diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-15 15:49:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-15 15:49:56 -0500 |
commit | 122804ecb59493fbb4d31b3ba9ac59faaf45276f (patch) | |
tree | cff4d8a158c412e4a8d3abc8d91bb0eb52b01c9a /drivers/media/video/cx231xx | |
parent | 16008d641670571ff4cd750b416c7caf2d89f467 (diff) | |
parent | 126400033940afb658123517a2e80eb68259fbd7 (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (655 commits)
[media] revert patch: HDIC HD29L2 DMB-TH USB2.0 reference design driver
mb86a20s: Add a few more register settings at the init seq
mb86a20s: Group registers into the same line
[media] [PATCH] don't reset the delivery system on DTV_CLEAR
[media] [BUG] it913x-fe fix typo error making SNR levels unstable
[media] cx23885: Query the CX25840 during enum_input for status
[media] cx25840: Add support for g_input_status
[media] rc-videomate-m1f.c Rename to match remote controler name
[media] drivers: media: au0828: Fix dependency for VIDEO_AU0828
[media] convert drivers/media/* to use module_platform_driver()
[media] drivers: video: cx231xx: Fix dependency for VIDEO_CX231XX_DVB
[media] Exynos4 JPEG codec v4l2 driver
[media] doc: v4l: selection: choose pixels as units for selection rectangles
[media] v4l: s5p-tv: mixer: fix setup of VP scaling
[media] v4l: s5p-tv: mixer: add support for selection API
[media] v4l: emulate old crop API using extended crop/compose API
[media] doc: v4l: add documentation for selection API
[media] doc: v4l: add binary images for selection API
[media] v4l: add support for selection api
[media] hd29l2: fix review findings
...
Diffstat (limited to 'drivers/media/video/cx231xx')
-rw-r--r-- | drivers/media/video/cx231xx/Kconfig | 6 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-audio.c | 24 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-cards.c | 86 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-core.c | 7 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-dvb.c | 4 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-input.c | 11 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-vbi.c | 4 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx-video.c | 14 | ||||
-rw-r--r-- | drivers/media/video/cx231xx/cx231xx.h | 2 |
9 files changed, 88 insertions, 70 deletions
diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index ae85a7a7bd73..446f692aabb7 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig | |||
@@ -40,10 +40,10 @@ config VIDEO_CX231XX_ALSA | |||
40 | 40 | ||
41 | config VIDEO_CX231XX_DVB | 41 | config VIDEO_CX231XX_DVB |
42 | tristate "DVB/ATSC Support for Cx231xx based TV cards" | 42 | tristate "DVB/ATSC Support for Cx231xx based TV cards" |
43 | depends on VIDEO_CX231XX && DVB_CORE | 43 | depends on VIDEO_CX231XX && DVB_CORE && DVB_CAPTURE_DRIVERS |
44 | select VIDEOBUF_DVB | 44 | select VIDEOBUF_DVB |
45 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE | 45 | select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE |
46 | select MEDIA_TUNER_NXP18271 if !DVB_FE_CUSTOMISE | 46 | select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE |
47 | select DVB_MB86A20S if !DVB_FE_CUSTOMISE | 47 | select DVB_MB86A20S if !DVB_FE_CUSTOMISE |
48 | 48 | ||
49 | ---help--- | 49 | ---help--- |
diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c index 30d13c15739a..a2c2b7d343ec 100644 --- a/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/drivers/media/video/cx231xx/cx231xx-audio.c | |||
@@ -111,6 +111,9 @@ static void cx231xx_audio_isocirq(struct urb *urb) | |||
111 | struct snd_pcm_substream *substream; | 111 | struct snd_pcm_substream *substream; |
112 | struct snd_pcm_runtime *runtime; | 112 | struct snd_pcm_runtime *runtime; |
113 | 113 | ||
114 | if (dev->state & DEV_DISCONNECTED) | ||
115 | return; | ||
116 | |||
114 | switch (urb->status) { | 117 | switch (urb->status) { |
115 | case 0: /* success */ | 118 | case 0: /* success */ |
116 | case -ETIMEDOUT: /* NAK */ | 119 | case -ETIMEDOUT: /* NAK */ |
@@ -196,6 +199,9 @@ static void cx231xx_audio_bulkirq(struct urb *urb) | |||
196 | struct snd_pcm_substream *substream; | 199 | struct snd_pcm_substream *substream; |
197 | struct snd_pcm_runtime *runtime; | 200 | struct snd_pcm_runtime *runtime; |
198 | 201 | ||
202 | if (dev->state & DEV_DISCONNECTED) | ||
203 | return; | ||
204 | |||
199 | switch (urb->status) { | 205 | switch (urb->status) { |
200 | case 0: /* success */ | 206 | case 0: /* success */ |
201 | case -ETIMEDOUT: /* NAK */ | 207 | case -ETIMEDOUT: /* NAK */ |
@@ -273,6 +279,9 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) | |||
273 | 279 | ||
274 | cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__); | 280 | cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__); |
275 | 281 | ||
282 | if (dev->state & DEV_DISCONNECTED) | ||
283 | return -ENODEV; | ||
284 | |||
276 | sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; | 285 | sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; |
277 | 286 | ||
278 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { | 287 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { |
@@ -298,7 +307,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) | |||
298 | urb->context = dev; | 307 | urb->context = dev; |
299 | urb->pipe = usb_rcvisocpipe(dev->udev, | 308 | urb->pipe = usb_rcvisocpipe(dev->udev, |
300 | dev->adev.end_point_addr); | 309 | dev->adev.end_point_addr); |
301 | urb->transfer_flags = URB_ISO_ASAP; | 310 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; |
302 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | 311 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; |
303 | urb->interval = 1; | 312 | urb->interval = 1; |
304 | urb->complete = cx231xx_audio_isocirq; | 313 | urb->complete = cx231xx_audio_isocirq; |
@@ -331,6 +340,9 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev) | |||
331 | 340 | ||
332 | cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__); | 341 | cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__); |
333 | 342 | ||
343 | if (dev->state & DEV_DISCONNECTED) | ||
344 | return -ENODEV; | ||
345 | |||
334 | sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; | 346 | sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; |
335 | 347 | ||
336 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { | 348 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { |
@@ -356,7 +368,7 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev) | |||
356 | urb->context = dev; | 368 | urb->context = dev; |
357 | urb->pipe = usb_rcvbulkpipe(dev->udev, | 369 | urb->pipe = usb_rcvbulkpipe(dev->udev, |
358 | dev->adev.end_point_addr); | 370 | dev->adev.end_point_addr); |
359 | urb->transfer_flags = 0; | 371 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; |
360 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | 372 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; |
361 | urb->complete = cx231xx_audio_bulkirq; | 373 | urb->complete = cx231xx_audio_bulkirq; |
362 | urb->transfer_buffer_length = sb_size; | 374 | urb->transfer_buffer_length = sb_size; |
@@ -432,6 +444,11 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) | |||
432 | return -ENODEV; | 444 | return -ENODEV; |
433 | } | 445 | } |
434 | 446 | ||
447 | if (dev->state & DEV_DISCONNECTED) { | ||
448 | cx231xx_errdev("Can't open. the device was removed.\n"); | ||
449 | return -ENODEV; | ||
450 | } | ||
451 | |||
435 | /* Sets volume, mute, etc */ | 452 | /* Sets volume, mute, etc */ |
436 | dev->mute = 0; | 453 | dev->mute = 0; |
437 | 454 | ||
@@ -571,6 +588,9 @@ static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, | |||
571 | struct cx231xx *dev = snd_pcm_substream_chip(substream); | 588 | struct cx231xx *dev = snd_pcm_substream_chip(substream); |
572 | int retval; | 589 | int retval; |
573 | 590 | ||
591 | if (dev->state & DEV_DISCONNECTED) | ||
592 | return -ENODEV; | ||
593 | |||
574 | spin_lock(&dev->adev.slock); | 594 | spin_lock(&dev->adev.slock); |
575 | switch (cmd) { | 595 | switch (cmd) { |
576 | case SNDRV_PCM_TRIGGER_START: | 596 | case SNDRV_PCM_TRIGGER_START: |
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 60b021e79864..919ed77b32f2 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c | |||
@@ -843,25 +843,34 @@ void cx231xx_release_resources(struct cx231xx *dev) | |||
843 | 843 | ||
844 | cx231xx_remove_from_devlist(dev); | 844 | cx231xx_remove_from_devlist(dev); |
845 | 845 | ||
846 | cx231xx_ir_exit(dev); | ||
847 | |||
846 | /* Release I2C buses */ | 848 | /* Release I2C buses */ |
847 | cx231xx_dev_uninit(dev); | 849 | cx231xx_dev_uninit(dev); |
848 | 850 | ||
849 | cx231xx_ir_exit(dev); | 851 | /* delete v4l2 device */ |
852 | v4l2_device_unregister(&dev->v4l2_dev); | ||
850 | 853 | ||
851 | usb_put_dev(dev->udev); | 854 | usb_put_dev(dev->udev); |
852 | 855 | ||
853 | /* Mark device as unused */ | 856 | /* Mark device as unused */ |
854 | cx231xx_devused &= ~(1 << dev->devno); | 857 | clear_bit(dev->devno, &cx231xx_devused); |
858 | |||
859 | kfree(dev->video_mode.alt_max_pkt_size); | ||
860 | kfree(dev->vbi_mode.alt_max_pkt_size); | ||
861 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | ||
862 | kfree(dev->ts1_mode.alt_max_pkt_size); | ||
863 | kfree(dev); | ||
864 | dev = NULL; | ||
855 | } | 865 | } |
856 | 866 | ||
857 | /* | 867 | /* |
858 | * cx231xx_init_dev() | 868 | * cx231xx_init_dev() |
859 | * allocates and inits the device structs, registers i2c bus and v4l device | 869 | * allocates and inits the device structs, registers i2c bus and v4l device |
860 | */ | 870 | */ |
861 | static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, | 871 | static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, |
862 | int minor) | 872 | int minor) |
863 | { | 873 | { |
864 | struct cx231xx *dev = *devhandle; | ||
865 | int retval = -ENOMEM; | 874 | int retval = -ENOMEM; |
866 | int errCode; | 875 | int errCode; |
867 | unsigned int maxh, maxw; | 876 | unsigned int maxh, maxw; |
@@ -1016,7 +1025,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1016 | int i, isoc_pipe = 0; | 1025 | int i, isoc_pipe = 0; |
1017 | char *speed; | 1026 | char *speed; |
1018 | char descr[255] = ""; | 1027 | char descr[255] = ""; |
1019 | struct usb_interface *lif = NULL; | ||
1020 | struct usb_interface_assoc_descriptor *assoc_desc; | 1028 | struct usb_interface_assoc_descriptor *assoc_desc; |
1021 | 1029 | ||
1022 | udev = usb_get_dev(interface_to_usbdev(interface)); | 1030 | udev = usb_get_dev(interface_to_usbdev(interface)); |
@@ -1030,21 +1038,21 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1030 | return -ENODEV; | 1038 | return -ENODEV; |
1031 | 1039 | ||
1032 | /* Check to see next free device and mark as used */ | 1040 | /* Check to see next free device and mark as used */ |
1033 | nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); | 1041 | do { |
1034 | cx231xx_devused |= 1 << nr; | 1042 | nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); |
1035 | 1043 | if (nr >= CX231XX_MAXBOARDS) { | |
1036 | if (nr >= CX231XX_MAXBOARDS) { | 1044 | /* No free device slots */ |
1037 | cx231xx_err(DRIVER_NAME | 1045 | cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n", |
1038 | ": Supports only %i cx231xx boards.\n", CX231XX_MAXBOARDS); | 1046 | CX231XX_MAXBOARDS); |
1039 | cx231xx_devused &= ~(1 << nr); | 1047 | return -ENOMEM; |
1040 | return -ENOMEM; | 1048 | } |
1041 | } | 1049 | } while (test_and_set_bit(nr, &cx231xx_devused)); |
1042 | 1050 | ||
1043 | /* allocate memory for our device state and initialize it */ | 1051 | /* allocate memory for our device state and initialize it */ |
1044 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 1052 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
1045 | if (dev == NULL) { | 1053 | if (dev == NULL) { |
1046 | cx231xx_err(DRIVER_NAME ": out of memory!\n"); | 1054 | cx231xx_err(DRIVER_NAME ": out of memory!\n"); |
1047 | cx231xx_devused &= ~(1 << nr); | 1055 | clear_bit(dev->devno, &cx231xx_devused); |
1048 | return -ENOMEM; | 1056 | return -ENOMEM; |
1049 | } | 1057 | } |
1050 | 1058 | ||
@@ -1071,9 +1079,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1071 | 1079 | ||
1072 | /* init CIR module TBD */ | 1080 | /* init CIR module TBD */ |
1073 | 1081 | ||
1074 | /* store the current interface */ | ||
1075 | lif = interface; | ||
1076 | |||
1077 | /*mode_tv: digital=1 or analog=0*/ | 1082 | /*mode_tv: digital=1 or analog=0*/ |
1078 | dev->mode_tv = 0; | 1083 | dev->mode_tv = 0; |
1079 | 1084 | ||
@@ -1113,9 +1118,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1113 | le16_to_cpu(udev->descriptor.idProduct), | 1118 | le16_to_cpu(udev->descriptor.idProduct), |
1114 | dev->max_iad_interface_count); | 1119 | dev->max_iad_interface_count); |
1115 | 1120 | ||
1116 | /* store the interface 0 back */ | ||
1117 | lif = udev->actconfig->interface[0]; | ||
1118 | |||
1119 | /* increment interface count */ | 1121 | /* increment interface count */ |
1120 | dev->interface_count++; | 1122 | dev->interface_count++; |
1121 | 1123 | ||
@@ -1126,7 +1128,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1126 | if (assoc_desc->bFirstInterface != ifnum) { | 1128 | if (assoc_desc->bFirstInterface != ifnum) { |
1127 | cx231xx_err(DRIVER_NAME ": Not found " | 1129 | cx231xx_err(DRIVER_NAME ": Not found " |
1128 | "matching IAD interface\n"); | 1130 | "matching IAD interface\n"); |
1129 | cx231xx_devused &= ~(1 << nr); | 1131 | clear_bit(dev->devno, &cx231xx_devused); |
1130 | kfree(dev); | 1132 | kfree(dev); |
1131 | dev = NULL; | 1133 | dev = NULL; |
1132 | return -ENODEV; | 1134 | return -ENODEV; |
@@ -1135,7 +1137,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1135 | cx231xx_info("registering interface %d\n", ifnum); | 1137 | cx231xx_info("registering interface %d\n", ifnum); |
1136 | 1138 | ||
1137 | /* save our data pointer in this interface device */ | 1139 | /* save our data pointer in this interface device */ |
1138 | usb_set_intfdata(lif, dev); | 1140 | usb_set_intfdata(interface, dev); |
1139 | 1141 | ||
1140 | /* | 1142 | /* |
1141 | * AV device initialization - only done at the last interface | 1143 | * AV device initialization - only done at the last interface |
@@ -1145,19 +1147,19 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1145 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); | 1147 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); |
1146 | if (retval) { | 1148 | if (retval) { |
1147 | cx231xx_errdev("v4l2_device_register failed\n"); | 1149 | cx231xx_errdev("v4l2_device_register failed\n"); |
1148 | cx231xx_devused &= ~(1 << nr); | 1150 | clear_bit(dev->devno, &cx231xx_devused); |
1149 | kfree(dev); | 1151 | kfree(dev); |
1150 | dev = NULL; | 1152 | dev = NULL; |
1151 | return -EIO; | 1153 | return -EIO; |
1152 | } | 1154 | } |
1153 | /* allocate device struct */ | 1155 | /* allocate device struct */ |
1154 | retval = cx231xx_init_dev(&dev, udev, nr); | 1156 | retval = cx231xx_init_dev(dev, udev, nr); |
1155 | if (retval) { | 1157 | if (retval) { |
1156 | cx231xx_devused &= ~(1 << dev->devno); | 1158 | clear_bit(dev->devno, &cx231xx_devused); |
1157 | v4l2_device_unregister(&dev->v4l2_dev); | 1159 | v4l2_device_unregister(&dev->v4l2_dev); |
1158 | kfree(dev); | 1160 | kfree(dev); |
1159 | dev = NULL; | 1161 | dev = NULL; |
1160 | usb_set_intfdata(lif, NULL); | 1162 | usb_set_intfdata(interface, NULL); |
1161 | 1163 | ||
1162 | return retval; | 1164 | return retval; |
1163 | } | 1165 | } |
@@ -1178,7 +1180,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1178 | 1180 | ||
1179 | if (dev->video_mode.alt_max_pkt_size == NULL) { | 1181 | if (dev->video_mode.alt_max_pkt_size == NULL) { |
1180 | cx231xx_errdev("out of memory!\n"); | 1182 | cx231xx_errdev("out of memory!\n"); |
1181 | cx231xx_devused &= ~(1 << nr); | 1183 | clear_bit(dev->devno, &cx231xx_devused); |
1182 | v4l2_device_unregister(&dev->v4l2_dev); | 1184 | v4l2_device_unregister(&dev->v4l2_dev); |
1183 | kfree(dev); | 1185 | kfree(dev); |
1184 | dev = NULL; | 1186 | dev = NULL; |
@@ -1212,7 +1214,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1212 | 1214 | ||
1213 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { | 1215 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { |
1214 | cx231xx_errdev("out of memory!\n"); | 1216 | cx231xx_errdev("out of memory!\n"); |
1215 | cx231xx_devused &= ~(1 << nr); | 1217 | clear_bit(dev->devno, &cx231xx_devused); |
1216 | v4l2_device_unregister(&dev->v4l2_dev); | 1218 | v4l2_device_unregister(&dev->v4l2_dev); |
1217 | kfree(dev); | 1219 | kfree(dev); |
1218 | dev = NULL; | 1220 | dev = NULL; |
@@ -1247,7 +1249,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1247 | 1249 | ||
1248 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { | 1250 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { |
1249 | cx231xx_errdev("out of memory!\n"); | 1251 | cx231xx_errdev("out of memory!\n"); |
1250 | cx231xx_devused &= ~(1 << nr); | 1252 | clear_bit(dev->devno, &cx231xx_devused); |
1251 | v4l2_device_unregister(&dev->v4l2_dev); | 1253 | v4l2_device_unregister(&dev->v4l2_dev); |
1252 | kfree(dev); | 1254 | kfree(dev); |
1253 | dev = NULL; | 1255 | dev = NULL; |
@@ -1283,7 +1285,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1283 | 1285 | ||
1284 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { | 1286 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { |
1285 | cx231xx_errdev("out of memory!\n"); | 1287 | cx231xx_errdev("out of memory!\n"); |
1286 | cx231xx_devused &= ~(1 << nr); | 1288 | clear_bit(dev->devno, &cx231xx_devused); |
1287 | v4l2_device_unregister(&dev->v4l2_dev); | 1289 | v4l2_device_unregister(&dev->v4l2_dev); |
1288 | kfree(dev); | 1290 | kfree(dev); |
1289 | dev = NULL; | 1291 | dev = NULL; |
@@ -1334,10 +1336,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) | |||
1334 | if (!dev->udev) | 1336 | if (!dev->udev) |
1335 | return; | 1337 | return; |
1336 | 1338 | ||
1337 | flush_request_modules(dev); | 1339 | dev->state |= DEV_DISCONNECTED; |
1338 | 1340 | ||
1339 | /* delete v4l2 device */ | 1341 | flush_request_modules(dev); |
1340 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1341 | 1342 | ||
1342 | /* wait until all current v4l2 io is finished then deallocate | 1343 | /* wait until all current v4l2 io is finished then deallocate |
1343 | resources */ | 1344 | resources */ |
@@ -1351,31 +1352,24 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) | |||
1351 | "deallocation are deferred on close.\n", | 1352 | "deallocation are deferred on close.\n", |
1352 | video_device_node_name(dev->vdev)); | 1353 | video_device_node_name(dev->vdev)); |
1353 | 1354 | ||
1354 | dev->state |= DEV_MISCONFIGURED; | 1355 | /* Even having users, it is safe to remove the RC i2c driver */ |
1356 | cx231xx_ir_exit(dev); | ||
1357 | |||
1355 | if (dev->USE_ISO) | 1358 | if (dev->USE_ISO) |
1356 | cx231xx_uninit_isoc(dev); | 1359 | cx231xx_uninit_isoc(dev); |
1357 | else | 1360 | else |
1358 | cx231xx_uninit_bulk(dev); | 1361 | cx231xx_uninit_bulk(dev); |
1359 | dev->state |= DEV_DISCONNECTED; | ||
1360 | wake_up_interruptible(&dev->wait_frame); | 1362 | wake_up_interruptible(&dev->wait_frame); |
1361 | wake_up_interruptible(&dev->wait_stream); | 1363 | wake_up_interruptible(&dev->wait_stream); |
1362 | } else { | 1364 | } else { |
1363 | dev->state |= DEV_DISCONNECTED; | ||
1364 | cx231xx_release_resources(dev); | ||
1365 | } | 1365 | } |
1366 | 1366 | ||
1367 | cx231xx_close_extension(dev); | 1367 | cx231xx_close_extension(dev); |
1368 | 1368 | ||
1369 | mutex_unlock(&dev->lock); | 1369 | mutex_unlock(&dev->lock); |
1370 | 1370 | ||
1371 | if (!dev->users) { | 1371 | if (!dev->users) |
1372 | kfree(dev->video_mode.alt_max_pkt_size); | 1372 | cx231xx_release_resources(dev); |
1373 | kfree(dev->vbi_mode.alt_max_pkt_size); | ||
1374 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | ||
1375 | kfree(dev->ts1_mode.alt_max_pkt_size); | ||
1376 | kfree(dev); | ||
1377 | dev = NULL; | ||
1378 | } | ||
1379 | } | 1373 | } |
1380 | 1374 | ||
1381 | static struct usb_driver cx231xx_usb_driver = { | 1375 | static struct usb_driver cx231xx_usb_driver = { |
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index d4457f9488ee..08dd930f882a 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c | |||
@@ -166,6 +166,9 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, | |||
166 | u8 _i2c_nostop = 0; | 166 | u8 _i2c_nostop = 0; |
167 | u8 _i2c_reserve = 0; | 167 | u8 _i2c_reserve = 0; |
168 | 168 | ||
169 | if (dev->state & DEV_DISCONNECTED) | ||
170 | return -ENODEV; | ||
171 | |||
169 | /* Get the I2C period, nostop and reserve parameters */ | 172 | /* Get the I2C period, nostop and reserve parameters */ |
170 | _i2c_period = i2c_bus->i2c_period; | 173 | _i2c_period = i2c_bus->i2c_period; |
171 | _i2c_nostop = i2c_bus->i2c_nostop; | 174 | _i2c_nostop = i2c_bus->i2c_nostop; |
@@ -1071,7 +1074,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, | |||
1071 | sb_size, cx231xx_isoc_irq_callback, dma_q, 1); | 1074 | sb_size, cx231xx_isoc_irq_callback, dma_q, 1); |
1072 | 1075 | ||
1073 | urb->number_of_packets = max_packets; | 1076 | urb->number_of_packets = max_packets; |
1074 | urb->transfer_flags = URB_ISO_ASAP; | 1077 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; |
1075 | 1078 | ||
1076 | k = 0; | 1079 | k = 0; |
1077 | for (j = 0; j < max_packets; j++) { | 1080 | for (j = 0; j < max_packets; j++) { |
@@ -1182,7 +1185,7 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, | |||
1182 | return -ENOMEM; | 1185 | return -ENOMEM; |
1183 | } | 1186 | } |
1184 | dev->video_mode.bulk_ctl.urb[i] = urb; | 1187 | dev->video_mode.bulk_ctl.urb[i] = urb; |
1185 | urb->transfer_flags = 0; | 1188 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; |
1186 | 1189 | ||
1187 | dev->video_mode.bulk_ctl.transfer_buffer[i] = | 1190 | dev->video_mode.bulk_ctl.transfer_buffer[i] = |
1188 | usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, | 1191 | usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, |
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c index da9a4a0aab79..7c4e360ba9bc 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c | |||
@@ -196,7 +196,7 @@ static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb) | |||
196 | if (!dev) | 196 | if (!dev) |
197 | return 0; | 197 | return 0; |
198 | 198 | ||
199 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 199 | if (dev->state & DEV_DISCONNECTED) |
200 | return 0; | 200 | return 0; |
201 | 201 | ||
202 | if (urb->status < 0) { | 202 | if (urb->status < 0) { |
@@ -228,7 +228,7 @@ static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb) | |||
228 | if (!dev) | 228 | if (!dev) |
229 | return 0; | 229 | return 0; |
230 | 230 | ||
231 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 231 | if (dev->state & DEV_DISCONNECTED) |
232 | return 0; | 232 | return 0; |
233 | 233 | ||
234 | if (urb->status < 0) { | 234 | if (urb->status < 0) { |
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 45e14cac4622..96176e9db5a2 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c | |||
@@ -27,12 +27,16 @@ | |||
27 | static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, | 27 | static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, |
28 | u32 *ir_raw) | 28 | u32 *ir_raw) |
29 | { | 29 | { |
30 | int rc; | ||
30 | u8 cmd, scancode; | 31 | u8 cmd, scancode; |
31 | 32 | ||
32 | dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__); | 33 | dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__); |
33 | 34 | ||
34 | /* poll IR chip */ | 35 | /* poll IR chip */ |
35 | if (1 != i2c_master_recv(ir->c, &cmd, 1)) | 36 | rc = i2c_master_recv(ir->c, &cmd, 1); |
37 | if (rc < 0) | ||
38 | return rc; | ||
39 | if (rc != 1) | ||
36 | return -EIO; | 40 | return -EIO; |
37 | 41 | ||
38 | /* it seems that 0xFE indicates that a button is still hold | 42 | /* it seems that 0xFE indicates that a button is still hold |
@@ -102,11 +106,14 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
102 | ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master; | 106 | ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master; |
103 | dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n", | 107 | dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n", |
104 | ir_i2c_bus, info.addr); | 108 | ir_i2c_bus, info.addr); |
105 | i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info); | 109 | dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info); |
106 | 110 | ||
107 | return 0; | 111 | return 0; |
108 | } | 112 | } |
109 | 113 | ||
110 | void cx231xx_ir_exit(struct cx231xx *dev) | 114 | void cx231xx_ir_exit(struct cx231xx *dev) |
111 | { | 115 | { |
116 | if (dev->ir_i2c_client) | ||
117 | i2c_unregister_device(dev->ir_i2c_client); | ||
118 | dev->ir_i2c_client = NULL; | ||
112 | } | 119 | } |
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c index 1c7a4daafecf..8cdee5f78f13 100644 --- a/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/drivers/media/video/cx231xx/cx231xx-vbi.c | |||
@@ -93,7 +93,7 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) | |||
93 | if (!dev) | 93 | if (!dev) |
94 | return 0; | 94 | return 0; |
95 | 95 | ||
96 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 96 | if (dev->state & DEV_DISCONNECTED) |
97 | return 0; | 97 | return 0; |
98 | 98 | ||
99 | if (urb->status < 0) { | 99 | if (urb->status < 0) { |
@@ -452,7 +452,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, | |||
452 | return -ENOMEM; | 452 | return -ENOMEM; |
453 | } | 453 | } |
454 | dev->vbi_mode.bulk_ctl.urb[i] = urb; | 454 | dev->vbi_mode.bulk_ctl.urb[i] = urb; |
455 | urb->transfer_flags = 0; | 455 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; |
456 | 456 | ||
457 | dev->vbi_mode.bulk_ctl.transfer_buffer[i] = | 457 | dev->vbi_mode.bulk_ctl.transfer_buffer[i] = |
458 | kzalloc(sb_size, GFP_KERNEL); | 458 | kzalloc(sb_size, GFP_KERNEL); |
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 6e81f970dc7d..829a41b0c9ef 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c | |||
@@ -337,7 +337,7 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) | |||
337 | if (!dev) | 337 | if (!dev) |
338 | return 0; | 338 | return 0; |
339 | 339 | ||
340 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 340 | if (dev->state & DEV_DISCONNECTED) |
341 | return 0; | 341 | return 0; |
342 | 342 | ||
343 | if (urb->status < 0) { | 343 | if (urb->status < 0) { |
@@ -440,7 +440,7 @@ static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) | |||
440 | if (!dev) | 440 | if (!dev) |
441 | return 0; | 441 | return 0; |
442 | 442 | ||
443 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 443 | if (dev->state & DEV_DISCONNECTED) |
444 | return 0; | 444 | return 0; |
445 | 445 | ||
446 | if (urb->status < 0) { | 446 | if (urb->status < 0) { |
@@ -1000,12 +1000,6 @@ static int check_dev(struct cx231xx *dev) | |||
1000 | cx231xx_errdev("v4l2 ioctl: device not present\n"); | 1000 | cx231xx_errdev("v4l2 ioctl: device not present\n"); |
1001 | return -ENODEV; | 1001 | return -ENODEV; |
1002 | } | 1002 | } |
1003 | |||
1004 | if (dev->state & DEV_MISCONFIGURED) { | ||
1005 | cx231xx_errdev("v4l2 ioctl: device is misconfigured; " | ||
1006 | "close and open it again\n"); | ||
1007 | return -EIO; | ||
1008 | } | ||
1009 | return 0; | 1003 | return 0; |
1010 | } | 1004 | } |
1011 | 1005 | ||
@@ -2347,7 +2341,8 @@ static int cx231xx_v4l2_close(struct file *filp) | |||
2347 | return 0; | 2341 | return 0; |
2348 | } | 2342 | } |
2349 | 2343 | ||
2350 | if (dev->users == 1) { | 2344 | dev->users--; |
2345 | if (!dev->users) { | ||
2351 | videobuf_stop(&fh->vb_vidq); | 2346 | videobuf_stop(&fh->vb_vidq); |
2352 | videobuf_mmap_free(&fh->vb_vidq); | 2347 | videobuf_mmap_free(&fh->vb_vidq); |
2353 | 2348 | ||
@@ -2374,7 +2369,6 @@ static int cx231xx_v4l2_close(struct file *filp) | |||
2374 | cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); | 2369 | cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); |
2375 | } | 2370 | } |
2376 | kfree(fh); | 2371 | kfree(fh); |
2377 | dev->users--; | ||
2378 | wake_up_interruptible_nr(&dev->open, 1); | 2372 | wake_up_interruptible_nr(&dev->open, 1); |
2379 | return 0; | 2373 | return 0; |
2380 | } | 2374 | } |
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 2000bc64c497..e17447554a0d 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h | |||
@@ -377,7 +377,6 @@ struct cx231xx_board { | |||
377 | enum cx231xx_dev_state { | 377 | enum cx231xx_dev_state { |
378 | DEV_INITIALIZED = 0x01, | 378 | DEV_INITIALIZED = 0x01, |
379 | DEV_DISCONNECTED = 0x02, | 379 | DEV_DISCONNECTED = 0x02, |
380 | DEV_MISCONFIGURED = 0x04, | ||
381 | }; | 380 | }; |
382 | 381 | ||
383 | enum AFE_MODE { | 382 | enum AFE_MODE { |
@@ -621,6 +620,7 @@ struct cx231xx { | |||
621 | 620 | ||
622 | /* For I2C IR support */ | 621 | /* For I2C IR support */ |
623 | struct IR_i2c_init_data init_data; | 622 | struct IR_i2c_init_data init_data; |
623 | struct i2c_client *ir_i2c_client; | ||
624 | 624 | ||
625 | unsigned int stream_on:1; /* Locks streams */ | 625 | unsigned int stream_on:1; /* Locks streams */ |
626 | unsigned int vbi_stream_on:1; /* Locks streams for VBI */ | 626 | unsigned int vbi_stream_on:1; /* Locks streams for VBI */ |