mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 15:14:18 +08:00
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>
This commit is contained in:
parent
ad117c558e
commit
ea16ef967e
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user