summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-03-13 11:49:58 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-03-13 11:49:58 -0700
commitb09bf7ca5dbfc0d8a408da09ba2656fa3a100ab1 (patch)
tree33a7c05e1ab735398373932be74620a4e588ddd3
parentc705131473b951b2e5532c5de7c9a51ab3d89e8d (diff)
parent768090d4d7ef7515ace6b63472e699df3a2df83e (diff)
Merge "input: touchscreen: remove gt9xx goodix touch driver"
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt104
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/gt9xx/Kconfig51
-rw-r--r--drivers/input/touchscreen/gt9xx/Makefile8
-rw-r--r--drivers/input/touchscreen/gt9xx/goodix_tool.c600
-rw-r--r--drivers/input/touchscreen/gt9xx/gt9xx.c2564
-rw-r--r--drivers/input/touchscreen/gt9xx/gt9xx.h220
-rw-r--r--drivers/input/touchscreen/gt9xx/gt9xx_update.c1530
9 files changed, 0 insertions, 5090 deletions
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 <linux/mutex.h>
-#include <linux/proc_fs.h>
-#include <linux/debugfs.h>
-
-#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(&gt_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(&gt_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(&gt_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(&gt_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(&gt_client->dev, "copy_from_user failed");
- ret = -EFAULT;
- goto exit;
- }
-
- dev_dbg(&gt_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(&gt_client->dev,
- "flag val:0x%02x, flag rel:0x%02x,\n", cmd_head.flag_val,
- cmd_head.flag_relation);
- dev_dbg(&gt_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(&gt_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(&gt_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(&gt_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(&gt_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(&gt_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(&gt_client->dev, "copy_from_user failed");
- ret = -EFAULT;
- goto exit;
- }
-
- if (cmd_head.data_len > sizeof(ic_type)) {
- dev_err(&gt_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(&gt_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(&gt_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(&gt_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(&gt_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(&gt_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(&gt_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 <linux/regulator/consumer.h>
-#include "gt9xx.h"
-
-#include <linux/of_gpio.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/input/mt.h>
-#include <linux/debugfs.h>
-#include <linux/interrupt.h>
-
-#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<<i));
- }
- touch_num = 0;
- pre_touch = 0;
- }
-
- pre_key = key_value;
-
- if (ts->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<<id);
- }
-
- for (i = 0; i < GTP_MAX_TOUCH; i++) {
- if (ts->pdata->with_pen)
- if (pre_pen == 1)
- break;
-
- if (touch_index & (0x01<<i)) {
- 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;
-
- gtp_touch_down(ts, id,
- input_x, input_y, input_w);
- pre_touch |= 0x01 << i;
-
- pos += 8;
- id = coor_data[pos] & 0x0F;
- touch_index |= (0x01<<id);
- } else {
- gtp_touch_up(ts, i);
- pre_touch &= ~(0x01 << i);
- }
- }
- }
- input_sync(ts->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, &gtp_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, &gtp_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, &gtp_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,
- &gtp_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(&gtp_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,
- &gtp_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(&gtp_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 <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/uaccess.h>
-
-#if defined(CONFIG_FB)
-#include <linux/notifier.h>
-#include <linux/fb.h>
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#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 <linux/firmware.h>
-#include <linux/workqueue.h>
-#include <linux/kernel.h>
-
-#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;
-}