@@ -775,6 +775,8 @@ struct gc2145_data {
775775	struct  gc2145_ctrls  ctrls ;
776776	struct  video_format  fmt ;
777777	struct  video_rect  crop ;
778+ 	uint16_t  format_width ;
779+ 	uint16_t  format_height ;
778780	uint8_t  c_ratio ;
779781	uint8_t  r_ratio ;
780782};
@@ -870,8 +872,7 @@ static int gc2145_set_output_format(const struct device *dev, int output_format)
870872}
871873
872874
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 )
875876{
876877	const  struct  gc2145_config  * cfg  =  dev -> config ;
877878	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
887888	if  ((w  ==  0 ) ||  (h  ==  0 )) {
888889		return  - EIO ;
889890	}
891+ 
892+ 	/* If we are called from set_format, then we compute ratio and initialize crop */ 
890893	drv_data -> c_ratio  =  RESOLUTION_UXGA_W  / w ;
891894	drv_data -> r_ratio  =  RESOLUTION_UXGA_H  / h ;
892895	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
895898		drv_data -> c_ratio  =  drv_data -> r_ratio ;
896899	}
897900
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+ 
898907	/* make sure we don't end up with ratio of 0 */ 
899908	if  (drv_data -> c_ratio  ==  0 ) {
900909		return  - EIO ;
901910	}
902911
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+ 
903923	/* Calculates the window boundaries to obtain the desired resolution */ 
904924
905925	win_w  =  w  *  drv_data -> c_ratio ;
906926	win_h  =  h  *  drv_data -> r_ratio ;
907927	win_x  =  ((UXGA_HSIZE  -  win_w ) / 2 );
908928	win_y  =  ((UXGA_VSIZE  -  win_h ) / 2 );
909929
910- 	drv_data -> crop .left  =  0 ;
911- 	drv_data -> crop .top  =  0 ;
912- 	drv_data -> crop .width  =  w ;
913- 	drv_data -> crop .height  =  h ;
914930
915931	x  =  (((win_w  / drv_data -> c_ratio ) -  w ) / 2 );
916932	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
9861002	return  0 ;
9871003}
9881004
989- static  int  gc2145_set_crop (const  struct  device  * dev )
1005+ static  int  gc2145_set_crop (const  struct  device  * dev ,  struct   video_selection   * sel )
9901006{
9911007	/* set the crop, start off with most of a duplicate of set resolution */ 
9921008	int  ret ;
1009+ 	const  struct  gc2145_config  * cfg  =  dev -> config ;
9931010	struct  gc2145_data  * drv_data  =  dev -> data ;
9941011
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 ) {
9981024		return  0 ;
9991025	}
10001026
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 ;
10101045	}
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 ;
10121062}
10131063
10141064
@@ -1137,7 +1187,7 @@ static int gc2145_set_fmt(const struct device *dev, struct video_format *fmt)
11371187	}
11381188
11391189	/* 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 );
11411191
11421192	if  (ret  <  0 ) {
11431193		LOG_ERR ("Failed to set the resolution" );
@@ -1239,11 +1289,8 @@ static int gc2145_set_selection(const struct device *dev, struct video_selection
12391289		return  - EINVAL ;
12401290	}
12411291
1242- 	struct  gc2145_data  * drv_data  =  dev -> data ;
1243- 
12441292	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 );
12471294	}
12481295
12491296	return  - EINVAL ;
@@ -1267,8 +1314,8 @@ static int gc2145_get_selection(const struct device *dev, struct video_selection
12671314	case  VIDEO_SEL_TGT_NATIVE_SIZE :
12681315		sel -> rect .top  =  0 ;
12691316		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 ;
12721319		break ;
12731320	default :
12741321		return  - EINVAL ;
0 commit comments