mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
media: i2c: imx347 fix exposure issue
1.add hdr exposure init 2.fix linear mode exposure issue Change-Id: I4850273f942677eb086e426139d9f0f61f4418c1 Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
This commit is contained in:
@@ -105,10 +105,10 @@
|
||||
#define IMX347_HDR_LANES 4
|
||||
#define IMX347_BITS_PER_SAMPLE 10
|
||||
|
||||
#define RHS1_MAX 3113 // <2*BRL=2*1556 && 4n+1
|
||||
#define SHS1_MIN 9
|
||||
#define FSC 4950
|
||||
#define BRL 1556
|
||||
#define RHS1_MAX 3113 // <2*BRL=2*1556 && 4n+1
|
||||
#define SHR1_MIN 9
|
||||
#define BRL 1556
|
||||
|
||||
static bool g_isHCG;
|
||||
|
||||
#define OF_CAMERA_PINCTRL_STATE_DEFAULT "rockchip,camera_default"
|
||||
@@ -180,6 +180,9 @@ struct imx347 {
|
||||
const char *module_facing;
|
||||
const char *module_name;
|
||||
const char *len_name;
|
||||
u32 cur_vts;
|
||||
bool has_init_exp;
|
||||
struct preisp_hdrae_exp_s init_hdrae_exp;
|
||||
};
|
||||
|
||||
#define to_imx347(sd) container_of(sd, struct imx347, subdev)
|
||||
@@ -283,8 +286,8 @@ static const struct regval imx347_hdr_2x_2688x1520_regs[] = {
|
||||
{0x3002, 0x00},
|
||||
{0x300C, 0x5B},
|
||||
{0x300D, 0x40},
|
||||
{0x3030, 0xab},
|
||||
{0x3031, 0x09},
|
||||
{0x3030, 0xbc},
|
||||
{0x3031, 0x07},
|
||||
{0x3032, 0x00},
|
||||
{0x3034, 0xEE},
|
||||
{0x3035, 0x02},
|
||||
@@ -409,11 +412,11 @@ static const struct imx347_mode supported_modes[] = {
|
||||
.height = 1536,
|
||||
.max_fps = {
|
||||
.numerator = 10000,
|
||||
.denominator = 200000,
|
||||
.denominator = 250000,
|
||||
},
|
||||
.exp_def = 0x0240,
|
||||
.hts_def = 0x02ee * 4,
|
||||
.vts_def = 0x09ab,
|
||||
.vts_def = 0x07bc,
|
||||
.reg_list = imx347_hdr_2x_2688x1520_regs,
|
||||
.hdr_mode = HDR_X2,
|
||||
.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_1,
|
||||
@@ -522,7 +525,8 @@ imx347_find_best_fit(struct imx347 *imx347, struct v4l2_subdev_format *fmt)
|
||||
|
||||
for (i = 0; i < imx347->cfg_num; i++) {
|
||||
dist = imx347_get_reso_dist(&supported_modes[i], framefmt);
|
||||
if (cur_best_fit_dist == -1 || dist < cur_best_fit_dist) {
|
||||
if ((cur_best_fit_dist == -1 || dist <= cur_best_fit_dist) &&
|
||||
supported_modes[i].bus_fmt == framefmt->code) {
|
||||
cur_best_fit_dist = dist;
|
||||
cur_best_fit = i;
|
||||
}
|
||||
@@ -691,21 +695,28 @@ static int imx347_set_hdrae(struct imx347 *imx347,
|
||||
u32 l_exp_time, m_exp_time, s_exp_time;
|
||||
u32 l_a_gain, m_a_gain, s_a_gain;
|
||||
u32 gain_switch = 0;
|
||||
u32 shs1 = 0;
|
||||
u32 shs2 = 0;
|
||||
u32 shr1 = 0;
|
||||
u32 shr0 = 0;
|
||||
u32 rhs1 = 0;
|
||||
u32 rhs1_max = 0;
|
||||
static int rhs1_old = 209;
|
||||
int rhs1_change_limit;
|
||||
int ret = 0;
|
||||
u32 fsc = imx347->cur_vts * 2;
|
||||
|
||||
if (!imx347->has_init_exp && !imx347->streaming) {
|
||||
imx347->init_hdrae_exp = *ae;
|
||||
imx347->has_init_exp = true;
|
||||
dev_dbg(&imx347->client->dev, "imx347 don't stream, record exp for hdr!\n");
|
||||
return ret;
|
||||
}
|
||||
l_exp_time = ae->long_exp_reg;
|
||||
m_exp_time = ae->middle_exp_reg;
|
||||
s_exp_time = ae->short_exp_reg;
|
||||
l_a_gain = ae->long_gain_reg;
|
||||
m_a_gain = ae->middle_gain_reg;
|
||||
s_a_gain = ae->short_gain_reg;
|
||||
dev_info(&client->dev,
|
||||
dev_dbg(&client->dev,
|
||||
"rev exp req: L_exp: 0x%x, 0x%x, M_exp: 0x%x, 0x%x S_exp: 0x%x, 0x%x\n",
|
||||
l_exp_time, m_exp_time, s_exp_time,
|
||||
l_a_gain, m_a_gain, s_a_gain);
|
||||
@@ -758,9 +769,9 @@ static int imx347_set_hdrae(struct imx347 *imx347,
|
||||
gain_switch & 0xff);
|
||||
|
||||
//long exposure and short exposure
|
||||
shs2 = FSC - l_exp_time;
|
||||
rhs1_max = (RHS1_MAX > (shs2 - 9)) ? (shs2 - 9) : RHS1_MAX;
|
||||
rhs1 = SHS1_MIN + s_exp_time;
|
||||
shr0 = fsc - l_exp_time;
|
||||
rhs1_max = (RHS1_MAX > (shr0 - 9)) ? (shr0 - 9) : RHS1_MAX;
|
||||
rhs1 = SHR1_MIN + s_exp_time;
|
||||
dev_dbg(&client->dev, "line(%d) rhs1 %d\n", __LINE__, rhs1);
|
||||
if (rhs1 < 13)
|
||||
rhs1 = 13;
|
||||
@@ -769,7 +780,7 @@ static int imx347_set_hdrae(struct imx347 *imx347,
|
||||
dev_dbg(&client->dev, "line(%d) rhs1 %d\n", __LINE__, rhs1);
|
||||
|
||||
//Dynamic adjustment rhs1 must meet the following conditions
|
||||
rhs1_change_limit = rhs1_old + 2 * BRL - FSC + 2;
|
||||
rhs1_change_limit = rhs1_old + 2 * BRL - fsc + 2;
|
||||
rhs1_change_limit = (rhs1_change_limit < 13) ? 13 : rhs1_change_limit;
|
||||
if (rhs1 < rhs1_change_limit)
|
||||
rhs1 = rhs1_change_limit;
|
||||
@@ -777,34 +788,34 @@ static int imx347_set_hdrae(struct imx347 *imx347,
|
||||
dev_dbg(&client->dev,
|
||||
"line(%d) rhs1 %d,short time %d rhs1_old %d test %d\n",
|
||||
__LINE__, rhs1, s_exp_time, rhs1_old,
|
||||
(rhs1_old + 2 * BRL - FSC + 2));
|
||||
(rhs1_old + 2 * BRL - fsc + 2));
|
||||
|
||||
rhs1 = (rhs1 >> 2) * 4 + 1;
|
||||
rhs1_old = rhs1;
|
||||
|
||||
if (rhs1 < s_exp_time) {
|
||||
shs1 = 9;
|
||||
s_exp_time = rhs1 - shs1;
|
||||
shr1 = 9;
|
||||
s_exp_time = rhs1 - shr1;
|
||||
} else {
|
||||
shs1 = rhs1 - s_exp_time;
|
||||
shr1 = rhs1 - s_exp_time;
|
||||
}
|
||||
|
||||
if (shs1 < 9)
|
||||
shs1 = 9;
|
||||
else if (shs1 > (rhs1 - 2))
|
||||
shs1 = rhs1 - 2;
|
||||
if (shr1 < 9)
|
||||
shr1 = 9;
|
||||
else if (shr1 > (rhs1 - 2))
|
||||
shr1 = rhs1 - 2;
|
||||
|
||||
if (shs2 < (rhs1 + 9))
|
||||
shs2 = rhs1 + 9;
|
||||
else if (shs2 > (FSC - 2))
|
||||
shs2 = FSC - 2;
|
||||
if (shr0 < (rhs1 + 9))
|
||||
shr0 = rhs1 + 9;
|
||||
else if (shr0 > (fsc - 2))
|
||||
shr0 = fsc - 2;
|
||||
|
||||
dev_dbg(&client->dev,
|
||||
"FSC=%d,RHS1_MAX=%d,SHS1_MIN=%d,rhs1_max=%d\n",
|
||||
FSC, RHS1_MAX, SHS1_MIN, rhs1_max);
|
||||
"fsc=%d,RHS1_MAX=%d,SHR1_MIN=%d,rhs1_max=%d\n",
|
||||
fsc, RHS1_MAX, SHR1_MIN, rhs1_max);
|
||||
dev_dbg(&client->dev,
|
||||
"l_exp_time=%d,s_exp_time=%d,shs2=%d,shs1=%d,rhs1=%d,l_a_gain=%d,s_a_gain=%d\n",
|
||||
l_exp_time, s_exp_time, shs2, shs1, rhs1, l_a_gain, s_a_gain);
|
||||
"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);
|
||||
//time effect n+2
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_RHS1_REG_L,
|
||||
@@ -822,27 +833,27 @@ static int imx347_set_hdrae(struct imx347 *imx347,
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_SF1_EXPO_REG_L,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_L(shs1));
|
||||
IMX347_FETCH_EXP_L(shr1));
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_SF1_EXPO_REG_M,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_M(shs1));
|
||||
IMX347_FETCH_EXP_M(shr1));
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_SF1_EXPO_REG_H,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_H(shs1));
|
||||
IMX347_FETCH_EXP_H(shr1));
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_LF_EXPO_REG_L,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_L(shs2));
|
||||
IMX347_FETCH_EXP_L(shr0));
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_LF_EXPO_REG_M,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_M(shs2));
|
||||
IMX347_FETCH_EXP_M(shr0));
|
||||
ret |= imx347_write_reg(client,
|
||||
IMX347_LF_EXPO_REG_H,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_H(shs2));
|
||||
IMX347_FETCH_EXP_H(shr0));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -988,17 +999,28 @@ static int __imx347_start_stream(struct imx347 *imx347)
|
||||
if (ret)
|
||||
return ret;
|
||||
/* In case these controls are set before streaming */
|
||||
mutex_unlock(&imx347->mutex);
|
||||
ret = v4l2_ctrl_handler_setup(&imx347->ctrl_handler);
|
||||
mutex_lock(&imx347->mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (imx347->has_init_exp && imx347->cur_mode->hdr_mode != NO_HDR) {
|
||||
ret = imx347_ioctl(&imx347->subdev, PREISP_CMD_SET_HDRAE_EXP,
|
||||
&imx347->init_hdrae_exp);
|
||||
if (ret) {
|
||||
dev_err(&imx347->client->dev,
|
||||
"init exp fail in hdr mode\n");
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
mutex_unlock(&imx347->mutex);
|
||||
ret = v4l2_ctrl_handler_setup(&imx347->ctrl_handler);
|
||||
mutex_lock(&imx347->mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
return imx347_write_reg(imx347->client, IMX347_REG_CTRL_MODE,
|
||||
IMX347_REG_VALUE_08BIT, 0);
|
||||
}
|
||||
|
||||
static int __imx347_stop_stream(struct imx347 *imx347)
|
||||
{
|
||||
imx347->has_init_exp = false;
|
||||
return imx347_write_reg(imx347->client, IMX347_REG_CTRL_MODE,
|
||||
IMX347_REG_VALUE_08BIT, 1);
|
||||
}
|
||||
@@ -1098,7 +1120,7 @@ static int __imx347_power_on(struct imx347 *imx347)
|
||||
}
|
||||
ret = clk_set_rate(imx347->xvclk, IMX347_XVCLK_FREQ);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
|
||||
dev_warn(dev, "Failed to set xvclk rate (37.125MHz)\n");
|
||||
if (clk_get_rate(imx347->xvclk) != IMX347_XVCLK_FREQ)
|
||||
dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
|
||||
ret = clk_prepare_enable(imx347->xvclk);
|
||||
@@ -1290,6 +1312,7 @@ static int imx347_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
s64 max;
|
||||
u32 vts = 0;
|
||||
int ret = 0;
|
||||
u32 shr0 = 0;
|
||||
|
||||
/* Propagate change of current control to all related controls */
|
||||
switch (ctrl->id) {
|
||||
@@ -1308,16 +1331,17 @@ static int imx347_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_EXPOSURE:
|
||||
shr0 = imx347->cur_vts - ctrl->val;
|
||||
ret = imx347_write_reg(imx347->client, IMX347_LF_EXPO_REG_L,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_L(ctrl->val));
|
||||
IMX347_FETCH_EXP_L(shr0));
|
||||
ret |= imx347_write_reg(imx347->client, IMX347_LF_EXPO_REG_M,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_M(ctrl->val));
|
||||
IMX347_FETCH_EXP_M(shr0));
|
||||
ret |= imx347_write_reg(imx347->client, IMX347_LF_EXPO_REG_H,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_EXP_H(ctrl->val));
|
||||
dev_info(&client->dev, "set exposure 0x%x\n",
|
||||
IMX347_FETCH_EXP_H(shr0));
|
||||
dev_dbg(&client->dev, "set exposure 0x%x\n",
|
||||
ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_ANALOGUE_GAIN:
|
||||
@@ -1327,7 +1351,7 @@ static int imx347_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
ret |= imx347_write_reg(imx347->client, IMX347_LF_GAIN_REG_L,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_GAIN_L(ctrl->val));
|
||||
dev_info(&client->dev, "set analog gain 0x%x\n",
|
||||
dev_dbg(&client->dev, "set analog gain 0x%x\n",
|
||||
ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_VBLANK:
|
||||
@@ -1341,7 +1365,8 @@ static int imx347_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
ret |= imx347_write_reg(imx347->client, IMX347_VTS_REG_H,
|
||||
IMX347_REG_VALUE_08BIT,
|
||||
IMX347_FETCH_VTS_H(vts));
|
||||
dev_info(&client->dev, "set vblank 0x%x\n",
|
||||
imx347->cur_vts = vts;
|
||||
dev_dbg(&client->dev, "set vblank 0x%x\n",
|
||||
ctrl->val);
|
||||
break;
|
||||
default:
|
||||
@@ -1398,6 +1423,7 @@ static int imx347_initialize_controls(struct imx347 *imx347)
|
||||
V4L2_CID_VBLANK, vblank_def,
|
||||
IMX347_VTS_MAX - mode->height,
|
||||
1, vblank_def);
|
||||
imx347->cur_vts = mode->vts_def;
|
||||
|
||||
exposure_max = mode->vts_def - 4;
|
||||
imx347->exposure = v4l2_ctrl_new_std(handler, &imx347_ctrl_ops,
|
||||
@@ -1417,6 +1443,7 @@ static int imx347_initialize_controls(struct imx347 *imx347)
|
||||
}
|
||||
|
||||
imx347->subdev.ctrl_handler = handler;
|
||||
imx347->has_init_exp = false;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1665,5 +1692,5 @@ static void __exit sensor_mod_exit(void)
|
||||
device_initcall_sync(sensor_mod_init);
|
||||
module_exit(sensor_mod_exit);
|
||||
|
||||
MODULE_DESCRIPTION("OmniVision imx347 sensor driver");
|
||||
MODULE_DESCRIPTION("Sony imx347 sensor driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
Reference in New Issue
Block a user