Commit 50144aee authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

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: default avatarLaurent Pinchart <laurent.pinchart@skynet.be>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent c90e7779
...@@ -1861,6 +1861,15 @@ static struct usb_device_id uvc_ids[] = { ...@@ -1861,6 +1861,15 @@ static struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1, .bInterfaceSubClass = 1,
.bInterfaceProtocol = 0, .bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_STREAM_NO_FID }, .driver_info = UVC_QUIRK_STREAM_NO_FID },
/* ViMicro */
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
| USB_DEVICE_ID_MATCH_INT_INFO,
.idVendor = 0x0ac8,
.idProduct = 0x0000,
.bInterfaceClass = USB_CLASS_VIDEO,
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_FIX_BANDWIDTH },
/* MT6227 */ /* MT6227 */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO, | USB_DEVICE_ID_MATCH_INT_INFO,
......
...@@ -61,7 +61,7 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, ...@@ -61,7 +61,7 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit,
return 0; 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_streaming_control *ctrl)
{ {
struct uvc_format *format; struct uvc_format *format;
...@@ -84,6 +84,31 @@ static void uvc_fixup_buffer_size(struct uvc_video_device *video, ...@@ -84,6 +84,31 @@ static void uvc_fixup_buffer_size(struct uvc_video_device *video,
video->dev->uvc_version < 0x0110)) video->dev->uvc_version < 0x0110))
ctrl->dwMaxVideoFrameSize = ctrl->dwMaxVideoFrameSize =
frame->dwMaxVideoFrameBufferSize; 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, 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, ...@@ -158,10 +183,11 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video,
ctrl->bMaxVersion = 0; ctrl->bMaxVersion = 0;
} }
/* Some broken devices return a null or wrong dwMaxVideoFrameSize. /* Some broken devices return null or wrong dwMaxVideoFrameSize and
* Try to get the value from the format and frame descriptors. * 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; ret = 0;
out: out:
......
...@@ -314,6 +314,7 @@ struct uvc_xu_control { ...@@ -314,6 +314,7 @@ struct uvc_xu_control {
#define UVC_QUIRK_STREAM_NO_FID 0x00000010 #define UVC_QUIRK_STREAM_NO_FID 0x00000010
#define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020 #define UVC_QUIRK_IGNORE_SELECTOR_UNIT 0x00000020
#define UVC_QUIRK_PRUNE_CONTROLS 0x00000040 #define UVC_QUIRK_PRUNE_CONTROLS 0x00000040
#define UVC_QUIRK_FIX_BANDWIDTH 0x00000080
/* Format flags */ /* Format flags */
#define UVC_FMT_FLAG_COMPRESSED 0x00000001 #define UVC_FMT_FLAG_COMPRESSED 0x00000001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment