diff --git a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt deleted file mode 100644 index bde115155eba..000000000000 --- a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt +++ /dev/null @@ -1,104 +0,0 @@ -Goodix GT9xx series touch controller - -The Goodix GT9xx series touch controller is connected to the host processor via -I2C. The controller generates interrupts when the user touches the panel. The -host controller is expected to read the touch coordinates over I2C and pass -the coordinates to the rest of the system. - -Required properties: - - - compatible : Should be "goodix,gt9xx" - - reg : I2C slave address of the device. - - interrupt-parent : Parent of interrupt. - - interrupts : Configuration of touch panel controller interrupt - GPIO. - - goodix,product-id : Product identification of the controller. - - interrupt-gpios : Interrupt gpio which is to provide interrupts to - host, same as "interrupts" node. - - reset-gpios : Reset gpio to control the reset of chip. - - goodix,display-coords : Display coordinates in pixels. It is a four - tuple consisting of min x, min y, max x and - max y values. - -Optional properties: - - - avdd-supply : Power supply needed to power up the device, this is - for fixed voltage external regulator. - - vdd-supply : Power supply needed to power up the device, when use - external regulator, do not add this property. - - vcc-i2c-supply : Power source required to power up i2c bus. - GT9xx series can provide 1.8V from internal - LDO, add this properties base on hardware - design. - - goodix,panel-coords : Panel coordinates for the chip in pixels. - It is a four tuple consisting of min x, - min y, max x and max y values. - - goodix,i2c-pull-up : To specify pull up is required. - - goodix,force-update : To specify force update is allowed. - - goodix,enable-power-off : Power off touchscreen during suspend. - - goodix,button-map : Button map of key codes. The number of key codes - depend on panel. - - goodix,cfg-data0 : Touch screen controller config data group 0. Ask vendor - to provide that. - Driver supports maximum six config groups. If more than one - groups are defined, driver will select config group depending - on hardware configuration. If only config group 0 is defined, - it will be used for all hardware configurations. - Touch screen controller will use its onchip default config data - if this property is not present. - - goodix,cfg-data1 : Touch screen controller config data group 1. Ask vendor - to provide that. - - goodix,cfg-data2 : Touch screen controller config data group 2. Ask vendor - to provide that. - - goodix,cfg-data3 : Touch screen controller config data group 3. Ask vendor - to provide that. - - goodix,cfg-data4 : Touch screen controller config data group 4. Ask vendor - to provide that. - - goodix,cfg-data5 : Touch screen controller config data group 5. Ask vendor - to provide that. - - goodix,fw-name : Touch screen controller firmware file name. - - goodix,slide-wakeup : To specify slide-wakeup property is enabled or not. - - goodix,dbl-clk-wakeup : To specify dbl-clk-wakeup property is enabled or not. - - goodix,change-x2y : To specify change-x2y property is enabled or not. - - goodix,driver-send-cfg : To specify driver-send-cfg property is enabled or not. - - goodix,have-touch-key : To specify have-touch-key property is enabled or not. - - goodix,with-pen : To specify with-pen property is enabled or not. -Example: -i2c@f9927000 { - goodix@5d { - compatible = "goodix,gt9xx"; - reg = <0x5d>; - interrupt-parent = <&msmgpio>; - interrupts = <17 0x2008>; - reset-gpios = <&msmgpio 16 0x00>; - interrupt-gpios = <&msmgpio 17 0x00>; - avdd-supply = <&tp_power>; - goodix,panel-coords = <0 0 720 1200>; - goodix,display-coords = <0 0 720 1080>; - goodix,button-map= <158 102 139>; - goodix,product-id = "915"; - goodix,cfg-data0 = [ - 41 D0 02 00 05 0A 05 01 01 08 - 12 58 50 41 03 05 00 00 00 00 - 00 00 00 00 00 00 00 8C 2E 0E - 28 24 73 13 00 00 00 83 03 1D - 40 02 00 00 00 03 64 32 00 00 - 00 1A 38 94 C0 02 00 00 00 04 - 9E 1C 00 8D 20 00 7A 26 00 6D - 2C 00 60 34 00 60 10 38 68 00 - F0 50 35 FF FF 27 00 00 00 00 - 00 01 1B 14 0C 14 00 00 01 00 - 00 00 00 00 00 00 00 00 00 00 - 00 00 02 04 06 08 0A 0C 0E 10 - 12 14 16 18 1A 1C FF FF FF FF - FF FF FF FF FF FF FF FF FF FF - FF FF 00 02 04 06 08 0A 0C 0F - 10 12 13 14 16 18 1C 1D 1E 1F - 20 21 22 24 26 28 29 2A FF FF - FF FF FF FF FF FF FF 22 22 22 - 22 22 22 FF 07 01]; - goodix,fw_name = "gtp_fw.bin"; - goodix,have-touch-key; - goodix,driver-send-cfg; - }; -}; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 99de4002275e..075c18e0e4ae 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1206,18 +1206,6 @@ config TOUCHSCREEN_IT7260_I2C To compile this driver as a module, choose M here: the module will be called it7258_ts_i2c. -config TOUCHSCREEN_GT9XX - bool "Goodix touchpanel GT9xx series" - depends on I2C - help - Say Y here if you have a Goodix GT9xx touchscreen. - Gt9xx controllers are multi touch controllers which can - report 5 touches at a time. - - If unsure, say N. - -source "drivers/input/touchscreen/gt9xx/Kconfig" - config TOUCHSCREEN_ST bool "STMicroelectronics Touchscreen Driver" depends on I2C diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index a32132cffe92..2e0161cf95bc 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -98,5 +98,4 @@ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o obj-$(CONFIG_TOUCHSCREEN_ZFORCE) += zforce_ts.o obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o -obj-$(CONFIG_TOUCHSCREEN_GT9XX) += gt9xx/ obj-$(CONFIG_TOUCHSCREEN_ST) += st/ diff --git a/drivers/input/touchscreen/gt9xx/Kconfig b/drivers/input/touchscreen/gt9xx/Kconfig deleted file mode 100644 index 2e1b5ba567a0..000000000000 --- a/drivers/input/touchscreen/gt9xx/Kconfig +++ /dev/null @@ -1,51 +0,0 @@ -# -# Goodix GT9xx Touchscreen driver -# - -config GT9XX_TOUCHPANEL_DRIVER - tristate "Goodix GT9xx touchpanel driver" - depends on TOUCHSCREEN_GT9XX - default n - help - This is the main file for touchpanel driver for Goodix GT9xx - touchscreens. - - Say Y here if you have a Goodix GT9xx touchscreen connected - to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called gt9xx. - -config GT9XX_TOUCHPANEL_UPDATE - tristate "Goodix GT9xx touchpanel auto update support" - depends on GT9XX_TOUCHPANEL_DRIVER - default n - help - This enables support for firmware update for Goodix GT9xx - touchscreens. - - Say Y here if you have a Goodix GT9xx touchscreen connected - to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called gt9xx_update. - -config GT9XX_TOUCHPANEL_DEBUG - tristate "Goodix GT9xx Tools for debuging" - depends on GT9XX_TOUCHPANEL_DRIVER - default n - help - This is application debug interface support for Goodix GT9xx - touchscreens. - - Say Y here if you want to have a Android app debug interface - to your system. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called gt9xx_tool. diff --git a/drivers/input/touchscreen/gt9xx/Makefile b/drivers/input/touchscreen/gt9xx/Makefile deleted file mode 100644 index 482d869a2d37..000000000000 --- a/drivers/input/touchscreen/gt9xx/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -#gt915 touchpanel driver - - -obj-$(CONFIG_GT9XX_TOUCHPANEL_DRIVER) += gt9xx.o -#gt915 update file -obj-$(CONFIG_GT9XX_TOUCHPANEL_UPDATE) += gt9xx_update.o -#debug tool -obj-$(CONFIG_GT9XX_TOUCHPANEL_DEBUG) += goodix_tool.o diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c deleted file mode 100644 index 02fa0cbbe392..000000000000 --- a/drivers/input/touchscreen/gt9xx/goodix_tool.c +++ /dev/null @@ -1,600 +0,0 @@ -/* drivers/input/touchscreen/goodix_tool.c - * - * 2010 - 2012 Goodix Technology. - * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be a reference - * to you, when you are integrating the GOODiX's CTP IC into your system, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Version:1.6 - * V1.0:2012/05/01,create file. - * V1.2:2012/06/08,modify some warning. - * V1.4:2012/08/28,modified to support GT9XX - * V1.6:new proc name - */ - -#include "gt9xx.h" -#include -#include -#include - -#define DATA_LENGTH_UINT 512 -#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head)) -static char procname[20] = {0}; - -struct st_cmd_head { - u8 wr; /* write read flag 0:R 1:W 2:PID 3: */ - u8 flag; /* 0:no need flag/int 1: need flag 2:need int */ - u8 flag_addr[2];/* flag address */ - u8 flag_val; /* flag val */ - u8 flag_relation; /* flag_val:flag 0:not equal 1:equal 2:> 3:< */ - u16 circle; /* polling cycle */ - u8 times; /* plling times */ - u8 retry; /* I2C retry times */ - u16 delay; /* delay before read or after write */ - u16 data_len; /* data length */ - u8 addr_len; /* address length */ - u8 addr[2]; /* address */ - u8 res[3]; /* reserved */ -} __packed; - -static struct st_cmd_head cmd_head; -static u8 *cmd_data; - -static struct i2c_client *gt_client; - -static struct proc_dir_entry *goodix_proc_entry; - -static struct mutex lock; - -static s32 (*tool_i2c_read)(u8 *, u16); -static s32 (*tool_i2c_write)(u8 *, u16); - -s32 data_length; -s8 ic_type[16] = {0}; - -static void tool_set_proc_name(char *procname) -{ - char *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - char date[20] = {0}; - char month[4] = {0}; - int i = 0, n_month = 1, n_day = 0, n_year = 0, ret; - - ret = sscanf(date, "%s %d %d", month, &n_day, &n_year); - if (!ret) - return; - for (i = 0; i < 12; ++i) { - if (!memcmp(months[i], month, 3)) { - n_month = i+1; - break; - } - } - - snprintf(procname, 20, "gmnode%04d%02d%02d", n_year, n_month, n_day); -} - -static s32 tool_i2c_read_no_extra(u8 *buf, u16 len) -{ - s32 ret = -1; - u8 i = 0; - struct i2c_msg msgs[2] = { - { - .flags = !I2C_M_RD, - .addr = gt_client->addr, - .len = cmd_head.addr_len, - .buf = &buf[0], - }, - { - .flags = I2C_M_RD, - .addr = gt_client->addr, - .len = len, - .buf = &buf[GTP_ADDR_LENGTH], - }, - }; - - for (i = 0; i < cmd_head.retry; i++) { - ret = i2c_transfer(gt_client->adapter, msgs, 2); - if (ret > 0) - break; - } - - if (i == cmd_head.retry) { - dev_err(>_client->dev, "I2C read retry limit over\n"); - ret = -EIO; - } - - return ret; -} - -static s32 tool_i2c_write_no_extra(u8 *buf, u16 len) -{ - s32 ret = -1; - u8 i = 0; - struct i2c_msg msg = { - .flags = !I2C_M_RD, - .addr = gt_client->addr, - .len = len, - .buf = buf, - }; - - for (i = 0; i < cmd_head.retry; i++) { - ret = i2c_transfer(gt_client->adapter, &msg, 1); - if (ret > 0) - break; - } - - if (i == cmd_head.retry) { - dev_err(>_client->dev, "I2C write retry limit over\n"); - ret = -EIO; - } - - return ret; -} - -static s32 tool_i2c_read_with_extra(u8 *buf, u16 len) -{ - s32 ret = -1; - u8 pre[2] = {0x0f, 0xff}; - u8 end[2] = {0x80, 0x00}; - - tool_i2c_write_no_extra(pre, 2); - ret = tool_i2c_read_no_extra(buf, len); - tool_i2c_write_no_extra(end, 2); - - return ret; -} - -static s32 tool_i2c_write_with_extra(u8 *buf, u16 len) -{ - s32 ret = -1; - u8 pre[2] = {0x0f, 0xff}; - u8 end[2] = {0x80, 0x00}; - - tool_i2c_write_no_extra(pre, 2); - ret = tool_i2c_write_no_extra(buf, len); - tool_i2c_write_no_extra(end, 2); - - return ret; -} - -static void register_i2c_func(void) -{ - if (strcmp(ic_type, "GT8110") && strcmp(ic_type, "GT8105") - && strcmp(ic_type, "GT801") && strcmp(ic_type, "GT800") - && strcmp(ic_type, "GT801PLUS") && strcmp(ic_type, "GT811") - && strcmp(ic_type, "GTxxx")) { - tool_i2c_read = tool_i2c_read_with_extra; - tool_i2c_write = tool_i2c_write_with_extra; - pr_debug("I2C function: with pre and end cmd\n"); - } else { - tool_i2c_read = tool_i2c_read_no_extra; - tool_i2c_write = tool_i2c_write_no_extra; - pr_info("I2C function: without pre and end cmd\n"); - } -} - -static void unregister_i2c_func(void) -{ - tool_i2c_read = NULL; - tool_i2c_write = NULL; - pr_info("I2C function: unregister i2c transfer function\n"); -} - -void uninit_wr_node(void) -{ - cmd_data = NULL; - unregister_i2c_func(); - proc_remove(goodix_proc_entry); -} - -static u8 relation(u8 src, u8 dst, u8 rlt) -{ - u8 ret = 0; - - switch (rlt) { - - case 0: - ret = (src != dst) ? true : false; - break; - - case 1: - ret = (src == dst) ? true : false; - pr_debug("equal:src:0x%02x dst:0x%02x ret:%d\n", - src, dst, (s32)ret); - break; - - case 2: - ret = (src > dst) ? true : false; - break; - - case 3: - ret = (src < dst) ? true : false; - break; - - case 4: - ret = (src & dst) ? true : false; - break; - - case 5: - ret = (!(src | dst)) ? true : false; - break; - - default: - ret = false; - break; - } - - return ret; -} - -/* - * Function: - * Comfirm function. - * Input: - * None. - * Output: - * Return write length. - */ -static u8 comfirm(void) -{ - s32 i = 0; - u8 buf[32]; - - memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len); - - for (i = 0; i < cmd_head.times; i++) { - if (tool_i2c_read(buf, 1) <= 0) { - dev_err(>_client->dev, "Read flag data failed"); - return FAIL; - } - if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val, - cmd_head.flag_relation)) { - pr_debug("value at flag addr:0x%02x\n", - buf[GTP_ADDR_LENGTH]); - pr_debug("flag value:0x%02x\n", cmd_head.flag_val); - break; - } - - msleep(cmd_head.circle); - } - - if (i >= cmd_head.times) { - dev_err(>_client->dev, "Didn't get the flag to continue"); - return FAIL; - } - - return SUCCESS; -} - -#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE -static s32 fill_update_info(char __user *user_buf, - size_t count, loff_t *ppos) -{ - u8 buf[4]; - - buf[0] = show_len >> 8; - buf[1] = show_len & 0xff; - buf[2] = total_len >> 8; - buf[3] = total_len & 0xff; - return simple_read_from_buffer(user_buf, count, ppos, - buf, sizeof(buf)); -} -#else -static s32 fill_update_info(char __user *user_buf, - size_t count, loff_t *ppos) -{ - return -ENODEV; -} -#endif - -/* - * Function: - * Goodix tool write function. - * Input: - * standard proc write function param. - * Output: - * Return write length. - */ -static ssize_t goodix_tool_write(struct file *filp, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - s32 ret = 0; - - mutex_lock(&lock); - ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH); - if (ret) { - dev_err(>_client->dev, "copy_from_user failed"); - ret = -EFAULT; - goto exit; - } - - dev_dbg(>_client->dev, - "wr: 0x%02x, flag:0x%02x, flag addr:0x%02x%02x\n", cmd_head.wr, - cmd_head.flag, cmd_head.flag_addr[0], cmd_head.flag_addr[1]); - dev_dbg(>_client->dev, - "flag val:0x%02x, flag rel:0x%02x,\n", cmd_head.flag_val, - cmd_head.flag_relation); - dev_dbg(>_client->dev, "circle:%u, times:%u, retry:%u, delay:%u\n", - (s32) cmd_head.circle, (s32) cmd_head.times, - (s32) cmd_head.retry, (s32)cmd_head.delay); - dev_dbg(>_client->dev, - "data len:%u, addr len:%u, addr:0x%02x%02x, write len: %u\n", - (s32)cmd_head.data_len, (s32)cmd_head.addr_len, - cmd_head.addr[0], cmd_head.addr[1], (s32)count); - - if (cmd_head.data_len > (data_length - GTP_ADDR_LENGTH)) { - dev_err(>_client->dev, "data len %u > data buff %d, rejected\n", - cmd_head.data_len, (data_length - GTP_ADDR_LENGTH)); - ret = -EINVAL; - goto exit; - } - - if (cmd_head.wr == GTP_RW_WRITE) { - ret = copy_from_user(&cmd_data[GTP_ADDR_LENGTH], - &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); - if (ret) { - dev_err(>_client->dev, "copy_from_user failed"); - ret = -EFAULT; - goto exit; - } - - memcpy(&cmd_data[GTP_ADDR_LENGTH - cmd_head.addr_len], - cmd_head.addr, cmd_head.addr_len); - - if (cmd_head.flag == GTP_NEED_FLAG) { - if (comfirm() == FAIL) { - dev_err(>_client->dev, "Confirm fail"); - ret = -EINVAL; - goto exit; - } - } else if (cmd_head.flag == GTP_NEED_INTERRUPT) { - /* Need interrupt! */ - } - if (tool_i2c_write( - &cmd_data[GTP_ADDR_LENGTH - cmd_head.addr_len], - cmd_head.data_len + cmd_head.addr_len) <= 0) { - dev_err(>_client->dev, "Write data failed"); - ret = -EIO; - goto exit; - } - - if (cmd_head.delay) - msleep(cmd_head.delay); - - ret = cmd_head.data_len + CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_WRITE_IC_TYPE) { /* Write ic type */ - ret = copy_from_user(&cmd_data[0], - &userbuf[CMD_HEAD_LENGTH], - cmd_head.data_len); - if (ret) { - dev_err(>_client->dev, "copy_from_user failed"); - ret = -EFAULT; - goto exit; - } - - if (cmd_head.data_len > sizeof(ic_type)) { - dev_err(>_client->dev, - "data len %u > data buff %zu, rejected\n", - cmd_head.data_len, sizeof(ic_type)); - ret = -EINVAL; - goto exit; - } - memcpy(ic_type, cmd_data, cmd_head.data_len); - - register_i2c_func(); - - ret = cmd_head.data_len + CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_NO_WRITE) { - ret = cmd_head.data_len + CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_DISABLE_IRQ) { /* disable irq! */ - gtp_irq_disable(i2c_get_clientdata(gt_client)); - - #if GTP_ESD_PROTECT - gtp_esd_switch(gt_client, SWITCH_OFF); - #endif - ret = CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_ENABLE_IRQ) { /* enable irq! */ - gtp_irq_enable(i2c_get_clientdata(gt_client)); - - #if GTP_ESD_PROTECT - gtp_esd_switch(gt_client, SWITCH_ON); - #endif - ret = CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_CHECK_RAWDIFF_MODE) { - struct goodix_ts_data *ts = i2c_get_clientdata(gt_client); - - ret = copy_from_user(&cmd_data[GTP_ADDR_LENGTH], - &userbuf[CMD_HEAD_LENGTH], cmd_head.data_len); - if (ret) { - dev_err(>_client->dev, "copy_from_user failed"); - goto exit; - } - if (cmd_data[GTP_ADDR_LENGTH]) { - pr_debug("gtp enter rawdiff\n"); - ts->gtp_rawdiff_mode = true; - } else { - ts->gtp_rawdiff_mode = false; - pr_debug("gtp leave rawdiff\n"); - } - ret = CMD_HEAD_LENGTH; - goto exit; - } else if (cmd_head.wr == GTP_RW_ENTER_UPDATE_MODE) { - /* Enter update mode! */ - if (gup_enter_update_mode(gt_client) == FAIL) { - ret = -EBUSY; - goto exit; - } - } else if (cmd_head.wr == GTP_RW_LEAVE_UPDATE_MODE) { - /* Leave update mode! */ - gup_leave_update_mode(gt_client); - } else if (cmd_head.wr == GTP_RW_UPDATE_FW) { - /* Update firmware! */ - show_len = 0; - total_len = 0; - if (cmd_head.data_len + 1 > data_length) { - dev_err(>_client->dev, "data len %u > data buff %d, rejected\n", - cmd_head.data_len + 1, data_length); - ret = -EINVAL; - goto exit; - } - memset(cmd_data, 0, cmd_head.data_len + 1); - memcpy(cmd_data, &userbuf[CMD_HEAD_LENGTH], - cmd_head.data_len); - - if (gup_update_proc((void *)cmd_data) == FAIL) { - ret = -EBUSY; - goto exit; - } - } - ret = CMD_HEAD_LENGTH; - -exit: - memset(&cmd_head, 0, sizeof(cmd_head)); - cmd_head.wr = 0xFF; - - mutex_unlock(&lock); - return ret; -} - -/* - * Function: - * Goodix tool read function. - * Input: - * standard proc read function param. - * Output: - * Return read length. - */ -static ssize_t goodix_tool_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - u16 data_len = 0; - s32 ret; - u8 buf[32]; - - mutex_lock(&lock); - if (cmd_head.wr & 0x1) { - dev_err(>_client->dev, "command head wrong\n"); - ret = -EINVAL; - goto exit; - } - - switch (cmd_head.wr) { - case GTP_RW_READ: - if (cmd_head.flag == GTP_NEED_FLAG) { - if (comfirm() == FAIL) { - dev_err(>_client->dev, "Confirm fail"); - ret = -EINVAL; - goto exit; - } - } else if (cmd_head.flag == GTP_NEED_INTERRUPT) { - /* Need interrupt! */ - } - - memcpy(cmd_data, cmd_head.addr, cmd_head.addr_len); - - pr_debug("[CMD HEAD DATA] ADDR:0x%02x%02x.\n", cmd_data[0], - cmd_data[1]); - pr_debug("[CMD HEAD ADDR] ADDR:0x%02x%02x.\n", cmd_head.addr[0], - cmd_head.addr[1]); - - if (cmd_head.delay) - msleep(cmd_head.delay); - - data_len = cmd_head.data_len; - if (data_len <= 0 || (data_len > data_length)) { - dev_err(>_client->dev, "Invalid data length %d\n", - data_len); - ret = -EINVAL; - goto exit; - } - if (data_len > count) - data_len = count; - - if (tool_i2c_read(cmd_data, data_len) <= 0) { - dev_err(>_client->dev, "Read data failed\n"); - ret = -EIO; - goto exit; - } - ret = simple_read_from_buffer(user_buf, count, ppos, - &cmd_data[GTP_ADDR_LENGTH], data_len); - break; - case GTP_RW_FILL_INFO: - ret = fill_update_info(user_buf, count, ppos); - break; - case GTP_RW_READ_VERSION: - /* Read driver version */ - data_len = scnprintf(buf, sizeof(buf), "%s\n", - GTP_DRIVER_VERSION); - ret = simple_read_from_buffer(user_buf, count, ppos, - buf, data_len); - break; - default: - ret = -EINVAL; - break; - } - -exit: - mutex_unlock(&lock); - return ret; -} - -static const struct file_operations goodix_proc_fops = { - .write = goodix_tool_write, - .read = goodix_tool_read, - .open = simple_open, - .owner = THIS_MODULE, -}; - -s32 init_wr_node(struct i2c_client *client) -{ - u8 i; - - gt_client = client; - memset(&cmd_head, 0, sizeof(cmd_head)); - cmd_data = NULL; - - i = GTP_I2C_RETRY_5; - while ((!cmd_data) && i) { - cmd_data = devm_kzalloc(&client->dev, - i * DATA_LENGTH_UINT, GFP_KERNEL); - if (cmd_data) - break; - i--; - } - if (i) { - data_length = i * DATA_LENGTH_UINT; - dev_dbg(&client->dev, "Applied memory size:%d", data_length); - } - - cmd_head.addr_len = 2; - cmd_head.retry = GTP_I2C_RETRY_5; - - register_i2c_func(); - - mutex_init(&lock); - tool_set_proc_name(procname); - goodix_proc_entry = proc_create(procname, - S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, - goodix_proc_entry, - &goodix_proc_fops); - if (goodix_proc_entry == NULL) { - dev_err(&client->dev, "Couldn't create proc entry"); - return FAIL; - } - - return SUCCESS; -} diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c deleted file mode 100644 index ead935120624..000000000000 --- a/drivers/input/touchscreen/gt9xx/gt9xx.c +++ /dev/null @@ -1,2564 +0,0 @@ -/* drivers/input/touchscreen/gt9xx.c - * - * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. - * - * 2010 - 2013 Goodix Technology. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be a reference - * to you, when you are integrating the GOODiX's CTP IC into your system, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Version: 1.8 - * Authors: andrew@goodix.com, meta@goodix.com - * Release Date: 2013/04/25 - * Revision record: - * V1.0: - * first Release. By Andrew, 2012/08/31 - * V1.2: - * modify gtp_reset_guitar,slot report,tracking_id & 0x0F. - * By Andrew, 2012/10/15 - * V1.4: - * modify gt9xx_update.c. By Andrew, 2012/12/12 - * V1.6: - * 1. new heartbeat/esd_protect mechanism(add external watchdog) - * 2. doze mode, sliding wakeup - * 3. 3 more cfg_group(GT9 Sensor_ID: 0~5) - * 3. config length verification - * 4. names & comments - * By Meta, 2013/03/11 - * V1.8: - * 1. pen/stylus identification - * 2. read double check & fixed config support - * 2. new esd & slide wakeup optimization - * By Meta, 2013/06/08 - */ - -#include -#include "gt9xx.h" - -#include -#include -#include -#include -#include -#include - -#define GOODIX_DEV_NAME "Goodix-CTP" -#define CFG_MAX_TOUCH_POINTS 5 -#define GOODIX_COORDS_ARR_SIZE 4 -#define MAX_BUTTONS 4 - -#define GOODIX_VTG_MIN_UV 2600000 -#define GOODIX_VTG_MAX_UV 3300000 -#define GOODIX_I2C_VTG_MIN_UV 1800000 -#define GOODIX_I2C_VTG_MAX_UV 1800000 -#define GOODIX_VDD_LOAD_MIN_UA 0 -#define GOODIX_VDD_LOAD_MAX_UA 10000 -#define GOODIX_VIO_LOAD_MIN_UA 0 -#define GOODIX_VIO_LOAD_MAX_UA 10000 - -#define RESET_DELAY_T3_US 200 /* T3: > 100us */ -#define RESET_DELAY_T4 20 /* T4: > 5ms */ -#define SLEEP_DELAY_US 5000 -#define WAKE_UP_DELAY_US 5000 - -#define PHY_BUF_SIZE 32 -#define PROP_NAME_SIZE 24 - -#define GTP_MAX_TOUCH 5 -#define GTP_ESD_CHECK_CIRCLE_MS 2000 - -static void gtp_int_sync(struct goodix_ts_data *ts, int ms); -static int gtp_i2c_test(struct i2c_client *client); -static int goodix_power_off(struct goodix_ts_data *ts); -static int goodix_power_on(struct goodix_ts_data *ts); - -#if defined(CONFIG_FB) -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data); -static int goodix_ts_suspend(struct device *dev); -static int goodix_ts_resume(struct device *dev); -#elif defined(CONFIG_HAS_EARLYSUSPEND) -static void goodix_ts_early_suspend(struct early_suspend *h); -static void goodix_ts_late_resume(struct early_suspend *h); -#endif - -#if GTP_ESD_PROTECT -static struct delayed_work gtp_esd_check_work; -static struct workqueue_struct *gtp_esd_check_workqueue; -static void gtp_esd_check_func(struct work_struct *work); -static int gtp_init_ext_watchdog(struct i2c_client *client); -#endif - -enum doze { - DOZE_DISABLED = 0, - DOZE_ENABLED = 1, - DOZE_WAKEUP = 2, -}; -static enum doze doze_status = DOZE_DISABLED; -static s8 gtp_enter_doze(struct goodix_ts_data *ts); - -bool init_done; -static u8 chip_gt9xxs; /* true if ic is gt9xxs, like gt915s */ -u8 grp_cfg_version; -struct i2c_client *i2c_connect_client; - -#define GTP_DEBUGFS_DIR "ts_debug" -#define GTP_DEBUGFS_FILE_SUSPEND "suspend" -#define GTP_DEBUGFS_FILE_DATA "data" -#define GTP_DEBUGFS_FILE_ADDR "addr" - -/******************************************************* -Function: - Read data from the i2c slave device. -Input: - client: i2c device. - buf[0~1]: read start address. - buf[2~len-1]: read data buffer. - len: GTP_ADDR_LENGTH + read bytes count -Output: - numbers of i2c_msgs to transfer: - 2: succeed, otherwise: failed -*********************************************************/ -int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len) -{ - struct goodix_ts_data *ts = i2c_get_clientdata(client); - int ret = -EIO; - u8 retries; - struct i2c_msg msgs[2] = { - { - .flags = !I2C_M_RD, - .addr = client->addr, - .len = GTP_ADDR_LENGTH, - .buf = &buf[0], - }, - { - .flags = I2C_M_RD, - .addr = client->addr, - .len = len - GTP_ADDR_LENGTH, - .buf = &buf[GTP_ADDR_LENGTH], - }, - }; - - for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) { - ret = i2c_transfer(client->adapter, msgs, 2); - if (ret == 2) - break; - dev_err(&client->dev, "I2C retry: %d\n", retries + 1); - } - if (retries == GTP_I2C_RETRY_5) { - if (ts->pdata->slide_wakeup) - /* reset chip would quit doze mode */ - if (doze_status == DOZE_ENABLED) - return ret; - - if (init_done) - gtp_reset_guitar(ts, 10); - else - dev_warn(&client->dev, - "gtp_reset_guitar exit init_done=%d:\n", - init_done); - } - return ret; -} - -/******************************************************* -Function: - Write data to the i2c slave device. -Input: - client: i2c device. - buf[0~1]: write start address. - buf[2~len-1]: data buffer - len: GTP_ADDR_LENGTH + write bytes count -Output: - numbers of i2c_msgs to transfer: - 1: succeed, otherwise: failed -*********************************************************/ -int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len) -{ - struct goodix_ts_data *ts = i2c_get_clientdata(client); - int ret = -EIO; - u8 retries; - struct i2c_msg msg = { - .flags = !I2C_M_RD, - .addr = client->addr, - .len = len, - .buf = buf, - }; - - for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) { - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret == 1) - break; - dev_err(&client->dev, "I2C retry: %d\n", retries + 1); - } - if (retries == GTP_I2C_RETRY_5) { - if (ts->pdata->slide_wakeup) - if (doze_status == DOZE_ENABLED) - return ret; - - if (init_done) - gtp_reset_guitar(ts, 10); - else - dev_warn(&client->dev, - "gtp_reset_guitar exit init_done=%d:\n", - init_done); - } - return ret; -} - -/******************************************************* -Function: - i2c read twice, compare the results -Input: - client: i2c device - addr: operate address - rxbuf: read data to store, if compare successful - len: bytes to read -Output: - FAIL: read failed - SUCCESS: read successful -*********************************************************/ -int gtp_i2c_read_dbl_check(struct i2c_client *client, - u16 addr, u8 *rxbuf, int len) -{ - u8 buf[16] = {0}; - u8 confirm_buf[16] = {0}; - u8 retry = 0; - - while (retry++ < GTP_I2C_RETRY_3) { - memset(buf, 0xAA, 16); - buf[0] = (u8)(addr >> 8); - buf[1] = (u8)(addr & 0xFF); - gtp_i2c_read(client, buf, len + 2); - - memset(confirm_buf, 0xAB, 16); - confirm_buf[0] = (u8)(addr >> 8); - confirm_buf[1] = (u8)(addr & 0xFF); - gtp_i2c_read(client, confirm_buf, len + 2); - - if (!memcmp(buf, confirm_buf, len + 2)) - break; - } - if (retry < GTP_I2C_RETRY_3) { - memcpy(rxbuf, confirm_buf + 2, len); - return SUCCESS; - } - dev_err(&client->dev, - "i2c read 0x%04X, %d bytes, double check failed!", addr, len); - return FAIL; -} - -/******************************************************* -Function: - Send config data. -Input: - client: i2c device. -Output: - result of i2c write operation. - > 0: succeed, otherwise: failed -*********************************************************/ -int gtp_send_cfg(struct goodix_ts_data *ts) -{ - int ret = 0; - int retry; - - if (ts->pdata->driver_send_cfg) { - if (ts->fixed_cfg) { - dev_dbg(&ts->client->dev, - "Ic fixed config, no config sent!"); - ret = 2; - } else { - for (retry = 0; retry < GTP_I2C_RETRY_5; retry++) { - ret = gtp_i2c_write(ts->client, - ts->config_data, - GTP_CONFIG_MAX_LENGTH + - GTP_ADDR_LENGTH); - if (ret > 0) - break; - } - } - } - - return ret; -} - -/******************************************************* -Function: - Disable irq function -Input: - ts: goodix i2c_client private data -Output: - None. -*********************************************************/ -void gtp_irq_disable(struct goodix_ts_data *ts) -{ - unsigned long irqflags; - - spin_lock_irqsave(&ts->irq_lock, irqflags); - if (!ts->irq_is_disabled) { - ts->irq_is_disabled = true; - disable_irq_nosync(ts->client->irq); - } - spin_unlock_irqrestore(&ts->irq_lock, irqflags); -} - -/******************************************************* -Function: - Enable irq function -Input: - ts: goodix i2c_client private data -Output: - None. -*********************************************************/ -void gtp_irq_enable(struct goodix_ts_data *ts) -{ - unsigned long irqflags = 0; - - spin_lock_irqsave(&ts->irq_lock, irqflags); - if (ts->irq_is_disabled) { - enable_irq(ts->client->irq); - ts->irq_is_disabled = false; - } - spin_unlock_irqrestore(&ts->irq_lock, irqflags); -} - -/******************************************************* -Function: - Report touch point event -Input: - ts: goodix i2c_client private data - id: trackId - x: input x coordinate - y: input y coordinate - w: input pressure -Output: - None. -*********************************************************/ -static void gtp_touch_down(struct goodix_ts_data *ts, int id, int x, int y, - int w) -{ - if (ts->pdata->change_x2y) - swap(x, y); - - input_mt_slot(ts->input_dev, id); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); -} - -/******************************************************* -Function: - Report touch release event -Input: - ts: goodix i2c_client private data -Output: - None. -*********************************************************/ -static void gtp_touch_up(struct goodix_ts_data *ts, int id) -{ - input_mt_slot(ts->input_dev, id); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false); -} - - - -/******************************************************* -Function: - Goodix touchscreen work function -Input: - work: work struct of goodix_workqueue -Output: - None. -*********************************************************/ -static void goodix_ts_work_func(struct work_struct *work) -{ - u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8, - GTP_READ_COOR_ADDR & 0xFF, 0}; - u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1] = { - GTP_READ_COOR_ADDR >> 8, - GTP_READ_COOR_ADDR & 0xFF}; - u8 touch_num = 0; - u8 finger = 0; - static u16 pre_touch; - static u8 pre_key; - static u8 pre_pen; - u8 key_value = 0; - u8 *coor_data = NULL; - s32 input_x = 0; - s32 input_y = 0; - s32 input_w = 0; - s32 id = 0; - s32 i = 0; - int ret = -1; - struct goodix_ts_data *ts = NULL; - u8 doze_buf[3] = {0x81, 0x4B}; - - ts = container_of(work, struct goodix_ts_data, work); -#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE - if (ts->enter_update) - return; -#endif - - if (ts->pdata->slide_wakeup) { - if (doze_status == DOZE_ENABLED) { - ret = gtp_i2c_read(ts->client, doze_buf, 3); - if (ret > 0) { - if (doze_buf[2] == 0xAA) { - dev_dbg(&ts->client->dev, - "Slide(0xAA) To Light up the screen!"); - doze_status = DOZE_WAKEUP; - input_report_key( - ts->input_dev, KEY_POWER, 1); - input_sync(ts->input_dev); - input_report_key( - ts->input_dev, KEY_POWER, 0); - input_sync(ts->input_dev); - /* clear 0x814B */ - doze_buf[2] = 0x00; - gtp_i2c_write(ts->client, doze_buf, 3); - } else if (doze_buf[2] == 0xBB) { - dev_dbg(&ts->client->dev, - "Slide(0xBB) To Light up the screen!"); - doze_status = DOZE_WAKEUP; - input_report_key(ts->input_dev, - KEY_POWER, 1); - input_sync(ts->input_dev); - input_report_key(ts->input_dev, - KEY_POWER, 0); - input_sync(ts->input_dev); - /* clear 0x814B*/ - doze_buf[2] = 0x00; - gtp_i2c_write(ts->client, doze_buf, 3); - } else if (0xC0 == (doze_buf[2] & 0xC0)) { - dev_dbg(&ts->client->dev, - "double click to light up the screen!"); - doze_status = DOZE_WAKEUP; - input_report_key(ts->input_dev, - KEY_POWER, 1); - input_sync(ts->input_dev); - input_report_key(ts->input_dev, - KEY_POWER, 0); - input_sync(ts->input_dev); - /* clear 0x814B */ - doze_buf[2] = 0x00; - gtp_i2c_write(ts->client, doze_buf, 3); - } else { - gtp_enter_doze(ts); - } - } - if (ts->use_irq) - gtp_irq_enable(ts); - - return; - } - } - - ret = gtp_i2c_read(ts->client, point_data, 12); - if (ret < 0) { - dev_err(&ts->client->dev, - "I2C transfer error. errno:%d\n ", ret); - goto exit_work_func; - } - - finger = point_data[GTP_ADDR_LENGTH]; - if ((finger & 0x80) == 0) - goto exit_work_func; - - touch_num = finger & 0x0f; - if (touch_num > GTP_MAX_TOUCH) - goto exit_work_func; - - if (touch_num > 1) { - u8 buf[8 * GTP_MAX_TOUCH] = { (GTP_READ_COOR_ADDR + 10) >> 8, - (GTP_READ_COOR_ADDR + 10) & 0xff }; - - ret = gtp_i2c_read(ts->client, buf, - 2 + 8 * (touch_num - 1)); - memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1)); - } - - - key_value = point_data[3 + 8 * touch_num]; - - if (key_value || pre_key) { - for (i = 0; i < ts->pdata->num_button; i++) { - input_report_key(ts->input_dev, - ts->pdata->button_map[i], - key_value & (0x01<pdata->with_pen) { - if (pre_pen && (touch_num == 0)) { - dev_dbg(&ts->client->dev, "Pen touch UP(Slot)!"); - input_report_key(ts->input_dev, BTN_TOOL_PEN, 0); - input_mt_slot(ts->input_dev, 5); - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); - pre_pen = 0; - } - } - - if (pre_touch || touch_num) { - s32 pos = 0; - u16 touch_index = 0; - - coor_data = &point_data[3]; - if (touch_num) { - id = coor_data[pos] & 0x0F; - if (ts->pdata->with_pen) { - id = coor_data[pos]; - if (id == 128) { - dev_dbg(&ts->client->dev, - "Pen touch DOWN(Slot)!"); - input_x = coor_data[pos + 1] - | (coor_data[pos + 2] << 8); - input_y = coor_data[pos + 3] - | (coor_data[pos + 4] << 8); - input_w = coor_data[pos + 5] - | (coor_data[pos + 6] << 8); - - input_report_key(ts->input_dev, - BTN_TOOL_PEN, 1); - input_mt_slot(ts->input_dev, 5); - input_report_abs(ts->input_dev, - ABS_MT_TRACKING_ID, 5); - input_report_abs(ts->input_dev, - ABS_MT_POSITION_X, input_x); - input_report_abs(ts->input_dev, - ABS_MT_POSITION_Y, input_y); - input_report_abs(ts->input_dev, - ABS_MT_TOUCH_MAJOR, input_w); - dev_dbg(&ts->client->dev, - "Pen/Stylus: (%d, %d)[%d]", - input_x, input_y, input_w); - pre_pen = 1; - pre_touch = 0; - } - } - - touch_index |= (0x01<pdata->with_pen) - if (pre_pen == 1) - break; - - if (touch_index & (0x01<input_dev); - -exit_work_func: - if (!ts->gtp_rawdiff_mode) { - ret = gtp_i2c_write(ts->client, end_cmd, 3); - if (ret < 0) - dev_warn(&ts->client->dev, "I2C write end_cmd error!\n"); - - } - if (ts->use_irq) - gtp_irq_enable(ts); - - return; -} - -/******************************************************* -Function: - External interrupt service routine for interrupt mode. -Input: - irq: interrupt number. - dev_id: private data pointer -Output: - Handle Result. - IRQ_HANDLED: interrupt handled successfully -*********************************************************/ -static irqreturn_t goodix_ts_irq_handler(int irq, void *dev_id) -{ - struct goodix_ts_data *ts = dev_id; - - gtp_irq_disable(ts); - - queue_work(ts->goodix_wq, &ts->work); - - return IRQ_HANDLED; -} -/******************************************************* -Function: - Synchronization. -Input: - ms: synchronization time in millisecond. -Output: - None. -*******************************************************/ -void gtp_int_sync(struct goodix_ts_data *ts, int ms) -{ - gpio_direction_output(ts->pdata->irq_gpio, 0); - msleep(ms); - gpio_direction_input(ts->pdata->irq_gpio); -} - -/******************************************************* -Function: - Reset chip. -Input: - ms: reset time in millisecond, must >10ms -Output: - None. -*******************************************************/ -void gtp_reset_guitar(struct goodix_ts_data *ts, int ms) -{ - /* This reset sequence will selcet I2C slave address */ - gpio_direction_output(ts->pdata->reset_gpio, 0); - msleep(ms); - - if (ts->client->addr == GTP_I2C_ADDRESS_HIGH) - gpio_direction_output(ts->pdata->irq_gpio, 1); - else - gpio_direction_output(ts->pdata->irq_gpio, 0); - - usleep_range(RESET_DELAY_T3_US, RESET_DELAY_T3_US + 1); - gpio_direction_output(ts->pdata->reset_gpio, 1); - msleep(RESET_DELAY_T4); - - gpio_direction_input(ts->pdata->reset_gpio); - - gtp_int_sync(ts, 50); - -#if GTP_ESD_PROTECT - gtp_init_ext_watchdog(ts->client); -#endif -} - -#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) -/******************************************************* -Function: - Enter doze mode for sliding wakeup. -Input: - ts: goodix tp private data -Output: - 1: succeed, otherwise failed -*******************************************************/ -static s8 gtp_enter_doze(struct goodix_ts_data *ts) -{ - int ret = -1; - s8 retry = 0; - u8 i2c_control_buf[3] = { - (u8)(GTP_REG_SLEEP >> 8), - (u8)GTP_REG_SLEEP, 8}; - - if (ts->pdata->dbl_clk_wakeup) - i2c_control_buf[2] = 0x09; - - gtp_irq_disable(ts); - - while (retry++ < GTP_I2C_RETRY_3) { - i2c_control_buf[0] = 0x80; - i2c_control_buf[1] = 0x46; - ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); - if (ret < 0) { - dev_err(&ts->client->dev, - "failed to set doze flag into 0x8046, %d", - retry); - continue; - } - i2c_control_buf[0] = 0x80; - i2c_control_buf[1] = 0x40; - ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); - if (ret > 0) { - doze_status = DOZE_ENABLED; - dev_dbg(&ts->client->dev, - "GTP has been working in doze mode!"); - gtp_irq_enable(ts); - return ret; - } - msleep(20); - } - dev_err(&ts->client->dev, "GTP send doze cmd failed.\n"); - gtp_irq_enable(ts); - return ret; -} -/** - * gtp_enter_sleep - Enter sleep mode - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static u8 gtp_enter_sleep(struct goodix_ts_data *ts) -{ - int ret = -1; - s8 retry = 0; - u8 i2c_control_buf[3] = { - (u8)(GTP_REG_SLEEP >> 8), - (u8)GTP_REG_SLEEP, 5}; - - ret = gpio_direction_output(ts->pdata->irq_gpio, 0); - if (ret) - dev_err(&ts->client->dev, - "GTP sleep: Cannot reconfig gpio %d.\n", - ts->pdata->irq_gpio); - if (ts->pdata->enable_power_off) { - ret = gpio_direction_output(ts->pdata->reset_gpio, 0); - if (ret) - dev_err(&ts->client->dev, - "GTP sleep: Cannot reconfig gpio %d.\n", - ts->pdata->reset_gpio); - ret = goodix_power_off(ts); - if (ret) { - dev_err(&ts->client->dev, "GTP power off failed.\n"); - return ret; - } - return 0; - } - usleep_range(SLEEP_DELAY_US, SLEEP_DELAY_US + 1); - while (retry++ < GTP_I2C_RETRY_5) { - ret = gtp_i2c_write(ts->client, i2c_control_buf, 3); - if (ret == 1) { - dev_dbg(&ts->client->dev, "GTP enter sleep!"); - return 0; - } - msleep(20); - } - dev_err(&ts->client->dev, "GTP send sleep cmd failed.\n"); - return ret; -} - -/******************************************************* -Function: - Wakeup from sleep. -Input: - ts: private data. -Output: - Executive outcomes. - >0: succeed, otherwise: failed. -*******************************************************/ -static s8 gtp_wakeup_sleep(struct goodix_ts_data *ts) -{ - u8 retry = 0; - s8 ret = -1; - - if (ts->pdata->enable_power_off) { - ret = gpio_direction_output(ts->pdata->irq_gpio, 0); - if (ret) - dev_err(&ts->client->dev, - "GTP wakeup: Cannot reconfig gpio %d.\n", - ts->pdata->irq_gpio); - ret = gpio_direction_output(ts->pdata->reset_gpio, 0); - if (ret) - dev_err(&ts->client->dev, - "GTP wakeup: Cannot reconfig gpio %d.\n", - ts->pdata->reset_gpio); - ret = goodix_power_on(ts); - if (ret) { - dev_err(&ts->client->dev, "GTP power on failed.\n"); - return 0; - } - - gtp_reset_guitar(ts, 20); - - ret = gtp_send_cfg(ts); - if (ret <= 0) { - dev_err(&ts->client->dev, - "GTP wakeup sleep failed.\n"); - return ret; - } - - dev_dbg(&ts->client->dev, - "Wakeup sleep send config success."); - } else { -err_retry: - if (ts->pdata->slide_wakeup) { /* wakeup not by slide */ - if (doze_status != DOZE_WAKEUP) - gtp_reset_guitar(ts, 10); - else - /* wakeup by slide */ - doze_status = DOZE_DISABLED; - } else { - if (chip_gt9xxs == 1) { - gtp_reset_guitar(ts, 10); - } else { - ret = gpio_direction_output( - ts->pdata->irq_gpio, 1); - usleep_range(WAKE_UP_DELAY_US, - WAKE_UP_DELAY_US + 1); - } - } - ret = gtp_i2c_test(ts->client); - if (ret == 2) { - dev_dbg(&ts->client->dev, "GTP wakeup sleep."); - if (!ts->pdata->slide_wakeup) { - if (chip_gt9xxs == 0) { - gtp_int_sync(ts, 25); - msleep(20); -#if GTP_ESD_PROTECT - gtp_init_ext_watchdog(ts->client); -#endif - } - } - return ret; - } - gtp_reset_guitar(ts, 20); - if (retry++ < GTP_I2C_RETRY_10) - goto err_retry; - dev_err(&ts->client->dev, "GTP wakeup sleep failed.\n"); - } - return ret; -} -#endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ - -/******************************************************* -Function: - Initialize gtp. -Input: - ts: goodix private data -Output: - Executive outcomes. - > =0: succeed, otherwise: failed -*******************************************************/ -static int gtp_init_panel(struct goodix_ts_data *ts) -{ - struct i2c_client *client = ts->client; - unsigned char *config_data = NULL; - int ret = -EIO; - int i; - u8 check_sum = 0; - u8 opr_buf[16]; - u8 sensor_id = 0; - - if (ts->pdata->driver_send_cfg) { - for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) - dev_dbg(&client->dev, "Config Groups(%d) Lengths: %zu", - i, ts->pdata->config_data_len[i]); - - ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1); - if (ret == SUCCESS) { - if (opr_buf[0] != 0xBE) { - ts->fw_error = 1; - dev_err(&client->dev, - "Firmware error, no config sent!"); - return -EINVAL; - } - } - - for (i = 1; i < GOODIX_MAX_CFG_GROUP; i++) { - if (ts->pdata->config_data_len[i]) - break; - } - - if (i == GOODIX_MAX_CFG_GROUP) { - sensor_id = 0; - } else { - ret = gtp_i2c_read_dbl_check(ts->client, - GTP_REG_SENSOR_ID, &sensor_id, 1); - if (ret == SUCCESS) { - if (sensor_id >= GOODIX_MAX_CFG_GROUP) { - dev_err(&client->dev, - "Invalid sensor_id(0x%02X), No Config Sent!", - sensor_id); - return -EINVAL; - } - } else { - dev_err(&client->dev, - "Failed to get sensor_id, No config sent!"); - return -EINVAL; - } - } - - dev_info(&client->dev, "Sensor ID selected: %d", sensor_id); - - if (ts->pdata->config_data_len[sensor_id] < - GTP_CONFIG_MIN_LENGTH || - !ts->pdata->config_data[sensor_id]) { - dev_err(&client->dev, - "Sensor_ID(%d) matches with NULL or invalid config group!\n", - sensor_id); - return -EINVAL; - } - - ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA, - &opr_buf[0], 1); - if (ret == SUCCESS) { - if (opr_buf[0] < 90) { - /* backup group config version */ - grp_cfg_version = - ts->pdata-> - config_data[sensor_id][GTP_ADDR_LENGTH]; - ts->pdata-> - config_data[sensor_id][GTP_ADDR_LENGTH] - = 0x00; - ts->fixed_cfg = 0; - } else { - /* treated as fixed config, not send config */ - dev_warn(&client->dev, - "Ic fixed config with config version(%d, 0x%02X)", - opr_buf[0], opr_buf[0]); - ts->fixed_cfg = 1; - } - } else { - dev_err(&client->dev, - "Failed to get ic config version!No config sent!"); - return -EINVAL; - } - - config_data = ts->pdata->config_data[sensor_id]; - ts->config_data = ts->pdata->config_data[sensor_id]; - ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id]; - -#if GTP_CUSTOM_CFG - config_data[RESOLUTION_LOC] = - (unsigned char)(GTP_MAX_WIDTH && 0xFF); - config_data[RESOLUTION_LOC + 1] = - (unsigned char)(GTP_MAX_WIDTH >> 8); - config_data[RESOLUTION_LOC + 2] = - (unsigned char)(GTP_MAX_HEIGHT && 0xFF); - config_data[RESOLUTION_LOC + 3] = - (unsigned char)(GTP_MAX_HEIGHT >> 8); - - if (GTP_INT_TRIGGER == 0) - config_data[TRIGGER_LOC] &= 0xfe; - else if (GTP_INT_TRIGGER == 1) - config_data[TRIGGER_LOC] |= 0x01; -#endif /* !GTP_CUSTOM_CFG */ - - check_sum = 0; - for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) - check_sum += config_data[i]; - - config_data[ts->gtp_cfg_len] = (~check_sum) + 1; - - } else { /* DRIVER NOT SEND CONFIG */ - ts->gtp_cfg_len = GTP_CONFIG_MAX_LENGTH; - ret = gtp_i2c_read(ts->client, config_data, - ts->gtp_cfg_len + GTP_ADDR_LENGTH); - if (ret < 0) { - dev_err(&client->dev, - "Read Config Failed, Using DEFAULT Resolution & INT Trigger!\n"); - ts->abs_x_max = GTP_MAX_WIDTH; - ts->abs_y_max = GTP_MAX_HEIGHT; - ts->int_trigger_type = GTP_INT_TRIGGER; - } - } /* !DRIVER NOT SEND CONFIG */ - - if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0)) { - ts->abs_x_max = (config_data[RESOLUTION_LOC + 1] << 8) - + config_data[RESOLUTION_LOC]; - ts->abs_y_max = (config_data[RESOLUTION_LOC + 3] << 8) - + config_data[RESOLUTION_LOC + 2]; - ts->int_trigger_type = (config_data[TRIGGER_LOC]) & 0x03; - } - ret = gtp_send_cfg(ts); - if (ret < 0) - dev_err(&client->dev, "%s: Send config error.\n", __func__); - - msleep(20); - return ret; -} - -/******************************************************* -Function: - Read firmware version -Input: - client: i2c device - version: buffer to keep ic firmware version -Output: - read operation return. - 0: succeed, otherwise: failed -*******************************************************/ -static int gtp_read_fw_version(struct i2c_client *client, u16 *version) -{ - int ret = 0; - u8 buf[GTP_FW_VERSION_BUFFER_MAXSIZE] = { - GTP_REG_FW_VERSION >> 8, GTP_REG_FW_VERSION & 0xff }; - - ret = gtp_i2c_read(client, buf, sizeof(buf)); - if (ret < 0) { - dev_err(&client->dev, "GTP read version failed.\n"); - return -EIO; - } - - if (version) - *version = (buf[3] << 8) | buf[2]; - - return ret; -} -/* - * Function: - * Read and check chip id. - * Input: - * client: i2c device - * Output: - * read operation return. - * 0: succeed, otherwise: failed - */ -static int gtp_check_product_id(struct i2c_client *client) -{ - int ret = 0; - char product_id[GTP_PRODUCT_ID_MAXSIZE]; - struct goodix_ts_data *ts = i2c_get_clientdata(client); - /* 04 bytes are used for the Product-id in the register space.*/ - u8 buf[GTP_PRODUCT_ID_BUFFER_MAXSIZE] = { - GTP_REG_PRODUCT_ID >> 8, GTP_REG_PRODUCT_ID & 0xff }; - - ret = gtp_i2c_read(client, buf, sizeof(buf)); - if (ret < 0) { - dev_err(&client->dev, "GTP read product_id failed.\n"); - return -EIO; - } - - if (buf[5] == 0x00) { - /* copy (GTP_PRODUCT_ID_MAXSIZE - 1) from buffer. Ex: 915 */ - strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE - 1); - } else { - if (buf[5] == 'S' || buf[5] == 's') - chip_gt9xxs = 1; - /* copy GTP_PRODUCT_ID_MAXSIZE from buffer. Ex: 915s */ - strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE); - } - - dev_info(&client->dev, "Goodix Product ID = %s\n", product_id); - - ret = strcmp(product_id, ts->pdata->product_id); - if (ret != 0) - return -EINVAL; - - return ret; -} - -/******************************************************* -Function: - I2c test Function. -Input: - client:i2c client. -Output: - Executive outcomes. - 2: succeed, otherwise failed. -*******************************************************/ -static int gtp_i2c_test(struct i2c_client *client) -{ - u8 buf[3] = { GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff }; - int retry = GTP_I2C_RETRY_5; - int ret = -EIO; - - while (retry--) { - ret = gtp_i2c_read(client, buf, 3); - if (ret > 0) - return ret; - dev_err(&client->dev, "GTP i2c test failed time %d.\n", retry); - msleep(20); - } - return ret; -} - -/******************************************************* -Function: - Request gpio(INT & RST) ports. -Input: - ts: private data. -Output: - Executive outcomes. - = 0: succeed, != 0: failed -*******************************************************/ -static int gtp_request_io_port(struct goodix_ts_data *ts) -{ - struct i2c_client *client = ts->client; - struct goodix_ts_platform_data *pdata = ts->pdata; - int ret; - - if (gpio_is_valid(pdata->irq_gpio)) { - ret = gpio_request(pdata->irq_gpio, "goodix_ts_irq_gpio"); - if (ret) { - dev_err(&client->dev, "Unable to request irq gpio [%d]\n", - pdata->irq_gpio); - goto err_pwr_off; - } - ret = gpio_direction_input(pdata->irq_gpio); - if (ret) { - dev_err(&client->dev, "Unable to set direction for irq gpio [%d]\n", - pdata->irq_gpio); - goto err_free_irq_gpio; - } - } else { - dev_err(&client->dev, "Invalid irq gpio [%d]!\n", - pdata->irq_gpio); - ret = -EINVAL; - goto err_pwr_off; - } - - if (gpio_is_valid(pdata->reset_gpio)) { - ret = gpio_request(pdata->reset_gpio, "goodix_ts_reset_gpio"); - if (ret) { - dev_err(&client->dev, "Unable to request reset gpio [%d]\n", - pdata->reset_gpio); - goto err_free_irq_gpio; - } - - ret = gpio_direction_output(pdata->reset_gpio, 0); - if (ret) { - dev_err(&client->dev, "Unable to set direction for reset gpio [%d]\n", - pdata->reset_gpio); - goto err_free_reset_gpio; - } - } else { - dev_err(&client->dev, "Invalid irq gpio [%d]!\n", - pdata->reset_gpio); - ret = -EINVAL; - goto err_free_irq_gpio; - } - /* IRQ GPIO is an input signal, but we are setting it to output - * direction and pulling it down, to comply with power up timing - * requirements, mentioned in power up timing section of device - * datasheet. - */ - ret = gpio_direction_output(pdata->irq_gpio, 0); - if (ret) - dev_warn(&client->dev, - "pull down interrupt gpio failed\n"); - ret = gpio_direction_output(pdata->reset_gpio, 0); - if (ret) - dev_warn(&client->dev, - "pull down reset gpio failed\n"); - - return ret; - -err_free_reset_gpio: - if (gpio_is_valid(pdata->reset_gpio)) - gpio_free(pdata->reset_gpio); -err_free_irq_gpio: - if (gpio_is_valid(pdata->irq_gpio)) - gpio_free(pdata->irq_gpio); -err_pwr_off: - return ret; -} - -/******************************************************* -Function: - Request interrupt. -Input: - ts: private data. -Output: - Executive outcomes. - 0: succeed, -1: failed. -*******************************************************/ -static int gtp_request_irq(struct goodix_ts_data *ts) -{ - int ret; - const u8 irq_table[] = GTP_IRQ_TAB; - - dev_dbg(&ts->client->dev, "INT trigger type:%x, irq=%d", - ts->int_trigger_type, - ts->client->irq); - - ret = request_threaded_irq(ts->client->irq, NULL, - goodix_ts_irq_handler, - irq_table[ts->int_trigger_type], - ts->client->name, ts); - if (ret) { - ts->use_irq = false; - return ret; - } - gtp_irq_disable(ts); - ts->use_irq = true; - return 0; -} - -/******************************************************* -Function: - Request input device Function. -Input: - ts:private data. -Output: - Executive outcomes. - 0: succeed, otherwise: failed. -*******************************************************/ -static int gtp_request_input_dev(struct goodix_ts_data *ts) -{ - int ret; - char phys[PHY_BUF_SIZE]; - int index = 0; - - ts->input_dev = input_allocate_device(); - if (ts->input_dev == NULL) { - dev_err(&ts->client->dev, - "Failed to allocate input device.\n"); - return -ENOMEM; - } - - ts->input_dev->evbit[0] = - BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - set_bit(BTN_TOOL_FINGER, ts->input_dev->keybit); - __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); - /* in case of "out of memory" */ - input_mt_init_slots(ts->input_dev, 10, 0); - - if (ts->pdata->have_touch_key) { - for (index = 0; index < ts->pdata->num_button; index++) { - input_set_capability(ts->input_dev, - EV_KEY, ts->pdata->button_map[index]); - } - } - - if (ts->pdata->slide_wakeup) - input_set_capability(ts->input_dev, EV_KEY, KEY_POWER); - - if (ts->pdata->with_pen) { /* pen support */ - __set_bit(BTN_TOOL_PEN, ts->input_dev->keybit); - __set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); - __set_bit(INPUT_PROP_POINTER, ts->input_dev->propbit); - } - - if (ts->pdata->change_x2y) - swap(ts->abs_x_max, ts->abs_y_max); - - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, - 0, ts->abs_x_max, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, - 0, ts->abs_y_max, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, - 0, 255, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, - 0, 255, 0, 0); - input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, - 0, 255, 0, 0); - - snprintf(phys, PHY_BUF_SIZE, "input/ts"); - ts->input_dev->name = GOODIX_DEV_NAME; - ts->input_dev->phys = phys; - ts->input_dev->id.bustype = BUS_I2C; - ts->input_dev->id.vendor = 0xDEAD; - ts->input_dev->id.product = 0xBEEF; - ts->input_dev->id.version = 10427; - - ret = input_register_device(ts->input_dev); - if (ret) { - dev_err(&ts->client->dev, - "Register %s input device failed.\n", - ts->input_dev->name); - goto exit_free_inputdev; - } - - return 0; - -exit_free_inputdev: - input_free_device(ts->input_dev); - ts->input_dev = NULL; - return ret; -} - -static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA) -{ - return (regulator_count_voltages(reg) > 0) ? - regulator_set_load(reg, load_uA) : 0; -} - -/** - * goodix_power_on - Turn device power ON - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static int goodix_power_on(struct goodix_ts_data *ts) -{ - int ret; - - if (ts->power_on) { - dev_info(&ts->client->dev, - "Device already power on\n"); - return 0; - } - - if (!IS_ERR(ts->avdd)) { - ret = reg_set_optimum_mode_check(ts->avdd, - GOODIX_VDD_LOAD_MAX_UA); - if (ret < 0) { - dev_err(&ts->client->dev, - "Regulator avdd set_opt failed rc=%d\n", ret); - goto err_set_opt_avdd; - } - ret = regulator_enable(ts->avdd); - if (ret) { - dev_err(&ts->client->dev, - "Regulator avdd enable failed ret=%d\n", ret); - goto err_enable_avdd; - } - } - - if (!IS_ERR(ts->vdd)) { - ret = regulator_set_voltage(ts->vdd, GOODIX_VTG_MIN_UV, - GOODIX_VTG_MAX_UV); - if (ret) { - dev_err(&ts->client->dev, - "Regulator set_vtg failed vdd ret=%d\n", ret); - goto err_set_vtg_vdd; - } - ret = reg_set_optimum_mode_check(ts->vdd, - GOODIX_VDD_LOAD_MAX_UA); - if (ret < 0) { - dev_err(&ts->client->dev, - "Regulator vdd set_opt failed rc=%d\n", ret); - goto err_set_opt_vdd; - } - ret = regulator_enable(ts->vdd); - if (ret) { - dev_err(&ts->client->dev, - "Regulator vdd enable failed ret=%d\n", ret); - goto err_enable_vdd; - } - } - - if (!IS_ERR(ts->vcc_i2c)) { - ret = regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV, - GOODIX_I2C_VTG_MAX_UV); - if (ret) { - dev_err(&ts->client->dev, - "Regulator set_vtg failed vcc_i2c ret=%d\n", - ret); - goto err_set_vtg_vcc_i2c; - } - ret = reg_set_optimum_mode_check(ts->vcc_i2c, - GOODIX_VIO_LOAD_MAX_UA); - if (ret < 0) { - dev_err(&ts->client->dev, - "Regulator vcc_i2c set_opt failed rc=%d\n", - ret); - goto err_set_opt_vcc_i2c; - } - ret = regulator_enable(ts->vcc_i2c); - if (ret) { - dev_err(&ts->client->dev, - "Regulator vcc_i2c enable failed ret=%d\n", - ret); - regulator_disable(ts->vdd); - goto err_enable_vcc_i2c; - } - } - - ts->power_on = true; - return 0; - -err_enable_vcc_i2c: -err_set_opt_vcc_i2c: - if (!IS_ERR(ts->vcc_i2c)) - regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV); -err_set_vtg_vcc_i2c: - if (!IS_ERR(ts->vdd)) - regulator_disable(ts->vdd); -err_enable_vdd: -err_set_opt_vdd: - if (!IS_ERR(ts->vdd)) - regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); -err_set_vtg_vdd: - if (!IS_ERR(ts->avdd)) - regulator_disable(ts->avdd); -err_enable_avdd: -err_set_opt_avdd: - ts->power_on = false; - return ret; -} - -/** - * goodix_power_off - Turn device power OFF - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static int goodix_power_off(struct goodix_ts_data *ts) -{ - int ret; - - if (!ts->power_on) { - dev_info(&ts->client->dev, - "Device already power off\n"); - return 0; - } - - if (!IS_ERR(ts->vcc_i2c)) { - ret = regulator_set_voltage(ts->vcc_i2c, 0, - GOODIX_I2C_VTG_MAX_UV); - if (ret < 0) - dev_err(&ts->client->dev, - "Regulator vcc_i2c set_vtg failed ret=%d\n", - ret); - ret = regulator_disable(ts->vcc_i2c); - if (ret) - dev_err(&ts->client->dev, - "Regulator vcc_i2c disable failed ret=%d\n", - ret); - } - - if (!IS_ERR(ts->vdd)) { - ret = regulator_set_voltage(ts->vdd, 0, GOODIX_VTG_MAX_UV); - if (ret < 0) - dev_err(&ts->client->dev, - "Regulator vdd set_vtg failed ret=%d\n", ret); - ret = regulator_disable(ts->vdd); - if (ret) - dev_err(&ts->client->dev, - "Regulator vdd disable failed ret=%d\n", ret); - } - - if (!IS_ERR(ts->avdd)) { - ret = regulator_disable(ts->avdd); - if (ret) - dev_err(&ts->client->dev, - "Regulator avdd disable failed ret=%d\n", ret); - } - - ts->power_on = false; - return 0; -} - -/** - * goodix_power_init - Initialize device power - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static int goodix_power_init(struct goodix_ts_data *ts) -{ - int ret; - - ts->avdd = regulator_get(&ts->client->dev, "avdd"); - if (IS_ERR(ts->avdd)) { - ret = PTR_ERR(ts->avdd); - dev_info(&ts->client->dev, - "Regulator get failed avdd ret=%d\n", ret); - } - - ts->vdd = regulator_get(&ts->client->dev, "vdd"); - if (IS_ERR(ts->vdd)) { - ret = PTR_ERR(ts->vdd); - dev_info(&ts->client->dev, - "Regulator get failed vdd ret=%d\n", ret); - } - - ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc-i2c"); - if (IS_ERR(ts->vcc_i2c)) { - ret = PTR_ERR(ts->vcc_i2c); - dev_info(&ts->client->dev, - "Regulator get failed vcc_i2c ret=%d\n", ret); - } - - return 0; -} - -/** - * goodix_power_deinit - Deinitialize device power - * @ts: driver private data - * - * Returns zero on success, else an error. - */ -static int goodix_power_deinit(struct goodix_ts_data *ts) -{ - regulator_put(ts->vdd); - regulator_put(ts->vcc_i2c); - regulator_put(ts->avdd); - - return 0; -} - -static ssize_t gtp_fw_name_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - - if (!strlen(ts->fw_name)) - return snprintf(buf, GTP_FW_NAME_MAXSIZE - 1, - "No fw name has been given."); - else - return snprintf(buf, GTP_FW_NAME_MAXSIZE - 1, - "%s\n", ts->fw_name); -} - -static ssize_t gtp_fw_name_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - - if (size > GTP_FW_NAME_MAXSIZE - 1) { - dev_err(dev, "FW name size exceeds the limit."); - return -EINVAL; - } - - strlcpy(ts->fw_name, buf, size); - if (ts->fw_name[size-1] == '\n') - ts->fw_name[size-1] = '\0'; - - return size; -} - -static ssize_t gtp_fw_upgrade_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - - return snprintf(buf, 2, "%d\n", ts->fw_loading); -} - -static ssize_t gtp_fw_upgrade_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - unsigned int val; - int ret; - - if (size > 2) - return -EINVAL; - - ret = kstrtouint(buf, 10, &val); - if (ret) - return ret; - - if (ts->gtp_is_suspend) { - dev_err(&ts->client->dev, - "Can't start fw upgrade. Device is in suspend state"); - return -EBUSY; - } - - mutex_lock(&ts->input_dev->mutex); - if (!ts->fw_loading && val) { - disable_irq(ts->client->irq); - ts->fw_loading = true; - if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) { - ret = gup_update_proc(NULL); - if (ret == FAIL) - dev_err(&ts->client->dev, - "Fail to update GTP firmware\n"); - } - ts->fw_loading = false; - enable_irq(ts->client->irq); - } - mutex_unlock(&ts->input_dev->mutex); - - return size; -} - -static ssize_t gtp_force_fw_upgrade_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - unsigned int val; - int ret; - - if (size > 2) - return -EINVAL; - - ret = kstrtouint(buf, 10, &val); - if (ret) - return ret; - - if (ts->gtp_is_suspend) { - dev_err(&ts->client->dev, - "Can't start fw upgrade. Device is in suspend state."); - return -EBUSY; - } - - mutex_lock(&ts->input_dev->mutex); - if (!ts->fw_loading && val) { - disable_irq(ts->client->irq); - ts->fw_loading = true; - ts->force_update = true; - if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) { - ret = gup_update_proc(NULL); - if (ret == FAIL) - dev_err(&ts->client->dev, - "Fail to force update GTP firmware.\n"); - } - ts->force_update = false; - ts->fw_loading = false; - enable_irq(ts->client->irq); - } - mutex_unlock(&ts->input_dev->mutex); - - return size; -} - -static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR | S_IWGRP), - gtp_fw_name_show, - gtp_fw_name_store); -static DEVICE_ATTR(fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP), - gtp_fw_upgrade_show, - gtp_fw_upgrade_store); -static DEVICE_ATTR(force_fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP), - gtp_fw_upgrade_show, - gtp_force_fw_upgrade_store); - -static struct attribute *gtp_attrs[] = { - &dev_attr_fw_name.attr, - &dev_attr_fw_upgrade.attr, - &dev_attr_force_fw_upgrade.attr, - NULL -}; - -static const struct attribute_group gtp_attr_grp = { - .attrs = gtp_attrs, -}; - -static int gtp_debug_addr_is_valid(u16 addr) -{ - if (addr < GTP_VALID_ADDR_START || addr > GTP_VALID_ADDR_END) { - pr_err("GTP reg address is invalid: 0x%x\n", addr); - return false; - } - - return true; -} - -static int gtp_debug_data_set(void *_data, u64 val) -{ - struct goodix_ts_data *ts = _data; - - mutex_lock(&ts->input_dev->mutex); - if (gtp_debug_addr_is_valid(ts->addr)) - dev_err(&ts->client->dev, - "Writing to GTP registers not supported\n"); - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -static int gtp_debug_data_get(void *_data, u64 *val) -{ - struct goodix_ts_data *ts = _data; - int ret; - u8 buf[3] = {0}; - - mutex_lock(&ts->input_dev->mutex); - buf[0] = ts->addr >> 8; - buf[1] = ts->addr & 0x00ff; - - if (gtp_debug_addr_is_valid(ts->addr)) { - ret = gtp_i2c_read(ts->client, buf, 3); - if (ret < 0) - dev_err(&ts->client->dev, - "GTP read register 0x%x failed (%d)\n", - ts->addr, ret); - else - *val = buf[2]; - } - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, gtp_debug_data_get, - gtp_debug_data_set, "%llx\n"); - -static int gtp_debug_addr_set(void *_data, u64 val) -{ - struct goodix_ts_data *ts = _data; - - if (gtp_debug_addr_is_valid(val)) { - mutex_lock(&ts->input_dev->mutex); - ts->addr = val; - mutex_unlock(&ts->input_dev->mutex); - } - - return 0; -} - -static int gtp_debug_addr_get(void *_data, u64 *val) -{ - struct goodix_ts_data *ts = _data; - - mutex_lock(&ts->input_dev->mutex); - if (gtp_debug_addr_is_valid(ts->addr)) - *val = ts->addr; - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, gtp_debug_addr_get, - gtp_debug_addr_set, "%llx\n"); - -static int gtp_debug_suspend_set(void *_data, u64 val) -{ - struct goodix_ts_data *ts = _data; - - mutex_lock(&ts->input_dev->mutex); - if (val) - goodix_ts_suspend(&ts->client->dev); - else - goodix_ts_resume(&ts->client->dev); - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -static int gtp_debug_suspend_get(void *_data, u64 *val) -{ - struct goodix_ts_data *ts = _data; - - mutex_lock(&ts->input_dev->mutex); - *val = ts->gtp_is_suspend; - mutex_unlock(&ts->input_dev->mutex); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, gtp_debug_suspend_get, - gtp_debug_suspend_set, "%lld\n"); - -static int gtp_debugfs_init(struct goodix_ts_data *data) -{ - data->debug_base = debugfs_create_dir(GTP_DEBUGFS_DIR, NULL); - - if (IS_ERR_OR_NULL(data->debug_base)) { - dev_err(&data->client->dev, "Failed to create debugfs dir\n"); - return -EINVAL; - } - - if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_SUSPEND, - S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, - data->debug_base, - data, - &debug_suspend_fops)))) { - dev_err(&data->client->dev, "Failed to create suspend file\n"); - debugfs_remove_recursive(data->debug_base); - return -EINVAL; - } - - if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_DATA, - S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, - data->debug_base, - data, - &debug_data_fops)))) { - dev_err(&data->client->dev, "Failed to create data file\n"); - debugfs_remove_recursive(data->debug_base); - return -EINVAL; - } - - if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_ADDR, - S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP, - data->debug_base, - data, - &debug_addr_fops)))) { - dev_err(&data->client->dev, "Failed to create addr file\n"); - debugfs_remove_recursive(data->debug_base); - return -EINVAL; - } - - return 0; -} - -static int goodix_ts_get_dt_coords(struct device *dev, char *name, - struct goodix_ts_platform_data *pdata) -{ - struct property *prop; - struct device_node *np = dev->of_node; - int rc; - u32 coords[GOODIX_COORDS_ARR_SIZE]; - - prop = of_find_property(np, name, NULL); - if (!prop) - return -EINVAL; - if (!prop->value) - return -ENODATA; - - rc = of_property_read_u32_array(np, name, coords, - GOODIX_COORDS_ARR_SIZE); - if (rc && (rc != -EINVAL)) { - dev_err(dev, "Unable to read %s\n", name); - return rc; - } - - if (!strcmp(name, "goodix,panel-coords")) { - pdata->panel_minx = coords[0]; - pdata->panel_miny = coords[1]; - pdata->panel_maxx = coords[2]; - pdata->panel_maxy = coords[3]; - } else if (!strcmp(name, "goodix,display-coords")) { - pdata->x_min = coords[0]; - pdata->y_min = coords[1]; - pdata->x_max = coords[2]; - pdata->y_max = coords[3]; - } else { - dev_err(dev, "unsupported property %s\n", name); - return -EINVAL; - } - - return 0; -} - -static int goodix_parse_dt(struct device *dev, - struct goodix_ts_platform_data *pdata) -{ - int rc; - struct device_node *np = dev->of_node; - struct property *prop; - u32 temp_val, num_buttons; - u32 button_map[MAX_BUTTONS]; - char prop_name[PROP_NAME_SIZE]; - int i, read_cfg_num, temp; - - rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata); - if (rc && (rc != -EINVAL)) - return rc; - - rc = goodix_ts_get_dt_coords(dev, "goodix,display-coords", pdata); - if (rc) - return rc; - - pdata->i2c_pull_up = of_property_read_bool(np, - "goodix,i2c-pull-up"); - - pdata->force_update = of_property_read_bool(np, - "goodix,force-update"); - - pdata->enable_power_off = of_property_read_bool(np, - "goodix,enable-power-off"); - - pdata->have_touch_key = of_property_read_bool(np, - "goodix,have-touch-key"); - - pdata->driver_send_cfg = of_property_read_bool(np, - "goodix,driver-send-cfg"); - - pdata->change_x2y = of_property_read_bool(np, - "goodix,change-x2y"); - - pdata->with_pen = of_property_read_bool(np, - "goodix,with-pen"); - - pdata->slide_wakeup = of_property_read_bool(np, - "goodix,slide-wakeup"); - - pdata->dbl_clk_wakeup = of_property_read_bool(np, - "goodix,dbl_clk_wakeup"); - - /* reset, irq gpio info */ - pdata->reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", - 0, &pdata->reset_gpio_flags); - if (pdata->reset_gpio < 0) - return pdata->reset_gpio; - - pdata->irq_gpio = of_get_named_gpio_flags(np, "interrupt-gpios", - 0, &pdata->irq_gpio_flags); - if (pdata->irq_gpio < 0) - return pdata->irq_gpio; - - rc = of_property_read_string(np, "goodix,product-id", - &pdata->product_id); - if (rc && (rc != -EINVAL)) { - dev_err(dev, "Failed to parse product_id."); - return -EINVAL; - } - - rc = of_property_read_string(np, "goodix,fw_name", - &pdata->fw_name); - if (rc && (rc != -EINVAL)) { - dev_err(dev, "Failed to parse firmware name.\n"); - return -EINVAL; - } - - prop = of_find_property(np, "goodix,button-map", NULL); - if (prop) { - num_buttons = prop->length / sizeof(temp_val); - if (num_buttons > MAX_BUTTONS) - return -EINVAL; - - rc = of_property_read_u32_array(np, - "goodix,button-map", button_map, - num_buttons); - if (rc) { - dev_err(dev, "Unable to read key codes\n"); - return rc; - } - pdata->num_button = num_buttons; - memcpy(pdata->button_map, button_map, - pdata->num_button * sizeof(u32)); - } - - read_cfg_num = 0; - for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) { - temp = 0; - snprintf(prop_name, sizeof(prop_name), "goodix,cfg-data%d", i); - prop = of_find_property(np, prop_name, &temp); - if (!prop || !prop->value) { - pdata->config_data_len[i] = 0; - pdata->config_data[i] = NULL; - continue; - } - pdata->config_data_len[i] = temp; - pdata->config_data[i] = devm_kzalloc(dev, - GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, - GFP_KERNEL); - if (!pdata->config_data[i]) { - dev_err(dev, - "Not enough memory for panel config data %d\n", - i); - return -ENOMEM; - } - pdata->config_data[i][0] = GTP_REG_CONFIG_DATA >> 8; - pdata->config_data[i][1] = GTP_REG_CONFIG_DATA & 0xff; - memcpy(&pdata->config_data[i][GTP_ADDR_LENGTH], - prop->value, pdata->config_data_len[i]); - read_cfg_num++; - } - dev_dbg(dev, "%d config data read from device tree\n", read_cfg_num); - - return 0; -} - -/******************************************************* -Function: - I2c probe. -Input: - client: i2c device struct. - id: device id. -Output: - Executive outcomes. - 0: succeed. -*******************************************************/ - -static int goodix_ts_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct goodix_ts_platform_data *pdata; - struct goodix_ts_data *ts; - u16 version_info; - int ret; - - dev_dbg(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr); - if (client->dev.of_node) { - pdata = devm_kzalloc(&client->dev, - sizeof(struct goodix_ts_platform_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - ret = goodix_parse_dt(&client->dev, pdata); - if (ret) - return ret; - } else { - pdata = client->dev.platform_data; - } - - if (!pdata) { - dev_err(&client->dev, "GTP invalid pdata\n"); - return -EINVAL; - } - - i2c_connect_client = client; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - dev_err(&client->dev, "GTP I2C not supported\n"); - return -ENODEV; - } - - ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL); - if (!ts) - return -ENOMEM; - - memset(ts, 0, sizeof(*ts)); - ts->client = client; - ts->pdata = pdata; - /* For 2.6.39 & later use spin_lock_init(&ts->irq_lock) - * For 2.6.39 & before, use ts->irq_lock = SPIN_LOCK_UNLOCKED - */ - spin_lock_init(&ts->irq_lock); - i2c_set_clientdata(client, ts); - ts->gtp_rawdiff_mode = 0; - ts->power_on = false; - - ret = gtp_request_io_port(ts); - if (ret) { - dev_err(&client->dev, "GTP request IO port failed.\n"); - goto exit_free_client_data; - } - - ret = goodix_power_init(ts); - if (ret) { - dev_err(&client->dev, "GTP power init failed\n"); - goto exit_free_io_port; - } - - ret = goodix_power_on(ts); - if (ret) { - dev_err(&client->dev, "GTP power on failed\n"); - goto exit_deinit_power; - } - - gtp_reset_guitar(ts, 20); - - ret = gtp_i2c_test(client); - if (ret != 2) { - dev_err(&client->dev, "I2C communication ERROR\n"); - goto exit_power_off; - } - - if (pdata->force_update) - ts->force_update = true; - - if (pdata->fw_name) - strlcpy(ts->fw_name, pdata->fw_name, - strlen(pdata->fw_name) + 1); - - if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) { - ret = gup_init_update_proc(ts); - if (ret < 0) { - dev_err(&client->dev, - "GTP Create firmware update thread error\n"); - goto exit_power_off; - } - } - ret = gtp_init_panel(ts); - if (ret < 0) { - dev_err(&client->dev, "GTP init panel failed\n"); - ts->abs_x_max = GTP_MAX_WIDTH; - ts->abs_y_max = GTP_MAX_HEIGHT; - ts->int_trigger_type = GTP_INT_TRIGGER; - } - - ret = gtp_request_input_dev(ts); - if (ret) { - dev_err(&client->dev, "GTP request input dev failed\n"); - goto exit_free_inputdev; - } - input_set_drvdata(ts->input_dev, ts); - - mutex_init(&ts->lock); -#if defined(CONFIG_FB) - ts->fb_notif.notifier_call = fb_notifier_callback; - ret = fb_register_client(&ts->fb_notif); - if (ret) - dev_err(&ts->client->dev, - "Unable to register fb_notifier: %d\n", - ret); -#elif defined(CONFIG_HAS_EARLYSUSPEND) - ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; - ts->early_suspend.suspend = goodix_ts_early_suspend; - ts->early_suspend.resume = goodix_ts_late_resume; - register_early_suspend(&ts->early_suspend); -#endif - - ts->goodix_wq = create_singlethread_workqueue("goodix_wq"); - INIT_WORK(&ts->work, goodix_ts_work_func); - - ret = gtp_request_irq(ts); - if (ret) - dev_info(&client->dev, "GTP request irq failed %d\n", ret); - else - dev_info(&client->dev, "GTP works in interrupt mode\n"); - - ret = gtp_read_fw_version(client, &version_info); - if (ret != 2) - dev_err(&client->dev, "GTP firmware version read failed\n"); - - ret = gtp_check_product_id(client); - if (ret != 0) { - dev_err(&client->dev, "GTP Product id doesn't match\n"); - goto exit_free_irq; - } - if (ts->use_irq) - gtp_irq_enable(ts); - -#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG - init_wr_node(client); -#endif - -#if GTP_ESD_PROTECT - gtp_esd_switch(client, SWITCH_ON); -#endif - ret = sysfs_create_group(&client->dev.kobj, >p_attr_grp); - if (ret < 0) { - dev_err(&client->dev, "sys file creation failed\n"); - goto exit_free_irq; - } - - ret = gtp_debugfs_init(ts); - if (ret != 0) - goto exit_remove_sysfs; - - init_done = true; - return 0; -exit_free_irq: - mutex_destroy(&ts->lock); -#if defined(CONFIG_FB) - if (fb_unregister_client(&ts->fb_notif)) - dev_err(&client->dev, - "Error occurred while unregistering fb_notifier\n"); -#elif defined(CONFIG_HAS_EARLYSUSPEND) - unregister_early_suspend(&ts->early_suspend); -#endif - if (ts->use_irq) - free_irq(client->irq, ts); - cancel_work_sync(&ts->work); - flush_workqueue(ts->goodix_wq); - destroy_workqueue(ts->goodix_wq); - - input_unregister_device(ts->input_dev); - if (ts->input_dev) { - input_free_device(ts->input_dev); - ts->input_dev = NULL; - } -exit_remove_sysfs: - sysfs_remove_group(&ts->input_dev->dev.kobj, >p_attr_grp); -exit_free_inputdev: - kfree(ts->config_data); -exit_power_off: - goodix_power_off(ts); -exit_deinit_power: - goodix_power_deinit(ts); -exit_free_io_port: - if (gpio_is_valid(pdata->reset_gpio)) - gpio_free(pdata->reset_gpio); - if (gpio_is_valid(pdata->irq_gpio)) - gpio_free(pdata->irq_gpio); -exit_free_client_data: - i2c_set_clientdata(client, NULL); - return ret; -} - -/******************************************************* -Function: - Goodix touchscreen driver release function. -Input: - client: i2c device struct. -Output: - Executive outcomes. 0---succeed. -*******************************************************/ -static int goodix_ts_remove(struct i2c_client *client) -{ - struct goodix_ts_data *ts = i2c_get_clientdata(client); - - sysfs_remove_group(&ts->input_dev->dev.kobj, >p_attr_grp); - -#if defined(CONFIG_FB) - if (fb_unregister_client(&ts->fb_notif)) - dev_err(&client->dev, - "Error occurred while unregistering fb_notifier\n"); -#elif defined(CONFIG_HAS_EARLYSUSPEND) - unregister_early_suspend(&ts->early_suspend); -#endif - mutex_destroy(&ts->lock); - -#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG - uninit_wr_node(); -#endif - -#if GTP_ESD_PROTECT - cancel_work_sync(gtp_esd_check_workqueue); - flush_workqueue(gtp_esd_check_workqueue); - destroy_workqueue(gtp_esd_check_workqueue); -#endif - - if (ts) { - if (ts->use_irq) - free_irq(client->irq, ts); - - cancel_work_sync(&ts->work); - flush_workqueue(ts->goodix_wq); - destroy_workqueue(ts->goodix_wq); - - input_unregister_device(ts->input_dev); - if (ts->input_dev) { - input_free_device(ts->input_dev); - ts->input_dev = NULL; - } - - if (gpio_is_valid(ts->pdata->reset_gpio)) - gpio_free(ts->pdata->reset_gpio); - if (gpio_is_valid(ts->pdata->irq_gpio)) - gpio_free(ts->pdata->irq_gpio); - - goodix_power_off(ts); - goodix_power_deinit(ts); - i2c_set_clientdata(client, NULL); - } - debugfs_remove_recursive(ts->debug_base); - - return 0; -} - -#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_FB) -/******************************************************* -Function: - Early suspend function. -Input: - h: early_suspend struct. -Output: - None. -*******************************************************/ -static int goodix_ts_suspend(struct device *dev) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - int ret = 0, i; - - if (ts->gtp_is_suspend) { - dev_dbg(&ts->client->dev, "Already in suspend state\n"); - return 0; - } - - mutex_lock(&ts->lock); - - if (ts->fw_loading) { - dev_info(&ts->client->dev, - "Fw upgrade in progress, can't go to suspend."); - mutex_unlock(&ts->lock); - return 0; - } - -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_OFF); -#endif - - if (ts->pdata->slide_wakeup) { - ret = gtp_enter_doze(ts); - } else { - if (ts->use_irq) - gtp_irq_disable(ts); - - for (i = 0; i < GTP_MAX_TOUCH; i++) - gtp_touch_up(ts, i); - - input_sync(ts->input_dev); - - ret = gtp_enter_sleep(ts); - if (ret < 0) - dev_err(&ts->client->dev, "GTP early suspend failed.\n"); - } - /* to avoid waking up while not sleeping, - * delay 48 + 10ms to ensure reliability - */ - msleep(58); - mutex_unlock(&ts->lock); - ts->gtp_is_suspend = 1; - - return ret; -} - -/******************************************************* -Function: - Late resume function. -Input: - h: early_suspend struct. -Output: - None. -*******************************************************/ -static int goodix_ts_resume(struct device *dev) -{ - struct goodix_ts_data *ts = dev_get_drvdata(dev); - int ret = 0; - - if (!ts->gtp_is_suspend) { - dev_dbg(&ts->client->dev, "Already in awake state\n"); - return 0; - } - - mutex_lock(&ts->lock); - ret = gtp_wakeup_sleep(ts); - - if (ts->pdata->slide_wakeup) - doze_status = DOZE_DISABLED; - - if (ret <= 0) - dev_err(&ts->client->dev, "GTP resume failed\n"); - - if (ts->use_irq) - gtp_irq_enable(ts); - -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_ON); -#endif - mutex_unlock(&ts->lock); - ts->gtp_is_suspend = 0; - - return ret; -} - -#if defined(CONFIG_FB) -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct fb_event *evdata = data; - int *blank; - struct goodix_ts_data *ts = - container_of(self, struct goodix_ts_data, fb_notif); - - if (evdata && evdata->data && event == FB_EVENT_BLANK && - ts && ts->client) { - blank = evdata->data; - if (*blank == FB_BLANK_UNBLANK) - goodix_ts_resume(&ts->client->dev); - else if (*blank == FB_BLANK_POWERDOWN) - goodix_ts_suspend(&ts->client->dev); - } - - return 0; -} -#elif defined(CONFIG_HAS_EARLYSUSPEND) -/* - * Function: - * Early suspend function. - * Input: - * h: early_suspend struct. - * Output: - * None. - */ -static void goodix_ts_early_suspend(struct early_suspend *h) -{ - struct goodix_ts_data *ts; - - ts = container_of(h, struct goodix_ts_data, early_suspend); - goodix_ts_suspend(&ts->client->dev); - return; -} - -/* - * Function: - * Late resume function. - * Input: - * h: early_suspend struct. - * Output: - * None. - */ -static void goodix_ts_late_resume(struct early_suspend *h) -{ - struct goodix_ts_data *ts; - - ts = container_of(h, struct goodix_ts_data, early_suspend); - goodix_ts_late_resume(ts); -} -#endif -#endif /* !CONFIG_HAS_EARLYSUSPEND && !CONFIG_FB*/ - -#if GTP_ESD_PROTECT -/* - * Function: - * switch on & off esd delayed work - * Input: - * client: i2c device - * on: SWITCH_ON / SWITCH_OFF - * Output: - * void - */ -void gtp_esd_switch(struct i2c_client *client, int on) -{ - struct goodix_ts_data *ts; - - ts = i2c_get_clientdata(client); - if (on == SWITCH_ON) { - /* switch on esd */ - if (!ts->esd_running) { - ts->esd_running = 1; - dev_dbg(&client->dev, "Esd started\n"); - queue_delayed_work(gtp_esd_check_workqueue, - >p_esd_check_work, GTP_ESD_CHECK_CIRCLE); - } - } else { - /* switch off esd */ - if (ts->esd_running) { - ts->esd_running = 0; - dev_dbg(&client->dev, "Esd cancelled\n"); - cancel_delayed_work_sync(>p_esd_check_work); - } - } -} - -/******************************************************* -Function: - Initialize external watchdog for esd protect -Input: - client: i2c device. -Output: - result of i2c write operation. - 1: succeed, otherwise: failed -*********************************************************/ -static int gtp_init_ext_watchdog(struct i2c_client *client) -{ - /* in case of recursively reset by calling gtp_i2c_write*/ - struct i2c_msg msg; - u8 opr_buffer[4] = {0x80, 0x40, 0xAA, 0xAA}; - int ret; - int retries = 0; - - msg.flags = !I2C_M_RD; - msg.addr = client->addr; - msg.len = 4; - msg.buf = opr_buffer; - - while (retries < GTP_I2C_RETRY_5) { - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret == 1) - return 1; - retries++; - } - if (retries == GTP_I2C_RETRY_5) - dev_err(&client->dev, "init external watchdog failed!"); - return 0; -} - -/******************************************************* -Function: - Esd protect function. - Added external watchdog by meta, 2013/03/07 -Input: - work: delayed work -Output: - None. -*******************************************************/ -static void gtp_esd_check_func(struct work_struct *work) -{ - s32 retry; - s32 ret = -1; - struct goodix_ts_data *ts = NULL; - u8 test[4] = {0x80, 0x40}; - - ts = i2c_get_clientdata(i2c_connect_client); - - if (ts->gtp_is_suspend) { - dev_dbg(&ts->client->dev, "Esd terminated!\n"); - ts->esd_running = 0; - return; - } -#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE - if (ts->enter_update) - return; -#endif - - for (retry = 0; retry < GTP_I2C_RETRY_3; retry++) { - ret = gtp_i2c_read(ts->client, test, 4); - - if ((ret < 0)) { - /* IC works abnormally..*/ - continue; - } else { - if ((test[2] == 0xAA) || (test[3] != 0xAA)) { - /* IC works abnormally..*/ - retry = GTP_I2C_RETRY_3; - break; - } - /* IC works normally, Write 0x8040 0xAA*/ - test[2] = 0xAA; - gtp_i2c_write(ts->client, test, 3); - break; - } - } - if (retry == GTP_I2C_RETRY_3) { - dev_err(&ts->client->dev, - "IC Working ABNORMALLY, Resetting Guitar...\n"); - gtp_reset_guitar(ts, 50); - } - - if (!ts->gtp_is_suspend) - queue_delayed_work(gtp_esd_check_workqueue, - >p_esd_check_work, GTP_ESD_CHECK_CIRCLE); - else { - dev_dbg(&ts->client->dev, "Esd terminated!\n"); - ts->esd_running = 0; - } - - return; -} -#endif - -#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)) -static const struct dev_pm_ops goodix_ts_dev_pm_ops = { - .suspend = goodix_ts_suspend, - .resume = goodix_ts_resume, -}; -#else -static const struct dev_pm_ops goodix_ts_dev_pm_ops = { -}; -#endif - -static const struct i2c_device_id goodix_ts_id[] = { - { GTP_I2C_NAME, 0 }, - { } -}; - -static const struct of_device_id goodix_match_table[] = { - { .compatible = "goodix,gt9xx", }, - { }, -}; - -static struct i2c_driver goodix_ts_driver = { - .probe = goodix_ts_probe, - .remove = goodix_ts_remove, -#ifdef CONFIG_HAS_EARLYSUSPEND - .suspend = goodix_ts_early_suspend, - .resume = goodix_ts_late_resume, -#endif - .id_table = goodix_ts_id, - .driver = { - .name = GTP_I2C_NAME, - .owner = THIS_MODULE, - .of_match_table = goodix_match_table, -#if CONFIG_PM - .pm = &goodix_ts_dev_pm_ops, -#endif - }, -}; - -/******************************************************* -Function: - Driver Install function. -Input: - None. -Output: - Executive Outcomes. 0---succeed. -********************************************************/ -static int __init goodix_ts_init(void) -{ - int ret; - -#if GTP_ESD_PROTECT - INIT_DELAYED_WORK(>p_esd_check_work, gtp_esd_check_func); - gtp_esd_check_workqueue = create_workqueue("gtp_esd_check"); -#endif - ret = i2c_add_driver(&goodix_ts_driver); - return ret; -} - -/******************************************************* -Function: - Driver uninstall function. -Input: - None. -Output: - Executive Outcomes. 0---succeed. -********************************************************/ -static void __exit goodix_ts_exit(void) -{ - i2c_del_driver(&goodix_ts_driver); -} - -module_init(goodix_ts_init); -module_exit(goodix_ts_exit); - -MODULE_DESCRIPTION("GTP Series Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h deleted file mode 100644 index 1e85e2fce276..000000000000 --- a/drivers/input/touchscreen/gt9xx/gt9xx.h +++ /dev/null @@ -1,220 +0,0 @@ -/* drivers/input/touchscreen/gt9xx.h - * - * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved. - * - * 2010 - 2013 Goodix Technology. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be a reference - * to you, when you are integrating the GOODiX's CTP IC into your system, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - */ - -#ifndef _GOODIX_GT9XX_H_ -#define _GOODIX_GT9XX_H_ - -#include -#include -#include -#include -#include - -#if defined(CONFIG_FB) -#include -#include -#elif defined(CONFIG_HAS_EARLYSUSPEND) -#include -#define GOODIX_SUSPEND_LEVEL 1 -#endif - -#define MAX_BUTTONS 4 -#define GOODIX_MAX_CFG_GROUP 6 -#define GTP_FW_NAME_MAXSIZE 50 - -struct goodix_ts_platform_data { - int irq_gpio; - u32 irq_gpio_flags; - int reset_gpio; - u32 reset_gpio_flags; - const char *product_id; - const char *fw_name; - u32 x_max; - u32 y_max; - u32 x_min; - u32 y_min; - u32 panel_minx; - u32 panel_miny; - u32 panel_maxx; - u32 panel_maxy; - bool force_update; - bool i2c_pull_up; - bool enable_power_off; - size_t config_data_len[GOODIX_MAX_CFG_GROUP]; - u8 *config_data[GOODIX_MAX_CFG_GROUP]; - u32 button_map[MAX_BUTTONS]; - u8 num_button; - bool have_touch_key; - bool driver_send_cfg; - bool change_x2y; - bool with_pen; - bool slide_wakeup; - bool dbl_clk_wakeup; -}; -struct goodix_ts_data { - spinlock_t irq_lock; - struct i2c_client *client; - struct input_dev *input_dev; - struct goodix_ts_platform_data *pdata; - struct hrtimer timer; - struct workqueue_struct *goodix_wq; - struct work_struct work; - char fw_name[GTP_FW_NAME_MAXSIZE]; - struct delayed_work goodix_update_work; - s32 irq_is_disabled; - s32 use_irq; - u16 abs_x_max; - u16 abs_y_max; - u16 addr; - u8 max_touch_num; - u8 int_trigger_type; - u8 green_wake_mode; - u8 chip_type; - u8 *config_data; - u8 enter_update; - u8 gtp_is_suspend; - u8 gtp_rawdiff_mode; - u8 gtp_cfg_len; - u8 fixed_cfg; - u8 esd_running; - u8 fw_error; - bool power_on; - struct mutex lock; - bool fw_loading; - bool force_update; - struct regulator *avdd; - struct regulator *vdd; - struct regulator *vcc_i2c; -#if defined(CONFIG_FB) - struct notifier_block fb_notif; -#elif defined(CONFIG_HAS_EARLYSUSPEND) - struct early_suspend early_suspend; -#endif - struct dentry *debug_base; -}; - -extern u16 show_len; -extern u16 total_len; - -/***************************PART1:ON/OFF define*******************************/ -#define GTP_CUSTOM_CFG 0 -#define GTP_ESD_PROTECT 0 - -#define GTP_IRQ_TAB {\ - IRQ_TYPE_EDGE_RISING,\ - IRQ_TYPE_EDGE_FALLING,\ - IRQ_TYPE_LEVEL_LOW,\ - IRQ_TYPE_LEVEL_HIGH\ - } - - -#define GTP_IRQ_TAB_RISING 0 -#define GTP_IRQ_TAB_FALLING 1 -#if GTP_CUSTOM_CFG -#define GTP_MAX_HEIGHT 800 -#define GTP_MAX_WIDTH 480 -#define GTP_INT_TRIGGER GTP_IRQ_TAB_RISING -#else -#define GTP_MAX_HEIGHT 4096 -#define GTP_MAX_WIDTH 4096 -#define GTP_INT_TRIGGER GTP_IRQ_TAB_FALLING -#endif - -#define GTP_PRODUCT_ID_MAXSIZE 5 -#define GTP_PRODUCT_ID_BUFFER_MAXSIZE 6 -#define GTP_FW_VERSION_BUFFER_MAXSIZE 4 -#define GTP_MAX_TOUCH 5 -#define GTP_ESD_CHECK_CIRCLE 2000 /* jiffy: ms */ - -/***************************PART3:OTHER define*********************************/ -#define GTP_DRIVER_VERSION "V1.8.1<2013/09/01>" -#define GTP_I2C_NAME "Goodix-TS" -#define GTP_POLL_TIME 10 /* jiffy: ms*/ -#define GTP_ADDR_LENGTH 2 -#define GTP_CONFIG_MIN_LENGTH 186 -#define GTP_CONFIG_MAX_LENGTH 240 -#define FAIL 0 -#define SUCCESS 1 -#define SWITCH_OFF 0 -#define SWITCH_ON 1 - -/* Registers define */ -#define GTP_READ_COOR_ADDR 0x814E -#define GTP_REG_SLEEP 0x8040 -#define GTP_REG_SENSOR_ID 0x814A -#define GTP_REG_CONFIG_DATA 0x8047 -#define GTP_REG_FW_VERSION 0x8144 -#define GTP_REG_PRODUCT_ID 0x8140 - -#define GTP_I2C_RETRY_3 3 -#define GTP_I2C_RETRY_5 5 -#define GTP_I2C_RETRY_10 10 - -#define RESOLUTION_LOC 3 -#define TRIGGER_LOC 8 - -/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */ -#define GTP_I2C_ADDRESS_HIGH 0x14 -#define GTP_I2C_ADDRESS_LOW 0x5D -#define GTP_VALID_ADDR_START 0x8040 -#define GTP_VALID_ADDR_END 0x8177 - -/* GTP CM_HEAD RW flags */ -#define GTP_RW_READ 0 -#define GTP_RW_WRITE 1 -#define GTP_RW_READ_IC_TYPE 2 -#define GTP_RW_WRITE_IC_TYPE 3 -#define GTP_RW_FILL_INFO 4 -#define GTP_RW_NO_WRITE 5 -#define GTP_RW_READ_ERROR 6 -#define GTP_RW_DISABLE_IRQ 7 -#define GTP_RW_READ_VERSION 8 -#define GTP_RW_ENABLE_IRQ 9 -#define GTP_RW_ENTER_UPDATE_MODE 11 -#define GTP_RW_LEAVE_UPDATE_MODE 13 -#define GTP_RW_UPDATE_FW 15 -#define GTP_RW_CHECK_RAWDIFF_MODE 17 - -/* GTP need flag or interrupt */ -#define GTP_NO_NEED 0 -#define GTP_NEED_FLAG 1 -#define GTP_NEED_INTERRUPT 2 - -/*****************************End of Part III********************************/ - -void gtp_esd_switch(struct i2c_client *client, int on); - -int gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr, - u8 *rxbuf, int len); -int gtp_send_cfg(struct goodix_ts_data *ts); -void gtp_reset_guitar(struct goodix_ts_data *ts, int ms); -void gtp_irq_disable(struct goodix_ts_data *ts); -void gtp_irq_enable(struct goodix_ts_data *ts); - -#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG -s32 init_wr_node(struct i2c_client *client); -void uninit_wr_node(void); -#endif - -u8 gup_init_update_proc(struct goodix_ts_data *ts); -s32 gup_enter_update_mode(struct i2c_client *client); -void gup_leave_update_mode(struct i2c_client *client); -s32 gup_update_proc(void *dir); -extern struct i2c_client *i2c_connect_client; -#endif /* _GOODIX_GT9XX_H_ */ diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c deleted file mode 100644 index 6bc243492272..000000000000 --- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c +++ /dev/null @@ -1,1530 +0,0 @@ -/* drivers/input/touchscreen/gt9xx_update.c - * - * 2010 - 2012 Goodix Technology. - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be a reference - * to you, when you are integrating the GOODiX's CTP IC into your system, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * Latest Version:1.6 - * Author: andrew@goodix.com - * Revision Record: - * V1.0: - * first release. By Andrew, 2012/08/31 - * V1.2: - * add force update,GT9110P pid map. By Andrew, 2012/10/15 - * V1.4: - * 1. add config auto update function; - * 2. modify enter_update_mode; - * 3. add update file cal checksum. - * By Andrew, 2012/12/12 - * V1.6: - * 1. replace guitar_client with i2c_connect_client; - * 2. support firmware header array update. - * By Meta, 2013/03/11 - */ -#include "gt9xx.h" -#include -#include -#include - -#define FIRMWARE_NAME_LEN_MAX 256 - -#define GUP_REG_HW_INFO 0x4220 -#define GUP_REG_FW_MSG 0x41E4 -#define GUP_REG_PID_VID 0x8140 - -#define GOODIX_FIRMWARE_FILE_NAME "_goodix_update_.bin" -#define GOODIX_CONFIG_FILE_NAME "_goodix_config_.cfg" - -#define FW_HEAD_LENGTH 14 -#define FW_SECTION_LENGTH 0x2000 -#define FW_DSP_ISP_LENGTH 0x1000 -#define FW_DSP_LENGTH 0x1000 -#define FW_BOOT_LENGTH 0x800 - -#define PACK_SIZE 256 -#define MAX_FRAME_CHECK_TIME 5 - -#define _bRW_MISCTL__SRAM_BANK 0x4048 -#define _bRW_MISCTL__MEM_CD_EN 0x4049 -#define _bRW_MISCTL__CACHE_EN 0x404B -#define _bRW_MISCTL__TMR0_EN 0x40B0 -#define _rRW_MISCTL__SWRST_B0_ 0x4180 -#define _bWO_MISCTL__CPU_SWRST_PULSE 0x4184 -#define _rRW_MISCTL__BOOTCTL_B0_ 0x4190 -#define _rRW_MISCTL__BOOT_OPT_B0_ 0x4218 -#define _rRW_MISCTL__BOOT_CTL_ 0x5094 - -#define FAIL 0 -#define SUCCESS 1 - -#define RESET_DELAY_US 20000 - -struct st_fw_head { - u8 hw_info[4]; /* hardware info */ - u8 pid[8]; /* product id */ - u16 vid; /* version id */ -} __packed; - -struct st_update_msg { - u8 force_update; - u8 fw_flag; - bool need_free; - u8 *fw_data; - u32 fw_len; - struct st_fw_head ic_fw_msg; -}; - -static struct st_update_msg update_msg; -u16 show_len; -u16 total_len; -u8 got_file_flag; -u8 searching_file; -/******************************************************* -Function: - Read data from the i2c slave device. -Input: - client: i2c device. - buf[0~1]: read start address. - buf[2~len-1]: read data buffer. - len: GTP_ADDR_LENGTH + read bytes count -Output: - numbers of i2c_msgs to transfer: - 2: succeed, otherwise: failed -*********************************************************/ -static s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len) -{ - s32 ret = -1; - u8 retries = 0; - struct i2c_msg msgs[2] = { - { - .flags = !I2C_M_RD, - .addr = client->addr, - .len = GTP_ADDR_LENGTH, - .buf = &buf[0], - }, - { - .flags = I2C_M_RD, - .addr = client->addr, - .len = len - GTP_ADDR_LENGTH, - .buf = &buf[GTP_ADDR_LENGTH], - }, - }; - - while (retries < 5) { - ret = i2c_transfer(client->adapter, msgs, 2); - if (ret == 2) - break; - retries++; - } - - if (retries == 5) { - dev_err(&client->dev, "I2C read retry limit over.\n"); - ret = -EIO; - } - - return ret; -} - -/******************************************************* -Function: - Write data to the i2c slave device. -Input: - client: i2c device. - buf[0~1]: write start address. - buf[2~len-1]: data buffer - len: GTP_ADDR_LENGTH + write bytes count -Output: - numbers of i2c_msgs to transfer: - 1: succeed, otherwise: failed -*********************************************************/ -s32 gup_i2c_write(struct i2c_client *client, u8 *buf, s32 len) -{ - s32 ret = -1; - u8 retries = 0; - struct i2c_msg msg = { - .flags = !I2C_M_RD, - .addr = client->addr, - .len = len, - .buf = buf, - }; - - while (retries < 5) { - ret = i2c_transfer(client->adapter, &msg, 1); - if (ret == 1) - break; - retries++; - } - - if (retries == 5) { - dev_err(&client->dev, "I2C write retry limit over\n"); - ret = -EIO; - } - - return ret; -} - -static s32 gup_init_panel(struct goodix_ts_data *ts) -{ - struct i2c_client *client = ts->client; - u8 *config_data; - s32 ret = 0; - s32 i = 0; - u8 check_sum = 0; - u8 opr_buf[16]; - u8 sensor_id = 0; - - for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) - if (ts->pdata->config_data_len[i]) - break; - - if (i == GOODIX_MAX_CFG_GROUP) { - sensor_id = 0; - } else { - ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID, - &sensor_id, 1); - if (ret == SUCCESS) { - if (sensor_id >= GOODIX_MAX_CFG_GROUP) { - pr_err("Invalid sensor_id(0x%02X), No Config Sent", - sensor_id); - return -EINVAL; - } - } else { - pr_err("Failed to get sensor_id, No config sent\n"); - return -EINVAL; - } - } - - pr_debug("Sensor ID selected: %d", sensor_id); - - if (ts->pdata->config_data_len[sensor_id] < GTP_CONFIG_MIN_LENGTH || - !ts->pdata->config_data_len[sensor_id]) { - pr_err("Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP", - sensor_id); - return -EINVAL; - } - - ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA, - &opr_buf[0], 1); - if (ret == SUCCESS) { - pr_debug("CFG_GROUP%d Config Version: %d, IC Config Version: %d", - sensor_id + 1, - ts->pdata->config_data[sensor_id][0], - opr_buf[0]); - - ts->pdata->config_data[sensor_id][0] = opr_buf[0]; - ts->fixed_cfg = 0; - } else { - pr_err("Failed to get ic config version. No config sent"); - return -EINVAL; - } - - config_data = ts->pdata->config_data[sensor_id]; - ts->config_data = ts->pdata->config_data[sensor_id]; - ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id]; - - pr_debug("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x\n", - ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type); - - config_data[RESOLUTION_LOC] = (u8)GTP_MAX_WIDTH; - config_data[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8); - config_data[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT; - config_data[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8); - - if (GTP_INT_TRIGGER == 0) /* RISING */ - config_data[TRIGGER_LOC] &= 0xfe; - else if (GTP_INT_TRIGGER == 1) /* FALLING */ - config_data[TRIGGER_LOC] |= 0x01; - - check_sum = 0; - for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++) - check_sum += config_data[i]; - - config_data[ts->gtp_cfg_len] = (~check_sum) + 1; - - ret = gtp_send_cfg(ts); - if (ret < 0) - pr_err("Send config error\n"); - - ts->config_data = NULL; - ts->gtp_cfg_len = 0; - msleep(20); - return 0; -} - -static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len) -{ - u8 i = 0; - - msg[0] = (addr >> 8) & 0xff; - msg[1] = addr & 0xff; - - for (i = 0; i < 5; i++) - if (gup_i2c_read(client, msg, GTP_ADDR_LENGTH + len) > 0) - break; - - if (i >= 5) { - pr_err("Read data from 0x%02x%02x failed\n", msg[0], msg[1]); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val) -{ - u8 i = 0; - u8 msg[3] = { - (addr >> 8) & 0xff, - addr & 0xff, - val, - }; - - for (i = 0; i < 5; i++) - if (gup_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0) - break; - - if (i >= 5) { - pr_err("Set data to 0x%02x%02x failed\n", msg[0], msg[1]); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_get_ic_fw_msg(struct i2c_client *client) -{ - s32 ret = -1; - u8 retry = 0; - u8 buf[16]; - u8 i; - - /* step1:get hardware info */ - ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO, - &buf[GTP_ADDR_LENGTH], 4); - if (ret == FAIL) { - pr_err("get hw_info failed,exit"); - return FAIL; - } - - /* buf[2~5]: 00 06 90 00 */ - /* hw_info: 00 90 06 00 */ - for (i = 0; i < 4; i++) - update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i]; - - pr_debug("IC Hardware info:%02x%02x%02x%02x\n", - update_msg.ic_fw_msg.hw_info[0], - update_msg.ic_fw_msg.hw_info[1], - update_msg.ic_fw_msg.hw_info[2], - update_msg.ic_fw_msg.hw_info[3]); - - /* step2:get firmware message */ - for (retry = 0; retry < 2; retry++) { - ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1); - if (ret == FAIL) { - pr_err("Read firmware message fail\n"); - return ret; - } - - update_msg.force_update = buf[GTP_ADDR_LENGTH]; - if ((update_msg.force_update != 0xBE) && (!retry)) { - pr_info("The check sum in ic is error\n"); - pr_info("The IC will be updated by force\n"); - continue; - } - break; - } - pr_debug("IC force update flag:0x%x\n", update_msg.force_update); - - /* step3:get pid & vid */ - ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID, - &buf[GTP_ADDR_LENGTH], 6); - if (ret == FAIL) { - pr_err("get pid & vid failed,exit"); - return FAIL; - } - - memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid)); - memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4); - pr_debug("IC Product id:%s\n", update_msg.ic_fw_msg.pid); - - /* GT9XX PID MAPPING - * |-----FLASH-----RAM-----| - * |------918------918-----| - * |------968------968-----| - * |------913------913-----| - * |------913P-----913P----| - * |------927------927-----| - * |------927P-----927P----| - * |------9110-----9110----| - * |------9110P----9111----| - */ - if (update_msg.ic_fw_msg.pid[0] != 0) { - if (!memcmp(update_msg.ic_fw_msg.pid, "9111", 4)) { - pr_debug("IC Mapping Product id:%s\n", - update_msg.ic_fw_msg.pid); - memcpy(update_msg.ic_fw_msg.pid, "9110P", 5); - } - } - - update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH + 4] + - (buf[GTP_ADDR_LENGTH + 5] << 8); - pr_debug("IC version id:%04x\n", update_msg.ic_fw_msg.vid); - - return SUCCESS; -} - -s32 gup_enter_update_mode(struct i2c_client *client) -{ - s32 ret = -1; - u8 retry = 0; - u8 rd_buf[3]; - struct goodix_ts_data *ts = i2c_get_clientdata(client); - - /* step1:RST output low last at least 2ms */ - gpio_direction_output(ts->pdata->reset_gpio, 0); - usleep_range(RESET_DELAY_US, RESET_DELAY_US + 1); - - /* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */ - gpio_direction_output(ts->pdata->irq_gpio, - (client->addr == GTP_I2C_ADDRESS_HIGH)); - msleep(20); - - /* step3:RST output high reset guitar */ - gpio_direction_output(ts->pdata->reset_gpio, 1); - - /* 20121211 modify start */ - msleep(20); - while (retry++ < 200) { - /* step4:Hold ss51 & dsp */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_debug("Hold ss51 & dsp I2C error,retry:%d\n", retry); - continue; - } - - /* step5:Confirm hold */ - ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1); - if (ret <= 0) { - pr_debug("Hold ss51 & dsp I2C error,retry:%d\n", retry); - continue; - } - if (rd_buf[GTP_ADDR_LENGTH] == 0x0C) { - pr_debug("Hold ss51 & dsp confirm SUCCESS\n"); - break; - } - pr_debug("Hold ss51 & dsp confirm 0x4180 failed,value:%d\n", - rd_buf[GTP_ADDR_LENGTH]); - } - if (retry >= 200) { - pr_err("Enter update Hold ss51 failed\n"); - return FAIL; - } - - /* step6:DSP_CK and DSP_ALU_CK PowerOn */ - ret = gup_set_ic_msg(client, 0x4010, 0x00); - - /* 20121211 modify end */ - return ret; -} - -void gup_leave_update_mode(struct i2c_client *client) -{ - struct goodix_ts_data *ts = i2c_get_clientdata(client); - - gpio_direction_input(ts->pdata->irq_gpio); - pr_debug("reset chip"); - gtp_reset_guitar(ts, 20); -} - -/* Get the correct nvram data - * The correct conditions: - * 1. the hardware info is the same - * 2. the product id is the same - * 3. the firmware version in update file is greater than the firmware - * version in ic or the check sum in ic is wrong - - * Update Conditions: - * 1. Same hardware info - * 2. Same PID - * 3. File PID > IC PID - - * Force Update Conditions: - * 1. Wrong ic firmware checksum - * 2. INVALID IC PID or VID - * 3. IC PID == 91XX || File PID == 91XX - */ - -static u8 gup_enter_update_judge(struct i2c_client *client, - struct st_fw_head *fw_head) -{ - u16 u16_tmp; - s32 i = 0; - - u16_tmp = fw_head->vid; - fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8); - - pr_debug("FILE HARDWARE INFO:%02x%02x%02x%02x\n", fw_head->hw_info[0], - fw_head->hw_info[1], fw_head->hw_info[2], fw_head->hw_info[3]); - pr_debug("FILE PID:%s\n", fw_head->pid); - pr_debug("FILE VID:%04x\n", fw_head->vid); - - pr_debug("IC HARDWARE INFO:%02x%02x%02x%02x\n", - update_msg.ic_fw_msg.hw_info[0], - update_msg.ic_fw_msg.hw_info[1], - update_msg.ic_fw_msg.hw_info[2], - update_msg.ic_fw_msg.hw_info[3]); - pr_debug("IC PID:%s\n", update_msg.ic_fw_msg.pid); - pr_debug("IC VID:%04x\n", update_msg.ic_fw_msg.vid); - - /* First two conditions */ - if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info, - sizeof(update_msg.ic_fw_msg.hw_info))) { - pr_debug("Get the same hardware info\n"); - if (update_msg.force_update != 0xBE) { - pr_info("FW chksum error,need enter update\n"); - return SUCCESS; - } - - /* 20130523 start */ - if (strlen(update_msg.ic_fw_msg.pid) < 3) { - pr_info("Illegal IC pid, need enter update\n"); - return SUCCESS; - } - for (i = 0; i < 3; i++) { - if ((update_msg.ic_fw_msg.pid[i] < 0x30) || - (update_msg.ic_fw_msg.pid[i] > 0x39)) { - pr_info("Illegal IC pid, out of bound, need enter update\n"); - return SUCCESS; - } - } - /* 20130523 end */ - - if ((!memcmp(fw_head->pid, update_msg.ic_fw_msg.pid, - (strlen(fw_head->pid) < 3 ? 3 : strlen(fw_head->pid)))) || - (!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) || - (!memcmp(fw_head->pid, "91XX", 4))) { - if (!memcmp(fw_head->pid, "91XX", 4)) - pr_debug("Force none same pid update mode\n"); - else - pr_debug("Get the same pid\n"); - - /* The third condition */ - if (fw_head->vid > update_msg.ic_fw_msg.vid) { - pr_info("Need enter update"); - return SUCCESS; - } - pr_err("Don't meet the third condition\n"); - pr_err("File VID <= Ic VID, update aborted\n"); - } else { - pr_err("File PID != Ic PID, update aborted\n"); - } - } else { - pr_err("Different Hardware, update aborted\n"); - } - - return FAIL; -} - -static s8 gup_update_config(struct i2c_client *client, - const struct firmware *cfg) -{ - s32 ret = 0; - s32 i = 0; - s32 file_cfg_len = 0; - u32 chip_cfg_len = 0; - s32 count = 0; - u8 *buf; - u8 *file_config; - u8 pid[8]; - u8 high, low; - - if (!cfg || !cfg->data) { - pr_err("No need to upgrade config"); - return FAIL; - } - - ret = gup_get_ic_msg(client, GUP_REG_PID_VID, pid, 6); - if (ret == FAIL) { - pr_err("Read product id & version id fail"); - return FAIL; - } - pid[5] = '\0'; - pr_debug("update cfg get pid:%s\n", &pid[GTP_ADDR_LENGTH]); - - chip_cfg_len = 186; - if (!memcmp(&pid[GTP_ADDR_LENGTH], "968", 3) || - !memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) || - !memcmp(&pid[GTP_ADDR_LENGTH], "960", 3)) { - chip_cfg_len = 228; - } - pr_debug("config file ASCII len: %zu", cfg->size); - pr_debug("need config binary len: %u", chip_cfg_len); - if ((cfg->size + 5) < chip_cfg_len * 5) { - pr_err("Config length error"); - return -EINVAL; - } - - buf = devm_kzalloc(&client->dev, cfg->size, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - file_config = devm_kzalloc(&client->dev, chip_cfg_len + GTP_ADDR_LENGTH, - GFP_KERNEL); - if (!file_config) - return -ENOMEM; - - pr_debug("Delete illegal character"); - for (i = 0, count = 0; i < cfg->size; i++) { - if (cfg->data[i] == ' ' || cfg->data[i] == '\r' - || cfg->data[i] == '\n') - continue; - buf[count++] = cfg->data[i]; - } - - pr_debug("Ascii to hex"); - file_config[0] = GTP_REG_CONFIG_DATA >> 8; - file_config[1] = GTP_REG_CONFIG_DATA & 0xff; - for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i = i + 5) { - if ((buf[i] == '0') && ((buf[i + 1] == 'x') || - (buf[i + 1] == 'X'))) { - ret = hex2bin(&high, &buf[i + 2], 1); - if (ret) { - pr_err("Failed to convert high address from hex2bin"); - return ret; - } - ret = hex2bin(&low, &buf[i + 3], 1); - if (ret) { - pr_err("Failed to convert low address from hex2bin"); - return ret; - } - - if ((high == 0xFF) || (low == 0xFF)) { - ret = 0; - pr_err("Illegal config file"); - return ret; - } - file_config[file_cfg_len++] = (high<<4) + low; - } else { - ret = 0; - pr_err("Illegal config file"); - return ret; - } - } - - i = 0; - while (i++ < 5) { - ret = gup_i2c_write(client, file_config, file_cfg_len); - if (ret > 0) - break; - pr_err("Send config i2c error"); - } - - return ret; -} - -static s32 gup_get_firmware_file(struct i2c_client *client, - struct st_update_msg *msg, u8 *path) -{ - s32 ret; - const struct firmware *fw = NULL; - - ret = request_firmware(&fw, path, &client->dev); - if (ret < 0) { - dev_info(&client->dev, "Cannot get firmware - %s (%d)\n", - path, ret); - return -EEXIST; - } - - dev_dbg(&client->dev, "Config File: %s size: %zu", path, fw->size); - msg->fw_data = - devm_kzalloc(&client->dev, fw->size, GFP_KERNEL); - if (!msg->fw_data) { - release_firmware(fw); - return -ENOMEM; - } - - memcpy(msg->fw_data, fw->data, fw->size); - msg->fw_len = fw->size; - msg->need_free = true; - release_firmware(fw); - return 0; -} - -static u8 gup_check_firmware_name(struct i2c_client *client, - u8 **path_p) -{ - u8 len; - u8 *fname; - - if (!(*path_p)) { - *path_p = GOODIX_FIRMWARE_FILE_NAME; - return 0; - } - - len = strnlen(*path_p, FIRMWARE_NAME_LEN_MAX); - if (len >= FIRMWARE_NAME_LEN_MAX) { - dev_err(&client->dev, "firmware name too long"); - return -EINVAL; - } - - fname = strrchr(*path_p, '/'); - if (fname) { - fname = fname + 1; - *path_p = fname; - } - return 0; -} - -static u8 gup_check_update_file(struct i2c_client *client, - struct st_fw_head *fw_head, u8 *path) -{ - s32 ret = 0; - s32 i = 0; - s32 fw_checksum = 0; - u16 temp; - const struct firmware *fw = NULL; - - ret = request_firmware(&fw, GOODIX_CONFIG_FILE_NAME, &client->dev); - if (ret < 0) { - dev_info(&client->dev, "Cannot get config file - %s (%d)\n", - GOODIX_CONFIG_FILE_NAME, ret); - } else { - dev_dbg(&client->dev, - "Update config File: %s", GOODIX_CONFIG_FILE_NAME); - ret = gup_update_config(client, fw); - if (ret <= 0) - dev_err(&client->dev, "Update config failed"); - release_firmware(fw); - } - - update_msg.need_free = false; - update_msg.fw_len = 0; - - if (gup_check_firmware_name(client, &path)) - goto load_failed; - - if (gup_get_firmware_file(client, &update_msg, path)) - goto load_failed; - - memcpy(fw_head, update_msg.fw_data, FW_HEAD_LENGTH); - - /* check firmware legality */ - fw_checksum = 0; - for (i = 0; i < FW_SECTION_LENGTH * 4 + FW_DSP_ISP_LENGTH + - FW_DSP_LENGTH + FW_BOOT_LENGTH; i += 2) { - temp = (update_msg.fw_data[FW_HEAD_LENGTH + i] << 8) + - update_msg.fw_data[FW_HEAD_LENGTH + i + 1]; - fw_checksum += temp; - } - - pr_debug("firmware checksum:%x", fw_checksum & 0xFFFF); - if (fw_checksum & 0xFFFF) { - dev_err(&client->dev, "Illegal firmware file"); - goto load_failed; - } - - return SUCCESS; - -load_failed: - if (update_msg.need_free) { - devm_kfree(&client->dev, update_msg.fw_data); - update_msg.need_free = false; - } - return FAIL; -} - -static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr, - u16 total_length) -{ - s32 ret = 0; - u16 burn_addr = start_addr; - u16 frame_length = 0; - u16 burn_length = 0; - u8 wr_buf[PACK_SIZE + GTP_ADDR_LENGTH]; - u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH]; - u8 retry = 0; - - pr_debug("Begin burn %dk data to addr 0x%x", (total_length / 1024), - start_addr); - while (burn_length < total_length) { - pr_debug("B/T:%04d/%04d", burn_length, total_length); - frame_length = ((total_length - burn_length) > PACK_SIZE) - ? PACK_SIZE : (total_length - burn_length); - wr_buf[0] = (u8)(burn_addr>>8); - rd_buf[0] = wr_buf[0]; - wr_buf[1] = (u8)burn_addr; - rd_buf[1] = wr_buf[1]; - memcpy(&wr_buf[GTP_ADDR_LENGTH], &burn_buf[burn_length], - frame_length); - - for (retry = 0; retry < MAX_FRAME_CHECK_TIME; retry++) { - ret = gup_i2c_write(client, wr_buf, - GTP_ADDR_LENGTH + frame_length); - if (ret <= 0) { - pr_err("Write frame data i2c error\n"); - continue; - } - ret = gup_i2c_read(client, rd_buf, GTP_ADDR_LENGTH + - frame_length); - if (ret <= 0) { - pr_err("Read back frame data i2c error\n"); - continue; - } - - if (memcmp(&wr_buf[GTP_ADDR_LENGTH], - &rd_buf[GTP_ADDR_LENGTH], frame_length)) { - pr_err("Check frame data fail,not equal\n"); - continue; - } else { - break; - } - } - if (retry >= MAX_FRAME_CHECK_TIME) { - pr_err("Burn frame data time out,exit\n"); - return FAIL; - } - burn_length += frame_length; - burn_addr += frame_length; - } - return SUCCESS; -} - -static u8 gup_load_section_file(u8 *buf, u16 offset, u16 length) -{ - if (!update_msg.fw_data || - update_msg.fw_len < FW_HEAD_LENGTH + offset + length) { - pr_err( - "<<-GTP->> cannot load section data. fw_len=%d read end=%d\n", - update_msg.fw_len, - FW_HEAD_LENGTH + offset + length); - return FAIL; - } - memcpy(buf, &update_msg.fw_data[FW_HEAD_LENGTH + offset], length); - - return SUCCESS; -} - -static u8 gup_recall_check(struct i2c_client *client, u8 *chk_src, - u16 start_rd_addr, u16 chk_length) -{ - u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH]; - s32 ret = 0; - u16 recall_addr = start_rd_addr; - u16 recall_length = 0; - u16 frame_length = 0; - - while (recall_length < chk_length) { - frame_length = ((chk_length - recall_length) > PACK_SIZE) - ? PACK_SIZE : (chk_length - recall_length); - ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length); - if (ret <= 0) { - pr_err("recall i2c error,exit\n"); - return FAIL; - } - - if (memcmp(&rd_buf[GTP_ADDR_LENGTH], &chk_src[recall_length], - frame_length)) { - pr_err("Recall frame data fail,not equal\n"); - return FAIL; - } - - recall_length += frame_length; - recall_addr += frame_length; - } - pr_debug("Recall check %dk firmware success\n", (chk_length/1024)); - - return SUCCESS; -} - -static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section, - u16 start_addr, u8 bank_cmd) -{ - s32 ret = 0; - u8 rd_buf[5]; - - /* step1:hold ss51 & dsp */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_err("hold ss51 & dsp fail"); - return FAIL; - } - - /* step2:set scramble */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); - if (ret <= 0) { - pr_err("set scramble fail"); - return FAIL; - } - - /* step3:select bank */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, - (bank_cmd >> 4)&0x0F); - if (ret <= 0) { - pr_err("select bank %d fail", - (bank_cmd >> 4)&0x0F); - return FAIL; - } - - /* step4:enable accessing code */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); - if (ret <= 0) { - pr_err("enable accessing code fail"); - return FAIL; - } - - /* step5:burn 8k fw section */ - ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("burn fw_section fail"); - return FAIL; - } - - /* step6:hold ss51 & release dsp */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); - if (ret <= 0) { - pr_err("hold ss51 & release dsp fail"); - return FAIL; - } - /* must delay */ - msleep(20); - - /* step7:send burn cmd to move data to flash from sram */ - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f); - if (ret <= 0) { - pr_err("send burn cmd fail"); - return FAIL; - } - pr_debug("Wait for the burn is complete"); - do { - ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); - if (ret <= 0) { - pr_err("Get burn state fail"); - return FAIL; - } - msleep(20); - } while (rd_buf[GTP_ADDR_LENGTH]); - - /* step8:select bank */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, - (bank_cmd >> 4)&0x0F); - if (ret <= 0) { - pr_err("select bank %d fail", - (bank_cmd >> 4)&0x0F); - return FAIL; - } - - /* step9:enable accessing code */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); - if (ret <= 0) { - pr_err("enable accessing code fail"); - return FAIL; - } - - /* step10:recall 8k fw section */ - ret = gup_recall_check(client, fw_section, start_addr, - FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("recall check 8k firmware fail"); - return FAIL; - } - - /* step11:disable accessing code */ - ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00); - if (ret <= 0) { - pr_err("disable accessing code fail"); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_burn_dsp_isp(struct i2c_client *client) -{ - s32 ret = 0; - u8 *fw_dsp_isp = NULL; - u8 retry = 0; - - pr_debug("Begin burn dsp isp"); - - /* step1:alloc memory */ - pr_debug("step1:alloc memory"); - while (retry++ < 5) { - fw_dsp_isp = devm_kzalloc(&client->dev, FW_DSP_ISP_LENGTH, - GFP_KERNEL); - if (fw_dsp_isp == NULL) { - continue; - } else { - break; - } - } - if (retry == 5) - return FAIL; - - /* step2:load dsp isp file data */ - pr_debug("step2:load dsp isp file data"); - ret = gup_load_section_file(fw_dsp_isp, (4 * FW_SECTION_LENGTH + - FW_DSP_LENGTH + FW_BOOT_LENGTH), FW_DSP_ISP_LENGTH); - if (ret == FAIL) { - pr_err("load firmware dsp_isp fail"); - return FAIL; - } - - /* step3:disable wdt,clear cache enable */ - pr_debug("step3:disable wdt,clear cache enable"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00); - if (ret <= 0) { - pr_err("disable wdt fail"); - return FAIL; - } - ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00); - if (ret <= 0) { - pr_err("clear cache enable fail"); - return FAIL; - } - - /* step4:hold ss51 & dsp */ - pr_debug("step4:hold ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_err("hold ss51 & dsp fail"); - return FAIL; - } - - /* step5:set boot from sram */ - pr_debug("step5:set boot from sram"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02); - if (ret <= 0) { - pr_err("set boot from sram fail"); - return FAIL; - } - - /* step6:software reboot */ - pr_debug("step6:software reboot"); - ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01); - if (ret <= 0) { - pr_err("software reboot fail"); - return FAIL; - } - - /* step7:select bank2 */ - pr_debug("step7:select bank2"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02); - if (ret <= 0) { - pr_err("select bank2 fail"); - return FAIL; - } - - /* step8:enable accessing code */ - pr_debug("step8:enable accessing code"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01); - if (ret <= 0) { - pr_err("enable accessing code fail"); - return FAIL; - } - - /* step9:burn 4k dsp_isp */ - pr_debug("step9:burn 4k dsp_isp"); - ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH); - if (ret == FAIL) { - pr_err("burn dsp_isp fail"); - return FAIL; - } - - /* step10:set scramble */ - pr_debug("step10:set scramble"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); - if (ret <= 0) { - pr_err("set scramble fail"); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_burn_fw_ss51(struct i2c_client *client) -{ - u8 *fw_ss51 = NULL; - u8 retry = 0; - s32 ret = 0; - - pr_debug("Begin burn ss51 firmware"); - - /* step1:alloc memory */ - pr_debug("step1:alloc memory"); - while (retry++ < 5) { - fw_ss51 = devm_kzalloc(&client->dev, FW_SECTION_LENGTH, - GFP_KERNEL); - if (fw_ss51 == NULL) { - continue; - } else { - break; - } - } - if (retry == 5) - return FAIL; - - /* step2:load ss51 firmware section 1 file data */ - pr_debug("step2:load ss51 firmware section 1 file data"); - ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("load ss51 firmware section 1 fail"); - return FAIL; - } - - /* step3:clear control flag */ - pr_debug("step3:clear control flag"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00); - if (ret <= 0) { - pr_err("clear control flag fail"); - return FAIL; - } - - /* step4:burn ss51 firmware section 1 */ - pr_debug("step4:burn ss51 firmware section 1"); - ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01); - if (ret == FAIL) { - pr_err("burn ss51 firmware section 1 fail"); - return FAIL; - } - - /* step5:load ss51 firmware section 2 file data */ - pr_debug("step5:load ss51 firmware section 2 file data"); - ret = gup_load_section_file(fw_ss51, FW_SECTION_LENGTH, - FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("[burn_fw_ss51]load ss51 firmware section 2 fail\n"); - return FAIL; - } - - /* step6:burn ss51 firmware section 2 */ - pr_debug("step6:burn ss51 firmware section 2"); - ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02); - if (ret == FAIL) { - pr_err("burn ss51 firmware section 2 fail"); - return FAIL; - } - - /* step7:load ss51 firmware section 3 file data */ - pr_debug("step7:load ss51 firmware section 3 file data"); - ret = gup_load_section_file(fw_ss51, 2*FW_SECTION_LENGTH, - FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("load ss51 firmware section 3 fail"); - return FAIL; - } - - /* step8:burn ss51 firmware section 3 */ - pr_debug("step8:burn ss51 firmware section 3"); - ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13); - if (ret == FAIL) { - pr_err("burn ss51 firmware section 3 fail"); - return FAIL; - } - - /* step9:load ss51 firmware section 4 file data */ - pr_debug("step9:load ss51 firmware section 4 file data"); - ret = gup_load_section_file(fw_ss51, 3*FW_SECTION_LENGTH, - FW_SECTION_LENGTH); - if (ret == FAIL) { - pr_err("load ss51 firmware section 4 fail"); - return FAIL; - } - - /* step10:burn ss51 firmware section 4 */ - pr_debug("step10:burn ss51 firmware section 4"); - ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14); - if (ret == FAIL) { - pr_err("burn ss51 firmware section 4 fail"); - return FAIL; - } - - return SUCCESS; -} - -static u8 gup_burn_fw_dsp(struct i2c_client *client) -{ - s32 ret = 0; - u8 *fw_dsp = NULL; - u8 retry = 0; - u8 rd_buf[5]; - - pr_debug("Begin burn dsp firmware"); - /* step1:alloc memory */ - pr_debug("step1:alloc memory"); - while (retry++ < 5) { - fw_dsp = devm_kzalloc(&client->dev, FW_DSP_LENGTH, - GFP_KERNEL); - if (fw_dsp == NULL) { - continue; - } else { - break; - } - } - if (retry == 5) - return FAIL; - - /* step2:load firmware dsp */ - pr_debug("step2:load firmware dsp"); - ret = gup_load_section_file(fw_dsp, 4*FW_SECTION_LENGTH, FW_DSP_LENGTH); - if (ret == FAIL) { - pr_err("load firmware dsp fail"); - return ret; - } - - /* step3:select bank3 */ - pr_debug("step3:select bank3"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); - if (ret <= 0) { - pr_err("select bank3 fail"); - return FAIL; - } - - /* Step4:hold ss51 & dsp */ - pr_debug("step4:hold ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_err("hold ss51 & dsp fail"); - return FAIL; - } - - /* step5:set scramble */ - pr_debug("step5:set scramble"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); - if (ret <= 0) { - pr_err("set scramble fail"); - return FAIL; - } - - /* step6:release ss51 & dsp */ - pr_debug("step6:release ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); - if (ret <= 0) { - pr_err("release ss51 & dsp fail"); - return FAIL; - } - /* must delay */ - msleep(20); - - /* step7:burn 4k dsp firmware */ - pr_debug("step7:burn 4k dsp firmware"); - ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH); - if (ret == FAIL) { - pr_err("[burn_fw_dsp]burn fw_section fail\n"); - return ret; - } - - /* step8:send burn cmd to move data to flash from sram */ - pr_debug("step8:send burn cmd to move data to flash from sram"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05); - if (ret <= 0) { - pr_err("send burn cmd fail"); - return ret; - } - pr_debug("Wait for the burn is complete"); - do { - ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); - if (ret <= 0) { - pr_err("Get burn state fail"); - return ret; - } - msleep(20); - } while (rd_buf[GTP_ADDR_LENGTH]); - - /* step9:recall check 4k dsp firmware */ - pr_debug("step9:recall check 4k dsp firmware"); - ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH); - if (ret == FAIL) { - pr_err("recall check 4k dsp firmware fail"); - return ret; - } - - return SUCCESS; -} - -static u8 gup_burn_fw_boot(struct i2c_client *client) -{ - s32 ret = 0; - u8 *fw_boot = NULL; - u8 retry = 0; - u8 rd_buf[5]; - - pr_debug("Begin burn bootloader firmware"); - - /* step1:Alloc memory */ - pr_debug("step1:Alloc memory"); - while (retry++ < 5) { - fw_boot = devm_kzalloc(&client->dev, FW_BOOT_LENGTH, - GFP_KERNEL); - if (fw_boot == NULL) { - continue; - } else { - break; - } - } - if (retry == 5) - return FAIL; - - /* step2:load firmware bootloader */ - pr_debug("step2:load firmware bootloader"); - ret = gup_load_section_file(fw_boot, (4 * FW_SECTION_LENGTH + - FW_DSP_LENGTH), FW_BOOT_LENGTH); - if (ret == FAIL) { - pr_err("load firmware dsp fail"); - return ret; - } - - /* step3:hold ss51 & dsp */ - pr_debug("step3:hold ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C); - if (ret <= 0) { - pr_err("hold ss51 & dsp fail"); - return FAIL; - } - - /* step4:set scramble */ - pr_debug("step4:set scramble"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00); - if (ret <= 0) { - pr_err("set scramble fail"); - return FAIL; - } - - /* step5:release ss51 & dsp */ - pr_debug("step5:release ss51 & dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04); - if (ret <= 0) { - pr_err("release ss51 & dsp fail"); - return FAIL; - } - /* must delay */ - msleep(20); - - /* step6:select bank3 */ - pr_debug("step6:select bank3"); - ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03); - if (ret <= 0) { - pr_err("select bank3 fail"); - return FAIL; - } - - /* step7:burn 2k bootloader firmware */ - pr_debug("step7:burn 2k bootloader firmware"); - ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH); - if (ret == FAIL) { - pr_err("burn fw_section fail"); - return ret; - } - - /* step7:send burn cmd to move data to flash from sram */ - pr_debug("step7:send burn cmd to flash data from sram"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06); - if (ret <= 0) { - pr_err("send burn cmd fail"); - return ret; - } - pr_debug("Wait for the burn is complete"); - do { - ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1); - if (ret <= 0) { - pr_err("Get burn state fail"); - return ret; - } - msleep(20); - } while (rd_buf[GTP_ADDR_LENGTH]); - - /* step8:recall check 2k bootloader firmware */ - pr_debug("step8:recall check 2k bootloader firmware"); - ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH); - if (ret == FAIL) { - pr_err("recall check 4k dsp firmware fail"); - return ret; - } - - /* step9:enable download DSP code */ - pr_debug("step9:enable download DSP code "); - ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99); - if (ret <= 0) { - pr_err("enable download DSP code fail"); - return FAIL; - } - - /* step10:release ss51 & hold dsp */ - pr_debug("step10:release ss51 & hold dsp"); - ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08); - if (ret <= 0) { - pr_err("release ss51 & hold dsp fail"); - return FAIL; - } - - return SUCCESS; -} - -s32 gup_update_proc(void *dir) -{ - s32 ret = 0; - u8 retry = 0; - struct st_fw_head fw_head; - struct goodix_ts_data *ts = NULL; - - pr_debug("Begin update."); - - if (!i2c_connect_client) { - pr_err("No i2c connect client for %s\n", __func__); - return -EIO; - } - - show_len = 1; - total_len = 100; - - ts = i2c_get_clientdata(i2c_connect_client); - - if (searching_file) { - /* exit .bin update file searching */ - searching_file = 0; - pr_info("Exiting searching .bin update file."); - /* wait for auto update quitted completely */ - while ((show_len != 200) && (show_len != 100)) - msleep(100); - } - - ret = gup_check_update_file(i2c_connect_client, &fw_head, (u8 *)dir); - if (ret == FAIL) { - pr_err("check update file fail"); - goto file_fail; - } - - /* gtp_reset_guitar(i2c_connect_client, 20); */ - ret = gup_get_ic_fw_msg(i2c_connect_client); - if (ret == FAIL) { - pr_err("get ic message fail"); - goto file_fail; - } - - if (ts->force_update) { - dev_dbg(&ts->client->dev, "Enter force update."); - } else { - ret = gup_enter_update_judge(ts->client, &fw_head); - if (ret == FAIL) { - dev_err(&ts->client->dev, - "Check *.bin file fail."); - goto file_fail; - } - } - - ts->enter_update = 1; - gtp_irq_disable(ts); -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_OFF); -#endif - ret = gup_enter_update_mode(i2c_connect_client); - if (ret == FAIL) { - pr_err("enter update mode fail"); - goto update_fail; - } - - while (retry++ < 5) { - show_len = 10; - total_len = 100; - ret = gup_burn_dsp_isp(i2c_connect_client); - if (ret == FAIL) { - pr_err("burn dsp isp fail"); - continue; - } - - show_len += 10; - ret = gup_burn_fw_ss51(i2c_connect_client); - if (ret == FAIL) { - pr_err("burn ss51 firmware fail"); - continue; - } - - show_len += 40; - ret = gup_burn_fw_dsp(i2c_connect_client); - if (ret == FAIL) { - pr_err("burn dsp firmware fail"); - continue; - } - - show_len += 20; - ret = gup_burn_fw_boot(i2c_connect_client); - if (ret == FAIL) { - pr_err("burn bootloader fw fail"); - continue; - } - show_len += 10; - pr_info("UPDATE SUCCESS"); - break; - } - if (retry >= 5) { - pr_err("retry timeout,UPDATE FAIL"); - goto update_fail; - } - - pr_debug("leave update mode"); - gup_leave_update_mode(i2c_connect_client); - - msleep(100); - - if (ts->fw_error) { - pr_info("firmware error auto update, resent config\n"); - gup_init_panel(ts); - } - show_len = 100; - total_len = 100; - ts->enter_update = 0; - gtp_irq_enable(ts); - -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_ON); -#endif - if (update_msg.need_free) { - devm_kfree(&ts->client->dev, update_msg.fw_data); - update_msg.need_free = false; - } - - return SUCCESS; - -update_fail: - ts->enter_update = 0; - gtp_irq_enable(ts); - -#if GTP_ESD_PROTECT - gtp_esd_switch(ts->client, SWITCH_ON); -#endif - -file_fail: - show_len = 200; - total_len = 100; - if (update_msg.need_free) { - devm_kfree(&ts->client->dev, update_msg.fw_data); - update_msg.need_free = false; - } - return FAIL; -} - -static void gup_update_work(struct work_struct *work) -{ - if (gup_update_proc(NULL) == FAIL) - pr_err("Goodix update work fail\n"); -} - -u8 gup_init_update_proc(struct goodix_ts_data *ts) -{ - dev_dbg(&ts->client->dev, "Ready to run update work\n"); - - INIT_DELAYED_WORK(&ts->goodix_update_work, gup_update_work); - schedule_delayed_work(&ts->goodix_update_work, - msecs_to_jiffies(3000)); - - return 0; -}