@@ -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 ;
@@ -569,8 +576,6 @@ static const struct imx477_reg mode_common_regs[] = {
569
576
570
577
/* 12 mpix 10fps */
571
578
static const struct imx477_reg mode_4056x3040_regs [] = {
572
- {0x0112 , 0x0c },
573
- {0x0113 , 0x0c },
574
579
{0x0344 , 0x00 },
575
580
{0x0345 , 0x00 },
576
581
{0x0346 , 0x00 },
@@ -625,7 +630,6 @@ static const struct imx477_reg mode_4056x3040_regs[] = {
625
630
{0x0305 , 0x04 },
626
631
{0x0306 , 0x01 },
627
632
{0x0307 , 0x5e },
628
- {0x0309 , 0x0c },
629
633
{0xe04c , 0x00 },
630
634
{0xe04d , 0x7f },
631
635
{0xe04e , 0x00 },
@@ -700,8 +704,6 @@ static const struct imx477_reg mode_4056x2160_regs[] = {
700
704
701
705
/* 2x2 binned. 40fps */
702
706
static const struct imx477_reg mode_2028x1520_regs [] = {
703
- {0x0112 , 0x0c },
704
- {0x0113 , 0x0c },
705
707
{0x0344 , 0x00 },
706
708
{0x0345 , 0x00 },
707
709
{0x0346 , 0x00 },
@@ -745,7 +747,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
745
747
{0x0305 , 0x04 },
746
748
{0x0306 , 0x01 },
747
749
{0x0307 , 0x5e },
748
- {0x0309 , 0x0c },
749
750
{0xe04c , 0x00 },
750
751
{0xe04d , 0x7f },
751
752
{0xe04e , 0x00 },
@@ -756,8 +757,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
756
757
757
758
/* 1080p cropped mode */
758
759
static const struct imx477_reg mode_2028x1080_regs [] = {
759
- {0x0112 , 0x0c },
760
- {0x0113 , 0x0c },
761
760
{0x0344 , 0x00 },
762
761
{0x0345 , 0x00 },
763
762
{0x0346 , 0x01 },
@@ -801,7 +800,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
801
800
{0x0305 , 0x04 },
802
801
{0x0306 , 0x01 },
803
802
{0x0307 , 0x5e },
804
- {0x0309 , 0x0c },
805
803
{0xe04c , 0x00 },
806
804
{0xe04d , 0x7f },
807
805
{0xe04e , 0x00 },
@@ -812,8 +810,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
812
810
813
811
/* 4x4 binned. 120fps */
814
812
static const struct imx477_reg mode_1332x990_regs [] = {
815
- {0x0112 , 0x0a },
816
- {0x0113 , 0x0a },
817
813
{0x420b , 0x01 },
818
814
{0x990c , 0x00 },
819
815
{0x990d , 0x08 },
@@ -881,7 +877,6 @@ static const struct imx477_reg mode_1332x990_regs[] = {
881
877
{0x0305 , 0x02 },
882
878
{0x0306 , 0x00 },
883
879
{0x0307 , 0xaf },
884
- {0x0309 , 0x0a },
885
880
{0xe04c , 0x00 },
886
881
{0xe04d , 0x5f },
887
882
{0xe04e , 0x00 },
@@ -891,12 +886,12 @@ static const struct imx477_reg mode_1332x990_regs[] = {
891
886
};
892
887
893
888
/* Mode configs */
894
- static const struct imx477_mode supported_modes_12bit [] = {
889
+ static const struct imx477_mode supported_modes [] = {
895
890
{
896
891
/* 12MPix 10fps mode */
897
892
.width = 4056 ,
898
893
.height = 3040 ,
899
- .line_length_pix = 24000 ,
894
+ .line_length_pix = { 24000 , 20000 } ,
900
895
.crop = {
901
896
.left = IMX477_PIXEL_ARRAY_LEFT ,
902
897
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -930,7 +925,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
930
925
/* 2x2 binned 40fps mode */
931
926
.width = 2028 ,
932
927
.height = 1520 ,
933
- .line_length_pix = 12740 ,
928
+ .line_length_pix = { 12740 , 10616 } ,
934
929
.crop = {
935
930
.left = IMX477_PIXEL_ARRAY_LEFT ,
936
931
.top = IMX477_PIXEL_ARRAY_TOP ,
@@ -947,7 +942,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
947
942
/* 1080p 50fps cropped mode */
948
943
.width = 2028 ,
949
944
.height = 1080 ,
950
- .line_length_pix = 12740 ,
945
+ .line_length_pix = { 12740 , 10616 } ,
951
946
.crop = {
952
947
.left = IMX477_PIXEL_ARRAY_LEFT ,
953
948
.top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -959,15 +954,12 @@ static const struct imx477_mode supported_modes_12bit[] = {
959
954
.num_of_regs = ARRAY_SIZE (mode_2028x1080_regs ),
960
955
.regs = mode_2028x1080_regs ,
961
956
},
962
- }
963
- };
964
-
965
- static const struct imx477_mode supported_modes_10bit [] = {
957
+ },
966
958
{
967
959
/* 120fps. 2x2 binned and cropped */
968
960
.width = 1332 ,
969
961
.height = 990 ,
970
- .line_length_pix = 6664 ,
962
+ .line_length_pix = { 7997 , 6664 } ,
971
963
.crop = {
972
964
/*
973
965
* FIXME: the analog crop rectangle is actually
@@ -1119,33 +1111,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
1119
1111
return container_of (_sd , struct imx477 , sd );
1120
1112
}
1121
1113
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
-
1149
1114
/* Read registers up to 2 at a time */
1150
1115
static int imx477_read_reg (struct imx477 * imx477 , u16 reg , u32 len , u32 * val )
1151
1116
{
@@ -1241,7 +1206,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
1241
1206
static void imx477_set_default_format (struct imx477 * imx477 )
1242
1207
{
1243
1208
/* Set default mode to max resolution */
1244
- imx477 -> mode = & supported_modes_12bit [0 ];
1209
+ imx477 -> mode = & supported_modes [0 ];
1245
1210
imx477 -> fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12 ;
1246
1211
}
1247
1212
@@ -1257,8 +1222,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
1257
1222
mutex_lock (& imx477 -> mutex );
1258
1223
1259
1224
/* 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 ;
1262
1227
try_fmt_img -> code = imx477_get_format_code (imx477 ,
1263
1228
MEDIA_BUS_FMT_SRGGB12_1X12 );
1264
1229
try_fmt_img -> field = V4L2_FIELD_NONE ;
@@ -1436,20 +1401,15 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
1436
1401
return - EINVAL ;
1437
1402
1438
1403
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 ))
1445
1405
return - EINVAL ;
1446
1406
1447
1407
if (fse -> code != imx477_get_format_code (imx477 , fse -> code ))
1448
1408
return - EINVAL ;
1449
1409
1450
- fse -> min_width = mode_list [fse -> index ].width ;
1410
+ fse -> min_width = supported_modes [fse -> index ].width ;
1451
1411
fse -> max_width = fse -> min_width ;
1452
- fse -> min_height = mode_list [fse -> index ].height ;
1412
+ fse -> min_height = supported_modes [fse -> index ].height ;
1453
1413
fse -> max_height = fse -> min_height ;
1454
1414
} else {
1455
1415
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,
1527
1487
return 0 ;
1528
1488
}
1529
1489
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
-
1546
1490
static void imx477_set_framing_limits (struct imx477 * imx477 )
1547
1491
{
1548
- unsigned int frm_length_default , hblank_min ;
1492
+ unsigned int hblank_min ;
1549
1493
const struct imx477_mode * mode = imx477 -> mode ;
1550
1494
unsigned int line_length_pix ;
1551
1495
1552
- frm_length_default =
1553
- imx477_get_frame_length (mode , mode -> framerate_default );
1554
-
1555
1496
/* Default to no long exposure multiplier. */
1556
1497
imx477 -> long_exp_shift = 0 ;
1557
1498
1558
1499
/* Update limits and set FPS to default */
1559
1500
__v4l2_ctrl_modify_range (imx477 -> vblank , 1 ,
1560
1501
((1 << IMX477_LONG_EXP_SHIFT_MAX ) *
1561
1502
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 );
1566
1504
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
+ }
1568
1520
if (imx477 -> double_link_freq )
1569
1521
line_length_pix /= 2 ;
1570
1522
hblank_min = line_length_pix - mode -> width ;
@@ -1587,17 +1539,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
1587
1539
mutex_lock (& imx477 -> mutex );
1588
1540
1589
1541
if (fmt -> pad == IMAGE_PAD ) {
1590
- const struct imx477_mode * mode_list ;
1591
- unsigned int num_modes ;
1592
-
1593
1542
/* Bayer order varies with flips */
1594
1543
fmt -> format .code = imx477_get_format_code (imx477 ,
1595
1544
fmt -> format .code );
1596
1545
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 ),
1601
1548
width , height ,
1602
1549
fmt -> format .width ,
1603
1550
fmt -> format .height );
@@ -1606,7 +1553,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
1606
1553
framefmt = v4l2_subdev_get_try_format (sd , sd_state ,
1607
1554
fmt -> pad );
1608
1555
* framefmt = fmt -> format ;
1609
- } else if (imx477 -> mode != mode ) {
1556
+ } else if (imx477 -> mode != mode ||
1557
+ fmt -> format .code != imx477 -> fmt_code ) {
1610
1558
imx477 -> mode = mode ;
1611
1559
imx477 -> fmt_code = fmt -> format .code ;
1612
1560
imx477_set_framing_limits (imx477 );
@@ -1685,7 +1633,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
1685
1633
struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
1686
1634
const struct imx477_reg_list * reg_list , * freq_regs ;
1687
1635
const struct imx477_reg_list * extra_regs ;
1688
- int ret , tm ;
1636
+ int ret , tm , val ;
1689
1637
1690
1638
if (!imx477 -> common_regs_written ) {
1691
1639
ret = imx477_write_regs (imx477 , mode_common_regs ,
@@ -1729,6 +1677,28 @@ static int imx477_start_streaming(struct imx477 *imx477)
1729
1677
return ret ;
1730
1678
}
1731
1679
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
+
1732
1702
/* Set on-sensor DPC. */
1733
1703
imx477_write_reg (imx477 , 0x0b05 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
1734
1704
imx477_write_reg (imx477 , 0x0b06 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
0 commit comments