diff --git a/drivers/input/touchscreen/gtx8/Kconfig b/drivers/input/touchscreen/gtx8/Kconfig index f665a37a62f1d4..c7581bb0be17ea 100644 --- a/drivers/input/touchscreen/gtx8/Kconfig +++ b/drivers/input/touchscreen/gtx8/Kconfig @@ -4,7 +4,8 @@ menuconfig TOUCHSCREEN_GOODIX_GTX8 tristate "Goodix GTx8 touchscreen" depends on I2C - default y + depends on OF + default n help Say Y here if you have a Goodix GTx8 touch controller to your system. diff --git a/drivers/input/touchscreen/gtx8/Makefile b/drivers/input/touchscreen/gtx8/Makefile index 0c2a720f59c7e2..8301113c70dfa5 100644 --- a/drivers/input/touchscreen/gtx8/Makefile +++ b/drivers/input/touchscreen/gtx8/Makefile @@ -1,2 +1,2 @@ obj-$(CONFIG_TOUCHSCREEN_GOODIX_GTX8) += gtx8.o -gtx8-y := goodix_ts_i2c.o goodix_ts_core.o goodix_cfg_bin.o +gtx8-y := goodix_ts_i2c.o goodix_ts_core.o diff --git a/drivers/input/touchscreen/gtx8/goodix_cfg_bin.c b/drivers/input/touchscreen/gtx8/goodix_cfg_bin.c deleted file mode 100644 index d80cd731279dd9..00000000000000 --- a/drivers/input/touchscreen/gtx8/goodix_cfg_bin.c +++ /dev/null @@ -1,605 +0,0 @@ -#include "goodix_cfg_bin.h" - -extern struct goodix_module goodix_modules; -int goodix_ts_stage2_init(struct goodix_ts_core *core_data); -int goodix_ts_core_release(void); - -static int goodix_parse_cfg_bin(struct goodix_cfg_bin *cfg_bin); -static int goodix_get_reg_and_cfg(struct goodix_ts_device *ts_dev, - struct goodix_cfg_bin *cfg_bin); -static int goodix_read_cfg_bin(struct device *dev, - struct goodix_cfg_bin *cfg_bin); -static void goodix_cfg_pkg_leToCpu(struct goodix_cfg_package *pkg); - -static int goodix_parse_cfg_bin(struct goodix_cfg_bin *cfg_bin) -{ - u8 checksum; - unsigned int i; - int r; - u16 offset1, offset2; - - if (!cfg_bin->bin_data || cfg_bin->bin_data_len == 0) { - ts_err("NO cfg_bin data, cfg_bin data length:%d", - cfg_bin->bin_data_len); - r = -EINVAL; - goto exit; - } - - /* copy cfg_bin head info */ - if (cfg_bin->bin_data_len < sizeof(struct goodix_cfg_bin_head)) { - ts_err("Invalid cfg_bin size:%d", cfg_bin->bin_data_len); - r = -EINVAL; - goto exit; - } - memcpy(&cfg_bin->head, cfg_bin->bin_data, - sizeof(struct goodix_cfg_bin_head)); - cfg_bin->head.bin_len = le32_to_cpu(cfg_bin->head.bin_len); - - /*check length*/ - if (cfg_bin->bin_data_len != cfg_bin->head.bin_len) { - ts_err("cfg_bin len check failed,%d != %d", - cfg_bin->head.bin_len, cfg_bin->bin_data_len); - r = -EINVAL; - goto exit; - } - - /*check cfg_bin valid*/ - checksum = 0; - for (i = TS_BIN_VERSION_START_INDEX; i < cfg_bin->bin_data_len; i++) { - checksum += cfg_bin->bin_data[i]; - } - if (checksum != cfg_bin->head.checksum) { - ts_err("cfg_bin checksum check filed 0x%02x != 0x%02x", - cfg_bin->head.checksum, checksum); - r = -EINVAL; - goto exit; - } - - /*allocate memory for cfg packages*/ - cfg_bin->cfg_pkgs = kzalloc(sizeof(struct goodix_cfg_package) * - cfg_bin->head.pkg_num, - GFP_KERNEL); - if (!cfg_bin->cfg_pkgs) { - ts_err("cfg_pkgs, allocate memory ERROR"); - r = -ENOMEM; - goto exit; - } - - /*get cfg_pkg's info*/ - for (i = 0; i < cfg_bin->head.pkg_num; i++) { - /*get cfg pkg length*/ - if (i == cfg_bin->head.pkg_num - 1) { - offset1 = cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN + - i * TS_CFG_OFFSET_LEN] + - (cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN + - i * TS_CFG_OFFSET_LEN + 1] - << 8); - - cfg_bin->cfg_pkgs[i].pkg_len = - cfg_bin->bin_data_len - offset1; - } else { - offset1 = cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN + - i * TS_CFG_OFFSET_LEN] + - (cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN + - i * TS_CFG_OFFSET_LEN + 1] - << 8); - - offset2 = cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN + - i * TS_CFG_OFFSET_LEN + 2] + - (cfg_bin->bin_data[TS_CFG_BIN_HEAD_LEN + - i * TS_CFG_OFFSET_LEN + 3] - << 8); - - if (offset2 <= offset1) { - ts_err("offset error,pkg:%d, offset1:%d, offset2:%d", - i, offset1, offset2); - r = -EINVAL; - goto exit; - } - - cfg_bin->cfg_pkgs[i].pkg_len = offset2 - offset1; - } - /*get cfg pkg head*/ - memcpy(&cfg_bin->cfg_pkgs[i].cnst_info, - &cfg_bin->bin_data[offset1], TS_PKG_CONST_INFO_LEN); - memcpy(&cfg_bin->cfg_pkgs[i].reg_info, - &cfg_bin->bin_data[offset1 + TS_PKG_CONST_INFO_LEN], - TS_PKG_REG_INFO_LEN); - /*compatible little edition and big edition*/ - goodix_cfg_pkg_leToCpu(&cfg_bin->cfg_pkgs[i]); - - /*get configuration data*/ - cfg_bin->cfg_pkgs[i].cfg = - &cfg_bin->bin_data[offset1 + TS_PKG_HEAD_LEN]; - } - - /*debug, print pkg information*/ - ts_debug("Driver bin info: ver %s, len %d, pkgs %d", - cfg_bin->head.bin_version, cfg_bin->head.bin_len, - cfg_bin->head.pkg_num); - for (i = 0; i < cfg_bin->head.pkg_num; i++) { - ts_debug("---------------------------------------------"); - ts_debug("------package:%d------", i + 1); - ts_debug("package len:%04x", - cfg_bin->cfg_pkgs[i].cnst_info.pkg_len); - ts_debug("package ic_type:%s", - cfg_bin->cfg_pkgs[i].cnst_info.ic_type); - ts_debug("package cfg_type:%01x", - cfg_bin->cfg_pkgs[i].cnst_info.cfg_type); - ts_debug("package sensor_id:%01x", - cfg_bin->cfg_pkgs[i].cnst_info.sensor_id); - ts_debug("package hw_pid:%s", - cfg_bin->cfg_pkgs[i].cnst_info.hw_pid); - ts_debug("package hw_vid:%s", - cfg_bin->cfg_pkgs[i].cnst_info.hw_vid); - ts_debug("package fw_mask_version:%s", - cfg_bin->cfg_pkgs[i].cnst_info.fw_mask); - ts_debug("package fw_patch_version:%s", - cfg_bin->cfg_pkgs[i].cnst_info.fw_patch); - ts_debug("package x_res_offset:%02x", - cfg_bin->cfg_pkgs[i].cnst_info.x_res_offset); - ts_debug("package y_res_offset:%02x", - cfg_bin->cfg_pkgs[i].cnst_info.y_res_offset); - ts_debug("package trigger_offset:%02x", - cfg_bin->cfg_pkgs[i].cnst_info.trigger_offset); - - ts_debug("reg info"); - ts_debug("send_cfg_flag reg:%02x", - cfg_bin->cfg_pkgs[i].reg_info.cfg_send_flag.addr); - ts_debug("version base reg:%02x, len:%d", - cfg_bin->cfg_pkgs[i].reg_info.version_base.addr, - cfg_bin->cfg_pkgs[i].reg_info.version_base.reserved1); - ts_debug("pid reg:%02x:%d", - cfg_bin->cfg_pkgs[i].reg_info.pid.addr, - cfg_bin->cfg_pkgs[i].reg_info.pid.reserved1); - ts_debug("vid reg:%02x:%d", - cfg_bin->cfg_pkgs[i].reg_info.vid.addr, - cfg_bin->cfg_pkgs[i].reg_info.vid.reserved1); - ts_debug("sensor_id reg:%02x,mask:%x", - cfg_bin->cfg_pkgs[i].reg_info.sensor_id.addr, - cfg_bin->cfg_pkgs[i].reg_info.sensor_id.addr); - ts_debug("fw_status reg:%02x", - cfg_bin->cfg_pkgs[i].reg_info.fw_status.addr); - ts_debug("cfg_addr reg:%02x", - cfg_bin->cfg_pkgs[i].reg_info.cfg_addr.addr); - ts_debug("esd reg:%02x", - cfg_bin->cfg_pkgs[i].reg_info.esd.addr); - ts_debug("command reg:%02x", - cfg_bin->cfg_pkgs[i].reg_info.command.addr); - ts_debug("coor:%02x", cfg_bin->cfg_pkgs[i].reg_info.coor.addr); - ts_debug("gesture:%02x", - cfg_bin->cfg_pkgs[i].reg_info.gesture.addr); - ts_debug("fw_request:%02x", - cfg_bin->cfg_pkgs[i].reg_info.fw_request.addr); - ts_debug("proximity:%02x", - cfg_bin->cfg_pkgs[i].reg_info.proximity.addr); - - ts_debug("--------------------------------------------"); - } - r = 0; -exit: - return r; -} - -static int goodix_cfg_bin_proc(struct goodix_ts_core *core_data) -{ - int r; - struct goodix_ts_device *ts_dev = core_data->ts_dev; - struct goodix_cfg_bin *cfg_bin = - kzalloc(sizeof(struct goodix_cfg_bin), GFP_KERNEL); - if (!cfg_bin) { - return -ENOMEM; - } - if (!ts_dev) { - ts_err("ts device can't be null"); - return -EINVAL; - } - - /* when start init config bin with error state */ - ts_dev->cfg_bin_state = CFG_BIN_STATE_ERROR; - - /*get cfg_bin from file system*/ - r = goodix_read_cfg_bin(ts_dev->dev, cfg_bin); - if (r < 0) { - ts_err("Failed get valid config bin data"); - goto exit; - } - /*parse cfg bin*/ - r = goodix_parse_cfg_bin(cfg_bin); - if (!r) { - ts_debug("parse cfg bin SUCCESS"); - } else { - ts_err("parse cfg bin FAILED"); - goto exit; - } - - /*get register address and configuration from cfg bin*/ - r = goodix_get_reg_and_cfg(ts_dev, cfg_bin); - if (!r) { - ts_debug("success get reg and cfg info from cfg bin"); - } else { - ts_err("failed get cfg and reg info, update fw then retry"); - } - - /*debug*/ - ts_debug("cfg_send_flag:0x%04x", ts_dev->reg.cfg_send_flag); - ts_debug("pid:0x%04x", ts_dev->reg.pid); - ts_debug("vid:0x%04x", ts_dev->reg.vid); - ts_debug("sensor_id:0x%04x", ts_dev->reg.sensor_id); - ts_debug("fw_mask:0x%04x", ts_dev->reg.fw_mask); - ts_debug("fw_status:0x%04x", ts_dev->reg.fw_status); - ts_debug("cfg_addr:0x%04x", ts_dev->reg.cfg_addr); - ts_debug("esd:0x%04x", ts_dev->reg.esd); - ts_debug("command:0x%04x", ts_dev->reg.command); - ts_debug("coor:0x%04x", ts_dev->reg.coor); - ts_debug("gesture:0x%04x", ts_dev->reg.gesture); - ts_debug("fw_request:0x%04x", ts_dev->reg.fw_request); - ts_debug("proximity:0x%04x", ts_dev->reg.proximity); - -exit: - kfree(cfg_bin->cfg_pkgs); - kfree(cfg_bin->bin_data); - kfree(cfg_bin); - if (r) - goodix_ts_blocking_notify(NOTIFY_CFG_BIN_FAILED, &r); - else - goodix_ts_blocking_notify(NOTIFY_CFG_BIN_SUCCESS, &r); - - ts_debug("cfg bin state %d, ret %d", ts_dev->cfg_bin_state, r); - return r; -} - -static int goodix_extract_cfg_pkg(struct goodix_ts_device *ts_dev, - struct goodix_cfg_package *cfg_pkg) -{ - struct goodix_ts_config *ts_cfg; - - if (cfg_pkg->cnst_info.cfg_type == TS_NORMAL_CFG) { - ts_cfg = &(ts_dev->normal_cfg); - } else if (cfg_pkg->cnst_info.cfg_type == TS_HIGH_SENSE_CFG) { - ts_cfg = &(ts_dev->highsense_cfg); - } else { - ts_err("unknown cfg type %d", cfg_pkg->cnst_info.cfg_type); - return -EINVAL; - } - - ts_cfg->length = - cfg_pkg->pkg_len - TS_PKG_CONST_INFO_LEN - TS_PKG_REG_INFO_LEN; - if (ts_cfg->length > sizeof(ts_cfg->data)) { - ts_err("illegal cfg length %d", ts_cfg->length); - return -EINVAL; - } - if (ts_cfg->length) { - ts_debug("get config type %d, len %d", - cfg_pkg->cnst_info.cfg_type, ts_cfg->length); - memcpy(ts_cfg->data, cfg_pkg->cfg, ts_cfg->length); - ts_cfg->initialized = TS_CFG_STABLE; - mutex_init(&ts_cfg->lock); - } else { - ts_debug("no config data"); - } - - /*get register info*/ - ts_dev->reg.cfg_send_flag = cfg_pkg->reg_info.cfg_send_flag.addr; - ts_dev->reg.version_base = cfg_pkg->reg_info.version_base.addr; - ts_dev->reg.version_len = cfg_pkg->reg_info.version_base.reserved1; - ts_dev->reg.pid = cfg_pkg->reg_info.pid.addr; - ts_dev->reg.pid_len = cfg_pkg->reg_info.pid.reserved1; - ts_dev->reg.vid = cfg_pkg->reg_info.vid.addr; - ts_dev->reg.vid_len = cfg_pkg->reg_info.vid.reserved1; - ts_dev->reg.sensor_id = cfg_pkg->reg_info.sensor_id.addr; - ts_dev->reg.sensor_id_mask = cfg_pkg->reg_info.sensor_id.reserved1; - ts_dev->reg.fw_mask = cfg_pkg->reg_info.fw_mask.addr; - ts_dev->reg.fw_status = cfg_pkg->reg_info.fw_status.addr; - ts_dev->reg.cfg_addr = cfg_pkg->reg_info.cfg_addr.addr; - ts_dev->reg.esd = cfg_pkg->reg_info.esd.addr; - ts_dev->reg.command = cfg_pkg->reg_info.command.addr; - ts_dev->reg.coor = cfg_pkg->reg_info.coor.addr; - ts_dev->reg.gesture = cfg_pkg->reg_info.gesture.addr; - ts_dev->reg.fw_request = cfg_pkg->reg_info.fw_request.addr; - ts_dev->reg.proximity = cfg_pkg->reg_info.proximity.addr; - - return 0; -} - -static int goodix_get_reg_and_cfg(struct goodix_ts_device *ts_dev, - struct goodix_cfg_bin *cfg_bin) -{ - int i; - u16 addr; - u8 read_len; - char temp_sensor_id = -1; - u8 temp_fw_mask[TS_CFG_BLOCK_FW_MASK_LEN] = { 0x00 }; - u8 temp_pid[TS_CFG_BLOCK_PID_LEN] = { 0x00 }; - int r = -EINVAL; - - if (!cfg_bin->head.pkg_num || !cfg_bin->cfg_pkgs) { - ts_err("there is none cfg package, pkg_num:%d", - cfg_bin->head.pkg_num); - return -EINVAL; - } - - memset(&ts_dev->normal_cfg, 0, sizeof(ts_dev->normal_cfg)); - memset(&ts_dev->highsense_cfg, 0, sizeof(ts_dev->highsense_cfg)); - - /* find suitable cfg packages */ - for (i = 0; i < cfg_bin->head.pkg_num; i++) { - /*get ic type*/ - if (!strncmp(cfg_bin->cfg_pkgs[i].cnst_info.ic_type, "normandy", - strlen("normandy"))) { - ts_dev->ic_type = IC_TYPE_NORMANDY; - } else if (!strncmp(cfg_bin->cfg_pkgs[i].cnst_info.ic_type, - "yellowstone", strlen("yellowstone"))) { - ts_dev->ic_type = IC_TYPE_YELLOWSTONE; - } else { - ts_err("unknown ic type of cfg_bin:%s", - cfg_bin->cfg_pkgs[i].cnst_info.ic_type); - continue; - } - - ts_debug("ic_type:%d", ts_dev->ic_type); - - /* contrast sensor id */ - addr = cfg_bin->cfg_pkgs[i].reg_info.sensor_id.addr; - if (!addr) { - ts_debug("pkg:%d, sensor_id reg is NULL", i); - continue; - } - - r = ts_dev->hw_ops->read(ts_dev, addr, &temp_sensor_id, 1); - if (r < 0) { - ts_err("failed get sensor of pkg:%d, reg:0x%02x", i, - addr); - goto get_default_pkg; - } - ts_debug("sensor id is %d", temp_sensor_id); - /*sensor.reserved1 is a mask, if it's not ZERO, use it*/ - if (cfg_bin->cfg_pkgs[i].reg_info.sensor_id.reserved1 != 0) - temp_sensor_id &= cfg_bin->cfg_pkgs[i] - .reg_info.sensor_id.reserved1; - - if (temp_sensor_id != - cfg_bin->cfg_pkgs[i].cnst_info.sensor_id) { - ts_err("pkg:%d, sensor id contrast FAILED, reg:0x%02x", - i, addr); - ts_err("sensor_id from i2c:%d, sensor_id of cfg bin:%d", - temp_sensor_id, - cfg_bin->cfg_pkgs[i].cnst_info.sensor_id); - continue; - } - - /*contrast fw_mask, if this reg is null, skip this step*/ - addr = cfg_bin->cfg_pkgs[i].reg_info.fw_mask.addr; - if (addr && cfg_bin->cfg_pkgs[i].cnst_info.fw_mask[0]) { - r = ts_dev->hw_ops->read(ts_dev, addr, temp_fw_mask, - sizeof(temp_fw_mask)); - if (r < 0) { - ts_err("failed read fw_mask pkg:%d, reg:0x%02x", - i, addr); - goto get_default_pkg; - } - if (strncmp(temp_fw_mask, - cfg_bin->cfg_pkgs[i].cnst_info.fw_mask, - sizeof(temp_fw_mask))) { - ts_err("pkg:%d, fw_mask contrast FAILED, reg:0x%02x,", - i, addr); - ts_err("mask from i2c:%s, mask of cfg bin:%s", - temp_fw_mask, - cfg_bin->cfg_pkgs[i].cnst_info.fw_mask); - continue; - } - } - - /*contrast pid*/ - addr = cfg_bin->cfg_pkgs[i].reg_info.pid.addr; - read_len = cfg_bin->cfg_pkgs[i].reg_info.pid.reserved1; - if (!addr) { - ts_err("pkg:%d, pid reg is NULL", i); - continue; - } - if (read_len <= 0 || read_len > TS_CFG_BLOCK_PID_LEN) { - ts_err("pkg:%d, hw_pid length ERROR, len:%d", i, - read_len); - continue; - } - r = ts_dev->hw_ops->read(ts_dev, addr, temp_pid, read_len); - if (r < 0) { - ts_err("failed read pid pkg:%d, pid reg:0x%02x", i, - addr); - goto get_default_pkg; - } - if (strncmp(temp_pid, cfg_bin->cfg_pkgs[i].cnst_info.hw_pid, - read_len)) { - ts_err("pkg:%d, pid contrast FAILED, reg:0x%02x", i, - addr); - ts_err("pid from i2c:%s, pid of cfg bin:%s", temp_pid, - cfg_bin->cfg_pkgs[i].cnst_info.hw_pid); - continue; - } - - ts_debug("try get package info: ic type %s, cfg type %d", - cfg_bin->cfg_pkgs[i].cnst_info.ic_type, - cfg_bin->cfg_pkgs[i].cnst_info.cfg_type); - /* currently only support normal and high_sense config */ - if (cfg_bin->cfg_pkgs[i].cnst_info.cfg_type == TS_NORMAL_CFG || - cfg_bin->cfg_pkgs[i].cnst_info.cfg_type == - TS_HIGH_SENSE_CFG) { - r = goodix_extract_cfg_pkg(ts_dev, - &cfg_bin->cfg_pkgs[i]); - if (!r) { - ts_dev->cfg_bin_state = - CFG_BIN_STATE_INITIALIZED; - ts_debug("success parse cfg bin"); - } else { - ts_err("failed parse cfg bin"); - break; - } - } - } - -get_default_pkg: - if (ts_dev->cfg_bin_state != CFG_BIN_STATE_INITIALIZED) { - ts_err("no valid normal cfg, use cfg_pkg 0 as default"); - /* Foo code for recover dead IC. - * force set package 0 config type to normal config, this will - * config will use to recover IC. - */ - cfg_bin->cfg_pkgs[0].cnst_info.cfg_type = TS_NORMAL_CFG; - if (goodix_extract_cfg_pkg(ts_dev, &cfg_bin->cfg_pkgs[0])) { - ts_err("failed get valid config for IC recover"); - ts_dev->cfg_bin_state = CFG_BIN_STATE_ERROR; - } else { - ts_dev->cfg_bin_state = CFG_BIN_STATE_TEMP; - ts_debug("get temp config data"); - } - - r = -EINVAL; - } - - return r; -} - -static int goodix_read_cfg_bin(struct device *dev, - struct goodix_cfg_bin *cfg_bin) -{ - const struct firmware *firmware = NULL; - char cfg_bin_name[32] = { 0x00 }; - int i = 0, r; - - /*get cfg_bin_name*/ - strlcpy(cfg_bin_name, TS_DEFAULT_CFG_BIN, sizeof(cfg_bin_name)); - - ts_debug("cfg_bin_name:%s", cfg_bin_name); - - for (i = 0; i < TS_RQST_FW_RETRY_TIMES; i++) { - r = request_firmware(&firmware, cfg_bin_name, dev); - if (r < 0) { - ts_err("failed get cfg bin[%s] error:%d, try_times:%d", - cfg_bin_name, r, i + 1); - msleep(1000); - } else { - ts_debug("Cfg_bin image [%s] is ready, try_times:%d", - cfg_bin_name, i + 1); - break; - } - } - if (i >= TS_RQST_FW_RETRY_TIMES) { - ts_err("get cfg_bin FAILED"); - goto exit; - } - - if (firmware->size <= 0) { - ts_err("request_firmware, cfg_bin length ERROR,len:%zu", - firmware->size); - r = -EINVAL; - goto exit; - } - - cfg_bin->bin_data_len = firmware->size; - /*allocate memory for cfg_bin->bin_data*/ - cfg_bin->bin_data = kzalloc(cfg_bin->bin_data_len, GFP_KERNEL); - if (!cfg_bin->bin_data) - r = -ENOMEM; - - memcpy(cfg_bin->bin_data, firmware->data, cfg_bin->bin_data_len); - - r = 0; -exit: - if (firmware) { - release_firmware(firmware); - firmware = NULL; - } - return r; -} - -static void goodix_cfg_pkg_leToCpu(struct goodix_cfg_package *pkg) -{ - if (!pkg) { - ts_err("cfg package is NULL"); - return; - } - /*package const_info*/ - pkg->cnst_info.pkg_len = le32_to_cpu(pkg->cnst_info.pkg_len); - pkg->cnst_info.x_res_offset = le16_to_cpu(pkg->cnst_info.x_res_offset); - pkg->cnst_info.y_res_offset = le16_to_cpu(pkg->cnst_info.y_res_offset); - pkg->cnst_info.trigger_offset = - le16_to_cpu(pkg->cnst_info.trigger_offset); - - /*package reg_info*/ - pkg->reg_info.cfg_send_flag.addr = - le16_to_cpu(pkg->reg_info.cfg_send_flag.addr); - pkg->reg_info.pid.addr = le16_to_cpu(pkg->reg_info.pid.addr); - pkg->reg_info.vid.addr = le16_to_cpu(pkg->reg_info.vid.addr); - pkg->reg_info.sensor_id.addr = - le16_to_cpu(pkg->reg_info.sensor_id.addr); - pkg->reg_info.fw_status.addr = - le16_to_cpu(pkg->reg_info.fw_status.addr); - pkg->reg_info.cfg_addr.addr = le16_to_cpu(pkg->reg_info.cfg_addr.addr); - pkg->reg_info.esd.addr = le16_to_cpu(pkg->reg_info.esd.addr); - pkg->reg_info.command.addr = le16_to_cpu(pkg->reg_info.command.addr); - pkg->reg_info.coor.addr = le16_to_cpu(pkg->reg_info.coor.addr); - pkg->reg_info.gesture.addr = le16_to_cpu(pkg->reg_info.gesture.addr); - pkg->reg_info.fw_request.addr = - le16_to_cpu(pkg->reg_info.fw_request.addr); - pkg->reg_info.proximity.addr = - le16_to_cpu(pkg->reg_info.proximity.addr); -} - -static int goodix_later_init_thread(void *data) -{ - int ret; - struct goodix_ts_core *ts_core = data; - struct goodix_ts_device *ts_dev; - - if (!data) { - ts_err("ts core data can't be null"); - return -EINVAL; - } - ts_dev = ts_core->ts_dev; - if (!ts_dev) { - ts_err("ts dev data can't be null"); - return -EINVAL; - } - - ret = goodix_cfg_bin_proc(ts_core); - if (ret) - ts_err("parse cfg bin encounter error, %d", ret); - else - ts_debug("success get cfg bin"); - - if (ts_dev->cfg_bin_state == CFG_BIN_STATE_ERROR) { - ts_err("parse cfg bin encounter fatal err"); - goto release_core; - } - - if (ts_dev->cfg_bin_state == CFG_BIN_STATE_TEMP) { - ts_err("failed get valid config data"); - goto release_core; - } else { - ts_info("success parse config bin"); - } - ret = goodix_ts_stage2_init(ts_core); - if (!ret) { - ts_debug("stage2 init success"); - return ret; - } - ts_err("stage2 init failed, %d", ret); - -release_core: - goodix_ts_core_release(); - return ret; -} - -int goodix_start_later_init(struct goodix_ts_core *ts_core) -{ - struct task_struct *init_thrd; - /* create and run update thread */ - init_thrd = kthread_run(goodix_later_init_thread, ts_core, - "goodix_init_thread"); - if (IS_ERR_OR_NULL(init_thrd)) { - ts_err("Failed to create update thread:%ld", - PTR_ERR(init_thrd)); - return -EFAULT; - } - return 0; -} diff --git a/drivers/input/touchscreen/gtx8/goodix_cfg_bin.h b/drivers/input/touchscreen/gtx8/goodix_cfg_bin.h deleted file mode 100644 index e04e3008f9e14e..00000000000000 --- a/drivers/input/touchscreen/gtx8/goodix_cfg_bin.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef _GOODIX_CFG_BIN_H_ -#define _GOODIX_CFG_BIN_H_ - -#include "goodix_ts_core.h" - -#define TS_DEFAULT_CFG_BIN "goodix_cfg_group.bin" -#define TS_BIN_VERSION_START_INDEX 5 -#define TS_BIN_VERSION_LEN 4 -#define TS_CFG_BIN_HEAD_RESERVED_LEN 6 -#define TS_CFG_OFFSET_LEN 2 -#define TS_IC_TYPE_NAME_MAX_LEN 15 -#define TS_CFG_BIN_HEAD_LEN \ - (sizeof(struct goodix_cfg_bin_head) + TS_CFG_BIN_HEAD_RESERVED_LEN) -#define TS_PKG_CONST_INFO_LEN (sizeof(struct goodix_cfg_pkg_const_info)) -#define TS_PKG_REG_INFO_LEN (sizeof(struct goodix_cfg_pkg_reg_info)) -#define TS_PKG_HEAD_LEN (TS_PKG_CONST_INFO_LEN + TS_PKG_REG_INFO_LEN) - -/*cfg block definitin*/ -#define TS_CFG_BLOCK_PID_LEN 8 -#define TS_CFG_BLOCK_VID_LEN 8 -#define TS_CFG_BLOCK_FW_MASK_LEN 9 -#define TS_CFG_BLOCK_FW_PATCH_LEN 4 -#define TS_CFG_BLOCK_RESERVED_LEN 9 - -#define TS_NORMAL_CFG 0x01 -#define TS_HIGH_SENSE_CFG 0x03 -#define TS_RQST_FW_RETRY_TIMES 2 - -#pragma pack(1) -struct goodix_cfg_pkg_reg { - u16 addr; - u8 reserved1; - u8 reserved2; -}; - -struct goodix_cfg_pkg_const_info { - u32 pkg_len; - u8 ic_type[TS_IC_TYPE_NAME_MAX_LEN]; - u8 cfg_type; - u8 sensor_id; - u8 hw_pid[TS_CFG_BLOCK_PID_LEN]; - u8 hw_vid[TS_CFG_BLOCK_VID_LEN]; - u8 fw_mask[TS_CFG_BLOCK_FW_MASK_LEN]; - u8 fw_patch[TS_CFG_BLOCK_FW_PATCH_LEN]; - u16 x_res_offset; - u16 y_res_offset; - u16 trigger_offset; -}; - -struct goodix_cfg_pkg_reg_info { - struct goodix_cfg_pkg_reg cfg_send_flag; - struct goodix_cfg_pkg_reg version_base; - struct goodix_cfg_pkg_reg pid; - struct goodix_cfg_pkg_reg vid; - struct goodix_cfg_pkg_reg sensor_id; - struct goodix_cfg_pkg_reg fw_mask; - struct goodix_cfg_pkg_reg fw_status; - struct goodix_cfg_pkg_reg cfg_addr; - struct goodix_cfg_pkg_reg esd; - struct goodix_cfg_pkg_reg command; - struct goodix_cfg_pkg_reg coor; - struct goodix_cfg_pkg_reg gesture; - struct goodix_cfg_pkg_reg fw_request; - struct goodix_cfg_pkg_reg proximity; - u8 reserved[TS_CFG_BLOCK_RESERVED_LEN]; -}; - -struct goodix_cfg_bin_head { - u32 bin_len; - u8 checksum; - u8 bin_version[TS_BIN_VERSION_LEN]; - u8 pkg_num; -}; - -#pragma pack() - -struct goodix_cfg_package { - struct goodix_cfg_pkg_const_info cnst_info; - struct goodix_cfg_pkg_reg_info reg_info; - const u8 *cfg; - u32 pkg_len; -}; - -struct goodix_cfg_bin { - unsigned char *bin_data; - unsigned int bin_data_len; - struct goodix_cfg_bin_head head; - struct goodix_cfg_package *cfg_pkgs; -}; - -#endif diff --git a/drivers/input/touchscreen/gtx8/goodix_ts_core.c b/drivers/input/touchscreen/gtx8/goodix_ts_core.c index a2ca803e1c0e81..501ecbcc7ae080 100644 --- a/drivers/input/touchscreen/gtx8/goodix_ts_core.c +++ b/drivers/input/touchscreen/gtx8/goodix_ts_core.c @@ -41,7 +41,6 @@ #define PINCTRL_STATE_SUSPEND "sleep" static int goodix_ts_remove(struct platform_device *pdev); -int goodix_start_later_init(struct goodix_ts_core *ts_core); void goodix_ts_dev_release(void); struct goodix_module goodix_modules; @@ -441,155 +440,6 @@ static ssize_t goodix_ts_reset_store(struct device *dev, return count; } -static ssize_t goodix_ts_read_cfg_show(struct device *dev, - struct device_attribute *attr - __attribute__((unused)), - char *buf) -{ - struct goodix_ts_core *core_data = dev_get_drvdata(dev); - struct goodix_ts_device *ts_dev = core_data->ts_dev; - int ret, i, offset; - char *cfg_buf; - - cfg_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); - if (!cfg_buf) - return -ENOMEM; - - if (ts_dev->hw_ops->read_config) - ret = ts_dev->hw_ops->read_config(ts_dev, cfg_buf); - else - ret = -EINVAL; - - if (ret > 0) { - offset = 0; - for (i = 0; i < ret; i++) { - if (i != 0 && i % 20 == 0) - buf[offset++] = '\n'; - offset += snprintf(&buf[offset], PAGE_SIZE - offset, - "%02x,", cfg_buf[i]); - } - } - kfree(cfg_buf); - if (ret <= 0) - return ret; - - return offset; -} - -static u8 ascii2hex(u8 a) -{ - s8 value = 0; - - if (a >= '0' && a <= '9') - value = a - '0'; - else if (a >= 'A' && a <= 'F') - value = a - 'A' + 0x0A; - else if (a >= 'a' && a <= 'f') - value = a - 'a' + 0x0A; - else - value = 0xff; - - return value; -} - -static int goodix_ts_convert_0x_data(const u8 *buf, int buf_size, - unsigned char *out_buf, int *out_buf_len) -{ - int i, m_size = 0; - int temp_index = 0; - u8 high, low; - - for (i = 0; i < buf_size; i++) { - if (buf[i] == 'x' || buf[i] == 'X') - m_size++; - } - - if (m_size <= 1) { - ts_err("cfg file ERROR, valid data count:%d\n", m_size); - return -EINVAL; - } - *out_buf_len = m_size; - - for (i = 0; i < buf_size; i++) { - if (buf[i] != 'x' && buf[i] != 'X') - continue; - - if (temp_index >= m_size) { - ts_err("exchange cfg data error, overflow," - "temp_index:%d,m_size:%d\n", - temp_index, m_size); - return -EINVAL; - } - high = ascii2hex(buf[i + 1]); - low = ascii2hex(buf[i + 2]); - if (high == 0xff || low == 0xff) { - ts_err("failed convert: 0x%x, 0x%x", buf[i + 1], - buf[i + 2]); - return -EINVAL; - } - out_buf[temp_index++] = (high << 4) + low; - } - return 0; -} - -static ssize_t goodix_ts_send_cfg_store(struct device *dev, - struct device_attribute *attr - __attribute__((unused)), - const char *buf, size_t count) -{ - struct goodix_ts_core *core_data = dev_get_drvdata(dev); - struct goodix_ts_device *ts_dev = core_data->ts_dev; - int en, r; - const struct firmware *cfg_img; - struct goodix_ts_config *config = NULL; - - if (sscanf(buf, "%d", &en) != 1) - return -EINVAL; - - if (en != 1) - return -EINVAL; - - disable_irq(core_data->irq); - - /*request configuration*/ - r = request_firmware(&cfg_img, GOODIX_DEFAULT_CFG_NAME, dev); - if (r < 0) { - ts_err("cfg file [%s] not available,errno:%d", - GOODIX_DEFAULT_CFG_NAME, r); - goto exit; - } else - ts_debug("cfg file [%s] is ready", GOODIX_DEFAULT_CFG_NAME); - - config = kzalloc(sizeof(*config), GFP_KERNEL); - if (config == NULL) - goto exit; - - /*parse cfg data*/ - if (goodix_ts_convert_0x_data(cfg_img->data, cfg_img->size, - config->data, &config->length)) { - ts_err("convert config data FAILED"); - goto exit; - } - - config->reg_base = ts_dev->reg.cfg_addr; - mutex_init(&config->lock); - config->initialized = TS_CFG_STABLE; - - if (ts_dev->hw_ops->send_config) - ts_dev->hw_ops->send_config(ts_dev, config); - -exit: - enable_irq(core_data->irq); - kfree(config); - config = NULL; - if (cfg_img) { - release_firmware(cfg_img); - cfg_img = NULL; - } - - return count; -} - /* show irq information */ static ssize_t goodix_ts_irq_info_show(struct device *dev, struct device_attribute *attr @@ -779,8 +629,6 @@ static DEVICE_ATTR(extmod_info, S_IRUGO, goodix_ts_extmod_show, NULL); static DEVICE_ATTR(driver_info, S_IRUGO, goodix_ts_driver_info_show, NULL); static DEVICE_ATTR(chip_info, S_IRUGO, goodix_ts_chip_info_show, NULL); static DEVICE_ATTR(reset, S_IWUSR | S_IWGRP, NULL, goodix_ts_reset_store); -static DEVICE_ATTR(send_cfg, S_IWUSR | S_IWGRP, NULL, goodix_ts_send_cfg_store); -static DEVICE_ATTR(read_cfg, S_IRUGO, goodix_ts_read_cfg_show, NULL); static DEVICE_ATTR(irq_info, S_IRUGO | S_IWUSR | S_IWGRP, goodix_ts_irq_info_show, goodix_ts_irq_info_store); static DEVICE_ATTR(reg_rw, S_IRUGO | S_IWUSR | S_IWGRP, goodix_ts_reg_rw_show, @@ -791,8 +639,6 @@ static struct attribute *sysfs_attrs[] = { &dev_attr_driver_info.attr, &dev_attr_chip_info.attr, &dev_attr_reset.attr, - &dev_attr_send_cfg.attr, - &dev_attr_read_cfg.attr, &dev_attr_irq_info.attr, &dev_attr_reg_rw.attr, NULL, @@ -802,98 +648,13 @@ static const struct attribute_group sysfs_group = { .attrs = sysfs_attrs, }; -static ssize_t goodix_sysfs_config_write(struct file *file - __attribute__((unused)), - struct kobject *kobj, - struct bin_attribute *attr - __attribute__((unused)), - char *buf, loff_t pos, size_t count) -{ - struct platform_device *pdev = - container_of(kobj_to_dev(kobj), struct platform_device, dev); - struct goodix_ts_core *ts_core = platform_get_drvdata(pdev); - struct goodix_ts_device *ts_dev = ts_core->ts_dev; - struct goodix_ts_config *config = NULL; - int ret; - - if (pos != 0 || count > GOODIX_CFG_MAX_SIZE) { - ts_debug("pos(%d) != 0, cfg size %zu", (int)pos, count); - return -EINVAL; - } - - config = kzalloc(sizeof(struct goodix_ts_config), GFP_KERNEL); - if (config == NULL) - return -ENOMEM; - - memcpy(config->data, buf, count); - config->length = count; - config->reg_base = ts_dev->reg.cfg_addr; - mutex_init(&config->lock); - config->initialized = true; - - ret = ts_dev->hw_ops->send_config(ts_dev, config); - if (ret) { - count = -EINVAL; - ts_err("send config failed %d", ret); - } else { - ts_debug("send config success"); - } - - kfree(config); - return count; -} - -static ssize_t goodix_sysfs_config_read( - struct file *file __attribute__((unused)), struct kobject *kobj, - struct bin_attribute *attr __attribute__((unused)), char *buf, - loff_t pos, size_t size __attribute__((unused))) -{ - struct platform_device *pdev = - container_of(kobj_to_dev(kobj), struct platform_device, dev); - struct goodix_ts_core *ts_core = platform_get_drvdata(pdev); - struct goodix_ts_device *ts_dev = ts_core->ts_dev; - int ret; - - ts_debug("pos = %d, size = %zu", (int)pos, size); - - if (pos != 0) - return 0; - - if (ts_dev->hw_ops->read_config) - ret = ts_dev->hw_ops->read_config(ts_dev, buf); - else - ret = -EINVAL; - - ts_debug("read config ret %d", ret); - return ret; -} - -static struct bin_attribute goodix_config_bin_attr = { - .attr = { - .name = "config_bin", - .mode = S_IRUGO | S_IWUSR | S_IWGRP, - }, - .size = GOODIX_CFG_MAX_SIZE, - .read = goodix_sysfs_config_read, - .write = goodix_sysfs_config_write, -}; - static int goodix_ts_sysfs_init(struct goodix_ts_core *core_data) { int ret; - ret = sysfs_create_bin_file(&core_data->pdev->dev.kobj, - &goodix_config_bin_attr); - if (ret) { - ts_err("failed create config bin attr"); - return ret; - } - ret = sysfs_create_group(&core_data->pdev->dev.kobj, &sysfs_group); if (ret) { ts_err("failed create core sysfs group"); - sysfs_remove_bin_file(&core_data->pdev->dev.kobj, - &goodix_config_bin_attr); return ret; } @@ -902,8 +663,6 @@ static int goodix_ts_sysfs_init(struct goodix_ts_core *core_data) static void goodix_ts_sysfs_exit(struct goodix_ts_core *core_data) { - sysfs_remove_bin_file(&core_data->pdev->dev.kobj, - &goodix_config_bin_attr); sysfs_remove_group(&core_data->pdev->dev.kobj, &sysfs_group); } @@ -945,35 +704,6 @@ int goodix_ts_blocking_notify(enum ts_notify_event evt, void *v) } EXPORT_SYMBOL_GPL(goodix_ts_blocking_notify); -static void goodix_ts_report_pen(struct input_dev *dev, - struct goodix_pen_data *pen_data) -{ - int i; - - if (pen_data->coords.status == TS_TOUCH) { - input_report_key(dev, BTN_TOUCH, 1); - input_report_key(dev, pen_data->coords.tool_type, 1); - } else if (pen_data->coords.status == TS_RELEASE) { - input_report_key(dev, BTN_TOUCH, 0); - input_report_key(dev, pen_data->coords.tool_type, 0); - } - if (pen_data->coords.status) { - input_report_abs(dev, ABS_X, pen_data->coords.x); - input_report_abs(dev, ABS_Y, pen_data->coords.y); - input_report_abs(dev, ABS_PRESSURE, pen_data->coords.p); - } - /* report pen button */ - for (i = 0; i < GOODIX_MAX_PEN_KEY; i++) { - if (!pen_data->keys[i].status) - continue; - if (pen_data->keys[i].status == TS_TOUCH) - input_report_key(dev, pen_data->keys[i].code, 1); - else if (pen_data->keys[i].status == TS_RELEASE) - input_report_key(dev, pen_data->keys[i].code, 0); - } - input_sync(dev); -} - static void goodix_ts_report_finger(struct input_dev *dev, struct goodix_touch_data *touch_data) { @@ -1060,11 +790,6 @@ static irqreturn_t goodix_ts_threadirq_func(int irq __attribute__((unused)), goodix_ts_report_finger(core_data->input_dev, &ts_event->touch_data); } - if (ts_dev->board_data.pen_enable && - ts_event->event_type == EVENT_PEN) { - goodix_ts_report_pen(core_data->pen_dev, - &ts_event->pen_data); - } } /* clean irq flag */ @@ -1422,48 +1147,6 @@ static int goodix_ts_input_dev_config(struct goodix_ts_core *core_data) return 0; } -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 r; - - pen_dev = input_allocate_device(); - if (!pen_dev) { - ts_err("Failed to allocated pen device"); - return -ENOMEM; - } - core_data->pen_dev = pen_dev; - input_set_drvdata(pen_dev, core_data); - - pen_dev->name = GOODIX_PEN_DRIVER_NAME; - pen_dev->id.product = 0xDEAD; - pen_dev->id.vendor = 0xBEEF; - pen_dev->id.version = 10427; - - pen_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - __set_bit(ABS_X, pen_dev->absbit); - __set_bit(ABS_Y, pen_dev->absbit); - __set_bit(BTN_STYLUS, pen_dev->keybit); - __set_bit(BTN_STYLUS2, pen_dev->keybit); - __set_bit(BTN_TOUCH, pen_dev->keybit); - __set_bit(BTN_TOOL_PEN, pen_dev->keybit); - __set_bit(INPUT_PROP_DIRECT, pen_dev->propbit); - input_set_abs_params(pen_dev, ABS_X, 0, ts_bdata->panel_max_x, 0, 0); - input_set_abs_params(pen_dev, ABS_Y, 0, ts_bdata->panel_max_y, 0, 0); - input_set_abs_params(pen_dev, ABS_PRESSURE, 0, GOODIX_PEN_MAX_PRESSURE, - 0, 0); - - r = input_register_device(pen_dev); - if (r < 0) { - ts_err("Unable to register pen device"); - input_free_device(pen_dev); - return r; - } - - return 0; -} - void goodix_ts_input_dev_remove(struct goodix_ts_core *core_data) { input_unregister_device(core_data->input_dev); @@ -1471,13 +1154,6 @@ void goodix_ts_input_dev_remove(struct goodix_ts_core *core_data) core_data->input_dev = NULL; } -void goodix_ts_pen_dev_remove(struct goodix_ts_core *core_data) -{ - input_unregister_device(core_data->pen_dev); - input_free_device(core_data->pen_dev); - core_data->pen_dev = NULL; -} - /** * goodix_ts_esd_work - check hardware status and recovery * the hardware if needed. @@ -1867,17 +1543,11 @@ static int goodix_ts_pm_resume(struct device *dev) #endif #endif -int goodix_ts_stage2_init(struct goodix_ts_core *core_data) +int goodix_ts_init(struct goodix_ts_core *core_data) { int r; struct goodix_ts_device *ts_dev = ts_device(core_data); - /* send normal-cfg to firmware */ - r = ts_dev->hw_ops->send_config(ts_dev, &(ts_dev->normal_cfg)); - if (r < 0) { - ts_debug("failed send normal config[ignore]"); - } - r = ts_dev->hw_ops->read_version(ts_dev, &ts_dev->chip_version); if (r < 0) ts_debug("failed read fw version info[ignore]"); @@ -1889,18 +1559,11 @@ int goodix_ts_stage2_init(struct goodix_ts_core *core_data) return r; } - if (ts_dev->board_data.pen_enable) { - r = goodix_ts_pen_dev_config(core_data); - if (r < 0) { - ts_err("failed set pen device"); - goto err_finger; - } - } /* request irq line */ r = goodix_ts_irq_setup(core_data); if (r < 0) { ts_debug("failed set irq"); - goto exit; + goto err_finger; } ts_debug("success register irq"); @@ -1920,10 +1583,6 @@ int goodix_ts_stage2_init(struct goodix_ts_core *core_data) /* esd protector */ goodix_ts_esd_init(core_data); return 0; -exit: - if (ts_dev->board_data.pen_enable) { - goodix_ts_pen_dev_remove(core_data); - } err_finger: goodix_ts_input_dev_remove(core_data); return r; @@ -1991,13 +1650,6 @@ static int goodix_ts_probe(struct platform_device *pdev) goto out; } - /* Try start a thread to get config-bin info */ - r = goodix_start_later_init(core_data); - if (r) { - ts_debug("Failed start cfg_bin_proc"); - goto out; - } - core_data->initialized = 1; goodix_modules.core_data = core_data; core_module_prob_sate = CORE_MODULE_PROB_SUCCESS; @@ -2006,10 +1658,14 @@ static int goodix_ts_probe(struct platform_device *pdev) kfree(core_data); core_data = NULL; core_module_prob_sate = CORE_MODULE_PROB_FAILED; + } else { + goodix_ts_init(core_data); } + ts_info("goodix_ts_probe OUT, r:%d", r); /* wakeup ext module register work */ complete_all(&goodix_modules.core_comp); + return r; } diff --git a/drivers/input/touchscreen/gtx8/goodix_ts_core.h b/drivers/input/touchscreen/gtx8/goodix_ts_core.h index e6f2327592b943..7ce0b45c2e7fab 100644 --- a/drivers/input/touchscreen/gtx8/goodix_ts_core.h +++ b/drivers/input/touchscreen/gtx8/goodix_ts_core.h @@ -36,10 +36,8 @@ #include #include #include -#ifdef CONFIG_OF #include #include -#endif #ifdef CONFIG_HAS_EARLYSUSPEND #include #endif @@ -60,12 +58,8 @@ #define GOODIX_PID_MAX_LEN 8 #define GOODIX_VID_MAX_LEN 8 -#define GOODIX_DEFAULT_CFG_NAME "goodix_config.cfg" - -#define IC_TYPE_NONE 0 -#define IC_TYPE_NORMANDY 1 -#define IC_TYPE_NANJING 2 -#define IC_TYPE_YELLOWSTONE 3 +#define IC_TYPE_NORMANDY 0 +#define IC_TYPE_YELLOWSTONE 1 #define GOODIX_TOUCH_EVENT 0x80 #define GOODIX_REQUEST_EVENT 0x40 @@ -129,7 +123,6 @@ struct goodix_ts_board_data { unsigned int panel_key_map[GOODIX_MAX_TP_KEY]; unsigned int x2x; unsigned int y2y; - bool pen_enable; unsigned int tp_key_num; /*add end*/ @@ -209,8 +202,6 @@ enum ts_notify_event { NOTIFY_RESUME, NOTIFY_ESD_OFF, NOTIFY_ESD_ON, - NOTIFY_CFG_BIN_FAILED, - NOTIFY_CFG_BIN_SUCCESS, }; enum touch_point_status { @@ -278,8 +269,6 @@ struct goodix_ts_version { }; struct goodix_ts_regs { - u16 cfg_send_flag; - u16 version_base; u8 version_len; @@ -292,17 +281,48 @@ struct goodix_ts_regs { u16 sensor_id; u8 sensor_id_mask; - u16 fw_mask; - u16 fw_status; u16 cfg_addr; u16 esd; u16 command; u16 coor; - u16 gesture; u16 fw_request; u16 proximity; }; +static const struct goodix_ts_regs goodix_ts_regs_normandy = { + version_base: 17708, + version_len: 72, + pid: 17717, + pid_len: 4, + vid: 17725, + vid_len: 4, + sensor_id: 17729, + sensor_id_mask: 15, + cfg_addr: 28536, + esd: 12531, + command: 28520, + coor: 16640, + fw_request: 0, + proximity: 0, +}; + +static const struct goodix_ts_regs goodix_ts_regs_yellowstone = { + version_base: 16404, + version_len: 135, + pid: 16418, + pid_len: 4, + vid: 16426, + vid_len: 4, + sensor_id: 16431, + sensor_id_mask: 15, + cfg_addr: 38648, + esd: 16742, + command: 16736, + coor: 16768, + fw_request: 16768, + proximity: 16770, +}; + enum goodix_cfg_bin_state { CFG_BIN_STATE_UNINIT, /* config bin uninit */ CFG_BIN_STATE_ERROR, /* config bin encounter fatal error */ @@ -319,8 +339,6 @@ enum goodix_cfg_bin_state { * @cfg_bin_state: see enum goodix_cfg_bin_state * @fw_uptodate: set to 1 after do fw update * @board_data: board data obtained from dts - * @normal_cfg: normal config data - * @highsense_cfg: high sense config data * @hw_ops: hardware operations * @chip_version: firmware version information * @sleep_cmd: sleep commang @@ -335,8 +353,6 @@ struct goodix_ts_device { int cfg_bin_state; struct goodix_ts_regs reg; struct goodix_ts_board_data board_data; - struct goodix_ts_config normal_cfg; - struct goodix_ts_config highsense_cfg; const struct goodix_ts_hw_ops *hw_ops; struct goodix_ts_version chip_version; @@ -350,7 +366,6 @@ struct goodix_ts_device { * @read: read data from touch device * @write: write data to touch device * @send_cmd: send command to touch device - * @send_config: send configuration data * @read_version: read firmware version * @event_handler: touch event handler * @suspend: put touch device into low power mode @@ -370,9 +385,6 @@ struct goodix_ts_hw_ops { unsigned char *data, unsigned int len); int (*send_cmd)(struct goodix_ts_device *dev, struct goodix_ts_cmd *cmd); - int (*send_config)(struct goodix_ts_device *dev, - struct goodix_ts_config *config); - int (*read_config)(struct goodix_ts_device *dev, u8 *config_data); int (*read_version)(struct goodix_ts_device *dev, struct goodix_ts_version *version); int (*event_handler)(struct goodix_ts_device *dev, diff --git a/drivers/input/touchscreen/gtx8/goodix_ts_i2c.c b/drivers/input/touchscreen/gtx8/goodix_ts_i2c.c index d97005e09d6527..33084c3c78ccb9 100644 --- a/drivers/input/touchscreen/gtx8/goodix_ts_i2c.c +++ b/drivers/input/touchscreen/gtx8/goodix_ts_i2c.c @@ -23,8 +23,8 @@ #include #include #include +#include #include "goodix_ts_core.h" -#include "goodix_cfg_bin.h" #define TS_DRIVER_NAME "gtx8" #define I2C_MAX_TRANSFER_SIZE 256 @@ -90,7 +90,6 @@ enum TS_SEND_CFG_REPLY { #define IRQ_HEAD_LEN_NOR 2 int goodix_ts_core_init(void); -#ifdef CONFIG_OF /** * goodix_parse_dt_resolution - parse resolution from dt * @node: devicetree node @@ -241,12 +240,6 @@ static int goodix_parse_dt(struct device_node *node, } } - /*get pen-enable switch and pen keys, must after "key map"*/ - board_data->pen_enable = - of_property_read_bool(node, "goodix,pen-enable"); - if (board_data->pen_enable) - ts_debug("goodix pen enabled"); - ts_debug("***key:%d, %d, %d, %d", board_data->panel_key_map[0], board_data->panel_key_map[1], board_data->panel_key_map[2], board_data->panel_key_map[3]); @@ -256,7 +249,6 @@ static int goodix_parse_dt(struct device_node *node, board_data->panel_max_p); return 0; } -#endif int goodix_i2c_test(struct goodix_ts_device *dev) { @@ -831,449 +823,6 @@ static int goodix_read_version(struct goodix_ts_device *dev, return r; } -static int goodix_wait_cfg_cmd_ready(struct goodix_ts_device *dev, u8 right_cmd, - u8 send_cmd) -{ - int try_times = 0; - u8 cmd_flag = 0; - u8 cmd_buf[3] = { 0 }; - u16 command_reg = dev->reg.command; - struct goodix_ts_cmd ts_cmd; - - goodix_cmd_init(dev, &ts_cmd, send_cmd, 0, command_reg); - - for (try_times = 0; try_times < TS_WAIT_CFG_READY_RETRY_TIMES; - try_times++) { - if (goodix_i2c_read(dev, command_reg, cmd_buf, 3)) { - ts_err("Read cmd_reg error"); - return -EINVAL; - } - cmd_flag = cmd_buf[0]; - if (cmd_flag == right_cmd) { - return 0; - } else if (cmd_flag != send_cmd) { - ts_err("failed cmd_reg:0x%X, 0x%X, 0x%X", cmd_buf[0], - cmd_buf[1], cmd_buf[2]); - if (goodix_send_command(dev, &ts_cmd)) { - ts_err("Resend cmd 0x%02X FAILED", send_cmd); - return -EINVAL; - } - } - usleep_range(10000, 11000); - } - - return -EINVAL; -} - -static int _do_goodix_send_config(struct goodix_ts_device *dev, - struct goodix_ts_config *config) -{ - int r = 0; - int try_times = 0; - u8 buf[3] = { 0 }; - u16 command_reg = dev->reg.command; - u16 cfg_reg = dev->reg.cfg_addr; - struct goodix_ts_cmd ts_cmd; - - /*1. Inquire command_reg until it's free*/ - for (try_times = 0; try_times < TS_WAIT_CMD_FREE_RETRY_TIMES; - try_times++) { - if (!goodix_i2c_read(dev, command_reg, buf, 1) && - buf[0] == TS_CMD_REG_READY) - break; - usleep_range(10000, 11000); - } - if (try_times >= TS_WAIT_CMD_FREE_RETRY_TIMES) { - ts_err("failed send cfg, reg:0x%04x is not 0xff", command_reg); - r = -EINVAL; - goto exit; - } - - /*2. send "start write cfg" command*/ - goodix_cmd_init(dev, &ts_cmd, COMMAND_START_SEND_CFG, 0, - dev->reg.command); - if (goodix_send_command(dev, &ts_cmd)) { - ts_err("failed send cfg, COMMAND_START_SEND_CFG ERROR"); - r = -EINVAL; - goto exit; - } - - /*3. wait ic set command_reg to 0x82*/ - if (goodix_wait_cfg_cmd_ready(dev, COMMAND_SEND_CFG_PREPARE_OK, - COMMAND_START_SEND_CFG)) { - ts_err("failed send cfg, reg:0x%04x is not 0x82", command_reg); - r = -EINVAL; - goto exit; - } - - /*4. write cfg*/ - if (goodix_i2c_write(dev, cfg_reg, config->data, config->length)) { - ts_err("Send cfg FAILED, write cfg to fw ERROR"); - r = -EINVAL; - goto exit; - } - - /*5. send "end send cfg" command*/ - goodix_cmd_init(dev, &ts_cmd, COMMAND_END_SEND_CFG, 0, - dev->reg.command); - if (goodix_send_command(dev, &ts_cmd)) { - ts_err("failed send cfg, COMMAND_END_SEND_CFG ERROR"); - r = -EINVAL; - goto exit; - } - - if (dev->ic_type == IC_TYPE_YELLOWSTONE) { - /*6. wait 0x7f or 0x7e */ - for (try_times = 0; try_times < TS_WAIT_CMD_FREE_RETRY_TIMES; - try_times++) { - r = goodix_i2c_read(dev, command_reg, buf, 3); - if (!r && (buf[0] == TS_CMD_CFG_ERR || - buf[0] == TS_CMD_CFG_OK)) - break; - usleep_range(10000, 11000); - } - ts_debug("send config result: %*ph", 3, buf); - /* set 0x7D to end send config process */ - goodix_cmd_init(dev, &ts_cmd, COMMAND_END_SEND_CFG_YS, 0, - dev->reg.command); - if (goodix_send_command(dev, &ts_cmd)) { - ts_err("failed send cfg end cmd"); - r = -EINVAL; - goto exit; - } - - if (try_times >= TS_WAIT_CMD_FREE_RETRY_TIMES) { - ts_err("failed get result"); - r = -EINVAL; - goto exit; - } - if (buf[0] == TS_CMD_CFG_ERR) { - if (buf[2] != TS_CFG_REPLY_DATA_EQU) - ts_err("failed send cfg"); - else - ts_debug("config data equal with flash"); - r = -EINVAL; - goto exit; - } - } else { - /*6. wait ic set command_reg to 0xff*/ - for (try_times = 0; try_times < TS_WAIT_CMD_FREE_RETRY_TIMES; - try_times++) { - if (!goodix_i2c_read(dev, command_reg, buf, 1) && - buf[0] == TS_CMD_REG_READY) - break; - usleep_range(10000, 11000); - } - if (try_times >= TS_WAIT_CMD_FREE_RETRY_TIMES) { - ts_err("failed send cfg, reg:0x%04x is 0x%x not 0xff", - command_reg, buf[0]); - r = -EINVAL; - goto exit; - } - } - - ts_debug("Send cfg SUCCESS"); - r = 0; - -exit: - return r; -} - -/*static int goodix_check_cfg_valid(struct goodix_ts_device *dev, u8 *cfg, u32 length) -{ - int ret; - u8 bag_num; - u8 checksum; - int i, j; - int bag_start = 0; - int bag_end = 0; - - if (!cfg || length < TS_CFG_HEAD_LEN) { - ts_err("cfg is INVALID, len:%d", length); - ret = -EINVAL; - goto exit; - } - - checksum = 0; - for (i = 0; i < TS_CFG_HEAD_LEN; i++) - checksum += cfg[i]; - if (checksum != 0) { - ts_err("cfg head checksum ERROR, checksum:0x%02x", - checksum); - ret = -EINVAL; - goto exit; - } - bag_num = cfg[TS_CFG_BAG_NUM_INDEX]; - bag_start = TS_CFG_BAG_START_INDEX; - - ts_debug("cfg bag_num:%d, cfg length:%d", bag_num, length); - for (j = 0; j < bag_num; j++) { - if (bag_start >= length - 1) { - ts_err("ERROR, overflow!!bag_start:%d, cfg_len:%d", - bag_start, length); - ret = -EINVAL; - goto exit; - } - - bag_end = bag_start + cfg[bag_start + 1] + 3; - - checksum = 0; - if (bag_end > length) { - ts_err("ERROR, overflow!!bag:%d, bag_start:%d," - "bag_end:%d, cfg length:%d", - j, bag_start, bag_end, length); - ret = -EINVAL; - goto exit; - } - for (i = bag_start; i < bag_end; i++) - checksum += cfg[i]; - if (checksum != 0) { - ts_err("cfg INVALID, bag:%d checksum ERROR:0x%02x", - j, checksum); - ret = -EINVAL; - goto exit; - } - bag_start = bag_end; - } - - ret = 0; - ts_debug("configuration check SUCCESS"); - -exit: - return ret; -}*/ - -static int goodix_send_config(struct goodix_ts_device *dev, - struct goodix_ts_config *config) -{ - int r = 0; - - if (!config || !config->initialized) { - ts_err("invalid config data"); - return -EINVAL; - } - - /*check configuration valid*/ - // TODO remove this - // r = goodix_check_cfg_valid(dev, config->data, config->length); - // if (r != 0) { - // ts_err("cfg check FAILED"); - // return -EINVAL; - // } - - ts_debug("ver:%02xh,size:%d", config->data[0], config->length); - mutex_lock(&config->lock); - - /*disable doze mode*/ - if (!goodix_set_i2c_doze_mode(dev, false)) { - r = _do_goodix_send_config(dev, config); - } else { - ts_err("failed disable doze[abort]"); - r = -EINVAL; - } - /*enable doze mode*/ - goodix_set_i2c_doze_mode(dev, true); - - mutex_unlock(&config->lock); - return r; -} - -/* success return config length else return -1 */ -static int goodix_read_config_ys(struct goodix_ts_device *dev, u8 *buf) -{ - u32 cfg_addr = dev->reg.cfg_addr; - int sub_bags = 0; - int offset = 0; - int subbag_len; - u16 checksum; - int i; - int ret; - - ret = goodix_i2c_read(dev, cfg_addr, buf, TS_CFG_HEAD_LEN_YS); - if (ret) - goto err_out; - - offset = TS_CFG_HEAD_LEN_YS; - sub_bags = buf[TS_CFG_BAG_NUM_INDEX]; - checksum = checksum_u8_ys(buf, TS_CFG_HEAD_LEN_YS); - if (checksum) { - ts_err("Config head checksum err:0x%x,data:%*ph", checksum, - TS_CFG_HEAD_LEN_YS, buf); - ret = -EINVAL; - goto err_out; - } - - ts_debug("config_version:%u, vub_bags:%u", buf[0], sub_bags); - for (i = 0; i < sub_bags; i++) { - /* read sub head [0]: sub bag num, [1]: sub bag length */ - ret = goodix_i2c_read(dev, cfg_addr + offset, buf + offset, 2); - if (ret) - goto err_out; - - /* read sub bag data */ - subbag_len = buf[offset + 1]; - - ts_debug("sub bag num:%u,sub bag length:%u", buf[offset], - subbag_len); - ret = goodix_i2c_read(dev, cfg_addr + offset + 2, - buf + offset + 2, subbag_len + 2); - if (ret) - goto err_out; - checksum = checksum_u8_ys(buf + offset, subbag_len + 4); - if (checksum) { - ts_err("sub bag checksum err:0x%x", checksum); - ret = -EINVAL; - goto err_out; - } - offset += subbag_len + 4; - ts_debug("sub bag %d, data:%*ph", buf[offset], - buf[offset + 1] + 4, buf + offset); - } - ret = offset; - -err_out: - return ret; -} - -/* success return config length else return -1 */ -static int goodix_read_config_nor(struct goodix_ts_device *dev, u8 *buf) -{ - u32 cfg_addr = dev->reg.cfg_addr; - int sub_bags = 0; - int offset = 0; - int subbag_len; - u8 checksum; - int i; - int ret; - - /*disable doze mode*/ - if (goodix_set_i2c_doze_mode(dev, false)) { - ts_err("failed disable doze mode[abort]"); - ret = -EINVAL; - goto err_out; - } - - ret = goodix_i2c_read(dev, cfg_addr, buf, TS_CFG_HEAD_LEN); - if (ret) - goto err_out; - - offset = TS_CFG_BAG_START_INDEX; - sub_bags = buf[TS_CFG_BAG_NUM_INDEX]; - checksum = checksum_u8(buf, TS_CFG_HEAD_LEN); - if (checksum) { - ts_err("Config head checksum err:0x%x,data:%*ph", checksum, - TS_CFG_HEAD_LEN, buf); - ret = -EINVAL; - goto err_out; - } - - ts_debug("config_version:%u, vub_bags:%u", buf[0], sub_bags); - for (i = 0; i < sub_bags; i++) { - /* read sub head [0]: sub bag num, [1]: sub bag length */ - ret = goodix_i2c_read(dev, cfg_addr + offset, buf + offset, 2); - if (ret) - goto err_out; - - /* read sub bag data */ - subbag_len = buf[offset + 1]; - - ts_debug("sub bag num:%u,sub bag length:%u", buf[offset], - subbag_len); - ret = goodix_i2c_read(dev, cfg_addr + offset + 2, - buf + offset + 2, subbag_len + 1); - if (ret) - goto err_out; - checksum = checksum_u8(buf + offset, subbag_len + 3); - if (checksum) { - ts_err("sub bag checksum err:0x%x", checksum); - ret = -EINVAL; - goto err_out; - } - offset += subbag_len + 3; - ts_debug("sub bag %d, data:%*ph", buf[offset], - buf[offset + 1] + 3, buf + offset); - } - ret = offset; - -err_out: - /*enable doze mode*/ - goodix_set_i2c_doze_mode(dev, true); - - return ret; -} - -/* success return config_len, <= 0 failed */ -static int goodix_read_config(struct goodix_ts_device *dev, u8 *config_data) -{ - struct goodix_ts_cmd ts_cmd; - u8 cmd_flag; - u32 cmd_reg = dev->reg.command; - int r = 0; - int i; - - if (!config_data) { - ts_err("Illegal params"); - return -EINVAL; - } - if (!dev->reg.command) { - ts_err("command register ERROR:0x%04x", dev->reg.command); - return -EINVAL; - } - - /*disable doze mode*/ - if (goodix_set_i2c_doze_mode(dev, false)) { - ts_err("failed disabled doze[abort]"); - r = -EINVAL; - goto exit; - } - - /* wait for IC in IDLE state */ - for (i = 0; i < TS_WAIT_CMD_FREE_RETRY_TIMES; i++) { - cmd_flag = 0; - r = goodix_i2c_read(dev, cmd_reg, &cmd_flag, 1); - if (r < 0 || cmd_flag == TS_CMD_REG_READY) - break; - usleep_range(10000, 11000); - } - if (cmd_flag != TS_CMD_REG_READY) { - ts_err("Wait for IC ready IDLE state timeout:addr 0x%x\n", - cmd_reg); - r = -EAGAIN; - goto exit; - } - /* 0x86 read config command */ - goodix_cmd_init(dev, &ts_cmd, COMMAND_START_READ_CFG, 0, cmd_reg); - r = goodix_send_command(dev, &ts_cmd); - if (r) { - ts_err("Failed send read config command"); - goto exit; - } - /* wait for config data ready */ - if (goodix_wait_cfg_cmd_ready(dev, COMMAND_READ_CFG_PREPARE_OK, - COMMAND_START_READ_CFG)) { - ts_err("Wait for config data ready timeout"); - r = -EAGAIN; - goto exit; - } - - if (dev->ic_type == IC_TYPE_YELLOWSTONE) - r = goodix_read_config_ys(dev, config_data); - else - r = goodix_read_config_nor(dev, config_data); - if (r <= 0) - ts_err("Failed read config data"); - - /* clear command */ - goodix_cmd_init(dev, &ts_cmd, TS_CMD_REG_READY, 0, cmd_reg); - goodix_send_command(dev, &ts_cmd); - -exit: - /*enable doze mode*/ - goodix_set_i2c_doze_mode(dev, true); - - return r; -} - /** * goodix_hw_reset - reset device * @@ -1323,15 +872,12 @@ static int goodix_request_handler(struct goodix_ts_device *dev) switch (buffer[0]) { case REQUEST_CONFIG: ts_debug("HW request config"); - r = goodix_send_config(dev, &(dev->normal_cfg)); - if (r != 0) - ts_debug("request config, send config failed"); break; case REQUEST_BAKREF: ts_debug("HW request bakref"); break; case REQUEST_RESET: - ts_debug("HW requset reset"); + ts_debug("HW request reset"); r = goodix_hw_reset(dev); if (r != 0) ts_debug("request reset, reset failed"); @@ -1787,8 +1333,6 @@ static const struct goodix_ts_hw_ops hw_i2c_ops = { .write_trans = goodix_i2c_write_trans, .reset = goodix_hw_reset, .event_handler = goodix_event_handler, - .send_config = goodix_send_config, - .read_config = goodix_read_config, .send_cmd = goodix_send_command, .read_version = goodix_read_version, .suspend = goodix_hw_suspend, @@ -1803,6 +1347,23 @@ static void goodix_pdev_release(struct device *dev __attribute__((unused))) ts_debug("goodix pdev released"); } +static const struct of_device_id i2c_matches[] = { + { + .compatible = "goodix,gt9896", + }, + { + .compatible = "goodix,gt9886", + }, + { + .compatible = "goodix,gt9889", + }, + { + .compatible = "goodix,gt5863", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, i2c_matches); + static int goodix_i2c_probe(struct i2c_client *client) { struct goodix_ts_device *ts_device = NULL; @@ -1820,12 +1381,34 @@ static int goodix_i2c_probe(struct i2c_client *client) if (!ts_device) return -ENOMEM; - if (IS_ENABLED(CONFIG_OF) && client->dev.of_node) { + if (client->dev.of_node) { /* parse devicetree property */ r = goodix_parse_dt(client->dev.of_node, &ts_device->board_data); if (r < 0) { - ts_err("failed parse device info from dts, %d", r); + ts_err("failed to parse device info from dts, %d", r); + return -EINVAL; + } + + /* guess touch ic based on compatible */ + const struct of_device_id *of_id = + of_match_device(i2c_matches, &client->dev); + if (of_id) { + const char *compatible = of_id->compatible; + + if (strcmp(compatible, "goodix,gt9896") == 0) { + ts_device->ic_type = IC_TYPE_YELLOWSTONE; + ts_device->reg = goodix_ts_regs_yellowstone; + } else if (strcmp(compatible, "goodix,gt9886") == 0 || + strcmp(compatible, "goodix,gt9889") == 0) { + ts_device->ic_type = IC_TYPE_NORMANDY; + ts_device->reg = goodix_ts_regs_normandy; + } else { + ts_err("unknown ic type"); + return -EINVAL; + } + } else { + ts_err("failed to get device id"); return -EINVAL; } } else { @@ -1833,7 +1416,7 @@ static int goodix_i2c_probe(struct i2c_client *client) return -ENODEV; } - ts_device->name = "Goodix TouchDevcie"; + ts_device->name = "Goodix TouchDevice"; ts_device->dev = &client->dev; ts_device->hw_ops = &hw_i2c_ops; @@ -1887,25 +1470,6 @@ static void goodix_i2c_remove(struct i2c_client *client __attribute__((unused))) } } -#ifdef CONFIG_OF -static const struct of_device_id i2c_matchs[] = { - { - .compatible = "goodix,gt9896", - }, - { - .compatible = "goodix,gt9886", - }, - { - .compatible = "goodix,gt9889", - }, - { - .compatible = "goodix,gt5863", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, i2c_matchs); -#endif - static const struct i2c_device_id i2c_id_table[] = { { TS_DRIVER_NAME, 0 }, {}, @@ -1916,7 +1480,7 @@ static struct i2c_driver goodix_i2c_driver = { .driver = { .name = TS_DRIVER_NAME, .owner = THIS_MODULE, - .of_match_table = of_match_ptr(i2c_matchs), + .of_match_table = of_match_ptr(i2c_matches), }, .probe = goodix_i2c_probe, .remove = goodix_i2c_remove,