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) {