/* SPDX-License-Identifier: GPL-2.0 */ /* Himax Android Driver Sample Code for inspection functions * * Copyright (C) 2022 Himax Corporation. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "himax_inspection.h" static int g_gap_vertical_partial = 3; static int *g_gap_vertical_part; static int g_gap_horizontal_partial = 3; static int *g_gap_horizontal_part; static int g_dc_max; static int g_1kind_raw_size; uint32_t g_rslt_data_len; int **g_inspt_crtra; int *g_inspt_crtra_flag; int *g_test_item_flag; int do_lpwg_test; int HX_CRITERIA_ITEM; int HX_CRITERIA_SIZE; char *g_rslt_data; bool file_w_flag; static char g_file_path[256]; static char g_rslt_log[256]; static char g_start_log[512]; #define FAIL_IN_INDEX "%s: %s FAIL in index %d\n" #define FAIL_IN_INDEX_CRTRA \ "%s: %s FAIL in index %d,max=%d, min=%d, RAW=%d\n" static char *g_hx_head_str[] = { "TP_Info", "Project_Info", "TestItem", "TestCriteria", NULL }; /*Need to map THP_INSPECTION_ENUM*/ static char *g_hx_inspt_mode[] = { "HIMAX_OPEN", "HIMAX_SELF_OPEN", "HIMAX_MICRO_OPEN", "HIMAX_SHORT", "HIMAX_SELF_SHORT", "HIMAX_SC", "HIMAX_WEIGHT_NOISE", "HIMAX_SELF_WEIGHT_NOISE", "HIMAX_ABS_NOISE", "HIMAX_SELF_ABS_NOISE", "HIMAX_RAWDATA", "HIMAX_BPN_RAWDATA", "HIMAX_SELF_BPN_RAWDATA", "HIMAX_PEN_MODE_RAWDATA", "HIMAX_SORTING", "HIMAX_GAPTEST_RAW", /*"HIMAX_GAPTEST_RAW_X",*/ /*"HIMAX_GAPTEST_RAW_Y",*/ "HIMAX_ACT_IDLE_NOISE", "HIMAX_ACT_IDLE_RAWDATA", "HIMAX_ACT_IDLE_BPN_RAWDATA", "HIMAX_LPWUG_WEIGHT_NOISE", "HIMAX_LPWUG_ABS_NOISE", "HIMAX_LPWUG_RAWDATA", "HIMAX_LPWUG_BPN_RAWDATA", "HIMAX_LPWUG_IDLE_NOISE", "HIMAX_LPWUG_IDLE_RAWDATA", "HIMAX_LPWUG_IDLE_BPN_RAWDATA", "HIMAX_BACK_NORMAL", NULL }; /* for criteria */ static char *g_hx_inspt_crtra_name[] = { "CRITERIA_RAW_MIN", "CRITERIA_RAW_MAX", "CRITERIA_RAW_BPN_MIN", "CRITERIA_RAW_BPN_MAX", "CRITERIA_SELF_RAW_BPN_MIN", "CRITERIA_SELF_RAW_BPN_MAX", "CRITERIA_SC_MIN", "CRITERIA_SC_MAX", "CRITERIA_SC_GOLDEN", "CRITERIA_SHORT_MIN", "CRITERIA_SHORT_MAX", "CRITERIA_SELF_SHORT_MIN", "CRITERIA_SELF_SHORT_MAX", "CRITERIA_OPEN_MIN", "CRITERIA_OPEN_MAX", "CRITERIA_SELF_OPEN_MIN", "CRITERIA_SELF_OPEN_MAX", "CRITERIA_MICRO_OPEN_MIN", "CRITERIA_MICRO_OPEN_MAX", "CRITERIA_NOISE_WT_MIN", "CRITERIA_NOISE_WT_MAX", "CRITERIA_SELF_NOISE_WT_MIN", "CRITERIA_SELF_NOISE_WT_MAX", "CRITERIA_NOISE_ABS_MIN", "CRITERIA_NOISE_ABS_MAX", "CRITERIA_SELF_NOISE_ABS_MIN", "CRITERIA_SELF_NOISE_ABS_MAX", "CRITERIA_PEN_MODE_DATA_SELF_MIN", "CRITERIA_PEN_MODE_DATA_SELF_MAX", "CRITERIA_SORT_MIN", "CRITERIA_SORT_MAX", "CRITERIA_GAP_RAW_HOR_MIN", "CRITERIA_GAP_RAW_HOR_MAX", "CRITERIA_GAP_RAW_VER_MIN", "CRITERIA_GAP_RAW_VER_MAX", "ACT_IDLE_NOISE_MIN", "ACT_IDLE_NOISE_MAX", "ACT_IDLE_RAWDATA_MIN", "ACT_IDLE_RAWDATA_MAX", "ACT_IDLE_RAW_BPN_MIN", "ACT_IDLE_RAW_BPN_MAX", "LPWUG_NOISE_WT_MIN", "LPWUG_NOISE_WT_MAX", "LPWUG_NOISE_ABS_MIN", "LPWUG_NOISE_ABS_MAX", "LPWUG_RAWDATA_MIN", "LPWUG_RAWDATA_MAX", "LPWUG_RAW_BPN_MIN", "LPWUG_RAW_BPN_MAX", "LPWUG_IDLE_NOISE_MIN", "LPWUG_IDLE_NOISE_MAX", "LPWUG_IDLE_RAWDATA_MIN", "LPWUG_IDLE_RAWDATA_MAX", "LPWUG_IDLE_RAW_BPN_MIN", "LPWUG_IDLE_RAW_BPN_MAX", NULL }; /* for other setting */ static char *g_hx_inspt_setting_name[] = { "RAW_BS_FRAME", "NOISE_BS_FRAME", "ACT_IDLE_BS_FRAME", "LP_BS_FRAME", "LP_IDLE_BS_FRAME", "NORMAL_N_FRAME", "IDLE_N_FRAME", "LP_RAW_N_FRAME", "LP_NOISE_N_FRAME", "LP_IDLE_RAW_N_FRAME", "LP_IDLE_NOISE_N_FRAME", NULL }; /* for criteria version */ static char *g_hx_inspt_ver_name = "hx_criteria_version"; static char *g_str_crtra_ver; static int *g_hx_inspt_setting_val; #if defined(HX_ZERO_FLASH) static int g_mp_fw_ver; #endif #define SYSTEM_TIME 1900 void (*_himax_self_test_init)(void) = himax_inspection_init; static void himax_press_powerkey(void) { I(" %s POWER KEY event %x press\n", __func__, KEY_POWER); input_report_key(hx_s_ts->input_dev, KEY_POWER, 1); input_sync(hx_s_ts->input_dev); msleep(100); I(" %s POWER KEY event %x release\n", __func__, KEY_POWER); input_report_key(hx_s_ts->input_dev, KEY_POWER, 0); input_sync(hx_s_ts->input_dev); } static uint16_t NOISEMAX; static uint16_t g_recal_thx; static int arraydata_max1, arraydata_max2, arraydata_max3; static int arraydata_min1, arraydata_min2, arraydata_min3; static int hx_check_self_test_item(int type) { int ret = 0; int self_type = -9487; switch (type) { case HX_WT_NOISE: self_type = HX_SELF_WT_NOISE; break; case HX_ABS_NOISE: self_type = HX_SELF_ABS_NOISE; break; case HX_BPN_RAWDATA: self_type = HX_SELF_BPN_RAWDATA; break; case HX_OPEN: self_type = HX_SELF_OPEN; break; case HX_SHORT: self_type = HX_SELF_SHORT; break; default: break; } if (self_type == -9487) ret = 0; else if (g_test_item_flag[type] && g_test_item_flag[self_type]) { ret = 1; I("%s: Support self type=%s", __func__, g_hx_inspt_mode[self_type]); } return ret; } static int hx_check_has_self(int type) { int ret; switch (type) { case HX_SELF_WT_NOISE: ret = HX_SELF_WT_NOISE; break; case HX_SELF_ABS_NOISE: ret = HX_SELF_ABS_NOISE; break; case HX_SELF_BPN_RAWDATA: ret = HX_SELF_BPN_RAWDATA; break; case HX_SELF_OPEN: ret = HX_SELF_OPEN; break; case HX_SELF_SHORT: ret = HX_SELF_SHORT; break; default: ret = -9487; break; } return ret; } int hx_check_char_val(char input) { int result = NO_ERR; if (input >= 'A' && input <= 'Z') { result = -1; goto END; } if (input >= 'a' && input <= 'z') { result = -1; goto END; } if (input >= '0' && input <= '9') { result = 1; goto END; } END: return result; } #ifdef HX_INSPT_DBG static int hx_print_crtra_after_parsing(void) { int i = 0, j; int all_mut_len = hx_s_ic_data->tx_num*hx_s_ic_data->rx_num; uint32_t rx_num = hx_s_ic_data->rx_num; for (i = 0; i < HX_CRITERIA_SIZE; i++) { I("Now is %s\n", g_hx_inspt_crtra_name[i]); if (g_inspt_crtra_flag[i] == 1) { for (j = 0; j < all_mut_len; j++) { PI("%d, ", g_inspt_crtra[i][j]); if (j % rx_num == (rx_num - 1)) PI("\n"); } } else { I("No this Item in this criteria file!\n"); } PI("\n"); } return 0; } #endif void himax_get_arraydata_edge(const int *RAW) { int temp, i, j; int len = hx_s_ic_data->rx_num * hx_s_ic_data->tx_num; int *ArrayData; ArrayData = kcalloc(len, sizeof(int), GFP_KERNEL); if (ArrayData == NULL) { E("%s: allocate ArrayData failed\n", __func__); return; } for (i = 0; i < len; i++) ArrayData[i] = RAW[i]; for (j = len-1; j > 0; j--) { /*min to max*/ for (i = 0; i < j; i++) { if (ArrayData[i] > ArrayData[i+1]) { temp = ArrayData[i]; ArrayData[i] = ArrayData[i+1]; ArrayData[i+1] = temp; } } } arraydata_min1 = ArrayData[0]; arraydata_min2 = ArrayData[1]; arraydata_min3 = ArrayData[2]; arraydata_max1 = ArrayData[len-1]; arraydata_max2 = ArrayData[len-2]; arraydata_max3 = ArrayData[len-3]; kfree(ArrayData); } static int hx_test_data_get(int RAW[], char *start_log, char *result, uint32_t ret_val, bool self) { uint32_t i; ssize_t len = 0; char *testdata = NULL; uint32_t SZ_SIZE = g_1kind_raw_size; testdata = kzalloc(sizeof(char) * SZ_SIZE, GFP_KERNEL); if (testdata == NULL) { E("%s: Memory allocation falied!\n", __func__); return MEM_ALLOC_FAIL; } len += snprintf((testdata + len), SZ_SIZE - len, "%s", start_log); if (ret_val == HX_INSP_ESCREEN) { len += snprintf((testdata + len), SZ_SIZE - len, "%s\n", "ERROR: abnormal screen status"); } else if (ret_val == HX_INSP_ESWITCHMODE) { len += snprintf((testdata + len), SZ_SIZE - len, "%s\n", "ERROR: abnormal sorting mode"); } else if (ret_val == HX_INSP_EGETRAW) { len += snprintf((testdata + len), SZ_SIZE - len, "%s\n", "ERROR: get dsram fail"); } else { for (i = 0; i < hx_s_ic_data->tx_num*hx_s_ic_data->rx_num; i++) { if (i > 1 && ((i + 1) % hx_s_ic_data->rx_num) == 0) len += snprintf((testdata + len), SZ_SIZE - len, "%5d,\n", RAW[i]); else len += snprintf((testdata + len), SZ_SIZE - len, "%5d,", RAW[i]); } if (self) { len += snprintf((testdata + len), SZ_SIZE - len, "Self-RX:"); for (i = 0; i < hx_s_ic_data->rx_num; i++) { len += snprintf((testdata + len), SZ_SIZE - len, "%5d,", RAW[i + (hx_s_ic_data->tx_num * hx_s_ic_data->rx_num)] ); } len += snprintf((testdata + len), SZ_SIZE - len, "\n"); len += snprintf((testdata + len), SZ_SIZE - len, "Self-TX:"); for (i = 0; i < hx_s_ic_data->tx_num; i++) { len += snprintf((testdata + len), SZ_SIZE - len, "%5d,", RAW[i + (hx_s_ic_data->tx_num * hx_s_ic_data->rx_num) + hx_s_ic_data->rx_num] ); } len += snprintf((testdata + len), SZ_SIZE - len, "\n"); } } len += snprintf((testdata + len), SZ_SIZE - len, "\n%s\n", result); memcpy(&g_rslt_data[g_rslt_data_len], testdata, len); g_rslt_data_len += len; I("%s: g_rslt_data_len=%d!\n", __func__, g_rslt_data_len); /* dbg */ /* for(i = 0; i < SZ_SIZE; i++) * { * I("0x%04X, ", g_rslt_data[i + (now_item * SZ_SIZE)]); * if(i > 0 && (i % 16 == 15)) * PI("\n"); * } */ kfree(testdata); I("%s: End!\n", __func__); return NO_ERR; } static int himax_switch_mode_inspection(int mode) { uint8_t tmp_data[4] = {0}; I("%s: Entering\n", __func__); /*Stop Handshaking*/ hx_s_core_fp._register_write(hx_s_ic_setup._addr_rawdata_buf, tmp_data, 4); /*Swtich Mode*/ switch (mode) { case HX_SORTING: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_SORTING_START; tmp_data[0] = PWD_SORTING_START; break; case HX_OPEN: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_OPEN_START; tmp_data[0] = PWD_OPEN_START; break; case HX_MICRO_OPEN: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_OPEN_START; tmp_data[0] = PWD_OPEN_START; break; case HX_SHORT: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_SHORT_START; tmp_data[0] = PWD_SHORT_START; break; case HX_GAPTEST_RAW: case HX_RAWDATA: case HX_BPN_RAWDATA: case HX_SC: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_RAWDATA_START; tmp_data[0] = PWD_RAWDATA_START; break; case HX_WT_NOISE: case HX_ABS_NOISE: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_NOISE_START; tmp_data[0] = PWD_NOISE_START; break; case HX_ACT_IDLE_RAWDATA: case HX_ACT_IDLE_BPN_RAWDATA: case HX_ACT_IDLE_NOISE: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_ACT_IDLE_START; tmp_data[0] = PWD_ACT_IDLE_START; break; case HX_LP_RAWDATA: case HX_LP_BPN_RAWDATA: case HX_LP_ABS_NOISE: case HX_LP_WT_NOISE: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_LP_START; tmp_data[0] = PWD_LP_START; break; case HX_LP_IDLE_RAWDATA: case HX_LP_IDLE_BPN_RAWDATA: case HX_LP_IDLE_NOISE: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_LP_IDLE_START; tmp_data[0] = PWD_LP_IDLE_START; break; case HX_PEN_MODE_DATA: tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PEN_MODE_START; tmp_data[0] = PEN_MODE_START; break; default: I("%s,Nothing to be done!\n", __func__); break; } if (hx_s_core_fp._assign_sorting_mode != NULL) hx_s_core_fp._assign_sorting_mode(tmp_data); I("%s: End of setting!\n", __func__); return 0; } static void himax_raw_data_dbg(int RAW[]) { uint32_t i = 0; uint32_t j = 0; uint32_t index = 0; for (j = 0; j < hx_s_ic_data->rx_num; j++) { if (j == 0) PI(" RX%2d", j + 1); else PI(" RX%2d", j + 1); } PI("\n"); for (i = 0; i < hx_s_ic_data->tx_num; i++) { PI("TX%2d", i + 1); for (j = 0; j < hx_s_ic_data->rx_num; j++) { PI("%5d ", RAW[index]); index++; } PI("\n"); } for (i = 0; i < hx_s_ic_data->rx_num; i++) { if (i == 0) PI("RX: %2d", RAW[index]); else PI(", %2d", RAW[index]); index++; } PI("\n"); for (i = 0; i < hx_s_ic_data->tx_num; i++) { if (i == 0) PI("TX: %2d", RAW[index]); else PI(", %2d", RAW[index]); index++; } } static uint32_t himax_get_rawdata(int RAW[], uint32_t len, uint8_t checktype) { uint8_t *tmp_rawdata; bool get_raw_rlst; uint32_t i = 0; int Min_DATA = 99999; int Max_DATA = -99999; /* We use two bytes to combine a value of rawdata.*/ tmp_rawdata = kzalloc(sizeof(uint8_t) * (len * 2), GFP_KERNEL); if (tmp_rawdata == NULL) { E("%s: Memory allocation falied!\n", __func__); return HX_INSP_MEMALLCTFAIL; } get_raw_rlst = hx_s_core_fp._get_DSRAM_data(tmp_rawdata, false); if (!get_raw_rlst) goto DIRECT_END; /* Copy Data*/ for (i = 0; i < len; i++) { if (checktype == HX_WT_NOISE || checktype == HX_ABS_NOISE || checktype == HX_ACT_IDLE_NOISE || checktype == HX_LP_WT_NOISE || checktype == HX_LP_ABS_NOISE || checktype == HX_LP_IDLE_NOISE) RAW[i] = ((int8_t)tmp_rawdata[(i * 2) + 1]<<8) + tmp_rawdata[(i * 2)]; else RAW[i] = tmp_rawdata[(i * 2) + 1]<<8 | tmp_rawdata[(i * 2)]; if (i < (len - hx_s_ic_data->rx_num - hx_s_ic_data->tx_num)) { if (i == 0) Min_DATA = Max_DATA = RAW[0]; else if (RAW[i] > Max_DATA) Max_DATA = RAW[i]; else if (RAW[i] < Min_DATA) Min_DATA = RAW[i]; } } I("Max = %5d, Min = %5d\n", Max_DATA, Min_DATA); if (hx_s_ts->debug_log_level & BIT(4)) himax_raw_data_dbg(RAW); DIRECT_END: kfree(tmp_rawdata); if (get_raw_rlst) return HX_INSP_OK; else return HX_INSP_EGETRAW; } static void himax_switch_data_type(uint8_t checktype) { uint8_t datatype = 0x00; if (hx_s_ts->debug_log_level & BIT(4)) { I("%s,Expected type[%d]=%s" , __func__ , checktype, g_hx_inspt_mode[checktype]); } switch (checktype) { case HX_SORTING: datatype = DATA_SORTING; break; case HX_OPEN: datatype = DATA_OPEN; break; case HX_MICRO_OPEN: datatype = DATA_MICRO_OPEN; break; case HX_SHORT: datatype = DATA_SHORT; break; case HX_RAWDATA: case HX_BPN_RAWDATA: case HX_SC: case HX_GAPTEST_RAW: datatype = DATA_RAWDATA; break; case HX_WT_NOISE: case HX_ABS_NOISE: datatype = DATA_NOISE; break; case HX_BACK_NORMAL: datatype = DATA_BACK_NORMAL; break; case HX_ACT_IDLE_RAWDATA: case HX_ACT_IDLE_BPN_RAWDATA: datatype = DATA_ACT_IDLE_RAWDATA; break; case HX_ACT_IDLE_NOISE: datatype = DATA_ACT_IDLE_NOISE; break; case HX_LP_RAWDATA: case HX_LP_BPN_RAWDATA: datatype = DATA_LP_RAWDATA; break; case HX_LP_WT_NOISE: case HX_LP_ABS_NOISE: datatype = DATA_LP_NOISE; break; case HX_LP_IDLE_RAWDATA: case HX_LP_IDLE_BPN_RAWDATA: datatype = DATA_LP_IDLE_RAWDATA; break; case HX_LP_IDLE_NOISE: datatype = DATA_LP_IDLE_NOISE; break; case HX_PEN_MODE_DATA: datatype = DATA_PEN_MODE; break; default: E("Wrong type=%d\n", checktype); break; } hx_s_core_fp._diag_register_set(datatype, 0x00, false); } static void himax_bank_search_set(uint16_t Nframe, uint8_t checktype) { uint8_t tmp_data[4]; /*skip frame 0x100070F4*/ hx_s_core_fp._register_read( hx_s_ic_setup._addr_skip_frame, tmp_data, 4); switch (checktype) { case HX_ACT_IDLE_RAWDATA: case HX_ACT_IDLE_BPN_RAWDATA: case HX_ACT_IDLE_NOISE: if (g_hx_inspt_setting_val[ACT_IDLE_BS_FRAME] > 0) tmp_data[0] = g_hx_inspt_setting_val[ACT_IDLE_BS_FRAME]; else tmp_data[0] = BS_ACT_IDLE; break; case HX_LP_RAWDATA: case HX_LP_BPN_RAWDATA: case HX_LP_ABS_NOISE: case HX_LP_WT_NOISE: if (g_hx_inspt_setting_val[LP_BS_FRAME] > 0) tmp_data[0] = g_hx_inspt_setting_val[LP_BS_FRAME]; else tmp_data[0] = BS_LPWUG; break; case HX_LP_IDLE_RAWDATA: case HX_LP_IDLE_BPN_RAWDATA: case HX_LP_IDLE_NOISE: if (g_hx_inspt_setting_val[LP_IDLE_BS_FRAME] > 0) tmp_data[0] = g_hx_inspt_setting_val[LP_IDLE_BS_FRAME]; else tmp_data[0] = BS_LP_dile; break; case HX_RAWDATA: case HX_BPN_RAWDATA: case HX_SC: if (g_hx_inspt_setting_val[RAW_BS_FRAME] > 0) tmp_data[0] = g_hx_inspt_setting_val[RAW_BS_FRAME]; else tmp_data[0] = BS_RAWDATA; break; case HX_WT_NOISE: case HX_ABS_NOISE: if (g_hx_inspt_setting_val[NOISE_BS_FRAME] > 0) tmp_data[0] = g_hx_inspt_setting_val[NOISE_BS_FRAME]; else tmp_data[0] = BS_NOISE; break; default: tmp_data[0] = BS_OPENSHORT; break; } if (hx_s_ts->debug_log_level & BIT(4)) { I("%s,Now BankSearch Value=%d\n", __func__, tmp_data[0]); } hx_s_core_fp._register_write( hx_s_ic_setup._addr_skip_frame, tmp_data, 4); } void himax_neg_noise_sup(uint8_t *data) { uint8_t tmp_data[4]; /*0x10007FD8 Check support negative value or not */ hx_s_core_fp._register_read( hx_s_ic_setup._addr_neg_noise_sup, tmp_data, 4); if ((tmp_data[3] & 0x04) == 0x04) { hx_parse_assign_cmd(hx_s_ic_setup._data_neg_noise, tmp_data, sizeof(tmp_data)); data[2] = tmp_data[2]; data[3] = tmp_data[3]; } else I("%s Not support negative noise\n", __func__); } static void himax_set_N_frame(uint16_t Nframe, uint8_t checktype) { uint8_t tmp_data[4]; himax_bank_search_set(Nframe, checktype); /*IIR MAX - 0x10007294*/ tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = (uint8_t)((Nframe & 0xFF00) >> 8); tmp_data[0] = (uint8_t)(Nframe & 0x00FF); hx_s_core_fp._register_write(hx_s_ic_setup._addr_set_frame, tmp_data, 4); if (checktype == HX_WT_NOISE || checktype == HX_ABS_NOISE || checktype == HX_LP_WT_NOISE || checktype == HX_LP_ABS_NOISE) hx_s_core_fp._neg_noise_sup(tmp_data); if (hx_s_ts->debug_log_level & BIT(4)) { I("%s,Now N frame Value=0x%02X%02X\n", __func__, tmp_data[1], tmp_data[0]); } hx_s_core_fp._register_write(hx_s_ic_setup._addr_set_frame, tmp_data, 4); } int himax_get_noise_weight_test(uint8_t checktype) { uint8_t tmp_data[4]; uint16_t weight = 0; uint16_t value = 0; uint32_t addr32 = 0x00; /*0x100072C8 weighting value*/ hx_s_core_fp._register_read( hx_s_ic_setup._addr_weight_sup, tmp_data, 4); if (tmp_data[3] != 0x72 || tmp_data[2] != 0xC8) return FW_NOT_READY; value = (tmp_data[1] << 8) | tmp_data[0]; I("%s: value = %d, %d, %d ", __func__, value, tmp_data[2], tmp_data[3]); switch (checktype) { case HX_WT_NOISE: addr32 = hx_s_ic_setup._addr_normal_weight_a; break; case HX_LP_WT_NOISE: addr32 = hx_s_ic_setup._addr_lpwug_weight_a; break; default: I("%s Not support type\n", __func__); } /*Normal:0x1000709C, LPWUG:0x100070A0 weighting threshold*/ hx_s_core_fp._register_read(addr32, tmp_data, 4); weight = tmp_data[0]; hx_s_core_fp._register_read(hx_s_ic_setup._addr_weight_b, tmp_data, 4); tmp_data[1] = tmp_data[1]&0x0F; if (tmp_data[1] == 0) tmp_data[1] = 1; weight = tmp_data[1] * weight;/*0x10007095 weighting threshold*/ I("%s: weight = %d ", __func__, weight); if (value > weight) return ERR_TEST_FAIL; else return 0; } #if !defined(HX_STRESS_SELF_TEST) || !defined(HX_ZERO_FLASH) static uint32_t himax_check_mode(uint8_t checktype) { int ret = 0; uint8_t tmp_data[4] = {0}; uint8_t wait_pwd[2] = {0}; switch (checktype) { case HX_SORTING: wait_pwd[0] = PWD_SORTING_END; wait_pwd[1] = PWD_SORTING_END; break; case HX_OPEN: wait_pwd[0] = PWD_OPEN_END; wait_pwd[1] = PWD_OPEN_END; break; case HX_MICRO_OPEN: wait_pwd[0] = PWD_OPEN_END; wait_pwd[1] = PWD_OPEN_END; break; case HX_SHORT: wait_pwd[0] = PWD_SHORT_END; wait_pwd[1] = PWD_SHORT_END; break; case HX_RAWDATA: case HX_BPN_RAWDATA: case HX_SC: case HX_GAPTEST_RAW: wait_pwd[0] = PWD_RAWDATA_END; wait_pwd[1] = PWD_RAWDATA_END; break; case HX_WT_NOISE: case HX_ABS_NOISE: wait_pwd[0] = PWD_NOISE_END; wait_pwd[1] = PWD_NOISE_END; break; case HX_ACT_IDLE_RAWDATA: case HX_ACT_IDLE_BPN_RAWDATA: case HX_ACT_IDLE_NOISE: wait_pwd[0] = PWD_ACT_IDLE_END; wait_pwd[1] = PWD_ACT_IDLE_END; break; case HX_LP_RAWDATA: case HX_LP_BPN_RAWDATA: case HX_LP_ABS_NOISE: case HX_LP_WT_NOISE: wait_pwd[0] = PWD_LP_END; wait_pwd[1] = PWD_LP_END; break; case HX_LP_IDLE_RAWDATA: case HX_LP_IDLE_BPN_RAWDATA: case HX_LP_IDLE_NOISE: wait_pwd[0] = PWD_LP_IDLE_END; wait_pwd[1] = PWD_LP_IDLE_END; break; case HX_PEN_MODE_DATA: wait_pwd[0] = PEN_MODE_END; wait_pwd[1] = PEN_MODE_END; break; default: E("Wrong type=%d\n", checktype); break; } if (hx_s_core_fp._check_sorting_mode != NULL) { ret = hx_s_core_fp._check_sorting_mode(tmp_data); if (ret != NO_ERR) return ret; } if ((wait_pwd[0] == tmp_data[0]) && (wait_pwd[1] == tmp_data[1])) { I("%s,It had been changed to [%d]=%s\n", __func__, checktype, g_hx_inspt_mode[checktype]); return NO_ERR; } else { return 1; } } #endif #define TEMP_LOG \ "%s:0x%08X,tmp_data[0]=%x,tmp_data[1]=%x,tmp_data[2]=%x,tmp_data[3]=%x\n" static uint32_t himax_wait_sorting_mode(uint8_t checktype) { uint8_t tmp_data[4] = {0}; uint8_t wait_pwd[2] = {0}; int count = 0; int i = 0; int len = (size_t)(sizeof(hx_s_ic_data->dbg_reg_ary)/sizeof(uint32_t)); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:start!\n", __func__); switch (checktype) { case HX_SORTING: wait_pwd[0] = PWD_SORTING_END; wait_pwd[1] = PWD_SORTING_END; break; case HX_OPEN: wait_pwd[0] = PWD_OPEN_END; wait_pwd[1] = PWD_OPEN_END; break; case HX_MICRO_OPEN: wait_pwd[0] = PWD_OPEN_END; wait_pwd[1] = PWD_OPEN_END; break; case HX_SHORT: wait_pwd[0] = PWD_SHORT_END; wait_pwd[1] = PWD_SHORT_END; break; case HX_RAWDATA: case HX_BPN_RAWDATA: case HX_SC: case HX_GAPTEST_RAW: wait_pwd[0] = PWD_RAWDATA_END; wait_pwd[1] = PWD_RAWDATA_END; break; case HX_WT_NOISE: case HX_ABS_NOISE: wait_pwd[0] = PWD_NOISE_END; wait_pwd[1] = PWD_NOISE_END; break; case HX_ACT_IDLE_RAWDATA: case HX_ACT_IDLE_BPN_RAWDATA: case HX_ACT_IDLE_NOISE: wait_pwd[0] = PWD_ACT_IDLE_END; wait_pwd[1] = PWD_ACT_IDLE_END; break; case HX_LP_RAWDATA: case HX_LP_BPN_RAWDATA: case HX_LP_ABS_NOISE: case HX_LP_WT_NOISE: wait_pwd[0] = PWD_LP_END; wait_pwd[1] = PWD_LP_END; break; case HX_LP_IDLE_RAWDATA: case HX_LP_IDLE_BPN_RAWDATA: case HX_LP_IDLE_NOISE: wait_pwd[0] = PWD_LP_IDLE_END; wait_pwd[1] = PWD_LP_IDLE_END; break; case HX_PEN_MODE_DATA: wait_pwd[0] = PEN_MODE_END; wait_pwd[1] = PEN_MODE_END; break; default: I("No Change Mode and now type=%d\n", checktype); break; } I("%s:NowType[%d] = %s, Expected=0x%02X%02X\n", __func__, checktype, g_hx_inspt_mode[checktype], wait_pwd[1], wait_pwd[0]); do { if (hx_s_ts->debug_log_level & BIT(4)) I("%s:start check_sorting_mode!\n", __func__); if (hx_s_core_fp._check_sorting_mode != NULL) hx_s_core_fp._check_sorting_mode(tmp_data); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:end check_sorting_mode!\n", __func__); if ((wait_pwd[0] == tmp_data[0]) && (wait_pwd[1] == tmp_data[1])) return HX_INSP_OK; if (hx_s_ts->debug_log_level & BIT(4)) { for (i = 0; i < len; i++) { hx_s_core_fp._register_read( hx_s_ic_data->dbg_reg_ary[i], tmp_data, DATA_LEN_4); I(TEMP_LOG, __func__, hx_s_ic_data->dbg_reg_ary[i], tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); } I("Now retry %d times!\n", count); } count++; msleep(50); } while (count < 50); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:end\n", __func__); return HX_INSP_ESWITCHMODE; } /* HX_GAP START gap test function */ /* extern int himax_write_to_ic_flash_flow(uint32_t start_addr,*/ /* uint32_t *write_data, uint32_t write_len);*/ static int himax_gap_test_vertical_setting(void) { g_gap_vertical_part[0] = 0; g_gap_vertical_part[1] = 4; g_gap_vertical_part[2] = 8; return NO_ERR; } static void himax_cal_gap_data_vertical(int start, int end_idx, int direct, const uint32_t *org_raw, uint32_t *result_raw) { int i = 0; int rx_num = hx_s_ic_data->rx_num; I("%s:start=%d,end_idx=%d\n", __func__, start, end_idx); for (i = start; i < (start + rx_num*end_idx); i++) { if (direct == 0) { /* up - down */ if (i < start+rx_num) result_raw[i] = 0; else result_raw[i] = org_raw[i-rx_num] - org_raw[i]; } else { /* down - up */ if (i > (start + rx_num*(end_idx-1)-1)) result_raw[i] = 0; else result_raw[i] = org_raw[i+rx_num] - org_raw[i]; } } } static int himax_gap_test_vertical_raw(int test_type, int *org_raw) { int i_partial = 0; int tmp_start = 0; int tmp_end_idx = 0; uint32_t *result_raw = NULL; int i = 0; int ret_val = NO_ERR; int tx_num = hx_s_ic_data->tx_num; int rx_num = hx_s_ic_data->rx_num; g_gap_vertical_part = kcalloc(g_gap_vertical_partial, sizeof(int), GFP_KERNEL); if (g_gap_vertical_part == NULL) { E("%s: Memory allocation falied!\n", __func__); return MEM_ALLOC_FAIL; } result_raw = kcalloc(tx_num*rx_num, sizeof(uint32_t), GFP_KERNEL); if (result_raw == NULL) { E("%s: Memory allocation falied!\n", __func__); ret_val = MEM_ALLOC_FAIL; goto alloc_result_raw_failed; } himax_gap_test_vertical_setting(); I("Print vertical ORG RAW\n"); for (i = 0; i < tx_num*rx_num; i++) { I("%04d,", org_raw[i]); if (i > 0 && i%rx_num == (rx_num-1)) I("\n"); } for (i_partial = 0; i_partial < g_gap_vertical_partial; i_partial++) { tmp_start = g_gap_vertical_part[i_partial]*rx_num; if (i_partial+1 == g_gap_vertical_partial) tmp_end_idx = tx_num - g_gap_vertical_part[i_partial]; else tmp_end_idx = g_gap_vertical_part[i_partial+1] - g_gap_vertical_part[i_partial]; if (i_partial % 2 == 0) himax_cal_gap_data_vertical(tmp_start, tmp_end_idx, 0, org_raw, result_raw); else himax_cal_gap_data_vertical(tmp_start, tmp_end_idx, 1, org_raw, result_raw); } I("Print Vertical New RAW\n"); for (i = 0; i < tx_num*rx_num; i++) { I("%04d,", result_raw[i]); if (i > 0 && i%rx_num == (rx_num-1)) I("\n"); } for (i = 0; i < tx_num*rx_num; i++) { if (result_raw[i] < g_inspt_crtra[IDX_GAP_VER_RAWMIN][i] && result_raw[i] > g_inspt_crtra[IDX_GAP_VER_RAWMAX][i]) { ret_val = NO_ERR - i; break; } } /* himax_write_to_ic_flash_flow(0x1A000,result_raw,tx_num*rx_num); */ kfree(result_raw); alloc_result_raw_failed: kfree(g_gap_vertical_part); g_gap_vertical_part = NULL; return ret_val; } static int himax_gap_test_horizontal_setting(void) { g_gap_horizontal_part[0] = 0; g_gap_horizontal_part[1] = 8; g_gap_horizontal_part[2] = 24; return NO_ERR; } static void himax_cal_gap_data_horizontal(int start, int end_idx, int direct, const uint32_t *org_raw, uint32_t *result_raw) { int i; int j = 0; int rx_num = hx_s_ic_data->rx_num; int tx_num = hx_s_ic_data->tx_num; I("start=%d,end_idx=%d\n", start, end_idx); for (j = 0; j < tx_num; j++) { for (i = (start + (j*rx_num)); i < (start + (j*rx_num) + end_idx); i++) { /* left - right */ if (direct == 0) { if (i == (start + (j*rx_num))) result_raw[i] = 0; else result_raw[i] = org_raw[i-1] - org_raw[i]; } else { /* right - left */ if (i == ((start + (j*rx_num) + end_idx) - 1)) result_raw[i] = 0; else result_raw[i] = org_raw[i + 1] - org_raw[i]; } } } } static int himax_gap_test_honrizontal_raw(int test_type, int *raw) { int rx_num = hx_s_ic_data->rx_num; int tx_num = hx_s_ic_data->tx_num; int tmp_start = 0; int tmp_end_idx = 0; int i_partial = 0; int *result_raw; int i = 0; int ret_val = NO_ERR; g_gap_horizontal_part = kcalloc(g_gap_horizontal_partial, sizeof(int), GFP_KERNEL); if (g_gap_horizontal_part == NULL) { E("%s: Memory allocation falied!\n", __func__); return MEM_ALLOC_FAIL; } result_raw = kcalloc(tx_num*rx_num, sizeof(int), GFP_KERNEL); if (result_raw == NULL) { E("%s: Memory allocation falied!\n", __func__); ret_val = MEM_ALLOC_FAIL; goto alloc_result_raw_failed; } himax_gap_test_horizontal_setting(); I("Print Horizontal ORG RAW\n"); for (i = 0; i < tx_num*rx_num; i++) { I("%04d,", raw[i]); if (i > 0 && i%rx_num == (rx_num-1)) I("\n"); } for (i_partial = 0; i_partial < g_gap_horizontal_partial; i_partial++) { tmp_start = g_gap_horizontal_part[i_partial]; if (i_partial+1 == g_gap_horizontal_partial) tmp_end_idx = rx_num - g_gap_horizontal_part[i_partial]; else tmp_end_idx = g_gap_horizontal_part[i_partial+1] - g_gap_horizontal_part[i_partial]; if (i_partial % 2 == 0) himax_cal_gap_data_horizontal(tmp_start, tmp_end_idx, 0, raw, result_raw); else himax_cal_gap_data_horizontal(tmp_start, tmp_end_idx, 1, raw, result_raw); } I("Print Horizontal New RAW\n"); for (i = 0; i < tx_num*rx_num; i++) { I("%04d,", result_raw[i]); if (i > 0 && i%rx_num == (rx_num-1)) I("\n"); } for (i = 0; i < tx_num*rx_num; i++) { if (result_raw[i] < g_inspt_crtra[IDX_GAP_HOR_RAWMIN][i] && result_raw[i] > g_inspt_crtra[IDX_GAP_HOR_RAWMAX][i]) { ret_val = NO_ERR - i; break; } } /* himax_write_to_ic_flash_flow(0x1A800,result_raw,tx_num*rx_num); */ kfree(result_raw); alloc_result_raw_failed: kfree(g_gap_horizontal_part); g_gap_horizontal_part = NULL; return ret_val; } static uint32_t himax_data_compare(uint8_t checktype, int *RAW) { int i = 0; int idx_max = 0; int idx_min = 0; int self_idx_max = 0; int self_idx_min = 0; int block_num = hx_s_ic_data->tx_num * hx_s_ic_data->rx_num; int self_block_num = hx_s_ic_data->tx_num + hx_s_ic_data->rx_num; uint16_t palm_num = 0; uint16_t noise_count = 0; uint32_t ret_val = HX_INSP_OK; int wet_val[2] = {0}; switch (checktype) { case HX_SORTING: idx_min = IDX_SORTMIN; break; case HX_OPEN: idx_max = IDX_OPENMAX; idx_min = IDX_OPENMIN; if (hx_check_self_test_item(checktype)) { self_idx_min = IDX_SELF_OPENMIN; self_idx_max = IDX_SELF_OPENMAX; } break; case HX_MICRO_OPEN: idx_max = IDX_M_OPENMAX; idx_min = IDX_M_OPENMIN; break; case HX_SHORT: idx_max = IDX_SHORTMAX; idx_min = IDX_SHORTMIN; if (hx_check_self_test_item(checktype)) { self_idx_min = IDX_SELF_SHORTMIN; self_idx_max = IDX_SELF_SHORTMAX; } break; case HX_RAWDATA: idx_max = IDX_RAWMAX; idx_min = IDX_RAWMIN; break; case HX_BPN_RAWDATA: idx_max = IDX_BPN_RAWMAX; idx_min = IDX_BPN_RAWMIN; if (hx_check_self_test_item(checktype)) { self_idx_min = IDX_SELF_BPN_RAWMIN; self_idx_max = IDX_SELF_BPN_RAWMAX; } break; case HX_SC: idx_max = IDX_SCMAX; idx_min = IDX_SCMIN; break; case HX_WT_NOISE: idx_max = IDX_WT_NOISEMAX; idx_min = IDX_WT_NOISEMIN; if (hx_check_self_test_item(checktype)) { self_idx_min = IDX_SELF_WT_NOISEMIN; self_idx_max = IDX_SELF_WT_NOISEMAX; } break; case HX_ABS_NOISE: idx_max = IDX_ABS_NOISEMAX; idx_min = IDX_ABS_NOISEMIN; if (hx_check_self_test_item(checktype)) { self_idx_min = IDX_SELF_ABS_NOISEMIN; self_idx_max = IDX_SELF_ABS_NOISEMAX; } break; case HX_GAPTEST_RAW: break; case HX_ACT_IDLE_RAWDATA: idx_max = IDX_ACT_IDLE_RAWDATA_MAX; idx_min = IDX_ACT_IDLE_RAWDATA_MIN; break; case HX_ACT_IDLE_BPN_RAWDATA: idx_max = IDX_ACT_IDLE_RAW_BPN_MAX; idx_min = IDX_ACT_IDLE_RAW_BPN_MIN; break; case HX_ACT_IDLE_NOISE: idx_max = IDX_ACT_IDLE_NOISE_MAX; idx_min = IDX_ACT_IDLE_NOISE_MIN; break; case HX_LP_RAWDATA: idx_max = IDX_LP_RAWDATA_MAX; idx_min = IDX_LP_RAWDATA_MIN; break; case HX_LP_BPN_RAWDATA: idx_max = IDX_LP_RAW_BPN_MAX; idx_min = IDX_LP_RAW_BPN_MIN; break; case HX_PEN_MODE_DATA: self_idx_min = IDX_PEN_MODE_DATAMIN; self_idx_max = IDX_PEN_MODE_DATAMAX; break; case HX_LP_WT_NOISE: idx_max = IDX_LP_WT_NOISEMAX; idx_min = IDX_LP_WT_NOISEMIN; break; case HX_LP_ABS_NOISE: idx_max = IDX_LP_NOISE_ABS_MAX; idx_min = IDX_LP_NOISE_ABS_MIN; break; case HX_LP_IDLE_RAWDATA: idx_max = IDX_LP_IDLE_RAWDATA_MAX; idx_min = IDX_LP_IDLE_RAWDATA_MIN; break; case HX_LP_IDLE_BPN_RAWDATA: idx_max = IDX_LP_IDLE_RAW_BPN_MAX; idx_min = IDX_LP_IDLE_RAW_BPN_MIN; break; case HX_LP_IDLE_NOISE: idx_max = IDX_LP_IDLE_NOISE_MAX; idx_min = IDX_LP_IDLE_NOISE_MIN; break; default: E("Wrong type=%d\n", checktype); break; } /*data process*/ switch (checktype) { case HX_SORTING: for (i = 0; i < block_num; i++) g_inspt_crtra[idx_max][i] = 999999; break; case HX_BPN_RAWDATA: case HX_ACT_IDLE_BPN_RAWDATA: case HX_LP_BPN_RAWDATA: case HX_LP_IDLE_BPN_RAWDATA: for (i = 0; i < block_num; i++) RAW[i] = (int)RAW[i] * 100 / g_dc_max; if (hx_check_self_test_item(checktype)) { for (i = 0; i < self_block_num; i++) RAW[i + block_num] = (int)RAW[i + block_num] * 100 / g_dc_max; } break; case HX_SC: for (i = 0; i < block_num; i++) { RAW[i] = ((int)RAW[i] - g_inspt_crtra[IDX_SC_GOLDEN][i]) * 100 / g_inspt_crtra[IDX_SC_GOLDEN][i]; } break; } /*data campare*/ switch (checktype) { case HX_GAPTEST_RAW: if (himax_gap_test_vertical_raw(HX_GAPTEST_RAW, RAW) != NO_ERR) { E("%s: HX_GAPTEST_RAW FAIL\n", __func__); ret_val = HX_INSP_ESPEC; break; } if (himax_gap_test_honrizontal_raw(HX_GAPTEST_RAW, RAW) != NO_ERR) { E("%s: HX_GAPTEST_RAW FAIL\n", __func__); ret_val = HX_INSP_ESPEC; break; } break; case HX_WT_NOISE: case HX_LP_WT_NOISE: noise_count = 0; if (checktype == HX_LP_WT_NOISE) hx_s_core_fp._get_noise_base(true, wet_val); else hx_s_core_fp._get_noise_base(false, wet_val); NOISEMAX = wet_val[0]; g_recal_thx = wet_val[1]; I("NOISEMAX = %d, g_recal_thx=%d\n", NOISEMAX, g_recal_thx); palm_num = hx_s_core_fp._get_palm_num(); for (i = 0; i < (hx_s_ic_data->tx_num * hx_s_ic_data->rx_num); i++) { if ((int)RAW[i] > NOISEMAX) { E("[%d] = Raw=%d, NOISEMAX=%d\n", i, RAW[i], NOISEMAX); noise_count++; } } I("noise_count=%d\n", noise_count); if (noise_count > palm_num) { E("%s: noise test FAIL\n", __func__); ret_val = HX_INSP_ESPEC; break; } /* snprintf(g_start_log, 256 * sizeof(char), "\n Threshold = %d\n", * NOISEMAX); */ /*Check weightingt*/ if (hx_s_core_fp._get_noise_weight_test(checktype) < 0) { I("%s: %s FAIL %X\n", __func__, g_hx_inspt_mode[checktype], ret_val); ret_val = HX_INSP_ESPEC; break; } /*Check negative side noise*/ for (i = 0; i < block_num; i++) { if ((int)RAW[i] > (g_inspt_crtra[idx_max][i] * NOISEMAX / 100) || (int)RAW[i] < (g_inspt_crtra[idx_min][i] * g_recal_thx / 100)) { if (hx_s_ts->debug_log_level & BIT(4)) { E(FAIL_IN_INDEX_CRTRA, __func__, g_hx_inspt_mode[checktype], i , g_inspt_crtra[idx_max][i] , g_inspt_crtra[idx_min][i] , RAW[i]); } else { E(FAIL_IN_INDEX, __func__, g_hx_inspt_mode[checktype], i); } ret_val = HX_INSP_ESPEC; break; } } if (ret_val != HX_INSP_ESPEC && (hx_check_self_test_item(checktype))) { if (hx_s_ts->debug_log_level & BIT(4)) I("in SELF of %s\n", g_hx_inspt_mode[checktype]); for (i = 0; i < self_block_num; i++) { if ((int)RAW[i + block_num] > (g_inspt_crtra[self_idx_max][i] * NOISEMAX / 100) || (int)RAW[i + block_num] < (g_inspt_crtra[self_idx_min][i] * g_recal_thx / 100)) { if (hx_s_ts->debug_log_level & BIT(4)) { E(FAIL_IN_INDEX_CRTRA, __func__, g_hx_inspt_mode[checktype], i , g_inspt_crtra[self_idx_max][i] , g_inspt_crtra[self_idx_min][i] , RAW[i + block_num]); } else { E(FAIL_IN_INDEX, __func__, g_hx_inspt_mode[checktype], i); } ret_val = HX_INSP_ESPEC; break; } } } break; case HX_LP_IDLE_RAWDATA: case HX_LP_IDLE_BPN_RAWDATA: case HX_LP_IDLE_NOISE: case HX_ACT_IDLE_RAWDATA: case HX_ACT_IDLE_BPN_RAWDATA: case HX_ACT_IDLE_NOISE: block_num = hx_s_ic_data->ic_adc_num; for (i = 0; i < block_num; i++) { if ((int)RAW[i] > g_inspt_crtra[idx_max][i] || (int)RAW[i] < g_inspt_crtra[idx_min][i]) { if (hx_s_ts->debug_log_level & BIT(4)) { E(FAIL_IN_INDEX_CRTRA, __func__, g_hx_inspt_mode[checktype], i , g_inspt_crtra[idx_max][i] , g_inspt_crtra[idx_min][i] , RAW[i]); } else { E(FAIL_IN_INDEX, __func__, g_hx_inspt_mode[checktype], i); } ret_val = HX_INSP_ESPEC; break; #ifdef HX_INSPT_DBG if ((hx_s_ts->debug_log_level & BIT(4))) { I("%s,type=%s, idx[%d]=%d\n", __func__, g_hx_inspt_mode[checktype], i, RAW[i]); I("%s, crteria,max=%d,min=%d\n", __func__, g_inspt_crtra[idx_max][i], g_inspt_crtra[idx_min][i]); } #endif } } break; case HX_SORTING: case HX_OPEN: case HX_MICRO_OPEN: case HX_SHORT: case HX_RAWDATA: case HX_BPN_RAWDATA: case HX_SC: case HX_ABS_NOISE: case HX_LP_RAWDATA: case HX_LP_BPN_RAWDATA: case HX_LP_ABS_NOISE: for (i = 0; i < block_num; i++) { if ((int)RAW[i] > g_inspt_crtra[idx_max][i] || (int)RAW[i] < g_inspt_crtra[idx_min][i]) { if (hx_s_ts->debug_log_level & BIT(4)) { E(FAIL_IN_INDEX_CRTRA, __func__, g_hx_inspt_mode[checktype], i , g_inspt_crtra[idx_max][i] , g_inspt_crtra[idx_min][i] , RAW[i]); } else { E(FAIL_IN_INDEX, __func__, g_hx_inspt_mode[checktype], i); } ret_val = HX_INSP_ESPEC; break; } } if ((ret_val != HX_INSP_ESPEC) && (hx_check_self_test_item(checktype))) { if (hx_s_ts->debug_log_level & BIT(4)) I("in SELF of %s\n", g_hx_inspt_mode[checktype]); for (i = 0; i < self_block_num; i++) { if ((int)RAW[i + block_num] > g_inspt_crtra[self_idx_max][i] || (int)RAW[i + block_num] < g_inspt_crtra[self_idx_min][i]) { if (hx_s_ts->debug_log_level & BIT(4)) { E(FAIL_IN_INDEX_CRTRA, __func__, g_hx_inspt_mode[checktype], i, g_inspt_crtra[self_idx_max][i], g_inspt_crtra[self_idx_min][i], RAW[i + block_num]); } else { E(FAIL_IN_INDEX, __func__, g_hx_inspt_mode[checktype], i); } ret_val = HX_INSP_ESPEC; break; } } #ifdef HX_INSPT_DBG if ((hx_s_ts->debug_log_level & BIT(4))) { I("%s,type=%s, idx[%d]=%d\n", __func__, g_hx_inspt_mode[checktype], i, RAW[i]); I("%s, crteria,max=%d,min=%d\n", __func__, g_inspt_crtra[idx_max][i], g_inspt_crtra[idx_min][i]); } #endif } break; case HX_PEN_MODE_DATA: if (hx_s_ts->debug_log_level & BIT(4)) I("test type=%s\n", g_hx_inspt_mode[checktype]); for (i = 0; i < self_block_num; i++) { if ((int)RAW[i + block_num] > g_inspt_crtra[self_idx_max][i] || (int)RAW[i + block_num] < g_inspt_crtra[self_idx_min][i]) { if (hx_s_ts->debug_log_level & BIT(4)) { E(FAIL_IN_INDEX_CRTRA, __func__, g_hx_inspt_mode[checktype], i, g_inspt_crtra[self_idx_max][i], g_inspt_crtra[self_idx_min][i], RAW[i + block_num]); } else { E(FAIL_IN_INDEX, __func__, g_hx_inspt_mode[checktype], i); } ret_val = HX_INSP_ESPEC; break; } } #ifdef HX_INSPT_DBG if ((hx_s_ts->debug_log_level & BIT(4))) { I("%s,type=%s, idx[%d]=%d\n", __func__, g_hx_inspt_mode[checktype], i, RAW[i]); I("%s, crteria,max=%d,min=%d\n", __func__, g_inspt_crtra[idx_max][i], g_inspt_crtra[idx_min][i]); } #endif break; default: E("Wrong type[%d] = %s\n", checktype, g_hx_inspt_mode[checktype]); break; } I("%s: %s %s\n", __func__, g_hx_inspt_mode[checktype], (ret_val == HX_INSP_OK)?"PASS":"FAIL"); return ret_val; } static int himax_get_max_dc(void) { uint8_t tmp_data[DATA_LEN_4]; int dc_max = 0; hx_s_core_fp._register_read(hx_s_ic_setup._addr_max_dc, tmp_data, DATA_LEN_4); I("%s: tmp_data[0-3] = %02x%02x%02x%02x\n", __func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); dc_max = tmp_data[3]<<24 | tmp_data[2]<<16 | tmp_data[1]<<8 | tmp_data[0]; I("%s: dc max = %d\n", __func__, dc_max); return dc_max; } /* HX_GAP END*/ static uint32_t mpTestFunc(uint8_t checktype, uint32_t datalen) { uint32_t len = 0; uint32_t *RAW = NULL; int n_frame = 0; uint32_t ret_val = NO_ERR; int check_sort_sts = NO_ERR; bool self = false; #if defined(HX_RETRY_SELF_TEST) int retry = 0; #endif /*uint16_t* pInspectGridData = &gInspectGridData[0];*/ /*uint16_t* pInspectNoiseData = &gInspectNoiseData[0];*/ I("Now Check type = %d\n", checktype); RAW = kcalloc(datalen, sizeof(uint32_t), GFP_KERNEL); if (RAW == NULL) { E("%s, Failed to allocate memory\n", __func__); return HX_INSP_MEMALLCTFAIL; } len += snprintf(g_start_log+len, sizeof(g_start_log) - len, "\n%s\n", g_hx_inspt_mode[checktype]); if (checktype >= HX_LP_WT_NOISE) { I("%s,Check status in Screen-Off test items\n", __func__); if (hx_s_ts->suspended) { if (hx_s_ts->debug_log_level & BIT(4)) I("%s, in Suspend!\n", __func__); } else { E("%s, Now is resume, Fail!\n", __func__); ret_val = HX_INSP_ESCREEN; goto fail_wait_sorting_mode; } } else { I("%s,Check status in Screen-On test items\n", __func__); if (hx_s_ts->suspended) { E("%s, Now is Suspend, Fail!\n", __func__); ret_val = HX_INSP_ESCREEN; goto fail_wait_sorting_mode; } else { if (hx_s_ts->debug_log_level & BIT(4)) I("%s, in Resume!\n", __func__); } } #if defined(HX_STRESS_SELF_TEST) check_sort_sts = 1; #else check_sort_sts = himax_check_mode(checktype); if (check_sort_sts < NO_ERR) { ret_val = HX_INSP_ESWITCHMODE; goto fail_wait_sorting_mode; } #endif #if defined(HX_RETRY_SELF_TEST) fail_retry: if (retry >= 1) check_sort_sts = 1; #endif if (check_sort_sts) { /*himax_check_mode(checktype);*/ I("Need Change Mode ,target=%s\n", g_hx_inspt_mode[checktype]); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:start sense off!\n", __func__); hx_s_core_fp._sense_off(true); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:end sense off!\n", __func__); #if !defined(HX_ZERO_FLASH) hx_s_core_fp._turn_on_mp_func(1); if (hx_s_core_fp._reload_disable != NULL) hx_s_core_fp._reload_disable(1); #endif himax_switch_mode_inspection(checktype); switch (checktype) { case HX_WT_NOISE: case HX_ABS_NOISE: if (g_hx_inspt_setting_val[NFRAME] > 0) n_frame = g_hx_inspt_setting_val[NFRAME]; else n_frame = NOISEFRAME; break; case HX_ACT_IDLE_RAWDATA: case HX_ACT_IDLE_NOISE: case HX_ACT_IDLE_BPN_RAWDATA: if (g_hx_inspt_setting_val[IDLE_NFRAME] > 0) n_frame = g_hx_inspt_setting_val[IDLE_NFRAME]; else n_frame = NORMAL_IDLE_RAWDATA_NOISEFRAME; break; case HX_LP_RAWDATA: case HX_LP_BPN_RAWDATA: if (g_hx_inspt_setting_val[LP_RAW_NFRAME] > 0) n_frame = g_hx_inspt_setting_val[LP_RAW_NFRAME]; else n_frame = LP_RAWDATAFRAME; break; case HX_LP_WT_NOISE: case HX_LP_ABS_NOISE: if (g_hx_inspt_setting_val[LP_NOISE_NFRAME] > 0) n_frame = g_hx_inspt_setting_val[LP_NOISE_NFRAME]; else n_frame = LP_NOISEFRAME; break; case HX_LP_IDLE_RAWDATA: case HX_LP_IDLE_BPN_RAWDATA: if (g_hx_inspt_setting_val[LP_IDLE_RAW_NFRAME] > 0) n_frame = g_hx_inspt_setting_val[LP_IDLE_RAW_NFRAME]; else n_frame = LP_IDLE_RAWDATAFRAME; break; case HX_LP_IDLE_NOISE: if (g_hx_inspt_setting_val[LP_IDLE_NOISE_NFRAME] > 0) n_frame = g_hx_inspt_setting_val[LP_IDLE_NOISE_NFRAME]; else n_frame = LP_IDLE_NOISEFRAME; break; case HX_PEN_MODE_DATA: n_frame = PEN_MODE_RAWDATAFRAME; break; default: n_frame = OTHERSFRAME; } himax_set_N_frame(n_frame, checktype); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:start sense on!\n", __func__); hx_s_core_fp._sense_on(1); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:end sense on!\n", __func__); } ret_val = himax_wait_sorting_mode(checktype); if (ret_val) { #if defined(HX_RETRY_SELF_TEST) if (retry < 3) { I("%s: himax_wait_sorting_mode FAIL, retry=%d\n", __func__, retry++); goto fail_retry; } #endif E("%s: himax_wait_sorting_mode FAIL\n", __func__); goto fail_wait_sorting_mode; } himax_switch_data_type(checktype); ret_val = himax_get_rawdata(RAW, datalen, checktype); if (ret_val) { #if defined(HX_RETRY_SELF_TEST) if (retry < 3) { himax_switch_data_type(HX_BACK_NORMAL); I("%s: himax_get_rawdata FAIL, retry=%d\n", __func__, retry++); goto fail_retry; } #endif E("%s: himax_get_rawdata FAIL\n", __func__); } /* back to normal */ himax_switch_data_type(HX_BACK_NORMAL); if (ret_val) { E("%s: himax_get_rawdata FAIL\n", __func__); goto fail_get_rawdata; } /*get Max DC from FW*/ g_dc_max = himax_get_max_dc(); I("%s: Init OK, start to test!\n", __func__); ret_val = himax_data_compare(checktype, RAW); himax_get_arraydata_edge(RAW); len += snprintf(g_start_log + len, sizeof(g_start_log) - len, "\n arraydata_min1 = %d,", arraydata_min1); len += snprintf(g_start_log + len, sizeof(g_start_log) - len, " arraydata_min2 = %d,", arraydata_min2); len += snprintf(g_start_log + len, sizeof(g_start_log) - len, " arraydata_min3 = %d,", arraydata_min3); len += snprintf(g_start_log + len, sizeof(g_start_log) - len, "\n arraydata_max1 = %d,", arraydata_max1); len += snprintf(g_start_log + len, sizeof(g_start_log) - len, " arraydata_max2 = %d,", arraydata_max2); len += snprintf(g_start_log + len, sizeof(g_start_log) - len, " arraydata_max3 = %d\n", arraydata_max3); fail_get_rawdata: fail_wait_sorting_mode: if (!ret_val) {/*PASS*/ snprintf(g_rslt_log, 256 * sizeof(char), "\n%s%s\n", g_hx_inspt_mode[checktype], ":Test Pass!"); I("pass write log\n"); } else {/*FAIL*/ snprintf(g_rslt_log, 256 * sizeof(char), "\n%s%s\n", g_hx_inspt_mode[checktype], ":Test Fail!"); I("fail write log\n"); } if (checktype == HX_PEN_MODE_DATA || hx_check_self_test_item(checktype)) self = true; hx_test_data_get(RAW, g_start_log, g_rslt_log, ret_val, self); kfree(RAW); return ret_val; } /* get idx of criteria whe parsing file */ int hx_find_crtra_id(char *input) { int i = 0; int result = 0; for (i = 0 ; i < HX_CRITERIA_SIZE ; i++) { if (strcmp(g_hx_inspt_crtra_name[i], input) == 0) { result = i; I("find the str=%s,idx=%d\n", g_hx_inspt_crtra_name[i], i); break; } } if (i > (HX_CRITERIA_SIZE - 1)) { E("%s: find Fail!\n", __func__); return LENGTH_FAIL; } return result; } static int hx_crtra_get(char *result, int himax_count_type, int comprae_data) { int temp = 0; int chk; chk = kstrtoint(result, 10, &temp); if (chk) { E("%s:addr kstrtoint return fail!\n", __func__); temp = -9487; } if (temp != -9487) g_inspt_crtra[himax_count_type][comprae_data] = temp; else { I("%s: Parsing Fail in %d, rslt = %d, str=%s\n", __func__, comprae_data, temp, result); return HX_INSP_EFILE; } return HX_INSP_OK; } static int hx_check_criteria(const struct firmware *file_entry, const char *start_str, int tx_num, int rx_num) { int now_pos = 0; int result = NO_ERR; int rx_count = 0; int tx_count = 0; int i = 0; int flag_non_comma = 0; now_pos = (int) (start_str - (char *)file_entry->data); /* Count RX number in criteria */ for (i = 0; now_pos + i < file_entry->size; i++) { if (*(file_entry->data + (now_pos + i)) >= 'A' && *(file_entry->data + (now_pos + i)) <= 'Z') { if (hx_s_ts->debug_log_level & BIT(4)) I("%s, get the character: %c!\n", __func__, *(file_entry->data + (now_pos + i))); break; } if (*(file_entry->data + (now_pos + i)) == ',') { if (flag_non_comma != 0) { flag_non_comma = 0; rx_count++; // I("%s: rx++!\n", __func__); continue; } else { // I("%s: , but there is no data\n", __func__); continue; } } /* reduce the last of sign:',' * but now determine it is the fail format * if (*(file_entry->data + (now_pos + i - 1 )) == ',' * && *(file_entry->data + (now_pos + i)) == '\n') * rx_count--; * if (*(file_entry->data + (now_pos + i - 1 )) == ',' * && *(file_entry->data + (now_pos + i)) == '\r') * rx_count--; */ if (*(file_entry->data + (now_pos + i)) == '\n' || *(file_entry->data + (now_pos + i)) == '\r') { if (flag_non_comma) rx_count++; I("%s:new line, skip\n", __func__); break; } flag_non_comma++; } if (rx_count != rx_num) { E("%s,RX Error, parse size is %d, but this is %d!\n", __func__, rx_count, rx_num); result = HX_INSP_EFILE; goto END; } /* Count TX number in criteria*/ flag_non_comma = 0; for (i = 0; now_pos + i < file_entry->size; i++) { if (hx_check_char_val(*(file_entry->data + (now_pos + i))) < NO_ERR) { if (hx_s_ts->debug_log_level & BIT(4)) I("%s,TX collect over, get char: %c!\n", __func__, *(file_entry->data + (now_pos + i))); break; } if (*(file_entry->data + (now_pos + i)) == '\n') tx_count++; } if (tx_count != tx_num) { E("%s,TX Error, parse size is %d, but this is %d!\n", __func__, tx_count, tx_num); result = HX_INSP_EFILE; goto END; } I("%s:parse TX count is %d, RX count is %d!\n", __func__, tx_count, rx_count); END: return result; } static int himax_parse_criteria_str(int match_start, int hx_str_len, const struct firmware *file_entry, int tx_num, int rx_num) { int err = HX_INSP_OK; char result[100] = {0}; char str_rslt[100] = {0}; char str_len = 0; char *str_addr = NULL; int str_flag = 1; int i, j = 0; //, k int crtra_id = 0; int mul_num = tx_num * rx_num; int flag = 1; int temp; char *str_data; int now_pointer_file; if (hx_s_ts->debug_log_level & BIT(4)) I("%s,Entering\n", __func__); str_data = (char *)(file_entry->data + match_start); memcpy(&str_rslt[0], str_data, hx_str_len); crtra_id = hx_find_crtra_id(str_rslt); if (crtra_id == -1) { E("Please check criteria file again!\n"); return HX_INSP_EFILE; } g_inspt_crtra_flag[crtra_id] = 1; str_data = str_data + hx_str_len + 1; if (hx_check_criteria(file_entry, str_data, tx_num, rx_num) == HX_INSP_EFILE) return HX_INSP_EFILE; /* Check the criteria file OK or not */ for (i = 0; i < mul_num; i++) { if (i <= mul_num - 2) { now_pointer_file = (int) (str_data - (char *)file_entry->data); /* if the search counter is over than file size, * broken the work */ if ((now_pointer_file >= file_entry->size) && now_pointer_file > 0) { E("Over file size 1 !\n"); return HX_INSP_EFILE; } while (flag) { /* Check search counter is over * than file size or not, * broken the work */ if (now_pointer_file + flag >= (int)file_entry->size) { E("Over file size 2!\n"); return HX_INSP_EFILE; } if (hx_check_char_val(*(str_data+flag)) < NO_ERR) { E("%s,Need INT but it's str=%s:%c\n", __func__, str_rslt, *(str_data+flag)); return HX_INSP_EFILE; } /* the starting of value must be ',' * so using this sign to start get content value */ if (*(str_data + flag) == ',') { str_addr = str_data + flag; flag = 1; break; } flag++; } /* * When size of comma sign * larger than size of value */ if (*(str_data) == ',' || *(str_data) == '\n' || *(str_data) == '\r') { str_data = str_data + flag; i--; continue; } if (str_addr == NULL) continue; /* determine the full content * and assign to other container */ str_flag = 1; str_len = str_addr - str_data; for (j = 1; j <= str_len; j++) { if ((*(str_data + j) == '\r' || *(str_data + j) == '\n' || *(str_data + j) == '\0')) { memset(result, 0, 100); memcpy(&result[0], str_data, j); str_flag = 0; break; } } if (str_flag) { memset(result, 0, 100); memcpy(&result[0], str_data, str_len); } /* parse to content string */ err = hx_crtra_get(result, crtra_id, i); if (err != HX_INSP_OK) { E("%s:Get crrteria Fail!!\n", __func__); return HX_INSP_EFILE; } str_data = str_addr + 1; } else{ /* last data of mutual */ temp = 1; while (hx_check_char_val((*(str_data + temp))) > NO_ERR) temp++; str_len = temp; memset(result, 0, 100); memcpy(&result[0], str_data, str_len); err = hx_crtra_get(result, crtra_id, mul_num - 1); if (err != HX_INSP_OK) { E("%s:Get crrteria Fail!\n", __func__); return HX_INSP_EFILE; } } } if (hx_s_ts->debug_log_level & BIT(4)) I("%s,END\n", __func__); return err; /* parsing Criteria end */ } static int himax_test_item_parse(char *str_data, int str_size) { int size = str_size; char *str_ptr = str_data; char *end_ptr = NULL; int i = 0; int ret = HX_INSP_EFILE; I("%s,str_data: %p, str_size: %d\n", __func__, str_data, str_size); do { str_ptr = strnstr(str_ptr, "HIMAX", size); end_ptr = strnstr(str_ptr, "\x0d\x0a", size); if (str_ptr != NULL && end_ptr != NULL) { while (g_hx_inspt_mode[i]) { if (strncmp(str_ptr, g_hx_inspt_mode[i], end_ptr - str_ptr) == 0) { I("%s,Find item : %s\n", __func__, g_hx_inspt_mode[i]); g_test_item_flag[i] = 1; ret = HX_INSP_OK; break; } i++; } size = str_size - (end_ptr - str_data); str_ptr = end_ptr++; i = 0; } else { I("%s,Can't find %s or %s\n", __func__, "HIMAX", "\x0d\x0a"); break; } } while (size > strlen("HIMAX")); return ret; } static int strcpy_idx(char *str, char *start, int end_idx) { int i = 0; int start_idx = 0; char *result; int size = 0; int ret = -1; if (str == NULL) { E("%s, input string is null!\n", __func__); return ret; } start_idx = (int)strcspn(str, start); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:start_idx = %d, end_idx = %d\n", __func__, start_idx, end_idx); if (end_idx < start_idx) { E("%s, end < start, fail\n", __func__); return ret; } result = kzalloc(sizeof(char) * (end_idx - start_idx), GFP_KERNEL); /* skip index 0, because start(char) doesn't include*/ size = end_idx - start_idx - 1; size = size > 0 ? size : 0; for (i = 0; i < size; i++) result[i] = str[(start_idx + 1) + i]; if (hx_s_ts->debug_log_level & BIT(4)) I("%s:result=%s\n", __func__, result); memset(str, 0x00, strlen(str)); memcpy(&str[0], &result[0], sizeof(char) * strlen(result)); kfree(result); return NO_ERR; } static int himax_parse_criteria_setting(const struct firmware *file_entry) { int i = 0, j = 0; int chk; int result = -1; int match_start = -1; int match_end = -1; char *find_start; char *find_end; char *line; int test_int = 0; int comm_1st = -1; line = kzalloc(sizeof(char) * 128, GFP_KERNEL); /* check all of item in the csv with g_hx_inspt_setting_name */ while (g_hx_inspt_setting_name[i] != NULL) { memset(line, 0x00, sizeof(char) * 128); /* check the name of item */ find_start = strnstr(file_entry->data, g_hx_inspt_setting_name[i], file_entry->size); if (find_start == NULL) { I("%s, Can't find %s, skip\n", __func__, g_hx_inspt_setting_name[i]); result = -1; i++; continue; } else match_start = (int)(find_start - (char *)file_entry->data); if (match_start >= 0) { memcpy(line, &file_entry->data[match_start], sizeof(char) * 128); } else { I("%s, start wrong:%s = %d, skip\n", __func__, g_hx_inspt_setting_name[i], match_start); result = -1; i++; continue; } for (j = 0; j < 128; j++) { if (comm_1st < 0) { if (line[j] == ',') comm_1st = j; else continue; } else { if (line[j] == ',' || line[j] == '\r') { line[j] = '\n'; break; } } } comm_1st = -1; /* get the end of line*/ find_end = strnchr(line, 128, '\n'); if (find_end == NULL) { I("%s, Can't find eol, skip\n", __func__); result = -1; i++; continue; } else match_end = (int)(find_end - line); if (match_end >= 128 || match_end <= 0) { I("%s, end wrong:%s = %d, skip\n", __func__, g_hx_inspt_setting_name[i], match_end); result = -1; i++; continue; } else line[match_end] = '\0'; /* Define the end of Line, * before NewLine will be \r(windows), ',' (format, 2nd) * it should remove this fr parsing easily */ for (j = 0; j < 128; j++) { if (comm_1st < 0) { if (line[j] == ',') { comm_1st = j; match_start = j; } else continue; } else { if (line[j] >= '0' && line[j] <= '9') { continue; } else { line[j] = '\0'; /* CF, \r */ match_end = j; /* LF, new line */ break; /* 2nd ,*/ } } } comm_1st = -1; if (hx_s_ts->debug_log_level & BIT(4)) I("Line=%s,start = %d, end=%d\n", line, match_start, match_end); /* get the number string, and set the end sign for line end */ if (strcpy_idx(line, ",", match_end) < 0) { E("%s, get value fail for %s!\n", __func__, g_hx_inspt_setting_name[i]); result = -1; i++; continue; } if (hx_s_ts->debug_log_level & BIT(4)) I("last..Line=%s\n", line); chk = kstrtoint(line, 10, &test_int); if (chk) { E("%s:addr kstrtoint return fail!\n", __func__); test_int = -9487; } g_hx_inspt_setting_val[i] = test_int; I("%s:[%d] %s,result value=%d\n", __func__, i, g_hx_inspt_setting_name[i], g_hx_inspt_setting_val[i]); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:test_int=%d\n", __func__, test_int); if (test_int <= -9487) { result = HX_INSP_EFILE; break; } i++; } kfree(line); return result; } static void himax_parse_criteria_version(const struct firmware *file_entry) { int j = 0; int match_start = -1; int match_end = -1; char *find_start; char *find_end; char *line; int comm_1st = -1; int parse_succ = 0; line = kzalloc(sizeof(char) * 128, GFP_KERNEL); /* check the name of item */ find_start = strnstr(file_entry->data, g_hx_inspt_ver_name, file_entry->size); if (find_start == NULL) { I("%s, Can't find %s, SKIP\n", __func__, g_hx_inspt_ver_name); parse_succ = -1; goto END; } else match_start = (int)(find_start - (char *)file_entry->data); if (match_start >= 0) { memcpy(line, &file_entry->data[match_start], sizeof(char) * 128); } else { I("%s, start wrong:%s = %d, skip\n", __func__, g_hx_inspt_ver_name, match_start); parse_succ = -1; goto END; } /* get the end of line*/ find_end = strnchr(line, 128, '\n'); if (find_end == NULL) { I("%s, Can't find eol, skip\n", __func__); parse_succ = -1; goto END; } else match_end = (int)(find_end - line); if (match_end >= 128 || match_end <= 0) { I("%s, end wrong:%s = %d, skip\n", __func__, g_hx_inspt_ver_name, match_end); parse_succ = -1; goto END; } else line[match_end] = '\0'; /* Define the end of Line, * before NewLine will be \r(windows), ',' (format, 2nd) * it should remove this fr parsing easily */ for (j = 0; j < 128; j++) { if (comm_1st < 0) { if (line[j] == ',') { comm_1st = j; match_start = j; } else continue; } else { if (line[j] >= 'a' && line[j] <= 'z') { continue; } else if (line[j] >= '0' && line[j] <= '9') { continue; } else if (line[j] >= 'A' && line[j] <= 'Z') { continue; } else if (line[j] == '-' || line[j] == '_') { continue; } else { line[j] = '\0'; /* CF, \r */ match_end = j; /* LF, new line */ break; /* 2nd ,*/ } } } if (hx_s_ts->debug_log_level & BIT(4)) I("Line=%s,start = %d, end=%d\n", line, match_start, match_end); /* get the number string, and set the end sign for line end */ if (strcpy_idx(line, ",", match_end) < 0) { E("%s, get value fail for %s!\n", __func__, g_hx_inspt_ver_name); parse_succ = -1; goto END; } END: if (g_str_crtra_ver != NULL) { kfree(g_str_crtra_ver); g_str_crtra_ver = NULL; } if (parse_succ == -1) { g_str_crtra_ver = kzalloc(sizeof(char) * (12), GFP_KERNEL); strlcpy(g_str_crtra_ver, "No Version", 12); } else { g_str_crtra_ver = kzalloc(sizeof(char) * (match_end - match_start), GFP_KERNEL); memcpy(g_str_crtra_ver, line, sizeof(char) * (match_end - match_start)); } I("%s:version=%s\n", __func__, g_str_crtra_ver); kfree(line); } static int himax_parse_criteria(const struct firmware *file_entry) { int ret = 0; int i = 0; int start_str_len = 0; int match_start = -1; char *start_ptr = NULL; int tx_num = hx_s_ic_data->tx_num; int rx_num = hx_s_ic_data->rx_num; char *chk_ptr; himax_parse_criteria_version(file_entry); if (himax_parse_criteria_setting(file_entry) == HX_INSP_EFILE) { ret = HX_INSP_EFILE; goto END; } i = 0; while (g_hx_inspt_crtra_name[i] != NULL) { start_ptr = strnstr(file_entry->data, g_hx_inspt_crtra_name[i], file_entry->size); if (start_ptr != NULL) { I("g_hx_inspt_crtra_name[%d] = %s\n", i, g_hx_inspt_crtra_name[i]); start_str_len = strlen(g_hx_inspt_crtra_name[i]); match_start = (int)(start_ptr - (char *)(file_entry->data)); chk_ptr = strnstr(g_hx_inspt_crtra_name[i], "SELF", start_str_len); if (chk_ptr != NULL) { I("Now run to self!\n"); tx_num = 1; rx_num = hx_s_ic_data->rx_num + hx_s_ic_data->tx_num; } else { I("Now run to mutual!\n"); tx_num = hx_s_ic_data->tx_num; rx_num = hx_s_ic_data->rx_num; } ret |= himax_parse_criteria_str(match_start, start_str_len, file_entry, tx_num, rx_num); if (ret >= HX_INSP_EFILE) break; } i++; } END: #ifdef HX_INSPT_DBG /* dbg:print all of criteria from parsing file */ hx_print_crtra_after_parsing(); #endif return ret; } static int himax_parse_test_dri_file(const struct firmware *file_entry) { int start_str_len; int str_size; char *start_ptr = NULL; char *end_ptr = NULL; int i = 0; int j; char str[2][60]; /*[0]->Start string, [1]->End string*/ char *str_tail[2] = {"_Begin]\x0d\x0a", "_End]\x0d\x0a"}; int ret = HX_INSP_OK; while (g_hx_head_str[i]) { /*compose header string of .dri file*/ for (j = 0; j < 2; j++) { strlcpy(str[j], "[", sizeof(str[j])); strlcat(str[j], g_hx_head_str[i], sizeof(str[j])); strlcat(str[j], str_tail[j], sizeof(str[j])); /*I("%s string[%d] : %s\n", __func__, j, str[j]);*/ } /*find each group of .dri file*/ start_str_len = strlen(str[0]); start_ptr = strnstr(file_entry->data, str[0], file_entry->size); end_ptr = strnstr(file_entry->data, str[1], file_entry->size); if (start_ptr == NULL || end_ptr == NULL) { E("%s,Can't find string %s\n", __func__, g_hx_head_str[i]); } else { /*parse each sub group string*/ /*if (strncmp(g_hx_head_str[i], "Project_Info",*/ /*strlen(g_hx_head_str[i])) == 0) {*/ /* get project informaion - Not Use*/ /*}*/ str_size = end_ptr - start_ptr - start_str_len; /*I("%s,String Length = %d\n", __func__, str_size);*/ if (strncmp(g_hx_head_str[i], "TestItem", strlen(g_hx_head_str[i])) == 0) { /*get Test Item*/ I("%s,Start to parse %s\n", __func__, g_hx_head_str[i]); ret |= himax_test_item_parse(start_ptr + start_str_len, str_size); } /*if (strncmp(g_hx_head_str[i], "TestCriteria_Weight",*/ /*strlen(g_hx_head_str[i])) == 0) {*/ /*get Test Criteria Weight - Not Use*/ /*}*/ if (strncmp(g_hx_head_str[i], "TestCriteria", strlen(g_hx_head_str[i])) == 0) { /*get Test Criteria*/ I("%s,Start to parse %s\n", __func__, g_hx_head_str[i]); ret |= himax_parse_criteria(file_entry); } } i++; } return ret; } static int himax_test_item_chk(int csv_test) { int i; int count = 0; if (csv_test) for (i = 0; i < HX_CRITERIA_ITEM - 1; i++) g_test_item_flag[i] = 1; g_test_item_flag[HX_OPEN] &= (g_inspt_crtra_flag[IDX_OPENMIN] == 1 && g_inspt_crtra_flag[IDX_OPENMAX] == 1) ? 1 : 0; g_test_item_flag[HX_SELF_OPEN] &= (g_inspt_crtra_flag[IDX_SELF_OPENMIN] == 1 && g_inspt_crtra_flag[IDX_SELF_OPENMAX] == 1) ? 1 : 0; g_test_item_flag[HX_MICRO_OPEN] &= (g_inspt_crtra_flag[IDX_M_OPENMIN] == 1 && g_inspt_crtra_flag[IDX_M_OPENMAX] == 1) ? 1 : 0; g_test_item_flag[HX_SHORT] &= (g_inspt_crtra_flag[IDX_SHORTMIN] == 1 && g_inspt_crtra_flag[IDX_SHORTMAX] == 1) ? 1 : 0; g_test_item_flag[HX_SELF_SHORT] &= (g_inspt_crtra_flag[IDX_SELF_SHORTMIN] == 1 && g_inspt_crtra_flag[IDX_SELF_SHORTMAX] == 1) ? 1 : 0; g_test_item_flag[HX_RAWDATA] &= (g_inspt_crtra_flag[IDX_RAWMIN] == 1 && g_inspt_crtra_flag[IDX_RAWMAX] == 1) ? 1 : 0; g_test_item_flag[HX_BPN_RAWDATA] &= (g_inspt_crtra_flag[IDX_BPN_RAWMIN] == 1 && g_inspt_crtra_flag[IDX_BPN_RAWMAX] == 1) ? 1 : 0; g_test_item_flag[HX_PEN_MODE_DATA] &= (g_inspt_crtra_flag[IDX_PEN_MODE_DATAMIN] == 1 && g_inspt_crtra_flag[IDX_PEN_MODE_DATAMAX] == 1) ? 1 : 0; g_test_item_flag[HX_SELF_BPN_RAWDATA] &= (g_inspt_crtra_flag[IDX_SELF_BPN_RAWMIN] == 1 && g_inspt_crtra_flag[IDX_SELF_BPN_RAWMAX] == 1) ? 1 : 0; g_test_item_flag[HX_SC] &= (g_inspt_crtra_flag[IDX_SCMIN] == 1 && g_inspt_crtra_flag[IDX_SCMAX] == 1 && g_inspt_crtra_flag[IDX_SC_GOLDEN] == 1) ? 1 : 0; g_test_item_flag[HX_WT_NOISE] &= (g_inspt_crtra_flag[IDX_WT_NOISEMIN] == 1 && g_inspt_crtra_flag[IDX_WT_NOISEMAX] == 1) ? 1 : 0; g_test_item_flag[HX_SELF_WT_NOISE] &= (g_inspt_crtra_flag[IDX_SELF_WT_NOISEMIN] == 1 && g_inspt_crtra_flag[IDX_SELF_WT_NOISEMAX] == 1) ? 1 : 0; g_test_item_flag[HX_ABS_NOISE] &= (g_inspt_crtra_flag[IDX_ABS_NOISEMIN] == 1 && g_inspt_crtra_flag[IDX_ABS_NOISEMAX] == 1) ? 1 : 0; g_test_item_flag[HX_SELF_ABS_NOISE] &= (g_inspt_crtra_flag[IDX_SELF_ABS_NOISEMIN] == 1 && g_inspt_crtra_flag[IDX_SELF_ABS_NOISEMAX] == 1) ? 1 : 0; g_test_item_flag[HX_SORTING] &= (g_inspt_crtra_flag[IDX_SORTMIN] == 1 && g_inspt_crtra_flag[IDX_SORTMAX] == 1) ? 1 : 0; g_test_item_flag[HX_GAPTEST_RAW] &= (g_inspt_crtra_flag[IDX_GAP_HOR_RAWMAX] == 1 && g_inspt_crtra_flag[IDX_GAP_HOR_RAWMIN] == 1 && g_inspt_crtra_flag[IDX_GAP_VER_RAWMAX] == 1 && g_inspt_crtra_flag[IDX_GAP_VER_RAWMIN] == 1) ? 1 : 0; g_test_item_flag[HX_ACT_IDLE_RAWDATA] &= (g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MIN] == 1 && g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MAX] == 1) ? 1 : 0; g_test_item_flag[HX_ACT_IDLE_BPN_RAWDATA] &= (g_inspt_crtra_flag[IDX_ACT_IDLE_RAW_BPN_MIN] == 1 && g_inspt_crtra_flag[IDX_ACT_IDLE_RAW_BPN_MAX] == 1) ? 1 : 0; g_test_item_flag[HX_ACT_IDLE_NOISE] &= (g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MIN] == 1 && g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MAX] == 1) ? 1 : 0; g_test_item_flag[HX_LP_RAWDATA] &= (g_inspt_crtra_flag[IDX_LP_RAWDATA_MIN] == 1 && g_inspt_crtra_flag[IDX_LP_RAWDATA_MAX] == 1) ? 1 : 0; g_test_item_flag[HX_LP_BPN_RAWDATA] &= (g_inspt_crtra_flag[IDX_LP_RAW_BPN_MIN] == 1 && g_inspt_crtra_flag[IDX_LP_RAW_BPN_MAX] == 1) ? 1 : 0; g_test_item_flag[HX_LP_WT_NOISE] &= (g_inspt_crtra_flag[IDX_LP_WT_NOISEMAX] == 1 && g_inspt_crtra_flag[IDX_LP_WT_NOISEMIN] == 1) ? 1 : 0; g_test_item_flag[HX_LP_ABS_NOISE] &= (g_inspt_crtra_flag[IDX_LP_NOISE_ABS_MAX] == 1 && g_inspt_crtra_flag[IDX_LP_NOISE_ABS_MIN] == 1) ? 1 : 0; g_test_item_flag[HX_LP_IDLE_RAWDATA] &= (g_inspt_crtra_flag[IDX_LP_IDLE_RAWDATA_MAX] == 1 && g_inspt_crtra_flag[IDX_LP_IDLE_RAWDATA_MIN] == 1) ? 1 : 0; g_test_item_flag[HX_LP_IDLE_BPN_RAWDATA] &= (g_inspt_crtra_flag[IDX_LP_IDLE_RAW_BPN_MIN] == 1 && g_inspt_crtra_flag[IDX_LP_IDLE_RAW_BPN_MAX] == 1) ? 1 : 0; g_test_item_flag[HX_LP_IDLE_NOISE] &= (g_inspt_crtra_flag[IDX_LP_IDLE_NOISE_MAX] == 1 && g_inspt_crtra_flag[IDX_LP_IDLE_NOISE_MIN] == 1) ? 1 : 0; do_lpwg_test = g_test_item_flag[HX_LP_RAWDATA] | g_test_item_flag[HX_LP_BPN_RAWDATA] | g_test_item_flag[HX_LP_WT_NOISE] | g_test_item_flag[HX_LP_ABS_NOISE] | g_test_item_flag[HX_LP_IDLE_RAWDATA] | g_test_item_flag[HX_LP_IDLE_BPN_RAWDATA] | g_test_item_flag[HX_LP_IDLE_NOISE]; for (i = 0; i < HX_CRITERIA_ITEM - 1; i++) { if (hx_s_ts->debug_log_level & BIT(4)) I("g_test_item_flag[%d] = %d\n", i, g_test_item_flag[i]); if (g_test_item_flag[i] == 1) count++; } return count; } int hx_get_size_str_arr(char **input) { int i = 0; int result = 0; while (input[i] != NULL) i++; result = i; if (hx_s_ts->debug_log_level & BIT(4)) I("There is %d in [0]=%s\n", result, input[0]); return result; } static void hx_print_criteria_ver(void) { uint32_t len = 0; char *prt_data = NULL; int buf_size = 1024; prt_data = kzalloc(sizeof(char) * (buf_size), GFP_KERNEL); if (prt_data == NULL) { E("%s: Memory allocation falied!\n", __func__); return; } len += snprintf(prt_data + len, buf_size - len, "Version : %s\n", g_str_crtra_ver); memcpy(&g_rslt_data[0], prt_data, len); g_rslt_data_len = len; I("%s: Criteria version=%s!\n", __func__, g_rslt_data); kfree(prt_data); } #if defined(HX_ZERO_FLASH) static void hx_print_fw_info(void) { uint32_t len = 0; char *prt_data = NULL; int fw_ver; int config_ver; int touch_cfg_ver; int display_cfg_ver; int cid_maj_ver; int cid_min_ver; int panel_ver; uint8_t cus_info[13] = {0}; uint8_t proj_info[13] = {0}; uint8_t data[12] = {0}; int buf_size = 1024; prt_data = kzalloc(sizeof(char) * (buf_size), GFP_KERNEL); if (prt_data == NULL) { E("%s: Memory allocation falied!\n", __func__); return; } hx_s_core_fp._register_read( hx_s_ic_setup._addr_fw_ver, data, DATA_LEN_4); panel_ver = data[0]; fw_ver = data[1] << 8 | data[2]; hx_s_core_fp._register_read(hx_s_ic_setup._addr_fw_cfg, data, DATA_LEN_4); config_ver = data[2] << 8 | data[3]; touch_cfg_ver = data[2]; display_cfg_ver = data[3]; hx_s_core_fp._register_read(hx_s_ic_setup._addr_fw_vendor, data, DATA_LEN_4); cid_maj_ver = data[2]; cid_min_ver = data[3]; hx_s_core_fp._register_read(hx_s_ic_setup._addr_cus_info, data, 12); memcpy(cus_info, data, 12); hx_s_core_fp._register_read(hx_s_ic_setup._addr_proj_info, data, 12); memcpy(proj_info, data, 12); len += snprintf(prt_data + len, buf_size - len, "\nFW_VER = 0x%2.2X\n", fw_ver); if (hx_s_ts->chip_cell_type == CHIP_IS_ON_CELL) { len += snprintf(prt_data + len, buf_size - len, "CONFIG_VER = 0x%2.2X\n", config_ver); } else { len += snprintf(prt_data + len, buf_size - len, "TOUCH_VER = 0x%2.2X\n", touch_cfg_ver); len += snprintf(prt_data + len, buf_size - len, "DISPLAY_VER = 0x%2.2X\n", display_cfg_ver); } if (cid_maj_ver < 0 && cid_min_ver < 0) { len += snprintf(prt_data + len, buf_size - len, "CID_VER = NULL\n"); } else { len += snprintf(prt_data + len, buf_size - len, "CID_VER = 0x%2.2X\n", (cid_maj_ver << 8 | cid_min_ver)); } if (panel_ver < 0) { len += snprintf(prt_data + len, buf_size - len, "PANEL_VER = NULL\n"); } else { len += snprintf(prt_data + len, buf_size - len, "PANEL_VER = 0x%2.2X\n", panel_ver); } if (hx_s_ts->chip_cell_type == CHIP_IS_IN_CELL) { len += snprintf(prt_data + len, buf_size - len, "Cusomer = %s\n", cus_info); len += snprintf(prt_data + len, buf_size - len, "Project = %s\n", proj_info); } memcpy(&g_rslt_data[g_rslt_data_len], prt_data, len); g_rslt_data_len += len; I("%s: g_rslt_data_len=%d!\n", __func__, g_rslt_data_len); kfree(prt_data); } #endif #if defined(HX_RW_FILE) static char *get_date_time_str(void) { static char time_data_buf[64] = {0}; struct time_var tv64; struct rtc_time rtc_now_time; ktime_get_real_ts64(&tv64); tv64.tv_sec -= (uint64_t)sys_tz.tz_minuteswest * 60; rtc_time64_to_tm(tv64.tv_sec, &rtc_now_time); snprintf(time_data_buf, sizeof(time_data_buf), "%04d%02d%02d_%02d%02d%02d", (rtc_now_time.tm_year + SYSTEM_TIME), 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; } #endif static int himax_self_test_data_init(void) { const struct firmware *file_entry = NULL; struct himax_ts_data *ts = hx_s_ts; char *file_name_1 = "hx_criteria.dri"; char *file_name_2 = "hx_criteria.csv"; int setting_sz = -1; int ret = HX_INSP_OK; int err = 0; int i = 0; /* * 5: one value will not over than 99999, so get this size of string * 2: get twice size */ g_1kind_raw_size = 5 * hx_s_ic_data->rx_num * hx_s_ic_data->tx_num * 2; /* get test item and its items of criteria*/ HX_CRITERIA_ITEM = hx_get_size_str_arr(g_hx_inspt_mode); HX_CRITERIA_SIZE = hx_get_size_str_arr(g_hx_inspt_crtra_name); I("There is %d HX_CRITERIA_ITEM and %d HX_CRITERIA_SIZE\n", HX_CRITERIA_ITEM, HX_CRITERIA_SIZE); /* init criteria data*/ g_test_item_flag = kcalloc(HX_CRITERIA_ITEM, sizeof(int), GFP_KERNEL); if (g_test_item_flag == NULL) { E("%s,%d: Memory allocation falied!\n", __func__, __LINE__); ret = HX_INSP_MEMALLCTFAIL; goto err_malloc_test_item_flag; } g_inspt_crtra_flag = kcalloc(HX_CRITERIA_SIZE, sizeof(int), GFP_KERNEL); if (g_inspt_crtra_flag == NULL) { E("%s,%d: Memory allocation falied!\n", __func__, __LINE__); ret = HX_INSP_MEMALLCTFAIL; goto err_malloc_inspt_crtra_flag; } g_inspt_crtra = kcalloc(HX_CRITERIA_SIZE, sizeof(int *), GFP_KERNEL); if (g_inspt_crtra == NULL) { E("%s,%d: Memory allocation falied!\n", __func__, __LINE__); ret = HX_INSP_MEMALLCTFAIL; goto err_malloc_inspection_criteria; } for (i = 0; i < HX_CRITERIA_SIZE; i++) { g_inspt_crtra[i] = kcalloc((hx_s_ic_data->tx_num * hx_s_ic_data->rx_num), sizeof(int), GFP_KERNEL); if (g_inspt_crtra[i] == NULL) { E("%s,%d: Memory allocation %d falied!\n", __func__, __LINE__, i); ret = HX_INSP_MEMALLCTFAIL; goto err_malloc_inspection_criteria2; } } g_rslt_data_len = 0; if (g_rslt_data == NULL) { I("1st, init log buffer!\n"); g_rslt_data = vmalloc( g_1kind_raw_size * HX_CRITERIA_ITEM * sizeof(char) ); if (g_rslt_data == NULL) { E("%s,%d: Memory allocation falied!\n", __func__, __LINE__); ret = HX_INSP_MEMALLCTFAIL; goto err_malloc_rslt_data; } } else { I("N-times, reset log buffer!\n"); memset(g_rslt_data, 0x00, g_1kind_raw_size * HX_CRITERIA_ITEM); } setting_sz = hx_get_size_str_arr(g_hx_inspt_setting_name); I("There are %d kinds of setting items\n", setting_sz); g_hx_inspt_setting_val = kcalloc(setting_sz, sizeof(int), GFP_KERNEL); if (g_hx_inspt_setting_val == NULL) { E("%s,%d: Memory allocation falied!\n", __func__, __LINE__); ret = HX_INSP_MEMALLCTFAIL; goto err_malloc_inspection_setting_val; } for (i = 0 ; i < setting_sz; i++) g_hx_inspt_setting_val[i] = -1; I("%s: initialize g_rslt_data, length = %d\n", __func__, g_1kind_raw_size * HX_CRITERIA_ITEM); memset(g_rslt_data, 0x00, g_1kind_raw_size * HX_CRITERIA_ITEM * sizeof(char)); /* default path is /system/etc/firmware */ /* request criteria file*/ err = request_firmware(&file_entry, file_name_1, ts->dev); if (err < 0) { E("%s,Fail to get %s\n", __func__, file_name_1); err = request_firmware(&file_entry, file_name_2, ts->dev); if (err < 0) { E("%s,Fail to get %s\n", __func__, file_name_2); I("No criteria file file"); ret = HX_INSP_EFILE; goto err_open_criteria_file; } else { I("%s,Success to get %s\n", __func__, file_name_2); /* parsing criteria from file .csv*/ ret = himax_parse_criteria(file_entry); release_firmware(file_entry); if (ret > 0) goto err_open_criteria_file; if (himax_test_item_chk(true) == 0) { E("%s: Criteira is empty!\n", __func__); ret = HX_INSP_EFILE; goto err_open_criteria_file; } } } else { /* parsing test file .dri*/ I("%s,Success to get %s\n", __func__, file_name_1); ret = himax_parse_test_dri_file(file_entry); release_firmware(file_entry); if (ret > 0) goto err_open_criteria_file; if (himax_test_item_chk(false) == 0) { E("%s: Criteira is empty!\n", __func__); ret = HX_INSP_EFILE; goto err_open_criteria_file; } } if (hx_s_ts->debug_log_level & BIT(4)) { /* print get criteria string */ for (i = 0 ; i < HX_CRITERIA_SIZE ; i++) { if (g_inspt_crtra_flag[i] != 0) I("%s: [%d]There is String=%s\n", __func__, i, g_hx_inspt_crtra_name[i]); } } snprintf(g_file_path, (int)(strlen(HX_RSLT_OUT_PATH) + strlen(HX_RSLT_OUT_FILE)+1), "%s%s", HX_RSLT_OUT_PATH, HX_RSLT_OUT_FILE); file_w_flag = true; return ret; err_open_criteria_file: kfree(g_hx_inspt_setting_val); g_hx_inspt_setting_val = NULL; err_malloc_inspection_setting_val: vfree(g_rslt_data); g_rslt_data = NULL; err_malloc_rslt_data: err_malloc_inspection_criteria2: for (i = 0; i < HX_CRITERIA_SIZE; i++) { if (g_inspt_crtra[i] != NULL) { kfree(g_inspt_crtra[i]); g_inspt_crtra[i] = NULL; } } kfree(g_inspt_crtra); g_inspt_crtra = NULL; err_malloc_inspection_criteria: kfree(g_inspt_crtra_flag); g_inspt_crtra_flag = NULL; err_malloc_inspt_crtra_flag: kfree(g_test_item_flag); g_test_item_flag = NULL; err_malloc_test_item_flag: return ret; } static void himax_self_test_data_deinit(void) { int i = 0; /*dbg*/ /* for (i = 0; i < HX_CRITERIA_ITEM; i++) * I("%s:[%d]%d\n", __func__, i, g_inspt_crtra[i]); */ I("%s: release allocated memory\n", __func__); for (i = 0; i < HX_CRITERIA_SIZE; i++) { if (g_inspt_crtra[i] != NULL) { kfree(g_inspt_crtra[i]); g_inspt_crtra[i] = NULL; } } kfree(g_inspt_crtra); g_inspt_crtra = NULL; kfree(g_inspt_crtra_flag); g_inspt_crtra_flag = NULL; kfree(g_test_item_flag); g_test_item_flag = NULL; // himax_inspect_data_clear(); kfree(g_hx_inspt_setting_val); g_hx_inspt_setting_val = NULL; I("%s: release finished\n", __func__); } static int himax_chip_self_test(struct seq_file *s, void *v) { int ret = HX_INSP_OK; uint32_t test_size = hx_s_ic_data->tx_num * hx_s_ic_data->rx_num + hx_s_ic_data->tx_num + hx_s_ic_data->rx_num; int i = 0; int j = 0; #if !defined(HX_ZERO_FLASH) uint8_t tmp_data[DATA_LEN_4] = {0x01, 0x00, 0x00, 0x00}; #endif #if defined(HX_RW_FILE) loff_t pos = 0; #endif uint32_t rslt = HX_INSP_OK; I("%s:IN\n", __func__); hx_s_ts->suspend_resume_done = 0; ret = himax_self_test_data_init(); if (ret > 0) { E("%s: initialize self test failed\n", __func__); if (ret == HX_INSP_EFILE) { seq_puts(s, "Self_Test Fail:\n" "- Criteria file!\n"); } goto END; } #if defined(HX_ZERO_FLASH) ret = hx_s_core_fp._0f_op_file_dirly(g_fw_mp_upgrade_name); if (ret) { E("%s: upgrade MPFW fail, code[%d]!!\n", __func__, ret); ret = HX_INSP_EUPDATE; goto UPDATE_MPFW_FAIL; } hx_s_core_fp._read_FW_ver(); g_mp_fw_ver = (hx_s_ic_data->vendor_cid_maj_ver << 8 | hx_s_ic_data->vendor_cid_min_ver); #else hx_s_core_fp._show_FW_ver(); #endif hx_print_criteria_ver(); /*Do normal test items*/ for (i = 0; i < HX_CRITERIA_ITEM; i++) { /* skip run self test item*/ if (i == hx_check_has_self(i)) continue; if (i < HX_LP_WT_NOISE) { if (g_test_item_flag[i] == 1) { I("%d. %s Start\n", i, g_hx_inspt_mode[i]); ret = mpTestFunc(i, test_size); I("%d. %s End, ret = %d\n", i, g_hx_inspt_mode[i], ret); if (ret) rslt |= 1 << i; if (ret > HX_INSP_ESPEC) goto SELF_TEST_FAIL; } } else { break; } } /* Press power key and do LPWUG test items*/ if (do_lpwg_test) { himax_press_powerkey(); /* Wait suspend done */ while (hx_s_ts->suspend_resume_done != 1) { usleep_range(1000, 1001); if (hx_s_ts->debug_log_level & BIT(4)) I("Waiting for tp suspend!\n"); } hx_s_ts->suspend_resume_done = 0; for (; i < HX_CRITERIA_ITEM; i++) { if (g_test_item_flag[i] == 1) { I("%d.%s Start\n", i, g_hx_inspt_mode[i]); ret = mpTestFunc(i, test_size); I("%d.%s End\n", i, g_hx_inspt_mode[i]); rslt |= 1 << i; if (ret > HX_INSP_ESPEC) goto SELF_TEST_LP_FAIL; } } SELF_TEST_LP_FAIL: himax_press_powerkey(); /* Wait resume done */ while (hx_s_ts->suspend_resume_done != 1) usleep_range(1000, 1001); } SELF_TEST_FAIL: #if defined(HX_RW_FILE) memset(g_file_path, 0, 256); snprintf(g_file_path, (int)(strlen(HX_RSLT_OUT_PATH)+ strlen(HX_SELF_RSLT_OUT_FILE)+ strlen(get_date_time_str())+ strlen(rslt ? "FAIL":"PASS")+ strlen("_.txt") + 1), "%s%s%s_%s.txt", HX_RSLT_OUT_PATH, HX_SELF_RSLT_OUT_FILE, rslt ? "FAIL":"PASS", get_date_time_str()); file_w_flag = true; if (file_w_flag) { I("Start to write fs!\n"); if (hx_open_file(g_file_path) != NO_ERR) { E("%s open file failed\n", __func__); file_w_flag = false; } } #else I("%s:No support RW file\n", __func__); #endif #if defined(HX_ZERO_FLASH) /* output FW version */ hx_print_fw_info(); #endif #if defined(HX_RW_FILE) if (file_w_flag) { hx_write_file(g_rslt_data, g_rslt_data_len, pos); pos += g_rslt_data_len; } if (file_w_flag) { I("file OK, now close!\n"); hx_close_file(); } else { I("file wrong, skip close!\n"); } #endif #if defined(HX_ZERO_FLASH) UPDATE_MPFW_FAIL: hx_s_core_fp._0f_op_file_dirly(g_fw_boot_upgrade_name); #else if (hx_s_ts->debug_log_level & BIT(4)) I("%s:start sense off!\n", __func__); hx_s_core_fp._sense_off(true); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:end sense off!\n", __func__); hx_s_core_fp._turn_on_mp_func(0); /*himax_set_N_frame(1, HX_INSPECTION_WT_NOISE);*/ /* set N frame back to default value 1*/ hx_s_core_fp._register_write(hx_s_ic_setup._addr_set_frame, tmp_data, 4); if (hx_s_core_fp._reload_disable != NULL) hx_s_core_fp._reload_disable(0); if (himax_check_mode(HX_RAWDATA)) { I("%s:try to Need to back to Normal!\n", __func__); himax_switch_mode_inspection(HX_RAWDATA); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:start sense on!\n", __func__); hx_s_core_fp._sense_on(0); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:end sense on!\n", __func__); himax_wait_sorting_mode(HX_RAWDATA); } else { I("%s: It has been in Normal!\n", __func__); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:start sense on!\n", __func__); hx_s_core_fp._sense_on(0); if (hx_s_ts->debug_log_level & BIT(4)) I("%s:end sense on!\n", __func__); } #endif if (rslt == HX_INSP_OK && ret == HX_INSP_OK) seq_puts(s, "Self_Test Pass:\n"); else seq_puts(s, "Self_Test Fail:\n"); seq_printf(s, "Version : %s\n", g_str_crtra_ver); #if defined(HX_ZERO_FLASH) if (hx_s_ts->debug_log_level & BIT(4)) seq_printf(s, "MP FW CID : 0x%04X\n", g_mp_fw_ver); #endif if (ret == HX_INSP_EUPDATE) { seq_puts(s, "MP FW Update fail!\n"); goto UPDATE_FAIL; } for (j = 0; j < HX_CRITERIA_ITEM - 1; j++) { if (j == hx_check_has_self(j)) continue; if (g_test_item_flag[j] == 1) { if (j <= i) { seq_printf(s, "%s : %s\n", g_hx_inspt_mode[j], (rslt & (1 << j)) ? "FAIL" : "PASS"); } else { seq_printf(s, "%s : %s\n", g_hx_inspt_mode[j], "SKIP"); } } } UPDATE_FAIL: himax_self_test_data_deinit(); END: I("running status = %X\n", ret); /*if (ret != 0)*/ /*ret = 1;*/ I("%s:OUT\n", __func__); return ret; } void himax_inspect_data_clear(void) { I("%s: Entering!\n", __func__); if (g_rslt_data != NULL) { I("%s: Clear log buf!\n", __func__); vfree(g_rslt_data); g_rslt_data = NULL; } } void himax_inspection_init(void) { I("%s: enter, %d\n", __func__, __LINE__); hx_s_core_fp._chip_self_test = himax_chip_self_test; }