Revert "Revert "media: video: tegra: sh532u: Focuser range tuning support""
Krupal Divvela [Thu, 2 Aug 2012 07:13:50 +0000 (12:13 +0530)]
Make focuser structs definitions same as
user space definitions

This reverts commit ca4bc41e88cf643169ccc4b10a6f130761f171da.

Bug 1027053
Bug 1026282

Change-Id: I91d0a0f5786a573efaa30ee0c55d65692001f37e
Signed-off-by: Krupal Divvela <kdivvela@nvidia.com>
Reviewed-on: http://git-master/r/120297
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Prayas Mohanty <pmohanty@nvidia.com>
Reviewed-by: Varun Wadekar <vwadekar@nvidia.com>

drivers/media/video/tegra/sh532u.c
include/media/nvc_focus.h

index 5bfbc48..86d8576 100644 (file)
 #define SH532U_TIMEOUT_MS      200
 #define SH532U_POS_LOW_DEFAULT 0xA000
 #define SH532U_POS_HIGH_DEFAULT        0x6000
-
+#define SH532U_SLEW_RATE                       1
+#define SH532U_POS_TRANSLATE           0
+#define SH532U_POS_SIGN_CHANGER                (-1)
 
 static u8 sh532u_ids[] = {
        0xF0,
@@ -151,6 +153,7 @@ struct sh532u_info {
        unsigned i2c_addr_rom;
        struct nvc_focus_nvc nvc;
        struct nvc_focus_cap cap;
+       struct nv_focuser_config config;
        enum nvc_focus_sts sts;
        struct sh532u_pdata_info cfg;
        bool reset_flag;
@@ -175,6 +178,8 @@ static struct nvc_focus_cap sh532u_default_cap = {
        .focus_macro    = SH532U_FOCUS_MACRO,
        .focus_hyper    = SH532U_FOCUS_HYPER,
        .focus_infinity = SH532U_FOCUS_INFINITY,
+       .slew_rate        = SH532U_SLEW_RATE,
+       .position_translate = SH532U_POS_TRANSLATE,
 };
 
 static struct nvc_focus_nvc sh532u_default_nvc = {
@@ -739,22 +744,31 @@ static void sh532u_sts_rd(struct sh532u_info *info)
        }
 }
 
-static s16 sh532u_rel2abs(struct sh532u_info *info, u32 rel_position)
+static s16 sh532u_rel2abs(struct sh532u_info *info, s32 rel_position)
 {
        s16 abs_pos;
 
        if (rel_position > info->cap.actuator_range)
                rel_position = info->cap.actuator_range;
-       rel_position = info->cap.actuator_range - rel_position;
-       if (rel_position) {
-               rel_position *= info->abs_range;
-               rel_position /= info->cap.actuator_range;
+       if (info->cap.position_translate)  {
+               rel_position = info->cap.actuator_range - rel_position;
+               if (rel_position) {
+                       rel_position *= info->abs_range;
+                       rel_position /= info->cap.actuator_range;
+               }
+               abs_pos = (s16)(info->abs_base + rel_position);
+       } else {
+               abs_pos = rel_position * SH532U_POS_SIGN_CHANGER;
        }
-       abs_pos = (s16)(info->abs_base + rel_position);
+
        if (abs_pos < info->cfg.limit_low)
                abs_pos = info->cfg.limit_low;
        if (abs_pos > info->cfg.limit_high)
                abs_pos = info->cfg.limit_high;
+
+       dev_dbg(&info->i2c_client->dev, "%s: rel_position %d returning abs_pos %d\n",
+                       __func__, rel_position, abs_pos);
+
        return abs_pos;
 }
 
@@ -766,12 +780,21 @@ static u32 sh532u_abs2rel(struct sh532u_info *info, s16 abs_position)
                abs_position = info->cfg.limit_high;
        if (abs_position < info->abs_base)
                abs_position = info->abs_base;
-       rel_pos = (u32)(abs_position - info->abs_base);
-       rel_pos *= info->cap.actuator_range;
-       rel_pos /= info->abs_range;
-       if (rel_pos > info->cap.actuator_range)
-               rel_pos = info->cap.actuator_range;
-       rel_pos = info->cap.actuator_range - rel_pos;
+
+       if (info->cap.position_translate) {
+               rel_pos = (u32)(abs_position - info->abs_base);
+               rel_pos *= info->cap.actuator_range;
+               rel_pos /= info->abs_range;
+
+               if (rel_pos > info->cap.actuator_range)
+                       rel_pos = info->cap.actuator_range;
+               rel_pos = info->cap.actuator_range - rel_pos;
+       } else {
+               rel_pos = abs_position * SH532U_POS_SIGN_CHANGER;
+       }
+       dev_dbg(&info->i2c_client->dev, "%s: abs_position %d returning rel_pos %d",
+                       __func__, abs_position, rel_pos);
+
        return rel_pos;
 }
 
@@ -785,7 +808,7 @@ static int sh532u_abs_pos_rd(struct sh532u_info *info, s16 *position)
        return err;
 }
 
-static int sh532u_rel_pos_rd(struct sh532u_info *info, u32 *position)
+static int sh532u_rel_pos_rd(struct sh532u_info *info, s32 *position)
 {
        s16 abs_pos;
        long msec;
@@ -814,9 +837,11 @@ static int sh532u_rel_pos_rd(struct sh532u_info *info, u32 *position)
                                pos = (int)info->pos_rel;
                }
        }
-       if (pos < 0)
-               pos = 0;
-       *position = (u32)pos;
+       if (info->cap.position_translate) {
+               if (pos < 0)
+                       pos = 0;
+       }
+       *position = pos;
        return 0;
 }
 
@@ -854,6 +879,8 @@ static void sh532u_calibration_caps(struct sh532u_info *info)
        rel_hi = info->cap.focus_infinity;
        info->abs_range = (u32)(info->cfg.pos_high - info->cfg.pos_low);
        loop_limit = (rel_lo > rel_hi) ? rel_lo : rel_hi;
+       dev_dbg(&info->i2c_client->dev, "%s: rel_lo %d rel_hi %d loop_limit %d\n",
+                               __func__, rel_lo, rel_hi, loop_limit);
        for (i = 0; i <= loop_limit; i++) {
                rel_range = info->cap.actuator_range - (rel_lo + rel_hi);
                step = info->abs_range / rel_range;
@@ -871,22 +898,36 @@ static void sh532u_calibration_caps(struct sh532u_info *info)
                                        abs_top <= info->cfg.limit_high)
                        break;
        }
+       dev_dbg(&info->i2c_client->dev, "%s: info->abs_range %d abs_base %d abs_top %d\n",
+                       __func__, info->abs_range, info->abs_base, abs_top);
+
+       if (!info->cap.position_translate && info->abs_range)
+               info->cap.actuator_range = info->abs_range;
+
        info->cap.focus_hyper = info->abs_range;
        info->abs_range = (u32)(abs_top - info->abs_base);
        /* calculate absolute hyperfocus position */
        info->cap.focus_hyper *= info->cfg.focus_hyper_ratio;
        info->cap.focus_hyper /= info->cfg.focus_hyper_div;
        abs_top = (s16)(info->cfg.pos_high - info->cap.focus_hyper);
+
        /* update actual relative positions */
        info->cap.focus_hyper = sh532u_abs2rel(info, abs_top);
+       dev_dbg(&info->i2c_client->dev, "%s: focus_hyper abs %d rel %d\n",
+                       __func__, abs_top, info->cap.focus_hyper);
+
        info->cap.focus_infinity = sh532u_abs2rel(info, info->cfg.pos_high);
+       dev_dbg(&info->i2c_client->dev, "%s: focus_infinity abs %d rel %d\n",
+                       __func__, info->cfg.pos_high, info->cap.focus_infinity);
+
        info->cap.focus_macro = sh532u_abs2rel(info, info->cfg.pos_low);
-       dev_dbg(&info->i2c_client->dev, "%s focus_macro=%u\n",
-               __func__, info->cap.focus_macro);
-       dev_dbg(&info->i2c_client->dev, "%s focus_infinity=%u\n",
-               __func__, info->cap.focus_infinity);
-       dev_dbg(&info->i2c_client->dev, "%s focus_hyper=%u\n",
-               __func__, info->cap.focus_hyper);
+       dev_dbg(&info->i2c_client->dev, "%s: focus_macro abs %d rel %d\n",
+                       __func__, info->cfg.pos_low, info->cap.focus_macro);
+
+       dev_dbg(&info->i2c_client->dev, "%s: Version %d actuator_range %d "
+                       "settle_time %d position_traslate %d\n",
+                       __func__, info->cap.version, info->cap.actuator_range,
+                       info->cap.settle_time, info->cap.position_translate);
 }
 
 static int sh532u_calibration(struct sh532u_info *info, bool use_defaults)
@@ -895,8 +936,11 @@ static int sh532u_calibration(struct sh532u_info *info, bool use_defaults)
        int err;
        int ret = 0;
 
-       if (info->init_cal_flag)
+       if (info->init_cal_flag) {
+               dev_dbg(&info->i2c_client->dev, "%s: Already initialized"
+                               "Returning\n", __func__);
                return 0;
+       }
 
        /*
         * Get Inf1, Mac1
@@ -968,8 +1012,9 @@ static int sh532u_calibration(struct sh532u_info *info, bool use_defaults)
         *  1     PASS  PASS   Continue to calculations
         */
        /* err = DATA where FAIL = 1 */
-       if (!info->cfg.pos_low || !info->cfg.pos_high ||
-                       !info->cfg.limit_low || !info->cfg.limit_high)
+       if (!info->cfg.pos_low || info->cfg.pos_high <= info->cfg.pos_low ||
+               !info->cfg.limit_low ||
+               info->cfg.limit_high <= info->cfg.limit_low)
                err = 1;
        else
                err = 0;
@@ -1001,6 +1046,7 @@ static int sh532u_calibration(struct sh532u_info *info, bool use_defaults)
                __func__, (int)info->cfg.limit_low);
        dev_dbg(&info->i2c_client->dev, "%s limit_high=%d\n",
                __func__, (int)info->cfg.limit_high);
+
        sh532u_calibration_caps(info);
        info->init_cal_flag = 1;
        dev_dbg(&info->i2c_client->dev, "%s complete\n", __func__);
@@ -1218,6 +1264,7 @@ static int sh532u_pos_abs_wr(struct sh532u_info *info, s16 tar_pos)
                                       STMLFF_OFF |
                                       STMVEN_ON));
        }
+       dev_dbg(&info->i2c_client->dev, "%s: position %d\n", __func__, tar_pos);
        return err;
 }
 
@@ -1292,30 +1339,101 @@ static int sh532u_hvca_pos_init(struct sh532u_info *info)
        return err;
 }
 
-static int sh532u_pos_rel_wr(struct sh532u_info *info, u32 position)
+static int sh532u_pos_rel_wr(struct sh532u_info *info, s32 position)
 {
        s16 abs_pos;
 
-       if (position > info->cap.actuator_range) {
-               dev_err(&info->i2c_client->dev, "%s invalid position %u\n",
-                       __func__, position);
-               return -EINVAL;
+       if (info->cap.position_translate) {
+               if (position > info->cap.actuator_range) {
+                       dev_err(&info->i2c_client->dev, "%s invalid position %d\n",
+                               __func__, position);
+                       return -EINVAL;
+               }
        }
-
        abs_pos = sh532u_rel2abs(info, position);
+
        info->pos_rel = position;
        info->pos_abs = abs_pos;
        info->pos_time_wr = jiffies;
        return sh532u_pos_abs_wr(info, abs_pos);
 }
 
+static void sh532u_get_focuser_capabilities(struct sh532u_info *info)
+{
+       memset(&info->config, 0, sizeof(info->config));
+
+       info->config.focal_length = info->nvc.focal_length;
+       info->config.fnumber = info->nvc.fnumber;
+       info->config.max_aperture = info->nvc.fnumber;
+       info->config.range_ends_reversed = (SH532U_POS_SIGN_CHANGER == -1)
+                                                               ? 1 : 0;
+
+       info->config.settle_time = info->cap.settle_time;
+
+       /*
+        * We do not use pos_working_low and pos_working_high
+        * in the kernel driver.
+        */
+       info->config.pos_working_low = AF_POS_INVALID_VALUE;
+       info->config.pos_working_high = AF_POS_INVALID_VALUE;
+
+       info->config.pos_actual_low = info->cfg.limit_high *
+                                                       SH532U_POS_SIGN_CHANGER;
+       info->config.pos_actual_high = info->cfg.limit_low *
+                                                       SH532U_POS_SIGN_CHANGER;
+       info->config.slew_rate = info->cap.slew_rate;
+       info->config.circle_of_confusion = -1;
+
+       /*
+        * These need to be passed up once we have the EEPROM/OTP read
+        * routines in teh kernel. These need to be passed up much earlier on.
+        * Till we have these routines, we pass them up as part of the get call.
+        */
+       info->config.num_focuser_sets = 1;
+       info->config.focuser_set[0].posture = 'S';
+       info->config.focuser_set[0].macro = info->cap.focus_macro;
+       info->config.focuser_set[0].hyper = info->cap.focus_hyper;
+       info->config.focuser_set[0].inf = info->cap.focus_infinity;
+       info->config.focuser_set[0].hysteresis = 0;
+       info->config.focuser_set[0].settle_time = info->cap.settle_time;
+       info->config.focuser_set[0].num_dist_pairs = 0;
+
+       dev_dbg(&info->i2c_client->dev, "%s: pos_actual_low %d pos_actual_high %d "
+               " settle_time %d\n", __func__, info->config.pos_actual_low,
+               info->config.pos_actual_high, info->cap.settle_time);
+
+}
+
+
+static int sh532u_set_focuser_capabilities(struct sh532u_info *info,
+                                       struct nvc_param *params)
+{
+       if (copy_from_user(&info->config, (const void __user *)params->p_value,
+               params->sizeofvalue)) {
+               dev_err(&info->i2c_client->dev, "%s Error: copy_from_user bytes %d\n",
+                               __func__, params->sizeofvalue);
+               return -EFAULT;
+       }
+
+       /* info.config.focuser_set[0].posture, macro, hyper, infinity and
+        * hysterisis can remain there only. We need only settle_time &
+        * slew_rate for use here.
+        */
+       info->cap.settle_time = info->config.focuser_set[0].settle_time;
+       info->config.slew_rate = info->config.slew_rate;
+
+       dev_dbg(&info->i2c_client->dev, "%s: copy_from_user bytes %d\n",
+                       __func__,  params->sizeofvalue);
+       return 0;
+}
+
 
 static int sh532u_param_rd(struct sh532u_info *info, unsigned long arg)
 {
        struct nvc_param params;
        const void *data_ptr;
        u32 data_size = 0;
-       u32 position;
+       s32 position;
        int err;
 
        if (copy_from_user(&params,
@@ -1369,16 +1487,14 @@ static int sh532u_param_rd(struct sh532u_info *info, unsigned long arg)
                sh532u_pm_dev_wr(info, NVC_PWR_STDBY);
                if (err)
                        return -EIO;
+               dev_dbg(&info->i2c_client->dev, "%s: NVC_PARAM_CAPS: params.param %d "
+                               "params.sizeofvalue %d\n",
+                               __func__, params.param, params.sizeofvalue);
 
-               data_ptr = &info->cap;
-               /* there are different sizes depending on the version */
-               /* send back just what's requested or our max size */
-               if (params.sizeofvalue < sizeof(info->cap))
-                       data_size = params.sizeofvalue;
-               else
-                       data_size = sizeof(info->cap);
-               dev_dbg(&info->i2c_client->dev, "%s CAPS\n",
-                       __func__);
+               sh532u_get_focuser_capabilities(info);
+
+               data_ptr = &info->config;
+               data_size = params.sizeofvalue;
                break;
 
        case NVC_PARAM_STS:
@@ -1424,16 +1540,15 @@ static int sh532u_param_wr_s(struct sh532u_info *info,
                             struct nvc_param *params,
                             u32 u32val)
 {
-       struct nvc_focus_cap cap;
        u8 u8val;
        int err;
 
        u8val = (u8)u32val;
        switch (params->param) {
        case NVC_PARAM_LOCUS:
-               dev_dbg(&info->i2c_client->dev, "%s LOCUS: %u\n",
-                       __func__, u32val);
-               err = sh532u_pos_rel_wr(info, u32val);
+               dev_dbg(&info->i2c_client->dev, "%s LOCUS: %d\n",
+                       __func__, (s32) u32val);
+               err = sh532u_pos_rel_wr(info, (s32) u32val);
                return err;
 
        case NVC_PARAM_RESET:
@@ -1449,27 +1564,9 @@ static int sh532u_param_wr_s(struct sh532u_info *info,
                return err;
 
        case NVC_PARAM_CAPS:
-               dev_dbg(&info->i2c_client->dev, "%s CAPS\n",
-                       __func__);
-               if (copy_from_user(&cap, (const void __user *)params->p_value,
-                                  sizeof(params->sizeofvalue))) {
-                       dev_err(&info->i2c_client->dev, "%s %d copy_from_user err\n",
-                               __func__, __LINE__);
-                       return -EFAULT;
-               }
-
-               if (!cap.version)
-                       return -EINVAL;
-
-               if (cap.version >= NVC_FOCUS_CAP_VER1)
-                       info->cap.actuator_range = cap.actuator_range;
-               if (cap.version >= NVC_FOCUS_CAP_VER2) {
-                       info->cap.focus_macro = cap.focus_macro;
-                       info->cap.focus_hyper = cap.focus_hyper;
-                       info->cap.focus_infinity = cap.focus_infinity;
-               }
-               sh532u_calibration_caps(info);
-               return 0;
+               dev_dbg(&info->i2c_client->dev, "%s CAPS. Error. sh532u_param_wr "
+                               "should be called instead\n", __func__);
+               return -EFAULT;
 
        default:
                dev_dbg(&info->i2c_client->dev,
@@ -1578,6 +1675,14 @@ static int sh532u_param_wr(struct sh532u_info *info, unsigned long arg)
 
                return err;
 
+       case NVC_PARAM_CAPS:
+               if (sh532u_set_focuser_capabilities(info, &params)) {
+                       dev_err(&info->i2c_client->dev, "%s: Error: copy_from_user bytes %d\n",
+                                       __func__, params.sizeofvalue);
+                       return -EFAULT;
+               }
+               return 0;
+
        default:
        /* parameters dependent on sync mode */
                switch (info->s_mode) {
@@ -1832,7 +1937,6 @@ static int sh532u_probe(
        char dname[16];
        int err;
 
-       dev_dbg(&client->dev, "%s\n", __func__);
        info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
        if (info == NULL) {
                dev_err(&client->dev, "%s: kzalloc error\n", __func__);
index c6ff1fa..e37d897 100644 (file)
@@ -33,6 +33,8 @@
 #define NVC_FOCUS_CAP_VER2             2
 #define NVC_FOCUS_CAP_VER              2 /* latest version */
 
+#define AF_POS_INVALID_VALUE INT_MAX
+
 enum nvc_focus_sts {
        NVC_FOCUS_STS_UNKNOWN           = 1,
        NVC_FOCUS_STS_NO_DEVICE,
@@ -52,11 +54,13 @@ struct nvc_focus_nvc {
 
 struct nvc_focus_cap {
        __u32 version;
-       __u32 actuator_range;
+       __s32 actuator_range;
        __u32 settle_time;
-       __u32 focus_macro;
-       __u32 focus_hyper;
-       __u32 focus_infinity;
+       __s32 focus_macro;
+       __s32 focus_hyper;
+       __s32 focus_infinity;
+       __u32 slew_rate;
+       __u32 position_translate;
 } __packed;
 
 
@@ -66,7 +70,7 @@ struct nvc_focus_cap {
 struct nv_focuser_set_dist_pairs {
        __s32 fdn;
        __s32 distance;
-};
+} __packed;
 
 struct nv_focuser_set {
        __s32 posture;
@@ -78,23 +82,26 @@ struct nv_focuser_set {
        __s32 macro_offset;
        __s32 inf_offset;
        __u32 num_dist_pairs;
-       struct nv_focuser_set_dist_pairs dist_pair[NV_FOCUSER_SET_DISTANCE_PAIR];
-};
+       struct nv_focuser_set_dist_pairs
+                       dist_pair[NV_FOCUSER_SET_DISTANCE_PAIR];
+} __packed;
 
 struct nv_focuser_config {
        __u32 focal_length;
        __u32 fnumber;
        __u32 max_aperture;
-       __u32 actuator_range;
+       __s32 actuator_range;
        __u32 settle_time;
+       __u32 range_ends_reversed;
        __s32 pos_working_low;
        __s32 pos_working_high;
        __s32 pos_actual_low;
        __s32 pos_actual_high;
        __u32 slew_rate;
        __u32 circle_of_confusion;
+       __u32 num_focuser_sets;
        struct nv_focuser_set focuser_set[NV_FOCUSER_SET_MAX];
-};
+} __packed;
 
 
 #endif /* __NVC_FOCUS_H__ */