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

📄 tda8290.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   i2c tv tuner chip device driver   controls the philips tda8290+75 tuner chip combo.   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.   This "tda8290" module was split apart from the original "tuner" module.*/#include <linux/i2c.h>#include <linux/delay.h>#include "compat.h"#include <linux/videodev.h>#include "tuner-i2c.h"#include "tda8290.h"#include "tda827x.h"#include "tda18271.h"static int debug;module_param(debug, int, 0644);MODULE_PARM_DESC(debug, "enable verbose debug messages");/* ---------------------------------------------------------------------- */struct tda8290_priv {	struct tuner_i2c_props i2c_props;	unsigned char tda8290_easy_mode;	unsigned char tda827x_addr;	unsigned char ver;#define TDA8290   1#define TDA8295   2#define TDA8275   4#define TDA8275A  8#define TDA18271 16	struct tda827x_config cfg;};/*---------------------------------------------------------------------*/static int tda8290_i2c_bridge(struct dvb_frontend *fe, int close){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char  enable[2] = { 0x21, 0xC0 };	unsigned char disable[2] = { 0x21, 0x00 };	unsigned char *msg;	if (close) {		msg = enable;		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);		/* let the bridge stabilize */		msleep(20);	} else {		msg = disable;		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);	}	return 0;}#if 1static int tda8295_i2c_bridge(struct dvb_frontend *fe, int close){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char  enable[2] = { 0x45, 0xc1 };	unsigned char disable[2] = { 0x46, 0x00 };	unsigned char buf[3] = { 0x45, 0x01, 0x00 };	unsigned char *msg;	if (close) {		msg = enable;		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);		/* let the bridge stabilize */		msleep(20);	} else {		msg = disable;		tuner_i2c_xfer_send(&priv->i2c_props, msg, 1);		tuner_i2c_xfer_recv(&priv->i2c_props, &msg[1], 1);		buf[2] = msg[1];		buf[2] &= ~0x04;		tuner_i2c_xfer_send(&priv->i2c_props, buf, 3);		msleep(5);		msg[1] |= 0x04;		tuner_i2c_xfer_send(&priv->i2c_props, msg, 2);	}	return 0;}#elsestatic int tda8295_i2c_bridge(struct dvb_frontend *fe, int close){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char buf[] = { 0x45, 0x00 };	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);	buf[1] &= 0x3f;	if (close)		buf[1] |= 0xc0;	else		buf[1] |= 0x80;	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);	return 0;}#endif/*---------------------------------------------------------------------*/static void set_audio(struct dvb_frontend *fe,		      struct analog_parameters *params){	struct tda8290_priv *priv = fe->analog_demod_priv;	char* mode;	if (params->std & V4L2_STD_MN) {		priv->tda8290_easy_mode = 0x01;		mode = "MN";	} else if (params->std & V4L2_STD_B) {		priv->tda8290_easy_mode = 0x02;		mode = "B";	} else if (params->std & V4L2_STD_GH) {		priv->tda8290_easy_mode = 0x04;		mode = "GH";	} else if (params->std & V4L2_STD_PAL_I) {		priv->tda8290_easy_mode = 0x08;		mode = "I";	} else if (params->std & V4L2_STD_DK) {		priv->tda8290_easy_mode = 0x10;		mode = "DK";	} else if (params->std & V4L2_STD_SECAM_L) {		priv->tda8290_easy_mode = 0x20;		mode = "L";	} else if (params->std & V4L2_STD_SECAM_LC) {		priv->tda8290_easy_mode = 0x40;		mode = "LC";	} else {		priv->tda8290_easy_mode = 0x10;		mode = "xx";	}	tuner_dbg("setting tda829x to system %s\n", mode);}static void tda8290_set_params(struct dvb_frontend *fe,			       struct analog_parameters *params){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char soft_reset[]  = { 0x00, 0x00 };	unsigned char easy_mode[]   = { 0x01, priv->tda8290_easy_mode };	unsigned char expert_mode[] = { 0x01, 0x80 };	unsigned char agc_out_on[]  = { 0x02, 0x00 };	unsigned char gainset_off[] = { 0x28, 0x14 };	unsigned char if_agc_spd[]  = { 0x0f, 0x88 };	unsigned char adc_head_6[]  = { 0x05, 0x04 };	unsigned char adc_head_9[]  = { 0x05, 0x02 };	unsigned char adc_head_12[] = { 0x05, 0x01 };	unsigned char pll_bw_nom[]  = { 0x0d, 0x47 };	unsigned char pll_bw_low[]  = { 0x0d, 0x27 };	unsigned char gainset_2[]   = { 0x28, 0x64 };	unsigned char agc_rst_on[]  = { 0x0e, 0x0b };	unsigned char agc_rst_off[] = { 0x0e, 0x09 };	unsigned char if_agc_set[]  = { 0x0f, 0x81 };	unsigned char addr_adc_sat  = 0x1a;	unsigned char addr_agc_stat = 0x1d;	unsigned char addr_pll_stat = 0x1b;	unsigned char adc_sat, agc_stat,		      pll_stat;	int i;	set_audio(fe, params);	if (priv->cfg.config)		tuner_dbg("tda827xa config is 0x%02x\n", priv->cfg.config);	tuner_i2c_xfer_send(&priv->i2c_props, easy_mode, 2);	tuner_i2c_xfer_send(&priv->i2c_props, agc_out_on, 2);	tuner_i2c_xfer_send(&priv->i2c_props, soft_reset, 2);	msleep(1);	expert_mode[1] = priv->tda8290_easy_mode + 0x80;	tuner_i2c_xfer_send(&priv->i2c_props, expert_mode, 2);	tuner_i2c_xfer_send(&priv->i2c_props, gainset_off, 2);	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_spd, 2);	if (priv->tda8290_easy_mode & 0x60)		tuner_i2c_xfer_send(&priv->i2c_props, adc_head_9, 2);	else		tuner_i2c_xfer_send(&priv->i2c_props, adc_head_6, 2);	tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_nom, 2);	tda8290_i2c_bridge(fe, 1);	if (fe->ops.tuner_ops.set_analog_params)		fe->ops.tuner_ops.set_analog_params(fe, params);	for (i = 0; i < 3; i++) {		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);		if (pll_stat & 0x80) {			tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);			tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);			tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);			tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);			tuner_dbg("tda8290 is locked, AGC: %d\n", agc_stat);			break;		} else {			tuner_dbg("tda8290 not locked, no signal?\n");			msleep(100);		}	}	/* adjust headroom resp. gain */	if ((agc_stat > 115) || (!(pll_stat & 0x80) && (adc_sat < 20))) {		tuner_dbg("adjust gain, step 1. Agc: %d, ADC stat: %d, lock: %d\n",			   agc_stat, adc_sat, pll_stat & 0x80);		tuner_i2c_xfer_send(&priv->i2c_props, gainset_2, 2);		msleep(100);		tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);		tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);		if ((agc_stat > 115) || !(pll_stat & 0x80)) {			tuner_dbg("adjust gain, step 2. Agc: %d, lock: %d\n",				   agc_stat, pll_stat & 0x80);			if (priv->cfg.agcf)				priv->cfg.agcf(fe);			msleep(100);			tuner_i2c_xfer_send(&priv->i2c_props, &addr_agc_stat, 1);			tuner_i2c_xfer_recv(&priv->i2c_props, &agc_stat, 1);			tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);			tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);			if((agc_stat > 115) || !(pll_stat & 0x80)) {				tuner_dbg("adjust gain, step 3. Agc: %d\n", agc_stat);				tuner_i2c_xfer_send(&priv->i2c_props, adc_head_12, 2);				tuner_i2c_xfer_send(&priv->i2c_props, pll_bw_low, 2);				msleep(100);			}		}	}	/* l/ l' deadlock? */	if(priv->tda8290_easy_mode & 0x60) {		tuner_i2c_xfer_send(&priv->i2c_props, &addr_adc_sat, 1);		tuner_i2c_xfer_recv(&priv->i2c_props, &adc_sat, 1);		tuner_i2c_xfer_send(&priv->i2c_props, &addr_pll_stat, 1);		tuner_i2c_xfer_recv(&priv->i2c_props, &pll_stat, 1);		if ((adc_sat > 20) || !(pll_stat & 0x80)) {			tuner_dbg("trying to resolve SECAM L deadlock\n");			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_on, 2);			msleep(40);			tuner_i2c_xfer_send(&priv->i2c_props, agc_rst_off, 2);		}	}	tda8290_i2c_bridge(fe, 0);	tuner_i2c_xfer_send(&priv->i2c_props, if_agc_set, 2);}/*---------------------------------------------------------------------*/static void tda8295_power(struct dvb_frontend *fe, int enable){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char buf[] = { 0x30, 0x00 }; /* clb_stdbt */	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);	if (enable)		buf[1] = 0x01;	else		buf[1] = 0x03;	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);}static void tda8295_set_easy_mode(struct dvb_frontend *fe, int enable){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char buf[] = { 0x01, 0x00 };	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);	if (enable)		buf[1] = 0x01; /* rising edge sets regs 0x02 - 0x23 */	else		buf[1] = 0x00; /* reset active bit */	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);}static void tda8295_set_video_std(struct dvb_frontend *fe){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char buf[] = { 0x00, priv->tda8290_easy_mode };	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);	tda8295_set_easy_mode(fe, 1);	msleep(20);	tda8295_set_easy_mode(fe, 0);}/*---------------------------------------------------------------------*/static void tda8295_agc1_out(struct dvb_frontend *fe, int enable){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char buf[] = { 0x02, 0x00 }; /* DIV_FUNC */	tuner_i2c_xfer_send(&priv->i2c_props, &buf[0], 1);	tuner_i2c_xfer_recv(&priv->i2c_props, &buf[1], 1);	if (enable)		buf[1] &= ~0x40;	else		buf[1] |= 0x40;	tuner_i2c_xfer_send(&priv->i2c_props, buf, 2);}static void tda8295_agc2_out(struct dvb_frontend *fe, int enable){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char set_gpio_cf[]    = { 0x44, 0x00 };	unsigned char set_gpio_val[]   = { 0x46, 0x00 };	tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_cf[0], 1);	tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_cf[1], 1);	tuner_i2c_xfer_send(&priv->i2c_props, &set_gpio_val[0], 1);	tuner_i2c_xfer_recv(&priv->i2c_props, &set_gpio_val[1], 1);	set_gpio_cf[1] &= 0xf0; /* clear GPIO_0 bits 3-0 */	if (enable) {		set_gpio_cf[1]  |= 0x01; /* config GPIO_0 as Open Drain Out */		set_gpio_val[1] &= 0xfe; /* set GPIO_0 pin low */	}	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_cf, 2);	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_val, 2);}static int tda8295_has_signal(struct dvb_frontend *fe){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char hvpll_stat = 0x26;	unsigned char ret;	tuner_i2c_xfer_send(&priv->i2c_props, &hvpll_stat, 1);	tuner_i2c_xfer_recv(&priv->i2c_props, &ret, 1);	return (ret & 0x01) ? 65535 : 0;}/*---------------------------------------------------------------------*/static void tda8295_set_params(struct dvb_frontend *fe,			       struct analog_parameters *params){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char blanking_mode[]     = { 0x1d, 0x00 };	set_audio(fe, params);	tuner_dbg("%s: freq = %d\n", __func__, params->frequency);	tda8295_power(fe, 1);	tda8295_agc1_out(fe, 1);	tuner_i2c_xfer_send(&priv->i2c_props, &blanking_mode[0], 1);	tuner_i2c_xfer_recv(&priv->i2c_props, &blanking_mode[1], 1);	tda8295_set_video_std(fe);	blanking_mode[1] = 0x03;	tuner_i2c_xfer_send(&priv->i2c_props, blanking_mode, 2);	msleep(20);	tda8295_i2c_bridge(fe, 1);	if (fe->ops.tuner_ops.set_analog_params)		fe->ops.tuner_ops.set_analog_params(fe, params);	if (priv->cfg.agcf)		priv->cfg.agcf(fe);	if (tda8295_has_signal(fe))		tuner_dbg("tda8295 is locked\n");	else		tuner_dbg("tda8295 not locked, no signal?\n");

⌨️ 快捷键说明

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