input: touchscreen: Add Goodix touchscreen support

Add Goodix gt9xx v2.8 driver support for 10" display panel.  Squash the
following commits:

    commit 9e50a79cf8aa780343b4e7b4e6ed5c6320215e01 (refs/remotes/goodix/master)
    Author: Charles Wang <charles.goodix@gmail.com>
    Date:   Mon Jul 2 14:53:38 2018 +0800

	Fix errors and warnings when build on msm-kernel-4.9

	- Fix errors and warnings when build on msm-kernel-4.9.
	- Optimization touch effect.

	Signed-off-by: Charles Wang <charles.goodix@gmail.com>

    commit bd29bac9657816c6f297b3df506d35c18898fdda
    Author: Charles Wang <charles.goodix@gmail.com>
    Date:   Fri Mar 2 01:59:08 2018 +0800

	Remove debug info form makefile

	Signed-off-by: Charles Wang <charles.goodix@gmail.com>

    commit 1a28cac74d1bfd175796f229cdb695676dd55c1c
    Author: Charles Wang <charles.goodix@gmail.com>
    Date:   Fri Mar 2 01:20:07 2018 +0800

	Fix some coding style problem

	Signed-off-by: Wang Yafei <wangyafei@goodix.com>

    commit 09baa4effb7b8379809ee8d9b30575f973f7233f
    Author: Wang Yafei <wangyafei@goodix.com>
    Date:   Fri Feb 2 19:27:42 2018 +0800

	Modify dts config properties

	Signed-off-by: Wang Yafei <wangyafei@goodix.com>

    commit 44446a88e9ccbd6c62cdec43bf3c7682c556cada
    Author: Wang Yafei <wangyafei@goodix.com>
    Date:   Mon Jan 29 20:30:46 2018 +0800

	Add reset-pin pinstrl support

	- Use pinctrl control reset-pin state
	- Fix user space memory direct access

	Signed-off-by: Wang Yafei <wangyafei@goodix.com>

    commit 6a5b40a189651121ed3ccdd6474b43116f759bcb
    Author: Wang Yafei <wangyafei@goodix.com>
    Date:   Sat Nov 11 02:03:44 2017 +0800

	Modify pinctrl

	Signed-off-by: Wang Yafei <wangyafei@goodix.com>

    commit 1ef4fbf61982222d0599b21d9d6ab6e017c54759
    Author: Wang Yafei <wangyafei@goodix.com>
    Date:   Thu Nov 9 02:09:09 2017 +0800

	Fix little problem when firmware update failed

	Signed-off-by: Wang Yafei <wangyafei@goodix.com>

    commit 529f4c536fbd0047bfcb5a31d277aae5706d8e4f
    Author: Wang Yafei <wangyafei@goodix.com>
    Date:   Wed Nov 8 05:03:42 2017 +0800

	Fix Kconfig problems

	Signed-off-by: Wang Yafei <wangyafei@goodix.com>

    commit 877e4b186d597f1a53ed35a2ba2fb7a2debde063
    Author: Wang Yafei <wangyafei@goodix.com>
    Date:   Tue Nov 7 05:29:48 2017 +0800

	Add Goodix gt9xx v2.8 driver

	Signed-off-by: Wang Yafei <wangyafei@goodix.com>

    commit ca7a8083ab72ab110919223c3a32e6f814dbbe9c
    Author: Wang Yafei <wangyafei@goodix.com>
    Date:   Tue Nov 7 05:12:11 2017 +0800

	Add apq8053-dragon dts file

	Signed-off-by: Wang Yafei <wangyafei@goodix.com>

    commit 6bd539a42db3a518ca10841d829be93f9d524d56
    Author: Wang Yafei <wangyafei@goodix.com>
    Date:   Tue Nov 7 03:38:36 2017 +0800

	first commit

	Signed-off-by: Wang Yafei <wangyafei@goodix.com>

Change-Id: I559e3ecc28e86b9de98721d02f46bc782e96aae6
Git-commit: 9e50a79cf8aa780343b4e7b4e6ed5c6320215e01
Git-repo: https://github.com/goodix/msm-3.18
Signed-off-by: Venkataraman Nerellapalli <venkataraman.nerellapalli@codeaurora.org>
This commit is contained in:
Wang Yafei 2018-07-03 17:30:32 +05:30 • committed by Venkataraman Nerellapalli
commit fa2e93ea6f
9 changed files with 5827 additions and 0 deletions

View file

@ -0,0 +1,99 @@
Goodix GT9xx series touch controller
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;
};
};

View file

@ -1279,6 +1279,18 @@ config FT_SECURE_TOUCH
If unsure, say N.
config TOUCHSCREEN_GT9XX_v28
bool "Goodix touchpanel GT9xx_v28 series"
depends on I2C
help
Say Y here if you have a Goodix GT9xx_v28 touchscreen.
Gt9xx controllers are multi touch controllers which can
report 5 touches at a time.
If unsure, say N.
source "drivers/input/touchscreen/gt9xx_v2.8/Kconfig"
config TOUCHSCREEN_HIMAX_CHIPSET
bool "Himax touchpanel CHIPSET"
depends on I2C

View file

@ -105,3 +105,4 @@ obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50) += colibri-vf50-ts.o
obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_touch/
obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET) += hxchipset/
obj-$(CONFIG_TOUCHSCREEN_GT9XX_v28) += gt9xx_v2.8/

View file

@ -0,0 +1,36 @@
#
# Goodix GT9xx Touchscreen driver
#
config TOUCHSCREEN_GT9XX_v28
bool "Goodix touchpanel GT9xx series"
depends on I2C
help
Enable this for support Goodix GT9xx_v28 driver.
Say Y here if you have a Goodix GT9xx touchscreen
controller.
If unsure, say N.
config TOUCHSCREEN_GT9XX_UPDATE
tristate "Goodix GT9xx touch controller auto update support"
depends on TOUCHSCREEN_GT9XX_v28
help
Enable this for support firmware update.
Say Y here if you want update touch controller
firmware.
If unsure, say N.
config TOUCHSCREEN_GT9XX_TOOL
tristate "Goodix GT9xx Tools for debuging"
depends on TOUCHSCREEN_GT9XX_v28
help
This implement interface support for Goodix GT9xx
touchscreen debug.
Say Y here if you want to have a Android app debug interface
to your system.
If unsure, say N.

View file

@ -0,0 +1,7 @@
#
# Makefile for the Goodix gt9xx touchscreen driver.
#
#subdir-ccflags-y += -DDEBUG
obj-$(CONFIG_TOUCHSCREEN_GT9XX_v28) += gt9xx.o
obj-$(CONFIG_TOUCHSCREEN_GT9XX_UPDATE) += gt9xx_update.o
obj-$(CONFIG_TOUCHSCREEN_GT9XX_TOOL) += goodix_tool.o

View file

@ -0,0 +1,529 @@
/*
* Goodix GT9xx touchscreen driver
*
* Copyright (C) 2016 - 2017 Goodix. Ltd.
*
* 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.
*
*/
#include "gt9xx.h"
#define DATA_LENGTH_UINT 512
#define CMD_HEAD_LENGTH (sizeof(struct st_cmd_head) - sizeof(u8 *))
static char procname[20] = {0};
#pragma pack(1)
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*/
u8 *data; }; /*data pointer*/
#pragma pack()
struct st_cmd_head cmd_head;
static struct i2c_client *gt_client;
static struct proc_dir_entry *goodix_proc_entry;
static ssize_t goodix_tool_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t goodix_tool_write(struct file *, const char __user *,
size_t, loff_t *);
static const struct file_operations gtp_proc_ops = {
.owner = THIS_MODULE,
.read = goodix_tool_read,
.write = goodix_tool_write,
};
/* static s32 goodix_tool_write(struct file *filp,
* const char __user *buff, unsigned long len, void *data);
*/
/*static s32 goodix_tool_read( char *page, char
**start, off_t off, int count, int *eof, void *data );
*/
static s32 (*tool_i2c_read)(u8 *, u16);
static s32 (*tool_i2c_write)(u8 *, u16);
static s32 DATA_LENGTH = (s32)0;
static s8 IC_TYPE[16] = "GT9XX";
static void tool_set_proc_name(char *procname)
{
snprintf(procname, 20, "gmnode"); /* modify for moto */
}
static s32 tool_i2c_read_no_extra(u8 *buf, u16 len)
{
s32 ret = -1;
s32 i = 0;
struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
for (i = 0; i < cmd_head.retry; i++) {
ret = gtp_i2c_read(ts->client, buf, len + GTP_ADDR_LENGTH);
if (ret > 0)
break;
}
return ret;
}
static s32 tool_i2c_write_no_extra(u8 *buf, u16 len)
{
s32 ret = -1;
s32 i = 0;
struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
for (i = 0; i < cmd_head.retry; i++) {
ret = gtp_i2c_write(ts->client, buf, len);
if (ret > 0)
break;
}
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, "GT818", 5)
* || !strcmp(IC_TYPE, "GT816", 5)
* || !strcmp(IC_TYPE, "GT811", 5)
* || !strcmp(IC_TYPE, "GT818F", 6)
* || !strcmp(IC_TYPE, "GT827", 5)
* || !strcmp(IC_TYPE,"GT828", 5)
* || !strcmp(IC_TYPE, "GT813", 5))
*/
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") &&
strcmp(IC_TYPE, "GT9XX")) {
tool_i2c_read = tool_i2c_read_with_extra;
tool_i2c_write = tool_i2c_write_with_extra;
dev_dbg(&gt_client->dev, "I2C function: with pre and end cmd!");
} else {
tool_i2c_read = tool_i2c_read_no_extra;
tool_i2c_write = tool_i2c_write_no_extra;
dev_info(&gt_client->dev, "I2C function: without pre and end cmd!");
}
}
static void unregister_i2c_func(void)
{
tool_i2c_read = NULL;
tool_i2c_write = NULL;
dev_info(&gt_client->dev, "I2C function: unregister i2c transfer function!");
}
s32 init_wr_node(struct i2c_client *client)
{
s32 i;
gt_client = client;
memset(&cmd_head, 0, sizeof(cmd_head));
cmd_head.data = NULL;
i = 6;
while ((!cmd_head.data) && i) {
cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL);
if (cmd_head.data)
break;
i--;
}
if (i) {
DATA_LENGTH = i * DATA_LENGTH_UINT - GTP_ADDR_LENGTH;
dev_info(&gt_client->dev,
"Alloc memory size:%d.", DATA_LENGTH);
} else {
dev_err(&gt_client->dev, "Apply for memory failed.");
return FAIL;
}
cmd_head.addr_len = 2;
cmd_head.retry = 5;
register_i2c_func();
tool_set_proc_name(procname);
goodix_proc_entry = proc_create(procname, 0664, NULL, &gtp_proc_ops);
if (!goodix_proc_entry) {
dev_err(&gt_client->dev, "Couldn't create proc entry!");
return FAIL;
}
dev_info(&gt_client->dev, "Create proc entry success!");
return SUCCESS;
}
void uninit_wr_node(void)
{
kfree(cmd_head.data);
cmd_head.data = NULL;
unregister_i2c_func();
remove_proc_entry(procname, NULL);
}
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;
dev_dbg(&gt_client->dev,
"equal:src:0x%02x dst:0x%02x ret:%d.",
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)) {
dev_dbg(&gt_client->dev, "value at flag addr:0x%02x.",
buf[GTP_ADDR_LENGTH]);
dev_dbg(&gt_client->dev, "flag value:0x%02x.",
cmd_head.flag_val);
break;
}
msleep(cmd_head.circle);
}
if (i >= cmd_head.times) {
dev_err(&gt_client->dev, "Can't get the continue flag!");
return FAIL;
}
return SUCCESS;
}
ssize_t goodix_tool_write(struct file *filp, const char __user *buff,
size_t len, loff_t *off)
{
s32 ret = 0;
struct goodix_ts_data *ts = i2c_get_clientdata(gt_client);
ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH);
if (ret) {
dev_err(&gt_client->dev, "copy_from_user failed.");
return -EPERM;
}
dev_dbg(&gt_client->dev, "[Operation]wr: %02X", cmd_head.wr);
dev_dbg(&gt_client->dev,
"[Flag]flag: %02X,addr: %02X%02X,value: %02X,relation: %02X",
cmd_head.flag, cmd_head.flag_addr[0],
cmd_head.flag_addr[1], cmd_head.flag_val,
cmd_head.flag_relation);
dev_dbg(&gt_client->dev,
"[Retry]circle: %d,times: %d,retry: %d, delay: %d",
(s32)cmd_head.circle,
(s32)cmd_head.times, (s32)cmd_head.retry,
(s32)cmd_head.delay);
if (cmd_head.wr == 1) {
if (cmd_head.data_len > DATA_LENGTH) {
dev_err(&gt_client->dev,
"Tool write failed data too long");
return -EPERM;
}
ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
&buff[CMD_HEAD_LENGTH],
cmd_head.data_len);
if (ret) {
dev_err(&gt_client->dev, "copy_from_user failed.");
return -EPERM;
}
memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
cmd_head.addr, cmd_head.addr_len);
GTP_DEBUG_ARRAY(cmd_head.data, cmd_head.data_len +
cmd_head.addr_len);
if (cmd_head.flag == 1) {
if (comfirm() == FAIL) {
dev_err(&gt_client->dev,
"[WRITE]Comfirm fail!");
return -EPERM;
}
} else if (cmd_head.flag == 2) {
/*Need interrupt!*/
}
if (tool_i2c_write(&cmd_head.data[GTP_ADDR_LENGTH -
cmd_head.addr_len], cmd_head.data_len +
cmd_head.addr_len) <= 0) {
dev_err(&gt_client->dev, "[WRITE]Write data failed!");
return -EPERM;
}
GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH -
cmd_head.addr_len],
cmd_head.data_len + cmd_head.addr_len);
if (cmd_head.delay)
msleep(cmd_head.delay);
} else if (cmd_head.wr == 3) {
if (cmd_head.data_len > DATA_LENGTH) {
dev_err(&gt_client->dev,
"Tool write failed data too long");
return -EPERM;
}
ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH],
cmd_head.data_len);
if (ret) {
dev_err(&gt_client->dev, "copy_from_user failed.");
return -EPERM;
}
memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);
register_i2c_func();
} else if (cmd_head.wr == 5) {
/*memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);*/
} else if (cmd_head.wr == 7) {/*disable irq!*/
gtp_work_control_enable(i2c_get_clientdata(gt_client), false);
if (ts->pdata->esd_protect)
gtp_esd_off(ts);
} else if (cmd_head.wr == 9) {/*enable irq!*/
gtp_work_control_enable(i2c_get_clientdata(gt_client), true);
if (ts->pdata->esd_protect)
gtp_esd_on(ts);
} else if (cmd_head.wr == 17) {
if (cmd_head.data_len > DATA_LENGTH) {
dev_err(&gt_client->dev,
"Tool write failed data too long");
return -EPERM;
}
ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
&buff[CMD_HEAD_LENGTH],
cmd_head.data_len);
if (ret) {
dev_dbg(&gt_client->dev, "copy_from_user failed.");
return -EPERM;
}
if (cmd_head.data[GTP_ADDR_LENGTH]) {
dev_info(&gt_client->dev, "gtp enter rawdiff.");
set_bit(RAW_DATA_MODE, &ts->flags);
} else {
clear_bit(RAW_DATA_MODE, &ts->flags);
dev_info(&gt_client->dev, "gtp leave rawdiff.");
}
} else if (cmd_head.wr == 19) {
/* add new command: reset guitar */
gtp_reset_guitar(gt_client, 20);
}
#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
else if (cmd_head.wr == 11) {/*Enter update mode!*/
if (gup_enter_update_mode(gt_client) == FAIL)
return -EPERM;
} else if (cmd_head.wr == 13) {/*Leave update mode!*/
gup_leave_update_mode(gt_client);
} else if (cmd_head.wr == 15) {/*Update firmware!*/
show_len = 0;
total_len = 0;
if (cmd_head.data_len > DATA_LENGTH) {
dev_err(&gt_client->dev,
"Tool write failed data too long");
return -EPERM;
}
memset(cmd_head.data, 0, DATA_LENGTH);
ret = copy_from_user(cmd_head.data,
&buff[CMD_HEAD_LENGTH],
cmd_head.data_len);
if (ret) {
dev_dbg(&gt_client->dev, "copy_from_user failed.");
return -EPERM;
}
if (gup_update_proc((void *)cmd_head.data) == FAIL)
return -EPERM;
}
#endif
return len;
}
/*******************************************************
* Function:
* Goodix tool read function.
* Input:
* standard proc read function param.
* Output:
* Return read length.
********************************************************/
ssize_t goodix_tool_read(struct file *file, char __user *page,
size_t size, loff_t *ppos)
{
s32 ret = 0;
if (*ppos) {
/* ADB call again
* dev_dbg(&gt_client->dev, "[HEAD]wr: %d", cmd_head.wr);
* dev_dbg(&gt_client->dev,
* "[PARAM]size: %d, *ppos: %d", size, (int)*ppos);
* dev_dbg(&gt_client->dev,
* "[TOOL_READ]ADB call again, return it.");
*/
*ppos = 0;
return 0;
}
if (cmd_head.wr % 2) {
return -EPERM;
} else if (!cmd_head.wr) {
u16 len, data_len, loc, addr;
if (cmd_head.flag == 1) {
if (comfirm() == FAIL) {
dev_err(&gt_client->dev, "[READ]Comfirm fail!");
return -EPERM;
}
} else if (cmd_head.flag == 2) {
/*Need interrupt!*/
}
if (cmd_head.delay)
msleep(cmd_head.delay);
data_len = cmd_head.data_len;
addr = (cmd_head.addr[0] << 8) + cmd_head.addr[1];
loc = 0;
while (data_len > 0) {
len = data_len > DATA_LENGTH ? DATA_LENGTH : data_len;
cmd_head.data[0] = (addr >> 8) & 0xFF;
cmd_head.data[1] = (addr & 0xFF);
if (tool_i2c_read(cmd_head.data, len) <= 0) {
dev_err(&gt_client->dev, "[READ]Read data failed!");
return -EPERM;
}
ret = simple_read_from_buffer(&page[loc], size, ppos,
&cmd_head.data[GTP_ADDR_LENGTH], len);
if (ret < 0)
return ret;
loc += len;
addr += len;
data_len -= len;
}
return cmd_head.data_len;
} else if (cmd_head.wr == 2) {
ret = simple_read_from_buffer(page, size, ppos,
IC_TYPE, sizeof(IC_TYPE));
return ret;
}
#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
else if (cmd_head.wr == 4) {
u8 progress_buf[4];
progress_buf[0] = show_len >> 8;
progress_buf[1] = show_len & 0xff;
progress_buf[2] = total_len >> 8;
progress_buf[3] = total_len & 0xff;
ret = simple_read_from_buffer(page, size, ppos,
progress_buf, 4);
return ret;
}
#endif
else if (cmd_head.wr == 6) {
/*Read error code!*/
} else if (cmd_head.wr == 8) { /*Read driver version*/
ret = simple_read_from_buffer(page, size, ppos,
GTP_DRIVER_VERSION,
strlen(GTP_DRIVER_VERSION));
return ret;
}
return -EPERM;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,375 @@
/*
* Goodix GT9xx touchscreen driver
*
* Copyright (C) 2016 - 2017 Goodix. Ltd.
*
* 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: 2.8.0.2
* Release Date: 2017/12/14
*/
#ifndef _GOODIX_GT9XX_H_
#define _GOODIX_GT9XX_H_
#include <linux/kernel.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/major.h>
#include <linux/kdev_t.h>
#ifdef CONFIG_OF
#include <linux/of_gpio.h>
#endif
#ifdef CONFIG_FB
#include <linux/notifier.h>
#include <linux/fb.h>
#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <linux/usb.h>
#include <linux/power_supply.h>
#define GTP_TOOL_PEN 1
#define GTP_TOOL_FINGER 2
#define MAX_KEY_NUMS 4
#define GTP_CONFIG_MAX_LENGTH 240
#define GTP_ADDR_LENGTH 2
/***************************PART1:ON/OFF define*******************************/
#define GTP_DEBUG_ON 1
#define GTP_DEBUG_ARRAY_ON 0
#define GTP_DEBUG_FUNC_ON 0
struct goodix_point_t {
int id;
int x;
int y;
int w;
int p;
int tool_type;
};
struct goodix_config_data {
int length;
u8 data[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH];
};
struct goodix_ts_platform_data {
int irq_gpio;
int rst_gpio;
u32 irq_flags;
u32 abs_size_x;
u32 abs_size_y;
u32 max_touch_id;
u32 max_touch_width;
u32 max_touch_pressure;
u32 key_map[MAX_KEY_NUMS];
u32 key_nums;
u32 int_sync;
u32 driver_send_cfg;
u32 swap_x2y;
u32 slide_wakeup;
u32 auto_update;
u32 auto_update_cfg;
u32 esd_protect;
u32 type_a_report;
u32 power_off_sleep;
u32 resume_in_workqueue;
u32 pen_suppress_finger;
struct goodix_config_data config;
};
struct goodix_ts_esd {
struct delayed_work delayed_work;
struct mutex mutex;
bool esd_on;
};
enum {
REPORT_THREAD_ENABLED = 0,
HRTIMER_USED,
FW_ERROR,
DOZE_MODE,
SLEEP_MODE,
POWER_OFF_MODE,
RAW_DATA_MODE,
FW_UPDATE_RUNNING,
PANEL_RESETTING
};
struct goodix_pinctrl {
struct pinctrl *pinctrl;
struct pinctrl_state *int_default;
struct pinctrl_state *int_out_high;
struct pinctrl_state *int_out_low;
struct pinctrl_state *int_input;
struct pinctrl_state *rst_default;
struct pinctrl_state *rst_out_high;
struct pinctrl_state *rst_out_low;
struct pinctrl_state *rst_input;
};
struct goodix_fw_info {
u8 pid[6];
u16 version;
u8 sensor_id;
};
struct goodix_ts_data {
unsigned long flags; /* This member record the device status */
struct goodix_ts_esd ts_esd;
struct i2c_client *client;
struct input_dev *input_dev;
struct input_dev *pen_dev;
struct goodix_ts_platform_data *pdata;
/* use pinctrl control int-pin output low or high */
struct goodix_pinctrl pinctrl;
struct hrtimer timer;
struct mutex lock;
struct notifier_block ps_notif;
struct regulator *vdd_ana;
struct regulator *vcc_i2c;
#if defined(CONFIG_FB)
struct notifier_block notifier;
struct work_struct fb_notify_work;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
struct goodix_fw_info fw_info;
bool force_update;
bool init_done;
};
/************************* PART2:TODO define *******************************/
/* STEP_1(REQUIRED): Define Configuration Information Group(s)
* Sensor_ID Map:
* sensor_opt1 sensor_opt2 Sensor_ID
* GND GND 0
* VDDIO GND 1
* NC GND 2
* GND NC/300K 3
* VDDIO NC/300K 4
* NC NC/300K 5
*/
/* TODO: define your own default or for Sensor_ID == 0 config here.
* The predefined one is just a sample config,
* which is not suitable for your tp in most cases.
*/
#define CTP_CFG_GROUP0 {\
0x41, 0xD0, 0x02, 0x00, 0x05, 0x0A, 0x34, \
0x00, 0x01, 0x08, 0x28, 0x05, 0x50, 0x32, \
0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x17, 0x19, 0x1E, 0x14, 0x8C, \
0x2D, 0x0E, 0x3C, 0x3E, 0x82, 0x0A, 0x82, \
0x0A, 0x00, 0x99, 0x33, 0x1D, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x2B, 0x19, 0x64, 0x94, 0xC0, 0x02, \
0x08, 0x00, 0x00, 0x04, 0xF2, 0x1C, 0x00, \
0xB9, 0x26, 0x00, 0x93, 0x32, 0x00, 0x77, \
0x42, 0x00, 0x62, 0x57, 0x00, 0x62, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0xFF, 0x65, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x19, 0x46, 0x00, 0x00, 0x00, 0x00, 0x32, \
0x1C, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10, \
0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, \
0x0A, 0x0C, 0x0F, 0x10, 0x12, 0x13, 0x14, \
0x18, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, \
0x22, 0x24, 0x26, 0x28, 0x29, 0x2A, 0xFF, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0xB8, 0x01\
}
/* TODO: define your config for Sensor_ID == 1 here, if needed */
#define CTP_CFG_GROUP1 {\
}
/* TODO: define your config for Sensor_ID == 2 here, if needed */
#define CTP_CFG_GROUP2 {\
}
/* TODO: define your config for Sensor_ID == 3 here, if needed */
#define CTP_CFG_GROUP3 {\
}
/* TODO: define your config for Sensor_ID == 4 here, if needed */
#define CTP_CFG_GROUP4 {\
}
/* TODO: define your config for Sensor_ID == 5 here, if needed */
#define CTP_CFG_GROUP5 {\
}
/* STEP_2(REQUIRED): Customize your I/O ports & I/O operations */
#define GTP_RST_PORT 64 /* EXYNOS4_GPX2(0) */
#define GTP_INT_PORT 65 /* EXYNOS4_GPX2(1) */
#define GTP_GPIO_AS_INPUT(pin) (gpio_direction_input(pin))
#define GTP_GPIO_AS_INT(pin) (GTP_GPIO_AS_INPUT(pin))
#define GTP_GPIO_GET_VALUE(pin) gpio_get_value(pin)
#define GTP_GPIO_OUTPUT(pin, level) gpio_direction_output(pin, level)
#define GTP_GPIO_REQUEST(pin, label) gpio_request(pin, label)
#define GTP_GPIO_FREE(pin) gpio_free(pin)
/* STEP_3(optional): Specify your special config info if needed */
#define GTP_DEFAULT_MAX_X 720 /* default coordinate max values */
#define GTP_DEFAULT_MAX_Y 1080
#define GTP_DEFAULT_MAX_WIDTH 1024
#define GTP_DEFAULT_MAX_PRESSURE 1024
#define GTP_DEFAULT_INT_TRIGGER 1 /* 1 rising, 2 falling */
#define GTP_MAX_TOUCH_ID 16
/* STEP_4(optional): If keys are available and reported as keys,
* config your key info here
*/
#define GTP_KEY_TAB {KEY_MENU, KEY_HOME, KEY_BACK, KEY_HOMEPAGE, \
KEY_F1, KEY_F2, KEY_F3}
/**************************PART3:OTHER define*******************************/
#define GTP_DRIVER_VERSION "V2.8.0.2<2017/12/14>"
#define GTP_I2C_NAME "goodix-ts"
#define GT91XX_CONFIG_PROC_FILE "gt9xx_config"
#define GTP_POLL_TIME 10
#define GTP_CONFIG_MIN_LENGTH 186
#define GTP_ESD_CHECK_VALUE 0xAA
#define RETRY_MAX_TIMES 5
#define PEN_TRACK_ID 9
#define MASK_BIT_8 0x80
#define FAIL 0
#define SUCCESS 1
/* Registers define */
#define GTP_REG_COMMAND 0x8040
#define GTP_REG_ESD_CHECK 0x8041
#define GTP_REG_COMMAND_CHECK 0x8046
#define GTP_REG_CONFIG_DATA 0x8047
#define GTP_REG_VERSION 0x8140
#define GTP_REG_SENSOR_ID 0x814A
#define GTP_REG_DOZE_BUF 0x814B
#define GTP_READ_COOR_ADDR 0x814E
/* Sleep time define */
#define GTP_1_DLY_MS 1
#define GTP_2_DLY_MS 2
#define GTP_10_DLY_MS 10
#define GTP_20_DLY_MS 20
#define GTP_50_DLY_MS 50
#define GTP_58_DLY_MS 58
#define GTP_100_DLY_MS 100
#define GTP_500_DLY_MS 500
#define GTP_1000_DLY_MS 1000
#define GTP_3000_DLY_MS 3000
#define RESOLUTION_LOC 3
#define TRIGGER_LOC 8
#define CFG_GROUP_LEN(p_cfg_grp) ARRAY_SIZE(p_cfg_grp)
/* Log define */
#define GTP_DEBUG(fmt, arg...) \
do { \
if (GTP_DEBUG_ON) {\
pr_info("<<-GTP-DEBUG->> [%d]"fmt"\n", __LINE__, ##arg);\
} \
} while (0)
#define GTP_DEBUG_ARRAY(array, num) \
do { \
s32 i;\
u8 *a = array;\
if (GTP_DEBUG_ARRAY_ON) {\
pr_warn("<<-GTP-DEBUG-ARRAY->>\n");\
for (i = 0; i < (num); i++) {\
pr_warn("%02x ", (a)[i]);\
if ((i + 1) % 10 == 0) {\
pr_warn("\n");\
} \
} \
pr_warn("\n");\
} \
} while (0)
#define GTP_DEBUG_FUNC() \
do {\
if (GTP_DEBUG_FUNC_ON) {\
pr_warn("<<-GTP-FUNC->> Func:%s@Line:%d\n", \
__func__, __LINE__);\
} \
} while (0)
#define GTP_SWAP(x, y) \
do {\
typeof(x) z = x;\
x = y;\
y = z;\
} while (0)
/******************************End of Part III********************************/
#ifdef CONFIG_OF
extern int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid);
#endif
extern void gtp_reset_guitar(struct i2c_client *client, s32 ms);
extern void gtp_int_sync(struct goodix_ts_data *ts, s32 ms);
extern void gtp_esd_on(struct goodix_ts_data *ts);
extern void gtp_esd_off(struct goodix_ts_data *ts);
extern void gtp_work_control_enable(struct goodix_ts_data *ts, bool enable);
#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
extern u16 show_len;
extern u16 total_len;
extern u8 gup_init_update_proc(struct goodix_ts_data *ts);
extern s32 gup_update_proc(void *dir);
extern s32 gup_enter_update_mode(struct i2c_client *client);
extern void gup_leave_update_mode(struct i2c_client *client);
#endif
#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL
extern s32 init_wr_node(struct i2c_client *client);
extern void uninit_wr_node(void);
#endif
/*********** For gt9xx_update Start *********/
extern struct i2c_client *i2c_connect_client;
extern void gtp_reset_guitar(struct i2c_client *client, s32 ms);
extern void gtp_int_output(struct goodix_ts_data *ts, int level);
extern void gtp_rst_output(struct goodix_ts_data *ts, int level);
extern void gtp_rst_input(struct goodix_ts_data *ts);
extern s32 gtp_send_cfg(struct i2c_client *client);
extern s32 gtp_get_fw_info(struct i2c_client *client,
struct goodix_fw_info *fw_info);
extern s32 gtp_i2c_read_dbl_check(struct i2c_client *client,
u16 addr, u8 *rxbuf, int len);
extern int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len);
extern int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len);
extern s32 gtp_fw_startup(struct i2c_client *client);
extern int gtp_ascii_to_array(const u8 *src_buf, int src_len, u8 *dst_buf);
/*********** For gt9xx_update End *********/
#endif /* _GOODIX_GT9XX_H_ */

File diff suppressed because it is too large Load diff