diff options
author | Jingle Wu <jingle.wu@emc.com.tw> | 2021-03-08 03:23:25 +0100 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2021-03-10 06:39:55 +0100 |
commit | ea16ef967ec88bd67466d564d461c3fdf7f85bd9 (patch) | |
tree | 45ae4cb81516d246a19e3fedcbaa97d220f7215d /drivers/input/mouse | |
parent | Input: exc3000 - add type sysfs attribute (diff) | |
download | linux-ea16ef967ec88bd67466d564d461c3fdf7f85bd9.tar.xz linux-ea16ef967ec88bd67466d564d461c3fdf7f85bd9.zip |
Input: elan_i2c - reduce the resume time for new devices
Newer controllers, such as Voxel, Delbin, Magple, Bobba and others, do not
need to be reset after issuing power-on command, and skipping reset saves
at least 100ms from resume time.
Note that if first attempt of re-initializing device fails we will not be
skipping reset on the subsequent ones.
Signed-off-by: Jingle Wu <jingle.wu@emc.com.tw>
Link: https://lore.kernel.org/r/20210226073537.4926-1-jingle.wu@emc.com.tw
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/mouse')
-rw-r--r-- | drivers/input/mouse/elan_i2c.h | 5 | ||||
-rw-r--r-- | drivers/input/mouse/elan_i2c_core.c | 58 |
2 files changed, 53 insertions, 10 deletions
diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h index e12da5b024b0..838b3b346316 100644 --- a/drivers/input/mouse/elan_i2c.h +++ b/drivers/input/mouse/elan_i2c.h @@ -55,6 +55,11 @@ #define ETP_FW_PAGE_SIZE_512 512 #define ETP_FW_SIGNATURE_SIZE 6 +#define ETP_PRODUCT_ID_DELBIN 0x00C2 +#define ETP_PRODUCT_ID_VOXEL 0x00BF +#define ETP_PRODUCT_ID_MAGPIE 0x0120 +#define ETP_PRODUCT_ID_BOBBA 0x0121 + struct i2c_client; struct completion; diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index bef73822315d..dad22c1ea6a0 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -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); |