rk30:improve gsensors precision
authorlw@rock-chips.com <lw@rock-chips.com>
Sun, 1 Apr 2012 10:16:37 +0000 (18:16 +0800)
committerlw <lw@rock-chips.com>
Sun, 1 Apr 2012 10:16:51 +0000 (18:16 +0800)
drivers/input/gsensor/bma023.c
drivers/input/gsensor/mma7660.c
drivers/input/gsensor/mma8452.c
include/linux/mma7660.h
include/linux/mma8452.h

index 4fe4f4979d607a9304e782a774ce86df49b95d0b..3d06c8bb6cc6fefd3887fe8f13c700562678c7c1 100755 (executable)
 #define BMA150_RANGE_4G                        1
 #define BMA150_RANGE_8G                        2
 
+#define BMA150_RANGE                   2000000
+#define BMA150_PRECISION               10
+#define BMA150_BOUNDARY                        (0x1 << (BMA150_PRECISION - 1))
+#define BMA150_GRAVITY_STEP            BMA150_RANGE / BMA150_BOUNDARY
+
 #define BMA150_BW_25HZ         0
 #define BMA150_BW_50HZ         1
 #define BMA150_BW_100HZ                2
 #define BMA150_MODE_WAKE_UP     3
 
 struct bma150acc{
-       s16     x,
+       s64     x,
                y,
                z;
 } ;
@@ -413,28 +418,49 @@ static int bma150_read_accel_xyz(struct i2c_client *client,
 
                acc->x = BMA150_GET_BITSLICE(data[0], BMA150_ACC_X_LSB) |
                        (BMA150_GET_BITSLICE(data[1], BMA150_ACC_X_MSB)<<
-                                                       BMA150_ACC_X_LSB__LEN);
+                                                       BMA150_ACC_X_LSB__LEN); 
+               if (acc->x < BMA150_BOUNDARY)
+                               acc->x = acc->x * BMA150_GRAVITY_STEP;
+               else
+                               acc->x = ~( ((~acc->x & (0x7fff>>(16-BMA150_PRECISION)) ) + 1) 
+                                               * BMA150_GRAVITY_STEP) + 1;
+#if 0
                acc->x = acc->x << (sizeof(short)*8-(BMA150_ACC_X_LSB__LEN+
                                                        BMA150_ACC_X_MSB__LEN));
                acc->x = acc->x >> (sizeof(short)*8-(BMA150_ACC_X_LSB__LEN+
                                                        BMA150_ACC_X_MSB__LEN));
+#endif
 
                acc->y = BMA150_GET_BITSLICE(data[2], BMA150_ACC_Y_LSB) |
                        (BMA150_GET_BITSLICE(data[3], BMA150_ACC_Y_MSB)<<
                                                        BMA150_ACC_Y_LSB__LEN);
+               if (acc->y < BMA150_BOUNDARY)
+                               acc->y = acc->y * BMA150_GRAVITY_STEP;
+               else
+                               acc->y = ~( ((~acc->y & (0x7fff>>(16-BMA150_PRECISION)) ) + 1) 
+                                               * BMA150_GRAVITY_STEP) + 1;
+#if 0
                acc->y = acc->y << (sizeof(short)*8-(BMA150_ACC_Y_LSB__LEN +
                                                        BMA150_ACC_Y_MSB__LEN));
                acc->y = acc->y >> (sizeof(short)*8-(BMA150_ACC_Y_LSB__LEN +
                                                        BMA150_ACC_Y_MSB__LEN));
+#endif
 
 
                acc->z = BMA150_GET_BITSLICE(data[4], BMA150_ACC_Z_LSB);
                acc->z |= (BMA150_GET_BITSLICE(data[5], BMA150_ACC_Z_MSB)<<
                                                        BMA150_ACC_Z_LSB__LEN);
+               if (acc->z < BMA150_BOUNDARY)
+                               acc->z = acc->z * BMA150_GRAVITY_STEP;
+               else
+                               acc->z = ~( ((~acc->z & (0x7fff>>(16-BMA150_PRECISION)) ) + 1) 
+                                               * BMA150_GRAVITY_STEP) + 1;
+#if 0
                acc->z = acc->z << (sizeof(short)*8-(BMA150_ACC_Z_LSB__LEN+
                                                        BMA150_ACC_Z_MSB__LEN));
                acc->z = acc->z >> (sizeof(short)*8-(BMA150_ACC_Z_LSB__LEN+
                                                        BMA150_ACC_Z_MSB__LEN));
+#endif
 
        }
 
@@ -446,7 +472,7 @@ static void bma150_work_func(struct work_struct *work)
        struct bma150_data *bma150 = container_of((struct delayed_work *)work,
                        struct bma150_data, work);
        static struct bma150acc acc;
-       s16     x,y,z;
+       s32     x,y,z;
        unsigned long delay = msecs_to_jiffies(atomic_read(&bma150->delay));
        struct bma023_platform_data *pdata = pdata = (bma150->bma150_client)->dev.platform_data;
 
@@ -461,9 +487,9 @@ static void bma150_work_func(struct work_struct *work)
                y = acc.y;
                z = acc.z;
        }
-       input_report_abs(bma150->input, ABS_X, x<<2);
-       input_report_abs(bma150->input, ABS_Y, y<<2);
-       input_report_abs(bma150->input, ABS_Z, z<<2);
+       input_report_abs(bma150->input, ABS_X, x);
+       input_report_abs(bma150->input, ABS_Y, y);
+       input_report_abs(bma150->input, ABS_Z, z);
        input_sync(bma150->input);
        mutex_lock(&bma150->value_mutex);
        bma150->value.x = x;
@@ -582,7 +608,7 @@ static ssize_t bma150_value_show(struct device *dev,
        acc_value = bma150->value;
        mutex_unlock(&bma150->value_mutex);
 
-       return sprintf(buf, "%d %d %d\n", acc_value.x, acc_value.y,
+       return sprintf(buf, "%ll %ll %ll\n", acc_value.x, acc_value.y,
                        acc_value.z);
 }
 
@@ -812,12 +838,12 @@ static long bma023_ioctl( struct file *file, unsigned int cmd, unsigned long arg
                
        case BMA_IOCTL_GETDATA:
                mutex_lock(&bma150->value_mutex);
-               if(abs(sense_data.x-bma150->value.x)>10)//·À¶¶¶¯
-                       sense_data.x=bma150->value.x<<2;
-               if(abs(sense_data.y-(bma150->value.y))>10)//·À¶¶¶¯
-                       sense_data.y=bma150->value.y<<2;
-               if(abs(sense_data.z-(bma150->value.z))>10)//·À¶¶¶¯
-                       sense_data.z=bma150->value.z<<2;
+               if(abs(sense_data.x-bma150->value.x)>40000)//·À¶¶¶¯
+                       sense_data.x=bma150->value.x;
+               if(abs(sense_data.y-(bma150->value.y))>40000)//·À¶¶¶¯
+                       sense_data.y=bma150->value.y;
+               if(abs(sense_data.z-(bma150->value.z))>40000)//·À¶¶¶¯
+                       sense_data.z=bma150->value.z;
               //bma150->value = acc;
                mutex_unlock(&bma150->value_mutex);
 
index 585f6eace78b196e2019fd4d527d615c15522721..bf6c734802bdd6bdc10b6c726519aad1c1aad0b5 100644 (file)
@@ -319,8 +319,7 @@ static int mma7660_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static int mma7660_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-          unsigned long arg)
+static long mma7660_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 
        void __user *argp = (void __user *)arg;
@@ -414,12 +413,12 @@ static struct file_operations mma7660_fops = {
        .owner = THIS_MODULE,
        .open = mma7660_open,
        .release = mma7660_release,
-       .ioctl = mma7660_ioctl,
+       .unlocked_ioctl = mma7660_ioctl,
 };
 
 static struct miscdevice mma7660_device = {
        .minor = MISC_DYNAMIC_MINOR,
-       .name = "gsensor",//"mma7660_daemon",
+       .name = "mma8452_daemon",//"mma7660_daemon",
        .fops = &mma7660_fops,
 };
 
@@ -562,11 +561,11 @@ static int  mma7660_probe(struct i2c_client *client, const struct i2c_device_id
        set_bit(EV_ABS, mma7660->input_dev->evbit);
 
        /* x-axis acceleration */
-       input_set_abs_params(mma7660->input_dev, ABS_X, -1500, 1500, 0, 0);
+       input_set_abs_params(mma7660->input_dev, ABS_X, -MMA7660_RANGE, MMA7660_RANGE, 0, 0);
        /* y-axis acceleration */
-       input_set_abs_params(mma7660->input_dev, ABS_Y, -1500, 1500, 0, 0);
+       input_set_abs_params(mma7660->input_dev, ABS_Y, -MMA7660_RANGE, MMA7660_RANGE, 0, 0);
        /* z-axis acceleration */
-       input_set_abs_params(mma7660->input_dev, ABS_Z, -1500, 1500, 0, 0);
+       input_set_abs_params(mma7660->input_dev, ABS_Z, -MMA7660_RANGE, MMA7660_RANGE, 0, 0);
 
        mma7660->input_dev->name = "compass";
        mma7660->input_dev->dev.parent = &client->dev;
index b745fb5b5b7bd839b8a08bff1ac30972cf84dbb6..37f469a4a5098566fa883af3d52d20a64b474a65 100755 (executable)
@@ -56,6 +56,7 @@ static int  mma8452_probe(struct i2c_client *client, const struct i2c_device_id
 #define MMA8452_SPEED          200 * 1000
 #define MMA8451_DEVID          0x1a
 #define MMA8452_DEVID          0x2a
+#define MMA8453_DEVID          0x3a
 /* Addresses to scan -- protected by sense_data_mutex */
 //static char sense_data[RBUFF_SIZE + 1];
 static struct i2c_client *this_client;
@@ -66,8 +67,9 @@ static DECLARE_WAIT_QUEUE_HEAD(data_ready_wq);
 #ifdef CONFIG_HAS_EARLYSUSPEND
 static struct early_suspend mma8452_early_suspend;
 #endif
-//static int revision = -1;
+static int revision = -1;
 static const char* vendor = "Freescale Semiconductor";
+static char devid;
 
 
 typedef char status_t;
@@ -197,7 +199,6 @@ static int mma845x_active(struct i2c_client *client,int enable)
        return ret;
 }
 
-#if 0
 static int mma8452_start_test(struct i2c_client *client)
 {
        int ret = 0;
@@ -242,7 +243,6 @@ static int mma8452_start_test(struct i2c_client *client)
 
        return ret;
 }
-#endif
 
 static int mma8452_start_dev(struct i2c_client *client, char rate)
 {
@@ -328,17 +328,56 @@ static int mma8452_reset_rate(struct i2c_client *client, char rate)
        return ret ;
 }
 
-static inline int mma8452_convert_to_int(char value)
+static inline int mma8452_convert_to_int(const char high_byte, const char low_byte)
 {
-    int result;
-
-    if (value < MMA8452_BOUNDARY) {
-       result = value * MMA8452_GRAVITY_STEP / 10;
+    s64 result;
+/* enabled only if FREAD MODE */
+/*
+    if (high_byte < MMA8452_BOUNDARY) {
+       result = high_byte * MMA8452_GRAVITY_STEP;
     } else {
-       result = ~(((~value & 0x7f) + 1)* MMA8452_GRAVITY_STEP / 10) + 1;
+       result = ~(((~high_byte&0x7f) + 1) * MMA8452_GRAVITY_STEP) + 1;
+    }
+*/
+       switch (devid) {
+
+               case MMA8451_DEVID:
+                       result = ((int)high_byte << (MMA8451_PRECISION-8)) 
+                                       | ((int)low_byte >> (16-MMA8451_PRECISION));
+                       if (result < MMA8451_BOUNDARY)
+                               result = result* MMA8451_GRAVITY_STEP;
+               else
+                               result = ~( ((~result & (0x7fff>>(16-MMA8451_PRECISION)) ) + 1) 
+                                               * MMA8451_GRAVITY_STEP) + 1;
+                       break;
+
+               case MMA8452_DEVID:
+                       result = ((int)high_byte << (MMA8452_PRECISION-8)) 
+                                       | ((int)low_byte >> (16-MMA8452_PRECISION));
+                       if (result < MMA8452_BOUNDARY)
+                               result = result* MMA8452_GRAVITY_STEP;
+               else
+                               result = ~( ((~result & (0x7fff>>(16-MMA8452_PRECISION)) ) + 1) 
+                                               * MMA8452_GRAVITY_STEP) + 1;
+                       break;
+                       
+               case MMA8453_DEVID:
+                       result = ((int)high_byte << (MMA8453_PRECISION-8)) 
+                                       | ((int)low_byte >> (16-MMA8453_PRECISION));
+                       if (result < MMA8453_BOUNDARY)
+                               result = result* MMA8453_GRAVITY_STEP;
+               else
+                               result = ~( ((~result & (0x7fff>>(16-MMA8453_PRECISION)) ) + 1) 
+                                               * MMA8453_GRAVITY_STEP) + 1;
+                       break;
+
+               default:
+                       mmaprintk(KERN_ERR
+                      "mma8452_convert_to_int: devid wasn't set correctly\n");
+                       return -EFAULT;
     }
 
-    return result;
+    return (int)result;
 }
 
 static void mma8452_report_value(struct i2c_client *client, struct mma8452_axis *axis)
@@ -358,26 +397,38 @@ static void mma8452_report_value(struct i2c_client *client, struct mma8452_axis
 static int mma8452_get_data(struct i2c_client *client)
 {
     struct mma8452_data* mma8452 = i2c_get_clientdata(client);
-       char buffer[6];
        int ret;
        int x,y,z;
     struct mma8452_axis axis;
     struct mma8452_platform_data *pdata = pdata = client->dev.platform_data;
 
+/* enabled only if FREAD MODE */
+/*
+       char buffer[3];
     do {
         memset(buffer, 0, 3);
         buffer[0] = MMA8452_REG_X_OUT_MSB;
-               //ret = mma8452_tx_data(client, &buffer[0], 1);
         ret = mma8452_rx_data(client, &buffer[0], 3);
         if (ret < 0)
             return ret;
     } while (0);
 
-       mmaprintkd("0x%02x 0x%02x 0x%02x \n",buffer[0],buffer[1],buffer[2]);
-       
-       x = mma8452_convert_to_int(buffer[0]);
-       y = mma8452_convert_to_int(buffer[1]);
-       z = mma8452_convert_to_int(buffer[2]);
+       x = mma8452_convert_to_int(buffer[0],0);
+       y = mma8452_convert_to_int(buffer[1],0);
+       z = mma8452_convert_to_int(buffer[2],0);
+*/
+       char buffer[6];
+    do {
+        memset(buffer, 0, 6);
+        buffer[0] = MMA8452_REG_X_OUT_MSB;
+        ret = mma8452_rx_data(client, &buffer[0], 6);
+        if (ret < 0)
+            return ret;
+    } while (0);
+
+       x = mma8452_convert_to_int(buffer[0],buffer[1]);
+       y = mma8452_convert_to_int(buffer[2],buffer[3]);
+       z = mma8452_convert_to_int(buffer[4],buffer[5]);
 
        if (pdata->swap_xyz) {
                axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
@@ -629,9 +680,9 @@ static void mma8452_resume(struct early_suspend *h)
 #else
 static int mma8452_suspend(struct i2c_client *client, pm_message_t mesg)
 {
-       int ret = 0;
-       //struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client);
+       int ret;
        mmaprintkd("Gsensor mma7760 enter 2 level  suspend mma8452->status %d\n",mma8452->status);
+       struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client);
 //     if(mma8452->status == MMA8452_OPEN)
 //     {
        //      mma8452->status = MMA8452_SUSPEND;
@@ -641,8 +692,8 @@ static int mma8452_suspend(struct i2c_client *client, pm_message_t mesg)
 }
 static int mma8452_resume(struct i2c_client *client)
 {
-       int ret = 0;
-       //struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client);
+       int ret;
+       struct mma8452_data *mma8452 = (struct mma8452_data *)i2c_get_clientdata(client);
        mmaprintkd("Gsensor mma7760 2 level resume!! mma8452->status %d\n",mma8452->status);
 //     if((mma8452->status == MMA8452_SUSPEND) && (mma8452->status != MMA8452_OPEN))
 //if (mma8452->status == MMA8452_OPEN)
@@ -712,7 +763,6 @@ static int  mma8452_probe(struct i2c_client *client, const struct i2c_device_id
        struct mma8452_data *mma8452;
        struct mma8452_platform_data *pdata = pdata = client->dev.platform_data;
        int err;
-       char devid;
 
        mmaprintkf("%s enter\n",__FUNCTION__);
 
@@ -743,7 +793,9 @@ static int  mma8452_probe(struct i2c_client *client, const struct i2c_device_id
        this_client = client;
 
        devid = mma8452_get_devid(this_client);
-       if ((MMA8452_DEVID != devid) && (MMA8451_DEVID != devid)) {
+       if ((MMA8452_DEVID != devid) 
+               && (MMA8451_DEVID != devid)
+               && (MMA8453_DEVID != devid)) {
                pr_info("mma8452: invalid devid\n");
                goto exit_invalid_devid;
        }
@@ -766,11 +818,11 @@ static int  mma8452_probe(struct i2c_client *client, const struct i2c_device_id
        set_bit(EV_ABS, mma8452->input_dev->evbit);
 
        /* x-axis acceleration */
-       input_set_abs_params(mma8452->input_dev, ABS_X, -2000, 2000, 0, 0); //2g full scale range
+       input_set_abs_params(mma8452->input_dev, ABS_X, -MMA845X_RANGE, MMA845X_RANGE, 0, 0); //2g full scale range
        /* y-axis acceleration */
-       input_set_abs_params(mma8452->input_dev, ABS_Y, -2000, 2000, 0, 0); //2g full scale range
+       input_set_abs_params(mma8452->input_dev, ABS_Y, -MMA845X_RANGE, MMA845X_RANGE, 0, 0); //2g full scale range
        /* z-axis acceleration */
-       input_set_abs_params(mma8452->input_dev, ABS_Z, -2000, 2000, 0, 0); //2g full scale range
+       input_set_abs_params(mma8452->input_dev, ABS_Z, -MMA845X_RANGE, MMA845X_RANGE, 0, 0); //2g full scale range
 
        // mma8452->input_dev->name = "compass";
        mma8452->input_dev->name = "gsensor";
@@ -784,7 +836,7 @@ static int  mma8452_probe(struct i2c_client *client, const struct i2c_device_id
                goto exit_input_register_device_failed;
        }
 
-       mma8452_device.parent = &client->dev;
+    mma8452_device.parent = &client->dev;
        err = misc_register(&mma8452_device);
        if (err < 0) {
                mmaprintk(KERN_ERR
@@ -800,10 +852,10 @@ static int  mma8452_probe(struct i2c_client *client, const struct i2c_device_id
        }
        
 #ifdef CONFIG_HAS_EARLYSUSPEND
-       mma8452_early_suspend.suspend = mma8452_suspend;
-       mma8452_early_suspend.resume = mma8452_resume;
-       mma8452_early_suspend.level = 0x2;
-       register_early_suspend(&mma8452_early_suspend);
+    mma8452_early_suspend.suspend = mma8452_suspend;
+    mma8452_early_suspend.resume = mma8452_resume;
+    mma8452_early_suspend.level = 0x2;
+    register_early_suspend(&mma8452_early_suspend);
 #endif
 
        printk(KERN_INFO "mma8452 probe ok\n");
@@ -814,9 +866,9 @@ static int  mma8452_probe(struct i2c_client *client, const struct i2c_device_id
        return 0;
 
 exit_gsensor_sysfs_init_failed:
-       misc_deregister(&mma8452_device);
+    misc_deregister(&mma8452_device);
 exit_misc_device_register_mma8452_device_failed:
-       input_unregister_device(mma8452->input_dev);
+    input_unregister_device(mma8452->input_dev);
 exit_input_register_device_failed:
        input_free_device(mma8452->input_dev);
 exit_input_allocate_device_failed:
index 8df0414485e9d2034d05807dae857129f233e44e..ea2f68175717b2f1e10d51feeafb92c8136f3f8b 100644 (file)
 
 #define MMA7660_IIC_ADDR           0x98  
 #define MMA7660_REG_LEN         11
-#define MMA7660_GRAVITY_STEP    47
+#define MMA7660_RANGE                                          2000000
 #define MMA7660_PRECISION       6
 #define MMA7660_BOUNDARY        (0x1 << (MMA7660_PRECISION - 1))
+#define MMA7660_GRAVITY_STEP    MMA7660_RANGE/MMA7660_BOUNDARY
 #define MMA7660_TOTAL_TIME      10
 
 
index 9de60414684ab784ab53d3ff0623a9ea5ee3ecea..6bc81c2a5b0ee11488b99e64524a910c42042fab 100755 (executable)
 #define MMA8452_ASLP_RATE_1P56        3
 #define MMA8452_ASLP_RATE_SHIFT                  6
 
-#define ACTIVE_MASK                            1
-#define FREAD_MASK                             2
+/*Auto-adapt mma845x series*/
+/*Modified by Yick @ROCKCHIP 
+  xieyi@rockchips.com*/
+/*
+  Range: unit(ug 1g=1 000 000 ug)
+                option(2g,4g,8g)
+                G would be defined on android HAL
+  Precision: bit wide of valid data
+  Boundary: Max positive count
+  Gravity_step: gravity value indicated by per count
+ */
+#define FREAD_MASK                             0 /* enabled(1<<1) only if reading MSB 8bits*/
+#define MMA845X_RANGE                  2000000
+/* mma8451 */
+#define MMA8451_PRECISION       14
+#define MMA8451_BOUNDARY        (0x1 << (MMA8451_PRECISION - 1))
+#define MMA8451_GRAVITY_STEP    MMA845X_RANGE / MMA8451_BOUNDARY
+
+/* mma8452 */
+#define MMA8452_PRECISION       12
+#define MMA8452_BOUNDARY        (0x1 << (MMA8452_PRECISION - 1))
+#define MMA8452_GRAVITY_STEP    MMA845X_RANGE / MMA8452_BOUNDARY
 
+/* mma8453 */
+#define MMA8453_PRECISION       10
+#define MMA8453_BOUNDARY        (0x1 << (MMA8453_PRECISION - 1))
+#define MMA8453_GRAVITY_STEP    MMA845X_RANGE / MMA8453_BOUNDARY
+
+/*End of precision adaption*/
+
+#define MMA8452_TOTAL_TIME      10
+
+#define ACTIVE_MASK                            1
 
 /*status*/
 #define MMA8452_SUSPEND           2
 #define MMA8452_OPEN           1
 #define MMA8452_CLOSE          0
 
-
-
-//#define MMA8452_IIC_ADDR         0x98  
 #define MMA8452_REG_LEN         11
-#define MMA8452_GRAVITY_STEP    156 //2g full scale range
-#define MMA8452_PRECISION       8 //8bit data
-#define MMA8452_BOUNDARY        (0x1 << (MMA8452_PRECISION - 1))
-#define MMA8452_TOTAL_TIME      10
 
 
 /*