diff options
Diffstat (limited to 'drivers/input/mouse/elantech.c')
-rw-r--r-- | drivers/input/mouse/elantech.c | 106 |
1 files changed, 68 insertions, 38 deletions
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index fda35e615abf..112b4ee52ff2 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
15 | #include <linux/input.h> | 16 | #include <linux/input.h> |
16 | #include <linux/serio.h> | 17 | #include <linux/serio.h> |
@@ -24,6 +25,10 @@ | |||
24 | printk(KERN_DEBUG format, ##arg); \ | 25 | printk(KERN_DEBUG format, ##arg); \ |
25 | } while (0) | 26 | } while (0) |
26 | 27 | ||
28 | static bool force_elantech; | ||
29 | module_param_named(force_elantech, force_elantech, bool, 0644); | ||
30 | MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); | ||
31 | |||
27 | /* | 32 | /* |
28 | * Send a Synaptics style sliced query command | 33 | * Send a Synaptics style sliced query command |
29 | */ | 34 | */ |
@@ -180,14 +185,18 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
180 | int fingers; | 185 | int fingers; |
181 | static int old_fingers; | 186 | static int old_fingers; |
182 | 187 | ||
183 | if (etd->fw_version_maj == 0x01) { | 188 | if (etd->fw_version < 0x020000) { |
184 | /* byte 0: D U p1 p2 1 p3 R L | 189 | /* |
185 | byte 1: f 0 th tw x9 x8 y9 y8 */ | 190 | * byte 0: D U p1 p2 1 p3 R L |
191 | * byte 1: f 0 th tw x9 x8 y9 y8 | ||
192 | */ | ||
186 | fingers = ((packet[1] & 0x80) >> 7) + | 193 | fingers = ((packet[1] & 0x80) >> 7) + |
187 | ((packet[1] & 0x30) >> 4); | 194 | ((packet[1] & 0x30) >> 4); |
188 | } else { | 195 | } else { |
189 | /* byte 0: n1 n0 p2 p1 1 p3 R L | 196 | /* |
190 | byte 1: 0 0 0 0 x9 x8 y9 y8 */ | 197 | * byte 0: n1 n0 p2 p1 1 p3 R L |
198 | * byte 1: 0 0 0 0 x9 x8 y9 y8 | ||
199 | */ | ||
191 | fingers = (packet[0] & 0xc0) >> 6; | 200 | fingers = (packet[0] & 0xc0) >> 6; |
192 | } | 201 | } |
193 | 202 | ||
@@ -201,13 +210,15 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
201 | 210 | ||
202 | input_report_key(dev, BTN_TOUCH, fingers != 0); | 211 | input_report_key(dev, BTN_TOUCH, fingers != 0); |
203 | 212 | ||
204 | /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 | 213 | /* |
205 | byte 3: y7 y6 y5 y4 y3 y2 y1 y0 */ | 214 | * byte 2: x7 x6 x5 x4 x3 x2 x1 x0 |
215 | * byte 3: y7 y6 y5 y4 y3 y2 y1 y0 | ||
216 | */ | ||
206 | if (fingers) { | 217 | if (fingers) { |
207 | input_report_abs(dev, ABS_X, | 218 | input_report_abs(dev, ABS_X, |
208 | ((packet[1] & 0x0c) << 6) | packet[2]); | 219 | ((packet[1] & 0x0c) << 6) | packet[2]); |
209 | input_report_abs(dev, ABS_Y, ETP_YMAX_V1 - | 220 | input_report_abs(dev, ABS_Y, |
210 | (((packet[1] & 0x03) << 8) | packet[3])); | 221 | ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); |
211 | } | 222 | } |
212 | 223 | ||
213 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 224 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
@@ -216,7 +227,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
216 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 227 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
217 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 228 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
218 | 229 | ||
219 | if ((etd->fw_version_maj == 0x01) && | 230 | if (etd->fw_version < 0x020000 && |
220 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { | 231 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { |
221 | /* rocker up */ | 232 | /* rocker up */ |
222 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); | 233 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); |
@@ -246,34 +257,47 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
246 | 257 | ||
247 | switch (fingers) { | 258 | switch (fingers) { |
248 | case 1: | 259 | case 1: |
249 | /* byte 1: x15 x14 x13 x12 x11 x10 x9 x8 | 260 | /* |
250 | byte 2: x7 x6 x5 x4 x4 x2 x1 x0 */ | 261 | * byte 1: . . . . . x10 x9 x8 |
251 | input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]); | 262 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 |
252 | /* byte 4: y15 y14 y13 y12 y11 y10 y8 y8 | 263 | */ |
253 | byte 5: y7 y6 y5 y4 y3 y2 y1 y0 */ | 264 | input_report_abs(dev, ABS_X, |
254 | input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - | 265 | ((packet[1] & 0x07) << 8) | packet[2]); |
255 | ((packet[4] << 8) | packet[5])); | 266 | /* |
267 | * byte 4: . . . . . . y9 y8 | ||
268 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | ||
269 | */ | ||
270 | input_report_abs(dev, ABS_Y, | ||
271 | ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5])); | ||
256 | break; | 272 | break; |
257 | 273 | ||
258 | case 2: | 274 | case 2: |
259 | /* The coordinate of each finger is reported separately with | 275 | /* |
260 | a lower resolution for two finger touches */ | 276 | * The coordinate of each finger is reported separately |
261 | /* byte 0: . . ay8 ax8 . . . . | 277 | * with a lower resolution for two finger touches: |
262 | byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */ | 278 | * byte 0: . . ay8 ax8 . . . . |
279 | * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 | ||
280 | */ | ||
263 | x1 = ((packet[0] & 0x10) << 4) | packet[1]; | 281 | x1 = ((packet[0] & 0x10) << 4) | packet[1]; |
264 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ | 282 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ |
265 | y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); | 283 | y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); |
266 | /* byte 3: . . by8 bx8 . . . . | 284 | /* |
267 | byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */ | 285 | * byte 3: . . by8 bx8 . . . . |
286 | * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 | ||
287 | */ | ||
268 | x2 = ((packet[3] & 0x10) << 4) | packet[4]; | 288 | x2 = ((packet[3] & 0x10) << 4) | packet[4]; |
269 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ | 289 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ |
270 | y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); | 290 | y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); |
271 | /* For compatibility with the X Synaptics driver scale up one | 291 | /* |
272 | coordinate and report as ordinary mouse movent */ | 292 | * For compatibility with the X Synaptics driver scale up |
293 | * one coordinate and report as ordinary mouse movent | ||
294 | */ | ||
273 | input_report_abs(dev, ABS_X, x1 << 2); | 295 | input_report_abs(dev, ABS_X, x1 << 2); |
274 | input_report_abs(dev, ABS_Y, y1 << 2); | 296 | input_report_abs(dev, ABS_Y, y1 << 2); |
275 | /* For compatibility with the proprietary X Elantech driver | 297 | /* |
276 | report both coordinates as hat coordinates */ | 298 | * For compatibility with the proprietary X Elantech driver |
299 | * report both coordinates as hat coordinates | ||
300 | */ | ||
277 | input_report_abs(dev, ABS_HAT0X, x1); | 301 | input_report_abs(dev, ABS_HAT0X, x1); |
278 | input_report_abs(dev, ABS_HAT0Y, y1); | 302 | input_report_abs(dev, ABS_HAT0Y, y1); |
279 | input_report_abs(dev, ABS_HAT1X, x2); | 303 | input_report_abs(dev, ABS_HAT1X, x2); |
@@ -297,7 +321,7 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) | |||
297 | unsigned char p1, p2, p3; | 321 | unsigned char p1, p2, p3; |
298 | 322 | ||
299 | /* Parity bits are placed differently */ | 323 | /* Parity bits are placed differently */ |
300 | if (etd->fw_version_maj == 0x01) { | 324 | if (etd->fw_version < 0x020000) { |
301 | /* byte 0: D U p1 p2 1 p3 R L */ | 325 | /* byte 0: D U p1 p2 1 p3 R L */ |
302 | p1 = (packet[0] & 0x20) >> 5; | 326 | p1 = (packet[0] & 0x20) >> 5; |
303 | p2 = (packet[0] & 0x10) >> 4; | 327 | p2 = (packet[0] & 0x10) >> 4; |
@@ -420,6 +444,7 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
420 | 444 | ||
421 | __set_bit(EV_KEY, dev->evbit); | 445 | __set_bit(EV_KEY, dev->evbit); |
422 | __set_bit(EV_ABS, dev->evbit); | 446 | __set_bit(EV_ABS, dev->evbit); |
447 | __clear_bit(EV_REL, dev->evbit); | ||
423 | 448 | ||
424 | __set_bit(BTN_LEFT, dev->keybit); | 449 | __set_bit(BTN_LEFT, dev->keybit); |
425 | __set_bit(BTN_RIGHT, dev->keybit); | 450 | __set_bit(BTN_RIGHT, dev->keybit); |
@@ -432,7 +457,7 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
432 | switch (etd->hw_version) { | 457 | switch (etd->hw_version) { |
433 | case 1: | 458 | case 1: |
434 | /* Rocker button */ | 459 | /* Rocker button */ |
435 | if ((etd->fw_version_maj == 0x01) && | 460 | if (etd->fw_version < 0x020000 && |
436 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { | 461 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { |
437 | __set_bit(BTN_FORWARD, dev->keybit); | 462 | __set_bit(BTN_FORWARD, dev->keybit); |
438 | __set_bit(BTN_BACK, dev->keybit); | 463 | __set_bit(BTN_BACK, dev->keybit); |
@@ -594,8 +619,12 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
594 | param[0], param[1], param[2]); | 619 | param[0], param[1], param[2]); |
595 | 620 | ||
596 | if (param[0] == 0 || param[1] != 0) { | 621 | if (param[0] == 0 || param[1] != 0) { |
597 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); | 622 | if (!force_elantech) { |
598 | return -1; | 623 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); |
624 | return -1; | ||
625 | } | ||
626 | |||
627 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); | ||
599 | } | 628 | } |
600 | 629 | ||
601 | if (set_properties) { | 630 | if (set_properties) { |
@@ -657,14 +686,14 @@ int elantech_init(struct psmouse *psmouse) | |||
657 | pr_err("elantech.c: failed to query firmware version.\n"); | 686 | pr_err("elantech.c: failed to query firmware version.\n"); |
658 | goto init_fail; | 687 | goto init_fail; |
659 | } | 688 | } |
660 | etd->fw_version_maj = param[0]; | 689 | |
661 | etd->fw_version_min = param[2]; | 690 | etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; |
662 | 691 | ||
663 | /* | 692 | /* |
664 | * Assume every version greater than this is new EeePC style | 693 | * Assume every version greater than this is new EeePC style |
665 | * hardware with 6 byte packets | 694 | * hardware with 6 byte packets |
666 | */ | 695 | */ |
667 | if (etd->fw_version_maj >= 0x02 && etd->fw_version_min >= 0x30) { | 696 | if (etd->fw_version >= 0x020030) { |
668 | etd->hw_version = 2; | 697 | etd->hw_version = 2; |
669 | /* For now show extra debug information */ | 698 | /* For now show extra debug information */ |
670 | etd->debug = 1; | 699 | etd->debug = 1; |
@@ -674,8 +703,9 @@ int elantech_init(struct psmouse *psmouse) | |||
674 | etd->hw_version = 1; | 703 | etd->hw_version = 1; |
675 | etd->paritycheck = 1; | 704 | etd->paritycheck = 1; |
676 | } | 705 | } |
677 | pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n", | 706 | |
678 | etd->hw_version, etd->fw_version_maj, etd->fw_version_min); | 707 | pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d.%d\n", |
708 | etd->hw_version, param[0], param[1], param[2]); | ||
679 | 709 | ||
680 | if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { | 710 | if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { |
681 | pr_err("elantech.c: failed to query capabilities.\n"); | 711 | pr_err("elantech.c: failed to query capabilities.\n"); |
@@ -690,8 +720,8 @@ int elantech_init(struct psmouse *psmouse) | |||
690 | * a touch action starts causing the mouse cursor or scrolled page | 720 | * a touch action starts causing the mouse cursor or scrolled page |
691 | * to jump. Enable a workaround. | 721 | * to jump. Enable a workaround. |
692 | */ | 722 | */ |
693 | if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { | 723 | if (etd->fw_version == 0x020022) { |
694 | pr_info("elantech.c: firmware version 2.34 detected, " | 724 | pr_info("elantech.c: firmware version 2.0.34 detected, " |
695 | "enabling jumpy cursor workaround\n"); | 725 | "enabling jumpy cursor workaround\n"); |
696 | etd->jumpy_cursor = 1; | 726 | etd->jumpy_cursor = 1; |
697 | } | 727 | } |