On Thu Mar 19 01:59:05 2026 +0200, Laurent Pinchart wrote:
> The histogram .set_fmt() handler suffers from two problems:
> 
> - When operating on the source pad, it returns correct information to
>   userspace, but does not store the format in the subdev state.
>   Subsequent calls to .get_fmt(), handled by the
>   vsp1_subdev_get_pad_format() helper, will not return the correct
>   information.
> 
> - When operating on the sink pad, it uses the
>   vsp1_subdev_set_pad_format(), which propagates the sink format to the
>   source, incorrectly overwriting the fixed source format.
> 
> The first issue could be fixed by implementing the set format operation
> with vsp1_subdev_get_pad_format() on the source pad, if it wasn't that
> .set_fmt() is also used to initialize the subdev state in
> vsp1_entity_init_state(). The histogram would need a custom
> .init_state() handler.
> 
> As the second issue would anyway overwrite the format, and therefore
> requires a custom .set_fmt() implementation, fix both issues without
> using the helpers.
> 
> Tested-by: Lad Prabhakar <[email protected]> # HiHope 
> RZ/G2M
> Link: 
> https://patch.msgid.link/20260318235907.831556-12-laurent.pinchart+rene...@ideasonboard.com
> Signed-off-by: Laurent Pinchart <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>

Patch committed.

Thanks,
Hans Verkuil

 drivers/media/platform/renesas/vsp1/vsp1_histo.c | 67 +++++++++++++++++++++---
 1 file changed, 59 insertions(+), 8 deletions(-)

---

diff --git a/drivers/media/platform/renesas/vsp1/vsp1_histo.c 
b/drivers/media/platform/renesas/vsp1/vsp1_histo.c
index 313b9f3ce0f1..79da56c456eb 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_histo.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_histo.c
@@ -350,17 +350,68 @@ static int histo_set_format(struct v4l2_subdev *subdev,
                            struct v4l2_subdev_state *sd_state,
                            struct v4l2_subdev_format *fmt)
 {
-       if (fmt->pad == HISTO_PAD_SOURCE) {
-               fmt->format.code = MEDIA_BUS_FMT_FIXED;
-               fmt->format.width = 0;
-               fmt->format.height = 0;
-               fmt->format.field = V4L2_FIELD_NONE;
-               fmt->format.colorspace = V4L2_COLORSPACE_RAW;
+       struct vsp1_entity *entity = to_vsp1_entity(subdev);
+       struct v4l2_subdev_state *state;
+       struct v4l2_mbus_framefmt *format;
+       struct v4l2_rect *selection;
+       unsigned int i;
 
-               return 0;
+       state = vsp1_entity_get_state(entity, sd_state, fmt->which);
+       if (!state)
+               return -EINVAL;
+
+       format = v4l2_subdev_state_get_format(state, fmt->pad);
+
+       guard(mutex)(&entity->lock);
+
+       if (fmt->pad == HISTO_PAD_SINK) {
+               /*
+                * Default to the first media bus code if the requested format
+                * is not supported.
+                */
+               for (i = 0; i < entity->num_codes; ++i) {
+                       if (fmt->format.code == entity->codes[i])
+                               break;
+               }
+
+               format->code = i < entity->num_codes
+                            ? entity->codes[i] : entity->codes[0];
+               format->width = clamp_t(unsigned int, fmt->format.width,
+                                       entity->min_width, entity->max_width);
+               format->height = clamp_t(unsigned int, fmt->format.height,
+                                        entity->min_height, 
entity->max_height);
+               format->field = V4L2_FIELD_NONE;
+
+               format->colorspace = fmt->format.colorspace;
+               format->xfer_func = fmt->format.xfer_func;
+               format->ycbcr_enc = fmt->format.ycbcr_enc;
+               format->quantization = fmt->format.quantization;
+
+               vsp1_entity_adjust_color_space(format);
+
+               /* Reset the crop and compose rectangles. */
+               selection = v4l2_subdev_state_get_crop(state, fmt->pad);
+               selection->left = 0;
+               selection->top = 0;
+               selection->width = format->width;
+               selection->height = format->height;
+
+               selection = v4l2_subdev_state_get_compose(state, fmt->pad);
+               selection->left = 0;
+               selection->top = 0;
+               selection->width = format->width;
+               selection->height = format->height;
+       } else {
+               format->code = MEDIA_BUS_FMT_METADATA_FIXED;
+               format->width = 0;
+               format->height = 0;
+               format->field = V4L2_FIELD_NONE;
+               format->colorspace = V4L2_COLORSPACE_RAW;
        }
 
-       return vsp1_subdev_set_pad_format(subdev, sd_state, fmt);
+       fmt->format = *format;
+
+       return 0;
 }
 
 static const struct v4l2_subdev_pad_ops histo_pad_ops = {
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to