From: He, Yong <[email protected]<mailto:[email protected]>>
Subject: [PATCH] MRST Tablet camera driver ver-0.942 fix power saving mode issue

Hi,

This patch is going to fix the Bug 
7832<https://bugzilla.otcshare.org/show_bug.cgi?id=7832> - OV5640 camera sensor 
does not enter power saving mode.

the solution is to redo a hw_init() after power resume. And also added save & 
restore user's configurations before and after suspend.

Signed-off-by: He, Yong <[email protected]<mailto:[email protected]>>
---
Index: a/drivers/staging/mrstci/mrstov5640/ov5640.h
===================================================================
--- a/drivers/staging/mrstci/mrstov5640/ov5640.h        (revision 67)
+++ a/drivers/staging/mrstci/mrstov5640/ov5640.h     (working copy)
@@ -42,8 +42,8 @@


static struct regval_list ov5640_reg_reset[] = {
-                 {0x3103, 0x11},
-                 {0x3008, 0x82},
+//             {0x3103, 0x11},
+//             {0x3008, 0x82},
                   {0x3008, 0x42},
                   {0x3103, 0x03},
                   {0x3017, 0x00},
Index: a/drivers/staging/mrstci/mrstov5640/mrstov5640.c
===================================================================
--- a/drivers/staging/mrstci/mrstov5640/mrstov5640.c         (revision 67)
+++ a/drivers/staging/mrstci/mrstov5640/mrstov5640.c      (working copy)
@@ -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,26 @@
#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

static struct __ov5640_status_ {
+    // sw status
         int current_res_i;
         int power;
         int reg_inited;
+
+       // hw status
+       u8 REG20;
+       u8 REG21;
+
} ov5640_status = {
                   .current_res_i = 6,//SENSOR_RES_VGA;
                   .power = OV5640_POWER_OFF,
-                 .reg_inited = OV5640_REG_INITED,
+                .reg_inited = OV5640_REG_BEFORE_PROBE,
+        .REG20 = 0,
+        .REG21 = 0,
};

/*
@@ -314,56 +323,74 @@
         int ret;
     DBG_entering;

-    if (ov5640_status.reg_inited ==  OV5640_REG_INITED) {
+    if (ov5640_status.reg_inited !=  OV5640_REG_RESET) {
         return 0;
     }

-        ret = ov5640_write(c, 0x3008, 0x82);
         /* 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);
+       ret += ov5640_write(c, 0x3503, 0x0);
         ov5640_set_data_pin_in(c);
-        msleep(300);
         ov5640_status.reg_inited = OV5640_REG_INITED;
+    ov5640_status.current_res_i = 6 ;

     DBG_leaving;
         return ret;
}

+static int ov5640_save_hw_status(struct i2c_client *c)
+{
+    // save original flip status
+    ov5640_read(c,0x3820,&ov5640_status.REG20);
+    ov5640_read(c,0x3821,&ov5640_status.REG21);
+    return 0;
+}

-static int ov5640_s_stream(struct v4l2_subdev *sd, int enable);
+static int ov5640_restore_hw_status(struct i2c_client *c)
+{
+    u8 REG20_new,REG21_new;
+    // restore original flip status
+    ov5640_read(c,0x3820,&REG20_new);
+    ov5640_read(c,0x3821,&REG21_new);
+    ov5640_write(c,0x3820,((REG20_new & 0xf9) | (ov5640_status.REG20& 0x6)));
+    ov5640_write(c,0x3821,((REG21_new & 0xf9) | (ov5640_status.REG21& 0x6)));
+    return 0;
+}

/*
  * Sensor specific helper function
  */
static int 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);
+       gpio_set_value(GPIO_STDBY_PIN, 1);
         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;
+       }
+
         dprintk(1, "PM: ov5640 standby called\n");
         return 0;
}

-static int ov5640_wakeup(struct v4l2_subdev *sd, int hw_init)
+static int ov5640_wakeup(struct v4l2_subdev *sd, int hw_reinit)
{
-        struct i2c_client *c = v4l2_get_subdevdata(sd);
+       dprintk(1, "PM: ov5640 wakeup called (%d)\n",hw_reinit);

-        dprintk(1, "PM: ov5640 wakeup called\n");
-
-        if (ov5640_status.power == OV5640_POWER_OFF) {
+       if (ov5640_status.power == OV5640_POWER_OFF)
+       {
                   dprintk(1, "PM: ov5640 switch OFF to ON.\n");
                   gpio_set_value(GPIO_STDBY_PIN, 0);
-                 //if (hw_init) {  ov5640_hw_init(c); }
+                if (hw_reinit)
+                {
+                          struct i2c_client *c = v4l2_get_subdevdata(sd);
+                          ov5640_save_hw_status(c);
+                          ov5640_hw_init(c);
+                          ov5640_restore_hw_status(c);
+                }
                   ov5640_status.power = OV5640_POWER_ON;
         }

@@ -419,7 +446,11 @@
         memcpy(info->name, "ov5640", 7);

         ov5640_status.reg_inited = OV5640_REG_RESET; // need do init reg here
+       ret = ov5640_write(c, 0x3008, 0x82);
+       ret = ov5640_write(c, 0x3013, 0x11);
+       ret = ov5640_write(c, 0x3008, 0x82);
         ret = ov5640_hw_init(c);
+    msleep(300);

         DBG_leaving;

@@ -608,19 +639,12 @@
                   target_res_index = find_OV5640_TIMING_index(res_index->res);

                   if (ov5640_status.current_res_i != target_res_index) {
-                           u8 REG20,REG21,REG20_new,REG21_new;
                            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);
-                           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_save_hw_status(client);
+            ret += ov5640_write_array(client, res_index->regs);
+            ov5640_restore_hw_status(client);

                            ov5640_status.current_res_i = target_res_index;
                   }



Best Regards,

Yong He
Software Engineer, PCSD SW Solutions,
Intel Asia-Pacific R&D Ltd.
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