diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.14/950-0162-Input-add-I2C-attached-EETI-EXC3000-multi-touch-driv.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.14/950-0162-Input-add-I2C-attached-EETI-EXC3000-multi-touch-driv.patch | 320 |
1 files changed, 0 insertions, 320 deletions
diff --git a/target/linux/brcm2708/patches-4.14/950-0162-Input-add-I2C-attached-EETI-EXC3000-multi-touch-driv.patch b/target/linux/brcm2708/patches-4.14/950-0162-Input-add-I2C-attached-EETI-EXC3000-multi-touch-driv.patch deleted file mode 100644 index 033039e5cb..0000000000 --- a/target/linux/brcm2708/patches-4.14/950-0162-Input-add-I2C-attached-EETI-EXC3000-multi-touch-driv.patch +++ /dev/null @@ -1,320 +0,0 @@ -From 99aaee7d1fde86bd2119d84e90435d89d6d3af07 Mon Sep 17 00:00:00 2001 -From: Ahmet Inan <inan@distec.de> -Date: Sat, 14 Oct 2017 10:10:53 -0700 -Subject: [PATCH 162/454] Input: add I2C attached EETI EXC3000 multi touch - driver - -commit 7e577a17f2eefeef32f1106ebf91e7cd143ba654 upstream. -beware: code adapted to use the old timer API. - -The 3000 series have a new protocol which allows to report up to 5 points -in a single 66 byte frame. One must always read in 66 byte frames. -To support up to 10 points, two consecutive frames need to be read: -The first frame says how many points until sync. -The second frame must say zero points or both frames must be discarded. - -To be able to work with the higher 400KHz I2C bus rate, one must -successfully send a special package prior _each_ read or the controller -will refuse to cooperate. - -This is a minimal implementation based on egalax_i2c.c (which can be found -on the internet) and egalax_ts.c but without the vendor interface and no -power management support. - -Signed-off-by: Ahmet Inan <inan@distec.de> -Acked-by: Rob Herring <robh@kernel.org> -Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> ---- - .../bindings/input/touchscreen/exc3000.txt | 27 +++ - drivers/input/touchscreen/Kconfig | 10 + - drivers/input/touchscreen/Makefile | 1 + - drivers/input/touchscreen/exc3000.c | 223 ++++++++++++++++++ - 4 files changed, 261 insertions(+) - create mode 100644 Documentation/devicetree/bindings/input/touchscreen/exc3000.txt - create mode 100644 drivers/input/touchscreen/exc3000.c - ---- /dev/null -+++ b/Documentation/devicetree/bindings/input/touchscreen/exc3000.txt -@@ -0,0 +1,27 @@ -+* EETI EXC3000 Multiple Touch Controller -+ -+Required properties: -+- compatible: must be "eeti,exc3000" -+- reg: i2c slave address -+- interrupt-parent: the phandle for the interrupt controller -+- interrupts: touch controller interrupt -+- touchscreen-size-x: See touchscreen.txt -+- touchscreen-size-y: See touchscreen.txt -+ -+Optional properties: -+- touchscreen-inverted-x: See touchscreen.txt -+- touchscreen-inverted-y: See touchscreen.txt -+- touchscreen-swapped-x-y: See touchscreen.txt -+ -+Example: -+ -+ touchscreen@2a { -+ compatible = "eeti,exc3000"; -+ reg = <0x2a>; -+ interrupt-parent = <&gpio1>; -+ interrupts = <9 IRQ_TYPE_LEVEL_LOW>; -+ touchscreen-size-x = <4096>; -+ touchscreen-size-y = <4096>; -+ touchscreen-inverted-x; -+ touchscreen-swapped-x-y; -+ }; ---- a/drivers/input/touchscreen/Kconfig -+++ b/drivers/input/touchscreen/Kconfig -@@ -316,6 +316,16 @@ config TOUCHSCREEN_EGALAX_SERIAL - To compile this driver as a module, choose M here: the - module will be called egalax_ts_serial. - -+config TOUCHSCREEN_EXC3000 -+ tristate "EETI EXC3000 multi-touch panel support" -+ depends on I2C -+ help -+ Say Y here to enable support for I2C connected EETI -+ EXC3000 multi-touch panels. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called exc3000. -+ - config TOUCHSCREEN_FUJITSU - tristate "Fujitsu serial touchscreen" - select SERIO ---- a/drivers/input/touchscreen/Makefile -+++ b/drivers/input/touchscreen/Makefile -@@ -39,6 +39,7 @@ obj-$(CONFIG_TOUCHSCREEN_ELAN) += elant - obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o - obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o - obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o -+obj-$(CONFIG_TOUCHSCREEN_EXC3000) += exc3000.o - obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o - obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o - obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o ---- /dev/null -+++ b/drivers/input/touchscreen/exc3000.c -@@ -0,0 +1,223 @@ -+/* -+ * Driver for I2C connected EETI EXC3000 multiple touch controller -+ * -+ * Copyright (C) 2017 Ahmet Inan <inan@distec.de> -+ * -+ * minimal implementation based on egalax_ts.c and egalax_i2c.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/bitops.h> -+#include <linux/device.h> -+#include <linux/i2c.h> -+#include <linux/input.h> -+#include <linux/input/mt.h> -+#include <linux/input/touchscreen.h> -+#include <linux/interrupt.h> -+#include <linux/module.h> -+#include <linux/of.h> -+#include <linux/timer.h> -+#include <asm/unaligned.h> -+ -+#define EXC3000_NUM_SLOTS 10 -+#define EXC3000_SLOTS_PER_FRAME 5 -+#define EXC3000_LEN_FRAME 66 -+#define EXC3000_LEN_POINT 10 -+#define EXC3000_MT_EVENT 6 -+#define EXC3000_TIMEOUT_MS 100 -+ -+struct exc3000_data { -+ struct i2c_client *client; -+ struct input_dev *input; -+ struct touchscreen_properties prop; -+ struct timer_list timer; -+ u8 buf[2 * EXC3000_LEN_FRAME]; -+}; -+ -+static void exc3000_report_slots(struct input_dev *input, -+ struct touchscreen_properties *prop, -+ const u8 *buf, int num) -+{ -+ for (; num--; buf += EXC3000_LEN_POINT) { -+ if (buf[0] & BIT(0)) { -+ input_mt_slot(input, buf[1]); -+ input_mt_report_slot_state(input, MT_TOOL_FINGER, true); -+ touchscreen_report_pos(input, prop, -+ get_unaligned_le16(buf + 2), -+ get_unaligned_le16(buf + 4), -+ true); -+ } -+ } -+} -+ -+static void exc3000_timer(unsigned long d) -+{ -+ struct exc3000_data *data = (void *)d; -+ -+ input_mt_sync_frame(data->input); -+ input_sync(data->input); -+} -+ -+static int exc3000_read_frame(struct i2c_client *client, u8 *buf) -+{ -+ int ret; -+ -+ ret = i2c_master_send(client, "'", 2); -+ if (ret < 0) -+ return ret; -+ -+ if (ret != 2) -+ return -EIO; -+ -+ ret = i2c_master_recv(client, buf, EXC3000_LEN_FRAME); -+ if (ret < 0) -+ return ret; -+ -+ if (ret != EXC3000_LEN_FRAME) -+ return -EIO; -+ -+ if (get_unaligned_le16(buf) != EXC3000_LEN_FRAME || -+ buf[2] != EXC3000_MT_EVENT) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static int exc3000_read_data(struct i2c_client *client, -+ u8 *buf, int *n_slots) -+{ -+ int error; -+ -+ error = exc3000_read_frame(client, buf); -+ if (error) -+ return error; -+ -+ *n_slots = buf[3]; -+ if (!*n_slots || *n_slots > EXC3000_NUM_SLOTS) -+ return -EINVAL; -+ -+ if (*n_slots > EXC3000_SLOTS_PER_FRAME) { -+ /* Read 2nd frame to get the rest of the contacts. */ -+ error = exc3000_read_frame(client, buf + EXC3000_LEN_FRAME); -+ if (error) -+ return error; -+ -+ /* 2nd chunk must have number of contacts set to 0. */ -+ if (buf[EXC3000_LEN_FRAME + 3] != 0) -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static irqreturn_t exc3000_interrupt(int irq, void *dev_id) -+{ -+ struct exc3000_data *data = dev_id; -+ struct input_dev *input = data->input; -+ u8 *buf = data->buf; -+ int slots, total_slots; -+ int error; -+ -+ error = exc3000_read_data(data->client, buf, &total_slots); -+ if (error) { -+ /* Schedule a timer to release "stuck" contacts */ -+ mod_timer(&data->timer, -+ jiffies + msecs_to_jiffies(EXC3000_TIMEOUT_MS)); -+ goto out; -+ } -+ -+ /* -+ * We read full state successfully, no contacts will be "stuck". -+ */ -+ del_timer_sync(&data->timer); -+ -+ while (total_slots > 0) { -+ slots = min(total_slots, EXC3000_SLOTS_PER_FRAME); -+ exc3000_report_slots(input, &data->prop, buf + 4, slots); -+ total_slots -= slots; -+ buf += EXC3000_LEN_FRAME; -+ } -+ -+ input_mt_sync_frame(input); -+ input_sync(input); -+ -+out: -+ return IRQ_HANDLED; -+} -+ -+static int exc3000_probe(struct i2c_client *client, -+ const struct i2c_device_id *id) -+{ -+ struct exc3000_data *data; -+ struct input_dev *input; -+ int error; -+ -+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); -+ if (!data) -+ return -ENOMEM; -+ -+ data->client = client; -+ setup_timer(&data->timer, exc3000_timer, (unsigned long)data); -+ -+ input = devm_input_allocate_device(&client->dev); -+ if (!input) -+ return -ENOMEM; -+ -+ data->input = input; -+ -+ input->name = "EETI EXC3000 Touch Screen"; -+ input->id.bustype = BUS_I2C; -+ -+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, 4095, 0, 0); -+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 4095, 0, 0); -+ touchscreen_parse_properties(input, true, &data->prop); -+ -+ error = input_mt_init_slots(input, EXC3000_NUM_SLOTS, -+ INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); -+ if (error) -+ return error; -+ -+ error = input_register_device(input); -+ if (error) -+ return error; -+ -+ error = devm_request_threaded_irq(&client->dev, client->irq, -+ NULL, exc3000_interrupt, IRQF_ONESHOT, -+ client->name, data); -+ if (error) -+ return error; -+ -+ return 0; -+} -+ -+static const struct i2c_device_id exc3000_id[] = { -+ { "exc3000", 0 }, -+ { } -+}; -+MODULE_DEVICE_TABLE(i2c, exc3000_id); -+ -+#ifdef CONFIG_OF -+static const struct of_device_id exc3000_of_match[] = { -+ { .compatible = "eeti,exc3000" }, -+ { } -+}; -+MODULE_DEVICE_TABLE(of, exc3000_of_match); -+#endif -+ -+static struct i2c_driver exc3000_driver = { -+ .driver = { -+ .name = "exc3000", -+ .of_match_table = of_match_ptr(exc3000_of_match), -+ }, -+ .id_table = exc3000_id, -+ .probe = exc3000_probe, -+}; -+ -+module_i2c_driver(exc3000_driver); -+ -+MODULE_AUTHOR("Ahmet Inan <inan@distec.de>"); -+MODULE_DESCRIPTION("I2C connected EETI EXC3000 multiple touch controller driver"); -+MODULE_LICENSE("GPL v2"); |