* [PATCH v2] media: uvc: limit max bandwidth for HDMI capture
@ 2021-06-22 8:29 Mauro Carvalho Chehab
0 siblings, 0 replies; only message in thread
From: Mauro Carvalho Chehab @ 2021-06-22 8:29 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab,
Mauro Carvalho Chehab, linux-kernel, linux-media
This device:
534d:2109 MacroSilicon
Announces that it supports several frame intervals for
their resolutions for MJPEG compression:
VideoStreaming Interface Descriptor:
bLength 46
bDescriptorType 36
bDescriptorSubtype 7 (FRAME_MJPEG)
bFrameIndex 1
bmCapabilities 0x00
Still image unsupported
wWidth 1920
wHeight 1080
dwMinBitRate 768000
dwMaxBitRate 196608000
dwMaxVideoFrameBufferSize 4147200
dwDefaultFrameInterval 166666
bFrameIntervalType 5
dwFrameInterval( 0) 166666
dwFrameInterval( 1) 333333
dwFrameInterval( 2) 400000
dwFrameInterval( 3) 500000
dwFrameInterval( 4) 1000000
However, the highest frame interval (166666), which means 60 fps
is not supported. If set to it, URB packages will be dropped,
causing JPEG decoding errors and part of the video frames will
be missed.
Also, as specified at the device's documentation, for such
resolution, the maximum interval is 30 fps (interval == 333333).
The last format that supports such frame interval is 1280x720.
Add a quirk to estimate a raw bandwidth, by doing:
width * height * framerate
E. g.:
1920 * 1080 * 30 = 62208000
if the bandwidth is greater than such threshold, get
the next value from the dwFrameInterval.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
drivers/media/usb/uvc/uvc_driver.c | 14 ++++++++++++++
drivers/media/usb/uvc/uvc_video.c | 30 +++++++++++++++++++++++++++---
drivers/media/usb/uvc/uvcvideo.h | 1 +
3 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 30ef2a3110f7..bb66e71b3064 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -2615,6 +2615,11 @@ static const struct uvc_device_info uvc_quirk_fix_bandwidth = {
.quirks = UVC_QUIRK_FIX_BANDWIDTH,
};
+static const struct uvc_device_info uvc_quirk_fix_bw_622 = {
+ .quirks = UVC_QUIRK_FIX_BANDWIDTH,
+ .max_bandwidth = 62208000,
+};
+
static const struct uvc_device_info uvc_quirk_probe_def = {
.quirks = UVC_QUIRK_PROBE_DEF,
};
@@ -2830,6 +2835,15 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = (kernel_ulong_t)&uvc_quirk_fix_bandwidth },
+ /* MacroSilicon HDMI capture */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x534d,
+ .idProduct = 0x2109,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = (kernel_ulong_t)&uvc_quirk_fix_bw_622 },
/* Genesys Logic USB 2.0 PC Camera */
{ .match_flags = USB_DEVICE_ID_MATCH_DEVICE
| USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index f2f565281e63..84edaa7cc24d 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -162,9 +162,33 @@ static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
if ((ctrl->dwMaxPayloadTransferSize & 0xffff0000) == 0xffff0000)
ctrl->dwMaxPayloadTransferSize &= ~0xffff0000;
- if (!(format->flags & UVC_FMT_FLAG_COMPRESSED) &&
- stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH &&
- stream->intf->num_altsetting > 1) {
+
+ if (!(stream->dev->quirks & UVC_QUIRK_FIX_BANDWIDTH))
+ return;
+
+ /* Handle UVC_QUIRK_FIX_BANDWIDTH */
+
+ if (format->flags & UVC_FMT_FLAG_COMPRESSED) {
+ u32 bandwidth;
+
+ if (!stream->dev->info->max_bandwidth || !frame->bFrameIntervalType)
+ return;
+
+ for (i = 0; i < frame->bFrameIntervalType; ++i) {
+ bandwidth = frame->wWidth * frame->wHeight;
+ bandwidth *= 10000000 / frame->dwFrameInterval[i];
+
+ if (bandwidth <= stream->dev->info->max_bandwidth)
+ break;
+ }
+
+ if (ctrl->dwFrameInterval < frame->dwFrameInterval[i])
+ ctrl->dwFrameInterval = frame->dwFrameInterval[i];
+
+ return;
+ }
+
+ if (stream->intf->num_altsetting > 1) {
u32 interval;
u32 bandwidth;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 97df5ecd66c9..f1c34225d896 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -658,6 +658,7 @@ static inline u32 uvc_urb_index(const struct uvc_urb *uvc_urb)
struct uvc_device_info {
u32 quirks;
+ u32 max_bandwidth;
u32 meta_format;
u16 uvc_version;
};
--
2.31.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2021-06-22 8:29 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-22 8:29 [PATCH v2] media: uvc: limit max bandwidth for HDMI capture Mauro Carvalho Chehab
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).