diff for duplicates of <220181476210841@web5j.yandex.ru> diff --git a/a/1.txt b/N1/1.txt index 5ed7f14..ec11dce 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,20 +1,20 @@ -12.10.2016, 01:40, "Dmitry Torokhov" <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>: +12.10.2016, 01:40, "Dmitry Torokhov" <dmitry.torokhov@gmail.com>: > Hi Icenowy, > > On Tue, Oct 11, 2016 at 08:33:57AM +0800, Icenowy Zheng wrote: ->> This driver adds support for Ilitek ili2139 touch IC, which is used in ->> several Colorfly tablets (for example, Colorfly E708 Q1, which is an ->> Allwinner A31s tablet with mainline kernel support). +>> ?This driver adds support for Ilitek ili2139 touch IC, which is used in +>> ?several Colorfly tablets (for example, Colorfly E708 Q1, which is an +>> ?Allwinner A31s tablet with mainline kernel support). >> ->> Theortically it may support more Ilitek touch ICs, however, only ili2139 ->> is used in any mainlined device. +>> ?Theortically it may support more Ilitek touch ICs, however, only ili2139 +>> ?is used in any mainlined device. >> ->> It supports device tree enumeration, with screen resolution and axis ->> quirks configurable. +>> ?It supports device tree enumeration, with screen resolution and axis +>> ?quirks configurable. >> ->> Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org> +>> ?Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz> > > Please extend ili210x.c instead of adding brand new driver, they look > very similar. @@ -30,383 +30,378 @@ the old protocol (but I have no chips to test it), and drop the old ili210x. (This driver is capable of dt probing, and uses devm_ functions) > ->> --- ->> drivers/input/touchscreen/Kconfig | 14 ++ ->> drivers/input/touchscreen/Makefile | 1 + ->> drivers/input/touchscreen/ili2139.c | 320 ++++++++++++++++++++++++++++++++++++ ->> 3 files changed, 335 insertions(+) ->> create mode 100644 drivers/input/touchscreen/ili2139.c +>> ?--- +>> ??drivers/input/touchscreen/Kconfig | 14 ++ +>> ??drivers/input/touchscreen/Makefile | 1 + +>> ??drivers/input/touchscreen/ili2139.c | 320 ++++++++++++++++++++++++++++++++++++ +>> ??3 files changed, 335 insertions(+) +>> ??create mode 100644 drivers/input/touchscreen/ili2139.c >> ->> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig ->> index 5079813..bb4d9d2 100644 ->> --- a/drivers/input/touchscreen/Kconfig ->> +++ b/drivers/input/touchscreen/Kconfig ->> @@ -348,6 +348,20 @@ config TOUCHSCREEN_ILI210X ->> To compile this driver as a module, choose M here: the ->> module will be called ili210x. +>> ?diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +>> ?index 5079813..bb4d9d2 100644 +>> ?--- a/drivers/input/touchscreen/Kconfig +>> ?+++ b/drivers/input/touchscreen/Kconfig +>> ?@@ -348,6 +348,20 @@ config TOUCHSCREEN_ILI210X +>> ????????????To compile this driver as a module, choose M here: the +>> ????????????module will be called ili210x. >> ->> +config TOUCHSCREEN_ILI2139 ->> + tristate "Ilitek ILI2139 based touchscreen" ->> + depends on I2C ->> + depends on OF ->> + help ->> + Say Y here if you have a ILI2139 based touchscreen ->> + controller. Such kind of chipsets can be found in several ->> + Colorfly tablets. ->> + ->> + If unsure, say N. ->> + ->> + To compile this driver as a module, choose M here; the ->> + module will be called ili2139. ->> + ->> config TOUCHSCREEN_IPROC ->> tristate "IPROC touch panel driver support" ->> depends on ARCH_BCM_IPROC || COMPILE_TEST ->> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile ->> index 81b8645..930b5e2 100644 ->> --- a/drivers/input/touchscreen/Makefile ->> +++ b/drivers/input/touchscreen/Makefile ->> @@ -40,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o ->> obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o ->> obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o ->> obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o ->> +obj-$(CONFIG_TOUCHSCREEN_ILI2139) += ili2139.o ->> obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o ->> obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o ->> obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o ->> diff --git a/drivers/input/touchscreen/ili2139.c b/drivers/input/touchscreen/ili2139.c ->> new file mode 100644 ->> index 0000000..65c2dea ->> --- /dev/null ->> +++ b/drivers/input/touchscreen/ili2139.c ->> @@ -0,0 +1,320 @@ ->> +/* ------------------------------------------------------------------------- ->> + * Copyright (C) 2016, Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org> ->> + * ->> + * Derived from: ->> + * ili210x.c ->> + * Copyright (C) Olivier Sobrie <olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org> ->> + * ->> + * This program is free software; you can redistribute it and/or modify ->> + * it under the terms of the GNU General Public License as published by ->> + * the Free Software Foundation; either version 2 of the License, or ->> + * (at your option) any later version. ->> + * ->> + * This program is distributed in the hope that it will be useful, ->> + * but WITHOUT ANY WARRANTY; without even the implied warranty of ->> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ->> + * GNU General Public License for more details. ->> + * ------------------------------------------------------------------------- ->> + */ ->> + ->> +#include <linux/module.h> ->> +#include <linux/i2c.h> ->> +#include <linux/interrupt.h> ->> +#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> ->> + ->> +#define DEFAULT_POLL_PERIOD 20 ->> + ->> +#define MAX_TOUCHES 10 ->> +#define COMPATIBLE_TOUCHES 2 ->> + ->> +/* Touchscreen commands */ ->> +#define REG_TOUCHDATA 0x10 ->> +#define REG_TOUCHSUBDATA 0x11 ->> +#define REG_PANEL_INFO 0x20 ->> +#define REG_FIRMWARE_VERSION 0x40 ->> +#define REG_PROTO_VERSION 0x42 ->> + ->> +#define SUBDATA_STATUS_TOUCH_POINT 0x80 ->> +#define SUBDATA_STATUS_RELEASE_POINT 0x00 ->> + ->> +struct finger { ->> + u8 x_low; ->> + u8 x_high; ->> + u8 y_low; ->> + u8 y_high; ->> +} __packed; ->> + ->> +struct touchdata { ->> + u8 length; ->> + struct finger finger[COMPATIBLE_TOUCHES]; ->> +} __packed; ->> + ->> +struct touch_subdata { ->> + u8 status; ->> + struct finger finger; ->> +} __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; ->> + ->> +struct ili2139 { ->> + struct i2c_client *client; ->> + struct input_dev *input; ->> + unsigned int poll_period; ->> + struct delayed_work dwork; ->> + struct touchscreen_properties prop; ->> + int slots[MAX_TOUCHES]; ->> + int ids[MAX_TOUCHES]; ->> + struct input_mt_pos pos[MAX_TOUCHES]; ->> +}; ->> + ->> +static int ili2139_read_reg(struct i2c_client *client, u8 reg, void *buf, ->> + size_t len) ->> +{ ->> + struct i2c_msg msg[2] = { ->> + { ->> + .addr = client->addr, ->> + .flags = 0, ->> + .len = 1, ->> + .buf = ®, ->> + }, ->> + { ->> + .addr = client->addr, ->> + .flags = I2C_M_RD, ->> + .len = len, ->> + .buf = buf, ->> + } ->> + }; ->> + ->> + if (i2c_transfer(client->adapter, msg, 2) != 2) { ->> + dev_err(&client->dev, "i2c transfer failed\n"); ->> + return -EIO; ->> + } ->> + ->> + return 0; ->> +} ->> + ->> +static void ili2139_work(struct work_struct *work) ->> +{ ->> + int id; ->> + struct ili2139 *priv = container_of(work, struct ili2139, ->> + dwork.work); ->> + struct i2c_client *client = priv->client; ->> + struct touchdata touchdata; ->> + struct touch_subdata subdata; ->> + int error; ->> + ->> + error = ili2139_read_reg(client, REG_TOUCHDATA, ->> + &touchdata, sizeof(touchdata)); ->> + if (error) { ->> + dev_err(&client->dev, ->> + "Unable to get touchdata, err = %d\n", error); ->> + return; ->> + } ->> + ->> + for (id = 0; id < touchdata.length; id++) { ->> + error = ili2139_read_reg(client, REG_TOUCHSUBDATA, &subdata, ->> + sizeof(subdata)); ->> + if (error) { ->> + dev_err(&client->dev, ->> + "Unable to get touch subdata, err = %d\n", ->> + error); ->> + return; ->> + } ->> + ->> + priv->ids[id] = subdata.status & 0x3F; ->> + ->> + /* The sequence changed in the v2 subdata protocol. */ ->> + touchscreen_set_mt_pos(&priv->pos[id], &priv->prop, ->> + (subdata.finger.x_high | (subdata.finger.x_low << 8)), ->> + (subdata.finger.y_high | (subdata.finger.y_low << 8))); ->> + } ->> + ->> + input_mt_assign_slots(priv->input, priv->slots, priv->pos, ->> + touchdata.length, 0); ->> + ->> + for (id = 0; id < touchdata.length; id++) { ->> + input_mt_slot(priv->input, priv->slots[id]); ->> + input_mt_report_slot_state(priv->input, MT_TOOL_FINGER, ->> + subdata.status & ->> + SUBDATA_STATUS_TOUCH_POINT); ->> + input_report_abs(priv->input, ABS_MT_POSITION_X, ->> + priv->pos[id].x); ->> + input_report_abs(priv->input, ABS_MT_POSITION_Y, ->> + priv->pos[id].y); ->> + } ->> + ->> + input_mt_sync_frame(priv->input); ->> + input_sync(priv->input); ->> + ->> + schedule_delayed_work(&priv->dwork, ->> + msecs_to_jiffies(priv->poll_period)); ->> +} ->> + ->> +static irqreturn_t ili2139_irq(int irq, void *irq_data) ->> +{ ->> + struct ili2139 *priv = irq_data; ->> + ->> + schedule_delayed_work(&priv->dwork, 0); ->> + ->> + return IRQ_HANDLED; ->> +} ->> + ->> +static int ili2139_i2c_probe(struct i2c_client *client, ->> + const struct i2c_device_id *id) ->> +{ ->> + struct device *dev = &client->dev; ->> + struct ili2139 *priv; ->> + struct input_dev *input; ->> + struct panel_info panel; ->> + struct firmware_version firmware; ->> + int xmax, ymax; ->> + int error; ->> + ->> + dev_dbg(dev, "Probing for ILI2139 I2C Touschreen driver"); ->> + ->> + if (client->irq <= 0) { ->> + dev_err(dev, "No IRQ!\n"); ->> + return -ENODEV; ->> + } ->> + ->> + /* Get firmware version */ ->> + error = ili2139_read_reg(client, REG_FIRMWARE_VERSION, ->> + &firmware, sizeof(firmware)); ->> + if (error) { ->> + dev_err(dev, "Failed to get firmware version, err: %d\n", ->> + error); ->> + return error; ->> + } ->> + ->> + /* get panel info */ ->> + error = ili2139_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 = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); ->> + input = devm_input_allocate_device(dev); ->> + if (!priv || !input) ->> + return -ENOMEM; ->> + ->> + priv->client = client; ->> + priv->input = input; ->> + priv->poll_period = DEFAULT_POLL_PERIOD; ->> + INIT_DELAYED_WORK(&priv->dwork, ili2139_work); ->> + ->> + /* Setup input device */ ->> + input->name = "ILI2139 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); ->> + ->> + /* Multi touch */ ->> + input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_DIRECT | ->> + INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK); ->> + 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); ->> + ->> + touchscreen_parse_properties(input, true, &priv->prop); ->> + ->> + input_set_drvdata(input, priv); ->> + i2c_set_clientdata(client, priv); ->> + ->> + error = devm_request_irq(dev, client->irq, ili2139_irq, ->> + IRQF_TRIGGER_FALLING, client->name, priv); ->> + if (error) { ->> + dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", ->> + error); ->> + return error; ->> + } ->> + ->> + error = input_register_device(priv->input); ->> + if (error) { ->> + dev_err(dev, "Cannot register input device, err: %d\n", error); ->> + return error; ->> + } ->> + ->> + device_init_wakeup(&client->dev, 1); ->> + ->> + dev_dbg(dev, ->> + "ILI2139 initialized (IRQ: %d), firmware version %d.%d.%d", ->> + client->irq, firmware.id, firmware.major, firmware.minor); ->> + ->> + return 0; ->> +} ->> + ->> +static int ili2139_i2c_remove(struct i2c_client *client) ->> +{ ->> + struct ili2139 *priv = i2c_get_clientdata(client); ->> + ->> + cancel_delayed_work_sync(&priv->dwork); ->> + ->> + return 0; ->> +} ->> + ->> +static int __maybe_unused ili2139_i2c_suspend(struct device *dev) ->> +{ ->> + struct i2c_client *client = to_i2c_client(dev); ->> + ->> + if (device_may_wakeup(&client->dev)) ->> + enable_irq_wake(client->irq); ->> + ->> + return 0; ->> +} ->> + ->> +static int __maybe_unused ili2139_i2c_resume(struct device *dev) ->> +{ ->> + struct i2c_client *client = to_i2c_client(dev); ->> + ->> + if (device_may_wakeup(&client->dev)) ->> + disable_irq_wake(client->irq); ->> + ->> + return 0; ->> +} ->> + ->> +static SIMPLE_DEV_PM_OPS(ili2139_i2c_pm, ->> + ili2139_i2c_suspend, ili2139_i2c_resume); ->> + ->> +static const struct i2c_device_id ili2139_i2c_id[] = { ->> + { "ili2139", 0 }, ->> + { } ->> +}; ->> +MODULE_DEVICE_TABLE(i2c, ili2139_i2c_id); ->> + ->> +static struct i2c_driver ili2139_ts_driver = { ->> + .driver = { ->> + .name = "ili2139_i2c", ->> + .pm = &ili2139_i2c_pm, ->> + }, ->> + .id_table = ili2139_i2c_id, ->> + .probe = ili2139_i2c_probe, ->> + .remove = ili2139_i2c_remove, ->> +}; ->> + ->> +module_i2c_driver(ili2139_ts_driver); ->> + ->> +MODULE_AUTHOR("Olivier Sobrie <olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org>"); ->> +MODULE_DESCRIPTION("ILI2139 I2C Touchscreen Driver"); ->> +MODULE_LICENSE("GPL"); ->> -- ->> 2.10.1 +>> ?+config TOUCHSCREEN_ILI2139 +>> ?+ tristate "Ilitek ILI2139 based touchscreen" +>> ?+ depends on I2C +>> ?+ depends on OF +>> ?+ help +>> ?+ Say Y here if you have a ILI2139 based touchscreen +>> ?+ controller. Such kind of chipsets can be found in several +>> ?+ Colorfly tablets. +>> ?+ +>> ?+ If unsure, say N. +>> ?+ +>> ?+ To compile this driver as a module, choose M here; the +>> ?+ module will be called ili2139. +>> ?+ +>> ??config TOUCHSCREEN_IPROC +>> ??????????tristate "IPROC touch panel driver support" +>> ??????????depends on ARCH_BCM_IPROC || COMPILE_TEST +>> ?diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile +>> ?index 81b8645..930b5e2 100644 +>> ?--- a/drivers/input/touchscreen/Makefile +>> ?+++ b/drivers/input/touchscreen/Makefile +>> ?@@ -40,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o +>> ??obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o +>> ??obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o +>> ??obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o +>> ?+obj-$(CONFIG_TOUCHSCREEN_ILI2139) += ili2139.o +>> ??obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o +>> ??obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o +>> ??obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o +>> ?diff --git a/drivers/input/touchscreen/ili2139.c b/drivers/input/touchscreen/ili2139.c +>> ?new file mode 100644 +>> ?index 0000000..65c2dea +>> ?--- /dev/null +>> ?+++ b/drivers/input/touchscreen/ili2139.c +>> ?@@ -0,0 +1,320 @@ +>> ?+/* ------------------------------------------------------------------------- +>> ?+ * Copyright (C) 2016, Icenowy Zheng <icenowy@aosc.xyz> +>> ?+ * +>> ?+ * Derived from: +>> ?+ * ili210x.c +>> ?+ * Copyright (C) Olivier Sobrie <olivier@sobrie.be> +>> ?+ * +>> ?+ * This program is free software; you can redistribute it and/or modify +>> ?+ * it under the terms of the GNU General Public License as published by +>> ?+ * the Free Software Foundation; either version 2 of the License, or +>> ?+ * (at your option) any later version. +>> ?+ * +>> ?+ * This program is distributed in the hope that it will be useful, +>> ?+ * but WITHOUT ANY WARRANTY; without even the implied warranty of +>> ?+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +>> ?+ * GNU General Public License for more details. +>> ?+ * ------------------------------------------------------------------------- +>> ?+ */ +>> ?+ +>> ?+#include <linux/module.h> +>> ?+#include <linux/i2c.h> +>> ?+#include <linux/interrupt.h> +>> ?+#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> +>> ?+ +>> ?+#define DEFAULT_POLL_PERIOD 20 +>> ?+ +>> ?+#define MAX_TOUCHES 10 +>> ?+#define COMPATIBLE_TOUCHES 2 +>> ?+ +>> ?+/* Touchscreen commands */ +>> ?+#define REG_TOUCHDATA 0x10 +>> ?+#define REG_TOUCHSUBDATA 0x11 +>> ?+#define REG_PANEL_INFO 0x20 +>> ?+#define REG_FIRMWARE_VERSION 0x40 +>> ?+#define REG_PROTO_VERSION 0x42 +>> ?+ +>> ?+#define SUBDATA_STATUS_TOUCH_POINT 0x80 +>> ?+#define SUBDATA_STATUS_RELEASE_POINT 0x00 +>> ?+ +>> ?+struct finger { +>> ?+ u8 x_low; +>> ?+ u8 x_high; +>> ?+ u8 y_low; +>> ?+ u8 y_high; +>> ?+} __packed; +>> ?+ +>> ?+struct touchdata { +>> ?+ u8 length; +>> ?+ struct finger finger[COMPATIBLE_TOUCHES]; +>> ?+} __packed; +>> ?+ +>> ?+struct touch_subdata { +>> ?+ u8 status; +>> ?+ struct finger finger; +>> ?+} __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; +>> ?+ +>> ?+struct ili2139 { +>> ?+ struct i2c_client *client; +>> ?+ struct input_dev *input; +>> ?+ unsigned int poll_period; +>> ?+ struct delayed_work dwork; +>> ?+ struct touchscreen_properties prop; +>> ?+ int slots[MAX_TOUCHES]; +>> ?+ int ids[MAX_TOUCHES]; +>> ?+ struct input_mt_pos pos[MAX_TOUCHES]; +>> ?+}; +>> ?+ +>> ?+static int ili2139_read_reg(struct i2c_client *client, u8 reg, void *buf, +>> ?+ size_t len) +>> ?+{ +>> ?+ struct i2c_msg msg[2] = { +>> ?+ { +>> ?+ .addr = client->addr, +>> ?+ .flags = 0, +>> ?+ .len = 1, +>> ?+ .buf = ®, +>> ?+ }, +>> ?+ { +>> ?+ .addr = client->addr, +>> ?+ .flags = I2C_M_RD, +>> ?+ .len = len, +>> ?+ .buf = buf, +>> ?+ } +>> ?+ }; +>> ?+ +>> ?+ if (i2c_transfer(client->adapter, msg, 2) != 2) { +>> ?+ dev_err(&client->dev, "i2c transfer failed\n"); +>> ?+ return -EIO; +>> ?+ } +>> ?+ +>> ?+ return 0; +>> ?+} +>> ?+ +>> ?+static void ili2139_work(struct work_struct *work) +>> ?+{ +>> ?+ int id; +>> ?+ struct ili2139 *priv = container_of(work, struct ili2139, +>> ?+ dwork.work); +>> ?+ struct i2c_client *client = priv->client; +>> ?+ struct touchdata touchdata; +>> ?+ struct touch_subdata subdata; +>> ?+ int error; +>> ?+ +>> ?+ error = ili2139_read_reg(client, REG_TOUCHDATA, +>> ?+ &touchdata, sizeof(touchdata)); +>> ?+ if (error) { +>> ?+ dev_err(&client->dev, +>> ?+ "Unable to get touchdata, err = %d\n", error); +>> ?+ return; +>> ?+ } +>> ?+ +>> ?+ for (id = 0; id < touchdata.length; id++) { +>> ?+ error = ili2139_read_reg(client, REG_TOUCHSUBDATA, &subdata, +>> ?+ sizeof(subdata)); +>> ?+ if (error) { +>> ?+ dev_err(&client->dev, +>> ?+ "Unable to get touch subdata, err = %d\n", +>> ?+ error); +>> ?+ return; +>> ?+ } +>> ?+ +>> ?+ priv->ids[id] = subdata.status & 0x3F; +>> ?+ +>> ?+ /* The sequence changed in the v2 subdata protocol. */ +>> ?+ touchscreen_set_mt_pos(&priv->pos[id], &priv->prop, +>> ?+ (subdata.finger.x_high | (subdata.finger.x_low << 8)), +>> ?+ (subdata.finger.y_high | (subdata.finger.y_low << 8))); +>> ?+ } +>> ?+ +>> ?+ input_mt_assign_slots(priv->input, priv->slots, priv->pos, +>> ?+ touchdata.length, 0); +>> ?+ +>> ?+ for (id = 0; id < touchdata.length; id++) { +>> ?+ input_mt_slot(priv->input, priv->slots[id]); +>> ?+ input_mt_report_slot_state(priv->input, MT_TOOL_FINGER, +>> ?+ subdata.status & +>> ?+ SUBDATA_STATUS_TOUCH_POINT); +>> ?+ input_report_abs(priv->input, ABS_MT_POSITION_X, +>> ?+ priv->pos[id].x); +>> ?+ input_report_abs(priv->input, ABS_MT_POSITION_Y, +>> ?+ priv->pos[id].y); +>> ?+ } +>> ?+ +>> ?+ input_mt_sync_frame(priv->input); +>> ?+ input_sync(priv->input); +>> ?+ +>> ?+ schedule_delayed_work(&priv->dwork, +>> ?+ msecs_to_jiffies(priv->poll_period)); +>> ?+} +>> ?+ +>> ?+static irqreturn_t ili2139_irq(int irq, void *irq_data) +>> ?+{ +>> ?+ struct ili2139 *priv = irq_data; +>> ?+ +>> ?+ schedule_delayed_work(&priv->dwork, 0); +>> ?+ +>> ?+ return IRQ_HANDLED; +>> ?+} +>> ?+ +>> ?+static int ili2139_i2c_probe(struct i2c_client *client, +>> ?+ const struct i2c_device_id *id) +>> ?+{ +>> ?+ struct device *dev = &client->dev; +>> ?+ struct ili2139 *priv; +>> ?+ struct input_dev *input; +>> ?+ struct panel_info panel; +>> ?+ struct firmware_version firmware; +>> ?+ int xmax, ymax; +>> ?+ int error; +>> ?+ +>> ?+ dev_dbg(dev, "Probing for ILI2139 I2C Touschreen driver"); +>> ?+ +>> ?+ if (client->irq <= 0) { +>> ?+ dev_err(dev, "No IRQ!\n"); +>> ?+ return -ENODEV; +>> ?+ } +>> ?+ +>> ?+ /* Get firmware version */ +>> ?+ error = ili2139_read_reg(client, REG_FIRMWARE_VERSION, +>> ?+ &firmware, sizeof(firmware)); +>> ?+ if (error) { +>> ?+ dev_err(dev, "Failed to get firmware version, err: %d\n", +>> ?+ error); +>> ?+ return error; +>> ?+ } +>> ?+ +>> ?+ /* get panel info */ +>> ?+ error = ili2139_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 = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); +>> ?+ input = devm_input_allocate_device(dev); +>> ?+ if (!priv || !input) +>> ?+ return -ENOMEM; +>> ?+ +>> ?+ priv->client = client; +>> ?+ priv->input = input; +>> ?+ priv->poll_period = DEFAULT_POLL_PERIOD; +>> ?+ INIT_DELAYED_WORK(&priv->dwork, ili2139_work); +>> ?+ +>> ?+ /* Setup input device */ +>> ?+ input->name = "ILI2139 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); +>> ?+ +>> ?+ /* Multi touch */ +>> ?+ input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_DIRECT | +>> ?+ INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK); +>> ?+ 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); +>> ?+ +>> ?+ touchscreen_parse_properties(input, true, &priv->prop); +>> ?+ +>> ?+ input_set_drvdata(input, priv); +>> ?+ i2c_set_clientdata(client, priv); +>> ?+ +>> ?+ error = devm_request_irq(dev, client->irq, ili2139_irq, +>> ?+ IRQF_TRIGGER_FALLING, client->name, priv); +>> ?+ if (error) { +>> ?+ dev_err(dev, "Unable to request touchscreen IRQ, err: %d\n", +>> ?+ error); +>> ?+ return error; +>> ?+ } +>> ?+ +>> ?+ error = input_register_device(priv->input); +>> ?+ if (error) { +>> ?+ dev_err(dev, "Cannot register input device, err: %d\n", error); +>> ?+ return error; +>> ?+ } +>> ?+ +>> ?+ device_init_wakeup(&client->dev, 1); +>> ?+ +>> ?+ dev_dbg(dev, +>> ?+ "ILI2139 initialized (IRQ: %d), firmware version %d.%d.%d", +>> ?+ client->irq, firmware.id, firmware.major, firmware.minor); +>> ?+ +>> ?+ return 0; +>> ?+} +>> ?+ +>> ?+static int ili2139_i2c_remove(struct i2c_client *client) +>> ?+{ +>> ?+ struct ili2139 *priv = i2c_get_clientdata(client); +>> ?+ +>> ?+ cancel_delayed_work_sync(&priv->dwork); +>> ?+ +>> ?+ return 0; +>> ?+} +>> ?+ +>> ?+static int __maybe_unused ili2139_i2c_suspend(struct device *dev) +>> ?+{ +>> ?+ struct i2c_client *client = to_i2c_client(dev); +>> ?+ +>> ?+ if (device_may_wakeup(&client->dev)) +>> ?+ enable_irq_wake(client->irq); +>> ?+ +>> ?+ return 0; +>> ?+} +>> ?+ +>> ?+static int __maybe_unused ili2139_i2c_resume(struct device *dev) +>> ?+{ +>> ?+ struct i2c_client *client = to_i2c_client(dev); +>> ?+ +>> ?+ if (device_may_wakeup(&client->dev)) +>> ?+ disable_irq_wake(client->irq); +>> ?+ +>> ?+ return 0; +>> ?+} +>> ?+ +>> ?+static SIMPLE_DEV_PM_OPS(ili2139_i2c_pm, +>> ?+ ili2139_i2c_suspend, ili2139_i2c_resume); +>> ?+ +>> ?+static const struct i2c_device_id ili2139_i2c_id[] = { +>> ?+ { "ili2139", 0 }, +>> ?+ { } +>> ?+}; +>> ?+MODULE_DEVICE_TABLE(i2c, ili2139_i2c_id); +>> ?+ +>> ?+static struct i2c_driver ili2139_ts_driver = { +>> ?+ .driver = { +>> ?+ .name = "ili2139_i2c", +>> ?+ .pm = &ili2139_i2c_pm, +>> ?+ }, +>> ?+ .id_table = ili2139_i2c_id, +>> ?+ .probe = ili2139_i2c_probe, +>> ?+ .remove = ili2139_i2c_remove, +>> ?+}; +>> ?+ +>> ?+module_i2c_driver(ili2139_ts_driver); +>> ?+ +>> ?+MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>"); +>> ?+MODULE_DESCRIPTION("ILI2139 I2C Touchscreen Driver"); +>> ?+MODULE_LICENSE("GPL"); +>> ?-- +>> ?2.10.1 > > -- > Dmitry - --- -You received this message because you are subscribed to the Google Groups "linux-sunxi" group. -To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org -For more options, visit https://groups.google.com/d/optout. diff --git a/a/content_digest b/N1/content_digest index 5c83bb0..f4fe95a 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -1,51 +1,29 @@ "ref\020161011003359.26079-1-icenowy@aosc.xyz\0" "ref\020161011003359.26079-3-icenowy@aosc.xyz\0" "ref\020161011174046.GA27925@dtor-ws\0" - "From\0Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>\0" - "Subject\0Re: [PATCH 3/5] Input: add driver for Ilitek ili2139 touch IC\0" + "From\0icenowy@aosc.xyz (Icenowy Zheng)\0" + "Subject\0[PATCH 3/5] Input: add driver for Ilitek ili2139 touch IC\0" "Date\0Wed, 12 Oct 2016 02:34:01 +0800\0" - "To\0Dmitry Torokhov <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>\0" - "Cc\0Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>" - Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> - Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org> - Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> - Henrik Rydberg <rydberg-FFUHeuDi6mxAfugRpC6u6w@public.gmane.org> - Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org> - Russell King <linux-I+IVW8TIWO2tmTQ+vhA3Yw@public.gmane.org> - Thierry Reding <treding-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org> - Shawn Guo <shawnguo-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> - Jarkko Sakkinen <jarkko.sakkinen-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> - Marek Vasut <marex-ynQEQJNshbs@public.gmane.org> - Rask Ingemann Lambertsen <ccc94453-1EA3ORoCGBhoJ7GROcy7lA@public.gmane.org> - Greg Kroah-Hartman <gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org> - Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org> - Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org> - Michael Welling <mwelling-EkmVulN54Sk@public.gmane.org> - Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org> - Markus Pargmann <mpa-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org> - Damien Riegel <damien.riegel-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/@public.gmane.org> - Benjamin Tissoires <benjamin.tissoires-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> - Jeffrey Lin <jeffrey.lin-s3Ivl27awEzQT0dZR+AlfA@public.gmane.org> - " Javier\0" + "To\0linux-arm-kernel@lists.infradead.org\0" "\00:1\0" "b\0" "\n" "\n" - "12.10.2016, 01:40, \"Dmitry Torokhov\" <dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>:\n" + "12.10.2016, 01:40, \"Dmitry Torokhov\" <dmitry.torokhov@gmail.com>:\n" "> Hi Icenowy,\n" ">\n" "> On Tue, Oct 11, 2016 at 08:33:57AM +0800, Icenowy Zheng wrote:\n" - ">> \302\240This driver adds support for Ilitek ili2139 touch IC, which is used in\n" - ">> \302\240several Colorfly tablets (for example, Colorfly E708 Q1, which is an\n" - ">> \302\240Allwinner A31s tablet with mainline kernel support).\n" + ">> ?This driver adds support for Ilitek ili2139 touch IC, which is used in\n" + ">> ?several Colorfly tablets (for example, Colorfly E708 Q1, which is an\n" + ">> ?Allwinner A31s tablet with mainline kernel support).\n" ">>\n" - ">> \302\240Theortically it may support more Ilitek touch ICs, however, only ili2139\n" - ">> \302\240is used in any mainlined device.\n" + ">> ?Theortically it may support more Ilitek touch ICs, however, only ili2139\n" + ">> ?is used in any mainlined device.\n" ">>\n" - ">> \302\240It supports device tree enumeration, with screen resolution and axis\n" - ">> \302\240quirks configurable.\n" + ">> ?It supports device tree enumeration, with screen resolution and axis\n" + ">> ?quirks configurable.\n" ">>\n" - ">> \302\240Signed-off-by: Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>\n" + ">> ?Signed-off-by: Icenowy Zheng <icenowy@aosc.xyz>\n" ">\n" "> Please extend ili210x.c instead of adding brand new driver, they look\n" "> very similar.\n" @@ -61,385 +39,380 @@ "(This driver is capable of dt probing, and uses devm_ functions)\n" "\n" ">\n" - ">> \302\240---\n" - ">> \302\240\302\240drivers/input/touchscreen/Kconfig | 14 ++\n" - ">> \302\240\302\240drivers/input/touchscreen/Makefile | 1 +\n" - ">> \302\240\302\240drivers/input/touchscreen/ili2139.c | 320 ++++++++++++++++++++++++++++++++++++\n" - ">> \302\240\302\2403 files changed, 335 insertions(+)\n" - ">> \302\240\302\240create mode 100644 drivers/input/touchscreen/ili2139.c\n" + ">> ?---\n" + ">> ??drivers/input/touchscreen/Kconfig | 14 ++\n" + ">> ??drivers/input/touchscreen/Makefile | 1 +\n" + ">> ??drivers/input/touchscreen/ili2139.c | 320 ++++++++++++++++++++++++++++++++++++\n" + ">> ??3 files changed, 335 insertions(+)\n" + ">> ??create mode 100644 drivers/input/touchscreen/ili2139.c\n" ">>\n" - ">> \302\240diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig\n" - ">> \302\240index 5079813..bb4d9d2 100644\n" - ">> \302\240--- a/drivers/input/touchscreen/Kconfig\n" - ">> \302\240+++ b/drivers/input/touchscreen/Kconfig\n" - ">> \302\240@@ -348,6 +348,20 @@ config TOUCHSCREEN_ILI210X\n" - ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240To compile this driver as a module, choose M here: the\n" - ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240module will be called ili210x.\n" + ">> ?diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig\n" + ">> ?index 5079813..bb4d9d2 100644\n" + ">> ?--- a/drivers/input/touchscreen/Kconfig\n" + ">> ?+++ b/drivers/input/touchscreen/Kconfig\n" + ">> ?@@ -348,6 +348,20 @@ config TOUCHSCREEN_ILI210X\n" + ">> ????????????To compile this driver as a module, choose M here: the\n" + ">> ????????????module will be called ili210x.\n" ">>\n" - ">> \302\240+config TOUCHSCREEN_ILI2139\n" - ">> \302\240+ tristate \"Ilitek ILI2139 based touchscreen\"\n" - ">> \302\240+ depends on I2C\n" - ">> \302\240+ depends on OF\n" - ">> \302\240+ help\n" - ">> \302\240+ Say Y here if you have a ILI2139 based touchscreen\n" - ">> \302\240+ controller. Such kind of chipsets can be found in several\n" - ">> \302\240+ Colorfly tablets.\n" - ">> \302\240+\n" - ">> \302\240+ If unsure, say N.\n" - ">> \302\240+\n" - ">> \302\240+ To compile this driver as a module, choose M here; the\n" - ">> \302\240+ module will be called ili2139.\n" - ">> \302\240+\n" - ">> \302\240\302\240config TOUCHSCREEN_IPROC\n" - ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240tristate \"IPROC touch panel driver support\"\n" - ">> \302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240\302\240depends on ARCH_BCM_IPROC || COMPILE_TEST\n" - ">> \302\240diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile\n" - ">> \302\240index 81b8645..930b5e2 100644\n" - ">> \302\240--- a/drivers/input/touchscreen/Makefile\n" - ">> \302\240+++ b/drivers/input/touchscreen/Makefile\n" - ">> \302\240@@ -40,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o\n" - ">> \302\240\302\240obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o\n" - ">> \302\240\302\240obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o\n" - ">> \302\240\302\240obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o\n" - ">> \302\240+obj-$(CONFIG_TOUCHSCREEN_ILI2139) += ili2139.o\n" - ">> \302\240\302\240obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o\n" - ">> \302\240\302\240obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o\n" - ">> \302\240\302\240obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o\n" - ">> \302\240diff --git a/drivers/input/touchscreen/ili2139.c b/drivers/input/touchscreen/ili2139.c\n" - ">> \302\240new file mode 100644\n" - ">> \302\240index 0000000..65c2dea\n" - ">> \302\240--- /dev/null\n" - ">> \302\240+++ b/drivers/input/touchscreen/ili2139.c\n" - ">> \302\240@@ -0,0 +1,320 @@\n" - ">> \302\240+/* -------------------------------------------------------------------------\n" - ">> \302\240+ * Copyright (C) 2016, Icenowy Zheng <icenowy-ymACFijhrKM@public.gmane.org>\n" - ">> \302\240+ *\n" - ">> \302\240+ * Derived from:\n" - ">> \302\240+ * ili210x.c\n" - ">> \302\240+ * Copyright (C) Olivier Sobrie <olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org>\n" - ">> \302\240+ *\n" - ">> \302\240+ * This program is free software; you can redistribute it and/or modify\n" - ">> \302\240+ * it under the terms of the GNU General Public License as published by\n" - ">> \302\240+ * the Free Software Foundation; either version 2 of the License, or\n" - ">> \302\240+ * (at your option) any later version.\n" - ">> \302\240+ *\n" - ">> \302\240+ * This program is distributed in the hope that it will be useful,\n" - ">> \302\240+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - ">> \302\240+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - ">> \302\240+ * GNU General Public License for more details.\n" - ">> \302\240+ * -------------------------------------------------------------------------\n" - ">> \302\240+ */\n" - ">> \302\240+\n" - ">> \302\240+#include <linux/module.h>\n" - ">> \302\240+#include <linux/i2c.h>\n" - ">> \302\240+#include <linux/interrupt.h>\n" - ">> \302\240+#include <linux/slab.h>\n" - ">> \302\240+#include <linux/input.h>\n" - ">> \302\240+#include <linux/input/mt.h>\n" - ">> \302\240+#include <linux/input/touchscreen.h>\n" - ">> \302\240+#include <linux/delay.h>\n" - ">> \302\240+#include <linux/workqueue.h>\n" - ">> \302\240+\n" - ">> \302\240+#define DEFAULT_POLL_PERIOD 20\n" - ">> \302\240+\n" - ">> \302\240+#define MAX_TOUCHES 10\n" - ">> \302\240+#define COMPATIBLE_TOUCHES 2\n" - ">> \302\240+\n" - ">> \302\240+/* Touchscreen commands */\n" - ">> \302\240+#define REG_TOUCHDATA 0x10\n" - ">> \302\240+#define REG_TOUCHSUBDATA 0x11\n" - ">> \302\240+#define REG_PANEL_INFO 0x20\n" - ">> \302\240+#define REG_FIRMWARE_VERSION 0x40\n" - ">> \302\240+#define REG_PROTO_VERSION 0x42\n" - ">> \302\240+\n" - ">> \302\240+#define SUBDATA_STATUS_TOUCH_POINT 0x80\n" - ">> \302\240+#define SUBDATA_STATUS_RELEASE_POINT 0x00\n" - ">> \302\240+\n" - ">> \302\240+struct finger {\n" - ">> \302\240+ u8 x_low;\n" - ">> \302\240+ u8 x_high;\n" - ">> \302\240+ u8 y_low;\n" - ">> \302\240+ u8 y_high;\n" - ">> \302\240+} __packed;\n" - ">> \302\240+\n" - ">> \302\240+struct touchdata {\n" - ">> \302\240+ u8 length;\n" - ">> \302\240+ struct finger finger[COMPATIBLE_TOUCHES];\n" - ">> \302\240+} __packed;\n" - ">> \302\240+\n" - ">> \302\240+struct touch_subdata {\n" - ">> \302\240+ u8 status;\n" - ">> \302\240+ struct finger finger;\n" - ">> \302\240+} __packed;\n" - ">> \302\240+\n" - ">> \302\240+struct panel_info {\n" - ">> \302\240+ struct finger finger_max;\n" - ">> \302\240+ u8 xchannel_num;\n" - ">> \302\240+ u8 ychannel_num;\n" - ">> \302\240+} __packed;\n" - ">> \302\240+\n" - ">> \302\240+struct firmware_version {\n" - ">> \302\240+ u8 id;\n" - ">> \302\240+ u8 major;\n" - ">> \302\240+ u8 minor;\n" - ">> \302\240+} __packed;\n" - ">> \302\240+\n" - ">> \302\240+struct ili2139 {\n" - ">> \302\240+ struct i2c_client *client;\n" - ">> \302\240+ struct input_dev *input;\n" - ">> \302\240+ unsigned int poll_period;\n" - ">> \302\240+ struct delayed_work dwork;\n" - ">> \302\240+ struct touchscreen_properties prop;\n" - ">> \302\240+ int slots[MAX_TOUCHES];\n" - ">> \302\240+ int ids[MAX_TOUCHES];\n" - ">> \302\240+ struct input_mt_pos pos[MAX_TOUCHES];\n" - ">> \302\240+};\n" - ">> \302\240+\n" - ">> \302\240+static int ili2139_read_reg(struct i2c_client *client, u8 reg, void *buf,\n" - ">> \302\240+ size_t len)\n" - ">> \302\240+{\n" - ">> \302\240+ struct i2c_msg msg[2] = {\n" - ">> \302\240+ {\n" - ">> \302\240+ .addr = client->addr,\n" - ">> \302\240+ .flags = 0,\n" - ">> \302\240+ .len = 1,\n" - ">> \302\240+ .buf = ®,\n" - ">> \302\240+ },\n" - ">> \302\240+ {\n" - ">> \302\240+ .addr = client->addr,\n" - ">> \302\240+ .flags = I2C_M_RD,\n" - ">> \302\240+ .len = len,\n" - ">> \302\240+ .buf = buf,\n" - ">> \302\240+ }\n" - ">> \302\240+ };\n" - ">> \302\240+\n" - ">> \302\240+ if (i2c_transfer(client->adapter, msg, 2) != 2) {\n" - ">> \302\240+ dev_err(&client->dev, \"i2c transfer failed\\n\");\n" - ">> \302\240+ return -EIO;\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ return 0;\n" - ">> \302\240+}\n" - ">> \302\240+\n" - ">> \302\240+static void ili2139_work(struct work_struct *work)\n" - ">> \302\240+{\n" - ">> \302\240+ int id;\n" - ">> \302\240+ struct ili2139 *priv = container_of(work, struct ili2139,\n" - ">> \302\240+ dwork.work);\n" - ">> \302\240+ struct i2c_client *client = priv->client;\n" - ">> \302\240+ struct touchdata touchdata;\n" - ">> \302\240+ struct touch_subdata subdata;\n" - ">> \302\240+ int error;\n" - ">> \302\240+\n" - ">> \302\240+ error = ili2139_read_reg(client, REG_TOUCHDATA,\n" - ">> \302\240+ &touchdata, sizeof(touchdata));\n" - ">> \302\240+ if (error) {\n" - ">> \302\240+ dev_err(&client->dev,\n" - ">> \302\240+ \"Unable to get touchdata, err = %d\\n\", error);\n" - ">> \302\240+ return;\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ for (id = 0; id < touchdata.length; id++) {\n" - ">> \302\240+ error = ili2139_read_reg(client, REG_TOUCHSUBDATA, &subdata,\n" - ">> \302\240+ sizeof(subdata));\n" - ">> \302\240+ if (error) {\n" - ">> \302\240+ dev_err(&client->dev,\n" - ">> \302\240+ \"Unable to get touch subdata, err = %d\\n\",\n" - ">> \302\240+ error);\n" - ">> \302\240+ return;\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ priv->ids[id] = subdata.status & 0x3F;\n" - ">> \302\240+\n" - ">> \302\240+ /* The sequence changed in the v2 subdata protocol. */\n" - ">> \302\240+ touchscreen_set_mt_pos(&priv->pos[id], &priv->prop,\n" - ">> \302\240+ (subdata.finger.x_high | (subdata.finger.x_low << 8)),\n" - ">> \302\240+ (subdata.finger.y_high | (subdata.finger.y_low << 8)));\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ input_mt_assign_slots(priv->input, priv->slots, priv->pos,\n" - ">> \302\240+ touchdata.length, 0);\n" - ">> \302\240+\n" - ">> \302\240+ for (id = 0; id < touchdata.length; id++) {\n" - ">> \302\240+ input_mt_slot(priv->input, priv->slots[id]);\n" - ">> \302\240+ input_mt_report_slot_state(priv->input, MT_TOOL_FINGER,\n" - ">> \302\240+ subdata.status &\n" - ">> \302\240+ SUBDATA_STATUS_TOUCH_POINT);\n" - ">> \302\240+ input_report_abs(priv->input, ABS_MT_POSITION_X,\n" - ">> \302\240+ priv->pos[id].x);\n" - ">> \302\240+ input_report_abs(priv->input, ABS_MT_POSITION_Y,\n" - ">> \302\240+ priv->pos[id].y);\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ input_mt_sync_frame(priv->input);\n" - ">> \302\240+ input_sync(priv->input);\n" - ">> \302\240+\n" - ">> \302\240+ schedule_delayed_work(&priv->dwork,\n" - ">> \302\240+ msecs_to_jiffies(priv->poll_period));\n" - ">> \302\240+}\n" - ">> \302\240+\n" - ">> \302\240+static irqreturn_t ili2139_irq(int irq, void *irq_data)\n" - ">> \302\240+{\n" - ">> \302\240+ struct ili2139 *priv = irq_data;\n" - ">> \302\240+\n" - ">> \302\240+ schedule_delayed_work(&priv->dwork, 0);\n" - ">> \302\240+\n" - ">> \302\240+ return IRQ_HANDLED;\n" - ">> \302\240+}\n" - ">> \302\240+\n" - ">> \302\240+static int ili2139_i2c_probe(struct i2c_client *client,\n" - ">> \302\240+ const struct i2c_device_id *id)\n" - ">> \302\240+{\n" - ">> \302\240+ struct device *dev = &client->dev;\n" - ">> \302\240+ struct ili2139 *priv;\n" - ">> \302\240+ struct input_dev *input;\n" - ">> \302\240+ struct panel_info panel;\n" - ">> \302\240+ struct firmware_version firmware;\n" - ">> \302\240+ int xmax, ymax;\n" - ">> \302\240+ int error;\n" - ">> \302\240+\n" - ">> \302\240+ dev_dbg(dev, \"Probing for ILI2139 I2C Touschreen driver\");\n" - ">> \302\240+\n" - ">> \302\240+ if (client->irq <= 0) {\n" - ">> \302\240+ dev_err(dev, \"No IRQ!\\n\");\n" - ">> \302\240+ return -ENODEV;\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ /* Get firmware version */\n" - ">> \302\240+ error = ili2139_read_reg(client, REG_FIRMWARE_VERSION,\n" - ">> \302\240+ &firmware, sizeof(firmware));\n" - ">> \302\240+ if (error) {\n" - ">> \302\240+ dev_err(dev, \"Failed to get firmware version, err: %d\\n\",\n" - ">> \302\240+ error);\n" - ">> \302\240+ return error;\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ /* get panel info */\n" - ">> \302\240+ error = ili2139_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));\n" - ">> \302\240+ if (error) {\n" - ">> \302\240+ dev_err(dev, \"Failed to get panel information, err: %d\\n\",\n" - ">> \302\240+ error);\n" - ">> \302\240+ return error;\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);\n" - ">> \302\240+ ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);\n" - ">> \302\240+\n" - ">> \302\240+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);\n" - ">> \302\240+ input = devm_input_allocate_device(dev);\n" - ">> \302\240+ if (!priv || !input)\n" - ">> \302\240+ return -ENOMEM;\n" - ">> \302\240+\n" - ">> \302\240+ priv->client = client;\n" - ">> \302\240+ priv->input = input;\n" - ">> \302\240+ priv->poll_period = DEFAULT_POLL_PERIOD;\n" - ">> \302\240+ INIT_DELAYED_WORK(&priv->dwork, ili2139_work);\n" - ">> \302\240+\n" - ">> \302\240+ /* Setup input device */\n" - ">> \302\240+ input->name = \"ILI2139 Touchscreen\";\n" - ">> \302\240+ input->id.bustype = BUS_I2C;\n" - ">> \302\240+ input->dev.parent = dev;\n" - ">> \302\240+\n" - ">> \302\240+ __set_bit(EV_SYN, input->evbit);\n" - ">> \302\240+ __set_bit(EV_KEY, input->evbit);\n" - ">> \302\240+ __set_bit(EV_ABS, input->evbit);\n" - ">> \302\240+\n" - ">> \302\240+ /* Multi touch */\n" - ">> \302\240+ input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_DIRECT |\n" - ">> \302\240+ INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK);\n" - ">> \302\240+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);\n" - ">> \302\240+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);\n" - ">> \302\240+\n" - ">> \302\240+ touchscreen_parse_properties(input, true, &priv->prop);\n" - ">> \302\240+\n" - ">> \302\240+ input_set_drvdata(input, priv);\n" - ">> \302\240+ i2c_set_clientdata(client, priv);\n" - ">> \302\240+\n" - ">> \302\240+ error = devm_request_irq(dev, client->irq, ili2139_irq,\n" - ">> \302\240+ IRQF_TRIGGER_FALLING, client->name, priv);\n" - ">> \302\240+ if (error) {\n" - ">> \302\240+ dev_err(dev, \"Unable to request touchscreen IRQ, err: %d\\n\",\n" - ">> \302\240+ error);\n" - ">> \302\240+ return error;\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ error = input_register_device(priv->input);\n" - ">> \302\240+ if (error) {\n" - ">> \302\240+ dev_err(dev, \"Cannot register input device, err: %d\\n\", error);\n" - ">> \302\240+ return error;\n" - ">> \302\240+ }\n" - ">> \302\240+\n" - ">> \302\240+ device_init_wakeup(&client->dev, 1);\n" - ">> \302\240+\n" - ">> \302\240+ dev_dbg(dev,\n" - ">> \302\240+ \"ILI2139 initialized (IRQ: %d), firmware version %d.%d.%d\",\n" - ">> \302\240+ client->irq, firmware.id, firmware.major, firmware.minor);\n" - ">> \302\240+\n" - ">> \302\240+ return 0;\n" - ">> \302\240+}\n" - ">> \302\240+\n" - ">> \302\240+static int ili2139_i2c_remove(struct i2c_client *client)\n" - ">> \302\240+{\n" - ">> \302\240+ struct ili2139 *priv = i2c_get_clientdata(client);\n" - ">> \302\240+\n" - ">> \302\240+ cancel_delayed_work_sync(&priv->dwork);\n" - ">> \302\240+\n" - ">> \302\240+ return 0;\n" - ">> \302\240+}\n" - ">> \302\240+\n" - ">> \302\240+static int __maybe_unused ili2139_i2c_suspend(struct device *dev)\n" - ">> \302\240+{\n" - ">> \302\240+ struct i2c_client *client = to_i2c_client(dev);\n" - ">> \302\240+\n" - ">> \302\240+ if (device_may_wakeup(&client->dev))\n" - ">> \302\240+ enable_irq_wake(client->irq);\n" - ">> \302\240+\n" - ">> \302\240+ return 0;\n" - ">> \302\240+}\n" - ">> \302\240+\n" - ">> \302\240+static int __maybe_unused ili2139_i2c_resume(struct device *dev)\n" - ">> \302\240+{\n" - ">> \302\240+ struct i2c_client *client = to_i2c_client(dev);\n" - ">> \302\240+\n" - ">> \302\240+ if (device_may_wakeup(&client->dev))\n" - ">> \302\240+ disable_irq_wake(client->irq);\n" - ">> \302\240+\n" - ">> \302\240+ return 0;\n" - ">> \302\240+}\n" - ">> \302\240+\n" - ">> \302\240+static SIMPLE_DEV_PM_OPS(ili2139_i2c_pm,\n" - ">> \302\240+ ili2139_i2c_suspend, ili2139_i2c_resume);\n" - ">> \302\240+\n" - ">> \302\240+static const struct i2c_device_id ili2139_i2c_id[] = {\n" - ">> \302\240+ { \"ili2139\", 0 },\n" - ">> \302\240+ { }\n" - ">> \302\240+};\n" - ">> \302\240+MODULE_DEVICE_TABLE(i2c, ili2139_i2c_id);\n" - ">> \302\240+\n" - ">> \302\240+static struct i2c_driver ili2139_ts_driver = {\n" - ">> \302\240+ .driver = {\n" - ">> \302\240+ .name = \"ili2139_i2c\",\n" - ">> \302\240+ .pm = &ili2139_i2c_pm,\n" - ">> \302\240+ },\n" - ">> \302\240+ .id_table = ili2139_i2c_id,\n" - ">> \302\240+ .probe = ili2139_i2c_probe,\n" - ">> \302\240+ .remove = ili2139_i2c_remove,\n" - ">> \302\240+};\n" - ">> \302\240+\n" - ">> \302\240+module_i2c_driver(ili2139_ts_driver);\n" - ">> \302\240+\n" - ">> \302\240+MODULE_AUTHOR(\"Olivier Sobrie <olivier-Ui3EtX6WB9GzQB+pC5nmwQ@public.gmane.org>\");\n" - ">> \302\240+MODULE_DESCRIPTION(\"ILI2139 I2C Touchscreen Driver\");\n" - ">> \302\240+MODULE_LICENSE(\"GPL\");\n" - ">> \302\240--\n" - ">> \302\2402.10.1\n" + ">> ?+config TOUCHSCREEN_ILI2139\n" + ">> ?+ tristate \"Ilitek ILI2139 based touchscreen\"\n" + ">> ?+ depends on I2C\n" + ">> ?+ depends on OF\n" + ">> ?+ help\n" + ">> ?+ Say Y here if you have a ILI2139 based touchscreen\n" + ">> ?+ controller. Such kind of chipsets can be found in several\n" + ">> ?+ Colorfly tablets.\n" + ">> ?+\n" + ">> ?+ If unsure, say N.\n" + ">> ?+\n" + ">> ?+ To compile this driver as a module, choose M here; the\n" + ">> ?+ module will be called ili2139.\n" + ">> ?+\n" + ">> ??config TOUCHSCREEN_IPROC\n" + ">> ??????????tristate \"IPROC touch panel driver support\"\n" + ">> ??????????depends on ARCH_BCM_IPROC || COMPILE_TEST\n" + ">> ?diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile\n" + ">> ?index 81b8645..930b5e2 100644\n" + ">> ?--- a/drivers/input/touchscreen/Makefile\n" + ">> ?+++ b/drivers/input/touchscreen/Makefile\n" + ">> ?@@ -40,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL) += egalax_ts_serial.o\n" + ">> ??obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o\n" + ">> ??obj-$(CONFIG_TOUCHSCREEN_GOODIX) += goodix.o\n" + ">> ??obj-$(CONFIG_TOUCHSCREEN_ILI210X) += ili210x.o\n" + ">> ?+obj-$(CONFIG_TOUCHSCREEN_ILI2139) += ili2139.o\n" + ">> ??obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC) += imx6ul_tsc.o\n" + ">> ??obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o\n" + ">> ??obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o\n" + ">> ?diff --git a/drivers/input/touchscreen/ili2139.c b/drivers/input/touchscreen/ili2139.c\n" + ">> ?new file mode 100644\n" + ">> ?index 0000000..65c2dea\n" + ">> ?--- /dev/null\n" + ">> ?+++ b/drivers/input/touchscreen/ili2139.c\n" + ">> ?@@ -0,0 +1,320 @@\n" + ">> ?+/* -------------------------------------------------------------------------\n" + ">> ?+ * Copyright (C) 2016, Icenowy Zheng <icenowy@aosc.xyz>\n" + ">> ?+ *\n" + ">> ?+ * Derived from:\n" + ">> ?+ * ili210x.c\n" + ">> ?+ * Copyright (C) Olivier Sobrie <olivier@sobrie.be>\n" + ">> ?+ *\n" + ">> ?+ * This program is free software; you can redistribute it and/or modify\n" + ">> ?+ * it under the terms of the GNU General Public License as published by\n" + ">> ?+ * the Free Software Foundation; either version 2 of the License, or\n" + ">> ?+ * (at your option) any later version.\n" + ">> ?+ *\n" + ">> ?+ * This program is distributed in the hope that it will be useful,\n" + ">> ?+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + ">> ?+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + ">> ?+ * GNU General Public License for more details.\n" + ">> ?+ * -------------------------------------------------------------------------\n" + ">> ?+ */\n" + ">> ?+\n" + ">> ?+#include <linux/module.h>\n" + ">> ?+#include <linux/i2c.h>\n" + ">> ?+#include <linux/interrupt.h>\n" + ">> ?+#include <linux/slab.h>\n" + ">> ?+#include <linux/input.h>\n" + ">> ?+#include <linux/input/mt.h>\n" + ">> ?+#include <linux/input/touchscreen.h>\n" + ">> ?+#include <linux/delay.h>\n" + ">> ?+#include <linux/workqueue.h>\n" + ">> ?+\n" + ">> ?+#define DEFAULT_POLL_PERIOD 20\n" + ">> ?+\n" + ">> ?+#define MAX_TOUCHES 10\n" + ">> ?+#define COMPATIBLE_TOUCHES 2\n" + ">> ?+\n" + ">> ?+/* Touchscreen commands */\n" + ">> ?+#define REG_TOUCHDATA 0x10\n" + ">> ?+#define REG_TOUCHSUBDATA 0x11\n" + ">> ?+#define REG_PANEL_INFO 0x20\n" + ">> ?+#define REG_FIRMWARE_VERSION 0x40\n" + ">> ?+#define REG_PROTO_VERSION 0x42\n" + ">> ?+\n" + ">> ?+#define SUBDATA_STATUS_TOUCH_POINT 0x80\n" + ">> ?+#define SUBDATA_STATUS_RELEASE_POINT 0x00\n" + ">> ?+\n" + ">> ?+struct finger {\n" + ">> ?+ u8 x_low;\n" + ">> ?+ u8 x_high;\n" + ">> ?+ u8 y_low;\n" + ">> ?+ u8 y_high;\n" + ">> ?+} __packed;\n" + ">> ?+\n" + ">> ?+struct touchdata {\n" + ">> ?+ u8 length;\n" + ">> ?+ struct finger finger[COMPATIBLE_TOUCHES];\n" + ">> ?+} __packed;\n" + ">> ?+\n" + ">> ?+struct touch_subdata {\n" + ">> ?+ u8 status;\n" + ">> ?+ struct finger finger;\n" + ">> ?+} __packed;\n" + ">> ?+\n" + ">> ?+struct panel_info {\n" + ">> ?+ struct finger finger_max;\n" + ">> ?+ u8 xchannel_num;\n" + ">> ?+ u8 ychannel_num;\n" + ">> ?+} __packed;\n" + ">> ?+\n" + ">> ?+struct firmware_version {\n" + ">> ?+ u8 id;\n" + ">> ?+ u8 major;\n" + ">> ?+ u8 minor;\n" + ">> ?+} __packed;\n" + ">> ?+\n" + ">> ?+struct ili2139 {\n" + ">> ?+ struct i2c_client *client;\n" + ">> ?+ struct input_dev *input;\n" + ">> ?+ unsigned int poll_period;\n" + ">> ?+ struct delayed_work dwork;\n" + ">> ?+ struct touchscreen_properties prop;\n" + ">> ?+ int slots[MAX_TOUCHES];\n" + ">> ?+ int ids[MAX_TOUCHES];\n" + ">> ?+ struct input_mt_pos pos[MAX_TOUCHES];\n" + ">> ?+};\n" + ">> ?+\n" + ">> ?+static int ili2139_read_reg(struct i2c_client *client, u8 reg, void *buf,\n" + ">> ?+ size_t len)\n" + ">> ?+{\n" + ">> ?+ struct i2c_msg msg[2] = {\n" + ">> ?+ {\n" + ">> ?+ .addr = client->addr,\n" + ">> ?+ .flags = 0,\n" + ">> ?+ .len = 1,\n" + ">> ?+ .buf = ®,\n" + ">> ?+ },\n" + ">> ?+ {\n" + ">> ?+ .addr = client->addr,\n" + ">> ?+ .flags = I2C_M_RD,\n" + ">> ?+ .len = len,\n" + ">> ?+ .buf = buf,\n" + ">> ?+ }\n" + ">> ?+ };\n" + ">> ?+\n" + ">> ?+ if (i2c_transfer(client->adapter, msg, 2) != 2) {\n" + ">> ?+ dev_err(&client->dev, \"i2c transfer failed\\n\");\n" + ">> ?+ return -EIO;\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ return 0;\n" + ">> ?+}\n" + ">> ?+\n" + ">> ?+static void ili2139_work(struct work_struct *work)\n" + ">> ?+{\n" + ">> ?+ int id;\n" + ">> ?+ struct ili2139 *priv = container_of(work, struct ili2139,\n" + ">> ?+ dwork.work);\n" + ">> ?+ struct i2c_client *client = priv->client;\n" + ">> ?+ struct touchdata touchdata;\n" + ">> ?+ struct touch_subdata subdata;\n" + ">> ?+ int error;\n" + ">> ?+\n" + ">> ?+ error = ili2139_read_reg(client, REG_TOUCHDATA,\n" + ">> ?+ &touchdata, sizeof(touchdata));\n" + ">> ?+ if (error) {\n" + ">> ?+ dev_err(&client->dev,\n" + ">> ?+ \"Unable to get touchdata, err = %d\\n\", error);\n" + ">> ?+ return;\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ for (id = 0; id < touchdata.length; id++) {\n" + ">> ?+ error = ili2139_read_reg(client, REG_TOUCHSUBDATA, &subdata,\n" + ">> ?+ sizeof(subdata));\n" + ">> ?+ if (error) {\n" + ">> ?+ dev_err(&client->dev,\n" + ">> ?+ \"Unable to get touch subdata, err = %d\\n\",\n" + ">> ?+ error);\n" + ">> ?+ return;\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ priv->ids[id] = subdata.status & 0x3F;\n" + ">> ?+\n" + ">> ?+ /* The sequence changed in the v2 subdata protocol. */\n" + ">> ?+ touchscreen_set_mt_pos(&priv->pos[id], &priv->prop,\n" + ">> ?+ (subdata.finger.x_high | (subdata.finger.x_low << 8)),\n" + ">> ?+ (subdata.finger.y_high | (subdata.finger.y_low << 8)));\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ input_mt_assign_slots(priv->input, priv->slots, priv->pos,\n" + ">> ?+ touchdata.length, 0);\n" + ">> ?+\n" + ">> ?+ for (id = 0; id < touchdata.length; id++) {\n" + ">> ?+ input_mt_slot(priv->input, priv->slots[id]);\n" + ">> ?+ input_mt_report_slot_state(priv->input, MT_TOOL_FINGER,\n" + ">> ?+ subdata.status &\n" + ">> ?+ SUBDATA_STATUS_TOUCH_POINT);\n" + ">> ?+ input_report_abs(priv->input, ABS_MT_POSITION_X,\n" + ">> ?+ priv->pos[id].x);\n" + ">> ?+ input_report_abs(priv->input, ABS_MT_POSITION_Y,\n" + ">> ?+ priv->pos[id].y);\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ input_mt_sync_frame(priv->input);\n" + ">> ?+ input_sync(priv->input);\n" + ">> ?+\n" + ">> ?+ schedule_delayed_work(&priv->dwork,\n" + ">> ?+ msecs_to_jiffies(priv->poll_period));\n" + ">> ?+}\n" + ">> ?+\n" + ">> ?+static irqreturn_t ili2139_irq(int irq, void *irq_data)\n" + ">> ?+{\n" + ">> ?+ struct ili2139 *priv = irq_data;\n" + ">> ?+\n" + ">> ?+ schedule_delayed_work(&priv->dwork, 0);\n" + ">> ?+\n" + ">> ?+ return IRQ_HANDLED;\n" + ">> ?+}\n" + ">> ?+\n" + ">> ?+static int ili2139_i2c_probe(struct i2c_client *client,\n" + ">> ?+ const struct i2c_device_id *id)\n" + ">> ?+{\n" + ">> ?+ struct device *dev = &client->dev;\n" + ">> ?+ struct ili2139 *priv;\n" + ">> ?+ struct input_dev *input;\n" + ">> ?+ struct panel_info panel;\n" + ">> ?+ struct firmware_version firmware;\n" + ">> ?+ int xmax, ymax;\n" + ">> ?+ int error;\n" + ">> ?+\n" + ">> ?+ dev_dbg(dev, \"Probing for ILI2139 I2C Touschreen driver\");\n" + ">> ?+\n" + ">> ?+ if (client->irq <= 0) {\n" + ">> ?+ dev_err(dev, \"No IRQ!\\n\");\n" + ">> ?+ return -ENODEV;\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ /* Get firmware version */\n" + ">> ?+ error = ili2139_read_reg(client, REG_FIRMWARE_VERSION,\n" + ">> ?+ &firmware, sizeof(firmware));\n" + ">> ?+ if (error) {\n" + ">> ?+ dev_err(dev, \"Failed to get firmware version, err: %d\\n\",\n" + ">> ?+ error);\n" + ">> ?+ return error;\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ /* get panel info */\n" + ">> ?+ error = ili2139_read_reg(client, REG_PANEL_INFO, &panel, sizeof(panel));\n" + ">> ?+ if (error) {\n" + ">> ?+ dev_err(dev, \"Failed to get panel information, err: %d\\n\",\n" + ">> ?+ error);\n" + ">> ?+ return error;\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ xmax = panel.finger_max.x_low | (panel.finger_max.x_high << 8);\n" + ">> ?+ ymax = panel.finger_max.y_low | (panel.finger_max.y_high << 8);\n" + ">> ?+\n" + ">> ?+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);\n" + ">> ?+ input = devm_input_allocate_device(dev);\n" + ">> ?+ if (!priv || !input)\n" + ">> ?+ return -ENOMEM;\n" + ">> ?+\n" + ">> ?+ priv->client = client;\n" + ">> ?+ priv->input = input;\n" + ">> ?+ priv->poll_period = DEFAULT_POLL_PERIOD;\n" + ">> ?+ INIT_DELAYED_WORK(&priv->dwork, ili2139_work);\n" + ">> ?+\n" + ">> ?+ /* Setup input device */\n" + ">> ?+ input->name = \"ILI2139 Touchscreen\";\n" + ">> ?+ input->id.bustype = BUS_I2C;\n" + ">> ?+ input->dev.parent = dev;\n" + ">> ?+\n" + ">> ?+ __set_bit(EV_SYN, input->evbit);\n" + ">> ?+ __set_bit(EV_KEY, input->evbit);\n" + ">> ?+ __set_bit(EV_ABS, input->evbit);\n" + ">> ?+\n" + ">> ?+ /* Multi touch */\n" + ">> ?+ input_mt_init_slots(input, MAX_TOUCHES, INPUT_MT_DIRECT |\n" + ">> ?+ INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK);\n" + ">> ?+ input_set_abs_params(input, ABS_MT_POSITION_X, 0, xmax, 0, 0);\n" + ">> ?+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0, ymax, 0, 0);\n" + ">> ?+\n" + ">> ?+ touchscreen_parse_properties(input, true, &priv->prop);\n" + ">> ?+\n" + ">> ?+ input_set_drvdata(input, priv);\n" + ">> ?+ i2c_set_clientdata(client, priv);\n" + ">> ?+\n" + ">> ?+ error = devm_request_irq(dev, client->irq, ili2139_irq,\n" + ">> ?+ IRQF_TRIGGER_FALLING, client->name, priv);\n" + ">> ?+ if (error) {\n" + ">> ?+ dev_err(dev, \"Unable to request touchscreen IRQ, err: %d\\n\",\n" + ">> ?+ error);\n" + ">> ?+ return error;\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ error = input_register_device(priv->input);\n" + ">> ?+ if (error) {\n" + ">> ?+ dev_err(dev, \"Cannot register input device, err: %d\\n\", error);\n" + ">> ?+ return error;\n" + ">> ?+ }\n" + ">> ?+\n" + ">> ?+ device_init_wakeup(&client->dev, 1);\n" + ">> ?+\n" + ">> ?+ dev_dbg(dev,\n" + ">> ?+ \"ILI2139 initialized (IRQ: %d), firmware version %d.%d.%d\",\n" + ">> ?+ client->irq, firmware.id, firmware.major, firmware.minor);\n" + ">> ?+\n" + ">> ?+ return 0;\n" + ">> ?+}\n" + ">> ?+\n" + ">> ?+static int ili2139_i2c_remove(struct i2c_client *client)\n" + ">> ?+{\n" + ">> ?+ struct ili2139 *priv = i2c_get_clientdata(client);\n" + ">> ?+\n" + ">> ?+ cancel_delayed_work_sync(&priv->dwork);\n" + ">> ?+\n" + ">> ?+ return 0;\n" + ">> ?+}\n" + ">> ?+\n" + ">> ?+static int __maybe_unused ili2139_i2c_suspend(struct device *dev)\n" + ">> ?+{\n" + ">> ?+ struct i2c_client *client = to_i2c_client(dev);\n" + ">> ?+\n" + ">> ?+ if (device_may_wakeup(&client->dev))\n" + ">> ?+ enable_irq_wake(client->irq);\n" + ">> ?+\n" + ">> ?+ return 0;\n" + ">> ?+}\n" + ">> ?+\n" + ">> ?+static int __maybe_unused ili2139_i2c_resume(struct device *dev)\n" + ">> ?+{\n" + ">> ?+ struct i2c_client *client = to_i2c_client(dev);\n" + ">> ?+\n" + ">> ?+ if (device_may_wakeup(&client->dev))\n" + ">> ?+ disable_irq_wake(client->irq);\n" + ">> ?+\n" + ">> ?+ return 0;\n" + ">> ?+}\n" + ">> ?+\n" + ">> ?+static SIMPLE_DEV_PM_OPS(ili2139_i2c_pm,\n" + ">> ?+ ili2139_i2c_suspend, ili2139_i2c_resume);\n" + ">> ?+\n" + ">> ?+static const struct i2c_device_id ili2139_i2c_id[] = {\n" + ">> ?+ { \"ili2139\", 0 },\n" + ">> ?+ { }\n" + ">> ?+};\n" + ">> ?+MODULE_DEVICE_TABLE(i2c, ili2139_i2c_id);\n" + ">> ?+\n" + ">> ?+static struct i2c_driver ili2139_ts_driver = {\n" + ">> ?+ .driver = {\n" + ">> ?+ .name = \"ili2139_i2c\",\n" + ">> ?+ .pm = &ili2139_i2c_pm,\n" + ">> ?+ },\n" + ">> ?+ .id_table = ili2139_i2c_id,\n" + ">> ?+ .probe = ili2139_i2c_probe,\n" + ">> ?+ .remove = ili2139_i2c_remove,\n" + ">> ?+};\n" + ">> ?+\n" + ">> ?+module_i2c_driver(ili2139_ts_driver);\n" + ">> ?+\n" + ">> ?+MODULE_AUTHOR(\"Olivier Sobrie <olivier@sobrie.be>\");\n" + ">> ?+MODULE_DESCRIPTION(\"ILI2139 I2C Touchscreen Driver\");\n" + ">> ?+MODULE_LICENSE(\"GPL\");\n" + ">> ?--\n" + ">> ?2.10.1\n" ">\n" "> --\n" - "> Dmitry\n" - "\n" - "-- \n" - "You received this message because you are subscribed to the Google Groups \"linux-sunxi\" group.\n" - "To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org\n" - For more options, visit https://groups.google.com/d/optout. + > Dmitry -cbb8b6cbba6162938f860ba28cdbba9b8fe4bc33c1f7e4f134f7c86dd43baaf7 +628a4155faa96cf7a6ff3639df0fdc0b65f5f105301155ae5a6850230d3cab88
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.