diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.19/950-0364-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.19/950-0364-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch | 490 |
1 files changed, 0 insertions, 490 deletions
diff --git a/target/linux/brcm2708/patches-4.19/950-0364-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch b/target/linux/brcm2708/patches-4.19/950-0364-Input-ili210x-fetch-touchscreen-geometry-from-DT.patch deleted file mode 100644 index 84c99ffa5a..0000000000 --- a/target/linux/brcm2708/patches-4.19/950-0364-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); |