diff --git a/drivers/media/i2c/imx415.c b/drivers/media/i2c/imx415.c index 6d32fb61de5d..5cb5a8831ff5 100644 --- a/drivers/media/i2c/imx415.c +++ b/drivers/media/i2c/imx415.c @@ -55,6 +55,7 @@ #define MIPI_FREQ_891M 891000000 #define MIPI_FREQ_446M 446000000 #define MIPI_FREQ_743M 743000000 +#define MIPI_FREQ_297M 297000000 #define IMX415_4LANES 4 @@ -145,13 +146,14 @@ #define IMX415_GROUP_HOLD_END 0x00 /* Basic Readout Lines. Number of necessary readout lines in sensor */ -#define BRL 2228u +#define BRL_ALL 2228u +#define BRL_BINNING 1115u /* Readout timing setting of SEF1(DOL2): RHS1 < 2 * BRL and should be 4n + 1 */ -#define RHS1_MAX_X2 ((BRL * 2 - 1) / 4 * 4 + 1) +#define RHS1_MAX_X2(VAL) (((VAL) * 2 - 1) / 4 * 4 + 1) #define SHR1_MIN_X2 9u /* Readout timing setting of SEF1(DOL3): RHS1 < 3 * BRL and should be 6n + 1 */ -#define RHS1_MAX_X3 ((BRL * 3 - 1) / 6 * 6 + 1) +#define RHS1_MAX_X3(VAL) (((VAL) * 3 - 1) / 6 * 6 + 1) #define SHR1_MIN_X3 13u #define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default" @@ -244,7 +246,11 @@ static __maybe_unused const struct regval imx415_global_12bit_3864x2192_regs[] = {0x3008, 0x7F}, {0x300A, 0x5B}, {0x30C1, 0x00}, + {0x3031, 0x01}, + {0x3032, 0x01}, + {0x30D9, 0x06}, {0x3116, 0x24}, + {0x3118, 0xC0}, {0x311E, 0x24}, {0x32D4, 0x21}, {0x32EC, 0xA1}, @@ -265,6 +271,7 @@ static __maybe_unused const struct regval imx415_global_12bit_3864x2192_regs[] = {0x36D8, 0x71}, {0x36DA, 0x8C}, {0x36DB, 0x00}, + {0x3701, 0x03}, {0x3724, 0x02}, {0x3726, 0x02}, {0x3732, 0x02}, @@ -323,6 +330,9 @@ static __maybe_unused const struct regval imx415_global_12bit_3864x2192_regs[] = }; static __maybe_unused const struct regval imx415_linear_12bit_3864x2192_891M_regs[] = { + {0x3020, 0x00}, + {0x3021, 0x00}, + {0x3022, 0x00}, {0x3024, 0xCA}, {0x3025, 0x08}, {0x3028, 0x4C}, @@ -354,6 +364,9 @@ static __maybe_unused const struct regval imx415_linear_12bit_3864x2192_891M_reg }; static __maybe_unused const struct regval imx415_hdr2_12bit_3864x2192_1782M_regs[] = { + {0x3020, 0x00}, + {0x3021, 0x00}, + {0x3022, 0x00}, {0x3024, 0xCA}, {0x3025, 0x08}, {0x3028, 0x26}, @@ -385,6 +398,9 @@ static __maybe_unused const struct regval imx415_hdr2_12bit_3864x2192_1782M_regs }; static __maybe_unused const struct regval imx415_hdr3_12bit_3864x2192_1782M_regs[] = { + {0x3020, 0x00}, + {0x3021, 0x00}, + {0x3022, 0x00}, {0x3024, 0x96}, {0x3025, 0x06}, {0x3028, 0x26}, @@ -422,6 +438,7 @@ static __maybe_unused const struct regval imx415_global_10bit_3864x2192_regs[] = {0x3031, 0x00}, {0x3032, 0x00}, {0x30C1, 0x00}, + {0x30D9, 0x06}, {0x3116, 0x24}, {0x311E, 0x24}, {0x32D4, 0x21}, @@ -502,6 +519,9 @@ static __maybe_unused const struct regval imx415_global_10bit_3864x2192_regs[] = }; static __maybe_unused const struct regval imx415_hdr3_10bit_3864x2192_1485M_regs[] = { + {0x3020, 0x00}, + {0x3021, 0x00}, + {0x3022, 0x00}, {0x3024, 0xBD}, {0x3025, 0x06}, {0x3028, 0x1A}, @@ -534,6 +554,9 @@ static __maybe_unused const struct regval imx415_hdr3_10bit_3864x2192_1485M_regs }; static __maybe_unused const struct regval imx415_hdr3_10bit_3864x2192_1782M_regs[] = { + {0x3020, 0x00}, + {0x3021, 0x00}, + {0x3022, 0x00}, {0x3024, 0xEA}, {0x3025, 0x07}, {0x3028, 0xCA}, @@ -566,6 +589,9 @@ static __maybe_unused const struct regval imx415_hdr3_10bit_3864x2192_1782M_regs }; static __maybe_unused const struct regval imx415_hdr2_10bit_3864x2192_1485M_regs[] = { + {0x3020, 0x00}, + {0x3021, 0x00}, + {0x3022, 0x00}, {0x3024, 0xFC}, {0x3025, 0x08}, {0x3028, 0x1A}, @@ -598,6 +624,9 @@ static __maybe_unused const struct regval imx415_hdr2_10bit_3864x2192_1485M_regs }; static __maybe_unused const struct regval imx415_linear_10bit_3864x2192_891M_regs[] = { + {0x3020, 0x00}, + {0x3021, 0x00}, + {0x3022, 0x00}, {0x3024, 0xCA}, {0x3025, 0x08}, {0x3028, 0x4C}, @@ -629,6 +658,84 @@ static __maybe_unused const struct regval imx415_linear_10bit_3864x2192_891M_reg {REG_NULL, 0x00}, }; +static __maybe_unused const struct regval imx415_linear_12bit_1932x1096_594M_regs[] = { + {0x3020, 0x01}, + {0x3021, 0x01}, + {0x3022, 0x01}, + {0x3024, 0x5D}, + {0x3025, 0x0C}, + {0x3028, 0x0E}, + {0x3029, 0x03}, + {0x302C, 0x00}, + {0x302D, 0x00}, + {0x3031, 0x00}, + {0x3033, 0x07}, + {0x3050, 0x08}, + {0x3051, 0x00}, + {0x3054, 0x19}, + {0x3058, 0x3E}, + {0x3060, 0x25}, + {0x3064, 0x4A}, + {0x30CF, 0x00}, + {0x30D9, 0x02}, + {0x30DA, 0x01}, + {0x3118, 0x80}, + {0x3260, 0x01}, + {0x3701, 0x00}, + {0x400C, 0x00}, + {0x4018, 0x67}, + {0x401A, 0x27}, + {0x401C, 0x27}, + {0x401E, 0xB7}, + {0x401F, 0x00}, + {0x4020, 0x2F}, + {0x4022, 0x4F}, + {0x4024, 0x2F}, + {0x4026, 0x47}, + {0x4028, 0x27}, + {0x4074, 0x01}, + {REG_NULL, 0x00}, +}; + +static __maybe_unused const struct regval imx415_hdr2_12bit_1932x1096_891M_regs[] = { + {0x3020, 0x01}, + {0x3021, 0x01}, + {0x3022, 0x01}, + {0x3024, 0xFC}, + {0x3025, 0x08}, + {0x3028, 0x1A}, + {0x3029, 0x02}, + {0x302C, 0x01}, + {0x302D, 0x01}, + {0x3031, 0x00}, + {0x3033, 0x05}, + {0x3050, 0xB8}, + {0x3051, 0x00}, + {0x3054, 0x09}, + {0x3058, 0x3E}, + {0x3060, 0x25}, + {0x3064, 0x4A}, + {0x30CF, 0x01}, + {0x30D9, 0x02}, + {0x30DA, 0x01}, + {0x3118, 0xC0}, + {0x3260, 0x00}, + {0x3701, 0x00}, + {0x400C, 0x00}, + {0x4018, 0xA7}, + {0x401A, 0x57}, + {0x401C, 0x5F}, + {0x401E, 0x97}, + {0x401F, 0x01}, + {0x4020, 0x5F}, + {0x4022, 0xAF}, + {0x4024, 0x5F}, + {0x4026, 0x9F}, + {0x4028, 0x4F}, + {0x4074, 0x01}, + {REG_NULL, 0x00}, +}; + /* * The width and height must be configured to be * the same as the current output resolution of the sensor. @@ -660,7 +767,7 @@ static const struct imx415_mode supported_modes[] = { .global_reg_list = imx415_global_10bit_3864x2192_regs, .reg_list = imx415_linear_10bit_3864x2192_891M_regs, .hdr_mode = NO_HDR, - .mipi_freq_idx = 0, + .mipi_freq_idx = 1, .bpp = 10, }, { @@ -681,7 +788,7 @@ static const struct imx415_mode supported_modes[] = { .global_reg_list = imx415_global_10bit_3864x2192_regs, .reg_list = imx415_hdr2_10bit_3864x2192_1485M_regs, .hdr_mode = HDR_X2, - .mipi_freq_idx = 1, + .mipi_freq_idx = 2, .bpp = 10, .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1, .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0 @@ -706,7 +813,7 @@ static const struct imx415_mode supported_modes[] = { .global_reg_list = imx415_global_10bit_3864x2192_regs, .reg_list = imx415_hdr3_10bit_3864x2192_1485M_regs, .hdr_mode = HDR_X3, - .mipi_freq_idx = 1, + .mipi_freq_idx = 2, .bpp = 10, .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_2, .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr0 @@ -731,7 +838,7 @@ static const struct imx415_mode supported_modes[] = { .global_reg_list = imx415_global_10bit_3864x2192_regs, .reg_list = imx415_hdr3_10bit_3864x2192_1782M_regs, .hdr_mode = HDR_X3, - .mipi_freq_idx = 2, + .mipi_freq_idx = 3, .bpp = 10, .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_2, .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr0 @@ -753,7 +860,7 @@ static const struct imx415_mode supported_modes[] = { .global_reg_list = imx415_global_12bit_3864x2192_regs, .reg_list = imx415_linear_12bit_3864x2192_891M_regs, .hdr_mode = NO_HDR, - .mipi_freq_idx = 0, + .mipi_freq_idx = 1, .bpp = 12, }, { @@ -774,7 +881,7 @@ static const struct imx415_mode supported_modes[] = { .global_reg_list = imx415_global_12bit_3864x2192_regs, .reg_list = imx415_hdr2_12bit_3864x2192_1782M_regs, .hdr_mode = HDR_X2, - .mipi_freq_idx = 2, + .mipi_freq_idx = 3, .bpp = 12, .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1, .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0 @@ -799,16 +906,59 @@ static const struct imx415_mode supported_modes[] = { .global_reg_list = imx415_global_12bit_3864x2192_regs, .reg_list = imx415_hdr3_12bit_3864x2192_1782M_regs, .hdr_mode = HDR_X3, - .mipi_freq_idx = 2, + .mipi_freq_idx = 3, .bpp = 12, .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_2, .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr0 .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0 .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_2,//S->csi wr2 }, + { + .bus_fmt = MEDIA_BUS_FMT_SGBRG12_1X12, + .width = 1944, + .height = 1097, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x05dc - 0x08, + .hts_def = 0x030e * 3, + .vts_def = 0x0c5d, + .global_reg_list = imx415_global_12bit_3864x2192_regs, + .reg_list = imx415_linear_12bit_1932x1096_594M_regs, + .hdr_mode = NO_HDR, + .mipi_freq_idx = 0, + .bpp = 12, + }, + { + .bus_fmt = MEDIA_BUS_FMT_SGBRG12_1X12, + .width = 1944, + .height = 1097, + .max_fps = { + .numerator = 10000, + .denominator = 300000, + }, + .exp_def = 0x08FC / 4, + .hts_def = 0x021A * 4, + /* + * IMX415 HDR mode T-line is half of Linear mode, + * make vts double(that is FSC) to workaround. + */ + .vts_def = 0x08FC * 2, + .global_reg_list = imx415_global_12bit_3864x2192_regs, + .reg_list = imx415_hdr2_12bit_1932x1096_891M_regs, + .hdr_mode = HDR_X2, + .mipi_freq_idx = 1, + .bpp = 12, + .vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1, + .vc[PAD1] = V4L2_MBUS_CSI2_CHANNEL_0,//L->csi wr0 + .vc[PAD2] = V4L2_MBUS_CSI2_CHANNEL_1, + .vc[PAD3] = V4L2_MBUS_CSI2_CHANNEL_1,//M->csi wr2 + }, }; static const s64 link_freq_items[] = { + MIPI_FREQ_297M, MIPI_FREQ_446M, MIPI_FREQ_743M, MIPI_FREQ_891M, @@ -1174,7 +1324,10 @@ static int imx415_set_hdrae_3frame(struct imx415 *imx415, __LINE__, shr0, l_exp_time, fsc); rhs1 = (SHR1_MIN_X3 + m_exp_time + 5) / 6 * 6 + 1; - rhs1_max = RHS1_MAX_X3; + if (imx415->cur_mode->height == 2192) + rhs1_max = RHS1_MAX_X3(BRL_ALL); + else + rhs1_max = RHS1_MAX_X3(BRL_BINNING); if (rhs1 < 25) rhs1 = 25; else if (rhs1 > rhs1_max) @@ -1184,7 +1337,10 @@ static int imx415_set_hdrae_3frame(struct imx415 *imx415, __LINE__, rhs1, m_exp_time, rhs1_old); //Dynamic adjustment rhs2 must meet the following conditions - rhs1_change_limit = rhs1_old + 3 * BRL - fsc + 3; + if (imx415->cur_mode->height == 2192) + rhs1_change_limit = rhs1_old + 3 * BRL_ALL - fsc + 3; + else + rhs1_change_limit = rhs1_old + 3 * BRL_BINNING - fsc + 3; rhs1_change_limit = (rhs1_change_limit < 25) ? 25 : rhs1_change_limit; rhs1_change_limit = (rhs1_change_limit + 5) / 6 * 6 + 1; if (rhs1_max < rhs1_change_limit) { @@ -1221,7 +1377,10 @@ static int imx415_set_hdrae_3frame(struct imx415 *imx415, __LINE__, rhs2, s_exp_time, rhs2_old); //Dynamic adjustment rhs2 must meet the following conditions - rhs2_change_limit = rhs2_old + 3 * BRL - fsc + 3; + if (imx415->cur_mode->height == 2192) + rhs2_change_limit = rhs2_old + 3 * BRL_ALL - fsc + 3; + else + rhs2_change_limit = rhs2_old + 3 * BRL_BINNING - fsc + 3; rhs2_change_limit = (rhs2_change_limit < 50) ? 50 : rhs2_change_limit; rhs2_change_limit = (rhs2_change_limit + 5) / 6 * 6 + 2; if ((shr0 - 13) < rhs2_change_limit) { @@ -1403,8 +1562,13 @@ static int imx415_set_hdrae(struct imx415 *imx415, fsc = imx415->cur_vts; shr0 = fsc - l_exp_time; - rhs1_max = min(RHS1_MAX_X2, ((shr0 - 9u) / 4 * 4 + 1)); - rhs1_min = max(SHR1_MIN_X2 + 8u, rhs1_old + 2 * BRL - fsc + 2); + if (imx415->cur_mode->height == 2192) { + rhs1_max = min(RHS1_MAX_X2(BRL_ALL), ((shr0 - 9u) / 4 * 4 + 1)); + rhs1_min = max(SHR1_MIN_X2 + 8u, rhs1_old + 2 * BRL_ALL - fsc + 2); + } else { + rhs1_max = min(RHS1_MAX_X2(BRL_BINNING), ((shr0 - 9u) / 4 * 4 + 1)); + rhs1_min = max(SHR1_MIN_X2 + 8u, rhs1_old + 2 * BRL_BINNING - fsc + 2); + } rhs1_min = (rhs1_min + 3) / 4 * 4 + 1; rhs1 = (SHR1_MIN_X2 + s_exp_time + 3) / 4 * 4 + 1;/* shall be 4n + 1 */ dev_dbg(&client->dev, @@ -1438,7 +1602,7 @@ static int imx415_set_hdrae(struct imx415 *imx415, dev_dbg(&client->dev, "fsc=%d,RHS1_MAX=%d,SHR1_MIN=%d,rhs1_max=%d\n", - fsc, RHS1_MAX_X2, SHR1_MIN_X2, rhs1_max); + fsc, RHS1_MAX_X2(BRL_ALL), SHR1_MIN_X2, rhs1_max); dev_dbg(&client->dev, "l_exp_time=%d,s_exp_time=%d,shr0=%d,shr1=%d,rhs1=%d,l_a_gain=%d,s_a_gain=%d\n", l_exp_time, s_exp_time, shr0, shr1, rhs1, l_a_gain, s_a_gain); @@ -1565,7 +1729,9 @@ static long imx415_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) break; case RKMODULE_GET_SONY_BRL: if (imx415->cur_mode->width == 3864 && imx415->cur_mode->height == 2192) - *((u32 *)arg) = BRL; + *((u32 *)arg) = BRL_ALL; + else + *((u32 *)arg) = BRL_BINNING; break; default: ret = -ENOIOCTLCMD; @@ -1945,8 +2111,10 @@ static int imx415_enum_frame_interval(struct v4l2_subdev *sd, } #define CROP_START(SRC, DST) (((SRC) - (DST)) / 2 / 4 * 4) -#define DST_WIDTH 3840 -#define DST_HEIGHT 2160 +#define DST_WIDTH_3840 3840 +#define DST_HEIGHT_2160 2160 +#define DST_WIDTH_1920 1920 +#define DST_HEIGHT_1080 1080 /* * The resolution of the driver configuration needs to be exactly @@ -1964,10 +2132,22 @@ static int imx415_get_selection(struct v4l2_subdev *sd, struct imx415 *imx415 = to_imx415(sd); if (sel->target == V4L2_SEL_TGT_CROP_BOUNDS) { - sel->r.left = CROP_START(imx415->cur_mode->width, DST_WIDTH); - sel->r.width = DST_WIDTH; - sel->r.top = CROP_START(imx415->cur_mode->height, DST_HEIGHT); - sel->r.height = DST_HEIGHT; + if (imx415->cur_mode->width == 3864) { + sel->r.left = CROP_START(imx415->cur_mode->width, DST_WIDTH_3840); + sel->r.width = DST_WIDTH_3840; + sel->r.top = CROP_START(imx415->cur_mode->height, DST_HEIGHT_2160); + sel->r.height = DST_HEIGHT_2160; + } else if (imx415->cur_mode->width == 1944) { + sel->r.left = CROP_START(imx415->cur_mode->width, DST_WIDTH_1920); + sel->r.width = DST_WIDTH_1920; + sel->r.top = CROP_START(imx415->cur_mode->height, DST_HEIGHT_1080); + sel->r.height = DST_HEIGHT_1080; + } else { + sel->r.left = CROP_START(imx415->cur_mode->width, imx415->cur_mode->width); + sel->r.width = imx415->cur_mode->width; + sel->r.top = CROP_START(imx415->cur_mode->height, imx415->cur_mode->height); + sel->r.height = imx415->cur_mode->height; + } return 0; } return -EINVAL;