kernel_samsung_a34x-permissive/drivers/input/touchscreen/ili9881x/ili9881x_mp.c

3932 lines
119 KiB
C
Raw Normal View History

/*
* ILITEK Touch IC driver
*
* Copyright (C) 2011 ILI Technology Corporation.
*
* Author: Dicky Chiang <dicky_chiang@ilitek.com>
*
* 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;
};