input: atmel_mxt: Add support for devices with no lpm support

Disable the regulators used by the controller when the device
does not support low power mode(lpm).

Change-Id: Ic974c7922c8888fefdfbbe1f5503f34c5964e993
Signed-off-by: Chun Zhang <chunz@codeaurora.org>
Signed-off-by: Mohan Pallaka <mpallaka@codeaurora.org>
diff --git a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
index 6fe88a9..4c6ae93 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/atmel-mxt-ts.txt
@@ -35,6 +35,8 @@
 					needed during wakeup.
  - atmel,no-force-update	: flag that signifies whether force configuration
 					update is applicable or not
+ - atmel,no-lpm-support		: flag that signifies whether low power mode is
+					supported or not on this platform
 
 Example:
 	i2c@f9966000 {
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 479b788..5415f4e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -393,6 +393,9 @@
 	bool update_cfg;
 	const char *fw_name;
 	bool no_force_update;
+	bool lpm_support;
+	bool regs_enabled;
+
 #if defined(CONFIG_SECURE_TOUCH)
 	atomic_t st_enabled;
 	atomic_t st_pending_irqs;
@@ -2158,6 +2161,11 @@
 	if (on == false)
 		goto power_off;
 
+	if (data->regs_enabled) {
+		dev_dbg(&data->client->dev, "regs are already enabled\n");
+		return 0;
+	}
+
 	rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
 	if (rc < 0) {
 		dev_err(&data->client->dev,
@@ -2206,6 +2214,8 @@
 		}
 	}
 
+	data->regs_enabled = true;
+
 	msleep(130);
 
 	return 0;
@@ -2226,6 +2236,12 @@
 	return rc;
 
 power_off:
+
+	if (!data->regs_enabled) {
+		dev_dbg(&data->client->dev, "regs are already disabled\n");
+		return 0;
+	}
+
 	reg_set_optimum_mode_check(data->vcc_ana, 0);
 	regulator_disable(data->vcc_ana);
 	if (data->pdata->digital_pwr_regulator) {
@@ -2236,6 +2252,9 @@
 		reg_set_optimum_mode_check(data->vcc_i2c, 0);
 		regulator_disable(data->vcc_i2c);
 	}
+
+	data->regs_enabled = false;
+
 	msleep(50);
 	return 0;
 }
@@ -2435,8 +2454,9 @@
 	struct input_dev *input_dev = data->input_dev;
 	int error;
 
-	mutex_lock(&input_dev->mutex);
+	disable_irq(data->irq);
 
+	mutex_lock(&input_dev->mutex);
 	if (input_dev->users) {
 		error = mxt_stop(data);
 		if (error < 0) {
@@ -2444,16 +2464,24 @@
 			mutex_unlock(&input_dev->mutex);
 			return error;
 		}
-
 	}
 
 	mutex_unlock(&input_dev->mutex);
+	mxt_release_all(data);
 
 	/* put regulators in low power mode */
-	error = mxt_regulator_lpm(data, true);
-	if (error < 0) {
-		dev_err(dev, "failed to enter low power mode\n");
-		return error;
+	if (data->lpm_support) {
+		error = mxt_regulator_lpm(data, true);
+		if (error < 0) {
+			dev_err(dev, "failed to enter low power mode\n");
+			return error;
+		}
+	} else {
+		error = mxt_power_on(data, false);
+		if (error < 0) {
+			dev_err(dev, "failed to disable regulators\n");
+			return error;
+		}
 	}
 
 	return 0;
@@ -2466,13 +2494,25 @@
 	struct input_dev *input_dev = data->input_dev;
 	int error;
 
-	/* put regulators in high power mode */
-	error = mxt_regulator_lpm(data, false);
-	if (error < 0) {
-		dev_err(dev, "failed to enter high power mode\n");
-		return error;
+	/* put regulators back in active power mode */
+	if (data->lpm_support) {
+		error = mxt_regulator_lpm(data, false);
+		if (error < 0) {
+			dev_err(dev, "failed to enter high power mode\n");
+			return error;
+		}
+	} else {
+		error = mxt_power_on(data, true);
+		if (error < 0) {
+			dev_err(dev, "failed to enable regulators\n");
+			return error;
+		}
+		mxt_power_on_delay(data);
 	}
 
+	mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
+	mxt_reset_delay(data);
+
 	mutex_lock(&input_dev->mutex);
 
 	if (input_dev->users) {
@@ -2495,6 +2535,8 @@
 
 	mutex_unlock(&input_dev->mutex);
 
+	enable_irq(data->irq);
+
 	return 0;
 }
 
@@ -2672,6 +2714,9 @@
 	pdata->no_force_update = of_property_read_bool(np,
 						"atmel,no-force-update");
 
+	pdata->no_lpm_support = of_property_read_bool(np,
+					"atmel,no-lpm-support");
+
 	/* reset, irq gpio info */
 	pdata->reset_gpio = of_get_named_gpio_flags(np, "atmel,reset-gpio",
 				0, &pdata->reset_gpio_flags);
@@ -2877,6 +2922,7 @@
 	data->input_dev = input_dev;
 	data->pdata = pdata;
 	data->no_force_update = pdata->no_force_update;
+	data->lpm_support = !pdata->no_lpm_support;
 
 	__set_bit(EV_ABS, input_dev->evbit);
 	__set_bit(EV_KEY, input_dev->evbit);
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
index b903dfb..e9fbf90 100644
--- a/include/linux/i2c/atmel_mxt_ts.h
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -77,6 +77,7 @@
 	int *key_codes;
 	bool need_calibration;
 	bool no_force_update;
+	bool no_lpm_support;
 	u8 bl_addr;
 
 	u8(*read_chg) (void);