PM / devfreq: rk3399_dmc: rename driver and internals to rockchip
[firefly-linux-kernel-4.4.55.git] / drivers / media / video / ov5640_for_td8801.c
index 69be80bf4c54bd214db79a90d24e2d91b55e8550..de06e98c9219b7358c917e4c64168ccf78398bef 100644 (file)
 #include <media/v4l2-common.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/soc_camera.h>
-#include <mach/rk29_camera.h>
+#include <plat/rk_camera.h>
 #include "ov5640.h"
 
-static int debug = 1;
+static int debug;
 module_param(debug, int, S_IRUGO|S_IWUSR);
 
 #define dprintk(level, fmt, arg...) do {                       \
@@ -53,7 +53,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define SENSOR_INIT_WIDTH      800                     /* Sensor pixel size for sensor_init_data array */
 #define SENSOR_INIT_HEIGHT  600
 #define SENSOR_INIT_WINSEQADR sensor_svga
-#define SENSOR_INIT_PIXFMT V4L2_MBUS_FMT_YUYV8_2X8
+#define SENSOR_INIT_PIXFMT  V4L2_MBUS_FMT_YUYV8_2X8
 
 #define CONFIG_SENSOR_WhiteBalance     1
 #define CONFIG_SENSOR_Brightness       0
@@ -62,7 +62,7 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define CONFIG_SENSOR_Effect        1
 #define CONFIG_SENSOR_Scene         1
 #define CONFIG_SENSOR_DigitalZoom   0
-#define CONFIG_SENSOR_Exposure      0
+#define CONFIG_SENSOR_Exposure      1
 #define CONFIG_SENSOR_Flash         1
 #define CONFIG_SENSOR_Mirror        0
 #define CONFIG_SENSOR_Flip          0
@@ -73,13 +73,13 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define CONFIG_SENSOR_Focus         0
 #endif
 
-#define CONFIG_SENSOR_I2C_SPEED    250000       /* Hz */
+#define CONFIG_SENSOR_I2C_SPEED    400*1000       /* Hz */
 /* Sensor write register continues by preempt_disable/preempt_enable for current process not be scheduled */
 #define CONFIG_SENSOR_I2C_NOSCHED   0
 #define CONFIG_SENSOR_I2C_RDWRCHK   0
 
 #define CONFIG_SENSOR_WRITE_REGS  1
-#define WRITE_REGS_NUM 100
+#define WRITE_REGS_NUM 3
 
 #define SENSOR_BUS_PARAM  (SOCAM_MASTER | SOCAM_PCLK_SAMPLE_RISING |\
                           SOCAM_HSYNC_ACTIVE_HIGH | SOCAM_VSYNC_ACTIVE_LOW |\
@@ -177,11 +177,24 @@ module_param(debug, int, S_IRUGO|S_IWUSR);
 #define StepFocus_Spec_Tag       0x10
 #endif
 
+//flash off in fixed time to prevent from too hot , zyc
+struct  flash_timer{
+    struct soc_camera_device *icd;
+       struct hrtimer timer;
+};
+static enum hrtimer_restart flash_off_func(struct hrtimer *timer);
+
+static struct  flash_timer flash_off_timer;
+//for user defined if user want to customize the series , zyc
+#ifdef CONFIG_OV5640_USER_DEFINED_SERIES
+#include "ov5640_user_series.c"
+#else
+
 /* init 800X600 SVGA */
 static struct reginfo sensor_init_data[] =
 {
        {0x3103, 0x11},
-       {0x3008, 0x82},
+//     {0x3008, 0x82},   //don't do software reset here, or writing some registers may fail
        {0x3008, 0x42},
        {0x3103, 0x03},
        {0x3017, 0xff},
@@ -467,6 +480,30 @@ static struct reginfo sensor_720p[]=
        {0x3a0d,0x02},
        {0x3a14,0x02},
        {0x3a15,0xe4},
+
+    {0x3820, 0x41}, //ddl@rock-chips.com add start: qsxvga -> 720p isn't stream on 
+       {0x3821, 0x07},
+       {0x3814, 0x31},
+       {0x3815, 0x31},
+       
+       {0x3618, 0x00},
+       {0x3612, 0x29},
+       {0x3709, 0x52},
+       {0x370c, 0x03},
+       {0x3a02, 0x03},
+       {0x3a03, 0xd8},
+       {0x3a08 ,0x01},///
+       {0x3a09, 0x27},///
+       {0x3a0a, 0x00},///
+       {0x3a0b, 0xf6},///
+       {0x3a0e, 0x03},
+       {0x3a0d, 0x04},
+       {0x3a14, 0x03},
+       {0x3a15, 0xd8},
+       {0x4004, 0x02},
+       {0x3002, 0x1c},////
+       {0x4713, 0x03},//////ddl@rock-chips.com add end
+    
        {0x3002,0x00},///
        {0x4713,0x02},///
        {0x4837,0x16},
@@ -767,15 +804,17 @@ static struct reginfo sensor_qcif[] =
 
        {SEQUENCE_END, 0x00}
 };
-
+#endif
 static  struct reginfo sensor_ClrFmt_YUYV[]=
 {
+       {0x4300,0x30},
        {0x4300,0x30},
        {SEQUENCE_END, 0x00}
 };
 
 static  struct reginfo sensor_ClrFmt_UYVY[]=
 {
+       {0x4300,0x32},
        {0x4300,0x32},
        {SEQUENCE_END, 0x00}
 };
@@ -961,31 +1000,73 @@ static struct reginfo *sensor_EffectSeqe[] = {sensor_Effect_Normal, sensor_Effec
 #if CONFIG_SENSOR_Exposure
 static  struct reginfo sensor_Exposure0[]=
 {
+       {0x3a0f, 0x10},
+       {0x3a10, 0x08},
+       {0x3a1b, 0x10},
+       {0x3a1e, 0x08},
+       {0x3a11, 0x20},
+       {0x3a1f, 0x10},
        {SEQUENCE_END, 0x00}
 };
 static  struct reginfo sensor_Exposure1[]=
 {
+       {0x3a0f, 0x20},
+       {0x3a10, 0x18},
+       {0x3a11, 0x41},
+       {0x3a1b, 0x20},
+       {0x3a1e, 0x18},
+       {0x3a1f, 0x10},
        {SEQUENCE_END, 0x00}
 };
 static  struct reginfo sensor_Exposure2[]=
 {
+       {0x3a0f, 0x30},
+       {0x3a10, 0x28},
+       {0x3a11, 0x61},
+       {0x3a1b, 0x30},
+       {0x3a1e, 0x28},
+       {0x3a1f, 0x10},
        {SEQUENCE_END, 0x00}
 };
 
 static  struct reginfo sensor_Exposure3[]=
 {
+       {0x3a0f, 0x38},
+       {0x3a10, 0x30},
+       {0x3a11, 0x61},
+       {0x3a1b, 0x38},
+       {0x3a1e, 0x30},
+       {0x3a1f, 0x10},
        {SEQUENCE_END, 0x00}
 };
 static  struct reginfo sensor_Exposure4[]=
 {
+       {0x3a0f, 0x40},
+       {0x3a10, 0x38},
+       {0x3a11, 0x71},
+       {0x3a1b, 0x40},
+       {0x3a1e, 0x38},
+       {0x3a1f, 0x10},
        {SEQUENCE_END, 0x00}
 };
 static  struct reginfo sensor_Exposure5[]=
 {
+       {0x3a0f, 0x50},
+       {0x3a10, 0x48},
+       {0x3a11, 0x90},
+       {0x3a1b, 0x50},
+       {0x3a1e, 0x48},
+       {0x3a1f, 0x20},
        {SEQUENCE_END, 0x00}
 };
 static  struct reginfo sensor_Exposure6[]=
 {
+       {0x3a0f, 0x60},
+       {0x3a10, 0x58},
+       {0x3a11, 0xa0},
+       {0x3a1b, 0x60},
+       {0x3a1e, 0x58},
+       {0x3a1f, 0x20},
        {SEQUENCE_END, 0x00}
 };
 static struct reginfo *sensor_ExposureSeqe[] = {sensor_Exposure0, sensor_Exposure1, sensor_Exposure2, sensor_Exposure3,
@@ -1150,7 +1231,7 @@ static const struct v4l2_querymenu sensor_menus[] =
     #endif
 };
 
-static const struct v4l2_queryctrl sensor_controls[] =
+static struct v4l2_queryctrl sensor_controls[] =
 {
        #if CONFIG_SENSOR_WhiteBalance
     {
@@ -1193,8 +1274,8 @@ static const struct v4l2_queryctrl sensor_controls[] =
         .id            = V4L2_CID_EXPOSURE,
         .type          = V4L2_CTRL_TYPE_INTEGER,
         .name          = "Exposure Control",
-        .minimum       = 0,
-        .maximum       = 6,
+        .minimum       = -3,
+        .maximum       = 3,
         .step          = 1,
         .default_value = 0,
     },
@@ -1843,7 +1924,7 @@ static int sensor_af_single(struct i2c_client *client)
                ret = -1;
                goto sensor_af_single_end;
        }
-       
+
        cnt = 0;
     do
     {
@@ -1880,8 +1961,8 @@ static int sensor_af_const(struct i2c_client *client)
 
 static int sensor_af_init(struct i2c_client *client)
 {
-       int ret = 0;
-       char state,cnt;
+       int ret = 0, cnt;
+       char state;
 
        ret = sensor_write_array(client, sensor_af_firmware);
     if (ret != 0) {
@@ -1893,17 +1974,16 @@ static int sensor_af_init(struct i2c_client *client)
     cnt = 0;
     do
     {
-       if (cnt != 0) {
-                       msleep(1);
-       }
-       cnt++;
-               ret = sensor_read(client, STA_FOCUS_Reg, &state);
+               msleep(1);
+       if (cnt++ > 500)
+               break;
+       ret = sensor_read(client, STA_FOCUS_Reg, &state);
                if (ret != 0){
                   SENSOR_TR("%s[%d] read focus_status failed\n",SENSOR_NAME_STRING(),__LINE__);
                   ret = -1;
                   goto sensor_af_init_end;
                }
-    }while((state == S_STARTUP) && (cnt<100)); 
+    } while (state != S_IDLE);
 
     if (state != S_IDLE) {
        SENSOR_TR("%s focus state(0x%x) is error!\n",SENSOR_NAME_STRING(),state);
@@ -1919,8 +1999,7 @@ sensor_af_init_end:
 static int sensor_af_downfirmware(struct i2c_client *client)
 {
        struct sensor *sensor = to_sensor(client);
-       struct af_cmdinfo cmdinfo;
-       int ret=0, focus_pos = 0xfe;
+       int ret=0;
     struct soc_camera_device *icd = client->dev.platform_data;
     struct v4l2_mbus_framefmt mf;
                
@@ -1940,34 +2019,13 @@ static int sensor_af_downfirmware(struct i2c_client *client)
         if (sensor_fmt_videochk(NULL, &mf) == true) {    /* ddl@rock-chips.com: focus mode fix const auto focus in video */
             ret = sensor_af_const(client);
         } else {
-               switch (sensor->info_priv.auto_focus)
-               {
-                       /*case SENSOR_AF_MODE_INFINITY:
-                       {
-                               focus_pos = 0x00;
-                       }
-                       case SENSOR_AF_MODE_MACRO:
-                       {
-                               if (focus_pos != 0x00)
-                                       focus_pos = 0xff;
-
-                               sensor_af_idlechk(client);
-                               cmdinfo.cmd_tag = StepFocus_Spec_Tag;
-                               cmdinfo.cmd_para[0] = focus_pos;
-                               cmdinfo.validate_bit = 0x81;
-                               //ret = sensor_af_cmdset(client, StepMode_Cmd, &cmdinfo);
-                               break;
-                       }*/
-                       case SENSOR_AF_MODE_AUTO:
-                       {
-                               ret = sensor_af_single(client);
-                               break;
-                       }
-                       /*case SENSOR_AF_MODE_CONTINUOUS:
-                       {
-                               ret = sensor_af_const(client);
-                               break;
-                       }*/
+               switch (sensor->info_priv.auto_focus)
+               {
+                       case SENSOR_AF_MODE_AUTO:
+                       {
+                               ret = sensor_af_single(client);
+                               break;
+                       }
                        case SENSOR_AF_MODE_CLOSE:
                        {
                                ret = 0;
@@ -1997,6 +2055,7 @@ static void sensor_af_workqueue(struct work_struct *work)
     SENSOR_DG("%s %s Enter, cmd:0x%x \n",SENSOR_NAME_STRING(), __FUNCTION__,sensor_work->cmd);
     
     mutex_lock(&sensor->wq_lock);
+    
     switch (sensor_work->cmd) 
     {
         case WqCmd_af_init:
@@ -2071,7 +2130,7 @@ static void sensor_af_workqueue(struct work_struct *work)
             SENSOR_TR("Unknow command(%d) in %s af workqueue!",sensor_work->cmd,SENSOR_NAME_STRING());
             break;
     } 
-
+set_end:
     if (sensor_work->wait == false) {
         kfree((void*)sensor_work);
     } else {
@@ -2092,6 +2151,14 @@ static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq
         ret = -EINVAL;
         goto sensor_af_workqueue_set_end;
     }
+
+    if ((sensor->info_priv.funmodule_state & SENSOR_AF_IS_OK) != SENSOR_AF_IS_OK) {
+        if (cmd != WqCmd_af_init) {
+            SENSOR_TR("%s %s cmd(%d) ingore,because af module isn't ready!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
+            ret = -1;
+            goto sensor_af_workqueue_set_end;
+        }
+    }
     
     wk = kzalloc(sizeof(struct sensor_work), GFP_KERNEL);
     if (wk) {
@@ -2112,9 +2179,9 @@ static int sensor_af_workqueue_set(struct soc_camera_device *icd, enum sensor_wq
         * and VIDIOC_DQBUF is sched. so unlock video_lock here.
         */
         if (wait == true) {
-            mutex_unlock(&icd->video_lock);                     
-            if (wait_event_timeout(wk->done, (wk->result != WqRet_inval), msecs_to_jiffies(2500)) == 0) {
-                SENSOR_TR("%s %s cmd(%d) is timeout!",SENSOR_NAME_STRING(),__FUNCTION__,cmd);                        
+            mutex_unlock(&icd->video_lock);
+            if (wait_event_timeout(wk->done, (wk->result != WqRet_inval), msecs_to_jiffies(5000)) == 0) {  //hhb
+                SENSOR_TR("%s %s cmd(%d) is timeout!\n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
             }
             ret = wk->result;
             kfree((void*)wk);
@@ -2163,8 +2230,8 @@ static int sensor_parameter_record(struct i2c_client *client)
        sensor_read(client,0x380f, &tp_l);
        sensor->parameter.preview_maxlines += tp_l;
 
-       sensor->parameter.capture_framerate = 300;
-       sensor->parameter.preview_framerate = 2500;
+       sensor->parameter.capture_framerate = 375;
+       sensor->parameter.preview_framerate = 1500;
 
        sensor_read(client,0x3400,&sensor->parameter.awb[0]);           //record awb value
        sensor_read(client,0x3401,&sensor->parameter.awb[1]);
@@ -2239,7 +2306,7 @@ static int sensor_ae_transfer(struct i2c_client *client)
                iCapture_Gain = iCapture_Gain << 1;
        }
        
-       //ulCapture_Exposure_Gain =(u32) (11 * ulCapture_Exposure * iCapture_Gain/5);   //0ld value 2.5, œâŸö¹ýÁÁ
+       //ulCapture_Exposure_Gain =(u32) (11 * ulCapture_Exposure * iCapture_Gain/5);   //0ld value 2.5, ½â¾ö¹ýÁÁ
        ulCapture_Exposure_Gain =(u32) (ulCapture_Exposure * iCapture_Gain);
        
        if(ulCapture_Exposure_Gain < Capture_MaxLines*16) {
@@ -2302,7 +2369,7 @@ static int sensor_ae_transfer(struct i2c_client *client)
        // SendToFile("ExposureLow = 0x%x\r\n", ExposureLow);
        // SendToFile("ExposureMid = 0x%x\r\n", ExposureMid);
        // SendToFile("ExposureHigh = 0x%x\r\n", ExposureHigh);
-       //ŒÓ³€ÑÓʱ£¬±ÜÃâ°µŽŠÅÄÕÕʱµÄÃ÷°µ·ÖœçÎÊÌâ
+       //¼Ó³¤ÑÓʱ£¬±ÜÃâ°µ´¦ÅÄÕÕʱµÄÃ÷°µ·Ö½çÎÊÌâ
        //camera_timed_wait(200);
        //linzhk camera_timed_wait(500);
 
@@ -2350,6 +2417,11 @@ static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd
 
                        if (sensor->sensor_io_request && sensor->sensor_io_request->sensor_ioctrl) {
                                sensor->sensor_io_request->sensor_ioctrl(icd->pdev,Cam_Flash, on);
+                if(on == Flash_On){
+                    //flash off after 2 secs
+                       hrtimer_cancel(&(flash_off_timer.timer));
+                       hrtimer_start(&(flash_off_timer.timer),ktime_set(0, 800*1000*1000),HRTIMER_MODE_REL);
+                               }
                        }
                        break;
                }
@@ -2363,6 +2435,15 @@ static int sensor_ioctrl(struct soc_camera_device *icd,enum rk29sensor_power_cmd
 sensor_power_end:
        return ret;
 }
+
+static enum hrtimer_restart flash_off_func(struct hrtimer *timer){
+       struct flash_timer *fps_timer = container_of(timer, struct flash_timer, timer);
+    sensor_ioctrl(fps_timer->icd,Sensor_Flash,0);
+       SENSOR_DG("%s %s !!!!!!",SENSOR_NAME_STRING(),__FUNCTION__);
+    return 0;
+    
+}
+
 static int sensor_init(struct v4l2_subdev *sd, u32 val)
 {
     struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -2420,6 +2501,8 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
     }
 
     ret = sensor_write_array(client, sensor_init_data);
+    udelay(1000);   //wait sensor power on,so that I2C write sensor registers would sucess hhb@rock-chips.con
+
     if (ret != 0) {
         SENSOR_TR("error: %s initial failed\n",SENSOR_NAME_STRING());
         goto sensor_INIT_ERR;
@@ -2476,6 +2559,8 @@ static int sensor_init(struct v4l2_subdev *sd, u32 val)
        qctrl = soc_camera_find_qctrl(&sensor_ops, V4L2_CID_FLASH);
        if (qctrl)
         sensor->info_priv.flash = qctrl->default_value;
+    flash_off_timer.icd = icd;
+       flash_off_timer.timer.function = flash_off_func;
     #endif
     SENSOR_DG("\n%s..%s.. icd->width = %d.. icd->height %d\n",SENSOR_NAME_STRING(),((val == 0)?__FUNCTION__:"sensor_reinit"),icd->user_width,icd->user_height);
 
@@ -2774,9 +2859,15 @@ static int sensor_s_fmt(struct v4l2_subdev *sd,struct v4l2_mbus_framefmt *mf)
                        if (((winseqe_set_addr->reg == SEQUENCE_PROPERTY) && (winseqe_set_addr->val == SEQUENCE_NORMAL))
                                || (winseqe_set_addr->reg != SEQUENCE_PROPERTY)) {
                                ret |= sensor_write_array(client,sensor_init_data);
+                               udelay(1000);   //wait sensor power on,so that I2C write sensor registers would sucess hhb@rock-chips.con
                                SENSOR_DG("\n%s reinit ret:0x%x \n",SENSOR_NAME_STRING(), ret);
                        }
                }
+
+        if ((winseqe_set_addr == sensor_qsxga) && (sensor->info_priv.winseqe_cur_addr == sensor_720p)) {
+            sensor_write_array(client, sensor_svga);
+        }
+        
         ret |= sensor_write_array(client, winseqe_set_addr);
         if (ret != 0) {
             SENSOR_TR("%s set format capability failed\n", SENSOR_NAME_STRING());
@@ -2843,7 +2934,7 @@ static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
     struct i2c_client *client = v4l2_get_subdevdata(sd);
     struct sensor *sensor = to_sensor(client);
     const struct sensor_datafmt *fmt;
-    int ret = 0;
+    int ret = 0,set_w,set_h;
    
        fmt = sensor_find_datafmt(mf->code, sensor_colour_fmts,
                                   ARRAY_SIZE(sensor_colour_fmts));
@@ -2862,6 +2953,78 @@ static int sensor_try_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
     else if (mf->width < SENSOR_MIN_WIDTH)
         mf->width = SENSOR_MIN_WIDTH;
 
+    set_w = mf->width;
+    set_h = mf->height;
+
+       if (((set_w <= 176) && (set_h <= 144)) && (sensor_qcif[0].reg!=SEQUENCE_END))
+       {
+        set_w = 176;
+        set_h = 144;
+       }
+       else if (((set_w <= 320) && (set_h <= 240)) && (sensor_qvga[0].reg!=SEQUENCE_END))
+    {
+        set_w = 320;
+        set_h = 240;
+    }
+    else if (((set_w <= 352) && (set_h<= 288)) && (sensor_cif[0].reg!=SEQUENCE_END))
+    {
+        set_w = 352;
+        set_h = 288;
+    }
+    else if (((set_w <= 640) && (set_h <= 480)) && (sensor_vga[0].reg!=SEQUENCE_END))
+    {
+        set_w = 640;
+        set_h = 480;
+    }
+    else if (((set_w <= 800) && (set_h <= 600)) && (sensor_svga[0].reg!=SEQUENCE_END))
+    {
+        set_w = 800;
+        set_h = 600;
+    }
+       else if (((set_w <= 1024) && (set_h <= 768)) && (sensor_xga[0].reg!=SEQUENCE_END))
+    {
+        set_w = 1024;
+        set_h = 768;
+    }
+       else if (((set_w <= 1280) && (set_h <= 720)) && (sensor_720p[0].reg!=SEQUENCE_END))
+    {
+        set_w = 1280;
+        set_h = 720;
+    }
+    else if (((set_w <= 1280) && (set_h <= 1024)) && (sensor_sxga[0].reg!=SEQUENCE_END))
+    {
+        set_w = 1280;
+        set_h = 1024;
+    }
+    else if (((set_w <= 1600) && (set_h <= 1200)) && (sensor_uxga[0].reg!=SEQUENCE_END))
+    {
+        set_w = 1600;
+        set_h = 1200;
+    }
+    else if (((set_w <= 1920) && (set_h <= 1080)) && (sensor_1080p[0].reg!=SEQUENCE_END))
+    {
+        set_w = 1920;
+        set_h = 1080;
+    }
+       else if (((set_w <= 2048) && (set_h <= 1536)) && (sensor_qxga[0].reg!=SEQUENCE_END))
+    {
+        set_w = 2048;
+        set_h = 1536;
+    }
+       else if (((set_w <= 2592) && (set_h <= 1944)) && (sensor_qsxga[0].reg!=SEQUENCE_END))
+    {
+        set_w = 2592;
+        set_h = 1944;
+    }
+    else
+    {
+        set_w = SENSOR_INIT_WIDTH;
+        set_h = SENSOR_INIT_HEIGHT;
+    }
+
+    mf->width = set_w;
+    mf->height = set_h;
+    
     mf->colorspace = fmt->colorspace;
     
     return ret;
@@ -3701,7 +3864,7 @@ static int sensor_s_stream(struct v4l2_subdev *sd, int enable)
                }
                #endif
        } else if (enable == 0) {
-               sensor->info_priv.enable = 0;
+           sensor->info_priv.enable = 0;
                #if CONFIG_SENSOR_Focus 
         flush_workqueue(sensor->sensor_wq);
                #endif
@@ -3774,26 +3937,34 @@ static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
        struct i2c_client *client = v4l2_get_subdevdata(sd);
     struct soc_camera_device *icd = client->dev.platform_data;
     struct sensor *sensor = to_sensor(client);
-    int ret = 0;
+    int ret = 0,i;
 
        SENSOR_DG("\n%s..%s..cmd:%x \n",SENSOR_NAME_STRING(),__FUNCTION__,cmd);
        switch (cmd)
        {
                case RK29_CAM_SUBDEV_DEACTIVATE:
                {
+                       #if CONFIG_SENSOR_Flash  //hhb
+                       sensor_ioctrl(icd, Sensor_Flash, Flash_Off);
+                       #endif
                        sensor_deactivate(client);
                        break;
                }
                case RK29_CAM_SUBDEV_IOREQUEST:
                {
-                       sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;           
+            sensor->sensor_io_request = (struct rk29camera_platform_data*)arg;           
             if (sensor->sensor_io_request != NULL) { 
-                if (sensor->sensor_io_request->gpio_res[0].dev_name && 
-                    (strcmp(sensor->sensor_io_request->gpio_res[0].dev_name, dev_name(icd->pdev)) == 0)) {
-                    sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[0];
-                } else if (sensor->sensor_io_request->gpio_res[1].dev_name && 
-                    (strcmp(sensor->sensor_io_request->gpio_res[1].dev_name, dev_name(icd->pdev)) == 0)) {
-                    sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[1];
+                sensor->sensor_gpio_res = NULL;
+                for (i=0; i<RK29_CAM_SUPPORT_NUMS;i++) {
+                    if (sensor->sensor_io_request->gpio_res[i].dev_name && 
+                        (strcmp(sensor->sensor_io_request->gpio_res[i].dev_name, dev_name(icd->pdev)) == 0)) {
+                        sensor->sensor_gpio_res = (struct rk29camera_gpio_res*)&sensor->sensor_io_request->gpio_res[i];
+                    }
+                }
+                if (sensor->sensor_gpio_res == NULL) {
+                    SENSOR_TR("%s %s obtain gpio resource failed when RK29_CAM_SUBDEV_IOREQUEST \n",SENSOR_NAME_STRING(),__FUNCTION__);
+                    ret = -EINVAL;
+                    goto sensor_ioctl_end;
                 }
             } else {
                 SENSOR_TR("%s %s RK29_CAM_SUBDEV_IOREQUEST fail\n",SENSOR_NAME_STRING(),__FUNCTION__);
@@ -3806,14 +3977,20 @@ static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
                if (sensor->sensor_gpio_res) {
                 printk("flash io:%d\n",sensor->sensor_gpio_res->gpio_flash);
                 if (sensor->sensor_gpio_res->gpio_flash == INVALID_GPIO) {
-                   int i;
                     for (i = 0; i < icd->ops->num_controls; i++) {
                                if (V4L2_CID_FLASH == icd->ops->controls[i].id) {
-                                       memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));                                       
+                                       //memset((char*)&icd->ops->controls[i],0x00,sizeof(struct v4l2_queryctrl));  
+                              sensor_controls[i].id=0xffff;                            
                                }
                     }
                     sensor->info_priv.flash = 0xff;
                     SENSOR_DG("%s flash gpio is invalidate!\n",SENSOR_NAME_STRING());
+                }else{ //two cameras are the same,need to deal diffrently ,zyc
+                    for (i = 0; i < icd->ops->num_controls; i++) {
+                           if(0xffff == icd->ops->controls[i].id){
+                              sensor_controls[i].id=V4L2_CID_FLASH;
+                           }               
+                    }
                 }
                }
             #endif
@@ -3916,7 +4093,7 @@ static int sensor_probe(struct i2c_client *client,
                mutex_init(&sensor->wq_lock);
                #endif
     }
-
+       hrtimer_init(&(flash_off_timer.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);
     SENSOR_DG("\n%s..%s..%d  ret = %x \n",__FUNCTION__,__FILE__,__LINE__,ret);
     return ret;
 }