@@ -775,6 +775,8 @@ struct gc2145_data {
775
775
struct gc2145_ctrls ctrls ;
776
776
struct video_format fmt ;
777
777
struct video_rect crop ;
778
+ uint16_t format_width ;
779
+ uint16_t format_height ;
778
780
uint8_t c_ratio ;
779
781
uint8_t r_ratio ;
780
782
};
@@ -870,8 +872,7 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
870
872
}
871
873
872
874
873
- static int gc2145_set_resolution (const struct device * dev , uint32_t w , uint32_t h ,
874
- bool compute_ratio )
875
+ static int gc2145_gc2145_set_resolution (const struct device * dev , uint32_t w , uint32_t h )
875
876
{
876
877
const struct gc2145_config * cfg = dev -> config ;
877
878
struct gc2145_data * drv_data = dev -> data ;
@@ -887,6 +888,8 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
887
888
if ((w == 0 ) || (h == 0 )) {
888
889
return - EIO ;
889
890
}
891
+
892
+ /* If we are called from set_format, then we compute ratio and initialize crop */
890
893
drv_data -> c_ratio = RESOLUTION_UXGA_W / w ;
891
894
drv_data -> r_ratio = RESOLUTION_UXGA_H / h ;
892
895
if (drv_data -> c_ratio < drv_data -> r_ratio ) {
@@ -895,22 +898,35 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
895
898
drv_data -> c_ratio = drv_data -> r_ratio ;
896
899
}
897
900
901
+ /* Restrict ratio to 3 for faster refresh ? */
902
+ if (drv_data -> c_ratio > 3 ) {
903
+ drv_data -> c_ratio = 3 ;
904
+ drv_data -> r_ratio = 3 ;
905
+ }
906
+
898
907
/* make sure we don't end up with ratio of 0 */
899
908
if (drv_data -> c_ratio == 0 ) {
900
909
return - EIO ;
901
910
}
902
911
912
+ /* remember the width and height passed in */
913
+ drv_data -> format_width = w ;
914
+ drv_data -> format_height = h ;
915
+
916
+ /* Default to crop rectangle being same size as passed in resolution */
917
+ drv_data -> crop .left = 0 ;
918
+ drv_data -> crop .top = 0 ;
919
+ drv_data -> crop .width = w ;
920
+ drv_data -> crop .height = h ;
921
+
922
+
903
923
/* Calculates the window boundaries to obtain the desired resolution */
904
924
905
925
win_w = w * drv_data -> c_ratio ;
906
926
win_h = h * drv_data -> r_ratio ;
907
927
win_x = ((UXGA_HSIZE - win_w ) / 2 );
908
928
win_y = ((UXGA_VSIZE - win_h ) / 2 );
909
929
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
930
915
931
x = (((win_w / drv_data -> c_ratio ) - w ) / 2 );
916
932
y = (((win_h / drv_data -> r_ratio ) - h ) / 2 );
@@ -986,29 +1002,63 @@ static int gc2145_set_resolution(const struct device *dev, uint32_t w, uint32_t
986
1002
return 0 ;
987
1003
}
988
1004
989
- static int gc2145_set_crop (const struct device * dev )
1005
+ static int gc2145_set_crop (const struct device * dev , struct video_selection * sel )
990
1006
{
991
1007
/* set the crop, start off with most of a duplicate of set resolution */
992
1008
int ret ;
1009
+ const struct gc2145_config * cfg = dev -> config ;
993
1010
struct gc2145_data * drv_data = dev -> data ;
994
1011
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 )) {
1012
+
1013
+ /* Verify the passed in rectangle is valid */
1014
+ if (((sel -> rect .left + sel -> rect .width ) > drv_data -> format_width ) ||
1015
+ ((sel -> rect .top + sel -> rect .height ) > drv_data -> format_height )) {
1016
+ LOG_INF ("(%u %u) %ux%u > %ux%u" , sel -> rect .left , sel -> rect .top ,
1017
+ sel -> rect .width , sel -> rect .height ,
1018
+ drv_data -> format_width , drv_data -> format_height );
1019
+ return - EINVAL ;
1020
+ }
1021
+
1022
+ /* if rectangle passed in is same as current, simply return */
1023
+ if (memcmp ((void * )& drv_data -> crop , (void * )& sel -> rect , sizeof (struct video_rect )) == 0 ) {
998
1024
return 0 ;
999
1025
}
1000
1026
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 ;
1027
+ /* save out the updated crop window registers */
1028
+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG8 (GC2145_REG_RESET ),
1029
+ GC2145_REG_RESET_P0_REGS );
1030
+ if (ret < 0 ) {
1031
+ return ret ;
1032
+ }
1033
+
1034
+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_OUT_WIN_ROW_START , sel -> rect .top );
1035
+ if (ret < 0 ) {
1036
+ return ret ;
1037
+ }
1038
+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_OUT_WIN_COL_START , sel -> rect .left );
1039
+ if (ret < 0 ) {
1040
+ return ret ;
1041
+ }
1042
+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_OUT_WIN_HEIGHT , sel -> rect .height );
1043
+ if (ret < 0 ) {
1044
+ return ret ;
1010
1045
}
1011
- return ret ;
1046
+ ret = video_write_cci_reg (& cfg -> i2c , GC2145_REG_OUT_WIN_WIDTH , sel -> rect .width );
1047
+ if (ret < 0 ) {
1048
+ return ret ;
1049
+ }
1050
+
1051
+
1052
+ /* Only if valid do we update our crop rectangle */
1053
+ drv_data -> crop = sel -> rect ;
1054
+
1055
+ /* enqueue/dequeue depend on this being set as well as the crop */
1056
+ drv_data -> fmt .width = drv_data -> crop .width ;
1057
+ drv_data -> fmt .height = drv_data -> crop .height ;
1058
+ drv_data -> fmt .pitch = drv_data -> fmt .width *
1059
+ video_bits_per_pixel (drv_data -> fmt .pixelformat ) / BITS_PER_BYTE ;
1060
+
1061
+ return 0 ;
1012
1062
}
1013
1063
1014
1064
@@ -1137,7 +1187,7 @@ static int gc2145_set_fmt(const struct device *dev, struct video_format *fmt)
1137
1187
}
1138
1188
1139
1189
/* Set window size */
1140
- ret = gc2145_set_resolution (dev , fmt -> width , fmt -> height , true );
1190
+ ret = gc2145_gc2145_set_resolution (dev , fmt -> width , fmt -> height );
1141
1191
1142
1192
if (ret < 0 ) {
1143
1193
LOG_ERR ("Failed to set the resolution" );
@@ -1239,11 +1289,8 @@ static int gc2145_set_selection(const struct device *dev, struct video_selection
1239
1289
return - EINVAL ;
1240
1290
}
1241
1291
1242
- struct gc2145_data * drv_data = dev -> data ;
1243
-
1244
1292
if (sel -> target == VIDEO_SEL_TGT_CROP ) {
1245
- drv_data -> crop = sel -> rect ;
1246
- return gc2145_set_crop (dev );
1293
+ return gc2145_set_crop (dev , sel );
1247
1294
}
1248
1295
1249
1296
return - EINVAL ;
@@ -1267,8 +1314,8 @@ static int gc2145_get_selection(const struct device *dev, struct video_selection
1267
1314
case VIDEO_SEL_TGT_NATIVE_SIZE :
1268
1315
sel -> rect .top = 0 ;
1269
1316
sel -> rect .left = 0 ;
1270
- sel -> rect .width = UXGA_HSIZE / drv_data -> c_ratio ;
1271
- sel -> rect .height = UXGA_VSIZE / drv_data -> r_ratio ;
1317
+ sel -> rect .width = drv_data -> format_width ;
1318
+ sel -> rect .height = drv_data -> format_height ;
1272
1319
break ;
1273
1320
default :
1274
1321
return - EINVAL ;
0 commit comments