diff options
author | JJ Ding <jj_ding@emc.com.tw> | 2011-09-09 13:30:31 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2011-09-09 13:34:58 -0400 |
commit | 28f49616113f3a1fbef789319bfd2122d0c3663f (patch) | |
tree | 5f0dba8f912dfcd19c0457bc4b2c8c3a823f9757 | |
parent | 3c8bbb951ab23dc1192473ccad76cde89c172d27 (diff) |
Input: elantech - add v3 hardware support
v3 hardware's packet format is almost identical to v2 (one/three finger touch),
except when sensing two finger touch, the hardware sends 12 bytes of data.
Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Acked-by: Daniel Kurtz <djkurtz@chromium.org>
Acked-by: Éric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r-- | Documentation/input/elantech.txt | 117 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.c | 208 | ||||
-rw-r--r-- | drivers/input/mouse/elantech.h | 12 |
3 files changed, 306 insertions, 31 deletions
diff --git a/Documentation/input/elantech.txt b/Documentation/input/elantech.txt index bce9941ffa94..cee08eecda43 100644 --- a/Documentation/input/elantech.txt +++ b/Documentation/input/elantech.txt | |||
@@ -16,15 +16,22 @@ Contents | |||
16 | 16 | ||
17 | 1. Introduction | 17 | 1. Introduction |
18 | 2. Extra knobs | 18 | 2. Extra knobs |
19 | 3. Hardware version 1 | 19 | 3. Differentiating hardware versions |
20 | 3.1 Registers | 20 | 4. Hardware version 1 |
21 | 3.2 Native relative mode 4 byte packet format | ||
22 | 3.3 Native absolute mode 4 byte packet format | ||
23 | 4. Hardware version 2 | ||
24 | 4.1 Registers | 21 | 4.1 Registers |
25 | 4.2 Native absolute mode 6 byte packet format | 22 | 4.2 Native relative mode 4 byte packet format |
26 | 4.2.1 One finger touch | 23 | 4.3 Native absolute mode 4 byte packet format |
27 | 4.2.2 Two finger touch | 24 | 5. Hardware version 2 |
25 | 5.1 Registers | ||
26 | 5.2 Native absolute mode 6 byte packet format | ||
27 | 5.2.1 Parity checking and packet re-synchronization | ||
28 | 5.2.2 One/Three finger touch | ||
29 | 5.2.3 Two finger touch | ||
30 | 6. Hardware version 3 | ||
31 | 6.1 Registers | ||
32 | 6.2 Native absolute mode 6 byte packet format | ||
33 | 6.2.1 One/Three finger touch | ||
34 | 6.2.2 Two finger touch | ||
28 | 35 | ||
29 | 36 | ||
30 | 37 | ||
@@ -375,7 +382,7 @@ For all the other ones, there are just a few constant bits: | |||
375 | 382 | ||
376 | In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). | 383 | In case an error is detected, all the packets are shifted by one (and packet[0] is discarded). |
377 | 384 | ||
378 | 5.2.1 One/Three finger touch | 385 | 5.2.2 One/Three finger touch |
379 | ~~~~~~~~~~~~~~~~ | 386 | ~~~~~~~~~~~~~~~~ |
380 | 387 | ||
381 | byte 0: | 388 | byte 0: |
@@ -384,7 +391,7 @@ byte 0: | |||
384 | n1 n0 w3 w2 . . R L | 391 | n1 n0 w3 w2 . . R L |
385 | 392 | ||
386 | L, R = 1 when Left, Right mouse button pressed | 393 | L, R = 1 when Left, Right mouse button pressed |
387 | n1..n0 = numbers of fingers on touchpad | 394 | n1..n0 = number of fingers on touchpad |
388 | 395 | ||
389 | byte 1: | 396 | byte 1: |
390 | 397 | ||
@@ -432,7 +439,7 @@ byte 5: | |||
432 | y11..y0 = absolute y value (vertical) | 439 | y11..y0 = absolute y value (vertical) |
433 | 440 | ||
434 | 441 | ||
435 | 4.2.2 Two finger touch | 442 | 5.2.3 Two finger touch |
436 | ~~~~~~~~~~~~~~~~ | 443 | ~~~~~~~~~~~~~~~~ |
437 | 444 | ||
438 | Note that the two pairs of coordinates are not exactly the coordinates of the | 445 | Note that the two pairs of coordinates are not exactly the coordinates of the |
@@ -446,7 +453,7 @@ byte 0: | |||
446 | n1 n0 ay8 ax8 . . R L | 453 | n1 n0 ay8 ax8 . . R L |
447 | 454 | ||
448 | L, R = 1 when Left, Right mouse button pressed | 455 | L, R = 1 when Left, Right mouse button pressed |
449 | n1..n0 = numbers of fingers on touchpad | 456 | n1..n0 = number of fingers on touchpad |
450 | 457 | ||
451 | byte 1: | 458 | byte 1: |
452 | 459 | ||
@@ -480,3 +487,89 @@ byte 5: | |||
480 | by7 by8 by5 by4 by3 by2 by1 by0 | 487 | by7 by8 by5 by4 by3 by2 by1 by0 |
481 | 488 | ||
482 | by8..by0 = upper-right finger absolute y value | 489 | by8..by0 = upper-right finger absolute y value |
490 | |||
491 | ///////////////////////////////////////////////////////////////////////////// | ||
492 | |||
493 | 6. Hardware version 3 | ||
494 | ================== | ||
495 | |||
496 | 6.1 Registers | ||
497 | ~~~~~~~~~ | ||
498 | * reg_10 | ||
499 | |||
500 | bit 7 6 5 4 3 2 1 0 | ||
501 | 0 0 0 0 0 0 0 A | ||
502 | |||
503 | A: 1 = enable absolute tracking | ||
504 | |||
505 | 6.2 Native absolute mode 6 byte packet format | ||
506 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
507 | 1 and 3 finger touch shares the same 6-byte packet format, except that | ||
508 | 3 finger touch only reports the position of the center of all three fingers. | ||
509 | |||
510 | Firmware would send 12 bytes of data for 2 finger touch. | ||
511 | |||
512 | Note on debounce: | ||
513 | In case the box has unstable power supply or other electricity issues, or | ||
514 | when number of finger changes, F/W would send "debounce packet" to inform | ||
515 | driver that the hardware is in debounce status. | ||
516 | The debouce packet has the following signature: | ||
517 | byte 0: 0xc4 | ||
518 | byte 1: 0xff | ||
519 | byte 2: 0xff | ||
520 | byte 3: 0x02 | ||
521 | byte 4: 0xff | ||
522 | byte 5: 0xff | ||
523 | When we encounter this kind of packet, we just ignore it. | ||
524 | |||
525 | 6.2.1 One/Three finger touch | ||
526 | ~~~~~~~~~~~~~~~~~~~~~~ | ||
527 | |||
528 | byte 0: | ||
529 | |||
530 | bit 7 6 5 4 3 2 1 0 | ||
531 | n1 n0 w3 w2 0 1 R L | ||
532 | |||
533 | L, R = 1 when Left, Right mouse button pressed | ||
534 | n1..n0 = number of fingers on touchpad | ||
535 | |||
536 | byte 1: | ||
537 | |||
538 | bit 7 6 5 4 3 2 1 0 | ||
539 | p7 p6 p5 p4 x11 x10 x9 x8 | ||
540 | |||
541 | byte 2: | ||
542 | |||
543 | bit 7 6 5 4 3 2 1 0 | ||
544 | x7 x6 x5 x4 x3 x2 x1 x0 | ||
545 | |||
546 | x11..x0 = absolute x value (horizontal) | ||
547 | |||
548 | byte 3: | ||
549 | |||
550 | bit 7 6 5 4 3 2 1 0 | ||
551 | 0 0 w1 w0 0 0 1 0 | ||
552 | |||
553 | w3..w0 = width of the finger touch | ||
554 | |||
555 | byte 4: | ||
556 | |||
557 | bit 7 6 5 4 3 2 1 0 | ||
558 | p3 p1 p2 p0 y11 y10 y9 y8 | ||
559 | |||
560 | p7..p0 = pressure | ||
561 | |||
562 | byte 5: | ||
563 | |||
564 | bit 7 6 5 4 3 2 1 0 | ||
565 | y7 y6 y5 y4 y3 y2 y1 y0 | ||
566 | |||
567 | y11..y0 = absolute y value (vertical) | ||
568 | |||
569 | 6.2.2 Two finger touch | ||
570 | ~~~~~~~~~~~~~~~~ | ||
571 | |||
572 | The packet format is exactly the same for two finger touch, except the hardware | ||
573 | sends two 6 byte packets. The first packet contains data for the first finger, | ||
574 | the second packet has data for the second finger. So for two finger touch a | ||
575 | total of 12 bytes are sent. | ||
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 1ab1c14449d7..9cfc70ae83fd 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -108,6 +108,16 @@ static int elantech_read_reg(struct psmouse *psmouse, unsigned char reg, | |||
108 | rc = -1; | 108 | rc = -1; |
109 | } | 109 | } |
110 | break; | 110 | break; |
111 | |||
112 | case 3: | ||
113 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
114 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | ||
115 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
116 | elantech_ps2_command(psmouse, NULL, reg) || | ||
117 | elantech_ps2_command(psmouse, param, PSMOUSE_CMD_GETINFO)) { | ||
118 | rc = -1; | ||
119 | } | ||
120 | break; | ||
111 | } | 121 | } |
112 | 122 | ||
113 | if (rc) | 123 | if (rc) |
@@ -154,6 +164,18 @@ static int elantech_write_reg(struct psmouse *psmouse, unsigned char reg, | |||
154 | rc = -1; | 164 | rc = -1; |
155 | } | 165 | } |
156 | break; | 166 | break; |
167 | |||
168 | case 3: | ||
169 | if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
170 | elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || | ||
171 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
172 | elantech_ps2_command(psmouse, NULL, reg) || | ||
173 | elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || | ||
174 | elantech_ps2_command(psmouse, NULL, val) || | ||
175 | elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { | ||
176 | rc = -1; | ||
177 | } | ||
178 | break; | ||
157 | } | 179 | } |
158 | 180 | ||
159 | if (rc) | 181 | if (rc) |
@@ -350,6 +372,84 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
350 | input_sync(dev); | 372 | input_sync(dev); |
351 | } | 373 | } |
352 | 374 | ||
375 | /* | ||
376 | * Interpret complete data packets and report absolute mode input events for | ||
377 | * hardware version 3. (12 byte packets for two fingers) | ||
378 | */ | ||
379 | static void elantech_report_absolute_v3(struct psmouse *psmouse, | ||
380 | int packet_type) | ||
381 | { | ||
382 | struct input_dev *dev = psmouse->dev; | ||
383 | struct elantech_data *etd = psmouse->private; | ||
384 | unsigned char *packet = psmouse->packet; | ||
385 | unsigned int fingers = 0, x1 = 0, y1 = 0, x2 = 0, y2 = 0; | ||
386 | unsigned int width = 0, pres = 0; | ||
387 | |||
388 | /* byte 0: n1 n0 . . . . R L */ | ||
389 | fingers = (packet[0] & 0xc0) >> 6; | ||
390 | |||
391 | switch (fingers) { | ||
392 | case 3: | ||
393 | case 1: | ||
394 | /* | ||
395 | * byte 1: . . . . x11 x10 x9 x8 | ||
396 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 | ||
397 | */ | ||
398 | x1 = ((packet[1] & 0x0f) << 8) | packet[2]; | ||
399 | /* | ||
400 | * byte 4: . . . . y11 y10 y9 y8 | ||
401 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | ||
402 | */ | ||
403 | y1 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); | ||
404 | break; | ||
405 | |||
406 | case 2: | ||
407 | if (packet_type == PACKET_V3_HEAD) { | ||
408 | /* | ||
409 | * byte 1: . . . . ax11 ax10 ax9 ax8 | ||
410 | * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 | ||
411 | */ | ||
412 | etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; | ||
413 | /* | ||
414 | * byte 4: . . . . ay11 ay10 ay9 ay8 | ||
415 | * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 | ||
416 | */ | ||
417 | etd->prev_y = etd->y_max - | ||
418 | (((packet[4] & 0x0f) << 8) | packet[5]); | ||
419 | /* | ||
420 | * wait for next packet | ||
421 | */ | ||
422 | return; | ||
423 | } | ||
424 | |||
425 | /* packet_type == PACKET_V3_TAIL */ | ||
426 | x1 = etd->prev_x; | ||
427 | y1 = etd->prev_y; | ||
428 | x2 = ((packet[1] & 0x0f) << 8) | packet[2]; | ||
429 | y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); | ||
430 | break; | ||
431 | } | ||
432 | |||
433 | pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); | ||
434 | width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); | ||
435 | |||
436 | input_report_key(dev, BTN_TOUCH, fingers != 0); | ||
437 | if (fingers != 0) { | ||
438 | input_report_abs(dev, ABS_X, x1); | ||
439 | input_report_abs(dev, ABS_Y, y1); | ||
440 | } | ||
441 | elantech_report_semi_mt_data(dev, fingers, x1, y1, x2, y2); | ||
442 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | ||
443 | input_report_key(dev, BTN_TOOL_DOUBLETAP, fingers == 2); | ||
444 | input_report_key(dev, BTN_TOOL_TRIPLETAP, fingers == 3); | ||
445 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | ||
446 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | ||
447 | input_report_abs(dev, ABS_PRESSURE, pres); | ||
448 | input_report_abs(dev, ABS_TOOL_WIDTH, width); | ||
449 | |||
450 | input_sync(dev); | ||
451 | } | ||
452 | |||
353 | static int elantech_packet_check_v1(struct psmouse *psmouse) | 453 | static int elantech_packet_check_v1(struct psmouse *psmouse) |
354 | { | 454 | { |
355 | struct elantech_data *etd = psmouse->private; | 455 | struct elantech_data *etd = psmouse->private; |
@@ -403,11 +503,37 @@ static int elantech_packet_check_v2(struct psmouse *psmouse) | |||
403 | } | 503 | } |
404 | 504 | ||
405 | /* | 505 | /* |
506 | * We check the constant bits to determine what packet type we get, | ||
507 | * so packet checking is mandatory for v3 hardware. | ||
508 | */ | ||
509 | static int elantech_packet_check_v3(struct psmouse *psmouse) | ||
510 | { | ||
511 | const u8 debounce_packet[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff }; | ||
512 | unsigned char *packet = psmouse->packet; | ||
513 | |||
514 | /* | ||
515 | * check debounce first, it has the same signature in byte 0 | ||
516 | * and byte 3 as PACKET_V3_HEAD. | ||
517 | */ | ||
518 | if (!memcmp(packet, debounce_packet, sizeof(debounce_packet))) | ||
519 | return PACKET_DEBOUNCE; | ||
520 | |||
521 | if ((packet[0] & 0x0c) == 0x04 && (packet[3] & 0xcf) == 0x02) | ||
522 | return PACKET_V3_HEAD; | ||
523 | |||
524 | if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) | ||
525 | return PACKET_V3_TAIL; | ||
526 | |||
527 | return PACKET_UNKNOWN; | ||
528 | } | ||
529 | |||
530 | /* | ||
406 | * Process byte stream from mouse and handle complete packets | 531 | * Process byte stream from mouse and handle complete packets |
407 | */ | 532 | */ |
408 | static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) | 533 | static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) |
409 | { | 534 | { |
410 | struct elantech_data *etd = psmouse->private; | 535 | struct elantech_data *etd = psmouse->private; |
536 | int packet_type; | ||
411 | 537 | ||
412 | if (psmouse->pktcnt < psmouse->pktsize) | 538 | if (psmouse->pktcnt < psmouse->pktsize) |
413 | return PSMOUSE_GOOD_DATA; | 539 | return PSMOUSE_GOOD_DATA; |
@@ -429,6 +555,18 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) | |||
429 | 555 | ||
430 | elantech_report_absolute_v2(psmouse); | 556 | elantech_report_absolute_v2(psmouse); |
431 | break; | 557 | break; |
558 | |||
559 | case 3: | ||
560 | packet_type = elantech_packet_check_v3(psmouse); | ||
561 | /* ignore debounce */ | ||
562 | if (packet_type == PACKET_DEBOUNCE) | ||
563 | return PSMOUSE_FULL_PACKET; | ||
564 | |||
565 | if (packet_type == PACKET_UNKNOWN) | ||
566 | return PSMOUSE_BAD_DATA; | ||
567 | |||
568 | elantech_report_absolute_v3(psmouse, packet_type); | ||
569 | break; | ||
432 | } | 570 | } |
433 | 571 | ||
434 | return PSMOUSE_FULL_PACKET; | 572 | return PSMOUSE_FULL_PACKET; |
@@ -463,8 +601,15 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) | |||
463 | elantech_write_reg(psmouse, 0x11, etd->reg_11) || | 601 | elantech_write_reg(psmouse, 0x11, etd->reg_11) || |
464 | elantech_write_reg(psmouse, 0x21, etd->reg_21)) { | 602 | elantech_write_reg(psmouse, 0x21, etd->reg_21)) { |
465 | rc = -1; | 603 | rc = -1; |
466 | break; | ||
467 | } | 604 | } |
605 | break; | ||
606 | |||
607 | case 3: | ||
608 | etd->reg_10 = 0x0b; | ||
609 | if (elantech_write_reg(psmouse, 0x10, etd->reg_10)) | ||
610 | rc = -1; | ||
611 | |||
612 | break; | ||
468 | } | 613 | } |
469 | 614 | ||
470 | if (rc == 0) { | 615 | if (rc == 0) { |
@@ -498,11 +643,12 @@ static int elantech_set_absolute_mode(struct psmouse *psmouse) | |||
498 | return rc; | 643 | return rc; |
499 | } | 644 | } |
500 | 645 | ||
501 | static void elantech_set_range(struct psmouse *psmouse, | 646 | static int elantech_set_range(struct psmouse *psmouse, |
502 | unsigned int *x_min, unsigned int *y_min, | 647 | unsigned int *x_min, unsigned int *y_min, |
503 | unsigned int *x_max, unsigned int *y_max) | 648 | unsigned int *x_max, unsigned int *y_max) |
504 | { | 649 | { |
505 | struct elantech_data *etd = psmouse->private; | 650 | struct elantech_data *etd = psmouse->private; |
651 | unsigned char param[3]; | ||
506 | int i; | 652 | int i; |
507 | 653 | ||
508 | switch (etd->hw_version) { | 654 | switch (etd->hw_version) { |
@@ -530,19 +676,30 @@ static void elantech_set_range(struct psmouse *psmouse, | |||
530 | *y_max = (etd->capabilities[2] - i) * 64; | 676 | *y_max = (etd->capabilities[2] - i) * 64; |
531 | } | 677 | } |
532 | break; | 678 | break; |
679 | |||
680 | case 3: | ||
681 | if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) | ||
682 | return -1; | ||
683 | |||
684 | *x_max = (0x0f & param[0]) << 8 | param[1]; | ||
685 | *y_max = (0xf0 & param[0]) << 4 | param[2]; | ||
686 | break; | ||
533 | } | 687 | } |
688 | |||
689 | return 0; | ||
534 | } | 690 | } |
535 | 691 | ||
536 | /* | 692 | /* |
537 | * Set the appropriate event bits for the input subsystem | 693 | * Set the appropriate event bits for the input subsystem |
538 | */ | 694 | */ |
539 | static void elantech_set_input_params(struct psmouse *psmouse) | 695 | static int elantech_set_input_params(struct psmouse *psmouse) |
540 | { | 696 | { |
541 | struct input_dev *dev = psmouse->dev; | 697 | struct input_dev *dev = psmouse->dev; |
542 | struct elantech_data *etd = psmouse->private; | 698 | struct elantech_data *etd = psmouse->private; |
543 | unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; | 699 | unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; |
544 | 700 | ||
545 | elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max); | 701 | if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) |
702 | return -1; | ||
546 | 703 | ||
547 | __set_bit(EV_KEY, dev->evbit); | 704 | __set_bit(EV_KEY, dev->evbit); |
548 | __set_bit(EV_ABS, dev->evbit); | 705 | __set_bit(EV_ABS, dev->evbit); |
@@ -570,6 +727,9 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
570 | 727 | ||
571 | case 2: | 728 | case 2: |
572 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 729 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
730 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
731 | /* fall through */ | ||
732 | case 3: | ||
573 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); | 733 | input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); |
574 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); | 734 | input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); |
575 | if (etd->reports_pressure) { | 735 | if (etd->reports_pressure) { |
@@ -578,7 +738,6 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
578 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, | 738 | input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, |
579 | ETP_WMAX_V2, 0, 0); | 739 | ETP_WMAX_V2, 0, 0); |
580 | } | 740 | } |
581 | __set_bit(INPUT_PROP_SEMI_MT, dev->propbit); | ||
582 | input_mt_init_slots(dev, 2); | 741 | input_mt_init_slots(dev, 2); |
583 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); | 742 | input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); |
584 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); | 743 | input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); |
@@ -586,6 +745,8 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
586 | } | 745 | } |
587 | 746 | ||
588 | etd->y_max = y_max; | 747 | etd->y_max = y_max; |
748 | |||
749 | return 0; | ||
589 | } | 750 | } |
590 | 751 | ||
591 | struct elantech_attr_data { | 752 | struct elantech_attr_data { |
@@ -727,7 +888,8 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
727 | * Report this in case there are Elantech models that use a different | 888 | * Report this in case there are Elantech models that use a different |
728 | * set of magic numbers | 889 | * set of magic numbers |
729 | */ | 890 | */ |
730 | if (param[0] != 0x3c || param[1] != 0x03 || param[2] != 0xc8) { | 891 | if (param[0] != 0x3c || param[1] != 0x03 || |
892 | (param[2] != 0xc8 && param[2] != 0x00)) { | ||
731 | pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", | 893 | pr_debug("unexpected magic knock result 0x%02x, 0x%02x, 0x%02x.\n", |
732 | param[0], param[1], param[2]); | 894 | param[0], param[1], param[2]); |
733 | return -1; | 895 | return -1; |
@@ -793,16 +955,16 @@ static int elantech_reconnect(struct psmouse *psmouse) | |||
793 | /* | 955 | /* |
794 | * determine hardware version and set some properties according to it. | 956 | * determine hardware version and set some properties according to it. |
795 | */ | 957 | */ |
796 | static void elantech_set_properties(struct elantech_data *etd) | 958 | static int elantech_set_properties(struct elantech_data *etd) |
797 | { | 959 | { |
798 | /* | ||
799 | * Assume every version greater than 0x020030 is new EeePC style | ||
800 | * hardware with 6 byte packets, except 0x020600 | ||
801 | */ | ||
802 | if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) | 960 | if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) |
803 | etd->hw_version = 1; | 961 | etd->hw_version = 1; |
804 | else | 962 | else if (etd->fw_version < 0x150600) |
805 | etd->hw_version = 2; | 963 | etd->hw_version = 2; |
964 | else if ((etd->fw_version & 0x0f0000) >> 16 == 5) | ||
965 | etd->hw_version = 3; | ||
966 | else | ||
967 | return -1; | ||
806 | 968 | ||
807 | /* | 969 | /* |
808 | * Turn on packet checking by default. | 970 | * Turn on packet checking by default. |
@@ -817,13 +979,15 @@ static void elantech_set_properties(struct elantech_data *etd) | |||
817 | etd->jumpy_cursor = | 979 | etd->jumpy_cursor = |
818 | (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); | 980 | (etd->fw_version == 0x020022 || etd->fw_version == 0x020600); |
819 | 981 | ||
820 | if (etd->hw_version == 2) { | 982 | if (etd->hw_version > 1) { |
821 | /* For now show extra debug information */ | 983 | /* For now show extra debug information */ |
822 | etd->debug = 1; | 984 | etd->debug = 1; |
823 | 985 | ||
824 | if (etd->fw_version >= 0x020800) | 986 | if (etd->fw_version >= 0x020800) |
825 | etd->reports_pressure = true; | 987 | etd->reports_pressure = true; |
826 | } | 988 | } |
989 | |||
990 | return 0; | ||
827 | } | 991 | } |
828 | 992 | ||
829 | /* | 993 | /* |
@@ -850,9 +1014,12 @@ int elantech_init(struct psmouse *psmouse) | |||
850 | pr_err("failed to query firmware version.\n"); | 1014 | pr_err("failed to query firmware version.\n"); |
851 | goto init_fail; | 1015 | goto init_fail; |
852 | } | 1016 | } |
853 | |||
854 | etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; | 1017 | etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; |
855 | elantech_set_properties(etd); | 1018 | |
1019 | if (elantech_set_properties(etd)) { | ||
1020 | pr_err("unknown hardware version, aborting...\n"); | ||
1021 | goto init_fail; | ||
1022 | } | ||
856 | pr_info("assuming hardware version %d " | 1023 | pr_info("assuming hardware version %d " |
857 | "(with firmware version 0x%02x%02x%02x)\n", | 1024 | "(with firmware version 0x%02x%02x%02x)\n", |
858 | etd->hw_version, param[0], param[1], param[2]); | 1025 | etd->hw_version, param[0], param[1], param[2]); |
@@ -871,7 +1038,10 @@ int elantech_init(struct psmouse *psmouse) | |||
871 | goto init_fail; | 1038 | goto init_fail; |
872 | } | 1039 | } |
873 | 1040 | ||
874 | elantech_set_input_params(psmouse); | 1041 | if (elantech_set_input_params(psmouse)) { |
1042 | pr_err("failed to query touchpad range.\n"); | ||
1043 | goto init_fail; | ||
1044 | } | ||
875 | 1045 | ||
876 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, | 1046 | error = sysfs_create_group(&psmouse->ps2dev.serio->dev.kobj, |
877 | &elantech_attr_group); | 1047 | &elantech_attr_group); |
@@ -883,7 +1053,7 @@ int elantech_init(struct psmouse *psmouse) | |||
883 | psmouse->protocol_handler = elantech_process_byte; | 1053 | psmouse->protocol_handler = elantech_process_byte; |
884 | psmouse->disconnect = elantech_disconnect; | 1054 | psmouse->disconnect = elantech_disconnect; |
885 | psmouse->reconnect = elantech_reconnect; | 1055 | psmouse->reconnect = elantech_reconnect; |
886 | psmouse->pktsize = etd->hw_version == 2 ? 6 : 4; | 1056 | psmouse->pktsize = etd->hw_version > 1 ? 6 : 4; |
887 | 1057 | ||
888 | return 0; | 1058 | return 0; |
889 | 1059 | ||
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index d9e614409f92..236c33cdc708 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
@@ -16,6 +16,7 @@ | |||
16 | /* | 16 | /* |
17 | * Command values for Synaptics style queries | 17 | * Command values for Synaptics style queries |
18 | */ | 18 | */ |
19 | #define ETP_FW_ID_QUERY 0x00 | ||
19 | #define ETP_FW_VERSION_QUERY 0x01 | 20 | #define ETP_FW_VERSION_QUERY 0x01 |
20 | #define ETP_CAPABILITIES_QUERY 0x02 | 21 | #define ETP_CAPABILITIES_QUERY 0x02 |
21 | 22 | ||
@@ -24,6 +25,7 @@ | |||
24 | */ | 25 | */ |
25 | #define ETP_REGISTER_READ 0x10 | 26 | #define ETP_REGISTER_READ 0x10 |
26 | #define ETP_REGISTER_WRITE 0x11 | 27 | #define ETP_REGISTER_WRITE 0x11 |
28 | #define ETP_REGISTER_READWRITE 0x00 | ||
27 | 29 | ||
28 | /* | 30 | /* |
29 | * Hardware version 2 custom PS/2 command value | 31 | * Hardware version 2 custom PS/2 command value |
@@ -79,6 +81,14 @@ | |||
79 | #define ETP_WMIN_V2 0 | 81 | #define ETP_WMIN_V2 0 |
80 | #define ETP_WMAX_V2 15 | 82 | #define ETP_WMAX_V2 15 |
81 | 83 | ||
84 | /* | ||
85 | * v3 hardware has 2 kinds of packet types. | ||
86 | */ | ||
87 | #define PACKET_UNKNOWN 0x01 | ||
88 | #define PACKET_DEBOUNCE 0x02 | ||
89 | #define PACKET_V3_HEAD 0x03 | ||
90 | #define PACKET_V3_TAIL 0x04 | ||
91 | |||
82 | struct elantech_data { | 92 | struct elantech_data { |
83 | unsigned char reg_10; | 93 | unsigned char reg_10; |
84 | unsigned char reg_11; | 94 | unsigned char reg_11; |
@@ -98,6 +108,8 @@ struct elantech_data { | |||
98 | unsigned int fw_version; | 108 | unsigned int fw_version; |
99 | unsigned int single_finger_reports; | 109 | unsigned int single_finger_reports; |
100 | unsigned int y_max; | 110 | unsigned int y_max; |
111 | unsigned int prev_x; | ||
112 | unsigned int prev_y; | ||
101 | unsigned char parity[256]; | 113 | unsigned char parity[256]; |
102 | }; | 114 | }; |
103 | 115 | ||