bcm27xx: remove linux 4.19 support
[openwrt/staging/luka.git] / target / linux / bcm27xx / patches-4.19 / 950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch
diff --git a/target/linux/bcm27xx/patches-4.19/950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch b/target/linux/bcm27xx/patches-4.19/950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch
deleted file mode 100644 (file)
index 84c99ff..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-From 9c823e2ee1ec1b815b8ec29c231b112c5e397202 Mon Sep 17 00:00:00 2001
-From: Samuel Hsu <hsu@distec.de>
-Date: Mon, 8 Apr 2019 16:42:17 +0200
-Subject: [PATCH] Input: ili210x - fetch touchscreen geometry from DT
-
-commit f67cc3e927d8414ad3872e046764534ea1f5db0d upstream
-
-Fetching the geometry from the ILI251x registers seems unreliable and
-sometimes returns all zeroes. Add support for fetching the geometry and
-axis inversion from DT instead.
-
-Signed-off-by: Marek Vasut <marex@denx.de>
-Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
----
- drivers/input/touchscreen/ili210x.c | 321 +++++++++++++++++-----------
- 1 file changed, 194 insertions(+), 127 deletions(-)
-
---- a/drivers/input/touchscreen/ili210x.c
-+++ b/drivers/input/touchscreen/ili210x.c
-@@ -4,11 +4,15 @@
- #include <linux/slab.h>
- #include <linux/input.h>
- #include <linux/input/mt.h>
-+#include <linux/input/touchscreen.h>
- #include <linux/delay.h>
- #include <linux/workqueue.h>
--#include <linux/input/ili210x.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/of_device.h>
-+#include <asm/unaligned.h>
--#define MAX_TOUCHES           2
-+#define ILI210X_TOUCHES               2
-+#define ILI251X_TOUCHES               10
- #define DEFAULT_POLL_PERIOD   20
- /* Touchscreen commands */
-@@ -17,41 +21,32 @@
- #define REG_FIRMWARE_VERSION  0x40
- #define REG_CALIBRATE         0xcc
--struct finger {
--      u8 x_low;
--      u8 x_high;
--      u8 y_low;
--      u8 y_high;
--} __packed;
--
--struct touchdata {
--      u8 status;
--      struct finger finger[MAX_TOUCHES];
--} __packed;
--
--struct panel_info {
--      struct finger finger_max;
--      u8 xchannel_num;
--      u8 ychannel_num;
--} __packed;
--
- struct firmware_version {
-       u8 id;
-       u8 major;
-       u8 minor;
- } __packed;
-+enum ili2xxx_model {
-+      MODEL_ILI210X,
-+      MODEL_ILI251X,
-+};
-+
- struct ili210x {
-       struct i2c_client *client;
-       struct input_dev *input;
--      bool (*get_pendown_state)(void);
-       unsigned int poll_period;
-       struct delayed_work dwork;
-+      struct gpio_desc *reset_gpio;
-+      struct touchscreen_properties prop;
-+      enum ili2xxx_model model;
-+      unsigned int max_touches;
- };
- static int ili210x_read_reg(struct i2c_client *client, u8 reg, void *buf,
-                           size_t len)
- {
-+      struct ili210x *priv = i2c_get_clientdata(client);
-       struct i2c_msg msg[2] = {
-               {
-                       .addr   = client->addr,
-@@ -67,7 +62,38 @@ static int ili210x_read_reg(struct i2c_c
-               }
-       };
--      if (i2c_transfer(client->adapter, msg, 2) != 2) {
-+      if (priv->model == MODEL_ILI251X) {
-+              if (i2c_transfer(client->adapter, msg, 1) != 1) {
-+                      dev_err(&client->dev, "i2c transfer failed\n");
-+                      return -EIO;
-+              }
-+
-+              usleep_range(5000, 5500);
-+
-+              if (i2c_transfer(client->adapter, msg + 1, 1) != 1) {
-+                      dev_err(&client->dev, "i2c transfer failed\n");
-+                      return -EIO;
-+              }
-+      } else {
-+              if (i2c_transfer(client->adapter, msg, 2) != 2) {
-+                      dev_err(&client->dev, "i2c transfer failed\n");
-+                      return -EIO;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+static int ili210x_read(struct i2c_client *client, void *buf, size_t len)
-+{
-+      struct i2c_msg msg = {
-+              .addr   = client->addr,
-+              .flags  = I2C_M_RD,
-+              .len    = len,
-+              .buf    = buf,
-+      };
-+
-+      if (i2c_transfer(client->adapter, &msg, 1) != 1) {
-               dev_err(&client->dev, "i2c transfer failed\n");
-               return -EIO;
-       }
-@@ -75,42 +101,72 @@ static int ili210x_read_reg(struct i2c_c
-       return 0;
- }
--static void ili210x_report_events(struct input_dev *input,
--                                const struct touchdata *touchdata)
-+static bool ili210x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
-+                                      unsigned int finger,
-+                                      unsigned int *x, unsigned int *y)
- {
--      int i;
--      bool touch;
--      unsigned int x, y;
--      const struct finger *finger;
-+      if (finger >= ILI210X_TOUCHES)
-+              return false;
--      for (i = 0; i < MAX_TOUCHES; i++) {
--              input_mt_slot(input, i);
-+      if (touchdata[0] & BIT(finger))
-+              return false;
--              finger = &touchdata->finger[i];
-+      *x = get_unaligned_be16(touchdata + 1 + (finger * 4) + 0);
-+      *y = get_unaligned_be16(touchdata + 1 + (finger * 4) + 2);
--              touch = touchdata->status & (1 << i);
--              input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
--              if (touch) {
--                      x = finger->x_low | (finger->x_high << 8);
--                      y = finger->y_low | (finger->y_high << 8);
-+      return true;
-+}
-+
-+static bool ili251x_touchdata_to_coords(struct ili210x *priv, u8 *touchdata,
-+                                      unsigned int finger,
-+                                      unsigned int *x, unsigned int *y)
-+{
-+      if (finger >= ILI251X_TOUCHES)
-+              return false;
-+
-+      *x = get_unaligned_be16(touchdata + 1 + (finger * 5) + 0);
-+      if (!(*x & BIT(15)))    /* Touch indication */
-+              return false;
-+
-+      *x &= 0x3fff;
-+      *y = get_unaligned_be16(touchdata + 1 + (finger * 5) + 2);
-+
-+      return true;
-+}
-+
-+static bool ili210x_report_events(struct ili210x *priv, u8 *touchdata)
-+{
-+      struct input_dev *input = priv->input;
-+      int i;
-+      bool contact = false, touch = false;
-+      unsigned int x = 0, y = 0;
--                      input_report_abs(input, ABS_MT_POSITION_X, x);
--                      input_report_abs(input, ABS_MT_POSITION_Y, y);
-+      for (i = 0; i < priv->max_touches; i++) {
-+              if (priv->model == MODEL_ILI210X) {
-+                      touch = ili210x_touchdata_to_coords(priv, touchdata,
-+                                                          i, &x, &y);
-+              } else if (priv->model == MODEL_ILI251X) {
-+                      touch = ili251x_touchdata_to_coords(priv, touchdata,
-+                                                          i, &x, &y);
-+                      if (touch)
-+                              contact = true;
-               }
-+
-+              input_mt_slot(input, i);
-+              input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
-+              if (!touch)
-+                      continue;
-+              touchscreen_report_pos(input, &priv->prop, x, y,
-+                                     true);
-       }
-       input_mt_report_pointer_emulation(input, false);
-       input_sync(input);
--}
--static bool get_pendown_state(const struct ili210x *priv)
--{
--      bool state = false;
--
--      if (priv->get_pendown_state)
--              state = priv->get_pendown_state();
-+      if (priv->model == MODEL_ILI210X)
-+              contact = touchdata[0] & 0xf3;
--      return state;
-+      return contact;
- }
- static void ili210x_work(struct work_struct *work)
-@@ -118,20 +174,29 @@ static void ili210x_work(struct work_str
-       struct ili210x *priv = container_of(work, struct ili210x,
-                                           dwork.work);
-       struct i2c_client *client = priv->client;
--      struct touchdata touchdata;
--      int error;
-+      u8 touchdata[64] = { 0 };
-+      bool touch;
-+      int error = -EINVAL;
-+
-+      if (priv->model == MODEL_ILI210X) {
-+              error = ili210x_read_reg(client, REG_TOUCHDATA,
-+                                       touchdata, sizeof(touchdata));
-+      } else if (priv->model == MODEL_ILI251X) {
-+              error = ili210x_read_reg(client, REG_TOUCHDATA,
-+                                       touchdata, 31);
-+              if (!error && touchdata[0] == 2)
-+                      error = ili210x_read(client, &touchdata[31], 20);
-+      }
--      error = ili210x_read_reg(client, REG_TOUCHDATA,
--                               &touchdata, sizeof(touchdata));
-       if (error) {
-               dev_err(&client->dev,
-                       "Unable to get touchdata, err = %d\n", error);
-               return;
-       }
--      ili210x_report_events(priv->input, &touchdata);
-+      touch = ili210x_report_events(priv, touchdata);
--      if ((touchdata.status & 0xf3) || get_pendown_state(priv))
-+      if (touch)
-               schedule_delayed_work(&priv->dwork,
-                                     msecs_to_jiffies(priv->poll_period));
- }
-@@ -180,30 +245,76 @@ static const struct attribute_group ili2
-       .attrs = ili210x_attributes,
- };
-+static void ili210x_power_down(void *data)
-+{
-+      struct gpio_desc *reset_gpio = data;
-+
-+      gpiod_set_value_cansleep(reset_gpio, 1);
-+}
-+
-+static void ili210x_cancel_work(void *data)
-+{
-+      struct ili210x *priv = data;
-+
-+      cancel_delayed_work_sync(&priv->dwork);
-+}
-+
- static int ili210x_i2c_probe(struct i2c_client *client,
-                                      const struct i2c_device_id *id)
- {
-       struct device *dev = &client->dev;
--      const struct ili210x_platform_data *pdata = dev_get_platdata(dev);
-       struct ili210x *priv;
-+      struct gpio_desc *reset_gpio;
-       struct input_dev *input;
--      struct panel_info panel;
-       struct firmware_version firmware;
--      int xmax, ymax;
-+      enum ili2xxx_model model;
-       int error;
--      dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
-+      model = (enum ili2xxx_model)id->driver_data;
--      if (!pdata) {
--              dev_err(dev, "No platform data!\n");
--              return -EINVAL;
--      }
-+      dev_dbg(dev, "Probing for ILI210X I2C Touschreen driver");
-       if (client->irq <= 0) {
-               dev_err(dev, "No IRQ!\n");
-               return -EINVAL;
-       }
-+      reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
-+      if (IS_ERR(reset_gpio))
-+              return PTR_ERR(reset_gpio);
-+
-+      if (reset_gpio) {
-+              error = devm_add_action_or_reset(dev, ili210x_power_down,
-+                                               reset_gpio);
-+              if (error)
-+                      return error;
-+
-+              usleep_range(50, 100);
-+              gpiod_set_value_cansleep(reset_gpio, 0);
-+              msleep(100);
-+      }
-+
-+      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+      if (!priv)
-+              return -ENOMEM;
-+
-+      input = devm_input_allocate_device(dev);
-+      if (!input)
-+              return -ENOMEM;
-+
-+      priv->client = client;
-+      priv->input = input;
-+      priv->poll_period = DEFAULT_POLL_PERIOD;
-+      INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
-+      priv->reset_gpio = reset_gpio;
-+      priv->model = model;
-+      if (model == MODEL_ILI210X)
-+              priv->max_touches = ILI210X_TOUCHES;
-+      if (model == MODEL_ILI251X)
-+              priv->max_touches = ILI251X_TOUCHES;
-+
-+      i2c_set_clientdata(client, priv);
-+
-       /* Get firmware version */
-       error = ili210x_read_reg(client, REG_FIRMWARE_VERSION,
-                                &firmware, sizeof(firmware));
-@@ -213,70 +324,40 @@ static int ili210x_i2c_probe(struct i2c_
-               return error;
-       }
--      /* get panel info */
--      error = ili210x_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));
--      if (error) {
--              dev_err(dev, "Failed to get panel information, err: %d\n",
--                      error);
--              return error;
--      }
--
--      xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);
--      ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);
--
--      priv = kzalloc(sizeof(*priv), GFP_KERNEL);
--      input = input_allocate_device();
--      if (!priv || !input) {
--              error = -ENOMEM;
--              goto err_free_mem;
--      }
--
--      priv->client = client;
--      priv->input = input;
--      priv->get_pendown_state = pdata->get_pendown_state;
--      priv->poll_period = pdata->poll_period ? : DEFAULT_POLL_PERIOD;
--      INIT_DELAYED_WORK(&priv->dwork, ili210x_work);
--
-       /* Setup input device */
-       input->name = "ILI210x Touchscreen";
-       input->id.bustype = BUS_I2C;
-       input->dev.parent = dev;
--      __set_bit(EV_SYN, input->evbit);
--      __set_bit(EV_KEY, input->evbit);
--      __set_bit(EV_ABS, input->evbit);
--      __set_bit(BTN_TOUCH, input->keybit);
--
--      /* Single touch */
--      input_set_abs_params(input, ABS_X, 0, xmax, 0, 0);
--      input_set_abs_params(input, ABS_Y, 0, ymax, 0, 0);
--
-       /* Multi touch */
--      input_mt_init_slots(input, MAX_TOUCHES, 0);
--      input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);
--      input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);
-+      input_set_abs_params(input, ABS_MT_POSITION_X, 0, 0xffff, 0, 0);
-+      input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 0xffff, 0, 0);
-+      touchscreen_parse_properties(input, true, &priv->prop);
-+      input_mt_init_slots(input, priv->max_touches, INPUT_MT_DIRECT);
--      i2c_set_clientdata(client, priv);
-+      error = devm_add_action(dev, ili210x_cancel_work, priv);
-+      if (error)
-+              return error;
--      error = request_irq(client->irq, ili210x_irq, pdata->irq_flags,
--                          client->name, priv);
-+      error = devm_request_irq(dev, client->irq, ili210x_irq, 0,
-+                               client->name, priv);
-       if (error) {
-               dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n",
-                       error);
--              goto err_free_mem;
-+              return error;
-       }
--      error = sysfs_create_group(&dev->kobj, &ili210x_attr_group);
-+      error = devm_device_add_group(dev, &ili210x_attr_group);
-       if (error) {
-               dev_err(dev, "Unable to create sysfs attributes, err: %d\n",
-                       error);
--              goto err_free_irq;
-+              return error;
-       }
-       error = input_register_device(priv->input);
-       if (error) {
-               dev_err(dev, "Cannot register input device, err: %d\n", error);
--              goto err_remove_sysfs;
-+              return error;
-       }
-       device_init_wakeup(dev, 1);
-@@ -286,28 +367,6 @@ static int ili210x_i2c_probe(struct i2c_
-               client->irq, firmware.id, firmware.major, firmware.minor);
-       return 0;
--
--err_remove_sysfs:
--      sysfs_remove_group(&dev->kobj, &ili210x_attr_group);
--err_free_irq:
--      free_irq(client->irq, priv);
--err_free_mem:
--      input_free_device(input);
--      kfree(priv);
--      return error;
--}
--
--static int ili210x_i2c_remove(struct i2c_client *client)
--{
--      struct ili210x *priv = i2c_get_clientdata(client);
--
--      sysfs_remove_group(&client->dev.kobj, &ili210x_attr_group);
--      free_irq(priv->client->irq, priv);
--      cancel_delayed_work_sync(&priv->dwork);
--      input_unregister_device(priv->input);
--      kfree(priv);
--
--      return 0;
- }
- static int __maybe_unused ili210x_i2c_suspend(struct device *dev)
-@@ -334,19 +393,27 @@ static SIMPLE_DEV_PM_OPS(ili210x_i2c_pm,
-                        ili210x_i2c_suspend, ili210x_i2c_resume);
- static const struct i2c_device_id ili210x_i2c_id[] = {
--      { "ili210x", 0 },
-+      { "ili210x", MODEL_ILI210X },
-+      { "ili251x", MODEL_ILI251X },
-       { }
- };
- MODULE_DEVICE_TABLE(i2c, ili210x_i2c_id);
-+static const struct of_device_id ili210x_dt_ids[] = {
-+      { .compatible = "ilitek,ili210x", .data = (void *)MODEL_ILI210X },
-+      { .compatible = "ilitek,ili251x", .data = (void *)MODEL_ILI251X },
-+      { },
-+};
-+MODULE_DEVICE_TABLE(of, ili210x_dt_ids);
-+
- static struct i2c_driver ili210x_ts_driver = {
-       .driver = {
-               .name = "ili210x_i2c",
-               .pm = &ili210x_i2c_pm,
-+              .of_match_table = ili210x_dt_ids,
-       },
-       .id_table = ili210x_i2c_id,
-       .probe = ili210x_i2c_probe,
--      .remove = ili210x_i2c_remove,
- };
- module_i2c_driver(ili210x_ts_driver);