@@ -43,6 +43,9 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
43
43
44
44
#define IMX477_REG_ORIENTATION 0x101
45
45
46
+ #define IMX477_REG_CSI_DT_FMT_H 0x0112
47
+ #define IMX477_REG_CSI_DT_FMT_L 0x0113
48
+
46
49
#define IMX477_XCLK_FREQ 24000000
47
50
48
51
#define IMX477_DEFAULT_LINK_FREQ 450000000
@@ -86,6 +89,7 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
86
89
#define IMX477_DGTL_GAIN_DEFAULT 0x0100
87
90
#define IMX477_DGTL_GAIN_STEP 1
88
91
92
+ #define IMX477_REG_IOP_PXCK_DIV 0x0309
89
93
#define IMX477_REG_DIV_IOP_PX 0x030b
90
94
91
95
/* Test Pattern Control */
@@ -153,8 +157,11 @@ struct imx477_mode {
153
157
/* Frame height */
154
158
unsigned int height ;
155
159
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 ];
158
165
159
166
/* Analog crop rectangle. */
160
167
struct v4l2_rect crop ;
@@ -602,8 +609,6 @@ static const struct imx477_reg mode_common_regs[] = {
602
609
603
610
/* 12 mpix 10fps */
604
611
static const struct imx477_reg mode_4056x3040_regs [] = {
605
- {0x0112 , 0x0c },
606
- {0x0113 , 0x0c },
607
612
{0x0344 , 0x00 },
608
613
{0x0345 , 0x00 },
609
614
{0x0346 , 0x00 },
@@ -658,7 +663,6 @@ static const struct imx477_reg mode_4056x3040_regs[] = {
658
663
{0x0305 , 0x04 },
659
664
{0x0306 , 0x01 },
660
665
{0x0307 , 0x5e },
661
- {0x0309 , 0x0c },
662
666
{0xe04c , 0x00 },
663
667
{0xe04d , 0x7f },
664
668
{0xe04e , 0x00 },
@@ -733,8 +737,6 @@ static const struct imx477_reg mode_4056x2160_regs[] = {
733
737
734
738
/* 2x2 binned. 40fps */
735
739
static const struct imx477_reg mode_2028x1520_regs [] = {
736
- {0x0112 , 0x0c },
737
- {0x0113 , 0x0c },
738
740
{0x0344 , 0x00 },
739
741
{0x0345 , 0x00 },
740
742
{0x0346 , 0x00 },
@@ -778,7 +780,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
778
780
{0x0305 , 0x04 },
779
781
{0x0306 , 0x01 },
780
782
{0x0307 , 0x5e },
781
- {0x0309 , 0x0c },
782
783
{0xe04c , 0x00 },
783
784
{0xe04d , 0x7f },
784
785
{0xe04e , 0x00 },
@@ -789,8 +790,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
789
790
790
791
/* 1080p cropped mode */
791
792
static const struct imx477_reg mode_2028x1080_regs [] = {
792
- {0x0112 , 0x0c },
793
- {0x0113 , 0x0c },
794
793
{0x0344 , 0x00 },
795
794
{0x0345 , 0x00 },
796
795
{0x0346 , 0x01 },
@@ -834,7 +833,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
834
833
{0x0305 , 0x04 },
835
834
{0x0306 , 0x01 },
836
835
{0x0307 , 0x5e },
837
- {0x0309 , 0x0c },
838
836
{0xe04c , 0x00 },
839
837
{0xe04d , 0x7f },
840
838
{0xe04e , 0x00 },
@@ -845,8 +843,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
845
843
846
844
/* 4x4 binned. 120fps */
847
845
static const struct imx477_reg mode_1332x990_regs [] = {
848
- {0x0112 , 0x0a },
849
- {0x0113 , 0x0a },
850
846
{0x420b , 0x01 },
851
847
{0x990c , 0x00 },
852
848
{0x990d , 0x08 },
@@ -914,7 +910,6 @@ static const struct imx477_reg mode_1332x990_regs[] = {
914
910
{0x0305 , 0x02 },
915
911
{0x0306 , 0x00 },
916
912
{0x0307 , 0xaf },
917
- {0x0309 , 0x0a },
918
913
{0xe04c , 0x00 },
919
914
{0xe04d , 0x5f },
920
915
{0xe04e , 0x00 },
@@ -924,12 +919,12 @@ static const struct imx477_reg mode_1332x990_regs[] = {
924
919
};
925
920
926
921
/* Mode configs */
927
- static const struct imx477_mode supported_modes_12bit [] = {
922
+ static const struct imx477_mode supported_modes [] = {
928
923
{
929
924
/* 12MPix 10fps mode */
930
925
.width = 4056 ,
931
926
.height = 3040 ,
932
- .line_length_pix = 24000 ,
927
+ .line_length_pix = { 24000 , 20000 } ,
933
928
.crop = {
934
929
.left = IMX477_PIXEL_ARRAY_LEFT ,
935
930
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -963,7 +958,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
963
958
/* 2x2 binned 40fps mode */
964
959
.width = 2028 ,
965
960
.height = 1520 ,
966
- .line_length_pix = 12740 ,
961
+ .line_length_pix = { 12740 , 10616 } ,
967
962
.crop = {
968
963
.left = IMX477_PIXEL_ARRAY_LEFT ,
969
964
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -980,7 +975,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
980
975
/* 1080p 50fps cropped mode */
981
976
.width = 2028 ,
982
977
.height = 1080 ,
983
- .line_length_pix = 12740 ,
978
+ .line_length_pix = { 12740 , 10616 } ,
984
979
.crop = {
985
980
.left = IMX477_PIXEL_ARRAY_LEFT ,
986
981
.top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -992,15 +987,12 @@ static const struct imx477_mode supported_modes_12bit[] = {
992
987
.num_of_regs = ARRAY_SIZE (mode_2028x1080_regs ),
993
988
.regs = mode_2028x1080_regs ,
994
989
},
995
- }
996
- };
997
-
998
- static const struct imx477_mode supported_modes_10bit [] = {
990
+ },
999
991
{
1000
992
/* 120fps. 2x2 binned and cropped */
1001
993
.width = 1332 ,
1002
994
.height = 990 ,
1003
- .line_length_pix = 6664 ,
995
+ .line_length_pix = { 7997 , 6664 } ,
1004
996
.crop = {
1005
997
/*
1006
998
* FIXME: the analog crop rectangle is actually
@@ -1152,33 +1144,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
1152
1144
return container_of (_sd , struct imx477 , sd );
1153
1145
}
1154
1146
1155
- static inline void get_mode_table (unsigned int code ,
1156
- const struct imx477_mode * * mode_list ,
1157
- unsigned int * num_modes )
1158
- {
1159
- switch (code ) {
1160
- /* 12-bit */
1161
- case MEDIA_BUS_FMT_SRGGB12_1X12 :
1162
- case MEDIA_BUS_FMT_SGRBG12_1X12 :
1163
- case MEDIA_BUS_FMT_SGBRG12_1X12 :
1164
- case MEDIA_BUS_FMT_SBGGR12_1X12 :
1165
- * mode_list = supported_modes_12bit ;
1166
- * num_modes = ARRAY_SIZE (supported_modes_12bit );
1167
- break ;
1168
- /* 10-bit */
1169
- case MEDIA_BUS_FMT_SRGGB10_1X10 :
1170
- case MEDIA_BUS_FMT_SGRBG10_1X10 :
1171
- case MEDIA_BUS_FMT_SGBRG10_1X10 :
1172
- case MEDIA_BUS_FMT_SBGGR10_1X10 :
1173
- * mode_list = supported_modes_10bit ;
1174
- * num_modes = ARRAY_SIZE (supported_modes_10bit );
1175
- break ;
1176
- default :
1177
- * mode_list = NULL ;
1178
- * num_modes = 0 ;
1179
- }
1180
- }
1181
-
1182
1147
/* Read registers up to 2 at a time */
1183
1148
static int imx477_read_reg (struct imx477 * imx477 , u16 reg , u32 len , u32 * val )
1184
1149
{
@@ -1274,7 +1239,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
1274
1239
static void imx477_set_default_format (struct imx477 * imx477 )
1275
1240
{
1276
1241
/* Set default mode to max resolution */
1277
- imx477 -> mode = & supported_modes_12bit [0 ];
1242
+ imx477 -> mode = & supported_modes [0 ];
1278
1243
imx477 -> fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12 ;
1279
1244
}
1280
1245
@@ -1290,8 +1255,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1290
1255
mutex_lock (& imx477 -> mutex );
1291
1256
1292
1257
/* Initialize try_fmt for the image pad */
1293
- try_fmt_img -> width = supported_modes_12bit [0 ].width ;
1294
- try_fmt_img -> height = supported_modes_12bit [0 ].height ;
1258
+ try_fmt_img -> width = supported_modes [0 ].width ;
1259
+ try_fmt_img -> height = supported_modes [0 ].height ;
1295
1260
try_fmt_img -> code = imx477_get_format_code (imx477 ,
1296
1261
MEDIA_BUS_FMT_SRGGB12_1X12 );
1297
1262
try_fmt_img -> field = V4L2_FIELD_NONE ;
@@ -1469,20 +1434,15 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
1469
1434
return - EINVAL ;
1470
1435
1471
1436
if (fse -> pad == IMAGE_PAD ) {
1472
- const struct imx477_mode * mode_list ;
1473
- unsigned int num_modes ;
1474
-
1475
- get_mode_table (fse -> code , & mode_list , & num_modes );
1476
-
1477
- if (fse -> index >= num_modes )
1437
+ if (fse -> index >= ARRAY_SIZE (supported_modes ))
1478
1438
return - EINVAL ;
1479
1439
1480
1440
if (fse -> code != imx477_get_format_code (imx477 , fse -> code ))
1481
1441
return - EINVAL ;
1482
1442
1483
- fse -> min_width = mode_list [fse -> index ].width ;
1443
+ fse -> min_width = supported_modes [fse -> index ].width ;
1484
1444
fse -> max_width = fse -> min_width ;
1485
- fse -> min_height = mode_list [fse -> index ].height ;
1445
+ fse -> min_height = supported_modes [fse -> index ].height ;
1486
1446
fse -> max_height = fse -> min_height ;
1487
1447
} else {
1488
1448
if (fse -> code != MEDIA_BUS_FMT_SENSOR_DATA || fse -> index > 0 )
@@ -1560,44 +1520,36 @@ static int imx477_get_pad_format(struct v4l2_subdev *sd,
1560
1520
return 0 ;
1561
1521
}
1562
1522
1563
- static
1564
- unsigned int imx477_get_frame_length (const struct imx477_mode * mode ,
1565
- unsigned int framerate_default )
1566
- {
1567
- u64 frame_length ;
1568
-
1569
- frame_length = IMX477_PIXEL_RATE ;
1570
- do_div (frame_length ,
1571
- (u64 )framerate_default * mode -> line_length_pix );
1572
-
1573
- if (WARN_ON (frame_length > IMX477_FRAME_LENGTH_MAX ))
1574
- frame_length = IMX477_FRAME_LENGTH_MAX ;
1575
-
1576
- return max_t (unsigned int , frame_length , mode -> height );
1577
- }
1578
-
1579
1523
static void imx477_set_framing_limits (struct imx477 * imx477 )
1580
1524
{
1581
- unsigned int frm_length_default , hblank_min ;
1525
+ unsigned int hblank_min ;
1582
1526
const struct imx477_mode * mode = imx477 -> mode ;
1583
1527
unsigned int line_length_pix ;
1584
1528
1585
- frm_length_default =
1586
- imx477_get_frame_length (mode , mode -> framerate_default );
1587
-
1588
1529
/* Default to no long exposure multiplier. */
1589
1530
imx477 -> long_exp_shift = 0 ;
1590
1531
1591
1532
/* Update limits and set FPS to default */
1592
1533
__v4l2_ctrl_modify_range (imx477 -> vblank , 1 ,
1593
1534
((1 << IMX477_LONG_EXP_SHIFT_MAX ) *
1594
1535
IMX477_FRAME_LENGTH_MAX ) - mode -> height ,
1595
- IMX477_VBLANK_MIN , frm_length_default - mode -> height );
1596
-
1597
- /* Setting this will adjust the exposure limits as well. */
1598
- __v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
1536
+ IMX477_VBLANK_MIN , IMX477_VBLANK_MIN );
1599
1537
1600
- line_length_pix = mode -> line_length_pix ;
1538
+ switch (imx477 -> fmt_code ) {
1539
+ case MEDIA_BUS_FMT_SRGGB12_1X12 :
1540
+ case MEDIA_BUS_FMT_SGRBG12_1X12 :
1541
+ case MEDIA_BUS_FMT_SGBRG12_1X12 :
1542
+ case MEDIA_BUS_FMT_SBGGR12_1X12 :
1543
+ line_length_pix = mode -> line_length_pix [0 ];
1544
+ break ;
1545
+ /* 10-bit */
1546
+ case MEDIA_BUS_FMT_SRGGB10_1X10 :
1547
+ case MEDIA_BUS_FMT_SGRBG10_1X10 :
1548
+ case MEDIA_BUS_FMT_SGBRG10_1X10 :
1549
+ case MEDIA_BUS_FMT_SBGGR10_1X10 :
1550
+ line_length_pix = mode -> line_length_pix [1 ];
1551
+ break ;
1552
+ }
1601
1553
if (imx477 -> double_link_freq )
1602
1554
line_length_pix /= 2 ;
1603
1555
hblank_min = line_length_pix - mode -> width ;
@@ -1620,17 +1572,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
1620
1572
mutex_lock (& imx477 -> mutex );
1621
1573
1622
1574
if (fmt -> pad == IMAGE_PAD ) {
1623
- const struct imx477_mode * mode_list ;
1624
- unsigned int num_modes ;
1625
-
1626
1575
/* Bayer order varies with flips */
1627
1576
fmt -> format .code = imx477_get_format_code (imx477 ,
1628
1577
fmt -> format .code );
1629
1578
1630
- get_mode_table (fmt -> format .code , & mode_list , & num_modes );
1631
-
1632
- mode = v4l2_find_nearest_size (mode_list ,
1633
- num_modes ,
1579
+ mode = v4l2_find_nearest_size (supported_modes ,
1580
+ ARRAY_SIZE (supported_modes ),
1634
1581
width , height ,
1635
1582
fmt -> format .width ,
1636
1583
fmt -> format .height );
@@ -1639,7 +1586,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
1639
1586
framefmt = v4l2_subdev_state_get_format (sd_state ,
1640
1587
fmt -> pad );
1641
1588
* framefmt = fmt -> format ;
1642
- } else if (imx477 -> mode != mode ) {
1589
+ } else if (imx477 -> mode != mode ||
1590
+ fmt -> format .code != imx477 -> fmt_code ) {
1643
1591
imx477 -> mode = mode ;
1644
1592
imx477 -> fmt_code = fmt -> format .code ;
1645
1593
imx477_set_framing_limits (imx477 );
@@ -1718,7 +1666,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
1718
1666
struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
1719
1667
const struct imx477_reg_list * reg_list , * freq_regs ;
1720
1668
const struct imx477_reg_list * extra_regs ;
1721
- int ret , tm ;
1669
+ int ret , tm , val ;
1722
1670
1723
1671
if (!imx477 -> common_regs_written ) {
1724
1672
ret = imx477_write_regs (imx477 , mode_common_regs ,
@@ -1762,6 +1710,28 @@ static int imx477_start_streaming(struct imx477 *imx477)
1762
1710
return ret ;
1763
1711
}
1764
1712
1713
+ switch (imx477 -> fmt_code ) {
1714
+ case MEDIA_BUS_FMT_SRGGB12_1X12 :
1715
+ case MEDIA_BUS_FMT_SGRBG12_1X12 :
1716
+ case MEDIA_BUS_FMT_SGBRG12_1X12 :
1717
+ case MEDIA_BUS_FMT_SBGGR12_1X12 :
1718
+ val = 0x0c ;
1719
+ break ;
1720
+ /* 10-bit */
1721
+ case MEDIA_BUS_FMT_SRGGB10_1X10 :
1722
+ case MEDIA_BUS_FMT_SGRBG10_1X10 :
1723
+ case MEDIA_BUS_FMT_SGBRG10_1X10 :
1724
+ case MEDIA_BUS_FMT_SBGGR10_1X10 :
1725
+ val = 0x0a ;
1726
+ break ;
1727
+ }
1728
+ imx477_write_reg (imx477 , IMX477_REG_CSI_DT_FMT_H ,
1729
+ IMX477_REG_VALUE_08BIT , val );
1730
+ imx477_write_reg (imx477 , IMX477_REG_CSI_DT_FMT_L ,
1731
+ IMX477_REG_VALUE_08BIT , val );
1732
+ imx477_write_reg (imx477 , IMX477_REG_IOP_PXCK_DIV ,
1733
+ IMX477_REG_VALUE_08BIT , val );
1734
+
1765
1735
/* Set on-sensor DPC. */
1766
1736
imx477_write_reg (imx477 , 0x0b05 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
1767
1737
imx477_write_reg (imx477 , 0x0b06 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
0 commit comments