summaryrefslogtreecommitdiff
path: root/drivers/media/usb/uvc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-10-07 21:04:35 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-10-07 21:04:35 +0300
commit5d435a3f7b6cb1db566d0f56f5f8dc33be0dde69 (patch)
tree9633f2458c973fccc3ee0fa85b0b24cfe62aa6bf /drivers/media/usb/uvc
parent4078aa68509746d0c1a70c50ab22a761ad7c2e0d (diff)
parentfbb6c848dd89786fe24856ee6b5e773910ded29c (diff)
downloadlinux-5d435a3f7b6cb1db566d0f56f5f8dc33be0dde69.tar.xz
Merge tag 'media/v6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: - New driver for Mediatek MDP V3 - New driver for NXP i.MX DW100 dewarper - Zoran driver got promoted from staging - Hantro and related drivers got promoted from staging - Several VB1 drivers got moved to staging/deprecated (cpia2, fsl-viu, meye, saa7146, av7110, stkwebcam, tm6000, vpfe_capture, davinci, zr364xx) - Usual set of driver fixes, improvements and cleanups * tag 'media/v6.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (107 commits) media: destage Hantro VPU driver media: platform: mtk-mdp3: add MediaTek MDP3 driver media: dt-binding: mediatek: add bindings for MediaTek CCORR and WDMA media: dt-binding: mediatek: add bindings for MediaTek MDP3 components media: xilinx: vipp: Fix refcount leak in xvip_graph_dma_init media: xilinx: video: Add 1X12 greyscale format media: xilinx: csi2rxss: Add 1X12 greyscale format media: staging: media: imx: imx7-media-csi: Increase video mem limit media: uvcvideo: Limit power line control for Sonix Technology media: uvcvideo: Use entity get_cur in uvc_ctrl_set media: uvcvideo: Fix typo 'the the' in comment media: uvcvideo: Use indexed loops in uvc_ctrl_init_ctrl() media: uvcvideo: Fix memory leak in uvc_gpio_parse media: renesas: vsp1: Add support for RZ/G2L VSPD media: renesas: vsp1: Add VSP1_HAS_NON_ZERO_LBA feature bit media: renesas: vsp1: Add support for VSP software version media: renesas: vsp1: Add support to deassert/assert reset line media: dt-bindings: media: renesas,vsp1: Document RZ/G2L VSPD bindings media: meson: vdec: add missing clk_disable_unprepare on error in vdec_hevc_start() media: amphion: fix a bug that vpu core may not resume after suspend ...
Diffstat (limited to 'drivers/media/usb/uvc')
-rw-r--r--drivers/media/usb/uvc/uvc_ctrl.c117
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c17
-rw-r--r--drivers/media/usb/uvc/uvc_video.c2
3 files changed, 79 insertions, 57 deletions
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 8c208db9600b..97f312020516 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -985,36 +985,56 @@ static s32 __uvc_ctrl_get_value(struct uvc_control_mapping *mapping,
return value;
}
-static int __uvc_ctrl_get(struct uvc_video_chain *chain,
- struct uvc_control *ctrl, struct uvc_control_mapping *mapping,
- s32 *value)
+static int __uvc_ctrl_load_cur(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl)
{
+ u8 *data;
int ret;
- if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
- return -EACCES;
+ if (ctrl->loaded)
+ return 0;
- if (!ctrl->loaded) {
- if (ctrl->entity->get_cur) {
- ret = ctrl->entity->get_cur(chain->dev,
- ctrl->entity,
- ctrl->info.selector,
- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
- ctrl->info.size);
- } else {
- ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
- ctrl->entity->id,
- chain->dev->intfnum,
- ctrl->info.selector,
- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
- ctrl->info.size);
- }
- if (ret < 0)
- return ret;
+ data = uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT);
+ if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
+ memset(data, 0, ctrl->info.size);
ctrl->loaded = 1;
+
+ return 0;
}
+ if (ctrl->entity->get_cur)
+ ret = ctrl->entity->get_cur(chain->dev, ctrl->entity,
+ ctrl->info.selector, data,
+ ctrl->info.size);
+ else
+ ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
+ ctrl->entity->id, chain->dev->intfnum,
+ ctrl->info.selector, data,
+ ctrl->info.size);
+
+ if (ret < 0)
+ return ret;
+
+ ctrl->loaded = 1;
+
+ return ret;
+}
+
+static int __uvc_ctrl_get(struct uvc_video_chain *chain,
+ struct uvc_control *ctrl,
+ struct uvc_control_mapping *mapping,
+ s32 *value)
+{
+ int ret;
+
+ if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
+ return -EACCES;
+
+ ret = __uvc_ctrl_load_cur(chain, ctrl);
+ if (ret < 0)
+ return ret;
+
*value = __uvc_ctrl_get_value(mapping,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
@@ -1810,21 +1830,10 @@ int uvc_ctrl_set(struct uvc_fh *handle,
* needs to be loaded from the device to perform the read-modify-write
* operation.
*/
- if (!ctrl->loaded && (ctrl->info.size * 8) != mapping->size) {
- if ((ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0) {
- memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
- 0, ctrl->info.size);
- } else {
- ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
- ctrl->entity->id, chain->dev->intfnum,
- ctrl->info.selector,
- uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
- ctrl->info.size);
- if (ret < 0)
- return ret;
- }
-
- ctrl->loaded = 1;
+ if ((ctrl->info.size * 8) != mapping->size) {
+ ret = __uvc_ctrl_load_cur(chain, ctrl);
+ if (ret < 0)
+ return ret;
}
/* Backup the current value in case we need to rollback later. */
@@ -2411,10 +2420,9 @@ static void uvc_ctrl_prune_entity(struct uvc_device *dev,
static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain,
struct uvc_control *ctrl)
{
- const struct uvc_control_info *info = uvc_ctrls;
- const struct uvc_control_info *iend = info + ARRAY_SIZE(uvc_ctrls);
- const struct uvc_control_mapping *mapping;
- const struct uvc_control_mapping *mend;
+ const struct uvc_control_mapping *mappings;
+ unsigned int num_mappings;
+ unsigned int i;
/*
* XU controls initialization requires querying the device for control
@@ -2425,7 +2433,9 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain,
if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT)
return;
- for (; info < iend; ++info) {
+ for (i = 0; i < ARRAY_SIZE(uvc_ctrls); ++i) {
+ const struct uvc_control_info *info = &uvc_ctrls[i];
+
if (uvc_entity_match_guid(ctrl->entity, info->entity) &&
ctrl->index == info->index) {
uvc_ctrl_add_info(chain->dev, ctrl, info);
@@ -2452,9 +2462,11 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain,
*/
if (chain->dev->info->mappings) {
bool custom = false;
- unsigned int i;
- for (i = 0; (mapping = chain->dev->info->mappings[i]); ++i) {
+ for (i = 0; chain->dev->info->mappings[i]; ++i) {
+ const struct uvc_control_mapping *mapping =
+ chain->dev->info->mappings[i];
+
if (uvc_entity_match_guid(ctrl->entity, mapping->entity) &&
ctrl->info.selector == mapping->selector) {
__uvc_ctrl_add_mapping(chain, ctrl, mapping);
@@ -2467,10 +2479,9 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain,
}
/* Process common mappings next. */
- mapping = uvc_ctrl_mappings;
- mend = mapping + ARRAY_SIZE(uvc_ctrl_mappings);
+ for (i = 0; i < ARRAY_SIZE(uvc_ctrl_mappings); ++i) {
+ const struct uvc_control_mapping *mapping = &uvc_ctrl_mappings[i];
- for (; mapping < mend; ++mapping) {
if (uvc_entity_match_guid(ctrl->entity, mapping->entity) &&
ctrl->info.selector == mapping->selector)
__uvc_ctrl_add_mapping(chain, ctrl, mapping);
@@ -2478,14 +2489,16 @@ static void uvc_ctrl_init_ctrl(struct uvc_video_chain *chain,
/* Finally process version-specific mappings. */
if (chain->dev->uvc_version < 0x0150) {
- mapping = uvc_ctrl_mappings_uvc11;
- mend = mapping + ARRAY_SIZE(uvc_ctrl_mappings_uvc11);
+ mappings = uvc_ctrl_mappings_uvc11;
+ num_mappings = ARRAY_SIZE(uvc_ctrl_mappings_uvc11);
} else {
- mapping = uvc_ctrl_mappings_uvc15;
- mend = mapping + ARRAY_SIZE(uvc_ctrl_mappings_uvc15);
+ mappings = uvc_ctrl_mappings_uvc15;
+ num_mappings = ARRAY_SIZE(uvc_ctrl_mappings_uvc15);
}
- for (; mapping < mend; ++mapping) {
+ for (i = 0; i < num_mappings; ++i) {
+ const struct uvc_control_mapping *mapping = &mappings[i];
+
if (uvc_entity_match_guid(ctrl->entity, mapping->entity) &&
ctrl->info.selector == mapping->selector)
__uvc_ctrl_add_mapping(chain, ctrl, mapping);
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index d509a4a2f08e..744051b52e12 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1553,10 +1553,6 @@ static int uvc_gpio_parse(struct uvc_device *dev)
if (IS_ERR_OR_NULL(gpio_privacy))
return PTR_ERR_OR_ZERO(gpio_privacy);
- unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1);
- if (!unit)
- return -ENOMEM;
-
irq = gpiod_to_irq(gpio_privacy);
if (irq < 0) {
if (irq != EPROBE_DEFER)
@@ -1565,6 +1561,10 @@ static int uvc_gpio_parse(struct uvc_device *dev)
return irq;
}
+ unit = uvc_alloc_entity(UVC_EXT_GPIO_UNIT, UVC_EXT_GPIO_UNIT_ID, 0, 1);
+ if (!unit)
+ return -ENOMEM;
+
unit->gpio.gpio_privacy = gpio_privacy;
unit->gpio.irq = irq;
unit->gpio.bControlSize = 1;
@@ -3264,6 +3264,15 @@ static const struct usb_device_id uvc_ids[] = {
.bInterfaceSubClass = 1,
.bInterfaceProtocol = 0,
.driver_info = UVC_INFO_QUIRK(UVC_QUIRK_FORCE_BPP) },
+ /* Sonix Technology USB 2.0 Camera */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x3277,
+ .idProduct = 0x0072,
+ .bInterfaceClass = USB_CLASS_VIDEO,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = (kernel_ulong_t)&uvc_ctrl_power_line_limited },
/* Acer EasyCamera */
{ .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 170a008f4006..d2eb9066e4dc 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1095,7 +1095,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream,
/*
* Synchronize to the input stream by waiting for the FID bit to be
- * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE.
+ * toggled when the buffer state is not UVC_BUF_STATE_ACTIVE.
* stream->last_fid is initialized to -1, so the first isochronous
* frame will always be in sync.
*