[PATCH v5] 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. Compute analog crop in set_pad_format: 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). Link: https://bugzilla.redhat.com/show_bug.cgi?id=2454119 Signed-off-by: John Cronin <[email protected]> Signed-off-by: John Cronin <[email protected]> --- v5: drop extra braces; declare crop/bin vars at start of set_pad_format (sorted by line length); wrap to 80 cols; keep only the bug/feature in the commit log v4: add Signed-off-by for [email protected] v3: rebase on media-committers next v2: compute analog crop in set_pad_format; return 0 after switch drivers/media/i2c/imx471.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/media/i2c/imx471.c b/drivers/media/i2c/imx471.c index 4053aed84..0ea18fbb9 100644 --- a/drivers/media/i2c/imx471.c +++ b/drivers/media/i2c/imx471.c @@ -421,6 +421,8 @@ static int imx471_set_pad_format(struct v4l2_subdev *sd, { struct imx471 *sensor = to_imx471(sd); const struct imx471_mode *mode; + u8 bin_h, bin_v, binning; + struct v4l2_rect *crop; int h_blank, ret; mode = v4l2_find_nearest_size(imx471_modes, ARRAY_SIZE(imx471_modes), @@ -431,6 +433,18 @@ static int imx471_set_pad_format(struct v4l2_subdev *sd, *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format; + /* Analog crop: 2x bin, centered in native array (imx219). */ + 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; @@ -468,7 +482,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: @@ -476,10 +490,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