Merge "input: sensors: add enable handler for mma8x5x"

This commit is contained in:
Linux Build Service Account 2014-01-05 02:19:19 -08:00 committed by Gerrit - the friendly Code Review server
commit 8f2e06ac62
1 changed files with 105 additions and 69 deletions

View File

@ -2,7 +2,7 @@
* mma8x5x.c - Linux kernel modules for 3-Axis Orientation/Motion
* Detection Sensor MMA8451/MMA8452/MMA8453
*
* Copyright (c) 2013, The Linux Foundation. All Rights Reserved.
* Copyright (c) 2013-2014, The Linux Foundation. All Rights Reserved.
* Linux Foundation chooses to take subject only to the GPLv2 license
* terms, and distributes only under these terms.
* Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
@ -68,6 +68,10 @@ static struct sensors_classdev sensors_cdev = {
.min_delay = 2000,
.fifo_reserved_event_count = 0,
.fifo_max_event_count = 0,
.enabled = 0,
.delay_msec = POLL_INTERVAL,
.sensors_enable = NULL,
.sensors_poll_delay = NULL,
};
struct sensor_regulator {
@ -162,6 +166,7 @@ struct mma8x5x_data {
struct i2c_client *client;
struct input_polled_dev *poll_dev;
struct mutex data_lock;
struct sensors_classdev cdev;
int active;
int position;
u8 chip_id;
@ -391,6 +396,79 @@ static void mma8x5x_dev_poll(struct input_polled_dev *dev)
mma8x5x_report_data(pdata);
}
static int mma8x5x_enable_set(struct sensors_classdev *sensors_cdev,
unsigned int enable)
{
struct mma8x5x_data *pdata = container_of(sensors_cdev,
struct mma8x5x_data, cdev);
struct i2c_client *client = pdata->client;
int ret;
u8 val = 0;
mutex_lock(&pdata->data_lock);
if (enable) {
if (pdata->active & MMA_SHUTTEDDOWN) {
ret = mma8x5x_config_regulator(client, 1);
if (ret)
goto err_failed;
ret = mma8x5x_device_start(client);
if (ret)
goto err_failed;
pdata->active &= ~MMA_SHUTTEDDOWN;
}
if (pdata->active == MMA_STANDBY) {
val = i2c_smbus_read_byte_data(client,
MMA8X5X_CTRL_REG1);
if (val < 0) {
dev_err(&client->dev, "read device state failed!");
ret = val;
goto err_failed;
}
ret = i2c_smbus_write_byte_data(client,
MMA8X5X_CTRL_REG1, val | 0x01);
if (ret) {
dev_err(&client->dev, "change device state failed!");
goto err_failed;
}
pdata->active = MMA_ACTIVED;
dev_dbg(&client->dev, "%s:mma enable setting active.\n",
__func__);
}
} else if (enable == 0) {
if (pdata->active == MMA_ACTIVED) {
val = i2c_smbus_read_byte_data(client,
MMA8X5X_CTRL_REG1);
if (val < 0) {
dev_err(&client->dev, "read device state failed!");
ret = val;
goto err_failed;
}
ret = i2c_smbus_write_byte_data(client,
MMA8X5X_CTRL_REG1, val & 0xFE);
if (ret) {
dev_err(&client->dev, "change device state failed!");
goto err_failed;
}
pdata->active = MMA_STANDBY;
dev_dbg(&client->dev, "%s:mma enable setting inactive.\n",
__func__);
}
if (!mma8x5x_config_regulator(client, 0))
pdata->active |= MMA_SHUTTEDDOWN;
}
mutex_unlock(&pdata->data_lock);
return 0;
err_failed:
mutex_unlock(&pdata->data_lock);
return ret;
}
static ssize_t mma8x5x_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -416,77 +494,17 @@ static ssize_t mma8x5x_enable_store(struct device *dev,
{
struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
struct i2c_client *client = pdata->client;
int ret;
unsigned long enable;
u8 val = 0;
ret = kstrtoul(buf, 10, &enable);
if (ret)
return ret;
mutex_lock(&pdata->data_lock);
enable = (enable > 0) ? 1 : 0;
if (enable) {
if (pdata->active & MMA_SHUTTEDDOWN) {
ret = mma8x5x_config_regulator(client, 1);
if (ret)
goto err_failed;
ret = mma8x5x_device_start(client);
if (ret)
goto err_failed;
pdata->active &= ~MMA_SHUTTEDDOWN;
}
if (pdata->active == MMA_STANDBY) {
val = i2c_smbus_read_byte_data(client,
MMA8X5X_CTRL_REG1);
if (val < 0) {
dev_err(dev, "read device state failed!");
ret = val;
goto err_failed;
}
ret = i2c_smbus_write_byte_data(client,
MMA8X5X_CTRL_REG1, val | 0x01);
if (ret) {
dev_err(dev, "change device state failed!");
goto err_failed;
}
pdata->active = MMA_ACTIVED;
dev_dbg(dev, "%s:mma enable setting active.\n",
__func__);
}
} else if (enable == 0) {
if (pdata->active == MMA_ACTIVED) {
val = i2c_smbus_read_byte_data(client,
MMA8X5X_CTRL_REG1);
if (val < 0) {
dev_err(dev, "read device state failed!");
ret = val;
goto err_failed;
}
ret = i2c_smbus_write_byte_data(client,
MMA8X5X_CTRL_REG1, val & 0xFE);
if (ret) {
dev_err(dev, "change device state failed!");
goto err_failed;
}
pdata->active = MMA_STANDBY;
dev_dbg(dev, "%s:mma enable setting inactive.\n",
__func__);
}
if (!mma8x5x_config_regulator(client, 0))
pdata->active |= MMA_SHUTTEDDOWN;
}
mutex_unlock(&pdata->data_lock);
ret = mma8x5x_enable_set(&pdata->cdev, enable);
if (ret < 0)
return ret;
return count;
err_failed:
mutex_unlock(&pdata->data_lock);
return ret;
}
static ssize_t mma8x5x_position_show(struct device *dev,
struct device_attribute *attr, char *buf)
@ -517,6 +535,20 @@ static ssize_t mma8x5x_position_store(struct device *dev,
return count;
}
static int mma8x5x_poll_delay_set(struct sensors_classdev *sensors_cdev,
unsigned int delay_ms)
{
struct mma8x5x_data *pdata = container_of(sensors_cdev,
struct mma8x5x_data, cdev);
mutex_lock(&pdata->data_lock);
pdata->poll_delay = delay_ms;
pdata->poll_dev->poll_interval = pdata->poll_delay;
mutex_unlock(&pdata->data_lock);
return 0;
}
static ssize_t mma8x5x_poll_delay_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@ -540,10 +572,9 @@ static ssize_t mma8x5x_poll_delay_store(struct device *dev,
interval = POLL_INTERVAL_MIN;
if (interval > POLL_INTERVAL_MAX)
interval = POLL_INTERVAL_MAX;
mutex_lock(&pdata->data_lock);
pdata->poll_delay = interval;
poll_dev->poll_interval = pdata->poll_delay;
mutex_unlock(&pdata->data_lock);
mma8x5x_poll_delay_set(&pdata->cdev, interval);
return count;
}
@ -694,7 +725,12 @@ static int mma8x5x_probe(struct i2c_client *client,
result = -EINVAL;
goto err_create_sysfs;
}
result = sensors_classdev_register(&client->dev, &sensors_cdev);
pdata->cdev = sensors_cdev;
pdata->cdev.min_delay = POLL_INTERVAL_MIN * 1000;
pdata->cdev.delay_msec = poll_dev->poll_interval;
pdata->cdev.sensors_enable = mma8x5x_enable_set;
pdata->cdev.sensors_poll_delay = mma8x5x_poll_delay_set;
result = sensors_classdev_register(&client->dev, &pdata->cdev);
if (result) {
dev_err(&client->dev, "create class device file failed!\n");
result = -EINVAL;