1212#include <zephyr/drivers/video-controls.h>
1313#include <zephyr/logging/log.h>
1414
15+ #include "video_common.h"
1516#include "video_ctrls.h"
1617#include "video_device.h"
1718
1819LOG_MODULE_REGISTER (video_ov7670 , CONFIG_VIDEO_LOG_LEVEL );
1920
20- /* Initialization register structure */
21- struct ov7670_reg {
22- uint8_t reg ;
23- uint8_t cmd ;
24- };
25-
2621struct ov7670_config {
2722 struct i2c_dt_spec bus ;
2823#if DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
@@ -43,63 +38,7 @@ struct ov7670_data {
4338 struct video_format fmt ;
4439};
4540
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-
41+ #define OV7670_REG8 (addr ) ((addr) | VIDEO_REG_ADDR8_DATA8)
10342/* OV7670 registers */
10443#define OV7670_PID 0x0A
10544#define OV7670_COM7 0x12
@@ -195,10 +134,10 @@ const struct ov7670_resolution_cfg OV7670_RESOLUTION_VGA = {
195134#define OV7670_MVFP_VFLIP 0x10
196135
197136#define OV7670_VIDEO_FORMAT_CAP (width , height , format ) \
198- { \
199- .pixelformat = (format), .width_min = (width), .width_max = (width), \
200- .height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \
201- }
137+ { \
138+ .pixelformat = (format), .width_min = (width), .width_max = (width), \
139+ .height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \
140+ }
202141
203142static const struct video_format_cap fmts [] = {
204143 OV7670_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_RGB565 ), /* QCIF */
@@ -209,13 +148,14 @@ static const struct video_format_cap fmts[] = {
209148 OV7670_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_YUYV ), /* QVGA */
210149 OV7670_VIDEO_FORMAT_CAP (352 , 288 , VIDEO_PIX_FMT_YUYV ), /* CIF */
211150 OV7670_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_YUYV ), /* VGA */
212- {0 }};
151+ {0 }
152+ };
213153
214154/*
215155 * This initialization table is based on the MCUX SDK driver for the OV7670.
216156 * Note that this table assumes the camera is fed a 6MHz XCLK signal
217157 */
218- static const struct ov7670_reg ov7670_init_regtbl [] = {
158+ static const struct video_reg8 ov7670_init_regtbl [] = {
219159 {OV7670_MVFP , 0x00 }, /* MVFP: Mirror/VFlip,Normal image */
220160
221161 /* configure the output timing */
@@ -369,6 +309,51 @@ static const struct ov7670_reg ov7670_init_regtbl[] = {
369309 {0xb8 , 0x0a },
370310};
371311
312+ /* Resolution settings for camera, based on those present in MCUX SDK */
313+ static const struct video_reg8 ov7670_regs_qcif [] = {
314+ {OV7670_COM7 , 0x2c },
315+ {OV7670_COM3 , 0x00 },
316+ {OV7670_COM14 , 0x11 },
317+ {OV7670_SCALING_XSC , 0x3a },
318+ {OV7670_SCALING_YSC , 0x35 },
319+ {OV7670_SCALING_DCWCTR , 0x11 },
320+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
321+ {OV7670_SCALING_PCLK_DELAY , 0x52 },
322+ };
323+
324+ static const struct video_reg8 ov7670_regs_qvga [] = {
325+ {OV7670_COM7 , 0x14 },
326+ {OV7670_COM3 , 0x04 },
327+ {OV7670_COM14 , 0x19 },
328+ {OV7670_SCALING_XSC , 0x3a },
329+ {OV7670_SCALING_YSC , 0x35 },
330+ {OV7670_SCALING_DCWCTR , 0x11 },
331+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
332+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
333+ };
334+
335+ static const struct video_reg8 ov7670_regs_cif [] = {
336+ {OV7670_COM7 , 0x24 },
337+ {OV7670_COM3 , 0x08 },
338+ {OV7670_COM14 , 0x11 },
339+ {OV7670_SCALING_XSC , 0x3a },
340+ {OV7670_SCALING_YSC , 0x35 },
341+ {OV7670_SCALING_DCWCTR , 0x11 },
342+ {OV7670_SCALING_PCLK_DIV , 0xf1 },
343+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
344+ };
345+
346+ static const struct video_reg8 ov7670_regs_vga [] = {
347+ {OV7670_COM7 , 0x04 },
348+ {OV7670_COM3 , 0x00 },
349+ {OV7670_COM14 , 0x00 },
350+ {OV7670_SCALING_XSC , 0x3a },
351+ {OV7670_SCALING_YSC , 0x35 },
352+ {OV7670_SCALING_DCWCTR , 0x11 },
353+ {OV7670_SCALING_PCLK_DIV , 0xf0 },
354+ {OV7670_SCALING_PCLK_DELAY , 0x02 },
355+ };
356+
372357static int ov7670_get_caps (const struct device * dev , struct video_caps * caps )
373358{
374359 caps -> format_caps = fmts ;
@@ -379,8 +364,7 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
379364{
380365 const struct ov7670_config * config = dev -> config ;
381366 struct ov7670_data * data = dev -> data ;
382- const struct ov7670_resolution_cfg * resolution ;
383- int ret ;
367+ int ret = - ENOTSUP ;
384368 uint8_t i = 0U ;
385369
386370 if (fmt -> pixelformat != VIDEO_PIX_FMT_RGB565 && fmt -> pixelformat != VIDEO_PIX_FMT_YUYV ) {
@@ -397,67 +381,46 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
397381
398382 /* Set output resolution */
399383 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+ if (fmts [i ].width_min == fmt -> width &&
385+ fmts [i ].height_min == fmt -> height &&
386+ fmts [i ].pixelformat == fmt -> pixelformat ) {
402387 /* Set output format */
403388 switch (fmts [i ].width_min ) {
404389 case 176 : /* QCIF */
405- resolution = & OV7670_RESOLUTION_QCIF ;
390+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qcif ,
391+ ARRAY_SIZE (ov7670_regs_qcif ));
392+ break ;
393+ case 352 : /* QCIF */
394+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_cif ,
395+ ARRAY_SIZE (ov7670_regs_cif ));
406396 break ;
407397 case 320 : /* QVGA */
408- resolution = & OV7670_RESOLUTION_QVGA ;
398+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qvga ,
399+ ARRAY_SIZE (ov7670_regs_qvga ));
409400 break ;
410- case 352 : /* CIF */
411- resolution = & OV7670_RESOLUTION_CIF ;
401+ case 640 : /* VGA */
402+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_vga ,
403+ ARRAY_SIZE (ov7670_regs_vga ));
412404 break ;
413- default : /* VGA */
414- resolution = & OV7670_RESOLUTION_VGA ;
405+ default : /* QVGA */
406+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qvga ,
407+ ARRAY_SIZE (ov7670_regs_vga ));
415408 break ;
416409 }
417- /* Program resolution bytes settings */
418- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM7 ,
419- resolution -> com7 );
420- if (ret < 0 ) {
421- return ret ;
422- }
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 );
445410 if (ret < 0 ) {
411+ LOG_ERR ("Resolution not set!" );
446412 return ret ;
447413 }
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 );
455414 }
456415 i ++ ;
457416 }
458417
459- LOG_ERR ("Unsupported format" );
460- return - ENOTSUP ;
418+ if (ret < 0 ) {
419+ LOG_ERR ("Resolution not supported!" );
420+ return ret ;
421+ }
422+
423+ return 0 ;
461424}
462425
463426static int ov7670_get_fmt (const struct device * dev , struct video_format * fmt )
@@ -487,14 +450,13 @@ static int ov7670_init_controls(const struct device *dev)
487450static int ov7670_init (const struct device * dev )
488451{
489452 const struct ov7670_config * config = dev -> config ;
490- int ret , i ;
453+ int ret ;
491454 uint8_t pid ;
492455 struct video_format fmt = {
493456 .pixelformat = VIDEO_PIX_FMT_RGB565 ,
494457 .width = 320 ,
495458 .height = 240 ,
496459 };
497- const struct ov7670_reg * reg ;
498460
499461 if (!i2c_is_ready_dt (& config -> bus )) {
500462 /* I2C device is not ready, return */
@@ -559,7 +521,7 @@ static int ov7670_init(const struct device *dev)
559521 }
560522
561523 /* Reset camera registers */
562- ret = i2c_reg_write_byte_dt (& config -> bus , OV7670_COM7 , 0x80 );
524+ ret = video_write_cci_reg (& config -> bus , OV7670_REG8 ( OV7670_COM7 ) , 0x80 );
563525 if (ret < 0 ) {
564526 LOG_ERR ("Could not reset camera: %d" , ret );
565527 return ret ;
@@ -568,17 +530,17 @@ static int ov7670_init(const struct device *dev)
568530 k_msleep (5 );
569531
570532 ret = ov7670_set_fmt (dev , & fmt );
533+
571534 if (ret < 0 ) {
572535 return ret ;
573536 }
574537
575538 /* 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- }
539+ ret = video_write_cci_multiregs8 (& config -> bus , ov7670_init_regtbl ,
540+ ARRAY_SIZE (ov7670_init_regtbl ));
541+
542+ if (ret < 0 ) {
543+ return ret ;
582544 }
583545
584546 /* Initialize controls */
@@ -631,12 +593,13 @@ static DEVICE_API(video, ov7670_api) = {
631593#define OV7670_INIT (inst ) \
632594 const struct ov7670_config ov7670_config_##inst = {.bus = I2C_DT_SPEC_INST_GET(inst), \
633595 OV7670_RESET_GPIO(inst) \
634- OV7670_PWDN_GPIO(inst)}; \
596+ OV7670_PWDN_GPIO(inst)}; \
597+ \
635598 struct ov7670_data ov7670_data_##inst; \
636599 \
637600 DEVICE_DT_INST_DEFINE(inst, ov7670_init, NULL, &ov7670_data_##inst, &ov7670_config_##inst, \
638601 POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &ov7670_api); \
639602 \
640603 VIDEO_DEVICE_DEFINE(ov7670_##inst, DEVICE_DT_INST_GET(inst), NULL);
641604
642- DT_INST_FOREACH_STATUS_OKAY (OV7670_INIT )
605+ DT_INST_FOREACH_STATUS_OKAY (OV7670_INIT )
0 commit comments