aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/touchscreen
diff options
context:
space:
mode:
authorLuwei <b45643@freescale.com>2013-08-08 04:35:24 -0400
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:01:06 -0400
commit40e015a51dc6d5c86e70faed921ecf8b5f2f9fe8 (patch)
treef6339fb34b32da722be89ab2776739f3917ac4ce /drivers/input/touchscreen
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/touchscreen')
-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 @@
1/* 1/*
2 * Driver for EETI eGalax Multiple Touch Controller 2 * Driver for EETI eGalax Multiple Touch Controller
3 * 3 *
4 * Copyright (C) 2011 Freescale Semiconductor, Inc. 4 * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
5 * 5 *
6 * based on max11801_ts.c 6 * based on max11801_ts.c
7 * 7 *
@@ -35,7 +35,7 @@
35 * which can only report one point at a given time. 35 * which can only report one point at a given time.
36 * This driver will ignore events in this mode. 36 * This driver will ignore events in this mode.
37 */ 37 */
38#define REPORT_MODE_MOUSE 0x1 38#define REPORT_MODE_SINGLE 0x1
39/* 39/*
40 * Vendor Mode: this mode is used to transfer some vendor specific 40 * Vendor Mode: this mode is used to transfer some vendor specific
41 * messages. 41 * messages.
@@ -47,6 +47,8 @@
47 47
48#define MAX_SUPPORT_POINTS 5 48#define MAX_SUPPORT_POINTS 5
49 49
50#define EVENT_MODE 0
51#define EVENT_STATUS 1
50#define EVENT_VALID_OFFSET 7 52#define EVENT_VALID_OFFSET 7
51#define EVENT_VALID_MASK (0x1 << EVENT_VALID_OFFSET) 53#define EVENT_VALID_MASK (0x1 << EVENT_VALID_OFFSET)
52#define EVENT_ID_OFFSET 2 54#define EVENT_ID_OFFSET 2
@@ -56,13 +58,21 @@
56 58
57#define MAX_I2C_DATA_LEN 10 59#define MAX_I2C_DATA_LEN 10
58 60
59#define EGALAX_MAX_X 32760 61#define EGALAX_MAX_X 32767
60#define EGALAX_MAX_Y 32760 62#define EGALAX_MAX_Y 32767
61#define EGALAX_MAX_TRIES 100 63#define EGALAX_MAX_TRIES 100
62 64
65struct egalax_pointer {
66 bool valid;
67 bool status;
68 u16 x;
69 u16 y;
70};
71
63struct egalax_ts { 72struct egalax_ts {
64 struct i2c_client *client; 73 struct i2c_client *client;
65 struct input_dev *input_dev; 74 struct input_dev *input_dev;
75 struct egalax_pointer events[MAX_SUPPORT_POINTS];
66}; 76};
67 77
68static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id) 78static 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)
70 struct egalax_ts *ts = dev_id; 80 struct egalax_ts *ts = dev_id;
71 struct input_dev *input_dev = ts->input_dev; 81 struct input_dev *input_dev = ts->input_dev;
72 struct i2c_client *client = ts->client; 82 struct i2c_client *client = ts->client;
83 struct egalax_pointer *events = ts->events;
73 u8 buf[MAX_I2C_DATA_LEN]; 84 u8 buf[MAX_I2C_DATA_LEN];
74 int id, ret, x, y, z; 85 int i, id, ret, x, y;
75 int tries = 0; 86 int tries = 0;
76 bool down, valid; 87 bool down, valid;
77 u8 state; 88 u8 state;
@@ -83,15 +94,38 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
83 if (ret < 0) 94 if (ret < 0)
84 return IRQ_HANDLED; 95 return IRQ_HANDLED;
85 96
86 if (buf[0] != REPORT_MODE_MTTOUCH) { 97 dev_dbg(&client->dev, "recv ret:%d", ret);
87 /* ignore mouse events and vendor events */ 98 for (i = 0; i < MAX_I2C_DATA_LEN; i++)
99 dev_dbg(&client->dev, " %x ", buf[i]);
100
101 if (buf[0] != REPORT_MODE_VENDOR
102 && buf[0] != REPORT_MODE_SINGLE
103 && buf[0] != REPORT_MODE_MTTOUCH) {
104 /* invalid point */
105 return IRQ_HANDLED;
106 }
107
108 if (buf[0] == REPORT_MODE_VENDOR) {
109 dev_dbg(&client->dev, "vendor message, ignored\n");
88 return IRQ_HANDLED; 110 return IRQ_HANDLED;
89 } 111 }
90 112
91 state = buf[1]; 113 state = buf[1];
92 x = (buf[3] << 8) | buf[2]; 114 x = (buf[3] << 8) | buf[2];
93 y = (buf[5] << 8) | buf[4]; 115 y = (buf[5] << 8) | buf[4];
94 z = (buf[7] << 8) | buf[6]; 116
117 /* Currently, the panel Freescale using on SMD board _NOT_
118 * support single pointer mode. All event are going to
119 * multiple pointer mode. Add single pointer mode according
120 * to EETI eGalax I2C programming manual.
121 */
122 if (buf[0] == REPORT_MODE_SINGLE) {
123 input_report_abs(input_dev, ABS_X, x);
124 input_report_abs(input_dev, ABS_Y, y);
125 input_report_key(input_dev, BTN_TOUCH, !!state);
126 input_sync(input_dev);
127 return IRQ_HANDLED;
128 }
95 129
96 valid = state & EVENT_VALID_MASK; 130 valid = state & EVENT_VALID_MASK;
97 id = (state & EVENT_ID_MASK) >> EVENT_ID_OFFSET; 131 id = (state & EVENT_ID_MASK) >> EVENT_ID_OFFSET;
@@ -102,19 +136,50 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
102 return IRQ_HANDLED; 136 return IRQ_HANDLED;
103 } 137 }
104 138
105 input_mt_slot(input_dev, id);
106 input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, down);
107
108 dev_dbg(&client->dev, "%s id:%d x:%d y:%d z:%d",
109 down ? "down" : "up", id, x, y, z);
110
111 if (down) { 139 if (down) {
112 input_report_abs(input_dev, ABS_MT_POSITION_X, x); 140 events[id].valid = valid;
113 input_report_abs(input_dev, ABS_MT_POSITION_Y, y); 141 events[id].status = down;
114 input_report_abs(input_dev, ABS_MT_PRESSURE, z); 142 events[id].x = x;
143 events[id].y = y;
144
145#ifdef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
146 input_report_abs(input_dev, ABS_X, x);
147 input_report_abs(input_dev, ABS_Y, y);
148 input_event(ts->input_dev, EV_KEY, BTN_TOUCH, 1);
149 input_report_abs(input_dev, ABS_PRESSURE, 1);
150#endif
151 } else {
152 dev_dbg(&client->dev, "release id:%d\n", id);
153 events[id].valid = 0;
154 events[id].status = 0;
155#ifdef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
156 input_report_key(input_dev, BTN_TOUCH, 0);
157 input_report_abs(input_dev, ABS_PRESSURE, 0);
158#else
159 input_report_abs(input_dev, ABS_MT_TRACKING_ID, id);
160 input_event(input_dev, EV_ABS, ABS_MT_TOUCH_MAJOR, 0);
161 input_mt_sync(input_dev);
162#endif
115 } 163 }
116 164
117 input_mt_report_pointer_emulation(input_dev, true); 165#ifndef CONFIG_TOUCHSCREEN_EGALAX_SINGLE_TOUCH
166 /* report all pointers */
167 for (i = 0; i < MAX_SUPPORT_POINTS; i++) {
168 if (!events[i].valid)
169 continue;
170 dev_dbg(&client->dev, "report id:%d valid:%d x:%d y:%d",
171 i, valid, x, y);
172 input_report_abs(input_dev,
173 ABS_MT_TRACKING_ID, i);
174 input_report_abs(input_dev,
175 ABS_MT_TOUCH_MAJOR, 1);
176 input_report_abs(input_dev,
177 ABS_MT_POSITION_X, events[i].x);
178 input_report_abs(input_dev,
179 ABS_MT_POSITION_Y, events[i].y);
180 input_mt_sync(input_dev);
181 }
182#endif
118 input_sync(input_dev); 183 input_sync(input_dev);
119 184
120 return IRQ_HANDLED; 185 return IRQ_HANDLED;
@@ -203,22 +268,34 @@ static int egalax_ts_probe(struct i2c_client *client,
203 goto err_free_dev; 268 goto err_free_dev;
204 } 269 }
205 270
206 input_dev->name = "EETI eGalax Touch Screen"; 271 input_dev->name = "eGalax Touch Screen";
272 input_dev->phys = "I2C",
207 input_dev->id.bustype = BUS_I2C; 273 input_dev->id.bustype = BUS_I2C;
274 input_dev->id.vendor = 0x0EEF;
275 input