@@ -689,20 +689,24 @@ struct gc2145_data {
689689 struct video_format fmt ;
690690};
691691
692- #define GC2145_VIDEO_FORMAT_CAP (width , height , format ) \
693- { \
694- .pixelformat = format, \
695- .width_min = width, \
696- .width_max = width, \
697- .height_min = height, \
698- .height_max = height, \
699- .width_step = 0, \
700- .height_step = 0, \
692+ #define GC2145_VIDEO_FORMAT_CAP (width , height , format ) \
693+ { \
694+ .pixelformat = format, .width_min = width, .width_max = width, \
695+ .height_min = height, .height_max = height, .width_step = 0, .height_step = 0, \
701696 }
702697
698+ enum resolutions {
699+ QVGA_RESOLUTION = 0 ,
700+ VGA_RESOLUTION ,
701+ UXGA_RESOLUTION ,
702+ RESOLUTIONS_MAX ,
703+ };
704+
703705static const struct video_format_cap fmts [] = {
704- GC2145_VIDEO_FORMAT_CAP (1600 , 1200 , VIDEO_PIX_FMT_RGB565 ), /* UXGA */
705- {0 },
706+ [QVGA_RESOLUTION ] = GC2145_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_RGB565 ), /* QVGA */
707+ [VGA_RESOLUTION ] = GC2145_VIDEO_FORMAT_CAP (640 , 480 , VIDEO_PIX_FMT_RGB565 ), /* VGA */
708+ [UXGA_RESOLUTION ] = GC2145_VIDEO_FORMAT_CAP (1600 , 1200 , VIDEO_PIX_FMT_RGB565 ), /* UXGA */
709+ [RESOLUTIONS_MAX ] = {0 },
706710};
707711
708712static int gc2145_write_reg (const struct i2c_dt_spec * spec , uint8_t reg_addr , uint8_t value )
@@ -901,28 +905,65 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
901905 return 0 ;
902906}
903907
904- static int gc2145_set_resolution (const struct device * dev , uint16_t img_width , uint16_t img_height )
908+ static int gc2145_set_resolution (const struct device * dev , enum resolutions res )
905909{
906910 int ret ;
907911 const struct gc2145_config * cfg = dev -> config ;
908912
909- uint16_t win_w = UXGA_HSIZE + 16 ;
910- uint16_t win_h = UXGA_VSIZE + 8 ;
911- uint16_t c_ratio = 1 ;
912- uint16_t r_ratio = 1 ;
913- uint16_t x = (((win_w / c_ratio ) - UXGA_HSIZE ) / 2 );
914- uint16_t y = (((win_h / r_ratio ) - UXGA_VSIZE ) / 2 );
915- uint16_t win_x = ((UXGA_HSIZE - win_w ) / 2 );
916- uint16_t win_y = ((UXGA_VSIZE - win_h ) / 2 );
913+ uint16_t w ;
914+ uint16_t h ;
915+ uint16_t win_w ;
916+ uint16_t win_h ;
917+ uint16_t c_ratio ;
918+ uint16_t r_ratio ;
919+ uint16_t x ;
920+ uint16_t y ;
921+ uint16_t win_x ;
922+ uint16_t win_y ;
923+
924+ if (res >= RESOLUTIONS_MAX ) {
925+ return - EIO ;
926+ }
927+
928+ w = fmts [res ].width_min ;
929+ h = fmts [res ].height_min ;
930+
931+ /* Add the subsampling factor depending on resolution */
932+ switch (res ) {
933+ case QVGA_RESOLUTION :
934+ c_ratio = 3 ;
935+ r_ratio = 3 ;
936+ break ;
937+ case VGA_RESOLUTION :
938+ c_ratio = 2 ;
939+ r_ratio = 2 ;
940+ break ;
941+ case UXGA_RESOLUTION :
942+ c_ratio = 1 ;
943+ r_ratio = 1 ;
944+ break ;
945+ default :
946+ LOG_ERR ("Unsupported resolution %d" , res );
947+ return - EIO ;
948+ };
949+
950+ /* Calculates the window boundaries to obtain the desired resolution */
951+ win_w = w * c_ratio ;
952+ win_h = h * r_ratio ;
953+ x = (((win_w / c_ratio ) - w ) / 2 );
954+ y = (((win_h / r_ratio ) - h ) / 2 );
955+ win_x = ((UXGA_HSIZE - win_w ) / 2 );
956+ win_y = ((UXGA_VSIZE - win_h ) / 2 );
917957
918958 /* Set readout window first. */
919- ret = gc2145_set_window (dev , GC2145_REG_BLANK_WINDOW_BASE , win_x , win_y , win_w , win_h );
959+ ret = gc2145_set_window (dev , GC2145_REG_BLANK_WINDOW_BASE , win_x , win_y , win_w + 16 ,
960+ win_h + 8 );
920961 if (ret < 0 ) {
921962 return ret ;
922963 }
923964
924965 /* Set cropping window next. */
925- ret = gc2145_set_window (dev , GC2145_REG_WINDOW_BASE , x , y , 1 , 1 );
966+ ret = gc2145_set_window (dev , GC2145_REG_WINDOW_BASE , x , y , w , h );
926967 if (ret < 0 ) {
927968 return ret ;
928969 }
@@ -972,8 +1013,7 @@ static uint8_t gc2145_check_connection(const struct device *dev)
9721013 }
9731014
9741015 if ((reg_ver_val != GC2145_REV_VAL ) || (reg_pid_val != GC2145_PID_VAL )) {
975- LOG_ERR ("failed to detect GC2145 pid: 0x%x rev: 0x%x" , reg_pid_val , reg_ver_val );
976- return - EIO ;
1016+ LOG_WRN ("Unexpected GC2145 pid: 0x%x or rev: 0x%x" , reg_pid_val , reg_ver_val );
9771017 }
9781018
9791019 return 0 ;
@@ -1014,7 +1054,7 @@ static int gc2145_set_fmt(const struct device *dev, enum video_endpoint_id ep,
10141054 if (fmts [i ].width_min == width && fmts [i ].height_min == height &&
10151055 fmts [i ].pixelformat == fmt -> pixelformat ) {
10161056 /* Set window size */
1017- ret = gc2145_set_resolution (dev , fmt -> width , fmt -> height );
1057+ ret = gc2145_set_resolution (dev , ( enum resolutions ) i );
10181058 if (ret < 0 ) {
10191059 LOG_ERR ("Failed to set the resolution" );
10201060 }
@@ -1105,11 +1145,12 @@ static int gc2145_init(const struct device *dev)
11051145 gc2145_soft_reset (dev );
11061146 gc2145_write_all (dev , default_regs , ARRAY_SIZE (default_regs ));
11071147
1108- /* set default/init format SVGA RGB565 */
1148+ /* set default/init format QVGA RGB565 */
11091149 fmt .pixelformat = VIDEO_PIX_FMT_RGB565 ;
1110- fmt .width = UXGA_HSIZE ;
1111- fmt .height = UXGA_VSIZE ;
1112- fmt .pitch = UXGA_HSIZE * 2 ;
1150+ fmt .width = fmts [QVGA_RESOLUTION ].width_min ;
1151+ fmt .height = fmts [QVGA_RESOLUTION ].height_min ;
1152+ fmt .pitch = fmts [QVGA_RESOLUTION ].width_min * 2 ;
1153+
11131154 ret = gc2145_set_fmt (dev , VIDEO_EP_OUT , & fmt );
11141155 if (ret ) {
11151156 LOG_ERR ("Unable to configure default format" );
0 commit comments