Skip to content

Commit 180b9e0

Browse files
ndyerehristev
authored andcommitted
Input: atmel_mxt_ts - add regulator control support
Allow the driver to optionally manage enabling/disable power to the touch controller itself. If the regulators are not present then use the deep sleep power mode instead. For a correct power on sequence, it is required that we have control over the RESET line. Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk> Acked-by: Benson Leung <bleung@chromium.org> Acked-by: Yufeng Shen <miletus@chromium.org> [cyrille.pitchen@atmel.com: adapt original patch to mainline] Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com> [eugen.hristev@microchip.com: adapt original patch to 4.14] Signed-off-by: Eugen Hristev <eugen.hristev@microchip.com>
1 parent 758120f commit 180b9e0

3 files changed

Lines changed: 154 additions & 18 deletions

File tree

drivers/input/touchscreen/atmel_mxt_ts.c

Lines changed: 130 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,12 @@
2727
#include <linux/input/mt.h>
2828
#include <linux/interrupt.h>
2929
#include <linux/of.h>
30+
#include <linux/of_gpio.h>
3031
#include <linux/slab.h>
3132
#include <linux/gpio/consumer.h>
3233
#include <asm/unaligned.h>
34+
#include <linux/regulator/consumer.h>
35+
#include <linux/gpio.h>
3336
#include <media/v4l2-device.h>
3437
#include <media/v4l2-ioctl.h>
3538
#include <media/videobuf2-v4l2.h>
@@ -198,6 +201,9 @@ enum t100_type {
198201
#define MXT_CRC_TIMEOUT 1000 /* msec */
199202
#define MXT_FW_RESET_TIME 3000 /* msec */
200203
#define MXT_FW_CHG_TIMEOUT 300 /* msec */
204+
#define MXT_REGULATOR_DELAY 150 /* msec */
205+
#define MXT_CHG_DELAY 100 /* msec */
206+
#define MXT_POWERON_DELAY 150 /* msec */
201207

202208
/* Command to unlock bootloader */
203209
#define MXT_UNLOCK_CMD_MSB 0xaa
@@ -301,6 +307,8 @@ struct mxt_data {
301307
u8 num_touchids;
302308
u8 multitouch;
303309
struct t7_config t7_cfg;
310+
struct regulator *reg_vdd;
311+
struct regulator *reg_avdd;
304312
struct mxt_dbg dbg;
305313
struct gpio_desc *reset_gpio;
306314

@@ -2086,6 +2094,84 @@ static void mxt_config_cb(const struct firmware *cfg, void *ctx)
20862094
release_firmware(cfg);
20872095
}
20882096

2097+
static void mxt_regulator_enable(struct mxt_data *data)
2098+
{
2099+
int error;
2100+
2101+
gpio_set_value(data->pdata->gpio_reset, 0);
2102+
2103+
error = regulator_enable(data->reg_vdd);
2104+
if (error)
2105+
return;
2106+
2107+
error = regulator_enable(data->reg_avdd);
2108+
if (error)
2109+
return;
2110+
2111+
/*
2112+
* According to maXTouch power sequencing specification, RESET line
2113+
* must be kept low until some time after regulators come up to
2114+
* voltage
2115+
*/
2116+
msleep(MXT_REGULATOR_DELAY);
2117+
gpio_set_value(data->pdata->gpio_reset, 1);
2118+
msleep(MXT_CHG_DELAY);
2119+
2120+
retry_wait:
2121+
reinit_completion(&data->bl_completion);
2122+
data->in_bootloader = true;
2123+
error = mxt_wait_for_completion(data, &data->bl_completion,
2124+
MXT_POWERON_DELAY);
2125+
if (error == -EINTR)
2126+
goto retry_wait;
2127+
2128+
data->in_bootloader = false;
2129+
}
2130+
2131+
static void mxt_regulator_disable(struct mxt_data *data)
2132+
{
2133+
regulator_disable(data->reg_vdd);
2134+
regulator_disable(data->reg_avdd);
2135+
}
2136+
2137+
static int mxt_probe_regulators(struct mxt_data *data)
2138+
{
2139+
struct device *dev = &data->client->dev;
2140+
int error;
2141+
2142+
/* Must have reset GPIO to use regulator support */
2143+
if (!gpio_is_valid(data->pdata->gpio_reset)) {
2144+
error = -EINVAL;
2145+
goto fail;
2146+
}
2147+
2148+
data->reg_vdd = regulator_get(dev, "vdd");
2149+
if (IS_ERR(data->reg_vdd)) {
2150+
error = PTR_ERR(data->reg_vdd);
2151+
dev_err(dev, "Error %d getting vdd regulator\n", error);
2152+
goto fail;
2153+
}
2154+
2155+
data->reg_avdd = regulator_get(dev, "avdd");
2156+
if (IS_ERR(data->reg_vdd)) {
2157+
error = PTR_ERR(data->reg_vdd);
2158+
dev_err(dev, "Error %d getting avdd regulator\n", error);
2159+
goto fail_release;
2160+
}
2161+
2162+
mxt_regulator_enable(data);
2163+
2164+
dev_dbg(dev, "Initialised regulators\n");
2165+
return 0;
2166+
2167+
fail_release:
2168+
regulator_put(data->reg_vdd);
2169+
fail:
2170+
data->reg_vdd = NULL;
2171+
data->reg_avdd = NULL;
2172+
return error;
2173+
}
2174+
20892175
static int mxt_initialize(struct mxt_data *data)
20902176
{
20912177
struct i2c_client *client = data->client;
@@ -2765,7 +2851,12 @@ static int mxt_load_fw(struct device *dev, const char *fn)
27652851
goto release_firmware;
27662852

27672853
if (data->suspended) {
2768-
enable_irq(data->irq);
2854+
if (data->pdata->suspend_mode == MXT_SUSPEND_REGULATOR)
2855+
mxt_regulator_enable(data);
2856+
2857+
if (data->pdata->suspend_mode == MXT_SUSPEND_DEEP_SLEEP)
2858+
enable_irq(data->irq);
2859+
27692860
data->suspended = false;
27702861
}
27712862

@@ -2931,12 +3022,6 @@ static void mxt_start(struct mxt_data *data)
29313022
if (!data->suspended || data->in_bootloader)
29323023
return;
29333024

2934-
/*
2935-
* Discard any touch messages still in message buffer
2936-
* from before chip went to sleep
2937-
*/
2938-
mxt_process_messages_until_invalid(data);
2939-
29403025
switch (data->pdata->suspend_mode) {
29413026
case MXT_SUSPEND_T9_CTRL:
29423027
mxt_soft_reset(data);
@@ -2947,16 +3032,28 @@ static void mxt_start(struct mxt_data *data)
29473032
MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0x83);
29483033
break;
29493034

3035+
case MXT_SUSPEND_REGULATOR:
3036+
enable_irq(data->irq);
3037+
mxt_regulator_enable(data);
3038+
break;
3039+
29503040
case MXT_SUSPEND_DEEP_SLEEP:
29513041
default:
3042+
/*
3043+
* Discard any touch messages still in message buffer
3044+
* from before chip went to sleep
3045+
*/
3046+
mxt_process_messages_until_invalid(data);
3047+
29523048
mxt_set_t7_power_cfg(data, MXT_POWER_CFG_RUN);
29533049

29543050
/* Recalibrate since chip has been in deep sleep */
29553051
mxt_t6_command(data, MXT_COMMAND_CALIBRATE, 1, false);
3052+
3053+
mxt_acquire_irq(data);
29563054
break;
29573055
}
29583056

2959-
mxt_acquire_irq(data);
29603057
data->suspended = false;
29613058
}
29623059

@@ -2965,22 +3062,29 @@ static void mxt_stop(struct mxt_data *data)
29653062
if (data->suspended || data->in_bootloader)
29663063
return;
29673064

2968-
disable_irq(data->irq);
2969-
29703065
switch (data->pdata->suspend_mode) {
29713066
case MXT_SUSPEND_T9_CTRL:
29723067
/* Touch disable */
29733068
mxt_write_object(data,
29743069
MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0);
29753070
break;
29763071

3072+
case MXT_SUSPEND_REGULATOR:
3073+
disable_irq(data->irq);
3074+
mxt_regulator_disable(data);
3075+
mxt_reset_slots(data);
3076+
break;
3077+
29773078
case MXT_SUSPEND_DEEP_SLEEP:
29783079
default:
3080+
disable_irq(data->irq);
3081+
29793082
mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
3083+
3084+
mxt_reset_slots(data);
29803085
break;
29813086
}
29823087

2983-
mxt_reset_slots(data);
29843088
data->suspended = true;
29853089
}
29863090

@@ -3015,6 +3119,9 @@ static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
30153119
if (!pdata)
30163120
return ERR_PTR(-ENOMEM);
30173121

3122+
pdata->gpio_reset = of_get_named_gpio_flags(np, "atmel,reset-gpio",
3123+
0, NULL);
3124+
30183125
if (of_find_property(np, "linux,gpio-keymap", &proplen)) {
30193126
pdata->t19_num_keys = proplen / sizeof(u32);
30203127

@@ -3033,7 +3140,7 @@ static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
30333140
pdata->t19_keymap = keymap;
30343141
}
30353142

3036-
pdata->suspend_mode = MXT_SUSPEND_DEEP_SLEEP;
3143+
of_property_read_u32(np, "atmel,suspend-mode", &pdata->suspend_mode);
30373144

30383145
return pdata;
30393146
}
@@ -3252,7 +3359,15 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
32523359
data->in_bootloader = false;
32533360
}
32543361

3255-
disable_irq(client->irq);
3362+
if (pdata->suspend_mode == MXT_SUSPEND_REGULATOR) {
3363+
error = mxt_probe_regulators(data);
3364+
if (error)
3365+
return error;
3366+
3367+
disable_irq(data->irq);
3368+
}
3369+
3370+
disable_irq(data->irq);
32563371

32573372
error = mxt_initialize(data);
32583373
if (error) {
@@ -3285,6 +3400,8 @@ static int mxt_remove(struct i2c_client *client)
32853400

32863401
disable_irq(data->irq);
32873402
sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
3403+
regulator_put(data->reg_avdd);
3404+
regulator_put(data->reg_vdd);
32883405
mxt_free_input_device(data);
32893406
mxt_free_object_table(data);
32903407

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Atmel maXTouch Touchscreen driver
3+
*
4+
* Copyright (C) 2015 Atmel Corporation
5+
* Author: Nick Dyer <nick.dyer@itdev.co.uk>
6+
*
7+
* This program is free software; you can redistribute it and/or modify it
8+
* under the terms of the GNU General Public License as published by the
9+
* Free Software Foundation; either version 2 of the License, or (at your
10+
* option) any later version.
11+
*/
12+
13+
#ifndef __DT_BINDINGS_ATMEL_MXT_TS_H
14+
#define __DT_BINDINGS_ATMEL_MXT_TS_H
15+
16+
enum mxt_suspend_mode {
17+
MXT_SUSPEND_DEEP_SLEEP = 0,
18+
MXT_SUSPEND_T9_CTRL = 1,
19+
MXT_SUSPEND_REGULATOR = 2,
20+
};
21+
22+
#endif /* __DT_BINDINGS_ATMEL_MXT_TS_H */

include/linux/platform_data/atmel_mxt_ts.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,15 @@
1414
#define __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H
1515

1616
#include <linux/types.h>
17-
18-
enum mxt_suspend_mode {
19-
MXT_SUSPEND_DEEP_SLEEP = 0,
20-
MXT_SUSPEND_T9_CTRL = 1,
21-
};
17+
#include <dt-bindings/input/atmel_mxt_ts.h>
2218

2319
/* The platform data for the Atmel maXTouch touchscreen driver */
2420
struct mxt_platform_data {
2521
unsigned long irqflags;
2622
u8 t19_num_keys;
2723
const unsigned int *t19_keymap;
2824
enum mxt_suspend_mode suspend_mode;
25+
unsigned long gpio_reset;
2926
};
3027

3128
#endif /* __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H */

0 commit comments

Comments
 (0)