diff options
Diffstat (limited to 'drivers/media/video/cx88/cx88-blackbird.c')
-rw-r--r-- | drivers/media/video/cx88/cx88-blackbird.c | 178 |
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 | ||
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,48 @@ 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 | 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) | |||
974 | static int mpeg_release(struct inode *inode, struct file *file) | 992 | static 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 */ | ||
1077 | static 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 */ | ||
1099 | static 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 | |||
1046 | static void blackbird_unregister_video(struct cx8802_dev *dev) | 1114 | static 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 | ||
1076 | static int __devinit blackbird_probe(struct pci_dev *pci_dev, | 1144 | static 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 | ||
1132 | static void __devexit blackbird_remove(struct pci_dev *pci_dev) | 1187 | static 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 | ||
1146 | static struct pci_device_id cx8802_pci_tbl[] = { | 1195 | static 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 | }; | ||
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 | }; | 1202 | }; |
1168 | 1203 | ||
1169 | static int blackbird_init(void) | 1204 | static 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 | ||
1182 | static void blackbird_fini(void) | 1219 | static void blackbird_fini(void) |
1183 | { | 1220 | { |
1184 | pci_unregister_driver(&blackbird_pci_driver); | 1221 | cx8802_unregister_driver(&cx8802_blackbird_driver); |
1185 | } | 1222 | } |
1186 | 1223 | ||
1187 | module_init(blackbird_init); | 1224 | module_init(blackbird_init); |
1188 | module_exit(blackbird_fini); | 1225 | module_exit(blackbird_fini); |
1189 | 1226 | ||
1227 | EXPORT_SYMBOL(cx88_ioctl_hook); | ||
1228 | EXPORT_SYMBOL(cx88_ioctl_translator); | ||
1229 | |||
1190 | /* ----------------------------------------------------------- */ | 1230 | /* ----------------------------------------------------------- */ |
1191 | /* | 1231 | /* |
1192 | * Local variables: | 1232 | * Local variables: |