1 From ffbb09db69889cb09a1d7d647364211605247158 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Wed, 16 Jun 2021 16:27:06 +0100
4 Subject: [PATCH] media: i2c: imx258: Add support for running on 2 CSI
7 Extends the driver to also support 2 data lanes.
8 Frame rates are obviously more restricted on 2 lanes, but some
9 hardware simply hasn't wired more up.
11 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
13 drivers/media/i2c/imx258.c | 212 ++++++++++++++++++++++++++++++++-----
14 1 file changed, 186 insertions(+), 26 deletions(-)
16 --- a/drivers/media/i2c/imx258.c
17 +++ b/drivers/media/i2c/imx258.c
18 @@ -87,13 +87,17 @@ struct imx258_reg_list {
19 const struct imx258_reg *regs;
22 +#define IMX258_LANE_CONFIGS 2
23 +#define IMX258_2_LANE_MODE 0
24 +#define IMX258_4_LANE_MODE 1
26 /* Link frequency config */
27 struct imx258_link_freq_config {
31 /* PLL registers for this link frequency */
32 - struct imx258_reg_list reg_list;
33 + struct imx258_reg_list reg_list[IMX258_LANE_CONFIGS];
36 /* Mode : resolution and related config&values */
37 @@ -113,8 +117,30 @@ struct imx258_mode {
38 struct imx258_reg_list reg_list;
41 -/* 4208x3120 needs 1267Mbps/lane, 4 lanes */
42 -static const struct imx258_reg mipi_1267mbps_19_2mhz[] = {
43 +/* 4208x3120 needs 1267Mbps/lane, 4 lanes. Use that rate on 2 lanes as well */
44 +static const struct imx258_reg mipi_1267mbps_19_2mhz_2l[] = {
66 +static const struct imx258_reg mipi_1267mbps_19_2mhz_4l[] = {
70 @@ -128,16 +154,18 @@ static const struct imx258_reg mipi_1267
82 -static const struct imx258_reg mipi_1272mbps_24mhz[] = {
83 +static const struct imx258_reg mipi_1272mbps_24mhz_2l[] = {
91 @@ -148,13 +176,59 @@ static const struct imx258_reg mipi_1272
103 -static const struct imx258_reg mipi_640mbps_19_2mhz[] = {
104 +static const struct imx258_reg mipi_1272mbps_24mhz_4l[] = {
126 +static const struct imx258_reg mipi_640mbps_19_2mhz_2l[] = {
148 +static const struct imx258_reg mipi_640mbps_19_2mhz_4l[] = {
152 @@ -168,13 +242,37 @@ static const struct imx258_reg mipi_640m
164 +static const struct imx258_reg mipi_642mbps_24mhz_2l[] = {
186 -static const struct imx258_reg mipi_642mbps_24mhz[] = {
187 +static const struct imx258_reg mipi_642mbps_24mhz_4l[] = {
191 @@ -188,6 +286,8 @@ static const struct imx258_reg mipi_642m
200 @@ -242,7 +342,6 @@ static const struct imx258_reg mode_4208
208 @@ -355,7 +454,6 @@ static const struct imx258_reg mode_2104
216 @@ -468,7 +566,6 @@ static const struct imx258_reg mode_1048
224 @@ -574,11 +671,13 @@ enum {
227 * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample
228 - * data rate => double data rate; number of lanes => 4; bits per pixel => 10
229 + * data rate => double data rate;
230 + * number of lanes => (configurable 2 or 4);
231 + * bits per pixel => 10
233 -static u64 link_freq_to_pixel_rate(u64 f)
234 +static u64 link_freq_to_pixel_rate(u64 f, unsigned int nlanes)
241 @@ -608,15 +707,27 @@ static const struct imx258_link_freq_con
242 [IMX258_LINK_FREQ_1267MBPS] = {
243 .pixels_per_line = IMX258_PPL_DEFAULT,
245 - .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz),
246 - .regs = mipi_1267mbps_19_2mhz,
247 + [IMX258_2_LANE_MODE] = {
248 + .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_2l),
249 + .regs = mipi_1267mbps_19_2mhz_2l,
251 + [IMX258_4_LANE_MODE] = {
252 + .num_of_regs = ARRAY_SIZE(mipi_1267mbps_19_2mhz_4l),
253 + .regs = mipi_1267mbps_19_2mhz_4l,
257 [IMX258_LINK_FREQ_640MBPS] = {
258 .pixels_per_line = IMX258_PPL_DEFAULT,
260 - .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz),
261 - .regs = mipi_640mbps_19_2mhz,
262 + [IMX258_2_LANE_MODE] = {
263 + .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_2l),
264 + .regs = mipi_640mbps_19_2mhz_2l,
266 + [IMX258_4_LANE_MODE] = {
267 + .num_of_regs = ARRAY_SIZE(mipi_640mbps_19_2mhz_4l),
268 + .regs = mipi_640mbps_19_2mhz_4l,
273 @@ -625,15 +736,27 @@ static const struct imx258_link_freq_con
274 [IMX258_LINK_FREQ_1267MBPS] = {
275 .pixels_per_line = IMX258_PPL_DEFAULT,
277 - .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz),
278 - .regs = mipi_1272mbps_24mhz,
279 + [IMX258_2_LANE_MODE] = {
280 + .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_2l),
281 + .regs = mipi_1272mbps_24mhz_2l,
283 + [IMX258_4_LANE_MODE] = {
284 + .num_of_regs = ARRAY_SIZE(mipi_1272mbps_24mhz_4l),
285 + .regs = mipi_1272mbps_24mhz_4l,
289 [IMX258_LINK_FREQ_640MBPS] = {
290 .pixels_per_line = IMX258_PPL_DEFAULT,
292 - .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz),
293 - .regs = mipi_642mbps_24mhz,
294 + [IMX258_2_LANE_MODE] = {
295 + .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_2l),
296 + .regs = mipi_642mbps_24mhz_2l,
298 + [IMX258_4_LANE_MODE] = {
299 + .num_of_regs = ARRAY_SIZE(mipi_642mbps_24mhz_4l),
300 + .regs = mipi_642mbps_24mhz_4l,
305 @@ -694,6 +817,7 @@ struct imx258 {
307 const struct imx258_link_freq_config *link_freq_configs;
308 const s64 *link_freq_menu_items;
309 + unsigned int nlanes;
312 * Mutex for serialized access:
313 @@ -1024,7 +1148,7 @@ static int imx258_set_pad_format(struct
314 __v4l2_ctrl_s_ctrl(imx258->link_freq, mode->link_freq_index);
316 link_freq = imx258->link_freq_menu_items[mode->link_freq_index];
317 - pixel_rate = link_freq_to_pixel_rate(link_freq);
318 + pixel_rate = link_freq_to_pixel_rate(link_freq, imx258->nlanes);
319 __v4l2_ctrl_s_ctrl_int64(imx258->pixel_rate, pixel_rate);
320 /* Update limits and set FPS to default */
321 vblank_def = imx258->cur_mode->vts_def -
322 @@ -1053,11 +1177,13 @@ static int imx258_start_streaming(struct
324 struct i2c_client *client = v4l2_get_subdevdata(&imx258->sd);
325 const struct imx258_reg_list *reg_list;
326 + const struct imx258_link_freq_config *link_freq_cfg;
327 int ret, link_freq_index;
330 link_freq_index = imx258->cur_mode->link_freq_index;
331 - reg_list = &imx258->link_freq_configs[link_freq_index].reg_list;
332 + link_freq_cfg = &imx258->link_freq_configs[link_freq_index];
333 + reg_list = &link_freq_cfg->reg_list[imx258->nlanes == 2 ? 0 : 1];
334 ret = imx258_write_regs(imx258, reg_list->regs, reg_list->num_of_regs);
336 dev_err(&client->dev, "%s failed to set plls\n", __func__);
337 @@ -1283,9 +1409,11 @@ static int imx258_init_controls(struct i
338 imx258->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
341 - link_freq_to_pixel_rate(imx258->link_freq_menu_items[0]);
342 + link_freq_to_pixel_rate(imx258->link_freq_menu_items[0],
345 - link_freq_to_pixel_rate(imx258->link_freq_menu_items[1]);
346 + link_freq_to_pixel_rate(imx258->link_freq_menu_items[1],
348 /* By default, PIXEL_RATE is read only */
349 imx258->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx258_ctrl_ops,
351 @@ -1393,6 +1521,10 @@ static int imx258_get_regulators(struct
352 static int imx258_probe(struct i2c_client *client)
354 struct imx258 *imx258;
355 + struct fwnode_handle *endpoint;
356 + struct v4l2_fwnode_endpoint ep = {
357 + .bus_type = V4L2_MBUS_CSI2_DPHY
362 @@ -1435,13 +1567,38 @@ static int imx258_probe(struct i2c_clien
366 + endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
368 + dev_err(&client->dev, "Endpoint node not found\n");
372 + ret = v4l2_fwnode_endpoint_alloc_parse(endpoint, &ep);
373 + fwnode_handle_put(endpoint);
374 + if (ret == -ENXIO) {
375 + dev_err(&client->dev, "Unsupported bus type, should be CSI2\n");
376 + goto error_endpoint_poweron;
378 + dev_err(&client->dev, "Parsing endpoint node failed\n");
379 + goto error_endpoint_poweron;
382 + /* Get number of data lanes */
383 + imx258->nlanes = ep.bus.mipi_csi2.num_data_lanes;
384 + if (imx258->nlanes != 2 && imx258->nlanes != 4) {
385 + dev_err(&client->dev, "Invalid data lanes: %u\n",
388 + goto error_endpoint_poweron;
391 /* Initialize subdev */
392 v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);
394 /* Will be powered off via pm_runtime_idle */
395 ret = imx258_power_on(&client->dev);
398 + goto error_endpoint_poweron;
400 /* Check module identity */
401 ret = imx258_identify_module(imx258);
402 @@ -1486,6 +1643,9 @@ error_handler_free:
404 imx258_power_off(&client->dev);
406 +error_endpoint_poweron:
407 + v4l2_fwnode_endpoint_free(&ep);