[PATCH v2] media: i2c: imx471: return 0 from get_selection after filling crop

John Cronin <[email protected]>
Newsgroups org.kernel.vger.linux-media
Message-ID <[email protected]>
libcamera issues VIDIOC_SUBDEV_G_SELECTION with target CROP (rectangle
0) during CameraSensorLegacy bring-up. imx471_get_selection filled the
rectangle then fell out of the switch and returned -EINVAL.

Fill every supported target, break, and return 0 after the switch
(default: -EINVAL), as Kate Hsuan suggested.

Compute analog crop in set_pad_format instead of storing a static
window on the mode: 2x binning, centered in the native array, same
idea as imx219. IMX471 2x2-binned 1928x1088 then reports CROP as
3856x2176 centered in 4672x3512.

Tested on ThinkPad X9-15 Gen 1 (SONY471A / IPU7), Fedora 44
kernel 7.1.8-200.fc44.

Link: https://bugzilla.redhat.com/show_bug.cgi?id=2454119
Signed-off-by: John Cronin <[email protected]>
---
 drivers/media/i2c/imx471.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/media/i2c/imx471.c b/drivers/media/i2c/imx471.c
index a0d7d7f..cab9797 100644
--- a/drivers/media/i2c/imx471.c
+++ b/drivers/media/i2c/imx471.c
@@ -430,6 +430,22 @@ static int imx471_set_pad_format(struct v4l2_subdev *sd,
 	imx471_update_pad_format(sensor, mode, fmt);
 
 	*v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format;
+
+	/* Analog crop: 2x bin, centered in the native array (same idea as imx219). */
+	{
+		struct v4l2_rect *crop;
+		u8 bin_h, bin_v, binning;
+
+		crop = v4l2_subdev_state_get_crop(sd_state, fmt->pad);
+		bin_h = min_t(u32, IMX471_PIXEL_ARRAY_WIDTH / fmt->format.width, 2);
+		bin_v = min_t(u32, IMX471_PIXEL_ARRAY_HEIGHT / fmt->format.height, 2);
+		binning = min(bin_h, bin_v);
+		crop->width = fmt->format.width * binning;
+		crop->height = fmt->format.height * binning;
+		crop->left = (IMX471_NATIVE_WIDTH - crop->width) / 2;
+		crop->top = (IMX471_NATIVE_HEIGHT - crop->height) / 2;
+	}
+
 	if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
 		return 0;
 
@@ -467,7 +483,7 @@ static int imx471_get_selection(struct v4l2_subdev *sd,
 		sel->r.left = 0;
 		sel->r.width = IMX471_NATIVE_WIDTH;
 		sel->r.height = IMX471_NATIVE_HEIGHT;
-		return 0;
+		break;
 
 	case V4L2_SEL_TGT_CROP_DEFAULT:
 	case V4L2_SEL_TGT_CROP_BOUNDS:
@@ -475,10 +491,13 @@ static int imx471_get_selection(struct v4l2_subdev *sd,
 		sel->r.left = IMX471_PIXEL_ARRAY_LEFT;
 		sel->r.width = IMX471_PIXEL_ARRAY_WIDTH;
 		sel->r.height = IMX471_PIXEL_ARRAY_HEIGHT;
-		return 0;
+		break;
+
+	default:
+		return -EINVAL;
 	}
 
-	return -EINVAL;
+	return 0;
 }
 
 static int imx471_init_state(struct v4l2_subdev *sd,
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.