Merge "input: misc: turn off mma8x5x device power while disabled"
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index f49ff14..a325d54 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -304,6 +304,28 @@
return 0;
}
+static int mma8x5x_device_start(struct i2c_client *client)
+{
+ struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+
+ if (i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, 0))
+ goto err_out;
+ if (i2c_smbus_write_byte_data(client, MMA8X5X_XYZ_DATA_CFG,
+ pdata->mode))
+ goto err_out;
+
+ /* The BT(boot time) for mma8x5x is 1.55ms according to
+ *Freescale mma8450Q document. Document Number:MMA8450Q
+ *Rev: 9.1, 04/2012
+ */
+ usleep_range(1600, 2000);
+ return 0;
+
+err_out:
+ dev_err(&client->dev, "%s:start device failed", __func__);
+ return -EIO;
+}
+
static int mma8x5x_read_data(struct i2c_client *client,
struct mma8x5x_data_axis *data)
{
@@ -381,32 +403,73 @@
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 && pdata->active == MMA_STANDBY) {
- val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
- ret = i2c_smbus_write_byte_data(client,
- MMA8X5X_CTRL_REG1, val|0x01);
- if (!ret) {
+ 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__);
+ dev_dbg(dev, "%s:mma enable setting active.\n",
+ __func__);
}
- } else if (enable == 0 && pdata->active == MMA_ACTIVED) {
- val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
- ret = i2c_smbus_write_byte_data(client,
- MMA8X5X_CTRL_REG1, val & 0xFE);
- if (!ret) {
+ } 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__);
+ 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);
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)
@@ -617,6 +680,8 @@
struct mma8x5x_data *pdata = i2c_get_clientdata(client);
if (pdata->active == MMA_ACTIVED)
mma8x5x_device_stop(client);
+ if (pdata->active & MMA_SHUTTEDDOWN)
+ return 0;
if (!mma8x5x_config_regulator(client, 0))
/* The highest bit sotres the power state */
pdata->active |= MMA_SHUTTEDDOWN;
@@ -628,22 +693,16 @@
int val = 0;
struct i2c_client *client = to_i2c_client(dev);
struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+
+ /* No need to power on while device is shutdowned from standby state */
+ if (pdata->active == (MMA_SHUTTEDDOWN | MMA_STANDBY))
+ return 0;
if (pdata->active & MMA_SHUTTEDDOWN) {
if (mma8x5x_config_regulator(client, 1))
goto out;
- if (i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, 0))
+ if (mma8x5x_device_start(client))
goto out;
-
- if (i2c_smbus_write_byte_data(client, MMA8X5X_XYZ_DATA_CFG,
- pdata->mode))
- goto out;
-
- /* The BT(boot time) for mma8x5x is 1.55ms according to
- Freescale mma8450Q document. Document Number:MMA8450Q
- Rev: 9.1, 04/2012
- */
- usleep_range(1600, 2000);
pdata->active &= ~MMA_SHUTTEDDOWN;
}
if (pdata->active == MMA_ACTIVED) {