From 6fd90db8df379e215f2d495d0b4f3d2553c00277 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 17 Jul 2012 08:58:48 -0300 Subject: [media] uvcvideo: Support super speed endpoints Compute the maximum number of bytes per interval using the burst and multiplier values for super speed endpoints. Signed-off-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/uvc/uvc_video.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers/media') diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 7ac4347ca09e..1c15b4227bdb 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -1438,6 +1438,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. @@ -1450,8 +1470,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); @@ -1506,7 +1525,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; @@ -1567,7 +1586,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; @@ -1595,8 +1614,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 = alts->desc.bAlternateSetting; best_psize = psize; -- cgit v1.2.1