/* * * FocalTech TouchScreen driver. * * Copyright (c) 2012-2018, FocalTech Systems, Ltd., all rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ /******************************************************************************* * Included header files *******************************************************************************/ #include "../focaltech_test.h" /******************************************************************************* * Private constant and macro definitions using #define *******************************************************************************/ #define REG_MS_SELECT 0x26 #define REG_CH_X_MASTER 0x50 #define REG_CH_Y_MASTER 0x51 #define REG_CH_X_SLAVE 0x52 #define REG_CH_Y_SLAVE 0x53 #define REG_FW_INFO_CNT 0x17 #define I2C_ADDR_M 0 #define I2C_ADDR_S 12 #define REG_FW_INFO_ADDR 0x81 #define REG_FW_INFO_LEN 32 #define MAX_ADC_VALUE 4015 #define FACTORY_NOISE_MODE_REG 0x5E /******************************************************************************* * Private enumerations, structures and unions using typedef *******************************************************************************/ enum M_S_TYPE { CHIP_AS_SLAVE = 0, CHIP_AS_MASTER = 1, SINGLE_CHIP = 3, }; enum CASCADE_DIRECTION { CASCADE_LEFT_RIGHT = 0, CASCADE_UP_DOWN = 1, }; /* * m_s_sel - master/slave information * m_i2c_addr - master ic I2C address * s_i2c_addr - slave ic I2C address * m_tx - master IC tx number * m_rx - master IC rx number * s_tx - slave IC tx number * s_rx - slave IC rx number */ struct ft8201_info { union m_s_sel { struct bits { u8 type : 6; u8 direction : 1; u8 s0_as_slave : 1; } bits; u8 byte_val; } m_s_sel; u8 m_i2c_addr; u8 s_i2c_addr; u8 m_tx; u8 m_rx; u8 s_tx; u8 s_rx; u8 current_slave_addr; }; /******************************************************************************* * Static function prototypes *******************************************************************************/ static void fts_array_copy(int *dest, const int *src, int len) { int i = 0; for (i = 0; i < len; i++) { dest[i] = src[i]; } } static void work_as_master(struct ft8201_info *info) { if (fts_data->client->addr != info->m_i2c_addr) { FTS_TEST_DBG("change i2c addr to master(0x%x)\n", info->m_i2c_addr); fts_data->client->addr = info->m_i2c_addr; } } static void work_as_slave(struct ft8201_info *info) { if (fts_data->client->addr != info->s_i2c_addr) { FTS_TEST_DBG("change i2c addr to slave(0x%x)\n", info->s_i2c_addr); fts_data->client->addr = info->s_i2c_addr; } } static int ft8201_write_reg(struct ft8201_info *info, u8 reg_addr, u8 reg_val) { int ret = 0; /* write master reg */ work_as_master(info); ret = fts_test_write_reg(reg_addr, reg_val); if (ret) { FTS_TEST_SAVE_ERR("write master reg fail\n"); return ret; } /* write slave reg */ work_as_slave(info); ret = fts_test_write_reg(reg_addr, reg_val); if (ret) { FTS_TEST_SAVE_ERR("write slave reg fail\n"); work_as_master(info); return ret; } work_as_master(info); return 0; } static void integrate_data(struct ft8201_info *info, int *m_buf, int *s_buf, int *data) { int i = 0; int *s0_buf; int *s1_buf; int s0_ch = 0; int s0_tx = 0; int s0_rx = 0; int s1_ch = 0; int s1_rx = 0; int row = 0; int s0_row = 0; int s1_row = 0; FTS_TEST_FUNC_ENTER(); if (false == info->m_s_sel.bits.s0_as_slave) { s0_buf = m_buf; s0_tx = info->m_tx; s0_rx = info->m_rx; s0_ch = info->m_tx * info->m_rx; s1_buf = s_buf; s1_rx = info->s_rx; s1_ch = info->s_tx * info->s_rx; } else { s0_buf = s_buf; s0_tx = info->s_tx; s0_rx = info->s_rx; s0_ch = info->s_tx * info->s_rx; s1_buf = m_buf; s1_rx = info->m_rx; s1_ch = info->m_tx * info->m_rx; } FTS_TEST_DBG("%d %d %d %d %d", s0_tx, s0_rx, s0_ch, s1_rx, s1_ch); if (CASCADE_LEFT_RIGHT == info->m_s_sel.bits.direction) { /* cascade direction : left to right */ for (i = 0; i < s0_tx; i++) { row = i * (s0_rx + s1_rx); s0_row = i * s0_rx; s1_row = i * s1_rx; fts_array_copy(data + row, s0_buf + s0_row, s0_rx); fts_array_copy(data + row + s0_rx, s1_buf + s1_row, s1_rx); } } else { /* cascade direction : up to down */ fts_array_copy(data, s0_buf, s0_ch); fts_array_copy(data + s0_ch, s1_buf, s1_ch); } /* key */ fts_array_copy(data + s0_ch + s1_ch, s0_buf + s0_ch, 6); fts_array_copy(data + s0_ch + s1_ch + 6, s1_buf + s1_ch, 6); FTS_TEST_FUNC_EXIT(); } static int check_ic_info_validity(struct ft8201_info *info) { /* IC type */ if ((info->m_s_sel.bits.type != CHIP_AS_SLAVE) && (info->m_s_sel.bits.type != CHIP_AS_MASTER)) { FTS_TEST_SAVE_ERR("IC cascade type(%d) fail\n", info->m_s_sel.bits.type); return -EINVAL; } /* I2C addr */ if ((0 == info->m_i2c_addr) || (0 == info->s_i2c_addr)) { FTS_TEST_SAVE_ERR("i2c addr of master(0x%x)/slave(0x%x) fail\n", info->m_i2c_addr, info->s_i2c_addr); return -EINVAL; } /* tx/rx */ if ((0 == info->m_tx) || (info->m_tx > TX_NUM_MAX)) { FTS_TEST_SAVE_ERR("master tx(%d) fail\n", info->m_tx); return -EINVAL; } if ((0 == info->m_rx) || (info->m_rx > TX_NUM_MAX)) { FTS_TEST_SAVE_ERR("master rx(%d) fail\n", info->m_rx); return -EINVAL; } if ((0 == info->s_tx) || (info->s_tx > TX_NUM_MAX)) { FTS_TEST_SAVE_ERR("slave tx(%d) fail\n", info->s_tx); return -EINVAL; } if ((0 == info->s_rx) || (info->s_rx > TX_NUM_MAX)) { FTS_TEST_SAVE_ERR("slave rx(%d) fail\n", info->s_rx); return -EINVAL; } return 0; } static int get_chip_information(struct ft8201_info *info) { int ret = 0; u8 value[REG_FW_INFO_LEN] = { 0 }; u8 cmd = 0; ret = fts_test_read_reg(REG_MS_SELECT, &value[0]); if (ret) { FTS_TEST_SAVE_ERR("read m/s select info fail\n"); return ret; } info->m_s_sel.byte_val = value[0]; ret = fts_test_read_reg(REG_CH_X_MASTER, &value[0]); if (ret) { FTS_TEST_SAVE_ERR("read ch_x_m fail\n"); return ret; } info->m_tx = value[0]; ret = fts_test_read_reg(REG_CH_Y_MASTER, &value[0]); if (ret) { FTS_TEST_SAVE_ERR("read ch_y_m fail\n"); return ret; } info->m_rx = value[0]; ret = fts_test_read_reg(REG_CH_X_SLAVE, &value[0]); if (ret) { FTS_TEST_SAVE_ERR("read ch_x_s fail\n"); return ret; } info->s_tx = value[0]; ret = fts_test_read_reg(REG_CH_Y_SLAVE, &value[0]); if (ret) { FTS_TEST_SAVE_ERR("read ch_y_s fail\n"); return ret; } info->s_rx = value[0]; ret = fts_test_write_reg(REG_FW_INFO_CNT, 0); if (ret) { FTS_TEST_SAVE_ERR("write fw into cnt fail\n"); return ret; } cmd = REG_FW_INFO_ADDR; ret = fts_test_read(cmd, &value[0], REG_FW_INFO_LEN); if (ret) { FTS_TEST_SAVE_ERR("read fw info fail\n"); return ret; } if ((value[I2C_ADDR_M] + value[I2C_ADDR_M + 1]) == 0xFF) { info->m_i2c_addr = value[I2C_ADDR_M] >> 1; } if ((value[I2C_ADDR_S] + value[I2C_ADDR_S + 1]) == 0xFF) { info->s_i2c_addr = value[I2C_ADDR_S] >> 1; } FTS_TEST_DBG("%s=%d,%s=%d,%s=%d,%s=0x%x,%s=0x%x,%s=%d,%s=%d,%s=%d,%s=%d\n", "type", info->m_s_sel.bits.type, "direction", info->m_s_sel.bits.direction, "s0_as_slave", info->m_s_sel.bits.s0_as_slave, "m_i2c_addr", info->m_i2c_addr, "s_i2c_addr", info->s_i2c_addr, "m_tx", info->m_tx, "m_rx", info->m_rx, "s_tx", info->s_tx, "s_rx", info->s_rx ); ret = check_ic_info_validity(info); if (ret) { FTS_TEST_SAVE_ERR("ic information invalid\n"); return ret; } return 0; } static int ft8201_test_init(struct ft8201_info *info) { int ret = 0; /* initialize info */ memset(info, 0, sizeof(struct ft8201_info)); /* enter factory mode */ ret = enter_factory_mode(); if (ret < 0) { FTS_TEST_SAVE_ERR("enter factory mode fail, can't get tx/rx num\n"); return ret; } /* get chip info */ ret = get_chip_information(info); if (ret < 0) { FTS_TEST_SAVE_ERR("get chip information fail\n"); return ret; } return 0; } static u8 ft8201_chip_clb(struct ft8201_info *info) { int ret = 0; FTS_TEST_FUNC_ENTER(); /* master clb */ work_as_master(info); ret = chip_clb(); if (ret) { FTS_TEST_SAVE_ERR("master clb fail\n"); return ret; } /* slave clb */ work_as_slave(info); ret = chip_clb(); if (ret) { FTS_TEST_SAVE_ERR("master clb fail\n"); work_as_master(info); return ret; } work_as_master(info); FTS_TEST_FUNC_EXIT(); return 0; } static int ft8201_get_tx_rx_cb(struct ft8201_info *info, u8 start_node, int read_num, int *read_buffer) { int ret = 0; int *buffer_master = NULL; int *buffer_slave = NULL; int master_tx = info->m_tx; int master_rx = info->m_rx; int slave_tx = info->s_tx; int slave_rx = info->s_rx; FTS_TEST_FUNC_ENTER(); buffer_master = fts_malloc((master_tx + 1) * master_rx * sizeof(int)); if (NULL == buffer_master) { FTS_TEST_SAVE_ERR("%s:master buf malloc fail\n", __func__); ret = -ENOMEM; goto GET_CB_ERR; } buffer_slave = fts_malloc((slave_tx + 1) * slave_rx * sizeof(int)); if (NULL == buffer_slave) { FTS_TEST_SAVE_ERR("%s:slave buf malloc fail\n", __func__); ret = -ENOMEM; goto GET_CB_ERR; } /* master cb */ work_as_master(info); ret = get_cb_incell(0, master_tx * master_rx + 6, buffer_master); if (ret ) { FTS_TEST_SAVE_ERR("master clb fail\n"); goto GET_CB_ERR; } /* slave cb */ work_as_slave(info); ret = get_cb_incell(0, slave_tx * slave_rx + 6, buffer_slave); if (ret ) { FTS_TEST_SAVE_ERR("slave clb fail\n"); work_as_master(info); goto GET_CB_ERR; } work_as_master(info); integrate_data(info, buffer_master, buffer_slave, read_buffer); GET_CB_ERR: fts_free(buffer_master); fts_free(buffer_slave); FTS_TEST_FUNC_EXIT(); return ret; } static int read_adc_data(u8 retval, int byte_num, int *adc_buf) { int ret = 0; int times = 0; u8 short_state = 0; FTS_TEST_FUNC_ENTER(); for (times = 0; times < FACTORY_TEST_RETRY; times++) { ret = fts_test_read_reg(FACTORY_REG_SHORT_TEST_STATE, &short_state); if ((0 == ret) && (retval == short_state)) break; else FTS_TEST_DBG("reg%x=%x,retry:%d", FACTORY_REG_SHORT_TEST_STATE, short_state, times); sys_delay(FACTORY_TEST_RETRY_DELAY); } if (times >= FACTORY_TEST_RETRY) { FTS_TEST_SAVE_ERR("short test timeout, ADC data not OK\n"); ret = -EIO; goto ADC_ERROR; } ret = read_mass_data(FACTORY_REG_SHORT_ADDR, byte_num, adc_buf); if (ret) { FTS_TEST_SAVE_ERR("get short(adc) data fail\n"); } ADC_ERROR: FTS_TEST_FUNC_EXIT(); return ret; } static u8 ft8201_weakshort_get_adcdata(struct ft8201_info *info, int *rbuf) { int ret = 0; int master_adc_num = 0; int slave_adc_num = 0; int *buffer_master = NULL; int *buffer_slave = NULL; int master_tx = info->m_tx; int master_rx = info->m_rx; int slave_tx = info->s_tx; int slave_rx = info->s_rx; int ch_num = 0; FTS_TEST_FUNC_ENTER(); buffer_master = fts_malloc((master_tx + 1) * master_rx * sizeof(int)); if (NULL == buffer_master) { FTS_TEST_SAVE_ERR("%s:master buf malloc fail\n", __func__); ret = -ENOMEM; goto ADC_ERROR; } buffer_slave = fts_malloc((slave_tx + 1) * slave_rx * sizeof(int)); if (NULL == buffer_slave) { FTS_TEST_SAVE_ERR("%s:slave buf malloc fail\n", __func__); ret = -ENOMEM; goto ADC_ERROR; } /* Start ADC sample */ ch_num = master_tx + master_rx; ret = fts_test_write_reg(FACTORY_REG_SHORT_TEST_EN, 0x01); if (ret) { FTS_TEST_SAVE_ERR("start short test fail\n"); goto ADC_ERROR; } sys_delay(ch_num * FACTORY_TEST_DELAY); /* read master adc data */ master_adc_num = (master_tx * master_rx + 6) * 2; work_as_master(info); ret = read_adc_data(TEST_RETVAL_00, master_adc_num, buffer_master); if (ret) { FTS_TEST_SAVE_ERR("read master adc data fail\n"); goto ADC_ERROR; } /* read slave adc data */ slave_adc_num = (slave_tx * slave_rx + 6) * 2; work_as_slave(info); ret = read_adc_data(TEST_RETVAL_00, slave_adc_num, buffer_slave); if (ret) { FTS_TEST_SAVE_ERR("read master adc data fail\n"); work_as_master(info); goto ADC_ERROR; } work_as_master(info); /* data integration */ integrate_data(info, buffer_master, buffer_slave, rbuf); ADC_ERROR: fts_free(buffer_master); fts_free(buffer_slave); FTS_TEST_FUNC_EXIT(); return ret; } static int ft8201_short_test(struct ft8201_info *info, struct fts_test *tdata, bool *test_result) { int ret = 0; bool tmp_result = true; int *adcdata = NULL; int tmp_adc = 0; int i = 0; struct incell_threshold *thr = &tdata->ic.incell.thr; FTS_TEST_FUNC_ENTER(); FTS_TEST_SAVE_INFO("\n============ Test Item: short test\n"); memset(tdata->buffer, 0, tdata->buffer_length); adcdata = tdata->buffer; ret = enter_factory_mode(); if (ret) { FTS_TEST_SAVE_ERR("//Failed to Enter factory mode.ret=%d\n", ret); goto test_err; } ret = ft8201_weakshort_get_adcdata(info, adcdata); if (ret) { FTS_TEST_SAVE_ERR("//Failed to get AdcData. ret=%d\n", ret); goto test_err; } /* change adc to resistance */ for (i = 0; i < tdata->node.node_num; ++i) { tmp_adc = adcdata[i]; /* avoid calculating the value of the resistance is too large, limiting the size of the ADC value */ if (tmp_adc > MAX_ADC_VALUE) tmp_adc = MAX_ADC_VALUE; adcdata[i] = (tmp_adc * 100) / (4095 - tmp_adc); } /* save */ show_data(adcdata, true); save_data_csv(adcdata, "Short Circuit Test", \ CODE_SHORT_TEST, false, true); /* compare */ tmp_result = compare_data(adcdata, thr->basic.short_res_min, TEST_SHORT_RES_MAX, thr->basic.short_res_vk_min, TEST_SHORT_RES_MAX, true); ret = 0; test_err: if (tmp_result) { *test_result = true; FTS_TEST_SAVE_INFO("\n------ Short Circuit Test PASS\n"); } else { *test_result = false; FTS_TEST_SAVE_INFO("\n------ Short Circuit Test NG\n"); } FTS_TEST_FUNC_EXIT(); return ret; } static int ft8201_open_test(struct ft8201_info *info, struct fts_test *tdata, bool *test_result) { int ret = 0; bool tmp_result = false; u8 reg20_val = 0; u8 reg86_val = 0; u8 tmp_val = 0; int min = 0; int max = 0; int *opendata = NULL; int byte_num = 0; struct incell_threshold *thr = &tdata->ic.incell.thr; FTS_TEST_FUNC_ENTER(); FTS_TEST_SAVE_INFO("\n============ Test Item: Open Test\n"); memset(tdata->buffer, 0, tdata->buffer_length); opendata = tdata->buffer; ret = enter_factory_mode(); if (ret) { FTS_TEST_SAVE_ERR("Enter Factory Failed\n"); goto test_err; } ret = fts_test_read_reg(FACTORY_REG_OPEN_REG86, ®86_val); if (ret < 0) { FTS_TEST_SAVE_ERR("read 0x86 fail\n"); goto test_err; } ret = fts_test_read_reg(FACTORY_REG_OPEN_REG20, ®20_val); if (ret < 0) { FTS_TEST_SAVE_ERR("read 0x20 fail\n"); goto test_err; } /* set open mode */ ret = ft8201_write_reg(info, FACTORY_REG_OPEN_REG86, 0x01); if (ret < 0) { FTS_TEST_SAVE_ERR("write 0x86 fail\n"); goto restore_reg; } /* set Bit4~Bit5 of reg0x20 is set to 2b'10 (Source to GND) */ tmp_val = reg20_val | (1 << 5); tmp_val &= ~(1 << 4); ret = ft8201_write_reg(info, FACTORY_REG_OPEN_REG20, tmp_val); if (ret) { FTS_TEST_SAVE_ERR("Failed to Read or Write Reg\n"); goto restore_reg; } /* wait fw state update before clb */ ret = wait_state_update(TEST_RETVAL_00); if (ret < 0) { FTS_TEST_SAVE_ERR("wait state update fail\n"); goto restore_reg; } ret = ft8201_chip_clb(info); if (ret) { FTS_TEST_SAVE_ERR("auto clb fail\n"); goto restore_reg; } /* get cb data */ byte_num = tdata->node.tx_num * tdata->node.rx_num; ret = ft8201_get_tx_rx_cb(info, 0, byte_num, opendata); if (ret < 0) { FTS_TEST_SAVE_ERR("get cb fail\n"); goto restore_reg; } /* show open data */ show_data(opendata, false); /* save data */ save_data_csv(opendata, "Open Test", \ CODE_OPEN_TEST, false, false); /* compare */ min = thr->basic.open_cb_min; max = 256; FTS_TEST_DBG("open %d %d\n", min, opendata[0]); tmp_result = compare_data(opendata, min, max, 0, 0, false); //ret = 0; restore_reg: /* restore */ ret = ft8201_write_reg(info, FACTORY_REG_OPEN_REG86, reg86_val); if (ret < 0) { FTS_TEST_SAVE_ERR("restore reg86 fail\n"); } ret = ft8201_write_reg(info, FACTORY_REG_OPEN_REG20, reg20_val); if (ret < 0) { FTS_TEST_SAVE_ERR("restore reg20 fail\n"); } ret = wait_state_update(TEST_RETVAL_00); if (ret < 0) { FTS_TEST_SAVE_ERR("wait state update fail\n"); } ret = ft8201_chip_clb(info); if (ret < 0) { FTS_TEST_SAVE_ERR("auto clb fail\n"); } test_err: if (tmp_result) { *test_result = true; FTS_TEST_SAVE_INFO("\n------ Open Test PASS\n"); } else { *test_result = false; FTS_TEST_SAVE_INFO("\n------ Open Test NG\n"); } FTS_TEST_FUNC_EXIT(); return ret; } static int ft8201_cb_test(struct ft8201_info *info, struct fts_test *tdata, bool *test_result) { bool tmp_result = false; int ret = 0; bool key_check = false; int byte_num = 0; int *cbdata = NULL; struct incell_threshold *thr = &tdata->ic.incell.thr; FTS_TEST_FUNC_ENTER(); FTS_TEST_SAVE_INFO("\n============ Test Item: CB Test\n"); memset(tdata->buffer, 0, tdata->buffer_length); cbdata = tdata->buffer; if (!thr->cb_min || !thr->cb_max) { FTS_TEST_SAVE_ERR("cb_min/max is null\n"); ret = -EINVAL; goto test_err; } ret = enter_factory_mode(); if (ret) { FTS_TEST_SAVE_ERR("// Failed to Enter factory mode.ret:%d\n", ret); goto test_err; } ret = ft8201_chip_clb(info); if (ret) { FTS_TEST_SAVE_ERR("//========= auto clb Failed\n"); goto test_err; } byte_num = tdata->node.node_num; ret = ft8201_get_tx_rx_cb(info, 0, byte_num, cbdata); if (ret < 0) { FTS_TEST_SAVE_ERR("get cb fail\n"); goto test_err; } key_check = thr->basic.cb_vkey_check; show_data(cbdata, key_check); save_data_csv(cbdata, "CB Test", \ CODE_CB_TEST, false, key_check); /* compare */ tmp_result = compare_array(cbdata, thr->cb_min, thr->cb_max, key_check); ret = 0; test_err: if (tmp_result) { *test_result = true; FTS_TEST_SAVE_INFO("\n------ CB Test PASS\n"); } else { *test_result = false; FTS_TEST_SAVE_INFO("\n------ CB Test NG\n"); } FTS_TEST_FUNC_EXIT(); return ret; } static int ft8201_rawdata_test(struct ft8201_info *info, struct fts_test *tdata, bool *test_result) { int ret = 0; bool tmp_result = false; int i = 0; bool key_check = true; int *rawdata = NULL; struct incell_threshold *thr = &tdata->ic.incell.thr; FTS_TEST_FUNC_ENTER(); FTS_TEST_SAVE_INFO("\n============ Test Item: RawData Test\n"); memset(tdata->buffer, 0, tdata->buffer_length); rawdata = tdata->buffer; if (!thr->rawdata_min || !thr->rawdata_max) { FTS_TEST_SAVE_ERR("rawdata_min/max is null\n"); ret = -EINVAL; goto test_err; } ret = enter_factory_mode(); if (ret < 0) { FTS_TEST_SAVE_ERR("enter factory mode fail,ret=%d\n", ret); goto test_err; } /* read rawdata */ for (i = 0 ; i < 3; i++) { ret = get_rawdata(rawdata); } if (ret < 0) { FTS_TEST_SAVE_ERR("get RawData fail,ret=%d\n", ret); goto test_err; } /* save */ show_data(rawdata, key_check); save_data_csv(rawdata, "RawData Test", \ CODE_RAWDATA_TEST, false, key_check); /* compare */ tmp_result = compare_array(rawdata, thr->rawdata_min, thr->rawdata_max, key_check); test_err: if (tmp_result) { *test_result = true; FTS_TEST_SAVE_INFO("\n------ RawData Test PASS\n"); } else { *test_result = false; FTS_TEST_SAVE_INFO("\n------ RawData Test NG\n"); } FTS_TEST_FUNC_EXIT(); return ret; } static int ft8201_lcdnoise_test(struct ft8201_info *info, struct fts_test *tdata, bool *test_result) { int ret = 0; bool tmp_result = false; int frame_num = 0; int i = 0; int max = 0; int max_vk = 0; int byte_num = 0; u8 old_mode = 0; u8 reg_value = 0; u8 status = 0; int *lcdnoise = NULL; struct incell_threshold *thr = &tdata->ic.incell.thr; FTS_TEST_FUNC_ENTER(); FTS_TEST_SAVE_INFO("\n============ Test Item: LCD Noise Test\n"); memset(tdata->buffer, 0, tdata->buffer_length); lcdnoise = tdata->buffer; ret = enter_factory_mode(); if (ret < 0) { FTS_TEST_SAVE_ERR("enter factory mode fail,ret=%d\n", ret); goto test_err; } ret = fts_test_read_reg(FACTORY_REG_DATA_SELECT, &old_mode); if (ret < 0) { FTS_TEST_SAVE_ERR("read reg06 fail\n"); goto test_err; } ret = fts_test_read_reg(FACTORY_NOISE_MODE_REG, ®_value); if (ret < 0) { FTS_TEST_SAVE_ERR("read reg5e fail\n"); goto test_err; } ret = ft8201_write_reg(info, FACTORY_REG_DATA_SELECT, 0x64); if (ret < 0) { FTS_TEST_SAVE_ERR("write 0x64 to reg5e fail\n"); goto restore_reg; } ret = ft8201_write_reg(info, FACTORY_REG_DATA_SELECT, 0x01); if (ret < 0) { FTS_TEST_SAVE_ERR("write 1 to reg06 fail\n"); goto restore_reg; } frame_num = thr->basic.lcdnoise_frame; ret = ft8201_write_reg(info, FACTORY_REG_LCD_NOISE_FRAME, frame_num & 0xff); if (ret < 0) { FTS_TEST_SAVE_INFO("write frame num fail\n"); goto restore_reg; } ret = ft8201_write_reg(info, FACTORY_REG_LCD_NOISE_FRAME + 1, (frame_num >> 8) & 0xff); if (ret < 0) { FTS_TEST_SAVE_INFO("write frame num fail\n"); goto restore_reg; } /* read noise data */ ret = fts_test_write_reg(FACTORY_REG_LINE_ADDR, 0xAD); if (ret < 0) { FTS_TEST_SAVE_ERR("write 0xAD to reg01 fail\n"); goto restore_reg; } /* start test */ ret = ft8201_write_reg(info, FACTORY_REG_LCD_NOISE_START, 0x01); if (ret < 0) { FTS_TEST_SAVE_INFO("start lcdnoise test fail\n"); goto restore_reg; } sys_delay(frame_num * FACTORY_TEST_DELAY / 2); for (i = 0; i < FACTORY_TEST_RETRY; i++) { status = 0xFF; ret = fts_test_read_reg(FACTORY_REG_LCD_NOISE_START, &status ); if ((ret >= 0) && (0x00 == status)) { break; } else { FTS_TEST_DBG("reg%x=%x,retry:%d\n", FACTORY_REG_LCD_NOISE_START, status, i); } sys_delay(FACTORY_TEST_RETRY_DELAY); } if (i >= FACTORY_TEST_RETRY) { FTS_TEST_SAVE_ERR("lcdnoise test timeout\n"); //ret = -ENODATA; goto restore_reg; } byte_num = tdata->node.node_num * 2; ret = read_mass_data(FACTORY_REG_RAWDATA_ADDR, byte_num, lcdnoise); if (ret < 0) { FTS_TEST_SAVE_ERR("read rawdata fail\n"); goto restore_reg; } /* save */ show_data(lcdnoise, true); save_data_csv(lcdnoise, "LCD Noise Test", \ CODE_LCD_NOISE_TEST, false, true); /* compare */ max = thr->basic.lcdnoise_coefficient * tdata->va_touch_thr * 32 / 100; max_vk = thr->basic.lcdnoise_coefficient_vkey * tdata->vk_touch_thr * 32 / 100; tmp_result = compare_data(lcdnoise, 0, max, 0, max_vk, true); //ret = 0; restore_reg: ret = fts_test_write_reg(FACTORY_REG_DATA_SELECT, old_mode); if (ret < 0) { FTS_TEST_SAVE_ERR("restore reg06 fail\n"); } ret = fts_test_write_reg(FACTORY_NOISE_MODE_REG, reg_value); if (ret < 0) { FTS_TEST_SAVE_ERR("restore reg5e fail\n"); } ret = fts_test_write_reg(FACTORY_REG_LCD_NOISE_START, 0x00); if (ret < 0) { FTS_TEST_SAVE_ERR("restore reg11 fail\n"); } test_err: if (tmp_result) { *test_result = true; FTS_TEST_SAVE_INFO("\n------ LCD Noise Test PASS\n"); } else { *test_result = false; FTS_TEST_SAVE_INFO("\n------ LCD Noise Test NG\n"); } FTS_TEST_FUNC_EXIT(); return ret; } static int start_test_ft8201(void) { int ret = 0; struct fts_test *tdata = fts_ftest; struct incell_testitem *test_item = &tdata->ic.incell.u.item; bool temp_result = false; bool test_result = true; struct ft8201_info info; FTS_TEST_FUNC_ENTER(); FTS_TEST_INFO("test item:0x%x", fts_ftest->ic.incell.u.tmp); if (!tdata || !tdata->testresult || !tdata->buffer) { FTS_TEST_ERROR("tdata is null"); return -EINVAL; } ret = ft8201_test_init(&info); if (ret) { FTS_TEST_SAVE_ERR("test init fail\n"); return ret; } /* short test */ if (true == test_item->short_test) { ret = ft8201_short_test(&info, tdata, &temp_result); if ((ret < 0) || (false == temp_result)) { test_result = false; } } /* open test */ if (true == test_item->open_test) { ret = ft8201_open_test(&info, tdata, &temp_result); if ((ret < 0) || (false == temp_result)) { test_result = false; } } /* cb test */ if (true == test_item->cb_test) { ret = ft8201_cb_test(&info, tdata, &temp_result); if ((ret < 0) || (false == temp_result)) { test_result = false; } } /* rawdata test */ if (true == test_item->rawdata_test) { ret = ft8201_rawdata_test(&info, tdata, &temp_result); if ((ret < 0) || (false == temp_result)) { test_result = false; } } /* lcd noise test */ if (true == test_item->lcdnoise_test) { ret = ft8201_lcdnoise_test(&info, tdata, &temp_result); if ((ret < 0) || (false == temp_result)) { test_result = false; } } return test_result; } struct test_funcs test_func_ft8201 = { .ctype = {0x10}, .hwtype = IC_HW_INCELL, .key_num_total = 12, .start_test = start_test_ft8201, };