⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tda10021.c

📁 LG TDA10021 DVBC linux driver
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    TDA10021  - Single Chip Cable Channel Receiver driver module               used on the the Siemens DVB-C cards    Copyright (C) 1999 Convergence Integrated Media GmbH <ralph@convergence.de>    Copyright (C) 2004 Markus Schulz <msc@antzsystem.de>                   Support for TDA10021    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <linux/config.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/string.h>#include <linux/slab.h>#include "dvb_frontend.h"#include "tda10021.h"struct tda10021_state {	struct i2c_adapter* i2c;	struct dvb_frontend_ops ops;	/* configuration settings */	const struct tda10021_config* config;	struct dvb_frontend frontend;	u8 pwm;	u8 reg0;};#if 0#define dprintk(x...) printk(x)#else#define dprintk(x...)#endifstatic int verbose;//ZHU#define m_iIfagcMax 140#define m_iIfagcMin 90#define m_iRfagcMax 255#define m_iRfagcMin 0#define m_iMpegoutput 1   //  0 Parllel 1 Serial Msb 2 Serial LSB#define m_Mpegmode 0 // 0 Mode A 1 Mode B #define m_MpegmodeBclk 13<<4#define m_Mpegclk 0    //0 Falling 1 rising //#define XIN 57840000UL#define XIN   58000000UL#define uSysClk XIN#define DISABLE_INVERSION(reg0)		do { reg0 |= 0x20; } while (0)#define ENABLE_INVERSION(reg0)		do { reg0 &= ~0x20; } while (0)#define HAS_INVERSION(reg0)		(!(reg0 & 0x20))#define FIN (XIN >> 4)static int tda10021_inittab_size = 0x40;static u8 tda10021_inittab[0x40]={//	0x73, 0x6a, 0x23, 0x0a, 0x02, 0x37, 0x77, 0x1a,//	0x37, 0x6a, 0x17, 0x8a, 0x1e, 0x86, 0x43, 0x40,//	0xb8, 0x3f, 0xa0, 0x00, 0xcd, 0x01, 0x00, 0xff,//	0x11, 0x00, 0x7c, 0x31, 0x30, 0x20, 0x00, 0x00,//	0x02, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00,//	0x07, 0x00, 0x33, 0x11, 0x0d, 0x95, 0x08, 0x58,//	0x00, 0x00, 0x80, 0x00, 0x80, 0xff, 0x00, 0x00,//	0x04, 0x2d, 0x2f, 0xff, 0x00, 0x00, 0x00, 0x00,//	0-8   1-9   2-a   3-b   4-c   5-d   6-e   7-f	0x47, 0x8c, 0x23, 0x4a, 0x0a, 0x64, 0x77, 0x1a,//0	0x74, 0x96, 0x96, 0x7b, 0x1a, 0x9b, 0x03, 0x40,//8	0x78, 0x2f, 0xa1, 0x00, 0xc1, 0x02, 0x00, 0x46,//10	0x0a, 0x06, 0x7c, 0x31, 0x30, 0x0b, 0x00, 0x00,//18	0x92, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,//20	0x1c, 0x00, 0x21, 0x11, 0x0d, 0x94, 0x08, 0x5a,//28	0x00, 0x00, 0x80, 0x00, 0x80, 0xff, 0x00, 0xfc,//30	0x07, 0x2f, 0x0f, 0x8c, 0x5a, 0x00, 0x00, 0x00,//38};static int tda10021_writereg (struct tda10021_state* state, u8 reg, u8 data){        u8 buf[] = { reg, data };	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 };        int ret;	ret = i2c_transfer (state->i2c, &msg, 1);	if (ret != 1)		printk("DVB: TDA10021(%d): %s, writereg error "			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",			state->frontend.dvb->num, __FUNCTION__, reg, data, ret);	msleep(10);	return (ret != 1) ? -EREMOTEIO : 0;}static u8 tda10021_readreg (struct tda10021_state* state, u8 reg){	u8 b0 [] = { reg };	u8 b1 [] = { 0 };	struct i2c_msg msg [] = { { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 1 },	                          { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };	int ret;	ret = i2c_transfer (state->i2c, msg, 2);	if (ret != 2)		printk("DVB: TDA10021(%d): %s: readreg error (ret == %i)\n",				state->frontend.dvb->num, __FUNCTION__, ret);	return b1[0];}//Zhustatic int ChipWriteMasked(struct tda10021_state * state,u8 addr,u8 mask,u8 data ){	u8 i;	i=tda10021_readreg(state,addr);	i=i&~mask;	i=i|(data & mask);	return tda10021_writereg(state,addr,i);        }//get access to tunerstatic int lock_tuner(struct tda10021_state* state){	u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] | 0x80 };	struct i2c_msg msg = {.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};	if(i2c_transfer(state->i2c, &msg, 1) != 1)	{		printk("tda10021: lock tuner fails\n");		return -EREMOTEIO;	}	return 0;}//release access from tunerstatic int unlock_tuner(struct tda10021_state* state){	u8 buf[2] = { 0x0f, tda10021_inittab[0x0f] & 0x7f };	struct i2c_msg msg_post={.addr=state->config->demod_address, .flags=0, .buf=buf, .len=2};	if(i2c_transfer(state->i2c, &msg_post, 1) != 1)	{		printk("tda10021: unlock tuner fails\n");		return -EREMOTEIO;	}	return 0;}static void Q10021AlgoDelay(u32 uNbSymbol,u32 uSR){	uNbSymbol *= 1000;		uNbSymbol += uSR/2;		uNbSymbol /= uSR;	//printk("udelay %d\n",uNbSymbol);	udelay((unsigned short)uNbSymbol);}static u8 Q10021AlgoGain(struct tda10021_state* state,u32 uSR,u8 bGain){	long lRCentralCoef, lICentralCoef;		u8 pReadCoef[2];    	do	{	// read the real part of the central coef of the equalizer		pReadCoef[0]=(u8)tda10021_readreg(state,0x50);    			pReadCoef[1]=(u8)tda10021_readreg(state,0x51);		lRCentralCoef = (u32)(pReadCoef[0] << 3 | pReadCoef[1] >> 5);		if (lRCentralCoef & 0x400)	lRCentralCoef |= 0xFFFFF800;		// lRCentralCoef^2		lRCentralCoef *= lRCentralCoef;		// read the imaginary part of the central coef of the equalizer		pReadCoef[0]=(u8)tda10021_readreg(state,0x90);    			pReadCoef[1]=(u8)tda10021_readreg(state,0x91);		lICentralCoef = (u32)(pReadCoef[0] << 3 | pReadCoef[1] >> 5);		if (lICentralCoef & 0x400)	lICentralCoef |= 0xFFFFF800;		// lICentralCoef^2		lICentralCoef *= lICentralCoef;		// test the module  	 	if ((lRCentralCoef + lICentralCoef) >490000)	 	{			//printk("bGain=%x\n",bGain);					// no scanning so use all agin - test if gain max is reached			if (bGain < 5)				{					// try next gain				bGain++;    				ChipWriteMasked(state,0x0e,0xe0, (u8)(bGain << 5));				// wait for synchro				Q10021AlgoDelay(10000, uSR);			}		 	else					return 6;//err	 	}	 	else 			return bGain; // if ok	}while(1);}static int tda10021_RunAlgo (struct tda10021_state* state,u32 uSR, u8 *pGain, u8 bAutoGain, u8 bAutoSpecInv){	u8 bAGC1, bAGC2, bSI,bGainFound;	    	if(bAutoGain)*pGain=0;    	bGainFound=*pGain;  	// set the gain    	ChipWriteMasked(state,0x0e,0xe0, (u8)(bGainFound << 5));	// set the AGC time constant	ChipWriteMasked(state,0x02, 0x03, 1);	// program the CARCONF	ChipWriteMasked(state,0x04, 0x3f, 0x0a);	// only use the central coef and disable other adaptation when gain auto	if (bAutoGain) ChipWriteMasked(state,0x1c, 0x08, 0x08);	// reset the demod     reset CLB bit    	ChipWriteMasked(state,0x00, 0x01, 0);	Q10021AlgoDelay(80000, uSR);	// read the AGC values	// test if there is a signal    	bAGC1=(u8)tda10021_readreg(state,0x17);      	bAGC2=(u8)tda10021_readreg(state,0x2f);	//printk("-----------bAGC1=%x,bAGC2=%x\n",bAGC1,bAGC2);	if (bAGC1 == 255 && bAGC2 == 255) return 1;	/*UpdateData(FALSE);*/	// test the algo in used	if (bAutoGain)	{			if ((bGainFound=Q10021AlgoGain(state, uSR, bGainFound)) == 6)				return 2;// if err		else		{  				// set the AGC time constant	        	ChipWriteMasked(state,0x02, 0x03, 1);	        	// use all coef        		ChipWriteMasked(state,0x1c, 0x08, 0);	        	// reset the demod	            	ChipWriteMasked(state,0x00, 0x01, 0);	        	Q10021AlgoDelay(80000, uSR);		        *pGain=bGainFound;		}	}      	// set the AGC time constant    	ChipWriteMasked(state,0x02, 0x03, 3);	Q10021AlgoDelay(200000, uSR);	// read the synchro registers // test if carlock	u8 bSyncReg;	bSyncReg=(u8)tda10021_readreg(state,0x11); 	if (!(bSyncReg & 0x02))return 3;	// test if frame synchro	if ((bSyncReg & 0x04) && !(bSyncReg & 0x40))	{		//printk("-----------------------------fram synchro test ok\n"); 		// oK case	   	if (uSR > 3000000)			ChipWriteMasked(state,0x04, 0x3f, 0x02);  		else  				ChipWriteMasked(state,0x04, 0x3f, 0x0a);       		return 0;    	}	// test if auto spectral inv	else if(bAutoSpecInv)	{			// test the other spectral inversion            	bSI=(u8)tda10021_readreg(state,0x00);		if (bSI & 0x20)				bSI &= ~0x20; 		else				bSI |= 0x20;		//printk("-------------------------bSI=%x\n",bSI);		tda10021_writereg(state,0x00,bSI);	     	Q10021AlgoDelay(30000, uSR);		// read the synchro registers	        bSyncReg=(u8)tda10021_readreg(state,0x11);		// test if frame sync and DVB	        if ((bSyncReg & 0x04) && !(bSyncReg & 0x40))		{		 	// oK case		      	if (uSR > 3000000)				ChipWriteMasked(state,0x04, 0x3f, 0x02); 			else  				ChipWriteMasked(state,0x04, 0x3f, 0x0a);              		return 0;		}	}	return 4;}/*static int tda10021_setup_reg0 (struct tda10021_state* state, u8 reg0,				fe_spectral_inversion_t inversion){	reg0 |= state->reg0 & 0x63;	if (INVERSION_ON == inversion)	{		ENABLE_INVERSION(reg0);		printk("Enable inversion\n");	}	else if (INVERSION_OFF == inversion)	{		DISABLE_INVERSION(reg0);		printk("Disable inversion\n");	}	tda10021_writereg (state, 0x00, reg0 & 0xfe);	tda10021_writereg (state, 0x00, reg0 | 0x01);	state->reg0 = reg0;	return 0;}*/static int tda10021_set_symbolrate (struct tda10021_state* state, u32 uFreqSymb){	u8	pWrite[4], bNdec, bSFil;	u32     uBDR, uFreqSymbInv, uFreqSymb240;/*	float   fFreqSymb, fSysClk ,fResult, fBDR ;*/	u32   fFreqSymb, fSysClk ,fResult, fBDR ;    	// add 240 ppm to the SR    	uFreqSymb240  = uFreqSymb*240;    	uFreqSymb240 /= 1000000;    	uFreqSymb240  = uFreqSymb + uFreqSymb240;        	// calculate the number of decimation and the antialias filter   	bNdec = 0;    	bSFil = 0;	if ((uFreqSymb240/10) < (uSysClk/123)){ bNdec = 0;    bSFil = 1;}	if ((uFreqSymb240/10) < (uSysClk/160)){ bNdec = 1;    bSFil = 0;}	if ((uFreqSymb240/10) < (uSysClk/246)){ bNdec = 1;    bSFil = 1;}	if ((uFreqSymb240/10) < (uSysClk/320)){ bNdec = 2;    bSFil = 0;}	if ((uFreqSymb240/10) < (uSysClk/492)){ bNdec = 2;    bSFil = 1;}	if ((uFreqSymb240/10) < (uSysClk/640)){ bNdec = 3;    bSFil = 0;}	if ((uFreqSymb240/10) < (uSysClk/984)){ bNdec = 3;    bSFil = 1;}    	// program SFIL    	ChipWriteMasked(state,0x0e, 0x10, (u8)(bSFil<<4));    	// program NDEC    	ChipWriteMasked(state,0x03, 0xc0, (u8)(bNdec<<6));    	// calculate the inversion of the symbol frequency	uFreqSymbInv   = uSysClk*16;	uFreqSymbInv >>= bNdec;		// divide by 2^decim	uFreqSymbInv  += uFreqSymb/2;	// rounding for division	uFreqSymbInv  /= uFreqSymb;	if (uFreqSymbInv > 255)	uFreqSymbInv = 255;    	// calculate the symbol rate//	fFreqSymb = (u32)uFreqSymb;//	fSysClk = (u32)uSysClk;//	fResult  = (u32)(1<<(24+bNdec));//	fResult /= fSysClk;//	fResult *= fFreqSymb;//	uBDR = (u32)fResult;	uBDR=(289262*(uFreqSymb/1000))/1000;	uBDR=uBDR*(1<<bNdec);	//printk("------------------------uBDR=%x\n",uBDR);	//uBDR=1735574;    	// program the value in register of the symbol rate	pWrite[0] = (u8)(uBDR);	pWrite[1] = (u8)(uBDR >> 8);	pWrite[2] = (u8)(uBDR >> 16);	pWrite[3] = (u8)uFreqSymbInv;     	tda10021_writereg(state,0x0a, pWrite[0]);    	tda10021_writereg(state,0x0b, pWrite[1]);    	tda10021_writereg(state,0x0c, pWrite[2]);    	tda10021_writereg(state,0x0d, pWrite[3]);     	// return the value programmed//	fBDR = (u32)uBDR;//	fSysClk = (u32)uSysClk;//	fResult  = fBDR*fSysClk;//	fResult /= (u32)(1<<(24+bNdec));	return (u32)fResult;}/*static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate){	s32 BDR;	s32 BDRI;	s16 SFIL=0;	u16 NDEC = 0;	u32 tmp, ratio;        printk("symbolrate=%x(%d)\n",symbolrate,symbolrate);	if (symbolrate > XIN/2)		symbolrate = XIN/2;	if (symbolrate < 500000)		symbolrate = 500000;	if (symbolrate < XIN/16) NDEC = 1;	if (symbolrate < XIN/32) NDEC = 2;	if (symbolrate < XIN/64) NDEC = 3;	if (symbolrate < (u32)(XIN/12.3)) SFIL = 1;	if (symbolrate < (u32)(XIN/16))	 SFIL = 0;	if (symbolrate < (u32)(XIN/24.6)) SFIL = 1;	if (symbolrate < (u32)(XIN/32))	 SFIL = 0;	if (symbolrate < (u32)(XIN/49.2)) SFIL = 1;	if (symbolrate < (u32)(XIN/64))	 SFIL = 0;	if (symbolrate < (u32)(XIN/98.4)) SFIL = 1;	symbolrate <<= NDEC;	ratio = (symbolrate << 4) / FIN;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -