1 From 1cec09c2c2f4c65350d29a0c597da6c7df5ef3bc Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 25 Jun 2020 17:03:11 +0100
4 Subject: [PATCH] media : i2c: imx290: Add support for the mono sensor
7 The IMX290 module is available as either mono or colour (Bayer).
9 Update the driver so that it can advertise the correct mono
10 formats instead of the colour ones.
12 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
14 drivers/media/i2c/imx290.c | 58 +++++++++++++++++++++++++++-----------
15 1 file changed, 41 insertions(+), 17 deletions(-)
17 --- a/drivers/media/i2c/imx290.c
18 +++ b/drivers/media/i2c/imx290.c
20 // SPDX-License-Identifier: GPL-2.0
22 - * Sony IMX290/327 CMOS Image Sensor Driver
23 + * Sony IMX290 & IMX327 CMOS Image Sensor Driver
25 * The IMX290 and IMX327 are very similar 1920x1080 1/2.8 CMOS image sensors.
26 - * IMX327 can support up to 60fps, whilst IMX290 support up to 120fps (only
27 - * 10bit and when connected over 4 CSI-2 lanes).
28 + * IMX327 can support up to 60fps, whilst IMX290 can support up to 120fps, but
29 + * only 10bit and when connected over 4 CSI-2 lanes.
30 + * The modules don't appear to have a mechanism to identify whether the mono or
31 + * colour variant is connected, therefore it is done via compatible string.
33 * Copyright (C) 2019 FRAMOS GmbH.
36 #include <linux/gpio/consumer.h>
37 #include <linux/i2c.h>
38 #include <linux/module.h>
39 +#include <linux/of_device.h>
40 #include <linux/pm_runtime.h>
41 #include <linux/regmap.h>
42 #include <linux/regulator/consumer.h>
43 @@ -95,6 +98,8 @@ struct imx290 {
47 + const struct imx290_pixfmt *formats;
49 struct v4l2_subdev sd;
51 struct v4l2_mbus_framefmt current_format;
52 @@ -120,11 +125,18 @@ struct imx290_pixfmt {
56 -static const struct imx290_pixfmt imx290_formats[] = {
57 +#define IMX290_NUM_FORMATS 2
59 +static const struct imx290_pixfmt imx290_colour_formats[IMX290_NUM_FORMATS] = {
60 { MEDIA_BUS_FMT_SRGGB10_1X10, 10 },
61 { MEDIA_BUS_FMT_SRGGB12_1X12, 12 },
64 +static const struct imx290_pixfmt imx290_mono_formats[IMX290_NUM_FORMATS] = {
65 + { MEDIA_BUS_FMT_Y10_1X10, 10 },
66 + { MEDIA_BUS_FMT_Y12_1X12, 12 },
69 static const struct regmap_config imx290_regmap_config = {
72 @@ -671,10 +683,12 @@ static int imx290_enum_mbus_code(struct
73 struct v4l2_subdev_state *sd_state,
74 struct v4l2_subdev_mbus_code_enum *code)
76 - if (code->index >= ARRAY_SIZE(imx290_formats))
77 + const struct imx290 *imx290 = to_imx290(sd);
79 + if (code->index >= IMX290_NUM_FORMATS)
82 - code->code = imx290_formats[code->index].code;
83 + code->code = imx290->formats[code->index].code;
87 @@ -686,8 +700,8 @@ static int imx290_enum_frame_size(struct
88 const struct imx290 *imx290 = to_imx290(sd);
89 const struct imx290_mode *imx290_modes = imx290_modes_ptr(imx290);
91 - if ((fse->code != imx290_formats[0].code) &&
92 - (fse->code != imx290_formats[1].code))
93 + if (fse->code != imx290->formats[0].code &&
94 + fse->code != imx290->formats[1].code)
97 if (fse->index >= imx290_modes_num(imx290))
98 @@ -765,14 +779,14 @@ static int imx290_set_fmt(struct v4l2_su
99 fmt->format.width = mode->width;
100 fmt->format.height = mode->height;
102 - for (i = 0; i < ARRAY_SIZE(imx290_formats); i++)
103 - if (imx290_formats[i].code == fmt->format.code)
104 + for (i = 0; i < IMX290_NUM_FORMATS; i++)
105 + if (imx290->formats[i].code == fmt->format.code)
108 - if (i >= ARRAY_SIZE(imx290_formats))
109 + if (i >= IMX290_NUM_FORMATS)
112 - fmt->format.code = imx290_formats[i].code;
113 + fmt->format.code = imx290->formats[i].code;
114 fmt->format.field = V4L2_FIELD_NONE;
116 if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
117 @@ -780,7 +794,7 @@ static int imx290_set_fmt(struct v4l2_su
119 format = &imx290->current_format;
120 imx290->current_mode = mode;
121 - imx290->bpp = imx290_formats[i].bpp;
122 + imx290->bpp = imx290->formats[i].bpp;
124 if (imx290->link_freq)
125 __v4l2_ctrl_s_ctrl(imx290->link_freq,
126 @@ -835,6 +849,7 @@ static int imx290_write_current_format(s
128 switch (imx290->current_format.code) {
129 case MEDIA_BUS_FMT_SRGGB10_1X10:
130 + case MEDIA_BUS_FMT_Y10_1X10:
131 ret = imx290_set_register_array(imx290, imx290_10bit_settings,
133 imx290_10bit_settings));
134 @@ -844,6 +859,7 @@ static int imx290_write_current_format(s
137 case MEDIA_BUS_FMT_SRGGB12_1X12:
138 + case MEDIA_BUS_FMT_Y12_1X12:
139 ret = imx290_set_register_array(imx290, imx290_12bit_settings,
141 imx290_12bit_settings));
142 @@ -1087,6 +1103,12 @@ static s64 imx290_check_link_freqs(const
146 +static const struct of_device_id imx290_of_match[] = {
147 + { .compatible = "sony,imx290", .data = imx290_colour_formats },
148 + { .compatible = "sony,imx290-mono", .data = imx290_mono_formats },
152 static int imx290_probe(struct i2c_client *client)
154 struct device *dev = &client->dev;
155 @@ -1095,6 +1117,7 @@ static int imx290_probe(struct i2c_clien
156 struct v4l2_fwnode_endpoint ep = {
157 .bus_type = V4L2_MBUS_CSI2_DPHY
159 + const struct of_device_id *match;
160 const struct imx290_mode *mode;
161 struct imx290 *imx290;
163 @@ -1111,6 +1134,11 @@ static int imx290_probe(struct i2c_clien
167 + match = of_match_device(imx290_of_match, dev);
170 + imx290->formats = (const struct imx290_pixfmt *)match->data;
172 endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
174 dev_err(dev, "Endpoint node not found\n");
175 @@ -1329,10 +1357,6 @@ static int imx290_remove(struct i2c_clie
179 -static const struct of_device_id imx290_of_match[] = {
180 - { .compatible = "sony,imx290" },
183 MODULE_DEVICE_TABLE(of, imx290_of_match);
185 static struct i2c_driver imx290_i2c_driver = {