/* * ILITEK Touch IC driver * * Copyright (C) 2011 ILI Technology Corporation. * * Author: Dicky Chiang * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "ili9881x.h" #define VALUE 0 #define RETRY_COUNT 3 #define INT_CHECK 0 #define POLL_CHECK 1 #define BENCHMARK 1 #define NODETYPE 1 #define TYPE_BENCHMARK 0 #define TYPE_NO_JUGE 1 #define TYPE_JUGE 2 #define NORMAL_CSV_PASS_NAME "mp_pass" #define NORMAL_CSV_FAIL_NAME "mp_fail" #define NORMAL_CSV_WARNING_NAME "mp_warning" #define CSV_FILE_SIZE (1 * M) #define PARSER_MAX_CFG_BUF (512 * 3) #define PARSER_MAX_KEY_NUM (600 * 3) #define PARSER_MAX_KEY_NAME_LEN 100 #define PARSER_MAX_KEY_VALUE_LEN 2000 #define MAX_SECTION_NUM 100 #define BENCHMARK_KEY_NAME "benchmark_data" #define NODE_TYPE_KEY_NAME "node type" #define INI_ERR_OUT_OF_LINE -1 #define CMD_MUTUAL_DAC 0x1 #define CMD_MUTUAL_BG 0x2 #define CMD_MUTUAL_SIGNAL 0x3 #define CMD_MUTUAL_NO_BK 0x5 #define CMD_MUTUAL_HAVE_BK 0x8 #define CMD_MUTUAL_BK_DAC 0x10 #define CMD_SELF_DAC 0xC #define CMD_SELF_BG 0xF #define CMD_SELF_SIGNAL 0xD #define CMD_SELF_NO_BK 0xE #define CMD_SELF_HAVE_BK 0xB #define CMD_SELF_BK_DAC 0x11 #define CMD_KEY_DAC 0x14 #define CMD_KEY_BG 0x16 #define CMD_KEY_NO_BK 0x7 #define CMD_KEY_HAVE_BK 0x15 #define CMD_KEY_OPEN 0x12 #define CMD_KEY_SHORT 0x13 #define CMD_ST_DAC 0x1A #define CMD_ST_BG 0x1C #define CMD_ST_NO_BK 0x17 #define CMD_ST_HAVE_BK 0x1B #define CMD_ST_OPEN 0x18 #define CMD_TX_SHORT 0x19 #define CMD_RX_SHORT 0x4 #define CMD_RX_OPEN 0x6 #define CMD_TX_RX_DELTA 0x1E #define CMD_CM_DATA 0x9 #define CMD_CS_DATA 0xA #define CMD_TRCRQ_PIN 0x20 #define CMD_RESX2_PIN 0x21 #define CMD_MUTUAL_INTEGRA_TIME 0x22 #define CMD_SELF_INTEGRA_TIME 0x23 #define CMD_KEY_INTERGRA_TIME 0x24 #define CMD_ST_INTERGRA_TIME 0x25 #define CMD_PEAK_TO_PEAK 0x1D #define CMD_GET_TIMING_INFO 0x30 #define CMD_DOZE_P2P 0x32 #define CMD_DOZE_RAW 0x33 #define CMD_PIN_TEST 0x61 #define MP_DATA_PASS 0 #define MP_DATA_FAIL -1 #define Mathabs(x) ({ \ long ret; \ if (sizeof(x) == sizeof(long)) { \ long __x = (x); \ ret = (__x < 0) ? -__x : __x; \ } else { \ int __x = (x); \ ret = (__x < 0) ? -__x : __x; \ } \ ret; \ }) #define DUMP(fmt, arg...) \ do { \ if (debug_en) \ pr_cont(fmt, ##arg); \ } while (0) static struct ini_file_data { char section_name[PARSER_MAX_KEY_NAME_LEN]; char key_name[PARSER_MAX_KEY_NAME_LEN]; char key_value[PARSER_MAX_KEY_VALUE_LEN]; int section_len; int key_name_len; int key_val_len; } *ini_info; enum open_test_node_type { NO_COMPARE = 0x00, /* Not A Area, No Compare */ AA_Area = 0x01, /* AA Area, Compare using Charge_AA */ Border_Area = 0x02, /* Border Area, Compare using Charge_Border */ Notch = 0x04, /* Notch Area, Compare using Charge_Notch */ Round_Corner = 0x08, /* Round Corner, No Compare */ Skip_Micro = 0x10 /* Skip_Micro, No Compare */ }; enum mp_test_catalog { MUTUAL_TEST = 0, SELF_TEST = 1, KEY_TEST = 2, ST_TEST = 3, TX_RX_DELTA = 4, UNTOUCH_P2P = 5, PIXEL = 6, OPEN_TEST = 7, PEAK_TO_PEAK_TEST = 8, SHORT_TEST = 9, PIN_TEST = 10, }; struct mp_test_P540_open { s32 *tdf_700; s32 *tdf_250; s32 *tdf_200; s32 *cbk_700; s32 *cbk_250; s32 *cbk_200; s32 *charg_rate; s32 *full_Open; s32 *dac; }; struct mp_test_open_c { s32 *cap_dac; s32 *cap_raw; s32 *dcl_cap; }; struct open_test_para { int tvch; int tvcl; int gain; int cbk_step; int cint; } open_para; struct shor_test_para { int tvch; int tvcl; int variation; int rinternal; int cint; } short_para; static struct core_mp_test_data { u32 chip_pid; u16 chip_id; u8 chip_type; u8 chip_ver; u32 fw_ver; u32 protocol_ver; u32 core_ver; char ini_date[128]; char ini_ver[64]; int no_bk_shift; bool retry; bool m_signal; bool m_dac; bool s_signal; bool s_dac; bool key_dac; bool st_dac; bool p_no_bk; bool p_has_bk; bool open_integ; bool open_cap; bool isLongV; bool td_retry; bool all_pass; int cdc_len; int xch_len; int ych_len; int stx_len; int srx_len; int key_len; int st_len; int frame_len; int mp_items; int final_result; int short_varia; u32 overlay_start_addr; u32 overlay_end_addr; u32 mp_flash_addr; u32 mp_size; u8 dma_trigger_enable; /* Tx/Rx threshold & buffer */ int TxDeltaMax; int TxDeltaMin; int RxDeltaMax; int RxDeltaMin; s32 *tx_delta_buf; s32 *rx_delta_buf; s32 *tx_max_buf; s32 *tx_min_buf; s32 *rx_max_buf; s32 *rx_min_buf; int tdf; int busy_cdc; bool ctrl_lcm; bool lost_benchmark; bool lost_parameter; } core_mp = {0}; struct mp_test_items { /* The description must be the same as ini's section name */ char *desp; char *result; int catalog; u8 cmd; u8 spec_option; u8 type_option; bool run; bool lcm; int bch_mrk_multi; int max; int max_res; int item_result; int min; int min_res; int frame_count; int trimmed_mean; int lowest_percentage; int highest_percentage; int v_tdf_1; int v_tdf_2; int h_tdf_1; int h_tdf_2; int goldenmode; int max_min_mode; int bch_mrk_frm_num; int retry_cnt; u8 delay_time; u8 test_int_pin; u8 int_pulse_test; s32 *result_buf; s32 *buf; s32 *max_buf; s32 *min_buf; s32 *bench_mark_max; s32 *bench_mark_min; s32 **bch_mrk_max; s32 **bch_mrk_min; s32 *node_type; int (*do_test)(int index); }; #define MP_TEST_ITEM 50 static struct mp_test_items tItems[MP_TEST_ITEM] = { {.desp = "baseline data(bg)", .catalog = MUTUAL_TEST, .cmd = CMD_MUTUAL_BG, .lcm = ON}, {.desp = "untouch signal data(bg-raw-4096) - mutual", .catalog = MUTUAL_TEST, .cmd = CMD_MUTUAL_SIGNAL, .lcm = ON}, {.desp = "manual bk data(mutual)", .catalog = MUTUAL_TEST, .cmd = CMD_MUTUAL_BK_DAC, .lcm = ON}, {.desp = "calibration data(dac) - self", .catalog = SELF_TEST, .cmd = CMD_SELF_DAC, .lcm = ON}, {.desp = "baselin data(bg,self_tx,self_r)", .catalog = SELF_TEST, .cmd = CMD_SELF_BG, .lcm = ON}, {.desp = "untouch signal data(bg-raw-4096) - self", .catalog = SELF_TEST, .cmd = CMD_SELF_SIGNAL, .lcm = ON}, {.desp = "raw data(no bk) - self", .catalog = SELF_TEST, .cmd = CMD_SELF_NO_BK, .lcm = ON}, {.desp = "raw data(have bk) - self", .catalog = SELF_TEST, .cmd = CMD_SELF_HAVE_BK, .lcm = ON}, {.desp = "manual bk dac data(self_tx,self_rx)", .catalog = SELF_TEST, .cmd = CMD_SELF_BK_DAC, .lcm = ON}, {.desp = "calibration data(dac/icon)", .catalog = KEY_TEST, .cmd = CMD_KEY_DAC, .lcm = ON}, {.desp = "key baseline data", .catalog = KEY_TEST, .cmd = CMD_KEY_BG, .lcm = ON}, {.desp = "key raw data", .catalog = KEY_TEST, .cmd = CMD_KEY_NO_BK, .lcm = ON}, {.desp = "key raw bk dac", .catalog = KEY_TEST, .cmd = CMD_KEY_HAVE_BK, .lcm = ON}, {.desp = "key raw open test", .catalog = KEY_TEST, .cmd = CMD_KEY_OPEN, .lcm = ON}, {.desp = "key raw short test", .catalog = KEY_TEST, .cmd = CMD_KEY_SHORT, .lcm = ON}, {.desp = "st calibration data(dac)", .catalog = ST_TEST, .cmd = CMD_ST_DAC, .lcm = ON}, {.desp = "st baseline data(bg)", .catalog = ST_TEST, .cmd = CMD_ST_BG, .lcm = ON}, {.desp = "st raw data(no bk)", .catalog = ST_TEST, .cmd = CMD_ST_NO_BK, .lcm = ON}, {.desp = "st raw(have bk)", .catalog = ST_TEST, .cmd = CMD_ST_HAVE_BK, .lcm = ON}, {.desp = "st open data", .catalog = ST_TEST, .cmd = CMD_ST_OPEN, .lcm = ON}, {.desp = "tx short test", .catalog = MUTUAL_TEST, .cmd = CMD_TX_SHORT, .lcm = ON}, {.desp = "rx open", .catalog = MUTUAL_TEST, .cmd = CMD_RX_OPEN, .lcm = ON}, {.desp = "untouch cm data", .catalog = MUTUAL_TEST, .cmd = CMD_CM_DATA, .lcm = ON}, {.desp = "untouch cs data", .catalog = MUTUAL_TEST, .cmd = CMD_CS_DATA, .lcm = ON}, {.desp = "tx/rx delta", .catalog = TX_RX_DELTA, .cmd = CMD_TX_RX_DELTA, .lcm = ON}, {.desp = "untouch peak to peak", .catalog = UNTOUCH_P2P, .cmd = CMD_MUTUAL_SIGNAL, .lcm = ON}, {.desp = "pixel raw (no bk)", .catalog = PIXEL, .cmd = CMD_MUTUAL_NO_BK, .lcm = ON}, {.desp = "pixel raw (have bk)", .catalog = PIXEL, .cmd = CMD_MUTUAL_HAVE_BK, .lcm = ON}, {.desp = "noise peak to peak(cut panel)", .catalog = PEAK_TO_PEAK_TEST, .lcm = ON}, {.desp = "open test(integration)", .catalog = OPEN_TEST, .cmd = CMD_RX_SHORT, .lcm = ON}, {.desp = "open test(cap)", .catalog = OPEN_TEST, .cmd = CMD_RX_SHORT, .lcm = ON}, /* Following is the new test items for protocol 5.4.0 above */ {.desp = "pin test ( int and rst )", .catalog = PIN_TEST, .cmd = CMD_PIN_TEST, .lcm = ON}, {.desp = "noise peak to peak(with panel)", .catalog = PEAK_TO_PEAK_TEST, .lcm = ON}, {.desp = "noise peak to peak(ic only)", .catalog = PEAK_TO_PEAK_TEST, .cmd = CMD_PEAK_TO_PEAK, .lcm = ON}, {.desp = "open test(integration)_sp", .catalog = OPEN_TEST, .lcm = ON}, {.desp = "raw data(no bk)", .catalog = MUTUAL_TEST, .cmd = CMD_MUTUAL_NO_BK, .lcm = ON}, {.desp = "raw data(have bk)", .catalog = MUTUAL_TEST, .cmd = CMD_MUTUAL_HAVE_BK, .lcm = ON}, {.desp = "calibration data(dac)", .catalog = MUTUAL_TEST, .cmd = CMD_MUTUAL_DAC, .lcm = ON}, {.desp = "short test -ili9881", .catalog = SHORT_TEST, .cmd = CMD_RX_SHORT, .lcm = ON}, {.desp = "short test", .catalog = SHORT_TEST, .lcm = ON}, {.desp = "doze raw data", .catalog = MUTUAL_TEST, .lcm = ON}, {.desp = "doze peak to peak", .catalog = PEAK_TO_PEAK_TEST, .lcm = ON}, {.desp = "open test_c", .catalog = OPEN_TEST, .lcm = ON}, {.desp = "touch deltac", .catalog = MUTUAL_TEST, .lcm = ON}, /* LCM OFF TEST */ {.desp = "raw data(have bk) (lcm off)", .catalog = MUTUAL_TEST, .lcm = OFF}, {.desp = "raw data(no bk) (lcm off)", .catalog = MUTUAL_TEST, .lcm = OFF}, {.desp = "noise peak to peak(with panel) (lcm off)", .catalog = PEAK_TO_PEAK_TEST, .lcm = OFF}, {.desp = "noise peak to peak(ic only) (lcm off)", .catalog = PEAK_TO_PEAK_TEST, .lcm = OFF}, {.desp = "raw data_td (lcm off)", .catalog = MUTUAL_TEST, .lcm = OFF}, {.desp = "peak to peak_td (lcm off)", .catalog = PEAK_TO_PEAK_TEST, .lcm = OFF}, }; static struct run_index { int count; int index[MP_TEST_ITEM]; } ri; static s32 *frame_buf; static s32 **frm_buf; static s32 *key_buf; static s32 *frame1_cbk700, *frame1_cbk250, *frame1_cbk200; static s32 *cap_dac, *cap_raw; static int g_ini_items = 0; static char csv_name[128] = {0}; static char seq_item[MAX_SECTION_NUM][PARSER_MAX_KEY_NAME_LEN] = {{0} }; static int isspace_t(int x) { if (x == ' ' || x == '\t' || x == '\n' || x == '\f' || x == '\b' || x == '\r') return 1; else return 0; } static void dump_benchmark_data(s32 *max_ptr, s32 *min_ptr) { ili_dump_data(max_ptr, 32, core_mp.frame_len, 0, "Dump Benchmark Max : "); ili_dump_data(min_ptr, 32, core_mp.frame_len, 0, "Dump Benchmark Min : "); } static void dump_node_type_buffer(s32 *node_ptr, u8 *name) { ili_dump_data(node_ptr, 32, core_mp.frame_len, 0, "Dump NodeType : "); } static int parser_get_ini_key_value(char *section, char *key, char *value) { int i = 0; int ret = -2; for (i = 0; i < g_ini_items; i++) { if (ipio_strcmp(section, ini_info[i].section_name) != 0) continue; if (ipio_strcmp(key, ini_info[i].key_name) == 0) { ipio_memcpy(value, ini_info[i].key_value, ini_info[i].key_val_len, PARSER_MAX_KEY_VALUE_LEN); ILI_DBG("%s (key: %s, value:%s) => (ini key: %s, val: %s)\n", __func__, key, value, ini_info[i].key_name, ini_info[i].key_value); ret = 0; break; } } return ret; } static void parser_ini_nodetype(s32 *type_ptr, char *desp, int frame_len) { int i = 0, j = 0, index1 = 0, temp, count = 0; char str[512] = {0}, record = ','; for (i = 0; i < g_ini_items; i++) { if (!strstr(ini_info[i].section_name, desp) || ipio_strcmp(ini_info[i].key_name, NODE_TYPE_KEY_NAME) != 0) { continue; } record = ','; for (j = 0, index1 = 0; j <= ini_info[i].key_val_len; j++) { if (ini_info[i].key_value[j] == ';' || j == ini_info[i].key_val_len) { if (record != '.') { memset(str, 0, sizeof(str)); ipio_memcpy(str, &ini_info[i].key_value[index1], (j - index1), sizeof(str)); temp = ili_katoi(str); /* Over boundary, end to calculate. */ if (count >= frame_len) { input_err(true, ilits->dev, "%s count(%d) is larger than frame length, break\n", __func__, count); break; } type_ptr[count] = temp; count++; } record = ini_info[i].key_value[j]; index1 = j + 1; } } } } static void parser_ini_benchmark(s32 *max_ptr, s32 *min_ptr, int8_t type, char *desp, int frame_len, char *bchmrk_name) { int i = 0, j = 0, index1 = 0, temp, count = 0; char str[512] = {0}, record = ','; s32 data[4]; char benchmark_str[256] = {0}; /* format complete string from the name of section "_Benchmark_Data". */ snprintf(benchmark_str, sizeof(benchmark_str), "%s%s%s", desp, "_", bchmrk_name); ILI_DBG("%s benchmark_str = %s\n", __func__, benchmark_str); for (i = 0; i < g_ini_items; i++) { if ((ipio_strcmp(ini_info[i].section_name, benchmark_str) != 0)) continue; record = ','; for (j = 0, index1 = 0; j <= ini_info[i].key_val_len; j++) { if (ini_info[i].key_value[j] == ',' || ini_info[i].key_value[j] == ';' || ini_info[i].key_value[j] == '.' || j == ini_info[i].key_val_len) { if (record != '.') { memset(str, 0, sizeof(str)); ipio_memcpy(str, &ini_info[i].key_value[index1], (j - index1), sizeof(str)); temp = ili_katoi(str); data[(count % 4)] = temp; /* Over boundary, end to calculate. */ if ((count / 4) >= frame_len) { input_err(true, ilits->dev, "%s count (%d) is larger than frame length, break\n", __func__, (count / 4)); break; } if ((count % 4) == 3) { if (data[0] == 1) { if (type == VALUE) { max_ptr[count/4] = data[1] + data[2]; min_ptr[count/4] = data[1] - data[3]; } else { max_ptr[count/4] = data[1] + (data[1] * data[2]) / 100; min_ptr[count/4] = data[1] - (data[1] * data[3]) / 100; } } else { max_ptr[count/4] = INT_MAX; min_ptr[count/4] = INT_MIN; } } count++; } record = ini_info[i].key_value[j]; index1 = j + 1; } } } } static int parser_get_tdf_value(char *str, int catalog) { u32 i, ans, index = 0, flag = 0, count = 0, size = 0; char s[10] = {0}; if (!str) { input_err(true, ilits->dev, "%s String is null\n", __func__); return -1; } size = strlen(str); for (i = 0, count = 0; i < size; i++) { if (str[i] == '.') { flag = 1; continue; } s[index++] = str[i]; if (flag) count++; } ans = ili_katoi(s); /* Multiply by 100 to shift out of decimal point */ if (catalog == SHORT_TEST) { if (count == 0) ans = ans * 100; else if (count == 1) ans = ans * 10; } return ans; } static int parser_get_u8_array(char *key, u8 *buf, u16 base, int len) { char *s = key; char *pToken; int ret, conut = 0; long s_to_long = 0; if (strlen(s) == 0 || len <= 0) { input_err(true, ilits->dev, "%s Can't find any characters inside buffer\n", __func__); return -1; } /* * @base: The number base to use. The maximum supported base is 16. If base is * given as 0, then the base of the string is automatically detected with the * conventional semantics - If it begins with 0x the number will be parsed as a * hexadecimal (case insensitive), if it otherwise begins with 0, it will be * parsed as an octal number. Otherwise it will be parsed as a decimal. */ if (isspace_t((int)(unsigned char)*s) == 0) { while ((pToken = strsep(&s, ",")) != NULL) { ret = kstrtol(pToken, base, &s_to_long); if (ret == 0) buf[conut] = s_to_long; else input_info(true, ilits->dev, "%s convert string too long, ret = %d\n", __func__, ret); conut++; if (conut >= len) break; } } return conut; } static int parser_get_int_data(char *section, char *keyname, char *rv, int rv_len) { int len = 0; char value[512] = { 0 }; if (rv == NULL || section == NULL || keyname == NULL) { input_err(true, ilits->dev, "%s Parameters are invalid\n", __func__); return -EINVAL; } /* return a white-space string if get nothing */ if (parser_get_ini_key_value(section, keyname, value) < 0) { snprintf(rv, rv_len, "%s", value); return 0; } len = snprintf(rv, rv_len, "%s", value); return len; } /* Count the number of each line and assign the content to tmp buffer */ static int parser_get_ini_phy_line(char *data, char *buffer, int maxlen) { int i = 0; int j = 0; int iRetNum = -1; char ch1 = '\0'; for (i = 0, j = 0; i < maxlen; j++) { ch1 = data[j]; iRetNum = j + 1; if (ch1 == '\n' || ch1 == '\r') { /* line end */ ch1 = data[j + 1]; if (ch1 == '\n' || ch1 == '\r') iRetNum++; break; } else if (ch1 == 0x00) { //iRetNum = -1; break; /* file end */ } buffer[i++] = ch1; } buffer[i] = '\0'; return iRetNum; } static char *parser_ini_str_trim_r(char *buf) { int len, i; char *tmp = NULL; char x[512] = {0}; char *y = NULL; char *empty = ""; len = strlen(buf); if (len < sizeof(x)) { tmp = x; goto copy; } y = kzalloc(len, GFP_KERNEL); if (ERR_ALLOC_MEM(y)) { input_err(true, ilits->dev, "%s Failed to allocate tmp buf\n", __func__); return empty; } tmp = y; copy: for (i = 0; i < len; i++) { if (buf[i] != ' ') break; } if (i < len) strncpy(tmp, (buf + i), (len - i)); strncpy(buf, tmp, len); ipio_kfree((void **)&y); return buf; } static int parser_get_ini_phy_data(char *data, int fsize) { int i, n = 0, ret = 0, banchmark_flag = 0, empty_section, nodetype_flag = 0; int offset = 0, isEqualSign = 0, scount = 0; char *ini_buf = NULL, *tmpSectionName = NULL; char M_CFG_SSL = '['; char M_CFG_SSR = ']'; /* char M_CFG_NIS = ':'; */ char M_CFG_NTS = '#'; char M_CFG_EQS = '='; if (data == NULL) { input_err(true, ilits->dev, "%s INI data is NULL\n", __func__); ret = -EINVAL; goto out; } ini_buf = kzalloc((PARSER_MAX_CFG_BUF + 1) * sizeof(char), GFP_KERNEL); if (ERR_ALLOC_MEM(ini_buf)) { input_err(true, ilits->dev, "%s Failed to allocate ini_buf memory, %ld\n", __func__, PTR_ERR(ini_buf)); ret = -ENOMEM; goto out; } tmpSectionName = kzalloc((PARSER_MAX_CFG_BUF + 1) * sizeof(char), GFP_KERNEL); if (ERR_ALLOC_MEM(tmpSectionName)) { input_err(true, ilits->dev, "%s Failed to allocate tmpSectionName memory, %ld\n", __func__, PTR_ERR(tmpSectionName)); ret = -ENOMEM; goto out; } memset(seq_item, 0, MP_TEST_ITEM * PARSER_MAX_KEY_NAME_LEN * sizeof(char)); while (true) { banchmark_flag = 0; empty_section = 0; nodetype_flag = 0; if (g_ini_items > PARSER_MAX_KEY_NUM) { input_err(true, ilits->dev, "%s MAX_KEY_NUM: Out of length\n", __func__); goto out; } if (offset >= fsize) goto out;/*over size*/ n = parser_get_ini_phy_line(data + offset, ini_buf, PARSER_MAX_CFG_BUF); if (n < 0) { input_err(true, ilits->dev, "%s End of Line\n", __func__); goto out; } offset += n; n = strlen(parser_ini_str_trim_r(ini_buf)); if (n == 0 || ini_buf[0] == M_CFG_NTS) continue; /* Get section names */ if (n > 2 && ((ini_buf[0] == M_CFG_SSL && ini_buf[n - 1] != M_CFG_SSR))) { input_err(true, ilits->dev, "%s Bad Section: %s\n", __func__, ini_buf); ret = -EINVAL; goto out; } else { if (ini_buf[0] == M_CFG_SSL) { ini_info[g_ini_items].section_len = n - 2; if (ini_info[g_ini_items].section_len > PARSER_MAX_KEY_NAME_LEN) { input_err(true, ilits->dev, "%s MAX_KEY_NAME_LEN: Out Of Length\n", __func__); ret = INI_ERR_OUT_OF_LINE; goto out; } if (scount > MAX_SECTION_NUM) { input_err(true, ilits->dev, "%s seq_item is over than its define (%d), abort\n", __func__, scount); ret = INI_ERR_OUT_OF_LINE; goto out; } ini_buf[n - 1] = 0x00; strncpy((char *)tmpSectionName, ini_buf + 1, (PARSER_MAX_CFG_BUF + 1) * sizeof(char)); banchmark_flag = 0; nodetype_flag = 0; strncpy(seq_item[scount], tmpSectionName, PARSER_MAX_KEY_NAME_LEN); scount++; ILI_DBG("%s Section Name: %s, Len: %d, offset = %d\n", __func__, seq_item[scount], n - 2, offset); continue; } } /* copy section's name without square brackets to its real buffer */ strncpy(ini_info[g_ini_items].section_name, tmpSectionName, (PARSER_MAX_KEY_NAME_LEN * sizeof(char))); ini_info[g_ini_items].section_len = strlen(tmpSectionName); isEqualSign = 0; for (i = 0; i < n; i++) { if (ini_buf[i] == M_CFG_EQS) { isEqualSign = i; break; } if (ini_buf[i] == M_CFG_SSL || ini_buf[i] == M_CFG_SSR) { empty_section = 1; break; } } if (isEqualSign == 0) { if (empty_section) continue; if (strstr(ini_info[g_ini_items].section_name, BENCHMARK_KEY_NAME) != NULL) { isEqualSign = -1; ini_info[g_ini_items].key_name_len = strlen(ini_info[g_ini_items].section_name); strncpy(ini_info[g_ini_items].key_name, ini_info[g_ini_items].section_name, (PARSER_MAX_KEY_NAME_LEN * sizeof(char))); ini_info[g_ini_items].key_val_len = n; } else if (strstr(ini_info[g_ini_items].section_name, NODE_TYPE_KEY_NAME) != NULL) { isEqualSign = -1; ini_info[g_ini_items].key_name_len = strlen(NODE_TYPE_KEY_NAME); strncpy(ini_info[g_ini_items].key_name, NODE_TYPE_KEY_NAME, (PARSER_MAX_KEY_NAME_LEN * sizeof(char))); ini_info[g_ini_items].key_val_len = n; } else { continue; } } else { ini_info[g_ini_items].key_name_len = isEqualSign; if (ini_info[g_ini_items].key_name_len > PARSER_MAX_KEY_NAME_LEN) { /* ret = CFG_ERR_OUT_OF_LEN; */ input_err(true, ilits->dev, "%s MAX_KEY_NAME_LEN: Out Of Length\n", __func__); ret = INI_ERR_OUT_OF_LINE; goto out; } ipio_memcpy(ini_info[g_ini_items].key_name, ini_buf, ini_info[g_ini_items].key_name_len, PARSER_MAX_KEY_NAME_LEN); ini_info[g_ini_items].key_val_len = n - isEqualSign - 1; } if (ini_info[g_ini_items].key_val_len > PARSER_MAX_KEY_VALUE_LEN) { input_err(true, ilits->dev, "%s MAX_KEY_VALUE_LEN: Out Of Length\n", __func__); ret = INI_ERR_OUT_OF_LINE; goto out; } ipio_memcpy(ini_info[g_ini_items].key_value, ini_buf + isEqualSign + 1, ini_info[g_ini_items].key_val_len, PARSER_MAX_KEY_VALUE_LEN); ILI_DBG("%s %s = %s\n", __func__, ini_info[g_ini_items].key_name, ini_info[g_ini_items].key_value); g_ini_items++; } out: ipio_kfree((void **)&ini_buf); ipio_kfree((void **)&tmpSectionName); return ret; } static int ilitek_tddi_mp_ini_parser(const char *path) { int i, ret = 0, fsize = 0; char *tmp = NULL; const struct firmware *ini = NULL; struct file *f = NULL; mm_segment_t old_fs; loff_t pos = 0; input_info(true, ilits->dev, "%s ini file path = %s\n", __func__, path); f = filp_open(path, O_RDONLY, 644); if (ERR_ALLOC_MEM(f)) { input_err(true, ilits->dev, "%s Failed to open ini file at %ld, try to request_firmware\n", __func__, PTR_ERR(f)); f = NULL; path = ilits->md_ini_rq_path; input_info(true, ilits->dev, "%s request path = %s\n", __func__, path); if (request_firmware(&ini, path, ilits->dev) < 0) { input_err(true, ilits->dev, "%s Request ini file failed\n", __func__); return -EINVAL; } } if (f != NULL) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) fsize = f->f_inode->i_size; #else struct inode *inode; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) inode = f->f_dentry->d_inode; #else inode = f->f_path.dentry->d_inode; #endif fsize = inode->i_size; #endif } else { fsize = ini->size; } input_info(true, ilits->dev, "%s ini file size = %d\n", __func__, fsize); if (fsize <= 0) { input_err(true, ilits->dev, "%s The size of file is invaild\n", __func__); ret = -EINVAL; goto out; } tmp = vmalloc(fsize+1); if (ERR_ALLOC_MEM(tmp)) { input_err(true, ilits->dev, "%s Failed to allocate tmp memory, %ld\n", __func__, PTR_ERR(tmp)); ret = -ENOMEM; goto out; } if (f != NULL) { old_fs = get_fs(); set_fs(get_ds()); vfs_read(f, tmp, fsize, &pos); set_fs(old_fs); tmp[fsize] = 0x0; } else { memcpy(tmp, ini->data, fsize); } g_ini_items = 0; /* Initialise ini strcture */ for (i = 0; i < PARSER_MAX_KEY_NUM; i++) { memset(ini_info[i].section_name, 0, PARSER_MAX_KEY_NAME_LEN); memset(ini_info[i].key_name, 0, PARSER_MAX_KEY_NAME_LEN); memset(ini_info[i].key_value, 0, PARSER_MAX_KEY_VALUE_LEN); ini_info[i].section_len = 0; ini_info[i].key_name_len = 0; ini_info[i].key_val_len = 0; } /* change all characters to lower case */ for (i = 0; i < fsize; i++) tmp[i] = tolower(tmp[i]); ret = parser_get_ini_phy_data(tmp, fsize); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to get physical ini data, ret = %d\n", __func__, ret); goto out; } input_info(true, ilits->dev, "%s Parsed ini file done\n", __func__); out: ipio_vfree((void **)&tmp); if (f != NULL) filp_close(f, NULL); else release_firmware(ini); return ret; } static void run_pixel_test(int index) { int i, x, y; s32 *p_comb = frame_buf; for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { int tmp[4] = { 0 }, max = 0; int shift = y * core_mp.xch_len; int centre = p_comb[shift + x]; /* * if its position is in corner, the number of point * we have to minus is around 2 to 3. */ if (y == 0 && x == 0) { tmp[0] = Mathabs(centre - p_comb[(shift + 1) + x]); /* down */ tmp[1] = Mathabs(centre - p_comb[shift + (x + 1)]); /* right */ } else if (y == (core_mp.ych_len - 1) && x == 0) { tmp[0] = Mathabs(centre - p_comb[(shift - 1) + x]); /* up */ tmp[1] = Mathabs(centre - p_comb[shift + (x + 1)]); /* right */ } else if (y == 0 && x == (core_mp.xch_len - 1)) { tmp[0] = Mathabs(centre - p_comb[(shift + 1) + x]); /* down */ tmp[1] = Mathabs(centre - p_comb[shift + (x - 1)]); /* left */ } else if (y == (core_mp.ych_len - 1) && x == (core_mp.xch_len - 1)) { tmp[0] = Mathabs(centre - p_comb[(shift - 1) + x]); /* up */ tmp[1] = Mathabs(centre - p_comb[shift + (x - 1)]); /* left */ } else if (y == 0 && x != 0) { tmp[0] = Mathabs(centre - p_comb[(shift + 1) + x]); /* down */ tmp[1] = Mathabs(centre - p_comb[shift + (x - 1)]); /* left */ tmp[2] = Mathabs(centre - p_comb[shift + (x + 1)]); /* right */ } else if (y != 0 && x == 0) { tmp[0] = Mathabs(centre - p_comb[(shift - 1) + x]); /* up */ tmp[1] = Mathabs(centre - p_comb[shift + (x + 1)]); /* right */ tmp[2] = Mathabs(centre - p_comb[(shift + 1) + x]); /* down */ } else if (y == (core_mp.ych_len - 1) && x != 0) { tmp[0] = Mathabs(centre - p_comb[(shift - 1) + x]); /* up */ tmp[1] = Mathabs(centre - p_comb[shift + (x - 1)]); /* left */ tmp[2] = Mathabs(centre - p_comb[shift + (x + 1)]); /* right */ } else if (y != 0 && x == (core_mp.xch_len - 1)) { tmp[0] = Mathabs(centre - p_comb[(shift - 1) + x]); /* up */ tmp[1] = Mathabs(centre - p_comb[shift + (x - 1)]); /* left */ tmp[2] = Mathabs(centre - p_comb[(shift + 1) + x]); /* down */ } else { /* middle minus four directions */ tmp[0] = Mathabs(centre - p_comb[(shift - 1) + x]); /* up */ tmp[1] = Mathabs(centre - p_comb[(shift + 1) + x]); /* down */ tmp[2] = Mathabs(centre - p_comb[shift + (x - 1)]); /* left */ tmp[3] = Mathabs(centre - p_comb[shift + (x + 1)]); /* right */ } max = tmp[0]; for (i = 0; i < 4; i++) { if (tmp[i] > max) max = tmp[i]; } tItems[index].buf[shift + x] = max; } } } static void run_untouch_p2p_test(int index) { int x, y; s32 *p_comb = frame_buf; for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { int shift = y * core_mp.xch_len; if (p_comb[shift + x] > tItems[index].max_buf[shift + x]) tItems[index].max_buf[shift + x] = p_comb[shift + x]; if (p_comb[shift + x] < tItems[index].min_buf[shift + x]) tItems[index].min_buf[shift + x] = p_comb[shift + x]; tItems[index].buf[shift + x] = tItems[index].max_buf[shift + x] - tItems[index].min_buf[shift + x]; } } } static int run_open_test(int index) { int i, x, y, k, ret = 0; int border_x[] = {-1, 0, 1, 1, 1, 0, -1, -1}; int border_y[] = {-1, -1, -1, 0, 1, 1, 1, 0}; s32 *p_comb = frame_buf; if (ipio_strcmp(tItems[index].desp, "open test(integration)") == 0) { for (i = 0; i < core_mp.frame_len; i++) tItems[index].buf[i] = p_comb[i]; } else if (ipio_strcmp(tItems[index].desp, "open test(cap)") == 0) { /* * Each result is getting from a 3 by 3 grid depending on where the centre location is. * So if the centre is at corner, the number of node grabbed from a grid will be different. */ for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { int sum = 0, avg = 0, count = 0; int shift = y * core_mp.xch_len; int centre = p_comb[shift + x]; for (k = 0; k < 8; k++) { if (((y + border_y[k] >= 0) && (y + border_y[k] < core_mp.ych_len)) && ((x + border_x[k] >= 0) && (x + border_x[k] < core_mp.xch_len))) { count++; sum += p_comb[(y + border_y[k]) * core_mp.xch_len + (x + border_x[k])]; } } avg = (sum + centre) / (count + 1); /* plus 1 because of centre */ tItems[index].buf[shift + x] = (centre * 100) / avg; } } } return ret; } static void run_tx_rx_delta_test(int index) { int x, y; s32 *p_comb = frame_buf; for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { int shift = y * core_mp.xch_len; /* Tx Delta */ if (y != (core_mp.ych_len - 1)) core_mp.tx_delta_buf[shift + x] = Mathabs(p_comb[shift + x] - p_comb[(shift + 1) + x]); /* Rx Delta */ if (x != (core_mp.xch_len - 1)) core_mp.rx_delta_buf[shift + x] = Mathabs(p_comb[shift + x] - p_comb[shift + (x + 1)]); } } } static char *get_date_time_str(void) { struct timespec now_time; struct rtc_time rtc_now_time; static char time_data_buf[128] = { 0 }; getnstimeofday(&now_time); rtc_time_to_tm(now_time.tv_sec, &rtc_now_time); snprintf(time_data_buf, sizeof(time_data_buf), "%04d%02d%02d-%02d%02d%02d", (rtc_now_time.tm_year + 1900), rtc_now_time.tm_mon + 1, rtc_now_time.tm_mday, rtc_now_time.tm_hour, rtc_now_time.tm_min, rtc_now_time.tm_sec); return time_data_buf; } static void mp_print_csv_header(char *csv, int *csv_len, int *csv_line, int file_size) { int i, seq, tmp_len = *csv_len, tmp_line = *csv_line; /* header must has 19 line*/ tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "==============================================================================\n"); tmp_line++; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "ILITek C-TP Utility V%s %x : Driver Sensor Test\n", DRIVER_VERSION, core_mp.chip_pid); tmp_line++; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "Confidentiality Notice:\n"); tmp_line++; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "Any information of this tool is confidential and privileged.\n"); tmp_line++; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "@ ILI TECHNOLOGY CORP. All Rights Reserved.\n"); tmp_line++; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "==============================================================================\n"); tmp_line++; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "Firmware Version ,0x%x\n", core_mp.fw_ver); tmp_line++; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "Panel information ,XCH=%d, YCH=%d\n", core_mp.xch_len, core_mp.ych_len); tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "INI Release Version ,%s\n", core_mp.ini_ver); tmp_line++; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "INI Release Date ,%s\n", core_mp.ini_date); tmp_line++; tmp_line++; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "Test Item:\n"); tmp_line++; for (seq = 0; seq < ri.count; seq++) { i = ri.index[seq]; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), " ---%s\n", tItems[i].desp); tmp_line++; } while (tmp_line < 19) { tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "\n"); tmp_line++; } tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "==============================================================================\n"); *csv_len = tmp_len; *csv_line = tmp_line; } static void mp_print_csv_tail(char *csv, int *csv_len, int file_size) { int i, seq, tmp_len = *csv_len; tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "==============================================================================\n"); tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "Result_Summary \n"); for (seq = 0; seq < ri.count; seq++) { i = ri.index[seq]; if (tItems[i].item_result == MP_DATA_PASS) { tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), " {%s} ,OK\n", tItems[i].desp); } else { tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), " {%s} ,NG\n", tItems[i].desp); } } *csv_len = tmp_len; } static void mp_print_csv_cdc_cmd(char *csv, int *csv_len, int index, int file_size) { int i, slen = 0, tmp_len = *csv_len, size; char str[128] = {0}; char *open_sp_cmd[] = {"open dac", "open raw1", "open raw2", "open raw3"}; char *open_c_cmd[] = {"open cap1 dac", "open cap1 raw"}; char *name = tItems[index].desp; if (ipio_strcmp(name, "open test(integration)_sp") == 0) { size = ARRAY_SIZE(open_sp_cmd); for (i = 0; i < size; i++) { slen = parser_get_int_data("pv5_4 command", open_sp_cmd[i], str, sizeof(str)); if (slen < 0) input_err(true, ilits->dev, "%s Failed to get CDC command %s from ini\n", __func__, open_sp_cmd[i]); else tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "%s = ,%s\n", open_sp_cmd[i], str); } } else if (ipio_strcmp(name, "open test_c") == 0) { size = ARRAY_SIZE(open_c_cmd); for (i = 0; i < size; i++) { slen = parser_get_int_data("pv5_4 command", open_c_cmd[i], str, sizeof(str)); if (slen < 0) input_err(true, ilits->dev, "%s Failed to get CDC command %s from ini\n", __func__, open_sp_cmd[i]); else tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "%s = ,%s\n", open_c_cmd[i], str); } } else { slen = parser_get_int_data("pv5_4 command", name, str, sizeof(str)); if (slen < 0) input_err(true, ilits->dev, "%s Failed to get CDC command %s from ini\n", __func__, name); else tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "CDC command = ,%s\n", str); /* Print short parameters */ if (ipio_strcmp(name, "short test") == 0) tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "Variation = ,%d\n", short_para.variation); /* Print td second command */ if (core_mp.td_retry && (ipio_strcmp(name, "peak to peak_td (lcm off)") == 0)) { name = "peak to peak_td (lcm off)_2"; parser_get_int_data("pv5_4 command", name, str, sizeof(str)); tmp_len += snprintf(csv + tmp_len, (file_size - tmp_len), "CDC command 2 = ,%s\n", str); } } *csv_len = tmp_len; } static void mp_compare_cdc_show_result(int index, s32 *tmp, char *csv, int *csv_len, int type, s32 *max_ts, s32 *min_ts, const char *desp, int file_zise) { int x, y, tmp_len = *csv_len; int mp_result = MP_DATA_PASS; if (ERR_ALLOC_MEM(tmp)) { input_err(true, ilits->dev, "%s The data of test item is null (%p)\n", __func__, tmp); mp_result = -EMP_INVAL; goto out; } /* print X raw only */ for (x = 0; x < core_mp.xch_len; x++) { if (x == 0) { DUMP("\n %s ", desp); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), "\n %s ,", desp); } DUMP(" X_%d ,", (x+1)); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), " X_%d ,", (x+1)); } DUMP("\n"); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), "\n"); for (y = 0; y < core_mp.ych_len; y++) { DUMP(" Y_%d ,", (y+1)); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), " Y_%d ,", (y+1)); for (x = 0; x < core_mp.xch_len; x++) { int shift = y * core_mp.xch_len + x; /* In Short teset, we only identify if its value is low than min threshold. */ if (tItems[index].catalog == SHORT_TEST) { if (tmp[shift] < min_ts[shift]) { DUMP(" #%7d ", tmp[shift]); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), "#%7d,", tmp[shift]); mp_result = MP_DATA_FAIL; } else { DUMP(" %7d ", tmp[shift]); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), " %7d, ", tmp[shift]); } continue; } if ((tmp[shift] <= max_ts[shift] && tmp[shift] >= min_ts[shift]) || (type != TYPE_JUGE)) { if ((tmp[shift] == INT_MAX || tmp[shift] == INT_MIN) && (type == TYPE_BENCHMARK)) { DUMP("%s", "BYPASS,"); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), "BYPASS,"); } else { DUMP(" %7d ", tmp[shift]); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), " %7d, ", tmp[shift]); } } else { if (tmp[shift] > max_ts[shift]) { DUMP(" *%7d ", tmp[shift]); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), "*%7d,", tmp[shift]); } else { DUMP(" #%7d ", tmp[shift]); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), "#%7d,", tmp[shift]); } mp_result = MP_DATA_FAIL; } } DUMP("\n"); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), "\n"); } out: if (type == TYPE_JUGE) { if (mp_result == MP_DATA_PASS) { pr_info("\n Result : PASS\n"); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), "Result : PASS\n"); } else { pr_info("\n Result : FAIL\n"); tmp_len += snprintf(csv + tmp_len, (file_zise - tmp_len), "Result : FAIL\n"); } } *csv_len = tmp_len; } #define ABS(a, b) ((a > b) ? (a - b) : (b - a)) #define ADDR(x, y) ((y * core_mp.xch_len) + (x)) static int compare_charge(s32 *charge_rate, int x, int y, s32 *inNodeType, int Charge_AA, int Charge_Border, int Charge_Notch) { int OpenThreadhold, tempY, tempX, ret, k; int sx[8] = {-1, 0, 1, -1, 1, -1, 0, 1}; int sy[8] = {-1, -1, -1, 0, 0, 1, 1, 1}; ret = charge_rate[ADDR(x, y)]; /*Setting Threadhold from node type */ if (charge_rate[ADDR(x, y)] == 0) return ret; else if ((inNodeType[ADDR(x, y)] & AA_Area) == AA_Area) OpenThreadhold = Charge_AA; else if ((inNodeType[ADDR(x, y)] & Border_Area) == Border_Area) OpenThreadhold = Charge_Border; else if ((inNodeType[ADDR(x, y)] & Notch) == Notch) OpenThreadhold = Charge_Notch; else return ret; /* compare carge rate with 3*3 node */ /* by pass => 1.no compare 2.corner 3.Skip_Micro 4.full open fail node */ for (k = 0; k < 8; k++) { tempX = x + sx[k]; tempY = y + sy[k]; /*out of range */ if ((tempX < 0) || (tempX >= core_mp.xch_len) || (tempY < 0) || (tempY >= core_mp.ych_len)) continue; if ((inNodeType[ADDR(tempX, tempY)] == NO_COMPARE) || ((inNodeType[ADDR(tempX, tempY)] & Round_Corner) == Round_Corner) || ((inNodeType[ADDR(tempX, tempY)] & Skip_Micro) == Skip_Micro) || charge_rate[ADDR(tempX, tempY)] == 0) continue; if ((charge_rate[ADDR(tempX, tempY)] - charge_rate[ADDR(x, y)]) > OpenThreadhold) return OpenThreadhold; } return ret; } static int full_open_rate_compare(s32 *full_open, s32 *cbk, int x, int y, s32 inNodeType, int full_open_rate) { int ret = true; if ((inNodeType == NO_COMPARE) || ((inNodeType & Round_Corner) == Round_Corner)) return true; if (full_open[ADDR(x, y)] < (cbk[ADDR(x, y)] * full_open_rate / 100)) ret = false; return ret; } static s32 open_sp_formula(int dac, int raw, int tvch, int tvcl) { s32 ret = 0; u16 id = core_mp.chip_id; if (id == ILI9881_CHIP) { ret = ((dac * 10000 * 161 / 100) - (16384 / 2 - raw) * 20000 * 7 / 16384 * 36 / 10) / (tvch - tvcl) / 2; } else { ret = ((dac * 10000 * 131 / 100) - (16384 / 2 - raw) * 20000 * 7 / 16384 * 36 / 10) / (tvch - tvcl) / 2; } return ret; } static s32 open_c_formula(int inCap1DAC, int inCap1Raw, int accuracy) { s32 inCap1Value = 0; u16 id = core_mp.chip_id; u8 type = core_mp.chip_type; int inFoutRange = 16384; int inFoutRange_half = 8192; int inVadc_range = 36; int inVbk = 39; int inCbk_step = open_para.cbk_step;/* from mp.ini */ int inCint = open_para.cint;/* from mp.ini */ int inVdrv = open_para.tvch - open_para.tvcl;/* from mp.ini */ int inGain = open_para.gain;/* from mp.ini */ int inMagnification = 10; int inPartDac = 0; int inPartRaw = 0; if ((inCbk_step == 0) || (inCint == 0)) { if (id == ILI9881_CHIP) { if ((type == ILI_N) || (type == ILI_O)) { inCbk_step = 32; inCint = 70; } } else if (id == ILI9882_CHIP) { if (type == ILI_N) { inCbk_step = 42; inCint = 70; } else if (type == ILI_H) { inCbk_step = 42; inCint = 69; } } else if (id == ILI7807_CHIP) { if (type == ILI_Q) { inCbk_step = 28; inCint = 70; } else if (type == ILI_S) { inCbk_step = 38; inCint = 66; inVbk = 42; inVdrv = inVdrv / 10; inGain = inGain / 10; } else if (type == ILI_V) { inCbk_step = 28; inCint = 70; } } } inPartDac = (inCap1DAC * inCbk_step * inVbk / 2); inPartRaw = ((inCap1Raw - inFoutRange_half) * inVadc_range * inCint * 10 / inFoutRange); if (accuracy) inCap1Value = ((inPartDac + inPartRaw) * 10) / inVdrv / inMagnification / inGain; else inCap1Value = (inPartDac + inPartRaw) / inVdrv / inMagnification / inGain; return inCap1Value; } static void allnode_open_cdc_result(int index, int *buf, int *dac, int *raw) { int i; char *desp = tItems[index].desp; char str[32] = {0}; int accuracy = 0; if (ipio_strcmp(desp, "open test(integration)_sp") == 0) { for (i = 0; i < core_mp.frame_len; i++) buf[i] = open_sp_formula(dac[i], raw[i], open_para.tvch, open_para.tvcl); } else if (ipio_strcmp(desp, "open test_c") == 0) { if (parser_get_int_data(desp, "accuracy", str, sizeof(str)) > 0) accuracy = ili_katoi(str); for (i = 0; i < core_mp.frame_len; i++) buf[i] = open_c_formula(dac[i], raw[i], accuracy); } } static int codeToOhm(s32 *ohm, s32 *Code, u16 *v_tdf, u16 *h_tdf) { u16 id = core_mp.chip_id; u8 type = core_mp.chip_type; int inTVCH = short_para.tvch; int inTVCL = short_para.tvcl; int inVariation = short_para.variation; int inTDF1 = 0; int inTDF2 = 0; int inCint = short_para.cint; int inRinternal = short_para.rinternal; s32 temp = 0; int j = 0; if (core_mp.isLongV) { inTDF1 = *v_tdf; inTDF2 = *(v_tdf + 1); } else { inTDF1 = *h_tdf; inTDF2 = *(h_tdf + 1); } if (inVariation == 0) inVariation = 100; if ((inCint == 0) || (inRinternal == 0)) { if (id == ILI9881_CHIP) { if ((type == ILI_N) || (type == ILI_O)) { inRinternal = 1915; inCint = 70; } } else if (id == ILI9882_CHIP) { if (type == ILI_N) { inRinternal = 1354; inCint = 70; } else if (type == ILI_H) { inRinternal = 1354; inCint = 69; } } else if (id == ILI7807_CHIP) { if (type == ILI_Q) { inRinternal = 1500; inCint = 70; } else if (type == ILI_S) { inRinternal = 1500; inCint = 66; inTVCH = inTVCH/10; inTVCL = inTVCL/10; } else if (type == ILI_V) { inRinternal = 1500; inCint = 70; } } } for (j = 0; j < core_mp.frame_len; j++) { if (Code[j] == 0) { input_err(true, ilits->dev, "%s code is invalid\n", __func__); } else { temp = ((inTVCH - inTVCL) * inVariation * (inTDF1 - inTDF2) * (1 << 12) / (9 * Code[j] * inCint)) * 1000; temp = (temp - inRinternal) / 1000; } ohm[j] = temp; } /* Unit = M Ohm */ return temp; } static int short_test(int index, int frame_index) { u32 pid = core_mp.chip_pid >> 8; int j = 0, ret = 0; u16 v_tdf[2] = {0}; u16 h_tdf[2] = {0}; char str[32] = {0}; v_tdf[0] = tItems[index].v_tdf_1; v_tdf[1] = tItems[index].v_tdf_2; h_tdf[0] = tItems[index].h_tdf_1; h_tdf[1] = tItems[index].h_tdf_2; parser_get_int_data("short test", "tvch", str, sizeof(str)); short_para.tvch = ili_katoi(str); parser_get_int_data("short test", "tvcl", str, sizeof(str)); short_para.tvcl = ili_katoi(str); parser_get_int_data("short test", "variation", str, sizeof(str)); short_para.variation = ili_katoi(str); parser_get_int_data("short test", "cint", str, sizeof(str)); short_para.cint = ili_katoi(str); parser_get_int_data("short test", "rinternal", str, sizeof(str)); short_para.rinternal = ili_katoi(str); /* 9881N, 9881O, 7807Q, 7807S not support cbk_step and cint read from mp.ini */ if ((pid != 0x988117) && (pid != 0x988118) && (pid != 0x78071A) && (pid != 0x78071C)) { if ((short_para.cint == 0) || (short_para.rinternal == 0)) { input_err(true, ilits->dev, "%s Failed to get short parameter", __func__); core_mp.lost_parameter = true; return -1; } } input_info(true, ilits->dev, "%s TVCH = %d, TVCL = %d, Variation = %d, V_TDF1 = %d, V_TDF2 = %d, H_TDF1 = %d, H_TDF2 = %d, Cint = %d, Rinternal = %d\n", __func__, short_para.tvch, short_para.tvcl, short_para.variation, tItems[index].v_tdf_1, tItems[index].v_tdf_2, tItems[index].h_tdf_1, tItems[index].h_tdf_2, short_para.cint, short_para.rinternal); if (core_mp.protocol_ver >= PROTOCOL_VER_540) { /* Calculate code to ohm and save to tItems[index].buf */ ili_dump_data(frame_buf, 10, core_mp.frame_len, core_mp.xch_len, "Short Raw 1"); codeToOhm(&tItems[index].buf[frame_index * core_mp.frame_len], frame_buf, v_tdf, h_tdf); ili_dump_data(&tItems[index].buf[frame_index * core_mp.frame_len], 10, core_mp.frame_len, core_mp.xch_len, "Short Ohm 1"); } else { for (j = 0; j < core_mp.frame_len; j++) tItems[index].buf[frame_index * core_mp.frame_len + j] = frame_buf[j]; } return ret; } static int allnode_key_cdc_data(int index) { int i, ret = 0, len = 0; int inDACp = 0, inDACn = 0; u8 cmd[3] = {0}; u8 *ori = NULL; len = core_mp.key_len * 2; ILI_DBG("%s Read key's length = %d\n", __func__, len); ILI_DBG("%s core_mp.key_len = %d\n", __func__, core_mp.key_len); if (len <= 0) { input_err(true, ilits->dev, "%s Length is invalid\n", __func__); ret = -1; goto out; } /* CDC init */ cmd[0] = P5_X_SET_CDC_INIT; cmd[1] = tItems[index].cmd; cmd[2] = 0; // /* Allocate a buffer for the original */ ori = kcalloc(len, sizeof(u8), GFP_KERNEL); if (ERR_ALLOC_MEM(ori)) { input_err(true, ilits->dev, "%s Failed to allocate ori mem (%ld)\n", __func__, PTR_ERR(ori)); ret = -1; goto out; } ret = ilits->wrapper(cmd, sizeof(cmd), ori, len, ON, ON); if (ret < 0) { input_err(true, ilits->dev, "%s fail to get cdc data\n", __func__); goto out; } ili_dump_data(ori, 8, len, 0, "Key CDC original"); if (key_buf == NULL) { key_buf = kcalloc(core_mp.key_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(key_buf)) { input_err(true, ilits->dev, "%s Failed to allocate FrameBuffer mem (%ld)\n", __func__, PTR_ERR(key_buf)); goto out; } } else { memset(key_buf, 0x0, core_mp.key_len); } /* Convert original data to the physical one in each node */ for (i = 0; i < core_mp.frame_len; i++) { if (tItems[index].cmd == CMD_KEY_DAC) { /* DAC - P */ if (((ori[(2 * i) + 1] & 0x80) >> 7) == 1) { /* Negative */ inDACp = 0 - (int)(ori[(2 * i) + 1] & 0x7F); } else { inDACp = ori[(2 * i) + 1] & 0x7F; } /* DAC - N */ if (((ori[(1 + (2 * i)) + 1] & 0x80) >> 7) == 1) { /* Negative */ inDACn = 0 - (int)(ori[(1 + (2 * i)) + 1] & 0x7F); } else { inDACn = ori[(1 + (2 * i)) + 1] & 0x7F; } key_buf[i] = (inDACp + inDACn) / 2; } } ili_dump_data(key_buf, 32, core_mp.frame_len, core_mp.xch_len, "Key CDC combined data"); out: ipio_kfree((void **)&ori); return ret; } static int mp_cdc_get_pv5_4_command(u8 *cmd, int len, int index) { int slen = 0; char str[128] = {0}; char *key = tItems[index].desp; if (core_mp.td_retry && (ipio_strcmp(key, "peak to peak_td (lcm off)") == 0)) key = "peak to peak_td (lcm off)_2"; slen = parser_get_int_data("pv5_4 command", key, str, sizeof(str)); if (slen < 0) return -1; if (parser_get_u8_array(str, cmd, 16, len) < 0) return -1; return 0; } static int mp_cdc_init_cmd_common(u8 *cmd, int len, int index) { int ret = 0; if (core_mp.protocol_ver >= PROTOCOL_VER_540) { core_mp.cdc_len = 15; return mp_cdc_get_pv5_4_command(cmd, len, index); } cmd[0] = P5_X_SET_CDC_INIT; cmd[1] = tItems[index].cmd; cmd[2] = 0; core_mp.cdc_len = 3; if (ipio_strcmp(tItems[index].desp, "open test(integration)") == 0) cmd[2] = 0x2; if (ipio_strcmp(tItems[index].desp, "open test(cap)") == 0) cmd[2] = 0x3; if (tItems[index].catalog == PEAK_TO_PEAK_TEST) { cmd[2] = ((tItems[index].frame_count & 0xff00) >> 8); cmd[3] = tItems[index].frame_count & 0xff; cmd[4] = 0; core_mp.cdc_len = 5; if (ipio_strcmp(tItems[index].desp, "noise peak to peak(cut panel)") == 0) cmd[4] = 0x1; ILI_DBG("%s P2P CMD: %d,%d,%d,%d,%d\n", __func__, cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]); } return ret; } static int allnode_open_cdc_data(int mode, int *buf) { int i = 0, ret = 0, len = 0; int inDACp = 0, inDACn = 0; u8 cmd[15] = {0}; u8 *ori = NULL; char str[128] = {0}; char *key[] = {"open dac", "open raw1", "open raw2", "open raw3", "open cap1 dac", "open cap1 raw"}; /* Multipling by 2 is due to the 16 bit in each node */ len = (core_mp.xch_len * core_mp.ych_len * 2) + 2; ILI_DBG("%s Read X/Y Channel length = %d, mode = %d\n", __func__, len, mode); if (len <= 2) { input_err(true, ilits->dev, "%s Length is invalid\n", __func__); ret = -EMP_INVAL; goto out; } /* CDC init. Read command from ini file */ if (parser_get_int_data("pv5_4 command", key[mode], str, sizeof(str)) < 0) { input_err(true, ilits->dev, "%s Failed to parse PV54 command, ret = %d\n", __func__, ret); ret = -EMP_PARSE; goto out; } parser_get_u8_array(str, cmd, 16, sizeof(cmd)); ili_dump_data(cmd, 8, sizeof(cmd), 0, "Open SP command"); /* Allocate a buffer for the original */ ori = kcalloc(len, sizeof(u8), GFP_KERNEL); if (ERR_ALLOC_MEM(ori)) { input_err(true, ilits->dev, "%s Failed to allocate ori, (%ld)\n", __func__, PTR_ERR(ori)); ret = -EMP_NOMEM; goto out; } /* Get original frame(cdc) data */ if (ilits->wrapper(cmd, core_mp.cdc_len, ori, len, ON, ON) < 0) { input_err(true, ilits->dev, "%s Failed to get cdc data\n", __func__); ret = -EMP_GET_CDC; goto out; } ili_dump_data(ori, 8, len, 0, "Open SP CDC original"); /* Convert original data to the physical one in each node */ for (i = 0; i < core_mp.frame_len; i++) { if ((mode == 0) || (mode == 4)) { /* DAC - P */ if (((ori[(2 * i) + 1] & 0x80) >> 7) == 1) { /* Negative */ inDACp = 0 - (int)(ori[(2 * i) + 1] & 0x7F); } else { inDACp = ori[(2 * i) + 1] & 0x7F; } /* DAC - N */ if (((ori[(1 + (2 * i)) + 1] & 0x80) >> 7) == 1) { /* Negative */ inDACn = 0 - (int)(ori[(1 + (2 * i)) + 1] & 0x7F); } else { inDACn = ori[(1 + (2 * i)) + 1] & 0x7F; } buf[i] = inDACp + inDACn; } else { /* H byte + L byte */ s32 tmp = (ori[(2 * i) + 1] << 8) + ori[(1 + (2 * i)) + 1]; if ((tmp & 0x8000) == 0x8000) buf[i] = tmp - 65536; else buf[i] = tmp; } } ili_dump_data(buf, 10, core_mp.frame_len, core_mp.xch_len, "Open SP CDC combined"); out: ipio_kfree((void **)&ori); return ret; } static int allnode_peak_to_peak_cdc_data(int index) { int i, k, ret = 0, len = 0, rd_frame_num = 1, cmd_len = 0; u8 cmd[15] = {0}; u8 *ori = NULL; /* Multipling by 2 is due to the 16 bit in each node */ len = (core_mp.frame_len * 2) + 2; ILI_DBG("%s Read X/Y Channel length = %d\n", __func__, len); if (len <= 2) { input_err(true, ilits->dev, "%s Length is invalid\n", __func__); ret = -EMP_INVAL; goto out; } memset(cmd, 0xFF, sizeof(cmd)); /* Allocate a buffer for the original */ ori = kcalloc(len, sizeof(u8), GFP_KERNEL); if (ERR_ALLOC_MEM(ori)) { input_err(true, ilits->dev, "%s Failed to allocate ori, (%ld)\n", __func__, PTR_ERR(ori)); ret = -EMP_NOMEM; goto out; } if (tItems[index].bch_mrk_multi) rd_frame_num = tItems[index].bch_mrk_frm_num - 1; if (frm_buf == NULL) { frm_buf = (s32 **)kzalloc(tItems[index].bch_mrk_frm_num * sizeof(s32 *), GFP_KERNEL); if (ERR_ALLOC_MEM(frm_buf)) { input_err(true, ilits->dev, "%s Failed to allocate frm_buf mem (%ld)\n", __func__, PTR_ERR(frm_buf)); ret = -EMP_NOMEM; goto out; } for (i = 0 ; i < tItems[index].bch_mrk_frm_num ; i++) { frm_buf[i] = (s32 *)kzalloc(core_mp.frame_len * sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(frm_buf)) { input_err(true, ilits->dev, "%s Failed to allocate frm_buf[%d] mem (%ld)\n", __func__, i, PTR_ERR(frm_buf)); ret = -EMP_NOMEM; goto out; } } } /* CDC init */ if (mp_cdc_init_cmd_common(cmd, sizeof(cmd), index) < 0) { input_err(true, ilits->dev, "%s Failed to get cdc command\n", __func__); ret = -EMP_CMD; goto out; } ili_dump_data(cmd, 8, core_mp.cdc_len, 0, "Mutual CDC command"); for (k = 0; k < rd_frame_num; k++) { if (k == 0) cmd_len = core_mp.cdc_len; else cmd_len = 0; memset(ori, 0, len); /* Get original frame(cdc) data */ if (ilits->wrapper(cmd, cmd_len, ori, len, ON, ON) < 0) { input_err(true, ilits->dev, "%s Failed to get cdc data\n", __func__); ret = -EMP_GET_CDC; goto out; } ili_dump_data(ori, 8, len, 0, "Mutual CDC original"); /* Convert original data to the physical one in each node */ for (i = 0; i < core_mp.frame_len; i++) { /* H byte + L byte */ s32 tmp = (ori[(2 * i) + 1] << 8) + ori[(1 + (2 * i)) + 1]; if ((tmp & 0x8000) == 0x8000) frm_buf[k][i] = tmp - 65536; else frm_buf[k][i] = tmp; // multiple case frame3 = frame1 - frame2 if (tItems[index].bch_mrk_multi && rd_frame_num == k + 1) frm_buf[k+1][i] = frm_buf[k-1][i] - frm_buf[k][i]; } } if (tItems[index].bch_mrk_multi) { ili_dump_data(frm_buf[0], 32, core_mp.frame_len, core_mp.xch_len, "Mutual CDC combined[0]/frame1"); ili_dump_data(frm_buf[1], 32, core_mp.frame_len, core_mp.xch_len, "Mutual CDC combined[1]/frame2"); ili_dump_data(frm_buf[2], 32, core_mp.frame_len, core_mp.xch_len, "Mutual CDC combined[2]/frame3"); } else { ili_dump_data(frm_buf[0], 32, core_mp.frame_len, core_mp.xch_len, "Mutual CDC combined[0]/frame1"); } out: ipio_kfree((void **)&ori); return ret; } static int allnode_mutual_cdc_data(int index) { int i, ret = 0, len = 0; int inDACp = 0, inDACn = 0; u8 cmd[15] = {0}; u8 *ori = NULL; /* Multipling by 2 is due to the 16 bit in each node */ len = (core_mp.frame_len * 2) + 2; ILI_DBG("%s Read X/Y Channel length = %d\n", __func__, len); if (len <= 2) { input_err(true, ilits->dev, "%s Length is invalid\n", __func__); ret = -EMP_INVAL; goto out; } memset(cmd, 0xFF, sizeof(cmd)); /* CDC init */ if (mp_cdc_init_cmd_common(cmd, sizeof(cmd), index) < 0) { input_err(true, ilits->dev, "%s Failed to get cdc command\n", __func__); ret = -EMP_CMD; goto out; } ili_dump_data(cmd, 8, core_mp.cdc_len, 0, "Mutual CDC command"); /* Allocate a buffer for the original */ ori = kcalloc(len, sizeof(u8), GFP_KERNEL); if (ERR_ALLOC_MEM(ori)) { input_err(true, ilits->dev, "%s Failed to allocate ori, (%ld)\n", __func__, PTR_ERR(ori)); ret = -EMP_NOMEM; goto out; } /* Get original frame(cdc) data */ if (ilits->wrapper(cmd, core_mp.cdc_len, ori, len, ON, ON) < 0) { input_err(true, ilits->dev, "%s Failed to get cdc data\n", __func__); ret = -EMP_GET_CDC; goto out; } ili_dump_data(ori, 8, len, 0, "Mutual CDC original"); if (frame_buf == NULL) { frame_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(frame_buf)) { input_err(true, ilits->dev, "%s Failed to allocate FrameBuffer mem (%ld)\n", __func__, PTR_ERR(frame_buf)); ret = -EMP_NOMEM; goto out; } } else { memset(frame_buf, 0x0, core_mp.frame_len); } /* Convert original data to the physical one in each node */ for (i = 0; i < core_mp.frame_len; i++) { if (ipio_strcmp(tItems[index].desp, "calibration data(dac)") == 0) { /* DAC - P */ if (((ori[(2 * i) + 1] & 0x80) >> 7) == 1) { /* Negative */ inDACp = 0 - (int)(ori[(2 * i) + 1] & 0x7F); } else { inDACp = ori[(2 * i) + 1] & 0x7F; } /* DAC - N */ if (((ori[(1 + (2 * i)) + 1] & 0x80) >> 7) == 1) { /* Negative */ inDACn = 0 - (int)(ori[(1 + (2 * i)) + 1] & 0x7F); } else { inDACn = ori[(1 + (2 * i)) + 1] & 0x7F; } frame_buf[i] = (inDACp + inDACn) / 2; } else { /* H byte + L byte */ s32 tmp = (ori[(2 * i) + 1] << 8) + ori[(1 + (2 * i)) + 1]; if ((tmp & 0x8000) == 0x8000) frame_buf[i] = tmp - 65536; else frame_buf[i] = tmp; if (ipio_strcmp(tItems[index].desp, "raw data(no bk)") == 0 || ipio_strcmp(tItems[index].desp, "raw data(no bk) (lcm off)") == 0) { frame_buf[i] -= core_mp.no_bk_shift; } } } ili_dump_data(frame_buf, 32, core_mp.frame_len, core_mp.xch_len, "Mutual CDC combined"); out: ipio_kfree((void **)&ori); return ret; } static void compare_MaxMin_result(int index, s32 *data) { int x, y; for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { int shift = y * core_mp.xch_len; if (tItems[index].catalog == UNTOUCH_P2P) return; else if (tItems[index].catalog == TX_RX_DELTA) { /* Tx max/min comparison */ if (core_mp.tx_delta_buf[shift + x] < data[shift + x]) core_mp.tx_max_buf[shift + x] = data[shift + x]; if (core_mp.tx_delta_buf[shift + x] > data[shift + x]) core_mp.tx_min_buf[shift + x] = data[shift + x]; /* Rx max/min comparison */ if (core_mp.rx_delta_buf[shift + x] < data[shift + x]) core_mp.rx_max_buf[shift + x] = data[shift + x]; if (core_mp.rx_delta_buf[shift + x] > data[shift + x]) core_mp.rx_min_buf[shift + x] = data[shift + x]; } else { if (tItems[index].max_buf[shift + x] < data[shift + x]) tItems[index].max_buf[shift + x] = data[shift + x]; if (tItems[index].min_buf[shift + x] > data[shift + x]) tItems[index].min_buf[shift + x] = data[shift + x]; } } } } static int create_mp_test_frame_buffer(int index, int frame_count) { int i; ILI_DBG("%s Create MP frame buffers (index = %d), count = %d\n", __func__, index, frame_count); if (tItems[index].catalog == TX_RX_DELTA) { if (core_mp.tx_delta_buf == NULL) { core_mp.tx_delta_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(core_mp.tx_delta_buf)) { input_err(true, ilits->dev, "%s Failed to allocate tx_delta_buf mem\n", __func__); ipio_kfree((void **)&core_mp.tx_delta_buf); return -ENOMEM; } } if (core_mp.rx_delta_buf == NULL) { core_mp.rx_delta_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(core_mp.rx_delta_buf)) { input_err(true, ilits->dev, "%s Failed to allocate rx_delta_buf mem\n", __func__); ipio_kfree((void **)&core_mp.rx_delta_buf); return -ENOMEM; } } if (core_mp.tx_max_buf == NULL) { core_mp.tx_max_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(core_mp.tx_max_buf)) { input_err(true, ilits->dev, "%s Failed to allocate tx_max_buf mem\n", __func__); ipio_kfree((void **)&core_mp.tx_max_buf); return -ENOMEM; } } if (core_mp.tx_min_buf == NULL) { core_mp.tx_min_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(core_mp.tx_min_buf)) { input_err(true, ilits->dev, "%s Failed to allocate tx_min_buf mem\n", __func__); ipio_kfree((void **)&core_mp.tx_min_buf); return -ENOMEM; } } if (core_mp.rx_max_buf == NULL) { core_mp.rx_max_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(core_mp.rx_max_buf)) { input_err(true, ilits->dev, "%s Failed to allocate rx_max_buf mem\n", __func__); ipio_kfree((void **)&core_mp.rx_max_buf); return -ENOMEM; } } if (core_mp.rx_min_buf == NULL) { core_mp.rx_min_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(core_mp.rx_min_buf)) { input_err(true, ilits->dev, "%s Failed to allocate rx_min_buf mem\n", __func__); ipio_kfree((void **)&core_mp.rx_min_buf); return -ENOMEM; } } } else { if (tItems[index].buf == NULL) { tItems[index].buf = vmalloc(frame_count * core_mp.frame_len * sizeof(s32)); if (ERR_ALLOC_MEM(tItems[index].buf)) { input_err(true, ilits->dev, "%s Failed to allocate buf mem\n", __func__); ipio_kfree((void **)&tItems[index].buf); return -ENOMEM; } } if (tItems[index].result_buf == NULL) { tItems[index].result_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].result_buf)) { input_err(true, ilits->dev, "%s Failed to allocate result_buf mem\n", __func__); ipio_kfree((void **)&tItems[index].result_buf); return -ENOMEM; } } if (tItems[index].max_buf == NULL) { tItems[index].max_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].max_buf)) { input_err(true, ilits->dev, "%s Failed to allocate max_buf mem\n", __func__); ipio_kfree((void **)&tItems[index].max_buf); return -ENOMEM; } } if (tItems[index].min_buf == NULL) { tItems[index].min_buf = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].min_buf)) { input_err(true, ilits->dev, "%s Failed to allocate min_buf mem\n", __func__); ipio_kfree((void **)&tItems[index].min_buf); return -ENOMEM; } } if (tItems[index].spec_option == BENCHMARK) { if (tItems[index].bch_mrk_max == NULL) { tItems[index].bch_mrk_max = (s32 **)kzalloc(tItems[index].bch_mrk_frm_num * sizeof(s32 *), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].bch_mrk_max)) { input_err(true, ilits->dev, "%s Failed to allocate bch_mrk_max mem\n", __func__); ipio_kfree((void **)&tItems[index].bch_mrk_max); return -ENOMEM; } for (i = 0; i < tItems[index].bch_mrk_frm_num; i++) { tItems[index].bch_mrk_max[i] = (s32 *)kzalloc(core_mp.frame_len * sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].bch_mrk_max[i])) { input_err(true, ilits->dev, "%s Failed to allocate bch_mrk_max[%d] mem\n", __func__, i); ipio_kfree((void **)&tItems[index].bch_mrk_max[i]); return -ENOMEM; } } } if (tItems[index].bch_mrk_min == NULL) { tItems[index].bch_mrk_min = (s32 **)kzalloc(tItems[index].bch_mrk_frm_num * sizeof(s32 *), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].bch_mrk_min)) { input_err(true, ilits->dev, "%s Failed to allocate bch_mrk_min mem\n", __func__); ipio_kfree((void **)&tItems[index].bch_mrk_min); return -ENOMEM; } for (i = 0; i < tItems[index].bch_mrk_frm_num; i++) { tItems[index].bch_mrk_min[i] = (s32 *)kzalloc(core_mp.frame_len * sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].bch_mrk_min[i])) { input_err(true, ilits->dev, "%s Failed to allocate bch_mrk_min[%d] mem\n", __func__, i); ipio_kfree((void **)&tItems[index].bch_mrk_min[i]); return -ENOMEM; } } } if (tItems[index].bench_mark_max == NULL) { tItems[index].bench_mark_max = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].bench_mark_max)) { input_err(true, ilits->dev, "%s Failed to allocate bench_mark_max mem\n", __func__); ipio_kfree((void **)&tItems[index].bench_mark_max); return -ENOMEM; } } if (tItems[index].bench_mark_min == NULL) { tItems[index].bench_mark_min = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].bench_mark_min)) { input_err(true, ilits->dev, "%s Failed to allocate bench_mark_min mem\n", __func__); ipio_kfree((void **)&tItems[index].bench_mark_min); return -ENOMEM; } } } } return 0; } static int pin_test(int index) { int ret = 0; u8 cmd[5] = {0}; input_info(true, ilits->dev, "%s PIN test start", __func__); input_info(true, ilits->dev, "%s test_int_pin = 0x%x\n", __func__, tItems[index].test_int_pin); input_info(true, ilits->dev, "%s int_pulse_test = 0x%x\n", __func__, tItems[index].int_pulse_test); input_info(true, ilits->dev, "%s delay_time = 0x%x\n", __func__, tItems[index].delay_time); if (tItems[index].test_int_pin == ENABLE) { /* test HIGH level*/ cmd[0] = tItems[index].cmd; cmd[1] = 0x1; ret = ilits->wrapper(cmd, 2, NULL, 0, OFF, OFF); if (ret < 0) { input_err(true, ilits->dev, "%s Write command failed\n", __func__); ret = -EMP_CMD; goto out; } ret = ilits->detect_int_stat(false); if (ret < 0) { ret = -EMP_INT; goto out; } /* test LOW level*/ cmd[1] = 0x0; ret = ilits->wrapper(cmd, 2, NULL, 0, OFF, OFF); if (ret < 0) { input_err(true, ilits->dev, "%s Write command failed\n", __func__); ret = -EMP_CMD; goto out; } ret = ilits->detect_int_stat(false); if (ret < 0) { ret = -EMP_INT; goto out; } } if (tItems[index].int_pulse_test == ENABLE) { input_info(true, ilits->dev, "%s MP IRQ Rising Trigger Test\n", __func__); cmd[1] = 0x2; cmd[2] = tItems[index].delay_time; ili_irq_unregister(); ret = ili_irq_register(IRQF_TRIGGER_RISING); if (ret < 0) { ret = -EMP_INT; goto out; } atomic_set(&ilits->cmd_int_check, ENABLE); ret = ilits->wrapper(cmd, 3, NULL, 0, OFF, OFF); if (ret < 0) { input_err(true, ilits->dev, "%s Write command failed\n", __func__); ret = -EMP_CMD; goto out; } ret = ilits->detect_int_stat(false); if (ret < 0) { ret = -EMP_INT; goto out; } input_info(true, ilits->dev, "%s MP IRQ Falling Trigger Test\n", __func__); ili_irq_unregister(); ret = ili_irq_register(IRQF_TRIGGER_FALLING); if (ret < 0) { ret = -EMP_INT; goto out; } atomic_set(&ilits->cmd_int_check, ENABLE); ret = ilits->wrapper(cmd, 3, NULL, 0, OFF, OFF); if (ret < 0) { input_err(true, ilits->dev, "%s Write command failed\n", __func__); ret = -EMP_CMD; goto out; } ret = ilits->detect_int_stat(false); if (ret < 0) { ret = -EMP_INT; goto out; } } tItems[index].item_result = MP_DATA_PASS; out: if (ret < 0) tItems[index].item_result = MP_DATA_FAIL; input_info(true, ilits->dev, "%s Change to defualt IRQ trigger type\n", __func__); ili_irq_unregister(); ili_irq_register(ilits->irq_tirgger_type); atomic_set(&ilits->cmd_int_check, DISABLE); return ret; } static int mutual_test(int index) { int i = 0, j = 0, x = 0, y = 0, ret = 0, get_frame_cont = 1; ILI_DBG("%s index = %d, desp = %s, Frame Count = %d\n", __func__, index, tItems[index].desp, tItems[index].frame_count); /* * We assume that users who are calling the test forget to config frame count * as 1, so we just help them to set it up. */ if (tItems[index].frame_count <= 0) { input_err(true, ilits->dev, "%s Frame count is zero, which is at least set as 1\n", __func__); tItems[index].frame_count = 1; } ret = create_mp_test_frame_buffer(index, tItems[index].frame_count); if (ret < 0) { ret = -EMP_NOMEM; goto out; } /* Init Max/Min buffer */ for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { if (tItems[i].catalog == TX_RX_DELTA) { core_mp.tx_max_buf[y * core_mp.xch_len + x] = INT_MIN; core_mp.rx_max_buf[y * core_mp.xch_len + x] = INT_MIN; core_mp.tx_min_buf[y * core_mp.xch_len + x] = INT_MAX; core_mp.rx_min_buf[y * core_mp.xch_len + x] = INT_MAX; } else { tItems[index].max_buf[y * core_mp.xch_len + x] = INT_MIN; tItems[index].min_buf[y * core_mp.xch_len + x] = INT_MAX; } } } if (tItems[index].catalog != PEAK_TO_PEAK_TEST) get_frame_cont = tItems[index].frame_count; if (tItems[index].spec_option == BENCHMARK) { parser_ini_benchmark(tItems[index].bench_mark_max, tItems[index].bench_mark_min, tItems[index].type_option, tItems[index].desp, core_mp.frame_len, BENCHMARK_KEY_NAME); dump_benchmark_data(tItems[index].bench_mark_max, tItems[index].bench_mark_min); } for (i = 0; i < get_frame_cont; i++) { ret = allnode_mutual_cdc_data(index); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to initialise CDC data, %d\n", __func__, ret); goto out; } switch (tItems[index].catalog) { case PIXEL: run_pixel_test(index); break; case UNTOUCH_P2P: run_untouch_p2p_test(index); break; case OPEN_TEST: run_open_test(index); break; case TX_RX_DELTA: run_tx_rx_delta_test(index); break; case SHORT_TEST: ret = short_test(index, i); if (ret < 0) { ret = -EMP_PARA_NULL; goto out; } break; default: for (j = 0; j < core_mp.frame_len; j++) tItems[index].buf[i * core_mp.frame_len + j] = frame_buf[j]; break; } compare_MaxMin_result(index, &tItems[index].buf[i * core_mp.frame_len]); } out: return ret; } static int peak_to_peak_test(int index) { int i = 0, j = 0, x = 0, y = 0, ret = 0; char benchmark_str[128] = {0}; ILI_DBG("%s index = %d, desp = %s bch_mrk_frm_num = %d\n", __func__, index, tItems[index].desp, tItems[index].bch_mrk_frm_num); ret = create_mp_test_frame_buffer(index, tItems[index].bch_mrk_frm_num); if (ret < 0) { ret = -EMP_NOMEM; goto out; } if (tItems[index].spec_option == BENCHMARK) { for (i = 0 ; i < tItems[index].bch_mrk_frm_num ; i++) { if (tItems[index].bch_mrk_multi) snprintf(benchmark_str, sizeof(benchmark_str), "%s%d", BENCHMARK_KEY_NAME, i+1); else snprintf(benchmark_str, sizeof(benchmark_str), "%s", BENCHMARK_KEY_NAME); parser_ini_benchmark(tItems[index].bch_mrk_max[i], tItems[index].bch_mrk_min[i], tItems[index].type_option, tItems[index].desp, core_mp.frame_len, benchmark_str); dump_benchmark_data(tItems[index].bch_mrk_max[i], tItems[index].bch_mrk_min[i]); } } /* Init Max/Min buffer */ for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { tItems[index].max_buf[y * core_mp.xch_len + x] = INT_MIN; tItems[index].min_buf[y * core_mp.xch_len + x] = INT_MAX; } } ret = allnode_peak_to_peak_cdc_data(index); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to initialise CDC data, %d\n", __func__, ret); goto out; } for (i = 0; i < tItems[index].bch_mrk_frm_num; i++) { for (j = 0; j < core_mp.frame_len; j++) tItems[index].buf[i * core_mp.frame_len + j] = frm_buf[i][j]; compare_MaxMin_result(index, &tItems[index].buf[i * core_mp.frame_len]); } out: return ret; } static int open_test_sp(int index) { struct mp_test_P540_open *open; int i = 0, x = 0, y = 0, ret = 0, addr = 0; int Charge_AA = 0, Charge_Border = 0, Charge_Notch = 0, full_open_rate = 0; char str[512] = {0}; ILI_DBG("%s index = %d, desp = %s, Frame Count = %d\n", __func__, index, tItems[index].desp, tItems[index].frame_count); /* * We assume that users who are calling the test forget to config frame count * as 1, so we just help them to set it up. */ if (tItems[index].frame_count <= 0) { input_err(true, ilits->dev, "%s Frame count is zero, which is at least set as 1\n", __func__); tItems[index].frame_count = 1; } open = kzalloc(tItems[index].frame_count * sizeof(struct mp_test_P540_open), GFP_KERNEL); if (ERR_ALLOC_MEM(open)) { input_err(true, ilits->dev, "%s Failed to allocate open mem (%ld)\n", __func__, PTR_ERR(open)); ret = -EMP_NOMEM; goto out; } ret = create_mp_test_frame_buffer(index, tItems[index].frame_count); if (ret < 0) { ret = -EMP_NOMEM; goto out; } if (frame1_cbk700 == NULL) { frame1_cbk700 = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(frame1_cbk700)) { input_err(true, ilits->dev, "%s Failed to allocate frame1_cbk700 buffer\n", __func__); return -EMP_NOMEM; } } else { memset(frame1_cbk700, 0x0, core_mp.frame_len); } if (frame1_cbk250 == NULL) { frame1_cbk250 = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(frame1_cbk250)) { input_err(true, ilits->dev, "%s Failed to allocate frame1_cbk250 buffer\n", __func__); ipio_kfree((void **)&frame1_cbk700); return -EMP_NOMEM; } } else { memset(frame1_cbk250, 0x0, core_mp.frame_len); } if (frame1_cbk200 == NULL) { frame1_cbk200 = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(frame1_cbk200)) { input_err(true, ilits->dev, "%s Failed to allocate cbk buffer\n", __func__); ipio_kfree((void **)&frame1_cbk700); ipio_kfree((void **)&frame1_cbk250); return -EMP_NOMEM; } } else { memset(frame1_cbk200, 0x0, core_mp.frame_len); } tItems[index].node_type = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(tItems[index].node_type)) { input_err(true, ilits->dev, "%s Failed to allocate node_type FRAME buffer\n", __func__); return -EMP_NOMEM; } /* Init Max/Min buffer */ for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { tItems[index].max_buf[y * core_mp.xch_len + x] = INT_MIN; tItems[index].min_buf[y * core_mp.xch_len + x] = INT_MAX; } } if (tItems[index].spec_option == BENCHMARK) { parser_ini_benchmark(tItems[index].bench_mark_max, tItems[index].bench_mark_min, tItems[index].type_option, tItems[index].desp, core_mp.frame_len, BENCHMARK_KEY_NAME); dump_benchmark_data(tItems[index].bench_mark_max, tItems[index].bench_mark_min); } parser_ini_nodetype(tItems[index].node_type, NODE_TYPE_KEY_NAME, core_mp.frame_len); dump_node_type_buffer(tItems[index].node_type, "node type"); parser_get_int_data(tItems[index].desp, "charge_aa", str, sizeof(str)); Charge_AA = ili_katoi(str); parser_get_int_data(tItems[index].desp, "charge_border", str, sizeof(str)); Charge_Border = ili_katoi(str); parser_get_int_data(tItems[index].desp, "charge_notch", str, sizeof(str)); Charge_Notch = ili_katoi(str); parser_get_int_data(tItems[index].desp, "full open", str, sizeof(str)); full_open_rate = ili_katoi(str); parser_get_int_data(tItems[index].desp, "tvch", str, sizeof(str)); open_para.tvch = ili_katoi(str); parser_get_int_data(tItems[index].desp, "tvcl", str, sizeof(str)); open_para.tvcl = ili_katoi(str); ILI_DBG("%s AA = %d, Border = %d, Notch = %d, full_open_rate = %d, tvch = %d, tvcl = %d\n", __func__, Charge_AA, Charge_Border, Charge_Notch, full_open_rate, open_para.tvch, open_para.tvcl); for (i = 0; i < tItems[index].frame_count; i++) { open[i].tdf_700 = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].tdf_250 = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].tdf_200 = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].cbk_700 = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].cbk_250 = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].cbk_200 = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].charg_rate = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].full_Open = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].dac = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); } for (i = 0; i < tItems[index].frame_count; i++) { ret = allnode_open_cdc_data(0, open[i].dac); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to get Open SP DAC data, %d\n", __func__, ret); goto out; } ret = allnode_open_cdc_data(1, open[i].tdf_700); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to get Open SP Raw1 data, %d\n", __func__, ret); goto out; } ret = allnode_open_cdc_data(2, open[i].tdf_250); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to get Open SP Raw2 data, %d\n", __func__, ret); goto out; } ret = allnode_open_cdc_data(3, open[i].tdf_200); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to get Open SP Raw3 data, %d\n", __func__, ret); goto out; } allnode_open_cdc_result(index, open[i].cbk_700, open[i].dac, open[i].tdf_700); allnode_open_cdc_result(index, open[i].cbk_250, open[i].dac, open[i].tdf_250); allnode_open_cdc_result(index, open[i].cbk_200, open[i].dac, open[i].tdf_200); addr = 0; /* record fist frame for debug */ if (i == 0) { ipio_memcpy(frame1_cbk700, open[i].cbk_700, core_mp.frame_len * sizeof(s32), core_mp.frame_len * sizeof(s32)); ipio_memcpy(frame1_cbk250, open[i].cbk_250, core_mp.frame_len * sizeof(s32), core_mp.frame_len * sizeof(s32)); ipio_memcpy(frame1_cbk200, open[i].cbk_200, core_mp.frame_len * sizeof(s32), core_mp.frame_len * sizeof(s32)); } ili_dump_data(open[i].cbk_700, 10, core_mp.frame_len, core_mp.xch_len, "cbk 700"); ili_dump_data(open[i].cbk_250, 10, core_mp.frame_len, core_mp.xch_len, "cbk 250"); ili_dump_data(open[i].cbk_200, 10, core_mp.frame_len, core_mp.xch_len, "cbk 200"); for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { open[i].charg_rate[addr] = open[i].cbk_250[addr] * 100 / open[i].cbk_700[addr]; open[i].full_Open[addr] = open[i].cbk_700[addr] - open[i].cbk_200[addr]; addr++; } } ili_dump_data(open[i].charg_rate, 10, core_mp.frame_len, core_mp.xch_len, "origin charge rate"); ili_dump_data(open[i].full_Open, 10, core_mp.frame_len, core_mp.xch_len, "origin full open"); addr = 0; for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { if (full_open_rate_compare(open[i].full_Open, open[i].cbk_700, x, y, tItems[index].node_type[addr], full_open_rate) == false) { tItems[index].buf[(i * core_mp.frame_len) + addr] = 0; open[i].charg_rate[addr] = 0; } addr++; } } ili_dump_data(&tItems[index].buf[(i * core_mp.frame_len)], 10, core_mp.frame_len, core_mp.xch_len, "after full_open_rate_compare"); addr = 0; for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { tItems[index].buf[(i * core_mp.frame_len) + addr] = compare_charge(open[i].charg_rate, x, y, tItems[index].node_type, Charge_AA, Charge_Border, Charge_Notch); addr++; } } ili_dump_data(&tItems[index].buf[(i * core_mp.frame_len)], 10, core_mp.frame_len, core_mp.xch_len, "after compare charge rate"); compare_MaxMin_result(index, &tItems[index].buf[(i * core_mp.frame_len)]); } out: ipio_kfree((void **)&tItems[index].node_type); if (open != NULL) { for (i = 0; i < tItems[index].frame_count; i++) { ipio_kfree((void **)&open[i].tdf_700); ipio_kfree((void **)&open[i].tdf_250); ipio_kfree((void **)&open[i].tdf_200); ipio_kfree((void **)&open[i].cbk_700); ipio_kfree((void **)&open[i].cbk_250); ipio_kfree((void **)&open[i].cbk_200); ipio_kfree((void **)&open[i].charg_rate); ipio_kfree((void **)&open[i].full_Open); ipio_kfree((void **)&open[i].dac); } kfree(open); open = NULL; } return ret; } static int open_test_cap(int index) { u32 pid = core_mp.chip_pid >> 8; struct mp_test_open_c *open; int i = 0, x = 0, y = 0, ret = 0, addr = 0; char str[512] = {0}; ILI_DBG("%s index = %d, desp = %s, Frame Count = %d\n", __func__, index, tItems[index].desp, tItems[index].frame_count); if (tItems[index].frame_count <= 0) { input_err(true, ilits->dev, "%s Frame count is zero, which is at least set as 1\n", __func__); tItems[index].frame_count = 1; } open = kzalloc(tItems[index].frame_count * sizeof(struct mp_test_open_c), GFP_KERNEL); if (ERR_ALLOC_MEM(open)) { input_err(true, ilits->dev, "%s Failed to allocate open mem (%ld)\n", __func__, PTR_ERR(open)); ret = -EMP_NOMEM; goto out; } if (create_mp_test_frame_buffer(index, tItems[index].frame_count) < 0) { ret = -EMP_NOMEM; goto out; } if (cap_dac == NULL) { cap_dac = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(cap_dac)) { input_err(true, ilits->dev, "%s Failed to allocate cap_dac buffer\n", __func__); return -EMP_NOMEM; } } else { memset(cap_dac, 0x0, core_mp.frame_len); } if (cap_raw == NULL) { cap_raw = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(cap_raw)) { input_err(true, ilits->dev, "%s Failed to allocate cap_raw buffer\n", __func__); ipio_kfree((void **)&cap_dac); return -EMP_NOMEM; } } else { memset(cap_raw, 0x0, core_mp.frame_len); } /* Init Max/Min buffer */ for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { tItems[index].max_buf[y * core_mp.xch_len + x] = INT_MIN; tItems[index].min_buf[y * core_mp.xch_len + x] = INT_MAX; } } if (tItems[index].spec_option == BENCHMARK) { parser_ini_benchmark(tItems[index].bench_mark_max, tItems[index].bench_mark_min, tItems[index].type_option, tItems[index].desp, core_mp.frame_len, BENCHMARK_KEY_NAME); dump_benchmark_data(tItems[index].bench_mark_max, tItems[index].bench_mark_min); } parser_get_int_data(tItems[index].desp, "gain", str, sizeof(str)); open_para.gain = ili_katoi(str); parser_get_int_data(tItems[index].desp, "tvch", str, sizeof(str)); open_para.tvch = ili_katoi(str); parser_get_int_data(tItems[index].desp, "tvcl", str, sizeof(str)); open_para.tvcl = ili_katoi(str); parser_get_int_data(tItems[index].desp, "cbk_step", str, sizeof(str)); open_para.cbk_step = ili_katoi(str); parser_get_int_data(tItems[index].desp, "cint", str, sizeof(str)); open_para.cint = ili_katoi(str); /* 9881N, 9881O, 7807Q, 7807S not support cbk_step and cint read from mp.ini */ if ((pid != 0x988117) && (pid != 0x988118) && (pid != 0x78071A) && (pid != 0x78071C)) { if ((open_para.cbk_step == 0) || (open_para.cint == 0)) { input_err(true, ilits->dev, "%s Failed to get open parameter", __func__); ret = -EMP_PARA_NULL; core_mp.lost_parameter = true; goto out; } } input_info(true, ilits->dev, "%s gain = %d, tvch = %d, tvcl = %d, cbk_step = %d, cint = %d\n", __func__, open_para.gain, open_para.tvch, open_para.tvcl, open_para.cbk_step, open_para.cint); for (i = 0; i < tItems[index].frame_count; i++) { open[i].cap_dac = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].cap_raw = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); open[i].dcl_cap = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); } for (i = 0; i < tItems[index].frame_count; i++) { ret = allnode_open_cdc_data(4, open[i].cap_dac); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to get Open CAP DAC data, %d\n", __func__, ret); goto out; } ret = allnode_open_cdc_data(5, open[i].cap_raw); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to get Open CAP RAW data, %d\n", __func__, ret); goto out; } allnode_open_cdc_result(index, open[i].dcl_cap, open[i].cap_dac, open[i].cap_raw); /* record fist frame for debug */ if (i == 0) { ipio_memcpy(cap_dac, open[i].cap_dac, core_mp.frame_len * sizeof(s32), core_mp.frame_len * sizeof(s32)); ipio_memcpy(cap_raw, open[i].cap_raw, core_mp.frame_len * sizeof(s32), core_mp.frame_len * sizeof(s32)); } ili_dump_data(open[i].dcl_cap, 10, core_mp.frame_len, core_mp.xch_len, "DCL_Cap"); addr = 0; for (y = 0; y < core_mp.ych_len; y++) { for (x = 0; x < core_mp.xch_len; x++) { tItems[index].buf[(i * core_mp.frame_len) + addr] = open[i].dcl_cap[addr]; addr++; } } compare_MaxMin_result(index, &tItems[index].buf[i * core_mp.frame_len]); } out: if (open != NULL) { for (i = 0; i < tItems[index].frame_count; i++) { ipio_kfree((void **)&open[i].cap_dac); ipio_kfree((void **)&open[i].cap_raw); ipio_kfree((void **)&open[i].dcl_cap); } kfree(open); open = NULL; } return ret; } static int key_test(int index) { int i, j = 0, ret = 0; ILI_DBG("%s Item = %s, Frame Count = %d\n", __func__, tItems[index].desp, tItems[index].frame_count); if (tItems[index].frame_count == 0) { input_err(true, ilits->dev, "%s Frame count is zero, which at least sets as 1\n", __func__); ret = -EINVAL; goto out; } ret = create_mp_test_frame_buffer(index, tItems[index].frame_count); if (ret < 0) goto out; for (i = 0; i < tItems[index].frame_count; i++) { ret = allnode_key_cdc_data(index); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to initialise CDC data, %d\n", __func__, ret); goto out; } for (j = 0; j < core_mp.key_len; j++) tItems[index].buf[j] = key_buf[j]; } compare_MaxMin_result(index, tItems[index].buf); out: return ret; } static int self_test(int index) { input_err(true, ilits->dev, "%s TDDI has no self to be tested currently\n", __func__); return -1; } static int st_test(int index) { input_err(true, ilits->dev, "%s ST Test is not supported by the driver\n", __func__); return -1; } static int mp_get_timing_info(void) { int slen = 0; char str[256] = {0}; u8 info[64] = {0}; char *key = "timing_info_raw"; core_mp.isLongV = 0; slen = parser_get_int_data("pv5_4 command", key, str, sizeof(str)); if (slen < 0) return -1; if (parser_get_u8_array(str, info, 16, slen) < 0) return -1; core_mp.isLongV = info[6]; input_info(true, ilits->dev, "%s DDI Mode = %s\n", __func__, (core_mp.isLongV ? "Long V" : "Long H")); return 0; } static int mp_test_data_sort_average(s32 *oringin_data, int index, s32 *avg_result) { int i, j, k, x, y, len = 5, size; s32 u32temp; int u32up_frame, u32down_frame; s32 *u32sum_raw_data = NULL; s32 *u32data_buff = NULL; int ret = 0; if (tItems[index].frame_count <= 1) { ret = 0; goto out; } if (ERR_ALLOC_MEM(oringin_data)) { input_err(true, ilits->dev, "%s Input wrong address\n", __func__); ret = -ENOMEM; goto out; } u32data_buff = kcalloc(core_mp.frame_len * tItems[index].frame_count, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(u32data_buff)) { input_err(true, ilits->dev, "%s Failed to allocate u32data_buff FRAME buffer\n", __func__); ret = -ENOMEM; goto out; } u32sum_raw_data = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(u32data_buff)) { input_err(true, ilits->dev, "%s Failed to allocate u32sum_raw_data FRAME buffer\n", __func__); ret = -ENOMEM; goto out; } size = core_mp.frame_len * tItems[index].frame_count; for (i = 0; i < size; i++) u32data_buff[i] = oringin_data[i]; u32up_frame = tItems[index].frame_count * tItems[index].highest_percentage / 100; u32down_frame = tItems[index].frame_count * tItems[index].lowest_percentage / 100; ILI_DBG("%s Up=%d, Down=%d -%s\n", __func__, u32up_frame, u32down_frame, tItems[index].desp); if (debug_en) { pr_cont("\n[Show Original frist%d and last%d node data]\n", len, len); for (i = 0; i < core_mp.frame_len; i++) { for (j = 0 ; j < tItems[index].frame_count ; j++) { if ((i < len) || (i >= (core_mp.frame_len-len))) pr_cont("%d,", u32data_buff[j * core_mp.frame_len + i]); } if ((i < len) || (i >= (core_mp.frame_len-len))) pr_cont("\n"); } } for (i = 0; i < core_mp.frame_len; i++) { for (j = 0; j < tItems[index].frame_count-1; j++) { for (k = 0; k < (tItems[index].frame_count-1-j); k++) { x = i+k*core_mp.frame_len; y = i+(k+1)*core_mp.frame_len; if (*(u32data_buff+x) > *(u32data_buff+y)) { u32temp = *(u32data_buff+x); *(u32data_buff+x) = *(u32data_buff+y); *(u32data_buff+y) = u32temp; } } } } if (debug_en) { pr_cont("\n[After sorting frist%d and last%d node data]\n", len, len); for (i = 0; i < core_mp.frame_len; i++) { for (j = u32down_frame; j < tItems[index].frame_count - u32up_frame; j++) { if ((i < len) || (i >= (core_mp.frame_len - len))) pr_cont("%d,", u32data_buff[i + j * core_mp.frame_len]); } if ((i < len) || (i >= (core_mp.frame_len-len))) pr_cont("\n"); } } for (i = 0 ; i < core_mp.frame_len ; i++) { u32sum_raw_data[i] = 0; for (j = u32down_frame; j < tItems[index].frame_count - u32up_frame; j++) u32sum_raw_data[i] += u32data_buff[i + j * core_mp.frame_len]; avg_result[i] = u32sum_raw_data[i] / (tItems[index].frame_count - u32down_frame - u32up_frame); } if (debug_en) { pr_cont("\n[Average result frist%d and last%d node data]\n", len, len); for (i = 0; i < core_mp.frame_len; i++) { if ((i < len) || (i >= (core_mp.frame_len-len))) pr_cont("%d,", avg_result[i]); } if ((i < len) || (i >= (core_mp.frame_len-len))) pr_cont("\n"); } out: ipio_kfree((void **)&u32data_buff); ipio_kfree((void **)&u32sum_raw_data); return ret; } static void mp_compare_cdc_result(int index, s32 *tmp, s32 *max_ts, s32 *min_ts, int *result) { int i; if (ERR_ALLOC_MEM(tmp)) { input_err(true, ilits->dev, "%s The data of test item is null (%p)\n", __func__, tmp); *result = MP_DATA_FAIL; return; } if (tItems[index].catalog == SHORT_TEST) { for (i = 0; i < core_mp.frame_len; i++) { if (tmp[i] < min_ts[i]) { *result = MP_DATA_FAIL; return; } } } else { for (i = 0; i < core_mp.frame_len; i++) { if (tmp[i] > max_ts[i] || tmp[i] < min_ts[i]) { ILI_DBG("%s Fail No.%d: max=%d, val=%d, min=%d\n", __func__, i, max_ts[i], tmp[i], min_ts[i]); *result = MP_DATA_FAIL; return; } } } } static int mp_compare_test_result(int index) { int i, test_result = MP_DATA_PASS; s32 *max_threshold = NULL, *min_threshold = NULL; if (tItems[index].catalog == PIN_TEST) return tItems[index].item_result; max_threshold = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(max_threshold)) { input_err(true, ilits->dev, "%s Failed to allocate threshold FRAME buffer\n", __func__); test_result = MP_DATA_FAIL; goto out; } min_threshold = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(min_threshold)) { input_err(true, ilits->dev, "%s Failed to allocate threshold FRAME buffer\n", __func__); test_result = MP_DATA_FAIL; goto out; } /* Show test result as below */ if (tItems[index].catalog == TX_RX_DELTA) { if (ERR_ALLOC_MEM(core_mp.rx_delta_buf) || ERR_ALLOC_MEM(core_mp.tx_delta_buf)) { input_err(true, ilits->dev, "%s This test item (%s) has no data inside its buffer\n", __func__, tItems[index].desp); test_result = MP_DATA_FAIL; goto out; } for (i = 0; i < core_mp.frame_len; i++) { max_threshold[i] = core_mp.TxDeltaMax; min_threshold[i] = core_mp.TxDeltaMin; } mp_compare_cdc_result(index, core_mp.tx_max_buf, max_threshold, min_threshold, &test_result); mp_compare_cdc_result(index, core_mp.tx_min_buf, max_threshold, min_threshold, &test_result); for (i = 0; i < core_mp.frame_len; i++) { max_threshold[i] = core_mp.RxDeltaMax; min_threshold[i] = core_mp.RxDeltaMin; } mp_compare_cdc_result(index, core_mp.rx_max_buf, max_threshold, min_threshold, &test_result); mp_compare_cdc_result(index, core_mp.rx_min_buf, max_threshold, min_threshold, &test_result); } else { if (ERR_ALLOC_MEM(tItems[index].buf) || ERR_ALLOC_MEM(tItems[index].max_buf) || ERR_ALLOC_MEM(tItems[index].min_buf) || ERR_ALLOC_MEM(tItems[index].result_buf)) { input_err(true, ilits->dev, "%s This test item (%s) has no data inside its buffer\n", __func__, tItems[index].desp); test_result = MP_DATA_FAIL; goto out; } if (tItems[index].spec_option == BENCHMARK) { if (tItems[index].catalog == PEAK_TO_PEAK_TEST) { for (i = 0; i < core_mp.frame_len; i++) { max_threshold[i] = tItems[index].bch_mrk_max[0][i]; min_threshold[i] = tItems[index].bch_mrk_min[0][i]; } } else { for (i = 0; i < core_mp.frame_len; i++) { max_threshold[i] = tItems[index].bench_mark_max[i]; min_threshold[i] = tItems[index].bench_mark_min[i]; } } } else { for (i = 0; i < core_mp.frame_len; i++) { max_threshold[i] = tItems[index].max; min_threshold[i] = tItems[index].min; } } /* general result */ if (tItems[index].trimmed_mean && tItems[index].catalog != PEAK_TO_PEAK_TEST) { mp_test_data_sort_average(tItems[index].buf, index, tItems[index].result_buf); mp_compare_cdc_result(index, tItems[index].result_buf, max_threshold, min_threshold, &test_result); } else { if (tItems[index].bch_mrk_multi) { for (i = 0; i < tItems[index].bch_mrk_frm_num; i++) { mp_compare_cdc_result(index, frm_buf[i], tItems[index].bch_mrk_max[i], tItems[index].bch_mrk_min[i], &test_result); } } else { mp_compare_cdc_result(index, tItems[index].max_buf, max_threshold, min_threshold, &test_result); mp_compare_cdc_result(index, tItems[index].min_buf, max_threshold, min_threshold, &test_result); } } } out: ipio_kfree((void **)&max_threshold); ipio_kfree((void **)&min_threshold); if (frm_buf != NULL) { for (i = 0; i < tItems[index].bch_mrk_frm_num; i++) if (frm_buf[i] != NULL) { kfree(frm_buf[i]); frm_buf[i] = NULL; } kfree(frm_buf); frm_buf = NULL; } if (core_mp.all_pass == true) test_result = MP_DATA_PASS; tItems[index].item_result = test_result; return test_result; } static void mp_do_retry(int index, int count) { if (count == 0) { input_info(true, ilits->dev, "%s Finish retry action\n", __func__); return; } input_info(true, ilits->dev, "%s retry = %d, item = %s\n", __func__, count, tItems[index].desp); tItems[index].do_test(index); if (mp_compare_test_result(index) < 0) return mp_do_retry(index, count - 1); } static int mp_show_result(bool lcm_on) { int ret = MP_DATA_PASS, seq; int i, x, y, j, k = 0, csv_len = 0, pass_item_count = 0, line_count = 0, get_frame_cont = 1; s32 *max_threshold = NULL, *min_threshold = NULL; char *csv = NULL; char *ret_pass_name = NULL, *ret_fail_name = NULL; struct file *f = NULL; mm_segment_t fs; loff_t pos; csv = vmalloc(CSV_FILE_SIZE); if (ERR_ALLOC_MEM(csv)) { input_err(true, ilits->dev, "%s Failed to allocate CSV mem\n", __func__); ret = -EMP_NOMEM; goto fail_open; } max_threshold = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); min_threshold = kcalloc(core_mp.frame_len, sizeof(s32), GFP_KERNEL); if (ERR_ALLOC_MEM(max_threshold) || ERR_ALLOC_MEM(min_threshold)) { input_err(true, ilits->dev, "%s Failed to allocate threshold FRAME buffer\n", __func__); ret = -EMP_NOMEM; goto fail_open; } if (parser_get_ini_key_value("pv5_4 command", "date", core_mp.ini_date) < 0) ipio_memcpy(core_mp.ini_date, "Unknown", strlen("Unknown"), strlen("Unknown")); if (parser_get_ini_key_value("pv5_4 command", "version", core_mp.ini_ver) < 0) ipio_memcpy(core_mp.ini_ver, "Unknown", strlen("Unknown"), strlen("Unknown")); mp_print_csv_header(csv, &csv_len, &line_count, CSV_FILE_SIZE); for (seq = 0; seq < ri.count; seq++) { i = ri.index[seq]; get_frame_cont = 1; if (tItems[i].item_result == MP_DATA_PASS) { pr_info("\n[%s],OK \n\n", tItems[i].desp); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "\n[%s],OK\n\n", tItems[i].desp); } else { pr_info("\n[%s],NG\n\n", tItems[i].desp); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "\n[%s],NG\n\n", tItems[i].desp); } if (tItems[i].catalog == PIN_TEST) { pr_info("Test INT Pin = %d\n", tItems[i].test_int_pin); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "Test INT Pin = %d\n", tItems[i].test_int_pin); pr_info("Pulse Test = %d\n", tItems[i].int_pulse_test); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "Pulse Test = %d\n", tItems[i].int_pulse_test); pr_info("Delay Time = %d\n", tItems[i].delay_time); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "Delay Time = %d\n", tItems[i].delay_time); continue; } mp_print_csv_cdc_cmd(csv, &csv_len, i, CSV_FILE_SIZE); pr_info("Frame count = %d\n", tItems[i].frame_count); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "Frame count = %d\n", tItems[i].frame_count); if (tItems[i].trimmed_mean && tItems[i].catalog != PEAK_TO_PEAK_TEST) { pr_info("lowest percentage = %d\n", tItems[i].lowest_percentage); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "lowest percentage = %d\n", tItems[i].lowest_percentage); pr_info("highest percentage = %d\n", tItems[i].highest_percentage); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "highest percentage = %d\n", tItems[i].highest_percentage); } /* Show result of benchmark max and min */ if (tItems[i].spec_option == BENCHMARK) { if (tItems[i].catalog == PEAK_TO_PEAK_TEST) { for (j = 0; j < core_mp.frame_len; j++) { max_threshold[j] = tItems[i].bch_mrk_max[0][j]; min_threshold[j] = tItems[i].bch_mrk_min[0][j]; } for (j = 0; j < tItems[i].bch_mrk_frm_num; j++) { char bench_name[128] = {0}; snprintf(bench_name, (CSV_FILE_SIZE - csv_len), "Max_Bench%d", (j+1)); mp_compare_cdc_show_result(i, tItems[i].bch_mrk_max[j], csv, &csv_len, TYPE_BENCHMARK, max_threshold, min_threshold, bench_name, CSV_FILE_SIZE); snprintf(bench_name, (CSV_FILE_SIZE - csv_len), "Min_Bench%d", (j+1)); mp_compare_cdc_show_result(i, tItems[i].bch_mrk_min[j], csv, &csv_len, TYPE_BENCHMARK, max_threshold, min_threshold, bench_name, CSV_FILE_SIZE); } } else { for (j = 0; j < core_mp.frame_len; j++) { max_threshold[j] = tItems[i].bench_mark_max[j]; min_threshold[j] = tItems[i].bench_mark_min[j]; } mp_compare_cdc_show_result(i, tItems[i].bench_mark_max, csv, &csv_len, TYPE_BENCHMARK, max_threshold, min_threshold, "Max_Bench", CSV_FILE_SIZE); mp_compare_cdc_show_result(i, tItems[i].bench_mark_min, csv, &csv_len, TYPE_BENCHMARK, max_threshold, min_threshold, "Min_Bench", CSV_FILE_SIZE); } } else { for (j = 0; j < core_mp.frame_len; j++) { max_threshold[j] = tItems[i].max; min_threshold[j] = tItems[i].min; } pr_info("Max = %d\n", tItems[i].max); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "Max = %d\n", tItems[i].max); pr_info("Min = %d\n", tItems[i].min); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "Min = %d\n", tItems[i].min); } if (ipio_strcmp(tItems[i].desp, "open test(integration)_sp") == 0) { mp_compare_cdc_show_result(i, frame1_cbk700, csv, &csv_len, TYPE_NO_JUGE, max_threshold, min_threshold, "frame1 cbk700", CSV_FILE_SIZE); mp_compare_cdc_show_result(i, frame1_cbk250, csv, &csv_len, TYPE_NO_JUGE, max_threshold, min_threshold, "frame1 cbk250", CSV_FILE_SIZE); mp_compare_cdc_show_result(i, frame1_cbk200, csv, &csv_len, TYPE_NO_JUGE, max_threshold, min_threshold, "frame1 cbk200", CSV_FILE_SIZE); } if (ipio_strcmp(tItems[i].desp, "open test_c") == 0) { mp_compare_cdc_show_result(i, cap_dac, csv, &csv_len, TYPE_NO_JUGE, max_threshold, min_threshold, "CAP_DAC", CSV_FILE_SIZE); mp_compare_cdc_show_result(i, cap_raw, csv, &csv_len, TYPE_NO_JUGE, max_threshold, min_threshold, "CAP_RAW", CSV_FILE_SIZE); } if (tItems[i].catalog == TX_RX_DELTA) { if (ERR_ALLOC_MEM(core_mp.rx_delta_buf) || ERR_ALLOC_MEM(core_mp.tx_delta_buf)) { input_err(true, ilits->dev, "%s This test item (%s) has no data inside its buffer\n", __func__, tItems[i].desp); continue; } } else { if (ERR_ALLOC_MEM(tItems[i].buf) || ERR_ALLOC_MEM(tItems[i].max_buf) || ERR_ALLOC_MEM(tItems[i].min_buf)) { input_err(true, ilits->dev, "%s This test item (%s) has no data inside its buffer\n", __func__, tItems[i].desp); continue; } } /* Show test result as below */ if (tItems[i].catalog == KEY_TEST) { for (x = 0; x < core_mp.key_len; x++) { DUMP("KEY_%02d ", x); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "KEY_%02d,", x); } DUMP("\n"); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "\n"); for (y = 0; y < core_mp.key_len; y++) { DUMP(" %3d ", tItems[i].buf[y]); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), " %3d, ", tItems[i].buf[y]); } DUMP("\n"); csv_len += snprintf(csv + csv_len, (CSV_FILE_SIZE - csv_len), "\n"); } else if (tItems[i].catalog == TX_RX_DELTA) { for (j = 0; j < core_mp.frame_len; j++) { max_threshold[j] = core_mp.TxDeltaMax; min_threshold[j] = core_mp.TxDeltaMin; } mp_compare_cdc_show_result(i, core_mp.tx_max_buf, csv, &csv_len, TYPE_JUGE, max_threshold, min_threshold, "TX Max Hold", CSV_FILE_SIZE); mp_compare_cdc_show_result(i, core_mp.tx_min_buf, csv, &csv_len, TYPE_JUGE, max_threshold, min_threshold, "TX Min Hold", CSV_FILE_SIZE); for (j = 0; j < core_mp.frame_len; j++) { max_threshold[j] = core_mp.RxDeltaMax; min_threshold[j] = core_mp.RxDeltaMin; } mp_compare_cdc_show_result(i, core_mp.rx_max_buf, csv, &csv_len, TYPE_JUGE, max_threshold, min_threshold, "RX Max Hold", CSV_FILE_SIZE); mp_compare_cdc_show_result(i, core_mp.rx_min_buf, csv, &csv_len, TYPE_JUGE, max_threshold, min_threshold, "RX Min Hold", CSV_FILE_SIZE); } else { /* general result */ if (tItems[i].trimmed_mean && tItems[i].catalog != PEAK_TO_PEAK_TEST) { mp_compare_cdc_show_result(i, tItems[i].result_buf, csv, &csv_len, TYPE_JUGE, max_threshold, min_threshold, "Mean result", CSV_FILE_SIZE); } else { if (!tItems[i].bch_mrk_multi) { mp_compare_cdc_show_result(i, tItems[i].max_buf, csv, &csv_len, TYPE_JUGE, max_threshold, min_threshold, "Max Hold", CSV_FILE_SIZE); mp_compare_cdc_show_result(i, tItems[i].min_buf, csv, &csv_len, TYPE_JUGE, max_threshold, min_threshold, "Min Hold", CSV_FILE_SIZE); } } if (tItems[i].catalog != PEAK_TO_PEAK_TEST) get_frame_cont = tItems[i].frame_count; if (tItems[i].bch_mrk_multi) get_frame_cont = tItems[i].bch_mrk_frm_num; /* result of each frame */ for (j = 0; j < get_frame_cont; j++) { char frame_name[128] = {0}; snprintf(frame_name, (CSV_FILE_SIZE - csv_len), "Frame %d", (j+1)); mp_compare_cdc_show_result(i, &tItems[i].buf[(j*core_mp.frame_len)], csv, &csv_len, TYPE_NO_JUGE, max_threshold, min_threshold, frame_name, CSV_FILE_SIZE); } } k = i; } memset(csv_name, 0, 128 * sizeof(char)); mp_print_csv_tail(csv, &csv_len, CSV_FILE_SIZE); for (i = 0; i < MP_TEST_ITEM; i++) { if (tItems[i].run) { if (tItems[i].item_result < 0) { pass_item_count = 0; break; } pass_item_count++; } } /* define csv file name */ ret_pass_name = NORMAL_CSV_PASS_NAME; ret_fail_name = NORMAL_CSV_FAIL_NAME; if (pass_item_count == 0) { core_mp.final_result = MP_DATA_FAIL; if ((ilits->sec.cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) || (ilits->sec.cmd_state == SEC_CMD_STATUS_RUNNING)) ret = MP_DATA_PASS;//Sec using this value for check fucntion error. Not a test result. else ret = MP_DATA_FAIL; if (core_mp.lost_parameter) { ret_fail_name = NULL; ret_fail_name = NORMAL_CSV_WARNING_NAME; input_err(true, ilits->dev, "%s WARNING! OPEN or SHORT parameter not found in ini file!!\n", __func__); } if (lcm_on) { snprintf(csv_name, (CSV_FILE_SIZE - csv_len), "%s/%s_%s_%s.csv", CSV_LCM_ON_PATH, get_date_time_str(), ret_fail_name, tItems[k].desp); } else { snprintf(csv_name, (CSV_FILE_SIZE - csv_len), "%s/%s_%s_%s.csv", CSV_LCM_OFF_PATH, get_date_time_str(), ret_fail_name, tItems[k].desp); } } else { core_mp.final_result = MP_DATA_PASS; ret = MP_DATA_PASS; if (core_mp.lost_benchmark) { ret_pass_name = NULL; ret_pass_name = NORMAL_CSV_WARNING_NAME; input_err(true, ilits->dev, "%s WARNING! Golden and SPEC in ini file aren't matched!!\n", __func__); } if (lcm_on) { snprintf(csv_name, (CSV_FILE_SIZE - csv_len), "%s/%s_%s_%s.csv", CSV_LCM_ON_PATH, get_date_time_str(), ret_pass_name, tItems[k].desp); } else { snprintf(csv_name, (CSV_FILE_SIZE - csv_len), "%s/%s_%s_%s.csv", CSV_LCM_OFF_PATH, get_date_time_str(), ret_pass_name, tItems[k].desp); } } input_info(true, ilits->dev, "%s Open CSV : %s\n", __func__, csv_name); if (f == NULL) f = filp_open(csv_name, O_WRONLY | O_CREAT | O_TRUNC, 644); if (ERR_ALLOC_MEM(f)) { input_err(true, ilits->dev, "%s Failed to open CSV file", __func__); ret = -EMP_NOMEM; goto fail_open; } input_info(true, ilits->dev, "%s Open CSV succeed, its length = %d\n ", __func__, csv_len); if (csv_len >= CSV_FILE_SIZE) { input_err(true, ilits->dev, "%s The length saved to CSV is too long !\n", __func__); ret = -EMP_INVAL; goto fail_open; } fs = get_fs(); set_fs(KERNEL_DS); pos = 0; vfs_write(f, csv, csv_len, &pos); set_fs(fs); filp_close(f, NULL); input_info(true, ilits->dev, "%s Writing Data into CSV succeed\n", __func__); fail_open: ipio_vfree((void **)&csv); ipio_kfree((void **)&max_threshold); ipio_kfree((void **)&min_threshold); return ret; } static void ilitek_tddi_mp_init_item(void) { int i = 0; memset(&core_mp, 0, sizeof(core_mp)); memset(&open_para, 0, sizeof(open_para)); memset(&short_para, 0, sizeof(short_para)); core_mp.chip_pid = ilits->chip->pid; core_mp.chip_id = ilits->chip->id; core_mp.chip_type = ilits->chip->type; core_mp.chip_ver = ilits->chip->ver; core_mp.fw_ver = ilits->chip->fw_ver; core_mp.protocol_ver = ilits->protocol->ver; core_mp.core_ver = ilits->chip->core_ver; core_mp.cdc_len = ilits->protocol->cdc_len; core_mp.no_bk_shift = ilits->chip->no_bk_shift; core_mp.xch_len = ilits->xch_num; core_mp.ych_len = ilits->ych_num; core_mp.frame_len = core_mp.xch_len * core_mp.ych_len; core_mp.stx_len = 0; core_mp.srx_len = 0; core_mp.key_len = 0; core_mp.st_len = 0; core_mp.tdf = 240; core_mp.busy_cdc = INT_CHECK; core_mp.retry = ilits->mp_retry; core_mp.td_retry = false; core_mp.final_result = MP_DATA_FAIL; core_mp.lost_benchmark = false; core_mp.lost_parameter = false; core_mp.all_pass = false; input_info(true, ilits->dev, "%s ============== TP & Panel info ================\n", __func__); input_info(true, ilits->dev, "Driver version = %s\n", DRIVER_VERSION); input_info(true, ilits->dev, "TP Module = %s\n", ilits->md_name); input_info(true, ilits->dev, "CHIP = 0x%x\n", core_mp.chip_pid); input_info(true, ilits->dev, "Firmware version = %x\n", core_mp.fw_ver); input_info(true, ilits->dev, "Protocol version = %x\n", core_mp.protocol_ver); input_info(true, ilits->dev, "Core version = %x\n", core_mp.core_ver); input_info(true, ilits->dev, "Read CDC Length = %d\n", core_mp.cdc_len); input_info(true, ilits->dev, "X length = %d, Y length = %d\n", core_mp.xch_len, core_mp.ych_len); input_info(true, ilits->dev, "Frame length = %d\n", core_mp.frame_len); input_info(true, ilits->dev, "Check busy method = %s\n", (core_mp.busy_cdc ? "Polling" : "Interrupt")); input_info(true, ilits->dev, "%s ===============================================\n", __func__); for (i = 0; i < MP_TEST_ITEM; i++) { tItems[i].spec_option = 0; tItems[i].type_option = 0; tItems[i].run = false; tItems[i].max = 0; tItems[i].max_res = MP_DATA_FAIL; tItems[i].item_result = MP_DATA_PASS; tItems[i].min = 0; tItems[i].min_res = MP_DATA_FAIL; tItems[i].frame_count = 0; tItems[i].trimmed_mean = 0; tItems[i].lowest_percentage = 0; tItems[i].highest_percentage = 0; tItems[i].v_tdf_1 = 0; tItems[i].v_tdf_2 = 0; tItems[i].h_tdf_1 = 0; tItems[i].h_tdf_2 = 0; tItems[i].max_min_mode = 0; tItems[i].bch_mrk_multi = false; tItems[i].bch_mrk_frm_num = 1; tItems[i].goldenmode = 0; tItems[i].retry_cnt = RETRY_COUNT; tItems[i].result_buf = NULL; tItems[i].buf = NULL; tItems[i].max_buf = NULL; tItems[i].min_buf = NULL; tItems[i].bench_mark_max = NULL; tItems[i].bench_mark_min = NULL; tItems[i].bch_mrk_max = NULL; tItems[i].bch_mrk_min = NULL; tItems[i].node_type = NULL; tItems[i].delay_time = 0; tItems[i].test_int_pin = 0; tItems[i].int_pulse_test = 0; if (tItems[i].catalog == MUTUAL_TEST) { tItems[i].do_test = mutual_test; } else if (tItems[i].catalog == TX_RX_DELTA) { tItems[i].do_test = mutual_test; } else if (tItems[i].catalog == UNTOUCH_P2P) { tItems[i].do_test = mutual_test; } else if (tItems[i].catalog == PIXEL) { tItems[i].do_test = mutual_test; } else if (tItems[i].catalog == OPEN_TEST) { if (ipio_strcmp(tItems[i].desp, "open test(integration)_sp") == 0) tItems[i].do_test = open_test_sp; else if (ipio_strcmp(tItems[i].desp, "open test_c") == 0) tItems[i].do_test = open_test_cap; else tItems[i].do_test = mutual_test; } else if (tItems[i].catalog == KEY_TEST) { tItems[i].do_test = key_test; } else if (tItems[i].catalog == SELF_TEST) { tItems[i].do_test = self_test; } else if (tItems[i].catalog == ST_TEST) { tItems[i].do_test = st_test; } else if (tItems[i].catalog == PEAK_TO_PEAK_TEST) { tItems[i].do_test = peak_to_peak_test; } else if (tItems[i].catalog == SHORT_TEST) { tItems[i].do_test = mutual_test; } else if (tItems[i].catalog == PIN_TEST) { tItems[i].do_test = pin_test; } tItems[i].result = kmalloc(16, GFP_KERNEL); snprintf(tItems[i].result, 16, "%s", "FAIL"); } } static void mp_p2p_td_retry_after_ra_fail(int p2p_td) { int i; for (i = 0; i < MP_TEST_ITEM; i++) { if (ipio_strcmp(tItems[i].desp, "noise peak to peak(with panel) (lcm off)") == 0) break; } if (i >= MP_TEST_ITEM) return; ILI_DBG("%s i = %d, p2p_noise_ret = %d, p2p_noise_run = %d\n", __func__, i, tItems[i].item_result, tItems[i].run); if (tItems[i].item_result == MP_DATA_PASS && tItems[i].run == 1) tItems[p2p_td].do_test(p2p_td); } static void mp_test_run(int index) { int i = index, j; char str[512] = {0}; /* Get parameters from ini */ parser_get_int_data(tItems[i].desp, "spec option", str, sizeof(str)); tItems[i].spec_option = ili_katoi(str); parser_get_int_data(tItems[i].desp, "type option", str, sizeof(str)); tItems[i].type_option = ili_katoi(str); parser_get_int_data(tItems[i].desp, "frame count", str, sizeof(str)); tItems[i].frame_count = ili_katoi(str); parser_get_int_data(tItems[i].desp, "trimmed mean", str, sizeof(str)); tItems[i].trimmed_mean = ili_katoi(str); parser_get_int_data(tItems[i].desp, "lowest percentage", str, sizeof(str)); tItems[i].lowest_percentage = ili_katoi(str); parser_get_int_data(tItems[i].desp, "highest percentage", str, sizeof(str)); tItems[i].highest_percentage = ili_katoi(str); parser_get_int_data(tItems[i].desp, "goldenmode", str, sizeof(str)); tItems[i].goldenmode = ili_katoi(str); parser_get_int_data(tItems[i].desp, "max min mode", str, sizeof(str)); tItems[i].max_min_mode = ili_katoi(str); parser_get_int_data(tItems[i].desp, "retry count", str, sizeof(str)); tItems[i].retry_cnt = ili_katoi(str); if (tItems[i].goldenmode && (tItems[i].spec_option != tItems[i].goldenmode)) core_mp.lost_benchmark = true; /* Get pin test delay time */ if (tItems[i].catalog == PIN_TEST) { parser_get_int_data(tItems[i].desp, "test int pin", str, sizeof(str)); tItems[i].test_int_pin = ili_katoi(str); parser_get_int_data(tItems[i].desp, "int pulse test", str, sizeof(str)); tItems[i].int_pulse_test = ili_katoi(str); parser_get_int_data(tItems[i].desp, "delay time", str, sizeof(str)); tItems[i].delay_time = ili_katoi(str); } /* Get TDF value from ini */ if (tItems[i].catalog == SHORT_TEST) { parser_get_int_data(tItems[i].desp, "v_tdf_1", str, sizeof(str)); tItems[i].v_tdf_1 = parser_get_tdf_value(str, tItems[i].catalog); parser_get_int_data(tItems[i].desp, "v_tdf_2", str, sizeof(str)); tItems[i].v_tdf_2 = parser_get_tdf_value(str, tItems[i].catalog); parser_get_int_data(tItems[i].desp, "h_tdf_1", str, sizeof(str)); tItems[i].h_tdf_1 = parser_get_tdf_value(str, tItems[i].catalog); parser_get_int_data(tItems[i].desp, "h_tdf_2", str, sizeof(str)); tItems[i].h_tdf_2 = parser_get_tdf_value(str, tItems[i].catalog); } else { parser_get_int_data(tItems[i].desp, "v_tdf", str, sizeof(str)); tItems[i].v_tdf_1 = parser_get_tdf_value(str, tItems[i].catalog); parser_get_int_data(tItems[i].desp, "h_tdf", str, sizeof(str)); tItems[i].h_tdf_1 = parser_get_tdf_value(str, tItems[i].catalog); } /* Get threshold from ini structure in parser */ if (ipio_strcmp(tItems[i].desp, "tx/rx delta") == 0) { parser_get_int_data(tItems[i].desp, "tx max", str, sizeof(str)); core_mp.TxDeltaMax = ili_katoi(str); parser_get_int_data(tItems[i].desp, "tx min", str, sizeof(str)); core_mp.TxDeltaMin = ili_katoi(str); parser_get_int_data(tItems[i].desp, "rx max", str, sizeof(str)); core_mp.RxDeltaMax = ili_katoi(str); parser_get_int_data(tItems[i].desp, "rx min", str, sizeof(str)); core_mp.RxDeltaMin = ili_katoi(str); ILI_DBG("%s %s: Tx Max = %d, Tx Min = %d, Rx Max = %d, Rx Min = %d\n", __func__, tItems[i].desp, core_mp.TxDeltaMax, core_mp.TxDeltaMin, core_mp.RxDeltaMax, core_mp.RxDeltaMin); } else { parser_get_int_data(tItems[i].desp, "max", str, sizeof(str)); tItems[i].max = ili_katoi(str); parser_get_int_data(tItems[i].desp, "min", str, sizeof(str)); tItems[i].min = ili_katoi(str); } /* Get pin test delay time */ if (tItems[i].catalog == PEAK_TO_PEAK_TEST) { if (tItems[i].max_min_mode == 1 && tItems[i].spec_option == 1) { tItems[i].bch_mrk_multi = true; for (j = 1; j < 11; j++) { char tmp[8] = {0}; /* format complete string from the name of section "_Benchmark_Data". */ snprintf(str, sizeof(str), "%s%s%s%d", tItems[index].desp, "_", BENCHMARK_KEY_NAME, j); if (parser_get_int_data(str, str, tmp, sizeof(tmp)) <= 0) break; tItems[i].bch_mrk_frm_num = j; } ILI_DBG("%s set bch_mrk_frm_num = %d\n", __func__, tItems[i].bch_mrk_frm_num); } } ILI_DBG("%s %s: run = %d, max = %d, min = %d, frame_count = %d\n", __func__, tItems[i].desp, tItems[i].run, tItems[i].max, tItems[i].min, tItems[i].frame_count); ILI_DBG("%s v_tdf_1 = %d, v_tdf_2 = %d, h_tdf_1 = %d, h_tdf_2 = %d", __func__, tItems[i].v_tdf_1, tItems[i].v_tdf_2, tItems[i].h_tdf_1, tItems[i].h_tdf_2); input_info(true, ilits->dev, "%s Run MP Test Item : %s\n", __func__, tItems[i].desp); tItems[i].do_test(i); mp_compare_test_result(i); /* P2P TD retry after RA sample failed. */ if (ipio_strcmp(tItems[i].desp, "peak to peak_td (lcm off)") == 0 && tItems[i].item_result == MP_DATA_FAIL) { parser_get_int_data(tItems[i].desp, "recheck ptop lcm off", str, sizeof(str)); input_info(true, ilits->dev, "%s Peak to Peak TD retry = %d\n", __func__, ili_katoi(str)); core_mp.td_retry = ili_katoi(str); if (core_mp.td_retry) mp_p2p_td_retry_after_ra_fail(i); } if (core_mp.retry && tItems[i].item_result == MP_DATA_FAIL) { input_info(true, ilits->dev, "%s MP failed, doing retry %d times\n", __func__, tItems[i].retry_cnt); mp_do_retry(i, tItems[i].retry_cnt); } input_info(true, ilits->dev, "current_mp:%s, running:%s\n", ilits->current_mpitem, tItems[i].desp); if (ipio_strcmp(tItems[i].desp, ilits->current_mpitem) == 0) sec_factory_print_frame(tItems[i].buf); } static void mp_test_free(void) { int i, j; input_info(true, ilits->dev, "%s Free all allocated mem for MP\n", __func__); core_mp.final_result = MP_DATA_FAIL; core_mp.td_retry = false; for (i = 0; i < MP_TEST_ITEM; i++) { tItems[i].run = false; tItems[i].max_res = MP_DATA_FAIL; tItems[i].min_res = MP_DATA_FAIL; tItems[i].item_result = MP_DATA_PASS; if (tItems[i].catalog == TX_RX_DELTA) { ipio_kfree((void **)&core_mp.rx_delta_buf); ipio_kfree((void **)&core_mp.tx_delta_buf); ipio_kfree((void **)&core_mp.tx_max_buf); ipio_kfree((void **)&core_mp.tx_min_buf); ipio_kfree((void **)&core_mp.rx_max_buf); ipio_kfree((void **)&core_mp.rx_min_buf); } else { if (tItems[i].spec_option == BENCHMARK) { ipio_kfree((void **)&tItems[i].bench_mark_max); ipio_kfree((void **)&tItems[i].bench_mark_min); if (tItems[i].bch_mrk_max != NULL) { for (j = 0; j < tItems[i].bch_mrk_frm_num; j++) if (tItems[i].bch_mrk_max[j] != NULL) { kfree(tItems[i].bch_mrk_max[j]); tItems[i].bch_mrk_max[j] = NULL; } kfree(tItems[i].bch_mrk_max); tItems[i].bch_mrk_max = NULL; } if (tItems[i].bch_mrk_min != NULL) { for (j = 0; j < tItems[i].bch_mrk_frm_num; j++) if (tItems[i].bch_mrk_min[j] != NULL) { kfree(tItems[i].bch_mrk_min[j]); tItems[i].bch_mrk_min[j] = NULL; } kfree(tItems[i].bch_mrk_min); tItems[i].bch_mrk_min = NULL; } } ipio_kfree((void **)&tItems[i].node_type); ipio_kfree((void **)&tItems[i].result); ipio_kfree((void **)&tItems[i].result_buf); ipio_kfree((void **)&tItems[i].max_buf); ipio_kfree((void **)&tItems[i].min_buf); ipio_vfree((void **)&tItems[i].buf); } } ipio_kfree((void **)&frame1_cbk700); ipio_kfree((void **)&frame1_cbk250); ipio_kfree((void **)&frame1_cbk200); ipio_kfree((void **)&frame_buf); ipio_kfree((void **)&key_buf); if (frm_buf != NULL) { for (j = 0; j < 3; j++) if (frm_buf[j] != NULL) { kfree(frm_buf[j]); frm_buf[j] = NULL; } kfree(frm_buf); frm_buf = NULL; } } /* The method to copy results to user depends on what APK needs */ static void mp_copy_ret_to_apk(char *buf) { int i, seq, len = 2; if (!buf) { input_err(true, ilits->dev, "%s apk buffer is null\n", __func__); return; } len += snprintf(buf + len, PAGE_SIZE - len, "CSV path: %s\n\n", csv_name); for (seq = 0; seq < ri.count; seq++) { i = ri.index[seq]; if (tItems[i].item_result == MP_DATA_FAIL) { input_err(true, ilits->dev, "%s [%s] = FAIL\n", __func__, tItems[i].desp); len += snprintf(buf + len, PAGE_SIZE - len, "[%s] = FAIL\n", tItems[i].desp); } else { input_info(true, ilits->dev, "%s [%s] = PASS\n", __func__, tItems[i].desp); len += snprintf(buf + len, PAGE_SIZE - len, "[%s] = PASS\n", tItems[i].desp); } } ilits->mp_ret_len = len; } static int mp_sort_item(bool lcm_on) { int i, j; char str[128] = {0}; ri.count = 0; memset(ri.index, 0x0, MP_TEST_ITEM); for (i = 0; i < MAX_SECTION_NUM; i++) { for (j = 0; j < MP_TEST_ITEM; j++) { if (ipio_strcmp(seq_item[i], tItems[j].desp) != 0) continue; parser_get_int_data(tItems[j].desp, "enable", str, sizeof(str)); tItems[j].run = ili_katoi(str); if (tItems[j].run != 1 || tItems[j].lcm != lcm_on) continue; if (ri.count > MP_TEST_ITEM) { input_err(true, ilits->dev, "%s Test item(%d) is invaild, abort\n", __func__, ri.count); return -EINVAL; } ri.index[ri.count] = j; ri.count++; } } return 0; } static void ilitek_tddi_mp_all_pass_check(void) { int ret = 0, retry = 5; u8 cmd[1] = {0xFD}; u8 temp[3] = {0}; ilits->wait_int_timeout = 20; do { ret = ilits->wrapper(cmd, 1, temp, 3, ON, OFF); if (ret < 0) { input_err(true, ilits->dev, "%s Write MP All Pass command failed\n", __func__); core_mp.all_pass = false; } else { if (temp[0] == 0xFD) break; } } while (--retry >= 0); ilits->wait_int_timeout = MP_INT_TIMEOUT; if (retry <= 0) { input_err(true, ilits->dev, "%s MP All Pass command failed, normal mode\n", __func__); core_mp.all_pass = false; return; } if (temp[2] == ili_calc_packet_checksum(temp, sizeof(temp) - 1) && temp[0] == 0xFD && temp[1] == 0x02) {//0xFD:back door command header, 0x02:Normal mode core_mp.all_pass = true; input_err(true, ilits->dev, "%s MP mode check: Back door mode, MP All Pass\n", __func__); } else { core_mp.all_pass = false;//0xFD:back door command header, 0x01:Normal mode input_err(true, ilits->dev, "%s MP mode check: Normal mode\n", __func__); } } int ili_mp_test_main(char *apk, bool lcm_on) { int i, ret = 0; char str[128] = {0}, ver[128] = {0}; if (ilits->xch_num <= 0 || ilits->ych_num <= 0) { input_err(true, ilits->dev, "%s Invalid frame length (%d, %d)\n", __func__, ilits->xch_num, ilits->ych_num); ret = -EMP_INVAL; goto out; } if (ini_info == NULL) { ini_info = (struct ini_file_data *)vmalloc(sizeof(struct ini_file_data) * PARSER_MAX_KEY_NUM); if (ERR_ALLOC_MEM(ini_info)) { input_err(true, ilits->dev, "%s Failed to malloc ini_info\n", __func__); ret = -EMP_NOMEM; goto out; } } ilitek_tddi_mp_init_item(); if ((ilits->sec.cmd_all_factory_state != SEC_CMD_STATUS_RUNNING) && (ilits->sec.cmd_state != SEC_CMD_STATUS_RUNNING)) ilitek_tddi_mp_all_pass_check(); ret = ilitek_tddi_mp_ini_parser(ilits->md_ini_path); if (ret < 0) { input_err(true, ilits->dev, "%s Failed to parsing INI file\n", __func__); ret = -EMP_INI; goto out; } /* Compare both protocol version of ini and firmware */ parser_get_ini_key_value("pv5_4 command", "protocol", str); snprintf(ver, sizeof(ver), "0x%s", str); if ((ili_str2hex(ver)) != (core_mp.protocol_ver >> 8)) { input_err(true, ilits->dev, "%s ERROR! MP Protocol version is invaild, 0x%x\n", __func__, ili_str2hex(ver)); ret = -EMP_PROTOCOL; goto out; } /* Read timing info from ini file */ if (mp_get_timing_info() < 0) { input_err(true, ilits->dev, "%s Failed to get timing info from ini\n", __func__); ret = -EMP_TIMING_INFO; goto out; } #if MP_INT_LEVEL if (ili_ic_int_trigger_ctrl(true) < 0) { input_err(true, ilits->dev, "%s Failed to set INT as Level trigger", __func__); ret = -EMP_CMD; goto out; } #endif /* Sort test item by ini file */ if (mp_sort_item(lcm_on) < 0) { input_err(true, ilits->dev, "%s Failed to sort test item\n", __func__); ret = -EMP_INI; goto out; } for (i = 0; i < ri.count; i++) mp_test_run(ri.index[i]); ret = mp_show_result(lcm_on); mp_copy_ret_to_apk(apk); out: mp_test_free(); #if MP_INT_LEVEL if (ili_ic_int_trigger_ctrl(false) < 0) { input_err(true, ilits->dev, "%s Failed to set INT back to pluse trigger", __func__); ret = -EMP_CMD; } #endif ipio_vfree((void **)&ini_info); return ret; };