1 /*
2 * Copyright 2017-2018, 2020 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_video_common.h"
10 #include "fsl_camera.h"
11 #include "fsl_camera_device.h"
12 #include "fsl_ov5640.h"
13
14 /*******************************************************************************
15 * Definitions
16 ******************************************************************************/
17 #define OV5640_DelayMs VIDEO_DelayMs
18
19 #define OV5640_SCCB_ADDR 0x3CU
20 #define OV5640_RESOLUTION_PARAM_NUM 0x16U
21
22 #define OV5640_WriteReg(handle, reg, val) \
23 SCCB_WriteReg(OV5640_SCCB_ADDR, kSCCB_RegAddr16Bit, (reg), (val), \
24 ((ov5640_resource_t *)((handle)->resource))->i2cSendFunc)
25
26 #define OV5640_WriteMultiRegs(handle, reg, val, len) \
27 SCCB_WriteMultiRegs(OV5640_SCCB_ADDR, kSCCB_RegAddr16Bit, (reg), (val), len, \
28 ((ov5640_resource_t *)((handle)->resource))->i2cSendFunc)
29
30 #define OV5640_ReadReg(handle, reg, val) \
31 SCCB_ReadReg(OV5640_SCCB_ADDR, kSCCB_RegAddr16Bit, (reg), (val), \
32 ((ov5640_resource_t *)((handle)->resource))->i2cReceiveFunc)
33
34 #define OV5640_ModifyReg(handle, reg, clrMask, val) \
35 SCCB_ModifyReg(OV5640_SCCB_ADDR, kSCCB_RegAddr16Bit, (reg), (clrMask), (val), \
36 ((ov5640_resource_t *)((handle)->resource))->i2cReceiveFunc, \
37 ((ov5640_resource_t *)((handle)->resource))->i2cSendFunc)
38
39 #define OV5640_POLARITY_CTRL00_VSYNC_MASK (1U << 0U)
40 #define OV5640_POLARITY_CTRL00_HREF_MASK (1U << 1U)
41 #define OV5640_POLARITY_CTRL00_GATE_PCLK_HREF_MASK (1U << 2U)
42 #define OV5640_POLARITY_CTRL00_GATE_PCLK_VSYNC_MASK (1U << 3U)
43 #define OV5640_POLARITY_CTRL00_PCLK_MASK (1U << 5U)
44
45 #define OV5640_SDE_CTRL0_REG 0x5580
46 #define OV5640_SDE_CTRL1_REG 0x5581
47 #define OV5640_SDE_CTRL2_REG 0x5582
48 #define OV5640_SDE_CTRL3_REG 0x5583
49 #define OV5640_SDE_CTRL4_REG 0x5584
50 #define OV5640_SDE_CTRL5_REG 0x5585
51 #define OV5640_SDE_CTRL6_REG 0x5586
52 #define OV5640_SDE_CTRL7_REG 0x5587
53 #define OV5640_SDE_CTRL8_REG 0x5588
54 #define OV5640_SDE_CTRL9_REG 0x5589
55 #define OV5640_SDE_CTRL10_REG 0x558a
56 #define OV5640_SDE_CTRL11_REG 0x558b
57 #define OV5640_SDE_CTRL12_REG 0x558c
58
59 #define OV5640_AWB_R_H_REG 0x3400
60 #define OV5640_AWB_R_L_REG 0x3401
61 #define OV5640_AWB_G_H_REG 0x3402
62 #define OV5640_AWB_G_L_REG 0x3403
63 #define OV5640_AWB_B_H_REG 0x3404
64 #define OV5640_AWB_B_L_REG 0x3405
65 #define OV5640_AWB_CTRL_REG 0x3406
66
67 #define OV5640_CHECK_RET(x) \
68 do \
69 { \
70 status = (x); \
71 if (kStatus_Success != status) \
72 { \
73 return status; \
74 } \
75 } while (false)
76
77 typedef struct _ov5640_reg_val
78 {
79 uint16_t regAddr; /*!< Register address. */
80 uint8_t regVal; /*!<Register value. */
81 } ov5640_reg_val_t;
82
83 typedef struct _ov5640_resolution_param
84 {
85 uint32_t resolution; /*!< Resolution, see @ref video_resolution_t and @ref FSL_VIDEO_RESOLUTION. */
86 uint8_t param[OV5640_RESOLUTION_PARAM_NUM]; /*!< Parameter 0x3800 to 0x3813. */
87 } ov5640_resolution_param_t;
88
89 typedef struct
90 {
91 uint32_t resolution;
92 uint8_t framePerSec;
93 uint8_t pllCtrl1;
94 uint8_t pllCtrl2;
95 uint8_t vfifoCtrl0C;
96 uint8_t pclkDiv;
97 uint8_t pclkPeriod;
98 } ov5640_clock_config_t;
99
100 typedef struct
101 {
102 uint8_t lightMode;
103 uint8_t awbCtrl;
104 uint8_t awbR_H;
105 uint8_t awbR_L;
106 uint8_t awbG_H;
107 uint8_t awbG_L;
108 uint8_t awbB_H;
109 uint8_t awbB_L;
110 } ov5640_light_mode_config_t;
111
112 typedef struct
113 {
114 uint8_t effect;
115 uint8_t sdeCtrl0;
116 uint8_t sdeCtrl3;
117 uint8_t sdeCtrl4;
118 } ov5640_special_effect_config_t;
119
120 typedef status_t (*ov5640_cmd_func_t)(camera_device_handle_t *handle, int32_t arg);
121
122 typedef struct
123 {
124 camera_device_cmd_t cmd;
125 ov5640_cmd_func_t func;
126 } ov5640_cmd_func_map_t;
127
128 /*******************************************************************************
129 * Prototypes
130 ******************************************************************************/
131 status_t OV5640_Init(camera_device_handle_t *handle, const camera_config_t *config);
132
133 status_t OV5640_Deinit(camera_device_handle_t *handle);
134
135 status_t OV5640_Control(camera_device_handle_t *handle, camera_device_cmd_t cmd, int32_t arg);
136
137 status_t OV5640_Start(camera_device_handle_t *handle);
138
139 status_t OV5640_Stop(camera_device_handle_t *handle);
140
141 status_t OV5640_InitExt(camera_device_handle_t *handle, const camera_config_t *config, const void *specialConfig);
142
143 status_t OV5640_SetSpecialEffect(camera_device_handle_t *handle, int32_t effect);
144
145 status_t OV5640_SetLightMode(camera_device_handle_t *handle, int32_t lightMode);
146
147 status_t OV5640_SetSaturation(camera_device_handle_t *handle, int32_t saturation);
148
149 status_t OV5640_SetContrast(camera_device_handle_t *handle, int32_t contrast);
150
151 status_t OV5640_SetBrightness(camera_device_handle_t *handle, int32_t brightness);
152
153 /*******************************************************************************
154 * Variables
155 ******************************************************************************/
156 static const ov5640_reg_val_t ov5640InitParam[] = {
157 {0x3008, 0x42},
158
159 /* System setting. */
160 {0x3103, 0x03},
161 {0x3000, 0x00},
162 {0x3004, 0xff},
163 {0x3002, 0x1c},
164 {0x3006, 0xc3},
165 {0x302e, 0x08},
166 {0x3037, 0x13},
167 {0x3108, 0x01},
168 {0x3618, 0x00},
169 {0x3612, 0x29},
170 {0x3708, 0x64},
171 {0x3709, 0x52},
172 {0x370c, 0x03},
173 {0x3820, 0x41},
174 {0x3821, 0x07},
175 {0x3630, 0x36},
176 {0x3631, 0x0e},
177 {0x3632, 0xe2},
178 {0x3633, 0x12},
179 {0x3621, 0xe0},
180 {0x3704, 0xa0},
181 {0x3703, 0x5a},
182 {0x3715, 0x78},
183 {0x3717, 0x01},
184 {0x370b, 0x60},
185 {0x3705, 0x1a},
186 {0x3905, 0x02},
187 {0x3906, 0x10},
188 {0x3901, 0x0a},
189 {0x3731, 0x12},
190 {0x3600, 0x08},
191 {0x3601, 0x33},
192 {0x302d, 0x60},
193 {0x3620, 0x52},
194 {0x371b, 0x20},
195 {0x471c, 0x50},
196 {0x3a13, 0x43},
197 {0x3a18, 0x00},
198 {0x3a19, 0x7c},
199 {0x3635, 0x13},
200 {0x3636, 0x03},
201 {0x3634, 0x40},
202 {0x3622, 0x01},
203 {0x3c01, 0x00},
204 {0x3a00, 0x58},
205 {0x4001, 0x02},
206 {0x4004, 0x02},
207 {0x4005, 0x1a},
208 {0x5001, 0xa3},
209
210 /* AEC */
211 {0x3a0f, 0x30},
212 {0x3a10, 0x28},
213 {0x3a1b, 0x30},
214 {0x3a1e, 0x26},
215 {0x3a11, 0x60},
216 {0x3a1f, 0x14},
217
218 /* AWB */
219 {0x5180, 0xff},
220 {0x5181, 0xf2},
221 {0x5182, 0x00},
222 {0x5183, 0x14},
223 {0x5184, 0x25},
224 {0x5185, 0x24},
225 {0x5186, 0x09},
226 {0x5187, 0x09},
227 {0x5188, 0x09},
228 {0x5189, 0x88},
229 {0x518a, 0x54},
230 {0x518b, 0xee},
231 {0x518c, 0xb2},
232 {0x518d, 0x50},
233 {0x518e, 0x34},
234 {0x518f, 0x6b},
235 {0x5190, 0x46},
236 {0x5191, 0xf8},
237 {0x5192, 0x04},
238 {0x5193, 0x70},
239 {0x5194, 0xf0},
240 {0x5195, 0xf0},
241 {0x5196, 0x03},
242 {0x5197, 0x01},
243 {0x5198, 0x04},
244 {0x5199, 0x6c},
245 {0x519a, 0x04},
246 {0x519b, 0x00},
247 {0x519c, 0x09},
248 {0x519d, 0x2b},
249 {0x519e, 0x38},
250
251 /* Color Matrix */
252 {0x5381, 0x1e},
253 {0x5382, 0x5b},
254 {0x5383, 0x08},
255 {0x5384, 0x0a},
256 {0x5385, 0x7e},
257 {0x5386, 0x88},
258 {0x5387, 0x7c},
259 {0x5388, 0x6c},
260 {0x5389, 0x10},
261 {0x538a, 0x01},
262 {0x538b, 0x98},
263
264 /* sharp */
265 {0x5300, 0x08},
266 {0x5301, 0x30},
267 {0x5302, 0x10},
268 {0x5303, 0x00},
269 {0x5304, 0x08},
270 {0x5305, 0x30},
271 {0x5306, 0x08},
272 {0x5307, 0x16},
273 {0x5309, 0x08},
274 {0x530a, 0x30},
275 {0x530b, 0x04},
276 {0x530c, 0x06},
277
278 /* Gamma */
279 {0x5480, 0x01},
280 {0x5481, 0x08},
281 {0x5482, 0x14},
282 {0x5483, 0x28},
283 {0x5484, 0x51},
284 {0x5485, 0x65},
285 {0x5486, 0x71},
286 {0x5487, 0x7d},
287 {0x5488, 0x87},
288 {0x5489, 0x91},
289 {0x548a, 0x9a},
290 {0x548b, 0xaa},
291 {0x548c, 0xb8},
292 {0x548d, 0xcd},
293 {0x548e, 0xdd},
294 {0x548f, 0xea},
295 {0x5490, 0x1d},
296
297 /* UV adjust. */
298 {0x5580, 0x02},
299 {0x5583, 0x40},
300 {0x5584, 0x10},
301 {0x5589, 0x10},
302 {0x558a, 0x00},
303 {0x558b, 0xf8},
304
305 /* Lens correction. */
306 {0x5800, 0x23},
307 {0x5801, 0x14},
308 {0x5802, 0x0f},
309 {0x5803, 0x0f},
310 {0x5804, 0x12},
311 {0x5805, 0x26},
312 {0x5806, 0x0c},
313 {0x5807, 0x08},
314 {0x5808, 0x05},
315 {0x5809, 0x05},
316 {0x580a, 0x08},
317 {0x580b, 0x0d},
318 {0x580c, 0x08},
319 {0x580d, 0x03},
320 {0x580e, 0x00},
321 {0x580f, 0x00},
322 {0x5810, 0x03},
323 {0x5811, 0x09},
324 {0x5812, 0x07},
325 {0x5813, 0x03},
326 {0x5814, 0x00},
327 {0x5815, 0x01},
328 {0x5816, 0x03},
329 {0x5817, 0x08},
330 {0x5818, 0x0d},
331 {0x5819, 0x08},
332 {0x581a, 0x05},
333 {0x581b, 0x06},
334 {0x581c, 0x08},
335 {0x581d, 0x0e},
336 {0x581e, 0x29},
337 {0x581f, 0x17},
338 {0x5820, 0x11},
339 {0x5821, 0x11},
340 {0x5822, 0x15},
341 {0x5823, 0x28},
342 {0x5824, 0x46},
343 {0x5825, 0x26},
344 {0x5826, 0x08},
345 {0x5827, 0x26},
346 {0x5828, 0x64},
347 {0x5829, 0x26},
348 {0x582a, 0x24},
349 {0x582b, 0x22},
350 {0x582c, 0x24},
351 {0x582d, 0x24},
352 {0x582e, 0x06},
353 {0x582f, 0x22},
354 {0x5830, 0x40},
355 {0x5831, 0x42},
356 {0x5832, 0x24},
357 {0x5833, 0x26},
358 {0x5834, 0x24},
359 {0x5835, 0x22},
360 {0x5836, 0x22},
361 {0x5837, 0x26},
362 {0x5838, 0x44},
363 {0x5839, 0x24},
364 {0x583a, 0x26},
365 {0x583b, 0x28},
366 {0x583c, 0x42},
367 {0x583d, 0xce},
368 };
369
370 static const ov5640_resolution_param_t resolutionParam[] = {
371 {
372 .resolution = (uint32_t)kVIDEO_ResolutionVGA,
373 .param = {0x00, 0x00, 0x00, 0x04, 0x0a, 0x3f, 0x07, 0x9b, 0x02, 0x80, 0x01,
374 0xe0, 0x07, 0x68, 0x03, 0xd8, 0x00, 0x10, 0x00, 0x06, 0x31, 0x31},
375 },
376 {
377 .resolution = (uint32_t)kVIDEO_ResolutionQVGA,
378 .param = {0x00, 0x00, 0x00, 0x04, 0x0a, 0x3f, 0x07, 0x9b, 0x01, 0x40, 0x00,
379 0xf0, 0x07, 0x68, 0x03, 0xd8, 0x00, 0x10, 0x00, 0x06, 0x31, 0x31},
380 },
381 {
382 .resolution = FSL_VIDEO_RESOLUTION(480, 272),
383 .param = {0x00, 0x00, 0x00, 0xfa, 0x0a, 0x3f, 0x06, 0xa9, 0x01, 0xE0, 0x01,
384 0x10, 0x07, 0x64, 0x02, 0xe4, 0x00, 0x10, 0x00, 0x04, 0x31, 0x31},
385 },
386 {
387 .resolution = (uint32_t)kVIDEO_Resolution720P,
388 .param = {0x00, 0x00, 0x00, 0xfa, 0x0a, 0x3f, 0x06, 0xa9, 0x05, 0x00, 0x02,
389 0xd0, 0x07, 0x64, 0x02, 0xe4, 0x00, 0x10, 0x00, 0x04, 0x31, 0x31},
390 },
391 {
392 .resolution = (uint32_t)kVIDEO_Resolution1080P,
393 .param = {0x01, 0x50, 0x01, 0xb2, 0x08, 0xef, 0x05, 0xf1, 0x07, 0x80, 0x04,
394 0x38, 0x09, 0xc4, 0x04, 0x60, 0x00, 0x10, 0x00, 0x04, 0x11, 0x11},
395 },
396 };
397
398 /* DVP */
399 static const ov5640_clock_config_t s_ov5640DvpClockConfigs[] = {
400 {
401 .resolution = (uint32_t)kVIDEO_ResolutionVGA,
402 .framePerSec = 15,
403 .pllCtrl1 = 0x21,
404 .pllCtrl2 = 0x46,
405 .vfifoCtrl0C = 0x22,
406 .pclkDiv = 0x02,
407 .pclkPeriod = 0x22,
408 },
409 {
410 .resolution = (uint32_t)kVIDEO_ResolutionVGA,
411 .framePerSec = 30,
412 .pllCtrl1 = 0x11,
413 .pllCtrl2 = 0x46,
414 .vfifoCtrl0C = 0x22,
415 .pclkDiv = 0x02,
416 .pclkPeriod = 0x22,
417 },
418 {
419 .resolution = (uint32_t)kVIDEO_ResolutionQVGA,
420 .framePerSec = 15,
421 .pllCtrl1 = 0x21,
422 .pllCtrl2 = 0x46,
423 .vfifoCtrl0C = 0x22,
424 .pclkDiv = 0x02,
425 .pclkPeriod = 0x22,
426 },
427 {
428 .resolution = (uint32_t)kVIDEO_ResolutionQVGA,
429 .framePerSec = 30,
430 .pllCtrl1 = 0x11,
431 .pllCtrl2 = 0x46,
432 .vfifoCtrl0C = 0x22,
433 .pclkDiv = 0x02,
434 .pclkPeriod = 0x22,
435 },
436 {
437 .resolution = FSL_VIDEO_RESOLUTION(480, 272),
438 .framePerSec = 15,
439 .pllCtrl1 = 0x41,
440 .pllCtrl2 = 0x69,
441 .vfifoCtrl0C = 0x20,
442 .pclkDiv = 0x04,
443 .pclkPeriod = 0x16,
444 },
445 {
446 .resolution = FSL_VIDEO_RESOLUTION(480, 272),
447 .framePerSec = 30,
448 .pllCtrl1 = 0x21,
449 .pllCtrl2 = 0x69,
450 .vfifoCtrl0C = 0x20,
451 .pclkDiv = 0x04,
452 .pclkPeriod = 0x16,
453 },
454 {
455 .resolution = (uint32_t)kVIDEO_Resolution720P,
456 .framePerSec = 15,
457 .pllCtrl1 = 0x41,
458 .pllCtrl2 = 0x69,
459 .vfifoCtrl0C = 0x20,
460 .pclkDiv = 0x04,
461 .pclkPeriod = 0x16,
462 },
463 {
464 .resolution = (uint32_t)kVIDEO_Resolution720P,
465 .framePerSec = 30,
466 .pllCtrl1 = 0x21,
467 .pllCtrl2 = 0x69,
468 .vfifoCtrl0C = 0x20,
469 .pclkDiv = 0x04,
470 .pclkPeriod = 0x16,
471 },
472 {
473 .resolution = (uint32_t)kVIDEO_Resolution1080P,
474 .framePerSec = 15,
475 .pllCtrl1 = 0x21,
476 .pllCtrl2 = 0x69,
477 .vfifoCtrl0C = 0x20,
478 .pclkDiv = 0x04,
479 .pclkPeriod = 0x16,
480 },
481 };
482
483 /* MIPI */
484 static const ov5640_clock_config_t s_ov5640MipiClockConfigs[] = {
485 {
486 .resolution = (uint32_t)kVIDEO_ResolutionVGA,
487 .framePerSec = 15,
488 .pllCtrl1 = 0x22,
489 .pllCtrl2 = 0x38,
490 .vfifoCtrl0C = 0x22,
491 .pclkDiv = 0x02,
492 .pclkPeriod = 0x0a,
493 },
494 {
495 .resolution = (uint32_t)kVIDEO_ResolutionVGA,
496 .framePerSec = 30,
497 .pllCtrl1 = 0x14,
498 .pllCtrl2 = 0x38,
499 .vfifoCtrl0C = 0x22,
500 .pclkDiv = 0x02,
501 .pclkPeriod = 0x0a,
502 },
503 {
504 .resolution = (uint32_t)kVIDEO_ResolutionQVGA,
505 .framePerSec = 15,
506 .pllCtrl1 = 0x22,
507 .pllCtrl2 = 0x38,
508 .vfifoCtrl0C = 0x22,
509 .pclkDiv = 0x02,
510 .pclkPeriod = 0x0a,
511 },
512 {
513 .resolution = (uint32_t)kVIDEO_ResolutionQVGA,
514 .framePerSec = 30,
515 .pllCtrl1 = 0x14,
516 .pllCtrl2 = 0x38,
517 .vfifoCtrl0C = 0x22,
518 .pclkDiv = 0x02,
519 .pclkPeriod = 0x0a,
520 },
521 {
522 .resolution = (uint32_t)kVIDEO_Resolution720P,
523 .framePerSec = 15,
524 .pllCtrl1 = 0x41,
525 .pllCtrl2 = 0x54,
526 .vfifoCtrl0C = 0x20,
527 .pclkDiv = 0x04,
528 .pclkPeriod = 0x0a,
529 },
530 {
531 .resolution = (uint32_t)kVIDEO_Resolution720P,
532 .framePerSec = 30,
533 .pllCtrl1 = 0x21,
534 .pllCtrl2 = 0x54,
535 .vfifoCtrl0C = 0x20,
536 .pclkDiv = 0x04,
537 .pclkPeriod = 0x0a,
538 },
539 {
540 .resolution = (uint32_t)kVIDEO_Resolution1080P,
541 .framePerSec = 15,
542 .pllCtrl1 = 0x21,
543 .pllCtrl2 = 0x54,
544 .vfifoCtrl0C = 0x20,
545 .pclkDiv = 0x04,
546 .pclkPeriod = 0x0a,
547 },
548 {
549 .resolution = (uint32_t)kVIDEO_Resolution1080P,
550 .framePerSec = 30,
551 .pllCtrl1 = 0x11,
552 .pllCtrl2 = 0x54,
553 .vfifoCtrl0C = 0x20,
554 .pclkDiv = 0x04,
555 .pclkPeriod = 0x0a,
556 },
557 };
558
559 static const ov5640_light_mode_config_t s_ov5640LightModeConfigs[] = {
560 /* Auto. */
561 {
562 .lightMode = CAMERA_LIGHT_MODE_AUTO,
563 .awbCtrl = 0x00,
564 .awbR_H = 0x04,
565 .awbR_L = 0x00,
566 .awbG_H = 0x04,
567 .awbG_L = 0x00,
568 .awbB_H = 0x04,
569 .awbB_L = 0x00,
570 },
571 /* Sunny. */
572 {
573 .lightMode = CAMERA_LIGHT_MODE_SUNNY,
574 .awbCtrl = 0x01,
575 .awbR_H = 0x06,
576 .awbR_L = 0x1c,
577 .awbG_H = 0x04,
578 .awbG_L = 0x00,
579 .awbB_H = 0x04,
580 .awbB_L = 0xf3,
581 },
582 /* Office. */
583 {
584 .lightMode = CAMERA_LIGHT_MODE_OFFICE,
585 .awbCtrl = 0x01,
586 .awbR_H = 0x05,
587 .awbR_L = 0x48,
588 .awbG_H = 0x04,
589 .awbG_L = 0x00,
590 .awbB_H = 0x07,
591 .awbB_L = 0xcf,
592 },
593 /* Cloudy. */
594 {
595 .lightMode = CAMERA_LIGHT_MODE_CLOUDY,
596 .awbCtrl = 0x01,
597 .awbR_H = 0x06,
598 .awbR_L = 0x48,
599 .awbG_H = 0x04,
600 .awbG_L = 0x00,
601 .awbB_H = 0x04,
602 .awbB_L = 0xd3,
603 },
604 /* Home. */
605 {
606 .lightMode = CAMERA_LIGHT_MODE_HOME,
607 .awbCtrl = 0x01,
608 .awbR_H = 0x04,
609 .awbR_L = 0x10,
610 .awbG_H = 0x04,
611 .awbG_L = 0x00,
612 .awbB_H = 0x08,
613 .awbB_L = 0x40,
614 },
615 };
616
617 static const ov5640_special_effect_config_t s_ov5640SpecialEffectConfigs[] = {
618 /* Normal. */
619 {
620 .effect = CAMERA_SPECIAL_EFFECT_NORMAL,
621 .sdeCtrl0 = 0x06,
622 .sdeCtrl3 = 0x40,
623 .sdeCtrl4 = 0x10,
624 },
625 /* Bluish. */
626 {
627 .effect = CAMERA_SPECIAL_EFFECT_BLUISH,
628 .sdeCtrl0 = 0x1e,
629 .sdeCtrl3 = 0xa0,
630 .sdeCtrl4 = 0x40,
631 },
632 /* Redish. */
633 {
634 .effect = CAMERA_SPECIAL_EFFECT_REDISH,
635 .sdeCtrl0 = 0x1e,
636 .sdeCtrl3 = 0x80,
637 .sdeCtrl4 = 0xc0,
638 },
639 /* B & W */
640 {
641 .effect = CAMERA_SPECIAL_EFFECT_BW,
642 .sdeCtrl0 = 0x1e,
643 .sdeCtrl3 = 0x80,
644 .sdeCtrl4 = 0x80,
645 },
646 /* Sepia. */
647 {
648 .effect = CAMERA_SPECIAL_EFFECT_SEPIA,
649 .sdeCtrl0 = 0x1e,
650 .sdeCtrl3 = 0x40,
651 .sdeCtrl4 = 0xa0,
652 },
653 /* Negtive. */
654 {
655 .effect = CAMERA_SPECIAL_EFFECT_NEGTIVE,
656 .sdeCtrl0 = 0x40,
657 .sdeCtrl3 = 0x40,
658 .sdeCtrl4 = 0x10,
659 },
660 /* Greenish. */
661 {
662 .effect = CAMERA_SPECIAL_EFFECT_GREENISH,
663 .sdeCtrl0 = 0x1e,
664 .sdeCtrl3 = 0x60,
665 .sdeCtrl4 = 0x60,
666 },
667 };
668
669 static const ov5640_cmd_func_map_t s_ov5640CmdFuncMap[] = {
670 {
671 kCAMERA_DeviceLightMode,
672 OV5640_SetLightMode,
673 },
674 {
675 kCAMERA_DeviceSaturation,
676 OV5640_SetSaturation,
677 },
678 {
679 kCAMERA_DeviceBrightness,
680 OV5640_SetBrightness,
681 },
682 {
683 kCAMERA_DeviceContrast,
684 OV5640_SetContrast,
685 },
686 {
687 kCAMERA_DeviceSpecialEffect,
688 OV5640_SetSpecialEffect,
689 },
690 };
691
692 const camera_device_operations_t ov5640_ops = {
693 .init = OV5640_Init,
694 .deinit = OV5640_Deinit,
695 .start = OV5640_Start,
696 .stop = OV5640_Stop,
697 .control = OV5640_Control,
698 .init_ext = OV5640_InitExt,
699 };
700
701 /*******************************************************************************
702 * Code
703 ******************************************************************************/
704
OV5640_LoadRegVal(camera_device_handle_t * handle,const ov5640_reg_val_t regVal[],uint32_t num)705 static status_t OV5640_LoadRegVal(camera_device_handle_t *handle, const ov5640_reg_val_t regVal[], uint32_t num)
706 {
707 uint32_t i;
708 status_t status;
709
710 for (i = 0; i < num; i++)
711 {
712 status = OV5640_WriteReg(handle, regVal[i].regAddr, regVal[i].regVal);
713
714 if (kStatus_Success != status)
715 {
716 return status;
717 }
718 }
719
720 return kStatus_Success;
721 }
722
OV5640_SoftwareReset(camera_device_handle_t * handle)723 static status_t OV5640_SoftwareReset(camera_device_handle_t *handle)
724 {
725 ov5640_reg_val_t param[] = {{0x3103, 0x11}, {0x3008, 0x82}};
726
727 return OV5640_LoadRegVal(handle, param, ARRAY_SIZE(param));
728 }
729
OV5640_GetResolutionParam(uint32_t resolution)730 static const uint8_t *OV5640_GetResolutionParam(uint32_t resolution)
731 {
732 /*
733 * This function returns the parameter for specific resolution, if
734 * the resolution is not supported, returns NULL.
735 */
736 uint32_t i;
737
738 for (i = 0; i < ARRAY_SIZE(resolutionParam); i++)
739 {
740 if (resolution == resolutionParam[i].resolution)
741 {
742 return resolutionParam[i].param;
743 }
744 }
745
746 return NULL;
747 }
748
OV5640_GetClockConfig(const camera_config_t * config)749 static const ov5640_clock_config_t *OV5640_GetClockConfig(const camera_config_t *config)
750 {
751 uint32_t i;
752
753 if (kCAMERA_InterfaceMIPI == config->interface)
754 {
755 for (i = 0; i < ARRAY_SIZE(s_ov5640MipiClockConfigs); i++)
756 {
757 if ((config->framePerSec == s_ov5640MipiClockConfigs[i].framePerSec) &&
758 (config->resolution == s_ov5640MipiClockConfigs[i].resolution))
759 {
760 return &s_ov5640MipiClockConfigs[i];
761 }
762 }
763 }
764 else
765 {
766 for (i = 0; i < ARRAY_SIZE(s_ov5640DvpClockConfigs); i++)
767 {
768 if ((config->framePerSec == s_ov5640DvpClockConfigs[i].framePerSec) &&
769 (config->resolution == s_ov5640DvpClockConfigs[i].resolution))
770 {
771 return &s_ov5640DvpClockConfigs[i];
772 }
773 }
774 }
775
776 return NULL;
777 }
778
OV5640_SetPixelFormat(camera_device_handle_t * handle,video_pixel_format_t pixelFormat)779 static status_t OV5640_SetPixelFormat(camera_device_handle_t *handle, video_pixel_format_t pixelFormat)
780 {
781 status_t status;
782 uint8_t param[2];
783
784 switch (pixelFormat)
785 {
786 case kVIDEO_PixelFormatYUYV:
787 param[0] = 0x3F;
788 param[1] = 0x00;
789 break;
790
791 case kVIDEO_PixelFormatRGB565:
792 default:
793 param[0] = 0x6f;
794 param[1] = 0x01;
795 break;
796 }
797
798 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x4300, param[0]));
799 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x501f, param[1]));
800
801 return kStatus_Success;
802 }
803
OV5640_Init(camera_device_handle_t * handle,const camera_config_t * config)804 status_t OV5640_Init(camera_device_handle_t *handle, const camera_config_t *config)
805 {
806 status_t status;
807 ov5640_resource_t *resource = (ov5640_resource_t *)(handle->resource);
808 uint8_t reg;
809 const ov5640_clock_config_t *clockConfig;
810
811 /* Verify the configuration. */
812 const uint8_t *resParam = OV5640_GetResolutionParam(config->resolution);
813
814 if (NULL == resParam)
815 {
816 return kStatus_InvalidArgument;
817 }
818
819 if ((kVIDEO_PixelFormatYUYV != config->pixelFormat) && (kVIDEO_PixelFormatRGB565 != config->pixelFormat))
820 {
821 return kStatus_InvalidArgument;
822 }
823
824 if ((kCAMERA_InterfaceNonGatedClock != config->interface) && (kCAMERA_InterfaceGatedClock != config->interface) &&
825 (kCAMERA_InterfaceCCIR656 != config->interface) && (kCAMERA_InterfaceMIPI != config->interface))
826 {
827 return kStatus_InvalidArgument;
828 }
829
830 /* Only support 2 data lanes. */
831 if ((kCAMERA_InterfaceMIPI == config->interface) && (2U != config->csiLanes))
832 {
833 return kStatus_InvalidArgument;
834 }
835
836 clockConfig = OV5640_GetClockConfig(config);
837
838 if (NULL == clockConfig)
839 {
840 return kStatus_InvalidArgument;
841 }
842
843 resource->pullPowerDownPin(true);
844 resource->pullResetPin(false);
845
846 /* Delay 5ms. */
847 OV5640_DelayMs(5);
848
849 resource->pullPowerDownPin(false);
850
851 /* Delay 1ms. */
852 OV5640_DelayMs(1);
853
854 resource->pullResetPin(true);
855
856 /* Delay 20ms. */
857 OV5640_DelayMs(20);
858
859 OV5640_CHECK_RET(OV5640_SoftwareReset(handle));
860
861 /* Delay 5ms. */
862 OV5640_DelayMs(5);
863
864 /* Initialize. */
865 status = OV5640_LoadRegVal(handle, ov5640InitParam, ARRAY_SIZE(ov5640InitParam));
866 if (kStatus_Success != status)
867 {
868 return status;
869 }
870
871 /* Resolution. */
872 OV5640_CHECK_RET(OV5640_WriteMultiRegs(handle, 0x3800, resParam, OV5640_RESOLUTION_PARAM_NUM));
873
874 if ((uint32_t)kVIDEO_Resolution1080P == config->resolution)
875 {
876 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3709, 0x12));
877 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3821, 0x06));
878 }
879
880 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x302c, 0xc2));
881
882 /* Pixel format. */
883 OV5640_CHECK_RET(OV5640_SetPixelFormat(handle, config->pixelFormat));
884
885 /* Clock. */
886 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3035, clockConfig->pllCtrl1));
887 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3036, clockConfig->pllCtrl2));
888 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x460c, clockConfig->vfifoCtrl0C));
889 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3824, clockConfig->pclkDiv));
890 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x4837, clockConfig->pclkPeriod));
891
892 /* Interface. */
893 if (kCAMERA_InterfaceMIPI == config->interface)
894 {
895 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3034, 0x18));
896
897 /* Set Frex, Vsync, Href, PCLK, data, GPIO to input. */
898 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3017, 0x00));
899 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3018, 0x00));
900
901 /*
902 * Set to MIPI mode, set data lane. Currently only support 2 data lanes,
903 * if need to use 1 data lane, write 0x25 to register 0x300e.
904 */
905 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x300e, 0x45));
906
907 /* Virtual channel. */
908 OV5640_CHECK_RET(OV5640_ModifyReg(handle, 0x4814, (3U << 6), (uint8_t)(config->mipiChannel) << 6));
909
910 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x4800, 0x04));
911 }
912 else
913 {
914 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3034, 0x1a));
915
916 /* Set Frex, Vsync, Href, PCLK, data, GPIO to output. */
917 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3017, 0xFF));
918 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3018, 0xFF));
919
920 /* DVP mode */
921 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x300e, 0x58));
922
923 if (kCAMERA_InterfaceCCIR656 == config->interface)
924 {
925 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x4719, 0x01));
926 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x4730, 0x01));
927 }
928 }
929
930 /* Signal polarity */
931 reg = 0;
932 if ((uint32_t)kCAMERA_HrefActiveHigh != (config->controlFlags & (uint32_t)kCAMERA_HrefActiveHigh))
933 {
934 reg |= OV5640_POLARITY_CTRL00_HREF_MASK;
935 }
936 if ((uint32_t)kCAMERA_VsyncActiveHigh != (config->controlFlags & (uint32_t)kCAMERA_VsyncActiveHigh))
937 {
938 reg |= OV5640_POLARITY_CTRL00_VSYNC_MASK;
939 }
940 if ((uint32_t)kCAMERA_DataLatchOnRisingEdge == (config->controlFlags & (uint32_t)kCAMERA_DataLatchOnRisingEdge))
941 {
942 reg |= OV5640_POLARITY_CTRL00_PCLK_MASK;
943 }
944
945 if (kCAMERA_InterfaceNonGatedClock == config->interface)
946 {
947 reg |= OV5640_POLARITY_CTRL00_GATE_PCLK_HREF_MASK | OV5640_POLARITY_CTRL00_GATE_PCLK_VSYNC_MASK;
948 }
949
950 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x4740, reg));
951
952 /* Lenc on, raw gamma on, BPC on, WPC on, CIP on. */
953 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x5000, 0xa7));
954
955 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3008, 0x02));
956
957 return kStatus_Success;
958 }
959
OV5640_Deinit(camera_device_handle_t * handle)960 status_t OV5640_Deinit(camera_device_handle_t *handle)
961 {
962 ((ov5640_resource_t *)(handle->resource))->pullPowerDownPin(true);
963
964 return kStatus_Success;
965 }
966
OV5640_Control(camera_device_handle_t * handle,camera_device_cmd_t cmd,int32_t arg)967 status_t OV5640_Control(camera_device_handle_t *handle, camera_device_cmd_t cmd, int32_t arg)
968 {
969 for (uint8_t i = 0; i < ARRAY_SIZE(s_ov5640CmdFuncMap); i++)
970 {
971 if (s_ov5640CmdFuncMap[i].cmd == cmd)
972 {
973 return s_ov5640CmdFuncMap[i].func(handle, arg);
974 }
975 }
976
977 return kStatus_InvalidArgument;
978 }
979
OV5640_Start(camera_device_handle_t * handle)980 status_t OV5640_Start(camera_device_handle_t *handle)
981 {
982 return OV5640_WriteReg(handle, 0x3008, 0x02);
983 }
984
OV5640_Stop(camera_device_handle_t * handle)985 status_t OV5640_Stop(camera_device_handle_t *handle)
986 {
987 return OV5640_WriteReg(handle, 0x3008, 0x42);
988 }
989
OV5640_InitExt(camera_device_handle_t * handle,const camera_config_t * config,const void * specialConfig)990 status_t OV5640_InitExt(camera_device_handle_t *handle, const camera_config_t *config, const void *specialConfig)
991 {
992 return OV5640_Init(handle, config);
993 }
994
OV5640_SetBrightness(camera_device_handle_t * handle,int32_t brightness)995 status_t OV5640_SetBrightness(camera_device_handle_t *handle, int32_t brightness)
996 {
997 status_t status;
998
999 if ((brightness < -4) || (brightness > 4))
1000 {
1001 return kStatus_InvalidArgument;
1002 }
1003
1004 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x03));
1005 if (brightness >= 0)
1006 {
1007 status = OV5640_WriteReg(handle, OV5640_SDE_CTRL8_REG, 0x01);
1008 }
1009 else
1010 {
1011 brightness = -brightness;
1012 status = OV5640_WriteReg(handle, OV5640_SDE_CTRL8_REG, 0x09);
1013 }
1014
1015 if (kStatus_Success != status)
1016 {
1017 return status;
1018 }
1019
1020 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL7_REG, ((uint8_t)brightness) << 4U));
1021
1022 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x13));
1023 return OV5640_WriteReg(handle, 0x3212, 0xa3);
1024 }
1025
OV5640_SetContrast(camera_device_handle_t * handle,int32_t contrast)1026 status_t OV5640_SetContrast(camera_device_handle_t *handle, int32_t contrast)
1027 {
1028 status_t status;
1029 uint8_t regVal;
1030
1031 if ((-4 > contrast) || (4 < contrast))
1032 {
1033 return kStatus_InvalidArgument;
1034 }
1035
1036 contrast = 0x20 + contrast * 0x04;
1037 regVal = (uint8_t)contrast;
1038
1039 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x03));
1040
1041 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL0_REG, 0x04));
1042 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL5_REG, regVal));
1043 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL6_REG, regVal));
1044
1045 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x13));
1046 return OV5640_WriteReg(handle, 0x3212, 0xa3);
1047 }
1048
OV5640_SetSaturation(camera_device_handle_t * handle,int32_t saturation)1049 status_t OV5640_SetSaturation(camera_device_handle_t *handle, int32_t saturation)
1050 {
1051 status_t status;
1052 uint8_t regVal;
1053
1054 if ((-4 > saturation) || (4 < saturation))
1055 {
1056 return kStatus_InvalidArgument;
1057 }
1058
1059 saturation = 0x40 + saturation * 0x10;
1060 regVal = (uint8_t)saturation;
1061
1062 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x03));
1063
1064 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL0_REG, 0x02));
1065 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL3_REG, regVal));
1066 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL4_REG, regVal));
1067 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL8_REG, 0x41));
1068
1069 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x13));
1070 return OV5640_WriteReg(handle, 0x3212, 0xa3);
1071 }
1072
OV5640_SetLightMode(camera_device_handle_t * handle,int32_t lightMode)1073 status_t OV5640_SetLightMode(camera_device_handle_t *handle, int32_t lightMode)
1074 {
1075 status_t status;
1076 uint8_t i;
1077
1078 for (i = 0; i < ARRAY_SIZE(s_ov5640LightModeConfigs); i++)
1079 {
1080 if (lightMode == (int32_t)s_ov5640LightModeConfigs[i].lightMode)
1081 {
1082 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x03));
1083
1084 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_AWB_CTRL_REG, s_ov5640LightModeConfigs[i].awbCtrl));
1085 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_AWB_R_H_REG, s_ov5640LightModeConfigs[i].awbR_H));
1086 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_AWB_R_L_REG, s_ov5640LightModeConfigs[i].awbR_L));
1087 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_AWB_G_H_REG, s_ov5640LightModeConfigs[i].awbG_H));
1088 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_AWB_G_L_REG, s_ov5640LightModeConfigs[i].awbG_L));
1089 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_AWB_B_H_REG, s_ov5640LightModeConfigs[i].awbB_H));
1090 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_AWB_B_L_REG, s_ov5640LightModeConfigs[i].awbB_L));
1091
1092 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x13));
1093 return OV5640_WriteReg(handle, 0x3212, 0xa3);
1094 }
1095 }
1096
1097 /* No configuration found. */
1098 return kStatus_InvalidArgument;
1099 }
1100
OV5640_SetSpecialEffect(camera_device_handle_t * handle,int32_t effect)1101 status_t OV5640_SetSpecialEffect(camera_device_handle_t *handle, int32_t effect)
1102 {
1103 status_t status;
1104 uint8_t i;
1105
1106 for (i = 0; i < ARRAY_SIZE(s_ov5640SpecialEffectConfigs); i++)
1107 {
1108 if (effect == (int32_t)s_ov5640SpecialEffectConfigs[i].effect)
1109 {
1110 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x03));
1111
1112 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL0_REG, s_ov5640SpecialEffectConfigs[i].sdeCtrl0));
1113 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL3_REG, s_ov5640SpecialEffectConfigs[i].sdeCtrl3));
1114 OV5640_CHECK_RET(OV5640_WriteReg(handle, OV5640_SDE_CTRL4_REG, s_ov5640SpecialEffectConfigs[i].sdeCtrl4));
1115
1116 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x5003, 0x08));
1117 OV5640_CHECK_RET(OV5640_WriteReg(handle, 0x3212, 0x13));
1118 return OV5640_WriteReg(handle, 0x3212, 0xa3);
1119 }
1120 }
1121
1122 /* No configuration found. */
1123 return kStatus_InvalidArgument;
1124 }
1125