diff options
-rw-r--r-- | drivers/media/video/uvc/uvc_video.c | 31 |
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, | |||
924 | static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) | 924 | static 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], |