UPSTREAM: [media] uvcvideo: Support super speed endpoints
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Tue, 17 Jul 2012 11:58:48 +0000 (08:58 -0300)
committerChromeBot <chrome-bot@google.com>
Thu, 4 Apr 2013 23:32:14 +0000 (16:32 -0700)
Compute the maximum number of bytes per interval using the burst and
multiplier values for super speed endpoints.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
(cherry picked from commit 6fd90db8df379e215f2d495d0b4f3d2553c00277)

BUG=chrome-os-partner:18460
TEST=None

Change-Id: I0ad74ce6edb7316e51a7f5fb7f1d41b4f6e3880c
Reviewed-on: https://gerrit.chromium.org/gerrit/47318
Tested-by: Julius Werner <jwerner@chromium.org>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Pawel Osciak <posciak@chromium.org>
Commit-Queue: Julius Werner <jwerner@chromium.org>

drivers/media/video/uvc/uvc_video.c

index b76b0ac..20566e0 100644 (file)
@@ -1434,6 +1434,26 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
                uvc_free_urb_buffers(stream);
 }
 
+/*
+ * Compute the maximum number of bytes per interval for an endpoint.
+ */
+static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev,
+                                        struct usb_host_endpoint *ep)
+{
+       u16 psize;
+
+       switch (dev->speed) {
+       case USB_SPEED_SUPER:
+               return ep->ss_ep_comp.wBytesPerInterval;
+       case USB_SPEED_HIGH:
+               psize = usb_endpoint_maxp(&ep->desc);
+               return (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+       default:
+               psize = usb_endpoint_maxp(&ep->desc);
+               return psize & 0x07ff;
+       }
+}
+
 /*
  * Initialize isochronous URBs and allocate transfer buffers. The packet size
  * is given by the endpoint.
@@ -1446,8 +1466,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
        u16 psize;
        u32 size;
 
-       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
-       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+       psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);
        size = stream->ctrl.dwMaxVideoFrameSize;
 
        npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);
@@ -1502,7 +1521,7 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
        u16 psize;
        u32 size;
 
-       psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff;
+       psize = usb_endpoint_maxp(&ep->desc) & 0x7ff;
        size = stream->ctrl.dwMaxPayloadTransferSize;
        stream->bulk.max_payload_size = size;
 
@@ -1563,7 +1582,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
 
        if (intf->num_altsetting > 1) {
                struct usb_host_endpoint *best_ep = NULL;
-               unsigned int best_psize = 3 * 1024;
+               unsigned int best_psize = UINT_MAX;
                unsigned int bandwidth;
                unsigned int uninitialized_var(altsetting);
                int intfnum = stream->intfnum;
@@ -1591,8 +1610,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
                                continue;
 
                        /* Check if the bandwidth is high enough. */
-                       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
-                       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+                       psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);
                        if (psize >= bandwidth && psize <= best_psize) {
                                altsetting = i;
                                best_psize = psize;