aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc/uvc_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/uvc/uvc_video.c')
-rw-r--r--drivers/media/video/uvc/uvc_video.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 9a9802830d41..7dcf534a0cf3 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -441,7 +441,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
441 if (fid != stream->last_fid && buf->buf.bytesused != 0) { 441 if (fid != stream->last_fid && buf->buf.bytesused != 0) {
442 uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " 442 uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit "
443 "toggled).\n"); 443 "toggled).\n");
444 buf->state = UVC_BUF_STATE_DONE; 444 buf->state = UVC_BUF_STATE_READY;
445 return -EAGAIN; 445 return -EAGAIN;
446 } 446 }
447 447
@@ -470,7 +470,7 @@ static void uvc_video_decode_data(struct uvc_streaming *stream,
470 /* Complete the current frame if the buffer size was exceeded. */ 470 /* Complete the current frame if the buffer size was exceeded. */
471 if (len > maxlen) { 471 if (len > maxlen) {
472 uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); 472 uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n");
473 buf->state = UVC_BUF_STATE_DONE; 473 buf->state = UVC_BUF_STATE_READY;
474 } 474 }
475} 475}
476 476
@@ -482,7 +482,7 @@ static void uvc_video_decode_end(struct uvc_streaming *stream,
482 uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); 482 uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
483 if (data[0] == len) 483 if (data[0] == len)
484 uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); 484 uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n");
485 buf->state = UVC_BUF_STATE_DONE; 485 buf->state = UVC_BUF_STATE_READY;
486 if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID) 486 if (stream->dev->quirks & UVC_QUIRK_STREAM_NO_FID)
487 stream->last_fid ^= UVC_STREAM_FID; 487 stream->last_fid ^= UVC_STREAM_FID;
488 } 488 }
@@ -568,8 +568,7 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream,
568 uvc_video_decode_end(stream, buf, mem, 568 uvc_video_decode_end(stream, buf, mem,
569 urb->iso_frame_desc[i].actual_length); 569 urb->iso_frame_desc[i].actual_length);
570 570
571 if (buf->state == UVC_BUF_STATE_DONE || 571 if (buf->state == UVC_BUF_STATE_READY)
572 buf->state == UVC_BUF_STATE_ERROR)
573 buf = uvc_queue_next_buffer(&stream->queue, buf); 572 buf = uvc_queue_next_buffer(&stream->queue, buf);
574 } 573 }
575} 574}
@@ -627,8 +626,7 @@ static void uvc_video_decode_bulk(struct urb *urb, struct uvc_streaming *stream,
627 if (!stream->bulk.skip_payload && buf != NULL) { 626 if (!stream->bulk.skip_payload && buf != NULL) {
628 uvc_video_decode_end(stream, buf, stream->bulk.header, 627 uvc_video_decode_end(stream, buf, stream->bulk.header,
629 stream->bulk.payload_size); 628 stream->bulk.payload_size);
630 if (buf->state == UVC_BUF_STATE_DONE || 629 if (buf->state == UVC_BUF_STATE_READY)
631 buf->state == UVC_BUF_STATE_ERROR)
632 buf = uvc_queue_next_buffer(&stream->queue, 630 buf = uvc_queue_next_buffer(&stream->queue,
633 buf); 631 buf);
634 } 632 }
@@ -669,7 +667,7 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream,
669 stream->bulk.payload_size == stream->bulk.max_payload_size) { 667 stream->bulk.payload_size == stream->bulk.max_payload_size) {
670 if (buf->buf.bytesused == stream->queue.buf_used) { 668 if (buf->buf.bytesused == stream->queue.buf_used) {
671 stream->queue.buf_used = 0; 669 stream->queue.buf_used = 0;
672 buf->state = UVC_BUF_STATE_DONE; 670 buf->state = UVC_BUF_STATE_READY;
673 uvc_queue_next_buffer(&stream->queue, buf); 671 uvc_queue_next_buffer(&stream->queue, buf);
674 stream->last_fid ^= UVC_STREAM_FID; 672 stream->last_fid ^= UVC_STREAM_FID;
675 } 673 }
@@ -924,10 +922,8 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
924static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) 922static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
925{ 923{
926 struct usb_interface *intf = stream->intf; 924 struct usb_interface *intf = stream->intf;
927 struct usb_host_interface *alts; 925 struct usb_host_endpoint *ep;
928 struct usb_host_endpoint *ep = NULL; 926 unsigned int i;
929 int intfnum = stream->intfnum;
930 unsigned int bandwidth, psize, i;
931 int ret; 927 int ret;
932 928
933 stream->last_fid = -1; 929 stream->last_fid = -1;
@@ -936,6 +932,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
936 stream->bulk.payload_size = 0; 932 stream->bulk.payload_size = 0;
937 933
938 if (intf->num_altsetting > 1) { 934 if (intf->num_altsetting > 1) {
935 struct usb_host_endpoint *best_ep = NULL;
936 unsigned int best_psize = 3 * 1024;
937 unsigned int bandwidth;
938 unsigned int uninitialized_var(altsetting);
939 int intfnum = stream->intfnum;
940
939 /* Isochronous endpoint, select the alternate setting. */ 941 /* Isochronous endpoint, select the alternate setting. */
940 bandwidth = stream->ctrl.dwMaxPayloadTransferSize; 942 bandwidth = stream->ctrl.dwMaxPayloadTransferSize;
941 943
@@ -949,6 +951,9 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
949 } 951 }
950 952
951 for (i = 0; i < intf->num_altsetting; ++i) { 953 for (i = 0; i < intf->num_altsetting; ++i) {
954 struct usb_host_interface *alts;
955 unsigned int psize;
956
952 alts = &intf->altsetting[i]; 957 alts = &intf->altsetting[i];
953 ep = uvc_find_endpoint(alts, 958 ep = uvc_find_endpoint(alts,
954 stream->header.bEndpointAddress); 959 stream->header.bEndpointAddress);
@@ -958,21 +963,27 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
958 /* Check if the bandwidth is high enough. */ 963 /* Check if the bandwidth is high enough. */
959 psize = le16_to_cpu(ep->desc.wMaxPacketSize); 964 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
960 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); 965 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
961 if (psize >= bandwidth) 966 if (psize >= bandwidth && psize <= best_psize) {
962 break; 967 altsetting = i;
968 best_psize = psize;
969 best_ep = ep;
970 }
963 } 971 }
964 972
965 if (i >= intf->num_altsetting) { 973 if (best_ep == NULL) {
966 uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " 974 uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting "
967 "for requested bandwidth.\n"); 975 "for requested bandwidth.\n");
968 return -EIO; 976 return -EIO;
969 } 977 }
970 978
971 ret = usb_set_interface(stream->dev->udev, intfnum, i); 979 uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u "
980 "(%u B/frame bandwidth).\n", altsetting, best_psize);
981
982 ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);
972 if (ret < 0) 983 if (ret < 0)
973 return ret; 984 return ret;
974 985
975 ret = uvc_init_video_isoc(stream, ep, gfp_flags); 986 ret = uvc_init_video_isoc(stream, best_ep, gfp_flags);
976 } else { 987 } else {
977 /* Bulk endpoint, proceed to URB initialization. */ 988 /* Bulk endpoint, proceed to URB initialization. */
978 ep = uvc_find_endpoint(&intf->altsetting[0], 989 ep = uvc_find_endpoint(&intf->altsetting[0],