summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2012-07-17 08:58:48 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-08-13 15:47:56 -0300
commit6fd90db8df379e215f2d495d0b4f3d2553c00277 (patch)
tree5bdbf0da46589b4b3c2946e9a28bd15b584736be /drivers/media/video/uvc
parentda2cd767f537082be0a02d83f87e0da4270e25b2 (diff)
[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 <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r--drivers/media/video/uvc/uvc_video.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 7ac4347ca09..1c15b4227bd 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -1439,6 +1439,26 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
}
/*
+ * 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;