diff options
author | Super Liu <supercjliu@google.com> | 2023-03-09 09:28:31 +0000 |
---|---|---|
committer | Super Liu <supercjliu@google.com> | 2023-03-29 06:30:39 +0000 |
commit | 901977ca79d2e3292fb33bc9a0729141ff2f2c87 (patch) | |
tree | 9c293b88b6ac29b9cbd96847623a246cc1ae86d1 | |
parent | 253ad573c516c2d46424d98ca2cdae07d2c8f555 (diff) | |
download | goodix_touch-901977ca79d2e3292fb33bc9a0729141ff2f2c87.tar.gz |
touch/goodix: Import driver v1.2.5
Bug: 272408020
Change-Id: I6ce72a2c502cdcaa85059fdb8e2bbdb28f6b9835
Signed-off-by: Super Liu <supercjliu@google.com>
-rw-r--r-- | goodix_brl_fwupdate.c | 466 | ||||
-rw-r--r-- | goodix_brl_hw.c | 257 | ||||
-rw-r--r-- | goodix_brl_i2c.c | 50 | ||||
-rw-r--r-- | goodix_brl_spi.c | 166 | ||||
-rw-r--r-- | goodix_cfg_bin.c | 2 | ||||
-rw-r--r-- | goodix_ts_core.c | 872 | ||||
-rw-r--r-- | goodix_ts_core.h | 292 | ||||
-rw-r--r-- | goodix_ts_gesture.c | 345 | ||||
-rw-r--r-- | goodix_ts_inspect.c | 20 | ||||
-rw-r--r-- | goodix_ts_proc.c | 333 | ||||
-rw-r--r-- | goodix_ts_tools.c | 195 | ||||
-rw-r--r-- | goodix_ts_utils.c | 15 |
12 files changed, 1093 insertions, 1920 deletions
diff --git a/goodix_brl_fwupdate.c b/goodix_brl_fwupdate.c index 0fb81e6..f7136fa 100644 --- a/goodix_brl_fwupdate.c +++ b/goodix_brl_fwupdate.c @@ -137,67 +137,12 @@ struct update_info_t update_brd = { ENABLE_MISCTL_BRD, }; -/** - * 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; +enum compare_status { + COMPARE_EQUAL = 0, + COMPARE_NOCODE, + COMPARE_PIDMISMATCH, + COMPARE_FW_NOTEQUAL, + COMPARE_CFG_NOTEQUAL, }; #pragma pack(1) @@ -218,90 +163,6 @@ 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 @@ -311,26 +172,24 @@ static int goodix_reg_read( * return: 0 - OK, < 0 - error */ /* sizeof(length) + sizeof(checksum) */ - -static int goodix_parse_firmware(struct firmware_data *fw_data) +static int goodix_parse_firmware(struct goodix_ts_core *cd, + 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 = goodix_fw_update_ctrl.core_data->bus->ic_type; + int ic_type = cd->bus->ic_type; int subsys_info_offset = - goodix_fw_update_ctrl.update_info->subsys_info_offset; - int header_size = goodix_fw_update_ctrl.update_info->header_size; + 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; int r = 0; fw_summary = &fw_data->fw_summary; /* copy firmware head info */ - if (goodix_fw_update_ctrl.mode & UPDATE_MODE_SRC_SYSFS) - firmware = fw_data->fw_sysfs; - else - firmware = fw_data->firmware; + firmware = fw_data->firmware; if (firmware->size < subsys_info_offset) { ts_err("Invalid firmware size:%zu", firmware->size); @@ -407,10 +266,10 @@ static int goodix_parse_firmware(struct firmware_data *fw_data) 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); - goodix_fw_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); + cd->update_ctrl.ic_config = one_binary_cfg; } } @@ -442,33 +301,29 @@ err_size: static int goodix_fw_version_compare(struct fw_update_ctrl *fwu_ctrl) { int ret = 0; - struct goodix_fw_version fw_version; + 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 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 */ - 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)) { + if (!memcmp(ic_ver->rom_pid, GOODIX_NOCODE, 6) || + !memcmp(ic_ver->patch_pid, GOODIX_NOCODE, 6)) { ts_info("there is no code in the chip"); return COMPARE_NOCODE; } - if (memcmp(fw_version.patch_pid, fw_summary->fw_pid, FW_PID_LEN)) { - ts_err("Product ID mismatch:%s != %s", fw_version.patch_pid, + if (memcmp(ic_ver->patch_pid, fw_summary->fw_pid, FW_PID_LEN)) { + ts_err("Product ID mismatch:%s != %s", ic_ver->patch_pid, fw_summary->fw_pid); return COMPARE_PIDMISMATCH; } - ret = memcmp(fw_version.patch_vid, fw_summary->fw_vid, FW_VID_LEN); + ret = memcmp(ic_ver->patch_vid, fw_summary->fw_vid, FW_VID_LEN); if (ret) { ts_info("active firmware version:%*ph", FW_VID_LEN, - fw_version.patch_vid); + ic_ver->patch_vid); ts_info("firmware file version: %*ph", FW_VID_LEN, fw_summary->fw_vid); return COMPARE_FW_NOTEQUAL; @@ -479,10 +334,8 @@ 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); - 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, + 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, file_cfg_id); return COMPARE_CFG_NOTEQUAL; } @@ -502,7 +355,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( +static int goodix_reg_write_confirm(struct goodix_ts_core *cd, unsigned int addr, unsigned char *data, unsigned int len) { u8 *cfm = NULL; @@ -518,11 +371,11 @@ static int goodix_reg_write_confirm( } for (i = 0; i < GOODIX_BUS_RETRY_TIMES; i++) { - r = goodix_reg_write(addr, data, len); + r = cd->hw_ops->write(cd, addr, data, len); if (r < 0) goto exit; - r = goodix_reg_read(addr, cfm, len); + r = cd->hw_ops->read(cd, addr, cfm, len); if (r < 0) goto exit; @@ -547,11 +400,11 @@ exit: * @fw_data: firmware data * return 0 ok, <0 error */ -static int goodix_load_isp(struct firmware_data *fw_data) +static int goodix_load_isp(struct goodix_ts_core *cd, struct firmware_data *fw_data) { struct goodix_fw_version isp_fw_version; struct fw_subsys_info *fw_isp; - u32 isp_ram_reg = goodix_fw_update_ctrl.update_info->isp_ram_reg; + u32 isp_ram_reg = cd->update_ctrl.update_info->isp_ram_reg; u8 reg_val[8] = { 0x00 }; int r; @@ -559,8 +412,8 @@ static int goodix_load_isp(struct firmware_data *fw_data) fw_isp = &fw_data->fw_summary.subsys[0]; ts_info("Loading ISP start"); - r = goodix_reg_write_confirm( - isp_ram_reg, (u8 *)fw_isp->data, fw_isp->size); + r = goodix_reg_write_confirm(cd, isp_ram_reg, + (u8 *)fw_isp->data, fw_isp->size); if (r < 0) { ts_err("Loading ISP error"); return r; @@ -570,17 +423,16 @@ static int goodix_load_isp(struct firmware_data *fw_data) /* SET BOOT OPTION TO 0X55 */ memset(reg_val, 0x55, 8); - r = goodix_reg_write_confirm(HW_REG_CPU_RUN_FROM, reg_val, 8); + r = goodix_reg_write_confirm(cd, 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); - if (goodix_fw_update_reset(100)) - ts_err("reset abnormal"); + cd->hw_ops->reset(cd, 100); /*check isp state */ - if (get_fw_version_info(&isp_fw_version)) { + if (cd->hw_ops->read_version(cd, &isp_fw_version)) { ts_err("failed read isp version"); return -2; } @@ -606,6 +458,8 @@ 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; @@ -613,18 +467,17 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl) /*reset IC*/ ts_info("firmware update, reset"); - if (goodix_fw_update_reset(5)) - ts_err("reset abnormal"); + hw_ops->reset(cd, 5); retry = 100; /* Hold cpu*/ do { reg_val[0] = 0x01; reg_val[1] = 0x00; - 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); + 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); 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)) { @@ -641,20 +494,20 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl) ts_info("Success hold CPU"); /* enable misctl clock */ - if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_D || - fwu_ctrl->core_data->bus->ic_type == IC_TYPE_NOTTINGHAM) - goodix_reg_write(misctl_reg, (u8 *)&enable_misctl_val, 4); + 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); else - goodix_reg_write(misctl_reg, (u8 *)&enable_misctl_val, 1); + hw_ops->write(cd, misctl_reg, (u8 *)&enable_misctl_val, 1); ts_info("enable misctl clock"); - if (fwu_ctrl->core_data->bus->ic_type == IC_TYPE_BERLIN_A) { + if (cd->bus->ic_type == IC_TYPE_BERLIN_A) { /* open ESD_KEY */ retry = 20; do { reg_val[0] = 0x95; - r = goodix_reg_write(ESD_KEY_REG, reg_val, 1); - r |= goodix_reg_read(ESD_KEY_REG, temp_buf, 1); + r = hw_ops->write(cd, ESD_KEY_REG, reg_val, 1); + r |= hw_ops->read(cd, ESD_KEY_REG, temp_buf, 1); if (!r && temp_buf[0] == 0x01) break; usleep_range(1000, 1100); @@ -670,11 +523,11 @@ static int goodix_update_prepare(struct fw_update_ctrl *fwu_ctrl) /* disable watch dog */ reg_val[0] = 0x00; - r = goodix_reg_write(watch_dog_reg, reg_val, 1); + r = hw_ops->write(cd, watch_dog_reg, reg_val, 1); ts_info("disable watch dog"); /* load ISP code and run form isp */ - r = goodix_load_isp(&fwu_ctrl->fw_data); + r = goodix_load_isp(cd, &fwu_ctrl->fw_data); if (r < 0) ts_err("Failed load and run isp"); @@ -684,17 +537,18 @@ 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_flash_cmd *flash_cmd) +static int goodix_send_flash_cmd(struct goodix_ts_core *cd, + struct goodix_flash_cmd *flash_cmd) { int i, ret, retry; struct goodix_flash_cmd tmp_cmd; - u32 flash_cmd_reg = goodix_fw_update_ctrl.update_info->flash_cmd_reg; + u32 flash_cmd_reg = cd->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 = goodix_reg_write( - flash_cmd_reg, flash_cmd->buf, sizeof(flash_cmd->buf)); + ret = cd->hw_ops->write(cd, flash_cmd_reg, + flash_cmd->buf, sizeof(flash_cmd->buf)); if (ret) { ts_err("failed send flash cmd %d", ret); return ret; @@ -702,8 +556,8 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd) retry = 5; for (i = 0; i < retry; i++) { - ret = goodix_reg_read( - flash_cmd_reg, tmp_cmd.buf, sizeof(tmp_cmd.buf)); + ret = cd->hw_ops->read(cd, 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); @@ -721,8 +575,8 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd) msleep(50); retry = 20; for (i = 0; i < retry; i++) { - ret = goodix_reg_read( - flash_cmd_reg, tmp_cmd.buf, sizeof(tmp_cmd.buf)); + ret = cd->hw_ops->read(cd, 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"); @@ -760,16 +614,17 @@ static int goodix_send_flash_cmd(struct goodix_flash_cmd *flash_cmd) } } -static int goodix_flash_package( - u8 subsys_type, u8 *pkg, u32 flash_addr, u16 pkg_len) +static int goodix_flash_package(struct goodix_ts_core *cd, + u8 subsys_type, u8 *pkg, + u32 flash_addr, u16 pkg_len) { int ret, retry; struct goodix_flash_cmd flash_cmd; - u32 isp_buffer_reg = goodix_fw_update_ctrl.update_info->isp_buffer_reg; + u32 isp_buffer_reg = cd->update_ctrl.update_info->isp_buffer_reg; retry = 2; do { - ret = goodix_reg_write(isp_buffer_reg, pkg, pkg_len); + ret = cd->hw_ops->write(cd, isp_buffer_reg, pkg, pkg_len); if (ret < 0) { ts_err("Failed to write firmware packet"); return ret; @@ -786,7 +641,7 @@ static int goodix_flash_package( goodix_append_checksum( &(flash_cmd.buf[2]), 9, CHECKSUM_MODE_U8_LE); - ret = goodix_send_flash_cmd(&flash_cmd); + ret = goodix_send_flash_cmd(cd, &flash_cmd); if (!ret) { ts_info("success write package to 0x%05X, len %d", flash_addr, pkg_len - 4); @@ -807,7 +662,8 @@ static int goodix_flash_package( * @subsys: subsystem information * return: 0 ok, < 0 error */ -static int goodix_flash_subsystem(struct fw_subsys_info *subsys) +static int goodix_flash_subsystem(struct goodix_ts_core *cd, + struct fw_subsys_info *subsys) { u32 data_size, offset; u32 total_size; @@ -840,7 +696,7 @@ static int goodix_flash_subsystem(struct fw_subsys_info *subsys) goodix_append_checksum( fw_packet, data_size, CHECKSUM_MODE_U16_LE); - r = goodix_flash_package(subsys->type, fw_packet, + r = goodix_flash_package(cd, subsys->type, fw_packet, subsys_base_addr + offset, data_size + 4); if (r) { ts_err("failed flash to 0x%05X,size:%u bytes", @@ -884,7 +740,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(&subsys_cfg); + r = goodix_flash_subsystem(fw_ctrl->core_data, &subsys_cfg); if (r) { ts_err("failed flash config with ISP, %d", r); return r; @@ -895,7 +751,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_x); + r = goodix_flash_subsystem(fw_ctrl->core_data, fw_x); if (r == 0) { ts_info("--- End flash subsystem[%d]: OK ---", i); i++; @@ -922,10 +778,24 @@ exit_flash: */ static int goodix_update_finish(struct fw_update_ctrl *fwu_ctrl) { + struct goodix_ts_core *cd = fwu_ctrl->core_data; int ret; - if (goodix_fw_update_reset(100)) - ts_err("reset abnormal"); + /* 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; + } + ret = goodix_fw_version_compare(fwu_ctrl); if (ret == COMPARE_EQUAL || ret == COMPARE_CFG_NOTEQUAL) return 0; @@ -946,7 +816,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->fw_data); + ret = goodix_parse_firmware(fwu_ctrl->core_data, &fwu_ctrl->fw_data); if (ret < 0) return ret; @@ -1008,7 +878,10 @@ static ssize_t update_en_store(struct device *dev, { int ret = 0; int mode = 0; - struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl; + 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; if (!buf || count <= 0) { ts_err("invalid params"); @@ -1035,7 +908,7 @@ static ssize_t update_en_store(struct device *dev, return -EINVAL; } - ret = goodix_do_fw_update(NULL, mode); + ret = goodix_do_fw_update(cd, mode); if (!ret) { ts_info("success do update work"); return count; @@ -1044,36 +917,18 @@ static ssize_t update_en_store(struct device *dev, return -EINVAL; } -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 */ +/* + * [GOOG] + * 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 fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl; + 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; char str[GOODIX_MAX_STR_LABEL_LEN] = { 0 }; int r = -EINVAL; @@ -1099,57 +954,51 @@ 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_attrs[] = { +static struct attribute *goodix_fwu_attrs[] = { &dev_attr_update_en.attr, &dev_attr_result.attr, - NULL, -}; - -static BIN_ATTR_WO(fwimage, 0); -static struct bin_attribute *goodix_bin_attrs[] = { - &bin_attr_fwimage, - NULL, + 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; } - fw_ctrl->attrs.attrs = goodix_attrs; - fw_ctrl->attrs.bin_attrs = goodix_bin_attrs; + /* [GOOG] */ + fw_ctrl->attrs.attrs = goodix_fwu_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(void) +static void goodix_fw_sysfs_remove(struct goodix_ts_core *cd) { - struct fw_update_ctrl *fw_ctrl = &goodix_fw_update_ctrl; + struct fw_update_ctrl *fw_ctrl = &cd->update_ctrl; - sysfs_remove_group(fw_ctrl->kobj, &fw_ctrl->attrs); - kobject_put(fw_ctrl->kobj); + sysfs_remove_group(fw_ctrl->kobj, &fw_ctrl->attrs); /* [GOOG] */ } /** @@ -1201,6 +1050,7 @@ 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; @@ -1210,7 +1060,10 @@ static int goodix_fw_update_thread(void *data) mutex_lock(&fwu_ctrl->mutex); ts_debug("notify update start"); - goodix_ts_blocking_notify(NOTIFY_FWUPDATE_START, NULL); + if (cd->init_stage >= CORE_INIT_STAGE2) { + cd->hw_ops->irq_enable(cd, 0); + goodix_ts_esd_off(cd); + } if (fwu_ctrl->mode & UPDATE_MODE_SRC_REQUEST) { ts_info("Firmware request update starts"); @@ -1218,21 +1071,6 @@ 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; @@ -1244,13 +1082,8 @@ static int goodix_fw_update_thread(void *data) r = goodix_fw_update_proc(fwu_ctrl); /* clean */ - 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) { + 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); @@ -1258,23 +1091,25 @@ 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_ic_config *ic_config, int mode) +int goodix_do_fw_update(struct goodix_ts_core *cd, int mode) { struct task_struct *fwu_thrd; - struct fw_update_ctrl *fwu_ctrl = &goodix_fw_update_ctrl; + struct fw_update_ctrl *fwu_ctrl = &cd->update_ctrl; int ret; if (!fwu_ctrl->initialized) { @@ -1283,7 +1118,7 @@ int goodix_do_fw_update(struct goodix_ic_config *ic_config, int mode) } fwu_ctrl->mode = mode; - fwu_ctrl->ic_config = ic_config; + fwu_ctrl->ic_config = cd->ic_configs[CONFIG_TYPE_NORMAL]; ts_debug("fw update mode 0x%x", mode); if (fwu_ctrl->mode & UPDATE_MODE_BLOCK) { ret = goodix_fw_update_thread(fwu_ctrl); @@ -1309,37 +1144,34 @@ int goodix_fw_update_init(struct goodix_ts_core *core_data) return -ENODEV; } - mutex_init(&goodix_fw_update_ctrl.mutex); - goodix_fw_update_ctrl.core_data = core_data; - goodix_fw_update_ctrl.mode = 0; + mutex_init(&core_data->update_ctrl.mutex); + core_data->update_ctrl.core_data = core_data; + core_data->update_ctrl.mode = 0; - strlcpy(goodix_fw_update_ctrl.fw_name, core_data->board_data.fw_name, - sizeof(goodix_fw_update_ctrl.fw_name)); + strlcpy(core_data->update_ctrl.fw_name, core_data->board_data.fw_name, + sizeof(core_data->update_ctrl.fw_name)); - ret = goodix_fw_sysfs_init(core_data, &goodix_fw_update_ctrl); + ret = goodix_fw_sysfs_init(core_data, &core_data->update_ctrl); if (ret) { ts_err("failed create fwupate sysfs node"); return ret; } if (core_data->bus->ic_type == IC_TYPE_BERLIN_A) - goodix_fw_update_ctrl.update_info = &update_bra; + core_data->update_ctrl.update_info = &update_bra; else if (core_data->bus->ic_type == IC_TYPE_BERLIN_B) - goodix_fw_update_ctrl.update_info = &update_brb; + core_data->update_ctrl.update_info = &update_brb; else - goodix_fw_update_ctrl.update_info = &update_brd; + core_data->update_ctrl.update_info = &update_brd; - goodix_fw_update_ctrl.initialized = 1; + core_data->update_ctrl.initialized = 1; return 0; } -void goodix_fw_update_uninit(void) +void goodix_fw_update_uninit(struct goodix_ts_core *core_data) { - if (!goodix_fw_update_ctrl.initialized) + if (!core_data->update_ctrl.initialized) return; - - 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); + goodix_fw_sysfs_remove(core_data); + core_data->update_ctrl.initialized = 0; + mutex_destroy(&core_data->update_ctrl.mutex); } diff --git a/goodix_brl_hw.c b/goodix_brl_hw.c index acfd294..cb073e1 100644 --- a/goodix_brl_hw.c +++ b/goodix_brl_hw.c @@ -79,6 +79,10 @@ 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( @@ -114,11 +118,6 @@ 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--) { @@ -850,7 +849,7 @@ static int convert_ic_info(struct goodix_ic_info *info, const u8 *data) return 0; } -static void print_ic_info(struct goodix_ic_info *ic_info) +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; @@ -975,8 +974,6 @@ 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) { @@ -1019,6 +1016,7 @@ 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 @@ -1028,69 +1026,42 @@ 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 int point_struct_len; -static void goodix_parse_finger( - struct goodix_touch_data *touch_data, u8 *buf, int touch_num) +static void goodix_parse_finger(struct goodix_ts_core *cd, + struct goodix_touch_data *touch_data, + u8 *buf, int id) { - 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; + 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; } static unsigned int goodix_pen_btn_code[] = { BTN_STYLUS, BTN_STYLUS2 }; static void goodix_parse_pen( - struct goodix_pen_data *pen_data, u8 *buf, int touch_num) + struct goodix_pen_data *pen_data, u8 *event_head, u8 *buf) { - unsigned int id = 0; u8 cur_key_map = 0; - u8 *coor_data; int16_t x_angle, y_angle; int i; - 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; - } + 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; cur_key_map = (buf[3] & 0x0F) >> 1; for (i = 0; i < GOODIX_MAX_PEN_KEY; i++) { @@ -1101,7 +1072,7 @@ static void goodix_parse_pen( } } -static int goodix_update_heatmap(struct goodix_ts_core *cd, uint8_t *event_data) +static int goodix_update_heatmap(struct goodix_ts_core *cd, u8 *event_data) { struct goodix_ic_info_misc *misc = &cd->ic_info.misc; int tx = cd->ic_info.parm.drv_num; @@ -1130,113 +1101,90 @@ 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 = 0; - static u8 pre_finger_num; - static u8 pre_pen_num; - - if (event_data->touches > GOODIX_MAX_TOUCH) { - ts_debug("invalid touch num %d", event_data->touches); - return -EINVAL; - } + u8 point_type; + int tid; + int i; - 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; + 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; } } - } - - goodix_update_heatmap(cd, (u8 *)event_data); - - ts_event->fp_flag = event_data->fp_flag; - - 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; + ret = checksum_cmp(event_data->data, + checksum_len + 2, + CHECKSUM_MODE_U8_LE); + if (ret) { + ts_debug("touch data checksum error"); + return -EINVAL; } } - if (event_data->status_changed) - ts_event->event_type |= EVENT_STATUS; + goodix_update_heatmap(cd, event_data->data); /* [GOOG] */ - /* process custom info */ - if (event_data->custom_coor_info_flag) - ts_debug("TODO add custom info process function"); + 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; 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)); @@ -1245,9 +1193,32 @@ static int brl_event_handler( ts_event->clear_count1 = event_data->clear_count1; ts_event->clear_count2 = event_data->clear_count2; /* read status event */ - if (event_data->status_changed) + if (event_data->status_changed) { + ts_event->event_type |= EVENT_STATUS; 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, @@ -1256,7 +1227,7 @@ static int brl_event_handler( 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) @@ -1292,9 +1263,7 @@ static int brl_event_handler( 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; - if (event_data->status_changed) - ts_event->event_type |= EVENT_STATUS; + ts_event->event_type |= EVENT_GESTURE; ts_event->gesture_data.gesture_type = gesture->gesture_type; ts_event->gesture_data.touches = gesture->touches; memcpy(ts_event->gesture_data.data, gesture->data, @@ -1394,7 +1363,7 @@ static int brld_get_cap_data( /* disable irq & close esd */ brl_irq_enable(cd, false); - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); info->buff[0] = rx; info->buff[1] = tx; @@ -1441,7 +1410,7 @@ exit: brl_send_cmd(cd, &temp_cmd); /* enable irq & esd */ brl_irq_enable(cd, true); - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); return ret; } @@ -1472,7 +1441,7 @@ static int brl_get_capacitance_data( /* disable irq & close esd */ brl_irq_enable(cd, false); - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); /* switch rawdata mode */ temp_cmd.cmd = GOODIX_CMD_RAWDATA; @@ -1535,7 +1504,7 @@ exit: brl_write(cd, flag_addr, &val, 1); /* enable irq & esd */ brl_irq_enable(cd, true); - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); return ret; } diff --git a/goodix_brl_i2c.c b/goodix_brl_i2c.c index 60018a6..b1409f2 100644 --- a/goodix_brl_i2c.c +++ b/goodix_brl_i2c.c @@ -25,8 +25,6 @@ #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) @@ -156,15 +154,10 @@ 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"); @@ -172,52 +165,45 @@ 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, &goodix_i2c_bus); + ret = goodix_get_ic_type(client->dev.of_node, &dev_res->bus); if (ret < 0) return ret; - 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->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_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; + dev_res->pdev.name = GOODIX_CORE_DRIVER_NAME; + dev_res->pdev.id = dev_res->id; + dev_res->pdev.num_resources = 0; /* register platform device, then the goodix_ts_core * module will probe the touch device. */ - ret = platform_device_register(goodix_pdev); + ret = platform_device_register(&dev_res->pdev); if (ret) { ts_err("failed register goodix platform device, %d", ret); goto err_pdev; } ts_info("i2c probe out"); - return ret; + return 0; err_pdev: - kfree(goodix_pdev); - goodix_pdev = NULL; + kfree(dev_res); 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 b7d82da..e3421b9 100644 --- a/goodix_brl_spi.c +++ b/goodix_brl_spi.c @@ -36,9 +36,6 @@ #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 @@ -51,6 +48,8 @@ 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; @@ -58,12 +57,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(&goodix_spi_bus.mutex); + mutex_lock(&bus->mutex); if (buf_len <= SPI_PREALLOC_RX_BUF_SIZE && buf_len <= SPI_PREALLOC_TX_BUF_SIZE) { - rx_buf = goodix_spi_bus.rx_buf; - tx_buf = goodix_spi_bus.tx_buf; + rx_buf = bus->rx_buf; + tx_buf = bus->tx_buf; memset(tx_buf, 0, buf_len); } else { rx_buf = kzalloc(buf_len, GFP_KERNEL); @@ -108,13 +107,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 != goodix_spi_bus.tx_buf) + if (tx_buf != bus->tx_buf) kfree(tx_buf); err_alloc_tx_buf: - if (rx_buf != goodix_spi_bus.rx_buf) + if (rx_buf != bus->rx_buf) kfree(rx_buf); err_alloc_rx_buf: - mutex_unlock(&goodix_spi_bus.mutex); + mutex_unlock(&bus->mutex); return ret; } @@ -122,6 +121,8 @@ 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; @@ -129,16 +130,15 @@ static int goodix_spi_read(struct device *dev, unsigned int addr, int ret = 0; int buf_len = SPI_READ_PREFIX_LEN - 1 + len; - if (goodix_spi_bus.dma_mode_enabled && buf_len >= 64) { + if (bus->dma_mode_enabled && buf_len >= 64) buf_len = ALIGN(buf_len, 4); - } - mutex_lock(&goodix_spi_bus.mutex); + mutex_lock(&bus->mutex); if (buf_len <= SPI_PREALLOC_RX_BUF_SIZE && buf_len <= SPI_PREALLOC_TX_BUF_SIZE) { - rx_buf = goodix_spi_bus.rx_buf; - tx_buf = goodix_spi_bus.tx_buf; + rx_buf = bus->rx_buf; + tx_buf = bus->tx_buf; memset(tx_buf, 0, buf_len); } else { rx_buf = kzalloc(buf_len, GFP_KERNEL); @@ -173,7 +173,8 @@ 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 (goodix_spi_bus.dma_mode_enabled) xfers.bits_per_word = buf_len >= 64 ? 32 : 8; + if (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) { @@ -183,32 +184,37 @@ 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 != goodix_spi_bus.tx_buf) + if (tx_buf != bus->tx_buf) kfree(tx_buf); err_alloc_tx_buf: - if (rx_buf != goodix_spi_bus.rx_buf) + if (rx_buf != bus->rx_buf) kfree(rx_buf); err_alloc_rx_buf: - mutex_unlock(&goodix_spi_bus.mutex); + mutex_unlock(&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 (goodix_spi_bus.dma_mode_enabled && buf_len >= 64) { + if (bus->dma_mode_enabled && buf_len >= 64) buf_len = ALIGN(buf_len, 4); - } if (buf_len <= SPI_PREALLOC_TX_BUF_SIZE) { - tx_buf = goodix_spi_bus.tx_buf; + tx_buf = bus->tx_buf; } else { tx_buf = kzalloc(buf_len, GFP_KERNEL); if (!tx_buf) { @@ -220,7 +226,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(&goodix_spi_bus.mutex); + mutex_lock(&bus->mutex); /*spi_read tx_buf format: 0xF1 + addr(4bytes) + data*/ tx_buf[0] = SPI_READ_FLAG; @@ -236,12 +242,13 @@ 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 (goodix_spi_bus.dma_mode_enabled) xfers.bits_per_word = buf_len >= 64 ? 32 : 8; + if (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(&goodix_spi_bus.mutex); + mutex_unlock(&bus->mutex); if (ret < 0) { ts_err("spi transfer error:%d", ret); @@ -249,7 +256,7 @@ static int goodix_spi_read_fast(struct device *dev, unsigned int addr, } err_spi_transfer: - if (tx_buf != goodix_spi_bus.tx_buf) + if (tx_buf != bus->tx_buf) kfree(tx_buf); return ret; } @@ -266,18 +273,19 @@ 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 (goodix_spi_bus.dma_mode_enabled && buf_len >= 64) { + if (bus->dma_mode_enabled && buf_len >= 64) buf_len = ALIGN(buf_len, 4); - } if (buf_len <= SPI_PREALLOC_TX_BUF_SIZE) { - tx_buf = goodix_spi_bus.tx_buf; + tx_buf = bus->tx_buf; } else { tx_buf = kzalloc(buf_len, GFP_KERNEL); if (!tx_buf) { @@ -289,7 +297,7 @@ static int goodix_spi_write(struct device *dev, unsigned int addr, spi_message_init(&spi_msg); memset(&xfers, 0, sizeof(xfers)); - mutex_lock(&goodix_spi_bus.mutex); + mutex_lock(&bus->mutex); tx_buf[0] = SPI_WRITE_FLAG; tx_buf[1] = (addr >> 24) & 0xFF; @@ -300,28 +308,24 @@ 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 (goodix_spi_bus.dma_mode_enabled) xfers.bits_per_word = buf_len >= 64 ? 32 : 8; + if (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(&goodix_spi_bus.mutex); + mutex_unlock(&bus->mutex); if (ret < 0) ts_err("spi transfer error:%d", ret); - if (tx_buf != goodix_spi_bus.tx_buf) + if (tx_buf != 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"); @@ -329,7 +333,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; + spi->rt = true; /* [GOOG] */ ret = spi_setup(spi); if (ret) { @@ -337,83 +341,71 @@ 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, &goodix_spi_bus); + ret = goodix_get_ic_type(spi->dev.of_node, &dev_res->bus); if (ret < 0) - return ret; + goto err_get_ic_type; - 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; + 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; } else { - goodix_spi_bus.read = goodix_spi_read; - goodix_spi_bus.read_fast = goodix_spi_read_fast; + dev_res->bus.read = goodix_spi_read; + dev_res->bus.read_fast = goodix_spi_read_fast; } - goodix_spi_bus.write = goodix_spi_write; + dev_res->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; - } - goodix_spi_bus.tx_buf = kzalloc(SPI_PREALLOC_TX_BUF_SIZE, GFP_KERNEL); - if (!goodix_spi_bus.tx_buf) { + /* [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) { ret = -ENOMEM; - goto err_alloc_tx_buf; + goto err_pdev; } + mutex_init(&dev_res->bus.mutex); - mutex_init(&goodix_spi_bus.mutex); - - goodix_spi_bus.dma_mode_enabled = false; + dev_res->bus.dma_mode_enabled = false; #ifdef CONFIG_GOOG_TOUCH_INTERFACE - 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"); + 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"); #endif - /* 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; + // platform device init + dev_res->pdev.name = GOODIX_CORE_DRIVER_NAME; + dev_res->pdev.id = dev_res->id; + dev_res->pdev.num_resources = 0; /* register platform device, then the goodix_ts_core * module will probe the touch device. */ - ret = platform_device_register(goodix_pdev); + ret = platform_device_register(&dev_res->pdev); if (ret) { ts_err("failed register goodix platform device, %d", ret); - goto err_register_platform_device; + goto err_pdev; } ts_info("spi probe out"); return 0; -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); - +err_pdev: + kfree(dev_res->bus.rx_buf); + kfree(dev_res->bus.tx_buf); +err_get_ic_type: + kfree(dev_res); ts_info("spi probe out, %d", ret); return ret; } static int goodix_spi_remove(struct spi_device *spi) { - platform_device_unregister(goodix_pdev); + /* goodix_ts_core_exit() will unregister device(s) */ + // platform_device_unregister(dev_res->pdev); return 0; } diff --git a/goodix_cfg_bin.c b/goodix_cfg_bin.c index f7fef30..ab24e6a 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(200); + msleep(300); } 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 120c4f5..20c317d 100644 --- a/goodix_ts_core.c +++ b/goodix_ts_core.c @@ -31,257 +31,60 @@ // #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_module goodix_modules; -int core_module_prob_sate = CORE_MODULE_UNPROBED; +struct goodix_device_manager goodix_devices; -static const struct dev_pm_ops dev_pm_ops; +static const struct dev_pm_ops dev_pm_ops; /* [GOOG] */ -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) +static void goodix_device_manager_init(void) { - 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"); + if (goodix_devices.initialized) return; - } - - if (__do_register_ext_module(module)) - ts_err("failed register module: %s", module->name); - else - ts_info("success register module: %s", module->name); + goodix_devices.initialized = true; + INIT_LIST_HEAD(&goodix_devices.list); + mutex_init(&goodix_devices.mutex); } -static void goodix_core_module_init(void) +static void goodix_device_manager_exit(void) { - if (goodix_modules.initialized) - return; - goodix_modules.initialized = true; - INIT_LIST_HEAD(&goodix_modules.head); - mutex_init(&goodix_modules.mutex); -} - -/** - * 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); -} - -/** - * 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) -{ - struct goodix_ext_module *ext_module, *next; - bool found = false; - - if (!module) - return -EINVAL; - - if (!goodix_modules.initialized) - return -EINVAL; - - if (!goodix_modules.core_data) - return -ENODEV; + struct goodix_device_resource *res, *next; - 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; - } + if (!list_empty(&goodix_devices.list)) { + list_for_each_entry_safe(res, next, &goodix_devices.list, list) { + platform_device_unregister(&res->pdev); + kfree(res); } - } 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 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) +int goodix_device_register(struct goodix_device_resource *device) { - 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 }; + if (!device) + return -ENXIO; -static struct kobj_type goodix_ext_ktype = { - .release = goodix_ext_sysfs_release, - .sysfs_ops = &goodix_ext_ops, -}; + 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); -struct kobj_type *goodix_get_default_ktype(void) -{ - return &goodix_ext_ktype; + return 0; } -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; -} +static int goodix_send_ic_config(struct goodix_ts_core *cd, int type); /* 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; @@ -670,13 +473,15 @@ 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_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); else - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); return count; } @@ -706,35 +511,19 @@ 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) { - if (len > sizeof(goodix_ble_data.freq)) { + struct goodix_ble_data *ble_data = &cd->ble_data; + + if (len > sizeof(ble_data->freq)) { ts_err("pen freq data exceed limit"); return -EINVAL; } - 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); + 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); sysfs_notify(&cd->pdev->dev.kobj, NULL, "pen_freq"); ts_debug("send pen freq hop event"); return 0; @@ -744,11 +533,14 @@ 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) { - 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); + 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); } /* debug level store */ @@ -757,12 +549,13 @@ 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); - goodix_ble_data.freq[0] = 0xC0; - goodix_ble_data.freq[1] = 1; - goodix_ble_data.freq[2] = pen_freq & 0xFF; + ble_data->freq[0] = 0xC0; + ble_data->freq[1] = 1; + ble_data->freq[2] = pen_freq & 0xFF; sysfs_notify(&core_data->pdev->dev.kobj, NULL, "pen_freq"); return count; @@ -772,18 +565,20 @@ 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(goodix_ble_data.hogp)) { + if (count < sizeof(ble_data->hogp)) { ts_err("data count to short"); return -EINVAL; } - 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); + mutex_lock(&ble_data->lock); + memcpy(ble_data->hogp, buf, sizeof(ble_data->hogp)); + ble_data->hogp_ready = 1; + mutex_unlock(&ble_data->lock); - tmp_prs = (struct goodix_hid_hogp *)goodix_ble_data.hogp; + tmp_prs = (struct goodix_hid_hogp *)ble_data->hogp; ts_debug("set ble pen data: %d, key %x", tmp_prs->pressure, tmp_prs->key); return count; @@ -841,6 +636,7 @@ 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) { @@ -907,10 +703,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_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); ts_info("set sense ON"); } else { - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); cd->hw_ops->irq_enable(cd, false); cd->hw_ops->suspend(cd); ts_info("set sense OFF"); @@ -969,8 +765,8 @@ static int get_mutual_sensor_data( cmd->buffer = (u8 *)cd->mutual_data; cmd->size = tx * rx * sizeof(uint16_t); } else { - /* close esd */ - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + /* disable esd */ + goodix_ts_esd_off(cd); ret = -EINVAL; if (cmd->type == GTI_SENSOR_DATA_TYPE_MS_DIFF) { @@ -985,9 +781,8 @@ static int get_mutual_sensor_data( cmd->buffer = (u8 *)cd->mutual_data_manual; cmd->size = tx * rx * sizeof(uint16_t); } - /* enable esd */ - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); } return ret; } @@ -1006,7 +801,7 @@ static int get_self_sensor_data( } else { /* disable irq & close esd */ cd->hw_ops->irq_enable(cd, false); - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); ret = -EINVAL; if (cmd->type == GTI_SENSOR_DATA_TYPE_SS_DIFF) { @@ -1024,7 +819,7 @@ static int get_self_sensor_data( /* enable irq & esd */ cd->hw_ops->irq_enable(cd, true); - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); } return ret; } @@ -1188,8 +983,10 @@ 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(cmd->buffer); + return driver_test_selftest(cd, cmd->buffer); } static int gti_get_context_driver(void *private_data, @@ -1207,6 +1004,7 @@ static int gti_set_report_rate(void *private_data, } #endif +/*~[GOOG] */ /* prosfs create */ static int rawdata_proc_show(struct seq_file *m, void *v) @@ -1257,8 +1055,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)) @@ -1279,78 +1077,51 @@ 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; - int ret = 0; + char proc_node[32] = {0}; + int ret = 0; /* [GOOG] */ - proc_entry = proc_mkdir("goodix_ts", NULL); - if (proc_entry == NULL) { - ts_err("failed to create proc entry: goodix_ts"); - return -ENOMEM; - } + sprintf(proc_node, "goodix_ts.%d", 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"); + core_data->proc_dir_entry = proc_mkdir(proc_node, NULL); + if (!core_data->proc_dir_entry) + 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); 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/driver_test"); + ts_err("failed to create proc entry: goodix_ts.%d/driver_test", dev_id); ret = -ENOMEM; goto err_create_driver; } - return ret; + + return 0; err_create_driver: - remove_proc_entry("goodix_ts/tp_capacitance_data", NULL); + remove_proc_entry("tp_capacitance_data", core_data->proc_dir_entry); err_create_data: - remove_proc_entry("goodix_ts", NULL); + remove_proc_entry(proc_node, NULL); return ret; } static void goodix_ts_procfs_exit(struct goodix_ts_core *core_data) { - driver_test_proc_remove(); - remove_proc_entry("goodix_ts/tp_capacitance_data", NULL); - remove_proc_entry("goodix_ts", NULL); -} + int dev_id = core_data->pdev->id; + char proc_node[32] = {0}; -/* 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); -} + sprintf(proc_node, "goodix_ts.%d", dev_id); -/** - * 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; + driver_test_proc_remove(core_data); + remove_proc_entry("tp_capacitance_data", core_data->proc_dir_entry); + remove_proc_entry(proc_node, NULL); } #if IS_ENABLED(CONFIG_OF) @@ -1619,8 +1390,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; @@ -1635,21 +1406,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, pen_data->coords.tool_type, 1); + input_report_key(dev, BTN_TOOL_PEN, 1); input_report_abs(dev, ABS_X, pen_data->coords.x); input_report_abs(dev, ABS_Y, pen_data->coords.y); - 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; + mutex_lock(&ble_data->lock); + if (ble_data->hogp_ready) { + hogp = (struct goodix_hid_hogp *)ble_data->hogp; + cd->pen_pressure = hogp->pressure; ts_debug("update pen pressure from ble %d", - pen_pressure); + cd->pen_pressure); } - goodix_ble_data.hogp_ready = 0; - mutex_unlock(&goodix_ble_data.lock); + ble_data->hogp_ready = 0; + mutex_unlock(&ble_data->lock); - if (pen_data->coords.p && pen_pressure) - pen_data->coords.p = pen_pressure; + if (pen_data->coords.p && cd->pen_pressure) + pen_data->coords.p = cd->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); @@ -1670,9 +1441,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); - pen_pressure = 0; + cd->pen_pressure = 0; input_report_key(dev, BTN_TOUCH, 0); - input_report_key(dev, pen_data->coords.tool_type, 0); + input_report_key(dev, BTN_TOOL_PEN, 0); } /* report pen button */ for (i = 0; i < GOODIX_MAX_PEN_KEY; i++) { @@ -1850,9 +1621,8 @@ 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( - NULL, UPDATE_MODE_FORCE | UPDATE_MODE_BLOCK | - UPDATE_MODE_SRC_REQUEST); + ret = goodix_do_fw_update(cd, 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)); @@ -1949,7 +1719,6 @@ 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; @@ -1962,29 +1731,18 @@ 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); @@ -2012,10 +1770,16 @@ 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); + hw_ops->after_event_handler(core_data); /* [GOOG] */ } +/* [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); @@ -2240,6 +2004,7 @@ 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(); @@ -2248,12 +2013,15 @@ static int goodix_ts_input_dev_config(struct goodix_ts_core *core_data) return -ENOMEM; } - 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; + 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; set_bit(EV_SYN, input_dev->evbit); set_bit(EV_KEY, input_dev->evbit); @@ -2302,6 +2070,7 @@ 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(); @@ -2310,12 +2079,15 @@ static int goodix_ts_pen_dev_config(struct goodix_ts_core *core_data) return -ENOMEM; } - 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; + 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->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); set_bit(ABS_X, pen_dev->absbit); @@ -2362,7 +2134,7 @@ void goodix_ts_pen_dev_remove(struct goodix_ts_core *core_data) { if (!core_data->pen_dev) return; - mutex_destroy(&goodix_ble_data.lock); + mutex_destroy(&core_data->ble_data.lock); input_unregister_device(core_data->pen_dev); core_data->pen_dev = NULL; } @@ -2420,7 +2192,7 @@ exit: /** * goodix_ts_esd_on - turn on esd protection */ -static void goodix_ts_esd_on(struct goodix_ts_core *cd) +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; @@ -2441,7 +2213,7 @@ static void goodix_ts_esd_on(struct goodix_ts_core *cd) /** * goodix_ts_esd_off - turn off esd protection */ -static void goodix_ts_esd_off(struct goodix_ts_core *cd) +void goodix_ts_esd_off(struct goodix_ts_core *cd) { struct goodix_ts_esd *ts_esd = &cd->ts_esd; int ret; @@ -2455,40 +2227,6 @@ static 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) @@ -2504,8 +2242,6 @@ 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; @@ -2516,10 +2252,13 @@ 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) +#if IS_ENABLED(CONFIG_GOOG_TOUCH_INTERFACE) +static void goodix_ts_release_connects(struct goodix_ts_core *core_data) +{ +} +#else static void goodix_ts_release_connects(struct goodix_ts_core *core_data) { struct input_dev *input_dev = core_data->input_dev; @@ -2545,9 +2284,7 @@ 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)) @@ -2557,68 +2294,23 @@ 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); - /* - * 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; - } - } + 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); } - 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; } @@ -2674,80 +2366,44 @@ 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); + goodix_set_pinctrl_state(core_data, PINCTRL_MODE_ACTIVE); /* [GOOG] */ atomic_set(&core_data->suspended, 0); hw_ops->irq_enable(core_data, false); - 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); - + /* [GOOG] */ if (check_gesture_mode(core_data)) { + struct goodix_gesture_data *gesture_data = + &core_data->ts_event.gesture_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 { - /* reset device or power on*/ - if (core_data->board_data.sleep_enable) + if (core_data->gesture_type) { + disable_irq_wake(core_data->irq); hw_ops->reset(core_data, GOODIX_NORMAL_RESET_DELAY_MS); - 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; - } + } 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); } } - mutex_unlock(&goodix_modules.mutex); -out: /* enable irq */ hw_ops->irq_enable(core_data, true); /* open esd */ - goodix_ts_blocking_notify(NOTIFY_RESUME, NULL); + goodix_ts_esd_on(core_data); ts_info("Resume end"); return 0; } @@ -2804,37 +2460,6 @@ 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; @@ -2866,7 +2491,7 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd) ts_err("failed set pen device"); goto err_finger; } - mutex_init(&goodix_ble_data.lock); + mutex_init(&cd->ble_data.lock); } #if IS_ENABLED(CONFIG_FB) @@ -2978,7 +2603,7 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd) #if IS_ENABLED(CONFIG_GOODIX_GESTURE) /* gesture init */ - ret = gesture_module_init(); + ret = gesture_module_init(cd); if (ret < 0) { ts_err("failed set init gesture"); goto err_init_gesture; @@ -2986,12 +2611,18 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd) #endif /* inspect init */ - ret = inspect_module_init(); + ret = inspect_module_init(cd); 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); @@ -3027,6 +2658,7 @@ 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); @@ -3039,10 +2671,10 @@ int goodix_ts_stage2_init(struct goodix_ts_core *cd) return 0; err_setup_irq: - inspect_module_exit(); + inspect_module_exit(cd); err_init_inspect: #if IS_ENABLED(CONFIG_GOODIX_GESTURE) - gesture_module_exit(); + gesture_module_exit(cd); err_init_gesture: #endif goodix_ts_esd_uninit(cd); @@ -3120,10 +2752,16 @@ 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: get config data from config bin */ + /* 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 */ ret = goodix_get_config_proc(cd); if (ret < 0) ts_info("no valid ic config found"); @@ -3132,35 +2770,20 @@ static int goodix_later_init_thread(void *data) else ts_info("one binary, no need find config"); -upgrade: - /* step 3: init fw struct add try do fw upgrade */ + /* step 4: 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->ic_configs[CONFIG_TYPE_NORMAL], update_flag); + ret = goodix_do_fw_update(cd, update_flag); if (ret) ts_err("failed do fw update"); - /* 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; - } + print_ic_info(&cd->ic_info); /* the recommend way to update ic config is throuth ISP, * if not we will send config with interactive mode @@ -3178,7 +2801,7 @@ upgrade: return 0; uninit_fw: - goodix_fw_update_uninit(); + goodix_fw_update_uninit(cd); err_out: ts_err("stage2 init failed"); cd->init_stage = CORE_INIT_FAIL; @@ -3220,25 +2843,16 @@ static int goodix_start_later_init(struct goodix_ts_core *ts_core) */ static int goodix_ts_probe(struct platform_device *pdev) { - struct goodix_ts_core *core_data = NULL; + struct goodix_device_resource *dev_res = + container_of(pdev, struct goodix_device_resource, pdev); + struct goodix_ts_core *core_data; struct goodix_bus_interface *bus_interface; int ret; ts_info("IN"); - 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; - } + core_data = &dev_res->core_data; + bus_interface = &dev_res->bus; if (IS_ENABLED(CONFIG_OF) && bus_interface->dev->of_node) { /* parse devicetree property */ @@ -3256,11 +2870,10 @@ 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; @@ -3298,12 +2911,8 @@ 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(); + ret = goodix_tools_init(core_data); if (ret) { ts_err("failed init tools"); goto err_init_tools; @@ -3313,8 +2922,6 @@ 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); @@ -3327,16 +2934,14 @@ static int goodix_ts_probe(struct platform_device *pdev) return 0; err_start_late_init: - goodix_tools_exit(); + goodix_tools_exit(core_data); 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; } @@ -3345,38 +2950,45 @@ 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); - inspect_module_exit(); + + /* goodix_ts_stage2_init() */ + inspect_module_exit(core_data); #if IS_ENABLED(CONFIG_GOODIX_GESTURE) - gesture_module_exit(); + gesture_module_exit(core_data); #endif - core_module_prob_sate = CORE_MODULE_REMOVED; - goodix_ts_esd_uninit(core_data); + if (atomic_read(&ts_esd->esd_on)) + goodix_ts_esd_off(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); - goog_touch_interface_remove(core_data->gti); - goodix_ts_sysfs_exit(core_data); #endif + goodix_ts_sysfs_exit(core_data); #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_fw_update_uninit(); + /* goodix_later_init_thread() */ + goodix_fw_update_uninit(core_data); } - goodix_tools_exit(); - goodix_ts_unregister_notifier(&core_data->ts_notifier); + /* goodix_ts_probe() */ + goodix_tools_exit(core_data); goodix_ts_power_off(core_data); +/*~[GOOG] */ goodix_set_pinctrl_state(core_data, PINCTRL_MODE_SUSPEND); mutex_destroy(&core_data->cmd_lock); @@ -3416,15 +3028,23 @@ 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(); -#else - ret = goodix_i2c_bus_init(); + if (ret) { + ts_err("failed add spi bus driver"); + return ret; + } #endif +#ifdef CONFIG_TOUCHSCREEN_GOODIX_BRL_I2C + ret = goodix_i2c_bus_init(); if (ret) { - ts_err("failed add bus driver"); + ts_err("failed add i2c bus driver"); return ret; } +#endif + return platform_driver_register(&goodix_ts_driver); } @@ -3434,9 +3054,11 @@ static void __exit goodix_ts_core_exit(void) platform_driver_unregister(&goodix_ts_driver); #ifdef CONFIG_TOUCHSCREEN_GOODIX_BRL_SPI goodix_spi_bus_exit(); -#else +#endif +#ifdef CONFIG_TOUCHSCREEN_GOODIX_BRL_I2C 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 33a59ee..bb03a78 100644 --- a/goodix_ts_core.h +++ b/goodix_ts_core.h @@ -16,21 +16,22 @@ */ #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/completion.h> +#include <linux/vmalloc.h> +#include <linux/kthread.h> #include <linux/delay.h> -#include <linux/firmware.h> -#include <linux/init.h> +#include <linux/mutex.h> +#include <linux/platform_device.h> +#include <linux/miscdevice.h> #include <linux/input.h> #include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/kthread.h> -#include <linux/module.h> -#include <linux/mutex.h> +#include <linux/completion.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> @@ -56,7 +57,7 @@ #define GOODIX_CORE_DRIVER_NAME "goodix_ts" #define GOODIX_PEN_DRIVER_NAME "goodix_ts,pen" -#define GOODIX_DRIVER_VERSION "v1.2.4" +#define GOODIX_DRIVER_VERSION "v1.2.5" #define GOODIX_MAX_TOUCH 10 #define GOODIX_PEN_MAX_PRESSURE 4096 #define GOODIX_MAX_PEN_KEY 2 @@ -74,11 +75,18 @@ #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" @@ -465,6 +473,45 @@ 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 */ @@ -498,6 +545,24 @@ 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]; @@ -613,7 +678,7 @@ struct goodix_self_sensing_data { }; struct goodix_rx_package { - uint8_t header[8]; + uint8_t header[8]; /* SPI prefix */ uint16_t data[0]; }; @@ -704,7 +769,6 @@ 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; }; @@ -720,36 +784,77 @@ 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 workqueue_struct *event_wq; - struct delayed_work monitor_gesture_work; - ktime_t gesture_down_timeout; - ktime_t gesture_up_timeout; + struct goodix_ble_data ble_data; + u32 pen_pressure; + + char input_name[32]; + char input_pen_name[32]; /* 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; - unsigned char gesture_type; + 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; 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; @@ -757,16 +862,17 @@ struct goodix_ts_core { atomic_t irq_enabled; atomic_t suspended; - bool screen_protector_mode_enabled; + bool screen_protector_mode_enabled; /* [GOOG] */ /* 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 @@ -779,93 +885,28 @@ struct goodix_ts_core { */ ktime_t isr_timestamp; ktime_t coords_timestamp; + /*~[GOOG] */ }; -/* 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_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 goodix_device_manager { struct list_head list; - char *name; - enum goodix_ext_priority priority; - const struct goodix_ext_module_funcs *funcs; - void *priv_data; - struct kobject kobj; - struct work_struct work; + bool initialized; + struct mutex mutex; + int nums; }; -/* - * 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); +struct goodix_device_resource { + struct list_head list; + int id; + char name[64]; + struct goodix_bus_interface bus; + struct platform_device pdev; + struct goodix_ts_core core_data; }; -/* external attrs helper macro */ -#define __EXTMOD_ATTR(_name, _mode, _show, _store) \ - { \ - .attr = { .name = __stringify(_name), .mode = _mode }, \ - .show = _show, .store = _store, \ - } +extern struct goodix_device_manager goodix_devices; +extern int goodix_device_register(struct goodix_device_resource *device); -/* 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; @@ -891,31 +932,6 @@ 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); @@ -931,22 +947,26 @@ 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(void); -int goodix_do_fw_update(struct goodix_ic_config *ic_config, int mode); +void goodix_fw_update_uninit(struct goodix_ts_core *core_data); +int goodix_do_fw_update(struct goodix_ts_core *core_data, int mode); int goodix_get_ic_type( struct device_node *node, struct goodix_bus_interface *bus_inf); -int gesture_module_init(void); -void gesture_module_exit(void); -int inspect_module_init(void); -void inspect_module_exit(void); -int goodix_tools_init(void); -void goodix_tools_exit(void); - -int driver_test_selftest(char* buf); +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 driver_test_proc_init(struct goodix_ts_core *core_data); -void driver_test_proc_remove(void); +void driver_test_proc_remove(struct goodix_ts_core *core_data); 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 d4246b0..51335da 100644 --- a/goodix_ts_gesture.c +++ b/goodix_ts_gesture.c @@ -27,236 +27,136 @@ #include <linux/spinlock.h> #include <linux/string.h> #include <linux/version.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 + * [GOOG] + * Move GOODIX_GESTURE_* define to goodix_ts_core.h. */ -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 goodix_ext_module *module, char *buf) +static ssize_t gsx_double_type_show(struct device *dev, + struct device_attribute *attr, char *buf) { - 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; - } + 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; return sprintf(buf, "%s\n", (type & GESTURE_DOUBLE_TAP) ? "enable" : "disable"); } -static ssize_t gsx_double_type_store( - struct goodix_ext_module *module, const char *buf, size_t count) +static ssize_t gsx_double_type_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - 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; - } + struct device *device = + container_of(((struct kobject *)dev)->parent, struct device, kobj); + struct goodix_ts_core *cd = dev_get_drvdata(device); if (buf[0] == '1') { ts_info("enable double tap"); - gsx->ts_core->gesture_type |= GESTURE_DOUBLE_TAP; + cd->gesture_type |= GESTURE_DOUBLE_TAP; } else if (buf[0] == '0') { ts_info("disable double tap"); - gsx->ts_core->gesture_type &= ~GESTURE_DOUBLE_TAP; + cd->gesture_type &= ~GESTURE_DOUBLE_TAP; } else ts_err("invalid cmd[%d]", buf[0]); return count; } -static ssize_t gsx_single_type_show(struct goodix_ext_module *module, char *buf) +static ssize_t gsx_single_type_show(struct device *dev, + struct device_attribute *attr, char *buf) { - 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; - } + 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; return sprintf(buf, "%s\n", (type & GESTURE_SINGLE_TAP) ? "enable" : "disable"); } -static ssize_t gsx_single_type_store( - struct goodix_ext_module *module, const char *buf, size_t count) +static ssize_t gsx_single_type_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - 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; - } + struct device *device = + container_of(((struct kobject *)dev)->parent, struct device, kobj); + struct goodix_ts_core *cd = dev_get_drvdata(device); if (buf[0] == '1') { ts_info("enable single tap"); - gsx->ts_core->gesture_type |= GESTURE_SINGLE_TAP; + cd->gesture_type |= GESTURE_SINGLE_TAP; } else if (buf[0] == '0') { ts_info("disable single tap"); - gsx->ts_core->gesture_type &= ~GESTURE_SINGLE_TAP; + cd->gesture_type &= ~GESTURE_SINGLE_TAP; } else ts_err("invalid cmd[%d]", buf[0]); return count; } -static ssize_t gsx_fod_type_show(struct goodix_ext_module *module, char *buf) +static ssize_t gsx_fod_type_show(struct device *dev, + struct device_attribute *attr, char *buf) { - 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; - } + 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; return sprintf( buf, "%s\n", (type & GESTURE_FOD_PRESS) ? "enable" : "disable"); } -static ssize_t gsx_fod_type_store( - struct goodix_ext_module *module, const char *buf, size_t count) +static ssize_t gsx_fod_type_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - 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; - } + struct device *device = + container_of(((struct kobject *)dev)->parent, struct device, kobj); + struct goodix_ts_core *cd = dev_get_drvdata(device); if (buf[0] == '1') { ts_info("enable fod"); - gsx->ts_core->gesture_type |= GESTURE_FOD_PRESS; + cd->gesture_type |= GESTURE_FOD_PRESS; } else if (buf[0] == '0') { ts_info("disable fod"); - gsx->ts_core->gesture_type &= ~GESTURE_FOD_PRESS; + cd->gesture_type &= ~GESTURE_FOD_PRESS; } else ts_err("invalid cmd[%d]", buf[0]); return count; } -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), -}; - -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; +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); - if (!cd || !cd->hw_ops->gesture) { - ts_err("gesture unsupported"); - return -EINVAL; - } - - atomic_set(&gsx->registered, 0); +static struct attribute *gesture_attrs[] = { + &dev_attr_double_type.attr, + &dev_attr_single_type.attr, + &dev_attr_fod_type.attr, + NULL, +}; - return 0; -} +const static struct attribute_group gesture_sysfs_group = { + .attrs = gesture_attrs, +}; -/** - * 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) +int goodix_ts_report_gesture(struct goodix_ts_core *cd, struct goodix_ts_event *event) { - 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 *)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]; + 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]; - switch (gs_event.gesture_data.gesture_type) { + switch (event->gesture_data.gesture_type) { case GOODIX_GESTURE_SINGLE_TAP: if (cd->gesture_type & GESTURE_SINGLE_TAP) { ts_info("get SINGLE-TAP gesture"); @@ -340,132 +240,45 @@ static int gsx_gesture_ist( } break; default: - ts_err("not support gesture type[%02X]", gs_event.gesture_data.gesture_type); + ts_err("not support gesture type[%02X]", event->gesture_data.gesture_type); break; } -re_send_ges_cmd: - return EVT_CANCEL_IRQEVT; -} - -/** - * 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; - 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; + return 0; } -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 gesture_module_init(struct goodix_ts_core *core_data) { - 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); + int ret = 0; + struct kobject *parent = &core_data->pdev->dev.kobj; /* gesture sysfs init */ - ret = kobject_init_and_add( - &gsx_gesture->module.kobj, def_kobj_type, def_kobj, "gesture"); - if (ret) { + core_data->gesture_kobj = kobject_create_and_add("gesture", parent); + if (!core_data->gesture_kobj) { ts_err("failed create gesture sysfs node!"); + ret = -ENOENT; /* [GOOG] */ goto err_out; } - for (i = 0; i < ARRAY_SIZE(gesture_attrs) && !ret; i++) - ret = sysfs_create_file( - &gsx_gesture->module.kobj, &gesture_attrs[i].attr); + ret = sysfs_create_group(core_data->gesture_kobj, &gesture_sysfs_group); if (ret) { - 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); + ts_err("failed create gesture sysfs files"); + kobject_put(core_data->gesture_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(void) +void gesture_module_exit(struct goodix_ts_core *core_data) { - 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); - kobject_put(&gsx_gesture->module.kobj); - kfree(gsx_gesture); - module_initialized = false; + sysfs_remove_group(core_data->gesture_kobj, &gesture_sysfs_group); + kobject_put(core_data->gesture_kobj); } diff --git a/goodix_ts_inspect.c b/goodix_ts_inspect.c index 119c8bc..bebc557 100644 --- a/goodix_ts_inspect.c +++ b/goodix_ts_inspect.c @@ -122,8 +122,6 @@ #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 }; @@ -517,7 +515,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_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(ts_test->ts); return 0; } @@ -529,7 +527,7 @@ static void goodix_tptest_finish(struct goodix_ts_test *ts_test) ts_test_reset(ts_test, 100); /* open esd */ - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(ts_test->ts); /* enable irq */ ts_test_irq_enable(ts_test, true); } @@ -1353,10 +1351,10 @@ static ssize_t get_rawdata_show( static DEVICE_ATTR(get_rawdata, 0444, get_rawdata_show, NULL); -int inspect_module_init(void) +int inspect_module_init(struct goodix_ts_core *core_data) { int ret; - struct kobject *def_kobj = goodix_get_default_kobj(); + struct kobject *def_kobj = &core_data->pdev->dev.kobj; /* create sysfs */ ret = sysfs_create_file(def_kobj, &dev_attr_get_rawdata.attr); @@ -1364,8 +1362,6 @@ int inspect_module_init(void) ts_err("create sysfs of get_rawdata failed"); goto err_out; } - - module_initialized = true; ts_info("inspect module init success"); return 0; @@ -1374,14 +1370,10 @@ err_out: return ret; } -void inspect_module_exit(void) +void inspect_module_exit(struct goodix_ts_core *core_data) { - struct kobject *def_kobj = goodix_get_default_kobj(); + struct kobject *def_kobj = &core_data->pdev->dev.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 a8ed02f..d2f0082 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" -char *cmd_list[] = { CMD_FW_UPDATE, CMD_AUTO_TEST, CMD_OPEN_TEST, +const static 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,7 +90,6 @@ 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; @@ -411,7 +410,7 @@ struct goodix_ts_test { }; static struct goodix_ts_test *ts_test; -static int cal_cha_to_cha_res(int v1, int v2) +static int cal_cha_to_cha_res(struct goodix_ts_core *cd, int v1, int v2) { if (cd->bus->ic_type == IC_TYPE_BERLIN_A) return (v1 - v2) * 63 / v2; @@ -423,7 +422,7 @@ static int cal_cha_to_cha_res(int v1, int v2) return (v1 / v2 - 1) * 55 + 45; } -static int cal_cha_to_avdd_res(int v1, int v2) +static int cal_cha_to_avdd_res(struct goodix_ts_core *cd, int v1, int v2) { if (cd->bus->ic_type == IC_TYPE_BERLIN_A) return 64 * (2 * v2 - 25) * 40 / v1 - 40; @@ -435,7 +434,7 @@ static int cal_cha_to_avdd_res(int v1, int v2) return 64 * (2 * v2 - 25) * 76 / v1 - 15; } -static int cal_cha_to_gnd_res(int v) +static int cal_cha_to_gnd_res(struct goodix_ts_core *cd, int v) { if (cd->bus->ic_type == IC_TYPE_BERLIN_A) return 64148 / v - 40; @@ -558,7 +557,7 @@ static void goodix_save_short_res(u16 chn1, u16 chn2, int r) } } -static int gdix_check_tx_tx_shortcircut(u8 short_ch_num) +static int gdix_check_tx_tx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_num) { int ret = 0, err = 0; u32 r_threshold = 0, short_r = 0; @@ -615,11 +614,9 @@ static int gdix_check_tx_tx_shortcircut(u8 short_ch_num) if (adc_signal < ts_test->short_threshold) continue; - short_r = (u32)cal_cha_to_cha_res( - self_capdata, adc_signal); + short_r = (u32)cal_cha_to_cha_res(cd, 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) { @@ -649,7 +646,7 @@ static int gdix_check_tx_tx_shortcircut(u8 short_ch_num) return err; } -static int gdix_check_rx_rx_shortcircut(u8 short_ch_num) +static int gdix_check_rx_rx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_num) { int ret = 0, err = 0; u32 r_threshold = 0, short_r = 0; @@ -703,8 +700,7 @@ static int gdix_check_rx_rx_shortcircut(u8 short_ch_num) if (adc_signal < ts_test->short_threshold) continue; - short_r = (u32)cal_cha_to_cha_res( - self_capdata, adc_signal); + short_r = (u32)cal_cha_to_cha_res(cd, self_capdata, adc_signal); if (short_r < r_threshold) { master_pin_num = map_die2pin(short_die_num); slave_pin_num = map_die2pin(j); @@ -736,7 +732,7 @@ static int gdix_check_rx_rx_shortcircut(u8 short_ch_num) return err; } -static int gdix_check_tx_rx_shortcircut(u8 short_ch_num) +static int gdix_check_tx_rx_shortcircut(struct goodix_ts_core *cd, u8 short_ch_num) { int ret = 0, err = 0; u32 r_threshold = 0, short_r = 0; @@ -791,8 +787,7 @@ static int gdix_check_tx_rx_shortcircut(u8 short_ch_num) if (adc_signal < ts_test->short_threshold) continue; - short_r = (u32)cal_cha_to_cha_res( - self_capdata, adc_signal); + short_r = (u32)cal_cha_to_cha_res(cd, 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); @@ -824,7 +819,7 @@ static int gdix_check_tx_rx_shortcircut(u8 short_ch_num) return err; } -static int gdix_check_resistance_to_gnd(u16 adc_signal, u32 pos) +static int gdix_check_resistance_to_gnd(struct goodix_ts_core *cd, u16 adc_signal, u32 pos) { long r = 0; u16 r_th = 0, avdd_value = 0; @@ -842,10 +837,10 @@ static int gdix_check_resistance_to_gnd(u16 adc_signal, u32 pos) if (short_type == 0) { /* short to GND */ - r = cal_cha_to_gnd_res(adc_signal); + r = cal_cha_to_gnd_res(cd, adc_signal); } else { /* short to VDD */ - r = cal_cha_to_avdd_res(adc_signal, avdd_value); + r = cal_cha_to_avdd_res(cd, adc_signal, avdd_value); } if (pos < max_drv_num) @@ -874,7 +869,7 @@ static int gdix_check_resistance_to_gnd(u16 adc_signal, u32 pos) return 0; } -static int gdix_check_gndvdd_shortcircut(void) +static int gdix_check_gndvdd_shortcircut(struct goodix_ts_core *cd) { int ret = 0, err = 0; int size = 0, i = 0; @@ -907,7 +902,7 @@ static int gdix_check_gndvdd_shortcircut(void) 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(adc_signal, i); + ret = gdix_check_resistance_to_gnd(cd, adc_signal, i); if (ret != 0) { ts_err("Resistance to-gnd/vdd short"); err = ret; @@ -922,7 +917,7 @@ err_out: #define NOTT_CHECKSUM_LEN 54 #define BRLD_CHECKSUM_LEN 62 #define BRLB_CHECKSUM_LEN 129 -static int goodix_shortcircut_analysis(void) +static int goodix_shortcircut_analysis(struct goodix_ts_core *cd) { int ret; int err = 0; @@ -963,13 +958,13 @@ static int goodix_shortcircut_analysis(void) test_result.drv_gnd_avdd_num, test_result.sen_gnd_avdd_num); if (test_result.drv_drv_num) - err |= gdix_check_tx_tx_shortcircut(test_result.drv_drv_num); + err |= gdix_check_tx_tx_shortcircut(cd, test_result.drv_drv_num); if (test_result.sen_sen_num) - err |= gdix_check_rx_rx_shortcircut(test_result.sen_sen_num); + err |= gdix_check_rx_rx_shortcircut(cd, test_result.sen_sen_num); if (test_result.drv_sen_num) - err |= gdix_check_tx_rx_shortcircut(test_result.drv_sen_num); + err |= gdix_check_tx_rx_shortcircut(cd, test_result.drv_sen_num); if (test_result.drv_gnd_avdd_num || test_result.sen_gnd_avdd_num) - err |= gdix_check_gndvdd_shortcircut(); + err |= gdix_check_gndvdd_shortcircut(cd); ts_info(">>>>> short check return 0x%x", err); @@ -979,7 +974,7 @@ static int goodix_shortcircut_analysis(void) #define INSPECT_FW_SWITCH_CMD 0x85 #define SHORT_TEST_RUN_FLAG 0xAA #define SHORT_TEST_RUN_REG 0x10400 -static int goodix_short_test_prepare(void) +static int goodix_short_test_prepare(struct goodix_ts_core *cd) { struct goodix_ts_cmd tmp_cmd; int ret; @@ -1018,7 +1013,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(void) +static int goodix_shortcircut_test(struct goodix_ts_core *cd) { int ret = 0; int res; @@ -1027,7 +1022,7 @@ static int goodix_shortcircut_test(void) u8 status; ts_info("---------------------- short_test begin ----------------------"); - ret = goodix_short_test_prepare(); + ret = goodix_short_test_prepare(cd); if (ret < 0) { ts_err("Failed enter short test mode"); return ret; @@ -1071,7 +1066,7 @@ static int goodix_shortcircut_test(void) /* start analysis short result */ ts_info("short_test finished, start analysis"); - res = goodix_shortcircut_analysis(); + res = goodix_shortcircut_analysis(cd); if (res == 0) { ts_test->result[GTP_SHORT_TEST] = TEST_OK; ret = 0; @@ -1093,7 +1088,8 @@ 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(uint8_t cmd, uint8_t status, int retry_count) +static int goodix_flash_cmd(struct goodix_ts_core *cd, + uint8_t cmd, uint8_t status, int retry_count) { u8 cmd_buf[] = { 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }; int ret; @@ -1122,7 +1118,7 @@ static int goodix_flash_cmd(uint8_t cmd, uint8_t status, int retry_count) return -EINVAL; } -static int goodix_flash_read(u32 addr, u8 *buf, int len) +static int goodix_flash_read(struct goodix_ts_core *cd, u32 addr, u8 *buf, int len) { int i; int ret; @@ -1142,7 +1138,7 @@ static int goodix_flash_read(u32 addr, u8 *buf, int len) checksum += p[i] | (p[i + 1] << 8); head_info.checksum = checksum; - ret = goodix_flash_cmd(FLASH_CMD_R_START, FLASH_CMD_STATE_READY, 15); + ret = goodix_flash_cmd(cd, FLASH_CMD_R_START, FLASH_CMD_STATE_READY, 15); if (ret < 0) { ts_err("failed enter flash read state"); goto read_end; @@ -1155,7 +1151,7 @@ static int goodix_flash_read(u32 addr, u8 *buf, int len) goto read_end; } - ret = goodix_flash_cmd(FLASH_CMD_RW_FINISH, FLASH_CMD_STATE_OKAY, 50); + ret = goodix_flash_cmd(cd, FLASH_CMD_RW_FINISH, FLASH_CMD_STATE_OKAY, 50); if (ret) { ts_err("faild read flash ready state"); goto read_end; @@ -1182,7 +1178,7 @@ static int goodix_flash_read(u32 addr, u8 *buf, int len) memcpy(buf, tmp_buf + sizeof(flash_head_info_t), len); ret = 0; read_end: - goodix_flash_cmd(0x0C, 0, 0); + goodix_flash_cmd(cd, 0x0C, 0, 0); return ret; } @@ -1223,15 +1219,27 @@ static const struct seq_operations seq_ops = { static int driver_test_open(struct inode *inode, struct file *file) { - return seq_open(file, &seq_ops); + 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; } 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(void) +static void goodix_save_header(struct goodix_ts_core *cd) { int i; bool total_result = true; @@ -1465,7 +1473,7 @@ static void goodix_data_cal(s16 *data, size_t data_size, s16 *stat_result) stat_result[2] = min; } -static void goodix_save_data(void) +static void goodix_save_data(struct goodix_ts_core *cd) { int tx = cd->ic_info.parm.drv_num; int rx = cd->ic_info.parm.sen_num; @@ -1553,12 +1561,12 @@ static void goodix_save_data(void) index += sprintf(&rbuf[index], "</DataRecord>\n"); } -static void goodix_save_tail(void) +static void goodix_save_tail(struct goodix_ts_core *cd) { index += sprintf(&rbuf[index], "</TESTLOG>\n"); } -static void goodix_save_test_result(bool is_brief) +static void goodix_save_test_result(struct goodix_ts_core *cd, bool is_brief) { if (is_brief) { if (ts_test->item[GTP_CAP_TEST]) { @@ -1592,9 +1600,9 @@ static void goodix_save_test_result(bool is_brief) : "FAIL"); } } else { - goodix_save_header(); - goodix_save_data(); - goodix_save_tail(); + goodix_save_header(cd); + goodix_save_data(cd); + goodix_save_tail(cd); } } @@ -1724,7 +1732,7 @@ static int parse_csvfile( return parse_valid_data(buf, size, ptr, data, rows); } -static int goodix_obtain_testlimits(void) +static int goodix_obtain_testlimits(struct goodix_ts_core *cd) { const struct firmware *firmware = NULL; struct device *dev = &cd->pdev->dev; @@ -1847,7 +1855,7 @@ exit_free: return ret; } -static int goodix_delta_test(void) +static int goodix_delta_test(struct goodix_ts_core *cd) { int i, j; int max_val; @@ -1899,7 +1907,7 @@ static int goodix_delta_test(void) return ret; } -static int goodix_open_test(void) +static int goodix_open_test(struct goodix_ts_core *cd) { u8 *tmp_buf; struct goodix_ts_cmd temp_cmd; @@ -1999,7 +2007,7 @@ static int goodix_open_test(void) ts_test->result[GTP_CAP_TEST] = TEST_NG; } - if (goodix_delta_test() == 0) + if (goodix_delta_test(cd) == 0) ts_test->result[GTP_DELTA_TEST] = TEST_OK; exit: @@ -2007,7 +2015,7 @@ exit: return ret; } -static int goodix_self_open_test(void) +static int goodix_self_open_test(struct goodix_ts_core *cd) { u8 *tmp_buf; struct goodix_ts_cmd temp_cmd; @@ -2085,7 +2093,7 @@ exit: return ret; } -static int goodix_noise_test(void) +static int goodix_noise_test(struct goodix_ts_core *cd) { u8 *tmp_buf; struct goodix_ts_cmd temp_cmd; @@ -2168,19 +2176,19 @@ exit: return ret; } -static int goodix_auto_test(bool is_brief) +static int goodix_auto_test(struct goodix_ts_core *cd, bool is_brief) { struct goodix_ts_cmd temp_cmd; int ret; - ret = goodix_obtain_testlimits(); + ret = goodix_obtain_testlimits(cd); if (ret < 0) { ts_err("obtain open test limits failed"); return ret; } cd->hw_ops->irq_enable(cd, false); - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); temp_cmd.len = 5; temp_cmd.cmd = 0x64; @@ -2190,7 +2198,7 @@ static int goodix_auto_test(bool is_brief) ret = cd->hw_ops->send_cmd(cd, &temp_cmd); if (ret < 0) ts_err("enter test mode failed"); - goodix_open_test(); + goodix_open_test(cd); cd->hw_ops->reset(cd, 100); } @@ -2198,27 +2206,27 @@ static int goodix_auto_test(bool is_brief) ret = cd->hw_ops->send_cmd(cd, &temp_cmd); if (ret < 0) ts_err("enter test mode failed"); - goodix_noise_test(); + goodix_noise_test(cd); cd->hw_ops->reset(cd, 100); } if (ts_test->item[GTP_SELFCAP_TEST]) { - goodix_self_open_test(); + goodix_self_open_test(cd); cd->hw_ops->reset(cd, 100); } if (ts_test->item[GTP_SHORT_TEST]) { - goodix_shortcircut_test(); + goodix_shortcircut_test(cd); cd->hw_ops->reset(cd, 100); } cd->hw_ops->irq_enable(cd, true); - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); - goodix_save_test_result(is_brief); + goodix_ts_esd_on(cd); + goodix_save_test_result(cd, is_brief); return 0; } -static void goodix_auto_noise_test(u16 cnt, int threshold) +static void goodix_auto_noise_test(struct goodix_ts_core *cd, u16 cnt, int threshold) { struct goodix_ts_cmd temp_cmd; struct goodix_ts_cmd rb_cmd; @@ -2245,7 +2253,7 @@ static void goodix_auto_noise_test(u16 cnt, int threshold) 8; cd->hw_ops->irq_enable(cd, false); - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); restart: temp_cmd.len = 0x07; @@ -2325,10 +2333,10 @@ exit: } kfree(tmp_buf); cd->hw_ops->irq_enable(cd, true); - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); } -static int get_cap_data(uint8_t *type) +static int get_cap_data(struct goodix_ts_core *cd, uint8_t *type) { struct goodix_ts_cmd temp_cmd; int tx = cd->ic_info.parm.drv_num; @@ -2362,7 +2370,7 @@ static int get_cap_data(uint8_t *type) /* disable irq & close esd */ cd->hw_ops->irq_enable(cd, false); - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); if (strstr(type, CMD_GET_BASEDATA) || strstr(type, CMD_GET_SELF_BASEDATA)) { @@ -2453,11 +2461,11 @@ exit: cd->hw_ops->send_cmd(cd, &temp_cmd); /* enable irq & esd */ cd->hw_ops->irq_enable(cd, true); - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); return ret; } -static void goodix_set_sense_mode(u8 val) +static void goodix_set_sense_mode(struct goodix_ts_core *cd, u8 val) { struct goodix_ts_cmd temp_cmd; @@ -2468,26 +2476,26 @@ static void goodix_set_sense_mode(u8 val) /* normal mode */ index = sprintf(rbuf, "switch to coordinate mode\n"); cd->hw_ops->send_cmd(cd, &temp_cmd); - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); 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_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); 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_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); cd->hw_ops->irq_enable(cd, false); cd->hw_ops->suspend(cd); } } -static void goodix_set_scan_mode(u8 val) +static void goodix_set_scan_mode(struct goodix_ts_core *cd, u8 val) { struct goodix_ts_cmd temp_cmd; @@ -2511,7 +2519,7 @@ static void goodix_set_scan_mode(u8 val) cd->hw_ops->send_cmd(cd, &temp_cmd); } -static void goodix_get_scan_mode(void) +static void goodix_get_scan_mode(struct goodix_ts_core *cd) { u8 status; @@ -2533,7 +2541,7 @@ static void goodix_get_scan_mode(void) } } -static void goodix_set_continue_mode(u8 val) +static void goodix_set_continue_mode(struct goodix_ts_core *cd, u8 val) { struct goodix_ts_cmd temp_cmd; @@ -2551,7 +2559,7 @@ static void goodix_set_continue_mode(u8 val) cd->hw_ops->send_cmd(cd, &temp_cmd); } -static void goodix_read_config(void) +static void goodix_read_config(struct goodix_ts_core *cd) { int ret; u8 *cfg_buf; @@ -2579,7 +2587,7 @@ exit: kfree(cfg_buf); } -static void goodix_get_fw_status(void) +static void goodix_get_fw_status(struct goodix_ts_core *cd) { u32 status_addr; u32 noise_lv_addr; @@ -2626,7 +2634,7 @@ static void goodix_get_fw_status(void) index += sprintf(&rbuf[index], "noise-lv[%d]\n", val); } -static void goodix_set_highsense_mode(u8 val) +static void goodix_set_highsense_mode(struct goodix_ts_core *cd, u8 val) { struct goodix_ts_cmd temp_cmd; static bool flag = false; @@ -2650,7 +2658,7 @@ static void goodix_set_highsense_mode(u8 val) cd->hw_ops->send_cmd(cd, &temp_cmd); } -static void goodix_set_grip_data(u8 val) +static void goodix_set_grip_data(struct goodix_ts_core *cd, u8 val) { struct goodix_ts_cmd temp_cmd; @@ -2679,7 +2687,7 @@ static void goodix_set_grip_data(u8 val) cd->hw_ops->send_cmd(cd, &temp_cmd); } -static void goodix_set_custom_mode(u8 type, u8 val) +static void goodix_set_custom_mode(struct goodix_ts_core *cd, u8 type, u8 val) { struct goodix_ts_cmd temp_cmd; @@ -2731,7 +2739,7 @@ static int obtain_param(char **buf) return val; } -static int goodix_parse_gesture_param(u8 type, char **buf) +static int goodix_parse_gesture_param(struct goodix_ts_core *cd, u8 type, char **buf) { if (type == GESTURE_STTW) { gesture_param_st.length = sizeof(gesture_param_st); @@ -2823,7 +2831,7 @@ static int goodix_parse_gesture_param(u8 type, char **buf) return 0; } -static void goodix_set_gesture_param(u8 type) +static void goodix_set_gesture_param(struct goodix_ts_core *cd, u8 type) { struct goodix_ts_cmd temp_cmd; u32 cmd_reg = cd->ic_info.misc.cmd_addr; @@ -2887,18 +2895,29 @@ exit: cd->hw_ops->send_cmd(cd, &temp_cmd); } -static void goodix_set_heatmap(int val) +static void goodix_set_heatmap(struct goodix_ts_core *cd, 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; @@ -2907,7 +2926,7 @@ static void goodix_set_heatmap(int val) cd->hw_ops->irq_enable(cd, true); } -static void goodix_get_self_compensation(void) +static void goodix_get_self_compensation(struct goodix_ts_core *cd) { u8 *cfg; u8 *cfg_buf; @@ -2962,7 +2981,7 @@ exit: kfree(cfg_buf); } -static void goodix_set_report_rate(int rate) +static void goodix_set_report_rate(struct goodix_ts_core *cd, int rate) { struct goodix_ts_cmd temp_cmd; @@ -2975,12 +2994,12 @@ static void goodix_set_report_rate(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(void) +#define DUMP_AREA3_LEN 64 +static void goodix_get_dump_log(struct goodix_ts_core *cd) { u8 buf[600]; int i; @@ -3010,7 +3029,7 @@ static void goodix_get_dump_log(void) } } -static void goodix_get_stylus_data(void) +static void goodix_get_stylus_data(struct goodix_ts_core *cd) { struct goodix_stylus_data stylus_data; u8 temp_buf[40] = { 0 }; @@ -3035,7 +3054,7 @@ static void goodix_get_stylus_data(void) /* disable irq & close esd */ cd->hw_ops->irq_enable(cd, false); - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); /* clean touch event flag */ ret = cd->hw_ops->write(cd, flag_addr, temp_buf, 1); @@ -3126,10 +3145,10 @@ static void goodix_get_stylus_data(void) exit: /* enable irq & esd */ cd->hw_ops->irq_enable(cd, true); - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); } -static void goodix_force_update(void) +static void goodix_force_update(struct goodix_ts_core *cd) { int i; int ret; @@ -3143,7 +3162,7 @@ static void goodix_force_update(void) if (ret < 0) ts_err("not found valid config"); - ret = goodix_do_fw_update(cd->ic_configs[CONFIG_TYPE_NORMAL], + ret = goodix_do_fw_update(cd, UPDATE_MODE_BLOCK | UPDATE_MODE_FORCE | UPDATE_MODE_SRC_REQUEST); if (ret < 0) @@ -3152,7 +3171,7 @@ static void goodix_force_update(void) index = sprintf(rbuf, "%s: OK\n", CMD_FW_UPDATE); } -static void goodix_set_freq_index(int freq) +static void goodix_set_freq_index(struct goodix_ts_core *cd, int freq) { struct goodix_ts_cmd temp_cmd; @@ -3164,7 +3183,7 @@ static void goodix_set_freq_index(int freq) cd->hw_ops->send_cmd(cd, &temp_cmd); } -static void goodix_disable_coor_filter(int val) +static void goodix_disable_coor_filter(struct goodix_ts_core *cd, int val) { struct goodix_ts_cmd temp_cmd; @@ -3175,9 +3194,11 @@ static void goodix_disable_coor_filter(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; @@ -3197,6 +3218,7 @@ static ssize_t driver_test_write( ts_err("copy from user failed"); return count; } + p[strlen(p) - 1] = 0; vfree(rbuf); rbuf = NULL; @@ -3207,7 +3229,7 @@ static ssize_t driver_test_write( if (!strncmp(p, CMD_FW_UPDATE, strlen(CMD_FW_UPDATE))) { rbuf = vzalloc(SHORT_SIZE); - goodix_force_update(); + goodix_force_update(cd); goto exit; } @@ -3232,7 +3254,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - ret = get_cap_data(CMD_GET_RAWDATA); + ret = get_cap_data(cd, CMD_GET_RAWDATA); if (ret < 0) { index = sprintf(rbuf, "%s: NG\n", CMD_GET_RAWDATA); } @@ -3245,7 +3267,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - ret = get_cap_data(CMD_GET_BASEDATA); + ret = get_cap_data(cd, CMD_GET_BASEDATA); if (ret < 0) { index = sprintf(rbuf, "%s: NG\n", CMD_GET_BASEDATA); } @@ -3258,7 +3280,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - ret = get_cap_data(CMD_GET_DIFFDATA); + ret = get_cap_data(cd, CMD_GET_DIFFDATA); if (ret < 0) { index = sprintf(rbuf, "%s: NG\n", CMD_GET_DIFFDATA); } @@ -3271,7 +3293,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - ret = get_cap_data(CMD_GET_SELF_RAWDATA); + ret = get_cap_data(cd, CMD_GET_SELF_RAWDATA); if (ret < 0) { index = sprintf(rbuf, "%s: NG\n", CMD_GET_SELF_RAWDATA); } @@ -3284,7 +3306,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - ret = get_cap_data(CMD_GET_SELF_DIFFDATA); + ret = get_cap_data(cd, CMD_GET_SELF_DIFFDATA); if (ret < 0) { index = sprintf( rbuf, "%s: NG\n", CMD_GET_SELF_DIFFDATA); @@ -3298,7 +3320,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - ret = get_cap_data(CMD_GET_SELF_BASEDATA); + ret = get_cap_data(cd, CMD_GET_SELF_BASEDATA); if (ret < 0) { index = sprintf( rbuf, "%s: NG\n", CMD_GET_SELF_BASEDATA); @@ -3446,11 +3468,11 @@ static ssize_t driver_test_write( goto exit; } if (cmd_val == 0) { - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(cd); index = sprintf( rbuf, "%s: disable OK\n", CMD_SET_ESD_ENABLE); } else { - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(cd); index = sprintf( rbuf, "%s: enable OK\n", CMD_SET_ESD_ENABLE); } @@ -3504,7 +3526,7 @@ static ssize_t driver_test_write( ts_test->item[GTP_DELTA_TEST] = true; ts_test->item[GTP_SELFCAP_TEST] = true; ts_test->item[GTP_SHORT_TEST] = true; - goodix_auto_test(true); + goodix_auto_test(cd, true); goto exit; } @@ -3525,7 +3547,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - ret = get_cap_data(CMD_GET_TX_FREQ); + ret = get_cap_data(cd, CMD_GET_TX_FREQ); if (ret < 0) { index = sprintf(rbuf, "%s: NG\n", CMD_GET_TX_FREQ); } @@ -3561,7 +3583,7 @@ static ssize_t driver_test_write( CMD_SET_SENSE_MODE); goto exit; } - goodix_set_sense_mode(cmd_val); + goodix_set_sense_mode(cd, cmd_val); goto exit; } @@ -3587,7 +3609,7 @@ static ssize_t driver_test_write( goto exit; } ts_test->item[GTP_NOISE_TEST] = true; - goodix_auto_test(false); + goodix_auto_test(cd, false); goto exit; } @@ -3615,7 +3637,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - goodix_auto_noise_test(cmd_val, cmd_val2); + goodix_auto_noise_test(cd, cmd_val, cmd_val2); goto exit; } @@ -3627,7 +3649,7 @@ static ssize_t driver_test_write( } mutex_lock(&cd->cmd_lock); usleep_range(6000, 6100); - ret = goodix_flash_read(0x1F301, &id, 1); + ret = goodix_flash_read(cd, 0x1F301, &id, 1); mutex_unlock(&cd->cmd_lock); if (ret < 0) index = sprintf(rbuf, "%s: NG\n", CMD_GET_PACKAGE_ID); @@ -3645,7 +3667,7 @@ static ssize_t driver_test_write( } mutex_lock(&cd->cmd_lock); usleep_range(6000, 6100); - ret = goodix_flash_read(0x1F314, &id, 1); + ret = goodix_flash_read(cd, 0x1F314, &id, 1); mutex_unlock(&cd->cmd_lock); if (ret < 0) index = sprintf(rbuf, "%s: NG\n", CMD_GET_MCU_ID); @@ -3676,7 +3698,7 @@ static ssize_t driver_test_write( CMD_SET_SCAN_MODE); goto exit; } - goodix_set_scan_mode(cmd_val); + goodix_set_scan_mode(cd, cmd_val); goto exit; } @@ -3686,7 +3708,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - goodix_get_scan_mode(); + goodix_get_scan_mode(cd); goto exit; } @@ -3712,7 +3734,7 @@ static ssize_t driver_test_write( CMD_SET_CONTINUE_MODE); goto exit; } - goodix_set_continue_mode(cmd_val); + goodix_set_continue_mode(cd, cmd_val); goto exit; } @@ -3749,7 +3771,7 @@ static ssize_t driver_test_write( } ts_test->item[GTP_CAP_TEST] = true; ts_test->freq = cmd_val2; - goodix_auto_test(false); + goodix_auto_test(cd, false); goto exit; } @@ -3765,7 +3787,7 @@ static ssize_t driver_test_write( goto exit; } ts_test->item[GTP_SELFCAP_TEST] = true; - goodix_auto_test(false); + goodix_auto_test(cd, false); goto exit; } @@ -3781,7 +3803,7 @@ static ssize_t driver_test_write( goto exit; } ts_test->item[GTP_SHORT_TEST] = true; - goodix_auto_test(false); + goodix_auto_test(cd, false); goto exit; } @@ -3791,7 +3813,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - goodix_read_config(); + goodix_read_config(cd); goto exit; } @@ -3801,7 +3823,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - goodix_get_fw_status(); + goodix_get_fw_status(cd); goto exit; } @@ -3828,7 +3850,7 @@ static ssize_t driver_test_write( CMD_SET_HIGHSENSE_MODE); goto exit; } - goodix_set_highsense_mode(cmd_val); + goodix_set_highsense_mode(cd, cmd_val); goto exit; } @@ -3849,7 +3871,7 @@ static ssize_t driver_test_write( CMD_SET_GRIP_DATA); goto exit; } - goodix_set_grip_data(cmd_val); + goodix_set_grip_data(cd, cmd_val); goto exit; } @@ -3870,7 +3892,7 @@ static ssize_t driver_test_write( CMD_SET_GRIP_MODE); goto exit; } - goodix_set_custom_mode(GRIP_FUNC, cmd_val); + goodix_set_custom_mode(cd, GRIP_FUNC, cmd_val); goto exit; } @@ -3891,7 +3913,7 @@ static ssize_t driver_test_write( CMD_SET_PALM_MODE); goto exit; } - goodix_set_custom_mode(PALM_FUNC, cmd_val); + goodix_set_custom_mode(cd, PALM_FUNC, cmd_val); goto exit; } @@ -3912,7 +3934,7 @@ static ssize_t driver_test_write( CMD_SET_NOISE_MODE); goto exit; } - goodix_set_custom_mode(NOISE_FUNC, cmd_val); + goodix_set_custom_mode(cd, NOISE_FUNC, cmd_val); goto exit; } @@ -3933,7 +3955,7 @@ static ssize_t driver_test_write( CMD_SET_WATER_MODE); goto exit; } - goodix_set_custom_mode(WATER_FUNC, cmd_val); + goodix_set_custom_mode(cd, WATER_FUNC, cmd_val); goto exit; } @@ -3949,8 +3971,8 @@ static ssize_t driver_test_write( CMD_SET_ST_PARAM); goto exit; } - goodix_parse_gesture_param(GESTURE_STTW, &p); - goodix_set_gesture_param(GESTURE_STTW); + goodix_parse_gesture_param(cd, GESTURE_STTW, &p); + goodix_set_gesture_param(cd, GESTURE_STTW); goto exit; } @@ -3966,8 +3988,8 @@ static ssize_t driver_test_write( CMD_SET_LP_PARAM); goto exit; } - goodix_parse_gesture_param(GESTURE_LPTW, &p); - goodix_set_gesture_param(GESTURE_LPTW); + goodix_parse_gesture_param(cd, GESTURE_LPTW, &p); + goodix_set_gesture_param(cd, GESTURE_LPTW); goto exit; } @@ -3988,7 +4010,7 @@ static ssize_t driver_test_write( CMD_SET_HEATMAP); goto exit; } - goodix_set_heatmap(cmd_val); + goodix_set_heatmap(cd, cmd_val); goto exit; } @@ -3998,7 +4020,7 @@ static ssize_t driver_test_write( ts_err("failed to alloc rbuf"); goto exit; } - goodix_get_self_compensation(); + goodix_get_self_compensation(cd); goto exit; } @@ -4019,25 +4041,27 @@ static ssize_t driver_test_write( CMD_SET_REPORT_RATE); goto exit; } - goodix_set_report_rate(cmd_val); + goodix_set_report_rate(cd, cmd_val); goto exit; } if (!strncmp(p, CMD_GET_DUMP_LOG, strlen(CMD_GET_DUMP_LOG))) { rbuf = vzalloc(LARGE_SIZE); - 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(); + if (!rbuf) { + ts_err("failed to alloc rbuf"); + goto exit; + } + goodix_get_dump_log(cd); goto exit; } - if (!strncmp(p, CMD_GET_STYLUS_DATA, strlen(CMD_GET_STYLUS_DATA))) { rbuf = vzalloc(LARGE_SIZE); - goodix_get_stylus_data(); + if (!rbuf) { + ts_err("failed to alloc rbuf"); + goto exit; + } + goodix_get_stylus_data(cd); goto exit; } @@ -4054,7 +4078,7 @@ static ssize_t driver_test_write( CMD_SET_FREQ_INDEX); goto exit; } - goodix_set_freq_index(cmd_val); + goodix_set_freq_index(cd, cmd_val); goto exit; } @@ -4071,7 +4095,7 @@ static ssize_t driver_test_write( CMD_DISABLE_FILTER); goto exit; } - goodix_disable_coor_filter(cmd_val); + goodix_disable_coor_filter(cd, cmd_val); goto exit; } @@ -4138,7 +4162,8 @@ static const struct file_operations cmd_list_ops = { }; #endif -int driver_test_selftest(char* buf) +/* [GOOG] */ +int driver_test_selftest(struct goodix_ts_core *cd, char *buf) { int ret = 0; @@ -4167,7 +4192,7 @@ int driver_test_selftest(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(true); + goodix_auto_test(cd, true); strlcpy(buf, rbuf, PAGE_SIZE); @@ -4179,22 +4204,24 @@ int driver_test_proc_init(struct goodix_ts_core *core_data) { struct proc_dir_entry *proc_entry; - proc_entry = proc_create( - "goodix_ts/driver_test", 0660, NULL, &driver_test_ops); + proc_entry = proc_create_data( + "driver_test", 0660, core_data->proc_dir_entry, &driver_test_ops, core_data); if (!proc_entry) { - ts_err("failed to create proc entry"); - return -ENOMEM; + ts_err("failed to create proc driver_test"); + return -ENODEV; } proc_entry = - proc_create("goodix_ts/cmd_list", 0440, NULL, &cmd_list_ops); - - cd = core_data; + 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; + } return 0; } -void driver_test_proc_remove(void) +void driver_test_proc_remove(struct goodix_ts_core *core_data) { - remove_proc_entry("goodix_ts/cmd_list", NULL); - remove_proc_entry("goodix_ts/driver_test", NULL); + remove_proc_entry("cmd_list", core_data->proc_dir_entry); + remove_proc_entry("driver_test", core_data->proc_dir_entry); } diff --git a/goodix_ts_tools.c b/goodix_ts_tools.c index 5fb175f..f648ba0 100644 --- a/goodix_ts_tools.c +++ b/goodix_ts_tools.c @@ -20,15 +20,14 @@ #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)); @@ -49,33 +48,9 @@ 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 */ @@ -85,7 +60,9 @@ 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]; - const struct goodix_ts_hw_ops *hw_ops = dev->ts_core->hw_ops; + 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; ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN); if (ret) @@ -105,7 +82,7 @@ static int async_read(struct goodix_tools_dev *dev, void __user *arg) return -ENOMEM; } - if (hw_ops->read(dev->ts_core, reg_addr, databuf, length)) { + if (hw_ops->read(ts_core, reg_addr, databuf, length)) { ret = -EBUSY; ts_err("Read i2c failed"); goto err_out; @@ -183,7 +160,8 @@ 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 = dev->ts_core; + 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; ret = copy_from_user(&i2c_msg_head, arg, I2C_MSG_HEAD_LEN); @@ -219,9 +197,6 @@ 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; @@ -254,29 +229,6 @@ 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 * @@ -290,15 +242,15 @@ static long goodix_tools_ioctl( { int ret = 0; struct goodix_tools_dev *dev = filp->private_data; - struct goodix_ts_core *ts_core; + struct goodix_ts_core *ts_core = + container_of(dev, struct goodix_ts_core, tools_dev); const struct goodix_ts_hw_ops *hw_ops; struct goodix_ic_config *temp_cfg = NULL; - if (dev->ts_core == NULL) { + if (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) { @@ -310,15 +262,9 @@ 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); @@ -327,9 +273,9 @@ static long goodix_tools_ioctl( break; case GTP_ESD_ENABLE: if (arg == 0) - goodix_ts_blocking_notify(NOTIFY_ESD_OFF, NULL); + goodix_ts_esd_off(ts_core); else - goodix_ts_blocking_notify(NOTIFY_ESD_ON, NULL); + goodix_ts_esd_on(ts_core); break; case GTP_DEV_RESET: hw_ops->reset(ts_core, GOODIX_NORMAL_RESET_DELAY_MS); @@ -346,7 +292,6 @@ 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( @@ -413,59 +358,49 @@ static long goodix_tools_compat_ioctl( } #endif -static int goodix_tools_open(struct inode *inode, struct file *filp) +static struct goodix_ts_core *core_data_locate(int minor) { - int ret = 0; + struct goodix_device_resource *res, *next; - 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; + 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("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; -} -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; + return NULL; } -static int goodix_tools_module_init( - struct goodix_ts_core *core_data, struct goodix_ext_module *module) +static int goodix_tools_open(struct inode *inode, struct file *filp) { - struct goodix_tools_dev *tools_dev = module->priv_data; + struct goodix_ts_core *cd = core_data_locate(iminor(inode)); - if (core_data) - tools_dev->ts_core = core_data; - else + if (!cd) { + ts_err("can't find core data"); 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_module_exit( - struct goodix_ts_core *core_data, struct goodix_ext_module *module) +static int goodix_tools_release( + struct inode *inode, struct file *filp) { - 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; + struct goodix_ts_core *cd = core_data_locate(iminor(inode)); + + if (!cd) { + ts_err("can't find core data"); + return -ENODEV; } + /* 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; } @@ -479,46 +414,21 @@ 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(void) +int goodix_tools_init(struct goodix_ts_core *core_data) { int ret; + struct goodix_tools_dev *tools_dev = &core_data->tools_dev; - 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); + 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); if (ret) ts_err("Debug tools miscdev register failed"); else @@ -527,9 +437,10 @@ int goodix_tools_init(void) return ret; } -void goodix_tools_exit(void) +void goodix_tools_exit(struct goodix_ts_core *core_data) { - misc_deregister(&goodix_tools_miscdev); - kfree(goodix_tools_dev); + struct goodix_tools_dev *tools_dev = &core_data->tools_dev; + + misc_deregister(&tools_dev->miscdev); ts_info("Debug tools miscdev exit"); } diff --git a/goodix_ts_utils.c b/goodix_ts_utils.c index 7649759..c3fc33e 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); + bool is_valid = !is_risk_data(data, size); /* [GOOG] */ if (mode == CHECKSUM_MODE_U8_LE) { if (size < 2) @@ -123,7 +123,11 @@ u32 goodix_get_file_config_id(u8 *ic_config) return le32_to_cpup((__le32 *)&ic_config[CONFIG_ID_OFFSET]); } -/* matrix transpose */ +/* + * matrix transpose: + * [GOOG] + * Add 'dest' as optional target(pa/2221748). + */ void goodix_rotate_abcd2cbad(int tx, int rx, s16 *src, s16 *dest) { s16 *temp_buf = dest; @@ -132,10 +136,14 @@ 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("malloc failed"); + ts_err("%s: malloc failed!\n", __func__); return; } } @@ -152,6 +160,7 @@ 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 */ |