Merge tag 'v4.12-rc3' into next
authorDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 30 May 2017 02:54:21 +0000 (19:54 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 30 May 2017 02:54:21 +0000 (19:54 -0700)
Sync with mainline to bring in changes in platform drovers dropping
calls to sparse_keymap_free() so that we can remove it for good.

1  2 
drivers/input/mouse/elan_i2c_i2c.c
drivers/input/mouse/elantech.c

  #define ETP_I2C_DESC_CMD              0x0001
  #define ETP_I2C_REPORT_DESC_CMD               0x0002
  #define ETP_I2C_STAND_CMD             0x0005
 +#define ETP_I2C_PATTERN_CMD           0x0100
  #define ETP_I2C_UNIQUEID_CMD          0x0101
  #define ETP_I2C_FW_VERSION_CMD                0x0102
 -#define ETP_I2C_SM_VERSION_CMD                0x0103
 +#define ETP_I2C_IC_TYPE_CMD           0x0103
 +#define ETP_I2C_OSM_VERSION_CMD               0x0103
 +#define ETP_I2C_NSM_VERSION_CMD               0x0104
  #define ETP_I2C_XY_TRACENUM_CMD               0x0105
  #define ETP_I2C_MAX_X_AXIS_CMD                0x0106
  #define ETP_I2C_MAX_Y_AXIS_CMD                0x0107
@@@ -242,34 -239,12 +242,34 @@@ static int elan_i2c_get_baseline_data(s
        return 0;
  }
  
 +static int elan_i2c_get_pattern(struct i2c_client *client, u8 *pattern)
 +{
 +      int error;
 +      u8 val[3];
 +
 +      error = elan_i2c_read_cmd(client, ETP_I2C_PATTERN_CMD, val);
 +      if (error) {
 +              dev_err(&client->dev, "failed to get pattern: %d\n", error);
 +              return error;
 +      }
 +      *pattern = val[1];
 +
 +      return 0;
 +}
 +
  static int elan_i2c_get_version(struct i2c_client *client,
                                bool iap, u8 *version)
  {
        int error;
 +      u8 pattern_ver;
        u8 val[3];
  
 +      error = elan_i2c_get_pattern(client, &pattern_ver);
 +      if (error) {
 +              dev_err(&client->dev, "failed to get pattern version\n");
 +              return error;
 +      }
 +
        error = elan_i2c_read_cmd(client,
                                  iap ? ETP_I2C_IAP_VERSION_CMD :
                                        ETP_I2C_FW_VERSION_CMD,
                return error;
        }
  
 -      *version = val[0];
 +      if (pattern_ver == 0x01)
 +              *version = iap ? val[1] : val[0];
 +      else
 +              *version = val[0];
        return 0;
  }
  
  static int elan_i2c_get_sm_version(struct i2c_client *client,
 -                                 u8 *ic_type, u8 *version)
 +                                 u16 *ic_type, u8 *version)
  {
        int error;
 +      u8 pattern_ver;
        u8 val[3];
  
 -      error = elan_i2c_read_cmd(client, ETP_I2C_SM_VERSION_CMD, val);
 +      error = elan_i2c_get_pattern(client, &pattern_ver);
        if (error) {
 -              dev_err(&client->dev, "failed to get SM version: %d\n", error);
 +              dev_err(&client->dev, "failed to get pattern version\n");
                return error;
        }
  
 -      *version = val[0];
 -      *ic_type = val[1];
 +      if (pattern_ver == 0x01) {
 +              error = elan_i2c_read_cmd(client, ETP_I2C_IC_TYPE_CMD, val);
 +              if (error) {
 +                      dev_err(&client->dev, "failed to get ic type: %d\n",
 +                              error);
 +                      return error;
 +              }
 +              *ic_type = be16_to_cpup((__be16 *)val);
 +
 +              error = elan_i2c_read_cmd(client, ETP_I2C_NSM_VERSION_CMD,
 +                                        val);
 +              if (error) {
 +                      dev_err(&client->dev, "failed to get SM version: %d\n",
 +                              error);
 +                      return error;
 +              }
 +              *version = val[1];
 +      } else {
 +              error = elan_i2c_read_cmd(client, ETP_I2C_OSM_VERSION_CMD, val);
 +              if (error) {
 +                      dev_err(&client->dev, "failed to get SM version: %d\n",
 +                              error);
 +                      return error;
 +              }
 +              *version = val[0];
 +              *ic_type = val[1];
 +      }
 +
        return 0;
  }
  
@@@ -609,32 -554,34 +609,34 @@@ static int elan_i2c_finish_fw_update(st
                                     struct completion *completion)
  {
        struct device *dev = &client->dev;
-       long ret;
        int error;
        int len;
-       u8 buffer[ETP_I2C_INF_LENGTH];
+       u8 buffer[ETP_I2C_REPORT_LEN];
+       len = i2c_master_recv(client, buffer, ETP_I2C_REPORT_LEN);
+       if (len != ETP_I2C_REPORT_LEN) {
+               error = len < 0 ? len : -EIO;
+               dev_warn(dev, "failed to read I2C data after FW WDT reset: %d (%d)\n",
+                       error, len);
+       }
  
        reinit_completion(completion);
        enable_irq(client->irq);
  
        error = elan_i2c_write_cmd(client, ETP_I2C_STAND_CMD, ETP_I2C_RESET);
-       if (!error)
-               ret = wait_for_completion_interruptible_timeout(completion,
-                                                       msecs_to_jiffies(300));
-       disable_irq(client->irq);
        if (error) {
                dev_err(dev, "device reset failed: %d\n", error);
-               return error;
-       } else if (ret == 0) {
+       } else if (!wait_for_completion_timeout(completion,
+                                               msecs_to_jiffies(300))) {
                dev_err(dev, "timeout waiting for device reset\n");
-               return -ETIMEDOUT;
-       } else if (ret < 0) {
-               error = ret;
-               dev_err(dev, "error waiting for device reset: %d\n", error);
-               return error;
+               error = -ETIMEDOUT;
        }
  
+       disable_irq(client->irq);
+       if (error)
+               return error;
        len = i2c_master_recv(client, buffer, ETP_I2C_INF_LENGTH);
        if (len != ETP_I2C_INF_LENGTH) {
                error = len < 0 ? len : -EIO;
@@@ -694,7 -641,5 +696,7 @@@ const struct elan_transport_ops elan_i2
        .write_fw_block         = elan_i2c_write_fw_block,
        .finish_fw_update       = elan_i2c_finish_fw_update,
  
 +      .get_pattern            = elan_i2c_get_pattern,
 +
        .get_report             = elan_i2c_get_report,
  };
@@@ -1118,6 -1118,7 +1118,7 @@@ static int elantech_get_resolution_v4(s
   * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
   * Avatar AVIU-145A2       0x361f00        ?               clickpad
   * Fujitsu LIFEBOOK E544   0x470f00        d0, 12, 09      2 hw buttons
+  * Fujitsu LIFEBOOK E547   0x470f00        50, 12, 09      2 hw buttons
   * Fujitsu LIFEBOOK E554   0x570f01        40, 14, 0c      2 hw buttons
   * Fujitsu T725            0x470f01        05, 12, 09      2 hw buttons
   * Fujitsu H730            0x570f00        c0, 14, 0c      3 hw buttons (**)
@@@ -1524,6 -1525,13 +1525,13 @@@ static const struct dmi_system_id elant
                },
        },
        {
+               /* Fujitsu LIFEBOOK E547 does not work with crc_enabled == 0 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E547"),
+               },
+       },
+       {
                /* Fujitsu LIFEBOOK E554  does not work with crc_enabled == 0 */
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
@@@ -1687,17 -1695,6 +1695,17 @@@ int elantech_init(struct psmouse *psmou
                             etd->samples[0], etd->samples[1], etd->samples[2]);
        }
  
 +      if (etd->samples[1] == 0x74 && etd->hw_version == 0x03) {
 +              /*
 +               * This module has a bug which makes absolute mode
 +               * unusable, so let's abort so we'll be using standard
 +               * PS/2 protocol.
 +               */
 +              psmouse_info(psmouse,
 +                           "absolute mode broken, forcing standard PS/2 protocol\n");
 +              goto init_fail;
 +      }
 +
        if (elantech_set_absolute_mode(psmouse)) {
                psmouse_err(psmouse,
                            "failed to put touchpad into absolute mode.\n");