media: i2c: sc850sl: fix gain discontinuity issue

sync update from 4.19

Change-Id: I432669771e6a3a5c9e07811f94f5bd77ed5b2e63
Signed-off-by: Lan Honglin <helin.lan@rock-chips.com>
This commit is contained in:
Lan Honglin
2023-12-26 11:19:35 +08:00
parent ce956f7a33
commit beb9974b6f

View File

@@ -73,7 +73,7 @@
#define SC850SL_REG_DGAIN 0x3e06
#define SC850SL_REG_AGAIN 0x3e08
#define SC850SL_REG_AGAIN_FINE 0x3e09
//#define SC850SL_REG_DGAIN_FINE 0x3e07
#define SC850SL_REG_DGAIN_FINE 0x3e07
//short fram gain reg
#define SC850SL_SF_REG_AGAIN 0x3e12
@@ -370,7 +370,6 @@ static __maybe_unused const struct regval sc850sl_linear10bit_3840x2160_regs[] =
{0x59fd, 0x3f},
{0x59fe, 0x38},
{0x59ff, 0x30},
{0x0100, 0x01},
/*
* [gain < 2x] {0x363c, 0x05},
* [gain >=2x] {0x363c, 0x07},
@@ -713,7 +712,7 @@ static void sc850sl_get_module_inf(struct sc850sl *sc850sl,
}
static void sc850sl_get_gain_reg(u32 val, u32 *again_reg, u32 *again_fine_reg,
u32 *dgain_reg)
u32 *dgain_reg, u32 *dgain_fine_reg)
{
u8 u8Reg0x3e09 = 0x40, u8Reg0x3e08 = 0x03;
u32 aCoarseGain = 0;
@@ -757,16 +756,19 @@ static void sc850sl_get_gain_reg(u32 val, u32 *again_reg, u32 *again_fine_reg,
u8Reg0x3e09 = aFineGain;
//dcg = 2.72  -->  2.72*1024=2785.28
u8Reg0x3e08 = (again > 200) ? (u8Reg0x3e08 | 0x20) : (u8Reg0x3e08 & 0x1f);
*dgain_fine_reg = val * 128 / again / dgain;
//dgain
if (dgain <= 1) { /*1x ~ 2x*/
if (dgain < 2) { /*1x ~ 2x*/
*dgain_reg = 0x00;
} else if (dgain <= 2) { /*2x ~ 4x*/
} else if (dgain < 4) { /*2x ~ 4x*/
*dgain_reg = 0x01;
} else if (dgain <= 4) { /*4x ~ 8x*/
*dgain_fine_reg += (dgain - 2) * 64;
} else if (dgain < 8) { /*4x ~ 8x*/
*dgain_reg = 0x03;
*dgain_fine_reg += (dgain - 4) * 32;
} else {
*dgain_reg = 0x07;
*dgain_fine_reg = 0x80;
}
*again_reg = u8Reg0x3e08;
@@ -1347,7 +1349,7 @@ static int sc850sl_set_ctrl(struct v4l2_ctrl *ctrl)
struct sc850sl, ctrl_handler);
struct i2c_client *client = sc850sl->client;
s64 max;
u32 again, again_fine, dgain;
u32 again, again_fine, dgain, dgain_fine;
int ret = 0;
u32 val;
@@ -1355,7 +1357,7 @@ static int sc850sl_set_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_VBLANK:
/* Update max exposure while meeting expected vblanking */
max = sc850sl->cur_mode->height + ctrl->val - 8;
max = sc850sl->cur_mode->height + ctrl->val - 4;
__v4l2_ctrl_modify_range(sc850sl->exposure,
sc850sl->exposure->minimum, max,
sc850sl->exposure->step,
@@ -1389,9 +1391,10 @@ static int sc850sl_set_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_ANALOGUE_GAIN:
if (sc850sl->cur_mode->hdr_mode != NO_HDR)
goto out_ctrl;
sc850sl_get_gain_reg(ctrl->val, &again, &again_fine, &dgain);
dev_dbg(&client->dev, "recv_gain:%d set again 0x%x, again_fine 0x%x, set dgain 0x%x\n",
ctrl->val, again, again_fine, dgain);
sc850sl_get_gain_reg(ctrl->val, &again, &again_fine, &dgain, &dgain_fine);
dev_dbg(&client->dev,
"recv_gain:%d set again 0x%x, again_fine 0x%x, set dgain 0x%x, dgain_fine 0x%x\n",
ctrl->val, again, again_fine, dgain, dgain_fine);
ret |= sc850sl_write_reg(sc850sl->client,
SC850SL_REG_AGAIN,
@@ -1405,6 +1408,10 @@ static int sc850sl_set_ctrl(struct v4l2_ctrl *ctrl)
SC850SL_REG_DGAIN,
SC850SL_REG_VALUE_08BIT,
dgain);
ret |= sc850sl_write_reg(sc850sl->client,
SC850SL_REG_DGAIN_FINE,
SC850SL_REG_VALUE_08BIT,
dgain_fine);
break;
case V4L2_CID_VBLANK:
ret = sc850sl_write_reg(sc850sl->client, SC850SL_REG_VTS,