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

📄 av7110.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	0x91, 0x01,	0xa0, 0x04,	0xa1, 0x00,	0xa2, 0x00,	0xb0, 0x91,	0xb1, 0x0b,	0xc0, 0x53,	0xc1, 0x70,	0xc2, 0x12,	0xd0, 0x00,	0xd1, 0x00,	0xd2, 0x00,	0xd3, 0x00,	0xd4, 0x00,	0xd5, 0x00,	0xde, 0x00,	0xdf, 0x00,	0x61, 0x49,	0x62, 0x0b,	0x53, 0x08,	0x59, 0x08,	0xff, 0xff,};static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params){	struct av7110* av7110 = fe->dvb->priv;	u32 div;	u8 data[4];	struct i2c_msg msg = { .addr = 0x63, .flags = 0, .buf = data, .len = sizeof(data) };	struct i2c_msg readmsg = { .addr = 0x63, .flags = I2C_M_RD, .buf = data, .len = 1 };	int i;	div = (params->frequency + 36150000 + 31250) / 62500;	data[0] = (div >> 8) & 0x7f;	data[1] = div & 0xff;	data[2] = 0xce;	if (params->frequency < 45000000)		return -EINVAL;	else if (params->frequency < 137000000)		data[3] = 0x01;	else if (params->frequency < 403000000)		data[3] = 0x02;	else if (params->frequency < 860000000)		data[3] = 0x04;	else		return -EINVAL;	stv0297_enable_plli2c(fe);	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {		printk("nexusca: pll transfer failed!\n");		return -EIO;	}	// wait for PLL lock	for(i = 0; i < 20; i++) {		stv0297_enable_plli2c(fe);		if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)			if (data[0] & 0x40) break;		msleep(10);	}	return 0;}static struct stv0297_config nexusca_stv0297_config = {	.demod_address = 0x1C,	.inittab = nexusca_stv0297_inittab,	.invert = 1,	.pll_set = nexusca_stv0297_pll_set,};static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params){	struct av7110* av7110 = (struct av7110*) fe->dvb->priv;	u32 div;	u8 cfg, cpump, band_select;	u8 data[4];	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };	div = (36125000 + params->frequency) / 166666;	cfg = 0x88;	if (params->frequency < 175000000) cpump = 2;	else if (params->frequency < 390000000) cpump = 1;	else if (params->frequency < 470000000) cpump = 2;	else if (params->frequency < 750000000) cpump = 1;	else cpump = 3;	if (params->frequency < 175000000) band_select = 0x0e;	else if (params->frequency < 470000000) band_select = 0x05;	else band_select = 0x03;	data[0] = (div >> 8) & 0x7f;	data[1] = div & 0xff;	data[2] = ((div >> 10) & 0x60) | cfg;	data[3] = (cpump << 6) | band_select;	if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;	return 0;}static struct l64781_config grundig_29504_401_config = {	.demod_address = 0x55,	.pll_set = grundig_29504_401_pll_set,};static int av7110_fe_lock_fix(struct av7110* av7110, fe_status_t status){	int ret = 0;	int synced = (status & FE_HAS_LOCK) ? 1 : 0;	av7110->fe_status = status;	if (av7110->fe_synced == synced)		return 0;	if (av7110->playing)		return 0;	if (down_interruptible(&av7110->pid_mutex))		return -ERESTARTSYS;	if (synced) {		ret = SetPIDs(av7110, av7110->pids[DMX_PES_VIDEO],			av7110->pids[DMX_PES_AUDIO],			av7110->pids[DMX_PES_TELETEXT], 0,			av7110->pids[DMX_PES_PCR]);		if (!ret)			ret = av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, Scan, 0);	} else {		ret = SetPIDs(av7110, 0, 0, 0, 0, 0);		if (!ret) {			ret = av7110_fw_cmd(av7110, COMTYPE_PID_FILTER, FlushTSQueue, 0);			if (!ret)				ret = av7110_wait_msgstate(av7110, GPMQBusy);		}	}	if (!ret)		av7110->fe_synced = synced;	up(&av7110->pid_mutex);	return ret;}static int av7110_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* params){	struct av7110* av7110 = fe->dvb->priv;	int ret = av7110_fe_lock_fix(av7110, 0);	if (!ret)		ret = av7110->fe_set_frontend(fe, params);	return ret;}static int av7110_fe_init(struct dvb_frontend* fe){	struct av7110* av7110 = fe->dvb->priv;	int ret = av7110_fe_lock_fix(av7110, 0);	if (!ret)		ret = av7110->fe_init(fe);	return ret;}static int av7110_fe_read_status(struct dvb_frontend* fe, fe_status_t* status){	struct av7110* av7110 = fe->dvb->priv;	/* call the real implementation */	int ret = av7110->fe_read_status(fe, status);	if (!ret)		if (((*status ^ av7110->fe_status) & FE_HAS_LOCK) && (*status & FE_HAS_LOCK))			ret = av7110_fe_lock_fix(av7110, *status);	return ret;}static int av7110_fe_diseqc_reset_overload(struct dvb_frontend* fe){	struct av7110* av7110 = fe->dvb->priv;	int ret = av7110_fe_lock_fix(av7110, 0);	if (!ret)		ret = av7110->fe_diseqc_reset_overload(fe);	return ret;}static int av7110_fe_diseqc_send_master_cmd(struct dvb_frontend* fe,					    struct dvb_diseqc_master_cmd* cmd){	struct av7110* av7110 = fe->dvb->priv;	int ret = av7110_fe_lock_fix(av7110, 0);	if (!ret)		ret = av7110->fe_diseqc_send_master_cmd(fe, cmd);	return ret;}static int av7110_fe_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd){	struct av7110* av7110 = fe->dvb->priv;	int ret = av7110_fe_lock_fix(av7110, 0);	if (!ret)		ret = av7110->fe_diseqc_send_burst(fe, minicmd);	return ret;}static int av7110_fe_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone){	struct av7110* av7110 = fe->dvb->priv;	int ret = av7110_fe_lock_fix(av7110, 0);	if (!ret)		ret = av7110->fe_set_tone(fe, tone);	return ret;}static int av7110_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage){	struct av7110* av7110 = fe->dvb->priv;	int ret = av7110_fe_lock_fix(av7110, 0);	if (!ret)		ret = av7110->fe_set_voltage(fe, voltage);	return ret;}static int av7110_fe_dishnetwork_send_legacy_command(struct dvb_frontend* fe, unsigned int cmd){	struct av7110* av7110 = fe->dvb->priv;	int ret = av7110_fe_lock_fix(av7110, 0);	if (!ret)		ret = av7110->fe_dishnetwork_send_legacy_command(fe, cmd);	return ret;}static u8 read_pwm(struct av7110* av7110){	u8 b = 0xff;	u8 pwm;	struct i2c_msg msg[] = { { .addr = 0x50,.flags = 0,.buf = &b,.len = 1 },				 { .addr = 0x50,.flags = I2C_M_RD,.buf = &pwm,.len = 1} };	if ((i2c_transfer(&av7110->i2c_adap, msg, 2) != 2) || (pwm == 0xff))		pwm = 0x48;	return pwm;}static int frontend_init(struct av7110 *av7110){	int ret;	if (av7110->dev->pci->subsystem_vendor == 0x110a) {		switch(av7110->dev->pci->subsystem_device) {		case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))			av7110->fe = ves1820_attach(&philips_cd1516_config,						    &av7110->i2c_adap, read_pwm(av7110));			break;		}	} else if (av7110->dev->pci->subsystem_vendor == 0x13c2) {		switch(av7110->dev->pci->subsystem_device) {		case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X		case 0x0003: // Hauppauge/TT WinTV Nexus-S Rev 2.X		case 0x1002: // Hauppauge/TT WinTV DVB-S rev1.3SE			// try the ALPS BSRV2 first of all			av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);			if (av7110->fe) {				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;				av7110->fe->ops->set_tone = av7110_set_tone;				break;			}			// try the ALPS BSRU6 now			av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);			if (av7110->fe) {				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;				av7110->fe->ops->set_tone = av7110_set_tone;				break;			}			// Try the grundig 29504-451		        av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);			if (av7110->fe) {				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;				av7110->fe->ops->set_tone = av7110_set_tone;				break;			}			/* Try DVB-C cards */			switch(av7110->dev->pci->subsystem_device) {			case 0x0000:				/* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */				av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,							read_pwm(av7110));				break;			case 0x0003:				/* Haupauge DVB-C 2.1 VES1820/ALPS TDBE2 */				av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,							read_pwm(av7110));				break;			}			break;		case 0x0001: // Hauppauge/TT Nexus-T premium rev1.X			// ALPS TDLB7		        av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);			break;		case 0x0002: // Hauppauge/TT DVB-C premium rev2.X		        av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));			break;		case 0x0006: /* Fujitsu-Siemens DVB-S rev 1.6 */			/* Grundig 29504-451 */			av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);			if (av7110->fe) {				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;				av7110->fe->ops->set_tone = av7110_set_tone;			}			break;		case 0x0008: // Hauppauge/TT DVB-T			av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);			break;		case 0x000A: // Hauppauge/TT Nexus-CA rev1.X			av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);			if (av7110->fe) {				/* set TDA9819 into DVB mode */				saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)				saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)				/* tuner on this needs a slower i2c bus speed */				av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;				break;			}			break;		case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */			/* ALPS BSBE1 */			av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);			if (av7110->fe)				av7110->fe->ops->set_voltage = lnbp21_set_voltage;			break;		}	}	if (!av7110->fe) {		/* FIXME: propagate the failure code from the lower layers */		ret = -ENOMEM;		printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",		       av7110->dev->pci->vendor,		       av7110->dev->pci->device,		       av7110->dev->pci->subsystem_vendor,		       av7110->dev->pci->subsystem_device);	} else {		FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init);		FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status);		FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);		FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);		FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);		FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone);		FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)		FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);		FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);		ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);		if (ret < 0) {			printk("av7110: Frontend registration failed!\n");			if (av7110->fe->ops->release)				av7110->fe->ops->release(av7110->fe);			av7110->fe = NULL;		}	}	return ret;}/* Budgetpatch note: * Original hardware design by Roberto Deza: * There is a DVB_Wiki at * http://212.227.36.83/linuxtv/wiki/index.php/Main_Page * where is described this 'DVB TT Budget Patch', on Card Modding: * http://212.227.36.83/linuxtv/wiki/index.php/DVB_TT_Budget_Patch * On the short description there is also a link to a external file, * with more details: * http://perso.wanadoo.es/jesussolano/Ttf_tsc1.zip * * New software triggering design by Emard that works on * original Roberto Deza's hardware: * * rps1 code for budgetpatch will copy internal HS event to GPIO3 pin. * GPIO3 is in budget-patch hardware connectd to port B VSYNC * HS is an internal event of 7146, accessible with RPS * and temporarily raised high every n lines * (n in defined in the RPS_THRESH1 counter threshold) * I think HS is raised high on the beginning of the n-th line * and remains high until this n-th line that triggered * it is completely received. When the receiption of n-th line * ends, HS is lowered. * * To transmit data over DMA, 7146 needs changing state at * port B VSYNC pin. Any changing of port B VSYNC will * cause some DMA data transfer, with more or less packets loss. * It depends on the phase and frequency of VSYNC and * the way of 7146 is instructed to trigger on port B (defined * in DD1_INIT register, 3rd nibble from the right valid * numbers are 0-7, see datasheet) * * The correct triggering can minimize packet loss, * dvbtraffic should give this stable bandwidths: *   22k transponder = 33814 kbit/s * 27.5k transponder = 38045 kbit/s * by experiment it is found that the best results * (stable bandwidths and almost no packet loss) * are obtained using DD1_INIT triggering number 2 * (Va at rising edge of VS Fa = HS x VS-failing forced toggle) * and a VSYNC phase that occurs in the middle of DMA transfer * (about byte 188*512=96256 in the DMA window). * * Phase of HS is still not clear to me how to control, * It just happens to be so. It can be seen if one enables * RPS_IRQ and print Event Counter 1 in vpeirq(). Every * time RPS_INTERRUPT is called, the Event Counter 1 will * increment. That's how the 7146 is programmed to do event * counting in this budget-patch.c * I *think* HPS setting has something to do with the phase * of HS but I cant be 100% sure in that. * * hardware debug note: a working budget card (including budget patch) * with vpeirq() interrupt setup in mode "0x90" (every 64K) will * generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes * and that means 3*25=75 Hz of interrupt freqency, as seen by * watch cat /proc/interrupts * * If this frequency is 3x lower (and data received in the DMA * buffer don't start with 0x47, but in the middle of packets, * whose lengths appear to be like 188 292 188 104 etc. * this means VSYNC line is not connected in the hardware. * (check soldering pcb and pins) * The same behaviour of missing VSYNC can be duplicated on budget * cards, by seting DD1_INIT trigger mode 7 in 3rd nibble. */static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext){	const int length = TS_WIDTH * TS_HEIGHT;	struct pci_dev *pdev = dev->pci;	struct av7110 *av7110;	int ret, count = 0;	dprintk(4, "dev: %p\n", dev);	/* Set RPS_IRQ to 1 to track rps1 activity.	 * Enabling this won't send any interrupt to PC CPU.	 */#define RPS_IRQ 0	if (budgetpatch == 1) {		budgetpatch = 0;		/* autodetect the presence of budget patch		 * this only works if saa7146 has been recently		 * reset with with MASK_31 to MC1		 *		 * will wait for VBI_B 

⌨️ 快捷键说明

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