diff options
| author | Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> | 2026-03-19 02:59:05 +0300 |
|---|---|---|
| committer | Hans Verkuil <hverkuil+cisco@kernel.org> | 2026-03-25 12:25:49 +0300 |
| commit | d17d21bb0e161bdd52135bca5d461b7fe672e0ee (patch) | |
| tree | df4fabffd6e22dbf578fd34717d24f3d5f05e129 | |
| parent | 1b5db4e308443227ed5b97d8e5c287c6fc34eb4b (diff) | |
| download | linux-d17d21bb0e161bdd52135bca5d461b7fe672e0ee.tar.xz | |
media: renesas: vsp1: histo: Fix format setting
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 <prabhakar.mahadev-lad.rj@bp.renesas.com> # HiHope RZ/G2M
Link: https://patch.msgid.link/20260318235907.831556-12-laurent.pinchart+renesas@ideasonboard.com
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
| -rw-r--r-- | drivers/media/platform/renesas/vsp1/vsp1_histo.c | 67 |
1 files 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 = { |
