camera: ov5640 add support touch focus
authorddl <ddl@rock-chips.com>
Fri, 16 Nov 2012 08:01:22 +0000 (16:01 +0800)
committerddl <ddl@rock-chips.com>
Fri, 16 Nov 2012 08:01:31 +0000 (16:01 +0800)
drivers/media/video/ov5640.c

index ab996b01caade3f95b629992c38d4a1d39256619..8bdbac5314a79b9121a88812a8abe86fc9d3b724 100755 (executable)
@@ -68,6 +68,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define CONFIG_SENSOR_Flip          0
 #ifdef CONFIG_OV5640_AUTOFOCUS
 #define CONFIG_SENSOR_Focus         1
+#define CONFIG_SENSOR_FocusCenterInCapture    0
 #include "ov5640_af_firmware.c"
 #else
 #define CONFIG_SENSOR_Focus         0
@@ -128,9 +129,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define STA_FOCUS_Reg          0x3029
 
 /* ov5640 VCM Command  */
-#define OverlayEn_Cmd     0x01
-#define OverlayDis_Cmd    0x02
-#define SingleFocus_Cmd   0x03
+
 #define ConstFocus_Cmd    0x04
 #define StepMode_Cmd      0x05
 #define PauseFocus_Cmd    0x06
@@ -138,12 +137,15 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define SetZone_Cmd       0x10
 #define UpdateZone_Cmd    0x12
 #define SetMotor_Cmd      0x20
+#define SingleFocus_Cmd             0x03
+#define GetFocusResult_Cmd                 0x07
+#define ReleaseFocus_Cmd            0x08
+#define ZoneRelaunch_Cmd               0x12
+#define DefaultZoneConfig_Cmd       0x80
+#define TouchZoneConfig_Cmd         0x81
+#define CustomZoneConfig_Cmd        0x8f
 
 
-#define Zone_configuration_Cmd         0x12
-#define Trig_autofocus_Cmd             0x03
-#define Get_focus_result_Cmd           0x07
-
 /* ov5640 Focus State */
 //#define S_FIRWRE             0xFF            /*Firmware is downloaded and not run*/
 #define S_STARTUP              0x7e            /*Firmware is initializing*/
@@ -1423,6 +1425,14 @@ static  struct v4l2_queryctrl sensor_controls[] =
         .default_value = 125,
     },*/
        {
+        .id            = V4L2_CID_FOCUSZONE,
+        .type          = V4L2_CTRL_TYPE_INTEGER,
+        .name          = "FocusZone Control",
+        .minimum       = -1,
+        .maximum       = 1,
+        .step          = 1,
+        .default_value = 0,
+    },{
         .id            = V4L2_CID_FOCUS_AUTO,
         .type          = V4L2_CTRL_TYPE_BOOLEAN,
         .name          = "Focus Control",
@@ -1529,6 +1539,7 @@ struct sensor_work
     enum sensor_wq_result result;
     bool wait;
     int var;    
+    int zone_center_pos[2];
 };
 
 typedef struct sensor_info_priv_s
@@ -1876,22 +1887,24 @@ static int sensor_af_cmdset(struct i2c_client *client, int cmd_main, struct af_c
        char read_tag=0xff,cnt;
 
        if (cmdinfo) {
-               if (cmdinfo->validate_bit & 0x80) {
-                       if (sensor_write(client, CMD_ACK_Reg, cmdinfo->cmd_tag)) {
-                               SENSOR_TR("%s write CMD_ACK_Reg(main:0x%x tag:0x%x) error!\n",SENSOR_NAME_STRING(),cmd_main,cmdinfo->cmd_tag);
-                               goto sensor_af_cmdset_err;
-                       }
-                       SENSOR_DG("%s write CMD_ACK_Reg(main:0x%x tag:0x%x) success!\n",SENSOR_NAME_STRING(),cmd_main,cmdinfo->cmd_tag);
-               }
-               for (i=0; i<4; i++) {
+        for (i=0; i<4; i++) {
                        if (cmdinfo->validate_bit & (1<<i)) {
-                               if (sensor_write(client, CMD_PARA0_Reg-i, cmdinfo->cmd_para[i])) {
+                               if (sensor_write(client, CMD_PARA0_Reg+i, cmdinfo->cmd_para[i])) {
                                        SENSOR_TR("%s write CMD_PARA_Reg(main:0x%x para%d:0x%x) error!\n",SENSOR_NAME_STRING(),cmd_main,i,cmdinfo->cmd_para[i]);
                                        goto sensor_af_cmdset_err;
                                }
                                SENSOR_DG("%s write CMD_PARA_Reg(main:0x%x para%d:0x%x) success!\n",SENSOR_NAME_STRING(),cmd_main,i,cmdinfo->cmd_para[i]);
                        }
                }
+    
+               if (cmdinfo->validate_bit & 0x80) {
+                       if (sensor_write(client, CMD_ACK_Reg, cmdinfo->cmd_tag)) {
+                               SENSOR_TR("%s write CMD_ACK_Reg(main:0x%x tag:0x%x) error!\n",SENSOR_NAME_STRING(),cmd_main,cmdinfo->cmd_tag);
+                               goto sensor_af_cmdset_err;
+                       }
+                       SENSOR_DG("%s write CMD_ACK_Reg(main:0x%x tag:0x%x) success!\n",SENSOR_NAME_STRING(),cmd_main,cmdinfo->cmd_tag);
+               }
+               
        } else {
                if (sensor_write(client, CMD_ACK_Reg, 0xff)) {
                        SENSOR_TR("%s write CMD_ACK_Reg(main:0x%x no tag) error!\n",SENSOR_NAME_STRING(),cmd_main);
@@ -1952,13 +1965,42 @@ static int sensor_af_idlechk(struct i2c_client *client)
 sensor_af_idlechk_end:
        return ret;
 }
+static int sensor_af_touch_zone(struct i2c_client *client, int *zone_center_pos)
+{
+       int ret = 0;
+       struct af_cmdinfo cmdinfo;
 
+    cmdinfo.cmd_tag = 0x01;
+       cmdinfo.validate_bit = 0x83;
+    if (zone_center_pos[0]<=8)
+        cmdinfo.cmd_para[0] = 0;
+    else if ((zone_center_pos[0]>8) && (zone_center_pos[0]<64))
+        cmdinfo.cmd_para[0] = zone_center_pos[0]-8;
+    else 
+        cmdinfo.cmd_para[0] = 64; 
+    
+    if (zone_center_pos[1]<=6)
+        cmdinfo.cmd_para[1] = 0;
+    else if ((zone_center_pos[1]>6) && (zone_center_pos[1]<48))
+        cmdinfo.cmd_para[1] = zone_center_pos[1]-6;
+    else 
+        cmdinfo.cmd_para[1] = 48;
+    
+    ret = sensor_af_cmdset(client, TouchZoneConfig_Cmd, &cmdinfo);
+       if(0 != ret) {
+               SENSOR_TR("%s touch zone config error!\n",SENSOR_NAME_STRING());
+               ret = -1;
+               goto sensor_af_zone_end;
+       }    
+sensor_af_zone_end:
+    return ret;
+}
 static int sensor_af_single(struct i2c_client *client)
 {
        int ret = 0;
        char state,cnt;
        struct af_cmdinfo cmdinfo;
-
+    
        cmdinfo.cmd_tag = 0x01;
        cmdinfo.validate_bit = 0x80;
        ret = sensor_af_cmdset(client, SingleFocus_Cmd, &cmdinfo);
@@ -2109,7 +2151,10 @@ static void sensor_af_workqueue(struct work_struct *work)
             break;
         }
         case WqCmd_af_single:
-        {
+        {      
+            if ((sensor_work->zone_center_pos[0] >=0) && (sensor_work->zone_center_pos[1]>=0))
+                sensor_af_touch_zone(client,sensor_work->zone_center_pos);
+            
             if (sensor_af_single(client) < 0) {
                        SENSOR_TR("%s Sensor_af_single is failed in sensor_af_workqueue!\n",SENSOR_NAME_STRING());
                 sensor_work->result = WqRet_fail;
@@ -2183,7 +2228,7 @@ set_end:
     return;
 }
 
-static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq_cmd cmd, int var, bool wait)
+static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq_cmd cmd, int var, bool wait, int *zone_pos)
 {
     struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
        struct sensor *sensor = to_sensor(client); 
@@ -2211,6 +2256,26 @@ static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq
         wk->result = WqRet_inval;
         wk->wait = wait;
         wk->var = var;
+
+        if (zone_pos) {   
+            if (*zone_pos || *(zone_pos+1) || *(zone_pos+2) || *(zone_pos+3)) {
+                *zone_pos += 1000;
+                *(zone_pos+1) += 1000;
+                *(zone_pos+2) += 1000;
+                *(zone_pos+3) += 1000;
+                wk->zone_center_pos[0] = ((*zone_pos + *(zone_pos+2))>>1)*80/2000;
+                wk->zone_center_pos[1] = ((*(zone_pos+1) + *(zone_pos+3))>>1)*60/2000;
+            } else {
+                #if CONFIG_SENSOR_FocusCenterInCapture
+                wk->zone_center_pos[0] = 32;
+                wk->zone_center_pos[1] = 24;
+                #else
+                wk->zone_center_pos[0] = -1;
+                wk->zone_center_pos[1] = -1;
+                #endif
+            }
+        }
+        
         init_waitqueue_head(&wk->done);
         
            queue_delayed_work(sensor->sensor_wq,&(wk->dwork),0);
@@ -2261,11 +2326,11 @@ static int sensor_parameter_record(struct i2c_client *client)
     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, &tp_l);
-       sensor->parameter.preview_gain = tp_l;
+       sensor_read(client,0x350b, &ret_l);
+       sensor->parameter.preview_gain = ret_l;
     
        SENSOR_DG(" %s Read 0x350b=0x%02x  PreviewExposure:%d 0x3500=0x%02x  0x3501=0x%02x 0x3502=0x%02x \n",
-     SENSOR_NAME_STRING(), tp_l,sensor->parameter.preview_exposure,ret_h, ret_m, ret_l);
+     SENSOR_NAME_STRING(), tp_l,sensor->parameter.preview_exposure,tp_h, tp_m, tp_l);
        return 0;
 }
 #define OV5640_FULL_PERIOD_PIXEL_NUMS_HTS         (2844) 
@@ -2278,14 +2343,8 @@ static int sensor_ae_transfer(struct i2c_client *client)
        u8  ExposureMid;
        u8  ExposureHigh;
        u16 ulCapture_Exposure;
-       u32 ulCapture_Exposure_Gain;
-       u16  iCapture_Gain;
-       u8   Lines_10ms;
-       bool m_60Hz = 0;
-       u8  reg_l = 0,reg_h =0;
        u16 Preview_Maxlines;
        u8  Gain;
-       u32  Capture_MaxLines;
     u16 OV5640_g_iExtra_ExpLines;
        struct sensor *sensor = to_sensor(client);
 
@@ -2299,9 +2358,7 @@ static int sensor_ae_transfer(struct i2c_client *client)
     SENSOR_DG("cap shutter calutaed = %d, 0x%x\n", ulCapture_Exposure,ulCapture_Exposure);
     
        // write the gain and exposure to 0x350* registers      
-       sensor_write(client,0x350b, Gain);
-       //Gain = (Gain >> 8) & 0x01;
-       //sensor_write(client,0x350a, Gain);
+       sensor_write(client,0x350b, Gain);      
 
     if (ulCapture_Exposure <= 1940) {
         OV5640_g_iExtra_ExpLines = 0;
@@ -2392,7 +2449,7 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
     struct sensor *sensor = to_sensor(client);
        const struct v4l2_queryctrl *qctrl;
     const struct sensor_datafmt *fmt;
-    char value,ret_h,ret_l;
+    char value;
     int ret,pid = 0;
 
     SENSOR_DG("\n%s..%s.. \n",SENSOR_NAME_STRING(),__FUNCTION__);
@@ -2656,7 +2713,6 @@ static int sensor_s_fmt(struct v4l2_subdev *sd,struct v4l2_mbus_framefmt *mf)
        struct soc_camera_device *icd = client->dev.platform_data;
     struct reginfo *winseqe_set_addr=NULL;
     int ret = 0, set_w,set_h;
-    char ret_h,ret_l;
 
        fmt = sensor_find_datafmt(mf->code, sensor_colour_fmts,
                                   ARRAY_SIZE(sensor_colour_fmts));
@@ -2848,7 +2904,7 @@ static int sensor_s_fmt(struct v4l2_subdev *sd,struct v4l2_mbus_framefmt *mf)
                        }
             #if CONFIG_SENSOR_Focus
             if (sensor->info_priv.auto_focus == SENSOR_AF_MODE_AUTO) {
-                sensor_af_workqueue_set(icd,WqCmd_af_return_idle,0,true);
+                sensor_af_workqueue_set(icd,WqCmd_af_return_idle,0,true,NULL);
                 msleep(200);
             } else {
                 msleep(500);
@@ -3252,7 +3308,7 @@ static int sensor_set_focus_absolute(struct soc_camera_device *icd, const struct
     
        if ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK) && (sensor->info_priv.affm_reinit == 0)) {
                if ((value >= qctrl_info->minimum) && (value <= qctrl_info->maximum)) {
-            ret = sensor_af_workqueue_set(icd, WqCmd_af_special_pos, value, true);
+            ret = sensor_af_workqueue_set(icd, WqCmd_af_special_pos, value, true,NULL);
                        SENSOR_DG("%s..%s : %d  ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
                } else {
                        ret = -EINVAL;
@@ -3280,9 +3336,9 @@ static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct
        if ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK) && (sensor->info_priv.affm_reinit == 0)) {
                if ((value >= qctrl_info->minimum) && (value <= qctrl_info->maximum)) {            
             if (value > 0) {
-                ret = sensor_af_workqueue_set(icd, WqCmd_af_near_pos, 0, true);
+                ret = sensor_af_workqueue_set(icd, WqCmd_af_near_pos, 0, true,NULL);
             } else {
-                ret = sensor_af_workqueue_set(icd, WqCmd_af_far_pos, 0, true);
+                ret = sensor_af_workqueue_set(icd, WqCmd_af_far_pos, 0, true,NULL);
             }
                        SENSOR_DG("%s..%s : %d  ret:0x%x\n",SENSOR_NAME_STRING(),__FUNCTION__, value,ret);
                } else {
@@ -3297,7 +3353,7 @@ static int sensor_set_focus_relative(struct soc_camera_device *icd, const struct
        return ret;
 }
 
-static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value)
+static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l2_queryctrl *qctrl, int value, int *zone_pos)
 {
        struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
        struct sensor *sensor = to_sensor(client);
@@ -3308,7 +3364,7 @@ static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l
                {
                        case SENSOR_AF_MODE_AUTO:
                        {
-                               ret = sensor_af_workqueue_set(icd, WqCmd_af_single, 0, true);
+                               ret = sensor_af_workqueue_set(icd, WqCmd_af_single, 0, true, zone_pos);
                                break;
                        }
 
@@ -3326,7 +3382,7 @@ static int sensor_set_focus_mode(struct soc_camera_device *icd, const struct v4l
                        
                        case SENSOR_AF_MODE_CONTINUOUS:
                        {
-                               ret = sensor_af_workqueue_set(icd, WqCmd_af_continues, 0, true);
+                               ret = sensor_af_workqueue_set(icd, WqCmd_af_continues, 0, true,NULL);
                                break;
                        }*/
                        default:
@@ -3597,7 +3653,7 @@ static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_c
     const struct v4l2_queryctrl *qctrl;
     struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
     struct sensor *sensor = to_sensor(client);
-    int val_offset,ret;
+    int val_offset;
 
     qctrl = soc_camera_find_qctrl(&sensor_ops, ext_ctrl->id);
 
@@ -3685,7 +3741,7 @@ static int sensor_s_ext_control(struct soc_camera_device *icd, struct v4l2_ext_c
                case V4L2_CID_FOCUS_AUTO:
                        {
                                if (ext_ctrl->value == 1) {
-                                       if (sensor_set_focus_mode(icd, qctrl,SENSOR_AF_MODE_AUTO) != 0) {
+                                       if (sensor_set_focus_mode(icd, qctrl,SENSOR_AF_MODE_AUTO,ext_ctrl->rect) != 0) {
                                                if(0 == (sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK)) {
                                                        sensor->info_priv.auto_focus = SENSOR_AF_MODE_AUTO;
                                                }
@@ -3800,7 +3856,7 @@ static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
                /* If auto focus firmware haven't download success, must download firmware again when in video or preview stream on */
                if (sensor_fmt_capturechk(sd, &mf) == false) {
                        if ((sensor->info_priv.affm_reinit == 1) || ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK)==0)) {
-                sensor_af_workqueue_set(icd, WqCmd_af_init, 0, false);
+                sensor_af_workqueue_set(icd, WqCmd_af_init, 0, false,NULL);
                                sensor->info_priv.affm_reinit = 0;
                        }
                }