summaryrefslogtreecommitdiff
path: root/drivers/media/video/uvc/uvc_video.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@skynet.be>2009-02-16 17:41:52 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 12:42:51 -0300
commit50144aeeb702ea105697ae5249f059ea3990b838 (patch)
treebfc7fedca2655d99094b363ba09934cd6b5aadde /drivers/media/video/uvc/uvc_video.c
parentc90e777976f6237a0cdb644c6a9406907939b174 (diff)
V4L/DVB (10652): uvcvideo: Add quirk to override wrong bandwidth value for Vimicro devices
At least 3 Vimicro cameras (0x332d, 0x3410 and 0x3420) fail to return correct bandwidth information. The first model rounds the value provided by the host to the nearest supported packet size, while the other two always request the maximum bandwidth. Introduce a device quirk to override the value returned by the device with an estimated bandwidth computed by the driver from the frame size and frame rate, and enable it for all Vimicro cameras. Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc/uvc_video.c')
-rw-r--r--drivers/media/video/uvc/uvc_video.c34
1 files changed, 30 insertions, 4 deletions
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 0789ba381fc..a95e17329c5 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: