@@ -43,6 +43,9 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
4343
4444#define  IMX477_REG_ORIENTATION 		0x101
4545
46+ #define  IMX477_REG_CSI_DT_FMT_H 		0x0112
47+ #define  IMX477_REG_CSI_DT_FMT_L 		0x0113
48+ 
4649#define  IMX477_XCLK_FREQ 		24000000
4750
4851#define  IMX477_DEFAULT_LINK_FREQ 	450000000
@@ -86,6 +89,7 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
8689#define  IMX477_DGTL_GAIN_DEFAULT 	0x0100
8790#define  IMX477_DGTL_GAIN_STEP 		1
8891
92+ #define  IMX477_REG_IOP_PXCK_DIV 		0x0309
8993#define  IMX477_REG_DIV_IOP_PX 		0x030b
9094
9195/* Test Pattern Control */ 
@@ -153,8 +157,11 @@ struct imx477_mode {
153157	/* Frame height */ 
154158	unsigned int   height ;
155159
156- 	/* H-timing in pixels when at 450MHz link freq */ 
157- 	unsigned int   line_length_pix ;
160+ 	/* 
161+ 	 * H-timing in pixels when at 450MHz link freq 
162+ 	 * Index 0 is for 12bpp. Index 1 is for 10bpp. 
163+ 	 */ 
164+ 	unsigned int   line_length_pix [2 ];
158165
159166	/* Analog crop rectangle. */ 
160167	struct  v4l2_rect  crop ;
@@ -569,8 +576,6 @@ static const struct imx477_reg mode_common_regs[] = {
569576
570577/* 12 mpix 10fps */ 
571578static  const  struct  imx477_reg  mode_4056x3040_regs [] =  {
572- 	{0x0112 , 0x0c },
573- 	{0x0113 , 0x0c },
574579	{0x0344 , 0x00 },
575580	{0x0345 , 0x00 },
576581	{0x0346 , 0x00 },
@@ -625,7 +630,6 @@ static const struct imx477_reg mode_4056x3040_regs[] = {
625630	{0x0305 , 0x04 },
626631	{0x0306 , 0x01 },
627632	{0x0307 , 0x5e },
628- 	{0x0309 , 0x0c },
629633	{0xe04c , 0x00 },
630634	{0xe04d , 0x7f },
631635	{0xe04e , 0x00 },
@@ -700,8 +704,6 @@ static const struct imx477_reg mode_4056x2160_regs[] = {
700704
701705/* 2x2 binned. 40fps */ 
702706static  const  struct  imx477_reg  mode_2028x1520_regs [] =  {
703- 	{0x0112 , 0x0c },
704- 	{0x0113 , 0x0c },
705707	{0x0344 , 0x00 },
706708	{0x0345 , 0x00 },
707709	{0x0346 , 0x00 },
@@ -745,7 +747,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
745747	{0x0305 , 0x04 },
746748	{0x0306 , 0x01 },
747749	{0x0307 , 0x5e },
748- 	{0x0309 , 0x0c },
749750	{0xe04c , 0x00 },
750751	{0xe04d , 0x7f },
751752	{0xe04e , 0x00 },
@@ -756,8 +757,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
756757
757758/* 1080p cropped mode */ 
758759static  const  struct  imx477_reg  mode_2028x1080_regs [] =  {
759- 	{0x0112 , 0x0c },
760- 	{0x0113 , 0x0c },
761760	{0x0344 , 0x00 },
762761	{0x0345 , 0x00 },
763762	{0x0346 , 0x01 },
@@ -801,7 +800,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
801800	{0x0305 , 0x04 },
802801	{0x0306 , 0x01 },
803802	{0x0307 , 0x5e },
804- 	{0x0309 , 0x0c },
805803	{0xe04c , 0x00 },
806804	{0xe04d , 0x7f },
807805	{0xe04e , 0x00 },
@@ -812,8 +810,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
812810
813811/* 4x4 binned. 120fps */ 
814812static  const  struct  imx477_reg  mode_1332x990_regs [] =  {
815- 	{0x0112 , 0x0a },
816- 	{0x0113 , 0x0a },
817813	{0x420b , 0x01 },
818814	{0x990c , 0x00 },
819815	{0x990d , 0x08 },
@@ -881,7 +877,6 @@ static const struct imx477_reg mode_1332x990_regs[] = {
881877	{0x0305 , 0x02 },
882878	{0x0306 , 0x00 },
883879	{0x0307 , 0xaf },
884- 	{0x0309 , 0x0a },
885880	{0xe04c , 0x00 },
886881	{0xe04d , 0x5f },
887882	{0xe04e , 0x00 },
@@ -891,12 +886,12 @@ static const struct imx477_reg mode_1332x990_regs[] = {
891886};
892887
893888/* Mode configs */ 
894- static  const  struct  imx477_mode  supported_modes_12bit [] =  {
889+ static  const  struct  imx477_mode  supported_modes [] =  {
895890	{
896891		/* 12MPix 10fps mode */ 
897892		.width  =  4056 ,
898893		.height  =  3040 ,
899- 		.line_length_pix  =  24000 ,
894+ 		.line_length_pix  =  {  24000 ,  20000  } ,
900895		.crop  =  {
901896			.left  =  IMX477_PIXEL_ARRAY_LEFT ,
902897			.top  =  IMX477_PIXEL_ARRAY_TOP ,
@@ -930,7 +925,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
930925		/* 2x2 binned 40fps mode */ 
931926		.width  =  2028 ,
932927		.height  =  1520 ,
933- 		.line_length_pix  =  12740 ,
928+ 		.line_length_pix  =  {  12740 ,  10616  } ,
934929		.crop  =  {
935930			.left  =  IMX477_PIXEL_ARRAY_LEFT ,
936931			.top  =  IMX477_PIXEL_ARRAY_TOP ,
@@ -947,7 +942,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
947942		/* 1080p 50fps cropped mode */ 
948943		.width  =  2028 ,
949944		.height  =  1080 ,
950- 		.line_length_pix  =  12740 ,
945+ 		.line_length_pix  =  {  12740 ,  10616  } ,
951946		.crop  =  {
952947			.left  =  IMX477_PIXEL_ARRAY_LEFT ,
953948			.top  =  IMX477_PIXEL_ARRAY_TOP  +  440 ,
@@ -959,15 +954,12 @@ static const struct imx477_mode supported_modes_12bit[] = {
959954			.num_of_regs  =  ARRAY_SIZE (mode_2028x1080_regs ),
960955			.regs  =  mode_2028x1080_regs ,
961956		},
962- 	}
963- };
964- 
965- static  const  struct  imx477_mode  supported_modes_10bit [] =  {
957+ 	},
966958	{
967959		/* 120fps. 2x2 binned and cropped */ 
968960		.width  =  1332 ,
969961		.height  =  990 ,
970- 		.line_length_pix  =  6664 ,
962+ 		.line_length_pix  =  {  7997 ,  6664  } ,
971963		.crop  =  {
972964			/* 
973965			 * FIXME: the analog crop rectangle is actually 
@@ -1119,33 +1111,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
11191111	return  container_of (_sd , struct  imx477 , sd );
11201112}
11211113
1122- static  inline  void  get_mode_table (unsigned int   code ,
1123- 				  const  struct  imx477_mode  * * mode_list ,
1124- 				  unsigned int   * num_modes )
1125- {
1126- 	switch  (code ) {
1127- 	/* 12-bit */ 
1128- 	case  MEDIA_BUS_FMT_SRGGB12_1X12 :
1129- 	case  MEDIA_BUS_FMT_SGRBG12_1X12 :
1130- 	case  MEDIA_BUS_FMT_SGBRG12_1X12 :
1131- 	case  MEDIA_BUS_FMT_SBGGR12_1X12 :
1132- 		* mode_list  =  supported_modes_12bit ;
1133- 		* num_modes  =  ARRAY_SIZE (supported_modes_12bit );
1134- 		break ;
1135- 	/* 10-bit */ 
1136- 	case  MEDIA_BUS_FMT_SRGGB10_1X10 :
1137- 	case  MEDIA_BUS_FMT_SGRBG10_1X10 :
1138- 	case  MEDIA_BUS_FMT_SGBRG10_1X10 :
1139- 	case  MEDIA_BUS_FMT_SBGGR10_1X10 :
1140- 		* mode_list  =  supported_modes_10bit ;
1141- 		* num_modes  =  ARRAY_SIZE (supported_modes_10bit );
1142- 		break ;
1143- 	default :
1144- 		* mode_list  =  NULL ;
1145- 		* num_modes  =  0 ;
1146- 	}
1147- }
1148- 
11491114/* Read registers up to 2 at a time */ 
11501115static  int  imx477_read_reg (struct  imx477  * imx477 , u16  reg , u32  len , u32  * val )
11511116{
@@ -1241,7 +1206,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
12411206static  void  imx477_set_default_format (struct  imx477  * imx477 )
12421207{
12431208	/* Set default mode to max resolution */ 
1244- 	imx477 -> mode  =  & supported_modes_12bit [0 ];
1209+ 	imx477 -> mode  =  & supported_modes [0 ];
12451210	imx477 -> fmt_code  =  MEDIA_BUS_FMT_SRGGB12_1X12 ;
12461211}
12471212
@@ -1257,8 +1222,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
12571222	mutex_lock (& imx477 -> mutex );
12581223
12591224	/* Initialize try_fmt for the image pad */ 
1260- 	try_fmt_img -> width  =  supported_modes_12bit [0 ].width ;
1261- 	try_fmt_img -> height  =  supported_modes_12bit [0 ].height ;
1225+ 	try_fmt_img -> width  =  supported_modes [0 ].width ;
1226+ 	try_fmt_img -> height  =  supported_modes [0 ].height ;
12621227	try_fmt_img -> code  =  imx477_get_format_code (imx477 ,
12631228						   MEDIA_BUS_FMT_SRGGB12_1X12 );
12641229	try_fmt_img -> field  =  V4L2_FIELD_NONE ;
@@ -1436,20 +1401,15 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
14361401		return  - EINVAL ;
14371402
14381403	if  (fse -> pad  ==  IMAGE_PAD ) {
1439- 		const  struct  imx477_mode  * mode_list ;
1440- 		unsigned int   num_modes ;
1441- 
1442- 		get_mode_table (fse -> code , & mode_list , & num_modes );
1443- 
1444- 		if  (fse -> index  >= num_modes )
1404+ 		if  (fse -> index  >= ARRAY_SIZE (supported_modes ))
14451405			return  - EINVAL ;
14461406
14471407		if  (fse -> code  !=  imx477_get_format_code (imx477 , fse -> code ))
14481408			return  - EINVAL ;
14491409
1450- 		fse -> min_width  =  mode_list [fse -> index ].width ;
1410+ 		fse -> min_width  =  supported_modes [fse -> index ].width ;
14511411		fse -> max_width  =  fse -> min_width ;
1452- 		fse -> min_height  =  mode_list [fse -> index ].height ;
1412+ 		fse -> min_height  =  supported_modes [fse -> index ].height ;
14531413		fse -> max_height  =  fse -> min_height ;
14541414	} else  {
14551415		if  (fse -> code  !=  MEDIA_BUS_FMT_SENSOR_DATA  ||  fse -> index  >  0 )
@@ -1527,44 +1487,36 @@ static int imx477_get_pad_format(struct v4l2_subdev *sd,
15271487	return  0 ;
15281488}
15291489
1530- static 
1531- unsigned int   imx477_get_frame_length (const  struct  imx477_mode  * mode ,
1532- 				     unsigned int   framerate_default )
1533- {
1534- 	u64  frame_length ;
1535- 
1536- 	frame_length  =  IMX477_PIXEL_RATE ;
1537- 	do_div (frame_length ,
1538- 	       (u64 )framerate_default  *  mode -> line_length_pix );
1539- 
1540- 	if  (WARN_ON (frame_length  >  IMX477_FRAME_LENGTH_MAX ))
1541- 		frame_length  =  IMX477_FRAME_LENGTH_MAX ;
1542- 
1543- 	return  max_t (unsigned  int , frame_length , mode -> height );
1544- }
1545- 
15461490static  void  imx477_set_framing_limits (struct  imx477  * imx477 )
15471491{
1548- 	unsigned int   frm_length_default ,  hblank_min ;
1492+ 	unsigned int   hblank_min ;
15491493	const  struct  imx477_mode  * mode  =  imx477 -> mode ;
15501494	unsigned int   line_length_pix ;
15511495
1552- 	frm_length_default  = 
1553- 		     imx477_get_frame_length (mode , mode -> framerate_default );
1554- 
15551496	/* Default to no long exposure multiplier. */ 
15561497	imx477 -> long_exp_shift  =  0 ;
15571498
15581499	/* Update limits and set FPS to default */ 
15591500	__v4l2_ctrl_modify_range (imx477 -> vblank , 1 ,
15601501				 ((1  << IMX477_LONG_EXP_SHIFT_MAX ) * 
15611502					IMX477_FRAME_LENGTH_MAX ) -  mode -> height ,
1562- 				 IMX477_VBLANK_MIN , frm_length_default  -  mode -> height );
1563- 
1564- 	/* Setting this will adjust the exposure limits as well. */ 
1565- 	__v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default  -  mode -> height );
1503+ 				 IMX477_VBLANK_MIN , IMX477_VBLANK_MIN );
15661504
1567- 	line_length_pix  =  mode -> line_length_pix ;
1505+ 	switch  (imx477 -> fmt_code ) {
1506+ 	case  MEDIA_BUS_FMT_SRGGB12_1X12 :
1507+ 	case  MEDIA_BUS_FMT_SGRBG12_1X12 :
1508+ 	case  MEDIA_BUS_FMT_SGBRG12_1X12 :
1509+ 	case  MEDIA_BUS_FMT_SBGGR12_1X12 :
1510+ 		line_length_pix  =  mode -> line_length_pix [0 ];
1511+ 		break ;
1512+ 	/* 10-bit */ 
1513+ 	case  MEDIA_BUS_FMT_SRGGB10_1X10 :
1514+ 	case  MEDIA_BUS_FMT_SGRBG10_1X10 :
1515+ 	case  MEDIA_BUS_FMT_SGBRG10_1X10 :
1516+ 	case  MEDIA_BUS_FMT_SBGGR10_1X10 :
1517+ 		line_length_pix  =  mode -> line_length_pix [1 ];
1518+ 		break ;
1519+ 	}
15681520	if  (imx477 -> double_link_freq )
15691521		line_length_pix  /= 2 ;
15701522	hblank_min  =  line_length_pix  -  mode -> width ;
@@ -1587,17 +1539,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
15871539	mutex_lock (& imx477 -> mutex );
15881540
15891541	if  (fmt -> pad  ==  IMAGE_PAD ) {
1590- 		const  struct  imx477_mode  * mode_list ;
1591- 		unsigned int   num_modes ;
1592- 
15931542		/* Bayer order varies with flips */ 
15941543		fmt -> format .code  =  imx477_get_format_code (imx477 ,
15951544							  fmt -> format .code );
15961545
1597- 		get_mode_table (fmt -> format .code , & mode_list , & num_modes );
1598- 
1599- 		mode  =  v4l2_find_nearest_size (mode_list ,
1600- 					      num_modes ,
1546+ 		mode  =  v4l2_find_nearest_size (supported_modes ,
1547+ 					      ARRAY_SIZE (supported_modes ),
16011548					      width , height ,
16021549					      fmt -> format .width ,
16031550					      fmt -> format .height );
@@ -1606,7 +1553,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
16061553			framefmt  =  v4l2_subdev_get_try_format (sd , sd_state ,
16071554							      fmt -> pad );
16081555			* framefmt  =  fmt -> format ;
1609- 		} else  if  (imx477 -> mode  !=  mode ) {
1556+ 		} else  if  (imx477 -> mode  !=  mode  || 
1557+ 			   fmt -> format .code  !=  imx477 -> fmt_code ) {
16101558			imx477 -> mode  =  mode ;
16111559			imx477 -> fmt_code  =  fmt -> format .code ;
16121560			imx477_set_framing_limits (imx477 );
@@ -1685,7 +1633,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
16851633	struct  i2c_client  * client  =  v4l2_get_subdevdata (& imx477 -> sd );
16861634	const  struct  imx477_reg_list  * reg_list , * freq_regs ;
16871635	const  struct  imx477_reg_list  * extra_regs ;
1688- 	int  ret , tm ;
1636+ 	int  ret , tm ,  val ;
16891637
16901638	if  (!imx477 -> common_regs_written ) {
16911639		ret  =  imx477_write_regs (imx477 , mode_common_regs ,
@@ -1729,6 +1677,28 @@ static int imx477_start_streaming(struct imx477 *imx477)
17291677		return  ret ;
17301678	}
17311679
1680+ 	switch  (imx477 -> fmt_code ) {
1681+ 	case  MEDIA_BUS_FMT_SRGGB12_1X12 :
1682+ 	case  MEDIA_BUS_FMT_SGRBG12_1X12 :
1683+ 	case  MEDIA_BUS_FMT_SGBRG12_1X12 :
1684+ 	case  MEDIA_BUS_FMT_SBGGR12_1X12 :
1685+ 		val  =  0x0c ;
1686+ 		break ;
1687+ 	/* 10-bit */ 
1688+ 	case  MEDIA_BUS_FMT_SRGGB10_1X10 :
1689+ 	case  MEDIA_BUS_FMT_SGRBG10_1X10 :
1690+ 	case  MEDIA_BUS_FMT_SGBRG10_1X10 :
1691+ 	case  MEDIA_BUS_FMT_SBGGR10_1X10 :
1692+ 		val  =  0x0a ;
1693+ 		break ;
1694+ 	}
1695+ 	imx477_write_reg (imx477 , IMX477_REG_CSI_DT_FMT_H ,
1696+ 			 IMX477_REG_VALUE_08BIT , val );
1697+ 	imx477_write_reg (imx477 , IMX477_REG_CSI_DT_FMT_L ,
1698+ 			 IMX477_REG_VALUE_08BIT , val );
1699+ 	imx477_write_reg (imx477 , IMX477_REG_IOP_PXCK_DIV ,
1700+ 			 IMX477_REG_VALUE_08BIT , val );
1701+ 
17321702	/* Set on-sensor DPC. */ 
17331703	imx477_write_reg (imx477 , 0x0b05 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
17341704	imx477_write_reg (imx477 , 0x0b06 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
0 commit comments