[PATCH 6/6] Input: edt-ft5x06 - add supply voltage support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently the driver do not care about the regulator which supplies the
controller. This can lead into problems since we support (deep-)sleep
because the regulator can be turned off before we send the (deep-)sleep
command to the controller. Using a own regulator improves the power
consumption during sleep even more.

Signed-off-by: Marco Felsch <m.felsch@xxxxxxxxxxxxxx>
---
 drivers/input/touchscreen/edt-ft5x06.c | 53 ++++++++++++++++++++++----
 1 file changed, 46 insertions(+), 7 deletions(-)

diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
index b95ce5a7482d..6429e915ec94 100644
--- a/drivers/input/touchscreen/edt-ft5x06.c
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/property.h>
 #include <linux/ratelimit.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 
@@ -96,6 +97,7 @@ struct edt_ft5x06_ts_data {
 
 	struct gpio_desc *reset_gpio;
 	struct gpio_desc *wake_gpio;
+	struct regulator *vdd;
 
 #if defined(CONFIG_DEBUG_FS)
 	struct dentry *debug_dir;
@@ -1090,6 +1092,23 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 		return error;
 	}
 
+	tsdata->vdd = devm_regulator_get(&client->dev, "vdd");
+	if (IS_ERR(tsdata->vdd)) {
+		error = PTR_ERR(tsdata->vdd);
+		if (error == -EPROBE_DEFER)
+			return error;
+		dev_err(&client->dev,
+			"Failed to request vdd-supply, error %d\n", error);
+		return error;
+	}
+
+	error = regulator_enable(tsdata->vdd);
+	if (error) {
+		dev_err(&client->dev,
+			"Failed to enable vdd-supply, error %d\n", error);
+		return error;
+	}
+
 	/*
 	 * We need to go this way to keep backward compatibility with old DT's
 	 * which may assume the default-on mechanism.
@@ -1111,7 +1130,8 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 	input = devm_input_allocate_device(&client->dev);
 	if (!input) {
 		dev_err(&client->dev, "failed to allocate input device.\n");
-		return -ENOMEM;
+		error = -ENOMEM;
+		goto err_reg_disable;
 	}
 
 	mutex_init(&tsdata->mutex);
@@ -1122,7 +1142,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 	error = edt_ft5x06_ts_identify(client, tsdata, fw_version);
 	if (error) {
 		dev_err(&client->dev, "touchscreen probe failed\n");
-		return error;
+		goto err_reg_disable;
 	}
 
 	edt_ft5x06_ts_set_regs(tsdata);
@@ -1158,7 +1178,7 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 				INPUT_MT_DIRECT);
 	if (error) {
 		dev_err(&client->dev, "Unable to init MT slots.\n");
-		return error;
+		goto err_reg_disable;
 	}
 
 	i2c_set_clientdata(client, tsdata);
@@ -1173,16 +1193,16 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 					client->name, tsdata);
 	if (error) {
 		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
-		return error;
+		goto err_reg_disable;
 	}
 
 	error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group);
 	if (error)
-		return error;
+		goto err_reg_disable;
 
 	error = input_register_device(input);
 	if (error)
-		return error;
+		goto err_reg_disable;
 
 	edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev));
 	device_init_wakeup(&client->dev, en_wakeup);
@@ -1194,6 +1214,10 @@ static int edt_ft5x06_ts_probe(struct i2c_client *client,
 		tsdata->reset_gpio ? desc_to_gpio(tsdata->reset_gpio) : -1);
 
 	return 0;
+
+err_reg_disable:
+	regulator_disable(tsdata->vdd);
+	return error;
 }
 
 static int edt_ft5x06_ts_remove(struct i2c_client *client)
@@ -1225,8 +1249,16 @@ static int __maybe_unused edt_ft5x06_ts_suspend(struct device *dev)
 
 	ret = edt_ft5x06_register_write(tsdata, PMOD_REGISTER_OPMODE,
 					PMOD_REGISTER_HIBERNATE);
-	if (ret)
+	if (ret) {
 		dev_err(dev, "Failed to set hibernate mode\n");
+		return ret;
+	}
+
+	ret = regulator_disable(tsdata->vdd);
+	if (ret) {
+		dev_err(dev, "Failed to disable vdd\n");
+		return ret;
+	}
 
 	return ret;
 }
@@ -1235,12 +1267,19 @@ static int __maybe_unused edt_ft5x06_ts_resume(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
+	int error;
 
 	if (device_may_wakeup(dev)) {
 		disable_irq_wake(client->irq);
 		return 0;
 	}
 
+	error = regulator_enable(tsdata->vdd);
+	if (error) {
+		dev_err(&client->dev, "Failed to enable vdd\n");
+		return error;
+	}
+
 	/* Recover from hibernate mode if hardware supports it */
 	if (tsdata->wake_gpio) {
 		gpiod_set_value_cansleep(tsdata->wake_gpio, 0);
-- 
2.20.1




[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux