aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/cafe_ccic.c35
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c1
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c3
-rw-r--r--drivers/media/video/ov7670.c5
-rw-r--r--drivers/media/video/pwc/pwc-if.c52
-rw-r--r--drivers/media/video/pwc/pwc.h1
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,
416static int ov7670_write(struct i2c_client *c, unsigned char reg, 416static 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
1200static 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 */
1200static int pwc_video_close(struct inode *inode, struct file *file) 1207static 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
1804disconnect_out: 1821disconnect_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];