1ac1dc6b2SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
266aee900SScott Liu /*
366aee900SScott Liu  * Elan Microelectronics touch panels with I2C interface
466aee900SScott Liu  *
566aee900SScott Liu  * Copyright (C) 2014 Elan Microelectronics Corporation.
666aee900SScott Liu  * Scott Liu <scott.liu@emc.com.tw>
766aee900SScott Liu  *
866aee900SScott Liu  * This code is partly based on hid-multitouch.c:
966aee900SScott Liu  *
1066aee900SScott Liu  *  Copyright (c) 2010-2012 Stephane Chatty <chatty@enac.fr>
1166aee900SScott Liu  *  Copyright (c) 2010-2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
1266aee900SScott Liu  *  Copyright (c) 2010-2012 Ecole Nationale de l'Aviation Civile, France
1366aee900SScott Liu  *
1466aee900SScott Liu  * This code is partly based on i2c-hid.c:
1566aee900SScott Liu  *
1666aee900SScott Liu  * Copyright (c) 2012 Benjamin Tissoires <benjamin.tissoires@gmail.com>
1766aee900SScott Liu  * Copyright (c) 2012 Ecole Nationale de l'Aviation Civile, France
1866aee900SScott Liu  * Copyright (c) 2012 Red Hat, Inc
1966aee900SScott Liu  */
2066aee900SScott Liu 
2166aee900SScott Liu 
22f27ad893SJohnny Chuang #include <linux/bits.h>
2366aee900SScott Liu #include <linux/module.h>
2466aee900SScott Liu #include <linux/input.h>
2566aee900SScott Liu #include <linux/interrupt.h>
264c83c071SDmitry Torokhov #include <linux/irq.h>
2766aee900SScott Liu #include <linux/platform_device.h>
2866aee900SScott Liu #include <linux/async.h>
2966aee900SScott Liu #include <linux/i2c.h>
3066aee900SScott Liu #include <linux/delay.h>
3166aee900SScott Liu #include <linux/uaccess.h>
3266aee900SScott Liu #include <linux/buffer_head.h>
3366aee900SScott Liu #include <linux/slab.h>
3466aee900SScott Liu #include <linux/firmware.h>
3566aee900SScott Liu #include <linux/input/mt.h>
3668334dbaSMichał Mirosław #include <linux/input/touchscreen.h>
3766aee900SScott Liu #include <linux/acpi.h>
3866aee900SScott Liu #include <linux/of.h>
39afe10358SDmitry Torokhov #include <linux/gpio/consumer.h>
40afe10358SDmitry Torokhov #include <linux/regulator/consumer.h>
4165299e8bSHans de Goede #include <linux/uuid.h>
4266aee900SScott Liu #include <asm/unaligned.h>
4366aee900SScott Liu 
4466aee900SScott Liu /* Device, Driver information */
4566aee900SScott Liu #define DEVICE_NAME	"elants_i2c"
4666aee900SScott Liu 
4766aee900SScott Liu /* Convert from rows or columns into resolution */
4866aee900SScott Liu #define ELAN_TS_RESOLUTION(n, m)   (((n) - 1) * (m))
4966aee900SScott Liu 
5066aee900SScott Liu /* FW header data */
5166aee900SScott Liu #define HEADER_SIZE		4
5266aee900SScott Liu #define FW_HDR_TYPE		0
5366aee900SScott Liu #define FW_HDR_COUNT		1
5466aee900SScott Liu #define FW_HDR_LENGTH		2
5566aee900SScott Liu 
5666aee900SScott Liu /* Buffer mode Queue Header information */
5766aee900SScott Liu #define QUEUE_HEADER_SINGLE	0x62
5866aee900SScott Liu #define QUEUE_HEADER_NORMAL	0X63
5966aee900SScott Liu #define QUEUE_HEADER_WAIT	0x64
609517b95bSMichał Mirosław #define QUEUE_HEADER_NORMAL2	0x66
6166aee900SScott Liu 
6266aee900SScott Liu /* Command header definition */
6366aee900SScott Liu #define CMD_HEADER_WRITE	0x54
6466aee900SScott Liu #define CMD_HEADER_READ		0x53
6566aee900SScott Liu #define CMD_HEADER_6B_READ	0x5B
66f0b57e19SJohnny.Chuang #define CMD_HEADER_ROM_READ	0x96
6766aee900SScott Liu #define CMD_HEADER_RESP		0x52
6866aee900SScott Liu #define CMD_HEADER_6B_RESP	0x9B
69f0b57e19SJohnny.Chuang #define CMD_HEADER_ROM_RESP	0x95
7066aee900SScott Liu #define CMD_HEADER_HELLO	0x55
7166aee900SScott Liu #define CMD_HEADER_REK		0x66
7266aee900SScott Liu 
7366aee900SScott Liu /* FW position data */
749517b95bSMichał Mirosław #define PACKET_SIZE_OLD		40
7566aee900SScott Liu #define PACKET_SIZE		55
7666aee900SScott Liu #define MAX_CONTACT_NUM		10
7766aee900SScott Liu #define FW_POS_HEADER		0
7866aee900SScott Liu #define FW_POS_STATE		1
7966aee900SScott Liu #define FW_POS_TOTAL		2
8066aee900SScott Liu #define FW_POS_XY		3
81f27ad893SJohnny Chuang #define FW_POS_TOOL_TYPE	33
8266aee900SScott Liu #define FW_POS_CHECKSUM		34
8366aee900SScott Liu #define FW_POS_WIDTH		35
8466aee900SScott Liu #define FW_POS_PRESSURE		45
8566aee900SScott Liu 
8666aee900SScott Liu #define HEADER_REPORT_10_FINGER	0x62
8766aee900SScott Liu 
88c18b443cSMichał Mirosław /* Header (4 bytes) plus 3 full 10-finger packets */
8966aee900SScott Liu #define MAX_PACKET_SIZE		169
9066aee900SScott Liu 
9166aee900SScott Liu #define BOOT_TIME_DELAY_MS	50
9266aee900SScott Liu 
9366aee900SScott Liu /* FW read command, 0x53 0x?? 0x0, 0x01 */
9466aee900SScott Liu #define E_ELAN_INFO_FW_VER	0x00
9566aee900SScott Liu #define E_ELAN_INFO_BC_VER	0x10
969517b95bSMichał Mirosław #define E_ELAN_INFO_X_RES	0x60
979517b95bSMichał Mirosław #define E_ELAN_INFO_Y_RES	0x63
9893f63406SJohnny Chuang #define E_ELAN_INFO_REK		0xD0
9966aee900SScott Liu #define E_ELAN_INFO_TEST_VER	0xE0
10066aee900SScott Liu #define E_ELAN_INFO_FW_ID	0xF0
10166aee900SScott Liu #define E_INFO_OSR		0xD6
10266aee900SScott Liu #define E_INFO_PHY_SCAN		0xD7
10366aee900SScott Liu #define E_INFO_PHY_DRIVER	0xD8
10466aee900SScott Liu 
105c18b443cSMichał Mirosław /* FW write command, 0x54 0x?? 0x0, 0x01 */
106c18b443cSMichał Mirosław #define E_POWER_STATE_SLEEP	0x50
107c18b443cSMichał Mirosław #define E_POWER_STATE_RESUME	0x58
108c18b443cSMichał Mirosław 
10966aee900SScott Liu #define MAX_RETRIES		3
11066aee900SScott Liu #define MAX_FW_UPDATE_RETRIES	30
11166aee900SScott Liu 
11266aee900SScott Liu #define ELAN_FW_PAGESIZE	132
11366aee900SScott Liu 
11466aee900SScott Liu /* calibration timeout definition */
11522c15e5eSJames Chen #define ELAN_CALI_TIMEOUT_MSEC	12000
11666aee900SScott Liu 
117afe10358SDmitry Torokhov #define ELAN_POWERON_DELAY_USEC	500
118afe10358SDmitry Torokhov #define ELAN_RESET_DELAY_MSEC	20
119afe10358SDmitry Torokhov 
120*4ebfee2bSJohnny Chuang /* FW boot code version */
121*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH3900x1_I2C        0x72
122*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH3900x2_I2C        0x82
123*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH3900x3_I2C        0x92
124*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH5312x1_I2C        0x6D
125*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH5312x2_I2C        0x6E
126*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C       0x77
127*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C       0x78
128*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH5312x1_I2C_USB    0x67
129*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH5312x2_I2C_USB    0x68
130*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C_USB   0x74
131*4ebfee2bSJohnny Chuang #define BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C_USB   0x75
132*4ebfee2bSJohnny Chuang 
1339517b95bSMichał Mirosław enum elants_chip_id {
1349517b95bSMichał Mirosław 	EKTH3500,
1359517b95bSMichał Mirosław 	EKTF3624,
1369517b95bSMichał Mirosław };
1379517b95bSMichał Mirosław 
13866aee900SScott Liu enum elants_state {
13966aee900SScott Liu 	ELAN_STATE_NORMAL,
14066aee900SScott Liu 	ELAN_WAIT_QUEUE_HEADER,
14166aee900SScott Liu 	ELAN_WAIT_RECALIBRATION,
14266aee900SScott Liu };
14366aee900SScott Liu 
14466aee900SScott Liu enum elants_iap_mode {
14566aee900SScott Liu 	ELAN_IAP_OPERATIONAL,
14666aee900SScott Liu 	ELAN_IAP_RECOVERY,
14766aee900SScott Liu };
14866aee900SScott Liu 
14966aee900SScott Liu /* struct elants_data - represents state of Elan touchscreen device */
15066aee900SScott Liu struct elants_data {
15166aee900SScott Liu 	struct i2c_client *client;
15266aee900SScott Liu 	struct input_dev *input;
15366aee900SScott Liu 
154afe10358SDmitry Torokhov 	struct regulator *vcc33;
155afe10358SDmitry Torokhov 	struct regulator *vccio;
156afe10358SDmitry Torokhov 	struct gpio_desc *reset_gpio;
157afe10358SDmitry Torokhov 
15866aee900SScott Liu 	u16 fw_version;
15966aee900SScott Liu 	u8 test_version;
16066aee900SScott Liu 	u8 solution_version;
16166aee900SScott Liu 	u8 bc_version;
16266aee900SScott Liu 	u8 iap_version;
16366aee900SScott Liu 	u16 hw_version;
1644238e52cSJohnny Chuang 	u8 major_res;
16566aee900SScott Liu 	unsigned int x_res;	/* resolution in units/mm */
16666aee900SScott Liu 	unsigned int y_res;
16766aee900SScott Liu 	unsigned int x_max;
16866aee900SScott Liu 	unsigned int y_max;
1699517b95bSMichał Mirosław 	unsigned int phy_x;
1709517b95bSMichał Mirosław 	unsigned int phy_y;
17168334dbaSMichał Mirosław 	struct touchscreen_properties prop;
17266aee900SScott Liu 
17366aee900SScott Liu 	enum elants_state state;
1749517b95bSMichał Mirosław 	enum elants_chip_id chip_id;
17566aee900SScott Liu 	enum elants_iap_mode iap_mode;
17666aee900SScott Liu 
17766aee900SScott Liu 	/* Guards against concurrent access to the device via sysfs */
17866aee900SScott Liu 	struct mutex sysfs_mutex;
17966aee900SScott Liu 
18066aee900SScott Liu 	u8 cmd_resp[HEADER_SIZE];
18166aee900SScott Liu 	struct completion cmd_done;
18266aee900SScott Liu 
18366aee900SScott Liu 	bool wake_irq_enabled;
184afe10358SDmitry Torokhov 	bool keep_power_in_suspend;
18500f73f97SStephen Boyd 
18600f73f97SStephen Boyd 	/* Must be last to be used for DMA operations */
18700f73f97SStephen Boyd 	u8 buf[MAX_PACKET_SIZE] ____cacheline_aligned;
18866aee900SScott Liu };
18966aee900SScott Liu 
19066aee900SScott Liu static int elants_i2c_send(struct i2c_client *client,
19166aee900SScott Liu 			   const void *data, size_t size)
19266aee900SScott Liu {
19366aee900SScott Liu 	int ret;
19466aee900SScott Liu 
19566aee900SScott Liu 	ret = i2c_master_send(client, data, size);
19666aee900SScott Liu 	if (ret == size)
19766aee900SScott Liu 		return 0;
19866aee900SScott Liu 
19966aee900SScott Liu 	if (ret >= 0)
20066aee900SScott Liu 		ret = -EIO;
20166aee900SScott Liu 
20266aee900SScott Liu 	dev_err(&client->dev, "%s failed (%*ph): %d\n",
20366aee900SScott Liu 		__func__, (int)size, data, ret);
20466aee900SScott Liu 
20566aee900SScott Liu 	return ret;
20666aee900SScott Liu }
20766aee900SScott Liu 
20866aee900SScott Liu static int elants_i2c_read(struct i2c_client *client, void *data, size_t size)
20966aee900SScott Liu {
21066aee900SScott Liu 	int ret;
21166aee900SScott Liu 
21266aee900SScott Liu 	ret = i2c_master_recv(client, data, size);
21366aee900SScott Liu 	if (ret == size)
21466aee900SScott Liu 		return 0;
21566aee900SScott Liu 
21666aee900SScott Liu 	if (ret >= 0)
21766aee900SScott Liu 		ret = -EIO;
21866aee900SScott Liu 
21966aee900SScott Liu 	dev_err(&client->dev, "%s failed: %d\n", __func__, ret);
22066aee900SScott Liu 
22166aee900SScott Liu 	return ret;
22266aee900SScott Liu }
22366aee900SScott Liu 
22466aee900SScott Liu static int elants_i2c_execute_command(struct i2c_client *client,
22566aee900SScott Liu 				      const u8 *cmd, size_t cmd_size,
226918e2844SMichał Mirosław 				      u8 *resp, size_t resp_size,
227918e2844SMichał Mirosław 				      int retries, const char *cmd_name)
22866aee900SScott Liu {
22966aee900SScott Liu 	struct i2c_msg msgs[2];
23066aee900SScott Liu 	int ret;
23166aee900SScott Liu 	u8 expected_response;
23266aee900SScott Liu 
23366aee900SScott Liu 	switch (cmd[0]) {
23466aee900SScott Liu 	case CMD_HEADER_READ:
23566aee900SScott Liu 		expected_response = CMD_HEADER_RESP;
23666aee900SScott Liu 		break;
23766aee900SScott Liu 
23866aee900SScott Liu 	case CMD_HEADER_6B_READ:
23966aee900SScott Liu 		expected_response = CMD_HEADER_6B_RESP;
24066aee900SScott Liu 		break;
24166aee900SScott Liu 
242f0b57e19SJohnny.Chuang 	case CMD_HEADER_ROM_READ:
243f0b57e19SJohnny.Chuang 		expected_response = CMD_HEADER_ROM_RESP;
244f0b57e19SJohnny.Chuang 		break;
245f0b57e19SJohnny.Chuang 
24666aee900SScott Liu 	default:
247918e2844SMichał Mirosław 		dev_err(&client->dev, "(%s): invalid command: %*ph\n",
248918e2844SMichał Mirosław 			cmd_name, (int)cmd_size, cmd);
24966aee900SScott Liu 		return -EINVAL;
25066aee900SScott Liu 	}
25166aee900SScott Liu 
252918e2844SMichał Mirosław 	for (;;) {
25366aee900SScott Liu 		msgs[0].addr = client->addr;
25466aee900SScott Liu 		msgs[0].flags = client->flags & I2C_M_TEN;
25566aee900SScott Liu 		msgs[0].len = cmd_size;
25666aee900SScott Liu 		msgs[0].buf = (u8 *)cmd;
25766aee900SScott Liu 
25866aee900SScott Liu 		msgs[1].addr = client->addr;
259918e2844SMichał Mirosław 		msgs[1].flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
26066aee900SScott Liu 		msgs[1].flags |= I2C_M_RD;
26166aee900SScott Liu 		msgs[1].len = resp_size;
26266aee900SScott Liu 		msgs[1].buf = resp;
26366aee900SScott Liu 
26466aee900SScott Liu 		ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
265918e2844SMichał Mirosław 		if (ret < 0) {
266918e2844SMichał Mirosław 			if (--retries > 0) {
267918e2844SMichał Mirosław 				dev_dbg(&client->dev,
268918e2844SMichał Mirosław 					"(%s) I2C transfer failed: %pe (retrying)\n",
269918e2844SMichał Mirosław 					cmd_name, ERR_PTR(ret));
270918e2844SMichał Mirosław 				continue;
271918e2844SMichał Mirosław 			}
27266aee900SScott Liu 
273918e2844SMichał Mirosław 			dev_err(&client->dev,
274918e2844SMichał Mirosław 				"(%s) I2C transfer failed: %pe\n",
275918e2844SMichał Mirosław 				cmd_name, ERR_PTR(ret));
276918e2844SMichał Mirosław 			return ret;
277918e2844SMichał Mirosław 		}
278918e2844SMichał Mirosław 
279918e2844SMichał Mirosław 		if (ret != ARRAY_SIZE(msgs) ||
280918e2844SMichał Mirosław 		    resp[FW_HDR_TYPE] != expected_response) {
281918e2844SMichał Mirosław 			if (--retries > 0) {
282918e2844SMichał Mirosław 				dev_dbg(&client->dev,
283918e2844SMichał Mirosław 					"(%s) unexpected response: %*ph (retrying)\n",
284918e2844SMichał Mirosław 					cmd_name, ret, resp);
285918e2844SMichał Mirosław 				continue;
286918e2844SMichał Mirosław 			}
287918e2844SMichał Mirosław 
288918e2844SMichał Mirosław 			dev_err(&client->dev,
289918e2844SMichał Mirosław 				"(%s) unexpected response: %*ph\n",
290918e2844SMichał Mirosław 				cmd_name, ret, resp);
29166aee900SScott Liu 			return -EIO;
292918e2844SMichał Mirosław 		}
29366aee900SScott Liu 
29466aee900SScott Liu 		return 0;
29566aee900SScott Liu 	}
296918e2844SMichał Mirosław }
29766aee900SScott Liu 
29866aee900SScott Liu static int elants_i2c_calibrate(struct elants_data *ts)
29966aee900SScott Liu {
30066aee900SScott Liu 	struct i2c_client *client = ts->client;
30166aee900SScott Liu 	int ret, error;
302c18b443cSMichał Mirosław 	static const u8 w_flashkey[] = { CMD_HEADER_WRITE, 0xC0, 0xE1, 0x5A };
303c18b443cSMichał Mirosław 	static const u8 rek[] = { CMD_HEADER_WRITE, 0x29, 0x00, 0x01 };
30466aee900SScott Liu 	static const u8 rek_resp[] = { CMD_HEADER_REK, 0x66, 0x66, 0x66 };
30566aee900SScott Liu 
30666aee900SScott Liu 	disable_irq(client->irq);
30766aee900SScott Liu 
30866aee900SScott Liu 	ts->state = ELAN_WAIT_RECALIBRATION;
30966aee900SScott Liu 	reinit_completion(&ts->cmd_done);
31066aee900SScott Liu 
31166aee900SScott Liu 	elants_i2c_send(client, w_flashkey, sizeof(w_flashkey));
31266aee900SScott Liu 	elants_i2c_send(client, rek, sizeof(rek));
31366aee900SScott Liu 
31466aee900SScott Liu 	enable_irq(client->irq);
31566aee900SScott Liu 
31666aee900SScott Liu 	ret = wait_for_completion_interruptible_timeout(&ts->cmd_done,
31766aee900SScott Liu 				msecs_to_jiffies(ELAN_CALI_TIMEOUT_MSEC));
31866aee900SScott Liu 
31966aee900SScott Liu 	ts->state = ELAN_STATE_NORMAL;
32066aee900SScott Liu 
32166aee900SScott Liu 	if (ret <= 0) {
32266aee900SScott Liu 		error = ret < 0 ? ret : -ETIMEDOUT;
32366aee900SScott Liu 		dev_err(&client->dev,
32466aee900SScott Liu 			"error while waiting for calibration to complete: %d\n",
32566aee900SScott Liu 			error);
32666aee900SScott Liu 		return error;
32766aee900SScott Liu 	}
32866aee900SScott Liu 
32966aee900SScott Liu 	if (memcmp(rek_resp, ts->cmd_resp, sizeof(rek_resp))) {
33066aee900SScott Liu 		dev_err(&client->dev,
33166aee900SScott Liu 			"unexpected calibration response: %*ph\n",
33266aee900SScott Liu 			(int)sizeof(ts->cmd_resp), ts->cmd_resp);
33366aee900SScott Liu 		return -EINVAL;
33466aee900SScott Liu 	}
33566aee900SScott Liu 
33666aee900SScott Liu 	return 0;
33766aee900SScott Liu }
33866aee900SScott Liu 
33966aee900SScott Liu static int elants_i2c_sw_reset(struct i2c_client *client)
34066aee900SScott Liu {
34166aee900SScott Liu 	const u8 soft_rst_cmd[] = { 0x77, 0x77, 0x77, 0x77 };
34266aee900SScott Liu 	int error;
34366aee900SScott Liu 
34466aee900SScott Liu 	error = elants_i2c_send(client, soft_rst_cmd,
34566aee900SScott Liu 				sizeof(soft_rst_cmd));
34666aee900SScott Liu 	if (error) {
34766aee900SScott Liu 		dev_err(&client->dev, "software reset failed: %d\n", error);
34866aee900SScott Liu 		return error;
34966aee900SScott Liu 	}
35066aee900SScott Liu 
35166aee900SScott Liu 	/*
35266aee900SScott Liu 	 * We should wait at least 10 msec (but no more than 40) before
35366aee900SScott Liu 	 * sending fastboot or IAP command to the device.
35466aee900SScott Liu 	 */
35566aee900SScott Liu 	msleep(30);
35666aee900SScott Liu 
35766aee900SScott Liu 	return 0;
35866aee900SScott Liu }
35966aee900SScott Liu 
36066aee900SScott Liu static u16 elants_i2c_parse_version(u8 *buf)
36166aee900SScott Liu {
36266aee900SScott Liu 	return get_unaligned_be32(buf) >> 4;
36366aee900SScott Liu }
36466aee900SScott Liu 
365bc1d57feSJohnny Chuang static int elants_i2c_query_hw_version(struct elants_data *ts)
36666aee900SScott Liu {
36766aee900SScott Liu 	struct i2c_client *client = ts->client;
368918e2844SMichał Mirosław 	int retry_cnt = MAX_RETRIES;
36966aee900SScott Liu 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_ID, 0x00, 0x01 };
37066aee900SScott Liu 	u8 resp[HEADER_SIZE];
371918e2844SMichał Mirosław 	int error;
37266aee900SScott Liu 
373918e2844SMichał Mirosław 	while (retry_cnt--) {
37466aee900SScott Liu 		error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
375918e2844SMichał Mirosław 						   resp, sizeof(resp), 1,
376918e2844SMichał Mirosław 						   "read fw id");
377918e2844SMichał Mirosław 		if (error)
378918e2844SMichał Mirosław 			return error;
379918e2844SMichał Mirosław 
38066aee900SScott Liu 		ts->hw_version = elants_i2c_parse_version(resp);
38166aee900SScott Liu 		if (ts->hw_version != 0xffff)
38266aee900SScott Liu 			return 0;
38366aee900SScott Liu 	}
38466aee900SScott Liu 
385bc1d57feSJohnny Chuang 	dev_err(&client->dev, "Invalid fw id: %#04x\n", ts->hw_version);
38666aee900SScott Liu 
38766aee900SScott Liu 	return -EINVAL;
38866aee900SScott Liu }
38966aee900SScott Liu 
39066aee900SScott Liu static int elants_i2c_query_fw_version(struct elants_data *ts)
39166aee900SScott Liu {
39266aee900SScott Liu 	struct i2c_client *client = ts->client;
393918e2844SMichał Mirosław 	int retry_cnt = MAX_RETRIES;
39466aee900SScott Liu 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_VER, 0x00, 0x01 };
39566aee900SScott Liu 	u8 resp[HEADER_SIZE];
396918e2844SMichał Mirosław 	int error;
39766aee900SScott Liu 
398918e2844SMichał Mirosław 	while (retry_cnt--) {
39966aee900SScott Liu 		error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
400918e2844SMichał Mirosław 						   resp, sizeof(resp), 1,
401918e2844SMichał Mirosław 						   "read fw version");
402918e2844SMichał Mirosław 		if (error)
403918e2844SMichał Mirosław 			return error;
404918e2844SMichał Mirosław 
40566aee900SScott Liu 		ts->fw_version = elants_i2c_parse_version(resp);
406918e2844SMichał Mirosław 		if (ts->fw_version != 0x0000 && ts->fw_version != 0xffff)
40766aee900SScott Liu 			return 0;
408918e2844SMichał Mirosław 
409918e2844SMichał Mirosław 		dev_dbg(&client->dev, "(read fw version) resp %*phC\n",
410918e2844SMichał Mirosław 			(int)sizeof(resp), resp);
41166aee900SScott Liu 	}
41266aee900SScott Liu 
413918e2844SMichał Mirosław 	dev_err(&client->dev, "Invalid fw ver: %#04x\n", ts->fw_version);
41466aee900SScott Liu 
41566aee900SScott Liu 	return -EINVAL;
41666aee900SScott Liu }
41766aee900SScott Liu 
41866aee900SScott Liu static int elants_i2c_query_test_version(struct elants_data *ts)
41966aee900SScott Liu {
42066aee900SScott Liu 	struct i2c_client *client = ts->client;
421918e2844SMichał Mirosław 	int error;
42266aee900SScott Liu 	u16 version;
42366aee900SScott Liu 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_TEST_VER, 0x00, 0x01 };
42466aee900SScott Liu 	u8 resp[HEADER_SIZE];
42566aee900SScott Liu 
42666aee900SScott Liu 	error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
427918e2844SMichał Mirosław 					   resp, sizeof(resp), MAX_RETRIES,
428918e2844SMichał Mirosław 					   "read test version");
429918e2844SMichał Mirosław 	if (error) {
430918e2844SMichał Mirosław 		dev_err(&client->dev, "Failed to read test version\n");
431918e2844SMichał Mirosław 		return error;
432918e2844SMichał Mirosław 	}
433918e2844SMichał Mirosław 
43466aee900SScott Liu 	version = elants_i2c_parse_version(resp);
43566aee900SScott Liu 	ts->test_version = version >> 8;
43666aee900SScott Liu 	ts->solution_version = version & 0xff;
43766aee900SScott Liu 
43866aee900SScott Liu 	return 0;
43966aee900SScott Liu }
44066aee900SScott Liu 
44166aee900SScott Liu static int elants_i2c_query_bc_version(struct elants_data *ts)
44266aee900SScott Liu {
44366aee900SScott Liu 	struct i2c_client *client = ts->client;
44466aee900SScott Liu 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_BC_VER, 0x00, 0x01 };
44566aee900SScott Liu 	u8 resp[HEADER_SIZE];
44666aee900SScott Liu 	u16 version;
44766aee900SScott Liu 	int error;
44866aee900SScott Liu 
44966aee900SScott Liu 	error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
450918e2844SMichał Mirosław 					   resp, sizeof(resp), 1,
451918e2844SMichał Mirosław 					   "read BC version");
452918e2844SMichał Mirosław 	if (error)
45366aee900SScott Liu 		return error;
45466aee900SScott Liu 
45566aee900SScott Liu 	version = elants_i2c_parse_version(resp);
45666aee900SScott Liu 	ts->bc_version = version >> 8;
45766aee900SScott Liu 	ts->iap_version = version & 0xff;
45866aee900SScott Liu 
45966aee900SScott Liu 	return 0;
46066aee900SScott Liu }
46166aee900SScott Liu 
4629517b95bSMichał Mirosław static int elants_i2c_query_ts_info_ektf(struct elants_data *ts)
4639517b95bSMichał Mirosław {
4649517b95bSMichał Mirosław 	struct i2c_client *client = ts->client;
4659517b95bSMichał Mirosław 	int error;
4669517b95bSMichał Mirosław 	u8 resp[4];
4679517b95bSMichał Mirosław 	u16 phy_x, phy_y;
4689517b95bSMichał Mirosław 	const u8 get_xres_cmd[] = {
4699517b95bSMichał Mirosław 		CMD_HEADER_READ, E_ELAN_INFO_X_RES, 0x00, 0x00
4709517b95bSMichał Mirosław 	};
4719517b95bSMichał Mirosław 	const u8 get_yres_cmd[] = {
4729517b95bSMichał Mirosław 		CMD_HEADER_READ, E_ELAN_INFO_Y_RES, 0x00, 0x00
4739517b95bSMichał Mirosław 	};
4749517b95bSMichał Mirosław 
4759517b95bSMichał Mirosław 	/* Get X/Y size in mm */
4769517b95bSMichał Mirosław 	error = elants_i2c_execute_command(client, get_xres_cmd,
4779517b95bSMichał Mirosław 					   sizeof(get_xres_cmd),
4789517b95bSMichał Mirosław 					   resp, sizeof(resp), 1,
4799517b95bSMichał Mirosław 					   "get X size");
4809517b95bSMichał Mirosław 	if (error)
4819517b95bSMichał Mirosław 		return error;
4829517b95bSMichał Mirosław 
4839517b95bSMichał Mirosław 	phy_x = resp[2] | ((resp[3] & 0xF0) << 4);
4849517b95bSMichał Mirosław 
4859517b95bSMichał Mirosław 	error = elants_i2c_execute_command(client, get_yres_cmd,
4869517b95bSMichał Mirosław 					   sizeof(get_yres_cmd),
4879517b95bSMichał Mirosław 					   resp, sizeof(resp), 1,
4889517b95bSMichał Mirosław 					   "get Y size");
4899517b95bSMichał Mirosław 	if (error)
4909517b95bSMichał Mirosław 		return error;
4919517b95bSMichał Mirosław 
4929517b95bSMichał Mirosław 	phy_y = resp[2] | ((resp[3] & 0xF0) << 4);
4939517b95bSMichał Mirosław 
4949517b95bSMichał Mirosław 	dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y);
4959517b95bSMichał Mirosław 
4969517b95bSMichał Mirosław 	ts->phy_x = phy_x;
4979517b95bSMichał Mirosław 	ts->phy_y = phy_y;
4989517b95bSMichał Mirosław 
4999517b95bSMichał Mirosław 	/* eKTF doesn't report max size, set it to default values */
5009517b95bSMichał Mirosław 	ts->x_max = 2240 - 1;
5019517b95bSMichał Mirosław 	ts->y_max = 1408 - 1;
5029517b95bSMichał Mirosław 
5039517b95bSMichał Mirosław 	return 0;
5049517b95bSMichał Mirosław }
5059517b95bSMichał Mirosław 
5069517b95bSMichał Mirosław static int elants_i2c_query_ts_info_ekth(struct elants_data *ts)
50766aee900SScott Liu {
50866aee900SScott Liu 	struct i2c_client *client = ts->client;
50966aee900SScott Liu 	int error;
51066aee900SScott Liu 	u8 resp[17];
51166aee900SScott Liu 	u16 phy_x, phy_y, rows, cols, osr;
51266aee900SScott Liu 	const u8 get_resolution_cmd[] = {
51366aee900SScott Liu 		CMD_HEADER_6B_READ, 0x00, 0x00, 0x00, 0x00, 0x00
51466aee900SScott Liu 	};
51566aee900SScott Liu 	const u8 get_osr_cmd[] = {
51666aee900SScott Liu 		CMD_HEADER_READ, E_INFO_OSR, 0x00, 0x01
51766aee900SScott Liu 	};
51866aee900SScott Liu 	const u8 get_physical_scan_cmd[] = {
51966aee900SScott Liu 		CMD_HEADER_READ, E_INFO_PHY_SCAN, 0x00, 0x01
52066aee900SScott Liu 	};
52166aee900SScott Liu 	const u8 get_physical_drive_cmd[] = {
52266aee900SScott Liu 		CMD_HEADER_READ, E_INFO_PHY_DRIVER, 0x00, 0x01
52366aee900SScott Liu 	};
52466aee900SScott Liu 
52566aee900SScott Liu 	/* Get trace number */
52666aee900SScott Liu 	error = elants_i2c_execute_command(client,
52766aee900SScott Liu 					   get_resolution_cmd,
52866aee900SScott Liu 					   sizeof(get_resolution_cmd),
529918e2844SMichał Mirosław 					   resp, sizeof(resp), 1,
530918e2844SMichał Mirosław 					   "get resolution");
531918e2844SMichał Mirosław 	if (error)
53266aee900SScott Liu 		return error;
53366aee900SScott Liu 
53466aee900SScott Liu 	rows = resp[2] + resp[6] + resp[10];
53566aee900SScott Liu 	cols = resp[3] + resp[7] + resp[11];
53666aee900SScott Liu 
5374238e52cSJohnny Chuang 	/* Get report resolution value of ABS_MT_TOUCH_MAJOR */
5384238e52cSJohnny Chuang 	ts->major_res = resp[16];
5394238e52cSJohnny Chuang 
54066aee900SScott Liu 	/* Process mm_to_pixel information */
54166aee900SScott Liu 	error = elants_i2c_execute_command(client,
54266aee900SScott Liu 					   get_osr_cmd, sizeof(get_osr_cmd),
543918e2844SMichał Mirosław 					   resp, sizeof(resp), 1, "get osr");
544918e2844SMichał Mirosław 	if (error)
54566aee900SScott Liu 		return error;
54666aee900SScott Liu 
54766aee900SScott Liu 	osr = resp[3];
54866aee900SScott Liu 
54966aee900SScott Liu 	error = elants_i2c_execute_command(client,
55066aee900SScott Liu 					   get_physical_scan_cmd,
55166aee900SScott Liu 					   sizeof(get_physical_scan_cmd),
552918e2844SMichał Mirosław 					   resp, sizeof(resp), 1,
553918e2844SMichał Mirosław 					   "get physical scan");
554918e2844SMichał Mirosław 	if (error)
55566aee900SScott Liu 		return error;
55666aee900SScott Liu 
55766aee900SScott Liu 	phy_x = get_unaligned_be16(&resp[2]);
55866aee900SScott Liu 
55966aee900SScott Liu 	error = elants_i2c_execute_command(client,
56066aee900SScott Liu 					   get_physical_drive_cmd,
56166aee900SScott Liu 					   sizeof(get_physical_drive_cmd),
562918e2844SMichał Mirosław 					   resp, sizeof(resp), 1,
563918e2844SMichał Mirosław 					   "get physical drive");
564918e2844SMichał Mirosław 	if (error)
56566aee900SScott Liu 		return error;
56666aee900SScott Liu 
56766aee900SScott Liu 	phy_y = get_unaligned_be16(&resp[2]);
56866aee900SScott Liu 
56966aee900SScott Liu 	dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y);
57066aee900SScott Liu 
57166aee900SScott Liu 	if (rows == 0 || cols == 0 || osr == 0) {
57266aee900SScott Liu 		dev_warn(&client->dev,
57366aee900SScott Liu 			 "invalid trace number data: %d, %d, %d\n",
57466aee900SScott Liu 			 rows, cols, osr);
57566aee900SScott Liu 	} else {
57666aee900SScott Liu 		/* translate trace number to TS resolution */
57766aee900SScott Liu 		ts->x_max = ELAN_TS_RESOLUTION(rows, osr);
57866aee900SScott Liu 		ts->x_res = DIV_ROUND_CLOSEST(ts->x_max, phy_x);
57966aee900SScott Liu 		ts->y_max = ELAN_TS_RESOLUTION(cols, osr);
58066aee900SScott Liu 		ts->y_res = DIV_ROUND_CLOSEST(ts->y_max, phy_y);
5819517b95bSMichał Mirosław 		ts->phy_x = phy_x;
5829517b95bSMichał Mirosław 		ts->phy_y = phy_y;
58366aee900SScott Liu 	}
58466aee900SScott Liu 
58566aee900SScott Liu 	return 0;
58666aee900SScott Liu }
58766aee900SScott Liu 
58866aee900SScott Liu static int elants_i2c_fastboot(struct i2c_client *client)
58966aee900SScott Liu {
59066aee900SScott Liu 	const u8 boot_cmd[] = { 0x4D, 0x61, 0x69, 0x6E };
59166aee900SScott Liu 	int error;
59266aee900SScott Liu 
59366aee900SScott Liu 	error = elants_i2c_send(client, boot_cmd, sizeof(boot_cmd));
59466aee900SScott Liu 	if (error) {
59566aee900SScott Liu 		dev_err(&client->dev, "boot failed: %d\n", error);
59666aee900SScott Liu 		return error;
59766aee900SScott Liu 	}
59866aee900SScott Liu 
59966aee900SScott Liu 	dev_dbg(&client->dev, "boot success -- 0x%x\n", client->addr);
60066aee900SScott Liu 	return 0;
60166aee900SScott Liu }
60266aee900SScott Liu 
60366aee900SScott Liu static int elants_i2c_initialize(struct elants_data *ts)
60466aee900SScott Liu {
60566aee900SScott Liu 	struct i2c_client *client = ts->client;
606bc1d57feSJohnny Chuang 	int error, error2, retry_cnt;
60766aee900SScott Liu 	const u8 hello_packet[] = { 0x55, 0x55, 0x55, 0x55 };
60866aee900SScott Liu 	const u8 recov_packet[] = { 0x55, 0x55, 0x80, 0x80 };
60966aee900SScott Liu 	u8 buf[HEADER_SIZE];
61066aee900SScott Liu 
61166aee900SScott Liu 	for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
61266aee900SScott Liu 		error = elants_i2c_sw_reset(client);
61366aee900SScott Liu 		if (error) {
61466aee900SScott Liu 			/* Continue initializing if it's the last try */
61566aee900SScott Liu 			if (retry_cnt < MAX_RETRIES - 1)
61666aee900SScott Liu 				continue;
61766aee900SScott Liu 		}
61866aee900SScott Liu 
61966aee900SScott Liu 		error = elants_i2c_fastboot(client);
62066aee900SScott Liu 		if (error) {
62166aee900SScott Liu 			/* Continue initializing if it's the last try */
62266aee900SScott Liu 			if (retry_cnt < MAX_RETRIES - 1)
62366aee900SScott Liu 				continue;
62466aee900SScott Liu 		}
62566aee900SScott Liu 
62666aee900SScott Liu 		/* Wait for Hello packet */
62766aee900SScott Liu 		msleep(BOOT_TIME_DELAY_MS);
62866aee900SScott Liu 
62966aee900SScott Liu 		error = elants_i2c_read(client, buf, sizeof(buf));
63066aee900SScott Liu 		if (error) {
63166aee900SScott Liu 			dev_err(&client->dev,
63266aee900SScott Liu 				"failed to read 'hello' packet: %d\n", error);
63366aee900SScott Liu 		} else if (!memcmp(buf, hello_packet, sizeof(hello_packet))) {
63466aee900SScott Liu 			ts->iap_mode = ELAN_IAP_OPERATIONAL;
63566aee900SScott Liu 			break;
63666aee900SScott Liu 		} else if (!memcmp(buf, recov_packet, sizeof(recov_packet))) {
63766aee900SScott Liu 			/*
63866aee900SScott Liu 			 * Setting error code will mark device
63966aee900SScott Liu 			 * in recovery mode below.
64066aee900SScott Liu 			 */
64166aee900SScott Liu 			error = -EIO;
64266aee900SScott Liu 			break;
64366aee900SScott Liu 		} else {
64466aee900SScott Liu 			error = -EINVAL;
64566aee900SScott Liu 			dev_err(&client->dev,
64666aee900SScott Liu 				"invalid 'hello' packet: %*ph\n",
64766aee900SScott Liu 				(int)sizeof(buf), buf);
64866aee900SScott Liu 		}
64966aee900SScott Liu 	}
65066aee900SScott Liu 
651bc1d57feSJohnny Chuang 	/* hw version is available even if device in recovery state */
652bc1d57feSJohnny Chuang 	error2 = elants_i2c_query_hw_version(ts);
653f0b57e19SJohnny.Chuang 	if (!error2)
654f0b57e19SJohnny.Chuang 		error2 = elants_i2c_query_bc_version(ts);
65566aee900SScott Liu 	if (!error)
656bc1d57feSJohnny Chuang 		error = error2;
657bc1d57feSJohnny Chuang 
65866aee900SScott Liu 	if (!error)
65966aee900SScott Liu 		error = elants_i2c_query_fw_version(ts);
660bc1d57feSJohnny Chuang 	if (!error)
661bc1d57feSJohnny Chuang 		error = elants_i2c_query_test_version(ts);
6629517b95bSMichał Mirosław 
6639517b95bSMichał Mirosław 	switch (ts->chip_id) {
6649517b95bSMichał Mirosław 	case EKTH3500:
665bc1d57feSJohnny Chuang 		if (!error)
6669517b95bSMichał Mirosław 			error = elants_i2c_query_ts_info_ekth(ts);
6679517b95bSMichał Mirosław 		break;
6689517b95bSMichał Mirosław 	case EKTF3624:
6699517b95bSMichał Mirosław 		if (!error)
6709517b95bSMichał Mirosław 			error = elants_i2c_query_ts_info_ektf(ts);
6719517b95bSMichał Mirosław 		break;
6729517b95bSMichał Mirosław 	default:
673ede6747cSJosh Poimboeuf 		BUG();
6749517b95bSMichał Mirosław 	}
67566aee900SScott Liu 
676bc1d57feSJohnny Chuang 	if (error)
67766aee900SScott Liu 		ts->iap_mode = ELAN_IAP_RECOVERY;
67866aee900SScott Liu 
67966aee900SScott Liu 	return 0;
68066aee900SScott Liu }
68166aee900SScott Liu 
68266aee900SScott Liu /*
68366aee900SScott Liu  * Firmware update interface.
68466aee900SScott Liu  */
68566aee900SScott Liu 
68666aee900SScott Liu static int elants_i2c_fw_write_page(struct i2c_client *client,
68766aee900SScott Liu 				    const void *page)
68866aee900SScott Liu {
68966aee900SScott Liu 	const u8 ack_ok[] = { 0xaa, 0xaa };
69066aee900SScott Liu 	u8 buf[2];
69166aee900SScott Liu 	int retry;
69266aee900SScott Liu 	int error;
69366aee900SScott Liu 
69466aee900SScott Liu 	for (retry = 0; retry < MAX_FW_UPDATE_RETRIES; retry++) {
69566aee900SScott Liu 		error = elants_i2c_send(client, page, ELAN_FW_PAGESIZE);
69666aee900SScott Liu 		if (error) {
69766aee900SScott Liu 			dev_err(&client->dev,
69866aee900SScott Liu 				"IAP Write Page failed: %d\n", error);
69966aee900SScott Liu 			continue;
70066aee900SScott Liu 		}
70166aee900SScott Liu 
70266aee900SScott Liu 		error = elants_i2c_read(client, buf, 2);
70366aee900SScott Liu 		if (error) {
70466aee900SScott Liu 			dev_err(&client->dev,
70566aee900SScott Liu 				"IAP Ack read failed: %d\n", error);
70666aee900SScott Liu 			return error;
70766aee900SScott Liu 		}
70866aee900SScott Liu 
70966aee900SScott Liu 		if (!memcmp(buf, ack_ok, sizeof(ack_ok)))
71066aee900SScott Liu 			return 0;
71166aee900SScott Liu 
71266aee900SScott Liu 		error = -EIO;
71366aee900SScott Liu 		dev_err(&client->dev,
71466aee900SScott Liu 			"IAP Get Ack Error [%02x:%02x]\n",
71566aee900SScott Liu 			buf[0], buf[1]);
71666aee900SScott Liu 	}
71766aee900SScott Liu 
71866aee900SScott Liu 	return error;
71966aee900SScott Liu }
72066aee900SScott Liu 
721f0b57e19SJohnny.Chuang static int elants_i2c_validate_remark_id(struct elants_data *ts,
722f0b57e19SJohnny.Chuang 					 const struct firmware *fw)
723f0b57e19SJohnny.Chuang {
724f0b57e19SJohnny.Chuang 	struct i2c_client *client = ts->client;
725f0b57e19SJohnny.Chuang 	int error;
726f0b57e19SJohnny.Chuang 	const u8 cmd[] = { CMD_HEADER_ROM_READ, 0x80, 0x1F, 0x00, 0x00, 0x21 };
727f0b57e19SJohnny.Chuang 	u8 resp[6] = { 0 };
728f0b57e19SJohnny.Chuang 	u16 ts_remark_id = 0;
729f0b57e19SJohnny.Chuang 	u16 fw_remark_id = 0;
730f0b57e19SJohnny.Chuang 
731f0b57e19SJohnny.Chuang 	/* Compare TS Remark ID and FW Remark ID */
732f0b57e19SJohnny.Chuang 	error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
733918e2844SMichał Mirosław 					   resp, sizeof(resp),
734918e2844SMichał Mirosław 					   1, "read Remark ID");
735918e2844SMichał Mirosław 	if (error)
736f0b57e19SJohnny.Chuang 		return error;
737f0b57e19SJohnny.Chuang 
738f0b57e19SJohnny.Chuang 	ts_remark_id = get_unaligned_be16(&resp[3]);
739f0b57e19SJohnny.Chuang 
740f0b57e19SJohnny.Chuang 	fw_remark_id = get_unaligned_le16(&fw->data[fw->size - 4]);
741f0b57e19SJohnny.Chuang 
742f0b57e19SJohnny.Chuang 	if (fw_remark_id != ts_remark_id) {
743f0b57e19SJohnny.Chuang 		dev_err(&client->dev,
744f0b57e19SJohnny.Chuang 			"Remark ID Mismatched: ts_remark_id=0x%04x, fw_remark_id=0x%04x.\n",
745f0b57e19SJohnny.Chuang 			ts_remark_id, fw_remark_id);
746f0b57e19SJohnny.Chuang 		return -EINVAL;
747f0b57e19SJohnny.Chuang 	}
748f0b57e19SJohnny.Chuang 
749f0b57e19SJohnny.Chuang 	return 0;
750f0b57e19SJohnny.Chuang }
751f0b57e19SJohnny.Chuang 
752*4ebfee2bSJohnny Chuang static bool elants_i2c_should_check_remark_id(struct elants_data *ts)
753*4ebfee2bSJohnny Chuang {
754*4ebfee2bSJohnny Chuang 	struct i2c_client *client = ts->client;
755*4ebfee2bSJohnny Chuang 	const u8 bootcode_version = ts->iap_version;
756*4ebfee2bSJohnny Chuang 	bool check;
757*4ebfee2bSJohnny Chuang 
758*4ebfee2bSJohnny Chuang 	/* I2C eKTH3900 and eKTH5312 are NOT support Remark ID */
759*4ebfee2bSJohnny Chuang 	if ((bootcode_version == BC_VER_H_BYTE_FOR_EKTH3900x1_I2C) ||
760*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH3900x2_I2C) ||
761*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH3900x3_I2C) ||
762*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x1_I2C) ||
763*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x2_I2C) ||
764*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C) ||
765*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C) ||
766*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x1_I2C_USB) ||
767*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312x2_I2C_USB) ||
768*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx1_I2C_USB) ||
769*4ebfee2bSJohnny Chuang 	    (bootcode_version == BC_VER_H_BYTE_FOR_EKTH5312cx2_I2C_USB)) {
770*4ebfee2bSJohnny Chuang 		dev_dbg(&client->dev,
771*4ebfee2bSJohnny Chuang 			"eKTH3900/eKTH5312(0x%02x) are not support remark id\n",
772*4ebfee2bSJohnny Chuang 			bootcode_version);
773*4ebfee2bSJohnny Chuang 		check = false;
774*4ebfee2bSJohnny Chuang 	} else if (bootcode_version >= 0x60) {
775*4ebfee2bSJohnny Chuang 		check = true;
776*4ebfee2bSJohnny Chuang 	} else {
777*4ebfee2bSJohnny Chuang 		check = false;
778*4ebfee2bSJohnny Chuang 	}
779*4ebfee2bSJohnny Chuang 
780*4ebfee2bSJohnny Chuang 	return check;
781*4ebfee2bSJohnny Chuang }
782*4ebfee2bSJohnny Chuang 
78366aee900SScott Liu static int elants_i2c_do_update_firmware(struct i2c_client *client,
78466aee900SScott Liu 					 const struct firmware *fw,
78566aee900SScott Liu 					 bool force)
78666aee900SScott Liu {
787f0b57e19SJohnny.Chuang 	struct elants_data *ts = i2c_get_clientdata(client);
78866aee900SScott Liu 	const u8 enter_iap[] = { 0x45, 0x49, 0x41, 0x50 };
78966aee900SScott Liu 	const u8 enter_iap2[] = { 0x54, 0x00, 0x12, 0x34 };
79066aee900SScott Liu 	const u8 iap_ack[] = { 0x55, 0xaa, 0x33, 0xcc };
7916fd38502SJames Chen 	const u8 close_idle[] = { 0x54, 0x2c, 0x01, 0x01 };
79266aee900SScott Liu 	u8 buf[HEADER_SIZE];
79366aee900SScott Liu 	u16 send_id;
79466aee900SScott Liu 	int page, n_fw_pages;
79566aee900SScott Liu 	int error;
796*4ebfee2bSJohnny Chuang 	bool check_remark_id = elants_i2c_should_check_remark_id(ts);
79766aee900SScott Liu 
79866aee900SScott Liu 	/* Recovery mode detection! */
79966aee900SScott Liu 	if (force) {
80066aee900SScott Liu 		dev_dbg(&client->dev, "Recovery mode procedure\n");
801f0b57e19SJohnny.Chuang 
802f0b57e19SJohnny.Chuang 		if (check_remark_id) {
803f0b57e19SJohnny.Chuang 			error = elants_i2c_validate_remark_id(ts, fw);
804f0b57e19SJohnny.Chuang 			if (error)
805f0b57e19SJohnny.Chuang 				return error;
806f0b57e19SJohnny.Chuang 		}
807f0b57e19SJohnny.Chuang 
80866aee900SScott Liu 		error = elants_i2c_send(client, enter_iap2, sizeof(enter_iap2));
809f0b57e19SJohnny.Chuang 		if (error) {
810f0b57e19SJohnny.Chuang 			dev_err(&client->dev, "failed to enter IAP mode: %d\n",
811f0b57e19SJohnny.Chuang 				error);
812f0b57e19SJohnny.Chuang 			return error;
813f0b57e19SJohnny.Chuang 		}
81466aee900SScott Liu 	} else {
81566aee900SScott Liu 		/* Start IAP Procedure */
81666aee900SScott Liu 		dev_dbg(&client->dev, "Normal IAP procedure\n");
817f0b57e19SJohnny.Chuang 
8186fd38502SJames Chen 		/* Close idle mode */
8196fd38502SJames Chen 		error = elants_i2c_send(client, close_idle, sizeof(close_idle));
8206fd38502SJames Chen 		if (error)
8216fd38502SJames Chen 			dev_err(&client->dev, "Failed close idle: %d\n", error);
8226fd38502SJames Chen 		msleep(60);
823f0b57e19SJohnny.Chuang 
82466aee900SScott Liu 		elants_i2c_sw_reset(client);
8256fd38502SJames Chen 		msleep(20);
826f0b57e19SJohnny.Chuang 
827f0b57e19SJohnny.Chuang 		if (check_remark_id) {
828f0b57e19SJohnny.Chuang 			error = elants_i2c_validate_remark_id(ts, fw);
829f0b57e19SJohnny.Chuang 			if (error)
830f0b57e19SJohnny.Chuang 				return error;
83166aee900SScott Liu 		}
83266aee900SScott Liu 
833f0b57e19SJohnny.Chuang 		error = elants_i2c_send(client, enter_iap, sizeof(enter_iap));
83466aee900SScott Liu 		if (error) {
835f0b57e19SJohnny.Chuang 			dev_err(&client->dev, "failed to enter IAP mode: %d\n",
836f0b57e19SJohnny.Chuang 				error);
83766aee900SScott Liu 			return error;
83866aee900SScott Liu 		}
839f0b57e19SJohnny.Chuang 	}
84066aee900SScott Liu 
84166aee900SScott Liu 	msleep(20);
84266aee900SScott Liu 
84366aee900SScott Liu 	/* check IAP state */
84466aee900SScott Liu 	error = elants_i2c_read(client, buf, 4);
84566aee900SScott Liu 	if (error) {
84666aee900SScott Liu 		dev_err(&client->dev,
84766aee900SScott Liu 			"failed to read IAP acknowledgement: %d\n",
84866aee900SScott Liu 			error);
84966aee900SScott Liu 		return error;
85066aee900SScott Liu 	}
85166aee900SScott Liu 
85266aee900SScott Liu 	if (memcmp(buf, iap_ack, sizeof(iap_ack))) {
85366aee900SScott Liu 		dev_err(&client->dev,
85466aee900SScott Liu 			"failed to enter IAP: %*ph (expected %*ph)\n",
85566aee900SScott Liu 			(int)sizeof(buf), buf, (int)sizeof(iap_ack), iap_ack);
85666aee900SScott Liu 		return -EIO;
85766aee900SScott Liu 	}
85866aee900SScott Liu 
85966aee900SScott Liu 	dev_info(&client->dev, "successfully entered IAP mode");
86066aee900SScott Liu 
86166aee900SScott Liu 	send_id = client->addr;
86266aee900SScott Liu 	error = elants_i2c_send(client, &send_id, 1);
86366aee900SScott Liu 	if (error) {
86466aee900SScott Liu 		dev_err(&client->dev, "sending dummy byte failed: %d\n",
86566aee900SScott Liu 			error);
86666aee900SScott Liu 		return error;
86766aee900SScott Liu 	}
86866aee900SScott Liu 
86966aee900SScott Liu 	/* Clear the last page of Master */
87066aee900SScott Liu 	error = elants_i2c_send(client, fw->data, ELAN_FW_PAGESIZE);
87166aee900SScott Liu 	if (error) {
87266aee900SScott Liu 		dev_err(&client->dev, "clearing of the last page failed: %d\n",
87366aee900SScott Liu 			error);
87466aee900SScott Liu 		return error;
87566aee900SScott Liu 	}
87666aee900SScott Liu 
87766aee900SScott Liu 	error = elants_i2c_read(client, buf, 2);
87866aee900SScott Liu 	if (error) {
87966aee900SScott Liu 		dev_err(&client->dev,
88066aee900SScott Liu 			"failed to read ACK for clearing the last page: %d\n",
88166aee900SScott Liu 			error);
88266aee900SScott Liu 		return error;
88366aee900SScott Liu 	}
88466aee900SScott Liu 
88566aee900SScott Liu 	n_fw_pages = fw->size / ELAN_FW_PAGESIZE;
88666aee900SScott Liu 	dev_dbg(&client->dev, "IAP Pages = %d\n", n_fw_pages);
88766aee900SScott Liu 
88866aee900SScott Liu 	for (page = 0; page < n_fw_pages; page++) {
88966aee900SScott Liu 		error = elants_i2c_fw_write_page(client,
89066aee900SScott Liu 					fw->data + page * ELAN_FW_PAGESIZE);
89166aee900SScott Liu 		if (error) {
89266aee900SScott Liu 			dev_err(&client->dev,
89366aee900SScott Liu 				"failed to write FW page %d: %d\n",
89466aee900SScott Liu 				page, error);
89566aee900SScott Liu 			return error;
89666aee900SScott Liu 		}
89766aee900SScott Liu 	}
89866aee900SScott Liu 
89966aee900SScott Liu 	/* Old iap needs to wait 200ms for WDT and rest is for hello packets */
90066aee900SScott Liu 	msleep(300);
90166aee900SScott Liu 
90266aee900SScott Liu 	dev_info(&client->dev, "firmware update completed\n");
90366aee900SScott Liu 	return 0;
90466aee900SScott Liu }
90566aee900SScott Liu 
90666aee900SScott Liu static int elants_i2c_fw_update(struct elants_data *ts)
90766aee900SScott Liu {
90866aee900SScott Liu 	struct i2c_client *client = ts->client;
90966aee900SScott Liu 	const struct firmware *fw;
91037dee1acSCharlie Mooney 	char *fw_name;
91166aee900SScott Liu 	int error;
91266aee900SScott Liu 
9138c0776a8SDmitry Torokhov 	fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version);
91437dee1acSCharlie Mooney 	if (!fw_name)
91537dee1acSCharlie Mooney 		return -ENOMEM;
91637dee1acSCharlie Mooney 
91737dee1acSCharlie Mooney 	dev_info(&client->dev, "requesting fw name = %s\n", fw_name);
91837dee1acSCharlie Mooney 	error = request_firmware(&fw, fw_name, &client->dev);
91937dee1acSCharlie Mooney 	kfree(fw_name);
92066aee900SScott Liu 	if (error) {
92137dee1acSCharlie Mooney 		dev_err(&client->dev, "failed to request firmware: %d\n",
92237dee1acSCharlie Mooney 			error);
92366aee900SScott Liu 		return error;
92466aee900SScott Liu 	}
92566aee900SScott Liu 
92666aee900SScott Liu 	if (fw->size % ELAN_FW_PAGESIZE) {
92766aee900SScott Liu 		dev_err(&client->dev, "invalid firmware length: %zu\n",
92866aee900SScott Liu 			fw->size);
92966aee900SScott Liu 		error = -EINVAL;
93066aee900SScott Liu 		goto out;
93166aee900SScott Liu 	}
93266aee900SScott Liu 
93366aee900SScott Liu 	disable_irq(client->irq);
93466aee900SScott Liu 
93566aee900SScott Liu 	error = elants_i2c_do_update_firmware(client, fw,
93666aee900SScott Liu 					ts->iap_mode == ELAN_IAP_RECOVERY);
93766aee900SScott Liu 	if (error) {
93866aee900SScott Liu 		dev_err(&client->dev, "firmware update failed: %d\n", error);
93966aee900SScott Liu 		ts->iap_mode = ELAN_IAP_RECOVERY;
94066aee900SScott Liu 		goto out_enable_irq;
94166aee900SScott Liu 	}
94266aee900SScott Liu 
94366aee900SScott Liu 	error = elants_i2c_initialize(ts);
94466aee900SScott Liu 	if (error) {
94566aee900SScott Liu 		dev_err(&client->dev,
94666aee900SScott Liu 			"failed to initialize device after firmware update: %d\n",
94766aee900SScott Liu 			error);
94866aee900SScott Liu 		ts->iap_mode = ELAN_IAP_RECOVERY;
94966aee900SScott Liu 		goto out_enable_irq;
95066aee900SScott Liu 	}
95166aee900SScott Liu 
95266aee900SScott Liu 	ts->iap_mode = ELAN_IAP_OPERATIONAL;
95366aee900SScott Liu 
95466aee900SScott Liu out_enable_irq:
95566aee900SScott Liu 	ts->state = ELAN_STATE_NORMAL;
95666aee900SScott Liu 	enable_irq(client->irq);
95766aee900SScott Liu 	msleep(100);
95866aee900SScott Liu 
95966aee900SScott Liu 	if (!error)
96066aee900SScott Liu 		elants_i2c_calibrate(ts);
96166aee900SScott Liu out:
96266aee900SScott Liu 	release_firmware(fw);
96366aee900SScott Liu 	return error;
96466aee900SScott Liu }
96566aee900SScott Liu 
96666aee900SScott Liu /*
96766aee900SScott Liu  * Event reporting.
96866aee900SScott Liu  */
96966aee900SScott Liu 
9709517b95bSMichał Mirosław static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf,
9719517b95bSMichał Mirosław 				size_t packet_size)
97266aee900SScott Liu {
97366aee900SScott Liu 	struct input_dev *input = ts->input;
97466aee900SScott Liu 	unsigned int n_fingers;
975f27ad893SJohnny Chuang 	unsigned int tool_type;
97666aee900SScott Liu 	u16 finger_state;
97766aee900SScott Liu 	int i;
97866aee900SScott Liu 
97966aee900SScott Liu 	n_fingers = buf[FW_POS_STATE + 1] & 0x0f;
98066aee900SScott Liu 	finger_state = ((buf[FW_POS_STATE + 1] & 0x30) << 4) |
98166aee900SScott Liu 			buf[FW_POS_STATE];
98266aee900SScott Liu 
98366aee900SScott Liu 	dev_dbg(&ts->client->dev,
98466aee900SScott Liu 		"n_fingers: %u, state: %04x\n",  n_fingers, finger_state);
98566aee900SScott Liu 
986f27ad893SJohnny Chuang 	/* Note: all fingers have the same tool type */
987f27ad893SJohnny Chuang 	tool_type = buf[FW_POS_TOOL_TYPE] & BIT(0) ?
988f27ad893SJohnny Chuang 			MT_TOOL_FINGER : MT_TOOL_PALM;
989f27ad893SJohnny Chuang 
99066aee900SScott Liu 	for (i = 0; i < MAX_CONTACT_NUM && n_fingers; i++) {
99166aee900SScott Liu 		if (finger_state & 1) {
99266aee900SScott Liu 			unsigned int x, y, p, w;
99366aee900SScott Liu 			u8 *pos;
99466aee900SScott Liu 
99566aee900SScott Liu 			pos = &buf[FW_POS_XY + i * 3];
99666aee900SScott Liu 			x = (((u16)pos[0] & 0xf0) << 4) | pos[1];
99766aee900SScott Liu 			y = (((u16)pos[0] & 0x0f) << 8) | pos[2];
9989517b95bSMichał Mirosław 
9999517b95bSMichał Mirosław 			/*
10009517b95bSMichał Mirosław 			 * eKTF3624 may have use "old" touch-report format,
10019517b95bSMichał Mirosław 			 * depending on a device and TS firmware version.
10029517b95bSMichał Mirosław 			 * For example, ASUS Transformer devices use the "old"
10039517b95bSMichał Mirosław 			 * format, while ASUS Nexus 7 uses the "new" formant.
10049517b95bSMichał Mirosław 			 */
10059517b95bSMichał Mirosław 			if (packet_size == PACKET_SIZE_OLD &&
10069517b95bSMichał Mirosław 			    ts->chip_id == EKTF3624) {
10079517b95bSMichał Mirosław 				w = buf[FW_POS_WIDTH + i / 2];
10089517b95bSMichał Mirosław 				w >>= 4 * (~i & 1);
10099517b95bSMichał Mirosław 				w |= w << 4;
10109517b95bSMichał Mirosław 				w |= !w;
10119517b95bSMichał Mirosław 				p = w;
10129517b95bSMichał Mirosław 			} else {
101366aee900SScott Liu 				p = buf[FW_POS_PRESSURE + i];
101466aee900SScott Liu 				w = buf[FW_POS_WIDTH + i];
10159517b95bSMichał Mirosław 			}
101666aee900SScott Liu 
101766aee900SScott Liu 			dev_dbg(&ts->client->dev, "i=%d x=%d y=%d p=%d w=%d\n",
101866aee900SScott Liu 				i, x, y, p, w);
101966aee900SScott Liu 
102066aee900SScott Liu 			input_mt_slot(input, i);
1021f27ad893SJohnny Chuang 			input_mt_report_slot_state(input, tool_type, true);
102268334dbaSMichał Mirosław 			touchscreen_report_pos(input, &ts->prop, x, y, true);
102366aee900SScott Liu 			input_event(input, EV_ABS, ABS_MT_PRESSURE, p);
102466aee900SScott Liu 			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, w);
102566aee900SScott Liu 
102666aee900SScott Liu 			n_fingers--;
102766aee900SScott Liu 		}
102866aee900SScott Liu 
102966aee900SScott Liu 		finger_state >>= 1;
103066aee900SScott Liu 	}
103166aee900SScott Liu 
103266aee900SScott Liu 	input_mt_sync_frame(input);
103366aee900SScott Liu 	input_sync(input);
103466aee900SScott Liu }
103566aee900SScott Liu 
103666aee900SScott Liu static u8 elants_i2c_calculate_checksum(u8 *buf)
103766aee900SScott Liu {
103866aee900SScott Liu 	u8 checksum = 0;
103966aee900SScott Liu 	u8 i;
104066aee900SScott Liu 
104166aee900SScott Liu 	for (i = 0; i < FW_POS_CHECKSUM; i++)
104266aee900SScott Liu 		checksum += buf[i];
104366aee900SScott Liu 
104466aee900SScott Liu 	return checksum;
104566aee900SScott Liu }
104666aee900SScott Liu 
10479517b95bSMichał Mirosław static void elants_i2c_event(struct elants_data *ts, u8 *buf,
10489517b95bSMichał Mirosław 			     size_t packet_size)
104966aee900SScott Liu {
105066aee900SScott Liu 	u8 checksum = elants_i2c_calculate_checksum(buf);
105166aee900SScott Liu 
105266aee900SScott Liu 	if (unlikely(buf[FW_POS_CHECKSUM] != checksum))
105366aee900SScott Liu 		dev_warn(&ts->client->dev,
105466aee900SScott Liu 			 "%s: invalid checksum for packet %02x: %02x vs. %02x\n",
105566aee900SScott Liu 			 __func__, buf[FW_POS_HEADER],
105666aee900SScott Liu 			 checksum, buf[FW_POS_CHECKSUM]);
105766aee900SScott Liu 	else if (unlikely(buf[FW_POS_HEADER] != HEADER_REPORT_10_FINGER))
105866aee900SScott Liu 		dev_warn(&ts->client->dev,
105966aee900SScott Liu 			 "%s: unknown packet type: %02x\n",
106066aee900SScott Liu 			 __func__, buf[FW_POS_HEADER]);
106166aee900SScott Liu 	else
10629517b95bSMichał Mirosław 		elants_i2c_mt_event(ts, buf, packet_size);
106366aee900SScott Liu }
106466aee900SScott Liu 
106566aee900SScott Liu static irqreturn_t elants_i2c_irq(int irq, void *_dev)
106666aee900SScott Liu {
106766aee900SScott Liu 	const u8 wait_packet[] = { 0x64, 0x64, 0x64, 0x64 };
106866aee900SScott Liu 	struct elants_data *ts = _dev;
106966aee900SScott Liu 	struct i2c_client *client = ts->client;
107066aee900SScott Liu 	int report_count, report_len;
107166aee900SScott Liu 	int i;
107266aee900SScott Liu 	int len;
107366aee900SScott Liu 
107400f73f97SStephen Boyd 	len = i2c_master_recv_dmasafe(client, ts->buf, sizeof(ts->buf));
107566aee900SScott Liu 	if (len < 0) {
107666aee900SScott Liu 		dev_err(&client->dev, "%s: failed to read data: %d\n",
107766aee900SScott Liu 			__func__, len);
107866aee900SScott Liu 		goto out;
107966aee900SScott Liu 	}
108066aee900SScott Liu 
108166aee900SScott Liu 	dev_dbg(&client->dev, "%s: packet %*ph\n",
108266aee900SScott Liu 		__func__, HEADER_SIZE, ts->buf);
108366aee900SScott Liu 
108466aee900SScott Liu 	switch (ts->state) {
108566aee900SScott Liu 	case ELAN_WAIT_RECALIBRATION:
108666aee900SScott Liu 		if (ts->buf[FW_HDR_TYPE] == CMD_HEADER_REK) {
108766aee900SScott Liu 			memcpy(ts->cmd_resp, ts->buf, sizeof(ts->cmd_resp));
108866aee900SScott Liu 			complete(&ts->cmd_done);
108966aee900SScott Liu 			ts->state = ELAN_STATE_NORMAL;
109066aee900SScott Liu 		}
109166aee900SScott Liu 		break;
109266aee900SScott Liu 
109366aee900SScott Liu 	case ELAN_WAIT_QUEUE_HEADER:
109466aee900SScott Liu 		if (ts->buf[FW_HDR_TYPE] != QUEUE_HEADER_NORMAL)
109566aee900SScott Liu 			break;
109666aee900SScott Liu 
109766aee900SScott Liu 		ts->state = ELAN_STATE_NORMAL;
10986f49c4f5SGustavo A. R. Silva 		fallthrough;
109966aee900SScott Liu 
110066aee900SScott Liu 	case ELAN_STATE_NORMAL:
110166aee900SScott Liu 
110266aee900SScott Liu 		switch (ts->buf[FW_HDR_TYPE]) {
110366aee900SScott Liu 		case CMD_HEADER_HELLO:
110466aee900SScott Liu 		case CMD_HEADER_RESP:
110566aee900SScott Liu 			break;
110666aee900SScott Liu 
110766aee900SScott Liu 		case QUEUE_HEADER_WAIT:
110866aee900SScott Liu 			if (memcmp(ts->buf, wait_packet, sizeof(wait_packet))) {
110966aee900SScott Liu 				dev_err(&client->dev,
111066aee900SScott Liu 					"invalid wait packet %*ph\n",
111166aee900SScott Liu 					HEADER_SIZE, ts->buf);
111266aee900SScott Liu 			} else {
111366aee900SScott Liu 				ts->state = ELAN_WAIT_QUEUE_HEADER;
111466aee900SScott Liu 				udelay(30);
111566aee900SScott Liu 			}
111666aee900SScott Liu 			break;
111766aee900SScott Liu 
111866aee900SScott Liu 		case QUEUE_HEADER_SINGLE:
11199517b95bSMichał Mirosław 			elants_i2c_event(ts, &ts->buf[HEADER_SIZE],
11209517b95bSMichał Mirosław 					 ts->buf[FW_HDR_LENGTH]);
112166aee900SScott Liu 			break;
112266aee900SScott Liu 
11239517b95bSMichał Mirosław 		case QUEUE_HEADER_NORMAL2: /* CMD_HEADER_REK */
11249517b95bSMichał Mirosław 			/*
11259517b95bSMichał Mirosław 			 * Depending on firmware version, eKTF3624 touchscreens
11269517b95bSMichał Mirosław 			 * may utilize one of these opcodes for the touch events:
11279517b95bSMichał Mirosław 			 * 0x63 (NORMAL) and 0x66 (NORMAL2).  The 0x63 is used by
11289517b95bSMichał Mirosław 			 * older firmware version and differs from 0x66 such that
11299517b95bSMichał Mirosław 			 * touch pressure value needs to be adjusted.  The 0x66
11309517b95bSMichał Mirosław 			 * opcode of newer firmware is equal to 0x63 of eKTH3500.
11319517b95bSMichał Mirosław 			 */
11329517b95bSMichał Mirosław 			if (ts->chip_id != EKTF3624)
11339517b95bSMichał Mirosław 				break;
11349517b95bSMichał Mirosław 
11359517b95bSMichał Mirosław 			fallthrough;
11369517b95bSMichał Mirosław 
113766aee900SScott Liu 		case QUEUE_HEADER_NORMAL:
113866aee900SScott Liu 			report_count = ts->buf[FW_HDR_COUNT];
11391c3415a0SGuenter Roeck 			if (report_count == 0 || report_count > 3) {
114066aee900SScott Liu 				dev_err(&client->dev,
11411c3415a0SGuenter Roeck 					"bad report count: %*ph\n",
114266aee900SScott Liu 					HEADER_SIZE, ts->buf);
114366aee900SScott Liu 				break;
114466aee900SScott Liu 			}
114566aee900SScott Liu 
114666aee900SScott Liu 			report_len = ts->buf[FW_HDR_LENGTH] / report_count;
11479517b95bSMichał Mirosław 
11489517b95bSMichał Mirosław 			if (report_len == PACKET_SIZE_OLD &&
11499517b95bSMichał Mirosław 			    ts->chip_id == EKTF3624) {
11509517b95bSMichał Mirosław 				dev_dbg_once(&client->dev,
11519517b95bSMichał Mirosław 					     "using old report format\n");
11529517b95bSMichał Mirosław 			} else if (report_len != PACKET_SIZE) {
115366aee900SScott Liu 				dev_err(&client->dev,
115466aee900SScott Liu 					"mismatching report length: %*ph\n",
115566aee900SScott Liu 					HEADER_SIZE, ts->buf);
115666aee900SScott Liu 				break;
115766aee900SScott Liu 			}
115866aee900SScott Liu 
115966aee900SScott Liu 			for (i = 0; i < report_count; i++) {
116066aee900SScott Liu 				u8 *buf = ts->buf + HEADER_SIZE +
11619517b95bSMichał Mirosław 							i * report_len;
11629517b95bSMichał Mirosław 				elants_i2c_event(ts, buf, report_len);
116366aee900SScott Liu 			}
116466aee900SScott Liu 			break;
116566aee900SScott Liu 
116666aee900SScott Liu 		default:
116766aee900SScott Liu 			dev_err(&client->dev, "unknown packet %*ph\n",
116866aee900SScott Liu 				HEADER_SIZE, ts->buf);
116966aee900SScott Liu 			break;
117066aee900SScott Liu 		}
117166aee900SScott Liu 		break;
117266aee900SScott Liu 	}
117366aee900SScott Liu 
117466aee900SScott Liu out:
117566aee900SScott Liu 	return IRQ_HANDLED;
117666aee900SScott Liu }
117766aee900SScott Liu 
117866aee900SScott Liu /*
117966aee900SScott Liu  * sysfs interface
118066aee900SScott Liu  */
118166aee900SScott Liu static ssize_t calibrate_store(struct device *dev,
118266aee900SScott Liu 			       struct device_attribute *attr,
118366aee900SScott Liu 			       const char *buf, size_t count)
118466aee900SScott Liu {
118566aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
118666aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
118766aee900SScott Liu 	int error;
118866aee900SScott Liu 
118966aee900SScott Liu 	error = mutex_lock_interruptible(&ts->sysfs_mutex);
119066aee900SScott Liu 	if (error)
119166aee900SScott Liu 		return error;
119266aee900SScott Liu 
119366aee900SScott Liu 	error = elants_i2c_calibrate(ts);
119466aee900SScott Liu 
119566aee900SScott Liu 	mutex_unlock(&ts->sysfs_mutex);
119666aee900SScott Liu 	return error ?: count;
119766aee900SScott Liu }
119866aee900SScott Liu 
119966aee900SScott Liu static ssize_t write_update_fw(struct device *dev,
120066aee900SScott Liu 			       struct device_attribute *attr,
120166aee900SScott Liu 			       const char *buf, size_t count)
120266aee900SScott Liu {
120366aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
120466aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
120566aee900SScott Liu 	int error;
120666aee900SScott Liu 
120766aee900SScott Liu 	error = mutex_lock_interruptible(&ts->sysfs_mutex);
120866aee900SScott Liu 	if (error)
120966aee900SScott Liu 		return error;
121066aee900SScott Liu 
121166aee900SScott Liu 	error = elants_i2c_fw_update(ts);
121266aee900SScott Liu 	dev_dbg(dev, "firmware update result: %d\n", error);
121366aee900SScott Liu 
121466aee900SScott Liu 	mutex_unlock(&ts->sysfs_mutex);
121566aee900SScott Liu 	return error ?: count;
121666aee900SScott Liu }
121766aee900SScott Liu 
121866aee900SScott Liu static ssize_t show_iap_mode(struct device *dev,
121966aee900SScott Liu 			     struct device_attribute *attr, char *buf)
122066aee900SScott Liu {
122166aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
122266aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
122366aee900SScott Liu 
122466aee900SScott Liu 	return sprintf(buf, "%s\n",
122566aee900SScott Liu 		       ts->iap_mode == ELAN_IAP_OPERATIONAL ?
122666aee900SScott Liu 				"Normal" : "Recovery");
122766aee900SScott Liu }
122866aee900SScott Liu 
1229cf520c64SJohnny Chuang static ssize_t show_calibration_count(struct device *dev,
1230cf520c64SJohnny Chuang 				      struct device_attribute *attr, char *buf)
1231cf520c64SJohnny Chuang {
1232cf520c64SJohnny Chuang 	struct i2c_client *client = to_i2c_client(dev);
1233cf520c64SJohnny Chuang 	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_REK, 0x00, 0x01 };
1234cf520c64SJohnny Chuang 	u8 resp[HEADER_SIZE];
1235cf520c64SJohnny Chuang 	u16 rek_count;
1236cf520c64SJohnny Chuang 	int error;
1237cf520c64SJohnny Chuang 
1238cf520c64SJohnny Chuang 	error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
1239918e2844SMichał Mirosław 					   resp, sizeof(resp), 1,
1240918e2844SMichał Mirosław 					   "read ReK status");
1241918e2844SMichał Mirosław 	if (error)
1242cf520c64SJohnny Chuang 		return sprintf(buf, "%d\n", error);
1243cf520c64SJohnny Chuang 
1244cf520c64SJohnny Chuang 	rek_count = get_unaligned_be16(&resp[2]);
1245cf520c64SJohnny Chuang 	return sprintf(buf, "0x%04x\n", rek_count);
1246cf520c64SJohnny Chuang }
1247cf520c64SJohnny Chuang 
12486cbaefb4SJoe Perches static DEVICE_ATTR_WO(calibrate);
124966aee900SScott Liu static DEVICE_ATTR(iap_mode, S_IRUGO, show_iap_mode, NULL);
1250cf520c64SJohnny Chuang static DEVICE_ATTR(calibration_count, S_IRUGO, show_calibration_count, NULL);
125166aee900SScott Liu static DEVICE_ATTR(update_fw, S_IWUSR, NULL, write_update_fw);
125266aee900SScott Liu 
125366aee900SScott Liu struct elants_version_attribute {
125466aee900SScott Liu 	struct device_attribute dattr;
125566aee900SScott Liu 	size_t field_offset;
125666aee900SScott Liu 	size_t field_size;
125766aee900SScott Liu };
125866aee900SScott Liu 
125966aee900SScott Liu #define __ELANTS_FIELD_SIZE(_field)					\
126066aee900SScott Liu 	sizeof(((struct elants_data *)NULL)->_field)
126166aee900SScott Liu #define __ELANTS_VERIFY_SIZE(_field)					\
126266aee900SScott Liu 	(BUILD_BUG_ON_ZERO(__ELANTS_FIELD_SIZE(_field) > 2) +		\
126366aee900SScott Liu 	 __ELANTS_FIELD_SIZE(_field))
126466aee900SScott Liu #define ELANTS_VERSION_ATTR(_field)					\
126566aee900SScott Liu 	struct elants_version_attribute elants_ver_attr_##_field = {	\
126666aee900SScott Liu 		.dattr = __ATTR(_field, S_IRUGO,			\
126766aee900SScott Liu 				elants_version_attribute_show, NULL),	\
126866aee900SScott Liu 		.field_offset = offsetof(struct elants_data, _field),	\
126966aee900SScott Liu 		.field_size = __ELANTS_VERIFY_SIZE(_field),		\
127066aee900SScott Liu 	}
127166aee900SScott Liu 
127266aee900SScott Liu static ssize_t elants_version_attribute_show(struct device *dev,
127366aee900SScott Liu 					     struct device_attribute *dattr,
127466aee900SScott Liu 					     char *buf)
127566aee900SScott Liu {
127666aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
127766aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
127866aee900SScott Liu 	struct elants_version_attribute *attr =
127966aee900SScott Liu 		container_of(dattr, struct elants_version_attribute, dattr);
128066aee900SScott Liu 	u8 *field = (u8 *)((char *)ts + attr->field_offset);
128166aee900SScott Liu 	unsigned int fmt_size;
128266aee900SScott Liu 	unsigned int val;
128366aee900SScott Liu 
128466aee900SScott Liu 	if (attr->field_size == 1) {
128566aee900SScott Liu 		val = *field;
128666aee900SScott Liu 		fmt_size = 2; /* 2 HEX digits */
128766aee900SScott Liu 	} else {
128866aee900SScott Liu 		val = *(u16 *)field;
128966aee900SScott Liu 		fmt_size = 4; /* 4 HEX digits */
129066aee900SScott Liu 	}
129166aee900SScott Liu 
129266aee900SScott Liu 	return sprintf(buf, "%0*x\n", fmt_size, val);
129366aee900SScott Liu }
129466aee900SScott Liu 
129566aee900SScott Liu static ELANTS_VERSION_ATTR(fw_version);
129666aee900SScott Liu static ELANTS_VERSION_ATTR(hw_version);
129766aee900SScott Liu static ELANTS_VERSION_ATTR(test_version);
129866aee900SScott Liu static ELANTS_VERSION_ATTR(solution_version);
129966aee900SScott Liu static ELANTS_VERSION_ATTR(bc_version);
130066aee900SScott Liu static ELANTS_VERSION_ATTR(iap_version);
130166aee900SScott Liu 
130266aee900SScott Liu static struct attribute *elants_attributes[] = {
130366aee900SScott Liu 	&dev_attr_calibrate.attr,
130466aee900SScott Liu 	&dev_attr_update_fw.attr,
130566aee900SScott Liu 	&dev_attr_iap_mode.attr,
1306cf520c64SJohnny Chuang 	&dev_attr_calibration_count.attr,
130766aee900SScott Liu 
130866aee900SScott Liu 	&elants_ver_attr_fw_version.dattr.attr,
130966aee900SScott Liu 	&elants_ver_attr_hw_version.dattr.attr,
131066aee900SScott Liu 	&elants_ver_attr_test_version.dattr.attr,
131166aee900SScott Liu 	&elants_ver_attr_solution_version.dattr.attr,
131266aee900SScott Liu 	&elants_ver_attr_bc_version.dattr.attr,
131366aee900SScott Liu 	&elants_ver_attr_iap_version.dattr.attr,
131466aee900SScott Liu 	NULL
131566aee900SScott Liu };
131666aee900SScott Liu 
131748f960ddSArvind Yadav static const struct attribute_group elants_attribute_group = {
131866aee900SScott Liu 	.attrs = elants_attributes,
131966aee900SScott Liu };
132066aee900SScott Liu 
1321afe10358SDmitry Torokhov static int elants_i2c_power_on(struct elants_data *ts)
1322afe10358SDmitry Torokhov {
1323afe10358SDmitry Torokhov 	int error;
1324afe10358SDmitry Torokhov 
1325afe10358SDmitry Torokhov 	/*
1326afe10358SDmitry Torokhov 	 * If we do not have reset gpio assume platform firmware
1327afe10358SDmitry Torokhov 	 * controls regulators and does power them on for us.
1328afe10358SDmitry Torokhov 	 */
1329afe10358SDmitry Torokhov 	if (IS_ERR_OR_NULL(ts->reset_gpio))
1330afe10358SDmitry Torokhov 		return 0;
1331afe10358SDmitry Torokhov 
1332afe10358SDmitry Torokhov 	gpiod_set_value_cansleep(ts->reset_gpio, 1);
1333afe10358SDmitry Torokhov 
1334afe10358SDmitry Torokhov 	error = regulator_enable(ts->vcc33);
1335afe10358SDmitry Torokhov 	if (error) {
1336afe10358SDmitry Torokhov 		dev_err(&ts->client->dev,
1337afe10358SDmitry Torokhov 			"failed to enable vcc33 regulator: %d\n",
1338afe10358SDmitry Torokhov 			error);
1339afe10358SDmitry Torokhov 		goto release_reset_gpio;
1340afe10358SDmitry Torokhov 	}
1341afe10358SDmitry Torokhov 
1342afe10358SDmitry Torokhov 	error = regulator_enable(ts->vccio);
1343afe10358SDmitry Torokhov 	if (error) {
1344afe10358SDmitry Torokhov 		dev_err(&ts->client->dev,
1345afe10358SDmitry Torokhov 			"failed to enable vccio regulator: %d\n",
1346afe10358SDmitry Torokhov 			error);
1347afe10358SDmitry Torokhov 		regulator_disable(ts->vcc33);
1348afe10358SDmitry Torokhov 		goto release_reset_gpio;
1349afe10358SDmitry Torokhov 	}
1350afe10358SDmitry Torokhov 
1351afe10358SDmitry Torokhov 	/*
1352afe10358SDmitry Torokhov 	 * We need to wait a bit after powering on controller before
1353afe10358SDmitry Torokhov 	 * we are allowed to release reset GPIO.
1354afe10358SDmitry Torokhov 	 */
1355afe10358SDmitry Torokhov 	udelay(ELAN_POWERON_DELAY_USEC);
1356afe10358SDmitry Torokhov 
1357afe10358SDmitry Torokhov release_reset_gpio:
1358afe10358SDmitry Torokhov 	gpiod_set_value_cansleep(ts->reset_gpio, 0);
1359afe10358SDmitry Torokhov 	if (error)
1360afe10358SDmitry Torokhov 		return error;
1361afe10358SDmitry Torokhov 
1362afe10358SDmitry Torokhov 	msleep(ELAN_RESET_DELAY_MSEC);
1363afe10358SDmitry Torokhov 
1364afe10358SDmitry Torokhov 	return 0;
1365afe10358SDmitry Torokhov }
1366afe10358SDmitry Torokhov 
1367afe10358SDmitry Torokhov static void elants_i2c_power_off(void *_data)
1368afe10358SDmitry Torokhov {
1369afe10358SDmitry Torokhov 	struct elants_data *ts = _data;
1370afe10358SDmitry Torokhov 
1371afe10358SDmitry Torokhov 	if (!IS_ERR_OR_NULL(ts->reset_gpio)) {
1372afe10358SDmitry Torokhov 		/*
1373afe10358SDmitry Torokhov 		 * Activate reset gpio to prevent leakage through the
1374afe10358SDmitry Torokhov 		 * pin once we shut off power to the controller.
1375afe10358SDmitry Torokhov 		 */
1376afe10358SDmitry Torokhov 		gpiod_set_value_cansleep(ts->reset_gpio, 1);
1377afe10358SDmitry Torokhov 		regulator_disable(ts->vccio);
1378afe10358SDmitry Torokhov 		regulator_disable(ts->vcc33);
1379afe10358SDmitry Torokhov 	}
1380afe10358SDmitry Torokhov }
1381afe10358SDmitry Torokhov 
138265299e8bSHans de Goede #ifdef CONFIG_ACPI
138365299e8bSHans de Goede static const struct acpi_device_id i2c_hid_ids[] = {
138465299e8bSHans de Goede 	{"ACPI0C50", 0 },
138565299e8bSHans de Goede 	{"PNP0C50", 0 },
138665299e8bSHans de Goede 	{ },
138765299e8bSHans de Goede };
138865299e8bSHans de Goede 
138965299e8bSHans de Goede static const guid_t i2c_hid_guid =
139065299e8bSHans de Goede 	GUID_INIT(0x3CDFF6F7, 0x4267, 0x4555,
139165299e8bSHans de Goede 		  0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE);
139265299e8bSHans de Goede 
139365299e8bSHans de Goede static bool elants_acpi_is_hid_device(struct device *dev)
139465299e8bSHans de Goede {
139565299e8bSHans de Goede 	acpi_handle handle = ACPI_HANDLE(dev);
139665299e8bSHans de Goede 	union acpi_object *obj;
139765299e8bSHans de Goede 
139865299e8bSHans de Goede 	if (acpi_match_device_ids(ACPI_COMPANION(dev), i2c_hid_ids))
139965299e8bSHans de Goede 		return false;
140065299e8bSHans de Goede 
140165299e8bSHans de Goede 	obj = acpi_evaluate_dsm_typed(handle, &i2c_hid_guid, 1, 1, NULL, ACPI_TYPE_INTEGER);
140265299e8bSHans de Goede 	if (obj) {
140365299e8bSHans de Goede 		ACPI_FREE(obj);
140465299e8bSHans de Goede 		return true;
140565299e8bSHans de Goede 	}
140665299e8bSHans de Goede 
140765299e8bSHans de Goede 	return false;
140865299e8bSHans de Goede }
140965299e8bSHans de Goede #else
141065299e8bSHans de Goede static bool elants_acpi_is_hid_device(struct device *dev)
141165299e8bSHans de Goede {
141265299e8bSHans de Goede 	return false;
141365299e8bSHans de Goede }
141465299e8bSHans de Goede #endif
141565299e8bSHans de Goede 
141645a4b683STakashi Iwai static int elants_i2c_probe(struct i2c_client *client)
141766aee900SScott Liu {
141866aee900SScott Liu 	union i2c_smbus_data dummy;
141966aee900SScott Liu 	struct elants_data *ts;
142066aee900SScott Liu 	unsigned long irqflags;
142166aee900SScott Liu 	int error;
142266aee900SScott Liu 
142365299e8bSHans de Goede 	/* Don't bind to i2c-hid compatible devices, these are handled by the i2c-hid drv. */
142465299e8bSHans de Goede 	if (elants_acpi_is_hid_device(&client->dev)) {
142565299e8bSHans de Goede 		dev_warn(&client->dev, "This device appears to be an I2C-HID device, not binding\n");
142665299e8bSHans de Goede 		return -ENODEV;
142765299e8bSHans de Goede 	}
142865299e8bSHans de Goede 
142966aee900SScott Liu 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
143065299e8bSHans de Goede 		dev_err(&client->dev, "I2C check functionality error\n");
143166aee900SScott Liu 		return -ENXIO;
143266aee900SScott Liu 	}
143366aee900SScott Liu 
143466aee900SScott Liu 	ts = devm_kzalloc(&client->dev, sizeof(struct elants_data), GFP_KERNEL);
143566aee900SScott Liu 	if (!ts)
143666aee900SScott Liu 		return -ENOMEM;
143766aee900SScott Liu 
143866aee900SScott Liu 	mutex_init(&ts->sysfs_mutex);
143966aee900SScott Liu 	init_completion(&ts->cmd_done);
144066aee900SScott Liu 
144166aee900SScott Liu 	ts->client = client;
1442b9c0ebb8STakashi Iwai 	ts->chip_id = (enum elants_chip_id)(uintptr_t)device_get_match_data(&client->dev);
144366aee900SScott Liu 	i2c_set_clientdata(client, ts);
144466aee900SScott Liu 
1445afe10358SDmitry Torokhov 	ts->vcc33 = devm_regulator_get(&client->dev, "vcc33");
1446afe10358SDmitry Torokhov 	if (IS_ERR(ts->vcc33)) {
1447afe10358SDmitry Torokhov 		error = PTR_ERR(ts->vcc33);
1448afe10358SDmitry Torokhov 		if (error != -EPROBE_DEFER)
1449afe10358SDmitry Torokhov 			dev_err(&client->dev,
1450afe10358SDmitry Torokhov 				"Failed to get 'vcc33' regulator: %d\n",
1451afe10358SDmitry Torokhov 				error);
1452afe10358SDmitry Torokhov 		return error;
1453afe10358SDmitry Torokhov 	}
1454afe10358SDmitry Torokhov 
1455afe10358SDmitry Torokhov 	ts->vccio = devm_regulator_get(&client->dev, "vccio");
1456afe10358SDmitry Torokhov 	if (IS_ERR(ts->vccio)) {
1457afe10358SDmitry Torokhov 		error = PTR_ERR(ts->vccio);
1458afe10358SDmitry Torokhov 		if (error != -EPROBE_DEFER)
1459afe10358SDmitry Torokhov 			dev_err(&client->dev,
1460afe10358SDmitry Torokhov 				"Failed to get 'vccio' regulator: %d\n",
1461afe10358SDmitry Torokhov 				error);
1462afe10358SDmitry Torokhov 		return error;
1463afe10358SDmitry Torokhov 	}
1464afe10358SDmitry Torokhov 
14657229b87bSStephen Rothwell 	ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW);
1466afe10358SDmitry Torokhov 	if (IS_ERR(ts->reset_gpio)) {
1467afe10358SDmitry Torokhov 		error = PTR_ERR(ts->reset_gpio);
1468afe10358SDmitry Torokhov 
1469afe10358SDmitry Torokhov 		if (error == -EPROBE_DEFER)
1470afe10358SDmitry Torokhov 			return error;
1471afe10358SDmitry Torokhov 
1472afe10358SDmitry Torokhov 		if (error != -ENOENT && error != -ENOSYS) {
1473afe10358SDmitry Torokhov 			dev_err(&client->dev,
1474afe10358SDmitry Torokhov 				"failed to get reset gpio: %d\n",
1475afe10358SDmitry Torokhov 				error);
1476afe10358SDmitry Torokhov 			return error;
1477afe10358SDmitry Torokhov 		}
1478afe10358SDmitry Torokhov 
1479afe10358SDmitry Torokhov 		ts->keep_power_in_suspend = true;
1480afe10358SDmitry Torokhov 	}
1481afe10358SDmitry Torokhov 
1482afe10358SDmitry Torokhov 	error = elants_i2c_power_on(ts);
1483afe10358SDmitry Torokhov 	if (error)
1484afe10358SDmitry Torokhov 		return error;
1485afe10358SDmitry Torokhov 
1486b083704fSCai Huoqing 	error = devm_add_action_or_reset(&client->dev,
1487b083704fSCai Huoqing 					 elants_i2c_power_off, ts);
1488afe10358SDmitry Torokhov 	if (error) {
1489afe10358SDmitry Torokhov 		dev_err(&client->dev,
1490afe10358SDmitry Torokhov 			"failed to install power off action: %d\n", error);
1491afe10358SDmitry Torokhov 		return error;
1492afe10358SDmitry Torokhov 	}
1493afe10358SDmitry Torokhov 
1494afe10358SDmitry Torokhov 	/* Make sure there is something at this address */
1495afe10358SDmitry Torokhov 	if (i2c_smbus_xfer(client->adapter, client->addr, 0,
1496afe10358SDmitry Torokhov 			   I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0) {
1497afe10358SDmitry Torokhov 		dev_err(&client->dev, "nothing at this address\n");
1498afe10358SDmitry Torokhov 		return -ENXIO;
1499afe10358SDmitry Torokhov 	}
1500afe10358SDmitry Torokhov 
150166aee900SScott Liu 	error = elants_i2c_initialize(ts);
150266aee900SScott Liu 	if (error) {
150366aee900SScott Liu 		dev_err(&client->dev, "failed to initialize: %d\n", error);
150466aee900SScott Liu 		return error;
150566aee900SScott Liu 	}
150666aee900SScott Liu 
150766aee900SScott Liu 	ts->input = devm_input_allocate_device(&client->dev);
150866aee900SScott Liu 	if (!ts->input) {
150966aee900SScott Liu 		dev_err(&client->dev, "Failed to allocate input device\n");
151066aee900SScott Liu 		return -ENOMEM;
151166aee900SScott Liu 	}
151266aee900SScott Liu 
151366aee900SScott Liu 	ts->input->name = "Elan Touchscreen";
151466aee900SScott Liu 	ts->input->id.bustype = BUS_I2C;
151566aee900SScott Liu 
151666aee900SScott Liu 	/* Multitouch input params setup */
151766aee900SScott Liu 
151866aee900SScott Liu 	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->x_max, 0, 0);
151966aee900SScott Liu 	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, 0, 0);
152066aee900SScott Liu 	input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
152166aee900SScott Liu 	input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
1522f27ad893SJohnny Chuang 	input_set_abs_params(ts->input, ABS_MT_TOOL_TYPE,
1523f27ad893SJohnny Chuang 			     0, MT_TOOL_PALM, 0, 0);
15249517b95bSMichał Mirosław 
15259517b95bSMichał Mirosław 	touchscreen_parse_properties(ts->input, true, &ts->prop);
15269517b95bSMichał Mirosław 
1527781bab32SDmitry Osipenko 	if (ts->chip_id == EKTF3624 && ts->phy_x && ts->phy_y) {
15289517b95bSMichał Mirosław 		/* calculate resolution from size */
15299517b95bSMichał Mirosław 		ts->x_res = DIV_ROUND_CLOSEST(ts->prop.max_x, ts->phy_x);
15309517b95bSMichał Mirosław 		ts->y_res = DIV_ROUND_CLOSEST(ts->prop.max_y, ts->phy_y);
15319517b95bSMichał Mirosław 	}
15329517b95bSMichał Mirosław 
153366aee900SScott Liu 	input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res);
153466aee900SScott Liu 	input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res);
15354238e52cSJohnny Chuang 	input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, ts->major_res);
153666aee900SScott Liu 
15376def17b1SMichał Mirosław 	error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM,
15386def17b1SMichał Mirosław 				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
15396def17b1SMichał Mirosław 	if (error) {
15406def17b1SMichał Mirosław 		dev_err(&client->dev,
15416def17b1SMichał Mirosław 			"failed to initialize MT slots: %d\n", error);
15426def17b1SMichał Mirosław 		return error;
15436def17b1SMichał Mirosław 	}
15446def17b1SMichał Mirosław 
154566aee900SScott Liu 	error = input_register_device(ts->input);
154666aee900SScott Liu 	if (error) {
154766aee900SScott Liu 		dev_err(&client->dev,
154866aee900SScott Liu 			"unable to register input device: %d\n", error);
154966aee900SScott Liu 		return error;
155066aee900SScott Liu 	}
155166aee900SScott Liu 
155266aee900SScott Liu 	/*
15534c83c071SDmitry Torokhov 	 * Platform code (ACPI, DTS) should normally set up interrupt
15544c83c071SDmitry Torokhov 	 * for us, but in case it did not let's fall back to using falling
15554c83c071SDmitry Torokhov 	 * edge to be compatible with older Chromebooks.
155666aee900SScott Liu 	 */
15574c83c071SDmitry Torokhov 	irqflags = irq_get_trigger_type(client->irq);
15584c83c071SDmitry Torokhov 	if (!irqflags)
15594c83c071SDmitry Torokhov 		irqflags = IRQF_TRIGGER_FALLING;
156066aee900SScott Liu 
156166aee900SScott Liu 	error = devm_request_threaded_irq(&client->dev, client->irq,
156266aee900SScott Liu 					  NULL, elants_i2c_irq,
156366aee900SScott Liu 					  irqflags | IRQF_ONESHOT,
156466aee900SScott Liu 					  client->name, ts);
156566aee900SScott Liu 	if (error) {
156666aee900SScott Liu 		dev_err(&client->dev, "Failed to register interrupt\n");
156766aee900SScott Liu 		return error;
156866aee900SScott Liu 	}
156966aee900SScott Liu 
157066aee900SScott Liu 	/*
157166aee900SScott Liu 	 * Systems using device tree should set up wakeup via DTS,
157266aee900SScott Liu 	 * the rest will configure device as wakeup source by default.
157366aee900SScott Liu 	 */
157466aee900SScott Liu 	if (!client->dev.of_node)
157566aee900SScott Liu 		device_init_wakeup(&client->dev, true);
157666aee900SScott Liu 
15778db69a9aSAndi Shyti 	error = devm_device_add_group(&client->dev, &elants_attribute_group);
157866aee900SScott Liu 	if (error) {
157966aee900SScott Liu 		dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
158066aee900SScott Liu 			error);
158166aee900SScott Liu 		return error;
158266aee900SScott Liu 	}
158366aee900SScott Liu 
158466aee900SScott Liu 	return 0;
158566aee900SScott Liu }
158666aee900SScott Liu 
158766aee900SScott Liu static int __maybe_unused elants_i2c_suspend(struct device *dev)
158866aee900SScott Liu {
158966aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
159066aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
1591c18b443cSMichał Mirosław 	const u8 set_sleep_cmd[] = {
1592c18b443cSMichał Mirosław 		CMD_HEADER_WRITE, E_POWER_STATE_SLEEP, 0x00, 0x01
1593c18b443cSMichał Mirosław 	};
159466aee900SScott Liu 	int retry_cnt;
159566aee900SScott Liu 	int error;
159666aee900SScott Liu 
159766aee900SScott Liu 	/* Command not support in IAP recovery mode */
159866aee900SScott Liu 	if (ts->iap_mode != ELAN_IAP_OPERATIONAL)
159966aee900SScott Liu 		return -EBUSY;
160066aee900SScott Liu 
160166aee900SScott Liu 	disable_irq(client->irq);
160266aee900SScott Liu 
1603478e5ed1SJames Chen 	if (device_may_wakeup(dev)) {
1604478e5ed1SJames Chen 		/*
1605478e5ed1SJames Chen 		 * The device will automatically enter idle mode
1606478e5ed1SJames Chen 		 * that has reduced power consumption.
1607478e5ed1SJames Chen 		 */
1608478e5ed1SJames Chen 		ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0);
1609478e5ed1SJames Chen 	} else if (ts->keep_power_in_suspend) {
161066aee900SScott Liu 		for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
161166aee900SScott Liu 			error = elants_i2c_send(client, set_sleep_cmd,
161266aee900SScott Liu 						sizeof(set_sleep_cmd));
161366aee900SScott Liu 			if (!error)
161466aee900SScott Liu 				break;
161566aee900SScott Liu 
1616afe10358SDmitry Torokhov 			dev_err(&client->dev,
1617afe10358SDmitry Torokhov 				"suspend command failed: %d\n", error);
161866aee900SScott Liu 		}
1619afe10358SDmitry Torokhov 	} else {
1620afe10358SDmitry Torokhov 		elants_i2c_power_off(ts);
1621afe10358SDmitry Torokhov 	}
162266aee900SScott Liu 
162366aee900SScott Liu 	return 0;
162466aee900SScott Liu }
162566aee900SScott Liu 
162666aee900SScott Liu static int __maybe_unused elants_i2c_resume(struct device *dev)
162766aee900SScott Liu {
162866aee900SScott Liu 	struct i2c_client *client = to_i2c_client(dev);
162966aee900SScott Liu 	struct elants_data *ts = i2c_get_clientdata(client);
1630c18b443cSMichał Mirosław 	const u8 set_active_cmd[] = {
1631c18b443cSMichał Mirosław 		CMD_HEADER_WRITE, E_POWER_STATE_RESUME, 0x00, 0x01
1632c18b443cSMichał Mirosław 	};
163366aee900SScott Liu 	int retry_cnt;
163466aee900SScott Liu 	int error;
163566aee900SScott Liu 
1636478e5ed1SJames Chen 	if (device_may_wakeup(dev)) {
1637478e5ed1SJames Chen 		if (ts->wake_irq_enabled)
163866aee900SScott Liu 			disable_irq_wake(client->irq);
1639478e5ed1SJames Chen 		elants_i2c_sw_reset(client);
1640478e5ed1SJames Chen 	} else if (ts->keep_power_in_suspend) {
164166aee900SScott Liu 		for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
164266aee900SScott Liu 			error = elants_i2c_send(client, set_active_cmd,
164366aee900SScott Liu 						sizeof(set_active_cmd));
164466aee900SScott Liu 			if (!error)
164566aee900SScott Liu 				break;
164666aee900SScott Liu 
1647afe10358SDmitry Torokhov 			dev_err(&client->dev,
1648afe10358SDmitry Torokhov 				"resume command failed: %d\n", error);
1649afe10358SDmitry Torokhov 		}
1650afe10358SDmitry Torokhov 	} else {
1651afe10358SDmitry Torokhov 		elants_i2c_power_on(ts);
1652afe10358SDmitry Torokhov 		elants_i2c_initialize(ts);
165366aee900SScott Liu 	}
165466aee900SScott Liu 
165566aee900SScott Liu 	ts->state = ELAN_STATE_NORMAL;
165666aee900SScott Liu 	enable_irq(client->irq);
165766aee900SScott Liu 
165866aee900SScott Liu 	return 0;
165966aee900SScott Liu }
166066aee900SScott Liu 
166166aee900SScott Liu static SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops,
166266aee900SScott Liu 			 elants_i2c_suspend, elants_i2c_resume);
166366aee900SScott Liu 
166466aee900SScott Liu static const struct i2c_device_id elants_i2c_id[] = {
16659517b95bSMichał Mirosław 	{ DEVICE_NAME, EKTH3500 },
16669517b95bSMichał Mirosław 	{ "ekth3500", EKTH3500 },
16679517b95bSMichał Mirosław 	{ "ektf3624", EKTF3624 },
166866aee900SScott Liu 	{ }
166966aee900SScott Liu };
167066aee900SScott Liu MODULE_DEVICE_TABLE(i2c, elants_i2c_id);
167166aee900SScott Liu 
167266aee900SScott Liu #ifdef CONFIG_ACPI
167366aee900SScott Liu static const struct acpi_device_id elants_acpi_id[] = {
16749517b95bSMichał Mirosław 	{ "ELAN0001", EKTH3500 },
167566aee900SScott Liu 	{ }
167666aee900SScott Liu };
167766aee900SScott Liu MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
167866aee900SScott Liu #endif
167966aee900SScott Liu 
168066aee900SScott Liu #ifdef CONFIG_OF
168166aee900SScott Liu static const struct of_device_id elants_of_match[] = {
1682b9c0ebb8STakashi Iwai 	{ .compatible = "elan,ekth3500", .data = (void *)EKTH3500 },
1683b9c0ebb8STakashi Iwai 	{ .compatible = "elan,ektf3624", .data = (void *)EKTF3624 },
168466aee900SScott Liu 	{ /* sentinel */ }
168566aee900SScott Liu };
168666aee900SScott Liu MODULE_DEVICE_TABLE(of, elants_of_match);
168766aee900SScott Liu #endif
168866aee900SScott Liu 
168966aee900SScott Liu static struct i2c_driver elants_i2c_driver = {
169045a4b683STakashi Iwai 	.probe_new = elants_i2c_probe,
169166aee900SScott Liu 	.id_table = elants_i2c_id,
169266aee900SScott Liu 	.driver = {
169366aee900SScott Liu 		.name = DEVICE_NAME,
169466aee900SScott Liu 		.pm = &elants_i2c_pm_ops,
169566aee900SScott Liu 		.acpi_match_table = ACPI_PTR(elants_acpi_id),
169666aee900SScott Liu 		.of_match_table = of_match_ptr(elants_of_match),
16979f6a07b6SDmitry Torokhov 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
169866aee900SScott Liu 	},
169966aee900SScott Liu };
170066aee900SScott Liu module_i2c_driver(elants_i2c_driver);
170166aee900SScott Liu 
170266aee900SScott Liu MODULE_AUTHOR("Scott Liu <scott.liu@emc.com.tw>");
170366aee900SScott Liu MODULE_DESCRIPTION("Elan I2c Touchscreen driver");
170466aee900SScott Liu MODULE_LICENSE("GPL");
1705