From: Laurent Pinchart Date: Wed, 18 Mar 2026 23:58:57 +0000 (+0200) Subject: media: renesas: vsp1: Fix code checks in frame size enumeration X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46d3ad607037b61747d980fc612d36bf489d3709;p=thirdparty%2Fkernel%2Fstable.git media: renesas: vsp1: Fix code checks in frame size enumeration 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 as the code locks mutexes. Tested-by: Niklas Söderlund Tested-by: Lad Prabhakar # HiHope RZ/G2M Link: https://patch.msgid.link/20260318235907.831556-4-laurent.pinchart+renesas@ideasonboard.com Signed-off-by: Laurent Pinchart Signed-off-by: Hans Verkuil --- diff --git a/drivers/media/platform/renesas/vsp1/vsp1_entity.c b/drivers/media/platform/renesas/vsp1/vsp1_entity.c index 04b7ae6fb935..892a2adfdf3a 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_entity.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_entity.c @@ -7,8 +7,10 @@ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) */ +#include #include #include +#include #include #include @@ -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; } /* diff --git a/drivers/media/platform/renesas/vsp1/vsp1_sru.c b/drivers/media/platform/renesas/vsp1/vsp1_sru.c index 1dc34e6a510d..37fd36d09045 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_sru.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_sru.c @@ -7,8 +7,10 @@ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) */ +#include #include #include +#include #include @@ -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, diff --git a/drivers/media/platform/renesas/vsp1/vsp1_uds.c b/drivers/media/platform/renesas/vsp1/vsp1_uds.c index 8006d49ffbea..dd4722315c56 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_uds.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_uds.c @@ -7,8 +7,10 @@ * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) */ +#include #include #include +#include #include @@ -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,