summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJing Wang <jwangh@google.com>2023-04-01 03:21:20 +0000
committerJing Wang <jwangh@google.com>2023-04-01 04:24:17 +0000
commita17332d87e6dd4f008e9575cb2f5a15fffa24fe9 (patch)
treebf1c3fe3a41c19f5b41ef9bc40ad7a363f547671
parentf7c506cc918825a37eb6a856e7dd31e7b283efdc (diff)
downloadgoodix_touch-a17332d87e6dd4f008e9575cb2f5a15fffa24fe9.tar.gz
Revert "touch/goodix: Import driver v1.2.5"
Revert submission 2421158-ct3_touch_bringup Reason for revert: b/276521272 Reverted changes: /q/submissionid:2421158-ct3_touch_bringup Change-Id: Id205ec6bddab3d7b55fdfe1b56e2ba2a2bed57cb
-rw-r--r--goodix_brl_fwupdate.c466
-rw-r--r--goodix_brl_hw.c257
-rw-r--r--goodix_brl_i2c.c50
-rw-r--r--goodix_brl_spi.c166
-rw-r--r--goodix_cfg_bin.c2
-rw-r--r--goodix_ts_core.c872
-rw-r--r--goodix_ts_core.h292
-rw-r--r--goodix_ts_gesture.c345
-rw-r--r--goodix_ts_inspect.c20
-rw-r--r--goodix_ts_proc.c333
-rw-r--r--goodix_ts_tools.c195
-rw-r--r--goodix_ts_utils.c15
12 files changed, 1920 insertions, 1093 deletions
diff --git a/goodix_brl_fwupdate.c b/goodix_brl_fwupdate.c
index f7136fa..0fb81e6 100644
--- a/goodix_brl_fwupdate.c
+++ b/goodix_brl_fwupdate.c
@@ -137,12 +137,67 @@ struct update_info_t update_brd = {
ENABLE_MISCTL_BRD,
};
-enum compare_status {
- COMPARE_EQUAL = 0,
- COMPARE_NOCODE,
- COMPARE_PIDMISMATCH,
- COMPARE_FW_NOTEQUAL,
- COMPARE_CFG_NOTEQUAL,
+/**
+ * fw_subsys_info - subsytem firmware information
+ * @type: sybsystem type
+ * @size: firmware size
+ * @flash_addr: flash address
+ * @data: firmware data
+ */
+struct fw_subsys_info {
+ u8 type;
+ u32 size;
+ u32 flash_addr;
+ const u8 *data;
+};
+
+/**
+ * firmware_summary
+ * @size: fw total length
+ * @checksum: checksum of fw
+ * @hw_pid: mask pid string
+ * @hw_pid: mask vid code
+ * @fw_pid: fw pid string
+ * @fw_vid: fw vid code
+ * @subsys_num: number of fw subsystem
+ * @chip_type: chip type
+ * @protocol_ver: firmware packing
+ * protocol version
+ * @bus_type: 0 represent I2C, 1 for SPI
+ * @subsys: sybsystem info
+ */
+#pragma pack(1)
+struct firmware_summary {
+ u32 size;
+ u32 checksum;
+ u8 hw_pid[6];
+ u8 hw_vid[3];
+ u8 fw_pid[FW_PID_LEN];
+ u8 fw_vid[FW_VID_LEN];
+ u8 subsys_num;
+ u8 chip_type;
+ u8 protocol_ver;
+ u8 bus_type;
+ u8 flash_protect;
+ // u8 reserved[8];
+ struct fw_subsys_info subsys[FW_SUBSYS_MAX_NUM];
+};
+#pragma pack()
+
+/**
+ * firmware_data - firmware data structure
+ * @fw_summary: firmware information
+ * @firmware: firmware data structure
+ */
+struct firmware_data {
+ struct firmware_summary fw_summary;
+ const struct firmware *firmware;
+ struct firmware *fw_sysfs;
+};
+
+struct config_data {
+ u8 *data;
+ int size;
};
#pragma pack(1)
@@ -163,6 +218,90 @@ struct goodix_flash_cmd {
};
#pragma pack()
+enum update_status {
+ UPSTA_NOTWORK = 0,
+ UPSTA_PREPARING,
+ UPSTA_UPDATING,
+ UPSTA_SUCCESS,
+ UPSTA_FAILED
+};
+
+enum compare_status {
+ COMPARE_EQUAL = 0,
+ COMPARE_NOCODE,
+ COMPARE_PIDMISMATCH,
+ COMPARE_FW_NOTEQUAL,
+ COMPARE_CFG_NOTEQUAL,
+};
+
+/**
+ * fw_update_ctrl - structure used to control the
+ * firmware update process
+ * @initialized: struct init state
+ * @mode: indicate weather reflash config or not, fw data source,
+ * and run on block mode or not.
+ * @status: update status
+ * @progress: indicate the progress of update
+ * @fw_data: firmware data
+ * @fw_name: firmware name
+ * @attr_fwimage: sysfs bin attrs, for storing fw image
+ * @fw_data_src: firmware data source form sysfs, request or head file
+ * @kobj: pointer to the sysfs kobject
+ */
+struct fw_update_ctrl {
+ struct mutex mutex;
+ int initialized;
+ char fw_name[GOODIX_MAX_STR_LABEL_LEN];
+ int mode;
+ enum update_status status;
+ int spend_time;
+
+ struct firmware_data fw_data;
+ struct goodix_ic_config *ic_config;
+ struct goodix_ts_core *core_data;
+ struct update_info_t *update_info;
+
+ struct attribute_group attrs;
+ struct kobject *kobj;
+};
+static struct fw_update_ctrl goodix_fw_update_ctrl;
+static struct goodix_ic_config one_binary_cfg;
+
+static int goodix_fw_update_reset(int delay)
+{
+ struct goodix_ts_hw_ops *hw_ops;
+
+ hw_ops = goodix_fw_update_ctrl.core_data->hw_ops;
+ return hw_ops->reset(goodix_fw_update_ctrl.core_data, delay);
+}
+
+static int get_fw_version_info(struct goodix_fw_version *fw_version)
+{
+ struct goodix_ts_hw_ops *hw_ops =
+ goodix_fw_update_ctrl.core_data->hw_ops;
+
+ return hw_ops->read_version(
+ goodix_fw_update_ctrl.core_data, fw_version);
+}
+
+static int goodix_reg_write(
+ unsigned int addr, unsigned char *data, unsigned int len)
+{
+ struct goodix_ts_hw_ops *hw_ops =
+ goodix_fw_update_ctrl.core_data->hw_ops;
+
+ return hw_ops->write(goodix_fw_update_ctrl.core_data, addr, data, len);
+}
+
+static int goodix_reg_read(
+ unsigned int addr, unsigned char *data, unsigned int len)
+{
+ struct goodix_ts_hw_ops *hw_ops =
+ goodix_fw_update_ctrl.core_data->hw_ops;
+
+ return hw_ops->read(goodix_fw_update_ctrl.core_data, addr, data, len);
+}
+
/**
* goodix_parse_firmware - parse firmware header information
* and subsystem information from firmware data buffer
@@ -172,24 +311,26 @@ struct goodix_flash_cmd {
* return: 0 - OK, < 0 - error
*/
/* sizeof(length) + sizeof(checksum) */
-static int goodix_parse_firmware(struct goodix_ts_core *cd,
- struct firmware_data *fw_data)
+
+static int goodix_parse_firmware(struct firmware_data *fw_data)
{
const struct firmware *firmware;
struct firmware_summary *fw_summary;
unsigned int i, fw_offset, info_offset;
u32 checksum;
- int ic_type = cd->bus->ic_type;
+ int ic_type = goodix_fw_update_ctrl.core_data->bus->ic_type;
int subsys_info_offset =
- cd->update_ctrl.update_info->subsys_info_offset;
- int header_size = cd->update_ctrl.update_info->header_size;
- struct goodix_ic_config *one_binary_cfg = &cd->update_ctrl.one_binary_cfg;
+ goodix_fw_update_ctrl.update_info->subsys_info_offset;
+ int header_size = goodix_fw_update_ctrl.update_info->header_size;
int r = 0;
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);
@@ -266,10 +407,10 @@ static int goodix_parse_firmware(struct goodix_ts_core *cd,
ts_debug("Subsystem Ptr:%p", fw_summary->subsys[i].data);
if (fw_summary->subsys[i].type == CONFIG_DATA_TYPE) {
- one_binary_cfg->len = fw_summary->subsys[i].size;
- memcpy(one_binary_cfg->data, fw_summary->subsys[i].data,
- one_binary_cfg->len);
- cd->update_ctrl.ic_config = one_binary_cfg;
+ one_binary_cfg.len = fw_summary->subsys[i].size;
+ memcpy(one_binary_cfg.data, fw_summary->subsys[i].data,
+ one_binary_cfg.len);
+ goodix_fw_update_ctrl.ic_config = &one_binary_cfg;
}
}
@@ -301,29 +442,33 @@ err_size:
static int goodix_fw_version_compare(struct fw_update_ctrl *fwu_ctrl)
{
int ret = 0;
- struct goodix_ts_core *cd = fwu_ctrl->core_data;
- struct goodix_fw_version *ic_ver = &cd->fw_version;
- struct goodix_ic_info *ic_info = &cd->ic_info;
+ struct goodix_fw_version fw_version;
struct firmware_summary *fw_summary = &fwu_ctrl->fw_data.fw_summary;
+ u32 config_id_reg = goodix_fw_update_ctrl.update_info->config_id_reg;
u32 file_cfg_id;
+ u32 ic_cfg_id;
/* compare fw_version */
- if (!memcmp(ic_ver->rom_pid, GOODIX_NOCODE, 6) ||
- !memcmp(ic_ver->patch_pid, GOODIX_NOCODE, 6)) {
+ ret = get_fw_version_info(&fw_version);
+ if (ret)
+ return -EINVAL;
+
+ if (!memcmp(fw_version.rom_pid, GOODIX_NOCODE, 6) ||
+ !memcmp(fw_version.patch_pid, GOODIX_NOCODE, 6)) {
ts_info("there is no code in the chip");
return COMPARE_NOCODE;
}
- if (memcmp(ic_ver->patch_pid, fw_summary->fw_pid, FW_PID_LEN)) {
- ts_err("Product ID mismatch:%s != %s", ic_ver->patch_pid,
+ if (memcmp(fw_version.patch_pid, fw_summary->fw_pid, FW_PID_LEN)) {
+ ts_err("Product ID mismatch:%s != %s", fw_version.patch_pid,
fw_summary->fw_pid);
return COMPARE_PIDMISMATCH;
}
- ret = memcmp(ic_ver->patch_vid, fw_summary->fw_vid, FW_VID_LEN);
+ ret = memcmp(fw_version.patch_vid, fw_summary->fw_vid, FW_VID_LEN);
if (ret) {
ts_info("active firmware version:%*ph", FW_VID_LEN,
- ic_ver->patch_vid);
+ fw_version.patch_vid);
ts_info("firmware file version: %*ph", FW_VID_LEN,
fw_summary->fw_vid);
return COMPARE_FW_NOTEQUAL;
@@ -334,8 +479,10 @@ static int goodix_fw_version_compare(struct fw_update_ctrl *fwu_ctrl)
if (fwu_ctrl->ic_config && fwu_ctrl->ic_config->len > 0) {
file_cfg_id =
goodix_get_file_config_id(fwu_ctrl->ic_config->data);
- if (ic_info->version.config_id != file_cfg_id) {
- ts_info("ic_cfg_id:0x%x != file_cfg_id:0x%x", ic_info->version.config_id,
+ goodix_reg_read(
+ config_id_reg, (u8 *)&ic_cfg_id, sizeof(ic_cfg_id));
+ if (ic_cfg_id != file_cfg_id) {
+ ts_info("ic_cfg_id:0x%x != file_cfg_id:0x%x", ic_cfg_id,
file_cfg_id);
return COMPARE_CFG_NOTEQUAL;
}
@@ -355,7 +502,7 @@ static int goodix_fw_version_compare(struct fw_update_ctrl *fwu_ctrl)
* return: 0 write success and confirm ok
* < 0 failed
*/
-static int goodix_reg_write_confirm(struct goodix_ts_core *cd,
+static int goodix_reg_write_confirm(
unsigned int addr, unsigned char *data, unsigned int len)
{
u8 *cfm = NULL;
@@ -371,11 +518,11 @@ static int goodix_reg_write_confirm(struct goodix_ts_core *cd,
}
for (i = 0; i < GOODIX_BUS_RETRY_TIMES; i++) {
- r = cd->hw_ops->write(cd, addr, data, len);
+ r = goodix_reg_write(addr, data, len);
if (r < 0)
goto exit;
- r = cd->hw_ops->read(cd, addr, cfm, len);
+ r = goodix_reg_read(addr, cfm, len);
if (r < 0)
goto exit;
@@ -400,11 +547,11 @@ exit:
* @fw_data: firmware data
* return 0 ok, <0 error
*/
-static int goodix_load_isp(struct goodix_ts_core *cd, struct firmware_data *fw_data)
+static int goodix_load_isp(struct firmware_data *fw_data)
{
struct goodix_fw_version isp_fw_version;
struct fw_subsys_info *fw_isp;
- u32 isp_ram_reg = cd->update_ctrl.update_info->isp_ram_reg;
+ u32 isp_ram_reg = goodix_fw_update_ctrl.update_info->isp_ram_reg;
u8 reg_val[8] = { 0x00 };
int r;
@@ -412,8 +559,8 @@ static int goodix_load_isp(struct goodix_ts_core *cd, struct firmware_data *fw_d
fw_isp = &fw_data->fw_summary.subsys[0];
ts_info("Loading ISP start");
- r = goodix_reg_write_confirm(cd, isp_ram_reg,
- (u8 *)fw_isp->data, fw_isp->size);
+ r = goodix_reg_write_confirm(
+ isp_ram_reg, (u8 *)fw_isp->data, fw_isp->size);
if (r < 0) {
ts_err("Loading ISP error");
return r;
@@ -423,16 +570,17 @@ static int goodix_load_isp(struct goodix_ts_core *cd, struct firmware_data *fw_d
/* SET BOOT OPTION TO 0X55 */
memset(reg_val, 0x55, 8);
- r = goodix_reg_write_confirm(cd, HW_REG_CPU_RUN_FROM, reg_val, 8);
+ r = goodix_reg_write_confirm(HW_REG_CPU_RUN_FROM, reg_val, 8);
if (r < 0) {
ts_err("Failed set REG_CPU_RUN_FROM flag");
return r;
}
ts_info("Success write [8]0x55 to 0x%x", HW_REG_CPU_RUN_FROM);
- cd->hw_ops->reset(cd, 100);
+ if (goodix_fw_update_reset(100))
+ ts_err("reset abnormal");
/*check isp state */
- if (cd->hw_ops->read_version(cd, &isp_fw_version)) {
+ if (get_fw_version_info(&isp_fw_version)) {
ts_err("failed read isp version");
return -2;
}
@@ -458,8 +606,6 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl)
u32 misctl_reg = fwu_ctrl->update_info->misctl_reg;
u32 watch_dog_reg = fwu_ctrl->update_info->watch_dog_reg;
u32 enable_misctl_val = fwu_ctrl->update_info->enable_misctl_val;
- struct goodix_ts_core *cd = fwu_ctrl->core_data;
- struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
u8 reg_val[4] = { 0 };
u8 temp_buf[64] = { 0 };
int retry = 20;
@@ -467,17 +613,18 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl)
/*reset IC*/
ts_info("firmware update, reset");
- hw_ops->reset(cd, 5);
+ if (goodix_fw_update_reset(5))
+ ts_err("reset abnormal");
retry = 100;
/* Hold cpu*/
do {
reg_val[0] = 0x01;
reg_val[1] = 0x00;
- r = hw_ops->write(cd, HOLD_CPU_REG_W, reg_val, 2);
- r |= hw_ops->read(cd, HOLD_CPU_REG_R, &temp_buf[0], 4);
- r |= hw_ops->read(cd, HOLD_CPU_REG_R, &temp_buf[4], 4);
- r |= hw_ops->read(cd, HOLD_CPU_REG_R, &temp_buf[8], 4);
+ r = goodix_reg_write(HOLD_CPU_REG_W, reg_val, 2);
+ r |= goodix_reg_read(HOLD_CPU_REG_R, &temp_buf[0], 4);
+ r |= goodix_reg_read(HOLD_CPU_REG_R, &temp_buf[4], 4);
+ r |= goodix_reg_read(HOLD_CPU_REG_R, &temp_buf[8], 4);
if (!r && !memcmp(&temp_buf[0], &temp_buf[4], 4) &&
!memcmp(&temp_buf[4], &temp_buf[8], 4) &&
!memcmp(&temp_buf[0], &temp_buf[8], 4)) {
@@ -494,20 +641,20 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl)
ts_info("Success hold CPU");
/* enable misctl clock */
- if (cd->bus->ic_type == IC_TYPE_BERLIN_D ||
- cd->bus->ic_type == IC_TYPE_NOTTINGHAM)
- hw_ops->write(cd, misctl_reg, (u8 *)&enable_misctl_val, 4);
+ 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
- hw_ops->write(cd, misctl_reg, (u8 *)&enable_misctl_val, 1);
+ goodix_reg_write(misctl_reg, (u8 *)&enable_misctl_val, 1);
ts_info("enable misctl clock");
- if (cd->bus->ic_type == IC_TYPE_BERLIN_A) {
+ if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_A) {
/* open ESD_KEY */
retry = 20;
do {
reg_val[0] = 0x95;
- r = hw_ops->write(cd, ESD_KEY_REG, reg_val, 1);
- r |= hw_ops->read(cd, ESD_KEY_REG, temp_buf, 1);
+ r = goodix_reg_write(ESD_KEY_REG, reg_val, 1);
+ r |= goodix_reg_read(ESD_KEY_REG, temp_buf, 1);
if (!r && temp_buf[0] == 0x01)
break;
usleep_range(1000, 1100);
@@ -523,11 +670,11 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl)
/* disable watch dog */
reg_val[0] = 0x00;
- r = hw_ops->write(cd, watch_dog_reg, reg_val, 1);
+ r = goodix_reg_write(watch_dog_reg, reg_val, 1);
ts_info("disable watch dog");
/* load ISP code and run form isp */
- r = goodix_load_isp(cd, &fwu_ctrl->fw_data);
+ r = goodix_load_isp(&fwu_ctrl->fw_data);
if (r < 0)
ts_err("Failed load and run isp");
@@ -537,18 +684,17 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl)
/* goodix_send_flash_cmd: send command to read or write flash data
* @flash_cmd: command need to send.
*/
-static int goodix_send_flash_cmd(struct goodix_ts_core *cd,
- struct goodix_flash_cmd *flash_cmd)
+static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd)
{
int i, ret, retry;
struct goodix_flash_cmd tmp_cmd;
- u32 flash_cmd_reg = cd->update_ctrl.update_info->flash_cmd_reg;
+ u32 flash_cmd_reg = goodix_fw_update_ctrl.update_info->flash_cmd_reg;
ts_info("try send flash cmd:%*ph", (int)sizeof(flash_cmd->buf),
flash_cmd->buf);
memset(tmp_cmd.buf, 0, sizeof(tmp_cmd));
- ret = cd->hw_ops->write(cd, flash_cmd_reg,
- flash_cmd->buf, sizeof(flash_cmd->buf));
+ ret = goodix_reg_write(
+ flash_cmd_reg, flash_cmd->buf, sizeof(flash_cmd->buf));
if (ret) {
ts_err("failed send flash cmd %d", ret);
return ret;
@@ -556,8 +702,8 @@ static int goodix_send_flash_cmd(struct goodix_ts_core *cd,
retry = 5;
for (i = 0; i < retry; i++) {
- ret = cd->hw_ops->read(cd, flash_cmd_reg,
- tmp_cmd.buf, sizeof(tmp_cmd.buf));
+ ret = goodix_reg_read(
+ flash_cmd_reg, tmp_cmd.buf, sizeof(tmp_cmd.buf));
if (!ret && tmp_cmd.ack == FLASH_CMD_ACK_CHK_PASS)
break;
usleep_range(5000, 5100);
@@ -575,8 +721,8 @@ static int goodix_send_flash_cmd(struct goodix_ts_core *cd,
msleep(50);
retry = 20;
for (i = 0; i < retry; i++) {
- ret = cd->hw_ops->read(cd, flash_cmd_reg,
- tmp_cmd.buf, sizeof(tmp_cmd.buf));
+ ret = goodix_reg_read(
+ flash_cmd_reg, tmp_cmd.buf, sizeof(tmp_cmd.buf));
if (!ret && tmp_cmd.ack == FLASH_CMD_ACK_CHK_PASS &&
tmp_cmd.status == FLASH_CMD_W_STATUS_WRITE_OK) {
ts_info("flash status check pass");
@@ -614,17 +760,16 @@ static int goodix_send_flash_cmd(struct goodix_ts_core *cd,
}
}
-static int goodix_flash_package(struct goodix_ts_core *cd,
- u8 subsys_type, u8 *pkg,
- u32 flash_addr, u16 pkg_len)
+static int goodix_flash_package(
+ u8 subsys_type, u8 *pkg, u32 flash_addr, u16 pkg_len)
{
int ret, retry;
struct goodix_flash_cmd flash_cmd;
- u32 isp_buffer_reg = cd->update_ctrl.update_info->isp_buffer_reg;
+ u32 isp_buffer_reg = goodix_fw_update_ctrl.update_info->isp_buffer_reg;
retry = 2;
do {
- ret = cd->hw_ops->write(cd, isp_buffer_reg, pkg, pkg_len);
+ ret = goodix_reg_write(isp_buffer_reg, pkg, pkg_len);
if (ret < 0) {
ts_err("Failed to write firmware packet");
return ret;
@@ -641,7 +786,7 @@ static int goodix_flash_package(struct goodix_ts_core *cd,
goodix_append_checksum(
&(flash_cmd.buf[2]), 9, CHECKSUM_MODE_U8_LE);
- ret = goodix_send_flash_cmd(cd, &flash_cmd);
+ ret = goodix_send_flash_cmd(&flash_cmd);
if (!ret) {
ts_info("success write package to 0x%05X, len %d",
flash_addr, pkg_len - 4);
@@ -662,8 +807,7 @@ static int goodix_flash_package(struct goodix_ts_core *cd,
* @subsys: subsystem information
* return: 0 ok, < 0 error
*/
-static int goodix_flash_subsystem(struct goodix_ts_core *cd,
- struct fw_subsys_info *subsys)
+static int goodix_flash_subsystem(struct fw_subsys_info *subsys)
{
u32 data_size, offset;
u32 total_size;
@@ -696,7 +840,7 @@ static int goodix_flash_subsystem(struct goodix_ts_core *cd,
goodix_append_checksum(
fw_packet, data_size, CHECKSUM_MODE_U16_LE);
- r = goodix_flash_package(cd, subsys->type, fw_packet,
+ r = goodix_flash_package(subsys->type, fw_packet,
subsys_base_addr + offset, data_size + 4);
if (r) {
ts_err("failed flash to 0x%05X,size:%u bytes",
@@ -740,7 +884,7 @@ static int goodix_flash_firmware(struct fw_update_ctrl *fw_ctrl)
subsys_cfg.size = GOODIX_CFG_MAX_SIZE;
subsys_cfg.flash_addr = config_data_reg;
subsys_cfg.type = CONFIG_DATA_TYPE;
- r = goodix_flash_subsystem(fw_ctrl->core_data, &subsys_cfg);
+ r = goodix_flash_subsystem(&subsys_cfg);
if (r) {
ts_err("failed flash config with ISP, %d", r);
return r;
@@ -751,7 +895,7 @@ static int goodix_flash_firmware(struct fw_update_ctrl *fw_ctrl)
for (i = 1; i < fw_num && retry;) {
ts_info("--- Start to flash subsystem[%d] ---", i);
fw_x = &fw_summary->subsys[i];
- r = goodix_flash_subsystem(fw_ctrl->core_data, fw_x);
+ r = goodix_flash_subsystem(fw_x);
if (r == 0) {
ts_info("--- End flash subsystem[%d]: OK ---", i);
i++;
@@ -778,24 +922,10 @@ exit_flash:
*/
static int goodix_update_finish(struct fw_update_ctrl *fwu_ctrl)
{
- struct goodix_ts_core *cd = fwu_ctrl->core_data;
int ret;
- /* step 1: reset IC */
- cd->hw_ops->reset(cd, 100);
- /* step 2: read version */
- ret = cd->hw_ops->read_version(cd, &cd->fw_version);
- if (ret < 0) {
- ts_err("still failed to read version after upgraded");
- return -EFAULT;
- }
- /* step 3: read ic info */
- ret = cd->hw_ops->get_ic_info(cd, &cd->ic_info);
- if (ret < 0) {
- ts_err("still failed to read ic info after upgraded");
- return -EFAULT;
- }
-
+ if (goodix_fw_update_reset(100))
+ ts_err("reset abnormal");
ret = goodix_fw_version_compare(fwu_ctrl);
if (ret == COMPARE_EQUAL || ret == COMPARE_CFG_NOTEQUAL)
return 0;
@@ -816,7 +946,7 @@ int goodix_fw_update_proc(struct fw_update_ctrl *fwu_ctrl)
int retry1 = FW_UPDATE_RETRY;
int ret = 0;
- ret = goodix_parse_firmware(fwu_ctrl->core_data, &fwu_ctrl->fw_data);
+ ret = goodix_parse_firmware(&fwu_ctrl->fw_data);
if (ret < 0)
return ret;
@@ -878,10 +1008,7 @@ static ssize_t update_en_store(struct device *dev,
{
int ret = 0;
int mode = 0;
- struct device *device =
- container_of(((struct kobject *)dev)->parent, struct device, kobj);
- struct goodix_ts_core *cd = dev_get_drvdata(device);
- struct fw_update_ctrl *fw_ctrl = &cd->update_ctrl;
+ struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
if (!buf || count <= 0) {
ts_err("invalid params");
@@ -908,7 +1035,7 @@ static ssize_t update_en_store(struct device *dev,
return -EINVAL;
}
- ret = goodix_do_fw_update(cd, mode);
+ ret = goodix_do_fw_update(NULL, mode);
if (!ret) {
ts_info("success do update work");
return count;
@@ -917,18 +1044,36 @@ static ssize_t update_en_store(struct device *dev,
return -EINVAL;
}
-/*
- * [GOOG]
- * return fw_update result
- */
+static ssize_t fwimage_write(struct file *file, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf, loff_t pos, size_t count)
+{
+ struct firmware **fw = &goodix_fw_update_ctrl.fw_data.fw_sysfs;
+
+ 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 > GOODIX_FW_MAX_SIEZE)
+ return -EFAULT;
+ memcpy((u8 *)&(*fw)->data[pos], buf, count);
+ (*fw)->size = pos + count;
+
+ return count;
+}
+
+/* return fw_update result */
static ssize_t result_show(
- struct device *dev, struct device_attribute *attr,
- char *buf)
+ struct device *dev, struct device_attribute *attr, char *buf)
{
- struct device *device =
- container_of(((struct kobject *)dev)->parent, struct device, kobj);
- struct goodix_ts_core *cd = dev_get_drvdata(device);
- struct fw_update_ctrl *fw_ctrl = &cd->update_ctrl;
+ struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
char str[GOODIX_MAX_STR_LABEL_LEN] = { 0 };
int r = -EINVAL;
@@ -954,51 +1099,57 @@ static ssize_t result_show(
break;
}
- r = snprintf(buf, PAGE_SIZE, "result:%s spend_time:%dms\n",
- str, fw_ctrl->spend_time);
+ r = snprintf(buf, PAGE_SIZE, "result:%s spend_time:%dms\n", str,
+ fw_ctrl->spend_time);
return r;
}
-/* [GOOG] */
static DEVICE_ATTR_WO(update_en);
static DEVICE_ATTR_RO(result);
-static struct attribute *goodix_fwu_attrs[] = {
+static struct attribute *goodix_attrs[] = {
&dev_attr_update_en.attr,
&dev_attr_result.attr,
- NULL
+ NULL,
+};
+
+static BIN_ATTR_WO(fwimage, 0);
+static struct bin_attribute *goodix_bin_attrs[] = {
+ &bin_attr_fwimage,
+ NULL,
};
-static int goodix_fw_sysfs_init(struct goodix_ts_core *core_data,
- struct fw_update_ctrl *fw_ctrl)
+static int goodix_fw_sysfs_init(
+ struct goodix_ts_core *core_data, struct fw_update_ctrl *fw_ctrl)
{
int ret = 0;
- fw_ctrl->kobj = kobject_create_and_add("fwupdate",
- &core_data->pdev->dev.kobj);
+ fw_ctrl->kobj =
+ kobject_create_and_add("fwupdate", &core_data->pdev->dev.kobj);
if (!fw_ctrl->kobj) {
ts_err("failed create sub dir for fwupdate");
return -EINVAL;
}
- /* [GOOG] */
- fw_ctrl->attrs.attrs = goodix_fwu_attrs;
+ fw_ctrl->attrs.attrs = goodix_attrs;
+ fw_ctrl->attrs.bin_attrs = goodix_bin_attrs;
ret = sysfs_create_group(fw_ctrl->kobj, &fw_ctrl->attrs);
if (ret) {
ts_err("Cannot create sysfs structure!\n");
kobject_put(fw_ctrl->kobj);
+ return -ENODEV;
}
- /*~[GOOG]*/
return ret;
}
-static void goodix_fw_sysfs_remove(struct goodix_ts_core *cd)
+static void goodix_fw_sysfs_remove(void)
{
- struct fw_update_ctrl *fw_ctrl = &cd->update_ctrl;
+ struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl;
- sysfs_remove_group(fw_ctrl->kobj, &fw_ctrl->attrs); /* [GOOG] */
+ sysfs_remove_group(fw_ctrl->kobj, &fw_ctrl->attrs);
+ kobject_put(fw_ctrl->kobj);
}
/**
@@ -1050,7 +1201,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 goodix_ts_core *cd = fwu_ctrl->core_data;
ktime_t start, end;
int r = -EINVAL;
@@ -1060,10 +1210,7 @@ static int goodix_fw_update_thread(void *data)
mutex_lock(&fwu_ctrl->mutex);
ts_debug("notify update start");
- if (cd->init_stage >= CORE_INIT_STAGE2) {
- cd->hw_ops->irq_enable(cd, 0);
- goodix_ts_esd_off(cd);
- }
+ goodix_ts_blocking_notify(NOTIFY_FWUPDATE_START, NULL);
if (fwu_ctrl->mode & UPDATE_MODE_SRC_REQUEST) {
ts_info("Firmware request update starts");
@@ -1071,6 +1218,21 @@ static int goodix_fw_update_thread(void *data)
&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.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;
@@ -1082,8 +1244,13 @@ static int goodix_fw_update_thread(void *data)
r = goodix_fw_update_proc(fwu_ctrl);
/* clean */
- if (fwu_ctrl->mode & UPDATE_MODE_SRC_REQUEST)
+ 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);
+ }
out:
fwu_ctrl->mode = UPDATE_MODE_DEFAULT;
mutex_unlock(&fwu_ctrl->mutex);
@@ -1091,25 +1258,23 @@ out:
if (r) {
ts_err("fw update failed, %d", r);
fwu_ctrl->status = UPSTA_FAILED;
+ goodix_ts_blocking_notify(NOTIFY_FWUPDATE_FAILED, NULL);
} else {
ts_info("fw update success");
fwu_ctrl->status = UPSTA_SUCCESS;
+ goodix_ts_blocking_notify(NOTIFY_FWUPDATE_SUCCESS, NULL);
}
end = ktime_get();
fwu_ctrl->spend_time = ktime_to_ms(ktime_sub(end, start));
- if (cd->init_stage >= CORE_INIT_STAGE2) {
- cd->hw_ops->irq_enable(cd, 1);
- goodix_ts_esd_on(cd);
- }
return r;
}
-int goodix_do_fw_update(struct goodix_ts_core *cd, int mode)
+int goodix_do_fw_update(struct goodix_ic_config *ic_config, int mode)
{
struct task_struct *fwu_thrd;
- struct fw_update_ctrl *fwu_ctrl = &cd->update_ctrl;
+ struct fw_update_ctrl *fwu_ctrl = &goodix_fw_update_ctrl;
int ret;
if (!fwu_ctrl->initialized) {
@@ -1118,7 +1283,7 @@ int goodix_do_fw_update(struct goodix_ts_core *cd, int mode)
}
fwu_ctrl->mode = mode;
- fwu_ctrl->ic_config = cd->ic_configs[CONFIG_TYPE_NORMAL];
+ fwu_ctrl->ic_config = ic_config;
ts_debug("fw update mode 0x%x", mode);
if (fwu_ctrl->mode & UPDATE_MODE_BLOCK) {
ret = goodix_fw_update_thread(fwu_ctrl);
@@ -1144,34 +1309,37 @@ int goodix_fw_update_init(struct goodix_ts_core *core_data)
return -ENODEV;
}
- mutex_init(&core_data->update_ctrl.mutex);
- core_data->update_ctrl.core_data = core_data;
- core_data->update_ctrl.mode = 0;
+ mutex_init(&goodix_fw_update_ctrl.mutex);
+ goodix_fw_update_ctrl.core_data = core_data;
+ goodix_fw_update_ctrl.mode = 0;
- strlcpy(core_data->update_ctrl.fw_name, core_data->board_data.fw_name,
- sizeof(core_data->update_ctrl.fw_name));
+ strlcpy(goodix_fw_update_ctrl.fw_name, core_data->board_data.fw_name,
+ sizeof(goodix_fw_update_ctrl.fw_name));
- ret = goodix_fw_sysfs_init(core_data, &core_data->update_ctrl);
+ ret = goodix_fw_sysfs_init(core_data, &goodix_fw_update_ctrl);
if (ret) {
ts_err("failed create fwupate sysfs node");
return ret;
}
if (core_data->bus->ic_type == IC_TYPE_BERLIN_A)
- core_data->update_ctrl.update_info = &update_bra;
+ goodix_fw_update_ctrl.update_info = &update_bra;
else if (core_data->bus->ic_type == IC_TYPE_BERLIN_B)
- core_data->update_ctrl.update_info = &update_brb;
+ goodix_fw_update_ctrl.update_info = &update_brb;
else
- core_data->update_ctrl.update_info = &update_brd;
+ goodix_fw_update_ctrl.update_info = &update_brd;
- core_data->update_ctrl.initialized = 1;
+ goodix_fw_update_ctrl.initialized = 1;
return 0;
}
-void goodix_fw_update_uninit(struct goodix_ts_core *core_data)
+void goodix_fw_update_uninit(void)
{
- if (!core_data->update_ctrl.initialized)
+ if (!goodix_fw_update_ctrl.initialized)
return;
- goodix_fw_sysfs_remove(core_data);
- core_data->update_ctrl.initialized = 0;
- mutex_destroy(&core_data->update_ctrl.mutex);
+
+ mutex_lock(&goodix_fw_update_ctrl.mutex);
+ goodix_fw_sysfs_remove();
+ goodix_fw_update_ctrl.initialized = 0;
+ mutex_unlock(&goodix_fw_update_ctrl.mutex);
+ mutex_destroy(&goodix_fw_update_ctrl.mutex);
}
diff --git a/goodix_brl_hw.c b/goodix_brl_hw.c
index cb073e1..acfd294 100644
--- a/goodix_brl_hw.c
+++ b/goodix_brl_hw.c
@@ -79,10 +79,6 @@ static int brl_dev_confirm(struct goodix_ts_core *cd)
u8 tx_buf[8] = { 0 };
u8 rx_buf[8] = { 0 };
- if (cd->bus->ic_type == IC_TYPE_BERLIN_A &&
- cd->bus->bus_type == GOODIX_BUS_TYPE_SPI)
- return brl_select_spi_mode(cd);
-
memset(tx_buf, DEV_CONFIRM_VAL, sizeof(tx_buf));
while (retry--) {
ret = hw_ops->write(
@@ -118,6 +114,11 @@ static int brl_reset_after(struct goodix_ts_core *cd)
ts_info("IN");
+ /* select spi mode */
+ ret = brl_select_spi_mode(cd);
+ if (ret < 0)
+ return ret;
+
/* hold cpu */
retry = GOODIX_RETRY_10;
while (retry--) {
@@ -849,7 +850,7 @@ static int convert_ic_info(struct goodix_ic_info *info, const u8 *data)
return 0;
}
-void print_ic_info(struct goodix_ic_info *ic_info)
+static void print_ic_info(struct goodix_ic_info *ic_info)
{
struct goodix_ic_info_version *version = &ic_info->version;
struct goodix_ic_info_feature *feature = &ic_info->feature;
@@ -974,6 +975,8 @@ static int brl_get_ic_info(
return ret;
}
+ print_ic_info(ic_info);
+
/* check some key info */
if (!ic_info->misc.cmd_addr || !ic_info->misc.fw_buffer_addr ||
!ic_info->misc.touch_data_addr) {
@@ -1016,7 +1019,6 @@ static int brl_esd_check(struct goodix_ts_core *cd)
#define IRQ_EVENT_HEAD_LEN 8
#define BYTES_PER_POINT 14
-#define BYTES_STYLUS_LEN 16
#define COOR_DATA_CHECKSUM_SIZE 2
#define GOODIX_TOUCH_EVENT 0x80
@@ -1026,42 +1028,69 @@ static int brl_esd_check(struct goodix_ts_core *cd)
#define GOODIX_FP_EVENT 0x08
#define POINT_TYPE_STYLUS_HOVER 0x01
#define POINT_TYPE_STYLUS 0x03
-static void goodix_parse_finger(struct goodix_ts_core *cd,
- struct goodix_touch_data *touch_data,
- u8 *buf, int id)
+static int point_struct_len;
+static void goodix_parse_finger(
+ struct goodix_touch_data *touch_data, u8 *buf, int touch_num)
{
- int point_struct_len = cd->ic_info.misc.point_struct_len;
- struct goodix_ts_coords *coord = &touch_data->coords[id]; /* [GOOG] */
-
- coord->status = TS_TOUCH;
- coord->x = le16_to_cpup((__le16 *)(buf + 2));
- coord->y = le16_to_cpup((__le16 *)(buf + 4));
- coord->w = le16_to_cpup((__le16 *)(buf + 6));
- if (point_struct_len > 8) {
- coord->p = buf[8];
- coord->major = le16_to_cpup((__le16 *)(buf + 9));
- coord->minor = le16_to_cpup((__le16 *)(buf + 11));
- coord->angle = (signed char)buf[13];
- }
- touch_data->touch_num += 1;
+ unsigned int id = 0;
+ u8 *coor_data;
+ int i;
+ struct goodix_ts_coords *coord;
+
+ coor_data = &buf[IRQ_EVENT_HEAD_LEN];
+ for (i = 0; i < touch_num; i++) {
+ id = (coor_data[0] >> 4) & 0x0F;
+ if (id >= GOODIX_MAX_TOUCH) {
+ ts_info("invalid finger id =%d", id);
+ touch_data->touch_num = 0;
+ return;
+ }
+ coord = &touch_data->coords[id];
+
+ coord->status = TS_TOUCH;
+ coord->x = le16_to_cpup((__le16 *)(coor_data + 2));
+ coord->y = le16_to_cpup((__le16 *)(coor_data + 4));
+ coord->w = le16_to_cpup((__le16 *)(coor_data + 6));
+
+ if (point_struct_len > 8) {
+ coord->p = coor_data[8];
+ coord->major = le16_to_cpup((__le16 *)(coor_data + 9));
+ coord->minor = le16_to_cpup((__le16 *)(coor_data + 11));
+ coord->angle = (signed char)coor_data[13];
+ }
+
+ coor_data += point_struct_len;
+ }
+ touch_data->touch_num = touch_num;
}
static unsigned int goodix_pen_btn_code[] = { BTN_STYLUS, BTN_STYLUS2 };
static void goodix_parse_pen(
- struct goodix_pen_data *pen_data, u8 *event_head, u8 *buf)
+ struct goodix_pen_data *pen_data, u8 *buf, int touch_num)
{
+ unsigned int id = 0;
u8 cur_key_map = 0;
+ u8 *coor_data;
int16_t x_angle, y_angle;
int i;
- pen_data->coords.status = TS_TOUCH;
- pen_data->coords.x = le16_to_cpup((__le16 *)(buf + 2));
- pen_data->coords.y = le16_to_cpup((__le16 *)(buf + 4));
- pen_data->coords.p = le16_to_cpup((__le16 *)(buf + 6));
- x_angle = le16_to_cpup((__le16 *)(buf + 8));
- y_angle = le16_to_cpup((__le16 *)(buf + 10));
- pen_data->coords.tilt_x = x_angle / 100;
- pen_data->coords.tilt_y = y_angle / 100;
+ pen_data->coords.tool_type = BTN_TOOL_PEN;
+
+ if (touch_num) {
+ pen_data->coords.status = TS_TOUCH;
+ coor_data = &buf[IRQ_EVENT_HEAD_LEN];
+
+ id = (coor_data[0] >> 4) & 0x0F;
+ pen_data->coords.x = le16_to_cpup((__le16 *)(coor_data + 2));
+ pen_data->coords.y = le16_to_cpup((__le16 *)(coor_data + 4));
+ pen_data->coords.p = le16_to_cpup((__le16 *)(coor_data + 6));
+ x_angle = le16_to_cpup((__le16 *)(coor_data + 8));
+ y_angle = le16_to_cpup((__le16 *)(coor_data + 10));
+ pen_data->coords.tilt_x = x_angle / 100;
+ pen_data->coords.tilt_y = y_angle / 100;
+ } else {
+ pen_data->coords.status = TS_RELEASE;
+ }
cur_key_map = (buf[3] & 0x0F) >> 1;
for (i = 0; i < GOODIX_MAX_PEN_KEY; i++) {
@@ -1072,7 +1101,7 @@ static void goodix_parse_pen(
}
}
-static int goodix_update_heatmap(struct goodix_ts_core *cd, u8 *event_data)
+static int goodix_update_heatmap(struct goodix_ts_core *cd, uint8_t *event_data)
{
struct goodix_ic_info_misc *misc = &cd->ic_info.misc;
int tx = cd->ic_info.parm.drv_num;
@@ -1101,90 +1130,113 @@ static int goodix_touch_handler(struct goodix_ts_core *cd,
struct goodix_ic_info_misc *misc = &cd->ic_info.misc;
struct goodix_touch_data *touch_data = &ts_event->touch_data;
struct goodix_pen_data *pen_data = &ts_event->pen_data;
- u8 *data = event_data->data;
- u8 touch_num;
- int checksum_len = 0;
int ret = 0;
- u8 point_type;
- int tid;
- int i;
+ u8 point_type = 0;
+ static u8 pre_finger_num;
+ static u8 pre_pen_num;
- touch_data->touch_num = 0; /* [GOOG] */
- touch_num = event_data->touches;
- if (touch_num > 0) {
- /*
- * [GOOG]
- * Touch Packet: 8 bytes header + data(stylus or finger).
- */
- for (i = 0; i < touch_num; i++) {
- point_type = event_data->type;
- tid = (data[0] >> 4) & 0x0F;
- if (point_type == POINT_TYPE_STYLUS ||
- point_type == POINT_TYPE_STYLUS_HOVER) {
- goodix_parse_pen(pen_data, (u8 *)event_data, data);
- checksum_len += BYTES_STYLUS_LEN;
- data += BYTES_STYLUS_LEN;
- } else {
- /* [GOOG] */
- if (tid >= GOODIX_MAX_TOUCH)
- ts_info("invalid touch#%d id %d", i, tid);
- else
- goodix_parse_finger(cd, touch_data, data, tid);
- checksum_len += misc->point_struct_len;
- data += misc->point_struct_len;
+ if (event_data->touches > GOODIX_MAX_TOUCH) {
+ ts_debug("invalid touch num %d", event_data->touches);
+ return -EINVAL;
+ }
+
+ if (event_data->touches > 0) {
+ point_type = event_data->data[0] & 0x0F;
+ if (point_type == POINT_TYPE_STYLUS ||
+ point_type == POINT_TYPE_STYLUS_HOVER) {
+ ret = checksum_cmp(event_data->data, 16 + 2, CHECKSUM_MODE_U8_LE);
+ if (ret) {
+ ts_debug("touch data checksum error");
+ ts_debug("data:%*ph", 16 + 2, event_data->data);
+ return -EINVAL;
+ }
+ } else {
+ point_struct_len = misc->point_struct_len;
+ ret = checksum_cmp(event_data->data,
+ event_data->touches * point_struct_len + 2,
+ CHECKSUM_MODE_U8_LE);
+ if (ret) {
+ ts_debug("touch data checksum error");
+ ts_debug("data:%*ph",
+ event_data->touches * point_struct_len +
+ 2,
+ event_data->data);
+ return -EINVAL;
}
- }
- ret = checksum_cmp(event_data->data,
- checksum_len + 2,
- CHECKSUM_MODE_U8_LE);
- if (ret) {
- ts_debug("touch data checksum error");
- return -EINVAL;
}
}
- goodix_update_heatmap(cd, event_data->data); /* [GOOG] */
+ goodix_update_heatmap(cd, (u8 *)event_data);
ts_event->fp_flag = event_data->fp_flag;
- ts_event->event_type |= EVENT_TOUCH;
- if (cd->board_data.pen_enable)
- ts_event->event_type |= EVENT_PEN;
+
+ if (event_data->touches > 0 &&
+ (point_type == POINT_TYPE_STYLUS ||
+ point_type == POINT_TYPE_STYLUS_HOVER)) {
+ /* stylus info */
+ if (pre_finger_num) {
+ ts_event->event_type = EVENT_TOUCH;
+ goodix_parse_finger(touch_data, (u8 *)event_data, 0);
+ pre_finger_num = 0;
+ } else {
+ pre_pen_num = 1;
+ ts_event->event_type = EVENT_PEN;
+ goodix_parse_pen(pen_data, (u8 *)event_data,
+ event_data->touches);
+ }
+ } else {
+ /* finger info */
+ if (pre_pen_num) {
+ ts_event->event_type = EVENT_PEN;
+ goodix_parse_pen(pen_data, (u8 *)event_data, 0);
+ pre_pen_num = 0;
+ } else {
+ ts_event->event_type = EVENT_TOUCH;
+ goodix_parse_finger(touch_data, (u8 *)event_data,
+ event_data->touches);
+ pre_finger_num = event_data->touches;
+ }
+ }
+
+ if (event_data->status_changed)
+ ts_event->event_type |= EVENT_STATUS;
+
+ /* process custom info */
+ if (event_data->custom_coor_info_flag)
+ ts_debug("TODO add custom info process function");
return 0;
}
-static int brl_event_handler(struct goodix_ts_core *cd,
- struct goodix_ts_event *ts_event)
+static int brl_event_handler(
+ struct goodix_ts_core *cd, struct goodix_ts_event *ts_event)
{
struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
struct goodix_ic_info_misc *misc = &cd->ic_info.misc;
-/* [GOOG] */
struct goodix_ts_event_data *event_data;
int ret;
- if (!cd->touch_frame_package || !cd->touch_frame_size)
- return -ENOMEM;
-
ret = hw_ops->read_fast(cd, misc->touch_data_addr,
- cd->touch_frame_package, cd->touch_frame_size);
+ cd->touch_frame_package, cd->touch_frame_size);
if (ret) {
ts_debug("failed get event head data");
return ret;
}
- event_data = (struct goodix_ts_event_data *)cd->touch_frame_package->data;
+ event_data =
+ (struct goodix_ts_event_data *)cd->touch_frame_package->data;
if (event_data->type == 0x00) {
ts_debug("invalid touch head");
return -EINVAL;
}
if (checksum_cmp((u8 *)event_data, IRQ_EVENT_HEAD_LEN,
- CHECKSUM_MODE_U8_LE)) {
+ CHECKSUM_MODE_U8_LE)) {
ts_debug("touch head checksum err[%*ph]", IRQ_EVENT_HEAD_LEN,
event_data);
+ hw_ops->after_event_handler(cd);
return -EINVAL;
}
-/*~[GOOG]*/
/* clean event buffer */
memset(ts_event, 0, sizeof(*ts_event));
@@ -1193,32 +1245,9 @@ static int brl_event_handler(struct goodix_ts_core *cd,
ts_event->clear_count1 = event_data->clear_count1;
ts_event->clear_count2 = event_data->clear_count2;
/* read status event */
- if (event_data->status_changed) {
- ts_event->event_type |= EVENT_STATUS;
+ if (event_data->status_changed)
hw_ops->read(cd, 0x1021C, (u8 *)&ts_event->status_data,
sizeof(ts_event->status_data));
- }
-
-/*
- * [GOOG]
- * Use goodix_update_heatmap() to do the heatmap process and
- * move after_event_handler() into goodix_ts_core.c.
- *
- // read done
- hw_ops->after_event_handler(cd);
-
- if (cd->heatmap_buffer) {
- offset = 248 + misc->frame_data_head_len +
- misc->fw_attr_len + misc->fw_log_len + 8;
- memcpy(cd->heatmap_diff, &pre_buf[offset], tx * rx * 2);
- goodix_rotate_abcd2cbad(tx, rx, cd->heatmap_diff);
- offset = 248 + misc->frame_data_head_len +
- misc->fw_attr_len + misc->fw_log_len +
- misc->mutual_struct_len + 10;
- memcpy(cd->heatmap_selfdiff, &pre_buf[offset], (tx + rx) * 2);
- }
- *~[GOOG]
- */
if (event_data->type & (GOODIX_TOUCH_EVENT >> 4))
return goodix_touch_handler(cd, ts_event,
@@ -1227,7 +1256,7 @@ static int brl_event_handler(struct goodix_ts_core *cd,
if (event_data->type & (GOODIX_REQUEST_EVENT >> 4)) {
struct goodix_ts_request_event_data *request =
(struct goodix_ts_request_event_data *)event_data;
- ts_event->event_type |= EVENT_REQUEST;
+ ts_event->event_type = EVENT_REQUEST;
if (request->request_type == BRL_REQUEST_CODE_CONFIG)
ts_event->request_code = REQUEST_TYPE_CONFIG;
else if (request->request_type == BRL_REQUEST_CODE_RESET)
@@ -1263,7 +1292,9 @@ static int brl_event_handler(struct goodix_ts_core *cd,
if (event_data->type & (GOODIX_GESTURE_EVENT >> 4)) {
struct goodix_ts_gesture_event_data *gesture =
(struct goodix_ts_gesture_event_data *)event_data;
- ts_event->event_type |= EVENT_GESTURE;
+ ts_event->event_type = EVENT_GESTURE;
+ if (event_data->status_changed)
+ ts_event->event_type |= EVENT_STATUS;
ts_event->gesture_data.gesture_type = gesture->gesture_type;
ts_event->gesture_data.touches = gesture->touches;
memcpy(ts_event->gesture_data.data, gesture->data,
@@ -1363,7 +1394,7 @@ static int brld_get_cap_data(
/* disable irq & close esd */
brl_irq_enable(cd, false);
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
info->buff[0] = rx;
info->buff[1] = tx;
@@ -1410,7 +1441,7 @@ exit:
brl_send_cmd(cd, &temp_cmd);
/* enable irq & esd */
brl_irq_enable(cd, true);
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
return ret;
}
@@ -1441,7 +1472,7 @@ static int brl_get_capacitance_data(
/* disable irq & close esd */
brl_irq_enable(cd, false);
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
/* switch rawdata mode */
temp_cmd.cmd = GOODIX_CMD_RAWDATA;
@@ -1504,7 +1535,7 @@ exit:
brl_write(cd, flag_addr, &val, 1);
/* enable irq & esd */
brl_irq_enable(cd, true);
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
return ret;
}
diff --git a/goodix_brl_i2c.c b/goodix_brl_i2c.c
index b1409f2..60018a6 100644
--- a/goodix_brl_i2c.c
+++ b/goodix_brl_i2c.c
@@ -25,6 +25,8 @@
#define GOODIX_BUS_RETRY_TIMES 2
#define GOODIX_REG_ADDR_SIZE 4
+static struct platform_device *goodix_pdev;
+struct goodix_bus_interface goodix_i2c_bus;
static int goodix_i2c_read(struct device *dev, unsigned int reg,
unsigned char *data, unsigned int len)
@@ -154,10 +156,15 @@ write_exit:
return r;
}
+static void goodix_pdev_release(struct device *dev)
+{
+ ts_info("goodix pdev released");
+ kfree(goodix_pdev);
+}
+
static int goodix_i2c_probe(
struct i2c_client *client, const struct i2c_device_id *dev_id)
{
- struct goodix_device_resource *dev_res;
int ret = 0;
ts_info("goodix i2c probe in");
@@ -165,45 +172,52 @@ static int goodix_i2c_probe(
if (!ret)
return -EIO;
- dev_res = kzalloc(sizeof(*dev_res), GFP_KERNEL);
- if (!dev_res)
- return -ENOMEM;
- goodix_device_register(dev_res);
-
/* get ic type */
- ret = goodix_get_ic_type(client->dev.of_node, &dev_res->bus);
+ ret = goodix_get_ic_type(client->dev.of_node, &goodix_i2c_bus);
if (ret < 0)
return ret;
- dev_res->bus.bus_type = GOODIX_BUS_TYPE_I2C;
- dev_res->bus.dev = &client->dev;
- dev_res->bus.read = goodix_i2c_read;
- dev_res->bus.write = goodix_i2c_write;
+ goodix_i2c_bus.bus_type = GOODIX_BUS_TYPE_I2C;
+ goodix_i2c_bus.dev = &client->dev;
+ goodix_i2c_bus.read = goodix_i2c_read;
+ goodix_i2c_bus.write = goodix_i2c_write;
+ /* ts core device */
+ goodix_pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+ if (!goodix_pdev)
+ return -ENOMEM;
- dev_res->pdev.name = GOODIX_CORE_DRIVER_NAME;
- dev_res->pdev.id = dev_res->id;
- dev_res->pdev.num_resources = 0;
+ goodix_pdev->name = GOODIX_CORE_DRIVER_NAME;
+ goodix_pdev->id = 0;
+ goodix_pdev->num_resources = 0;
+ /*
+ * you can find this platform dev in
+ * /sys/devices/platform/goodix_ts.0
+ * goodix_pdev->dev.parent = &client->dev;
+ */
+ goodix_pdev->dev.platform_data = &goodix_i2c_bus;
+ goodix_pdev->dev.release = goodix_pdev_release;
/* register platform device, then the goodix_ts_core
* module will probe the touch device.
*/
- ret = platform_device_register(&dev_res->pdev);
+ ret = platform_device_register(goodix_pdev);
if (ret) {
ts_err("failed register goodix platform device, %d", ret);
goto err_pdev;
}
ts_info("i2c probe out");
- return 0;
+ return ret;
err_pdev:
- kfree(dev_res);
+ kfree(goodix_pdev);
+ goodix_pdev = NULL;
ts_info("i2c probe out, %d", ret);
return ret;
}
static int goodix_i2c_remove(struct i2c_client *client)
{
- // platform_device_unregister(goodix_pdev);
+ platform_device_unregister(goodix_pdev);
return 0;
}
diff --git a/goodix_brl_spi.c b/goodix_brl_spi.c
index e3421b9..b7d82da 100644
--- a/goodix_brl_spi.c
+++ b/goodix_brl_spi.c
@@ -36,6 +36,9 @@
#define SPI_WRITE_FLAG 0xF0
#define SPI_READ_FLAG 0xF1
+static struct platform_device *goodix_pdev;
+struct goodix_bus_interface goodix_spi_bus;
+
/**
* goodix_spi_read_bra- read device register through spi bus
* @dev: pointer to device data
@@ -48,8 +51,6 @@ static int goodix_spi_read_bra(struct device *dev, unsigned int addr,
unsigned char *data, unsigned int len)
{
struct spi_device *spi = to_spi_device(dev);
- struct goodix_ts_core *cd = dev_get_drvdata(dev);
- struct goodix_bus_interface *bus = cd->bus;
u8 *rx_buf = NULL;
u8 *tx_buf = NULL;
struct spi_transfer xfers;
@@ -57,12 +58,12 @@ static int goodix_spi_read_bra(struct device *dev, unsigned int addr,
int ret = 0;
int buf_len = SPI_READ_PREFIX_LEN + len;
- mutex_lock(&bus->mutex);
+ mutex_lock(&goodix_spi_bus.mutex);
if (buf_len <= SPI_PREALLOC_RX_BUF_SIZE &&
buf_len <= SPI_PREALLOC_TX_BUF_SIZE) {
- rx_buf = bus->rx_buf;
- tx_buf = bus->tx_buf;
+ rx_buf = goodix_spi_bus.rx_buf;
+ tx_buf = goodix_spi_bus.tx_buf;
memset(tx_buf, 0, buf_len);
} else {
rx_buf = kzalloc(buf_len, GFP_KERNEL);
@@ -107,13 +108,13 @@ static int goodix_spi_read_bra(struct device *dev, unsigned int addr,
memcpy(data, &rx_buf[SPI_READ_PREFIX_LEN], len);
err_spi_transfer:
- if (tx_buf != bus->tx_buf)
+ if (tx_buf != goodix_spi_bus.tx_buf)
kfree(tx_buf);
err_alloc_tx_buf:
- if (rx_buf != bus->rx_buf)
+ if (rx_buf != goodix_spi_bus.rx_buf)
kfree(rx_buf);
err_alloc_rx_buf:
- mutex_unlock(&bus->mutex);
+ mutex_unlock(&goodix_spi_bus.mutex);
return ret;
}
@@ -121,8 +122,6 @@ static int goodix_spi_read(struct device *dev, unsigned int addr,
unsigned char *data, unsigned int len)
{
struct spi_device *spi = to_spi_device(dev);
- struct goodix_ts_core *cd = dev_get_drvdata(dev);
- struct goodix_bus_interface *bus = cd->bus;
u8 *rx_buf = NULL;
u8 *tx_buf = NULL;
struct spi_transfer xfers;
@@ -130,15 +129,16 @@ static int goodix_spi_read(struct device *dev, unsigned int addr,
int ret = 0;
int buf_len = SPI_READ_PREFIX_LEN - 1 + len;
- if (bus->dma_mode_enabled && buf_len >= 64)
+ if (goodix_spi_bus.dma_mode_enabled && buf_len >= 64) {
buf_len = ALIGN(buf_len, 4);
+ }
- mutex_lock(&bus->mutex);
+ mutex_lock(&goodix_spi_bus.mutex);
if (buf_len <= SPI_PREALLOC_RX_BUF_SIZE &&
buf_len <= SPI_PREALLOC_TX_BUF_SIZE) {
- rx_buf = bus->rx_buf;
- tx_buf = bus->tx_buf;
+ rx_buf = goodix_spi_bus.rx_buf;
+ tx_buf = goodix_spi_bus.tx_buf;
memset(tx_buf, 0, buf_len);
} else {
rx_buf = kzalloc(buf_len, GFP_KERNEL);
@@ -173,8 +173,7 @@ static int goodix_spi_read(struct device *dev, unsigned int addr,
xfers.rx_buf = rx_buf;
xfers.len = buf_len;
xfers.cs_change = 0;
- if (bus->dma_mode_enabled)
- xfers.bits_per_word = buf_len >= 64 ? 32 : 8;
+ if (goodix_spi_bus.dma_mode_enabled) xfers.bits_per_word = buf_len >= 64 ? 32 : 8;
spi_message_add_tail(&xfers, &spi_msg);
ret = spi_sync(spi, &spi_msg);
if (ret < 0) {
@@ -184,37 +183,32 @@ static int goodix_spi_read(struct device *dev, unsigned int addr,
memcpy(data, &rx_buf[SPI_READ_PREFIX_LEN - 1], len);
err_spi_transfer:
- if (tx_buf != bus->tx_buf)
+ if (tx_buf != goodix_spi_bus.tx_buf)
kfree(tx_buf);
err_alloc_tx_buf:
- if (rx_buf != bus->rx_buf)
+ if (rx_buf != goodix_spi_bus.rx_buf)
kfree(rx_buf);
err_alloc_rx_buf:
- mutex_unlock(&bus->mutex);
+ mutex_unlock(&goodix_spi_bus.mutex);
return ret;
}
-/* [GOOG]
- * This SPI transaction will direct read into `struct goodix_rx_package`.
- * And, the package are comprised of `SPI prefix header` + `data`.
- */
static int goodix_spi_read_fast(struct device *dev, unsigned int addr,
struct goodix_rx_package *package, unsigned int len)
{
struct spi_device *spi = to_spi_device(dev);
- struct goodix_ts_core *cd = dev_get_drvdata(dev);
- struct goodix_bus_interface *bus = cd->bus;
u8 *tx_buf = NULL;
struct spi_transfer xfers;
struct spi_message spi_msg;
int ret = 0;
int buf_len = SPI_READ_PREFIX_LEN - 1 + len;
- if (bus->dma_mode_enabled && buf_len >= 64)
+ if (goodix_spi_bus.dma_mode_enabled && buf_len >= 64) {
buf_len = ALIGN(buf_len, 4);
+ }
if (buf_len <= SPI_PREALLOC_TX_BUF_SIZE) {
- tx_buf = bus->tx_buf;
+ tx_buf = goodix_spi_bus.tx_buf;
} else {
tx_buf = kzalloc(buf_len, GFP_KERNEL);
if (!tx_buf) {
@@ -226,7 +220,7 @@ static int goodix_spi_read_fast(struct device *dev, unsigned int addr,
spi_message_init(&spi_msg);
memset(&xfers, 0, sizeof(xfers));
- mutex_lock(&bus->mutex);
+ mutex_lock(&goodix_spi_bus.mutex);
/*spi_read tx_buf format: 0xF1 + addr(4bytes) + data*/
tx_buf[0] = SPI_READ_FLAG;
@@ -242,13 +236,12 @@ static int goodix_spi_read_fast(struct device *dev, unsigned int addr,
xfers.rx_buf = package->header;
xfers.len = buf_len;
xfers.cs_change = 0;
- if (bus->dma_mode_enabled)
- xfers.bits_per_word = buf_len >= 64 ? 32 : 8;
+ if (goodix_spi_bus.dma_mode_enabled) xfers.bits_per_word = buf_len >= 64 ? 32 : 8;
spi_message_add_tail(&xfers, &spi_msg);
ret = spi_sync(spi, &spi_msg);
- mutex_unlock(&bus->mutex);
+ mutex_unlock(&goodix_spi_bus.mutex);
if (ret < 0) {
ts_err("spi transfer error:%d", ret);
@@ -256,7 +249,7 @@ static int goodix_spi_read_fast(struct device *dev, unsigned int addr,
}
err_spi_transfer:
- if (tx_buf != bus->tx_buf)
+ if (tx_buf != goodix_spi_bus.tx_buf)
kfree(tx_buf);
return ret;
}
@@ -273,19 +266,18 @@ static int goodix_spi_write(struct device *dev, unsigned int addr,
unsigned char *data, unsigned int len)
{
struct spi_device *spi = to_spi_device(dev);
- struct goodix_ts_core *cd = dev_get_drvdata(dev);
- struct goodix_bus_interface *bus = cd->bus;
u8 *tx_buf = NULL;
struct spi_transfer xfers;
struct spi_message spi_msg;
int ret = 0;
int buf_len = SPI_WRITE_PREFIX_LEN + len;
- if (bus->dma_mode_enabled && buf_len >= 64)
+ if (goodix_spi_bus.dma_mode_enabled && buf_len >= 64) {
buf_len = ALIGN(buf_len, 4);
+ }
if (buf_len <= SPI_PREALLOC_TX_BUF_SIZE) {
- tx_buf = bus->tx_buf;
+ tx_buf = goodix_spi_bus.tx_buf;
} else {
tx_buf = kzalloc(buf_len, GFP_KERNEL);
if (!tx_buf) {
@@ -297,7 +289,7 @@ static int goodix_spi_write(struct device *dev, unsigned int addr,
spi_message_init(&spi_msg);
memset(&xfers, 0, sizeof(xfers));
- mutex_lock(&bus->mutex);
+ mutex_lock(&goodix_spi_bus.mutex);
tx_buf[0] = SPI_WRITE_FLAG;
tx_buf[1] = (addr >> 24) & 0xFF;
@@ -308,24 +300,28 @@ static int goodix_spi_write(struct device *dev, unsigned int addr,
xfers.tx_buf = tx_buf;
xfers.len = buf_len;
xfers.cs_change = 0;
- if (bus->dma_mode_enabled)
- xfers.bits_per_word = buf_len >= 64 ? 32 : 8;
+ if (goodix_spi_bus.dma_mode_enabled) xfers.bits_per_word = buf_len >= 64 ? 32 : 8;
spi_message_add_tail(&xfers, &spi_msg);
ret = spi_sync(spi, &spi_msg);
- mutex_unlock(&bus->mutex);
+ mutex_unlock(&goodix_spi_bus.mutex);
if (ret < 0)
ts_err("spi transfer error:%d", ret);
- if (tx_buf != bus->tx_buf)
+ if (tx_buf != goodix_spi_bus.tx_buf)
kfree(tx_buf);
return ret;
}
+static void goodix_pdev_release(struct device *dev)
+{
+ ts_info("goodix pdev released");
+ kfree(goodix_pdev);
+}
+
static int goodix_spi_probe(struct spi_device *spi)
{
- struct goodix_device_resource *dev_res;
int ret = 0;
ts_info("goodix spi probe in");
@@ -333,7 +329,7 @@ static int goodix_spi_probe(struct spi_device *spi)
/* init spi_device */
spi->mode = SPI_MODE_0;
spi->bits_per_word = 8;
- spi->rt = true; /* [GOOG] */
+ spi->rt = true;
ret = spi_setup(spi);
if (ret) {
@@ -341,71 +337,83 @@ static int goodix_spi_probe(struct spi_device *spi)
return ret;
}
- dev_res = kzalloc(sizeof(*dev_res), GFP_KERNEL);
- if (!dev_res)
- return -ENOMEM;
- goodix_device_register(dev_res);
-
/* get ic type */
- ret = goodix_get_ic_type(spi->dev.of_node, &dev_res->bus);
+ ret = goodix_get_ic_type(spi->dev.of_node, &goodix_spi_bus);
if (ret < 0)
- goto err_get_ic_type;
+ return ret;
- dev_res->bus.bus_type = GOODIX_BUS_TYPE_SPI;
- dev_res->bus.dev = &spi->dev;
- if (dev_res->bus.ic_type == IC_TYPE_BERLIN_A) {
- dev_res->bus.read = goodix_spi_read_bra;
+ goodix_spi_bus.bus_type = GOODIX_BUS_TYPE_SPI;
+ goodix_spi_bus.dev = &spi->dev;
+ if (goodix_spi_bus.ic_type == IC_TYPE_BERLIN_A) {
+ goodix_spi_bus.read = goodix_spi_read_bra;
} else {
- dev_res->bus.read = goodix_spi_read;
- dev_res->bus.read_fast = goodix_spi_read_fast;
+ goodix_spi_bus.read = goodix_spi_read;
+ goodix_spi_bus.read_fast = goodix_spi_read_fast;
}
- dev_res->bus.write = goodix_spi_write;
+ goodix_spi_bus.write = goodix_spi_write;
+ goodix_spi_bus.rx_buf = kzalloc(SPI_PREALLOC_RX_BUF_SIZE, GFP_KERNEL);
+ if (!goodix_spi_bus.rx_buf) {
+ return -ENOMEM;
+ }
- /* [GOOG] */
- dev_res->bus.rx_buf = kzalloc(SPI_PREALLOC_RX_BUF_SIZE, GFP_KERNEL);
- dev_res->bus.tx_buf = kzalloc(SPI_PREALLOC_TX_BUF_SIZE, GFP_KERNEL);
- if (!dev_res->bus.rx_buf || !dev_res->bus.tx_buf) {
+ goodix_spi_bus.tx_buf = kzalloc(SPI_PREALLOC_TX_BUF_SIZE, GFP_KERNEL);
+ if (!goodix_spi_bus.tx_buf) {
ret = -ENOMEM;
- goto err_pdev;
+ goto err_alloc_tx_buf;
}
- mutex_init(&dev_res->bus.mutex);
- dev_res->bus.dma_mode_enabled = false;
+ mutex_init(&goodix_spi_bus.mutex);
+
+ goodix_spi_bus.dma_mode_enabled = false;
#ifdef CONFIG_GOOG_TOUCH_INTERFACE
- dev_res->bus.dma_mode_enabled = goog_check_spi_dma_enabled(spi);
- ts_info("dma_mode: %s\n", dev_res->bus.dma_mode_enabled ? "enabled" : "disabled");
+ goodix_spi_bus.dma_mode_enabled = goog_check_spi_dma_enabled(spi);
+ ts_info("dma_mode: %s\n", goodix_spi_bus.dma_mode_enabled ? "enabled" : "disabled");
#endif
- // platform device init
- dev_res->pdev.name = GOODIX_CORE_DRIVER_NAME;
- dev_res->pdev.id = dev_res->id;
- dev_res->pdev.num_resources = 0;
+ /* ts core device */
+ goodix_pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+ if (!goodix_pdev) {
+ ret = -ENOMEM;
+ goto err_alloc_pdev;
+ }
+
+ goodix_pdev->name = GOODIX_CORE_DRIVER_NAME;
+ goodix_pdev->id = 0;
+ goodix_pdev->num_resources = 0;
+ /*
+ * you can find this platform dev in
+ * /sys/devices/platform/goodix_ts.0
+ * goodix_pdev->dev.parent = &client->dev;
+ */
+ goodix_pdev->dev.platform_data = &goodix_spi_bus;
+ goodix_pdev->dev.release = goodix_pdev_release;
/* register platform device, then the goodix_ts_core
* module will probe the touch device.
*/
- ret = platform_device_register(&dev_res->pdev);
+ ret = platform_device_register(goodix_pdev);
if (ret) {
ts_err("failed register goodix platform device, %d", ret);
- goto err_pdev;
+ goto err_register_platform_device;
}
ts_info("spi probe out");
return 0;
-err_pdev:
- kfree(dev_res->bus.rx_buf);
- kfree(dev_res->bus.tx_buf);
-err_get_ic_type:
- kfree(dev_res);
+err_register_platform_device:
+ kfree(goodix_pdev);
+err_alloc_pdev:
+ kfree(goodix_spi_bus.tx_buf);
+err_alloc_tx_buf:
+ kfree(goodix_spi_bus.rx_buf);
+
ts_info("spi probe out, %d", ret);
return ret;
}
static int goodix_spi_remove(struct spi_device *spi)
{
- /* goodix_ts_core_exit() will unregister device(s) */
- // platform_device_unregister(dev_res->pdev);
+ platform_device_unregister(goodix_pdev);
return 0;
}
diff --git a/goodix_cfg_bin.c b/goodix_cfg_bin.c
index ab24e6a..f7fef30 100644
--- a/goodix_cfg_bin.c
+++ b/goodix_cfg_bin.c
@@ -114,7 +114,7 @@ static int goodix_read_cfg_bin(struct device *dev, const char *cfg_name,
if (!ret)
break;
ts_info("get cfg bin retry:[%d]", GOODIX_RETRY_3 - retry);
- msleep(300);
+ msleep(200);
}
if (retry < 0) {
ts_err("failed get cfg bin[%s] error:%d", cfg_name, ret);
diff --git a/goodix_ts_core.c b/goodix_ts_core.c
index 20c317d..120c4f5 100644
--- a/goodix_ts_core.c
+++ b/goodix_ts_core.c
@@ -31,60 +31,257 @@
// #include "../../../video/fbdev/core/fb_firefly.h"
#define GOODIX_DEFAULT_CFG_NAME "goodix_cfg_group.cfg"
+#define GOOIDX_INPUT_PHYS "goodix_ts/input0"
-struct goodix_device_manager goodix_devices;
+struct goodix_module goodix_modules;
+int core_module_prob_sate = CORE_MODULE_UNPROBED;
-static const struct dev_pm_ops dev_pm_ops; /* [GOOG] */
+static const struct dev_pm_ops dev_pm_ops;
-static void goodix_device_manager_init(void)
+static int goodix_send_ic_config(struct goodix_ts_core *cd, int type);
+/**
+ * __do_register_ext_module - register external module
+ * to register into touch core modules structure
+ * return 0 on success, otherwise return < 0
+ */
+static int __do_register_ext_module(struct goodix_ext_module *module)
{
- if (goodix_devices.initialized)
+ struct goodix_ext_module *ext_module, *next;
+ struct list_head *insert_point = &goodix_modules.head;
+
+ /* prority level *must* be set */
+ if (module->priority == EXTMOD_PRIO_RESERVED) {
+ ts_err("Priority of module [%s] needs to be set", module->name);
+ return -EINVAL;
+ }
+ mutex_lock(&goodix_modules.mutex);
+ /* find insert point for the specified priority */
+ if (!list_empty(&goodix_modules.head)) {
+ list_for_each_entry_safe(
+ ext_module, next, &goodix_modules.head, list)
+ {
+ if (ext_module == module) {
+ ts_info("Module [%s] already exists",
+ module->name);
+ mutex_unlock(&goodix_modules.mutex);
+ return 0;
+ }
+ }
+
+ /* smaller priority value with higher priority level */
+ list_for_each_entry_safe(
+ ext_module, next, &goodix_modules.head, list)
+ {
+ if (ext_module->priority >= module->priority) {
+ insert_point = &ext_module->list;
+ break;
+ }
+ }
+ }
+
+ if (module->funcs && module->funcs->init) {
+ if (module->funcs->init(goodix_modules.core_data, module) < 0) {
+ ts_err("Module [%s] init error",
+ module->name ? module->name : " ");
+ mutex_unlock(&goodix_modules.mutex);
+ return -EFAULT;
+ }
+ }
+
+ list_add(&module->list, insert_point->prev);
+ mutex_unlock(&goodix_modules.mutex);
+
+ return 0;
+}
+
+static void goodix_register_ext_module_work(struct work_struct *work)
+{
+ struct goodix_ext_module *module =
+ container_of(work, struct goodix_ext_module, work);
+
+ ts_info("module register work IN");
+
+ /* driver probe failed */
+ if (core_module_prob_sate != CORE_MODULE_PROB_SUCCESS) {
+ ts_err("Can't register ext_module core error");
return;
- goodix_devices.initialized = true;
- INIT_LIST_HEAD(&goodix_devices.list);
- mutex_init(&goodix_devices.mutex);
+ }
+
+ if (__do_register_ext_module(module))
+ ts_err("failed register module: %s", module->name);
+ else
+ ts_info("success register module: %s", module->name);
}
-static void goodix_device_manager_exit(void)
+static void goodix_core_module_init(void)
{
- struct goodix_device_resource *res, *next;
+ if (goodix_modules.initialized)
+ return;
+ goodix_modules.initialized = true;
+ INIT_LIST_HEAD(&goodix_modules.head);
+ mutex_init(&goodix_modules.mutex);
+}
- if (!list_empty(&goodix_devices.list)) {
- list_for_each_entry_safe(res, next, &goodix_devices.list, list) {
- platform_device_unregister(&res->pdev);
- kfree(res);
- }
+/**
+ * goodix_register_ext_module - interface for register external module
+ * to the core. This will create a workqueue to finish the real register
+ * work and return immediately. The user need to check the final result
+ * to make sure registe is success or fail.
+ *
+ * @module: pointer to external module to be register
+ * return: 0 ok, <0 failed
+ */
+int goodix_register_ext_module(struct goodix_ext_module *module)
+{
+ if (!module)
+ return -EINVAL;
+
+ ts_info("IN");
+
+ goodix_core_module_init();
+ INIT_WORK(&module->work, goodix_register_ext_module_work);
+ schedule_work(&module->work);
+
+ ts_info("OUT");
+ return 0;
+}
+
+/**
+ * goodix_register_ext_module_no_wait
+ * return: 0 ok, <0 failed
+ */
+int goodix_register_ext_module_no_wait(struct goodix_ext_module *module)
+{
+ if (!module)
+ return -EINVAL;
+
+ ts_info("IN");
+ goodix_core_module_init();
+ /* driver probe failed */
+ if (core_module_prob_sate != CORE_MODULE_PROB_SUCCESS) {
+ ts_err("Can't register ext_module core error");
+ return -EINVAL;
}
+ return __do_register_ext_module(module);
}
-int goodix_device_register(struct goodix_device_resource *device)
+/**
+ * goodix_unregister_ext_module - interface for external module
+ * to unregister external modules
+ *
+ * @module: pointer to external module
+ * return: 0 ok, <0 failed
+ */
+int goodix_unregister_ext_module(struct goodix_ext_module *module)
{
- if (!device)
- return -ENXIO;
+ struct goodix_ext_module *ext_module, *next;
+ bool found = false;
+
+ if (!module)
+ return -EINVAL;
- mutex_lock(&goodix_devices.mutex);
- list_add(&device->list, &goodix_devices.list);
- device->id = goodix_devices.nums++;
- sprintf(device->name, "%s.%d", GOODIX_CORE_DRIVER_NAME, device->id);
- mutex_unlock(&goodix_devices.mutex);
- ts_info("register device %s", device->name);
+ if (!goodix_modules.initialized)
+ return -EINVAL;
+
+ if (!goodix_modules.core_data)
+ return -ENODEV;
+ mutex_lock(&goodix_modules.mutex);
+ if (!list_empty(&goodix_modules.head)) {
+ list_for_each_entry_safe(
+ ext_module, next, &goodix_modules.head, list)
+ {
+ if (ext_module == module) {
+ found = true;
+ break;
+ }
+ }
+ } else {
+ mutex_unlock(&goodix_modules.mutex);
+ return 0;
+ }
+
+ if (!found) {
+ ts_debug("Module [%s] never registed", module->name);
+ mutex_unlock(&goodix_modules.mutex);
+ return 0;
+ }
+
+ list_del(&module->list);
+ mutex_unlock(&goodix_modules.mutex);
+
+ if (module->funcs && module->funcs->exit)
+ module->funcs->exit(goodix_modules.core_data, module);
+
+ ts_info("Module [%s] unregistered", module->name ? module->name : " ");
return 0;
}
-static int goodix_send_ic_config(struct goodix_ts_core *cd, int type);
+static void goodix_ext_sysfs_release(struct kobject *kobj)
+{
+ ts_info("Kobject released!");
+}
+
+#define to_ext_module(kobj) container_of(kobj, struct goodix_ext_module, kobj)
+#define to_ext_attr(attr) container_of(attr, struct goodix_ext_attribute, attr)
+
+static ssize_t goodix_ext_sysfs_show(
+ struct kobject *kobj, struct attribute *attr, char *buf)
+{
+ struct goodix_ext_module *module = to_ext_module(kobj);
+ struct goodix_ext_attribute *ext_attr = to_ext_attr(attr);
+
+ if (ext_attr->show)
+ return ext_attr->show(module, buf);
+
+ return -EIO;
+}
+
+static ssize_t goodix_ext_sysfs_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t count)
+{
+ struct goodix_ext_module *module = to_ext_module(kobj);
+ struct goodix_ext_attribute *ext_attr = to_ext_attr(attr);
+
+ if (ext_attr->store)
+ return ext_attr->store(module, buf, count);
+
+ return -EIO;
+}
+
+static const struct sysfs_ops goodix_ext_ops = { .show = goodix_ext_sysfs_show,
+ .store = goodix_ext_sysfs_store };
+
+static struct kobj_type goodix_ext_ktype = {
+ .release = goodix_ext_sysfs_release,
+ .sysfs_ops = &goodix_ext_ops,
+};
+
+struct kobj_type *goodix_get_default_ktype(void)
+{
+ return &goodix_ext_ktype;
+}
+
+struct kobject *goodix_get_default_kobj(void)
+{
+ struct kobject *kobj = NULL;
+
+ if (goodix_modules.core_data && goodix_modules.core_data->pdev)
+ kobj = &goodix_modules.core_data->pdev->dev.kobj;
+ return kobj;
+}
/* show driver information */
-static ssize_t driver_info_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t driver_info_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "DriverVersion:%s\n",
- GOODIX_DRIVER_VERSION);
+ return snprintf(
+ buf, PAGE_SIZE, "DriverVersion:%s\n", GOODIX_DRIVER_VERSION);
}
/* show chip infoamtion */
-static ssize_t chip_info_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t chip_info_show(
+ struct device *dev, struct device_attribute *attr, char *buf)
{
struct goodix_ts_core *cd = dev_get_drvdata(dev);
struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
@@ -473,15 +670,13 @@ static ssize_t goodix_ts_esd_info_show(
static ssize_t goodix_ts_esd_info_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct goodix_ts_core *cd = dev_get_drvdata(dev);
-
if (!buf || count <= 0)
return -EINVAL;
if (buf[0] != '0')
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
else
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
return count;
}
@@ -511,19 +706,35 @@ static ssize_t goodix_ts_debug_log_store(struct device *dev,
return count;
}
+#define GOODIX_MAX_PEN_FREQ_DATA_LEN 16
+#define GOODIX_HOGP_INFO_LEN 3
+
+#pragma pack(1)
+struct goodix_hid_hogp {
+ u16 pressure;
+ u8 key;
+};
+#pragma pack()
+
+struct goodix_ble_data {
+ u8 freq[GOODIX_MAX_PEN_FREQ_DATA_LEN];
+ u8 hogp[GOODIX_HOGP_INFO_LEN];
+ int hogp_ready;
+ int freq_ready;
+ struct mutex lock;
+} goodix_ble_data;
+
int goodix_update_pen_freq(struct goodix_ts_core *cd, u8 *data, int len)
{
- struct goodix_ble_data *ble_data = &cd->ble_data;
-
- if (len > sizeof(ble_data->freq)) {
+ if (len > sizeof(goodix_ble_data.freq)) {
ts_err("pen freq data exceed limit");
return -EINVAL;
}
- mutex_lock(&ble_data->lock);
- memset(ble_data->freq, 0, sizeof(ble_data->freq));
- memcpy(ble_data->freq, data, len);
- ble_data->freq_ready = 1;
- mutex_unlock(&ble_data->lock);
+ mutex_lock(&goodix_ble_data.lock);
+ memset(goodix_ble_data.freq, 0, sizeof(goodix_ble_data.freq));
+ memcpy(goodix_ble_data.freq, data, len);
+ goodix_ble_data.freq_ready = 1;
+ mutex_unlock(&goodix_ble_data.lock);
sysfs_notify(&cd->pdev->dev.kobj, NULL, "pen_freq");
ts_debug("send pen freq hop event");
return 0;
@@ -533,14 +744,11 @@ int goodix_update_pen_freq(struct goodix_ts_core *cd, u8 *data, int len)
static ssize_t goodix_ts_pen_freq_show(
struct device *dev, struct device_attribute *attr, char *buf)
{
- struct goodix_ts_core *core_data = dev_get_drvdata(dev);
- struct goodix_ble_data *ble_data = &core_data->ble_data;
-
- mutex_lock(&ble_data->lock);
- memcpy(buf, ble_data->freq, sizeof(ble_data->freq));
- ble_data->freq_ready = 0;
- mutex_unlock(&ble_data->lock);
- return sizeof(ble_data->freq);
+ mutex_lock(&goodix_ble_data.lock);
+ memcpy(buf, goodix_ble_data.freq, sizeof(goodix_ble_data.freq));
+ goodix_ble_data.freq_ready = 0;
+ mutex_unlock(&goodix_ble_data.lock);
+ return sizeof(goodix_ble_data.freq);
}
/* debug level store */
@@ -549,13 +757,12 @@ static ssize_t goodix_ts_pen_debug_store(struct device *dev,
{
int pen_freq;
struct goodix_ts_core *core_data = dev_get_drvdata(dev);
- struct goodix_ble_data *ble_data = &core_data->ble_data;
sscanf(buf, "%d", &pen_freq);
ts_debug("set new pen_freq %d", pen_freq);
- ble_data->freq[0] = 0xC0;
- ble_data->freq[1] = 1;
- ble_data->freq[2] = pen_freq & 0xFF;
+ goodix_ble_data.freq[0] = 0xC0;
+ goodix_ble_data.freq[1] = 1;
+ goodix_ble_data.freq[2] = pen_freq & 0xFF;
sysfs_notify(&core_data->pdev->dev.kobj, NULL, "pen_freq");
return count;
@@ -565,20 +772,18 @@ static ssize_t goodix_ts_pen_hogp_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct goodix_hid_hogp *tmp_prs;
- struct goodix_ts_core *core_data = dev_get_drvdata(dev);
- struct goodix_ble_data *ble_data = &core_data->ble_data;
- if (count < sizeof(ble_data->hogp)) {
+ if (count < sizeof(goodix_ble_data.hogp)) {
ts_err("data count to short");
return -EINVAL;
}
- mutex_lock(&ble_data->lock);
- memcpy(ble_data->hogp, buf, sizeof(ble_data->hogp));
- ble_data->hogp_ready = 1;
- mutex_unlock(&ble_data->lock);
+ mutex_lock(&goodix_ble_data.lock);
+ memcpy(goodix_ble_data.hogp, buf, sizeof(goodix_ble_data.hogp));
+ goodix_ble_data.hogp_ready = 1;
+ mutex_unlock(&goodix_ble_data.lock);
- tmp_prs = (struct goodix_hid_hogp *)ble_data->hogp;
+ tmp_prs = (struct goodix_hid_hogp *)goodix_ble_data.hogp;
ts_debug("set ble pen data: %d, key %x", tmp_prs->pressure,
tmp_prs->key);
return count;
@@ -636,7 +841,6 @@ static void goodix_ts_sysfs_exit(struct goodix_ts_core *core_data)
sysfs_remove_group(&core_data->pdev->dev.kobj, &sysfs_group);
}
-/* [GOOG] */
#if IS_ENABLED(CONFIG_TOUCHSCREEN_MOTION_FILTER)
int set_continuously_report_enabled(struct device *dev, bool enabled)
{
@@ -703,10 +907,10 @@ int set_sensing_enabled(struct device *dev, bool enabled)
if (enabled) {
cd->hw_ops->resume(cd);
cd->hw_ops->irq_enable(cd, true);
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
ts_info("set sense ON");
} else {
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
cd->hw_ops->irq_enable(cd, false);
cd->hw_ops->suspend(cd);
ts_info("set sense OFF");
@@ -765,8 +969,8 @@ static int get_mutual_sensor_data(
cmd->buffer = (u8 *)cd->mutual_data;
cmd->size = tx * rx * sizeof(uint16_t);
} else {
- /* disable esd */
- goodix_ts_esd_off(cd);
+ /* close esd */
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
ret = -EINVAL;
if (cmd->type == GTI_SENSOR_DATA_TYPE_MS_DIFF) {
@@ -781,8 +985,9 @@ static int get_mutual_sensor_data(
cmd->buffer = (u8 *)cd->mutual_data_manual;
cmd->size = tx * rx * sizeof(uint16_t);
}
+
/* enable esd */
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
}
return ret;
}
@@ -801,7 +1006,7 @@ static int get_self_sensor_data(
} else {
/* disable irq & close esd */
cd->hw_ops->irq_enable(cd, false);
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
ret = -EINVAL;
if (cmd->type == GTI_SENSOR_DATA_TYPE_SS_DIFF) {
@@ -819,7 +1024,7 @@ static int get_self_sensor_data(
/* enable irq & esd */
cd->hw_ops->irq_enable(cd, true);
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
}
return ret;
}
@@ -983,10 +1188,8 @@ static int gti_ping(void *private_data, struct gti_ping_cmd *cmd)
static int gti_selftest(void *private_data, struct gti_selftest_cmd *cmd)
{
- struct goodix_ts_core *cd = private_data;
-
cmd->result = GTI_SELFTEST_RESULT_DONE;
- return driver_test_selftest(cd, cmd->buffer);
+ return driver_test_selftest(cmd->buffer);
}
static int gti_get_context_driver(void *private_data,
@@ -1004,7 +1207,6 @@ static int gti_set_report_rate(void *private_data,
}
#endif
-/*~[GOOG] */
/* prosfs create */
static int rawdata_proc_show(struct seq_file *m, void *v)
@@ -1055,8 +1257,8 @@ exit:
static int rawdata_proc_open(struct inode *inode, struct file *file)
{
- return single_open_size(file, rawdata_proc_show,
- PDE_DATA(inode), PAGE_SIZE * 10);
+ return single_open_size(
+ file, rawdata_proc_show, PDE_DATA(inode), PAGE_SIZE * 10);
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
@@ -1077,51 +1279,78 @@ static const struct file_operations rawdata_proc_fops = {
static int goodix_ts_procfs_init(struct goodix_ts_core *core_data)
{
- int dev_id = core_data->pdev->id;
struct proc_dir_entry *proc_entry;
- char proc_node[32] = {0};
- int ret = 0; /* [GOOG] */
-
- sprintf(proc_node, "goodix_ts.%d", dev_id);
+ int ret = 0;
- core_data->proc_dir_entry = proc_mkdir(proc_node, NULL);
- if (!core_data->proc_dir_entry)
+ proc_entry = proc_mkdir("goodix_ts", NULL);
+ if (proc_entry == NULL) {
+ ts_err("failed to create proc entry: goodix_ts");
return -ENOMEM;
- proc_entry = proc_create_data("tp_capacitance_data",
- 0664, core_data->proc_dir_entry, &rawdata_proc_fops, core_data);
- if (!proc_entry) {
- ts_err("failed to create proc entry: goodix_ts.%d/tp_capacitance_data",
- dev_id);
+ }
+
+ proc_entry = proc_create_data("goodix_ts/tp_capacitance_data", 0664,
+ NULL, &rawdata_proc_fops, core_data);
+ if (proc_entry == NULL) {
+ ts_err("failed to create proc entry: goodix_ts/tp_capacitance_data");
ret = -ENOMEM;
goto err_create_data;
}
ret = driver_test_proc_init(core_data);
if (ret != 0) {
- ts_err("failed to create proc entry: goodix_ts.%d/driver_test", dev_id);
+ ts_err("failed to create proc entry: goodix_ts/driver_test");
ret = -ENOMEM;
goto err_create_driver;
}
-
- return 0;
+ return ret;
err_create_driver:
- remove_proc_entry("tp_capacitance_data", core_data->proc_dir_entry);
+ remove_proc_entry("goodix_ts/tp_capacitance_data", NULL);
err_create_data:
- remove_proc_entry(proc_node, NULL);
+ remove_proc_entry("goodix_ts", NULL);
return ret;
}
static void goodix_ts_procfs_exit(struct goodix_ts_core *core_data)
{
- int dev_id = core_data->pdev->id;
- char proc_node[32] = {0};
+ driver_test_proc_remove();
+ remove_proc_entry("goodix_ts/tp_capacitance_data", NULL);
+ remove_proc_entry("goodix_ts", NULL);
+}
- sprintf(proc_node, "goodix_ts.%d", dev_id);
+/* event notifier */
+static BLOCKING_NOTIFIER_HEAD(ts_notifier_list);
+/**
+ * goodix_ts_register_client - register a client notifier
+ * @nb: notifier block to callback on events
+ * see enum ts_notify_event in goodix_ts_core.h
+ */
+int goodix_ts_register_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&ts_notifier_list, nb);
+}
- driver_test_proc_remove(core_data);
- remove_proc_entry("tp_capacitance_data", core_data->proc_dir_entry);
- remove_proc_entry(proc_node, NULL);
+/**
+ * goodix_ts_unregister_client - unregister a client notifier
+ * @nb: notifier block to callback on events
+ * see enum ts_notify_event in goodix_ts_core.h
+ */
+int goodix_ts_unregister_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_unregister(&ts_notifier_list, nb);
+}
+
+/**
+ * fb_notifier_call_chain - notify clients of fb_events
+ * see enum ts_notify_event in goodix_ts_core.h
+ */
+int goodix_ts_blocking_notify(enum ts_notify_event evt, void *v)
+{
+ int ret;
+
+ ret = blocking_notifier_call_chain(
+ &ts_notifier_list, (unsigned long)evt, v);
+ return ret;
}
#if IS_ENABLED(CONFIG_OF)
@@ -1390,8 +1619,8 @@ static void goodix_ts_report_pen(
{
struct input_dev *dev = cd->pen_dev;
int i;
+ static unsigned int pen_pressure;
struct goodix_hid_hogp *hogp;
- struct goodix_ble_data *ble_data = &cd->ble_data;
char trace_tag[128];
ktime_t pen_ktime;
@@ -1406,21 +1635,21 @@ static void goodix_ts_report_pen(
ktime_to_ns(ktime_sub(pen_ktime, cd->coords_timestamp)));
ATRACE_BEGIN(trace_tag);
input_report_key(dev, BTN_TOUCH, 1);
- input_report_key(dev, BTN_TOOL_PEN, 1);
+ input_report_key(dev, pen_data->coords.tool_type, 1);
input_report_abs(dev, ABS_X, pen_data->coords.x);
input_report_abs(dev, ABS_Y, pen_data->coords.y);
- mutex_lock(&ble_data->lock);
- if (ble_data->hogp_ready) {
- hogp = (struct goodix_hid_hogp *)ble_data->hogp;
- cd->pen_pressure = hogp->pressure;
+ mutex_lock(&goodix_ble_data.lock);
+ if (goodix_ble_data.hogp_ready) {
+ hogp = (struct goodix_hid_hogp *)goodix_ble_data.hogp;
+ pen_pressure = hogp->pressure;
ts_debug("update pen pressure from ble %d",
- cd->pen_pressure);
+ pen_pressure);
}
- ble_data->hogp_ready = 0;
- mutex_unlock(&ble_data->lock);
+ goodix_ble_data.hogp_ready = 0;
+ mutex_unlock(&goodix_ble_data.lock);
- if (pen_data->coords.p && cd->pen_pressure)
- pen_data->coords.p = cd->pen_pressure;
+ if (pen_data->coords.p && pen_pressure)
+ pen_data->coords.p = pen_pressure;
input_report_abs(dev, ABS_PRESSURE, pen_data->coords.p);
if (pen_data->coords.p == 0)
input_report_abs(dev, ABS_DISTANCE, 1);
@@ -1441,9 +1670,9 @@ static void goodix_ts_report_pen(
ktime_to_ns(cd->coords_timestamp), ktime_to_ns(pen_ktime),
ktime_to_ns(ktime_sub(pen_ktime, cd->coords_timestamp)));
ATRACE_BEGIN(trace_tag);
- cd->pen_pressure = 0;
+ pen_pressure = 0;
input_report_key(dev, BTN_TOUCH, 0);
- input_report_key(dev, BTN_TOOL_PEN, 0);
+ input_report_key(dev, pen_data->coords.tool_type, 0);
}
/* report pen button */
for (i = 0; i < GOODIX_MAX_PEN_KEY; i++) {
@@ -1621,8 +1850,9 @@ static int goodix_ts_request_handle(
else if (ts_event->request_code == REQUEST_TYPE_RESET)
ret = hw_ops->reset(cd, GOODIX_NORMAL_RESET_DELAY_MS);
else if (ts_event->request_code == REQUEST_TYPE_UPDATE)
- ret = goodix_do_fw_update(cd, UPDATE_MODE_FORCE | UPDATE_MODE_BLOCK |
- UPDATE_MODE_SRC_REQUEST);
+ ret = goodix_do_fw_update(
+ NULL, UPDATE_MODE_FORCE | UPDATE_MODE_BLOCK |
+ UPDATE_MODE_SRC_REQUEST);
else if (ts_event->request_code == REQUEST_PEN_FREQ_HOP)
ret = goodix_update_pen_freq(cd, ts_event->request_data,
sizeof(ts_event->request_data));
@@ -1719,6 +1949,7 @@ static irqreturn_t goodix_ts_threadirq_func(int irq, void *data)
{
struct goodix_ts_core *core_data = data;
struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
+ struct goodix_ext_module *ext_module, *next;
struct goodix_ts_event *ts_event = &core_data->ts_event;
struct goodix_ts_esd *ts_esd = &core_data->ts_esd;
int ret;
@@ -1731,18 +1962,29 @@ static irqreturn_t goodix_ts_threadirq_func(int irq, void *data)
}
#endif
-/* [GOOG]
- * Remove the control to enable/disable the interrupt for bottom-half.
- disable_irq_nosync(core_data->irq);
- */
-
- /* [GOOG]
+ /*
* Since we received an interrupt from touch firmware, it means touch
* firmware is still alive. So skip esd check once.
*/
ts_esd->skip_once = true;
core_data->irq_trig_cnt++;
+ /* inform external module */
+ mutex_lock(&goodix_modules.mutex);
+ list_for_each_entry_safe(ext_module, next, &goodix_modules.head, list)
+ {
+ if (!ext_module->funcs->irq_event)
+ continue;
+ ret = ext_module->funcs->irq_event(core_data, ext_module);
+ if (ret == EVT_CANCEL_IRQEVT) {
+ mutex_unlock(&goodix_modules.mutex);
+#if IS_ENABLED(CONFIG_GOOG_TOUCH_INTERFACE) && IS_ENABLED(CONFIG_GTI_PM)
+ goog_pm_wake_unlock_nosync(core_data->gti, GTI_PM_WAKELOCK_TYPE_IRQ);
+#endif
+ return IRQ_HANDLED;
+ }
+ }
+ mutex_unlock(&goodix_modules.mutex);
/* read touch data from touch device */
ret = hw_ops->event_handler(core_data, ts_event);
@@ -1770,16 +2012,10 @@ static irqreturn_t goodix_ts_threadirq_func(int irq, void *data)
goodix_ts_request_handle(core_data, ts_event);
if (ts_event->event_type & EVENT_STATUS)
goodix_ts_report_status(core_data, ts_event);
- if (ts_event->event_type & EVENT_GESTURE)
- goodix_ts_report_gesture(core_data, ts_event);
/* read done */
- hw_ops->after_event_handler(core_data); /* [GOOG] */
+ hw_ops->after_event_handler(core_data);
}
-/* [GOOG]
- * Remove the control to enable/disable the interrupt for bottom-half.
- enable_irq(core_data->irq);
- */
#if IS_ENABLED(CONFIG_GOOG_TOUCH_INTERFACE) && IS_ENABLED(CONFIG_GTI_PM)
goog_pm_wake_unlock_nosync(core_data->gti, GTI_PM_WAKELOCK_TYPE_IRQ);
@@ -2004,7 +2240,6 @@ static int goodix_ts_input_dev_config(struct goodix_ts_core *core_data)
{
struct goodix_ts_board_data *ts_bdata = board_data(core_data);
struct input_dev *input_dev = NULL;
- int dev_id = core_data->pdev->id;
int r;
input_dev = input_allocate_device();
@@ -2013,15 +2248,12 @@ static int goodix_ts_input_dev_config(struct goodix_ts_core *core_data)
return -ENOMEM;
}
- sprintf(core_data->input_name, "%s%d", GOODIX_CORE_DRIVER_NAME, dev_id);
- input_dev->dev.parent = &core_data->pdev->dev; /* [GOOG] */
- input_dev->name = core_data->input_name;
- input_dev->uniq = input_dev->name;
- input_dev->phys = input_dev->name;
- input_dev->id.bustype = core_data->bus->bus_type;
- input_dev->id.product = 0x0100 + dev_id;
- input_dev->id.vendor = 0x27C6;
- input_dev->id.version = 0x0100;
+ input_dev->name = GOODIX_CORE_DRIVER_NAME;
+ input_dev->phys = GOOIDX_INPUT_PHYS;
+ input_dev->uniq = "goodix_ts";
+ input_dev->id.product = 0xDEAD;
+ input_dev->id.vendor = 0xBEEF;
+ input_dev->id.version = 10427;
set_bit(EV_SYN, input_dev->evbit);
set_bit(EV_KEY, input_dev->evbit);
@@ -2070,7 +2302,6 @@ static int goodix_ts_pen_dev_config(struct goodix_ts_core *core_data)
{
struct goodix_ts_board_data *ts_bdata = board_data(core_data);
struct input_dev *pen_dev = NULL;
- int dev_id = core_data->pdev->id;
int r;
pen_dev = input_allocate_device();
@@ -2079,15 +2310,12 @@ static int goodix_ts_pen_dev_config(struct goodix_ts_core *core_data)
return -ENOMEM;
}
- sprintf(core_data->input_pen_name, "%s%d%s", GOODIX_CORE_DRIVER_NAME, dev_id, ",pen");
- pen_dev->dev.parent = &core_data->pdev->dev; /* [GOOG] */
- pen_dev->name = core_data->input_pen_name;
- pen_dev->uniq = pen_dev->name;
- pen_dev->phys = pen_dev->name;
- pen_dev->id.bustype = core_data->bus->bus_type;
- pen_dev->id.product = 0x0200 + dev_id;
- pen_dev->id.vendor = 0x27C6;
- pen_dev->id.version = 0x0100;
+ pen_dev->name = GOODIX_PEN_DRIVER_NAME;
+ pen_dev->phys = "goodix_ts,pen/input0";
+ pen_dev->uniq = "goodix_ts,pen";
+ pen_dev->id.product = 0xDEAD;
+ pen_dev->id.vendor = 0xBEEF;
+ pen_dev->id.version = 10427;
pen_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
set_bit(ABS_X, pen_dev->absbit);
@@ -2134,7 +2362,7 @@ void goodix_ts_pen_dev_remove(struct goodix_ts_core *core_data)
{
if (!core_data->pen_dev)
return;
- mutex_destroy(&core_data->ble_data.lock);
+ mutex_destroy(&goodix_ble_data.lock);
input_unregister_device(core_data->pen_dev);
core_data->pen_dev = NULL;
}
@@ -2192,7 +2420,7 @@ exit:
/**
* goodix_ts_esd_on - turn on esd protection
*/
-void goodix_ts_esd_on(struct goodix_ts_core *cd)
+static void goodix_ts_esd_on(struct goodix_ts_core *cd)
{
struct goodix_ic_info_misc *misc = &cd->ic_info.misc;
struct goodix_ts_esd *ts_esd = &cd->ts_esd;
@@ -2213,7 +2441,7 @@ void goodix_ts_esd_on(struct goodix_ts_core *cd)
/**
* goodix_ts_esd_off - turn off esd protection
*/
-void goodix_ts_esd_off(struct goodix_ts_core *cd)
+static void goodix_ts_esd_off(struct goodix_ts_core *cd)
{
struct goodix_ts_esd *ts_esd = &cd->ts_esd;
int ret;
@@ -2227,6 +2455,40 @@ void goodix_ts_esd_off(struct goodix_ts_core *cd)
}
/**
+ * goodix_esd_notifier_callback - notification callback
+ * under certain condition, we need to turn off/on the esd
+ * protector, we use kernel notify call chain to achieve this.
+ *
+ * for example: before firmware update we need to turn off the
+ * esd protector and after firmware update finished, we should
+ * turn on the esd protector.
+ */
+static int goodix_esd_notifier_callback(
+ struct notifier_block *nb, unsigned long action, void *data)
+{
+ struct goodix_ts_esd *ts_esd =
+ container_of(nb, struct goodix_ts_esd, esd_notifier);
+
+ switch (action) {
+ case NOTIFY_FWUPDATE_START:
+ case NOTIFY_SUSPEND:
+ case NOTIFY_ESD_OFF:
+ goodix_ts_esd_off(ts_esd->ts_core);
+ break;
+ case NOTIFY_FWUPDATE_FAILED:
+ case NOTIFY_FWUPDATE_SUCCESS:
+ case NOTIFY_RESUME:
+ case NOTIFY_ESD_ON:
+ goodix_ts_esd_on(ts_esd->ts_core);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/**
* goodix_ts_esd_init - initialize esd protection
*/
int goodix_ts_esd_init(struct goodix_ts_core *cd)
@@ -2242,6 +2504,8 @@ int goodix_ts_esd_init(struct goodix_ts_core *cd)
INIT_DELAYED_WORK(&ts_esd->esd_work, goodix_ts_esd_work);
ts_esd->ts_core = cd;
atomic_set(&ts_esd->esd_on, 0);
+ ts_esd->esd_notifier.notifier_call = goodix_esd_notifier_callback;
+ goodix_ts_register_notifier(&ts_esd->esd_notifier);
goodix_ts_esd_on(cd);
return 0;
@@ -2252,13 +2516,10 @@ void goodix_ts_esd_uninit(struct goodix_ts_core *cd)
struct goodix_ts_esd *ts_esd = &cd->ts_esd;
if (atomic_read(&ts_esd->esd_on))
goodix_ts_esd_off(cd);
+ goodix_ts_unregister_notifier(&ts_esd->esd_notifier);
}
-#if IS_ENABLED(CONFIG_GOOG_TOUCH_INTERFACE)
-static void goodix_ts_release_connects(struct goodix_ts_core *core_data)
-{
-}
-#else
+#if !IS_ENABLED(CONFIG_GOOG_TOUCH_INTERFACE)
static void goodix_ts_release_connects(struct goodix_ts_core *core_data)
{
struct input_dev *input_dev = core_data->input_dev;
@@ -2284,7 +2545,9 @@ static void goodix_ts_release_connects(struct goodix_ts_core *core_data)
*/
static int goodix_ts_suspend(struct goodix_ts_core *core_data)
{
+ struct goodix_ext_module *ext_module, *next;
struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
+ int ret;
if (core_data->init_stage < CORE_INIT_STAGE2 ||
atomic_read(&core_data->suspended))
@@ -2294,23 +2557,68 @@ static int goodix_ts_suspend(struct goodix_ts_core *core_data)
atomic_set(&core_data->suspended, 1);
/* disable irq */
hw_ops->disable_irq_nosync(core_data);
- goodix_ts_esd_off(core_data);
- if (core_data->gesture_type) {
- /* enter gesture mode */
- hw_ops->gesture(core_data, 0);
- hw_ops->irq_enable(core_data, true);
- enable_irq_wake(core_data->irq);
- } else {
- /* enter sleep mode or power off */
- if (core_data->board_data.sleep_enable)
- hw_ops->suspend(core_data);
- else
- goodix_ts_power_off(core_data);
+ /*
+ * notify suspend event, inform the esd protector
+ * and charger detector to turn off the work
+ */
+ goodix_ts_blocking_notify(NOTIFY_SUSPEND, NULL);
+
+ /* inform external module */
+ mutex_lock(&goodix_modules.mutex);
+ if (!list_empty(&goodix_modules.head)) {
+ list_for_each_entry_safe(
+ ext_module, next, &goodix_modules.head, list)
+ {
+ if (!ext_module->funcs->before_suspend)
+ continue;
+
+ ret = ext_module->funcs->before_suspend(
+ core_data, ext_module);
+ if (ret == EVT_CANCEL_SUSPEND) {
+ mutex_unlock(&goodix_modules.mutex);
+ ts_info("Canceled by module:%s",
+ ext_module->name);
+ goto out;
+ }
+ }
}
+ mutex_unlock(&goodix_modules.mutex);
+
+ /* enter sleep mode or power off */
+ 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);
+ if (!list_empty(&goodix_modules.head)) {
+ list_for_each_entry_safe(
+ ext_module, next, &goodix_modules.head, list)
+ {
+ if (!ext_module->funcs->after_suspend)
+ continue;
+
+ ret = ext_module->funcs->after_suspend(
+ core_data, ext_module);
+ if (ret == EVT_CANCEL_SUSPEND) {
+ mutex_unlock(&goodix_modules.mutex);
+ ts_info("Canceled by module:%s",
+ ext_module->name);
+ goto out;
+ }
+ }
+ }
+ mutex_unlock(&goodix_modules.mutex);
+
+ goodix_set_pinctrl_state(core_data, PINCTRL_MODE_SUSPEND);
+
+out:
+#if !IS_ENABLED(CONFIG_GOOG_TOUCH_INTERFACE)
goodix_ts_release_connects(core_data);
+#endif
- goodix_set_pinctrl_state(core_data, PINCTRL_MODE_SUSPEND); /* [GOOG] */
ts_info("Suspend end");
return 0;
}
@@ -2366,44 +2674,80 @@ static void monitor_gesture_event(struct work_struct *work)
*/
static int goodix_ts_resume(struct goodix_ts_core *core_data)
{
+ struct goodix_ext_module *ext_module, *next;
struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
+ struct goodix_gesture_data* gesture_data = &core_data->ts_event.gesture_data;
+ int ret;
+
if (core_data->init_stage < CORE_INIT_STAGE2 ||
!atomic_read(&core_data->suspended))
return 0;
ts_info("Resume start");
- goodix_set_pinctrl_state(core_data, PINCTRL_MODE_ACTIVE); /* [GOOG] */
+ goodix_set_pinctrl_state(core_data, PINCTRL_MODE_ACTIVE);
atomic_set(&core_data->suspended, 0);
hw_ops->irq_enable(core_data, false);
- /* [GOOG] */
- if (check_gesture_mode(core_data)) {
- struct goodix_gesture_data *gesture_data =
- &core_data->ts_event.gesture_data;
+ mutex_lock(&goodix_modules.mutex);
+ if (!list_empty(&goodix_modules.head)) {
+ list_for_each_entry_safe(
+ ext_module, next, &goodix_modules.head, list)
+ {
+ if (!ext_module->funcs->before_resume)
+ continue;
+
+ ret = ext_module->funcs->before_resume(
+ core_data, ext_module);
+ if (ret == EVT_CANCEL_RESUME) {
+ mutex_unlock(&goodix_modules.mutex);
+ ts_info("Canceled by module:%s",
+ ext_module->name);
+ goto out;
+ }
+ }
+ }
+ mutex_unlock(&goodix_modules.mutex);
+ if (check_gesture_mode(core_data)) {
gesture_data->gesture_type = GOODIX_GESTURE_UNKNOWN;
core_data->gesture_down_timeout = ktime_add_ms(ktime_get(), 100);
core_data->gesture_up_timeout = ktime_add_ms(ktime_get(), 200);
queue_delayed_work(core_data->event_wq, &core_data->monitor_gesture_work,
msecs_to_jiffies(5));
} else {
- if (core_data->gesture_type) {
- disable_irq_wake(core_data->irq);
+ /* reset device or power on*/
+ if (core_data->board_data.sleep_enable)
hw_ops->reset(core_data, GOODIX_NORMAL_RESET_DELAY_MS);
- } else {
- /* reset device or power on*/
- if (core_data->board_data.sleep_enable)
- hw_ops->resume(core_data);
- else
- goodix_ts_power_on(core_data);
+ else
+ goodix_ts_power_on(core_data);
+ }
+
+ mutex_lock(&goodix_modules.mutex);
+ if (!list_empty(&goodix_modules.head)) {
+ list_for_each_entry_safe(
+ ext_module, next, &goodix_modules.head, list)
+ {
+ if (!ext_module->funcs->after_resume)
+ continue;
+
+ ret = ext_module->funcs->after_resume(
+ core_data, ext_module);
+ if (ret == EVT_CANCEL_RESUME) {
+ mutex_unlock(&goodix_modules.mutex);
+ ts_info("Canceled by module:%s",
+ ext_module->name);
+ goto out;
+ }
}
}
+ mutex_unlock(&goodix_modules.mutex);
+out:
/* enable irq */
hw_ops->irq_enable(core_data, true);
/* open esd */
- goodix_ts_esd_on(core_data);
+ goodix_ts_blocking_notify(NOTIFY_RESUME, NULL);
ts_info("Resume end");
return 0;
}
@@ -2460,6 +2804,37 @@ static int goodix_ts_pm_resume(struct device *dev)
#endif
#endif
+/**
+ * goodix_generic_noti_callback - generic notifier callback
+ * for goodix touch notification event.
+ */
+static int goodix_generic_noti_callback(
+ struct notifier_block *self, unsigned long action, void *data)
+{
+ struct goodix_ts_core *cd =
+ container_of(self, struct goodix_ts_core, ts_notifier);
+ const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
+
+ if (cd->init_stage < CORE_INIT_STAGE2)
+ return 0;
+
+ ts_info("notify event type 0x%x", (unsigned int)action);
+ switch (action) {
+ case NOTIFY_FWUPDATE_START:
+ hw_ops->irq_enable(cd, 0);
+ break;
+ case NOTIFY_FWUPDATE_SUCCESS:
+ case NOTIFY_FWUPDATE_FAILED:
+ if (hw_ops->read_version(cd, &cd->fw_version))
+ ts_info("failed read fw version info[ignore]");
+ hw_ops->irq_enable(cd, 1);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
int goodix_ts_stage2_init(struct goodix_ts_core *cd)
{
int ret;
@@ -2491,7 +2866,7 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
ts_err("failed set pen device");
goto err_finger;
}
- mutex_init(&cd->ble_data.lock);
+ mutex_init(&goodix_ble_data.lock);
}
#if IS_ENABLED(CONFIG_FB)
@@ -2603,7 +2978,7 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
#if IS_ENABLED(CONFIG_GOODIX_GESTURE)
/* gesture init */
- ret = gesture_module_init(cd);
+ ret = gesture_module_init();
if (ret < 0) {
ts_err("failed set init gesture");
goto err_init_gesture;
@@ -2611,18 +2986,12 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
#endif
/* inspect init */
- ret = inspect_module_init(cd);
+ ret = inspect_module_init();
if (ret < 0) {
ts_err("failed set init inspect");
goto err_init_inspect;
}
-/*
- * [GOOG]
- * Touch frame package will read into `struct goodix_rx_package`.
- * The total read size for SPI is `touch_frame_size` + 8 bytes(SPI prefix header).
- * Therefore, `touch_frame_package` will need to allocate 8 extra bytes for SPI I/O.
- */
cd->touch_frame_size = touch_frame_size;
cd->touch_frame_package =
devm_kzalloc(&cd->pdev->dev, touch_frame_size + 8, GFP_KERNEL);
@@ -2658,7 +3027,6 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
ret = -ENOMEM;
goto err_setup_irq;
}
-/*~[GOOG]*/
/* request irq line */
ret = goodix_ts_irq_setup(cd);
@@ -2671,10 +3039,10 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd)
return 0;
err_setup_irq:
- inspect_module_exit(cd);
+ inspect_module_exit();
err_init_inspect:
#if IS_ENABLED(CONFIG_GOODIX_GESTURE)
- gesture_module_exit(cd);
+ gesture_module_exit();
err_init_gesture:
#endif
goodix_ts_esd_uninit(cd);
@@ -2752,16 +3120,10 @@ static int goodix_later_init_thread(void *data)
if (ret < 0) {
ts_err("failed to get version info, try to upgrade");
update_flag |= UPDATE_MODE_FORCE;
+ goto upgrade;
}
- /* step 2: read ic info */
- ret = hw_ops->get_ic_info(cd, &cd->ic_info);
- if (ret < 0) {
- ts_err("failed to get ic info, try to upgrade");
- update_flag |= UPDATE_MODE_FORCE;
- }
-
- /* step 3: get config data from config bin */
+ /* step 2: get config data from config bin */
ret = goodix_get_config_proc(cd);
if (ret < 0)
ts_info("no valid ic config found");
@@ -2770,20 +3132,35 @@ static int goodix_later_init_thread(void *data)
else
ts_info("one binary, no need find config");
- /* step 4: init fw struct add try do fw upgrade */
+upgrade:
+ /* step 3: init fw struct add try do fw upgrade */
ret = goodix_fw_update_init(cd);
if (ret) {
ts_err("failed init fw update module");
goto err_out;
}
- /* step 5: do upgrade */
ts_info("update flag: 0x%X", update_flag);
- ret = goodix_do_fw_update(cd, update_flag);
+ ret = goodix_do_fw_update(
+ cd->ic_configs[CONFIG_TYPE_NORMAL], update_flag);
if (ret)
ts_err("failed do fw update");
- print_ic_info(&cd->ic_info);
+ /* step 4: get fw version and ic_info
+ * at this step we believe that the ic is in normal mode,
+ * if the version info is invalid there must have some
+ * problem we cann't cover so exit init directly.
+ */
+ ret = hw_ops->read_version(cd, &cd->fw_version);
+ if (ret) {
+ ts_err("invalid fw version, abort");
+ goto uninit_fw;
+ }
+ ret = hw_ops->get_ic_info(cd, &cd->ic_info);
+ if (ret) {
+ ts_err("invalid ic info, abort");
+ goto uninit_fw;
+ }
/* the recommend way to update ic config is throuth ISP,
* if not we will send config with interactive mode
@@ -2801,7 +3178,7 @@ static int goodix_later_init_thread(void *data)
return 0;
uninit_fw:
- goodix_fw_update_uninit(cd);
+ goodix_fw_update_uninit();
err_out:
ts_err("stage2 init failed");
cd->init_stage = CORE_INIT_FAIL;
@@ -2843,16 +3220,25 @@ static int goodix_start_later_init(struct goodix_ts_core *ts_core)
*/
static int goodix_ts_probe(struct platform_device *pdev)
{
- struct goodix_device_resource *dev_res =
- container_of(pdev, struct goodix_device_resource, pdev);
- struct goodix_ts_core *core_data;
+ struct goodix_ts_core *core_data = NULL;
struct goodix_bus_interface *bus_interface;
int ret;
ts_info("IN");
- core_data = &dev_res->core_data;
- bus_interface = &dev_res->bus;
+ bus_interface = pdev->dev.platform_data;
+ if (!bus_interface) {
+ ts_err("Invalid touch device");
+ core_module_prob_sate = CORE_MODULE_PROB_FAILED;
+ return -ENODEV;
+ }
+
+ core_data = devm_kzalloc(
+ &pdev->dev, sizeof(struct goodix_ts_core), GFP_KERNEL);
+ if (!core_data) {
+ core_module_prob_sate = CORE_MODULE_PROB_FAILED;
+ return -ENOMEM;
+ }
if (IS_ENABLED(CONFIG_OF) && bus_interface->dev->of_node) {
/* parse devicetree property */
@@ -2870,10 +3256,11 @@ static int goodix_ts_probe(struct platform_device *pdev)
core_data->hw_ops = goodix_get_hw_ops();
if (!core_data->hw_ops) {
ts_err("hw ops is NULL");
+ core_module_prob_sate = CORE_MODULE_PROB_FAILED;
return -EINVAL;
}
mutex_init(&core_data->cmd_lock);
-
+ goodix_core_module_init();
/* touch core layer is a platform driver */
core_data->pdev = pdev;
core_data->bus = bus_interface;
@@ -2911,8 +3298,12 @@ static int goodix_ts_probe(struct platform_device *pdev)
goto err_setup_gpio;
}
+ /* generic notifier callback */
+ core_data->ts_notifier.notifier_call = goodix_generic_noti_callback;
+ goodix_ts_register_notifier(&core_data->ts_notifier);
+
/* debug node init */
- ret = goodix_tools_init(core_data);
+ ret = goodix_tools_init();
if (ret) {
ts_err("failed init tools");
goto err_init_tools;
@@ -2922,6 +3313,8 @@ static int goodix_ts_probe(struct platform_device *pdev)
// 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;
/* Try start a thread to get config-bin info */
ret = goodix_start_later_init(core_data);
@@ -2934,14 +3327,16 @@ static int goodix_ts_probe(struct platform_device *pdev)
return 0;
err_start_late_init:
- goodix_tools_exit(core_data);
+ goodix_tools_exit();
err_init_tools:
+ goodix_ts_unregister_notifier(&core_data->ts_notifier);
goodix_ts_power_off(core_data);
err_setup_gpio:
goodix_set_pinctrl_state(core_data, PINCTRL_MODE_SUSPEND);
err_out:
mutex_destroy(&core_data->cmd_lock);
core_data->init_stage = CORE_INIT_FAIL;
+ core_module_prob_sate = CORE_MODULE_PROB_FAILED;
ts_err("goodix_ts_core failed, ret:%d", ret);
return ret;
}
@@ -2950,45 +3345,38 @@ static int goodix_ts_remove(struct platform_device *pdev)
{
struct goodix_ts_core *core_data = platform_get_drvdata(pdev);
struct goodix_ts_hw_ops *hw_ops = core_data->hw_ops;
- struct goodix_ts_esd *ts_esd = &core_data->ts_esd;
-
if (core_data->init_stage >= CORE_INIT_STAGE2) {
-/* [GOOG]
- * Follow the reversed order of probe() to release resources.
- */
hw_ops->irq_enable(core_data, false);
-
- /* goodix_ts_stage2_init() */
- inspect_module_exit(core_data);
+ inspect_module_exit();
#if IS_ENABLED(CONFIG_GOODIX_GESTURE)
- gesture_module_exit(core_data);
+ gesture_module_exit();
#endif
- if (atomic_read(&ts_esd->esd_on))
- goodix_ts_esd_off(core_data);
+ core_module_prob_sate = CORE_MODULE_REMOVED;
+ goodix_ts_esd_uninit(core_data);
goodix_ts_procfs_exit(core_data);
+
#if IS_ENABLED(CONFIG_GOOG_TOUCH_INTERFACE)
#if IS_ENABLED(CONFIG_GTI_PM)
goog_pm_unregister_notification(core_data->gti);
#endif
- goog_touch_interface_remove(core_data->gti);
destroy_workqueue(core_data->event_wq);
touch_apis_deinit(&core_data->pdev->dev);
-#endif
+ goog_touch_interface_remove(core_data->gti);
goodix_ts_sysfs_exit(core_data);
+#endif
#if IS_ENABLED(CONFIG_FB)
fb_unregister_client(&core_data->fb_notifier);
#endif
goodix_ts_pen_dev_remove(core_data);
goodix_ts_input_dev_remove(core_data);
- /* goodix_later_init_thread() */
- goodix_fw_update_uninit(core_data);
+
+ goodix_fw_update_uninit();
}
- /* goodix_ts_probe() */
- goodix_tools_exit(core_data);
+ goodix_tools_exit();
+ goodix_ts_unregister_notifier(&core_data->ts_notifier);
goodix_ts_power_off(core_data);
-/*~[GOOG] */
goodix_set_pinctrl_state(core_data, PINCTRL_MODE_SUSPEND);
mutex_destroy(&core_data->cmd_lock);
@@ -3028,23 +3416,15 @@ static int __init goodix_ts_core_init(void)
int ret;
ts_info("Core layer init:%s", GOODIX_DRIVER_VERSION);
- goodix_device_manager_init();
-
#ifdef CONFIG_TOUCHSCREEN_GOODIX_BRL_SPI
ret = goodix_spi_bus_init();
- if (ret) {
- ts_err("failed add spi bus driver");
- return ret;
- }
-#endif
-#ifdef CONFIG_TOUCHSCREEN_GOODIX_BRL_I2C
+#else
ret = goodix_i2c_bus_init();
+#endif
if (ret) {
- ts_err("failed add i2c bus driver");
+ ts_err("failed add bus driver");
return ret;
}
-#endif
-
return platform_driver_register(&goodix_ts_driver);
}
@@ -3054,11 +3434,9 @@ static void __exit goodix_ts_core_exit(void)
platform_driver_unregister(&goodix_ts_driver);
#ifdef CONFIG_TOUCHSCREEN_GOODIX_BRL_SPI
goodix_spi_bus_exit();
-#endif
-#ifdef CONFIG_TOUCHSCREEN_GOODIX_BRL_I2C
+#else
goodix_i2c_bus_exit();
#endif
- goodix_device_manager_exit();
}
late_initcall(goodix_ts_core_init);
diff --git a/goodix_ts_core.h b/goodix_ts_core.h
index bb03a78..33a59ee 100644
--- a/goodix_ts_core.h
+++ b/goodix_ts_core.h
@@ -16,22 +16,21 @@
*/
#ifndef _GOODIX_TS_CORE_H_
#define _GOODIX_TS_CORE_H_
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/firmware.h>
-#include <linux/slab.h>
#include <asm/unaligned.h>
-#include <linux/vmalloc.h>
-#include <linux/kthread.h>
+#include <linux/completion.h>
#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/platform_device.h>
-#include <linux/miscdevice.h>
+#include <linux/firmware.h>
+#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
-#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <drm/drm_panel.h>
#if IS_ENABLED(CONFIG_OF)
#include <linux/of_gpio.h>
@@ -57,7 +56,7 @@
#define GOODIX_CORE_DRIVER_NAME "goodix_ts"
#define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen"
-#define GOODIX_DRIVER_VERSION "v1.2.5"
+#define GOODIX_DRIVER_VERSION "v1.2.4"
#define GOODIX_MAX_TOUCH 10
#define GOODIX_PEN_MAX_PRESSURE 4096
#define GOODIX_MAX_PEN_KEY 2
@@ -75,18 +74,11 @@
#define GOODIX_RETRY_5 5
#define GOODIX_RETRY_10 10
-/*
- * [GOOG]
- * Don't hardcode for tx/rx num.
-#define GOODIX_MAX_DRV_NUM 32
-#define GOODIX_MAX_SEN_NUM 39
- */
#define GOODIX_GESTURE_UNKNOWN 0x00
#define GOODIX_GESTURE_DOUBLE_TAP 0xCC
#define GOODIX_GESTURE_SINGLE_TAP 0x4C
#define GOODIX_GESTURE_FOD_DOWN 0x46
#define GOODIX_GESTURE_FOD_UP 0x55
-/*~[GOOG] */
#define TS_DEFAULT_FIRMWARE "goodix_firmware.bin"
#define TS_DEFAULT_CFG_BIN "goodix_cfg_group.bin"
@@ -473,45 +465,6 @@ enum touch_point_status {
TS_RELEASE,
TS_TOUCH,
};
-
-enum update_status {
- UPSTA_NOTWORK = 0,
- UPSTA_PREPARING,
- UPSTA_UPDATING,
- UPSTA_SUCCESS,
- UPSTA_FAILED
-};
-
-struct fw_subsys_info {
- u8 type;
- u32 size;
- u32 flash_addr;
- const u8 *data;
-};
-
-#pragma pack(1)
-struct firmware_summary {
- u32 size;
- u32 checksum;
- u8 hw_pid[6];
- u8 hw_vid[3];
- u8 fw_pid[8];
- u8 fw_vid[4];
- u8 subsys_num;
- u8 chip_type;
- u8 protocol_ver;
- u8 bus_type;
- u8 flash_protect;
- // u8 reserved[8];
- struct fw_subsys_info subsys[47];
-};
-#pragma pack()
-
-struct firmware_data {
- struct firmware_summary fw_summary;
- const struct firmware *firmware;
-};
-
/* coordinate package */
struct goodix_ts_coords {
int status; /* NONE, RELEASE, TOUCH */
@@ -545,24 +498,6 @@ struct goodix_ts_key {
int code;
};
-#define GOODIX_MAX_PEN_FREQ_DATA_LEN 16
-#define GOODIX_HOGP_INFO_LEN 3
-
-#pragma pack(1)
-struct goodix_hid_hogp {
- u16 pressure;
- u8 key;
-};
-#pragma pack()
-
-struct goodix_ble_data {
- u8 freq[GOODIX_MAX_PEN_FREQ_DATA_LEN];
- u8 hogp[GOODIX_HOGP_INFO_LEN];
- int hogp_ready;
- int freq_ready;
- struct mutex lock;
-};
-
struct goodix_pen_data {
struct goodix_pen_coords coords;
struct goodix_ts_key keys[GOODIX_MAX_PEN_KEY];
@@ -678,7 +613,7 @@ struct goodix_self_sensing_data {
};
struct goodix_rx_package {
- uint8_t header[8]; /* SPI prefix */
+ uint8_t header[8];
uint16_t data[0];
};
@@ -769,6 +704,7 @@ struct goodix_ts_esd {
bool skip_once;
atomic_t esd_on;
struct delayed_work esd_work;
+ struct notifier_block esd_notifier;
struct goodix_ts_core *ts_core;
};
@@ -784,77 +720,36 @@ struct goodix_ic_config {
u8 data[GOODIX_CFG_MAX_SIZE];
};
-struct fw_update_ctrl {
- struct mutex mutex;
- int initialized;
- char fw_name[GOODIX_MAX_STR_LABEL_LEN];
- int mode;
- enum update_status status;
- int spend_time;
-
- struct firmware_data fw_data;
- struct goodix_ic_config *ic_config;
- struct goodix_ic_config one_binary_cfg;
- struct goodix_ts_core *core_data;
- struct update_info_t *update_info;
- struct kobject *kobj;
- struct attribute_group attrs; /* [GOOG] */
-};
-
-struct goodix_tools_dev {
- bool is_open;
- struct miscdevice miscdev;
- char name[32];
-};
-
struct goodix_ts_core {
int init_stage;
- struct goodix_tools_dev tools_dev;
- struct fw_update_ctrl update_ctrl;
- struct kobject *gesture_kobj;
- struct proc_dir_entry *proc_dir_entry;
struct platform_device *pdev;
struct goodix_fw_version fw_version;
struct goodix_ic_info ic_info;
struct goodix_bus_interface *bus;
struct goodix_ts_board_data board_data;
+ struct touch_apis_data apis_data;
struct goodix_ts_hw_ops *hw_ops;
struct input_dev *input_dev;
struct input_dev *pen_dev;
struct mutex cmd_lock;
/* TODO counld we remove this from core data? */
struct goodix_ts_event ts_event;
- struct goodix_ble_data ble_data;
- u32 pen_pressure;
-
- char input_name[32];
- char input_pen_name[32];
+ struct workqueue_struct *event_wq;
+ struct delayed_work monitor_gesture_work;
+ ktime_t gesture_down_timeout;
+ ktime_t gesture_up_timeout;
/* every pointer of this array represent a kind of config */
struct goodix_ic_config *ic_configs[GOODIX_MAX_CONFIG_GROUP];
struct regulator *avdd;
struct regulator *iovdd;
- uint32_t gesture_type;
-
- /*
- * [GOOG]
- * Use goodix_update_heatmap() to do the heatmap process.
- u8 heatmap_buffer;
- s16 heatmap_diff[GOODIX_MAX_DRV_NUM * GOODIX_MAX_SEN_NUM];
- s16 heatmap_selfdiff[GOODIX_MAX_DRV_NUM + GOODIX_MAX_SEN_NUM];
- */
- struct touch_apis_data apis_data;
- struct workqueue_struct *event_wq;
- struct delayed_work monitor_gesture_work;
- ktime_t gesture_down_timeout;
- ktime_t gesture_up_timeout;
+ unsigned char gesture_type;
struct goodix_rx_package *touch_frame_package;
size_t touch_frame_size;
uint16_t *mutual_data;
uint16_t *self_sensing_data;
uint16_t *mutual_data_manual;
uint16_t *self_sensing_data_manual;
- /*~[GOOG] */
int power_on;
int irq;
@@ -862,17 +757,16 @@ struct goodix_ts_core {
atomic_t irq_enabled;
atomic_t suspended;
- bool screen_protector_mode_enabled; /* [GOOG] */
+ bool screen_protector_mode_enabled;
/* when this flag is true, driver should not clean the sync flag */
bool tools_ctrl_sync;
+ struct notifier_block ts_notifier;
struct goodix_ts_esd ts_esd;
#if IS_ENABLED(CONFIG_FB)
struct notifier_block fb_notifier;
#endif
-
- /* [GOOG] */
#if IS_ENABLED(CONFIG_TOUCHSCREEN_MOTION_FILTER)
struct touch_mf tmf;
#endif
@@ -885,28 +779,93 @@ struct goodix_ts_core {
*/
ktime_t isr_timestamp;
ktime_t coords_timestamp;
- /*~[GOOG] */
};
-struct goodix_device_manager {
- struct list_head list;
- bool initialized;
- struct mutex mutex;
- int nums;
+/* external module structures */
+enum goodix_ext_priority {
+ EXTMOD_PRIO_RESERVED = 0,
+ EXTMOD_PRIO_FWUPDATE,
+ EXTMOD_PRIO_GESTURE,
+ EXTMOD_PRIO_HOTKNOT,
+ EXTMOD_PRIO_DBGTOOL,
+ EXTMOD_PRIO_DEFAULT,
+};
+
+#define EVT_HANDLED 0
+#define EVT_CONTINUE 0
+#define EVT_CANCEL 1
+#define EVT_CANCEL_IRQEVT 1
+#define EVT_CANCEL_SUSPEND 1
+#define EVT_CANCEL_RESUME 1
+#define EVT_CANCEL_RESET 1
+
+struct goodix_ext_module;
+/* external module's operations callback */
+struct goodix_ext_module_funcs {
+ int (*init)(struct goodix_ts_core *core_data,
+ struct goodix_ext_module *module);
+ int (*exit)(struct goodix_ts_core *core_data,
+ struct goodix_ext_module *module);
+ int (*before_reset)(struct goodix_ts_core *core_data,
+ struct goodix_ext_module *module);
+ int (*after_reset)(struct goodix_ts_core *core_data,
+ struct goodix_ext_module *module);
+ int (*before_suspend)(struct goodix_ts_core *core_data,
+ struct goodix_ext_module *module);
+ int (*after_suspend)(struct goodix_ts_core *core_data,
+ struct goodix_ext_module *module);
+ int (*before_resume)(struct goodix_ts_core *core_data,
+ struct goodix_ext_module *module);
+ int (*after_resume)(struct goodix_ts_core *core_data,
+ struct goodix_ext_module *module);
+ int (*irq_event)(struct goodix_ts_core *core_data,
+ struct goodix_ext_module *module);
};
-struct goodix_device_resource {
+/*
+ * struct goodix_ext_module - external module struct
+ * @list: list used to link into modules manager
+ * @name: name of external module
+ * @priority: module priority value, zero is invalid
+ * @funcs: operations callback
+ * @priv_data: private data region
+ * @kobj: kobject
+ * @work: used to queue one work to do registration
+ */
+struct goodix_ext_module {
struct list_head list;
- int id;
- char name[64];
- struct goodix_bus_interface bus;
- struct platform_device pdev;
- struct goodix_ts_core core_data;
+ char *name;
+ enum goodix_ext_priority priority;
+ const struct goodix_ext_module_funcs *funcs;
+ void *priv_data;
+ struct kobject kobj;
+ struct work_struct work;
};
-extern struct goodix_device_manager goodix_devices;
-extern int goodix_device_register(struct goodix_device_resource *device);
+/*
+ * struct goodix_ext_attribute - exteranl attribute struct
+ * @attr: attribute
+ * @show: show interface of external attribute
+ * @store: store interface of external attribute
+ */
+struct goodix_ext_attribute {
+ struct attribute attr;
+ 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 */
+#define __EXTMOD_ATTR(_name, _mode, _show, _store) \
+ { \
+ .attr = { .name = __stringify(_name), .mode = _mode }, \
+ .show = _show, .store = _store, \
+ }
+
+/* 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)
/* log macro */
extern bool debug_log_flag;
@@ -932,6 +891,31 @@ static inline struct goodix_ts_board_data *board_data(
return &(core->board_data);
}
+/**
+ * goodix_register_ext_module - interface for external module
+ * to register into touch core modules structure
+ *
+ * @module: pointer to external module to be register
+ * return: 0 ok, <0 failed
+ */
+int goodix_register_ext_module(struct goodix_ext_module *module);
+/* register module no wait */
+int goodix_register_ext_module_no_wait(struct goodix_ext_module *module);
+/**
+ * goodix_unregister_ext_module - interface for external module
+ * to unregister external modules
+ *
+ * @module: pointer to external module
+ * return: 0 ok, <0 failed
+ */
+int goodix_unregister_ext_module(struct goodix_ext_module *module);
+/* remove all registered ext module
+ * return 0 on success, otherwise return < 0
+ */
+int goodix_ts_blocking_notify(enum ts_notify_event evt, void *v);
+struct kobj_type *goodix_get_default_ktype(void);
+struct kobject *goodix_get_default_kobj(void);
+
struct goodix_ts_hw_ops *goodix_get_hw_ops(void);
int goodix_get_config_proc(struct goodix_ts_core *cd);
@@ -947,26 +931,22 @@ u32 goodix_get_file_config_id(u8 *ic_config);
void goodix_rotate_abcd2cbad(int tx, int rx, s16 *src, s16 *dest);
int goodix_fw_update_init(struct goodix_ts_core *core_data);
-void goodix_fw_update_uninit(struct goodix_ts_core *core_data);
-int goodix_do_fw_update(struct goodix_ts_core *core_data, int mode);
+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, struct goodix_bus_interface *bus_inf);
-int gesture_module_init(struct goodix_ts_core *core_data);
-void gesture_module_exit(struct goodix_ts_core *core_data);
-int inspect_module_init(struct goodix_ts_core *core_data);
-void inspect_module_exit(struct goodix_ts_core *core_data);
-int goodix_tools_init(struct goodix_ts_core *core_data);
-void goodix_tools_exit(struct goodix_ts_core *core_data);
-void goodix_ts_esd_on(struct goodix_ts_core *cd);
-void goodix_ts_esd_off(struct goodix_ts_core *cd);
-void print_ic_info(struct goodix_ic_info *ic_info);
-
-int driver_test_selftest(struct goodix_ts_core *cd, char *buf);
+int gesture_module_init(void);
+void gesture_module_exit(void);
+int inspect_module_init(void);
+void inspect_module_exit(void);
+int goodix_tools_init(void);
+void goodix_tools_exit(void);
+
+int driver_test_selftest(char* buf);
int driver_test_proc_init(struct goodix_ts_core *core_data);
-void driver_test_proc_remove(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);
-int goodix_ts_report_gesture(struct goodix_ts_core *cd, struct goodix_ts_event *event);
void goodix_ts_report_status(struct goodix_ts_core *core_data,
struct goodix_ts_event *ts_event);
int goodix_update_pen_freq(struct goodix_ts_core *cd, u8 *data, int len);
diff --git a/goodix_ts_gesture.c b/goodix_ts_gesture.c
index 51335da..d4246b0 100644
--- a/goodix_ts_gesture.c
+++ b/goodix_ts_gesture.c
@@ -27,136 +27,236 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/version.h>
+
/*
- * [GOOG]
- * Move GOODIX_GESTURE_* define to goodix_ts_core.h.
+ * struct gesture_module - gesture module data
+ * @registered: module register state
+ * @sysfs_node_created: sysfs node state
+ * @gesture_type: valid gesture type, each bit represent one gesture type
+ * @gesture_data: store latest gesture code get from irq event
+ * @gesture_ts_cmd: gesture command data
*/
+struct gesture_module {
+ atomic_t registered;
+ 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;
-static ssize_t gsx_double_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t gsx_double_type_show(struct goodix_ext_module *module, char *buf)
{
- struct device *device =
- container_of(((struct kobject *)dev)->parent, struct device, kobj);
- struct goodix_ts_core *cd = dev_get_drvdata(device);
- uint32_t type = cd->gesture_type;
+ 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_DOUBLE_TAP) ? "enable" : "disable");
}
-static ssize_t gsx_double_type_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t gsx_double_type_store(
+ struct goodix_ext_module *module, const char *buf, size_t count)
{
- struct device *device =
- container_of(((struct kobject *)dev)->parent, struct device, kobj);
- struct goodix_ts_core *cd = dev_get_drvdata(device);
+ struct gesture_module *gsx = module->priv_data;
+
+ if (!gsx)
+ return -EIO;
+
+ if (atomic_read(&gsx->registered) == 0) {
+ ts_err("gesture module is not registered");
+ return 0;
+ }
if (buf[0] == '1') {
ts_info("enable double tap");
- cd->gesture_type |= GESTURE_DOUBLE_TAP;
+ gsx->ts_core->gesture_type |= GESTURE_DOUBLE_TAP;
} else if (buf[0] == '0') {
ts_info("disable double tap");
- cd->gesture_type &= ~GESTURE_DOUBLE_TAP;
+ gsx->ts_core->gesture_type &= ~GESTURE_DOUBLE_TAP;
} else
ts_err("invalid cmd[%d]", buf[0]);
return count;
}
-static ssize_t gsx_single_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t gsx_single_type_show(struct goodix_ext_module *module, char *buf)
{
- struct device *device =
- container_of(((struct kobject *)dev)->parent, struct device, kobj);
- struct goodix_ts_core *cd = dev_get_drvdata(device);
- uint32_t type = cd->gesture_type;
+ 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_SINGLE_TAP) ? "enable" : "disable");
}
-static ssize_t gsx_single_type_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t gsx_single_type_store(
+ struct goodix_ext_module *module, const char *buf, size_t count)
{
- struct device *device =
- container_of(((struct kobject *)dev)->parent, struct device, kobj);
- struct goodix_ts_core *cd = dev_get_drvdata(device);
+ struct gesture_module *gsx = module->priv_data;
+
+ if (!gsx)
+ return -EIO;
+
+ if (atomic_read(&gsx->registered) == 0) {
+ ts_err("gesture module is not registered");
+ return 0;
+ }
if (buf[0] == '1') {
ts_info("enable single tap");
- cd->gesture_type |= GESTURE_SINGLE_TAP;
+ gsx->ts_core->gesture_type |= GESTURE_SINGLE_TAP;
} else if (buf[0] == '0') {
ts_info("disable single tap");
- cd->gesture_type &= ~GESTURE_SINGLE_TAP;
+ gsx->ts_core->gesture_type &= ~GESTURE_SINGLE_TAP;
} else
ts_err("invalid cmd[%d]", buf[0]);
return count;
}
-static ssize_t gsx_fod_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t gsx_fod_type_show(struct goodix_ext_module *module, char *buf)
{
- struct device *device =
- container_of(((struct kobject *)dev)->parent, struct device, kobj);
- struct goodix_ts_core *cd = dev_get_drvdata(device);
- uint32_t type = cd->gesture_type;
+ 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_fod_type_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+static ssize_t gsx_fod_type_store(
+ struct goodix_ext_module *module, const char *buf, size_t count)
{
- struct device *device =
- container_of(((struct kobject *)dev)->parent, struct device, kobj);
- struct goodix_ts_core *cd = dev_get_drvdata(device);
+ struct gesture_module *gsx = module->priv_data;
+
+ if (!gsx)
+ return -EIO;
+
+ if (atomic_read(&gsx->registered) == 0) {
+ ts_err("gesture module is not registered");
+ return 0;
+ }
if (buf[0] == '1') {
ts_info("enable fod");
- cd->gesture_type |= GESTURE_FOD_PRESS;
+ gsx->ts_core->gesture_type |= GESTURE_FOD_PRESS;
} else if (buf[0] == '0') {
ts_info("disable fod");
- cd->gesture_type &= ~GESTURE_FOD_PRESS;
+ gsx->ts_core->gesture_type &= ~GESTURE_FOD_PRESS;
} else
ts_err("invalid cmd[%d]", buf[0]);
return count;
}
-static DEVICE_ATTR(double_type, 0664, gsx_double_type_show, gsx_double_type_store);
-static DEVICE_ATTR(single_type, 0664, gsx_single_type_show, gsx_single_type_store);
-static DEVICE_ATTR(fod_type, 0664, gsx_fod_type_show, gsx_fod_type_store);
-
-static struct attribute *gesture_attrs[] = {
- &dev_attr_double_type.attr,
- &dev_attr_single_type.attr,
- &dev_attr_fod_type.attr,
- NULL,
+const struct goodix_ext_attribute gesture_attrs[] = {
+ __EXTMOD_ATTR(
+ 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),
};
-const static struct attribute_group gesture_sysfs_group = {
- .attrs = gesture_attrs,
-};
+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;
+ }
+
+ gsx->ts_core = cd;
+ gsx->ts_core->gesture_type = 0;
+ atomic_set(&gsx->registered, 1);
+
+ return 0;
+}
+
+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;
+ }
+
+ atomic_set(&gsx->registered, 0);
+
+ return 0;
+}
-int goodix_ts_report_gesture(struct goodix_ts_core *cd, struct goodix_ts_event *event)
+/**
+ * gsx_gesture_ist - Gesture Irq handle
+ * This functions is excuted when interrupt happened and
+ * ic in doze mode.
+ *
+ * @cd: pointer to touch core data
+ * @module: pointer to goodix_ext_module struct
+ * return: 0 goon execute, EVT_CANCEL_IRQEVT stop execute
+ */
+static int gsx_gesture_ist(
+ struct goodix_ts_core *cd, struct goodix_ext_module *module)
{
+ struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
+ struct goodix_ts_event gs_event = { 0 };
int coor_x, coor_y, coor_size, coor_press;
int major, minor, orientation;
+ int ret;
+
+ if (atomic_read(&cd->suspended) == 0 || cd->gesture_type == 0)
+ return EVT_CONTINUE;
+
+ ret = hw_ops->event_handler(cd, &gs_event);
+ if (ret) {
+ ts_err("failed get gesture data");
+ cd->hw_ops->gesture(cd, 0);
+ goto re_send_ges_cmd;
+ }
+
+ if (!(gs_event.event_type & EVENT_GESTURE)) {
+ ts_err("invalid event type: 0x%x", cd->ts_event.event_type);
+ cd->hw_ops->gesture(cd, 0);
+ goto re_send_ges_cmd;
+ }
+
+ if (gs_event.event_type & EVENT_STATUS)
+ goodix_ts_report_status(cd, &gs_event);
- coor_x = le16_to_cpup((__le16 *)event->gesture_data.data);
- coor_y = le16_to_cpup((__le16 *)(event->gesture_data.data + 2));
- coor_size = le16_to_cpup((__le16 *)(event->gesture_data.data + 4));
- coor_press = event->gesture_data.data[6];
- major = le16_to_cpup((__le16 *)(event->gesture_data.data + 7));
- minor = le16_to_cpup((__le16 *)(event->gesture_data.data + 9));
- orientation = (s8)event->gesture_data.data[11];
+ coor_x = le16_to_cpup((__le16 *)gs_event.gesture_data.data);
+ coor_y = le16_to_cpup((__le16 *)(gs_event.gesture_data.data + 2));
+ coor_size = le16_to_cpup((__le16 *)(gs_event.gesture_data.data + 4));
+ coor_press = gs_event.gesture_data.data[6];
+ major = le16_to_cpup((__le16 *)(gs_event.gesture_data.data + 7));
+ minor = le16_to_cpup((__le16 *)(gs_event.gesture_data.data + 9));
+ orientation = (s8)gs_event.gesture_data.data[11];
- switch (event->gesture_data.gesture_type) {
+ switch (gs_event.gesture_data.gesture_type) {
case GOODIX_GESTURE_SINGLE_TAP:
if (cd->gesture_type & GESTURE_SINGLE_TAP) {
ts_info("get SINGLE-TAP gesture");
@@ -240,45 +340,132 @@ int goodix_ts_report_gesture(struct goodix_ts_core *cd, struct goodix_ts_event *
}
break;
default:
- ts_err("not support gesture type[%02X]", event->gesture_data.gesture_type);
+ ts_err("not support gesture type[%02X]", gs_event.gesture_data.gesture_type);
break;
}
- return 0;
+re_send_ges_cmd:
+ return EVT_CANCEL_IRQEVT;
}
-int gesture_module_init(struct goodix_ts_core *core_data)
+/**
+ * gsx_gesture_before_suspend - execute gesture suspend routine
+ * This functions is excuted to set ic into doze mode
+ *
+ * @cd: pointer to touch core data
+ * @module: pointer to goodix_ext_module struct
+ * return: 0 goon execute, EVT_IRQCANCLED stop execute
+ */
+static int gsx_gesture_before_suspend(
+ struct goodix_ts_core *cd, struct goodix_ext_module *module)
{
- int ret = 0;
- struct kobject *parent = &core_data->pdev->dev.kobj;
+ 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, type[0x%02X]", cd->gesture_type);
+
+ hw_ops->irq_enable(cd, true);
+ enable_irq_wake(cd->irq);
+
+ return EVT_CANCEL_SUSPEND;
+}
+
+static int gsx_gesture_before_resume(
+ struct goodix_ts_core *cd, struct goodix_ext_module *module)
+{
+ const struct goodix_ts_hw_ops *hw_ops = cd->hw_ops;
+
+ if (cd->gesture_type == 0)
+ return EVT_CONTINUE;
+
+ disable_irq_wake(cd->irq);
+ hw_ops->reset(cd, GOODIX_NORMAL_RESET_DELAY_MS);
+
+ return EVT_CANCEL_RESUME;
+}
+
+static struct goodix_ext_module_funcs gsx_gesture_funcs = {
+ .irq_event = gsx_gesture_ist,
+ .init = gsx_gesture_init,
+ .exit = gsx_gesture_exit,
+ .before_suspend = gsx_gesture_before_suspend,
+ .before_resume = gsx_gesture_before_resume,
+};
+
+int gesture_module_init(void)
+{
+ int ret;
+ int i;
+ struct kobject *def_kobj = goodix_get_default_kobj();
+ struct kobj_type *def_kobj_type = goodix_get_default_ktype();
+
+ gsx_gesture = kzalloc(sizeof(struct gesture_module), GFP_KERNEL);
+ if (!gsx_gesture)
+ return -ENOMEM;
+
+ gsx_gesture->module.funcs = &gsx_gesture_funcs;
+ gsx_gesture->module.priority = EXTMOD_PRIO_GESTURE;
+ gsx_gesture->module.name = "Goodix_gsx_gesture";
+ gsx_gesture->module.priv_data = gsx_gesture;
+
+ atomic_set(&gsx_gesture->registered, 0);
/* gesture sysfs init */
- core_data->gesture_kobj = kobject_create_and_add("gesture", parent);
- if (!core_data->gesture_kobj) {
+ ret = kobject_init_and_add(
+ &gsx_gesture->module.kobj, def_kobj_type, def_kobj, "gesture");
+ if (ret) {
ts_err("failed create gesture sysfs node!");
- ret = -ENOENT; /* [GOOG] */
goto err_out;
}
- ret = sysfs_create_group(core_data->gesture_kobj, &gesture_sysfs_group);
+ for (i = 0; i < ARRAY_SIZE(gesture_attrs) && !ret; i++)
+ ret = sysfs_create_file(
+ &gsx_gesture->module.kobj, &gesture_attrs[i].attr);
if (ret) {
- ts_err("failed create gesture sysfs files");
- kobject_put(core_data->gesture_kobj);
+ ts_err("failed create gst sysfs files");
+ while (--i >= 0)
+ sysfs_remove_file(&gsx_gesture->module.kobj,
+ &gesture_attrs[i].attr);
+
+ kobject_put(&gsx_gesture->module.kobj);
goto err_out;
}
+ module_initialized = true;
+ goodix_register_ext_module_no_wait(&gsx_gesture->module);
ts_info("gesture module init success");
+
return 0;
err_out:
ts_err("gesture module init failed!");
+ kfree(gsx_gesture);
return ret;
}
-void gesture_module_exit(struct goodix_ts_core *core_data)
+void gesture_module_exit(void)
{
+ int i;
+
ts_info("gesture module exit");
+ if (!module_initialized)
+ return;
+
+ goodix_unregister_ext_module(&gsx_gesture->module);
+
+ /* deinit sysfs */
+ for (i = 0; i < ARRAY_SIZE(gesture_attrs); i++)
+ sysfs_remove_file(
+ &gsx_gesture->module.kobj, &gesture_attrs[i].attr);
- sysfs_remove_group(core_data->gesture_kobj, &gesture_sysfs_group);
- kobject_put(core_data->gesture_kobj);
+ kobject_put(&gsx_gesture->module.kobj);
+ kfree(gsx_gesture);
+ module_initialized = false;
}
diff --git a/goodix_ts_inspect.c b/goodix_ts_inspect.c
index bebc557..119c8bc 100644
--- a/goodix_ts_inspect.c
+++ b/goodix_ts_inspect.c
@@ -122,6 +122,8 @@
#define ABS(val) ((val < 0) ? -(val) : val)
#define MAX(a, b) ((a > b) ? a : b)
+static bool module_initialized;
+
/* short threshold, drv-drv, drv-sen, sen-sen, drv-gnd, sen-gnd, avdd */
static u8 short_circuit_threshold[] = { 10, 200, 200, 200, 200, 200, 30 };
@@ -515,7 +517,7 @@ static int goodix_tptest_prepare(struct goodix_ts_test *ts_test)
/* disable irq */
ts_test_irq_enable(ts_test, false);
/* close esd */
- goodix_ts_esd_off(ts_test->ts);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
return 0;
}
@@ -527,7 +529,7 @@ static void goodix_tptest_finish(struct goodix_ts_test *ts_test)
ts_test_reset(ts_test, 100);
/* open esd */
- goodix_ts_esd_on(ts_test->ts);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
/* enable irq */
ts_test_irq_enable(ts_test, true);
}
@@ -1351,10 +1353,10 @@ static ssize_t get_rawdata_show(
static DEVICE_ATTR(get_rawdata, 0444, get_rawdata_show, NULL);
-int inspect_module_init(struct goodix_ts_core *core_data)
+int inspect_module_init(void)
{
int ret;
- struct kobject *def_kobj = &core_data->pdev->dev.kobj;
+ struct kobject *def_kobj = goodix_get_default_kobj();
/* create sysfs */
ret = sysfs_create_file(def_kobj, &dev_attr_get_rawdata.attr);
@@ -1362,6 +1364,8 @@ int inspect_module_init(struct goodix_ts_core *core_data)
ts_err("create sysfs of get_rawdata failed");
goto err_out;
}
+
+ module_initialized = true;
ts_info("inspect module init success");
return 0;
@@ -1370,10 +1374,14 @@ err_out:
return ret;
}
-void inspect_module_exit(struct goodix_ts_core *core_data)
+void inspect_module_exit(void)
{
- struct kobject *def_kobj = &core_data->pdev->dev.kobj;
+ 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
index d2f0082..a8ed02f 100644
--- a/goodix_ts_proc.c
+++ b/goodix_ts_proc.c
@@ -52,7 +52,7 @@
#define CMD_SET_FREQ_INDEX "set_freq_index"
#define CMD_DISABLE_FILTER "disable_filter"
-const static char *cmd_list[] = { CMD_FW_UPDATE, CMD_AUTO_TEST, CMD_OPEN_TEST,
+char *cmd_list[] = { CMD_FW_UPDATE, CMD_AUTO_TEST, CMD_OPEN_TEST,
CMD_SELF_OPEN_TEST, CMD_NOISE_TEST, CMD_AUTO_NOISE_TEST, CMD_SHORT_TEST,
CMD_GET_PACKAGE_ID, CMD_GET_MCU_ID, CMD_GET_VERSION, CMD_GET_RAWDATA,
CMD_GET_DIFFDATA, CMD_GET_BASEDATA, CMD_GET_SELF_RAWDATA,
@@ -90,6 +90,7 @@ const static char *cmd_list[] = { CMD_FW_UPDATE, CMD_AUTO_TEST, CMD_OPEN_TEST,
#define LARGE_SIZE 5 * 1024
#define MAX_FRAME_CNT 50
#define HUGE_SIZE MAX_FRAME_CNT * 20 * 1024
+static struct goodix_ts_core *cd;
static char wbuf[SHORT_SIZE];
static char *rbuf;
static uint32_t index;
@@ -410,7 +411,7 @@ struct goodix_ts_test {
};
static struct goodix_ts_test *ts_test;
-static int cal_cha_to_cha_res(struct goodix_ts_core *cd, int v1, int v2)
+static int cal_cha_to_cha_res(int v1, int v2)
{
if (cd->bus->ic_type == IC_TYPE_BERLIN_A)
return (v1 - v2) * 63 / v2;
@@ -422,7 +423,7 @@ static int cal_cha_to_cha_res(struct goodix_ts_core *cd, int v1, int v2)
return (v1 / v2 - 1) * 55 + 45;
}
-static int cal_cha_to_avdd_res(struct goodix_ts_core *cd, int v1, int v2)
+static int cal_cha_to_avdd_res(int v1, int v2)
{
if (cd->bus->ic_type == IC_TYPE_BERLIN_A)
return 64 * (2 * v2 - 25) * 40 / v1 - 40;
@@ -434,7 +435,7 @@ static int cal_cha_to_avdd_res(struct goodix_ts_core *cd, int v1, int v2)
return 64 * (2 * v2 - 25) * 76 / v1 - 15;
}
-static int cal_cha_to_gnd_res(struct goodix_ts_core *cd, int v)
+static int cal_cha_to_gnd_res(int v)
{
if (cd->bus->ic_type == IC_TYPE_BERLIN_A)
return 64148 / v - 40;
@@ -557,7 +558,7 @@ static void goodix_save_short_res(u16 chn1, u16 chn2, int r)
}
}
-static int gdix_check_tx_tx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_num)
+static int gdix_check_tx_tx_shortcircut(u8 short_ch_num)
{
int ret = 0, err = 0;
u32 r_threshold = 0, short_r = 0;
@@ -614,9 +615,11 @@ static int gdix_check_tx_tx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_n
if (adc_signal < ts_test->short_threshold)
continue;
- short_r = (u32)cal_cha_to_cha_res(cd, self_capdata, adc_signal);
+ short_r = (u32)cal_cha_to_cha_res(
+ self_capdata, adc_signal);
if (short_r < r_threshold) {
- master_pin_num = map_die2pin(short_die_num + max_sen_num);
+ master_pin_num = map_die2pin(
+ short_die_num + max_sen_num);
slave_pin_num = map_die2pin(j + max_sen_num);
if (master_pin_num == 0xFF ||
slave_pin_num == 0xFF) {
@@ -646,7 +649,7 @@ static int gdix_check_tx_tx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_n
return err;
}
-static int gdix_check_rx_rx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_num)
+static int gdix_check_rx_rx_shortcircut(u8 short_ch_num)
{
int ret = 0, err = 0;
u32 r_threshold = 0, short_r = 0;
@@ -700,7 +703,8 @@ static int gdix_check_rx_rx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_n
if (adc_signal < ts_test->short_threshold)
continue;
- short_r = (u32)cal_cha_to_cha_res(cd, self_capdata, adc_signal);
+ short_r = (u32)cal_cha_to_cha_res(
+ self_capdata, adc_signal);
if (short_r < r_threshold) {
master_pin_num = map_die2pin(short_die_num);
slave_pin_num = map_die2pin(j);
@@ -732,7 +736,7 @@ static int gdix_check_rx_rx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_n
return err;
}
-static int gdix_check_tx_rx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_num)
+static int gdix_check_tx_rx_shortcircut(u8 short_ch_num)
{
int ret = 0, err = 0;
u32 r_threshold = 0, short_r = 0;
@@ -787,7 +791,8 @@ static int gdix_check_tx_rx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_n
if (adc_signal < ts_test->short_threshold)
continue;
- short_r = (u32)cal_cha_to_cha_res(cd, self_capdata, adc_signal);
+ short_r = (u32)cal_cha_to_cha_res(
+ self_capdata, adc_signal);
if (short_r < r_threshold) {
master_pin_num = map_die2pin(short_die_num);
slave_pin_num = map_die2pin(j + max_sen_num);
@@ -819,7 +824,7 @@ static int gdix_check_tx_rx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_n
return err;
}
-static int gdix_check_resistance_to_gnd(struct goodix_ts_core *cd, u16 adc_signal, u32 pos)
+static int gdix_check_resistance_to_gnd(u16 adc_signal, u32 pos)
{
long r = 0;
u16 r_th = 0, avdd_value = 0;
@@ -837,10 +842,10 @@ static int gdix_check_resistance_to_gnd(struct goodix_ts_core *cd, u16 adc_signa
if (short_type == 0) {
/* short to GND */
- r = cal_cha_to_gnd_res(cd, adc_signal);
+ r = cal_cha_to_gnd_res(adc_signal);
} else {
/* short to VDD */
- r = cal_cha_to_avdd_res(cd, adc_signal, avdd_value);
+ r = cal_cha_to_avdd_res(adc_signal, avdd_value);
}
if (pos < max_drv_num)
@@ -869,7 +874,7 @@ static int gdix_check_resistance_to_gnd(struct goodix_ts_core *cd, u16 adc_signa
return 0;
}
-static int gdix_check_gndvdd_shortcircut(struct goodix_ts_core *cd)
+static int gdix_check_gndvdd_shortcircut(void)
{
int ret = 0, err = 0;
int size = 0, i = 0;
@@ -902,7 +907,7 @@ static int gdix_check_gndvdd_shortcircut(struct goodix_ts_core *cd)
for (i = 0; i < max_drv_num + max_sen_num; i++) {
adc_signal = le16_to_cpup((__le16 *)&data_buf[i * 2]);
- ret = gdix_check_resistance_to_gnd(cd, adc_signal, i);
+ ret = gdix_check_resistance_to_gnd(adc_signal, i);
if (ret != 0) {
ts_err("Resistance to-gnd/vdd short");
err = ret;
@@ -917,7 +922,7 @@ err_out:
#define NOTT_CHECKSUM_LEN 54
#define BRLD_CHECKSUM_LEN 62
#define BRLB_CHECKSUM_LEN 129
-static int goodix_shortcircut_analysis(struct goodix_ts_core *cd)
+static int goodix_shortcircut_analysis(void)
{
int ret;
int err = 0;
@@ -958,13 +963,13 @@ static int goodix_shortcircut_analysis(struct goodix_ts_core *cd)
test_result.drv_gnd_avdd_num, test_result.sen_gnd_avdd_num);
if (test_result.drv_drv_num)
- err |= gdix_check_tx_tx_shortcircut(cd, test_result.drv_drv_num);
+ err |= gdix_check_tx_tx_shortcircut(test_result.drv_drv_num);
if (test_result.sen_sen_num)
- err |= gdix_check_rx_rx_shortcircut(cd, test_result.sen_sen_num);
+ err |= gdix_check_rx_rx_shortcircut(test_result.sen_sen_num);
if (test_result.drv_sen_num)
- err |= gdix_check_tx_rx_shortcircut(cd, test_result.drv_sen_num);
+ err |= gdix_check_tx_rx_shortcircut(test_result.drv_sen_num);
if (test_result.drv_gnd_avdd_num || test_result.sen_gnd_avdd_num)
- err |= gdix_check_gndvdd_shortcircut(cd);
+ err |= gdix_check_gndvdd_shortcircut();
ts_info(">>>>> short check return 0x%x", err);
@@ -974,7 +979,7 @@ static int goodix_shortcircut_analysis(struct goodix_ts_core *cd)
#define INSPECT_FW_SWITCH_CMD 0x85
#define SHORT_TEST_RUN_FLAG 0xAA
#define SHORT_TEST_RUN_REG 0x10400
-static int goodix_short_test_prepare(struct goodix_ts_core *cd)
+static int goodix_short_test_prepare(void)
{
struct goodix_ts_cmd tmp_cmd;
int ret;
@@ -1013,7 +1018,7 @@ resend_cmd:
#define MAX_TEST_TIME_MS 15000
#define DEFAULT_TEST_TIME_MS 7000
#define SHORT_TEST_FINISH_FLAG 0x88
-static int goodix_shortcircut_test(struct goodix_ts_core *cd)
+static int goodix_shortcircut_test(void)
{
int ret = 0;
int res;
@@ -1022,7 +1027,7 @@ static int goodix_shortcircut_test(struct goodix_ts_core *cd)
u8 status;
ts_info("---------------------- short_test begin ----------------------");
- ret = goodix_short_test_prepare(cd);
+ ret = goodix_short_test_prepare();
if (ret < 0) {
ts_err("Failed enter short test mode");
return ret;
@@ -1066,7 +1071,7 @@ static int goodix_shortcircut_test(struct goodix_ts_core *cd)
/* start analysis short result */
ts_info("short_test finished, start analysis");
- res = goodix_shortcircut_analysis(cd);
+ res = goodix_shortcircut_analysis();
if (res == 0) {
ts_test->result[GTP_SHORT_TEST] = TEST_OK;
ret = 0;
@@ -1088,8 +1093,7 @@ typedef struct __attribute__((packed)) {
#define FLASH_CMD_STATE_CHECKERR 0x05
#define FLASH_CMD_STATE_DENY 0x06
#define FLASH_CMD_STATE_OKAY 0x07
-static int goodix_flash_cmd(struct goodix_ts_core *cd,
- uint8_t cmd, uint8_t status, int retry_count)
+static int goodix_flash_cmd(uint8_t cmd, uint8_t status, int retry_count)
{
u8 cmd_buf[] = { 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 };
int ret;
@@ -1118,7 +1122,7 @@ static int goodix_flash_cmd(struct goodix_ts_core *cd,
return -EINVAL;
}
-static int goodix_flash_read(struct goodix_ts_core *cd, u32 addr, u8 *buf, int len)
+static int goodix_flash_read(u32 addr, u8 *buf, int len)
{
int i;
int ret;
@@ -1138,7 +1142,7 @@ static int goodix_flash_read(struct goodix_ts_core *cd, u32 addr, u8 *buf, int l
checksum += p[i] | (p[i + 1] << 8);
head_info.checksum = checksum;
- ret = goodix_flash_cmd(cd, FLASH_CMD_R_START, FLASH_CMD_STATE_READY, 15);
+ ret = goodix_flash_cmd(FLASH_CMD_R_START, FLASH_CMD_STATE_READY, 15);
if (ret < 0) {
ts_err("failed enter flash read state");
goto read_end;
@@ -1151,7 +1155,7 @@ static int goodix_flash_read(struct goodix_ts_core *cd, u32 addr, u8 *buf, int l
goto read_end;
}
- ret = goodix_flash_cmd(cd, FLASH_CMD_RW_FINISH, FLASH_CMD_STATE_OKAY, 50);
+ ret = goodix_flash_cmd(FLASH_CMD_RW_FINISH, FLASH_CMD_STATE_OKAY, 50);
if (ret) {
ts_err("faild read flash ready state");
goto read_end;
@@ -1178,7 +1182,7 @@ static int goodix_flash_read(struct goodix_ts_core *cd, u32 addr, u8 *buf, int l
memcpy(buf, tmp_buf + sizeof(flash_head_info_t), len);
ret = 0;
read_end:
- goodix_flash_cmd(cd, 0x0C, 0, 0);
+ goodix_flash_cmd(0x0C, 0, 0);
return ret;
}
@@ -1219,27 +1223,15 @@ static const struct seq_operations seq_ops = {
static int driver_test_open(struct inode *inode, struct file *file)
{
- struct seq_file *seq_file;
- int ret;
-
- ret = seq_open(file, &seq_ops);
- if (ret)
- return ret;
- seq_file = (struct seq_file *)file->private_data;
- if (seq_file)
- seq_file->private = PDE_DATA(inode);
-
- mutex_lock(&goodix_devices.mutex);
- return 0;
+ return seq_open(file, &seq_ops);
}
static int driver_test_release(struct inode *inode, struct file *file)
{
- mutex_unlock(&goodix_devices.mutex);
return seq_release(inode, file);
}
-static void goodix_save_header(struct goodix_ts_core *cd)
+static void goodix_save_header(void)
{
int i;
bool total_result = true;
@@ -1473,7 +1465,7 @@ static void goodix_data_cal(s16 *data, size_t data_size, s16 *stat_result)
stat_result[2] = min;
}
-static void goodix_save_data(struct goodix_ts_core *cd)
+static void goodix_save_data(void)
{
int tx = cd->ic_info.parm.drv_num;
int rx = cd->ic_info.parm.sen_num;
@@ -1561,12 +1553,12 @@ static void goodix_save_data(struct goodix_ts_core *cd)
index += sprintf(&rbuf[index], "</DataRecord>\n");
}
-static void goodix_save_tail(struct goodix_ts_core *cd)
+static void goodix_save_tail(void)
{
index += sprintf(&rbuf[index], "</TESTLOG>\n");
}
-static void goodix_save_test_result(struct goodix_ts_core *cd, bool is_brief)
+static void goodix_save_test_result(bool is_brief)
{
if (is_brief) {
if (ts_test->item[GTP_CAP_TEST]) {
@@ -1600,9 +1592,9 @@ static void goodix_save_test_result(struct goodix_ts_core *cd, bool is_brief)
: "FAIL");
}
} else {
- goodix_save_header(cd);
- goodix_save_data(cd);
- goodix_save_tail(cd);
+ goodix_save_header();
+ goodix_save_data();
+ goodix_save_tail();
}
}
@@ -1732,7 +1724,7 @@ static int parse_csvfile(
return parse_valid_data(buf, size, ptr, data, rows);
}
-static int goodix_obtain_testlimits(struct goodix_ts_core *cd)
+static int goodix_obtain_testlimits(void)
{
const struct firmware *firmware = NULL;
struct device *dev = &cd->pdev->dev;
@@ -1855,7 +1847,7 @@ exit_free:
return ret;
}
-static int goodix_delta_test(struct goodix_ts_core *cd)
+static int goodix_delta_test(void)
{
int i, j;
int max_val;
@@ -1907,7 +1899,7 @@ static int goodix_delta_test(struct goodix_ts_core *cd)
return ret;
}
-static int goodix_open_test(struct goodix_ts_core *cd)
+static int goodix_open_test(void)
{
u8 *tmp_buf;
struct goodix_ts_cmd temp_cmd;
@@ -2007,7 +1999,7 @@ static int goodix_open_test(struct goodix_ts_core *cd)
ts_test->result[GTP_CAP_TEST] = TEST_NG;
}
- if (goodix_delta_test(cd) == 0)
+ if (goodix_delta_test() == 0)
ts_test->result[GTP_DELTA_TEST] = TEST_OK;
exit:
@@ -2015,7 +2007,7 @@ exit:
return ret;
}
-static int goodix_self_open_test(struct goodix_ts_core *cd)
+static int goodix_self_open_test(void)
{
u8 *tmp_buf;
struct goodix_ts_cmd temp_cmd;
@@ -2093,7 +2085,7 @@ exit:
return ret;
}
-static int goodix_noise_test(struct goodix_ts_core *cd)
+static int goodix_noise_test(void)
{
u8 *tmp_buf;
struct goodix_ts_cmd temp_cmd;
@@ -2176,19 +2168,19 @@ exit:
return ret;
}
-static int goodix_auto_test(struct goodix_ts_core *cd, bool is_brief)
+static int goodix_auto_test(bool is_brief)
{
struct goodix_ts_cmd temp_cmd;
int ret;
- ret = goodix_obtain_testlimits(cd);
+ ret = goodix_obtain_testlimits();
if (ret < 0) {
ts_err("obtain open test limits failed");
return ret;
}
cd->hw_ops->irq_enable(cd, false);
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
temp_cmd.len = 5;
temp_cmd.cmd = 0x64;
@@ -2198,7 +2190,7 @@ static int goodix_auto_test(struct goodix_ts_core *cd, bool is_brief)
ret = cd->hw_ops->send_cmd(cd, &temp_cmd);
if (ret < 0)
ts_err("enter test mode failed");
- goodix_open_test(cd);
+ goodix_open_test();
cd->hw_ops->reset(cd, 100);
}
@@ -2206,27 +2198,27 @@ static int goodix_auto_test(struct goodix_ts_core *cd, bool is_brief)
ret = cd->hw_ops->send_cmd(cd, &temp_cmd);
if (ret < 0)
ts_err("enter test mode failed");
- goodix_noise_test(cd);
+ goodix_noise_test();
cd->hw_ops->reset(cd, 100);
}
if (ts_test->item[GTP_SELFCAP_TEST]) {
- goodix_self_open_test(cd);
+ goodix_self_open_test();
cd->hw_ops->reset(cd, 100);
}
if (ts_test->item[GTP_SHORT_TEST]) {
- goodix_shortcircut_test(cd);
+ goodix_shortcircut_test();
cd->hw_ops->reset(cd, 100);
}
cd->hw_ops->irq_enable(cd, true);
- goodix_ts_esd_on(cd);
- goodix_save_test_result(cd, is_brief);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
+ goodix_save_test_result(is_brief);
return 0;
}
-static void goodix_auto_noise_test(struct goodix_ts_core *cd, u16 cnt, int threshold)
+static void goodix_auto_noise_test(u16 cnt, int threshold)
{
struct goodix_ts_cmd temp_cmd;
struct goodix_ts_cmd rb_cmd;
@@ -2253,7 +2245,7 @@ static void goodix_auto_noise_test(struct goodix_ts_core *cd, u16 cnt, int thres
8;
cd->hw_ops->irq_enable(cd, false);
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
restart:
temp_cmd.len = 0x07;
@@ -2333,10 +2325,10 @@ exit:
}
kfree(tmp_buf);
cd->hw_ops->irq_enable(cd, true);
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
}
-static int get_cap_data(struct goodix_ts_core *cd, uint8_t *type)
+static int get_cap_data(uint8_t *type)
{
struct goodix_ts_cmd temp_cmd;
int tx = cd->ic_info.parm.drv_num;
@@ -2370,7 +2362,7 @@ static int get_cap_data(struct goodix_ts_core *cd, uint8_t *type)
/* disable irq & close esd */
cd->hw_ops->irq_enable(cd, false);
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
if (strstr(type, CMD_GET_BASEDATA) ||
strstr(type, CMD_GET_SELF_BASEDATA)) {
@@ -2461,11 +2453,11 @@ exit:
cd->hw_ops->send_cmd(cd, &temp_cmd);
/* enable irq & esd */
cd->hw_ops->irq_enable(cd, true);
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
return ret;
}
-static void goodix_set_sense_mode(struct goodix_ts_core *cd, u8 val)
+static void goodix_set_sense_mode(u8 val)
{
struct goodix_ts_cmd temp_cmd;
@@ -2476,26 +2468,26 @@ static void goodix_set_sense_mode(struct goodix_ts_core *cd, u8 val)
/* normal mode */
index = sprintf(rbuf, "switch to coordinate mode\n");
cd->hw_ops->send_cmd(cd, &temp_cmd);
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
cd->hw_ops->irq_enable(cd, true);
atomic_set(&cd->suspended, 0);
} else if (val == 2) {
/* gesture mode */
index = sprintf(rbuf, "switch to gesture mode\n");
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
cd->hw_ops->gesture(cd, 0);
cd->hw_ops->irq_enable(cd, true);
atomic_set(&cd->suspended, 1);
} else {
/* sleep mode */
index = sprintf(rbuf, "switch to sleep mode\n");
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
cd->hw_ops->irq_enable(cd, false);
cd->hw_ops->suspend(cd);
}
}
-static void goodix_set_scan_mode(struct goodix_ts_core *cd, u8 val)
+static void goodix_set_scan_mode(u8 val)
{
struct goodix_ts_cmd temp_cmd;
@@ -2519,7 +2511,7 @@ static void goodix_set_scan_mode(struct goodix_ts_core *cd, u8 val)
cd->hw_ops->send_cmd(cd, &temp_cmd);
}
-static void goodix_get_scan_mode(struct goodix_ts_core *cd)
+static void goodix_get_scan_mode(void)
{
u8 status;
@@ -2541,7 +2533,7 @@ static void goodix_get_scan_mode(struct goodix_ts_core *cd)
}
}
-static void goodix_set_continue_mode(struct goodix_ts_core *cd, u8 val)
+static void goodix_set_continue_mode(u8 val)
{
struct goodix_ts_cmd temp_cmd;
@@ -2559,7 +2551,7 @@ static void goodix_set_continue_mode(struct goodix_ts_core *cd, u8 val)
cd->hw_ops->send_cmd(cd, &temp_cmd);
}
-static void goodix_read_config(struct goodix_ts_core *cd)
+static void goodix_read_config(void)
{
int ret;
u8 *cfg_buf;
@@ -2587,7 +2579,7 @@ exit:
kfree(cfg_buf);
}
-static void goodix_get_fw_status(struct goodix_ts_core *cd)
+static void goodix_get_fw_status(void)
{
u32 status_addr;
u32 noise_lv_addr;
@@ -2634,7 +2626,7 @@ static void goodix_get_fw_status(struct goodix_ts_core *cd)
index += sprintf(&rbuf[index], "noise-lv[%d]\n", val);
}
-static void goodix_set_highsense_mode(struct goodix_ts_core *cd, u8 val)
+static void goodix_set_highsense_mode(u8 val)
{
struct goodix_ts_cmd temp_cmd;
static bool flag = false;
@@ -2658,7 +2650,7 @@ static void goodix_set_highsense_mode(struct goodix_ts_core *cd, u8 val)
cd->hw_ops->send_cmd(cd, &temp_cmd);
}
-static void goodix_set_grip_data(struct goodix_ts_core *cd, u8 val)
+static void goodix_set_grip_data(u8 val)
{
struct goodix_ts_cmd temp_cmd;
@@ -2687,7 +2679,7 @@ static void goodix_set_grip_data(struct goodix_ts_core *cd, u8 val)
cd->hw_ops->send_cmd(cd, &temp_cmd);
}
-static void goodix_set_custom_mode(struct goodix_ts_core *cd, u8 type, u8 val)
+static void goodix_set_custom_mode(u8 type, u8 val)
{
struct goodix_ts_cmd temp_cmd;
@@ -2739,7 +2731,7 @@ static int obtain_param(char **buf)
return val;
}
-static int goodix_parse_gesture_param(struct goodix_ts_core *cd, u8 type, char **buf)
+static int goodix_parse_gesture_param(u8 type, char **buf)
{
if (type == GESTURE_STTW) {
gesture_param_st.length = sizeof(gesture_param_st);
@@ -2831,7 +2823,7 @@ static int goodix_parse_gesture_param(struct goodix_ts_core *cd, u8 type, char *
return 0;
}
-static void goodix_set_gesture_param(struct goodix_ts_core *cd, u8 type)
+static void goodix_set_gesture_param(u8 type)
{
struct goodix_ts_cmd temp_cmd;
u32 cmd_reg = cd->ic_info.misc.cmd_addr;
@@ -2895,29 +2887,18 @@ exit:
cd->hw_ops->send_cmd(cd, &temp_cmd);
}
-static void goodix_set_heatmap(struct goodix_ts_core *cd, int val)
+static void goodix_set_heatmap(int val)
{
struct goodix_ts_cmd temp_cmd;
cd->hw_ops->irq_enable(cd, false);
if (val == 0) {
index = sprintf(rbuf, "disable heatmap\n");
-/*
- * [GOOG]
- * Use goodix_update_heatmap() to do the heatmap process.
- kfree(cd->heatmap_buffer);
- cd->heatmap_buffer = NULL;
- */
temp_cmd.len = 5;
temp_cmd.cmd = 0xC9;
temp_cmd.data[0] = 0;
} else {
index = sprintf(rbuf, "enable heatmap\n");
-/*
- * [GOOG]
- * Use goodix_update_heatmap() to do the heatmap process.
- cd->heatmap_buffer = kzalloc(GOODIX_MAX_FRAMEDATA_LEN, GFP_KERNEL);
- */
temp_cmd.len = 5;
temp_cmd.cmd = 0xC9;
temp_cmd.data[0] = 1;
@@ -2926,7 +2907,7 @@ static void goodix_set_heatmap(struct goodix_ts_core *cd, int val)
cd->hw_ops->irq_enable(cd, true);
}
-static void goodix_get_self_compensation(struct goodix_ts_core *cd)
+static void goodix_get_self_compensation(void)
{
u8 *cfg;
u8 *cfg_buf;
@@ -2981,7 +2962,7 @@ exit:
kfree(cfg_buf);
}
-static void goodix_set_report_rate(struct goodix_ts_core *cd, int rate)
+static void goodix_set_report_rate(int rate)
{
struct goodix_ts_cmd temp_cmd;
@@ -2994,12 +2975,12 @@ static void goodix_set_report_rate(struct goodix_ts_core *cd, int rate)
}
#define DUMP_AREA1_ADDR 0x10194
-#define DUMP_AREA1_LEN 132
+#define DUMP_AREA1_LEN 132
#define DUMP_AREA2_ADDR 0x10400
-#define DUMP_AREA2_LEN 596
+#define DUMP_AREA2_LEN 596
#define DUMP_AREA3_ADDR 0x10308
-#define DUMP_AREA3_LEN 64
-static void goodix_get_dump_log(struct goodix_ts_core *cd)
+#define DUMP_AREA3_LEN 64
+static void goodix_get_dump_log(void)
{
u8 buf[600];
int i;
@@ -3029,7 +3010,7 @@ static void goodix_get_dump_log(struct goodix_ts_core *cd)
}
}
-static void goodix_get_stylus_data(struct goodix_ts_core *cd)
+static void goodix_get_stylus_data(void)
{
struct goodix_stylus_data stylus_data;
u8 temp_buf[40] = { 0 };
@@ -3054,7 +3035,7 @@ static void goodix_get_stylus_data(struct goodix_ts_core *cd)
/* disable irq & close esd */
cd->hw_ops->irq_enable(cd, false);
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
/* clean touch event flag */
ret = cd->hw_ops->write(cd, flag_addr, temp_buf, 1);
@@ -3145,10 +3126,10 @@ static void goodix_get_stylus_data(struct goodix_ts_core *cd)
exit:
/* enable irq & esd */
cd->hw_ops->irq_enable(cd, true);
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
}
-static void goodix_force_update(struct goodix_ts_core *cd)
+static void goodix_force_update(void)
{
int i;
int ret;
@@ -3162,7 +3143,7 @@ static void goodix_force_update(struct goodix_ts_core *cd)
if (ret < 0)
ts_err("not found valid config");
- ret = goodix_do_fw_update(cd,
+ ret = goodix_do_fw_update(cd->ic_configs[CONFIG_TYPE_NORMAL],
UPDATE_MODE_BLOCK | UPDATE_MODE_FORCE |
UPDATE_MODE_SRC_REQUEST);
if (ret < 0)
@@ -3171,7 +3152,7 @@ static void goodix_force_update(struct goodix_ts_core *cd)
index = sprintf(rbuf, "%s: OK\n", CMD_FW_UPDATE);
}
-static void goodix_set_freq_index(struct goodix_ts_core *cd, int freq)
+static void goodix_set_freq_index(int freq)
{
struct goodix_ts_cmd temp_cmd;
@@ -3183,7 +3164,7 @@ static void goodix_set_freq_index(struct goodix_ts_core *cd, int freq)
cd->hw_ops->send_cmd(cd, &temp_cmd);
}
-static void goodix_disable_coor_filter(struct goodix_ts_core *cd, int val)
+static void goodix_disable_coor_filter(int val)
{
struct goodix_ts_cmd temp_cmd;
@@ -3194,11 +3175,9 @@ static void goodix_disable_coor_filter(struct goodix_ts_core *cd, int val)
cd->hw_ops->send_cmd(cd, &temp_cmd);
}
-static ssize_t driver_test_write(struct file *file, const char __user *buf,
- size_t count, loff_t *pos)
+static ssize_t driver_test_write(
+ struct file *file, const char __user *buf, size_t count, loff_t *pos)
{
- struct seq_file *seq_file = (struct seq_file *)file->private_data;
- struct goodix_ts_core *cd = (struct goodix_ts_core *)seq_file->private;
struct goodix_fw_version fw_ver;
struct goodix_ic_info ic_info;
char *p = wbuf;
@@ -3218,7 +3197,6 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("copy from user failed");
return count;
}
- p[strlen(p) - 1] = 0;
vfree(rbuf);
rbuf = NULL;
@@ -3229,7 +3207,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
if (!strncmp(p, CMD_FW_UPDATE, strlen(CMD_FW_UPDATE))) {
rbuf = vzalloc(SHORT_SIZE);
- goodix_force_update(cd);
+ goodix_force_update();
goto exit;
}
@@ -3254,7 +3232,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- ret = get_cap_data(cd, CMD_GET_RAWDATA);
+ ret = get_cap_data(CMD_GET_RAWDATA);
if (ret < 0) {
index = sprintf(rbuf, "%s: NG\n", CMD_GET_RAWDATA);
}
@@ -3267,7 +3245,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- ret = get_cap_data(cd, CMD_GET_BASEDATA);
+ ret = get_cap_data(CMD_GET_BASEDATA);
if (ret < 0) {
index = sprintf(rbuf, "%s: NG\n", CMD_GET_BASEDATA);
}
@@ -3280,7 +3258,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- ret = get_cap_data(cd, CMD_GET_DIFFDATA);
+ ret = get_cap_data(CMD_GET_DIFFDATA);
if (ret < 0) {
index = sprintf(rbuf, "%s: NG\n", CMD_GET_DIFFDATA);
}
@@ -3293,7 +3271,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- ret = get_cap_data(cd, CMD_GET_SELF_RAWDATA);
+ ret = get_cap_data(CMD_GET_SELF_RAWDATA);
if (ret < 0) {
index = sprintf(rbuf, "%s: NG\n", CMD_GET_SELF_RAWDATA);
}
@@ -3306,7 +3284,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- ret = get_cap_data(cd, CMD_GET_SELF_DIFFDATA);
+ ret = get_cap_data(CMD_GET_SELF_DIFFDATA);
if (ret < 0) {
index = sprintf(
rbuf, "%s: NG\n", CMD_GET_SELF_DIFFDATA);
@@ -3320,7 +3298,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- ret = get_cap_data(cd, CMD_GET_SELF_BASEDATA);
+ ret = get_cap_data(CMD_GET_SELF_BASEDATA);
if (ret < 0) {
index = sprintf(
rbuf, "%s: NG\n", CMD_GET_SELF_BASEDATA);
@@ -3468,11 +3446,11 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
goto exit;
}
if (cmd_val == 0) {
- goodix_ts_esd_off(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
index = sprintf(
rbuf, "%s: disable OK\n", CMD_SET_ESD_ENABLE);
} else {
- goodix_ts_esd_on(cd);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
index = sprintf(
rbuf, "%s: enable OK\n", CMD_SET_ESD_ENABLE);
}
@@ -3526,7 +3504,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_test->item[GTP_DELTA_TEST] = true;
ts_test->item[GTP_SELFCAP_TEST] = true;
ts_test->item[GTP_SHORT_TEST] = true;
- goodix_auto_test(cd, true);
+ goodix_auto_test(true);
goto exit;
}
@@ -3547,7 +3525,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- ret = get_cap_data(cd, CMD_GET_TX_FREQ);
+ ret = get_cap_data(CMD_GET_TX_FREQ);
if (ret < 0) {
index = sprintf(rbuf, "%s: NG\n", CMD_GET_TX_FREQ);
}
@@ -3583,7 +3561,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_SENSE_MODE);
goto exit;
}
- goodix_set_sense_mode(cd, cmd_val);
+ goodix_set_sense_mode(cmd_val);
goto exit;
}
@@ -3609,7 +3587,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
goto exit;
}
ts_test->item[GTP_NOISE_TEST] = true;
- goodix_auto_test(cd, false);
+ goodix_auto_test(false);
goto exit;
}
@@ -3637,7 +3615,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- goodix_auto_noise_test(cd, cmd_val, cmd_val2);
+ goodix_auto_noise_test(cmd_val, cmd_val2);
goto exit;
}
@@ -3649,7 +3627,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
}
mutex_lock(&cd->cmd_lock);
usleep_range(6000, 6100);
- ret = goodix_flash_read(cd, 0x1F301, &id, 1);
+ ret = goodix_flash_read(0x1F301, &id, 1);
mutex_unlock(&cd->cmd_lock);
if (ret < 0)
index = sprintf(rbuf, "%s: NG\n", CMD_GET_PACKAGE_ID);
@@ -3667,7 +3645,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
}
mutex_lock(&cd->cmd_lock);
usleep_range(6000, 6100);
- ret = goodix_flash_read(cd, 0x1F314, &id, 1);
+ ret = goodix_flash_read(0x1F314, &id, 1);
mutex_unlock(&cd->cmd_lock);
if (ret < 0)
index = sprintf(rbuf, "%s: NG\n", CMD_GET_MCU_ID);
@@ -3698,7 +3676,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_SCAN_MODE);
goto exit;
}
- goodix_set_scan_mode(cd, cmd_val);
+ goodix_set_scan_mode(cmd_val);
goto exit;
}
@@ -3708,7 +3686,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- goodix_get_scan_mode(cd);
+ goodix_get_scan_mode();
goto exit;
}
@@ -3734,7 +3712,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_CONTINUE_MODE);
goto exit;
}
- goodix_set_continue_mode(cd, cmd_val);
+ goodix_set_continue_mode(cmd_val);
goto exit;
}
@@ -3771,7 +3749,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
}
ts_test->item[GTP_CAP_TEST] = true;
ts_test->freq = cmd_val2;
- goodix_auto_test(cd, false);
+ goodix_auto_test(false);
goto exit;
}
@@ -3787,7 +3765,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
goto exit;
}
ts_test->item[GTP_SELFCAP_TEST] = true;
- goodix_auto_test(cd, false);
+ goodix_auto_test(false);
goto exit;
}
@@ -3803,7 +3781,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
goto exit;
}
ts_test->item[GTP_SHORT_TEST] = true;
- goodix_auto_test(cd, false);
+ goodix_auto_test(false);
goto exit;
}
@@ -3813,7 +3791,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- goodix_read_config(cd);
+ goodix_read_config();
goto exit;
}
@@ -3823,7 +3801,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- goodix_get_fw_status(cd);
+ goodix_get_fw_status();
goto exit;
}
@@ -3850,7 +3828,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_HIGHSENSE_MODE);
goto exit;
}
- goodix_set_highsense_mode(cd, cmd_val);
+ goodix_set_highsense_mode(cmd_val);
goto exit;
}
@@ -3871,7 +3849,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_GRIP_DATA);
goto exit;
}
- goodix_set_grip_data(cd, cmd_val);
+ goodix_set_grip_data(cmd_val);
goto exit;
}
@@ -3892,7 +3870,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_GRIP_MODE);
goto exit;
}
- goodix_set_custom_mode(cd, GRIP_FUNC, cmd_val);
+ goodix_set_custom_mode(GRIP_FUNC, cmd_val);
goto exit;
}
@@ -3913,7 +3891,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_PALM_MODE);
goto exit;
}
- goodix_set_custom_mode(cd, PALM_FUNC, cmd_val);
+ goodix_set_custom_mode(PALM_FUNC, cmd_val);
goto exit;
}
@@ -3934,7 +3912,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_NOISE_MODE);
goto exit;
}
- goodix_set_custom_mode(cd, NOISE_FUNC, cmd_val);
+ goodix_set_custom_mode(NOISE_FUNC, cmd_val);
goto exit;
}
@@ -3955,7 +3933,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_WATER_MODE);
goto exit;
}
- goodix_set_custom_mode(cd, WATER_FUNC, cmd_val);
+ goodix_set_custom_mode(WATER_FUNC, cmd_val);
goto exit;
}
@@ -3971,8 +3949,8 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_ST_PARAM);
goto exit;
}
- goodix_parse_gesture_param(cd, GESTURE_STTW, &p);
- goodix_set_gesture_param(cd, GESTURE_STTW);
+ goodix_parse_gesture_param(GESTURE_STTW, &p);
+ goodix_set_gesture_param(GESTURE_STTW);
goto exit;
}
@@ -3988,8 +3966,8 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_LP_PARAM);
goto exit;
}
- goodix_parse_gesture_param(cd, GESTURE_LPTW, &p);
- goodix_set_gesture_param(cd, GESTURE_LPTW);
+ goodix_parse_gesture_param(GESTURE_LPTW, &p);
+ goodix_set_gesture_param(GESTURE_LPTW);
goto exit;
}
@@ -4010,7 +3988,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_HEATMAP);
goto exit;
}
- goodix_set_heatmap(cd, cmd_val);
+ goodix_set_heatmap(cmd_val);
goto exit;
}
@@ -4020,7 +3998,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
ts_err("failed to alloc rbuf");
goto exit;
}
- goodix_get_self_compensation(cd);
+ goodix_get_self_compensation();
goto exit;
}
@@ -4041,27 +4019,25 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_REPORT_RATE);
goto exit;
}
- goodix_set_report_rate(cd, cmd_val);
+ goodix_set_report_rate(cmd_val);
goto exit;
}
if (!strncmp(p, CMD_GET_DUMP_LOG, strlen(CMD_GET_DUMP_LOG))) {
rbuf = vzalloc(LARGE_SIZE);
- if (!rbuf) {
- ts_err("failed to alloc rbuf");
- goto exit;
- }
- goodix_get_dump_log(cd);
+ goodix_get_dump_log();
+ goto exit;
+ }
+ if (!strncmp(p, CMD_GET_STYLUS_DATA, strlen(CMD_GET_STYLUS_DATA))) {
+ rbuf = vzalloc(LARGE_SIZE);
+ goodix_get_stylus_data();
goto exit;
}
+
if (!strncmp(p, CMD_GET_STYLUS_DATA, strlen(CMD_GET_STYLUS_DATA))) {
rbuf = vzalloc(LARGE_SIZE);
- if (!rbuf) {
- ts_err("failed to alloc rbuf");
- goto exit;
- }
- goodix_get_stylus_data(cd);
+ goodix_get_stylus_data();
goto exit;
}
@@ -4078,7 +4054,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_SET_FREQ_INDEX);
goto exit;
}
- goodix_set_freq_index(cd, cmd_val);
+ goodix_set_freq_index(cmd_val);
goto exit;
}
@@ -4095,7 +4071,7 @@ static ssize_t driver_test_write(struct file *file, const char __user *buf,
CMD_DISABLE_FILTER);
goto exit;
}
- goodix_disable_coor_filter(cd, cmd_val);
+ goodix_disable_coor_filter(cmd_val);
goto exit;
}
@@ -4162,8 +4138,7 @@ static const struct file_operations cmd_list_ops = {
};
#endif
-/* [GOOG] */
-int driver_test_selftest(struct goodix_ts_core *cd, char *buf)
+int driver_test_selftest(char* buf)
{
int ret = 0;
@@ -4192,7 +4167,7 @@ int driver_test_selftest(struct goodix_ts_core *cd, char *buf)
ts_test->item[GTP_DELTA_TEST] = true;
ts_test->item[GTP_SELFCAP_TEST] = true;
ts_test->item[GTP_SHORT_TEST] = true;
- goodix_auto_test(cd, true);
+ goodix_auto_test(true);
strlcpy(buf, rbuf, PAGE_SIZE);
@@ -4204,24 +4179,22 @@ int driver_test_proc_init(struct goodix_ts_core *core_data)
{
struct proc_dir_entry *proc_entry;
- proc_entry = proc_create_data(
- "driver_test", 0660, core_data->proc_dir_entry, &driver_test_ops, core_data);
+ proc_entry = proc_create(
+ "goodix_ts/driver_test", 0660, NULL, &driver_test_ops);
if (!proc_entry) {
- ts_err("failed to create proc driver_test");
- return -ENODEV;
+ ts_err("failed to create proc entry");
+ return -ENOMEM;
}
proc_entry =
- proc_create("cmd_list", 0440, core_data->proc_dir_entry, &cmd_list_ops);
- if (!proc_entry) {
- ts_err("failed to create proc cmd_list");
- return -ENODEV;
- }
+ proc_create("goodix_ts/cmd_list", 0440, NULL, &cmd_list_ops);
+
+ cd = core_data;
return 0;
}
-void driver_test_proc_remove(struct goodix_ts_core *core_data)
+void driver_test_proc_remove(void)
{
- remove_proc_entry("cmd_list", core_data->proc_dir_entry);
- remove_proc_entry("driver_test", core_data->proc_dir_entry);
+ remove_proc_entry("goodix_ts/cmd_list", NULL);
+ remove_proc_entry("goodix_ts/driver_test", NULL);
}
diff --git a/goodix_ts_tools.c b/goodix_ts_tools.c
index f648ba0..5fb175f 100644
--- a/goodix_ts_tools.c
+++ b/goodix_ts_tools.c
@@ -20,14 +20,15 @@
#include <linux/ioctl.h>
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/wait.h>
-#define GOODIX_TOOLS_NAME "gtp_tools"
-#define GOODIX_TOOLS_VER_MAJOR 1
-#define GOODIX_TOOLS_VER_MINOR 0
+#define GOODIX_TOOLS_NAME "gtp_tools"
+#define GOODIX_TOOLS_VER_MAJOR 1
+#define GOODIX_TOOLS_VER_MINOR 0
static const u16 goodix_tools_ver =
((GOODIX_TOOLS_VER_MAJOR << 8) + (GOODIX_TOOLS_VER_MINOR));
@@ -48,9 +49,33 @@ static const u16 goodix_tools_ver =
(_IOW(GOODIX_TS_IOC_MAGIC, 10, u8) & NEGLECT_SIZE_MASK)
#define MAX_BUF_LENGTH (16 * 1024)
+#define IRQ_FALG (0x01 << 2)
#define I2C_MSG_HEAD_LEN 20
+/*
+ * struct goodix_tools_dev - goodix tools device struct
+ * @ts_core: The core data struct of ts driver
+ * @ops_mode: represent device work mode
+ * @rawdiffcmd: Set slave device into rawdata mode
+ * @normalcmd: Set slave device into normal mode
+ * @wq: Wait queue struct use in synchronous data read
+ * @mutex: Protect goodix_tools_dev
+ * @in_use: device in use
+ */
+struct goodix_tools_dev {
+ struct goodix_ts_core *ts_core;
+ struct list_head head;
+ unsigned int ops_mode;
+ struct goodix_ts_cmd rawdiffcmd, normalcmd;
+ wait_queue_head_t wq;
+ bool is_clean_flag;
+ struct delayed_work sync_work;
+ struct mutex mutex;
+ atomic_t in_use;
+ struct goodix_ext_module module;
+} *goodix_tools_dev;
+
/* read data asynchronous,
* success return data length, otherwise return < 0
*/
@@ -60,9 +85,7 @@ static int async_read(struct goodix_tools_dev *dev, void __user *arg)
int ret = 0;
u32 reg_addr, length;
u8 i2c_msg_head[I2C_MSG_HEAD_LEN];
- struct goodix_ts_core *ts_core =
- container_of(dev, struct goodix_ts_core, tools_dev);
- const struct goodix_ts_hw_ops *hw_ops = ts_core->hw_ops;
+ const struct goodix_ts_hw_ops *hw_ops = dev->ts_core->hw_ops;
ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
if (ret)
@@ -82,7 +105,7 @@ static int async_read(struct goodix_tools_dev *dev, void __user *arg)
return -ENOMEM;
}
- if (hw_ops->read(ts_core, reg_addr, databuf, length)) {
+ if (hw_ops->read(dev->ts_core, reg_addr, databuf, length)) {
ret = -EBUSY;
ts_err("Read i2c failed");
goto err_out;
@@ -160,8 +183,7 @@ static int async_write(struct goodix_tools_dev *dev, void __user *arg)
int ret = 0;
u32 reg_addr, length;
u8 i2c_msg_head[I2C_MSG_HEAD_LEN];
- struct goodix_ts_core *ts_core =
- container_of(dev, struct goodix_ts_core, tools_dev);
+ struct goodix_ts_core *ts_core = dev->ts_core;
const struct goodix_ts_hw_ops *hw_ops = ts_core->hw_ops;
ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN);
@@ -197,6 +219,9 @@ static int async_write(struct goodix_tools_dev *dev, void __user *arg)
ret = length;
}
+ if (reg_addr == ts_core->ic_info.misc.touch_data_addr)
+ dev->is_clean_flag = true;
+
err_out:
kfree(databuf);
return ret;
@@ -229,6 +254,29 @@ static int init_cfg_data(struct goodix_ic_config *cfg, void __user *arg)
return 0;
}
+static void goodix_ctrl_sync_work(struct work_struct *work)
+{
+ struct goodix_ts_core *cd = goodix_tools_dev->ts_core;
+ static int cnt;
+
+ if (atomic_read(&goodix_tools_dev->in_use) == 0)
+ return;
+
+ if (cd->tools_ctrl_sync && !goodix_tools_dev->is_clean_flag) {
+ cnt++;
+ if (cnt >= 2) {
+ cnt = 0;
+ cd->tools_ctrl_sync = false;
+ ts_info("restore tools sync flag to 0");
+ }
+ } else {
+ cnt = 0;
+ }
+
+ goodix_tools_dev->is_clean_flag = false;
+ schedule_delayed_work(&goodix_tools_dev->sync_work, 5 * HZ);
+}
+
/**
* goodix_tools_ioctl - ioctl implementation
*
@@ -242,15 +290,15 @@ static long goodix_tools_ioctl(
{
int ret = 0;
struct goodix_tools_dev *dev = filp->private_data;
- struct goodix_ts_core *ts_core =
- container_of(dev, struct goodix_ts_core, tools_dev);
+ struct goodix_ts_core *ts_core;
const struct goodix_ts_hw_ops *hw_ops;
struct goodix_ic_config *temp_cfg = NULL;
- if (ts_core == NULL) {
+ if (dev->ts_core == NULL) {
ts_err("Tools module not register");
return -EINVAL;
}
+ ts_core = dev->ts_core;
hw_ops = ts_core->hw_ops;
if (_IOC_TYPE(cmd) != GOODIX_TS_IOC_MAGIC) {
@@ -262,9 +310,15 @@ static long goodix_tools_ioctl(
case GTP_IRQ_ENABLE:
if (arg == 1) {
hw_ops->irq_enable(ts_core, true);
+ mutex_lock(&dev->mutex);
+ dev->ops_mode |= IRQ_FALG;
+ mutex_unlock(&dev->mutex);
ts_info("IRQ enabled");
} else if (arg == 0) {
hw_ops->irq_enable(ts_core, false);
+ mutex_lock(&dev->mutex);
+ dev->ops_mode &= ~IRQ_FALG;
+ mutex_unlock(&dev->mutex);
ts_info("IRQ disabled");
} else {
ts_info("Irq aready set with, arg = %ld", arg);
@@ -273,9 +327,9 @@ static long goodix_tools_ioctl(
break;
case GTP_ESD_ENABLE:
if (arg == 0)
- goodix_ts_esd_off(ts_core);
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
else
- goodix_ts_esd_on(ts_core);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
break;
case GTP_DEV_RESET:
hw_ops->reset(ts_core, GOODIX_NORMAL_RESET_DELAY_MS);
@@ -292,6 +346,7 @@ static long goodix_tools_ioctl(
ret = -ENOMEM;
goto err_out;
}
+
ret = init_cfg_data(temp_cfg, (void __user *)arg);
if (!ret && hw_ops->send_config) {
ret = hw_ops->send_config(
@@ -358,49 +413,59 @@ static long goodix_tools_compat_ioctl(
}
#endif
-static struct goodix_ts_core *core_data_locate(int minor)
+static int goodix_tools_open(struct inode *inode, struct file *filp)
{
- struct goodix_device_resource *res, *next;
+ int ret = 0;
- if (!list_empty(&goodix_devices.list)) {
- list_for_each_entry_safe(res, next, &goodix_devices.list, list) {
- if (res->core_data.tools_dev.miscdev.minor == minor)
- return &res->core_data;
- }
+ ts_info("try open tool");
+ /* Only the first time open device need to register module */
+ ret = goodix_register_ext_module_no_wait(&goodix_tools_dev->module);
+ if (ret) {
+ ts_info("failed register to core module");
+ return -EFAULT;
}
+ ts_info("success open tools");
+ goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL);
+ filp->private_data = goodix_tools_dev;
+ atomic_set(&goodix_tools_dev->in_use, 1);
+ schedule_delayed_work(&goodix_tools_dev->sync_work, 5 * HZ);
+ return 0;
+}
- return NULL;
+static int goodix_tools_release(struct inode *inode, struct file *filp)
+{
+ int ret = 0;
+ /* when the last close this dev node unregister the module */
+ goodix_tools_dev->ts_core->tools_ctrl_sync = false;
+ atomic_set(&goodix_tools_dev->in_use, 0);
+ cancel_delayed_work_sync(&goodix_tools_dev->sync_work);
+ goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL);
+ ret = goodix_unregister_ext_module(&goodix_tools_dev->module);
+ return ret;
}
-static int goodix_tools_open(struct inode *inode, struct file *filp)
+static int goodix_tools_module_init(
+ struct goodix_ts_core *core_data, struct goodix_ext_module *module)
{
- struct goodix_ts_core *cd = core_data_locate(iminor(inode));
+ struct goodix_tools_dev *tools_dev = module->priv_data;
- if (!cd) {
- ts_err("can't find core data");
+ if (core_data)
+ tools_dev->ts_core = core_data;
+ else
return -ENODEV;
- }
- goodix_ts_esd_off(cd);
- cd->tools_dev.is_open = true;
- filp->private_data = &cd->tools_dev;
- ts_info("success open tools");
return 0;
}
-static int goodix_tools_release(
- struct inode *inode, struct file *filp)
+static int goodix_tools_module_exit(
+ struct goodix_ts_core *core_data, struct goodix_ext_module *module)
{
- struct goodix_ts_core *cd = core_data_locate(iminor(inode));
-
- if (!cd) {
- ts_err("can't find core data");
- return -ENODEV;
+ struct goodix_tools_dev *tools_dev = module->priv_data;
+ ts_debug("tools module unregister");
+ if (atomic_read(&tools_dev->in_use)) {
+ ts_err("tools module busy, please close it then retry");
+ return -EBUSY;
}
- /* when the last close this dev node unregister the module */
- cd->tools_dev.is_open = false;
- cd->tools_ctrl_sync = false;
- goodix_ts_esd_on(cd);
return 0;
}
@@ -414,21 +479,46 @@ static const struct file_operations goodix_tools_fops = {
#endif
};
+static struct miscdevice goodix_tools_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = GOODIX_TOOLS_NAME,
+ .fops = &goodix_tools_fops,
+};
+
+static struct goodix_ext_module_funcs goodix_tools_module_funcs = {
+ .init = goodix_tools_module_init,
+ .exit = goodix_tools_module_exit,
+};
+
/**
* goodix_tools_init - init goodix tools device and register a miscdevice
*
* return: 0 success, else failed
*/
-int goodix_tools_init(struct goodix_ts_core *core_data)
+int goodix_tools_init(void)
{
int ret;
- struct goodix_tools_dev *tools_dev = &core_data->tools_dev;
- sprintf(tools_dev->name, "%s.%d", GOODIX_TOOLS_NAME, core_data->pdev->id);
- tools_dev->miscdev.minor = MISC_DYNAMIC_MINOR;
- tools_dev->miscdev.name = tools_dev->name;
- tools_dev->miscdev.fops = &goodix_tools_fops;
- ret = misc_register(&tools_dev->miscdev);
+ goodix_tools_dev = kzalloc(sizeof(struct goodix_tools_dev), GFP_KERNEL);
+ if (goodix_tools_dev == NULL) {
+ ts_err("Memory allco err");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&goodix_tools_dev->head);
+ goodix_tools_dev->ops_mode = 0;
+ goodix_tools_dev->ops_mode |= IRQ_FALG;
+ init_waitqueue_head(&goodix_tools_dev->wq);
+ mutex_init(&goodix_tools_dev->mutex);
+ atomic_set(&goodix_tools_dev->in_use, 0);
+
+ goodix_tools_dev->module.funcs = &goodix_tools_module_funcs;
+ goodix_tools_dev->module.name = GOODIX_TOOLS_NAME;
+ goodix_tools_dev->module.priv_data = goodix_tools_dev;
+ goodix_tools_dev->module.priority = EXTMOD_PRIO_DBGTOOL;
+ INIT_DELAYED_WORK(&goodix_tools_dev->sync_work, goodix_ctrl_sync_work);
+
+ ret = misc_register(&goodix_tools_miscdev);
if (ret)
ts_err("Debug tools miscdev register failed");
else
@@ -437,10 +527,9 @@ int goodix_tools_init(struct goodix_ts_core *core_data)
return ret;
}
-void goodix_tools_exit(struct goodix_ts_core *core_data)
+void goodix_tools_exit(void)
{
- struct goodix_tools_dev *tools_dev = &core_data->tools_dev;
-
- misc_deregister(&tools_dev->miscdev);
+ misc_deregister(&goodix_tools_miscdev);
+ kfree(goodix_tools_dev);
ts_info("Debug tools miscdev exit");
}
diff --git a/goodix_ts_utils.c b/goodix_ts_utils.c
index c3fc33e..7649759 100644
--- a/goodix_ts_utils.c
+++ b/goodix_ts_utils.c
@@ -69,7 +69,7 @@ int checksum_cmp(const u8 *data, int size, int mode)
u32 cal_checksum = 0;
u32 r_checksum = 0;
u32 i;
- bool is_valid = !is_risk_data(data, size); /* [GOOG] */
+ bool is_valid = !is_risk_data(data, size);
if (mode == CHECKSUM_MODE_U8_LE) {
if (size < 2)
@@ -123,11 +123,7 @@ u32 goodix_get_file_config_id(u8 *ic_config)
return le32_to_cpup((__le32 *)&ic_config[CONFIG_ID_OFFSET]);
}
-/*
- * matrix transpose:
- * [GOOG]
- * Add 'dest' as optional target(pa/2221748).
- */
+/* matrix transpose */
void goodix_rotate_abcd2cbad(int tx, int rx, s16 *src, s16 *dest)
{
s16 *temp_buf = dest;
@@ -136,14 +132,10 @@ void goodix_rotate_abcd2cbad(int tx, int rx, s16 *src, s16 *dest)
s16 *curr;
int index_org = 0;
- /*
- * [GOOG]
- * If no 'dest' assign, 'src' will be overwrote.
- */
if (dest == NULL) {
temp_buf = kcalloc(size, sizeof(s16), GFP_KERNEL);
if (!temp_buf) {
- ts_err("%s: malloc failed!\n", __func__);
+ ts_err("malloc failed");
return;
}
}
@@ -160,7 +152,6 @@ void goodix_rotate_abcd2cbad(int tx, int rx, s16 *src, s16 *dest)
memcpy(src, temp_buf, size * sizeof(s16));
kfree(temp_buf);
}
- /*~[GOOG] */
}
/* get ic type */