aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-07-30 01:34:47 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-07-30 01:34:47 -0400
commitcf45b5a2525d9e7473db955750a8db9d4160b6ab (patch)
treefa0d5db50adfbf4906313567c9f8f72984fadb0e /drivers/input
parent314820c9e892d8f41ba4db300ec96770d9c8294b (diff)
parentc0394506e69b37c47d391c2a7bbea3ea236d8ec8 (diff)
Merge branch 'next' into for-linus
Prepare second set of changes for 3.6 merge window.
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/mouse/synaptics.c22
-rw-r--r--drivers/input/tablet/wacom_wac.c21
-rw-r--r--drivers/input/tablet/wacom_wac.h3
-rw-r--r--drivers/input/touchscreen/Kconfig13
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c898
6 files changed, 955 insertions, 3 deletions
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index d5b390f75c9a..14eaecea2b70 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -40,11 +40,27 @@
40 * Note that newer firmware allows querying device for maximum useable 40 * Note that newer firmware allows querying device for maximum useable
41 * coordinates. 41 * coordinates.
42 */ 42 */
43#define XMIN 0
44#define XMAX 6143
45#define YMIN 0
46#define YMAX 6143
43#define XMIN_NOMINAL 1472 47#define XMIN_NOMINAL 1472
44#define XMAX_NOMINAL 5472 48#define XMAX_NOMINAL 5472
45#define YMIN_NOMINAL 1408 49#define YMIN_NOMINAL 1408
46#define YMAX_NOMINAL 4448 50#define YMAX_NOMINAL 4448
47 51
52/* Size in bits of absolute position values reported by the hardware */
53#define ABS_POS_BITS 13
54
55/*
56 * Any position values from the hardware above the following limits are
57 * treated as "wrapped around negative" values that have been truncated to
58 * the 13-bit reporting range of the hardware. These are just reasonable
59 * guesses and can be adjusted if hardware is found that operates outside
60 * of these parameters.
61 */
62#define X_MAX_POSITIVE (((1 << ABS_POS_BITS) + XMAX) / 2)
63#define Y_MAX_POSITIVE (((1 << ABS_POS_BITS) + YMAX) / 2)
48 64
49/***************************************************************************** 65/*****************************************************************************
50 * Stuff we need even when we do not want native Synaptics support 66 * Stuff we need even when we do not want native Synaptics support
@@ -588,6 +604,12 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
588 hw->right = (buf[0] & 0x02) ? 1 : 0; 604 hw->right = (buf[0] & 0x02) ? 1 : 0;
589 } 605 }
590 606
607 /* Convert wrap-around values to negative */
608 if (hw->x > X_MAX_POSITIVE)
609 hw->x -= 1 << ABS_POS_BITS;
610 if (hw->y > Y_MAX_POSITIVE)
611 hw->y -= 1 << ABS_POS_BITS;
612
591 return 0; 613 return 0;
592} 614}
593 615
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 6533f44be5bd..002041975de9 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -464,7 +464,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
464 t = (data[6] << 2) | ((data[7] >> 6) & 3); 464 t = (data[6] << 2) | ((data[7] >> 6) & 3);
465 if ((features->type >= INTUOS4S && features->type <= INTUOS4L) || 465 if ((features->type >= INTUOS4S && features->type <= INTUOS4L) ||
466 (features->type >= INTUOS5S && features->type <= INTUOS5L) || 466 (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
467 features->type == WACOM_21UX2 || features->type == WACOM_24HD) { 467 (features->type >= WACOM_21UX2 && features->type <= WACOM_24HD)) {
468 t = (t << 1) | (data[1] & 1); 468 t = (t << 1) | (data[1] & 1);
469 } 469 }
470 input_report_abs(input, ABS_PRESSURE, t); 470 input_report_abs(input, ABS_PRESSURE, t);
@@ -614,7 +614,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
614 input_report_abs(input, ABS_MISC, 0); 614 input_report_abs(input, ABS_MISC, 0);
615 } 615 }
616 } else { 616 } else {
617 if (features->type == WACOM_21UX2) { 617 if (features->type == WACOM_21UX2 || features->type == WACOM_22HD) {
618 input_report_key(input, BTN_0, (data[5] & 0x01)); 618 input_report_key(input, BTN_0, (data[5] & 0x01));
619 input_report_key(input, BTN_1, (data[6] & 0x01)); 619 input_report_key(input, BTN_1, (data[6] & 0x01));
620 input_report_key(input, BTN_2, (data[6] & 0x02)); 620 input_report_key(input, BTN_2, (data[6] & 0x02));
@@ -633,6 +633,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
633 input_report_key(input, BTN_Z, (data[8] & 0x20)); 633 input_report_key(input, BTN_Z, (data[8] & 0x20));
634 input_report_key(input, BTN_BASE, (data[8] & 0x40)); 634 input_report_key(input, BTN_BASE, (data[8] & 0x40));
635 input_report_key(input, BTN_BASE2, (data[8] & 0x80)); 635 input_report_key(input, BTN_BASE2, (data[8] & 0x80));
636
637 if (features->type == WACOM_22HD) {
638 input_report_key(input, KEY_PROG1, data[9] & 0x01);
639 input_report_key(input, KEY_PROG2, data[9] & 0x02);
640 input_report_key(input, KEY_PROG3, data[9] & 0x04);
641 }
636 } else { 642 } else {
637 input_report_key(input, BTN_0, (data[5] & 0x01)); 643 input_report_key(input, BTN_0, (data[5] & 0x01));
638 input_report_key(input, BTN_1, (data[5] & 0x02)); 644 input_report_key(input, BTN_1, (data[5] & 0x02));
@@ -1231,6 +1237,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
1231 case CINTIQ: 1237 case CINTIQ:
1232 case WACOM_BEE: 1238 case WACOM_BEE:
1233 case WACOM_21UX2: 1239 case WACOM_21UX2:
1240 case WACOM_22HD:
1234 case WACOM_24HD: 1241 case WACOM_24HD:
1235 sync = wacom_intuos_irq(wacom_wac); 1242 sync = wacom_intuos_irq(wacom_wac);
1236 break; 1243 break;
@@ -1432,6 +1439,12 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
1432 wacom_setup_cintiq(wacom_wac); 1439 wacom_setup_cintiq(wacom_wac);
1433 break; 1440 break;
1434 1441
1442 case WACOM_22HD:
1443 __set_bit(KEY_PROG1, input_dev->keybit);
1444 __set_bit(KEY_PROG2, input_dev->keybit);
1445 __set_bit(KEY_PROG3, input_dev->keybit);
1446 /* fall through */
1447
1435 case WACOM_21UX2: 1448 case WACOM_21UX2:
1436 __set_bit(BTN_A, input_dev->keybit); 1449 __set_bit(BTN_A, input_dev->keybit);
1437 __set_bit(BTN_B, input_dev->keybit); 1450 __set_bit(BTN_B, input_dev->keybit);
@@ -1858,6 +1871,9 @@ static const struct wacom_features wacom_features_0xF0 =
1858static const struct wacom_features wacom_features_0xCC = 1871static const struct wacom_features wacom_features_0xCC =
1859 { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 1872 { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047,
1860 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; 1873 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
1874static const struct wacom_features wacom_features_0xFA =
1875 { "Wacom Cintiq 22HD", WACOM_PKGLEN_INTUOS, 95840, 54260, 2047,
1876 63, WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
1861static const struct wacom_features wacom_features_0x90 = 1877static const struct wacom_features wacom_features_0x90 =
1862 { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 1878 { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255,
1863 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; 1879 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2075,6 +2091,7 @@ const struct usb_device_id wacom_ids[] = {
2075 { USB_DEVICE_WACOM(0xEF) }, 2091 { USB_DEVICE_WACOM(0xEF) },
2076 { USB_DEVICE_WACOM(0x47) }, 2092 { USB_DEVICE_WACOM(0x47) },
2077 { USB_DEVICE_WACOM(0xF4) }, 2093 { USB_DEVICE_WACOM(0xF4) },
2094 { USB_DEVICE_WACOM(0xFA) },
2078 { USB_DEVICE_LENOVO(0x6004) }, 2095 { USB_DEVICE_LENOVO(0x6004) },
2079 { } 2096 { }
2080}; 2097};
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index bd5d37b28714..96c185cc301e 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -73,8 +73,9 @@ enum {
73 INTUOS5S, 73 INTUOS5S,
74 INTUOS5, 74 INTUOS5,
75 INTUOS5L, 75 INTUOS5L,
76 WACOM_24HD,
77 WACOM_21UX2, 76 WACOM_21UX2,
77 WACOM_22HD,
78 WACOM_24HD,
78 CINTIQ, 79 CINTIQ,
79 WACOM_BEE, 80 WACOM_BEE,
80 WACOM_MO, 81 WACOM_MO,
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 73bd2f6b82ec..1ba232cbc09d 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -472,6 +472,19 @@ config TOUCHSCREEN_PENMOUNT
472 To compile this driver as a module, choose M here: the 472 To compile this driver as a module, choose M here: the
473 module will be called penmount. 473 module will be called penmount.
474 474
475config TOUCHSCREEN_EDT_FT5X06
476 tristate "EDT FocalTech FT5x06 I2C Touchscreen support"
477 depends on I2C
478 help
479 Say Y here if you have an EDT "Polytouch" touchscreen based
480 on the FocalTech FT5x06 family of controllers connected to
481 your system.
482
483 If unsure, say N.
484
485 To compile this driver as a module, choose M here: the
486 module will be called edt-ft5x06.
487
475config TOUCHSCREEN_MIGOR 488config TOUCHSCREEN_MIGOR
476 tristate "Renesas MIGO-R touchscreen" 489 tristate "Renesas MIGO-R touchscreen"
477 depends on SH_MIGOR && I2C 490 depends on SH_MIGOR && I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 5920c60f999d..178eb128d90f 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_TOUCHSCREEN_CYTTSP_SPI) += cyttsp_spi.o
24obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o 24obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
25obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o 25obj-$(CONFIG_TOUCHSCREEN_DA9052) += da9052_tsi.o
26obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o 26obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
27obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o
27obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o 28obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
28obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o 29obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
29obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o 30obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
diff --git a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
new file mode 100644
index 000000000000..9afc777a40a7
--- /dev/null
+++ b/drivers/input/touchscreen/edt-ft5x06.c
@@ -0,0 +1,898 @@
1/*
2 * Copyright (C) 2012 Simon Budig, <simon.budig@kernelconcepts.de>
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
18/*
19 * This is a driver for the EDT "Polytouch" family of touch controllers
20 * based on the FocalTech FT5x06 line of chips.
21 *
22 * Development of this driver has been sponsored by Glyn:
23 * http://www.glyn.com/Products/Displays
24 */
25
26#include <linux/module.h>
27#include <linux/ratelimit.h>
28#include <linux/interrupt.h>
29#include <linux/input.h>
30#include <linux/i2c.h>
31#include <linux/uaccess.h>
32#include <linux/delay.h>
33#include <linux/debugfs.h>
34#include <linux/slab.h>
35#include <linux/gpio.h>
36#include <linux/input/mt.h>
37#include <linux/input/edt-ft5x06.h>
38
39#define MAX_SUPPORT_POINTS 5
40
41#define WORK_REGISTER_THRESHOLD 0x00
42#define WORK_REGISTER_REPORT_RATE 0x08
43#define WORK_REGISTER_GAIN 0x30
44#define WORK_REGISTER_OFFSET 0x31
45#define WORK_REGISTER_NUM_X 0x33
46#define WORK_REGISTER_NUM_Y 0x34
47
48#define WORK_REGISTER_OPMODE 0x3c
49#define FACTORY_REGISTER_OPMODE 0x01
50
51#define TOUCH_EVENT_DOWN 0x00
52#define TOUCH_EVENT_UP 0x01
53#define TOUCH_EVENT_ON 0x02
54#define TOUCH_EVENT_RESERVED 0x03
55
56#define EDT_NAME_LEN 23
57#define EDT_SWITCH_MODE_RETRIES 10
58#define EDT_SWITCH_MODE_DELAY 5 /* msec */
59#define EDT_RAW_DATA_RETRIES 100
60#define EDT_RAW_DATA_DELAY 1 /* msec */
61
62struct edt_ft5x06_ts_data {
63 struct i2c_client *client;
64 struct input_dev *input;
65 u16 num_x;
66 u16 num_y;
67
68#if defined(CONFIG_DEBUG_FS)
69 struct dentry *debug_dir;
70 u8 *raw_buffer;
71 size_t raw_bufsize;
72#endif
73
74 struct mutex mutex;
75 bool factory_mode;
76 int threshold;
77 int gain;
78 int offset;
79 int report_rate;
80
81 char name[EDT_NAME_LEN];
82};
83
84static int edt_ft5x06_ts_readwrite(struct i2c_client *client,
85 u16 wr_len, u8 *wr_buf,
86 u16 rd_len, u8 *rd_buf)
87{
88 struct i2c_msg wrmsg[2];
89 int i = 0;
90 int ret;
91
92 if (wr_len) {
93 wrmsg[i].addr = client->addr;
94 wrmsg[i].flags = 0;
95 wrmsg[i].len = wr_len;
96 wrmsg[i].buf = wr_buf;
97 i++;
98 }
99 if (rd_len) {
100 wrmsg[i].addr = client->addr;
101 wrmsg[i].flags = I2C_M_RD;
102 wrmsg[i].len = rd_len;
103 wrmsg[i].buf = rd_buf;
104 i++;
105 }
106
107 ret = i2c_transfer(client->adapter, wrmsg, i);
108 if (ret < 0)
109 return ret;
110 if (ret != i)
111 return -EIO;
112
113 return 0;
114}
115
116static bool edt_ft5x06_ts_check_crc(struct edt_ft5x06_ts_data *tsdata,
117 u8 *buf, int buflen)
118{
119 int i;
120 u8 crc = 0;
121
122 for (i = 0; i < buflen - 1; i++)
123 crc ^= buf[i];
124
125 if (crc != buf[buflen-1]) {
126 dev_err_ratelimited(&tsdata->client->dev,
127 "crc error: 0x%02x expected, got 0x%02x\n",
128 crc, buf[buflen-1]);
129 return false;
130 }
131
132 return true;
133}
134
135static irqreturn_t edt_ft5x06_ts_isr(int irq, void *dev_id)
136{
137 struct edt_ft5x06_ts_data *tsdata = dev_id;
138 struct device *dev = &tsdata->client->dev;
139 u8 cmd = 0xf9;
140 u8 rdbuf[26];
141 int i, type, x, y, id;
142 int error;
143
144 memset(rdbuf, 0, sizeof(rdbuf));
145
146 error = edt_ft5x06_ts_readwrite(tsdata->client,
147 sizeof(cmd), &cmd,
148 sizeof(rdbuf), rdbuf);
149 if (error) {
150 dev_err_ratelimited(dev, "Unable to fetch data, error: %d\n",
151 error);
152 goto out;
153 }
154
155 if (rdbuf[0] != 0xaa || rdbuf[1] != 0xaa || rdbuf[2] != 26) {
156 dev_err_ratelimited(dev, "Unexpected header: %02x%02x%02x!\n",
157 rdbuf[0], rdbuf[1], rdbuf[2]);
158 goto out;
159 }
160
161 if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, 26))
162 goto out;
163
164 for (i = 0; i < MAX_SUPPORT_POINTS; i++) {
165 u8 *buf = &rdbuf[i * 4 + 5];
166 bool down;
167
168 type = buf[0] >> 6;
169 /* ignore Reserved events */
170 if (type == TOUCH_EVENT_RESERVED)
171 continue;
172
173 x = ((buf[0] << 8) | buf[1]) & 0x0fff;
174 y = ((buf[2] << 8) | buf[3]) & 0x0fff;
175 id = (buf[2] >> 4) & 0x0f;
176 down = (type != TOUCH_EVENT_UP);
177
178 input_mt_slot(tsdata->input, id);
179 input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER, down);
180
181 if (!down)
182 continue;
183
184 input_report_abs(tsdata->input, ABS_MT_POSITION_X, x);
185 input_report_abs(tsdata->input, ABS_MT_POSITION_Y, y);
186 }
187
188 input_mt_report_pointer_emulation(tsdata->input, true);
189 input_sync(tsdata->input);
190
191out:
192 return IRQ_HANDLED;
193}
194
195static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
196 u8 addr, u8 value)
197{
198 u8 wrbuf[4];
199
200 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
201 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
202 wrbuf[2] = value;
203 wrbuf[3] = wrbuf[0] ^ wrbuf[1] ^ wrbuf[2];
204
205 return edt_ft5x06_ts_readwrite(tsdata->client, 4, wrbuf, 0, NULL);
206}
207
208static int edt_ft5x06_register_read(struct edt_ft5x06_ts_data *tsdata,
209 u8 addr)
210{
211 u8 wrbuf[2], rdbuf[2];
212 int error;
213
214 wrbuf[0] = tsdata->factory_mode ? 0xf3 : 0xfc;
215 wrbuf[1] = tsdata->factory_mode ? addr & 0x7f : addr & 0x3f;
216 wrbuf[1] |= tsdata->factory_mode ? 0x80 : 0x40;
217
218 error = edt_ft5x06_ts_readwrite(tsdata->client, 2, wrbuf, 2, rdbuf);
219 if (error)
220 return error;
221
222 if ((wrbuf[0] ^ wrbuf[1] ^ rdbuf[0]) != rdbuf[1]) {
223 dev_err(&tsdata->client->dev,
224 "crc error: 0x%02x expected, got 0x%02x\n",
225 wrbuf[0] ^ wrbuf[1] ^ rdbuf[0], rdbuf[1]);
226 return -EIO;
227 }
228
229 return rdbuf[0];
230}
231
232struct edt_ft5x06_attribute {
233 struct device_attribute dattr;
234 size_t field_offset;
235 u8 limit_low;
236 u8 limit_high;
237 u8 addr;
238};
239
240#define EDT_ATTR(_field, _mode, _addr, _limit_low, _limit_high) \
241 struct edt_ft5x06_attribute edt_ft5x06_attr_##_field = { \
242 .dattr = __ATTR(_field, _mode, \
243 edt_ft5x06_setting_show, \
244 edt_ft5x06_setting_store), \
245 .field_offset = \
246 offsetof(struct edt_ft5x06_ts_data, _field), \
247 .limit_low = _limit_low, \
248 .limit_high = _limit_high, \
249 .addr = _addr, \
250 }
251
252static ssize_t edt_ft5x06_setting_show(struct device *dev,
253 struct device_attribute *dattr,
254 char *buf)
255{
256 struct i2c_client *client = to_i2c_client(dev);
257 struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
258 struct edt_ft5x06_attribute *attr =
259 container_of(dattr, struct edt_ft5x06_attribute, dattr);
260 u8 *field = (u8 *)((char *)tsdata + attr->field_offset);
261 int val;
262 size_t count = 0;
263 int error = 0;
264
265 mutex_lock(&tsdata->mutex);
266
267 if (tsdata->factory_mode) {
268 error = -EIO;
269 goto out;
270 }
271
272 val = edt_ft5x06_register_read(tsdata, attr->addr);
273 if (val < 0) {
274 error = val;
275 dev_err(&tsdata->client->dev,
276 "Failed to fetch attribute %s, error %d\n",
277 dattr->attr.name, error);
278 goto out;
279 }
280
281 if (val != *field) {
282 dev_warn(&tsdata->client->dev,
283 "%s: read (%d) and stored value (%d) differ\n",
284 dattr->attr.name, val, *field);
285 *field = val;
286 }
287
288 count = scnprintf(buf, PAGE_SIZE, "%d\n", val);
289out:
290 mutex_unlock(&tsdata->mutex);
291 return error ?: count;
292}
293
294static ssize_t edt_ft5x06_setting_store(struct device *dev,
295 struct device_attribute *dattr,
296 const char *buf, size_t count)
297{
298 struct i2c_client *client = to_i2c_client(dev);
299 struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
300 struct edt_ft5x06_attribute *attr =
301 container_of(dattr, struct edt_ft5x06_attribute, dattr);
302 u8 *field = (u8 *)((char *)tsdata + attr->field_offset);
303 unsigned int val;
304 int error;
305
306 mutex_lock(&tsdata->mutex);
307
308 if (tsdata->factory_mode) {
309 error = -EIO;
310 goto out;
311 }
312
313 error = kstrtouint(buf, 0, &val);
314 if (error)
315 goto out;
316
317 if (val < attr->limit_low || val > attr->limit_high) {
318 error = -ERANGE;
319 goto out;
320 }
321
322 error = edt_ft5x06_register_write(tsdata, attr->addr, val);
323 if (error) {
324 dev_err(&tsdata->client->dev,
325 "Failed to update attribute %s, error: %d\n",
326 dattr->attr.name, error);
327 goto out;
328 }
329
330 *field = val;
331
332out:
333 mutex_unlock(&tsdata->mutex);
334 return error ?: count;
335}
336
337static EDT_ATTR(gain, S_IWUSR | S_IRUGO, WORK_REGISTER_GAIN, 0, 31);
338static EDT_ATTR(offset, S_IWUSR | S_IRUGO, WORK_REGISTER_OFFSET, 0, 31);
339static EDT_ATTR(threshold, S_IWUSR | S_IRUGO,
340 WORK_REGISTER_THRESHOLD, 20, 80);
341static EDT_ATTR(report_rate, S_IWUSR | S_IRUGO,
342 WORK_REGISTER_REPORT_RATE, 3, 14);
343
344static struct attribute *edt_ft5x06_attrs[] = {
345 &edt_ft5x06_attr_gain.dattr.attr,
346 &edt_ft5x06_attr_offset.dattr.attr,
347 &edt_ft5x06_attr_threshold.dattr.attr,
348 &edt_ft5x06_attr_report_rate.dattr.attr,
349 NULL
350};
351
352static const struct attribute_group edt_ft5x06_attr_group = {
353 .attrs = edt_ft5x06_attrs,
354};
355
356#ifdef CONFIG_DEBUG_FS
357static int edt_ft5x06_factory_mode(struct edt_ft5x06_ts_data *tsdata)
358{
359 struct i2c_client *client = tsdata->client;
360 int retries = EDT_SWITCH_MODE_RETRIES;
361 int ret;
362 int error;
363
364 disable_irq(client->irq);
365
366 if (!tsdata->raw_buffer) {
367 tsdata->raw_bufsize = tsdata->num_x * tsdata->num_y *
368 sizeof(u16);
369 tsdata->raw_buffer = kzalloc(tsdata->raw_bufsize, GFP_KERNEL);
370 if (!tsdata->raw_buffer) {
371 error = -ENOMEM;
372 goto err_out;
373 }
374 }
375
376 /* mode register is 0x3c when in the work mode */
377 error = edt_ft5x06_register_write(tsdata, WORK_REGISTER_OPMODE, 0x03);
378 if (error) {
379 dev_err(&client->dev,
380 "failed to switch to factory mode, error %d\n", error);
381 goto err_out;
382 }
383
384 tsdata->factory_mode = true;
385 do {
386 mdelay(EDT_SWITCH_MODE_DELAY);
387 /* mode register is 0x01 when in factory mode */
388 ret = edt_ft5x06_register_read(tsdata, FACTORY_REGISTER_OPMODE);
389 if (ret == 0x03)
390 break;
391 } while (--retries > 0);
392
393 if (retries == 0) {
394 dev_err(&client->dev, "not in factory mode after %dms.\n",
395 EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY);
396 error = -EIO;
397 goto err_out;
398 }
399
400 return 0;
401
402err_out:
403 kfree(tsdata->raw_buffer);
404 tsdata->raw_buffer = NULL;
405 tsdata->factory_mode = false;
406 enable_irq(client->irq);
407
408 return error;
409}
410
411static int edt_ft5x06_work_mode(struct edt_ft5x06_ts_data *tsdata)
412{
413 struct i2c_client *client = tsdata->client;
414 int retries = EDT_SWITCH_MODE_RETRIES;
415 int ret;
416 int error;
417
418 /* mode register is 0x01 when in the factory mode */
419 error = edt_ft5x06_register_write(tsdata, FACTORY_REGISTER_OPMODE, 0x1);
420 if (error) {
421 dev_err(&client->dev,
422 "failed to switch to work mode, error: %d\n", error);
423 return error;
424 }
425
426 tsdata->factory_mode = false;
427
428 do {
429 mdelay(EDT_SWITCH_MODE_DELAY);
430 /* mode register is 0x01 when in factory mode */
431 ret = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OPMODE);
432 if (ret == 0x01)
433 break;
434 } while (--retries > 0);
435
436 if (retries == 0) {
437 dev_err(&client->dev, "not in work mode after %dms.\n",
438 EDT_SWITCH_MODE_RETRIES * EDT_SWITCH_MODE_DELAY);
439 tsdata->factory_mode = true;
440 return -EIO;
441 }
442
443 if (tsdata->raw_buffer)
444 kfree(tsdata->raw_buffer);
445 tsdata->raw_buffer = NULL;
446
447 /* restore parameters */
448 edt_ft5x06_register_write(tsdata, WORK_REGISTER_THRESHOLD,
449 tsdata->threshold);
450 edt_ft5x06_register_write(tsdata, WORK_REGISTER_GAIN,
451 tsdata->gain);
452 edt_ft5x06_register_write(tsdata, WORK_REGISTER_OFFSET,
453 tsdata->offset);
454 edt_ft5x06_register_write(tsdata, WORK_REGISTER_REPORT_RATE,
455 tsdata->report_rate);
456
457 enable_irq(client->irq);
458
459 return 0;
460}
461
462static int edt_ft5x06_debugfs_mode_get(void *data, u64 *mode)
463{
464 struct edt_ft5x06_ts_data *tsdata = data;
465
466 *mode = tsdata->factory_mode;
467
468 return 0;
469};
470
471static int edt_ft5x06_debugfs_mode_set(void *data, u64 mode)
472{
473 struct edt_ft5x06_ts_data *tsdata = data;
474 int retval = 0;
475
476 if (mode > 1)
477 return -ERANGE;
478
479 mutex_lock(&tsdata->mutex);
480
481 if (mode != tsdata->factory_mode) {
482 retval = mode ? edt_ft5x06_factory_mode(tsdata) :
483 edt_ft5x06_work_mode(tsdata);
484 }
485
486 mutex_unlock(&tsdata->mutex);
487
488 return retval;
489};
490
491DEFINE_SIMPLE_ATTRIBUTE(debugfs_mode_fops, edt_ft5x06_debugfs_mode_get,
492 edt_ft5x06_debugfs_mode_set, "%llu\n");
493
494static int edt_ft5x06_debugfs_raw_data_open(struct inode *inode,
495 struct file *file)
496{
497 file->private_data = inode->i_private;
498
499 return 0;
500}
501
502static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
503 char __user *buf, size_t count, loff_t *off)
504{
505 struct edt_ft5x06_ts_data *tsdata = file->private_data;
506 struct i2c_client *client = tsdata->client;
507 int retries = EDT_RAW_DATA_RETRIES;
508 int val, i, error;
509 size_t read = 0;
510 int colbytes;
511 char wrbuf[3];
512 u8 *rdbuf;
513
514 if (*off < 0 || *off >= tsdata->raw_bufsize)
515 return 0;
516
517 mutex_lock(&tsdata->mutex);
518
519 if (!tsdata->factory_mode || !tsdata->raw_buffer) {
520 error = -EIO;
521 goto out;
522 }
523
524 error = edt_ft5x06_register_write(tsdata, 0x08, 0x01);
525 if (error) {
526 dev_dbg(&client->dev,
527 "failed to write 0x08 register, error %d\n", error);
528 goto out;
529 }
530
531 do {
532 msleep(EDT_RAW_DATA_DELAY);
533 val = edt_ft5x06_register_read(tsdata, 0x08);
534 if (val < 1)
535 break;
536 } while (--retries > 0);
537
538 if (val < 0) {
539 error = val;
540 dev_dbg(&client->dev,
541 "failed to read 0x08 register, error %d\n", error);
542 goto out;
543 }
544
545 if (retries == 0) {
546 dev_dbg(&client->dev,
547 "timed out waiting for register to settle\n");
548 error = -ETIMEDOUT;
549 goto out;
550 }
551
552 rdbuf = tsdata->raw_buffer;
553 colbytes = tsdata->num_y * sizeof(u16);
554
555 wrbuf[0] = 0xf5;
556 wrbuf[1] = 0x0e;
557 for (i = 0; i < tsdata->num_x; i++) {
558 wrbuf[2] = i; /* column index */
559 error = edt_ft5x06_ts_readwrite(tsdata->client,
560 sizeof(wrbuf), wrbuf,
561 colbytes, rdbuf);
562 if (error)
563 goto out;
564
565 rdbuf += colbytes;
566 }
567
568 read = min_t(size_t, count, tsdata->raw_bufsize - *off);
569 error = copy_to_user(buf, tsdata->raw_buffer + *off, read);
570 if (!error)
571 *off += read;
572out:
573 mutex_unlock(&tsdata->mutex);
574 return error ?: read;
575};
576
577
578static const struct file_operations debugfs_raw_data_fops = {
579 .open = edt_ft5x06_debugfs_raw_data_open,
580 .read = edt_ft5x06_debugfs_raw_data_read,
581};
582
583static void __devinit
584edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
585 const char *debugfs_name)
586{
587 tsdata->debug_dir = debugfs_create_dir(debugfs_name, NULL);
588 if (!tsdata->debug_dir)
589 return;
590
591 debugfs_create_u16("num_x", S_IRUSR, tsdata->debug_dir, &tsdata->num_x);
592 debugfs_create_u16("num_y", S_IRUSR, tsdata->debug_dir, &tsdata->num_y);
593
594 debugfs_create_file("mode", S_IRUSR | S_IWUSR,
595 tsdata->debug_dir, tsdata, &debugfs_mode_fops);
596 debugfs_create_file("raw_data", S_IRUSR,
597 tsdata->debug_dir, tsdata, &debugfs_raw_data_fops);
598}
599
600static void __devexit
601edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
602{
603 if (tsdata->debug_dir)
604 debugfs_remove_recursive(tsdata->debug_dir);
605}
606
607#else
608
609static inline void
610edt_ft5x06_ts_prepare_debugfs(struct edt_ft5x06_ts_data *tsdata,
611 const char *debugfs_name)
612{
613}
614
615static inline void
616edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
617{
618}
619
620#endif /* CONFIG_DEBUGFS */
621
622
623
624static int __devinit edt_ft5x06_ts_reset(struct i2c_client *client,
625 int reset_pin)
626{
627 int error;
628
629 if (gpio_is_valid(reset_pin)) {
630 /* this pulls reset down, enabling the low active reset */
631 error = gpio_request_one(reset_pin, GPIOF_OUT_INIT_LOW,
632 "edt-ft5x06 reset");
633 if (error) {
634 dev_err(&client->dev,
635 "Failed to request GPIO %d as reset pin, error %d\n",
636 reset_pin, error);
637 return error;
638 }
639
640 mdelay(50);
641 gpio_set_value(reset_pin, 1);
642 mdelay(100);
643 }
644
645 return 0;
646}
647
648static int __devinit edt_ft5x06_ts_identify(struct i2c_client *client,
649 char *model_name,
650 char *fw_version)
651{
652 u8 rdbuf[EDT_NAME_LEN];
653 char *p;
654 int error;
655
656 error = edt_ft5x06_ts_readwrite(client, 1, "\xbb",
657 EDT_NAME_LEN - 1, rdbuf);
658 if (error)
659 return error;
660
661 /* remove last '$' end marker */
662 rdbuf[EDT_NAME_LEN - 1] = '\0';
663 if (rdbuf[EDT_NAME_LEN - 2] == '$')
664 rdbuf[EDT_NAME_LEN - 2] = '\0';
665
666 /* look for Model/Version separator */
667 p = strchr(rdbuf, '*');
668 if (p)
669 *p++ = '\0';
670
671 strlcpy(model_name, rdbuf + 1, EDT_NAME_LEN);
672 strlcpy(fw_version, p ? p : "", EDT_NAME_LEN);
673
674 return 0;
675}
676
677#define EDT_ATTR_CHECKSET(name, reg) \
678 if (pdata->name >= edt_ft5x06_attr_##name.limit_low && \
679 pdata->name <= edt_ft5x06_attr_##name.limit_high) \
680 edt_ft5x06_register_write(tsdata, reg, pdata->name)
681
682static void __devinit
683edt_ft5x06_ts_get_defaults(struct edt_ft5x06_ts_data *tsdata,
684 const struct edt_ft5x06_platform_data *pdata)
685{
686 if (!pdata->use_parameters)
687 return;
688
689 /* pick up defaults from the platform data */
690 EDT_ATTR_CHECKSET(threshold, WORK_REGISTER_THRESHOLD);
691 EDT_ATTR_CHECKSET(gain, WORK_REGISTER_GAIN);
692 EDT_ATTR_CHECKSET(offset, WORK_REGISTER_OFFSET);
693 EDT_ATTR_CHECKSET(report_rate, WORK_REGISTER_REPORT_RATE);
694}
695
696static void __devinit
697edt_ft5x06_ts_get_parameters(struct edt_ft5x06_ts_data *tsdata)
698{
699 tsdata->threshold = edt_ft5x06_register_read(tsdata,
700 WORK_REGISTER_THRESHOLD);
701 tsdata->gain = edt_ft5x06_register_read(tsdata, WORK_REGISTER_GAIN);
702 tsdata->offset = edt_ft5x06_register_read(tsdata, WORK_REGISTER_OFFSET);
703 tsdata->report_rate = edt_ft5x06_register_read(tsdata,
704 WORK_REGISTER_REPORT_RATE);
705 tsdata->num_x = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_X);
706 tsdata->num_y = edt_ft5x06_register_read(tsdata, WORK_REGISTER_NUM_Y);
707}
708
709static int __devinit edt_ft5x06_ts_probe(struct i2c_client *client,
710 const struct i2c_device_id *id)
711{
712 const struct edt_ft5x06_platform_data *pdata =
713 client->dev.platform_data;
714 struct edt_ft5x06_ts_data *tsdata;
715 struct input_dev *input;
716 int error;
717 char fw_version[EDT_NAME_LEN];
718
719 dev_dbg(&client->dev, "probing for EDT FT5x06 I2C\n");
720
721 if (!pdata) {
722 dev_err(&client->dev, "no platform data?\n");
723 return -EINVAL;
724 }
725
726 error = edt_ft5x06_ts_reset(client, pdata->reset_pin);
727 if (error)
728 return error;
729
730 if (gpio_is_valid(pdata->irq_pin)) {
731 error = gpio_request_one(pdata->irq_pin,
732 GPIOF_IN, "edt-ft5x06 irq");
733 if (error) {
734 dev_err(&client->dev,
735 "Failed to request GPIO %d, error %d\n",
736 pdata->irq_pin, error);
737 return error;
738 }
739 }
740
741 tsdata = kzalloc(sizeof(*tsdata), GFP_KERNEL);
742 input = input_allocate_device();
743 if (!tsdata || !input) {
744 dev_err(&client->dev, "failed to allocate driver data.\n");
745 error = -ENOMEM;
746 goto err_free_mem;
747 }
748
749 mutex_init(&tsdata->mutex);
750 tsdata->client = client;
751 tsdata->input = input;
752 tsdata->factory_mode = false;
753
754 error = edt_ft5x06_ts_identify(client, tsdata->name, fw_version);
755 if (error) {
756 dev_err(&client->dev, "touchscreen probe failed\n");
757 goto err_free_mem;
758 }
759
760 edt_ft5x06_ts_get_defaults(tsdata, pdata);
761 edt_ft5x06_ts_get_parameters(tsdata);
762
763 dev_dbg(&client->dev,
764 "Model \"%s\", Rev. \"%s\", %dx%d sensors\n",
765 tsdata->name, fw_version, tsdata->num_x, tsdata->num_y);
766
767 input->name = tsdata->name;
768 input->id.bustype = BUS_I2C;
769 input->dev.parent = &client->dev;
770
771 __set_bit(EV_SYN, input->evbit);
772 __set_bit(EV_KEY, input->evbit);
773 __set_bit(EV_ABS, input->evbit);
774 __set_bit(BTN_TOUCH, input->keybit);
775 input_set_abs_params(input, ABS_X, 0, tsdata->num_x * 64 - 1, 0, 0);
776 input_set_abs_params(input, ABS_Y, 0, tsdata->num_y * 64 - 1, 0, 0);
777 input_set_abs_params(input, ABS_MT_POSITION_X,
778 0, tsdata->num_x * 64 - 1, 0, 0);
779 input_set_abs_params(input, ABS_MT_POSITION_Y,
780 0, tsdata->num_y * 64 - 1, 0, 0);
781 error = input_mt_init_slots(input, MAX_SUPPORT_POINTS);
782 if (error) {
783 dev_err(&client->dev, "Unable to init MT slots.\n");
784 goto err_free_mem;
785 }
786
787 input_set_drvdata(input, tsdata);
788 i2c_set_clientdata(client, tsdata);
789
790 error = request_threaded_irq(client->irq, NULL, edt_ft5x06_ts_isr,
791 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
792 client->name, tsdata);
793 if (error) {
794 dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
795 goto err_free_mem;
796 }
797
798 error = sysfs_create_group(&client->dev.kobj, &edt_ft5x06_attr_group);
799 if (error)
800 goto err_free_irq;
801
802 error = input_register_device(input);
803 if (error)
804 goto err_remove_attrs;
805
806 edt_ft5x06_ts_prepare_debugfs(tsdata, dev_driver_string(&client->dev));
807 device_init_wakeup(&client->dev, 1);
808
809 dev_dbg(&client->dev,
810 "EDT FT5x06 initialized: IRQ pin %d, Reset pin %d.\n",
811 pdata->irq_pin, pdata->reset_pin);
812
813 return 0;
814
815err_remove_attrs:
816 sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group);
817err_free_irq:
818 free_irq(client->irq, tsdata);
819err_free_mem:
820 input_free_device(input);
821 kfree(tsdata);
822
823 if (gpio_is_valid(pdata->irq_pin))
824 gpio_free(pdata->irq_pin);
825
826 return error;
827}
828
829static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client)
830{
831 const struct edt_ft5x06_platform_data *pdata =
832 dev_get_platdata(&client->dev);
833 struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
834
835 edt_ft5x06_ts_teardown_debugfs(tsdata);
836 sysfs_remove_group(&client->dev.kobj, &edt_ft5x06_attr_group);
837
838 free_irq(client->irq, tsdata);
839 input_unregister_device(tsdata->input);
840
841 if (gpio_is_valid(pdata->irq_pin))
842 gpio_free(pdata->irq_pin);
843 if (gpio_is_valid(pdata->reset_pin))
844 gpio_free(pdata->reset_pin);
845
846 kfree(tsdata->raw_buffer);
847 kfree(tsdata);
848
849 return 0;
850}
851
852#ifdef CONFIG_PM_SLEEP
853static int edt_ft5x06_ts_suspend(struct device *dev)
854{
855 struct i2c_client *client = to_i2c_client(dev);
856
857 if (device_may_wakeup(dev))
858 enable_irq_wake(client->irq);
859
860 return 0;
861}
862
863static int edt_ft5x06_ts_resume(struct device *dev)
864{
865 struct i2c_client *client = to_i2c_client(dev);
866
867 if (device_may_wakeup(dev))
868 disable_irq_wake(client->irq);
869
870 return 0;
871}
872#endif
873
874static SIMPLE_DEV_PM_OPS(edt_ft5x06_ts_pm_ops,
875 edt_ft5x06_ts_suspend, edt_ft5x06_ts_resume);
876
877static const struct i2c_device_id edt_ft5x06_ts_id[] = {
878 { "edt-ft5x06", 0 },
879 { }
880};
881MODULE_DEVICE_TABLE(i2c, edt_ft5x06_ts_id);
882
883static struct i2c_driver edt_ft5x06_ts_driver = {
884 .driver = {
885 .owner = THIS_MODULE,
886 .name = "edt_ft5x06",
887 .pm = &edt_ft5x06_ts_pm_ops,
888 },
889 .id_table = edt_ft5x06_ts_id,
890 .probe = edt_ft5x06_ts_probe,
891 .remove = __devexit_p(edt_ft5x06_ts_remove),
892};
893
894module_i2c_driver(edt_ft5x06_ts_driver);
895
896MODULE_AUTHOR("Simon Budig <simon.budig@kernelconcepts.de>");
897MODULE_DESCRIPTION("EDT FT5x06 I2C Touchscreen Driver");
898MODULE_LICENSE("GPL");