diff options
Diffstat (limited to 'drivers/media/video/cx88/cx88-blackbird.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 179 |
1 files changed, 110 insertions, 69 deletions
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 | ||
53 | static 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 | ||
921 | int (*cx88_ioctl_hook)(struct inode *inode, struct file *file, | ||
922 | unsigned int cmd, void *arg); | ||
923 | unsigned int (*cx88_ioctl_translator)(unsigned int cmd); | ||
924 | |||
922 | static unsigned int mpeg_translate_ioctl(unsigned int cmd) | 925 | static 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) | |||
927 | static int mpeg_ioctl(struct inode *inode, struct file *file, | 930 | static 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 | ||
934 | static int mpeg_open(struct inode *inode, struct file *file) | 937 | static 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) | |||
974 | static int mpeg_release(struct inode *inode, struct file *file) | 993 | static 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 */ | ||
1078 | static 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 */ | ||
1100 | static 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 | |||
1046 | static void blackbird_unregister_video(struct cx8802_dev *dev) | 1115 | static 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 | ||
1076 | static int __devinit blackbird_probe(struct pci_dev *pci_dev, | 1145 | static 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 | ||
1132 | static void __devexit blackbird_remove(struct pci_dev *pci_dev) | 1188 | static 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 | ||
1146 | static struct pci_device_id cx8802_pci_tbl[] = { | 1196 | static 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 | }; | ||
1156 | MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); | ||
1157 | |||
1158 | static 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 | ||
1169 | static int blackbird_init(void) | 1205 | static 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 | ||
1182 | static void blackbird_fini(void) | 1220 | static void blackbird_fini(void) |
1183 | { | 1221 | { |
1184 | pci_unregister_driver(&blackbird_pci_driver); | 1222 | cx8802_unregister_driver(&cx8802_blackbird_driver); |
1185 | } | 1223 | } |
1186 | 1224 | ||
1187 | module_init(blackbird_init); | 1225 | module_init(blackbird_init); |
1188 | module_exit(blackbird_fini); | 1226 | module_exit(blackbird_fini); |
1189 | 1227 | ||
1228 | EXPORT_SYMBOL(cx88_ioctl_hook); | ||
1229 | EXPORT_SYMBOL(cx88_ioctl_translator); | ||
1230 | |||
1190 | /* ----------------------------------------------------------- */ | 1231 | /* ----------------------------------------------------------- */ |
1191 | /* | 1232 | /* |
1192 | * Local variables: | 1233 | * Local variables: |