blob: 72df84c2d076fa4984e60739b65f7aab17e9e45d [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/* Himax Android Driver Sample Code for debug nodes
*
* Copyright (C) 2019 Himax Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "himax_debug.h"
#include "himax_ic_core.h"
#if defined(HX_TP_PROC_2T2R)
bool Is_2T2R;
EXPORT_SYMBOL(Is_2T2R);
int HX_RX_NUM_2;
int HX_TX_NUM_2;
#endif
uint8_t g_diag_arr_num;
bool g_test_result;
int g_max_mutual;
int g_min_mutual = 0xFFFF;
int g_max_self;
int g_min_self = 0xFFFF;
/* moved from debug.h */
static char g_file_path[256];
uint8_t proc_reg_addr[4];
uint8_t proc_reg_addr_type;
uint8_t *proc_reg_buf;
uint8_t proc_reg_85xx_flag;
struct proc_dir_entry *himax_proc_stack_file;
struct proc_dir_entry *himax_proc_delta_file;
struct proc_dir_entry *himax_proc_dc_file;
struct proc_dir_entry *himax_proc_baseline_file;
bool dsram_flag;
#if defined(HX_TP_PROC_2T2R)
uint32_t *diag_mutual_2;
#endif
int32_t *diag_mutual;
int32_t *diag_mutual_new;
int32_t *diag_mutual_old;
uint8_t hx_state_info[2];
uint8_t diag_coor[128];
int32_t *diag_self;
int32_t *diag_self_new;
int32_t *diag_self_old;
struct proc_dir_entry *himax_proc_debug_file;
bool fw_update_complete;
bool fw_update_going;
int handshaking_result;
unsigned char debug_level_cmd;
uint8_t cmd_set[8];
uint8_t mutual_set_flag;
struct proc_dir_entry *himax_proc_flash_dump_file;
uint8_t *g_dump_buffer;
uint8_t g_dump_cmd;
uint8_t g_dump_show;
uint32_t g_dump_addr;
uint32_t g_dump_size;
uint8_t g_flash_progress;
bool g_flash_dump_rst; /*Fail = 0, Pass = 1*/
uint32_t **raw_data_array;
uint8_t X_NUM;
uint8_t Y_NUM;
uint8_t sel_type = 0x0D;
/* Moved from debug.h End */
char buf_tmp[BUF_SIZE] = {0};
struct proc_dir_entry *himax_proc_pen_pos_file;
#if defined(KERNEL_VER_ABOVE_5_10)
struct timespec64 timeStart, timeEnd, timeDelta;
#else
struct timespec timeStart, timeEnd, timeDelta;
#endif
int g_switch_mode;
/*
* Segment : Himax PROC Debug Function
*/
/****** useful functions ******/
int count_char(char *input)
{
int count = 0;
int i = 0;
for (i = 0; input[i] != '\0'; i++)
count++;
return count;
}
#define SIOS_DBG_STR "i = %d, j =%d, idx_find_str=%d, sts_find[%d]=%d\n"
static int str_idx_of_str(char *base, char *find)
{
int i = 0, j = 0;
int idx_find_str = 0;
int len_find_str = strlen(find);
int len_base_str = strlen(base);
int ret = -1;
int sts_find[256];
if (len_find_str > 256)
len_find_str = 256;
for (i = 0; i < len_base_str; i++) {
if (i + len_find_str > len_base_str) {
I("Command Check End!\n");
sts_find[0] = -1;
goto END;
}
for (j = 0; j < len_find_str; j++) {
if (*(base + i + j) == *(find + idx_find_str)) {
sts_find[idx_find_str] = i + j;
I(SIOS_DBG_STR,
i, j, idx_find_str,
idx_find_str, sts_find[idx_find_str]);
if (idx_find_str++ == (len_find_str - 1)) {
I("all check finish!\n");
goto END;
}
} else {
idx_find_str = 0;
sts_find[0] = -1;
break;
}
}
}
END:
ret = sts_find[0];
return ret;
}
static void _str_to_arr_in_char(char **arr, int arr_size, char *str, char c)
{
int i = 0;
int _arr_str_idx = 0;
int _arr_idx = 0;
int _arr_max_idx = arr_size;
for (i = 0; str[i] != '\0'; i++) {
if (_arr_max_idx <= _arr_idx) {
I("%s: Oversize!\n", __func__);
goto END;
}
if (str[i] == c || str[i] == '\0') {
I("%s: String parse compelete!\n", __func__);
_arr_idx++;
_arr_str_idx = 0;
} else {
arr[_arr_idx][_arr_str_idx] = str[i];
_arr_str_idx++;
continue;
}
}
END:
return;
}
bool chk_normal_str(char *str)
{
int i = 0;
bool result = false;
int str_len = strlen(str);
I("%s, str_len=%d\n", __func__, str_len);
for (i = 0; i < str_len; i++) {
if (str[i] >= '0' && str[i] <= '9') {
result = true;
continue;
} else if (str[i] >= 'A' && str[i] <= 'Z') {
result = true;
continue;
} else if (str[i] >= 'a' && str[i] <= 'z') {
result = true;
continue;
} else {
result = false;
break;
}
}
return result;
}
bool chk_normal_char(char c)
{
bool result = false;
if (c >= '0' && c <= '9')
result = true;
else if (c >= 'A' && c <= 'Z')
result = true;
else if (c >= 'a' && c <= 'z')
result = true;
else
result = false;
return result;
}
/* claculate 10's power function */
static int himax_power_cal(int pow, int number, int base)
{
int i = 0;
int result = 1;
for (i = 0; i < pow; i++)
result *= base;
result = result * number;
return result;
}
/* String to int */
static int hiamx_parse_str2int(char *str)
{
int i = 0;
int temp_cal = 0;
int result = -948794;
unsigned int str_len = strlen(str);
int negtive_flag = 0;
for (i = 0; i < str_len; i++) {
if (i == 0)
result = 0;
if (str[i] != '-' && str[i] > '9' && str[i] < '0') {
E("%s: Parsing fail!\n", __func__);
result = -9487;
negtive_flag = 0;
break;
}
if (str[i] == '-') {
negtive_flag = 1;
continue;
}
temp_cal = str[i] - '0';
result += himax_power_cal(str_len-i-1, temp_cal, 10);
/* str's the lowest char is the number's the highest number
* So we should reverse this number before using the power
* function
* -1: starting number is from 0 ex:10^0 = 1,10^1=10
*/
}
if (negtive_flag == 1)
result = 0 - result;
return result;
}
/* String in Hex to int */
static int hx_parse_hexstr2int(char *str)
{
int i = 0;
int temp_cal = 0;
int result = -948794;
unsigned int str_len = strlen(str);
int negtive_flag = 0;
for (i = 0; i < str_len; i++) {
if (i == 0)
result = 0;
if (str[i] == '-' && i == 0) {
negtive_flag = 1;
continue;
} else if (str[i] <= '9' && str[i] >= '0') {
temp_cal = str[i] - '0';
result += himax_power_cal(str_len-i-1, temp_cal, 16);
} else if (str[i] <= 'f' && str[i] >= 'a') {
temp_cal = str[i] - 'a' + 10;
result += himax_power_cal(str_len-i-1, temp_cal, 16);
} else if (str[i] <= 'F' && str[i] >= 'A') {
temp_cal = str[i] - 'A' + 10;
result += himax_power_cal(str_len-i-1, temp_cal, 16);
} else {
E("%s: Parsing fail!\n", __func__);
result = -9487;
negtive_flag = 0;
break;
}
}
if (negtive_flag == 1)
result = 0 - result;
return result;
}
/****** end ******/
static int himax_crc_test_read(struct seq_file *m)
{
int ret = 0;
uint8_t result = 0;
uint32_t size = 0;
g_core_fp.fp_sense_off(true);
msleep(20);
if (g_core_fp._diff_overlay_flash() == 1)
size = FW_SIZE_128k;
else
size = FW_SIZE_64k;
result = g_core_fp.fp_calculateChecksum(false, size);
g_core_fp.fp_sense_on(0x01);
if (result)
seq_printf(m,
"CRC test is Pass!\n");
else
seq_printf(m,
"CRC test is Fail!\n");
return ret;
}
static int himax_proc_fw_debug_read(struct seq_file *m)
{
int ret = 0;
uint8_t i = 0;
uint8_t addr[4] = {0};
uint8_t data[4] = {0};
int len = 0;
len = (size_t)(sizeof(dbg_reg_ary)/sizeof(uint32_t));
for (i = 0; i < len; i++) {
himax_parse_assign_cmd(dbg_reg_ary[i], addr, 4);
g_core_fp.fp_register_read(addr, data, DATA_LEN_4);
seq_printf(m,
"reg[0-3] : 0x%08X = 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
dbg_reg_ary[i], data[0], data[1], data[2], data[3]);
I("reg[0-3] : 0x%08X = 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
dbg_reg_ary[i], data[0], data[1], data[2], data[3]);
}
return ret;
}
static int himax_attn_read(struct seq_file *m)
{
int ret = 0;
struct himax_ts_data *ts_data;
ts_data = private_ts;
seq_printf(m, "attn = %x\n",
himax_int_gpio_read(ts_data->pdata->gpio_irq));
return ret;
}
static int himax_layout_read(struct seq_file *m)
{
struct himax_ts_data *ts = private_ts;
size_t ret = 0;
if (debug_data->is_call_help) {
seq_printf(m, HELP_LAYOUT);
debug_data->is_call_help = false;
} else {
seq_printf(m, "%d ",
ts->pdata->abs_x_min);
seq_printf(m, "%d ",
ts->pdata->abs_x_max);
seq_printf(m, "%d ",
ts->pdata->abs_y_min);
seq_printf(m, "%d ",
ts->pdata->abs_y_max);
seq_puts(m, "\n");
}
return ret;
}
static ssize_t himax_layout_write(char *buf, size_t len)
{
struct himax_ts_data *ts = private_ts;
char buf_tmp[5] = {0};
int i = 0, j = 0, k = 0, ret;
unsigned long value;
int layout[4] = {0};
if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (str_idx_of_str(buf, "help") >= 0) {
debug_data->is_call_help = true;
goto END;
} else {
for (i = 0; i < 20; i++) {
if (buf[i] == ',' || buf[i] == '\n') {
memset(buf_tmp, 0x0, sizeof(buf_tmp));
if (i - j <= 5) {
memcpy(buf_tmp, buf + j, i - j);
} else {
I("buffer size is over 5 char\n");
return len;
}
j = i + 1;
if (k < 4) {
ret = kstrtoul(buf_tmp, 10, &value);
layout[k++] = value;
}
}
}
if (k == 4) {
ts->pdata->abs_x_min = layout[0];
ts->pdata->abs_x_max = (layout[1] - 1);
ts->pdata->abs_y_min = layout[2];
ts->pdata->abs_y_max = (layout[3] - 1);
I("%d, %d, %d, %d\n",
ts->pdata->abs_x_min, ts->pdata->abs_x_max,
ts->pdata->abs_y_min, ts->pdata->abs_y_max);
input_unregister_device(ts->input_dev);
himax_input_register(ts);
} else {
I("ERR@%d, %d, %d, %d\n",
ts->pdata->abs_x_min, ts->pdata->abs_x_max,
ts->pdata->abs_y_min, ts->pdata->abs_y_max);
}
}
END:
return len;
}
#if defined(HX_EXCP_RECOVERY)
#if defined(HW_ED_EXCP_EVENT)
static int himax_excp_cnt_read(struct seq_file *m)
{
int ret = 0;
I("%s: enter, %d\n", __func__, __LINE__);
if (debug_data->is_call_help) {
seq_printf(m, HELP_EXCPT);
debug_data->is_call_help = false;
} else {
seq_printf(m,
"EB_cnt = %d, EC_cnt = %d, EE_cnt = %d\n",
hx_EB_event_flag,
hx_EC_event_flag,
hx_EE_event_flag);
}
return ret;
}
static ssize_t himax_excp_cnt_write(char *buf, size_t len)
{
int i = 0;
if (len >= 12) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (str_idx_of_str(buf, "help") >= 0) {
debug_data->is_call_help = true;
} else {
if (buf[i] == '0') {
I("Clear EXCEPTION Flag\n");
hx_EB_event_flag = 0;
hx_EC_event_flag = 0;
hx_EE_event_flag = 0;
}
}
return len;
}
#else
static int himax_excp_cnt_read(struct seq_file *m)
{
int ret = 0;
I("%s: enter, %d\n", __func__, __LINE__);
if (debug_data->is_call_help) {
seq_printf(m, HELP_EXCPT);
debug_data->is_call_help = false;
} else {
seq_printf(m,
"EB_cnt = %d, EC_cnt = %d, ED_cnt = %d\n",
hx_EB_event_flag,
hx_EC_event_flag,
hx_ED_event_flag);
}
return ret;
}
static ssize_t himax_excp_cnt_write(char *buf, size_t len)
{
int i = 0;
if (len >= 12) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (str_idx_of_str(buf, "help") >= 0) {
debug_data->is_call_help = true;
} else {
I("Clear EXCEPTION Flag\n");
if (buf[i] == '0') {
hx_EB_event_flag = 0;
hx_EC_event_flag = 0;
hx_ED_event_flag = 0;
}
}
return len;
}
#endif
#endif
static int himax_sense_on_off_read(struct seq_file *m)
{
int ret = 0;
I("%s: enter, %d\n", __func__, __LINE__);
if (debug_data->is_call_help) {
seq_printf(m, HELP_SNS);
debug_data->is_call_help = false;
} else {
if (g_test_result) {
seq_printf(m,"Result: Pass\n");
} else {
seq_printf(m,"Result: Fail\n");
}
}
return ret;
}
static ssize_t himax_sense_on_off_write(char *buf, size_t len)
{
int ret;
g_test_result = false;
if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (str_idx_of_str(buf, "help") >= 0) {
debug_data->is_call_help = true;
} else {
if (buf[0] == '0') {
ret = g_core_fp.fp_sense_off(true);
if (ret) {
g_test_result = true;
}
I("Sense off\n");
} else if (buf[0] == '1') {
if (buf[1] == 's') {
ret = g_core_fp.fp_sense_on(0x00);
I("Sense on re-map on, run sram\n");
} else {
ret = g_core_fp.fp_sense_on(0x01);
I("Sense on re-map off, run flash\n");
}
if (ret) {
g_test_result = true;
}
} else {
I("Do nothing\n");
}
}
return len;
}
static int test_irq_pin(void)
{
struct himax_ts_data *ts = private_ts;
int result = NO_ERR;
int irq_sts = -1;
uint8_t tmp_addr[DATA_LEN_4] = {0};
uint8_t tmp_data[DATA_LEN_4] = {0};
uint8_t tmp_read[DATA_LEN_4] = {0};
g_core_fp.fp_sense_off(true);
I("check IRQ LOW\n");
usleep_range(20000, 20001);
himax_parse_assign_cmd(0x90028060, tmp_addr, DATA_LEN_4);
himax_parse_assign_cmd(0x00000002, tmp_data, DATA_LEN_4);
g_core_fp.fp_register_write(tmp_addr, tmp_data, DATA_LEN_4);
usleep_range(20000, 20001);
g_core_fp.fp_register_read(tmp_addr, tmp_read, DATA_LEN_4);
I("R%02X%02X%02X%02XH = 0x%02X%02X%02X%02X\n",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]);
usleep_range(20000, 20001);
himax_parse_assign_cmd(0x90028064, tmp_addr, DATA_LEN_4);
himax_parse_assign_cmd(0x00000001, tmp_data, DATA_LEN_4);
g_core_fp.fp_register_write(tmp_addr, tmp_data, DATA_LEN_4);
usleep_range(20000, 20001);
g_core_fp.fp_register_read(tmp_addr, tmp_read, DATA_LEN_4);
I("R%02X%02X%02X%02XH = 0x%02X%02X%02X%02X\n",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]);
usleep_range(20000, 20001);
himax_parse_assign_cmd(0x90028068, tmp_addr, DATA_LEN_4);
himax_parse_assign_cmd(0x00000000, tmp_data, DATA_LEN_4);
g_core_fp.fp_register_write(tmp_addr, tmp_data, DATA_LEN_4);
usleep_range(20000, 20001);
g_core_fp.fp_register_read(tmp_addr, tmp_read, DATA_LEN_4);
I("R%02X%02X%02X%02XH = 0x%02X%02X%02X%02X\n",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]);
usleep_range(20000, 20001);
irq_sts = himax_int_gpio_read(ts->pdata->gpio_irq);
if (irq_sts == 0) {
I("[LOW]Now IRQ is LOW!\n");
result += NO_ERR;
} else {
I("[LOW]Now IRQ is High!\n");
result += 1;
}
I("check IRQ High\n");
usleep_range(20000, 20001);
himax_parse_assign_cmd(0x90028060, tmp_addr, DATA_LEN_4);
himax_parse_assign_cmd(0x00000002, tmp_data, DATA_LEN_4);
g_core_fp.fp_register_write(tmp_addr, tmp_data, DATA_LEN_4);
usleep_range(20000, 20001);
g_core_fp.fp_register_read(tmp_addr, tmp_read, DATA_LEN_4);
I("R%02X%02X%02X%02XH = 0x%02X%02X%02X%02X\n",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]);
usleep_range(20000, 20001);
himax_parse_assign_cmd(0x90028064, tmp_addr, DATA_LEN_4);
himax_parse_assign_cmd(0x00000001, tmp_data, DATA_LEN_4);
g_core_fp.fp_register_write(tmp_addr, tmp_data, DATA_LEN_4);
usleep_range(20000, 20001);
g_core_fp.fp_register_read(tmp_addr, tmp_read, DATA_LEN_4);
I("R%02X%02X%02X%02XH = 0x%02X%02X%02X%02X\n",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]);
usleep_range(20000, 20001);
himax_parse_assign_cmd(0x90028068, tmp_addr, DATA_LEN_4);
himax_parse_assign_cmd(0x00000001, tmp_data, DATA_LEN_4);
g_core_fp.fp_register_write(tmp_addr, tmp_data, DATA_LEN_4);
usleep_range(20000, 20001);
g_core_fp.fp_register_read(tmp_addr, tmp_read, DATA_LEN_4);
I("R%02X%02X%02X%02XH = 0x%02X%02X%02X%02X\n",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]);
usleep_range(20000, 20001);
irq_sts = himax_int_gpio_read(ts->pdata->gpio_irq);
if (irq_sts == 0) {
I("[High]Now IRQ is LOW!\n");
result += 1;
} else {
I("[High]Now IRQ is High!\n");
result += NO_ERR;
}
debug_data->is_checking_irq = false;
g_core_fp.fp_sense_on(0x00);
return result;
}
static int himax_int_en_read(struct seq_file *m)
{
struct himax_ts_data *ts = private_ts;
int ret = 0;
int check_rslt = -1;
if (debug_data->is_checking_irq) {
check_rslt = test_irq_pin();
if (check_rslt == NO_ERR) {
seq_printf(m,
"IRQ check OK!\n");
} else {
seq_printf(m,
"IRQ check Fail!\n");
}
} else {
seq_printf(m, "irq_status:%d\n",
ts->irq_enabled);
}
return ret;
}
static ssize_t himax_int_en_write(char *buf, size_t len)
{
struct himax_ts_data *ts = private_ts;
int ret = 0;
if (len >= 12) {
I("%s: no command exceeds 12 chars.\n", __func__);
return -EFAULT;
}
if (buf[0] == '0') {
himax_int_enable(0);
} else if (buf[0] == '1') {
himax_int_enable(1);
} else if (buf[0] == '2') {
himax_int_enable(0);
free_irq(ts->hx_irq, ts);
ts->irq_enabled = 0;
} else if (buf[0] == '3') {
ret = himax_int_en_set();
if (ret == 0) {
ts->irq_enabled = 1;
atomic_set(&ts->irq_state, 1);
}
} else if (str_idx_of_str(buf, "test") >= 0) {
debug_data->is_checking_irq = true;
I("Checking IRQ start!\n");
} else
return -EINVAL;
return len;
}
static int himax_irq_info_read(struct seq_file *m)
{
// struct himax_ts_data *ts = private_ts;
int ret = 0;
if (g_core_fp.fp_read_ic_trigger_type() == 1)
seq_printf(m,
"IC Interrupt type is edge trigger.\n");
else if (g_core_fp.fp_read_ic_trigger_type() == 0)
seq_printf(m,
"IC Interrupt type is level trigger.\n");
else
seq_printf(m,
"Unkown IC trigger type.\n");
if (ic_data->HX_INT_IS_EDGE)
seq_printf(m,
"Driver register Interrupt : EDGE TIRGGER\n");
else
seq_printf(m,
"Driver register Interrupt : LEVEL TRIGGER\n");
return ret;
}
static ssize_t himax_irq_info_write(char *buf, size_t len)
{
// struct himax_ts_data *ts = private_ts;
// int ret = 0;
if (len >= 12) {
I("%s: no command exceeds 12 chars.\n", __func__);
return -EFAULT;
}
return len;
}
static int himax_debug_level_read(struct seq_file *m)
{
struct himax_ts_data *ts_data;
int ret = 0;
ts_data = private_ts;
seq_printf(m, "tsdbg: %d\n",
g_ts_dbg);
seq_printf(m, "level: %X\n",
ts_data->debug_log_level);
return ret;
}
static ssize_t himax_debug_level_write(char *buf, size_t len)
{
struct himax_ts_data *ts;
int i;
int cmp_rslt = -1;
ts = private_ts;
if (len >= 12) {
I("%s: no command exceeds 12 chars.\n", __func__);
return -EFAULT;
}
cmp_rslt = str_idx_of_str(buf, "tsdbg");
if (cmp_rslt >= 0) {
if (buf[5] == '1') {
I("Open Ts Debug!\n");
g_ts_dbg = 1;
} else if (buf[5] == '0') {
I("Close Ts Debug!\n");
g_ts_dbg = 0;
} else {
E("Parameter fault for ts debug\n");
}
} else {
ts->debug_log_level = 0;
for (i = 0; i < len; i++) {
if (buf[i] >= '0' && buf[i] <= '9')
ts->debug_log_level |= (buf[i] - '0');
else if (buf[i] >= 'A' && buf[i] <= 'F')
ts->debug_log_level |= (buf[i] - 'A' + 10);
else if (buf[i] >= 'a' && buf[i] <= 'f')
ts->debug_log_level |= (buf[i] - 'a' + 10);
if (i != len - 1)
ts->debug_log_level <<= 4;
}
I("Now debug level value=%d\n", ts->debug_log_level);
if (ts->debug_log_level & BIT(4)) {
I("Turn on/Enable Debug Mode for Inspection!\n");
goto END_FUNC;
}
if (ts->debug_log_level & BIT(3)) {
if (ts->pdata->screenWidth > 0
&& ts->pdata->screenHeight > 0
&& (ts->pdata->abs_x_max - ts->pdata->abs_x_min) > 0
&& (ts->pdata->abs_y_max - ts->pdata->abs_y_min) > 0) {
ts->widthFactor =
(ts->pdata->screenWidth << SHIFTBITS)
/ (ts->pdata->abs_x_max
- ts->pdata->abs_x_min);
ts->heightFactor =
(ts->pdata->screenHeight << SHIFTBITS)
/ (ts->pdata->abs_y_max
- ts->pdata->abs_y_min);
if (ts->widthFactor > 0 &&
ts->heightFactor > 0) {
ts->useScreenRes = 1;
} else {
ts->heightFactor = 0;
ts->widthFactor = 0;
ts->useScreenRes = 0;
}
} else
I("En-finger-dbg with raw position mode!\n");
} else {
ts->useScreenRes = 0;
ts->widthFactor = 0;
ts->heightFactor = 0;
}
}
END_FUNC:
return len;
}
static int himax_proc_register_read(struct seq_file *m)
{
int ret = 0;
uint16_t i;
if (debug_data->is_call_help) {
seq_printf(m, HELP_REGISTER);
debug_data->is_call_help = false;
} else {
memset(proc_reg_buf, 0x00, 128 * sizeof(uint8_t));
I("himax_register_show: %02X,%02X,%02X,%02X\n",
proc_reg_addr[3], proc_reg_addr[2], proc_reg_addr[1],
proc_reg_addr[0]);
if (proc_reg_addr_type == 1) {
ret = himax_bus_read(proc_reg_addr[0], proc_reg_buf,
128);
if (ret < 0) {
E("%s: bus access fail!\n", __func__);
return BUS_FAIL;
}
} else {
if (proc_reg_85xx_flag)
g_core_fp.fp_idle_mode(1);
g_core_fp.fp_register_read(proc_reg_addr, proc_reg_buf,
128);
/* don't enable idle mode ??
*if (proc_reg_85xx_flag)
* g_core_fp.fp_idle_mode(0);
*/
}
seq_printf(m, "command: %02X,%02X,%02X,%02X\n",
proc_reg_addr[3], proc_reg_addr[2], proc_reg_addr[1],
proc_reg_addr[0]);
for (i = 0; i < 128; i++) {
seq_printf(m, "0x%2.2X ", proc_reg_buf[i]);
if ((i % 16) == 15)
seq_puts(m, "\n");
}
seq_puts(m, "\n");
}
return ret;
}
static ssize_t himax_proc_register_write(char *buf, size_t len)
{
char buff_tmp[16] = {0};
uint8_t length = 0;
uint8_t byte_length = 0;
unsigned long result = 0;
uint8_t i = 0;
char *data_str = NULL;
uint8_t w_data[20] = {0};
uint8_t x_pos[20] = {0};
uint8_t count = 0;
int ret = 0;
if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
I("himax %s\n", buf);
if (str_idx_of_str(buf, "help") >= 0) {
debug_data->is_call_help = true;
goto END;
}
memset(proc_reg_addr, 0x0, sizeof(proc_reg_addr));
proc_reg_85xx_flag = 0;
if ((buf[0] == 'r' || buf[0] == 'w')
&& buf[1] == ':' && buf[2] == 'x') {
length = strlen(buf);
/* I("%s: length = %d.\n", __func__,length); */
for (i = 0; i < length; i++) {
/* find postion of 'x' */
if (buf[i] == 'x') {
x_pos[count] = i;
count++;
}
}
data_str = strrchr(buf, 'x');
I("%s: %s.\n", __func__, data_str);
length = strlen(data_str + 1);
switch (buf[0]) {
case 'r':
if (buf[3] == 'F' && buf[4] == 'E' && length == 4) {
length = length - 2;
proc_reg_addr_type = 1;
memcpy(buff_tmp, data_str + 3, length);
} else {
proc_reg_addr_type = 0;
memcpy(buff_tmp, data_str + 1, length);
}
byte_length = length / 2;
if (!kstrtoul(buff_tmp, 16, &result)) {
for (i = 0; i < byte_length; i++)
proc_reg_addr[i] = (uint8_t)(result >> (i * 8));
}
if (strcmp(HX_85XX_H_SERIES_PWON, private_ts->chip_name) == 0)
proc_reg_85xx_flag = 1;
break;
case 'w':
if (buf[3] == 'F' && buf[4] == 'E') {
proc_reg_addr_type = 1;
memcpy(buff_tmp, buf + 5, length);
} else {
proc_reg_addr_type = 0;
memcpy(buff_tmp, buf + 3, length);
}
if (count < 3) {
byte_length = length / 2;
if (!kstrtoul(buff_tmp, 16, &result)) {
/* command */
for (i = 0; i < byte_length; i++)
proc_reg_addr[i] =
(uint8_t)(result >> (i * 8));
}
if (!kstrtoul(data_str + 1, 16, &result)) {
/* data */
for (i = 0; i < byte_length; i++)
w_data[i] = (uint8_t)(result >> i * 8);
}
} else {
for (i = 0; i < count; i++) {
/* parsing addr after 'x' */
memset(buff_tmp, 0x0, sizeof(buff_tmp));
if (proc_reg_addr_type != 0 && i != 0)
byte_length = 2;
else
byte_length = x_pos[1] - x_pos[0] - 2;
/* original */
memcpy(buff_tmp, buf+x_pos[i]+1, byte_length);
if (!kstrtoul(buff_tmp, 16, &result)) {
if (i == 0)
proc_reg_addr[i] =
(uint8_t)(result);
else
w_data[i - 1] =
(uint8_t)(result);
}
}
byte_length = count - 1;
if (strcmp(HX_85XX_H_SERIES_PWON, private_ts->chip_name)
== 0)
proc_reg_85xx_flag = 1;
}
if (proc_reg_addr_type == 1) {
ret = himax_bus_write(proc_reg_addr[0], w_data,
byte_length);
if (ret < 0) {
E("%s: bus access fail!\n", __func__);
return BUS_FAIL;
}
} else {
if (proc_reg_85xx_flag)
g_core_fp.fp_idle_mode(1);
g_core_fp.fp_register_write(proc_reg_addr, w_data,
byte_length);
if (proc_reg_85xx_flag)
g_core_fp.fp_idle_mode(0);
}
break;
};
}
END:
return len;
}
int32_t *getMutualBuffer(void)
{
return diag_mutual;
}
int32_t *getMutualNewBuffer(void)
{
return diag_mutual_new;
}
int32_t *getMutualOldBuffer(void)
{
return diag_mutual_old;
}
int32_t *getSelfBuffer(void)
{
return diag_self;
}
int32_t *getSelfNewBuffer(void)
{
return diag_self_new;
}
int32_t *getSelfOldBuffer(void)
{
return diag_self_old;
}
void setMutualBuffer(uint8_t x_num, uint8_t y_num)
{
diag_mutual = kzalloc(x_num * y_num * sizeof(int32_t), GFP_KERNEL);
}
void setMutualNewBuffer(uint8_t x_num, uint8_t y_num)
{
diag_mutual_new = kzalloc(x_num * y_num * sizeof(int32_t), GFP_KERNEL);
}
void setMutualOldBuffer(uint8_t x_num, uint8_t y_num)
{
diag_mutual_old = kzalloc(x_num * y_num * sizeof(int32_t), GFP_KERNEL);
}
void setSelfBuffer(uint8_t x_num, uint8_t y_num)
{
diag_self = kzalloc((x_num + y_num) * sizeof(int32_t), GFP_KERNEL);
}
void setSelfNewBuffer(uint8_t x_num, uint8_t y_num)
{
diag_self_new = kzalloc((x_num + y_num) * sizeof(int32_t), GFP_KERNEL);
}
void setSelfOldBuffer(uint8_t x_num, uint8_t y_num)
{
diag_self_old = kzalloc((x_num + y_num) * sizeof(int32_t), GFP_KERNEL);
}
#if defined(HX_TP_PROC_2T2R)
int32_t *getMutualBuffer_2(void)
{
return diag_mutual_2;
}
void setMutualBuffer_2(uint8_t x_num_2, uint8_t y_num_2)
{
diag_mutual_2 =
kzalloc(x_num_2 * y_num_2 * sizeof(int32_t), GFP_KERNEL);
}
#endif
int himax_set_diag_cmd(struct himax_ic_data *ic_data,
struct himax_report_data *hx_touch_data)
{
struct himax_ts_data *ts = private_ts;
int32_t *mutual_data;
int32_t *self_data;
int mul_num;
int self_num;
/* int RawDataLen = 0; */
hx_touch_data->diag_cmd = ts->diag_cmd;
if (hx_touch_data->diag_cmd >= 1 && hx_touch_data->diag_cmd <= 7) {
/* Check event stack CRC */
if (!g_core_fp.fp_diag_check_sum(hx_touch_data))
goto bypass_checksum_failed_packet;
#if defined(HX_TP_PROC_2T2R)
if (Is_2T2R && (hx_touch_data->diag_cmd >= 4 &&
hx_touch_data->diag_cmd <= 6)) {
mutual_data = getMutualBuffer_2();
self_data = getSelfBuffer();
/* initiallize the block number of mutual and self */
mul_num = ic_data->HX_RX_NUM_2 * ic_data->HX_TX_NUM_2;
self_num = ic_data->HX_RX_NUM_2 + ic_data->HX_TX_NUM_2;
} else
#endif
{
mutual_data = getMutualBuffer();
self_data = getSelfBuffer();
/* initiallize the block number of mutual and self */
mul_num = ic_data->HX_RX_NUM * ic_data->HX_TX_NUM;
self_num = ic_data->HX_RX_NUM + ic_data->HX_TX_NUM;
}
g_core_fp.fp_diag_parse_raw_data(hx_touch_data, mul_num,
self_num, hx_touch_data->diag_cmd, mutual_data,
self_data);
} else if (hx_touch_data->diag_cmd == 8) {
memset(diag_coor, 0x00, sizeof(diag_coor));
memcpy(&(diag_coor[0]), &hx_touch_data->hx_coord_buf[0],
hx_touch_data->touch_info_size);
}
/* assign state info data */
memcpy(&(hx_state_info[0]), &hx_touch_data->hx_state_info[0], 2);
return NO_ERR;
bypass_checksum_failed_packet:
return 1;
}
/* #if defined(HX_DEBUG_LEVEL) */
void himax_log_touch_data(int start)
{
int i = 0;
int print_size = 0;
uint8_t *buf = NULL;
if (start == 1)
return; /* report data when end of ts_work*/
if (hx_touch_data->diag_cmd > 0) {
print_size = hx_touch_data->touch_all_size;
buf = kcalloc(print_size, sizeof(uint8_t), GFP_KERNEL);
if (buf == NULL) {
E("%s, Failed to allocate memory\n", __func__);
return;
}
memcpy(buf, hx_touch_data->hx_coord_buf,
hx_touch_data->touch_info_size);
memcpy(&buf[hx_touch_data->touch_info_size],
hx_touch_data->hx_rawdata_buf,
print_size - hx_touch_data->touch_info_size);
}
#if defined(HX_SMART_WAKEUP)
else if (private_ts->SMWP_enable > 0 && private_ts->suspended) {
print_size = hx_touch_data->event_size;
buf = kcalloc(print_size, sizeof(uint8_t), GFP_KERNEL);
if (buf == NULL) {
E("%s, Failed to allocate memory\n", __func__);
return;
}
memcpy(buf, hx_touch_data->hx_event_buf, print_size);
}
#endif
else if (hx_touch_data->diag_cmd == 0) {
print_size = hx_touch_data->touch_info_size;
buf = kcalloc(print_size, sizeof(uint8_t), GFP_KERNEL);
if (buf == NULL) {
E("%s, Failed to allocate memory\n", __func__);
return;
}
memcpy(buf, hx_touch_data->hx_coord_buf, print_size);
} else {
E("%s:cmd fault\n", __func__);
return;
}
for (i = 0; i < print_size; i += 8) {
if ((i + 7) >= print_size) {
I("P %2d = 0x%2.2X P %2d = 0x%2.2X ",
i,
buf[i],
i + 1,
buf[i + 1]);
I("P %2d = 0x%2.2X P %2d = 0x%2.2X\n",
i + 2,
buf[i + 2],
i + 3,
buf[i + 3]);
break;
}
I("P %2d = 0x%2.2X P %2d = 0x%2.2X ",
i, buf[i], i + 1, buf[i + 1]);
I("P %2d = 0x%2.2X P %2d = 0x%2.2X ",
i + 2, buf[i + 2], i + 3, buf[i + 3]);
I("P %2d = 0x%2.2X P %2d = 0x%2.2X ",
i + 4, buf[i + 4], i + 5, buf[i + 5]);
I("P %2d = 0x%2.2X P %2d = 0x%2.2X ",
i + 6, buf[i + 6], i + 7, buf[i + 7]);
I("\n");
}
kfree(buf);
}
void himax_log_touch_event(struct himax_ts_data *ts, int start)
{
int i = 0;
if (start == 1)
return; /*report data when end of ts_work*/
if (g_target_report_data->finger_on > 0 &&
g_target_report_data->finger_num > 0) {
for (i = 0; i < ts->nFinger_support; i++) {
if (g_target_report_data->p[i].x >= 0
&& g_target_report_data->p[i].x
<= ts->pdata->abs_x_max
&& g_target_report_data->p[i].y >= 0
&& g_target_report_data->p[i].y
<= ts->pdata->abs_y_max) {
I(PRT_LOG,
i + 1,
g_target_report_data->p[i].x,
g_target_report_data->p[i].y,
g_target_report_data->p[i].w,
g_target_report_data->p[i].w,
i + 1,
g_target_report_data->ig_count);
}
}
} else if (g_target_report_data->finger_on == 0
&& g_target_report_data->finger_num == 0) {
I("All Finger leave\n");
} else {
I("%s : wrong input!\n", __func__);
}
}
void himax_log_touch_int_devation(int touched)
{
if (touched == HX_FINGER_ON) {
#if defined(KERNEL_VER_ABOVE_5_10)
ktime_get_ts64(&timeStart);
#else
getnstimeofday(&timeStart);
#endif
/* I(" Irq start time = %ld.%06ld s\n",
* timeStart.tv_sec, timeStart.tv_nsec/1000);
*/
} else if (touched == HX_FINGER_LEAVE) {
#if defined(KERNEL_VER_ABOVE_5_10)
ktime_get_ts64(&timeEnd);
#else
getnstimeofday(&timeEnd);
#endif
timeDelta.tv_nsec =
(timeEnd.tv_sec * 1000000000 + timeEnd.tv_nsec) -
(timeStart.tv_sec * 1000000000 + timeStart.tv_nsec);
/* I("Irq finish time = %ld.%06ld s\n",
* timeEnd.tv_sec, timeEnd.tv_nsec/1000);
*/
I("Touch latency = %ld us\n", timeDelta.tv_nsec / 1000);
I("bus_speed = %d kHz\n", private_ts->bus_speed);
if (g_target_report_data->finger_on == 0
&& g_target_report_data->finger_num == 0)
I("All Finger leave\n");
} else {
I("%s : wrong input!\n", __func__);
}
}
void himax_log_touch_event_detail(struct himax_ts_data *ts, int start)
{
int i = 0;
if (start == HX_FINGER_LEAVE) {
for (i = 0; i < ts->nFinger_support; i++) {
if (((ts->old_finger >> i & 1) == 0)
&& ((ts->pre_finger_mask >> i & 1) == 1)) {
if (g_target_report_data->p[i].x >= 0
&& g_target_report_data->p[i].x
<= ts->pdata->abs_x_max
&& g_target_report_data->p[i].y >= 0
&& g_target_report_data->p[i].y
<= ts->pdata->abs_y_max) {
I(RAW_DOWN_STATUS, i + 1,
g_target_report_data->p[i].x,
g_target_report_data->p[i].y,
g_target_report_data->p[i].w);
}
} else if ((((ts->old_finger >> i & 1) == 1)
&& ((ts->pre_finger_mask >> i & 1) == 0))) {
I(RAW_UP_STATUS, i + 1,
ts->pre_finger_data[i][0],
ts->pre_finger_data[i][1]);
} else {
/* I("dbg hx_point_num=%d, old_finger=0x%02X,"
* " pre_finger_mask=0x%02X\n",
* ts->hx_point_num, ts->old_finger,
* ts->pre_finger_mask);
*/
}
}
}
}
void himax_ts_dbg_func(struct himax_ts_data *ts, int start)
{
if (ts->debug_log_level & BIT(0)) {
/* I("debug level 1\n"); */
himax_log_touch_data(start);
}
if (ts->debug_log_level & BIT(1)) {
/* I("debug level 2\n"); */
himax_log_touch_event(ts, start);
}
if (ts->debug_log_level & BIT(2)) {
/* I("debug level 4\n"); */
himax_log_touch_int_devation(start);
}
if (ts->debug_log_level & BIT(3)) {
/* I("debug level 8\n"); */
himax_log_touch_event_detail(ts, start);
}
}
static int himax_change_mode(uint8_t str_pw, uint8_t end_pw)
{
uint8_t data[4] = {0};
int count = 0;
/*sense off*/
g_core_fp.fp_sense_off(true);
/*mode change*/
data[1] = str_pw; data[0] = str_pw;
if (g_core_fp.fp_assign_sorting_mode != NULL)
g_core_fp.fp_assign_sorting_mode(data);
/*sense on*/
g_core_fp.fp_sense_on(1);
/*wait mode change*/
do {
if (g_core_fp.fp_check_sorting_mode != NULL)
g_core_fp.fp_check_sorting_mode(data);
if ((data[0] == end_pw) && (data[1] == end_pw))
return 0;
I("Now retry %d times!\n", count);
count++;
msleep(50);
} while (count < 50);
return ERR_WORK_OUT;
}
static ssize_t himax_irq_dbg_cmd_write(char *buf, size_t len)
{
// struct himax_ts_data *ts = private_ts;
int cmd = 0;
if (!kstrtoint(buf, 16, &cmd)) {
I("%s, now irq_dbg status=%d!\n", __func__, cmd);
g_ts_dbg = cmd;
} else {
E("%s: command not int!\n", __func__);
}
return len;
}
static ssize_t himax_diag_cmd_write(char *buf, size_t len)
{
struct himax_ts_data *ts = private_ts;
char *dbg_map_str = "mode:";
char *str_ptr = NULL;
int str_len = 0;
int rst = 0;
uint8_t str_pw = 0;
uint8_t end_pw = 0;
if (str_idx_of_str(buf, "help") >= 0) {
debug_data->is_call_help = true;
goto END;
}
switch (len) {
case 1:/*raw out select - diag,X*/
if (!kstrtoint(buf, 16, &rst)) {
ts->diag_cmd = rst;
I("%s: dsram_flag = %d\n", __func__, dsram_flag);
if (dsram_flag) {
/*Cancal work queue and return to stack*/
process_type = 0;
while (dsram_flag == true)
usleep_range(10000, 11000);
cancel_delayed_work(&ts->himax_diag_delay_work);
himax_int_enable(1);
g_core_fp.fp_return_event_stack();
}
g_core_fp.fp_diag_register_set(ts->diag_cmd, 0, false);
I("%s: Set raw out select 0x%X.\n",
__func__, ts->diag_cmd);
}
if (!ts->diag_cmd) {
if (mode_flag) /*back to normal mode*/
himax_change_mode(0x00, 0x99);
}
break;
case 2:/*data processing + rawout select - diag,XY*/
if (!kstrtoint(buf, 16, &rst)) {
process_type = (rst >> 4) & 0xF;
ts->diag_cmd = rst & 0xF;
}
if (ts->diag_cmd == 0)
break;
else if (process_type > 0 && process_type <= 3) {
if (!dsram_flag) {
/*Start wrok queue*/
himax_int_enable(0);
g_core_fp.fp_diag_register_set(ts->diag_cmd,
process_type, false);
queue_delayed_work(ts->himax_diag_wq,
&ts->himax_diag_delay_work, 2 * HZ / 100);
dsram_flag = true;
I("%s: Start get raw data in DSRAM\n",
__func__);
} else {
g_core_fp.fp_diag_register_set(ts->diag_cmd,
process_type, false);
}
}
break;
case 4:/*data processing + rawout select - diag,XXYY*/
/*ex:XXYY=010A=dsram rawdata*/
I("%s, now case 4\n", __func__);
if (!kstrtoint(buf, 16, &rst)) {
process_type = (rst >> 8) & 0xFF;
ts->diag_cmd = rst & 0xFF;
I("%s:process_type=0x%02X, diag_cmd=0x%02X\n",
__func__, process_type, ts->diag_cmd);
}
if (process_type <= 0 || ts->diag_cmd <= 0)
break;
else if (process_type > 0 && process_type <= 3) {
if (!dsram_flag) {
/*Start wrok queue*/
himax_int_enable(0);
g_core_fp.fp_diag_register_set(ts->diag_cmd,
process_type, true);
queue_delayed_work(ts->himax_diag_wq,
&ts->himax_diag_delay_work, 2 * HZ / 100);
dsram_flag = true;
I("%s: Start get raw data in DSRAM\n",
__func__);
} else {
g_core_fp.fp_diag_register_set(ts->diag_cmd,
process_type, true);
}
}
break;
case 9:/*change mode - mode:XXYY(start PW,end PW)*/
str_ptr = strnstr(buf, dbg_map_str, len);
if (str_ptr) {
str_len = strlen(dbg_map_str);
if (!kstrtoint(buf + str_len, 16, &rst)) {
str_pw = (rst >> 8) & 0xFF;
end_pw = rst & 0xFF;
if (!himax_change_mode(str_pw, end_pw)) {
mode_flag = 1;
I(PRT_OK_LOG, __func__,
rst, str_pw, end_pw);
} else
I(PRT_FAIL_LOG, __func__,
str_pw, end_pw);
}
} else {
I("%s: Can't find string [%s].\n",
__func__, dbg_map_str);
}
break;
default:
I("%s: Length is not correct.\n", __func__);
}
END:
return len;
}
static int himax_diag_arrange_read(struct seq_file *m)
{
int ret = NO_ERR;
if (debug_data->is_call_help) {
seq_printf(m, HELP_DIAG_ARR);
debug_data->is_call_help = false;
} else {
seq_printf(m, "diag value=%d\n", g_diag_arr_num);
}
return ret;
}
static ssize_t himax_diag_arrange_write(char *buf, size_t len)
{
if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (str_idx_of_str(buf, "help") >= 0) {
debug_data->is_call_help = true;
} else {
g_diag_arr_num = buf[0] - '0';
I("%s: g_diag_arr_num = %d\n", __func__, g_diag_arr_num);
}
return len;
}
void himax_get_mutual_edge(void)
{
int i = 0;
for (i = 0; i < (ic_data->HX_RX_NUM * ic_data->HX_TX_NUM); i++) {
if (diag_mutual[i] > g_max_mutual)
g_max_mutual = diag_mutual[i];
if (diag_mutual[i] < g_min_mutual)
g_min_mutual = diag_mutual[i];
}
}
void himax_get_self_edge(void)
{
int i = 0;
for (i = 0; i < (ic_data->HX_RX_NUM + ic_data->HX_TX_NUM); i++) {
if (diag_self[i] > g_max_self)
g_max_self = diag_self[i];
if (diag_self[i] < g_min_self)
g_min_self = diag_self[i];
}
}
static void print_state_info(struct seq_file *s)
{
/* seq_printf(s, "State_info_2bytes:%3d, %3d\n",
* _state_info[0],hx_state_info[1]);
*/
#if defined(HX_NEW_EVENT_STACK_FORMAT)
seq_printf(s, "ReCal = %d\t", hx_state_info[0] & 0x03);
seq_printf(s, "Base Line = %d\t", hx_state_info[0] >> 2 & 0x01);
seq_printf(s, "Palm = %d\t", hx_state_info[0] >> 3 & 0x01);
seq_printf(s, "Idle mode = %d\t", hx_state_info[0] >> 4 & 0x01);
seq_printf(s, "Water = %d\n", hx_state_info[0] >> 5 & 0x01);
seq_printf(s, "TX Hop = %d\t", hx_state_info[0] >> 6 & 0x01);
seq_printf(s, "AC mode = %d\t", hx_state_info[0] >> 7 & 0x01);
seq_printf(s, "Glove = %d\t", hx_state_info[1] & 0x01);
seq_printf(s, "Stylus = %d\t", hx_state_info[1] >> 1 & 0x01);
seq_printf(s, "Hovering = %d\t", hx_state_info[1] >> 2 & 0x01);
seq_printf(s, "Proximity = %d\t", hx_state_info[1] >> 3 & 0x01);
seq_printf(s, "KEY = %d\n", hx_state_info[1] >> 4 & 0x0F);
#else
seq_printf(s, "ReCal = %d\t", hx_state_info[0] & 0x01);
seq_printf(s, "Palm = %d\t", hx_state_info[0] >> 1 & 0x01);
seq_printf(s, "AC mode = %d\t", hx_state_info[0] >> 2 & 0x01);
seq_printf(s, "Water = %d\n", hx_state_info[0] >> 3 & 0x01);
seq_printf(s, "Glove = %d\t", hx_state_info[0] >> 4 & 0x01);
seq_printf(s, "TX Hop = %d\t", hx_state_info[0] >> 5 & 0x01);
seq_printf(s, "Base Line = %d\t", hx_state_info[0] >> 6 & 0x01);
seq_printf(s, "OSR Hop = %d\t", hx_state_info[1] >> 3 & 0x01);
seq_printf(s, "KEY = %d\n", hx_state_info[1] >> 4 & 0x0F);
#endif
}
static void himax_diag_arrange_print(struct seq_file *s, int i, int j,
int transpose)
{
if (transpose)
seq_printf(s, "%6d", diag_mutual[j + i * ic_data->HX_RX_NUM]);
else
seq_printf(s, "%6d", diag_mutual[i + j * ic_data->HX_RX_NUM]);
}
/* ready to print second step which is column*/
static void himax_diag_arrange_inloop(struct seq_file *s, int in_init,
int out_init, bool transpose, int j)
{
int x_channel = ic_data->HX_RX_NUM;
int y_channel = ic_data->HX_TX_NUM;
int i;
int in_max = 0;
if (transpose)
in_max = y_channel;
else
in_max = x_channel;
if (in_init > 0) { /* bit0 = 1 */
for (i = in_init - 1; i >= 0; i--)
himax_diag_arrange_print(s, i, j, transpose);
if (transpose) {
if (out_init > 0)
seq_printf(s, " %5d\n", diag_self[j]);
else
seq_printf(s, " %5d\n",
diag_self[x_channel - j - 1]);
}
} else { /* bit0 = 0 */
for (i = 0; i < in_max; i++)
himax_diag_arrange_print(s, i, j, transpose);
if (transpose) {
if (out_init > 0)
seq_printf(s, " %5d\n",
diag_self[x_channel - j - 1]);
else
seq_printf(s, " %5d\n", diag_self[j]);
}
}
}
/* print first step which is row */
static void himax_diag_arrange_outloop(struct seq_file *s, int transpose,
int out_init, int in_init)
{
int j;
int x_channel = ic_data->HX_RX_NUM;
int y_channel = ic_data->HX_TX_NUM;
int out_max = 0;
int self_cnt = 0;
if (transpose)
out_max = x_channel;
else
out_max = y_channel;
if (out_init > 0) { /* bit1 = 1 */
self_cnt = 1;
for (j = out_init - 1; j >= 0; j--) {
seq_printf(s, "%3c%02d%c", '[', j + 1, ']');
himax_diag_arrange_inloop(s, in_init, out_init,
transpose, j);
if (!transpose) {
seq_printf(s, " %5d\n",
diag_self[y_channel + x_channel - self_cnt]);
self_cnt++;
}
}
} else { /* bit1 = 0 */
/* self_cnt = x_channel; */
for (j = 0; j < out_max; j++) {
seq_printf(s, "%3c%02d%c", '[', j + 1, ']');
himax_diag_arrange_inloop(s, in_init, out_init,
transpose, j);
if (!transpose) {
seq_printf(s, " %5d\n",
diag_self[j + x_channel]);
}
}
}
}
/* determin the output format of diag */
static void himax_diag_arrange(struct seq_file *s)
{
int x_channel = ic_data->HX_RX_NUM;
int y_channel = ic_data->HX_TX_NUM;
int bit2, bit1, bit0;
int i;
/* rotate bit */
bit2 = g_diag_arr_num >> 2;
/* reverse Y */
bit1 = g_diag_arr_num >> 1 & 0x1;
/* reverse X */
bit0 = g_diag_arr_num & 0x1;
if (g_diag_arr_num < 4) {
for (i = 0 ; i <= x_channel; i++)
seq_printf(s, "%3c%02d%c", '[', i, ']');
seq_puts(s, "\n");
himax_diag_arrange_outloop(s, bit2, bit1 * y_channel,
bit0 * x_channel);
seq_printf(s, "%6c", ' ');
if (bit0 == 1) {
for (i = x_channel - 1; i >= 0; i--)
seq_printf(s, "%6d", diag_self[i]);
} else {
for (i = 0; i < x_channel; i++)
seq_printf(s, "%6d", diag_self[i]);
}
} else {
for (i = 0 ; i <= y_channel; i++)
seq_printf(s, "%3c%02d%c", '[', i, ']');
seq_puts(s, "\n");
himax_diag_arrange_outloop(s, bit2, bit1 * x_channel,
bit0 * y_channel);
seq_printf(s, "%6c", ' ');
if (bit1 == 1) {
for (i = x_channel + y_channel - 1; i >= x_channel;
i--)
seq_printf(s, "%6d", diag_self[i]);
} else {
for (i = x_channel; i < x_channel + y_channel; i++)
seq_printf(s, "%6d", diag_self[i]);
}
}
}
/* DSRAM thread */
bool himax_ts_diag_func(int dsram_type)
{
int i = 0, j = 0;
unsigned int index = 0;
int x_channel = ic_data->HX_RX_NUM;
int y_channel = ic_data->HX_TX_NUM;
int total_size = (y_channel * x_channel + y_channel + x_channel) * 2;
uint8_t *info_data = NULL;
int32_t *mutual_data = NULL;
int32_t *mutual_data_new = NULL;
int32_t *mutual_data_old = NULL;
int32_t *self_data = NULL;
int32_t *self_data_new = NULL;
int32_t *self_data_old = NULL;
int32_t new_data;
/* 1:common dsram,2:100 frame Max,3:N-(N-1)frame */
if (dsram_type < 1 || dsram_type > 3) {
E("%s: type %d is out of range\n", __func__, dsram_type);
return false;
}
info_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL);
if (info_data == NULL) {
E("%s: Failed to allocate memory\n", __func__);
return false;
}
memset(info_data, 0, total_size * sizeof(uint8_t));
g_core_fp.fp_burst_enable(1);
if (dsram_type == 1 || dsram_type == 2) {
mutual_data = getMutualBuffer();
self_data = getSelfBuffer();
} else if (dsram_type == 3) {
mutual_data = getMutualBuffer();
mutual_data_new = getMutualNewBuffer();
mutual_data_old = getMutualOldBuffer();
self_data = getSelfBuffer();
self_data_new = getSelfNewBuffer();
self_data_old = getSelfOldBuffer();
}
if (!g_core_fp.fp_get_DSRAM_data(info_data, dsram_flag)) {
E("%s: Get DSRAM data failed\n", __func__);
kfree(info_data);
return false;
}
index = 0;
for (i = 0; i < y_channel; i++) { /*mutual data*/
for (j = 0; j < x_channel; j++) {
new_data = (((int8_t)info_data[index + 1] << 8) |
info_data[index]);
if (dsram_type <= 1) {
mutual_data[i * x_channel + j] = new_data;
} else if (dsram_type == 2) { /* Keep max data */
if (mutual_data[i * x_channel + j] < new_data)
mutual_data[i * x_channel + j] =
new_data;
} else if (dsram_type == 3) {
/* Cal data for [N]-[N-1] frame */
mutual_data_new[i * x_channel + j] = new_data;
mutual_data[i * x_channel + j] =
mutual_data_new[i * x_channel + j]
- mutual_data_old[i * x_channel + j];
}
index += 2;
}
}
for (i = 0; i < x_channel + y_channel; i++) { /*self data*/
new_data = (((int8_t)info_data[index + 1] << 8) |
info_data[index]);
if (dsram_type <= 1) {
self_data[i] = new_data;
} else if (dsram_type == 2) { /* Keep max data */
if (self_data[i] < new_data)
self_data[i] = new_data;
} else if (dsram_type == 3) { /* Cal data for [N]-[N-1] frame */
self_data_new[i] = new_data;
self_data[i] = self_data_new[i] - self_data_old[i];
}
index += 2;
}
kfree(info_data);
if (dsram_type == 3) {
memcpy(mutual_data_old, mutual_data_new,
x_channel * y_channel * sizeof(int32_t));
/* copy N data to N-1 array */
memcpy(self_data_old, self_data_new,
(x_channel + y_channel) * sizeof(int32_t));
/* copy N data to N-1 array */
}
return true;
}
static int himax_diag_print(struct seq_file *s, void *v)
{
int x_num = ic_data->HX_RX_NUM;
int y_num = ic_data->HX_TX_NUM;
size_t ret = 0;
uint16_t mutual_num, self_num, width;
mutual_num = x_num * y_num;
self_num = x_num + y_num;
/* don't add KEY_COUNT */
width = x_num;
seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_num, y_num);
/* start to show out the raw data in adb shell */
himax_diag_arrange(s);
seq_puts(s, "\n");
seq_puts(s, "ChannelEnd");
seq_puts(s, "\n");
/* print Mutual/Slef Maximum and Minimum */
himax_get_mutual_edge();
himax_get_self_edge();
seq_printf(s, "Mutual Max:%3d, Min:%3d\n", g_max_mutual,
g_min_mutual);
seq_printf(s, "Self Max:%3d, Min:%3d\n", g_max_self,
g_min_self);
/* recovery status after print*/
g_max_mutual = 0;
g_min_mutual = 0xFFFF;
g_max_self = 0;
g_min_self = 0xFFFF;
/*pring state info*/
print_state_info(s);
if (s->count >= s->size)
overflow++;
return ret;
}
static int himax_stack_show(struct seq_file *s, void *v)
{
struct himax_ts_data *ts = private_ts;
if (debug_data->is_call_help) {
seq_puts(s, HELP_DIAG);
debug_data->is_call_help = false;
} else {
if (ts->diag_cmd)
himax_diag_print(s, v);
else
seq_puts(s, "Please set raw out select 'echo diag,X > debug'\n\n");
}
return 0;
}
__CREATE_OREAD_NODE_HX(stack);
static int himax_sram_read(struct seq_file *s, void *v, uint8_t rs)
{
struct himax_ts_data *ts = private_ts;
int d_type = 0;
int current_size =
((ic_data->HX_TX_NUM + 1) * (ic_data->HX_RX_NUM + 1)
+ ic_data->HX_TX_NUM + ic_data->HX_RX_NUM) * 6 + 256;
if (debug_data->is_call_help) {
seq_puts(s, HELP_DIAG);
debug_data->is_call_help = false;
} else {
d_type = (!ts->diag_cmd)?rs:ts->diag_cmd;
I("%s, s->size = %d\n", __func__, (int)s->size);
I("%s, sizeof(s->buf) = %d\n", __func__, (int)sizeof(s->buf));
s->size = current_size;
s->buf = kcalloc(s->size, sizeof(char), GFP_KERNEL);
if (s->buf == NULL) {
E("%s,%d: Memory allocation falied!\n",
__func__, __LINE__);
return -ENOMEM;
}
memset(s->buf, 0, s->size * sizeof(char));
if (!overflow) {
if (!process_type) {
himax_int_enable(0);
g_core_fp.fp_diag_register_set(d_type,
0, false);
/* use process type 1 for default */
if (!himax_ts_diag_func(1))
seq_puts(s, "Get sram data failed.");
else
himax_diag_print(s, v);
ts->diag_cmd = 0;
g_core_fp.fp_diag_register_set(0, 0, false);
himax_int_enable(1);
}
}
if ((process_type <= 3
&& ts->diag_cmd
&& dsram_flag)
|| overflow) {
himax_diag_print(s, v);
overflow = 0;
}
}
return 0;
}
static int himax_delta_show(struct seq_file *s, void *v)
{
return himax_sram_read(s, v, 0x09);
}
__CREATE_OREAD_NODE_HX(delta);
static int himax_dc_show(struct seq_file *s, void *v)
{
return himax_sram_read(s, v, 0x0A);
}
__CREATE_OREAD_NODE_HX(dc);
static int himax_baseline_show(struct seq_file *s, void *v)
{
return himax_sram_read(s, v, 0x0B);
}
__CREATE_OREAD_NODE_HX(baseline);
#if defined(HX_RST_PIN_FUNC)
static void test_rst_pin(void)
{
int rst_sts1 = -1;
int rst_sts2 = -1;
int cnt = 0;
uint8_t tmp_addr[DATA_LEN_4] = {0};
uint8_t tmp_data[DATA_LEN_4] = {0};
uint8_t tmp_read[DATA_LEN_4] = {0};
himax_int_enable(0);
g_core_fp.fp_sense_off(true);
usleep_range(20000, 20001);
himax_parse_assign_cmd(0x900000F0, tmp_addr, DATA_LEN_4);
himax_parse_assign_cmd(0x00000001, tmp_data, DATA_LEN_4);
g_core_fp.fp_register_write(tmp_addr, tmp_data, DATA_LEN_4);
usleep_range(20000, 20001);
g_core_fp.fp_register_read(tmp_addr, tmp_read, DATA_LEN_4);
I("R%02X%02X%02X%02XH = 0x%02X%02X%02X%02X\n",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]);
I("trigger Reset Pin\n");
g_core_fp.fp_ic_reset(false, false);
usleep_range(20000, 20001);
do {
himax_parse_assign_cmd(0x900000A8, tmp_addr, DATA_LEN_4);
g_core_fp.fp_register_read(tmp_addr, tmp_read, DATA_LEN_4);
I("R%02X%02X%02X%02XH = 0x%02X%02X%02X%02X\n",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]);
rst_sts1 = tmp_read[0];
cnt++;
if (rst_sts1 == 0x05)
break;
if (rst_sts1 == 0x00)
cnt += 5;
if (cnt > 20)
goto END_FUNC;
} while (rst_sts1 == 0x04);
himax_parse_assign_cmd(0x900000F0, tmp_addr, DATA_LEN_4);
g_core_fp.fp_register_read(tmp_addr, tmp_read, DATA_LEN_4);
I("R%02X%02X%02X%02XH = 0x%02X%02X%02X%02X\n",
tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0],
tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]);
rst_sts2 = tmp_read[0];
END_FUNC:
if (rst_sts1 == 0x05 && rst_sts2 == 0x00)
I("%s: TP Reset test OK!\n", __func__);
else if (rst_sts1 == 0xFF || rst_sts2 == 0x01)
I("%s: TP Reset test Fail!\n", __func__);
else
I("%s, Unknown Fail state1=0x%02X, state2=0x%02X!\n",
__func__, rst_sts1, rst_sts2);
g_core_fp.fp_sense_on(0x00);
himax_int_enable(1);
}
#endif
static int himax_reset_read(struct seq_file *m)
{
int ret = 0;
I("%s: enter, %d\n", __func__, __LINE__);
if (debug_data->is_call_help) {
seq_printf(m, HELP_RST);
debug_data->is_call_help = false;
} else {
if (g_test_result) {
seq_printf(m,"Result: Pass\n");
} else {
seq_printf(m,"Result: Fail\n");
}
}
return ret;
}
static ssize_t himax_reset_write(char *buf, size_t len)
{
int ret = 0;
g_test_result = false;
if (len >= 12) {
I("%s: no command exceeds 12 chars.\n", __func__);
return -EFAULT;
}
if (str_idx_of_str(buf, "help") >= 0) {
debug_data->is_call_help = true;
} else {
#if defined(HX_RST_PIN_FUNC)
if (buf[0] == '1')
ret = g_core_fp.fp_ic_reset(false, false);
else if (buf[0] == '2')
ret = g_core_fp.fp_ic_reset(false, true);
/* else if (buf[0] == '5') */
/* ESD_HW_REST(); */
else if (str_idx_of_str(buf, "test") >= 0)
test_rst_pin();
#endif
#if defined(HX_ZERO_FLASH)
if (g_core_fp.fp_0f_reload_to_active)
g_core_fp.fp_0f_reload_to_active();
#endif
if (ret) {
g_test_result = true;
}
}
return len;
}
void hx_dump_prog_set(uint8_t prog)
{
g_flash_progress = prog;
if (prog == ONGOING)
debug_data->flash_dump_going = ONGOING;
else
debug_data->flash_dump_going = START;
}
static int himax_flash_dump_show(struct seq_file *s, void *v)
{
ssize_t ret = 0;
int i;
uint8_t flash_progress = g_flash_progress;
// uint8_t flash_cmd = g_dump_show;
bool flash_rst = g_flash_dump_rst;
I("dump_progress = %d\n", flash_progress);
if (!flash_rst) {
seq_puts(s, "DumpStart:Fail\n");
seq_puts(s, "DumpEnd\n");
goto END;
}
if (flash_progress == START)
seq_puts(s, "Dump - Start\n");
else if (flash_progress == ONGOING)
seq_puts(s, "Dump - On-going\n");
else if (flash_progress == FINISHED)
seq_puts(s, "Dump - Finished\n");
/*print flash dump data*/
if (g_dump_show == 2 && flash_progress == FINISHED) {
seq_puts(s, "Start to print dump data\n");
for (i = 0; i < ic_data->flash_size; i++) {
seq_printf(s, "0x%02X,", g_dump_buffer[i]);
if (i % 16 == 15)
seq_puts(s, "\n");
}
}
seq_puts(s, "DumpEnd\n");
END:
return ret;
}
#define FDS_DBG1 "%s, input cmd:is_flash=%d, is_file=%d, dump_size=%d, addr=0x%08X\n"
#define FDS_DBG2 "%s, assigned:is_flash=%d, is_file=%d, dump_size=%d, addr=0x%08X\n"
static ssize_t himax_flash_dump_store(struct file *filp,
const char __user *buff, size_t len, loff_t *data)
{
char buf[80] = {0};
char *input_str[4];
int i = 0;
int is_flash = -1;
int is_file = -1;
int dump_size = -1;
uint32_t addr = 0x000000;
g_dump_cmd = 0;
g_dump_size = 0;
g_dump_show = 0;
g_dump_addr = 0;
if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, buff, len))
return -EFAULT;
I("%s: buf = %s\n", __func__, buf);
if (g_flash_progress == ONGOING) {
E("%s: process is busy , return!\n", __func__);
return len;
}
buf[len - 1] = '\0';
for (i = 0; i < 4; i++)
input_str[i] = kzalloc(sizeof(char) * 128, GFP_KERNEL);
_str_to_arr_in_char(input_str, 4, buf, ',');
for (i = 0; i < 4; i++) {
if (input_str[i] == NULL) {
continue;
} else {
I("%d:%s\n", i, input_str[i]);
switch (i) {
case 0:
if (str_idx_of_str(input_str[i],
"help") >= 0) {
is_flash = 0;
goto CON_WORK;
} else if (str_idx_of_str(input_str[i],
"flash") >= 0) {
is_flash = 1;
} else if (str_idx_of_str(input_str[i],
"ram") >= 0) {
is_flash = 2;
} else {
is_flash = -1;
goto CON_WORK;
}
break;
case 1:
if (str_idx_of_str(input_str[i],
"print") >= 0) {
is_file = 2;
} else if (str_idx_of_str(input_str[i],
"file") >= 0) {
is_file = 1;
} else {
is_file = -1;
goto CON_WORK;
}
break;
case 2:
dump_size = hiamx_parse_str2int(
input_str[i]);
break;
case 3:
if (input_str[i] == NULL)
addr = 0x00;
else
addr = hx_parse_hexstr2int(
input_str[i]);
I("addr=%d\n", addr);
break;
default:
break;
}
}
}
CON_WORK:
I(FDS_DBG1,
__func__, is_flash, is_file, dump_size, addr);
/*
*
* if ((buf[1] == '_') && (buf[2] == '3') && (buf[3] == '2'))
* g_dump_size = FW_SIZE_32k;
* else if ((buf[1] == '_') && (buf[2] == '6')) {
* if (buf[3] == '0')
* g_dump_size = FW_SIZE_60k;
* else if (buf[3] == '4')
* g_dump_size = FW_SIZE_64k;
*} else if ((buf[1] == '_') && (buf[2] == '2')) {
* if (buf[3] == '4')
* g_dump_size = FW_SIZE_124k;
* else if (buf[3] == '8')
* g_dump_size = FW_SIZE_128k;
*}
*
* //1 : print flash to window, 2 : dump to sdcard
*if (buf[0] == '1') {
* //1_32,1_60,1_64,1_24,1_28 for flash size:
* // 32k,60k,64k,124k,128k
*
* g_dump_cmd = 1;
* hx_dump_prog_set(START);
* g_flash_dump_rst = true;
* queue_work(private_ts->dump_wq, &private_ts->dump_work);
*} else if (buf[0] == '2') {
* // 2_32,2_60,2_64,2_24,2_28 for dump size:
* // 32k,60k,64k,124k,128k
*
* g_dump_cmd = 2;
* hx_dump_prog_set(START);
* g_flash_dump_rst = true;
* queue_work(private_ts->dump_wq, &private_ts->dump_work);
*}
**/
g_dump_cmd = is_flash;
g_dump_size = dump_size;
g_dump_show = is_file;
g_dump_addr = addr;
I(FDS_DBG2,
__func__, g_dump_cmd, g_dump_show, g_dump_size, g_dump_addr);
hx_dump_prog_set(START);
g_flash_dump_rst = true;
queue_work(private_ts->dump_wq, &private_ts->dump_work);
for (i = 0; i < 4; i++)
kfree(input_str[i]);
return len;
}
__CREATE_RW_NODE_HX(flash_dump);
void himax_ts_dump_func(void)
{
uint8_t tmp_addr[DATA_LEN_4] = {0};
int ret = NO_ERR;
hx_dump_prog_set(ONGOING);
/*msleep(100);*/
// I("%s: flash_command = %d enter.\n", __func__, flash_command);
I("%s: entering, is_flash=%d, is_file=%d, size=%d, add=0x%08X\n",
__func__, g_dump_cmd, g_dump_show, g_dump_size, g_dump_addr);
if (g_dump_cmd == 1) {
himax_int_enable(0);
g_core_fp.fp_flash_dump_func(g_dump_cmd, g_dump_size,
g_dump_buffer);
g_flash_dump_rst = true;
himax_int_enable(1);
} else if (g_dump_cmd == 2) {
I("dump ram start\n");
if (g_dump_addr != -948794) {
tmp_addr[0] = g_dump_addr % 0x100;
tmp_addr[1] = (g_dump_addr >> 8) % 0x100;
tmp_addr[2] = (g_dump_addr >> 16) % 0x100;
tmp_addr[3] = g_dump_addr / 0x1000000;
ret = g_core_fp.fp_register_read(tmp_addr,
g_dump_buffer, g_dump_size);
g_flash_dump_rst = true;
} else {
E("addr is wrong!\n");
g_flash_dump_rst = false;
goto END;
}
if (ret) {
E("read ram fail, please check cmd !\n");
g_flash_dump_rst = false;
goto END;
}
}
I("Dump Complete\n");
END:
hx_dump_prog_set(FINISHED);
}
#if defined(HX_TP_PROC_GUEST_INFO)
static int printMat(struct seq_file *m, int max_size,
uint8_t *guest_str, int loc)
{
int ret = loc;
int i;
for (i = 0; i < max_size; i++) {
if ((i % 16) == 0 && i > 0)
seq_puts(m, "\n");
seq_printf(m, "0x%02X\t",
guest_str[i]);
}
return ret;
}
static int printUnit(struct seq_file *m, int max_size,
char *info_item, uint8_t *guest_str, int loc)
{
int ret = loc;
seq_printf(m, "%s:\n", info_item);
ret = printMat(m, max_size, guest_str, ret);
seq_puts(m, "\n");
return ret;
}
static int himax_proc_guest_info_read(struct seq_file *m)
{
int ret = 0;
int j = 0;
int max_size = 128;
struct hx_guest_info *info = g_guest_info_data;
if (debug_data->is_call_help) {
seq_printf(m, HELP_GUEST_INFO);
debug_data->is_call_help = false;
} else {
I("guest info progress\n");
if (g_core_fp.guest_info_get_status()) {
seq_printf(m,
"Not Ready\n");
goto END_FUNCTION;
} else {
if (info->g_guest_info_type == 1) {
for (j = 0; j < 3; j++) {
ret = printUnit(m, max_size,
g_guest_info_item[j],
info->g_guest_str[j], ret);
I("str[%d] %s\n", j,
info->g_guest_str[j]);
}
ret = printUnit(m, max_size,
g_guest_info_item[8],
info->g_guest_str[8],
ret);
I("str[8] %s\n",
info->g_guest_str[8]);
ret = printUnit(m, max_size,
g_guest_info_item[9],
info->g_guest_str[9],
ret);
I("str[9] %s\n", info->g_guest_str[9]);
} else if (info->g_guest_info_type == 0) {
for (j = 0; j < 10; j++) {
if (j == 3)
j = 8;
seq_printf(m, "%s:\n",
g_guest_info_item[j]);
if (info->g_guest_data_type[j] == 0) {
seq_printf(m, "%s",
info->g_guest_str_in_format[j]);
} else {
ret = printMat(m,
info->g_guest_data_len[j],
info->g_guest_str_in_format[j],
ret);
}
seq_puts(m, "\n");
}
}
}
}
END_FUNCTION:
return ret;
}
static ssize_t himax_proc_guest_info_write(char *buf, size_t len)
{
if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
I("%s: buf = %s\n", __func__, buf);
if (str_idx_of_str(buf, "help") >= 0) {
debug_data->is_call_help = true;
} else {
if (buf[0] == 'r') {
I("%s,Test to get", __func__);
queue_work(private_ts->guest_info_wq,
&private_ts->guest_info_work);
}
}
return len;
}
#endif
static int himax_test_bus_read(struct seq_file *m)
{
int ret = NO_ERR;
if (g_core_fp.fp_read_i2c_status())
seq_printf(m,
"Bus communication is bad.\n");
else
seq_printf(m,
"Bus communication is good.\n");
return ret;
}
static int himax_info_read(struct seq_file *m)
{
int ret = NO_ERR;
seq_printf(m,
"Himax Touch IC Information :\n");
seq_printf(m,
"%s\n", private_ts->chip_name);
switch (IC_CHECKSUM) {
case HX_TP_BIN_CHECKSUM_SW:
seq_printf(m,
"IC Checksum : SW\n");
break;
case HX_TP_BIN_CHECKSUM_HW:
seq_printf(m,
"IC Checksum : HW\n");
break;
case HX_TP_BIN_CHECKSUM_CRC:
seq_printf(m,
"IC Checksum : CRC\n");
break;
default:
seq_printf(m,
"IC Checksum error.\n");
}
if (ic_data->HX_INT_IS_EDGE)
seq_printf(m,
"Driver register Interrupt : EDGE TIRGGER\n");
else
seq_printf(m,
"Driver register Interrupt : LEVEL TRIGGER\n");
if (private_ts->protocol_type == PROTOCOL_TYPE_A)
seq_printf(m,
"Protocol : TYPE_A\n");
else
seq_printf(m,
"Protocol : TYPE_B\n");
seq_printf(m,
"RX Num : %d\n", ic_data->HX_RX_NUM);
seq_printf(m,
"TX Num : %d\n", ic_data->HX_TX_NUM);
seq_printf(m,
"BT Num : %d\n", ic_data->HX_BT_NUM);
seq_printf(m,
"X Resolution : %d\n", ic_data->HX_X_RES);
seq_printf(m,
"Y Resolution : %d\n", ic_data->HX_Y_RES);
seq_printf(m,
"Max Point : %d\n", ic_data->HX_MAX_PT);
#if defined(HX_TP_PROC_2T2R)
if (Is_2T2R) {
seq_printf(m,
"2T2R panel\n");
seq_printf(m,
"RX Num_2 : %d\n", HX_RX_NUM_2);
seq_printf(m,
"TX Num_2 : %d\n", HX_TX_NUM_2);
}
#endif
return ret;
}
static int hx_node_update(char *buf, size_t is_len)
{
int result;
char fileName[128];
int fw_type = 0;
const struct firmware *fw = NULL;
fw_update_complete = false;
fw_update_going = true;
memset(fileName, 0, 128);
/* parse the file name */
if (!is_len)
memcpy(fileName, buf, strlen(buf) * sizeof(char));
else
snprintf(fileName, is_len - 2, "%s", &buf[2]);
I("%s: upgrade from file(%s) start!\n", __func__, fileName);
/* manual upgrade will not use embedded firmware */
result = request_firmware(&fw, fileName, private_ts->dev);
if (result < 0) {
E("request FW %s failed(%d)\n", fileName, result);
return result;
}
I("%s: FW image: %02X, %02X, %02X, %02X\n", __func__,
fw->data[0], fw->data[1],
fw->data[2], fw->data[3]);
himax_int_enable(0);
#if defined(HX_ZERO_FLASH)
I("NOW Running Zero flash update!\n");
/* FW type: 0, normal; 1, MPFW */
if (strcmp(fileName, MPAP_FWNAME) == 0)
fw_type = 1;
CFG_TABLE_FLASH_ADDR = CFG_TABLE_FLASH_ADDR_T;
g_core_fp.fp_bin_desc_get((unsigned char *)fw->data, HX1K);
result = g_core_fp.fp_firmware_update_0f(fw, fw_type);
if (result) {
fw_update_complete = false;
I("Zero flash update fail!\n");
} else {
fw_update_complete = true;
I("Zero flash update complete!\n");
}
#else
I("NOW Running common flow update!\n");
fw_type = (fw->size) / 1024;
I("Now FW size is : %dk\n", fw_type);
switch (fw_type) {
case 32:
if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k(
(unsigned char *)fw->data, fw->size, false) == 0) {
E("%s: TP upgrade error, line: %d\n",
__func__, __LINE__);
fw_update_complete = false;
} else {
I("%s: TP upgrade OK, line: %d\n",
__func__, __LINE__);
fw_update_complete = true;
}
break;
case 60:
if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k(
(unsigned char *)fw->data, fw->size, false) == 0) {
E("%s: TP upgrade error, line: %d\n",
__func__, __LINE__);
fw_update_complete = false;
} else {
I("%s: TP upgrade OK, line: %d\n",
__func__, __LINE__);
fw_update_complete = true;
}
break;
case 64:
if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k(
(unsigned char *)fw->data, fw->size, false) == 0) {
E("%s: TP upgrade error, line: %d\n",
__func__, __LINE__);
fw_update_complete = false;
} else {
I("%s: TP upgrade OK, line: %d\n",
__func__, __LINE__);
fw_update_complete = true;
}
break;
case 124:
if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k(
(unsigned char *)fw->data, fw->size, false) == 0) {
E("%s: TP upgrade error, line: %d\n",
__func__, __LINE__);
fw_update_complete = false;
} else {
I("%s: TP upgrade OK, line: %d\n",
__func__, __LINE__);
fw_update_complete = true;
}
break;
case 128:
if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k(
(unsigned char *)fw->data, fw->size, false) == 0) {
E("%s: TP upgrade error, line: %d\n",
__func__, __LINE__);
fw_update_complete = false;
} else {
I("%s: TP upgrade OK, line: %d\n",
__func__, __LINE__);
fw_update_complete = true;
}
break;
case 255:
if (g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_255k(
(unsigned char *)fw->data, fw->size, false) == 0) {
E("%s: TP upgrade error, line: %d\n",
__func__, __LINE__);
fw_update_complete = false;
} else {
I("%s: TP upgrade OK, line: %d\n",
__func__, __LINE__);
fw_update_complete = true;
}
break;
default:
E("%s: Flash command fail: %d\n", __func__, __LINE__);
fw_update_complete = false;
break;
}
#endif
release_firmware(fw);
goto firmware_upgrade_done;
firmware_upgrade_done:
fw_update_going = false;
g_core_fp.fp_reload_disable(0);
g_core_fp.fp_power_on_init();
g_core_fp.fp_read_FW_ver();
g_core_fp.fp_tp_info_check();
himax_int_enable(1);
return result;
}
static int himax_update_read(struct seq_file *m)
{
int ret = NO_ERR;
if (debug_data->is_call_help) {
seq_printf(m, HELP_UPDATE);
debug_data->is_call_help = false;
} else {
if (!fw_update_going) {
if (fw_update_complete)
seq_printf(m,
"FW Update Complete\n");
else
seq_printf(m,
"FW Update Fail\n");
} else {
seq_printf(m,
"FW Update Ongoing\n");
}
}
return ret;
}
static ssize_t himax_update_write(char *buf, size_t len)
{
I("Now cmd=%s", buf);
if (str_idx_of_str(buf, "help") >= 0)
debug_data->is_call_help = true;
else
hx_node_update(buf, 0);
return len;
}
static int himax_version_read(struct seq_file *m)
{
int ret = NO_ERR;
I("%s: enter, %d\n", __func__, __LINE__);
if (debug_data->is_call_help) {
seq_printf(m, HELP_VER);
debug_data->is_call_help = false;
} else {
seq_printf(m,
"FW_VER = 0x%2.2X\n",
ic_data->vendor_fw_ver);
if (private_ts->chip_cell_type == CHIP_IS_ON_CELL)
seq_printf(m,
"CONFIG_VER = 0x%2.2X\n",
ic_data->vendor_config_ver);
else {
seq_printf(m,
"TOUCH_VER = 0x%2.2X\n",
ic_data->vendor_touch_cfg_ver);
seq_printf(m,
"DISPLAY_VER = 0x%2.2X\n",
ic_data->vendor_display_cfg_ver);
}
if (ic_data->vendor_cid_maj_ver < 0
&& ic_data->vendor_cid_min_ver < 0)
seq_printf(m,
"CID_VER = NULL\n");
else
seq_printf(m,
"CID_VER = 0x%2.2X\n",
(ic_data->vendor_cid_maj_ver << 8 |
ic_data->vendor_cid_min_ver));
if (ic_data->vendor_panel_ver < 0)
seq_printf(m,
"PANEL_VER = NULL\n");
else
seq_printf(m,
"PANEL_VER = 0x%2.2X\n",
ic_data->vendor_panel_ver);
if (private_ts->chip_cell_type == CHIP_IS_IN_CELL) {
seq_printf(m,
"Cusomer = %s\n",
ic_data->vendor_cus_info);
seq_printf(m,
"Project = %s\n",
ic_data->vendor_proj_info);
}
seq_puts(m, "\n");
seq_printf(m,
"Himax Touch Driver Version:\n");
seq_printf(m,
"%s\n", HIMAX_DRIVER_VER);
}
return ret;
}
static ssize_t himax_version_write(char *buf, size_t len)
{
if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
I("Now cmd=%s", buf);
if (str_idx_of_str(buf, "help") >= 0)
debug_data->is_call_help = true;
else
g_core_fp.fp_read_FW_ver();
return len;
}
static int himax_list_cmd_read(struct seq_file *m)
{
int ret = NO_ERR;
int i = 0, j = 0;
for (i = CMD_START_IDX; dbg_cmd_str[i] != NULL; i++) {
for (j = 0; dbg_cmd_str[i][j] != NULL ; j++) {
if (j != 0)
seq_puts(m, ", ");
seq_printf(m, dbg_cmd_str[i][j]);
}
seq_puts(m, "\n");
}
return ret;
}
static int himax_help_read(struct seq_file *m)
{
int ret = NO_ERR;
seq_printf(m, HELP_ALL_DEBUG);
return ret;
}
static ssize_t himax_help_write(char *buf, size_t len)
{
if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
I("Now cmd=%s", buf);
return len;
}
static int himax_debug_show(struct seq_file *m, void *v)
{
int ret = 0;
if (dbg_cmd_flag) {
if (dbg_func_ptr_r[dbg_cmd_flag]) {
dbg_func_ptr_r[dbg_cmd_flag](m);
goto END_FUNC_R;
}
}
if (debug_level_cmd == 't') {
if (!fw_update_going) {
if (fw_update_complete)
seq_printf(m,
"FW Update Complete ");
else
seq_printf(m,
"FW Update Fail ");
} else {
seq_printf(m,
"FW Update Ongoing ");
}
} else if (debug_level_cmd == 'h') {
if (handshaking_result == 0)
seq_printf(m,
"Handshaking Result = %d (MCU Running)\n",
handshaking_result);
else if (handshaking_result == 1)
seq_printf(m,
"Handshaking Result = %d (MCU Stop)\n",
handshaking_result);
else if (handshaking_result == 2)
seq_printf(m,
"Handshaking Result = %d (I2C Error)\n",
handshaking_result);
else
seq_printf(m,
"Handshaking Result = error\n");
} else {
himax_list_cmd_read(m);
}
END_FUNC_R:
return ret;
}
static ssize_t himax_debug_store(struct file *file, const char __user *ubuf,
size_t len, loff_t *data)
{
char buf[80] = "\0";
char *str_ptr = NULL;
int str_len = 0;
int input_cmd_len = 0;
int i = 0, j = 0;
if (len >= 80) {
I("%s: no command exceeds 80 chars.\n", __func__);
return -EFAULT;
}
if (copy_from_user(buf, ubuf, len))
return -EFAULT;
str_len = len;
buf[str_len - 1] = '\0';/*remove \n*/
input_cmd_len = (int)strcspn(buf, ",");
if (input_cmd_len == -1)
input_cmd_len = str_len;
i = CMD_START_IDX; /* start from 1*/
while (dbg_cmd_str[i] != NULL) {
while (dbg_cmd_str[i][j] != NULL) {
str_ptr = strnstr(buf, dbg_cmd_str[i][j], len);
str_len = strlen(dbg_cmd_str[i][j]);
if (str_len != input_cmd_len) {
str_ptr = NULL;
j++;
continue;
}
if (str_ptr) {
dbg_cmd_flag = i;
debug_level_cmd = 0;
I("Cmd is correct :%s, dbg_cmd = %d\n",
str_ptr, dbg_cmd_flag);
goto CHECK;
}
j++;
}
j = 0;
i++;
}
CHECK:
if (!str_ptr) {
I("Cmd is in old fromat or incorrect\n");
dbg_cmd_flag = 0;
goto CONTI;
}
if (buf[str_len] == ',') {
dbg_cmd_par = buf + str_len + 1;
if (dbg_func_ptr_w[dbg_cmd_flag])
/* 2 => '/n' + ','*/
dbg_func_ptr_w[dbg_cmd_flag](dbg_cmd_par,
len - str_len - 2);
I("string of paremeter is %s; dbg_cmd_par = %s, size = %d\n",
buf + str_len + 1,
dbg_cmd_par, (int)(len - str_len - 2));
} else {
I("Write cmd=%s, without parameter\n",
dbg_cmd_str[dbg_cmd_flag][0]);
}
CONTI:
if (dbg_cmd_flag)
return len;
if (buf[0] == 't') {
/* Update firmware */
debug_level_cmd = buf[0];
hx_node_update(buf, len);
} else if (buf[0] == 'c' && buf[1] == 't' && buf[2] == 'i') {
/* Compare Touch Information */
g_core_fp.fp_tp_info_check();
goto ENDFUCTION;
} else if (buf[0] == 'e' && buf[1] == 'c') {
/* Erase firmware */
g_core_fp.fp_sense_off(true);
g_core_fp.fp_chip_erase();
} else {
/* others, do nothing */
debug_level_cmd = 0;
}
ENDFUCTION:
return len;
}
__CREATE_RW_NODE_HX(debug);
static int himax_vendor_show(struct seq_file *m, void *v)
{
int ret = 0;
seq_printf(m,
"IC = %s\n", private_ts->chip_name);
seq_printf(m,
"FW_VER = 0x%2.2X\n", ic_data->vendor_fw_ver);
if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) {
seq_printf(m,
"CONFIG_VER = 0x%2.2X\n",
ic_data->vendor_config_ver);
} else {
seq_printf(m,
"TOUCH_VER = 0x%2.2X\n",
ic_data->vendor_touch_cfg_ver);
seq_printf(m,
"DISPLAY_VER = 0x%2.2X\n",
ic_data->vendor_display_cfg_ver);
}
if (ic_data->vendor_cid_maj_ver < 0
&& ic_data->vendor_cid_min_ver < 0) {
seq_printf(m,
"CID_VER = NULL\n");
} else {
seq_printf(m,
"CID_VER = 0x%2.2X\n",
(ic_data->vendor_cid_maj_ver << 8 |
ic_data->vendor_cid_min_ver));
}
if (ic_data->vendor_panel_ver < 0) {
seq_printf(m,
"PANEL_VER = NULL\n");
} else {
seq_printf(m,
"PANEL_VER = 0x%2.2X\n",
ic_data->vendor_panel_ver);
}
if (private_ts->chip_cell_type == CHIP_IS_IN_CELL) {
seq_printf(m,
"Cusomer = %s\n",
ic_data->vendor_cus_info);
seq_printf(m,
"Project = %s\n",
ic_data->vendor_proj_info);
}
seq_puts(m, "\n");
seq_printf(m,
"Himax Touch Driver Version:\n");
seq_printf(m, "%s\n",
HIMAX_DRIVER_VER);
return ret;
}
__CREATE_OREAD_NODE_HX(vendor);
static void himax_himax_data_init(void)
{
debug_data->fp_ts_dbg_func = himax_ts_dbg_func;
debug_data->fp_set_diag_cmd = himax_set_diag_cmd;
debug_data->flash_dump_going = false;
debug_data->is_checking_irq = false;
debug_data->is_call_help = false;
}
static void himax_ts_dump_work_func(struct work_struct *work)
{
himax_ts_dump_func();
}
#if defined(HX_TP_PROC_GUEST_INFO)
static void himax_ts_guest_info_work_func(struct work_struct *work)
{
g_core_fp.read_guest_info();
}
#endif
static void himax_ts_diag_work_func(struct work_struct *work)
{
himax_ts_diag_func(process_type);
if (process_type != 0) {
queue_delayed_work(private_ts->himax_diag_wq,
&private_ts->himax_diag_delay_work, 1 / 10 * HZ);
} else {
dsram_flag = false;
}
}
void dbg_func_ptr_init(void)
{
/*debug function ptr init*/
dbg_func_ptr_r[CMD_CRC_TEST] = himax_crc_test_read;
dbg_func_ptr_r[CND_FW_DBG] = himax_proc_fw_debug_read;
dbg_func_ptr_r[CMD_ATTN] = himax_attn_read;
dbg_func_ptr_w[CMD_LAYOUT] = himax_layout_write;
dbg_func_ptr_r[CMD_LAYOUT] = himax_layout_read;
#if defined(HX_EXCP_RECOVERY)
dbg_func_ptr_w[CMD_EXCEPT] = himax_excp_cnt_write;
dbg_func_ptr_r[CMD_EXCEPT] = himax_excp_cnt_read;
#endif
dbg_func_ptr_w[CMD_SENSE_ON_OFF] = himax_sense_on_off_write;
dbg_func_ptr_r[CMD_SENSE_ON_OFF] = himax_sense_on_off_read;
dbg_func_ptr_w[CMD_DBG_LEVEL] = himax_debug_level_write;
dbg_func_ptr_r[CMD_DBG_LEVEL] = himax_debug_level_read;
#if defined(HX_TP_PROC_GUEST_INFO)
dbg_func_ptr_w[CMD_GUEST_INFO] = himax_proc_guest_info_write;
dbg_func_ptr_r[CMD_GUEST_INFO] = himax_proc_guest_info_read;
#endif
dbg_func_ptr_w[CMD_INTERRUPT] = himax_int_en_write;
dbg_func_ptr_r[CMD_INTERRUPT] = himax_int_en_read;
dbg_func_ptr_w[CND_IRQ_INFO] = himax_irq_info_write;
dbg_func_ptr_r[CND_IRQ_INFO] = himax_irq_info_read;
dbg_func_ptr_w[CMD_REGISTER] = himax_proc_register_write;
dbg_func_ptr_r[CMD_REGISTER] = himax_proc_register_read;
dbg_func_ptr_w[CMD_RESET] = himax_reset_write;
dbg_func_ptr_r[CMD_RESET] = himax_reset_read;
dbg_func_ptr_w[CMD_DIAG_ARRANGE] = himax_diag_arrange_write;
dbg_func_ptr_r[CMD_DIAG_ARRANGE] = himax_diag_arrange_read;
dbg_func_ptr_w[CMD_DIAG_CMD] = himax_diag_cmd_write;
dbg_func_ptr_w[CMD_IRQ_DBG_CMD] = himax_irq_dbg_cmd_write;
dbg_func_ptr_r[CMD_TEST_BUS] = himax_test_bus_read;
dbg_func_ptr_w[CMD_FW_UPDATE] = himax_update_write;
dbg_func_ptr_r[CMD_FW_UPDATE] = himax_update_read;
dbg_func_ptr_w[CMD_VERSION] = himax_version_write;
dbg_func_ptr_r[CMD_VERSION] = himax_version_read;
dbg_func_ptr_r[CND_INFO] = himax_info_read;
dbg_func_ptr_r[CMD_LIST] = himax_list_cmd_read;
dbg_func_ptr_w[CMD_HELP] = himax_help_write;
dbg_func_ptr_r[CMD_HELP] = himax_help_read;
}
int himax_touch_proc_init(void)
{
himax_proc_diag_dir = proc_mkdir(HIMAX_PROC_DIAG_FOLDER,
himax_touch_proc_dir);
if (himax_proc_diag_dir == NULL) {
E(" %s: himax_proc_diag_dir file create failed!\n", __func__);
return -ENOMEM;
}
himax_proc_stack_file = proc_create(HIMAX_PROC_STACK_FILE, 0444,
himax_proc_diag_dir, &himax_stack_ops);
if (himax_proc_stack_file == NULL) {
E(" %s: proc stack file create failed!\n", __func__);
goto fail_2_1;
}
himax_proc_delta_file = proc_create(HIMAX_PROC_DELTA_FILE, 0444,
himax_proc_diag_dir, &himax_delta_ops);
if (himax_proc_delta_file == NULL) {
E(" %s: proc delta file create failed!\n", __func__);
goto fail_2_2;
}
himax_proc_dc_file = proc_create(HIMAX_PROC_DC_FILE, 0444,
himax_proc_diag_dir, &himax_dc_ops);
if (himax_proc_dc_file == NULL) {
E(" %s: proc dc file create failed!\n", __func__);
goto fail_2_3;
}
himax_proc_baseline_file = proc_create(HIMAX_PROC_BASELINE_FILE, 0444,
himax_proc_diag_dir, &himax_baseline_ops);
if (himax_proc_baseline_file == NULL) {
E(" %s: proc baseline file create failed!\n", __func__);
goto fail_2_4;
}
himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE,
0644, himax_touch_proc_dir,
&himax_debug_ops);
if (himax_proc_debug_file == NULL) {
E(" %s: proc debug file create failed!\n", __func__);
goto fail_3;
}
dbg_func_ptr_init();
himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE,
0644, himax_touch_proc_dir,
&himax_flash_dump_ops);
if (himax_proc_flash_dump_file == NULL) {
E(" %s: proc flash dump file create failed!\n", __func__);
goto fail_4;
}
return 0;
fail_4: remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir);
fail_3: remove_proc_entry(HIMAX_PROC_BASELINE_FILE, himax_proc_diag_dir);
fail_2_4: remove_proc_entry(HIMAX_PROC_DC_FILE, himax_proc_diag_dir);
fail_2_3: remove_proc_entry(HIMAX_PROC_DELTA_FILE, himax_proc_diag_dir);
fail_2_2: remove_proc_entry(HIMAX_PROC_STACK_FILE, himax_proc_diag_dir);
fail_2_1:
return -ENOMEM;
}
void himax_touch_proc_deinit(void)
{
remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir);
remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir);
remove_proc_entry(HIMAX_PROC_BASELINE_FILE, himax_proc_diag_dir);
remove_proc_entry(HIMAX_PROC_DC_FILE, himax_proc_diag_dir);
remove_proc_entry(HIMAX_PROC_DELTA_FILE, himax_proc_diag_dir);
remove_proc_entry(HIMAX_PROC_STACK_FILE, himax_proc_diag_dir);
}
int himax_debug_init(void)
{
struct himax_ts_data *ts = private_ts;
I("%s:Enter\n", __func__);
if (ts == NULL) {
E("%s: ts struct is NULL\n", __func__);
return -EPROBE_DEFER;
}
proc_reg_buf = kzalloc(128 * sizeof(uint8_t), GFP_KERNEL);
if (proc_reg_buf == NULL) {
E("%s: reg_read_data allocate failed\n", __func__);
goto err_alloc_reg_read_data_fail;
}
debug_data = kzalloc(sizeof(struct himax_debug), GFP_KERNEL);
if (debug_data == NULL) { /*Allocate debug data space*/
E("%s: debug_data allocate failed\n", __func__);
goto err_alloc_debug_data_fail;
}
himax_himax_data_init();
g_dump_buffer = kcalloc(ic_data->flash_size,
sizeof(uint8_t),
GFP_KERNEL);
if (g_dump_buffer == NULL) {
E("%s: dump buffer allocate fail failed\n", __func__);
goto err_dump_buf_alloc_failed;
}
ts->dump_wq = create_singlethread_workqueue("himax_dump_wq");
if (!ts->dump_wq) {
E("%s: create flash workqueue failed\n", __func__);
goto err_create_flash_dump_wq_failed;
}
INIT_WORK(&ts->dump_work, himax_ts_dump_work_func);
g_flash_progress = START;
#if defined(HX_TP_PROC_GUEST_INFO)
if (g_guest_info_data == NULL) {
g_guest_info_data = kzalloc(sizeof(struct hx_guest_info),
GFP_KERNEL);
if (g_guest_info_data == NULL) {
E("%s: flash buffer allocate fail failed\n", __func__);
goto err_guest_info_alloc_failed;
}
g_guest_info_data->g_guest_info_ongoing = 0;
g_guest_info_data->g_guest_info_type = 0;
}
ts->guest_info_wq =
create_singlethread_workqueue("himax_guest_info_wq");
if (!ts->guest_info_wq) {
E("%s: create guest info workqueue failed\n", __func__);
goto err_create_guest_info_wq_failed;
}
INIT_WORK(&ts->guest_info_work, himax_ts_guest_info_work_func);
#endif
setSelfBuffer(ic_data->HX_RX_NUM, ic_data->HX_TX_NUM);
if (getSelfBuffer() == NULL) {
E("%s: self buffer allocate failed\n", __func__);
goto err_self_buf_alloc_failed;
}
setSelfNewBuffer(ic_data->HX_RX_NUM, ic_data->HX_TX_NUM);
if (getSelfNewBuffer() == NULL) {
E("%s: self new buffer allocate failed\n", __func__);
goto err_self_new_alloc_failed;
}
setSelfOldBuffer(ic_data->HX_RX_NUM, ic_data->HX_TX_NUM);
if (getSelfOldBuffer() == NULL) {
E("%s: self old buffer allocate failed\n", __func__);
goto err_self_old_alloc_failed;
}
setMutualBuffer(ic_data->HX_RX_NUM, ic_data->HX_TX_NUM);
if (getMutualBuffer() == NULL) {
E("%s: mutual buffer allocate failed\n", __func__);
goto err_mut_buf_alloc_failed;
}
setMutualNewBuffer(ic_data->HX_RX_NUM, ic_data->HX_TX_NUM);
if (getMutualNewBuffer() == NULL) {
E("%s: mutual new buffer allocate failed\n", __func__);
goto err_mut_new_alloc_failed;
}
setMutualOldBuffer(ic_data->HX_RX_NUM, ic_data->HX_TX_NUM);
if (getMutualOldBuffer() == NULL) {
E("%s: mutual old buffer allocate failed\n", __func__);
goto err_mut_old_alloc_failed;
}
#if defined(HX_TP_PROC_2T2R)
if (Is_2T2R) {
setMutualBuffer_2(ic_data->HX_RX_NUM_2, ic_data->HX_TX_NUM_2);
if (getMutualBuffer_2() == NULL) {
E("%s: mutual buffer 2 allocate failed\n", __func__);
goto err_mut_buf2_alloc_failed;
}
}
#endif
ts->himax_diag_wq = create_singlethread_workqueue("himax_diag");
if (!ts->himax_diag_wq) {
E("%s: create diag workqueue failed\n", __func__);
goto err_create_diag_wq_failed;
}
INIT_DELAYED_WORK(&ts->himax_diag_delay_work, himax_ts_diag_work_func);
if (himax_touch_proc_init())
goto err_proc_init_failed;
snprintf(g_file_path, (int)(strlen(HX_RSLT_OUT_PATH)
+ strlen(HX_RSLT_OUT_FILE)+1),
"%s%s", HX_RSLT_OUT_PATH, HX_RSLT_OUT_FILE);
return 0;
err_proc_init_failed:
cancel_delayed_work_sync(&ts->himax_diag_delay_work);
destroy_workqueue(ts->himax_diag_wq);
err_create_diag_wq_failed:
#if defined(HX_TP_PROC_2T2R)
kfree(diag_mutual_2);
diag_mutual_2 = NULL;
err_mut_buf2_alloc_failed:
#endif
kfree(diag_mutual_old);
diag_mutual_old = NULL;
err_mut_old_alloc_failed:
kfree(diag_mutual_new);
diag_mutual_new = NULL;
err_mut_new_alloc_failed:
kfree(diag_mutual);
diag_mutual = NULL;
err_mut_buf_alloc_failed:
kfree(diag_self_old);
diag_self_old = NULL;
err_self_old_alloc_failed:
kfree(diag_self_new);
diag_self_new = NULL;
err_self_new_alloc_failed:
kfree(diag_self);
diag_self = NULL;
err_self_buf_alloc_failed:
#if defined(HX_TP_PROC_GUEST_INFO)
cancel_work_sync(&ts->guest_info_work);
destroy_workqueue(ts->guest_info_wq);
err_create_guest_info_wq_failed:
if (g_guest_info_data != NULL) {
kfree(g_guest_info_data);
g_guest_info_data = NULL;
}
err_guest_info_alloc_failed:
#endif
cancel_work_sync(&ts->dump_work);
destroy_workqueue(ts->dump_wq);
err_create_flash_dump_wq_failed:
kfree(g_dump_buffer);
g_dump_buffer = NULL;
err_dump_buf_alloc_failed:
kfree(debug_data);
debug_data = NULL;
err_alloc_debug_data_fail:
kfree(proc_reg_buf);
proc_reg_buf = NULL;
err_alloc_reg_read_data_fail:
return -ENOMEM;
}
EXPORT_SYMBOL(himax_debug_init);
int himax_debug_remove(void)
{
struct himax_ts_data *ts = private_ts;
himax_touch_proc_deinit();
cancel_delayed_work_sync(&ts->himax_diag_delay_work);
destroy_workqueue(ts->himax_diag_wq);
kfree(diag_mutual_2);
diag_mutual_2 = NULL;
kfree(diag_mutual_old);
diag_mutual_old = NULL;
kfree(diag_mutual_new);
diag_mutual_new = NULL;
kfree(diag_mutual);
diag_mutual = NULL;
kfree(diag_self_old);
diag_self_old = NULL;
kfree(diag_self_new);
diag_self_new = NULL;
kfree(diag_self);
diag_self = NULL;
#if defined(HX_TP_PROC_GUEST_INFO)
cancel_work_sync(&ts->guest_info_work);
destroy_workqueue(ts->guest_info_wq);
if (g_guest_info_data != NULL) {
kfree(g_guest_info_data);
g_guest_info_data = NULL;
}
#endif
cancel_work_sync(&ts->dump_work);
destroy_workqueue(ts->dump_wq);
kfree(g_dump_buffer);
g_dump_buffer = NULL;
kfree(debug_data);
debug_data = NULL;
kfree(proc_reg_buf);
proc_reg_buf = NULL;
return 0;
}
EXPORT_SYMBOL(himax_debug_remove);