📄 pluto2.c
字号:
{ /* disable interrupts */ pluto_disable_irqs(pluto); pluto_reset_ts(pluto, 0); /* LED: disable automatic control, enable yellow, disable green */ pluto_rw(pluto, REG_MISC, MISC_ALED | MISC_LED1 | MISC_LED0, MISC_LED1); /* unmap DMA */ pluto_dma_unmap(pluto); pluto_reset_frontend(pluto, 0);}static inline u32 divide(u32 numerator, u32 denominator){ if (denominator == 0) return ~0; return (numerator + denominator / 2) / denominator;}/* LG Innotek TDTE-E001P (Infineon TUA6034) */static int lg_tdtpe001p_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *p){ struct pluto *pluto = frontend_to_pluto(fe); struct i2c_msg msg; int ret; u8 buf[4]; u32 div; // Fref = 166.667 Hz // Fref * 3 = 500.000 Hz // IF = 36166667 // IF / Fref = 217 //div = divide(p->frequency + 36166667, 166667); div = divide(p->frequency * 3, 500000) + 217; buf[0] = (div >> 8) & 0x7f; buf[1] = (div >> 0) & 0xff; if (p->frequency < 611000000) buf[2] = 0xb4; else if (p->frequency < 811000000) buf[2] = 0xbc; else buf[2] = 0xf4; // VHF: 174-230 MHz // center: 350 MHz // UHF: 470-862 MHz if (p->frequency < 350000000) buf[3] = 0x02; else buf[3] = 0x04; if (p->u.ofdm.bandwidth == BANDWIDTH_8_MHZ) buf[3] |= 0x08; if (sizeof(buf) == 6) { buf[4] = buf[2]; buf[4] &= ~0x1c; buf[4] |= 0x18; buf[5] = (0 << 7) | (2 << 4); } msg.addr = I2C_ADDR_TUA6034 >> 1; msg.flags = 0; msg.buf = buf; msg.len = sizeof(buf); ret = i2c_transfer(&pluto->i2c_adap, &msg, 1); if (ret < 0) return ret; else if (ret == 0) return -EREMOTEIO; return 0;}static int pluto2_request_firmware(struct dvb_frontend *fe, const struct firmware **fw, char *name){ struct pluto *pluto = frontend_to_pluto(fe); return request_firmware(fw, name, &pluto->pdev->dev);}static struct tda1004x_config pluto2_fe_config __devinitdata = { .demod_address = I2C_ADDR_TDA10046 >> 1, .invert = 1, .invert_oclk = 0, .xtal_freq = TDA10046_XTAL_16M, .agc_config = TDA10046_AGC_DEFAULT, .if_freq = TDA10046_FREQ_3617, .pll_set = lg_tdtpe001p_pll_set, .pll_sleep = NULL, .request_firmware = pluto2_request_firmware,};static int __devinit frontend_init(struct pluto *pluto){ int ret; pluto->fe = tda10046_attach(&pluto2_fe_config, &pluto->i2c_adap); if (!pluto->fe) { dev_err(&pluto->pdev->dev, "could not attach frontend\n"); return -ENODEV; } ret = dvb_register_frontend(&pluto->dvb_adapter, pluto->fe); if (ret < 0) { if (pluto->fe->ops->release) pluto->fe->ops->release(pluto->fe); return ret; } return 0;}static void __devinit pluto_read_rev(struct pluto *pluto){ u32 val = pluto_readreg(pluto, REG_MISC) & MISC_DVR; dev_info(&pluto->pdev->dev, "board revision %d.%d\n", (val >> 12) & 0x0f, (val >> 4) & 0xff);}static void __devinit pluto_read_mac(struct pluto *pluto, u8 *mac){ u32 val = pluto_readreg(pluto, REG_MMAC); mac[0] = (val >> 8) & 0xff; mac[1] = (val >> 0) & 0xff; val = pluto_readreg(pluto, REG_IMAC); mac[2] = (val >> 8) & 0xff; mac[3] = (val >> 0) & 0xff; val = pluto_readreg(pluto, REG_LMAC); mac[4] = (val >> 8) & 0xff; mac[5] = (val >> 0) & 0xff; dev_info(&pluto->pdev->dev, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);}static int __devinit pluto_read_serial(struct pluto *pluto){ struct pci_dev *pdev = pluto->pdev; unsigned int i, j; u8 __iomem *cis; cis = pci_iomap(pdev, 1, 0); if (!cis) return -EIO; dev_info(&pdev->dev, "S/N "); for (i = 0xe0; i < 0x100; i += 4) { u32 val = readl(&cis[i]); for (j = 0; j < 32; j += 8) { if ((val & 0xff) == 0xff) goto out; printk("%c", val & 0xff); val >>= 8; } }out: printk("\n"); pci_iounmap(pdev, cis); return 0;}static int __devinit pluto2_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ struct pluto *pluto; struct dvb_adapter *dvb_adapter; struct dvb_demux *dvbdemux; struct dmx_demux *dmx; int ret = -ENOMEM; pluto = kzalloc(sizeof(struct pluto), GFP_KERNEL); if (!pluto) goto out; pluto->pdev = pdev; ret = pci_enable_device(pdev); if (ret < 0) goto err_kfree; /* enable interrupts */ pci_write_config_dword(pdev, 0x6c, 0x8000); ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (ret < 0) goto err_pci_disable_device; pci_set_master(pdev); ret = pci_request_regions(pdev, DRIVER_NAME); if (ret < 0) goto err_pci_disable_device; pluto->io_mem = pci_iomap(pdev, 0, 0x40); if (!pluto->io_mem) { ret = -EIO; goto err_pci_release_regions; } pci_set_drvdata(pdev, pluto); ret = request_irq(pdev->irq, pluto_irq, SA_SHIRQ, DRIVER_NAME, pluto); if (ret < 0) goto err_pci_iounmap; ret = pluto_hw_init(pluto); if (ret < 0) goto err_free_irq; /* i2c */ i2c_set_adapdata(&pluto->i2c_adap, pluto); strcpy(pluto->i2c_adap.name, DRIVER_NAME); pluto->i2c_adap.owner = THIS_MODULE; pluto->i2c_adap.class = I2C_CLASS_TV_DIGITAL; pluto->i2c_adap.dev.parent = &pdev->dev; pluto->i2c_adap.algo_data = &pluto->i2c_bit; pluto->i2c_bit.data = pluto; pluto->i2c_bit.setsda = pluto_setsda; pluto->i2c_bit.setscl = pluto_setscl; pluto->i2c_bit.getsda = pluto_getsda; pluto->i2c_bit.getscl = pluto_getscl; pluto->i2c_bit.udelay = 10; pluto->i2c_bit.timeout = 10; /* Raise SCL and SDA */ pluto_setsda(pluto, 1); pluto_setscl(pluto, 1); ret = i2c_bit_add_bus(&pluto->i2c_adap); if (ret < 0) goto err_pluto_hw_exit; /* dvb */ ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE); if (ret < 0) goto err_i2c_bit_del_bus; dvb_adapter = &pluto->dvb_adapter; pluto_read_rev(pluto); pluto_read_serial(pluto); pluto_read_mac(pluto, dvb_adapter->proposed_mac); dvbdemux = &pluto->demux; dvbdemux->filternum = 256; dvbdemux->feednum = 256; dvbdemux->start_feed = pluto_start_feed; dvbdemux->stop_feed = pluto_stop_feed; dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); ret = dvb_dmx_init(dvbdemux); if (ret < 0) goto err_dvb_unregister_adapter; dmx = &dvbdemux->dmx; pluto->hw_frontend.source = DMX_FRONTEND_0; pluto->mem_frontend.source = DMX_MEMORY_FE; pluto->dmxdev.filternum = NHWFILTERS; pluto->dmxdev.demux = dmx; ret = dvb_dmxdev_init(&pluto->dmxdev, dvb_adapter); if (ret < 0) goto err_dvb_dmx_release; ret = dmx->add_frontend(dmx, &pluto->hw_frontend); if (ret < 0) goto err_dvb_dmxdev_release; ret = dmx->add_frontend(dmx, &pluto->mem_frontend); if (ret < 0) goto err_remove_hw_frontend; ret = dmx->connect_frontend(dmx, &pluto->hw_frontend); if (ret < 0) goto err_remove_mem_frontend; ret = frontend_init(pluto); if (ret < 0) goto err_disconnect_frontend; dvb_net_init(dvb_adapter, &pluto->dvbnet, dmx);out: return ret;err_disconnect_frontend: dmx->disconnect_frontend(dmx);err_remove_mem_frontend: dmx->remove_frontend(dmx, &pluto->mem_frontend);err_remove_hw_frontend: dmx->remove_frontend(dmx, &pluto->hw_frontend);err_dvb_dmxdev_release: dvb_dmxdev_release(&pluto->dmxdev);err_dvb_dmx_release: dvb_dmx_release(dvbdemux);err_dvb_unregister_adapter: dvb_unregister_adapter(dvb_adapter);err_i2c_bit_del_bus: i2c_bit_del_bus(&pluto->i2c_adap);err_pluto_hw_exit: pluto_hw_exit(pluto);err_free_irq: free_irq(pdev->irq, pluto);err_pci_iounmap: pci_iounmap(pdev, pluto->io_mem);err_pci_release_regions: pci_release_regions(pdev);err_pci_disable_device: pci_disable_device(pdev);err_kfree: pci_set_drvdata(pdev, NULL); kfree(pluto); goto out;}static void __devexit pluto2_remove(struct pci_dev *pdev){ struct pluto *pluto = pci_get_drvdata(pdev); struct dvb_adapter *dvb_adapter = &pluto->dvb_adapter; struct dvb_demux *dvbdemux = &pluto->demux; struct dmx_demux *dmx = &dvbdemux->dmx; dmx->close(dmx); dvb_net_release(&pluto->dvbnet); if (pluto->fe) dvb_unregister_frontend(pluto->fe); dmx->disconnect_frontend(dmx); dmx->remove_frontend(dmx, &pluto->mem_frontend); dmx->remove_frontend(dmx, &pluto->hw_frontend); dvb_dmxdev_release(&pluto->dmxdev); dvb_dmx_release(dvbdemux); dvb_unregister_adapter(dvb_adapter); i2c_bit_del_bus(&pluto->i2c_adap); pluto_hw_exit(pluto); free_irq(pdev->irq, pluto); pci_iounmap(pdev, pluto->io_mem); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); kfree(pluto);}#ifndef PCI_VENDOR_ID_SCM#define PCI_VENDOR_ID_SCM 0x0432#endif#ifndef PCI_DEVICE_ID_PLUTO2#define PCI_DEVICE_ID_PLUTO2 0x0001#endifstatic struct pci_device_id pluto2_id_table[] __devinitdata = { { .vendor = PCI_VENDOR_ID_SCM, .device = PCI_DEVICE_ID_PLUTO2, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, { /* empty */ },};MODULE_DEVICE_TABLE(pci, pluto2_id_table);static struct pci_driver pluto2_driver = { .name = DRIVER_NAME, .id_table = pluto2_id_table, .probe = pluto2_probe, .remove = __devexit_p(pluto2_remove),};static int __init pluto2_init(void){ return pci_register_driver(&pluto2_driver);}static void __exit pluto2_exit(void){ pci_unregister_driver(&pluto2_driver);}module_init(pluto2_init);module_exit(pluto2_exit);MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");MODULE_DESCRIPTION("Pluto2 driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -