1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2017 Intel Corporation. |
3 | |
4 | #include <linux/acpi.h> |
5 | #include <linux/i2c.h> |
6 | #include <linux/module.h> |
7 | #include <linux/pm_runtime.h> |
8 | #include <media/v4l2-ctrls.h> |
9 | #include <media/v4l2-device.h> |
10 | #include <media/v4l2-event.h> |
11 | #include <media/v4l2-fwnode.h> |
12 | |
13 | #define OV13858_REG_VALUE_08BIT 1 |
14 | #define OV13858_REG_VALUE_16BIT 2 |
15 | #define OV13858_REG_VALUE_24BIT 3 |
16 | |
17 | #define OV13858_REG_MODE_SELECT 0x0100 |
18 | #define OV13858_MODE_STANDBY 0x00 |
19 | #define OV13858_MODE_STREAMING 0x01 |
20 | |
21 | #define OV13858_REG_SOFTWARE_RST 0x0103 |
22 | #define OV13858_SOFTWARE_RST 0x01 |
23 | |
24 | /* PLL1 generates PCLK and MIPI_PHY_CLK */ |
25 | #define OV13858_REG_PLL1_CTRL_0 0x0300 |
26 | #define OV13858_REG_PLL1_CTRL_1 0x0301 |
27 | #define OV13858_REG_PLL1_CTRL_2 0x0302 |
28 | #define OV13858_REG_PLL1_CTRL_3 0x0303 |
29 | #define OV13858_REG_PLL1_CTRL_4 0x0304 |
30 | #define OV13858_REG_PLL1_CTRL_5 0x0305 |
31 | |
32 | /* PLL2 generates DAC_CLK, SCLK and SRAM_CLK */ |
33 | #define OV13858_REG_PLL2_CTRL_B 0x030b |
34 | #define OV13858_REG_PLL2_CTRL_C 0x030c |
35 | #define OV13858_REG_PLL2_CTRL_D 0x030d |
36 | #define OV13858_REG_PLL2_CTRL_E 0x030e |
37 | #define OV13858_REG_PLL2_CTRL_F 0x030f |
38 | #define OV13858_REG_PLL2_CTRL_12 0x0312 |
39 | #define OV13858_REG_MIPI_SC_CTRL0 0x3016 |
40 | #define OV13858_REG_MIPI_SC_CTRL1 0x3022 |
41 | |
42 | /* Chip ID */ |
43 | #define OV13858_REG_CHIP_ID 0x300a |
44 | #define OV13858_CHIP_ID 0x00d855 |
45 | |
46 | /* V_TIMING internal */ |
47 | #define OV13858_REG_VTS 0x380e |
48 | #define OV13858_VTS_30FPS 0x0c8e /* 30 fps */ |
49 | #define OV13858_VTS_60FPS 0x0648 /* 60 fps */ |
50 | #define OV13858_VTS_MAX 0x7fff |
51 | |
52 | /* HBLANK control - read only */ |
53 | #define OV13858_PPL_270MHZ 2244 |
54 | #define OV13858_PPL_540MHZ 4488 |
55 | |
56 | /* Exposure control */ |
57 | #define OV13858_REG_EXPOSURE 0x3500 |
58 | #define OV13858_EXPOSURE_MIN 4 |
59 | #define OV13858_EXPOSURE_STEP 1 |
60 | #define OV13858_EXPOSURE_DEFAULT 0x640 |
61 | |
62 | /* Analog gain control */ |
63 | #define OV13858_REG_ANALOG_GAIN 0x3508 |
64 | #define OV13858_ANA_GAIN_MIN 0 |
65 | #define OV13858_ANA_GAIN_MAX 0x1fff |
66 | #define OV13858_ANA_GAIN_STEP 1 |
67 | #define OV13858_ANA_GAIN_DEFAULT 0x80 |
68 | |
69 | /* Digital gain control */ |
70 | #define OV13858_REG_B_MWB_GAIN 0x5100 |
71 | #define OV13858_REG_G_MWB_GAIN 0x5102 |
72 | #define OV13858_REG_R_MWB_GAIN 0x5104 |
73 | #define OV13858_DGTL_GAIN_MIN 0 |
74 | #define OV13858_DGTL_GAIN_MAX 16384 /* Max = 16 X */ |
75 | #define OV13858_DGTL_GAIN_DEFAULT 1024 /* Default gain = 1 X */ |
76 | #define OV13858_DGTL_GAIN_STEP 1 /* Each step = 1/1024 */ |
77 | |
78 | /* Test Pattern Control */ |
79 | #define OV13858_REG_TEST_PATTERN 0x4503 |
80 | #define OV13858_TEST_PATTERN_ENABLE BIT(7) |
81 | #define OV13858_TEST_PATTERN_MASK 0xfc |
82 | |
83 | /* Number of frames to skip */ |
84 | #define OV13858_NUM_OF_SKIP_FRAMES 2 |
85 | |
86 | struct ov13858_reg { |
87 | u16 address; |
88 | u8 val; |
89 | }; |
90 | |
91 | struct ov13858_reg_list { |
92 | u32 num_of_regs; |
93 | const struct ov13858_reg *regs; |
94 | }; |
95 | |
96 | /* Link frequency config */ |
97 | struct ov13858_link_freq_config { |
98 | u32 pixels_per_line; |
99 | |
100 | /* PLL registers for this link frequency */ |
101 | struct ov13858_reg_list reg_list; |
102 | }; |
103 | |
104 | /* Mode : resolution and related config&values */ |
105 | struct ov13858_mode { |
106 | /* Frame width */ |
107 | u32 width; |
108 | /* Frame height */ |
109 | u32 height; |
110 | |
111 | /* V-timing */ |
112 | u32 vts_def; |
113 | u32 vts_min; |
114 | |
115 | /* Index of Link frequency config to be used */ |
116 | u32 link_freq_index; |
117 | /* Default register values */ |
118 | struct ov13858_reg_list reg_list; |
119 | }; |
120 | |
121 | /* 4224x3136 needs 1080Mbps/lane, 4 lanes */ |
122 | static const struct ov13858_reg mipi_data_rate_1080mbps[] = { |
123 | /* PLL1 registers */ |
124 | {OV13858_REG_PLL1_CTRL_0, 0x07}, |
125 | {OV13858_REG_PLL1_CTRL_1, 0x01}, |
126 | {OV13858_REG_PLL1_CTRL_2, 0xc2}, |
127 | {OV13858_REG_PLL1_CTRL_3, 0x00}, |
128 | {OV13858_REG_PLL1_CTRL_4, 0x00}, |
129 | {OV13858_REG_PLL1_CTRL_5, 0x01}, |
130 | |
131 | /* PLL2 registers */ |
132 | {OV13858_REG_PLL2_CTRL_B, 0x05}, |
133 | {OV13858_REG_PLL2_CTRL_C, 0x01}, |
134 | {OV13858_REG_PLL2_CTRL_D, 0x0e}, |
135 | {OV13858_REG_PLL2_CTRL_E, 0x05}, |
136 | {OV13858_REG_PLL2_CTRL_F, 0x01}, |
137 | {OV13858_REG_PLL2_CTRL_12, 0x01}, |
138 | {OV13858_REG_MIPI_SC_CTRL0, 0x72}, |
139 | {OV13858_REG_MIPI_SC_CTRL1, 0x01}, |
140 | }; |
141 | |
142 | /* |
143 | * 2112x1568, 2112x1188, 1056x784 need 540Mbps/lane, |
144 | * 4 lanes |
145 | */ |
146 | static const struct ov13858_reg mipi_data_rate_540mbps[] = { |
147 | /* PLL1 registers */ |
148 | {OV13858_REG_PLL1_CTRL_0, 0x07}, |
149 | {OV13858_REG_PLL1_CTRL_1, 0x01}, |
150 | {OV13858_REG_PLL1_CTRL_2, 0xc2}, |
151 | {OV13858_REG_PLL1_CTRL_3, 0x01}, |
152 | {OV13858_REG_PLL1_CTRL_4, 0x00}, |
153 | {OV13858_REG_PLL1_CTRL_5, 0x01}, |
154 | |
155 | /* PLL2 registers */ |
156 | {OV13858_REG_PLL2_CTRL_B, 0x05}, |
157 | {OV13858_REG_PLL2_CTRL_C, 0x01}, |
158 | {OV13858_REG_PLL2_CTRL_D, 0x0e}, |
159 | {OV13858_REG_PLL2_CTRL_E, 0x05}, |
160 | {OV13858_REG_PLL2_CTRL_F, 0x01}, |
161 | {OV13858_REG_PLL2_CTRL_12, 0x01}, |
162 | {OV13858_REG_MIPI_SC_CTRL0, 0x72}, |
163 | {OV13858_REG_MIPI_SC_CTRL1, 0x01}, |
164 | }; |
165 | |
166 | static const struct ov13858_reg mode_4224x3136_regs[] = { |
167 | {0x3013, 0x32}, |
168 | {0x301b, 0xf0}, |
169 | {0x301f, 0xd0}, |
170 | {0x3106, 0x15}, |
171 | {0x3107, 0x23}, |
172 | {0x350a, 0x00}, |
173 | {0x350e, 0x00}, |
174 | {0x3510, 0x00}, |
175 | {0x3511, 0x02}, |
176 | {0x3512, 0x00}, |
177 | {0x3600, 0x2b}, |
178 | {0x3601, 0x52}, |
179 | {0x3602, 0x60}, |
180 | {0x3612, 0x05}, |
181 | {0x3613, 0xa4}, |
182 | {0x3620, 0x80}, |
183 | {0x3621, 0x10}, |
184 | {0x3622, 0x30}, |
185 | {0x3624, 0x1c}, |
186 | {0x3640, 0x10}, |
187 | {0x3641, 0x70}, |
188 | {0x3660, 0x04}, |
189 | {0x3661, 0x80}, |
190 | {0x3662, 0x12}, |
191 | {0x3664, 0x73}, |
192 | {0x3665, 0xa7}, |
193 | {0x366e, 0xff}, |
194 | {0x366f, 0xf4}, |
195 | {0x3674, 0x00}, |
196 | {0x3679, 0x0c}, |
197 | {0x367f, 0x01}, |
198 | {0x3680, 0x0c}, |
199 | {0x3681, 0x50}, |
200 | {0x3682, 0x50}, |
201 | {0x3683, 0xa9}, |
202 | {0x3684, 0xa9}, |
203 | {0x3709, 0x5f}, |
204 | {0x3714, 0x24}, |
205 | {0x371a, 0x3e}, |
206 | {0x3737, 0x04}, |
207 | {0x3738, 0xcc}, |
208 | {0x3739, 0x12}, |
209 | {0x373d, 0x26}, |
210 | {0x3764, 0x20}, |
211 | {0x3765, 0x20}, |
212 | {0x37a1, 0x36}, |
213 | {0x37a8, 0x3b}, |
214 | {0x37ab, 0x31}, |
215 | {0x37c2, 0x04}, |
216 | {0x37c3, 0xf1}, |
217 | {0x37c5, 0x00}, |
218 | {0x37d8, 0x03}, |
219 | {0x37d9, 0x0c}, |
220 | {0x37da, 0xc2}, |
221 | {0x37dc, 0x02}, |
222 | {0x37e0, 0x00}, |
223 | {0x37e1, 0x0a}, |
224 | {0x37e2, 0x14}, |
225 | {0x37e3, 0x04}, |
226 | {0x37e4, 0x2a}, |
227 | {0x37e5, 0x03}, |
228 | {0x37e6, 0x04}, |
229 | {0x3800, 0x00}, |
230 | {0x3801, 0x00}, |
231 | {0x3802, 0x00}, |
232 | {0x3803, 0x08}, |
233 | {0x3804, 0x10}, |
234 | {0x3805, 0x9f}, |
235 | {0x3806, 0x0c}, |
236 | {0x3807, 0x57}, |
237 | {0x3808, 0x10}, |
238 | {0x3809, 0x80}, |
239 | {0x380a, 0x0c}, |
240 | {0x380b, 0x40}, |
241 | {0x380c, 0x04}, |
242 | {0x380d, 0x62}, |
243 | {0x380e, 0x0c}, |
244 | {0x380f, 0x8e}, |
245 | {0x3811, 0x04}, |
246 | {0x3813, 0x05}, |
247 | {0x3814, 0x01}, |
248 | {0x3815, 0x01}, |
249 | {0x3816, 0x01}, |
250 | {0x3817, 0x01}, |
251 | {0x3820, 0xa8}, |
252 | {0x3821, 0x00}, |
253 | {0x3822, 0xc2}, |
254 | {0x3823, 0x18}, |
255 | {0x3826, 0x11}, |
256 | {0x3827, 0x1c}, |
257 | {0x3829, 0x03}, |
258 | {0x3832, 0x00}, |
259 | {0x3c80, 0x00}, |
260 | {0x3c87, 0x01}, |
261 | {0x3c8c, 0x19}, |
262 | {0x3c8d, 0x1c}, |
263 | {0x3c90, 0x00}, |
264 | {0x3c91, 0x00}, |
265 | {0x3c92, 0x00}, |
266 | {0x3c93, 0x00}, |
267 | {0x3c94, 0x40}, |
268 | {0x3c95, 0x54}, |
269 | {0x3c96, 0x34}, |
270 | {0x3c97, 0x04}, |
271 | {0x3c98, 0x00}, |
272 | {0x3d8c, 0x73}, |
273 | {0x3d8d, 0xc0}, |
274 | {0x3f00, 0x0b}, |
275 | {0x3f03, 0x00}, |
276 | {0x4001, 0xe0}, |
277 | {0x4008, 0x00}, |
278 | {0x4009, 0x0f}, |
279 | {0x4011, 0xf0}, |
280 | {0x4017, 0x08}, |
281 | {0x4050, 0x04}, |
282 | {0x4051, 0x0b}, |
283 | {0x4052, 0x00}, |
284 | {0x4053, 0x80}, |
285 | {0x4054, 0x00}, |
286 | {0x4055, 0x80}, |
287 | {0x4056, 0x00}, |
288 | {0x4057, 0x80}, |
289 | {0x4058, 0x00}, |
290 | {0x4059, 0x80}, |
291 | {0x405e, 0x20}, |
292 | {0x4500, 0x07}, |
293 | {0x4503, 0x00}, |
294 | {0x450a, 0x04}, |
295 | {0x4809, 0x04}, |
296 | {0x480c, 0x12}, |
297 | {0x481f, 0x30}, |
298 | {0x4833, 0x10}, |
299 | {0x4837, 0x0e}, |
300 | {0x4902, 0x01}, |
301 | {0x4d00, 0x03}, |
302 | {0x4d01, 0xc9}, |
303 | {0x4d02, 0xbc}, |
304 | {0x4d03, 0xd7}, |
305 | {0x4d04, 0xf0}, |
306 | {0x4d05, 0xa2}, |
307 | {0x5000, 0xfd}, |
308 | {0x5001, 0x01}, |
309 | {0x5040, 0x39}, |
310 | {0x5041, 0x10}, |
311 | {0x5042, 0x10}, |
312 | {0x5043, 0x84}, |
313 | {0x5044, 0x62}, |
314 | {0x5180, 0x00}, |
315 | {0x5181, 0x10}, |
316 | {0x5182, 0x02}, |
317 | {0x5183, 0x0f}, |
318 | {0x5200, 0x1b}, |
319 | {0x520b, 0x07}, |
320 | {0x520c, 0x0f}, |
321 | {0x5300, 0x04}, |
322 | {0x5301, 0x0c}, |
323 | {0x5302, 0x0c}, |
324 | {0x5303, 0x0f}, |
325 | {0x5304, 0x00}, |
326 | {0x5305, 0x70}, |
327 | {0x5306, 0x00}, |
328 | {0x5307, 0x80}, |
329 | {0x5308, 0x00}, |
330 | {0x5309, 0xa5}, |
331 | {0x530a, 0x00}, |
332 | {0x530b, 0xd3}, |
333 | {0x530c, 0x00}, |
334 | {0x530d, 0xf0}, |
335 | {0x530e, 0x01}, |
336 | {0x530f, 0x10}, |
337 | {0x5310, 0x01}, |
338 | {0x5311, 0x20}, |
339 | {0x5312, 0x01}, |
340 | {0x5313, 0x20}, |
341 | {0x5314, 0x01}, |
342 | {0x5315, 0x20}, |
343 | {0x5316, 0x08}, |
344 | {0x5317, 0x08}, |
345 | {0x5318, 0x10}, |
346 | {0x5319, 0x88}, |
347 | {0x531a, 0x88}, |
348 | {0x531b, 0xa9}, |
349 | {0x531c, 0xaa}, |
350 | {0x531d, 0x0a}, |
351 | {0x5405, 0x02}, |
352 | {0x5406, 0x67}, |
353 | {0x5407, 0x01}, |
354 | {0x5408, 0x4a}, |
355 | }; |
356 | |
357 | static const struct ov13858_reg mode_2112x1568_regs[] = { |
358 | {0x3013, 0x32}, |
359 | {0x301b, 0xf0}, |
360 | {0x301f, 0xd0}, |
361 | {0x3106, 0x15}, |
362 | {0x3107, 0x23}, |
363 | {0x350a, 0x00}, |
364 | {0x350e, 0x00}, |
365 | {0x3510, 0x00}, |
366 | {0x3511, 0x02}, |
367 | {0x3512, 0x00}, |
368 | {0x3600, 0x2b}, |
369 | {0x3601, 0x52}, |
370 | {0x3602, 0x60}, |
371 | {0x3612, 0x05}, |
372 | {0x3613, 0xa4}, |
373 | {0x3620, 0x80}, |
374 | {0x3621, 0x10}, |
375 | {0x3622, 0x30}, |
376 | {0x3624, 0x1c}, |
377 | {0x3640, 0x10}, |
378 | {0x3641, 0x70}, |
379 | {0x3660, 0x04}, |
380 | {0x3661, 0x80}, |
381 | {0x3662, 0x10}, |
382 | {0x3664, 0x73}, |
383 | {0x3665, 0xa7}, |
384 | {0x366e, 0xff}, |
385 | {0x366f, 0xf4}, |
386 | {0x3674, 0x00}, |
387 | {0x3679, 0x0c}, |
388 | {0x367f, 0x01}, |
389 | {0x3680, 0x0c}, |
390 | {0x3681, 0x50}, |
391 | {0x3682, 0x50}, |
392 | {0x3683, 0xa9}, |
393 | {0x3684, 0xa9}, |
394 | {0x3709, 0x5f}, |
395 | {0x3714, 0x28}, |
396 | {0x371a, 0x3e}, |
397 | {0x3737, 0x08}, |
398 | {0x3738, 0xcc}, |
399 | {0x3739, 0x20}, |
400 | {0x373d, 0x26}, |
401 | {0x3764, 0x20}, |
402 | {0x3765, 0x20}, |
403 | {0x37a1, 0x36}, |
404 | {0x37a8, 0x3b}, |
405 | {0x37ab, 0x31}, |
406 | {0x37c2, 0x14}, |
407 | {0x37c3, 0xf1}, |
408 | {0x37c5, 0x00}, |
409 | {0x37d8, 0x03}, |
410 | {0x37d9, 0x0c}, |
411 | {0x37da, 0xc2}, |
412 | {0x37dc, 0x02}, |
413 | {0x37e0, 0x00}, |
414 | {0x37e1, 0x0a}, |
415 | {0x37e2, 0x14}, |
416 | {0x37e3, 0x08}, |
417 | {0x37e4, 0x38}, |
418 | {0x37e5, 0x03}, |
419 | {0x37e6, 0x08}, |
420 | {0x3800, 0x00}, |
421 | {0x3801, 0x00}, |
422 | {0x3802, 0x00}, |
423 | {0x3803, 0x00}, |
424 | {0x3804, 0x10}, |
425 | {0x3805, 0x9f}, |
426 | {0x3806, 0x0c}, |
427 | {0x3807, 0x5f}, |
428 | {0x3808, 0x08}, |
429 | {0x3809, 0x40}, |
430 | {0x380a, 0x06}, |
431 | {0x380b, 0x20}, |
432 | {0x380c, 0x04}, |
433 | {0x380d, 0x62}, |
434 | {0x380e, 0x0c}, |
435 | {0x380f, 0x8e}, |
436 | {0x3811, 0x04}, |
437 | {0x3813, 0x05}, |
438 | {0x3814, 0x03}, |
439 | {0x3815, 0x01}, |
440 | {0x3816, 0x03}, |
441 | {0x3817, 0x01}, |
442 | {0x3820, 0xab}, |
443 | {0x3821, 0x00}, |
444 | {0x3822, 0xc2}, |
445 | {0x3823, 0x18}, |
446 | {0x3826, 0x04}, |
447 | {0x3827, 0x90}, |
448 | {0x3829, 0x07}, |
449 | {0x3832, 0x00}, |
450 | {0x3c80, 0x00}, |
451 | {0x3c87, 0x01}, |
452 | {0x3c8c, 0x19}, |
453 | {0x3c8d, 0x1c}, |
454 | {0x3c90, 0x00}, |
455 | {0x3c91, 0x00}, |
456 | {0x3c92, 0x00}, |
457 | {0x3c93, 0x00}, |
458 | {0x3c94, 0x40}, |
459 | {0x3c95, 0x54}, |
460 | {0x3c96, 0x34}, |
461 | {0x3c97, 0x04}, |
462 | {0x3c98, 0x00}, |
463 | {0x3d8c, 0x73}, |
464 | {0x3d8d, 0xc0}, |
465 | {0x3f00, 0x0b}, |
466 | {0x3f03, 0x00}, |
467 | {0x4001, 0xe0}, |
468 | {0x4008, 0x00}, |
469 | {0x4009, 0x0d}, |
470 | {0x4011, 0xf0}, |
471 | {0x4017, 0x08}, |
472 | {0x4050, 0x04}, |
473 | {0x4051, 0x0b}, |
474 | {0x4052, 0x00}, |
475 | {0x4053, 0x80}, |
476 | {0x4054, 0x00}, |
477 | {0x4055, 0x80}, |
478 | {0x4056, 0x00}, |
479 | {0x4057, 0x80}, |
480 | {0x4058, 0x00}, |
481 | {0x4059, 0x80}, |
482 | {0x405e, 0x20}, |
483 | {0x4500, 0x07}, |
484 | {0x4503, 0x00}, |
485 | {0x450a, 0x04}, |
486 | {0x4809, 0x04}, |
487 | {0x480c, 0x12}, |
488 | {0x481f, 0x30}, |
489 | {0x4833, 0x10}, |
490 | {0x4837, 0x1c}, |
491 | {0x4902, 0x01}, |
492 | {0x4d00, 0x03}, |
493 | {0x4d01, 0xc9}, |
494 | {0x4d02, 0xbc}, |
495 | {0x4d03, 0xd7}, |
496 | {0x4d04, 0xf0}, |
497 | {0x4d05, 0xa2}, |
498 | {0x5000, 0xfd}, |
499 | {0x5001, 0x01}, |
500 | {0x5040, 0x39}, |
501 | {0x5041, 0x10}, |
502 | {0x5042, 0x10}, |
503 | {0x5043, 0x84}, |
504 | {0x5044, 0x62}, |
505 | {0x5180, 0x00}, |
506 | {0x5181, 0x10}, |
507 | {0x5182, 0x02}, |
508 | {0x5183, 0x0f}, |
509 | {0x5200, 0x1b}, |
510 | {0x520b, 0x07}, |
511 | {0x520c, 0x0f}, |
512 | {0x5300, 0x04}, |
513 | {0x5301, 0x0c}, |
514 | {0x5302, 0x0c}, |
515 | {0x5303, 0x0f}, |
516 | {0x5304, 0x00}, |
517 | {0x5305, 0x70}, |
518 | {0x5306, 0x00}, |
519 | {0x5307, 0x80}, |
520 | {0x5308, 0x00}, |
521 | {0x5309, 0xa5}, |
522 | {0x530a, 0x00}, |
523 | {0x530b, 0xd3}, |
524 | {0x530c, 0x00}, |
525 | {0x530d, 0xf0}, |
526 | {0x530e, 0x01}, |
527 | {0x530f, 0x10}, |
528 | {0x5310, 0x01}, |
529 | {0x5311, 0x20}, |
530 | {0x5312, 0x01}, |
531 | {0x5313, 0x20}, |
532 | {0x5314, 0x01}, |
533 | {0x5315, 0x20}, |
534 | {0x5316, 0x08}, |
535 | {0x5317, 0x08}, |
536 | {0x5318, 0x10}, |
537 | {0x5319, 0x88}, |
538 | {0x531a, 0x88}, |
539 | {0x531b, 0xa9}, |
540 | {0x531c, 0xaa}, |
541 | {0x531d, 0x0a}, |
542 | {0x5405, 0x02}, |
543 | {0x5406, 0x67}, |
544 | {0x5407, 0x01}, |
545 | {0x5408, 0x4a}, |
546 | }; |
547 | |
548 | static const struct ov13858_reg mode_2112x1188_regs[] = { |
549 | {0x3013, 0x32}, |
550 | {0x301b, 0xf0}, |
551 | {0x301f, 0xd0}, |
552 | {0x3106, 0x15}, |
553 | {0x3107, 0x23}, |
554 | {0x350a, 0x00}, |
555 | {0x350e, 0x00}, |
556 | {0x3510, 0x00}, |
557 | {0x3511, 0x02}, |
558 | {0x3512, 0x00}, |
559 | {0x3600, 0x2b}, |
560 | {0x3601, 0x52}, |
561 | {0x3602, 0x60}, |
562 | {0x3612, 0x05}, |
563 | {0x3613, 0xa4}, |
564 | {0x3620, 0x80}, |
565 | {0x3621, 0x10}, |
566 | {0x3622, 0x30}, |
567 | {0x3624, 0x1c}, |
568 | {0x3640, 0x10}, |
569 | {0x3641, 0x70}, |
570 | {0x3660, 0x04}, |
571 | {0x3661, 0x80}, |
572 | {0x3662, 0x10}, |
573 | {0x3664, 0x73}, |
574 | {0x3665, 0xa7}, |
575 | {0x366e, 0xff}, |
576 | {0x366f, 0xf4}, |
577 | {0x3674, 0x00}, |
578 | {0x3679, 0x0c}, |
579 | {0x367f, 0x01}, |
580 | {0x3680, 0x0c}, |
581 | {0x3681, 0x50}, |
582 | {0x3682, 0x50}, |
583 | {0x3683, 0xa9}, |
584 | {0x3684, 0xa9}, |
585 | {0x3709, 0x5f}, |
586 | {0x3714, 0x28}, |
587 | {0x371a, 0x3e}, |
588 | {0x3737, 0x08}, |
589 | {0x3738, 0xcc}, |
590 | {0x3739, 0x20}, |
591 | {0x373d, 0x26}, |
592 | {0x3764, 0x20}, |
593 | {0x3765, 0x20}, |
594 | {0x37a1, 0x36}, |
595 | {0x37a8, 0x3b}, |
596 | {0x37ab, 0x31}, |
597 | {0x37c2, 0x14}, |
598 | {0x37c3, 0xf1}, |
599 | {0x37c5, 0x00}, |
600 | {0x37d8, 0x03}, |
601 | {0x37d9, 0x0c}, |
602 | {0x37da, 0xc2}, |
603 | {0x37dc, 0x02}, |
604 | {0x37e0, 0x00}, |
605 | {0x37e1, 0x0a}, |
606 | {0x37e2, 0x14}, |
607 | {0x37e3, 0x08}, |
608 | {0x37e4, 0x38}, |
609 | {0x37e5, 0x03}, |
610 | {0x37e6, 0x08}, |
611 | {0x3800, 0x00}, |
612 | {0x3801, 0x00}, |
613 | {0x3802, 0x01}, |
614 | {0x3803, 0x84}, |
615 | {0x3804, 0x10}, |
616 | {0x3805, 0x9f}, |
617 | {0x3806, 0x0a}, |
618 | {0x3807, 0xd3}, |
619 | {0x3808, 0x08}, |
620 | {0x3809, 0x40}, |
621 | {0x380a, 0x04}, |
622 | {0x380b, 0xa4}, |
623 | {0x380c, 0x04}, |
624 | {0x380d, 0x62}, |
625 | {0x380e, 0x0c}, |
626 | {0x380f, 0x8e}, |
627 | {0x3811, 0x08}, |
628 | {0x3813, 0x03}, |
629 | {0x3814, 0x03}, |
630 | {0x3815, 0x01}, |
631 | {0x3816, 0x03}, |
632 | {0x3817, 0x01}, |
633 | {0x3820, 0xab}, |
634 | {0x3821, 0x00}, |
635 | {0x3822, 0xc2}, |
636 | {0x3823, 0x18}, |
637 | {0x3826, 0x04}, |
638 | {0x3827, 0x90}, |
639 | {0x3829, 0x07}, |
640 | {0x3832, 0x00}, |
641 | {0x3c80, 0x00}, |
642 | {0x3c87, 0x01}, |
643 | {0x3c8c, 0x19}, |
644 | {0x3c8d, 0x1c}, |
645 | {0x3c90, 0x00}, |
646 | {0x3c91, 0x00}, |
647 | {0x3c92, 0x00}, |
648 | {0x3c93, 0x00}, |
649 | {0x3c94, 0x40}, |
650 | {0x3c95, 0x54}, |
651 | {0x3c96, 0x34}, |
652 | {0x3c97, 0x04}, |
653 | {0x3c98, 0x00}, |
654 | {0x3d8c, 0x73}, |
655 | {0x3d8d, 0xc0}, |
656 | {0x3f00, 0x0b}, |
657 | {0x3f03, 0x00}, |
658 | {0x4001, 0xe0}, |
659 | {0x4008, 0x00}, |
660 | {0x4009, 0x0d}, |
661 | {0x4011, 0xf0}, |
662 | {0x4017, 0x08}, |
663 | {0x4050, 0x04}, |
664 | {0x4051, 0x0b}, |
665 | {0x4052, 0x00}, |
666 | {0x4053, 0x80}, |
667 | {0x4054, 0x00}, |
668 | {0x4055, 0x80}, |
669 | {0x4056, 0x00}, |
670 | {0x4057, 0x80}, |
671 | {0x4058, 0x00}, |
672 | {0x4059, 0x80}, |
673 | {0x405e, 0x20}, |
674 | {0x4500, 0x07}, |
675 | {0x4503, 0x00}, |
676 | {0x450a, 0x04}, |
677 | {0x4809, 0x04}, |
678 | {0x480c, 0x12}, |
679 | {0x481f, 0x30}, |
680 | {0x4833, 0x10}, |
681 | {0x4837, 0x1c}, |
682 | {0x4902, 0x01}, |
683 | {0x4d00, 0x03}, |
684 | {0x4d01, 0xc9}, |
685 | {0x4d02, 0xbc}, |
686 | {0x4d03, 0xd7}, |
687 | {0x4d04, 0xf0}, |
688 | {0x4d05, 0xa2}, |
689 | {0x5000, 0xfd}, |
690 | {0x5001, 0x01}, |
691 | {0x5040, 0x39}, |
692 | {0x5041, 0x10}, |
693 | {0x5042, 0x10}, |
694 | {0x5043, 0x84}, |
695 | {0x5044, 0x62}, |
696 | {0x5180, 0x00}, |
697 | {0x5181, 0x10}, |
698 | {0x5182, 0x02}, |
699 | {0x5183, 0x0f}, |
700 | {0x5200, 0x1b}, |
701 | {0x520b, 0x07}, |
702 | {0x520c, 0x0f}, |
703 | {0x5300, 0x04}, |
704 | {0x5301, 0x0c}, |
705 | {0x5302, 0x0c}, |
706 | {0x5303, 0x0f}, |
707 | {0x5304, 0x00}, |
708 | {0x5305, 0x70}, |
709 | {0x5306, 0x00}, |
710 | {0x5307, 0x80}, |
711 | {0x5308, 0x00}, |
712 | {0x5309, 0xa5}, |
713 | {0x530a, 0x00}, |
714 | {0x530b, 0xd3}, |
715 | {0x530c, 0x00}, |
716 | {0x530d, 0xf0}, |
717 | {0x530e, 0x01}, |
718 | {0x530f, 0x10}, |
719 | {0x5310, 0x01}, |
720 | {0x5311, 0x20}, |
721 | {0x5312, 0x01}, |
722 | {0x5313, 0x20}, |
723 | {0x5314, 0x01}, |
724 | {0x5315, 0x20}, |
725 | {0x5316, 0x08}, |
726 | {0x5317, 0x08}, |
727 | {0x5318, 0x10}, |
728 | {0x5319, 0x88}, |
729 | {0x531a, 0x88}, |
730 | {0x531b, 0xa9}, |
731 | {0x531c, 0xaa}, |
732 | {0x531d, 0x0a}, |
733 | {0x5405, 0x02}, |
734 | {0x5406, 0x67}, |
735 | {0x5407, 0x01}, |
736 | {0x5408, 0x4a}, |
737 | }; |
738 | |
739 | static const struct ov13858_reg mode_1056x784_regs[] = { |
740 | {0x3013, 0x32}, |
741 | {0x301b, 0xf0}, |
742 | {0x301f, 0xd0}, |
743 | {0x3106, 0x15}, |
744 | {0x3107, 0x23}, |
745 | {0x350a, 0x00}, |
746 | {0x350e, 0x00}, |
747 | {0x3510, 0x00}, |
748 | {0x3511, 0x02}, |
749 | {0x3512, 0x00}, |
750 | {0x3600, 0x2b}, |
751 | {0x3601, 0x52}, |
752 | {0x3602, 0x60}, |
753 | {0x3612, 0x05}, |
754 | {0x3613, 0xa4}, |
755 | {0x3620, 0x80}, |
756 | {0x3621, 0x10}, |
757 | {0x3622, 0x30}, |
758 | {0x3624, 0x1c}, |
759 | {0x3640, 0x10}, |
760 | {0x3641, 0x70}, |
761 | {0x3660, 0x04}, |
762 | {0x3661, 0x80}, |
763 | {0x3662, 0x08}, |
764 | {0x3664, 0x73}, |
765 | {0x3665, 0xa7}, |
766 | {0x366e, 0xff}, |
767 | {0x366f, 0xf4}, |
768 | {0x3674, 0x00}, |
769 | {0x3679, 0x0c}, |
770 | {0x367f, 0x01}, |
771 | {0x3680, 0x0c}, |
772 | {0x3681, 0x50}, |
773 | {0x3682, 0x50}, |
774 | {0x3683, 0xa9}, |
775 | {0x3684, 0xa9}, |
776 | {0x3709, 0x5f}, |
777 | {0x3714, 0x30}, |
778 | {0x371a, 0x3e}, |
779 | {0x3737, 0x08}, |
780 | {0x3738, 0xcc}, |
781 | {0x3739, 0x20}, |
782 | {0x373d, 0x26}, |
783 | {0x3764, 0x20}, |
784 | {0x3765, 0x20}, |
785 | {0x37a1, 0x36}, |
786 | {0x37a8, 0x3b}, |
787 | {0x37ab, 0x31}, |
788 | {0x37c2, 0x2c}, |
789 | {0x37c3, 0xf1}, |
790 | {0x37c5, 0x00}, |
791 | {0x37d8, 0x03}, |
792 | {0x37d9, 0x06}, |
793 | {0x37da, 0xc2}, |
794 | {0x37dc, 0x02}, |
795 | {0x37e0, 0x00}, |
796 | {0x37e1, 0x0a}, |
797 | {0x37e2, 0x14}, |
798 | {0x37e3, 0x08}, |
799 | {0x37e4, 0x36}, |
800 | {0x37e5, 0x03}, |
801 | {0x37e6, 0x08}, |
802 | {0x3800, 0x00}, |
803 | {0x3801, 0x00}, |
804 | {0x3802, 0x00}, |
805 | {0x3803, 0x00}, |
806 | {0x3804, 0x10}, |
807 | {0x3805, 0x9f}, |
808 | {0x3806, 0x0c}, |
809 | {0x3807, 0x5f}, |
810 | {0x3808, 0x04}, |
811 | {0x3809, 0x20}, |
812 | {0x380a, 0x03}, |
813 | {0x380b, 0x10}, |
814 | {0x380c, 0x04}, |
815 | {0x380d, 0x62}, |
816 | {0x380e, 0x0c}, |
817 | {0x380f, 0x8e}, |
818 | {0x3811, 0x04}, |
819 | {0x3813, 0x05}, |
820 | {0x3814, 0x07}, |
821 | {0x3815, 0x01}, |
822 | {0x3816, 0x07}, |
823 | {0x3817, 0x01}, |
824 | {0x3820, 0xac}, |
825 | {0x3821, 0x00}, |
826 | {0x3822, 0xc2}, |
827 | {0x3823, 0x18}, |
828 | {0x3826, 0x04}, |
829 | {0x3827, 0x48}, |
830 | {0x3829, 0x03}, |
831 | {0x3832, 0x00}, |
832 | {0x3c80, 0x00}, |
833 | {0x3c87, 0x01}, |
834 | {0x3c8c, 0x19}, |
835 | {0x3c8d, 0x1c}, |
836 | {0x3c90, 0x00}, |
837 | {0x3c91, 0x00}, |
838 | {0x3c92, 0x00}, |
839 | {0x3c93, 0x00}, |
840 | {0x3c94, 0x40}, |
841 | {0x3c95, 0x54}, |
842 | {0x3c96, 0x34}, |
843 | {0x3c97, 0x04}, |
844 | {0x3c98, 0x00}, |
845 | {0x3d8c, 0x73}, |
846 | {0x3d8d, 0xc0}, |
847 | {0x3f00, 0x0b}, |
848 | {0x3f03, 0x00}, |
849 | {0x4001, 0xe0}, |
850 | {0x4008, 0x00}, |
851 | {0x4009, 0x05}, |
852 | {0x4011, 0xf0}, |
853 | {0x4017, 0x08}, |
854 | {0x4050, 0x02}, |
855 | {0x4051, 0x05}, |
856 | {0x4052, 0x00}, |
857 | {0x4053, 0x80}, |
858 | {0x4054, 0x00}, |
859 | {0x4055, 0x80}, |
860 | {0x4056, 0x00}, |
861 | {0x4057, 0x80}, |
862 | {0x4058, 0x00}, |
863 | {0x4059, 0x80}, |
864 | {0x405e, 0x20}, |
865 | {0x4500, 0x07}, |
866 | {0x4503, 0x00}, |
867 | {0x450a, 0x04}, |
868 | {0x4809, 0x04}, |
869 | {0x480c, 0x12}, |
870 | {0x481f, 0x30}, |
871 | {0x4833, 0x10}, |
872 | {0x4837, 0x1e}, |
873 | {0x4902, 0x02}, |
874 | {0x4d00, 0x03}, |
875 | {0x4d01, 0xc9}, |
876 | {0x4d02, 0xbc}, |
877 | {0x4d03, 0xd7}, |
878 | {0x4d04, 0xf0}, |
879 | {0x4d05, 0xa2}, |
880 | {0x5000, 0xfd}, |
881 | {0x5001, 0x01}, |
882 | {0x5040, 0x39}, |
883 | {0x5041, 0x10}, |
884 | {0x5042, 0x10}, |
885 | {0x5043, 0x84}, |
886 | {0x5044, 0x62}, |
887 | {0x5180, 0x00}, |
888 | {0x5181, 0x10}, |
889 | {0x5182, 0x02}, |
890 | {0x5183, 0x0f}, |
891 | {0x5200, 0x1b}, |
892 | {0x520b, 0x07}, |
893 | {0x520c, 0x0f}, |
894 | {0x5300, 0x04}, |
895 | {0x5301, 0x0c}, |
896 | {0x5302, 0x0c}, |
897 | {0x5303, 0x0f}, |
898 | {0x5304, 0x00}, |
899 | {0x5305, 0x70}, |
900 | {0x5306, 0x00}, |
901 | {0x5307, 0x80}, |
902 | {0x5308, 0x00}, |
903 | {0x5309, 0xa5}, |
904 | {0x530a, 0x00}, |
905 | {0x530b, 0xd3}, |
906 | {0x530c, 0x00}, |
907 | {0x530d, 0xf0}, |
908 | {0x530e, 0x01}, |
909 | {0x530f, 0x10}, |
910 | {0x5310, 0x01}, |
911 | {0x5311, 0x20}, |
912 | {0x5312, 0x01}, |
913 | {0x5313, 0x20}, |
914 | {0x5314, 0x01}, |
915 | {0x5315, 0x20}, |
916 | {0x5316, 0x08}, |
917 | {0x5317, 0x08}, |
918 | {0x5318, 0x10}, |
919 | {0x5319, 0x88}, |
920 | {0x531a, 0x88}, |
921 | {0x531b, 0xa9}, |
922 | {0x531c, 0xaa}, |
923 | {0x531d, 0x0a}, |
924 | {0x5405, 0x02}, |
925 | {0x5406, 0x67}, |
926 | {0x5407, 0x01}, |
927 | {0x5408, 0x4a}, |
928 | }; |
929 | |
930 | static const char * const [] = { |
931 | "Disabled" , |
932 | "Vertical Color Bar Type 1" , |
933 | "Vertical Color Bar Type 2" , |
934 | "Vertical Color Bar Type 3" , |
935 | "Vertical Color Bar Type 4" |
936 | }; |
937 | |
938 | /* Configurations for supported link frequencies */ |
939 | #define OV13858_NUM_OF_LINK_FREQS 2 |
940 | #define OV13858_LINK_FREQ_540MHZ 540000000ULL |
941 | #define OV13858_LINK_FREQ_270MHZ 270000000ULL |
942 | #define OV13858_LINK_FREQ_INDEX_0 0 |
943 | #define OV13858_LINK_FREQ_INDEX_1 1 |
944 | |
945 | /* |
946 | * pixel_rate = link_freq * data-rate * nr_of_lanes / bits_per_sample |
947 | * data rate => double data rate; number of lanes => 4; bits per pixel => 10 |
948 | */ |
949 | static u64 link_freq_to_pixel_rate(u64 f) |
950 | { |
951 | f *= 2 * 4; |
952 | do_div(f, 10); |
953 | |
954 | return f; |
955 | } |
956 | |
957 | /* Menu items for LINK_FREQ V4L2 control */ |
958 | static const s64 [OV13858_NUM_OF_LINK_FREQS] = { |
959 | OV13858_LINK_FREQ_540MHZ, |
960 | OV13858_LINK_FREQ_270MHZ |
961 | }; |
962 | |
963 | /* Link frequency configs */ |
964 | static const struct ov13858_link_freq_config |
965 | link_freq_configs[OV13858_NUM_OF_LINK_FREQS] = { |
966 | { |
967 | .pixels_per_line = OV13858_PPL_540MHZ, |
968 | .reg_list = { |
969 | .num_of_regs = ARRAY_SIZE(mipi_data_rate_1080mbps), |
970 | .regs = mipi_data_rate_1080mbps, |
971 | } |
972 | }, |
973 | { |
974 | .pixels_per_line = OV13858_PPL_270MHZ, |
975 | .reg_list = { |
976 | .num_of_regs = ARRAY_SIZE(mipi_data_rate_540mbps), |
977 | .regs = mipi_data_rate_540mbps, |
978 | } |
979 | } |
980 | }; |
981 | |
982 | /* Mode configs */ |
983 | static const struct ov13858_mode supported_modes[] = { |
984 | { |
985 | .width = 4224, |
986 | .height = 3136, |
987 | .vts_def = OV13858_VTS_30FPS, |
988 | .vts_min = OV13858_VTS_30FPS, |
989 | .reg_list = { |
990 | .num_of_regs = ARRAY_SIZE(mode_4224x3136_regs), |
991 | .regs = mode_4224x3136_regs, |
992 | }, |
993 | .link_freq_index = OV13858_LINK_FREQ_INDEX_0, |
994 | }, |
995 | { |
996 | .width = 2112, |
997 | .height = 1568, |
998 | .vts_def = OV13858_VTS_30FPS, |
999 | .vts_min = 1608, |
1000 | .reg_list = { |
1001 | .num_of_regs = ARRAY_SIZE(mode_2112x1568_regs), |
1002 | .regs = mode_2112x1568_regs, |
1003 | }, |
1004 | .link_freq_index = OV13858_LINK_FREQ_INDEX_1, |
1005 | }, |
1006 | { |
1007 | .width = 2112, |
1008 | .height = 1188, |
1009 | .vts_def = OV13858_VTS_30FPS, |
1010 | .vts_min = 1608, |
1011 | .reg_list = { |
1012 | .num_of_regs = ARRAY_SIZE(mode_2112x1188_regs), |
1013 | .regs = mode_2112x1188_regs, |
1014 | }, |
1015 | .link_freq_index = OV13858_LINK_FREQ_INDEX_1, |
1016 | }, |
1017 | { |
1018 | .width = 1056, |
1019 | .height = 784, |
1020 | .vts_def = OV13858_VTS_30FPS, |
1021 | .vts_min = 804, |
1022 | .reg_list = { |
1023 | .num_of_regs = ARRAY_SIZE(mode_1056x784_regs), |
1024 | .regs = mode_1056x784_regs, |
1025 | }, |
1026 | .link_freq_index = OV13858_LINK_FREQ_INDEX_1, |
1027 | } |
1028 | }; |
1029 | |
1030 | struct ov13858 { |
1031 | struct v4l2_subdev sd; |
1032 | struct media_pad pad; |
1033 | |
1034 | struct v4l2_ctrl_handler ctrl_handler; |
1035 | /* V4L2 Controls */ |
1036 | struct v4l2_ctrl *link_freq; |
1037 | struct v4l2_ctrl *pixel_rate; |
1038 | struct v4l2_ctrl *vblank; |
1039 | struct v4l2_ctrl *hblank; |
1040 | struct v4l2_ctrl *exposure; |
1041 | |
1042 | /* Current mode */ |
1043 | const struct ov13858_mode *cur_mode; |
1044 | |
1045 | /* Mutex for serialized access */ |
1046 | struct mutex mutex; |
1047 | }; |
1048 | |
1049 | #define to_ov13858(_sd) container_of(_sd, struct ov13858, sd) |
1050 | |
1051 | /* Read registers up to 4 at a time */ |
1052 | static int ov13858_read_reg(struct ov13858 *ov13858, u16 reg, u32 len, |
1053 | u32 *val) |
1054 | { |
1055 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov13858->sd); |
1056 | struct i2c_msg msgs[2]; |
1057 | u8 *data_be_p; |
1058 | int ret; |
1059 | __be32 data_be = 0; |
1060 | __be16 reg_addr_be = cpu_to_be16(reg); |
1061 | |
1062 | if (len > 4) |
1063 | return -EINVAL; |
1064 | |
1065 | data_be_p = (u8 *)&data_be; |
1066 | /* Write register address */ |
1067 | msgs[0].addr = client->addr; |
1068 | msgs[0].flags = 0; |
1069 | msgs[0].len = 2; |
1070 | msgs[0].buf = (u8 *)®_addr_be; |
1071 | |
1072 | /* Read data from register */ |
1073 | msgs[1].addr = client->addr; |
1074 | msgs[1].flags = I2C_M_RD; |
1075 | msgs[1].len = len; |
1076 | msgs[1].buf = &data_be_p[4 - len]; |
1077 | |
1078 | ret = i2c_transfer(adap: client->adapter, msgs, ARRAY_SIZE(msgs)); |
1079 | if (ret != ARRAY_SIZE(msgs)) |
1080 | return -EIO; |
1081 | |
1082 | *val = be32_to_cpu(data_be); |
1083 | |
1084 | return 0; |
1085 | } |
1086 | |
1087 | /* Write registers up to 4 at a time */ |
1088 | static int ov13858_write_reg(struct ov13858 *ov13858, u16 reg, u32 len, |
1089 | u32 __val) |
1090 | { |
1091 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov13858->sd); |
1092 | int buf_i, val_i; |
1093 | u8 buf[6], *val_p; |
1094 | __be32 val; |
1095 | |
1096 | if (len > 4) |
1097 | return -EINVAL; |
1098 | |
1099 | buf[0] = reg >> 8; |
1100 | buf[1] = reg & 0xff; |
1101 | |
1102 | val = cpu_to_be32(__val); |
1103 | val_p = (u8 *)&val; |
1104 | buf_i = 2; |
1105 | val_i = 4 - len; |
1106 | |
1107 | while (val_i < 4) |
1108 | buf[buf_i++] = val_p[val_i++]; |
1109 | |
1110 | if (i2c_master_send(client, buf, count: len + 2) != len + 2) |
1111 | return -EIO; |
1112 | |
1113 | return 0; |
1114 | } |
1115 | |
1116 | /* Write a list of registers */ |
1117 | static int ov13858_write_regs(struct ov13858 *ov13858, |
1118 | const struct ov13858_reg *regs, u32 len) |
1119 | { |
1120 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov13858->sd); |
1121 | int ret; |
1122 | u32 i; |
1123 | |
1124 | for (i = 0; i < len; i++) { |
1125 | ret = ov13858_write_reg(ov13858, reg: regs[i].address, len: 1, |
1126 | val: regs[i].val); |
1127 | if (ret) { |
1128 | dev_err_ratelimited( |
1129 | &client->dev, |
1130 | "Failed to write reg 0x%4.4x. error = %d\n" , |
1131 | regs[i].address, ret); |
1132 | |
1133 | return ret; |
1134 | } |
1135 | } |
1136 | |
1137 | return 0; |
1138 | } |
1139 | |
1140 | static int ov13858_write_reg_list(struct ov13858 *ov13858, |
1141 | const struct ov13858_reg_list *r_list) |
1142 | { |
1143 | return ov13858_write_regs(ov13858, regs: r_list->regs, len: r_list->num_of_regs); |
1144 | } |
1145 | |
1146 | /* Open sub-device */ |
1147 | static int ov13858_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
1148 | { |
1149 | struct ov13858 *ov13858 = to_ov13858(sd); |
1150 | struct v4l2_mbus_framefmt *try_fmt = v4l2_subdev_state_get_format(fh->state, |
1151 | 0); |
1152 | |
1153 | mutex_lock(&ov13858->mutex); |
1154 | |
1155 | /* Initialize try_fmt */ |
1156 | try_fmt->width = ov13858->cur_mode->width; |
1157 | try_fmt->height = ov13858->cur_mode->height; |
1158 | try_fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10; |
1159 | try_fmt->field = V4L2_FIELD_NONE; |
1160 | |
1161 | /* No crop or compose */ |
1162 | mutex_unlock(lock: &ov13858->mutex); |
1163 | |
1164 | return 0; |
1165 | } |
1166 | |
1167 | static int ov13858_update_digital_gain(struct ov13858 *ov13858, u32 d_gain) |
1168 | { |
1169 | int ret; |
1170 | |
1171 | ret = ov13858_write_reg(ov13858, OV13858_REG_B_MWB_GAIN, |
1172 | OV13858_REG_VALUE_16BIT, val: d_gain); |
1173 | if (ret) |
1174 | return ret; |
1175 | |
1176 | ret = ov13858_write_reg(ov13858, OV13858_REG_G_MWB_GAIN, |
1177 | OV13858_REG_VALUE_16BIT, val: d_gain); |
1178 | if (ret) |
1179 | return ret; |
1180 | |
1181 | ret = ov13858_write_reg(ov13858, OV13858_REG_R_MWB_GAIN, |
1182 | OV13858_REG_VALUE_16BIT, val: d_gain); |
1183 | |
1184 | return ret; |
1185 | } |
1186 | |
1187 | static int ov13858_enable_test_pattern(struct ov13858 *ov13858, u32 pattern) |
1188 | { |
1189 | int ret; |
1190 | u32 val; |
1191 | |
1192 | ret = ov13858_read_reg(ov13858, OV13858_REG_TEST_PATTERN, |
1193 | OV13858_REG_VALUE_08BIT, val: &val); |
1194 | if (ret) |
1195 | return ret; |
1196 | |
1197 | if (pattern) { |
1198 | val &= OV13858_TEST_PATTERN_MASK; |
1199 | val |= (pattern - 1) | OV13858_TEST_PATTERN_ENABLE; |
1200 | } else { |
1201 | val &= ~OV13858_TEST_PATTERN_ENABLE; |
1202 | } |
1203 | |
1204 | return ov13858_write_reg(ov13858, OV13858_REG_TEST_PATTERN, |
1205 | OV13858_REG_VALUE_08BIT, val: val); |
1206 | } |
1207 | |
1208 | static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl) |
1209 | { |
1210 | struct ov13858 *ov13858 = container_of(ctrl->handler, |
1211 | struct ov13858, ctrl_handler); |
1212 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov13858->sd); |
1213 | s64 max; |
1214 | int ret; |
1215 | |
1216 | /* Propagate change of current control to all related controls */ |
1217 | switch (ctrl->id) { |
1218 | case V4L2_CID_VBLANK: |
1219 | /* Update max exposure while meeting expected vblanking */ |
1220 | max = ov13858->cur_mode->height + ctrl->val - 8; |
1221 | __v4l2_ctrl_modify_range(ctrl: ov13858->exposure, |
1222 | min: ov13858->exposure->minimum, |
1223 | max, step: ov13858->exposure->step, def: max); |
1224 | break; |
1225 | } |
1226 | |
1227 | /* |
1228 | * Applying V4L2 control value only happens |
1229 | * when power is up for streaming |
1230 | */ |
1231 | if (!pm_runtime_get_if_in_use(dev: &client->dev)) |
1232 | return 0; |
1233 | |
1234 | ret = 0; |
1235 | switch (ctrl->id) { |
1236 | case V4L2_CID_ANALOGUE_GAIN: |
1237 | ret = ov13858_write_reg(ov13858, OV13858_REG_ANALOG_GAIN, |
1238 | OV13858_REG_VALUE_16BIT, val: ctrl->val); |
1239 | break; |
1240 | case V4L2_CID_DIGITAL_GAIN: |
1241 | ret = ov13858_update_digital_gain(ov13858, d_gain: ctrl->val); |
1242 | break; |
1243 | case V4L2_CID_EXPOSURE: |
1244 | ret = ov13858_write_reg(ov13858, OV13858_REG_EXPOSURE, |
1245 | OV13858_REG_VALUE_24BIT, |
1246 | val: ctrl->val << 4); |
1247 | break; |
1248 | case V4L2_CID_VBLANK: |
1249 | /* Update VTS that meets expected vertical blanking */ |
1250 | ret = ov13858_write_reg(ov13858, OV13858_REG_VTS, |
1251 | OV13858_REG_VALUE_16BIT, |
1252 | val: ov13858->cur_mode->height |
1253 | + ctrl->val); |
1254 | break; |
1255 | case V4L2_CID_TEST_PATTERN: |
1256 | ret = ov13858_enable_test_pattern(ov13858, pattern: ctrl->val); |
1257 | break; |
1258 | default: |
1259 | dev_info(&client->dev, |
1260 | "ctrl(id:0x%x,val:0x%x) is not handled\n" , |
1261 | ctrl->id, ctrl->val); |
1262 | break; |
1263 | } |
1264 | |
1265 | pm_runtime_put(dev: &client->dev); |
1266 | |
1267 | return ret; |
1268 | } |
1269 | |
1270 | static const struct v4l2_ctrl_ops ov13858_ctrl_ops = { |
1271 | .s_ctrl = ov13858_set_ctrl, |
1272 | }; |
1273 | |
1274 | static int ov13858_enum_mbus_code(struct v4l2_subdev *sd, |
1275 | struct v4l2_subdev_state *sd_state, |
1276 | struct v4l2_subdev_mbus_code_enum *code) |
1277 | { |
1278 | /* Only one bayer order(GRBG) is supported */ |
1279 | if (code->index > 0) |
1280 | return -EINVAL; |
1281 | |
1282 | code->code = MEDIA_BUS_FMT_SGRBG10_1X10; |
1283 | |
1284 | return 0; |
1285 | } |
1286 | |
1287 | static int ov13858_enum_frame_size(struct v4l2_subdev *sd, |
1288 | struct v4l2_subdev_state *sd_state, |
1289 | struct v4l2_subdev_frame_size_enum *fse) |
1290 | { |
1291 | if (fse->index >= ARRAY_SIZE(supported_modes)) |
1292 | return -EINVAL; |
1293 | |
1294 | if (fse->code != MEDIA_BUS_FMT_SGRBG10_1X10) |
1295 | return -EINVAL; |
1296 | |
1297 | fse->min_width = supported_modes[fse->index].width; |
1298 | fse->max_width = fse->min_width; |
1299 | fse->min_height = supported_modes[fse->index].height; |
1300 | fse->max_height = fse->min_height; |
1301 | |
1302 | return 0; |
1303 | } |
1304 | |
1305 | static void ov13858_update_pad_format(const struct ov13858_mode *mode, |
1306 | struct v4l2_subdev_format *fmt) |
1307 | { |
1308 | fmt->format.width = mode->width; |
1309 | fmt->format.height = mode->height; |
1310 | fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10; |
1311 | fmt->format.field = V4L2_FIELD_NONE; |
1312 | } |
1313 | |
1314 | static int ov13858_do_get_pad_format(struct ov13858 *ov13858, |
1315 | struct v4l2_subdev_state *sd_state, |
1316 | struct v4l2_subdev_format *fmt) |
1317 | { |
1318 | struct v4l2_mbus_framefmt *framefmt; |
1319 | |
1320 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
1321 | framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); |
1322 | fmt->format = *framefmt; |
1323 | } else { |
1324 | ov13858_update_pad_format(mode: ov13858->cur_mode, fmt); |
1325 | } |
1326 | |
1327 | return 0; |
1328 | } |
1329 | |
1330 | static int ov13858_get_pad_format(struct v4l2_subdev *sd, |
1331 | struct v4l2_subdev_state *sd_state, |
1332 | struct v4l2_subdev_format *fmt) |
1333 | { |
1334 | struct ov13858 *ov13858 = to_ov13858(sd); |
1335 | int ret; |
1336 | |
1337 | mutex_lock(&ov13858->mutex); |
1338 | ret = ov13858_do_get_pad_format(ov13858, sd_state, fmt); |
1339 | mutex_unlock(lock: &ov13858->mutex); |
1340 | |
1341 | return ret; |
1342 | } |
1343 | |
1344 | static int |
1345 | ov13858_set_pad_format(struct v4l2_subdev *sd, |
1346 | struct v4l2_subdev_state *sd_state, |
1347 | struct v4l2_subdev_format *fmt) |
1348 | { |
1349 | struct ov13858 *ov13858 = to_ov13858(sd); |
1350 | const struct ov13858_mode *mode; |
1351 | struct v4l2_mbus_framefmt *framefmt; |
1352 | s32 vblank_def; |
1353 | s32 vblank_min; |
1354 | s64 h_blank; |
1355 | s64 pixel_rate; |
1356 | s64 link_freq; |
1357 | |
1358 | mutex_lock(&ov13858->mutex); |
1359 | |
1360 | /* Only one raw bayer(GRBG) order is supported */ |
1361 | if (fmt->format.code != MEDIA_BUS_FMT_SGRBG10_1X10) |
1362 | fmt->format.code = MEDIA_BUS_FMT_SGRBG10_1X10; |
1363 | |
1364 | mode = v4l2_find_nearest_size(supported_modes, |
1365 | ARRAY_SIZE(supported_modes), |
1366 | width, height, |
1367 | fmt->format.width, fmt->format.height); |
1368 | ov13858_update_pad_format(mode, fmt); |
1369 | if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { |
1370 | framefmt = v4l2_subdev_state_get_format(sd_state, fmt->pad); |
1371 | *framefmt = fmt->format; |
1372 | } else { |
1373 | ov13858->cur_mode = mode; |
1374 | __v4l2_ctrl_s_ctrl(ctrl: ov13858->link_freq, val: mode->link_freq_index); |
1375 | link_freq = link_freq_menu_items[mode->link_freq_index]; |
1376 | pixel_rate = link_freq_to_pixel_rate(f: link_freq); |
1377 | __v4l2_ctrl_s_ctrl_int64(ctrl: ov13858->pixel_rate, val: pixel_rate); |
1378 | |
1379 | /* Update limits and set FPS to default */ |
1380 | vblank_def = ov13858->cur_mode->vts_def - |
1381 | ov13858->cur_mode->height; |
1382 | vblank_min = ov13858->cur_mode->vts_min - |
1383 | ov13858->cur_mode->height; |
1384 | __v4l2_ctrl_modify_range( |
1385 | ctrl: ov13858->vblank, min: vblank_min, |
1386 | OV13858_VTS_MAX - ov13858->cur_mode->height, step: 1, |
1387 | def: vblank_def); |
1388 | __v4l2_ctrl_s_ctrl(ctrl: ov13858->vblank, val: vblank_def); |
1389 | h_blank = |
1390 | link_freq_configs[mode->link_freq_index].pixels_per_line |
1391 | - ov13858->cur_mode->width; |
1392 | __v4l2_ctrl_modify_range(ctrl: ov13858->hblank, min: h_blank, |
1393 | max: h_blank, step: 1, def: h_blank); |
1394 | } |
1395 | |
1396 | mutex_unlock(lock: &ov13858->mutex); |
1397 | |
1398 | return 0; |
1399 | } |
1400 | |
1401 | static int ov13858_get_skip_frames(struct v4l2_subdev *sd, u32 *frames) |
1402 | { |
1403 | *frames = OV13858_NUM_OF_SKIP_FRAMES; |
1404 | |
1405 | return 0; |
1406 | } |
1407 | |
1408 | /* Start streaming */ |
1409 | static int ov13858_start_streaming(struct ov13858 *ov13858) |
1410 | { |
1411 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov13858->sd); |
1412 | const struct ov13858_reg_list *reg_list; |
1413 | int ret, link_freq_index; |
1414 | |
1415 | /* Get out of from software reset */ |
1416 | ret = ov13858_write_reg(ov13858, OV13858_REG_SOFTWARE_RST, |
1417 | OV13858_REG_VALUE_08BIT, OV13858_SOFTWARE_RST); |
1418 | if (ret) { |
1419 | dev_err(&client->dev, "%s failed to set powerup registers\n" , |
1420 | __func__); |
1421 | return ret; |
1422 | } |
1423 | |
1424 | /* Setup PLL */ |
1425 | link_freq_index = ov13858->cur_mode->link_freq_index; |
1426 | reg_list = &link_freq_configs[link_freq_index].reg_list; |
1427 | ret = ov13858_write_reg_list(ov13858, r_list: reg_list); |
1428 | if (ret) { |
1429 | dev_err(&client->dev, "%s failed to set plls\n" , __func__); |
1430 | return ret; |
1431 | } |
1432 | |
1433 | /* Apply default values of current mode */ |
1434 | reg_list = &ov13858->cur_mode->reg_list; |
1435 | ret = ov13858_write_reg_list(ov13858, r_list: reg_list); |
1436 | if (ret) { |
1437 | dev_err(&client->dev, "%s failed to set mode\n" , __func__); |
1438 | return ret; |
1439 | } |
1440 | |
1441 | /* Apply customized values from user */ |
1442 | ret = __v4l2_ctrl_handler_setup(hdl: ov13858->sd.ctrl_handler); |
1443 | if (ret) |
1444 | return ret; |
1445 | |
1446 | return ov13858_write_reg(ov13858, OV13858_REG_MODE_SELECT, |
1447 | OV13858_REG_VALUE_08BIT, |
1448 | OV13858_MODE_STREAMING); |
1449 | } |
1450 | |
1451 | /* Stop streaming */ |
1452 | static int ov13858_stop_streaming(struct ov13858 *ov13858) |
1453 | { |
1454 | return ov13858_write_reg(ov13858, OV13858_REG_MODE_SELECT, |
1455 | OV13858_REG_VALUE_08BIT, OV13858_MODE_STANDBY); |
1456 | } |
1457 | |
1458 | static int ov13858_set_stream(struct v4l2_subdev *sd, int enable) |
1459 | { |
1460 | struct ov13858 *ov13858 = to_ov13858(sd); |
1461 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1462 | int ret = 0; |
1463 | |
1464 | mutex_lock(&ov13858->mutex); |
1465 | |
1466 | if (enable) { |
1467 | ret = pm_runtime_resume_and_get(dev: &client->dev); |
1468 | if (ret < 0) |
1469 | goto err_unlock; |
1470 | |
1471 | /* |
1472 | * Apply default & customized values |
1473 | * and then start streaming. |
1474 | */ |
1475 | ret = ov13858_start_streaming(ov13858); |
1476 | if (ret) |
1477 | goto err_rpm_put; |
1478 | } else { |
1479 | ov13858_stop_streaming(ov13858); |
1480 | pm_runtime_put(dev: &client->dev); |
1481 | } |
1482 | |
1483 | mutex_unlock(lock: &ov13858->mutex); |
1484 | |
1485 | return ret; |
1486 | |
1487 | err_rpm_put: |
1488 | pm_runtime_put(dev: &client->dev); |
1489 | err_unlock: |
1490 | mutex_unlock(lock: &ov13858->mutex); |
1491 | |
1492 | return ret; |
1493 | } |
1494 | |
1495 | /* Verify chip ID */ |
1496 | static int ov13858_identify_module(struct ov13858 *ov13858) |
1497 | { |
1498 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov13858->sd); |
1499 | int ret; |
1500 | u32 val; |
1501 | |
1502 | ret = ov13858_read_reg(ov13858, OV13858_REG_CHIP_ID, |
1503 | OV13858_REG_VALUE_24BIT, val: &val); |
1504 | if (ret) |
1505 | return ret; |
1506 | |
1507 | if (val != OV13858_CHIP_ID) { |
1508 | dev_err(&client->dev, "chip id mismatch: %x!=%x\n" , |
1509 | OV13858_CHIP_ID, val); |
1510 | return -EIO; |
1511 | } |
1512 | |
1513 | return 0; |
1514 | } |
1515 | |
1516 | static const struct v4l2_subdev_core_ops ov13858_core_ops = { |
1517 | .log_status = v4l2_ctrl_subdev_log_status, |
1518 | .subscribe_event = v4l2_ctrl_subdev_subscribe_event, |
1519 | .unsubscribe_event = v4l2_event_subdev_unsubscribe, |
1520 | }; |
1521 | |
1522 | static const struct v4l2_subdev_video_ops ov13858_video_ops = { |
1523 | .s_stream = ov13858_set_stream, |
1524 | }; |
1525 | |
1526 | static const struct v4l2_subdev_pad_ops ov13858_pad_ops = { |
1527 | .enum_mbus_code = ov13858_enum_mbus_code, |
1528 | .get_fmt = ov13858_get_pad_format, |
1529 | .set_fmt = ov13858_set_pad_format, |
1530 | .enum_frame_size = ov13858_enum_frame_size, |
1531 | }; |
1532 | |
1533 | static const struct v4l2_subdev_sensor_ops ov13858_sensor_ops = { |
1534 | .g_skip_frames = ov13858_get_skip_frames, |
1535 | }; |
1536 | |
1537 | static const struct v4l2_subdev_ops ov13858_subdev_ops = { |
1538 | .core = &ov13858_core_ops, |
1539 | .video = &ov13858_video_ops, |
1540 | .pad = &ov13858_pad_ops, |
1541 | .sensor = &ov13858_sensor_ops, |
1542 | }; |
1543 | |
1544 | static const struct media_entity_operations ov13858_subdev_entity_ops = { |
1545 | .link_validate = v4l2_subdev_link_validate, |
1546 | }; |
1547 | |
1548 | static const struct v4l2_subdev_internal_ops ov13858_internal_ops = { |
1549 | .open = ov13858_open, |
1550 | }; |
1551 | |
1552 | /* Initialize control handlers */ |
1553 | static int ov13858_init_controls(struct ov13858 *ov13858) |
1554 | { |
1555 | struct i2c_client *client = v4l2_get_subdevdata(sd: &ov13858->sd); |
1556 | struct v4l2_fwnode_device_properties props; |
1557 | struct v4l2_ctrl_handler *ctrl_hdlr; |
1558 | s64 exposure_max; |
1559 | s64 vblank_def; |
1560 | s64 vblank_min; |
1561 | s64 hblank; |
1562 | s64 pixel_rate_min; |
1563 | s64 pixel_rate_max; |
1564 | const struct ov13858_mode *mode; |
1565 | int ret; |
1566 | |
1567 | ctrl_hdlr = &ov13858->ctrl_handler; |
1568 | ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10); |
1569 | if (ret) |
1570 | return ret; |
1571 | |
1572 | mutex_init(&ov13858->mutex); |
1573 | ctrl_hdlr->lock = &ov13858->mutex; |
1574 | ov13858->link_freq = v4l2_ctrl_new_int_menu(hdl: ctrl_hdlr, |
1575 | ops: &ov13858_ctrl_ops, |
1576 | V4L2_CID_LINK_FREQ, |
1577 | OV13858_NUM_OF_LINK_FREQS - 1, |
1578 | def: 0, |
1579 | qmenu_int: link_freq_menu_items); |
1580 | if (ov13858->link_freq) |
1581 | ov13858->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
1582 | |
1583 | pixel_rate_max = link_freq_to_pixel_rate(f: link_freq_menu_items[0]); |
1584 | pixel_rate_min = link_freq_to_pixel_rate(f: link_freq_menu_items[1]); |
1585 | /* By default, PIXEL_RATE is read only */ |
1586 | ov13858->pixel_rate = v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov13858_ctrl_ops, |
1587 | V4L2_CID_PIXEL_RATE, |
1588 | min: pixel_rate_min, max: pixel_rate_max, |
1589 | step: 1, def: pixel_rate_max); |
1590 | |
1591 | mode = ov13858->cur_mode; |
1592 | vblank_def = mode->vts_def - mode->height; |
1593 | vblank_min = mode->vts_min - mode->height; |
1594 | ov13858->vblank = v4l2_ctrl_new_std( |
1595 | hdl: ctrl_hdlr, ops: &ov13858_ctrl_ops, V4L2_CID_VBLANK, |
1596 | min: vblank_min, OV13858_VTS_MAX - mode->height, step: 1, |
1597 | def: vblank_def); |
1598 | |
1599 | hblank = link_freq_configs[mode->link_freq_index].pixels_per_line - |
1600 | mode->width; |
1601 | ov13858->hblank = v4l2_ctrl_new_std( |
1602 | hdl: ctrl_hdlr, ops: &ov13858_ctrl_ops, V4L2_CID_HBLANK, |
1603 | min: hblank, max: hblank, step: 1, def: hblank); |
1604 | if (ov13858->hblank) |
1605 | ov13858->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
1606 | |
1607 | exposure_max = mode->vts_def - 8; |
1608 | ov13858->exposure = v4l2_ctrl_new_std( |
1609 | hdl: ctrl_hdlr, ops: &ov13858_ctrl_ops, |
1610 | V4L2_CID_EXPOSURE, OV13858_EXPOSURE_MIN, |
1611 | max: exposure_max, OV13858_EXPOSURE_STEP, |
1612 | OV13858_EXPOSURE_DEFAULT); |
1613 | |
1614 | v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov13858_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, |
1615 | OV13858_ANA_GAIN_MIN, OV13858_ANA_GAIN_MAX, |
1616 | OV13858_ANA_GAIN_STEP, OV13858_ANA_GAIN_DEFAULT); |
1617 | |
1618 | /* Digital gain */ |
1619 | v4l2_ctrl_new_std(hdl: ctrl_hdlr, ops: &ov13858_ctrl_ops, V4L2_CID_DIGITAL_GAIN, |
1620 | OV13858_DGTL_GAIN_MIN, OV13858_DGTL_GAIN_MAX, |
1621 | OV13858_DGTL_GAIN_STEP, OV13858_DGTL_GAIN_DEFAULT); |
1622 | |
1623 | v4l2_ctrl_new_std_menu_items(hdl: ctrl_hdlr, ops: &ov13858_ctrl_ops, |
1624 | V4L2_CID_TEST_PATTERN, |
1625 | ARRAY_SIZE(ov13858_test_pattern_menu) - 1, |
1626 | mask: 0, def: 0, qmenu: ov13858_test_pattern_menu); |
1627 | if (ctrl_hdlr->error) { |
1628 | ret = ctrl_hdlr->error; |
1629 | dev_err(&client->dev, "%s control init failed (%d)\n" , |
1630 | __func__, ret); |
1631 | goto error; |
1632 | } |
1633 | |
1634 | ret = v4l2_fwnode_device_parse(dev: &client->dev, props: &props); |
1635 | if (ret) |
1636 | goto error; |
1637 | |
1638 | ret = v4l2_ctrl_new_fwnode_properties(hdl: ctrl_hdlr, ctrl_ops: &ov13858_ctrl_ops, |
1639 | p: &props); |
1640 | if (ret) |
1641 | goto error; |
1642 | |
1643 | ov13858->sd.ctrl_handler = ctrl_hdlr; |
1644 | |
1645 | return 0; |
1646 | |
1647 | error: |
1648 | v4l2_ctrl_handler_free(hdl: ctrl_hdlr); |
1649 | mutex_destroy(lock: &ov13858->mutex); |
1650 | |
1651 | return ret; |
1652 | } |
1653 | |
1654 | static void ov13858_free_controls(struct ov13858 *ov13858) |
1655 | { |
1656 | v4l2_ctrl_handler_free(hdl: ov13858->sd.ctrl_handler); |
1657 | mutex_destroy(lock: &ov13858->mutex); |
1658 | } |
1659 | |
1660 | static int ov13858_probe(struct i2c_client *client) |
1661 | { |
1662 | struct ov13858 *ov13858; |
1663 | int ret; |
1664 | u32 val = 0; |
1665 | |
1666 | device_property_read_u32(dev: &client->dev, propname: "clock-frequency" , val: &val); |
1667 | if (val != 19200000) |
1668 | return -EINVAL; |
1669 | |
1670 | ov13858 = devm_kzalloc(dev: &client->dev, size: sizeof(*ov13858), GFP_KERNEL); |
1671 | if (!ov13858) |
1672 | return -ENOMEM; |
1673 | |
1674 | /* Initialize subdev */ |
1675 | v4l2_i2c_subdev_init(sd: &ov13858->sd, client, ops: &ov13858_subdev_ops); |
1676 | |
1677 | /* Check module identity */ |
1678 | ret = ov13858_identify_module(ov13858); |
1679 | if (ret) { |
1680 | dev_err(&client->dev, "failed to find sensor: %d\n" , ret); |
1681 | return ret; |
1682 | } |
1683 | |
1684 | /* Set default mode to max resolution */ |
1685 | ov13858->cur_mode = &supported_modes[0]; |
1686 | |
1687 | ret = ov13858_init_controls(ov13858); |
1688 | if (ret) |
1689 | return ret; |
1690 | |
1691 | /* Initialize subdev */ |
1692 | ov13858->sd.internal_ops = &ov13858_internal_ops; |
1693 | ov13858->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | |
1694 | V4L2_SUBDEV_FL_HAS_EVENTS; |
1695 | ov13858->sd.entity.ops = &ov13858_subdev_entity_ops; |
1696 | ov13858->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
1697 | |
1698 | /* Initialize source pad */ |
1699 | ov13858->pad.flags = MEDIA_PAD_FL_SOURCE; |
1700 | ret = media_entity_pads_init(entity: &ov13858->sd.entity, num_pads: 1, pads: &ov13858->pad); |
1701 | if (ret) { |
1702 | dev_err(&client->dev, "%s failed:%d\n" , __func__, ret); |
1703 | goto error_handler_free; |
1704 | } |
1705 | |
1706 | ret = v4l2_async_register_subdev_sensor(sd: &ov13858->sd); |
1707 | if (ret < 0) |
1708 | goto error_media_entity; |
1709 | |
1710 | /* |
1711 | * Device is already turned on by i2c-core with ACPI domain PM. |
1712 | * Enable runtime PM and turn off the device. |
1713 | */ |
1714 | pm_runtime_set_active(dev: &client->dev); |
1715 | pm_runtime_enable(dev: &client->dev); |
1716 | pm_runtime_idle(dev: &client->dev); |
1717 | |
1718 | return 0; |
1719 | |
1720 | error_media_entity: |
1721 | media_entity_cleanup(entity: &ov13858->sd.entity); |
1722 | |
1723 | error_handler_free: |
1724 | ov13858_free_controls(ov13858); |
1725 | dev_err(&client->dev, "%s failed:%d\n" , __func__, ret); |
1726 | |
1727 | return ret; |
1728 | } |
1729 | |
1730 | static void ov13858_remove(struct i2c_client *client) |
1731 | { |
1732 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
1733 | struct ov13858 *ov13858 = to_ov13858(sd); |
1734 | |
1735 | v4l2_async_unregister_subdev(sd); |
1736 | media_entity_cleanup(entity: &sd->entity); |
1737 | ov13858_free_controls(ov13858); |
1738 | |
1739 | pm_runtime_disable(dev: &client->dev); |
1740 | } |
1741 | |
1742 | static const struct i2c_device_id ov13858_id_table[] = { |
1743 | {"ov13858" , 0}, |
1744 | {}, |
1745 | }; |
1746 | |
1747 | MODULE_DEVICE_TABLE(i2c, ov13858_id_table); |
1748 | |
1749 | #ifdef CONFIG_ACPI |
1750 | static const struct acpi_device_id ov13858_acpi_ids[] = { |
1751 | {"OVTID858" }, |
1752 | { /* sentinel */ } |
1753 | }; |
1754 | |
1755 | MODULE_DEVICE_TABLE(acpi, ov13858_acpi_ids); |
1756 | #endif |
1757 | |
1758 | static struct i2c_driver ov13858_i2c_driver = { |
1759 | .driver = { |
1760 | .name = "ov13858" , |
1761 | .acpi_match_table = ACPI_PTR(ov13858_acpi_ids), |
1762 | }, |
1763 | .probe = ov13858_probe, |
1764 | .remove = ov13858_remove, |
1765 | .id_table = ov13858_id_table, |
1766 | }; |
1767 | |
1768 | module_i2c_driver(ov13858_i2c_driver); |
1769 | |
1770 | MODULE_AUTHOR("Kan, Chris <chris.kan@intel.com>" ); |
1771 | MODULE_AUTHOR("Rapolu, Chiranjeevi" ); |
1772 | MODULE_AUTHOR("Yang, Hyungwoo" ); |
1773 | MODULE_DESCRIPTION("Omnivision ov13858 sensor driver" ); |
1774 | MODULE_LICENSE("GPL v2" ); |
1775 | |