Merge "input: misc: stk3x1x: turn off device power when sensor is not enabled"
diff --git a/drivers/input/misc/stk3x1x.c b/drivers/input/misc/stk3x1x.c
index 937bf6c..b753d55 100644
--- a/drivers/input/misc/stk3x1x.c
+++ b/drivers/input/misc/stk3x1x.c
@@ -190,6 +190,7 @@
 
 struct stk3x1x_data {
 	struct i2c_client *client;
+	struct stk3x1x_platform_data *pdata;
 #if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
     int32_t irq;
     struct work_struct stk_work;
@@ -257,6 +258,7 @@
 static int32_t stk3x1x_set_ps_thd_h(struct stk3x1x_data *ps_data, uint16_t thd_h);
 static int32_t stk3x1x_set_als_thd_l(struct stk3x1x_data *ps_data, uint16_t thd_l);
 static int32_t stk3x1x_set_als_thd_h(struct stk3x1x_data *ps_data, uint16_t thd_h);
+static int stk3x1x_device_ctl(struct stk3x1x_data *ps_data, bool enable);
 //static int32_t stk3x1x_set_ps_aoffset(struct stk3x1x_data *ps_data, uint16_t offset);
 
 inline uint32_t stk_alscode2lux(struct stk3x1x_data *ps_data, uint32_t alscode)
@@ -600,6 +602,12 @@
 	if(curr_ps_enable == enable)
 		return 0;
 
+	if (enable) {
+		ret = stk3x1x_device_ctl(ps_data, enable);
+		if (ret)
+			return ret;
+	}
+
     ret = i2c_smbus_read_byte_data(ps_data->client, STK_STATE_REG);
     if (ret < 0)
     {
@@ -662,6 +670,12 @@
 #endif
 		ps_data->ps_enabled = false;
 	}
+	if (!enable) {
+		ret = stk3x1x_device_ctl(ps_data, enable);
+		if (ret)
+			return ret;
+	}
+
 	return ret;
 }
 
@@ -674,6 +688,11 @@
 	if(curr_als_enable == enable)
 		return 0;
 
+	if (enable) {
+		ret = stk3x1x_device_ctl(ps_data, enable);
+		if (ret)
+			return ret;
+	}
 #ifndef STK_POLL_ALS
     if (enable)
 	{
@@ -724,6 +743,12 @@
 			disable_irq(ps_data->irq);
 #endif
 	}
+	if (!enable) {
+		ret = stk3x1x_device_ctl(ps_data, enable);
+		if (ret)
+			return ret;
+	}
+
     return ret;
 }
 
@@ -1817,11 +1842,6 @@
 	int32_t ret;
 	struct stk3x1x_data *ps_data = i2c_get_clientdata(client);
 
-	mutex_lock(&ps_data->io_lock);
-	ps_data->als_enabled = false;
-	ps_data->ps_enabled = false;
-	mutex_unlock(&ps_data->io_lock);
-
 	ret = stk3x1x_software_reset(ps_data);
 	if(ret < 0)
 		return ret;
@@ -1946,7 +1966,7 @@
 }
 #endif	//#ifdef CONFIG_HAS_EARLYSUSPEND
 
-static int stk3x1x_power_on(struct stk3x1x_data *data, bool on)
+static int stk3x1x_power_ctl(struct stk3x1x_data *data, bool on)
 {
 	int ret = 0;
 
@@ -1963,7 +1983,11 @@
 			dev_err(&data->client->dev,
 				"Regulator vio disable failed ret=%d\n", ret);
 			regulator_enable(data->vdd);
+			return ret;
 		}
+		data->power_enabled = on;
+		dev_dbg(&data->client->dev, "stk3x1x_power_ctl on=%d\n",
+				on);
 	} else if (on && !data->power_enabled) {
 
 		ret = regulator_enable(data->vdd);
@@ -1978,7 +2002,11 @@
 			dev_err(&data->client->dev,
 				"Regulator vio enable failed ret=%d\n", ret);
 			regulator_disable(data->vdd);
+			return ret;
 		}
+		data->power_enabled = on;
+		dev_dbg(&data->client->dev, "stk3x1x_power_ctl on=%d\n",
+				on);
 	} else {
 		dev_warn(&data->client->dev,
 				"Power on=%d. enabled=%d\n",
@@ -2057,6 +2085,43 @@
 	return ret;
 }
 
+static int stk3x1x_device_ctl(struct stk3x1x_data *ps_data, bool enable)
+{
+	int ret;
+	struct device *dev = &ps_data->client->dev;
+
+	if (enable && !ps_data->power_enabled) {
+		ret = stk3x1x_power_ctl(ps_data, true);
+		if (ret) {
+			dev_err(dev, "Failed to enable device power\n");
+			goto err_exit;
+		}
+		ret = stk3x1x_init_all_setting(ps_data->client, ps_data->pdata);
+		if (ret < 0) {
+			stk3x1x_power_ctl(ps_data, false);
+			dev_err(dev, "Failed to re-init device setting\n");
+			goto err_exit;
+		}
+	} else if (!enable && ps_data->power_enabled) {
+		if (!ps_data->als_enabled && !ps_data->ps_enabled) {
+			ret = stk3x1x_power_ctl(ps_data, false);
+			if (ret) {
+				dev_err(dev, "Failed to disable device power\n");
+				goto err_exit;
+			}
+		} else {
+			dev_dbg(dev, "device control: als_enabled=%d, ps_enabled=%d\n",
+				ps_data->als_enabled, ps_data->ps_enabled);
+		}
+	} else {
+		dev_dbg(dev, "device control: enable=%d, power_enabled=%d\n",
+			enable, ps_data->power_enabled);
+	}
+	return 0;
+
+err_exit:
+	return ret;
+}
 #ifdef CONFIG_OF
 static int stk3x1x_parse_dt(struct device *dev,
 			struct stk3x1x_platform_data *pdata)
@@ -2205,6 +2270,7 @@
 	ps_data->als_transmittance = plat_data->transmittance;
 	ps_data->int_pin = plat_data->int_pin;
 	ps_data->use_fir = plat_data->use_fir;
+	ps_data->pdata = plat_data;
 
 	if (ps_data->als_transmittance == 0) {
 		dev_err(&client->dev,
@@ -2285,24 +2351,28 @@
 	if (err)
 		goto err_power_init;
 
-	err = stk3x1x_power_on(ps_data, true);
+	err = stk3x1x_power_ctl(ps_data, true);
 	if (err)
 		goto err_power_on;
 
-	err = stk3x1x_init_all_setting(client, plat_data);
-	if(err < 0)
-		goto err_init_all_setting;
+	ps_data->als_enabled = false;
+	ps_data->ps_enabled = false;
 #ifdef CONFIG_HAS_EARLYSUSPEND
 	ps_data->stk_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
 	ps_data->stk_early_suspend.suspend = stk3x1x_early_suspend;
 	ps_data->stk_early_suspend.resume = stk3x1x_late_resume;
 	register_early_suspend(&ps_data->stk_early_suspend);
 #endif
-	printk(KERN_INFO "%s: probe successfully", __func__);
+	/* enable device power only when it is enabled */
+	err = stk3x1x_power_ctl(ps_data, false);
+	if (err)
+		goto err_init_all_setting;
+
+	dev_dbg(&client->dev, "%s: probe successfully", __func__);
 	return 0;
 
 err_init_all_setting:
-	stk3x1x_power_on(ps_data, false);
+	stk3x1x_power_ctl(ps_data, false);
 err_power_on:
 	stk3x1x_power_init(ps_data, false);
 err_power_init: