Input: synaptics - fix handling of disabling gesture mode
[cascardo/linux.git] / drivers / input / mouse / synaptics.c
index f6a3a7b..994ae78 100644 (file)
@@ -67,6 +67,9 @@
 #define X_MAX_POSITIVE 8176
 #define Y_MAX_POSITIVE 8176
 
+/* maximum ABS_MT_POSITION displacement (in mm) */
+#define DMAX 10
+
 /*****************************************************************************
  *     Stuff we need even when we do not want native Synaptics support
  ****************************************************************************/
@@ -147,6 +150,11 @@ static const struct min_max_quirk min_max_pnpid_table[] = {
                {ANY_BOARD_ID, 2961},
                1024, 5112, 2024, 4832
        },
+       {
+               (const char * const []){"LEN2000", NULL},
+               {ANY_BOARD_ID, ANY_BOARD_ID},
+               1024, 5113, 2021, 4832
+       },
        {
                (const char * const []){"LEN2001", NULL},
                {ANY_BOARD_ID, ANY_BOARD_ID},
@@ -155,7 +163,7 @@ static const struct min_max_quirk min_max_pnpid_table[] = {
        {
                (const char * const []){"LEN2006", NULL},
                {2691, 2691},
-               1024, 5045, 2457, 4632
+               1024, 5045, 2457, 4832
        },
        {
                (const char * const []){"LEN2006", NULL},
@@ -188,7 +196,7 @@ static const char * const topbuttonpad_pnp_ids[] = {
        "LEN0045",
        "LEN0047",
        "LEN0049",
-       "LEN2000",
+       "LEN2000", /* S540 */
        "LEN2001", /* Edge E431 */
        "LEN2002", /* Edge E531 */
        "LEN2003",
@@ -203,6 +211,13 @@ static const char * const topbuttonpad_pnp_ids[] = {
        NULL
 };
 
+/* This list has been kindly provided by Synaptics. */
+static const char * const forcepad_pnp_ids[] = {
+       "SYN300D",
+       "SYN3014",
+       NULL
+};
+
 /*****************************************************************************
  *     Synaptics communications functions
  ****************************************************************************/
@@ -504,14 +519,18 @@ static int synaptics_set_mode(struct psmouse *psmouse)
        struct synaptics_data *priv = psmouse->private;
 
        priv->mode = 0;
-       if (priv->absolute_mode)
+
+       if (priv->absolute_mode) {
                priv->mode |= SYN_BIT_ABSOLUTE_MODE;
-       if (priv->disable_gesture)
+               if (SYN_CAP_EXTENDED(priv->capabilities))
+                       priv->mode |= SYN_BIT_W_MODE;
+       }
+
+       if (!SYN_MODE_WMODE(priv->mode) && priv->disable_gesture)
                priv->mode |= SYN_BIT_DISABLE_GESTURE;
+
        if (psmouse->rate >= 80)
                priv->mode |= SYN_BIT_HIGH_RATE;
-       if (SYN_CAP_EXTENDED(priv->capabilities))
-               priv->mode |= SYN_BIT_W_MODE;
 
        if (synaptics_mode_cmd(psmouse, priv->mode))
                return -1;
@@ -687,8 +706,6 @@ static void synaptics_parse_ext_buttons(const unsigned char buf[],
        hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits;
 }
 
-static bool is_forcepad;
-
 static int synaptics_parse_hw_state(const unsigned char buf[],
                                    struct synaptics_data *priv,
                                    struct synaptics_hw_state *hw)
@@ -718,7 +735,7 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
                hw->left  = (buf[0] & 0x01) ? 1 : 0;
                hw->right = (buf[0] & 0x02) ? 1 : 0;
 
-               if (is_forcepad) {
+               if (priv->is_forcepad) {
                        /*
                         * ForcePads, like Clickpads, use middle button
                         * bits to report primary button clicks.
@@ -917,7 +934,7 @@ static void synaptics_report_mt_data(struct psmouse *psmouse,
                pos[i].y = synaptics_invert_y(hw[i]->y);
        }
 
-       input_mt_assign_slots(dev, slot, pos, nsemi, 0);
+       input_mt_assign_slots(dev, slot, pos, nsemi, DMAX * priv->x_res);
 
        for (i = 0; i < nsemi; i++) {
                input_mt_slot(dev, slot[i]);
@@ -1418,29 +1435,11 @@ static const struct dmi_system_id __initconst cr48_dmi_table[] = {
        { }
 };
 
-static const struct dmi_system_id forcepad_dmi_table[] __initconst = {
-#if defined(CONFIG_DMI) && defined(CONFIG_X86)
-       {
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook Folio 1040 G1"),
-               },
-       },
-#endif
-       { }
-};
-
 void __init synaptics_module_init(void)
 {
        impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table);
        broken_olpc_ec = dmi_check_system(olpc_dmi_table);
        cr48_profile_sensor = dmi_check_system(cr48_dmi_table);
-
-       /*
-        * Unfortunately ForcePad capability is not exported over PS/2,
-        * so we have to resort to checking DMI.
-        */
-       is_forcepad = dmi_check_system(forcepad_dmi_table);
 }
 
 static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
@@ -1475,6 +1474,12 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
        if (SYN_ID_DISGEST_SUPPORTED(priv->identity))
                priv->disable_gesture = true;
 
+       /*
+        * Unfortunately ForcePad capability is not exported over PS/2,
+        * so we have to resort to checking PNP IDs.
+        */
+       priv->is_forcepad = psmouse_matches_pnp_id(psmouse, forcepad_pnp_ids);
+
        if (synaptics_set_mode(psmouse)) {
                psmouse_err(psmouse, "Unable to initialize device.\n");
                goto init_fail;
@@ -1483,12 +1488,12 @@ static int __synaptics_init(struct psmouse *psmouse, bool absolute_mode)
        priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
 
        psmouse_info(psmouse,
-                    "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n",
+                    "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n",
                     SYN_ID_MODEL(priv->identity),
                     SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
                     priv->model_id,
                     priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
-                    priv->board_id, priv->firmware_id);
+                    priv->ext_cap_10, priv->board_id, priv->firmware_id);
 
        set_input_params(psmouse, priv);