📄 av7110.c
字号:
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 + -