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
7 The sensor supports H & V flips, but the controls were READ_ONLY.
9 Note that the Bayer order changes with these flips, therefore
10 they set the V4L2_CTRL_FLAG_MODIFY_LAYOUT property.
12 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
14 drivers/media/i2c/imx258.c | 98 +++++++++++++++++++++++++-------------
15 1 file changed, 64 insertions(+), 34 deletions(-)
17 --- a/drivers/media/i2c/imx258.c
18 +++ b/drivers/media/i2c/imx258.c
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
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),
34 + * The supported formats.
35 + * This table MUST contain 4 entries per format, to cover the various flip
36 + * combinations in the order
42 +static const u32 codes[] = {
44 + MEDIA_BUS_FMT_SRGGB10_1X10,
45 + MEDIA_BUS_FMT_SGRBG10_1X10,
46 + MEDIA_BUS_FMT_SGBRG10_1X10,
47 + MEDIA_BUS_FMT_SBGGR10_1X10
50 static const char * const imx258_test_pattern_menu[] = {
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;
62 @@ -968,9 +988,22 @@ static int imx258_write_regs(struct imx2
66 +/* Get bayer order based on flip setting. */
67 +static u32 imx258_get_format_code(struct imx258 *imx258)
71 + lockdep_assert_held(&imx258->mutex);
73 + i = (imx258->vflip->val ? 2 : 0) |
74 + (imx258->hflip->val ? 1 : 0);
79 static int imx258_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
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;
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,
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);
103 case V4L2_CID_WIDE_DYNAMIC_RANGE:
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);
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));
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)
125 - /* Only one bayer order(GRBG) is supported */
126 + struct imx258 *imx258 = to_imx258(sd);
128 + /* Only one bayer format (10 bit) is supported */
132 - code->code = MEDIA_BUS_FMT_SBGGR10_1X10;
133 + code->code = imx258_get_format_code(imx258);
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)
141 + struct imx258 *imx258 = to_imx258(sd);
142 if (fse->index >= ARRAY_SIZE(supported_modes))
145 - if (fse->code != MEDIA_BUS_FMT_SBGGR10_1X10)
146 + if (fse->code != imx258_get_format_code(imx258))
149 fse->min_width = supported_modes[fse->index].width;
150 @@ -1164,12 +1205,13 @@ static int imx258_enum_frame_size(struct
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)
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;
166 @@ -1182,7 +1224,7 @@ static int __imx258_get_pad_format(struc
170 - imx258_update_pad_format(imx258->cur_mode, fmt);
171 + imx258_update_pad_format(imx258, imx258->cur_mode, fmt);
175 @@ -1218,13 +1260,12 @@ static int imx258_set_pad_format(struct
177 mutex_lock(&imx258->mutex);
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);
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
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);
199 - dev_err(&client->dev, "%s failed to set orientation\n",
204 /* Apply customized values from user */
205 ret = __v4l2_ctrl_handler_setup(imx258->sd.ctrl_handler);
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;
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;
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);
223 - hflip->flags |= V4L2_CTRL_FLAG_READ_ONLY;
225 - vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
226 - V4L2_CID_VFLIP, 1, 1, 1, 1);
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);
232 + imx258->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
234 + imx258->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
235 + V4L2_CID_VFLIP, 0, 1, 1, 1);
237 + imx258->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT;
239 link_freq_cfgs = &imx258->link_freq_configs[0];
240 link_cfg = link_freq_cfgs[imx258->lane_mode_idx].link_cfg;