f74627962e1f314c78b5ead7127c9656b76a4e03
[openwrt/staging/mans0n.git] /
1 From e3c6ec43e950d9e08715e2c693771080c7d078a3 Mon Sep 17 00:00:00 2001
2 From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
3 Date: Fri, 12 Jun 2020 15:53:50 +0200
4 Subject: [PATCH] media: i2c: imx290: Add configurable link frequency
5 and pixel rate
6
7 Commit 98e0500eadb772e1be32d8e369fcc3b7bcac93ed upstream.
8
9 IMX290 operates with multiple link frequency and pixel rate combinations.
10 The initial driver used a single setting for both but since we now have
11 the lane count support in place, let's add configurable link frequency
12 and pixel rate.
13
14 Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
15 Signed-off-by: Andrey Konovalov <andrey.konovalov@linaro.org>
16 Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
17 Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
18 ---
19 drivers/media/i2c/imx290.c | 148 +++++++++++++++++++++++++++----------
20 1 file changed, 109 insertions(+), 39 deletions(-)
21
22 --- a/drivers/media/i2c/imx290.c
23 +++ b/drivers/media/i2c/imx290.c
24 @@ -32,8 +32,6 @@
25 #define IMX290_PHY_LANE_NUM 0x3407
26 #define IMX290_CSI_LANE_MODE 0x3443
27
28 -#define IMX290_DEFAULT_LINK_FREQ 445500000
29 -
30 static const char * const imx290_supply_name[] = {
31 "vdda",
32 "vddd",
33 @@ -51,8 +49,7 @@ struct imx290_mode {
34 u32 width;
35 u32 height;
36 u32 hmax;
37 - u32 pixel_rate;
38 - u32 link_freq_index;
39 + u8 link_freq_index;
40
41 const struct imx290_regval *data;
42 u32 data_size;
43 @@ -243,9 +240,36 @@ static const struct imx290_regval imx290
44 };
45
46 /* supported link frequencies */
47 -static const s64 imx290_link_freq[] = {
48 - IMX290_DEFAULT_LINK_FREQ,
49 -};
50 +#define FREQ_INDEX_1080P 0
51 +#define FREQ_INDEX_720P 1
52 +static const s64 imx290_link_freq_2lanes[] = {
53 + [FREQ_INDEX_1080P] = 445500000,
54 + [FREQ_INDEX_720P] = 297000000,
55 +};
56 +static const s64 imx290_link_freq_4lanes[] = {
57 + [FREQ_INDEX_1080P] = 222750000,
58 + [FREQ_INDEX_720P] = 148500000,
59 +};
60 +
61 +/*
62 + * In this function and in the similar ones below We rely on imx290_probe()
63 + * to ensure that nlanes is either 2 or 4.
64 + */
65 +static inline const s64 *imx290_link_freqs_ptr(const struct imx290 *imx290)
66 +{
67 + if (imx290->nlanes == 2)
68 + return imx290_link_freq_2lanes;
69 + else
70 + return imx290_link_freq_4lanes;
71 +}
72 +
73 +static inline int imx290_link_freqs_num(const struct imx290 *imx290)
74 +{
75 + if (imx290->nlanes == 2)
76 + return ARRAY_SIZE(imx290_link_freq_2lanes);
77 + else
78 + return ARRAY_SIZE(imx290_link_freq_4lanes);
79 +}
80
81 /* Mode configs */
82 static const struct imx290_mode imx290_modes_2lanes[] = {
83 @@ -253,19 +277,17 @@ static const struct imx290_mode imx290_m
84 .width = 1920,
85 .height = 1080,
86 .hmax = 0x1130,
87 + .link_freq_index = FREQ_INDEX_1080P,
88 .data = imx290_1080p_settings,
89 .data_size = ARRAY_SIZE(imx290_1080p_settings),
90 - .pixel_rate = 178200000,
91 - .link_freq_index = 0,
92 },
93 {
94 .width = 1280,
95 .height = 720,
96 .hmax = 0x19c8,
97 + .link_freq_index = FREQ_INDEX_720P,
98 .data = imx290_720p_settings,
99 .data_size = ARRAY_SIZE(imx290_720p_settings),
100 - .pixel_rate = 178200000,
101 - .link_freq_index = 0,
102 },
103 };
104
105 @@ -274,25 +296,22 @@ static const struct imx290_mode imx290_m
106 .width = 1920,
107 .height = 1080,
108 .hmax = 0x0898,
109 + .link_freq_index = FREQ_INDEX_1080P,
110 .data = imx290_1080p_settings,
111 .data_size = ARRAY_SIZE(imx290_1080p_settings),
112 - .pixel_rate = 178200000,
113 - .link_freq_index = 0,
114 },
115 {
116 .width = 1280,
117 .height = 720,
118 .hmax = 0x0ce4,
119 + .link_freq_index = FREQ_INDEX_720P,
120 .data = imx290_720p_settings,
121 .data_size = ARRAY_SIZE(imx290_720p_settings),
122 - .pixel_rate = 178200000,
123 - .link_freq_index = 0,
124 },
125 };
126
127 static inline const struct imx290_mode *imx290_modes_ptr(const struct imx290 *imx290)
128 {
129 - /* We rely on imx290_probe() to ensure that nlanes is either 2 or 4 */
130 if (imx290->nlanes == 2)
131 return imx290_modes_2lanes;
132 else
133 @@ -477,6 +496,30 @@ static int imx290_get_fmt(struct v4l2_su
134 return 0;
135 }
136
137 +static inline u8 imx290_get_link_freq_index(struct imx290 *imx290)
138 +{
139 + return imx290->current_mode->link_freq_index;
140 +}
141 +
142 +static s64 imx290_get_link_freq(struct imx290 *imx290)
143 +{
144 + u8 index = imx290_get_link_freq_index(imx290);
145 +
146 + return *(imx290_link_freqs_ptr(imx290) + index);
147 +}
148 +
149 +static u64 imx290_calc_pixel_rate(struct imx290 *imx290)
150 +{
151 + s64 link_freq = imx290_get_link_freq(imx290);
152 + u8 nlanes = imx290->nlanes;
153 + u64 pixel_rate;
154 +
155 + /* pixel rate = link_freq * 2 * nr_of_lanes / bits_per_sample */
156 + pixel_rate = link_freq * 2 * nlanes;
157 + do_div(pixel_rate, 10);
158 + return pixel_rate;
159 +}
160 +
161 static int imx290_set_fmt(struct v4l2_subdev *sd,
162 struct v4l2_subdev_pad_config *cfg,
163 struct v4l2_subdev_format *fmt)
164 @@ -509,10 +552,14 @@ static int imx290_set_fmt(struct v4l2_su
165 format = v4l2_subdev_get_try_format(sd, cfg, fmt->pad);
166 } else {
167 format = &imx290->current_format;
168 - __v4l2_ctrl_s_ctrl(imx290->link_freq, mode->link_freq_index);
169 - __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate, mode->pixel_rate);
170 -
171 imx290->current_mode = mode;
172 +
173 + if (imx290->link_freq)
174 + __v4l2_ctrl_s_ctrl(imx290->link_freq,
175 + imx290_get_link_freq_index(imx290));
176 + if (imx290->pixel_rate)
177 + __v4l2_ctrl_s_ctrl_int64(imx290->pixel_rate,
178 + imx290_calc_pixel_rate(imx290));
179 }
180
181 *format = fmt->format;
182 @@ -536,12 +583,11 @@ static int imx290_entity_init_cfg(struct
183 return 0;
184 }
185
186 -static int imx290_write_current_format(struct imx290 *imx290,
187 - struct v4l2_mbus_framefmt *format)
188 +static int imx290_write_current_format(struct imx290 *imx290)
189 {
190 int ret;
191
192 - switch (format->code) {
193 + switch (imx290->current_format.code) {
194 case MEDIA_BUS_FMT_SRGGB10_1X10:
195 ret = imx290_set_register_array(imx290, imx290_10bit_settings,
196 ARRAY_SIZE(
197 @@ -592,8 +638,8 @@ static int imx290_start_streaming(struct
198 return ret;
199 }
200
201 - /* Set current frame format */
202 - ret = imx290_write_current_format(imx290, &imx290->current_format);
203 + /* Apply the register values related to current frame format */
204 + ret = imx290_write_current_format(imx290);
205 if (ret < 0) {
206 dev_err(imx290->dev, "Could not set frame format\n");
207 return ret;
208 @@ -776,13 +822,34 @@ static const struct media_entity_operati
209 .link_validate = v4l2_subdev_link_validate,
210 };
211
212 +/*
213 + * Returns 0 if all link frequencies used by the driver for the given number
214 + * of MIPI data lanes are mentioned in the device tree, or the value of the
215 + * first missing frequency otherwise.
216 + */
217 +static s64 imx290_check_link_freqs(const struct imx290 *imx290)
218 +{
219 + int i, j;
220 + const s64 *freqs = imx290_link_freqs_ptr(imx290);
221 + int freqs_count = imx290_link_freqs_num(imx290);
222 +
223 + for (i = 0; i < freqs_count; i++) {
224 + for (j = 0; j < imx290->ep.nr_of_link_frequencies; j++)
225 + if (freqs[i] == imx290->ep.link_frequencies[j])
226 + break;
227 + if (j == imx290->ep.nr_of_link_frequencies)
228 + return freqs[i];
229 + }
230 + return 0;
231 +}
232 +
233 static int imx290_probe(struct i2c_client *client)
234 {
235 struct device *dev = &client->dev;
236 struct fwnode_handle *endpoint;
237 struct imx290 *imx290;
238 u32 xclk_freq;
239 - u32 default_pixel_rate;
240 + s64 fq;
241 int ret;
242
243 imx290 = devm_kzalloc(dev, sizeof(*imx290), GFP_KERNEL);
244 @@ -825,8 +892,10 @@ static int imx290_probe(struct i2c_clien
245 goto free_err;
246 }
247
248 - if (imx290->ep.link_frequencies[0] != IMX290_DEFAULT_LINK_FREQ) {
249 - dev_err(dev, "Unsupported link frequency\n");
250 + /* Check that link frequences for all the modes are in device tree */
251 + fq = imx290_check_link_freqs(imx290);
252 + if (fq) {
253 + dev_err(dev, "Link frequency of %lld is not supported\n", fq);
254 ret = -EINVAL;
255 goto free_err;
256 }
257 @@ -883,26 +952,30 @@ static int imx290_probe(struct i2c_clien
258
259 mutex_init(&imx290->lock);
260
261 + /*
262 + * Initialize the frame format. In particular, imx290->current_mode
263 + * and imx290->bpp are set to defaults: imx290_calc_pixel_rate() call
264 + * below relies on these fields.
265 + */
266 + imx290_entity_init_cfg(&imx290->sd, NULL);
267 +
268 v4l2_ctrl_handler_init(&imx290->ctrls, 3);
269
270 v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
271 V4L2_CID_GAIN, 0, 72, 1, 0);
272 +
273 imx290->link_freq =
274 - v4l2_ctrl_new_int_menu(&imx290->ctrls,
275 - &imx290_ctrl_ops,
276 + v4l2_ctrl_new_int_menu(&imx290->ctrls, &imx290_ctrl_ops,
277 V4L2_CID_LINK_FREQ,
278 - ARRAY_SIZE(imx290_link_freq) - 1,
279 - 0, imx290_link_freq);
280 + imx290_link_freqs_num(imx290) - 1, 0,
281 + imx290_link_freqs_ptr(imx290));
282 if (imx290->link_freq)
283 imx290->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
284
285 - default_pixel_rate = imx290->nlanes == 2 ?
286 - imx290_modes_2lanes[0].pixel_rate :
287 - imx290_modes_4lanes[0].pixel_rate;
288 imx290->pixel_rate = v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
289 - V4L2_CID_PIXEL_RATE, 1,
290 - INT_MAX, 1,
291 - default_pixel_rate);
292 + V4L2_CID_PIXEL_RATE,
293 + 1, INT_MAX, 1,
294 + imx290_calc_pixel_rate(imx290));
295
296 imx290->sd.ctrl_handler = &imx290->ctrls;
297
298 @@ -926,9 +999,6 @@ static int imx290_probe(struct i2c_clien
299 goto free_ctrl;
300 }
301
302 - /* Initialize the frame format (this also sets imx290->current_mode) */
303 - imx290_entity_init_cfg(&imx290->sd, NULL);
304 -
305 ret = v4l2_async_register_subdev(&imx290->sd);
306 if (ret < 0) {
307 dev_err(dev, "Could not register v4l2 device\n");