media: i2c: imx415 add 1080p binning mode

Signed-off-by: Zhenke Fan <fanzy.fan@rock-chips.com>
Change-Id: I5b4a1f2c728d6f45406c2efd5c3cc9c9306ccb3a
This commit is contained in:
Zhenke Fan
2021-07-10 17:26:24 +08:00
committed by Tao Huang
parent 6fc680cb0d
commit 34b4a03fee

View File

@@ -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;