]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
media: renesas: vsp1: Fix code checks in frame size enumeration
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Wed, 18 Mar 2026 23:58:57 +0000 (01:58 +0200)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Wed, 25 Mar 2026 09:25:48 +0000 (10:25 +0100)
The media bus code passed to the .enum_frame_size() operation for the
sink pad is required to be supported by the device, but not to match the
current format. All entities that use the vsp1_subdev_enum_frame_size()
helper, as well as the SRU and UDS entities that implement the operation
manually, perform the check incorrectly.

Fix the issue by implementing the correct code check in the
vsp1_subdev_enum_frame_size(). For the SRU and UDS, to avoid duplicating
code, use the vsp1_subdev_enum_frame_size() as a base and override the
enumerated size on the source pad with entity-specific constraints.

While at it, include the missing <linux/mutex.h> as the code locks
mutexes.

Tested-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Tested-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> # HiHope RZ/G2M
Link: https://patch.msgid.link/20260318235907.831556-4-laurent.pinchart+renesas@ideasonboard.com
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
drivers/media/platform/renesas/vsp1/vsp1_entity.c
drivers/media/platform/renesas/vsp1/vsp1_sru.c
drivers/media/platform/renesas/vsp1/vsp1_uds.c

index 04b7ae6fb93554904b67439a0c0d8021202636c5..892a2adfdf3a7eb141cb1876940ac411f13c661b 100644 (file)
@@ -7,8 +7,10 @@
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
+#include <linux/cleanup.h>
 #include <linux/device.h>
 #include <linux/gfp.h>
+#include <linux/mutex.h>
 
 #include <media/media-entity.h>
 #include <media/v4l2-ctrls.h>
@@ -238,42 +240,51 @@ int vsp1_subdev_enum_frame_size(struct v4l2_subdev *subdev,
                                struct v4l2_subdev_frame_size_enum *fse)
 {
        struct vsp1_entity *entity = to_vsp1_entity(subdev);
-       struct v4l2_subdev_state *state;
-       struct v4l2_mbus_framefmt *format;
-       int ret = 0;
 
-       state = vsp1_entity_get_state(entity, sd_state, fse->which);
-       if (!state)
+       if (fse->index)
                return -EINVAL;
 
-       format = v4l2_subdev_state_get_format(state, fse->pad);
+       if (fse->pad == 0) {
+               unsigned int i;
 
-       mutex_lock(&entity->lock);
+               for (i = 0; i < entity->num_codes; ++i) {
+                       if (fse->code == entity->codes[i])
+                               break;
+               }
 
-       if (fse->index || fse->code != format->code) {
-               ret = -EINVAL;
-               goto done;
-       }
+               if (i == entity->num_codes)
+                       return -EINVAL;
 
-       if (fse->pad == 0) {
                fse->min_width = entity->min_width;
                fse->max_width = entity->max_width;
                fse->min_height = entity->min_height;
                fse->max_height = entity->max_height;
        } else {
+               struct v4l2_subdev_state *state;
+               struct v4l2_mbus_framefmt *format;
+
+               state = vsp1_entity_get_state(entity, sd_state, fse->which);
+               if (!state)
+                       return -EINVAL;
+
                /*
-                * The size on the source pad are fixed and always identical to
-                * the size on the sink pad.
+                * The media bus code and size on the source pad are fixed and
+                * always identical to the sink pad.
                 */
+               format = v4l2_subdev_state_get_format(state, 0);
+
+               guard(mutex)(&entity->lock);
+
+               if (fse->code != format->code)
+                       return -EINVAL;
+
                fse->min_width = format->width;
                fse->max_width = format->width;
                fse->min_height = format->height;
                fse->max_height = format->height;
        }
 
-done:
-       mutex_unlock(&entity->lock);
-       return ret;
+       return 0;
 }
 
 /*
index 1dc34e6a510d24e0ebaca41da018e8785f9725b3..37fd36d09045a221fb7a9fe252158818eb340d21 100644 (file)
@@ -7,8 +7,10 @@
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
+#include <linux/cleanup.h>
 #include <linux/device.h>
 #include <linux/gfp.h>
+#include <linux/mutex.h>
 
 #include <media/v4l2-subdev.h>
 
@@ -116,29 +118,25 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev,
                               struct v4l2_subdev_frame_size_enum *fse)
 {
        struct vsp1_sru *sru = to_sru(subdev);
-       struct v4l2_subdev_state *state;
-       struct v4l2_mbus_framefmt *format;
-       int ret = 0;
+       int ret;
 
-       state = vsp1_entity_get_state(&sru->entity, sd_state, fse->which);
-       if (!state)
-               return -EINVAL;
+       ret = vsp1_subdev_enum_frame_size(subdev, sd_state, fse);
+       if (ret)
+               return ret;
 
-       format = v4l2_subdev_state_get_format(state, SRU_PAD_SINK);
+       if (fse->pad == SRU_PAD_SOURCE) {
+               struct v4l2_subdev_state *state;
+               struct v4l2_mbus_framefmt *format;
 
-       mutex_lock(&sru->entity.lock);
+               state = vsp1_entity_get_state(&sru->entity, sd_state,
+                                             fse->which);
+               if (!state)
+                       return -EINVAL;
 
-       if (fse->index || fse->code != format->code) {
-               ret = -EINVAL;
-               goto done;
-       }
+               format = v4l2_subdev_state_get_format(state, SRU_PAD_SINK);
+
+               guard(mutex)(&sru->entity.lock);
 
-       if (fse->pad == SRU_PAD_SINK) {
-               fse->min_width = SRU_MIN_SIZE;
-               fse->max_width = SRU_MAX_SIZE;
-               fse->min_height = SRU_MIN_SIZE;
-               fse->max_height = SRU_MAX_SIZE;
-       } else {
                fse->min_width = format->width;
                fse->min_height = format->height;
                if (format->width <= SRU_MAX_SIZE / 2 &&
@@ -151,9 +149,7 @@ static int sru_enum_frame_size(struct v4l2_subdev *subdev,
                }
        }
 
-done:
-       mutex_unlock(&sru->entity.lock);
-       return ret;
+       return 0;
 }
 
 static void sru_try_format(struct vsp1_sru *sru,
index 8006d49ffbea5e301edd3d7bcf24978671347b69..dd4722315c564e0180847e4bebac1ece35325b59 100644 (file)
@@ -7,8 +7,10 @@
  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
  */
 
+#include <linux/cleanup.h>
 #include <linux/device.h>
 #include <linux/gfp.h>
+#include <linux/mutex.h>
 
 #include <media/v4l2-subdev.h>
 
@@ -121,38 +123,32 @@ static int uds_enum_frame_size(struct v4l2_subdev *subdev,
                               struct v4l2_subdev_frame_size_enum *fse)
 {
        struct vsp1_uds *uds = to_uds(subdev);
-       struct v4l2_subdev_state *state;
-       struct v4l2_mbus_framefmt *format;
-       int ret = 0;
+       int ret;
 
-       state = vsp1_entity_get_state(&uds->entity, sd_state, fse->which);
-       if (!state)
-               return -EINVAL;
+       ret = vsp1_subdev_enum_frame_size(subdev, sd_state, fse);
+       if (ret)
+               return ret;
 
-       format = v4l2_subdev_state_get_format(state, UDS_PAD_SINK);
+       if (fse->pad == UDS_PAD_SOURCE) {
+               struct v4l2_subdev_state *state;
+               struct v4l2_mbus_framefmt *format;
 
-       mutex_lock(&uds->entity.lock);
+               state = vsp1_entity_get_state(&uds->entity, sd_state,
+                                             fse->which);
+               if (!state)
+                       return -EINVAL;
 
-       if (fse->index || fse->code != format->code) {
-               ret = -EINVAL;
-               goto done;
-       }
+               format = v4l2_subdev_state_get_format(state, UDS_PAD_SINK);
+
+               guard(mutex)(&uds->entity.lock);
 
-       if (fse->pad == UDS_PAD_SINK) {
-               fse->min_width = UDS_MIN_SIZE;
-               fse->max_width = UDS_MAX_SIZE;
-               fse->min_height = UDS_MIN_SIZE;
-               fse->max_height = UDS_MAX_SIZE;
-       } else {
                uds_output_limits(format->width, &fse->min_width,
                                  &fse->max_width);
                uds_output_limits(format->height, &fse->min_height,
                                  &fse->max_height);
        }
 
-done:
-       mutex_unlock(&uds->entity.lock);
-       return ret;
+       return 0;
 }
 
 static void uds_try_format(struct vsp1_uds *uds,