@@ -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 ;
@@ -569,8 +576,6 @@ static const struct imx477_reg mode_common_regs[] = {
569576
570577/* 12 mpix 10fps */
571578static const struct imx477_reg mode_4056x3040_regs [] = {
572- {0x0112 , 0x0c },
573- {0x0113 , 0x0c },
574579 {0x0344 , 0x00 },
575580 {0x0345 , 0x00 },
576581 {0x0346 , 0x00 },
@@ -625,7 +630,6 @@ static const struct imx477_reg mode_4056x3040_regs[] = {
625630 {0x0305 , 0x04 },
626631 {0x0306 , 0x01 },
627632 {0x0307 , 0x5e },
628- {0x0309 , 0x0c },
629633 {0xe04c , 0x00 },
630634 {0xe04d , 0x7f },
631635 {0xe04e , 0x00 },
@@ -700,8 +704,6 @@ static const struct imx477_reg mode_4056x2160_regs[] = {
700704
701705/* 2x2 binned. 40fps */
702706static const struct imx477_reg mode_2028x1520_regs [] = {
703- {0x0112 , 0x0c },
704- {0x0113 , 0x0c },
705707 {0x0344 , 0x00 },
706708 {0x0345 , 0x00 },
707709 {0x0346 , 0x00 },
@@ -745,7 +747,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
745747 {0x0305 , 0x04 },
746748 {0x0306 , 0x01 },
747749 {0x0307 , 0x5e },
748- {0x0309 , 0x0c },
749750 {0xe04c , 0x00 },
750751 {0xe04d , 0x7f },
751752 {0xe04e , 0x00 },
@@ -756,8 +757,6 @@ static const struct imx477_reg mode_2028x1520_regs[] = {
756757
757758/* 1080p cropped mode */
758759static const struct imx477_reg mode_2028x1080_regs [] = {
759- {0x0112 , 0x0c },
760- {0x0113 , 0x0c },
761760 {0x0344 , 0x00 },
762761 {0x0345 , 0x00 },
763762 {0x0346 , 0x01 },
@@ -801,7 +800,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
801800 {0x0305 , 0x04 },
802801 {0x0306 , 0x01 },
803802 {0x0307 , 0x5e },
804- {0x0309 , 0x0c },
805803 {0xe04c , 0x00 },
806804 {0xe04d , 0x7f },
807805 {0xe04e , 0x00 },
@@ -812,8 +810,6 @@ static const struct imx477_reg mode_2028x1080_regs[] = {
812810
813811/* 4x4 binned. 120fps */
814812static const struct imx477_reg mode_1332x990_regs [] = {
815- {0x0112 , 0x0a },
816- {0x0113 , 0x0a },
817813 {0x420b , 0x01 },
818814 {0x990c , 0x00 },
819815 {0x990d , 0x08 },
@@ -881,7 +877,6 @@ static const struct imx477_reg mode_1332x990_regs[] = {
881877 {0x0305 , 0x02 },
882878 {0x0306 , 0x00 },
883879 {0x0307 , 0xaf },
884- {0x0309 , 0x0a },
885880 {0xe04c , 0x00 },
886881 {0xe04d , 0x5f },
887882 {0xe04e , 0x00 },
@@ -891,12 +886,12 @@ static const struct imx477_reg mode_1332x990_regs[] = {
891886};
892887
893888/* Mode configs */
894- static const struct imx477_mode supported_modes_12bit [] = {
889+ static const struct imx477_mode supported_modes [] = {
895890 {
896891 /* 12MPix 10fps mode */
897892 .width = 4056 ,
898893 .height = 3040 ,
899- .line_length_pix = 24000 ,
894+ .line_length_pix = { 24000 , 20000 } ,
900895 .crop = {
901896 .left = IMX477_PIXEL_ARRAY_LEFT ,
902897 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -930,7 +925,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
930925 /* 2x2 binned 40fps mode */
931926 .width = 2028 ,
932927 .height = 1520 ,
933- .line_length_pix = 12740 ,
928+ .line_length_pix = { 12740 , 10616 } ,
934929 .crop = {
935930 .left = IMX477_PIXEL_ARRAY_LEFT ,
936931 .top = IMX477_PIXEL_ARRAY_TOP ,
@@ -947,7 +942,7 @@ static const struct imx477_mode supported_modes_12bit[] = {
947942 /* 1080p 50fps cropped mode */
948943 .width = 2028 ,
949944 .height = 1080 ,
950- .line_length_pix = 12740 ,
945+ .line_length_pix = { 12740 , 10616 } ,
951946 .crop = {
952947 .left = IMX477_PIXEL_ARRAY_LEFT ,
953948 .top = IMX477_PIXEL_ARRAY_TOP + 440 ,
@@ -959,15 +954,12 @@ static const struct imx477_mode supported_modes_12bit[] = {
959954 .num_of_regs = ARRAY_SIZE (mode_2028x1080_regs ),
960955 .regs = mode_2028x1080_regs ,
961956 },
962- }
963- };
964-
965- static const struct imx477_mode supported_modes_10bit [] = {
957+ },
966958 {
967959 /* 120fps. 2x2 binned and cropped */
968960 .width = 1332 ,
969961 .height = 990 ,
970- .line_length_pix = 6664 ,
962+ .line_length_pix = { 7997 , 6664 } ,
971963 .crop = {
972964 /*
973965 * FIXME: the analog crop rectangle is actually
@@ -1119,33 +1111,6 @@ static inline struct imx477 *to_imx477(struct v4l2_subdev *_sd)
11191111 return container_of (_sd , struct imx477 , sd );
11201112}
11211113
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-
11491114/* Read registers up to 2 at a time */
11501115static int imx477_read_reg (struct imx477 * imx477 , u16 reg , u32 len , u32 * val )
11511116{
@@ -1241,7 +1206,7 @@ static u32 imx477_get_format_code(struct imx477 *imx477, u32 code)
12411206static void imx477_set_default_format (struct imx477 * imx477 )
12421207{
12431208 /* Set default mode to max resolution */
1244- imx477 -> mode = & supported_modes_12bit [0 ];
1209+ imx477 -> mode = & supported_modes [0 ];
12451210 imx477 -> fmt_code = MEDIA_BUS_FMT_SRGGB12_1X12 ;
12461211}
12471212
@@ -1257,8 +1222,8 @@ static int imx477_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
12571222 mutex_lock (& imx477 -> mutex );
12581223
12591224 /* 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 ;
12621227 try_fmt_img -> code = imx477_get_format_code (imx477 ,
12631228 MEDIA_BUS_FMT_SRGGB12_1X12 );
12641229 try_fmt_img -> field = V4L2_FIELD_NONE ;
@@ -1436,20 +1401,15 @@ static int imx477_enum_frame_size(struct v4l2_subdev *sd,
14361401 return - EINVAL ;
14371402
14381403 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 ))
14451405 return - EINVAL ;
14461406
14471407 if (fse -> code != imx477_get_format_code (imx477 , fse -> code ))
14481408 return - EINVAL ;
14491409
1450- fse -> min_width = mode_list [fse -> index ].width ;
1410+ fse -> min_width = supported_modes [fse -> index ].width ;
14511411 fse -> max_width = fse -> min_width ;
1452- fse -> min_height = mode_list [fse -> index ].height ;
1412+ fse -> min_height = supported_modes [fse -> index ].height ;
14531413 fse -> max_height = fse -> min_height ;
14541414 } else {
14551415 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,
15271487 return 0 ;
15281488}
15291489
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-
15461490static void imx477_set_framing_limits (struct imx477 * imx477 )
15471491{
1548- unsigned int frm_length_default , hblank_min ;
1492+ unsigned int hblank_min ;
15491493 const struct imx477_mode * mode = imx477 -> mode ;
15501494 unsigned int line_length_pix ;
15511495
1552- frm_length_default =
1553- imx477_get_frame_length (mode , mode -> framerate_default );
1554-
15551496 /* Default to no long exposure multiplier. */
15561497 imx477 -> long_exp_shift = 0 ;
15571498
15581499 /* Update limits and set FPS to default */
15591500 __v4l2_ctrl_modify_range (imx477 -> vblank , 1 ,
15601501 ((1 << IMX477_LONG_EXP_SHIFT_MAX ) *
15611502 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 );
15661504
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+ }
15681520 if (imx477 -> double_link_freq )
15691521 line_length_pix /= 2 ;
15701522 hblank_min = line_length_pix - mode -> width ;
@@ -1587,17 +1539,12 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
15871539 mutex_lock (& imx477 -> mutex );
15881540
15891541 if (fmt -> pad == IMAGE_PAD ) {
1590- const struct imx477_mode * mode_list ;
1591- unsigned int num_modes ;
1592-
15931542 /* Bayer order varies with flips */
15941543 fmt -> format .code = imx477_get_format_code (imx477 ,
15951544 fmt -> format .code );
15961545
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 ),
16011548 width , height ,
16021549 fmt -> format .width ,
16031550 fmt -> format .height );
@@ -1606,7 +1553,8 @@ static int imx477_set_pad_format(struct v4l2_subdev *sd,
16061553 framefmt = v4l2_subdev_get_try_format (sd , sd_state ,
16071554 fmt -> pad );
16081555 * framefmt = fmt -> format ;
1609- } else if (imx477 -> mode != mode ) {
1556+ } else if (imx477 -> mode != mode ||
1557+ fmt -> format .code != imx477 -> fmt_code ) {
16101558 imx477 -> mode = mode ;
16111559 imx477 -> fmt_code = fmt -> format .code ;
16121560 imx477_set_framing_limits (imx477 );
@@ -1685,7 +1633,7 @@ static int imx477_start_streaming(struct imx477 *imx477)
16851633 struct i2c_client * client = v4l2_get_subdevdata (& imx477 -> sd );
16861634 const struct imx477_reg_list * reg_list , * freq_regs ;
16871635 const struct imx477_reg_list * extra_regs ;
1688- int ret , tm ;
1636+ int ret , tm , val ;
16891637
16901638 if (!imx477 -> common_regs_written ) {
16911639 ret = imx477_write_regs (imx477 , mode_common_regs ,
@@ -1729,6 +1677,28 @@ static int imx477_start_streaming(struct imx477 *imx477)
17291677 return ret ;
17301678 }
17311679
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+
17321702 /* Set on-sensor DPC. */
17331703 imx477_write_reg (imx477 , 0x0b05 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
17341704 imx477_write_reg (imx477 , 0x0b06 , IMX477_REG_VALUE_08BIT , !!dpc_enable );
0 commit comments