[PORT FROM R2] mt9e013: Add runtime check for old vs new VCM
authorJozef Kruger <jozef.kruger@intel.com>
Thu, 12 Jan 2012 23:31:38 +0000 (15:31 -0800)
committerbuildbot <buildbot@intel.com>
Fri, 20 Jan 2012 19:08:33 +0000 (11:08 -0800)
BZ: 20773

ORIG_BZ: 11145

This patch adds a check that uses the IFWI (firmware) version to determine
whether the VCM maintains focus position when the sensor module is put into
standby mode or not. This is a temporary feature that is needed as long as
prototype phones (earlier than PR3.3) are still being used. After those have
been phased out completely, this check can be removed.

Change-Id: I21b130e9a029d33f468a30f8f3f53b34c2cfc5b7
Orig-Change-Id: I5f2dd8545574f8e5d20c489fc3cfd357dc9611c1
Signed-off-by: Jozef Kruger <jozef.kruger@intel.com>
Reviewed-on: http://android.intel.com:8080/31764
Reviewed-by: Jong-a-lock, Robert <robert.jong-a-lock@intel.com>
Reviewed-by: Samurov, Vitali <vitali.samurov@intel.com>
Reviewed-by: Toivonen, Tuukka <tuukka.toivonen@intel.com>
Reviewed-by: Wang, Wen W <wen.w.wang@intel.com>
Tested-by: Lampila, KalleX <kallex.lampila@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
Reviewed-on: http://android.intel.com:8080/32602
Reviewed-by: Lampila, KalleX <kallex.lampila@intel.com>
drivers/media/video/mt9e013.c
drivers/media/video/mt9e013.h

index 013dc0f..d3da160 100644 (file)
 #include <linux/bitops.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
+#include <asm/intel_scu_ipc.h>
 
 #include "mt9e013.h"
 
 #define to_mt9e013_sensor(sd) container_of(sd, struct mt9e013_device, sd)
 
 #define HOME_POS 255
-
+#define PR3_2_FW 0x0400
+#define PR3_3_FW 0x0500
 
 /* divides a by b using half up rounding and div/0 prevention
  * (result is 0 if b == 0) */
@@ -904,6 +906,8 @@ static int mt9e013_init_registers(struct v4l2_subdev *sd)
 static int __mt9e013_init(struct v4l2_subdev *sd, u32 val)
 {
        int ret;
+       struct mt9e013_device *dev = to_mt9e013_sensor(sd);
+       u8 fw_rev[16];
 
        /* set inital registers */
        ret = mt9e013_init_registers(sd);
@@ -915,6 +919,25 @@ static int __mt9e013_init(struct v4l2_subdev *sd, u32 val)
        mt9e013_res = mt9e013_res_preview;
        N_RES = N_RES_PREVIEW;
 
+       /* The only way to detect whether this VCM maintains focus after putting
+        * the sensor into standby mode is by looking at the SCU FW version.
+        * PR3.3 or higher runs on FW version 05.00 or higher.
+        * We cannot distinguish between PR3.2 and PR3.25, so we need to be
+        * conservative. PR3.25 owners can change the comparison to compare
+        * to PR3_2_FW instead of PR3_3_FW for testing purposes.
+        */
+       dev->keeps_focus_pos = false;
+       ret |= intel_scu_ipc_command(IPCMSG_FW_REVISION, 0, NULL, 0,
+                                      (u32 *)fw_rev, 4);
+       if (ret == 0) {
+               u16 fw_version = (fw_rev[15] << 8) | fw_rev[14];
+               dev->keeps_focus_pos = fw_version >= PR3_3_FW;
+       }
+       if (!dev->keeps_focus_pos) {
+               v4l2_warn(sd, "VCM does not maintain focus position in standby"
+                             "mode, using software workaround\n");
+       }
+
        return ret;
 }
 
@@ -1701,8 +1724,7 @@ static int mt9e013_s_stream(struct v4l2_subdev *sd, int enable)
 
        mutex_lock(&dev->input_lock);
        if (enable) {
-               if (dev->sensor_revision <= 0x0) {
-                       /* begin: vcm hack, needs to be removed when new camera module is availible */
+               if (!dev->keeps_focus_pos) {
                        struct mt9e013_reg mt9e013_stream_enable[] = {
                                mt9e013_streaming[0],
                                {MT9E013_16BIT, {0x30F2}, 0x0000}, /* VCM_NEW_CODE */
@@ -1716,8 +1738,6 @@ static int mt9e013_s_stream(struct v4l2_subdev *sd, int enable)
                        mt9e013_stream_enable[3].val = (MT9E013_MAX_FOCUS_POS - dev->focus);
 
                        ret = mt9e013_write_reg_array(client, mt9e013_stream_enable);
-
-                       /* end: vcm hack, needs to be removed when new camera module is availible */
                } else {
                        ret = mt9e013_write_reg_array(client, mt9e013_streaming);
                }
index 8e5c5bb..96a6812 100644 (file)
@@ -386,6 +386,8 @@ struct mt9e013_device {
        s16 number_of_steps;
        struct mutex input_lock; /* serialize sensor's ioctl */
        void *otp_data;
+       /* Older VCMs could not maintain the focus position in standby mode. */
+       bool keeps_focus_pos;
 };
 
 #define MT9E013_MAX_WRITE_BUF_SIZE     32
@@ -596,7 +598,7 @@ static const struct mt9e013_reg mt9e013_start_streaming[] = {
 
 #define GROUPED_PARAMETER_HOLD_DISABLE {MT9E013_8BIT, {0x0104}, 0x0}
 
-#define INIT_VCM_CONTROL       {MT9E013_16BIT, {0x30F0}, 0x8004}  /* slew_rate[2:0] */
+#define INIT_VCM_CONTROL {MT9E013_16BIT, {0x30F0}, 0x800C} /* slew_rate[2:0] */
 static const struct mt9e013_reg mt9e013_init_vcm[] = {
        INIT_VCM_CONTROL,                                  /* VCM_CONTROL */
        {MT9E013_16BIT, {0x30F2}, 0x0000}, /* VCM_NEW_CODE */