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

📄 tda10086.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
  /*     Driver for Philips tda10086 DVBS Demodulator     (c) 2006 Andrew de Quincey     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/init.h>#include <linux/module.h>#include <linux/device.h>#include <linux/jiffies.h>#include <linux/string.h>#include <linux/slab.h>#include "dvb_frontend.h"#include "tda10086.h"#include "compat.h"#define SACLK 96000000struct tda10086_state {	struct i2c_adapter* i2c;	const struct tda10086_config* config;	struct dvb_frontend frontend;	/* private demod data */	u32 frequency;	u32 symbol_rate;	bool has_lock;};static int debug;#define dprintk(args...) \	do { \		if (debug) printk(KERN_DEBUG "tda10086: " args); \	} while (0)static int tda10086_write_byte(struct tda10086_state *state, int reg, int data){	int ret;	u8 b0[] = { reg, data };	struct i2c_msg msg = { .flags = 0, .buf = b0, .len = 2 };	msg.addr = state->config->demod_address;	ret = i2c_transfer(state->i2c, &msg, 1);	if (ret != 1)		dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n",			__func__, reg, data, ret);	return (ret != 1) ? ret : 0;}static int tda10086_read_byte(struct tda10086_state *state, int reg){	int ret;	u8 b0[] = { reg };	u8 b1[] = { 0 };	struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },				{ .flags = I2C_M_RD, .buf = b1, .len = 1 }};	msg[0].addr = state->config->demod_address;	msg[1].addr = state->config->demod_address;	ret = i2c_transfer(state->i2c, msg, 2);	if (ret != 2) {		dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg,			ret);		return ret;	}	return b1[0];}static int tda10086_write_mask(struct tda10086_state *state, int reg, int mask, int data){	int val;	/* read a byte and check */	val = tda10086_read_byte(state, reg);	if (val < 0)		return val;	/* mask if off */	val = val & ~mask;	val |= data & 0xff;	/* write it out again */	return tda10086_write_byte(state, reg, val);}static int tda10086_init(struct dvb_frontend* fe){	struct tda10086_state* state = fe->demodulator_priv;	u8 t22k_off = 0x80;	dprintk ("%s\n", __func__);	if (state->config->diseqc_tone)		t22k_off = 0;	/* reset */	tda10086_write_byte(state, 0x00, 0x00);	msleep(10);	/* misc setup */	tda10086_write_byte(state, 0x01, 0x94);	tda10086_write_byte(state, 0x02, 0x35); /* NOTE: TT drivers appear to disable CSWP */	tda10086_write_byte(state, 0x03, 0xe4);	tda10086_write_byte(state, 0x04, 0x43);	tda10086_write_byte(state, 0x0c, 0x0c);	tda10086_write_byte(state, 0x1b, 0xb0); /* noise threshold */	tda10086_write_byte(state, 0x20, 0x89); /* misc */	tda10086_write_byte(state, 0x30, 0x04); /* acquisition period length */	tda10086_write_byte(state, 0x32, 0x00); /* irq off */	tda10086_write_byte(state, 0x31, 0x56); /* setup AFC */	/* setup PLL (this assumes SACLK = 96MHz) */	tda10086_write_byte(state, 0x55, 0x2c); /* misc PLL setup */	if (state->config->xtal_freq == TDA10086_XTAL_16M) {		tda10086_write_byte(state, 0x3a, 0x0b); /* M=12 */		tda10086_write_byte(state, 0x3b, 0x01); /* P=2 */	} else {		tda10086_write_byte(state, 0x3a, 0x17); /* M=24 */		tda10086_write_byte(state, 0x3b, 0x00); /* P=1 */	}	tda10086_write_mask(state, 0x55, 0x20, 0x00); /* powerup PLL */	/* setup TS interface */	tda10086_write_byte(state, 0x11, 0x81);	tda10086_write_byte(state, 0x12, 0x81);	tda10086_write_byte(state, 0x19, 0x40); /* parallel mode A + MSBFIRST */	tda10086_write_byte(state, 0x56, 0x80); /* powerdown WPLL - unused in the mode we use */	tda10086_write_byte(state, 0x57, 0x08); /* bypass WPLL - unused in the mode we use */	tda10086_write_byte(state, 0x10, 0x2a);	/* setup ADC */	tda10086_write_byte(state, 0x58, 0x61); /* ADC setup */	tda10086_write_mask(state, 0x58, 0x01, 0x00); /* powerup ADC */	/* setup AGC */	tda10086_write_byte(state, 0x05, 0x0B);	tda10086_write_byte(state, 0x37, 0x63);	tda10086_write_byte(state, 0x3f, 0x0a); /* NOTE: flydvb varies it */	tda10086_write_byte(state, 0x40, 0x64);	tda10086_write_byte(state, 0x41, 0x4f);	tda10086_write_byte(state, 0x42, 0x43);	/* setup viterbi */	tda10086_write_byte(state, 0x1a, 0x11); /* VBER 10^6, DVB, QPSK */	/* setup carrier recovery */	tda10086_write_byte(state, 0x3d, 0x80);	/* setup SEC */	tda10086_write_byte(state, 0x36, t22k_off); /* all SEC off, 22k tone */	tda10086_write_byte(state, 0x34, (((1<<19) * (22000/1000)) / (SACLK/1000)));	tda10086_write_byte(state, 0x35, (((1<<19) * (22000/1000)) / (SACLK/1000)) >> 8);	return 0;}static void tda10086_diseqc_wait(struct tda10086_state *state){	unsigned long timeout = jiffies + msecs_to_jiffies(200);	while (!(tda10086_read_byte(state, 0x50) & 0x01)) {		if(time_after(jiffies, timeout)) {			printk("%s: diseqc queue not ready, command may be lost.\n", __func__);			break;		}		msleep(10);	}}static int tda10086_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone){	struct tda10086_state* state = fe->demodulator_priv;	u8 t22k_off = 0x80;	dprintk ("%s\n", __func__);	if (state->config->diseqc_tone)		t22k_off = 0;	switch (tone) {	case SEC_TONE_OFF:		tda10086_write_byte(state, 0x36, t22k_off);		break;	case SEC_TONE_ON:		tda10086_write_byte(state, 0x36, 0x01 + t22k_off);		break;	}	return 0;}static int tda10086_send_master_cmd (struct dvb_frontend* fe,				    struct dvb_diseqc_master_cmd* cmd){	struct tda10086_state* state = fe->demodulator_priv;	int i;	u8 oldval;	u8 t22k_off = 0x80;	dprintk ("%s\n", __func__);	if (state->config->diseqc_tone)		t22k_off = 0;	if (cmd->msg_len > 6)		return -EINVAL;	oldval = tda10086_read_byte(state, 0x36);	for(i=0; i< cmd->msg_len; i++) {		tda10086_write_byte(state, 0x48+i, cmd->msg[i]);	}	tda10086_write_byte(state, 0x36, (0x08 + t22k_off)					| ((cmd->msg_len - 1) << 4));	tda10086_diseqc_wait(state);	tda10086_write_byte(state, 0x36, oldval);	return 0;}static int tda10086_send_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd){	struct tda10086_state* state = fe->demodulator_priv;	u8 oldval = tda10086_read_byte(state, 0x36);	u8 t22k_off = 0x80;	dprintk ("%s\n", __func__);	if (state->config->diseqc_tone)		t22k_off = 0;	switch(minicmd) {	case SEC_MINI_A:		tda10086_write_byte(state, 0x36, 0x04 + t22k_off);		break;	case SEC_MINI_B:		tda10086_write_byte(state, 0x36, 0x06 + t22k_off);		break;	}	tda10086_diseqc_wait(state);	tda10086_write_byte(state, 0x36, oldval);	return 0;}static int tda10086_set_inversion(struct tda10086_state *state,				  struct dvb_frontend_parameters *fe_params){	u8 invval = 0x80;	dprintk ("%s %i %i\n", __func__, fe_params->inversion, state->config->invert);	switch(fe_params->inversion) {	case INVERSION_OFF:		if (state->config->invert)			invval = 0x40;		break;	case INVERSION_ON:		if (!state->config->invert)			invval = 0x40;		break;	case INVERSION_AUTO:		invval = 0x00;		break;	}	tda10086_write_mask(state, 0x0c, 0xc0, invval);	return 0;}static int tda10086_set_symbol_rate(struct tda10086_state *state,				    struct dvb_frontend_parameters *fe_params){	u8 dfn = 0;	u8 afs = 0;	u8 byp = 0;	u8 reg37 = 0x43;	u8 reg42 = 0x43;	u64 big;	u32 tmp;	u32 bdr;	u32 bdri;	u32 symbol_rate = fe_params->u.qpsk.symbol_rate;	dprintk ("%s %i\n", __func__, symbol_rate);	/* setup the decimation and anti-aliasing filters.. */	if (symbol_rate < (u32) (SACLK * 0.0137)) {		dfn=4;		afs=1;	} else if (symbol_rate < (u32) (SACLK * 0.0208)) {		dfn=4;		afs=0;	} else if (symbol_rate < (u32) (SACLK * 0.0270)) {		dfn=3;		afs=1;	} else if (symbol_rate < (u32) (SACLK * 0.0416)) {		dfn=3;		afs=0;	} else if (symbol_rate < (u32) (SACLK * 0.0550)) {		dfn=2;		afs=1;	} else if (symbol_rate < (u32) (SACLK * 0.0833)) {		dfn=2;		afs=0;	} else if (symbol_rate < (u32) (SACLK * 0.1100)) {		dfn=1;		afs=1;	} else if (symbol_rate < (u32) (SACLK * 0.1666)) {		dfn=1;		afs=0;	} else if (symbol_rate < (u32) (SACLK * 0.2200)) {		dfn=0;		afs=1;	} else if (symbol_rate < (u32) (SACLK * 0.3333)) {		dfn=0;		afs=0;	} else {		reg37 = 0x63;		reg42 = 0x4f;		byp=1;	}	/* calculate BDR */	big = (1ULL<<21) * ((u64) symbol_rate/1000ULL) * (1ULL<<dfn);	big += ((SACLK/1000ULL)-1ULL);	do_div(big, (SACLK/1000ULL));	bdr = big & 0xfffff;	/* calculate BDRI */	tmp = (1<<dfn)*(symbol_rate/1000);	bdri = ((32 * (SACLK/1000)) + (tmp-1)) / tmp;	tda10086_write_byte(state, 0x21, (afs << 7) | dfn);	tda10086_write_mask(state, 0x20, 0x08, byp << 3);	tda10086_write_byte(state, 0x06, bdr);	tda10086_write_byte(state, 0x07, bdr >> 8);	tda10086_write_byte(state, 0x08, bdr >> 16);	tda10086_write_byte(state, 0x09, bdri);	tda10086_write_byte(state, 0x37, reg37);	tda10086_write_byte(state, 0x42, reg42);	return 0;}static int tda10086_set_fec(struct tda10086_state *state,			    struct dvb_frontend_parameters *fe_params){	u8 fecval;	dprintk ("%s %i\n", __func__, fe_params->u.qpsk.fec_inner);	switch(fe_params->u.qpsk.fec_inner) {	case FEC_1_2:		fecval = 0x00;		break;	case FEC_2_3:		fecval = 0x01;		break;	case FEC_3_4:		fecval = 0x02;		break;	case FEC_4_5:		fecval = 0x03;		break;

⌨️ 快捷键说明

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