1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2019 Intel Corporation. |
3 | |
4 | #include <asm/unaligned.h> |
5 | #include <linux/acpi.h> |
6 | #include <linux/clk.h> |
7 | #include <linux/delay.h> |
8 | #include <linux/gpio/consumer.h> |
9 | #include <linux/i2c.h> |
10 | #include <linux/mod_devicetable.h> |
11 | #include <linux/module.h> |
12 | #include <linux/pm_runtime.h> |
13 | #include <linux/regulator/consumer.h> |
14 | #include <media/v4l2-ctrls.h> |
15 | #include <media/v4l2-device.h> |
16 | #include <media/v4l2-fwnode.h> |
17 | |
18 | #define OV5675_REG_VALUE_08BIT 1 |
19 | #define OV5675_REG_VALUE_16BIT 2 |
20 | #define OV5675_REG_VALUE_24BIT 3 |
21 | |
22 | #define OV5675_LINK_FREQ_450MHZ 450000000ULL |
23 | #define OV5675_SCLK 90000000LL |
24 | #define OV5675_XVCLK_19_2 19200000 |
25 | #define OV5675_DATA_LANES 2 |
26 | #define OV5675_RGB_DEPTH 10 |
27 | |
28 | #define OV5675_REG_CHIP_ID 0x300a |
29 | #define OV5675_CHIP_ID 0x5675 |
30 | |
31 | #define OV5675_REG_MODE_SELECT 0x0100 |
32 | #define OV5675_MODE_STANDBY 0x00 |
33 | #define OV5675_MODE_STREAMING 0x01 |
34 | |
35 | /* vertical-timings from sensor */ |
36 | #define OV5675_REG_VTS 0x380e |
37 | #define OV5675_VTS_30FPS 0x07e4 |
38 | #define OV5675_VTS_30FPS_MIN 0x07e4 |
39 | #define OV5675_VTS_MAX 0x7fff |
40 | |
41 | /* horizontal-timings from sensor */ |
42 | #define OV5675_REG_HTS 0x380c |
43 | |
44 | /* Exposure controls from sensor */ |
45 | #define OV5675_REG_EXPOSURE 0x3500 |
46 | #define OV5675_EXPOSURE_MIN 4 |
47 | #define OV5675_EXPOSURE_MAX_MARGIN 4 |
48 | #define OV5675_EXPOSURE_STEP 1 |
49 | |
50 | /* Analog gain controls from sensor */ |
51 | #define OV5675_REG_ANALOG_GAIN 0x3508 |
52 | #define OV5675_ANAL_GAIN_MIN 128 |
53 | #define OV5675_ANAL_GAIN_MAX 2047 |
54 | #define OV5675_ANAL_GAIN_STEP 1 |
55 | |
56 | /* Digital gain controls from sensor */ |
57 | #define OV5675_REG_DIGITAL_GAIN 0x350a |
58 | #define OV5675_REG_MWB_R_GAIN 0x5019 |
59 | #define OV5675_REG_MWB_G_GAIN 0x501b |
60 | #define OV5675_REG_MWB_B_GAIN 0x501d |
61 | #define OV5675_DGTL_GAIN_MIN 1024 |
62 | #define OV5675_DGTL_GAIN_MAX 4095 |
63 | #define OV5675_DGTL_GAIN_STEP 1 |
64 | #define OV5675_DGTL_GAIN_DEFAULT 1024 |
65 | |
66 | /* Group Access */ |
67 | #define OV5675_REG_GROUP_ACCESS 0x3208 |
68 | #define OV5675_GROUP_HOLD_START 0x0 |
69 | #define OV5675_GROUP_HOLD_END 0x10 |
70 | #define OV5675_GROUP_HOLD_LAUNCH 0xa0 |
71 | |
72 | /* Test Pattern Control */ |
73 | #define OV5675_REG_TEST_PATTERN 0x4503 |
74 | #define OV5675_TEST_PATTERN_ENABLE BIT(7) |
75 | #define OV5675_TEST_PATTERN_BAR_SHIFT 2 |
76 | |
77 | /* Flip Mirror Controls from sensor */ |
78 | #define OV5675_REG_FORMAT1 0x3820 |
79 | #define OV5675_REG_FORMAT2 0x373d |
80 | |
81 | #define to_ov5675(_sd) container_of(_sd, struct ov5675, sd) |
82 | |
83 | static const char * const ov5675_supply_names[] = { |
84 | "avdd" , /* Analog power */ |
85 | "dovdd" , /* Digital I/O power */ |
86 | "dvdd" , /* Digital core power */ |
87 | }; |
88 | |
89 | #define OV5675_NUM_SUPPLIES ARRAY_SIZE(ov5675_supply_names) |
90 | |
91 | enum { |
92 | OV5675_LINK_FREQ_900MBPS, |
93 | }; |
94 | |
95 | struct ov5675_reg { |
96 | u16 address; |
97 | u8 val; |
98 | }; |
99 | |
100 | struct ov5675_reg_list { |
101 | u32 num_of_regs; |
102 | const struct ov5675_reg *regs; |
103 | }; |
104 | |
105 | struct ov5675_link_freq_config { |
106 | const struct ov5675_reg_list reg_list; |
107 | }; |
108 | |
109 | struct ov5675_mode { |
110 | /* Frame width in pixels */ |
111 | u32 width; |
112 | |
113 | /* Frame height in pixels */ |
114 | u32 height; |
115 | |
116 | /* Horizontal timining size */ |
117 | u32 hts; |
118 | |
119 | /* Default vertical timining size */ |
120 | u32 vts_def; |
121 | |
122 | /* Min vertical timining size */ |
123 | u32 vts_min; |
124 | |
125 | /* Link frequency needed for this resolution */ |
126 | u32 link_freq_index; |
127 | |
128 | /* Sensor register settings for this resolution */ |
129 | const struct ov5675_reg_list reg_list; |
130 | }; |
131 | |
132 | static const struct ov5675_reg mipi_data_rate_900mbps[] = { |
133 | {0x0103, 0x01}, |
134 | {0x0100, 0x00}, |
135 | {0x0300, 0x04}, |
136 | {0x0302, 0x8d}, |
137 | {0x0303, 0x00}, |
138 | {0x030d, 0x26}, |
139 | }; |
140 | |
141 | static const struct ov5675_reg mode_2592x1944_regs[] = { |
142 | {0x3002, 0x21}, |
143 | {0x3107, 0x23}, |
144 | {0x3501, 0x20}, |
145 | {0x3503, 0x0c}, |
146 | {0x3508, 0x03}, |
147 | {0x3509, 0x00}, |
148 | {0x3600, 0x66}, |
149 | {0x3602, 0x30}, |
150 | {0x3610, 0xa5}, |
151 | {0x3612, 0x93}, |
152 | {0x3620, 0x80}, |
153 | {0x3642, 0x0e}, |
154 | {0x3661, 0x00}, |
155 | {0x3662, 0x10}, |
156 | {0x3664, 0xf3}, |
157 | {0x3665, 0x9e}, |
158 | {0x3667, 0xa5}, |
159 | {0x366e, 0x55}, |
160 | {0x366f, 0x55}, |
161 | {0x3670, 0x11}, |
162 | {0x3671, 0x11}, |
163 | {0x3672, 0x11}, |
164 | {0x3673, 0x11}, |
165 | {0x3714, 0x24}, |
166 | {0x371a, 0x3e}, |
167 | {0x3733, 0x10}, |
168 | {0x3734, 0x00}, |
169 | {0x373d, 0x24}, |
170 | {0x3764, 0x20}, |
171 | {0x3765, 0x20}, |
172 | {0x3766, 0x12}, |
173 | {0x37a1, 0x14}, |
174 | {0x37a8, 0x1c}, |
175 | {0x37ab, 0x0f}, |
176 | {0x37c2, 0x04}, |
177 | {0x37cb, 0x00}, |
178 | {0x37cc, 0x00}, |
179 | {0x37cd, 0x00}, |
180 | {0x37ce, 0x00}, |
181 | {0x37d8, 0x02}, |
182 | {0x37d9, 0x08}, |
183 | {0x37dc, 0x04}, |
184 | {0x3800, 0x00}, |
185 | {0x3801, 0x00}, |
186 | {0x3802, 0x00}, |
187 | {0x3803, 0x04}, |
188 | {0x3804, 0x0a}, |
189 | {0x3805, 0x3f}, |
190 | {0x3806, 0x07}, |
191 | {0x3807, 0xb3}, |
192 | {0x3808, 0x0a}, |
193 | {0x3809, 0x20}, |
194 | {0x380a, 0x07}, |
195 | {0x380b, 0x98}, |
196 | {0x380c, 0x02}, |
197 | {0x380d, 0xee}, |
198 | {0x380e, 0x07}, |
199 | {0x380f, 0xe4}, |
200 | {0x3811, 0x10}, |
201 | {0x3813, 0x0d}, |
202 | {0x3814, 0x01}, |
203 | {0x3815, 0x01}, |
204 | {0x3816, 0x01}, |
205 | {0x3817, 0x01}, |
206 | {0x381e, 0x02}, |
207 | {0x3820, 0x88}, |
208 | {0x3821, 0x01}, |
209 | {0x3832, 0x04}, |
210 | {0x3c80, 0x01}, |
211 | {0x3c82, 0x00}, |
212 | {0x3c83, 0xc8}, |
213 | {0x3c8c, 0x0f}, |
214 | {0x3c8d, 0xa0}, |
215 | {0x3c90, 0x07}, |
216 | {0x3c91, 0x00}, |
217 | {0x3c92, 0x00}, |
218 | {0x3c93, 0x00}, |
219 | {0x3c94, 0xd0}, |
220 | {0x3c95, 0x50}, |
221 | {0x3c96, 0x35}, |
222 | {0x3c97, 0x00}, |
223 | {0x4001, 0xe0}, |
224 | {0x4008, 0x02}, |
225 | {0x4009, 0x0d}, |
226 | {0x400f, 0x80}, |
227 | {0x4013, 0x02}, |
228 | {0x4040, 0x00}, |
229 | {0x4041, 0x07}, |
230 | {0x404c, 0x50}, |
231 | {0x404e, 0x20}, |
232 | {0x4500, 0x06}, |
233 | {0x4503, 0x00}, |
234 | {0x450a, 0x04}, |
235 | {0x4809, 0x04}, |
236 | {0x480c, 0x12}, |
237 | {0x4819, 0x70}, |
238 | {0x4825, 0x32}, |
239 | {0x4826, 0x32}, |
240 | {0x482a, 0x06}, |
241 | {0x4833, 0x08}, |
242 | {0x4837, 0x0d}, |
243 | {0x5000, 0x77}, |
244 | {0x5b00, 0x01}, |
245 | {0x5b01, 0x10}, |
246 | {0x5b02, 0x01}, |
247 | {0x5b03, 0xdb}, |
248 | {0x5b05, 0x6c}, |
249 | {0x5e10, 0xfc}, |
250 | {0x3500, 0x00}, |
251 | {0x3501, 0x3E}, |
252 | {0x3502, 0x60}, |
253 | {0x3503, 0x08}, |
254 | {0x3508, 0x04}, |
255 | {0x3509, 0x00}, |
256 | {0x3832, 0x48}, |
257 | {0x5780, 0x3e}, |
258 | {0x5781, 0x0f}, |
259 | {0x5782, 0x44}, |
260 | {0x5783, 0x02}, |
261 | {0x5784, 0x01}, |
262 | {0x5785, 0x01}, |
263 | {0x5786, 0x00}, |
264 | {0x5787, 0x04}, |
265 | {0x5788, 0x02}, |
266 | {0x5789, 0x0f}, |
267 | {0x578a, 0xfd}, |
268 | {0x578b, 0xf5}, |
269 | {0x578c, 0xf5}, |
270 | {0x578d, 0x03}, |
271 | {0x578e, 0x08}, |
272 | {0x578f, 0x0c}, |
273 | {0x5790, 0x08}, |
274 | {0x5791, 0x06}, |
275 | {0x5792, 0x00}, |
276 | {0x5793, 0x52}, |
277 | {0x5794, 0xa3}, |
278 | {0x4003, 0x40}, |
279 | {0x3107, 0x01}, |
280 | {0x3c80, 0x08}, |
281 | {0x3c83, 0xb1}, |
282 | {0x3c8c, 0x10}, |
283 | {0x3c8d, 0x00}, |
284 | {0x3c90, 0x00}, |
285 | {0x3c94, 0x00}, |
286 | {0x3c95, 0x00}, |
287 | {0x3c96, 0x00}, |
288 | {0x37cb, 0x09}, |
289 | {0x37cc, 0x15}, |
290 | {0x37cd, 0x1f}, |
291 | {0x37ce, 0x1f}, |
292 | }; |
293 | |
294 | static const struct ov5675_reg mode_1296x972_regs[] = { |
295 | {0x3002, 0x21}, |
296 | {0x3107, 0x23}, |
297 | {0x3501, 0x20}, |
298 | {0x3503, 0x0c}, |
299 | {0x3508, 0x03}, |
300 | {0x3509, 0x00}, |
301 | {0x3600, 0x66}, |
302 | {0x3602, 0x30}, |
303 | {0x3610, 0xa5}, |
304 | {0x3612, 0x93}, |
305 | {0x3620, 0x80}, |
306 | {0x3642, 0x0e}, |
307 | {0x3661, 0x00}, |
308 | {0x3662, 0x08}, |
309 | {0x3664, 0xf3}, |
310 | {0x3665, 0x9e}, |
311 | {0x3667, 0xa5}, |
312 | {0x366e, 0x55}, |
313 | {0x366f, 0x55}, |
314 | {0x3670, 0x11}, |
315 | {0x3671, 0x11}, |
316 | {0x3672, 0x11}, |
317 | {0x3673, 0x11}, |
318 | {0x3714, 0x28}, |
319 | {0x371a, 0x3e}, |
320 | {0x3733, 0x10}, |
321 | {0x3734, 0x00}, |
322 | {0x373d, 0x24}, |
323 | {0x3764, 0x20}, |
324 | {0x3765, 0x20}, |
325 | {0x3766, 0x12}, |
326 | {0x37a1, 0x14}, |
327 | {0x37a8, 0x1c}, |
328 | {0x37ab, 0x0f}, |
329 | {0x37c2, 0x14}, |
330 | {0x37cb, 0x00}, |
331 | {0x37cc, 0x00}, |
332 | {0x37cd, 0x00}, |
333 | {0x37ce, 0x00}, |
334 | {0x37d8, 0x02}, |
335 | {0x37d9, 0x04}, |
336 | {0x37dc, 0x04}, |
337 | {0x3800, 0x00}, |
338 | {0x3801, 0x00}, |
339 | {0x3802, 0x00}, |
340 | {0x3803, 0x00}, |
341 | {0x3804, 0x0a}, |
342 | {0x3805, 0x3f}, |
343 | {0x3806, 0x07}, |
344 | {0x3807, 0xb7}, |
345 | {0x3808, 0x05}, |
346 | {0x3809, 0x10}, |
347 | {0x380a, 0x03}, |
348 | {0x380b, 0xcc}, |
349 | {0x380c, 0x02}, |
350 | {0x380d, 0xee}, |
351 | {0x380e, 0x07}, |
352 | {0x380f, 0xd0}, |
353 | {0x3811, 0x08}, |
354 | {0x3813, 0x0d}, |
355 | {0x3814, 0x03}, |
356 | {0x3815, 0x01}, |
357 | {0x3816, 0x03}, |
358 | {0x3817, 0x01}, |
359 | {0x381e, 0x02}, |
360 | {0x3820, 0x8b}, |
361 | {0x3821, 0x01}, |
362 | {0x3832, 0x04}, |
363 | {0x3c80, 0x01}, |
364 | {0x3c82, 0x00}, |
365 | {0x3c83, 0xc8}, |
366 | {0x3c8c, 0x0f}, |
367 | {0x3c8d, 0xa0}, |
368 | {0x3c90, 0x07}, |
369 | {0x3c91, 0x00}, |
370 | {0x3c92, 0x00}, |
371 | {0x3c93, 0x00}, |
372 | {0x3c94, 0xd0}, |
373 | {0x3c95, 0x50}, |
374 | {0x3c96, 0x35}, |
375 | {0x3c97, 0x00}, |
376 | {0x4001, 0xe0}, |
377 | {0x4008, 0x00}, |
378 | {0x4009, 0x07}, |
379 | {0x400f, 0x80}, |
380 | {0x4013, 0x02}, |
381 | {0x4040, 0x00}, |
382 | {0x4041, 0x03}, |
383 | {0x404c, 0x50}, |
384 | {0x404e, 0x20}, |
385 | {0x4500, 0x06}, |
386 | {0x4503, 0x00}, |
387 | {0x450a, 0x04}, |
388 | {0x4809, 0x04}, |
389 | {0x480c, 0x12}, |
390 | {0x4819, 0x70}, |
391 | {0x4825, 0x32}, |
392 | {0x4826, 0x32}, |
393 | {0x482a, 0x06}, |
394 | {0x4833, 0x08}, |
395 | {0x4837, 0x0d}, |
396 | {0x5000, 0x77}, |
397 | {0x5b00, 0x01}, |
398 | {0x5b01, 0x10}, |
399 | {0x5b02, 0x01}, |
400 | {0x5b03, 0xdb}, |
401 | {0x5b05, 0x6c}, |
402 | {0x5e10, 0xfc}, |
403 | {0x3500, 0x00}, |
404 | {0x3501, 0x1F}, |
405 | {0x3502, 0x20}, |
406 | {0x3503, 0x08}, |
407 | {0x3508, 0x04}, |
408 | {0x3509, 0x00}, |
409 | {0x3832, 0x48}, |
410 | {0x5780, 0x3e}, |
411 | {0x5781, 0x0f}, |
412 | {0x5782, 0x44}, |
413 | {0x5783, 0x02}, |
414 | {0x5784, 0x01}, |
415 | {0x5785, 0x01}, |
416 | {0x5786, 0x00}, |
417 | {0x5787, 0x04}, |
418 | {0x5788, 0x02}, |
419 | {0x5789, 0x0f}, |
420 | {0x578a, 0xfd}, |
421 | {0x578b, 0xf5}, |
422 | {0x578c, 0xf5}, |
423 | {0x578d, 0x03}, |
424 | {0x578e, 0x08}, |
425 | {0x578f, 0x0c}, |
426 | {0x5790, 0x08}, |
427 | {0x5791, 0x06}, |
428 | {0x5792, 0x00}, |
429 | {0x5793, 0x52}, |
430 | {0x5794, 0xa3}, |
431 | {0x4003, 0x40}, |
432 | {0x3107, 0x01}, |
433 | {0x3c80, 0x08}, |
434 | {0x3c83, 0xb1}, |
435 | {0x3c8c, 0x10}, |
436 | {0x3c8d, 0x00}, |
437 | {0x3c90, 0x00}, |
438 | {0x3c94, 0x00}, |
439 | {0x3c95, 0x00}, |
440 | {0x3c96, 0x00}, |
441 | {0x37cb, 0x09}, |
442 | {0x37cc, 0x15}, |
443 | {0x37cd, 0x1f}, |
444 | {0x37ce, 0x1f}, |
445 | }; |
446 | |
447 | static const char * const [] = { |
448 | "Disabled" , |
449 | "Standard Color Bar" , |
450 | "Top-Bottom Darker Color Bar" , |
451 | "Right-Left Darker Color Bar" , |
452 | "Bottom-Top Darker Color Bar" |
453 | }; |
454 | |
455 | static const s64 [] = { |
456 | OV5675_LINK_FREQ_450MHZ, |
457 | }; |
458 | |
459 | static const struct ov5675_link_freq_config link_freq_configs[] = { |
460 | [OV5675_LINK_FREQ_900MBPS] = { |
461 | .reg_list = { |
462 | .num_of_regs = ARRAY_SIZE(mipi_data_rate_900mbps), |
463 | .regs = mipi_data_rate_900mbps, |
464 | } |
465 | } |
466 | }; |
467 | |
468 | static const struct ov5675_mode supported_modes[] = { |
469 | { |
470 | .width = 2592, |
471 | .height = 1944, |
472 | .hts = 1500, |
473 | .vts_def = OV5675_VTS_30FPS, |
474 | .vts_min = OV5675_VTS_30FPS_MIN, |
475 | .reg_list = { |
476 | .num_of_regs = ARRAY_SIZE(mode_2592x1944_regs), |
477 | .regs = mode_2592x1944_regs, |
478 | }, |
479 | .link_freq_index = OV5675_LINK_FREQ_900MBPS, |
480 | }, |
481 | { |
482 | .width = 1296, |
483 | .height = 972, |
484 | .hts = 1500, |
485 | .vts_def = OV5675_VTS_30FPS, |
486 | .vts_min = OV5675_VTS_30FPS_MIN, |
487 | .reg_list = { |
488 | .num_of_regs = ARRAY_SIZE(mode_1296x972_regs), |
489 | .regs = mode_1296x972_regs, |
490 | }, |
491 | .link_freq_index = OV5675_LINK_FREQ_900MBPS, |
492 | } |
493 | }; |
494 | |
495 | struct ov5675 { |
496 | struct v4l2_subdev sd; |
497 | struct media_pad pad; |
498 | struct v4l2_ctrl_handler ctrl_handler; |
499 | struct clk *xvclk; |
500 | struct gpio_desc *reset_gpio; |
501 | struct regulator_bulk_data supplies[OV5675_NUM_SUPPLIES]; |
502 | |
503 | /* V4L2 Controls */ |
504 | struct v4l2_ctrl *link_freq; |
505 | struct v4l2_ctrl *pixel_rate; |
506 | struct v4l2_ctrl *vblank; |
507 | struct v4l2_ctrl *hblank; |
508 | struct v4l2_ctrl *exposure; |
509 | |
510 | /* Current mode */ |
511 | const struct ov5675_mode *cur_mode; |
512 | |
513 | /* To serialize asynchronus callbacks */ |
514 | struct mutex mutex; |
515 | |
516 | /* True if the device has been identified */ |
517 | bool identified; |
518 | }; |
519 | |
520 | static u64 to_pixel_rate(u32 f_index) |
521 | { |
522 | u64 pixel_rate = link_freq_menu_items[f_index] * 2 * OV5675_DATA_LANES; |
523 | |
524 | do_div(pixel_rate, OV5675_RGB_DEPTH); |
525 | |
526 | return pixel_rate; |
527 | } |
528 | |
529 | static u64 to_pixels_per_line(u32 hts, u32 f_index) |
530 | { |
531 | u64 ppl = hts * to_pixel_rate(f_index); |
532 | |
533 | do_div(ppl, OV5675_SCLK); |
534 | |
535 | return ppl; |
536 | } |
537 | |
538 | static int ov5675_read_reg(struct ov5675 *ov5675, u16 reg, u16 len, u32 *val) |
539 | { |
540 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov5675->sd); |
541 | struct i2c_msg msgs[2]; |
542 | u8 addr_buf[2]; |
543 | u8 data_buf[4] = {0}; |
544 | int ret; |
545 | |
546 | if (len > 4) |
547 | return -EINVAL; |
548 | |
549 | put_unaligned_be16(val: reg, p: addr_buf); |
550 | msgs[0].addr = client->addr; |
551 | msgs[0].flags = 0; |
552 | msgs[0].len = sizeof(addr_buf); |
553 | msgs[0].buf = addr_buf; |
554 | msgs[1].addr = client->addr; |
555 | msgs[1].flags = I2C_M_RD; |
556 | msgs[1].len = len; |
557 | msgs[1].buf = &data_buf[4 - len]; |
558 | |
559 | ret = i2c_transfer(adap: client->adapter, msgs, ARRAY_SIZE(msgs)); |
560 | if (ret != ARRAY_SIZE(msgs)) |
561 | return -EIO; |
562 | |
563 | *val = get_unaligned_be32(p: data_buf); |
564 | |
565 | return 0; |
566 | } |
567 | |
568 | static int ov5675_write_reg(struct ov5675 *ov5675, u16 reg, u16 len, u32 val) |
569 | { |
570 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov5675->sd); |
571 | u8 buf[6]; |
572 | |
573 | if (len > 4) |
574 | return -EINVAL; |
575 | |
576 | put_unaligned_be16(val: reg, p: buf); |
577 | put_unaligned_be32(val: val << 8 * (4 - len), p: buf + 2); |
578 | if (i2c_master_send(client, buf, count: len + 2) != len + 2) |
579 | return -EIO; |
580 | |
581 | return 0; |
582 | } |
583 | |
584 | static int ov5675_write_reg_list(struct ov5675 *ov5675, |
585 | const struct ov5675_reg_list *r_list) |
586 | { |
587 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov5675->sd); |
588 | unsigned int i; |
589 | int ret; |
590 | |
591 | for (i = 0; i < r_list->num_of_regs; i++) { |
592 | ret = ov5675_write_reg(ov5675, reg: r_list->regs[i].address, len: 1, |
593 | val: r_list->regs[i].val); |
594 | if (ret) { |
595 | dev_err_ratelimited(&client->dev, |
596 | "failed to write reg 0x%4.4x. error = %d" , |
597 | r_list->regs[i].address, ret); |
598 | return ret; |
599 | } |
600 | } |
601 | |
602 | return 0; |
603 | } |
604 | |
605 | static int ov5675_update_digital_gain(struct ov5675 *ov5675, u32 d_gain) |
606 | { |
607 | int ret; |
608 | |
609 | ret = ov5675_write_reg(ov5675, OV5675_REG_GROUP_ACCESS, |
610 | OV5675_REG_VALUE_08BIT, |
611 | OV5675_GROUP_HOLD_START); |
612 | if (ret) |
613 | return ret; |
614 | |
615 | ret = ov5675_write_reg(ov5675, OV5675_REG_MWB_R_GAIN, |
616 | OV5675_REG_VALUE_16BIT, val: d_gain); |
617 | if (ret) |
618 | return ret; |
619 | |
620 | ret = ov5675_write_reg(ov5675, OV5675_REG_MWB_G_GAIN, |
621 | OV5675_REG_VALUE_16BIT, val: d_gain); |
622 | if (ret) |
623 | return ret; |
624 | |
625 | ret = ov5675_write_reg(ov5675, OV5675_REG_MWB_B_GAIN, |
626 | OV5675_REG_VALUE_16BIT, val: d_gain); |
627 | if (ret) |
628 | return ret; |
629 | |
630 | ret = ov5675_write_reg(ov5675, OV5675_REG_GROUP_ACCESS, |
631 | OV5675_REG_VALUE_08BIT, |
632 | OV5675_GROUP_HOLD_END); |
633 | if (ret) |
634 | return ret; |
635 | |
636 | ret = ov5675_write_reg(ov5675, OV5675_REG_GROUP_ACCESS, |
637 | OV5675_REG_VALUE_08BIT, |
638 | OV5675_GROUP_HOLD_LAUNCH); |
639 | return ret; |
640 | } |
641 | |
642 | static int ov5675_test_pattern(struct ov5675 *ov5675, u32 pattern) |
643 | { |
644 | if (pattern) |
645 | pattern = (pattern - 1) << OV5675_TEST_PATTERN_BAR_SHIFT | |
646 | OV5675_TEST_PATTERN_ENABLE; |
647 | |
648 | return ov5675_write_reg(ov5675, OV5675_REG_TEST_PATTERN, |
649 | OV5675_REG_VALUE_08BIT, val: pattern); |
650 | } |
651 | |
652 | /* |
653 | * OV5675 supports keeping the pixel order by mirror and flip function |
654 | * The Bayer order isn't affected by the flip controls |
655 | */ |
656 | static int ov5675_set_ctrl_hflip(struct ov5675 *ov5675, u32 ctrl_val) |
657 | { |
658 | int ret; |
659 | u32 val; |
660 | |
661 | ret = ov5675_read_reg(ov5675, OV5675_REG_FORMAT1, |
662 | OV5675_REG_VALUE_08BIT, val: &val); |
663 | if (ret) |
664 | return ret; |
665 | |
666 | return ov5675_write_reg(ov5675, OV5675_REG_FORMAT1, |
667 | OV5675_REG_VALUE_08BIT, |
668 | val: ctrl_val ? val & ~BIT(3) : val | BIT(3)); |
669 | } |
670 | |
671 | static int ov5675_set_ctrl_vflip(struct ov5675 *ov5675, u8 ctrl_val) |
672 | { |
673 | int ret; |
674 | u32 val; |
675 | |
676 | ret = ov5675_read_reg(ov5675, OV5675_REG_FORMAT1, |
677 | OV5675_REG_VALUE_08BIT, val: &val); |
678 | if (ret) |
679 | return ret; |
680 | |
681 | ret = ov5675_write_reg(ov5675, OV5675_REG_FORMAT1, |
682 | OV5675_REG_VALUE_08BIT, |
683 | val: ctrl_val ? val | BIT(4) | BIT(5) : val & ~BIT(4) & ~BIT(5)); |
684 | |
685 | if (ret) |
686 | return ret; |
687 | |
688 | ret = ov5675_read_reg(ov5675, OV5675_REG_FORMAT2, |
689 | OV5675_REG_VALUE_08BIT, val: &val); |
690 | |
691 | if (ret) |
692 | return ret; |
693 | |
694 | return ov5675_write_reg(ov5675, OV5675_REG_FORMAT2, |
695 | OV5675_REG_VALUE_08BIT, |
696 | val: ctrl_val ? val | BIT(1) : val & ~BIT(1)); |
697 | } |
698 | |
699 | static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl) |
700 | { |
701 | struct ov5675 *ov5675 = container_of(ctrl->handler, |
702 | struct ov5675, ctrl_handler); |
703 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov5675->sd); |
704 | s64 exposure_max; |
705 | int ret = 0; |
706 | |
707 | /* Propagate change of current control to all related controls */ |
708 | if (ctrl->id == V4L2_CID_VBLANK) { |
709 | /* Update max exposure while meeting expected vblanking */ |
710 | exposure_max = ov5675->cur_mode->height + ctrl->val - |
711 | OV5675_EXPOSURE_MAX_MARGIN; |
712 | __v4l2_ctrl_modify_range(ctrl: ov5675->exposure, |
713 | min: ov5675->exposure->minimum, |
714 | max: exposure_max, step: ov5675->exposure->step, |
715 | def: exposure_max); |
716 | } |
717 | |
718 | /* V4L2 controls values will be applied only when power is already up */ |
719 | if (!pm_runtime_get_if_in_use(dev: &client->dev)) |
720 | return 0; |
721 | |
722 | switch (ctrl->id) { |
723 | case V4L2_CID_ANALOGUE_GAIN: |
724 | ret = ov5675_write_reg(ov5675, OV5675_REG_ANALOG_GAIN, |
725 | OV5675_REG_VALUE_16BIT, val: ctrl->val); |
726 | break; |
727 | |
728 | case V4L2_CID_DIGITAL_GAIN: |
729 | ret = ov5675_update_digital_gain(ov5675, d_gain: ctrl->val); |
730 | break; |
731 | |
732 | case V4L2_CID_EXPOSURE: |
733 | /* 4 least significant bits of expsoure are fractional part |
734 | * val = val << 4 |
735 | * for ov5675, the unit of exposure is differnt from other |
736 | * OmniVision sensors, its exposure value is twice of the |
737 | * register value, the exposure should be divided by 2 before |
738 | * set register, e.g. val << 3. |
739 | */ |
740 | ret = ov5675_write_reg(ov5675, OV5675_REG_EXPOSURE, |
741 | OV5675_REG_VALUE_24BIT, val: ctrl->val << 3); |
742 | break; |
743 | |
744 | case V4L2_CID_VBLANK: |
745 | ret = ov5675_write_reg(ov5675, OV5675_REG_VTS, |
746 | OV5675_REG_VALUE_16BIT, |
747 | val: ov5675->cur_mode->height + ctrl->val + |
748 | 10); |
749 | break; |
750 | |
751 | case V4L2_CID_TEST_PATTERN: |
752 | ret = ov5675_test_pattern(ov5675, pattern: ctrl->val); |
753 | break; |
754 | |
755 | case V4L2_CID_HFLIP: |
756 | ov5675_set_ctrl_hflip(ov5675, ctrl_val: ctrl->val); |
757 | break; |
758 | |
759 | case V4L2_CID_VFLIP: |
760 | ov5675_set_ctrl_vflip(ov5675, ctrl_val: ctrl->val); |
761 | break; |
762 | |
763 | default: |
764 | ret = -EINVAL; |
765 | break; |
766 | } |
767 | |
768 | pm_runtime_put(dev: &client->dev); |
769 | |
770 | return ret; |
771 | } |
772 | |
773 | static const struct v4l2_ctrl_ops ov5675_ctrl_ops = { |
774 | .s_ctrl = ov5675_set_ctrl, |
775 | }; |
776 | |
777 | static int ov5675_init_controls(struct ov5675 *ov5675) |
778 | { |
779 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov5675->sd); |
780 | struct v4l2_fwnode_device_properties props; |
781 | struct v4l2_ctrl_handler *ctrl_hdlr; |
782 | s64 exposure_max, h_blank; |
783 | int ret; |
784 | |
785 | ctrl_hdlr = &ov5675->ctrl_handler; |
786 | ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10); |
787 | if (ret) |
788 | return ret; |
789 | |
790 | ctrl_hdlr->lock = &ov5675->mutex; |
791 | ov5675->link_freq = v4l2_ctrl_new_int_menu(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, |
792 | V4L2_CID_LINK_FREQ, |
793 | ARRAY_SIZE(link_freq_menu_items) - 1, |
794 | def: 0, qmenu_int: link_freq_menu_items); |
795 | if (ov5675->link_freq) |
796 | ov5675->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
797 | |
798 | ov5675->pixel_rate = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, |
799 | V4L2_CID_PIXEL_RATE, min: 0, |
800 | max: to_pixel_rate(f_index: OV5675_LINK_FREQ_900MBPS), |
801 | step: 1, |
802 | def: to_pixel_rate(f_index: OV5675_LINK_FREQ_900MBPS)); |
803 | ov5675->vblank = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, |
804 | V4L2_CID_VBLANK, |
805 | min: ov5675->cur_mode->vts_min - ov5675->cur_mode->height, |
806 | OV5675_VTS_MAX - ov5675->cur_mode->height, step: 1, |
807 | def: ov5675->cur_mode->vts_def - ov5675->cur_mode->height); |
808 | h_blank = to_pixels_per_line(hts: ov5675->cur_mode->hts, |
809 | f_index: ov5675->cur_mode->link_freq_index) - ov5675->cur_mode->width; |
810 | ov5675->hblank = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, |
811 | V4L2_CID_HBLANK, min: h_blank, max: h_blank, step: 1, |
812 | def: h_blank); |
813 | if (ov5675->hblank) |
814 | ov5675->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
815 | |
816 | v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, |
817 | OV5675_ANAL_GAIN_MIN, OV5675_ANAL_GAIN_MAX, |
818 | OV5675_ANAL_GAIN_STEP, OV5675_ANAL_GAIN_MIN); |
819 | v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, V4L2_CID_DIGITAL_GAIN, |
820 | OV5675_DGTL_GAIN_MIN, OV5675_DGTL_GAIN_MAX, |
821 | OV5675_DGTL_GAIN_STEP, OV5675_DGTL_GAIN_DEFAULT); |
822 | exposure_max = (ov5675->cur_mode->vts_def - OV5675_EXPOSURE_MAX_MARGIN); |
823 | ov5675->exposure = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, |
824 | V4L2_CID_EXPOSURE, |
825 | OV5675_EXPOSURE_MIN, max: exposure_max, |
826 | OV5675_EXPOSURE_STEP, |
827 | def: exposure_max); |
828 | v4l2_ctrl_new_std_menu_items(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, |
829 | V4L2_CID_TEST_PATTERN, |
830 | ARRAY_SIZE(ov5675_test_pattern_menu) - 1, |
831 | mask: 0, def: 0, qmenu: ov5675_test_pattern_menu); |
832 | v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, |
833 | V4L2_CID_HFLIP, min: 0, max: 1, step: 1, def: 0); |
834 | v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov5675_ctrl_ops, |
835 | V4L2_CID_VFLIP, min: 0, max: 1, step: 1, def: 0); |
836 | |
837 | if (ctrl_hdlr->error) { |
838 | v4l2_ctrl_handler_free(hdl: ctrl_hdlr); |
839 | return ctrl_hdlr->error; |
840 | } |
841 | |
842 | ret = v4l2_fwnode_device_parse(dev: &client->dev, props: &props); |
843 | if (ret) |
844 | goto error; |
845 | |
846 | ret = v4l2_ctrl_new_fwnode_properties(hdl: ctrl_hdlr, ctrl_ops: &ov5675_ctrl_ops, |
847 | p: &props); |
848 | if (ret) |
849 | goto error; |
850 | |
851 | ov5675->sd.ctrl_handler = ctrl_hdlr; |
852 | |
853 | return 0; |
854 | |
855 | error: |
856 | v4l2_ctrl_handler_free(hdl: ctrl_hdlr); |
857 | |
858 | return ret; |
859 | } |
860 | |
861 | static void ov5675_update_pad_format(const struct ov5675_mode *mode, |
862 | struct v4l2_mbus_framefmt *fmt) |
863 | { |
864 | fmt->width = mode->width; |
865 | fmt->height = mode->height; |
866 | fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; |
867 | fmt->field = V4L2_FIELD_NONE; |
868 | } |
869 | |
870 | static int ov5675_identify_module(struct ov5675 *ov5675) |
871 | { |
872 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov5675->sd); |
873 | int ret; |
874 | u32 val; |
875 | |
876 | if (ov5675->identified) |
877 | return 0; |
878 | |
879 | ret = ov5675_read_reg(ov5675, OV5675_REG_CHIP_ID, |
880 | OV5675_REG_VALUE_24BIT, val: &val); |
881 | if (ret) |
882 | return ret; |
883 | |
884 | if (val != OV5675_CHIP_ID) { |
885 | dev_err(&client->dev, "chip id mismatch: %x!=%x" , |
886 | OV5675_CHIP_ID, val); |
887 | return -ENXIO; |
888 | } |
889 | |
890 | ov5675->identified = true; |
891 | |
892 | return 0; |
893 | } |
894 | |
895 | static int ov5675_start_streaming(struct ov5675 *ov5675) |
896 | { |
897 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov5675->sd); |
898 | const struct ov5675_reg_list *reg_list; |
899 | int link_freq_index, ret; |
900 | |
901 | ret = ov5675_identify_module(ov5675); |
902 | if (ret) |
903 | return ret; |
904 | |
905 | link_freq_index = ov5675->cur_mode->link_freq_index; |
906 | reg_list = &link_freq_configs[link_freq_index].reg_list; |
907 | ret = ov5675_write_reg_list(ov5675, r_list: reg_list); |
908 | if (ret) { |
909 | dev_err(&client->dev, "failed to set plls" ); |
910 | return ret; |
911 | } |
912 | |
913 | reg_list = &ov5675->cur_mode->reg_list; |
914 | ret = ov5675_write_reg_list(ov5675, r_list: reg_list); |
915 | if (ret) { |
916 | dev_err(&client->dev, "failed to set mode" ); |
917 | return ret; |
918 | } |
919 | |
920 | ret = __v4l2_ctrl_handler_setup(hdl: ov5675->sd.ctrl_handler); |
921 | if (ret) |
922 | return ret; |
923 | |
924 | ret = ov5675_write_reg(ov5675, OV5675_REG_MODE_SELECT, |
925 | OV5675_REG_VALUE_08BIT, OV5675_MODE_STREAMING); |
926 | if (ret) { |
927 | dev_err(&client->dev, "failed to set stream" ); |
928 | return ret; |
929 | } |
930 | |
931 | return 0; |
932 | } |
933 | |
934 | static void ov5675_stop_streaming(struct ov5675 *ov5675) |
935 | { |
936 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov5675->sd); |
937 | |
938 | if (ov5675_write_reg(ov5675, OV5675_REG_MODE_SELECT, |
939 | OV5675_REG_VALUE_08BIT, OV5675_MODE_STANDBY)) |
940 | dev_err(&client->dev, "failed to set stream" ); |
941 | } |
942 | |
943 | static int ov5675_set_stream(struct v4l2_subdev *sd, int enable) |
944 | { |
945 | struct ov5675 *ov5675 = to_ov5675(sd); |
946 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
947 | int ret = 0; |
948 | |
949 | mutex_lock(&ov5675->mutex); |
950 | if (enable) { |
951 | ret = pm_runtime_resume_and_get(dev: &client->dev); |
952 | if (ret < 0) { |
953 | mutex_unlock(lock: &ov5675->mutex); |
954 | return ret; |
955 | } |
956 | |
957 | ret = ov5675_start_streaming(ov5675); |
958 | if (ret) { |
959 | enable = 0; |
960 | ov5675_stop_streaming(ov5675); |
961 | pm_runtime_put(dev: &client->dev); |
962 | } |
963 | } else { |
964 | ov5675_stop_streaming(ov5675); |
965 | pm_runtime_put(dev: &client->dev); |
966 | } |
967 | |
968 | mutex_unlock(lock: &ov5675->mutex); |
969 | |
970 | return ret; |
971 | } |
972 | |
973 | static int ov5675_power_off(struct device *dev) |
974 | { |
975 | /* 512 xvclk cycles after the last SCCB transation or MIPI frame end */ |
976 | u32 delay_us = DIV_ROUND_UP(512, OV5675_XVCLK_19_2 / 1000 / 1000); |
977 | struct v4l2_subdev *sd = dev_get_drvdata(dev); |
978 | struct ov5675 *ov5675 = to_ov5675(sd); |
979 | |
980 | usleep_range(min: delay_us, max: delay_us * 2); |
981 | |
982 | clk_disable_unprepare(clk: ov5675->xvclk); |
983 | gpiod_set_value_cansleep(desc: ov5675->reset_gpio, value: 1); |
984 | regulator_bulk_disable(OV5675_NUM_SUPPLIES, consumers: ov5675->supplies); |
985 | |
986 | return 0; |
987 | } |
988 | |
989 | static int ov5675_power_on(struct device *dev) |
990 | { |
991 | u32 delay_us = DIV_ROUND_UP(8192, OV5675_XVCLK_19_2 / 1000 / 1000); |
992 | struct v4l2_subdev *sd = dev_get_drvdata(dev); |
993 | struct ov5675 *ov5675 = to_ov5675(sd); |
994 | int ret; |
995 | |
996 | ret = clk_prepare_enable(clk: ov5675->xvclk); |
997 | if (ret < 0) { |
998 | dev_err(dev, "failed to enable xvclk: %d\n" , ret); |
999 | return ret; |
1000 | } |
1001 | |
1002 | gpiod_set_value_cansleep(desc: ov5675->reset_gpio, value: 1); |
1003 | |
1004 | ret = regulator_bulk_enable(OV5675_NUM_SUPPLIES, consumers: ov5675->supplies); |
1005 | if (ret) { |
1006 | clk_disable_unprepare(clk: ov5675->xvclk); |
1007 | return ret; |
1008 | } |
1009 | |
1010 | /* Reset pulse should be at least 2ms and reset gpio released only once |
1011 | * regulators are stable. |
1012 | */ |
1013 | usleep_range(min: 2000, max: 2200); |
1014 | |
1015 | gpiod_set_value_cansleep(desc: ov5675->reset_gpio, value: 0); |
1016 | |
1017 | /* 8192 xvclk cycles prior to the first SCCB transation */ |
1018 | usleep_range(min: delay_us, max: delay_us * 2); |
1019 | |
1020 | return 0; |
1021 | } |
1022 | |
1023 | static int ov5675_set_format(struct v4l2_subdev *sd, |
1024 | struct v4l2_subdev_state *sd_state, |
1025 | struct v4l2_subdev_format *fmt) |
1026 | { |
1027 | struct ov5675 *ov5675 = to_ov5675(sd); |
1028 | const struct ov5675_mode *mode; |
1029 | s32 vblank_def, h_blank; |
1030 | |
1031 | mode = v4l2_find_nearest_size(supported_modes, |
1032 | ARRAY_SIZE(supported_modes), width, |
1033 | height, fmt->format.width, |
1034 | fmt->format.height); |
1035 | |
1036 | mutex_lock(&ov5675->mutex); |
1037 | ov5675_update_pad_format(mode, fmt: &fmt->format); |
1038 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
1039 | *v4l2_subdev_state_get_format(sd_state, fmt->pad) = fmt->format; |
1040 | } else { |
1041 | ov5675->cur_mode = mode; |
1042 | __v4l2_ctrl_s_ctrl(ctrl: ov5675->link_freq, val: mode->link_freq_index); |
1043 | __v4l2_ctrl_s_ctrl_int64(ctrl: ov5675->pixel_rate, |
1044 | val: to_pixel_rate(f_index: mode->link_freq_index)); |
1045 | |
1046 | /* Update limits and set FPS to default */ |
1047 | vblank_def = mode->vts_def - mode->height; |
1048 | __v4l2_ctrl_modify_range(ctrl: ov5675->vblank, |
1049 | min: mode->vts_min - mode->height, |
1050 | OV5675_VTS_MAX - mode->height, step: 1, |
1051 | def: vblank_def); |
1052 | __v4l2_ctrl_s_ctrl(ctrl: ov5675->vblank, val: vblank_def); |
1053 | h_blank = to_pixels_per_line(hts: mode->hts, f_index: mode->link_freq_index) - |
1054 | mode->width; |
1055 | __v4l2_ctrl_modify_range(ctrl: ov5675->hblank, min: h_blank, max: h_blank, step: 1, |
1056 | def: h_blank); |
1057 | } |
1058 | |
1059 | mutex_unlock(lock: &ov5675->mutex); |
1060 | |
1061 | return 0; |
1062 | } |
1063 | |
1064 | static int ov5675_get_format(struct v4l2_subdev *sd, |
1065 | struct v4l2_subdev_state *sd_state, |
1066 | struct v4l2_subdev_format *fmt) |
1067 | { |
1068 | struct ov5675 *ov5675 = to_ov5675(sd); |
1069 | |
1070 | mutex_lock(&ov5675->mutex); |
1071 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) |
1072 | fmt->format = *v4l2_subdev_state_get_format(sd_state, |
1073 | fmt->pad); |
1074 | else |
1075 | ov5675_update_pad_format(mode: ov5675->cur_mode, fmt: &fmt->format); |
1076 | |
1077 | mutex_unlock(lock: &ov5675->mutex); |
1078 | |
1079 | return 0; |
1080 | } |
1081 | |
1082 | static int ov5675_get_selection(struct v4l2_subdev *sd, |
1083 | struct v4l2_subdev_state *state, |
1084 | struct v4l2_subdev_selection *sel) |
1085 | { |
1086 | if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE) |
1087 | return -EINVAL; |
1088 | |
1089 | switch (sel->target) { |
1090 | case V4L2_SEL_TGT_CROP_BOUNDS: |
1091 | sel->r.top = 0; |
1092 | sel->r.left = 0; |
1093 | sel->r.width = 2624; |
1094 | sel->r.height = 2000; |
1095 | return 0; |
1096 | case V4L2_SEL_TGT_CROP: |
1097 | case V4L2_SEL_TGT_CROP_DEFAULT: |
1098 | sel->r.top = 16; |
1099 | sel->r.left = 16; |
1100 | sel->r.width = 2592; |
1101 | sel->r.height = 1944; |
1102 | return 0; |
1103 | } |
1104 | return -EINVAL; |
1105 | } |
1106 | |
1107 | static int ov5675_enum_mbus_code(struct v4l2_subdev *sd, |
1108 | struct v4l2_subdev_state *sd_state, |
1109 | struct v4l2_subdev_mbus_code_enum *code) |
1110 | { |
1111 | if (code->index > 0) |
1112 | return -EINVAL; |
1113 | |
1114 | code->code = MEDIA_BUS_FMT_SGRBG10_1X10; |
1115 | |
1116 | return 0; |
1117 | } |
1118 | |
1119 | static int ov5675_enum_frame_size(struct v4l2_subdev *sd, |
1120 | struct v4l2_subdev_state *sd_state, |
1121 | struct v4l2_subdev_frame_size_enum *fse) |
1122 | { |
1123 | if (fse->index >= ARRAY_SIZE(supported_modes)) |
1124 | return -EINVAL; |
1125 | |
1126 | if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) |
1127 | return -EINVAL; |
1128 | |
1129 | fse->min_width = supported_modes[fse->index].width; |
1130 | fse->max_width = fse->min_width; |
1131 | fse->min_height = supported_modes[fse->index].height; |
1132 | fse->max_height = fse->min_height; |
1133 | |
1134 | return 0; |
1135 | } |
1136 | |
1137 | static int ov5675_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
1138 | { |
1139 | struct ov5675 *ov5675 = to_ov5675(sd); |
1140 | |
1141 | mutex_lock(&ov5675->mutex); |
1142 | ov5675_update_pad_format(mode: &supported_modes[0], |
1143 | v4l2_subdev_state_get_format(fh->state, 0)); |
1144 | mutex_unlock(lock: &ov5675->mutex); |
1145 | |
1146 | return 0; |
1147 | } |
1148 | |
1149 | static const struct v4l2_subdev_video_ops ov5675_video_ops = { |
1150 | .s_stream = ov5675_set_stream, |
1151 | }; |
1152 | |
1153 | static const struct v4l2_subdev_pad_ops ov5675_pad_ops = { |
1154 | .set_fmt = ov5675_set_format, |
1155 | .get_fmt = ov5675_get_format, |
1156 | .get_selection = ov5675_get_selection, |
1157 | .enum_mbus_code = ov5675_enum_mbus_code, |
1158 | .enum_frame_size = ov5675_enum_frame_size, |
1159 | }; |
1160 | |
1161 | static const struct v4l2_subdev_ops ov5675_subdev_ops = { |
1162 | .video = &ov5675_video_ops, |
1163 | .pad = &ov5675_pad_ops, |
1164 | }; |
1165 | |
1166 | static const struct media_entity_operations ov5675_subdev_entity_ops = { |
1167 | .link_validate = v4l2_subdev_link_validate, |
1168 | }; |
1169 | |
1170 | static const struct v4l2_subdev_internal_ops ov5675_internal_ops = { |
1171 | .open = ov5675_open, |
1172 | }; |
1173 | |
1174 | static int ov5675_get_hwcfg(struct ov5675 *ov5675, struct device *dev) |
1175 | { |
1176 | struct fwnode_handle *ep; |
1177 | struct fwnode_handle *fwnode = dev_fwnode(dev); |
1178 | struct v4l2_fwnode_endpoint bus_cfg = { |
1179 | .bus_type = V4L2_MBUS_CSI2_DPHY |
1180 | }; |
1181 | u32 xvclk_rate; |
1182 | int ret; |
1183 | unsigned int i, j; |
1184 | |
1185 | if (!fwnode) |
1186 | return -ENXIO; |
1187 | |
1188 | ov5675->xvclk = devm_clk_get_optional(dev, NULL); |
1189 | if (IS_ERR(ptr: ov5675->xvclk)) |
1190 | return dev_err_probe(dev, err: PTR_ERR(ptr: ov5675->xvclk), |
1191 | fmt: "failed to get xvclk: %ld\n" , |
1192 | PTR_ERR(ptr: ov5675->xvclk)); |
1193 | |
1194 | if (ov5675->xvclk) { |
1195 | xvclk_rate = clk_get_rate(clk: ov5675->xvclk); |
1196 | } else { |
1197 | ret = fwnode_property_read_u32(fwnode, propname: "clock-frequency" , |
1198 | val: &xvclk_rate); |
1199 | |
1200 | if (ret) { |
1201 | dev_err(dev, "can't get clock frequency" ); |
1202 | return ret; |
1203 | } |
1204 | } |
1205 | |
1206 | if (xvclk_rate != OV5675_XVCLK_19_2) { |
1207 | dev_err(dev, "external clock rate %u is unsupported" , |
1208 | xvclk_rate); |
1209 | return -EINVAL; |
1210 | } |
1211 | |
1212 | ov5675->reset_gpio = devm_gpiod_get_optional(dev, con_id: "reset" , |
1213 | flags: GPIOD_OUT_HIGH); |
1214 | if (IS_ERR(ptr: ov5675->reset_gpio)) { |
1215 | ret = PTR_ERR(ptr: ov5675->reset_gpio); |
1216 | dev_err(dev, "failed to get reset-gpios: %d\n" , ret); |
1217 | return ret; |
1218 | } |
1219 | |
1220 | for (i = 0; i < OV5675_NUM_SUPPLIES; i++) |
1221 | ov5675->supplies[i].supply = ov5675_supply_names[i]; |
1222 | |
1223 | ret = devm_regulator_bulk_get(dev, OV5675_NUM_SUPPLIES, |
1224 | consumers: ov5675->supplies); |
1225 | if (ret) |
1226 | return ret; |
1227 | |
1228 | ep = fwnode_graph_get_next_endpoint(fwnode, NULL); |
1229 | if (!ep) |
1230 | return -ENXIO; |
1231 | |
1232 | ret = v4l2_fwnode_endpoint_alloc_parse(fwnode: ep, vep: &bus_cfg); |
1233 | fwnode_handle_put(fwnode: ep); |
1234 | if (ret) |
1235 | return ret; |
1236 | |
1237 | if (bus_cfg.bus.mipi_csi2.num_data_lanes != OV5675_DATA_LANES) { |
1238 | dev_err(dev, "number of CSI2 data lanes %d is not supported" , |
1239 | bus_cfg.bus.mipi_csi2.num_data_lanes); |
1240 | ret = -EINVAL; |
1241 | goto check_hwcfg_error; |
1242 | } |
1243 | |
1244 | if (!bus_cfg.nr_of_link_frequencies) { |
1245 | dev_err(dev, "no link frequencies defined" ); |
1246 | ret = -EINVAL; |
1247 | goto check_hwcfg_error; |
1248 | } |
1249 | |
1250 | for (i = 0; i < ARRAY_SIZE(link_freq_menu_items); i++) { |
1251 | for (j = 0; j < bus_cfg.nr_of_link_frequencies; j++) { |
1252 | if (link_freq_menu_items[i] == |
1253 | bus_cfg.link_frequencies[j]) |
1254 | break; |
1255 | } |
1256 | |
1257 | if (j == bus_cfg.nr_of_link_frequencies) { |
1258 | dev_err(dev, "no link frequency %lld supported" , |
1259 | link_freq_menu_items[i]); |
1260 | ret = -EINVAL; |
1261 | goto check_hwcfg_error; |
1262 | } |
1263 | } |
1264 | |
1265 | check_hwcfg_error: |
1266 | v4l2_fwnode_endpoint_free(vep: &bus_cfg); |
1267 | |
1268 | return ret; |
1269 | } |
1270 | |
1271 | static void ov5675_remove(struct i2c_client *client) |
1272 | { |
1273 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
1274 | struct ov5675 *ov5675 = to_ov5675(sd); |
1275 | |
1276 | v4l2_async_unregister_subdev(sd); |
1277 | media_entity_cleanup(entity: &sd->entity); |
1278 | v4l2_ctrl_handler_free(hdl: sd->ctrl_handler); |
1279 | pm_runtime_disable(dev: &client->dev); |
1280 | mutex_destroy(lock: &ov5675->mutex); |
1281 | |
1282 | if (!pm_runtime_status_suspended(dev: &client->dev)) |
1283 | ov5675_power_off(dev: &client->dev); |
1284 | pm_runtime_set_suspended(dev: &client->dev); |
1285 | } |
1286 | |
1287 | static int ov5675_probe(struct i2c_client *client) |
1288 | { |
1289 | struct ov5675 *ov5675; |
1290 | bool full_power; |
1291 | int ret; |
1292 | |
1293 | ov5675 = devm_kzalloc(dev: &client->dev, size: sizeof(*ov5675), GFP_KERNEL); |
1294 | if (!ov5675) |
1295 | return -ENOMEM; |
1296 | |
1297 | ret = ov5675_get_hwcfg(ov5675, dev: &client->dev); |
1298 | if (ret) { |
1299 | dev_err(&client->dev, "failed to get HW configuration: %d" , |
1300 | ret); |
1301 | return ret; |
1302 | } |
1303 | |
1304 | v4l2_i2c_subdev_init(sd: &ov5675->sd, client, ops: &ov5675_subdev_ops); |
1305 | |
1306 | ret = ov5675_power_on(dev: &client->dev); |
1307 | if (ret) { |
1308 | dev_err(&client->dev, "failed to power on: %d\n" , ret); |
1309 | return ret; |
1310 | } |
1311 | |
1312 | full_power = acpi_dev_state_d0(dev: &client->dev); |
1313 | if (full_power) { |
1314 | ret = ov5675_identify_module(ov5675); |
1315 | if (ret) { |
1316 | dev_err(&client->dev, "failed to find sensor: %d" , ret); |
1317 | goto probe_power_off; |
1318 | } |
1319 | } |
1320 | |
1321 | mutex_init(&ov5675->mutex); |
1322 | ov5675->cur_mode = &supported_modes[0]; |
1323 | ret = ov5675_init_controls(ov5675); |
1324 | if (ret) { |
1325 | dev_err(&client->dev, "failed to init controls: %d" , ret); |
1326 | goto probe_error_v4l2_ctrl_handler_free; |
1327 | } |
1328 | |
1329 | ov5675->sd.internal_ops = &ov5675_internal_ops; |
1330 | ov5675->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
1331 | ov5675->sd.entity.ops = &ov5675_subdev_entity_ops; |
1332 | ov5675->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
1333 | ov5675->pad.flags = MEDIA_PAD_FL_SOURCE; |
1334 | ret = media_entity_pads_init(entity: &ov5675->sd.entity, num_pads: 1, pads: &ov5675->pad); |
1335 | if (ret) { |
1336 | dev_err(&client->dev, "failed to init entity pads: %d" , ret); |
1337 | goto probe_error_v4l2_ctrl_handler_free; |
1338 | } |
1339 | |
1340 | ret = v4l2_async_register_subdev_sensor(sd: &ov5675->sd); |
1341 | if (ret < 0) { |
1342 | dev_err(&client->dev, "failed to register V4L2 subdev: %d" , |
1343 | ret); |
1344 | goto probe_error_media_entity_cleanup; |
1345 | } |
1346 | |
1347 | /* Set the device's state to active if it's in D0 state. */ |
1348 | if (full_power) |
1349 | pm_runtime_set_active(dev: &client->dev); |
1350 | pm_runtime_enable(dev: &client->dev); |
1351 | pm_runtime_idle(dev: &client->dev); |
1352 | |
1353 | return 0; |
1354 | |
1355 | probe_error_media_entity_cleanup: |
1356 | media_entity_cleanup(entity: &ov5675->sd.entity); |
1357 | |
1358 | probe_error_v4l2_ctrl_handler_free: |
1359 | v4l2_ctrl_handler_free(hdl: ov5675->sd.ctrl_handler); |
1360 | mutex_destroy(lock: &ov5675->mutex); |
1361 | probe_power_off: |
1362 | ov5675_power_off(dev: &client->dev); |
1363 | |
1364 | return ret; |
1365 | } |
1366 | |
1367 | static const struct dev_pm_ops ov5675_pm_ops = { |
1368 | SET_RUNTIME_PM_OPS(ov5675_power_off, ov5675_power_on, NULL) |
1369 | }; |
1370 | |
1371 | #ifdef CONFIG_ACPI |
1372 | static const struct acpi_device_id ov5675_acpi_ids[] = { |
1373 | {"OVTI5675" }, |
1374 | {} |
1375 | }; |
1376 | |
1377 | MODULE_DEVICE_TABLE(acpi, ov5675_acpi_ids); |
1378 | #endif |
1379 | |
1380 | static const struct of_device_id ov5675_of_match[] = { |
1381 | { .compatible = "ovti,ov5675" , }, |
1382 | { /* sentinel */ }, |
1383 | }; |
1384 | MODULE_DEVICE_TABLE(of, ov5675_of_match); |
1385 | |
1386 | static struct i2c_driver ov5675_i2c_driver = { |
1387 | .driver = { |
1388 | .name = "ov5675" , |
1389 | .pm = &ov5675_pm_ops, |
1390 | .acpi_match_table = ACPI_PTR(ov5675_acpi_ids), |
1391 | .of_match_table = ov5675_of_match, |
1392 | }, |
1393 | .probe = ov5675_probe, |
1394 | .remove = ov5675_remove, |
1395 | .flags = I2C_DRV_ACPI_WAIVE_D0_PROBE, |
1396 | }; |
1397 | |
1398 | module_i2c_driver(ov5675_i2c_driver); |
1399 | |
1400 | MODULE_AUTHOR("Shawn Tu" ); |
1401 | MODULE_DESCRIPTION("OmniVision OV5675 sensor driver" ); |
1402 | MODULE_LICENSE("GPL v2" ); |
1403 | |