| From a191c6d6e5180f54ecf16adda61988a16ce9fe48 Mon Sep 17 00:00:00 2001 |
| From: Dave Stevenson <dave.stevenson@raspberrypi.com> |
| Date: Tue, 7 Jul 2020 11:23:48 +0100 |
| Subject: [PATCH] media: i2c: imx290: Add support for g_selection to |
| report cropping |
| |
| Userspace needs to know the cropping arrangements for each mode, |
| so expose this through g_selection. |
| |
| Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> |
| --- |
| drivers/media/i2c/imx290.c | 84 ++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 84 insertions(+) |
| |
| --- a/drivers/media/i2c/imx290.c |
| +++ b/drivers/media/i2c/imx290.c |
| @@ -61,6 +61,13 @@ enum imx290_clk_index { |
| #define IMX290_PGCTRL_THRU BIT(1) |
| #define IMX290_PGCTRL_MODE(n) ((n) << 4) |
| |
| +#define IMX290_NATIVE_WIDTH 1945U |
| +#define IMX290_NATIVE_HEIGHT 1109U |
| +#define IMX290_PIXEL_ARRAY_LEFT 4U |
| +#define IMX290_PIXEL_ARRAY_TOP 12U |
| +#define IMX290_PIXEL_ARRAY_WIDTH 1937U |
| +#define IMX290_PIXEL_ARRAY_HEIGHT 1097U |
| + |
| static const char * const imx290_supply_name[] = { |
| "vdda", |
| "vddd", |
| @@ -80,6 +87,7 @@ struct imx290_mode { |
| u32 hmax; |
| u32 vmax; |
| u8 link_freq_index; |
| + struct v4l2_rect crop; |
| |
| const struct imx290_regval *data; |
| u32 data_size; |
| @@ -384,6 +392,12 @@ static const struct imx290_mode imx290_m |
| .hmax = 0x1130, |
| .vmax = 0x0465, |
| .link_freq_index = FREQ_INDEX_1080P, |
| + .crop = { |
| + .left = 4 + 8, |
| + .top = 12 + 8, |
| + .width = 1920, |
| + .height = 1080, |
| + }, |
| .data = imx290_1080p_settings, |
| .data_size = ARRAY_SIZE(imx290_1080p_settings), |
| .clk_data = { |
| @@ -398,6 +412,12 @@ static const struct imx290_mode imx290_m |
| .hmax = 0x19c8, |
| .vmax = 0x02ee, |
| .link_freq_index = FREQ_INDEX_720P, |
| + .crop = { |
| + .left = 4 + 8 + 320, |
| + .top = 12 + 8 + 180, |
| + .width = 1280, |
| + .height = 720, |
| + }, |
| .data = imx290_720p_settings, |
| .data_size = ARRAY_SIZE(imx290_720p_settings), |
| .clk_data = { |
| @@ -415,6 +435,12 @@ static const struct imx290_mode imx290_m |
| .hmax = 0x0898, |
| .vmax = 0x0465, |
| .link_freq_index = FREQ_INDEX_1080P, |
| + .crop = { |
| + .left = 4 + 8, |
| + .top = 12 + 8, |
| + .width = 1920, |
| + .height = 1080, |
| + }, |
| .data = imx290_1080p_settings, |
| .data_size = ARRAY_SIZE(imx290_1080p_settings), |
| .clk_data = { |
| @@ -429,6 +455,12 @@ static const struct imx290_mode imx290_m |
| .hmax = 0x0ce4, |
| .vmax = 0x02ee, |
| .link_freq_index = FREQ_INDEX_720P, |
| + .crop = { |
| + .left = 4 + 8 + 320, |
| + .top = 12 + 8 + 180, |
| + .width = 1280, |
| + .height = 720, |
| + }, |
| .data = imx290_720p_settings, |
| .data_size = ARRAY_SIZE(imx290_720p_settings), |
| .clk_data = { |
| @@ -875,6 +907,57 @@ static int imx290_write_current_format(s |
| return 0; |
| } |
| |
| +static const struct v4l2_rect * |
| +__imx290_get_pad_crop(struct imx290 *imx290, struct v4l2_subdev_pad_config *cfg, |
| + unsigned int pad, enum v4l2_subdev_format_whence which) |
| +{ |
| + switch (which) { |
| + case V4L2_SUBDEV_FORMAT_TRY: |
| + return v4l2_subdev_get_try_crop(&imx290->sd, cfg, pad); |
| + case V4L2_SUBDEV_FORMAT_ACTIVE: |
| + return &imx290->current_mode->crop; |
| + } |
| + |
| + return NULL; |
| +} |
| + |
| +static int imx290_get_selection(struct v4l2_subdev *sd, |
| + struct v4l2_subdev_pad_config *cfg, |
| + struct v4l2_subdev_selection *sel) |
| +{ |
| + switch (sel->target) { |
| + case V4L2_SEL_TGT_CROP: { |
| + struct imx290 *imx290 = to_imx290(sd); |
| + |
| + mutex_lock(&imx290->lock); |
| + sel->r = *__imx290_get_pad_crop(imx290, cfg, sel->pad, |
| + sel->which); |
| + mutex_unlock(&imx290->lock); |
| + |
| + return 0; |
| + } |
| + |
| + case V4L2_SEL_TGT_NATIVE_SIZE: |
| + sel->r.top = 0; |
| + sel->r.left = 0; |
| + sel->r.width = IMX290_NATIVE_WIDTH; |
| + sel->r.height = IMX290_NATIVE_HEIGHT; |
| + |
| + return 0; |
| + |
| + case V4L2_SEL_TGT_CROP_DEFAULT: |
| + case V4L2_SEL_TGT_CROP_BOUNDS: |
| + sel->r.top = IMX290_PIXEL_ARRAY_TOP; |
| + sel->r.left = IMX290_PIXEL_ARRAY_LEFT; |
| + sel->r.width = IMX290_PIXEL_ARRAY_WIDTH; |
| + sel->r.height = IMX290_PIXEL_ARRAY_HEIGHT; |
| + |
| + return 0; |
| + } |
| + |
| + return -EINVAL; |
| +} |
| + |
| /* Start streaming */ |
| static int imx290_start_streaming(struct imx290 *imx290) |
| { |
| @@ -1073,6 +1156,7 @@ static const struct v4l2_subdev_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 = { |