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> 4166aee900SScott Liu #include <asm/unaligned.h> 4266aee900SScott Liu 4366aee900SScott Liu /* Device, Driver information */ 4466aee900SScott Liu #define DEVICE_NAME "elants_i2c" 4566aee900SScott Liu 4666aee900SScott Liu /* Convert from rows or columns into resolution */ 4766aee900SScott Liu #define ELAN_TS_RESOLUTION(n, m) (((n) - 1) * (m)) 4866aee900SScott Liu 4966aee900SScott Liu /* FW header data */ 5066aee900SScott Liu #define HEADER_SIZE 4 5166aee900SScott Liu #define FW_HDR_TYPE 0 5266aee900SScott Liu #define FW_HDR_COUNT 1 5366aee900SScott Liu #define FW_HDR_LENGTH 2 5466aee900SScott Liu 5566aee900SScott Liu /* Buffer mode Queue Header information */ 5666aee900SScott Liu #define QUEUE_HEADER_SINGLE 0x62 5766aee900SScott Liu #define QUEUE_HEADER_NORMAL 0X63 5866aee900SScott Liu #define QUEUE_HEADER_WAIT 0x64 5966aee900SScott Liu 6066aee900SScott Liu /* Command header definition */ 6166aee900SScott Liu #define CMD_HEADER_WRITE 0x54 6266aee900SScott Liu #define CMD_HEADER_READ 0x53 6366aee900SScott Liu #define CMD_HEADER_6B_READ 0x5B 64f0b57e19SJohnny.Chuang #define CMD_HEADER_ROM_READ 0x96 6566aee900SScott Liu #define CMD_HEADER_RESP 0x52 6666aee900SScott Liu #define CMD_HEADER_6B_RESP 0x9B 67f0b57e19SJohnny.Chuang #define CMD_HEADER_ROM_RESP 0x95 6866aee900SScott Liu #define CMD_HEADER_HELLO 0x55 6966aee900SScott Liu #define CMD_HEADER_REK 0x66 7066aee900SScott Liu 7166aee900SScott Liu /* FW position data */ 7266aee900SScott Liu #define PACKET_SIZE 55 7366aee900SScott Liu #define MAX_CONTACT_NUM 10 7466aee900SScott Liu #define FW_POS_HEADER 0 7566aee900SScott Liu #define FW_POS_STATE 1 7666aee900SScott Liu #define FW_POS_TOTAL 2 7766aee900SScott Liu #define FW_POS_XY 3 78f27ad893SJohnny Chuang #define FW_POS_TOOL_TYPE 33 7966aee900SScott Liu #define FW_POS_CHECKSUM 34 8066aee900SScott Liu #define FW_POS_WIDTH 35 8166aee900SScott Liu #define FW_POS_PRESSURE 45 8266aee900SScott Liu 8366aee900SScott Liu #define HEADER_REPORT_10_FINGER 0x62 8466aee900SScott Liu 8566aee900SScott Liu /* Header (4 bytes) plus 3 fill 10-finger packets */ 8666aee900SScott Liu #define MAX_PACKET_SIZE 169 8766aee900SScott Liu 8866aee900SScott Liu #define BOOT_TIME_DELAY_MS 50 8966aee900SScott Liu 9066aee900SScott Liu /* FW read command, 0x53 0x?? 0x0, 0x01 */ 9166aee900SScott Liu #define E_ELAN_INFO_FW_VER 0x00 9266aee900SScott Liu #define E_ELAN_INFO_BC_VER 0x10 93cf520c64SJohnny Chuang #define E_ELAN_INFO_REK 0xE0 9466aee900SScott Liu #define E_ELAN_INFO_TEST_VER 0xE0 9566aee900SScott Liu #define E_ELAN_INFO_FW_ID 0xF0 9666aee900SScott Liu #define E_INFO_OSR 0xD6 9766aee900SScott Liu #define E_INFO_PHY_SCAN 0xD7 9866aee900SScott Liu #define E_INFO_PHY_DRIVER 0xD8 9966aee900SScott Liu 10066aee900SScott Liu #define MAX_RETRIES 3 10166aee900SScott Liu #define MAX_FW_UPDATE_RETRIES 30 10266aee900SScott Liu 10366aee900SScott Liu #define ELAN_FW_PAGESIZE 132 10466aee900SScott Liu 10566aee900SScott Liu /* calibration timeout definition */ 10622c15e5eSJames Chen #define ELAN_CALI_TIMEOUT_MSEC 12000 10766aee900SScott Liu 108afe10358SDmitry Torokhov #define ELAN_POWERON_DELAY_USEC 500 109afe10358SDmitry Torokhov #define ELAN_RESET_DELAY_MSEC 20 110afe10358SDmitry Torokhov 11166aee900SScott Liu enum elants_state { 11266aee900SScott Liu ELAN_STATE_NORMAL, 11366aee900SScott Liu ELAN_WAIT_QUEUE_HEADER, 11466aee900SScott Liu ELAN_WAIT_RECALIBRATION, 11566aee900SScott Liu }; 11666aee900SScott Liu 11766aee900SScott Liu enum elants_iap_mode { 11866aee900SScott Liu ELAN_IAP_OPERATIONAL, 11966aee900SScott Liu ELAN_IAP_RECOVERY, 12066aee900SScott Liu }; 12166aee900SScott Liu 12266aee900SScott Liu /* struct elants_data - represents state of Elan touchscreen device */ 12366aee900SScott Liu struct elants_data { 12466aee900SScott Liu struct i2c_client *client; 12566aee900SScott Liu struct input_dev *input; 12666aee900SScott Liu 127afe10358SDmitry Torokhov struct regulator *vcc33; 128afe10358SDmitry Torokhov struct regulator *vccio; 129afe10358SDmitry Torokhov struct gpio_desc *reset_gpio; 130afe10358SDmitry Torokhov 13166aee900SScott Liu u16 fw_version; 13266aee900SScott Liu u8 test_version; 13366aee900SScott Liu u8 solution_version; 13466aee900SScott Liu u8 bc_version; 13566aee900SScott Liu u8 iap_version; 13666aee900SScott Liu u16 hw_version; 13766aee900SScott Liu unsigned int x_res; /* resolution in units/mm */ 13866aee900SScott Liu unsigned int y_res; 13966aee900SScott Liu unsigned int x_max; 14066aee900SScott Liu unsigned int y_max; 14168334dbaSMichał Mirosław struct touchscreen_properties prop; 14266aee900SScott Liu 14366aee900SScott Liu enum elants_state state; 14466aee900SScott Liu enum elants_iap_mode iap_mode; 14566aee900SScott Liu 14666aee900SScott Liu /* Guards against concurrent access to the device via sysfs */ 14766aee900SScott Liu struct mutex sysfs_mutex; 14866aee900SScott Liu 14966aee900SScott Liu u8 cmd_resp[HEADER_SIZE]; 15066aee900SScott Liu struct completion cmd_done; 15166aee900SScott Liu 15266aee900SScott Liu bool wake_irq_enabled; 153afe10358SDmitry Torokhov bool keep_power_in_suspend; 15400f73f97SStephen Boyd 15500f73f97SStephen Boyd /* Must be last to be used for DMA operations */ 15600f73f97SStephen Boyd u8 buf[MAX_PACKET_SIZE] ____cacheline_aligned; 15766aee900SScott Liu }; 15866aee900SScott Liu 15966aee900SScott Liu static int elants_i2c_send(struct i2c_client *client, 16066aee900SScott Liu const void *data, size_t size) 16166aee900SScott Liu { 16266aee900SScott Liu int ret; 16366aee900SScott Liu 16466aee900SScott Liu ret = i2c_master_send(client, data, size); 16566aee900SScott Liu if (ret == size) 16666aee900SScott Liu return 0; 16766aee900SScott Liu 16866aee900SScott Liu if (ret >= 0) 16966aee900SScott Liu ret = -EIO; 17066aee900SScott Liu 17166aee900SScott Liu dev_err(&client->dev, "%s failed (%*ph): %d\n", 17266aee900SScott Liu __func__, (int)size, data, ret); 17366aee900SScott Liu 17466aee900SScott Liu return ret; 17566aee900SScott Liu } 17666aee900SScott Liu 17766aee900SScott Liu static int elants_i2c_read(struct i2c_client *client, void *data, size_t size) 17866aee900SScott Liu { 17966aee900SScott Liu int ret; 18066aee900SScott Liu 18166aee900SScott Liu ret = i2c_master_recv(client, data, size); 18266aee900SScott Liu if (ret == size) 18366aee900SScott Liu return 0; 18466aee900SScott Liu 18566aee900SScott Liu if (ret >= 0) 18666aee900SScott Liu ret = -EIO; 18766aee900SScott Liu 18866aee900SScott Liu dev_err(&client->dev, "%s failed: %d\n", __func__, ret); 18966aee900SScott Liu 19066aee900SScott Liu return ret; 19166aee900SScott Liu } 19266aee900SScott Liu 19366aee900SScott Liu static int elants_i2c_execute_command(struct i2c_client *client, 19466aee900SScott Liu const u8 *cmd, size_t cmd_size, 19566aee900SScott Liu u8 *resp, size_t resp_size) 19666aee900SScott Liu { 19766aee900SScott Liu struct i2c_msg msgs[2]; 19866aee900SScott Liu int ret; 19966aee900SScott Liu u8 expected_response; 20066aee900SScott Liu 20166aee900SScott Liu switch (cmd[0]) { 20266aee900SScott Liu case CMD_HEADER_READ: 20366aee900SScott Liu expected_response = CMD_HEADER_RESP; 20466aee900SScott Liu break; 20566aee900SScott Liu 20666aee900SScott Liu case CMD_HEADER_6B_READ: 20766aee900SScott Liu expected_response = CMD_HEADER_6B_RESP; 20866aee900SScott Liu break; 20966aee900SScott Liu 210f0b57e19SJohnny.Chuang case CMD_HEADER_ROM_READ: 211f0b57e19SJohnny.Chuang expected_response = CMD_HEADER_ROM_RESP; 212f0b57e19SJohnny.Chuang break; 213f0b57e19SJohnny.Chuang 21466aee900SScott Liu default: 21566aee900SScott Liu dev_err(&client->dev, "%s: invalid command %*ph\n", 21666aee900SScott Liu __func__, (int)cmd_size, cmd); 21766aee900SScott Liu return -EINVAL; 21866aee900SScott Liu } 21966aee900SScott Liu 22066aee900SScott Liu msgs[0].addr = client->addr; 22166aee900SScott Liu msgs[0].flags = client->flags & I2C_M_TEN; 22266aee900SScott Liu msgs[0].len = cmd_size; 22366aee900SScott Liu msgs[0].buf = (u8 *)cmd; 22466aee900SScott Liu 22566aee900SScott Liu msgs[1].addr = client->addr; 22666aee900SScott Liu msgs[1].flags = client->flags & I2C_M_TEN; 22766aee900SScott Liu msgs[1].flags |= I2C_M_RD; 22866aee900SScott Liu msgs[1].len = resp_size; 22966aee900SScott Liu msgs[1].buf = resp; 23066aee900SScott Liu 23166aee900SScott Liu ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 23266aee900SScott Liu if (ret < 0) 23366aee900SScott Liu return ret; 23466aee900SScott Liu 23566aee900SScott Liu if (ret != ARRAY_SIZE(msgs) || resp[FW_HDR_TYPE] != expected_response) 23666aee900SScott Liu return -EIO; 23766aee900SScott Liu 23866aee900SScott Liu return 0; 23966aee900SScott Liu } 24066aee900SScott Liu 24166aee900SScott Liu static int elants_i2c_calibrate(struct elants_data *ts) 24266aee900SScott Liu { 24366aee900SScott Liu struct i2c_client *client = ts->client; 24466aee900SScott Liu int ret, error; 24566aee900SScott Liu static const u8 w_flashkey[] = { 0x54, 0xC0, 0xE1, 0x5A }; 24666aee900SScott Liu static const u8 rek[] = { 0x54, 0x29, 0x00, 0x01 }; 24766aee900SScott Liu static const u8 rek_resp[] = { CMD_HEADER_REK, 0x66, 0x66, 0x66 }; 24866aee900SScott Liu 24966aee900SScott Liu disable_irq(client->irq); 25066aee900SScott Liu 25166aee900SScott Liu ts->state = ELAN_WAIT_RECALIBRATION; 25266aee900SScott Liu reinit_completion(&ts->cmd_done); 25366aee900SScott Liu 25466aee900SScott Liu elants_i2c_send(client, w_flashkey, sizeof(w_flashkey)); 25566aee900SScott Liu elants_i2c_send(client, rek, sizeof(rek)); 25666aee900SScott Liu 25766aee900SScott Liu enable_irq(client->irq); 25866aee900SScott Liu 25966aee900SScott Liu ret = wait_for_completion_interruptible_timeout(&ts->cmd_done, 26066aee900SScott Liu msecs_to_jiffies(ELAN_CALI_TIMEOUT_MSEC)); 26166aee900SScott Liu 26266aee900SScott Liu ts->state = ELAN_STATE_NORMAL; 26366aee900SScott Liu 26466aee900SScott Liu if (ret <= 0) { 26566aee900SScott Liu error = ret < 0 ? ret : -ETIMEDOUT; 26666aee900SScott Liu dev_err(&client->dev, 26766aee900SScott Liu "error while waiting for calibration to complete: %d\n", 26866aee900SScott Liu error); 26966aee900SScott Liu return error; 27066aee900SScott Liu } 27166aee900SScott Liu 27266aee900SScott Liu if (memcmp(rek_resp, ts->cmd_resp, sizeof(rek_resp))) { 27366aee900SScott Liu dev_err(&client->dev, 27466aee900SScott Liu "unexpected calibration response: %*ph\n", 27566aee900SScott Liu (int)sizeof(ts->cmd_resp), ts->cmd_resp); 27666aee900SScott Liu return -EINVAL; 27766aee900SScott Liu } 27866aee900SScott Liu 27966aee900SScott Liu return 0; 28066aee900SScott Liu } 28166aee900SScott Liu 28266aee900SScott Liu static int elants_i2c_sw_reset(struct i2c_client *client) 28366aee900SScott Liu { 28466aee900SScott Liu const u8 soft_rst_cmd[] = { 0x77, 0x77, 0x77, 0x77 }; 28566aee900SScott Liu int error; 28666aee900SScott Liu 28766aee900SScott Liu error = elants_i2c_send(client, soft_rst_cmd, 28866aee900SScott Liu sizeof(soft_rst_cmd)); 28966aee900SScott Liu if (error) { 29066aee900SScott Liu dev_err(&client->dev, "software reset failed: %d\n", error); 29166aee900SScott Liu return error; 29266aee900SScott Liu } 29366aee900SScott Liu 29466aee900SScott Liu /* 29566aee900SScott Liu * We should wait at least 10 msec (but no more than 40) before 29666aee900SScott Liu * sending fastboot or IAP command to the device. 29766aee900SScott Liu */ 29866aee900SScott Liu msleep(30); 29966aee900SScott Liu 30066aee900SScott Liu return 0; 30166aee900SScott Liu } 30266aee900SScott Liu 30366aee900SScott Liu static u16 elants_i2c_parse_version(u8 *buf) 30466aee900SScott Liu { 30566aee900SScott Liu return get_unaligned_be32(buf) >> 4; 30666aee900SScott Liu } 30766aee900SScott Liu 308bc1d57feSJohnny Chuang static int elants_i2c_query_hw_version(struct elants_data *ts) 30966aee900SScott Liu { 31066aee900SScott Liu struct i2c_client *client = ts->client; 31166aee900SScott Liu int error, retry_cnt; 31266aee900SScott Liu const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_ID, 0x00, 0x01 }; 31366aee900SScott Liu u8 resp[HEADER_SIZE]; 31466aee900SScott Liu 31566aee900SScott Liu for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { 31666aee900SScott Liu error = elants_i2c_execute_command(client, cmd, sizeof(cmd), 31766aee900SScott Liu resp, sizeof(resp)); 31866aee900SScott Liu if (!error) { 31966aee900SScott Liu ts->hw_version = elants_i2c_parse_version(resp); 32066aee900SScott Liu if (ts->hw_version != 0xffff) 32166aee900SScott Liu return 0; 32266aee900SScott Liu } 32366aee900SScott Liu 32466aee900SScott Liu dev_dbg(&client->dev, "read fw id error=%d, buf=%*phC\n", 32566aee900SScott Liu error, (int)sizeof(resp), resp); 32666aee900SScott Liu } 32766aee900SScott Liu 328bc1d57feSJohnny Chuang if (error) { 32966aee900SScott Liu dev_err(&client->dev, 330bc1d57feSJohnny Chuang "Failed to read fw id: %d\n", error); 331bc1d57feSJohnny Chuang return error; 332bc1d57feSJohnny Chuang } 333bc1d57feSJohnny Chuang 334bc1d57feSJohnny Chuang dev_err(&client->dev, "Invalid fw id: %#04x\n", ts->hw_version); 33566aee900SScott Liu 33666aee900SScott Liu return -EINVAL; 33766aee900SScott Liu } 33866aee900SScott Liu 33966aee900SScott Liu static int elants_i2c_query_fw_version(struct elants_data *ts) 34066aee900SScott Liu { 34166aee900SScott Liu struct i2c_client *client = ts->client; 34266aee900SScott Liu int error, retry_cnt; 34366aee900SScott Liu const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_VER, 0x00, 0x01 }; 34466aee900SScott Liu u8 resp[HEADER_SIZE]; 34566aee900SScott Liu 34666aee900SScott Liu for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { 34766aee900SScott Liu error = elants_i2c_execute_command(client, cmd, sizeof(cmd), 34866aee900SScott Liu resp, sizeof(resp)); 34966aee900SScott Liu if (!error) { 35066aee900SScott Liu ts->fw_version = elants_i2c_parse_version(resp); 35166aee900SScott Liu if (ts->fw_version != 0x0000 && 35266aee900SScott Liu ts->fw_version != 0xffff) 35366aee900SScott Liu return 0; 35466aee900SScott Liu } 35566aee900SScott Liu 35666aee900SScott Liu dev_dbg(&client->dev, "read fw version error=%d, buf=%*phC\n", 35766aee900SScott Liu error, (int)sizeof(resp), resp); 35866aee900SScott Liu } 35966aee900SScott Liu 36066aee900SScott Liu dev_err(&client->dev, 36166aee900SScott Liu "Failed to read fw version or fw version is invalid\n"); 36266aee900SScott Liu 36366aee900SScott Liu return -EINVAL; 36466aee900SScott Liu } 36566aee900SScott Liu 36666aee900SScott Liu static int elants_i2c_query_test_version(struct elants_data *ts) 36766aee900SScott Liu { 36866aee900SScott Liu struct i2c_client *client = ts->client; 36966aee900SScott Liu int error, retry_cnt; 37066aee900SScott Liu u16 version; 37166aee900SScott Liu const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_TEST_VER, 0x00, 0x01 }; 37266aee900SScott Liu u8 resp[HEADER_SIZE]; 37366aee900SScott Liu 37466aee900SScott Liu for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { 37566aee900SScott Liu error = elants_i2c_execute_command(client, cmd, sizeof(cmd), 37666aee900SScott Liu resp, sizeof(resp)); 37766aee900SScott Liu if (!error) { 37866aee900SScott Liu version = elants_i2c_parse_version(resp); 37966aee900SScott Liu ts->test_version = version >> 8; 38066aee900SScott Liu ts->solution_version = version & 0xff; 38166aee900SScott Liu 38266aee900SScott Liu return 0; 38366aee900SScott Liu } 38466aee900SScott Liu 38566aee900SScott Liu dev_dbg(&client->dev, 38666aee900SScott Liu "read test version error rc=%d, buf=%*phC\n", 38766aee900SScott Liu error, (int)sizeof(resp), resp); 38866aee900SScott Liu } 38966aee900SScott Liu 39066aee900SScott Liu dev_err(&client->dev, "Failed to read test version\n"); 39166aee900SScott Liu 39266aee900SScott Liu return -EINVAL; 39366aee900SScott Liu } 39466aee900SScott Liu 39566aee900SScott Liu static int elants_i2c_query_bc_version(struct elants_data *ts) 39666aee900SScott Liu { 39766aee900SScott Liu struct i2c_client *client = ts->client; 39866aee900SScott Liu const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_BC_VER, 0x00, 0x01 }; 39966aee900SScott Liu u8 resp[HEADER_SIZE]; 40066aee900SScott Liu u16 version; 40166aee900SScott Liu int error; 40266aee900SScott Liu 40366aee900SScott Liu error = elants_i2c_execute_command(client, cmd, sizeof(cmd), 40466aee900SScott Liu resp, sizeof(resp)); 40566aee900SScott Liu if (error) { 40666aee900SScott Liu dev_err(&client->dev, 40766aee900SScott Liu "read BC version error=%d, buf=%*phC\n", 40866aee900SScott Liu error, (int)sizeof(resp), resp); 40966aee900SScott Liu return error; 41066aee900SScott Liu } 41166aee900SScott Liu 41266aee900SScott Liu version = elants_i2c_parse_version(resp); 41366aee900SScott Liu ts->bc_version = version >> 8; 41466aee900SScott Liu ts->iap_version = version & 0xff; 41566aee900SScott Liu 41666aee900SScott Liu return 0; 41766aee900SScott Liu } 41866aee900SScott Liu 41966aee900SScott Liu static int elants_i2c_query_ts_info(struct elants_data *ts) 42066aee900SScott Liu { 42166aee900SScott Liu struct i2c_client *client = ts->client; 42266aee900SScott Liu int error; 42366aee900SScott Liu u8 resp[17]; 42466aee900SScott Liu u16 phy_x, phy_y, rows, cols, osr; 42566aee900SScott Liu const u8 get_resolution_cmd[] = { 42666aee900SScott Liu CMD_HEADER_6B_READ, 0x00, 0x00, 0x00, 0x00, 0x00 42766aee900SScott Liu }; 42866aee900SScott Liu const u8 get_osr_cmd[] = { 42966aee900SScott Liu CMD_HEADER_READ, E_INFO_OSR, 0x00, 0x01 43066aee900SScott Liu }; 43166aee900SScott Liu const u8 get_physical_scan_cmd[] = { 43266aee900SScott Liu CMD_HEADER_READ, E_INFO_PHY_SCAN, 0x00, 0x01 43366aee900SScott Liu }; 43466aee900SScott Liu const u8 get_physical_drive_cmd[] = { 43566aee900SScott Liu CMD_HEADER_READ, E_INFO_PHY_DRIVER, 0x00, 0x01 43666aee900SScott Liu }; 43766aee900SScott Liu 43866aee900SScott Liu /* Get trace number */ 43966aee900SScott Liu error = elants_i2c_execute_command(client, 44066aee900SScott Liu get_resolution_cmd, 44166aee900SScott Liu sizeof(get_resolution_cmd), 44266aee900SScott Liu resp, sizeof(resp)); 44366aee900SScott Liu if (error) { 44466aee900SScott Liu dev_err(&client->dev, "get resolution command failed: %d\n", 44566aee900SScott Liu error); 44666aee900SScott Liu return error; 44766aee900SScott Liu } 44866aee900SScott Liu 44966aee900SScott Liu rows = resp[2] + resp[6] + resp[10]; 45066aee900SScott Liu cols = resp[3] + resp[7] + resp[11]; 45166aee900SScott Liu 45266aee900SScott Liu /* Process mm_to_pixel information */ 45366aee900SScott Liu error = elants_i2c_execute_command(client, 45466aee900SScott Liu get_osr_cmd, sizeof(get_osr_cmd), 45566aee900SScott Liu resp, sizeof(resp)); 45666aee900SScott Liu if (error) { 45766aee900SScott Liu dev_err(&client->dev, "get osr command failed: %d\n", 45866aee900SScott Liu error); 45966aee900SScott Liu return error; 46066aee900SScott Liu } 46166aee900SScott Liu 46266aee900SScott Liu osr = resp[3]; 46366aee900SScott Liu 46466aee900SScott Liu error = elants_i2c_execute_command(client, 46566aee900SScott Liu get_physical_scan_cmd, 46666aee900SScott Liu sizeof(get_physical_scan_cmd), 46766aee900SScott Liu resp, sizeof(resp)); 46866aee900SScott Liu if (error) { 46966aee900SScott Liu dev_err(&client->dev, "get physical scan command failed: %d\n", 47066aee900SScott Liu error); 47166aee900SScott Liu return error; 47266aee900SScott Liu } 47366aee900SScott Liu 47466aee900SScott Liu phy_x = get_unaligned_be16(&resp[2]); 47566aee900SScott Liu 47666aee900SScott Liu error = elants_i2c_execute_command(client, 47766aee900SScott Liu get_physical_drive_cmd, 47866aee900SScott Liu sizeof(get_physical_drive_cmd), 47966aee900SScott Liu resp, sizeof(resp)); 48066aee900SScott Liu if (error) { 48166aee900SScott Liu dev_err(&client->dev, "get physical drive command failed: %d\n", 48266aee900SScott Liu error); 48366aee900SScott Liu return error; 48466aee900SScott Liu } 48566aee900SScott Liu 48666aee900SScott Liu phy_y = get_unaligned_be16(&resp[2]); 48766aee900SScott Liu 48866aee900SScott Liu dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y); 48966aee900SScott Liu 49066aee900SScott Liu if (rows == 0 || cols == 0 || osr == 0) { 49166aee900SScott Liu dev_warn(&client->dev, 49266aee900SScott Liu "invalid trace number data: %d, %d, %d\n", 49366aee900SScott Liu rows, cols, osr); 49466aee900SScott Liu } else { 49566aee900SScott Liu /* translate trace number to TS resolution */ 49666aee900SScott Liu ts->x_max = ELAN_TS_RESOLUTION(rows, osr); 49766aee900SScott Liu ts->x_res = DIV_ROUND_CLOSEST(ts->x_max, phy_x); 49866aee900SScott Liu ts->y_max = ELAN_TS_RESOLUTION(cols, osr); 49966aee900SScott Liu ts->y_res = DIV_ROUND_CLOSEST(ts->y_max, phy_y); 50066aee900SScott Liu } 50166aee900SScott Liu 50266aee900SScott Liu return 0; 50366aee900SScott Liu } 50466aee900SScott Liu 50566aee900SScott Liu static int elants_i2c_fastboot(struct i2c_client *client) 50666aee900SScott Liu { 50766aee900SScott Liu const u8 boot_cmd[] = { 0x4D, 0x61, 0x69, 0x6E }; 50866aee900SScott Liu int error; 50966aee900SScott Liu 51066aee900SScott Liu error = elants_i2c_send(client, boot_cmd, sizeof(boot_cmd)); 51166aee900SScott Liu if (error) { 51266aee900SScott Liu dev_err(&client->dev, "boot failed: %d\n", error); 51366aee900SScott Liu return error; 51466aee900SScott Liu } 51566aee900SScott Liu 51666aee900SScott Liu dev_dbg(&client->dev, "boot success -- 0x%x\n", client->addr); 51766aee900SScott Liu return 0; 51866aee900SScott Liu } 51966aee900SScott Liu 52066aee900SScott Liu static int elants_i2c_initialize(struct elants_data *ts) 52166aee900SScott Liu { 52266aee900SScott Liu struct i2c_client *client = ts->client; 523bc1d57feSJohnny Chuang int error, error2, retry_cnt; 52466aee900SScott Liu const u8 hello_packet[] = { 0x55, 0x55, 0x55, 0x55 }; 52566aee900SScott Liu const u8 recov_packet[] = { 0x55, 0x55, 0x80, 0x80 }; 52666aee900SScott Liu u8 buf[HEADER_SIZE]; 52766aee900SScott Liu 52866aee900SScott Liu for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { 52966aee900SScott Liu error = elants_i2c_sw_reset(client); 53066aee900SScott Liu if (error) { 53166aee900SScott Liu /* Continue initializing if it's the last try */ 53266aee900SScott Liu if (retry_cnt < MAX_RETRIES - 1) 53366aee900SScott Liu continue; 53466aee900SScott Liu } 53566aee900SScott Liu 53666aee900SScott Liu error = elants_i2c_fastboot(client); 53766aee900SScott Liu if (error) { 53866aee900SScott Liu /* Continue initializing if it's the last try */ 53966aee900SScott Liu if (retry_cnt < MAX_RETRIES - 1) 54066aee900SScott Liu continue; 54166aee900SScott Liu } 54266aee900SScott Liu 54366aee900SScott Liu /* Wait for Hello packet */ 54466aee900SScott Liu msleep(BOOT_TIME_DELAY_MS); 54566aee900SScott Liu 54666aee900SScott Liu error = elants_i2c_read(client, buf, sizeof(buf)); 54766aee900SScott Liu if (error) { 54866aee900SScott Liu dev_err(&client->dev, 54966aee900SScott Liu "failed to read 'hello' packet: %d\n", error); 55066aee900SScott Liu } else if (!memcmp(buf, hello_packet, sizeof(hello_packet))) { 55166aee900SScott Liu ts->iap_mode = ELAN_IAP_OPERATIONAL; 55266aee900SScott Liu break; 55366aee900SScott Liu } else if (!memcmp(buf, recov_packet, sizeof(recov_packet))) { 55466aee900SScott Liu /* 55566aee900SScott Liu * Setting error code will mark device 55666aee900SScott Liu * in recovery mode below. 55766aee900SScott Liu */ 55866aee900SScott Liu error = -EIO; 55966aee900SScott Liu break; 56066aee900SScott Liu } else { 56166aee900SScott Liu error = -EINVAL; 56266aee900SScott Liu dev_err(&client->dev, 56366aee900SScott Liu "invalid 'hello' packet: %*ph\n", 56466aee900SScott Liu (int)sizeof(buf), buf); 56566aee900SScott Liu } 56666aee900SScott Liu } 56766aee900SScott Liu 568bc1d57feSJohnny Chuang /* hw version is available even if device in recovery state */ 569bc1d57feSJohnny Chuang error2 = elants_i2c_query_hw_version(ts); 570f0b57e19SJohnny.Chuang if (!error2) 571f0b57e19SJohnny.Chuang error2 = elants_i2c_query_bc_version(ts); 57266aee900SScott Liu if (!error) 573bc1d57feSJohnny Chuang error = error2; 574bc1d57feSJohnny Chuang 57566aee900SScott Liu if (!error) 57666aee900SScott Liu error = elants_i2c_query_fw_version(ts); 577bc1d57feSJohnny Chuang if (!error) 578bc1d57feSJohnny Chuang error = elants_i2c_query_test_version(ts); 579bc1d57feSJohnny Chuang if (!error) 580bc1d57feSJohnny Chuang error = elants_i2c_query_ts_info(ts); 58166aee900SScott Liu 582bc1d57feSJohnny Chuang if (error) 58366aee900SScott Liu ts->iap_mode = ELAN_IAP_RECOVERY; 58466aee900SScott Liu 58566aee900SScott Liu return 0; 58666aee900SScott Liu } 58766aee900SScott Liu 58866aee900SScott Liu /* 58966aee900SScott Liu * Firmware update interface. 59066aee900SScott Liu */ 59166aee900SScott Liu 59266aee900SScott Liu static int elants_i2c_fw_write_page(struct i2c_client *client, 59366aee900SScott Liu const void *page) 59466aee900SScott Liu { 59566aee900SScott Liu const u8 ack_ok[] = { 0xaa, 0xaa }; 59666aee900SScott Liu u8 buf[2]; 59766aee900SScott Liu int retry; 59866aee900SScott Liu int error; 59966aee900SScott Liu 60066aee900SScott Liu for (retry = 0; retry < MAX_FW_UPDATE_RETRIES; retry++) { 60166aee900SScott Liu error = elants_i2c_send(client, page, ELAN_FW_PAGESIZE); 60266aee900SScott Liu if (error) { 60366aee900SScott Liu dev_err(&client->dev, 60466aee900SScott Liu "IAP Write Page failed: %d\n", error); 60566aee900SScott Liu continue; 60666aee900SScott Liu } 60766aee900SScott Liu 60866aee900SScott Liu error = elants_i2c_read(client, buf, 2); 60966aee900SScott Liu if (error) { 61066aee900SScott Liu dev_err(&client->dev, 61166aee900SScott Liu "IAP Ack read failed: %d\n", error); 61266aee900SScott Liu return error; 61366aee900SScott Liu } 61466aee900SScott Liu 61566aee900SScott Liu if (!memcmp(buf, ack_ok, sizeof(ack_ok))) 61666aee900SScott Liu return 0; 61766aee900SScott Liu 61866aee900SScott Liu error = -EIO; 61966aee900SScott Liu dev_err(&client->dev, 62066aee900SScott Liu "IAP Get Ack Error [%02x:%02x]\n", 62166aee900SScott Liu buf[0], buf[1]); 62266aee900SScott Liu } 62366aee900SScott Liu 62466aee900SScott Liu return error; 62566aee900SScott Liu } 62666aee900SScott Liu 627f0b57e19SJohnny.Chuang static int elants_i2c_validate_remark_id(struct elants_data *ts, 628f0b57e19SJohnny.Chuang const struct firmware *fw) 629f0b57e19SJohnny.Chuang { 630f0b57e19SJohnny.Chuang struct i2c_client *client = ts->client; 631f0b57e19SJohnny.Chuang int error; 632f0b57e19SJohnny.Chuang const u8 cmd[] = { CMD_HEADER_ROM_READ, 0x80, 0x1F, 0x00, 0x00, 0x21 }; 633f0b57e19SJohnny.Chuang u8 resp[6] = { 0 }; 634f0b57e19SJohnny.Chuang u16 ts_remark_id = 0; 635f0b57e19SJohnny.Chuang u16 fw_remark_id = 0; 636f0b57e19SJohnny.Chuang 637f0b57e19SJohnny.Chuang /* Compare TS Remark ID and FW Remark ID */ 638f0b57e19SJohnny.Chuang error = elants_i2c_execute_command(client, cmd, sizeof(cmd), 639f0b57e19SJohnny.Chuang resp, sizeof(resp)); 640f0b57e19SJohnny.Chuang if (error) { 641f0b57e19SJohnny.Chuang dev_err(&client->dev, "failed to query Remark ID: %d\n", error); 642f0b57e19SJohnny.Chuang return error; 643f0b57e19SJohnny.Chuang } 644f0b57e19SJohnny.Chuang 645f0b57e19SJohnny.Chuang ts_remark_id = get_unaligned_be16(&resp[3]); 646f0b57e19SJohnny.Chuang 647f0b57e19SJohnny.Chuang fw_remark_id = get_unaligned_le16(&fw->data[fw->size - 4]); 648f0b57e19SJohnny.Chuang 649f0b57e19SJohnny.Chuang if (fw_remark_id != ts_remark_id) { 650f0b57e19SJohnny.Chuang dev_err(&client->dev, 651f0b57e19SJohnny.Chuang "Remark ID Mismatched: ts_remark_id=0x%04x, fw_remark_id=0x%04x.\n", 652f0b57e19SJohnny.Chuang ts_remark_id, fw_remark_id); 653f0b57e19SJohnny.Chuang return -EINVAL; 654f0b57e19SJohnny.Chuang } 655f0b57e19SJohnny.Chuang 656f0b57e19SJohnny.Chuang return 0; 657f0b57e19SJohnny.Chuang } 658f0b57e19SJohnny.Chuang 65966aee900SScott Liu static int elants_i2c_do_update_firmware(struct i2c_client *client, 66066aee900SScott Liu const struct firmware *fw, 66166aee900SScott Liu bool force) 66266aee900SScott Liu { 663f0b57e19SJohnny.Chuang struct elants_data *ts = i2c_get_clientdata(client); 66466aee900SScott Liu const u8 enter_iap[] = { 0x45, 0x49, 0x41, 0x50 }; 66566aee900SScott Liu const u8 enter_iap2[] = { 0x54, 0x00, 0x12, 0x34 }; 66666aee900SScott Liu const u8 iap_ack[] = { 0x55, 0xaa, 0x33, 0xcc }; 6676fd38502SJames Chen const u8 close_idle[] = { 0x54, 0x2c, 0x01, 0x01 }; 66866aee900SScott Liu u8 buf[HEADER_SIZE]; 66966aee900SScott Liu u16 send_id; 67066aee900SScott Liu int page, n_fw_pages; 67166aee900SScott Liu int error; 672f0b57e19SJohnny.Chuang bool check_remark_id = ts->iap_version >= 0x60; 67366aee900SScott Liu 67466aee900SScott Liu /* Recovery mode detection! */ 67566aee900SScott Liu if (force) { 67666aee900SScott Liu dev_dbg(&client->dev, "Recovery mode procedure\n"); 677f0b57e19SJohnny.Chuang 678f0b57e19SJohnny.Chuang if (check_remark_id) { 679f0b57e19SJohnny.Chuang error = elants_i2c_validate_remark_id(ts, fw); 680f0b57e19SJohnny.Chuang if (error) 681f0b57e19SJohnny.Chuang return error; 682f0b57e19SJohnny.Chuang } 683f0b57e19SJohnny.Chuang 68466aee900SScott Liu error = elants_i2c_send(client, enter_iap2, sizeof(enter_iap2)); 685f0b57e19SJohnny.Chuang if (error) { 686f0b57e19SJohnny.Chuang dev_err(&client->dev, "failed to enter IAP mode: %d\n", 687f0b57e19SJohnny.Chuang error); 688f0b57e19SJohnny.Chuang return error; 689f0b57e19SJohnny.Chuang } 69066aee900SScott Liu } else { 69166aee900SScott Liu /* Start IAP Procedure */ 69266aee900SScott Liu dev_dbg(&client->dev, "Normal IAP procedure\n"); 693f0b57e19SJohnny.Chuang 6946fd38502SJames Chen /* Close idle mode */ 6956fd38502SJames Chen error = elants_i2c_send(client, close_idle, sizeof(close_idle)); 6966fd38502SJames Chen if (error) 6976fd38502SJames Chen dev_err(&client->dev, "Failed close idle: %d\n", error); 6986fd38502SJames Chen msleep(60); 699f0b57e19SJohnny.Chuang 70066aee900SScott Liu elants_i2c_sw_reset(client); 7016fd38502SJames Chen msleep(20); 702f0b57e19SJohnny.Chuang 703f0b57e19SJohnny.Chuang if (check_remark_id) { 704f0b57e19SJohnny.Chuang error = elants_i2c_validate_remark_id(ts, fw); 705f0b57e19SJohnny.Chuang if (error) 706f0b57e19SJohnny.Chuang return error; 70766aee900SScott Liu } 70866aee900SScott Liu 709f0b57e19SJohnny.Chuang error = elants_i2c_send(client, enter_iap, sizeof(enter_iap)); 71066aee900SScott Liu if (error) { 711f0b57e19SJohnny.Chuang dev_err(&client->dev, "failed to enter IAP mode: %d\n", 712f0b57e19SJohnny.Chuang error); 71366aee900SScott Liu return error; 71466aee900SScott Liu } 715f0b57e19SJohnny.Chuang } 71666aee900SScott Liu 71766aee900SScott Liu msleep(20); 71866aee900SScott Liu 71966aee900SScott Liu /* check IAP state */ 72066aee900SScott Liu error = elants_i2c_read(client, buf, 4); 72166aee900SScott Liu if (error) { 72266aee900SScott Liu dev_err(&client->dev, 72366aee900SScott Liu "failed to read IAP acknowledgement: %d\n", 72466aee900SScott Liu error); 72566aee900SScott Liu return error; 72666aee900SScott Liu } 72766aee900SScott Liu 72866aee900SScott Liu if (memcmp(buf, iap_ack, sizeof(iap_ack))) { 72966aee900SScott Liu dev_err(&client->dev, 73066aee900SScott Liu "failed to enter IAP: %*ph (expected %*ph)\n", 73166aee900SScott Liu (int)sizeof(buf), buf, (int)sizeof(iap_ack), iap_ack); 73266aee900SScott Liu return -EIO; 73366aee900SScott Liu } 73466aee900SScott Liu 73566aee900SScott Liu dev_info(&client->dev, "successfully entered IAP mode"); 73666aee900SScott Liu 73766aee900SScott Liu send_id = client->addr; 73866aee900SScott Liu error = elants_i2c_send(client, &send_id, 1); 73966aee900SScott Liu if (error) { 74066aee900SScott Liu dev_err(&client->dev, "sending dummy byte failed: %d\n", 74166aee900SScott Liu error); 74266aee900SScott Liu return error; 74366aee900SScott Liu } 74466aee900SScott Liu 74566aee900SScott Liu /* Clear the last page of Master */ 74666aee900SScott Liu error = elants_i2c_send(client, fw->data, ELAN_FW_PAGESIZE); 74766aee900SScott Liu if (error) { 74866aee900SScott Liu dev_err(&client->dev, "clearing of the last page failed: %d\n", 74966aee900SScott Liu error); 75066aee900SScott Liu return error; 75166aee900SScott Liu } 75266aee900SScott Liu 75366aee900SScott Liu error = elants_i2c_read(client, buf, 2); 75466aee900SScott Liu if (error) { 75566aee900SScott Liu dev_err(&client->dev, 75666aee900SScott Liu "failed to read ACK for clearing the last page: %d\n", 75766aee900SScott Liu error); 75866aee900SScott Liu return error; 75966aee900SScott Liu } 76066aee900SScott Liu 76166aee900SScott Liu n_fw_pages = fw->size / ELAN_FW_PAGESIZE; 76266aee900SScott Liu dev_dbg(&client->dev, "IAP Pages = %d\n", n_fw_pages); 76366aee900SScott Liu 76466aee900SScott Liu for (page = 0; page < n_fw_pages; page++) { 76566aee900SScott Liu error = elants_i2c_fw_write_page(client, 76666aee900SScott Liu fw->data + page * ELAN_FW_PAGESIZE); 76766aee900SScott Liu if (error) { 76866aee900SScott Liu dev_err(&client->dev, 76966aee900SScott Liu "failed to write FW page %d: %d\n", 77066aee900SScott Liu page, error); 77166aee900SScott Liu return error; 77266aee900SScott Liu } 77366aee900SScott Liu } 77466aee900SScott Liu 77566aee900SScott Liu /* Old iap needs to wait 200ms for WDT and rest is for hello packets */ 77666aee900SScott Liu msleep(300); 77766aee900SScott Liu 77866aee900SScott Liu dev_info(&client->dev, "firmware update completed\n"); 77966aee900SScott Liu return 0; 78066aee900SScott Liu } 78166aee900SScott Liu 78266aee900SScott Liu static int elants_i2c_fw_update(struct elants_data *ts) 78366aee900SScott Liu { 78466aee900SScott Liu struct i2c_client *client = ts->client; 78566aee900SScott Liu const struct firmware *fw; 78637dee1acSCharlie Mooney char *fw_name; 78766aee900SScott Liu int error; 78866aee900SScott Liu 7898c0776a8SDmitry Torokhov fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version); 79037dee1acSCharlie Mooney if (!fw_name) 79137dee1acSCharlie Mooney return -ENOMEM; 79237dee1acSCharlie Mooney 79337dee1acSCharlie Mooney dev_info(&client->dev, "requesting fw name = %s\n", fw_name); 79437dee1acSCharlie Mooney error = request_firmware(&fw, fw_name, &client->dev); 79537dee1acSCharlie Mooney kfree(fw_name); 79666aee900SScott Liu if (error) { 79737dee1acSCharlie Mooney dev_err(&client->dev, "failed to request firmware: %d\n", 79837dee1acSCharlie Mooney error); 79966aee900SScott Liu return error; 80066aee900SScott Liu } 80166aee900SScott Liu 80266aee900SScott Liu if (fw->size % ELAN_FW_PAGESIZE) { 80366aee900SScott Liu dev_err(&client->dev, "invalid firmware length: %zu\n", 80466aee900SScott Liu fw->size); 80566aee900SScott Liu error = -EINVAL; 80666aee900SScott Liu goto out; 80766aee900SScott Liu } 80866aee900SScott Liu 80966aee900SScott Liu disable_irq(client->irq); 81066aee900SScott Liu 81166aee900SScott Liu error = elants_i2c_do_update_firmware(client, fw, 81266aee900SScott Liu ts->iap_mode == ELAN_IAP_RECOVERY); 81366aee900SScott Liu if (error) { 81466aee900SScott Liu dev_err(&client->dev, "firmware update failed: %d\n", error); 81566aee900SScott Liu ts->iap_mode = ELAN_IAP_RECOVERY; 81666aee900SScott Liu goto out_enable_irq; 81766aee900SScott Liu } 81866aee900SScott Liu 81966aee900SScott Liu error = elants_i2c_initialize(ts); 82066aee900SScott Liu if (error) { 82166aee900SScott Liu dev_err(&client->dev, 82266aee900SScott Liu "failed to initialize device after firmware update: %d\n", 82366aee900SScott Liu error); 82466aee900SScott Liu ts->iap_mode = ELAN_IAP_RECOVERY; 82566aee900SScott Liu goto out_enable_irq; 82666aee900SScott Liu } 82766aee900SScott Liu 82866aee900SScott Liu ts->iap_mode = ELAN_IAP_OPERATIONAL; 82966aee900SScott Liu 83066aee900SScott Liu out_enable_irq: 83166aee900SScott Liu ts->state = ELAN_STATE_NORMAL; 83266aee900SScott Liu enable_irq(client->irq); 83366aee900SScott Liu msleep(100); 83466aee900SScott Liu 83566aee900SScott Liu if (!error) 83666aee900SScott Liu elants_i2c_calibrate(ts); 83766aee900SScott Liu out: 83866aee900SScott Liu release_firmware(fw); 83966aee900SScott Liu return error; 84066aee900SScott Liu } 84166aee900SScott Liu 84266aee900SScott Liu /* 84366aee900SScott Liu * Event reporting. 84466aee900SScott Liu */ 84566aee900SScott Liu 84666aee900SScott Liu static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf) 84766aee900SScott Liu { 84866aee900SScott Liu struct input_dev *input = ts->input; 84966aee900SScott Liu unsigned int n_fingers; 850f27ad893SJohnny Chuang unsigned int tool_type; 85166aee900SScott Liu u16 finger_state; 85266aee900SScott Liu int i; 85366aee900SScott Liu 85466aee900SScott Liu n_fingers = buf[FW_POS_STATE + 1] & 0x0f; 85566aee900SScott Liu finger_state = ((buf[FW_POS_STATE + 1] & 0x30) << 4) | 85666aee900SScott Liu buf[FW_POS_STATE]; 85766aee900SScott Liu 85866aee900SScott Liu dev_dbg(&ts->client->dev, 85966aee900SScott Liu "n_fingers: %u, state: %04x\n", n_fingers, finger_state); 86066aee900SScott Liu 861f27ad893SJohnny Chuang /* Note: all fingers have the same tool type */ 862f27ad893SJohnny Chuang tool_type = buf[FW_POS_TOOL_TYPE] & BIT(0) ? 863f27ad893SJohnny Chuang MT_TOOL_FINGER : MT_TOOL_PALM; 864f27ad893SJohnny Chuang 86566aee900SScott Liu for (i = 0; i < MAX_CONTACT_NUM && n_fingers; i++) { 86666aee900SScott Liu if (finger_state & 1) { 86766aee900SScott Liu unsigned int x, y, p, w; 86866aee900SScott Liu u8 *pos; 86966aee900SScott Liu 87066aee900SScott Liu pos = &buf[FW_POS_XY + i * 3]; 87166aee900SScott Liu x = (((u16)pos[0] & 0xf0) << 4) | pos[1]; 87266aee900SScott Liu y = (((u16)pos[0] & 0x0f) << 8) | pos[2]; 87366aee900SScott Liu p = buf[FW_POS_PRESSURE + i]; 87466aee900SScott Liu w = buf[FW_POS_WIDTH + i]; 87566aee900SScott Liu 87666aee900SScott Liu dev_dbg(&ts->client->dev, "i=%d x=%d y=%d p=%d w=%d\n", 87766aee900SScott Liu i, x, y, p, w); 87866aee900SScott Liu 87966aee900SScott Liu input_mt_slot(input, i); 880f27ad893SJohnny Chuang input_mt_report_slot_state(input, tool_type, true); 88168334dbaSMichał Mirosław touchscreen_report_pos(input, &ts->prop, x, y, true); 88266aee900SScott Liu input_event(input, EV_ABS, ABS_MT_PRESSURE, p); 88366aee900SScott Liu input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, w); 88466aee900SScott Liu 88566aee900SScott Liu n_fingers--; 88666aee900SScott Liu } 88766aee900SScott Liu 88866aee900SScott Liu finger_state >>= 1; 88966aee900SScott Liu } 89066aee900SScott Liu 89166aee900SScott Liu input_mt_sync_frame(input); 89266aee900SScott Liu input_sync(input); 89366aee900SScott Liu } 89466aee900SScott Liu 89566aee900SScott Liu static u8 elants_i2c_calculate_checksum(u8 *buf) 89666aee900SScott Liu { 89766aee900SScott Liu u8 checksum = 0; 89866aee900SScott Liu u8 i; 89966aee900SScott Liu 90066aee900SScott Liu for (i = 0; i < FW_POS_CHECKSUM; i++) 90166aee900SScott Liu checksum += buf[i]; 90266aee900SScott Liu 90366aee900SScott Liu return checksum; 90466aee900SScott Liu } 90566aee900SScott Liu 90666aee900SScott Liu static void elants_i2c_event(struct elants_data *ts, u8 *buf) 90766aee900SScott Liu { 90866aee900SScott Liu u8 checksum = elants_i2c_calculate_checksum(buf); 90966aee900SScott Liu 91066aee900SScott Liu if (unlikely(buf[FW_POS_CHECKSUM] != checksum)) 91166aee900SScott Liu dev_warn(&ts->client->dev, 91266aee900SScott Liu "%s: invalid checksum for packet %02x: %02x vs. %02x\n", 91366aee900SScott Liu __func__, buf[FW_POS_HEADER], 91466aee900SScott Liu checksum, buf[FW_POS_CHECKSUM]); 91566aee900SScott Liu else if (unlikely(buf[FW_POS_HEADER] != HEADER_REPORT_10_FINGER)) 91666aee900SScott Liu dev_warn(&ts->client->dev, 91766aee900SScott Liu "%s: unknown packet type: %02x\n", 91866aee900SScott Liu __func__, buf[FW_POS_HEADER]); 91966aee900SScott Liu else 92066aee900SScott Liu elants_i2c_mt_event(ts, buf); 92166aee900SScott Liu } 92266aee900SScott Liu 92366aee900SScott Liu static irqreturn_t elants_i2c_irq(int irq, void *_dev) 92466aee900SScott Liu { 92566aee900SScott Liu const u8 wait_packet[] = { 0x64, 0x64, 0x64, 0x64 }; 92666aee900SScott Liu struct elants_data *ts = _dev; 92766aee900SScott Liu struct i2c_client *client = ts->client; 92866aee900SScott Liu int report_count, report_len; 92966aee900SScott Liu int i; 93066aee900SScott Liu int len; 93166aee900SScott Liu 93200f73f97SStephen Boyd len = i2c_master_recv_dmasafe(client, ts->buf, sizeof(ts->buf)); 93366aee900SScott Liu if (len < 0) { 93466aee900SScott Liu dev_err(&client->dev, "%s: failed to read data: %d\n", 93566aee900SScott Liu __func__, len); 93666aee900SScott Liu goto out; 93766aee900SScott Liu } 93866aee900SScott Liu 93966aee900SScott Liu dev_dbg(&client->dev, "%s: packet %*ph\n", 94066aee900SScott Liu __func__, HEADER_SIZE, ts->buf); 94166aee900SScott Liu 94266aee900SScott Liu switch (ts->state) { 94366aee900SScott Liu case ELAN_WAIT_RECALIBRATION: 94466aee900SScott Liu if (ts->buf[FW_HDR_TYPE] == CMD_HEADER_REK) { 94566aee900SScott Liu memcpy(ts->cmd_resp, ts->buf, sizeof(ts->cmd_resp)); 94666aee900SScott Liu complete(&ts->cmd_done); 94766aee900SScott Liu ts->state = ELAN_STATE_NORMAL; 94866aee900SScott Liu } 94966aee900SScott Liu break; 95066aee900SScott Liu 95166aee900SScott Liu case ELAN_WAIT_QUEUE_HEADER: 95266aee900SScott Liu if (ts->buf[FW_HDR_TYPE] != QUEUE_HEADER_NORMAL) 95366aee900SScott Liu break; 95466aee900SScott Liu 95566aee900SScott Liu ts->state = ELAN_STATE_NORMAL; 95666aee900SScott Liu /* fall through */ 95766aee900SScott Liu 95866aee900SScott Liu case ELAN_STATE_NORMAL: 95966aee900SScott Liu 96066aee900SScott Liu switch (ts->buf[FW_HDR_TYPE]) { 96166aee900SScott Liu case CMD_HEADER_HELLO: 96266aee900SScott Liu case CMD_HEADER_RESP: 96366aee900SScott Liu case CMD_HEADER_REK: 96466aee900SScott Liu break; 96566aee900SScott Liu 96666aee900SScott Liu case QUEUE_HEADER_WAIT: 96766aee900SScott Liu if (memcmp(ts->buf, wait_packet, sizeof(wait_packet))) { 96866aee900SScott Liu dev_err(&client->dev, 96966aee900SScott Liu "invalid wait packet %*ph\n", 97066aee900SScott Liu HEADER_SIZE, ts->buf); 97166aee900SScott Liu } else { 97266aee900SScott Liu ts->state = ELAN_WAIT_QUEUE_HEADER; 97366aee900SScott Liu udelay(30); 97466aee900SScott Liu } 97566aee900SScott Liu break; 97666aee900SScott Liu 97766aee900SScott Liu case QUEUE_HEADER_SINGLE: 97866aee900SScott Liu elants_i2c_event(ts, &ts->buf[HEADER_SIZE]); 97966aee900SScott Liu break; 98066aee900SScott Liu 98166aee900SScott Liu case QUEUE_HEADER_NORMAL: 98266aee900SScott Liu report_count = ts->buf[FW_HDR_COUNT]; 9831c3415a0SGuenter Roeck if (report_count == 0 || report_count > 3) { 98466aee900SScott Liu dev_err(&client->dev, 9851c3415a0SGuenter Roeck "bad report count: %*ph\n", 98666aee900SScott Liu HEADER_SIZE, ts->buf); 98766aee900SScott Liu break; 98866aee900SScott Liu } 98966aee900SScott Liu 99066aee900SScott Liu report_len = ts->buf[FW_HDR_LENGTH] / report_count; 99166aee900SScott Liu if (report_len != PACKET_SIZE) { 99266aee900SScott Liu dev_err(&client->dev, 99366aee900SScott Liu "mismatching report length: %*ph\n", 99466aee900SScott Liu HEADER_SIZE, ts->buf); 99566aee900SScott Liu break; 99666aee900SScott Liu } 99766aee900SScott Liu 99866aee900SScott Liu for (i = 0; i < report_count; i++) { 99966aee900SScott Liu u8 *buf = ts->buf + HEADER_SIZE + 100066aee900SScott Liu i * PACKET_SIZE; 100166aee900SScott Liu elants_i2c_event(ts, buf); 100266aee900SScott Liu } 100366aee900SScott Liu break; 100466aee900SScott Liu 100566aee900SScott Liu default: 100666aee900SScott Liu dev_err(&client->dev, "unknown packet %*ph\n", 100766aee900SScott Liu HEADER_SIZE, ts->buf); 100866aee900SScott Liu break; 100966aee900SScott Liu } 101066aee900SScott Liu break; 101166aee900SScott Liu } 101266aee900SScott Liu 101366aee900SScott Liu out: 101466aee900SScott Liu return IRQ_HANDLED; 101566aee900SScott Liu } 101666aee900SScott Liu 101766aee900SScott Liu /* 101866aee900SScott Liu * sysfs interface 101966aee900SScott Liu */ 102066aee900SScott Liu static ssize_t calibrate_store(struct device *dev, 102166aee900SScott Liu struct device_attribute *attr, 102266aee900SScott Liu const char *buf, size_t count) 102366aee900SScott Liu { 102466aee900SScott Liu struct i2c_client *client = to_i2c_client(dev); 102566aee900SScott Liu struct elants_data *ts = i2c_get_clientdata(client); 102666aee900SScott Liu int error; 102766aee900SScott Liu 102866aee900SScott Liu error = mutex_lock_interruptible(&ts->sysfs_mutex); 102966aee900SScott Liu if (error) 103066aee900SScott Liu return error; 103166aee900SScott Liu 103266aee900SScott Liu error = elants_i2c_calibrate(ts); 103366aee900SScott Liu 103466aee900SScott Liu mutex_unlock(&ts->sysfs_mutex); 103566aee900SScott Liu return error ?: count; 103666aee900SScott Liu } 103766aee900SScott Liu 103866aee900SScott Liu static ssize_t write_update_fw(struct device *dev, 103966aee900SScott Liu struct device_attribute *attr, 104066aee900SScott Liu const char *buf, size_t count) 104166aee900SScott Liu { 104266aee900SScott Liu struct i2c_client *client = to_i2c_client(dev); 104366aee900SScott Liu struct elants_data *ts = i2c_get_clientdata(client); 104466aee900SScott Liu int error; 104566aee900SScott Liu 104666aee900SScott Liu error = mutex_lock_interruptible(&ts->sysfs_mutex); 104766aee900SScott Liu if (error) 104866aee900SScott Liu return error; 104966aee900SScott Liu 105066aee900SScott Liu error = elants_i2c_fw_update(ts); 105166aee900SScott Liu dev_dbg(dev, "firmware update result: %d\n", error); 105266aee900SScott Liu 105366aee900SScott Liu mutex_unlock(&ts->sysfs_mutex); 105466aee900SScott Liu return error ?: count; 105566aee900SScott Liu } 105666aee900SScott Liu 105766aee900SScott Liu static ssize_t show_iap_mode(struct device *dev, 105866aee900SScott Liu struct device_attribute *attr, char *buf) 105966aee900SScott Liu { 106066aee900SScott Liu struct i2c_client *client = to_i2c_client(dev); 106166aee900SScott Liu struct elants_data *ts = i2c_get_clientdata(client); 106266aee900SScott Liu 106366aee900SScott Liu return sprintf(buf, "%s\n", 106466aee900SScott Liu ts->iap_mode == ELAN_IAP_OPERATIONAL ? 106566aee900SScott Liu "Normal" : "Recovery"); 106666aee900SScott Liu } 106766aee900SScott Liu 1068cf520c64SJohnny Chuang static ssize_t show_calibration_count(struct device *dev, 1069cf520c64SJohnny Chuang struct device_attribute *attr, char *buf) 1070cf520c64SJohnny Chuang { 1071cf520c64SJohnny Chuang struct i2c_client *client = to_i2c_client(dev); 1072cf520c64SJohnny Chuang const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_REK, 0x00, 0x01 }; 1073cf520c64SJohnny Chuang u8 resp[HEADER_SIZE]; 1074cf520c64SJohnny Chuang u16 rek_count; 1075cf520c64SJohnny Chuang int error; 1076cf520c64SJohnny Chuang 1077cf520c64SJohnny Chuang error = elants_i2c_execute_command(client, cmd, sizeof(cmd), 1078cf520c64SJohnny Chuang resp, sizeof(resp)); 1079cf520c64SJohnny Chuang if (error) { 1080cf520c64SJohnny Chuang dev_err(&client->dev, 1081cf520c64SJohnny Chuang "read ReK status error=%d, buf=%*phC\n", 1082cf520c64SJohnny Chuang error, (int)sizeof(resp), resp); 1083cf520c64SJohnny Chuang return sprintf(buf, "%d\n", error); 1084cf520c64SJohnny Chuang } 1085cf520c64SJohnny Chuang 1086cf520c64SJohnny Chuang rek_count = get_unaligned_be16(&resp[2]); 1087cf520c64SJohnny Chuang 1088cf520c64SJohnny Chuang return sprintf(buf, "0x%04x\n", rek_count); 1089cf520c64SJohnny Chuang } 1090cf520c64SJohnny Chuang 10916cbaefb4SJoe Perches static DEVICE_ATTR_WO(calibrate); 109266aee900SScott Liu static DEVICE_ATTR(iap_mode, S_IRUGO, show_iap_mode, NULL); 1093cf520c64SJohnny Chuang static DEVICE_ATTR(calibration_count, S_IRUGO, show_calibration_count, NULL); 109466aee900SScott Liu static DEVICE_ATTR(update_fw, S_IWUSR, NULL, write_update_fw); 109566aee900SScott Liu 109666aee900SScott Liu struct elants_version_attribute { 109766aee900SScott Liu struct device_attribute dattr; 109866aee900SScott Liu size_t field_offset; 109966aee900SScott Liu size_t field_size; 110066aee900SScott Liu }; 110166aee900SScott Liu 110266aee900SScott Liu #define __ELANTS_FIELD_SIZE(_field) \ 110366aee900SScott Liu sizeof(((struct elants_data *)NULL)->_field) 110466aee900SScott Liu #define __ELANTS_VERIFY_SIZE(_field) \ 110566aee900SScott Liu (BUILD_BUG_ON_ZERO(__ELANTS_FIELD_SIZE(_field) > 2) + \ 110666aee900SScott Liu __ELANTS_FIELD_SIZE(_field)) 110766aee900SScott Liu #define ELANTS_VERSION_ATTR(_field) \ 110866aee900SScott Liu struct elants_version_attribute elants_ver_attr_##_field = { \ 110966aee900SScott Liu .dattr = __ATTR(_field, S_IRUGO, \ 111066aee900SScott Liu elants_version_attribute_show, NULL), \ 111166aee900SScott Liu .field_offset = offsetof(struct elants_data, _field), \ 111266aee900SScott Liu .field_size = __ELANTS_VERIFY_SIZE(_field), \ 111366aee900SScott Liu } 111466aee900SScott Liu 111566aee900SScott Liu static ssize_t elants_version_attribute_show(struct device *dev, 111666aee900SScott Liu struct device_attribute *dattr, 111766aee900SScott Liu char *buf) 111866aee900SScott Liu { 111966aee900SScott Liu struct i2c_client *client = to_i2c_client(dev); 112066aee900SScott Liu struct elants_data *ts = i2c_get_clientdata(client); 112166aee900SScott Liu struct elants_version_attribute *attr = 112266aee900SScott Liu container_of(dattr, struct elants_version_attribute, dattr); 112366aee900SScott Liu u8 *field = (u8 *)((char *)ts + attr->field_offset); 112466aee900SScott Liu unsigned int fmt_size; 112566aee900SScott Liu unsigned int val; 112666aee900SScott Liu 112766aee900SScott Liu if (attr->field_size == 1) { 112866aee900SScott Liu val = *field; 112966aee900SScott Liu fmt_size = 2; /* 2 HEX digits */ 113066aee900SScott Liu } else { 113166aee900SScott Liu val = *(u16 *)field; 113266aee900SScott Liu fmt_size = 4; /* 4 HEX digits */ 113366aee900SScott Liu } 113466aee900SScott Liu 113566aee900SScott Liu return sprintf(buf, "%0*x\n", fmt_size, val); 113666aee900SScott Liu } 113766aee900SScott Liu 113866aee900SScott Liu static ELANTS_VERSION_ATTR(fw_version); 113966aee900SScott Liu static ELANTS_VERSION_ATTR(hw_version); 114066aee900SScott Liu static ELANTS_VERSION_ATTR(test_version); 114166aee900SScott Liu static ELANTS_VERSION_ATTR(solution_version); 114266aee900SScott Liu static ELANTS_VERSION_ATTR(bc_version); 114366aee900SScott Liu static ELANTS_VERSION_ATTR(iap_version); 114466aee900SScott Liu 114566aee900SScott Liu static struct attribute *elants_attributes[] = { 114666aee900SScott Liu &dev_attr_calibrate.attr, 114766aee900SScott Liu &dev_attr_update_fw.attr, 114866aee900SScott Liu &dev_attr_iap_mode.attr, 1149cf520c64SJohnny Chuang &dev_attr_calibration_count.attr, 115066aee900SScott Liu 115166aee900SScott Liu &elants_ver_attr_fw_version.dattr.attr, 115266aee900SScott Liu &elants_ver_attr_hw_version.dattr.attr, 115366aee900SScott Liu &elants_ver_attr_test_version.dattr.attr, 115466aee900SScott Liu &elants_ver_attr_solution_version.dattr.attr, 115566aee900SScott Liu &elants_ver_attr_bc_version.dattr.attr, 115666aee900SScott Liu &elants_ver_attr_iap_version.dattr.attr, 115766aee900SScott Liu NULL 115866aee900SScott Liu }; 115966aee900SScott Liu 116048f960ddSArvind Yadav static const struct attribute_group elants_attribute_group = { 116166aee900SScott Liu .attrs = elants_attributes, 116266aee900SScott Liu }; 116366aee900SScott Liu 1164afe10358SDmitry Torokhov static int elants_i2c_power_on(struct elants_data *ts) 1165afe10358SDmitry Torokhov { 1166afe10358SDmitry Torokhov int error; 1167afe10358SDmitry Torokhov 1168afe10358SDmitry Torokhov /* 1169afe10358SDmitry Torokhov * If we do not have reset gpio assume platform firmware 1170afe10358SDmitry Torokhov * controls regulators and does power them on for us. 1171afe10358SDmitry Torokhov */ 1172afe10358SDmitry Torokhov if (IS_ERR_OR_NULL(ts->reset_gpio)) 1173afe10358SDmitry Torokhov return 0; 1174afe10358SDmitry Torokhov 1175afe10358SDmitry Torokhov gpiod_set_value_cansleep(ts->reset_gpio, 1); 1176afe10358SDmitry Torokhov 1177afe10358SDmitry Torokhov error = regulator_enable(ts->vcc33); 1178afe10358SDmitry Torokhov if (error) { 1179afe10358SDmitry Torokhov dev_err(&ts->client->dev, 1180afe10358SDmitry Torokhov "failed to enable vcc33 regulator: %d\n", 1181afe10358SDmitry Torokhov error); 1182afe10358SDmitry Torokhov goto release_reset_gpio; 1183afe10358SDmitry Torokhov } 1184afe10358SDmitry Torokhov 1185afe10358SDmitry Torokhov error = regulator_enable(ts->vccio); 1186afe10358SDmitry Torokhov if (error) { 1187afe10358SDmitry Torokhov dev_err(&ts->client->dev, 1188afe10358SDmitry Torokhov "failed to enable vccio regulator: %d\n", 1189afe10358SDmitry Torokhov error); 1190afe10358SDmitry Torokhov regulator_disable(ts->vcc33); 1191afe10358SDmitry Torokhov goto release_reset_gpio; 1192afe10358SDmitry Torokhov } 1193afe10358SDmitry Torokhov 1194afe10358SDmitry Torokhov /* 1195afe10358SDmitry Torokhov * We need to wait a bit after powering on controller before 1196afe10358SDmitry Torokhov * we are allowed to release reset GPIO. 1197afe10358SDmitry Torokhov */ 1198afe10358SDmitry Torokhov udelay(ELAN_POWERON_DELAY_USEC); 1199afe10358SDmitry Torokhov 1200afe10358SDmitry Torokhov release_reset_gpio: 1201afe10358SDmitry Torokhov gpiod_set_value_cansleep(ts->reset_gpio, 0); 1202afe10358SDmitry Torokhov if (error) 1203afe10358SDmitry Torokhov return error; 1204afe10358SDmitry Torokhov 1205afe10358SDmitry Torokhov msleep(ELAN_RESET_DELAY_MSEC); 1206afe10358SDmitry Torokhov 1207afe10358SDmitry Torokhov return 0; 1208afe10358SDmitry Torokhov } 1209afe10358SDmitry Torokhov 1210afe10358SDmitry Torokhov static void elants_i2c_power_off(void *_data) 1211afe10358SDmitry Torokhov { 1212afe10358SDmitry Torokhov struct elants_data *ts = _data; 1213afe10358SDmitry Torokhov 1214afe10358SDmitry Torokhov if (!IS_ERR_OR_NULL(ts->reset_gpio)) { 1215afe10358SDmitry Torokhov /* 1216afe10358SDmitry Torokhov * Activate reset gpio to prevent leakage through the 1217afe10358SDmitry Torokhov * pin once we shut off power to the controller. 1218afe10358SDmitry Torokhov */ 1219afe10358SDmitry Torokhov gpiod_set_value_cansleep(ts->reset_gpio, 1); 1220afe10358SDmitry Torokhov regulator_disable(ts->vccio); 1221afe10358SDmitry Torokhov regulator_disable(ts->vcc33); 1222afe10358SDmitry Torokhov } 1223afe10358SDmitry Torokhov } 1224afe10358SDmitry Torokhov 122566aee900SScott Liu static int elants_i2c_probe(struct i2c_client *client, 122666aee900SScott Liu const struct i2c_device_id *id) 122766aee900SScott Liu { 122866aee900SScott Liu union i2c_smbus_data dummy; 122966aee900SScott Liu struct elants_data *ts; 123066aee900SScott Liu unsigned long irqflags; 123166aee900SScott Liu int error; 123266aee900SScott Liu 123366aee900SScott Liu if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 123466aee900SScott Liu dev_err(&client->dev, 123566aee900SScott Liu "%s: i2c check functionality error\n", DEVICE_NAME); 123666aee900SScott Liu return -ENXIO; 123766aee900SScott Liu } 123866aee900SScott Liu 123966aee900SScott Liu ts = devm_kzalloc(&client->dev, sizeof(struct elants_data), GFP_KERNEL); 124066aee900SScott Liu if (!ts) 124166aee900SScott Liu return -ENOMEM; 124266aee900SScott Liu 124366aee900SScott Liu mutex_init(&ts->sysfs_mutex); 124466aee900SScott Liu init_completion(&ts->cmd_done); 124566aee900SScott Liu 124666aee900SScott Liu ts->client = client; 124766aee900SScott Liu i2c_set_clientdata(client, ts); 124866aee900SScott Liu 1249afe10358SDmitry Torokhov ts->vcc33 = devm_regulator_get(&client->dev, "vcc33"); 1250afe10358SDmitry Torokhov if (IS_ERR(ts->vcc33)) { 1251afe10358SDmitry Torokhov error = PTR_ERR(ts->vcc33); 1252afe10358SDmitry Torokhov if (error != -EPROBE_DEFER) 1253afe10358SDmitry Torokhov dev_err(&client->dev, 1254afe10358SDmitry Torokhov "Failed to get 'vcc33' regulator: %d\n", 1255afe10358SDmitry Torokhov error); 1256afe10358SDmitry Torokhov return error; 1257afe10358SDmitry Torokhov } 1258afe10358SDmitry Torokhov 1259afe10358SDmitry Torokhov ts->vccio = devm_regulator_get(&client->dev, "vccio"); 1260afe10358SDmitry Torokhov if (IS_ERR(ts->vccio)) { 1261afe10358SDmitry Torokhov error = PTR_ERR(ts->vccio); 1262afe10358SDmitry Torokhov if (error != -EPROBE_DEFER) 1263afe10358SDmitry Torokhov dev_err(&client->dev, 1264afe10358SDmitry Torokhov "Failed to get 'vccio' regulator: %d\n", 1265afe10358SDmitry Torokhov error); 1266afe10358SDmitry Torokhov return error; 1267afe10358SDmitry Torokhov } 1268afe10358SDmitry Torokhov 12697229b87bSStephen Rothwell ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW); 1270afe10358SDmitry Torokhov if (IS_ERR(ts->reset_gpio)) { 1271afe10358SDmitry Torokhov error = PTR_ERR(ts->reset_gpio); 1272afe10358SDmitry Torokhov 1273afe10358SDmitry Torokhov if (error == -EPROBE_DEFER) 1274afe10358SDmitry Torokhov return error; 1275afe10358SDmitry Torokhov 1276afe10358SDmitry Torokhov if (error != -ENOENT && error != -ENOSYS) { 1277afe10358SDmitry Torokhov dev_err(&client->dev, 1278afe10358SDmitry Torokhov "failed to get reset gpio: %d\n", 1279afe10358SDmitry Torokhov error); 1280afe10358SDmitry Torokhov return error; 1281afe10358SDmitry Torokhov } 1282afe10358SDmitry Torokhov 1283afe10358SDmitry Torokhov ts->keep_power_in_suspend = true; 1284afe10358SDmitry Torokhov } 1285afe10358SDmitry Torokhov 1286afe10358SDmitry Torokhov error = elants_i2c_power_on(ts); 1287afe10358SDmitry Torokhov if (error) 1288afe10358SDmitry Torokhov return error; 1289afe10358SDmitry Torokhov 1290afe10358SDmitry Torokhov error = devm_add_action(&client->dev, elants_i2c_power_off, ts); 1291afe10358SDmitry Torokhov if (error) { 1292afe10358SDmitry Torokhov dev_err(&client->dev, 1293afe10358SDmitry Torokhov "failed to install power off action: %d\n", error); 1294afe10358SDmitry Torokhov elants_i2c_power_off(ts); 1295afe10358SDmitry Torokhov return error; 1296afe10358SDmitry Torokhov } 1297afe10358SDmitry Torokhov 1298afe10358SDmitry Torokhov /* Make sure there is something at this address */ 1299afe10358SDmitry Torokhov if (i2c_smbus_xfer(client->adapter, client->addr, 0, 1300afe10358SDmitry Torokhov I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0) { 1301afe10358SDmitry Torokhov dev_err(&client->dev, "nothing at this address\n"); 1302afe10358SDmitry Torokhov return -ENXIO; 1303afe10358SDmitry Torokhov } 1304afe10358SDmitry Torokhov 130566aee900SScott Liu error = elants_i2c_initialize(ts); 130666aee900SScott Liu if (error) { 130766aee900SScott Liu dev_err(&client->dev, "failed to initialize: %d\n", error); 130866aee900SScott Liu return error; 130966aee900SScott Liu } 131066aee900SScott Liu 131166aee900SScott Liu ts->input = devm_input_allocate_device(&client->dev); 131266aee900SScott Liu if (!ts->input) { 131366aee900SScott Liu dev_err(&client->dev, "Failed to allocate input device\n"); 131466aee900SScott Liu return -ENOMEM; 131566aee900SScott Liu } 131666aee900SScott Liu 131766aee900SScott Liu ts->input->name = "Elan Touchscreen"; 131866aee900SScott Liu ts->input->id.bustype = BUS_I2C; 131966aee900SScott Liu 132066aee900SScott Liu /* Multitouch input params setup */ 132166aee900SScott Liu 132266aee900SScott Liu input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->x_max, 0, 0); 132366aee900SScott Liu input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, 0, 0); 132466aee900SScott Liu input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); 132566aee900SScott Liu input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0); 1326f27ad893SJohnny Chuang input_set_abs_params(ts->input, ABS_MT_TOOL_TYPE, 1327f27ad893SJohnny Chuang 0, MT_TOOL_PALM, 0, 0); 132866aee900SScott Liu input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res); 132966aee900SScott Liu input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res); 133006170671SJohnny Chuang input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, 1); 133166aee900SScott Liu 133268334dbaSMichał Mirosław touchscreen_parse_properties(ts->input, true, &ts->prop); 133368334dbaSMichał Mirosław 13346def17b1SMichał Mirosław error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM, 13356def17b1SMichał Mirosław INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 13366def17b1SMichał Mirosław if (error) { 13376def17b1SMichał Mirosław dev_err(&client->dev, 13386def17b1SMichał Mirosław "failed to initialize MT slots: %d\n", error); 13396def17b1SMichał Mirosław return error; 13406def17b1SMichał Mirosław } 13416def17b1SMichał Mirosław 134266aee900SScott Liu error = input_register_device(ts->input); 134366aee900SScott Liu if (error) { 134466aee900SScott Liu dev_err(&client->dev, 134566aee900SScott Liu "unable to register input device: %d\n", error); 134666aee900SScott Liu return error; 134766aee900SScott Liu } 134866aee900SScott Liu 134966aee900SScott Liu /* 13504c83c071SDmitry Torokhov * Platform code (ACPI, DTS) should normally set up interrupt 13514c83c071SDmitry Torokhov * for us, but in case it did not let's fall back to using falling 13524c83c071SDmitry Torokhov * edge to be compatible with older Chromebooks. 135366aee900SScott Liu */ 13544c83c071SDmitry Torokhov irqflags = irq_get_trigger_type(client->irq); 13554c83c071SDmitry Torokhov if (!irqflags) 13564c83c071SDmitry Torokhov irqflags = IRQF_TRIGGER_FALLING; 135766aee900SScott Liu 135866aee900SScott Liu error = devm_request_threaded_irq(&client->dev, client->irq, 135966aee900SScott Liu NULL, elants_i2c_irq, 136066aee900SScott Liu irqflags | IRQF_ONESHOT, 136166aee900SScott Liu client->name, ts); 136266aee900SScott Liu if (error) { 136366aee900SScott Liu dev_err(&client->dev, "Failed to register interrupt\n"); 136466aee900SScott Liu return error; 136566aee900SScott Liu } 136666aee900SScott Liu 136766aee900SScott Liu /* 136866aee900SScott Liu * Systems using device tree should set up wakeup via DTS, 136966aee900SScott Liu * the rest will configure device as wakeup source by default. 137066aee900SScott Liu */ 137166aee900SScott Liu if (!client->dev.of_node) 137266aee900SScott Liu device_init_wakeup(&client->dev, true); 137366aee900SScott Liu 13748db69a9aSAndi Shyti error = devm_device_add_group(&client->dev, &elants_attribute_group); 137566aee900SScott Liu if (error) { 137666aee900SScott Liu dev_err(&client->dev, "failed to create sysfs attributes: %d\n", 137766aee900SScott Liu error); 137866aee900SScott Liu return error; 137966aee900SScott Liu } 138066aee900SScott Liu 138166aee900SScott Liu return 0; 138266aee900SScott Liu } 138366aee900SScott Liu 138466aee900SScott Liu static int __maybe_unused elants_i2c_suspend(struct device *dev) 138566aee900SScott Liu { 138666aee900SScott Liu struct i2c_client *client = to_i2c_client(dev); 138766aee900SScott Liu struct elants_data *ts = i2c_get_clientdata(client); 138866aee900SScott Liu const u8 set_sleep_cmd[] = { 0x54, 0x50, 0x00, 0x01 }; 138966aee900SScott Liu int retry_cnt; 139066aee900SScott Liu int error; 139166aee900SScott Liu 139266aee900SScott Liu /* Command not support in IAP recovery mode */ 139366aee900SScott Liu if (ts->iap_mode != ELAN_IAP_OPERATIONAL) 139466aee900SScott Liu return -EBUSY; 139566aee900SScott Liu 139666aee900SScott Liu disable_irq(client->irq); 139766aee900SScott Liu 1398478e5ed1SJames Chen if (device_may_wakeup(dev)) { 1399478e5ed1SJames Chen /* 1400478e5ed1SJames Chen * The device will automatically enter idle mode 1401478e5ed1SJames Chen * that has reduced power consumption. 1402478e5ed1SJames Chen */ 1403478e5ed1SJames Chen ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0); 1404478e5ed1SJames Chen } else if (ts->keep_power_in_suspend) { 140566aee900SScott Liu for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { 140666aee900SScott Liu error = elants_i2c_send(client, set_sleep_cmd, 140766aee900SScott Liu sizeof(set_sleep_cmd)); 140866aee900SScott Liu if (!error) 140966aee900SScott Liu break; 141066aee900SScott Liu 1411afe10358SDmitry Torokhov dev_err(&client->dev, 1412afe10358SDmitry Torokhov "suspend command failed: %d\n", error); 141366aee900SScott Liu } 1414afe10358SDmitry Torokhov } else { 1415afe10358SDmitry Torokhov elants_i2c_power_off(ts); 1416afe10358SDmitry Torokhov } 141766aee900SScott Liu 141866aee900SScott Liu return 0; 141966aee900SScott Liu } 142066aee900SScott Liu 142166aee900SScott Liu static int __maybe_unused elants_i2c_resume(struct device *dev) 142266aee900SScott Liu { 142366aee900SScott Liu struct i2c_client *client = to_i2c_client(dev); 142466aee900SScott Liu struct elants_data *ts = i2c_get_clientdata(client); 142566aee900SScott Liu const u8 set_active_cmd[] = { 0x54, 0x58, 0x00, 0x01 }; 142666aee900SScott Liu int retry_cnt; 142766aee900SScott Liu int error; 142866aee900SScott Liu 1429478e5ed1SJames Chen if (device_may_wakeup(dev)) { 1430478e5ed1SJames Chen if (ts->wake_irq_enabled) 143166aee900SScott Liu disable_irq_wake(client->irq); 1432478e5ed1SJames Chen elants_i2c_sw_reset(client); 1433478e5ed1SJames Chen } else if (ts->keep_power_in_suspend) { 143466aee900SScott Liu for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) { 143566aee900SScott Liu error = elants_i2c_send(client, set_active_cmd, 143666aee900SScott Liu sizeof(set_active_cmd)); 143766aee900SScott Liu if (!error) 143866aee900SScott Liu break; 143966aee900SScott Liu 1440afe10358SDmitry Torokhov dev_err(&client->dev, 1441afe10358SDmitry Torokhov "resume command failed: %d\n", error); 1442afe10358SDmitry Torokhov } 1443afe10358SDmitry Torokhov } else { 1444afe10358SDmitry Torokhov elants_i2c_power_on(ts); 1445afe10358SDmitry Torokhov elants_i2c_initialize(ts); 144666aee900SScott Liu } 144766aee900SScott Liu 144866aee900SScott Liu ts->state = ELAN_STATE_NORMAL; 144966aee900SScott Liu enable_irq(client->irq); 145066aee900SScott Liu 145166aee900SScott Liu return 0; 145266aee900SScott Liu } 145366aee900SScott Liu 145466aee900SScott Liu static SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops, 145566aee900SScott Liu elants_i2c_suspend, elants_i2c_resume); 145666aee900SScott Liu 145766aee900SScott Liu static const struct i2c_device_id elants_i2c_id[] = { 145866aee900SScott Liu { DEVICE_NAME, 0 }, 145966aee900SScott Liu { } 146066aee900SScott Liu }; 146166aee900SScott Liu MODULE_DEVICE_TABLE(i2c, elants_i2c_id); 146266aee900SScott Liu 146366aee900SScott Liu #ifdef CONFIG_ACPI 146466aee900SScott Liu static const struct acpi_device_id elants_acpi_id[] = { 146566aee900SScott Liu { "ELAN0001", 0 }, 146666aee900SScott Liu { } 146766aee900SScott Liu }; 146866aee900SScott Liu MODULE_DEVICE_TABLE(acpi, elants_acpi_id); 146966aee900SScott Liu #endif 147066aee900SScott Liu 147166aee900SScott Liu #ifdef CONFIG_OF 147266aee900SScott Liu static const struct of_device_id elants_of_match[] = { 147366aee900SScott Liu { .compatible = "elan,ekth3500" }, 147466aee900SScott Liu { /* sentinel */ } 147566aee900SScott Liu }; 147666aee900SScott Liu MODULE_DEVICE_TABLE(of, elants_of_match); 147766aee900SScott Liu #endif 147866aee900SScott Liu 147966aee900SScott Liu static struct i2c_driver elants_i2c_driver = { 148066aee900SScott Liu .probe = elants_i2c_probe, 148166aee900SScott Liu .id_table = elants_i2c_id, 148266aee900SScott Liu .driver = { 148366aee900SScott Liu .name = DEVICE_NAME, 148466aee900SScott Liu .pm = &elants_i2c_pm_ops, 148566aee900SScott Liu .acpi_match_table = ACPI_PTR(elants_acpi_id), 148666aee900SScott Liu .of_match_table = of_match_ptr(elants_of_match), 14879f6a07b6SDmitry Torokhov .probe_type = PROBE_PREFER_ASYNCHRONOUS, 148866aee900SScott Liu }, 148966aee900SScott Liu }; 149066aee900SScott Liu module_i2c_driver(elants_i2c_driver); 149166aee900SScott Liu 149266aee900SScott Liu MODULE_AUTHOR("Scott Liu <scott.liu@emc.com.tw>"); 149366aee900SScott Liu MODULE_DESCRIPTION("Elan I2c Touchscreen driver"); 149466aee900SScott Liu MODULE_LICENSE("GPL"); 1495