Skip to content

Commit 78bcfcc

Browse files
committed
add some settings to support 3A
Change-Id: Ib7216deb4000e4f6df8f1b2979007db72ef044cb Reviewed-on: https://tp-biosrd-v02/gerrit/82869 Reviewed-by: Jamess Huang(黃以民) <Jamess_Huang@asus.com> Tested-by: Jamess Huang(黃以民) <Jamess_Huang@asus.com>
1 parent 824183f commit 78bcfcc

1 file changed

Lines changed: 165 additions & 80 deletions

File tree

drivers/media/i2c/imx219.c

100644100755
Lines changed: 165 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,19 @@
2626
#define IMX219_TABLE_END 0xffff
2727
#define IMX219_ANALOGUE_GAIN_MULTIPLIER 256
2828
#define IMX219_ANALOGUE_GAIN_MIN (1 * IMX219_ANALOGUE_GAIN_MULTIPLIER)
29-
#define IMX219_ANALOGUE_GAIN_MAX (8 * IMX219_ANALOGUE_GAIN_MULTIPLIER)
29+
#define IMX219_ANALOGUE_GAIN_MAX (11 * IMX219_ANALOGUE_GAIN_MULTIPLIER)
3030
#define IMX219_ANALOGUE_GAIN_DEFAULT (2 * IMX219_ANALOGUE_GAIN_MULTIPLIER)
3131

3232
/* In dB*256 */
3333
#define IMX219_DIGITAL_GAIN_MIN 256
34-
#define IMX219_DIGITAL_GAIN_MAX 4095
34+
#define IMX219_DIGITAL_GAIN_MAX 43663
3535
#define IMX219_DIGITAL_GAIN_DEFAULT 256
3636

3737
#define IMX219_DIGITAL_EXPOSURE_MIN 0
3838
#define IMX219_DIGITAL_EXPOSURE_MAX 4095
39-
#define IMX219_DIGITAL_EXPOSURE_DEFAULT 256
39+
#define IMX219_DIGITAL_EXPOSURE_DEFAULT 1575
40+
41+
#define IMX219_EXP_LINES_MARGIN 4
4042

4143
static const s64 link_freq_menu_items[] = {
4244
456000000,
@@ -74,12 +76,22 @@ static const struct imx219_reg imx219_init_tab_3280_2464_21fps[] = {
7476
{0x0161, 0xC4}, /* FRM_LENGTH_A[7:0] */
7577
{0x0162, 0x0D}, /* LINE_LENGTH_A[15:8] */
7678
{0x0163, 0x78}, /* LINE_LENGTH_A[7:0] */
79+
{0x0260, 0x09}, /* FRM_LENGTH_B[15:8] */
80+
{0x0261, 0xC4}, /* FRM_LENGTH_B[7:0] */
81+
{0x0262, 0x0D}, /* LINE_LENGTH_B[15:8] */
82+
{0x0263, 0x78}, /* LINE_LENGTH_B[7:0] */
7783
{0x0170, 0x01}, /* X_ODD_INC_A[2:0] */
7884
{0x0171, 0x01}, /* Y_ODD_INC_A[2:0] */
85+
{0x0270, 0x01}, /* X_ODD_INC_B[2:0] */
86+
{0x0271, 0x01}, /* Y_ODD_INC_B[2:0] */
7987
{0x0174, 0x00}, /* BINNING_MODE_H_A */
8088
{0x0175, 0x00}, /* BINNING_MODE_V_A */
89+
{0x0274, 0x00}, /* BINNING_MODE_H_B */
90+
{0x0275, 0x00}, /* BINNING_MODE_V_B */
8191
{0x018C, 0x0A}, /* CSI_DATA_FORMAT_A[15:8] */
8292
{0x018D, 0x0A}, /* CSI_DATA_FORMAT_A[7:0] */
93+
{0x028C, 0x0A}, /* CSI_DATA_FORMAT_B[15:8] */
94+
{0x028D, 0x0A}, /* CSI_DATA_FORMAT_B[7:0] */
8395
{0x0301, 0x05}, /* VTPXCK_DIV */
8496
{0x0303, 0x01}, /* VTSYCK_DIV */
8597
{0x0304, 0x03}, /* PREPLLCK_VT_DIV[3:0] */
@@ -98,46 +110,57 @@ static const struct imx219_reg imx219_init_tab_3280_2464_21fps[] = {
98110
{IMX219_TABLE_END, 0x00}
99111
};
100112

101-
/* MCLK:24MHz 1920x1080 47.5fps MIPI LANE2 */
102-
static const struct imx219_reg imx219_init_tab_1920_1080_48fps[] = {
103-
{0x30EB, 0x05}, /* Access Code for address over 0x3000 */
104-
{0x30EB, 0x0C}, /* Access Code for address over 0x3000 */
105-
{0x300A, 0xFF}, /* Access Code for address over 0x3000 */
106-
{0x300B, 0xFF}, /* Access Code for address over 0x3000 */
107-
{0x30EB, 0x05}, /* Access Code for address over 0x3000 */
108-
{0x30EB, 0x09}, /* Access Code for address over 0x3000 */
109-
{0x0114, 0x01}, /* CSI_LANE_MODE[1:0} */
110-
{0x0128, 0x00}, /* DPHY_CNTRL */
111-
{0x012A, 0x18}, /* EXCK_FREQ[15:8] */
112-
{0x012B, 0x00}, /* EXCK_FREQ[7:0] */
113-
{0x015A, 0x03}, /* INTEG TIME[15:8] */
114-
{0x015B, 0xE8}, /* INTEG TIME[7:0] */
115-
{0x0160, 0x04}, /* FRM_LENGTH_A[15:8] */
116-
{0x0161, 0x59}, /* FRM_LENGTH_A[7:0] */
117-
{0x0162, 0x0D}, /* LINE_LENGTH_A[15:8] */
118-
{0x0163, 0x78}, /* LINE_LENGTH_A[7:0] */
119-
{0x0170, 0x01}, /* X_ODD_INC_A[2:0] */
120-
{0x0171, 0x01}, /* Y_ODD_INC_A[2:0] */
121-
{0x0174, 0x00}, /* BINNING_MODE_H_A */
122-
{0x0175, 0x00}, /* BINNING_MODE_V_A */
123-
{0x018C, 0x0A}, /* CSI_DATA_FORMAT_A[15:8] */
124-
{0x018D, 0x0A}, /* CSI_DATA_FORMAT_A[7:0] */
125-
{0x0301, 0x05}, /* VTPXCK_DIV */
126-
{0x0303, 0x01}, /* VTSYCK_DIV */
127-
{0x0304, 0x03}, /* PREPLLCK_VT_DIV[3:0] */
128-
{0x0305, 0x03}, /* PREPLLCK_OP_DIV[3:0] */
129-
{0x0306, 0x00}, /* PLL_VT_MPY[10:8] */
130-
{0x0307, 0x39}, /* PLL_VT_MPY[7:0] */
131-
{0x0309, 0x0A}, /* OPPXCK_DIV[4:0] */
132-
{0x030B, 0x01}, /* OPSYCK_DIV */
133-
{0x030C, 0x00}, /* PLL_OP_MPY[10:8] */
134-
{0x030D, 0x72}, /* PLL_OP_MPY[7:0] */
135-
{0x455E, 0x00}, /* CIS Tuning */
136-
{0x471E, 0x4B}, /* CIS Tuning */
137-
{0x4767, 0x0F}, /* CIS Tuning */
138-
{0x4750, 0x14}, /* CIS Tuning */
139-
{0x47B4, 0x14}, /* CIS Tuning */
140-
{IMX219_TABLE_END, 0x00}
113+
/* MCLK:24MHz 1920x1080 30fps MIPI LANE2 */
114+
static const struct imx219_reg imx219_init_tab_1920_1080_30fps[] = {
115+
{0x30EB,0x05},
116+
{0x30EB,0x0C},
117+
{0x300A,0xFF},
118+
{0x300B,0xFF},
119+
{0x30EB,0x05},
120+
{0x30EB,0x09},
121+
{0x0114,0x01},
122+
{0x0128,0x00},
123+
{0x012A,0x18},
124+
{0x012B,0x00},
125+
{0x0160,0x06},
126+
{0x0161,0xE6},
127+
{0x0162,0x0D},
128+
{0x0163,0x78},
129+
{0x0164,0x02},
130+
{0x0165,0xA8},
131+
{0x0166,0x0A},
132+
{0x0167,0x27},
133+
{0x0168,0x02},
134+
{0x0169,0xB4},
135+
{0x016A,0x06},
136+
{0x016B,0xEB},
137+
{0x016C,0x07},
138+
{0x016D,0x80},
139+
{0x016E,0x04},
140+
{0x016F,0x38},
141+
{0x0170,0x01},
142+
{0x0171,0x01},
143+
{0x0174,0x00},
144+
{0x0175,0x00},
145+
{0x018C,0x0A},
146+
{0x018D,0x0A},
147+
{0x0301,0x05},
148+
{0x0303,0x01},
149+
{0x0304,0x03},
150+
{0x0305,0x03},
151+
{0x0306,0x00},
152+
{0x0307,0x39},
153+
{0x0309,0x0A},
154+
{0x030B,0x01},
155+
{0x030C,0x00},
156+
{0x030D,0x72},
157+
{0x455E,0x00},
158+
{0x471E,0x4B},
159+
{0x4767,0x0F},
160+
{0x4750,0x14},
161+
{0x4540,0x00},
162+
{0x47B4,0x14},
163+
{IMX219_TABLE_END, 0x00}
141164
};
142165

143166
static const struct imx219_reg start[] = {
@@ -207,25 +230,27 @@ struct imx219 {
207230
struct v4l2_ctrl *vblank;
208231
struct v4l2_ctrl *pixel_rate;
209232
const struct imx219_mode *cur_mode;
233+
u16 cur_vts;
210234
};
211235

212236
static const struct imx219_mode supported_modes[] = {
237+
{
238+
.width = 1920,
239+
.height = 1080,
240+
.max_fps = 30,
241+
.hts_def = 0x0d78,
242+
//.hts_def = 0x0d78 - IMX219_EXP_LINES_MARGIN,
243+
.vts_def = 0x06E6,
244+
.reg_list = imx219_init_tab_1920_1080_30fps,
245+
},
213246
{
214247
.width = 3280,
215248
.height = 2464,
216249
.max_fps = 21,
217-
.hts_def = 0x0d78,
250+
.hts_def = 0x0d78 - IMX219_EXP_LINES_MARGIN,
218251
.vts_def = 0x09c4,
219252
.reg_list = imx219_init_tab_3280_2464_21fps,
220253
},
221-
{
222-
.width = 1920,
223-
.height = 1080,
224-
.max_fps = 48,
225-
.hts_def = 0x0d78,
226-
.vts_def = 0x0459,
227-
.reg_list = imx219_init_tab_1920_1080_48fps,
228-
},
229254
};
230255

231256
static struct imx219 *to_imx219(const struct i2c_client *client)
@@ -314,12 +339,12 @@ static int imx219_s_stream(struct v4l2_subdev *sd, int enable)
314339
/* Handle crop */
315340
ret = reg_write(client, 0x0164, priv->crop_rect.left >> 8);
316341
ret |= reg_write(client, 0x0165, priv->crop_rect.left & 0xff);
317-
ret |= reg_write(client, 0x0166, (priv->crop_rect.width - 1) >> 8);
318-
ret |= reg_write(client, 0x0167, (priv->crop_rect.width - 1) & 0xff);
342+
ret |= reg_write(client, 0x0166, (priv->crop_rect.left + priv->crop_rect.width - 1) >> 8);
343+
ret |= reg_write(client, 0x0167, (priv->crop_rect.left + priv->crop_rect.width - 1) & 0xff);
319344
ret |= reg_write(client, 0x0168, priv->crop_rect.top >> 8);
320345
ret |= reg_write(client, 0x0169, priv->crop_rect.top & 0xff);
321-
ret |= reg_write(client, 0x016A, (priv->crop_rect.height - 1) >> 8);
322-
ret |= reg_write(client, 0x016B, (priv->crop_rect.height - 1) & 0xff);
346+
ret |= reg_write(client, 0x016A, (priv->crop_rect.top + priv->crop_rect.height - 1) >> 8);
347+
ret |= reg_write(client, 0x016B, (priv->crop_rect.top + priv->crop_rect.height - 1) & 0xff);
323348
ret |= reg_write(client, 0x016C, priv->crop_rect.width >> 8);
324349
ret |= reg_write(client, 0x016D, priv->crop_rect.width & 0xff);
325350
ret |= reg_write(client, 0x016E, priv->crop_rect.height >> 8);
@@ -371,6 +396,7 @@ static int imx219_s_stream(struct v4l2_subdev *sd, int enable)
371396
ret |= reg_write(client, 0x0601, 0x00);
372397
}
373398

399+
priv->cur_vts = priv->cur_mode->vts_def - IMX219_EXP_LINES_MARGIN;
374400
if (ret)
375401
return ret;
376402

@@ -476,7 +502,10 @@ static int imx219_s_ctrl(struct v4l2_ctrl *ctrl)
476502
container_of(ctrl->handler, struct imx219, ctrl_handler);
477503
struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
478504
u8 reg;
479-
int ret;
505+
int ret = 0;
506+
u16 gain = 256;
507+
u16 a_gain = 256;
508+
u16 d_gain = 1;
480509

481510
switch (ctrl->id) {
482511
case V4L2_CID_HFLIP:
@@ -486,37 +515,88 @@ static int imx219_s_ctrl(struct v4l2_ctrl *ctrl)
486515
priv->vflip = ctrl->val;
487516
break;
488517
case V4L2_CID_ANALOGUE_GAIN:
518+
case V4L2_CID_GAIN:
489519
/*
490-
* Register value goes from 0 to 224, and the analog gain
491-
* setting is 256 / (256 - reg). This results in a total gain
492-
* of 1.0f to 8.0f. We multiply the control setting by some
493-
* big number IMX219_ANALOGUE_GAIN_MULTIPLIER to make use of
494-
* the full resolution of this register.
495-
*/
496-
priv->analogue_gain =
497-
256 - ((256 * IMX219_ANALOGUE_GAIN_MULTIPLIER) / ctrl->val);
498-
ret = reg_write(client, 0x0157, priv->analogue_gain);
520+
* hal transfer (gain * 256) to kernel
521+
* than devide into analog gain & digital gain in kernel
522+
*/
523+
524+
gain = ctrl->val;
525+
if(gain < 256)
526+
gain = 256;
527+
528+
if(gain > 43663)
529+
gain = 43663;
530+
531+
if(gain >= 256 && gain <= 2728){
532+
a_gain = gain;
533+
d_gain = 1*256;
534+
}else{
535+
a_gain = 2728;
536+
d_gain = (gain*256) / a_gain;
537+
}
499538

500-
return ret;
501-
case V4L2_CID_GAIN:
502539
/*
503-
* Register value goes from 256 to 4095, and the digital gain
504-
* setting is reg / 256. This results in a total gain of 0dB
505-
* to 24dB.
540+
* Analog gain, reg range[0, 232], gain value[1, 10.66]
541+
* reg = 256 - 256/again
542+
* a_gain here is 256 multify
543+
* so the reg = 256 - 256*256 /a_gain
544+
*/
545+
priv->analogue_gain = (256 - (256*256)/a_gain);
546+
if(priv->analogue_gain < 0)
547+
priv->analogue_gain = 0;
548+
if(priv->analogue_gain > 232)
549+
priv->analogue_gain = 232;
550+
551+
/*
552+
* Digital gain, reg range[256, 4095], gain rage[1, 16]
553+
* reg = dgain * 256
506554
*/
507-
priv->digital_gain = ctrl->val;
508-
ret = reg_write(client, 0x0158, priv->digital_gain >> 8);
555+
priv->digital_gain = d_gain;
556+
if(priv->digital_gain < 256)
557+
priv->digital_gain = 256;
558+
if(priv->digital_gain > 4095)
559+
priv->digital_gain = 4095;
560+
561+
/* for bank A and bank B switch
562+
* exposure time , gain, vts must change at the same time
563+
* so the exposure & gain can reflect at the same frame
564+
*/
565+
printk("oyyf gain: value:%u a_gain:%u 0x%x d_gain:%u 0x%x vts:0x%x\n",
566+
ctrl->val, a_gain, priv->analogue_gain,
567+
d_gain, priv->digital_gain, priv->cur_vts);
568+
569+
570+
ret = reg_write(client, 0x0157, priv->analogue_gain);
571+
ret |= reg_write(client, 0x0158, priv->digital_gain >> 8);
509572
ret |= reg_write(client, 0x0159, priv->digital_gain & 0xff);
510-
573+
511574
return ret;
512575
case V4L2_CID_EXPOSURE:
513576
priv->exposure_time = ctrl->val;
577+
printk("oyyf exposure: value:%u\n", ctrl->val);
578+
579+
/* To do: not same as 3A
580+
if(priv->exposure_time > priv->cur_vts)
581+
priv->exposure_time = priv->cur_vts;
582+
if(priv->exposure_time < 1)
583+
priv->exposure_time = 1;
584+
*/
585+
586+
printk("oyyf 00 exposure: value:%u\n", priv->exposure_time);
514587
ret = reg_write(client, 0x015a, priv->exposure_time >> 8);
515588
ret |= reg_write(client, 0x015b, priv->exposure_time & 0xff);
516-
517589
return ret;
518590
case V4L2_CID_TEST_PATTERN:
519591
return imx219_s_ctrl_test_pattern(ctrl);
592+
case V4L2_CID_VBLANK:
593+
if(ctrl->val < priv->cur_mode->vts_def)
594+
ctrl->val = priv->cur_mode->vts_def;
595+
if((ctrl->val - IMX219_EXP_LINES_MARGIN) != priv->cur_vts)
596+
priv->cur_vts = ctrl->val - IMX219_EXP_LINES_MARGIN;
597+
ret |= reg_write(client, 0x0160, ((priv->cur_vts>>8)&0xff));
598+
ret |= reg_write(client, 0x0161, (priv->cur_vts&0xff));
599+
return ret;
520600
default:
521601
return -EINVAL;
522602
}
@@ -596,8 +676,12 @@ static int imx219_set_fmt(struct v4l2_subdev *sd,
596676
pixel_rate, 1, pixel_rate);
597677

598678
/* reset crop window */
599-
priv->crop_rect.left = 0;
600-
priv->crop_rect.top = 0;
679+
priv->crop_rect.left = 1640 - (mode->width/2);
680+
if (priv->crop_rect.left < 0)
681+
priv->crop_rect.left = 0;
682+
priv->crop_rect.top = 1232 - (mode->height/2);
683+
if (priv->crop_rect.top < 0)
684+
priv->crop_rect.top = 0;
601685
priv->crop_rect.width = mode->width;
602686
priv->crop_rect.height = mode->height;
603687

@@ -802,6 +886,7 @@ static int imx219_probe(struct i2c_client *client,
802886
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
803887
int ret;
804888

889+
printk("[jcliao] imx219_probe \n");
805890
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
806891
dev_warn(&adapter->dev,
807892
"I2C-Adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
@@ -818,11 +903,11 @@ static int imx219_probe(struct i2c_client *client,
818903
return -EPROBE_DEFER;
819904
}
820905

821-
/* 3280 * 2464 by default */
906+
/* 1920 * 1080 by default */
822907
priv->cur_mode = &supported_modes[0];
823908

824-
priv->crop_rect.left = 0;
825-
priv->crop_rect.top = 0;
909+
priv->crop_rect.left = 680;
910+
priv->crop_rect.top = 692;
826911
priv->crop_rect.width = priv->cur_mode->width;
827912
priv->crop_rect.height = priv->cur_mode->height;
828913

0 commit comments

Comments
 (0)