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

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.tw


Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent ad117c55
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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;

+48 −10
Original line number Diff line number Diff line
@@ -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,7 +93,37 @@ 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,17 +291,19 @@ 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;

	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);
	if (error)
@@ -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);