media: i2c: os04a10 change

1.add digital gain control
2.add delay time to 12ms after power_on
3.os04a10_global_regs write in start_stream
4.default used 12 bit

Change-Id: I8c9918c3188608b19d73bf23f83ec02dda1b926e
Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
This commit is contained in:
Zefa Chen
2020-04-20 20:38:04 +08:00
committed by Tao Huang
parent 874374348b
commit 4629acc757

View File

@@ -53,20 +53,17 @@
#define OS04A10_VTS_MAX 0xffff
#define OS04A10_REG_EXP_LONG_H 0x3501
#define OS04A10_REG_EXP_LONG_L 0x3502
#define OS04A10_REG_EXP_MID_H 0x3541
#define OS04A10_REG_EXP_MID_L 0x3542
#define OS04A10_REG_EXP_VS_H 0x3581
#define OS04A10_REG_EXP_VS_L 0x3582
#define OS04A10_REG_GAIN_LONG_H 0x3508
#define OS04A10_REG_GAIN_LONG_L 0x3509
#define OS04A10_REG_GAIN_MID_H 0x3548
#define OS04A10_REG_GAIN_MID_L 0x3549
#define OS04A10_REG_GAIN_VS_H 0x3588
#define OS04A10_REG_GAIN_VS_L 0x3589
#define OS04A10_REG_AGAIN_LONG_H 0x3508
#define OS04A10_REG_AGAIN_MID_H 0x3548
#define OS04A10_REG_AGAIN_VS_H 0x3588
#define OS04A10_REG_DGAIN_LONG_H 0x350A
#define OS04A10_REG_DGAIN_MID_H 0x354A
#define OS04A10_REG_DGAIN_VS_H 0x358A
#define OS04A10_GAIN_MIN 0x10
#define OS04A10_GAIN_MAX 0x100
#define OS04A10_GAIN_MAX 0xF7C
#define OS04A10_GAIN_STEP 1
#define OS04A10_GAIN_DEFAULT 0x10
@@ -75,6 +72,8 @@
#define OS04A10_GROUP_UPDATE_END_DATA 0x10
#define OS04A10_GROUP_UPDATE_END_LAUNCH 0xA0
#define OS04A10_SOFTWARE_RESET_REG 0x0103
#define OS04A10_FETCH_MSB_BYTE_EXP(VAL) (((VAL) >> 8) & 0xFF) /* 8 Bits */
#define OS04A10_FETCH_LSB_BYTE_EXP(VAL) ((VAL) & 0xFF) /* 8 Bits */
@@ -177,7 +176,6 @@ struct os04a10 {
* Xclk 24Mhz
*/
static const struct regval os04a10_global_regs[] = {
{0x0103, 0x01},
{0x0109, 0x01},
{0x0104, 0x02},
{0x0102, 0x00},
@@ -593,10 +591,10 @@ static const struct regval os04a10_hdr10bit_2688x1520_regs[] = {
{0x380b, 0xf0},
{0x380c, 0x02},
{0x380d, 0xdc},
/* {0x380e, 0x06}, */
/* {0x380f, 0x58}, */
{0x380e, 0x0c},
{0x380f, 0xb0},
{0x380e, 0x06},
{0x380f, 0x58},
//{0x380e, 0x0c},
//{0x380f, 0xb0},
{0x381c, 0x08},
{0x3820, 0x03},
{0x3833, 0x41},
@@ -799,6 +797,24 @@ static const struct os04a10_mode supported_modes[] = {
.hdr_mode = NO_HDR,
.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
},
{
.bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12,
.width = 2688,
.height = 1520,
.max_fps = {
.numerator = 10000,
.denominator = 225000,
},
.exp_def = 0x0240,
.hts_def = 0x05c4 * 2,
.vts_def = 0x0658,
.reg_list = os04a10_hdr12bit_2688x1520_regs,
.hdr_mode = HDR_X2,
.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
},
{
.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
.width = 2688,
@@ -814,25 +830,6 @@ static const struct os04a10_mode supported_modes[] = {
.hdr_mode = NO_HDR,
.vc[PAD0] = V4L2_MBUS_CSI2_CHANNEL_0,
},
{
.bus_fmt = MEDIA_BUS_FMT_SBGGR12_1X12,
.width = 2688,
.height = 1520,
.max_fps = {
.numerator = 10000,
/* .denominator = 302834 * 2, */
.denominator = 225000,
},
.exp_def = 0x0240,
.hts_def = 0x05c4 * 2,
.vts_def = 0x0658,
.reg_list = os04a10_hdr12bit_2688x1520_regs,
.hdr_mode = HDR_X2,
.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
},
{
.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
.width = 2688,
@@ -1186,6 +1183,9 @@ static int os04a10_set_hdrae(struct os04a10 *os04a10,
{
u32 l_exp_time, m_exp_time, s_exp_time;
u32 l_a_gain, m_a_gain, s_a_gain;
u32 l_d_gain = 1024;
u32 m_d_gain = 1024;
u32 s_d_gain = 1024;
int ret = 0;
if (!os04a10->has_init_exp && !os04a10->streaming) {
@@ -1213,22 +1213,44 @@ static int os04a10_set_hdrae(struct os04a10 *os04a10,
m_a_gain = s_a_gain;
m_exp_time = s_exp_time;
}
if (l_a_gain > 248) {
l_d_gain = l_a_gain * 1024 / 248;
l_a_gain = 248;
}
if (m_a_gain > 248) {
m_d_gain = m_a_gain * 1024 / 248;
m_a_gain = 248;
}
if (os04a10->cur_mode->hdr_mode == HDR_X3 && s_a_gain > 248) {
s_d_gain = s_a_gain * 1024 / 248;
s_a_gain = 248;
}
ret |= os04a10_write_reg(os04a10->client,
OS04A10_GROUP_UPDATE_ADDRESS,
OS04A10_REG_VALUE_08BIT,
OS04A10_GROUP_UPDATE_START_DATA);
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_GAIN_LONG_H,
OS04A10_REG_AGAIN_LONG_H,
OS04A10_REG_VALUE_16BIT,
(l_a_gain << 4) & 0x1ff0);
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_DGAIN_LONG_H,
OS04A10_REG_VALUE_24BIT,
(l_d_gain << 6) & 0xfffc0);
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_EXP_LONG_H,
OS04A10_REG_VALUE_16BIT,
l_exp_time);
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_GAIN_MID_H,
OS04A10_REG_AGAIN_MID_H,
OS04A10_REG_VALUE_16BIT,
(m_a_gain << 4) & 0x1ff0);
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_DGAIN_MID_H,
OS04A10_REG_VALUE_24BIT,
(m_d_gain << 6) & 0xfffc0);
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_EXP_MID_H,
OS04A10_REG_VALUE_16BIT,
@@ -1236,13 +1258,17 @@ static int os04a10_set_hdrae(struct os04a10 *os04a10,
if (os04a10->cur_mode->hdr_mode == HDR_X3) {
//3 stagger
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_GAIN_VS_H,
OS04A10_REG_AGAIN_VS_H,
OS04A10_REG_VALUE_16BIT,
(s_a_gain << 4) & 0x1ff0);
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_EXP_VS_H,
OS04A10_REG_VALUE_16BIT,
s_exp_time);
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_DGAIN_VS_H,
OS04A10_REG_VALUE_24BIT,
(s_d_gain << 6) & 0xfffc0);
}
ret |= os04a10_write_reg(os04a10->client,
OS04A10_GROUP_UPDATE_ADDRESS,
@@ -1395,6 +1421,13 @@ static int __os04a10_start_stream(struct os04a10 *os04a10)
{
int ret;
ret = os04a10_write_array(os04a10->client, os04a10_global_regs);
if (ret) {
dev_err(&os04a10->client->dev,
"could not set init registers\n");
return ret;
}
ret = os04a10_write_array(os04a10->client, os04a10->cur_mode->reg_list);
if (ret)
return ret;
@@ -1480,12 +1513,11 @@ static int os04a10_s_power(struct v4l2_subdev *sd, int on)
goto unlock_and_return;
}
ret = os04a10_write_array(os04a10->client, os04a10_global_regs);
if (ret) {
v4l2_err(sd, "could not set init registers\n");
pm_runtime_put_noidle(&client->dev);
goto unlock_and_return;
}
ret |= os04a10_write_reg(os04a10->client,
OS04A10_SOFTWARE_RESET_REG,
OS04A10_REG_VALUE_08BIT,
0x01);
usleep_range(100, 200);
os04a10->power_on = true;
} else {
@@ -1542,7 +1574,7 @@ static int __os04a10_power_on(struct os04a10 *os04a10)
usleep_range(500, 1000);
if (!IS_ERR(os04a10->pwdn_gpio))
gpiod_set_value_cansleep(os04a10->pwdn_gpio, 1);
usleep_range(6000, 8000);
usleep_range(12000, 16000);
/* 8192 cycles prior to first SCCB transaction */
delay_us = os04a10_cal_delay(8192);
usleep_range(delay_us, delay_us * 2);
@@ -1680,6 +1712,7 @@ static int os04a10_set_ctrl(struct v4l2_ctrl *ctrl)
struct i2c_client *client = os04a10->client;
s64 max;
int ret = 0;
u32 again, dgain;
/* Propagate change of current control to all related controls */
switch (ctrl->id) {
@@ -1706,10 +1739,21 @@ static int os04a10_set_ctrl(struct v4l2_ctrl *ctrl)
ctrl->val);
break;
case V4L2_CID_ANALOGUE_GAIN:
if (ctrl->val > 248) {
dgain = ctrl->val * 1024 / 248;
again = 248;
} else {
dgain = 1024;
again = ctrl->val;
}
ret = os04a10_write_reg(os04a10->client,
OS04A10_REG_GAIN_LONG_H,
OS04A10_REG_AGAIN_LONG_H,
OS04A10_REG_VALUE_16BIT,
(ctrl->val << 4) & 0x1ff0);
(again << 4) & 0x1ff0);
ret |= os04a10_write_reg(os04a10->client,
OS04A10_REG_DGAIN_LONG_H,
OS04A10_REG_VALUE_24BIT,
(dgain << 6) & 0xfffc0);
dev_dbg(&client->dev, "set analog gain 0x%x\n",
ctrl->val);
break;