summaryrefslogtreecommitdiff
path: root/drivers/hwmon/mxc_mma8451.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/mxc_mma8451.c')
-rw-r--r--drivers/hwmon/mxc_mma8451.c162
1 files changed, 93 insertions, 69 deletions
diff --git a/drivers/hwmon/mxc_mma8451.c b/drivers/hwmon/mxc_mma8451.c
index 110ff3485e3f..d144cbcbacdb 100644
--- a/drivers/hwmon/mxc_mma8451.c
+++ b/drivers/hwmon/mxc_mma8451.c
@@ -2,7 +2,7 @@
* mma8451.c - Linux kernel modules for 3-Axis Orientation/Motion
* Detection Sensor
*
- * Copyright (C) 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,20 +33,30 @@
#include <linux/hwmon.h>
#include <linux/input-polldev.h>
+#define MMA8451_DRV_NAME "mma8451"
#define MMA8451_I2C_ADDR 0x1C
#define MMA8451_ID 0x1A
#define MMA8452_ID 0x2A
#define MMA8453_ID 0x3A
-#define POLL_INTERVAL_MIN 1
-#define POLL_INTERVAL_MAX 500
-#define POLL_INTERVAL 100 /* msecs */
-#define INPUT_FUZZ 32
-#define INPUT_FLAT 32
+#define POLL_INTERVAL_MIN 20
+#define POLL_INTERVAL_MAX 1000
+#define POLL_INTERVAL 500
+#define INPUT_FUZZ 128
+#define INPUT_FLAT 128
#define MODE_CHANGE_DELAY_MS 100
#define MMA8451_STATUS_ZYXDR 0x08
-#define MMA8451_BUF_SIZE 7
+#define MMA8451_BUF_SIZE 6
+
+#define DR_1_25MS 0
+#define DR_2_5MS 1
+#define DR_5_0MS 2
+#define DR_10_0MS 3
+#define DR_20_0MS 4
+#define DR_80_0MS 5
+#define DR_160_0MS 6
+#define DR_640_0MS 7
/* register enum for mma8451 registers */
enum {
@@ -106,8 +116,8 @@ enum {
};
/* The sensitivity is represented in counts/g. In 2g mode the
-sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512
-counts/g and in 8g mode the sensitivity is 256 counts/g.
+ sensitivity is 1024 counts/g. In 4g mode the sensitivity is 512
+ counts/g and in 8g mode the sensitivity is 256 counts/g.
*/
enum {
MODE_2G = 0,
@@ -135,15 +145,15 @@ static struct i2c_client *mma8451_i2c_client;
static int senstive_mode = MODE_2G;
static int ACCHAL[8][3][3] = {
- { {0, -1, 0}, {1, 0, 0}, {0, 0, 1} },
- { {-1, 0, 0}, {0, -1, 0}, {0, 0, 1} },
- { {0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
- { {1, 0, 0}, {0, 1, 0}, {0, 0, 1} },
-
- { {0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
- { {-1, 0, 0}, {0, 1, 0}, {0, 0, -1} },
- { {0, 1, 0}, {1, 0, 0}, {0, 0, -1} },
- { {1, 0, 0}, {0, -1, 0}, {0, 0, -1} },
+ {{ 0, -1, 0}, { 1, 0, 0}, {0, 0, 1} },
+ {{-1, 0, 0}, { 0, -1, 0}, {0, 0, 1} },
+ {{ 0, 1, 0}, {-1, 0, 0}, {0, 0, 1} },
+ {{ 1, 0, 0}, { 0, 1, 0}, {0, 0, 1} },
+
+ {{ 0, -1, 0}, {-1, 0, 0}, {0, 0, -1} },
+ {{-1, 0, 0}, { 0, 1, 0}, {0, 0, -1} },
+ {{ 0, 1, 0}, { 1, 0, 0}, {0, 0, -1} },
+ {{ 1, 0, 0}, { 0, -1, 0}, {0, 0, -1} },
};
static DEFINE_MUTEX(mma8451_lock);
@@ -154,10 +164,12 @@ static int mma8451_adjust_position(short *x, short *y, short *z)
int position = mma_status.position;
if (position < 0 || position > 7)
position = 0;
+
rawdata[0] = *x;
rawdata[1] = *y;
rawdata[2] = *z;
- for (i = 0; i < 3; i++) {
+
+ for (i = 0; i < 3 ; i++) {
data[i] = 0;
for (j = 0; j < 3; j++)
data[i] += rawdata[j] * ACCHAL[position][i][j];
@@ -172,17 +184,23 @@ static int mma8451_change_mode(struct i2c_client *client, int mode)
{
int result;
- mma_status.ctl_reg1 = 0;
- result = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1, 0);
+ /* Put sensor into Standby Mode by clearing the Active bit */
+ mma_status.ctl_reg1 = 0x00;
+ result = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
+ mma_status.ctl_reg1);
if (result < 0)
goto out;
+ /* Write the 2g dynamic range value */
mma_status.mode = mode;
result = i2c_smbus_write_byte_data(client, MMA8451_XYZ_DATA_CFG,
- mma_status.mode);
+ mma_status.mode);
if (result < 0)
goto out;
+
+ /* Set the Active bit and Data rate in CTRL Reg 1 */
mma_status.active = MMA_STANDBY;
+
mdelay(MODE_CHANGE_DELAY_MS);
return 0;
@@ -196,13 +214,15 @@ static int mma8451_read_data(short *x, short *y, short *z)
u8 tmp_data[MMA8451_BUF_SIZE];
int ret;
+ /* Read 14-bit XYZ results using 6 byte */
ret = i2c_smbus_read_i2c_block_data(mma8451_i2c_client,
- MMA8451_OUT_X_MSB, 7, tmp_data);
+ MMA8451_OUT_X_MSB, MMA8451_BUF_SIZE, tmp_data);
if (ret < MMA8451_BUF_SIZE) {
dev_err(&mma8451_i2c_client->dev, "i2c block read failed\n");
return -EIO;
}
+ /* Concatenate the MSB and LSB */
*x = ((tmp_data[0] << 8) & 0xff00) | tmp_data[1];
*y = ((tmp_data[2] << 8) & 0xff00) | tmp_data[3];
*z = ((tmp_data[4] << 8) & 0xff00) | tmp_data[5];
@@ -213,23 +233,24 @@ static void report_abs(void)
{
short x, y, z;
int result;
- int retry = 3;
mutex_lock(&mma8451_lock);
if (mma_status.active == MMA_STANDBY)
goto out;
- /* wait for the data ready */
- do {
- result = i2c_smbus_read_byte_data(mma8451_i2c_client,
- MMA8451_STATUS);
- retry--;
- msleep(1);
- } while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0);
- if (retry == 0)
+ /* Read Status register */
+ result = i2c_smbus_read_byte_data(mma8451_i2c_client, MMA8451_STATUS);
+
+ /* Check ZYXDR status bit for data available */
+ if (!(result & MMA8451_STATUS_ZYXDR)) {
+ /* Data not ready */
goto out;
+ }
+
+ /* Read XYZ data */
if (mma8451_read_data(&x, &y, &z) != 0)
goto out;
mma8451_adjust_position(&x, &y, &z);
+ /* Report XYZ data */
input_report_abs(mma8451_idev->input, ABS_X, x);
input_report_abs(mma8451_idev->input, ABS_Y, y);
input_report_abs(mma8451_idev->input, ABS_Z, z);
@@ -244,7 +265,7 @@ static void mma8451_dev_poll(struct input_polled_dev *dev)
}
static ssize_t mma8451_enable_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
struct i2c_client *client;
u8 val;
@@ -262,8 +283,8 @@ static ssize_t mma8451_enable_show(struct device *dev,
}
static ssize_t mma8451_enable_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct i2c_client *client;
int ret;
@@ -273,42 +294,45 @@ static ssize_t mma8451_enable_store(struct device *dev,
mutex_lock(&mma8451_lock);
client = mma8451_i2c_client;
enable = (enable > 0) ? 1 : 0;
- if (enable && mma_status.active == MMA_STANDBY) {
+
+ if (enable && mma_status.active == MMA_STANDBY) {
val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
- ret =
- i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- val | 0x01);
+ /* Set the Active bit and Data rate in CTRL Reg 1 */
+ val |= (DR_20_0MS<<3);
+ val |= 1;
+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
+ val);
if (!ret) {
mma_status.active = MMA_ACTIVED;
+ printk(KERN_DEBUG "mma enable setting active\n");
}
- } else if (enable == 0 && mma_status.active == MMA_ACTIVED) {
+ } else if (enable == 0 && mma_status.active == MMA_ACTIVED) {
val = i2c_smbus_read_byte_data(client, MMA8451_CTRL_REG1);
- ret =
- i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- val & 0xFE);
+ ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
+ val & 0xFE);
if (!ret) {
mma_status.active = MMA_STANDBY;
+ printk(KERN_DEBUG "mma enable setting inactive\n");
}
}
mutex_unlock(&mma8451_lock);
return count;
}
-
static ssize_t mma8451_position_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr, char *buf)
{
int position = 0;
mutex_lock(&mma8451_lock);
- position = mma_status.position;
+ position = mma_status.position ;
mutex_unlock(&mma8451_lock);
return sprintf(buf, "%d\n", position);
}
static ssize_t mma8451_position_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- int position;
+ int position;
position = simple_strtoul(buf, NULL, 10);
mutex_lock(&mma8451_lock);
mma_status.position = position;
@@ -317,9 +341,9 @@ static ssize_t mma8451_position_store(struct device *dev,
}
static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
- mma8451_enable_show, mma8451_enable_store);
+ mma8451_enable_show, mma8451_enable_store);
static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
- mma8451_position_show, mma8451_position_store);
+ mma8451_position_show, mma8451_position_store);
static struct attribute *mma8451_attributes[] = {
&dev_attr_enable.attr,
@@ -332,7 +356,7 @@ static const struct attribute_group mma8451_attr_group = {
};
static int __devinit mma8451_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *id)
{
int result, client_id;
struct input_dev *idev;
@@ -341,18 +365,18 @@ static int __devinit mma8451_probe(struct i2c_client *client,
mma8451_i2c_client = client;
adapter = to_i2c_adapter(client->dev.parent);
result = i2c_check_functionality(adapter,
- I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA);
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA);
if (!result)
goto err_out;
client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I);
- if (client_id != MMA8451_ID && client_id != MMA8452_ID
- && client_id != MMA8453_ID) {
+ if (client_id != MMA8451_ID && client_id != MMA8452_ID &&
+ client_id != MMA8453_ID) {
dev_err(&client->dev,
- "read chip ID 0x%x is not equal to 0x%x or 0x%x!\n",
- result, MMA8451_ID, MMA8452_ID);
+ "read chip ID 0x%x is not equal to 0x%x \
+ or 0x%x!\n", result, MMA8451_ID, MMA8452_ID);
result = -EINVAL;
goto err_out;
}
@@ -361,14 +385,15 @@ static int __devinit mma8451_probe(struct i2c_client *client,
result = mma8451_change_mode(client, senstive_mode);
if (result) {
dev_err(&client->dev,
- "error when init mma8451 chip:(%d)\n", result);
+ "error when init mma8451 chip:(%d)\n", result);
goto err_out;
}
hwmon_dev = hwmon_device_register(&client->dev);
if (!hwmon_dev) {
result = -ENOMEM;
- dev_err(&client->dev, "error when register hwmon device\n");
+ dev_err(&client->dev,
+ "error when register hwmon device\n");
goto err_out;
}
@@ -417,9 +442,9 @@ static int mma8451_stop_chip(struct i2c_client *client)
int ret = 0;
if (mma_status.active == MMA_ACTIVED) {
mma_status.ctl_reg1 = i2c_smbus_read_byte_data(client,
- MMA8451_CTRL_REG1);
+ MMA8451_CTRL_REG1);
ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- mma_status.ctl_reg1 & 0xFE);
+ mma_status.ctl_reg1 & 0xFE);
}
return ret;
}
@@ -447,25 +472,24 @@ static int mma8451_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
if (mma_status.active == MMA_ACTIVED)
ret = i2c_smbus_write_byte_data(client, MMA8451_CTRL_REG1,
- mma_status.ctl_reg1);
+ mma_status.ctl_reg1);
return ret;
}
#endif
static const struct i2c_device_id mma8451_id[] = {
- {"mma8451", 0},
+ {MMA8451_DRV_NAME, 0},
};
-
MODULE_DEVICE_TABLE(i2c, mma8451_id);
static SIMPLE_DEV_PM_OPS(mma8451_pm_ops, mma8451_suspend, mma8451_resume);
static struct i2c_driver mma8451_driver = {
.driver = {
- .name = "mma8451",
- .owner = THIS_MODULE,
- .pm = &mma8451_pm_ops,
- },
+ .name = MMA8451_DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &mma8451_pm_ops,
+ },
.probe = mma8451_probe,
.remove = __devexit_p(mma8451_remove),
.id_table = mma8451_id,