11/* 
22 * Copyright 2024 NXP 
33 * Copyright 2021 Arduino SA 
4+  * Copyright (c) 2013-2021 Ibrahim Abdelkader <[email protected] > 5+  * Copyright (c) 2013-2021 Kwabena W. Agyeman <[email protected] > 46 * Copyright (c) 2025 Michael Smorto 
57 * 
68 * SPDX-License-Identifier: Apache-2.0 
@@ -134,15 +136,16 @@ struct ov767x_data {
134136#define  OV7670_HAECC5              0xA8
135137#define  OV7670_HAECC6              0xA9
136138
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       */ 
139+ /* Addition defines to support OV7675 */ 
140+ #define  OV7670_RGB444                0x8C /* REG444 */ 
141+ #define  OV7675_COM3_DCW_EN           0x04 /* DCW enable */ 
142+ #define  OV7670_COM1                  0x04 /*Com Cntrl1 */ 
143+ #define  OV7675_COM7_RGB_FMT          0x04 /* Output format RGB        */ 
144+ #define  OV7675_COM13_GAMMA_EN        0x80 /* Gamma enable */ 
145+ #define  OV7675_COM13_UVSAT_AUTO      0x40 /* UV saturation level - UV auto adjustment. */ 
146+ #define  OV7675_COM15_OUT_00_FF       0xC0 /* Output data range 00 to FF  */ 
147+ #define  OV7675_COM15_FMT_RGB_NORMAL  0x00 /* Normal RGB normal output    */ 
148+ #define  OV7675_COM15_FMT_RGB565      0x10 /* Normal RGB 565 output       */ 
146149
147150/* OV7670 definitions */ 
148151#define  OV7670_PROD_ID  0x76
@@ -342,25 +345,10 @@ static const struct video_reg8 ov767x_init_regtbl[] = {
342345	{0xb8 , 0x0a },
343346};
344347
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- 
360348/* TODO: These registers probably need to be fixed too. */ 
361349static  const  struct  video_reg8  ov767x_yuv422_regs [] =  {
362350	{OV7670_COM7 , 0x00 },   /* Selects YUV mode */ 
363- 	{OV7675_RGB444 , 0x00 }, /* No RGB444 please */ 
351+ 	{OV7670_RGB444 , 0x00 }, /* No RGB444 please */ 
364352	{OV7670_COM1 , 0x00 },   /* CCIR601 */ 
365353	{OV7670_COM15 , OV7675_COM15_OUT_00_FF },
366354	{OV7670_COM9 , 0x48 }, /* 32x gain ceiling; 0x8 is reserved bit */ 
@@ -373,6 +361,22 @@ static const struct video_reg8 ov767x_yuv422_regs[] = {
373361	{OV7670_COM13 , OV7675_COM13_GAMMA_EN  | OV7675_COM13_UVSAT_AUTO },
374362};
375363
364+ #if  DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7670 )
365+ static  const  struct  video_reg8  ov7670_rgb565_regs [] =  {
366+ 	{OV7670_COM7 , OV7675_COM7_RGB_FMT }, /* Selects RGB mode */ 
367+ 	{OV7670_RGB444 , 0x00 },              /* No RGB444 please */ 
368+ 	{OV7670_COM1 , 0x00 },                /* CCIR601 */ 
369+ 	{OV7670_COM15 , OV7675_COM15_OUT_00_FF  | OV7675_COM15_FMT_RGB565 },
370+ 	{OV7670_COM9 , 0x6a }, /* 16x gain ceiling; 0x8 is reserved bit */ 
371+ 	{0x4f , 0xb3 },        /* "matrix coefficient 1" */ 
372+ 	{0x50 , 0xb3 },        /* "matrix coefficient 2" */ 
373+ 	{0x51 , 0x00 },        /* "matrix Coefficient 3" */ 
374+ 	{0x52 , 0x3d },        /* "matrix coefficient 4" */ 
375+ 	{0x53 , 0xa7 },        /* "matrix coefficient 5" */ 
376+ 	{0x54 , 0xe4 },        /* "matrix coefficient 6" */ 
377+ 	{OV7670_COM13 , OV7675_COM13_UVSAT_AUTO },
378+ };
379+ 
376380/* Resolution settings for camera, based on those present in MCUX SDK */ 
377381static  const  struct  video_reg8  ov7670_regs_qcif [] =  {
378382	{OV7670_COM7 , 0x2c },
@@ -417,6 +421,23 @@ static const struct video_reg8 ov7670_regs_vga[] = {
417421	{OV7670_SCALING_PCLK_DIV , 0xf0 },
418422	{OV7670_SCALING_PCLK_DELAY , 0x02 },
419423};
424+ #endif 
425+ 
426+ #if  DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7675 )
427+ static  const  struct  video_reg8  ov7675_rgb565_regs [] =  {
428+ 	{OV7670_COM7 , OV7675_COM7_RGB_FMT }, /* Selects RGB mode */ 
429+ 	{OV7670_RGB444 , 0x00 },              /* No RGB444 please */ 
430+ 	{OV7670_COM1 , 0x00 },                /* CCIR601 */ 
431+ 	{OV7670_COM15 , OV7675_COM15_OUT_00_FF  | OV7675_COM15_FMT_RGB565 },
432+ 	{OV7670_COM9 , 0x38 }, /* 16x gain ceiling; 0x8 is reserved bit */ 
433+ 	{0x4f , 0xb3 },        /* "matrix coefficient 1" */ 
434+ 	{0x50 , 0xb3 },        /* "matrix coefficient 2" */ 
435+ 	{0x51 , 0x00 },        /* "matrix Coefficient 3" */ 
436+ 	{0x52 , 0x3d },        /* "matrix coefficient 4" */ 
437+ 	{0x53 , 0xa7 },        /* "matrix coefficient 5" */ 
438+ 	{0x54 , 0xe4 },        /* "matrix coefficient 6" */ 
439+ 	{OV7670_COM13 , OV7675_COM13_GAMMA_EN  | OV7675_COM13_UVSAT_AUTO },
440+ };
420441
421442static  const  struct  video_reg8  ov7675_regs_vga [] =  {
422443	{OV7670_COM3 , 0x00 },   {OV7670_COM14 , 0x00 }, {0x72 , 0x11 }, /* downsample by 4 */ 
@@ -428,8 +449,8 @@ static const struct video_reg8 ov7675_regs_vga[] = {
428449static  const  struct  video_reg8  ov7675_regs_qvga [] =  {
429450	{OV7670_COM3 , OV7675_COM3_DCW_EN },
430451	{OV7670_COM14 , 0x11 }, /* Divide by 2 */ 
431- 	{0x72 , 0x22 },          /* This has no effect on OV7675 */ 
432- 	{0x73 , 0xf2 },          /* This has no effect on OV7675 */ 
452+ 	{0x72 , 0x22 },
453+ 	{0x73 , 0xf2 },
433454	{OV7670_HSTART , 0x15 },
434455	{OV7670_HSTOP , 0x03 },
435456	{OV7670_HREF , 0xC0 },
@@ -441,15 +462,16 @@ static const struct video_reg8 ov7675_regs_qvga[] = {
441462static  const  struct  video_reg8  ov7675_regs_qqvga [] =  {
442463	{OV7670_COM3 , OV7675_COM3_DCW_EN },
443464	{OV7670_COM14 , 0x11 }, /* Divide by 2 */ 
444- 	{0x72 , 0x22 },          /* This has no effect on OV7675*/ 
445- 	{0x73 , 0xf2 },          /* This has no effect on OV7675*/ 
465+ 	{0x72 , 0x22 },
466+ 	{0x73 , 0xf2 },
446467	{OV7670_HSTART , 0x16 },
447468	{OV7670_HSTOP , 0x04 },
448469	{OV7670_HREF , 0xa4 },
449470	{OV7670_VSTRT , 0x22 },
450471	{OV7670_VSTOP , 0x7a },
451472	{OV7670_VREF , 0xfa },
452473};
474+ #endif 
453475
454476static  int  ov767x_get_caps (const  struct  device  * dev , struct  video_caps  * caps )
455477{
@@ -466,9 +488,26 @@ static int ov767x_set_fmt(const struct device *dev, struct video_format *fmt)
466488	int  ret  =  - ENOTSUP ;
467489	uint8_t  i  =  0U ;
468490
469- 	if  (fmt -> pixelformat  !=  VIDEO_PIX_FMT_RGB565  &&  fmt -> pixelformat  !=  VIDEO_PIX_FMT_YUYV ) {
470- 		LOG_ERR ("Only RGB565 and YUYV supported!" );
471- 		return  - ENOTSUP ;
491+ 	if  (!memcmp (& data -> fmt , fmt , sizeof (data -> fmt ))) {
492+ 		/* nothing to do */ 
493+ 		return  0 ;
494+ 	}
495+ 
496+ 	/* Set RGB Format */ 
497+ 	if  (fmt -> pixelformat  ==  VIDEO_PIX_FMT_RGB565 ) {
498+ 		ret  =  video_write_cci_multiregs8 (& config -> bus , ov7670_rgb565_regs ,
499+ 						 ARRAY_SIZE (ov7670_rgb565_regs ));
500+ 	} else  if  (fmt -> pixelformat  ==  VIDEO_PIX_FMT_YUYV ) {
501+ 		ret  =  video_write_cci_multiregs8 (& config -> bus , ov767x_yuv422_regs ,
502+ 						 ARRAY_SIZE (ov767x_yuv422_regs ));
503+ 	} else  {
504+ 		LOG_ERR ("Image format not supported" );
505+ 		ret  =  - ENOTSUP ;
506+ 	}
507+ 
508+ 	if  (ret  <  0 ) {
509+ 		LOG_ERR ("Format not set!" );
510+ 		return  ret ;
472511	}
473512
474513	if  (!memcmp (& data -> fmt , fmt , sizeof (data -> fmt ))) {
@@ -535,51 +574,107 @@ static int ov767x_set_fmt(const struct device *dev, struct video_format *fmt)
535574			i ++ ;
536575		}
537576	}
577+ 	if  (ret  <  0 ) {
578+ 		LOG_ERR ("Resolution not supported!" );
579+ 		return  ret ;
580+ 	}
538581
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- 				}
582+ 	return  0 ;
583+ }
584+ #endif 
585+ #if  DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7675 )
586+ static  int  ov7675_set_fmt (const  struct  device  * dev , struct  video_format  * fmt )
587+ {
588+ 	const  struct  ov767x_config  * config  =  dev -> config ;
589+ 	struct  ov767x_data  * data  =  dev -> data ;
590+ 	int  ret  =  - ENOTSUP ;
591+ 	uint8_t  i  =  0U ;
592+ 
593+ 	if  (!memcmp (& data -> fmt , fmt , sizeof (data -> fmt ))) {
594+ 		/* nothing to do */ 
595+ 		return  0 ;
596+ 	}
597+ 
598+ 	/* Set RGB Format */ 
599+ 	if  (fmt -> pixelformat  ==  VIDEO_PIX_FMT_RGB565 ) {
600+ 		ret  =  video_write_cci_multiregs8 (& config -> bus , ov7675_rgb565_regs ,
601+ 						 ARRAY_SIZE (ov7675_rgb565_regs ));
602+ 	} else  if  (fmt -> pixelformat  ==  VIDEO_PIX_FMT_YUYV ) {
603+ 		ret  =  video_write_cci_multiregs8 (& config -> bus , ov767x_yuv422_regs ,
604+ 						 ARRAY_SIZE (ov767x_yuv422_regs ));
605+ 	} else  {
606+ 		LOG_ERR ("Image format not supported" );
607+ 		ret  =  - ENOTSUP ;
608+ 	}
609+ 
610+ 	if  (ret  <  0 ) {
611+ 		LOG_ERR ("Format not set!" );
612+ 		return  ret ;
613+ 	}
614+ 
615+ 	while  (config -> fmts [i ].pixelformat ) {
616+ 		if  (config -> fmts [i ].width_min  ==  fmt -> width  && 
617+ 		    config -> fmts [i ].height_min  ==  fmt -> height  && 
618+ 		    config -> fmts [i ].pixelformat  ==  fmt -> pixelformat ) {
619+ 			/* Set output format */ 
620+ 			switch  (config -> fmts [i ].width_min ) {
621+ 			case  160 : /* QQVGA */ 
622+ 				ret  =  video_write_cci_multiregs8 (& config -> bus , ov7675_regs_qqvga ,
623+ 								 ARRAY_SIZE (ov7675_regs_qqvga ));
624+ 				break ;
625+ 			case  320 : /* QVGA */ 
626+ 				ret  =  video_write_cci_multiregs8 (& config -> bus , ov7675_regs_qvga ,
627+ 								 ARRAY_SIZE (ov7675_regs_qvga ));
628+ 				break ;
629+ 			case  640 : /* VGA */ 
630+ 				ret  =  video_write_cci_multiregs8 (& config -> bus , ov7675_regs_vga ,
631+ 								 ARRAY_SIZE (ov7675_regs_vga ));
632+ 				break ;
633+ 			default : /* QVGA */ 
634+ 				ret  =  video_write_cci_multiregs8 (& config -> bus , ov7675_regs_qvga ,
635+ 								 ARRAY_SIZE (ov7675_regs_qvga ));
636+ 				break ;
637+ 			}
638+ 			if  (ret  <  0 ) {
639+ 				LOG_ERR ("Resolution not set!" );
640+ 				return  ret ;
571641			}
572- 			i ++ ;
573642		}
643+ 		i ++ ;
574644	}
575- 
576645	if  (ret  <  0 ) {
577646		LOG_ERR ("Resolution not supported!" );
578647		return  ret ;
579648	}
580649
581650	return  0 ;
582651}
652+ #endif 
653+ 
654+ static  int  ov767x_set_fmt (const  struct  device  * dev , struct  video_format  * fmt )
655+ {
656+ 	int  ret ;
657+ 
658+ 	if  (fmt -> pixelformat  !=  VIDEO_PIX_FMT_RGB565  &&  fmt -> pixelformat  !=  VIDEO_PIX_FMT_YUYV ) {
659+ 		LOG_ERR ("Only RGB565 and YUYV supported!" );
660+ 		return  - ENOTSUP ;
661+ 	}
662+ 
663+ #if  DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7670 )
664+ 	ret  =  ov7670_set_fmt (dev , fmt );
665+ 	if  (ret  <  0 ) {
666+ 		return  ret ;
667+ 	}
668+ #endif 
669+ #if  DT_HAS_COMPAT_STATUS_OKAY (ovti_ov7675 )
670+ 	ret  =  ov7675_set_fmt (dev , fmt );
671+ 	if  (ret  <  0 ) {
672+ 		return  ret ;
673+ 	}
674+ #endif 
675+ 
676+ 	return  0 ;
677+ }
583678
584679static  int  ov767x_get_fmt (const  struct  device  * dev , struct  video_format  * fmt )
585680{
@@ -689,7 +784,9 @@ static int ov767x_init(const struct device *dev)
689784	}
690785	/* Delay after reset */ 
691786	k_msleep (5 );
787+ 
692788	ret  =  ov767x_set_fmt (dev , & fmt );
789+ 
693790	if  (ret  <  0 ) {
694791		return  ret ;
695792	}
0 commit comments