4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*/
6
6
7
- #define DT_DRV_COMPAT ovti_ov7670
8
-
9
7
#include <zephyr/drivers/gpio.h>
10
8
#include <zephyr/drivers/i2c.h>
11
9
#include <zephyr/drivers/video.h>
12
10
#include <zephyr/drivers/video-controls.h>
13
11
#include <zephyr/logging/log.h>
14
12
13
+ #include "video_common.h"
15
14
#include "video_ctrls.h"
16
15
#include "video_device.h"
17
16
18
17
LOG_MODULE_REGISTER (video_ov7670 , CONFIG_VIDEO_LOG_LEVEL );
19
18
20
- /* Initialization register structure */
21
- struct ov7670_reg {
22
- uint8_t reg ;
23
- uint8_t cmd ;
24
- };
25
-
26
19
struct ov7670_config {
27
20
struct i2c_dt_spec bus ;
28
- #if DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
29
- struct gpio_dt_spec reset ;
30
- #endif
31
- #if DT_ANY_INST_HAS_PROP_STATUS_OKAY (pwdn_gpios )
32
- struct gpio_dt_spec pwdn ;
33
- #endif
21
+ const struct gpio_dt_spec reset ;
22
+ const struct gpio_dt_spec pwdn ;
34
23
};
35
24
36
25
struct ov7670_ctrls {
@@ -43,63 +32,7 @@ struct ov7670_data {
43
32
struct video_format fmt ;
44
33
};
45
34
46
- struct ov7670_resolution_cfg {
47
- uint8_t com7 ;
48
- uint8_t com3 ;
49
- uint8_t com14 ;
50
- uint8_t scaling_xsc ;
51
- uint8_t scaling_ysc ;
52
- uint8_t dcwctr ;
53
- uint8_t pclk_div ;
54
- uint8_t pclk_delay ;
55
- };
56
-
57
- /* Resolution settings for camera, based on those present in MCUX SDK */
58
- const struct ov7670_resolution_cfg OV7670_RESOLUTION_QCIF = {
59
- .com7 = 0x2c ,
60
- .com3 = 0x00 ,
61
- .com14 = 0x11 ,
62
- .scaling_xsc = 0x3a ,
63
- .scaling_ysc = 0x35 ,
64
- .dcwctr = 0x11 ,
65
- .pclk_div = 0xf1 ,
66
- .pclk_delay = 0x52
67
- };
68
-
69
- const struct ov7670_resolution_cfg OV7670_RESOLUTION_QVGA = {
70
- .com7 = 0x14 ,
71
- .com3 = 0x04 ,
72
- .com14 = 0x19 ,
73
- .scaling_xsc = 0x3a ,
74
- .scaling_ysc = 0x35 ,
75
- .dcwctr = 0x11 ,
76
- .pclk_div = 0xf1 ,
77
- .pclk_delay = 0x02
78
- };
79
-
80
- const struct ov7670_resolution_cfg OV7670_RESOLUTION_CIF = {
81
- .com7 = 0x24 ,
82
- .com3 = 0x08 ,
83
- .com14 = 0x11 ,
84
- .scaling_xsc = 0x3a ,
85
- .scaling_ysc = 0x35 ,
86
- .dcwctr = 0x11 ,
87
- .pclk_div = 0xf1 ,
88
- .pclk_delay = 0x02
89
- };
90
-
91
- const struct ov7670_resolution_cfg OV7670_RESOLUTION_VGA = {
92
- .com7 = 0x04 ,
93
- .com3 = 0x00 ,
94
- .com14 = 0x00 ,
95
- .scaling_xsc = 0x3a ,
96
- .scaling_ysc = 0x35 ,
97
- .dcwctr = 0x11 ,
98
- .pclk_div = 0xf0 ,
99
- .pclk_delay = 0x02
100
- };
101
-
102
-
35
+ #define OV7670_REG8 (addr ) ((addr) | VIDEO_REG_ADDR8_DATA8)
103
36
/* OV7670 registers */
104
37
#define OV7670_PID 0x0A
105
38
#define OV7670_COM7 0x12
@@ -190,37 +123,26 @@ const struct ov7670_resolution_cfg OV7670_RESOLUTION_VGA = {
190
123
#define OV7670_HAECC6 0xA9
191
124
192
125
/* OV7670 definitions */
193
- #define OV7670_PROD_ID 0x76
126
+ #define OV7670_PROD_ID 0x76
194
127
#define OV7670_MVFP_HFLIP 0x20
195
128
#define OV7670_MVFP_VFLIP 0x10
196
129
197
- #define OV7670_VIDEO_FORMAT_CAP (width , height , format ) \
130
+ #define OV767X_VIDEO_FORMAT_CAP (width , height , format ) \
198
131
{ \
199
132
.pixelformat = (format), .width_min = (width), .width_max = (width), \
200
133
.height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \
201
134
}
202
135
203
- static const struct video_format_cap fmts [] = {
204
- OV7670_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_RGB565 ), /* QCIF */
205
- OV7670_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_RGB565 ), /* QVGA */
206
- OV7670_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_RGB565 ), /* CIF */
207
- OV7670_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_RGB565 ), /* VGA */
208
- OV7670_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_YUYV ), /* QCIF */
209
- OV7670_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_YUYV ), /* QVGA */
210
- OV7670_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_YUYV ), /* CIF */
211
- OV7670_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_YUYV ), /* VGA */
212
- {0 }};
213
-
214
136
/*
215
137
* This initialization table is based on the MCUX SDK driver for the OV7670.
216
138
* Note that this table assumes the camera is fed a 6MHz XCLK signal
217
139
*/
218
- static const struct ov7670_reg ov7670_init_regtbl [] = {
140
+ static const struct video_reg8 ov7670_init_regtbl [] = {
219
141
{OV7670_MVFP , 0x00 }, /* MVFP: Mirror/VFlip,Normal image */
220
142
221
143
/* configure the output timing */
222
144
/* PCLK does not toggle during horizontal blank, one PCLK, one pixel */
223
- {OV7670_COM10 , 0x20 }, /* COM10 */
145
+ {OV7670_COM10 , 0x03 }, /* COM10 */
224
146
{OV7670_COM12 , 0x00 }, /* COM12,No HREF when VSYNC is low */
225
147
/* Brightness Control, with signal -128 to +128, 0x00 is middle value */
226
148
{OV7670_BRIGHT , 0x2f },
@@ -369,8 +291,67 @@ static const struct ov7670_reg ov7670_init_regtbl[] = {
369
291
{0xb8 , 0x0a },
370
292
};
371
293
294
+ #if DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7670 )
295
+ /* Resolution settings for camera, based on those present in MCUX SDK */
296
+ static const struct video_reg8 ov7670_regs_qcif [] = {
297
+ {OV7670_COM7 , 0x2c },
298
+ {OV7670_COM3 , 0x00 },
299
+ {OV7670_COM14 , 0x11 },
300
+ {OV7670_SCALING_XSC , 0x3a },
301
+ {OV7670_SCALING_YSC , 0x35 },
302
+ {OV7670_SCALING_DCWCTR , 0x11 },
303
+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
304
+ {OV7670_SCALING_PCLK_DELAY , 0x52 },
305
+ };
306
+
307
+ static const struct video_reg8 ov7670_regs_qvga [] = {
308
+ {OV7670_COM7 , 0x14 },
309
+ {OV7670_COM3 , 0x04 },
310
+ {OV7670_COM14 , 0x19 },
311
+ {OV7670_SCALING_XSC , 0x3a },
312
+ {OV7670_SCALING_YSC , 0x35 },
313
+ {OV7670_SCALING_DCWCTR , 0x11 },
314
+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
315
+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
316
+ };
317
+
318
+ static const struct video_reg8 ov7670_regs_cif [] = {
319
+ {OV7670_COM7 , 0x24 },
320
+ {OV7670_COM3 , 0x08 },
321
+ {OV7670_COM14 , 0x11 },
322
+ {OV7670_SCALING_XSC , 0x3a },
323
+ {OV7670_SCALING_YSC , 0x35 },
324
+ {OV7670_SCALING_DCWCTR , 0x11 },
325
+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
326
+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
327
+ };
328
+
329
+ static const struct video_reg8 ov7670_regs_vga [] = {
330
+ {OV7670_COM7 , 0x04 },
331
+ {OV7670_COM3 , 0x00 },
332
+ {OV7670_COM14 , 0x00 },
333
+ {OV7670_SCALING_XSC , 0x3a },
334
+ {OV7670_SCALING_YSC , 0x35 },
335
+ {OV7670_SCALING_DCWCTR , 0x11 },
336
+ {OV7670_SCALING_PCLK_DIV , 0xf0 },
337
+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
338
+ };
339
+
340
+ static const struct video_format_cap fmts [] = {
341
+ OV767X_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_RGB565 ), /* QCIF */
342
+ OV767X_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_RGB565 ), /* QVGA */
343
+ OV767X_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_RGB565 ), /* CIF */
344
+ OV767X_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_RGB565 ), /* VGA */
345
+ OV767X_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_YUYV ), /* QCIF */
346
+ OV767X_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_YUYV ), /* QVGA */
347
+ OV767X_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_YUYV ), /* CIF */
348
+ OV767X_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_YUYV ), /* VGA */
349
+ {0 }};
350
+ #endif
351
+
372
352
static int ov7670_get_caps (const struct device * dev , struct video_caps * caps )
373
353
{
354
+
374
355
caps -> format_caps = fmts ;
375
356
return 0 ;
376
357
}
@@ -379,7 +360,6 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
379
360
{
380
361
const struct ov7670_config * config = dev -> config ;
381
362
struct ov7670_data * data = dev -> data ;
382
- const struct ov7670_resolution_cfg * resolution ;
383
363
int ret ;
384
364
uint8_t i = 0U ;
385
365
@@ -397,67 +377,38 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
397
377
398
378
/* Set output resolution */
399
379
while (fmts [i ].pixelformat ) {
400
- if (fmts [i ].width_min == fmt -> width && fmts [i ].height_min == fmt -> height &&
380
+ if (fmts [i ].width_min == fmt -> width &&
381
+ fmts [i ].height_min == fmt -> height &&
401
382
fmts [i ].pixelformat == fmt -> pixelformat ) {
402
383
/* Set output format */
403
384
switch (fmts [i ].width_min ) {
404
385
case 176 : /* QCIF */
405
- resolution = & OV7670_RESOLUTION_QCIF ;
406
- break ;
407
- case 320 : /* QVGA */
408
- resolution = & OV7670_RESOLUTION_QVGA ;
386
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qcif ,
387
+ ARRAY_SIZE (ov7670_regs_qcif ));
409
388
break ;
410
389
case 352 : /* CIF */
411
- resolution = & OV7670_RESOLUTION_CIF ;
390
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_cif ,
391
+ ARRAY_SIZE (ov7670_regs_cif ));
412
392
break ;
393
+ case 320 : /* QVGA */
394
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qvga ,
395
+ ARRAY_SIZE (ov7670_regs_qvga ));
396
+ break ;
397
+
413
398
default : /* VGA */
414
- resolution = & OV7670_RESOLUTION_VGA ;
399
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_vga ,
400
+ ARRAY_SIZE (ov7670_regs_vga ));
415
401
break ;
416
402
}
417
- /* Program resolution bytes settings */
418
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM7 ,
419
- resolution -> com7 );
420
403
if (ret < 0 ) {
404
+ LOG_ERR ("Resolution not set or not supported!" );
421
405
return ret ;
422
406
}
423
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM3 ,
424
- resolution -> com3 );
425
- if (ret < 0 ) {
426
- return ret ;
427
- }
428
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM14 ,
429
- resolution -> com14 );
430
- if (ret < 0 ) {
431
- return ret ;
432
- }
433
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_XSC ,
434
- resolution -> scaling_xsc );
435
- if (ret < 0 ) {
436
- return ret ;
437
- }
438
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_YSC ,
439
- resolution -> scaling_ysc );
440
- if (ret < 0 ) {
441
- return ret ;
442
- }
443
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_DCWCTR ,
444
- resolution -> dcwctr );
445
- if (ret < 0 ) {
446
- return ret ;
447
- }
448
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_PCLK_DIV ,
449
- resolution -> pclk_div );
450
- if (ret < 0 ) {
451
- return ret ;
452
- }
453
- return i2c_reg_write_byte_dt (& config -> bus , OV7670_SCALING_PCLK_DELAY ,
454
- resolution -> pclk_delay );
455
407
}
456
408
i ++ ;
457
409
}
458
410
459
- LOG_ERR ("Unsupported format" );
460
- return - ENOTSUP ;
411
+ return 0 ;
461
412
}
462
413
463
414
static int ov7670_get_fmt (const struct device * dev , struct video_format * fmt )
@@ -487,14 +438,13 @@ static int ov7670_init_controls(const struct device *dev)
487
438
static int ov7670_init (const struct device * dev )
488
439
{
489
440
const struct ov7670_config * config = dev -> config ;
490
- int ret , i ;
441
+ int ret ;
491
442
uint8_t pid ;
492
443
struct video_format fmt = {
493
444
.pixelformat = VIDEO_PIX_FMT_RGB565 ,
494
445
.width = 320 ,
495
446
.height = 240 ,
496
447
};
497
- const struct ov7670_reg * reg ;
498
448
499
449
if (!i2c_is_ready_dt (& config -> bus )) {
500
450
/* I2C device is not ready, return */
@@ -559,7 +509,7 @@ static int ov7670_init(const struct device *dev)
559
509
}
560
510
561
511
/* Reset camera registers */
562
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM7 , 0x80 );
512
+ ret = video_write_cci_reg (& config -> bus , OV7670_REG8 ( OV7670_COM7 ) , 0x80 );
563
513
if (ret < 0 ) {
564
514
LOG_ERR ("Could not reset camera: %d" , ret );
565
515
return ret ;
@@ -573,12 +523,10 @@ static int ov7670_init(const struct device *dev)
573
523
}
574
524
575
525
/* Write initialization values to OV7670 */
576
- for (i = 0 ; i < ARRAY_SIZE (ov7670_init_regtbl ); i ++ ) {
577
- reg = & ov7670_init_regtbl [i ];
578
- ret = i2c_reg_write_byte_dt (& config -> bus , reg -> reg , reg -> cmd );
579
- if (ret < 0 ) {
580
- return ret ;
581
- }
526
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_init_regtbl ,
527
+ ARRAY_SIZE (ov7670_init_regtbl ));
528
+ if (ret < 0 ) {
529
+ return ret ;
582
530
}
583
531
584
532
/* Initialize controls */
@@ -616,27 +564,28 @@ static DEVICE_API(video, ov7670_api) = {
616
564
.set_ctrl = ov7670_set_ctrl ,
617
565
};
618
566
619
- #if DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
620
- #define OV7670_RESET_GPIO (inst ) .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}),
621
- #else
622
- #define OV7670_RESET_GPIO (inst )
623
- #endif
624
-
625
- #if DT_ANY_INST_HAS_PROP_STATUS_OKAY (pwdn_gpios )
626
- #define OV7670_PWDN_GPIO (inst ) .pwdn = GPIO_DT_SPEC_INST_GET_OR(inst, pwdn_gpios, {}),
627
- #else
628
- #define OV7670_PWDN_GPIO (inst )
629
- #endif
630
-
631
- #define OV7670_INIT (inst ) \
632
- const struct ov7670_config ov7670_config_##inst = {.bus = I2C_DT_SPEC_INST_GET(inst), \
633
- OV7670_RESET_GPIO(inst) \
634
- OV7670_PWDN_GPIO(inst)}; \
635
- struct ov7670_data ov7670_data_##inst; \
636
- \
637
- DEVICE_DT_INST_DEFINE(inst, ov7670_init, NULL, &ov7670_data_##inst, &ov7670_config_##inst, \
638
- POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &ov7670_api); \
639
- \
640
- VIDEO_DEVICE_DEFINE(ov7670_##inst, DEVICE_DT_INST_GET(inst), NULL);
641
-
642
- DT_INST_FOREACH_STATUS_OKAY (OV7670_INIT )
567
+ #define OV7670_INIT (n , id ) \
568
+ static const struct ov7670_config ov7670_config_##n = { \
569
+ .bus = I2C_DT_SPEC_INST_GET(n), \
570
+ .reset = \
571
+ GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {}), \
572
+ .pwdn = \
573
+ GPIO_DT_SPEC_INST_GET_OR(n, pwdn_gpios, {}), \
574
+ }; \
575
+ \
576
+ static struct ov7670_data ov7670_data_##n; \
577
+ \
578
+ DEVICE_DT_INST_DEFINE(n, \
579
+ ov7670_init, \
580
+ NULL, \
581
+ &ov7670##_data_##n, \
582
+ &ov7670##_config_##n, \
583
+ POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
584
+ &ov7670_api); \
585
+ \
586
+ VIDEO_DEVICE_DEFINE(ov7670_##n, DEVICE_DT_INST_GET(n), NULL); \
587
+
588
+
589
+ #undef DT_DRV_COMPAT
590
+ #define DT_DRV_COMPAT ovti_ov7670
591
+ DT_INST_FOREACH_STATUS_OKAY_VARGS (OV7670_INIT , 7670 )
0 commit comments