aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/elantech.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/mouse/elantech.c')
-rw-r--r--drivers/input/mouse/elantech.c48
1 files changed, 41 insertions, 7 deletions
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 6ab0eb1ada1c..4bc78892ba91 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Elantech Touchpad driver (v5) 2 * Elantech Touchpad driver (v6)
3 * 3 *
4 * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net> 4 * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published 7 * under the terms of the GNU General Public License version 2 as published
@@ -178,6 +178,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
178 struct elantech_data *etd = psmouse->private; 178 struct elantech_data *etd = psmouse->private;
179 unsigned char *packet = psmouse->packet; 179 unsigned char *packet = psmouse->packet;
180 int fingers; 180 int fingers;
181 static int old_fingers;
181 182
182 if (etd->fw_version_maj == 0x01) { 183 if (etd->fw_version_maj == 0x01) {
183 /* byte 0: D U p1 p2 1 p3 R L 184 /* byte 0: D U p1 p2 1 p3 R L
@@ -190,6 +191,14 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
190 fingers = (packet[0] & 0xc0) >> 6; 191 fingers = (packet[0] & 0xc0) >> 6;
191 } 192 }
192 193
194 if (etd->jumpy_cursor) {
195 /* Discard packets that are likely to have bogus coordinates */
196 if (fingers > old_fingers) {
197 elantech_debug("elantech.c: discarding packet\n");
198 goto discard_packet_v1;
199 }
200 }
201
193 input_report_key(dev, BTN_TOUCH, fingers != 0); 202 input_report_key(dev, BTN_TOUCH, fingers != 0);
194 203
195 /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 204 /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0
@@ -216,6 +225,9 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
216 } 225 }
217 226
218 input_sync(dev); 227 input_sync(dev);
228
229 discard_packet_v1:
230 old_fingers = fingers;
219} 231}
220 232
221/* 233/*
@@ -363,9 +375,14 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
363 rc = -1; 375 rc = -1;
364 break; 376 break;
365 } 377 }
378 }
379
380 if (rc == 0) {
366 /* 381 /*
367 * Read back reg 0x10. The touchpad is probably initalising 382 * Read back reg 0x10. For hardware version 1 we must make
368 * and not ready until we read back the value we just wrote. 383 * sure the absolute mode bit is set. For hardware version 2
384 * the touchpad is probably initalising and not ready until
385 * we read back the value we just wrote.
369 */ 386 */
370 do { 387 do {
371 rc = elantech_read_reg(psmouse, 0x10, &val); 388 rc = elantech_read_reg(psmouse, 0x10, &val);
@@ -373,12 +390,18 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse)
373 break; 390 break;
374 tries--; 391 tries--;
375 elantech_debug("elantech.c: retrying read (%d).\n", 392 elantech_debug("elantech.c: retrying read (%d).\n",
376 tries); 393 tries);
377 msleep(ETP_READ_BACK_DELAY); 394 msleep(ETP_READ_BACK_DELAY);
378 } while (tries > 0); 395 } while (tries > 0);
379 if (rc) 396
397 if (rc) {
380 pr_err("elantech.c: failed to read back register 0x10.\n"); 398 pr_err("elantech.c: failed to read back register 0x10.\n");
381 break; 399 } else if (etd->hw_version == 1 &&
400 !(val & ETP_R10_ABSOLUTE_MODE)) {
401 pr_err("elantech.c: touchpad refuses "
402 "to switch to absolute mode.\n");
403 rc = -1;
404 }
382 } 405 }
383 406
384 if (rc) 407 if (rc)
@@ -662,6 +685,17 @@ int elantech_init(struct psmouse *psmouse)
662 param[0], param[1], param[2]); 685 param[0], param[1], param[2]);
663 etd->capabilities = param[0]; 686 etd->capabilities = param[0];
664 687
688 /*
689 * This firmware seems to suffer from misreporting coordinates when
690 * a touch action starts causing the mouse cursor or scrolled page
691 * to jump. Enable a workaround.
692 */
693 if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) {
694 pr_info("elantech.c: firmware version 2.34 detected, "
695 "enabling jumpy cursor workaround\n");
696 etd->jumpy_cursor = 1;
697 }
698
665 if (elantech_set_absolute_mode(psmouse)) { 699 if (elantech_set_absolute_mode(psmouse)) {
666 pr_err("elantech.c: failed to put touchpad into absolute mode.\n"); 700 pr_err("elantech.c: failed to put touchpad into absolute mode.\n");
667 goto init_fail; 701 goto init_fail;