summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore8
-rw-r--r--Makefile3
-rw-r--r--goodix_brl_fwupdate.c138
-rw-r--r--goodix_brl_hw.c53
-rw-r--r--goodix_brl_i2c.c11
-rw-r--r--goodix_brl_spi.c15
-rw-r--r--goodix_cfg_bin.c11
-rw-r--r--goodix_ts_core.c201
-rw-r--r--goodix_ts_core.h73
-rw-r--r--goodix_ts_gesture.c308
-rw-r--r--goodix_ts_inspect.c1333
-rw-r--r--goodix_ts_proc.c376
-rw-r--r--goodix_ts_tools.c1
-rw-r--r--goodix_ts_utils.c69
14 files changed, 1597 insertions, 1003 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0183c58
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,8 @@
+/.vscode
+*.a
+*.ko
+*.o
+*.cmd
+*.builtin
+*.order
+*.mod.*
diff --git a/Makefile b/Makefile
index 903a1cc..7a1a4cc 100644
--- a/Makefile
+++ b/Makefile
@@ -9,4 +9,5 @@ goodix_core-y := \
goodix_brl_fwupdate.o \
goodix_ts_gesture.o \
goodix_ts_inspect.o \
- goodix_ts_tools.o
+ goodix_ts_tools.o \
+ goodix_ts_proc.o
diff --git a/goodix_brl_fwupdate.c b/goodix_brl_fwupdate.c
index 6bce047..b01d572 100644
--- a/goodix_brl_fwupdate.c
+++ b/goodix_brl_fwupdate.c
@@ -192,6 +192,7 @@ struct firmware_summary {
struct firmware_data {
struct firmware_summary fw_summary;
const struct firmware *firmware;
+ struct firmware *fw_sysfs;
};
struct config_data {
@@ -325,7 +326,11 @@ static int goodix_parse_firmware(struct firmware_data *fw_data)
fw_summary = &fw_data->fw_summary;
/* copy firmware head info */
- firmware = fw_data->firmware;
+ if (goodix_fw_update_ctrl.mode & UPDATE_MODE_SRC_SYSFS)
+ firmware = fw_data->fw_sysfs;
+ else
+ firmware = fw_data->firmware;
+
if (firmware->size < subsys_info_offset) {
ts_err("Invalid firmware size:%zu", firmware->size);
r = -EINVAL;
@@ -337,7 +342,8 @@ static int goodix_parse_firmware(struct firmware_data *fw_data)
fw_summary->size = le32_to_cpu(fw_summary->size);
if (firmware->size != fw_summary->size + FW_FILE_CHECKSUM_OFFSET) {
ts_err("Bad firmware, size not match, %zu != %d",
- firmware->size, fw_summary->size + 6);
+ firmware->size,
+ fw_summary->size + FW_FILE_CHECKSUM_OFFSET);
r = -EINVAL;
goto err_size;
}
@@ -627,7 +633,8 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl)
ts_info("Success hold CPU");
/* enable misctl clock */
- if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_D)
+ if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_D ||
+ fwu_ctrl->core_data->bus->ic_type == IC_TYPE_NOTTINGHAM)
goodix_reg_write(misctl_reg, (u8 *)&enable_misctl_val, 4);
else
goodix_reg_write(misctl_reg, (u8 *)&enable_misctl_val, 1);
@@ -703,7 +710,7 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
}
ts_info("flash cmd ack check pass");
- msleep(80);
+ msleep(50);
retry = 20;
for (i = 0; i < retry; i++) {
ret = goodix_reg_read(
@@ -716,7 +723,7 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
ts_info("flash cmd status not ready, retry %d, ack 0x%x, status 0x%x, ret %d",
i, tmp_cmd.ack, tmp_cmd.status, ret);
- msleep(20);
+ usleep_range(10000, 11000);
}
ts_err("flash cmd status error %d, ack 0x%x, status 0x%x, ret %d", i,
@@ -773,7 +780,7 @@ static int goodix_flash_package(
ret = goodix_send_flash_cmd(&flash_cmd);
if (!ret) {
- ts_info("success write package to 0x%x, len %d",
+ ts_info("success write package to 0x%05X, len %d",
flash_addr, pkg_len - 4);
return 0;
}
@@ -817,7 +824,7 @@ static int goodix_flash_subsystem(struct fw_subsys_info *subsys)
while (total_size > 0) {
data_size = total_size > ISP_MAX_BUFFERSIZE ? ISP_MAX_BUFFERSIZE
: total_size;
- ts_info("Flash firmware to %08x,size:%u bytes",
+ ts_info("Flash firmware to 0x%05X,size:%u bytes",
subsys_base_addr + offset, data_size);
memcpy(fw_packet, &subsys->data[offset], data_size);
@@ -828,7 +835,7 @@ static int goodix_flash_subsystem(struct fw_subsys_info *subsys)
r = goodix_flash_package(subsys->type, fw_packet,
subsys_base_addr + offset, data_size + 4);
if (r) {
- ts_err("failed flash to %08x,size:%u bytes",
+ ts_err("failed flash to 0x%05X,size:%u bytes",
subsys_base_addr + offset, data_size);
break;
}
@@ -866,7 +873,7 @@ static int goodix_flash_firmware(struct fw_update_ctrl *fw_ctrl)
/* flash config data first if we have */
if (fw_ctrl->ic_config && fw_ctrl->ic_config->len) {
subsys_cfg.data = fw_ctrl->ic_config->data;
- subsys_cfg.size = fw_ctrl->ic_config->len;
+ subsys_cfg.size = GOODIX_CFG_MAX_SIZE;
subsys_cfg.flash_addr = config_data_reg;
subsys_cfg.type = CONFIG_DATA_TYPE;
r = goodix_flash_subsystem(&subsys_cfg);
@@ -938,10 +945,10 @@ int goodix_fw_update_proc(struct fw_update_ctrl *fwu_ctrl)
if (!(fwu_ctrl->mode & UPDATE_MODE_FORCE)) {
ret = goodix_fw_version_compare(fwu_ctrl);
if (!ret) {
- ts_info("firmware upgraded");
+ ts_info("no need to upgrade");
return 0;
- } else
- ts_info("need to upgrade");
+ }
+ ts_info("need to upgrade");
}
start_update:
@@ -1029,73 +1036,29 @@ static ssize_t goodix_sysfs_update_en_store(struct device *dev,
return -EINVAL;
}
-static ssize_t goodix_sysfs_fwsize_show(
- struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
- int r = -EINVAL;
-
- if (fw_ctrl && fw_ctrl->fw_data.firmware)
- r = snprintf(buf, PAGE_SIZE, "%zu\n",
- fw_ctrl->fw_data.firmware->size);
- return r;
-}
-
-static ssize_t goodix_sysfs_fwsize_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
- struct firmware *fw;
- u8 **data;
- size_t size = 0;
-
- if (!fw_ctrl)
- return -EINVAL;
-
- if (sscanf(buf, "%zu", &size) < 0 || !size) {
- ts_err("Failed to get fwsize");
- return -EFAULT;
- }
-
- /* use vmalloc to alloc huge memory */
- fw = vmalloc(sizeof(*fw) + size);
- if (!fw)
- return -ENOMEM;
- mutex_lock(&fw_ctrl->mutex);
- memset(fw, 0x00, sizeof(*fw) + size);
- data = (u8 **)&fw->data;
- *data = (u8 *)fw + sizeof(struct firmware);
- fw->size = size;
- fw_ctrl->fw_data.firmware = fw;
- fw_ctrl->mode = UPDATE_MODE_SRC_SYSFS;
- mutex_unlock(&fw_ctrl->mutex);
- return count;
-}
-
static ssize_t goodix_sysfs_fwimage_store(struct file *file,
struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t pos,
size_t count)
{
- struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
- struct firmware_data *fw_data;
-
- fw_data = &fw_ctrl->fw_data;
-
- if (!fw_data->firmware) {
- ts_err("Need set fw image size first");
- return -ENOMEM;
- }
+ struct firmware **fw = &goodix_fw_update_ctrl.fw_data.fw_sysfs;
- if (fw_data->firmware->size == 0) {
- ts_err("Invalid firmware size");
- return -EINVAL;
+ if (*fw == NULL) {
+ *fw = kzalloc(sizeof(**fw), GFP_KERNEL);
+ if (*fw == NULL)
+ return -ENOMEM;
+ (*fw)->data = vmalloc(GOODIX_FW_MAX_SIEZE);
+ if ((*fw)->data == NULL) {
+ kfree(*fw);
+ *fw = NULL;
+ return -ENOMEM;
+ }
}
- if (pos + count > fw_data->firmware->size)
+ if (pos + count > GOODIX_FW_MAX_SIEZE)
return -EFAULT;
- mutex_lock(&fw_ctrl->mutex);
- memcpy((u8 *)&fw_data->firmware->data[pos], buf, count);
- mutex_unlock(&fw_ctrl->mutex);
+ memcpy((u8 *)&(*fw)->data[pos], buf, count);
+ (*fw)->size = pos + count;
+
return count;
}
@@ -1136,12 +1099,10 @@ static ssize_t goodix_sysfs_result_show(
}
static DEVICE_ATTR(update_en, 0220, NULL, goodix_sysfs_update_en_store);
-static DEVICE_ATTR(
- fwsize, 0664, goodix_sysfs_fwsize_show, goodix_sysfs_fwsize_store);
static DEVICE_ATTR(result, 0664, goodix_sysfs_result_show, NULL);
static struct attribute *goodix_fwu_attrs[] = { &dev_attr_update_en.attr,
- &dev_attr_fwsize.attr, &dev_attr_result.attr };
+ &dev_attr_result.attr };
static int goodix_fw_sysfs_init(
struct goodix_ts_core *core_data, struct fw_update_ctrl *fw_ctrl)
@@ -1168,7 +1129,7 @@ static int goodix_fw_sysfs_init(
}
fw_ctrl->attr_fwimage.attr.name = "fwimage";
- fw_ctrl->attr_fwimage.attr.mode = 0666;
+ fw_ctrl->attr_fwimage.attr.mode = 0664;
fw_ctrl->attr_fwimage.size = 0;
fw_ctrl->attr_fwimage.write = goodix_sysfs_fwimage_store;
ret = sysfs_create_bin_file(fw_ctrl->kobj, &fw_ctrl->attr_fwimage);
@@ -1244,7 +1205,6 @@ static inline void goodix_release_firmware(struct firmware_data *fw_data)
static int goodix_fw_update_thread(void *data)
{
struct fw_update_ctrl *fwu_ctrl = data;
- struct firmware *temp_firmware = NULL;
ktime_t start, end;
int r = -EINVAL;
@@ -1253,37 +1213,45 @@ static int goodix_fw_update_thread(void *data)
fwu_ctrl->status = UPSTA_NOTWORK;
mutex_lock(&fwu_ctrl->mutex);
+ ts_debug("notify update start");
+ goodix_ts_blocking_notify(NOTIFY_FWUPDATE_START, NULL);
+
if (fwu_ctrl->mode & UPDATE_MODE_SRC_REQUEST) {
ts_info("Firmware request update starts");
r = goodix_request_firmware(
&fwu_ctrl->fw_data, fwu_ctrl->fw_name);
if (r < 0)
goto out;
-
} else if (fwu_ctrl->mode & UPDATE_MODE_SRC_SYSFS) {
- if (!fwu_ctrl->fw_data.firmware) {
+ if (!fwu_ctrl->fw_data.fw_sysfs) {
ts_err("Invalid firmware from sysfs");
r = -EINVAL;
goto out;
}
+ if (fwu_ctrl->fw_data.fw_sysfs->size < 4096) {
+ ts_err("Invalid firmware size[%ld] from sysfs",
+ fwu_ctrl->fw_data.fw_sysfs->size);
+ vfree(fwu_ctrl->fw_data.fw_sysfs->data);
+ kfree(fwu_ctrl->fw_data.fw_sysfs);
+ fwu_ctrl->fw_data.fw_sysfs = NULL;
+ r = -EINVAL;
+ goto out;
+ }
} else {
ts_err("unknown update mode 0x%x", fwu_ctrl->mode);
r = -EINVAL;
goto out;
}
- ts_debug("notify update start");
- goodix_ts_blocking_notify(NOTIFY_FWUPDATE_START, NULL);
-
/* ready to update */
ts_debug("start update proc");
r = goodix_fw_update_proc(fwu_ctrl);
/* clean */
- if (fwu_ctrl->mode & UPDATE_MODE_SRC_HEAD) {
- kfree(fwu_ctrl->fw_data.firmware);
- fwu_ctrl->fw_data.firmware = NULL;
- temp_firmware = NULL;
+ if (fwu_ctrl->mode & UPDATE_MODE_SRC_SYSFS) {
+ vfree(fwu_ctrl->fw_data.fw_sysfs->data);
+ kfree(fwu_ctrl->fw_data.fw_sysfs);
+ fwu_ctrl->fw_data.fw_sysfs = NULL;
} else if (fwu_ctrl->mode & UPDATE_MODE_SRC_REQUEST) {
goodix_release_firmware(&fwu_ctrl->fw_data);
}
diff --git a/goodix_brl_hw.c b/goodix_brl_hw.c
index 41bf117..19a2c1b 100644
--- a/goodix_brl_hw.c
+++ b/goodix_brl_hw.c
@@ -65,8 +65,7 @@ static int brl_select_spi_mode(struct goodix_ts_core *cd)
if (!ret && r_value == w_value)
return 0;
}
- ts_err("failed switch SPI mode after reset, ret:%d r_value:%02x", ret,
- r_value);
+ ts_err("failed switch SPI mode, ret:%d r_value:%02x", ret, r_value);
return -EINVAL;
}
@@ -93,8 +92,8 @@ static int brl_dev_confirm(struct goodix_ts_core *cd)
}
if (retry < 0) {
- ret = -EINVAL;
ts_err("device confirm failed, rx_buf:%*ph", 8, rx_buf);
+ return -EINVAL;
}
ts_info("device connected");
@@ -254,17 +253,12 @@ power_off:
return ret;
}
-#define GOODIX_SLEEP_CMD 0x84
int brl_suspend(struct goodix_ts_core *cd)
{
- struct goodix_ts_cmd sleep_cmd;
+ u32 cmd_reg = cd->ic_info.misc.cmd_addr;
+ u8 sleep_cmd[] = { 0x00, 0x00, 0x04, 0x84, 0x88, 0x00 };
- sleep_cmd.cmd = GOODIX_SLEEP_CMD;
- sleep_cmd.len = 4;
- if (cd->hw_ops->send_cmd(cd, &sleep_cmd))
- ts_err("failed send sleep cmd");
-
- return 0;
+ return cd->hw_ops->write(cd, cmd_reg, sleep_cmd, sizeof(sleep_cmd));
}
int brl_resume(struct goodix_ts_core *cd)
@@ -272,12 +266,16 @@ int brl_resume(struct goodix_ts_core *cd)
return cd->hw_ops->reset(cd, GOODIX_NORMAL_RESET_DELAY_MS);
}
-#define GOODIX_GESTURE_CMD 0x12
+#define GOODIX_GESTURE_CMD_BA 0x12
+#define GOODIX_GESTURE_CMD 0xA6
int brl_gesture(struct goodix_ts_core *cd, int gesture_type)
{
struct goodix_ts_cmd cmd;
- cmd.cmd = GOODIX_GESTURE_CMD;
+ if (cd->bus->ic_type == IC_TYPE_BERLIN_A)
+ cmd.cmd = GOODIX_GESTURE_CMD_BA;
+ else
+ cmd.cmd = GOODIX_GESTURE_CMD;
cmd.len = 5;
cmd.data[0] = gesture_type;
if (cd->hw_ops->send_cmd(cd, &cmd))
@@ -373,7 +371,7 @@ static int brl_send_cmd(struct goodix_ts_core *cd, struct goodix_ts_cmd *cmd)
ts_debug("cmd ack data %*ph", (int)sizeof(cmd_ack),
cmd_ack.buf);
if (cmd_ack.ack == CMD_ACK_OK) {
- usleep_range(2000, 2100);
+ msleep(40); // wait for cmd response
return 0;
}
if (cmd_ack.ack == CMD_ACK_BUSY ||
@@ -960,6 +958,7 @@ static int brl_esd_check(struct goodix_ts_core *cd)
#define GOODIX_TOUCH_EVENT 0x80
#define GOODIX_REQUEST_EVENT 0x40
#define GOODIX_GESTURE_EVENT 0x20
+#define GOODIX_FP_EVENT 0x08
#define POINT_TYPE_STYLUS_HOVER 0x01
#define POINT_TYPE_STYLUS 0x03
@@ -1064,6 +1063,9 @@ static int goodix_touch_handler(struct goodix_ts_core *cd,
}
}
+ /* read done */
+ hw_ops->after_event_handler(cd);
+
if (touch_num > 0) {
point_type = buffer[IRQ_EVENT_HEAD_LEN] & 0x0F;
if (point_type == POINT_TYPE_STYLUS ||
@@ -1090,6 +1092,8 @@ static int goodix_touch_handler(struct goodix_ts_core *cd,
}
}
+ ts_event->fp_flag = pre_buf[0] & GOODIX_FP_EVENT;
+
if (touch_num > 0 && (point_type == POINT_TYPE_STYLUS ||
point_type == POINT_TYPE_STYLUS_HOVER)) {
/* stylus info */
@@ -1140,10 +1144,14 @@ static int brl_event_handler(
return ret;
}
+ if (pre_buf[0] == 0x00) {
+ ts_debug("invalid touch head");
+ return -EINVAL;
+ }
+
if (checksum_cmp(pre_buf, IRQ_EVENT_HEAD_LEN, CHECKSUM_MODE_U8_LE)) {
- ts_debug("touch head checksum err");
- ts_debug("touch_head %*ph", IRQ_EVENT_HEAD_LEN, pre_buf);
- ts_event->retry = 1;
+ ts_debug("touch head checksum err[%*ph]", IRQ_EVENT_HEAD_LEN,
+ pre_buf);
return -EINVAL;
}
@@ -1161,10 +1169,16 @@ static int brl_event_handler(
else
ts_debug("unsupported request code 0x%x", pre_buf[2]);
}
+
if (event_status & GOODIX_GESTURE_EVENT) {
ts_event->event_type = EVENT_GESTURE;
ts_event->gesture_type = pre_buf[4];
+ memcpy(ts_event->gesture_data, &pre_buf[8],
+ GOODIX_GESTURE_DATA_LEN);
}
+ /* read done */
+ hw_ops->after_event_handler(cd);
+
return 0;
}
@@ -1174,6 +1188,8 @@ static int brl_after_event_handler(struct goodix_ts_core *cd)
struct goodix_ic_info_misc *misc = &cd->ic_info.misc;
u8 sync_clean = 0;
+ if (cd->tools_ctrl_sync)
+ return 0;
return hw_ops->write(cd, misc->touch_data_addr, &sync_clean, 1);
}
@@ -1318,7 +1334,8 @@ static int brl_get_capacitance_data(
return -EIO;
}
- if (cd->bus->ic_type == IC_TYPE_BERLIN_D)
+ if (cd->bus->ic_type == IC_TYPE_BERLIN_D ||
+ cd->bus->ic_type == IC_TYPE_NOTTINGHAM)
return brld_get_cap_data(cd, info);
/* disable irq & close esd */
diff --git a/goodix_brl_i2c.c b/goodix_brl_i2c.c
index be7d638..1173add 100644
--- a/goodix_brl_i2c.c
+++ b/goodix_brl_i2c.c
@@ -173,7 +173,7 @@ static int goodix_i2c_probe(
return -EIO;
/* get ic type */
- ret = goodix_get_ic_type(client->dev.of_node);
+ ret = goodix_get_ic_type(client->dev.of_node, &goodix_i2c_bus);
if (ret < 0)
return ret;
@@ -225,13 +225,16 @@ static int goodix_i2c_remove(struct i2c_client *client)
#ifdef CONFIG_OF
static const struct of_device_id i2c_matches[] = {
{
- .compatible = "goodix,gt9897",
+ .compatible = "goodix,brl-a",
},
{
- .compatible = "goodix,gt9966",
+ .compatible = "goodix,brl-b",
},
{
- .compatible = "goodix,gt9916",
+ .compatible = "goodix,brl-d",
+ },
+ {
+ .compatible = "goodix,nottingham",
},
{},
};
diff --git a/goodix_brl_spi.c b/goodix_brl_spi.c
index 8f53776..413cd9b 100644
--- a/goodix_brl_spi.c
+++ b/goodix_brl_spi.c
@@ -159,11 +159,8 @@ static int goodix_spi_write(struct device *dev, unsigned int addr,
int ret = 0;
tx_buf = kzalloc(SPI_WRITE_PREFIX_LEN + len, GFP_KERNEL);
- if (!tx_buf) {
- ts_err("alloc tx_buf failed, size:%d",
- SPI_WRITE_PREFIX_LEN + len);
+ if (!tx_buf)
return -ENOMEM;
- }
spi_message_init(&spi_msg);
memset(&xfers, 0, sizeof(xfers));
@@ -209,7 +206,7 @@ static int goodix_spi_probe(struct spi_device *spi)
}
/* get ic type */
- ret = goodix_get_ic_type(spi->dev.of_node);
+ ret = goodix_get_ic_type(spi->dev.of_node, &goodix_spi_bus);
if (ret < 0)
return ret;
@@ -264,16 +261,16 @@ static int goodix_spi_remove(struct spi_device *spi)
#ifdef CONFIG_OF
static const struct of_device_id spi_matches[] = {
{
- .compatible = "goodix,gt9897S",
+ .compatible = "goodix,brl-a",
},
{
- .compatible = "goodix,gt9897T",
+ .compatible = "goodix,brl-b",
},
{
- .compatible = "goodix,gt9966S",
+ .compatible = "goodix,brl-d",
},
{
- .compatible = "goodix,gt9916S",
+ .compatible = "goodix,nottingham",
},
{},
};
diff --git a/goodix_cfg_bin.c b/goodix_cfg_bin.c
index 922aee4..42b991a 100644
--- a/goodix_cfg_bin.c
+++ b/goodix_cfg_bin.c
@@ -167,9 +167,9 @@ static int goodix_parse_cfg_bin(struct goodix_cfg_bin *cfg_bin)
/*check cfg_bin valid*/
checksum = 0;
- for (i = TS_BIN_VERSION_START_INDEX; i < cfg_bin->bin_data_len; i++) {
+ for (i = TS_BIN_VERSION_START_INDEX; i < cfg_bin->bin_data_len; i++)
checksum += cfg_bin->bin_data[i];
- }
+
if (checksum != cfg_bin->head.checksum) {
ts_err("cfg_bin checksum check filed 0x%02x != 0x%02x",
cfg_bin->head.checksum, checksum);
@@ -180,10 +180,8 @@ static int goodix_parse_cfg_bin(struct goodix_cfg_bin *cfg_bin)
cfg_bin->cfg_pkgs = kzalloc(
sizeof(struct goodix_cfg_package) * cfg_bin->head.pkg_num,
GFP_KERNEL);
- if (!cfg_bin->cfg_pkgs) {
- ts_err("cfg_pkgs, allocate memory ERROR");
+ if (!cfg_bin->cfg_pkgs)
return -ENOMEM;
- }
/*get cfg_pkg's info*/
for (i = 0; i < cfg_bin->head.pkg_num; i++) {
@@ -296,8 +294,7 @@ static int goodix_get_reg_and_cfg(
err_out:
/* parse config enter error, release memory alloced */
for (i = 0; i < GOODIX_MAX_CONFIG_GROUP; i++) {
- if (cd->ic_configs[i])
- kfree(cd->ic_configs[i]);
+ kfree(cd->ic_configs[i]);
cd->ic_configs[i] = NULL;
}
return -EINVAL;
diff --git a/goodix_ts_core.c b/goodix_ts_core.c
index 54e18af..1b25d94 100644
--- a/goodix_ts_core.c
+++ b/goodix_ts_core.c
@@ -26,6 +26,8 @@
#endif
#include "goodix_ts_core.h"
+/* goodix fb test */
+// #include "../../../video/fbdev/core/fb_firefly.h"
#define GOODIX_DEFAULT_CFG_NAME "goodix_cfg_group.cfg"
#define GOOIDX_INPUT_PHYS "goodix_ts/input0"
@@ -86,8 +88,6 @@ static int __do_register_ext_module(struct goodix_ext_module *module)
list_add(&module->list, insert_point->prev);
mutex_unlock(&goodix_modules.mutex);
- ts_info("Module [%s] registered,priority:%u", module->name,
- module->priority);
return 0;
}
@@ -133,13 +133,13 @@ int goodix_register_ext_module(struct goodix_ext_module *module)
if (!module)
return -EINVAL;
- ts_info("goodix_register_ext_module IN");
+ ts_info("IN");
goodix_core_module_init();
INIT_WORK(&module->work, goodix_register_ext_module_work);
schedule_work(&module->work);
- ts_info("goodix_register_ext_module OUT");
+ ts_info("OUT");
return 0;
}
@@ -151,7 +151,8 @@ int goodix_register_ext_module_no_wait(struct goodix_ext_module *module)
{
if (!module)
return -EINVAL;
- ts_info("goodix_register_ext_module_no_wait IN");
+
+ ts_info("IN");
goodix_core_module_init();
/* driver probe failed */
if (core_module_prob_sate != CORE_MODULE_PROB_SUCCESS) {
@@ -268,7 +269,7 @@ struct kobject *goodix_get_default_kobj(void)
}
/* show driver information */
-static ssize_t goodix_ts_driver_info_show(
+static ssize_t driver_info_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(
@@ -276,18 +277,19 @@ static ssize_t goodix_ts_driver_info_show(
}
/* show chip infoamtion */
-static ssize_t goodix_ts_chip_info_show(
+static ssize_t chip_info_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
- struct goodix_ts_core *core_data = dev_get_drvdata(dev);
- struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
+ struct goodix_ts_core *cd = dev_get_drvdata(dev);
+ struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
struct goodix_fw_version chip_ver;
+ struct goodix_ic_info ic_info;
u8 temp_pid[8] = { 0 };
int ret;
int cnt = -EINVAL;
if (hw_ops->read_version) {
- ret = hw_ops->read_version(core_data, &chip_ver);
+ ret = hw_ops->read_version(cd, &chip_ver);
if (!ret) {
memcpy(temp_pid, chip_ver.rom_pid,
sizeof(chip_ver.rom_pid));
@@ -306,13 +308,13 @@ static ssize_t goodix_ts_chip_info_show(
}
if (hw_ops->get_ic_info) {
- ret = hw_ops->get_ic_info(core_data, &core_data->ic_info);
+ ret = hw_ops->get_ic_info(cd, &ic_info);
if (!ret) {
cnt += snprintf(&buf[cnt], PAGE_SIZE, "config_id:%x\n",
- core_data->ic_info.version.config_id);
+ ic_info.version.config_id);
cnt += snprintf(&buf[cnt], PAGE_SIZE,
"config_version:%x\n",
- core_data->ic_info.version.config_version);
+ ic_info.version.config_version);
}
}
@@ -334,7 +336,7 @@ static ssize_t goodix_ts_reset_store(struct device *dev,
}
/* read config */
-static ssize_t goodix_ts_read_cfg_show(
+static ssize_t read_cfg_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
struct goodix_ts_core *core_data = dev_get_drvdata(dev);
@@ -409,8 +411,7 @@ static int goodix_ts_convert_0x_data(
continue;
if (temp_index >= m_size) {
- ts_err("exchange cfg data error, overflow,"
- "temp_index:%d,m_size:%d",
+ ts_err("exchange cfg data error, overflow, temp_index:%d,m_size:%d",
temp_index, m_size);
return -EINVAL;
}
@@ -434,13 +435,9 @@ static ssize_t goodix_ts_send_cfg_store(struct device *dev,
struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
struct goodix_ic_config *config = NULL;
const struct firmware *cfg_img = NULL;
- int en;
int ret;
- if (sscanf(buf, "%d", &en) != 1)
- return -EINVAL;
-
- if (en != 1)
+ if (buf[0] != '1')
return -EINVAL;
hw_ops->irq_enable(core_data, false);
@@ -720,11 +717,11 @@ static ssize_t goodix_ts_debug_log_store(struct device *dev,
return count;
}
-static DEVICE_ATTR(driver_info, 0444, goodix_ts_driver_info_show, NULL);
-static DEVICE_ATTR(chip_info, 0444, goodix_ts_chip_info_show, NULL);
+static DEVICE_ATTR(driver_info, 0440, driver_info_show, NULL);
+static DEVICE_ATTR(chip_info, 0440, chip_info_show, NULL);
static DEVICE_ATTR(reset, 0220, NULL, goodix_ts_reset_store);
static DEVICE_ATTR(send_cfg, 0220, NULL, goodix_ts_send_cfg_store);
-static DEVICE_ATTR(read_cfg, 0444, goodix_ts_read_cfg_show, NULL);
+static DEVICE_ATTR(read_cfg, 0440, read_cfg_show, NULL);
static DEVICE_ATTR(reg_rw, 0664, goodix_ts_reg_rw_show, goodix_ts_reg_rw_store);
static DEVICE_ATTR(
irq_info, 0664, goodix_ts_irq_info_show, goodix_ts_irq_info_store);
@@ -779,16 +776,12 @@ static int rawdata_proc_show(struct seq_file *m, void *v)
int i;
int index;
- if (!m || !v || !cd) {
- ts_err("rawdata_proc_show, input null ptr");
+ if (!m || !v || !cd)
return -EIO;
- }
info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
- ts_err("Failed to alloc rawdata info memory");
+ if (!info)
return -ENOMEM;
- }
ret = cd->hw_ops->get_capacitance_data(cd, info);
if (ret < 0) {
@@ -799,19 +792,19 @@ static int rawdata_proc_show(struct seq_file *m, void *v)
rx = info->buff[0];
tx = info->buff[1];
seq_printf(m, "TX:%d RX:%d\n", tx, rx);
- seq_printf(m, "mutual_rawdata:\n");
+ seq_puts(m, "mutual_rawdata:\n");
index = 2;
for (i = 0; i < tx * rx; i++) {
seq_printf(m, "%5d,", info->buff[index + i]);
if ((i + 1) % tx == 0)
- seq_printf(m, "\n");
+ seq_puts(m, "\n");
}
- seq_printf(m, "mutual_diffdata:\n");
+ seq_puts(m, "mutual_diffdata:\n");
index += tx * rx;
for (i = 0; i < tx * rx; i++) {
seq_printf(m, "%3d,", info->buff[index + i]);
if ((i + 1) % tx == 0)
- seq_printf(m, "\n");
+ seq_puts(m, "\n");
}
exit:
@@ -825,23 +818,39 @@ static int rawdata_proc_open(struct inode *inode, struct file *file)
file, rawdata_proc_show, PDE_DATA(inode), PAGE_SIZE * 10);
}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
static const struct proc_ops rawdata_proc_fops = {
.proc_open = rawdata_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
+#else
+static const struct file_operations rawdata_proc_fops = {
+ .open = rawdata_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif
static void goodix_ts_procfs_init(struct goodix_ts_core *core_data)
{
+ struct proc_dir_entry *proc_entry;
+
if (!proc_mkdir("goodix_ts", NULL))
return;
- proc_create_data("goodix_ts/tp_capacitance_data", 0666, NULL,
- &rawdata_proc_fops, core_data);
+ proc_entry = proc_create_data("goodix_ts/tp_capacitance_data", 0664,
+ NULL, &rawdata_proc_fops, core_data);
+ if (!proc_entry)
+ ts_err("failed to create proc entry");
+
+ driver_test_proc_init(core_data);
}
static void goodix_ts_procfs_exit(struct goodix_ts_core *core_data)
{
+ driver_test_proc_remove();
remove_proc_entry("goodix_ts/tp_capacitance_data", NULL);
remove_proc_entry("goodix_ts", NULL);
}
@@ -881,7 +890,7 @@ int goodix_ts_blocking_notify(enum ts_notify_event evt, void *v)
return ret;
}
-#ifdef CONFIG_OF
+#if IS_ENABLED(CONFIG_OF)
/**
* goodix_parse_dt_resolution - parse resolution from dt
* @node: devicetree node
@@ -1041,15 +1050,18 @@ static int goodix_parse_dt(
return r;
}
+ /* get sleep mode flag */
+ board_data->sleep_enable =
+ of_property_read_bool(node, "goodix,sleep-enable");
+
/*get pen-enable switch and pen keys, must after "key map"*/
board_data->pen_enable =
of_property_read_bool(node, "goodix,pen-enable");
- if (board_data->pen_enable)
- ts_info("goodix pen enabled");
- ts_debug("[DT]x:%d, y:%d, w:%d, p:%d", board_data->panel_max_x,
- board_data->panel_max_y, board_data->panel_max_w,
- board_data->panel_max_p);
+ ts_info("[DT]x:%d, y:%d, w:%d, p:%d sleep_enable:%d pen_enable:%d",
+ board_data->panel_max_x, board_data->panel_max_y,
+ board_data->panel_max_w, board_data->panel_max_p,
+ board_data->sleep_enable, board_data->pen_enable);
return 0;
}
#endif
@@ -1067,6 +1079,10 @@ static void goodix_ts_report_pen(
input_report_abs(dev, ABS_X, pen_data->coords.x);
input_report_abs(dev, ABS_Y, pen_data->coords.y);
input_report_abs(dev, ABS_PRESSURE, pen_data->coords.p);
+ if (pen_data->coords.p == 0)
+ input_report_abs(dev, ABS_DISTANCE, 1);
+ else
+ input_report_abs(dev, ABS_DISTANCE, 0);
input_report_abs(dev, ABS_TILT_X, pen_data->coords.tilt_x);
input_report_abs(dev, ABS_TILT_Y, pen_data->coords.tilt_y);
ts_debug(
@@ -1102,7 +1118,7 @@ static void goodix_ts_report_finger(
for (i = 0; i < GOODIX_MAX_TOUCH; i++) {
if (touch_data->coords[i].status == TS_TOUCH) {
- ts_debug("report: id %d, x %d, y %d, w %d", i,
+ ts_debug("report: id[%d], x %d, y %d, w %d", i,
touch_data->coords[i].x,
touch_data->coords[i].y,
touch_data->coords[i].w);
@@ -1193,15 +1209,10 @@ static irqreturn_t goodix_ts_threadirq_func(int irq, void *data)
goodix_ts_report_pen(
core_data->pen_dev, &ts_event->pen_data);
}
- if (ts_event->event_type == EVENT_REQUEST) {
+ if (ts_event->event_type == EVENT_REQUEST)
goodix_ts_request_handle(core_data, ts_event);
- }
}
- if (!core_data->tools_ctrl_sync && !ts_event->retry)
- hw_ops->after_event_handler(core_data);
- ts_event->retry = 0;
-
return IRQ_HANDLED;
}
@@ -1397,15 +1408,12 @@ static int goodix_ts_input_dev_config(struct goodix_ts_core *core_data)
input_dev->id.vendor = 0xBEEF;
input_dev->id.version = 10427;
- __set_bit(EV_SYN, input_dev->evbit);
- __set_bit(EV_KEY, input_dev->evbit);
- __set_bit(EV_ABS, input_dev->evbit);
- __set_bit(BTN_TOUCH, input_dev->keybit);
- __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
-
-#ifdef INPUT_PROP_DIRECT
- __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
-#endif
+ set_bit(EV_SYN, input_dev->evbit);
+ set_bit(EV_KEY, input_dev->evbit);
+ set_bit(EV_ABS, input_dev->evbit);
+ set_bit(BTN_TOUCH, input_dev->keybit);
+ set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+ set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
/* set input parameters */
input_set_abs_params(
@@ -1423,6 +1431,8 @@ static int goodix_ts_input_dev_config(struct goodix_ts_core *core_data)
#endif
input_set_capability(input_dev, EV_KEY, KEY_POWER);
+ input_set_capability(input_dev, EV_KEY, KEY_WAKEUP);
+ input_set_capability(input_dev, EV_KEY, KEY_GOTO);
r = input_register_device(input_dev);
if (r < 0) {
@@ -1455,19 +1465,20 @@ static int goodix_ts_pen_dev_config(struct goodix_ts_core *core_data)
pen_dev->id.version = 10427;
pen_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- __set_bit(ABS_X, pen_dev->absbit);
- __set_bit(ABS_Y, pen_dev->absbit);
- __set_bit(ABS_TILT_X, pen_dev->absbit);
- __set_bit(ABS_TILT_Y, pen_dev->absbit);
- __set_bit(BTN_STYLUS, pen_dev->keybit);
- __set_bit(BTN_STYLUS2, pen_dev->keybit);
- __set_bit(BTN_TOUCH, pen_dev->keybit);
- __set_bit(BTN_TOOL_PEN, pen_dev->keybit);
- __set_bit(INPUT_PROP_DIRECT, pen_dev->propbit);
+ set_bit(ABS_X, pen_dev->absbit);
+ set_bit(ABS_Y, pen_dev->absbit);
+ set_bit(ABS_TILT_X, pen_dev->absbit);
+ set_bit(ABS_TILT_Y, pen_dev->absbit);
+ set_bit(BTN_STYLUS, pen_dev->keybit);
+ set_bit(BTN_STYLUS2, pen_dev->keybit);
+ set_bit(BTN_TOUCH, pen_dev->keybit);
+ set_bit(BTN_TOOL_PEN, pen_dev->keybit);
+ set_bit(INPUT_PROP_DIRECT, pen_dev->propbit);
input_set_abs_params(pen_dev, ABS_X, 0, ts_bdata->panel_max_x, 0, 0);
input_set_abs_params(pen_dev, ABS_Y, 0, ts_bdata->panel_max_y, 0, 0);
input_set_abs_params(
pen_dev, ABS_PRESSURE, 0, ts_bdata->panel_max_p, 0, 0);
+ input_set_abs_params(pen_dev, ABS_DISTANCE, 0, 255, 0, 0);
input_set_abs_params(pen_dev, ABS_TILT_X, -GOODIX_PEN_MAX_TILT,
GOODIX_PEN_MAX_TILT, 0, 0);
input_set_abs_params(pen_dev, ABS_TILT_Y, -GOODIX_PEN_MAX_TILT,
@@ -1553,9 +1564,9 @@ static void goodix_ts_esd_on(struct goodix_ts_core *cd)
return;
atomic_set(&ts_esd->esd_on, 1);
- if (!schedule_delayed_work(&ts_esd->esd_work, 2 * HZ)) {
+ if (!schedule_delayed_work(&ts_esd->esd_work, 2 * HZ))
ts_info("esd work already in workqueue");
- }
+
ts_info("esd on");
}
@@ -1652,7 +1663,7 @@ static void goodix_ts_release_connects(struct goodix_ts_core *core_data)
/**
* goodix_ts_suspend - Touchscreen suspend function
- * Called by PM/FB/EARLYSUSPEN module to put the device to sleep
+ * Called by PM/FB/EARLYSUSPEN module to put the device to sleep
*/
static int goodix_ts_suspend(struct goodix_ts_core *core_data)
{
@@ -1697,8 +1708,10 @@ static int goodix_ts_suspend(struct goodix_ts_core *core_data)
mutex_unlock(&goodix_modules.mutex);
/* enter sleep mode or power off */
- if (hw_ops->suspend)
+ if (core_data->board_data.sleep_enable)
hw_ops->suspend(core_data);
+ else
+ goodix_ts_power_off(core_data);
/* inform exteranl modules */
mutex_lock(&goodix_modules.mutex);
@@ -1743,6 +1756,7 @@ static int goodix_ts_resume(struct goodix_ts_core *core_data)
ts_info("Resume start");
atomic_set(&core_data->suspended, 0);
+ hw_ops->irq_enable(core_data, false);
mutex_lock(&goodix_modules.mutex);
if (!list_empty(&goodix_modules.head)) {
@@ -1765,8 +1779,10 @@ static int goodix_ts_resume(struct goodix_ts_core *core_data)
mutex_unlock(&goodix_modules.mutex);
/* reset device or power on*/
- if (hw_ops->resume)
+ if (core_data->board_data.sleep_enable)
hw_ops->resume(core_data);
+ else
+ goodix_ts_power_on(core_data);
mutex_lock(&goodix_modules.mutex);
if (!list_empty(&goodix_modules.head)) {
@@ -1797,7 +1813,7 @@ out:
return 0;
}
-#ifdef CONFIG_FB
+#if IS_ENABLED(CONFIG_FB)
/**
* goodix_ts_fb_notifier_callback - Framebuffer notifier callback
* Called by kernel during framebuffer blanck/unblank phrase
@@ -1810,10 +1826,9 @@ int goodix_ts_fb_notifier_callback(
struct fb_event *fb_event = data;
if (fb_event && fb_event->data && core_data) {
- if (event == FB_EARLY_EVENT_BLANK) {
- /* before fb blank */
- } else if (event == FB_EVENT_BLANK) {
+ if (event == FB_EVENT_BLANK) {
int *blank = fb_event->data;
+
if (*blank == FB_BLANK_UNBLANK)
goodix_ts_resume(core_data);
else if (*blank == FB_BLANK_POWERDOWN)
@@ -1825,8 +1840,8 @@ int goodix_ts_fb_notifier_callback(
}
#endif
-#ifdef CONFIG_PM
-#if !defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)
+#if IS_ENABLED(CONFIG_PM)
+#if !IS_ENABLED(CONFIG_FB) && !IS_ENABLED(CONFIG_HAS_EARLYSUSPEND)
/**
* goodix_ts_pm_suspend - PM suspend function
* Called by kernel during system suspend phrase
@@ -1907,7 +1922,7 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
}
ts_info("success register irq");
-#ifdef CONFIG_FB
+#if IS_ENABLED(CONFIG_FB)
cd->fb_notifier.notifier_call = goodix_ts_fb_notifier_callback;
if (fb_register_client(&cd->fb_notifier))
ts_err("Failed to register fb notifier client:%d", ret);
@@ -2042,8 +2057,7 @@ err_out:
ts_err("stage2 init failed");
cd->init_stage = CORE_INIT_FAIL;
for (i = 0; i < GOODIX_MAX_CONFIG_GROUP; i++) {
- if (cd->ic_configs[i])
- kfree(cd->ic_configs[i]);
+ kfree(cd->ic_configs[i]);
cd->ic_configs[i] = NULL;
}
return ret;
@@ -2063,6 +2077,17 @@ static int goodix_start_later_init(struct goodix_ts_core *ts_core)
return 0;
}
+/* goodix fb test */
+// static void test_suspend(void)
+// {
+// goodix_ts_suspend(goodix_modules.core_data);
+// }
+
+// static void test_resume(void)
+// {
+// goodix_ts_resume(goodix_modules.core_data);
+// }
+
/**
* goodix_ts_probe - called by kernel when Goodix touch
* platform driver is added.
@@ -2073,7 +2098,7 @@ static int goodix_ts_probe(struct platform_device *pdev)
struct goodix_bus_interface *bus_interface;
int ret;
- ts_info("goodix_ts_probe IN");
+ ts_info("IN");
bus_interface = pdev->dev.platform_data;
if (!bus_interface) {
@@ -2085,7 +2110,6 @@ static int goodix_ts_probe(struct platform_device *pdev)
core_data = devm_kzalloc(
&pdev->dev, sizeof(struct goodix_ts_core), GFP_KERNEL);
if (!core_data) {
- ts_err("Failed to allocate memory for core data");
core_module_prob_sate = CORE_MODULE_PROB_FAILED;
return -ENOMEM;
}
@@ -2141,6 +2165,9 @@ static int goodix_ts_probe(struct platform_device *pdev)
/* debug node init */
goodix_tools_init();
+ /* goodix fb test */
+ // fb_firefly_register(test_suspend, test_resume);
+
core_data->init_stage = CORE_INIT_STAGE1;
goodix_modules.core_data = core_data;
core_module_prob_sate = CORE_MODULE_PROB_SUCCESS;
@@ -2171,7 +2198,7 @@ static int goodix_ts_remove(struct platform_device *pdev)
gesture_module_exit();
inspect_module_exit();
hw_ops->irq_enable(core_data, false);
-#ifdef CONFIG_FB
+#if IS_ENABLED(CONFIG_FB)
fb_unregister_client(&core_data->fb_notifier);
#endif
core_module_prob_sate = CORE_MODULE_REMOVED;
@@ -2190,9 +2217,9 @@ static int goodix_ts_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM
+#if IS_ENABLED(CONFIG_PM)
static const struct dev_pm_ops dev_pm_ops = {
-#if !defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND)
+#if !IS_ENABLED(CONFIG_FB) && !IS_ENABLED(CONFIG_HAS_EARLYSUSPEND)
.suspend = goodix_ts_pm_suspend,
.resume = goodix_ts_pm_resume,
#endif
@@ -2208,7 +2235,7 @@ static struct platform_driver goodix_ts_driver = {
.driver = {
.name = GOODIX_CORE_DRIVER_NAME,
.owner = THIS_MODULE,
-#ifdef CONFIG_PM
+#if IS_ENABLED(CONFIG_PM)
.pm = &dev_pm_ops,
#endif
},
diff --git a/goodix_ts_core.h b/goodix_ts_core.h
index a37fb50..9269acd 100644
--- a/goodix_ts_core.h
+++ b/goodix_ts_core.h
@@ -1,3 +1,19 @@
+/*
+ * Goodix Gesture Module
+ *
+ * Copyright (C) 2019 - 2020 Goodix, Inc.
+ *
+ * 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_TS_CORE_H_
#define _GOODIX_TS_CORE_H_
#include <asm/unaligned.h>
@@ -15,25 +31,27 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#ifdef CONFIG_OF
+#if IS_ENABLED(CONFIG_OF)
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#endif
-#ifdef CONFIG_FB
+#if IS_ENABLED(CONFIG_FB)
#include <linux/fb.h>
#include <linux/notifier.h>
#endif
#define GOODIX_CORE_DRIVER_NAME "goodix_ts"
#define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen"
-#define GOODIX_DRIVER_VERSION "v2.0.0"
+#define GOODIX_DRIVER_VERSION "v1.0.0"
#define GOODIX_MAX_TOUCH 10
#define GOODIX_PEN_MAX_PRESSURE 4096
#define GOODIX_MAX_PEN_KEY 2
#define GOODIX_PEN_MAX_TILT 90
#define GOODIX_CFG_MAX_SIZE 4096
+#define GOODIX_FW_MAX_SIEZE (300 * 1024)
#define GOODIX_MAX_STR_LABEL_LEN 32
#define GOODIX_MAX_FRAMEDATA_LEN 1700
+#define GOODIX_GESTURE_DATA_LEN 16
#define GOODIX_NORMAL_RESET_DELAY_MS 100
#define GOODIX_HOLD_CPU_RESET_DELAY_MS 5
@@ -45,6 +63,12 @@
#define TS_DEFAULT_FIRMWARE "goodix_firmware.bin"
#define TS_DEFAULT_CFG_BIN "goodix_cfg_group.bin"
+enum GOODIX_GESTURE_TYP {
+ GESTURE_SINGLE_TAP = (1 << 0),
+ GESTURE_DOUBLE_TAP = (1 << 1),
+ GESTURE_FOD_PRESS = (1 << 2)
+};
+
enum CORD_PROB_STA {
CORE_MODULE_UNPROBED = 0,
CORE_MODULE_PROB_SUCCESS = 1,
@@ -62,6 +86,7 @@ enum GOODIX_ERR_CODE {
GOODIX_EOTHER = (1 << 7)
};
+/* MAIN-ID */
enum IC_TYPE_ID {
IC_TYPE_NONE,
IC_TYPE_NORMANDY,
@@ -69,7 +94,17 @@ enum IC_TYPE_ID {
IC_TYPE_YELLOWSTONE,
IC_TYPE_BERLIN_A,
IC_TYPE_BERLIN_B,
- IC_TYPE_BERLIN_D
+ IC_TYPE_BERLIN_D,
+ IC_TYPE_NOTTINGHAM
+};
+
+/* SUB-ID
+ * sub type of berlinB serial IC.
+ * for convenience we put the MAIN-ID on the hith bits,
+ * hith 8 bits is MAIN-ID, low 8 bits is MIN-ID
+ */
+enum BERLIN_B_SUB_ID {
+ IC_TYPE_SUB_B2 = (IC_TYPE_BERLIN_B << 8) | 0x2,
};
enum GOODIX_IC_CONFIG_TYPE {
@@ -90,8 +125,8 @@ enum CHECKSUM_MODE {
CHECKSUM_MODE_U16_LE,
};
-#define MAX_SCAN_FREQ_NUM 5
-#define MAX_SCAN_RATE_NUM 5
+#define MAX_SCAN_FREQ_NUM 8
+#define MAX_SCAN_RATE_NUM 8
#define MAX_FREQ_NUM_STYLUS 8
#define MAX_STYLUS_SCAN_FREQ_NUM 6
#pragma pack(1)
@@ -265,6 +300,7 @@ struct goodix_ts_board_data {
unsigned int panel_max_p; /*pressure*/
bool pen_enable;
+ bool sleep_enable;
char fw_name[GOODIX_MAX_STR_LABEL_LEN];
char cfg_bin_name[GOODIX_MAX_STR_LABEL_LEN];
};
@@ -366,10 +402,11 @@ struct goodix_pen_data {
* @event_data: event data
*/
struct goodix_ts_event {
- int retry;
enum ts_event_type event_type;
+ u8 fp_flag; /* finger print DOWN flag */
u8 request_code; /* represent the request type */
u8 gesture_type;
+ u8 gesture_data[GOODIX_GESTURE_DATA_LEN];
struct goodix_touch_data touch_data;
struct goodix_pen_data pen_data;
};
@@ -383,6 +420,7 @@ enum goodix_ic_bus_type {
struct goodix_bus_interface {
int bus_type;
int ic_type;
+ int sub_ic_type;
struct device *dev;
int (*read)(struct device *dev, unsigned int addr, unsigned char *data,
unsigned int len);
@@ -412,8 +450,7 @@ struct goodix_ts_hw_ops {
int (*esd_check)(struct goodix_ts_core *cd);
int (*event_handler)(
struct goodix_ts_core *cd, struct goodix_ts_event *ts_event);
- int (*after_event_handler)(
- struct goodix_ts_core *cd); /* clean sync flag */
+ int (*after_event_handler)(struct goodix_ts_core *cd);
int (*get_capacitance_data)(
struct goodix_ts_core *cd, struct ts_rawdata_info *info);
};
@@ -461,6 +498,7 @@ struct goodix_ts_core {
struct goodix_ic_config *ic_configs[GOODIX_MAX_CONFIG_GROUP];
struct regulator *avdd;
struct regulator *iovdd;
+ unsigned char gesture_type;
int power_on;
int irq;
@@ -474,7 +512,7 @@ struct goodix_ts_core {
struct notifier_block ts_notifier;
struct goodix_ts_esd ts_esd;
-#ifdef CONFIG_FB
+#if IS_ENABLED(CONFIG_FB)
struct notifier_block fb_notifier;
#endif
};
@@ -548,8 +586,9 @@ struct goodix_ext_module {
*/
struct goodix_ext_attribute {
struct attribute attr;
- ssize_t (*show)(struct goodix_ext_module *, char *);
- ssize_t (*store)(struct goodix_ext_module *, const char *, size_t);
+ ssize_t (*show)(struct goodix_ext_module *module, char *buf);
+ ssize_t (*store)(
+ struct goodix_ext_module *module, const char *buf, size_t len);
};
/* external attrs helper macro */
@@ -562,7 +601,7 @@ struct goodix_ext_attribute {
/* external attrs helper macro, used to define external attrs */
#define DEFINE_EXTMOD_ATTR(_name, _mode, _show, _store) \
static struct goodix_ext_attribute ext_attr_##_name = \
- __EXTMOD_ATTR(_name, _mode, _show, _store);
+ __EXTMOD_ATTR(_name, _mode, _show, _store)
/* log macro */
extern bool debug_log_flag;
@@ -626,13 +665,13 @@ int checksum_cmp(const u8 *data, int size, int mode);
int is_risk_data(const u8 *data, int size);
u32 goodix_get_file_config_id(u8 *ic_config);
void goodix_rotate_abcd2cbad(int tx, int rx, s16 *data);
-int goodix_gesture_enable(int enable);
int goodix_fw_update_init(struct goodix_ts_core *core_data);
void goodix_fw_update_uninit(void);
int goodix_do_fw_update(struct goodix_ic_config *ic_config, int mode);
-int goodix_get_ic_type(struct device_node *node);
+int goodix_get_ic_type(
+ struct device_node *node, struct goodix_bus_interface *bus_inf);
int gesture_module_init(void);
void gesture_module_exit(void);
int inspect_module_init(void);
@@ -640,4 +679,8 @@ void inspect_module_exit(void);
int goodix_tools_init(void);
void goodix_tools_exit(void);
+int driver_test_proc_init(struct goodix_ts_core *core_data);
+void driver_test_proc_remove(void);
+int goodix_do_inspect(struct goodix_ts_core *cd, struct ts_rawdata_info *info);
+
#endif
diff --git a/goodix_ts_gesture.c b/goodix_ts_gesture.c
index 43899b4..837b9a4 100644
--- a/goodix_ts_gesture.c
+++ b/goodix_ts_gesture.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/input/mt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -27,9 +28,10 @@
#include <linux/string.h>
#include <linux/version.h>
-#define QUERYBIT(longlong, bit) (!!(longlong[bit / 8] & (1 << bit % 8)))
-
-#define GSX_GESTURE_TYPE_LEN 32
+#define GOODIX_GESTURE_DOUBLE_TAP 0xCC
+#define GOODIX_GESTURE_SINGLE_TAP 0x4C
+#define GOODIX_GESTURE_FOD_DOWN 0x46
+#define GOODIX_GESTURE_FOD_UP 0x55
/*
* struct gesture_module - gesture module data
@@ -41,156 +43,160 @@
*/
struct gesture_module {
atomic_t registered;
- rwlock_t rwlock;
- u8 gesture_type[GSX_GESTURE_TYPE_LEN];
- u8 gesture_data;
+ struct goodix_ts_core *ts_core;
struct goodix_ext_module module;
};
static struct gesture_module *gsx_gesture; /*allocated in gesture init module*/
static bool module_initialized;
-int goodix_gesture_enable(int enable)
+static ssize_t gsx_double_type_show(struct goodix_ext_module *module, char *buf)
{
- int ret = 0;
+ struct gesture_module *gsx = module->priv_data;
+ unsigned char type = gsx->ts_core->gesture_type;
- if (!module_initialized)
+ if (!gsx)
+ return -EIO;
+
+ if (atomic_read(&gsx->registered) == 0) {
+ ts_err("gesture module is not registered");
return 0;
+ }
+
+ return sprintf(buf, "%s\n",
+ (type & GESTURE_DOUBLE_TAP) ? "enable" : "disable");
+}
+
+static ssize_t gsx_double_type_store(
+ struct goodix_ext_module *module, const char *buf, size_t count)
+{
+ struct gesture_module *gsx = module->priv_data;
- if (enable) {
- if (atomic_read(&gsx_gesture->registered))
- ts_info("gesture module has been already registered");
- else
- ret = goodix_register_ext_module_no_wait(
- &gsx_gesture->module);
- } else {
- if (!atomic_read(&gsx_gesture->registered))
- ts_info("gesture module has been already unregistered");
- else
- ret = goodix_unregister_ext_module(
- &gsx_gesture->module);
+ if (!gsx)
+ return -EIO;
+
+ if (atomic_read(&gsx->registered) == 0) {
+ ts_err("gesture module is not registered");
+ return 0;
}
- return ret;
+ if (buf[0] == '1') {
+ ts_info("enable double tap");
+ gsx->ts_core->gesture_type |= GESTURE_DOUBLE_TAP;
+ } else if (buf[0] == '0') {
+ ts_info("disable double tap");
+ gsx->ts_core->gesture_type &= ~GESTURE_DOUBLE_TAP;
+ } else
+ ts_err("invalid cmd[%d]", buf[0]);
+
+ return count;
}
-/**
- * gsx_gesture_type_show - show valid gesture type
- *
- * @module: pointer to goodix_ext_module struct
- * @buf: pointer to output buffer
- * Returns >=0 - succeed,< 0 - failed
- */
-static ssize_t gsx_gesture_type_show(
- struct goodix_ext_module *module, char *buf)
+static ssize_t gsx_single_type_show(struct goodix_ext_module *module, char *buf)
{
- int count = 0, i, ret = 0;
- unsigned char *type;
+ struct gesture_module *gsx = module->priv_data;
+ unsigned char type = gsx->ts_core->gesture_type;
- type = kzalloc(PAGE_SIZE, GFP_KERNEL);
- if (!type)
- return -ENOMEM;
- read_lock(&gsx_gesture->rwlock);
- for (i = 0; i < 256; i++) {
- if (QUERYBIT(gsx_gesture->gesture_type, i)) {
- count += scnprintf(type + count, PAGE_SIZE, "%02x,", i);
- }
+ if (!gsx)
+ return -EIO;
+
+ if (atomic_read(&gsx->registered) == 0) {
+ ts_err("gesture module is not registered");
+ return 0;
}
- if (count > 0)
- ret = scnprintf(buf, PAGE_SIZE, "%s\n", type);
- read_unlock(&gsx_gesture->rwlock);
- kfree(type);
- return ret;
+ return sprintf(buf, "%s\n",
+ (type & GESTURE_SINGLE_TAP) ? "enable" : "disable");
}
-/**
- * gsx_gesture_type_store - set vailed gesture
- *
- * @module: pointer to goodix_ext_module struct
- * @buf: pointer to valid gesture type
- * @count: length of buf
- * Returns >0 - valid gestures, < 0 - failed
- */
-static ssize_t gsx_gesture_type_store(
+static ssize_t gsx_single_type_store(
struct goodix_ext_module *module, const char *buf, size_t count)
{
- int i;
+ struct gesture_module *gsx = module->priv_data;
- if (count <= 0 || count > 256 || buf == NULL) {
- ts_err("Parameter error");
- return -EINVAL;
+ if (!gsx)
+ return -EIO;
+
+ if (atomic_read(&gsx->registered) == 0) {
+ ts_err("gesture module is not registered");
+ return 0;
}
- write_lock(&gsx_gesture->rwlock);
- memset(gsx_gesture->gesture_type, 0, GSX_GESTURE_TYPE_LEN);
- for (i = 0; i < count; i++)
- gsx_gesture->gesture_type[buf[i] / 8] |= (0x1 << buf[i] % 8);
- write_unlock(&gsx_gesture->rwlock);
+ if (buf[0] == '1') {
+ ts_info("enable single tap");
+ gsx->ts_core->gesture_type |= GESTURE_SINGLE_TAP;
+ } else if (buf[0] == '0') {
+ ts_info("disable single tap");
+ gsx->ts_core->gesture_type &= ~GESTURE_SINGLE_TAP;
+ } else
+ ts_err("invalid cmd[%d]", buf[0]);
return count;
}
-static ssize_t gsx_gesture_enable_show(
- struct goodix_ext_module *module, char *buf)
+static ssize_t gsx_fod_type_show(struct goodix_ext_module *module, char *buf)
{
- return scnprintf(
- buf, PAGE_SIZE, "%d\n", atomic_read(&gsx_gesture->registered));
+ struct gesture_module *gsx = module->priv_data;
+ unsigned char type = gsx->ts_core->gesture_type;
+
+ if (!gsx)
+ return -EIO;
+
+ if (atomic_read(&gsx->registered) == 0) {
+ ts_err("gesture module is not registered");
+ return 0;
+ }
+
+ return sprintf(
+ buf, "%s\n", (type & GESTURE_FOD_PRESS) ? "enable" : "disable");
}
-static ssize_t gsx_gesture_enable_store(
+static ssize_t gsx_fod_type_store(
struct goodix_ext_module *module, const char *buf, size_t count)
{
- bool val;
- int ret;
+ struct gesture_module *gsx = module->priv_data;
- ret = strtobool(buf, &val);
- if (ret < 0)
- return ret;
+ if (!gsx)
+ return -EIO;
- if (val) {
- ret = goodix_gesture_enable(1);
- return ret ? ret : count;
- } else {
- ret = goodix_gesture_enable(0);
- return ret ? ret : count;
+ if (atomic_read(&gsx->registered) == 0) {
+ ts_err("gesture module is not registered");
+ return 0;
}
-}
-
-static ssize_t gsx_gesture_data_show(
- struct goodix_ext_module *module, char *buf)
-{
- ssize_t count;
- read_lock(&gsx_gesture->rwlock);
- count = scnprintf(buf, PAGE_SIZE, "gesture type code:0x%x\n",
- gsx_gesture->gesture_data);
- read_unlock(&gsx_gesture->rwlock);
+ if (buf[0] == '1') {
+ ts_info("enable fod");
+ gsx->ts_core->gesture_type |= GESTURE_FOD_PRESS;
+ } else if (buf[0] == '0') {
+ ts_info("disable fod");
+ gsx->ts_core->gesture_type &= ~GESTURE_FOD_PRESS;
+ } else
+ ts_err("invalid cmd[%d]", buf[0]);
return count;
}
const struct goodix_ext_attribute gesture_attrs[] = {
__EXTMOD_ATTR(
- type, 0666, gsx_gesture_type_show, gsx_gesture_type_store),
- __EXTMOD_ATTR(enable, 0666, gsx_gesture_enable_show,
- gsx_gesture_enable_store),
- __EXTMOD_ATTR(data, 0444, gsx_gesture_data_show, NULL)
+ double_en, 0664, gsx_double_type_show, gsx_double_type_store),
+ __EXTMOD_ATTR(
+ single_en, 0664, gsx_single_type_show, gsx_single_type_store),
+ __EXTMOD_ATTR(fod_en, 0664, gsx_fod_type_show, gsx_fod_type_store),
};
static int gsx_gesture_init(
struct goodix_ts_core *cd, struct goodix_ext_module *module)
{
+ struct gesture_module *gsx = module->priv_data;
+
if (!cd || !cd->hw_ops->gesture) {
ts_err("gesture unsupported");
return -EINVAL;
}
- ts_info("gesture switch: ON");
- ts_debug("enable all gesture type");
- /* set all bit to 1 to enable all gesture wakeup */
- memset(gsx_gesture->gesture_type, 0xff, GSX_GESTURE_TYPE_LEN);
- atomic_set(&gsx_gesture->registered, 1);
+ gsx->ts_core = cd;
+ gsx->ts_core->gesture_type = 0;
+ atomic_set(&gsx->registered, 1);
return 0;
}
@@ -198,15 +204,14 @@ static int gsx_gesture_init(
static int gsx_gesture_exit(
struct goodix_ts_core *cd, struct goodix_ext_module *module)
{
+ struct gesture_module *gsx = module->priv_data;
+
if (!cd || !cd->hw_ops->gesture) {
ts_err("gesture unsupported");
return -EINVAL;
}
- ts_info("gesture switch: OFF");
- ts_debug("disable all gesture type");
- memset(gsx_gesture->gesture_type, 0x00, GSX_GESTURE_TYPE_LEN);
- atomic_set(&gsx_gesture->registered, 0);
+ atomic_set(&gsx->registered, 0);
return 0;
}
@@ -225,9 +230,10 @@ static int gsx_gesture_ist(
{
struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
struct goodix_ts_event gs_event = { 0 };
+ int fodx, fody, overlay_area;
int ret;
- if (atomic_read(&cd->suspended) == 0)
+ if (atomic_read(&cd->suspended) == 0 || cd->gesture_type == 0)
return EVT_CONTINUE;
ret = hw_ops->event_handler(cd, &gs_event);
@@ -241,25 +247,78 @@ static int gsx_gesture_ist(
goto re_send_ges_cmd;
}
- if (QUERYBIT(gsx_gesture->gesture_type, gs_event.gesture_type)) {
- gsx_gesture->gesture_data = gs_event.gesture_type;
- /* do resume routine */
- ts_info("got valid gesture type 0x%x", gs_event.gesture_type);
- input_report_key(cd->input_dev, KEY_POWER, 1);
- input_sync(cd->input_dev);
- input_report_key(cd->input_dev, KEY_POWER, 0);
- input_sync(cd->input_dev);
- goto gesture_ist_exit;
- } else {
- ts_info("unsupported gesture:%x", gs_event.gesture_type);
+ switch (gs_event.gesture_type) {
+ case GOODIX_GESTURE_SINGLE_TAP:
+ if (cd->gesture_type & GESTURE_SINGLE_TAP) {
+ ts_info("get SINGLE-TAP gesture");
+ input_report_key(cd->input_dev, KEY_WAKEUP, 1);
+ // input_report_key(cd->input_dev, KEY_GOTO, 1);
+ input_sync(cd->input_dev);
+ input_report_key(cd->input_dev, KEY_WAKEUP, 0);
+ // input_report_key(cd->input_dev, KEY_GOTO, 0);
+ input_sync(cd->input_dev);
+ } else {
+ ts_debug("not enable SINGLE-TAP");
+ }
+ break;
+ case GOODIX_GESTURE_DOUBLE_TAP:
+ if (cd->gesture_type & GESTURE_DOUBLE_TAP) {
+ ts_info("get DOUBLE-TAP gesture");
+ input_report_key(cd->input_dev, KEY_WAKEUP, 1);
+ input_sync(cd->input_dev);
+ input_report_key(cd->input_dev, KEY_WAKEUP, 0);
+ input_sync(cd->input_dev);
+ } else {
+ ts_debug("not enable DOUBLE-TAP");
+ }
+ break;
+ case GOODIX_GESTURE_FOD_DOWN:
+ if (cd->gesture_type & GESTURE_FOD_PRESS) {
+ ts_info("get FOD-DOWN gesture");
+ fodx = le16_to_cpup((__le16 *)gs_event.gesture_data);
+ fody = le16_to_cpup(
+ (__le16 *)(gs_event.gesture_data + 2));
+ overlay_area = gs_event.gesture_data[4];
+ ts_debug("fodx:%d fody:%d overlay_area:%d", fodx, fody,
+ overlay_area);
+ input_report_key(cd->input_dev, BTN_TOUCH, 1);
+ input_mt_slot(cd->input_dev, 0);
+ input_mt_report_slot_state(
+ cd->input_dev, MT_TOOL_FINGER, 1);
+ input_report_abs(
+ cd->input_dev, ABS_MT_POSITION_X, fodx);
+ input_report_abs(
+ cd->input_dev, ABS_MT_POSITION_Y, fody);
+ input_report_abs(cd->input_dev, ABS_MT_WIDTH_MAJOR,
+ overlay_area);
+ input_sync(cd->input_dev);
+ } else {
+ ts_debug("not enable FOD-DOWN");
+ }
+ break;
+ case GOODIX_GESTURE_FOD_UP:
+ if (cd->gesture_type & GESTURE_FOD_PRESS) {
+ ts_info("get FOD-UP gesture");
+ // fodx = le16_to_cpup((__le16 *)gs_event.gesture_data);
+ // fody = le16_to_cpup((__le16 *)(gs_event.gesture_data
+ // + 2)); overlay_area = gs_event.gesture_data[4];
+ input_report_key(cd->input_dev, BTN_TOUCH, 0);
+ input_mt_slot(cd->input_dev, 0);
+ input_mt_report_slot_state(
+ cd->input_dev, MT_TOOL_FINGER, 0);
+ input_sync(cd->input_dev);
+ } else {
+ ts_debug("not enable FOD-UP");
+ }
+ break;
+ default:
+ ts_err("not support gesture type[%02X]", gs_event.gesture_type);
+ break;
}
re_send_ges_cmd:
if (hw_ops->gesture(cd, 0))
ts_info("warning: failed re_send gesture cmd");
-gesture_ist_exit:
- if (!cd->tools_ctrl_sync)
- hw_ops->after_event_handler(cd);
return EVT_CANCEL_IRQEVT;
}
@@ -277,11 +336,14 @@ static int gsx_gesture_before_suspend(
int ret;
const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
+ if (cd->gesture_type == 0)
+ return EVT_CONTINUE;
+
ret = hw_ops->gesture(cd, 0);
if (ret)
ts_err("failed enter gesture mode");
else
- ts_info("enter gesture mode");
+ ts_info("enter gesture mode, type[0x%02X]", cd->gesture_type);
hw_ops->irq_enable(cd, true);
enable_irq_wake(cd->irq);
@@ -294,7 +356,9 @@ static int gsx_gesture_before_resume(
{
const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
- hw_ops->irq_enable(cd, false);
+ if (cd->gesture_type == 0)
+ return EVT_CONTINUE;
+
disable_irq_wake(cd->irq);
hw_ops->reset(cd, GOODIX_NORMAL_RESET_DELAY_MS);
@@ -326,7 +390,6 @@ int gesture_module_init(void)
gsx_gesture->module.priv_data = gsx_gesture;
atomic_set(&gsx_gesture->registered, 0);
- rwlock_init(&gsx_gesture->rwlock);
/* gesture sysfs init */
ret = kobject_init_and_add(
@@ -350,6 +413,7 @@ int gesture_module_init(void)
}
module_initialized = true;
+ goodix_register_ext_module_no_wait(&gsx_gesture->module);
ts_info("gesture module init success");
return 0;
@@ -368,7 +432,7 @@ void gesture_module_exit(void)
if (!module_initialized)
return;
- goodix_gesture_enable(0);
+ goodix_unregister_ext_module(&gsx_gesture->module);
/* deinit sysfs */
for (i = 0; i < ARRAY_SIZE(gesture_attrs); i++)
diff --git a/goodix_ts_inspect.c b/goodix_ts_inspect.c
index 6b6e942..125db6b 100644
--- a/goodix_ts_inspect.c
+++ b/goodix_ts_inspect.c
@@ -25,7 +25,7 @@
/* test config */
#define TOTAL_FRAME_NUM 1 /* rawdata test frames */
#define NOISEDATA_TEST_TIMES 1 /* noise test frames */
-#define SAVE_IN_CSV
+// #define SAVE_IN_CSV
#define GOODIX_RESULT_SAVE_PATH "/vendor/etc/Test_Data.csv"
#define GOODIX_TEST_FILE_NAME "goodix"
@@ -108,6 +108,17 @@
#define DRV_SEN_SELFCODE_REG_BRD 0x14556
#define DIFF_CODE_DATA_REG_BRD 0x14D00
+/* nottingham */
+#define MAX_DRV_NUM_NOT 17
+#define MAX_SEN_NUM_NOT 35
+#define SHORT_TEST_TIME_REG_NOT 0x1479E
+#define SHORT_TEST_STATUS_REG_NOT 0x13400
+#define SHORT_TEST_RESULT_REG_NOT 0x13408
+#define DRV_DRV_SELFCODE_REG_NOT 0x13446
+#define SEN_SEN_SELFCODE_REG_NOT 0x136EE
+#define DRV_SEN_SELFCODE_REG_NOT 0x14152
+#define DIFF_CODE_DATA_REG_NOT 0x14734
+
#define ABS(val) ((val < 0) ? -(val) : val)
#define MAX(a, b) ((a > b) ? a : b)
@@ -200,6 +211,14 @@ static u8 brl_d_sen_map[] = {
39,
};
+/* nottingham drv-sen map */
+static u8 not_drv_map[] = { 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51 };
+
+static u8 not_sen_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 34 };
+
typedef struct __attribute__((packed)) {
u8 result;
u8 drv_drv_num;
@@ -278,6 +297,23 @@ struct params_info_t params_brd = {
DFT_DIFFCODE_SHORT_THRESHOLD_BRD,
};
+struct params_info_t params_not = {
+ MAX_DRV_NUM_NOT,
+ MAX_SEN_NUM_NOT,
+ not_drv_map,
+ not_sen_map,
+ SHORT_TEST_TIME_REG_NOT,
+ SHORT_TEST_STATUS_REG_NOT,
+ SHORT_TEST_RESULT_REG_NOT,
+ DRV_DRV_SELFCODE_REG_NOT,
+ SEN_SEN_SELFCODE_REG_NOT,
+ DRV_SEN_SELFCODE_REG_NOT,
+ DIFF_CODE_DATA_REG_NOT,
+ 0,
+ 0,
+ 0,
+};
+
struct ts_test_params {
bool test_items[MAX_TEST_ITEMS];
@@ -354,18 +390,22 @@ static int cal_cha_to_cha_res(struct goodix_ts_test *ts_test, int v1, int v2)
return (v1 - v2) * 63 / v2;
else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_B)
return (v1 - v2) * 74 / v2 + 20;
- else
+ else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D)
return (v1 / v2 - 1) * 70 + 59;
+ else
+ return (v1 / v2 - 1) * 55 + 45;
}
static int cal_cha_to_avdd_res(struct goodix_ts_test *ts_test, int v1, int v2)
{
if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_A)
- return 125 * 1024 * (100 * v2 - 125) * 40 / (10000 * v1) - 40;
+ return 64 * (2 * v2 - 25) * 40 / v1 - 40;
else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_B)
- return 125 * 1024 * (100 * v2 - 125) * 99 / (10000 * v1) - 60;
+ return 64 * (2 * v2 - 25) * 99 / v1 - 60;
+ else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D)
+ return 64 * (2 * v2 - 25) * 93 / v1 - 20;
else
- return 125 * 1024 * (100 * v2 - 125) * 93 / (10000 * v1) - 20;
+ return 64 * (2 * v2 - 25) * 76 / v1 - 15;
}
static int cal_cha_to_gnd_res(struct goodix_ts_test *ts_test, int v)
@@ -374,8 +414,10 @@ static int cal_cha_to_gnd_res(struct goodix_ts_test *ts_test, int v)
return 64148 / v - 40;
else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_B)
return 150500 / v - 60;
- else
+ else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D)
return 145000 / v - 15;
+ else
+ return 120000 / v - 16;
}
static int ts_test_reset(struct goodix_ts_test *ts_test, u32 delay_ms)
@@ -592,8 +634,10 @@ static void goodix_init_params(struct goodix_ts_test *ts_test)
test_params->params_info = &params_bra;
else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_B)
test_params->params_info = &params_brb;
- else
+ else if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D)
test_params->params_info = &params_brd;
+ else if (ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM)
+ test_params->params_info = &params_not;
}
static int goodix_init_testlimits(struct goodix_ts_test *ts_test)
@@ -805,7 +849,8 @@ static int goodix_short_test_prepare(struct goodix_ts_test *ts_test)
struct goodix_ts_cmd tmp_cmd;
struct goodix_fw_version fw_ver;
int ret;
- int retry = 3;
+ int retry;
+ int resend = 3;
u8 status;
ts_info("short test prepare IN");
@@ -813,12 +858,14 @@ static int goodix_short_test_prepare(struct goodix_ts_test *ts_test)
tmp_cmd.len = 4;
tmp_cmd.cmd = INSPECT_FW_SWITCH_CMD;
+resend_cmd:
ret = ts_test_send_cmd(ts_test, &tmp_cmd);
if (ret < 0) {
ts_err("send test mode failed");
return ret;
}
+ retry = 3;
while (retry--) {
msleep(40);
if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_A) {
@@ -843,6 +890,11 @@ static int goodix_short_test_prepare(struct goodix_ts_test *ts_test)
}
}
+ if (resend--) {
+ ts_test_reset(ts_test, 100);
+ goto resend_cmd;
+ }
+
return -EINVAL;
}
@@ -1204,22 +1256,24 @@ static int gdix_check_resistance_to_gnd(
u16 r_th = 0, avdd_value = 0;
u16 chn_id_tmp = 0;
u8 pin_num = 0;
+ unsigned short short_type;
struct goodix_ts_test *ts_test =
container_of(test_params, struct goodix_ts_test, test_params);
int max_drv_num = test_params->params_info->max_drv_num;
int max_sen_num = test_params->params_info->max_sen_num;
avdd_value = test_params->avdd_value;
- if (adc_signal == 0 || adc_signal == 0x8000)
- adc_signal |= 1;
+ short_type = adc_signal & 0x8000;
+ adc_signal &= ~0x8000;
+ if (adc_signal == 0)
+ adc_signal = 1;
- if ((adc_signal & 0x8000) == 0) {
+ if (short_type == 0) {
/* short to GND */
r = cal_cha_to_gnd_res(ts_test, adc_signal);
} else {
/* short to VDD */
- r = cal_cha_to_avdd_res(
- ts_test, adc_signal & ~0x8000, avdd_value);
+ r = cal_cha_to_avdd_res(ts_test, adc_signal, avdd_value);
}
if (pos < max_drv_num)
@@ -1236,11 +1290,11 @@ static int gdix_check_resistance_to_gnd(
if (r < r_th) {
pin_num = map_die2pin(test_params, chn_id_tmp);
goodix_save_short_res(test_params, pin_num,
- (adc_signal & 0x8000) ? CHN_VDD : CHN_GND, r);
+ short_type ? CHN_VDD : CHN_GND, r);
ts_err("%s%d shortcircut to %s,R=%ldK,R_Threshold=%dK",
(pin_num & DRV_CHANNEL_FLAG) ? "DRV" : "SEN",
(pin_num & ~DRV_CHANNEL_FLAG),
- (adc_signal & 0x8000) ? "VDD" : "GND", r, r_th);
+ short_type ? "VDD" : "GND", r, r_th);
return -EINVAL;
}
@@ -1490,7 +1544,8 @@ static int goodix_cap_test_prepare(struct goodix_ts_test *ts_test)
ts_test->test_result[GTP_SELFNOISE_TEST] = SYS_SOFTWARE_REASON;
/* switch rawdata mode */
- if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D) {
+ if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D ||
+ ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM) {
temp_cmd.cmd = 0x90;
temp_cmd.data[0] = 0x81;
temp_cmd.len = 5;
@@ -1529,7 +1584,8 @@ static int goodix_cache_rawdata(struct goodix_ts_test *ts_test)
u32 data_addr = ts_test->test_params.rawdata_addr;
u32 flag_addr = ts_test->ts->ic_info.misc.touch_data_addr;
- if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D)
+ if (ts_test->ts->bus->ic_type == IC_TYPE_BERLIN_D ||
+ ts_test->ts->bus->ic_type == IC_TYPE_NOTTINGHAM)
flag_addr = ts_test->ts->ic_info.misc.frame_data_addr;
for (i = 0; i < TOTAL_FRAME_NUM; i++) {
@@ -1552,7 +1608,8 @@ static int goodix_cache_rawdata(struct goodix_ts_test *ts_test)
return -EAGAIN;
}
- if (cd->bus->ic_type == IC_TYPE_BERLIN_D) {
+ if (cd->bus->ic_type == IC_TYPE_BERLIN_D ||
+ cd->bus->ic_type == IC_TYPE_NOTTINGHAM) {
ret = ts_test_read(ts_test, flag_addr, frame_buf,
sizeof(frame_buf));
if (ret < 0)
@@ -1651,7 +1708,8 @@ static int goodix_cache_self_rawdata(struct goodix_ts_test *ts_test)
unsigned char frame_buf[GOODIX_MAX_FRAMEDATA_LEN];
unsigned char *cur_ptr;
- if (cd->bus->ic_type == IC_TYPE_BERLIN_D) {
+ if (cd->bus->ic_type == IC_TYPE_BERLIN_D ||
+ cd->bus->ic_type == IC_TYPE_NOTTINGHAM) {
ret = ts_test_read(
ts_test, flag_addr, frame_buf, sizeof(frame_buf));
if (ret < 0)
@@ -1705,7 +1763,8 @@ static int goodix_cache_noisedata(struct goodix_ts_test *ts_test)
u32 data_addr = ts_test->test_params.noisedata_addr;
u32 flag_addr = ts_test->ts->ic_info.misc.touch_data_addr;
- if (cd->bus->ic_type == IC_TYPE_BERLIN_D) {
+ if (cd->bus->ic_type == IC_TYPE_BERLIN_D ||
+ cd->bus->ic_type == IC_TYPE_NOTTINGHAM) {
flag_addr = ts_test->ts->ic_info.misc.frame_data_addr;
temp_cmd.cmd = 0x90;
temp_cmd.data[0] = 0x82;
@@ -1737,7 +1796,8 @@ static int goodix_cache_noisedata(struct goodix_ts_test *ts_test)
return -EAGAIN;
}
- if (cd->bus->ic_type == IC_TYPE_BERLIN_D) {
+ if (cd->bus->ic_type == IC_TYPE_BERLIN_D ||
+ cd->bus->ic_type == IC_TYPE_NOTTINGHAM) {
ret = ts_test_read(ts_test, flag_addr, frame_buf,
sizeof(frame_buf));
if (ret < 0)
@@ -1793,7 +1853,8 @@ static int goodix_cache_self_noisedata(struct goodix_ts_test *ts_test)
unsigned char frame_buf[GOODIX_MAX_FRAMEDATA_LEN];
unsigned char *cur_ptr;
- if (cd->bus->ic_type == IC_TYPE_BERLIN_D) {
+ if (cd->bus->ic_type == IC_TYPE_BERLIN_D ||
+ cd->bus->ic_type == IC_TYPE_NOTTINGHAM) {
ret = ts_test_read(
ts_test, flag_addr, frame_buf, sizeof(frame_buf));
if (ret < 0)
@@ -2323,740 +2384,750 @@ static int goodix_save_limits(struct goodix_ts_test *ts_test, struct file *fp)
data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
if (!data) {
- ts_err("alloc memory failed for ");
return -ENOMEM;
- }
- bytes += sprintf(&data[bytes], "<TestItems>\n");
+ bytes += sprintf(&data[bytes], "<TestItems>\n");
- /* save short result */
- if (ts_test->test_result[GTP_SHORT_TEST]) {
- bytes += sprintf(&data[bytes], "<Item name=\"Short Test\">\n");
- bytes += sprintf(&data[bytes], "<ShortNum>%d</ShortNum>\n",
- ts_test->short_res.short_num);
- for (i = 0; i < ts_test->short_res.short_num; i++) {
- chn1 = ts_test->short_res.short_msg[4 * i];
- chn2 = ts_test->short_res.short_msg[4 * i + 1];
- r = (ts_test->short_res.short_msg[4 * i + 2] << 8) +
- ts_test->short_res.short_msg[4 * i + 3];
- if (chn1 == CHN_VDD)
- bytes += sprintf(&data[bytes],
- "<ShortMess Chn1=\"VDD\" ");
- else if (chn1 == CHN_GND)
- bytes += sprintf(&data[bytes],
- "<ShortMess Chn1=\"GND\" ");
- else if (chn1 & DRV_CHANNEL_FLAG)
- bytes += sprintf(&data[bytes],
- "<ShortMess Chn1=\"Tx%d\" ",
- chn1 & 0x7f);
- else
- bytes += sprintf(&data[bytes],
- "<ShortMess Chn1=\"Rx%d\" ",
- chn1 & 0x7f);
- if (chn2 == CHN_VDD)
- bytes += sprintf(&data[bytes],
- "Chn2=\"VDD\" ShortResistor= \"%dKom\"/>\n",
- r);
- else if (chn2 == CHN_GND)
- bytes += sprintf(&data[bytes],
- "Chn2=\"GND\" ShortResistor= \"%dKom\"/>\n",
- r);
- else if (chn2 & DRV_CHANNEL_FLAG)
- bytes += sprintf(&data[bytes],
- "Chn2=\"Tx%d\" ShortResistor= \"%dKom\"/>\n",
- chn2 & 0x7f, r);
- else
- bytes += sprintf(&data[bytes],
- "Chn2=\"Rx%d\" ShortResistor= \"%dKom\"/>\n",
- chn2 & 0x7f, r);
- }
- bytes += sprintf(&data[bytes], "</Item>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0) {
- ts_err("short res write fail.");
- goto save_end;
+ /* save short result */
+ if (ts_test->test_result[GTP_SHORT_TEST]) {
+ bytes += sprintf(
+ &data[bytes], "<Item name=\"Short Test\">\n");
+ bytes += sprintf(&data[bytes],
+ "<ShortNum>%d</ShortNum>\n",
+ ts_test->short_res.short_num);
+ for (i = 0; i < ts_test->short_res.short_num; i++) {
+ chn1 = ts_test->short_res.short_msg[4 * i];
+ chn2 = ts_test->short_res.short_msg[4 * i + 1];
+ r = (ts_test->short_res.short_msg[4 * i + 2]
+ << 8) +
+ ts_test->short_res.short_msg[4 * i + 3];
+ if (chn1 == CHN_VDD)
+ bytes += sprintf(&data[bytes],
+ "<ShortMess Chn1=\"VDD\" ");
+ else if (chn1 == CHN_GND)
+ bytes += sprintf(&data[bytes],
+ "<ShortMess Chn1=\"GND\" ");
+ else if (chn1 & DRV_CHANNEL_FLAG)
+ bytes += sprintf(&data[bytes],
+ "<ShortMess Chn1=\"Tx%d\" ",
+ chn1 & 0x7f);
+ else
+ bytes += sprintf(&data[bytes],
+ "<ShortMess Chn1=\"Rx%d\" ",
+ chn1 & 0x7f);
+ if (chn2 == CHN_VDD)
+ bytes += sprintf(&data[bytes],
+ "Chn2=\"VDD\" ShortResistor= \"%dKom\"/>\n",
+ r);
+ else if (chn2 == CHN_GND)
+ bytes += sprintf(&data[bytes],
+ "Chn2=\"GND\" ShortResistor= \"%dKom\"/>\n",
+ r);
+ else if (chn2 & DRV_CHANNEL_FLAG)
+ bytes += sprintf(&data[bytes],
+ "Chn2=\"Tx%d\" ShortResistor= \"%dKom\"/>\n",
+ chn2 & 0x7f, r);
+ else
+ bytes += sprintf(&data[bytes],
+ "Chn2=\"Rx%d\" ShortResistor= \"%dKom\"/>\n",
+ chn2 & 0x7f, r);
+ }
+ bytes += sprintf(&data[bytes], "</Item>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0) {
+ ts_err("short res write fail.");
+ goto save_end;
+ }
+ bytes = 0;
}
- bytes = 0;
- }
-
- /* rawdata max limit */
- bytes += sprintf(&data[bytes], "<Item name=\"Rawdata Test Sets\">\n");
- bytes += sprintf(&data[bytes], "<TotalFrameCnt>%d</TotalFrameCnt>\n",
- TOTAL_FRAME_NUM);
- bytes += sprintf(&data[bytes], "<MaxRawLimit>\n");
- for (i = 0; i < tx * rx; i++) {
- bytes += sprintf(&data[bytes], "%d,",
- ts_test->test_params.max_limits[i]);
- if ((i + 1) % tx == 0)
- bytes += sprintf(&data[bytes], "\n");
- }
- bytes += sprintf(&data[bytes], "</MaxRawLimit>\n");
- /* BeyondRawdataUpperLimit */
- bytes += sprintf(&data[bytes], "<BeyondRawdataUpperLimitCnt>\n");
- for (i = 0; i < tx * rx; i++) {
- bytes += sprintf(&data[bytes], "%d,",
- ts_test->open_res.beyond_max_limit_cnt[i]);
- if ((i + 1) % tx == 0)
- bytes += sprintf(&data[bytes], "\n");
- }
- bytes += sprintf(&data[bytes], "</BeyondRawdataUpperLimitCnt>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0) {
- ts_err("rawdata limit write failed");
- goto save_end;
- }
- bytes = 0;
- /* rawdata min limit */
- bytes += sprintf(&data[bytes], "<MinRawLimit>\n");
- for (i = 0; i < tx * rx; i++) {
- bytes += sprintf(&data[bytes], "%d,",
- ts_test->test_params.min_limits[i]);
- if ((i + 1) % tx == 0)
- bytes += sprintf(&data[bytes], "\n");
- }
- bytes += sprintf(&data[bytes], "</MinRawLimit>\n");
- /* BeyondRawdataLower limit */
- bytes += sprintf(&data[bytes], "<BeyondRawdataLowerLimitCnt>\n");
- for (i = 0; i < tx * rx; i++) {
- bytes += sprintf(&data[bytes], "%d,",
- ts_test->open_res.beyond_min_limit_cnt[i]);
- if ((i + 1) % tx == 0)
- bytes += sprintf(&data[bytes], "\n");
- }
- bytes += sprintf(&data[bytes], "</BeyondRawdataLowerLimitCnt>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0) {
- ts_err("rawdata limit write failed");
- goto save_end;
- }
- bytes = 0;
-
- /* Max Accord limit */
- bytes += sprintf(&data[bytes], "<MaxAccordLimit>\n");
- for (i = 0; i < tx * rx; i++) {
- bytes += sprintf(&data[bytes], "%d,",
- ts_test->test_params.deviation_limits[i]);
- if ((i + 1) % tx == 0)
- bytes += sprintf(&data[bytes], "\n");
- }
- bytes += sprintf(&data[bytes], "</MaxAccordLimit>\n");
- /* BeyondAccordLimitCnt */
- bytes += sprintf(&data[bytes], "<BeyondAccordLimitCnt>\n");
- for (i = 0; i < tx * rx; i++) {
- bytes += sprintf(&data[bytes], "%d,",
- ts_test->open_res.beyond_accord_limit_cnt[i]);
- if ((i + 1) % tx == 0)
- bytes += sprintf(&data[bytes], "\n");
- }
- bytes += sprintf(&data[bytes], "</BeyondAccordLimitCnt>\n");
- bytes += sprintf(&data[bytes], "</Item>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0) {
- ts_err("rawdata limit write failed");
- goto save_end;
- }
- bytes = 0;
-
- /* save noise limit */
- if (ts_test->test_result[GTP_NOISE_TEST]) {
+ /* rawdata max limit */
bytes += sprintf(
- &data[bytes], "<Item name=\"Diffdata Test Sets\">\n");
- bytes += sprintf(&data[bytes],
- "<TotalFrameCnt>%d</TotalFrameCnt>\n",
- NOISEDATA_TEST_TIMES);
- bytes += sprintf(&data[bytes],
- "<MaxJitterLimit>%d</MaxJitterLimit>\n",
- ts_test->test_params.noise_threshold);
- bytes += sprintf(&data[bytes], "</Item>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0) {
- ts_err("noise limit write failed");
- goto save_end;
- }
- bytes = 0;
- }
-
- /* save self rawdata limit */
- if (ts_test->test_result[GTP_SELFCAP_TEST]) {
+ &data[bytes], "<Item name=\"Rawdata Test Sets\">\n");
bytes += sprintf(&data[bytes],
- "<Item name=\"Self Rawdata Test Sets\">\n");
- bytes += sprintf(
- &data[bytes], "<TotalFrameCnt>1</TotalFrameCnt>\n");
+ "<TotalFrameCnt>%d</TotalFrameCnt>\n", TOTAL_FRAME_NUM);
bytes += sprintf(&data[bytes], "<MaxRawLimit>\n");
- for (i = 0; i < tx + rx; i++) {
+ for (i = 0; i < tx * rx; i++) {
bytes += sprintf(&data[bytes], "%d,",
- ts_test->test_params.self_max_limits[i]);
+ ts_test->test_params.max_limits[i]);
if ((i + 1) % tx == 0)
bytes += sprintf(&data[bytes], "\n");
}
- if ((tx + rx) % tx != 0)
- bytes += sprintf(&data[bytes], "\n");
bytes += sprintf(&data[bytes], "</MaxRawLimit>\n");
- bytes += sprintf(&data[bytes], "<MinRawLimit>\n");
- for (i = 0; i < tx + rx; i++) {
+ /* BeyondRawdataUpperLimit */
+ bytes +=
+ sprintf(&data[bytes], "<BeyondRawdataUpperLimitCnt>\n");
+ for (i = 0; i < tx * rx; i++) {
bytes += sprintf(&data[bytes], "%d,",
- ts_test->test_params.self_min_limits[i]);
+ ts_test->open_res.beyond_max_limit_cnt[i]);
if ((i + 1) % tx == 0)
bytes += sprintf(&data[bytes], "\n");
}
- if ((tx + rx) % tx != 0)
- bytes += sprintf(&data[bytes], "\n");
- bytes += sprintf(&data[bytes], "</MinRawLimit>\n");
- bytes += sprintf(&data[bytes], "</Item>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0) {
- ts_err("self rawdata limit write failed");
- goto save_end;
- }
- bytes = 0;
- }
-
- /* save selfnoise limit */
- if (ts_test->test_result[GTP_SELFNOISE_TEST]) {
- bytes += sprintf(&data[bytes],
- "<Item name=\"Self Diffdata Test Sets\">\n");
bytes += sprintf(
- &data[bytes], "<TotalFrameCnt>1</TotalFrameCnt>\n");
- bytes += sprintf(&data[bytes],
- "<MaxJitterLimit>%d</MaxJitterLimit>\n",
- ts_test->test_params.self_noise_threshold);
- bytes += sprintf(&data[bytes], "</Item>\n");
+ &data[bytes], "</BeyondRawdataUpperLimitCnt>\n");
ret = fs_write(data, bytes, fp);
if (ret < 0) {
- ts_err("raw limit write failed");
+ ts_err("rawdata limit write failed");
goto save_end;
}
bytes = 0;
- }
- bytes += sprintf(&data[bytes], "</TestItems>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0)
- ts_err("limit write fail.");
-
-save_end:
- kfree(data);
- return ret;
-}
-
-static int goodix_save_rawdata(struct goodix_ts_test *ts_test, struct file *fp)
-{
- int i;
- int j;
- int ret;
- int bytes = 0;
- s16 stat_result[3];
- char *data = NULL;
- int tx = ts_test->test_params.drv_num;
- int rx = ts_test->test_params.sen_num;
- int len = tx * rx;
-
- data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
- if (!data) {
- ts_err("alloc memory failed for ");
- return -ENOMEM;
- }
-
- bytes += sprintf(&data[bytes], "<RawDataRecord>\n");
- for (i = 0; i < TOTAL_FRAME_NUM; i++) {
- goodix_data_cal(ts_test->rawdata[i].data, len, stat_result);
- bytes += sprintf(&data[bytes],
- "<DataContent No.=\"%d\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
- i, len, stat_result[1], stat_result[2], stat_result[0]);
- for (j = 0; j < len; j++) {
+ /* rawdata min limit */
+ bytes += sprintf(&data[bytes], "<MinRawLimit>\n");
+ for (i = 0; i < tx * rx; i++) {
bytes += sprintf(&data[bytes], "%d,",
- ts_test->rawdata[i].data[j]);
- if ((j + 1) % tx == 0)
+ ts_test->test_params.min_limits[i]);
+ if ((i + 1) % tx == 0)
bytes += sprintf(&data[bytes], "\n");
}
- bytes += sprintf(&data[bytes], "</DataContent>\n");
- goodix_data_cal(ts_test->accord_arr[i].data, len, stat_result);
- bytes += sprintf(&data[bytes],
- "<RawAccord No.=\"%d\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
- i, len, stat_result[1], stat_result[2], stat_result[0]);
- for (j = 0; j < len; j++) {
+ bytes += sprintf(&data[bytes], "</MinRawLimit>\n");
+ /* BeyondRawdataLower limit */
+ bytes +=
+ sprintf(&data[bytes], "<BeyondRawdataLowerLimitCnt>\n");
+ for (i = 0; i < tx * rx; i++) {
bytes += sprintf(&data[bytes], "%d,",
- ts_test->accord_arr[i].data[j]);
- if ((j + 1) % tx == 0)
+ ts_test->open_res.beyond_min_limit_cnt[i]);
+ if ((i + 1) % tx == 0)
bytes += sprintf(&data[bytes], "\n");
}
- bytes += sprintf(&data[bytes], "</RawAccord>\n");
+ bytes += sprintf(
+ &data[bytes], "</BeyondRawdataLowerLimitCnt>\n");
ret = fs_write(data, bytes, fp);
if (ret < 0) {
- ts_err("rawdata write fail.");
+ ts_err("rawdata limit write failed");
goto save_end;
}
bytes = 0;
- }
-
- bytes += sprintf(&data[bytes], "</RawDataRecord>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0)
- ts_err("rawdata write fail.");
-
-save_end:
- kfree(data);
- return ret;
-}
-static int goodix_save_noise_data(
- struct goodix_ts_test *ts_test, struct file *fp)
-{
- int i;
- int j;
- int ret = 0;
- int bytes = 0;
- s16 stat_result[3];
- char *data = NULL;
- int tx = ts_test->test_params.drv_num;
- int rx = ts_test->test_params.sen_num;
- int len = tx * rx;
-
- data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
- if (!data) {
- ts_err("alloc memory failed for ");
- return -ENOMEM;
- }
-
- bytes += sprintf(&data[bytes], "<DiffDataRecord>\n");
- for (i = 0; i < NOISEDATA_TEST_TIMES; i++) {
- goodix_data_cal(ts_test->noisedata[i].data, len, stat_result);
- bytes += sprintf(&data[bytes],
- "<DataContent No.=\"%d\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
- i, len, stat_result[1], stat_result[2], stat_result[0]);
- for (j = 0; j < len; j++) {
+ /* Max Accord limit */
+ bytes += sprintf(&data[bytes], "<MaxAccordLimit>\n");
+ for (i = 0; i < tx * rx; i++) {
bytes += sprintf(&data[bytes], "%d,",
- ts_test->noisedata[i].data[j]);
- if ((j + 1) % tx == 0)
+ ts_test->test_params.deviation_limits[i]);
+ if ((i + 1) % tx == 0)
bytes += sprintf(&data[bytes], "\n");
}
- bytes += sprintf(&data[bytes], "</DataContent>\n");
+ bytes += sprintf(&data[bytes], "</MaxAccordLimit>\n");
+ /* BeyondAccordLimitCnt */
+ bytes += sprintf(&data[bytes], "<BeyondAccordLimitCnt>\n");
+ for (i = 0; i < tx * rx; i++) {
+ bytes += sprintf(&data[bytes], "%d,",
+ ts_test->open_res.beyond_accord_limit_cnt[i]);
+ if ((i + 1) % tx == 0)
+ bytes += sprintf(&data[bytes], "\n");
+ }
+ bytes += sprintf(&data[bytes], "</BeyondAccordLimitCnt>\n");
+ bytes += sprintf(&data[bytes], "</Item>\n");
ret = fs_write(data, bytes, fp);
if (ret < 0) {
- ts_err("noisedata write fail.");
+ ts_err("rawdata limit write failed");
goto save_end;
}
bytes = 0;
- }
- bytes += sprintf(&data[bytes], "</DiffDataRecord>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0)
- ts_err("noisedata write fail.");
+ /* save noise limit */
+ if (ts_test->test_result[GTP_NOISE_TEST]) {
+ bytes += sprintf(&data[bytes],
+ "<Item name=\"Diffdata Test Sets\">\n");
+ bytes += sprintf(&data[bytes],
+ "<TotalFrameCnt>%d</TotalFrameCnt>\n",
+ NOISEDATA_TEST_TIMES);
+ bytes += sprintf(&data[bytes],
+ "<MaxJitterLimit>%d</MaxJitterLimit>\n",
+ ts_test->test_params.noise_threshold);
+ bytes += sprintf(&data[bytes], "</Item>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0) {
+ ts_err("noise limit write failed");
+ goto save_end;
+ }
+ bytes = 0;
+ }
-save_end:
- kfree(data);
- return ret;
-}
+ /* save self rawdata limit */
+ if (ts_test->test_result[GTP_SELFCAP_TEST]) {
+ bytes += sprintf(&data[bytes],
+ "<Item name=\"Self Rawdata Test Sets\">\n");
+ bytes += sprintf(&data[bytes],
+ "<TotalFrameCnt>1</TotalFrameCnt>\n");
+ bytes += sprintf(&data[bytes], "<MaxRawLimit>\n");
+ for (i = 0; i < tx + rx; i++) {
+ bytes += sprintf(&data[bytes], "%d,",
+ ts_test->test_params
+ .self_max_limits[i]);
+ if ((i + 1) % tx == 0)
+ bytes += sprintf(&data[bytes], "\n");
+ }
+ if ((tx + rx) % tx != 0)
+ bytes += sprintf(&data[bytes], "\n");
+ bytes += sprintf(&data[bytes], "</MaxRawLimit>\n");
+ bytes += sprintf(&data[bytes], "<MinRawLimit>\n");
+ for (i = 0; i < tx + rx; i++) {
+ bytes += sprintf(&data[bytes], "%d,",
+ ts_test->test_params
+ .self_min_limits[i]);
+ if ((i + 1) % tx == 0)
+ bytes += sprintf(&data[bytes], "\n");
+ }
+ if ((tx + rx) % tx != 0)
+ bytes += sprintf(&data[bytes], "\n");
+ bytes += sprintf(&data[bytes], "</MinRawLimit>\n");
+ bytes += sprintf(&data[bytes], "</Item>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0) {
+ ts_err("self rawdata limit write failed");
+ goto save_end;
+ }
+ bytes = 0;
+ }
-static int goodix_save_self_data(struct goodix_ts_test *ts_test,
- struct file *fp, s16 *src_data, u8 *title, int len)
-{
- int i;
- int ret = 0;
- s32 bytes = 0;
- char *data;
- s16 stat_result[3];
- int tx = ts_test->test_params.drv_num;
+ /* save selfnoise limit */
+ if (ts_test->test_result[GTP_SELFNOISE_TEST]) {
+ bytes += sprintf(&data[bytes],
+ "<Item name=\"Self Diffdata Test Sets\">\n");
+ bytes += sprintf(&data[bytes],
+ "<TotalFrameCnt>1</TotalFrameCnt>\n");
+ bytes += sprintf(&data[bytes],
+ "<MaxJitterLimit>%d</MaxJitterLimit>\n",
+ ts_test->test_params.self_noise_threshold);
+ bytes += sprintf(&data[bytes], "</Item>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0) {
+ ts_err("raw limit write failed");
+ goto save_end;
+ }
+ bytes = 0;
+ }
- data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
- if (!data) {
- ts_err("alloc memory failed for ");
- return -ENOMEM;
- }
+ bytes += sprintf(&data[bytes], "</TestItems>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0)
+ ts_err("limit write fail.");
- bytes += sprintf(&data[bytes], "<%s>\n", title);
- ret = fs_write(data, bytes, fp);
- if (ret < 0) {
- ts_err("rawdata write fail.");
- goto save_end;
+ save_end:
+ kfree(data);
+ return ret;
}
- bytes = 0;
- goodix_data_cal(src_data, len, stat_result);
- bytes += sprintf(&data[bytes],
- "<DataContent No.=\"0\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
- len, stat_result[1], stat_result[2], stat_result[0]);
- for (i = 0; i < len; i++) {
- bytes += sprintf(&data[bytes], "%d,", src_data[i]);
- if ((i + 1) % tx == 0)
- bytes += sprintf(&data[bytes], "\n");
+ static int goodix_save_rawdata(
+ struct goodix_ts_test * ts_test, struct file * fp)
+ {
+ int i;
+ int j;
+ int ret;
+ int bytes = 0;
+ s16 stat_result[3];
+ char *data = NULL;
+ int tx = ts_test->test_params.drv_num;
+ int rx = ts_test->test_params.sen_num;
+ int len = tx * rx;
+
+ data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ bytes += sprintf(&data[bytes], "<RawDataRecord>\n");
+ for (i = 0; i < TOTAL_FRAME_NUM; i++) {
+ goodix_data_cal(
+ ts_test->rawdata[i].data, len, stat_result);
+ bytes += sprintf(&data[bytes],
+ "<DataContent No.=\"%d\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
+ i, len, stat_result[1], stat_result[2],
+ stat_result[0]);
+ for (j = 0; j < len; j++) {
+ bytes += sprintf(&data[bytes], "%d,",
+ ts_test->rawdata[i].data[j]);
+ if ((j + 1) % tx == 0)
+ bytes += sprintf(&data[bytes], "\n");
+ }
+ bytes += sprintf(&data[bytes], "</DataContent>\n");
+ goodix_data_cal(
+ ts_test->accord_arr[i].data, len, stat_result);
+ bytes += sprintf(&data[bytes],
+ "<RawAccord No.=\"%d\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
+ i, len, stat_result[1], stat_result[2],
+ stat_result[0]);
+ for (j = 0; j < len; j++) {
+ bytes += sprintf(&data[bytes], "%d,",
+ ts_test->accord_arr[i].data[j]);
+ if ((j + 1) % tx == 0)
+ bytes += sprintf(&data[bytes], "\n");
+ }
+ bytes += sprintf(&data[bytes], "</RawAccord>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0) {
+ ts_err("rawdata write fail.");
+ goto save_end;
+ }
+ bytes = 0;
+ }
+
+ bytes += sprintf(&data[bytes], "</RawDataRecord>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0)
+ ts_err("rawdata write fail.");
+
+ save_end:
+ kfree(data);
+ return ret;
}
- if (len % tx != 0)
- bytes += sprintf(&data[bytes], "\n");
- bytes += sprintf(&data[bytes], "</DataContent>\n");
- bytes += sprintf(&data[bytes], "</%s>\n", title);
- ret = fs_write(data, bytes, fp);
- if (ret < 0)
- ts_err("rawdata write fail.");
-save_end:
- kfree(data);
- return ret;
-}
+ static int goodix_save_noise_data(
+ struct goodix_ts_test * ts_test, struct file * fp)
+ {
+ int i;
+ int j;
+ int ret = 0;
+ int bytes = 0;
+ s16 stat_result[3];
+ char *data = NULL;
+ int tx = ts_test->test_params.drv_num;
+ int rx = ts_test->test_params.sen_num;
+ int len = tx * rx;
+
+ data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ bytes += sprintf(&data[bytes], "<DiffDataRecord>\n");
+ for (i = 0; i < NOISEDATA_TEST_TIMES; i++) {
+ goodix_data_cal(
+ ts_test->noisedata[i].data, len, stat_result);
+ bytes += sprintf(&data[bytes],
+ "<DataContent No.=\"%d\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
+ i, len, stat_result[1], stat_result[2],
+ stat_result[0]);
+ for (j = 0; j < len; j++) {
+ bytes += sprintf(&data[bytes], "%d,",
+ ts_test->noisedata[i].data[j]);
+ if ((j + 1) % tx == 0)
+ bytes += sprintf(&data[bytes], "\n");
+ }
+ bytes += sprintf(&data[bytes], "</DataContent>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0) {
+ ts_err("noisedata write fail.");
+ goto save_end;
+ }
+ bytes = 0;
+ }
-static int goodix_save_data(struct goodix_ts_test *ts_test, struct file *fp)
-{
- int ret;
- int bytes = 0;
- char *data = NULL;
+ bytes += sprintf(&data[bytes], "</DiffDataRecord>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0)
+ ts_err("noisedata write fail.");
- data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
- if (!data) {
- ts_err("alloc memory failed for ");
- return -ENOMEM;
+ save_end:
+ kfree(data);
+ return ret;
}
- bytes += sprintf(&data[bytes], "<DataRecord>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0) {
- ts_err("rawdata record label failed");
- goto save_end;
- }
- bytes = 0;
+ static int goodix_save_self_data(struct goodix_ts_test * ts_test,
+ struct file * fp, s16 * src_data, u8 * title, int len)
+ {
+ int i;
+ int ret = 0;
+ s32 bytes = 0;
+ char *data;
+ s16 stat_result[3];
+ int tx = ts_test->test_params.drv_num;
- ret = goodix_save_rawdata(ts_test, fp);
- if (ret < 0)
- goto save_end;
+ data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- if (ts_test->test_result[GTP_NOISE_TEST]) {
- ret = goodix_save_noise_data(ts_test, fp);
- if (ret < 0)
+ bytes += sprintf(&data[bytes], "<%s>\n", title);
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0) {
+ ts_err("rawdata write fail.");
goto save_end;
- }
+ }
+ bytes = 0;
- if (ts_test->test_result[GTP_SELFCAP_TEST]) {
- ret = goodix_save_self_data(ts_test, fp,
- ts_test->self_rawdata.data, "selfDataRecord",
- ts_test->self_rawdata.size);
+ goodix_data_cal(src_data, len, stat_result);
+ bytes += sprintf(&data[bytes],
+ "<DataContent No.=\"0\" DataCount=\"%d\" Maximum=\"%d\" Minimum=\"%d\" Average=\"%d\">\n",
+ len, stat_result[1], stat_result[2], stat_result[0]);
+ for (i = 0; i < len; i++) {
+ bytes += sprintf(&data[bytes], "%d,", src_data[i]);
+ if ((i + 1) % tx == 0)
+ bytes += sprintf(&data[bytes], "\n");
+ }
+ if (len % tx != 0)
+ bytes += sprintf(&data[bytes], "\n");
+ bytes += sprintf(&data[bytes], "</DataContent>\n");
+ bytes += sprintf(&data[bytes], "</%s>\n", title);
+ ret = fs_write(data, bytes, fp);
if (ret < 0)
- goto save_end;
- }
+ ts_err("rawdata write fail.");
- if (ts_test->test_result[GTP_SELFNOISE_TEST]) {
- ret = goodix_save_self_data(ts_test, fp,
- ts_test->self_noisedata.data, "selfDiffDataRecord",
- ts_test->self_noisedata.size);
- if (ret < 0)
- goto save_end;
+ save_end:
+ kfree(data);
+ return ret;
}
- bytes += sprintf(&data[bytes], "</DataRecord>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0)
- ts_err("rawdata data record label fail.");
+ static int goodix_save_data(
+ struct goodix_ts_test * ts_test, struct file * fp)
+ {
+ int ret;
+ int bytes = 0;
+ char *data = NULL;
-save_end:
- kfree(data);
- return ret;
-}
+ data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
-/* save end tag in csv file */
-static int goodix_save_tail(struct goodix_ts_test *ts_test, struct file *fp)
-{
- int ret = 0;
- int bytes = 0;
- char *data = NULL;
+ bytes += sprintf(&data[bytes], "<DataRecord>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0) {
+ ts_err("rawdata record label failed");
+ goto save_end;
+ }
+ bytes = 0;
- data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
- if (!data) {
- ts_err("alloc memory failed for ");
- return -ENOMEM;
- }
+ ret = goodix_save_rawdata(ts_test, fp);
+ if (ret < 0)
+ goto save_end;
- bytes += sprintf(&data[bytes], "</TESTLOG>\n");
- ret = fs_write(data, bytes, fp);
- if (ret < 0)
- ts_err("tail write failed");
+ if (ts_test->test_result[GTP_NOISE_TEST]) {
+ ret = goodix_save_noise_data(ts_test, fp);
+ if (ret < 0)
+ goto save_end;
+ }
- kfree(data);
- return ret;
-}
+ if (ts_test->test_result[GTP_SELFCAP_TEST]) {
+ ret = goodix_save_self_data(ts_test, fp,
+ ts_test->self_rawdata.data, "selfDataRecord",
+ ts_test->self_rawdata.size);
+ if (ret < 0)
+ goto save_end;
+ }
-static void goodix_save_result_data(struct goodix_ts_test *ts_test)
-{
- int ret = 0;
- char save_path[100];
- struct file *fp = NULL;
+ if (ts_test->test_result[GTP_SELFNOISE_TEST]) {
+ ret = goodix_save_self_data(ts_test, fp,
+ ts_test->self_noisedata.data,
+ "selfDiffDataRecord",
+ ts_test->self_noisedata.size);
+ if (ret < 0)
+ goto save_end;
+ }
- /* format result file */
- sprintf(save_path, GOODIX_RESULT_SAVE_PATH);
- ts_info("save result IN, file_name:%s", save_path);
+ bytes += sprintf(&data[bytes], "</DataRecord>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0)
+ ts_err("rawdata data record label fail.");
- fp = filp_open(save_path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
- if (IS_ERR(fp)) {
- ts_err("create file:%s failed, fp:%ld", save_path, PTR_ERR(fp));
- return;
+ save_end:
+ kfree(data);
+ return ret;
}
- /* save header */
- ret = goodix_save_header(ts_test, fp);
- if (ret < 0)
- goto save_end;
+ /* save end tag in csv file */
+ static int goodix_save_tail(
+ struct goodix_ts_test * ts_test, struct file * fp)
+ {
+ int ret = 0;
+ int bytes = 0;
+ char *data = NULL;
- /* save limits */
- ret = goodix_save_limits(ts_test, fp);
- if (ret < 0)
- goto save_end;
+ data = kzalloc(MAX_DATA_BUFFER, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
- /* save data */
- ret = goodix_save_data(ts_test, fp);
- if (ret < 0)
- goto save_end;
+ bytes += sprintf(&data[bytes], "</TESTLOG>\n");
+ ret = fs_write(data, bytes, fp);
+ if (ret < 0)
+ ts_err("tail write failed");
- /* save tail */
- ret = goodix_save_tail(ts_test, fp);
- if (ret < 0)
- goto save_end;
+ kfree(data);
+ return ret;
+ }
- ts_info("the test result save in %s", save_path);
-save_end:
- filp_close(fp, NULL);
-}
-#endif // SAVE_IN_CSV
+ static void goodix_save_result_data(struct goodix_ts_test * ts_test)
+ {
+ int ret = 0;
+ char save_path[100];
+ struct file *fp = NULL;
-static void goodix_put_test_result(
- struct goodix_ts_test *ts_test, struct ts_rawdata_info *info)
-{
- int i;
- bool have_bus_error = false;
- bool have_panel_error = false;
- char statistics_data[STATISTICS_DATA_LEN] = { 0 };
- struct goodix_ts_core *ts = ts_test->ts;
+ /* format result file */
+ sprintf(save_path, GOODIX_RESULT_SAVE_PATH);
+ ts_info("save result IN, file_name:%s", save_path);
- ts_info("put test result IN");
+ fp = filp_open(save_path, O_CREAT | O_WRONLY | O_TRUNC, 0666);
+ if (IS_ERR(fp)) {
+ ts_err("create file:%s failed, fp:%ld", save_path,
+ PTR_ERR(fp));
+ return;
+ }
- info->buff[0] = ts_test->test_params.sen_num;
- info->buff[1] = ts_test->test_params.drv_num;
- info->used_size = 2;
- /* save rawdata to info->buff, only one frame */
- if (ts_test->rawdata[0].size) {
- for (i = 0; i < ts_test->rawdata[0].size; i++)
- info->buff[info->used_size + i] =
- ts_test->rawdata[0].data[i];
- info->used_size += ts_test->rawdata[0].size;
- }
+ /* save header */
+ ret = goodix_save_header(ts_test, fp);
+ if (ret < 0)
+ goto save_end;
- /* save noisedata to info->buff */
- if (ts_test->noisedata[0].size) {
- for (i = 0; i < ts_test->noisedata[0].size; i++)
- info->buff[info->used_size + i] =
- ts_test->noisedata[0].data[i];
- info->used_size += ts_test->noisedata[0].size;
- }
+ /* save limits */
+ ret = goodix_save_limits(ts_test, fp);
+ if (ret < 0)
+ goto save_end;
- /* save self_noisedata to info->buff */
- if (ts_test->self_noisedata.size) {
- for (i = 0; i < ts_test->self_noisedata.size; i++)
- info->buff[info->used_size + i] =
- ts_test->self_noisedata.data[i];
- info->used_size += ts_test->self_noisedata.size;
- }
+ /* save data */
+ ret = goodix_save_data(ts_test, fp);
+ if (ret < 0)
+ goto save_end;
- /* save self_rawdata to info->buff */
- if (ts_test->self_rawdata.size) {
- for (i = 0; i < ts_test->self_rawdata.size; i++)
- info->buff[info->used_size + i] =
- ts_test->self_rawdata.data[i];
- info->used_size += ts_test->self_rawdata.size;
- }
+ /* save tail */
+ ret = goodix_save_tail(ts_test, fp);
+ if (ret < 0)
+ goto save_end;
- /* check if there have bus error */
- for (i = 0; i < MAX_TEST_ITEMS; i++) {
- if (ts_test->test_result[i] == SYS_SOFTWARE_REASON)
- have_bus_error = true;
- else if (ts_test->test_result[i] == GTP_PANEL_REASON)
- have_panel_error = true;
+ ts_info("the test result save in %s", save_path);
+ save_end:
+ filp_close(fp, NULL);
}
- ts_info("Have bus error:%d", have_bus_error);
- if (have_bus_error || have_panel_error)
- goodix_strncat(
- ts_test->test_info, "[FAIL]-", TS_RAWDATA_RESULT_MAX);
- else
- goodix_strncat(
- ts_test->test_info, "[PASS]-", TS_RAWDATA_RESULT_MAX);
-
- if (have_bus_error)
- goodix_strncat(
- ts_test->test_info, "0F-", TS_RAWDATA_RESULT_MAX);
- else
- goodix_strncat(
- ts_test->test_info, "0P-", TS_RAWDATA_RESULT_MAX);
+#endif // SAVE_IN_CSV
- for (i = 0; i < MAX_TEST_ITEMS; i++) {
- /* if have tested, show result */
- if (ts_test->test_result[i]) {
- if (GTP_TEST_PASS == ts_test->test_result[i])
- goodix_strncatint(ts_test->test_info, i, "%dP-",
- TS_RAWDATA_RESULT_MAX);
- else
- goodix_strncatint(ts_test->test_info, i, "%dF-",
- TS_RAWDATA_RESULT_MAX);
+ static void goodix_put_test_result(
+ struct goodix_ts_test * ts_test, struct ts_rawdata_info * info)
+ {
+ int i;
+ bool have_bus_error = false;
+ bool have_panel_error = false;
+ char statistics_data[STATISTICS_DATA_LEN] = { 0 };
+ struct goodix_ts_core *ts = ts_test->ts;
+
+ ts_info("put test result IN");
+
+ info->buff[0] = ts_test->test_params.sen_num;
+ info->buff[1] = ts_test->test_params.drv_num;
+ info->used_size = 2;
+ /* save rawdata to info->buff, only one frame */
+ if (ts_test->rawdata[0].size) {
+ for (i = 0; i < ts_test->rawdata[0].size; i++)
+ info->buff[info->used_size + i] =
+ ts_test->rawdata[0].data[i];
+ info->used_size += ts_test->rawdata[0].size;
+ }
+
+ /* save noisedata to info->buff */
+ if (ts_test->noisedata[0].size) {
+ for (i = 0; i < ts_test->noisedata[0].size; i++)
+ info->buff[info->used_size + i] =
+ ts_test->noisedata[0].data[i];
+ info->used_size += ts_test->noisedata[0].size;
}
- }
- /* calculate rawdata min avg max value*/
- if (ts_test->rawdata[0].size) {
- goodix_data_statistics(ts_test->rawdata[0].data,
- ts_test->rawdata[0].size, statistics_data,
- STATISTICS_DATA_LEN);
- goodix_strncat(ts_test->test_info, statistics_data,
- TS_RAWDATA_RESULT_MAX);
- } else {
- ts_err("NO valiable rawdata");
- goodix_strncat(
- ts_test->test_info, "[0,0,0]", TS_RAWDATA_RESULT_MAX);
- }
+ /* save self_noisedata to info->buff */
+ if (ts_test->self_noisedata.size) {
+ for (i = 0; i < ts_test->self_noisedata.size; i++)
+ info->buff[info->used_size + i] =
+ ts_test->self_noisedata.data[i];
+ info->used_size += ts_test->self_noisedata.size;
+ }
- /* calculate noisedata min avg max value*/
- if (ts_test->test_params.test_items[GTP_NOISE_TEST]) {
- if (ts_test->noisedata[0].size) {
- goodix_data_statistics(ts_test->noisedata[0].data,
- ts_test->noisedata[0].size, statistics_data,
- STATISTICS_DATA_LEN);
- goodix_strncat(ts_test->test_info, statistics_data,
+ /* save self_rawdata to info->buff */
+ if (ts_test->self_rawdata.size) {
+ for (i = 0; i < ts_test->self_rawdata.size; i++)
+ info->buff[info->used_size + i] =
+ ts_test->self_rawdata.data[i];
+ info->used_size += ts_test->self_rawdata.size;
+ }
+
+ /* check if there have bus error */
+ for (i = 0; i < MAX_TEST_ITEMS; i++) {
+ if (ts_test->test_result[i] == SYS_SOFTWARE_REASON)
+ have_bus_error = true;
+ else if (ts_test->test_result[i] == GTP_PANEL_REASON)
+ have_panel_error = true;
+ }
+ ts_info("Have bus error:%d", have_bus_error);
+ if (have_bus_error || have_panel_error)
+ goodix_strncat(ts_test->test_info, "[FAIL]-",
TS_RAWDATA_RESULT_MAX);
- } else {
- ts_err("NO valiable noisedata");
- goodix_strncat(ts_test->test_info, "[0,0,0]",
+ else
+ goodix_strncat(ts_test->test_info, "[PASS]-",
TS_RAWDATA_RESULT_MAX);
- }
- }
- /* calculate self_rawdata min avg max value*/
- if (ts_test->test_params.test_items[GTP_SELFCAP_TEST]) {
- if (ts_test->self_rawdata.size) {
- goodix_data_statistics(ts_test->self_rawdata.data,
- ts_test->self_rawdata.size, statistics_data,
- STATISTICS_DATA_LEN);
- goodix_strncat(ts_test->test_info, statistics_data,
+ if (have_bus_error)
+ goodix_strncat(ts_test->test_info, "0F-",
TS_RAWDATA_RESULT_MAX);
- } else {
- ts_err("NO valiable self_rawdata");
- goodix_strncat(ts_test->test_info, "[0,0,0]",
+ else
+ goodix_strncat(ts_test->test_info, "0P-",
TS_RAWDATA_RESULT_MAX);
+
+ for (i = 0; i < MAX_TEST_ITEMS; i++) {
+ /* if have tested, show result */
+ if (ts_test->test_result[i]) {
+ if (ts_test->test_result[i] == GTP_TEST_PASS)
+ goodix_strncatint(ts_test->test_info, i,
+ "%dP-", TS_RAWDATA_RESULT_MAX);
+ else
+ goodix_strncatint(ts_test->test_info, i,
+ "%dF-", TS_RAWDATA_RESULT_MAX);
+ }
}
- }
- /* calculate self_noisedata min avg max value*/
- if (ts_test->test_params.test_items[GTP_SELFNOISE_TEST]) {
- if (ts_test->self_noisedata.size) {
- goodix_data_statistics(ts_test->self_noisedata.data,
- ts_test->self_noisedata.size, statistics_data,
+ /* calculate rawdata min avg max value*/
+ if (ts_test->rawdata[0].size) {
+ goodix_data_statistics(ts_test->rawdata[0].data,
+ ts_test->rawdata[0].size, statistics_data,
STATISTICS_DATA_LEN);
goodix_strncat(ts_test->test_info, statistics_data,
TS_RAWDATA_RESULT_MAX);
} else {
- ts_err("NO valiable self_noisedata");
+ ts_err("NO valiable rawdata");
goodix_strncat(ts_test->test_info, "[0,0,0]",
TS_RAWDATA_RESULT_MAX);
}
- }
- goodix_strncat(ts_test->test_info, "-GT", TS_RAWDATA_RESULT_MAX);
- goodix_strncat(ts_test->test_info, ts->fw_version.patch_pid,
- TS_RAWDATA_RESULT_MAX);
- goodix_strncat(ts_test->test_info, "\n", TS_RAWDATA_RESULT_MAX);
- strncpy(info->result, ts_test->test_info, TS_RAWDATA_RESULT_MAX - 1);
+ /* calculate noisedata min avg max value*/
+ if (ts_test->test_params.test_items[GTP_NOISE_TEST]) {
+ if (ts_test->noisedata[0].size) {
+ goodix_data_statistics(
+ ts_test->noisedata[0].data,
+ ts_test->noisedata[0].size,
+ statistics_data, STATISTICS_DATA_LEN);
+ goodix_strncat(ts_test->test_info,
+ statistics_data, TS_RAWDATA_RESULT_MAX);
+ } else {
+ ts_err("NO valiable noisedata");
+ goodix_strncat(ts_test->test_info, "[0,0,0]",
+ TS_RAWDATA_RESULT_MAX);
+ }
+ }
-#ifdef SAVE_IN_CSV
- /* save result to file */
- goodix_save_result_data(ts_test);
-#endif
-}
+ /* calculate self_rawdata min avg max value*/
+ if (ts_test->test_params.test_items[GTP_SELFCAP_TEST]) {
+ if (ts_test->self_rawdata.size) {
+ goodix_data_statistics(
+ ts_test->self_rawdata.data,
+ ts_test->self_rawdata.size,
+ statistics_data, STATISTICS_DATA_LEN);
+ goodix_strncat(ts_test->test_info,
+ statistics_data, TS_RAWDATA_RESULT_MAX);
+ } else {
+ ts_err("NO valiable self_rawdata");
+ goodix_strncat(ts_test->test_info, "[0,0,0]",
+ TS_RAWDATA_RESULT_MAX);
+ }
+ }
-static int goodix_do_inspect(
- struct goodix_ts_core *cd, struct ts_rawdata_info *info)
-{
- int ret;
- struct goodix_ts_test *ts_test = NULL;
+ /* calculate self_noisedata min avg max value*/
+ if (ts_test->test_params.test_items[GTP_SELFNOISE_TEST]) {
+ if (ts_test->self_noisedata.size) {
+ goodix_data_statistics(
+ ts_test->self_noisedata.data,
+ ts_test->self_noisedata.size,
+ statistics_data, STATISTICS_DATA_LEN);
+ goodix_strncat(ts_test->test_info,
+ statistics_data, TS_RAWDATA_RESULT_MAX);
+ } else {
+ ts_err("NO valiable self_noisedata");
+ goodix_strncat(ts_test->test_info, "[0,0,0]",
+ TS_RAWDATA_RESULT_MAX);
+ }
+ }
- if (!cd || !info) {
- ts_err("core_data or info is NULL");
- return -ENODEV;
- }
+ goodix_strncat(
+ ts_test->test_info, "-GT", TS_RAWDATA_RESULT_MAX);
+ goodix_strncat(ts_test->test_info, ts->fw_version.patch_pid,
+ TS_RAWDATA_RESULT_MAX);
+ goodix_strncat(ts_test->test_info, "\n", TS_RAWDATA_RESULT_MAX);
+ strncpy(info->result, ts_test->test_info,
+ TS_RAWDATA_RESULT_MAX - 1);
- ts_test = kzalloc(sizeof(*ts_test), GFP_KERNEL);
- if (!ts_test) {
- ts_err("Failed to alloc mem");
- return -ENOMEM;
+#ifdef SAVE_IN_CSV
+ /* save result to file */
+ goodix_save_result_data(ts_test);
+#endif
}
- ts_test->ts = cd;
- ret = goodix_tptest_prepare(ts_test);
- if (ret < 0) {
- ts_err("Failed to prepare TP test, exit");
- strncpy(info->result, "[FAIL]-0F-software reason\n",
- TS_RAWDATA_RESULT_MAX - 1);
- goto exit_finish;
- }
- ts_info("TP test prepare OK");
+ int goodix_do_inspect(
+ struct goodix_ts_core * cd, struct ts_rawdata_info * info)
+ {
+ int ret;
+ struct goodix_ts_test *ts_test = NULL;
- goodix_capacitance_test(ts_test); /* 1F 3F 6F 7F test */
- if (ts_test->test_params.test_items[GTP_SHORT_TEST])
- goodix_shortcircut_test(ts_test); /* 5F test */
- goodix_put_test_result(ts_test, info);
- goodix_tptest_finish(ts_test);
+ if (!cd || !info) {
+ ts_err("core_data or info is NULL");
+ return -ENODEV;
+ }
-exit_finish:
- kfree(ts_test);
- return ret;
-}
+ ts_test = kzalloc(sizeof(*ts_test), GFP_KERNEL);
+ if (!ts_test)
+ return -ENOMEM;
-/* show rawdata */
-static ssize_t goodix_ts_get_rawdata_show(
- struct device *dev, struct device_attribute *attr, char *buf)
-{
- int ret = 0;
- struct ts_rawdata_info *info = NULL;
- struct goodix_ts_core *cd = dev_get_drvdata(dev);
+ ts_test->ts = cd;
+ ret = goodix_tptest_prepare(ts_test);
+ if (ret < 0) {
+ ts_err("Failed to prepare TP test, exit");
+ strncpy(info->result, "[FAIL]-0F-software reason\n",
+ TS_RAWDATA_RESULT_MAX - 1);
+ goto exit_finish;
+ }
+ ts_info("TP test prepare OK");
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info) {
- ts_err("Failed to alloc rawdata info memory");
- return -ENOMEM;
+ goodix_capacitance_test(ts_test); /* 1F 3F 6F 7F test */
+ if (ts_test->test_params.test_items[GTP_SHORT_TEST])
+ goodix_shortcircut_test(ts_test); /* 5F test */
+ goodix_put_test_result(ts_test, info);
+ goodix_tptest_finish(ts_test);
+
+ exit_finish:
+ kfree(ts_test);
+ return ret;
}
- goodix_do_inspect(cd, info);
+ /* show rawdata */
+ static ssize_t get_rawdata_show(
+ struct device * dev, struct device_attribute * attr, char *buf)
+ {
+ int ret = 0;
+ struct ts_rawdata_info *info = NULL;
+ struct goodix_ts_core *cd = dev_get_drvdata(dev);
- ret = snprintf(buf, PAGE_SIZE, "resultInfo: %s", info->result);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
- kfree(info);
- return ret;
-}
+ goodix_do_inspect(cd, info);
-static DEVICE_ATTR(get_rawdata, S_IRUGO, goodix_ts_get_rawdata_show, NULL);
-
-int inspect_module_init(void)
-{
- int ret;
- struct kobject *def_kobj = goodix_get_default_kobj();
+ ret = snprintf(buf, PAGE_SIZE, "resultInfo: %s", info->result);
- /* create sysfs */
- ret = sysfs_create_file(def_kobj, &dev_attr_get_rawdata.attr);
- if (ret < 0) {
- ts_err("create sysfs of get_rawdata failed");
- goto err_out;
+ kfree(info);
+ return ret;
}
- module_initialized = true;
- ts_info("inspect module init success");
- return 0;
+ static DEVICE_ATTR(get_rawdata, 0444, get_rawdata_show, NULL);
-err_out:
- ts_err("inspect module init failed!");
- return ret;
-}
+ int inspect_module_init(void)
+ {
+ int ret;
+ struct kobject *def_kobj = goodix_get_default_kobj();
-void inspect_module_exit(void)
-{
- struct kobject *def_kobj = goodix_get_default_kobj();
+ /* create sysfs */
+ ret = sysfs_create_file(def_kobj, &dev_attr_get_rawdata.attr);
+ if (ret < 0) {
+ ts_err("create sysfs of get_rawdata failed");
+ goto err_out;
+ }
- ts_info("inspect module exit");
- if (!module_initialized)
- return;
+ module_initialized = true;
+ ts_info("inspect module init success");
+ return 0;
- sysfs_remove_file(def_kobj, &dev_attr_get_rawdata.attr);
- module_initialized = false;
-}
+ err_out:
+ ts_err("inspect module init failed!");
+ return ret;
+ }
+
+ void inspect_module_exit(void)
+ {
+ struct kobject *def_kobj = goodix_get_default_kobj();
+
+ ts_info("inspect module exit");
+ if (!module_initialized)
+ return;
+
+ sysfs_remove_file(def_kobj, &dev_attr_get_rawdata.attr);
+ module_initialized = false;
+ }
diff --git a/goodix_ts_proc.c b/goodix_ts_proc.c
new file mode 100644
index 0000000..37457f2
--- /dev/null
+++ b/goodix_ts_proc.c
@@ -0,0 +1,376 @@
+#include "goodix_ts_core.h"
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/version.h>
+
+#define CMD_FW_UPDATE "fw_update"
+#define CMD_AUTO_TEST "auto_test"
+#define CMD_GET_VERSION "get_version"
+#define CMD_GET_RAWDATA "get_raw"
+#define CMD_GET_DIFFDATA "get_diff"
+#define CMD_GET_SELF_RAWDATA "get_self_raw"
+#define CMD_GET_SELF_DIFFDATA "get_self_diff"
+#define CMD_SET_DOUBLE_TAP "set_double_tap"
+#define CMD_SET_SINGLE_TAP "set_single_tap"
+#define CMD_SET_CHARGE_MODE "set_charge_mode"
+#define CMD_SET_IRQ_ENABLE "set_irq_enable"
+#define CMD_SET_ESD_ENABLE "set_esd_enable"
+#define CMD_SET_DEBUG_LOG "set_debug_log"
+
+#define SHORT_SIZE 100
+#define LARGE_SIZE 4096
+static struct goodix_ts_core *cd;
+static char wbuf[SHORT_SIZE];
+static char *rbuf;
+static uint32_t index;
+
+static void *seq_start(struct seq_file *s, loff_t *pos)
+{
+ if (*pos >= index)
+ return NULL;
+
+ return rbuf + *pos;
+}
+
+static int seq_show(struct seq_file *s, void *v)
+{
+ seq_printf(s, (u8 *)v);
+ return 0;
+}
+
+static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ *pos += index;
+ return NULL;
+}
+
+static void seq_stop(struct seq_file *s, void *v)
+{
+ if (s->read_pos >= index) {
+ // ts_info("read_pos:%d", (int)s->read_pos);
+ kfree(rbuf);
+ rbuf = NULL;
+ index = 0;
+ }
+}
+
+static const struct seq_operations seq_ops = {
+ .start = seq_start, .next = seq_next, .stop = seq_stop, .show = seq_show
+};
+
+static int driver_test_open(struct inode *inode, struct file *file)
+{
+ memset(wbuf, 0, sizeof(wbuf));
+
+ return seq_open(file, &seq_ops);
+}
+
+static int driver_test_release(struct inode *inode, struct file *file)
+{
+ return seq_release(inode, file);
+}
+
+static int get_cap_data(uint8_t *type)
+{
+ struct goodix_ts_cmd temp_cmd;
+ int tx = cd->ic_info.parm.drv_num;
+ int rx = cd->ic_info.parm.sen_num;
+ uint8_t val;
+ int retry = 20;
+ struct frame_head *frame_head;
+ unsigned char frame_buf[GOODIX_MAX_FRAMEDATA_LEN];
+ unsigned char *cur_ptr;
+ unsigned int flag_addr = cd->ic_info.misc.frame_data_addr;
+ int i;
+ int ret;
+
+ /* disable irq & close esd */
+ cd->hw_ops->irq_enable(cd, false);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
+
+ if (strstr(type, CMD_GET_RAWDATA) ||
+ strstr(type, CMD_GET_SELF_RAWDATA)) {
+ temp_cmd.data[0] = 0x81;
+ } else {
+ temp_cmd.data[0] = 0x82;
+ }
+ temp_cmd.cmd = 0x90;
+ temp_cmd.len = 5;
+ ret = cd->hw_ops->send_cmd(cd, &temp_cmd);
+ if (ret < 0) {
+ ts_err("report rawdata failed, exit!");
+ goto exit;
+ }
+
+ /* clean touch event flag */
+ val = 0;
+ ret = cd->hw_ops->write(cd, flag_addr, &val, 1);
+ if (ret < 0) {
+ ts_err("clean touch event failed, exit!");
+ goto exit;
+ }
+
+ while (retry--) {
+ usleep_range(2000, 2100);
+ ret = cd->hw_ops->read(cd, flag_addr, &val, 1);
+ if (!ret && (val & 0x80))
+ break;
+ }
+ if (retry < 0) {
+ ts_err("framedata is not ready val:0x%02x, exit!", val);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ ret = cd->hw_ops->read(
+ cd, flag_addr, frame_buf, GOODIX_MAX_FRAMEDATA_LEN);
+ if (ret < 0) {
+ ts_err("read frame data failed");
+ goto exit;
+ }
+
+ if (checksum_cmp(frame_buf, cd->ic_info.misc.frame_data_head_len,
+ CHECKSUM_MODE_U8_LE)) {
+ ts_err("frame head checksum error");
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ frame_head = (struct frame_head *)frame_buf;
+ if (checksum_cmp(frame_buf, frame_head->cur_frame_len,
+ CHECKSUM_MODE_U16_LE)) {
+ ts_err("frame body checksum error");
+ ret = -EINVAL;
+ goto exit;
+ }
+ cur_ptr = frame_buf;
+ cur_ptr += cd->ic_info.misc.frame_data_head_len;
+ cur_ptr += cd->ic_info.misc.fw_attr_len;
+ cur_ptr += cd->ic_info.misc.fw_log_len;
+ cur_ptr += 8;
+
+ if (strstr(type, CMD_GET_RAWDATA) || strstr(type, CMD_GET_DIFFDATA)) {
+ goodix_rotate_abcd2cbad(tx, rx, (s16 *)cur_ptr);
+ for (i = 0; i < tx * rx; i++) {
+ index += sprintf(
+ &rbuf[index], "%5d,", *((s16 *)cur_ptr + i));
+ if ((i + 1) % tx == 0)
+ index += sprintf(&rbuf[index], "\n");
+ }
+ } else {
+ cur_ptr += tx * rx * 2 + 10;
+ index += sprintf(&rbuf[index], "TX:");
+ for (i = 0; i < tx + rx; i++) {
+ index += sprintf(
+ &rbuf[index], "%5d,", *((s16 *)cur_ptr + i));
+ if ((i + 1) == tx)
+ index += sprintf(&rbuf[index], "\nRX:");
+ }
+ index += sprintf(&rbuf[index], "\n");
+ }
+
+exit:
+ temp_cmd.cmd = 0x90;
+ temp_cmd.data[0] = 0;
+ temp_cmd.len = 5;
+ cd->hw_ops->send_cmd(cd, &temp_cmd);
+ /* enable irq & esd */
+ cd->hw_ops->irq_enable(cd, true);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
+ return ret;
+}
+
+static ssize_t driver_test_write(
+ struct file *file, const char __user *buf, size_t count, loff_t *pos)
+{
+ struct goodix_fw_version fw_ver;
+ struct ts_rawdata_info *info = NULL;
+ char *p = wbuf;
+ int ret;
+
+ if (count > SHORT_SIZE) {
+ ts_err("invalid cmd size[%ld]", count);
+ return count;
+ }
+
+ if (copy_from_user(p, buf, count) != 0) {
+ ts_err("copy from user failed");
+ return count;
+ }
+
+ kfree(rbuf);
+ rbuf = NULL;
+ index = 0;
+
+ if (strstr(p, CMD_FW_UPDATE)) {
+ rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
+ ret = goodix_do_fw_update(
+ NULL, UPDATE_MODE_BLOCK | UPDATE_MODE_FORCE |
+ UPDATE_MODE_SRC_REQUEST);
+ if (ret < 0) {
+ index = sprintf(rbuf, "%s: NG\n", CMD_FW_UPDATE);
+ } else {
+ index = sprintf(rbuf, "%s: OK\n", CMD_FW_UPDATE);
+ }
+ } else if (strstr(p, CMD_GET_VERSION)) {
+ rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
+ ret = cd->hw_ops->read_version(cd, &fw_ver);
+ if (ret < 0) {
+ index = sprintf(rbuf, "%s: NG\n", CMD_GET_VERSION);
+ } else {
+ index = sprintf(rbuf, "%s: %02x%02x%02x%02x\n",
+ CMD_GET_VERSION, fw_ver.patch_vid[0],
+ fw_ver.patch_vid[1], fw_ver.patch_vid[2],
+ fw_ver.patch_vid[3]);
+ }
+ } else if (strstr(p, CMD_GET_RAWDATA)) {
+ rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
+ ret = get_cap_data(CMD_GET_RAWDATA);
+ if (ret < 0) {
+ index = sprintf(rbuf, "%s: NG\n", CMD_GET_RAWDATA);
+ }
+ } else if (strstr(p, CMD_GET_DIFFDATA)) {
+ rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
+ ret = get_cap_data(CMD_GET_DIFFDATA);
+ if (ret < 0) {
+ index = sprintf(rbuf, "%s: NG\n", CMD_GET_DIFFDATA);
+ }
+ } else if (strstr(p, CMD_GET_SELF_RAWDATA)) {
+ rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
+ ret = get_cap_data(CMD_GET_SELF_RAWDATA);
+ if (ret < 0) {
+ index = sprintf(rbuf, "%s: NG\n", CMD_GET_SELF_RAWDATA);
+ }
+ } else if (strstr(p, CMD_GET_SELF_DIFFDATA)) {
+ rbuf = kzalloc(LARGE_SIZE, GFP_KERNEL);
+ ret = get_cap_data(CMD_GET_SELF_DIFFDATA);
+ if (ret < 0) {
+ index = sprintf(
+ rbuf, "%s: NG\n", CMD_GET_SELF_DIFFDATA);
+ }
+ } else if (strstr(p, CMD_SET_DOUBLE_TAP)) {
+ rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
+ if (strlen(p) - strlen(CMD_SET_DOUBLE_TAP) > 1) {
+ if (p[strlen(CMD_SET_DOUBLE_TAP) + 1] == '0') {
+ cd->gesture_type &= ~GESTURE_DOUBLE_TAP;
+ index = sprintf(rbuf, "%s: disable OK\n",
+ CMD_SET_DOUBLE_TAP);
+ } else {
+ cd->gesture_type |= GESTURE_DOUBLE_TAP;
+ index = sprintf(rbuf, "%s: enable OK\n",
+ CMD_SET_DOUBLE_TAP);
+ }
+ } else {
+ index = sprintf(rbuf, "%s: NG\n", CMD_SET_DOUBLE_TAP);
+ }
+ } else if (strstr(p, CMD_SET_SINGLE_TAP)) {
+ rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
+ if (strlen(p) - strlen(CMD_SET_SINGLE_TAP) > 1) {
+ if (p[strlen(CMD_SET_SINGLE_TAP) + 1] == '0') {
+ cd->gesture_type &= ~GESTURE_SINGLE_TAP;
+ index = sprintf(rbuf, "%s: disable OK\n",
+ CMD_SET_SINGLE_TAP);
+ } else {
+ cd->gesture_type |= GESTURE_SINGLE_TAP;
+ index = sprintf(rbuf, "%s: enable OK\n",
+ CMD_SET_SINGLE_TAP);
+ }
+ } else {
+ index = sprintf(rbuf, "%s: NG\n", CMD_SET_SINGLE_TAP);
+ }
+ } else if (strstr(p, CMD_SET_IRQ_ENABLE)) {
+ rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
+ if (strlen(p) - strlen(CMD_SET_IRQ_ENABLE) > 1) {
+ if (p[strlen(CMD_SET_IRQ_ENABLE) + 1] == '0') {
+ cd->hw_ops->irq_enable(cd, false);
+ index = sprintf(rbuf, "%s: disable OK\n",
+ CMD_SET_IRQ_ENABLE);
+ } else {
+ cd->hw_ops->irq_enable(cd, true);
+ index = sprintf(rbuf, "%s: enable OK\n",
+ CMD_SET_IRQ_ENABLE);
+ }
+ } else {
+ index = sprintf(rbuf, "%s: NG\n", CMD_SET_IRQ_ENABLE);
+ }
+ } else if (strstr(p, CMD_SET_ESD_ENABLE)) {
+ rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
+ if (strlen(p) - strlen(CMD_SET_ESD_ENABLE) > 1) {
+ if (p[strlen(CMD_SET_ESD_ENABLE) + 1] == '0') {
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
+ index = sprintf(rbuf, "%s: disable OK\n",
+ CMD_SET_ESD_ENABLE);
+ } else {
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
+ index = sprintf(rbuf, "%s: enable OK\n",
+ CMD_SET_ESD_ENABLE);
+ }
+ } else {
+ index = sprintf(rbuf, "%s: NG\n", CMD_SET_ESD_ENABLE);
+ }
+ } else if (strstr(p, CMD_SET_DEBUG_LOG)) {
+ rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
+ if (strlen(p) - strlen(CMD_SET_DEBUG_LOG) > 1) {
+ if (p[strlen(CMD_SET_DEBUG_LOG) + 1] == '0') {
+ debug_log_flag = false;
+ index = sprintf(rbuf, "%s: disable OK\n",
+ CMD_SET_DEBUG_LOG);
+ } else {
+ debug_log_flag = true;
+ index = sprintf(rbuf, "%s: enable OK\n",
+ CMD_SET_DEBUG_LOG);
+ }
+ } else {
+ index = sprintf(rbuf, "%s: NG\n", CMD_SET_DEBUG_LOG);
+ }
+ } else if (strstr(p, CMD_AUTO_TEST)) {
+ rbuf = kzalloc(SHORT_SIZE, GFP_KERNEL);
+ info = vmalloc(sizeof(*info));
+ goodix_do_inspect(cd, info);
+ index = sprintf(rbuf, "%s: %s", CMD_AUTO_TEST, info->result);
+ vfree(info);
+ } else {
+ ts_err("not support cmd[%s]", p);
+ }
+
+ return count;
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+static const struct proc_ops driver_test_ops = {
+ .proc_open = driver_test_open,
+ .proc_read = seq_read,
+ .proc_write = driver_test_write,
+ .proc_lseek = seq_lseek,
+ .proc_release = driver_test_release,
+};
+#else
+static const struct file_operations driver_test_ops = {
+ .open = driver_test_open,
+ .read = seq_read,
+ .write = driver_test_write,
+ .llseek = seq_lseek,
+ .release = driver_test_release,
+};
+#endif
+
+int driver_test_proc_init(struct goodix_ts_core *core_data)
+{
+ struct proc_dir_entry *proc_entry;
+
+ proc_entry = proc_create(
+ "goodix_ts/driver_test", 0777, NULL, &driver_test_ops);
+ if (!proc_entry) {
+ ts_err("failed to create proc entry");
+ return -ENOMEM;
+ }
+
+ cd = core_data;
+ return 0;
+}
+
+void driver_test_proc_remove(void)
+{
+ remove_proc_entry("goodix_ts/driver_test", NULL);
+} \ No newline at end of file
diff --git a/goodix_ts_tools.c b/goodix_ts_tools.c
index 88e3917..ceae2b7 100644
--- a/goodix_ts_tools.c
+++ b/goodix_ts_tools.c
@@ -16,7 +16,6 @@
*/
#include "goodix_ts_core.h"
#include <linux/atomic.h>
-#include <linux/compat.h>
#include <linux/fs.h>
#include <linux/ioctl.h>
#include <linux/kernel.h>
diff --git a/goodix_ts_utils.c b/goodix_ts_utils.c
index 2dc08b5..ff6dafb 100644
--- a/goodix_ts_utils.c
+++ b/goodix_ts_utils.c
@@ -75,7 +75,6 @@ int checksum_cmp(const u8 *data, int size, int mode)
return 1;
for (i = 0; i < size - 2; i++)
cal_checksum += data[i];
-
r_checksum = data[size - 2] + (data[size - 1] << 8);
return (cal_checksum & 0xFFFF) == r_checksum ? 0 : 1;
}
@@ -101,12 +100,12 @@ int is_risk_data(const u8 *data, int size)
for (i = 0; i < size; i++) {
if (data[i] == 0)
zero_count++;
- else if (data[i] == 0xff)
+ else if (data[i] == 0xFF)
ff_count++;
}
if (zero_count == size || ff_count == size) {
ts_info("warning data is all %s\n",
- zero_count == size ? "zero" : "0xff");
+ zero_count == size ? "0x00" : "0xFF");
return 1;
}
@@ -150,30 +149,54 @@ void goodix_rotate_abcd2cbad(int tx, int rx, s16 *data)
}
/* get ic type */
-int goodix_get_ic_type(struct device_node *node)
+int goodix_get_ic_type(
+ struct device_node *node, struct goodix_bus_interface *bus_inf)
{
- const char *name_tmp;
- int ret;
+ const struct property *prop;
+ char ic_name[128] = { 0 };
+ int i;
- ret = of_property_read_string(node, "compatible", &name_tmp);
- if (ret < 0) {
- ts_err("get compatible failed");
- return ret;
+ prop = of_find_property(node, "compatible", NULL);
+ if (!prop || !prop->value || prop->length > sizeof(ic_name)) {
+ ts_err("invalid compatible property");
+ return -EINVAL;
}
- if (strstr(name_tmp, "9897")) {
- ts_info("ic type is BerlinA");
- ret = IC_TYPE_BERLIN_A;
- } else if (strstr(name_tmp, "9966") || strstr(name_tmp, "7986")) {
- ts_info("ic type is BerlinB");
- ret = IC_TYPE_BERLIN_B;
- } else if (strstr(name_tmp, "9916")) {
- ts_info("ic type is BerlinD");
- ret = IC_TYPE_BERLIN_D;
- } else {
- ts_info("can't find valid ic_type");
- ret = -EINVAL;
+ memcpy(ic_name, prop->value, prop->length);
+
+ /* replace string end flag with ';' */
+ for (i = 0; i < prop->length - 1; i++)
+ if (ic_name[i] == 0)
+ ic_name[i] = ';';
+
+ ts_info("ic_name %s", ic_name);
+
+ if (strstr(ic_name, "brl-a")) {
+ ts_info("ic type is brl-a");
+ bus_inf->ic_type = IC_TYPE_BERLIN_A;
+ return 0;
+ }
+
+ if (strstr(ic_name, "brl-b")) {
+ ts_info("ic type is brl-b");
+ bus_inf->ic_type = IC_TYPE_BERLIN_B;
+ if (strstr(ic_name, "ga687x")) {
+ bus_inf->sub_ic_type = IC_TYPE_SUB_B2;
+ ts_info("sub ic type is brl-b2");
+ }
+ return 0;
+ }
+ if (strstr(ic_name, "brl-d")) {
+ ts_info("ic type is brl-d");
+ bus_inf->ic_type = IC_TYPE_BERLIN_D;
+ return 0;
+ }
+ if (strstr(ic_name, "nottingham")) {
+ ts_info("ic type is nottingham");
+ bus_inf->ic_type = IC_TYPE_NOTTINGHAM;
+ return 0;
}
- return ret;
+ ts_err("unsupported ic type %s", ic_name);
+ return -EINVAL;
}