From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
To: Ricardo Ribalda <ribalda@chromium.org>
Cc: Hans de Goede <hdegoede@redhat.com>,
Mauro Carvalho Chehab <mchehab@kernel.org>,
Hans Verkuil <hverkuil@xs4all.nl>,
Sakari Ailus <sakari.ailus@linux.intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Linus Walleij <linus.walleij@linaro.org>,
Bartosz Golaszewski <brgl@bgdev.pl>,
linux-media@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
linux-gpio@vger.kernel.org
Subject: Re: [PATCH 7/8] media: uvcvideo: Add support for V4L2_CID_CAMERA_ORIENTATION
Date: Wed, 23 Apr 2025 00:40:30 +0300 [thread overview]
Message-ID: <20250422214030.GS17813@pendragon.ideasonboard.com> (raw)
In-Reply-To: <20250422213236.GR17813@pendragon.ideasonboard.com>
On Wed, Apr 23, 2025 at 12:32:37AM +0300, Laurent Pinchart wrote:
> Hi Ricardo,
>
> Thank you for the patch.
>
> On Thu, Apr 03, 2025 at 07:16:18PM +0000, Ricardo Ribalda wrote:
> > Fetch the orientation from the fwnode and map it into a control.
> >
> > The uvc driver does not use the media controller, so we need to create a
> > virtual entity, like we previously did with the external gpio.
>
> I don't want to create a new entity every time we need to expose a new
> "software" control. If we keep handling GPIO as an entity, can we use it
> to expose all non-UVC controls ? Otherwise, if we have to create a new
> entity here, let's make sure we can reuse it in the future for more
> controls, and name it appropriately.
>
> This being said, functionally speaking, wouldn't the
> V4L2_CID_CAMERA_ORIENTATION control make more sense on the camera input
> terminal ? Have you considered adding it there ? Or would it be too
> intrusive ?
Scratch the last comment, I was thinking about exposing controls on
subdevs, which we obviously don't do.
> > Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
> > ---
> > drivers/media/usb/uvc/Makefile | 2 +-
> > drivers/media/usb/uvc/uvc_ctrl.c | 21 +++++++++++
> > drivers/media/usb/uvc/uvc_driver.c | 14 ++++++--
> > drivers/media/usb/uvc/uvc_entity.c | 1 +
> > drivers/media/usb/uvc/uvc_fwnode.c | 73 ++++++++++++++++++++++++++++++++++++++
> > drivers/media/usb/uvc/uvcvideo.h | 15 ++++++++
> > include/linux/usb/uvc.h | 3 ++
> > 7 files changed, 125 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/media/usb/uvc/Makefile b/drivers/media/usb/uvc/Makefile
> > index 85514b6e538fbb8284e574ca14700f2d749e1a2e..2a5b76aab756c21011d966f3ce0410ff6b8e5b19 100644
> > --- a/drivers/media/usb/uvc/Makefile
> > +++ b/drivers/media/usb/uvc/Makefile
> > @@ -1,7 +1,7 @@
> > # SPDX-License-Identifier: GPL-2.0
> > uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \
> > uvc_status.o uvc_isight.o uvc_debugfs.o uvc_metadata.o \
> > - uvc_gpio.o
> > + uvc_gpio.o uvc_fwnode.o
> > ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
> > uvcvideo-objs += uvc_entity.o
> > endif
> > diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
> > index cbf19aa1d82374a08cf79b6a6787fa348b83523a..df84bf292dcab6b833fbd3c70eccbe9e567ee567 100644
> > --- a/drivers/media/usb/uvc/uvc_ctrl.c
> > +++ b/drivers/media/usb/uvc/uvc_ctrl.c
> > @@ -376,6 +376,13 @@ static const struct uvc_control_info uvc_ctrls[] = {
> > | UVC_CTRL_FLAG_GET_DEF
> > | UVC_CTRL_FLAG_AUTO_UPDATE,
> > },
> > + {
> > + .entity = UVC_GUID_FWNODE,
> > + .selector = 0,
> > + .index = 0,
> > + .size = 1,
> > + .flags = UVC_CTRL_FLAG_GET_CUR,
> > + },
> > };
> >
> > static const u32 uvc_control_classes[] = {
> > @@ -975,6 +982,17 @@ static const struct uvc_control_mapping uvc_ctrl_mappings[] = {
> > .data_type = UVC_CTRL_DATA_TYPE_BITMASK,
> > .name = "Region of Interest Auto Ctrls",
> > },
> > + {
> > + .id = V4L2_CID_CAMERA_ORIENTATION,
> > + .entity = UVC_GUID_FWNODE,
> > + .selector = 0,
> > + .size = 8,
> > + .offset = 0,
> > + .v4l2_type = V4L2_CTRL_TYPE_MENU,
> > + .data_type = UVC_CTRL_DATA_TYPE_ENUM,
> > + .menu_mask = GENMASK(V4L2_CAMERA_ORIENTATION_EXTERNAL,
> > + V4L2_CAMERA_ORIENTATION_FRONT),
> > + },
> > };
> >
> > /* ------------------------------------------------------------------------
> > @@ -3170,6 +3188,9 @@ static int uvc_ctrl_init_chain(struct uvc_video_chain *chain)
> > } else if (UVC_ENTITY_TYPE(entity) == UVC_EXT_GPIO_UNIT) {
> > bmControls = entity->gpio.bmControls;
> > bControlSize = entity->gpio.bControlSize;
> > + } else if (UVC_ENTITY_TYPE(entity) == UVC_FWNODE_UNIT) {
> > + bmControls = entity->fwnode.bmControls;
> > + bControlSize = entity->fwnode.bControlSize;
> > }
> >
> > /* Remove bogus/blacklisted controls */
> > diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
> > index b52e1ff401e24f69b867b5e975cda4260463e760..9a8e5d94b3eba09e1ee1be20bad5b016b6def915 100644
> > --- a/drivers/media/usb/uvc/uvc_driver.c
> > +++ b/drivers/media/usb/uvc/uvc_driver.c
> > @@ -1752,11 +1752,15 @@ static int uvc_scan_device(struct uvc_device *dev)
> > return -1;
> > }
> >
> > - /* Add GPIO entity to the first chain. */
> > - if (dev->gpio_unit) {
> > + /* Add virtual entities to the first chain. */
> > + if (dev->gpio_unit || dev->fwnode_unit) {
> > chain = list_first_entry(&dev->chains,
> > struct uvc_video_chain, list);
> > - list_add_tail(&dev->gpio_unit->chain, &chain->entities);
> > + if (dev->gpio_unit)
> > + list_add_tail(&dev->gpio_unit->chain, &chain->entities);
> > + if (dev->fwnode_unit)
> > + list_add_tail(&dev->fwnode_unit->chain,
> > + &chain->entities);
> > }
> >
> > return 0;
> > @@ -2132,6 +2136,10 @@ static int uvc_probe(struct usb_interface *intf,
> > if (ret < 0)
> > goto error;
> >
> > + ret = uvc_fwnode_parse(dev);
> > + if (ret < 0)
> > + goto error;
> > +
> > dev_info(&dev->udev->dev, "Found UVC %u.%02x device %s (%04x:%04x)\n",
> > dev->uvc_version >> 8, dev->uvc_version & 0xff,
> > udev->product ? udev->product : "<unnamed>",
> > diff --git a/drivers/media/usb/uvc/uvc_entity.c b/drivers/media/usb/uvc/uvc_entity.c
> > index cc68dd24eb42dce5b2846ca52a8dfa499c8aed96..01eeba2f049e9ebb25e091340a133656acbf28ca 100644
> > --- a/drivers/media/usb/uvc/uvc_entity.c
> > +++ b/drivers/media/usb/uvc/uvc_entity.c
> > @@ -106,6 +106,7 @@ static int uvc_mc_init_entity(struct uvc_video_chain *chain,
> > case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
> > case UVC_EXTERNAL_VENDOR_SPECIFIC:
> > case UVC_EXT_GPIO_UNIT:
> > + case UVC_FWNODE_UNIT:
> > default:
> > function = MEDIA_ENT_F_V4L2_SUBDEV_UNKNOWN;
> > break;
> > diff --git a/drivers/media/usb/uvc/uvc_fwnode.c b/drivers/media/usb/uvc/uvc_fwnode.c
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..20f7b8847551acfd44cbf09bcbf653d89985561f
> > --- /dev/null
> > +++ b/drivers/media/usb/uvc/uvc_fwnode.c
> > @@ -0,0 +1,73 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * uvc_fwnode.c -- USB Video Class driver
> > + *
> > + * Copyright 2025 Google LLC
> > + */
> > +
> > +#include <linux/kernel.h>
> > +#include <linux/usb/uvc.h>
> > +#include <media/v4l2-fwnode.h>
> > +#include "uvcvideo.h"
> > +
> > +static int uvc_fwnode_get_cur(struct uvc_device *dev, struct uvc_entity *entity,
> > + u8 cs, void *data, u16 size)
> > +{
> > + if (size < 1)
> > + return -EINVAL;
> > +
> > + switch (entity->fwnode.props.orientation) {
> > + case V4L2_FWNODE_ORIENTATION_FRONT:
> > + *(u8 *)data = V4L2_CAMERA_ORIENTATION_FRONT;
> > + break;
> > + case V4L2_FWNODE_ORIENTATION_BACK:
> > + *(u8 *)data = V4L2_CAMERA_ORIENTATION_BACK;
> > + break;
> > + default:
> > + *(u8 *)data = V4L2_CAMERA_ORIENTATION_EXTERNAL;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int uvc_fwnode_get_info(struct uvc_device *dev,
> > + struct uvc_entity *entity, u8 cs, u8 *caps)
> > +{
> > + *caps = UVC_CONTROL_CAP_GET;
> > + return 0;
> > +}
> > +
> > +int uvc_fwnode_parse(struct uvc_device *dev)
> > +{
> > + static const u8 uvc_fwnode_guid[] = UVC_GUID_FWNODE;
> > + struct v4l2_fwnode_device_properties props;
> > + struct uvc_entity *unit;
> > + int ret;
> > +
> > + ret = v4l2_fwnode_device_parse(&dev->udev->dev, &props);
> > + if (ret)
> > + return dev_err_probe(&dev->intf->dev, ret,
> > + "Can't parse fwnode\n");
> > +
> > + if (props.orientation == V4L2_FWNODE_PROPERTY_UNSET)
> > + return 0;
> > +
> > + unit = uvc_alloc_entity(UVC_FWNODE_UNIT, UVC_FWNODE_UNIT_ID, 0, 1);
> > + if (!unit)
> > + return -ENOMEM;
> > +
> > + memcpy(unit->guid, uvc_fwnode_guid, sizeof(unit->guid));
> > + unit->fwnode.props = props;
> > + unit->fwnode.bControlSize = 1;
> > + unit->fwnode.bmControls = (u8 *)unit + sizeof(*unit);
> > + unit->fwnode.bmControls[0] = 1;
> > + unit->get_cur = uvc_fwnode_get_cur;
> > + unit->get_info = uvc_fwnode_get_info;
> > + strscpy(unit->name, "FWNODE", sizeof(unit->name));
> > +
> > + list_add_tail(&unit->list, &dev->entities);
> > +
> > + dev->fwnode_unit = unit;
> > +
> > + return 0;
> > +}
> > diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
> > index aef96b96499ce09ffa286c51793482afd9832097..c52ab99bf8d21ab37270d27ffc040fd115b3f5ba 100644
> > --- a/drivers/media/usb/uvc/uvcvideo.h
> > +++ b/drivers/media/usb/uvc/uvcvideo.h
> > @@ -19,6 +19,7 @@
> > #include <media/v4l2-event.h>
> > #include <media/v4l2-fh.h>
> > #include <media/videobuf2-v4l2.h>
> > +#include <media/v4l2-fwnode.h>
> >
> > /* --------------------------------------------------------------------------
> > * UVC constants
> > @@ -41,6 +42,9 @@
> > #define UVC_EXT_GPIO_UNIT 0x7ffe
> > #define UVC_EXT_GPIO_UNIT_ID 0x100
> >
> > +#define UVC_FWNODE_UNIT 0x7ffd
> > +#define UVC_FWNODE_UNIT_ID 0x101
> > +
> > /* ------------------------------------------------------------------------
> > * Driver specific constants.
> > */
> > @@ -242,6 +246,12 @@ struct uvc_entity {
> > int irq;
> > bool initialized;
> > } gpio;
> > +
> > + struct {
> > + u8 bControlSize;
> > + u8 *bmControls;
> > + struct v4l2_fwnode_device_properties props;
> > + } fwnode;
> > };
> >
> > u8 bNrInPins;
> > @@ -617,6 +627,7 @@ struct uvc_device {
> > } async_ctrl;
> >
> > struct uvc_entity *gpio_unit;
> > + struct uvc_entity *fwnode_unit;
> > };
> >
> > enum uvc_handle_state {
> > @@ -835,4 +846,8 @@ size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf,
> > int uvc_gpio_parse(struct uvc_device *dev);
> > int uvc_gpio_init_irq(struct uvc_device *dev);
> > void uvc_gpio_deinit(struct uvc_device *dev);
> > +
> > +/* fwnode */
> > +int uvc_fwnode_parse(struct uvc_device *dev);
> > +
> > #endif
> > diff --git a/include/linux/usb/uvc.h b/include/linux/usb/uvc.h
> > index bce95153e5a65613a710d7316fc17cf5462b5bce..d818839b0442988d94ab44935e1ce855b0adf4a1 100644
> > --- a/include/linux/usb/uvc.h
> > +++ b/include/linux/usb/uvc.h
> > @@ -29,6 +29,9 @@
> > #define UVC_GUID_EXT_GPIO_CONTROLLER \
> > {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
> > 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03}
> > +#define UVC_GUID_FWNODE \
> > + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
> > + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04}
> >
> > #define UVC_GUID_FORMAT_MJPEG \
> > { 'M', 'J', 'P', 'G', 0x00, 0x00, 0x10, 0x00, \
> >
--
Regards,
Laurent Pinchart
next prev parent reply other threads:[~2025-04-22 21:40 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-03 19:16 [PATCH 0/8] media: uvcvideo: Add support for V4L2_CID_CAMERA_SENSOR_ORIENTATION Ricardo Ribalda
2025-04-03 19:16 ` [PATCH 1/8] media: uvcvideo: Fix deferred probing error Ricardo Ribalda
2025-04-03 19:16 ` [PATCH 2/8] media: uvcvideo: Use dev_err_probe for devm_gpiod_get_optional Ricardo Ribalda
2025-04-03 19:16 ` [PATCH 3/8] media: v4l: fwnode: Support acpi devices for v4l2_fwnode_device_parse Ricardo Ribalda
2025-04-13 9:50 ` Sakari Ailus
2025-04-22 0:23 ` Ricardo Ribalda
2025-04-22 8:44 ` Hans de Goede
2025-04-22 9:41 ` Sakari Ailus
2025-05-05 20:34 ` Ricardo Ribalda
2025-04-03 19:16 ` [PATCH 4/8] media: ipu-bridge: Use v4l2_fwnode_device_parse helper Ricardo Ribalda
2025-04-03 19:16 ` [PATCH 5/8] dt-bindings: usb: usb-device: Add orientation Ricardo Ribalda
2025-04-04 19:36 ` Rob Herring
2025-04-04 20:31 ` Ricardo Ribalda
2025-04-03 19:16 ` [PATCH 6/8] media: uvcvideo: Factor out gpio functions to its own file Ricardo Ribalda
2025-04-22 21:28 ` Laurent Pinchart
2025-04-22 22:20 ` Ricardo Ribalda
2025-04-22 22:25 ` Laurent Pinchart
2025-04-22 22:35 ` Ricardo Ribalda
2025-04-22 22:48 ` Laurent Pinchart
2025-04-28 14:07 ` Hans de Goede
2025-04-28 15:32 ` Ricardo Ribalda
2025-04-03 19:16 ` [PATCH 7/8] media: uvcvideo: Add support for V4L2_CID_CAMERA_ORIENTATION Ricardo Ribalda
2025-04-22 21:32 ` Laurent Pinchart
2025-04-22 21:40 ` Laurent Pinchart [this message]
2025-04-03 19:16 ` [PATCH 8/8] media: uvcvideo: Do not create MC entities for virtual entities Ricardo Ribalda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250422214030.GS17813@pendragon.ideasonboard.com \
--to=laurent.pinchart@ideasonboard.com \
--cc=brgl@bgdev.pl \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=hdegoede@redhat.com \
--cc=hverkuil@xs4all.nl \
--cc=krzk+dt@kernel.org \
--cc=linus.walleij@linaro.org \
--cc=linux-gpio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=ribalda@chromium.org \
--cc=robh@kernel.org \
--cc=sakari.ailus@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.