diff options
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/cafe_ccic.c | 35 | ||||
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 1 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-ioctl.c | 3 | ||||
-rw-r--r-- | drivers/media/video/ov7670.c | 5 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 52 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc.h | 1 |
6 files changed, 75 insertions, 22 deletions
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index c08f650df423..ef5361824f87 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -356,6 +356,7 @@ static int cafe_smbus_write_data(struct cafe_camera *cam, | |||
356 | { | 356 | { |
357 | unsigned int rval; | 357 | unsigned int rval; |
358 | unsigned long flags; | 358 | unsigned long flags; |
359 | DEFINE_WAIT(the_wait); | ||
359 | 360 | ||
360 | spin_lock_irqsave(&cam->dev_lock, flags); | 361 | spin_lock_irqsave(&cam->dev_lock, flags); |
361 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); | 362 | rval = TWSIC0_EN | ((addr << TWSIC0_SID_SHIFT) & TWSIC0_SID); |
@@ -369,10 +370,29 @@ static int cafe_smbus_write_data(struct cafe_camera *cam, | |||
369 | rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); | 370 | rval = value | ((command << TWSIC1_ADDR_SHIFT) & TWSIC1_ADDR); |
370 | cafe_reg_write(cam, REG_TWSIC1, rval); | 371 | cafe_reg_write(cam, REG_TWSIC1, rval); |
371 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 372 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
372 | msleep(2); /* Required or things flake */ | ||
373 | 373 | ||
374 | /* | ||
375 | * Time to wait for the write to complete. THIS IS A RACY | ||
376 | * WAY TO DO IT, but the sad fact is that reading the TWSIC1 | ||
377 | * register too quickly after starting the operation sends | ||
378 | * the device into a place that may be kinder and better, but | ||
379 | * which is absolutely useless for controlling the sensor. In | ||
380 | * practice we have plenty of time to get into our sleep state | ||
381 | * before the interrupt hits, and the worst case is that we | ||
382 | * time out and then see that things completed, so this seems | ||
383 | * the best way for now. | ||
384 | */ | ||
385 | do { | ||
386 | prepare_to_wait(&cam->smbus_wait, &the_wait, | ||
387 | TASK_UNINTERRUPTIBLE); | ||
388 | schedule_timeout(1); /* even 1 jiffy is too long */ | ||
389 | finish_wait(&cam->smbus_wait, &the_wait); | ||
390 | } while (!cafe_smbus_write_done(cam)); | ||
391 | |||
392 | #ifdef IF_THE_CAFE_HARDWARE_WORKED_RIGHT | ||
374 | wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), | 393 | wait_event_timeout(cam->smbus_wait, cafe_smbus_write_done(cam), |
375 | CAFE_SMBUS_TIMEOUT); | 394 | CAFE_SMBUS_TIMEOUT); |
395 | #endif | ||
376 | spin_lock_irqsave(&cam->dev_lock, flags); | 396 | spin_lock_irqsave(&cam->dev_lock, flags); |
377 | rval = cafe_reg_read(cam, REG_TWSIC1); | 397 | rval = cafe_reg_read(cam, REG_TWSIC1); |
378 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 398 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
@@ -710,7 +730,7 @@ static void cafe_ctlr_init(struct cafe_camera *cam) | |||
710 | * Here we must wait a bit for the controller to come around. | 730 | * Here we must wait a bit for the controller to come around. |
711 | */ | 731 | */ |
712 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 732 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
713 | mdelay(5); /* FIXME revisit this */ | 733 | msleep(5); |
714 | spin_lock_irqsave(&cam->dev_lock, flags); | 734 | spin_lock_irqsave(&cam->dev_lock, flags); |
715 | 735 | ||
716 | cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); | 736 | cafe_reg_write(cam, REG_GL_CSR, GCSR_CCIC_EN|GCSR_SRC|GCSR_MRC); |
@@ -2233,12 +2253,21 @@ static int cafe_pci_resume(struct pci_dev *pdev) | |||
2233 | if (ret) | 2253 | if (ret) |
2234 | return ret; | 2254 | return ret; |
2235 | ret = pci_enable_device(pdev); | 2255 | ret = pci_enable_device(pdev); |
2256 | |||
2236 | if (ret) { | 2257 | if (ret) { |
2237 | cam_warn(cam, "Unable to re-enable device on resume!\n"); | 2258 | cam_warn(cam, "Unable to re-enable device on resume!\n"); |
2238 | return ret; | 2259 | return ret; |
2239 | } | 2260 | } |
2240 | cafe_ctlr_init(cam); | 2261 | cafe_ctlr_init(cam); |
2241 | cafe_ctlr_power_up(cam); | 2262 | cafe_ctlr_power_down(cam); |
2263 | |||
2264 | mutex_lock(&cam->s_mutex); | ||
2265 | if (cam->users > 0) { | ||
2266 | cafe_ctlr_power_up(cam); | ||
2267 | __cafe_cam_reset(cam); | ||
2268 | } | ||
2269 | mutex_unlock(&cam->s_mutex); | ||
2270 | |||
2242 | set_bit(CF_CONFIG_NEEDED, &cam->flags); | 2271 | set_bit(CF_CONFIG_NEEDED, &cam->flags); |
2243 | if (cam->state == S_SPECREAD) | 2272 | if (cam->state == S_SPECREAD) |
2244 | cam->state = S_IDLE; /* Don't bother restarting */ | 2273 | cam->state = S_IDLE; /* Don't bother restarting */ |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 2c7b158ce7e1..40307f3f6fe3 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -1772,6 +1772,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
1772 | if (dev->alt_max_pkt_size == NULL) { | 1772 | if (dev->alt_max_pkt_size == NULL) { |
1773 | em28xx_errdev("out of memory!\n"); | 1773 | em28xx_errdev("out of memory!\n"); |
1774 | em28xx_devused&=~(1<<nr); | 1774 | em28xx_devused&=~(1<<nr); |
1775 | kfree(dev); | ||
1775 | return -ENOMEM; | 1776 | return -ENOMEM; |
1776 | } | 1777 | } |
1777 | 1778 | ||
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 047624b9e271..5977a79619c2 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c | |||
@@ -1190,6 +1190,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1190 | itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; | 1190 | itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0; |
1191 | itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0; | 1191 | itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0; |
1192 | itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; | 1192 | itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0; |
1193 | ivtv_set_osd_alpha(itv); | ||
1193 | break; | 1194 | break; |
1194 | } | 1195 | } |
1195 | 1196 | ||
@@ -1234,7 +1235,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void | |||
1234 | IVTV_INFO("Tuner: %s\n", | 1235 | IVTV_INFO("Tuner: %s\n", |
1235 | test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); | 1236 | test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); |
1236 | cx2341x_log_status(&itv->params, itv->name); | 1237 | cx2341x_log_status(&itv->params, itv->name); |
1237 | IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); | 1238 | IVTV_INFO("Version: %s Status flags: 0x%08lx\n", IVTV_VERSION, itv->i_flags); |
1238 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { | 1239 | for (i = 0; i < IVTV_MAX_STREAMS; i++) { |
1239 | struct ivtv_stream *s = &itv->streams[i]; | 1240 | struct ivtv_stream *s = &itv->streams[i]; |
1240 | 1241 | ||
diff --git a/drivers/media/video/ov7670.c b/drivers/media/video/ov7670.c index f8f21ddd9843..c4c5bd67f795 100644 --- a/drivers/media/video/ov7670.c +++ b/drivers/media/video/ov7670.c | |||
@@ -416,7 +416,10 @@ static int ov7670_read(struct i2c_client *c, unsigned char reg, | |||
416 | static int ov7670_write(struct i2c_client *c, unsigned char reg, | 416 | static int ov7670_write(struct i2c_client *c, unsigned char reg, |
417 | unsigned char value) | 417 | unsigned char value) |
418 | { | 418 | { |
419 | return i2c_smbus_write_byte_data(c, reg, value); | 419 | int ret = i2c_smbus_write_byte_data(c, reg, value); |
420 | if (reg == REG_COM7 && (value & COM7_RESET)) | ||
421 | msleep(2); /* Wait for reset to run */ | ||
422 | return ret; | ||
420 | } | 423 | } |
421 | 424 | ||
422 | 425 | ||
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 9c0e8d18c2f6..3d81966d8c42 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -1196,12 +1196,19 @@ static int pwc_video_open(struct inode *inode, struct file *file) | |||
1196 | return 0; | 1196 | return 0; |
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | |||
1200 | static void pwc_cleanup(struct pwc_device *pdev) | ||
1201 | { | ||
1202 | pwc_remove_sysfs_files(pdev->vdev); | ||
1203 | video_unregister_device(pdev->vdev); | ||
1204 | } | ||
1205 | |||
1199 | /* Note that all cleanup is done in the reverse order as in _open */ | 1206 | /* Note that all cleanup is done in the reverse order as in _open */ |
1200 | static int pwc_video_close(struct inode *inode, struct file *file) | 1207 | static int pwc_video_close(struct inode *inode, struct file *file) |
1201 | { | 1208 | { |
1202 | struct video_device *vdev = file->private_data; | 1209 | struct video_device *vdev = file->private_data; |
1203 | struct pwc_device *pdev; | 1210 | struct pwc_device *pdev; |
1204 | int i; | 1211 | int i, hint; |
1205 | 1212 | ||
1206 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); | 1213 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); |
1207 | 1214 | ||
@@ -1224,8 +1231,9 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
1224 | pwc_isoc_cleanup(pdev); | 1231 | pwc_isoc_cleanup(pdev); |
1225 | pwc_free_buffers(pdev); | 1232 | pwc_free_buffers(pdev); |
1226 | 1233 | ||
1234 | lock_kernel(); | ||
1227 | /* Turn off LEDS and power down camera, but only when not unplugged */ | 1235 | /* Turn off LEDS and power down camera, but only when not unplugged */ |
1228 | if (pdev->error_status != EPIPE) { | 1236 | if (!pdev->unplugged) { |
1229 | /* Turn LEDs off */ | 1237 | /* Turn LEDs off */ |
1230 | if (pwc_set_leds(pdev, 0, 0) < 0) | 1238 | if (pwc_set_leds(pdev, 0, 0) < 0) |
1231 | PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); | 1239 | PWC_DEBUG_MODULE("Failed to set LED on/off time.\n"); |
@@ -1234,9 +1242,19 @@ static int pwc_video_close(struct inode *inode, struct file *file) | |||
1234 | if (i < 0) | 1242 | if (i < 0) |
1235 | PWC_ERROR("Failed to power down camera (%d)\n", i); | 1243 | PWC_ERROR("Failed to power down camera (%d)\n", i); |
1236 | } | 1244 | } |
1245 | pdev->vopen--; | ||
1246 | PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", i); | ||
1247 | } else { | ||
1248 | pwc_cleanup(pdev); | ||
1249 | /* Free memory (don't set pdev to 0 just yet) */ | ||
1250 | kfree(pdev); | ||
1251 | /* search device_hint[] table if we occupy a slot, by any chance */ | ||
1252 | for (hint = 0; hint < MAX_DEV_HINTS; hint++) | ||
1253 | if (device_hint[hint].pdev == pdev) | ||
1254 | device_hint[hint].pdev = NULL; | ||
1237 | } | 1255 | } |
1238 | pdev->vopen--; | 1256 | unlock_kernel(); |
1239 | PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); | 1257 | |
1240 | return 0; | 1258 | return 0; |
1241 | } | 1259 | } |
1242 | 1260 | ||
@@ -1791,21 +1809,21 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
1791 | /* Alert waiting processes */ | 1809 | /* Alert waiting processes */ |
1792 | wake_up_interruptible(&pdev->frameq); | 1810 | wake_up_interruptible(&pdev->frameq); |
1793 | /* Wait until device is closed */ | 1811 | /* Wait until device is closed */ |
1794 | while (pdev->vopen) | 1812 | if(pdev->vopen) { |
1795 | schedule(); | 1813 | pdev->unplugged = 1; |
1796 | /* Device is now closed, so we can safely unregister it */ | 1814 | } else { |
1797 | PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); | 1815 | /* Device is closed, so we can safely unregister it */ |
1798 | pwc_remove_sysfs_files(pdev->vdev); | 1816 | PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); |
1799 | video_unregister_device(pdev->vdev); | 1817 | pwc_cleanup(pdev); |
1800 | 1818 | /* Free memory (don't set pdev to 0 just yet) */ | |
1801 | /* Free memory (don't set pdev to 0 just yet) */ | 1819 | kfree(pdev); |
1802 | kfree(pdev); | ||
1803 | 1820 | ||
1804 | disconnect_out: | 1821 | disconnect_out: |
1805 | /* search device_hint[] table if we occupy a slot, by any chance */ | 1822 | /* search device_hint[] table if we occupy a slot, by any chance */ |
1806 | for (hint = 0; hint < MAX_DEV_HINTS; hint++) | 1823 | for (hint = 0; hint < MAX_DEV_HINTS; hint++) |
1807 | if (device_hint[hint].pdev == pdev) | 1824 | if (device_hint[hint].pdev == pdev) |
1808 | device_hint[hint].pdev = NULL; | 1825 | device_hint[hint].pdev = NULL; |
1826 | } | ||
1809 | 1827 | ||
1810 | unlock_kernel(); | 1828 | unlock_kernel(); |
1811 | } | 1829 | } |
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 910a04f53920..8e8e5b27e77e 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h | |||
@@ -193,6 +193,7 @@ struct pwc_device | |||
193 | char vsnapshot; /* snapshot mode */ | 193 | char vsnapshot; /* snapshot mode */ |
194 | char vsync; /* used by isoc handler */ | 194 | char vsync; /* used by isoc handler */ |
195 | char vmirror; /* for ToUCaM series */ | 195 | char vmirror; /* for ToUCaM series */ |
196 | char unplugged; | ||
196 | 197 | ||
197 | int cmd_len; | 198 | int cmd_len; |
198 | unsigned char cmd_buf[13]; | 199 | unsigned char cmd_buf[13]; |