@@ -60,6 +60,9 @@ MODULE_PARM_DESC(fstrobe_delay, "Set fstrobe delay from end all lines starting t
60
60
61
61
#define IMX477_REG_ORIENTATION CCI_REG8(0x101)
62
62
63
+ #define IMX477_REG_CSI_DT_FMT_H CCI_REG8(0x0112)
64
+ #define IMX477_REG_CSI_DT_FMT_L CCI_REG8(0x0113)
65
+
63
66
#define IMX477_XCLK_FREQ 24000000
64
67
65
68
#define IMX477_DEFAULT_LINK_FREQ 450000000
@@ -103,6 +106,7 @@ MODULE_PARM_DESC(fstrobe_delay, "Set fstrobe delay from end all lines starting t
103
106
#define IMX477_DGTL_GAIN_DEFAULT 0x0100
104
107
#define IMX477_DGTL_GAIN_STEP 1
105
108
109
+ #define IMX477_REG_IOP_PXCK_DIV CCI_REG8(0x0309)
106
110
#define IMX477_REG_IOP_SYSCK_DIV CCI_REG8(0x030b)
107
111
#define IMX477_IOP_SYSCK_DIV 0x02
108
112
#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
142
146
#define IMX477_REG_XVS_IO_CTRL CCI_REG8(0x3040)
143
147
#define IMX477_REG_EXTOUT_EN CCI_REG8(0x4b81)
144
148
149
+ #define IMX477_REG_ADBIT_MODE CCI_REG8(0x3f0d)
145
150
/* Temperature sensor */
146
151
#define IMX477_REG_TEMP_SEN_CTL CCI_REG8(0x0138)
147
152
@@ -490,8 +495,6 @@ static const struct cci_reg_sequence mode_common_regs[] = {
490
495
{CCI_REG8 (0xb21f ), 0x04 },
491
496
{CCI_REG8 (0xb35c ), 0x00 },
492
497
{CCI_REG8 (0xb35e ), 0x08 },
493
- {CCI_REG8 (0x0112 ), 0x0c },
494
- {CCI_REG8 (0x0113 ), 0x0c },
495
498
{CCI_REG8 (0x0114 ), 0x01 },
496
499
{CCI_REG8 (0x0350 ), 0x00 },
497
500
{CCI_REG8 (0xbcf1 ), 0x02 },
@@ -557,7 +560,6 @@ static const struct cci_reg_sequence mode_4056x3040_regs[] = {
557
560
{CCI_REG8 (0x0901 ), 0x11 },
558
561
{CCI_REG8 (0x3c01 ), 0x03 },
559
562
{CCI_REG8 (0x3c02 ), 0xa2 },
560
- {CCI_REG8 (0x3f0d ), 0x01 },
561
563
{CCI_REG8 (0x5748 ), 0x07 },
562
564
{CCI_REG8 (0x5749 ), 0xff },
563
565
{CCI_REG8 (0x574a ), 0x00 },
@@ -593,7 +595,6 @@ static const struct cci_reg_sequence mode_4056x3040_regs[] = {
593
595
{CCI_REG8 (0x0305 ), 0x04 },
594
596
{CCI_REG8 (0x0306 ), 0x01 },
595
597
{CCI_REG8 (0x0307 ), 0x5e },
596
- {CCI_REG8 (0x0309 ), 0x0c },
597
598
{CCI_REG8 (0xe04c ), 0x00 },
598
599
{CCI_REG8 (0xe04d ), 0x7f },
599
600
{CCI_REG8 (0xe04e ), 0x00 },
@@ -622,7 +623,6 @@ static const struct cci_reg_sequence mode_4056x2160_regs[] = {
622
623
{CCI_REG8 (0x0901 ), 0x11 },
623
624
{CCI_REG8 (0x3c01 ), 0x03 },
624
625
{CCI_REG8 (0x3c02 ), 0xa2 },
625
- {CCI_REG8 (0x3f0d ), 0x01 },
626
626
{CCI_REG8 (0x5748 ), 0x07 },
627
627
{CCI_REG8 (0x5749 ), 0xff },
628
628
{CCI_REG8 (0x574a ), 0x00 },
@@ -680,7 +680,6 @@ static const struct cci_reg_sequence mode_2028x1520_regs[] = {
680
680
{CCI_REG8 (0x0901 ), 0x22 },
681
681
{CCI_REG8 (0x3c01 ), 0x03 },
682
682
{CCI_REG8 (0x3c02 ), 0xa2 },
683
- {CCI_REG8 (0x3f0d ), 0x01 },
684
683
{CCI_REG8 (0x5748 ), 0x07 },
685
684
{CCI_REG8 (0x5749 ), 0xff },
686
685
{CCI_REG8 (0x574a ), 0x00 },
@@ -711,7 +710,6 @@ static const struct cci_reg_sequence mode_2028x1520_regs[] = {
711
710
{CCI_REG8 (0x0305 ), 0x04 },
712
711
{CCI_REG8 (0x0306 ), 0x01 },
713
712
{CCI_REG8 (0x0307 ), 0x5e },
714
- {CCI_REG8 (0x0309 ), 0x0c },
715
713
{CCI_REG8 (0xe04c ), 0x00 },
716
714
{CCI_REG8 (0xe04d ), 0x7f },
717
715
{CCI_REG8 (0xe04e ), 0x00 },
@@ -734,7 +732,6 @@ static const struct cci_reg_sequence mode_2028x1080_regs[] = {
734
732
{CCI_REG8 (0x0901 ), 0x22 },
735
733
{CCI_REG8 (0x3c01 ), 0x03 },
736
734
{CCI_REG8 (0x3c02 ), 0xa2 },
737
- {CCI_REG8 (0x3f0d ), 0x01 },
738
735
{CCI_REG8 (0x5748 ), 0x07 },
739
736
{CCI_REG8 (0x5749 ), 0xff },
740
737
{CCI_REG8 (0x574a ), 0x00 },
@@ -765,7 +762,6 @@ static const struct cci_reg_sequence mode_2028x1080_regs[] = {
765
762
{CCI_REG8 (0x0305 ), 0x04 },
766
763
{CCI_REG8 (0x0306 ), 0x01 },
767
764
{CCI_REG8 (0x0307 ), 0x5e },
768
- {CCI_REG8 (0x0309 ), 0x0c },
769
765
{CCI_REG8 (0xe04c ), 0x00 },
770
766
{CCI_REG8 (0xe04d ), 0x7f },
771
767
{CCI_REG8 (0xe04e ), 0x00 },
@@ -788,8 +784,6 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
788
784
{CCI_REG8 (0x9a4b ), 0x06 },
789
785
{CCI_REG8 (0x9a4c ), 0x06 },
790
786
{CCI_REG8 (0x9a4d ), 0x06 },
791
- {CCI_REG8 (0x0112 ), 0x0a },
792
- {CCI_REG8 (0x0113 ), 0x0a },
793
787
{CCI_REG8 (0x0114 ), 0x01 },
794
788
{CCI_REG8 (0x0340 ), 0x04 },
795
789
{CCI_REG8 (0x0341 ), 0x1a },
@@ -821,7 +815,6 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
821
815
{CCI_REG8 (0x3c00 ), 0x00 },
822
816
{CCI_REG8 (0x3c01 ), 0x01 },
823
817
{CCI_REG8 (0x3c02 ), 0x9c },
824
- {CCI_REG8 (0x3f0d ), 0x00 },
825
818
{CCI_REG8 (0x5748 ), 0x00 },
826
819
{CCI_REG8 (0x5749 ), 0x00 },
827
820
{CCI_REG8 (0x574a ), 0x00 },
@@ -857,7 +850,6 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
857
850
{CCI_REG8 (0x0305 ), 0x02 },
858
851
{CCI_REG8 (0x0306 ), 0x00 },
859
852
{CCI_REG8 (0x0307 ), 0xaf },
860
- {CCI_REG8 (0x0309 ), 0x0a },
861
853
{CCI_REG8 (0xe04c ), 0x00 },
862
854
{CCI_REG8 (0xe04d ), 0x5f },
863
855
{CCI_REG8 (0xe04e ), 0x00 },
@@ -867,7 +859,7 @@ static const struct cci_reg_sequence mode_1332x990_regs[] = {
867
859
};
868
860
869
861
/* Mode configs */
870
- static const struct imx477_mode supported_modes_12bit [] = {
862
+ static const struct imx477_mode supported_modes [] = {
871
863
{
872
864
/* 12MPix 10fps mode */
873
865
.width = 4056 ,
@@ -931,10 +923,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
931
923
.num_of_regs = ARRAY_SIZE (mode_2028x1080_regs ),
932
924
.regs = mode_2028x1080_regs ,
933
925
},
934
- }
935
- };
936
-
937
- static const struct imx477_mode supported_modes_10bit [] = {
926
+ },
938
927
{
939
928
/* 120fps. 2x2 binned and cropped */
940
929
.width = 1332 ,
@@ -1081,33 +1070,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
1081
1070
return container_of (_sd , struct imx477 , sd );
1082
1071
}
1083
1072
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
-
1111
1073
/* Get bayer order based on flip setting. */
1112
1074
static u32 imx477_get_format_code (struct imx477 * imx477 , u32 code )
1113
1075
{
@@ -1131,7 +1093,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
1131
1093
static void imx477_set_default_format (struct imx477 * imx477 )
1132
1094
{
1133
1095
/* Set default mode to max resolution */
1134
- imx477 -> mode = & supported_modes_12bit [0 ];
1096
+ imx477 -> mode = & supported_modes [0 ];
1135
1097
imx477 -> fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12 ;
1136
1098
}
1137
1099
@@ -1165,8 +1127,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1165
1127
mutex_lock (& imx477 -> mutex );
1166
1128
1167
1129
/* 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 ;
1170
1132
try_fmt_img -> code = imx477_get_format_code (imx477 ,
1171
1133
MEDIA_BUS_FMT_SRGGB12_1X12 );
1172
1134
try_fmt_img -> field = V4L2_FIELD_NONE ;
@@ -1342,12 +1304,7 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
1342
1304
return - EINVAL ;
1343
1305
1344
1306
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 ))
1351
1308
return - EINVAL ;
1352
1309
1353
1310
mutex_lock (& imx477 -> mutex );
@@ -1357,9 +1314,9 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
1357
1314
if (fse -> code != code )
1358
1315
return - EINVAL ;
1359
1316
1360
- fse -> min_width = mode_list [fse -> index ].width ;
1317
+ fse -> min_width = supported_modes [fse -> index ].width ;
1361
1318
fse -> max_width = fse -> min_width ;
1362
- fse -> min_height = mode_list [fse -> index ].height ;
1319
+ fse -> min_height = supported_modes [fse -> index ].height ;
1363
1320
fse -> max_height = fse -> min_height ;
1364
1321
} else {
1365
1322
if (fse -> code != MEDIA_BUS_FMT_SENSOR_DATA || fse -> index > 0 )
@@ -1465,6 +1422,16 @@ static void imx477_set_framing_limits(struct imx477 *imx477)
1465
1422
/* Allow 500pixel clocks for HS<>LP transitions (approx 0.6usecs) */
1466
1423
line_length_min += 500 ;
1467
1424
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
+
1468
1435
hblank_min = line_length_min - mode -> width ;
1469
1436
__v4l2_ctrl_modify_range (imx477 -> hblank , hblank_min ,
1470
1437
IMX477_LINE_LENGTH_MAX , 1 , hblank_min );
@@ -1485,17 +1452,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
1485
1452
mutex_lock (& imx477 -> mutex );
1486
1453
1487
1454
if (fmt -> pad == IMAGE_PAD ) {
1488
- const struct imx477_mode * mode_list ;
1489
- unsigned int num_modes ;
1490
-
1491
1455
/* Bayer order varies with flips */
1492
1456
fmt -> format .code = imx477_get_format_code (imx477 ,
1493
1457
fmt -> format .code );
1494
1458
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 ),
1499
1461
width , height ,
1500
1462
fmt -> format .width ,
1501
1463
fmt -> format .height );
@@ -1504,7 +1466,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
1504
1466
framefmt = v4l2_subdev_state_get_format (sd_state ,
1505
1467
fmt -> pad );
1506
1468
* framefmt = fmt -> format ;
1507
- } else if (imx477 -> mode != mode ) {
1469
+ } else if (imx477 -> mode != mode ||
1470
+ imx477 -> fmt_code != fmt -> format .code ) {
1508
1471
imx477 -> mode = mode ;
1509
1472
imx477 -> fmt_code = fmt -> format .code ;
1510
1473
imx477_set_framing_limits (imx477 );
@@ -1585,7 +1548,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
1585
1548
const struct imx477_reg_list * extra_regs ;
1586
1549
unsigned int fst_width ;
1587
1550
unsigned int fst_mult ;
1588
- int ret , tm ;
1551
+ int ret , tm , bpp ;
1589
1552
1590
1553
if (!imx477 -> common_regs_written ) {
1591
1554
ret = cci_multi_reg_write (imx477 -> regmap , mode_common_regs ,
@@ -1653,6 +1616,13 @@ static int imx477_start_streaming(struct imx477 *imx477)
1653
1616
// FLASH_TRIG_RS
1654
1617
cci_write (imx477 -> regmap , CCI_REG8 (0x0c1B ), !!fstrobe_enable , & ret );
1655
1618
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
+
1656
1626
/* Set on-sensor DPC. */
1657
1627
cci_write (imx477 -> regmap , CCI_REG8 (0x0b05 ), !!dpc_enable , & ret );
1658
1628
cci_write (imx477 -> regmap , CCI_REG8 (0x0b06 ), !!dpc_enable , & ret );
0 commit comments