Skip to content

Commit

Permalink
Input: atmel_mxt_ts - add regulator control support
Browse files Browse the repository at this point in the history
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 <[email protected]>
Acked-by: Benson Leung <[email protected]>
Acked-by: Yufeng Shen <[email protected]>
  • Loading branch information
ndyer committed Apr 26, 2016
1 parent 2679443 commit 14052b6
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 8 deletions.
8 changes: 8 additions & 0 deletions Documentation/devicetree/bindings/input/atmel,maxtouch.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ Optional properties for main touchpad device:
experiment to determine which bit corresponds to which input. Use
KEY_RESERVED for unused padding values.

- atmel,suspend-mode: Select method used to suspend:
MXT_SUSPEND_DEEP_SLEEP - use T7 to suspend the device into deep sleep
MXT_SUSPEND_T9_CTRL - use T9.CTRL to turn off touch processing
MXT_SUSPEND_REGULATOR - use regulators to power down device during suspend
Definitions are in <dt-bindings/input/atmel_mxt_ts.h>.

- atmel,reset-gpio: Configure RESET GPIO. Required for regulator support.

Example:

touch@4b {
Expand Down
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -2055,6 +2055,7 @@ S: Supported
F: Documentation/devicetree/bindings/input/atmel,maxtouch.txt
F: drivers/input/touchscreen/atmel_mxt_ts.c
F: include/linux/platform_data/atmel_mxt_ts.h
F: include/dt-bindings/input/atmel_mxt_ts.h

ATTO EXPRESSSAS SAS/SATA RAID SCSI DRIVER
M: Bradley Grove <[email protected]>
Expand Down
125 changes: 122 additions & 3 deletions drivers/input/touchscreen/atmel_mxt_ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio.h>

/* Firmware files */
#define MXT_FW_NAME "maxtouch.fw"
Expand Down Expand Up @@ -186,6 +189,9 @@ enum t100_type {
#define MXT_CRC_TIMEOUT 1000 /* msec */
#define MXT_FW_RESET_TIME 3000 /* msec */
#define MXT_FW_CHG_TIMEOUT 300 /* msec */
#define MXT_REGULATOR_DELAY 150 /* msec */
#define MXT_CHG_DELAY 100 /* msec */
#define MXT_POWERON_DELAY 150 /* msec */

/* Command to unlock bootloader */
#define MXT_UNLOCK_CMD_MSB 0xaa
Expand Down Expand Up @@ -271,6 +277,8 @@ struct mxt_data {
u8 stylus_aux_pressure;
u8 stylus_aux_peak;
bool use_retrigen_workaround;
struct regulator *reg_vdd;
struct regulator *reg_avdd;

/* Cached parameters from object table */
u16 T5_address;
Expand Down Expand Up @@ -1997,6 +2005,90 @@ static int mxt_read_info_block(struct mxt_data *data)
return error;
}

static void mxt_regulator_enable(struct mxt_data *data)
{
int error;

if (!data->reg_vdd || !data->reg_avdd)
return;

gpio_set_value(data->pdata->gpio_reset, 0);

error = regulator_enable(data->reg_vdd);
if (error)
return;

error = regulator_enable(data->reg_avdd);
if (error)
return;

/*
* According to maXTouch power sequencing specification, RESET line
* must be kept low until some time after regulators come up to
* voltage
*/
msleep(MXT_REGULATOR_DELAY);
gpio_set_value(data->pdata->gpio_reset, 1);
msleep(MXT_CHG_DELAY);

retry_wait:
reinit_completion(&data->bl_completion);
data->in_bootloader = true;
error = mxt_wait_for_completion(data, &data->bl_completion,
MXT_POWERON_DELAY);
if (error == -EINTR)
goto retry_wait;

data->in_bootloader = false;
}

static void mxt_regulator_disable(struct mxt_data *data)
{
if (!data->reg_vdd || !data->reg_avdd)
return;

regulator_disable(data->reg_vdd);
regulator_disable(data->reg_avdd);
}

static int mxt_probe_regulators(struct mxt_data *data)
{
struct device *dev = &data->client->dev;
int error;

/* Must have reset GPIO to use regulator support */
if (!gpio_is_valid(data->pdata->gpio_reset)) {
error = -EINVAL;
goto fail;
}

data->reg_vdd = regulator_get(dev, "vdd");
if (IS_ERR(data->reg_vdd)) {
error = PTR_ERR(data->reg_vdd);
dev_err(dev, "Error %d getting vdd regulator\n", error);
goto fail;
}

data->reg_avdd = regulator_get(dev, "avdd");
if (IS_ERR(data->reg_avdd)) {
error = PTR_ERR(data->reg_avdd);
dev_err(dev, "Error %d getting avdd regulator\n", error);
goto fail_release;
}

mxt_regulator_enable(data);

dev_dbg(dev, "Initialised regulators\n");
return 0;

fail_release:
regulator_put(data->reg_vdd);
fail:
data->reg_vdd = NULL;
data->reg_avdd = NULL;
return error;
}

static int mxt_read_t9_resolution(struct mxt_data *data)
{
struct i2c_client *client = data->client;
Expand Down Expand Up @@ -2609,7 +2701,12 @@ static int mxt_load_fw(struct device *dev, const char *fn)
goto release_firmware;

if (data->suspended) {
enable_irq(data->irq);
if (data->pdata->suspend_mode == MXT_SUSPEND_REGULATOR)
mxt_regulator_enable(data);

if (data->pdata->suspend_mode == MXT_SUSPEND_DEEP_SLEEP)
enable_irq(data->irq);

data->suspended = false;
}

Expand Down Expand Up @@ -2817,6 +2914,11 @@ static void mxt_start(struct mxt_data *data)
MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0x83);
break;

case MXT_SUSPEND_REGULATOR:
enable_irq(data->irq);
mxt_regulator_enable(data);
break;

case MXT_SUSPEND_DEEP_SLEEP:
default:
/*
Expand Down Expand Up @@ -2849,6 +2951,12 @@ static void mxt_stop(struct mxt_data *data)
MXT_TOUCH_MULTI_T9, MXT_T9_CTRL, 0);
break;

case MXT_SUSPEND_REGULATOR:
disable_irq(data->irq);
mxt_regulator_disable(data);
mxt_reset_slots(data);
break;

case MXT_SUSPEND_DEEP_SLEEP:
default:
disable_irq(data->irq);
Expand Down Expand Up @@ -2893,6 +3001,9 @@ static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
if (!pdata)
return ERR_PTR(-ENOMEM);

pdata->gpio_reset = of_get_named_gpio_flags(np, "atmel,reset-gpio",
0, NULL);

if (of_find_property(np, "linux,gpio-keymap", &proplen)) {
pdata->t19_num_keys = proplen / sizeof(u32);

Expand All @@ -2911,7 +3022,7 @@ static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
pdata->t19_keymap = keymap;
}

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

return pdata;
}
Expand Down Expand Up @@ -3100,7 +3211,13 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
goto err_free_mem;
}

disable_irq(client->irq);
if (pdata->suspend_mode == MXT_SUSPEND_REGULATOR) {
error = mxt_probe_regulators(data);
if (error)
goto err_free_irq;
}

disable_irq(data->irq);

error = sysfs_create_group(&client->dev.kobj, &mxt_fw_attr_group);
if (error) {
Expand Down Expand Up @@ -3129,6 +3246,8 @@ static int mxt_remove(struct i2c_client *client)
sysfs_remove_group(&client->dev.kobj, &mxt_fw_attr_group);
mxt_sysfs_remove(data);
free_irq(data->irq, data);
regulator_put(data->reg_avdd);
regulator_put(data->reg_vdd);
mxt_free_input_device(data);
mxt_free_object_table(data);
kfree(data);
Expand Down
22 changes: 22 additions & 0 deletions include/dt-bindings/input/atmel_mxt_ts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Atmel maXTouch Touchscreen driver
*
* Copyright (C) 2015 Atmel Corporation
* Author: Nick Dyer <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/

#ifndef __DT_BINDINGS_ATMEL_MXT_TS_H
#define __DT_BINDINGS_ATMEL_MXT_TS_H

enum mxt_suspend_mode {
MXT_SUSPEND_DEEP_SLEEP = 0,
MXT_SUSPEND_T9_CTRL = 1,
MXT_SUSPEND_REGULATOR = 2,
};

#endif /* __DT_BINDINGS_ATMEL_MXT_TS_H */
7 changes: 2 additions & 5 deletions include/linux/platform_data/atmel_mxt_ts.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@
#define __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H

#include <linux/types.h>

enum mxt_suspend_mode {
MXT_SUSPEND_DEEP_SLEEP = 0,
MXT_SUSPEND_T9_CTRL = 1,
};
#include <dt-bindings/input/atmel_mxt_ts.h>

/* The platform data for the Atmel maXTouch touchscreen driver */
struct mxt_platform_data {
Expand All @@ -28,6 +24,7 @@ struct mxt_platform_data {
enum mxt_suspend_mode suspend_mode;
int t15_num_keys;
const unsigned int *t15_keymap;
unsigned long gpio_reset;
};

#endif /* __LINUX_PLATFORM_DATA_ATMEL_MXT_TS_H */

0 comments on commit 14052b6

Please sign in to comment.