Merge branch 'next' into for-linus
[sfrench/cifs-2.6.git] / drivers / input / touchscreen / atmel_mxt_ts.c
index 383a848eb60158c88315e6f6eae73a7bdfb2ac7e..05de92c0293bca82889c7a94912e748368b8b1b6 100644 (file)
@@ -31,6 +31,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
+#include <dt-bindings/input/atmel-maxtouch.h>
 
 /* Firmware files */
 #define MXT_FW_NAME            "maxtouch.fw"
@@ -199,6 +200,7 @@ 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_WAKEUP_TIME                25      /* msec */
 
 /* Command to unlock bootloader */
 #define MXT_UNLOCK_CMD_MSB     0xaa
@@ -312,6 +314,7 @@ struct mxt_data {
        struct mxt_dbg dbg;
        struct regulator_bulk_data regulators[2];
        struct gpio_desc *reset_gpio;
+       struct gpio_desc *wake_gpio;
        bool use_retrigen_workaround;
 
        /* Cached parameters from object table */
@@ -342,6 +345,8 @@ struct mxt_data {
        unsigned int t19_num_keys;
 
        enum mxt_suspend_mode suspend_mode;
+
+       u32 wakeup_method;
 };
 
 struct mxt_vb2_buffer {
@@ -621,10 +626,42 @@ static int mxt_send_bootloader_cmd(struct mxt_data *data, bool unlock)
        return mxt_bootloader_write(data, buf, sizeof(buf));
 }
 
+static bool mxt_wakeup_toggle(struct i2c_client *client,
+                             bool wake_up, bool in_i2c)
+{
+       struct mxt_data *data = i2c_get_clientdata(client);
+
+       switch (data->wakeup_method) {
+       case ATMEL_MXT_WAKEUP_I2C_SCL:
+               if (!in_i2c)
+                       return false;
+               break;
+
+       case ATMEL_MXT_WAKEUP_GPIO:
+               if (in_i2c)
+                       return false;
+
+               gpiod_set_value(data->wake_gpio, wake_up);
+               break;
+
+       default:
+               return false;
+       }
+
+       if (wake_up) {
+               dev_dbg(&client->dev, "waking up controller\n");
+
+               msleep(MXT_WAKEUP_TIME);
+       }
+
+       return true;
+}
+
 static int __mxt_read_reg(struct i2c_client *client,
                               u16 reg, u16 len, void *val)
 {
        struct i2c_msg xfer[2];
+       bool retried = false;
        u8 buf[2];
        int ret;
 
@@ -643,9 +680,13 @@ static int __mxt_read_reg(struct i2c_client *client,
        xfer[1].len = len;
        xfer[1].buf = val;
 
+retry:
        ret = i2c_transfer(client->adapter, xfer, 2);
        if (ret == 2) {
                ret = 0;
+       } else if (!retried && mxt_wakeup_toggle(client, true, true)) {
+               retried = true;
+               goto retry;
        } else {
                if (ret >= 0)
                        ret = -EIO;
@@ -659,6 +700,7 @@ static int __mxt_read_reg(struct i2c_client *client,
 static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
                           const void *val)
 {
+       bool retried = false;
        u8 *buf;
        size_t count;
        int ret;
@@ -672,9 +714,13 @@ static int __mxt_write_reg(struct i2c_client *client, u16 reg, u16 len,
        buf[1] = (reg >> 8) & 0xff;
        memcpy(&buf[2], val, len);
 
+retry:
        ret = i2c_master_send(client, buf, count);
        if (ret == count) {
                ret = 0;
+       } else if (!retried && mxt_wakeup_toggle(client, true, true)) {
+               retried = true;
+               goto retry;
        } else {
                if (ret >= 0)
                        ret = -EIO;
@@ -2975,6 +3021,8 @@ static const struct attribute_group mxt_attr_group = {
 
 static void mxt_start(struct mxt_data *data)
 {
+       mxt_wakeup_toggle(data->client, true, false);
+
        switch (data->suspend_mode) {
        case MXT_SUSPEND_T9_CTRL:
                mxt_soft_reset(data);
@@ -3009,6 +3057,8 @@ static void mxt_stop(struct mxt_data *data)
                mxt_set_t7_power_cfg(data, MXT_POWER_CFG_DEEPSLEEP);
                break;
        }
+
+       mxt_wakeup_toggle(data->client, false, false);
 }
 
 static int mxt_input_open(struct input_dev *dev)
@@ -3155,16 +3205,24 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
                return error;
        }
 
+       /* Request the WAKE line as asserted so we go out of sleep */
+       data->wake_gpio = devm_gpiod_get_optional(&client->dev,
+                                                 "wake", GPIOD_OUT_HIGH);
+       if (IS_ERR(data->wake_gpio)) {
+               error = PTR_ERR(data->wake_gpio);
+               dev_err(&client->dev, "Failed to get wake gpio: %d\n", error);
+               return error;
+       }
+
        error = devm_request_threaded_irq(&client->dev, client->irq,
-                                         NULL, mxt_interrupt, IRQF_ONESHOT,
+                                         NULL, mxt_interrupt,
+                                         IRQF_ONESHOT | IRQF_NO_AUTOEN,
                                          client->name, data);
        if (error) {
                dev_err(&client->dev, "Failed to register interrupt\n");
                return error;
        }
 
-       disable_irq(client->irq);
-
        error = regulator_bulk_enable(ARRAY_SIZE(data->regulators),
                                      data->regulators);
        if (error) {
@@ -3185,6 +3243,25 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
                msleep(MXT_RESET_INVALID_CHG);
        }
 
+       /*
+        * Controllers like mXT1386 have a dedicated WAKE line that could be
+        * connected to a GPIO or to I2C SCL pin, or permanently asserted low.
+        *
+        * This WAKE line is used for waking controller from a deep-sleep and
+        * it needs to be asserted low for 25 milliseconds before I2C transfers
+        * could be accepted by controller if it was in a deep-sleep mode.
+        * Controller will go into sleep automatically after 2 seconds of
+        * inactivity if WAKE line is deasserted and deep sleep is activated.
+        *
+        * If WAKE line is connected to I2C SCL pin, then the first I2C transfer
+        * will get an instant NAK and transfer needs to be retried after 25ms.
+        *
+        * If WAKE line is connected to a GPIO line, the line must be asserted
+        * 25ms before the host attempts to communicate with the controller.
+        */
+       device_property_read_u32(&client->dev, "atmel,wakeup-method",
+                                &data->wakeup_method);
+
        error = mxt_initialize(data);
        if (error)
                goto err_disable_regulators;