diff options
Diffstat (limited to 'drivers/media/video/pwc')
-rw-r--r-- | drivers/media/video/pwc/pwc-ctrl.c | 7 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 68 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-v4l.c | 30 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc.h | 1 |
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 | ||
970 | int 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; | |||
275 | extern int pwc_mbufs; | 275 | extern int pwc_mbufs; |
276 | 276 | ||
277 | /** functions in pwc-if.c */ | 277 | /** functions in pwc-if.c */ |
278 | int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot); | ||
279 | int pwc_handle_frame(struct pwc_device *pdev); | 278 | int pwc_handle_frame(struct pwc_device *pdev); |
280 | void pwc_next_image(struct pwc_device *pdev); | 279 | void pwc_next_image(struct pwc_device *pdev); |
281 | int pwc_isoc_init(struct pwc_device *pdev); | 280 | int pwc_isoc_init(struct pwc_device *pdev); |