RE: [PATCH] Input: elan_i2c - Reduce the resume time for new dev ices

From: jingle
Date: Mon Mar 08 2021 - 03:57:13 EST


Hi Dmitry:

1. missing "i<"
+ u32 quirks = 0;
+ int i;
+
+ for (i = 0; ARRAY_SIZE(elan_i2c_quirks); i++) {

-> for (i = 0; i<ARRAY_SIZE(elan_i2c_quirks); i++) {

2. elan_resume () funtion are different with at Chromeos driver.
@@ -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);

-> https://chromium.googlesource.com/chromiumos/third_party/kernel/+/ref
-> s/heads/chromeos-5.4/drivers/input/mouse/elan_i2c_core.c#1434
-> error = elan_initialize(data); this code is in elan_reactivate()
function at Chromeos driver.
-> Will this change affect cherrypick from linux kernel to chromeos?

THANKS
JINGLE

-----Original Message-----
From: 'Dmitry Torokhov' [mailto:dmitry.torokhov@xxxxxxxxx]
Sent: Monday, March 08, 2021 11:18 AM
To: jingle
Cc: 'linux-kernel'; 'linux-input'; 'phoenix'; 'dave.wang'; 'josh.chen'
Subject: Re: [PATCH] Input: elan_i2c - Reduce the resume time for new dev
ices

Hi Jingle,

On Fri, Mar 05, 2021 at 09:50:35AM +0800, jingle wrote:
> HI Dmitry:
>
> 1. You mean to let all devices ignore skipping reset/sleep part of
> device initialization?
> 2. The test team found that some old firmware will have errors
> (invalid report etc...), so ELAN can only ensure that the new device
> can meet the newer parts.

I see. OK, fair enough.

I would prefer if we were more explicit about when we skip resetting the
device, what do you think about the version of your patch below?

Thanks.

--
Dmitry


Input: elan_i2c - reduce the resume time for new devices

From: Jingle Wu <jingle.wu@xxxxxxxxxx>

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@xxxxxxxxxx>
Link: https://lore.kernel.org/r/20210226073537.4926-1-jingle.wu@xxxxxxxxxx
Patchwork-Id: 12105967
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>
---
drivers/input/mouse/elan_i2c.h | 5 +++
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..51a65f6bf1e3 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; 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);