media: uvcvideo: Add a quirk to force GEO GC6500 Camera bits-per-pixel value
authorSergey Zakharchenko <szakharchenko@digital-loggers.com>
Thu, 3 Oct 2019 09:31:23 +0000 (11:31 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Thu, 23 Jan 2020 12:16:13 +0000 (13:16 +0100)
This device does not function correctly in raw mode in kernel
versions validating buffer sizes in bulk mode. It erroneously
announces 16 bits per pixel instead of 12 for NV12 format, so it
needs this quirk to fix computed frame size and avoid legitimate
frames getting discarded.

[Move info and div variables to local scope]

Signed-off-by: Sergey Zakharchenko <szakharchenko@digital-loggers.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/usb/uvc/uvc_driver.c
drivers/media/usb/uvc/uvcvideo.h

index 2b688cc39bb816256fa13802b3a07abedcc13aff..99883550375e9c54772b2c4c1f73248dc9f55773 100644 (file)
@@ -497,6 +497,22 @@ static int uvc_parse_format(struct uvc_device *dev,
                        }
                }
 
+               /* Some devices report bpp that doesn't match the format. */
+               if (dev->quirks & UVC_QUIRK_FORCE_BPP) {
+                       const struct v4l2_format_info *info =
+                               v4l2_format_info(format->fcc);
+
+                       if (info) {
+                               unsigned int div = info->hdiv * info->vdiv;
+
+                               n = info->bpp[0] * div;
+                               for (i = 1; i < info->comp_planes; i++)
+                                       n += info->bpp[i];
+
+                               format->bpp = DIV_ROUND_UP(8 * n, div);
+                       }
+               }
+
                if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
                        ftype = UVC_VS_FRAME_UNCOMPRESSED;
                } else {
@@ -2874,6 +2890,15 @@ static const struct usb_device_id uvc_ids[] = {
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0,
          .driver_info          = (kernel_ulong_t)&uvc_quirk_force_y8 },
+       /* GEO Semiconductor GC6500 */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x29fe,
+         .idProduct            = 0x4d53,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_INFO_QUIRK(UVC_QUIRK_FORCE_BPP) },
        /* Intel RealSense D4M */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
index f773dc5d802cd672ca3fc49c6352476ee0e9bbac..6ab972c643e37a95bec5ff0c26b53dfb77c28fc8 100644 (file)
 #define UVC_QUIRK_RESTRICT_FRAME_RATE  0x00000200
 #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT        0x00000400
 #define UVC_QUIRK_FORCE_Y8             0x00000800
+#define UVC_QUIRK_FORCE_BPP            0x00001000
 
 /* Format flags */
 #define UVC_FMT_FLAG_COMPRESSED                0x00000001