123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- #include "focaltech_core.h"
- #if FTS_ESDCHECK_EN
- #define ESDCHECK_WAIT_TIME 1000
- #define LCD_ESD_PATCH 0
- #define ESDCHECK_INTRCNT_MAX 2
- struct fts_esdcheck_st {
- u8 mode : 1;
- u8 suspend : 1;
- u8 proc_debug : 1;
- u8 intr : 1;
- u8 unused : 4;
- u8 intr_cnt;
- u8 flow_work_hold_cnt;
- u8 flow_work_cnt_last;
- u32 hardware_reset_cnt;
- u32 nack_cnt;
- u32 dataerror_cnt;
- };
- static struct fts_esdcheck_st fts_esdcheck_data;
- #if LCD_ESD_PATCH
- int lcd_need_reset;
- static int tp_need_recovery;
- int idc_esdcheck_lcderror(struct fts_ts_data *ts_data)
- {
- int ret = 0;
- u8 val = 0;
- FTS_DEBUG("check LCD ESD");
- if ( (tp_need_recovery == 1) && (lcd_need_reset == 0) ) {
- tp_need_recovery = 0;
-
- fts_release_all_finger();
- fts_tp_state_recovery(ts_data);
- }
- ret = fts_read_reg(FTS_REG_ESD_SATURATE, &val);
- if ( ret < 0) {
- FTS_ERROR("read reg0xED fail,ret:%d", ret);
- return -EIO;
- }
- if (val == 0xAA) {
-
- FTS_INFO("LCD ESD, need execute LCD reset");
- lcd_need_reset = 1;
- tp_need_recovery = 1;
- }
- return 0;
- }
- #endif
- static int fts_esdcheck_tp_reset(struct fts_ts_data *ts_data)
- {
- FTS_FUNC_ENTER();
- fts_esdcheck_data.flow_work_hold_cnt = 0;
- fts_esdcheck_data.hardware_reset_cnt++;
- fts_reset_proc(200);
- fts_release_all_finger();
- fts_tp_state_recovery(ts_data);
- FTS_FUNC_EXIT();
- return 0;
- }
- static bool get_chip_id(struct fts_ts_data *ts_data)
- {
- int ret = 0;
- int i = 0;
- u8 reg_value = 0;
- u8 reg_addr = 0;
- u8 chip_id = ts_data->ic_info.ids.chip_idh;
- for (i = 0; i < 3; i++) {
- reg_addr = FTS_REG_CHIP_ID;
- ret = fts_read(®_addr, 1, ®_value, 1);
- if (ret < 0) {
- FTS_ERROR("read chip id fail,ret:%d", ret);
- fts_esdcheck_data.nack_cnt++;
- } else {
- if (reg_value == chip_id) {
- break;
- } else {
- FTS_DEBUG("read chip_id:%x,retry:%d", reg_value, i);
- fts_esdcheck_data.dataerror_cnt++;
- }
- }
- msleep(10);
- }
-
- if (i >= 3) {
- FTS_ERROR("read chip id 3 times fail, need execute TP reset");
- return true;
- }
- return false;
- }
- static bool get_flow_cnt(struct fts_ts_data *ts_data)
- {
- int ret = 0;
- u8 reg_value = 0;
- u8 reg_addr = 0;
- reg_addr = FTS_REG_FLOW_WORK_CNT;
- ret = fts_read(®_addr, 1, ®_value, 1);
- if (ret < 0) {
- FTS_ERROR("read reg0x91 fail,ret:%d", ret);
- fts_esdcheck_data.nack_cnt++;
- } else {
- if ( reg_value == fts_esdcheck_data.flow_work_cnt_last ) {
- FTS_DEBUG("reg0x91,val:%x,last:%x", reg_value,
- fts_esdcheck_data.flow_work_cnt_last);
- fts_esdcheck_data.flow_work_hold_cnt++;
- } else {
- fts_esdcheck_data.flow_work_hold_cnt = 0;
- }
- fts_esdcheck_data.flow_work_cnt_last = reg_value;
- }
-
- if (fts_esdcheck_data.flow_work_hold_cnt >= 5) {
- FTS_DEBUG("reg0x91 keep a value for 5 times, need execute TP reset");
- return true;
- }
- return false;
- }
- static int esdcheck_algorithm(struct fts_ts_data *ts_data)
- {
- int ret = 0;
- u8 reg_value = 0;
- u8 reg_addr = 0;
- bool hardware_reset = 0;
-
- if (fts_esdcheck_data.intr == 1) {
- fts_esdcheck_data.intr_cnt++;
- if (fts_esdcheck_data.intr_cnt > ESDCHECK_INTRCNT_MAX)
- fts_esdcheck_data.intr = 0;
- else
- return 0;
- }
-
- if (fts_esdcheck_data.suspend == 1) {
- FTS_DEBUG("In suspend, not check esd");
-
- return 0;
- }
-
- if (fts_esdcheck_data.proc_debug == 1) {
- FTS_INFO("In apk/adb command mode, not check esd");
- return 0;
- }
-
- reg_addr = FTS_REG_WORKMODE;
- ret = fts_read_reg(reg_addr, ®_value);
- if ( ret < 0 ) {
- fts_esdcheck_data.nack_cnt++;
- } else if ( (reg_value & 0x70) != FTS_REG_WORKMODE_WORK_VALUE) {
- FTS_DEBUG("not in work mode(%x), no check esd", reg_value);
- return 0;
- }
-
- #if LCD_ESD_PATCH
- idc_esdcheck_lcderror(ts_data);
- #endif
-
- hardware_reset = get_chip_id(ts_data);
-
- if (!hardware_reset) {
- hardware_reset = get_flow_cnt(ts_data);
- }
-
- if (hardware_reset == 1) {
- FTS_DEBUG("NoACK=%d, Error Data=%d, Hardware Reset=%d",
- fts_esdcheck_data.nack_cnt,
- fts_esdcheck_data.dataerror_cnt,
- fts_esdcheck_data.hardware_reset_cnt);
- fts_esdcheck_tp_reset(ts_data);
- }
- return 0;
- }
- static void esdcheck_func(struct work_struct *work)
- {
- struct fts_ts_data *ts_data = container_of(work,
- struct fts_ts_data, esdcheck_work.work);
- if (ENABLE == fts_esdcheck_data.mode) {
- esdcheck_algorithm(ts_data);
- queue_delayed_work(ts_data->ts_workqueue,
- &ts_data->esdcheck_work,
- msecs_to_jiffies(ESDCHECK_WAIT_TIME));
- }
- }
- int fts_esdcheck_set_intr(bool intr)
- {
-
- fts_esdcheck_data.intr = intr;
- fts_esdcheck_data.intr_cnt = (u8)intr;
- return 0;
- }
- static int fts_esdcheck_get_status(void)
- {
-
- return fts_esdcheck_data.mode;
- }
- int fts_esdcheck_proc_busy(bool proc_debug)
- {
- fts_esdcheck_data.proc_debug = proc_debug;
- return 0;
- }
- int fts_esdcheck_switch(bool enable)
- {
- struct fts_ts_data *ts_data = fts_data;
- FTS_FUNC_ENTER();
- if (fts_esdcheck_data.mode == ENABLE) {
- if (enable) {
- FTS_DEBUG("ESD check start");
- fts_esdcheck_data.flow_work_hold_cnt = 0;
- fts_esdcheck_data.flow_work_cnt_last = 0;
- fts_esdcheck_data.intr = 0;
- fts_esdcheck_data.intr_cnt = 0;
- queue_delayed_work(ts_data->ts_workqueue,
- &ts_data->esdcheck_work,
- msecs_to_jiffies(ESDCHECK_WAIT_TIME));
- } else {
- FTS_DEBUG("ESD check stop");
- cancel_delayed_work_sync(&ts_data->esdcheck_work);
- }
- }
- FTS_FUNC_EXIT();
- return 0;
- }
- int fts_esdcheck_suspend(void)
- {
- FTS_FUNC_ENTER();
- fts_esdcheck_switch(DISABLE);
- fts_esdcheck_data.suspend = 1;
- fts_esdcheck_data.intr = 0;
- fts_esdcheck_data.intr_cnt = 0;
- FTS_FUNC_EXIT();
- return 0;
- }
- int fts_esdcheck_resume( void )
- {
- FTS_FUNC_ENTER();
- fts_esdcheck_switch(ENABLE);
- fts_esdcheck_data.suspend = 0;
- fts_esdcheck_data.intr = 0;
- fts_esdcheck_data.intr_cnt = 0;
- FTS_FUNC_EXIT();
- return 0;
- }
- static ssize_t fts_esdcheck_store(
- struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
- {
- struct input_dev *input_dev = fts_data->input_dev;
- mutex_lock(&input_dev->mutex);
- if (FTS_SYSFS_ECHO_ON(buf)) {
- FTS_DEBUG("enable esdcheck");
- fts_esdcheck_data.mode = ENABLE;
- fts_esdcheck_switch(ENABLE);
- } else if (FTS_SYSFS_ECHO_OFF(buf)) {
- FTS_DEBUG("disable esdcheck");
- fts_esdcheck_switch(DISABLE);
- fts_esdcheck_data.mode = DISABLE;
- }
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- static ssize_t fts_esdcheck_show(
- struct device *dev, struct device_attribute *attr, char *buf)
- {
- int count;
- struct input_dev *input_dev = fts_data->input_dev;
- mutex_lock(&input_dev->mutex);
- count = snprintf(buf, PAGE_SIZE, "Esd check: %s\n", \
- fts_esdcheck_get_status() ? "On" : "Off");
- mutex_unlock(&input_dev->mutex);
- return count;
- }
- static DEVICE_ATTR (fts_esd_mode, S_IRUGO | S_IWUSR, fts_esdcheck_show, fts_esdcheck_store);
- static struct attribute *fts_esd_mode_attrs[] = {
- &dev_attr_fts_esd_mode.attr,
- NULL,
- };
- static struct attribute_group fts_esd_group = {
- .attrs = fts_esd_mode_attrs,
- };
- int fts_create_esd_sysfs(struct device *dev)
- {
- int ret = 0;
- ret = sysfs_create_group(&dev->kobj, &fts_esd_group);
- if ( ret != 0) {
- FTS_ERROR("fts_create_esd_sysfs(sysfs) create fail");
- sysfs_remove_group(&dev->kobj, &fts_esd_group);
- return ret;
- }
- return 0;
- }
- int fts_esdcheck_init(struct fts_ts_data *ts_data)
- {
- FTS_FUNC_ENTER();
- if (ts_data->ts_workqueue) {
- INIT_DELAYED_WORK(&ts_data->esdcheck_work, esdcheck_func);
- } else {
- FTS_ERROR("fts workqueue is NULL, can't run esd check func!");
- return -EINVAL;
- }
- memset((u8 *)&fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st));
- fts_esdcheck_data.mode = ENABLE;
- fts_esdcheck_data.intr = 0;
- fts_esdcheck_data.intr_cnt = 0;
- fts_esdcheck_switch(ENABLE);
- fts_create_esd_sysfs(ts_data->dev);
- FTS_FUNC_EXIT();
- return 0;
- }
- int fts_esdcheck_exit(struct fts_ts_data *ts_data)
- {
- sysfs_remove_group(&ts_data->dev->kobj, &fts_esd_group);
- return 0;
- }
- #endif
|