/* SPDX-License-Identifier: GPL-2.0 */ /* Himax Android Driver Sample Code for debug nodes * * Copyright (C) 2022 Himax Corporation. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "himax_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 static void hx_dbg_rst_rb(void); uint8_t g_diag_arr_num; int g_re_ass_rb_idx = -9487; 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; 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; uint8_t *diag_mutual_byte; int32_t *diag_mutual_new; int32_t *diag_mutual_old; uint8_t state_info[2]; uint8_t diag_coor[128]; int32_t *diag_self; uint8_t *diag_self_byte; 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; #if defined(HX_UID_PASSWORD) bool g_uid_upgrade_flag; #endif /* Moved from debug.h End */ struct proc_dir_entry *himax_proc_pen_pos_file; struct time_var timeStart, timeEnd, timeDelta; int g_switch_mode; /* * Segment : Himax PROC Debug Function */ /****** useful functions ******/ static void _str_to_arr_in_char(char **arr, int arr_size, const 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' || str[i] == '\n') { 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; } static int chk_slave_reg(char *str, int str_len) { char *buf_write_slave_cmd = NULL; char *buf_read_slave_cmd = NULL; int write_cmd_len = -1; int read_cmd_len = -1; int chk; int cal; I("Entering: %s\n", __func__); I("cmd=%s\n", str); I("len=%d\n", str_len); write_cmd_len = (int)strcspn(str, ","); if (write_cmd_len == -1 || write_cmd_len >= str_len) { hx_s_ts->slave_write_reg = 0; I("%s: no other cmd\n", __func__); goto END; } buf_write_slave_cmd = kcalloc(write_cmd_len + 1, sizeof(char), GFP_KERNEL); memset(buf_write_slave_cmd, 0x00, write_cmd_len + 1); memcpy(&buf_write_slave_cmd[0], &str[0], write_cmd_len); str_len = str_len - write_cmd_len - 1; memcpy(&str[0], &str[write_cmd_len + 1], str_len); str[str_len] = '\0'; chk = kstrtoint(buf_write_slave_cmd, 16, &cal); if (chk) { E("%s, kstrtoint return fail1!\n", __func__); str_len = 0; goto END; } hx_s_ts->slave_write_reg = cal % 0x100; I("%s: str=%s, str_len=%d\n", __func__, str, str_len); I("%s: buf_write_slave_cmd=%s, write_cmd_len=%d, slave_write_reg=%d\n", __func__, buf_write_slave_cmd, write_cmd_len, hx_s_ts->slave_write_reg); I("cmd=%s, len=%d\n", str, str_len); read_cmd_len = (int)strcspn(str, ","); if (read_cmd_len == -1 || read_cmd_len >= str_len) { hx_s_ts->slave_read_reg = 0; I("%s: no other cmd\n", __func__); goto END; } buf_read_slave_cmd = kcalloc(read_cmd_len + 1, sizeof(char), GFP_KERNEL); memset(buf_read_slave_cmd, 0x00, read_cmd_len + 1); memcpy(&buf_read_slave_cmd[0], &str[0], read_cmd_len); str_len = str_len - read_cmd_len - 1; memcpy(&str[0], &str[read_cmd_len + 1], str_len); str[str_len] = '\0'; cal = 0; chk = kstrtoint(buf_read_slave_cmd, 16, &cal); if (chk) { E("%s, kstrtoint return fail2!\n", __func__); str_len = 0; goto END; } hx_s_ts->slave_read_reg = cal % 0x100; I("%s: str=%s, str_len=%d\n", __func__, str, str_len); I("%s: buf_read_slave_cmd=%s, read_cmd_len=%d, slave_read_reg=%d\n", __func__, buf_read_slave_cmd, read_cmd_len, hx_s_ts->slave_read_reg); hx_s_ts->select_slave_reg = true; I("%s : Now try to R/W slave address!\n", __func__); END: if (buf_write_slave_cmd != NULL) { kfree(buf_write_slave_cmd); buf_write_slave_cmd = NULL; } if (buf_read_slave_cmd != NULL) { kfree(buf_read_slave_cmd); buf_read_slave_cmd = NULL; } return str_len; } static int himax_crc_test_read(struct seq_file *m) { int ret = 0; #if !defined(HX_ZERO_FLASH) uint8_t result = 0; uint32_t size = 0; I("%s: now flash = %d\n", __func__, hx_s_ic_data->flash_size); size = hx_s_ic_data->flash_size; hx_s_core_fp._sense_off(true); msleep(20); result = hx_s_core_fp._calculateChecksum(false, size); hx_s_core_fp._sense_on(0x01); if (result) seq_printf(m, "CRC test is Pass!\n"); else seq_printf(m, "CRC test is Fail!\n"); #else seq_printf(m, "No flash, skip!\n"); #endif 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(hx_s_ic_data->dbg_reg_ary)/sizeof(uint32_t)); for (i = 0; i < len; i++) { hx_parse_assign_cmd(hx_s_ic_data->dbg_reg_ary[i], addr, 4); hx_s_core_fp._register_read(hx_s_ic_data->dbg_reg_ary[i], data, DATA_LEN_4); seq_printf(m, "reg[0-3] : 0x%08X = 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", hx_s_ic_data->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", hx_s_ic_data->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 = hx_s_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 = hx_s_ts; size_t ret = 0; if (hx_s_debug_data->is_call_help) { seq_printf(m, HELP_LAYOUT); hx_s_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 = hx_s_ts; char buf_tmp[5] = {0}; int i = 0, j = 0, k = 0; unsigned long value; int layout[4] = {0}; int chk; if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (strnstr(buf, "help", len) != NULL) { hx_s_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) { chk = kstrtoul(buf_tmp, 10, &value); if (chk < 0) { E("%s: string parse fail!\n", __func__); len = -EFAULT; goto END; } 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 (hx_s_debug_data->is_call_help) { seq_printf(m, HELP_EXCPT); hx_s_debug_data->is_call_help = false; } else { seq_printf(m, "EB_cnt = %d, EC_cnt = %d, EE_cnt = %d\n", g_flag_eb_event, g_flag_ec_event, g_flag_ee_event); } 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 (strnstr(buf, "help", len) != NULL) { hx_s_debug_data->is_call_help = true; } else { if (buf[i] == '0') { I("Clear EXCEPTION Flag\n"); g_flag_eb_event = 0; g_flag_ec_event = 0; g_flag_ee_event = 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 (hx_s_debug_data->is_call_help) { seq_printf(m, HELP_EXCPT); hx_s_debug_data->is_call_help = false; } else { seq_printf(m, "EB_cnt = %d, EC_cnt = %d, ED_cnt = %d\n", g_flag_eb_event, g_flag_ec_event, g_flag_ed_event); } 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 (strnstr(buf, "help", len) != NULL) { hx_s_debug_data->is_call_help = true; } else { I("Clear EXCEPTION Flag\n"); if (buf[0] == '0') { g_flag_eb_event = 0; g_flag_ec_event = 0; g_flag_ed_event = 0; } } return len; } #endif #endif static ssize_t himax_sense_on_off_write(char *buf, size_t len) { if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (buf[0] == '0') { hx_s_core_fp._sense_off(true); I("Sense off\n"); } else if (buf[0] == '1') { if (buf[1] == 's') { hx_s_core_fp._sense_on(0x00); I("Sense on re-map on, run sram\n"); } else { hx_s_core_fp._sense_on(0x01); I("Sense on re-map off, run flash\n"); } } else { I("Do nothing\n"); } return len; } static int test_irq_pin(void) { struct himax_ts_data *ts = hx_s_ts; int result = NO_ERR; int irq_sts = -1; uint8_t tmp_data[DATA_LEN_4] = {0}; uint8_t tmp_read[DATA_LEN_4] = {0}; hx_s_core_fp._sense_off(true); I("check IRQ LOW\n"); usleep_range(20000, 20001); hx_parse_assign_cmd(0x00000002, tmp_data, DATA_LEN_4); hx_s_core_fp._register_write(0x90028060, tmp_data, DATA_LEN_4); usleep_range(20000, 20001); hx_s_core_fp._register_read(0x90028060, tmp_read, DATA_LEN_4); I("R%08XH = 0x%02X%02X%02X%02X\n", 0x90028060, tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]); usleep_range(20000, 20001); hx_parse_assign_cmd(0x00000001, tmp_data, DATA_LEN_4); hx_s_core_fp._register_write(0x90028064, tmp_data, DATA_LEN_4); usleep_range(20000, 20001); hx_s_core_fp._register_read(0x90028064, tmp_read, DATA_LEN_4); I("R%08XH = 0x%02X%02X%02X%02X\n", 0x90028064, tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]); usleep_range(20000, 20001); hx_parse_assign_cmd(0x00000000, tmp_data, DATA_LEN_4); hx_s_core_fp._register_write(0x90028068, tmp_data, DATA_LEN_4); usleep_range(20000, 20001); hx_s_core_fp._register_read(0x90028068, tmp_read, DATA_LEN_4); I("R%08XH = 0x%02X%02X%02X%02X\n", 0x90028068, 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); hx_parse_assign_cmd(0x00000002, tmp_data, DATA_LEN_4); hx_s_core_fp._register_write(0x90028060, tmp_data, DATA_LEN_4); usleep_range(20000, 20001); hx_s_core_fp._register_read(0x90028060, tmp_read, DATA_LEN_4); I("R%08XH = 0x%02X%02X%02X%02X\n", 0x90028060, tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]); usleep_range(20000, 20001); hx_parse_assign_cmd(0x00000001, tmp_data, DATA_LEN_4); hx_s_core_fp._register_write(0x90028064, tmp_data, DATA_LEN_4); usleep_range(20000, 20001); hx_s_core_fp._register_read(0x90028064, tmp_read, DATA_LEN_4); I("R%08XH = 0x%02X%02X%02X%02X\n", 0x90028064, tmp_read[3], tmp_read[2], tmp_read[1], tmp_read[0]); usleep_range(20000, 20001); hx_parse_assign_cmd(0x00000001, tmp_data, DATA_LEN_4); hx_s_core_fp._register_write(0x90028068, tmp_data, DATA_LEN_4); usleep_range(20000, 20001); hx_s_core_fp._register_read(0x90028068, tmp_read, DATA_LEN_4); I("R%08XH = 0x%02X%02X%02X%02X\n", 0x90028068, 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; } hx_s_debug_data->is_checking_irq = false; hx_s_core_fp._sense_on(0x00); return result; } static int himax_int_en_read(struct seq_file *m) { struct himax_ts_data *ts = hx_s_ts; int ret = 0; if (hx_s_debug_data->is_checking_irq) { if (test_irq_pin() == 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 = hx_s_ts; int ret; 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 (strnstr(buf, "test", len) != NULL) { hx_s_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 = hx_s_ts; int ret = 0; if (hx_s_core_fp._read_ic_trigger_type() == 1) seq_printf(m, "IC Interrupt type is edge trigger.\n"); else if (hx_s_core_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 (hx_s_ic_data->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 = hx_s_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 = hx_s_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; ts = hx_s_ts; if (len >= 12) { I("%s: no command exceeds 12 chars.\n", __func__); return -EFAULT; } if (strnstr(buf, "tsdbg", len) != NULL) { 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; uint32_t addr32 = 0x00; uint8_t test_data[DATA_LEN_4] = {0}; if (hx_s_debug_data->is_call_help) { seq_printf(m, HELP_REGISTER); hx_s_debug_data->is_call_help = false; } else { if (!hx_s_ts->acc_slave_reg && hx_s_ts->select_slave_reg) { I("First read Slave, test it !\n"); ret = himax_bus_read(0x13, test_data, 1); if (ret < 0) { E("%s: bus access fail!\n", __func__); seq_puts(m, "Reading Slave fail, maybe no support!\n"); ret = BUS_FAIL; goto bus_fail_end; } if (test_data[0] == 0x00) { seq_puts(m, "Reading HW Slave fail, maybe no support!\n"); ret = BUS_FAIL; goto bus_fail_end; } hx_s_ts->acc_slave_reg = true; } if (hx_s_ts->select_slave_reg) seq_printf(m, "[Slave W:0x%02X, R:0x%02X]\n", hx_s_ts->slave_write_reg, hx_s_ts->slave_read_reg); 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 { addr32 = proc_reg_addr[3] << 24 | proc_reg_addr[2] << 16 | proc_reg_addr[1] << 8 | proc_reg_addr[0]; hx_s_core_fp._register_read(addr32, proc_reg_buf, 128); } 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"); } } bus_fail_end: seq_puts(m, "\n"); if (hx_s_ts->select_slave_reg) hx_s_ts->select_slave_reg = false; return ret; } static ssize_t himax_proc_register_write(char *buf, size_t len) { char *buff_tmp; int length = 0; int byte_length = 0; unsigned long result = 0; int i = 0; char *data_str = NULL; uint8_t *w_data; int x_pos[32] = {0}; int count = 0; uint32_t addr32; int ret = 0; int len_reg; int idx = 0; if (len >= 4096) { I("%s: no command exceeds 4096 chars.\n", __func__); return -EFAULT; } if (strnstr(buf, "help", len) != NULL) { hx_s_debug_data->is_call_help = true; goto END; } buff_tmp = kzalloc(sizeof(char) * 4096, GFP_KERNEL); w_data = kzalloc(sizeof(uint8_t) * 4096, GFP_KERNEL); len = chk_slave_reg(buf, len); if (len == 0) { E("%s: Parse cmd fail:%s", __func__, buf); goto PARSE_FAIL_END; } memset(proc_reg_addr, 0x0, sizeof(proc_reg_addr)); if ((buf[0] == 'r' || buf[0] == 'w') && buf[1] == ':' && buf[2] == 'x') { length = len; 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); if (x_pos[1] > 0) length = len - x_pos[1] - 1;//strlen(data_str + 1); else length = strlen(data_str + 1); I("para length = %d\n", length); switch (buf[0]) { case 'r': if (buf[3] == 'F' && buf[4] == 'E' && length == 4) { len_reg = 2; // Now len of reg is 1 byte(char size = 2) length = length - 2; proc_reg_addr_type = 1; memcpy(buff_tmp, data_str + 3, length); } else { len_reg = 8; // Now len of reg is 4 byte(char size = 8) 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)); } break; case 'w': if (buf[3] == 'F' && buf[4] == 'E') { len_reg = 2; proc_reg_addr_type = 1; memcpy(buff_tmp, buf + 5, len_reg); } else { len_reg = 8; proc_reg_addr_type = 0; memcpy(buff_tmp, buf + 3, len_reg); } if (count < 3) { byte_length = length; I("%s: 1byte_length=%d\n", __func__, byte_length); if (!kstrtoul(buff_tmp, 16, &result)) { /* command */ for (i = 0; i < len_reg / 2; i++) { proc_reg_addr[i] = (uint8_t)(result >> (i * 8)); // I("%s: proc_reg_addr[%d]=0x%02X\n", // __func__, // i, // proc_reg_addr[i]); } } for (i = 0; i < byte_length / 2; i++) { idx = (byte_length - (i+1) * 2) / 2; memcpy(&buff_tmp[0], data_str + 1 + i * 2, 2); buff_tmp[2] = '\0'; if (!kstrtoul(buff_tmp, 16, &result)) w_data[idx] = (uint8_t)(result); // I("%s: w_data[%d]=0x%02X\n", // __func__, // idx, w_data[idx]); } } else { for (i = 0; i < count; i++) { /* parsing addr after 'x' */ memset(buff_tmp, 0x0, 4096); if (proc_reg_addr_type != 0 && i != 0) byte_length = 2; else byte_length = length; /* original */ I("%s: 2byte_length=%d\n", __func__, byte_length); 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 (proc_reg_addr_type == 1) { ret = himax_bus_write(proc_reg_addr[0], NUM_NULL, w_data, byte_length); if (ret < 0) { E("%s: bus access fail!\n", __func__); return BUS_FAIL; } } else { addr32 = proc_reg_addr[3] << 24 | proc_reg_addr[2] << 16 | proc_reg_addr[1] << 8 | proc_reg_addr[0]; hx_s_core_fp._register_write(addr32, w_data, byte_length / 2); } break; }; } PARSE_FAIL_END: kfree(buff_tmp); kfree(w_data); END: return len; } uint8_t *getMutualBufferByte(void) { return diag_mutual_byte; } int32_t *getMutualBuffer(void) { return diag_mutual; } int32_t *getMutualNewBuffer(void) { return diag_mutual_new; } int32_t *getMutualOldBuffer(void) { return diag_mutual_old; } uint8_t *getSelfBufferByte(void) { return diag_self_byte; } int32_t *getSelfBuffer(void) { return diag_self; } int32_t *getSelfNewBuffer(void) { return diag_self_new; } int32_t *getSelfOldBuffer(void) { return diag_self_old; } void setMutualBufferByte(uint8_t x_num, uint8_t y_num) { diag_mutual_byte = kzalloc(x_num * y_num * 2* sizeof(uint8_t), GFP_KERNEL); } 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 setSelfBufferByte(uint8_t x_num, uint8_t y_num) { diag_self_byte = kzalloc((x_num + y_num) * 2* sizeof(uint8_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 *hx_s_ic_data, struct himax_report_data *hx_s_touch_data) { struct himax_ts_data *ts = hx_s_ts; int32_t *mutual_data; int32_t *self_data; uint8_t *mutual_data_byte; uint8_t *self_data_byte; int mul_num; int self_num; /* int RawDataLen = 0; */ hx_s_touch_data->diag_cmd = ts->diag_cmd; if (hx_s_touch_data->diag_cmd >= 1 && hx_s_touch_data->diag_cmd <= 7) { /* Check event stack CRC */ if (!hx_s_core_fp._diag_check_sum(hx_s_touch_data)) goto bypass_checksum_failed_packet; #if defined(HX_TP_PROC_2T2R) if (Is_2T2R && (hx_s_touch_data->diag_cmd >= 4 && hx_s_touch_data->diag_cmd <= 6)) { mutual_data = getMutualBuffer_2(); self_data = getSelfBuffer(); mutual_data_byte = getMutualBufferByte(); self_data_byte = getSelfBufferByte(); /* initiallize the block number of mutual and self */ mul_num = hx_s_ic_data->rx_num_2 * hx_s_ic_data->tx_num_2; self_num = hx_s_ic_data->rx_num_2 + hx_s_ic_data->tx_num_2; } else #endif { mutual_data = getMutualBuffer(); self_data = getSelfBuffer(); mutual_data_byte = getMutualBufferByte(); self_data_byte = getSelfBufferByte(); /* initiallize the block number of mutual and self */ mul_num = hx_s_ic_data->rx_num * hx_s_ic_data->tx_num; self_num = hx_s_ic_data->rx_num + hx_s_ic_data->tx_num; } hx_s_core_fp._diag_parse_raw_data(hx_s_touch_data, mul_num, self_num, hx_s_touch_data->diag_cmd, mutual_data, self_data, mutual_data_byte, self_data_byte); } else if (hx_s_touch_data->diag_cmd == 8) { memset(diag_coor, 0x00, sizeof(diag_coor)); memcpy(&(diag_coor[0]), &hx_s_touch_data->coord_buf[0], hx_s_touch_data->touch_info_size); } /* assign state info data */ memcpy(&(state_info[0]), &hx_s_touch_data->state_info[0], 2); return NO_ERR; bypass_checksum_failed_packet: return 1; } int hx_dbg_raw_full_stack(struct himax_ic_data *hx_s_ic_data, struct himax_report_data *hx_s_touch_data) { struct himax_ts_data *ts = hx_s_ts; int32_t *mutual_data; int32_t *self_data; int x_channel = hx_s_ic_data->rx_num; int y_channel = hx_s_ic_data->tx_num; int mul_num; int self_num; int update_idx; int data_status = 0; uint8_t *mutual_data_byte; uint8_t *self_data_byte; hx_s_touch_data->diag_cmd = ts->diag_cmd; mutual_data = getMutualBuffer(); self_data = getSelfBuffer(); mutual_data_byte = getMutualBufferByte(); self_data_byte = getSelfBufferByte(); /* initiallize the block number of mutual and self */ mul_num = hx_s_ic_data->rx_num * hx_s_ic_data->tx_num; self_num = hx_s_ic_data->rx_num + hx_s_ic_data->tx_num; data_status = hx_s_core_fp._diag_parse_raw_data(hx_s_touch_data, mul_num, self_num, hx_s_touch_data->diag_cmd, mutual_data, self_data, mutual_data_byte, self_data_byte); if (data_status != NO_ERR) return data_status; update_idx = atomic_read(&(g_rb_frame.p_update)); // memcpy(&g_rb_frame.rawdata[update_idx].self[0], // &self_data[0], self_num * sizeof(int32_t)); // memcpy(&g_rb_frame.rawdata[update_idx].mutual[0], // &mutual_data[0], mul_num * sizeof(int32_t)); memcpy(&g_rb_frame.rawdata[update_idx].self[0], &hx_s_touch_data->rawdata_buf[4 + 2 * (x_channel * y_channel)], 2 * (x_channel + y_channel) * sizeof(uint8_t)); memcpy(&g_rb_frame.rawdata[update_idx].mutual[0], &hx_s_touch_data->rawdata_buf[4], 2 * (x_channel * y_channel) * sizeof(uint8_t)); g_rb_frame.frame_idx[update_idx] = g_rb_frame.rawdata->index++; if (atomic_read(&(g_rb_frame.p_update)) == (HX_RB_FRAME_SIZE - 1)) atomic_set(&(g_rb_frame.p_update), 0); else { atomic_set(&(g_rb_frame.p_update), atomic_read(&(g_rb_frame.p_update)) + 1); } g_rb_frame.rawdata->cnt_update++; if (ts->debug_log_level & BIT(5)) I("Updated: rb_idx=%d, value_idx=%d\n", update_idx, g_rb_frame.frame_idx[update_idx]); return NO_ERR; } /* #if defined(HX_DEBUG_LEVEL) */ #define HX_DL_COORD_FORMAT \ "P%3d = 0x%2.2X,P%3d = 0x%2.2X,P%3d = 0x%2.2X,P%3d = 0x%2.2X\n" void himax_log_touch_data(struct himax_ts_data *ts, int start) { int i = 0; int print_size = 128; if (start == 1) return; /* report data when end of ts_work*/ if (print_size > hx_s_touch_data->touch_all_size) { E("%s: print size is too large!\n", __func__); return; } for (i = 0; i < print_size; i += 8) { if ((i + 7) >= print_size) { I(HX_DL_COORD_FORMAT, i, ts->xfer_buff[i], i + 1, ts->xfer_buff[i + 1], i + 2, ts->xfer_buff[i + 2], i + 3, ts->xfer_buff[i + 3]); break; } I(HX_DL_COORD_FORMAT, i, ts->xfer_buff[i], i + 1, ts->xfer_buff[i + 1], i + 2, ts->xfer_buff[i + 2], i + 3, ts->xfer_buff[i + 3]); I(HX_DL_COORD_FORMAT, i + 4, ts->xfer_buff[i + 4], i + 5, ts->xfer_buff[i + 5], i + 6, ts->xfer_buff[i + 6], i + 7, ts->xfer_buff[i + 7]); } } #define HX_PEN_LV2_LOG(x) "Stylus[" \ x \ "] X:%d,Y:%d,W:%d,btn1:%d,btn2:%d,tilt_x:%d,tilt_y:%d\n" void himax_log_touch_event(struct himax_ts_data *ts, int start) { int i; bool stylus_valid; if (start == 1) return; /*report data when end of ts_work*/ /* finger log info */ 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 : Finger wrong input!\n", __func__); } /* stylus log info */ if (hx_s_ic_data->stylus_func) { if (g_target_report_data->s[0].x >= 0 && g_target_report_data->s[0].x <= ((ts->pdata->abs_x_max+1)*hx_s_ic_data->stylus_ratio-1) && g_target_report_data->s[0].y >= 0 && g_target_report_data->s[0].y <= ((ts->pdata->abs_y_max+1)*hx_s_ic_data->stylus_ratio-1) && (g_target_report_data->s[0].on == 1)) stylus_valid = true; else stylus_valid = false; if (stylus_valid) {/*stylus down*/ if (g_target_report_data->s[0].hover) I(HX_PEN_LV2_LOG("Hover"), g_target_report_data->s[0].x, g_target_report_data->s[0].y, g_target_report_data->s[0].w, g_target_report_data->s[0].btn, g_target_report_data->s[0].btn2, g_target_report_data->s[0].tilt_x, g_target_report_data->s[0].tilt_y); else I(HX_PEN_LV2_LOG("Contact"), g_target_report_data->s[0].x, g_target_report_data->s[0].y, g_target_report_data->s[0].w, g_target_report_data->s[0].btn, g_target_report_data->s[0].btn2, g_target_report_data->s[0].tilt_x, g_target_report_data->s[0].tilt_y); } } } void himax_log_touch_int_devation(int touched) { if (touched == HX_FINGER_ON) { time_func(&timeStart); /* I(" Irq start time = %ld.%06ld s\n", * timeStart.tv_sec, timeStart.tv_nsec/1000); */ } else if (touched == HX_FINGER_LEAVE) { time_func(&timeEnd); 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", hx_s_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; 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(ts, 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*/ hx_s_core_fp._sense_off(true); /*mode change*/ data[1] = str_pw; data[0] = str_pw; if (hx_s_core_fp._assign_sorting_mode != NULL) hx_s_core_fp._assign_sorting_mode(data); /*sense on*/ hx_s_core_fp._sense_on(1); /*wait mode change*/ do { if (hx_s_core_fp._check_sorting_mode != NULL) hx_s_core_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 = hx_s_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 = hx_s_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; int frame_indx; if (strnstr(buf, "help", len) != NULL) { hx_s_debug_data->is_call_help = true; goto END; } if (buf[0] == 'r' && buf[1] == 'b' && hx_s_debug_data->is_stack_full_raw == true){ if (len > 0) { strlcpy(&buf[0], &buf[2], len); len -= 2; if (!kstrtoint(buf, 10, &rst)) { frame_indx = rst; if (frame_indx >= HX_RB_FRAME_SIZE) E("Bigger than rb max size, %d\n", frame_indx); else { I("Now set to idx %d\n", frame_indx); g_re_ass_rb_idx = frame_indx; } } goto END; } else { E("%s:Fail command!\n", __func__); goto END; } } switch (len) { case 1:/*raw out select - diag,X*/ if (!kstrtoint(buf, 16, &rst)) { process_type = (rst >> 4) & 0xF; ts->diag_cmd = rst & 0xF; 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); hx_s_core_fp._return_event_stack(); } hx_s_core_fp._diag_register_set(ts->diag_cmd, process_type, false); if (ts->diag_cmd == 0) { hx_s_touch_data->touch_all_size = hx_s_touch_data->touch_all_size_normal; hx_s_touch_data->rawdata_size = hx_s_touch_data->rawdata_size_normal; hx_s_debug_data->is_stack_full_raw = false; hx_s_debug_data->is_stack_output_bin = 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); hx_s_core_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 { hx_s_core_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); hx_s_core_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 { hx_s_core_fp._diag_register_set(ts->diag_cmd, process_type, true); } } else if (process_type == 0x0f) { hx_s_touch_data->touch_all_size = hx_s_touch_data->touch_all_size_full_stack; hx_s_touch_data->rawdata_size = hx_s_touch_data->rawdata_size_full_stack; hx_dbg_rst_rb(); hx_s_debug_data->is_stack_full_raw = true; hx_s_core_fp._diag_register_set(ts->diag_cmd, 0, true); } else if (process_type == 0x0e) { hx_s_debug_data->is_stack_output_bin = true; if (ts->diag_cmd <= 3 && ts->diag_cmd >= 1) { hx_s_core_fp._diag_register_set(ts->diag_cmd, 0, true); } else { process_type = 1; if (!dsram_flag) { /*Start wrok queue*/ himax_int_enable(0); hx_s_core_fp._diag_register_set( ts->diag_cmd, 0, 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 { hx_s_core_fp._diag_register_set( ts->diag_cmd, 0, 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: hx_s_debug_data->is_stack_full_raw = false; 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 (hx_s_debug_data->is_call_help) { seq_printf(m, HELP_DIAG_ARR); hx_s_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 (strnstr(buf, "help", len) != NULL) { hx_s_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 < (hx_s_ic_data->rx_num * hx_s_ic_data->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 < (hx_s_ic_data->rx_num + hx_s_ic_data->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],state_info[1]); */ #if defined(HX_NEW_EVENT_STACK_FORMAT) seq_printf(s, "ReCal = %d\t", state_info[0] & 0x03); seq_printf(s, "Base Line = %d\t", state_info[0] >> 2 & 0x01); seq_printf(s, "Palm = %d\t", state_info[0] >> 3 & 0x01); seq_printf(s, "Idle mode = %d\t", state_info[0] >> 4 & 0x01); seq_printf(s, "Water = %d\n", state_info[0] >> 5 & 0x01); seq_printf(s, "TX Hop = %d\t", state_info[0] >> 6 & 0x01); seq_printf(s, "AC mode = %d\t", state_info[0] >> 7 & 0x01); seq_printf(s, "Glove = %d\t", state_info[1] & 0x01); seq_printf(s, "Stylus = %d\t", state_info[1] >> 1 & 0x01); seq_printf(s, "Hovering = %d\t", state_info[1] >> 2 & 0x01); seq_printf(s, "Proximity = %d\t", state_info[1] >> 3 & 0x01); seq_printf(s, "KEY = %d\n", state_info[1] >> 4 & 0x0F); #else seq_printf(s, "ReCal = %d\t", state_info[0] & 0x01); seq_printf(s, "Palm = %d\t", state_info[0] >> 1 & 0x01); seq_printf(s, "AC mode = %d\t", state_info[0] >> 2 & 0x01); seq_printf(s, "Water = %d\n", state_info[0] >> 3 & 0x01); seq_printf(s, "Glove = %d\t", state_info[0] >> 4 & 0x01); seq_printf(s, "TX Hop = %d\t", state_info[0] >> 5 & 0x01); seq_printf(s, "Base Line = %d\t", state_info[0] >> 6 & 0x01); seq_printf(s, "OSR Hop = %d\t", state_info[1] >> 3 & 0x01); seq_printf(s, "KEY = %d\n", 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 * hx_s_ic_data->rx_num]); else seq_printf(s, "%6d", diag_mutual[i + j * hx_s_ic_data->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 = hx_s_ic_data->rx_num; int y_channel = hx_s_ic_data->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 = hx_s_ic_data->rx_num; int y_channel = hx_s_ic_data->tx_num; int out_max; int self_cnt; 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 = hx_s_ic_data->rx_num; int y_channel = hx_s_ic_data->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, j; unsigned int index = 0; int x_channel = hx_s_ic_data->rx_num; int y_channel = hx_s_ic_data->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; uint8_t *mutual_data_byte = NULL; uint8_t *self_data_byte = NULL; int32_t new_data; int update_idx = 0; /* 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)); 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 (!hx_s_core_fp._get_DSRAM_data(info_data, dsram_flag)) { E("%s: Get DSRAM data failed\n", __func__); kfree(info_data); return false; } index = 0; if (hx_s_debug_data->is_stack_output_bin) { mutual_data_byte = getMutualBufferByte(); self_data_byte = getSelfBufferByte(); memcpy(mutual_data_byte, info_data, y_channel * x_channel*2); memcpy(self_data_byte, info_data+(y_channel * x_channel*2), (y_channel + x_channel)*2); } else { 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; } } 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 */ } if (hx_s_debug_data->is_stack_full_raw) { update_idx = atomic_read(&(g_rb_frame.p_update)); // memcpy(&g_rb_frame.rawdata[update_idx].self[0], // &self_data[0], // (x_channel + y_channel) * sizeof(int32_t)); // memcpy(&g_rb_frame.rawdata[update_idx].mutual[0], // &mutual_data[0], // (x_channel * y_channel) * sizeof(int32_t)); memcpy(&g_rb_frame.rawdata[update_idx].self[0], &info_data[2 * (x_channel * y_channel)], 2 * (x_channel + y_channel) * sizeof(uint8_t)); memcpy(&g_rb_frame.rawdata[update_idx].mutual[0], &info_data[0], 2 * (x_channel * y_channel) * sizeof(uint8_t)); g_rb_frame.frame_idx[update_idx] = g_rb_frame.rawdata->index++; if (atomic_read(&(g_rb_frame.p_update)) == (HX_RB_FRAME_SIZE - 1)) atomic_set(&(g_rb_frame.p_update), 0); else { atomic_set(&(g_rb_frame.p_update), atomic_read(&(g_rb_frame.p_update)) + 1); } g_rb_frame.rawdata->cnt_update++; I("Updated: rb_idx=%d, value_idx=%d\n", update_idx, g_rb_frame.frame_idx[update_idx]); } kfree(info_data); return true; } static int find_idx_min_array(const int *array, int size) { int result = 0; int i = 0; for (i = 0; i < size; i++) { if (array[result] > array[i]) result = i; } return result; } static void node_output_bin(struct seq_file *s, int mutual_len, int self_len, uint8_t *self, uint8_t *mutual, int rb_idx, int frm_idx){ uint8_t header[RAW_DATA_HEADER_LENGTH]; header[0] = 0x03;//Mutual+self header[1] = 0xff&rb_idx; header[2] = 0xff&frm_idx; header[3] = 0xff&(frm_idx>>8); header[4] = 0xff&(frm_idx>>16); header[5] = 0xff&(frm_idx>>24); seq_write(s, header, RAW_DATA_HEADER_LENGTH); seq_write(s, self, sizeof(uint8_t) * self_len); // Mutual seq_write(s, mutual, sizeof(uint8_t) * mutual_len); } static int himax_diag_print(struct seq_file *s, void *v) { int x_num = hx_s_ic_data->rx_num; int y_num = hx_s_ic_data->tx_num; size_t ret = 0; uint16_t mutual_num, self_num; int output_p = atomic_read(&(g_rb_frame.p_output)); int next_output_p; mutual_num = (x_num * y_num)*2; self_num = (x_num + y_num)*2; /* don't add KEY_COUNT */ if (!hx_s_debug_data->is_stack_full_raw) { if (hx_s_debug_data->is_stack_output_bin) { node_output_bin(s, mutual_num, self_num, diag_self_byte, diag_mutual_byte, 0, 0); } else { 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); /*pring state info*/ print_state_info(s); } } else { if (output_p + 1 == HX_RB_FRAME_SIZE) next_output_p = 0; else next_output_p = output_p + 1; if (g_rb_frame.frame_idx[output_p] < g_rb_frame.frame_idx[next_output_p]) output_p = next_output_p; if (g_rb_frame.rawdata->cnt_update >= (HX_RB_FRAME_SIZE - 1)) output_p = find_idx_min_array( g_rb_frame.frame_idx, HX_RB_FRAME_SIZE); if (g_re_ass_rb_idx >= 0) { I("reassign to get idx %d!\n", g_re_ass_rb_idx); output_p = g_re_ass_rb_idx; g_re_ass_rb_idx = -9487; } node_output_bin(s, mutual_num, self_num, g_rb_frame.rawdata[output_p].self, g_rb_frame.rawdata[output_p].mutual, output_p, g_rb_frame.frame_idx[output_p]); atomic_set(&(g_rb_frame.p_output), output_p); g_rb_frame.rawdata->cnt_update = 0; } /* recovery status after print*/ g_max_mutual = 0; g_min_mutual = 0xFFFF; g_max_self = 0; g_min_self = 0xFFFF; if (s->count >= s->size) overflow++; return ret; } static int himax_stack_show(struct seq_file *s, void *v) { struct himax_ts_data *ts = hx_s_ts; if (hx_s_debug_data->is_call_help) { seq_puts(s, HELP_DIAG); hx_s_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 = hx_s_ts; int d_type; int current_size = ((hx_s_ic_data->tx_num + 1) * (hx_s_ic_data->rx_num + 1) + hx_s_ic_data->tx_num + hx_s_ic_data->rx_num) * 10 + 256; if (hx_s_debug_data->is_call_help) { seq_puts(s, HELP_DIAG); hx_s_debug_data->is_call_help = false; } else { d_type = (!ts->diag_cmd)?rs:ts->diag_cmd; s->size = current_size; I("%s, s->size = %d\n", __func__, (int)s->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); hx_s_core_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; hx_s_core_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 int 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}; int ret = NO_ERR; himax_int_enable(0); hx_s_core_fp._sense_off(true); usleep_range(20000, 20001); hx_parse_assign_cmd(0x00000001, tmp_data, DATA_LEN_4); hx_s_core_fp._register_write(0x900000F0, tmp_data, DATA_LEN_4); usleep_range(20000, 20001); hx_s_core_fp._register_read(0x900000F0, 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"); #if defined(HX_ZERO_FLASH) hx_s_core_fp._ic_reset(3); #else hx_s_core_fp._ic_reset(0); #endif usleep_range(20000, 20001); do { hx_parse_assign_cmd(0x900000A8, tmp_addr, DATA_LEN_4); hx_s_core_fp._register_read(0x900000A8, 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); hx_parse_assign_cmd(0x900000F0, tmp_addr, DATA_LEN_4); hx_s_core_fp._register_read(0x900000F0, 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__); ret++; } else { I("%s, Unknown Fail state1=0x%02X, state2=0x%02X!\n", __func__, rst_sts1, rst_sts2); ret++; } hx_s_core_fp._sense_on(0x00); himax_int_enable(1); return ret; } #endif static int himax_reset_read(struct seq_file *m) { int ret = NO_ERR; if (hx_s_debug_data->is_checking_reset) { #if defined(HX_RST_PIN_FUNC) if (test_rst_pin() == NO_ERR) { seq_printf(m, "Reset PIN check OK!\n"); } else { seq_printf(m, "Reset PIN check Fail!\n"); } #endif hx_s_debug_data->is_checking_reset = false; } else { if (hx_s_debug_data->is_call_help) { seq_printf(m, HELP_RST); hx_s_debug_data->is_call_help = false; } else { seq_printf(m, "reset,%d finish\n", (hx_s_debug_data->reset_cmd_value+1)); } } return ret; } static ssize_t himax_reset_write(char *buf, size_t len) { if (len >= 12) { I("%s: no command exceeds 12 chars.\n", __func__); return -EFAULT; } if (strnstr(buf, "help", len) != NULL) { hx_s_debug_data->is_call_help = true; } else { #if defined(HX_RST_PIN_FUNC) if (strnstr(buf, "test", len) != NULL) { hx_s_debug_data->is_checking_reset = true; goto END; } #endif if (buf[0] == '1') hx_s_debug_data->reset_cmd_value = 0; else if (buf[0] == '2') hx_s_debug_data->reset_cmd_value = 1; else if (buf[0] == '3') hx_s_debug_data->reset_cmd_value = 2; else if (buf[0] == '4') hx_s_debug_data->reset_cmd_value = 3; else if (buf[0] == 'l' && buf[1] == 'o') hx_s_debug_data->reset_cmd_value = 4; else if (buf[0] == 'h' && buf[1] == 'i') hx_s_debug_data->reset_cmd_value = 5; hx_s_core_fp._ic_reset(hx_s_debug_data->reset_cmd_value); /* else if (buf[0] == '5') */ /* ESD_HW_REST(); */ } #if defined(HX_ZERO_FLASH) if (buf[0] != '4') hx_s_core_fp._0f_reload_to_active(); #endif #if defined(HX_RST_PIN_FUNC) END: #endif return len; } void hx_dump_prog_set(uint8_t prog) { g_flash_progress = prog; if (prog == ONGOING) hx_s_debug_data->flash_dump_going = ONGOING; else hx_s_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; uint32_t dump_size = 0; uint32_t print_size = 0; #if defined(HX_RW_FILE) loff_t pos = 0; #endif I("dump_progress = %d\n", flash_progress); if (g_dump_cmd == 0) { seq_printf(s, HELP_FLASH_DUMP); goto END; } 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"); if (g_dump_size != 0) dump_size = g_dump_size; else dump_size = hx_s_ic_data->flash_size; print_size = dump_size * 6 + 256; I("Now buffer size=%d, data size = %d ,print size = %d!\n", (int)s->size, dump_size, print_size); /*print flash dump data*/ if (g_dump_show == 2 && flash_progress == FINISHED) { if (s->size < print_size) { s->size = print_size; I("%s, s->size = %d\n", __func__, (int)s->size); s->buf = kcalloc(s->size, sizeof(char), GFP_KERNEL); if (s->buf == NULL) { E("%s,%d: Memory allocation falied!\n", __func__, __LINE__); ret = -ENOMEM; goto END; } memset(s->buf, 0, s->size * sizeof(char)); } seq_puts(s, "Start to print dump data\n"); for (i = 0; i < dump_size; i++) { seq_printf(s, "0x%02X,", g_dump_buffer[i]); if (i % 16 == 15) seq_puts(s, "\n"); } } else if (g_dump_show == 1) { #if defined(HX_RW_FILE) I("Now vts_name=%s\n", g_file_path); if (hx_open_file(g_file_path) == NO_ERR) { hx_write_file(g_dump_buffer, dump_size, pos); hx_close_file(); } #else I("%s:No support RW file\n", __func__); #endif } 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; uint32_t str_len = 0; int chk; 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; } str_len = len; buf[str_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]); if (i == 0) { if (strnstr(input_str[i], "help", len) != NULL) { is_flash = 0; goto CON_WORK; } else if (strnstr(input_str[i], "flash", len) != NULL) { is_flash = 1; } else if (strnstr(input_str[i], "ram", len) != NULL) { is_flash = 2; } else { is_flash = -1; goto CON_WORK; } } else if (i == 1) { if (strnstr(input_str[i], "print", len) != NULL) { is_file = 2; } else if (strnstr(input_str[i], "file", len) != NULL) { is_file = 1; } else { is_file = -1; goto CON_WORK; } } else if (i == 2) { chk = kstrtoint(input_str[i], 10, &dump_size); if (chk) { E("%s:addr kstrtoint return fail!\n", __func__); dump_size = 0; } } else if (i == 3) { chk = kstrtoint(input_str[i], 16, &addr); if (chk) { E("%s:addr kstrtoint return fail!\n", __func__); addr = 0; } I("addr=0x%08X\n", addr); } } } 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(hx_s_ts->dump_wq, &hx_s_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(hx_s_ts->dump_wq, &hx_s_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(hx_s_ts->dump_wq, &hx_s_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); hx_s_core_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 = hx_s_core_fp._register_read(g_dump_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 (hx_s_debug_data->is_call_help) { seq_printf(m, HELP_GUEST_INFO); hx_s_debug_data->is_call_help = false; } else { I("guest info progress\n"); if (hx_s_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++) { 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 (strnstr(buf, "help", len) != NULL) { hx_s_debug_data->is_call_help = true; } else { if (buf[0] == 'r') { I("%s,Test to get", __func__); queue_work(hx_s_ts->guest_info_wq, &hx_s_ts->guest_info_work); } } return len; } #endif static int himax_test_bus_read(struct seq_file *m) { int ret = NO_ERR; if (hx_s_core_fp._read_i2c_status()) seq_printf(m, "Bus communication is bad.\n"); else seq_printf(m, "Bus communication is good.\n"); i2c_error_count = 0; 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", hx_s_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 (hx_s_ic_data->int_is_edge) seq_printf(m, "Driver register Interrupt : EDGE TIRGGER\n"); else seq_printf(m, "Driver register Interrupt : LEVEL TRIGGER\n"); if (hx_s_ic_data->fw_int_is_edge != hx_s_ic_data->int_is_edge) seq_printf(m, "\tTirgger different in fw\n"); if (hx_s_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", hx_s_ic_data->rx_num); if (hx_s_ic_data->fw_rx_num != hx_s_ic_data->rx_num) seq_printf(m, "\t[Warning]FW RX Num : %d\n", hx_s_ic_data->fw_rx_num); seq_printf(m, "TX Num : %d\n", hx_s_ic_data->tx_num); if (hx_s_ic_data->fw_tx_num != hx_s_ic_data->tx_num) seq_printf(m, "\t[Warning]FW TX Num : %d\n", hx_s_ic_data->fw_tx_num); seq_printf(m, "BT Num : %d\n", hx_s_ic_data->bt_num); if (hx_s_ic_data->fw_bt_num != hx_s_ic_data->bt_num) seq_printf(m, "\t[Warning]FW BT Num : %d\n", hx_s_ic_data->fw_bt_num); seq_printf(m, "X Resolution : %d\n", hx_s_ic_data->x_res); seq_printf(m, "Y Resolution : %d\n", hx_s_ic_data->y_res); seq_printf(m, "Max Point : %d\n", hx_s_ic_data->max_pt); if (hx_s_ic_data->fw_max_pt != hx_s_ic_data->max_pt) seq_printf(m, "\t[Warning]FW Max point : %d\n", hx_s_ic_data->fw_max_pt); seq_printf(m, "Stylus Support : %d\n", hx_s_ic_data->stylus_func); if (hx_s_ic_data->fw_stylus_func != hx_s_ic_data->stylus_func) seq_printf(m, "\t[Warning]FW Stylus Support : %d\n", hx_s_ic_data->fw_stylus_func); if (hx_s_ic_data->stylus_func) seq_printf(m, "Stylus Ratio : %d\n", hx_s_ic_data->stylus_ratio); if ((hx_s_ic_data->fw_stylus_ratio != hx_s_ic_data->stylus_ratio) && hx_s_ic_data->stylus_func) seq_printf(m, "\t[Warning]FW Stylus Ratio : %d\n", hx_s_ic_data->fw_stylus_ratio); if (hx_s_ic_data->stylus_func) seq_printf(m, "Stylus V2 EN : %d\n", hx_s_ic_data->stylus_id_v2); if ((hx_s_ic_data->stylus_id_v2 != hx_s_ic_data->fw_stylus_id_v2) && hx_s_ic_data->stylus_func) seq_printf(m, "\t[Warning]FW Stylus V2 EN : %d\n", hx_s_ic_data->fw_stylus_id_v2); #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 #if defined(HX_ZERO_FLASH) seq_printf(m, "Flash Type: Zero Flash\n"); #else seq_printf(m, "Flash Type: With Flash\n"); #endif if (hx_s_ts->spi == NULL) { seq_printf(m, "Bus: I2C\n"); } else { seq_printf(m, "Bus: SPI\n"); } return ret; } static int himax_pen_info_read(struct seq_file *m) { int ret = NO_ERR; if (FIX_HX_STYLUS_FUNC != 0 || FIX_HX_STYLUS_ID_V2 != 0) { seq_printf(m, "Pen Battery info:\n"); seq_printf(m, "%d\n", g_target_report_data->s[0].battery_info); seq_printf(m, "Pen ID:\n"); seq_printf(m, "%llx\n", g_target_report_data->s[0].id); } else { seq_printf(m, "No support pen\n"); } 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{ #if defined(HX_UID_PASSWORD) snprintf(fileName, is_len - 5, "%s", &buf[5]); #else snprintf(fileName, is_len - 2, "%s", &buf[2]); #endif } I("%s: upgrade from file(%s) start!\n", __func__, fileName); /* manual upgrade will not use embedded firmware */ result = request_firmware(&fw, fileName, hx_s_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; hx_s_core_fp._bin_desc_get((unsigned char *)fw->data, HX1K); result = hx_s_core_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); #if defined(HX_UID_PASSWORD) if(g_uid_upgrade_flag){ result = i_add_uid_for_FW(fw); if (hx_s_core_fp._fts_ctpm_fw_upgrade_with_sys_fs( (unsigned char *)g_remodify_fw, g_remodify_fw_len, 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; } } else { I("NOW Running common flow update!\n"); if (hx_s_core_fp._fts_ctpm_fw_upgrade_with_sys_fs( (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; } } #else if (hx_s_core_fp._fts_ctpm_fw_upgrade_with_sys_fs( (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; } #endif #endif release_firmware(fw); goto firmware_upgrade_done; firmware_upgrade_done: fw_update_going = false; hx_s_core_fp._reload_disable(0); hx_s_core_fp._power_on_init(); hx_s_core_fp._read_FW_ver(); hx_s_core_fp._tp_info_check(); himax_int_enable(1); return result; } static int himax_update_read(struct seq_file *m) { int ret = NO_ERR; if (hx_s_debug_data->is_call_help) { seq_printf(m, HELP_UPDATE); hx_s_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 (strnstr(buf, "help", len) != NULL) hx_s_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; if (hx_s_debug_data->is_call_help) { seq_printf(m, HELP_VER); hx_s_debug_data->is_call_help = false; } else { seq_printf(m, "FW_VER = 0x%2.2X\n", hx_s_ic_data->vendor_fw_ver); if (hx_s_ts->chip_cell_type == CHIP_IS_ON_CELL) seq_printf(m, "CONFIG_VER = 0x%2.2X\n", hx_s_ic_data->vendor_config_ver); else { seq_printf(m, "TOUCH_VER = 0x%2.2X\n", hx_s_ic_data->vendor_touch_cfg_ver); seq_printf(m, "DISPLAY_VER = 0x%2.2X\n", hx_s_ic_data->vendor_display_cfg_ver); } if (hx_s_ic_data->vendor_cid_maj_ver < 0 && hx_s_ic_data->vendor_cid_min_ver < 0) seq_printf(m, "CID_VER = NULL\n"); else seq_printf(m, "CID_VER = 0x%2.2X\n", (hx_s_ic_data->vendor_cid_maj_ver << 8 | hx_s_ic_data->vendor_cid_min_ver)); if (hx_s_ic_data->vendor_panel_ver < 0) seq_printf(m, "PANEL_VER = NULL\n"); else seq_printf(m, "PANEL_VER = 0x%2.2X\n", hx_s_ic_data->vendor_panel_ver); if (hx_s_ts->chip_cell_type == CHIP_IS_IN_CELL) { seq_printf(m, "Cusomer = %s\n", hx_s_ic_data->vendor_cus_info); seq_printf(m, "Project = %s\n", hx_s_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 (strnstr(buf, "help", len) != NULL) hx_s_debug_data->is_call_help = true; else hx_s_core_fp._read_FW_ver(); return len; } static int himax_list_cmd_read(struct seq_file *m) { int ret = NO_ERR; int i, j; 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 { if (hx_s_debug_data->is_info_check) { if (hx_s_core_fp._tp_info_check() == 0) { seq_printf(m, "FIX_TOUCH_INFO is OK\n"); } else { seq_printf(m, "FIX_TOUCH_INFO does NOT match to FW information\n"); } hx_s_debug_data->is_info_check = false; } 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; char *str_ptr = NULL; int str_len = 0; int input_cmd_len = 0; int i = 0, j = 0; if (len >= 4096) { I("%s: no command exceeds 4096 chars.\n", __func__); return -EFAULT; } buf = kzalloc(sizeof(char) * 4096, GFP_KERNEL); if (copy_from_user(buf, ubuf, len)) { len = -EFAULT; goto ENDFUCTION; } 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) goto ENDFUCTION; if (buf[0] == 't') { #if defined(HX_UID_PASSWORD) if (buf[1] == 'u'&& buf[2] == 'i'&& buf[3] == 'd'){ g_uid_upgrade_flag = true; I("g_uid_upgrade_flag is true! update with uid number \n"); }else if (buf[1] == 'n'&& buf[2] == 'i'&& buf[3] == 'd'){ g_uid_upgrade_flag = false; I("g_uid_upgrade_flag is false,normal update \n"); } #else g_uid_upgrade_flag = false; I("g_uid_upgrade_flag is false,normal update\n"); #endif debug_level_cmd = buf[0]; hx_node_update(buf, len); } else if (buf[0] == 'c' && buf[1] == 't' && buf[2] == 'i') { /* Compare Touch Information */ hx_s_debug_data->is_info_check = true; goto ENDFUCTION; } else { /* others,do nothing */ debug_level_cmd = 0; } ENDFUCTION: kfree(buf); 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", hx_s_ts->chip_name); seq_printf(m, "FW_VER = 0x%2.2X\n", hx_s_ic_data->vendor_fw_ver); if (hx_s_ts->chip_cell_type == CHIP_IS_ON_CELL) { seq_printf(m, "CONFIG_VER = 0x%2.2X\n", hx_s_ic_data->vendor_config_ver); } else { seq_printf(m, "TOUCH_VER = 0x%2.2X\n", hx_s_ic_data->vendor_touch_cfg_ver); seq_printf(m, "DISPLAY_VER = 0x%2.2X\n", hx_s_ic_data->vendor_display_cfg_ver); } if (hx_s_ic_data->vendor_cid_maj_ver < 0 && hx_s_ic_data->vendor_cid_min_ver < 0) { seq_printf(m, "CID_VER = NULL\n"); } else { seq_printf(m, "CID_VER = 0x%2.2X\n", (hx_s_ic_data->vendor_cid_maj_ver << 8 | hx_s_ic_data->vendor_cid_min_ver)); } if (hx_s_ic_data->vendor_panel_ver < 0) { seq_printf(m, "PANEL_VER = NULL\n"); } else { seq_printf(m, "PANEL_VER = 0x%2.2X\n", hx_s_ic_data->vendor_panel_ver); } if (hx_s_ts->chip_cell_type == CHIP_IS_IN_CELL) { seq_printf(m, "Cusomer = %s\n", hx_s_ic_data->vendor_cus_info); seq_printf(m, "Project = %s\n", hx_s_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) { hx_s_debug_data->_ts_dbg_func = himax_ts_dbg_func; hx_s_debug_data->_set_diag_cmd = himax_set_diag_cmd; hx_s_debug_data->_raw_full_stack = hx_dbg_raw_full_stack; hx_s_debug_data->flash_dump_going = false; hx_s_debug_data->is_checking_irq = false; hx_s_debug_data->is_info_check = false; hx_s_debug_data->is_checking_reset = false; hx_s_debug_data->is_call_help = false; hx_s_debug_data->is_stack_full_raw = false; hx_s_ts->select_slave_reg = false; hx_s_ts->acc_slave_reg = 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) { hx_s_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(hx_s_ts->himax_diag_wq, &hx_s_ts->himax_diag_delay_work, 1 / 10 * HZ); } else { dsram_flag = false; } } void dbg_func_ptr_init(void) { /*debug function ptr init*/ int idx = 1; dbg_func_ptr_r[idx] = himax_crc_test_read; idx++; dbg_func_ptr_r[idx] = himax_proc_FW_debug_read; idx++; dbg_func_ptr_r[idx] = himax_attn_read; idx++; dbg_func_ptr_w[idx] = himax_layout_write; dbg_func_ptr_r[idx] = himax_layout_read; idx++; #if defined(HX_EXCP_RECOVERY) dbg_func_ptr_w[idx] = himax_excp_cnt_write; dbg_func_ptr_r[idx] = himax_excp_cnt_read; #endif idx++; dbg_func_ptr_w[idx] = himax_sense_on_off_write; idx++; dbg_func_ptr_w[idx] = himax_debug_level_write; dbg_func_ptr_r[idx] = himax_debug_level_read; idx++; #if defined(HX_TP_PROC_GUEST_INFO) dbg_func_ptr_w[idx] = himax_proc_guest_info_write; dbg_func_ptr_r[idx] = himax_proc_guest_info_read; #endif idx++; dbg_func_ptr_w[idx] = himax_int_en_write; dbg_func_ptr_r[idx] = himax_int_en_read; idx++; dbg_func_ptr_w[idx] = himax_irq_info_write; dbg_func_ptr_r[idx] = himax_irq_info_read; idx++; dbg_func_ptr_r[idx] = himax_proc_register_read; dbg_func_ptr_w[idx] = himax_proc_register_write; idx++; dbg_func_ptr_r[idx] = himax_reset_read; dbg_func_ptr_w[idx] = himax_reset_write; idx++; dbg_func_ptr_r[idx] = himax_diag_arrange_read; dbg_func_ptr_w[idx] = himax_diag_arrange_write; idx++; dbg_func_ptr_w[idx] = himax_diag_cmd_write; idx++; dbg_func_ptr_w[idx] = himax_irq_dbg_cmd_write; idx++; dbg_func_ptr_r[idx] = himax_test_bus_read; idx++; dbg_func_ptr_w[idx] = himax_update_write; dbg_func_ptr_r[idx] = himax_update_read; idx++; dbg_func_ptr_w[idx] = himax_version_write; dbg_func_ptr_r[idx] = himax_version_read; idx++; dbg_func_ptr_r[idx] = himax_info_read; idx++; dbg_func_ptr_r[idx] = himax_pen_info_read; idx++; dbg_func_ptr_r[idx] = himax_list_cmd_read; idx++; dbg_func_ptr_w[idx] = himax_help_write; dbg_func_ptr_r[idx] = himax_help_read; } int himax_touch_proc_init(void) { himax_proc_diag_dir = proc_mkdir(HIMAX_PROC_DIAG_FOLDER, hx_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, hx_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, hx_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, hx_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: remove_proc_entry(HIMAX_PROC_DIAG_FOLDER, hx_touch_proc_dir); return -ENOMEM; } void himax_touch_proc_deinit(void) { remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, hx_touch_proc_dir); remove_proc_entry(HIMAX_PROC_DEBUG_FILE, hx_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); remove_proc_entry(HIMAX_PROC_DIAG_FOLDER, hx_touch_proc_dir); } static void hx_dbg_rst_rb(void) { int i = 0; I("%s: Now reset ring buffer!\n", __func__); g_rb_frame.rawdata->index = 0; g_rb_frame.rawdata->cnt_update = 0; atomic_set(&(g_rb_frame.p_update), 0); atomic_set(&(g_rb_frame.p_output), 0); atomic_set(&(g_rb_frame.length), 0); for (i = 0; i < HX_RB_FRAME_SIZE; i++) { memset(g_rb_frame.rawdata[i].mutual, 0x00, (sizeof(uint8_t) * (hx_s_ic_data->rx_num * hx_s_ic_data->tx_num) * 2)); memset(g_rb_frame.rawdata[i].self, 0x00, (sizeof(uint8_t) * (hx_s_ic_data->rx_num + hx_s_ic_data->tx_num) * 2)); g_rb_frame.frame_idx[i] = 0; } } int himax_debug_init(void) { struct himax_ts_data *ts = hx_s_ts; int i = 0; 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; } hx_s_debug_data = kzalloc(sizeof(struct himax_debug), GFP_KERNEL); if (hx_s_debug_data == NULL) { /*Allocate debug data space*/ E("%s: hx_s_debug_data allocate failed\n", __func__); goto err_alloc_debug_data_fail; } himax_himax_data_init(); g_dump_buffer = kcalloc(hx_s_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(hx_s_ic_data->rx_num, hx_s_ic_data->tx_num); if (getSelfBuffer() == NULL) { E("%s: self buffer allocate failed\n", __func__); goto err_self_buf_alloc_failed; } setSelfBufferByte(hx_s_ic_data->rx_num, hx_s_ic_data->tx_num); if (getSelfBufferByte() == NULL) { E("%s: self buffer allocate failed\n", __func__); goto err_self_byte_buf_alloc_failed; } setSelfNewBuffer(hx_s_ic_data->rx_num, hx_s_ic_data->tx_num); if (getSelfNewBuffer() == NULL) { E("%s: self new buffer allocate failed\n", __func__); goto err_self_new_alloc_failed; } setSelfOldBuffer(hx_s_ic_data->rx_num, hx_s_ic_data->tx_num); if (getSelfOldBuffer() == NULL) { E("%s: self old buffer allocate failed\n", __func__); goto err_self_old_alloc_failed; } setMutualBuffer(hx_s_ic_data->rx_num, hx_s_ic_data->tx_num); if (getMutualBuffer() == NULL) { E("%s: mutual buffer allocate failed\n", __func__); goto err_mut_buf_alloc_failed; } setMutualBufferByte(hx_s_ic_data->rx_num, hx_s_ic_data->tx_num); if (getMutualBufferByte() == NULL) { E("%s: mutual buffer allocate failed\n", __func__); goto err_mut_byte_buf_alloc_failed; } setMutualNewBuffer(hx_s_ic_data->rx_num, hx_s_ic_data->tx_num); if (getMutualNewBuffer() == NULL) { E("%s: mutual new buffer allocate failed\n", __func__); goto err_mut_new_alloc_failed; } setMutualOldBuffer(hx_s_ic_data->rx_num, hx_s_ic_data->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(hx_s_ic_data->rx_num_2, hx_s_ic_data->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); g_rb_frame.rawdata = kzalloc( sizeof(struct frame_data) * HX_RB_FRAME_SIZE, GFP_KERNEL); g_rb_frame.rawdata->index = 0; g_rb_frame.rawdata->cnt_update = 0; atomic_set(&(g_rb_frame.p_update), 0); atomic_set(&(g_rb_frame.p_output), 0); atomic_set(&(g_rb_frame.length), 0); for (i = 0; i < HX_RB_FRAME_SIZE; i++) { g_rb_frame.rawdata[i].mutual = kzalloc( sizeof(uint8_t) * (hx_s_ic_data->rx_num * hx_s_ic_data->tx_num) * 2, GFP_KERNEL); g_rb_frame.rawdata[i].self = kzalloc( sizeof(uint8_t) * (hx_s_ic_data->rx_num + hx_s_ic_data->tx_num) * 2, GFP_KERNEL); } 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_byte); diag_mutual_byte = NULL; err_mut_byte_buf_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_byte); diag_self_byte = NULL; err_self_byte_buf_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(hx_s_debug_data); hx_s_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 = hx_s_ts; himax_touch_proc_deinit(); cancel_delayed_work_sync(&ts->himax_diag_delay_work); destroy_workqueue(ts->himax_diag_wq); #if defined(HX_TP_PROC_2T2R) kfree(diag_mutual_2); diag_mutual_2 = NULL; #endif kfree(diag_mutual_byte); diag_mutual_byte = 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_byte); diag_self_byte = 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(hx_s_debug_data); hx_s_debug_data = NULL; kfree(proc_reg_buf); proc_reg_buf = NULL; return 0; } EXPORT_SYMBOL(himax_debug_remove);