diff options
author | Steven Toth <stoth@hauppauge.com> | 2006-12-02 18:15:51 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 05:50:47 -0500 |
commit | 6c5be74c86f102c2d4e123bc51d2fa93155fd794 (patch) | |
tree | 72bb1b00045f7c263721f113f92d286405ae96d7 /drivers/media/video/cx88/cx88-dvb.c | |
parent | 91bb9be6ff4101652bb104f9f083f340e73ba6dd (diff) |
V4L/DVB (4676): Dynamic cx88 mpeg port management for HVR1300 MPEG2/DVB-T support.
A series of patches to change the cx88 framework to allow the
PCI mpeg port to be shared dynamically between different
types of drivers or applications. This patch changes the cx88-dvb
and cx88-blackbird drivers to become 'sub drivers' of a higher
single cx88-mpeg driver.
The cx88-mpeg driver is a superset of the previous cx88-mpeg/blackbird
drivers and now owns the IRQ. cx88-dvb/blackbird now become mini drivers,
registering themselves with cx88-mpeg through a standard interface with
callbacks.
Sub drivers request access to hardware via the cx88-mpeg driver. In turn
the cx88-mpeg driver determines whether the hardware is busy and accepts
or refuses the request, grant access using callbacks into the sub drivers.
The net effect is that you are no longer able to tamper with the mpeg port
from multiple different applications at the same time, potentially breaking
a live mpeg2 hardware encoding or dvb stream.
The mechanism extends to enable multiple dvb frontends to be registered
and share the single resource.
Signed-off-by: Steven Toth <stoth@hauppauge.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/cx88/cx88-dvb.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-dvb.c | 197 |
1 files changed, 108 insertions, 89 deletions
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 0ef13e7efa2e..8150c09cd2c0 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -57,7 +57,7 @@ module_param(debug, int, 0644); | |||
57 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); | 57 | MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); |
58 | 58 | ||
59 | #define dprintk(level,fmt, arg...) if (debug >= level) \ | 59 | #define dprintk(level,fmt, arg...) if (debug >= level) \ |
60 | printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->core->name , ## arg) | 60 | printk(KERN_DEBUG "%s/2-dvb: " fmt, core->name, ## arg) |
61 | 61 | ||
62 | /* ------------------------------------------------------------------ */ | 62 | /* ------------------------------------------------------------------ */ |
63 | 63 | ||
@@ -315,20 +315,36 @@ static struct cx22702_config hauppauge_novat_config = { | |||
315 | .demod_address = 0x43, | 315 | .demod_address = 0x43, |
316 | .output_mode = CX22702_SERIAL_OUTPUT, | 316 | .output_mode = CX22702_SERIAL_OUTPUT, |
317 | }; | 317 | }; |
318 | |||
319 | static struct cx22702_config hauppauge_hvr1100_config = { | 318 | static struct cx22702_config hauppauge_hvr1100_config = { |
320 | .demod_address = 0x63, | 319 | .demod_address = 0x63, |
321 | .output_mode = CX22702_SERIAL_OUTPUT, | 320 | .output_mode = CX22702_SERIAL_OUTPUT, |
322 | }; | 321 | }; |
323 | 322 | static struct cx22702_config hauppauge_hvr3000_config = { | |
324 | static struct cx22702_config hauppauge_hvr1300_config = { | ||
325 | .demod_address = 0x63, | 323 | .demod_address = 0x63, |
326 | .output_mode = CX22702_SERIAL_OUTPUT, | 324 | .output_mode = CX22702_SERIAL_OUTPUT, |
327 | }; | 325 | }; |
328 | 326 | ||
329 | static struct cx22702_config hauppauge_hvr3000_config = { | 327 | static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, |
328 | int acquire) | ||
329 | { | ||
330 | struct cx8802_dev *dev= fe->dvb->priv; | ||
331 | struct cx8802_driver *drv = NULL; | ||
332 | int ret = 0; | ||
333 | |||
334 | drv = cx8802_get_driver(dev, CX88_MPEG_DVB); | ||
335 | if (drv) { | ||
336 | if(acquire) | ||
337 | ret = drv->request_acquire(drv); | ||
338 | else | ||
339 | ret = drv->request_release(drv); | ||
340 | } | ||
341 | |||
342 | return ret; | ||
343 | } | ||
344 | |||
345 | static struct cx22702_config hauppauge_hvr1300_config = { | ||
330 | .demod_address = 0x63, | 346 | .demod_address = 0x63, |
331 | .output_mode = CX22702_SERIAL_OUTPUT, | 347 | .output_mode = CX22702_SERIAL_OUTPUT, |
332 | }; | 348 | }; |
333 | 349 | ||
334 | static int or51132_set_ts_param(struct dvb_frontend* fe, | 350 | static int or51132_set_ts_param(struct dvb_frontend* fe, |
@@ -555,26 +571,6 @@ static int dvb_register(struct cx8802_dev *dev) | |||
555 | &dvb_pll_fmd1216me); | 571 | &dvb_pll_fmd1216me); |
556 | } | 572 | } |
557 | break; | 573 | break; |
558 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
559 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
560 | &hauppauge_hvr1300_config, | ||
561 | &dev->core->i2c_adap); | ||
562 | if (dev->dvb.frontend != NULL) { | ||
563 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
564 | &dev->core->i2c_adap, | ||
565 | &dvb_pll_fmd1216me); | ||
566 | } | ||
567 | break; | ||
568 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
569 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
570 | &hauppauge_hvr3000_config, | ||
571 | &dev->core->i2c_adap); | ||
572 | if (dev->dvb.frontend != NULL) { | ||
573 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
574 | &dev->core->i2c_adap, | ||
575 | &dvb_pll_fmd1216me); | ||
576 | } | ||
577 | break; | ||
578 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: | 574 | case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: |
579 | dev->dvb.frontend = dvb_attach(mt352_attach, | 575 | dev->dvb.frontend = dvb_attach(mt352_attach, |
580 | &dvico_fusionhdtv, | 576 | &dvico_fusionhdtv, |
@@ -782,6 +778,26 @@ static int dvb_register(struct cx8802_dev *dev) | |||
782 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; | 778 | dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; |
783 | } | 779 | } |
784 | break; | 780 | break; |
781 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
782 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
783 | &hauppauge_hvr1300_config, | ||
784 | &dev->core->i2c_adap); | ||
785 | if (dev->dvb.frontend != NULL) { | ||
786 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
787 | &dev->core->i2c_adap, | ||
788 | &dvb_pll_fmd1216me); | ||
789 | } | ||
790 | break; | ||
791 | case CX88_BOARD_HAUPPAUGE_HVR3000: | ||
792 | dev->dvb.frontend = dvb_attach(cx22702_attach, | ||
793 | &hauppauge_hvr3000_config, | ||
794 | &dev->core->i2c_adap); | ||
795 | if (dev->dvb.frontend != NULL) { | ||
796 | dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, | ||
797 | &dev->core->i2c_adap, | ||
798 | &dvb_pll_fmd1216me); | ||
799 | } | ||
800 | break; | ||
785 | default: | 801 | default: |
786 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", | 802 | printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", |
787 | dev->core->name); | 803 | dev->core->name); |
@@ -796,6 +812,8 @@ static int dvb_register(struct cx8802_dev *dev) | |||
796 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; | 812 | dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; |
797 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; | 813 | dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max; |
798 | } | 814 | } |
815 | /* Ensure all frontends negotiate bus access */ | ||
816 | dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; | ||
799 | 817 | ||
800 | /* Put the analog decoder in standby to keep it quiet */ | 818 | /* Put the analog decoder in standby to keep it quiet */ |
801 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | 819 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
@@ -806,37 +824,67 @@ static int dvb_register(struct cx8802_dev *dev) | |||
806 | 824 | ||
807 | /* ----------------------------------------------------------- */ | 825 | /* ----------------------------------------------------------- */ |
808 | 826 | ||
809 | static int __devinit dvb_probe(struct pci_dev *pci_dev, | 827 | /* CX8802 MPEG -> mini driver - We have been given the hardware */ |
810 | const struct pci_device_id *pci_id) | 828 | static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv) |
811 | { | 829 | { |
812 | struct cx8802_dev *dev; | 830 | struct cx88_core *core = drv->core; |
813 | struct cx88_core *core; | 831 | int err = 0; |
832 | dprintk( 1, "%s\n", __FUNCTION__); | ||
833 | |||
834 | switch (core->board) { | ||
835 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
836 | /* We arrive here with either the cx23416 or the cx22702 | ||
837 | * on the bus. Take the bus from the cx23416 and enable the | ||
838 | * cx22702 demod | ||
839 | */ | ||
840 | cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */ | ||
841 | cx_clear(MO_GP0_IO, 0x00000004); | ||
842 | udelay(1000); | ||
843 | break; | ||
844 | default: | ||
845 | err = -ENODEV; | ||
846 | } | ||
847 | return err; | ||
848 | } | ||
849 | |||
850 | /* CX8802 MPEG -> mini driver - We no longer have the hardware */ | ||
851 | static int cx8802_dvb_advise_release(struct cx8802_driver *drv) | ||
852 | { | ||
853 | struct cx88_core *core = drv->core; | ||
854 | int err = 0; | ||
855 | dprintk( 1, "%s\n", __FUNCTION__); | ||
856 | |||
857 | switch (core->board) { | ||
858 | case CX88_BOARD_HAUPPAUGE_HVR1300: | ||
859 | /* Do Nothing, leave the cx22702 on the bus. */ | ||
860 | break; | ||
861 | default: | ||
862 | err = -ENODEV; | ||
863 | } | ||
864 | return err; | ||
865 | } | ||
866 | |||
867 | static int cx8802_dvb_probe(struct cx8802_driver *drv) | ||
868 | { | ||
869 | struct cx88_core *core = drv->core; | ||
870 | struct cx8802_dev *dev = drv->core->dvbdev; | ||
814 | int err; | 871 | int err; |
815 | 872 | ||
816 | /* general setup */ | 873 | dprintk( 1, "%s\n", __FUNCTION__); |
817 | core = cx88_core_get(pci_dev); | 874 | dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n", |
818 | if (NULL == core) | 875 | core->board, |
819 | return -EINVAL; | 876 | core->name, |
877 | core->pci_bus, | ||
878 | core->pci_slot); | ||
820 | 879 | ||
821 | err = -ENODEV; | 880 | err = -ENODEV; |
822 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) | 881 | if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) |
823 | goto fail_core; | 882 | goto fail_core; |
824 | 883 | ||
825 | err = -ENOMEM; | ||
826 | dev = kzalloc(sizeof(*dev),GFP_KERNEL); | ||
827 | if (NULL == dev) | ||
828 | goto fail_core; | ||
829 | dev->pci = pci_dev; | ||
830 | dev->core = core; | ||
831 | |||
832 | err = cx8802_init_common(dev); | ||
833 | if (0 != err) | ||
834 | goto fail_free; | ||
835 | |||
836 | #ifdef HAVE_VP3054_I2C | 884 | #ifdef HAVE_VP3054_I2C |
837 | err = vp3054_i2c_probe(dev); | 885 | err = vp3054_i2c_probe(dev); |
838 | if (0 != err) | 886 | if (0 != err) |
839 | goto fail_free; | 887 | goto fail_core; |
840 | #endif | 888 | #endif |
841 | 889 | ||
842 | /* dvb stuff */ | 890 | /* dvb stuff */ |
@@ -848,28 +896,16 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, | |||
848 | sizeof(struct cx88_buffer), | 896 | sizeof(struct cx88_buffer), |
849 | dev); | 897 | dev); |
850 | err = dvb_register(dev); | 898 | err = dvb_register(dev); |
851 | if (0 != err) | 899 | if (err != 0) |
852 | goto fail_fini; | 900 | printk("%s dvb_register failed err = %d\n", __FUNCTION__, err); |
853 | |||
854 | /* Maintain a reference to cx88-video can query the 8802 device. */ | ||
855 | core->dvbdev = dev; | ||
856 | return 0; | ||
857 | 901 | ||
858 | fail_fini: | ||
859 | cx8802_fini_common(dev); | ||
860 | fail_free: | ||
861 | kfree(dev); | ||
862 | fail_core: | 902 | fail_core: |
863 | cx88_core_put(core,pci_dev); | ||
864 | return err; | 903 | return err; |
865 | } | 904 | } |
866 | 905 | ||
867 | static void __devexit dvb_remove(struct pci_dev *pci_dev) | 906 | static int cx8802_dvb_remove(struct cx8802_driver *drv) |
868 | { | 907 | { |
869 | struct cx8802_dev *dev = pci_get_drvdata(pci_dev); | 908 | struct cx8802_dev *dev = drv->core->dvbdev; |
870 | |||
871 | /* Destroy any 8802 reference. */ | ||
872 | dev->core->dvbdev = NULL; | ||
873 | 909 | ||
874 | /* dvb */ | 910 | /* dvb */ |
875 | videobuf_dvb_unregister(&dev->dvb); | 911 | videobuf_dvb_unregister(&dev->dvb); |
@@ -878,33 +914,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev) | |||
878 | vp3054_i2c_remove(dev); | 914 | vp3054_i2c_remove(dev); |
879 | #endif | 915 | #endif |
880 | 916 | ||
881 | /* common */ | 917 | return 0; |
882 | cx8802_fini_common(dev); | ||
883 | cx88_core_put(dev->core,dev->pci); | ||
884 | kfree(dev); | ||
885 | } | 918 | } |
886 | 919 | ||
887 | static struct pci_device_id cx8802_pci_tbl[] = { | 920 | static struct cx8802_driver cx8802_dvb_driver = { |
888 | { | 921 | .type_id = CX88_MPEG_DVB, |
889 | .vendor = 0x14f1, | 922 | .hw_access = CX8802_DRVCTL_SHARED, |
890 | .device = 0x8802, | 923 | .probe = cx8802_dvb_probe, |
891 | .subvendor = PCI_ANY_ID, | 924 | .remove = cx8802_dvb_remove, |
892 | .subdevice = PCI_ANY_ID, | 925 | .advise_acquire = cx8802_dvb_advise_acquire, |
893 | },{ | 926 | .advise_release = cx8802_dvb_advise_release, |
894 | /* --- end of list --- */ | ||
895 | } | ||
896 | }; | ||
897 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
898 | |||
899 | static struct pci_driver dvb_pci_driver = { | ||
900 | .name = "cx88-dvb", | ||
901 | .id_table = cx8802_pci_tbl, | ||
902 | .probe = dvb_probe, | ||
903 | .remove = __devexit_p(dvb_remove), | ||
904 | #ifdef CONFIG_PM | ||
905 | .suspend = cx8802_suspend_common, | ||
906 | .resume = cx8802_resume_common, | ||
907 | #endif | ||
908 | }; | 927 | }; |
909 | 928 | ||
910 | static int dvb_init(void) | 929 | static int dvb_init(void) |
@@ -917,12 +936,12 @@ static int dvb_init(void) | |||
917 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", | 936 | printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", |
918 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); | 937 | SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); |
919 | #endif | 938 | #endif |
920 | return pci_register_driver(&dvb_pci_driver); | 939 | return cx8802_register_driver(&cx8802_dvb_driver); |
921 | } | 940 | } |
922 | 941 | ||
923 | static void dvb_fini(void) | 942 | static void dvb_fini(void) |
924 | { | 943 | { |
925 | pci_unregister_driver(&dvb_pci_driver); | 944 | cx8802_unregister_driver(&cx8802_dvb_driver); |
926 | } | 945 | } |
927 | 946 | ||
928 | module_init(dvb_init); | 947 | module_init(dvb_init); |