@@ -706,10 +706,16 @@ static const struct video_reg8 default_regs[] = {
706706 {0x46 , 0xcf },
707707
708708 {GC2145_REG_RESET , GC2145_REG_RESET_P0_REGS },
709+ /* Hb and Vb from Teensy_camera */
709710 {0x05 , 0x01 },
710- {0x06 , 0x1C },
711- {0x07 , 0x00 },
712- {0x08 , 0x32 },
711+ {0x06 , 0x3b },
712+ {0x07 , 0x01 },
713+ {0x08 , 0x0b },
714+ /* Hb and Vb from current */
715+ /*{0x05, 0x01}, */
716+ /*{0x06, 0x1C}, */
717+ /*{0x07, 0x00}, */
718+ /*{0x08, 0x32}, */
713719 {0x11 , 0x00 },
714720 {0x12 , 0x1D },
715721 {0x13 , 0x00 },
@@ -768,12 +774,22 @@ struct gc2145_ctrls {
768774struct gc2145_data {
769775 struct gc2145_ctrls ctrls ;
770776 struct video_format fmt ;
777+ struct video_rect crop ;
778+ uint8_t c_ratio ;
779+ uint8_t r_ratio ;
771780};
772781
773- #define GC2145_VIDEO_FORMAT_CAP (width , height , format ) \
774- { \
775- .pixelformat = format, .width_min = width, .width_max = width, \
776- .height_min = height, .height_max = height, .width_step = 0, .height_step = 0, \
782+ #define USE_ONE_FORMAT_WIDTH_HEIGHT
783+ #define GC2145_VIDEO_FORMAT_CAP (width , height , format ) \
784+ { \
785+ .pixelformat = format, .width_min = width, .width_max = width, \
786+ .height_min = height, .height_max = height, .width_step = 0, .height_step = 0, \
787+ }
788+
789+ #define GC2145_VIDEO_FORMAT_CAP_HL (width_l , width_h , height_l , height_h , format ) \
790+ { \
791+ .pixelformat = format, .width_min = width_l, .width_max = width_h, \
792+ .height_min = height_l, .height_max = height_h, .width_step = 0, .height_step = 0,\
777793 }
778794
779795#define RESOLUTION_QVGA_W 320
@@ -786,12 +802,22 @@ struct gc2145_data {
786802#define RESOLUTION_UXGA_H 1200
787803
788804static const struct video_format_cap fmts [] = {
805+ #ifdef USE_ONE_FORMAT_WIDTH_HEIGHT
806+ GC2145_VIDEO_FORMAT_CAP_HL (128 , 1600 , 128 , 1200 , VIDEO_PIX_FMT_RGB565 ),
807+ GC2145_VIDEO_FORMAT_CAP_HL (128 , 1600 , 128 , 1200 , VIDEO_PIX_FMT_YUYV ),
808+ #else
789809 GC2145_VIDEO_FORMAT_CAP (RESOLUTION_QVGA_W , RESOLUTION_QVGA_H , VIDEO_PIX_FMT_RGB565 ),
790810 GC2145_VIDEO_FORMAT_CAP (RESOLUTION_VGA_W , RESOLUTION_VGA_H , VIDEO_PIX_FMT_RGB565 ),
791811 GC2145_VIDEO_FORMAT_CAP (RESOLUTION_UXGA_W , RESOLUTION_UXGA_H , VIDEO_PIX_FMT_RGB565 ),
812+ /* Add some full size possible resolutions */
813+ GC2145_VIDEO_FORMAT_CAP (800 , 600 , VIDEO_PIX_FMT_RGB565 ), /* div 2 */
814+ GC2145_VIDEO_FORMAT_CAP (533 , 400 , VIDEO_PIX_FMT_RGB565 ), /* div 3 */
815+ GC2145_VIDEO_FORMAT_CAP (400 , 300 , VIDEO_PIX_FMT_RGB565 ), /* div 4 */
816+ GC2145_VIDEO_FORMAT_CAP (320 , 240 , VIDEO_PIX_FMT_RGB565 ), /* div 5 */
792817 GC2145_VIDEO_FORMAT_CAP (RESOLUTION_QVGA_W , RESOLUTION_QVGA_H , VIDEO_PIX_FMT_YUYV ),
793818 GC2145_VIDEO_FORMAT_CAP (RESOLUTION_VGA_W , RESOLUTION_VGA_H , VIDEO_PIX_FMT_YUYV ),
794819 GC2145_VIDEO_FORMAT_CAP (RESOLUTION_UXGA_W , RESOLUTION_UXGA_H , VIDEO_PIX_FMT_YUYV ),
820+ #endif
795821 {0 },
796822};
797823
@@ -843,47 +869,52 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
843869 return 0 ;
844870}
845871
846- static int gc2145_set_resolution (const struct device * dev , uint32_t w , uint32_t h )
872+
873+ static int gc2145_set_resolution (const struct device * dev , uint32_t w , uint32_t h ,
874+ bool compute_ratio )
847875{
848876 const struct gc2145_config * cfg = dev -> config ;
877+ struct gc2145_data * drv_data = dev -> data ;
849878 int ret ;
850879
851880 uint16_t win_w ;
852881 uint16_t win_h ;
853- uint16_t c_ratio ;
854- uint16_t r_ratio ;
855882 uint16_t x ;
856883 uint16_t y ;
857884 uint16_t win_x ;
858885 uint16_t win_y ;
859886
860- /* Add the subsampling factor depending on resolution */
861- switch (w ) {
862- case RESOLUTION_QVGA_W :
863- c_ratio = 3 ;
864- r_ratio = 3 ;
865- break ;
866- case RESOLUTION_VGA_W :
867- c_ratio = 2 ;
868- r_ratio = 2 ;
869- break ;
870- case RESOLUTION_UXGA_W :
871- c_ratio = 1 ;
872- r_ratio = 1 ;
873- break ;
874- default :
875- LOG_ERR ("Unsupported resolution %d %d" , w , h );
887+ if ((w == 0 ) || (h == 0 )) {
876888 return - EIO ;
877- };
889+ }
890+ drv_data -> c_ratio = RESOLUTION_UXGA_W / w ;
891+ drv_data -> r_ratio = RESOLUTION_UXGA_H / h ;
892+ if (drv_data -> c_ratio < drv_data -> r_ratio ) {
893+ drv_data -> r_ratio = drv_data -> c_ratio ;
894+ } else {
895+ drv_data -> c_ratio = drv_data -> r_ratio ;
896+ }
897+
898+ /* make sure we don't end up with ratio of 0 */
899+ if (drv_data -> c_ratio == 0 ) {
900+ return - EIO ;
901+ }
878902
879903 /* Calculates the window boundaries to obtain the desired resolution */
880- win_w = w * c_ratio ;
881- win_h = h * r_ratio ;
882- x = (((win_w / c_ratio ) - w ) / 2 );
883- y = (((win_h / r_ratio ) - h ) / 2 );
904+
905+ win_w = w * drv_data -> c_ratio ;
906+ win_h = h * drv_data -> r_ratio ;
884907 win_x = ((UXGA_HSIZE - win_w ) / 2 );
885908 win_y = ((UXGA_VSIZE - win_h ) / 2 );
886909
910+ drv_data -> crop .left = 0 ;
911+ drv_data -> crop .top = 0 ;
912+ drv_data -> crop .width = w ;
913+ drv_data -> crop .height = h ;
914+
915+ x = (((win_w / drv_data -> c_ratio ) - w ) / 2 );
916+ y = (((win_h / drv_data -> r_ratio ) - h ) / 2 );
917+
887918 ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG8 (GC2145_REG_RESET ),
888919 GC2145_REG_RESET_P0_REGS );
889920 if (ret < 0 ) {
@@ -933,7 +964,8 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
933964 }
934965
935966 /* Set Sub-sampling ratio and mode */
936- ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE , ((r_ratio << 4 ) | c_ratio ));
967+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_SUBSAMPLE ,
968+ ((drv_data -> r_ratio << 4 ) | drv_data -> c_ratio ));
937969 if (ret < 0 ) {
938970 return ret ;
939971 }
@@ -954,6 +986,32 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
954986 return 0 ;
955987}
956988
989+ static int gc2145_set_crop (const struct device * dev )
990+ {
991+ /* set the crop, start off with most of a duplicate of set resolution */
992+ int ret ;
993+ struct gc2145_data * drv_data = dev -> data ;
994+
995+ /* Calculates the window boundaries to obtain the desired resolution */
996+ if ((drv_data -> fmt .width == drv_data -> crop .width ) &&
997+ (drv_data -> fmt .height == drv_data -> crop .height )) {
998+ return 0 ;
999+ }
1000+
1001+ LOG_DBG ("set_res: %u %u ratios: %u %u" , drv_data -> crop .width , drv_data -> crop .height ,
1002+ drv_data -> c_ratio , drv_data -> r_ratio );
1003+ ret = gc2145_set_resolution (dev , drv_data -> crop .width , drv_data -> crop .height , false);
1004+ if (ret == 0 ) {
1005+ /* enqueue/dequeue depend on this being set as well as the crop */
1006+ drv_data -> fmt .width = drv_data -> crop .width ;
1007+ drv_data -> fmt .height = drv_data -> crop .height ;
1008+ drv_data -> fmt .pitch = drv_data -> fmt .width
1009+ * video_bits_per_pixel (drv_data -> fmt .pixelformat ) / BITS_PER_BYTE ;
1010+ }
1011+ return ret ;
1012+ }
1013+
1014+
9571015static int gc2145_check_connection (const struct device * dev )
9581016{
9591017 const struct gc2145_config * cfg = dev -> config ;
@@ -1057,7 +1115,10 @@ static int gc2145_set_fmt(const struct device *dev, struct video_format *fmt)
10571115
10581116 /* Check if camera is capable of handling given format */
10591117 for (int i = 0 ; i < ARRAY_SIZE (fmts ) - 1 ; i ++ ) {
1060- if (fmts [i ].width_min == fmt -> width && fmts [i ].height_min == fmt -> height &&
1118+ if ((fmts [i ].width_min <= fmt -> width ) &&
1119+ (fmts [i ].width_max >= fmt -> width ) &&
1120+ (fmts [i ].height_min <= fmt -> height ) &&
1121+ (fmts [i ].height_max >= fmt -> height ) &&
10611122 fmts [i ].pixelformat == fmt -> pixelformat ) {
10621123 res = i ;
10631124 break ;
@@ -1076,7 +1137,7 @@ static int gc2145_set_fmt(const struct device *dev, struct video_format *fmt)
10761137 }
10771138
10781139 /* Set window size */
1079- ret = gc2145_set_resolution (dev , fmt -> width , fmt -> height );
1140+ ret = gc2145_set_resolution (dev , fmt -> width , fmt -> height , true );
10801141
10811142 if (ret < 0 ) {
10821143 LOG_ERR ("Failed to set the resolution" );
@@ -1171,12 +1232,60 @@ static int gc2145_set_ctrl(const struct device *dev, uint32_t id)
11711232 }
11721233}
11731234
1235+ static int gc2145_set_selection (const struct device * dev , struct video_selection * sel )
1236+ {
1237+ LOG_DBG ("called: (%p, %p: %u %u)" , dev , sel , sel -> type , sel -> target );
1238+ if (sel -> type != VIDEO_BUF_TYPE_OUTPUT ) {
1239+ return - EINVAL ;
1240+ }
1241+
1242+ struct gc2145_data * drv_data = dev -> data ;
1243+
1244+ if (sel -> target == VIDEO_SEL_TGT_CROP ) {
1245+ drv_data -> crop = sel -> rect ;
1246+ return gc2145_set_crop (dev );
1247+ }
1248+
1249+ return - EINVAL ;
1250+ }
1251+
1252+ static int gc2145_get_selection (const struct device * dev , struct video_selection * sel )
1253+ {
1254+ LOG_DBG ("called: (%p, %p: %u %u)" , dev , sel , sel -> type , sel -> target );
1255+ if (sel -> type != VIDEO_BUF_TYPE_OUTPUT ) {
1256+ return - EINVAL ;
1257+ }
1258+
1259+ struct gc2145_data * drv_data = dev -> data ;
1260+
1261+ switch (sel -> target ) {
1262+ case VIDEO_SEL_TGT_COMPOSE :
1263+ case VIDEO_SEL_TGT_CROP :
1264+ sel -> rect = drv_data -> crop ;
1265+ break ;
1266+
1267+ case VIDEO_SEL_TGT_NATIVE_SIZE :
1268+ sel -> rect .top = 0 ;
1269+ sel -> rect .left = 0 ;
1270+ sel -> rect .width = UXGA_HSIZE / drv_data -> c_ratio ;
1271+ sel -> rect .height = UXGA_VSIZE / drv_data -> r_ratio ;
1272+ break ;
1273+ default :
1274+ return - EINVAL ;
1275+ }
1276+
1277+ return 0 ;
1278+ }
1279+
1280+
11741281static DEVICE_API (video , gc2145_driver_api ) = {
11751282 .set_format = gc2145_set_fmt ,
11761283 .get_format = gc2145_get_fmt ,
11771284 .get_caps = gc2145_get_caps ,
11781285 .set_stream = gc2145_set_stream ,
11791286 .set_ctrl = gc2145_set_ctrl ,
1287+ .set_selection = gc2145_set_selection ,
1288+ .get_selection = gc2145_get_selection ,
11801289};
11811290
11821291static int gc2145_init_controls (const struct device * dev )
@@ -1214,8 +1323,8 @@ static int gc2145_init(const struct device *dev)
12141323 /* set default/init format VGA RGB565 */
12151324 struct video_format fmt = {
12161325 .pixelformat = VIDEO_PIX_FMT_RGB565 ,
1217- .width = RESOLUTION_VGA_W ,
1218- .height = RESOLUTION_VGA_H ,
1326+ .width = RESOLUTION_QVGA_W ,
1327+ .height = RESOLUTION_QVGA_H ,
12191328 };
12201329 int ret ;
12211330 const struct gc2145_config * cfg = dev -> config ;
0 commit comments