Commit ea16ef96 authored by Jingle Wu's avatar Jingle Wu Committed by Dmitry Torokhov

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: default avatarJingle Wu <jingle.wu@emc.com.tw>
Link: https://lore.kernel.org/r/20210226073537.4926-1-jingle.wu@emc.com.twSigned-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent ad117c55
...@@ -55,6 +55,11 @@ ...@@ -55,6 +55,11 @@
#define ETP_FW_PAGE_SIZE_512 512 #define ETP_FW_PAGE_SIZE_512 512
#define ETP_FW_SIGNATURE_SIZE 6 #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 i2c_client;
struct completion; struct completion;
......
...@@ -46,6 +46,9 @@ ...@@ -46,6 +46,9 @@
#define ETP_FINGER_WIDTH 15 #define ETP_FINGER_WIDTH 15
#define ETP_RETRY_COUNT 3 #define ETP_RETRY_COUNT 3
/* quirks to control the device */
#define ETP_QUIRK_QUICK_WAKEUP BIT(0)
/* The main device structure */ /* The main device structure */
struct elan_tp_data { struct elan_tp_data {
struct i2c_client *client; struct i2c_client *client;
...@@ -90,8 +93,38 @@ struct elan_tp_data { ...@@ -90,8 +93,38 @@ struct elan_tp_data {
bool baseline_ready; bool baseline_ready;
u8 clickpad; u8 clickpad;
bool middle_button; 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, static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count,
u32 *signature_address, u16 *page_size) u32 *signature_address, u16 *page_size)
{ {
...@@ -258,16 +291,18 @@ static int elan_check_ASUS_special_fw(struct elan_tp_data *data) ...@@ -258,16 +291,18 @@ static int elan_check_ASUS_special_fw(struct elan_tp_data *data)
return false; 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; struct i2c_client *client = data->client;
bool woken_up = false; bool woken_up = false;
int error; int error;
error = data->ops->initialize(client); if (!skip_reset) {
if (error) { error = data->ops->initialize(client);
dev_err(&client->dev, "device initialize failed: %d\n", error); if (error) {
return error; dev_err(&client->dev, "device initialize failed: %d\n", error);
return error;
}
} }
error = elan_query_product(data); error = elan_query_product(data);
...@@ -311,16 +346,17 @@ static int __elan_initialize(struct elan_tp_data *data) ...@@ -311,16 +346,17 @@ static int __elan_initialize(struct elan_tp_data *data)
return 0; 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 repeat = ETP_RETRY_COUNT;
int error; int error;
do { do {
error = __elan_initialize(data); error = __elan_initialize(data, skip_reset);
if (!error) if (!error)
return 0; return 0;
skip_reset = false;
msleep(30); msleep(30);
} while (--repeat > 0); } while (--repeat > 0);
...@@ -357,6 +393,8 @@ static int elan_query_device_info(struct elan_tp_data *data) ...@@ -357,6 +393,8 @@ static int elan_query_device_info(struct elan_tp_data *data)
if (error) if (error)
return 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, error = elan_get_fwinfo(data->ic_type, data->iap_version,
&data->fw_validpage_count, &data->fw_validpage_count,
&data->fw_signature_address, &data->fw_signature_address,
...@@ -546,7 +584,7 @@ static int elan_update_firmware(struct elan_tp_data *data, ...@@ -546,7 +584,7 @@ static int elan_update_firmware(struct elan_tp_data *data,
data->ops->iap_reset(client); data->ops->iap_reset(client);
} else { } else {
/* Reinitialize TP after fw is updated */ /* Reinitialize TP after fw is updated */
elan_initialize(data); elan_initialize(data, false);
elan_query_device_info(data); elan_query_device_info(data);
} }
...@@ -1247,7 +1285,7 @@ static int elan_probe(struct i2c_client *client, ...@@ -1247,7 +1285,7 @@ static int elan_probe(struct i2c_client *client,
} }
/* Initialize the touchpad. */ /* Initialize the touchpad. */
error = elan_initialize(data); error = elan_initialize(data, false);
if (error) if (error)
return error; return error;
...@@ -1384,7 +1422,7 @@ static int __maybe_unused elan_resume(struct device *dev) ...@@ -1384,7 +1422,7 @@ static int __maybe_unused elan_resume(struct device *dev)
goto err; goto err;
} }
error = elan_initialize(data); error = elan_initialize(data, data->quirks & ETP_QUIRK_QUICK_WAKEUP);
if (error) if (error)
dev_err(dev, "initialize when resuming failed: %d\n", error); dev_err(dev, "initialize when resuming failed: %d\n", error);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment