]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
media: v4l2-subdev: Support hybrid links in v4l2_subdev_link_validate()
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Wed, 19 Jun 2024 00:02:42 +0000 (03:02 +0300)
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Mon, 26 Aug 2024 13:36:14 +0000 (16:36 +0300)
The v4l2_subdev_link_validate() helper function is meant to be used as a
drop-in implementation of a V4L2 subdev entity .link_validate() handler.
It supports subdev-to-subdev links only, and complains if one end of the
link is not a subdev. This forces drivers that have video output devices
connected to subdevs to implement a custom .link_validate() handler,
calling v4l2_subdev_link_validate() for the subdev-to-subdev links, and
performing manual link validation for the video-to-subdev links.

Video devices embed a media entity, and therefore also have a
.link_validate() operation. For video capture devices, the operation
should be manually implemented by drivers for validate the
subdev-to-video links. For video output devices, on the other hand, that
operation is never called, as link validation is performed in the
context of the sink entity.

As a result, we end up forcing drivers to implement a custom
.link_validate() handler for subdevs connected to video output devices,
when the video devices provide an operation that could be used for that
purpose.

To improve that situation, make v4l2_subdev_link_validate() delegate
link validation to the source's .link_validate() operation when the link
source is a video device and the link sink is a subdev. This allows
broader usage of v4l2_subdev_link_validate(), and simplifies drivers by
making video device link validation easy to implement in the video
device .link_validate(), regardless of whether the video device is an
output device or a capture device.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Tomi Valkeinen <tomi.valkeinen+renesas@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
drivers/media/v4l2-core/v4l2-subdev.c
include/media/v4l2-subdev.h

index d3196042d5c5715c8a37870c86ee358dcdd7c5fb..3a4ba08810d249a94ce8de31059c20a198c55a49 100644 (file)
@@ -1450,13 +1450,46 @@ int v4l2_subdev_link_validate(struct media_link *link)
        if (WARN_ON_ONCE(!is_media_entity_v4l2_subdev(link->sink->entity)))
                return -EINVAL;
 
-       if (!is_media_entity_v4l2_subdev(link->source->entity)) {
-               pr_warn_once("source of link '%s':%u->'%s':%u is not a V4L2 sub-device, driver bug!\n",
-                            link->source->entity->name, link->source->index,
-                            link->sink->entity->name, link->sink->index);
-               return 0;
+       /*
+        * If the source is a video device, delegate link validation to it. This
+        * allows usage of this helper for subdev connected to a video output
+        * device, provided that the driver implement the video output device's
+        * .link_validate() operation.
+        */
+       if (is_media_entity_v4l2_video_device(link->source->entity)) {
+               struct media_entity *source = link->source->entity;
+
+               if (!source->ops || !source->ops->link_validate) {
+                       /*
+                        * Many existing drivers do not implement the required
+                        * .link_validate() operation for their video devices.
+                        * Print a warning to get the drivers fixed, and return
+                        * 0 to avoid breaking userspace. This should
+                        * eventually be turned into a WARN_ON() when all
+                        * drivers will have been fixed.
+                        */
+                       pr_warn_once("video device '%s' does not implement .link_validate(), driver bug!\n",
+                                    source->name);
+                       return 0;
+               }
+
+               /*
+                * Avoid infinite loops in case a video device incorrectly uses
+                * this helper function as its .link_validate() handler.
+                */
+               if (WARN_ON(source->ops->link_validate == v4l2_subdev_link_validate))
+                       return -EINVAL;
+
+               return source->ops->link_validate(link);
        }
 
+       /*
+        * If the source is still not a subdev, usage of this helper is a clear
+        * driver bug.
+        */
+       if (WARN_ON(!is_media_entity_v4l2_subdev(link->source->entity)))
+               return -EINVAL;
+
        sink_sd = media_entity_to_v4l2_subdev(link->sink->entity);
        source_sd = media_entity_to_v4l2_subdev(link->source->entity);
 
index bd235d325ff96cd094bbd693d91f719fe186416b..8daa0929865cfa3caee4154d52fc206e17e66534 100644 (file)
@@ -1250,6 +1250,12 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev *sd,
  * calls v4l2_subdev_link_validate_default() to ensure that
  * width, height and the media bus pixel code are equal on both
  * source and sink of the link.
+ *
+ * The function can be used as a drop-in &media_entity_ops.link_validate
+ * implementation for v4l2_subdev instances. It supports all links between
+ * subdevs, as well as links between subdevs and video devices, provided that
+ * the video devices also implement their &media_entity_ops.link_validate
+ * operation.
  */
 int v4l2_subdev_link_validate(struct media_link *link);