aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx88')
-rw-r--r--drivers/media/video/cx88/Kconfig1
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c179
-rw-r--r--drivers/media/video/cx88/cx88-cards.c86
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c333
-rw-r--r--drivers/media/video/cx88/cx88-input.c77
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c348
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c13
-rw-r--r--drivers/media/video/cx88/cx88-video.c32
-rw-r--r--drivers/media/video/cx88/cx88.h47
9 files changed, 754 insertions, 362 deletions
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 0f9d96963618..b2a66ba625f9 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -53,6 +53,7 @@ config VIDEO_CX88_DVB
53 select DVB_OR51132 if !DVB_FE_CUSTOMISE 53 select DVB_OR51132 if !DVB_FE_CUSTOMISE
54 select DVB_CX22702 if !DVB_FE_CUSTOMISE 54 select DVB_CX22702 if !DVB_FE_CUSTOMISE
55 select DVB_LGDT330X if !DVB_FE_CUSTOMISE 55 select DVB_LGDT330X if !DVB_FE_CUSTOMISE
56 select DVB_TUNER_LGH06XF if !DVB_FE_CUSTOMISE
56 select DVB_NXT200X if !DVB_FE_CUSTOMISE 57 select DVB_NXT200X if !DVB_FE_CUSTOMISE
57 select DVB_CX24123 if !DVB_FE_CUSTOMISE 58 select DVB_CX24123 if !DVB_FE_CUSTOMISE
58 select DVB_ISL6421 if !DVB_FE_CUSTOMISE 59 select DVB_ISL6421 if !DVB_FE_CUSTOMISE
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 46738321adaf..0cf0360588e6 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,49 @@ 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 dev = cx8802_get_device(inode);
942 h = list_entry(list, struct cx8802_dev, devlist); 946
943 if (h->mpeg_dev->minor == minor) 947 dprintk( 1, "%s\n", __FUNCTION__);
944 dev = h; 948
945 } 949 if (dev == NULL)
946 if (NULL == dev)
947 return -ENODEV; 950 return -ENODEV;
948 951
949 if (blackbird_initialize_codec(dev) < 0) 952 /* Make sure we can acquire the hardware */
953 drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
954 if (drv) {
955 err = drv->request_acquire(drv);
956 if(err != 0) {
957 dprintk(1,"%s: Unable to acquire hardware, %d\n", __FUNCTION__, err);
958 return err;
959 }
960 }
961
962 if (blackbird_initialize_codec(dev) < 0) {
963 if (drv)
964 drv->request_release(drv);
950 return -EINVAL; 965 return -EINVAL;
966 }
951 dprintk(1,"open minor=%d\n",minor); 967 dprintk(1,"open minor=%d\n",minor);
952 968
953 /* allocate + initialize per filehandle data */ 969 /* allocate + initialize per filehandle data */
954 fh = kzalloc(sizeof(*fh),GFP_KERNEL); 970 fh = kzalloc(sizeof(*fh),GFP_KERNEL);
955 if (NULL == fh) 971 if (NULL == fh) {
972 if (drv)
973 drv->request_release(drv);
956 return -ENOMEM; 974 return -ENOMEM;
975 }
957 file->private_data = fh; 976 file->private_data = fh;
958 fh->dev = dev; 977 fh->dev = dev;
959 978
@@ -974,6 +993,8 @@ static int mpeg_open(struct inode *inode, struct file *file)
974static int mpeg_release(struct inode *inode, struct file *file) 993static int mpeg_release(struct inode *inode, struct file *file)
975{ 994{
976 struct cx8802_fh *fh = file->private_data; 995 struct cx8802_fh *fh = file->private_data;
996 struct cx8802_dev *dev = NULL;
997 struct cx8802_driver *drv = NULL;
977 998
978 /* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */ 999 /* 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, 1000 blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
@@ -992,6 +1013,16 @@ static int mpeg_release(struct inode *inode, struct file *file)
992 videobuf_mmap_free(&fh->mpegq); 1013 videobuf_mmap_free(&fh->mpegq);
993 file->private_data = NULL; 1014 file->private_data = NULL;
994 kfree(fh); 1015 kfree(fh);
1016
1017 /* Make sure we release the hardware */
1018 dev = cx8802_get_device(inode);
1019 if (dev == NULL)
1020 return -ENODEV;
1021
1022 drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
1023 if (drv)
1024 drv->request_release(drv);
1025
995 return 0; 1026 return 0;
996} 1027}
997 1028
@@ -1043,6 +1074,44 @@ static struct video_device cx8802_mpeg_template =
1043 1074
1044/* ------------------------------------------------------------------ */ 1075/* ------------------------------------------------------------------ */
1045 1076
1077/* The CX8802 MPEG API will call this when we can use the hardware */
1078static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
1079{
1080 struct cx88_core *core = drv->core;
1081 int err = 0;
1082
1083 switch (core->board) {
1084 case CX88_BOARD_HAUPPAUGE_HVR1300:
1085 /* By default, core setup will leave the cx22702 out of reset, on the bus.
1086 * We left the hardware on power up with the cx22702 active.
1087 * We're being given access to re-arrange the GPIOs.
1088 * Take the bus off the cx22702 and put the cx23416 on it.
1089 */
1090 cx_clear(MO_GP0_IO, 0x00000080); /* cx22702 in reset */
1091 cx_set(MO_GP0_IO, 0x00000004); /* Disable the cx22702 */
1092 break;
1093 default:
1094 err = -ENODEV;
1095 }
1096 return err;
1097}
1098
1099/* The CX8802 MPEG API will call this when we need to release the hardware */
1100static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
1101{
1102 struct cx88_core *core = drv->core;
1103 int err = 0;
1104
1105 switch (core->board) {
1106 case CX88_BOARD_HAUPPAUGE_HVR1300:
1107 /* Exit leaving the cx23416 on the bus */
1108 break;
1109 default:
1110 err = -ENODEV;
1111 }
1112 return err;
1113}
1114
1046static void blackbird_unregister_video(struct cx8802_dev *dev) 1115static void blackbird_unregister_video(struct cx8802_dev *dev)
1047{ 1116{
1048 if (dev->mpeg_dev) { 1117 if (dev->mpeg_dev) {
@@ -1073,28 +1142,23 @@ static int blackbird_register_video(struct cx8802_dev *dev)
1073 1142
1074/* ----------------------------------------------------------- */ 1143/* ----------------------------------------------------------- */
1075 1144
1076static int __devinit blackbird_probe(struct pci_dev *pci_dev, 1145static int cx8802_blackbird_probe(struct cx8802_driver *drv)
1077 const struct pci_device_id *pci_id)
1078{ 1146{
1079 struct cx8802_dev *dev; 1147 struct cx88_core *core = drv->core;
1080 struct cx88_core *core; 1148 struct cx8802_dev *dev = core->dvbdev;
1081 int err; 1149 int err;
1082 1150
1083 /* general setup */ 1151 dprintk( 1, "%s\n", __FUNCTION__);
1084 core = cx88_core_get(pci_dev); 1152 dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
1085 if (NULL == core) 1153 core->board,
1086 return -EINVAL; 1154 core->name,
1155 core->pci_bus,
1156 core->pci_slot);
1087 1157
1088 err = -ENODEV; 1158 err = -ENODEV;
1089 if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD)) 1159 if (!(cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD))
1090 goto fail_core; 1160 goto fail_core;
1091 1161
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; 1162 dev->width = 720;
1099 dev->height = 576; 1163 dev->height = 576;
1100 cx2341x_fill_defaults(&dev->params); 1164 cx2341x_fill_defaults(&dev->params);
@@ -1106,64 +1170,36 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev,
1106 dev->height = 576; 1170 dev->height = 576;
1107 } 1171 }
1108 1172
1109 err = cx8802_init_common(dev);
1110 if (0 != err)
1111 goto fail_free;
1112
1113 /* blackbird stuff */ 1173 /* blackbird stuff */
1114 printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", 1174 printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
1115 core->name); 1175 core->name);
1116 host_setup(dev->core); 1176 host_setup(dev->core);
1117 1177
1118 list_add_tail(&dev->devlist,&cx8802_devlist);
1119 blackbird_register_video(dev); 1178 blackbird_register_video(dev);
1120 1179
1121 /* initial device configuration: needed ? */ 1180 /* initial device configuration: needed ? */
1122 1181
1123 return 0; 1182 return 0;
1124 1183
1125 fail_free:
1126 kfree(dev);
1127 fail_core: 1184 fail_core:
1128 cx88_core_put(core,pci_dev);
1129 return err; 1185 return err;
1130} 1186}
1131 1187
1132static void __devexit blackbird_remove(struct pci_dev *pci_dev) 1188static int cx8802_blackbird_remove(struct cx8802_driver *drv)
1133{ 1189{
1134 struct cx8802_dev *dev = pci_get_drvdata(pci_dev);
1135
1136 /* blackbird */ 1190 /* blackbird */
1137 blackbird_unregister_video(dev); 1191 blackbird_unregister_video(drv->core->dvbdev);
1138 list_del(&dev->devlist);
1139 1192
1140 /* common */ 1193 return 0;
1141 cx8802_fini_common(dev);
1142 cx88_core_put(dev->core,dev->pci);
1143 kfree(dev);
1144} 1194}
1145 1195
1146static struct pci_device_id cx8802_pci_tbl[] = { 1196static struct cx8802_driver cx8802_blackbird_driver = {
1147 { 1197 .type_id = CX88_MPEG_BLACKBIRD,
1148 .vendor = 0x14f1, 1198 .hw_access = CX8802_DRVCTL_SHARED,
1149 .device = 0x8802, 1199 .probe = cx8802_blackbird_probe,
1150 .subvendor = PCI_ANY_ID, 1200 .remove = cx8802_blackbird_remove,
1151 .subdevice = PCI_ANY_ID, 1201 .advise_acquire = cx8802_blackbird_advise_acquire,
1152 },{ 1202 .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}; 1203};
1168 1204
1169static int blackbird_init(void) 1205static int blackbird_init(void)
@@ -1176,17 +1212,22 @@ static int blackbird_init(void)
1176 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", 1212 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
1177 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); 1213 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
1178#endif 1214#endif
1179 return pci_register_driver(&blackbird_pci_driver); 1215 cx88_ioctl_hook = mpeg_do_ioctl;
1216 cx88_ioctl_translator = mpeg_translate_ioctl;
1217 return cx8802_register_driver(&cx8802_blackbird_driver);
1180} 1218}
1181 1219
1182static void blackbird_fini(void) 1220static void blackbird_fini(void)
1183{ 1221{
1184 pci_unregister_driver(&blackbird_pci_driver); 1222 cx8802_unregister_driver(&cx8802_blackbird_driver);
1185} 1223}
1186 1224
1187module_init(blackbird_init); 1225module_init(blackbird_init);
1188module_exit(blackbird_fini); 1226module_exit(blackbird_fini);
1189 1227
1228EXPORT_SYMBOL(cx88_ioctl_hook);
1229EXPORT_SYMBOL(cx88_ioctl_translator);
1230
1190/* ----------------------------------------------------------- */ 1231/* ----------------------------------------------------------- */
1191/* 1232/*
1192 * Local variables: 1233 * Local variables:
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index f764a57c56be..c791708b1336 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -281,18 +281,22 @@ struct cx88_board cx88_boards[] = {
281 .type = CX88_VMUX_TELEVISION, 281 .type = CX88_VMUX_TELEVISION,
282 .vmux = 0, 282 .vmux = 0,
283 .gpio0 = 0x0000bde2, 283 .gpio0 = 0x0000bde2,
284 .extadc = 1,
284 },{ 285 },{
285 .type = CX88_VMUX_COMPOSITE1, 286 .type = CX88_VMUX_COMPOSITE1,
286 .vmux = 1, 287 .vmux = 1,
287 .gpio0 = 0x0000bde6, 288 .gpio0 = 0x0000bde6,
289 .extadc = 1,
288 },{ 290 },{
289 .type = CX88_VMUX_SVIDEO, 291 .type = CX88_VMUX_SVIDEO,
290 .vmux = 2, 292 .vmux = 2,
291 .gpio0 = 0x0000bde6, 293 .gpio0 = 0x0000bde6,
294 .extadc = 1,
292 }}, 295 }},
293 .radio = { 296 .radio = {
294 .type = CX88_RADIO, 297 .type = CX88_RADIO,
295 .gpio0 = 0x0000bd62, 298 .gpio0 = 0x0000bd62,
299 .extadc = 1,
296 }, 300 },
297 .mpeg = CX88_MPEG_BLACKBIRD, 301 .mpeg = CX88_MPEG_BLACKBIRD,
298 }, 302 },
@@ -353,6 +357,7 @@ struct cx88_board cx88_boards[] = {
353 .type = CX88_VMUX_SVIDEO, 357 .type = CX88_VMUX_SVIDEO,
354 .vmux = 2, 358 .vmux = 2,
355 .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? 359 .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in?
360 .extadc = 1,
356 }}, 361 }},
357 .radio = { 362 .radio = {
358 .type = CX88_RADIO, 363 .type = CX88_RADIO,
@@ -523,6 +528,7 @@ struct cx88_board cx88_boards[] = {
523 .input = {{ 528 .input = {{
524 .type = CX88_VMUX_TELEVISION, 529 .type = CX88_VMUX_TELEVISION,
525 .vmux = 0, 530 .vmux = 0,
531 .extadc = 1,
526 }}, 532 }},
527 .mpeg = CX88_MPEG_BLACKBIRD, 533 .mpeg = CX88_MPEG_BLACKBIRD,
528 }, 534 },
@@ -646,18 +652,22 @@ struct cx88_board cx88_boards[] = {
646 .type = CX88_VMUX_TELEVISION, 652 .type = CX88_VMUX_TELEVISION,
647 .vmux = 0, 653 .vmux = 0,
648 .gpio0 = 0x00009d80, 654 .gpio0 = 0x00009d80,
655 .extadc = 1,
649 },{ 656 },{
650 .type = CX88_VMUX_COMPOSITE1, 657 .type = CX88_VMUX_COMPOSITE1,
651 .vmux = 1, 658 .vmux = 1,
652 .gpio0 = 0x00009d76, 659 .gpio0 = 0x00009d76,
660 .extadc = 1,
653 },{ 661 },{
654 .type = CX88_VMUX_SVIDEO, 662 .type = CX88_VMUX_SVIDEO,
655 .vmux = 2, 663 .vmux = 2,
656 .gpio0 = 0x00009d76, 664 .gpio0 = 0x00009d76,
665 .extadc = 1,
657 }}, 666 }},
658 .radio = { 667 .radio = {
659 .type = CX88_RADIO, 668 .type = CX88_RADIO,
660 .gpio0 = 0x00009d00, 669 .gpio0 = 0x00009d00,
670 .extadc = 1,
661 }, 671 },
662 .mpeg = CX88_MPEG_BLACKBIRD, 672 .mpeg = CX88_MPEG_BLACKBIRD,
663 }, 673 },
@@ -786,25 +796,29 @@ struct cx88_board cx88_boards[] = {
786 .tuner_addr = ADDR_UNSET, 796 .tuner_addr = ADDR_UNSET,
787 .radio_addr = ADDR_UNSET, 797 .radio_addr = ADDR_UNSET,
788 .tda9887_conf = TDA9887_PRESENT, 798 .tda9887_conf = TDA9887_PRESENT,
789 .mpeg = CX88_MPEG_BLACKBIRD,
790 .input = {{ 799 .input = {{
791 .type = CX88_VMUX_COMPOSITE1, 800 .type = CX88_VMUX_COMPOSITE1,
792 .vmux = 0, 801 .vmux = 0,
793 .gpio0 = 0x0000cd73, 802 .gpio0 = 0x0000cd73,
803 .extadc = 1,
794 },{ 804 },{
795 .type = CX88_VMUX_SVIDEO, 805 .type = CX88_VMUX_SVIDEO,
796 .vmux = 1, 806 .vmux = 1,
797 .gpio0 = 0x0000cd73, 807 .gpio0 = 0x0000cd73,
808 .extadc = 1,
798 },{ 809 },{
799 .type = CX88_VMUX_TELEVISION, 810 .type = CX88_VMUX_TELEVISION,
800 .vmux = 3, 811 .vmux = 3,
801 .gpio0 = 0x0000cdb3, 812 .gpio0 = 0x0000cdb3,
813 .extadc = 1,
802 }}, 814 }},
803 .radio = { 815 .radio = {
804 .type = CX88_RADIO, 816 .type = CX88_RADIO,
805 .vmux = 2, 817 .vmux = 2,
806 .gpio0 = 0x0000cdf3, 818 .gpio0 = 0x0000cdf3,
819 .extadc = 1,
807 }, 820 },
821 .mpeg = CX88_MPEG_BLACKBIRD,
808 }, 822 },
809 [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { 823 [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = {
810 /* Alexander Wold <awold@bigfoot.com> */ 824 /* Alexander Wold <awold@bigfoot.com> */
@@ -1050,7 +1064,6 @@ struct cx88_board cx88_boards[] = {
1050 .mpeg = CX88_MPEG_DVB, 1064 .mpeg = CX88_MPEG_DVB,
1051 }, 1065 },
1052 [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = { 1066 [CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
1053 /* FIXME: Audio not working for s-video / composite inputs. */
1054 .name = "KWorld HardwareMpegTV XPert", 1067 .name = "KWorld HardwareMpegTV XPert",
1055 .tuner_type = TUNER_PHILIPS_TDA8290, 1068 .tuner_type = TUNER_PHILIPS_TDA8290,
1056 .radio_type = UNSET, 1069 .radio_type = UNSET,
@@ -1065,10 +1078,12 @@ struct cx88_board cx88_boards[] = {
1065 .type = CX88_VMUX_COMPOSITE1, 1078 .type = CX88_VMUX_COMPOSITE1,
1066 .vmux = 1, 1079 .vmux = 1,
1067 .gpio0 = 0x3de6, 1080 .gpio0 = 0x3de6,
1081 .extadc = 1,
1068 },{ 1082 },{
1069 .type = CX88_VMUX_SVIDEO, 1083 .type = CX88_VMUX_SVIDEO,
1070 .vmux = 2, 1084 .vmux = 2,
1071 .gpio0 = 0x3de6, 1085 .gpio0 = 0x3de6,
1086 .extadc = 1,
1072 }}, 1087 }},
1073 .radio = { 1088 .radio = {
1074 .type = CX88_RADIO, 1089 .type = CX88_RADIO,
@@ -1252,35 +1267,35 @@ struct cx88_board cx88_boards[] = {
1252 .gpio0 = 0x070b, 1267 .gpio0 = 0x070b,
1253 }}, 1268 }},
1254 }, 1269 },
1255 [CX88_BOARD_TE_DTV_250_OEM_SWANN] = { 1270 [CX88_BOARD_TE_DTV_250_OEM_SWANN] = {
1256 .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM", 1271 .name = "Shenzhen Tungsten Ages Tech TE-DTV-250 / Swann OEM",
1257 .tuner_type = TUNER_LG_PAL_NEW_TAPC, 1272 .tuner_type = TUNER_LG_PAL_NEW_TAPC,
1258 .radio_type = UNSET, 1273 .radio_type = UNSET,
1259 .tuner_addr = ADDR_UNSET, 1274 .tuner_addr = ADDR_UNSET,
1260 .radio_addr = ADDR_UNSET, 1275 .radio_addr = ADDR_UNSET,
1261 .input = {{ 1276 .input = {{
1262 .type = CX88_VMUX_TELEVISION, 1277 .type = CX88_VMUX_TELEVISION,
1263 .vmux = 0, 1278 .vmux = 0,
1264 .gpio0 = 0x003fffff, 1279 .gpio0 = 0x003fffff,
1265 .gpio1 = 0x00e00000, 1280 .gpio1 = 0x00e00000,
1266 .gpio2 = 0x003fffff, 1281 .gpio2 = 0x003fffff,
1267 .gpio3 = 0x02000000, 1282 .gpio3 = 0x02000000,
1268 },{ 1283 },{
1269 .type = CX88_VMUX_COMPOSITE1, 1284 .type = CX88_VMUX_COMPOSITE1,
1270 .vmux = 1, 1285 .vmux = 1,
1271 .gpio0 = 0x003fffff, 1286 .gpio0 = 0x003fffff,
1272 .gpio1 = 0x00e00000, 1287 .gpio1 = 0x00e00000,
1273 .gpio2 = 0x003fffff, 1288 .gpio2 = 0x003fffff,
1274 .gpio3 = 0x02000000, 1289 .gpio3 = 0x02000000,
1275 },{ 1290 },{
1276 .type = CX88_VMUX_SVIDEO, 1291 .type = CX88_VMUX_SVIDEO,
1277 .vmux = 2, 1292 .vmux = 2,
1278 .gpio0 = 0x003fffff, 1293 .gpio0 = 0x003fffff,
1279 .gpio1 = 0x00e00000, 1294 .gpio1 = 0x00e00000,
1280 .gpio2 = 0x003fffff, 1295 .gpio2 = 0x003fffff,
1281 .gpio3 = 0x02000000, 1296 .gpio3 = 0x02000000,
1282 }}, 1297 }},
1283 }, 1298 },
1284 [CX88_BOARD_HAUPPAUGE_HVR1300] = { 1299 [CX88_BOARD_HAUPPAUGE_HVR1300] = {
1285 .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder", 1300 .name = "Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder",
1286 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, 1301 .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3,
@@ -1293,17 +1308,20 @@ struct cx88_board cx88_boards[] = {
1293 .type = CX88_VMUX_TELEVISION, 1308 .type = CX88_VMUX_TELEVISION,
1294 .vmux = 0, 1309 .vmux = 0,
1295 .gpio0 = 0xe780, 1310 .gpio0 = 0xe780,
1311 .extadc = 1,
1296 },{ 1312 },{
1297 .type = CX88_VMUX_COMPOSITE1, 1313 .type = CX88_VMUX_COMPOSITE1,
1298 .vmux = 1, 1314 .vmux = 1,
1299 .gpio0 = 0xe780, 1315 .gpio0 = 0xe780,
1316 .extadc = 1,
1300 },{ 1317 },{
1301 .type = CX88_VMUX_SVIDEO, 1318 .type = CX88_VMUX_SVIDEO,
1302 .vmux = 2, 1319 .vmux = 2,
1303 .gpio0 = 0xe780, 1320 .gpio0 = 0xe780,
1321 .extadc = 1,
1304 }}, 1322 }},
1305 /* fixme: Add radio support */ 1323 /* fixme: Add radio support */
1306 .mpeg = CX88_MPEG_DVB, 1324 .mpeg = CX88_MPEG_DVB | CX88_MPEG_BLACKBIRD,
1307 }, 1325 },
1308}; 1326};
1309const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards); 1327const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -1513,6 +1531,10 @@ struct cx88_subid cx88_subids[] = {
1513 },{ 1531 },{
1514 .subvendor = 0x17de, 1532 .subvendor = 0x17de,
1515 .subdevice = 0x0840, 1533 .subdevice = 0x0840,
1534 .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
1535 },{
1536 .subvendor = 0x1421,
1537 .subdevice = 0x0305,
1516 .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, 1538 .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT,
1517 },{ 1539 },{
1518 .subvendor = 0x18ac, 1540 .subvendor = 0x18ac,
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 0ef13e7efa2e..8b203354fccd 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -42,7 +42,7 @@
42#include "cx22702.h" 42#include "cx22702.h"
43#include "or51132.h" 43#include "or51132.h"
44#include "lgdt330x.h" 44#include "lgdt330x.h"
45#include "lg_h06xf.h" 45#include "lgh06xf.h"
46#include "nxt200x.h" 46#include "nxt200x.h"
47#include "cx24123.h" 47#include "cx24123.h"
48#include "isl6421.h" 48#include "isl6421.h"
@@ -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
@@ -74,8 +74,8 @@ static int dvb_buf_setup(struct videobuf_queue *q,
74 return 0; 74 return 0;
75} 75}
76 76
77static int dvb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, 77static int dvb_buf_prepare(struct videobuf_queue *q,
78 enum v4l2_field field) 78 struct videobuf_buffer *vb, enum v4l2_field field)
79{ 79{
80 struct cx8802_dev *dev = q->priv_data; 80 struct cx8802_dev *dev = q->priv_data;
81 return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field); 81 return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
@@ -87,7 +87,8 @@ static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
87 cx8802_buf_queue(dev, (struct cx88_buffer*)vb); 87 cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
88} 88}
89 89
90static void dvb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) 90static void dvb_buf_release(struct videobuf_queue *q,
91 struct videobuf_buffer *vb)
91{ 92{
92 cx88_free_buffer(q, (struct cx88_buffer*)vb); 93 cx88_free_buffer(q, (struct cx88_buffer*)vb);
93} 94}
@@ -100,6 +101,26 @@ static struct videobuf_queue_ops dvb_qops = {
100}; 101};
101 102
102/* ------------------------------------------------------------------ */ 103/* ------------------------------------------------------------------ */
104
105static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
106{
107 struct cx8802_dev *dev= fe->dvb->priv;
108 struct cx8802_driver *drv = NULL;
109 int ret = 0;
110
111 drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
112 if (drv) {
113 if (acquire)
114 ret = drv->request_acquire(drv);
115 else
116 ret = drv->request_release(drv);
117 }
118
119 return ret;
120}
121
122/* ------------------------------------------------------------------ */
123
103static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe) 124static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
104{ 125{
105 static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 }; 126 static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x39 };
@@ -268,35 +289,6 @@ static struct mt352_config dntv_live_dvbt_pro_config = {
268}; 289};
269#endif 290#endif
270 291
271static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe,
272 struct dvb_frontend_parameters *params)
273{
274 u8 pllbuf[4];
275 struct cx8802_dev *dev= fe->dvb->priv;
276 struct i2c_msg msg =
277 { .addr = dev->core->pll_addr, .flags = 0,
278 .buf = pllbuf, .len = 4 };
279 int err;
280
281 dvb_pll_configure(dev->core->pll_desc, pllbuf,
282 params->frequency,
283 params->u.ofdm.bandwidth);
284
285 if (fe->ops.i2c_gate_ctrl)
286 fe->ops.i2c_gate_ctrl(fe, 1);
287 if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
288 printk(KERN_WARNING "cx88-dvb: %s error "
289 "(addr %02x <- %02x, err = %i)\n",
290 __FUNCTION__, pllbuf[0], pllbuf[1], err);
291 if (err < 0)
292 return err;
293 else
294 return -EREMOTEIO;
295 }
296
297 return 0;
298}
299
300static struct zl10353_config dvico_fusionhdtv_hybrid = { 292static struct zl10353_config dvico_fusionhdtv_hybrid = {
301 .demod_address = 0x0f, 293 .demod_address = 0x0f,
302 .no_tuner = 1, 294 .no_tuner = 1,
@@ -311,28 +303,12 @@ static struct cx22702_config connexant_refboard_config = {
311 .output_mode = CX22702_SERIAL_OUTPUT, 303 .output_mode = CX22702_SERIAL_OUTPUT,
312}; 304};
313 305
314static struct cx22702_config hauppauge_novat_config = { 306static struct cx22702_config hauppauge_hvr_config = {
315 .demod_address = 0x43,
316 .output_mode = CX22702_SERIAL_OUTPUT,
317};
318
319static struct cx22702_config hauppauge_hvr1100_config = {
320 .demod_address = 0x63, 307 .demod_address = 0x63,
321 .output_mode = CX22702_SERIAL_OUTPUT, 308 .output_mode = CX22702_SERIAL_OUTPUT,
322}; 309};
323 310
324static struct cx22702_config hauppauge_hvr1300_config = { 311static int or51132_set_ts_param(struct dvb_frontend* fe, int is_punctured)
325 .demod_address = 0x63,
326 .output_mode = CX22702_SERIAL_OUTPUT,
327};
328
329static struct cx22702_config hauppauge_hvr3000_config = {
330 .demod_address = 0x63,
331 .output_mode = CX22702_SERIAL_OUTPUT,
332};
333
334static int or51132_set_ts_param(struct dvb_frontend* fe,
335 int is_punctured)
336{ 312{
337 struct cx8802_dev *dev= fe->dvb->priv; 313 struct cx8802_dev *dev= fe->dvb->priv;
338 dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; 314 dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
@@ -344,50 +320,6 @@ static struct or51132_config pchdtv_hd3000 = {
344 .set_ts_params = or51132_set_ts_param, 320 .set_ts_params = or51132_set_ts_param,
345}; 321};
346 322
347static int lgdt3302_tuner_set_params(struct dvb_frontend* fe,
348 struct dvb_frontend_parameters* params)
349{
350 /* FIXME make this routine use the tuner-simple code.
351 * It could probably be shared with a number of ATSC
352 * frontends. Many share the same tuner with analog TV. */
353
354 struct cx8802_dev *dev= fe->dvb->priv;
355 struct cx88_core *core = dev->core;
356 u8 buf[4];
357 struct i2c_msg msg =
358 { .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
359 int err;
360
361 dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
362 dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
363 __FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
364
365 if (fe->ops.i2c_gate_ctrl)
366 fe->ops.i2c_gate_ctrl(fe, 1);
367 if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
368 printk(KERN_WARNING "cx88-dvb: %s error "
369 "(addr %02x <- %02x, err = %i)\n",
370 __FUNCTION__, buf[0], buf[1], err);
371 if (err < 0)
372 return err;
373 else
374 return -EREMOTEIO;
375 }
376 return 0;
377}
378
379static int lgdt3303_tuner_set_params(struct dvb_frontend* fe,
380 struct dvb_frontend_parameters* params)
381{
382 struct cx8802_dev *dev= fe->dvb->priv;
383 struct cx88_core *core = dev->core;
384
385 /* Put the analog decoder in standby to keep it quiet */
386 cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
387
388 return lg_h06xf_pll_set(fe, &core->i2c_adap, params);
389}
390
391static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index) 323static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
392{ 324{
393 struct cx8802_dev *dev= fe->dvb->priv; 325 struct cx8802_dev *dev= fe->dvb->priv;
@@ -432,8 +364,7 @@ static struct lgdt330x_config pchdtv_hd5500 = {
432 .set_ts_params = lgdt330x_set_ts_param, 364 .set_ts_params = lgdt330x_set_ts_param,
433}; 365};
434 366
435static int nxt200x_set_ts_param(struct dvb_frontend* fe, 367static int nxt200x_set_ts_param(struct dvb_frontend* fe, int is_punctured)
436 int is_punctured)
437{ 368{
438 struct cx8802_dev *dev= fe->dvb->priv; 369 struct cx8802_dev *dev= fe->dvb->priv;
439 dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00; 370 dev->ts_gen_cntrl = is_punctured ? 0x04 : 0x00;
@@ -469,11 +400,10 @@ static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe,
469 struct cx8802_dev *dev= fe->dvb->priv; 400 struct cx8802_dev *dev= fe->dvb->priv;
470 struct cx88_core *core = dev->core; 401 struct cx88_core *core = dev->core;
471 402
472 if (voltage == SEC_VOLTAGE_OFF) { 403 if (voltage == SEC_VOLTAGE_OFF)
473 cx_write(MO_GP0_IO, 0x000006fb); 404 cx_write(MO_GP0_IO, 0x000006fb);
474 } else { 405 else
475 cx_write(MO_GP0_IO, 0x000006f9); 406 cx_write(MO_GP0_IO, 0x000006f9);
476 }
477 407
478 if (core->prev_set_voltage) 408 if (core->prev_set_voltage)
479 return core->prev_set_voltage(fe, voltage); 409 return core->prev_set_voltage(fe, voltage);
@@ -522,7 +452,7 @@ static int dvb_register(struct cx8802_dev *dev)
522 switch (dev->core->board) { 452 switch (dev->core->board) {
523 case CX88_BOARD_HAUPPAUGE_DVB_T1: 453 case CX88_BOARD_HAUPPAUGE_DVB_T1:
524 dev->dvb.frontend = dvb_attach(cx22702_attach, 454 dev->dvb.frontend = dvb_attach(cx22702_attach,
525 &hauppauge_novat_config, 455 &connexant_refboard_config,
526 &dev->core->i2c_adap); 456 &dev->core->i2c_adap);
527 if (dev->dvb.frontend != NULL) { 457 if (dev->dvb.frontend != NULL) {
528 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 458 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
@@ -547,32 +477,11 @@ static int dvb_register(struct cx8802_dev *dev)
547 case CX88_BOARD_HAUPPAUGE_HVR1100: 477 case CX88_BOARD_HAUPPAUGE_HVR1100:
548 case CX88_BOARD_HAUPPAUGE_HVR1100LP: 478 case CX88_BOARD_HAUPPAUGE_HVR1100LP:
549 dev->dvb.frontend = dvb_attach(cx22702_attach, 479 dev->dvb.frontend = dvb_attach(cx22702_attach,
550 &hauppauge_hvr1100_config, 480 &hauppauge_hvr_config,
551 &dev->core->i2c_adap);
552 if (dev->dvb.frontend != NULL) {
553 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
554 &dev->core->i2c_adap,
555 &dvb_pll_fmd1216me);
556 }
557 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); 481 &dev->core->i2c_adap);
572 if (dev->dvb.frontend != NULL) { 482 if (dev->dvb.frontend != NULL) {
573 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 483 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
574 &dev->core->i2c_adap, 484 &dev->core->i2c_adap, &dvb_pll_fmd1216me);
575 &dvb_pll_fmd1216me);
576 } 485 }
577 break; 486 break;
578 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: 487 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
@@ -647,18 +556,17 @@ static int dvb_register(struct cx8802_dev *dev)
647#endif 556#endif
648 break; 557 break;
649 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: 558 case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
650 dev->core->pll_addr = 0x61;
651 dev->core->pll_desc = &dvb_pll_thomson_fe6600;
652 dev->dvb.frontend = dvb_attach(zl10353_attach, 559 dev->dvb.frontend = dvb_attach(zl10353_attach,
653 &dvico_fusionhdtv_hybrid, 560 &dvico_fusionhdtv_hybrid,
654 &dev->core->i2c_adap); 561 &dev->core->i2c_adap);
655 if (dev->dvb.frontend != NULL) { 562 if (dev->dvb.frontend != NULL) {
656 dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params; 563 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
564 &dev->core->i2c_adap,
565 &dvb_pll_thomson_fe6600);
657 } 566 }
658 break; 567 break;
659 case CX88_BOARD_PCHDTV_HD3000: 568 case CX88_BOARD_PCHDTV_HD3000:
660 dev->dvb.frontend = dvb_attach(or51132_attach, 569 dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000,
661 &pchdtv_hd3000,
662 &dev->core->i2c_adap); 570 &dev->core->i2c_adap);
663 if (dev->dvb.frontend != NULL) { 571 if (dev->dvb.frontend != NULL) {
664 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, 572 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
@@ -679,13 +587,13 @@ static int dvb_register(struct cx8802_dev *dev)
679 587
680 /* Select RF connector callback */ 588 /* Select RF connector callback */
681 fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; 589 fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set;
682 dev->core->pll_addr = 0x61;
683 dev->core->pll_desc = &dvb_pll_microtune_4042;
684 dev->dvb.frontend = dvb_attach(lgdt330x_attach, 590 dev->dvb.frontend = dvb_attach(lgdt330x_attach,
685 &fusionhdtv_3_gold, 591 &fusionhdtv_3_gold,
686 &dev->core->i2c_adap); 592 &dev->core->i2c_adap);
687 if (dev->dvb.frontend != NULL) { 593 if (dev->dvb.frontend != NULL) {
688 dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; 594 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
595 &dev->core->i2c_adap,
596 &dvb_pll_microtune_4042);
689 } 597 }
690 } 598 }
691 break; 599 break;
@@ -699,13 +607,13 @@ static int dvb_register(struct cx8802_dev *dev)
699 mdelay(100); 607 mdelay(100);
700 cx_set(MO_GP0_IO, 9); 608 cx_set(MO_GP0_IO, 9);
701 mdelay(200); 609 mdelay(200);
702 dev->core->pll_addr = 0x61;
703 dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
704 dev->dvb.frontend = dvb_attach(lgdt330x_attach, 610 dev->dvb.frontend = dvb_attach(lgdt330x_attach,
705 &fusionhdtv_3_gold, 611 &fusionhdtv_3_gold,
706 &dev->core->i2c_adap); 612 &dev->core->i2c_adap);
707 if (dev->dvb.frontend != NULL) { 613 if (dev->dvb.frontend != NULL) {
708 dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params; 614 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
615 &dev->core->i2c_adap,
616 &dvb_pll_thomson_dtt761x);
709 } 617 }
710 } 618 }
711 break; 619 break;
@@ -723,7 +631,8 @@ static int dvb_register(struct cx8802_dev *dev)
723 &fusionhdtv_5_gold, 631 &fusionhdtv_5_gold,
724 &dev->core->i2c_adap); 632 &dev->core->i2c_adap);
725 if (dev->dvb.frontend != NULL) { 633 if (dev->dvb.frontend != NULL) {
726 dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; 634 dvb_attach(lgh06xf_attach, dev->dvb.frontend,
635 &dev->core->i2c_adap);
727 } 636 }
728 } 637 }
729 break; 638 break;
@@ -741,7 +650,8 @@ static int dvb_register(struct cx8802_dev *dev)
741 &pchdtv_hd5500, 650 &pchdtv_hd5500,
742 &dev->core->i2c_adap); 651 &dev->core->i2c_adap);
743 if (dev->dvb.frontend != NULL) { 652 if (dev->dvb.frontend != NULL) {
744 dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params; 653 dvb_attach(lgh06xf_attach, dev->dvb.frontend,
654 &dev->core->i2c_adap);
745 } 655 }
746 } 656 }
747 break; 657 break;
@@ -782,6 +692,24 @@ static int dvb_register(struct cx8802_dev *dev)
782 dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; 692 dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage;
783 } 693 }
784 break; 694 break;
695 case CX88_BOARD_HAUPPAUGE_HVR1300:
696 dev->dvb.frontend = dvb_attach(cx22702_attach,
697 &hauppauge_hvr_config,
698 &dev->core->i2c_adap);
699 if (dev->dvb.frontend != NULL) {
700 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
701 &dev->core->i2c_adap, &dvb_pll_fmd1216me);
702 }
703 break;
704 case CX88_BOARD_HAUPPAUGE_HVR3000:
705 dev->dvb.frontend = dvb_attach(cx22702_attach,
706 &hauppauge_hvr_config,
707 &dev->core->i2c_adap);
708 if (dev->dvb.frontend != NULL) {
709 dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61,
710 &dev->core->i2c_adap, &dvb_pll_fmd1216me);
711 }
712 break;
785 default: 713 default:
786 printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", 714 printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n",
787 dev->core->name); 715 dev->core->name);
@@ -796,6 +724,8 @@ static int dvb_register(struct cx8802_dev *dev)
796 dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min; 724 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; 725 dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max;
798 } 726 }
727 /* Ensure all frontends negotiate bus access */
728 dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl;
799 729
800 /* Put the analog decoder in standby to keep it quiet */ 730 /* Put the analog decoder in standby to keep it quiet */
801 cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); 731 cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
@@ -806,37 +736,67 @@ static int dvb_register(struct cx8802_dev *dev)
806 736
807/* ----------------------------------------------------------- */ 737/* ----------------------------------------------------------- */
808 738
809static int __devinit dvb_probe(struct pci_dev *pci_dev, 739/* CX8802 MPEG -> mini driver - We have been given the hardware */
810 const struct pci_device_id *pci_id) 740static int cx8802_dvb_advise_acquire(struct cx8802_driver *drv)
811{ 741{
812 struct cx8802_dev *dev; 742 struct cx88_core *core = drv->core;
813 struct cx88_core *core; 743 int err = 0;
744 dprintk( 1, "%s\n", __FUNCTION__);
745
746 switch (core->board) {
747 case CX88_BOARD_HAUPPAUGE_HVR1300:
748 /* We arrive here with either the cx23416 or the cx22702
749 * on the bus. Take the bus from the cx23416 and enable the
750 * cx22702 demod
751 */
752 cx_set(MO_GP0_IO, 0x00000080); /* cx22702 out of reset and enable */
753 cx_clear(MO_GP0_IO, 0x00000004);
754 udelay(1000);
755 break;
756 default:
757 err = -ENODEV;
758 }
759 return err;
760}
761
762/* CX8802 MPEG -> mini driver - We no longer have the hardware */
763static int cx8802_dvb_advise_release(struct cx8802_driver *drv)
764{
765 struct cx88_core *core = drv->core;
766 int err = 0;
767 dprintk( 1, "%s\n", __FUNCTION__);
768
769 switch (core->board) {
770 case CX88_BOARD_HAUPPAUGE_HVR1300:
771 /* Do Nothing, leave the cx22702 on the bus. */
772 break;
773 default:
774 err = -ENODEV;
775 }
776 return err;
777}
778
779static int cx8802_dvb_probe(struct cx8802_driver *drv)
780{
781 struct cx88_core *core = drv->core;
782 struct cx8802_dev *dev = drv->core->dvbdev;
814 int err; 783 int err;
815 784
816 /* general setup */ 785 dprintk( 1, "%s\n", __FUNCTION__);
817 core = cx88_core_get(pci_dev); 786 dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
818 if (NULL == core) 787 core->board,
819 return -EINVAL; 788 core->name,
789 core->pci_bus,
790 core->pci_slot);
820 791
821 err = -ENODEV; 792 err = -ENODEV;
822 if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB)) 793 if (!(cx88_boards[core->board].mpeg & CX88_MPEG_DVB))
823 goto fail_core; 794 goto fail_core;
824 795
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 796#ifdef HAVE_VP3054_I2C
837 err = vp3054_i2c_probe(dev); 797 err = vp3054_i2c_probe(dev);
838 if (0 != err) 798 if (0 != err)
839 goto fail_free; 799 goto fail_core;
840#endif 800#endif
841 801
842 /* dvb stuff */ 802 /* dvb stuff */
@@ -848,28 +808,16 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev,
848 sizeof(struct cx88_buffer), 808 sizeof(struct cx88_buffer),
849 dev); 809 dev);
850 err = dvb_register(dev); 810 err = dvb_register(dev);
851 if (0 != err) 811 if (err != 0)
852 goto fail_fini; 812 printk("%s dvb_register failed err = %d\n", __FUNCTION__, err);
853 813
854 /* Maintain a reference to cx88-video can query the 8802 device. */
855 core->dvbdev = dev;
856 return 0;
857
858 fail_fini:
859 cx8802_fini_common(dev);
860 fail_free:
861 kfree(dev);
862 fail_core: 814 fail_core:
863 cx88_core_put(core,pci_dev);
864 return err; 815 return err;
865} 816}
866 817
867static void __devexit dvb_remove(struct pci_dev *pci_dev) 818static int cx8802_dvb_remove(struct cx8802_driver *drv)
868{ 819{
869 struct cx8802_dev *dev = pci_get_drvdata(pci_dev); 820 struct cx8802_dev *dev = drv->core->dvbdev;
870
871 /* Destroy any 8802 reference. */
872 dev->core->dvbdev = NULL;
873 821
874 /* dvb */ 822 /* dvb */
875 videobuf_dvb_unregister(&dev->dvb); 823 videobuf_dvb_unregister(&dev->dvb);
@@ -878,33 +826,16 @@ static void __devexit dvb_remove(struct pci_dev *pci_dev)
878 vp3054_i2c_remove(dev); 826 vp3054_i2c_remove(dev);
879#endif 827#endif
880 828
881 /* common */ 829 return 0;
882 cx8802_fini_common(dev);
883 cx88_core_put(dev->core,dev->pci);
884 kfree(dev);
885} 830}
886 831
887static struct pci_device_id cx8802_pci_tbl[] = { 832static struct cx8802_driver cx8802_dvb_driver = {
888 { 833 .type_id = CX88_MPEG_DVB,
889 .vendor = 0x14f1, 834 .hw_access = CX8802_DRVCTL_SHARED,
890 .device = 0x8802, 835 .probe = cx8802_dvb_probe,
891 .subvendor = PCI_ANY_ID, 836 .remove = cx8802_dvb_remove,
892 .subdevice = PCI_ANY_ID, 837 .advise_acquire = cx8802_dvb_advise_acquire,
893 },{ 838 .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}; 839};
909 840
910static int dvb_init(void) 841static int dvb_init(void)
@@ -917,12 +848,12 @@ static int dvb_init(void)
917 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", 848 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
918 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); 849 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
919#endif 850#endif
920 return pci_register_driver(&dvb_pci_driver); 851 return cx8802_register_driver(&cx8802_dvb_driver);
921} 852}
922 853
923static void dvb_fini(void) 854static void dvb_fini(void)
924{ 855{
925 pci_unregister_driver(&dvb_pci_driver); 856 cx8802_unregister_driver(&cx8802_dvb_driver);
926} 857}
927 858
928module_init(dvb_init); 859module_init(dvb_init);
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index e60a0a52e4b2..8136673fe9e8 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -155,6 +155,35 @@ static void cx88_ir_work(struct work_struct *work)
155 mod_timer(&ir->timer, timeout); 155 mod_timer(&ir->timer, timeout);
156} 156}
157 157
158static void cx88_ir_start(struct cx88_core *core, struct cx88_IR *ir)
159{
160 if (ir->polling) {
161 INIT_WORK(&ir->work, cx88_ir_work);
162 init_timer(&ir->timer);
163 ir->timer.function = ir_timer;
164 ir->timer.data = (unsigned long)ir;
165 schedule_work(&ir->work);
166 }
167 if (ir->sampling) {
168 core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
169 cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */
170 cx_write(MO_DDSCFG_IO, 0x5); /* enable */
171 }
172}
173
174static void cx88_ir_stop(struct cx88_core *core, struct cx88_IR *ir)
175{
176 if (ir->sampling) {
177 cx_write(MO_DDSCFG_IO, 0x0);
178 core->pci_irqmask &= ~(1 << 18);
179 }
180
181 if (ir->polling) {
182 del_timer_sync(&ir->timer);
183 flush_scheduled_work();
184 }
185}
186
158/* ---------------------------------------------------------------------- */ 187/* ---------------------------------------------------------------------- */
159 188
160int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) 189int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
@@ -163,14 +192,12 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
163 struct input_dev *input_dev; 192 struct input_dev *input_dev;
164 IR_KEYTAB_TYPE *ir_codes = NULL; 193 IR_KEYTAB_TYPE *ir_codes = NULL;
165 int ir_type = IR_TYPE_OTHER; 194 int ir_type = IR_TYPE_OTHER;
195 int err = -ENOMEM;
166 196
167 ir = kzalloc(sizeof(*ir), GFP_KERNEL); 197 ir = kzalloc(sizeof(*ir), GFP_KERNEL);
168 input_dev = input_allocate_device(); 198 input_dev = input_allocate_device();
169 if (!ir || !input_dev) { 199 if (!ir || !input_dev)
170 kfree(ir); 200 goto err_out_free;
171 input_free_device(input_dev);
172 return -ENOMEM;
173 }
174 201
175 ir->input = input_dev; 202 ir->input = input_dev;
176 203
@@ -280,9 +307,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
280 } 307 }
281 308
282 if (NULL == ir_codes) { 309 if (NULL == ir_codes) {
283 kfree(ir); 310 err = -ENODEV;
284 input_free_device(input_dev); 311 goto err_out_free;
285 return -ENODEV;
286 } 312 }
287 313
288 /* init input device */ 314 /* init input device */
@@ -307,23 +333,22 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
307 ir->core = core; 333 ir->core = core;
308 core->ir = ir; 334 core->ir = ir;
309 335
310 if (ir->polling) { 336 cx88_ir_start(core, ir);
311 INIT_WORK(&ir->work, cx88_ir_work);
312 init_timer(&ir->timer);
313 ir->timer.function = ir_timer;
314 ir->timer.data = (unsigned long)ir;
315 schedule_work(&ir->work);
316 }
317 if (ir->sampling) {
318 core->pci_irqmask |= (1 << 18); /* IR_SMP_INT */
319 cx_write(MO_DDS_IO, 0xa80a80); /* 4 kHz sample rate */
320 cx_write(MO_DDSCFG_IO, 0x5); /* enable */
321 }
322 337
323 /* all done */ 338 /* all done */
324 input_register_device(ir->input); 339 err = input_register_device(ir->input);
340 if (err)
341 goto err_out_stop;
325 342
326 return 0; 343 return 0;
344
345 err_out_stop:
346 cx88_ir_stop(core, ir);
347 core->ir = NULL;
348 err_out_free:
349 input_free_device(input_dev);
350 kfree(ir);
351 return err;
327} 352}
328 353
329int cx88_ir_fini(struct cx88_core *core) 354int cx88_ir_fini(struct cx88_core *core)
@@ -334,15 +359,7 @@ int cx88_ir_fini(struct cx88_core *core)
334 if (NULL == ir) 359 if (NULL == ir)
335 return 0; 360 return 0;
336 361
337 if (ir->sampling) { 362 cx88_ir_stop(core, ir);
338 cx_write(MO_DDSCFG_IO, 0x0);
339 core->pci_irqmask &= ~(1 << 18);
340 }
341 if (ir->polling) {
342 del_timer(&ir->timer);
343 flush_scheduled_work();
344 }
345
346 input_unregister_device(ir->input); 363 input_unregister_device(ir->input);
347 kfree(ir); 364 kfree(ir);
348 365
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 6b23a4e6f66d..1fe1a833c7c7 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,315 @@ 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 if (h != dev)
576 continue;
577
578 list_for_each(list2, &h->drvlist.devlist) {
579 d = list_entry(list2, struct cx8802_driver, devlist);
580
581 /* only unregister the correct driver type */
582 if (d->type_id == btype) {
583 return d;
584 }
585 }
586 }
587
588 return NULL;
589}
590
591/* Driver asked for hardware access. */
592int cx8802_request_acquire(struct cx8802_driver *drv)
593{
594 struct cx88_core *core = drv->core;
595
596 /* Fail a request for hardware if the device is busy. */
597 if (core->active_type_id != CX88_BOARD_NONE)
598 return -EBUSY;
599
600 if (drv->advise_acquire)
601 {
602 core->active_type_id = drv->type_id;
603 drv->advise_acquire(drv);
604
605 mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
606 }
607
608 return 0;
609}
610
611/* Driver asked to release hardware. */
612int cx8802_request_release(struct cx8802_driver *drv)
613{
614 struct cx88_core *core = drv->core;
615
616 if (drv->advise_release)
617 {
618 drv->advise_release(drv);
619 core->active_type_id = CX88_BOARD_NONE;
620 mpeg_dbg(1,"%s() Post release GPIO=%x\n", __FUNCTION__, cx_read(MO_GP0_IO));
621 }
622
623 return 0;
624}
625
626static int cx8802_check_driver(struct cx8802_driver *drv)
627{
628 if (drv == NULL)
629 return -ENODEV;
630
631 if ((drv->type_id != CX88_MPEG_DVB) &&
632 (drv->type_id != CX88_MPEG_BLACKBIRD))
633 return -EINVAL;
634
635 if ((drv->hw_access != CX8802_DRVCTL_SHARED) &&
636 (drv->hw_access != CX8802_DRVCTL_EXCLUSIVE))
637 return -EINVAL;
638
639 if ((drv->probe == NULL) ||
640 (drv->remove == NULL) ||
641 (drv->advise_acquire == NULL) ||
642 (drv->advise_release == NULL))
643 return -EINVAL;
644
645 return 0;
646}
647
648int cx8802_register_driver(struct cx8802_driver *drv)
649{
650 struct cx8802_dev *h;
651 struct cx8802_driver *driver;
652 struct list_head *list;
653 int err = 0, i = 0;
654
655 printk(KERN_INFO "%s() ->registering driver type=%s access=%s\n", __FUNCTION__ ,
656 drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird",
657 drv->hw_access == CX8802_DRVCTL_SHARED ? "shared" : "exclusive");
658
659 if ((err = cx8802_check_driver(drv)) != 0) {
660 printk(KERN_INFO "%s() cx8802_driver is invalid\n", __FUNCTION__ );
661 return err;
662 }
663
664 list_for_each(list,&cx8802_devlist) {
665 h = list_entry(list, struct cx8802_dev, devlist);
666
667 printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
668 h->core->name,h->pci->subsystem_vendor,
669 h->pci->subsystem_device,cx88_boards[h->core->board].name,
670 h->core->board);
671
672 /* Bring up a new struct for each driver instance */
673 driver = kzalloc(sizeof(*drv),GFP_KERNEL);
674 if (driver == NULL)
675 return -ENOMEM;
676
677 /* Snapshot of the driver registration data */
678 drv->core = h->core;
679 drv->suspend = cx8802_suspend_common;
680 drv->resume = cx8802_resume_common;
681 drv->request_acquire = cx8802_request_acquire;
682 drv->request_release = cx8802_request_release;
683 memcpy(driver, drv, sizeof(*driver));
684
685 err = drv->probe(driver);
686 if (err == 0) {
687 i++;
688 mutex_lock(&drv->core->lock);
689 list_add_tail(&driver->devlist,&h->drvlist.devlist);
690 mutex_unlock(&drv->core->lock);
691 } else {
692 printk(KERN_ERR "%s() ->probe failed err = %d\n", __FUNCTION__, err);
693 }
694
695 }
696 if (i == 0)
697 err = -ENODEV;
698 else
699 err = 0;
700
701 return err;
702}
703
704int cx8802_unregister_driver(struct cx8802_driver *drv)
705{
706 struct cx8802_dev *h;
707 struct cx8802_driver *d;
708 struct list_head *list;
709 struct list_head *list2, *q;
710 int err = 0, i = 0;
711
712 printk(KERN_INFO "%s() ->unregistering driver type=%s\n", __FUNCTION__ ,
713 drv->type_id == CX88_MPEG_DVB ? "dvb" : "blackbird");
714
715 list_for_each(list,&cx8802_devlist) {
716 i++;
717 h = list_entry(list, struct cx8802_dev, devlist);
718
719 printk(KERN_INFO "CORE %s: subsystem: %04x:%04x, board: %s [card=%d]\n",
720 h->core->name,h->pci->subsystem_vendor,
721 h->pci->subsystem_device,cx88_boards[h->core->board].name,
722 h->core->board);
723
724 list_for_each_safe(list2, q, &h->drvlist.devlist) {
725 d = list_entry(list2, struct cx8802_driver, devlist);
726
727 /* only unregister the correct driver type */
728 if (d->type_id != drv->type_id)
729 continue;
730
731 err = d->remove(d);
732 if (err == 0) {
733 mutex_lock(&drv->core->lock);
734 list_del(list2);
735 mutex_unlock(&drv->core->lock);
736 } else
737 printk(KERN_ERR "%s() ->remove failed err = %d\n", __FUNCTION__, err);
738
739 }
740
741 }
742
743 return err;
744}
745
545/* ----------------------------------------------------------- */ 746/* ----------------------------------------------------------- */
747static int __devinit cx8802_probe(struct pci_dev *pci_dev,
748 const struct pci_device_id *pci_id)
749{
750 struct cx8802_dev *dev;
751 struct cx88_core *core;
752 int err;
753
754 /* general setup */
755 core = cx88_core_get(pci_dev);
756 if (NULL == core)
757 return -EINVAL;
546 758
759 printk("%s/2: cx2388x 8802 Driver Manager\n", core->name);
760
761 err = -ENODEV;
762 if (!cx88_boards[core->board].mpeg)
763 goto fail_core;
764
765 err = -ENOMEM;
766 dev = kzalloc(sizeof(*dev),GFP_KERNEL);
767 if (NULL == dev)
768 goto fail_core;
769 dev->pci = pci_dev;
770 dev->core = core;
771
772 err = cx8802_init_common(dev);
773 if (err != 0)
774 goto fail_free;
775
776 INIT_LIST_HEAD(&dev->drvlist.devlist);
777 list_add_tail(&dev->devlist,&cx8802_devlist);
778
779 /* Maintain a reference so cx88-video can query the 8802 device. */
780 core->dvbdev = dev;
781 return 0;
782
783 fail_free:
784 kfree(dev);
785 fail_core:
786 cx88_core_put(core,pci_dev);
787 return err;
788}
789
790static void __devexit cx8802_remove(struct pci_dev *pci_dev)
791{
792 struct cx8802_dev *dev;
793 struct cx8802_driver *h;
794 struct list_head *list;
795
796 dev = pci_get_drvdata(pci_dev);
797
798 dprintk( 1, "%s\n", __FUNCTION__);
799
800 list_for_each(list,&dev->drvlist.devlist) {
801 h = list_entry(list, struct cx8802_driver, devlist);
802 dprintk( 1, " ->driver\n");
803 if (h->remove == NULL) {
804 printk(KERN_ERR "%s .. skipping driver, no probe function\n", __FUNCTION__);
805 continue;
806 }
807 printk(KERN_INFO "%s .. Removing driver type %d\n", __FUNCTION__, h->type_id);
808 cx8802_unregister_driver(h);
809 list_del(&dev->drvlist.devlist);
810 }
811
812 /* Destroy any 8802 reference. */
813 dev->core->dvbdev = NULL;
814
815 /* common */
816 cx8802_fini_common(dev);
817 cx88_core_put(dev->core,dev->pci);
818 kfree(dev);
819}
820
821static struct pci_device_id cx8802_pci_tbl[] = {
822 {
823 .vendor = 0x14f1,
824 .device = 0x8802,
825 .subvendor = PCI_ANY_ID,
826 .subdevice = PCI_ANY_ID,
827 },{
828 /* --- end of list --- */
829 }
830};
831MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl);
832
833static struct pci_driver cx8802_pci_driver = {
834 .name = "cx88-mpeg driver manager",
835 .id_table = cx8802_pci_tbl,
836 .probe = cx8802_probe,
837 .remove = __devexit_p(cx8802_remove),
838};
839
840static int cx8802_init(void)
841{
842 printk(KERN_INFO "cx2388x cx88-mpeg Driver Manager version %d.%d.%d loaded\n",
843 (CX88_VERSION_CODE >> 16) & 0xff,
844 (CX88_VERSION_CODE >> 8) & 0xff,
845 CX88_VERSION_CODE & 0xff);
846#ifdef SNAPSHOT
847 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
848 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
849#endif
850 return pci_register_driver(&cx8802_pci_driver);
851}
852
853static void cx8802_fini(void)
854{
855 pci_unregister_driver(&cx8802_pci_driver);
856}
857
858module_init(cx8802_init);
859module_exit(cx8802_fini);
547EXPORT_SYMBOL(cx8802_buf_prepare); 860EXPORT_SYMBOL(cx8802_buf_prepare);
548EXPORT_SYMBOL(cx8802_buf_queue); 861EXPORT_SYMBOL(cx8802_buf_queue);
549EXPORT_SYMBOL(cx8802_cancel_buffers); 862EXPORT_SYMBOL(cx8802_cancel_buffers);
@@ -551,9 +864,10 @@ EXPORT_SYMBOL(cx8802_cancel_buffers);
551EXPORT_SYMBOL(cx8802_init_common); 864EXPORT_SYMBOL(cx8802_init_common);
552EXPORT_SYMBOL(cx8802_fini_common); 865EXPORT_SYMBOL(cx8802_fini_common);
553 866
554EXPORT_SYMBOL(cx8802_suspend_common); 867EXPORT_SYMBOL(cx8802_register_driver);
555EXPORT_SYMBOL(cx8802_resume_common); 868EXPORT_SYMBOL(cx8802_unregister_driver);
556 869EXPORT_SYMBOL(cx8802_get_device);
870EXPORT_SYMBOL(cx8802_get_driver);
557/* ----------------------------------------------------------- */ 871/* ----------------------------------------------------------- */
558/* 872/*
559 * Local variables: 873 * Local variables:
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 58ba9f773524..3482e0114d43 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -143,19 +143,6 @@ static void set_audio_finish(struct cx88_core *core, u32 ctl)
143 cx88_start_audio_dma(core); 143 cx88_start_audio_dma(core);
144 144
145 if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) { 145 if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
146 /* sets sound input from external adc */
147 switch (core->board) {
148 case CX88_BOARD_HAUPPAUGE_ROSLYN:
149 case CX88_BOARD_KWORLD_MCE200_DELUXE:
150 case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT:
151 case CX88_BOARD_PIXELVIEW_PLAYTV_P7000:
152 case CX88_BOARD_ASUS_PVR_416:
153 cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
154 break;
155 default:
156 cx_set(AUD_CTL, EN_I2SIN_ENABLE);
157 }
158
159 cx_write(AUD_I2SINPUTCNTL, 4); 146 cx_write(AUD_I2SINPUTCNTL, 4);
160 cx_write(AUD_BAUDRATE, 1); 147 cx_write(AUD_BAUDRATE, 1);
161 /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */ 148 /* 'pass-thru mode': this enables the i2s output to the mpeg encoder */
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 90e298d074d1..8613378428fd 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -454,6 +454,14 @@ static int video_mux(struct cx88_core *core, unsigned int input)
454 cx_clear(MO_FILTER_ODD, 0x00002020); 454 cx_clear(MO_FILTER_ODD, 0x00002020);
455 break; 455 break;
456 } 456 }
457
458 if (cx88_boards[core->board].mpeg & CX88_MPEG_BLACKBIRD) {
459 /* sets sound input from external adc */
460 if (INPUT(input)->extadc)
461 cx_set(AUD_CTL, EN_I2SIN_ENABLE);
462 else
463 cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
464 }
457 return 0; 465 return 0;
458} 466}
459 467
@@ -1490,6 +1498,30 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
1490 mutex_unlock(&core->lock); 1498 mutex_unlock(&core->lock);
1491 return 0; 1499 return 0;
1492 } 1500 }
1501#ifdef CONFIG_VIDEO_ADV_DEBUG
1502 /* ioctls to allow direct acces to the cx2388x registers */
1503 case VIDIOC_INT_G_REGISTER:
1504 {
1505 struct v4l2_register *reg = arg;
1506
1507 if (reg->i2c_id != 0)
1508 return -EINVAL;
1509 /* cx2388x has a 24-bit register space */
1510 reg->val = cx_read(reg->reg&0xffffff);
1511 return 0;
1512 }
1513 case VIDIOC_INT_S_REGISTER:
1514 {
1515 struct v4l2_register *reg = arg;
1516
1517 if (reg->i2c_id != 0)
1518 return -EINVAL;
1519 if (!capable(CAP_SYS_ADMIN))
1520 return -EPERM;
1521 cx_write(reg->reg&0xffffff, reg->val);
1522 return 0;
1523 }
1524#endif
1493 1525
1494 default: 1526 default:
1495 return v4l_compat_translate_ioctl(inode,file,cmd,arg, 1527 return v4l_compat_translate_ioctl(inode,file,cmd,arg,
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 3bc91aad4fe5..7054e941f1d7 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
@@ -220,6 +225,7 @@ struct cx88_input {
220 enum cx88_itype type; 225 enum cx88_itype type;
221 unsigned int vmux; 226 unsigned int vmux;
222 u32 gpio0, gpio1, gpio2, gpio3; 227 u32 gpio0, gpio1, gpio2, gpio3;
228 unsigned int extadc:1;
223}; 229};
224 230
225struct cx88_board { 231struct cx88_board {
@@ -330,6 +336,7 @@ struct cx88_core {
330 336
331 /* cx88-video needs to access cx8802 for hybrid tuner pll access. */ 337 /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
332 struct cx8802_dev *dvbdev; 338 struct cx8802_dev *dvbdev;
339 enum cx88_board_type active_type_id;
333}; 340};
334 341
335struct cx8800_dev; 342struct cx8800_dev;
@@ -405,6 +412,31 @@ struct cx8802_suspend_state {
405 int disabled; 412 int disabled;
406}; 413};
407 414
415struct cx8802_driver {
416 struct cx88_core *core;
417 struct list_head devlist;
418
419 /* Type of driver and access required */
420 enum cx88_board_type type_id;
421 enum cx8802_board_access hw_access;
422
423 /* MPEG 8802 internal only */
424 int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
425 int (*resume)(struct pci_dev *pci_dev);
426
427 /* MPEG 8802 -> mini driver - Driver probe and configuration */
428 int (*probe)(struct cx8802_driver *drv);
429 int (*remove)(struct cx8802_driver *drv);
430
431 /* MPEG 8802 -> mini driver - Access for hardware control */
432 int (*advise_acquire)(struct cx8802_driver *drv);
433 int (*advise_release)(struct cx8802_driver *drv);
434
435 /* MPEG 8802 <- mini driver - Access for hardware control */
436 int (*request_acquire)(struct cx8802_driver *drv);
437 int (*request_release)(struct cx8802_driver *drv);
438};
439
408struct cx8802_dev { 440struct cx8802_dev {
409 struct cx88_core *core; 441 struct cx88_core *core;
410 spinlock_t slock; 442 spinlock_t slock;
@@ -439,6 +471,9 @@ struct cx8802_dev {
439 471
440 /* mpeg params */ 472 /* mpeg params */
441 struct cx2341x_mpeg_params params; 473 struct cx2341x_mpeg_params params;
474
475 /* List of attached drivers */
476 struct cx8802_driver drvlist;
442}; 477};
443 478
444/* ----------------------------------------------------------- */ 479/* ----------------------------------------------------------- */
@@ -571,6 +606,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); 606void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
572int cx88_audio_thread(void *data); 607int cx88_audio_thread(void *data);
573 608
609int cx8802_register_driver(struct cx8802_driver *drv);
610int cx8802_unregister_driver(struct cx8802_driver *drv);
611struct cx8802_dev * cx8802_get_device(struct inode *inode);
612struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
613
574/* ----------------------------------------------------------- */ 614/* ----------------------------------------------------------- */
575/* cx88-input.c */ 615/* cx88-input.c */
576 616
@@ -600,6 +640,13 @@ extern int cx88_do_ioctl(struct inode *inode, struct file *file, int radio,
600extern const u32 cx88_user_ctrls[]; 640extern const u32 cx88_user_ctrls[];
601extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl); 641extern int cx8800_ctrl_query(struct v4l2_queryctrl *qctrl);
602 642
643/* ----------------------------------------------------------- */
644/* cx88-blackbird.c */
645/* used by cx88-ivtv ioctl emulation layer */
646extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
647 unsigned int cmd, void *arg);
648extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
649
603/* 650/*
604 * Local variables: 651 * Local variables:
605 * c-basic-offset: 8 652 * c-basic-offset: 8