diff options
Diffstat (limited to 'drivers/media/video/pwc/pwc-if.c')
-rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 68 |
1 files changed, 22 insertions, 46 deletions
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; |