1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Driver for the OV7251 camera sensor. |
4 | * |
5 | * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. |
6 | * Copyright (c) 2017-2018, Linaro Ltd. |
7 | */ |
8 | |
9 | #include <linux/bitops.h> |
10 | #include <linux/clk.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/device.h> |
13 | #include <linux/gpio/consumer.h> |
14 | #include <linux/i2c.h> |
15 | #include <linux/init.h> |
16 | #include <linux/module.h> |
17 | #include <linux/mod_devicetable.h> |
18 | #include <linux/pm_runtime.h> |
19 | #include <linux/regulator/consumer.h> |
20 | #include <linux/slab.h> |
21 | #include <linux/types.h> |
22 | #include <media/v4l2-ctrls.h> |
23 | #include <media/v4l2-fwnode.h> |
24 | #include <media/v4l2-subdev.h> |
25 | |
26 | #define OV7251_SC_MODE_SELECT 0x0100 |
27 | #define OV7251_SC_MODE_SELECT_SW_STANDBY 0x0 |
28 | #define OV7251_SC_MODE_SELECT_STREAMING 0x1 |
29 | |
30 | #define OV7251_CHIP_ID_HIGH 0x300a |
31 | #define OV7251_CHIP_ID_HIGH_BYTE 0x77 |
32 | #define OV7251_CHIP_ID_LOW 0x300b |
33 | #define OV7251_CHIP_ID_LOW_BYTE 0x50 |
34 | #define OV7251_SC_GP_IO_IN1 0x3029 |
35 | #define OV7251_AEC_EXPO_0 0x3500 |
36 | #define OV7251_AEC_EXPO_1 0x3501 |
37 | #define OV7251_AEC_EXPO_2 0x3502 |
38 | #define OV7251_AEC_AGC_ADJ_0 0x350a |
39 | #define OV7251_AEC_AGC_ADJ_1 0x350b |
40 | #define OV7251_TIMING_FORMAT1 0x3820 |
41 | #define OV7251_TIMING_FORMAT1_VFLIP BIT(2) |
42 | #define OV7251_TIMING_FORMAT2 0x3821 |
43 | #define OV7251_TIMING_FORMAT2_MIRROR BIT(2) |
44 | #define OV7251_PRE_ISP_00 0x5e00 |
45 | #define OV7251_PRE_ISP_00_TEST_PATTERN BIT(7) |
46 | #define OV7251_PLL1_PRE_DIV_REG 0x30b4 |
47 | #define OV7251_PLL1_MULT_REG 0x30b3 |
48 | #define OV7251_PLL1_DIVIDER_REG 0x30b1 |
49 | #define OV7251_PLL1_PIX_DIV_REG 0x30b0 |
50 | #define OV7251_PLL1_MIPI_DIV_REG 0x30b5 |
51 | #define OV7251_PLL2_PRE_DIV_REG 0x3098 |
52 | #define OV7251_PLL2_MULT_REG 0x3099 |
53 | #define OV7251_PLL2_DIVIDER_REG 0x309d |
54 | #define OV7251_PLL2_SYS_DIV_REG 0x309a |
55 | #define OV7251_PLL2_ADC_DIV_REG 0x309b |
56 | |
57 | #define OV7251_NATIVE_WIDTH 656 |
58 | #define OV7251_NATIVE_HEIGHT 496 |
59 | #define OV7251_ACTIVE_START_LEFT 4 |
60 | #define OV7251_ACTIVE_START_TOP 4 |
61 | #define OV7251_ACTIVE_WIDTH 648 |
62 | #define OV7251_ACTIVE_HEIGHT 488 |
63 | |
64 | #define OV7251_FIXED_PPL 928 |
65 | #define OV7251_TIMING_VTS_REG 0x380e |
66 | #define OV7251_TIMING_MIN_VTS 1 |
67 | #define OV7251_TIMING_MAX_VTS 0xffff |
68 | #define OV7251_INTEGRATION_MARGIN 20 |
69 | |
70 | struct reg_value { |
71 | u16 reg; |
72 | u8 val; |
73 | }; |
74 | |
75 | struct ov7251_mode_info { |
76 | u32 width; |
77 | u32 height; |
78 | u32 vts; |
79 | const struct reg_value *data; |
80 | u32 data_size; |
81 | u32 pixel_clock; |
82 | u32 link_freq; |
83 | u16 exposure_max; |
84 | u16 exposure_def; |
85 | struct v4l2_fract timeperframe; |
86 | }; |
87 | |
88 | struct ov7251_pll1_cfg { |
89 | unsigned int pre_div; |
90 | unsigned int mult; |
91 | unsigned int div; |
92 | unsigned int pix_div; |
93 | unsigned int mipi_div; |
94 | }; |
95 | |
96 | struct ov7251_pll2_cfg { |
97 | unsigned int pre_div; |
98 | unsigned int mult; |
99 | unsigned int div; |
100 | unsigned int sys_div; |
101 | unsigned int adc_div; |
102 | }; |
103 | |
104 | /* |
105 | * Rubbish ordering, but only PLL1 needs to have a separate configuration per |
106 | * link frequency and the array member needs to be last. |
107 | */ |
108 | struct ov7251_pll_cfgs { |
109 | const struct ov7251_pll2_cfg *pll2; |
110 | const struct ov7251_pll1_cfg *pll1[]; |
111 | }; |
112 | |
113 | enum xclk_rate { |
114 | OV7251_19_2_MHZ, |
115 | OV7251_24_MHZ, |
116 | OV7251_NUM_SUPPORTED_RATES |
117 | }; |
118 | |
119 | enum supported_link_freqs { |
120 | OV7251_LINK_FREQ_240_MHZ, |
121 | OV7251_LINK_FREQ_319_2_MHZ, |
122 | OV7251_NUM_SUPPORTED_LINK_FREQS |
123 | }; |
124 | |
125 | struct ov7251 { |
126 | struct i2c_client *i2c_client; |
127 | struct device *dev; |
128 | struct v4l2_subdev sd; |
129 | struct media_pad pad; |
130 | struct v4l2_fwnode_endpoint ep; |
131 | struct v4l2_mbus_framefmt fmt; |
132 | struct v4l2_rect crop; |
133 | struct clk *xclk; |
134 | u32 xclk_freq; |
135 | |
136 | struct regulator *io_regulator; |
137 | struct regulator *core_regulator; |
138 | struct regulator *analog_regulator; |
139 | |
140 | const struct ov7251_pll_cfgs *pll_cfgs; |
141 | enum supported_link_freqs link_freq_idx; |
142 | const struct ov7251_mode_info *current_mode; |
143 | |
144 | struct v4l2_ctrl_handler ctrls; |
145 | struct v4l2_ctrl *pixel_clock; |
146 | struct v4l2_ctrl *link_freq; |
147 | struct v4l2_ctrl *exposure; |
148 | struct v4l2_ctrl *gain; |
149 | struct v4l2_ctrl *hblank; |
150 | struct v4l2_ctrl *vblank; |
151 | |
152 | /* Cached register values */ |
153 | u8 aec_pk_manual; |
154 | u8 pre_isp_00; |
155 | u8 timing_format1; |
156 | u8 timing_format2; |
157 | |
158 | struct mutex lock; /* lock to protect power state, ctrls and mode */ |
159 | bool power_on; |
160 | |
161 | struct gpio_desc *enable_gpio; |
162 | }; |
163 | |
164 | static inline struct ov7251 *to_ov7251(struct v4l2_subdev *sd) |
165 | { |
166 | return container_of(sd, struct ov7251, sd); |
167 | } |
168 | |
169 | static const struct ov7251_pll1_cfg ov7251_pll1_cfg_19_2_mhz_240_mhz = { |
170 | .pre_div = 0x03, |
171 | .mult = 0x4b, |
172 | .div = 0x01, |
173 | .pix_div = 0x0a, |
174 | .mipi_div = 0x05, |
175 | }; |
176 | |
177 | static const struct ov7251_pll1_cfg ov7251_pll1_cfg_19_2_mhz_319_2_mhz = { |
178 | .pre_div = 0x01, |
179 | .mult = 0x85, |
180 | .div = 0x04, |
181 | .pix_div = 0x0a, |
182 | .mipi_div = 0x05, |
183 | }; |
184 | |
185 | static const struct ov7251_pll1_cfg ov7251_pll1_cfg_24_mhz_240_mhz = { |
186 | .pre_div = 0x03, |
187 | .mult = 0x64, |
188 | .div = 0x01, |
189 | .pix_div = 0x0a, |
190 | .mipi_div = 0x05, |
191 | }; |
192 | |
193 | static const struct ov7251_pll1_cfg ov7251_pll1_cfg_24_mhz_319_2_mhz = { |
194 | .pre_div = 0x05, |
195 | .mult = 0x85, |
196 | .div = 0x02, |
197 | .pix_div = 0x0a, |
198 | .mipi_div = 0x05, |
199 | }; |
200 | |
201 | static const struct ov7251_pll2_cfg ov7251_pll2_cfg_19_2_mhz = { |
202 | .pre_div = 0x04, |
203 | .mult = 0x32, |
204 | .div = 0x00, |
205 | .sys_div = 0x05, |
206 | .adc_div = 0x04, |
207 | }; |
208 | |
209 | static const struct ov7251_pll2_cfg ov7251_pll2_cfg_24_mhz = { |
210 | .pre_div = 0x04, |
211 | .mult = 0x28, |
212 | .div = 0x00, |
213 | .sys_div = 0x05, |
214 | .adc_div = 0x04, |
215 | }; |
216 | |
217 | static const struct ov7251_pll_cfgs ov7251_pll_cfgs_19_2_mhz = { |
218 | .pll2 = &ov7251_pll2_cfg_19_2_mhz, |
219 | .pll1 = { |
220 | [OV7251_LINK_FREQ_240_MHZ] = &ov7251_pll1_cfg_19_2_mhz_240_mhz, |
221 | [OV7251_LINK_FREQ_319_2_MHZ] = &ov7251_pll1_cfg_19_2_mhz_319_2_mhz, |
222 | }, |
223 | }; |
224 | |
225 | static const struct ov7251_pll_cfgs ov7251_pll_cfgs_24_mhz = { |
226 | .pll2 = &ov7251_pll2_cfg_24_mhz, |
227 | .pll1 = { |
228 | [OV7251_LINK_FREQ_240_MHZ] = &ov7251_pll1_cfg_24_mhz_240_mhz, |
229 | [OV7251_LINK_FREQ_319_2_MHZ] = &ov7251_pll1_cfg_24_mhz_319_2_mhz, |
230 | }, |
231 | }; |
232 | |
233 | static const struct ov7251_pll_cfgs *ov7251_pll_cfgs[] = { |
234 | [OV7251_19_2_MHZ] = &ov7251_pll_cfgs_19_2_mhz, |
235 | [OV7251_24_MHZ] = &ov7251_pll_cfgs_24_mhz, |
236 | }; |
237 | |
238 | static const struct reg_value ov7251_global_init_setting[] = { |
239 | { 0x0103, 0x01 }, |
240 | { 0x303b, 0x02 }, |
241 | }; |
242 | |
243 | static const struct reg_value ov7251_setting_vga_30fps[] = { |
244 | { 0x3005, 0x00 }, |
245 | { 0x3012, 0xc0 }, |
246 | { 0x3013, 0xd2 }, |
247 | { 0x3014, 0x04 }, |
248 | { 0x3016, 0xf0 }, |
249 | { 0x3017, 0xf0 }, |
250 | { 0x3018, 0xf0 }, |
251 | { 0x301a, 0xf0 }, |
252 | { 0x301b, 0xf0 }, |
253 | { 0x301c, 0xf0 }, |
254 | { 0x3023, 0x05 }, |
255 | { 0x3037, 0xf0 }, |
256 | { 0x3106, 0xda }, |
257 | { 0x3503, 0x07 }, |
258 | { 0x3509, 0x10 }, |
259 | { 0x3600, 0x1c }, |
260 | { 0x3602, 0x62 }, |
261 | { 0x3620, 0xb7 }, |
262 | { 0x3622, 0x04 }, |
263 | { 0x3626, 0x21 }, |
264 | { 0x3627, 0x30 }, |
265 | { 0x3630, 0x44 }, |
266 | { 0x3631, 0x35 }, |
267 | { 0x3634, 0x60 }, |
268 | { 0x3636, 0x00 }, |
269 | { 0x3662, 0x01 }, |
270 | { 0x3663, 0x70 }, |
271 | { 0x3664, 0x50 }, |
272 | { 0x3666, 0x0a }, |
273 | { 0x3669, 0x1a }, |
274 | { 0x366a, 0x00 }, |
275 | { 0x366b, 0x50 }, |
276 | { 0x3673, 0x01 }, |
277 | { 0x3674, 0xff }, |
278 | { 0x3675, 0x03 }, |
279 | { 0x3705, 0xc1 }, |
280 | { 0x3709, 0x40 }, |
281 | { 0x373c, 0x08 }, |
282 | { 0x3742, 0x00 }, |
283 | { 0x3757, 0xb3 }, |
284 | { 0x3788, 0x00 }, |
285 | { 0x37a8, 0x01 }, |
286 | { 0x37a9, 0xc0 }, |
287 | { 0x3800, 0x00 }, |
288 | { 0x3801, 0x04 }, |
289 | { 0x3802, 0x00 }, |
290 | { 0x3803, 0x04 }, |
291 | { 0x3804, 0x02 }, |
292 | { 0x3805, 0x8b }, |
293 | { 0x3806, 0x01 }, |
294 | { 0x3807, 0xeb }, |
295 | { 0x3808, 0x02 }, /* width high */ |
296 | { 0x3809, 0x80 }, /* width low */ |
297 | { 0x380a, 0x01 }, /* height high */ |
298 | { 0x380b, 0xe0 }, /* height low */ |
299 | { 0x380c, 0x03 }, /* total horiz timing high */ |
300 | { 0x380d, 0xa0 }, /* total horiz timing low */ |
301 | { 0x380e, 0x06 }, /* total vertical timing high */ |
302 | { 0x380f, 0xbc }, /* total vertical timing low */ |
303 | { 0x3810, 0x00 }, |
304 | { 0x3811, 0x04 }, |
305 | { 0x3812, 0x00 }, |
306 | { 0x3813, 0x05 }, |
307 | { 0x3814, 0x11 }, |
308 | { 0x3815, 0x11 }, |
309 | { 0x3820, 0x40 }, |
310 | { 0x3821, 0x00 }, |
311 | { 0x382f, 0x0e }, |
312 | { 0x3832, 0x00 }, |
313 | { 0x3833, 0x05 }, |
314 | { 0x3834, 0x00 }, |
315 | { 0x3835, 0x0c }, |
316 | { 0x3837, 0x00 }, |
317 | { 0x3b80, 0x00 }, |
318 | { 0x3b81, 0xa5 }, |
319 | { 0x3b82, 0x10 }, |
320 | { 0x3b83, 0x00 }, |
321 | { 0x3b84, 0x08 }, |
322 | { 0x3b85, 0x00 }, |
323 | { 0x3b86, 0x01 }, |
324 | { 0x3b87, 0x00 }, |
325 | { 0x3b88, 0x00 }, |
326 | { 0x3b89, 0x00 }, |
327 | { 0x3b8a, 0x00 }, |
328 | { 0x3b8b, 0x05 }, |
329 | { 0x3b8c, 0x00 }, |
330 | { 0x3b8d, 0x00 }, |
331 | { 0x3b8e, 0x00 }, |
332 | { 0x3b8f, 0x1a }, |
333 | { 0x3b94, 0x05 }, |
334 | { 0x3b95, 0xf2 }, |
335 | { 0x3b96, 0x40 }, |
336 | { 0x3c00, 0x89 }, |
337 | { 0x3c01, 0x63 }, |
338 | { 0x3c02, 0x01 }, |
339 | { 0x3c03, 0x00 }, |
340 | { 0x3c04, 0x00 }, |
341 | { 0x3c05, 0x03 }, |
342 | { 0x3c06, 0x00 }, |
343 | { 0x3c07, 0x06 }, |
344 | { 0x3c0c, 0x01 }, |
345 | { 0x3c0d, 0xd0 }, |
346 | { 0x3c0e, 0x02 }, |
347 | { 0x3c0f, 0x0a }, |
348 | { 0x4001, 0x42 }, |
349 | { 0x4004, 0x04 }, |
350 | { 0x4005, 0x00 }, |
351 | { 0x404e, 0x01 }, |
352 | { 0x4300, 0xff }, |
353 | { 0x4301, 0x00 }, |
354 | { 0x4315, 0x00 }, |
355 | { 0x4501, 0x48 }, |
356 | { 0x4600, 0x00 }, |
357 | { 0x4601, 0x4e }, |
358 | { 0x4801, 0x0f }, |
359 | { 0x4806, 0x0f }, |
360 | { 0x4819, 0xaa }, |
361 | { 0x4823, 0x3e }, |
362 | { 0x4837, 0x19 }, |
363 | { 0x4a0d, 0x00 }, |
364 | { 0x4a47, 0x7f }, |
365 | { 0x4a49, 0xf0 }, |
366 | { 0x4a4b, 0x30 }, |
367 | { 0x5000, 0x85 }, |
368 | { 0x5001, 0x80 }, |
369 | }; |
370 | |
371 | static const struct reg_value ov7251_setting_vga_60fps[] = { |
372 | { 0x3005, 0x00 }, |
373 | { 0x3012, 0xc0 }, |
374 | { 0x3013, 0xd2 }, |
375 | { 0x3014, 0x04 }, |
376 | { 0x3016, 0x10 }, |
377 | { 0x3017, 0x00 }, |
378 | { 0x3018, 0x00 }, |
379 | { 0x301a, 0x00 }, |
380 | { 0x301b, 0x00 }, |
381 | { 0x301c, 0x00 }, |
382 | { 0x3023, 0x05 }, |
383 | { 0x3037, 0xf0 }, |
384 | { 0x3106, 0xda }, |
385 | { 0x3503, 0x07 }, |
386 | { 0x3509, 0x10 }, |
387 | { 0x3600, 0x1c }, |
388 | { 0x3602, 0x62 }, |
389 | { 0x3620, 0xb7 }, |
390 | { 0x3622, 0x04 }, |
391 | { 0x3626, 0x21 }, |
392 | { 0x3627, 0x30 }, |
393 | { 0x3630, 0x44 }, |
394 | { 0x3631, 0x35 }, |
395 | { 0x3634, 0x60 }, |
396 | { 0x3636, 0x00 }, |
397 | { 0x3662, 0x01 }, |
398 | { 0x3663, 0x70 }, |
399 | { 0x3664, 0x50 }, |
400 | { 0x3666, 0x0a }, |
401 | { 0x3669, 0x1a }, |
402 | { 0x366a, 0x00 }, |
403 | { 0x366b, 0x50 }, |
404 | { 0x3673, 0x01 }, |
405 | { 0x3674, 0xff }, |
406 | { 0x3675, 0x03 }, |
407 | { 0x3705, 0xc1 }, |
408 | { 0x3709, 0x40 }, |
409 | { 0x373c, 0x08 }, |
410 | { 0x3742, 0x00 }, |
411 | { 0x3757, 0xb3 }, |
412 | { 0x3788, 0x00 }, |
413 | { 0x37a8, 0x01 }, |
414 | { 0x37a9, 0xc0 }, |
415 | { 0x3800, 0x00 }, |
416 | { 0x3801, 0x04 }, |
417 | { 0x3802, 0x00 }, |
418 | { 0x3803, 0x04 }, |
419 | { 0x3804, 0x02 }, |
420 | { 0x3805, 0x8b }, |
421 | { 0x3806, 0x01 }, |
422 | { 0x3807, 0xeb }, |
423 | { 0x3808, 0x02 }, /* width high */ |
424 | { 0x3809, 0x80 }, /* width low */ |
425 | { 0x380a, 0x01 }, /* height high */ |
426 | { 0x380b, 0xe0 }, /* height low */ |
427 | { 0x380c, 0x03 }, /* total horiz timing high */ |
428 | { 0x380d, 0xa0 }, /* total horiz timing low */ |
429 | { 0x380e, 0x03 }, /* total vertical timing high */ |
430 | { 0x380f, 0x5c }, /* total vertical timing low */ |
431 | { 0x3810, 0x00 }, |
432 | { 0x3811, 0x04 }, |
433 | { 0x3812, 0x00 }, |
434 | { 0x3813, 0x05 }, |
435 | { 0x3814, 0x11 }, |
436 | { 0x3815, 0x11 }, |
437 | { 0x3820, 0x40 }, |
438 | { 0x3821, 0x00 }, |
439 | { 0x382f, 0x0e }, |
440 | { 0x3832, 0x00 }, |
441 | { 0x3833, 0x05 }, |
442 | { 0x3834, 0x00 }, |
443 | { 0x3835, 0x0c }, |
444 | { 0x3837, 0x00 }, |
445 | { 0x3b80, 0x00 }, |
446 | { 0x3b81, 0xa5 }, |
447 | { 0x3b82, 0x10 }, |
448 | { 0x3b83, 0x00 }, |
449 | { 0x3b84, 0x08 }, |
450 | { 0x3b85, 0x00 }, |
451 | { 0x3b86, 0x01 }, |
452 | { 0x3b87, 0x00 }, |
453 | { 0x3b88, 0x00 }, |
454 | { 0x3b89, 0x00 }, |
455 | { 0x3b8a, 0x00 }, |
456 | { 0x3b8b, 0x05 }, |
457 | { 0x3b8c, 0x00 }, |
458 | { 0x3b8d, 0x00 }, |
459 | { 0x3b8e, 0x00 }, |
460 | { 0x3b8f, 0x1a }, |
461 | { 0x3b94, 0x05 }, |
462 | { 0x3b95, 0xf2 }, |
463 | { 0x3b96, 0x40 }, |
464 | { 0x3c00, 0x89 }, |
465 | { 0x3c01, 0x63 }, |
466 | { 0x3c02, 0x01 }, |
467 | { 0x3c03, 0x00 }, |
468 | { 0x3c04, 0x00 }, |
469 | { 0x3c05, 0x03 }, |
470 | { 0x3c06, 0x00 }, |
471 | { 0x3c07, 0x06 }, |
472 | { 0x3c0c, 0x01 }, |
473 | { 0x3c0d, 0xd0 }, |
474 | { 0x3c0e, 0x02 }, |
475 | { 0x3c0f, 0x0a }, |
476 | { 0x4001, 0x42 }, |
477 | { 0x4004, 0x04 }, |
478 | { 0x4005, 0x00 }, |
479 | { 0x404e, 0x01 }, |
480 | { 0x4300, 0xff }, |
481 | { 0x4301, 0x00 }, |
482 | { 0x4315, 0x00 }, |
483 | { 0x4501, 0x48 }, |
484 | { 0x4600, 0x00 }, |
485 | { 0x4601, 0x4e }, |
486 | { 0x4801, 0x0f }, |
487 | { 0x4806, 0x0f }, |
488 | { 0x4819, 0xaa }, |
489 | { 0x4823, 0x3e }, |
490 | { 0x4837, 0x19 }, |
491 | { 0x4a0d, 0x00 }, |
492 | { 0x4a47, 0x7f }, |
493 | { 0x4a49, 0xf0 }, |
494 | { 0x4a4b, 0x30 }, |
495 | { 0x5000, 0x85 }, |
496 | { 0x5001, 0x80 }, |
497 | }; |
498 | |
499 | static const struct reg_value ov7251_setting_vga_90fps[] = { |
500 | { 0x3005, 0x00 }, |
501 | { 0x3012, 0xc0 }, |
502 | { 0x3013, 0xd2 }, |
503 | { 0x3014, 0x04 }, |
504 | { 0x3016, 0x10 }, |
505 | { 0x3017, 0x00 }, |
506 | { 0x3018, 0x00 }, |
507 | { 0x301a, 0x00 }, |
508 | { 0x301b, 0x00 }, |
509 | { 0x301c, 0x00 }, |
510 | { 0x3023, 0x05 }, |
511 | { 0x3037, 0xf0 }, |
512 | { 0x3106, 0xda }, |
513 | { 0x3503, 0x07 }, |
514 | { 0x3509, 0x10 }, |
515 | { 0x3600, 0x1c }, |
516 | { 0x3602, 0x62 }, |
517 | { 0x3620, 0xb7 }, |
518 | { 0x3622, 0x04 }, |
519 | { 0x3626, 0x21 }, |
520 | { 0x3627, 0x30 }, |
521 | { 0x3630, 0x44 }, |
522 | { 0x3631, 0x35 }, |
523 | { 0x3634, 0x60 }, |
524 | { 0x3636, 0x00 }, |
525 | { 0x3662, 0x01 }, |
526 | { 0x3663, 0x70 }, |
527 | { 0x3664, 0x50 }, |
528 | { 0x3666, 0x0a }, |
529 | { 0x3669, 0x1a }, |
530 | { 0x366a, 0x00 }, |
531 | { 0x366b, 0x50 }, |
532 | { 0x3673, 0x01 }, |
533 | { 0x3674, 0xff }, |
534 | { 0x3675, 0x03 }, |
535 | { 0x3705, 0xc1 }, |
536 | { 0x3709, 0x40 }, |
537 | { 0x373c, 0x08 }, |
538 | { 0x3742, 0x00 }, |
539 | { 0x3757, 0xb3 }, |
540 | { 0x3788, 0x00 }, |
541 | { 0x37a8, 0x01 }, |
542 | { 0x37a9, 0xc0 }, |
543 | { 0x3800, 0x00 }, |
544 | { 0x3801, 0x04 }, |
545 | { 0x3802, 0x00 }, |
546 | { 0x3803, 0x04 }, |
547 | { 0x3804, 0x02 }, |
548 | { 0x3805, 0x8b }, |
549 | { 0x3806, 0x01 }, |
550 | { 0x3807, 0xeb }, |
551 | { 0x3808, 0x02 }, /* width high */ |
552 | { 0x3809, 0x80 }, /* width low */ |
553 | { 0x380a, 0x01 }, /* height high */ |
554 | { 0x380b, 0xe0 }, /* height low */ |
555 | { 0x380c, 0x03 }, /* total horiz timing high */ |
556 | { 0x380d, 0xa0 }, /* total horiz timing low */ |
557 | { 0x380e, 0x02 }, /* total vertical timing high */ |
558 | { 0x380f, 0x3c }, /* total vertical timing low */ |
559 | { 0x3810, 0x00 }, |
560 | { 0x3811, 0x04 }, |
561 | { 0x3812, 0x00 }, |
562 | { 0x3813, 0x05 }, |
563 | { 0x3814, 0x11 }, |
564 | { 0x3815, 0x11 }, |
565 | { 0x3820, 0x40 }, |
566 | { 0x3821, 0x00 }, |
567 | { 0x382f, 0x0e }, |
568 | { 0x3832, 0x00 }, |
569 | { 0x3833, 0x05 }, |
570 | { 0x3834, 0x00 }, |
571 | { 0x3835, 0x0c }, |
572 | { 0x3837, 0x00 }, |
573 | { 0x3b80, 0x00 }, |
574 | { 0x3b81, 0xa5 }, |
575 | { 0x3b82, 0x10 }, |
576 | { 0x3b83, 0x00 }, |
577 | { 0x3b84, 0x08 }, |
578 | { 0x3b85, 0x00 }, |
579 | { 0x3b86, 0x01 }, |
580 | { 0x3b87, 0x00 }, |
581 | { 0x3b88, 0x00 }, |
582 | { 0x3b89, 0x00 }, |
583 | { 0x3b8a, 0x00 }, |
584 | { 0x3b8b, 0x05 }, |
585 | { 0x3b8c, 0x00 }, |
586 | { 0x3b8d, 0x00 }, |
587 | { 0x3b8e, 0x00 }, |
588 | { 0x3b8f, 0x1a }, |
589 | { 0x3b94, 0x05 }, |
590 | { 0x3b95, 0xf2 }, |
591 | { 0x3b96, 0x40 }, |
592 | { 0x3c00, 0x89 }, |
593 | { 0x3c01, 0x63 }, |
594 | { 0x3c02, 0x01 }, |
595 | { 0x3c03, 0x00 }, |
596 | { 0x3c04, 0x00 }, |
597 | { 0x3c05, 0x03 }, |
598 | { 0x3c06, 0x00 }, |
599 | { 0x3c07, 0x06 }, |
600 | { 0x3c0c, 0x01 }, |
601 | { 0x3c0d, 0xd0 }, |
602 | { 0x3c0e, 0x02 }, |
603 | { 0x3c0f, 0x0a }, |
604 | { 0x4001, 0x42 }, |
605 | { 0x4004, 0x04 }, |
606 | { 0x4005, 0x00 }, |
607 | { 0x404e, 0x01 }, |
608 | { 0x4300, 0xff }, |
609 | { 0x4301, 0x00 }, |
610 | { 0x4315, 0x00 }, |
611 | { 0x4501, 0x48 }, |
612 | { 0x4600, 0x00 }, |
613 | { 0x4601, 0x4e }, |
614 | { 0x4801, 0x0f }, |
615 | { 0x4806, 0x0f }, |
616 | { 0x4819, 0xaa }, |
617 | { 0x4823, 0x3e }, |
618 | { 0x4837, 0x19 }, |
619 | { 0x4a0d, 0x00 }, |
620 | { 0x4a47, 0x7f }, |
621 | { 0x4a49, 0xf0 }, |
622 | { 0x4a4b, 0x30 }, |
623 | { 0x5000, 0x85 }, |
624 | { 0x5001, 0x80 }, |
625 | }; |
626 | |
627 | static const unsigned long supported_xclk_rates[] = { |
628 | [OV7251_19_2_MHZ] = 19200000, |
629 | [OV7251_24_MHZ] = 24000000, |
630 | }; |
631 | |
632 | static const s64 link_freq[] = { |
633 | [OV7251_LINK_FREQ_240_MHZ] = 240000000, |
634 | [OV7251_LINK_FREQ_319_2_MHZ] = 319200000, |
635 | }; |
636 | |
637 | static const s64 pixel_rates[] = { |
638 | [OV7251_LINK_FREQ_240_MHZ] = 48000000, |
639 | [OV7251_LINK_FREQ_319_2_MHZ] = 63840000, |
640 | }; |
641 | |
642 | static const struct ov7251_mode_info ov7251_mode_info_data[] = { |
643 | { |
644 | .width = 640, |
645 | .height = 480, |
646 | .vts = 1724, |
647 | .data = ov7251_setting_vga_30fps, |
648 | .data_size = ARRAY_SIZE(ov7251_setting_vga_30fps), |
649 | .exposure_max = 1704, |
650 | .exposure_def = 504, |
651 | .timeperframe = { |
652 | .numerator = 100, |
653 | .denominator = 3000 |
654 | } |
655 | }, |
656 | { |
657 | .width = 640, |
658 | .height = 480, |
659 | .vts = 860, |
660 | .data = ov7251_setting_vga_60fps, |
661 | .data_size = ARRAY_SIZE(ov7251_setting_vga_60fps), |
662 | .exposure_max = 840, |
663 | .exposure_def = 504, |
664 | .timeperframe = { |
665 | .numerator = 100, |
666 | .denominator = 6014 |
667 | } |
668 | }, |
669 | { |
670 | .width = 640, |
671 | .height = 480, |
672 | .vts = 572, |
673 | .data = ov7251_setting_vga_90fps, |
674 | .data_size = ARRAY_SIZE(ov7251_setting_vga_90fps), |
675 | .exposure_max = 552, |
676 | .exposure_def = 504, |
677 | .timeperframe = { |
678 | .numerator = 100, |
679 | .denominator = 9043 |
680 | } |
681 | }, |
682 | }; |
683 | |
684 | static int ov7251_regulators_enable(struct ov7251 *ov7251) |
685 | { |
686 | int ret; |
687 | |
688 | /* OV7251 power up sequence requires core regulator |
689 | * to be enabled not earlier than io regulator |
690 | */ |
691 | |
692 | ret = regulator_enable(regulator: ov7251->io_regulator); |
693 | if (ret < 0) { |
694 | dev_err(ov7251->dev, "set io voltage failed\n" ); |
695 | return ret; |
696 | } |
697 | |
698 | ret = regulator_enable(regulator: ov7251->analog_regulator); |
699 | if (ret) { |
700 | dev_err(ov7251->dev, "set analog voltage failed\n" ); |
701 | goto err_disable_io; |
702 | } |
703 | |
704 | ret = regulator_enable(regulator: ov7251->core_regulator); |
705 | if (ret) { |
706 | dev_err(ov7251->dev, "set core voltage failed\n" ); |
707 | goto err_disable_analog; |
708 | } |
709 | |
710 | return 0; |
711 | |
712 | err_disable_analog: |
713 | regulator_disable(regulator: ov7251->analog_regulator); |
714 | |
715 | err_disable_io: |
716 | regulator_disable(regulator: ov7251->io_regulator); |
717 | |
718 | return ret; |
719 | } |
720 | |
721 | static void ov7251_regulators_disable(struct ov7251 *ov7251) |
722 | { |
723 | int ret; |
724 | |
725 | ret = regulator_disable(regulator: ov7251->core_regulator); |
726 | if (ret < 0) |
727 | dev_err(ov7251->dev, "core regulator disable failed\n" ); |
728 | |
729 | ret = regulator_disable(regulator: ov7251->analog_regulator); |
730 | if (ret < 0) |
731 | dev_err(ov7251->dev, "analog regulator disable failed\n" ); |
732 | |
733 | ret = regulator_disable(regulator: ov7251->io_regulator); |
734 | if (ret < 0) |
735 | dev_err(ov7251->dev, "io regulator disable failed\n" ); |
736 | } |
737 | |
738 | static int ov7251_write_reg(struct ov7251 *ov7251, u16 reg, u8 val) |
739 | { |
740 | u8 regbuf[3]; |
741 | int ret; |
742 | |
743 | regbuf[0] = reg >> 8; |
744 | regbuf[1] = reg & 0xff; |
745 | regbuf[2] = val; |
746 | |
747 | ret = i2c_master_send(client: ov7251->i2c_client, buf: regbuf, count: 3); |
748 | if (ret < 0) { |
749 | dev_err(ov7251->dev, "%s: write reg error %d: reg=%x, val=%x\n" , |
750 | __func__, ret, reg, val); |
751 | return ret; |
752 | } |
753 | |
754 | return 0; |
755 | } |
756 | |
757 | static int ov7251_write_seq_regs(struct ov7251 *ov7251, u16 reg, u8 *val, |
758 | u8 num) |
759 | { |
760 | u8 regbuf[5]; |
761 | u8 nregbuf = sizeof(reg) + num * sizeof(*val); |
762 | int ret = 0; |
763 | |
764 | if (nregbuf > sizeof(regbuf)) |
765 | return -EINVAL; |
766 | |
767 | regbuf[0] = reg >> 8; |
768 | regbuf[1] = reg & 0xff; |
769 | |
770 | memcpy(regbuf + 2, val, num); |
771 | |
772 | ret = i2c_master_send(client: ov7251->i2c_client, buf: regbuf, count: nregbuf); |
773 | if (ret < 0) { |
774 | dev_err(ov7251->dev, |
775 | "%s: write seq regs error %d: first reg=%x\n" , |
776 | __func__, ret, reg); |
777 | return ret; |
778 | } |
779 | |
780 | return 0; |
781 | } |
782 | |
783 | static int ov7251_read_reg(struct ov7251 *ov7251, u16 reg, u8 *val) |
784 | { |
785 | u8 regbuf[2]; |
786 | int ret; |
787 | |
788 | regbuf[0] = reg >> 8; |
789 | regbuf[1] = reg & 0xff; |
790 | |
791 | ret = i2c_master_send(client: ov7251->i2c_client, buf: regbuf, count: 2); |
792 | if (ret < 0) { |
793 | dev_err(ov7251->dev, "%s: write reg error %d: reg=%x\n" , |
794 | __func__, ret, reg); |
795 | return ret; |
796 | } |
797 | |
798 | ret = i2c_master_recv(client: ov7251->i2c_client, buf: val, count: 1); |
799 | if (ret < 0) { |
800 | dev_err(ov7251->dev, "%s: read reg error %d: reg=%x\n" , |
801 | __func__, ret, reg); |
802 | return ret; |
803 | } |
804 | |
805 | return 0; |
806 | } |
807 | |
808 | static int ov7251_pll_configure(struct ov7251 *ov7251) |
809 | { |
810 | const struct ov7251_pll_cfgs *configs; |
811 | int ret; |
812 | |
813 | configs = ov7251->pll_cfgs; |
814 | |
815 | ret = ov7251_write_reg(ov7251, OV7251_PLL1_PRE_DIV_REG, |
816 | val: configs->pll1[ov7251->link_freq_idx]->pre_div); |
817 | if (ret < 0) |
818 | return ret; |
819 | |
820 | ret = ov7251_write_reg(ov7251, OV7251_PLL1_MULT_REG, |
821 | val: configs->pll1[ov7251->link_freq_idx]->mult); |
822 | if (ret < 0) |
823 | return ret; |
824 | ret = ov7251_write_reg(ov7251, OV7251_PLL1_DIVIDER_REG, |
825 | val: configs->pll1[ov7251->link_freq_idx]->div); |
826 | if (ret < 0) |
827 | return ret; |
828 | |
829 | ret = ov7251_write_reg(ov7251, OV7251_PLL1_PIX_DIV_REG, |
830 | val: configs->pll1[ov7251->link_freq_idx]->pix_div); |
831 | if (ret < 0) |
832 | return ret; |
833 | |
834 | ret = ov7251_write_reg(ov7251, OV7251_PLL1_MIPI_DIV_REG, |
835 | val: configs->pll1[ov7251->link_freq_idx]->mipi_div); |
836 | if (ret < 0) |
837 | return ret; |
838 | |
839 | ret = ov7251_write_reg(ov7251, OV7251_PLL2_PRE_DIV_REG, |
840 | val: configs->pll2->pre_div); |
841 | if (ret < 0) |
842 | return ret; |
843 | |
844 | ret = ov7251_write_reg(ov7251, OV7251_PLL2_MULT_REG, |
845 | val: configs->pll2->mult); |
846 | if (ret < 0) |
847 | return ret; |
848 | |
849 | ret = ov7251_write_reg(ov7251, OV7251_PLL2_DIVIDER_REG, |
850 | val: configs->pll2->div); |
851 | if (ret < 0) |
852 | return ret; |
853 | |
854 | ret = ov7251_write_reg(ov7251, OV7251_PLL2_SYS_DIV_REG, |
855 | val: configs->pll2->sys_div); |
856 | if (ret < 0) |
857 | return ret; |
858 | |
859 | ret = ov7251_write_reg(ov7251, OV7251_PLL2_ADC_DIV_REG, |
860 | val: configs->pll2->adc_div); |
861 | |
862 | return ret; |
863 | } |
864 | |
865 | static int ov7251_set_exposure(struct ov7251 *ov7251, s32 exposure) |
866 | { |
867 | u16 reg; |
868 | u8 val[3]; |
869 | |
870 | reg = OV7251_AEC_EXPO_0; |
871 | val[0] = (exposure & 0xf000) >> 12; /* goes to OV7251_AEC_EXPO_0 */ |
872 | val[1] = (exposure & 0x0ff0) >> 4; /* goes to OV7251_AEC_EXPO_1 */ |
873 | val[2] = (exposure & 0x000f) << 4; /* goes to OV7251_AEC_EXPO_2 */ |
874 | |
875 | return ov7251_write_seq_regs(ov7251, reg, val, num: 3); |
876 | } |
877 | |
878 | static int ov7251_set_gain(struct ov7251 *ov7251, s32 gain) |
879 | { |
880 | u16 reg; |
881 | u8 val[2]; |
882 | |
883 | reg = OV7251_AEC_AGC_ADJ_0; |
884 | val[0] = (gain & 0x0300) >> 8; /* goes to OV7251_AEC_AGC_ADJ_0 */ |
885 | val[1] = gain & 0xff; /* goes to OV7251_AEC_AGC_ADJ_1 */ |
886 | |
887 | return ov7251_write_seq_regs(ov7251, reg, val, num: 2); |
888 | } |
889 | |
890 | static int ov7251_set_register_array(struct ov7251 *ov7251, |
891 | const struct reg_value *settings, |
892 | unsigned int num_settings) |
893 | { |
894 | unsigned int i; |
895 | int ret; |
896 | |
897 | for (i = 0; i < num_settings; ++i, ++settings) { |
898 | ret = ov7251_write_reg(ov7251, reg: settings->reg, val: settings->val); |
899 | if (ret < 0) |
900 | return ret; |
901 | } |
902 | |
903 | return 0; |
904 | } |
905 | |
906 | static int ov7251_set_power_on(struct device *dev) |
907 | { |
908 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); |
909 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
910 | struct ov7251 *ov7251 = to_ov7251(sd); |
911 | int ret; |
912 | u32 wait_us; |
913 | |
914 | ret = ov7251_regulators_enable(ov7251); |
915 | if (ret < 0) |
916 | return ret; |
917 | |
918 | ret = clk_prepare_enable(clk: ov7251->xclk); |
919 | if (ret < 0) { |
920 | dev_err(ov7251->dev, "clk prepare enable failed\n" ); |
921 | ov7251_regulators_disable(ov7251); |
922 | return ret; |
923 | } |
924 | |
925 | gpiod_set_value_cansleep(desc: ov7251->enable_gpio, value: 1); |
926 | |
927 | /* wait at least 65536 external clock cycles */ |
928 | wait_us = DIV_ROUND_UP(65536 * 1000, |
929 | DIV_ROUND_UP(ov7251->xclk_freq, 1000)); |
930 | usleep_range(min: wait_us, max: wait_us + 1000); |
931 | |
932 | ret = ov7251_set_register_array(ov7251, |
933 | settings: ov7251_global_init_setting, |
934 | ARRAY_SIZE(ov7251_global_init_setting)); |
935 | if (ret < 0) { |
936 | dev_err(ov7251->dev, "error during global init\n" ); |
937 | gpiod_set_value_cansleep(desc: ov7251->enable_gpio, value: 0); |
938 | clk_disable_unprepare(clk: ov7251->xclk); |
939 | ov7251_regulators_disable(ov7251); |
940 | return ret; |
941 | } |
942 | |
943 | return ret; |
944 | } |
945 | |
946 | static int ov7251_set_power_off(struct device *dev) |
947 | { |
948 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); |
949 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
950 | struct ov7251 *ov7251 = to_ov7251(sd); |
951 | |
952 | clk_disable_unprepare(clk: ov7251->xclk); |
953 | gpiod_set_value_cansleep(desc: ov7251->enable_gpio, value: 0); |
954 | ov7251_regulators_disable(ov7251); |
955 | |
956 | return 0; |
957 | } |
958 | |
959 | static int ov7251_set_hflip(struct ov7251 *ov7251, s32 value) |
960 | { |
961 | u8 val = ov7251->timing_format2; |
962 | int ret; |
963 | |
964 | if (value) |
965 | val |= OV7251_TIMING_FORMAT2_MIRROR; |
966 | else |
967 | val &= ~OV7251_TIMING_FORMAT2_MIRROR; |
968 | |
969 | ret = ov7251_write_reg(ov7251, OV7251_TIMING_FORMAT2, val); |
970 | if (!ret) |
971 | ov7251->timing_format2 = val; |
972 | |
973 | return ret; |
974 | } |
975 | |
976 | static int ov7251_set_vflip(struct ov7251 *ov7251, s32 value) |
977 | { |
978 | u8 val = ov7251->timing_format1; |
979 | int ret; |
980 | |
981 | if (value) |
982 | val |= OV7251_TIMING_FORMAT1_VFLIP; |
983 | else |
984 | val &= ~OV7251_TIMING_FORMAT1_VFLIP; |
985 | |
986 | ret = ov7251_write_reg(ov7251, OV7251_TIMING_FORMAT1, val); |
987 | if (!ret) |
988 | ov7251->timing_format1 = val; |
989 | |
990 | return ret; |
991 | } |
992 | |
993 | static int ov7251_set_test_pattern(struct ov7251 *ov7251, s32 value) |
994 | { |
995 | u8 val = ov7251->pre_isp_00; |
996 | int ret; |
997 | |
998 | if (value) |
999 | val |= OV7251_PRE_ISP_00_TEST_PATTERN; |
1000 | else |
1001 | val &= ~OV7251_PRE_ISP_00_TEST_PATTERN; |
1002 | |
1003 | ret = ov7251_write_reg(ov7251, OV7251_PRE_ISP_00, val); |
1004 | if (!ret) |
1005 | ov7251->pre_isp_00 = val; |
1006 | |
1007 | return ret; |
1008 | } |
1009 | |
1010 | static const char * const [] = { |
1011 | "Disabled" , |
1012 | "Vertical Pattern Bars" , |
1013 | }; |
1014 | |
1015 | static int ov7251_vts_configure(struct ov7251 *ov7251, s32 vblank) |
1016 | { |
1017 | u8 vts[2]; |
1018 | |
1019 | vts[0] = ((ov7251->current_mode->height + vblank) & 0xff00) >> 8; |
1020 | vts[1] = ((ov7251->current_mode->height + vblank) & 0x00ff); |
1021 | |
1022 | return ov7251_write_seq_regs(ov7251, OV7251_TIMING_VTS_REG, val: vts, num: 2); |
1023 | } |
1024 | |
1025 | static int ov7251_s_ctrl(struct v4l2_ctrl *ctrl) |
1026 | { |
1027 | struct ov7251 *ov7251 = container_of(ctrl->handler, |
1028 | struct ov7251, ctrls); |
1029 | int ret; |
1030 | |
1031 | /* If VBLANK is altered we need to update exposure to compensate */ |
1032 | if (ctrl->id == V4L2_CID_VBLANK) { |
1033 | int exposure_max; |
1034 | |
1035 | exposure_max = ov7251->current_mode->height + ctrl->val - |
1036 | OV7251_INTEGRATION_MARGIN; |
1037 | __v4l2_ctrl_modify_range(ctrl: ov7251->exposure, |
1038 | min: ov7251->exposure->minimum, |
1039 | max: exposure_max, |
1040 | step: ov7251->exposure->step, |
1041 | min(ov7251->exposure->val, |
1042 | exposure_max)); |
1043 | } |
1044 | |
1045 | /* v4l2_ctrl_lock() locks our mutex */ |
1046 | |
1047 | if (!pm_runtime_get_if_in_use(dev: ov7251->dev)) |
1048 | return 0; |
1049 | |
1050 | switch (ctrl->id) { |
1051 | case V4L2_CID_EXPOSURE: |
1052 | ret = ov7251_set_exposure(ov7251, exposure: ctrl->val); |
1053 | break; |
1054 | case V4L2_CID_GAIN: |
1055 | ret = ov7251_set_gain(ov7251, gain: ctrl->val); |
1056 | break; |
1057 | case V4L2_CID_TEST_PATTERN: |
1058 | ret = ov7251_set_test_pattern(ov7251, value: ctrl->val); |
1059 | break; |
1060 | case V4L2_CID_HFLIP: |
1061 | ret = ov7251_set_hflip(ov7251, value: ctrl->val); |
1062 | break; |
1063 | case V4L2_CID_VFLIP: |
1064 | ret = ov7251_set_vflip(ov7251, value: ctrl->val); |
1065 | break; |
1066 | case V4L2_CID_VBLANK: |
1067 | ret = ov7251_vts_configure(ov7251, vblank: ctrl->val); |
1068 | break; |
1069 | default: |
1070 | ret = -EINVAL; |
1071 | break; |
1072 | } |
1073 | |
1074 | pm_runtime_put(dev: ov7251->dev); |
1075 | |
1076 | return ret; |
1077 | } |
1078 | |
1079 | static const struct v4l2_ctrl_ops ov7251_ctrl_ops = { |
1080 | .s_ctrl = ov7251_s_ctrl, |
1081 | }; |
1082 | |
1083 | static int ov7251_enum_mbus_code(struct v4l2_subdev *sd, |
1084 | struct v4l2_subdev_state *sd_state, |
1085 | struct v4l2_subdev_mbus_code_enum *code) |
1086 | { |
1087 | if (code->index > 0) |
1088 | return -EINVAL; |
1089 | |
1090 | code->code = MEDIA_BUS_FMT_Y10_1X10; |
1091 | |
1092 | return 0; |
1093 | } |
1094 | |
1095 | static int ov7251_enum_frame_size(struct v4l2_subdev *subdev, |
1096 | struct v4l2_subdev_state *sd_state, |
1097 | struct v4l2_subdev_frame_size_enum *fse) |
1098 | { |
1099 | if (fse->code != MEDIA_BUS_FMT_Y10_1X10) |
1100 | return -EINVAL; |
1101 | |
1102 | if (fse->index >= ARRAY_SIZE(ov7251_mode_info_data)) |
1103 | return -EINVAL; |
1104 | |
1105 | fse->min_width = ov7251_mode_info_data[fse->index].width; |
1106 | fse->max_width = ov7251_mode_info_data[fse->index].width; |
1107 | fse->min_height = ov7251_mode_info_data[fse->index].height; |
1108 | fse->max_height = ov7251_mode_info_data[fse->index].height; |
1109 | |
1110 | return 0; |
1111 | } |
1112 | |
1113 | static int ov7251_enum_frame_ival(struct v4l2_subdev *subdev, |
1114 | struct v4l2_subdev_state *sd_state, |
1115 | struct v4l2_subdev_frame_interval_enum *fie) |
1116 | { |
1117 | unsigned int index = fie->index; |
1118 | unsigned int i; |
1119 | |
1120 | for (i = 0; i < ARRAY_SIZE(ov7251_mode_info_data); i++) { |
1121 | if (fie->width != ov7251_mode_info_data[i].width || |
1122 | fie->height != ov7251_mode_info_data[i].height) |
1123 | continue; |
1124 | |
1125 | if (index-- == 0) { |
1126 | fie->interval = ov7251_mode_info_data[i].timeperframe; |
1127 | return 0; |
1128 | } |
1129 | } |
1130 | |
1131 | return -EINVAL; |
1132 | } |
1133 | |
1134 | static struct v4l2_mbus_framefmt * |
1135 | __ov7251_get_pad_format(struct ov7251 *ov7251, |
1136 | struct v4l2_subdev_state *sd_state, |
1137 | unsigned int pad, |
1138 | enum v4l2_subdev_format_whence which) |
1139 | { |
1140 | switch (which) { |
1141 | case V4L2_SUBDEV_FORMAT_TRY: |
1142 | return v4l2_subdev_state_get_format(sd_state, pad); |
1143 | case V4L2_SUBDEV_FORMAT_ACTIVE: |
1144 | return &ov7251->fmt; |
1145 | default: |
1146 | return NULL; |
1147 | } |
1148 | } |
1149 | |
1150 | static int ov7251_get_format(struct v4l2_subdev *sd, |
1151 | struct v4l2_subdev_state *sd_state, |
1152 | struct v4l2_subdev_format *format) |
1153 | { |
1154 | struct ov7251 *ov7251 = to_ov7251(sd); |
1155 | |
1156 | mutex_lock(&ov7251->lock); |
1157 | format->format = *__ov7251_get_pad_format(ov7251, sd_state, |
1158 | pad: format->pad, |
1159 | which: format->which); |
1160 | mutex_unlock(lock: &ov7251->lock); |
1161 | |
1162 | return 0; |
1163 | } |
1164 | |
1165 | static struct v4l2_rect * |
1166 | __ov7251_get_pad_crop(struct ov7251 *ov7251, |
1167 | struct v4l2_subdev_state *sd_state, |
1168 | unsigned int pad, enum v4l2_subdev_format_whence which) |
1169 | { |
1170 | switch (which) { |
1171 | case V4L2_SUBDEV_FORMAT_TRY: |
1172 | return v4l2_subdev_state_get_crop(sd_state, pad); |
1173 | case V4L2_SUBDEV_FORMAT_ACTIVE: |
1174 | return &ov7251->crop; |
1175 | default: |
1176 | return NULL; |
1177 | } |
1178 | } |
1179 | |
1180 | static inline u32 avg_fps(const struct v4l2_fract *t) |
1181 | { |
1182 | return (t->denominator + (t->numerator >> 1)) / t->numerator; |
1183 | } |
1184 | |
1185 | static const struct ov7251_mode_info * |
1186 | ov7251_find_mode_by_ival(struct ov7251 *ov7251, struct v4l2_fract *timeperframe) |
1187 | { |
1188 | const struct ov7251_mode_info *mode = ov7251->current_mode; |
1189 | unsigned int fps_req = avg_fps(t: timeperframe); |
1190 | unsigned int max_dist_match = (unsigned int) -1; |
1191 | unsigned int i, n = 0; |
1192 | |
1193 | for (i = 0; i < ARRAY_SIZE(ov7251_mode_info_data); i++) { |
1194 | unsigned int dist; |
1195 | unsigned int fps_tmp; |
1196 | |
1197 | if (mode->width != ov7251_mode_info_data[i].width || |
1198 | mode->height != ov7251_mode_info_data[i].height) |
1199 | continue; |
1200 | |
1201 | fps_tmp = avg_fps(t: &ov7251_mode_info_data[i].timeperframe); |
1202 | |
1203 | dist = abs(fps_req - fps_tmp); |
1204 | |
1205 | if (dist < max_dist_match) { |
1206 | n = i; |
1207 | max_dist_match = dist; |
1208 | } |
1209 | } |
1210 | |
1211 | return &ov7251_mode_info_data[n]; |
1212 | } |
1213 | |
1214 | static int ov7251_set_format(struct v4l2_subdev *sd, |
1215 | struct v4l2_subdev_state *sd_state, |
1216 | struct v4l2_subdev_format *format) |
1217 | { |
1218 | struct ov7251 *ov7251 = to_ov7251(sd); |
1219 | struct v4l2_mbus_framefmt *__format; |
1220 | int vblank_max, vblank_def; |
1221 | struct v4l2_rect *__crop; |
1222 | const struct ov7251_mode_info *new_mode; |
1223 | int ret = 0; |
1224 | |
1225 | mutex_lock(&ov7251->lock); |
1226 | |
1227 | __crop = __ov7251_get_pad_crop(ov7251, sd_state, pad: format->pad, |
1228 | which: format->which); |
1229 | |
1230 | new_mode = v4l2_find_nearest_size(ov7251_mode_info_data, |
1231 | ARRAY_SIZE(ov7251_mode_info_data), |
1232 | width, height, |
1233 | format->format.width, format->format.height); |
1234 | |
1235 | __crop->width = new_mode->width; |
1236 | __crop->height = new_mode->height; |
1237 | |
1238 | if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE) { |
1239 | ret = __v4l2_ctrl_modify_range(ctrl: ov7251->exposure, |
1240 | min: 1, max: new_mode->exposure_max, |
1241 | step: 1, def: new_mode->exposure_def); |
1242 | if (ret < 0) |
1243 | goto exit; |
1244 | |
1245 | ret = __v4l2_ctrl_s_ctrl(ctrl: ov7251->exposure, |
1246 | val: new_mode->exposure_def); |
1247 | if (ret < 0) |
1248 | goto exit; |
1249 | |
1250 | ret = __v4l2_ctrl_s_ctrl(ctrl: ov7251->gain, val: 16); |
1251 | if (ret < 0) |
1252 | goto exit; |
1253 | |
1254 | vblank_max = OV7251_TIMING_MAX_VTS - new_mode->height; |
1255 | vblank_def = new_mode->vts - new_mode->height; |
1256 | ret = __v4l2_ctrl_modify_range(ctrl: ov7251->vblank, |
1257 | OV7251_TIMING_MIN_VTS, |
1258 | max: vblank_max, step: 1, def: vblank_def); |
1259 | if (ret < 0) |
1260 | goto exit; |
1261 | |
1262 | ov7251->current_mode = new_mode; |
1263 | } |
1264 | |
1265 | __format = __ov7251_get_pad_format(ov7251, sd_state, pad: format->pad, |
1266 | which: format->which); |
1267 | __format->width = __crop->width; |
1268 | __format->height = __crop->height; |
1269 | __format->code = MEDIA_BUS_FMT_Y10_1X10; |
1270 | __format->field = V4L2_FIELD_NONE; |
1271 | __format->colorspace = V4L2_COLORSPACE_SRGB; |
1272 | __format->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(__format->colorspace); |
1273 | __format->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true, |
1274 | __format->colorspace, __format->ycbcr_enc); |
1275 | __format->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(__format->colorspace); |
1276 | |
1277 | format->format = *__format; |
1278 | |
1279 | exit: |
1280 | mutex_unlock(lock: &ov7251->lock); |
1281 | |
1282 | return ret; |
1283 | } |
1284 | |
1285 | static int ov7251_init_state(struct v4l2_subdev *subdev, |
1286 | struct v4l2_subdev_state *sd_state) |
1287 | { |
1288 | struct v4l2_subdev_format fmt = { |
1289 | .which = sd_state ? V4L2_SUBDEV_FORMAT_TRY |
1290 | : V4L2_SUBDEV_FORMAT_ACTIVE, |
1291 | .format = { |
1292 | .width = 640, |
1293 | .height = 480 |
1294 | } |
1295 | }; |
1296 | |
1297 | ov7251_set_format(sd: subdev, sd_state, format: &fmt); |
1298 | |
1299 | return 0; |
1300 | } |
1301 | |
1302 | static int ov7251_get_selection(struct v4l2_subdev *sd, |
1303 | struct v4l2_subdev_state *sd_state, |
1304 | struct v4l2_subdev_selection *sel) |
1305 | { |
1306 | struct ov7251 *ov7251 = to_ov7251(sd); |
1307 | |
1308 | switch (sel->target) { |
1309 | case V4L2_SEL_TGT_CROP_DEFAULT: |
1310 | case V4L2_SEL_TGT_CROP: |
1311 | mutex_lock(&ov7251->lock); |
1312 | sel->r = *__ov7251_get_pad_crop(ov7251, sd_state, pad: sel->pad, |
1313 | which: sel->which); |
1314 | mutex_unlock(lock: &ov7251->lock); |
1315 | break; |
1316 | case V4L2_SEL_TGT_NATIVE_SIZE: |
1317 | sel->r.top = 0; |
1318 | sel->r.left = 0; |
1319 | sel->r.width = OV7251_NATIVE_WIDTH; |
1320 | sel->r.height = OV7251_NATIVE_HEIGHT; |
1321 | break; |
1322 | case V4L2_SEL_TGT_CROP_BOUNDS: |
1323 | sel->r.top = OV7251_ACTIVE_START_TOP; |
1324 | sel->r.left = OV7251_ACTIVE_START_LEFT; |
1325 | sel->r.width = OV7251_ACTIVE_WIDTH; |
1326 | sel->r.height = OV7251_ACTIVE_HEIGHT; |
1327 | break; |
1328 | default: |
1329 | return -EINVAL; |
1330 | } |
1331 | |
1332 | return 0; |
1333 | } |
1334 | |
1335 | static int ov7251_s_stream(struct v4l2_subdev *subdev, int enable) |
1336 | { |
1337 | struct ov7251 *ov7251 = to_ov7251(sd: subdev); |
1338 | int ret; |
1339 | |
1340 | mutex_lock(&ov7251->lock); |
1341 | |
1342 | if (enable) { |
1343 | ret = pm_runtime_resume_and_get(dev: ov7251->dev); |
1344 | if (ret) { |
1345 | mutex_unlock(lock: &ov7251->lock); |
1346 | return ret; |
1347 | } |
1348 | |
1349 | ret = ov7251_pll_configure(ov7251); |
1350 | if (ret) { |
1351 | dev_err(ov7251->dev, "error configuring PLLs\n" ); |
1352 | goto err_power_down; |
1353 | } |
1354 | |
1355 | ret = ov7251_set_register_array(ov7251, |
1356 | settings: ov7251->current_mode->data, |
1357 | num_settings: ov7251->current_mode->data_size); |
1358 | if (ret < 0) { |
1359 | dev_err(ov7251->dev, "could not set mode %dx%d\n" , |
1360 | ov7251->current_mode->width, |
1361 | ov7251->current_mode->height); |
1362 | goto err_power_down; |
1363 | } |
1364 | ret = __v4l2_ctrl_handler_setup(hdl: &ov7251->ctrls); |
1365 | if (ret < 0) { |
1366 | dev_err(ov7251->dev, "could not sync v4l2 controls\n" ); |
1367 | goto err_power_down; |
1368 | } |
1369 | ret = ov7251_write_reg(ov7251, OV7251_SC_MODE_SELECT, |
1370 | OV7251_SC_MODE_SELECT_STREAMING); |
1371 | if (ret) |
1372 | goto err_power_down; |
1373 | } else { |
1374 | ret = ov7251_write_reg(ov7251, OV7251_SC_MODE_SELECT, |
1375 | OV7251_SC_MODE_SELECT_SW_STANDBY); |
1376 | pm_runtime_put(dev: ov7251->dev); |
1377 | } |
1378 | |
1379 | mutex_unlock(lock: &ov7251->lock); |
1380 | return ret; |
1381 | |
1382 | err_power_down: |
1383 | pm_runtime_put(dev: ov7251->dev); |
1384 | mutex_unlock(lock: &ov7251->lock); |
1385 | return ret; |
1386 | } |
1387 | |
1388 | static int ov7251_get_frame_interval(struct v4l2_subdev *subdev, |
1389 | struct v4l2_subdev_state *sd_state, |
1390 | struct v4l2_subdev_frame_interval *fi) |
1391 | { |
1392 | struct ov7251 *ov7251 = to_ov7251(sd: subdev); |
1393 | |
1394 | /* |
1395 | * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 |
1396 | * subdev active state API. |
1397 | */ |
1398 | if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) |
1399 | return -EINVAL; |
1400 | |
1401 | mutex_lock(&ov7251->lock); |
1402 | fi->interval = ov7251->current_mode->timeperframe; |
1403 | mutex_unlock(lock: &ov7251->lock); |
1404 | |
1405 | return 0; |
1406 | } |
1407 | |
1408 | static int ov7251_set_frame_interval(struct v4l2_subdev *subdev, |
1409 | struct v4l2_subdev_state *sd_state, |
1410 | struct v4l2_subdev_frame_interval *fi) |
1411 | { |
1412 | struct ov7251 *ov7251 = to_ov7251(sd: subdev); |
1413 | const struct ov7251_mode_info *new_mode; |
1414 | int ret = 0; |
1415 | |
1416 | /* |
1417 | * FIXME: Implement support for V4L2_SUBDEV_FORMAT_TRY, using the V4L2 |
1418 | * subdev active state API. |
1419 | */ |
1420 | if (fi->which != V4L2_SUBDEV_FORMAT_ACTIVE) |
1421 | return -EINVAL; |
1422 | |
1423 | mutex_lock(&ov7251->lock); |
1424 | new_mode = ov7251_find_mode_by_ival(ov7251, timeperframe: &fi->interval); |
1425 | |
1426 | if (new_mode != ov7251->current_mode) { |
1427 | ret = __v4l2_ctrl_modify_range(ctrl: ov7251->exposure, |
1428 | min: 1, max: new_mode->exposure_max, |
1429 | step: 1, def: new_mode->exposure_def); |
1430 | if (ret < 0) |
1431 | goto exit; |
1432 | |
1433 | ret = __v4l2_ctrl_s_ctrl(ctrl: ov7251->exposure, |
1434 | val: new_mode->exposure_def); |
1435 | if (ret < 0) |
1436 | goto exit; |
1437 | |
1438 | ret = __v4l2_ctrl_s_ctrl(ctrl: ov7251->gain, val: 16); |
1439 | if (ret < 0) |
1440 | goto exit; |
1441 | |
1442 | ov7251->current_mode = new_mode; |
1443 | } |
1444 | |
1445 | fi->interval = ov7251->current_mode->timeperframe; |
1446 | |
1447 | exit: |
1448 | mutex_unlock(lock: &ov7251->lock); |
1449 | |
1450 | return ret; |
1451 | } |
1452 | |
1453 | static const struct v4l2_subdev_video_ops ov7251_video_ops = { |
1454 | .s_stream = ov7251_s_stream, |
1455 | }; |
1456 | |
1457 | static const struct v4l2_subdev_pad_ops ov7251_subdev_pad_ops = { |
1458 | .enum_mbus_code = ov7251_enum_mbus_code, |
1459 | .enum_frame_size = ov7251_enum_frame_size, |
1460 | .enum_frame_interval = ov7251_enum_frame_ival, |
1461 | .get_fmt = ov7251_get_format, |
1462 | .set_fmt = ov7251_set_format, |
1463 | .get_selection = ov7251_get_selection, |
1464 | .get_frame_interval = ov7251_get_frame_interval, |
1465 | .set_frame_interval = ov7251_set_frame_interval, |
1466 | }; |
1467 | |
1468 | static const struct v4l2_subdev_ops ov7251_subdev_ops = { |
1469 | .video = &ov7251_video_ops, |
1470 | .pad = &ov7251_subdev_pad_ops, |
1471 | }; |
1472 | |
1473 | static const struct v4l2_subdev_internal_ops ov7251_internal_ops = { |
1474 | .init_state = ov7251_init_state, |
1475 | }; |
1476 | |
1477 | static int ov7251_check_hwcfg(struct ov7251 *ov7251) |
1478 | { |
1479 | struct fwnode_handle *fwnode = dev_fwnode(ov7251->dev); |
1480 | struct v4l2_fwnode_endpoint bus_cfg = { |
1481 | .bus_type = V4L2_MBUS_CSI2_DPHY, |
1482 | }; |
1483 | struct fwnode_handle *endpoint; |
1484 | unsigned int i, j; |
1485 | int ret; |
1486 | |
1487 | endpoint = fwnode_graph_get_next_endpoint(fwnode, NULL); |
1488 | if (!endpoint) |
1489 | return -EPROBE_DEFER; /* could be provided by cio2-bridge */ |
1490 | |
1491 | ret = v4l2_fwnode_endpoint_alloc_parse(fwnode: endpoint, vep: &bus_cfg); |
1492 | fwnode_handle_put(fwnode: endpoint); |
1493 | if (ret) |
1494 | return dev_err_probe(dev: ov7251->dev, err: ret, |
1495 | fmt: "parsing endpoint node failed\n" ); |
1496 | |
1497 | if (!bus_cfg.nr_of_link_frequencies) { |
1498 | ret = dev_err_probe(dev: ov7251->dev, err: -EINVAL, |
1499 | fmt: "no link frequencies defined\n" ); |
1500 | goto out_free_bus_cfg; |
1501 | } |
1502 | |
1503 | for (i = 0; i < bus_cfg.nr_of_link_frequencies; i++) { |
1504 | for (j = 0; j < ARRAY_SIZE(link_freq); j++) |
1505 | if (bus_cfg.link_frequencies[i] == link_freq[j]) |
1506 | break; |
1507 | |
1508 | if (j < ARRAY_SIZE(link_freq)) |
1509 | break; |
1510 | } |
1511 | |
1512 | if (i == bus_cfg.nr_of_link_frequencies) { |
1513 | ret = dev_err_probe(dev: ov7251->dev, err: -EINVAL, |
1514 | fmt: "no supported link freq found\n" ); |
1515 | goto out_free_bus_cfg; |
1516 | } |
1517 | |
1518 | ov7251->link_freq_idx = i; |
1519 | |
1520 | out_free_bus_cfg: |
1521 | v4l2_fwnode_endpoint_free(vep: &bus_cfg); |
1522 | |
1523 | return ret; |
1524 | } |
1525 | |
1526 | static int ov7251_detect_chip(struct ov7251 *ov7251) |
1527 | { |
1528 | u8 chip_id_high, chip_id_low, chip_rev; |
1529 | int ret; |
1530 | |
1531 | ret = ov7251_read_reg(ov7251, OV7251_CHIP_ID_HIGH, val: &chip_id_high); |
1532 | if (ret < 0 || chip_id_high != OV7251_CHIP_ID_HIGH_BYTE) |
1533 | return dev_err_probe(dev: ov7251->dev, err: -ENODEV, |
1534 | fmt: "could not read ID high\n" ); |
1535 | |
1536 | ret = ov7251_read_reg(ov7251, OV7251_CHIP_ID_LOW, val: &chip_id_low); |
1537 | if (ret < 0 || chip_id_low != OV7251_CHIP_ID_LOW_BYTE) |
1538 | return dev_err_probe(dev: ov7251->dev, err: -ENODEV, |
1539 | fmt: "could not read ID low\n" ); |
1540 | |
1541 | ret = ov7251_read_reg(ov7251, OV7251_SC_GP_IO_IN1, val: &chip_rev); |
1542 | if (ret < 0) |
1543 | return dev_err_probe(dev: ov7251->dev, err: -ENODEV, |
1544 | fmt: "could not read revision\n" ); |
1545 | chip_rev >>= 4; |
1546 | |
1547 | dev_info(ov7251->dev, |
1548 | "OV7251 revision %x (%s) detected at address 0x%02x\n" , |
1549 | chip_rev, |
1550 | chip_rev == 0x4 ? "1A / 1B" : |
1551 | chip_rev == 0x5 ? "1C / 1D" : |
1552 | chip_rev == 0x6 ? "1E" : |
1553 | chip_rev == 0x7 ? "1F" : "unknown" , |
1554 | ov7251->i2c_client->addr); |
1555 | |
1556 | return 0; |
1557 | } |
1558 | |
1559 | static int ov7251_init_ctrls(struct ov7251 *ov7251) |
1560 | { |
1561 | int vblank_max, vblank_def; |
1562 | s64 pixel_rate; |
1563 | int hblank; |
1564 | |
1565 | v4l2_ctrl_handler_init(&ov7251->ctrls, 7); |
1566 | ov7251->ctrls.lock = &ov7251->lock; |
1567 | |
1568 | v4l2_ctrl_new_std(hdl: &ov7251->ctrls, ops: &ov7251_ctrl_ops, |
1569 | V4L2_CID_HFLIP, min: 0, max: 1, step: 1, def: 0); |
1570 | v4l2_ctrl_new_std(hdl: &ov7251->ctrls, ops: &ov7251_ctrl_ops, |
1571 | V4L2_CID_VFLIP, min: 0, max: 1, step: 1, def: 0); |
1572 | ov7251->exposure = v4l2_ctrl_new_std(hdl: &ov7251->ctrls, ops: &ov7251_ctrl_ops, |
1573 | V4L2_CID_EXPOSURE, min: 1, max: 32, step: 1, def: 32); |
1574 | ov7251->gain = v4l2_ctrl_new_std(hdl: &ov7251->ctrls, ops: &ov7251_ctrl_ops, |
1575 | V4L2_CID_GAIN, min: 16, max: 1023, step: 1, def: 16); |
1576 | v4l2_ctrl_new_std_menu_items(hdl: &ov7251->ctrls, ops: &ov7251_ctrl_ops, |
1577 | V4L2_CID_TEST_PATTERN, |
1578 | ARRAY_SIZE(ov7251_test_pattern_menu) - 1, |
1579 | mask: 0, def: 0, qmenu: ov7251_test_pattern_menu); |
1580 | |
1581 | pixel_rate = pixel_rates[ov7251->link_freq_idx]; |
1582 | ov7251->pixel_clock = v4l2_ctrl_new_std(hdl: &ov7251->ctrls, |
1583 | ops: &ov7251_ctrl_ops, |
1584 | V4L2_CID_PIXEL_RATE, |
1585 | min: pixel_rate, INT_MAX, |
1586 | step: pixel_rate, def: pixel_rate); |
1587 | ov7251->link_freq = v4l2_ctrl_new_int_menu(hdl: &ov7251->ctrls, |
1588 | ops: &ov7251_ctrl_ops, |
1589 | V4L2_CID_LINK_FREQ, |
1590 | ARRAY_SIZE(link_freq) - 1, |
1591 | def: ov7251->link_freq_idx, |
1592 | qmenu_int: link_freq); |
1593 | if (ov7251->link_freq) |
1594 | ov7251->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
1595 | if (ov7251->pixel_clock) |
1596 | ov7251->pixel_clock->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
1597 | |
1598 | hblank = OV7251_FIXED_PPL - ov7251->current_mode->width; |
1599 | ov7251->hblank = v4l2_ctrl_new_std(hdl: &ov7251->ctrls, ops: &ov7251_ctrl_ops, |
1600 | V4L2_CID_HBLANK, min: hblank, max: hblank, step: 1, |
1601 | def: hblank); |
1602 | if (ov7251->hblank) |
1603 | ov7251->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; |
1604 | |
1605 | vblank_max = OV7251_TIMING_MAX_VTS - ov7251->current_mode->height; |
1606 | vblank_def = ov7251->current_mode->vts - ov7251->current_mode->height; |
1607 | ov7251->vblank = v4l2_ctrl_new_std(hdl: &ov7251->ctrls, ops: &ov7251_ctrl_ops, |
1608 | V4L2_CID_VBLANK, |
1609 | OV7251_TIMING_MIN_VTS, max: vblank_max, step: 1, |
1610 | def: vblank_def); |
1611 | |
1612 | ov7251->sd.ctrl_handler = &ov7251->ctrls; |
1613 | |
1614 | if (ov7251->ctrls.error) { |
1615 | v4l2_ctrl_handler_free(hdl: &ov7251->ctrls); |
1616 | return ov7251->ctrls.error; |
1617 | } |
1618 | |
1619 | return 0; |
1620 | } |
1621 | |
1622 | static int ov7251_probe(struct i2c_client *client) |
1623 | { |
1624 | struct device *dev = &client->dev; |
1625 | struct ov7251 *ov7251; |
1626 | unsigned int rate = 0, clk_rate = 0; |
1627 | int ret; |
1628 | int i; |
1629 | |
1630 | ov7251 = devm_kzalloc(dev, size: sizeof(struct ov7251), GFP_KERNEL); |
1631 | if (!ov7251) |
1632 | return -ENOMEM; |
1633 | |
1634 | ov7251->i2c_client = client; |
1635 | ov7251->dev = dev; |
1636 | |
1637 | ret = ov7251_check_hwcfg(ov7251); |
1638 | if (ret) |
1639 | return ret; |
1640 | |
1641 | /* get system clock (xclk) */ |
1642 | ov7251->xclk = devm_clk_get_optional(dev, NULL); |
1643 | if (IS_ERR(ptr: ov7251->xclk)) |
1644 | return dev_err_probe(dev, err: PTR_ERR(ptr: ov7251->xclk), |
1645 | fmt: "could not get xclk" ); |
1646 | |
1647 | /* |
1648 | * We could have either a 24MHz or 19.2MHz clock rate from either DT or |
1649 | * ACPI. We also need to support the IPU3 case which will have both an |
1650 | * external clock AND a clock-frequency property. |
1651 | */ |
1652 | ret = fwnode_property_read_u32(dev_fwnode(dev), propname: "clock-frequency" , |
1653 | val: &rate); |
1654 | if (ret && !ov7251->xclk) |
1655 | return dev_err_probe(dev, err: ret, fmt: "invalid clock config\n" ); |
1656 | |
1657 | clk_rate = clk_get_rate(clk: ov7251->xclk); |
1658 | ov7251->xclk_freq = clk_rate ? clk_rate : rate; |
1659 | |
1660 | if (ov7251->xclk_freq == 0) |
1661 | return dev_err_probe(dev, err: -EINVAL, fmt: "invalid clock frequency\n" ); |
1662 | |
1663 | if (!ret && ov7251->xclk) { |
1664 | ret = clk_set_rate(clk: ov7251->xclk, rate); |
1665 | if (ret) |
1666 | return dev_err_probe(dev, err: ret, |
1667 | fmt: "failed to set clock rate\n" ); |
1668 | } |
1669 | |
1670 | for (i = 0; i < ARRAY_SIZE(supported_xclk_rates); i++) |
1671 | if (ov7251->xclk_freq == supported_xclk_rates[i]) |
1672 | break; |
1673 | |
1674 | if (i == ARRAY_SIZE(supported_xclk_rates)) |
1675 | return dev_err_probe(dev, err: -EINVAL, |
1676 | fmt: "clock rate %u Hz is unsupported\n" , |
1677 | ov7251->xclk_freq); |
1678 | |
1679 | ov7251->pll_cfgs = ov7251_pll_cfgs[i]; |
1680 | |
1681 | ov7251->io_regulator = devm_regulator_get(dev, id: "vdddo" ); |
1682 | if (IS_ERR(ptr: ov7251->io_regulator)) { |
1683 | dev_err(dev, "cannot get io regulator\n" ); |
1684 | return PTR_ERR(ptr: ov7251->io_regulator); |
1685 | } |
1686 | |
1687 | ov7251->core_regulator = devm_regulator_get(dev, id: "vddd" ); |
1688 | if (IS_ERR(ptr: ov7251->core_regulator)) { |
1689 | dev_err(dev, "cannot get core regulator\n" ); |
1690 | return PTR_ERR(ptr: ov7251->core_regulator); |
1691 | } |
1692 | |
1693 | ov7251->analog_regulator = devm_regulator_get(dev, id: "vdda" ); |
1694 | if (IS_ERR(ptr: ov7251->analog_regulator)) { |
1695 | dev_err(dev, "cannot get analog regulator\n" ); |
1696 | return PTR_ERR(ptr: ov7251->analog_regulator); |
1697 | } |
1698 | |
1699 | ov7251->enable_gpio = devm_gpiod_get(dev, con_id: "enable" , flags: GPIOD_OUT_HIGH); |
1700 | if (IS_ERR(ptr: ov7251->enable_gpio)) { |
1701 | dev_err(dev, "cannot get enable gpio\n" ); |
1702 | return PTR_ERR(ptr: ov7251->enable_gpio); |
1703 | } |
1704 | |
1705 | mutex_init(&ov7251->lock); |
1706 | |
1707 | ov7251->current_mode = &ov7251_mode_info_data[0]; |
1708 | ret = ov7251_init_ctrls(ov7251); |
1709 | if (ret) { |
1710 | dev_err_probe(dev, err: ret, fmt: "error during v4l2 ctrl init\n" ); |
1711 | goto destroy_mutex; |
1712 | } |
1713 | |
1714 | v4l2_i2c_subdev_init(sd: &ov7251->sd, client, ops: &ov7251_subdev_ops); |
1715 | ov7251->sd.internal_ops = &ov7251_internal_ops; |
1716 | ov7251->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
1717 | ov7251->pad.flags = MEDIA_PAD_FL_SOURCE; |
1718 | ov7251->sd.dev = &client->dev; |
1719 | ov7251->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; |
1720 | |
1721 | ret = media_entity_pads_init(entity: &ov7251->sd.entity, num_pads: 1, pads: &ov7251->pad); |
1722 | if (ret < 0) { |
1723 | dev_err(dev, "could not register media entity\n" ); |
1724 | goto free_ctrl; |
1725 | } |
1726 | |
1727 | ret = ov7251_set_power_on(dev: ov7251->dev); |
1728 | if (ret) |
1729 | goto free_entity; |
1730 | |
1731 | ret = ov7251_detect_chip(ov7251); |
1732 | if (ret) |
1733 | goto power_down; |
1734 | |
1735 | pm_runtime_set_active(dev: &client->dev); |
1736 | pm_runtime_get_noresume(dev: &client->dev); |
1737 | pm_runtime_enable(dev: &client->dev); |
1738 | |
1739 | ret = ov7251_read_reg(ov7251, OV7251_PRE_ISP_00, |
1740 | val: &ov7251->pre_isp_00); |
1741 | if (ret < 0) { |
1742 | dev_err(dev, "could not read test pattern value\n" ); |
1743 | ret = -ENODEV; |
1744 | goto err_pm_runtime; |
1745 | } |
1746 | |
1747 | ret = ov7251_read_reg(ov7251, OV7251_TIMING_FORMAT1, |
1748 | val: &ov7251->timing_format1); |
1749 | if (ret < 0) { |
1750 | dev_err(dev, "could not read vflip value\n" ); |
1751 | ret = -ENODEV; |
1752 | goto err_pm_runtime; |
1753 | } |
1754 | |
1755 | ret = ov7251_read_reg(ov7251, OV7251_TIMING_FORMAT2, |
1756 | val: &ov7251->timing_format2); |
1757 | if (ret < 0) { |
1758 | dev_err(dev, "could not read hflip value\n" ); |
1759 | ret = -ENODEV; |
1760 | goto err_pm_runtime; |
1761 | } |
1762 | |
1763 | pm_runtime_set_autosuspend_delay(dev: &client->dev, delay: 1000); |
1764 | pm_runtime_use_autosuspend(dev: &client->dev); |
1765 | pm_runtime_put_autosuspend(dev: &client->dev); |
1766 | |
1767 | ret = v4l2_async_register_subdev(sd: &ov7251->sd); |
1768 | if (ret < 0) { |
1769 | dev_err(dev, "could not register v4l2 device\n" ); |
1770 | goto free_entity; |
1771 | } |
1772 | |
1773 | ov7251_init_state(subdev: &ov7251->sd, NULL); |
1774 | |
1775 | return 0; |
1776 | |
1777 | err_pm_runtime: |
1778 | pm_runtime_disable(dev: ov7251->dev); |
1779 | pm_runtime_put_noidle(dev: ov7251->dev); |
1780 | power_down: |
1781 | ov7251_set_power_off(dev: ov7251->dev); |
1782 | free_entity: |
1783 | media_entity_cleanup(entity: &ov7251->sd.entity); |
1784 | free_ctrl: |
1785 | v4l2_ctrl_handler_free(hdl: &ov7251->ctrls); |
1786 | destroy_mutex: |
1787 | mutex_destroy(lock: &ov7251->lock); |
1788 | |
1789 | return ret; |
1790 | } |
1791 | |
1792 | static void ov7251_remove(struct i2c_client *client) |
1793 | { |
1794 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
1795 | struct ov7251 *ov7251 = to_ov7251(sd); |
1796 | |
1797 | v4l2_async_unregister_subdev(sd: &ov7251->sd); |
1798 | media_entity_cleanup(entity: &ov7251->sd.entity); |
1799 | v4l2_ctrl_handler_free(hdl: &ov7251->ctrls); |
1800 | mutex_destroy(lock: &ov7251->lock); |
1801 | |
1802 | pm_runtime_disable(dev: ov7251->dev); |
1803 | if (!pm_runtime_status_suspended(dev: ov7251->dev)) |
1804 | ov7251_set_power_off(dev: ov7251->dev); |
1805 | pm_runtime_set_suspended(dev: ov7251->dev); |
1806 | } |
1807 | |
1808 | static const struct dev_pm_ops ov7251_pm_ops = { |
1809 | SET_RUNTIME_PM_OPS(ov7251_set_power_off, ov7251_set_power_on, NULL) |
1810 | }; |
1811 | |
1812 | static const struct of_device_id ov7251_of_match[] = { |
1813 | { .compatible = "ovti,ov7251" }, |
1814 | { /* sentinel */ } |
1815 | }; |
1816 | MODULE_DEVICE_TABLE(of, ov7251_of_match); |
1817 | |
1818 | static const struct acpi_device_id ov7251_acpi_match[] = { |
1819 | { "INT347E" }, |
1820 | { } |
1821 | }; |
1822 | MODULE_DEVICE_TABLE(acpi, ov7251_acpi_match); |
1823 | |
1824 | static struct i2c_driver ov7251_i2c_driver = { |
1825 | .driver = { |
1826 | .of_match_table = ov7251_of_match, |
1827 | .acpi_match_table = ov7251_acpi_match, |
1828 | .name = "ov7251" , |
1829 | .pm = &ov7251_pm_ops, |
1830 | }, |
1831 | .probe = ov7251_probe, |
1832 | .remove = ov7251_remove, |
1833 | }; |
1834 | |
1835 | module_i2c_driver(ov7251_i2c_driver); |
1836 | |
1837 | MODULE_DESCRIPTION("Omnivision OV7251 Camera Driver" ); |
1838 | MODULE_AUTHOR("Todor Tomov <todor.tomov@linaro.org>" ); |
1839 | MODULE_LICENSE("GPL v2" ); |
1840 | |