@@ -24,10 +24,12 @@ struct ov767x_config {
2424 struct i2c_dt_spec bus ;
2525 uint32_t camera_model ;
2626 const struct video_format_cap * fmts ;
27- #if DT_ANY_INST_HAS_PROP_STATUS_OKAY (reset_gpios )
27+ #if DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7670 , reset_gpios ) || \
28+ DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7675 , reset_gpios )
2829 struct gpio_dt_spec reset ;
2930#endif
30- #if DT_ANY_INST_HAS_PROP_STATUS_OKAY (pwdn_gpios )
31+ #if DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7670 , pwdn_gpios ) || \
32+ DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7675 , pwdn_gpios )
3133 struct gpio_dt_spec pwdn ;
3234#endif
3335};
@@ -132,6 +134,16 @@ struct ov767x_data {
132134#define OV7670_HAECC5 0xA8
133135#define OV7670_HAECC6 0xA9
134136
137+ /* Addition defines for OV7675 */
138+ #define OV7675_RGB444 0x8C /* REG444 */
139+ #define OV7675_COM3_DCW_EN 0x04 /* DCW enable */
140+ #define OV7670_COM1 0x04 /*Com Cntrl1 */
141+ #define OV7675_COM7_RGB_FMT 0x04 /* Output format RGB */
142+ #define OV7675_COM13_GAMMA_EN 0x80 /* Gamma enable */
143+ #define OV7675_COM13_UVSAT_AUTO 0x40 /* UV saturation level - UV auto adjustment. */
144+ #define OV7675_COM15_OUT_00_FF 0xC0 /* Output data range 00 to FF */
145+ #define OV7675_COM15_FMT_RGB565 0x10 /* Normal RGB 565 output */
146+
135147/* OV7670 definitions */
136148#define OV7670_PROD_ID 0x76
137149#define OV7670_MVFP_HFLIP 0x20
@@ -141,11 +153,12 @@ struct ov767x_data {
141153#define OV767X_MODEL_OV7675 7675
142154
143155#define OV767X_VIDEO_FORMAT_CAP (width , height , format ) \
144- { \
145- .pixelformat = (format), .width_min = (width), .width_max = (width), \
146- .height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \
147- }
156+ { \
157+ .pixelformat = (format), .width_min = (width), .width_max = (width), \
158+ .height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \
159+ }
148160
161+ #if DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7670 )
149162static const struct video_format_cap ov7670_fmts [] = {
150163 OV767X_VIDEO_FORMAT_CAP (176 , 144 , VIDEO_PIX_FMT_RGB565 ), /* QCIF */
151164 OV767X_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_RGB565 ), /* QVGA */
@@ -157,6 +170,19 @@ static const struct video_format_cap ov7670_fmts[] = {
157170 OV767X_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_YUYV ), /* VGA */
158171 {0 }
159172};
173+ #endif
174+
175+ #if DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7675 )
176+ static const struct video_format_cap ov7675_fmts [] = {
177+ OV767X_VIDEO_FORMAT_CAP (160 , 120 , VIDEO_PIX_FMT_RGB565 ), /* QQVGA */
178+ OV767X_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_RGB565 ), /* QVGA */
179+ OV767X_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_RGB565 ), /* VGA */
180+ OV767X_VIDEO_FORMAT_CAP (160 , 120 , VIDEO_PIX_FMT_YUYV ), /* QQVGA */
181+ OV767X_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_YUYV ), /* QVGA */
182+ OV767X_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_YUYV ), /* VGA */
183+ {0 }
184+ };
185+ #endif
160186
161187/*
162188 * This initialization table is based on the MCUX SDK driver for the OV7670.
@@ -167,7 +193,7 @@ static const struct video_reg8 ov767x_init_regtbl[] = {
167193
168194 /* configure the output timing */
169195 /* PCLK does not toggle during horizontal blank, one PCLK, one pixel */
170- {OV7670_COM10 , 0x20 }, /* COM10 */
196+ {OV7670_COM10 , 0x03 }, /* COM10 */
171197 {OV7670_COM12 , 0x00 }, /* COM12,No HREF when VSYNC is low */
172198 /* Brightness Control, with signal -128 to +128, 0x00 is middle value */
173199 {OV7670_BRIGHT , 0x2f },
@@ -316,6 +342,37 @@ static const struct video_reg8 ov767x_init_regtbl[] = {
316342 {0xb8 , 0x0a },
317343};
318344
345+ static const struct video_reg8 ov767x_rgb565_regs [] = {
346+ {OV7670_COM7 , OV7675_COM7_RGB_FMT }, /* Selects RGB mode */
347+ {OV7675_RGB444 , 0x00 }, /* No RGB444 please */
348+ {OV7670_COM1 , 0x00 }, /* CCIR601 */
349+ {OV7670_COM15 , OV7675_COM15_OUT_00_FF | OV7675_COM15_FMT_RGB565 },
350+ {OV7670_COM9 , 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */
351+ {0x4f , 0xb3 }, /* "matrix coefficient 1" */
352+ {0x50 , 0xb3 }, /* "matrix coefficient 2" */
353+ {0x51 , 0x00 }, /* "matrix Coefficient 3" */
354+ {0x52 , 0x3d }, /* "matrix coefficient 4" */
355+ {0x53 , 0xa7 }, /* "matrix coefficient 5" */
356+ {0x54 , 0xe4 }, /* "matrix coefficient 6" */
357+ {OV7670_COM13 , OV7675_COM13_GAMMA_EN | OV7675_COM13_UVSAT_AUTO },
358+ };
359+
360+ /* TODO: These registers probably need to be fixed too. */
361+ static const struct video_reg8 ov767x_yuv422_regs [] = {
362+ {OV7670_COM7 , 0x00 }, /* Selects YUV mode */
363+ {OV7675_RGB444 , 0x00 }, /* No RGB444 please */
364+ {OV7670_COM1 , 0x00 }, /* CCIR601 */
365+ {OV7670_COM15 , OV7675_COM15_OUT_00_FF },
366+ {OV7670_COM9 , 0x48 }, /* 32x gain ceiling; 0x8 is reserved bit */
367+ {0x4f , 0x80 }, /* "matrix coefficient 1" */
368+ {0x50 , 0x80 }, /* "matrix coefficient 2" */
369+ {0x51 , 0x00 }, /* vb */
370+ {0x52 , 0x22 }, /* "matrix coefficient 4" */
371+ {0x53 , 0x5e }, /* "matrix coefficient 5" */
372+ {0x54 , 0x80 }, /* "matrix coefficient 6" */
373+ {OV7670_COM13 , OV7675_COM13_GAMMA_EN | OV7675_COM13_UVSAT_AUTO },
374+ };
375+
319376/* Resolution settings for camera, based on those present in MCUX SDK */
320377static const struct video_reg8 ov7670_regs_qcif [] = {
321378 {OV7670_COM7 , 0x2c },
@@ -361,6 +418,39 @@ static const struct video_reg8 ov7670_regs_vga[] = {
361418 {OV7670_SCALING_PCLK_DELAY , 0x02 },
362419};
363420
421+ static const struct video_reg8 ov7675_regs_vga [] = {
422+ {OV7670_COM3 , 0x00 }, {OV7670_COM14 , 0x00 }, {0x72 , 0x11 }, /* downsample by 4 */
423+ {0x73 , 0xf0 }, /* divide by 4 */
424+ {OV7670_HSTART , 0x12 }, {OV7670_HSTOP , 0x00 }, {OV7670_HREF , 0xb6 },
425+ {OV7670_VSTRT , 0x02 }, {OV7670_VSTOP , 0x7a }, {OV7670_VREF , 0x00 },
426+ };
427+
428+ static const struct video_reg8 ov7675_regs_qvga [] = {
429+ {OV7670_COM3 , OV7675_COM3_DCW_EN },
430+ {OV7670_COM14 , 0x11 }, /* Divide by 2 */
431+ {0x72 , 0x22 }, /* This has no effect on OV7675 */
432+ {0x73 , 0xf2 }, /* This has no effect on OV7675 */
433+ {OV7670_HSTART , 0x15 },
434+ {OV7670_HSTOP , 0x03 },
435+ {OV7670_HREF , 0xC0 },
436+ {OV7670_VSTRT , 0x03 },
437+ {OV7670_VSTOP , 0x7B },
438+ {OV7670_VREF , 0xF0 },
439+ };
440+
441+ static const struct video_reg8 ov7675_regs_qqvga [] = {
442+ {OV7670_COM3 , OV7675_COM3_DCW_EN },
443+ {OV7670_COM14 , 0x11 }, /* Divide by 2 */
444+ {0x72 , 0x22 }, /* This has no effect on OV7675*/
445+ {0x73 , 0xf2 }, /* This has no effect on OV7675*/
446+ {OV7670_HSTART , 0x16 },
447+ {OV7670_HSTOP , 0x04 },
448+ {OV7670_HREF , 0xa4 },
449+ {OV7670_VSTRT , 0x22 },
450+ {OV7670_VSTOP , 0x7a },
451+ {OV7670_VREF , 0xfa },
452+ };
453+
364454static int ov767x_get_caps (const struct device * dev , struct video_caps * caps )
365455{
366456 const struct ov767x_config * config = dev -> config ;
@@ -369,8 +459,7 @@ static int ov767x_get_caps(const struct device *dev, struct video_caps *caps)
369459 return 0 ;
370460}
371461
372- #if DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7670 )
373- static int ov7670_set_fmt (const struct device * dev , struct video_format * fmt )
462+ static int ov767x_set_fmt (const struct device * dev , struct video_format * fmt )
374463{
375464 const struct ov767x_config * config = dev -> config ;
376465 struct ov767x_data * data = dev -> data ;
@@ -382,66 +471,112 @@ static int ov7670_set_fmt(const struct device *dev, struct video_format *fmt)
382471 return - ENOTSUP ;
383472 }
384473
385- /* Set output resolution */
386- while (config -> fmts [i ].pixelformat ) {
387- if (config -> fmts [i ].width_min == fmt -> width &&
388- config -> fmts [i ].height_min == fmt -> height &&
389- config -> fmts [i ].pixelformat == fmt -> pixelformat ) {
390- /* Set output format */
391- switch (config -> fmts [i ].width_min ) {
392- case 176 : /* QCIF */
393- ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qcif ,
394- ARRAY_SIZE (ov7670_regs_qcif ));
395- break ;
396- case 352 : /* QCIF */
397- ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_cif ,
398- ARRAY_SIZE (ov7670_regs_cif ));
399- break ;
400- case 320 : /* QVGA */
401- ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qvga ,
402- ARRAY_SIZE (ov7670_regs_qvga ));
403- break ;
404- case 640 : /* VGA */
405- ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_vga ,
406- ARRAY_SIZE (ov7670_regs_vga ));
407- break ;
408- default : /* QVGA */
409- ret = video_write_cci_multiregs8 (& config -> bus , ov7670_regs_qvga ,
410- ARRAY_SIZE (ov7670_regs_vga ));
411- break ;
412- }
413- if (ret < 0 ) {
414- LOG_ERR ("Resolution not set!" );
415- return ret ;
416- }
417- }
418- i ++ ;
474+ if (!memcmp (& data -> fmt , fmt , sizeof (data -> fmt ))) {
475+ /* nothing to do */
476+ return 0 ;
477+ }
478+
479+ /* Set RGB Format */
480+ if (fmt -> pixelformat == VIDEO_PIX_FMT_RGB565 ) {
481+ ret = video_write_cci_multiregs8 (& config -> bus , ov767x_rgb565_regs ,
482+ ARRAY_SIZE (ov767x_rgb565_regs ));
483+ } else if (fmt -> pixelformat == VIDEO_PIX_FMT_YUYV ) {
484+ ret = video_write_cci_multiregs8 (& config -> bus , ov767x_yuv422_regs ,
485+ ARRAY_SIZE (ov767x_yuv422_regs ));
486+ } else {
487+ LOG_ERR ("Image format not supported" );
488+ ret = - ENOTSUP ;
419489 }
420490
421491 if (ret < 0 ) {
422- LOG_ERR ("Resolution not supported !" );
492+ LOG_ERR ("Format not set !" );
423493 return ret ;
424494 }
425495
426- return 0 ;
427- }
428- #endif
429-
430- static int ov767x_set_fmt (const struct device * dev , struct video_format * fmt )
431- {
432- int ret ;
496+ /* Set output resolution */
497+ if (config -> camera_model == OV767X_MODEL_OV7670 ) {
498+ while (config -> fmts [i ].pixelformat ) {
499+ if (config -> fmts [i ].width_min == fmt -> width &&
500+ config -> fmts [i ].height_min == fmt -> height &&
501+ config -> fmts [i ].pixelformat == fmt -> pixelformat ) {
502+ /* Set output format */
503+ switch (config -> fmts [i ].width_min ) {
504+ case 176 : /* QCIF */
505+ ret = video_write_cci_multiregs8 (
506+ & config -> bus , ov7670_regs_qcif ,
507+ ARRAY_SIZE (ov7670_regs_qcif ));
508+ break ;
509+ case 352 : /* QCIF */
510+ ret = video_write_cci_multiregs8 (
511+ & config -> bus , ov7670_regs_cif ,
512+ ARRAY_SIZE (ov7670_regs_cif ));
513+ break ;
514+ case 320 : /* QVGA */
515+ ret = video_write_cci_multiregs8 (
516+ & config -> bus , ov7670_regs_qvga ,
517+ ARRAY_SIZE (ov7670_regs_qvga ));
518+ break ;
519+ case 640 : /* VGA */
520+ ret = video_write_cci_multiregs8 (
521+ & config -> bus , ov7670_regs_vga ,
522+ ARRAY_SIZE (ov7670_regs_vga ));
523+ break ;
524+ default : /* QVGA */
525+ ret = video_write_cci_multiregs8 (
526+ & config -> bus , ov7670_regs_qvga ,
527+ ARRAY_SIZE (ov7670_regs_vga ));
528+ break ;
529+ }
530+ if (ret < 0 ) {
531+ LOG_ERR ("Resolution not set!" );
532+ return ret ;
533+ }
534+ }
535+ i ++ ;
536+ }
537+ }
433538
434- if (fmt -> pixelformat != VIDEO_PIX_FMT_RGB565 && fmt -> pixelformat != VIDEO_PIX_FMT_YUYV ) {
435- LOG_ERR ("Only RGB565 and YUYV supported!" );
436- return - ENOTSUP ;
539+ if (config -> camera_model == OV767X_MODEL_OV7675 ) {
540+ while (config -> fmts [i ].pixelformat ) {
541+ if (config -> fmts [i ].width_min == fmt -> width &&
542+ config -> fmts [i ].height_min == fmt -> height &&
543+ config -> fmts [i ].pixelformat == fmt -> pixelformat ) {
544+ /* Set output format */
545+ switch (config -> fmts [i ].width_min ) {
546+ case 160 : /* QQVGA */
547+ ret = video_write_cci_multiregs8 (
548+ & config -> bus , ov7675_regs_qqvga ,
549+ ARRAY_SIZE (ov7675_regs_qqvga ));
550+ break ;
551+ case 320 : /* QVGA */
552+ ret = video_write_cci_multiregs8 (
553+ & config -> bus , ov7675_regs_qvga ,
554+ ARRAY_SIZE (ov7675_regs_qvga ));
555+ break ;
556+ case 640 : /* VGA */
557+ ret = video_write_cci_multiregs8 (
558+ & config -> bus , ov7675_regs_vga ,
559+ ARRAY_SIZE (ov7675_regs_vga ));
560+ break ;
561+ default : /* QVGA */
562+ ret = video_write_cci_multiregs8 (
563+ & config -> bus , ov7675_regs_qvga ,
564+ ARRAY_SIZE (ov7675_regs_qvga ));
565+ break ;
566+ }
567+ if (ret < 0 ) {
568+ LOG_ERR ("Resolution not set!" );
569+ return ret ;
570+ }
571+ }
572+ i ++ ;
573+ }
437574 }
438575
439- #if DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7670 )
440- ret = ov7670_set_fmt (dev , fmt );
441576 if (ret < 0 ) {
577+ LOG_ERR ("Resolution not supported!" );
442578 return ret ;
443579 }
444- #endif
445580
446581 return 0 ;
447582}
@@ -486,7 +621,8 @@ static int ov767x_init(const struct device *dev)
486621 return - ENODEV ;
487622 }
488623
489- #if DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7670 , pwdn_gpios )
624+ #if DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7670 , pwdn_gpios ) || \
625+ DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7675 , pwdn_gpios )
490626 /* Power up camera module */
491627 if (config -> pwdn .port != NULL ) {
492628 if (!gpio_is_ready_dt (& config -> pwdn )) {
@@ -500,7 +636,8 @@ static int ov767x_init(const struct device *dev)
500636 }
501637#endif
502638
503- #if DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7670 , reset_gpios )
639+ #if DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7670 , reset_gpios ) || \
640+ DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY (ovti_ov7675 , reset_gpios )
504641 /* Reset camera module */
505642 if (config -> reset .port != NULL ) {
506643 if (!gpio_is_ready_dt (& config -> reset )) {
@@ -629,3 +766,7 @@ static DEVICE_API(video, ov767x_api) = {
629766#undef DT_DRV_COMPAT
630767#define DT_DRV_COMPAT ovti_ov7670
631768DT_INST_FOREACH_STATUS_OKAY_VARGS (OV767X_INIT , 7670 )
769+
770+ #undef DT_DRV_COMPAT
771+ #define DT_DRV_COMPAT ovti_ov7675
772+ DT_INST_FOREACH_STATUS_OKAY_VARGS (OV767X_INIT , 7675 )
0 commit comments