aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@skynet.be>2009-02-16 15:41:52 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:42:51 -0400
commit50144aeeb702ea105697ae5249f059ea3990b838 (patch)
treebfc7fedca2655d99094b363ba09934cd6b5aadde /drivers
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')
-rw-r--r--drivers/media/video/uvc/uvc_driver.c9
-rw-r--r--drivers/media/video/uvc/uvc_video.c34
-rw-r--r--drivers/media/video/uvc/uvcvideo.h1
3 files changed, 40 insertions, 4 deletions
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c
index ebcd5bf0edb7..22e2783ac555 100644
--- a/drivers/media/video/uvc/uvc_driver.c
+++ b/drivers/media/video/uvc/uvc_driver.c
@@ -1861,6 +1861,15 @@ static struct usb_device_id uvc_ids[] = {
1861 .bInterfaceSubClass = 1, 1861 .bInterfaceSubClass = 1,
1862 .bInterfaceProtocol = 0, 1862 .bInterfaceProtocol = 0,
1863 .driver_info = UVC_QUIRK_STREAM_NO_FID }, 1863 .driver_info = UVC_QUIRK_STREAM_NO_FID },
1864 /* ViMicro */
1865 { .match_flags = USB_DEVICE_ID_MATCH_VENDOR
1866 | USB_DEVICE_ID_MATCH_INT_INFO,
1867 .idVendor = 0x0ac8,
1868 .idProduct = 0x0000,
1869 .bInterfaceClass = USB_CLASS_VIDEO,
1870 .bInterfaceSubClass = 1,
1871 .bInterfaceProtocol = 0,
1872 .driver_info = UVC_QUIRK_FIX_BANDWIDTH },
1864 /* MT6227 */ 1873 /* MT6227 */
1865 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE 1874 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
1866 | USB_DEVICE_ID_MATCH_INT_INFO, 1875 | USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 0789ba381fc1..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,
61 return 0; 61 return 0;
62} 62}
63 63
64static void uvc_fixup_buffer_size(struct uvc_video_device *video, 64static void uvc_fixup_video_ctrl(struct uvc_video_device *video,
65 struct uvc_streaming_control *ctrl) 65 struct uvc_streaming_control *ctrl)
66{ 66{
67 struct uvc_format *format; 67 struct uvc_format *format;
@@ -84,6 +84,31 @@ static void uvc_fixup_buffer_size(struct uvc_video_device *video,
84 video->dev->uvc_version < 0x0110)) 84 video->dev->uvc_version < 0x0110))
85 ctrl->dwMaxVideoFrameSize = 85 ctrl->dwMaxVideoFrameSize =
86 frame->dwMaxVideoFrameBufferSize; 86 frame->dwMaxVideoFrameBufferSize;
87
88 if (video->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
89 video->streaming->intf->num_altsetting > 1) {
90 u32 interval;
91 u32 bandwidth;
92
93 interval = (ctrl->dwFrameInterval > 100000)
94 ? ctrl->dwFrameInterval
95 : frame->dwFrameInterval[0];
96
97 /* Compute a bandwidth estimation by multiplying the frame
98 * size by the number of video frames per second, divide the
99 * result by the number of USB frames (or micro-frames for
100 * high-speed devices) per second and add the UVC header size
101 * (assumed to be 12 bytes long).
102 */
103 bandwidth = frame->wWidth * frame->wHeight / 8 * format->bpp;
104 bandwidth *= 10000000 / interval + 1;
105 bandwidth /= 1000;
106 if (video->dev->udev->speed == USB_SPEED_HIGH)
107 bandwidth /= 8;
108 bandwidth += 12;
109
110 ctrl->dwMaxPayloadTransferSize = bandwidth;
111 }
87} 112}
88 113
89static int uvc_get_video_ctrl(struct uvc_video_device *video, 114static 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,
158 ctrl->bMaxVersion = 0; 183 ctrl->bMaxVersion = 0;
159 } 184 }
160 185
161 /* Some broken devices return a null or wrong dwMaxVideoFrameSize. 186 /* Some broken devices return null or wrong dwMaxVideoFrameSize and
162 * Try to get the value from the format and frame descriptors. 187 * dwMaxPayloadTransferSize fields. Try to get the value from the
188 * format and frame descriptors.
163 */ 189 */
164 uvc_fixup_buffer_size(video, ctrl); 190 uvc_fixup_video_ctrl(video, ctrl);
165 ret = 0; 191 ret = 0;
166 192
167out: 193out:
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 6f55c4d49cf4..e5014e668f99 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -314,6 +314,7 @@ struct uvc_xu_control {
314#define UVC_QUIRK_STREAM_NO_FID 0x00000010 314#define UVC_QUIRK_STREAM_NO_FID 0x00000010
315#define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 315#define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020
316#define UVC_QUIRK_PRUNE_CONTROLS 0x00000040 316#define UVC_QUIRK_PRUNE_CONTROLS 0x00000040
317#define UVC_QUIRK_FIX_BANDWIDTH 0x00000080
317 318
318/* Format flags */ 319/* Format flags */
319#define UVC_FMT_FLAG_COMPRESSED 0x00000001 320#define UVC_FMT_FLAG_COMPRESSED 0x00000001