media: i2c: imx258: Add get_selection for pixel array information

Libcamera requires the cropping information for each mode, so
add this information to the driver.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
This commit is contained in:
Dave Stevenson
2022-03-23 15:48:49 +00:00
committed by Dom Cobley
parent d3fe3a8b42
commit 9fecff83db

View File

@@ -77,6 +77,14 @@
#define REG_CONFIG_MIRROR_FLIP 0x03
#define REG_CONFIG_FLIP_TEST_PATTERN 0x02
/* IMX258 native and active pixel array size. */
#define IMX258_NATIVE_WIDTH 4224U
#define IMX258_NATIVE_HEIGHT 3192U
#define IMX258_PIXEL_ARRAY_LEFT 8U
#define IMX258_PIXEL_ARRAY_TOP 16U
#define IMX258_PIXEL_ARRAY_WIDTH 4208U
#define IMX258_PIXEL_ARRAY_HEIGHT 3120U
struct imx258_reg {
u16 address;
u8 val;
@@ -115,6 +123,9 @@ struct imx258_mode {
u32 link_freq_index;
/* Default register values */
struct imx258_reg_list reg_list;
/* Analog crop rectangle. */
struct v4l2_rect crop;
};
/* 4208x3120 needs 1267Mbps/lane, 4 lanes. Use that rate on 2 lanes as well */
@@ -757,6 +768,12 @@ static const struct imx258_mode supported_modes[] = {
.regs = mode_4208x3120_regs,
},
.link_freq_index = IMX258_LINK_FREQ_1267MBPS,
.crop = {
.left = IMX258_PIXEL_ARRAY_LEFT,
.top = IMX258_PIXEL_ARRAY_TOP,
.width = 4208,
.height = 3120,
},
},
{
.width = 2104,
@@ -768,6 +785,12 @@ static const struct imx258_mode supported_modes[] = {
.regs = mode_2104_1560_regs,
},
.link_freq_index = IMX258_LINK_FREQ_640MBPS,
.crop = {
.left = IMX258_PIXEL_ARRAY_LEFT,
.top = IMX258_PIXEL_ARRAY_TOP,
.width = 4208,
.height = 3120,
},
},
{
.width = 1048,
@@ -779,6 +802,12 @@ static const struct imx258_mode supported_modes[] = {
.regs = mode_1048_780_regs,
},
.link_freq_index = IMX258_LINK_FREQ_640MBPS,
.crop = {
.left = IMX258_PIXEL_ARRAY_LEFT,
.top = IMX258_PIXEL_ARRAY_TOP,
.width = 4208,
.height = 3120,
},
},
};
@@ -895,6 +924,7 @@ static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct v4l2_mbus_framefmt *try_fmt =
v4l2_subdev_state_get_format(fh->state, 0);
struct v4l2_rect *try_crop;
/* Initialize try_fmt */
try_fmt->width = supported_modes[0].width;
@@ -902,6 +932,13 @@ static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
try_fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
try_fmt->field = V4L2_FIELD_NONE;
/* Initialize try_crop */
try_crop = v4l2_subdev_state_get_crop(fh->state, 0);
try_crop->left = IMX258_PIXEL_ARRAY_LEFT;
try_crop->top = IMX258_PIXEL_ARRAY_TOP;
try_crop->width = IMX258_PIXEL_ARRAY_WIDTH;
try_crop->height = IMX258_PIXEL_ARRAY_HEIGHT;
return 0;
}
@@ -1149,6 +1186,58 @@ static int imx258_set_pad_format(struct v4l2_subdev *sd,
return 0;
}
static const struct v4l2_rect *
__imx258_get_pad_crop(struct imx258 *imx258,
struct v4l2_subdev_state *sd_state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
return v4l2_subdev_state_get_crop(sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &imx258->cur_mode->crop;
}
return NULL;
}
static int imx258_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
switch (sel->target) {
case V4L2_SEL_TGT_CROP: {
struct imx258 *imx258 = to_imx258(sd);
mutex_lock(&imx258->mutex);
sel->r = *__imx258_get_pad_crop(imx258, sd_state, sel->pad,
sel->which);
mutex_unlock(&imx258->mutex);
return 0;
}
case V4L2_SEL_TGT_NATIVE_SIZE:
sel->r.left = 0;
sel->r.top = 0;
sel->r.width = IMX258_NATIVE_WIDTH;
sel->r.height = IMX258_NATIVE_HEIGHT;
return 0;
case V4L2_SEL_TGT_CROP_DEFAULT:
case V4L2_SEL_TGT_CROP_BOUNDS:
sel->r.left = IMX258_PIXEL_ARRAY_LEFT;
sel->r.top = IMX258_PIXEL_ARRAY_TOP;
sel->r.width = IMX258_PIXEL_ARRAY_WIDTH;
sel->r.height = IMX258_PIXEL_ARRAY_HEIGHT;
return 0;
}
return -EINVAL;
}
/* Start streaming */
static int imx258_start_streaming(struct imx258 *imx258)
{
@@ -1318,6 +1407,7 @@ static const struct v4l2_subdev_pad_ops imx258_pad_ops = {
.get_fmt = imx258_get_pad_format,
.set_fmt = imx258_set_pad_format,
.enum_frame_size = imx258_enum_frame_size,
.get_selection = imx258_get_selection,
};
static const struct v4l2_subdev_ops imx258_subdev_ops = {