diff options
Diffstat (limited to 'drivers/media/video/uvc/uvc_video.c')
-rw-r--r-- | drivers/media/video/uvc/uvc_video.c | 133 |
1 files changed, 88 insertions, 45 deletions
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 9bc4705be78d..a95e17329c5b 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c @@ -61,7 +61,7 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, return 0; } -static void uvc_fixup_buffer_size(struct uvc_video_device *video, +static void uvc_fixup_video_ctrl(struct uvc_video_device *video, struct uvc_streaming_control *ctrl) { struct uvc_format *format; @@ -84,6 +84,31 @@ static void uvc_fixup_buffer_size(struct uvc_video_device *video, video->dev->uvc_version < 0x0110)) ctrl->dwMaxVideoFrameSize = frame->dwMaxVideoFrameBufferSize; + + if (video->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH && + video->streaming->intf->num_altsetting > 1) { + u32 interval; + u32 bandwidth; + + interval = (ctrl->dwFrameInterval > 100000) + ? ctrl->dwFrameInterval + : frame->dwFrameInterval[0]; + + /* Compute a bandwidth estimation by multiplying the frame + * size by the number of video frames per second, divide the + * result by the number of USB frames (or micro-frames for + * high-speed devices) per second and add the UVC header size + * (assumed to be 12 bytes long). + */ + bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp; + bandwidth *= 10000000 / interval + 1; + bandwidth /= 1000; + if (video->dev->udev->speed == USB_SPEED_HIGH) + bandwidth /= 8; + bandwidth += 12; + + ctrl->dwMaxPayloadTransferSize = bandwidth; + } } static int uvc_get_video_ctrl(struct uvc_video_device *video, @@ -158,10 +183,11 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, ctrl->bMaxVersion = 0; } - /* Some broken devices return a null or wrong dwMaxVideoFrameSize. - * Try to get the value from the format and frame descriptors. + /* Some broken devices return null or wrong dwMaxVideoFrameSize and + * dwMaxPayloadTransferSize fields. Try to get the value from the + * format and frame descriptors. */ - uvc_fixup_buffer_size(video, ctrl); + uvc_fixup_video_ctrl(video, ctrl); ret = 0; out: @@ -540,6 +566,9 @@ static void uvc_video_decode_bulk(struct urb *urb, u8 *mem; int len, ret; + if (urb->actual_length == 0) + return; + mem = urb->transfer_buffer; len = urb->actual_length; video->bulk.payload_size += len; @@ -699,27 +728,47 @@ static void uvc_free_urb_buffers(struct uvc_video_device *video) * already allocated when resuming from suspend, in which case it will * return without touching the buffers. * - * Return 0 on success or -ENOMEM when out of memory. + * Limit the buffer size to UVC_MAX_PACKETS bulk/isochronous packets. If the + * system is too low on memory try successively smaller numbers of packets + * until allocation succeeds. + * + * Return the number of allocated packets on success or 0 when out of memory. */ static int uvc_alloc_urb_buffers(struct uvc_video_device *video, - unsigned int size) + unsigned int size, unsigned int psize, gfp_t gfp_flags) { + unsigned int npackets; unsigned int i; /* Buffers are already allocated, bail out. */ if (video->urb_size) return 0; - for (i = 0; i < UVC_URBS; ++i) { - video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev, - size, GFP_KERNEL, &video->urb_dma[i]); - if (video->urb_buffer[i] == NULL) { - uvc_free_urb_buffers(video); - return -ENOMEM; + /* Compute the number of packets. Bulk endpoints might transfer UVC + * payloads accross multiple URBs. + */ + npackets = DIV_ROUND_UP(size, psize); + if (npackets > UVC_MAX_PACKETS) + npackets = UVC_MAX_PACKETS; + + /* Retry allocations until one succeed. */ + for (; npackets > 1; npackets /= 2) { + for (i = 0; i < UVC_URBS; ++i) { + video->urb_buffer[i] = usb_buffer_alloc( + video->dev->udev, psize * npackets, + gfp_flags | __GFP_NOWARN, &video->urb_dma[i]); + if (!video->urb_buffer[i]) { + uvc_free_urb_buffers(video); + break; + } + } + + if (i == UVC_URBS) { + video->urb_size = psize * npackets; + return npackets; } } - video->urb_size = size; return 0; } @@ -753,29 +802,19 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, { struct urb *urb; unsigned int npackets, i, j; - __u16 psize; - __u32 size; + u16 psize; + u32 size; - /* Compute the number of isochronous packets to allocate by dividing - * the maximum video frame size by the packet size. Limit the result - * to UVC_MAX_ISO_PACKETS. - */ psize = le16_to_cpu(ep->desc.wMaxPacketSize); psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); - size = video->streaming->ctrl.dwMaxVideoFrameSize; - if (size > UVC_MAX_FRAME_SIZE) - return -EINVAL; - npackets = DIV_ROUND_UP(size, psize); - if (npackets > UVC_MAX_ISO_PACKETS) - npackets = UVC_MAX_ISO_PACKETS; + npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); + if (npackets == 0) + return -ENOMEM; size = npackets * psize; - if (uvc_alloc_urb_buffers(video, size) < 0) - return -ENOMEM; - for (i = 0; i < UVC_URBS; ++i) { urb = usb_alloc_urb(npackets, gfp_flags); if (urb == NULL) { @@ -814,25 +853,20 @@ static int uvc_init_video_bulk(struct uvc_video_device *video, struct usb_host_endpoint *ep, gfp_t gfp_flags) { struct urb *urb; - unsigned int pipe, i; - __u16 psize; - __u32 size; - - /* Compute the bulk URB size. Some devices set the maximum payload - * size to a value too high for memory-constrained devices. We must - * then transfer the payload accross multiple URBs. To be consistant - * with isochronous mode, allocate maximum UVC_MAX_ISO_PACKETS per bulk - * URB. - */ + unsigned int npackets, pipe, i; + u16 psize; + u32 size; + psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff; size = video->streaming->ctrl.dwMaxPayloadTransferSize; video->bulk.max_payload_size = size; - if (size > psize * UVC_MAX_ISO_PACKETS) - size = psize * UVC_MAX_ISO_PACKETS; - if (uvc_alloc_urb_buffers(video, size) < 0) + npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); + if (npackets == 0) return -ENOMEM; + size = npackets * psize; + if (usb_endpoint_dir_in(&ep->desc)) pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress); @@ -1021,11 +1055,20 @@ int uvc_video_init(struct uvc_video_device *video) */ usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); - /* Some webcams don't suport GET_DEF requests on the probe control. We - * fall back to GET_CUR if GET_DEF fails. + /* Set the streaming probe control with default streaming parameters + * retrieved from the device. Webcams that don't suport GET_DEF + * requests on the probe control will just keep their current streaming + * parameters. + */ + if (uvc_get_video_ctrl(video, probe, 1, GET_DEF) == 0) + uvc_set_video_ctrl(video, probe, 1); + + /* Initialize the streaming parameters with the probe control current + * value. This makes sure SET_CUR requests on the streaming commit + * control will always use values retrieved from a successful GET_CUR + * request on the probe control, as required by the UVC specification. */ - if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_DEF)) < 0 && - (ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) + if ((ret = uvc_get_video_ctrl(video, probe, 1, GET_CUR)) < 0) return ret; /* Check if the default format descriptor exists. Use the first |