diff options
Diffstat (limited to 'drivers/input/mouse/elantech.c')
-rw-r--r-- | drivers/input/mouse/elantech.c | 84 |
1 files changed, 56 insertions, 28 deletions
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index a138b5da79f9..0520c2e19927 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
@@ -25,6 +25,10 @@ | |||
25 | printk(KERN_DEBUG format, ##arg); \ | 25 | printk(KERN_DEBUG format, ##arg); \ |
26 | } while (0) | 26 | } while (0) |
27 | 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 | |||
28 | /* | 32 | /* |
29 | * Send a Synaptics style sliced query command | 33 | * Send a Synaptics style sliced query command |
30 | */ | 34 | */ |
@@ -182,13 +186,17 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
182 | static int old_fingers; | 186 | static int old_fingers; |
183 | 187 | ||
184 | if (etd->fw_version_maj == 0x01) { | 188 | if (etd->fw_version_maj == 0x01) { |
185 | /* byte 0: D U p1 p2 1 p3 R L | 189 | /* |
186 | 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 | */ | ||
187 | fingers = ((packet[1] & 0x80) >> 7) + | 193 | fingers = ((packet[1] & 0x80) >> 7) + |
188 | ((packet[1] & 0x30) >> 4); | 194 | ((packet[1] & 0x30) >> 4); |
189 | } else { | 195 | } else { |
190 | /* byte 0: n1 n0 p2 p1 1 p3 R L | 196 | /* |
191 | 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 | */ | ||
192 | fingers = (packet[0] & 0xc0) >> 6; | 200 | fingers = (packet[0] & 0xc0) >> 6; |
193 | } | 201 | } |
194 | 202 | ||
@@ -202,13 +210,15 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
202 | 210 | ||
203 | input_report_key(dev, BTN_TOUCH, fingers != 0); | 211 | input_report_key(dev, BTN_TOUCH, fingers != 0); |
204 | 212 | ||
205 | /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 | 213 | /* |
206 | 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 | */ | ||
207 | if (fingers) { | 217 | if (fingers) { |
208 | input_report_abs(dev, ABS_X, | 218 | input_report_abs(dev, ABS_X, |
209 | ((packet[1] & 0x0c) << 6) | packet[2]); | 219 | ((packet[1] & 0x0c) << 6) | packet[2]); |
210 | input_report_abs(dev, ABS_Y, ETP_YMAX_V1 - | 220 | input_report_abs(dev, ABS_Y, |
211 | (((packet[1] & 0x03) << 8) | packet[3])); | 221 | ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); |
212 | } | 222 | } |
213 | 223 | ||
214 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 224 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
@@ -247,34 +257,47 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
247 | 257 | ||
248 | switch (fingers) { | 258 | switch (fingers) { |
249 | case 1: | 259 | case 1: |
250 | /* byte 1: x15 x14 x13 x12 x11 x10 x9 x8 | 260 | /* |
251 | byte 2: x7 x6 x5 x4 x4 x2 x1 x0 */ | 261 | * byte 1: . . . . . x10 x9 x8 |
252 | input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]); | 262 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 |
253 | /* byte 4: y15 y14 y13 y12 y11 y10 y8 y8 | 263 | */ |
254 | byte 5: y7 y6 y5 y4 y3 y2 y1 y0 */ | 264 | input_report_abs(dev, ABS_X, |
255 | input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - | 265 | ((packet[1] & 0x07) << 8) | packet[2]); |
256 | ((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])); | ||
257 | break; | 272 | break; |
258 | 273 | ||
259 | case 2: | 274 | case 2: |
260 | /* The coordinate of each finger is reported separately with | 275 | /* |
261 | a lower resolution for two finger touches */ | 276 | * The coordinate of each finger is reported separately |
262 | /* byte 0: . . ay8 ax8 . . . . | 277 | * with a lower resolution for two finger touches: |
263 | 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 | */ | ||
264 | x1 = ((packet[0] & 0x10) << 4) | packet[1]; | 281 | x1 = ((packet[0] & 0x10) << 4) | packet[1]; |
265 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ | 282 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ |
266 | y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); | 283 | y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); |
267 | /* byte 3: . . by8 bx8 . . . . | 284 | /* |
268 | 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 | */ | ||
269 | x2 = ((packet[3] & 0x10) << 4) | packet[4]; | 288 | x2 = ((packet[3] & 0x10) << 4) | packet[4]; |
270 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ | 289 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ |
271 | y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); | 290 | y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); |
272 | /* For compatibility with the X Synaptics driver scale up one | 291 | /* |
273 | 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 | */ | ||
274 | input_report_abs(dev, ABS_X, x1 << 2); | 295 | input_report_abs(dev, ABS_X, x1 << 2); |
275 | input_report_abs(dev, ABS_Y, y1 << 2); | 296 | input_report_abs(dev, ABS_Y, y1 << 2); |
276 | /* For compatibility with the proprietary X Elantech driver | 297 | /* |
277 | report both coordinates as hat coordinates */ | 298 | * For compatibility with the proprietary X Elantech driver |
299 | * report both coordinates as hat coordinates | ||
300 | */ | ||
278 | input_report_abs(dev, ABS_HAT0X, x1); | 301 | input_report_abs(dev, ABS_HAT0X, x1); |
279 | input_report_abs(dev, ABS_HAT0Y, y1); | 302 | input_report_abs(dev, ABS_HAT0Y, y1); |
280 | input_report_abs(dev, ABS_HAT1X, x2); | 303 | input_report_abs(dev, ABS_HAT1X, x2); |
@@ -596,8 +619,12 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
596 | param[0], param[1], param[2]); | 619 | param[0], param[1], param[2]); |
597 | 620 | ||
598 | if (param[0] == 0 || param[1] != 0) { | 621 | if (param[0] == 0 || param[1] != 0) { |
599 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); | 622 | if (!force_elantech) { |
600 | 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"); | ||
601 | } | 628 | } |
602 | 629 | ||
603 | if (set_properties) { | 630 | if (set_properties) { |
@@ -666,7 +693,8 @@ int elantech_init(struct psmouse *psmouse) | |||
666 | * Assume every version greater than this is new EeePC style | 693 | * Assume every version greater than this is new EeePC style |
667 | * hardware with 6 byte packets | 694 | * hardware with 6 byte packets |
668 | */ | 695 | */ |
669 | if (etd->fw_version_maj >= 0x02 && etd->fw_version_min >= 0x30) { | 696 | if ((etd->fw_version_maj == 0x02 && etd->fw_version_min >= 0x30) || |
697 | etd->fw_version_maj > 0x02) { | ||
670 | etd->hw_version = 2; | 698 | etd->hw_version = 2; |
671 | /* For now show extra debug information */ | 699 | /* For now show extra debug information */ |
672 | etd->debug = 1; | 700 | etd->debug = 1; |