diff options
author | Mason Wang <masonwang@google.com> | 2021-09-10 21:57:03 +0800 |
---|---|---|
committer | Mason Wang <masonwang@google.com> | 2021-09-14 21:56:39 +0800 |
commit | e5e70be2c8b926a2faaf80cd53113b1c3b14c38b (patch) | |
tree | 1c3dd0142388517ca2d1a6450738ce60e73e4679 /ft3658/focaltech_test | |
parent | 1ef6a8918a2cabaa5ab7271ffdb2ebe50c64237a (diff) | |
download | focaltech_touch-e5e70be2c8b926a2faaf80cd53113b1c3b14c38b.tar.gz |
touch/focaltech: support open & short test for FATP test.
Bug: 199105014
Test: Verify pass by following test command:
adb shell cat /proc/focaltech_touch/selftest/Rawdata
adb shell cat /proc/focaltech_touch/selftest/Short
Signed-off-by: Mason Wang <masonwang@google.com>
Change-Id: Ia4c1c41978de8fa9b36d0cd5df067aa2fe07603c
Diffstat (limited to 'ft3658/focaltech_test')
-rw-r--r-- | ft3658/focaltech_test/focaltech_test.c | 251 | ||||
-rw-r--r-- | ft3658/focaltech_test/focaltech_test.h | 9 | ||||
-rw-r--r-- | ft3658/focaltech_test/supported_ic/focaltech_test_ft3658u.c | 290 |
3 files changed, 540 insertions, 10 deletions
diff --git a/ft3658/focaltech_test/focaltech_test.c b/ft3658/focaltech_test/focaltech_test.c index 96e9a6c..2a3e3f4 100644 --- a/ft3658/focaltech_test/focaltech_test.c +++ b/ft3658/focaltech_test/focaltech_test.c @@ -453,22 +453,34 @@ int wait_state_update(u8 retval) { int ret = 0; int times = 0; + u8 addr = 0; u8 state = 0xFF; + struct fts_test *tdata = fts_ftest; + + if ((NULL == tdata) || (NULL == tdata->func)) { + FTS_TEST_SAVE_ERR("test/func is null\n"); + return -EINVAL; + } + + if (IC_HW_INCELL == tdata->func->hwtype) { + addr = FACTORY_REG_PARAM_UPDATE_STATE; + } else { + addr = FACTORY_REG_PARAM_UPDATE_STATE_TOUCH; + } while (times++ < FACTORY_TEST_RETRY) { sys_delay(FACTORY_TEST_DELAY); /* Wait register status update */ state = 0xFF; - ret = fts_test_read_reg(FACTORY_REG_PARAM_UPDATE_STATE, &state); + ret = fts_test_read_reg(addr, &state); if ((ret >= 0) && (retval == state)) break; else - FTS_TEST_DBG("reg%x=%x,retry:%d", \ - FACTORY_REG_PARAM_UPDATE_STATE, state, times); + FTS_TEST_DBG("reg%x=%x,retry:%d", addr, state, times); } if (times >= FACTORY_TEST_RETRY) { - FTS_TEST_SAVE_ERR("Wait State Update fail\n"); + FTS_TEST_SAVE_ERR("Wait State Update fail,reg%x=%x\n", addr, state); return -EIO; } @@ -2143,8 +2155,8 @@ static ssize_t fts_test_store( } /* test from test.ini -* example:echo "***.ini" > fts_test -*/ + * example:echo "***.ini" > fts_test + */ static DEVICE_ATTR(fts_test, S_IRUGO | S_IWUSR, fts_test_show, fts_test_store); static struct attribute *fts_test_attributes[] = { @@ -2192,10 +2204,221 @@ static int fts_test_func_init(struct fts_ts_data *ts_data) return -ENODATA; } - fts_ftest->ts_data = fts_data; + fts_ftest->ts_data = ts_data; return 0; } +extern int fts_test_get_raw(int *raw, u8 tx, u8 rx); +extern int fts_test_get_short(int *short_data, u8 tx, u8 rx); + +/* Rawdata test */ +static int proc_test_raw_show(struct seq_file *s, void *v) +{ + int ret = 0; + int i = 0; + int node_num = 0; + u8 tx = 0; + u8 rx = 0; + int *raw; + + ret = enter_factory_mode(); + if (ret < 0) { + FTS_ERROR("enter factory mode fails"); + return ret; + } + /* get Tx chanel number */ + ret = fts_read_reg(FACTORY_REG_CHX_NUM, &tx); + if (ret < 0) { + FTS_ERROR("read tx fails"); + enter_work_mode(); + return ret; + } + /* get Rx chanel number */ + ret = fts_read_reg(FACTORY_REG_CHY_NUM, &rx); + if (ret < 0) { + FTS_ERROR("read rx fails"); + enter_work_mode(); + return ret; + } + + node_num = tx * rx; + raw = fts_malloc(node_num * sizeof(int)); + if (!raw) { + FTS_ERROR("malloc memory for raw fails"); + enter_work_mode(); + return -ENOMEM; + } + + /* get raw data */ + fts_test_get_raw(raw, tx, rx); + + /* output raw data */ + seq_printf(s, " "); + for (i = 0; i < rx; i++) + seq_printf(s, " RX%02d ", (i + 1)); + + for (i = 0; i < node_num; i++) { + if ((i % rx) == 0) + seq_printf(s, "\nTX%02d:%5d,", (i / rx + 1), raw[i]); + else + seq_printf(s, "%5d,", raw[i]); + } + + seq_printf(s, "\n\n"); + + fts_free(raw); + + ret = enter_work_mode(); + + return ret; +} + +static int proc_test_raw_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_test_raw_show, PDE_DATA(inode)); +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)) +static const struct proc_ops proc_test_raw_fops = { + .proc_open = proc_test_raw_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; +#else +static const struct file_operations proc_test_raw_fops = { + .owner = THIS_MODULE, + .open = proc_test_raw_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +/* Short test */ +static int proc_test_short_show(struct seq_file *s, void *v) +{ + int ret = 0; + int i = 0; + int node_num = 0; + u8 tx = 0; + u8 rx = 0; + int *short_data; + + ret = enter_factory_mode(); + if (ret < 0) { + FTS_ERROR("enter factory mode fails"); + return ret; + } + /* get Tx chanel number */ + ret = fts_read_reg(FACTORY_REG_CHX_NUM, &tx); + if (ret < 0) { + FTS_ERROR("read tx fails"); + enter_work_mode(); + return ret; + } + /* get Rx chanel number */ + ret = fts_read_reg(FACTORY_REG_CHY_NUM, &rx); + if (ret < 0) { + FTS_ERROR("read rx fails"); + enter_work_mode(); + return ret; + } + + node_num = tx + rx; + short_data = fts_malloc(node_num * sizeof(int)); + if (!short_data) { + FTS_ERROR("malloc memory for raw fails"); + enter_work_mode(); + return -ENOMEM; + } + + /* get raw data */ + fts_test_get_short(short_data, tx, rx); + + /* output short data */ + seq_printf(s, "TX:"); + for (i = 0; i < tx; i++) { + seq_printf(s, "%d,", short_data[i]); + } + seq_printf(s, "\n"); + + seq_printf(s, "RX:"); + for (i = tx; i < node_num; i++) { + seq_printf(s, "%d,", short_data[i]); + } + seq_printf(s, "\n\n"); + + fts_free(short_data); + + ret = enter_work_mode(); + + return ret; +} + +static int proc_test_short_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_test_short_show, PDE_DATA(inode)); +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)) +static const struct proc_ops proc_test_short_fops = { + .proc_open = proc_test_short_open, + .proc_read = seq_read, + .proc_lseek = seq_lseek, + .proc_release = single_release, +}; +#else +static const struct file_operations proc_test_short_fops = { + .open = proc_test_short_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +#define FTS_PROC_TEST_DIR "selftest" + +struct proc_dir_entry *fts_proc_test_dir; +struct proc_dir_entry *proc_test_raw; +struct proc_dir_entry *proc_test_short; + +#define MODE_OWNER_READ 0400 +static int fts_create_test_procs(struct fts_ts_data *ts_data) +{ + int ret = 0; + + proc_test_raw = proc_create_data("Rawdata", MODE_OWNER_READ, + fts_proc_test_dir, &proc_test_raw_fops, ts_data); + if (!proc_test_raw) { + FTS_ERROR("create proc_test_raw entry fail"); + return -ENOMEM; + } + + proc_test_short = proc_create_data("Short", MODE_OWNER_READ, + fts_proc_test_dir, &proc_test_short_fops, ts_data); + if (!proc_test_short) { + FTS_ERROR("create proc_test_short entry fail"); + return -ENOMEM; + } + + FTS_INFO("create test procs succeeds"); + return ret; +} + +static void fts_free_test_procs(void) +{ + FTS_TEST_FUNC_ENTER(); + + if (proc_test_raw) + proc_remove(proc_test_raw); + + if (proc_test_short) + proc_remove(proc_test_short); + + FTS_TEST_FUNC_EXIT(); +} + int fts_test_init(struct fts_ts_data *ts_data) { int ret = 0; @@ -2215,6 +2438,19 @@ int fts_test_init(struct fts_ts_data *ts_data) } else { FTS_TEST_DBG("sysfs(test) create successfully"); } + + fts_proc_test_dir = proc_mkdir(FTS_PROC_TEST_DIR, + ts_data->proc_touch_entry); + if (!fts_proc_test_dir) { + FTS_ERROR("create %s fails", FTS_PROC_TEST_DIR); + return -ENOMEM; + } + + ret = fts_create_test_procs(ts_data); + if (ret) { + FTS_TEST_ERROR("create test procs fail"); + } + FTS_TEST_FUNC_EXIT(); return ret; @@ -2224,6 +2460,7 @@ int fts_test_exit(struct fts_ts_data *ts_data) { FTS_TEST_FUNC_ENTER(); + fts_free_test_procs(); sysfs_remove_group(&ts_data->dev->kobj, &fts_test_attribute_group); fts_free(fts_ftest); FTS_TEST_FUNC_EXIT(); diff --git a/ft3658/focaltech_test/focaltech_test.h b/ft3658/focaltech_test/focaltech_test.h index 69c6b8c..180b421 100644 --- a/ft3658/focaltech_test/focaltech_test.h +++ b/ft3658/focaltech_test/focaltech_test.h @@ -91,6 +91,7 @@ Test Status #define FACTORY_REG_RAWBUF_SELECT 0x09 #define FACTORY_REG_KEY_CBWIDTH 0x0B #define FACTORY_REG_PARAM_UPDATE_STATE 0x0E +#define FACTORY_REG_PARAM_UPDATE_STATE_TOUCH 0xB5 #define FACTORY_REG_SHORT_TEST_EN 0x0F #define FACTORY_REG_SHORT_TEST_STATE 0x10 #define FACTORY_REG_LCD_NOISE_START 0x11 @@ -474,6 +475,7 @@ struct test_funcs { bool mc_sc_short_v2; bool raw_u16; bool cb_high_support; + bool param_update_support; int (*param_init)(void); int (*init)(void); int (*start_test)(void); @@ -604,8 +606,8 @@ void fts_test_save_data(char *name, int code, int *data, int datacnt, }\ } while(0) -#define CSV_SUPPORT 1 -#define TXT_SUPPORT 1 +#define CSV_SUPPORT 0 +#define TXT_SUPPORT 0 #define FTS_TEST_DBG(fmt, args...) do { \ printk("[FTS_TS][TEST]%s:"fmt"\n", __func__, ##args); \ @@ -620,7 +622,7 @@ printk("[FTS_TS][TEST]%s:"fmt"\n", __func__, ##args); \ } while (0) #define FTS_TEST_INFO(fmt, args...) do { \ - printk(KERN_ERR "[FTS_TS/I][TEST]%s:"fmt"\n", __func__, ##args); \ + printk("[FTS_TS/I][TEST]%s:"fmt"\n", __func__, ##args); \ } while (0) #define FTS_TEST_ERROR(fmt, args...) do { \ @@ -634,6 +636,7 @@ printk("[FTS_TS][TEST]%s:"fmt"\n", __func__, ##args); \ TXT_BUFFER_LEN, \ fmt, ##args);\ } \ + printk("[FTS_TS/I][TEST]%s:"fmt"\n", __func__, ##args);\ } while (0) #define FTS_TEST_SAVE_ERR(fmt, args...) do { \ diff --git a/ft3658/focaltech_test/supported_ic/focaltech_test_ft3658u.c b/ft3658/focaltech_test/supported_ic/focaltech_test_ft3658u.c index db8851b..8b4a8e0 100644 --- a/ft3658/focaltech_test/supported_ic/focaltech_test_ft3658u.c +++ b/ft3658/focaltech_test/supported_ic/focaltech_test_ft3658u.c @@ -1400,3 +1400,293 @@ struct test_funcs test_func_ft5652 = { .cb_high_support = true, .start_test = start_test_ft5652, }; + +static int get_short_adc(int *adc_buf, int byte_num, u8 mode) +{ + int ret = 0; + int i = 0; + u8 short_state = 0; + + FTS_TEST_FUNC_ENTER(); + /* select short test mode & start test */ + ret = fts_test_write_reg(FACTROY_REG_SHORT2_TEST_EN, mode); + if (ret < 0) { + FTS_TEST_ERROR("write short test mode fail\n"); + return ret; + } + + for (i = 0; i < FACTORY_TEST_RETRY; i++) { + sys_delay(FACTORY_TEST_RETRY_DELAY); + + ret = fts_test_read_reg(FACTROY_REG_SHORT2_TEST_STATE, &short_state); + if ((ret >= 0) && (TEST_RETVAL_AA == short_state)) + break; + else + FTS_TEST_DBG("reg%x=%x,retry:%d", FACTROY_REG_SHORT2_TEST_STATE, + short_state, i); + } + if (i >= FACTORY_TEST_RETRY) { + FTS_TEST_ERROR("short test timeout, ADC data not OK\n"); + ret = -EIO; + return ret; + } + + ret = read_mass_data(FACTORY_REG_SHORT2_ADDR_MC, byte_num, adc_buf); + if (ret < 0) { + FTS_TEST_ERROR("get short(adc) data fail\n"); + } + + FTS_TEST_FUNC_EXIT(); + return ret; +} + +static int fts_test_get_raw_restore_reg(u8 fre, u8 data_sel, u8 data_type) { + int ret = 0; + u8 state = 0; + bool param_update_support = false; + + FTS_TEST_FUNC_ENTER(); + + fts_test_read_reg(FACTORY_REG_PARAM_UPDATE_STATE_TOUCH, &state); + param_update_support = (0xAA == state); + + /* set the origin value */ + ret = fts_test_write_reg(FACTORY_REG_FRE_LIST, fre); + if (ret < 0) { + FTS_TEST_ERROR("restore FACTORY_REG_FRE_LIST fail,ret=%d\n", ret); + } + + if (param_update_support) { + ret = wait_state_update(TEST_RETVAL_AA); + if (ret < 0) { + FTS_TEST_SAVE_ERR("wait state update fail\n"); + } + } + + ret = fts_test_write_reg(FACTORY_REG_DATA_TYPE, data_type); + if (ret < 0) { + FTS_TEST_ERROR("set FACTORY_REG_DATA_TYPE type fail,ret=%d\n", ret); + } + + if (param_update_support) { + ret = wait_state_update(TEST_RETVAL_AA); + if (ret < 0) { + FTS_TEST_SAVE_ERR("wait state update fail\n"); + } + } + + ret = fts_test_write_reg(FACTORY_REG_DATA_SELECT, data_sel); + if (ret < 0) { + FTS_TEST_ERROR("restore FACTORY_REG_DATA_SELECT fail,ret=%d\n", ret); + } + + if (param_update_support) { + ret = wait_state_update(TEST_RETVAL_AA); + if (ret < 0) { + FTS_TEST_SAVE_ERR("wait state update fail\n"); + } + } + FTS_TEST_FUNC_EXIT(); + return ret; +} + +int fts_test_get_raw(int *raw, u8 tx, u8 rx) +{ + int ret = 0; + int i = 0; + int times = 0; + int node_num = tx * rx; + u8 fre = 0; + u8 data_sel = 0; + u8 data_type = 0; + u8 val = 0; + u8 state = 0; + bool param_update_support = false; + + FTS_INFO("============ Test Item: rawdata test start"); + + fts_test_read_reg(FACTORY_REG_PARAM_UPDATE_STATE_TOUCH, &state); + param_update_support = (0xAA == state); + FTS_TEST_INFO("Param update:%d", param_update_support); + + /* save origin value */ + ret = fts_test_read_reg(FACTORY_REG_FRE_LIST, &fre); + if (ret) { + FTS_TEST_ERROR("read FACTORY_REG_FRE_LIST fail,ret=%d\n", ret); + return ret; + } + + ret = fts_test_read_reg(FACTORY_REG_DATA_TYPE, &data_type); + if (ret) { + FTS_ERROR("read FACTORY_REG_DATA_TYPE fail,ret=%d\n", ret); + return ret; + } + + ret = fts_test_read_reg(FACTORY_REG_DATA_SELECT, &data_sel); + if (ret) { + FTS_TEST_ERROR("read FACTORY_REG_DATA_SELECT error,ret=%d\n", ret); + return ret; + } + + /* set frequecy high */ + ret = fts_test_write_reg(FACTORY_REG_FRE_LIST, 0x81); + if (ret < 0) { + FTS_TEST_ERROR("set frequecy fail,ret=%d\n", ret); + fts_test_get_raw_restore_reg(fre, data_sel, data_type); + return ret; + } + + if (param_update_support) { + ret = wait_state_update(TEST_RETVAL_AA); + if (ret < 0) { + FTS_TEST_SAVE_ERR("wait state update fail\n"); + fts_test_get_raw_restore_reg(fre, data_sel, data_type); + return ret; + } + } + + ret = fts_test_write_reg(FACTORY_REG_DATA_TYPE, 0x01); + if (ret < 0) { + FTS_TEST_ERROR("set raw type fail,ret=%d\n", ret); + fts_test_get_raw_restore_reg(fre, data_sel, data_type); + return ret; + } + + /* select rawdata */ + ret = fts_test_write_reg(FACTORY_REG_DATA_SELECT, 0x00); + if (ret < 0) { + FTS_TEST_ERROR("set fir fail,ret=%d\n", ret); + fts_test_get_raw_restore_reg(fre, data_sel, data_type); + return ret; + } + + if (param_update_support) { + ret = wait_state_update(TEST_RETVAL_AA); + if (ret < 0) { + FTS_TEST_SAVE_ERR("wait state update fail\n"); + fts_test_get_raw_restore_reg(fre, data_sel, data_type); + return ret; + } + } + + /*********************GET RAWDATA*********************/ + for (i = 0; i < 3; i++) { + FTS_TEST_INFO("get rawdata,i=%d", i); + ret = fts_test_write_reg(DEVIDE_MODE_ADDR, 0xC0); + if (ret < 0) { + FTS_TEST_ERROR("write start scan mode fail\n"); + continue; + } + + while (times++ < FACTORY_TEST_RETRY) { + sys_delay(FACTORY_TEST_DELAY); + + ret = fts_test_read_reg(DEVIDE_MODE_ADDR, &val); + if ((ret >= 0) && (val == 0x40)) { + break; + } else + FTS_TEST_DBG("reg%x=%x,retry:%d", DEVIDE_MODE_ADDR, val, + times); + } + + if (times >= FACTORY_TEST_RETRY) { + FTS_TEST_ERROR("scan timeout\n"); + continue; + } + + ret = fts_test_write_reg(FACTORY_REG_LINE_ADDR, 0xAA); + if (ret < 0) { + FTS_TEST_ERROR("wirte line/start addr fail\n"); + continue; + } + + ret = read_mass_data(FACTORY_REG_RAWDATA_ADDR_MC_SC, (node_num * 2), + raw); + } + if (ret < 0) { + FTS_TEST_ERROR("get rawdata fail,ret=%d\n", ret); + fts_test_get_raw_restore_reg(fre, data_sel, data_type); + return ret; + } + + fts_test_get_raw_restore_reg(fre, data_sel, data_type); + FTS_TEST_INFO("============ Test Item: rawdata test end\n"); + return ret; +} + +static int fts_test_get_short_restore_reg(u8 res_level) { + int ret = 0; + + FTS_TEST_FUNC_ENTER(); + ret = fts_test_write_reg(FACTROY_REG_SHORT2_RES_LEVEL, res_level); + if (ret < 0) { + FTS_TEST_ERROR("restore FACTROY_REG_SHORT2_RES_LEVEL level fails"); + } + + FTS_TEST_FUNC_EXIT(); + return ret; +} + +int fts_test_get_short(int *short_data, u8 tx, u8 rx) +{ + int ret = 0; + int i = 0; + int ch_num = (tx + rx); + int offset = 0; + int code = 0; + int denominator = 0; + int numerator = 0; + u8 res_level = 0; + + FTS_TEST_INFO("============ Test Item: Short Test start\n"); + + ret = fts_test_read_reg(FACTROY_REG_SHORT2_RES_LEVEL, &res_level); + if (ret < 0) { + FTS_TEST_ERROR("read short level fails\n"); + return ret; + } + + /* get offset = readdata - 1024 */ + ret = get_short_adc(&offset, 1 * 2, FACTROY_REG_SHORT2_OFFSET); + if (ret < 0) { + FTS_TEST_ERROR("get weak short data fail,ret:%d\n", ret); + fts_test_get_short_restore_reg(res_level); + return ret; + } + offset -= 1024; + FTS_TEST_INFO("short offset:%d", offset); + + /* get short resistance and exceptional channel */ + /* choose resistor_level */ + ret = fts_test_write_reg(FACTROY_REG_SHORT2_RES_LEVEL, 1); + if (ret < 0) { + FTS_TEST_ERROR("write short resistor level fail\n"); + fts_test_get_short_restore_reg(res_level); + return ret; + } + + /* get adc data */ + ret = get_short_adc(short_data, ch_num * 2, FACTROY_REG_SHORT2_CA); + if (ret < 0) { + FTS_TEST_ERROR("get weak short data fail,ret:%d\n", ret); + fts_test_get_short_restore_reg(res_level); + return ret; + } + + for (i = 0; i < ch_num; i++) { + code = short_data[i]; + denominator = 1407 - code + offset; + if (denominator == 0) { + short_data[i] = 2000; + } else { + numerator = (code - offset + 395) * 112; + short_data[i] = fts_abs(numerator / denominator - 3); + } + } + + ret = fts_test_get_short_restore_reg(res_level); + + FTS_TEST_INFO("============ Test Item: Short Test end\n"); + return ret; +} + |