📄 dm1105.c
字号:
if ((dm1105dvb->PacketErrorCount >= 2) && (dm1105dvb->dmarst == 0)) { outb(1, dm_io_mem(DM1105_RST)); dm1105dvb->wrp = 0; dm1105dvb->PacketErrorCount = 0; dm1105dvb->dmarst = 0; spin_unlock(&dm1105dvb->lock); return IRQ_HANDLED; } } if (nextwrp < oldwrp) { piece = dm1105dvb->buffer_size - oldwrp; memcpy(dm1105dvb->ts_buf + dm1105dvb->buffer_size, dm1105dvb->ts_buf, nextwrp); nbpackets = (piece + nextwrp)/188; } else { nbpackets = (nextwrp - oldwrp)/188; } dvb_dmx_swfilter_packets(&dm1105dvb->demux, &dm1105dvb->ts_buf[oldwrp], nbpackets); dm1105dvb->wrp = nextwrp; spin_unlock(&dm1105dvb->lock); break; case INTSTS_IR: command = inl(dm_io_mem(DM1105_IRCODE)); if (ir_debug) printk("dm1105: received byte 0x%04x\n", command); dm1105dvb->ir.ir_command = command; tasklet_schedule(&dm1105dvb->ir.ir_tasklet); break; } return IRQ_HANDLED;}/* register with input layer */static void input_register_keys(struct infrared *ir){ int i; memset(ir->input_dev->keybit, 0, sizeof(ir->input_dev->keybit)); for (i = 0; i < ARRAY_SIZE(ir->key_map); i++) set_bit(ir->key_map[i], ir->input_dev->keybit); ir->input_dev->keycode = ir->key_map; ir->input_dev->keycodesize = sizeof(ir->key_map[0]); ir->input_dev->keycodemax = ARRAY_SIZE(ir->key_map);}int __devinit dm1105_ir_init(struct dm1105dvb *dm1105){ struct input_dev *input_dev; int err; dm1105dvb_local = dm1105; input_dev = input_allocate_device(); if (!input_dev) return -ENOMEM; dm1105->ir.input_dev = input_dev; snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys), "pci-%s/ir0", pci_name(dm1105->pdev)); input_dev->evbit[0] = BIT(EV_KEY); input_dev->name = "DVB on-card IR receiver"; input_dev->phys = dm1105->ir.input_phys; input_dev->id.bustype = BUS_PCI; input_dev->id.version = 2; if (dm1105->pdev->subsystem_vendor) { input_dev->id.vendor = dm1105->pdev->subsystem_vendor; input_dev->id.product = dm1105->pdev->subsystem_device; } else { input_dev->id.vendor = dm1105->pdev->vendor; input_dev->id.product = dm1105->pdev->device; } input_dev->dev.parent = &dm1105->pdev->dev; /* initial keymap */ memcpy(dm1105->ir.key_map, ir_codes_dm1105_nec, sizeof dm1105->ir.key_map); input_register_keys(&dm1105->ir); err = input_register_device(input_dev); if (err) { input_free_device(input_dev); return err; } tasklet_init(&dm1105->ir.ir_tasklet, dm1105_emit_key, (unsigned long) &dm1105->ir); return 0;}void __devexit dm1105_ir_exit(struct dm1105dvb *dm1105){ tasklet_kill(&dm1105->ir.ir_tasklet); input_unregister_device(dm1105->ir.input_dev);}static int __devinit dm1105dvb_hw_init(struct dm1105dvb *dm1105dvb){ dm1105dvb_disable_irqs(dm1105dvb); outb(0, dm_io_mem(DM1105_HOST_CTR)); /*DATALEN 188,*/ outb(188, dm_io_mem(DM1105_DTALENTH)); /*TS_STRT TS_VALP MSBFIRST TS_MODE ALPAS TSPES*/ outw(0xc10a, dm_io_mem(DM1105_TSCTR)); /* map DMA and set address */ dm1105dvb_dma_map(dm1105dvb); dm1105dvb_set_dma_addr(dm1105dvb); /* big buffer */ outl(5*DM1105_DMA_BYTES, dm_io_mem(DM1105_RLEN)); outb(47, dm_io_mem(DM1105_INTCNT)); /* IR NEC mode enable */ outb((DM1105_IR_EN | DM1105_SYS_CHK), dm_io_mem(DM1105_IRCTR)); outb(0, dm_io_mem(DM1105_IRMODE)); outw(0, dm_io_mem(DM1105_SYSTEMCODE)); return 0;}static void dm1105dvb_hw_exit(struct dm1105dvb *dm1105dvb){ dm1105dvb_disable_irqs(dm1105dvb); /* IR disable */ outb(0, dm_io_mem(DM1105_IRCTR)); outb(INTMAK_NONEMASK, dm_io_mem(DM1105_INTMAK)); dm1105dvb_dma_unmap(dm1105dvb);}static struct stv0299_config sharp_z0194a_config = { .demod_address = 0x68, .inittab = sharp_z0194a_inittab, .mclk = 88000000UL, .invert = 1, .skip_reinit = 0, .lock_output = STV0299_LOCKOUTPUT_1, .volt13_op0_op1 = STV0299_VOLT13_OP1, .min_delay_ms = 100, .set_symbol_rate = sharp_z0194a_set_symbol_rate,};static struct stv0288_config earda_config = { .demod_address = 0x68, .min_delay_ms = 100,};static struct si21xx_config serit_config = { .demod_address = 0x68, .min_delay_ms = 100,};static struct cx24116_config serit_sp2633_config = { .demod_address = 0x55,};static int __devinit frontend_init(struct dm1105dvb *dm1105dvb){ int ret; switch (dm1105dvb->pdev->subsystem_device) { case PCI_DEVICE_ID_DW2002: dm1105dvb->fe = dvb_attach( stv0299_attach, &sharp_z0194a_config, &dm1105dvb->i2c_adap); if (dm1105dvb->fe) { dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, &dm1105dvb->i2c_adap, DVB_PLL_OPERA1); } if (!dm1105dvb->fe) { dm1105dvb->fe = dvb_attach( stv0288_attach, &earda_config, &dm1105dvb->i2c_adap); if (dm1105dvb->fe) { dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, &dm1105dvb->i2c_adap); } } if (!dm1105dvb->fe) { dm1105dvb->fe = dvb_attach( si21xx_attach, &serit_config, &dm1105dvb->i2c_adap); if (dm1105dvb->fe) dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; } break; case PCI_DEVICE_ID_DW2004: dm1105dvb->fe = dvb_attach( cx24116_attach, &serit_sp2633_config, &dm1105dvb->i2c_adap); if (dm1105dvb->fe) dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; break; } if (!dm1105dvb->fe) { dev_err(&dm1105dvb->pdev->dev, "could not attach frontend\n"); return -ENODEV; } ret = dvb_register_frontend(&dm1105dvb->dvb_adapter, dm1105dvb->fe); if (ret < 0) { if (dm1105dvb->fe->ops.release) dm1105dvb->fe->ops.release(dm1105dvb->fe); dm1105dvb->fe = NULL; return ret; } return 0;}static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac){ static u8 command[1] = { 0x28 }; struct i2c_msg msg[] = { { .addr = IIC_24C01_addr >> 1, .flags = 0, .buf = command, .len = 1 }, { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD, .buf = mac, .len = 6 }, }; dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); dev_info(&dm1105dvb->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 dm1105_probe(struct pci_dev *pdev, const struct pci_device_id *ent){ struct dm1105dvb *dm1105dvb; struct dvb_adapter *dvb_adapter; struct dvb_demux *dvbdemux; struct dmx_demux *dmx; int ret = -ENOMEM; dm1105dvb = kzalloc(sizeof(struct dm1105dvb), GFP_KERNEL); if (!dm1105dvb) goto out; dm1105dvb->pdev = pdev; dm1105dvb->buffer_size = 5 * DM1105_DMA_BYTES; dm1105dvb->PacketErrorCount = 0; dm1105dvb->dmarst = 0; ret = pci_enable_device(pdev); if (ret < 0) goto err_kfree; 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; dm1105dvb->io_mem = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); if (!dm1105dvb->io_mem) { ret = -EIO; goto err_pci_release_regions; } spin_lock_init(&dm1105dvb->lock); pci_set_drvdata(pdev, dm1105dvb); ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, DRIVER_NAME, dm1105dvb); if (ret < 0) goto err_pci_iounmap; ret = dm1105dvb_hw_init(dm1105dvb); if (ret < 0) goto err_free_irq; /* i2c */ i2c_set_adapdata(&dm1105dvb->i2c_adap, dm1105dvb); strcpy(dm1105dvb->i2c_adap.name, DRIVER_NAME); dm1105dvb->i2c_adap.owner = THIS_MODULE; dm1105dvb->i2c_adap.class = I2C_CLASS_TV_DIGITAL; dm1105dvb->i2c_adap.dev.parent = &pdev->dev; dm1105dvb->i2c_adap.algo = &dm1105_algo; dm1105dvb->i2c_adap.algo_data = dm1105dvb; ret = i2c_add_adapter(&dm1105dvb->i2c_adap); if (ret < 0) goto err_dm1105dvb_hw_exit; /* dvb */ ret = dvb_register_adapter(&dm1105dvb->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev, adapter_nr); if (ret < 0) goto err_i2c_del_adapter; dvb_adapter = &dm1105dvb->dvb_adapter; dm1105dvb_read_mac(dm1105dvb, dvb_adapter->proposed_mac); dvbdemux = &dm1105dvb->demux; dvbdemux->filternum = 256; dvbdemux->feednum = 256; dvbdemux->start_feed = dm1105dvb_start_feed; dvbdemux->stop_feed = dm1105dvb_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; dm1105dvb->dmxdev.filternum = 256; dm1105dvb->dmxdev.demux = dmx; dm1105dvb->dmxdev.capabilities = 0; ret = dvb_dmxdev_init(&dm1105dvb->dmxdev, dvb_adapter); if (ret < 0) goto err_dvb_dmx_release; dm1105dvb->hw_frontend.source = DMX_FRONTEND_0; ret = dmx->add_frontend(dmx, &dm1105dvb->hw_frontend); if (ret < 0) goto err_dvb_dmxdev_release; dm1105dvb->mem_frontend.source = DMX_MEMORY_FE; ret = dmx->add_frontend(dmx, &dm1105dvb->mem_frontend); if (ret < 0) goto err_remove_hw_frontend; ret = dmx->connect_frontend(dmx, &dm1105dvb->hw_frontend); if (ret < 0) goto err_remove_mem_frontend; ret = frontend_init(dm1105dvb); if (ret < 0) goto err_disconnect_frontend; dvb_net_init(dvb_adapter, &dm1105dvb->dvbnet, dmx); dm1105_ir_init(dm1105dvb);out: return ret;err_disconnect_frontend: dmx->disconnect_frontend(dmx);err_remove_mem_frontend: dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend);err_remove_hw_frontend: dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend);err_dvb_dmxdev_release: dvb_dmxdev_release(&dm1105dvb->dmxdev);err_dvb_dmx_release: dvb_dmx_release(dvbdemux);err_dvb_unregister_adapter: dvb_unregister_adapter(dvb_adapter);err_i2c_del_adapter: i2c_del_adapter(&dm1105dvb->i2c_adap);err_dm1105dvb_hw_exit: dm1105dvb_hw_exit(dm1105dvb);err_free_irq: free_irq(pdev->irq, dm1105dvb);err_pci_iounmap: pci_iounmap(pdev, dm1105dvb->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(dm1105dvb); goto out;}static void __devexit dm1105_remove(struct pci_dev *pdev){ struct dm1105dvb *dm1105dvb = pci_get_drvdata(pdev); struct dvb_adapter *dvb_adapter = &dm1105dvb->dvb_adapter; struct dvb_demux *dvbdemux = &dm1105dvb->demux; struct dmx_demux *dmx = &dvbdemux->dmx; dm1105_ir_exit(dm1105dvb); dmx->close(dmx); dvb_net_release(&dm1105dvb->dvbnet); if (dm1105dvb->fe) dvb_unregister_frontend(dm1105dvb->fe); dmx->disconnect_frontend(dmx); dmx->remove_frontend(dmx, &dm1105dvb->mem_frontend); dmx->remove_frontend(dmx, &dm1105dvb->hw_frontend); dvb_dmxdev_release(&dm1105dvb->dmxdev); dvb_dmx_release(dvbdemux); dvb_unregister_adapter(dvb_adapter); if (&dm1105dvb->i2c_adap) i2c_del_adapter(&dm1105dvb->i2c_adap); dm1105dvb_hw_exit(dm1105dvb); synchronize_irq(pdev->irq); free_irq(pdev->irq, dm1105dvb); pci_iounmap(pdev, dm1105dvb->io_mem); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); kfree(dm1105dvb);}static struct pci_device_id dm1105_id_table[] __devinitdata = { { .vendor = PCI_VENDOR_ID_TRIGEM, .device = PCI_DEVICE_ID_DM1105, .subvendor = PCI_ANY_ID, .subdevice = PCI_DEVICE_ID_DW2002, }, { .vendor = PCI_VENDOR_ID_TRIGEM, .device = PCI_DEVICE_ID_DM1105, .subvendor = PCI_ANY_ID, .subdevice = PCI_DEVICE_ID_DW2004, }, { /* empty */ },};MODULE_DEVICE_TABLE(pci, dm1105_id_table);static struct pci_driver dm1105_driver = { .name = DRIVER_NAME, .id_table = dm1105_id_table, .probe = dm1105_probe, .remove = __devexit_p(dm1105_remove),};static int __init dm1105_init(void){ return pci_register_driver(&dm1105_driver);}static void __exit dm1105_exit(void){ pci_unregister_driver(&dm1105_driver);}module_init(dm1105_init);module_exit(dm1105_exit);MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");MODULE_DESCRIPTION("SDMC DM1105 DVB driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -