Hi Laurent On Wed, Apr 30, 2025 at 02:53:18AM +0300, Laurent Pinchart wrote: > 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. > > Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@xxxxxxxxxxxxxxxx> > --- > .../media/platform/renesas/vsp1/vsp1_entity.c | 47 +++++++++++-------- > .../media/platform/renesas/vsp1/vsp1_sru.c | 36 ++++++-------- > .../media/platform/renesas/vsp1/vsp1_uds.c | 36 ++++++-------- > 3 files changed, 58 insertions(+), 61 deletions(-) > > diff --git a/drivers/media/platform/renesas/vsp1/vsp1_entity.c b/drivers/media/platform/renesas/vsp1/vsp1_entity.c > index 0d4fe0028b13..a3d4bf2887ec 100644 > --- a/drivers/media/platform/renesas/vsp1/vsp1_entity.c > +++ b/drivers/media/platform/renesas/vsp1/vsp1_entity.c > @@ -233,42 +233,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); > - > - mutex_lock(&entity->lock); > - > - if (fse->index || fse->code != format->code) { > - ret = -EINVAL; > - goto done; > - } > - > if (fse->pad == 0) { > + unsigned int i; > + > + for (i = 0; i < entity->num_codes; ++i) { > + if (fse->code == entity->codes[i]) > + break; > + } > + > + if (i == entity->num_codes) > + return -EINVAL; > + > 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); Should you now include cleanup.h ? > + > + 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..e821eac1cbc2 100644 > --- a/drivers/media/platform/renesas/vsp1/vsp1_sru.c > +++ b/drivers/media/platform/renesas/vsp1/vsp1_sru.c > @@ -116,29 +116,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 +147,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..95c9939ae077 100644 > --- a/drivers/media/platform/renesas/vsp1/vsp1_uds.c > +++ b/drivers/media/platform/renesas/vsp1/vsp1_uds.c > @@ -121,38 +121,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, > -- > Regards, > > Laurent Pinchart > >