aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Toth <stoth@hauppauge.com>2006-12-02 18:15:51 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-12-10 05:50:47 -0500
commit6c5be74c86f102c2d4e123bc51d2fa93155fd794 (patch)
tree72bb1b00045f7c263721f113f92d286405ae96d7
parent91bb9be6ff4101652bb104f9f083f340e73ba6dd (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>
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c178
-rw-r--r--drivers/media/video/cx88/cx88-cards.c2
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c197
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c344
-rw-r--r--drivers/media/video/cx88/cx88.h46
5 files changed, 591 insertions, 176 deletions
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 46738321adaf..0037188d77d4 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -50,7 +50,6 @@ MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
50#define dprintk(level,fmt, arg...) if (debug >= level) \ 50#define dprintk(level,fmt, arg...) if (debug >= level) \
51 printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) 51 printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg)
52 52
53static LIST_HEAD(cx8802_devlist);
54 53
55/* ------------------------------------------------------------------ */ 54/* ------------------------------------------------------------------ */
56 55
@@ -882,7 +881,7 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
882 BLACKBIRD_MPEG_CAPTURE, 881 BLACKBIRD_MPEG_CAPTURE,
883 BLACKBIRD_RAW_BITS_NONE); 882 BLACKBIRD_RAW_BITS_NONE);
884 883
885 cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); 884 cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
886 885
887 blackbird_initialize_codec(dev); 886 blackbird_initialize_codec(dev);
888 cx88_set_scale(dev->core, dev->width, dev->height, 887 cx88_set_scale(dev->core, dev->width, dev->height,
@@ -914,11 +913,15 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file,
914 } 913 }
915 914
916 default: 915 default:
917 return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl); 916 return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook);
918 } 917 }
919 return 0; 918 return 0;
920} 919}
921 920
921int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
922 unsigned int cmd, void *arg);
923unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
924
922static unsigned int mpeg_translate_ioctl(unsigned int cmd) 925static unsigned int mpeg_translate_ioctl(unsigned int cmd)
923{ 926{
924 return cmd; 927 return cmd;
@@ -927,33 +930,48 @@ static unsigned int mpeg_translate_ioctl(unsigned int cmd)
927static int mpeg_ioctl(struct inode *inode, struct file *file, 930static int mpeg_ioctl(struct inode *inode, struct file *file,
928 unsigned int cmd, unsigned long arg) 931 unsigned int cmd, unsigned long arg)
929{ 932{
930 cmd = mpeg_translate_ioctl( cmd ); 933 cmd = cx88_ioctl_translator( cmd );
931 return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl); 934 return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
932} 935}
933 936
934static int mpeg_open(struct inode *inode, struct file *file) 937static int mpeg_open(struct inode *inode, struct file *file)
935{ 938{
936 int minor = iminor(inode); 939 int minor = iminor(inode);
937 struct cx8802_dev *h,*dev = NULL; 940 struct cx8802_dev *dev = NULL;
938 struct cx8802_fh *fh; 941 struct cx8802_fh *fh;
939 struct list_head *list; 942 struct cx8802_driver *drv = NULL;
943 int err;
940 944
941 list_for_each(list,&cx8802_devlist) { 945 dprintk( 1, "%s\n", __FUNCTION__);
942 h = list_entry(list, struct cx8802_dev, devlist); 946
943 if (h->mpeg_dev->minor == minor) 947 dev = cx8802_get_device(inode);
944 dev = h; 948 if (dev == NULL)
945 }
946 if (NULL == dev)
947 return -ENODEV; 949 return -ENODEV;
948 950
949 if (blackbird_initialize_codec(dev) < 0) 951 /* Make sure we can acquire the hardware */
952 drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
953 if (drv) {
954 err = drv->request_acquire(drv);
955 if(err != 0) {
956 dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
957 return err;
958 }
959 }
960
961 if (blackbird_initialize_codec(dev) < 0) {
962 if (drv)
963 drv->request_release(drv);
950 return -EINVAL; 964 return -EINVAL;
965 }
951 dprintk(1,"open minor=%d\n",minor); 966 dprintk(1,"open minor=%d\n",minor);
952 967
953 /* allocate + initialize per filehandle data */ 968 /* allocate + initialize per filehandle data */
954 fh = kzalloc(sizeof(*fh),GFP_KERNEL); 969 fh = kzalloc(sizeof(*fh),GFP_KERNEL);
955 if (NULL == fh) 970 if (NULL == fh) {
971 if (drv)
972 drv->request_release(drv);
956 return -ENOMEM; 973 return -ENOMEM;
974 }
957 file->private_data = fh; 975 file->private_data = fh;
958 fh->dev = dev; 976 fh->dev = dev;
959 977
@@ -974,6 +992,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
974static int mpeg_release(struct inode *inode, struct file *file) 992static int mpeg_release(struct inode *inode, struct file *file)
975{ 993{
976 struct cx8802_fh *fh = file->private_data; 994 struct cx8802_fh *fh = file->private_data;
995 struct cx8802_dev *dev = NULL;
996 struct cx8802_driver *drv = NULL;
977 997
978 /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ 998 /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
979 blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, 999 blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
@@ -992,6 +1012,16 @@ static int mpeg_release(struct inode *inode, struct file *file)
992 videobuf_mmap_free(&fh->mpegq); 1012 videobuf_mmap_free(&fh->mpegq);
993 file->private_data = NULL; 1013 file->private_data = NULL;
994 kfree(fh); 1014 kfree(fh);
1015
1016 /* Make sure we release the hardware */
1017 dev = cx8802_get_device(inode);
1018 if (dev == NULL)
1019 return -ENODEV;
1020
1021 drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
1022 if (drv)
1023 drv->request_release(drv);
1024
995 return 0; 1025 return 0;
996} 1026}
997 1027
@@ -1043,6 +1073,44 @@ static struct video_device cx8802_mpeg_template =
1043 1073
1044/* ------------------------------------------------------------------ */ 1074/* ------------------------------------------------------------------ */
1045 1075
1076/* The CX8802 MPEG API will call this when we can use the hardware */
1077static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
1078{
1079 struct cx88_core *core = drv->core;
1080 int err = 0;
1081
1082 switch (core->board) {
1083 case CX88_BOARD_HAUPPAUGE_HVR1300:
1084 /* By default, core setup will leave the cx22702 out of reset, on the bus.
1085 * We left the hardware on power up with the cx22702 active.
1086 * We're being given access to re-arrange the GPIOs.
1087 * Take the bus off the cx22702 and put the cx23416 on it.
1088 */
1089 cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */
1090 cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */
1091 break;
1092 default:
1093 err = -ENODEV;
1094 }
1095 return err;
1096}
1097
1098/* The CX8802 MPEG API will call this when we need to release the hardware */
1099static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
1100{
1101 struct cx88_core *core = drv->core;
1102 int err = 0;
1103
1104 switch (core->board) {
1105 case CX88_BOARD_HAUPPAUGE_HVR1300:
1106 /* Exit leaving the cx23416 on the bus */
1107 break;
1108 default:
1109 err = -ENODEV;
1110 }
1111 return err;
1112}
1113
1046static void blackbird_unregister_video(struct cx8802_dev *dev) 1114static void blackbird_unregister_video(struct cx8802_dev *dev)
1047{ 1115{
1048 if (dev->mpeg_dev) { 1116 if (dev->mpeg_dev) {
@@ -1073,28 +1141,23 @@ static int blackbird_register_video(struct cx8802_dev *dev)
1073 1141
1074/* ----------------------------------------------------------- */ 1142/* ----------------------------------------------------------- */
1075 1143
1076static int __devinit blackbird_probe(struct pci_dev *pci_dev, 1144static int cx8802_blackbird_probe(struct cx8802_driver *drv)
1077 const struct pci_device_id *pci_id)
1078{ 1145{
1079 struct cx8802_dev *dev; 1146 struct cx88_core *core = drv->core;
1080 struct cx88_core *core; 1147 struct cx8802_dev *dev = core->dvbdev;
1081 int err; 1148 int err;
1082 1149
1083 /* general setup */ 1150 dprintk( 1, "%s\n", __FUNCTION__);
1084 core = cx88_core_get(pci_dev); 1151 dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
1085 if (NULL == core) 1152 core->board,
1086 return -EINVAL; 1153 core->name,
1154 core->pci_bus,
1155 core->pci_slot);
1087 1156
1088 err = -ENODEV; 1157 err = -ENODEV;
1089 if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) 1158 if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))
1090 goto fail_core; 1159 goto fail_core;
1091 1160
1092 err = -ENOMEM;
1093 dev = kzalloc(sizeof(*dev),GFP_KERNEL);
1094 if (NULL == dev)
1095 goto fail_core;
1096 dev->pci = pci_dev;
1097 dev->core = core;
1098 dev->width = 720; 1161 dev->width = 720;
1099 dev->height = 576; 1162 dev->height = 576;
1100 cx2341x_fill_defaults(&dev->params); 1163 cx2341x_fill_defaults(&dev->params);
@@ -1106,64 +1169,36 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
1106 dev->height = 576; 1169 dev->height = 576;
1107 } 1170 }
1108 1171
1109 err = cx8802_init_common(dev);
1110 if (0 != err)
1111 goto fail_free;
1112
1113 /* blackbird stuff */ 1172 /* blackbird stuff */
1114 printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", 1173 printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
1115 core->name); 1174 core->name);
1116 host_setup(dev->core); 1175 host_setup(dev->core);
1117 1176
1118 list_add_tail(&dev->devlist,&cx8802_devlist);
1119 blackbird_register_video(dev); 1177 blackbird_register_video(dev);
1120 1178
1121 /* initial device configuration: needed ? */ 1179 /* initial device configuration: needed ? */
1122 1180
1123 return 0; 1181 return 0;
1124 1182
1125 fail_free:
1126 kfree(dev);
1127 fail_core: 1183 fail_core:
1128 cx88_core_put(core,pci_dev);
1129 return err; 1184 return err;
1130} 1185}
1131 1186
1132static void __devexit blackbird_remove(struct pci_dev *pci_dev) 1187static int cx8802_blackbird_remove(struct cx8802_driver *drv)
1133{ 1188{
1134 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
1135
1136 /* blackbird */ 1189 /* blackbird */
1137 blackbird_unregister_video(dev); 1190 blackbird_unregister_video(drv->core->dvbdev);
1138 list_del(&dev->devlist);
1139 1191
1140 /* common */ 1192 return 0;
1141 cx8802_fini_common(dev);
1142 cx88_core_put(dev->core,dev->pci);
1143 kfree(dev);
1144} 1193}
1145 1194
1146static struct pci_device_id cx8802_pci_tbl[] = { 1195static struct cx8802_driver cx8802_blackbird_driver = {
1147 { 1196 .type_id = CX88_MPEG_BLACKBIRD,
1148 .vendor = 0x14f1, 1197 .hw_access = CX8802_DRVCTL_SHARED,
1149 .device = 0x8802, 1198 .probe = cx8802_blackbird_probe,
1150 .subvendor = PCI_ANY_ID, 1199 .remove = cx8802_blackbird_remove,
1151 .subdevice = PCI_ANY_ID, 1200 .advise_acquire = cx8802_blackbird_advise_acquire,
1152 },{ 1201 .advise_release = cx8802_blackbird_advise_release,
1153 /* --- end of list --- */
1154 }
1155};
1156MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
1157
1158static struct pci_driver blackbird_pci_driver = {
1159 .name = "cx88-blackbird",
1160 .id_table = cx8802_pci_tbl,
1161 .probe = blackbird_probe,
1162 .remove = __devexit_p(blackbird_remove),
1163#ifdef CONFIG_PM
1164 .suspend = cx8802_suspend_common,
1165 .resume = cx8802_resume_common,
1166#endif
1167}; 1202};
1168 1203
1169static int blackbird_init(void) 1204static int blackbird_init(void)
@@ -1176,17 +1211,22 @@ static int blackbird_init(void)
1176 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", 1211 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
1177 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); 1212 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
1178#endif 1213#endif
1179 return pci_register_driver(&blackbird_pci_driver); 1214 cx88_ioctl_hook = mpeg_do_ioctl;
1215 cx88_ioctl_translator = mpeg_translate_ioctl;
1216 return cx8802_register_driver(&cx8802_blackbird_driver);
1180} 1217}
1181 1218
1182static void blackbird_fini(void) 1219static void blackbird_fini(void)
1183{ 1220{
1184 pci_unregister_driver(&blackbird_pci_driver); 1221 cx8802_unregister_driver(&cx8802_blackbird_driver);
1185} 1222}
1186 1223
1187module_init(blackbird_init); 1224module_init(blackbird_init);
1188module_exit(blackbird_fini); 1225module_exit(blackbird_fini);
1189 1226
1227EXPORT_SYMBOL(cx88_ioctl_hook);
1228EXPORT_SYMBOL(cx88_ioctl_translator);
1229
1190/* ----------------------------------------------------------- */ 1230/* ----------------------------------------------------------- */
1191/* 1231/*
1192 * Local variables: 1232 * Local variables:
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index f764a57c56be..1c5db2070a6e 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1303,7 +1303,7 @@ struct cx88_board cx88_boards[] = {
1303 .gpio0 = 0xe780, 1303 .gpio0 = 0xe780,
1304 }}, 1304 }},
1305 /* fixme: Add radio support */ 1305 /* fixme: Add radio support */
1306 .mpeg = CX88_MPEG_DVB, 1306 .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
1307 }, 1307 },
1308}; 1308};
1309const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); 1309const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
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);
57MODULE_PARM_DESC(debug,"enable debug messages [dvb]"); 57MODULE_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
319static struct cx22702_config hauppauge_hvr1100_config = { 318static 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 322static struct cx22702_config hauppauge_hvr3000_config = {
324static 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
329static struct cx22702_config hauppauge_hvr3000_config = { 327static 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
345static 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
334static int or51132_set_ts_param(struct dvb_frontend* fe, 350static 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
809static 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) 828static 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 */
851static 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
867static 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
867static void __devexit dvb_remove(struct pci_dev *pci_dev) 906static 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
887static struct pci_device_id cx8802_pci_tbl[] = { 920static 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};
897MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
898
899static 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
910static int dvb_init(void) 929static 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
923static void dvb_fini(void) 942static void dvb_fini(void)
924{ 943{
925 pci_unregister_driver(&dvb_pci_driver); 944 cx8802_unregister_driver(&cx8802_dvb_driver);
926} 945}
927 946
928module_init(dvb_init); 947module_init(dvb_init);
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 6b23a4e6f66d..6f155713ee02 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -44,8 +44,12 @@ module_param(debug,int,0644);
44MODULE_PARM_DESC(debug,"enable debug messages [mpeg]"); 44MODULE_PARM_DESC(debug,"enable debug messages [mpeg]");
45 45
46#define dprintk(level,fmt, arg...) if (debug >= level) \ 46#define dprintk(level,fmt, arg...) if (debug >= level) \
47 printk(KERN_DEBUG "%s/2: " fmt, dev->core->name , ## arg) 47 printk(KERN_DEBUG "%s/2-mpeg: " fmt, dev->core->name, ## arg)
48 48
49#define mpeg_dbg(level,fmt, arg...) if (debug >= level) \
50 printk(KERN_DEBUG "%s/2-mpeg: " fmt, core->name, ## arg)
51
52static LIST_HEAD(cx8802_devlist);
49/* ------------------------------------------------------------------ */ 53/* ------------------------------------------------------------------ */
50 54
51static int cx8802_start_dma(struct cx8802_dev *dev, 55static int cx8802_start_dma(struct cx8802_dev *dev,
@@ -65,17 +69,13 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
65 69
66 /* FIXME: this needs a review. 70 /* FIXME: this needs a review.
67 * also: move to cx88-blackbird + cx88-dvb source files? */ 71 * also: move to cx88-blackbird + cx88-dvb source files? */
68 if (cx88_boards[core->board].mpeg == (CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) ) {
69 /* Report a warning until the mini driver patch is applied,
70 * else the following conditions will set the dma registers incorrectly.
71 * This will be removed in the next major patch and changes to the conditions
72 * will be made.
73 */
74 printk(KERN_INFO "%s() board->(CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD) is invalid\n", __FUNCTION__);
75 return -EINVAL;
76 }
77 72
78 if (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) { 73 dprintk( 1, "core->active_type_id = 0x%08x\n", core->active_type_id);
74
75 if ( (core->active_type_id == CX88_MPEG_DVB) &&
76 (cx88_boards[core->board].mpeg & CX88_MPEG_DVB) ) {
77
78 dprintk( 1, "cx8802_start_dma doing .dvb\n");
79 /* negedge driven & software reset */ 79 /* negedge driven & software reset */
80 cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl); 80 cx_write(TS_GEN_CNTRL, 0x0040 | dev->ts_gen_cntrl);
81 udelay(100); 81 udelay(100);
@@ -93,15 +93,17 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
93 cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */ 93 cx_write(MO_PINMUX_IO, 0x88); /* Enable MPEG parallel IO and video signal pins */
94 udelay(100); 94 udelay(100);
95 break; 95 break;
96 case CX88_BOARD_HAUPPAUGE_HVR1300:
97 break;
96 default: 98 default:
97 cx_write(TS_SOP_STAT, 0x00); 99 cx_write(TS_SOP_STAT, 0x00);
98 break; 100 break;
99 } 101 }
100 cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl); 102 cx_write(TS_GEN_CNTRL, dev->ts_gen_cntrl);
101 udelay(100); 103 udelay(100);
102 } 104 } else if ( (core->active_type_id == CX88_MPEG_BLACKBIRD) &&
103 105 (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) ) {
104 if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { 106 dprintk( 1, "cx8802_start_dma doing .blackbird\n");
105 cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */ 107 cx_write(MO_PINMUX_IO, 0x88); /* enable MPEG parallel IO */
106 108
107 cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */ 109 cx_write(TS_GEN_CNTRL, 0x46); /* punctured clock TS & posedge driven & software reset */
@@ -112,6 +114,10 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
112 114
113 cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */ 115 cx_write(TS_GEN_CNTRL, 0x06); /* punctured clock TS & posedge driven */
114 udelay(100); 116 udelay(100);
117 } else {
118 printk( "%s() Failed. Unsupported value in .mpeg (0x%08x)\n", __FUNCTION__,
119 cx88_boards[core->board].mpeg );
120 return -EINVAL;
115 } 121 }
116 122
117 /* reset counter */ 123 /* reset counter */
@@ -542,8 +548,311 @@ int cx8802_resume_common(struct pci_dev *pci_dev)
542 return 0; 548 return 0;
543} 549}
544 550
551struct cx8802_dev * cx8802_get_device(struct inode *inode)
552{
553 int minor = iminor(inode);
554 struct cx8802_dev *h = NULL;
555 struct list_head *list;
556
557 list_for_each(list,&cx8802_devlist) {
558 h = list_entry(list, struct cx8802_dev, devlist);
559 if (h->mpeg_dev->minor == minor)
560 return h;
561 }
562
563 return NULL;
564}
565
566struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype)
567{
568 struct cx8802_dev *h = NULL;
569 struct cx8802_driver *d = NULL;
570 struct list_head *list;
571 struct list_head *list2;
572
573 list_for_each(list,&cx8802_devlist) {
574 h = list_entry(list, struct cx8802_dev, devlist);
575
576 list_for_each(list2, &h->drvlist.devlist) {
577 d = list_entry(list2, struct cx8802_driver, devlist);
578
579 /* only unregister the correct driver type */
580 if (d->type_id == btype) {
581 return d;
582 }
583 }
584 }
585
586 return NULL;
587}
588
589/* Driver asked for hardware access. */
590int cx8802_request_acquire(struct cx8802_driver *drv)
591{
592 struct cx88_core *core = drv->core;
593
594 /* Fail a request for hardware if the device is busy. */
595 if (core->active_type_id != CX88_BOARD_NONE)
596 return -EBUSY;
597
598 if (drv->advise_acquire)
599 {
600 core->active_type_id = drv->type_id;
601 drv->advise_acquire(drv);
602
603 mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
604 }
605
606 return 0;
607}
608
609/* Driver asked to release hardware. */
610int cx8802_request_release(struct cx8802_driver *drv)
611{
612 struct cx88_core *core = drv->core;
613
614 if (drv->advise_release)
615 {
616 drv->advise_release(drv);
617 core->active_type_id = CX88_BOARD_NONE;
618 mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
619 }
620
621 return 0;
622}
623
624static int cx8802_check_driver(struct cx8802_driver *drv)
625{
626 if (drv == NULL)
627 return -ENODEV;
628
629 if ((drv->type_id != CX88_MPEG_DVB) &&
630 (drv->type_id != CX88_MPEG_BLACKBIRD))
631 return -EINVAL;
632
633 if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
634 (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
635 return -EINVAL;
636
637 if ((drv->probe == NULL) ||
638 (drv->remove == NULL) ||
639 (drv->advise_acquire == NULL) ||
640 (drv->advise_release == NULL))
641 return -EINVAL;
642
643 return 0;
644}
645
646int cx8802_register_driver(struct cx8802_driver *drv)
647{
648 struct cx8802_dev *h;
649 struct cx8802_driver *driver;
650 struct list_head *list;
651 int err = 0, i = 0;
652
653 printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ ,
654 drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
655 drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
656
657 if ((err = cx8802_check_driver(drv)) != 0) {
658 printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ );
659 return err;
660 }
661
662 list_for_each(list,&cx8802_devlist) {
663 i++;
664 h = list_entry(list, struct cx8802_dev, devlist);
665
666 printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
667 h->core->name,h->pci->subsystem_vendor,
668 h->pci->subsystem_device,cx88_boards[h->core->board].name,
669 h->core->board);
670
671 /* Bring up a new struct for each driver instance */
672 driver = kzalloc(sizeof(*drv),GFP_KERNEL);
673 if (driver == NULL)
674 return -ENOMEM;
675
676 /* Snapshot of the driver registration data */
677 drv->core = h->core;
678 drv->suspend = cx8802_suspend_common;
679 drv->resume = cx8802_resume_common;
680 drv->request_acquire = cx8802_request_acquire;
681 drv->request_release = cx8802_request_release;
682 memcpy(driver, drv, sizeof(*driver));
683
684 err = drv->probe(driver);
685 if (err == 0) {
686 mutex_lock(&drv->core->lock);
687 list_add_tail(&driver->devlist,&h->drvlist.devlist);
688 mutex_unlock(&drv->core->lock);
689 } else {
690 printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err);
691 }
692
693 }
694 if (i == 0)
695 err = -ENODEV;
696
697 return err;
698}
699
700int cx8802_unregister_driver(struct cx8802_driver *drv)
701{
702 struct cx8802_dev *h;
703 struct cx8802_driver *d;
704 struct list_head *list;
705 struct list_head *list2, *q;
706 int err = 0, i = 0;
707
708 printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ ,
709 drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird");
710
711 list_for_each(list,&cx8802_devlist) {
712 i++;
713 h = list_entry(list, struct cx8802_dev, devlist);
714
715 printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
716 h->core->name,h->pci->subsystem_vendor,
717 h->pci->subsystem_device,cx88_boards[h->core->board].name,
718 h->core->board);
719
720 list_for_each_safe(list2, q, &h->drvlist.devlist) {
721 d = list_entry(list2, struct cx8802_driver, devlist);
722
723 /* only unregister the correct driver type */
724 if (d->type_id != drv->type_id)
725 continue;
726
727 err = d->remove(d);
728 if (err == 0) {
729 mutex_lock(&drv->core->lock);
730 list_del(list2);
731 mutex_unlock(&drv->core->lock);
732 } else
733 printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err);
734
735 }
736
737 }
738
739 return err;
740}
741
545/* ----------------------------------------------------------- */ 742/* ----------------------------------------------------------- */
743static int __devinit cx8802_probe(struct pci_dev *pci_dev,
744 const struct pci_device_id *pci_id)
745{
746 struct cx8802_dev *dev;
747 struct cx88_core *core;
748 int err;
749
750 /* general setup */
751 core = cx88_core_get(pci_dev);
752 if (NULL == core)
753 return -EINVAL;
754
755 printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
756
757 err = -ENODEV;
758 if (!cx88_boards[core->board].mpeg)
759 goto fail_core;
760
761 err = -ENOMEM;
762 dev = kzalloc(sizeof(*dev),GFP_KERNEL);
763 if (NULL == dev)
764 goto fail_core;
765 dev->pci = pci_dev;
766 dev->core = core;
767
768 err = cx8802_init_common(dev);
769 if (err != 0)
770 goto fail_free;
771
772 INIT_LIST_HEAD(&dev->drvlist.devlist);
773 list_add_tail(&dev->devlist,&cx8802_devlist);
546 774
775 /* Maintain a reference so cx88-video can query the 8802 device. */
776 core->dvbdev = dev;
777 return 0;
778
779 fail_free:
780 kfree(dev);
781 fail_core:
782 cx88_core_put(core,pci_dev);
783 return err;
784}
785
786static void __devexit cx8802_remove(struct pci_dev *pci_dev)
787{
788 struct cx8802_dev *dev;
789 struct cx8802_driver *h;
790 struct list_head *list;
791
792 dev = pci_get_drvdata(pci_dev);
793
794 dprintk( 1, "%s\n", __FUNCTION__);
795
796 list_for_each(list,&dev->drvlist.devlist) {
797 h = list_entry(list, struct cx8802_driver, devlist);
798 dprintk( 1, " ->driver\n");
799 if (h->remove == NULL) {
800 printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__);
801 continue;
802 }
803 printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id);
804 cx8802_unregister_driver(h);
805 list_del(&dev->drvlist.devlist);
806 }
807
808 /* Destroy any 8802 reference. */
809 dev->core->dvbdev = NULL;
810
811 /* common */
812 cx8802_fini_common(dev);
813 cx88_core_put(dev->core,dev->pci);
814 kfree(dev);
815}
816
817static struct pci_device_id cx8802_pci_tbl[] = {
818 {
819 .vendor = 0x14f1,
820 .device = 0x8802,
821 .subvendor = PCI_ANY_ID,
822 .subdevice = PCI_ANY_ID,
823 },{
824 /* --- end of list --- */
825 }
826};
827MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
828
829static struct pci_driver cx8802_pci_driver = {
830 .name = "cx88-mpeg driver manager",
831 .id_table = cx8802_pci_tbl,
832 .probe = cx8802_probe,
833 .remove = __devexit_p(cx8802_remove),
834};
835
836static int cx8802_init(void)
837{
838 printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n",
839 (CX88_VERSION_CODE >> 16) & 0xff,
840 (CX88_VERSION_CODE >> 8) & 0xff,
841 CX88_VERSION_CODE & 0xff);
842#ifdef SNAPSHOT
843 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
844 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
845#endif
846 return pci_register_driver(&cx8802_pci_driver);
847}
848
849static void cx8802_fini(void)
850{
851 pci_unregister_driver(&cx8802_pci_driver);
852}
853
854module_init(cx8802_init);
855module_exit(cx8802_fini);
547EXPORT_SYMBOL(cx8802_buf_prepare); 856EXPORT_SYMBOL(cx8802_buf_prepare);
548EXPORT_SYMBOL(cx8802_buf_queue); 857EXPORT_SYMBOL(cx8802_buf_queue);
549EXPORT_SYMBOL(cx8802_cancel_buffers); 858EXPORT_SYMBOL(cx8802_cancel_buffers);
@@ -551,9 +860,10 @@ EXPORT_SYMBOL(cx8802_cancel_buffers);
551EXPORT_SYMBOL(cx8802_init_common); 860EXPORT_SYMBOL(cx8802_init_common);
552EXPORT_SYMBOL(cx8802_fini_common); 861EXPORT_SYMBOL(cx8802_fini_common);
553 862
554EXPORT_SYMBOL(cx8802_suspend_common); 863EXPORT_SYMBOL(cx8802_register_driver);
555EXPORT_SYMBOL(cx8802_resume_common); 864EXPORT_SYMBOL(cx8802_unregister_driver);
556 865EXPORT_SYMBOL(cx8802_get_device);
866EXPORT_SYMBOL(cx8802_get_driver);
557/* ----------------------------------------------------------- */ 867/* ----------------------------------------------------------- */
558/* 868/*
559 * Local variables: 869 * Local variables:
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 3bc91aad4fe5..5980e47aee13 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -74,6 +74,11 @@ enum cx88_board_type {
74 CX88_MPEG_BLACKBIRD 74 CX88_MPEG_BLACKBIRD
75}; 75};
76 76
77enum cx8802_board_access {
78 CX8802_DRVCTL_SHARED = 1,
79 CX8802_DRVCTL_EXCLUSIVE = 2,
80};
81
77/* ----------------------------------------------------------- */ 82/* ----------------------------------------------------------- */
78/* tv norms */ 83/* tv norms */
79 84
@@ -330,6 +335,7 @@ struct cx88_core {
330 335
331 /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ 336 /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
332 struct cx8802_dev *dvbdev; 337 struct cx8802_dev *dvbdev;
338 enum cx88_board_type active_type_id;
333}; 339};
334 340
335struct cx8800_dev; 341struct cx8800_dev;
@@ -405,6 +411,31 @@ struct cx8802_suspend_state {
405 int disabled; 411 int disabled;
406}; 412};
407 413
414struct cx8802_driver {
415 struct cx88_core *core;
416 struct list_head devlist;
417
418 /* Type of driver and access required */
419 enum cx88_board_type type_id;
420 enum cx8802_board_access hw_access;
421
422 /* MPEG 8802 internal only */
423 int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
424 int (*resume)(struct pci_dev *pci_dev);
425
426 /* MPEG 8802 -> mini driver - Driver probe and configuration */
427 int (*probe)(struct cx8802_driver *drv);
428 int (*remove)(struct cx8802_driver *drv);
429
430 /* MPEG 8802 -> mini driver - Access for hardware control */
431 int (*advise_acquire)(struct cx8802_driver *drv);
432 int (*advise_release)(struct cx8802_driver *drv);
433
434 /* MPEG 8802 <- mini driver - Access for hardware control */
435 int (*request_acquire)(struct cx8802_driver *drv);
436 int (*request_release)(struct cx8802_driver *drv);
437};
438
408struct cx8802_dev { 439struct cx8802_dev {
409 struct cx88_core *core; 440 struct cx88_core *core;
410 spinlock_t slock; 441 spinlock_t slock;
@@ -439,6 +470,9 @@ struct cx8802_dev {
439 470
440 /* mpeg params */ 471 /* mpeg params */
441 struct cx2341x_mpeg_params params; 472 struct cx2341x_mpeg_params params;
473
474 /* List of attached drivers */
475 struct cx8802_driver drvlist;
442}; 476};
443 477
444/* ----------------------------------------------------------- */ 478/* ----------------------------------------------------------- */
@@ -571,6 +605,11 @@ void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
571void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual); 605void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
572int cx88_audio_thread(void *data); 606int cx88_audio_thread(void *data);
573 607
608int cx8802_register_driver(struct cx8802_driver *drv);
609int cx8802_unregister_driver(struct cx8802_driver *drv);
610struct cx8802_dev * cx8802_get_device(struct inode *inode);
611struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
612
574/* ----------------------------------------------------------- */ 613/* ----------------------------------------------------------- */
575/* cx88-input.c */ 614/* cx88-input.c */
576 615
@@ -600,6 +639,13 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
600extern const u32 cx88_user_ctrls[]; 639extern const u32 cx88_user_ctrls[];
601extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); 640extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
602 641
642/* ----------------------------------------------------------- */
643/* cx88-blackbird.c */
644/* used by cx88-ivtv ioctl emulation layer */
645extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
646 unsigned int cmd, void *arg);
647extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
648
603/* 649/*
604 * Local variables: 650 * Local variables:
605 * c-basic-offset: 8 651 * c-basic-offset: 8