Input: elantech - better support all those v2 variants
authorJJ Ding <jj_ding@emc.com.tw>
Wed, 21 Sep 2011 05:42:51 +0000 (22:42 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Wed, 21 Sep 2011 05:46:27 +0000 (22:46 -0700)
V2 hardware has many variants. This patch adddresses two issues:

 - some model also has debounce packets, but with a different signature
   than v3. Now we just check debounce for all v2 hardware.

 - due to different scanning methods the hardware uses, x and y ranges have
   to be calculated differently. And for some specific versions, we can just
   see them as custom-made, so set {x, y} the same values as Windows driver
   does.

Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Tested-by: Richard Schütz <r.schtz@t-online.de>
Reviewed-by: Éric Piel <eric.piel@tremplin-utc.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/mouse/elantech.c
drivers/input/mouse/elantech.h

index b8733b377266ce85cdb9b505c2205b27fbfa2569..c2d91ebbadf4a4ba321cc28c7ebeb3d0997e359a 100644 (file)
@@ -613,6 +613,18 @@ static int elantech_packet_check_v1(struct psmouse *psmouse)
               etd->parity[packet[3]] == p3;
 }
 
+static int elantech_debounce_check_v2(struct psmouse *psmouse)
+{
+        /*
+         * When we encounter packet that matches this exactly, it means the
+         * hardware is in debounce status. Just ignore the whole packet.
+         */
+        const u8 debounce_packet[] = { 0x84, 0xff, 0xff, 0x02, 0xff, 0xff };
+        unsigned char *packet = psmouse->packet;
+
+        return !memcmp(packet, debounce_packet, sizeof(debounce_packet));
+}
+
 static int elantech_packet_check_v2(struct psmouse *psmouse)
 {
        struct elantech_data *etd = psmouse->private;
@@ -708,6 +720,10 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
                break;
 
        case 2:
+               /* ignore debounce */
+               if (elantech_debounce_check_v2(psmouse))
+                       return PSMOUSE_FULL_PACKET;
+
                if (etd->paritycheck && !elantech_packet_check_v2(psmouse))
                        return PSMOUSE_BAD_DATA;
 
@@ -825,7 +841,6 @@ static int elantech_set_range(struct psmouse *psmouse,
        struct elantech_data *etd = psmouse->private;
        unsigned char param[3];
        unsigned char traces;
-       int i;
 
        switch (etd->hw_version) {
        case 1:
@@ -844,12 +859,33 @@ static int elantech_set_range(struct psmouse *psmouse,
                        *x_max = ETP_XMAX_V2;
                        *y_max = ETP_YMAX_V2;
                } else {
+                       int i;
+                       int fixed_dpi;
+
                        i = (etd->fw_version > 0x020800 &&
                             etd->fw_version < 0x020900) ? 1 : 2;
-                       *x_min = 0;
-                       *y_min = 0;
-                       *x_max = (etd->capabilities[1] - i) * 64;
-                       *y_max = (etd->capabilities[2] - i) * 64;
+
+                       if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param))
+                               return -1;
+
+                       fixed_dpi = param[1] & 0x10;
+
+                       if (((etd->fw_version >> 16) == 0x14) && fixed_dpi) {
+                               if (synaptics_send_cmd(psmouse, ETP_SAMPLE_QUERY, param))
+                                       return -1;
+
+                               *x_max = (etd->capabilities[1] - i) * param[1] / 2;
+                               *y_max = (etd->capabilities[2] - i) * param[2] / 2;
+                       } else if (etd->fw_version == 0x040216) {
+                               *x_max = 819;
+                               *y_max = 405;
+                       } else if (etd->fw_version == 0x040219 || etd->fw_version == 0x040215) {
+                               *x_max = 900;
+                               *y_max = 500;
+                       } else {
+                               *x_max = (etd->capabilities[1] - i) * 64;
+                               *y_max = (etd->capabilities[2] - i) * 64;
+                       }
                }
                break;
 
index 7ecaef0c07c43aeedb6d7005b2c08c4457daafb3..9e5f1aabea7e92c2abc48fe7de380c17279873be 100644 (file)
@@ -19,6 +19,7 @@
 #define ETP_FW_ID_QUERY                        0x00
 #define ETP_FW_VERSION_QUERY           0x01
 #define ETP_CAPABILITIES_QUERY         0x02
+#define ETP_SAMPLE_QUERY               0x03
 
 /*
  * Command values for register reading or writing