]> git.ipfire.org Git - thirdparty/openwrt.git/blob
c3abb8c329888185cede1c05cb0e4370a29f6b1e
[thirdparty/openwrt.git] /
1 From e9b26efc223784f72ec43cc64b4c485c6798be42 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Tue, 15 Jun 2021 18:29:52 +0100
4 Subject: [PATCH 0463/1085] media: i2c: imx258: Make HFLIP and VFLIP controls
5 writable
6
7 The sensor supports H & V flips, but the controls were READ_ONLY.
8
9 Note that the Bayer order changes with these flips, therefore
10 they set the V4L2_CTRL_FLAG_MODIFY_LAYOUT property.
11
12 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
13 ---
14 drivers/media/i2c/imx258.c | 98 +++++++++++++++++++++++++-------------
15 1 file changed, 64 insertions(+), 34 deletions(-)
16
17 --- a/drivers/media/i2c/imx258.c
18 +++ b/drivers/media/i2c/imx258.c
19 @@ -82,7 +82,8 @@
20
21 /* Orientation */
22 #define REG_MIRROR_FLIP_CONTROL 0x0101
23 -#define REG_CONFIG_MIRROR_FLIP 0x03
24 +#define REG_CONFIG_MIRROR_HFLIP 0x01
25 +#define REG_CONFIG_MIRROR_VFLIP 0x02
26 #define REG_CONFIG_FLIP_TEST_PATTERN 0x02
27
28 /* IMX258 native and active pixel array size. */
29 @@ -672,6 +673,23 @@ static const struct imx258_variant_cfg i
30 .num_regs = ARRAY_SIZE(imx258_pdaf_cfg_regs),
31 };
32
33 +/*
34 + * The supported formats.
35 + * This table MUST contain 4 entries per format, to cover the various flip
36 + * combinations in the order
37 + * - no flip
38 + * - h flip
39 + * - v flip
40 + * - h&v flips
41 + */
42 +static const u32 codes[] = {
43 + /* 10-bit modes. */
44 + MEDIA_BUS_FMT_SRGGB10_1X10,
45 + MEDIA_BUS_FMT_SGRBG10_1X10,
46 + MEDIA_BUS_FMT_SGBRG10_1X10,
47 + MEDIA_BUS_FMT_SBGGR10_1X10
48 +};
49 +
50 static const char * const imx258_test_pattern_menu[] = {
51 "Disabled",
52 "Solid Colour",
53 @@ -865,6 +883,8 @@ struct imx258 {
54 struct v4l2_ctrl *vblank;
55 struct v4l2_ctrl *hblank;
56 struct v4l2_ctrl *exposure;
57 + struct v4l2_ctrl *hflip;
58 + struct v4l2_ctrl *vflip;
59 /* Current long exposure factor in use. Set through V4L2_CID_VBLANK */
60 unsigned int long_exp_shift;
61
62 @@ -968,9 +988,22 @@ static int imx258_write_regs(struct imx2
63 return 0;
64 }
65
66 +/* Get bayer order based on flip setting. */
67 +static u32 imx258_get_format_code(struct imx258 *imx258)
68 +{
69 + unsigned int i;
70 +
71 + lockdep_assert_held(&imx258->mutex);
72 +
73 + i = (imx258->vflip->val ? 2 : 0) |
74 + (imx258->hflip->val ? 1 : 0);
75 +
76 + return codes[i];
77 +}
78 /* Open sub-device */
79 static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
80 {
81 + struct imx258 *imx258 = to_imx258(sd);
82 struct v4l2_mbus_framefmt *try_fmt =
83 v4l2_subdev_get_try_format(sd, fh->state, 0);
84 struct v4l2_rect *try_crop;
85 @@ -978,7 +1011,7 @@ static int imx258_open(struct v4l2_subde
86 /* Initialize try_fmt */
87 try_fmt->width = supported_modes[0].width;
88 try_fmt->height = supported_modes[0].height;
89 - try_fmt->code = MEDIA_BUS_FMT_SBGGR10_1X10;
90 + try_fmt->code = imx258_get_format_code(imx258);
91 try_fmt->field = V4L2_FIELD_NONE;
92
93 /* Initialize try_crop */
94 @@ -1091,10 +1124,6 @@ static int imx258_set_ctrl(struct v4l2_c
95 ret = imx258_write_reg(imx258, IMX258_REG_TEST_PATTERN,
96 IMX258_REG_VALUE_16BIT,
97 ctrl->val);
98 - ret = imx258_write_reg(imx258, REG_MIRROR_FLIP_CONTROL,
99 - IMX258_REG_VALUE_08BIT,
100 - !ctrl->val ? REG_CONFIG_MIRROR_FLIP :
101 - REG_CONFIG_FLIP_TEST_PATTERN);
102 break;
103 case V4L2_CID_WIDE_DYNAMIC_RANGE:
104 if (!ctrl->val) {
105 @@ -1116,6 +1145,15 @@ static int imx258_set_ctrl(struct v4l2_c
106 ret = imx258_set_frame_length(imx258,
107 imx258->cur_mode->height + ctrl->val);
108 break;
109 + case V4L2_CID_VFLIP:
110 + case V4L2_CID_HFLIP:
111 + ret = imx258_write_reg(imx258, REG_MIRROR_FLIP_CONTROL,
112 + IMX258_REG_VALUE_08BIT,
113 + (imx258->hflip->val ?
114 + REG_CONFIG_MIRROR_HFLIP : 0) |
115 + (imx258->vflip->val ?
116 + REG_CONFIG_MIRROR_VFLIP : 0));
117 + break;
118 default:
119 dev_info(&client->dev,
120 "ctrl(id:0x%x,val:0x%x) is not handled\n",
121 @@ -1137,11 +1175,13 @@ static int imx258_enum_mbus_code(struct
122 struct v4l2_subdev_state *sd_state,
123 struct v4l2_subdev_mbus_code_enum *code)
124 {
125 - /* Only one bayer order(GRBG) is supported */
126 + struct imx258 *imx258 = to_imx258(sd);
127 +
128 + /* Only one bayer format (10 bit) is supported */
129 if (code->index > 0)
130 return -EINVAL;
131
132 - code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
133 + code->code = imx258_get_format_code(imx258);
134
135 return 0;
136 }
137 @@ -1150,10 +1190,11 @@ static int imx258_enum_frame_size(struct
138 struct v4l2_subdev_state *sd_state,
139 struct v4l2_subdev_frame_size_enum *fse)
140 {
141 + struct imx258 *imx258 = to_imx258(sd);
142 if (fse->index >= ARRAY_SIZE(supported_modes))
143 return -EINVAL;
144
145 - if (fse->code != MEDIA_BUS_FMT_SBGGR10_1X10)
146 + if (fse->code != imx258_get_format_code(imx258))
147 return -EINVAL;
148
149 fse->min_width = supported_modes[fse->index].width;
150 @@ -1164,12 +1205,13 @@ static int imx258_enum_frame_size(struct
151 return 0;
152 }
153
154 -static void imx258_update_pad_format(const struct imx258_mode *mode,
155 +static void imx258_update_pad_format(struct imx258 *imx258,
156 + const struct imx258_mode *mode,
157 struct v4l2_subdev_format *fmt)
158 {
159 fmt->format.width = mode->width;
160 fmt->format.height = mode->height;
161 - fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
162 + fmt->format.code = imx258_get_format_code(imx258);
163 fmt->format.field = V4L2_FIELD_NONE;
164 }
165
166 @@ -1182,7 +1224,7 @@ static int __imx258_get_pad_format(struc
167 sd_state,
168 fmt->pad);
169 else
170 - imx258_update_pad_format(imx258->cur_mode, fmt);
171 + imx258_update_pad_format(imx258, imx258->cur_mode, fmt);
172
173 return 0;
174 }
175 @@ -1218,13 +1260,12 @@ static int imx258_set_pad_format(struct
176
177 mutex_lock(&imx258->mutex);
178
179 - /* Only one raw bayer(GBRG) order is supported */
180 - fmt->format.code = MEDIA_BUS_FMT_SBGGR10_1X10;
181 + fmt->format.code = imx258_get_format_code(imx258);
182
183 mode = v4l2_find_nearest_size(supported_modes,
184 ARRAY_SIZE(supported_modes), width, height,
185 fmt->format.width, fmt->format.height);
186 - imx258_update_pad_format(mode, fmt);
187 + imx258_update_pad_format(imx258, mode, fmt);
188 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
189 framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
190 *framefmt = fmt->format;
191 @@ -1367,15 +1408,6 @@ static int imx258_start_streaming(struct
192 return ret;
193 }
194
195 - /* Set Orientation be 180 degree */
196 - ret = imx258_write_reg(imx258, REG_MIRROR_FLIP_CONTROL,
197 - IMX258_REG_VALUE_08BIT, REG_CONFIG_MIRROR_FLIP);
198 - if (ret) {
199 - dev_err(&client->dev, "%s failed to set orientation\n",
200 - __func__);
201 - return ret;
202 - }
203 -
204 /* Apply customized values from user */
205 ret = __v4l2_ctrl_handler_setup(imx258->sd.ctrl_handler);
206 if (ret)
207 @@ -1564,7 +1596,6 @@ static int imx258_init_controls(struct i
208 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
209 const struct imx258_link_freq_config *link_freq_cfgs;
210 struct v4l2_fwnode_device_properties props;
211 - struct v4l2_ctrl *vflip, *hflip;
212 struct v4l2_ctrl_handler *ctrl_hdlr;
213 const struct imx258_link_cfg *link_cfg;
214 s64 vblank_def;
215 @@ -1589,16 +1620,15 @@ static int imx258_init_controls(struct i
216 if (imx258->link_freq)
217 imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
218
219 - /* The driver only supports one bayer order and flips by default. */
220 - hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
221 - V4L2_CID_HFLIP, 1, 1, 1, 1);
222 - if (hflip)
223 - hflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
224 -
225 - vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
226 - V4L2_CID_VFLIP, 1, 1, 1, 1);
227 - if (vflip)
228 - vflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
229 + imx258->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
230 + V4L2_CID_HFLIP, 0, 1, 1, 1);
231 + if (imx258->hflip)
232 + imx258->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
233 +
234 + imx258->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
235 + V4L2_CID_VFLIP, 0, 1, 1, 1);
236 + if (imx258->vflip)
237 + imx258->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
238
239 link_freq_cfgs = &imx258->link_freq_configs[0];
240 link_cfg = link_freq_cfgs[imx258->lane_mode_idx].link_cfg;