aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/mouse/elantech.c
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2010-05-10 09:32:46 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2010-05-10 09:32:46 -0400
commit0ae28a35bcb7984838acbf28bfba9c030f8b74f0 (patch)
tree4f449d929b5df9e126e839f388ff0fd2b52028a0 /drivers/input/mouse/elantech.c
parent6f1f3d0ab5c3eeea9f04486481c25e9afdfa26c5 (diff)
parentb57f95a38233a2e73b679bea4a5453a1cc2a1cc9 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts: drivers/mtd/mtdcore.c Pull in the bdi fixes and ARM platform changes that other outstanding patches depend on.
Diffstat (limited to 'drivers/input/mouse/elantech.c')
-rw-r--r--drivers/input/mouse/elantech.c85
1 files changed, 57 insertions, 28 deletions
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index b27684f267bf..0520c2e19927 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
28static bool force_elantech;
29module_param_named(force_elantech, force_elantech, bool, 0644);
30MODULE_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 */
@@ -181,13 +186,17 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse)
181 static int old_fingers; 186 static int old_fingers;
182 187
183 if (etd->fw_version_maj == 0x01) { 188 if (etd->fw_version_maj == 0x01) {
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);
@@ -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);
@@ -595,8 +619,12 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
595 param[0], param[1], param[2]); 619 param[0], param[1], param[2]);
596 620
597 if (param[0] == 0 || param[1] != 0) { 621 if (param[0] == 0 || param[1] != 0) {
598 pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); 622 if (!force_elantech) {
599 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");
600 } 628 }
601 629
602 if (set_properties) { 630 if (set_properties) {
@@ -665,7 +693,8 @@ int elantech_init(struct psmouse *psmouse)
665 * Assume every version greater than this is new EeePC style 693 * Assume every version greater than this is new EeePC style
666 * hardware with 6 byte packets 694 * hardware with 6 byte packets
667 */ 695 */
668 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) {
669 etd->hw_version = 2; 698 etd->hw_version = 2;
670 /* For now show extra debug information */ 699 /* For now show extra debug information */
671 etd->debug = 1; 700 etd->debug = 1;