linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
To: linux-media@vger.kernel.org, sakari.ailus@linux.intel.com,
	Jacopo Mondi <jacopo+renesas@jmondi.org>,
	Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
	niklas.soderlund+renesas@ragnatech.se
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>,
	Hans Verkuil <hverkuil-cisco@xs4all.nl>,
	Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>,
	Pratyush Yadav <p.yadav@ti.com>,
	Lokesh Vutla <lokeshvutla@ti.com>,
	Michal Simek <michal.simek@xilinx.com>
Subject: [PATCH v8 28/36] media: subdev: Add [GS]_ROUTING subdev ioctls and operations
Date: Mon, 30 Aug 2021 14:01:08 +0300	[thread overview]
Message-ID: <20210830110116.488338-29-tomi.valkeinen@ideasonboard.com> (raw)
In-Reply-To: <20210830110116.488338-1-tomi.valkeinen@ideasonboard.com>

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

Add support for subdev internal routing. A route is defined as a single
stream from a sink pad to a source pad.

The userspace can configure the routing via two new ioctls,
VIDIOC_SUBDEV_G_ROUTING and VIDIOC_SUBDEV_S_ROUTING, and subdevs can
implement the functionality with v4l2_subdev_pad_ops.set_routing().

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>

- Add sink and source streams for multiplexed links
- Copy the argument back in case of an error. This is needed to let the
  caller know the number of routes.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>

- Expand and refine documentation.
- Make the 'routes' pointer a __u64 __user pointer so that a compat32
  version of the ioctl is not required.
- Add struct v4l2_subdev_krouting to be used for subdevice operations.

Signed-off-by: Jacopo Mondi <jacopo+renesas@jmondi.org>

- Fix typecasing warnings
- Check sink & source pad types
- Add 'which' field
- Add V4L2_SUBDEV_ROUTE_FL_SOURCE
- Routing to subdev state
- Dropped get_routing subdev op

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
---
 drivers/media/v4l2-core/v4l2-ioctl.c  | 25 ++++++++-
 drivers/media/v4l2-core/v4l2-subdev.c | 75 +++++++++++++++++++++++++++
 include/media/v4l2-subdev.h           | 24 +++++++++
 include/uapi/linux/v4l2-subdev.h      | 57 ++++++++++++++++++++
 4 files changed, 180 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 05d5db3d85e5..8e9315ffcb99 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/version.h>
 
+#include <linux/v4l2-subdev.h>
 #include <linux/videodev2.h>
 
 #include <media/v4l2-common.h>
@@ -3065,6 +3066,21 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
 		ret = 1;
 		break;
 	}
+
+	case VIDIOC_SUBDEV_G_ROUTING:
+	case VIDIOC_SUBDEV_S_ROUTING: {
+		struct v4l2_subdev_routing *routing = parg;
+
+		if (routing->num_routes > 256)
+			return -EINVAL;
+
+		*user_ptr = u64_to_user_ptr(routing->routes);
+		*kernel_ptr = (void **)&routing->routes;
+		*array_size = sizeof(struct v4l2_subdev_route)
+			    * routing->num_routes;
+		ret = 1;
+		break;
+	}
 	}
 
 	return ret;
@@ -3328,8 +3344,15 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg,
 	/*
 	 * Some ioctls can return an error, but still have valid
 	 * results that must be returned.
+	 *
+	 * FIXME: subdev IOCTLS are partially handled here and partially in
+	 * v4l2-subdev.c and the 'always_copy' flag can only be set for IOCTLS
+	 * defined here as part of the 'v4l2_ioctls' array. As
+	 * VIDIOC_SUBDEV_G_ROUTING needs to return results to applications even
+	 * in case of failure, but it is not defined here as part of the
+	 * 'v4l2_ioctls' array, insert an ad-hoc check to address that.
 	 */
-	if (err < 0 && !always_copy)
+	if (err < 0 && !always_copy && cmd != VIDIOC_SUBDEV_G_ROUTING)
 		goto out;
 
 out_array_args:
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index b1e65488210d..0e1f325b3159 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -395,6 +395,12 @@ subdev_ioctl_get_state(struct v4l2_subdev *sd, struct v4l2_subdev_fh *subdev_fh,
 		which = ((struct v4l2_subdev_selection *)arg)->which;
 		break;
 	}
+
+	case VIDIOC_SUBDEV_G_ROUTING:
+	case VIDIOC_SUBDEV_S_ROUTING: {
+		which = ((struct v4l2_subdev_routing *)arg)->which;
+		break;
+	}
 	}
 
 	return which == V4L2_SUBDEV_FORMAT_TRY ?
@@ -711,6 +717,74 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 	case VIDIOC_SUBDEV_QUERYSTD:
 		return v4l2_subdev_call(sd, video, querystd, arg);
 
+	case VIDIOC_SUBDEV_G_ROUTING: {
+		struct v4l2_subdev_routing *routing = arg;
+		struct v4l2_subdev_krouting *krouting;
+
+		if (!(sd->flags & V4L2_SUBDEV_FL_MULTIPLEXED))
+			return -ENOIOCTLCMD;
+
+		memset(routing->reserved, 0, sizeof(routing->reserved));
+
+		krouting = &state->routing;
+
+		if (routing->num_routes < krouting->num_routes) {
+			routing->num_routes = krouting->num_routes;
+			return -ENOSPC;
+		}
+
+		memcpy((struct v4l2_subdev_route *)(uintptr_t)routing->routes,
+		       krouting->routes,
+		       krouting->num_routes * sizeof(*krouting->routes));
+		routing->num_routes = krouting->num_routes;
+
+		return 0;
+	}
+
+	case VIDIOC_SUBDEV_S_ROUTING: {
+		struct v4l2_subdev_routing *routing = arg;
+		struct v4l2_subdev_route *routes =
+			(struct v4l2_subdev_route *)(uintptr_t)routing->routes;
+		struct v4l2_subdev_krouting krouting = {};
+		unsigned int i;
+
+		if (!(sd->flags & V4L2_SUBDEV_FL_MULTIPLEXED))
+			return -ENOIOCTLCMD;
+
+		if (routing->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev)
+			return -EPERM;
+
+		memset(routing->reserved, 0, sizeof(routing->reserved));
+
+		for (i = 0; i < routing->num_routes; ++i) {
+			const struct v4l2_subdev_route *route = &routes[i];
+			const struct media_pad *pads = sd->entity.pads;
+
+			/* Do not check sink pad for source routes */
+			if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_SOURCE)) {
+				if (route->sink_pad >= sd->entity.num_pads)
+					return -EINVAL;
+
+				if (!(pads[route->sink_pad].flags &
+				      MEDIA_PAD_FL_SINK))
+					return -EINVAL;
+			}
+
+			if (route->source_pad >= sd->entity.num_pads)
+				return -EINVAL;
+
+			if (!(pads[route->source_pad].flags &
+			      MEDIA_PAD_FL_SOURCE))
+				return -EINVAL;
+		}
+
+		krouting.which = routing->which;
+		krouting.num_routes = routing->num_routes;
+		krouting.routes = routes;
+
+		return v4l2_subdev_call(sd, pad, set_routing, state, &krouting);
+	}
+
 	default:
 		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
 	}
@@ -975,6 +1049,7 @@ void v4l2_free_subdev_state(struct v4l2_subdev_state *state)
 
 	mutex_destroy(&state->lock);
 
+	kvfree(state->routing.routes);
 	kvfree(state->pads);
 	kfree(state);
 }
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 356901d8a948..cd6aad21ae0c 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -694,12 +694,29 @@ struct v4l2_subdev_pad_config {
 	struct v4l2_rect try_compose;
 };
 
+/**
+ * struct v4l2_subdev_krouting - subdev routing table
+ *
+ * @which: format type (from enum v4l2_subdev_format_whence)
+ * @routes: &struct v4l2_subdev_route
+ * @num_routes: number of routes
+ *
+ * This structure is used to translate arguments received from
+ * VIDIOC_SUBDEV_G/S_ROUTING() ioctl to subdev device drivers operations.
+ */
+struct v4l2_subdev_krouting {
+	u32 which;
+	struct v4l2_subdev_route *routes;
+	unsigned int num_routes;
+};
+
 /**
  * struct v4l2_subdev_state - Used for storing subdev state information.
  *
  * @lock: mutex for the state
  * @which: state type (from enum v4l2_subdev_format_whence)
  * @pads: &struct v4l2_subdev_pad_config array
+ * @routing: routing table for the subdev
  *
  * This structure only needs to be passed to the pad op if the 'which' field
  * of the main argument is set to %V4L2_SUBDEV_FORMAT_TRY. For
@@ -709,6 +726,7 @@ struct v4l2_subdev_state {
 	struct mutex lock;
 	u32 which;
 	struct v4l2_subdev_pad_config *pads;
+	struct v4l2_subdev_krouting routing;
 };
 
 /**
@@ -772,6 +790,9 @@ struct v4l2_subdev_state {
  *		     applied to the hardware. The operation shall fail if the
  *		     pad index it has been called on is not valid or in case of
  *		     unrecoverable failures.
+ *
+ * @set_routing: enable or disable data connection routes described in the
+ *		 subdevice routing table.
  */
 struct v4l2_subdev_pad_ops {
 	int (*init_cfg)(struct v4l2_subdev *sd,
@@ -816,6 +837,9 @@ struct v4l2_subdev_pad_ops {
 			       struct v4l2_mbus_config *config);
 	int (*set_mbus_config)(struct v4l2_subdev *sd, unsigned int pad,
 			       struct v4l2_mbus_config *config);
+	int (*set_routing)(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_state *state,
+			   struct v4l2_subdev_krouting *route);
 };
 
 /**
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index 658106f5b5dc..3aa623e0e5f9 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -188,6 +188,61 @@ struct v4l2_subdev_capability {
 /* The v4l2 sub-device video device node is registered in read-only mode. */
 #define V4L2_SUBDEV_CAP_RO_SUBDEV		0x00000001
 
+/*
+ * Is the route active? An active route will start when streaming is enabled
+ * on a video node.
+ */
+#define V4L2_SUBDEV_ROUTE_FL_ACTIVE		BIT(0)
+
+/*
+ * Is the route immutable, i.e. can it be activated and inactivated?
+ * Set by the driver.
+ */
+#define V4L2_SUBDEV_ROUTE_FL_IMMUTABLE		BIT(1)
+
+/*
+ * Is the route a source endpoint? A source endpoint route refers to a stream
+ * generated internally by the subdevice (usually a sensor), and thus there
+ * is no sink-side endpoint for the route. The sink_pad and sink_stream
+ * fields are unused.
+ * Set by the driver.
+ */
+#define V4L2_SUBDEV_ROUTE_FL_SOURCE		BIT(2)
+
+/**
+ * struct v4l2_subdev_route - A route inside a subdev
+ *
+ * @sink_pad: the sink pad index
+ * @sink_stream: the sink stream identifier
+ * @source_pad: the source pad index
+ * @source_stream: the source stream identifier
+ * @flags: route flags V4L2_SUBDEV_ROUTE_FL_*
+ * @reserved: drivers and applications must zero this array
+ */
+struct v4l2_subdev_route {
+	__u32 sink_pad;
+	__u32 sink_stream;
+	__u32 source_pad;
+	__u32 source_stream;
+	__u32 flags;
+	__u32 reserved[5];
+};
+
+/**
+ * struct v4l2_subdev_routing - Subdev routing information
+ *
+ * @which: configuration type (from enum v4l2_subdev_format_whence)
+ * @routes: pointer to the routes array
+ * @num_routes: the total number of routes in the routes array
+ * @reserved: drivers and applications must zero this array
+ */
+struct v4l2_subdev_routing {
+	__u32 which;
+	__u64 routes;
+	__u32 num_routes;
+	__u32 reserved[5];
+};
+
 /* Backwards compatibility define --- to be removed */
 #define v4l2_subdev_edid v4l2_edid
 
@@ -203,6 +258,8 @@ struct v4l2_subdev_capability {
 #define VIDIOC_SUBDEV_S_CROP			_IOWR('V', 60, struct v4l2_subdev_crop)
 #define VIDIOC_SUBDEV_G_SELECTION		_IOWR('V', 61, struct v4l2_subdev_selection)
 #define VIDIOC_SUBDEV_S_SELECTION		_IOWR('V', 62, struct v4l2_subdev_selection)
+#define VIDIOC_SUBDEV_G_ROUTING			_IOWR('V', 38, struct v4l2_subdev_routing)
+#define VIDIOC_SUBDEV_S_ROUTING			_IOWR('V', 39, struct v4l2_subdev_routing)
 /* The following ioctls are identical to the ioctls in videodev2.h */
 #define VIDIOC_SUBDEV_G_STD			_IOR('V', 23, v4l2_std_id)
 #define VIDIOC_SUBDEV_S_STD			_IOW('V', 24, v4l2_std_id)
-- 
2.25.1


  parent reply	other threads:[~2021-08-30 11:02 UTC|newest]

Thread overview: 86+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-30 11:00 [PATCH v8 00/36] v4l: subdev internal routing and streams Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 01/36] media: subdev: rename subdev-state alloc & free Tomi Valkeinen
2021-09-26 23:06   ` Laurent Pinchart
2021-09-27  6:38     ` Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 02/36] media: subdev: add active state to struct v4l2_subdev Tomi Valkeinen
2021-09-13 10:57   ` Jacopo Mondi
2021-09-13 12:00     ` Tomi Valkeinen
2021-09-15  9:44   ` Jacopo Mondi
2021-09-16  6:17     ` Tomi Valkeinen
2021-09-16  6:52       ` Tomi Valkeinen
2021-09-16  8:08         ` Jacopo Mondi
2021-09-16  9:36           ` Tomi Valkeinen
2021-09-26 23:58             ` Laurent Pinchart
2021-09-27  7:05               ` Tomi Valkeinen
2021-09-27  9:39                 ` Laurent Pinchart
2021-09-28  5:14                   ` Tomi Valkeinen
2021-09-28 12:33                     ` Tomi Valkeinen
2021-09-29 15:41                       ` Laurent Pinchart
2021-08-30 11:00 ` [PATCH v8 03/36] media: subdev: add 'which' to subdev state Tomi Valkeinen
2021-09-13 11:41   ` Jacopo Mondi
2021-09-13 12:17     ` Tomi Valkeinen
2021-09-13 13:38       ` Jacopo Mondi
2021-09-13 14:26         ` Tomi Valkeinen
2021-09-16 13:07           ` Jacopo Mondi
2021-09-16 13:24             ` Tomi Valkeinen
2021-09-27  0:48               ` Laurent Pinchart
2021-09-27  8:55                 ` Tomi Valkeinen
2021-09-27 10:49                   ` Laurent Pinchart
2021-09-27  0:46             ` Laurent Pinchart
2021-09-27  8:35               ` Tomi Valkeinen
2021-09-27 10:01                 ` Laurent Pinchart
2021-08-30 11:00 ` [PATCH v8 04/36] media: subdev: pass also the active state to subdevs from ioctls Tomi Valkeinen
2021-09-15 10:17   ` Jacopo Mondi
2021-09-16  6:44     ` Tomi Valkeinen
2021-09-16  8:02       ` Jacopo Mondi
2021-09-16  8:43         ` Tomi Valkeinen
2021-09-27  1:13           ` Laurent Pinchart
2021-08-30 11:00 ` [PATCH v8 05/36] media: subdev: add subdev state locking Tomi Valkeinen
2021-09-27  1:35   ` Laurent Pinchart
2021-09-27  9:49     ` Tomi Valkeinen
2021-09-27 10:06       ` Laurent Pinchart
2021-08-30 11:00 ` [PATCH v8 06/36] media: subdev: Add v4l2_subdev_validate(_and_lock)_state() Tomi Valkeinen
2021-09-27  1:45   ` Laurent Pinchart
2021-09-28  5:02     ` Tomi Valkeinen
2021-09-28  7:52       ` Laurent Pinchart
2021-09-29 15:35         ` Tomi Valkeinen
2021-09-29 15:39           ` Laurent Pinchart
2021-08-30 11:00 ` [PATCH v8 07/36] media: Documentation: add documentation about subdev state Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 08/36] media: entity: Use pad as a starting point for graph walk Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 09/36] media: entity: Use pads instead of entities in the media graph walk stack Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 10/36] media: entity: Walk the graph based on pads Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 11/36] media: mc: Start walk from a specific pad in use count calculation Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 12/36] media: entity: Add iterator helper for entity pads Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 13/36] media: entity: Move the pipeline from entity to pads Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 14/36] media: entity: Use pad as the starting point for a pipeline Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 15/36] media: entity: Add has_route entity operation Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 16/36] media: entity: Add media_entity_has_route() function Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 17/36] media: entity: Use routing information during graph traversal Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 18/36] media: entity: Skip link validation for pads to which there is no route Tomi Valkeinen
2021-08-30 11:00 ` [PATCH v8 19/36] media: entity: Add an iterator helper for connected pads Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 20/36] media: entity: Add only connected pads to the pipeline Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 21/36] media: entity: Add debug information in graph walk route check Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 22/36] media: Add bus type to frame descriptors Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 23/36] media: Add CSI-2 bus configuration " Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 24/36] media: Add stream to frame descriptor Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 25/36] media: subdev: increase V4L2_FRAME_DESC_ENTRY_MAX to 8 Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 26/36] media: add V4L2_SUBDEV_FL_MULTIPLEXED Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 27/36] media: Documentation: Add GS_ROUTING documentation Tomi Valkeinen
2021-08-30 11:01 ` Tomi Valkeinen [this message]
2021-09-15 16:10   ` [PATCH v8 28/36] media: subdev: Add [GS]_ROUTING subdev ioctls and operations Jacopo Mondi
2021-09-16  6:57     ` Tomi Valkeinen
2021-10-03 19:52   ` Dafna Hirschfeld
2021-10-04  5:15     ` Tomi Valkeinen
2021-10-05 10:19       ` Dafna Hirschfeld
2021-10-05 10:54         ` Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 29/36] media: subdev: add v4l2_subdev_has_route() Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 30/36] media: subdev: add v4l2_subdev_set_routing helper() Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 31/36] media: subdev: add stream based configuration Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 32/36] media: subdev: use streams in v4l2_subdev_link_validate() Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 33/36] media: subdev: add "opposite" stream helper funcs Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 34/36] media: subdev: add v4l2_subdev_get_fmt() helper function Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 35/36] media: subdev: add v4l2_subdev_set_routing_with_fmt() helper Tomi Valkeinen
2021-08-30 11:01 ` [PATCH v8 36/36] media: subdev: add v4l2_routing_simple_verify() helper Tomi Valkeinen
2021-09-20 10:19 ` [PATCH v8 00/36] v4l: subdev internal routing and streams Tomi Valkeinen
2021-09-27  1:24   ` Laurent Pinchart
2021-09-28  7:59     ` Jacopo Mondi

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=20210830110116.488338-29-tomi.valkeinen@ideasonboard.com \
    --to=tomi.valkeinen@ideasonboard.com \
    --cc=hverkuil-cisco@xs4all.nl \
    --cc=jacopo+renesas@jmondi.org \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-media@vger.kernel.org \
    --cc=lokeshvutla@ti.com \
    --cc=mchehab@kernel.org \
    --cc=michal.simek@xilinx.com \
    --cc=niklas.soderlund+renesas@ragnatech.se \
    --cc=p.yadav@ti.com \
    --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 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).