71b520eb8cc6edfe9429431405a8da1f5448910d
[openwrt/staging/ansuel.git] /
1 From d0cc0819d6750d39624741d9091ab3f73836f11b Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 16 Feb 2023 00:29:50 +0200
4 Subject: [PATCH] media: i2c: imx290: Add support for the mono sensor
5 variant
6
7 Should be upstream commit 9bf52c7136d1
8
9 The IMX290 module is available as either mono or colour (Bayer).
10
11 Update the driver so that it can advertise the correct mono
12 formats instead of the colour ones.
13
14 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
15 Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
16 Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
17 Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
18 Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
19 ---
20 drivers/media/i2c/imx290.c | 75 +++++++++++++++++++++++++++++++-------
21 1 file changed, 61 insertions(+), 14 deletions(-)
22
23 --- a/drivers/media/i2c/imx290.c
24 +++ b/drivers/media/i2c/imx290.c
25 @@ -13,6 +13,7 @@
26 #include <linux/gpio/consumer.h>
27 #include <linux/i2c.h>
28 #include <linux/module.h>
29 +#include <linux/of_device.h>
30 #include <linux/pm_runtime.h>
31 #include <linux/regmap.h>
32 #include <linux/regulator/consumer.h>
33 @@ -160,6 +161,21 @@
34
35 #define IMX290_NUM_SUPPLIES 3
36
37 +enum imx290_colour_variant {
38 + IMX290_VARIANT_COLOUR,
39 + IMX290_VARIANT_MONO,
40 + IMX290_VARIANT_MAX
41 +};
42 +
43 +enum imx290_model {
44 + IMX290_MODEL_IMX290LQR,
45 + IMX290_MODEL_IMX290LLR,
46 +};
47 +
48 +struct imx290_model_info {
49 + enum imx290_colour_variant colour_variant;
50 +};
51 +
52 struct imx290_regval {
53 u32 reg;
54 u32 val;
55 @@ -180,6 +196,7 @@ struct imx290 {
56 struct clk *xclk;
57 struct regmap *regmap;
58 u8 nlanes;
59 + const struct imx290_model_info *model;
60
61 struct v4l2_subdev sd;
62 struct media_pad pad;
63 @@ -417,7 +434,7 @@ static inline int imx290_modes_num(const
64 }
65
66 struct imx290_format_info {
67 - u32 code;
68 + u32 code[IMX290_VARIANT_MAX];
69 u8 bpp;
70 const struct imx290_regval *regs;
71 unsigned int num_regs;
72 @@ -425,26 +442,33 @@ struct imx290_format_info {
73
74 static const struct imx290_format_info imx290_formats[] = {
75 {
76 - .code = MEDIA_BUS_FMT_SRGGB10_1X10,
77 + .code = {
78 + [IMX290_VARIANT_COLOUR] = MEDIA_BUS_FMT_SRGGB10_1X10,
79 + [IMX290_VARIANT_MONO] = MEDIA_BUS_FMT_Y10_1X10
80 + },
81 .bpp = 10,
82 .regs = imx290_10bit_settings,
83 .num_regs = ARRAY_SIZE(imx290_10bit_settings),
84 }, {
85 - .code = MEDIA_BUS_FMT_SRGGB12_1X12,
86 + .code = {
87 + [IMX290_VARIANT_COLOUR] = MEDIA_BUS_FMT_SRGGB12_1X12,
88 + [IMX290_VARIANT_MONO] = MEDIA_BUS_FMT_Y12_1X12
89 + },
90 .bpp = 12,
91 .regs = imx290_12bit_settings,
92 .num_regs = ARRAY_SIZE(imx290_12bit_settings),
93 }
94 };
95
96 -static const struct imx290_format_info *imx290_format_info(u32 code)
97 +static const struct imx290_format_info *
98 +imx290_format_info(const struct imx290 *imx290, u32 code)
99 {
100 unsigned int i;
101
102 for (i = 0; i < ARRAY_SIZE(imx290_formats); ++i) {
103 const struct imx290_format_info *info = &imx290_formats[i];
104
105 - if (info->code == code)
106 + if (info->code[imx290->model->colour_variant] == code)
107 return info;
108 }
109
110 @@ -541,7 +565,7 @@ static int imx290_set_black_level(struct
111 const struct v4l2_mbus_framefmt *format,
112 unsigned int black_level, int *err)
113 {
114 - unsigned int bpp = imx290_format_info(format->code)->bpp;
115 + unsigned int bpp = imx290_format_info(imx290, format->code)->bpp;
116
117 return imx290_write(imx290, IMX290_BLKLEVEL,
118 black_level >> (16 - bpp), err);
119 @@ -553,7 +577,7 @@ static int imx290_setup_format(struct im
120 const struct imx290_format_info *info;
121 int ret;
122
123 - info = imx290_format_info(format->code);
124 + info = imx290_format_info(imx290, format->code);
125
126 ret = imx290_set_register_array(imx290, info->regs, info->num_regs);
127 if (ret < 0) {
128 @@ -654,7 +678,7 @@ static void imx290_ctrl_update(struct im
129
130 /* pixel rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
131 pixel_rate = link_freq * 2 * imx290->nlanes;
132 - do_div(pixel_rate, imx290_format_info(format->code)->bpp);
133 + do_div(pixel_rate, imx290_format_info(imx290, format->code)->bpp);
134
135 __v4l2_ctrl_s_ctrl(imx290->link_freq, mode->link_freq_index);
136 __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate, pixel_rate);
137 @@ -849,10 +873,12 @@ static int imx290_enum_mbus_code(struct
138 struct v4l2_subdev_state *sd_state,
139 struct v4l2_subdev_mbus_code_enum *code)
140 {
141 + const struct imx290 *imx290 = to_imx290(sd);
142 +
143 if (code->index >= ARRAY_SIZE(imx290_formats))
144 return -EINVAL;
145
146 - code->code = imx290_formats[code->index].code;
147 + code->code = imx290_formats[code->index].code[imx290->model->colour_variant];
148
149 return 0;
150 }
151 @@ -864,7 +890,7 @@ static int imx290_enum_frame_size(struct
152 const struct imx290 *imx290 = to_imx290(sd);
153 const struct imx290_mode *imx290_modes = imx290_modes_ptr(imx290);
154
155 - if (!imx290_format_info(fse->code))
156 + if (!imx290_format_info(imx290, fse->code))
157 return -EINVAL;
158
159 if (fse->index >= imx290_modes_num(imx290))
160 @@ -893,8 +919,8 @@ static int imx290_set_fmt(struct v4l2_su
161 fmt->format.width = mode->width;
162 fmt->format.height = mode->height;
163
164 - if (!imx290_format_info(fmt->format.code))
165 - fmt->format.code = imx290_formats[0].code;
166 + if (!imx290_format_info(imx290, fmt->format.code))
167 + fmt->format.code = imx290_formats[0].code[imx290->model->colour_variant];
168
169 fmt->format.field = V4L2_FIELD_NONE;
170
171 @@ -1182,6 +1208,15 @@ static s64 imx290_check_link_freqs(const
172 return 0;
173 }
174
175 +static const struct imx290_model_info imx290_models[] = {
176 + [IMX290_MODEL_IMX290LQR] = {
177 + .colour_variant = IMX290_VARIANT_COLOUR,
178 + },
179 + [IMX290_MODEL_IMX290LLR] = {
180 + .colour_variant = IMX290_VARIANT_MONO,
181 + },
182 +};
183 +
184 static int imx290_parse_dt(struct imx290 *imx290)
185 {
186 /* Only CSI2 is supported for now: */
187 @@ -1192,6 +1227,8 @@ static int imx290_parse_dt(struct imx290
188 int ret;
189 s64 fq;
190
191 + imx290->model = of_device_get_match_data(imx290->dev);
192 +
193 endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(imx290->dev), NULL);
194 if (!endpoint) {
195 dev_err(imx290->dev, "Endpoint node not found\n");
196 @@ -1357,8 +1394,18 @@ static void imx290_remove(struct i2c_cli
197 }
198
199 static const struct of_device_id imx290_of_match[] = {
200 - { .compatible = "sony,imx290" },
201 - { /* sentinel */ }
202 + {
203 + /* Deprecated - synonym for "sony,imx290lqr" */
204 + .compatible = "sony,imx290",
205 + .data = &imx290_models[IMX290_MODEL_IMX290LQR],
206 + }, {
207 + .compatible = "sony,imx290lqr",
208 + .data = &imx290_models[IMX290_MODEL_IMX290LQR],
209 + }, {
210 + .compatible = "sony,imx290llr",
211 + .data = &imx290_models[IMX290_MODEL_IMX290LLR],
212 + },
213 + { /* sentinel */ },
214 };
215 MODULE_DEVICE_TABLE(of, imx290_of_match);
216