@@ -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 */
@@ -156,8 +160,11 @@ struct imx477_mode {
156160 /* Frame height */
157161 unsigned int height ;
158162
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 ];
161168
162169 /* Analog crop rectangle. */
163170 struct v4l2_rect crop ;
@@ -605,8 +612,6 @@ static const struct imx477_reg mode_common_regs[] = {
605612
606613/* 12 mpix 10fps */
607614static const struct imx477_reg mode_4056x3040_regs [] = {
608- {0x0112 , 0x0c },
609- {0x0113 , 0x0c },
610615 {0x0344 , 0x00 },
611616 {0x0345 , 0x00 },
612617 {0x0346 , 0x00 },
@@ -661,7 +666,6 @@ static const struct imx477_reg mode_4056x3040_regs[] = {
661666 {0x0305 , 0x04 },
662667 {0x0306 , 0x01 },
663668 {0x0307 , 0x5e },
664- {0x0309 , 0x0c },
665669 {0xe04c , 0x00 },
666670 {0xe04d , 0x7f },
667671 {0xe04e , 0x00 },
@@ -736,8 +740,6 @@ static const struct imx477_reg mode_4056x2160_regs[] = {
736740
737741/* 2x2 binned. 40fps */
738742static const struct imx477_reg mode_2028x1520_regs [] = {
739- {0x0112 , 0x0c },
740- {0x0113 , 0x0c },
741743 {0x0344 , 0x00 },
742744 {0x0345 , 0x00 },
743745 {0x0346 , 0x00 },
@@ -781,7 +783,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
781783 {0x0305 , 0x04 },
782784 {0x0306 , 0x01 },
783785 {0x0307 , 0x5e },
784- {0x0309 , 0x0c },
785786 {0xe04c , 0x00 },
786787 {0xe04d , 0x7f },
787788 {0xe04e , 0x00 },
@@ -792,8 +793,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
792793
793794/* 1080p cropped mode */
794795static const struct imx477_reg mode_2028x1080_regs [] = {
795- {0x0112 , 0x0c },
796- {0x0113 , 0x0c },
797796 {0x0344 , 0x00 },
798797 {0x0345 , 0x00 },
799798 {0x0346 , 0x01 },
@@ -837,7 +836,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
837836 {0x0305 , 0x04 },
838837 {0x0306 , 0x01 },
839838 {0x0307 , 0x5e },
840- {0x0309 , 0x0c },
841839 {0xe04c , 0x00 },
842840 {0xe04d , 0x7f },
843841 {0xe04e , 0x00 },
@@ -848,8 +846,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
848846
849847/* 4x4 binned. 120fps */
850848static const struct imx477_reg mode_1332x990_regs [] = {
851- {0x0112 , 0x0a },
852- {0x0113 , 0x0a },
853849 {0x420b , 0x01 },
854850 {0x990c , 0x00 },
855851 {0x990d , 0x08 },
@@ -917,7 +913,6 @@ static const struct imx477_reg mode_1332x990_regs[] = {
917913 {0x0305 , 0x02 },
918914 {0x0306 , 0x00 },
919915 {0x0307 , 0xaf },
920- {0x0309 , 0x0a },
921916 {0xe04c , 0x00 },
922917 {0xe04d , 0x5f },
923918 {0xe04e , 0x00 },
@@ -927,12 +922,12 @@ static const struct imx477_reg mode_1332x990_regs[] = {
927922};
928923
929924/* Mode configs */
930- static const struct imx477_mode supported_modes_12bit [] = {
925+ static const struct imx477_mode supported_modes [] = {
931926 {
932927 /* 12MPix 10fps mode */
933928 .width = 4056 ,
934929 .height = 3040 ,
935- .line_length_pix = 24000 ,
930+ .line_length_pix = { 24000 , 20000 } ,
936931 .crop = {
937932 .left = IMX477_PIXEL_ARRAY_LEFT ,
938933 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -966,7 +961,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
966961 /* 2x2 binned 40fps mode */
967962 .width = 2028 ,
968963 .height = 1520 ,
969- .line_length_pix = 12740 ,
964+ .line_length_pix = { 12740 , 10616 } ,
970965 .crop = {
971966 .left = IMX477_PIXEL_ARRAY_LEFT ,
972967 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -983,7 +978,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
983978 /* 1080p 50fps cropped mode */
984979 .width = 2028 ,
985980 .height = 1080 ,
986- .line_length_pix = 12740 ,
981+ .line_length_pix = { 12740 , 10616 } ,
987982 .crop = {
988983 .left = IMX477_PIXEL_ARRAY_LEFT ,
989984 .top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -995,15 +990,12 @@ static const struct imx477_mode supported_modes_12bit[] = {
995990 .num_of_regs = ARRAY_SIZE (mode_2028x1080_regs ),
996991 .regs = mode_2028x1080_regs ,
997992 },
998- }
999- };
1000-
1001- static const struct imx477_mode supported_modes_10bit [] = {
993+ },
1002994 {
1003995 /* 120fps. 2x2 binned and cropped */
1004996 .width = 1332 ,
1005997 .height = 990 ,
1006- .line_length_pix = 6664 ,
998+ .line_length_pix = { 7997 , 6664 } ,
1007999 .crop = {
10081000 /*
10091001 * FIXME: the analog crop rectangle is actually
@@ -1155,33 +1147,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
11551147 return container_of (_sd , struct imx477 , sd );
11561148}
11571149
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-
11851150/* Read registers up to 2 at a time */
11861151static int imx477_read_reg (struct imx477 * imx477 , u16 reg , u32 len , u32 * val )
11871152{
@@ -1277,7 +1242,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
12771242static void imx477_set_default_format (struct imx477 * imx477 )
12781243{
12791244 /* Set default mode to max resolution */
1280- imx477 -> mode = & supported_modes_12bit [0 ];
1245+ imx477 -> mode = & supported_modes [0 ];
12811246 imx477 -> fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12 ;
12821247}
12831248
@@ -1293,8 +1258,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
12931258 mutex_lock (& imx477 -> mutex );
12941259
12951260 /* 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 ;
12981263 try_fmt_img -> code = imx477_get_format_code (imx477 ,
12991264 MEDIA_BUS_FMT_SRGGB12_1X12 );
13001265 try_fmt_img -> field = V4L2_FIELD_NONE ;
@@ -1475,12 +1440,7 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
14751440 return - EINVAL ;
14761441
14771442 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 ))
14841444 return - EINVAL ;
14851445
14861446 mutex_lock (& imx477 -> mutex );
@@ -1490,9 +1450,9 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
14901450 if (fse -> code != code )
14911451 return - EINVAL ;
14921452
1493- fse -> min_width = mode_list [fse -> index ].width ;
1453+ fse -> min_width = supported_modes [fse -> index ].width ;
14941454 fse -> max_width = fse -> min_width ;
1495- fse -> min_height = mode_list [fse -> index ].height ;
1455+ fse -> min_height = supported_modes [fse -> index ].height ;
14961456 fse -> max_height = fse -> min_height ;
14971457 } else {
14981458 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,
15701530 return 0 ;
15711531}
15721532
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-
15891533static void imx477_set_framing_limits (struct imx477 * imx477 )
15901534{
1591- unsigned int frm_length_default , hblank_min ;
1535+ unsigned int hblank_min ;
15921536 const struct imx477_mode * mode = imx477 -> mode ;
15931537 unsigned int line_length_pix ;
15941538
1595- frm_length_default =
1596- imx477_get_frame_length (mode , mode -> framerate_default );
1597-
15981539 /* Default to no long exposure multiplier. */
15991540 imx477 -> long_exp_shift = 0 ;
16001541
16011542 /* Update limits and set FPS to default */
16021543 __v4l2_ctrl_modify_range (imx477 -> vblank , 1 ,
16031544 ((1 << IMX477_LONG_EXP_SHIFT_MAX ) *
16041545 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 );
16091547
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+ }
16111563 if (imx477 -> double_link_freq )
16121564 line_length_pix /= 2 ;
16131565 hblank_min = line_length_pix - mode -> width ;
@@ -1630,17 +1582,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
16301582 mutex_lock (& imx477 -> mutex );
16311583
16321584 if (fmt -> pad == IMAGE_PAD ) {
1633- const struct imx477_mode * mode_list ;
1634- unsigned int num_modes ;
1635-
16361585 /* Bayer order varies with flips */
16371586 fmt -> format .code = imx477_get_format_code (imx477 ,
16381587 fmt -> format .code );
16391588
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 ),
16441591 width , height ,
16451592 fmt -> format .width ,
16461593 fmt -> format .height );
@@ -1649,7 +1596,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
16491596 framefmt = v4l2_subdev_state_get_format (sd_state ,
16501597 fmt -> pad );
16511598 * framefmt = fmt -> format ;
1652- } else if (imx477 -> mode != mode ) {
1599+ } else if (imx477 -> mode != mode ||
1600+ fmt -> format .code != imx477 -> fmt_code ) {
16531601 imx477 -> mode = mode ;
16541602 imx477 -> fmt_code = fmt -> format .code ;
16551603 imx477_set_framing_limits (imx477 );
@@ -1728,7 +1676,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
17281676 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
17291677 const struct imx477_reg_list * reg_list , * freq_regs ;
17301678 const struct imx477_reg_list * extra_regs ;
1731- int ret , tm ;
1679+ int ret , tm , val ;
17321680
17331681 if (!imx477 -> common_regs_written ) {
17341682 ret = imx477_write_regs (imx477 , mode_common_regs ,
@@ -1772,6 +1720,28 @@ static int imx477_start_streaming(struct imx477 *imx477)
17721720 return ret ;
17731721 }
17741722
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+
17751745 /* Set on-sensor DPC. */
17761746 imx477_write_reg (imx477 , 0x0b05 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
17771747 imx477_write_reg (imx477 , 0x0b06 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
0 commit comments