diff mbox series

[4/7] media: renesas: vsp1: Fix RPF sink alignment for YUV formats

Message ID 20250429235322.29826-5-laurent.pinchart+renesas@ideasonboard.com
State New
Headers show
Series [1/7] media: renesas: vsp1: Store supported media bus codes in vsp1_entity | expand

Commit Message

Laurent Pinchart April 29, 2025, 11:53 p.m. UTC
When reading YUV formats from memory, the hardware requires the crop
rectangle size and position to be aligned to multiples of two, depending
on the horizontal and vertical subsampling factors. The driver doesn't
enforce this, leading to incorrect operation.

As the crop rectangle is implemented on the RPF subdev's sink pad,
enforcing the constraint conditionally based on the subsampling factors
is difficult, as those are only known by the RPF video device. We could
perform the check at pipeline validation time, but that could lead to
confusing -EPIPE errors. As there is very few use cases for odd crop
offsets and sizes with non-subsampled YUV, take the easier and more
user-friendly route of enforcing the constraint on all YUV formats.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 .../media/platform/renesas/vsp1/vsp1_rwpf.c   | 41 ++++++++++++-------
 1 file changed, 26 insertions(+), 15 deletions(-)
diff mbox series

Patch

diff --git a/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c b/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
index 83ff2c266038..61f7e13ebeee 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
@@ -117,6 +117,17 @@  static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev,
 				RWPF_MIN_WIDTH, rwpf->entity.max_width);
 	format->height = clamp_t(unsigned int, fmt->format.height,
 				 RWPF_MIN_HEIGHT, rwpf->entity.max_height);
+
+	/*
+	 * For YUV formats on the RPF, restrict the size to multiples of 2 to
+	 * avoid shifting the color plane.
+	 */
+	if (rwpf->entity.type == VSP1_ENTITY_RPF &&
+	    format->code == MEDIA_BUS_FMT_AYUV8_1X32) {
+		format->width = ALIGN(format->width, 2);
+		format->height = ALIGN(format->height, 2);
+	}
+
 	format->field = V4L2_FIELD_NONE;
 
 	format->colorspace = fmt->format.colorspace;
@@ -231,23 +242,23 @@  static int vsp1_rwpf_set_selection(struct v4l2_subdev *subdev,
 	/* Make sure the crop rectangle is entirely contained in the image. */
 	format = v4l2_subdev_state_get_format(state, RWPF_PAD_SINK);
 
-	/*
-	 * Restrict the crop rectangle coordinates to multiples of 2 to avoid
-	 * shifting the color plane.
-	 */
-	if (format->code == MEDIA_BUS_FMT_AYUV8_1X32) {
-		sel->r.left = ALIGN(sel->r.left, 2);
-		sel->r.top = ALIGN(sel->r.top, 2);
-		sel->r.width = round_down(sel->r.width, 2);
-		sel->r.height = round_down(sel->r.height, 2);
-	}
-
 	sel->r.left = min_t(unsigned int, sel->r.left, format->width - 2);
 	sel->r.top = min_t(unsigned int, sel->r.top, format->height - 2);
-	sel->r.width = min_t(unsigned int, sel->r.width,
-			     format->width - sel->r.left);
-	sel->r.height = min_t(unsigned int, sel->r.height,
-			      format->height - sel->r.top);
+	sel->r.width = clamp_t(unsigned int, sel->r.width, RWPF_MIN_WIDTH,
+			       format->width - sel->r.left);
+	sel->r.height = clamp_t(unsigned int, sel->r.height, RWPF_MIN_HEIGHT,
+				format->height - sel->r.top);
+
+	/*
+	 * For YUV formats, restrict the crop rectangle coordinates to multiples
+	 * of 2 to avoid shifting the color plane.
+	 */
+	if (format->code == MEDIA_BUS_FMT_AYUV8_1X32) {
+		sel->r.left = round_down(sel->r.left, 2);
+		sel->r.top = round_down(sel->r.top, 2);
+		sel->r.width = ALIGN(sel->r.width, 2);
+		sel->r.height = ALIGN(sel->r.height, 2);
+	}
 
 	crop = v4l2_subdev_state_get_crop(state, RWPF_PAD_SINK);
 	*crop = sel->r;