input: cyttsp-i2c: Move regulators to LPM/HPM in suspend/resume

Change-Id: I341f33d2627dc9f3f7c511a69db8a84c4b886841
Signed-off-by: Anirudh Ghayal <aghayal@codeaurora.org>
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 03307f0..9fb9fb6 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -389,6 +389,14 @@
 	return rc;
 }
 
+/* TODO: Put the regulator to LPM / HPM in suspend/resume*/
+static int cyttsp_platform_suspend(struct i2c_client *client)
+{
+	msleep(20);
+
+	return CY_OK;
+}
+
 static int cyttsp_platform_resume(struct i2c_client *client)
 {
 	/* add any special code to strobe a wakeup pin or chip reset */
@@ -432,6 +440,7 @@
 	 */
 	.lp_intrvl = CY_LP_INTRVL_DFLT,
 	.resume = cyttsp_platform_resume,
+	.suspend = cyttsp_platform_suspend,
 	.init = cyttsp_platform_init,
 	.sleep_gpio = -1,
 	.resout_gpio = -1,
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
index b06bb53..103a224 100644
--- a/arch/arm/mach-msm/board-msm8960.c
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -3341,14 +3341,16 @@
 		.name = "vdd",
 		.min_uV = CY_TMA300_VTG_MIN_UV,
 		.max_uV = CY_TMA300_VTG_MAX_UV,
-		.load_uA = CY_TMA300_CURR_24HZ_UA,
+		.hpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+		.lpm_load_uA = CY_TMA300_SLEEP_CURR_UA,
 	},
 	/* TODO: Remove after runtime PM is enabled in I2C driver */
 	{
 		.name = "vcc_i2c",
 		.min_uV = CY_I2C_VTG_MIN_UV,
 		.max_uV = CY_I2C_VTG_MAX_UV,
-		.load_uA = CY_I2C_CURR_UA,
+		.hpm_load_uA = CY_I2C_CURR_UA,
+		.lpm_load_uA = CY_I2C_SLEEP_CURR_UA,
 	},
 };
 
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 916645c..d891fdf 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -3209,6 +3209,14 @@
 	return rc;
 }
 
+/* TODO: Put the regulator to LPM / HPM in suspend/resume*/
+static int cyttsp_platform_suspend(struct i2c_client *client)
+{
+	msleep(20);
+
+	return CY_OK;
+}
+
 static int cyttsp_platform_resume(struct i2c_client *client)
 {
 	/* add any special code to strobe a wakeup pin or chip reset */
@@ -3248,6 +3256,7 @@
 	.resout_gpio = -1,
 	.irq_gpio = CYTTSP_TS_GPIO_IRQ,
 	.resume = cyttsp_platform_resume,
+	.suspend = cyttsp_platform_suspend,
 	.init = cyttsp_platform_init,
 };
 
@@ -3290,6 +3299,7 @@
 	.resout_gpio = -1,
 	.irq_gpio = CYTTSP_TS_GPIO_IRQ,
 	.resume = cyttsp_platform_resume,
+	.suspend = cyttsp_platform_suspend,
 	.init = cyttsp_platform_init,
 	.disable_ghost_det = true,
 };
diff --git a/drivers/input/touchscreen/cyttsp-i2c.c b/drivers/input/touchscreen/cyttsp-i2c.c
index a3446a3..aefce3e 100644
--- a/drivers/input/touchscreen/cyttsp-i2c.c
+++ b/drivers/input/touchscreen/cyttsp-i2c.c
@@ -2419,7 +2419,7 @@
 		}
 
 		rc = regulator_set_optimum_mode(ts->vdd[i],
-						reg_info[i].load_uA);
+						reg_info[i].hpm_load_uA);
 		if (rc < 0) {
 			pr_err("%s: regulator_set_optimum_mode failed rc=%d\n",
 								__func__, rc);
@@ -2838,6 +2838,57 @@
 }
 
 #ifdef CONFIG_PM
+static int cyttsp_regulator_lpm(struct cyttsp *ts, bool on)
+{
+	int rc = 0, i;
+	const struct cyttsp_regulator *reg_info =
+			ts->platform_data->regulator_info;
+	u8 num_reg = ts->platform_data->num_regulators;
+
+	if (on == false)
+		goto regulator_hpm;
+
+	for (i = 0; i < num_reg; i++) {
+		rc = regulator_set_optimum_mode(ts->vdd[i],
+					reg_info[i].lpm_load_uA);
+		if (rc < 0) {
+			pr_err("%s: regulator_set_optimum failed rc = %d\n",
+							__func__, rc);
+			goto fail_regulator_lpm;
+		}
+
+	}
+
+	return 0;
+
+regulator_hpm:
+	for (i = 0; i < num_reg; i++) {
+		rc = regulator_set_optimum_mode(ts->vdd[i],
+					reg_info[i].hpm_load_uA);
+		if (rc < 0) {
+			pr_err("%s: regulator_set_optimum failed"
+				"rc = %d\n", __func__, rc);
+			goto fail_regulator_hpm;
+		}
+	}
+
+	return 0;
+
+fail_regulator_lpm:
+	while (i--)
+		regulator_set_optimum_mode(ts->vdd[i],
+					reg_info[i].hpm_load_uA);
+
+	return rc;
+
+fail_regulator_hpm:
+	while (i--)
+		regulator_set_optimum_mode(ts->vdd[i],
+					reg_info[i].lpm_load_uA);
+
+	return rc;
+}
+
 /* Function to manage power-on resume */
 static int cyttsp_resume(struct device *dev)
 {
@@ -2865,6 +2916,8 @@
 		(ts->platform_data->power_state != CY_ACTIVE_STATE)) {
 		if (ts->platform_data->resume)
 			retval = ts->platform_data->resume(ts->client);
+		else
+			retval = cyttsp_regulator_lpm(ts, false);
 		/* take TTSP device out of bootloader mode;
 		 * switch back to TrueTouch operational mode */
 		if (!(retval < CY_OK)) {
@@ -2948,14 +3001,23 @@
 	if (!(retval < CY_OK)) {
 		if (ts->platform_data->use_sleep &&
 			(ts->platform_data->power_state == CY_ACTIVE_STATE)) {
+			if (ts->platform_data->suspend) {
+				retval =
+				ts->platform_data->suspend(ts->client);
+			} else {
+				retval = cyttsp_regulator_lpm(ts, true);
+			}
 			if (ts->platform_data->use_sleep & CY_USE_DEEP_SLEEP_SEL)
 				sleep_mode = CY_DEEP_SLEEP_MODE;
 			else
 				sleep_mode = CY_LOW_PWR_MODE;
 
-			retval = i2c_smbus_write_i2c_block_data(ts->client,
-				CY_REG_BASE,
-				sizeof(sleep_mode), &sleep_mode);
+			if (!(retval < CY_OK)) {
+				retval =
+				i2c_smbus_write_i2c_block_data(ts->client,
+								CY_REG_BASE,
+					sizeof(sleep_mode), &sleep_mode);
+			}
 		}
 	}
 
diff --git a/include/linux/cyttsp.h b/include/linux/cyttsp.h
index 8d69031..0e5cac7 100644
--- a/include/linux/cyttsp.h
+++ b/include/linux/cyttsp.h
@@ -87,9 +87,11 @@
 #define CY_TMA300_VTG_MAX_UV		5500000
 #define CY_TMA300_VTG_MIN_UV		1710000
 #define CY_TMA300_CURR_24HZ_UA		17500
+#define CY_TMA300_SLEEP_CURR_UA		10
 #define CY_I2C_VTG_MAX_UV		1800000
 #define CY_I2C_VTG_MIN_UV		1800000
 #define CY_I2C_CURR_UA			9630
+#define CY_I2C_SLEEP_CURR_UA		10
 
 
 /* define for inclusion of TTSP App Update Load File
@@ -445,9 +447,10 @@
 
 struct cyttsp_regulator {
 	const char *name;
-	u32	min_uV;
 	u32	max_uV;
-	u32	load_uA;
+	u32	min_uV;
+	u32	hpm_load_uA;
+	u32	lpm_load_uA;
 };
 
 struct cyttsp_platform_data {
@@ -484,6 +487,7 @@
 #ifdef CY_USE_I2C_DRIVER
 	s32 (*init)(struct i2c_client *client);
 	s32 (*resume)(struct i2c_client *client);
+	s32 (*suspend)(struct i2c_client *client);
 #endif
 #ifdef CY_USE_SPI_DRIVER
 	s32 (*init)(struct spi_device *spi);