diff options
| author | Ulrik De Bie <ulrik.debie-os@e2big.org> | 2015-04-06 18:35:38 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-04-06 18:39:07 -0400 |
| commit | bd884149aca61de269fd9bad83fe2a4232ffab21 (patch) | |
| tree | 3f97de62459c36712336e1aa7bf1e37f42a81d05 /drivers | |
| parent | 58d8a3be36cf0fe2eb2609e205bb07a141c29a7c (diff) | |
Input: elantech - fix absolute mode setting on some ASUS laptops
On ASUS TP500LN and X750JN, the touchpad absolute mode is reset each
time set_rate is done.
In order to fix this, we will verify the firmware version, and if it
matches the one in those laptops, the set_rate function is overloaded
with a function elantech_set_rate_restore_reg_07 that performs the
set_rate with the original function, followed by a restore of reg_07
(the register that sets the absolute mode on elantech v4 hardware).
Also the ASUS TP500LN and X750JN firmware version, capabilities, and
button constellation is added to elantech.c
Cc: stable@vger.kernel.org
Reported-and-tested-by: George Moutsopoulos <gmoutso@yahoo.co.uk>
Signed-off-by: Ulrik De Bie <ulrik.debie-os@e2big.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/input/mouse/elantech.c | 22 | ||||
| -rw-r--r-- | drivers/input/mouse/elantech.h | 1 |
2 files changed, 23 insertions, 0 deletions
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 6e22682c8255..991dc6b20a58 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
| @@ -893,6 +893,21 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse) | |||
| 893 | } | 893 | } |
| 894 | 894 | ||
| 895 | /* | 895 | /* |
| 896 | * This writes the reg_07 value again to the hardware at the end of every | ||
| 897 | * set_rate call because the register loses its value. reg_07 allows setting | ||
| 898 | * absolute mode on v4 hardware | ||
| 899 | */ | ||
| 900 | static void elantech_set_rate_restore_reg_07(struct psmouse *psmouse, | ||
| 901 | unsigned int rate) | ||
| 902 | { | ||
| 903 | struct elantech_data *etd = psmouse->private; | ||
| 904 | |||
| 905 | etd->original_set_rate(psmouse, rate); | ||
| 906 | if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) | ||
| 907 | psmouse_err(psmouse, "restoring reg_07 failed\n"); | ||
| 908 | } | ||
| 909 | |||
| 910 | /* | ||
| 896 | * Put the touchpad into absolute mode | 911 | * Put the touchpad into absolute mode |
| 897 | */ | 912 | */ |
| 898 | static int elantech_set_absolute_mode(struct psmouse *psmouse) | 913 | static int elantech_set_absolute_mode(struct psmouse *psmouse) |
| @@ -1094,6 +1109,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse, | |||
| 1094 | * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons | 1109 | * Asus K53SV 0x450f01 78, 15, 0c 2 hw buttons |
| 1095 | * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons | 1110 | * Asus G46VW 0x460f02 00, 18, 0c 2 hw buttons |
| 1096 | * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons | 1111 | * Asus G750JX 0x360f00 00, 16, 0c 2 hw buttons |
| 1112 | * Asus TP500LN 0x381f17 10, 14, 0e clickpad | ||
| 1113 | * Asus X750JN 0x381f17 10, 14, 0e clickpad | ||
| 1097 | * Asus UX31 0x361f00 20, 15, 0e clickpad | 1114 | * Asus UX31 0x361f00 20, 15, 0e clickpad |
| 1098 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad | 1115 | * Asus UX32VD 0x361f02 00, 15, 0e clickpad |
| 1099 | * Avatar AVIU-145A2 0x361f00 ? clickpad | 1116 | * Avatar AVIU-145A2 0x361f00 ? clickpad |
| @@ -1635,6 +1652,11 @@ int elantech_init(struct psmouse *psmouse) | |||
| 1635 | goto init_fail; | 1652 | goto init_fail; |
| 1636 | } | 1653 | } |
| 1637 | 1654 | ||
| 1655 | if (etd->fw_version == 0x381f17) { | ||
| 1656 | etd->original_set_rate = psmouse->set_rate; | ||
| 1657 | psmouse->set_rate = elantech_set_rate_restore_reg_07; | ||
| 1658 | } | ||
| 1659 | |||
| 1638 | if (elantech_set_input_params(psmouse)) { | 1660 | if (elantech_set_input_params(psmouse)) { |
| 1639 | psmouse_err(psmouse, "failed to query touchpad range.\n"); | 1661 | psmouse_err(psmouse, "failed to query touchpad range.\n"); |
| 1640 | goto init_fail; | 1662 | goto init_fail; |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index 6f3afec02f03..f965d1569cc3 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
| @@ -142,6 +142,7 @@ struct elantech_data { | |||
| 142 | struct finger_pos mt[ETP_MAX_FINGERS]; | 142 | struct finger_pos mt[ETP_MAX_FINGERS]; |
| 143 | unsigned char parity[256]; | 143 | unsigned char parity[256]; |
| 144 | int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param); | 144 | int (*send_cmd)(struct psmouse *psmouse, unsigned char c, unsigned char *param); |
| 145 | void (*original_set_rate)(struct psmouse *psmouse, unsigned int rate); | ||
| 145 | }; | 146 | }; |
| 146 | 147 | ||
| 147 | #ifdef CONFIG_MOUSE_PS2_ELANTECH | 148 | #ifdef CONFIG_MOUSE_PS2_ELANTECH |
