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

📄 tda8290.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
	tda8295_i2c_bridge(fe, 0);}/*---------------------------------------------------------------------*/static int tda8290_has_signal(struct dvb_frontend *fe){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char i2c_get_afc[1] = { 0x1B };	unsigned char afc = 0;	tuner_i2c_xfer_send(&priv->i2c_props, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));	tuner_i2c_xfer_recv(&priv->i2c_props, &afc, 1);	return (afc & 0x80)? 65535:0;}/*---------------------------------------------------------------------*/static void tda8290_standby(struct dvb_frontend *fe){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char cb1[] = { 0x30, 0xD0 };	unsigned char tda8290_standby[] = { 0x00, 0x02 };	unsigned char tda8290_agc_tri[] = { 0x02, 0x20 };	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0, .buf=cb1, .len = 2};	tda8290_i2c_bridge(fe, 1);	if (priv->ver & TDA8275A)		cb1[1] = 0x90;	i2c_transfer(priv->i2c_props.adap, &msg, 1);	tda8290_i2c_bridge(fe, 0);	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_agc_tri, 2);	tuner_i2c_xfer_send(&priv->i2c_props, tda8290_standby, 2);}static void tda8295_standby(struct dvb_frontend *fe){	tda8295_agc1_out(fe, 0); /* Put AGC in tri-state */	tda8295_power(fe, 0);}static void tda8290_init_if(struct dvb_frontend *fe){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char set_VS[] = { 0x30, 0x6F };	unsigned char set_GP00_CF[] = { 0x20, 0x01 };	unsigned char set_GP01_CF[] = { 0x20, 0x0B };	if ((priv->cfg.config == 1) || (priv->cfg.config == 2))		tuner_i2c_xfer_send(&priv->i2c_props, set_GP00_CF, 2);	else		tuner_i2c_xfer_send(&priv->i2c_props, set_GP01_CF, 2);	tuner_i2c_xfer_send(&priv->i2c_props, set_VS, 2);}static void tda8295_init_if(struct dvb_frontend *fe){	struct tda8290_priv *priv = fe->analog_demod_priv;	static unsigned char set_adc_ctl[]       = { 0x33, 0x14 };	static unsigned char set_adc_ctl2[]      = { 0x34, 0x00 };	static unsigned char set_pll_reg6[]      = { 0x3e, 0x63 };	static unsigned char set_pll_reg0[]      = { 0x38, 0x23 };	static unsigned char set_pll_reg7[]      = { 0x3f, 0x01 };	static unsigned char set_pll_reg10[]     = { 0x42, 0x61 };	static unsigned char set_gpio_reg0[]     = { 0x44, 0x0b };	tda8295_power(fe, 1);	tda8295_set_easy_mode(fe, 0);	tda8295_set_video_std(fe);	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl, 2);	tuner_i2c_xfer_send(&priv->i2c_props, set_adc_ctl2, 2);	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg6, 2);	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg0, 2);	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg7, 2);	tuner_i2c_xfer_send(&priv->i2c_props, set_pll_reg10, 2);	tuner_i2c_xfer_send(&priv->i2c_props, set_gpio_reg0, 2);	tda8295_agc1_out(fe, 0);	tda8295_agc2_out(fe, 0);}static void tda8290_init_tuner(struct dvb_frontend *fe){	struct tda8290_priv *priv = fe->analog_demod_priv;	unsigned char tda8275_init[]  = { 0x00, 0x00, 0x00, 0x40, 0xdC, 0x04, 0xAf,					  0x3F, 0x2A, 0x04, 0xFF, 0x00, 0x00, 0x40 };	unsigned char tda8275a_init[] = { 0x00, 0x00, 0x00, 0x00, 0xdC, 0x05, 0x8b,					  0x0c, 0x04, 0x20, 0xFF, 0x00, 0x00, 0x4b };	struct i2c_msg msg = {.addr = priv->tda827x_addr, .flags=0,			      .buf=tda8275_init, .len = 14};	if (priv->ver & TDA8275A)		msg.buf = tda8275a_init;	tda8290_i2c_bridge(fe, 1);	i2c_transfer(priv->i2c_props.adap, &msg, 1);	tda8290_i2c_bridge(fe, 0);}/*---------------------------------------------------------------------*/static void tda829x_release(struct dvb_frontend *fe){	struct tda8290_priv *priv = fe->analog_demod_priv;	/* only try to release the tuner if we've	 * attached it from within this module */	if (priv->ver & (TDA18271 | TDA8275 | TDA8275A))		if (fe->ops.tuner_ops.release)			fe->ops.tuner_ops.release(fe);	kfree(fe->analog_demod_priv);	fe->analog_demod_priv = NULL;}static struct tda18271_config tda829x_tda18271_config = {	.gate    = TDA18271_GATE_ANALOG,};static int tda829x_find_tuner(struct dvb_frontend *fe){	struct tda8290_priv *priv = fe->analog_demod_priv;	struct analog_demod_ops *analog_ops = &fe->ops.analog_ops;	int i, ret, tuners_found;	u32 tuner_addrs;	u8 data;	struct i2c_msg msg = { .flags = I2C_M_RD, .buf = &data, .len = 1 };	if (NULL == analog_ops->i2c_gate_ctrl)		return -EINVAL;	analog_ops->i2c_gate_ctrl(fe, 1);	/* probe for tuner chip */	tuners_found = 0;	tuner_addrs = 0;	for (i = 0x60; i <= 0x63; i++) {		msg.addr = i;		ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);		if (ret == 1) {			tuners_found++;			tuner_addrs = (tuner_addrs << 8) + i;		}	}	/* if there is more than one tuner, we expect the right one is	   behind the bridge and we choose the highest address that doesn't	   give a response now	 */	analog_ops->i2c_gate_ctrl(fe, 0);	if (tuners_found > 1)		for (i = 0; i < tuners_found; i++) {			msg.addr = tuner_addrs  & 0xff;			ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);			if (ret == 1)				tuner_addrs = tuner_addrs >> 8;			else				break;		}	if (tuner_addrs == 0) {		tuner_addrs = 0x60;		tuner_info("could not clearly identify tuner address, "			   "defaulting to %x\n", tuner_addrs);	} else {		tuner_addrs = tuner_addrs & 0xff;		tuner_info("setting tuner address to %x\n", tuner_addrs);	}	priv->tda827x_addr = tuner_addrs;	msg.addr = tuner_addrs;	analog_ops->i2c_gate_ctrl(fe, 1);	ret = i2c_transfer(priv->i2c_props.adap, &msg, 1);	if (ret != 1) {		tuner_warn("tuner access failed!\n");		return -EREMOTEIO;	}	if ((data == 0x83) || (data == 0x84)) {		priv->ver |= TDA18271;		dvb_attach(tda18271_attach, fe, priv->tda827x_addr,			   priv->i2c_props.adap, &tda829x_tda18271_config);	} else {		if ((data & 0x3c) == 0)			priv->ver |= TDA8275;		else			priv->ver |= TDA8275A;		dvb_attach(tda827x_attach, fe, priv->tda827x_addr,			   priv->i2c_props.adap, &priv->cfg);		priv->cfg.switch_addr = priv->i2c_props.addr;	}	if (fe->ops.tuner_ops.init)		fe->ops.tuner_ops.init(fe);	if (fe->ops.tuner_ops.sleep)		fe->ops.tuner_ops.sleep(fe);	analog_ops->i2c_gate_ctrl(fe, 0);	return 0;}static int tda8290_probe(struct tuner_i2c_props *i2c_props){#define TDA8290_ID 0x89	unsigned char tda8290_id[] = { 0x1f, 0x00 };	/* detect tda8290 */	tuner_i2c_xfer_send(i2c_props, &tda8290_id[0], 1);	tuner_i2c_xfer_recv(i2c_props, &tda8290_id[1], 1);	if (tda8290_id[1] == TDA8290_ID) {		if (debug)			printk(KERN_DEBUG "%s: tda8290 detected @ %d-%04x\n",			       __func__, i2c_adapter_id(i2c_props->adap),			       i2c_props->addr);		return 0;	}	return -ENODEV;}static int tda8295_probe(struct tuner_i2c_props *i2c_props){#define TDA8295_ID 0x8a	unsigned char tda8295_id[] = { 0x2f, 0x00 };	/* detect tda8295 */	tuner_i2c_xfer_send(i2c_props, &tda8295_id[0], 1);	tuner_i2c_xfer_recv(i2c_props, &tda8295_id[1], 1);	if (tda8295_id[1] == TDA8295_ID) {		if (debug)			printk(KERN_DEBUG "%s: tda8295 detected @ %d-%04x\n",			       __func__, i2c_adapter_id(i2c_props->adap),			       i2c_props->addr);		return 0;	}	return -ENODEV;}static struct analog_demod_ops tda8290_ops = {	.set_params     = tda8290_set_params,	.has_signal     = tda8290_has_signal,	.standby        = tda8290_standby,	.release        = tda829x_release,	.i2c_gate_ctrl  = tda8290_i2c_bridge,};static struct analog_demod_ops tda8295_ops = {	.set_params     = tda8295_set_params,	.has_signal     = tda8295_has_signal,	.standby        = tda8295_standby,	.release        = tda829x_release,	.i2c_gate_ctrl  = tda8295_i2c_bridge,};struct dvb_frontend *tda829x_attach(struct dvb_frontend *fe,				    struct i2c_adapter *i2c_adap, u8 i2c_addr,				    struct tda829x_config *cfg){	struct tda8290_priv *priv = NULL;	char *name;	priv = kzalloc(sizeof(struct tda8290_priv), GFP_KERNEL);	if (priv == NULL)		return NULL;	fe->analog_demod_priv = priv;	priv->i2c_props.addr     = i2c_addr;	priv->i2c_props.adap     = i2c_adap;	priv->i2c_props.name     = "tda829x";	if (cfg)		priv->cfg.config         = cfg->lna_cfg;	if (tda8290_probe(&priv->i2c_props) == 0) {		priv->ver = TDA8290;		memcpy(&fe->ops.analog_ops, &tda8290_ops,		       sizeof(struct analog_demod_ops));	}	if (tda8295_probe(&priv->i2c_props) == 0) {		priv->ver = TDA8295;		memcpy(&fe->ops.analog_ops, &tda8295_ops,		       sizeof(struct analog_demod_ops));	}	if ((!(cfg) || (TDA829X_PROBE_TUNER == cfg->probe_tuner)) &&	    (tda829x_find_tuner(fe) < 0))		goto fail;	switch (priv->ver) {	case TDA8290:		name = "tda8290";		break;	case TDA8295:		name = "tda8295";		break;	case TDA8290 | TDA8275:		name = "tda8290+75";		break;	case TDA8295 | TDA8275:		name = "tda8295+75";		break;	case TDA8290 | TDA8275A:		name = "tda8290+75a";		break;	case TDA8295 | TDA8275A:		name = "tda8295+75a";		break;	case TDA8290 | TDA18271:		name = "tda8290+18271";		break;	case TDA8295 | TDA18271:		name = "tda8295+18271";		break;	default:		goto fail;	}	tuner_info("type set to %s\n", name);	fe->ops.analog_ops.info.name = name;	if (priv->ver & TDA8290) {		tda8290_init_tuner(fe);		tda8290_init_if(fe);	} else if (priv->ver & TDA8295)		tda8295_init_if(fe);#if 0	t->mode = V4L2_TUNER_ANALOG_TV;#endif	return fe;fail:	tda829x_release(fe);	return NULL;}EXPORT_SYMBOL_GPL(tda829x_attach);int tda829x_probe(struct i2c_adapter *i2c_adap, u8 i2c_addr){	struct tuner_i2c_props i2c_props = {		.adap = i2c_adap,		.addr = i2c_addr,	};	unsigned char soft_reset[]   = { 0x00, 0x00 };	unsigned char easy_mode_b[]  = { 0x01, 0x02 };	unsigned char easy_mode_g[]  = { 0x01, 0x04 };	unsigned char restore_9886[] = { 0x00, 0xd6, 0x30 };	unsigned char addr_dto_lsb = 0x07;	unsigned char data;#define PROBE_BUFFER_SIZE 8	unsigned char buf[PROBE_BUFFER_SIZE];	int i;	/* rule out tda9887, which would return the same byte repeatedly */	tuner_i2c_xfer_send(&i2c_props, soft_reset, 1);	tuner_i2c_xfer_recv(&i2c_props, buf, PROBE_BUFFER_SIZE);	for (i = 1; i < PROBE_BUFFER_SIZE; i++) {		if (buf[i] != buf[0])			break;	}	/* all bytes are equal, not a tda829x - probably a tda9887 */	if (i == PROBE_BUFFER_SIZE)		return -ENODEV;	if ((tda8290_probe(&i2c_props) == 0) ||	    (tda8295_probe(&i2c_props) == 0))		return 0;	/* fall back to old probing method */	tuner_i2c_xfer_send(&i2c_props, easy_mode_b, 2);	tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);	tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);	tuner_i2c_xfer_recv(&i2c_props, &data, 1);	if (data == 0) {		tuner_i2c_xfer_send(&i2c_props, easy_mode_g, 2);		tuner_i2c_xfer_send(&i2c_props, soft_reset, 2);		tuner_i2c_xfer_send(&i2c_props, &addr_dto_lsb, 1);		tuner_i2c_xfer_recv(&i2c_props, &data, 1);		if (data == 0x7b) {			return 0;		}	}	tuner_i2c_xfer_send(&i2c_props, restore_9886, 3);	return -ENODEV;}EXPORT_SYMBOL_GPL(tda829x_probe);MODULE_DESCRIPTION("Philips/NXP TDA8290/TDA8295 analog IF demodulator driver");MODULE_AUTHOR("Gerd Knorr, Hartmut Hackmann, Michael Krufky");MODULE_LICENSE("GPL");/* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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