[PORT FROM R2] atomisp: mt9e013: add fuseid data to sensor's private data
authorDavid Cohen <david.a.cohen@intel.com>
Fri, 2 Dec 2011 16:12:33 +0000 (18:12 +0200)
committerbuildbot <buildbot@intel.com>
Thu, 2 Feb 2012 10:47:14 +0000 (02:47 -0800)
BZ: 21906

ORIG-BZ: 15475

FUSEID information is necessary to userspace. This patch adds FUSEID
to sensor's private data.

Change-Id: I12eb18309de497db8d9983dc4c632e5339cd2096
Orig-Change-Id: Ic9995c477d9930e87ef958a73d3ac9b64d39b29c
Signed-off-by: David Cohen <david.a.cohen@intel.com>
Reviewed-on: http://android.intel.com:8080/27052
Reviewed-by: Jong-a-lock, Robert <robert.jong-a-lock@intel.com>
Reviewed-by: Tuppurainen, Miikka <miikka.tuppurainen@intel.com>
Reviewed-by: Koskinen, Ilkka <ilkka.koskinen@intel.com>
Tested-by: Koski, Anttu <anttu.koski@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
Reviewed-on: http://android.intel.com:8080/33538
Reviewed-by: Lampila, KalleX <kallex.lampila@intel.com>
Reviewed-by: Gross, Mark <mark.gross@intel.com>
Reviewed-by: Koski, Anttu <anttu.koski@intel.com>
drivers/media/video/mt9e013.c
drivers/media/video/mt9e013.h

index 8d3818c..ccae716 100644 (file)
@@ -837,39 +837,83 @@ static void *mt9e013_otp_read(struct v4l2_subdev *sd)
        return buf;
 }
 
+static u8 *mt9e013_fuseid_read(struct v4l2_subdev *sd)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       u8 data[MT9E013_FUSEID_SIZE];
+       u8 *fuseid;
+       int ret, i;
+
+       ret = mt9e013_read_reg_array(client, MT9E013_FUSEID_SIZE,
+                                    MT9E013_FUSEID_START_ADDR, &data);
+       if (ret < 0) {
+               v4l2_err(client, "%s: error reading FUSEID.\n", __func__);
+               return ERR_PTR(ret);
+       }
+
+       fuseid = kmalloc(sizeof(*fuseid) * MT9E013_FUSEID_SIZE, GFP_KERNEL);
+
+       if (!fuseid) {
+               v4l2_err(client, "%s: no memory available when reading "
+                                "FUSEID.\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       /* FUSEID is in reverse order */
+       for (i = 0; i < MT9E013_FUSEID_SIZE; i++)
+               fuseid[i] = data[MT9E013_FUSEID_SIZE - i - 1];
+
+       return fuseid;
+}
+
 static int mt9e013_g_priv_int_data(struct v4l2_subdev *sd,
                                   struct v4l2_private_int_data *priv)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9e013_device *dev = to_mt9e013_sensor(sd);
+       u8 *to = priv->data;
        u32 read_size = priv->size;
        int ret;
 
        /* No OTP data available on sensor */
-       if (!dev->otp_data)
+       if (!dev->otp_data || !dev->fuseid)
                return -EIO;
 
-       if (!priv)
-               return -EINVAL;
-
-       /* Return correct size */
-       priv->size = MT9E013_OTP_DATA_SIZE;
-
        /* No need to copy data if size is 0 */
        if (!read_size)
-               return 0;
+               goto out;
 
        /* Correct read_size value only if bigger than maximum */
        if (read_size > MT9E013_OTP_DATA_SIZE)
                read_size = MT9E013_OTP_DATA_SIZE;
 
-       ret = copy_to_user(priv->data, dev->otp_data, read_size);
+       ret = copy_to_user(to, dev->otp_data, read_size);
        if (ret) {
                v4l2_err(client, "%s: failed to copy OTP data to user\n",
                         __func__);
                return -EFAULT;
        }
 
+       /* No room for FUSEID */
+       if (priv->size <= MT9E013_OTP_DATA_SIZE)
+               goto out;
+
+       read_size = priv->size - MT9E013_OTP_DATA_SIZE;
+       if (read_size > MT9E013_FUSEID_SIZE)
+               read_size = MT9E013_FUSEID_SIZE;
+       to += MT9E013_OTP_DATA_SIZE;
+
+       ret = copy_to_user(to, dev->fuseid, read_size);
+       if (ret) {
+               v4l2_err(client, "%s: failed to copy FUSEID to user\n",
+                        __func__);
+               return -EFAULT;
+       }
+
+out:
+       /* Return correct size */
+       priv->size = MT9E013_OTP_DATA_SIZE + MT9E013_FUSEID_SIZE;
+
        return 0;
 }
 
@@ -1827,6 +1871,7 @@ static int mt9e013_s_config(struct v4l2_subdev *sd,
        u16 sensor_id;
        int ret;
        void *otp_data;
+       void *fuseid;
 
        if (pdata == NULL)
                return -ENODEV;
@@ -1861,6 +1906,10 @@ static int mt9e013_s_config(struct v4l2_subdev *sd,
        if (!IS_ERR(otp_data))
                dev->otp_data = otp_data;
 
+       fuseid = mt9e013_fuseid_read(sd);
+       if (!IS_ERR(fuseid))
+               dev->fuseid = fuseid;
+
        /* power off sensor */
        ret = mt9e013_s_power(sd, 0);
        mutex_unlock(&dev->input_lock);
@@ -2093,6 +2142,7 @@ static int mt9e013_remove(struct i2c_client *client)
        dev->platform_data->csi_cfg(sd, 0);
        v4l2_device_unregister_subdev(sd);
        kfree(dev->otp_data);
+       kfree(dev->fuseid);
        kfree(dev);
 
        return 0;
index 96a6812..144cb19 100644 (file)
@@ -358,6 +358,8 @@ struct mt9e013_format {
        struct s_register_setting *regs;
 };
 
+#define MT9E013_FUSEID_SIZE            8
+#define MT9E013_FUSEID_START_ADDR      0x31f4
 
 /* mt9e013 device structure */
 struct mt9e013_device {
@@ -386,6 +388,7 @@ struct mt9e013_device {
        s16 number_of_steps;
        struct mutex input_lock; /* serialize sensor's ioctl */
        void *otp_data;
+       void *fuseid;
        /* Older VCMs could not maintain the focus position in standby mode. */
        bool keeps_focus_pos;
 };
@@ -606,7 +609,7 @@ static const struct mt9e013_reg mt9e013_init_vcm[] = {
        {MT9E013_TOK_TERM, {0}, 0}
 };
 
-#define RESET_REGISTER {MT9E013_16BIT, {0x301A}, 0x4A18}
+#define RESET_REGISTER {MT9E013_16BIT, {0x301A}, 0x4A38}
 static const struct mt9e013_reg mt9e013_reset_register[] = {
        RESET_REGISTER,
        {MT9E013_TOK_TERM, {0}, 0}