summaryrefslogtreecommitdiff
path: root/drivers/input
diff options
context:
space:
mode:
authorLuwei <b45643@freescale.com>2013-08-08 16:35:24 +0800
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 08:01:06 -0500
commit40e015a51dc6d5c86e70faed921ecf8b5f2f9fe8 (patch)
treef6339fb34b32da722be89ab2776739f3917ac4ce /drivers/input
parent2317e1f41eadaa70b7fa9412ac4a0a8d785564b1 (diff)
ENGR00274247: touch: add egalax touch driver support on i.MX6Q/DL AUTO/SD
Copy the egalax touch screen driver from linux3.5.7.Make some modification.Remove the __devinit __devexit __devexit_p out of the file, because 3.10 does not support. Signed-off-by: Luwei Zhou <b45643@freescale.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/touchscreen/egalax_ts.c129
1 files changed, 103 insertions, 26 deletions
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index 39f3df8670c3..e237bdf678e0 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -1,7 +1,7 @@
/*
* Driver for EETI eGalax Multiple Touch Controller
*
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
*
* based on max11801_ts.c
*
@@ -35,7 +35,7 @@
* which can only report one point at a given time.
* This driver will ignore events in this mode.
*/
-#define REPORT_MODE_MOUSE 0x1
+#define REPORT_MODE_SINGLE 0x1
/*
* Vendor Mode: this mode is used to transfer some vendor specific
* messages.
@@ -47,6 +47,8 @@
#define MAX_SUPPORT_POINTS 5
+#define EVENT_MODE 0
+#define EVENT_STATUS 1
#define EVENT_VALID_OFFSET 7
#define EVENT_VALID_MASK (0x1 << EVENT_VALID_OFFSET)
#define EVENT_ID_OFFSET 2
@@ -56,13 +58,21 @@
#define MAX_I2C_DATA_LEN 10
-#define EGALAX_MAX_X 32760
-#define EGALAX_MAX_Y 32760
+#define EGALAX_MAX_X 32767
+#define EGALAX_MAX_Y 32767
#define EGALAX_MAX_TRIES 100
+struct egalax_pointer {
+ bool valid;
+ bool status;
+ u16 x;
+ u16 y;
+};
+
struct egalax_ts {
struct i2c_client *client;
struct input_dev *input_dev;
+ struct egalax_pointer events[MAX_SUPPORT_POINTS];
};
static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
@@ -70,8 +80,9 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
struct egalax_ts *ts = dev_id;
struct input_dev *input_dev = ts->input_dev;
struct i2c_client *client = ts->client;
+ struct egalax_pointer *events = ts->events;
u8 buf[MAX_I2C_DATA_LEN];
- int id, ret, x, y, z;
+ int i, id, ret, x, y;
int tries = 0;
bool down, valid;
u8 state;
@@ -83,15 +94,38 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
if (ret < 0)
return IRQ_HANDLED;
- if (buf[0] != REPORT_MODE_MTTOUCH) {
- /* ignore mouse events and vendor events */
+ dev_dbg(&client->dev, "recv ret:%d", ret);
+ for (i = 0; i < MAX_I2C_DATA_LEN; i++)
+ dev_dbg(&client->dev, " %x ", buf[i]);
+
+ if (buf[0] != REPORT_MODE_VENDOR
+ && buf[0] != REPORT_MODE_SINGLE
+ && buf[0] != REPORT_MODE_MTTOUCH) {
+ /* invalid point */
+ return IRQ_HANDLED;
+ }
+
+ if (buf[0] == REPORT_MODE_VENDOR) {
+ dev_dbg(&client->dev, "vendor message, ignored\n");
return IRQ_HANDLED;
}
state = buf[1];
x = (buf[3] << 8) | buf[2];
y = (buf[5] << 8) | buf[4];
- z = (buf[7] << 8) | buf[6];
+
+ /* Currently, the panel Freescale using on SMD board _NOT_
+ * support single pointer mode. All event are going to
+ * multiple pointer mode. Add single pointer mode according
+ * to EETI eGalax I2C programming manual.
+ */
+ if (buf[0] == REPORT_MODE_SINGLE) {
+ input_report_abs(input_dev, ABS_X, x);
+ input_report_abs(input_dev, ABS_Y, y);
+ input_report_key(input_dev, BTN_TOUCH, !!state);
+ input_sync(input_dev);
+ return IRQ_HANDLED;
+ }
valid = state & EVENT_VALID_MASK;
id = (state & EVENT_ID_MASK) >> EVENT_ID_OFFSET;
@@ -102,19 +136,50 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
- input_mt_slot(input_dev, id);
- input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, down);
-
- dev_dbg(&client->dev, "%s id:%d x:%d y:%d z:%d",
- down ? "down" : "up", id, x, y, z);
-
if (down) {
- input_report_abs(input_dev, ABS_MT_POSITION_X, x);
- input_report_abs(input_dev, ABS_MT_POSITION_Y, y);
- input_report_abs(input_dev, ABS_MT_PRESSURE, z);
+ events[id].valid = valid;
+ events[id].status = down;
+ events[id].x = x;
+ events[id].y = y;
+
+#ifdef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
+ input_report_abs(input_dev, ABS_X, x);
+ input_report_abs(input_dev, ABS_Y, y);
+ input_event(ts->input_dev, EV_KEY, BTN_TOUCH, 1);
+ input_report_abs(input_dev, ABS_PRESSURE, 1);
+#endif
+ } else {
+ dev_dbg(&client->dev, "release id:%d\n", id);
+ events[id].valid = 0;
+ events[id].status = 0;
+#ifdef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
+ input_report_key(input_dev, BTN_TOUCH, 0);
+ input_report_abs(input_dev, ABS_PRESSURE, 0);
+#else
+ input_report_abs(input_dev, ABS_MT_TRACKING_ID, id);
+ input_event(input_dev, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
+ input_mt_sync(input_dev);
+#endif
}
- input_mt_report_pointer_emulation(input_dev, true);
+#ifndef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
+ /* report all pointers */
+ for (i = 0; i < MAX_SUPPORT_POINTS; i++) {
+ if (!events[i].valid)
+ continue;
+ dev_dbg(&client->dev, "report id:%d valid:%d x:%d y:%d",
+ i, valid, x, y);
+ input_report_abs(input_dev,
+ ABS_MT_TRACKING_ID, i);
+ input_report_abs(input_dev,
+ ABS_MT_TOUCH_MAJOR, 1);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_X, events[i].x);
+ input_report_abs(input_dev,
+ ABS_MT_POSITION_Y, events[i].y);
+ input_mt_sync(input_dev);
+ }
+#endif
input_sync(input_dev);
return IRQ_HANDLED;
@@ -203,22 +268,34 @@ static int egalax_ts_probe(struct i2c_client *client,
goto err_free_dev;
}
- input_dev->name = "EETI eGalax Touch Screen";
+ input_dev->name = "eGalax Touch Screen";
+ input_dev->phys = "I2C",
input_dev->id.bustype = BUS_I2C;
+ input_dev->id.vendor = 0x0EEF;
+ input_dev->id.product = 0x0020;
+ input_dev->id.version = 0x0001;
input_dev->dev.parent = &client->dev;
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(BTN_TOUCH, input_dev->keybit);
-
+ __set_bit(ABS_X, input_dev->absbit);
+ __set_bit(ABS_Y, input_dev->absbit);
+ __set_bit(ABS_PRESSURE, input_dev->absbit);
input_set_abs_params(input_dev, ABS_X, 0, EGALAX_MAX_X, 0, 0);
input_set_abs_params(input_dev, ABS_Y, 0, EGALAX_MAX_Y, 0, 0);
- input_set_abs_params(input_dev,
- ABS_MT_POSITION_X, 0, EGALAX_MAX_X, 0, 0);
- input_set_abs_params(input_dev,
- ABS_MT_POSITION_Y, 0, EGALAX_MAX_Y, 0, 0);
- input_mt_init_slots(input_dev, MAX_SUPPORT_POINTS, 0);
-
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, 1, 0, 0);
+
+#ifndef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+ 0, EGALAX_MAX_X, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+ 0, EGALAX_MAX_Y, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
+ MAX_SUPPORT_POINTS, 0, 0);
+#endif
input_set_drvdata(input_dev, ts);
error = request_threaded_irq(client->irq, NULL, egalax_ts_interrupt,