diff options
author | Igor M. Liplianin <liplianin@me.by> | 2009-06-14 20:34:12 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-16 18:07:48 -0400 |
commit | 519a4bdcf8221c6b2d129b3c720761b7cab7f2c1 (patch) | |
tree | 66dc2ede76d298d4561158ab6cced01610c10c2e | |
parent | 1dac77c9d82f344b21c1d962d79875ec331f83cc (diff) |
V4L/DVB (11984): Add support for yet another SDMC DM1105 based DVB-S card.
Add support for SDMC DM1105 based DVB-S cards with PCI ID 195d:1105
Also create separate workqueue for demuxing.
Signed-off-by: Igor M. Liplianin <liplianin@me.by>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/dvb/dm1105/dm1105.c | 121 |
1 files changed, 80 insertions, 41 deletions
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c index 971a8b18f6dd..4dbd7d4185af 100644 --- a/drivers/media/dvb/dm1105/dm1105.c +++ b/drivers/media/dvb/dm1105/dm1105.c | |||
@@ -51,6 +51,9 @@ | |||
51 | #ifndef PCI_VENDOR_ID_TRIGEM | 51 | #ifndef PCI_VENDOR_ID_TRIGEM |
52 | #define PCI_VENDOR_ID_TRIGEM 0x109f | 52 | #define PCI_VENDOR_ID_TRIGEM 0x109f |
53 | #endif | 53 | #endif |
54 | #ifndef PCI_VENDOR_ID_AXESS | ||
55 | #define PCI_VENDOR_ID_AXESS 0x195d | ||
56 | #endif | ||
54 | #ifndef PCI_DEVICE_ID_DM1105 | 57 | #ifndef PCI_DEVICE_ID_DM1105 |
55 | #define PCI_DEVICE_ID_DM1105 0x036f | 58 | #define PCI_DEVICE_ID_DM1105 0x036f |
56 | #endif | 59 | #endif |
@@ -60,6 +63,9 @@ | |||
60 | #ifndef PCI_DEVICE_ID_DW2004 | 63 | #ifndef PCI_DEVICE_ID_DW2004 |
61 | #define PCI_DEVICE_ID_DW2004 0x2004 | 64 | #define PCI_DEVICE_ID_DW2004 0x2004 |
62 | #endif | 65 | #endif |
66 | #ifndef PCI_DEVICE_ID_DM05 | ||
67 | #define PCI_DEVICE_ID_DM05 0x1105 | ||
68 | #endif | ||
63 | /* ----------------------------------------------- */ | 69 | /* ----------------------------------------------- */ |
64 | /* sdmc dm1105 registers */ | 70 | /* sdmc dm1105 registers */ |
65 | 71 | ||
@@ -150,6 +156,11 @@ | |||
150 | #define DM1105_LNB_13V 0x00010100 | 156 | #define DM1105_LNB_13V 0x00010100 |
151 | #define DM1105_LNB_18V 0x00000100 | 157 | #define DM1105_LNB_18V 0x00000100 |
152 | 158 | ||
159 | /* GPIO's for LNB power control for Axess DM05 */ | ||
160 | #define DM05_LNB_MASK 0x00000000 | ||
161 | #define DM05_LNB_13V 0x00020000 | ||
162 | #define DM05_LNB_18V 0x00030000 | ||
163 | |||
153 | static int ir_debug; | 164 | static int ir_debug; |
154 | module_param(ir_debug, int, 0644); | 165 | module_param(ir_debug, int, 0644); |
155 | MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); | 166 | MODULE_PARM_DESC(ir_debug, "enable debugging information for IR decoding"); |
@@ -188,6 +199,8 @@ struct dm1105dvb { | |||
188 | 199 | ||
189 | /* irq */ | 200 | /* irq */ |
190 | struct work_struct work; | 201 | struct work_struct work; |
202 | struct workqueue_struct *wq; | ||
203 | char wqn[16]; | ||
191 | 204 | ||
192 | /* dma */ | 205 | /* dma */ |
193 | dma_addr_t dma_addr; | 206 | dma_addr_t dma_addr; |
@@ -313,15 +326,25 @@ static inline struct dm1105dvb *frontend_to_dm1105dvb(struct dvb_frontend *fe) | |||
313 | static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | 326 | static int dm1105dvb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) |
314 | { | 327 | { |
315 | struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe); | 328 | struct dm1105dvb *dm1105dvb = frontend_to_dm1105dvb(fe); |
329 | u32 lnb_mask, lnb_13v, lnb_18v; | ||
316 | 330 | ||
317 | if (voltage == SEC_VOLTAGE_18) { | 331 | switch (dm1105dvb->pdev->subsystem_device) { |
318 | outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); | 332 | case PCI_DEVICE_ID_DM05: |
319 | outl(DM1105_LNB_18V, dm_io_mem(DM1105_GPIOVAL)); | 333 | lnb_mask = DM05_LNB_MASK; |
320 | } else { | 334 | lnb_13v = DM05_LNB_13V; |
321 | /*LNB ON-13V by default!*/ | 335 | lnb_18v = DM05_LNB_18V; |
322 | outl(DM1105_LNB_MASK, dm_io_mem(DM1105_GPIOCTR)); | 336 | break; |
323 | outl(DM1105_LNB_13V, dm_io_mem(DM1105_GPIOVAL)); | 337 | default: |
324 | } | 338 | lnb_mask = DM1105_LNB_MASK; |
339 | lnb_13v = DM1105_LNB_13V; | ||
340 | lnb_18v = DM1105_LNB_18V; | ||
341 | } | ||
342 | |||
343 | outl(lnb_mask, dm_io_mem(DM1105_GPIOCTR)); | ||
344 | if (voltage == SEC_VOLTAGE_18) | ||
345 | outl(lnb_18v , dm_io_mem(DM1105_GPIOVAL)); | ||
346 | else | ||
347 | outl(lnb_13v, dm_io_mem(DM1105_GPIOVAL)); | ||
325 | 348 | ||
326 | return 0; | 349 | return 0; |
327 | } | 350 | } |
@@ -440,7 +463,7 @@ static irqreturn_t dm1105dvb_irq(int irq, void *dev_id) | |||
440 | case (INTSTS_TSIRQ | INTSTS_IR): | 463 | case (INTSTS_TSIRQ | INTSTS_IR): |
441 | dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) - | 464 | dm1105dvb->nextwrp = inl(dm_io_mem(DM1105_WRP)) - |
442 | inl(dm_io_mem(DM1105_STADR)); | 465 | inl(dm_io_mem(DM1105_STADR)); |
443 | schedule_work(&dm1105dvb->work); | 466 | queue_work(dm1105dvb->wq, &dm1105dvb->work); |
444 | break; | 467 | break; |
445 | case INTSTS_IR: | 468 | case INTSTS_IR: |
446 | dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); | 469 | dm1105dvb->ir.ir_command = inl(dm_io_mem(DM1105_IRCODE)); |
@@ -567,46 +590,44 @@ static int __devinit frontend_init(struct dm1105dvb *dm1105dvb) | |||
567 | int ret; | 590 | int ret; |
568 | 591 | ||
569 | switch (dm1105dvb->pdev->subsystem_device) { | 592 | switch (dm1105dvb->pdev->subsystem_device) { |
570 | case PCI_DEVICE_ID_DW2002: | 593 | case PCI_DEVICE_ID_DW2004: |
571 | dm1105dvb->fe = dvb_attach( | 594 | dm1105dvb->fe = dvb_attach( |
572 | stv0299_attach, &sharp_z0194a_config, | 595 | cx24116_attach, &serit_sp2633_config, |
573 | &dm1105dvb->i2c_adap); | 596 | &dm1105dvb->i2c_adap); |
597 | if (dm1105dvb->fe) | ||
598 | dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; | ||
574 | 599 | ||
600 | break; | ||
601 | default: | ||
602 | dm1105dvb->fe = dvb_attach( | ||
603 | stv0299_attach, &sharp_z0194a_config, | ||
604 | &dm1105dvb->i2c_adap); | ||
575 | if (dm1105dvb->fe) { | 605 | if (dm1105dvb->fe) { |
576 | dm1105dvb->fe->ops.set_voltage = | 606 | dm1105dvb->fe->ops.set_voltage = |
577 | dm1105dvb_set_voltage; | 607 | dm1105dvb_set_voltage; |
578 | dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, | 608 | dvb_attach(dvb_pll_attach, dm1105dvb->fe, 0x60, |
579 | &dm1105dvb->i2c_adap, DVB_PLL_OPERA1); | 609 | &dm1105dvb->i2c_adap, DVB_PLL_OPERA1); |
610 | break; | ||
580 | } | 611 | } |
581 | 612 | ||
582 | if (!dm1105dvb->fe) { | 613 | dm1105dvb->fe = dvb_attach( |
583 | dm1105dvb->fe = dvb_attach( | 614 | stv0288_attach, &earda_config, |
584 | stv0288_attach, &earda_config, | 615 | &dm1105dvb->i2c_adap); |
585 | &dm1105dvb->i2c_adap); | 616 | if (dm1105dvb->fe) { |
586 | if (dm1105dvb->fe) { | 617 | dm1105dvb->fe->ops.set_voltage = |
587 | dm1105dvb->fe->ops.set_voltage = | 618 | dm1105dvb_set_voltage; |
588 | dm1105dvb_set_voltage; | 619 | dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, |
589 | dvb_attach(stb6000_attach, dm1105dvb->fe, 0x61, | 620 | &dm1105dvb->i2c_adap); |
590 | &dm1105dvb->i2c_adap); | 621 | break; |
591 | } | ||
592 | } | 622 | } |
593 | 623 | ||
594 | if (!dm1105dvb->fe) { | ||
595 | dm1105dvb->fe = dvb_attach( | ||
596 | si21xx_attach, &serit_config, | ||
597 | &dm1105dvb->i2c_adap); | ||
598 | if (dm1105dvb->fe) | ||
599 | dm1105dvb->fe->ops.set_voltage = | ||
600 | dm1105dvb_set_voltage; | ||
601 | } | ||
602 | break; | ||
603 | case PCI_DEVICE_ID_DW2004: | ||
604 | dm1105dvb->fe = dvb_attach( | 624 | dm1105dvb->fe = dvb_attach( |
605 | cx24116_attach, &serit_sp2633_config, | 625 | si21xx_attach, &serit_config, |
606 | &dm1105dvb->i2c_adap); | 626 | &dm1105dvb->i2c_adap); |
607 | if (dm1105dvb->fe) | 627 | if (dm1105dvb->fe) |
608 | dm1105dvb->fe->ops.set_voltage = dm1105dvb_set_voltage; | 628 | dm1105dvb->fe->ops.set_voltage = |
609 | break; | 629 | dm1105dvb_set_voltage; |
630 | |||
610 | } | 631 | } |
611 | 632 | ||
612 | if (!dm1105dvb->fe) { | 633 | if (!dm1105dvb->fe) { |
@@ -630,10 +651,17 @@ static void __devinit dm1105dvb_read_mac(struct dm1105dvb *dm1105dvb, u8 *mac) | |||
630 | static u8 command[1] = { 0x28 }; | 651 | static u8 command[1] = { 0x28 }; |
631 | 652 | ||
632 | struct i2c_msg msg[] = { | 653 | struct i2c_msg msg[] = { |
633 | { .addr = IIC_24C01_addr >> 1, .flags = 0, | 654 | { |
634 | .buf = command, .len = 1 }, | 655 | .addr = IIC_24C01_addr >> 1, |
635 | { .addr = IIC_24C01_addr >> 1, .flags = I2C_M_RD, | 656 | .flags = 0, |
636 | .buf = mac, .len = 6 }, | 657 | .buf = command, |
658 | .len = 1 | ||
659 | }, { | ||
660 | .addr = IIC_24C01_addr >> 1, | ||
661 | .flags = I2C_M_RD, | ||
662 | .buf = mac, | ||
663 | .len = 6 | ||
664 | }, | ||
637 | }; | 665 | }; |
638 | 666 | ||
639 | dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); | 667 | dm1105_i2c_xfer(&dm1105dvb->i2c_adap, msg , 2); |
@@ -752,14 +780,22 @@ static int __devinit dm1105_probe(struct pci_dev *pdev, | |||
752 | dm1105_ir_init(dm1105dvb); | 780 | dm1105_ir_init(dm1105dvb); |
753 | 781 | ||
754 | INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer); | 782 | INIT_WORK(&dm1105dvb->work, dm1105_dmx_buffer); |
783 | sprintf(dm1105dvb->wqn, "%s/%d", dvb_adapter->name, dvb_adapter->num); | ||
784 | dm1105dvb->wq = create_singlethread_workqueue(dm1105dvb->wqn); | ||
785 | if (!dm1105dvb->wq) | ||
786 | goto err_dvb_net; | ||
755 | 787 | ||
756 | ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, | 788 | ret = request_irq(pdev->irq, dm1105dvb_irq, IRQF_SHARED, |
757 | DRIVER_NAME, dm1105dvb); | 789 | DRIVER_NAME, dm1105dvb); |
758 | if (ret < 0) | 790 | if (ret < 0) |
759 | goto err_free_irq; | 791 | goto err_workqueue; |
760 | 792 | ||
761 | return 0; | 793 | return 0; |
762 | 794 | ||
795 | err_workqueue: | ||
796 | destroy_workqueue(dm1105dvb->wq); | ||
797 | err_dvb_net: | ||
798 | dvb_net_release(&dm1105dvb->dvbnet); | ||
763 | err_disconnect_frontend: | 799 | err_disconnect_frontend: |
764 | dmx->disconnect_frontend(dmx); | 800 | dmx->disconnect_frontend(dmx); |
765 | err_remove_mem_frontend: | 801 | err_remove_mem_frontend: |
@@ -776,8 +812,6 @@ err_i2c_del_adapter: | |||
776 | i2c_del_adapter(&dm1105dvb->i2c_adap); | 812 | i2c_del_adapter(&dm1105dvb->i2c_adap); |
777 | err_dm1105dvb_hw_exit: | 813 | err_dm1105dvb_hw_exit: |
778 | dm1105dvb_hw_exit(dm1105dvb); | 814 | dm1105dvb_hw_exit(dm1105dvb); |
779 | err_free_irq: | ||
780 | free_irq(pdev->irq, dm1105dvb); | ||
781 | err_pci_iounmap: | 815 | err_pci_iounmap: |
782 | pci_iounmap(pdev, dm1105dvb->io_mem); | 816 | pci_iounmap(pdev, dm1105dvb->io_mem); |
783 | err_pci_release_regions: | 817 | err_pci_release_regions: |
@@ -834,6 +868,11 @@ static struct pci_device_id dm1105_id_table[] __devinitdata = { | |||
834 | .subvendor = PCI_ANY_ID, | 868 | .subvendor = PCI_ANY_ID, |
835 | .subdevice = PCI_DEVICE_ID_DW2004, | 869 | .subdevice = PCI_DEVICE_ID_DW2004, |
836 | }, { | 870 | }, { |
871 | .vendor = PCI_VENDOR_ID_AXESS, | ||
872 | .device = PCI_DEVICE_ID_DM05, | ||
873 | .subvendor = PCI_VENDOR_ID_AXESS, | ||
874 | .subdevice = PCI_DEVICE_ID_DM05, | ||
875 | }, { | ||
837 | /* empty */ | 876 | /* empty */ |
838 | }, | 877 | }, |
839 | }; | 878 | }; |