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
21
#if DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
@@ -43,63 +36,7 @@ struct ov7670_data {
43
36
struct video_format fmt ;
44
37
};
45
38
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
-
39
+ #define OV7670_REG8 (addr ) ((addr) | VIDEO_REG_ADDR8_DATA8)
103
40
/* OV7670 registers */
104
41
#define OV7670_PID 0x0A
105
42
#define OV7670_COM7 0x12
@@ -190,32 +127,21 @@ const struct ov7670_resolution_cfg OV7670_RESOLUTION_VGA = {
190
127
#define OV7670_HAECC6 0xA9
191
128
192
129
/* OV7670 definitions */
193
- #define OV7670_PROD_ID 0x76
130
+ #define OV7670_PROD_ID 0x76
194
131
#define OV7670_MVFP_HFLIP 0x20
195
132
#define OV7670_MVFP_VFLIP 0x10
196
133
197
- #define OV7670_VIDEO_FORMAT_CAP (width , height , format ) \
134
+ #define OV767X_VIDEO_FORMAT_CAP (width , height , format ) \
198
135
{ \
199
136
.pixelformat = (format), .width_min = (width), .width_max = (width), \
200
137
.height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \
201
138
}
202
139
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
140
/*
215
141
* This initialization table is based on the MCUX SDK driver for the OV7670.
216
142
* Note that this table assumes the camera is fed a 6MHz XCLK signal
217
143
*/
218
- static const struct ov7670_reg ov7670_init_regtbl [] = {
144
+ static const struct video_reg8 ov7670_init_regtbl [] = {
219
145
{OV7670_MVFP , 0x00 }, /* MVFP: Mirror/VFlip,Normal image */
220
146
221
147
/* configure the output timing */
@@ -369,8 +295,66 @@ static const struct ov7670_reg ov7670_init_regtbl[] = {
369
295
{0xb8 , 0x0a },
370
296
};
371
297
298
+ /* Resolution settings for camera, based on those present in MCUX SDK */
299
+ static const struct video_reg8 ov7670_regs_qcif [] = {
300
+ {OV7670_COM7 , 0x2c },
301
+ {OV7670_COM3 , 0x00 },
302
+ {OV7670_COM14 , 0x11 },
303
+ {OV7670_SCALING_XSC , 0x3a },
304
+ {OV7670_SCALING_YSC , 0x35 },
305
+ {OV7670_SCALING_DCWCTR , 0x11 },
306
+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
307
+ {OV7670_SCALING_PCLK_DELAY , 0x52 },
308
+ };
309
+
310
+ static const struct video_reg8 ov7670_regs_qvga [] = {
311
+ {OV7670_COM7 , 0x14 },
312
+ {OV7670_COM3 , 0x04 },
313
+ {OV7670_COM14 , 0x19 },
314
+ {OV7670_SCALING_XSC , 0x3a },
315
+ {OV7670_SCALING_YSC , 0x35 },
316
+ {OV7670_SCALING_DCWCTR , 0x11 },
317
+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
318
+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
319
+ };
320
+
321
+ static const struct video_reg8 ov7670_regs_cif [] = {
322
+ {OV7670_COM7 , 0x24 },
323
+ {OV7670_COM3 , 0x08 },
324
+ {OV7670_COM14 , 0x11 },
325
+ {OV7670_SCALING_XSC , 0x3a },
326
+ {OV7670_SCALING_YSC , 0x35 },
327
+ {OV7670_SCALING_DCWCTR , 0x11 },
328
+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
329
+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
330
+ };
331
+
332
+ static const struct video_reg8 ov7670_regs_vga [] = {
333
+ {OV7670_COM7 , 0x04 },
334
+ {OV7670_COM3 , 0x00 },
335
+ {OV7670_COM14 , 0x00 },
336
+ {OV7670_SCALING_XSC , 0x3a },
337
+ {OV7670_SCALING_YSC , 0x35 },
338
+ {OV7670_SCALING_DCWCTR , 0x11 },
339
+ {OV7670_SCALING_PCLK_DIV , 0xf0 },
340
+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
341
+ };
342
+
343
+ static const struct video_format_cap fmts [] = {
344
+ OV767X_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_RGB565 ), /* QCIF */
345
+ OV767X_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_RGB565 ), /* QVGA */
346
+ OV767X_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_RGB565 ), /* CIF */
347
+ OV767X_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_RGB565 ), /* VGA */
348
+ OV767X_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_YUYV ), /* QCIF */
349
+ OV767X_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_YUYV ), /* QVGA */
350
+ OV767X_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_YUYV ), /* CIF */
351
+ OV767X_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_YUYV ), /* VGA */
352
+ {0 }
353
+ };
354
+
372
355
static int ov7670_get_caps (const struct device * dev , struct video_caps * caps )
373
356
{
357
+
374
358
caps -> format_caps = fmts ;
375
359
return 0 ;
376
360
}
@@ -379,9 +363,8 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
379
363
{
380
364
const struct ov7670_config * config = dev -> config ;
381
365
struct ov7670_data * data = dev -> data ;
382
- const struct ov7670_resolution_cfg * resolution ;
383
366
int ret ;
384
- uint8_t i = 0U ;
367
+ uint8_t icount = 0U ;
385
368
386
369
if (fmt -> pixelformat != VIDEO_PIX_FMT_RGB565 && fmt -> pixelformat != VIDEO_PIX_FMT_YUYV ) {
387
370
LOG_ERR ("Only RGB565 and YUYV supported!" );
@@ -395,69 +378,46 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
395
378
396
379
memcpy (& data -> fmt , fmt , sizeof (data -> fmt ));
397
380
381
+ uint32_t a , b , c ;
382
+
398
383
/* Set output resolution */
399
- while (fmts [i ].pixelformat ) {
400
- if (fmts [i ].width_min == fmt -> width && fmts [i ].height_min == fmt -> height &&
401
- fmts [i ].pixelformat == fmt -> pixelformat ) {
384
+ ret = - ENOTSUP ;
385
+ icount = 0 ;
386
+ while (fmts [icount ].pixelformat ) {
387
+ a = fmts [icount ].width_min ;
388
+ b = fmts [icount ].height_min ;
389
+ c = fmts [icount ].pixelformat ;
390
+ if (a == fmt -> width && b == fmt -> height && c == fmt -> pixelformat ) {
402
391
/* Set output format */
403
- switch (fmts [i ].width_min ) {
392
+ switch (fmts [icount ].width_min ) {
404
393
case 176 : /* QCIF */
405
- resolution = & OV7670_RESOLUTION_QCIF ;
406
- break ;
407
- case 320 : /* QVGA */
408
- resolution = & OV7670_RESOLUTION_QVGA ;
394
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qcif ,
395
+ ARRAY_SIZE (ov7670_regs_qcif ));
409
396
break ;
410
- case 352 : /* CIF */
411
- resolution = & OV7670_RESOLUTION_CIF ;
397
+ case 352 : /* QCIF */
398
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_cif ,
399
+ ARRAY_SIZE (ov7670_regs_cif ));
412
400
break ;
413
- default : /* VGA */
414
- resolution = & OV7670_RESOLUTION_VGA ;
401
+ case 320 : /* QVGA */
402
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qvga ,
403
+ ARRAY_SIZE (ov7670_regs_qvga ));
404
+ case 640 : /* VGA */
405
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_vga ,
406
+ ARRAY_SIZE (ov7670_regs_vga ));
407
+ default : /* QVGA */
408
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qvga ,
409
+ ARRAY_SIZE (ov7670_regs_vga ));
415
410
break ;
416
411
}
417
- /* Program resolution bytes settings */
418
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM7 ,
419
- resolution -> com7 );
420
412
if (ret < 0 ) {
413
+ LOG_ERR ("Resolution not set!" );
421
414
return ret ;
422
415
}
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
416
}
456
- i ++ ;
417
+ icount ++ ;
457
418
}
458
419
459
- LOG_ERR ("Unsupported format" );
460
- return - ENOTSUP ;
420
+ return ret ;
461
421
}
462
422
463
423
static int ov7670_get_fmt (const struct device * dev , struct video_format * fmt )
@@ -487,14 +447,13 @@ static int ov7670_init_controls(const struct device *dev)
487
447
static int ov7670_init (const struct device * dev )
488
448
{
489
449
const struct ov7670_config * config = dev -> config ;
490
- int ret , i ;
450
+ int ret ;
491
451
uint8_t pid ;
492
452
struct video_format fmt = {
493
453
.pixelformat = VIDEO_PIX_FMT_RGB565 ,
494
454
.width = 320 ,
495
455
.height = 240 ,
496
456
};
497
- const struct ov7670_reg * reg ;
498
457
499
458
if (!i2c_is_ready_dt (& config -> bus )) {
500
459
/* I2C device is not ready, return */
@@ -559,7 +518,7 @@ static int ov7670_init(const struct device *dev)
559
518
}
560
519
561
520
/* Reset camera registers */
562
- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM7 , 0x80 );
521
+ ret = video_write_cci_reg (& config -> bus , OV7670_REG8 ( OV7670_COM7 ) , 0x80 );
563
522
if (ret < 0 ) {
564
523
LOG_ERR ("Could not reset camera: %d" , ret );
565
524
return ret ;
@@ -573,12 +532,10 @@ static int ov7670_init(const struct device *dev)
573
532
}
574
533
575
534
/* 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
- }
535
+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_init_regtbl ,
536
+ ARRAY_SIZE (ov7670_init_regtbl ));
537
+ if (ret < 0 ) {
538
+ return ret ;
582
539
}
583
540
584
541
/* Initialize controls */
@@ -617,26 +574,36 @@ static DEVICE_API(video, ov7670_api) = {
617
574
};
618
575
619
576
#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, {}),
577
+ #define OV7670_RESET_GPIO (n ) .reset = GPIO_DT_SPEC_INST_GET_OR(n , reset_gpios, {}),
621
578
#else
622
- #define OV7670_RESET_GPIO (inst )
579
+ #define OV7670_RESET_GPIO (n )
623
580
#endif
624
581
625
582
#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, {}),
583
+ #define OV7670_PWDN_GPIO (n ) .pwdn = GPIO_DT_SPEC_INST_GET_OR(n , pwdn_gpios, {}),
627
584
#else
628
- #define OV7670_PWDN_GPIO (inst )
585
+ #define OV7670_PWDN_GPIO (n )
629
586
#endif
630
587
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
-
588
+ #define OV7670_INIT (n ) \
589
+ const struct ov7670_config ov7670_config_##n = { \
590
+ .bus = I2C_DT_SPEC_INST_GET(n), \
591
+ OV7670_RESET_GPIO(n) \
592
+ OV7670_PWDN_GPIO(n)}; \
593
+ \
594
+ static struct ov7670_data ov7670_data_##n; \
595
+ \
596
+ DEVICE_DT_INST_DEFINE(n, \
597
+ ov7670_init, \
598
+ NULL, \
599
+ &ov7670_data_##n, \
600
+ &ov7670_config_##n, \
601
+ POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \
602
+ &ov7670_api); \
603
+ \
604
+ VIDEO_DEVICE_DEFINE(ov7670_##n, DEVICE_DT_INST_GET(n), NULL); \
605
+
606
+
607
+ #undef DT_DRV_COMPAT
608
+ #define DT_DRV_COMPAT ovti_ov7670
642
609
DT_INST_FOREACH_STATUS_OKAY (OV7670_INIT )
0 commit comments