1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * imx214.c - imx214 sensor driver |
4 | * |
5 | * Copyright 2018 Qtechnology A/S |
6 | * |
7 | * Ricardo Ribalda <ribalda@kernel.org> |
8 | */ |
9 | #include <linux/clk.h> |
10 | #include <linux/delay.h> |
11 | #include <linux/gpio/consumer.h> |
12 | #include <linux/i2c.h> |
13 | #include <linux/module.h> |
14 | #include <linux/pm_runtime.h> |
15 | #include <linux/regmap.h> |
16 | #include <linux/regulator/consumer.h> |
17 | #include <media/media-entity.h> |
18 | #include <media/v4l2-ctrls.h> |
19 | #include <media/v4l2-fwnode.h> |
20 | #include <media/v4l2-subdev.h> |
21 | |
22 | #define IMX214_REG_MODE_SELECT 0x0100 |
23 | #define IMX214_MODE_STANDBY 0x00 |
24 | #define IMX214_MODE_STREAMING 0x01 |
25 | |
26 | #define IMX214_DEFAULT_CLK_FREQ 24000000 |
27 | #define IMX214_DEFAULT_LINK_FREQ 480000000 |
28 | #define IMX214_DEFAULT_PIXEL_RATE ((IMX214_DEFAULT_LINK_FREQ * 8LL) / 10) |
29 | #define IMX214_FPS 30 |
30 | #define IMX214_MBUS_CODE MEDIA_BUS_FMT_SRGGB10_1X10 |
31 | |
32 | /* Exposure control */ |
33 | #define IMX214_REG_EXPOSURE 0x0202 |
34 | #define IMX214_EXPOSURE_MIN 0 |
35 | #define IMX214_EXPOSURE_MAX 3184 |
36 | #define IMX214_EXPOSURE_STEP 1 |
37 | #define IMX214_EXPOSURE_DEFAULT 3184 |
38 | |
39 | /* IMX214 native and active pixel array size */ |
40 | #define IMX214_NATIVE_WIDTH 4224U |
41 | #define IMX214_NATIVE_HEIGHT 3136U |
42 | #define IMX214_PIXEL_ARRAY_LEFT 8U |
43 | #define IMX214_PIXEL_ARRAY_TOP 8U |
44 | #define IMX214_PIXEL_ARRAY_WIDTH 4208U |
45 | #define IMX214_PIXEL_ARRAY_HEIGHT 3120U |
46 | |
47 | static const char * const imx214_supply_name[] = { |
48 | "vdda" , |
49 | "vddd" , |
50 | "vdddo" , |
51 | }; |
52 | |
53 | #define IMX214_NUM_SUPPLIES ARRAY_SIZE(imx214_supply_name) |
54 | |
55 | struct imx214 { |
56 | struct device *dev; |
57 | struct clk *xclk; |
58 | struct regmap *regmap; |
59 | |
60 | struct v4l2_subdev sd; |
61 | struct media_pad pad; |
62 | struct v4l2_mbus_framefmt fmt; |
63 | struct v4l2_rect crop; |
64 | |
65 | struct v4l2_ctrl_handler ctrls; |
66 | struct v4l2_ctrl *pixel_rate; |
67 | struct v4l2_ctrl *link_freq; |
68 | struct v4l2_ctrl *exposure; |
69 | struct v4l2_ctrl *unit_size; |
70 | |
71 | struct regulator_bulk_data supplies[IMX214_NUM_SUPPLIES]; |
72 | |
73 | struct gpio_desc *enable_gpio; |
74 | |
75 | /* |
76 | * Serialize control access, get/set format, get selection |
77 | * and start streaming. |
78 | */ |
79 | struct mutex mutex; |
80 | }; |
81 | |
82 | struct reg_8 { |
83 | u16 addr; |
84 | u8 val; |
85 | }; |
86 | |
87 | enum { |
88 | IMX214_TABLE_WAIT_MS = 0, |
89 | IMX214_TABLE_END, |
90 | IMX214_MAX_RETRIES, |
91 | IMX214_WAIT_MS |
92 | }; |
93 | |
94 | /*From imx214_mode_tbls.h*/ |
95 | static const struct reg_8 mode_4096x2304[] = { |
96 | {0x0114, 0x03}, |
97 | {0x0220, 0x00}, |
98 | {0x0221, 0x11}, |
99 | {0x0222, 0x01}, |
100 | {0x0340, 0x0C}, |
101 | {0x0341, 0x7A}, |
102 | {0x0342, 0x13}, |
103 | {0x0343, 0x90}, |
104 | {0x0344, 0x00}, |
105 | {0x0345, 0x38}, |
106 | {0x0346, 0x01}, |
107 | {0x0347, 0x98}, |
108 | {0x0348, 0x10}, |
109 | {0x0349, 0x37}, |
110 | {0x034A, 0x0A}, |
111 | {0x034B, 0x97}, |
112 | {0x0381, 0x01}, |
113 | {0x0383, 0x01}, |
114 | {0x0385, 0x01}, |
115 | {0x0387, 0x01}, |
116 | {0x0900, 0x00}, |
117 | {0x0901, 0x00}, |
118 | {0x0902, 0x00}, |
119 | {0x3000, 0x35}, |
120 | {0x3054, 0x01}, |
121 | {0x305C, 0x11}, |
122 | |
123 | {0x0112, 0x0A}, |
124 | {0x0113, 0x0A}, |
125 | {0x034C, 0x10}, |
126 | {0x034D, 0x00}, |
127 | {0x034E, 0x09}, |
128 | {0x034F, 0x00}, |
129 | {0x0401, 0x00}, |
130 | {0x0404, 0x00}, |
131 | {0x0405, 0x10}, |
132 | {0x0408, 0x00}, |
133 | {0x0409, 0x00}, |
134 | {0x040A, 0x00}, |
135 | {0x040B, 0x00}, |
136 | {0x040C, 0x10}, |
137 | {0x040D, 0x00}, |
138 | {0x040E, 0x09}, |
139 | {0x040F, 0x00}, |
140 | |
141 | {0x0301, 0x05}, |
142 | {0x0303, 0x02}, |
143 | {0x0305, 0x03}, |
144 | {0x0306, 0x00}, |
145 | {0x0307, 0x96}, |
146 | {0x0309, 0x0A}, |
147 | {0x030B, 0x01}, |
148 | {0x0310, 0x00}, |
149 | |
150 | {0x0820, 0x12}, |
151 | {0x0821, 0xC0}, |
152 | {0x0822, 0x00}, |
153 | {0x0823, 0x00}, |
154 | |
155 | {0x3A03, 0x09}, |
156 | {0x3A04, 0x50}, |
157 | {0x3A05, 0x01}, |
158 | |
159 | {0x0B06, 0x01}, |
160 | {0x30A2, 0x00}, |
161 | |
162 | {0x30B4, 0x00}, |
163 | |
164 | {0x3A02, 0xFF}, |
165 | |
166 | {0x3011, 0x00}, |
167 | {0x3013, 0x01}, |
168 | |
169 | {0x0202, 0x0C}, |
170 | {0x0203, 0x70}, |
171 | {0x0224, 0x01}, |
172 | {0x0225, 0xF4}, |
173 | |
174 | {0x0204, 0x00}, |
175 | {0x0205, 0x00}, |
176 | {0x020E, 0x01}, |
177 | {0x020F, 0x00}, |
178 | {0x0210, 0x01}, |
179 | {0x0211, 0x00}, |
180 | {0x0212, 0x01}, |
181 | {0x0213, 0x00}, |
182 | {0x0214, 0x01}, |
183 | {0x0215, 0x00}, |
184 | {0x0216, 0x00}, |
185 | {0x0217, 0x00}, |
186 | |
187 | {0x4170, 0x00}, |
188 | {0x4171, 0x10}, |
189 | {0x4176, 0x00}, |
190 | {0x4177, 0x3C}, |
191 | {0xAE20, 0x04}, |
192 | {0xAE21, 0x5C}, |
193 | |
194 | {IMX214_TABLE_WAIT_MS, 10}, |
195 | {0x0138, 0x01}, |
196 | {IMX214_TABLE_END, 0x00} |
197 | }; |
198 | |
199 | static const struct reg_8 mode_1920x1080[] = { |
200 | {0x0114, 0x03}, |
201 | {0x0220, 0x00}, |
202 | {0x0221, 0x11}, |
203 | {0x0222, 0x01}, |
204 | {0x0340, 0x0C}, |
205 | {0x0341, 0x7A}, |
206 | {0x0342, 0x13}, |
207 | {0x0343, 0x90}, |
208 | {0x0344, 0x04}, |
209 | {0x0345, 0x78}, |
210 | {0x0346, 0x03}, |
211 | {0x0347, 0xFC}, |
212 | {0x0348, 0x0B}, |
213 | {0x0349, 0xF7}, |
214 | {0x034A, 0x08}, |
215 | {0x034B, 0x33}, |
216 | {0x0381, 0x01}, |
217 | {0x0383, 0x01}, |
218 | {0x0385, 0x01}, |
219 | {0x0387, 0x01}, |
220 | {0x0900, 0x00}, |
221 | {0x0901, 0x00}, |
222 | {0x0902, 0x00}, |
223 | {0x3000, 0x35}, |
224 | {0x3054, 0x01}, |
225 | {0x305C, 0x11}, |
226 | |
227 | {0x0112, 0x0A}, |
228 | {0x0113, 0x0A}, |
229 | {0x034C, 0x07}, |
230 | {0x034D, 0x80}, |
231 | {0x034E, 0x04}, |
232 | {0x034F, 0x38}, |
233 | {0x0401, 0x00}, |
234 | {0x0404, 0x00}, |
235 | {0x0405, 0x10}, |
236 | {0x0408, 0x00}, |
237 | {0x0409, 0x00}, |
238 | {0x040A, 0x00}, |
239 | {0x040B, 0x00}, |
240 | {0x040C, 0x07}, |
241 | {0x040D, 0x80}, |
242 | {0x040E, 0x04}, |
243 | {0x040F, 0x38}, |
244 | |
245 | {0x0301, 0x05}, |
246 | {0x0303, 0x02}, |
247 | {0x0305, 0x03}, |
248 | {0x0306, 0x00}, |
249 | {0x0307, 0x96}, |
250 | {0x0309, 0x0A}, |
251 | {0x030B, 0x01}, |
252 | {0x0310, 0x00}, |
253 | |
254 | {0x0820, 0x12}, |
255 | {0x0821, 0xC0}, |
256 | {0x0822, 0x00}, |
257 | {0x0823, 0x00}, |
258 | |
259 | {0x3A03, 0x04}, |
260 | {0x3A04, 0xF8}, |
261 | {0x3A05, 0x02}, |
262 | |
263 | {0x0B06, 0x01}, |
264 | {0x30A2, 0x00}, |
265 | |
266 | {0x30B4, 0x00}, |
267 | |
268 | {0x3A02, 0xFF}, |
269 | |
270 | {0x3011, 0x00}, |
271 | {0x3013, 0x01}, |
272 | |
273 | {0x0202, 0x0C}, |
274 | {0x0203, 0x70}, |
275 | {0x0224, 0x01}, |
276 | {0x0225, 0xF4}, |
277 | |
278 | {0x0204, 0x00}, |
279 | {0x0205, 0x00}, |
280 | {0x020E, 0x01}, |
281 | {0x020F, 0x00}, |
282 | {0x0210, 0x01}, |
283 | {0x0211, 0x00}, |
284 | {0x0212, 0x01}, |
285 | {0x0213, 0x00}, |
286 | {0x0214, 0x01}, |
287 | {0x0215, 0x00}, |
288 | {0x0216, 0x00}, |
289 | {0x0217, 0x00}, |
290 | |
291 | {0x4170, 0x00}, |
292 | {0x4171, 0x10}, |
293 | {0x4176, 0x00}, |
294 | {0x4177, 0x3C}, |
295 | {0xAE20, 0x04}, |
296 | {0xAE21, 0x5C}, |
297 | |
298 | {IMX214_TABLE_WAIT_MS, 10}, |
299 | {0x0138, 0x01}, |
300 | {IMX214_TABLE_END, 0x00} |
301 | }; |
302 | |
303 | static const struct reg_8 mode_table_common[] = { |
304 | /* software reset */ |
305 | |
306 | /* software standby settings */ |
307 | {0x0100, 0x00}, |
308 | |
309 | /* ATR setting */ |
310 | {0x9300, 0x02}, |
311 | |
312 | /* external clock setting */ |
313 | {0x0136, 0x18}, |
314 | {0x0137, 0x00}, |
315 | |
316 | /* global setting */ |
317 | /* basic config */ |
318 | {0x0101, 0x00}, |
319 | {0x0105, 0x01}, |
320 | {0x0106, 0x01}, |
321 | {0x4550, 0x02}, |
322 | {0x4601, 0x00}, |
323 | {0x4642, 0x05}, |
324 | {0x6227, 0x11}, |
325 | {0x6276, 0x00}, |
326 | {0x900E, 0x06}, |
327 | {0xA802, 0x90}, |
328 | {0xA803, 0x11}, |
329 | {0xA804, 0x62}, |
330 | {0xA805, 0x77}, |
331 | {0xA806, 0xAE}, |
332 | {0xA807, 0x34}, |
333 | {0xA808, 0xAE}, |
334 | {0xA809, 0x35}, |
335 | {0xA80A, 0x62}, |
336 | {0xA80B, 0x83}, |
337 | {0xAE33, 0x00}, |
338 | |
339 | /* analog setting */ |
340 | {0x4174, 0x00}, |
341 | {0x4175, 0x11}, |
342 | {0x4612, 0x29}, |
343 | {0x461B, 0x12}, |
344 | {0x461F, 0x06}, |
345 | {0x4635, 0x07}, |
346 | {0x4637, 0x30}, |
347 | {0x463F, 0x18}, |
348 | {0x4641, 0x0D}, |
349 | {0x465B, 0x12}, |
350 | {0x465F, 0x11}, |
351 | {0x4663, 0x11}, |
352 | {0x4667, 0x0F}, |
353 | {0x466F, 0x0F}, |
354 | {0x470E, 0x09}, |
355 | {0x4909, 0xAB}, |
356 | {0x490B, 0x95}, |
357 | {0x4915, 0x5D}, |
358 | {0x4A5F, 0xFF}, |
359 | {0x4A61, 0xFF}, |
360 | {0x4A73, 0x62}, |
361 | {0x4A85, 0x00}, |
362 | {0x4A87, 0xFF}, |
363 | |
364 | /* embedded data */ |
365 | {0x5041, 0x04}, |
366 | {0x583C, 0x04}, |
367 | {0x620E, 0x04}, |
368 | {0x6EB2, 0x01}, |
369 | {0x6EB3, 0x00}, |
370 | {0x9300, 0x02}, |
371 | |
372 | /* imagequality */ |
373 | /* HDR setting */ |
374 | {0x3001, 0x07}, |
375 | {0x6D12, 0x3F}, |
376 | {0x6D13, 0xFF}, |
377 | {0x9344, 0x03}, |
378 | {0x9706, 0x10}, |
379 | {0x9707, 0x03}, |
380 | {0x9708, 0x03}, |
381 | {0x9E04, 0x01}, |
382 | {0x9E05, 0x00}, |
383 | {0x9E0C, 0x01}, |
384 | {0x9E0D, 0x02}, |
385 | {0x9E24, 0x00}, |
386 | {0x9E25, 0x8C}, |
387 | {0x9E26, 0x00}, |
388 | {0x9E27, 0x94}, |
389 | {0x9E28, 0x00}, |
390 | {0x9E29, 0x96}, |
391 | |
392 | /* CNR parameter setting */ |
393 | {0x69DB, 0x01}, |
394 | |
395 | /* Moire reduction */ |
396 | {0x6957, 0x01}, |
397 | |
398 | /* image enhancement */ |
399 | {0x6987, 0x17}, |
400 | {0x698A, 0x03}, |
401 | {0x698B, 0x03}, |
402 | |
403 | /* white balanace */ |
404 | {0x0B8E, 0x01}, |
405 | {0x0B8F, 0x00}, |
406 | {0x0B90, 0x01}, |
407 | {0x0B91, 0x00}, |
408 | {0x0B92, 0x01}, |
409 | {0x0B93, 0x00}, |
410 | {0x0B94, 0x01}, |
411 | {0x0B95, 0x00}, |
412 | |
413 | /* ATR setting */ |
414 | {0x6E50, 0x00}, |
415 | {0x6E51, 0x32}, |
416 | {0x9340, 0x00}, |
417 | {0x9341, 0x3C}, |
418 | {0x9342, 0x03}, |
419 | {0x9343, 0xFF}, |
420 | {IMX214_TABLE_END, 0x00} |
421 | }; |
422 | |
423 | /* |
424 | * Declare modes in order, from biggest |
425 | * to smallest height. |
426 | */ |
427 | static const struct imx214_mode { |
428 | u32 width; |
429 | u32 height; |
430 | const struct reg_8 *reg_table; |
431 | } imx214_modes[] = { |
432 | { |
433 | .width = 4096, |
434 | .height = 2304, |
435 | .reg_table = mode_4096x2304, |
436 | }, |
437 | { |
438 | .width = 1920, |
439 | .height = 1080, |
440 | .reg_table = mode_1920x1080, |
441 | }, |
442 | }; |
443 | |
444 | static inline struct imx214 *to_imx214(struct v4l2_subdev *sd) |
445 | { |
446 | return container_of(sd, struct imx214, sd); |
447 | } |
448 | |
449 | static int __maybe_unused imx214_power_on(struct device *dev) |
450 | { |
451 | struct i2c_client *client = to_i2c_client(dev); |
452 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
453 | struct imx214 *imx214 = to_imx214(sd); |
454 | int ret; |
455 | |
456 | ret = regulator_bulk_enable(IMX214_NUM_SUPPLIES, consumers: imx214->supplies); |
457 | if (ret < 0) { |
458 | dev_err(imx214->dev, "failed to enable regulators: %d\n" , ret); |
459 | return ret; |
460 | } |
461 | |
462 | usleep_range(min: 2000, max: 3000); |
463 | |
464 | ret = clk_prepare_enable(clk: imx214->xclk); |
465 | if (ret < 0) { |
466 | regulator_bulk_disable(IMX214_NUM_SUPPLIES, consumers: imx214->supplies); |
467 | dev_err(imx214->dev, "clk prepare enable failed\n" ); |
468 | return ret; |
469 | } |
470 | |
471 | gpiod_set_value_cansleep(desc: imx214->enable_gpio, value: 1); |
472 | usleep_range(min: 12000, max: 15000); |
473 | |
474 | return 0; |
475 | } |
476 | |
477 | static int __maybe_unused imx214_power_off(struct device *dev) |
478 | { |
479 | struct i2c_client *client = to_i2c_client(dev); |
480 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
481 | struct imx214 *imx214 = to_imx214(sd); |
482 | |
483 | gpiod_set_value_cansleep(desc: imx214->enable_gpio, value: 0); |
484 | |
485 | clk_disable_unprepare(clk: imx214->xclk); |
486 | |
487 | regulator_bulk_disable(IMX214_NUM_SUPPLIES, consumers: imx214->supplies); |
488 | usleep_range(min: 10, max: 20); |
489 | |
490 | return 0; |
491 | } |
492 | |
493 | static int imx214_enum_mbus_code(struct v4l2_subdev *sd, |
494 | struct v4l2_subdev_state *sd_state, |
495 | struct v4l2_subdev_mbus_code_enum *code) |
496 | { |
497 | if (code->index > 0) |
498 | return -EINVAL; |
499 | |
500 | code->code = IMX214_MBUS_CODE; |
501 | |
502 | return 0; |
503 | } |
504 | |
505 | static int imx214_enum_frame_size(struct v4l2_subdev *subdev, |
506 | struct v4l2_subdev_state *sd_state, |
507 | struct v4l2_subdev_frame_size_enum *fse) |
508 | { |
509 | if (fse->code != IMX214_MBUS_CODE) |
510 | return -EINVAL; |
511 | |
512 | if (fse->index >= ARRAY_SIZE(imx214_modes)) |
513 | return -EINVAL; |
514 | |
515 | fse->min_width = fse->max_width = imx214_modes[fse->index].width; |
516 | fse->min_height = fse->max_height = imx214_modes[fse->index].height; |
517 | |
518 | return 0; |
519 | } |
520 | |
521 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
522 | static int imx214_s_register(struct v4l2_subdev *subdev, |
523 | const struct v4l2_dbg_register *reg) |
524 | { |
525 | struct imx214 *imx214 = container_of(subdev, struct imx214, sd); |
526 | |
527 | return regmap_write(map: imx214->regmap, reg: reg->reg, val: reg->val); |
528 | } |
529 | |
530 | static int imx214_g_register(struct v4l2_subdev *subdev, |
531 | struct v4l2_dbg_register *reg) |
532 | { |
533 | struct imx214 *imx214 = container_of(subdev, struct imx214, sd); |
534 | unsigned int aux; |
535 | int ret; |
536 | |
537 | reg->size = 1; |
538 | ret = regmap_read(map: imx214->regmap, reg: reg->reg, val: &aux); |
539 | reg->val = aux; |
540 | |
541 | return ret; |
542 | } |
543 | #endif |
544 | |
545 | static const struct v4l2_subdev_core_ops imx214_core_ops = { |
546 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
547 | .g_register = imx214_g_register, |
548 | .s_register = imx214_s_register, |
549 | #endif |
550 | }; |
551 | |
552 | static struct v4l2_mbus_framefmt * |
553 | __imx214_get_pad_format(struct imx214 *imx214, |
554 | struct v4l2_subdev_state *sd_state, |
555 | unsigned int pad, |
556 | enum v4l2_subdev_format_whence which) |
557 | { |
558 | switch (which) { |
559 | case V4L2_SUBDEV_FORMAT_TRY: |
560 | return v4l2_subdev_state_get_format(sd_state, pad); |
561 | case V4L2_SUBDEV_FORMAT_ACTIVE: |
562 | return &imx214->fmt; |
563 | default: |
564 | return NULL; |
565 | } |
566 | } |
567 | |
568 | static int imx214_get_format(struct v4l2_subdev *sd, |
569 | struct v4l2_subdev_state *sd_state, |
570 | struct v4l2_subdev_format *format) |
571 | { |
572 | struct imx214 *imx214 = to_imx214(sd); |
573 | |
574 | mutex_lock(&imx214->mutex); |
575 | format->format = *__imx214_get_pad_format(imx214, sd_state, |
576 | pad: format->pad, |
577 | which: format->which); |
578 | mutex_unlock(lock: &imx214->mutex); |
579 | |
580 | return 0; |
581 | } |
582 | |
583 | static struct v4l2_rect * |
584 | __imx214_get_pad_crop(struct imx214 *imx214, |
585 | struct v4l2_subdev_state *sd_state, |
586 | unsigned int pad, enum v4l2_subdev_format_whence which) |
587 | { |
588 | switch (which) { |
589 | case V4L2_SUBDEV_FORMAT_TRY: |
590 | return v4l2_subdev_state_get_crop(sd_state, pad); |
591 | case V4L2_SUBDEV_FORMAT_ACTIVE: |
592 | return &imx214->crop; |
593 | default: |
594 | return NULL; |
595 | } |
596 | } |
597 | |
598 | static int imx214_set_format(struct v4l2_subdev *sd, |
599 | struct v4l2_subdev_state *sd_state, |
600 | struct v4l2_subdev_format *format) |
601 | { |
602 | struct imx214 *imx214 = to_imx214(sd); |
603 | struct v4l2_mbus_framefmt *__format; |
604 | struct v4l2_rect *__crop; |
605 | const struct imx214_mode *mode; |
606 | |
607 | mutex_lock(&imx214->mutex); |
608 | |
609 | __crop = __imx214_get_pad_crop(imx214, sd_state, pad: format->pad, |
610 | which: format->which); |
611 | |
612 | mode = v4l2_find_nearest_size(imx214_modes, |
613 | ARRAY_SIZE(imx214_modes), width, height, |
614 | format->format.width, |
615 | format->format.height); |
616 | |
617 | __crop->width = mode->width; |
618 | __crop->height = mode->height; |
619 | |
620 | __format = __imx214_get_pad_format(imx214, sd_state, pad: format->pad, |
621 | which: format->which); |
622 | __format->width = __crop->width; |
623 | __format->height = __crop->height; |
624 | __format->code = IMX214_MBUS_CODE; |
625 | __format->field = V4L2_FIELD_NONE; |
626 | __format->colorspace = V4L2_COLORSPACE_SRGB; |
627 | __format->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(__format->colorspace); |
628 | __format->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, |
629 | __format->colorspace, __format->ycbcr_enc); |
630 | __format->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(__format->colorspace); |
631 | |
632 | format->format = *__format; |
633 | |
634 | mutex_unlock(lock: &imx214->mutex); |
635 | |
636 | return 0; |
637 | } |
638 | |
639 | static int imx214_get_selection(struct v4l2_subdev *sd, |
640 | struct v4l2_subdev_state *sd_state, |
641 | struct v4l2_subdev_selection *sel) |
642 | { |
643 | struct imx214 *imx214 = to_imx214(sd); |
644 | |
645 | switch (sel->target) { |
646 | case V4L2_SEL_TGT_CROP: |
647 | mutex_lock(&imx214->mutex); |
648 | sel->r = *__imx214_get_pad_crop(imx214, sd_state, pad: sel->pad, |
649 | which: sel->which); |
650 | mutex_unlock(lock: &imx214->mutex); |
651 | return 0; |
652 | |
653 | case V4L2_SEL_TGT_NATIVE_SIZE: |
654 | sel->r.top = 0; |
655 | sel->r.left = 0; |
656 | sel->r.width = IMX214_NATIVE_WIDTH; |
657 | sel->r.height = IMX214_NATIVE_HEIGHT; |
658 | return 0; |
659 | |
660 | case V4L2_SEL_TGT_CROP_DEFAULT: |
661 | case V4L2_SEL_TGT_CROP_BOUNDS: |
662 | sel->r.top = IMX214_PIXEL_ARRAY_TOP; |
663 | sel->r.left = IMX214_PIXEL_ARRAY_LEFT; |
664 | sel->r.width = IMX214_PIXEL_ARRAY_WIDTH; |
665 | sel->r.height = IMX214_PIXEL_ARRAY_HEIGHT; |
666 | return 0; |
667 | } |
668 | |
669 | return -EINVAL; |
670 | } |
671 | |
672 | static int imx214_entity_init_state(struct v4l2_subdev *subdev, |
673 | struct v4l2_subdev_state *sd_state) |
674 | { |
675 | struct v4l2_subdev_format fmt = { }; |
676 | |
677 | fmt.which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE; |
678 | fmt.format.width = imx214_modes[0].width; |
679 | fmt.format.height = imx214_modes[0].height; |
680 | |
681 | imx214_set_format(sd: subdev, sd_state, format: &fmt); |
682 | |
683 | return 0; |
684 | } |
685 | |
686 | static int imx214_set_ctrl(struct v4l2_ctrl *ctrl) |
687 | { |
688 | struct imx214 *imx214 = container_of(ctrl->handler, |
689 | struct imx214, ctrls); |
690 | u8 vals[2]; |
691 | int ret; |
692 | |
693 | /* |
694 | * Applying V4L2 control value only happens |
695 | * when power is up for streaming |
696 | */ |
697 | if (!pm_runtime_get_if_in_use(dev: imx214->dev)) |
698 | return 0; |
699 | |
700 | switch (ctrl->id) { |
701 | case V4L2_CID_EXPOSURE: |
702 | vals[1] = ctrl->val; |
703 | vals[0] = ctrl->val >> 8; |
704 | ret = regmap_bulk_write(map: imx214->regmap, IMX214_REG_EXPOSURE, val: vals, val_count: 2); |
705 | if (ret < 0) |
706 | dev_err(imx214->dev, "Error %d\n" , ret); |
707 | ret = 0; |
708 | break; |
709 | |
710 | default: |
711 | ret = -EINVAL; |
712 | } |
713 | |
714 | pm_runtime_put(dev: imx214->dev); |
715 | |
716 | return ret; |
717 | } |
718 | |
719 | static const struct v4l2_ctrl_ops imx214_ctrl_ops = { |
720 | .s_ctrl = imx214_set_ctrl, |
721 | }; |
722 | |
723 | static int imx214_ctrls_init(struct imx214 *imx214) |
724 | { |
725 | static const s64 link_freq[] = { |
726 | IMX214_DEFAULT_LINK_FREQ |
727 | }; |
728 | static const struct v4l2_area unit_size = { |
729 | .width = 1120, |
730 | .height = 1120, |
731 | }; |
732 | struct v4l2_fwnode_device_properties props; |
733 | struct v4l2_ctrl_handler *ctrl_hdlr; |
734 | int ret; |
735 | |
736 | ret = v4l2_fwnode_device_parse(dev: imx214->dev, props: &props); |
737 | if (ret < 0) |
738 | return ret; |
739 | |
740 | ctrl_hdlr = &imx214->ctrls; |
741 | ret = v4l2_ctrl_handler_init(&imx214->ctrls, 6); |
742 | if (ret) |
743 | return ret; |
744 | |
745 | imx214->pixel_rate = v4l2_ctrl_new_std(hdl: ctrl_hdlr, NULL, |
746 | V4L2_CID_PIXEL_RATE, min: 0, |
747 | IMX214_DEFAULT_PIXEL_RATE, step: 1, |
748 | IMX214_DEFAULT_PIXEL_RATE); |
749 | |
750 | imx214->link_freq = v4l2_ctrl_new_int_menu(hdl: ctrl_hdlr, NULL, |
751 | V4L2_CID_LINK_FREQ, |
752 | ARRAY_SIZE(link_freq) - 1, |
753 | def: 0, qmenu_int: link_freq); |
754 | if (imx214->link_freq) |
755 | imx214->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
756 | |
757 | /* |
758 | * WARNING! |
759 | * Values obtained reverse engineering blobs and/or devices. |
760 | * Ranges and functionality might be wrong. |
761 | * |
762 | * Sony, please release some register set documentation for the |
763 | * device. |
764 | * |
765 | * Yours sincerely, Ricardo. |
766 | */ |
767 | imx214->exposure = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &imx214_ctrl_ops, |
768 | V4L2_CID_EXPOSURE, |
769 | IMX214_EXPOSURE_MIN, |
770 | IMX214_EXPOSURE_MAX, |
771 | IMX214_EXPOSURE_STEP, |
772 | IMX214_EXPOSURE_DEFAULT); |
773 | |
774 | imx214->unit_size = v4l2_ctrl_new_std_compound(hdl: ctrl_hdlr, |
775 | NULL, |
776 | V4L2_CID_UNIT_CELL_SIZE, |
777 | p_def: v4l2_ctrl_ptr_create(ptr: (void *)&unit_size)); |
778 | |
779 | v4l2_ctrl_new_fwnode_properties(hdl: ctrl_hdlr, ctrl_ops: &imx214_ctrl_ops, p: &props); |
780 | |
781 | ret = ctrl_hdlr->error; |
782 | if (ret) { |
783 | v4l2_ctrl_handler_free(hdl: ctrl_hdlr); |
784 | dev_err(imx214->dev, "failed to add controls: %d\n" , ret); |
785 | return ret; |
786 | } |
787 | |
788 | imx214->sd.ctrl_handler = ctrl_hdlr; |
789 | |
790 | return 0; |
791 | }; |
792 | |
793 | #define MAX_CMD 4 |
794 | static int imx214_write_table(struct imx214 *imx214, |
795 | const struct reg_8 table[]) |
796 | { |
797 | u8 vals[MAX_CMD]; |
798 | int i; |
799 | int ret; |
800 | |
801 | for (; table->addr != IMX214_TABLE_END ; table++) { |
802 | if (table->addr == IMX214_TABLE_WAIT_MS) { |
803 | usleep_range(min: table->val * 1000, |
804 | max: table->val * 1000 + 500); |
805 | continue; |
806 | } |
807 | |
808 | for (i = 0; i < MAX_CMD; i++) { |
809 | if (table[i].addr != (table[0].addr + i)) |
810 | break; |
811 | vals[i] = table[i].val; |
812 | } |
813 | |
814 | ret = regmap_bulk_write(map: imx214->regmap, reg: table->addr, val: vals, val_count: i); |
815 | |
816 | if (ret) { |
817 | dev_err(imx214->dev, "write_table error: %d\n" , ret); |
818 | return ret; |
819 | } |
820 | |
821 | table += i - 1; |
822 | } |
823 | |
824 | return 0; |
825 | } |
826 | |
827 | static int imx214_start_streaming(struct imx214 *imx214) |
828 | { |
829 | const struct imx214_mode *mode; |
830 | int ret; |
831 | |
832 | mutex_lock(&imx214->mutex); |
833 | ret = imx214_write_table(imx214, table: mode_table_common); |
834 | if (ret < 0) { |
835 | dev_err(imx214->dev, "could not sent common table %d\n" , ret); |
836 | goto error; |
837 | } |
838 | |
839 | mode = v4l2_find_nearest_size(imx214_modes, |
840 | ARRAY_SIZE(imx214_modes), width, height, |
841 | imx214->fmt.width, imx214->fmt.height); |
842 | ret = imx214_write_table(imx214, table: mode->reg_table); |
843 | if (ret < 0) { |
844 | dev_err(imx214->dev, "could not sent mode table %d\n" , ret); |
845 | goto error; |
846 | } |
847 | ret = __v4l2_ctrl_handler_setup(hdl: &imx214->ctrls); |
848 | if (ret < 0) { |
849 | dev_err(imx214->dev, "could not sync v4l2 controls\n" ); |
850 | goto error; |
851 | } |
852 | ret = regmap_write(map: imx214->regmap, IMX214_REG_MODE_SELECT, IMX214_MODE_STREAMING); |
853 | if (ret < 0) { |
854 | dev_err(imx214->dev, "could not sent start table %d\n" , ret); |
855 | goto error; |
856 | } |
857 | |
858 | mutex_unlock(lock: &imx214->mutex); |
859 | return 0; |
860 | |
861 | error: |
862 | mutex_unlock(lock: &imx214->mutex); |
863 | return ret; |
864 | } |
865 | |
866 | static int imx214_stop_streaming(struct imx214 *imx214) |
867 | { |
868 | int ret; |
869 | |
870 | ret = regmap_write(map: imx214->regmap, IMX214_REG_MODE_SELECT, IMX214_MODE_STANDBY); |
871 | if (ret < 0) |
872 | dev_err(imx214->dev, "could not sent stop table %d\n" , ret); |
873 | |
874 | return ret; |
875 | } |
876 | |
877 | static int imx214_s_stream(struct v4l2_subdev *subdev, int enable) |
878 | { |
879 | struct imx214 *imx214 = to_imx214(sd: subdev); |
880 | int ret; |
881 | |
882 | if (enable) { |
883 | ret = pm_runtime_resume_and_get(dev: imx214->dev); |
884 | if (ret < 0) |
885 | return ret; |
886 | |
887 | ret = imx214_start_streaming(imx214); |
888 | if (ret < 0) |
889 | goto err_rpm_put; |
890 | } else { |
891 | ret = imx214_stop_streaming(imx214); |
892 | if (ret < 0) |
893 | goto err_rpm_put; |
894 | pm_runtime_put(dev: imx214->dev); |
895 | } |
896 | |
897 | return 0; |
898 | |
899 | err_rpm_put: |
900 | pm_runtime_put(dev: imx214->dev); |
901 | return ret; |
902 | } |
903 | |
904 | static int imx214_get_frame_interval(struct v4l2_subdev *subdev, |
905 | struct v4l2_subdev_state *sd_state, |
906 | struct v4l2_subdev_frame_interval *fival) |
907 | { |
908 | /* |
909 | * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 |
910 | * subdev active state API. |
911 | */ |
912 | if (fival->which != V4L2_SUBDEV_FORMAT_ACTIVE) |
913 | return -EINVAL; |
914 | |
915 | fival->interval.numerator = 1; |
916 | fival->interval.denominator = IMX214_FPS; |
917 | |
918 | return 0; |
919 | } |
920 | |
921 | static int imx214_enum_frame_interval(struct v4l2_subdev *subdev, |
922 | struct v4l2_subdev_state *sd_state, |
923 | struct v4l2_subdev_frame_interval_enum *fie) |
924 | { |
925 | const struct imx214_mode *mode; |
926 | |
927 | if (fie->index != 0) |
928 | return -EINVAL; |
929 | |
930 | mode = v4l2_find_nearest_size(imx214_modes, |
931 | ARRAY_SIZE(imx214_modes), width, height, |
932 | fie->width, fie->height); |
933 | |
934 | fie->code = IMX214_MBUS_CODE; |
935 | fie->width = mode->width; |
936 | fie->height = mode->height; |
937 | fie->interval.numerator = 1; |
938 | fie->interval.denominator = IMX214_FPS; |
939 | |
940 | return 0; |
941 | } |
942 | |
943 | static const struct v4l2_subdev_video_ops imx214_video_ops = { |
944 | .s_stream = imx214_s_stream, |
945 | }; |
946 | |
947 | static const struct v4l2_subdev_pad_ops imx214_subdev_pad_ops = { |
948 | .enum_mbus_code = imx214_enum_mbus_code, |
949 | .enum_frame_size = imx214_enum_frame_size, |
950 | .enum_frame_interval = imx214_enum_frame_interval, |
951 | .get_fmt = imx214_get_format, |
952 | .set_fmt = imx214_set_format, |
953 | .get_selection = imx214_get_selection, |
954 | .get_frame_interval = imx214_get_frame_interval, |
955 | .set_frame_interval = imx214_get_frame_interval, |
956 | }; |
957 | |
958 | static const struct v4l2_subdev_ops imx214_subdev_ops = { |
959 | .core = &imx214_core_ops, |
960 | .video = &imx214_video_ops, |
961 | .pad = &imx214_subdev_pad_ops, |
962 | }; |
963 | |
964 | static const struct v4l2_subdev_internal_ops imx214_internal_ops = { |
965 | .init_state = imx214_entity_init_state, |
966 | }; |
967 | |
968 | static const struct regmap_config sensor_regmap_config = { |
969 | .reg_bits = 16, |
970 | .val_bits = 8, |
971 | .cache_type = REGCACHE_MAPLE, |
972 | }; |
973 | |
974 | static int imx214_get_regulators(struct device *dev, struct imx214 *imx214) |
975 | { |
976 | unsigned int i; |
977 | |
978 | for (i = 0; i < IMX214_NUM_SUPPLIES; i++) |
979 | imx214->supplies[i].supply = imx214_supply_name[i]; |
980 | |
981 | return devm_regulator_bulk_get(dev, IMX214_NUM_SUPPLIES, |
982 | consumers: imx214->supplies); |
983 | } |
984 | |
985 | static int imx214_parse_fwnode(struct device *dev) |
986 | { |
987 | struct fwnode_handle *endpoint; |
988 | struct v4l2_fwnode_endpoint bus_cfg = { |
989 | .bus_type = V4L2_MBUS_CSI2_DPHY, |
990 | }; |
991 | unsigned int i; |
992 | int ret; |
993 | |
994 | endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL); |
995 | if (!endpoint) { |
996 | dev_err(dev, "endpoint node not found\n" ); |
997 | return -EINVAL; |
998 | } |
999 | |
1000 | ret = v4l2_fwnode_endpoint_alloc_parse(fwnode: endpoint, vep: &bus_cfg); |
1001 | if (ret) { |
1002 | dev_err(dev, "parsing endpoint node failed\n" ); |
1003 | goto done; |
1004 | } |
1005 | |
1006 | for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) |
1007 | if (bus_cfg.link_frequencies[i] == IMX214_DEFAULT_LINK_FREQ) |
1008 | break; |
1009 | |
1010 | if (i == bus_cfg.nr_of_link_frequencies) { |
1011 | dev_err(dev, "link-frequencies %d not supported, Please review your DT\n" , |
1012 | IMX214_DEFAULT_LINK_FREQ); |
1013 | ret = -EINVAL; |
1014 | goto done; |
1015 | } |
1016 | |
1017 | done: |
1018 | v4l2_fwnode_endpoint_free(vep: &bus_cfg); |
1019 | fwnode_handle_put(fwnode: endpoint); |
1020 | return ret; |
1021 | } |
1022 | |
1023 | static int imx214_probe(struct i2c_client *client) |
1024 | { |
1025 | struct device *dev = &client->dev; |
1026 | struct imx214 *imx214; |
1027 | int ret; |
1028 | |
1029 | ret = imx214_parse_fwnode(dev); |
1030 | if (ret) |
1031 | return ret; |
1032 | |
1033 | imx214 = devm_kzalloc(dev, size: sizeof(*imx214), GFP_KERNEL); |
1034 | if (!imx214) |
1035 | return -ENOMEM; |
1036 | |
1037 | imx214->dev = dev; |
1038 | |
1039 | imx214->xclk = devm_clk_get(dev, NULL); |
1040 | if (IS_ERR(ptr: imx214->xclk)) { |
1041 | dev_err(dev, "could not get xclk" ); |
1042 | return PTR_ERR(ptr: imx214->xclk); |
1043 | } |
1044 | |
1045 | ret = clk_set_rate(clk: imx214->xclk, IMX214_DEFAULT_CLK_FREQ); |
1046 | if (ret) { |
1047 | dev_err(dev, "could not set xclk frequency\n" ); |
1048 | return ret; |
1049 | } |
1050 | |
1051 | ret = imx214_get_regulators(dev, imx214); |
1052 | if (ret < 0) { |
1053 | dev_err(dev, "cannot get regulators\n" ); |
1054 | return ret; |
1055 | } |
1056 | |
1057 | imx214->enable_gpio = devm_gpiod_get(dev, con_id: "enable" , flags: GPIOD_OUT_LOW); |
1058 | if (IS_ERR(ptr: imx214->enable_gpio)) { |
1059 | dev_err(dev, "cannot get enable gpio\n" ); |
1060 | return PTR_ERR(ptr: imx214->enable_gpio); |
1061 | } |
1062 | |
1063 | imx214->regmap = devm_regmap_init_i2c(client, &sensor_regmap_config); |
1064 | if (IS_ERR(ptr: imx214->regmap)) { |
1065 | dev_err(dev, "regmap init failed\n" ); |
1066 | return PTR_ERR(ptr: imx214->regmap); |
1067 | } |
1068 | |
1069 | v4l2_i2c_subdev_init(sd: &imx214->sd, client, ops: &imx214_subdev_ops); |
1070 | imx214->sd.internal_ops = &imx214_internal_ops; |
1071 | |
1072 | /* |
1073 | * Enable power initially, to avoid warnings |
1074 | * from clk_disable on power_off |
1075 | */ |
1076 | imx214_power_on(dev: imx214->dev); |
1077 | |
1078 | pm_runtime_set_active(dev: imx214->dev); |
1079 | pm_runtime_enable(dev: imx214->dev); |
1080 | pm_runtime_idle(dev: imx214->dev); |
1081 | |
1082 | ret = imx214_ctrls_init(imx214); |
1083 | if (ret < 0) |
1084 | goto error_power_off; |
1085 | |
1086 | mutex_init(&imx214->mutex); |
1087 | imx214->ctrls.lock = &imx214->mutex; |
1088 | |
1089 | imx214->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
1090 | imx214->pad.flags = MEDIA_PAD_FL_SOURCE; |
1091 | imx214->sd.dev = &client->dev; |
1092 | imx214->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
1093 | |
1094 | ret = media_entity_pads_init(entity: &imx214->sd.entity, num_pads: 1, pads: &imx214->pad); |
1095 | if (ret < 0) { |
1096 | dev_err(dev, "could not register media entity\n" ); |
1097 | goto free_ctrl; |
1098 | } |
1099 | |
1100 | imx214_entity_init_state(subdev: &imx214->sd, NULL); |
1101 | |
1102 | ret = v4l2_async_register_subdev_sensor(sd: &imx214->sd); |
1103 | if (ret < 0) { |
1104 | dev_err(dev, "could not register v4l2 device\n" ); |
1105 | goto free_entity; |
1106 | } |
1107 | |
1108 | return 0; |
1109 | |
1110 | free_entity: |
1111 | media_entity_cleanup(entity: &imx214->sd.entity); |
1112 | free_ctrl: |
1113 | mutex_destroy(lock: &imx214->mutex); |
1114 | v4l2_ctrl_handler_free(hdl: &imx214->ctrls); |
1115 | error_power_off: |
1116 | pm_runtime_disable(dev: imx214->dev); |
1117 | |
1118 | return ret; |
1119 | } |
1120 | |
1121 | static void imx214_remove(struct i2c_client *client) |
1122 | { |
1123 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
1124 | struct imx214 *imx214 = to_imx214(sd); |
1125 | |
1126 | v4l2_async_unregister_subdev(sd: &imx214->sd); |
1127 | media_entity_cleanup(entity: &imx214->sd.entity); |
1128 | v4l2_ctrl_handler_free(hdl: &imx214->ctrls); |
1129 | |
1130 | pm_runtime_disable(dev: &client->dev); |
1131 | pm_runtime_set_suspended(dev: &client->dev); |
1132 | |
1133 | mutex_destroy(lock: &imx214->mutex); |
1134 | } |
1135 | |
1136 | static const struct of_device_id imx214_of_match[] = { |
1137 | { .compatible = "sony,imx214" }, |
1138 | { } |
1139 | }; |
1140 | MODULE_DEVICE_TABLE(of, imx214_of_match); |
1141 | |
1142 | static const struct dev_pm_ops imx214_pm_ops = { |
1143 | SET_RUNTIME_PM_OPS(imx214_power_off, imx214_power_on, NULL) |
1144 | }; |
1145 | |
1146 | static struct i2c_driver imx214_i2c_driver = { |
1147 | .driver = { |
1148 | .of_match_table = imx214_of_match, |
1149 | .pm = &imx214_pm_ops, |
1150 | .name = "imx214" , |
1151 | }, |
1152 | .probe = imx214_probe, |
1153 | .remove = imx214_remove, |
1154 | }; |
1155 | |
1156 | module_i2c_driver(imx214_i2c_driver); |
1157 | |
1158 | MODULE_DESCRIPTION("Sony IMX214 Camera driver" ); |
1159 | MODULE_AUTHOR("Ricardo Ribalda <ribalda@kernel.org>" ); |
1160 | MODULE_LICENSE("GPL v2" ); |
1161 | |