@@ -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