aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/uvc/uvc_video.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 9a9802830d41..e8cc0a9ddadd 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -924,10 +924,8 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
924static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) 924static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
925{ 925{
926 struct usb_interface *intf = stream->intf; 926 struct usb_interface *intf = stream->intf;
927 struct usb_host_interface *alts; 927 struct usb_host_endpoint *ep;
928 struct usb_host_endpoint *ep = NULL; 928 unsigned int i;
929 int intfnum = stream->intfnum;
930 unsigned int bandwidth, psize, i;
931 int ret; 929 int ret;
932 930
933 stream->last_fid = -1; 931 stream->last_fid = -1;
@@ -936,6 +934,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
936 stream->bulk.payload_size = 0; 934 stream->bulk.payload_size = 0;
937 935
938 if (intf->num_altsetting > 1) { 936 if (intf->num_altsetting > 1) {
937 struct usb_host_endpoint *best_ep = NULL;
938 unsigned int best_psize = 3 * 1024;
939 unsigned int bandwidth;
940 unsigned int uninitialized_var(altsetting);
941 int intfnum = stream->intfnum;
942
939 /* Isochronous endpoint, select the alternate setting. */ 943 /* Isochronous endpoint, select the alternate setting. */
940 bandwidth = stream->ctrl.dwMaxPayloadTransferSize; 944 bandwidth = stream->ctrl.dwMaxPayloadTransferSize;
941 945
@@ -949,6 +953,9 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
949 } 953 }
950 954
951 for (i = 0; i < intf->num_altsetting; ++i) { 955 for (i = 0; i < intf->num_altsetting; ++i) {
956 struct usb_host_interface *alts;
957 unsigned int psize;
958
952 alts = &intf->altsetting[i]; 959 alts = &intf->altsetting[i];
953 ep = uvc_find_endpoint(alts, 960 ep = uvc_find_endpoint(alts,
954 stream->header.bEndpointAddress); 961 stream->header.bEndpointAddress);
@@ -958,21 +965,27 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
958 /* Check if the bandwidth is high enough. */ 965 /* Check if the bandwidth is high enough. */
959 psize = le16_to_cpu(ep->desc.wMaxPacketSize); 966 psize = le16_to_cpu(ep->desc.wMaxPacketSize);
960 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); 967 psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
961 if (psize >= bandwidth) 968 if (psize >= bandwidth && psize <= best_psize) {
962 break; 969 altsetting = i;
970 best_psize = psize;
971 best_ep = ep;
972 }
963 } 973 }
964 974
965 if (i >= intf->num_altsetting) { 975 if (best_ep == NULL) {
966 uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting " 976 uvc_trace(UVC_TRACE_VIDEO, "No fast enough alt setting "
967 "for requested bandwidth.\n"); 977 "for requested bandwidth.\n");
968 return -EIO; 978 return -EIO;
969 } 979 }
970 980
971 ret = usb_set_interface(stream->dev->udev, intfnum, i); 981 uvc_trace(UVC_TRACE_VIDEO, "Selecting alternate setting %u "
982 "(%u B/frame bandwidth).\n", altsetting, best_psize);
983
984 ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);
972 if (ret < 0) 985 if (ret < 0)
973 return ret; 986 return ret;
974 987
975 ret = uvc_init_video_isoc(stream, ep, gfp_flags); 988 ret = uvc_init_video_isoc(stream, best_ep, gfp_flags);
976 } else { 989 } else {
977 /* Bulk endpoint, proceed to URB initialization. */ 990 /* Bulk endpoint, proceed to URB initialization. */
978 ep = uvc_find_endpoint(&intf->altsetting[0], 991 ep = uvc_find_endpoint(&intf->altsetting[0],