157 lines
4.1 KiB
Diff
157 lines
4.1 KiB
Diff
From ee95eb32c4202a2d290af6c754806ef3bdfb3fda 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 = {
|