Re: [PATCH 18/19] media: i2c: imx290: Add crop selection targets support

Laurent Pinchart
2022-10-16T05:53:42Z

Hi Dave,

On Thu, Jul 21, 2022 at 04:39:08PM +0100, Dave Stevenson wrote:
> On Thu, 21 Jul 2022 at 09:36, Laurent Pinchart wrote:
> > Implement read-only access to crop selection rectangles to expose the
> > analogue crop rectangle. The public (leaked) IMX290 documentation is not
> > very clear on how cropping is implemented and configured exactly, so
> > the margins may not be entirely accurate.
> >
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > drivers/media/i2c/imx290.c | 94 ++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 94 insertions(+)
> >
> > diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
> > index baf9941c5fbe..0cb11ec1cf0f 100644
> > --- a/drivers/media/i2c/imx290.c
> > +++ b/drivers/media/i2c/imx290.c
> > @@ -105,6 +105,53 @@
> >
> > #define IMX290_VMAX_DEFAULT 1125
> >
> > +
> > +/*
> > + * The IMX290 pixel array is organized as follows:
> > + *
> > + * +------------------------------------+
> > + * | Optical Black | } Vertical effective optical black (10)
> > + * +---+------------------------------------+---+
> > + * | | | | } Effective top margin (8)
> > + * | | +----------------------------+ | | \
> > + * | | | | | | |
> > + * | | | | | | |
> > + * | | | | | | |
> > + * | | | Recording Pixel Area | | | | Recommended height (1080)
> > + * | | | | | | |
> > + * | | | | | | |
> > + * | | | | | | |
> > + * | | +----------------------------+ | | /
> > + * | | | | } Effective bottom margin (8)
>
> I have an official datasheet from Sony. "Effective margin for colour
> processing" at the bottom is stated to be 9 lines, not 8. That also
> makes the numbers then tally of total height being 8 + 1080 + 9 =
> 1097.

Will fix in v2. The value in the text and macro is correct, only the
diagram has an issue.

> Otherwise I agree with the numbers you quote here.
>
> My datasheet does go into how window mode is configured, however
> window mode is not being used.
> The register sets present in the driver set the output image size to
> 1920x1080 or 1280x720 of the overall 1945x1097 pixels. They differ
> slightly from the definitions given in the datasheet for the Full HD
> 1080p and HD720p modes which read out 1945x1097 and 1297x725 pixels
> respectively (assuming I've read it correctly). Exactly how those
> extra pixels are cropped off isn't defined, but I'd suspect it was the
> top left portion of the full image.
>
> If you want 100% defined cropping for each mode then that should be
> achievable using window mode.

I'd like that, but one thing at a time :-) I may experiment if I can
find free time.

> > + * +---+------------------------------------+---+
> > + * <-> <-> <--------------------------> <-> <->
> > + * \---- Ignored right margin (4)
> > + * \-------- Effective right margin (9)
> > + * \------------------------- Recommended width (1920)
> > + * \----------------------------------------- Effective left margin (8)
> > + * \--------------------------------------------- Ignored left margin (4)
> > + *
> > + * The optical black lines are output over CSI-2 with a separate data type.
> > + *
> > + * The pixel array is meant to have 1920x1080 usable pixels after image
> > + * processing in an ISP. It has 8 (9) extra active pixels usable for color
> > + * processing in the ISP on the top and left (bottom and right) sides of the
> > + * image. In addition, 4 additional pixels are present on the left and right
> > + * sides of the image, documented as "ignored area".
> > + *
> > + * As far as is understood, all pixels of the pixel array (ignored area, color
> > + * processing margins and recording area) can be output by the sensor.
> > + */
> > +
> > +#define IMX290_PIXEL_ARRAY_WIDTH 1945
> > +#define IMX290_PIXEL_ARRAY_HEIGHT 1097
> > +#define IMX920_PIXEL_ARRAY_MARGIN_LEFT 12
> > +#define IMX920_PIXEL_ARRAY_MARGIN_RIGHT 13
> > +#define IMX920_PIXEL_ARRAY_MARGIN_TOP 8
> > +#define IMX920_PIXEL_ARRAY_MARGIN_BOTTOM 9
> > +#define IMX290_PIXEL_ARRAY_RECORDING_WIDTH 1920
> > +#define IMX290_PIXEL_ARRAY_RECORDING_HEIGHT 1080
> > +
> > static const char * const imx290_supply_name[] = {
> > "vdda",
> > "vddd",
> > @@ -671,6 +718,52 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
> > return 0;
> > }
> >
> > +static int imx290_get_selection(struct v4l2_subdev *sd,
> > + struct v4l2_subdev_state *sd_state,
> > + struct v4l2_subdev_selection *sel)
> > +{
> > + struct imx290 *imx290 = to_imx290(sd);
> > + struct v4l2_mbus_framefmt *format;
> > +
> > + switch (sel->target) {
> > + case V4L2_SEL_TGT_CROP: {
> > + format = imx290_get_pad_format(imx290, sd_state, sel->which);
> > +
> > + mutex_lock(&imx290->lock);
> > +
> > + sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP
> > + + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2;
> > + sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT
> > + + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2;
> > + sel->r.width = format->width;
> > + sel->r.height = format->height;
> > +
> > + mutex_unlock(&imx290->lock);
> > + return 0;
> > + }
> > +
> > + case V4L2_SEL_TGT_NATIVE_SIZE:
> > + case V4L2_SEL_TGT_CROP_BOUNDS:
> > + sel->r.top = 0;
> > + sel->r.left = 0;
> > + sel->r.width = IMX290_PIXEL_ARRAY_WIDTH;
> > + sel->r.height = IMX290_PIXEL_ARRAY_HEIGHT;
> > +
> > + return 0;
> > +
> > + case V4L2_SEL_TGT_CROP_DEFAULT:
> > + sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP;
> > + sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT;
> > + sel->r.width = IMX290_PIXEL_ARRAY_RECORDING_WIDTH;
> > + sel->r.height = IMX290_PIXEL_ARRAY_RECORDING_HEIGHT;
> > +
> > + return 0;
> > +
> > + default:
> > + return -EINVAL;
> > + }
> > +}
> > +
> > static int imx290_entity_init_cfg(struct v4l2_subdev *subdev,
> > struct v4l2_subdev_state *sd_state)
> > {
> > @@ -887,6 +980,7 @@ static const struct v4l2_subdev_pad_ops imx290_pad_ops = {
> > .enum_frame_size = imx290_enum_frame_size,
> > .get_fmt = imx290_get_fmt,
> > .set_fmt = imx290_set_fmt,
> > + .get_selection = imx290_get_selection,
> > };
> >
> > static const struct v4l2_subdev_ops imx290_subdev_ops = {

--
Regards,

Laurent Pinchart