This is an automatic generated email to let you know that the following patch 
were queued:

Subject: media: subdev: Improve v4l2_subdev_enable/disable_streams_fallback
Author:  Tomi Valkeinen <tomi.valkei...@ideasonboard.com>
Date:    Wed Apr 24 18:39:08 2024 +0300

v4l2_subdev_enable/disable_streams_fallback() supports falling back to
.s_stream() for subdevs with a single source pad. It also tracks the
enabled streams for that one pad in the sd->enabled_streams field.

Tracking the enabled streams with sd->enabled_streams does not make
sense, as with .s_stream() there can only be a single stream per pad.
Thus, as the v4l2_subdev_enable/disable_streams_fallback() only supports
a single source pad, all we really need is a boolean which tells whether
streaming has been enabled on this pad or not.

However, as we only need a true/false state for a pad (instead of
tracking which streams have been enabled for a pad), we can easily
extend the fallback mechanism to support multiple source pads as we only
need to keep track of which pads have been enabled.

Change the sd->enabled_streams field to sd->enabled_pads, which is a
64-bit bitmask tracking the enabled source pads. With this change we can
remove the restriction that
v4l2_subdev_enable/disable_streams_fallback() only supports a single
source pad.

Reviewed-by: Laurent Pinchart <laurent.pinch...@ideasonboard.com>
Tested-by: Umang Jain <umang.j...@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkei...@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ai...@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-ci...@xs4all.nl>

 drivers/media/v4l2-core/v4l2-subdev.c | 68 ++++++++++++++++++++---------------
 include/media/v4l2-subdev.h           |  9 +++--
 2 files changed, 44 insertions(+), 33 deletions(-)

---

diff --git a/drivers/media/v4l2-core/v4l2-subdev.c 
b/drivers/media/v4l2-core/v4l2-subdev.c
index 8675ad0688af..0231acf7168e 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -2159,37 +2159,43 @@ static int v4l2_subdev_enable_streams_fallback(struct 
v4l2_subdev *sd, u32 pad,
                                               u64 streams_mask)
 {
        struct device *dev = sd->entity.graph_obj.mdev->dev;
-       unsigned int i;
        int ret;
 
        /*
         * The subdev doesn't implement pad-based stream enable, fall back
-        * on the .s_stream() operation. This can only be done for subdevs that
-        * have a single source pad, as sd->enabled_streams is global to the
-        * subdev.
+        * to the .s_stream() operation.
         */
        if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE))
                return -EOPNOTSUPP;
 
-       for (i = 0; i < sd->entity.num_pads; ++i) {
-               if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
-                       return -EOPNOTSUPP;
-       }
+       /*
+        * .s_stream() means there is no streams support, so the only allowed
+        * stream is the implicit stream 0.
+        */
+       if (streams_mask != BIT_ULL(0))
+               return -EOPNOTSUPP;
+
+       /*
+        * We use a 64-bit bitmask for tracking enabled pads, so only subdevices
+        * with 64 pads or less can be supported.
+        */
+       if (pad >= sizeof(sd->enabled_pads) * BITS_PER_BYTE)
+               return -EOPNOTSUPP;
 
-       if (sd->enabled_streams & streams_mask) {
-               dev_dbg(dev, "set of streams %#llx already enabled on %s:%u\n",
-                       streams_mask, sd->entity.name, pad);
+       if (sd->enabled_pads & BIT_ULL(pad)) {
+               dev_dbg(dev, "pad %u already enabled on %s\n",
+                       pad, sd->entity.name);
                return -EALREADY;
        }
 
-       /* Start streaming when the first streams are enabled. */
-       if (!sd->enabled_streams) {
+       /* Start streaming when the first pad is enabled. */
+       if (!sd->enabled_pads) {
                ret = v4l2_subdev_call(sd, video, s_stream, 1);
                if (ret)
                        return ret;
        }
 
-       sd->enabled_streams |= streams_mask;
+       sd->enabled_pads |= BIT_ULL(pad);
 
        return 0;
 }
@@ -2276,37 +2282,43 @@ static int v4l2_subdev_disable_streams_fallback(struct 
v4l2_subdev *sd, u32 pad,
                                                u64 streams_mask)
 {
        struct device *dev = sd->entity.graph_obj.mdev->dev;
-       unsigned int i;
        int ret;
 
        /*
-        * If the subdev doesn't implement pad-based stream enable, fall  back
-        * on the .s_stream() operation. This can only be done for subdevs that
-        * have a single source pad, as sd->enabled_streams is global to the
-        * subdev.
+        * If the subdev doesn't implement pad-based stream enable, fall back
+        * to the .s_stream() operation.
         */
        if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE))
                return -EOPNOTSUPP;
 
-       for (i = 0; i < sd->entity.num_pads; ++i) {
-               if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
-                       return -EOPNOTSUPP;
-       }
+       /*
+        * .s_stream() means there is no streams support, so the only allowed
+        * stream is the implicit stream 0.
+        */
+       if (streams_mask != BIT_ULL(0))
+               return -EOPNOTSUPP;
+
+       /*
+        * We use a 64-bit bitmask for tracking enabled pads, so only subdevices
+        * with 64 pads or less can be supported.
+        */
+       if (pad >= sizeof(sd->enabled_pads) * BITS_PER_BYTE)
+               return -EOPNOTSUPP;
 
-       if ((sd->enabled_streams & streams_mask) != streams_mask) {
-               dev_dbg(dev, "set of streams %#llx already disabled on %s:%u\n",
-                       streams_mask, sd->entity.name, pad);
+       if (!(sd->enabled_pads & BIT_ULL(pad))) {
+               dev_dbg(dev, "pad %u already disabled on %s\n",
+                       pad, sd->entity.name);
                return -EALREADY;
        }
 
        /* Stop streaming when the last streams are disabled. */
-       if (!(sd->enabled_streams & ~streams_mask)) {
+       if (!(sd->enabled_pads & ~BIT_ULL(pad))) {
                ret = v4l2_subdev_call(sd, video, s_stream, 0);
                if (ret)
                        return ret;
        }
 
-       sd->enabled_streams &= ~streams_mask;
+       sd->enabled_pads &= ~BIT_ULL(pad);
 
        return 0;
 }
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index d3f15882927b..f191cf00c840 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -1041,10 +1041,9 @@ struct v4l2_subdev_platform_data {
  * @active_state: Active state for the subdev (NULL for subdevs tracking the
  *               state internally). Initialized by calling
  *               v4l2_subdev_init_finalize().
- * @enabled_streams: Bitmask of enabled streams used by
- *                  v4l2_subdev_enable_streams() and
- *                  v4l2_subdev_disable_streams() helper functions for fallback
- *                  cases.
+ * @enabled_pads: Bitmask of enabled pads used by v4l2_subdev_enable_streams()
+ *               and v4l2_subdev_disable_streams() helper functions for
+ *               fallback cases.
  * @s_stream_enabled: Tracks whether streaming has been enabled with s_stream.
  *                    This is only for call_s_stream() internal use.
  *
@@ -1094,7 +1093,7 @@ struct v4l2_subdev {
         * doesn't support it.
         */
        struct v4l2_subdev_state *active_state;
-       u64 enabled_streams;
+       u64 enabled_pads;
        bool s_stream_enabled;
 };
 

Reply via email to