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

📄 av7110.c

📁 linux环境下的dvb驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter);	av7110->hw_frontend.source = DMX_FRONTEND_0;	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend);	if (ret < 0)		return ret;	av7110->mem_frontend.source = DMX_MEMORY_FE;	ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend);	if (ret < 0)		return ret;	ret = dvbdemux->dmx.connect_frontend(&dvbdemux->dmx,					     &av7110->hw_frontend);	if (ret < 0)		return ret;	av7110_av_register(av7110);	av7110_ca_register(av7110);#ifdef CONFIG_DVB_AV7110_OSD	dvb_register_device(av7110->dvb_adapter, &av7110->osd_dev,			    &dvbdev_osd, av7110, DVB_DEVICE_OSD);#endif	dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);	return 0;}static void dvb_unregister(struct av7110 *av7110){	struct dvb_demux *dvbdemux = &av7110->demux;	DEB_EE(("av7110: %p\n", av7110));	if (!av7110->registered)		return;	dvb_net_release(&av7110->dvb_net);	dvbdemux->dmx.close(&dvbdemux->dmx);	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->hw_frontend);	dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &av7110->mem_frontend);	dvb_dmxdev_release(&av7110->dmxdev);	dvb_dmx_release(&av7110->demux);	dvb_remove_frontend_notifier (av7110->dvb_adapter,				      av7110_before_after_tune);	dvb_remove_frontend_ioctls (av7110->dvb_adapter,				    av7110_diseqc_ioctl, NULL);	dvb_unregister_device(av7110->osd_dev);	av7110_av_unregister(av7110);	av7110_ca_unregister(av7110);}/**************************************************************************** * I2C client commands ****************************************************************************/int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val){	u8 msg[2] = { reg, val };	struct dvb_i2c_bus *i2c = av7110->i2c_bus;	struct i2c_msg msgs;	msgs.flags = 0;	msgs.addr = id / 2;	msgs.len = 2;	msgs.buf = msg;	return i2c->xfer(i2c, &msgs, 1);}u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg){	struct dvb_i2c_bus *i2c = av7110->i2c_bus;	u8 mm1[] = {0x00};	u8 mm2[] = {0x00};	struct i2c_msg msgs[2];	msgs[0].flags = 0;	msgs[1].flags = I2C_M_RD;	msgs[0].addr = msgs[1].addr = id / 2;	mm1[0] = reg;	msgs[0].len = 1; msgs[1].len = 1;	msgs[0].buf = mm1; msgs[1].buf = mm2;	i2c->xfer(i2c, msgs, 2);	return mm2[0];}static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num){	struct saa7146_dev *dev = i2c->data;	return saa7146_i2c_transfer(dev, msgs, num, 6);}/**************************************************************************** * INITIALIZATION ****************************************************************************/#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))#define CONFIG_DVB_AV7110_FIRMWARE_FILE#endifstatic int check_firmware(struct av7110* av7110){	u32 crc = 0, len = 0;	unsigned char *ptr;	/* check for firmware magic */	ptr = av7110->bin_fw;	if (ptr[0] != 'A' || ptr[1] != 'V' ||	    ptr[2] != 'F' || ptr[3] != 'W') {		printk("dvb-ttpci: this is not an av7110 firmware\n");		return -EINVAL;	}	ptr += 4;	/* check dpram file */	crc = ntohl(*(u32*) ptr);	ptr += 4;	len = ntohl(*(u32*) ptr);	ptr += 4;	if (len >= 512) {		printk("dvb-ttpci: dpram file is way to big.\n");		return -EINVAL;	}	if (crc != crc32_le(0, ptr, len)) {		printk("dvb-ttpci: crc32 of dpram file does not match.\n");		return -EINVAL;	}	av7110->bin_dpram = ptr;	av7110->size_dpram = len;	ptr += len;	/* check root file */	crc = ntohl(*(u32*) ptr);	ptr += 4;	len = ntohl(*(u32*) ptr);	ptr += 4;	if (len <= 200000 || len >= 300000 ||	    len > ((av7110->bin_fw + av7110->size_fw) - ptr)) {		printk("dvb-ttpci: root file has strange size (%d). aborting.\n", len);		return -EINVAL;	}	if( crc != crc32_le(0, ptr, len)) {		printk("dvb-ttpci: crc32 of root file does not match.\n");		return -EINVAL;	}	av7110->bin_root = ptr;	av7110->size_root = len;	return 0;}#ifdef CONFIG_DVB_AV7110_FIRMWARE_FILE#include "av7110_firm.h"static inline int get_firmware(struct av7110* av7110){	av7110->bin_fw = dvb_ttpci_fw;	av7110->size_fw = sizeof(dvb_ttpci_fw);	return check_firmware(av7110);}#elsestatic int get_firmware(struct av7110* av7110){	int ret;	const struct firmware *fw;	/* request the av7110 firmware, this will block until someone uploads it */	ret = request_firmware(&fw, "dvb-ttpci-01.fw", &av7110->dev->pci->dev);	if (ret) {		printk("dvb-ttpci: cannot request firmware!\n");		return -EINVAL;	}	if (fw->size <= 200000) {		printk("dvb-ttpci: this firmware is way too small.\n");		return -EINVAL;	}	/* check if the firmware is available */	av7110->bin_fw = (unsigned char*) vmalloc(fw->size);	if (NULL == av7110->bin_fw) {		DEB_D(("out of memory\n"));		return -ENOMEM;	}	memcpy(av7110->bin_fw, fw->data, fw->size);	av7110->size_fw = fw->size;	if ((ret = check_firmware(av7110)))		vfree(av7110->bin_fw);	return ret;}#endifstatic int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext){	struct av7110 *av7110 = NULL;	int ret = 0;	DEB_EE(("dev: %p\n", dev));	/* prepare the av7110 device struct */	if (!(av7110 = kmalloc (sizeof (struct av7110), GFP_KERNEL))) {		printk ("%s: out of memory!\n", __FUNCTION__);		return -ENOMEM;	}	DEB_EE(("av7110: %p\n", av7110));	memset(av7110, 0, sizeof(struct av7110));	av7110->card_name = (char*) pci_ext->ext_priv;	av7110->dev = (struct saa7146_dev *) dev;	dev->ext_priv = av7110;	if ((ret = get_firmware(av7110))) {		kfree(av7110);		return ret;	}	dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name);	/* the Siemens DVB needs this if you want to have the i2c chips	   get recognized before the main driver is fully loaded */	saa7146_write(dev, GPIO_CTRL, 0x500000);	saa7146_i2c_adapter_prepare(dev, NULL, SAA7146_I2C_BUS_BIT_RATE_120); /* 275 kHz */	av7110->i2c_bus = dvb_register_i2c_bus(master_xfer, dev,					       av7110->dvb_adapter, 0);	if (!av7110->i2c_bus) {		dvb_unregister_adapter(av7110->dvb_adapter);		kfree(av7110);		return -ENOMEM;	}	ttpci_eeprom_parse_mac(av7110->i2c_bus);	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);	saa7146_write(dev, BCS_CTRL, 0x80400040);	/* set dd1 stream a & b */	saa7146_write(dev, DD1_STREAM_B, 0x00000000);	saa7146_write(dev, DD1_INIT, 0x03000000);	saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26));	/* upload all */	saa7146_write(dev, MC2, 0x077c077c);	saa7146_write(dev, GPIO_CTRL, 0x000000);	tasklet_init (&av7110->debi_tasklet, debiirq, (unsigned long) av7110);	tasklet_init (&av7110->gpio_tasklet, gpioirq, (unsigned long) av7110);	sema_init(&av7110->pid_mutex, 1);	/* locks for data transfers from/to AV7110 */	spin_lock_init (&av7110->debilock);	sema_init(&av7110->dcomlock, 1);	av7110->debilock = SPIN_LOCK_UNLOCKED;	av7110->debitype = -1;	/* default OSD window */	av7110->osdwin = 1;	/* ARM "watchdog" */	init_waitqueue_head(&av7110->arm_wait);	av7110->arm_thread = 0;	/* allocate and init buffers */	av7110->debi_virt = pci_alloc_consistent(dev->pci, 8192,						 &av7110->debi_bus);	if (!av7110->debi_virt) {		ret = -ENOMEM;		goto err;	}	av7110->iobuf = vmalloc(AVOUTLEN+AOUTLEN+BMPLEN+4*IPACKS);	if (!av7110->iobuf) {		ret = -ENOMEM;		goto err;	}	av7110_av_init(av7110);	/* init BMP buffer */	av7110->bmpbuf = av7110->iobuf+AVOUTLEN+AOUTLEN;	init_waitqueue_head(&av7110->bmpq);	av7110_ca_init(av7110);	/* load firmware into AV7110 cards */	av7110_bootarm(av7110);	if (av7110_firmversion(av7110)) {		ret = -EIO;		goto err2;	}	if (FW_VERSION(av7110->arm_app)<0x2501)		printk ("av7110: Warning, firmware version 0x%04x is too old. "			"System might be unstable!\n", FW_VERSION(av7110->arm_app));	if (kernel_thread(arm_thread, (void *) av7110, 0) < 0) {		printk(KERN_ERR "av7110(%d): faile to start arm_mon kernel thread\n",		       av7110->dvb_adapter->num);		goto err2;	}	/* set internal volume control to maximum */	av7110->adac_type = DVB_ADAC_TI;	av7110_set_volume(av7110, 0xff, 0xff);	VidMode(av7110, vidmode);	/* handle different card types */	/* remaining inits according to card and frontend type */	av7110->has_analog_tuner = 0;	av7110->current_input = 0;	if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {		printk ("av7110(%d): Crystal audio DAC detected\n",			av7110->dvb_adapter->num);		av7110->adac_type = DVB_ADAC_CRYSTAL;		i2c_writereg(av7110, 0x20, 0x01, 0xd2);		i2c_writereg(av7110, 0x20, 0x02, 0x49);		i2c_writereg(av7110, 0x20, 0x03, 0x00);		i2c_writereg(av7110, 0x20, 0x04, 0x00);	/**	 * some special handling for the Siemens DVB-C cards...	 */	} else if (0 == av7110_init_analog_module(av7110)) {		/* done. */	}	else if (dev->pci->subsystem_vendor == 0x110a) {		printk("av7110(%d): DVB-C w/o analog module detected\n",			av7110->dvb_adapter->num);		av7110->adac_type = DVB_ADAC_NONE;	}	else {		av7110->adac_type = adac;		printk("av7110(%d): adac type set to %d\n",			av7110->dvb_adapter->num, av7110->adac_type);	}	if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) {		// switch DVB SCART on		av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0);		av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1);		if (rgb_on)			saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16		//saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8	}	av7110_set_volume(av7110, 0xff, 0xff);	av7110_setup_irc_config(av7110, 0);	av7110_register(av7110);	/* special case DVB-C: these cards have an analog tuner	   plus need some special handling, so we have separate	   saa7146_ext_vv data for these... */	ret = av7110_init_v4l(av7110);	if (ret)		goto err3;	printk(KERN_INFO "av7110: found av7110-%d.\n", av7110_num);	av7110->device_initialized = 1;	av7110_num++;	return 0;err3:	av7110->arm_rmmod = 1;	wake_up_interruptible(&av7110->arm_wait);	while (av7110->arm_thread)		dvb_delay(1);err2:	av7110_ca_exit(av7110);	av7110_av_exit(av7110);err:	dvb_unregister_i2c_bus(master_xfer, av7110->i2c_bus->adapter,			       av7110->i2c_bus->id);	dvb_unregister_adapter(av7110->dvb_adapter);	if (NULL != av7110->debi_virt)		pci_free_consistent(dev->pci, 8192, av7110->debi_virt, av7110->debi_bus);	if (NULL != av7110->iobuf)		vfree(av7110->iobuf);	if (NULL != av7110 ) {		kfree(av7110);	}	return ret;}static int av7110_detach (struct saa7146_dev* saa){	struct av7110 *av7110 = (struct av7110*)saa->ext_priv;	DEB_EE(("av7110: %p\n", av7110));	if( 0 == av7110->device_initialized ) {		return 0;	}	av7110_exit_v4l(av7110);	av7110->arm_rmmod = 1;	wake_up_interruptible(&av7110->arm_wait);	while (av7110->arm_thread)		dvb_delay(1);	dvb_unregister(av7110);	IER_DISABLE(saa, (MASK_19 | MASK_03));//	saa7146_write (av7110->dev, IER,//		     saa7146_read(av7110->dev, IER) & ~(MASK_19 | MASK_03));	saa7146_write(av7110->dev, ISR,(MASK_19 | MASK_03));	av7110_ca_exit(av7110);	av7110_av_exit(av7110);	vfree(av7110->iobuf);	pci_free_consistent(saa->pci, 8192, av7110->debi_virt,			    av7110->debi_bus);	dvb_unregister_i2c_bus (master_xfer,av7110->i2c_bus->adapter, av7110->i2c_bus->id);	dvb_unregister_adapter (av7110->dvb_adapter);	av7110_num--;#ifndef CONFIG_DVB_AV7110_FIRMWARE_FILE	if (av7110->bin_fw)		vfree(av7110->bin_fw);#endif	kfree(av7110);	saa->ext_priv = NULL;	return 0;}static void av7110_irq(struct saa7146_dev* dev, u32 *isr){	struct av7110 *av7110 = (struct av7110*)dev->ext_priv;//	DEB_INT(("dev: %p, av7110: %p\n",dev,av7110));	if (*isr & MASK_19)		tasklet_schedule (&av7110->debi_tasklet);	if (*isr & MASK_03)		tasklet_schedule (&av7110->gpio_tasklet);}static struct saa7146_extension av7110_extension;#define MAKE_AV7110_INFO(x_var,x_name) \static struct saa7146_pci_extension_data x_var = { \	.ext_priv = x_name, \	.ext = &av7110_extension }MAKE_AV7110_INFO(fs_1_5, "Siemens cable card PCI rev1.5");MAKE_AV7110_INFO(fs_1_3, "Siemens/Technotrend/Hauppauge PCI rev1.3");MAKE_AV7110_INFO(tt_1_6, "Technotrend/Hauppauge PCI rev1.3 or 1.6");MAKE_AV7110_INFO(tt_2_1, "Technotrend/Hauppauge PCI rev2.1");MAKE_AV7110_INFO(tt_t,	 "Technotrend/Hauppauge PCI DVB-T");MAKE_AV7110_INFO(unkwn0, "Technotrend/Hauppauge PCI rev?(unknown0)?");MAKE_AV7110_INFO(unkwn1, "Technotrend/Hauppauge PCI rev?(unknown1)?");MAKE_AV7110_INFO(unkwn2, "Technotrend/Hauppauge PCI rev?(unknown2)?");MAKE_AV7110_INFO(nexus,  "Technotrend/Hauppauge Nexus PCI DVB-S");MAKE_AV7110_INFO(dvboc11,"Octal/Technotrend DVB-C for iTV");static struct pci_device_id pci_tbl[] = {	MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0xffff),	MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0x0000),	MAKE_EXTENSION_PCI(fs_1_3, 0x13c2, 0x0000),	MAKE_EXTENSION_PCI(unkwn0, 0x13c2, 0x1002),	MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0001),	MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0002),	MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0003),	MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0004),	MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0006),	MAKE_EXTENSION_PCI(tt_t,   0x13c2, 0x0008),	MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x1102),	MAKE_EXTENSION_PCI(unkwn1, 0xffc2, 0x0000),	MAKE_EXTENSION_PCI(unkwn2, 0x00a1, 0x00a1),	MAKE_EXTENSION_PCI(nexus,  0x00a1, 0xa1a0),	MAKE_EXTENSION_PCI(dvboc11,0x13c2, 0x000a),	{		.vendor    = 0,	}};MODULE_DEVICE_TABLE(pci, pci_tbl);static struct saa7146_extension av7110_extension = {	.name		= "dvb\0",	.flags		= SAA7146_I2C_SHORT_DELAY,	.module		= THIS_MODULE,	.pci_tbl	= &pci_tbl[0],	.attach		= av7110_attach,	.detach		= av7110_detach,	.irq_mask	= MASK_19|MASK_03,	.irq_func	= av7110_irq,};static int __init av7110_init(void){	int retval;	retval = saa7146_register_extension(&av7110_extension);	if (retval)		goto failed_saa7146_register;	retval = av7110_ir_init();	if (retval)		goto failed_av7110_ir_init;	return 0;failed_av7110_ir_init:	saa7146_unregister_extension(&av7110_extension);failed_saa7146_register:	return retval;}static void __exit av7110_exit(void){	av7110_ir_exit();	saa7146_unregister_extension(&av7110_extension);}module_init(av7110_init);module_exit(av7110_exit);MODULE_DESCRIPTION("driver for the SAA7146 based AV110 PCI DVB cards by "		   "Siemens, Technotrend, Hauppauge");MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, others");MODULE_LICENSE("GPL");MODULE_PARM(av7110_debug,"i");MODULE_PARM(vidmode,"i");MODULE_PARM_DESC(vidmode,"analog video out: 0 off, 1 CVBS+RGB (default), 2 CVBS+YC, 3 YC");MODULE_PARM(pids_off,"i");MODULE_PARM_DESC(pids_off,"clear video/audio/PCR PID filters when demux is closed");MODULE_PARM(adac,"i");MODULE_PARM_DESC(adac,"audio DAC type: 0 TI, 1 CRYSTAL, 2 MSP (use if autodetection fails)");MODULE_PARM(hw_sections, "i");MODULE_PARM_DESC(hw_sections, "0 use software section filter, 1 use hardware");MODULE_PARM(rgb_on, "i");MODULE_PARM_DESC(rgb_on, "For Siemens DVB-C cards only: Enable RGB control"		" signal on SCART pin 16 to switch SCART video mode from CVBS to RGB");

⌨️ 快捷键说明

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