diff options
author | Jagan Teki | 2019-04-04 00:20:26 +0200 |
---|---|---|
committer | Dmitry Torokhov | 2019-04-04 01:10:42 +0200 |
commit | ae97fb589648cd5558f1ceea317404a639307501 (patch) | |
tree | bda65aa2969e515cce8a5ca9842ff06f7bfff23a /drivers/input | |
parent | Input: evdev - use struct_size() in kzalloc() and vzalloc() (diff) | |
download | kernel-qcow2-linux-ae97fb589648cd5558f1ceea317404a639307501.tar.gz kernel-qcow2-linux-ae97fb589648cd5558f1ceea317404a639307501.tar.xz kernel-qcow2-linux-ae97fb589648cd5558f1ceea317404a639307501.zip |
Input: goodix - add regulators suppot
Goodix CTP controllers require AVDD28, VDDIO regulators for power-on
sequence.
The delay between these regualtor operations as per Power-on Timing
from datasheet[1] is 0 (T1 >= 0 usec).
So, enable and disable these regulators in proper order using normal
regulator functions without any delay in between.
[1] GT5663 Datasheet_English_20151106_Rev.01
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/touchscreen/goodix.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index f57d82220a88..b1c071fd243a 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -27,6 +27,7 @@ #include <linux/delay.h> #include <linux/irq.h> #include <linux/interrupt.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/acpi.h> #include <linux/of.h> @@ -47,6 +48,8 @@ struct goodix_ts_data { struct touchscreen_properties prop; unsigned int max_touch_num; unsigned int int_trigger_type; + struct regulator *avdd28; + struct regulator *vddio; struct gpio_desc *gpiod_int; struct gpio_desc *gpiod_rst; u16 id; @@ -532,6 +535,24 @@ static int goodix_get_gpio_config(struct goodix_ts_data *ts) return -EINVAL; dev = &ts->client->dev; + ts->avdd28 = devm_regulator_get(dev, "AVDD28"); + if (IS_ERR(ts->avdd28)) { + error = PTR_ERR(ts->avdd28); + if (error != -EPROBE_DEFER) + dev_err(dev, + "Failed to get AVDD28 regulator: %d\n", error); + return error; + } + + ts->vddio = devm_regulator_get(dev, "VDDIO"); + if (IS_ERR(ts->vddio)) { + error = PTR_ERR(ts->vddio); + if (error != -EPROBE_DEFER) + dev_err(dev, + "Failed to get VDDIO regulator: %d\n", error); + return error; + } + /* Get the interrupt GPIO pin number */ gpiod = devm_gpiod_get_optional(dev, GOODIX_GPIO_INT_NAME, GPIOD_IN); if (IS_ERR(gpiod)) { @@ -764,6 +785,14 @@ err_release_cfg: complete_all(&ts->firmware_loading_complete); } +static void goodix_disable_regulators(void *arg) +{ + struct goodix_ts_data *ts = arg; + + regulator_disable(ts->vddio); + regulator_disable(ts->avdd28); +} + static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -789,6 +818,29 @@ static int goodix_ts_probe(struct i2c_client *client, if (error) return error; + /* power up the controller */ + error = regulator_enable(ts->avdd28); + if (error) { + dev_err(&client->dev, + "Failed to enable AVDD28 regulator: %d\n", + error); + return error; + } + + error = regulator_enable(ts->vddio); + if (error) { + dev_err(&client->dev, + "Failed to enable VDDIO regulator: %d\n", + error); + regulator_disable(ts->avdd28); + return error; + } + + error = devm_add_action_or_reset(&client->dev, + goodix_disable_regulators, ts); + if (error) + return error; + if (ts->gpiod_int && ts->gpiod_rst) { /* reset the controller */ error = goodix_reset(ts); |