Hi,
all checkpath errors and warnings are cleaned, 
Please review the updates.

From: Yong He <[email protected]>
Subject: [PATCH] MRST Tablet camera driver ver-0.942 (re-send 2), fix 9411

Bug 9411 - power regression test failed for camera driver version 0.941 this is 
caused by the back sensor HW power down GPIO-49, when perform a HW power down 
using this GPIO, somewhere else is leaking, So I revert to use software power 
down.
Also, this patch added hw status flag and save/restore ops between standby and 
wakeup.

        Signed-off-by: Yong He <[email protected]>

Index: linux-2.6.37/drivers/staging/mrstci/mrstisp/mrstisp_main.c
===================================================================
--- linux-2.6.37/drivers/staging/mrstci/mrstisp/mrstisp_main.c  (revision 98)
+++ linux-2.6.37/drivers/staging/mrstci/mrstisp/mrstisp_main.c  (revision 100)
@@ -1369,8 +1369,10 @@
        DBG_entering;
 
        for (i = 0 ; i <= isp->sensor_max; i++) {
-               // power the sensor
-               v4l2_subdev_call(isp->cameras[i].camera, core, s_gpio, 1);
+               if (isp->cameras[i].camera != NULL) {
+                       v4l2_subdev_call(isp->cameras[i].camera,
+                                       core, s_gpio, 1);
+               }
        };
 
        DBG_leaving;
@@ -2245,6 +2247,18 @@
                return -EBUSY;
        }
 
+       /* switch to a different sensor? */
+       if (isp->sensor_curr != i) {
+               /* suspend current sensor */
+               if ((isp->sensor_curr >= 0) &&
+                               (isp->sensor_curr <= isp->sensor_max)) {
+                       if (isp->cameras[isp->sensor_curr].camera)
+                               v4l2_subdev_call(
+                                       isp->cameras[isp->sensor_curr].camera,
+                                       core, s_gpio, 1);
+               }
+       }
+
        isp->sensor_curr = i;
        dprintk(0, "set sensor %s as input", camera->name);
 
Index: linux-2.6.37/drivers/staging/mrstci/mrstov5640/ov5640.h
===================================================================
--- linux-2.6.37/drivers/staging/mrstci/mrstov5640/ov5640.h     (revision 98)
+++ linux-2.6.37/drivers/staging/mrstci/mrstov5640/ov5640.h     (revision 100)
@@ -42,8 +42,6 @@
 
 
 static struct regval_list ov5640_reg_reset[] = {
-               {0x3103, 0x11},
-               {0x3008, 0x82},
                {0x3008, 0x42},
                {0x3103, 0x03},
                {0x3017, 0x00},
Index: linux-2.6.37/drivers/staging/mrstci/mrstov5640/mrstov5640.c
===================================================================
--- linux-2.6.37/drivers/staging/mrstci/mrstov5640/mrstov5640.c (revision 98)
+++ linux-2.6.37/drivers/staging/mrstci/mrstov5640/mrstov5640.c (revision 100)
@@ -48,7 +48,7 @@
 #include "ci_sensor_common.h"
 #include "ov5640.h"
 
-#define DRIVER_VERSION "0.941"
+#define DRIVER_VERSION "0.942"
 
 static int mrstov5640_debug=5;
 module_param(mrstov5640_debug, int, 0644);
@@ -183,17 +183,34 @@
 #define OV5640_POWER_OFF 0
 #define OV5640_POWER_ON 1
 
-#define OV5640_REG_RESET 0
+#define OV5640_REG_RESET 2
 #define OV5640_REG_INITED 1
+#define OV5640_REG_BEFORE_PROBE 0
 
+/*
+ * 6 -- VGA index in the array ov5640_res[],
+ * which is the default resolution setting
+ */
+
+#define RESOLUTION_INDEX_VGA 6
+
 static struct __ov5640_status_ {
+    /* lock */
+       spinlock_t state_lock;
+
+    /* sw status*/
        int current_res_i;
        int power;
        int reg_inited;
+       int hflip, vflip;
+
 } ov5640_status = {
-               .current_res_i = 6,//SENSOR_RES_VGA;
-               .power = OV5640_POWER_OFF,
-               .reg_inited = OV5640_REG_INITED,
+       .state_lock = __SPIN_LOCK_UNLOCKED(),
+       .current_res_i = RESOLUTION_INDEX_VGA,
+       .power = OV5640_POWER_OFF,
+       .reg_inited = OV5640_REG_BEFORE_PROBE,
+       .hflip = 0,
+       .vflip = 1,
 };
 
 /*
@@ -312,62 +329,77 @@
 static int ov5640_hw_init (struct i2c_client *c)
 {
        int ret;
-    DBG_entering;
+       unsigned long flags;
+       DBG_entering;
 
-    if (ov5640_status.reg_inited ==  OV5640_REG_INITED) {
-       return 0;
-    }
+       spin_lock_irqsave(&ov5640_status.state_lock, flags);
 
-       ret = ov5640_write(c, 0x3008, 0x82);
+       if (ov5640_status.reg_inited != OV5640_REG_RESET) {
+               spin_unlock_irqrestore(&ov5640_status.state_lock, flags);
+               ret = 0;
+               goto __ov5640_hw_init_exit;
+       }
+
+       ov5640_status.reg_inited = OV5640_REG_INITED;
+       ov5640_status.current_res_i = RESOLUTION_INDEX_VGA;
+       spin_unlock_irqrestore(&ov5640_status.state_lock, flags);
+
        /* Set registers into default config value */
-       ret += ov5640_write_array(c, ov5640_def_reg);
+       ret = ov5640_write_array(c, ov5640_def_reg);
        dprintk( 1, "[ov5640-wr-reg] <----------- load ov5640 default 
settings\n");
-       // turn on AGC/AEC
-       ov5640_write(c, 0x3503, 0x0);
-       ov5640_status.current_res_i = 6 ;
-
-       /* added by wen to stop sensor from streaming */
-       ov5640_write(c, 0x3008, 0x42);
+       /* turn on AGC/AEC */
+       ret += ov5640_write(c, 0x3503, 0x0);
        ov5640_set_data_pin_in(c);
-       msleep(300);
-       ov5640_status.reg_inited = OV5640_REG_INITED;
 
+__ov5640_hw_init_exit:
     DBG_leaving;
        return ret;
 }
 
-
+static int ov5640_save_hw_status(struct i2c_client *c);
+static int ov5640_restore_hw_status(struct i2c_client *c);
 static int ov5640_s_stream(struct v4l2_subdev *sd, int enable);
-
 /*
  * Sensor specific helper function
  */
-static int ov5640_standby(struct v4l2_subdev *sd)
+static void ov5640_standby(struct v4l2_subdev *sd)
 {
-       // set software power down instead.
-       ov5640_s_stream(sd, 0);
-       // set hw power down
-       //gpio_set_value(GPIO_STDBY_PIN, 1);
+       unsigned long flags;
+       struct i2c_client *c = v4l2_get_subdevdata(sd);
+
+       ov5640_save_hw_status(c);
+       ov5640_s_stream(sd , 0);
+       spin_lock_irqsave(&ov5640_status.state_lock, flags);
+
        ov5640_status.power = OV5640_POWER_OFF;
-       //ov5640_status.reg_inited = OV5640_REG_RESET;
+
+       if (ov5640_status.reg_inited == OV5640_REG_INITED)
+               ov5640_status.reg_inited = OV5640_REG_RESET;
+
+       spin_unlock_irqrestore(&ov5640_status.state_lock, flags);
        dprintk(1, "PM: ov5640 standby called\n");
-       return 0;
 }
 
-static int ov5640_wakeup(struct v4l2_subdev *sd, int hw_init)
+static void ov5640_wakeup(struct v4l2_subdev *sd, int hw_reinit)
 {
-       struct i2c_client *c = v4l2_get_subdevdata(sd);
-
+       unsigned long flags;
        dprintk(1, "PM: ov5640 wakeup called\n");
+       spin_lock_irqsave(&ov5640_status.state_lock, flags);
 
        if (ov5640_status.power == OV5640_POWER_OFF) {
+               ov5640_status.power = OV5640_POWER_ON;
+               spin_unlock_irqrestore(&ov5640_status.state_lock, flags);
                dprintk(1, "PM: ov5640 switch OFF to ON.\n");
                gpio_set_value(GPIO_STDBY_PIN, 0);
-               //if (hw_init) {        ov5640_hw_init(c); }
-               ov5640_status.power = OV5640_POWER_ON;
+               if (hw_reinit)  {
+                       struct i2c_client *c = v4l2_get_subdevdata(sd);
+                       ov5640_hw_init(c);
+                       ov5640_restore_hw_status(c);
+               }
+       } else {
+               spin_unlock_irqrestore(&ov5640_status.state_lock, flags);
        }
 
-       return 0;
 }
 
 static int ov5640_s_power(struct v4l2_subdev *sd, u32 val)
@@ -418,8 +450,11 @@
        info->mipi_lanes = MIPI_LANES;  /*MIPI lanes, 1 or 2*/
        memcpy(info->name, "ov5640", 7);
 
-       ov5640_status.reg_inited = OV5640_REG_RESET; // need do init reg here
+       ov5640_status.reg_inited = OV5640_REG_RESET; /* need do init reg here*/
+       ret = ov5640_write(c, 0x3013, 0x11);
+       ret = ov5640_write(c, 0x3008, 0x82);
        ret = ov5640_hw_init(c);
+       msleep(300);
 
         DBG_leaving;
 
@@ -584,6 +619,7 @@
 static int ov5640_set_fmt(struct v4l2_subdev *sd,
                        struct v4l2_mbus_framefmt *fmt)
 {
+       unsigned long flags;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ci_sensor_config *info = to_sensor_config(sd);
        int ret = 0;
@@ -606,25 +642,21 @@
                uint8_t target_res_index;
 
                target_res_index = find_OV5640_TIMING_index(res_index->res);
+               spin_lock_irqsave(&ov5640_status.state_lock, flags);
 
                if (ov5640_status.current_res_i != target_res_index) {
-                       u8 REG20,REG21,REG20_new,REG21_new;
+                       ov5640_status.current_res_i = target_res_index;
+                       spin_unlock_irqrestore(
+                                       &ov5640_status.state_lock, flags);
                        dprintk( 3, "[ov5640-wr-reg] <----------- changing res 
from index-%d to index-%d (%dx%d)", ov5640_status.current_res_i, 
target_res_index,width, height);
                        dprintk( 3, "[ov5640-wr-reg] <----------- Set 
resolutiojn Configs");
-
-                       // save original flip status
-                       ov5640_read(client,0x3820,&REG20);
-                       ov5640_read(client,0x3821,&REG21);
+                       ov5640_save_hw_status(client);
                        ret += ov5640_write_array(client, res_index->regs);
-                       // restore original flip status
-                       ov5640_read(client,0x3820,&REG20_new);
-                       ov5640_read(client,0x3821,&REG21_new);
-                       ov5640_write(client,0x3820,((REG20_new & 0xf9) | 
(REG20& 0x6)));
-                       ov5640_write(client,0x3821,((REG21_new & 0xf9) | 
(REG21& 0x6)));
-
-                       ov5640_status.current_res_i = target_res_index;
+                       ov5640_restore_hw_status(client);
                }
                else {
+                       spin_unlock_irqrestore(
+                                       &ov5640_status.state_lock, flags);
                        dprintk(3, "[ov5640-wr-reg] <----------- same res 
index-%d (%dx%d)", target_res_index,width, height);
                }
 
@@ -690,6 +722,7 @@
                //info->bpat = SENSOR_BPAT_BGBGGRGR;
        }
        err += ov5640_write(client, 0x3821, v);
+       ov5640_status.hflip = value;
        msleep(10);  /* FIXME */
 
        return err;
@@ -720,6 +753,7 @@
        else
                v &= ~0x06;
        err += ov5640_write(client, 0x3820, v);
+       ov5640_status.vflip = value;
        msleep(10);  /* FIXME */
 
        return err;
@@ -980,6 +1014,29 @@
        return ret;
 }
 
+static int ov5640_save_hw_status(struct i2c_client *c)
+{
+       int ret = 0;
+       /* flip status has already been saved in the ioctl,
+        * no need to save here
+        * */
+
+       /* TODO: save original hw status*/
+
+       return ret;
+}
+
+static int ov5640_restore_hw_status(struct i2c_client *c)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(c);
+       int ret = 0;
+
+       /* restore original flip status*/
+       ov5640_t_hflip(sd, ov5640_status.hflip);
+       ov5640_t_vflip(sd, ov5640_status.vflip);
+       return ret;
+}
+
 static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -995,10 +1052,8 @@
                        ov5640_write(client, 0x3008, 0x02);
                        msleep(300);
                }
-               //ov5640_set_data_pin_out(client);
        } else {
                ov5640_write(client, 0x3008, 0x42);
-               //ov5640_set_data_pin_in(client);
        }
 
        DBG_leaving;
@@ -1076,7 +1131,7 @@
        if (ov5640_res[ov5640_status.current_res_i].used) {
                for (fps_i = 0; fps_i < OV5640_N_FPS;  fps_i++) {
                        if (target_fps == 
ov5640_res[ov5640_status.current_res_i].fps[fps_i]) {
-                               // found the target fps
+                               /* found the target fps*/
                                u8 val;
                                dprintk( 1, "set sensor FPS to %d\n", 
target_fps);
                                ov5640_read(client, 0x3008, &val);
        Signed-off-by: Yong He <[email protected]>

Thanks,

-- Yong
Phone (+86) 21-61166334
Lab (+86) 21-61167881

Attachment: linux-2.6.37-camera-ov5640-ov9740-version-0.941_to_0.942.patch
Description: linux-2.6.37-camera-ov5640-ov9740-version-0.941_to_0.942.patch

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to