| From: ming_qian <ming_qian@realsil.com.cn> |
| Date: Tue, 8 May 2018 22:13:08 -0400 |
| Subject: media: uvcvideo: Support realtek's UVC 1.5 device |
| |
| commit f620d1d7afc7db57ab59f35000752840c91f67e7 upstream. |
| |
| media: uvcvideo: Support UVC 1.5 video probe & commit controls |
| |
| The length of UVC 1.5 video control is 48, and it is 34 for UVC 1.1. |
| Change it to 48 for UVC 1.5 device, and the UVC 1.5 device can be |
| recognized. |
| |
| More changes to the driver are needed for full UVC 1.5 compatibility. |
| However, at least the UVC 1.5 Realtek RTS5847/RTS5852 cameras have been |
| reported to work well. |
| |
| [laurent.pinchart@ideasonboard.com: Factor out code to helper function, update size checks] |
| |
| Signed-off-by: ming_qian <ming_qian@realsil.com.cn> |
| Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> |
| Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com> |
| Tested-by: Ana Guerrero Lopez <ana.guerrero@collabora.com> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> |
| [bwh: Backported to 3.16: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/media/usb/uvc/uvc_video.c | 24 ++++++++++++++++++------ |
| 1 file changed, 18 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/media/usb/uvc/uvc_video.c |
| +++ b/drivers/media/usb/uvc/uvc_video.c |
| @@ -155,14 +155,27 @@ static void uvc_fixup_video_ctrl(struct |
| } |
| } |
| |
| +static size_t uvc_video_ctrl_size(struct uvc_streaming *stream) |
| +{ |
| + /* |
| + * Return the size of the video probe and commit controls, which depends |
| + * on the protocol version. |
| + */ |
| + if (stream->dev->uvc_version < 0x0110) |
| + return 26; |
| + else if (stream->dev->uvc_version < 0x0150) |
| + return 34; |
| + else |
| + return 48; |
| +} |
| + |
| static int uvc_get_video_ctrl(struct uvc_streaming *stream, |
| struct uvc_streaming_control *ctrl, int probe, __u8 query) |
| { |
| + u16 size = uvc_video_ctrl_size(stream); |
| __u8 *data; |
| - __u16 size; |
| int ret; |
| |
| - size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; |
| if ((stream->dev->quirks & UVC_QUIRK_PROBE_DEF) && |
| query == UVC_GET_DEF) |
| return -EIO; |
| @@ -217,7 +230,7 @@ static int uvc_get_video_ctrl(struct uvc |
| ctrl->dwMaxVideoFrameSize = get_unaligned_le32(&data[18]); |
| ctrl->dwMaxPayloadTransferSize = get_unaligned_le32(&data[22]); |
| |
| - if (size == 34) { |
| + if (size >= 34) { |
| ctrl->dwClockFrequency = get_unaligned_le32(&data[26]); |
| ctrl->bmFramingInfo = data[30]; |
| ctrl->bPreferedVersion = data[31]; |
| @@ -246,11 +259,10 @@ out: |
| static int uvc_set_video_ctrl(struct uvc_streaming *stream, |
| struct uvc_streaming_control *ctrl, int probe) |
| { |
| + u16 size = uvc_video_ctrl_size(stream); |
| __u8 *data; |
| - __u16 size; |
| int ret; |
| |
| - size = stream->dev->uvc_version >= 0x0110 ? 34 : 26; |
| data = kzalloc(size, GFP_KERNEL); |
| if (data == NULL) |
| return -ENOMEM; |
| @@ -267,7 +279,7 @@ static int uvc_set_video_ctrl(struct uvc |
| put_unaligned_le32(ctrl->dwMaxVideoFrameSize, &data[18]); |
| put_unaligned_le32(ctrl->dwMaxPayloadTransferSize, &data[22]); |
| |
| - if (size == 34) { |
| + if (size >= 34) { |
| put_unaligned_le32(ctrl->dwClockFrequency, &data[26]); |
| data[30] = ctrl->bmFramingInfo; |
| data[31] = ctrl->bPreferedVersion; |