Merge tag 'v4.0-rc5' into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 23 Mar 2015 16:18:27 +0000 (09:18 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 23 Mar 2015 16:18:27 +0000 (09:18 -0700)
Merge with the latest upstream to synchronize Synaptics changes
and bring in new infrastructure pieces.

Conflicts:
drivers/input/mouse/synaptics.c

1  2 
Documentation/devicetree/bindings/vendor-prefixes.txt
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/input/touchscreen/Kconfig
include/uapi/linux/input.h

index 943ed01f9fe59e48e74055284e7f5ebc2b3b4313,fae26d014aaf25c83f499889969e1cb017491f34..c862cf94c9c8780768dcf603f21394c1d866f318
@@@ -4,12 -4,15 +4,15 @@@ This isn't an exhaustive list, but you 
  using them to avoid name-space collisions.
  
  abilis        Abilis Systems
+ abcn  Abracon Corporation
  active-semi   Active-Semi International Inc
  ad    Avionic Design GmbH
  adapteva      Adapteva, Inc.
+ adh   AD Holdings Plc.
  adi   Analog Devices, Inc.
  aeroflexgaisler       Aeroflex Gaisler AB
  allwinner     Allwinner Technology Co., Ltd.
+ alphascale    AlphaScale Integrated Circuits Systems, Inc.
  altr  Altera Corp.
  amcc  Applied Micro Circuits Corporation (APM, formally AMCC)
  amd   Advanced Micro Devices (AMD), Inc.
@@@ -17,12 -20,15 +20,15 @@@ amlogic    Amlogic, Inc
  ams   AMS AG
  amstaos       AMS-Taos Inc.
  apm   Applied Micro Circuits Corporation (APM)
+ arasan        Arasan Chip Systems
  arm   ARM Ltd.
  armadeus      ARMadeus Systems SARL
  asahi-kasei   Asahi Kasei Corp.
  atmel Atmel Corporation
  auo   AU Optronics Corporation
  avago Avago Technologies
+ avic  Shanghai AVIC Optoelectronics Co., Ltd.
+ axis  Axis Communications AB
  bosch Bosch Sensortec GmbH
  brcm  Broadcom Corporation
  buffalo       Buffalo, Inc.
@@@ -31,11 -37,15 +37,15 @@@ capella    Capella Microsystems, In
  cavium        Cavium, Inc.
  cdns  Cadence Design Systems Inc.
  chipidea      Chipidea, Inc
+ chipspark     ChipSPARK
  chrp  Common Hardware Reference Platform
  chunghwa      Chunghwa Picture Tubes Ltd.
  cirrus        Cirrus Logic, Inc.
+ cloudengines  Cloud Engines, Inc.
  cnm   Chips&Media, Inc.
+ cnxt  Conexant Systems, Inc.
  cortina       Cortina Systems, Inc.
+ cosmic        Cosmic Circuits
  crystalfontz  Crystalfontz America, Inc.
  dallas        Maxim Integrated Products (formerly Dallas Semiconductor)
  davicom       DAVICOM Semiconductor, Inc.
@@@ -57,20 -67,23 +67,24 @@@ est        ESTeem Wireless Modem
  ettus NI Ettus Research
  eukrea  EukrĂ©a Electromatique
  everest       Everest Semiconductor Co. Ltd.
+ everspin      Everspin Technologies, Inc.
  excito        Excito
  fcs   Fairchild Semiconductor
+ firefly       Firefly
  fsl   Freescale Semiconductor
  GEFanuc       GE Fanuc Intelligent Platforms Embedded Systems, Inc.
  gef   GE Fanuc Intelligent Platforms Embedded Systems, Inc.
  geniatech     Geniatech, Inc.
+ giantplus     Giantplus Technology Co., Ltd.
  globalscale   Globalscale Technologies, Inc.
  gmt   Global Mixed-mode Technology, Inc.
 +goodix        Shenzhen Huiding Technology Co., Ltd.
  google        Google, Inc.
  gumstix       Gumstix, Inc.
  gw    Gateworks Corporation
  hannstar      HannStar Display Corporation
  haoyu Haoyu Microelectronic Co. Ltd.
+ himax Himax Technologies, Inc.
  hisilicon     Hisilicon Limited.
  hit   Hitachi Ltd.
  honeywell     Honeywell
@@@ -84,8 -97,7 +98,7 @@@ innolux       Innolux Corporatio
  intel Intel Corporation
  intercontrol  Inter Control Group
  isee  ISEE 2007 S.L.
- isil    Intersil (deprecated, use isl)
- isl   Intersil
+ isil  Intersil
  karo  Ka-Ro electronics GmbH
  keymile       Keymile GmbH
  lacie LaCie
@@@ -120,7 -132,9 +133,9 @@@ nvidia     NVIDI
  nxp   NXP Semiconductors
  onnn  ON Semiconductor Corp.
  opencores     OpenCores.org
+ ovti  OmniVision Technologies
  panasonic     Panasonic Corporation
+ parade        Parade Technologies Inc.
  pericom       Pericom Technology Inc.
  phytec        PHYTEC Messtechnik GmbH
  picochip      Picochip Ltd
@@@ -144,8 -158,10 +159,10 @@@ sandisk  Sandisk Corporatio
  sbs   Smart Battery System
  schindler     Schindler
  seagate       Seagate Technology PLC
+ semtech       Semtech Corporation
  sil   Silicon Image
  silabs        Silicon Laboratories
+ siliconmitus  Silicon Mitus, Inc.
  simtek
  sii   Seiko Instruments, Inc.
  silergy       Silergy Corp.
@@@ -156,6 -172,7 +173,7 @@@ snps       Synopsys, Inc
  solidrun      SolidRun
  sony  Sony Corporation
  spansion      Spansion Inc.
+ sprd  Spreadtrum Communications Inc.
  st    STMicroelectronics
  ste   ST-Ericsson
  stericsson    ST-Ericsson
@@@ -167,6 -184,7 +185,7 @@@ tlm        Trusted Logic Mobilit
  toradex       Toradex AG
  toshiba       Toshiba Corporation
  toumaz        Toumaz
+ truly Truly Semiconductors Limited
  usi   Universal Scientific Industrial Co., Ltd.
  v3    V3 Semiconductor
  variscite     Variscite Ltd.
index bd91a8efa0f177a9a0216b8278e0bc089479b34e,8bc61237bc1b1c95d43b0d7e3d11e90275aa8d4a..27057df7ba74eeeba06f24f0e24fcf6d4387eda3
@@@ -453,6 -453,17 +453,17 @@@ static void psmouse_set_rate(struct psm
        psmouse->rate = r;
  }
  
+ /*
+  * Here we set the mouse scaling.
+  */
+ static void psmouse_set_scale(struct psmouse *psmouse, enum psmouse_scale scale)
+ {
+       ps2_command(&psmouse->ps2dev, NULL,
+                   scale == PSMOUSE_SCALE21 ? PSMOUSE_CMD_SETSCALE21 :
+                                              PSMOUSE_CMD_SETSCALE11);
+ }
  /*
   * psmouse_poll() - default poll handler. Everyone except for ALPS uses it.
   */
@@@ -463,45 -474,19 +474,45 @@@ static int psmouse_poll(struct psmouse 
                           PSMOUSE_CMD_POLL | (psmouse->pktsize << 8));
  }
  
 +static bool psmouse_check_pnp_id(const char *id, const char * const ids[])
 +{
 +      int i;
 +
 +      for (i = 0; ids[i]; i++)
 +              if (!strcasecmp(id, ids[i]))
 +                      return true;
 +
 +      return false;
 +}
 +
  /*
   * psmouse_matches_pnp_id - check if psmouse matches one of the passed in ids.
   */
  bool psmouse_matches_pnp_id(struct psmouse *psmouse, const char * const ids[])
  {
 -      int i;
 -
 -      if (!strncmp(psmouse->ps2dev.serio->firmware_id, "PNP:", 4))
 -              for (i = 0; ids[i]; i++)
 -                      if (strstr(psmouse->ps2dev.serio->firmware_id, ids[i]))
 -                              return true;
 +      struct serio *serio = psmouse->ps2dev.serio;
 +      char *p, *fw_id_copy, *save_ptr;
 +      bool found = false;
 +
 +      if (strncmp(serio->firmware_id, "PNP: ", 5))
 +              return false;
 +
 +      fw_id_copy = kstrndup(&serio->firmware_id[5],
 +                            sizeof(serio->firmware_id) - 5,
 +                            GFP_KERNEL);
 +      if (!fw_id_copy)
 +              return false;
 +
 +      save_ptr = fw_id_copy;
 +      while ((p = strsep(&fw_id_copy, " ")) != NULL) {
 +              if (psmouse_check_pnp_id(p, ids)) {
 +                      found = true;
 +                      break;
 +              }
 +      }
  
 -      return false;
 +      kfree(save_ptr);
 +      return found;
  }
  
  /*
@@@ -715,6 -700,7 +726,7 @@@ static void psmouse_apply_defaults(stru
  
        psmouse->set_rate = psmouse_set_rate;
        psmouse->set_resolution = psmouse_set_resolution;
+       psmouse->set_scale = psmouse_set_scale;
        psmouse->poll = psmouse_poll;
        psmouse->protocol_handler = psmouse_process_byte;
        psmouse->pktsize = 3;
@@@ -1186,7 -1172,7 +1198,7 @@@ static void psmouse_initialize(struct p
        if (psmouse_max_proto != PSMOUSE_PS2) {
                psmouse->set_rate(psmouse, psmouse->rate);
                psmouse->set_resolution(psmouse, psmouse->resolution);
-               ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11);
+               psmouse->set_scale(psmouse, PSMOUSE_SCALE11);
        }
  }
  
index 4c69e3304011d936ddc01b3f4a64e97cd0ebd353,dda605836546847afbdbdd4c77c976134a914a2e..d73a94270211041293c140b9144300621dcba9af
@@@ -67,9 -67,6 +67,6 @@@
  #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
   ****************************************************************************/
@@@ -123,32 -120,41 +120,41 @@@ void synaptics_reset(struct psmouse *ps
  
  static bool cr48_profile_sensor;
  
+ #define ANY_BOARD_ID 0
  struct min_max_quirk {
        const char * const *pnp_ids;
+       struct {
+               unsigned long int min, max;
+       } board_id;
        int x_min, x_max, y_min, y_max;
  };
  
  static const struct min_max_quirk min_max_pnpid_table[] = {
        {
                (const char * const []){"LEN0033", NULL},
+               {ANY_BOARD_ID, ANY_BOARD_ID},
                1024, 5052, 2258, 4832
        },
        {
-               (const char * const []){"LEN0035", "LEN0042", NULL},
+               (const char * const []){"LEN0042", NULL},
+               {ANY_BOARD_ID, ANY_BOARD_ID},
                1232, 5710, 1156, 4696
        },
        {
                (const char * const []){"LEN0034", "LEN0036", "LEN0037",
                                        "LEN0039", "LEN2002", "LEN2004",
                                        NULL},
+               {ANY_BOARD_ID, 2961},
                1024, 5112, 2024, 4832
        },
        {
                (const char * const []){"LEN2001", NULL},
+               {ANY_BOARD_ID, ANY_BOARD_ID},
                1024, 5022, 2508, 4832
        },
        {
                (const char * const []){"LEN2006", NULL},
+               {ANY_BOARD_ID, ANY_BOARD_ID},
                1264, 5675, 1171, 4688
        },
        { }
@@@ -175,9 -181,7 +181,7 @@@ static const char * const topbuttonpad_
        "LEN0041",
        "LEN0042", /* Yoga */
        "LEN0045",
-       "LEN0046",
        "LEN0047",
-       "LEN0048",
        "LEN0049",
        "LEN2000",
        "LEN2001", /* Edge E431 */
        NULL
  };
  
 +/* This list has been kindly provided by Synaptics. */
 +static const char * const forcepad_pnp_ids[] = {
 +      "SYN300D",
 +      "SYN3014",
 +      NULL
 +};
 +
  /*****************************************************************************
   *    Synaptics communications functions
   ****************************************************************************/
@@@ -242,18 -239,39 +246,39 @@@ static int synaptics_model_id(struct ps
        return 0;
  }
  
+ static int synaptics_more_extended_queries(struct psmouse *psmouse)
+ {
+       struct synaptics_data *priv = psmouse->private;
+       unsigned char buf[3];
+       if (synaptics_send_cmd(psmouse, SYN_QUE_MEXT_CAPAB_10, buf))
+               return -1;
+       priv->ext_cap_10 = (buf[0]<<16) | (buf[1]<<8) | buf[2];
+       return 0;
+ }
  /*
-  * Read the board id from the touchpad
+  * Read the board id and the "More Extended Queries" from the touchpad
   * The board id is encoded in the "QUERY MODES" response
   */
- static int synaptics_board_id(struct psmouse *psmouse)
+ static int synaptics_query_modes(struct psmouse *psmouse)
  {
        struct synaptics_data *priv = psmouse->private;
        unsigned char bid[3];
  
+       /* firmwares prior 7.5 have no board_id encoded */
+       if (SYN_ID_FULL(priv->identity) < 0x705)
+               return 0;
        if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid))
                return -1;
        priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1];
+       if (SYN_MEXT_CAP_BIT(bid[0]))
+               return synaptics_more_extended_queries(psmouse);
        return 0;
  }
  
@@@ -353,7 -371,6 +378,6 @@@ static int synaptics_resolution(struct 
  {
        struct synaptics_data *priv = psmouse->private;
        unsigned char resp[3];
-       int i;
  
        if (SYN_ID_MAJOR(priv->identity) < 4)
                return 0;
                }
        }
  
-       for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) {
-               if (psmouse_matches_pnp_id(psmouse,
-                                          min_max_pnpid_table[i].pnp_ids)) {
-                       priv->x_min = min_max_pnpid_table[i].x_min;
-                       priv->x_max = min_max_pnpid_table[i].x_max;
-                       priv->y_min = min_max_pnpid_table[i].y_min;
-                       priv->y_max = min_max_pnpid_table[i].y_max;
-                       return 0;
-               }
-       }
        if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 &&
            SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) {
                if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) {
                } else {
                        priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
                        priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
+                       psmouse_info(psmouse,
+                                    "queried max coordinates: x [..%d], y [..%d]\n",
+                                    priv->x_max, priv->y_max);
                }
        }
  
-       if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 &&
-           SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) {
+       if (SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c) &&
+           (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 ||
+            /*
+             * Firmware v8.1 does not report proper number of extended
+             * capabilities, but has been proven to report correct min
+             * coordinates.
+             */
+            SYN_ID_FULL(priv->identity) == 0x801)) {
                if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) {
                        psmouse_warn(psmouse,
                                     "device claims to have min coordinates query, but I'm not able to read it.\n");
                } else {
                        priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1);
                        priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3);
+                       psmouse_info(psmouse,
+                                    "queried min coordinates: x [%d..], y [%d..]\n",
+                                    priv->x_min, priv->y_min);
                }
        }
  
        return 0;
  }
  
+ /*
+  * Apply quirk(s) if the hardware matches
+  */
+ static void synaptics_apply_quirks(struct psmouse *psmouse)
+ {
+       struct synaptics_data *priv = psmouse->private;
+       int i;
+       for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) {
+               if (!psmouse_matches_pnp_id(psmouse,
+                                           min_max_pnpid_table[i].pnp_ids))
+                       continue;
+               if (min_max_pnpid_table[i].board_id.min != ANY_BOARD_ID &&
+                   priv->board_id < min_max_pnpid_table[i].board_id.min)
+                       continue;
+               if (min_max_pnpid_table[i].board_id.max != ANY_BOARD_ID &&
+                   priv->board_id > min_max_pnpid_table[i].board_id.max)
+                       continue;
+               priv->x_min = min_max_pnpid_table[i].x_min;
+               priv->x_max = min_max_pnpid_table[i].x_max;
+               priv->y_min = min_max_pnpid_table[i].y_min;
+               priv->y_max = min_max_pnpid_table[i].y_max;
+               psmouse_info(psmouse,
+                            "quirked min/max coordinates: x [%d..%d], y [%d..%d]\n",
+                            priv->x_min, priv->x_max,
+                            priv->y_min, priv->y_max);
+               break;
+       }
+ }
  static int synaptics_query_hardware(struct psmouse *psmouse)
  {
        if (synaptics_identify(psmouse))
                return -1;
        if (synaptics_firmware_id(psmouse))
                return -1;
-       if (synaptics_board_id(psmouse))
+       if (synaptics_query_modes(psmouse))
                return -1;
        if (synaptics_capability(psmouse))
                return -1;
        if (synaptics_resolution(psmouse))
                return -1;
  
+       synaptics_apply_quirks(psmouse);
        return 0;
  }
  
@@@ -523,18 -577,22 +584,22 @@@ static int synaptics_is_pt_packet(unsig
        return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
  }
  
- static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
+ static void synaptics_pass_pt_packet(struct psmouse *psmouse,
+                                    struct serio *ptport,
+                                    unsigned char *packet)
  {
+       struct synaptics_data *priv = psmouse->private;
        struct psmouse *child = serio_get_drvdata(ptport);
  
        if (child && child->state == PSMOUSE_ACTIVATED) {
-               serio_interrupt(ptport, packet[1], 0);
+               serio_interrupt(ptport, packet[1] | priv->pt_buttons, 0);
                serio_interrupt(ptport, packet[4], 0);
                serio_interrupt(ptport, packet[5], 0);
                if (child->pktsize == 4)
                        serio_interrupt(ptport, packet[2], 0);
-       } else
+       } else {
                serio_interrupt(ptport, packet[1], 0);
+       }
  }
  
  static void synaptics_pt_activate(struct psmouse *psmouse)
@@@ -612,6 -670,20 +677,18 @@@ static void synaptics_parse_agm(const u
        }
  }
  
 -static bool is_forcepad;
 -
+ static void synaptics_parse_ext_buttons(const unsigned char buf[],
+                                       struct synaptics_data *priv,
+                                       struct synaptics_hw_state *hw)
+ {
+       unsigned int ext_bits =
+               (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1;
+       unsigned int ext_mask = GENMASK(ext_bits - 1, 0);
+       hw->ext_buttons = buf[4] & ext_mask;
+       hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits;
+ }
  static int synaptics_parse_hw_state(const unsigned char buf[],
                                    struct synaptics_data *priv,
                                    struct synaptics_hw_state *hw)
                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.
                        hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
                }
  
-               if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
+               if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 0 &&
                    ((buf[0] ^ buf[3]) & 0x02)) {
-                       switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
-                       default:
-                               /*
-                                * if nExtBtn is greater than 8 it should be
-                                * considered invalid and treated as 0
-                                */
-                               break;
-                       case 8:
-                               hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
-                               hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
-                       case 6:
-                               hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
-                               hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
-                       case 4:
-                               hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
-                               hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
-                       case 2:
-                               hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
-                               hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
-                       }
+                       synaptics_parse_ext_buttons(buf, priv, hw);
                }
        } else {
                hw->x = (((buf[1] & 0x1f) << 8) | buf[2]);
@@@ -779,12 -832,54 +837,54 @@@ static void synaptics_report_semi_mt_da
        }
  }
  
+ static void synaptics_report_ext_buttons(struct psmouse *psmouse,
+                                        const struct synaptics_hw_state *hw)
+ {
+       struct input_dev *dev = psmouse->dev;
+       struct synaptics_data *priv = psmouse->private;
+       int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1;
+       char buf[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+       int i;
+       if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
+               return;
+       /* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */
+       if (SYN_ID_FULL(priv->identity) == 0x801 &&
+           !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02))
+               return;
+       if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) {
+               for (i = 0; i < ext_bits; i++) {
+                       input_report_key(dev, BTN_0 + 2 * i,
+                               hw->ext_buttons & (1 << i));
+                       input_report_key(dev, BTN_1 + 2 * i,
+                               hw->ext_buttons & (1 << (i + ext_bits)));
+               }
+               return;
+       }
+       /*
+        * This generation of touchpads has the trackstick buttons
+        * physically wired to the touchpad. Re-route them through
+        * the pass-through interface.
+        */
+       if (!priv->pt_port)
+               return;
+       /* The trackstick expects at most 3 buttons */
+       priv->pt_buttons = SYN_CAP_EXT_BUTTON_STICK_L(hw->ext_buttons)      |
+                          SYN_CAP_EXT_BUTTON_STICK_R(hw->ext_buttons) << 1 |
+                          SYN_CAP_EXT_BUTTON_STICK_M(hw->ext_buttons) << 2;
+       synaptics_pass_pt_packet(psmouse, priv->pt_port, buf);
+ }
  static void synaptics_report_buttons(struct psmouse *psmouse,
                                     const struct synaptics_hw_state *hw)
  {
        struct input_dev *dev = psmouse->dev;
        struct synaptics_data *priv = psmouse->private;
-       int i;
  
        input_report_key(dev, BTN_LEFT, hw->left);
        input_report_key(dev, BTN_RIGHT, hw->right);
                input_report_key(dev, BTN_BACK, hw->down);
        }
  
-       for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
-               input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i));
+       synaptics_report_ext_buttons(psmouse, hw);
  }
  
  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, DMAX * priv->x_res);
+       input_mt_assign_slots(dev, slot, pos, nsemi, 0);
  
        for (i = 0; i < nsemi; i++) {
                input_mt_slot(dev, slot[i]);
@@@ -1019,7 -1113,8 +1118,8 @@@ static psmouse_ret_t synaptics_process_
                if (SYN_CAP_PASS_THROUGH(priv->capabilities) &&
                    synaptics_is_pt_packet(psmouse->packet)) {
                        if (priv->pt_port)
-                               synaptics_pass_pt_packet(priv->pt_port, psmouse->packet);
+                               synaptics_pass_pt_packet(psmouse, priv->pt_port,
+                                                        psmouse->packet);
                } else
                        synaptics_process_packet(psmouse);
  
@@@ -1121,8 -1216,9 +1221,9 @@@ static void set_input_params(struct psm
                __set_bit(BTN_BACK, dev->keybit);
        }
  
-       for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
-               __set_bit(BTN_0 + i, dev->keybit);
+       if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10))
+               for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
+                       __set_bit(BTN_0 + i, dev->keybit);
  
        __clear_bit(EV_REL, dev->evbit);
        __clear_bit(REL_X, dev->relbit);
  
        if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
                __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
-               if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids))
+               if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) &&
+                   !SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10))
                        __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit);
                /* Clickpads report only left button */
                __clear_bit(BTN_RIGHT, dev->keybit);
@@@ -1316,11 -1413,29 +1418,11 @@@ static const struct dmi_system_id __ini
        { }
  };
  
 -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)
        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;
index fb3838ca28de6a41744844b5fea9ae06345ac491,ee4bd0d12b26fa2770445a381134b62124be6741..56faa7ec443480af63e66b56819be46fb44a6ee7
@@@ -22,6 -22,7 +22,7 @@@
  #define SYN_QUE_EXT_CAPAB_0C          0x0c
  #define SYN_QUE_EXT_MAX_COORDS                0x0d
  #define SYN_QUE_EXT_MIN_COORDS                0x0f
+ #define SYN_QUE_MEXT_CAPAB_10         0x10
  
  /* synatics modes */
  #define SYN_BIT_ABSOLUTE_MODE         (1 << 7)
@@@ -53,6 -54,7 +54,7 @@@
  #define SYN_EXT_CAP_REQUESTS(c)               (((c) & 0x700000) >> 20)
  #define SYN_CAP_MULTI_BUTTON_NO(ec)   (((ec) & 0x00f000) >> 12)
  #define SYN_CAP_PRODUCT_ID(ec)                (((ec) & 0xff0000) >> 16)
+ #define SYN_MEXT_CAP_BIT(m)           ((m) & (1 << 1))
  
  /*
   * The following describes response for the 0x0c query.
  #define SYN_CAP_REDUCED_FILTERING(ex0c)       ((ex0c) & 0x000400)
  #define SYN_CAP_IMAGE_SENSOR(ex0c)    ((ex0c) & 0x000800)
  
+ /*
+  * The following descibes response for the 0x10 query.
+  *
+  * byte       mask    name                    meaning
+  * ----       ----    -------                 ------------
+  * 1  0x01    ext buttons are stick   buttons exported in the extended
+  *                                    capability are actually meant to be used
+  *                                    by the tracktick (pass-through).
+  * 1  0x02    SecurePad               the touchpad is a SecurePad, so it
+  *                                    contains a built-in fingerprint reader.
+  * 1  0xe0    more ext count          how many more extented queries are
+  *                                    available after this one.
+  * 2  0xff    SecurePad width         the width of the SecurePad fingerprint
+  *                                    reader.
+  * 3  0xff    SecurePad height        the height of the SecurePad fingerprint
+  *                                    reader.
+  */
+ #define SYN_CAP_EXT_BUTTONS_STICK(ex10)       ((ex10) & 0x010000)
+ #define SYN_CAP_SECUREPAD(ex10)               ((ex10) & 0x020000)
+ #define SYN_CAP_EXT_BUTTON_STICK_L(eb)        (!!((eb) & 0x01))
+ #define SYN_CAP_EXT_BUTTON_STICK_M(eb)        (!!((eb) & 0x02))
+ #define SYN_CAP_EXT_BUTTON_STICK_R(eb)        (!!((eb) & 0x04))
  /* synaptics modes query bits */
  #define SYN_MODE_ABSOLUTE(m)          ((m) & (1 << 7))
  #define SYN_MODE_RATE(m)              ((m) & (1 << 6))
@@@ -143,6 -169,7 +169,7 @@@ struct synaptics_data 
        unsigned long int capabilities;         /* Capabilities */
        unsigned long int ext_cap;              /* Extended Capabilities */
        unsigned long int ext_cap_0c;           /* Ext Caps from 0x0c query */
+       unsigned long int ext_cap_10;           /* Ext Caps from 0x10 query */
        unsigned long int identity;             /* Identification */
        unsigned int x_res, y_res;              /* X/Y resolution in units/mm */
        unsigned int x_max, y_max;              /* Max coordinates (from FW) */
        bool disable_gesture;                   /* disable gestures */
  
        struct serio *pt_port;                  /* Pass-through serio port */
+       unsigned char pt_buttons;               /* Pass-through buttons */
  
        /*
         * Last received Advanced Gesture Mode (AGM) packet. An AGM packet
        unsigned long                           press_start;
        bool                                    press;
        bool                                    report_press;
 +      bool                                    is_forcepad;
  };
  
  void synaptics_module_init(void);
index 2310d863a6f1d62ad5d23c3141ad0767b44d1c7b,6261fd6d7c3c4ddcb758b6796b0ba6ca0c222c99..1130c40591045e3c8919b68e71cc36c2806142fe
@@@ -297,12 -297,11 +297,12 @@@ config TOUCHSCREEN_FUJITS
  
  config TOUCHSCREEN_GOODIX
        tristate "Goodix I2C touchscreen"
 -      depends on I2C && ACPI
 +      depends on I2C
        help
          Say Y here if you have the Goodix touchscreen (such as one
          installed in Onda v975w tablets) connected to your
 -        system.
 +        system. It also supports 5-finger chip models, which can be
 +        found on ARM tablets, like Wexler TAB7200 and MSI Primo73.
  
          If unsure, say N.
  
@@@ -944,6 -943,7 +944,7 @@@ config TOUCHSCREEN_SUN4
        tristate "Allwinner sun4i resistive touchscreen controller support"
        depends on ARCH_SUNXI || COMPILE_TEST
        depends on HWMON
+       depends on THERMAL || !THERMAL_OF
        help
          This selects support for the resistive touchscreen controller
          found on Allwinner sunxi SoCs.
@@@ -962,17 -962,6 +963,17 @@@ config TOUCHSCREEN_SUR4
          To compile this driver as a module, choose M here: the
          module will be called sur40.
  
 +config TOUCHSCREEN_SX8654
 +      tristate "Semtech SX8654 touchscreen"
 +      depends on I2C
 +      help
 +        Say Y here if you have a Semtech SX8654 touchscreen controller.
 +
 +        If unsure, say N
 +
 +        To compile this driver as a module, choose M here: the
 +        module will be called sx8654.
 +
  config TOUCHSCREEN_TPS6507X
        tristate "TPS6507x based touchscreens"
        depends on I2C
index eff1cf18031ef29c04b46db96b34e65f9f782ec1,b0a81307985282005ade90ee6da96e3048c405d3..8ddbf1fbbed5255291e58575933eb2a3adbb29e7
@@@ -166,6 -166,7 +166,7 @@@ struct input_keymap_entry 
  #define INPUT_PROP_SEMI_MT            0x03    /* touch rectangle only */
  #define INPUT_PROP_TOPBUTTONPAD               0x04    /* softbuttons at top of pad */
  #define INPUT_PROP_POINTING_STICK     0x05    /* is a pointing stick */
+ #define INPUT_PROP_ACCELEROMETER      0x06    /* has accelerometer */
  
  #define INPUT_PROP_MAX                        0x1f
  #define INPUT_PROP_CNT                        (INPUT_PROP_MAX + 1)
  #define KEY_MSDOS             151
  #define KEY_COFFEE            152     /* AL Terminal Lock/Screensaver */
  #define KEY_SCREENLOCK                KEY_COFFEE
 -#define KEY_DIRECTION         153
 +#define KEY_ROTATE_DISPLAY    153     /* Display orientation for e.g. tablets */
 +#define KEY_DIRECTION         KEY_ROTATE_DISPLAY
  #define KEY_CYCLEWINDOWS      154
  #define KEY_MAIL              155
  #define KEY_BOOKMARKS         156     /* AC Bookmarks */