From 39a7d2c580039727272ff25195ef4a01251a5111 Mon Sep 17 00:00:00 2001
From: ddl <ddl@rock-chips.com>
Date: Tue, 27 Nov 2012 15:33:19 +0800
Subject: [PATCH] camera: support ov2659 manual exposure in capture, and delete
 some invalidate printk in cif driver

---
 drivers/media/video/ov2659.c               | 260 ++++++++++++++++++++-
 drivers/media/video/rk30_camera_oneframe.c |  12 +-
 2 files changed, 263 insertions(+), 9 deletions(-)

diff --git a/drivers/media/video/ov2659.c b/drivers/media/video/ov2659.c
index 071f070b2404..0bd0f8647e5b 100755
--- a/drivers/media/video/ov2659.c
+++ b/drivers/media/video/ov2659.c
@@ -276,6 +276,7 @@ static struct reginfo sensor_init_data[] =
 	{0x5063, 0x69},
 	{0x3004, 0x20},
 		{0x0100, 0x01},
+
 	{0x0000, 0x00}
 };
 
@@ -451,6 +452,7 @@ static struct reginfo sensor_720p[]=
 /* 1600X1200 UXGA */
 static struct reginfo sensor_uxga[] =
 {
+#if 0
     {0x3800, 0x00},
 	{0x3801, 0x00},
 	{0x3802, 0x00},
@@ -496,6 +498,84 @@ static struct reginfo sensor_uxga[] =
 	{0x5002, 0x00},
 	{0x3005, 0x24},
 	{0x3004, 0x20},
+#else
+    //{0x3a00,OV2659ReadReg(0x3a00)&0xfb}, 
+    {0x3503,0x03}, 
+    //{0x3406,OV2659ReadReg(0x3406)|0x01}, 
+
+    {0x506e,0x44},	
+    {0x5064,0x08},	
+    {0x5065,0x10},
+    {0x5066,0x18},	// zenghaihui 20110920 16
+    {0x5067,0x10},
+    {0x506c,0x08},
+    {0x506d,0x10},	
+    {0x506f,0xa6},	
+    {0x5068,0x08},
+    {0x5069,0x10},	
+    {0x506a,0x08},
+    {0x506b,0x28},
+    {0x5084,0x14},//0c
+    {0x5085,0x3c},//34	
+    {0x5005,0x80}, 
+
+
+
+    {0x5066, 0x3c},         
+    {0x5067, 0x1a}, 
+    {0x506a, 0x0e},    
+    {0x506b, 0x2e},    
+
+    {0x3800, 0x00}, 
+    {0x3801, 0x00}, 
+    {0x3802, 0x00}, 
+    {0x3803, 0x00}, 
+    {0x3804, 0x06}, 
+    {0x3805, 0x5f}, 
+    {0x3806, 0x04}, 
+    {0x3807, 0xbb}, 
+    {0x3808, 0x06}, 
+    {0x3809, 0x40}, 
+    {0x380a, 0x04}, 
+    {0x380b, 0xb0}, 
+    {0x3811, 0x10}, 
+    {0x3813, 0x06}, 
+    {0x3814, 0x11}, 
+    {0x3815, 0x11}, 
+
+    {0x3623, 0x00}, 
+    {0x3634, 0x44}, 
+    {0x3701, 0x44}, 
+    {0x3208, 0xa2}, 
+    {0x3705, 0x18},      
+    {0x3820, 0x80}, 
+    {0x3821, 0x00}, 
+
+    {0x3003, 0x80},//10fps 
+    {0x3004, 0x20}, //10         
+    {0x3005, 0x18}, 
+    {0x3006, 0x0d}, 
+
+    {0x380c, 0x07}, 
+    {0x380d, 0x9f}, 
+    {0x380e, 0x04}, 
+    {0x380f, 0xd0}, 
+
+    {0x370a, 0x12}, 
+    {0x4608, 0x00}, 
+    {0x4609, 0x80}, 
+    {0x5002, 0x00}, 
+
+    {0x3a08, 0x00}, 
+    {0x3a09, 0x3e},//7b 
+    {0x3a0e, 0x13},//0a 
+
+    {0x3a0a, 0x00}, 
+    {0x3a0b, 0x3e},//7b                 
+    {0x3a0d, 0x13},//0a         
+
+    {0x4003, 0x88}, 
+#endif
 	{0x0000, 0x00}
 };
 
@@ -512,7 +592,7 @@ static struct reginfo sensor_xga[] =
 /* 800X600 SVGA*/
 static struct reginfo sensor_svga[] =
 {
-		{0x0100, 0x00},    //software sleep : Sensor vsync singal may not output if haven't sleep the sensor when transfer the array,
+	{0x0100, 0x00},    //software sleep : Sensor vsync singal may not output if haven't sleep the sensor when transfer the array,
 	{0x3800, 0x00},
 	{0x3801, 0x00},
 	{0x3802, 0x00},
@@ -558,7 +638,8 @@ static struct reginfo sensor_svga[] =
 	{0x5002, 0x10},
 	{0x3005, 0x18},
 	{0x3004, 0x20},
-		{0x0100, 0x01},		//software wake
+	{0x3503,0x00},
+	{0x0100, 0x01},		//software wake
 	{0x0000, 0x00}
 };
 
@@ -1273,11 +1354,25 @@ typedef struct sensor_info_priv_s
     unsigned int funmodule_state;
 } sensor_info_priv_t;
 
+struct sensor_parameter
+{
+	unsigned int PreviewDummyPixels;
+    unsigned int CaptureDummyPixels;
+	unsigned int preview_exposure;
+	unsigned short int preview_line_width;
+	unsigned short int preview_gain;
+
+	unsigned short int PreviewPclk;
+	unsigned short int CapturePclk;
+	char awb[6];
+};
+
 struct sensor
 {
     struct v4l2_subdev subdev;
     struct i2c_client *client;
     sensor_info_priv_t info_priv;
+    struct sensor_parameter parameter;
     int model;	/* V4L2_IDENT_OV* codes from v4l2-chip-ident.h */
 #if CONFIG_SENSOR_I2C_NOSCHED
 	atomic_t tasklock_cnt;
@@ -1467,6 +1562,165 @@ static int sensor_readchk_array(struct i2c_client *client, struct reginfo *regar
     return 0;
 }
 #endif
+
+static int sensor_parameter_record(struct i2c_client *client)
+{
+	u8 ret_l,ret_m,ret_h;
+	int tp_l,tp_m,tp_h;
+	struct sensor *sensor = to_sensor(client);
+
+    sensor_read(client,0x3a00, &ret_l);
+    sensor_write(client,0x3a00, ret_l&0xfb);
+
+	sensor_write(client,0x3503,0x07);	//stop AE/AG
+
+	sensor_read(client,0x3500,&ret_h);
+	sensor_read(client,0x3501, &ret_m);
+	sensor_read(client,0x3502, &ret_l);
+	tp_l = ret_l;
+	tp_m = ret_m;
+	tp_h = ret_h;
+    sensor->parameter.preview_exposure = ((tp_h<<12) & 0xF000) | ((tp_m<<4) & 0x0FF0) | ((tp_l>>4) & 0x0F);
+	
+	//Read back AGC Gain for preview
+	sensor_read(client,0x350b, &ret_l);
+	sensor->parameter.preview_gain = ret_l;
+
+    sensor->parameter.CapturePclk = 24000000;
+    sensor->parameter.PreviewPclk = 24000000;
+    sensor->parameter.PreviewDummyPixels = 0;
+    sensor->parameter.CaptureDummyPixels = 0;
+	SENSOR_DG(" %s Read 0x350b=0x%02x  PreviewExposure:%d 0x3500=0x%02x  0x3501=0x%02x 0x3502=0x%02x \n",
+     SENSOR_NAME_STRING(), ret_l,sensor->parameter.preview_exposure,tp_h, tp_m, tp_l);
+	return 0;
+}
+#define OV2659_FULL_PERIOD_PIXEL_NUMS  (1940)  // default pixel#(w/o dummy pixels) in UXGA mode
+#define OV2659_FULL_PERIOD_LINE_NUMS   (1238)  // default line#(w/o dummy lines) in UXGA mode
+#define OV2659_PV_PERIOD_PIXEL_NUMS	  (970)  // default pixel#(w/o dummy pixels) in SVGA mode
+#define OV2659_PV_PERIOD_LINE_NUMS	  (618)   // default line#(w/o dummy lines) in SVGA mode
+
+/* SENSOR EXPOSURE LINE LIMITATION */
+#define OV2659_FULL_EXPOSURE_LIMITATION	  (1236)
+#define OV2659_PV_EXPOSURE_LIMITATION	  (618)
+
+// SENSOR UXGA SIZE
+#define OV2659_IMAGE_SENSOR_FULL_WIDTH	  (1600)
+#define OV2659_IMAGE_SENSOR_FULL_HEIGHT	  (1200)
+
+#define OV2659_FULL_GRAB_WIDTH				(OV2659_IMAGE_SENSOR_FULL_WIDTH - 16)
+#define OV2659_FULL_GRAB_HEIGHT				(OV2659_IMAGE_SENSOR_FULL_HEIGHT - 12)
+
+static void OV2659SetDummy(struct i2c_client *client,unsigned int dummy_pixels, unsigned int dummy_lines)
+{
+    unsigned char val;
+	unsigned int temp_reg1, temp_reg2;
+	unsigned int temp_reg, base_shutter = 0x9B;
+	
+	if (dummy_pixels > 0)
+	{
+		sensor_read(client,0x380D,&val);    // HTS[b7~b0]
+		temp_reg1 = val;
+		sensor_read(client,0x380C,&val);    // HTS[b15~b8]
+		temp_reg2 = val;
+		temp_reg = (temp_reg1 & 0xFF) | (temp_reg2 << 8);
+	
+		temp_reg += dummy_pixels;
+	
+		sensor_write(client,0x380D,(temp_reg&0xFF));         //HTS[7:0]
+		sensor_write(client,0x380C,((temp_reg&0xFF00)>>8));  //HTS[15:8]
+	}
+
+	if (dummy_lines > 0)
+	{
+		sensor_read(client,0x380F,&val);    // VTS[b7~b0]
+		temp_reg1 = val;
+		sensor_read(client,0x380E,&val);    // VTS[b15~b8]
+		temp_reg2 = val;
+		temp_reg = (temp_reg1 & 0xFF) | (temp_reg2 << 8);
+	
+		temp_reg += dummy_lines;
+	
+		sensor_write(client,0x380F,(temp_reg&0xFF));         //VTS[7:0]
+		sensor_write(client,0x380E,((temp_reg&0xFF00)>>8));  //VTS[15:8]
+	}
+}    /* OV2659_set_dummy */
+static void OV2659WriteShutter(struct i2c_client *client,bool is_preview, unsigned int shutter)
+{
+	unsigned int extra_exposure_lines = 0;
+
+    if (shutter < 1)
+	{
+		shutter = 1;
+	}
+	
+	if (is_preview) 
+	{
+		if (shutter <= OV2659_PV_EXPOSURE_LIMITATION) 
+		{
+			extra_exposure_lines = 0;
+		}
+		else 
+		{
+			extra_exposure_lines=shutter - OV2659_PV_EXPOSURE_LIMITATION;
+		}
+		
+	}
+	else 
+	{
+		if (shutter <= OV2659_FULL_EXPOSURE_LIMITATION) 
+		{
+			extra_exposure_lines = 0;
+		}
+		else 
+		{
+			extra_exposure_lines = shutter - OV2659_FULL_EXPOSURE_LIMITATION;
+		}
+		
+	}
+	
+	//AEC PK EXPOSURE
+	shutter*=16;
+	sensor_write(client,0x3502, (shutter & 0x00FF));           //AEC[7:0]
+	sensor_write(client,0x3501, ((shutter & 0x0FF00) >>8));  //AEC[15:8]
+	sensor_write(client,0x3500, ((shutter & 0xFF0000) >> 16));	
+	
+	if(extra_exposure_lines>0)
+	{
+		// set extra exposure line [aec add vts]
+		sensor_write(client,0x3507, extra_exposure_lines & 0xFF);          // EXVTS[b7~b0]
+		sensor_write(client,0x3506, (extra_exposure_lines & 0xFF00) >> 8); // EXVTS[b15~b8]
+	}
+	else
+	{
+		// set extra exposure line [aec add vts]
+		sensor_write(client,0x3507, 0x00);          // EXVTS[b7~b0]
+		sensor_write(client,0x3506, 0x00); // EXVTS[b15~b8]
+	}
+	
+}    /* OV2659_write_shutter */
+static int sensor_ae_transfer(struct i2c_client *client)
+{
+	unsigned int prev_line_len,cap_line_len,shutter;
+	struct sensor *sensor = to_sensor(client);
+
+    mdelay(100);
+    shutter = sensor->parameter.preview_exposure;
+
+    OV2659SetDummy(client,600,0);	
+	
+    prev_line_len = OV2659_PV_PERIOD_PIXEL_NUMS + sensor->parameter.PreviewDummyPixels;
+  	cap_line_len = OV2659_FULL_PERIOD_PIXEL_NUMS + sensor->parameter.CaptureDummyPixels;
+  	shutter = (shutter * sensor->parameter.CapturePclk) / sensor->parameter.PreviewPclk;
+  	shutter = (shutter * prev_line_len) / cap_line_len;
+ 	shutter*=2;
+
+    OV2659WriteShutter(client,0,shutter);
+    
+	
+	return 0;
+}
+
+
 static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd cmd, int on)
 {
 	struct soc_camera_link *icl = to_soc_camera_link(icd);
@@ -1981,6 +2235,7 @@ static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
     if ((int)winseqe_set_addr  != sensor->info_priv.winseqe_cur_addr) {
         #if CONFIG_SENSOR_Flash
         if (sensor_fmt_capturechk(sd,mf) == true) {      /* ddl@rock-chips.com : Capture */
+            sensor_parameter_record(client);
             if ((sensor->info_priv.flash == 1) || (sensor->info_priv.flash == 2)) {
                 sensor_ioctrl(icd, Sensor_Flash, Flash_On);
                 SENSOR_DG("%s flash on in capture!\n", SENSOR_NAME_STRING());
@@ -2009,6 +2264,7 @@ static int sensor_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
         sensor->info_priv.winseqe_cur_addr  = (int)winseqe_set_addr;
 
 		if (sensor_fmt_capturechk(sd,mf) == true) {				    /* ddl@rock-chips.com : Capture */
+            sensor_ae_transfer(client);
 			qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_EFFECT);
 			sensor_set_effect(icd, qctrl,sensor->info_priv.effect);
 			if (sensor->info_priv.whiteBalance != 0) {
diff --git a/drivers/media/video/rk30_camera_oneframe.c b/drivers/media/video/rk30_camera_oneframe.c
index 359340c36a5f..eed218f6bbb7 100755
--- a/drivers/media/video/rk30_camera_oneframe.c
+++ b/drivers/media/video/rk30_camera_oneframe.c
@@ -484,7 +484,6 @@ static int rk_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
 	else
 		bytes_per_line_host = soc_mbus_bytes_per_line(pcdev->host_width,
 					   icd->current_fmt->host_fmt);
-	printk("user code = %d,packing = %d",icd->current_fmt->code,fmt.packing);
     dev_dbg(&icd->dev, "count=%d, size=%d\n", *count, *size);
 
 	if (bytes_per_line_host < 0)
@@ -1818,11 +1817,10 @@ static void rk_camera_setup_format(struct soc_camera_device *icd, __u32 host_pix
     if((read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_PINGPONG)
 		||(read_cif_reg(pcdev->base,CIF_CIF_CTRL) & MODE_LINELOOP)) {
 	    BUG();	
-     } else{ // this is one frame mode
-		cif_crop = (rect->left+ (rect->top<<16));
-		cif_fs	= ((rect->width ) + (rect->height<<16));
-	 }
-	RKCAMERA_TR("%s..%d.. \n",__FUNCTION__,__LINE__);
+    } else{ // this is one frame mode
+	    cif_crop = (rect->left+ (rect->top<<16));
+	    cif_fs	= ((rect->width ) + (rect->height<<16));
+	}
 
 	write_cif_reg(pcdev->base,CIF_CIF_CROP, cif_crop);
 	write_cif_reg(pcdev->base,CIF_CIF_SET_SIZE, cif_fs);
@@ -1982,7 +1980,7 @@ static int rk_camera_set_fmt(struct soc_camera_device *icd,
 
 	usr_w = pix->width;
 	usr_h = pix->height;
-    RKCAMERA_TR("%s enter width:%d  height:%d\n",__FUNCTION__,usr_w,usr_h);
+    RKCAMERA_DG("%s enter width:%d  height:%d\n",__FUNCTION__,usr_w,usr_h);
     xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
     if (!xlate) {
         dev_err(dev, "Format %x not found\n", pix->pixelformat);
-- 
2.34.1