Merge branch 'next' into for-linus
[sfrench/cifs-2.6.git] / drivers / input / mouse / elan_i2c_core.c
index bef73822315d5139ab81804c209d3d90f1648d2b..dad22c1ea6a0ff3c6763205fe2b8fd46393f25ea 100644 (file)
@@ -46,6 +46,9 @@
 #define ETP_FINGER_WIDTH       15
 #define ETP_RETRY_COUNT                3
 
+/* quirks to control the device */
+#define ETP_QUIRK_QUICK_WAKEUP BIT(0)
+
 /* The main device structure */
 struct elan_tp_data {
        struct i2c_client       *client;
@@ -90,8 +93,38 @@ struct elan_tp_data {
        bool                    baseline_ready;
        u8                      clickpad;
        bool                    middle_button;
+
+       u32                     quirks;         /* Various quirks */
 };
 
+static u32 elan_i2c_lookup_quirks(u16 ic_type, u16 product_id)
+{
+       static const struct {
+               u16 ic_type;
+               u16 product_id;
+               u32 quirks;
+       } elan_i2c_quirks[] = {
+               { 0x0D, ETP_PRODUCT_ID_DELBIN, ETP_QUIRK_QUICK_WAKEUP },
+               { 0x10, ETP_PRODUCT_ID_VOXEL, ETP_QUIRK_QUICK_WAKEUP },
+               { 0x14, ETP_PRODUCT_ID_MAGPIE, ETP_QUIRK_QUICK_WAKEUP },
+               { 0x14, ETP_PRODUCT_ID_BOBBA, ETP_QUIRK_QUICK_WAKEUP },
+       };
+       u32 quirks = 0;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(elan_i2c_quirks); i++) {
+               if (elan_i2c_quirks[i].ic_type == ic_type &&
+                   elan_i2c_quirks[i].product_id == product_id) {
+                       quirks = elan_i2c_quirks[i].quirks;
+               }
+       }
+
+       if (ic_type >= 0x0D && product_id >= 0x123)
+               quirks |= ETP_QUIRK_QUICK_WAKEUP;
+
+       return quirks;
+}
+
 static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count,
                           u32 *signature_address, u16 *page_size)
 {
@@ -258,16 +291,18 @@ static int elan_check_ASUS_special_fw(struct elan_tp_data *data)
        return false;
 }
 
-static int __elan_initialize(struct elan_tp_data *data)
+static int __elan_initialize(struct elan_tp_data *data, bool skip_reset)
 {
        struct i2c_client *client = data->client;
        bool woken_up = false;
        int error;
 
-       error = data->ops->initialize(client);
-       if (error) {
-               dev_err(&client->dev, "device initialize failed: %d\n", error);
-               return error;
+       if (!skip_reset) {
+               error = data->ops->initialize(client);
+               if (error) {
+                       dev_err(&client->dev, "device initialize failed: %d\n", error);
+                       return error;
+               }
        }
 
        error = elan_query_product(data);
@@ -311,16 +346,17 @@ static int __elan_initialize(struct elan_tp_data *data)
        return 0;
 }
 
-static int elan_initialize(struct elan_tp_data *data)
+static int elan_initialize(struct elan_tp_data *data, bool skip_reset)
 {
        int repeat = ETP_RETRY_COUNT;
        int error;
 
        do {
-               error = __elan_initialize(data);
+               error = __elan_initialize(data, skip_reset);
                if (!error)
                        return 0;
 
+               skip_reset = false;
                msleep(30);
        } while (--repeat > 0);
 
@@ -357,6 +393,8 @@ static int elan_query_device_info(struct elan_tp_data *data)
        if (error)
                return error;
 
+       data->quirks = elan_i2c_lookup_quirks(data->ic_type, data->product_id);
+
        error = elan_get_fwinfo(data->ic_type, data->iap_version,
                                &data->fw_validpage_count,
                                &data->fw_signature_address,
@@ -546,7 +584,7 @@ static int elan_update_firmware(struct elan_tp_data *data,
                data->ops->iap_reset(client);
        } else {
                /* Reinitialize TP after fw is updated */
-               elan_initialize(data);
+               elan_initialize(data, false);
                elan_query_device_info(data);
        }
 
@@ -1247,7 +1285,7 @@ static int elan_probe(struct i2c_client *client,
        }
 
        /* Initialize the touchpad. */
-       error = elan_initialize(data);
+       error = elan_initialize(data, false);
        if (error)
                return error;
 
@@ -1384,7 +1422,7 @@ static int __maybe_unused elan_resume(struct device *dev)
                goto err;
        }
 
-       error = elan_initialize(data);
+       error = elan_initialize(data, data->quirks & ETP_QUIRK_QUICK_WAKEUP);
        if (error)
                dev_err(dev, "initialize when resuming failed: %d\n", error);