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
4143static 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
143166static 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
212236static 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
231256static 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