aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-4.19/950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-4.19/950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch')
-rw-r--r--target/linux/bcm27xx/patches-4.19/950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch490
1 files changed, 0 insertions, 490 deletions
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
index 84c99ffa5a..0000000000
--- a/target/linux/bcm27xx/patches-4.19/950-0362-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch
+++ /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);