diff mbox series

media: uvc: limit max bandwidth for HDMI capture

Message ID b791d5874c83663505cbd4f74907ac38d00bb727.1612206534.git.mchehab+huawei@kernel.org
State New
Headers show
Series media: uvc: limit max bandwidth for HDMI capture | expand

Commit Message

Mauro Carvalho Chehab Feb. 1, 2021, 7:08 p.m. UTC
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. For such resolution, the maximum interval
is, instead 333333 (30 fps).

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 | 15 +++++++++++++++
 drivers/media/usb/uvc/uvc_video.c  | 26 +++++++++++++++++++++++---
 drivers/media/usb/uvc/uvcvideo.h   |  2 ++
 3 files changed, 40 insertions(+), 3 deletions(-)

Comments

Laurent Pinchart June 21, 2021, 6:22 p.m. UTC | #1
Hi Mauro,

Thank you for the patch.

On Mon, Feb 01, 2021 at 08:08:59PM +0100, Mauro Carvalho Chehab wrote:
> 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. For such resolution, the maximum interval

> is, instead 333333 (30 fps).


What happens if you try to select it ?

> 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 | 15 +++++++++++++++

>  drivers/media/usb/uvc/uvc_video.c  | 26 +++++++++++++++++++++++---

>  drivers/media/usb/uvc/uvcvideo.h   |  2 ++

>  3 files changed, 40 insertions(+), 3 deletions(-)

> 

> diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c

> index 1abc122a0977..c83a329f6527 100644

> --- a/drivers/media/usb/uvc/uvc_driver.c

> +++ b/drivers/media/usb/uvc/uvc_driver.c

> @@ -2339,6 +2339,7 @@ static int uvc_probe(struct usb_interface *intf,

>  	dev->info = info ? info : &uvc_quirk_none;

>  	dev->quirks = uvc_quirks_param == -1

>  		    ? dev->info->quirks : uvc_quirks_param;

> +	dev->max_bandwidth = dev->info->max_bandwidth;

>  

>  	if (id->idVendor && id->idProduct)

>  		uvc_dbg(dev, PROBE, "Probing known UVC device %s (%04x:%04x)\n",

> @@ -2615,6 +2616,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 +2836,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..4afc1fbe0801 100644

> --- a/drivers/media/usb/uvc/uvc_video.c

> +++ b/drivers/media/usb/uvc/uvc_video.c

> @@ -162,9 +162,29 @@ 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 &&

> +	    stream->dev->max_bandwidth && frame->bFrameIntervalType) {

> +		u32 bandwidth;

> +

> +		for (i = 0; i < frame->bFrameIntervalType - 1; ++i) {


Why - 1 ?

> +			bandwidth = frame->wWidth * frame->wHeight;

> +			bandwidth *= 10000000 / frame->dwFrameInterval[i];

> +

> +			if (bandwidth <= stream->dev->max_bandwidth)

> +				break;

> +		}

> +

> +		ctrl->dwFrameInterval = frame->dwFrameInterval[i];


This doesn't seem correct, you're selecting the first frame internal
below the bandwidth limit, even if the user explicitly requests a lower
frame rate.

> +		return;

> +	}

> +

> +	if (stream->intf->num_altsetting > 1) {


There's an incorrect change in logic here. Before the patch this code
would run only for !UVC_FMT_FLAG_COMPRESSED, while with the patch, it will
run if UVC_FMT_FLAG_COMPRESSED && !(stream->dev->max_bandwidth &&
frame->bFrameIntervalType).

>  		u32 interval;

>  		u32 bandwidth;

>  

> diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h

> index 97df5ecd66c9..b44e0cd4c826 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;

>  };

> @@ -667,6 +668,7 @@ struct uvc_device {

>  	struct usb_interface *intf;

>  	unsigned long warnings;

>  	u32 quirks;

> +	u32 max_bandwidth;


uvc_device has a uvc_device_info pointer, there's no need to copy the
field here.

>  	int intfnum;

>  	char name[32];

>  


-- 
Regards,

Laurent Pinchart
Mauro Carvalho Chehab June 22, 2021, 8:29 a.m. UTC | #2
Em Mon, 21 Jun 2021 21:22:26 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> escreveu:

> Hi Mauro,

> 

> Thank you for the patch.


Thanks for reviewing it!

> 

> On Mon, Feb 01, 2021 at 08:08:59PM +0100, Mauro Carvalho Chehab wrote:

> > 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. For such resolution, the maximum interval

> > is, instead 333333 (30 fps).  

> 

> What happens if you try to select it ?


Basically, URBs get lost: they cause apps like qv4l2 to crash
sometimes, with:

	v4l-convert: libjpeg error: Corrupt JPEG data: premature end of data segment

The image keeps blinking, and part of the image is replaced by
white noise.

Clearly, it tries to send more data than the maximum available bandwidth
on this chipset.


Sent a v2 addressing the issues you pointed.


Thanks,
Mauro
Dave Stevenson June 22, 2021, 8:50 a.m. UTC | #3
Hi Mauro

On Tue, 22 Jun 2021 at 09:29, Mauro Carvalho Chehab
<mchehab+huawei@kernel.org> wrote:
>

> Em Mon, 21 Jun 2021 21:22:26 +0300

> Laurent Pinchart <laurent.pinchart@ideasonboard.com> escreveu:

>

> > Hi Mauro,

> >

> > Thank you for the patch.

>

> Thanks for reviewing it!

>

> >

> > On Mon, Feb 01, 2021 at 08:08:59PM +0100, Mauro Carvalho Chehab wrote:

> > > 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. For such resolution, the maximum interval

> > > is, instead 333333 (30 fps).

> >

> > What happens if you try to select it ?

>

> Basically, URBs get lost: they cause apps like qv4l2 to crash

> sometimes, with:

>

>         v4l-convert: libjpeg error: Corrupt JPEG data: premature end of data segment

>

> The image keeps blinking, and part of the image is replaced by

> white noise.

>

> Clearly, it tries to send more data than the maximum available bandwidth

> on this chipset.


What platform are you running this on?
I've previously encountered a USB3 camera module where the datastream
was VERY bursty. The memcpy of the data from URB to V4L2 buffer took
long enough that sometimes the module didn't have an URB to fill at
the appropriate moment, and it dropped data. I seem to recall
increasing UVC_URBS from the default of 5 to 10 to handle the peak
data rate without loss, but it may have been higher still. This was on
a ~1.5GHz Atom processor, so not lacking in performance.

I wonder if the same is true in your case. If it's MJPEG compressed
then the peak rate may again be high. Just a thought.

  Dave

> Sent a v2 addressing the issues you pointed.

>

>

> Thanks,

> Mauro
Laurent Pinchart June 22, 2021, 8:59 a.m. UTC | #4
On Tue, Jun 22, 2021 at 09:50:37AM +0100, Dave Stevenson wrote:
> On Tue, 22 Jun 2021 at 09:29, Mauro Carvalho Chehab wrote:

> > Em Mon, 21 Jun 2021 21:22:26 +0300 Laurent Pinchart escreveu:

> >

> > > Hi Mauro,

> > >

> > > Thank you for the patch.

> >

> > Thanks for reviewing it!

> >

> > >

> > > On Mon, Feb 01, 2021 at 08:08:59PM +0100, Mauro Carvalho Chehab wrote:

> > > > 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. For such resolution, the maximum interval

> > > > is, instead 333333 (30 fps).

> > >

> > > What happens if you try to select it ?

> >

> > Basically, URBs get lost: they cause apps like qv4l2 to crash

> > sometimes, with:

> >

> >         v4l-convert: libjpeg error: Corrupt JPEG data: premature end of data segment

> >

> > The image keeps blinking, and part of the image is replaced by

> > white noise.

> >

> > Clearly, it tries to send more data than the maximum available bandwidth

> > on this chipset.

> 

> What platform are you running this on?

> I've previously encountered a USB3 camera module where the datastream

> was VERY bursty. The memcpy of the data from URB to V4L2 buffer took

> long enough that sometimes the module didn't have an URB to fill at

> the appropriate moment, and it dropped data. I seem to recall

> increasing UVC_URBS from the default of 5 to 10 to handle the peak

> data rate without loss, but it may have been higher still. This was on

> a ~1.5GHz Atom processor, so not lacking in performance.

> 

> I wonder if the same is true in your case. If it's MJPEG compressed

> then the peak rate may again be high. Just a thought.


It's worth investigating indeed. How often are URBs dropped ? Does it
occur for every frame, or once in a while ?

> > Sent a v2 addressing the issues you pointed.


-- 
Regards,

Laurent Pinchart
Mauro Carvalho Chehab June 22, 2021, 9:09 a.m. UTC | #5
Em Tue, 22 Jun 2021 11:59:10 +0300
Laurent Pinchart <laurent.pinchart@ideasonboard.com> escreveu:

> On Tue, Jun 22, 2021 at 09:50:37AM +0100, Dave Stevenson wrote:

> > On Tue, 22 Jun 2021 at 09:29, Mauro Carvalho Chehab wrote:  

> > > Em Mon, 21 Jun 2021 21:22:26 +0300 Laurent Pinchart escreveu:

> > >  

> > > > Hi Mauro,

> > > >

> > > > Thank you for the patch.  

> > >

> > > Thanks for reviewing it!

> > >  

> > > >

> > > > On Mon, Feb 01, 2021 at 08:08:59PM +0100, Mauro Carvalho Chehab wrote:  

> > > > > 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. For such resolution, the maximum interval

> > > > > is, instead 333333 (30 fps).  

> > > >

> > > > What happens if you try to select it ?  

> > >

> > > Basically, URBs get lost: they cause apps like qv4l2 to crash

> > > sometimes, with:

> > >

> > >         v4l-convert: libjpeg error: Corrupt JPEG data: premature end of data segment

> > >

> > > The image keeps blinking, and part of the image is replaced by

> > > white noise.

> > >

> > > Clearly, it tries to send more data than the maximum available bandwidth

> > > on this chipset.  

> > 

> > What platform are you running this on?

> > I've previously encountered a USB3 camera module where the datastream

> > was VERY bursty. The memcpy of the data from URB to V4L2 buffer took

> > long enough that sometimes the module didn't have an URB to fill at

> > the appropriate moment, and it dropped data. I seem to recall

> > increasing UVC_URBS from the default of 5 to 10 to handle the peak

> > data rate without loss, but it may have been higher still. This was on

> > a ~1.5GHz Atom processor, so not lacking in performance.

> > 

> > I wonder if the same is true in your case. If it's MJPEG compressed

> > then the peak rate may again be high. Just a thought.  

> 

> It's worth investigating indeed. How often are URBs dropped ? Does it

> occur for every frame, or once in a while ?


It occurs on every frame. Monitoring the traffic with usbtop shows
that about the same amount of data is shown when selecting 30 or 60
fps.

Btw, the manual of the device clearly says that it supports only 30
fps at the maximum resolution.

What's happening is that the USB descriptors are not correct.

Btw, this is the device:

	https://www.amazon.de/-/en/gp/product/B088NWWSKN

I'm basically using it (together with a Logitech nano receiver) as
a cheap KVM device :-)

Thanks,
Mauro
Nicolas Dufresne June 25, 2021, 7:18 p.m. UTC | #6
Le mardi 22 juin 2021 à 10:29 +0200, Mauro Carvalho Chehab a écrit :
> Em Mon, 21 Jun 2021 21:22:26 +0300

> Laurent Pinchart <laurent.pinchart@ideasonboard.com> escreveu:

> 

> > Hi Mauro,

> > 

> > Thank you for the patch.

> 

> Thanks for reviewing it!

> 

> > 

> > On Mon, Feb 01, 2021 at 08:08:59PM +0100, Mauro Carvalho Chehab wrote:

> > > 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. For such resolution, the maximum interval

> > > is, instead 333333 (30 fps).  

> > 

> > What happens if you try to select it ?

> 

> Basically, URBs get lost: they cause apps like qv4l2 to crash

> sometimes, with:

> 

> 	v4l-convert: libjpeg error: Corrupt JPEG data: premature end of data segment


This is the emulated format handler that decodes jpeg behind application back
that is broken. The converter should implement this in a nicer way. E.g. it
could return ERROR buffer with payload = 0 in that case.

> 

> The image keeps blinking, and part of the image is replaced by

> white noise.

> 

> Clearly, it tries to send more data than the maximum available bandwidth

> on this chipset.

> 

> 

> Sent a v2 addressing the issues you pointed.

> 

> 

> Thanks,

> Mauro
diff mbox series

Patch

diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 1abc122a0977..c83a329f6527 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -2339,6 +2339,7 @@  static int uvc_probe(struct usb_interface *intf,
 	dev->info = info ? info : &uvc_quirk_none;
 	dev->quirks = uvc_quirks_param == -1
 		    ? dev->info->quirks : uvc_quirks_param;
+	dev->max_bandwidth = dev->info->max_bandwidth;
 
 	if (id->idVendor && id->idProduct)
 		uvc_dbg(dev, PROBE, "Probing known UVC device %s (%04x:%04x)\n",
@@ -2615,6 +2616,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 +2836,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..4afc1fbe0801 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -162,9 +162,29 @@  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 &&
+	    stream->dev->max_bandwidth && frame->bFrameIntervalType) {
+		u32 bandwidth;
+
+		for (i = 0; i < frame->bFrameIntervalType - 1; ++i) {
+			bandwidth = frame->wWidth * frame->wHeight;
+			bandwidth *= 10000000 / frame->dwFrameInterval[i];
+
+			if (bandwidth <= stream->dev->max_bandwidth)
+				break;
+		}
+
+		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..b44e0cd4c826 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;
 };
@@ -667,6 +668,7 @@  struct uvc_device {
 	struct usb_interface *intf;
 	unsigned long warnings;
 	u32 quirks;
+	u32 max_bandwidth;
 	int intfnum;
 	char name[32];