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
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)
3238#define GC2145_SET_P0_REGS 0x00
33- #define GC2145_REG_CROP_ENABLE 0x90
39+ #define GC2145_REG_CROP_ENABLE GC2145_REG8( 0x90)
3440#define GC2145_CROP_SET_ENABLE 0x01
35- #define GC2145_REG_BLANK_WINDOW_BASE 0x09
36- #define GC2145_REG_WINDOW_BASE 0x91
37- #define GC2145_REG_SUBSAMPLE 0x99
38- #define GC2145_REG_SUBSAMPLE_MODE 0x9A
41+ #define GC2145_REG_BLANK_WINDOW_BASE GC2145_REG8( 0x09)
42+ #define GC2145_REG_WINDOW_BASE GC2145_REG8( 0x91)
43+ #define GC2145_REG_SUBSAMPLE GC2145_REG8( 0x99)
44+ #define GC2145_REG_SUBSAMPLE_MODE GC2145_REG8( 0x9A)
3945#define GC2145_SUBSAMPLE_MODE_SMOOTH 0x0E
4046
4147#define UXGA_HSIZE 1600
@@ -103,8 +109,8 @@ static const struct gc2145_reg default_regs[] = {
103109 {0x81 , 0x26 },
104110 {0x82 , 0xfa },
105111 {0x83 , 0x00 },
106- {GC2145_REG_OUTPUT_FMT , 0x06 },
107- {GC2145_REG_SYNC_MODE , 0x23 },
112+ {( uint8_t ) GC2145_REG_OUTPUT_FMT , 0x06 },
113+ {( uint8_t ) GC2145_REG_SYNC_MODE , 0x23 },
108114 {0x88 , 0x03 },
109115 {0x89 , 0x03 },
110116 {0x85 , 0x08 },
@@ -195,7 +201,7 @@ static const struct gc2145_reg default_regs[] = {
195201 {0x0c , 0x10 },
196202 {0x11 , 0x10 },
197203 {0x13 , 0x68 },
198- {GC2145_REG_OUTPUT_FMT , 0x00 },
204+ {( uint8_t ) GC2145_REG_OUTPUT_FMT , 0x00 },
199205 {0x1c , 0x11 },
200206 {0x1e , 0x61 },
201207 {0x1f , 0x35 },
@@ -226,8 +232,8 @@ static const struct gc2145_reg default_regs[] = {
226232 {0x81 , 0x08 },
227233 {0x82 , 0x05 },
228234 {0x83 , 0x08 },
229- {GC2145_REG_OUTPUT_FMT , 0x0a },
230- {GC2145_REG_SYNC_MODE , 0xf0 },
235+ {( uint8_t ) GC2145_REG_OUTPUT_FMT , 0x0a },
236+ {( uint8_t ) GC2145_REG_SYNC_MODE , 0xf0 },
231237 {0x87 , 0x50 },
232238 {0x88 , 0x15 },
233239 {0x89 , 0xb0 },
@@ -262,7 +268,7 @@ static const struct gc2145_reg default_regs[] = {
262268 {0x14 , 0x27 },
263269 {0x15 , 0x37 },
264270 {0x16 , 0x45 },
265- {GC2145_REG_OUTPUT_FMT , 0x53 },
271+ {( uint8_t ) GC2145_REG_OUTPUT_FMT , 0x53 },
266272 {0x18 , 0x69 },
267273 {0x19 , 0x7d },
268274 {0x1a , 0x8f },
@@ -718,54 +724,6 @@ static const struct video_format_cap fmts[] = {
718724 {0 },
719725};
720726
721- static int gc2145_write_reg (const struct i2c_dt_spec * spec , uint8_t reg_addr , uint8_t value )
722- {
723- int ret ;
724- uint8_t tries = 3 ;
725-
726- /*
727- * It rarely happens that the camera does not respond with ACK signal.
728- * In that case it usually responds on 2nd try but there is a 3rd one
729- * just to be sure that the connection error is not caused by driver
730- * itself.
731- */
732- do {
733- ret = i2c_reg_write_byte_dt (spec , reg_addr , value );
734- if (!ret ) {
735- return 0 ;
736- }
737- /* If writing failed wait 5ms before next attempt */
738- k_msleep (5 );
739- } while (tries -- > 0 );
740-
741- LOG_ERR ("failed to write 0x%x to 0x%x," , value , reg_addr );
742- return ret ;
743- }
744-
745- static int gc2145_read_reg (const struct i2c_dt_spec * spec , uint8_t reg_addr , uint8_t * value )
746- {
747- int ret ;
748- uint8_t tries = 3 ;
749-
750- /*
751- * It rarely happens that the camera does not respond with ACK signal.
752- * In that case it usually responds on 2nd try but there is a 3rd one
753- * just to be sure that the connection error is not caused by driver
754- * itself.
755- */
756- do {
757- ret = i2c_reg_read_byte_dt (spec , reg_addr , value );
758- if (!ret ) {
759- return 0 ;
760- }
761- /* If writing failed wait 5ms before next attempt */
762- k_msleep (5 );
763- } while (tries -- > 0 );
764-
765- LOG_ERR ("failed to read 0x%x register" , reg_addr );
766- return ret ;
767- }
768-
769727static int gc2145_write_all (const struct device * dev , const struct gc2145_reg * regs ,
770728 uint16_t reg_num )
771729{
@@ -774,7 +732,7 @@ static int gc2145_write_all(const struct device *dev, const struct gc2145_reg *r
774732 for (uint16_t i = 0 ; i < reg_num ; i ++ ) {
775733 int ret ;
776734
777- ret = gc2145_write_reg (& cfg -> i2c , regs [i ].addr , regs [i ].value );
735+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG8 ( regs [i ].addr ) , regs [i ].value );
778736 if (ret < 0 ) {
779737 return ret ;
780738 }
@@ -789,7 +747,7 @@ static int gc2145_soft_reset(const struct device *dev)
789747 const struct gc2145_config * cfg = dev -> config ;
790748
791749 /* Initiate system reset */
792- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_REG_SW_RESET );
750+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_REG_SW_RESET );
793751
794752 k_msleep (300 );
795753
@@ -798,87 +756,49 @@ static int gc2145_soft_reset(const struct device *dev)
798756
799757static int gc2145_set_ctrl_vflip (const struct device * dev , bool enable )
800758{
801- int ret ;
802759 const struct gc2145_config * cfg = dev -> config ;
803- uint8_t old_value ;
804-
805- ret = gc2145_read_reg (& cfg -> i2c , GC2145_REG_AMODE1 , & old_value );
806- if (ret < 0 ) {
807- return ret ;
808- }
809760
810761 /* Set the vertical flip state */
811- return gc2145_write_reg (& cfg -> i2c , GC2145_REG_AMODE1 ,
812- ( old_value & GC2145_AMODE1_WINDOW_MASK ) | ( enable << 1 ));
762+ return video_write_cci_field (& cfg -> i2c , GC2145_REG_AMODE1 , GC2145_AMODE1_WINDOW_MASK ,
763+ FIELD_PREP ( GC2145_AMODE1_WINDOW_MASK , enable << 1 ));
813764}
814765
815766static int gc2145_set_ctrl_hmirror (const struct device * dev , bool enable )
816767{
817- int ret ;
818768 const struct gc2145_config * cfg = dev -> config ;
819- uint8_t old_value ;
820-
821- ret = gc2145_read_reg (& cfg -> i2c , GC2145_REG_AMODE1 , & old_value );
822- if (ret < 0 ) {
823- return ret ;
824- }
825769
826770 /* Set the horizontal mirror state */
827- return gc2145_write_reg (& cfg -> i2c , GC2145_REG_AMODE1 ,
828- ( old_value & GC2145_AMODE1_WINDOW_MASK ) | enable );
771+ return video_write_cci_field (& cfg -> i2c , GC2145_REG_AMODE1 , GC2145_AMODE1_WINDOW_MASK ,
772+ FIELD_PREP ( GC2145_AMODE1_WINDOW_MASK , enable ) );
829773}
830774
831- static int gc2145_set_window (const struct device * dev , uint16_t reg , uint16_t x , uint16_t y ,
832- uint16_t w , uint16_t h )
775+ static int gc2145_set_window (const struct device * dev , uint32_t reg , uint32_t x_offset ,
776+ uint32_t y_offset , uint32_t window_width , uint32_t window_height )
833777{
834778 int ret ;
835779 const struct gc2145_config * cfg = dev -> config ;
836780
837- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_SET_P0_REGS );
838- if (ret < 0 ) {
839- return ret ;
840- }
841-
842- /* Y/row offset */
843- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , y >> 8 );
781+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_SET_P0_REGS );
844782 if (ret < 0 ) {
845783 return ret ;
846784 }
847785
848- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , y & 0xff );
786+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG16 ( reg + 0 ), y_offset );
849787 if (ret < 0 ) {
850788 return ret ;
851789 }
852790
853- /* X/col offset */
854- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , x >> 8 );
791+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG16 (reg + 2 ), x_offset );
855792 if (ret < 0 ) {
856793 return ret ;
857794 }
858795
859- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , x & 0xff );
796+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG16 ( reg + 4 ), window_height );
860797 if (ret < 0 ) {
861798 return ret ;
862799 }
863800
864- /* Window height */
865- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , h >> 8 );
866- if (ret < 0 ) {
867- return ret ;
868- }
869-
870- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , h & 0xff );
871- if (ret < 0 ) {
872- return ret ;
873- }
874-
875- /* Window width */
876- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , w >> 8 );
877- if (ret < 0 ) {
878- return ret ;
879- }
880-
881- ret = gc2145_write_reg (& cfg -> i2c , reg ++ , w & 0xff );
801+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG16 (reg + 6 ), window_width );
882802 if (ret < 0 ) {
883803 return ret ;
884804 }
@@ -889,10 +809,9 @@ static int gc2145_set_window(const struct device *dev, uint16_t reg, uint16_t x,
889809static int gc2145_set_output_format (const struct device * dev , int output_format )
890810{
891811 int ret ;
892- uint8_t old_value ;
893812 const struct gc2145_config * cfg = dev -> config ;
894813
895- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_SET_P0_REGS );
814+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_RESET , GC2145_SET_P0_REGS );
896815 if (ret < 0 ) {
897816 return ret ;
898817 }
@@ -907,13 +826,8 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
907826 return - ENOTSUP ;
908827 }
909828
910- ret = gc2145_read_reg (& cfg -> i2c , GC2145_REG_OUTPUT_FMT , & old_value );
911- if (ret < 0 ) {
912- return ret ;
913- }
914-
915- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_OUTPUT_FMT ,
916- (old_value & ~GC2145_REG_OUTPUT_FMT_MASK ) | output_format );
829+ ret = video_write_cci_field (& cfg -> i2c , GC2145_REG_OUTPUT_FMT , GC2145_REG_OUTPUT_FMT_MASK ,
830+ output_format );
917831 if (ret < 0 ) {
918832 return ret ;
919833 }
@@ -965,31 +879,32 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
965879 win_y = ((UXGA_VSIZE - win_h ) / 2 );
966880
967881 /* Set readout window first. */
968- ret = gc2145_set_window (dev , GC2145_REG_BLANK_WINDOW_BASE , win_x , win_y , win_w + 16 ,
969- win_h + 8 );
882+ ret = gc2145_set_window (dev , ( uint8_t ) GC2145_REG_BLANK_WINDOW_BASE , win_x , win_y ,
883+ win_w + 16 , win_h + 8 );
970884 if (ret < 0 ) {
971885 return ret ;
972886 }
973887
974888 /* Set cropping window next. */
975- ret = gc2145_set_window (dev , GC2145_REG_WINDOW_BASE , x , y , w , h );
889+ ret = gc2145_set_window (dev , ( uint8_t ) GC2145_REG_WINDOW_BASE , x , y , w , h );
976890 if (ret < 0 ) {
977891 return ret ;
978892 }
979893
980894 /* Enable crop */
981- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_CROP_ENABLE , GC2145_CROP_SET_ENABLE );
895+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_CROP_ENABLE , GC2145_CROP_SET_ENABLE );
982896 if (ret < 0 ) {
983897 return ret ;
984898 }
985899
986900 /* Set Sub-sampling ratio and mode */
987- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE , ((r_ratio << 4 ) | c_ratio ));
901+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE , ((r_ratio << 4 ) | c_ratio ));
988902 if (ret < 0 ) {
989903 return ret ;
990904 }
991905
992- ret = gc2145_write_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE_MODE , GC2145_SUBSAMPLE_MODE_SMOOTH );
906+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE_MODE ,
907+ GC2145_SUBSAMPLE_MODE_SMOOTH );
993908 if (ret < 0 ) {
994909 return ret ;
995910 }
@@ -1008,21 +923,13 @@ static uint8_t gc2145_check_connection(const struct device *dev)
1008923{
1009924 int ret ;
1010925 const struct gc2145_config * cfg = dev -> config ;
1011- uint8_t reg_chip_id [2 ];
1012- uint16_t chip_id ;
926+ uint32_t chip_id ;
1013927
1014- ret = gc2145_read_reg (& cfg -> i2c , 0xf0 , & reg_chip_id [ 0 ] );
928+ ret = video_read_cci_reg (& cfg -> i2c , GC2145_REG_CHIP_ID , & chip_id );
1015929 if (ret < 0 ) {
1016930 return ret ;
1017931 }
1018932
1019- ret = gc2145_read_reg (& cfg -> i2c , 0xf1 , & reg_chip_id [1 ]);
1020- if (ret < 0 ) {
1021- return ret ;
1022- }
1023-
1024- chip_id = reg_chip_id [0 ] << 8 | reg_chip_id [1 ];
1025-
1026933 if (chip_id != 0x2145 && chip_id != 0x2155 ) {
1027934 LOG_WRN ("Unexpected GC2145 chip ID: 0x%04x" , chip_id );
1028935 }
@@ -1089,8 +996,8 @@ static int gc2145_set_stream(const struct device *dev, bool enable)
1089996{
1090997 const struct gc2145_config * cfg = dev -> config ;
1091998
1092- return enable ? gc2145_write_reg (& cfg -> i2c , 0xf2 , 0x0f )
1093- : gc2145_write_reg (& cfg -> i2c , 0xf2 , 0x00 );
999+ return enable ? video_write_cci_reg (& cfg -> i2c , GC2145_REG8 ( 0xf2 ) , 0x0f )
1000+ : video_write_cci_reg (& cfg -> i2c , GC2145_REG8 ( 0xf2 ) , 0x00 );
10941001}
10951002
10961003static int gc2145_get_caps (const struct device * dev , enum video_endpoint_id ep ,
0 commit comments