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

📄 tuner-simple.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* 0x00 -> NTSC antenna input 1 */		/* 0x08 -> NTSC antenna input 2 */		buffer[0] = 0x14;		buffer[1] = 0x00;		buffer[2] = 0x17;		buffer[3] = 0x00;		cb &= ~0x40;		if (params->std & V4L2_STD_ATSC) {			cb |= 0x40;			buffer[1] = 0x04;		}		/* set to the correct mode (analog or digital) */		tuneraddr = priv->i2c_props.addr;		priv->i2c_props.addr = 0x0a;		if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[0],2)))			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);		if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,&buffer[2],2)))			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);		priv->i2c_props.addr = tuneraddr;		/* FIXME: input */		break;	}	if (t_params->cb_first_if_lower_freq && div < priv->last_div) {		buffer[0] = config;		buffer[1] = cb;		buffer[2] = (div>>8) & 0x7f;		buffer[3] = div      & 0xff;	} else {		buffer[0] = (div>>8) & 0x7f;		buffer[1] = div      & 0xff;		buffer[2] = config;		buffer[3] = cb;	}	priv->last_div = div;	if (t_params->has_tda9887) {		int config = 0;		int is_secam_l = (params->std & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) &&			!(params->std & ~(V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC));		if (params->std == V4L2_STD_SECAM_LC) {			if (t_params->port1_active ^ t_params->port1_invert_for_secam_lc)				config |= TDA9887_PORT1_ACTIVE;			if (t_params->port2_active ^ t_params->port2_invert_for_secam_lc)				config |= TDA9887_PORT2_ACTIVE;		}		else {			if (t_params->port1_active)				config |= TDA9887_PORT1_ACTIVE;			if (t_params->port2_active)				config |= TDA9887_PORT2_ACTIVE;		}		if (t_params->intercarrier_mode)			config |= TDA9887_INTERCARRIER;		if (is_secam_l) {			if (i == 0 && t_params->default_top_secam_low)				config |= TDA9887_TOP(t_params->default_top_secam_low);			else if (i == 1 && t_params->default_top_secam_mid)				config |= TDA9887_TOP(t_params->default_top_secam_mid);			else if (t_params->default_top_secam_high)				config |= TDA9887_TOP(t_params->default_top_secam_high);		}		else {			if (i == 0 && t_params->default_top_low)				config |= TDA9887_TOP(t_params->default_top_low);			else if (i == 1 && t_params->default_top_mid)				config |= TDA9887_TOP(t_params->default_top_mid);			else if (t_params->default_top_high)				config |= TDA9887_TOP(t_params->default_top_high);		}		if (t_params->default_pll_gating_18)			config |= TDA9887_GATING_18;		i2c_clients_command(priv->i2c_props.adap, TDA9887_SET_CONFIG, &config);	}	tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",		  buffer[0],buffer[1],buffer[2],buffer[3]);	if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))		tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);	switch (priv->type) {	case TUNER_LG_TDVS_H06XF:		/* Set the Auxiliary Byte. */		buffer[0] = buffer[2];		buffer[0] &= ~0x20;		buffer[0] |= 0x18;		buffer[1] = 0x20;		tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]);		if (2 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,2)))			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc);		break;	case TUNER_MICROTUNE_4042FI5:	{		// FIXME - this may also work for other tuners		unsigned long timeout = jiffies + msecs_to_jiffies(1);		u8 status_byte = 0;		/* Wait until the PLL locks */		for (;;) {			if (time_after(jiffies,timeout))				return 0;			if (1 != (rc = tuner_i2c_xfer_recv(&priv->i2c_props,&status_byte,1))) {				tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc);				break;			}			if (status_byte & TUNER_PLL_LOCKED)				break;			udelay(10);		}		/* Set the charge pump for optimized phase noise figure */		config &= ~TUNER_CHARGE_PUMP;		buffer[0] = (div>>8) & 0x7f;		buffer[1] = div      & 0xff;		buffer[2] = config;		buffer[3] = cb;		tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",			  buffer[0],buffer[1],buffer[2],buffer[3]);		if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))			tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);		break;	}	}	return 0;}static int simple_set_radio_freq(struct dvb_frontend *fe,				 struct analog_parameters *params){	struct tunertype *tun;	struct tuner_simple_priv *priv = fe->tuner_priv;	u8 buffer[4];	u16 div;	int rc, j;	struct tuner_params *t_params;	unsigned int freq = params->frequency;	tun = priv->tun;	for (j = tun->count-1; j > 0; j--)		if (tun->params[j].type == TUNER_PARAM_TYPE_RADIO)			break;	/* default t_params (j=0) will be used if desired type wasn't found */	t_params = &tun->params[j];	/* Select Radio 1st IF used */	switch (t_params->radio_if) {	case 0: /* 10.7 MHz */		freq += (unsigned int)(10.7*16000);		break;	case 1: /* 33.3 MHz */		freq += (unsigned int)(33.3*16000);		break;	case 2: /* 41.3 MHz */		freq += (unsigned int)(41.3*16000);		break;	default:		tuner_warn("Unsupported radio_if value %d\n", t_params->radio_if);		return 0;	}	/* Bandswitch byte */	switch (priv->type) {	case TUNER_TENA_9533_DI:	case TUNER_YMEC_TVF_5533MF:		tuner_dbg("This tuner doesn't have FM. Most cards have a TEA5767 for FM\n");		return 0;	case TUNER_PHILIPS_FM1216ME_MK3:	case TUNER_PHILIPS_FM1236_MK3:	case TUNER_PHILIPS_FMD1216ME_MK3:	case TUNER_LG_NTSC_TAPE:	case TUNER_PHILIPS_FM1256_IH3:		buffer[3] = 0x19;		break;	case TUNER_TNF_5335MF:		buffer[3] = 0x11;		break;	case TUNER_LG_PAL_FM:		buffer[3] = 0xa5;		break;	case TUNER_THOMSON_DTT761X:		buffer[3] = 0x39;		break;	case TUNER_MICROTUNE_4049FM5:	default:		buffer[3] = 0xa4;		break;	}	buffer[2] = (t_params->ranges[0].config & ~TUNER_RATIO_MASK) |		    TUNER_RATIO_SELECT_50; /* 50 kHz step */	/* Convert from 1/16 kHz V4L steps to 1/20 MHz (=50 kHz) PLL steps	   freq * (1 Mhz / 16000 V4L steps) * (20 PLL steps / 1 MHz) =	   freq * (1/800) */	div = (freq + 400) / 800;	if (t_params->cb_first_if_lower_freq && div < priv->last_div) {		buffer[0] = buffer[2];		buffer[1] = buffer[3];		buffer[2] = (div>>8) & 0x7f;		buffer[3] = div      & 0xff;	} else {		buffer[0] = (div>>8) & 0x7f;		buffer[1] = div      & 0xff;	}	tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",	       buffer[0],buffer[1],buffer[2],buffer[3]);	priv->last_div = div;	if (t_params->has_tda9887) {		int config = 0;		if (t_params->port1_active && !t_params->port1_fm_high_sensitivity)			config |= TDA9887_PORT1_ACTIVE;		if (t_params->port2_active && !t_params->port2_fm_high_sensitivity)			config |= TDA9887_PORT2_ACTIVE;		if (t_params->intercarrier_mode)			config |= TDA9887_INTERCARRIER;/*		if (t_params->port1_set_for_fm_mono)			config &= ~TDA9887_PORT1_ACTIVE;*/		if (t_params->fm_gain_normal)			config |= TDA9887_GAIN_NORMAL;		if (t_params->radio_if == 2)			config |= TDA9887_RIF_41_3;		i2c_clients_command(priv->i2c_props.adap, TDA9887_SET_CONFIG, &config);	}	if (4 != (rc = tuner_i2c_xfer_send(&priv->i2c_props,buffer,4)))		tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);	return 0;}static int simple_set_params(struct dvb_frontend *fe,			     struct analog_parameters *params){	struct tuner_simple_priv *priv = fe->tuner_priv;	int ret = -EINVAL;	switch (params->mode) {	case V4L2_TUNER_RADIO:		ret = simple_set_radio_freq(fe, params);		priv->frequency = params->frequency * 125 / 2;		break;	case V4L2_TUNER_ANALOG_TV:	case V4L2_TUNER_DIGITAL_TV:		ret = simple_set_tv_freq(fe, params);		priv->frequency = params->frequency * 62500;		break;	}	return ret;}static int simple_release(struct dvb_frontend *fe){	kfree(fe->tuner_priv);	fe->tuner_priv = NULL;	return 0;}static int simple_get_frequency(struct dvb_frontend *fe, u32 *frequency){	struct tuner_simple_priv *priv = fe->tuner_priv;	*frequency = priv->frequency;	return 0;}static struct dvb_tuner_ops simple_tuner_ops = {	.set_analog_params = simple_set_params,	.release           = simple_release,	.get_frequency     = simple_get_frequency,	.get_status        = simple_get_status,	.get_rf_strength   = simple_get_rf_strength,};struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,					 struct i2c_adapter *i2c_adap,					 u8 i2c_addr,					 struct simple_tuner_config *cfg){	struct tuner_simple_priv *priv = NULL;	priv = kzalloc(sizeof(struct tuner_simple_priv), GFP_KERNEL);	if (priv == NULL)		return NULL;	fe->tuner_priv = priv;	priv->i2c_props.addr = i2c_addr;	priv->i2c_props.adap = i2c_adap;	priv->type = cfg->type;	priv->tun  = cfg->tun;	memcpy(&fe->ops.tuner_ops, &simple_tuner_ops, sizeof(struct dvb_tuner_ops));	tuner_info("type set to %d (%s)\n", cfg->type, cfg->tun->name);	strlcpy(fe->ops.tuner_ops.info.name, cfg->tun->name, sizeof(fe->ops.tuner_ops.info.name));	return fe;}EXPORT_SYMBOL_GPL(simple_tuner_attach);MODULE_DESCRIPTION("Simple 4-control-bytes style tuner driver");MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");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 + -