1212#include <zephyr/drivers/video-controls.h>
1313#include <zephyr/drivers/i2c.h>
1414#include <zephyr/drivers/gpio.h>
15-
1615#include <zephyr/logging/log.h>
16+
17+ #include "video_common.h"
18+
1719LOG_MODULE_REGISTER (video_gc2145 , CONFIG_VIDEO_LOG_LEVEL );
1820
19- #define GC2145_REG_AMODE1 0x17
21+ #define GC2145_REG8 (addr ) ((addr) | VIDEO_REG_ADDR8_DATA8)
22+ #define GC2145_REG16 (addr ) ((addr) | VIDEO_REG_ADDR8_DATA16_LE)
23+
24+ #define GC2145_REG_AMODE1 GC2145_REG8(0x17)
2025#define GC2145_AMODE1_WINDOW_MASK 0xFC
21- #define GC2145_REG_AMODE1_DEF 0x14
22- #define GC2145_REG_OUTPUT_FMT 0x84
23- #define GC2145_REG_OUTPUT_FMT_MASK 0x1F
24- #define GC2145_REG_OUTPUT_FMT_RGB565 0x06
25- #define GC2145_REG_OUTPUT_FMT_YCBYCR 0x02
26- #define GC2145_REG_SYNC_MODE 0x86
27- #define GC2145_REG_SYNC_MODE_DEF 0x23
28- #define GC2145_REG_SYNC_MODE_COL_SWITCH 0x10
29- #define GC2145_REG_SYNC_MODE_ROW_SWITCH 0x20
30- #define GC2145_REG_RESET 0xFE
31- #define GC2145_REG_SW_RESET 0x80
32- #define GC2145_PID_VAL 0x21
33- #define GC2145_REV_VAL 0x55
26+ #define GC2145_REG_AMODE1_DEF GC2145_REG8( 0x14)
27+ #define GC2145_REG_OUTPUT_FMT GC2145_REG8( 0x84)
28+ #define GC2145_REG_OUTPUT_FMT_MASK GC2145_REG8( 0x1F)
29+ #define GC2145_REG_OUTPUT_FMT_RGB565 GC2145_REG8( 0x06)
30+ #define GC2145_REG_OUTPUT_FMT_YCBYCR GC2145_REG8( 0x02)
31+ #define GC2145_REG_SYNC_MODE GC2145_REG8( 0x86)
32+ #define GC2145_REG_SYNC_MODE_DEF GC2145_REG8( 0x23)
33+ #define GC2145_REG_SYNC_MODE_COL_SWITCH GC2145_REG8( 0x10)
34+ #define GC2145_REG_SYNC_MODE_ROW_SWITCH GC2145_REG8( 0x20)
35+ #define GC2145_REG_RESET GC2145_REG8( 0xFE)
36+ #define GC2145_REG_SW_RESET GC2145_REG8( 0x80)
37+ #define GC2145_REG_CHIP_ID GC2145_REG8(0xF0)
38+ #define GC2145_CHIP_ID 0x2155
3439#define GC2145_SET_P0_REGS 0x00
35- #define GC2145_REG_CROP_ENABLE 0x90
40+ #define GC2145_REG_CROP_ENABLE GC2145_REG8( 0x90)
3641#define GC2145_CROP_SET_ENABLE 0x01
37- #define GC2145_REG_BLANK_WINDOW_BASE 0x09
38- #define GC2145_REG_WINDOW_BASE 0x91
39- #define GC2145_REG_SUBSAMPLE 0x99
40- #define GC2145_REG_SUBSAMPLE_MODE 0x9A
42+ #define GC2145_REG_BLANK_WINDOW_BASE GC2145_REG8( 0x09)
43+ #define GC2145_REG_WINDOW_BASE GC2145_REG8( 0x91)
44+ #define GC2145_REG_SUBSAMPLE GC2145_REG8( 0x99)
45+ #define GC2145_REG_SUBSAMPLE_MODE GC2145_REG8( 0x9A)
4146#define GC2145_SUBSAMPLE_MODE_SMOOTH 0x0E
4247
4348#define UXGA_HSIZE 1600
@@ -105,8 +110,8 @@ static const struct gc2145_reg default_regs[] = {
105110 {0x81 , 0x26 },
106111 {0x82 , 0xfa },
107112 {0x83 , 0x00 },
108- {GC2145_REG_OUTPUT_FMT , 0x06 },
109- {GC2145_REG_SYNC_MODE , 0x23 },
113+ {( uint8_t ) GC2145_REG_OUTPUT_FMT , 0x06 },
114+ {( uint8_t ) GC2145_REG_SYNC_MODE , 0x23 },
110115 {0x88 , 0x03 },
111116 {0x89 , 0x03 },
112117 {0x85 , 0x08 },
@@ -197,7 +202,7 @@ static const struct gc2145_reg default_regs[] = {
197202 {0x0c , 0x10 },
198203 {0x11 , 0x10 },
199204 {0x13 , 0x68 },
200- {GC2145_REG_OUTPUT_FMT , 0x00 },
205+ {( uint8_t ) GC2145_REG_OUTPUT_FMT , 0x00 },
201206 {0x1c , 0x11 },
202207 {0x1e , 0x61 },
203208 {0x1f , 0x35 },
@@ -228,8 +233,8 @@ static const struct gc2145_reg default_regs[] = {
228233 {0x81 , 0x08 },
229234 {0x82 , 0x05 },
230235 {0x83 , 0x08 },
231- {GC2145_REG_OUTPUT_FMT , 0x0a },
232- {GC2145_REG_SYNC_MODE , 0xf0 },
236+ {( uint8_t ) GC2145_REG_OUTPUT_FMT , 0x0a },
237+ {( uint8_t ) GC2145_REG_SYNC_MODE , 0xf0 },
233238 {0x87 , 0x50 },
234239 {0x88 , 0x15 },
235240 {0x89 , 0xb0 },
@@ -264,7 +269,7 @@ static const struct gc2145_reg default_regs[] = {
264269 {0x14 , 0x27 },
265270 {0x15 , 0x37 },
266271 {0x16 , 0x45 },
267- {GC2145_REG_OUTPUT_FMT , 0x53 },
272+ {( uint8_t ) GC2145_REG_OUTPUT_FMT , 0x53 },
268273 {0x18 , 0x69 },
269274 {0x19 , 0x7d },
270275 {0x1a , 0x8f },
@@ -720,54 +725,6 @@ static const struct video_format_cap fmts[] = {
720725 {0 },
721726};
722727
723- static int gc2145_write_reg (const struct i2c_dt_spec * spec , uint8_t reg_addr , uint8_t value )
724- {
725- int ret ;
726- uint8_t tries = 3 ;
727-
728- /*
729- * It rarely happens that the camera does not respond with ACK signal.
730- * In that case it usually responds on 2nd try but there is a 3rd one
731- * just to be sure that the connection error is not caused by driver
732- * itself.
733- */
734- do {
735- ret = i2c_reg_write_byte_dt (spec , reg_addr , value );
736- if (!ret ) {
737- return 0 ;
738- }
739- /* If writing failed wait 5ms before next attempt */
740- k_msleep (5 );
741- } while (tries -- > 0 );
742-
743- LOG_ERR ("failed to write 0x%x to 0x%x," , value , reg_addr );
744- return ret ;
745- }
746-
747- static int gc2145_read_reg (const struct i2c_dt_spec * spec , uint8_t reg_addr , uint8_t * value )
748- {
749- int ret ;
750- uint8_t tries = 3 ;
751-
752- /*
753- * It rarely happens that the camera does not respond with ACK signal.
754- * In that case it usually responds on 2nd try but there is a 3rd one
755- * just to be sure that the connection error is not caused by driver
756- * itself.
757- */
758- do {
759- ret = i2c_reg_read_byte_dt (spec , reg_addr , value );
760- if (!ret ) {
761- return 0 ;
762- }
763- /* If writing failed wait 5ms before next attempt */
764- k_msleep (5 );
765- } while (tries -- > 0 );
766-
767- LOG_ERR ("failed to read 0x%x register" , reg_addr );
768- return ret ;
769- }
770-
771728static int gc2145_write_all (const struct device * dev , const struct gc2145_reg * regs ,
772729 uint16_t reg_num )
773730{
@@ -776,7 +733,7 @@ static int gc2145_write_all(const struct device *dev, const struct gc2145_reg *r
776733 for (uint16_t i = 0 ; i < reg_num ; i ++ ) {
777734 int ret ;
778735
779- ret = gc2145_write_reg (& cfg -> i2c , regs [i ].addr , regs [i ].value );
736+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG8 ( regs [i ].addr ) , regs [i ].value );
780737 if (ret < 0 ) {
781738 return ret ;
782739 }
@@ -791,7 +748,7 @@ static int gc2145_soft_reset(const struct device *dev)
791748 const struct gc2145_config * cfg = dev -> config ;
792749
793750 /* Initiate system reset */
794- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_REG_SW_RESET );
751+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_REG_SW_RESET );
795752
796753 k_msleep (300 );
797754
@@ -800,87 +757,49 @@ static int gc2145_soft_reset(const struct device *dev)
800757
801758static int gc2145_set_ctrl_vflip (const struct device * dev , bool enable )
802759{
803- int ret ;
804760 const struct gc2145_config * cfg = dev -> config ;
805- uint8_t old_value ;
806-
807- ret = gc2145_read_reg (& cfg -> i2c , GC2145_REG_AMODE1 , & old_value );
808- if (ret < 0 ) {
809- return ret ;
810- }
811761
812762 /* Set the vertical flip state */
813- return gc2145_write_reg (& cfg -> i2c , GC2145_REG_AMODE1 ,
814- ( old_value & GC2145_AMODE1_WINDOW_MASK ) | ( enable << 1 ));
763+ return video_write_cci_field (& cfg -> i2c , GC2145_REG_AMODE1 , GC2145_AMODE1_WINDOW_MASK ,
764+ FIELD_PREP ( GC2145_AMODE1_WINDOW_MASK , enable << 1 ));
815765}
816766
817767static int gc2145_set_ctrl_hmirror (const struct device * dev , bool enable )
818768{
819- int ret ;
820769 const struct gc2145_config * cfg = dev -> config ;
821- uint8_t old_value ;
822-
823- ret = gc2145_read_reg (& cfg -> i2c , GC2145_REG_AMODE1 , & old_value );
824- if (ret < 0 ) {
825- return ret ;
826- }
827770
828771 /* Set the horizontal mirror state */
829- return gc2145_write_reg (& cfg -> i2c , GC2145_REG_AMODE1 ,
830- ( old_value & GC2145_AMODE1_WINDOW_MASK ) | enable );
772+ return video_write_cci_field (& cfg -> i2c , GC2145_REG_AMODE1 , GC2145_AMODE1_WINDOW_MASK ,
773+ FIELD_PREP ( GC2145_AMODE1_WINDOW_MASK , enable ) );
831774}
832775
833- static int gc2145_set_window (const struct device * dev , uint16_t reg , uint16_t x , uint16_t y ,
834- uint16_t w , uint16_t h )
776+ static int gc2145_set_window (const struct device * dev , uint32_t reg , uint32_t x_offset ,
777+ uint32_t y_offset , uint32_t window_width , uint32_t window_height )
835778{
836779 int ret ;
837780 const struct gc2145_config * cfg = dev -> config ;
838781
839- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_SET_P0_REGS );
782+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_SET_P0_REGS );
840783 if (ret < 0 ) {
841784 return ret ;
842785 }
843786
844- /* Y/row offset */
845- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , y >> 8 );
787+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG16 (reg + 0 ), y_offset );
846788 if (ret < 0 ) {
847789 return ret ;
848790 }
849791
850- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , y & 0xff );
792+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG16 ( reg + 2 ), x_offset );
851793 if (ret < 0 ) {
852794 return ret ;
853795 }
854796
855- /* X/col offset */
856- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , x >> 8 );
797+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG16 (reg + 4 ), window_height );
857798 if (ret < 0 ) {
858799 return ret ;
859800 }
860801
861- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , x & 0xff );
862- if (ret < 0 ) {
863- return ret ;
864- }
865-
866- /* Window height */
867- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , h >> 8 );
868- if (ret < 0 ) {
869- return ret ;
870- }
871-
872- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , h & 0xff );
873- if (ret < 0 ) {
874- return ret ;
875- }
876-
877- /* Window width */
878- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , w >> 8 );
879- if (ret < 0 ) {
880- return ret ;
881- }
882-
883- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , w & 0xff );
802+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG16 (reg + 6 ), window_width );
884803 if (ret < 0 ) {
885804 return ret ;
886805 }
@@ -891,10 +810,9 @@ static int gc2145_set_window(const struct device *dev, uint16_t reg, uint16_t x,
891810static int gc2145_set_output_format (const struct device * dev , int output_format )
892811{
893812 int ret ;
894- uint8_t old_value ;
895813 const struct gc2145_config * cfg = dev -> config ;
896814
897- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_SET_P0_REGS );
815+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_SET_P0_REGS );
898816 if (ret < 0 ) {
899817 return ret ;
900818 }
@@ -909,13 +827,8 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
909827 return - ENOTSUP ;
910828 }
911829
912- ret = gc2145_read_reg (& cfg -> i2c , GC2145_REG_OUTPUT_FMT , & old_value );
913- if (ret < 0 ) {
914- return ret ;
915- }
916-
917- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_OUTPUT_FMT ,
918- (old_value & ~GC2145_REG_OUTPUT_FMT_MASK ) | output_format );
830+ ret = video_write_cci_field (& cfg -> i2c , GC2145_REG_OUTPUT_FMT , GC2145_REG_OUTPUT_FMT_MASK ,
831+ output_format );
919832 if (ret < 0 ) {
920833 return ret ;
921834 }
@@ -967,31 +880,32 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
967880 win_y = ((UXGA_VSIZE - win_h ) / 2 );
968881
969882 /* Set readout window first. */
970- ret = gc2145_set_window (dev , GC2145_REG_BLANK_WINDOW_BASE , win_x , win_y , win_w + 16 ,
971- win_h + 8 );
883+ ret = gc2145_set_window (dev , ( uint8_t ) GC2145_REG_BLANK_WINDOW_BASE , win_x , win_y ,
884+ win_w + 16 , win_h + 8 );
972885 if (ret < 0 ) {
973886 return ret ;
974887 }
975888
976889 /* Set cropping window next. */
977- ret = gc2145_set_window (dev , GC2145_REG_WINDOW_BASE , x , y , w , h );
890+ ret = gc2145_set_window (dev , ( uint8_t ) GC2145_REG_WINDOW_BASE , x , y , w , h );
978891 if (ret < 0 ) {
979892 return ret ;
980893 }
981894
982895 /* Enable crop */
983- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_CROP_ENABLE , GC2145_CROP_SET_ENABLE );
896+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_CROP_ENABLE , GC2145_CROP_SET_ENABLE );
984897 if (ret < 0 ) {
985898 return ret ;
986899 }
987900
988901 /* Set Sub-sampling ratio and mode */
989- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE , ((r_ratio << 4 ) | c_ratio ));
902+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE , ((r_ratio << 4 ) | c_ratio ));
990903 if (ret < 0 ) {
991904 return ret ;
992905 }
993906
994- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE_MODE , GC2145_SUBSAMPLE_MODE_SMOOTH );
907+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE_MODE ,
908+ GC2145_SUBSAMPLE_MODE_SMOOTH );
995909 if (ret < 0 ) {
996910 return ret ;
997911 }
@@ -1010,21 +924,15 @@ static uint8_t gc2145_check_connection(const struct device *dev)
1010924{
1011925 int ret ;
1012926 const struct gc2145_config * cfg = dev -> config ;
1013- uint8_t reg_pid_val ;
1014- uint8_t reg_ver_val ;
1015-
1016- ret = gc2145_read_reg (& cfg -> i2c , 0xf0 , & reg_pid_val );
1017- if (ret < 0 ) {
1018- return ret ;
1019- }
927+ uint32_t chip_id ;
1020928
1021- ret = gc2145_read_reg (& cfg -> i2c , 0xf1 , & reg_ver_val );
929+ ret = video_read_cci_reg (& cfg -> i2c , GC2145_REG_CHIP_ID , & chip_id );
1022930 if (ret < 0 ) {
1023931 return ret ;
1024932 }
1025933
1026- if (( reg_ver_val != GC2145_REV_VAL ) || ( reg_pid_val != GC2145_PID_VAL ) ) {
1027- LOG_WRN ("Unexpected GC2145 pid: 0x%x or rev: 0x%x" , reg_pid_val , reg_ver_val );
934+ if (chip_id != 0x2155 ) {
935+ LOG_WRN ("Unexpected GC2145 chip ID 0x%x" , chip_id );
1028936 }
1029937
1030938 return 0 ;
@@ -1089,8 +997,8 @@ static int gc2145_set_stream(const struct device *dev, bool enable)
1089997{
1090998 const struct gc2145_config * cfg = dev -> config ;
1091999
1092- return enable ? gc2145_write_reg (& cfg -> i2c , 0xf2 , 0x0f )
1093- : gc2145_write_reg (& cfg -> i2c , 0xf2 , 0x00 );
1000+ return enable ? video_write_cci_reg (& cfg -> i2c , GC2145_REG8 ( 0xf2 ) , 0x0f )
1001+ : video_write_cci_reg (& cfg -> i2c , GC2145_REG8 ( 0xf2 ) , 0x00 );
10941002}
10951003
10961004static int gc2145_get_caps (const struct device * dev , enum video_endpoint_id ep ,
0 commit comments