mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
media: i2c: sc132gs fixes some error
1.fixes exposure range 2.add digital again support 3.update init setting 4.fixes testpattern operation error Change-Id: I8f6060965cfc994e555a169e437e106803970470 Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
This commit is contained in:
@@ -50,21 +50,23 @@
|
||||
#define SC132GS_MODE_SW_STANDBY 0x0
|
||||
#define SC132GS_MODE_STREAMING BIT(0)
|
||||
|
||||
#define SC132GS_REG_EXPOSURE 0x3e01
|
||||
#define SC132GS_EXPOSURE_MIN 6
|
||||
#define SC132GS_REG_EXPOSURE 0x3e00
|
||||
#define SC132GS_EXPOSURE_MIN 1
|
||||
#define SC132GS_EXPOSURE_STEP 1
|
||||
#define SC132GS_VTS_MAX 0xffff
|
||||
|
||||
#define SC132GS_REG_COARSE_AGAIN 0x3e08
|
||||
#define SC132GS_REG_FINE_AGAIN 0x3e09
|
||||
#define SC132GS_REG_COARSE_DGAIN 0x3e06
|
||||
#define SC132GS_REG_FINE_DGAIN 0x3e07
|
||||
|
||||
#define ANALOG_GAIN_MIN 0x20
|
||||
#define ANALOG_GAIN_MAX 0x391
|
||||
#define ANALOG_GAIN_MAX 0x6c80
|
||||
#define ANALOG_GAIN_STEP 1
|
||||
#define ANALOG_GAIN_DEFAULT 0x20
|
||||
|
||||
#define SC132GS_REG_TEST_PATTERN 0x4501
|
||||
#define SC132GS_TEST_PATTERN_ENABLE 0xcc
|
||||
#define SC132GS_TEST_PATTERN_DISABLE 0xc4
|
||||
#define SC132GS_TEST_PATTERN_BIT_MASK BIT(3)
|
||||
|
||||
#define SC132GS_REG_VTS 0x320e
|
||||
|
||||
@@ -285,18 +287,18 @@ static const struct regval sc132gs_2lane_10bit_regs[] = {
|
||||
{0x3018, 0x32},
|
||||
{0x3019, 0x0c},
|
||||
{0x301a, 0xb4},
|
||||
{0x3031, 0x0a},
|
||||
{0x301f, 0x51},
|
||||
{0x3032, 0x60},
|
||||
{0x3038, 0x44},
|
||||
{0x3207, 0x17},
|
||||
{0x320c, 0x05},
|
||||
{0x320d, 0xdc},
|
||||
{0x320e, 0x09},
|
||||
{0x320f, 0x60},
|
||||
{0x320c, 0x02},
|
||||
{0x320d, 0xee},
|
||||
{0x320e, 0x05},
|
||||
{0x320f, 0x78},
|
||||
{0x3250, 0xcc},
|
||||
{0x3251, 0x02},
|
||||
{0x3252, 0x09},
|
||||
{0x3253, 0x5b},
|
||||
{0x3252, 0x05},
|
||||
{0x3253, 0x73},
|
||||
{0x3254, 0x05},
|
||||
{0x3255, 0x3b},
|
||||
{0x3306, 0x78},
|
||||
@@ -331,18 +333,22 @@ static const struct regval sc132gs_2lane_10bit_regs[] = {
|
||||
{0x363b, 0x48},
|
||||
{0x363c, 0x83},
|
||||
{0x363d, 0x10},
|
||||
{0x36ea, 0x38},
|
||||
{0x36fa, 0x25},
|
||||
{0x36fb, 0x05},
|
||||
{0x36fd, 0x04},
|
||||
{0x36ea, 0x36},
|
||||
{0x36eb, 0x04},
|
||||
{0x36ec, 0x13},
|
||||
{0x36ed, 0x24},
|
||||
{0x36fa, 0x2b},
|
||||
{0x36fb, 0x1b},
|
||||
{0x36fc, 0x11},
|
||||
{0x36fd, 0x34},
|
||||
{0x3900, 0x11},
|
||||
{0x3901, 0x05},
|
||||
{0x3902, 0xc5},
|
||||
{0x3904, 0x04},
|
||||
{0x3908, 0x91},
|
||||
{0x391e, 0x00},
|
||||
{0x3e01, 0x11},
|
||||
{0x3e02, 0x20},
|
||||
{0x3e01, 0x4e},
|
||||
{0x3e02, 0xc0},
|
||||
{0x3e09, 0x20},
|
||||
{0x3e0e, 0xd2},
|
||||
{0x3e14, 0xb0},
|
||||
@@ -350,7 +356,7 @@ static const struct regval sc132gs_2lane_10bit_regs[] = {
|
||||
{0x3e26, 0x20},
|
||||
{0x4418, 0x38},
|
||||
{0x4503, 0x10},
|
||||
{0x4837, 0x21},
|
||||
{0x4837, 0x35},
|
||||
{0x5000, 0x0e},
|
||||
{0x540c, 0x51},
|
||||
{0x550f, 0x38},
|
||||
@@ -381,8 +387,13 @@ static const struct regval sc132gs_2lane_10bit_regs[] = {
|
||||
//{0x3221, ((0x3 << 1)|(0x3 << 5))},
|
||||
|
||||
//PLL set
|
||||
{0x36e9, 0x20},
|
||||
{0x36f9, 0x24},
|
||||
{0x36e9, 0x54},
|
||||
{0x36f9, 0x50},
|
||||
{0x0100, 0x01},
|
||||
|
||||
//gain >= 2
|
||||
{0x33fa, 0x02},
|
||||
{0x3317, 0x14},
|
||||
|
||||
{REG_NULL, 0x00},
|
||||
};
|
||||
@@ -395,14 +406,14 @@ static const struct sc132gs_mode supported_modes[] = {
|
||||
.numerator = 10000,
|
||||
.denominator = 300000,
|
||||
},
|
||||
.exp_def = 0x0148,
|
||||
.hts_def = 0x06a0,
|
||||
.vts_def = 0x084a,
|
||||
.exp_def = 0x04ec,
|
||||
.hts_def = 0x02ee*2,
|
||||
.vts_def = 0x0578,
|
||||
.link_freq_index = LINK_FREQ_180M_INDEX,
|
||||
.pixel_rate = PIXEL_RATE_WITH_180M,
|
||||
.reg_list = sc132gs_2lane_10bit_regs,
|
||||
.lanes = 2,
|
||||
.bus_fmt = MEDIA_BUS_FMT_Y10_1X10,
|
||||
.bus_fmt = MEDIA_BUS_FMT_SBGGR10_1X10,
|
||||
},
|
||||
|
||||
{
|
||||
@@ -644,15 +655,19 @@ static int sc132gs_enum_frame_sizes(struct v4l2_subdev *sd,
|
||||
|
||||
static int sc132gs_enable_test_pattern(struct sc132gs *sc132gs, u32 pattern)
|
||||
{
|
||||
u32 val;
|
||||
u32 val = 0;
|
||||
int ret = 0;
|
||||
|
||||
ret = sc132gs_read_reg(sc132gs->client, SC132GS_REG_TEST_PATTERN,
|
||||
SC132GS_REG_VALUE_08BIT, &val);
|
||||
if (pattern)
|
||||
val = (pattern - 1) | SC132GS_TEST_PATTERN_ENABLE;
|
||||
val |= SC132GS_TEST_PATTERN_BIT_MASK;
|
||||
else
|
||||
val = SC132GS_TEST_PATTERN_DISABLE;
|
||||
val &= ~SC132GS_TEST_PATTERN_BIT_MASK;
|
||||
|
||||
return sc132gs_write_reg(sc132gs->client, SC132GS_REG_TEST_PATTERN,
|
||||
SC132GS_REG_VALUE_08BIT, val);
|
||||
ret |= sc132gs_write_reg(sc132gs->client, SC132GS_REG_TEST_PATTERN,
|
||||
SC132GS_REG_VALUE_08BIT, val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sc132gs_get_module_inf(struct sc132gs *sc132gs,
|
||||
@@ -737,50 +752,75 @@ static long sc132gs_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
static int sc132gs_set_ctrl_gain(struct sc132gs *sc132gs, u32 a_gain)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 coarse_again, fine_again, fine_again_reg, coarse_again_reg;
|
||||
u32 fine_again_reg, coarse_again_reg, fine_dgain_reg, coarse_dgain_reg;
|
||||
|
||||
if (a_gain < 0x20)
|
||||
a_gain = 0x20;
|
||||
if (a_gain > 0x391)
|
||||
a_gain = 0x391;
|
||||
if (a_gain > 0x6c80)
|
||||
a_gain = 0x6c80;
|
||||
|
||||
if (a_gain < 0x3a) {/*1x~1.813*/
|
||||
fine_again = a_gain;
|
||||
coarse_again = 0x03;
|
||||
fine_again_reg = fine_again & 0x3f;
|
||||
coarse_again_reg = coarse_again & 0x3F;
|
||||
if (fine_again_reg >= 0x39)
|
||||
fine_again_reg = 0x39;
|
||||
} else if (a_gain < 0x72) {/*1.813~3.568x*/
|
||||
fine_again = (a_gain - 0x3a) * 1000 / 1755 + 0x20;
|
||||
coarse_again = 0x23;
|
||||
if (fine_again > 0x3f)
|
||||
fine_again = 0x3f;
|
||||
fine_again_reg = fine_again & 0x3f;
|
||||
coarse_again_reg = coarse_again & 0x3F;
|
||||
fine_again_reg = a_gain;
|
||||
coarse_again_reg = 0x03;
|
||||
fine_dgain_reg = 0x80;
|
||||
coarse_dgain_reg = 0x00;
|
||||
} else if (a_gain < 0x74) {/*1.813~3.568x*/
|
||||
fine_again_reg = a_gain * 0x20 / 0x3a;
|
||||
coarse_again_reg = 0x23;
|
||||
fine_dgain_reg = 0x80;
|
||||
coarse_dgain_reg = 0x00;
|
||||
} else if (a_gain < 0xe8) { /*3.568x~7.250x*/
|
||||
fine_again = (a_gain - 0x72) * 1000 / 3682 + 0x20;
|
||||
coarse_again = 0x27;
|
||||
if (fine_again > 0x3f)
|
||||
fine_again = 0x3f;
|
||||
fine_again_reg = fine_again & 0x3f;
|
||||
coarse_again_reg = coarse_again & 0x3F;
|
||||
fine_again_reg = a_gain * 0x20 / 0x74;
|
||||
coarse_again_reg = 0x27;
|
||||
fine_dgain_reg = 0x80;
|
||||
coarse_dgain_reg = 0x00;
|
||||
} else if (a_gain < 0x1d0) { /*7.250x~14.5x*/
|
||||
fine_again = (a_gain - 0xe8) * 100 / 725 + 0x20;
|
||||
coarse_again = 0x2f;
|
||||
if (fine_again > 0x3f)
|
||||
fine_again = 0x3f;
|
||||
fine_again_reg = fine_again & 0x3f;
|
||||
coarse_again_reg = coarse_again & 0x3F;
|
||||
} else { /*14.5x~28.547*/
|
||||
fine_again = (a_gain - 0x1d0) * 1000 / 14047 + 0x20;
|
||||
coarse_again = 0x3f;
|
||||
if (fine_again > 0x3f)
|
||||
fine_again = 0x3f;
|
||||
fine_again_reg = fine_again & 0x3f;
|
||||
coarse_again_reg = coarse_again & 0x3F;
|
||||
fine_again_reg = a_gain * 0x20 / 0xe8;
|
||||
coarse_again_reg = 0x2f;
|
||||
fine_dgain_reg = 0x80;
|
||||
coarse_dgain_reg = 0x00;
|
||||
} else if (a_gain < 0x3a0) { /*14.5x~28.547x*/
|
||||
fine_again_reg = a_gain * 0x20 / 0x1d0;
|
||||
coarse_again_reg = 0x3f;
|
||||
fine_dgain_reg = 0x80;
|
||||
coarse_dgain_reg = 0x00;
|
||||
} else if (a_gain < 0x740) { /*again:28.547x, dgain: 1x~2x*/
|
||||
fine_again_reg = 0x3f ;
|
||||
coarse_again_reg = 0x3f;
|
||||
fine_dgain_reg = a_gain * 0x8 / 0x3a;
|
||||
if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80;
|
||||
else fine_dgain_reg = fine_dgain_reg & 0xfc;
|
||||
coarse_dgain_reg = 0x00;
|
||||
} else if (a_gain < 0xe80) { /*again:28.547x, dgain: 2x~4x*/
|
||||
fine_again_reg = 0x3f ;
|
||||
coarse_again_reg = 0x3f;
|
||||
fine_dgain_reg = a_gain * 0x8 / 0x74;
|
||||
if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80;
|
||||
else fine_dgain_reg = fine_dgain_reg & 0xfc;
|
||||
coarse_dgain_reg = 0x01;
|
||||
} else if (a_gain < 0x1d00) { /*again:28.547x, dgain: 4x~8x*/
|
||||
fine_again_reg = 0x3f ;
|
||||
coarse_again_reg = 0x3f;
|
||||
fine_dgain_reg = a_gain * 0x8 / 0xe8;
|
||||
if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80;
|
||||
else fine_dgain_reg = fine_dgain_reg & 0xfc;
|
||||
coarse_dgain_reg = 0x03;
|
||||
} else if (a_gain < 0x3a00) { /*again:28.547x, dgain: 8x~16x*/
|
||||
fine_again_reg = 0x3f ;
|
||||
coarse_again_reg = 0x3f;
|
||||
fine_dgain_reg = a_gain * 0x8 / 0x1d0;
|
||||
if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80;
|
||||
else fine_dgain_reg = fine_dgain_reg & 0xfc;
|
||||
coarse_dgain_reg = 0x07;
|
||||
} else { /*again:28.547x, dgain: 16x~31.5x*/
|
||||
fine_again_reg = 0x3f ;
|
||||
coarse_again_reg = 0x3f;
|
||||
fine_dgain_reg = a_gain * 0x8 / 0x3a0;
|
||||
if(fine_dgain_reg < 0x80) fine_dgain_reg =0x80;
|
||||
else fine_dgain_reg = fine_dgain_reg & 0xfc;
|
||||
coarse_dgain_reg = 0x0f;
|
||||
}
|
||||
ret |= sc132gs_write_reg(sc132gs->client,
|
||||
ret = sc132gs_write_reg(sc132gs->client,
|
||||
SC132GS_REG_COARSE_AGAIN,
|
||||
SC132GS_REG_VALUE_08BIT,
|
||||
coarse_again_reg);
|
||||
@@ -788,6 +828,34 @@ static int sc132gs_set_ctrl_gain(struct sc132gs *sc132gs, u32 a_gain)
|
||||
SC132GS_REG_FINE_AGAIN,
|
||||
SC132GS_REG_VALUE_08BIT,
|
||||
fine_again_reg);
|
||||
ret |= sc132gs_write_reg(sc132gs->client,
|
||||
SC132GS_REG_COARSE_DGAIN,
|
||||
SC132GS_REG_VALUE_08BIT,
|
||||
coarse_dgain_reg);
|
||||
ret |= sc132gs_write_reg(sc132gs->client,
|
||||
SC132GS_REG_FINE_DGAIN,
|
||||
SC132GS_REG_VALUE_08BIT,
|
||||
fine_dgain_reg);
|
||||
if (a_gain < 0x40) {
|
||||
ret |= sc132gs_write_reg(sc132gs->client,
|
||||
0x33fa,
|
||||
SC132GS_REG_VALUE_08BIT,
|
||||
0x01);
|
||||
ret |= sc132gs_write_reg(sc132gs->client,
|
||||
0x3317,
|
||||
SC132GS_REG_VALUE_08BIT,
|
||||
0xf0);
|
||||
} else {
|
||||
ret |= sc132gs_write_reg(sc132gs->client,
|
||||
0x33fa,
|
||||
SC132GS_REG_VALUE_08BIT,
|
||||
0x02);
|
||||
ret |= sc132gs_write_reg(sc132gs->client,
|
||||
0x3317,
|
||||
SC132GS_REG_VALUE_08BIT,
|
||||
0x0a);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1110,7 +1178,7 @@ static int sc132gs_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
switch (ctrl->id) {
|
||||
case V4L2_CID_VBLANK:
|
||||
/* Update max exposure while meeting expected vblanking */
|
||||
max = sc132gs->cur_mode->height + ctrl->val - 6;
|
||||
max = sc132gs->cur_mode->height + ctrl->val - 8;
|
||||
__v4l2_ctrl_modify_range(sc132gs->exposure,
|
||||
sc132gs->exposure->minimum, max,
|
||||
sc132gs->exposure->step,
|
||||
@@ -1125,10 +1193,13 @@ static int sc132gs_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
case V4L2_CID_EXPOSURE:
|
||||
/* 4 least significant bits of expsoure are fractional part */
|
||||
ret = sc132gs_write_reg(sc132gs->client, SC132GS_REG_EXPOSURE,
|
||||
SC132GS_REG_VALUE_16BIT, ctrl->val << 4);
|
||||
SC132GS_REG_VALUE_24BIT, ctrl->val << 4);
|
||||
|
||||
dev_dbg(&client->dev, "set exposure 0x%x \n",ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_ANALOGUE_GAIN:
|
||||
ret = sc132gs_set_ctrl_gain(sc132gs, ctrl->val);
|
||||
dev_dbg(&client->dev, "set gain 0x%x \n",ctrl->val);
|
||||
break;
|
||||
case V4L2_CID_VBLANK:
|
||||
ret = sc132gs_write_reg(sc132gs->client, SC132GS_REG_VTS,
|
||||
@@ -1136,8 +1207,8 @@ static int sc132gs_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
ctrl->val + sc132gs->cur_mode->height);
|
||||
if (!ret)
|
||||
sc132gs->cur_vts = ctrl->val + sc132gs->cur_mode->height;
|
||||
sc132gs_modify_fps_info(sc132gs);
|
||||
break;
|
||||
if (sc132gs->cur_vts != sc132gs->cur_mode->vts_def)
|
||||
sc132gs_modify_fps_info(sc132gs);
|
||||
break;
|
||||
case V4L2_CID_TEST_PATTERN:
|
||||
ret = sc132gs_enable_test_pattern(sc132gs, ctrl->val);
|
||||
@@ -1195,7 +1266,7 @@ static int sc132gs_initialize_controls(struct sc132gs *sc132gs)
|
||||
SC132GS_VTS_MAX - mode->height,
|
||||
1, vblank_def);
|
||||
|
||||
exposure_max = mode->vts_def - 6;
|
||||
exposure_max = mode->vts_def - 8;
|
||||
sc132gs->exposure = v4l2_ctrl_new_std(handler, &sc132gs_ctrl_ops,
|
||||
V4L2_CID_EXPOSURE, SC132GS_EXPOSURE_MIN,
|
||||
exposure_max, SC132GS_EXPOSURE_STEP,
|
||||
|
||||
Reference in New Issue
Block a user