On Thu Mar 19 01:58:58 2026 +0200, Laurent Pinchart wrote:
> The RPF doesn't enforces the alignment constraint on the sink pad
> format, which could have an odd size, possibly down to 1x1. In that
> case, the upper bounds for the left and top coordinates clamping would
> become negative, cast to a very large positive value. Incorrect crop
> rectangle coordinates would then be incorrectly accepted.
> 
> A second issue can occur when the requested left and top coordinates are
> negative. They are cast to a large unsigned value, clamped to the
> maximum. While the calculation will produce valid values for the
> hardware, this is not compliant with the V4L2 specification that
> requires values to be adjusted to the closest valid value.
> 
> Fix both issues by switching to signed clamping, with an explicit
> minimum to adjust negative values, and adjusting the clamp bounds to
> avoid negative upper bounds.
> 
> Tested-by: Niklas Söderlund <[email protected]>
> Reviewed-by: Jacopo Mondi <[email protected]>
> Tested-by: Lad Prabhakar <[email protected]> # HiHope 
> RZ/G2M
> Link: 
> https://patch.msgid.link/20260318235907.831556-5-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_rwpf.c | 28 +++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

---

diff --git a/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c 
b/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
index 56464875a6c5..ffc1b3ab54e2 100644
--- a/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
+++ b/drivers/media/platform/renesas/vsp1/vsp1_rwpf.c
@@ -201,6 +201,8 @@ static int vsp1_rwpf_set_selection(struct v4l2_subdev 
*subdev,
                                   struct v4l2_subdev_state *sd_state,
                                   struct v4l2_subdev_selection *sel)
 {
+       unsigned int min_width = RWPF_MIN_WIDTH;
+       unsigned int min_height = RWPF_MIN_HEIGHT;
        struct vsp1_rwpf *rwpf = to_rwpf(subdev);
        struct v4l2_subdev_state *state;
        struct v4l2_mbus_framefmt *format;
@@ -229,18 +231,36 @@ static int vsp1_rwpf_set_selection(struct v4l2_subdev 
*subdev,
        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.
+        * 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 = 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);
+
+               /*
+                * The RPF doesn't enforces the alignment constraint on the sink
+                * pad format, which could have an odd size, possibly down to
+                * 1x1. In that case, the minimum width and height would be
+                * smaller than the sink pad format, leading to a negative upper
+                * bound in the left and top clamping. Clamp the minimum width
+                * and height to the format width and height to avoid this.
+                *
+                * In such a situation, odd values for the crop rectangle size
+                * would be accepted when clamping the width and height below.
+                * While that would create an invalid hardware configuration,
+                * the video device enforces proper alignment of the pixel
+                * format, and the mismatch will then result in link validation
+                * failure. Incorrect operation of the hardware is not possible.
+                */
+               min_width = min(ALIGN(min_width, 2), format->width);
+               min_height = min(ALIGN(min_height, 2), format->height);
        }
 
-       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.left = clamp_t(int, sel->r.left, 0, format->width - min_width);
+       sel->r.top = clamp_t(int, sel->r.top, 0, format->height - min_height);
        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,
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to