aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88/cx88-blackbird.c
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 /drivers/media/video/cx88/cx88-blackbird.c
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>
Diffstat (limited to 'drivers/media/video/cx88/cx88-blackbird.c')
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c178
1 files changed, 109 insertions, 69 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: