17798e50b7a9c621d969837e8f5054f507916e9a
[openwrt/staging/stintel.git] /
1 From ee95eb32c4202a2d290af6c754806ef3bdfb3fda Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Tue, 7 Jul 2020 11:23:48 +0100
4 Subject: [PATCH] media: i2c: imx290: Add support for g_selection to
5 report cropping
6
7 Userspace needs to know the cropping arrangements for each mode,
8 so expose this through g_selection.
9
10 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
11 ---
12 drivers/media/i2c/imx290.c | 84 ++++++++++++++++++++++++++++++++++++++
13 1 file changed, 84 insertions(+)
14
15 --- a/drivers/media/i2c/imx290.c
16 +++ b/drivers/media/i2c/imx290.c
17 @@ -61,6 +61,13 @@ enum imx290_clk_index {
18 #define IMX290_PGCTRL_THRU BIT(1)
19 #define IMX290_PGCTRL_MODE(n) ((n) << 4)
20
21 +#define IMX290_NATIVE_WIDTH 1945U
22 +#define IMX290_NATIVE_HEIGHT 1109U
23 +#define IMX290_PIXEL_ARRAY_LEFT 4U
24 +#define IMX290_PIXEL_ARRAY_TOP 12U
25 +#define IMX290_PIXEL_ARRAY_WIDTH 1937U
26 +#define IMX290_PIXEL_ARRAY_HEIGHT 1097U
27 +
28 static const char * const imx290_supply_name[] = {
29 "vdda",
30 "vddd",
31 @@ -80,6 +87,7 @@ struct imx290_mode {
32 u32 hmax;
33 u32 vmax;
34 u8 link_freq_index;
35 + struct v4l2_rect crop;
36
37 const struct imx290_regval *data;
38 u32 data_size;
39 @@ -384,6 +392,12 @@ static const struct imx290_mode imx290_m
40 .hmax = 0x1130,
41 .vmax = 0x0465,
42 .link_freq_index = FREQ_INDEX_1080P,
43 + .crop = {
44 + .left = 4 + 8,
45 + .top = 12 + 8,
46 + .width = 1920,
47 + .height = 1080,
48 + },
49 .data = imx290_1080p_settings,
50 .data_size = ARRAY_SIZE(imx290_1080p_settings),
51 .clk_data = {
52 @@ -398,6 +412,12 @@ static const struct imx290_mode imx290_m
53 .hmax = 0x19c8,
54 .vmax = 0x02ee,
55 .link_freq_index = FREQ_INDEX_720P,
56 + .crop = {
57 + .left = 4 + 8 + 320,
58 + .top = 12 + 8 + 180,
59 + .width = 1280,
60 + .height = 720,
61 + },
62 .data = imx290_720p_settings,
63 .data_size = ARRAY_SIZE(imx290_720p_settings),
64 .clk_data = {
65 @@ -415,6 +435,12 @@ static const struct imx290_mode imx290_m
66 .hmax = 0x0898,
67 .vmax = 0x0465,
68 .link_freq_index = FREQ_INDEX_1080P,
69 + .crop = {
70 + .left = 4 + 8,
71 + .top = 12 + 8,
72 + .width = 1920,
73 + .height = 1080,
74 + },
75 .data = imx290_1080p_settings,
76 .data_size = ARRAY_SIZE(imx290_1080p_settings),
77 .clk_data = {
78 @@ -429,6 +455,12 @@ static const struct imx290_mode imx290_m
79 .hmax = 0x0ce4,
80 .vmax = 0x02ee,
81 .link_freq_index = FREQ_INDEX_720P,
82 + .crop = {
83 + .left = 4 + 8 + 320,
84 + .top = 12 + 8 + 180,
85 + .width = 1280,
86 + .height = 720,
87 + },
88 .data = imx290_720p_settings,
89 .data_size = ARRAY_SIZE(imx290_720p_settings),
90 .clk_data = {
91 @@ -875,6 +907,57 @@ static int imx290_write_current_format(s
92 return 0;
93 }
94
95 +static const struct v4l2_rect *
96 +__imx290_get_pad_crop(struct imx290 *imx290, struct v4l2_subdev_pad_config *cfg,
97 + unsigned int pad, enum v4l2_subdev_format_whence which)
98 +{
99 + switch (which) {
100 + case V4L2_SUBDEV_FORMAT_TRY:
101 + return v4l2_subdev_get_try_crop(&imx290->sd, cfg, pad);
102 + case V4L2_SUBDEV_FORMAT_ACTIVE:
103 + return &imx290->current_mode->crop;
104 + }
105 +
106 + return NULL;
107 +}
108 +
109 +static int imx290_get_selection(struct v4l2_subdev *sd,
110 + struct v4l2_subdev_pad_config *cfg,
111 + struct v4l2_subdev_selection *sel)
112 +{
113 + switch (sel->target) {
114 + case V4L2_SEL_TGT_CROP: {
115 + struct imx290 *imx290 = to_imx290(sd);
116 +
117 + mutex_lock(&imx290->lock);
118 + sel->r = *__imx290_get_pad_crop(imx290, cfg, sel->pad,
119 + sel->which);
120 + mutex_unlock(&imx290->lock);
121 +
122 + return 0;
123 + }
124 +
125 + case V4L2_SEL_TGT_NATIVE_SIZE:
126 + sel->r.top = 0;
127 + sel->r.left = 0;
128 + sel->r.width = IMX290_NATIVE_WIDTH;
129 + sel->r.height = IMX290_NATIVE_HEIGHT;
130 +
131 + return 0;
132 +
133 + case V4L2_SEL_TGT_CROP_DEFAULT:
134 + case V4L2_SEL_TGT_CROP_BOUNDS:
135 + sel->r.top = IMX290_PIXEL_ARRAY_TOP;
136 + sel->r.left = IMX290_PIXEL_ARRAY_LEFT;
137 + sel->r.width = IMX290_PIXEL_ARRAY_WIDTH;
138 + sel->r.height = IMX290_PIXEL_ARRAY_HEIGHT;
139 +
140 + return 0;
141 + }
142 +
143 + return -EINVAL;
144 +}
145 +
146 /* Start streaming */
147 static int imx290_start_streaming(struct imx290 *imx290)
148 {
149 @@ -1073,6 +1156,7 @@ static const struct v4l2_subdev_pad_ops
150 .enum_frame_size = imx290_enum_frame_size,
151 .get_fmt = imx290_get_fmt,
152 .set_fmt = imx290_set_fmt,
153 + .get_selection = imx290_get_selection,
154 };
155
156 static const struct v4l2_subdev_ops imx290_subdev_ops = {