aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pwc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pwc')
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c7
-rw-r--r--drivers/media/video/pwc/pwc-if.c68
-rw-r--r--drivers/media/video/pwc/pwc-v4l.c30
-rw-r--r--drivers/media/video/pwc/pwc.h1
4 files changed, 35 insertions, 71 deletions
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 6b8fbddc0747..1593f8deb810 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -1386,11 +1386,16 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1386 { 1386 {
1387 ARG_DEF(int, qual) 1387 ARG_DEF(int, qual)
1388 1388
1389 if (pdev->iso_init) {
1390 ret = -EBUSY;
1391 break;
1392 }
1393
1389 ARG_IN(qual) 1394 ARG_IN(qual)
1390 if (ARGR(qual) < 0 || ARGR(qual) > 3) 1395 if (ARGR(qual) < 0 || ARGR(qual) > 3)
1391 ret = -EINVAL; 1396 ret = -EINVAL;
1392 else 1397 else
1393 ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); 1398 ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
1394 if (ret >= 0) 1399 if (ret >= 0)
1395 pdev->vcompression = ARGR(qual); 1400 pdev->vcompression = ARGR(qual);
1396 break; 1401 break;
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index f3dc89da4c4e..bd1519a4ecb4 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -287,14 +287,13 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
287 /* create frame buffers, and make circular ring */ 287 /* create frame buffers, and make circular ring */
288 for (i = 0; i < default_fbufs; i++) { 288 for (i = 0; i < default_fbufs; i++) {
289 if (pdev->fbuf[i].data == NULL) { 289 if (pdev->fbuf[i].data == NULL) {
290 kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */ 290 kbuf = vzalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
291 if (kbuf == NULL) { 291 if (kbuf == NULL) {
292 PWC_ERROR("Failed to allocate frame buffer %d.\n", i); 292 PWC_ERROR("Failed to allocate frame buffer %d.\n", i);
293 return -ENOMEM; 293 return -ENOMEM;
294 } 294 }
295 PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf); 295 PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf);
296 pdev->fbuf[i].data = kbuf; 296 pdev->fbuf[i].data = kbuf;
297 memset(kbuf, 0, PWC_FRAME_SIZE);
298 } 297 }
299 } 298 }
300 299
@@ -899,10 +898,13 @@ int pwc_isoc_init(struct pwc_device *pdev)
899 /* link */ 898 /* link */
900 for (i = 0; i < MAX_ISO_BUFS; i++) { 899 for (i = 0; i < MAX_ISO_BUFS; i++) {
901 ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL); 900 ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
902 if (ret) 901 if (ret) {
903 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); 902 PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
904 else 903 pdev->iso_init = 1;
905 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb); 904 pwc_isoc_cleanup(pdev);
905 return ret;
906 }
907 PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);
906 } 908 }
907 909
908 /* All is done... */ 910 /* All is done... */
@@ -958,7 +960,7 @@ void pwc_isoc_cleanup(struct pwc_device *pdev)
958 /* Stop camera, but only if we are sure the camera is still there (unplug 960 /* Stop camera, but only if we are sure the camera is still there (unplug
959 is signalled by EPIPE) 961 is signalled by EPIPE)
960 */ 962 */
961 if (pdev->error_status && pdev->error_status != EPIPE) { 963 if (pdev->error_status != EPIPE) {
962 PWC_DEBUG_OPEN("Setting alternate interface 0.\n"); 964 PWC_DEBUG_OPEN("Setting alternate interface 0.\n");
963 usb_set_interface(pdev->udev, 0, 0); 965 usb_set_interface(pdev->udev, 0, 0);
964 } 966 }
@@ -967,36 +969,6 @@ void pwc_isoc_cleanup(struct pwc_device *pdev)
967 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); 969 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
968} 970}
969 971
970int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
971{
972 int ret, start;
973
974 /* Stop isoc stuff */
975 pwc_isoc_cleanup(pdev);
976 /* Reset parameters */
977 pwc_reset_buffers(pdev);
978 /* Try to set video mode... */
979 start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
980 if (ret) {
981 PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n");
982 /* That failed... restore old mode (we know that worked) */
983 start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
984 if (start) {
985 PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n");
986 }
987 }
988 if (start == 0)
989 {
990 if (pwc_isoc_init(pdev) < 0)
991 {
992 PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
993 ret = -EAGAIN; /* let's try again, who knows if it works a second time */
994 }
995 }
996 pdev->drop_frames++; /* try to avoid garbage during switch */
997 return ret; /* Return original error code */
998}
999
1000/********* 972/*********
1001 * sysfs 973 * sysfs
1002 *********/ 974 *********/
@@ -1176,7 +1148,7 @@ static int pwc_video_open(struct file *file)
1176 /* Set some defaults */ 1148 /* Set some defaults */
1177 pdev->vsnapshot = 0; 1149 pdev->vsnapshot = 0;
1178 1150
1179 /* Start iso pipe for video; first try the last used video size 1151 /* Set video size, first try the last used video size
1180 (or the default one); if that fails try QCIF/10 or QSIF/10; 1152 (or the default one); if that fails try QCIF/10 or QSIF/10;
1181 it that fails too, give up. 1153 it that fails too, give up.
1182 */ 1154 */
@@ -1203,15 +1175,6 @@ static int pwc_video_open(struct file *file)
1203 return i; 1175 return i;
1204 } 1176 }
1205 1177
1206 i = pwc_isoc_init(pdev);
1207 if (i) {
1208 PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i);
1209 pwc_isoc_cleanup(pdev);
1210 pwc_free_buffers(pdev);
1211 mutex_unlock(&pdev->modlock);
1212 return i;
1213 }
1214
1215 /* Initialize the webcam to sane value */ 1178 /* Initialize the webcam to sane value */
1216 pwc_set_brightness(pdev, 0x7fff); 1179 pwc_set_brightness(pdev, 0x7fff);
1217 pwc_set_agc(pdev, 1, 0); 1180 pwc_set_agc(pdev, 1, 0);
@@ -1326,6 +1289,11 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
1326 goto err_out; 1289 goto err_out;
1327 } 1290 }
1328 1291
1292 /* Start the stream (if not already started) */
1293 rv = pwc_isoc_init(pdev);
1294 if (rv)
1295 goto err_out;
1296
1329 /* In case we're doing partial reads, we don't have to wait for a frame */ 1297 /* In case we're doing partial reads, we don't have to wait for a frame */
1330 if (pdev->image_read_pos == 0) { 1298 if (pdev->image_read_pos == 0) {
1331 /* Do wait queueing according to the (doc)book */ 1299 /* Do wait queueing according to the (doc)book */
@@ -1395,6 +1363,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
1395{ 1363{
1396 struct video_device *vdev = file->private_data; 1364 struct video_device *vdev = file->private_data;
1397 struct pwc_device *pdev; 1365 struct pwc_device *pdev;
1366 int ret;
1398 1367
1399 if (vdev == NULL) 1368 if (vdev == NULL)
1400 return -EFAULT; 1369 return -EFAULT;
@@ -1402,6 +1371,13 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
1402 if (pdev == NULL) 1371 if (pdev == NULL)
1403 return -EFAULT; 1372 return -EFAULT;
1404 1373
1374 /* Start the stream (if not already started) */
1375 mutex_lock(&pdev->modlock);
1376 ret = pwc_isoc_init(pdev);
1377 mutex_unlock(&pdev->modlock);
1378 if (ret)
1379 return ret;
1380
1405 poll_wait(file, &pdev->frameq, wait); 1381 poll_wait(file, &pdev->frameq, wait);
1406 if (pdev->error_status) 1382 if (pdev->error_status)
1407 return POLLERR; 1383 return POLLERR;
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 7061a03f5cf1..8ca4d22b4384 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -309,7 +309,10 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
309 pixelformat != V4L2_PIX_FMT_PWC2) 309 pixelformat != V4L2_PIX_FMT_PWC2)
310 return -EINVAL; 310 return -EINVAL;
311 311
312 PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d " 312 if (pdev->iso_init)
313 return -EBUSY;
314
315 PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d "
313 "compression=%d snapshot=%d format=%c%c%c%c\n", 316 "compression=%d snapshot=%d format=%c%c%c%c\n",
314 f->fmt.pix.width, f->fmt.pix.height, fps, 317 f->fmt.pix.width, f->fmt.pix.height, fps,
315 compression, snapshot, 318 compression, snapshot,
@@ -318,14 +321,14 @@ static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
318 (pixelformat>>16)&255, 321 (pixelformat>>16)&255,
319 (pixelformat>>24)&255); 322 (pixelformat>>24)&255);
320 323
321 ret = pwc_try_video_mode(pdev, 324 ret = pwc_set_video_mode(pdev,
322 f->fmt.pix.width, 325 f->fmt.pix.width,
323 f->fmt.pix.height, 326 f->fmt.pix.height,
324 fps, 327 fps,
325 compression, 328 compression,
326 snapshot); 329 snapshot);
327 330
328 PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret); 331 PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret);
329 332
330 if (ret) 333 if (ret)
331 return ret; 334 return ret;
@@ -359,23 +362,6 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
359 362
360 363
361 switch (cmd) { 364 switch (cmd) {
362#ifdef CONFIG_VIDEO_V4L1_COMPAT
363 /* mmap() functions */
364 case VIDIOCGMBUF:
365 {
366 /* Tell the user program how much memory is needed for a mmap() */
367 struct video_mbuf *vm = arg;
368 int i;
369
370 memset(vm, 0, sizeof(*vm));
371 vm->size = pwc_mbufs * pdev->len_per_image;
372 vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */
373 for (i = 0; i < pwc_mbufs; i++)
374 vm->offsets[i] = i * pdev->len_per_image;
375 break;
376 }
377#endif
378
379 /* V4L2 Layer */ 365 /* V4L2 Layer */
380 case VIDIOC_QUERYCAP: 366 case VIDIOC_QUERYCAP:
381 { 367 {
@@ -882,9 +868,7 @@ long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
882 868
883 case VIDIOC_STREAMON: 869 case VIDIOC_STREAMON:
884 { 870 {
885 /* WARNING: pwc_try_video_mode() called pwc_isoc_init */ 871 return pwc_isoc_init(pdev);
886 pwc_isoc_init(pdev);
887 return 0;
888 } 872 }
889 873
890 case VIDIOC_STREAMOFF: 874 case VIDIOC_STREAMOFF:
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 36a9c83b5f5d..16bbc6df9b07 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -275,7 +275,6 @@ extern int pwc_trace;
275extern int pwc_mbufs; 275extern int pwc_mbufs;
276 276
277/** functions in pwc-if.c */ 277/** functions in pwc-if.c */
278int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
279int pwc_handle_frame(struct pwc_device *pdev); 278int pwc_handle_frame(struct pwc_device *pdev);
280void pwc_next_image(struct pwc_device *pdev); 279void pwc_next_image(struct pwc_device *pdev);
281int pwc_isoc_init(struct pwc_device *pdev); 280int pwc_isoc_init(struct pwc_device *pdev);