@@ -43,6 +43,9 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
4343
4444#define IMX477_REG_ORIENTATION 0x101
4545
46+ #define IMX477_REG_CSI_DT_FMT_H 0x0112
47+ #define IMX477_REG_CSI_DT_FMT_L 0x0113
48+
4649#define IMX477_XCLK_FREQ 24000000
4750
4851#define IMX477_DEFAULT_LINK_FREQ 450000000
@@ -86,6 +89,7 @@ MODULE_PARM_DESC(trigger_mode, "Set vsync trigger mode: 1=source, 2=sink");
8689#define IMX477_DGTL_GAIN_DEFAULT 0x0100
8790#define IMX477_DGTL_GAIN_STEP 1
8891
92+ #define IMX477_REG_IOP_PXCK_DIV 0x0309
8993#define IMX477_REG_DIV_IOP_PX 0x030b
9094
9195/* Test Pattern Control */
@@ -153,8 +157,11 @@ struct imx477_mode {
153157 /* Frame height */
154158 unsigned int height ;
155159
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 ];
158165
159166 /* Analog crop rectangle. */
160167 struct v4l2_rect crop ;
@@ -602,8 +609,6 @@ static const struct imx477_reg mode_common_regs[] = {
602609
603610/* 12 mpix 10fps */
604611static const struct imx477_reg mode_4056x3040_regs [] = {
605- {0x0112 , 0x0c },
606- {0x0113 , 0x0c },
607612 {0x0344 , 0x00 },
608613 {0x0345 , 0x00 },
609614 {0x0346 , 0x00 },
@@ -658,7 +663,6 @@ static const struct imx477_reg mode_4056x3040_regs[] = {
658663 {0x0305 , 0x04 },
659664 {0x0306 , 0x01 },
660665 {0x0307 , 0x5e },
661- {0x0309 , 0x0c },
662666 {0xe04c , 0x00 },
663667 {0xe04d , 0x7f },
664668 {0xe04e , 0x00 },
@@ -733,8 +737,6 @@ static const struct imx477_reg mode_4056x2160_regs[] = {
733737
734738/* 2x2 binned. 40fps */
735739static const struct imx477_reg mode_2028x1520_regs [] = {
736- {0x0112 , 0x0c },
737- {0x0113 , 0x0c },
738740 {0x0344 , 0x00 },
739741 {0x0345 , 0x00 },
740742 {0x0346 , 0x00 },
@@ -778,7 +780,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
778780 {0x0305 , 0x04 },
779781 {0x0306 , 0x01 },
780782 {0x0307 , 0x5e },
781- {0x0309 , 0x0c },
782783 {0xe04c , 0x00 },
783784 {0xe04d , 0x7f },
784785 {0xe04e , 0x00 },
@@ -789,8 +790,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
789790
790791/* 1080p cropped mode */
791792static const struct imx477_reg mode_2028x1080_regs [] = {
792- {0x0112 , 0x0c },
793- {0x0113 , 0x0c },
794793 {0x0344 , 0x00 },
795794 {0x0345 , 0x00 },
796795 {0x0346 , 0x01 },
@@ -834,7 +833,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
834833 {0x0305 , 0x04 },
835834 {0x0306 , 0x01 },
836835 {0x0307 , 0x5e },
837- {0x0309 , 0x0c },
838836 {0xe04c , 0x00 },
839837 {0xe04d , 0x7f },
840838 {0xe04e , 0x00 },
@@ -845,8 +843,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
845843
846844/* 4x4 binned. 120fps */
847845static const struct imx477_reg mode_1332x990_regs [] = {
848- {0x0112 , 0x0a },
849- {0x0113 , 0x0a },
850846 {0x420b , 0x01 },
851847 {0x990c , 0x00 },
852848 {0x990d , 0x08 },
@@ -914,7 +910,6 @@ static const struct imx477_reg mode_1332x990_regs[] = {
914910 {0x0305 , 0x02 },
915911 {0x0306 , 0x00 },
916912 {0x0307 , 0xaf },
917- {0x0309 , 0x0a },
918913 {0xe04c , 0x00 },
919914 {0xe04d , 0x5f },
920915 {0xe04e , 0x00 },
@@ -924,12 +919,12 @@ static const struct imx477_reg mode_1332x990_regs[] = {
924919};
925920
926921/* Mode configs */
927- static const struct imx477_mode supported_modes_12bit [] = {
922+ static const struct imx477_mode supported_modes [] = {
928923 {
929924 /* 12MPix 10fps mode */
930925 .width = 4056 ,
931926 .height = 3040 ,
932- .line_length_pix = 24000 ,
927+ .line_length_pix = { 24000 , 20000 } ,
933928 .crop = {
934929 .left = IMX477_PIXEL_ARRAY_LEFT ,
935930 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -963,7 +958,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
963958 /* 2x2 binned 40fps mode */
964959 .width = 2028 ,
965960 .height = 1520 ,
966- .line_length_pix = 12740 ,
961+ .line_length_pix = { 12740 , 10616 } ,
967962 .crop = {
968963 .left = IMX477_PIXEL_ARRAY_LEFT ,
969964 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -980,7 +975,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
980975 /* 1080p 50fps cropped mode */
981976 .width = 2028 ,
982977 .height = 1080 ,
983- .line_length_pix = 12740 ,
978+ .line_length_pix = { 12740 , 10616 } ,
984979 .crop = {
985980 .left = IMX477_PIXEL_ARRAY_LEFT ,
986981 .top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -992,15 +987,12 @@ static const struct imx477_mode supported_modes_12bit[] = {
992987 .num_of_regs = ARRAY_SIZE (mode_2028x1080_regs ),
993988 .regs = mode_2028x1080_regs ,
994989 },
995- }
996- };
997-
998- static const struct imx477_mode supported_modes_10bit [] = {
990+ },
999991 {
1000992 /* 120fps. 2x2 binned and cropped */
1001993 .width = 1332 ,
1002994 .height = 990 ,
1003- .line_length_pix = 6664 ,
995+ .line_length_pix = { 7997 , 6664 } ,
1004996 .crop = {
1005997 /*
1006998 * FIXME: the analog crop rectangle is actually
@@ -1152,33 +1144,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
11521144 return container_of (_sd , struct imx477 , sd );
11531145}
11541146
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-
11821147/* Read registers up to 2 at a time */
11831148static int imx477_read_reg (struct imx477 * imx477 , u16 reg , u32 len , u32 * val )
11841149{
@@ -1274,7 +1239,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
12741239static void imx477_set_default_format (struct imx477 * imx477 )
12751240{
12761241 /* Set default mode to max resolution */
1277- imx477 -> mode = & supported_modes_12bit [0 ];
1242+ imx477 -> mode = & supported_modes [0 ];
12781243 imx477 -> fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12 ;
12791244}
12801245
@@ -1290,8 +1255,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
12901255 mutex_lock (& imx477 -> mutex );
12911256
12921257 /* 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 ;
12951260 try_fmt_img -> code = imx477_get_format_code (imx477 ,
12961261 MEDIA_BUS_FMT_SRGGB12_1X12 );
12971262 try_fmt_img -> field = V4L2_FIELD_NONE ;
@@ -1469,20 +1434,15 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
14691434 return - EINVAL ;
14701435
14711436 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 ))
14781438 return - EINVAL ;
14791439
14801440 if (fse -> code != imx477_get_format_code (imx477 , fse -> code ))
14811441 return - EINVAL ;
14821442
1483- fse -> min_width = mode_list [fse -> index ].width ;
1443+ fse -> min_width = supported_modes [fse -> index ].width ;
14841444 fse -> max_width = fse -> min_width ;
1485- fse -> min_height = mode_list [fse -> index ].height ;
1445+ fse -> min_height = supported_modes [fse -> index ].height ;
14861446 fse -> max_height = fse -> min_height ;
14871447 } else {
14881448 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,
15601520 return 0 ;
15611521}
15621522
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-
15791523static void imx477_set_framing_limits (struct imx477 * imx477 )
15801524{
1581- unsigned int frm_length_default , hblank_min ;
1525+ unsigned int hblank_min ;
15821526 const struct imx477_mode * mode = imx477 -> mode ;
15831527 unsigned int line_length_pix ;
15841528
1585- frm_length_default =
1586- imx477_get_frame_length (mode , mode -> framerate_default );
1587-
15881529 /* Default to no long exposure multiplier. */
15891530 imx477 -> long_exp_shift = 0 ;
15901531
15911532 /* Update limits and set FPS to default */
15921533 __v4l2_ctrl_modify_range (imx477 -> vblank , 1 ,
15931534 ((1 << IMX477_LONG_EXP_SHIFT_MAX ) *
15941535 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 );
15991537
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+ }
16011553 if (imx477 -> double_link_freq )
16021554 line_length_pix /= 2 ;
16031555 hblank_min = line_length_pix - mode -> width ;
@@ -1620,17 +1572,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
16201572 mutex_lock (& imx477 -> mutex );
16211573
16221574 if (fmt -> pad == IMAGE_PAD ) {
1623- const struct imx477_mode * mode_list ;
1624- unsigned int num_modes ;
1625-
16261575 /* Bayer order varies with flips */
16271576 fmt -> format .code = imx477_get_format_code (imx477 ,
16281577 fmt -> format .code );
16291578
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 ),
16341581 width , height ,
16351582 fmt -> format .width ,
16361583 fmt -> format .height );
@@ -1639,7 +1586,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
16391586 framefmt = v4l2_subdev_state_get_format (sd_state ,
16401587 fmt -> pad );
16411588 * framefmt = fmt -> format ;
1642- } else if (imx477 -> mode != mode ) {
1589+ } else if (imx477 -> mode != mode ||
1590+ fmt -> format .code != imx477 -> fmt_code ) {
16431591 imx477 -> mode = mode ;
16441592 imx477 -> fmt_code = fmt -> format .code ;
16451593 imx477_set_framing_limits (imx477 );
@@ -1718,7 +1666,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
17181666 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
17191667 const struct imx477_reg_list * reg_list , * freq_regs ;
17201668 const struct imx477_reg_list * extra_regs ;
1721- int ret , tm ;
1669+ int ret , tm , val ;
17221670
17231671 if (!imx477 -> common_regs_written ) {
17241672 ret = imx477_write_regs (imx477 , mode_common_regs ,
@@ -1762,6 +1710,28 @@ static int imx477_start_streaming(struct imx477 *imx477)
17621710 return ret ;
17631711 }
17641712
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+
17651735 /* Set on-sensor DPC. */
17661736 imx477_write_reg (imx477 , 0x0b05 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
17671737 imx477_write_reg (imx477 , 0x0b06 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
0 commit comments