@@ -60,6 +60,9 @@ MODULE_PARM_DESC(fstrobe_delay, "Set fstrobe delay from end all lines starting t
6060
6161#define IMX477_REG_ORIENTATION CCI_REG8(0x101)
6262
63+ #define IMX477_REG_CSI_DT_FMT_H CCI_REG8(0x0112)
64+ #define IMX477_REG_CSI_DT_FMT_L CCI_REG8(0x0113)
65+
6366#define IMX477_XCLK_FREQ 24000000
6467
6568#define IMX477_DEFAULT_LINK_FREQ 450000000
@@ -103,6 +106,7 @@ MODULE_PARM_DESC(fstrobe_delay, "Set fstrobe delay from end all lines starting t
103106#define IMX477_DGTL_GAIN_DEFAULT 0x0100
104107#define IMX477_DGTL_GAIN_STEP 1
105108
109+ #define IMX477_REG_IOP_PXCK_DIV CCI_REG8(0x0309)
106110#define IMX477_REG_IOP_SYSCK_DIV CCI_REG8(0x030b)
107111 #define IMX477_IOP_SYSCK_DIV 0x02
108112#define IMX477_REG_IOP_PREDIV CCI_REG8(0x030d)
@@ -142,6 +146,7 @@ MODULE_PARM_DESC(fstrobe_delay, "Set fstrobe delay from end all lines starting t
142146#define IMX477_REG_XVS_IO_CTRL CCI_REG8(0x3040)
143147#define IMX477_REG_EXTOUT_EN CCI_REG8(0x4b81)
144148
149+ #define IMX477_REG_ADBIT_MODE CCI_REG8(0x3f0d)
145150/* Temperature sensor */
146151#define IMX477_REG_TEMP_SEN_CTL CCI_REG8(0x0138)
147152
@@ -490,8 +495,6 @@ static const struct cci_reg_sequence mode_common_regs[] = {
490495 {CCI_REG8 (0xb21f ), 0x04 },
491496 {CCI_REG8 (0xb35c ), 0x00 },
492497 {CCI_REG8 (0xb35e ), 0x08 },
493- {CCI_REG8 (0x0112 ), 0x0c },
494- {CCI_REG8 (0x0113 ), 0x0c },
495498 {CCI_REG8 (0x0114 ), 0x01 },
496499 {CCI_REG8 (0x0350 ), 0x00 },
497500 {CCI_REG8 (0xbcf1 ), 0x02 },
@@ -557,7 +560,6 @@ static const struct cci_reg_sequence mode_4056x3040_regs[] = {
557560 {CCI_REG8 (0x0901 ), 0x11 },
558561 {CCI_REG8 (0x3c01 ), 0x03 },
559562 {CCI_REG8 (0x3c02 ), 0xa2 },
560- {CCI_REG8 (0x3f0d ), 0x01 },
561563 {CCI_REG8 (0x5748 ), 0x07 },
562564 {CCI_REG8 (0x5749 ), 0xff },
563565 {CCI_REG8 (0x574a ), 0x00 },
@@ -593,7 +595,6 @@ static const struct cci_reg_sequence mode_4056x3040_regs[] = {
593595 {CCI_REG8 (0x0305 ), 0x04 },
594596 {CCI_REG8 (0x0306 ), 0x01 },
595597 {CCI_REG8 (0x0307 ), 0x5e },
596- {CCI_REG8 (0x0309 ), 0x0c },
597598 {CCI_REG8 (0xe04c ), 0x00 },
598599 {CCI_REG8 (0xe04d ), 0x7f },
599600 {CCI_REG8 (0xe04e ), 0x00 },
@@ -622,7 +623,6 @@ static const struct cci_reg_sequence mode_4056x2160_regs[] = {
622623 {CCI_REG8 (0x0901 ), 0x11 },
623624 {CCI_REG8 (0x3c01 ), 0x03 },
624625 {CCI_REG8 (0x3c02 ), 0xa2 },
625- {CCI_REG8 (0x3f0d ), 0x01 },
626626 {CCI_REG8 (0x5748 ), 0x07 },
627627 {CCI_REG8 (0x5749 ), 0xff },
628628 {CCI_REG8 (0x574a ), 0x00 },
@@ -680,7 +680,6 @@ static const struct cci_reg_sequence mode_2028x1520_regs[] = {
680680 {CCI_REG8 (0x0901 ), 0x22 },
681681 {CCI_REG8 (0x3c01 ), 0x03 },
682682 {CCI_REG8 (0x3c02 ), 0xa2 },
683- {CCI_REG8 (0x3f0d ), 0x01 },
684683 {CCI_REG8 (0x5748 ), 0x07 },
685684 {CCI_REG8 (0x5749 ), 0xff },
686685 {CCI_REG8 (0x574a ), 0x00 },
@@ -711,7 +710,6 @@ static const struct cci_reg_sequence mode_2028x1520_regs[] = {
711710 {CCI_REG8 (0x0305 ), 0x04 },
712711 {CCI_REG8 (0x0306 ), 0x01 },
713712 {CCI_REG8 (0x0307 ), 0x5e },
714- {CCI_REG8 (0x0309 ), 0x0c },
715713 {CCI_REG8 (0xe04c ), 0x00 },
716714 {CCI_REG8 (0xe04d ), 0x7f },
717715 {CCI_REG8 (0xe04e ), 0x00 },
@@ -734,7 +732,6 @@ static const struct cci_reg_sequence mode_2028x1080_regs[] = {
734732 {CCI_REG8 (0x0901 ), 0x22 },
735733 {CCI_REG8 (0x3c01 ), 0x03 },
736734 {CCI_REG8 (0x3c02 ), 0xa2 },
737- {CCI_REG8 (0x3f0d ), 0x01 },
738735 {CCI_REG8 (0x5748 ), 0x07 },
739736 {CCI_REG8 (0x5749 ), 0xff },
740737 {CCI_REG8 (0x574a ), 0x00 },
@@ -765,7 +762,6 @@ static const struct cci_reg_sequence mode_2028x1080_regs[] = {
765762 {CCI_REG8 (0x0305 ), 0x04 },
766763 {CCI_REG8 (0x0306 ), 0x01 },
767764 {CCI_REG8 (0x0307 ), 0x5e },
768- {CCI_REG8 (0x0309 ), 0x0c },
769765 {CCI_REG8 (0xe04c ), 0x00 },
770766 {CCI_REG8 (0xe04d ), 0x7f },
771767 {CCI_REG8 (0xe04e ), 0x00 },
@@ -788,8 +784,6 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
788784 {CCI_REG8 (0x9a4b ), 0x06 },
789785 {CCI_REG8 (0x9a4c ), 0x06 },
790786 {CCI_REG8 (0x9a4d ), 0x06 },
791- {CCI_REG8 (0x0112 ), 0x0a },
792- {CCI_REG8 (0x0113 ), 0x0a },
793787 {CCI_REG8 (0x0114 ), 0x01 },
794788 {CCI_REG8 (0x0340 ), 0x04 },
795789 {CCI_REG8 (0x0341 ), 0x1a },
@@ -821,7 +815,6 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
821815 {CCI_REG8 (0x3c00 ), 0x00 },
822816 {CCI_REG8 (0x3c01 ), 0x01 },
823817 {CCI_REG8 (0x3c02 ), 0x9c },
824- {CCI_REG8 (0x3f0d ), 0x00 },
825818 {CCI_REG8 (0x5748 ), 0x00 },
826819 {CCI_REG8 (0x5749 ), 0x00 },
827820 {CCI_REG8 (0x574a ), 0x00 },
@@ -857,7 +850,6 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
857850 {CCI_REG8 (0x0305 ), 0x02 },
858851 {CCI_REG8 (0x0306 ), 0x00 },
859852 {CCI_REG8 (0x0307 ), 0xaf },
860- {CCI_REG8 (0x0309 ), 0x0a },
861853 {CCI_REG8 (0xe04c ), 0x00 },
862854 {CCI_REG8 (0xe04d ), 0x5f },
863855 {CCI_REG8 (0xe04e ), 0x00 },
@@ -867,7 +859,7 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
867859};
868860
869861/* Mode configs */
870- static const struct imx477_mode supported_modes_12bit [] = {
862+ static const struct imx477_mode supported_modes [] = {
871863 {
872864 /* 12MPix 10fps mode */
873865 .width = 4056 ,
@@ -931,10 +923,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
931923 .num_of_regs = ARRAY_SIZE (mode_2028x1080_regs ),
932924 .regs = mode_2028x1080_regs ,
933925 },
934- }
935- };
936-
937- static const struct imx477_mode supported_modes_10bit [] = {
926+ },
938927 {
939928 /* 120fps. 2x2 binned and cropped */
940929 .width = 1332 ,
@@ -1081,33 +1070,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
10811070 return container_of (_sd , struct imx477 , sd );
10821071}
10831072
1084- static inline void get_mode_table (unsigned int code ,
1085- const struct imx477_mode * * mode_list ,
1086- unsigned int * num_modes )
1087- {
1088- switch (code ) {
1089- /* 12-bit */
1090- case MEDIA_BUS_FMT_SRGGB12_1X12 :
1091- case MEDIA_BUS_FMT_SGRBG12_1X12 :
1092- case MEDIA_BUS_FMT_SGBRG12_1X12 :
1093- case MEDIA_BUS_FMT_SBGGR12_1X12 :
1094- * mode_list = supported_modes_12bit ;
1095- * num_modes = ARRAY_SIZE (supported_modes_12bit );
1096- break ;
1097- /* 10-bit */
1098- case MEDIA_BUS_FMT_SRGGB10_1X10 :
1099- case MEDIA_BUS_FMT_SGRBG10_1X10 :
1100- case MEDIA_BUS_FMT_SGBRG10_1X10 :
1101- case MEDIA_BUS_FMT_SBGGR10_1X10 :
1102- * mode_list = supported_modes_10bit ;
1103- * num_modes = ARRAY_SIZE (supported_modes_10bit );
1104- break ;
1105- default :
1106- * mode_list = NULL ;
1107- * num_modes = 0 ;
1108- }
1109- }
1110-
11111073/* Get bayer order based on flip setting. */
11121074static u32 imx477_get_format_code (struct imx477 * imx477 , u32 code )
11131075{
@@ -1131,7 +1093,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
11311093static void imx477_set_default_format (struct imx477 * imx477 )
11321094{
11331095 /* Set default mode to max resolution */
1134- imx477 -> mode = & supported_modes_12bit [0 ];
1096+ imx477 -> mode = & supported_modes [0 ];
11351097 imx477 -> fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12 ;
11361098}
11371099
@@ -1165,8 +1127,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
11651127 mutex_lock (& imx477 -> mutex );
11661128
11671129 /* Initialize try_fmt for the image pad */
1168- try_fmt_img -> width = supported_modes_12bit [0 ].width ;
1169- try_fmt_img -> height = supported_modes_12bit [0 ].height ;
1130+ try_fmt_img -> width = supported_modes [0 ].width ;
1131+ try_fmt_img -> height = supported_modes [0 ].height ;
11701132 try_fmt_img -> code = imx477_get_format_code (imx477 ,
11711133 MEDIA_BUS_FMT_SRGGB12_1X12 );
11721134 try_fmt_img -> field = V4L2_FIELD_NONE ;
@@ -1342,12 +1304,7 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
13421304 return - EINVAL ;
13431305
13441306 if (fse -> pad == IMAGE_PAD ) {
1345- const struct imx477_mode * mode_list ;
1346- unsigned int num_modes ;
1347-
1348- get_mode_table (fse -> code , & mode_list , & num_modes );
1349-
1350- if (fse -> index >= num_modes )
1307+ if (fse -> index >= ARRAY_SIZE (supported_modes ))
13511308 return - EINVAL ;
13521309
13531310 mutex_lock (& imx477 -> mutex );
@@ -1357,9 +1314,9 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
13571314 if (fse -> code != code )
13581315 return - EINVAL ;
13591316
1360- fse -> min_width = mode_list [fse -> index ].width ;
1317+ fse -> min_width = supported_modes [fse -> index ].width ;
13611318 fse -> max_width = fse -> min_width ;
1362- fse -> min_height = mode_list [fse -> index ].height ;
1319+ fse -> min_height = supported_modes [fse -> index ].height ;
13631320 fse -> max_height = fse -> min_height ;
13641321 } else {
13651322 if (fse -> code != MEDIA_BUS_FMT_SENSOR_DATA || fse -> index > 0 )
@@ -1465,6 +1422,16 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
14651422 /* Allow 500pixel clocks for HS<>LP transitions (approx 0.6usecs) */
14661423 line_length_min += 500 ;
14671424
1425+ /*
1426+ * 1332x990 12bit mode appears to need additional horizontal blanking
1427+ * compared to all other modes. Empirically determined setting with
1428+ * link freq of 750MHz where it still gives valid images. The limit
1429+ * leaves all other modes unchanged as their line times are inherently
1430+ * greater.
1431+ */
1432+ if (bpp == 12 )
1433+ line_length_min = max (line_length_min , 1332 + 4600 );
1434+
14681435 hblank_min = line_length_min - mode -> width ;
14691436 __v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
14701437 IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
@@ -1485,17 +1452,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
14851452 mutex_lock (& imx477 -> mutex );
14861453
14871454 if (fmt -> pad == IMAGE_PAD ) {
1488- const struct imx477_mode * mode_list ;
1489- unsigned int num_modes ;
1490-
14911455 /* Bayer order varies with flips */
14921456 fmt -> format .code = imx477_get_format_code (imx477 ,
14931457 fmt -> format .code );
14941458
1495- get_mode_table (fmt -> format .code , & mode_list , & num_modes );
1496-
1497- mode = v4l2_find_nearest_size (mode_list ,
1498- num_modes ,
1459+ mode = v4l2_find_nearest_size (supported_modes ,
1460+ ARRAY_SIZE (supported_modes ),
14991461 width , height ,
15001462 fmt -> format .width ,
15011463 fmt -> format .height );
@@ -1504,7 +1466,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
15041466 framefmt = v4l2_subdev_state_get_format (sd_state ,
15051467 fmt -> pad );
15061468 * framefmt = fmt -> format ;
1507- } else if (imx477 -> mode != mode ) {
1469+ } else if (imx477 -> mode != mode ||
1470+ imx477 -> fmt_code != fmt -> format .code ) {
15081471 imx477 -> mode = mode ;
15091472 imx477 -> fmt_code = fmt -> format .code ;
15101473 imx477_set_framing_limits (imx477 );
@@ -1585,7 +1548,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
15851548 const struct imx477_reg_list * extra_regs ;
15861549 unsigned int fst_width ;
15871550 unsigned int fst_mult ;
1588- int ret , tm ;
1551+ int ret , tm , bpp ;
15891552
15901553 if (!imx477 -> common_regs_written ) {
15911554 ret = cci_multi_reg_write (imx477 -> regmap , mode_common_regs ,
@@ -1653,6 +1616,13 @@ static int imx477_start_streaming(struct imx477 *imx477)
16531616 // FLASH_TRIG_RS
16541617 cci_write (imx477 -> regmap , CCI_REG8 (0x0c1B ), !!fstrobe_enable , & ret );
16551618
1619+ bpp = imx477_get_bpp (imx477 -> fmt_code );
1620+ cci_write (imx477 -> regmap , IMX477_REG_CSI_DT_FMT_H , bpp , & ret );
1621+ cci_write (imx477 -> regmap , IMX477_REG_CSI_DT_FMT_L , bpp , & ret );
1622+ cci_write (imx477 -> regmap , IMX477_REG_IOP_PXCK_DIV , bpp , & ret );
1623+ cci_write (imx477 -> regmap , IMX477_REG_ADBIT_MODE , bpp == 12 ? 1 : 0 ,
1624+ & ret );
1625+
16561626 /* Set on-sensor DPC. */
16571627 cci_write (imx477 -> regmap , CCI_REG8 (0x0b05 ), !!dpc_enable , & ret );
16581628 cci_write (imx477 -> regmap , CCI_REG8 (0x0b06 ), !!dpc_enable , & ret );
0 commit comments