@@ -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 */
@@ -156,8 +160,11 @@ struct imx477_mode {
156
160
/* Frame height */
157
161
unsigned int height ;
158
162
159
- /* H-timing in pixels when at 450MHz link freq */
160
- unsigned int line_length_pix ;
163
+ /*
164
+ * H-timing in pixels when at 450MHz link freq
165
+ * Index 0 is for 12bpp. Index 1 is for 10bpp.
166
+ */
167
+ unsigned int line_length_pix [2 ];
161
168
162
169
/* Analog crop rectangle. */
163
170
struct v4l2_rect crop ;
@@ -605,8 +612,6 @@ static const struct imx477_reg mode_common_regs[] = {
605
612
606
613
/* 12 mpix 10fps */
607
614
static const struct imx477_reg mode_4056x3040_regs [] = {
608
- {0x0112 , 0x0c },
609
- {0x0113 , 0x0c },
610
615
{0x0344 , 0x00 },
611
616
{0x0345 , 0x00 },
612
617
{0x0346 , 0x00 },
@@ -661,7 +666,6 @@ static const struct imx477_reg mode_4056x3040_regs[] = {
661
666
{0x0305 , 0x04 },
662
667
{0x0306 , 0x01 },
663
668
{0x0307 , 0x5e },
664
- {0x0309 , 0x0c },
665
669
{0xe04c , 0x00 },
666
670
{0xe04d , 0x7f },
667
671
{0xe04e , 0x00 },
@@ -736,8 +740,6 @@ static const struct imx477_reg mode_4056x2160_regs[] = {
736
740
737
741
/* 2x2 binned. 40fps */
738
742
static const struct imx477_reg mode_2028x1520_regs [] = {
739
- {0x0112 , 0x0c },
740
- {0x0113 , 0x0c },
741
743
{0x0344 , 0x00 },
742
744
{0x0345 , 0x00 },
743
745
{0x0346 , 0x00 },
@@ -781,7 +783,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
781
783
{0x0305 , 0x04 },
782
784
{0x0306 , 0x01 },
783
785
{0x0307 , 0x5e },
784
- {0x0309 , 0x0c },
785
786
{0xe04c , 0x00 },
786
787
{0xe04d , 0x7f },
787
788
{0xe04e , 0x00 },
@@ -792,8 +793,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
792
793
793
794
/* 1080p cropped mode */
794
795
static const struct imx477_reg mode_2028x1080_regs [] = {
795
- {0x0112 , 0x0c },
796
- {0x0113 , 0x0c },
797
796
{0x0344 , 0x00 },
798
797
{0x0345 , 0x00 },
799
798
{0x0346 , 0x01 },
@@ -837,7 +836,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
837
836
{0x0305 , 0x04 },
838
837
{0x0306 , 0x01 },
839
838
{0x0307 , 0x5e },
840
- {0x0309 , 0x0c },
841
839
{0xe04c , 0x00 },
842
840
{0xe04d , 0x7f },
843
841
{0xe04e , 0x00 },
@@ -848,8 +846,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
848
846
849
847
/* 4x4 binned. 120fps */
850
848
static const struct imx477_reg mode_1332x990_regs [] = {
851
- {0x0112 , 0x0a },
852
- {0x0113 , 0x0a },
853
849
{0x420b , 0x01 },
854
850
{0x990c , 0x00 },
855
851
{0x990d , 0x08 },
@@ -917,7 +913,6 @@ static const struct imx477_reg mode_1332x990_regs[] = {
917
913
{0x0305 , 0x02 },
918
914
{0x0306 , 0x00 },
919
915
{0x0307 , 0xaf },
920
- {0x0309 , 0x0a },
921
916
{0xe04c , 0x00 },
922
917
{0xe04d , 0x5f },
923
918
{0xe04e , 0x00 },
@@ -927,12 +922,12 @@ static const struct imx477_reg mode_1332x990_regs[] = {
927
922
};
928
923
929
924
/* Mode configs */
930
- static const struct imx477_mode supported_modes_12bit [] = {
925
+ static const struct imx477_mode supported_modes [] = {
931
926
{
932
927
/* 12MPix 10fps mode */
933
928
.width = 4056 ,
934
929
.height = 3040 ,
935
- .line_length_pix = 24000 ,
930
+ .line_length_pix = { 24000 , 20000 } ,
936
931
.crop = {
937
932
.left = IMX477_PIXEL_ARRAY_LEFT ,
938
933
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -966,7 +961,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
966
961
/* 2x2 binned 40fps mode */
967
962
.width = 2028 ,
968
963
.height = 1520 ,
969
- .line_length_pix = 12740 ,
964
+ .line_length_pix = { 12740 , 10616 } ,
970
965
.crop = {
971
966
.left = IMX477_PIXEL_ARRAY_LEFT ,
972
967
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -983,7 +978,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
983
978
/* 1080p 50fps cropped mode */
984
979
.width = 2028 ,
985
980
.height = 1080 ,
986
- .line_length_pix = 12740 ,
981
+ .line_length_pix = { 12740 , 10616 } ,
987
982
.crop = {
988
983
.left = IMX477_PIXEL_ARRAY_LEFT ,
989
984
.top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -995,15 +990,12 @@ static const struct imx477_mode supported_modes_12bit[] = {
995
990
.num_of_regs = ARRAY_SIZE (mode_2028x1080_regs ),
996
991
.regs = mode_2028x1080_regs ,
997
992
},
998
- }
999
- };
1000
-
1001
- static const struct imx477_mode supported_modes_10bit [] = {
993
+ },
1002
994
{
1003
995
/* 120fps. 2x2 binned and cropped */
1004
996
.width = 1332 ,
1005
997
.height = 990 ,
1006
- .line_length_pix = 6664 ,
998
+ .line_length_pix = { 7997 , 6664 } ,
1007
999
.crop = {
1008
1000
/*
1009
1001
* FIXME: the analog crop rectangle is actually
@@ -1155,33 +1147,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
1155
1147
return container_of (_sd , struct imx477 , sd );
1156
1148
}
1157
1149
1158
- static inline void get_mode_table (unsigned int code ,
1159
- const struct imx477_mode * * mode_list ,
1160
- unsigned int * num_modes )
1161
- {
1162
- switch (code ) {
1163
- /* 12-bit */
1164
- case MEDIA_BUS_FMT_SRGGB12_1X12 :
1165
- case MEDIA_BUS_FMT_SGRBG12_1X12 :
1166
- case MEDIA_BUS_FMT_SGBRG12_1X12 :
1167
- case MEDIA_BUS_FMT_SBGGR12_1X12 :
1168
- * mode_list = supported_modes_12bit ;
1169
- * num_modes = ARRAY_SIZE (supported_modes_12bit );
1170
- break ;
1171
- /* 10-bit */
1172
- case MEDIA_BUS_FMT_SRGGB10_1X10 :
1173
- case MEDIA_BUS_FMT_SGRBG10_1X10 :
1174
- case MEDIA_BUS_FMT_SGBRG10_1X10 :
1175
- case MEDIA_BUS_FMT_SBGGR10_1X10 :
1176
- * mode_list = supported_modes_10bit ;
1177
- * num_modes = ARRAY_SIZE (supported_modes_10bit );
1178
- break ;
1179
- default :
1180
- * mode_list = NULL ;
1181
- * num_modes = 0 ;
1182
- }
1183
- }
1184
-
1185
1150
/* Read registers up to 2 at a time */
1186
1151
static int imx477_read_reg (struct imx477 * imx477 , u16 reg , u32 len , u32 * val )
1187
1152
{
@@ -1277,7 +1242,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
1277
1242
static void imx477_set_default_format (struct imx477 * imx477 )
1278
1243
{
1279
1244
/* Set default mode to max resolution */
1280
- imx477 -> mode = & supported_modes_12bit [0 ];
1245
+ imx477 -> mode = & supported_modes [0 ];
1281
1246
imx477 -> fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12 ;
1282
1247
}
1283
1248
@@ -1293,8 +1258,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1293
1258
mutex_lock (& imx477 -> mutex );
1294
1259
1295
1260
/* Initialize try_fmt for the image pad */
1296
- try_fmt_img -> width = supported_modes_12bit [0 ].width ;
1297
- try_fmt_img -> height = supported_modes_12bit [0 ].height ;
1261
+ try_fmt_img -> width = supported_modes [0 ].width ;
1262
+ try_fmt_img -> height = supported_modes [0 ].height ;
1298
1263
try_fmt_img -> code = imx477_get_format_code (imx477 ,
1299
1264
MEDIA_BUS_FMT_SRGGB12_1X12 );
1300
1265
try_fmt_img -> field = V4L2_FIELD_NONE ;
@@ -1475,12 +1440,7 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
1475
1440
return - EINVAL ;
1476
1441
1477
1442
if (fse -> pad == IMAGE_PAD ) {
1478
- const struct imx477_mode * mode_list ;
1479
- unsigned int num_modes ;
1480
-
1481
- get_mode_table (fse -> code , & mode_list , & num_modes );
1482
-
1483
- if (fse -> index >= num_modes )
1443
+ if (fse -> index >= ARRAY_SIZE (supported_modes ))
1484
1444
return - EINVAL ;
1485
1445
1486
1446
mutex_lock (& imx477 -> mutex );
@@ -1490,9 +1450,9 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
1490
1450
if (fse -> code != code )
1491
1451
return - EINVAL ;
1492
1452
1493
- fse -> min_width = mode_list [fse -> index ].width ;
1453
+ fse -> min_width = supported_modes [fse -> index ].width ;
1494
1454
fse -> max_width = fse -> min_width ;
1495
- fse -> min_height = mode_list [fse -> index ].height ;
1455
+ fse -> min_height = supported_modes [fse -> index ].height ;
1496
1456
fse -> max_height = fse -> min_height ;
1497
1457
} else {
1498
1458
if (fse -> code != MEDIA_BUS_FMT_SENSOR_DATA || fse -> index > 0 )
@@ -1570,44 +1530,36 @@ static int imx477_get_pad_format(struct v4l2_subdev *sd,
1570
1530
return 0 ;
1571
1531
}
1572
1532
1573
- static
1574
- unsigned int imx477_get_frame_length (const struct imx477_mode * mode ,
1575
- unsigned int framerate_default )
1576
- {
1577
- u64 frame_length ;
1578
-
1579
- frame_length = IMX477_PIXEL_RATE ;
1580
- do_div (frame_length ,
1581
- (u64 )framerate_default * mode -> line_length_pix );
1582
-
1583
- if (WARN_ON (frame_length > IMX477_FRAME_LENGTH_MAX ))
1584
- frame_length = IMX477_FRAME_LENGTH_MAX ;
1585
-
1586
- return max_t (unsigned int , frame_length , mode -> height );
1587
- }
1588
-
1589
1533
static void imx477_set_framing_limits (struct imx477 * imx477 )
1590
1534
{
1591
- unsigned int frm_length_default , hblank_min ;
1535
+ unsigned int hblank_min ;
1592
1536
const struct imx477_mode * mode = imx477 -> mode ;
1593
1537
unsigned int line_length_pix ;
1594
1538
1595
- frm_length_default =
1596
- imx477_get_frame_length (mode , mode -> framerate_default );
1597
-
1598
1539
/* Default to no long exposure multiplier. */
1599
1540
imx477 -> long_exp_shift = 0 ;
1600
1541
1601
1542
/* Update limits and set FPS to default */
1602
1543
__v4l2_ctrl_modify_range (imx477 -> vblank , 1 ,
1603
1544
((1 << IMX477_LONG_EXP_SHIFT_MAX ) *
1604
1545
IMX477_FRAME_LENGTH_MAX ) - mode -> height ,
1605
- IMX477_VBLANK_MIN , frm_length_default - mode -> height );
1606
-
1607
- /* Setting this will adjust the exposure limits as well. */
1608
- __v4l2_ctrl_s_ctrl (imx477 -> vblank , frm_length_default - mode -> height );
1546
+ IMX477_VBLANK_MIN , IMX477_VBLANK_MIN );
1609
1547
1610
- line_length_pix = mode -> line_length_pix ;
1548
+ switch (imx477 -> fmt_code ) {
1549
+ case MEDIA_BUS_FMT_SRGGB12_1X12 :
1550
+ case MEDIA_BUS_FMT_SGRBG12_1X12 :
1551
+ case MEDIA_BUS_FMT_SGBRG12_1X12 :
1552
+ case MEDIA_BUS_FMT_SBGGR12_1X12 :
1553
+ line_length_pix = mode -> line_length_pix [0 ];
1554
+ break ;
1555
+ /* 10-bit */
1556
+ case MEDIA_BUS_FMT_SRGGB10_1X10 :
1557
+ case MEDIA_BUS_FMT_SGRBG10_1X10 :
1558
+ case MEDIA_BUS_FMT_SGBRG10_1X10 :
1559
+ case MEDIA_BUS_FMT_SBGGR10_1X10 :
1560
+ line_length_pix = mode -> line_length_pix [1 ];
1561
+ break ;
1562
+ }
1611
1563
if (imx477 -> double_link_freq )
1612
1564
line_length_pix /= 2 ;
1613
1565
hblank_min = line_length_pix - mode -> width ;
@@ -1630,17 +1582,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
1630
1582
mutex_lock (& imx477 -> mutex );
1631
1583
1632
1584
if (fmt -> pad == IMAGE_PAD ) {
1633
- const struct imx477_mode * mode_list ;
1634
- unsigned int num_modes ;
1635
-
1636
1585
/* Bayer order varies with flips */
1637
1586
fmt -> format .code = imx477_get_format_code (imx477 ,
1638
1587
fmt -> format .code );
1639
1588
1640
- get_mode_table (fmt -> format .code , & mode_list , & num_modes );
1641
-
1642
- mode = v4l2_find_nearest_size (mode_list ,
1643
- num_modes ,
1589
+ mode = v4l2_find_nearest_size (supported_modes ,
1590
+ ARRAY_SIZE (supported_modes ),
1644
1591
width , height ,
1645
1592
fmt -> format .width ,
1646
1593
fmt -> format .height );
@@ -1649,7 +1596,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
1649
1596
framefmt = v4l2_subdev_state_get_format (sd_state ,
1650
1597
fmt -> pad );
1651
1598
* framefmt = fmt -> format ;
1652
- } else if (imx477 -> mode != mode ) {
1599
+ } else if (imx477 -> mode != mode ||
1600
+ fmt -> format .code != imx477 -> fmt_code ) {
1653
1601
imx477 -> mode = mode ;
1654
1602
imx477 -> fmt_code = fmt -> format .code ;
1655
1603
imx477_set_framing_limits (imx477 );
@@ -1728,7 +1676,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
1728
1676
struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
1729
1677
const struct imx477_reg_list * reg_list , * freq_regs ;
1730
1678
const struct imx477_reg_list * extra_regs ;
1731
- int ret , tm ;
1679
+ int ret , tm , val ;
1732
1680
1733
1681
if (!imx477 -> common_regs_written ) {
1734
1682
ret = imx477_write_regs (imx477 , mode_common_regs ,
@@ -1772,6 +1720,28 @@ static int imx477_start_streaming(struct imx477 *imx477)
1772
1720
return ret ;
1773
1721
}
1774
1722
1723
+ switch (imx477 -> fmt_code ) {
1724
+ case MEDIA_BUS_FMT_SRGGB12_1X12 :
1725
+ case MEDIA_BUS_FMT_SGRBG12_1X12 :
1726
+ case MEDIA_BUS_FMT_SGBRG12_1X12 :
1727
+ case MEDIA_BUS_FMT_SBGGR12_1X12 :
1728
+ val = 0x0c ;
1729
+ break ;
1730
+ /* 10-bit */
1731
+ case MEDIA_BUS_FMT_SRGGB10_1X10 :
1732
+ case MEDIA_BUS_FMT_SGRBG10_1X10 :
1733
+ case MEDIA_BUS_FMT_SGBRG10_1X10 :
1734
+ case MEDIA_BUS_FMT_SBGGR10_1X10 :
1735
+ val = 0x0a ;
1736
+ break ;
1737
+ }
1738
+ imx477_write_reg (imx477 , IMX477_REG_CSI_DT_FMT_H ,
1739
+ IMX477_REG_VALUE_08BIT , val );
1740
+ imx477_write_reg (imx477 , IMX477_REG_CSI_DT_FMT_L ,
1741
+ IMX477_REG_VALUE_08BIT , val );
1742
+ imx477_write_reg (imx477 , IMX477_REG_IOP_PXCK_DIV ,
1743
+ IMX477_REG_VALUE_08BIT , val );
1744
+
1775
1745
/* Set on-sensor DPC. */
1776
1746
imx477_write_reg (imx477 , 0x0b05 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
1777
1747
imx477_write_reg (imx477 , 0x0b06 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
0 commit comments