diff --git a/drivers/input/touchscreen/himax_v3_mmi/Android.mk b/drivers/input/touchscreen/himax_v3_mmi/Android.mk index 285f58e5436e..e058fe1694a1 100644 --- a/drivers/input/touchscreen/himax_v3_mmi/Android.mk +++ b/drivers/input/touchscreen/himax_v3_mmi/Android.mk @@ -7,8 +7,23 @@ else HIMAX_MMI_MODULE_PATH := $(KERNEL_MODULES_OUT) endif -ifeq ($(HIMAX_V3_MMI_HX83102),true) - KERNEL_CFLAGS += CONFIG_INPUT_HIMAX_V3_MMI_IC_NAME=hx83102 +ifeq ($(HIMAX_V2_MMI_0FLASH),true) + KERNEL_CFLAGS += CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_0FLASH=y +endif +ifneq ($(BOARD_USES_TOUCH_PALM),) + KERNEL_CFLAGS += CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_ENABLE_PALM=y +endif + +ifneq ($(BOARD_USES_DOUBLE_TAP),) + KERNEL_CFLAGS += CONFIG_INPUT_HIMAX_V2_MMI_ENABLE_DOUBLE_TAP=y +endif + +ifneq ($(BOARD_USES_HIMAX_MULTI_BIN),) + KERNEL_CFLAGS += CONFIG_INPUT_HIMAX_V2_MMI_ENABLE_MULTI_BIN=y +endif + +ifeq ($(HIMAX_V2_MMI_HX83102D),true) + KERNEL_CFLAGS += CONFIG_INPUT_HIMAX_V2_MMI_IC_NAME_D=hx83102d endif include $(CLEAR_VARS) diff --git a/drivers/input/touchscreen/himax_v3_mmi/Kbuild b/drivers/input/touchscreen/himax_v3_mmi/Kbuild index daa55e8bad79..54bb15ef0f2e 100644 --- a/drivers/input/touchscreen/himax_v3_mmi/Kbuild +++ b/drivers/input/touchscreen/himax_v3_mmi/Kbuild @@ -2,23 +2,46 @@ EXTRA_CFLAGS += -Wall EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include \ -I$(TOP)/motorola/kernel/modules/drivers/input/touchscreen/himax_v3_mmi -EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_HIMAX_CHIPSET \ - -DCONFIG_TOUCHSCREEN_HIMAX_COMMON - EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_HIMAX_DEBUG \ -DCONFIG_TOUCHSCREEN_HIMAX_INSPECT EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_HIMAX_INCELL +EXTRA_CFLAGS += -DCONFIG_HMX_DB -ifneq ($(filter hx83102,$(CONFIG_INPUT_HIMAX_V3_MMI_IC_NAME)),) +ifneq ($(filter hx83112,$(CONFIG_INPUT_HIMAX_V2_MMI_IC_NAME)),) + EXTRA_CFLAGS += -D__HIMAX_HX83112_MOD__ +endif + +ifneq ($(filter hx83102,$(CONFIG_INPUT_HIMAX_V2_MMI_IC_NAME)),) EXTRA_CFLAGS += -D__HIMAX_HX83102_MOD__ endif +ifneq ($(filter hx83102d,$(CONFIG_INPUT_HIMAX_V2_MMI_IC_NAME_D)),) + EXTRA_CFLAGS += -D__HIMAX_HX83102D_MOD__ + EXTRA_CFLAGS += -DHX_CODE_OVERLAY +endif + +ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_ENABLE_PALM)),) + EXTRA_CFLAGS += -DHIMAX_PALM_SENSOR_EN +endif + +ifneq ($(filter m y,$(CONFIG_INPUT_HIMAX_V2_MMI_ENABLE_DOUBLE_TAP)),) + EXTRA_CFLAGS += -DHIMAX_V2_SENSOR_EN +endif + +ifneq ($(filter m y,$(CONFIG_INPUT_HIMAX_V2_MMI_ENABLE_MULTI_BIN)),) + EXTRA_CFLAGS += -DHIMAX_V2_MULTI_BIN +endif + obj-m := himax_v3_mmi.o -himax_v3_mmi-objs += himax_platform.o +ifneq ($(filter m y,$(CONFIG_INPUT_TOUCHSCREEN_HIMAX_V2_MMI_0FLASH)),) + himax_v3_mmi-objs += himax_platform_QCT_SPI.o + EXTRA_CFLAGS += -D__HIMAX_PLATFORM_SPI__ \ + -DHX_ZERO_FLASH +endif + himax_v3_mmi-objs += himax_common.o himax_v3_mmi-objs += himax_debug.o himax_v3_mmi-objs += himax_ic_incell_core.o himax_v3_mmi-objs += himax_inspection.o - diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_common.c b/drivers/input/touchscreen/himax_v3_mmi/himax_common.c old mode 100644 new mode 100755 index e47cc5ffe1fe..958e1bb8b2c5 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_common.c +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_common.c @@ -1,3405 +1,4064 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for common functions - * - * 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_common.h"*/ -/*#include "himax_ic_core.h"*/ -#include "himax_inspection.h" -#include "himax_modular_table.h" - -#if defined(__HIMAX_MOD__) -int (*hx_msm_drm_register_client)(struct notifier_block *nb); -int (*hx_msm_drm_unregister_client)(struct notifier_block *nb); -#endif - -#if defined(HX_SMART_WAKEUP) -#define GEST_SUP_NUM 26 -/* Setting cust key define (DF = double finger) */ -/* {Double Tap, Up, Down, Left, Right, C, Z, M, - * O, S, V, W, e, m, @, (reserve), - * Finger gesture, ^, >, <, f(R), f(L), Up(DF), Down(DF), - * Left(DF), Right(DF)} - */ -uint8_t gest_event[GEST_SUP_NUM] = { - 0x80, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x81, 0x1D, 0x2D, 0x3D, 0x1F, 0x2F, 0x51, 0x52, - 0x53, 0x54}; - -/*gest_event mapping to gest_key_def*/ -uint16_t gest_key_def[GEST_SUP_NUM] = { - KEY_POWER, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275}; - -uint8_t *wake_event_buffer; -#endif - -#if !defined(HX_USE_KSYM) -struct himax_chip_entry himax_ksym_lookup; -EXPORT_SYMBOL(himax_ksym_lookup); -#endif - -#define SUPPORT_FINGER_DATA_CHECKSUM 0x0F -#define TS_WAKE_LOCK_TIMEOUT (5000) -#define FRAME_COUNT 5 - -#if defined(HX_TP_PROC_GUEST_INFO) -struct hx_guest_info *g_guest_info_data; -EXPORT_SYMBOL(g_guest_info_data); - -char *g_guest_info_item[] = { - "projectID", - "CGColor", - "BarCode", - "Reserve1", - "Reserve2", - "Reserve3", - "Reserve4", - "Reserve5", - "VCOM", - "Vcom-3Gar", - NULL -}; -#endif - -uint32_t g_hx_chip_inited; - -#if defined(__EMBEDDED_FW__) -struct firmware g_embedded_fw = { - .data = _binary___Himax_firmware_bin_start, -}; -#endif - -#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) -char *i_CTPM_firmware_name = "Himax_firmware.bin"; -bool g_auto_update_flag; -#endif -#if defined(HX_AUTO_UPDATE_FW) -unsigned char *i_CTPM_FW; -int i_CTPM_FW_len; -int g_i_FW_VER; -int g_i_CFG_VER; -int g_i_CID_MAJ; /*GUEST ID*/ -int g_i_CID_MIN; /*VER for GUEST*/ -#endif -#if defined(HX_ZERO_FLASH) -int g_f_0f_updat; -#endif - -struct himax_ts_data *private_ts; -EXPORT_SYMBOL(private_ts); - -struct himax_ic_data *ic_data; -EXPORT_SYMBOL(ic_data); - -struct himax_report_data *hx_touch_data; -EXPORT_SYMBOL(hx_touch_data); - -struct himax_core_fp g_core_fp; -EXPORT_SYMBOL(g_core_fp); - -struct himax_debug *debug_data; -EXPORT_SYMBOL(debug_data); - -struct proc_dir_entry *himax_touch_proc_dir; -EXPORT_SYMBOL(himax_touch_proc_dir); - -int g_mmi_refcnt; -EXPORT_SYMBOL(g_mmi_refcnt); - -#define HIMAX_PROC_TOUCH_FOLDER "android_touch" -/*ts_work about start*/ -struct himax_target_report_data *g_target_report_data; -EXPORT_SYMBOL(g_target_report_data); - -static void himax_report_all_leave_event(struct himax_ts_data *ts); -/*ts_work about end*/ -static int HX_TOUCH_INFO_POINT_CNT; - -struct filename* (*kp_getname_kernel)(const char *filename); -struct file* (*kp_file_open_name)(struct filename *name, - int flags, umode_t mode); - -unsigned long FW_VER_MAJ_FLASH_ADDR; -EXPORT_SYMBOL(FW_VER_MAJ_FLASH_ADDR); - -unsigned long FW_VER_MIN_FLASH_ADDR; -EXPORT_SYMBOL(FW_VER_MIN_FLASH_ADDR); - -unsigned long CFG_VER_MAJ_FLASH_ADDR; -EXPORT_SYMBOL(CFG_VER_MAJ_FLASH_ADDR); - -unsigned long CFG_VER_MIN_FLASH_ADDR; -EXPORT_SYMBOL(CFG_VER_MIN_FLASH_ADDR); - -unsigned long CID_VER_MAJ_FLASH_ADDR; -EXPORT_SYMBOL(CID_VER_MAJ_FLASH_ADDR); - -unsigned long CID_VER_MIN_FLASH_ADDR; -EXPORT_SYMBOL(CID_VER_MIN_FLASH_ADDR); -/*unsigned long PANEL_VERSION_ADDR;*/ - -unsigned long FW_VER_MAJ_FLASH_LENG; -EXPORT_SYMBOL(FW_VER_MAJ_FLASH_LENG); - -unsigned long FW_VER_MIN_FLASH_LENG; -EXPORT_SYMBOL(FW_VER_MIN_FLASH_LENG); - -unsigned long CFG_VER_MAJ_FLASH_LENG; -EXPORT_SYMBOL(CFG_VER_MAJ_FLASH_LENG); - -unsigned long CFG_VER_MIN_FLASH_LENG; -EXPORT_SYMBOL(CFG_VER_MIN_FLASH_LENG); - -unsigned long CID_VER_MAJ_FLASH_LENG; -EXPORT_SYMBOL(CID_VER_MAJ_FLASH_LENG); - -unsigned long CID_VER_MIN_FLASH_LENG; -EXPORT_SYMBOL(CID_VER_MIN_FLASH_LENG); -/*unsigned long PANEL_VERSION_LENG;*/ - -unsigned long FW_CFG_VER_FLASH_ADDR; - -unsigned char IC_CHECKSUM; -EXPORT_SYMBOL(IC_CHECKSUM); - -#if defined(HX_ESD_RECOVERY) -u8 HX_ESD_RESET_ACTIVATE; -EXPORT_SYMBOL(HX_ESD_RESET_ACTIVATE); - -int hx_EB_event_flag; -EXPORT_SYMBOL(hx_EB_event_flag); - -int hx_EC_event_flag; -EXPORT_SYMBOL(hx_EC_event_flag); - -int hx_ED_event_flag; -EXPORT_SYMBOL(hx_ED_event_flag); - -int g_zero_event_count; - -#endif - -static bool chip_test_r_flag; -u8 HX_HW_RESET_ACTIVATE; - -static uint8_t AA_press; -static uint8_t EN_NoiseFilter; -static uint8_t Last_EN_NoiseFilter; - -static int p_point_num = 0xFFFF; -static int probe_fail_flag; -#if defined(HX_USB_DETECT_GLOBAL) -bool USB_detect_flag; -#endif - -#if defined(HX_GESTURE_TRACK) -static int gest_pt_cnt; -static int gest_pt_x[GEST_PT_MAX_NUM]; -static int gest_pt_y[GEST_PT_MAX_NUM]; -static int gest_start_x, gest_start_y, gest_end_x, gest_end_y; -static int gest_width, gest_height, gest_mid_x, gest_mid_y; -static int hx_gesture_coor[16]; -#endif - -int g_ts_dbg; -EXPORT_SYMBOL(g_ts_dbg); - -/* File node for Selftest, SMWP and HSEN - Start*/ -#define HIMAX_PROC_SELF_TEST_FILE "self_test" -struct proc_dir_entry *himax_proc_self_test_file; - -uint8_t HX_PROC_SEND_FLAG; -EXPORT_SYMBOL(HX_PROC_SEND_FLAG); - -#if defined(HX_SMART_WAKEUP) -#define HIMAX_PROC_SMWP_FILE "SMWP" -struct proc_dir_entry *himax_proc_SMWP_file; -#define HIMAX_PROC_GESTURE_FILE "GESTURE" -struct proc_dir_entry *himax_proc_GESTURE_file; -uint8_t HX_SMWP_EN; -#if defined(HX_ULTRA_LOW_POWER) -#define HIMAX_PROC_PSENSOR_FILE "Psensor" -struct proc_dir_entry *himax_proc_psensor_file; -#endif -#endif - -#if defined(HX_HIGH_SENSE) -#define HIMAX_PROC_HSEN_FILE "HSEN" -struct proc_dir_entry *himax_proc_HSEN_file; -#endif - -#if defined(HX_PALM_REPORT) -static int himax_palm_detect(uint8_t *buf) -{ - struct himax_ts_data *ts = private_ts; - int32_t loop_i; - int base = 0; - int x = 0, y = 0, w = 0; - - loop_i = 0; - base = loop_i * 4; - x = buf[base] << 8 | buf[base + 1]; - y = (buf[base + 2] << 8 | buf[base + 3]); - w = buf[(ts->nFinger_support * 4) + loop_i]; - I(" %s HX_PALM_REPORT_loopi=%d,base=%x,X=%x,Y=%x,W=%x\n", - __func__, loop_i, base, x, y, w); - if ((!atomic_read(&ts->suspend_mode)) - && (x == 0xFA5A) - && (y == 0xFA5A) - && (w == 0x00)) - return PALM_REPORT; - else - return NOT_REPORT; -} -#endif - -static ssize_t himax_self_test(struct seq_file *s, void *v) -{ - int val = 0x00; - size_t ret = 0; - - I("%s: enter, %d\n", __func__, __LINE__); - - if (private_ts->suspended == 1) { - E("%s: please do self test in normal active mode\n", __func__); - return HX_INIT_FAIL; - } - - himax_int_enable(0);/* disable irq */ - - private_ts->in_self_test = 1; - - val = g_core_fp.fp_chip_self_test(s, v); -/* - *#if defined(HX_ESD_RECOVERY) - * HX_ESD_RESET_ACTIVATE = 1; - *#endif - * himax_int_enable(1); //enable irq - */ - - private_ts->in_self_test = 0; - -#if defined(HX_ESD_RECOVERY) - HX_ESD_RESET_ACTIVATE = 1; -#endif - himax_int_enable(1); - - return ret; -} - -static void *himax_self_test_seq_start(struct seq_file *s, loff_t *pos) -{ - if (*pos >= 1) - return NULL; - - - return (void *)((unsigned long) *pos + 1); -} - -static void *himax_self_test_seq_next(struct seq_file *s, void *v, loff_t *pos) -{ - return NULL; -} - -static void himax_self_test_seq_stop(struct seq_file *s, void *v) -{ -} - -static int himax_self_test_seq_read(struct seq_file *s, void *v) -{ - size_t ret = 0; - - if (chip_test_r_flag) { -#if defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT) - if (g_rslt_data) - seq_printf(s, "%s", g_rslt_data); - else -#endif - seq_puts(s, "No chip test data.\n"); - } else { - himax_self_test(s, v); - } - - return ret; -} - -static const struct seq_operations himax_self_test_seq_ops = { - .start = himax_self_test_seq_start, - .next = himax_self_test_seq_next, - .stop = himax_self_test_seq_stop, - .show = himax_self_test_seq_read, -}; - -static int himax_self_test_proc_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &himax_self_test_seq_ops); -}; - -static ssize_t himax_self_test_write(struct file *filp, const char __user *buff, - size_t len, loff_t *data) -{ - char buf[80]; - - if (len >= 80) { - I("%s: no command exceeds 80 chars.\n", __func__); - return -EFAULT; - } - - if (copy_from_user(buf, buff, len)) - return -EFAULT; - - if (buf[0] == 'r') { - chip_test_r_flag = true; - I("%s: Start to read chip test data.\n", __func__); - } else { - chip_test_r_flag = false; - I("%s: Back to do self test.\n", __func__); - } - - return len; -} - -static const struct file_operations himax_proc_self_test_ops = { - .owner = THIS_MODULE, - .open = himax_self_test_proc_open, - .read = seq_read, - .write = himax_self_test_write, - .release = seq_release, -}; - -#if defined(HX_HIGH_SENSE) -static ssize_t himax_HSEN_read(struct file *file, char *buf, - size_t len, loff_t *pos) -{ - struct himax_ts_data *ts = private_ts; - size_t count = 0; - char *temp_buf = NULL; - - if (!HX_PROC_SEND_FLAG) { - temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL); - if (temp_buf != NULL) { - count = snprintf(temp_buf, PAGE_SIZE, "%d\n", - ts->HSEN_enable); - - if (copy_to_user(buf, temp_buf, len)) - I("%s, here:%d\n", __func__, __LINE__); - - kfree(temp_buf); - HX_PROC_SEND_FLAG = 1; - } else { - E("%s, Failed to allocate memory\n", __func__); - } - } else { - HX_PROC_SEND_FLAG = 0; - } - - return count; -} - -static ssize_t himax_HSEN_write(struct file *file, const char *buff, - size_t len, loff_t *pos) -{ - struct himax_ts_data *ts = private_ts; - char buf[80] = {0}; - - if (len >= 80) { - I("%s: no command exceeds 80 chars.\n", __func__); - return -EFAULT; - } - - if (copy_from_user(buf, buff, len)) - return -EFAULT; - - if (buf[0] == '0') - ts->HSEN_enable = 0; - else if (buf[0] == '1') - ts->HSEN_enable = 1; - else - return -EINVAL; - - g_core_fp.fp_set_HSEN_enable(ts->HSEN_enable, ts->suspended); - I("%s: HSEN_enable = %d.\n", __func__, ts->HSEN_enable); - return len; -} - -static const struct file_operations himax_proc_HSEN_ops = { - .owner = THIS_MODULE, - .read = himax_HSEN_read, - .write = himax_HSEN_write, -}; -#endif - -#if defined(HX_SMART_WAKEUP) -static ssize_t himax_SMWP_read(struct file *file, char *buf, - size_t len, loff_t *pos) -{ - size_t count = 0; - struct himax_ts_data *ts = private_ts; - char *temp_buf = NULL; - - if (!HX_PROC_SEND_FLAG) { - temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL); - if (temp_buf != NULL) { - count = snprintf(temp_buf, PAGE_SIZE, "%d\n", - ts->SMWP_enable); - - if (copy_to_user(buf, temp_buf, len)) - I("%s, here:%d\n", __func__, __LINE__); - - kfree(temp_buf); - HX_PROC_SEND_FLAG = 1; - } else { - E("%s, Failed to allocate memory\n", __func__); - } - } else { - HX_PROC_SEND_FLAG = 0; - } - - return count; -} - -static ssize_t himax_SMWP_write(struct file *file, const char *buff, - size_t len, loff_t *pos) -{ - struct himax_ts_data *ts = private_ts; - char buf[80] = {0}; - - if (len >= 80) { - I("%s: no command exceeds 80 chars.\n", __func__); - return -EFAULT; - } - - if (copy_from_user(buf, buff, len)) - return -EFAULT; - - if (buf[0] == '0') - ts->SMWP_enable = 0; - else if (buf[0] == '1') - ts->SMWP_enable = 1; - else - return -EINVAL; - - g_core_fp.fp_set_SMWP_enable(ts->SMWP_enable, ts->suspended); - HX_SMWP_EN = ts->SMWP_enable; - I("%s: SMART_WAKEUP_enable = %d.\n", __func__, HX_SMWP_EN); - return len; -} - -static const struct file_operations himax_proc_SMWP_ops = { - .owner = THIS_MODULE, - .read = himax_SMWP_read, - .write = himax_SMWP_write, -}; - -static ssize_t himax_GESTURE_read(struct file *file, char *buf, - size_t len, loff_t *pos) -{ - struct himax_ts_data *ts = private_ts; - int i = 0; - size_t ret = 0; - char *temp_buf = NULL; - - if (!HX_PROC_SEND_FLAG) { - temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL); - if (temp_buf != NULL) { - for (i = 0; i < GEST_SUP_NUM; i++) - ret += snprintf(temp_buf + ret, len - ret, - "ges_en[%d]=%d\n", - i, ts->gesture_cust_en[i]); - - if (copy_to_user(buf, temp_buf, len)) - I("%s, here:%d\n", __func__, __LINE__); - - kfree(temp_buf); - HX_PROC_SEND_FLAG = 1; - } else { - E("%s, Failed to allocate memory\n", __func__); - } - } else { - HX_PROC_SEND_FLAG = 0; - ret = 0; - } - - return ret; -} - -static ssize_t himax_GESTURE_write(struct file *file, const char *buff, - size_t len, loff_t *pos) -{ - struct himax_ts_data *ts = private_ts; - int i = 0; - int j = 0; - char buf[80] = {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("himax_GESTURE_store= %s, len = %d\n", buf, (int)len); - - for (i = 0; i < len; i++) { - if (buf[i] == '0' && j < GEST_SUP_NUM) { - ts->gesture_cust_en[j] = 0; - I("gesture en[%d]=%d\n", j, ts->gesture_cust_en[j]); - j++; - } else if (buf[i] == '1' && j < GEST_SUP_NUM) { - ts->gesture_cust_en[j] = 1; - I("gesture en[%d]=%d\n", j, ts->gesture_cust_en[j]); - j++; - } else - I("Not 0/1 or >=GEST_SUP_NUM : buf[%d] = %c\n", - i, buf[i]); - } - - return len; -} - -static const struct file_operations himax_proc_Gesture_ops = { - .owner = THIS_MODULE, - .read = himax_GESTURE_read, - .write = himax_GESTURE_write, -}; - -#if defined(HX_ULTRA_LOW_POWER) -static ssize_t himax_psensor_read(struct file *file, char *buf, - size_t len, loff_t *pos) -{ - size_t count = 0; - struct himax_ts_data *ts = private_ts; - char *temp_buf = NULL; - - if (!HX_PROC_SEND_FLAG) { - temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL); - if (temp_buf != NULL) { - count = snprintf(temp_buf, PAGE_SIZE, - "p-sensor flag = %d\n", - ts->psensor_flag); - - if (copy_to_user(buf, temp_buf, len)) - I("%s, here:%d\n", __func__, __LINE__); - - kfree(temp_buf); - HX_PROC_SEND_FLAG = 1; - } else { - E("%s, Failed to allocate memory\n", __func__); - } - } else { - HX_PROC_SEND_FLAG = 0; - } - - return count; -} - -static ssize_t himax_psensor_write(struct file *file, const char *buff, - size_t len, loff_t *pos) -{ - struct himax_ts_data *ts = private_ts; - char buf[80] = {0}; - - if (len >= 80) { - I("%s: no command exceeds 80 chars.\n", __func__); - return -EFAULT; - } - - if (copy_from_user(buf, buff, len)) - return -EFAULT; - - if (buf[0] == '0' && ts->SMWP_enable == 1) { - ts->psensor_flag = false; - g_core_fp.fp_black_gest_ctrl(false); - } else if (buf[0] == '1' && ts->SMWP_enable == 1) { - ts->psensor_flag = true; - g_core_fp.fp_black_gest_ctrl(true); - } else if (ts->SMWP_enable == 0) { - I("%s: SMWP is disable, not supprot to ctrl p-sensor.\n", - __func__); - } else - return -EINVAL; - - I("%s: psensor_flag = %d.\n", __func__, ts->psensor_flag); - return len; -} - -static const struct file_operations himax_proc_psensor_ops = { - .owner = THIS_MODULE, - .read = himax_psensor_read, - .write = himax_psensor_write, -}; -#endif -#endif - -int himax_common_proc_init(void) -{ - himax_touch_proc_dir = proc_mkdir(HIMAX_PROC_TOUCH_FOLDER, NULL); - - if (himax_touch_proc_dir == NULL) { - E(" %s: himax_touch_proc_dir file create failed!\n", __func__); - return -ENOMEM; - } -#if defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT) - if (fp_himax_self_test_init != NULL) - fp_himax_self_test_init(); -#endif - - himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE, 0444, - himax_touch_proc_dir, &himax_proc_self_test_ops); - if (himax_proc_self_test_file == NULL) { - E(" %s: proc self_test file create failed!\n", __func__); - goto fail_1; - } - -#if defined(HX_HIGH_SENSE) - himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, 0666, - himax_touch_proc_dir, &himax_proc_HSEN_ops); - - if (himax_proc_HSEN_file == NULL) { - E(" %s: proc HSEN file create failed!\n", __func__); - goto fail_2; - } - -#endif -#if defined(HX_SMART_WAKEUP) - himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, 0666, - himax_touch_proc_dir, &himax_proc_SMWP_ops); - - if (himax_proc_SMWP_file == NULL) { - E(" %s: proc SMWP file create failed!\n", __func__); - goto fail_3; - } - - himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, 0666, - himax_touch_proc_dir, &himax_proc_Gesture_ops); - - if (himax_proc_GESTURE_file == NULL) { - E(" %s: proc GESTURE file create failed!\n", __func__); - goto fail_4; - } -#if defined(HX_ULTRA_LOW_POWER) - himax_proc_psensor_file = proc_create(HIMAX_PROC_PSENSOR_FILE, 0666, - himax_touch_proc_dir, &himax_proc_psensor_ops); - - if (himax_proc_psensor_file == NULL) { - E(" %s: proc GESTURE file create failed!\n", __func__); - goto fail_5; - } -#endif -#endif - return 0; -#if defined(HX_SMART_WAKEUP) -#if defined(HX_ULTRA_LOW_POWER) - remove_proc_entry(HIMAX_PROC_PSENSOR_FILE, himax_touch_proc_dir); -fail_5: -#endif - remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir); -fail_4: - remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir); -fail_3: -#endif -#if defined(HX_HIGH_SENSE) - remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir); -fail_2: -#endif - remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir); -fail_1: - return -ENOMEM; -} - -void himax_common_proc_deinit(void) -{ - remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir); -#if defined(HX_HIGH_SENSE) - remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir); -#endif -#if defined(HX_SMART_WAKEUP) -#if defined(HX_ULTRA_LOW_POWER) - remove_proc_entry(HIMAX_PROC_PSENSOR_FILE, himax_touch_proc_dir); -#endif - remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir); - remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir); -#endif - remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL); -} - -/* File node for SMWP and HSEN - End*/ - -void himax_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len) -{ - /*I("%s: Entering!\n", __func__);*/ - - switch (len) { - case 1: - cmd[0] = addr; - /*I("%s: cmd[0] = 0x%02X\n", __func__, cmd[0]);*/ - break; - - case 2: - cmd[0] = addr % 0x100; - cmd[1] = (addr >> 8) % 0x100; - /*I("%s: cmd[0] = 0x%02X,cmd[1] = 0x%02X\n",*/ - /* __func__, cmd[0], cmd[1]);*/ - break; - - case 4: - cmd[0] = addr % 0x100; - cmd[1] = (addr >> 8) % 0x100; - cmd[2] = (addr >> 16) % 0x100; - cmd[3] = addr / 0x1000000; - /* I("%s: cmd[0] = 0x%02X,cmd[1] = 0x%02X,*/ - /*cmd[2] = 0x%02X,cmd[3] = 0x%02X\n", */ - /* __func__, cmd[0], cmd[1], cmd[2], cmd[3]);*/ - break; - - default: - E("%s: input length fault,len = %d!\n", __func__, len); - } -} -EXPORT_SYMBOL(himax_parse_assign_cmd); - -int himax_input_register(struct himax_ts_data *ts) -{ - int ret = 0; -#if defined(HX_SMART_WAKEUP) - int i = 0; -#endif - ret = himax_dev_set(ts); - - if (ret < 0) { - I("%s, input device register fail!\n", __func__); - ret = INPUT_REGISTER_FAIL; - goto input_device_fail; - } - - set_bit(EV_SYN, ts->input_dev->evbit); - set_bit(EV_ABS, ts->input_dev->evbit); - set_bit(EV_KEY, ts->input_dev->evbit); - set_bit(KEY_BACK, ts->input_dev->keybit); - set_bit(KEY_HOME, ts->input_dev->keybit); - set_bit(KEY_MENU, ts->input_dev->keybit); - set_bit(KEY_SEARCH, ts->input_dev->keybit); - -#if defined(HX_SMART_WAKEUP) - for (i = 0; i < GEST_SUP_NUM; i++) - set_bit(gest_key_def[i], ts->input_dev->keybit); -#elif defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT) || defined(HX_PALM_REPORT) - set_bit(KEY_POWER, ts->input_dev->keybit); -#endif - set_bit(BTN_TOUCH, ts->input_dev->keybit); - set_bit(KEY_APPSELECT, ts->input_dev->keybit); - set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); -#if defined(HX_PROTOCOL_A) - /*ts->input_dev->mtsize = ts->nFinger_support;*/ - input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, 3, 0, 0); -#else - set_bit(MT_TOOL_FINGER, ts->input_dev->keybit); -#if defined(HX_PROTOCOL_B_3PA) - input_mt_init_slots(ts->input_dev, ts->nFinger_support, - INPUT_MT_DIRECT); -#else - input_mt_init_slots(ts->input_dev, ts->nFinger_support); -#endif -#endif - I("input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n", - ts->pdata->abs_x_min, - ts->pdata->abs_x_max, - ts->pdata->abs_y_min, - ts->pdata->abs_y_max); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, - ts->pdata->abs_x_min, ts->pdata->abs_x_max, - ts->pdata->abs_x_fuzz, 0); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, - ts->pdata->abs_y_min, ts->pdata->abs_y_max, - ts->pdata->abs_y_fuzz, 0); - input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, - ts->pdata->abs_pressure_min, - ts->pdata->abs_pressure_max, - ts->pdata->abs_pressure_fuzz, 0); -#if !defined(HX_PROTOCOL_A) - input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, - ts->pdata->abs_pressure_min, - ts->pdata->abs_pressure_max, - ts->pdata->abs_pressure_fuzz, 0); - input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, - ts->pdata->abs_width_min, - ts->pdata->abs_width_max, - ts->pdata->abs_pressure_fuzz, 0); -#endif -/* input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0,*/ -/* ((ts->pdata->abs_pressure_max << 16)*/ -/* | ts->pdata->abs_width_max),*/ -/* 0, 0);*/ -/* input_set_abs_params(ts->input_dev, ABS_MT_POSITION,*/ -/* 0, (BIT(31)*/ -/* | (ts->pdata->abs_x_max << 16)*/ -/* | ts->pdata->abs_y_max),*/ -/* 0, 0);*/ - - if (himax_input_register_device(ts->input_dev) == 0) { - ret = NO_ERR; - } else { - E("%s: input register fail\n", __func__); - ret = INPUT_REGISTER_FAIL; - goto input_device_fail; - } - - if (!ic_data->HX_PEN_FUNC) - goto skip_pen_operation; - - set_bit(EV_SYN, ts->hx_pen_dev->evbit); - set_bit(EV_ABS, ts->hx_pen_dev->evbit); - set_bit(EV_KEY, ts->hx_pen_dev->evbit); - set_bit(BTN_TOUCH, ts->hx_pen_dev->keybit); - set_bit(INPUT_PROP_DIRECT, ts->hx_pen_dev->propbit); - - set_bit(BTN_TOOL_PEN, ts->hx_pen_dev->keybit); - set_bit(BTN_TOOL_RUBBER, ts->hx_pen_dev->keybit); - - input_set_abs_params(ts->hx_pen_dev, ABS_PRESSURE, 0, 4095, 0, 0); - input_set_abs_params(ts->hx_pen_dev, ABS_DISTANCE, 0, 1, 0, 0); - input_set_abs_params(ts->hx_pen_dev, ABS_TILT_X, -60, 60, 0, 0); - input_set_abs_params(ts->hx_pen_dev, ABS_TILT_Y, -60, 60, 0, 0); - /*input_set_capability(ts->hx_pen_dev, EV_SW, SW_PEN_INSERT);*/ - input_set_capability(ts->hx_pen_dev, EV_KEY, BTN_TOUCH); - input_set_capability(ts->hx_pen_dev, EV_KEY, BTN_STYLUS); - input_set_capability(ts->hx_pen_dev, EV_KEY, BTN_STYLUS2); - - input_set_abs_params(ts->hx_pen_dev, ABS_X, ts->pdata->abs_x_min, - ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0); - input_set_abs_params(ts->hx_pen_dev, ABS_Y, ts->pdata->abs_y_min, - ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0); - - if (himax_input_register_device(ts->hx_pen_dev) == 0) { - ret = NO_ERR; - } else { - E("%s: input register pen fail\n", __func__); - ret = INPUT_REGISTER_FAIL; - goto input_device_fail; - } - -skip_pen_operation: - - I("%s, input device registered.\n", __func__); - -input_device_fail: - return ret; -} -EXPORT_SYMBOL(himax_input_register); - -static void calcDataSize(void) -{ - struct himax_ts_data *ts_data = private_ts; - - ts_data->x_channel = ic_data->HX_RX_NUM; - ts_data->y_channel = ic_data->HX_TX_NUM; - ts_data->nFinger_support = ic_data->HX_MAX_PT; - - ts_data->coord_data_size = 4 * ts_data->nFinger_support; - ts_data->area_data_size = ((ts_data->nFinger_support / 4) - + (ts_data->nFinger_support % 4 ? 1 : 0)) * 4; - ts_data->coordInfoSize = ts_data->coord_data_size - + ts_data->area_data_size + 4; - ts_data->raw_data_frame_size = 128 - ts_data->coord_data_size - - ts_data->area_data_size - 4 - 4 - 1; - - if (ts_data->raw_data_frame_size == 0) { - E("%s: could NOT calculate!\n", __func__); - return; - } - - ts_data->raw_data_nframes = ((uint32_t)ts_data->x_channel - * ts_data->y_channel - + ts_data->x_channel - + ts_data->y_channel) - / ts_data->raw_data_frame_size - + (((uint32_t)ts_data->x_channel - * ts_data->y_channel - + ts_data->x_channel - + ts_data->y_channel) - % ts_data->raw_data_frame_size) ? 1 : 0; - - I("%s: coord_dsz:%d,area_dsz:%d,raw_data_fsz:%d,raw_data_nframes:%d", - __func__, - ts_data->coord_data_size, - ts_data->area_data_size, - ts_data->raw_data_frame_size, - ts_data->raw_data_nframes); -} - -static void calculate_point_number(void) -{ - HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4; - - if ((ic_data->HX_MAX_PT % 4) == 0) - HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4; - else - HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) + 1) * 4; -} -#if defined(HX_AUTO_UPDATE_FW) -static int himax_auto_update_check(void) -{ - int32_t ret; - - I("%s: Entering!\n", __func__); - if (g_core_fp.fp_fw_ver_bin() == 0) { - if (((ic_data->vendor_fw_ver < g_i_FW_VER) - || (ic_data->vendor_config_ver < g_i_CFG_VER))) { - I("%s: Need update\n", __func__); - ret = 0; - } else { - I("%s: Need not update!\n", __func__); - ret = 1; - } - } else { - E("%s: FW bin fail!\n", __func__); - ret = 1; - } - - return ret; -} - -static int i_get_FW(void) -{ - int ret = 0; - int result = NO_ERR; - const struct firmware *image = NULL; - - I("file name = %s\n", i_CTPM_firmware_name); - ret = request_firmware(&image, i_CTPM_firmware_name, private_ts->dev); - if (ret < 0) { -#if defined(__EMBEDDED_FW__) - image = &g_embedded_fw; - I("%s: Not find FW in userspace, use embedded FW(size:%zu)", - __func__, g_embedded_fw.size); -#else - E("%s,%d: error code = %d\n", __func__, __LINE__, ret); - return OPEN_FILE_FAIL; -#endif - } - - i_CTPM_FW_len = image->size; - i_CTPM_FW = kcalloc(i_CTPM_FW_len, sizeof(char), GFP_KERNEL); - if (i_CTPM_FW != NULL) { - memcpy(i_CTPM_FW, image->data, sizeof(char)*i_CTPM_FW_len); - } else { - E("%s, Failed to allocate memory\n", __func__); - result = MEM_ALLOC_FAIL; - } - - if (ret >= 0) - release_firmware(image); - - return result; -} -static int i_update_FW(void) -{ - int upgrade_times = 0; - int8_t ret = 0, result = 0; - - himax_int_enable(0); - -update_retry: - - if (i_CTPM_FW_len == FW_SIZE_32k) - ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k( - i_CTPM_FW, i_CTPM_FW_len, false); - else if (i_CTPM_FW_len == FW_SIZE_60k) - ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k( - i_CTPM_FW, i_CTPM_FW_len, false); - else if (i_CTPM_FW_len == FW_SIZE_64k) - ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k( - i_CTPM_FW, i_CTPM_FW_len, false); - else if (i_CTPM_FW_len == FW_SIZE_124k) - ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k( - i_CTPM_FW, i_CTPM_FW_len, false); - else if (i_CTPM_FW_len == FW_SIZE_128k) - ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k( - i_CTPM_FW, i_CTPM_FW_len, false); - - if (ret == 0) { - upgrade_times++; - E("%s: TP upgrade error, upgrade_times = %d\n", - __func__, upgrade_times); - - if (upgrade_times < 3) - goto update_retry; - else - result = -1; - - - } else { - g_core_fp.fp_read_FW_ver(); - g_core_fp.fp_touch_information(); - result = 1;/*upgrade success*/ - I("%s: TP upgrade OK\n", __func__); - } - - kfree(i_CTPM_FW); - i_CTPM_FW = NULL; - -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(true, false); -#else - g_core_fp.fp_sense_on(0x00); -#endif - himax_int_enable(1); - return result; -} -#endif -/* - *static int himax_loadSensorConfig(struct himax_i2c_platform_data *pdata) - *{ - * I("%s: initialization complete\n", __func__); - * return NO_ERR; - *} - */ -#if defined(HX_ESD_RECOVERY) -static void himax_esd_hw_reset(void) -{ -#if defined(HX_ZERO_FLASH) - int result = 0; -#endif - if (g_ts_dbg != 0) - I("%s: Entering\n", __func__); - - I("START_Himax TP: ESD - Reset\n"); - - if (private_ts->in_self_test == 1) { - I("In self test , not TP: ESD - Reset\n"); - return; - } - - /*g_core_fp.fp_esd_ic_reset();*/ -#if defined(HX_ZERO_FLASH) - I("It will update fw after esd event in zero flash mode!\n"); - result = g_core_fp.fp_0f_operation_dirly(); - if (result) { - E("Something is wrong! Skip Update with zero flash!\n"); - goto ESCAPE_0F_UPDATE; - } - g_core_fp.fp_reload_disable(0); - g_core_fp.fp_sense_on(0x00); - himax_report_all_leave_event(private_ts); - himax_int_enable(1); -ESCAPE_0F_UPDATE: -#else - g_core_fp.fp_esd_ic_reset(); -#endif - I("END_Himax TP: ESD - Reset\n"); -} -#endif - -#if defined(HX_SMART_WAKEUP) -#if defined(HX_GESTURE_TRACK) -static void gest_pt_log_coordinate(int rx, int tx) -{ - /*driver report x y with range 0 - 255 , we scale it up to x/y pixel*/ - gest_pt_x[gest_pt_cnt] = rx * (ic_data->HX_X_RES) / 255; - gest_pt_y[gest_pt_cnt] = tx * (ic_data->HX_Y_RES) / 255; -} -#endif -static int himax_wake_event_parse(struct himax_ts_data *ts, int ts_status) -{ - uint8_t *buf = wake_event_buffer; -#if defined(HX_GESTURE_TRACK) - int tmp_max_x = 0x00; - int tmp_min_x = 0xFFFF; - int tmp_max_y = 0x00; - int tmp_min_y = 0xFFFF; - int gest_len; -#endif - int i = 0, check_FC = 0, ret; - int j = 0, gesture_pos = 0, gesture_flag = 0; - - if (g_ts_dbg != 0) - I("%s: Entering!, ts_status=%d\n", __func__, ts_status); - - if (buf == NULL) { - ret = -ENOMEM; - goto END; - } - - memcpy(buf, hx_touch_data->hx_event_buf, hx_touch_data->event_size); - - for (i = 0; i < GEST_PTLG_ID_LEN; i++) { - for (j = 0; j < GEST_SUP_NUM; j++) { - if (buf[i] == gest_event[j]) { - gesture_flag = buf[i]; - gesture_pos = j; - break; - } - } - I("0x%2.2X ", buf[i]); - if (buf[i] == gesture_flag) { - check_FC++; - } else { - I("ID START at %x , value = 0x%2X skip the event\n", - i, buf[i]); - break; - } - } - - I("Himax gesture_flag= %x\n", gesture_flag); - I("Himax check_FC is %d\n", check_FC); - - if (check_FC != GEST_PTLG_ID_LEN) { - ret = 0; - goto END; - } - - if (buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1 - || buf[GEST_PTLG_ID_LEN + 1] != GEST_PTLG_HDR_ID2) { - ret = 0; - goto END; - } - -#if defined(HX_GESTURE_TRACK) - - if (buf[GEST_PTLG_ID_LEN] == GEST_PTLG_HDR_ID1 - && buf[GEST_PTLG_ID_LEN + 1] == GEST_PTLG_HDR_ID2) { - gest_len = buf[GEST_PTLG_ID_LEN + 2]; - I("gest_len = %d\n", gest_len); - i = 0; - gest_pt_cnt = 0; - I("gest doornidate start\n %s", __func__); - - while (i < (gest_len + 1) / 2) { - gest_pt_log_coordinate( - buf[GEST_PTLG_ID_LEN + 4 + i * 2], - buf[GEST_PTLG_ID_LEN + 4 + i * 2 + 1]); - i++; - I("gest_pt_x[%d]=%d,gest_pt_y[%d]=%d\n", - gest_pt_cnt, - gest_pt_x[gest_pt_cnt], - gest_pt_cnt, - gest_pt_y[gest_pt_cnt]); - gest_pt_cnt += 1; - } - - if (gest_pt_cnt) { - for (i = 0; i < gest_pt_cnt; i++) { - if (tmp_max_x < gest_pt_x[i]) - tmp_max_x = gest_pt_x[i]; - if (tmp_min_x > gest_pt_x[i]) - tmp_min_x = gest_pt_x[i]; - if (tmp_max_y < gest_pt_y[i]) - tmp_max_y = gest_pt_y[i]; - if (tmp_min_y > gest_pt_y[i]) - tmp_min_y = gest_pt_y[i]; - } - - I("gest_point x_min=%d,x_max=%d,y_min=%d,y_max=%d\n", - tmp_min_x, tmp_max_x, tmp_min_y, tmp_max_y); - - gest_start_x = gest_pt_x[0]; - hx_gesture_coor[0] = gest_start_x; - gest_start_y = gest_pt_y[0]; - hx_gesture_coor[1] = gest_start_y; - gest_end_x = gest_pt_x[gest_pt_cnt - 1]; - hx_gesture_coor[2] = gest_end_x; - gest_end_y = gest_pt_y[gest_pt_cnt - 1]; - hx_gesture_coor[3] = gest_end_y; - gest_width = tmp_max_x - tmp_min_x; - hx_gesture_coor[4] = gest_width; - gest_height = tmp_max_y - tmp_min_y; - hx_gesture_coor[5] = gest_height; - gest_mid_x = (tmp_max_x + tmp_min_x) / 2; - hx_gesture_coor[6] = gest_mid_x; - gest_mid_y = (tmp_max_y + tmp_min_y) / 2; - hx_gesture_coor[7] = gest_mid_y; - /*gest_up_x*/ - hx_gesture_coor[8] = gest_mid_x; - /*gest_up_y*/ - hx_gesture_coor[9] = gest_mid_y - gest_height / 2; - /*gest_down_x*/ - hx_gesture_coor[10] = gest_mid_x; - /*gest_down_y*/ - hx_gesture_coor[11] = gest_mid_y + gest_height / 2; - /*gest_left_x*/ - hx_gesture_coor[12] = gest_mid_x - gest_width / 2; - /*gest_left_y*/ - hx_gesture_coor[13] = gest_mid_y; - /*gest_right_x*/ - hx_gesture_coor[14] = gest_mid_x + gest_width / 2; - /*gest_right_y*/ - hx_gesture_coor[15] = gest_mid_y; - } - } - -#endif - - if (!ts->gesture_cust_en[gesture_pos]) { - I("%s NOT report key [%d] = %d\n", __func__, - gesture_pos, gest_key_def[gesture_pos]); - g_target_report_data->SMWP_event_chk = 0; - ret = 0; - } else { - g_target_report_data->SMWP_event_chk = - gest_key_def[gesture_pos]; - ret = gesture_pos; - } -END: - return ret; -} - -static void himax_wake_event_report(void) -{ - int KEY_EVENT = g_target_report_data->SMWP_event_chk; - - if (g_ts_dbg != 0) - I("%s: Entering!\n", __func__); - - if (KEY_EVENT) { - I("%s SMART WAKEUP KEY event %d press\n", __func__, KEY_EVENT); - input_report_key(private_ts->input_dev, KEY_EVENT, 1); - input_sync(private_ts->input_dev); - I("%s SMART WAKEUP KEY event %d release\n", - __func__, KEY_EVENT); - input_report_key(private_ts->input_dev, KEY_EVENT, 0); - input_sync(private_ts->input_dev); -#if defined(HX_GESTURE_TRACK) - I("gest_start_x=%d,start_y=%d,end_x=%d,end_y=%d\n", - gest_start_x, - gest_start_y, - gest_end_x, - gest_end_y); - I("gest_width=%d,height=%d,mid_x=%d,mid_y=%d\n", - gest_width, - gest_height, - gest_mid_x, - gest_mid_y); - I("gest_up_x=%d,up_y=%d,down_x=%d,down_y=%d\n", - hx_gesture_coor[8], - hx_gesture_coor[9], - hx_gesture_coor[10], - hx_gesture_coor[11]); - I("gest_left_x=%d,left_y=%d,right_x=%d,right_y=%d\n", - hx_gesture_coor[12], - hx_gesture_coor[13], - hx_gesture_coor[14], - hx_gesture_coor[15]); -#endif - g_target_report_data->SMWP_event_chk = 0; - } -} - -#endif - -int himax_report_data_init(void) -{ - if (hx_touch_data->hx_coord_buf != NULL) { - kfree(hx_touch_data->hx_coord_buf); - hx_touch_data->hx_coord_buf = NULL; - } - - if (hx_touch_data->hx_rawdata_buf != NULL) { - kfree(hx_touch_data->hx_rawdata_buf); - hx_touch_data->hx_rawdata_buf = NULL; - } - -#if defined(HX_SMART_WAKEUP) - hx_touch_data->event_size = g_core_fp.fp_get_touch_data_size(); - - if (hx_touch_data->hx_event_buf != NULL) { - kfree(hx_touch_data->hx_event_buf); - hx_touch_data->hx_event_buf = NULL; - } - - if (wake_event_buffer != NULL) { - kfree(wake_event_buffer); - wake_event_buffer = NULL; - } - -#endif - hx_touch_data->touch_all_size = g_core_fp.fp_get_touch_data_size(); - hx_touch_data->raw_cnt_max = ic_data->HX_MAX_PT / 4; - hx_touch_data->raw_cnt_rmd = ic_data->HX_MAX_PT % 4; - /* more than 4 fingers */ - if (hx_touch_data->raw_cnt_rmd != 0x00) { - hx_touch_data->rawdata_size = - g_core_fp.fp_cal_data_len( - hx_touch_data->raw_cnt_rmd, - ic_data->HX_MAX_PT, - hx_touch_data->raw_cnt_max); - - hx_touch_data->touch_info_size = (ic_data->HX_MAX_PT - + hx_touch_data->raw_cnt_max + 2) * 4; - } else { /* less than 4 fingers */ - hx_touch_data->rawdata_size = - g_core_fp.fp_cal_data_len( - hx_touch_data->raw_cnt_rmd, - ic_data->HX_MAX_PT, - hx_touch_data->raw_cnt_max); - - hx_touch_data->touch_info_size = (ic_data->HX_MAX_PT - + hx_touch_data->raw_cnt_max + 1) * 4; - } - - if (ic_data->HX_PEN_FUNC) { - hx_touch_data->touch_info_size += PEN_INFO_SZ; - hx_touch_data->rawdata_size -= PEN_INFO_SZ; - } - - if ((ic_data->HX_TX_NUM - * ic_data->HX_RX_NUM - + ic_data->HX_TX_NUM - + ic_data->HX_RX_NUM) - % hx_touch_data->rawdata_size == 0) - hx_touch_data->rawdata_frame_size = - (ic_data->HX_TX_NUM - * ic_data->HX_RX_NUM - + ic_data->HX_TX_NUM - + ic_data->HX_RX_NUM) - / hx_touch_data->rawdata_size; - else - hx_touch_data->rawdata_frame_size = - (ic_data->HX_TX_NUM - * ic_data->HX_RX_NUM - + ic_data->HX_TX_NUM - + ic_data->HX_RX_NUM) - / hx_touch_data->rawdata_size - + 1; - - I("%s:rawdata_fsz = %d,HX_MAX_PT:%d,hx_raw_cnt_max:%d\n", - __func__, - hx_touch_data->rawdata_frame_size, - ic_data->HX_MAX_PT, - hx_touch_data->raw_cnt_max); - I("%s:hx_raw_cnt_rmd:%d,g_hx_rawdata_size:%d,touch_info_size:%d\n", - __func__, - hx_touch_data->raw_cnt_rmd, - hx_touch_data->rawdata_size, - hx_touch_data->touch_info_size); - - hx_touch_data->hx_coord_buf = kzalloc(sizeof(uint8_t) - * (hx_touch_data->touch_info_size), - GFP_KERNEL); - - if (hx_touch_data->hx_coord_buf == NULL) - goto mem_alloc_fail_coord_buf; - -#if defined(HX_SMART_WAKEUP) - wake_event_buffer = kcalloc(hx_touch_data->event_size, - sizeof(uint8_t), GFP_KERNEL); - if (wake_event_buffer == NULL) - goto mem_alloc_fail_smwp; - - hx_touch_data->hx_event_buf = kzalloc(sizeof(uint8_t) - * (hx_touch_data->event_size), GFP_KERNEL); - if (hx_touch_data->hx_event_buf == NULL) - goto mem_alloc_fail_event_buf; -#endif - - hx_touch_data->hx_rawdata_buf = kzalloc(sizeof(uint8_t) - * (hx_touch_data->touch_all_size - - hx_touch_data->touch_info_size), - GFP_KERNEL); - if (hx_touch_data->hx_rawdata_buf == NULL) - goto mem_alloc_fail_rawdata_buf; - - if (g_target_report_data == NULL) { - g_target_report_data = - kzalloc(sizeof(struct himax_target_report_data), - GFP_KERNEL); - if (g_target_report_data == NULL) - goto mem_alloc_fail_report_data; -/* - *#if defined(HX_SMART_WAKEUP) - * g_target_report_data->SMWP_event_chk = 0; - *#endif - * I("%s: SMWP_event_chk = %d\n", __func__, - * g_target_report_data->SMWP_event_chk); - */ - g_target_report_data->x = kzalloc(sizeof(int) - * (ic_data->HX_MAX_PT), GFP_KERNEL); - if (g_target_report_data->x == NULL) - goto mem_alloc_fail_report_data_x; - - g_target_report_data->y = kzalloc(sizeof(int) - * (ic_data->HX_MAX_PT), GFP_KERNEL); - if (g_target_report_data->y == NULL) - goto mem_alloc_fail_report_data_y; - - g_target_report_data->w = kzalloc(sizeof(int) - * (ic_data->HX_MAX_PT), GFP_KERNEL); - if (g_target_report_data->w == NULL) - goto mem_alloc_fail_report_data_w; - - g_target_report_data->finger_id = kzalloc(sizeof(int) - * (ic_data->HX_MAX_PT), GFP_KERNEL); - if (g_target_report_data->finger_id == NULL) - goto mem_alloc_fail_report_data_fid; - - if (!ic_data->HX_PEN_FUNC) - goto skip_pen_operation; - - g_target_report_data->p_x = kzalloc(sizeof(int)*2, GFP_KERNEL); - if (g_target_report_data->p_x == NULL) - goto mem_alloc_fail_report_data_px; - - g_target_report_data->p_y = kzalloc(sizeof(int)*2, GFP_KERNEL); - if (g_target_report_data->p_y == NULL) - goto mem_alloc_fail_report_data_py; - - g_target_report_data->p_w = kzalloc(sizeof(int)*2, GFP_KERNEL); - if (g_target_report_data->p_w == NULL) - goto mem_alloc_fail_report_data_pw; - - g_target_report_data->pen_id = kzalloc(sizeof(int)*2, - GFP_KERNEL); - if (g_target_report_data->pen_id == NULL) - goto mem_alloc_fail_report_data_pid; - - g_target_report_data->p_hover = kzalloc(sizeof(int)*2, - GFP_KERNEL); - if (g_target_report_data->p_hover == NULL) - goto mem_alloc_fail_report_data_ph; - - g_target_report_data->p_tilt_x = kzalloc(sizeof(int)*2, - GFP_KERNEL); - if (g_target_report_data->p_tilt_x == NULL) - goto mem_alloc_fail_report_data_ptx; - - g_target_report_data->p_btn = kzalloc(sizeof(int)*2, - GFP_KERNEL); - if (g_target_report_data->p_btn == NULL) - goto mem_alloc_fail_report_data_pb; - - g_target_report_data->p_btn2 = kzalloc(sizeof(int)*2, - GFP_KERNEL); - if (g_target_report_data->p_btn2 == NULL) - goto mem_alloc_fail_report_data_pb2; - - g_target_report_data->p_tilt_y = kzalloc(sizeof(int)*2, - GFP_KERNEL); - if (g_target_report_data->p_tilt_y == NULL) - goto mem_alloc_fail_report_data_pty; - - g_target_report_data->p_on = kzalloc(sizeof(int)*2, GFP_KERNEL); - if (g_target_report_data->p_on == NULL) - goto mem_alloc_fail_report_data_pon; - } - -skip_pen_operation: - - return NO_ERR; - -mem_alloc_fail_report_data_pon: - kfree(g_target_report_data->p_tilt_y); - g_target_report_data->p_tilt_y = NULL; -mem_alloc_fail_report_data_pty: - kfree(g_target_report_data->p_btn2); - g_target_report_data->p_btn2 = NULL; -mem_alloc_fail_report_data_pb2: - kfree(g_target_report_data->p_btn); - g_target_report_data->p_btn = NULL; -mem_alloc_fail_report_data_pb: - kfree(g_target_report_data->p_tilt_x); - g_target_report_data->p_tilt_x = NULL; -mem_alloc_fail_report_data_ptx: - kfree(g_target_report_data->p_hover); - g_target_report_data->p_hover = NULL; -mem_alloc_fail_report_data_ph: - kfree(g_target_report_data->pen_id); - g_target_report_data->pen_id = NULL; -mem_alloc_fail_report_data_pid: - kfree(g_target_report_data->p_w); - g_target_report_data->p_w = NULL; -mem_alloc_fail_report_data_pw: - kfree(g_target_report_data->p_y); - g_target_report_data->p_y = NULL; -mem_alloc_fail_report_data_py: - kfree(g_target_report_data->p_x); - g_target_report_data->p_x = NULL; -mem_alloc_fail_report_data_px: - - kfree(g_target_report_data->finger_id); - g_target_report_data->finger_id = NULL; -mem_alloc_fail_report_data_fid: - kfree(g_target_report_data->w); - g_target_report_data->w = NULL; -mem_alloc_fail_report_data_w: - kfree(g_target_report_data->y); - g_target_report_data->y = NULL; -mem_alloc_fail_report_data_y: - kfree(g_target_report_data->x); - g_target_report_data->x = NULL; -mem_alloc_fail_report_data_x: - kfree(g_target_report_data); - g_target_report_data = NULL; -mem_alloc_fail_report_data: - kfree(hx_touch_data->hx_rawdata_buf); - hx_touch_data->hx_rawdata_buf = NULL; -mem_alloc_fail_rawdata_buf: -#if defined(HX_SMART_WAKEUP) - kfree(hx_touch_data->hx_event_buf); - hx_touch_data->hx_event_buf = NULL; -mem_alloc_fail_event_buf: - kfree(wake_event_buffer); - wake_event_buffer = NULL; -mem_alloc_fail_smwp: -#endif - kfree(hx_touch_data->hx_coord_buf); - hx_touch_data->hx_coord_buf = NULL; -mem_alloc_fail_coord_buf: - - E("%s: Failed to allocate memory\n", __func__); - return MEM_ALLOC_FAIL; -} -EXPORT_SYMBOL(himax_report_data_init); - -void himax_report_data_deinit(void) -{ - if (ic_data->HX_PEN_FUNC) { - kfree(g_target_report_data->p_on); - g_target_report_data->p_on = NULL; - kfree(g_target_report_data->p_tilt_y); - g_target_report_data->p_tilt_y = NULL; - kfree(g_target_report_data->p_btn2); - g_target_report_data->p_btn2 = NULL; - kfree(g_target_report_data->p_btn); - g_target_report_data->p_btn = NULL; - kfree(g_target_report_data->p_tilt_x); - g_target_report_data->p_tilt_x = NULL; - kfree(g_target_report_data->p_hover); - g_target_report_data->p_hover = NULL; - kfree(g_target_report_data->pen_id); - g_target_report_data->pen_id = NULL; - kfree(g_target_report_data->p_w); - g_target_report_data->p_w = NULL; - kfree(g_target_report_data->p_y); - g_target_report_data->p_y = NULL; - kfree(g_target_report_data->p_x); - g_target_report_data->p_x = NULL; - } - - kfree(g_target_report_data->finger_id); - g_target_report_data->finger_id = NULL; - kfree(g_target_report_data->w); - g_target_report_data->w = NULL; - kfree(g_target_report_data->y); - g_target_report_data->y = NULL; - kfree(g_target_report_data->x); - g_target_report_data->x = NULL; - kfree(g_target_report_data); - g_target_report_data = NULL; - -#if defined(HX_SMART_WAKEUP) - kfree(wake_event_buffer); - wake_event_buffer = NULL; - kfree(hx_touch_data->hx_event_buf); - hx_touch_data->hx_event_buf = NULL; -#endif - kfree(hx_touch_data->hx_rawdata_buf); - hx_touch_data->hx_rawdata_buf = NULL; - kfree(hx_touch_data->hx_coord_buf); - hx_touch_data->hx_coord_buf = NULL; -} - -/*start ts_work*/ -#if defined(HX_USB_DETECT_GLOBAL) -void himax_cable_detect_func(bool force_renew) -{ - struct himax_ts_data *ts; - - /*u32 connect_status = 0;*/ - uint8_t connect_status = 0; - - connect_status = USB_detect_flag;/* upmu_is_chr_det(); */ - ts = private_ts; - - /* I("Touch: cable status=%d, cable_config=%p, usb_connected=%d\n",*/ - /* connect_status, ts->cable_config, ts->usb_connected); */ - if (ts->cable_config) { - if ((connect_status != ts->usb_connected) || force_renew) { - if (connect_status) { - ts->cable_config[1] = 0x01; - ts->usb_connected = 0x01; - } else { - ts->cable_config[1] = 0x00; - ts->usb_connected = 0x00; - } - - g_core_fp.fp_usb_detect_set(ts->cable_config); - I("%s: Cable status change: 0x%2.2X\n", __func__, - ts->usb_connected); - } - - /*else*/ - /* I("%s: Cable status is the same as*/ - /* previous one, ignore.\n", __func__);*/ - } -} -#endif - -static int himax_ts_work_status(struct himax_ts_data *ts) -{ - /* 1: normal, 2:SMWP */ - int result = HX_REPORT_COORD; - - hx_touch_data->diag_cmd = ts->diag_cmd; - if (hx_touch_data->diag_cmd) - result = HX_REPORT_COORD_RAWDATA; - -#if defined(HX_SMART_WAKEUP) - if (atomic_read(&ts->suspend_mode) - && (ts->SMWP_enable) - && (!hx_touch_data->diag_cmd)) - result = HX_REPORT_SMWP_EVENT; -#endif - /* I("Now Status is %d\n", result); */ - return result; -} - -static int himax_touch_get(struct himax_ts_data *ts, uint8_t *buf, - int ts_path, int ts_status) -{ - if (g_ts_dbg != 0) - I("%s: Entering, ts_status=%d!\n", __func__, ts_status); - - switch (ts_path) { - /*normal*/ - case HX_REPORT_COORD: - if ((HX_HW_RESET_ACTIVATE) -#if defined(HX_ESD_RECOVERY) - || (HX_ESD_RESET_ACTIVATE) -#endif - ) { - if (!g_core_fp.fp_read_event_stack(buf, 128)) { - E("%s: can't read data from chip!\n", __func__); - ts_status = HX_TS_GET_DATA_FAIL; - } - } else { - if (!g_core_fp.fp_read_event_stack(buf, - hx_touch_data->touch_info_size)) { - E("%s: can't read data from chip!\n", __func__); - ts_status = HX_TS_GET_DATA_FAIL; - } - } - break; -#if defined(HX_SMART_WAKEUP) - - /*SMWP*/ - case HX_REPORT_SMWP_EVENT: - __pm_wakeup_event(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT); - msleep(20); - g_core_fp.fp_burst_enable(0); - - if (!g_core_fp.fp_read_event_stack(buf, - hx_touch_data->event_size)) { - E("%s: can't read data from chip!\n", __func__); - ts_status = HX_TS_GET_DATA_FAIL; - } - break; -#endif - case HX_REPORT_COORD_RAWDATA: - if (!g_core_fp.fp_read_event_stack(buf, 128)) { - E("%s: can't read data from chip!\n", __func__); - ts_status = HX_TS_GET_DATA_FAIL; - } - break; - default: - break; - } - - return ts_status; -} - -/* start error_control*/ -static int himax_checksum_cal(struct himax_ts_data *ts, uint8_t *buf, - int ts_path, int ts_status) -{ - uint16_t check_sum_cal = 0; - int32_t i = 0; - int length = 0; - int zero_cnt = 0; - int raw_data_sel = 0; - int ret_val = ts_status; - - if (g_ts_dbg != 0) - I("%s: Entering, ts_status=%d!\n", __func__, ts_status); - - /* Normal */ - switch (ts_path) { - case HX_REPORT_COORD: - length = hx_touch_data->touch_info_size; - break; -#if defined(HX_SMART_WAKEUP) -/* SMWP */ - case HX_REPORT_SMWP_EVENT: - length = (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN); - break; -#endif - case HX_REPORT_COORD_RAWDATA: - length = hx_touch_data->touch_info_size; - break; - default: - I("%s, Neither Normal Nor SMWP error!\n", __func__); - ret_val = HX_PATH_FAIL; - goto END_FUNCTION; - } - - for (i = 0; i < length; i++) { - check_sum_cal += buf[i]; - if (buf[i] == 0x00) - zero_cnt++; - } - - if (check_sum_cal % 0x100 != 0) { - I("point data_checksum not match check_sum_cal: 0x%02X", - check_sum_cal); - ret_val = HX_CHKSUM_FAIL; - } else if (zero_cnt == length) { - if (ts->use_irq) - I("[HIMAX TP MSG] All Zero event\n"); - - ret_val = HX_CHKSUM_FAIL; - } else { - raw_data_sel = buf[HX_TOUCH_INFO_POINT_CNT]>>4 & 0x0F; - /*I("%s:raw_out_sel=%x , hx_touch_data->diag_cmd=%x.\n",*/ - /* __func__, raw_data_sel,*/ - /* hx_touch_data->diag_cmd);*/ - /*raw data out not match skip it*/ - if ((raw_data_sel != 0x0F) - && (raw_data_sel != hx_touch_data->diag_cmd)) { - /*I("%s:raw data out not match.\n", __func__);*/ - if (!hx_touch_data->diag_cmd) { - /*Need to clear event stack here*/ - g_core_fp.fp_read_event_stack(buf, - (128-hx_touch_data->touch_info_size)); - /*I("%s: size =%d, buf[0]=%x ,buf[1]=%x,*/ - /* buf[2]=%x, buf[3]=%x.\n",*/ - /* __func__,*/ - /* (128-hx_touch_data->touch_info_size),*/ - /* buf[0], buf[1], buf[2], buf[3]);*/ - /*I("%s:also clear event stack.\n", __func__);*/ - } - ret_val = HX_READY_SERVE; - } - } - -END_FUNCTION: - if (g_ts_dbg != 0) - I("%s: END, ret_val=%d!\n", __func__, ret_val); - return ret_val; -} - -#if defined(HX_ESD_RECOVERY) -#if defined(HX_ZERO_FLASH) -void hx_update_dirly_0f(void) -{ - I("It will update fw after esd event in zero flash mode!\n"); - g_core_fp.fp_0f_operation_dirly(); -} -#endif -static int himax_ts_event_check(struct himax_ts_data *ts, - uint8_t *buf, int ts_path, int ts_status) -{ - int hx_EB_event = 0; - int hx_EC_event = 0; - int hx_ED_event = 0; - int hx_esd_event = 0; - int hx_zero_event = 0; - int shaking_ret = 0; - - int32_t loop_i = 0; - int length = 0; - int ret_val = ts_status; - - if (g_ts_dbg != 0) - I("%s: Entering, ts_status=%d!\n", __func__, ts_status); - - /* Normal */ - switch (ts_path) { - case HX_REPORT_COORD: - length = hx_touch_data->touch_info_size; - break; -#if defined(HX_SMART_WAKEUP) -/* SMWP */ - case HX_REPORT_SMWP_EVENT: - length = (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN); - break; -#endif - case HX_REPORT_COORD_RAWDATA: - length = hx_touch_data->touch_info_size; - break; - default: - I("%s, Neither Normal Nor SMWP error!\n", __func__); - ret_val = HX_PATH_FAIL; - goto END_FUNCTION; - } - - if (g_ts_dbg != 0) - I("Now Path=%d, Now status=%d, length=%d\n", - ts_path, ts_status, length); - - for (loop_i = 0; loop_i < length; loop_i++) { - if (ts_path == HX_REPORT_COORD - || ts_path == HX_REPORT_COORD_RAWDATA) { - /* case 1 ESD recovery flow */ - if (buf[loop_i] == 0xEB) { - hx_EB_event++; - } else if (buf[loop_i] == 0xEC) { - hx_EC_event++; - } else if (buf[loop_i] == 0xED) { - hx_ED_event++; - - /* case 2 ESD recovery flow-Disable */ - } else if (buf[loop_i] == 0x00) { - hx_zero_event++; - } else { - hx_EB_event = 0; - hx_EC_event = 0; - hx_ED_event = 0; - hx_zero_event = 0; - g_zero_event_count = 0; - } - } - } - - if (hx_EB_event == length) { - hx_esd_event = length; - hx_EB_event_flag++; - I("[HIMAX TP MSG]: ESD event checked - ALL 0xEB.\n"); - } else if (hx_EC_event == length) { - hx_esd_event = length; - hx_EC_event_flag++; - I("[HIMAX TP MSG]: ESD event checked - ALL 0xEC.\n"); - } else if (hx_ED_event == length) { - hx_esd_event = length; - hx_ED_event_flag++; - I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n"); - } -/*#if defined(HX_ZERO_FLASH) - * //This is for previous version(a, b) because HW pull TSIX - * low continuely after watchdog timeout reset - * else if (hx_zero_event == length) { - * //check zero flash status - * if (g_core_fp.fp_0f_esd_check() < 0) { - * g_zero_event_count = 6; - * I("[HIMAX TP MSG]: ESD event checked - - ALL Zero in ZF.\n"); - * } else { - * I("[HIMAX TP MSG]: Status check pass in ZF.\n"); - * } - * } - *#endif - */ - else - hx_esd_event = 0; - - if ((hx_esd_event == length || hx_zero_event == length) - && (HX_HW_RESET_ACTIVATE == 0) - && (HX_ESD_RESET_ACTIVATE == 0) - && (hx_touch_data->diag_cmd == 0) - && (ts->in_self_test == 0)) { - shaking_ret = g_core_fp.fp_ic_esd_recovery(hx_esd_event, - hx_zero_event, length); - - if (shaking_ret == HX_ESD_EVENT) { - himax_esd_hw_reset(); - ret_val = HX_ESD_EVENT; - } else if (shaking_ret == HX_ZERO_EVENT_COUNT) { - ret_val = HX_ZERO_EVENT_COUNT; - } else { - I("I2C running. Nothing to be done!\n"); - ret_val = HX_IC_RUNNING; - } - - /* drop 1st interrupts after chip reset */ - } else if (HX_ESD_RESET_ACTIVATE) { - HX_ESD_RESET_ACTIVATE = 0; - I("[HX_ESD_RESET_ACTIVATE]%s:Back from reset,ready to serve.\n", - __func__); - ret_val = HX_ESD_REC_OK; - } - -END_FUNCTION: - if (g_ts_dbg != 0) - I("%s: END, ret_val=%d!\n", __func__, ret_val); - - return ret_val; -} -#endif - -static int himax_err_ctrl(struct himax_ts_data *ts, - uint8_t *buf, int ts_path, int ts_status) -{ -#if defined(HX_RST_PIN_FUNC) - if (HX_HW_RESET_ACTIVATE) { - /* drop 1st interrupts after chip reset */ - HX_HW_RESET_ACTIVATE = 0; - I("[HX_HW_RESET_ACTIVATE]%s:Back from reset,ready to serve.\n", - __func__); - ts_status = HX_RST_OK; - goto END_FUNCTION; - } -#endif - - ts_status = himax_checksum_cal(ts, buf, ts_path, ts_status); - if (ts_status == HX_CHKSUM_FAIL) { - goto CHK_FAIL; - } else { -#if defined(HX_ESD_RECOVERY) - /* continuous N times record, not total N times. */ - g_zero_event_count = 0; -#endif - goto END_FUNCTION; - } - -CHK_FAIL: -#if defined(HX_ESD_RECOVERY) - ts_status = himax_ts_event_check(ts, buf, ts_path, ts_status); -#endif - -END_FUNCTION: - if (g_ts_dbg != 0) - I("%s: END, ts_status=%d!\n", __func__, ts_status); - return ts_status; -} -/* end error_control*/ - -/* start distribute_data*/ -static int himax_distribute_touch_data(uint8_t *buf, - int ts_path, int ts_status) -{ - uint8_t hx_state_info_pos = hx_touch_data->touch_info_size - 3; - - if (ic_data->HX_PEN_FUNC) - hx_state_info_pos -= PEN_INFO_SZ; - - if (g_ts_dbg != 0) - I("%s: Entering, ts_status=%d!\n", __func__, ts_status); - - if (ts_path == HX_REPORT_COORD) { - memcpy(hx_touch_data->hx_coord_buf, &buf[0], - hx_touch_data->touch_info_size); - - if (buf[hx_state_info_pos] != 0xFF - && buf[hx_state_info_pos + 1] != 0xFF) - memcpy(hx_touch_data->hx_state_info, - &buf[hx_state_info_pos], 2); - else - memset(hx_touch_data->hx_state_info, 0x00, - sizeof(hx_touch_data->hx_state_info)); - - if ((HX_HW_RESET_ACTIVATE) -#if defined(HX_ESD_RECOVERY) - || (HX_ESD_RESET_ACTIVATE) -#endif - ) { - memcpy(hx_touch_data->hx_rawdata_buf, - &buf[hx_touch_data->touch_info_size], - hx_touch_data->touch_all_size - - hx_touch_data->touch_info_size); - } - } else if (ts_path == HX_REPORT_COORD_RAWDATA) { - memcpy(hx_touch_data->hx_coord_buf, &buf[0], - hx_touch_data->touch_info_size); - - if (buf[hx_state_info_pos] != 0xFF - && buf[hx_state_info_pos + 1] != 0xFF) - memcpy(hx_touch_data->hx_state_info, - &buf[hx_state_info_pos], 2); - else - memset(hx_touch_data->hx_state_info, 0x00, - sizeof(hx_touch_data->hx_state_info)); - - memcpy(hx_touch_data->hx_rawdata_buf, - &buf[hx_touch_data->touch_info_size], - hx_touch_data->touch_all_size - - hx_touch_data->touch_info_size); -#if defined(HX_SMART_WAKEUP) - } else if (ts_path == HX_REPORT_SMWP_EVENT) { - memcpy(hx_touch_data->hx_event_buf, buf, - hx_touch_data->event_size); -#endif - } else { - E("%s, Fail Path!\n", __func__); - ts_status = HX_PATH_FAIL; - } - - if (g_ts_dbg != 0) - I("%s: End, ts_status=%d!\n", __func__, ts_status); - return ts_status; -} -/* end assign_data*/ - -/* start parse_report_data*/ -int himax_parse_report_points(struct himax_ts_data *ts, - int ts_path, int ts_status) -{ - int x = 0, y = 0, w = 0; - - uint8_t p_hover = 0, p_btn = 0, p_btn2 = 0; - int8_t p_tilt_x = 0, p_tilt_y = 0; - int p_x = 0, p_y = 0, p_w = 0; - static uint8_t p_p_on; - - int base = 0; - int32_t loop_i = 0; - - if (g_ts_dbg != 0) - I("%s: start!\n", __func__); - - - if (!ic_data->HX_PEN_FUNC) - goto skip_pen_operation; - - p_p_on = 0; - base = hx_touch_data->touch_info_size - PEN_INFO_SZ; - - p_x = hx_touch_data->hx_coord_buf[base] << 8 - | hx_touch_data->hx_coord_buf[base + 1]; - p_y = (hx_touch_data->hx_coord_buf[base + 2] << 8 - | hx_touch_data->hx_coord_buf[base + 3]); - p_w = (hx_touch_data->hx_coord_buf[base + 4] << 8 - | hx_touch_data->hx_coord_buf[base + 5]); - p_tilt_x = (int8_t)hx_touch_data->hx_coord_buf[base + 6]; - p_hover = hx_touch_data->hx_coord_buf[base + 7]; - p_btn = hx_touch_data->hx_coord_buf[base + 8]; - p_btn2 = hx_touch_data->hx_coord_buf[base + 9]; - p_tilt_y = (int8_t)hx_touch_data->hx_coord_buf[base + 10]; - - if (g_ts_dbg != 0) { - D("%s: p_x=%d, p_y=%d, p_w=%d,p_tilt_x=%d, p_hover=%d\n", - __func__, p_x, p_y, p_w, p_tilt_x, p_hover); - D("%s: p_btn=%d, p_btn2=%d, p_tilt_y=%d\n", - __func__, p_btn, p_btn2, p_tilt_y); - } - - if (p_x >= 0 - && p_x <= ts->pdata->abs_x_max - && p_y >= 0 - && p_y <= ts->pdata->abs_y_max) { - g_target_report_data->p_x[0] = p_x; - g_target_report_data->p_y[0] = p_y; - g_target_report_data->p_w[0] = p_w; - g_target_report_data->p_hover[0] = p_hover; - g_target_report_data->pen_id[0] = 1; - g_target_report_data->p_btn[0] = p_btn; - g_target_report_data->p_btn2[0] = p_btn2; - g_target_report_data->p_tilt_x[0] = p_tilt_x; - g_target_report_data->p_tilt_y[0] = p_tilt_y; - g_target_report_data->p_on[0] = 1; - ts->hx_point_num++; - } else {/* report coordinates */ - g_target_report_data->p_x[0] = 0; - g_target_report_data->p_y[0] = 0; - g_target_report_data->p_w[0] = 0; - g_target_report_data->p_hover[0] = 0; - g_target_report_data->pen_id[0] = 0; - g_target_report_data->p_btn[0] = 0; - g_target_report_data->p_btn2[0] = 0; - g_target_report_data->p_tilt_x[0] = 0; - g_target_report_data->p_tilt_y[0] = 0; - g_target_report_data->p_on[0] = 0; - } - - if (g_ts_dbg != 0) { - if (p_p_on != g_target_report_data->p_on[0]) { - I("p_on[0] = %d, hx_point_num=%d\n", - g_target_report_data->p_on[0], - ts->hx_point_num); - p_p_on = g_target_report_data->p_on[0]; - } - } -skip_pen_operation: - - ts->old_finger = ts->pre_finger_mask; - if (ts->hx_point_num == 0) { - if (g_ts_dbg != 0) - I("%s: hx_point_num = 0!\n", __func__); - return ts_status; - } - ts->pre_finger_mask = 0; - hx_touch_data->finger_num = - hx_touch_data->hx_coord_buf[ts->coordInfoSize - 4] - & 0x0F; - hx_touch_data->finger_on = 1; - AA_press = 1; - - g_target_report_data->finger_num = hx_touch_data->finger_num; - g_target_report_data->finger_on = hx_touch_data->finger_on; - g_target_report_data->ig_count = - hx_touch_data->hx_coord_buf[ts->coordInfoSize - 5]; - - if (g_ts_dbg != 0) - I("%s:finger_num = 0x%2X, finger_on = %d\n", __func__, - g_target_report_data->finger_num, - g_target_report_data->finger_on); - - for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { - base = loop_i * 4; - x = hx_touch_data->hx_coord_buf[base] << 8 - | hx_touch_data->hx_coord_buf[base + 1]; - y = (hx_touch_data->hx_coord_buf[base + 2] << 8 - | hx_touch_data->hx_coord_buf[base + 3]); - w = hx_touch_data->hx_coord_buf[(ts->nFinger_support * 4) - + loop_i]; - - if (g_ts_dbg != 0) - D("%s: now parsing[%d]:x=%d, y=%d, w=%d\n", __func__, - loop_i, x, y, w); - - if (x >= 0 - && x <= ts->pdata->abs_x_max - && y >= 0 - && y <= ts->pdata->abs_y_max) { - hx_touch_data->finger_num--; - - g_target_report_data->x[loop_i] = x; - g_target_report_data->y[loop_i] = y; - g_target_report_data->w[loop_i] = w; - g_target_report_data->finger_id[loop_i] = 1; - - /*I("%s: g_target_report_data->x[loop_i]=%d,*/ - /*g_target_report_data->y[loop_i]=%d,*/ - /*g_target_report_data->w[loop_i]=%d",*/ - /*__func__, g_target_report_data->x[loop_i],*/ - /*g_target_report_data->y[loop_i],*/ - /*g_target_report_data->w[loop_i]); */ - - - if (!ts->first_pressed) { - ts->first_pressed = 1; - I("S1@%d, %d\n", x, y); - } - - ts->pre_finger_data[loop_i][0] = x; - ts->pre_finger_data[loop_i][1] = y; - - ts->pre_finger_mask = ts->pre_finger_mask - + (1 << loop_i); - } else {/* report coordinates */ - g_target_report_data->x[loop_i] = x; - g_target_report_data->y[loop_i] = y; - g_target_report_data->w[loop_i] = w; - g_target_report_data->finger_id[loop_i] = 0; - - if (loop_i == 0 && ts->first_pressed == 1) { - ts->first_pressed = 2; - I("E1@%d, %d\n", ts->pre_finger_data[0][0], - ts->pre_finger_data[0][1]); - } - } - } - - if (g_ts_dbg != 0) { - for (loop_i = 0; loop_i < 10; loop_i++) - D("DBG X=%d Y=%d ID=%d\n", - g_target_report_data->x[loop_i], - g_target_report_data->y[loop_i], - g_target_report_data->finger_id[loop_i]); - - D("DBG finger number %d\n", g_target_report_data->finger_num); - } - - if (g_ts_dbg != 0) - I("%s: end!\n", __func__); - return ts_status; -} - -static int himax_parse_report_data(struct himax_ts_data *ts, - int ts_path, int ts_status) -{ - - if (g_ts_dbg != 0) - I("%s: start now_status=%d!\n", __func__, ts_status); - - - EN_NoiseFilter = - (hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 3); - /* I("EN_NoiseFilter=%d\n", EN_NoiseFilter); */ - EN_NoiseFilter = EN_NoiseFilter & 0x01; - /* I("EN_NoiseFilter2=%d\n", EN_NoiseFilter); */ - p_point_num = ts->hx_point_num; - - if (hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT] == 0xff) - ts->hx_point_num = 0; - else - ts->hx_point_num = - hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT] - & 0x0f; - - switch (ts_path) { - case HX_REPORT_COORD: - ts_status = himax_parse_report_points(ts, ts_path, ts_status); - break; - case HX_REPORT_COORD_RAWDATA: - /* touch monitor rawdata */ - if (debug_data != NULL) { - if (debug_data->fp_set_diag_cmd(ic_data, hx_touch_data)) - I("%s:raw data_checksum not match\n", __func__); - } else { - E("%s,There is no init set_diag_cmd\n", __func__); - } - ts_status = himax_parse_report_points(ts, ts_path, ts_status); - break; -#if defined(HX_SMART_WAKEUP) - case HX_REPORT_SMWP_EVENT: - himax_wake_event_parse(ts, ts_status); - break; -#endif - default: - E("%s:Fail Path!\n", __func__); - ts_status = HX_PATH_FAIL; - break; - } - if (g_ts_dbg != 0) - I("%s: end now_status=%d!\n", __func__, ts_status); - return ts_status; -} - -/* end parse_report_data*/ - -static void himax_report_all_leave_event(struct himax_ts_data *ts) -{ - int loop_i = 0; - - for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { -#if !defined(HX_PROTOCOL_A) - input_mt_slot(ts->input_dev, loop_i); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); -#endif - } - input_report_key(ts->input_dev, BTN_TOUCH, 0); - input_sync(ts->input_dev); -} - -/* start report_point*/ -static void himax_finger_report(struct himax_ts_data *ts) -{ - int i = 0; - bool valid = false; - - - if (g_ts_dbg != 0) { - I("%s:start hx_touch_data->finger_num=%d\n", - __func__, hx_touch_data->finger_num); - } - for (i = 0; i < ts->nFinger_support; i++) { - if (g_target_report_data->x[i] >= 0 - && g_target_report_data->x[i] <= ts->pdata->abs_x_max - && g_target_report_data->y[i] >= 0 - && g_target_report_data->y[i] <= ts->pdata->abs_y_max) - valid = true; - else - valid = false; - if (g_ts_dbg != 0) - I("valid=%d\n", valid); - if (valid) { - if (g_ts_dbg != 0) { - I("report_data->x[i]=%d,y[i]=%d,w[i]=%d", - g_target_report_data->x[i], - g_target_report_data->y[i], - g_target_report_data->w[i]); - } -#if !defined(HX_PROTOCOL_A) - input_mt_slot(ts->input_dev, i); -#else - input_report_key(ts->input_dev, BTN_TOUCH, 1); -#endif - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, - g_target_report_data->w[i]); -#if !defined(HX_PROTOCOL_A) - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, - g_target_report_data->w[i]); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, - g_target_report_data->w[i]); -#else - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i); -#endif - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, - g_target_report_data->x[i]); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, - g_target_report_data->y[i]); -#if !defined(HX_PROTOCOL_A) - ts->last_slot = i; - input_mt_report_slot_state(ts->input_dev, - MT_TOOL_FINGER, 1); -#else - input_mt_sync(ts->input_dev); -#endif - } else { -#if !defined(HX_PROTOCOL_A) - input_mt_slot(ts->input_dev, i); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); - input_mt_report_slot_state(ts->input_dev, - MT_TOOL_FINGER, 0); -#endif - } - } -#if !defined(HX_PROTOCOL_A) - input_report_key(ts->input_dev, BTN_TOUCH, 1); -#endif - input_sync(ts->input_dev); - - if (!ic_data->HX_PEN_FUNC) - goto skip_pen_operation; - - valid = false; - - if (g_target_report_data->p_x[0] >= 0 - && g_target_report_data->p_x[0] <= ts->pdata->abs_x_max - && g_target_report_data->p_y[0] >= 0 - && g_target_report_data->p_y[0] <= ts->pdata->abs_y_max - && (g_target_report_data->p_on[0] == 1)) - valid = true; - else - valid = false; - - if (g_ts_dbg != 0) - I("pen valid=%d\n", valid); - - if (valid) {/*Pen down*/ - if (g_ts_dbg != 0) - I("p_x[i]=%d, p_y[i]=%d, p_w[i]=%d\n", - g_target_report_data->p_x[0], - g_target_report_data->p_y[0], - g_target_report_data->p_w[0]); - - input_report_abs(ts->hx_pen_dev, ABS_X, - g_target_report_data->p_x[0]); - input_report_abs(ts->hx_pen_dev, ABS_Y, - g_target_report_data->p_y[0]); - - if (g_target_report_data->p_btn[0] != - g_target_report_data->pre_p_btn) { - if (g_ts_dbg != 0) - I("BTN_STYLUS:%d\n", - g_target_report_data->p_btn[0]); - - input_report_key(ts->hx_pen_dev, BTN_STYLUS, - g_target_report_data->p_btn[0]); - - g_target_report_data->pre_p_btn = - g_target_report_data->p_btn[0]; - } else { - if (g_ts_dbg != 0) - I("BTN_STYLUS status no change, value=%d!\n", - g_target_report_data->p_btn[0]); - } - - if (g_target_report_data->p_btn2[0] - != g_target_report_data->pre_p_btn2) { - if (g_ts_dbg != 0) - I("BTN_STYLUS2:%d\n", - g_target_report_data->p_btn2[0]); - - input_report_key(ts->hx_pen_dev, BTN_STYLUS2, - g_target_report_data->p_btn2[0]); - - g_target_report_data->pre_p_btn2 = - g_target_report_data->p_btn2[0]; - } else { - if (g_ts_dbg != 0) - I("BTN_STYLUS2 status no change, value=%d!\n", - g_target_report_data->p_btn2[0]); - } - input_report_abs(ts->hx_pen_dev, ABS_TILT_X, - g_target_report_data->p_tilt_x[0]); - - input_report_abs(ts->hx_pen_dev, ABS_TILT_Y, - g_target_report_data->p_tilt_y[0]); - - input_report_key(ts->hx_pen_dev, BTN_TOOL_PEN, 1); - - if (g_target_report_data->p_hover[0] == 0) { - input_report_key(ts->hx_pen_dev, BTN_TOUCH, 1); - input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 0); - input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, - g_target_report_data->p_w[0]); - } else { - input_report_key(ts->hx_pen_dev, BTN_TOUCH, 0); - input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 1); - input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0); - } - } else {/*Pen up*/ - g_target_report_data->pre_p_btn = 0; - g_target_report_data->pre_p_btn2 = 0; - input_report_key(ts->hx_pen_dev, BTN_STYLUS, 0); - input_report_key(ts->hx_pen_dev, BTN_STYLUS2, 0); - input_report_key(ts->hx_pen_dev, BTN_TOUCH, 0); - input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0); - input_sync(ts->hx_pen_dev); - - input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 0); - input_report_key(ts->hx_pen_dev, BTN_TOOL_RUBBER, 0); - input_report_key(ts->hx_pen_dev, BTN_TOOL_PEN, 0); - input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0); - } - input_sync(ts->hx_pen_dev); - -skip_pen_operation: - - if (g_ts_dbg != 0) - I("%s:end\n", __func__); -} - -static void himax_finger_leave(struct himax_ts_data *ts) -{ -#if !defined(HX_PROTOCOL_A) - int32_t loop_i = 0; -#endif - - if (g_ts_dbg != 0) - I("%s: start!\n", __func__); -#if defined(HX_PALM_REPORT) - if (himax_palm_detect(hx_touch_data->hx_coord_buf) == PALM_REPORT) { - I(" %s HX_PALM_REPORT KEY power event press\n", __func__); - input_report_key(ts->input_dev, KEY_POWER, 1); - input_sync(ts->input_dev); - msleep(100); - - I(" %s HX_PALM_REPORT KEY power event release\n", __func__); - input_report_key(ts->input_dev, KEY_POWER, 0); - input_sync(ts->input_dev); - return; - } -#endif - - hx_touch_data->finger_on = 0; - g_target_report_data->finger_on = 0; - g_target_report_data->finger_num = 0; - AA_press = 0; - -#if defined(HX_PROTOCOL_A) - input_mt_sync(ts->input_dev); -#endif -#if !defined(HX_PROTOCOL_A) - for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { - input_mt_slot(ts->input_dev, loop_i); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); - } -#endif - if (ts->pre_finger_mask > 0) - ts->pre_finger_mask = 0; - - if (ts->first_pressed == 1) { - ts->first_pressed = 2; - I("E1@%d, %d\n", ts->pre_finger_data[0][0], - ts->pre_finger_data[0][1]); - } - - /*if (ts->debug_log_level & BIT(1))*/ - /* himax_log_touch_event(x, y, w, loop_i, EN_NoiseFilter,*/ - /* HX_FINGER_LEAVE); */ - - input_report_key(ts->input_dev, BTN_TOUCH, 0); - input_sync(ts->input_dev); - - if (ic_data->HX_PEN_FUNC) { - input_report_key(ts->hx_pen_dev, BTN_STYLUS, 0); - input_report_key(ts->hx_pen_dev, BTN_TOUCH, 0); - input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0); - input_sync(ts->hx_pen_dev); - - input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 0); - input_report_abs(ts->hx_pen_dev, ABS_TILT_X, 0); - input_report_abs(ts->hx_pen_dev, ABS_TILT_Y, 0); - input_report_key(ts->hx_pen_dev, BTN_TOOL_RUBBER, 0); - input_report_key(ts->hx_pen_dev, BTN_TOOL_PEN, 0); - input_sync(ts->hx_pen_dev); - } - - if (g_ts_dbg != 0) - I("%s: end!\n", __func__); - - -} - -static void himax_report_points(struct himax_ts_data *ts) -{ - if (g_ts_dbg != 0) - I("%s: start!\n", __func__); - - if (ts->hx_point_num != 0) - himax_finger_report(ts); - else - himax_finger_leave(ts); - - Last_EN_NoiseFilter = EN_NoiseFilter; - - if (g_ts_dbg != 0) - I("%s: end!\n", __func__); -} -/* end report_points*/ - -int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status) -{ - if (g_ts_dbg != 0) - I("%s: Entering, ts_status=%d!\n", __func__, ts_status); - - if (ts_path == HX_REPORT_COORD || ts_path == HX_REPORT_COORD_RAWDATA) { - /* Touch Point information */ - himax_report_points(ts); - -#if defined(HX_SMART_WAKEUP) - } else if (ts_path == HX_REPORT_SMWP_EVENT) { - himax_wake_event_report(); -#endif - } else { - E("%s:Fail Path!\n", __func__); - ts_status = HX_PATH_FAIL; - } - - if (g_ts_dbg != 0) - I("%s: END, ts_status=%d!\n", __func__, ts_status); - return ts_status; -} -/* end report_data */ - -static int himax_ts_operation(struct himax_ts_data *ts, - int ts_path, int ts_status) -{ - uint8_t hw_reset_check[2]; - - memset(ts->xfer_buff, 0x00, 128 * sizeof(uint8_t)); - memset(hw_reset_check, 0x00, sizeof(hw_reset_check)); - - ts_status = himax_touch_get(ts, ts->xfer_buff, ts_path, ts_status); - if (ts_status == HX_TS_GET_DATA_FAIL) - goto END_FUNCTION; - - ts_status = himax_distribute_touch_data(ts->xfer_buff, - ts_path, ts_status); - ts_status = himax_err_ctrl(ts, ts->xfer_buff, ts_path, ts_status); - if (ts_status == HX_REPORT_DATA || ts_status == HX_TS_NORMAL_END) - ts_status = himax_parse_report_data(ts, ts_path, ts_status); - else - goto END_FUNCTION; - - - ts_status = himax_report_data(ts, ts_path, ts_status); - - -END_FUNCTION: - return ts_status; -} - -void himax_ts_work(struct himax_ts_data *ts) -{ - - int ts_status = HX_TS_NORMAL_END; - int ts_path = 0; - - if (debug_data != NULL) - debug_data->fp_ts_dbg_func(ts, HX_FINGER_ON); - -#if defined(HX_USB_DETECT_GLOBAL) - himax_cable_detect_func(false); -#endif - - ts_path = himax_ts_work_status(ts); - switch (ts_path) { - case HX_REPORT_COORD: - ts_status = himax_ts_operation(ts, ts_path, ts_status); - break; - case HX_REPORT_SMWP_EVENT: - ts_status = himax_ts_operation(ts, ts_path, ts_status); - break; - case HX_REPORT_COORD_RAWDATA: - ts_status = himax_ts_operation(ts, ts_path, ts_status); - break; - default: - E("%s:Path Fault! value=%d\n", __func__, ts_path); - goto END_FUNCTION; - } - - if (ts_status == HX_TS_GET_DATA_FAIL) - goto GET_TOUCH_FAIL; - else - goto END_FUNCTION; - -GET_TOUCH_FAIL: - I("%s: Now reset the Touch chip.\n", __func__); -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(false, true); -#else - g_core_fp.fp_system_reset(); -#endif -#if defined(HX_ZERO_FLASH) - if (g_core_fp.fp_0f_reload_to_active) - g_core_fp.fp_0f_reload_to_active(); -#endif -END_FUNCTION: - if (debug_data != NULL) - debug_data->fp_ts_dbg_func(ts, HX_FINGER_LEAVE); - -} -/*end ts_work*/ -enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer) -{ - struct himax_ts_data *ts; - - - ts = container_of(timer, struct himax_ts_data, timer); - queue_work(ts->himax_wq, &ts->work); - hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL); - return HRTIMER_NORESTART; -} - -#if defined(HX_AUTO_UPDATE_FW) -static void himax_update_register(struct work_struct *work) -{ - if (i_get_FW() != 0) - return; - - if (g_auto_update_flag == true) { - I("%s: Forced upgrade\n", __func__); - goto UPDATE_FW; - } - - if (himax_auto_update_check() != 0) { - kfree(i_CTPM_FW); - i_CTPM_FW = NULL; - return; - } - -UPDATE_FW: - if (i_update_FW() <= 0) - E("%s: Update FW fail\n", __func__); - else - I("%s: Update FW success\n", __func__); - -} -#endif - -#if !defined(HX_ZERO_FLASH) -static int hx_chk_flash_sts(void) -{ - int rslt = 0; - uint32_t size = 0; - - I("%s: Entering\n", __func__); - size = FW_SIZE_128k; - - -#if defined(HX_AUTO_UPDATE_FW) - g_auto_update_flag = (!g_core_fp.fp_calculateChecksum(false, size)); - g_auto_update_flag |= g_core_fp.fp_flash_lastdata_check(size); -#else - g_core_fp.fp_calculateChecksum(false, size); - g_core_fp.fp_flash_lastdata_check(size); -#endif - - return rslt; -} -#endif - -#if defined(HX_CONFIG_FB) || defined(CONFIG_DRM) -extern struct drm_panel *himax_active_panel; -static void himax_fb_register(struct work_struct *work) -{ - int ret = -1; - - struct himax_ts_data *ts = container_of(work, struct himax_ts_data, - work_att.work); - - I("%s in\n", __func__); -#if defined(HX_CONFIG_FB) - ts->fb_notif.notifier_call = fb_notifier_callback; - ret = fb_register_client(&ts->fb_notif); -#elif defined(CONFIG_DRM) -#if defined(__HIMAX_MOD__) - hx_msm_drm_register_client = - (void *)kallsyms_lookup_name("msm_drm_register_client"); - if (hx_msm_drm_register_client != NULL) { - ts->fb_notif.notifier_call = drm_notifier_callback; - ret = hx_msm_drm_register_client(&ts->fb_notif); - } else - E("hx_msm_drm_register_client is NULL\n"); -#else - ts->fb_notif.notifier_call = drm_notifier_callback; - if (himax_active_panel) - ret = drm_panel_notifier_register(himax_active_panel, &ts->fb_notif); -#endif -#endif - if (ret) - E("Unable to register fb_notifier: %d\n", ret); -} -#endif - -#include -#include - -/* Attribute: path (RO) */ -static ssize_t path_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct himax_ts_data *ts = dev_get_drvdata(dev); - ssize_t blen; - const char *path; - - if (!ts) { - pr_err("cannot get himax_ts_data pointer\n"); - return (ssize_t)0; - } - path = kobject_get_path(&ts->dev->kobj, GFP_KERNEL); - blen = scnprintf(buf, PAGE_SIZE, "%s", path ? path : "na"); - kfree(path); - return blen; -} - -/* Attribute: vendor (RO) */ -static ssize_t vendor_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return scnprintf(buf, PAGE_SIZE, "himax"); -} - -static struct device_attribute touchscreen_attributes[] = { - __ATTR_RO(path), - __ATTR_RO(vendor), - __ATTR_NULL -}; - -#define TSDEV_MINOR_BASE 128 -#define TSDEV_MINOR_MAX 32 - -static int himax_sysfs_touchscreen( - struct himax_ts_data *ts, bool create) -{ - struct device_attribute *attrs = touchscreen_attributes; - int i, error = 0; - static struct class *touchscreen_class; - static struct device *ts_class_dev; - static int minor; - - if (create) { - minor = input_get_new_minor(0x90, - 1, false); - if (minor < 0) - minor = input_get_new_minor(TSDEV_MINOR_BASE, - TSDEV_MINOR_MAX, true); - pr_info("assigned minor %d\n", minor); - - touchscreen_class = class_create(THIS_MODULE, "touchscreen"); - if (IS_ERR(touchscreen_class)) { - error = PTR_ERR(touchscreen_class); - touchscreen_class = NULL; - return error; - } - - ts_class_dev = device_create(touchscreen_class, NULL, - MKDEV(INPUT_MAJOR, minor), - ts, "%s", ts->chip_name); - if (IS_ERR(ts_class_dev)) { - error = PTR_ERR(ts_class_dev); - ts_class_dev = NULL; - return error; - } - for (i = 0; attrs[i].attr.name != NULL; ++i) { - error = device_create_file(ts_class_dev, &attrs[i]); - if (error) - break; - } - - if (error) - goto device_destroy; - } else { - if (!touchscreen_class || !ts_class_dev) - return -ENODEV; - - for (i = 0; attrs[i].attr.name != NULL; ++i) - device_remove_file(ts_class_dev, &attrs[i]); - - device_unregister(ts_class_dev); - class_unregister(touchscreen_class); - } - - return 0; - -device_destroy: - for (--i; i >= 0; --i) - device_remove_file(ts_class_dev, &attrs[i]); - device_destroy(touchscreen_class, MKDEV(INPUT_MAJOR, minor)); - ts_class_dev = NULL; - class_unregister(touchscreen_class); - pr_err("error creating touchscreen class\n"); - - return -ENODEV; -} - -#if defined(HX_CONTAINER_SPEED_UP) -static void himax_resume_work_func(struct work_struct *work) -{ - himax_chip_common_resume(private_ts); -} -#endif - -int himax_chip_common_init(void) -{ - - int i = 0, ret = 0, idx = 0; - int err = PROBE_FAIL; - struct himax_ts_data *ts = private_ts; - struct himax_i2c_platform_data *pdata; - struct himax_chip_entry *entry; - - I("Prepare kernel fp\n"); - kp_getname_kernel = (void *)kallsyms_lookup_name("getname_kernel"); - if (!kp_getname_kernel) { - E("prepare kp_getname_kernel failed!\n"); - /*goto err_xfer_buff_fail;*/ - } - kp_file_open_name = (void *)kallsyms_lookup_name("file_open_name"); - if (!kp_file_open_name) { - E("prepare kp_file_open_name failed!\n"); - goto err_xfer_buff_fail; - } -#if defined(__EMBEDDED_FW__) - g_embedded_fw.size = (size_t)_binary___Himax_firmware_bin_end - - (size_t)_binary___Himax_firmware_bin_start; -#endif - ts->xfer_buff = devm_kzalloc(ts->dev, 128 * sizeof(uint8_t), - GFP_KERNEL); - if (ts->xfer_buff == NULL) { - err = -ENOMEM; - goto err_xfer_buff_fail; - } - - I("PDATA START\n"); - pdata = kzalloc(sizeof(struct himax_i2c_platform_data), GFP_KERNEL); - - if (pdata == NULL) { /*Allocate Platform data space*/ - err = -ENOMEM; - goto err_dt_platform_data_fail; - } - - I("ic_data START\n"); - ic_data = kzalloc(sizeof(struct himax_ic_data), GFP_KERNEL); - if (ic_data == NULL) { /*Allocate IC data space*/ - err = -ENOMEM; - goto err_dt_ic_data_fail; - } - - /* allocate report data */ - hx_touch_data = kzalloc(sizeof(struct himax_report_data), GFP_KERNEL); - if (hx_touch_data == NULL) { - err = -ENOMEM; - goto err_alloc_touch_data_failed; - } - - if (himax_parse_dt(ts, pdata) < 0) { - I(" pdata is NULL for DT\n"); - goto err_alloc_dt_pdata_failed; - } - -#if defined(HX_RST_PIN_FUNC) - ts->rst_gpio = pdata->gpio_reset; -#endif - himax_gpio_power_config(pdata); -#if !defined(CONFIG_OF) - - if (pdata->power) { - ret = pdata->power(1); - - if (ret < 0) { - E("%s: power on failed\n", __func__); - goto err_power_failed; - } - } - -#endif - - g_hx_chip_inited = 0; - idx = himax_get_ksym_idx(); - if (idx >= 0) { - if (isEmpty(idx) != 0) { - I("%s: no chip registered, please insmod ic.ko!\n", - __func__); - goto error_ic_detect_failed; - } - entry = get_chip_entry_by_index(idx); - - for (i = 0; i < entry->hx_ic_dt_num; i++) { - if (entry->core_chip_dt[i].fp_chip_detect != NULL) { - if (entry->core_chip_dt[i].fp_chip_detect()) { - I("%s: chip found! list_num=%d\n", - __func__, i); - goto found_hx_chip; - } else { - I("%s:num=%d,chip NOT found! go Next\n", - __func__, i); - continue; - } - } - } - } else { - I("%s: No available chip exist!\n", __func__); - goto error_ic_detect_failed; - } - - if (i == entry->hx_ic_dt_num) { - E("%s: chip detect failed!\n", __func__); - goto error_ic_detect_failed; - } - -found_hx_chip: - if (g_core_fp.fp_chip_init != NULL) { - g_core_fp.fp_chip_init(); - } else { - E("%s: function point of chip_init is NULL!\n", __func__); - goto error_ic_detect_failed; - } - - if (pdata->virtual_key) - ts->button = pdata->virtual_key; - -#if !defined(HX_ZERO_FLASH) - g_core_fp.fp_read_FW_ver(); - hx_chk_flash_sts(); -#endif - -#if defined(HX_AUTO_UPDATE_FW) - if (g_auto_update_flag) - goto FW_force_upgrade; -#endif - -#if defined(HX_AUTO_UPDATE_FW) -FW_force_upgrade: - ts->himax_update_wq = - create_singlethread_workqueue("HMX_update_request"); - if (!ts->himax_update_wq) { - E(" allocate himax_update_wq failed\n"); - err = -ENOMEM; - goto err_update_wq_failed; - } - INIT_DELAYED_WORK(&ts->work_update, himax_update_register); - queue_delayed_work(ts->himax_update_wq, &ts->work_update, - msecs_to_jiffies(2000)); -#endif -#if defined(HX_ZERO_FLASH) - g_auto_update_flag = true; - ts->himax_0f_update_wq = - create_singlethread_workqueue("HMX_0f_update_request"); - if (!ts->himax_0f_update_wq) { - E(" allocate himax_0f_update_wq failed\n"); - err = -ENOMEM; - goto err_0f_update_wq_failed; - } - INIT_DELAYED_WORK(&ts->work_0f_update, g_core_fp.fp_0f_operation); - queue_delayed_work(ts->himax_0f_update_wq, &ts->work_0f_update, - msecs_to_jiffies(2000)); -#endif - -#if defined(HX_CONTAINER_SPEED_UP) - ts->ts_int_workqueue = - create_singlethread_workqueue("himax_ts_resume_wq"); - if (!ts->ts_int_workqueue) { - E("%s: create ts_resume workqueue failed\n", __func__); - goto err_create_ts_resume_wq_failed; - } - INIT_DELAYED_WORK(&ts->ts_int_work, himax_resume_work_func); -#endif - - /*Himax Power On and Load Config*/ -/* if (himax_loadSensorConfig(pdata)) { - * E("%s: Load Sesnsor configuration failed, unload driver.\n", - * __func__); - * goto err_detect_failed; - * } - */ - g_core_fp.fp_power_on_init(); - calculate_point_number(); - -#if defined(CONFIG_OF) - ts->power = pdata->power; -#endif - - ts->pdata = pdata; - /*calculate the i2c data size*/ - calcDataSize(); - I("%s: calcDataSize complete\n", __func__); - -#if defined(CONFIG_OF) - ts->pdata->abs_pressure_min = 0; - ts->pdata->abs_pressure_max = 200; - ts->pdata->abs_width_min = 0; - ts->pdata->abs_width_max = 200; - pdata->cable_config[0] = 0xF0; - pdata->cable_config[1] = 0x00; -#endif - - ts->suspended = false; - -#if defined(HX_USB_DETECT_GLOBAL) - ts->usb_connected = 0x00; - ts->cable_config = pdata->cable_config; -#endif - -#if defined(HX_PROTOCOL_A) - ts->protocol_type = PROTOCOL_TYPE_A; -#else - ts->protocol_type = PROTOCOL_TYPE_B; -#endif - I("%s: Use Protocol Type %c\n", __func__, - ts->protocol_type == PROTOCOL_TYPE_A ? 'A' : 'B'); - - ret = himax_input_register(ts); - if (ret) { - E("%s: Unable to register %s input device\n", - __func__, ts->input_dev->name); - goto err_input_register_device_failed; - } - - spin_lock_init(&ts->irq_lock); - ts->initialized = true; - -#if defined(HX_CONFIG_FB) || defined(CONFIG_DRM) - ts->himax_att_wq = create_singlethread_workqueue("HMX_ATT_request"); - - if (!ts->himax_att_wq) { - E(" allocate himax_att_wq failed\n"); - err = -ENOMEM; - goto err_get_intr_bit_failed; - } - - INIT_DELAYED_WORK(&ts->work_att, himax_fb_register); - queue_delayed_work(ts->himax_att_wq, &ts->work_att, - msecs_to_jiffies(1500)); -#endif - -#if defined(HX_SMART_WAKEUP) - ts->SMWP_enable = 0; - wakeup_source_init(&ts->ts_SMWP_wake_lock, HIMAX_common_NAME); -#endif -#if defined(HX_HIGH_SENSE) - ts->HSEN_enable = 0; -#endif - - /*touch data init*/ - err = himax_report_data_init(); - - if (err) - goto err_report_data_init_failed; - - if (himax_common_proc_init()) { - E(" %s: himax_common proc_init failed!\n", __func__); - goto err_creat_proc_file_failed; - } - himax_sysfs_touchscreen(ts, true); - - himax_ts_register_interrupt(); - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) - if (himax_debug_init()) - E(" %s: debug initial failed!\n", __func__); -#endif - -#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) - - if (g_auto_update_flag) - himax_int_enable(0); - -#endif - g_hx_chip_inited = true; - return 0; - -err_creat_proc_file_failed: - himax_report_data_deinit(); -err_report_data_init_failed: -#if defined(HX_SMART_WAKEUP) - wakeup_source_trash(&ts->ts_SMWP_wake_lock); -#endif -#if defined(HX_CONFIG_FB) || defined(CONFIG_DRM) - cancel_delayed_work_sync(&ts->work_att); - destroy_workqueue(ts->himax_att_wq); -err_get_intr_bit_failed: -#endif -err_input_register_device_failed: - input_free_device(ts->input_dev); -/*err_detect_failed:*/ - -#if defined(HX_CONTAINER_SPEED_UP) - cancel_delayed_work_sync(&ts->ts_int_work); - destroy_workqueue(ts->ts_int_workqueue); -err_create_ts_resume_wq_failed: -#endif - -#if defined(HX_ZERO_FLASH) - cancel_delayed_work_sync(&ts->work_0f_update); - destroy_workqueue(ts->himax_0f_update_wq); -err_0f_update_wq_failed: -#endif - -#if defined(HX_AUTO_UPDATE_FW) - if (g_auto_update_flag) { - cancel_delayed_work_sync(&ts->work_update); - destroy_workqueue(ts->himax_update_wq); - } -err_update_wq_failed: -#endif -error_ic_detect_failed: - himax_gpio_power_deconfig(pdata); -#if !defined(CONFIG_OF) -err_power_failed: -#endif -err_alloc_dt_pdata_failed: - kfree(hx_touch_data); - hx_touch_data = NULL; -err_alloc_touch_data_failed: - kfree(ic_data); - ic_data = NULL; -err_dt_ic_data_fail: - kfree(pdata); - pdata = NULL; -err_dt_platform_data_fail: - devm_kfree(ts->dev, ts->xfer_buff); - ts->xfer_buff = NULL; -err_xfer_buff_fail: - probe_fail_flag = 1; - return err; -} - -void himax_chip_common_deinit(void) -{ - struct himax_ts_data *ts = private_ts; - - himax_ts_unregister_interrupt(); - - himax_sysfs_touchscreen(ts, false); - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT) - himax_inspect_data_clear(); -#endif - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) - himax_debug_remove(); -#endif - - himax_common_proc_deinit(); - himax_report_data_deinit(); - -#if defined(HX_SMART_WAKEUP) - wakeup_source_trash(&ts->ts_SMWP_wake_lock); -#endif -#if defined(HX_CONFIG_FB) - if (fb_unregister_client(&ts->fb_notif)) - E("Error occurred while unregistering fb_notifier.\n"); - cancel_delayed_work_sync(&ts->work_att); - destroy_workqueue(ts->himax_att_wq); -#elif defined(CONFIG_DRM) -#if defined(__HIMAX_MOD__) - hx_msm_drm_unregister_client = - (void *)kallsyms_lookup_name("msm_drm_unregister_client"); - if (hx_msm_drm_unregister_client != NULL) { - if (hx_msm_drm_unregister_client(&ts->fb_notif)) - E("Error occurred while unregistering drm_notifier.\n"); - } else - E("hx_msm_drm_unregister_client is NULL\n"); -#else - if (himax_active_panel) - if (drm_panel_notifier_unregister(himax_active_panel, &ts->fb_notif)) - E("Error occurred while unregistering drm_notifier.\n"); -#endif - cancel_delayed_work_sync(&ts->work_att); - destroy_workqueue(ts->himax_att_wq); -#endif - input_free_device(ts->input_dev); -#if defined(HX_CONTAINER_SPEED_UP) - cancel_delayed_work_sync(&ts->ts_int_work); - destroy_workqueue(ts->ts_int_workqueue); -#endif -#if defined(HX_ZERO_FLASH) - cancel_delayed_work_sync(&ts->work_0f_update); - destroy_workqueue(ts->himax_0f_update_wq); -#endif -#if defined(HX_AUTO_UPDATE_FW) - cancel_delayed_work_sync(&ts->work_update); - destroy_workqueue(ts->himax_update_wq); -#endif - himax_gpio_power_deconfig(ts->pdata); - if (himax_mcu_cmd_struct_free) - himax_mcu_cmd_struct_free(); - - kfree(hx_touch_data); - hx_touch_data = NULL; - kfree(ic_data); - ic_data = NULL; - kfree(ts->pdata->virtual_key); - ts->pdata->virtual_key = NULL; - devm_kfree(ts->dev, ts->xfer_buff); - ts->xfer_buff = NULL; - kfree(ts->pdata); - ts->pdata = NULL; - kfree(ts); - ts = NULL; - probe_fail_flag = 0; - - I("%s: Common section deinited!\n", __func__); -} - -int himax_chip_common_suspend(struct himax_ts_data *ts) -{ - if (ts->suspended) { - I("%s: Already suspended. Skipped.\n", __func__); - goto END; - } else { - ts->suspended = true; - I("%s: enter\n", __func__); - } - - if (debug_data != NULL && debug_data->flash_dump_going == true) { - I("[himax] %s: Flash dump is going, reject suspend\n", - __func__); - goto END; - } - -#if defined(HX_SMART_WAKEUP)\ - || defined(HX_HIGH_SENSE)\ - || defined(HX_USB_DETECT_GLOBAL) -#if !defined(HX_RESUME_SEND_CMD) - g_core_fp.fp_resend_cmd_func(ts->suspended); -#endif -#endif -#if defined(HX_SMART_WAKEUP) - - if (ts->SMWP_enable) { -#if defined(HX_CODE_OVERLAY) - if (ts->in_self_test == 0) - g_core_fp.fp_0f_overlay(2, 0); -#endif - - atomic_set(&ts->suspend_mode, 1); - ts->pre_finger_mask = 0; - I("[himax] %s: SMART_WAKEUP enable, reject suspend\n", - __func__); - goto END; - } - -#endif - himax_int_enable(0); - /*if (g_core_fp.fp_suspend_ic_action != NULL)*/ - /*g_core_fp.fp_suspend_ic_action();*/ - - if (!ts->use_irq) { - int32_t cancel_state; - - cancel_state = cancel_work_sync(&ts->work); - if (cancel_state) - himax_int_enable(1); - } - - /*ts->first_pressed = 0;*/ - atomic_set(&ts->suspend_mode, 1); - ts->pre_finger_mask = 0; - - if (ts->pdata) - if (ts->pdata->powerOff3V3 && ts->pdata->power) - ts->pdata->power(0); - -END: - if (ts->in_self_test == 1) - ts->suspend_resume_done = 1; - - I("%s: END\n", __func__); - - return 0; -} - -int himax_chip_common_resume(struct himax_ts_data *ts) -{ -#if defined(HX_ZERO_FLASH) && defined(HX_RESUME_SET_FW) - int result = 0; -#endif - I("%s: enter\n", __func__); - - if (ts->suspended == false) { - I("%s: It had entered resume, skip this step\n", __func__); - goto END; - } else { - ts->suspended = false; - } - -#if defined(HX_ESD_RECOVERY) - /* continuous N times record, not total N times. */ - g_zero_event_count = 0; -#endif - - atomic_set(&ts->suspend_mode, 0); - ts->diag_cmd = 0; - - if (ts->pdata) - if (ts->pdata->powerOff3V3 && ts->pdata->power) - ts->pdata->power(1); - -#if defined(HX_RST_PIN_FUNC) && defined(HX_RESUME_HW_RESET) - if (g_core_fp.fp_ic_reset != NULL) - g_core_fp.fp_ic_reset(false, false); -#endif - -#if defined(HX_ZERO_FLASH) && defined(HX_RESUME_SET_FW) -#if defined(HX_SMART_WAKEUP) - if (!ts->SMWP_enable) { -#endif - I("It will update fw after resume in zero flash mode!\n"); - if (g_core_fp.fp_0f_operation_dirly != NULL) { - result = g_core_fp.fp_0f_operation_dirly(); - if (result) { - E("Something wrong! Skip Update zero flash!\n"); - goto ESCAPE_0F_UPDATE; - } - } - if (g_core_fp.fp_reload_disable != NULL) - g_core_fp.fp_reload_disable(0); - if (g_core_fp.fp_sense_on != NULL) - g_core_fp.fp_sense_on(0x00); -#if defined(HX_SMART_WAKEUP) - } -#endif -#endif -#if defined(HX_SMART_WAKEUP)\ - || defined(HX_HIGH_SENSE)\ - || defined(HX_USB_DETECT_GLOBAL) - if (g_core_fp.fp_resend_cmd_func != NULL) - g_core_fp.fp_resend_cmd_func(ts->suspended); - -#if defined(HX_CODE_OVERLAY) - if (ts->SMWP_enable && ts->in_self_test == 0) - g_core_fp.fp_0f_overlay(3, 0); -#endif -#endif - himax_report_all_leave_event(ts); - - if (g_core_fp.fp_sense_on != NULL) - g_core_fp.fp_resume_ic_action(); - - himax_int_enable(1); -#if defined(HX_ZERO_FLASH) && defined(HX_RESUME_SET_FW) -ESCAPE_0F_UPDATE: -#endif -END: - if (ts->in_self_test == 1) - ts->suspend_resume_done = 1; - - I("%s: END\n", __func__); - return 0; -} - +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for common functions + * + * 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_common.h"*/ +/*#include "himax_ic_core.h"*/ +#include "himax_inspection.h" +#include "himax_modular_table.h" + +#ifdef HX_SMART_WAKEUP +#define GEST_SUP_NUM 26 +/* Setting cust key define (DF = double finger) */ +/* {Double Tap, Up, Down, Left, Rright, C, Z, M, + * O, S, V, W, e, m, @, (reserve), + * Finger gesture, ^, >, <, f(R), f(L), Up(DF), Down(DF), + * Left(DF), Right(DF)} + */ + uint8_t gest_event[GEST_SUP_NUM] = { + 0x80, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x81, 0x1D, 0x2D, 0x3D, 0x1F, 0x2F, 0x51, 0x52, + 0x53, 0x54}; + +/*gest_event mapping to gest_key_def*/ + uint16_t gest_key_def[GEST_SUP_NUM] = { + KEY_POWER, 251, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, 273, + 274, 275}; + +uint8_t *wake_event_buffer; +#endif + +#ifdef HIMAX_PALM_SENSOR_EN +static struct sensors_classdev __maybe_unused palm_sensors_touch_cdev = { + .name = "palm-gesture", + .vendor = "Himax", + .version = 1, + .type = SENSOR_TYPE_MOTO_TOUCH_PALM, + .max_range = "5.0", + .resolution = "5.0", + .sensor_power = "1", + .min_delay = 0, + .max_delay = 0, + .fifo_reserved_event_count = 0, + .fifo_max_event_count = 0, + .enabled = 0, + .delay_msec = 200, + .sensors_enable = NULL, + .sensors_poll_delay = NULL, +}; +static void himax_palm_detect_func(struct himax_ts_data *ts, bool detected); +#endif + +#ifdef HIMAX_V2_SENSOR_EN +static struct sensors_classdev __maybe_unused sensors_touch_cdev = { + .name = "dt-gesture", + .vendor = "Himax", + .version = 1, + .type = SENSOR_TYPE_MOTO_DOUBLE_TAP, + .max_range = "5.0", + .resolution = "5.0", + .sensor_power = "1", + .min_delay = 0, + .max_delay = 0, + /* WAKE_UP & SPECIAL_REPORT */ + .flags = 1 | 6, + .fifo_reserved_event_count = 0, + .fifo_max_event_count = 0, + .enabled = 0, + .delay_msec = 200, + .sensors_enable = NULL, + .sensors_poll_delay = NULL, +}; +#define REPORT_MAX_COUNT 10000 +#endif + +#define SUPPORT_FINGER_DATA_CHECKSUM 0x0F +#define TS_WAKE_LOCK_TIMEOUT (5000) +#define FRAME_COUNT 5 + +#ifdef HX_TP_PROC_GUEST_INFO +struct hx_guest_info *g_guest_info_data; +EXPORT_SYMBOL(g_guest_info_data); + +char *g_guest_info_item[] = { + "projectID", + "CGColor", + "BarCode", + "Reserve1", + "Reserve2", + "Reserve3", + "Reserve4", + "Reserve5", + "VCOM", + "Vcom-3Gar", + NULL +}; +#endif + +uint32_t g_hx_chip_inited; + +#if defined(__EMBEDDED_FW__) +struct firmware g_embedded_fw = { + .data = _binary___Himax_firmware_bin_start, +}; +#endif + +#define HIMAX_FILE_NAME_LENGTH 128 + +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) +#if defined(HX_EN_DYNAMIC_NAME) +char *i_CTPM_firmware_name; +#else +char *i_CTPM_firmware_name = "Himax_firmware.bin"; +#endif +bool g_auto_update_flag; +#endif +#if defined(HX_AUTO_UPDATE_FW) +unsigned char *i_CTPM_FW; +int i_CTPM_FW_len; +int g_i_FW_VER; +int g_i_CFG_VER; +int g_i_CID_MAJ; /*GUEST ID*/ +int g_i_CID_MIN; /*VER for GUEST*/ +#endif +#ifdef HX_ZERO_FLASH +int g_f_0f_updat; +#endif + +struct himax_ts_data *private_ts; +EXPORT_SYMBOL(private_ts); + +struct himax_ic_data *ic_data; +EXPORT_SYMBOL(ic_data); + +struct himax_report_data *hx_touch_data; +EXPORT_SYMBOL(hx_touch_data); + +struct himax_core_fp g_core_fp; +EXPORT_SYMBOL(g_core_fp); + +struct himax_debug *debug_data; +EXPORT_SYMBOL(debug_data); + +struct proc_dir_entry *himax_touch_proc_dir; +EXPORT_SYMBOL(himax_touch_proc_dir); + +struct himax_chip_detect *g_core_chip_dt; +EXPORT_SYMBOL(g_core_chip_dt); + +int g_mmi_refcnt; +EXPORT_SYMBOL(g_mmi_refcnt); + +#define HIMAX_PROC_TOUCH_FOLDER "android_touch" +/*ts_work about start*/ +struct himax_target_report_data *g_target_report_data; +EXPORT_SYMBOL(g_target_report_data); + +static void himax_report_all_leave_event(struct himax_ts_data *ts); +/*ts_work about end*/ +static int HX_TOUCH_INFO_POINT_CNT; + +struct filename* (*kp_getname_kernel)(const char *filename); +struct file* (*kp_file_open_name)(struct filename *name, int flags, umode_t mode); + +unsigned long FW_VER_MAJ_FLASH_ADDR; +EXPORT_SYMBOL(FW_VER_MAJ_FLASH_ADDR); + +unsigned long FW_VER_MIN_FLASH_ADDR; +EXPORT_SYMBOL(FW_VER_MIN_FLASH_ADDR); + +unsigned long CFG_VER_MAJ_FLASH_ADDR; +EXPORT_SYMBOL(CFG_VER_MAJ_FLASH_ADDR); + +unsigned long CFG_VER_MIN_FLASH_ADDR; +EXPORT_SYMBOL(CFG_VER_MIN_FLASH_ADDR); + +unsigned long CID_VER_MAJ_FLASH_ADDR; +EXPORT_SYMBOL(CID_VER_MAJ_FLASH_ADDR); + +unsigned long CID_VER_MIN_FLASH_ADDR; +EXPORT_SYMBOL(CID_VER_MIN_FLASH_ADDR); +/*unsigned long PANEL_VERSION_ADDR;*/ + +unsigned long FW_VER_MAJ_FLASH_LENG; +EXPORT_SYMBOL(FW_VER_MAJ_FLASH_LENG); + +unsigned long FW_VER_MIN_FLASH_LENG; +EXPORT_SYMBOL(FW_VER_MIN_FLASH_LENG); + +unsigned long CFG_VER_MAJ_FLASH_LENG; +EXPORT_SYMBOL(CFG_VER_MAJ_FLASH_LENG); + +unsigned long CFG_VER_MIN_FLASH_LENG; +EXPORT_SYMBOL(CFG_VER_MIN_FLASH_LENG); + +unsigned long CID_VER_MAJ_FLASH_LENG; +EXPORT_SYMBOL(CID_VER_MAJ_FLASH_LENG); + +unsigned long CID_VER_MIN_FLASH_LENG; +EXPORT_SYMBOL(CID_VER_MIN_FLASH_LENG); +/*unsigned long PANEL_VERSION_LENG;*/ + +unsigned long FW_CFG_VER_FLASH_ADDR; + + +unsigned char IC_CHECKSUM; +EXPORT_SYMBOL(IC_CHECKSUM); + +#ifdef HX_ESD_RECOVERY +u8 HX_ESD_RESET_ACTIVATE; +EXPORT_SYMBOL(HX_ESD_RESET_ACTIVATE); + +int hx_EB_event_flag; +EXPORT_SYMBOL(hx_EB_event_flag); + +int hx_EC_event_flag; +EXPORT_SYMBOL(hx_EC_event_flag); + +int hx_ED_event_flag; +EXPORT_SYMBOL(hx_ED_event_flag); + +int g_zero_event_count; + +#endif + +u8 HX_HW_RESET_ACTIVATE; + +static uint8_t AA_press; +static uint8_t EN_NoiseFilter; +static uint8_t Last_EN_NoiseFilter; + +static int p_point_num = 0xFFFF; +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) +static uint8_t vk_press; +static int tpd_key; +static int tpd_key_old; +#endif +static int probe_fail_flag; +#ifdef HX_USB_DETECT_GLOBAL + bool USB_detect_flag; +#endif + +#if defined(CONFIG_DRM) +int drm_notifier_callback(struct notifier_block *self, + unsigned long event, void *data); +#elif defined(CONFIG_FB) +int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data); +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void himax_ts_early_suspend(struct early_suspend *h); +static void himax_ts_late_resume(struct early_suspend *h); +#endif + +#ifdef HX_GESTURE_TRACK + static int gest_pt_cnt; + static int gest_pt_x[GEST_PT_MAX_NUM]; + static int gest_pt_y[GEST_PT_MAX_NUM]; + static int gest_start_x, gest_start_y, gest_end_x, gest_end_y; + static int gest_width, gest_height, gest_mid_x, gest_mid_y; + static int hx_gesture_coor[16]; +#endif + +int g_ts_dbg; +EXPORT_SYMBOL(g_ts_dbg); + +/* File node for Selftest, SMWP and HSEN - Start*/ +#define HIMAX_PROC_SELF_TEST_FILE "self_test" +struct proc_dir_entry *himax_proc_self_test_file; + +#define HIMAX_PROC_SELF_TEST_RAW_FILE "self_test_rawdata" +struct proc_dir_entry *himax_proc_self_raw_file = NULL; + +uint8_t HX_PROC_SEND_FLAG; +EXPORT_SYMBOL(HX_PROC_SEND_FLAG); + +#ifdef HX_SMART_WAKEUP + #define HIMAX_PROC_SMWP_FILE "SMWP" + struct proc_dir_entry *himax_proc_SMWP_file = NULL; + #define HIMAX_PROC_GESTURE_FILE "GESTURE" + struct proc_dir_entry *himax_proc_GESTURE_file = NULL; + uint8_t HX_SMWP_EN; +#ifdef HX_P_SENSOR + #define HIMAX_PROC_PSENSOR_FILE "Psensor" + struct proc_dir_entry *himax_proc_psensor_file = NULL; +#endif +#endif + +#ifdef HX_EDGE_LIMIT + #define HIMAX_PROC_EDGE_LIMIT_FILE "edge_en" + struct proc_dir_entry *himax_proc_edge_limit_file = NULL; +#endif + +#if defined(HX_SMART_WAKEUP) || defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT) +bool FAKE_POWER_KEY_SEND = true; +#endif + +#ifdef HX_HIGH_SENSE + #define HIMAX_PROC_HSEN_FILE "HSEN" + struct proc_dir_entry *himax_proc_HSEN_file = NULL; +#endif + +#if defined(HX_PALM_REPORT) +static int himax_palm_detect(uint8_t *buf) +{ + struct himax_ts_data *ts = private_ts; + int32_t loop_i; + int base = 0; + int x = 0, y = 0, w = 0; + + loop_i = 0; + base = loop_i * 4; + x = buf[base] << 8 | buf[base + 1]; + y = (buf[base + 2] << 8 | buf[base + 3]); + w = buf[(ts->nFinger_support * 4) + loop_i]; +#ifndef HIMAX_PALM_SENSOR_EN + I(" %s HX_PALM_REPORT_loopi=%d,base=%x,X=%x,Y=%x,W=%x\n", __func__, loop_i, base, x, y, w); + if ((!atomic_read(&ts->suspend_mode)) && (x == 0xFA5A) && (y == 0xFA5A) && (w == 0x00)) + return PALM_REPORT; + else + return NOT_REPORT; +#else + if ((x == 0xFA5A) && (y == 0xFA5A)) { + I("%s: HX_PALM_REPORT loop_i=%d base=%x X=%x, Y=%x, W=%x\n", + __func__, loop_i, base, x, y, w); + return PALM_REPORT; + } else if ((x == 0xFC5C) && (y == 0xFC5C)) { + I("%s: HX_PALM_REPORT loop_i=%d base=%x X=%x, Y=%x, W=%x\n", + __func__, loop_i, base, x, y, w); + return PALM_LEAVE_REPORT; + } else + return NOT_REPORT; +#endif +} +#endif + +static ssize_t himax_self_test_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + int i = 0; + char buf[80] = {0}; + + if (len >= 80) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) { + return -EFAULT; + } + + if (hx_self_test_file_name == NULL) { + E("file name is NULL\n"); + hx_self_test_file_name = kzalloc(80, GFP_KERNEL); + snprintf(hx_self_test_file_name, 15, "hx_criteria.csv"); + } + + for (i = 0; i < 80; i++) { + if (buf[i] == ',' || buf[i] == '\n') { + memset(hx_self_test_file_name, 0x0, 80); + memcpy(hx_self_test_file_name, buf, i); + I("%s: Get name from Customer\n", __func__); + break; + } + } + if (i == 80) { + memset(hx_self_test_file_name, 0x0, 80); + snprintf(hx_self_test_file_name, 16, "hx_criteria.csv"); + I("%s: Use default name\n", __func__); + } + I("file name = %s\n", hx_self_test_file_name); + + return len; +} + +static ssize_t himax_self_test_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + int val = 0x00; + size_t ret = 0; + char *temp_buf; + I("%s: enter, %d \n", __func__, __LINE__); + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kzalloc(len, GFP_KERNEL); + himax_int_enable(0);/* disable irq */ + private_ts->in_self_test = 1; + val = g_core_fp.fp_chip_self_test(); +#ifdef HX_ESD_RECOVERY + HX_ESD_RESET_ACTIVATE = 1; +#endif + himax_int_enable(1);/* enable irq */ + + if (val == 0x00) { + ret += snprintf(temp_buf + ret, len - ret, "Self_Test Pass\n"); + } else { + ret += snprintf(temp_buf + ret, len - ret, "Self_Test Fail\n"); + } + + private_ts->in_self_test = 0; + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } else { + HX_PROC_SEND_FLAG = 0; + } + + return ret; +} + +static struct file_operations himax_proc_self_test_ops = { + .owner = THIS_MODULE, + .read = himax_self_test_read, + .write = himax_self_test_write, +}; + +static void *himax_self_raw_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos >= 1) { + return NULL; + } + return (void *)((unsigned long) *pos + 1); +} + +static void *himax_self_raw_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + return NULL; +} + +static void himax_self_raw_seq_stop(struct seq_file *s, void *v) +{ +} + +static int himax_self_raw_seq_read(struct seq_file *s, void *v) +{ + size_t ret = 0; + + if (g_rslt_data != NULL) { + seq_printf(s, "%s", g_rslt_data); + } + return ret; +} +static struct seq_operations himax_self_raw_seq_ops = { + .start = himax_self_raw_seq_start, + .next = himax_self_raw_seq_next, + .stop = himax_self_raw_seq_stop, + .show = himax_self_raw_seq_read, +}; +static int himax_self_raw_proc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &himax_self_raw_seq_ops); +}; + +static struct file_operations himax_proc_self_raw_ops = { + .owner = THIS_MODULE, + .open = himax_self_raw_proc_open, + .read = seq_read, +}; + +#if 0 +static ssize_t himax_self_test(struct seq_file *s, void *v) +{ + int val = 0x00; + size_t ret = 0; + + I("%s: enter, %d\n", __func__, __LINE__); + + if (private_ts->suspended == 1) { + E("%s: please do self test in normal active mode\n", __func__); + return HX_INIT_FAIL; + } + + himax_int_enable(0);/* disable irq */ + + private_ts->in_self_test = 1; + + val = g_core_fp.fp_chip_self_test(); +/* + *#ifdef HX_ESD_RECOVERY + * HX_ESD_RESET_ACTIVATE = 1; + *#endif + * himax_int_enable(1); //enable irq + */ + if (val == HX_INSPECT_OK) + seq_puts(s, "Self_Test Pass:\n"); + else + seq_puts(s, "Self_Test Fail:\n"); + + /*Print_Self_Test_Info(val,temp_buf);*/ + if ((val & HX_INSPECT_EFILE) == HX_INSPECT_EFILE) { + seq_puts(s, " Get criteria File Fail\n"); + goto END_FUNC; + } else if ((val & HX_INSPECT_MEMALLCTFAIL) == HX_INSPECT_MEMALLCTFAIL) { + seq_puts(s, " Allocate memory Fail\n"); + goto END_FUNC; + } else { + seq_puts(s, " Get criteria File OK\n"); + } + if ((val & HX_INSPECT_EGETRAW) == HX_INSPECT_EGETRAW) { + seq_puts(s, " Get raw data Fail\n"); + goto END_FUNC; + } else { + seq_puts(s, " Get raw data OK\n"); + } +#ifdef CONFIG_TOUCHSCREEN_HIMAX_INSPECT + if (g_inspt_crtra_flag[IDX_RAWMIN] == 1 && g_inspt_crtra_flag[IDX_RAWMAX] == 1) { + if ((val & HX_INSPECT_ERAW) == HX_INSPECT_ERAW) + seq_puts(s, " Check Raw data Fail\n"); + else + seq_puts(s, " Check Raw data OK\n"); + } + if (g_inspt_crtra_flag[IDX_WT_NOISEMAX] == 1 && g_inspt_crtra_flag[IDX_WT_NOISEMIN] == 1) { + if ((val & HX_INSPECT_WT_ENOISE) == HX_INSPECT_WT_ENOISE) + seq_puts(s, " Check Noise(weight) Fail\n"); + else + seq_puts(s, " Check Noise(weight) OK\n"); + } + if (g_inspt_crtra_flag[IDX_ABS_NOISEMAX] == 1 && g_inspt_crtra_flag[IDX_ABS_NOISEMIN] == 1) { + if ((val & HX_INSPECT_ABS_ENOISE) == HX_INSPECT_ABS_ENOISE) + seq_puts(s, " Check Noise(absolute) Fail\n"); + else + seq_puts(s, " Check Noise(absolute) OK\n"); + } + if (g_inspt_crtra_flag[IDX_OPENMIN] == 1 && g_inspt_crtra_flag[IDX_OPENMAX] == 1) { + if ((val & HX_INSPECT_EOPEN) == HX_INSPECT_EOPEN) + seq_puts(s, " Check Sensor open Fail\n"); + else + seq_puts(s, " Check Sensor open OK\n"); + } + if (g_inspt_crtra_flag[IDX_M_OPENMIN] == 1 && g_inspt_crtra_flag[IDX_M_OPENMAX] == 1) { + if ((val & HX_INSPECT_EMOPEN) == HX_INSPECT_EMOPEN) + seq_puts(s, " Check Sensor micro open Fail\n"); + else + seq_puts(s, " Check Sensor micro open OK\n"); + } + if (g_inspt_crtra_flag[IDX_SORTMIN] == 1 && g_inspt_crtra_flag[IDX_SORTMAX] == 1) { + if ((val & HX_INSPECT_ESHORT) == HX_INSPECT_ESHORT) + seq_puts(s, " Check Sensor short Fail\n"); + else + seq_puts(s, " Check Sensor short OK\n"); + } + if ((g_inspt_crtra_flag[IDX_GAP_HOR_RAWMIN] == 1 && g_inspt_crtra_flag[IDX_GAP_HOR_RAWMAX] == 1) || + (g_inspt_crtra_flag[IDX_GAP_VER_RAWMIN] == 1 && g_inspt_crtra_flag[IDX_GAP_VER_RAWMAX] == 1)) { + if ((val & HX_INSPECT_EGAP_RAW) == HX_INSPECT_EGAP_RAW) + seq_puts(s, " Check Raw Data GAP Fail\n"); + else + seq_puts(s, " Check Raw Data GAP OK\n"); + } + if (g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MIN] == 1 && g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MAX] == 1) { + if ((val & HX_INSPECT_EACT_IDLE_RAW) == HX_INSPECT_EACT_IDLE_RAW) + seq_puts(s, " Check ACT_IDLE RAW Fail\n"); + else + seq_puts(s, " Check ACT_IDLE RAW OK\n"); + } + if (g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MIN] == 1 && g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MAX] == 1) { + if ((val & HX_INSPECT_EACT_IDLE_NOISE) == HX_INSPECT_EACT_IDLE_NOISE) + seq_puts(s, " Check ACT_IDLE NOISE Fail\n"); + else + seq_puts(s, " Check ACT_IDLE NOISE OK\n"); + } + if (g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MIN] == 1 && g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MAX] == 1) { + if ((val & HX_INSPECT_ELPWUG_RAW) == HX_INSPECT_ELPWUG_RAW) + seq_puts(s, " Check LPWUG RAW Fail\n"); + else + seq_puts(s, " Check LPWUG RAW OK\n"); + } + if (g_inspt_crtra_flag[IDX_LPWUG_NOISE_MIN] == 1 && g_inspt_crtra_flag[IDX_LPWUG_NOISE_MAX] == 1) { + if ((val & HX_INSPECT_ELPWUG_NOISE) == HX_INSPECT_ELPWUG_NOISE) + seq_puts(s, " Check LPWUG NOISE Fail\n"); + else + seq_puts(s, " Check LPWUG NOISE OK\n"); + } + if (g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MIN] == 1 && g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MAX] == 1) { + if ((val & HX_INSPECT_ELPWUG_IDLE_RAW) == HX_INSPECT_ELPWUG_IDLE_RAW) + seq_puts(s, " Check LPWUG IDLE RAW Fail\n"); + else + seq_puts(s, " Check LPWUG IDLE RAW OK\n"); + } + if (g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MIN] == 1 && g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MAX] == 1) { + if ((val & HX_INSPECT_ELPWUG_IDLE_NOISE) == HX_INSPECT_ELPWUG_IDLE_NOISE) + seq_puts(s, " Check LPWUG IDLE NOISE Fail\n"); + else + seq_puts(s, " Check LPWUG IDLE NOISE OK\n"); + } +#endif + +END_FUNC: + private_ts->in_self_test = 0; + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_INSPECT + if (g_inspt_crtra_flag != NULL) { + kfree(g_inspt_crtra_flag); + g_inspt_crtra_flag = NULL; + } +#endif + +#ifdef HX_ESD_RECOVERY + HX_ESD_RESET_ACTIVATE = 1; +#endif + himax_int_enable(1);/* enable irq */ + + return ret; +} + +static void *himax_self_test_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos >= 1) + return NULL; + + + return (void *)((unsigned long) *pos + 1); +} + +static void *himax_self_test_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + return NULL; +} + +static void himax_self_test_seq_stop(struct seq_file *s, void *v) +{ +} + +static ssize_t himax_self_test_write(struct file *filp, const char __user *buff, + size_t len, loff_t *data) +{ + char buf[80]; + + if (len >= 80) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + if (buf[0] == 'r') { + chip_test_r_flag = true; + I("%s: Start to read chip test data.\n", __func__); + } else { + chip_test_r_flag = false; + I("%s: Back to do self test.\n", __func__); + } + + return len; +} + +static int himax_self_test_seq_read(struct seq_file *s, void *v) +{ + size_t ret = 0; + + if (chip_test_r_flag) { +#ifdef CONFIG_TOUCHSCREEN_HIMAX_INSPECT + if (g_rslt_data) + seq_printf(s, "%s", g_rslt_data); + else +#endif + seq_puts(s, "No chip test data.\n"); + } else { + himax_self_test(s, v); + } + + return ret; +} + +static const struct seq_operations himax_self_test_seq_ops = { + .start = himax_self_test_seq_start, + .next = himax_self_test_seq_next, + .stop = himax_self_test_seq_stop, + .show = himax_self_test_seq_read, +}; + +static int himax_self_test_proc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &himax_self_test_seq_ops); +}; + +static const struct file_operations himax_proc_self_test_ops = { + .owner = THIS_MODULE, + .open = himax_self_test_proc_open, + .read = seq_read, + .write = himax_self_test_write, + .release = seq_release, +}; +#endif + +#ifdef HX_HIGH_SENSE +static ssize_t himax_HSEN_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + size_t count = 0; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL); + count = snprintf(temp_buf, PAGE_SIZE, "%d\n", ts->HSEN_enable); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } else { + HX_PROC_SEND_FLAG = 0; + } + + return count; +} + +static ssize_t himax_HSEN_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf[80] = {0}; + + if (len >= 80) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + if (buf[0] == '0') + ts->HSEN_enable = 0; + else if (buf[0] == '1') + ts->HSEN_enable = 1; + else + return -EINVAL; + + g_core_fp.fp_set_HSEN_enable(ts->HSEN_enable, ts->suspended); + I("%s: HSEN_enable = %d.\n", __func__, ts->HSEN_enable); + return len; +} + +static const struct file_operations himax_proc_HSEN_ops = { + .owner = THIS_MODULE, + .read = himax_HSEN_read, + .write = himax_HSEN_write, +}; +#endif + +#ifdef HX_SMART_WAKEUP +static ssize_t himax_SMWP_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + size_t count = 0; + struct himax_ts_data *ts = private_ts; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL); + count = snprintf(temp_buf, PAGE_SIZE, "%d\n", ts->SMWP_enable); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } else { + HX_PROC_SEND_FLAG = 0; + } + + return count; +} + +static ssize_t himax_SMWP_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf[80] = {0}; + + if (len >= 80) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + if (buf[0] == '0') + ts->SMWP_enable = 0; + else if (buf[0] == '1') + ts->SMWP_enable = 1; + else + return -EINVAL; + + g_core_fp.fp_set_SMWP_enable(ts->SMWP_enable, ts->suspended); + HX_SMWP_EN = ts->SMWP_enable; + I("%s: SMART_WAKEUP_enable = %d.\n", __func__, HX_SMWP_EN); + return len; +} + +static const struct file_operations himax_proc_SMWP_ops = { + .owner = THIS_MODULE, + .read = himax_SMWP_read, + .write = himax_SMWP_write, +}; + +static ssize_t himax_GESTURE_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + int i = 0; + size_t ret = 0; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL); + + for (i = 0; i < GEST_SUP_NUM; i++) + ret += snprintf(temp_buf + ret, len - ret, "ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } else { + HX_PROC_SEND_FLAG = 0; + ret = 0; + } + + return ret; +} + +static ssize_t himax_GESTURE_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + int i = 0; + int j = 0; + char buf[80] = {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("himax_GESTURE_store= %s, len = %d\n", buf, (int)len); + + for (i = 0; i < len; i++) { + if (buf[i] == '0' && j < GEST_SUP_NUM) { + ts->gesture_cust_en[j] = 0; + I("gesture en[%d]=%d\n", j, ts->gesture_cust_en[j]); + j++; + } else if (buf[i] == '1' && j < GEST_SUP_NUM) { + ts->gesture_cust_en[j] = 1; + I("gesture en[%d]=%d\n", j, ts->gesture_cust_en[j]); + j++; + } else + I("Not 0/1 or >=GEST_SUP_NUM : buf[%d] = %c\n", i, buf[i]); + } + + return len; +} + +static const struct file_operations himax_proc_Gesture_ops = { + .owner = THIS_MODULE, + .read = himax_GESTURE_read, + .write = himax_GESTURE_write, +}; + +#ifdef HX_P_SENSOR +static ssize_t himax_psensor_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + size_t count = 0; + struct himax_ts_data *ts = private_ts; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kcalloc(len, sizeof(char), GFP_KERNEL); + count = snprintf(temp_buf, PAGE_SIZE, "p-sensor flag = %d\n", ts->psensor_flag); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } else { + HX_PROC_SEND_FLAG = 0; + } + + return count; +} + +static ssize_t himax_psensor_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf[80] = {0}; + + if (len >= 80) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + if (buf[0] == '0' && ts->SMWP_enable == 1) { + ts->psensor_flag = false; + g_core_fp.fp_black_gest_ctrl(false); + } else if (buf[0] == '1' && ts->SMWP_enable == 1) { + ts->psensor_flag = true; + g_core_fp.fp_black_gest_ctrl(true); + } else if (ts->SMWP_enable == 0) { + I("%s: SMWP is disable, not supprot to ctrl p-sensor.\n", __func__); + } else + return -EINVAL; + + I("%s: psensor_flag = %d.\n", __func__, ts->psensor_flag); + return len; +} + +static const struct file_operations himax_proc_psensor_ops = { + .owner = THIS_MODULE, + .read = himax_psensor_read, + .write = himax_psensor_write, +}; +#endif +#endif + +#ifdef HX_EDGE_LIMIT +static ssize_t himax_edge_limit_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + size_t count = 0; + struct himax_ts_data *ts = private_ts; + char *temp_buf; + + if (!HX_PROC_SEND_FLAG) { + temp_buf = kzalloc(len, GFP_KERNEL); + count = snprintf(temp_buf, PAGE_SIZE, "%d\n", ts->edge_limit_enable); + + if (copy_to_user(buf, temp_buf, len)) + I("%s,here:%d\n", __func__, __LINE__); + + kfree(temp_buf); + HX_PROC_SEND_FLAG = 1; + } else { + HX_PROC_SEND_FLAG = 0; + } + + return count; +} + +static ssize_t himax_edge_limit_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + struct himax_ts_data *ts = private_ts; + char buf[80] = {0}; + + if (len >= 80) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) { + return -EFAULT; + } + + if (buf[0] == '0') + ts->edge_limit_enable = 0; + else if (buf[0] == '1') + ts->edge_limit_enable = 1;/*Portrait*/ + else if (buf[0] == '2') + ts->edge_limit_enable = 2;/*Landscape-Right*/ + else if (buf[0] == '3') + ts->edge_limit_enable = 3;/*Landscape-Left*/ + else + return -EINVAL; + + g_core_fp.fp_set_edge_limit_enable(ts->edge_limit_enable, ts->suspended); + I("%s: edge_limit_enable = %d.\n", __func__, ts->edge_limit_enable); + return len; +} + +static struct file_operations himax_proc_edge_limit_ops = { + .owner = THIS_MODULE, + .read = himax_edge_limit_read, + .write = himax_edge_limit_write, +}; +#endif + +int himax_common_proc_init(void) +{ + himax_touch_proc_dir = proc_mkdir(HIMAX_PROC_TOUCH_FOLDER, NULL); + + if (himax_touch_proc_dir == NULL) { + E(" %s: himax_touch_proc_dir file create failed!\n", __func__); + return -ENOMEM; + } +#ifdef CONFIG_TOUCHSCREEN_HIMAX_INSPECT + if (fp_himax_self_test_init != NULL) + fp_himax_self_test_init(); +#endif + + himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE, 0664, himax_touch_proc_dir, &himax_proc_self_test_ops); + if (himax_proc_self_test_file == NULL) { + E(" %s: proc self_test file create failed!\n", __func__); + goto fail_1; + } + + himax_proc_self_raw_file = proc_create(HIMAX_PROC_SELF_TEST_RAW_FILE, 0444, himax_touch_proc_dir, &himax_proc_self_raw_ops); + if (himax_proc_self_raw_file == NULL) { + E(" %s: proc self_test raw file create failed!\n", __func__); + goto fail_1_1; + } + +#ifdef HX_HIGH_SENSE + himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, 0666, + himax_touch_proc_dir, &himax_proc_HSEN_ops); + + if (himax_proc_HSEN_file == NULL) { + E(" %s: proc HSEN file create failed!\n", __func__); + goto fail_2; + } + +#endif +#ifdef HX_SMART_WAKEUP + himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, 0666, + himax_touch_proc_dir, &himax_proc_SMWP_ops); + + if (himax_proc_SMWP_file == NULL) { + E(" %s: proc SMWP file create failed!\n", __func__); + goto fail_3; + } + + himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, 0666, + himax_touch_proc_dir, &himax_proc_Gesture_ops); + + if (himax_proc_GESTURE_file == NULL) { + E(" %s: proc GESTURE file create failed!\n", __func__); + goto fail_4; + } +#ifdef HX_P_SENSOR + himax_proc_psensor_file = proc_create(HIMAX_PROC_PSENSOR_FILE, 0666, + himax_touch_proc_dir, &himax_proc_psensor_ops); + + if (himax_proc_psensor_file == NULL) { + E(" %s: proc GESTURE file create failed!\n", __func__); + goto fail_5; + } +#endif +#endif +#ifdef HX_EDGE_LIMIT + himax_proc_edge_limit_file = proc_create(HIMAX_PROC_EDGE_LIMIT_FILE, 0666, + himax_touch_proc_dir, &himax_proc_edge_limit_ops); + + if (himax_proc_edge_limit_file == NULL) { + E(" %s: proc edge limit file create failed!\n", __func__); + goto fail_6; + } +#endif + return 0; +#ifdef HX_EDGE_LIMIT + remove_proc_entry(HIMAX_PROC_EDGE_LIMIT_FILE, himax_touch_proc_dir); +fail_6: +#endif +#ifdef HX_SMART_WAKEUP +#ifdef HX_P_SENSOR + remove_proc_entry(HIMAX_PROC_PSENSOR_FILE, himax_touch_proc_dir); +fail_5: +#endif + remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir); +fail_4: + remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir); +fail_3: +#endif +#ifdef HX_HIGH_SENSE + remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir); +fail_2: +#endif + remove_proc_entry(HIMAX_PROC_SELF_TEST_RAW_FILE, himax_touch_proc_dir); +fail_1_1: + remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir); +fail_1: + return -ENOMEM; +} + +void himax_common_proc_deinit(void) +{ +remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir); +remove_proc_entry(HIMAX_PROC_SELF_TEST_RAW_FILE, himax_touch_proc_dir); + +#ifdef HX_EDGE_LIMIT + remove_proc_entry(HIMAX_PROC_EDGE_LIMIT_FILE, himax_touch_proc_dir); +#endif +#ifdef HX_HIGH_SENSE + remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir); +#endif +#ifdef HX_SMART_WAKEUP +#ifdef HX_P_SENSOR + remove_proc_entry(HIMAX_PROC_PSENSOR_FILE, himax_touch_proc_dir); +#endif + remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir); +#endif + remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL); +} + +/* File node for SMWP and HSEN - End*/ + +int himax_input_register(struct himax_ts_data *ts) +{ + int ret = 0; +#if defined(HX_SMART_WAKEUP) + int i = 0; +#endif + ret = himax_dev_set(ts); + + if (ret < 0) { + I("%s, input device register fail!\n", __func__); + ret = INPUT_REGISTER_FAIL; + goto input_device_fail; + } + + set_bit(EV_SYN, ts->input_dev->evbit); + set_bit(EV_ABS, ts->input_dev->evbit); + set_bit(EV_KEY, ts->input_dev->evbit); +#if defined(HX_PLATFOME_DEFINE_KEY) + himax_platform_key(); +#else + set_bit(KEY_BACK, ts->input_dev->keybit); + set_bit(KEY_HOME, ts->input_dev->keybit); + set_bit(KEY_MENU, ts->input_dev->keybit); + set_bit(KEY_SEARCH, ts->input_dev->keybit); +#endif +#if defined(HX_SMART_WAKEUP) || defined(HX_PALM_REPORT) + set_bit(KEY_POWER, ts->input_dev->keybit); +#endif +#if defined(HX_SMART_WAKEUP) + for (i = 1; i < GEST_SUP_NUM; i++) + set_bit(gest_key_def[i], ts->input_dev->keybit); + +#endif + set_bit(BTN_TOUCH, ts->input_dev->keybit); + set_bit(KEY_APPSELECT, ts->input_dev->keybit); + set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); +#ifdef HX_PROTOCOL_A + /*ts->input_dev->mtsize = ts->nFinger_support;*/ + input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, 3, 0, 0); +#else + set_bit(MT_TOOL_FINGER, ts->input_dev->keybit); +#if defined(HX_PROTOCOL_B_3PA) + input_mt_init_slots(ts->input_dev, ts->nFinger_support, INPUT_MT_DIRECT); +#else + input_mt_init_slots(ts->input_dev, ts->nFinger_support); +#endif +#endif + I("input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n", + ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0); +#ifndef HX_PROTOCOL_A + input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, ts->pdata->abs_width_min, ts->pdata->abs_width_max, ts->pdata->abs_pressure_fuzz, 0); +#endif +/* input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0, ((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0); + * input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0, (BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0); + */ + + if (himax_input_register_device(ts->input_dev) == 0) + ret = NO_ERR; + else + ret = INPUT_REGISTER_FAIL; + +#if defined(HX_PEN_FUNC_EN) + set_bit(EV_SYN, ts->hx_pen_dev->evbit); + set_bit(EV_ABS, ts->hx_pen_dev->evbit); + set_bit(EV_KEY, ts->hx_pen_dev->evbit); + set_bit(BTN_TOUCH, ts->hx_pen_dev->keybit); + set_bit(INPUT_PROP_DIRECT, ts->hx_pen_dev->propbit); + + set_bit(BTN_TOOL_PEN, ts->hx_pen_dev->keybit); + set_bit(BTN_TOOL_RUBBER, ts->hx_pen_dev->keybit); + + input_set_abs_params(ts->hx_pen_dev, ABS_PRESSURE, 0, 4095, 0, 0); + input_set_abs_params(ts->hx_pen_dev, ABS_DISTANCE, 0, 1, 0, 0); + input_set_abs_params(ts->hx_pen_dev, ABS_TILT_X, -60, 60, 0, 0); + input_set_abs_params(ts->hx_pen_dev, ABS_TILT_Y, -60, 60, 0, 0); + /*input_set_capability(ts->hx_pen_dev, EV_SW, SW_PEN_INSERT);*/ + input_set_capability(ts->hx_pen_dev, EV_KEY, BTN_TOUCH); + input_set_capability(ts->hx_pen_dev, EV_KEY, BTN_STYLUS); + + input_set_abs_params(ts->hx_pen_dev, ABS_X, ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0); + input_set_abs_params(ts->hx_pen_dev, ABS_Y, ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0); + + if (himax_input_register_device(ts->hx_pen_dev) == 0) + ret = NO_ERR; + else + ret = INPUT_REGISTER_FAIL; + +#endif + I("%s, input device registered.\n", __func__); + +input_device_fail: + return ret; +} +EXPORT_SYMBOL(himax_input_register); + +static void calcDataSize(void) +{ + struct himax_ts_data *ts_data = private_ts; + + ts_data->x_channel = ic_data->HX_RX_NUM; + ts_data->y_channel = ic_data->HX_TX_NUM; + ts_data->nFinger_support = ic_data->HX_MAX_PT; + + ts_data->coord_data_size = 4 * ts_data->nFinger_support; + ts_data->area_data_size = ((ts_data->nFinger_support / 4) + (ts_data->nFinger_support % 4 ? 1 : 0)) * 4; + ts_data->coordInfoSize = ts_data->coord_data_size + ts_data->area_data_size + 4; + ts_data->raw_data_frame_size = 128 - ts_data->coord_data_size - ts_data->area_data_size - 4 - 4 - 1; + + if (ts_data->raw_data_frame_size == 0) { + E("%s: could NOT calculate!\n", __func__); + return; + } + + ts_data->raw_data_nframes = ((uint32_t)ts_data->x_channel * ts_data->y_channel + + ts_data->x_channel + ts_data->y_channel) / ts_data->raw_data_frame_size + + (((uint32_t)ts_data->x_channel * ts_data->y_channel + + ts_data->x_channel + ts_data->y_channel) % ts_data->raw_data_frame_size) ? 1 : 0; + I("%s: coord_data_size: %d, area_data_size:%d, raw_data_frame_size:%d, raw_data_nframes:%d\n", __func__, ts_data->coord_data_size, ts_data->area_data_size, ts_data->raw_data_frame_size, ts_data->raw_data_nframes); +} + +static void calculate_point_number(void) +{ + HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4; + + if ((ic_data->HX_MAX_PT % 4) == 0) + HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4; + else + HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) + 1) * 4; +} +#if defined(HX_AUTO_UPDATE_FW) +static int himax_auto_update_check(void) +{ + int32_t ret; + int flag_sys_ex_is_same = 0; + + I("%s:Entering!\n", __func__); + if (g_core_fp.fp_fw_ver_bin() == 0) { + flag_sys_ex_is_same = (g_core_fp._diff_overlay_flash() != g_core_fp._diff_overlay_bin()) ? 1 : 0; + I("Now flag_sys_ex_is_same valur=%d\n", flag_sys_ex_is_same); + if (((ic_data->vendor_fw_ver < g_i_FW_VER) || (ic_data->vendor_config_ver < g_i_CFG_VER)) + || (flag_sys_ex_is_same == 1)) { + I("Need to update!\n"); + ret = NO_ERR; + } else { + E("No need to update!\n"); + ret = 1; + } + } else { + E("FW bin fail!\n"); + ret = 1; + } + + return ret; +} + +static int i_get_FW(void) +{ + int ret = 0; + const struct firmware *image = NULL; + + I("file name = %s\n", i_CTPM_firmware_name); + ret = request_firmware(&image, i_CTPM_firmware_name, private_ts->dev); + if (ret < 0) { +#if defined(__EMBEDDED_FW__) + image = &g_embedded_fw; + I("%s: Couldn't find userspace FW, use embedded FW(size:%zu) instead.\n", __func__, g_embedded_fw.size); +#else + E("%s,fail in line%d error code=%d\n", __func__, __LINE__, ret); + return OPEN_FILE_FAIL; +#endif + } + + if (image != NULL) { + i_CTPM_FW_len = image->size; + i_CTPM_FW = kcalloc(i_CTPM_FW_len, sizeof(char), GFP_KERNEL); + memcpy(i_CTPM_FW, image->data, sizeof(char)*i_CTPM_FW_len); + } else { + I("%s: i_CTPM_FW = NULL\n", __func__); + return OPEN_FILE_FAIL; + } + + if (ret >= 0) + release_firmware(image); + ret = NO_ERR; + return ret; +} +static int i_update_FW(void) +{ + int upgrade_times = 0; + uint8_t ret = 0, result = 0; + + himax_int_enable(0); + + +update_retry: + + if (i_CTPM_FW_len == FW_SIZE_32k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k(i_CTPM_FW, i_CTPM_FW_len, false); + else if (i_CTPM_FW_len == FW_SIZE_60k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k(i_CTPM_FW, i_CTPM_FW_len, false); + else if (i_CTPM_FW_len == FW_SIZE_64k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k(i_CTPM_FW, i_CTPM_FW_len, false); + else if (i_CTPM_FW_len == FW_SIZE_124k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k(i_CTPM_FW, i_CTPM_FW_len, false); + else if (i_CTPM_FW_len == FW_SIZE_128k) + ret = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k(i_CTPM_FW, i_CTPM_FW_len, false); + + if (ret == 0) { + upgrade_times++; + E("%s: TP upgrade error, upgrade_times = %d\n", __func__, upgrade_times); + + if (upgrade_times < 3) + goto update_retry; + else + result = -1; + + + } else { + g_core_fp.fp_read_FW_ver(); + g_core_fp.fp_touch_information(); + result = 1;/*upgrade success*/ + I("%s: TP upgrade OK\n", __func__); + } + + kfree(i_CTPM_FW); + i_CTPM_FW = NULL; + +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(true, false); +#else + g_core_fp.fp_sense_on(0x00); +#endif + himax_int_enable(1); + return result; +} +#endif + + +static int himax_loadSensorConfig(struct himax_i2c_platform_data *pdata) +{ + I("%s: initialization complete\n", __func__); + return NO_ERR; +} + +#ifdef HX_ESD_RECOVERY +static void himax_esd_hw_reset(void) +{ +#ifdef HX_ZERO_FLASH + int result = 0; +#endif + if (g_ts_dbg != 0) + I("%s: Entering\n", __func__); + + I("START_Himax TP: ESD - Reset\n"); + + if (private_ts->in_self_test == 1) { + I("In self test , not TP: ESD - Reset\n"); + return; + } + + g_core_fp.fp_esd_ic_reset(); +#ifdef HX_ZERO_FLASH + I("It will update fw after esd event in zero flash mode!\n"); + result = g_core_fp.fp_0f_operation_dirly(); + if (result) { + E("Something is wrong! Skip Update with zero flash!\n"); + goto ESCAPE_0F_UPDATE; + } + g_core_fp.fp_reload_disable(0); + g_core_fp.fp_sense_on(0x00); + himax_report_all_leave_event(private_ts); + himax_int_enable(1); +ESCAPE_0F_UPDATE: +#endif + I("END_Himax TP: ESD - Reset\n"); +} +#endif + +#ifdef HX_SMART_WAKEUP +#ifdef HX_GESTURE_TRACK +static void gest_pt_log_coordinate(int rx, int tx) +{ + /*driver report x y with range 0 - 255 , we scale it up to x/y pixel*/ + gest_pt_x[gest_pt_cnt] = rx * (ic_data->HX_X_RES) / 255; + gest_pt_y[gest_pt_cnt] = tx * (ic_data->HX_Y_RES) / 255; +} +#endif +static int himax_wake_event_parse(struct himax_ts_data *ts, int ts_status) +{ + uint8_t *buf = wake_event_buffer; +#ifdef HX_GESTURE_TRACK + int tmp_max_x = 0x00, tmp_min_x = 0xFFFF, tmp_max_y = 0x00, tmp_min_y = 0xFFFF; + int gest_len; +#endif + int i = 0, check_FC = 0, ret; + int j = 0, gesture_pos = 0, gesture_flag = 0; + + if (g_ts_dbg != 0) + I("%s: Entering!, ts_status=%d\n", __func__, ts_status); + + if (buf == NULL) { + ret = -ENOMEM; + goto END; + } + + memcpy(buf, hx_touch_data->hx_event_buf, hx_touch_data->event_size); + + for (i = 0; i < GEST_PTLG_ID_LEN; i++) { + for (j = 0; j < GEST_SUP_NUM; j++) { + if (buf[i] == gest_event[j]) { + gesture_flag = buf[i]; + gesture_pos = j; + break; + } + } + I("0x%2.2X ", buf[i]); + if (buf[i] == gesture_flag) { + check_FC++; + } else { + I("ID START at %x , value = 0x%2X skip the event\n", i, buf[i]); + break; + } + } + + I("Himax gesture_flag= %x\n", gesture_flag); + I("Himax check_FC is %d\n", check_FC); + + if (check_FC != GEST_PTLG_ID_LEN) { + ret = 0; + goto END; + } + + if (buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1 || + buf[GEST_PTLG_ID_LEN + 1] != GEST_PTLG_HDR_ID2) { + ret = 0; + goto END; + } + +#ifdef HX_GESTURE_TRACK + + if (buf[GEST_PTLG_ID_LEN] == GEST_PTLG_HDR_ID1 && + buf[GEST_PTLG_ID_LEN + 1] == GEST_PTLG_HDR_ID2) { + gest_len = buf[GEST_PTLG_ID_LEN + 2]; + I("gest_len = %d\n", gest_len); + i = 0; + gest_pt_cnt = 0; + I("gest doornidate start\n %s", __func__); + + while (i < (gest_len + 1) / 2) { + gest_pt_log_coordinate(buf[GEST_PTLG_ID_LEN + 4 + i * 2], buf[GEST_PTLG_ID_LEN + 4 + i * 2 + 1]); + i++; + I("gest_pt_x[%d]=%d\n", gest_pt_cnt, gest_pt_x[gest_pt_cnt]); + I("gest_pt_y[%d]=%d\n", gest_pt_cnt, gest_pt_y[gest_pt_cnt]); + gest_pt_cnt += 1; + } + + if (gest_pt_cnt) { + for (i = 0; i < gest_pt_cnt; i++) { + if (tmp_max_x < gest_pt_x[i]) + tmp_max_x = gest_pt_x[i]; + if (tmp_min_x > gest_pt_x[i]) + tmp_min_x = gest_pt_x[i]; + if (tmp_max_y < gest_pt_y[i]) + tmp_max_y = gest_pt_y[i]; + if (tmp_min_y > gest_pt_y[i]) + tmp_min_y = gest_pt_y[i]; + } + + I("gest_point x_min= %d, x_max= %d, y_min= %d, y_max= %d\n", tmp_min_x, tmp_max_x, tmp_min_y, tmp_max_y); + gest_start_x = gest_pt_x[0]; + hx_gesture_coor[0] = gest_start_x; + gest_start_y = gest_pt_y[0]; + hx_gesture_coor[1] = gest_start_y; + gest_end_x = gest_pt_x[gest_pt_cnt - 1]; + hx_gesture_coor[2] = gest_end_x; + gest_end_y = gest_pt_y[gest_pt_cnt - 1]; + hx_gesture_coor[3] = gest_end_y; + gest_width = tmp_max_x - tmp_min_x; + hx_gesture_coor[4] = gest_width; + gest_height = tmp_max_y - tmp_min_y; + hx_gesture_coor[5] = gest_height; + gest_mid_x = (tmp_max_x + tmp_min_x) / 2; + hx_gesture_coor[6] = gest_mid_x; + gest_mid_y = (tmp_max_y + tmp_min_y) / 2; + hx_gesture_coor[7] = gest_mid_y; + hx_gesture_coor[8] = gest_mid_x;/*gest_up_x*/ + hx_gesture_coor[9] = gest_mid_y - gest_height / 2; /*gest_up_y*/ + hx_gesture_coor[10] = gest_mid_x;/*gest_down_x*/ + hx_gesture_coor[11] = gest_mid_y + gest_height / 2; /*gest_down_y*/ + hx_gesture_coor[12] = gest_mid_x - gest_width / 2; /*gest_left_x*/ + hx_gesture_coor[13] = gest_mid_y; /*gest_left_y*/ + hx_gesture_coor[14] = gest_mid_x + gest_width / 2; /*gest_right_x*/ + hx_gesture_coor[15] = gest_mid_y; /*gest_right_y*/ + } + } + +#endif + + if (!ts->gesture_cust_en[gesture_pos]) { + I("%s NOT report key [%d] = %d\n", __func__, gesture_pos, gest_key_def[gesture_pos]); + g_target_report_data->SMWP_event_chk = 0; + ret = 0; + } else { + g_target_report_data->SMWP_event_chk = gest_key_def[gesture_pos]; + ret = gesture_pos; + } +END: + return ret; +} + +static void himax_wake_event_report(void) +{ + int KEY_EVENT = g_target_report_data->SMWP_event_chk; +#ifdef HIMAX_V2_SENSOR_EN + static int report_cnt = 0; +#endif + if (g_ts_dbg != 0) + I("%s: Entering!\n", __func__); + + if (KEY_EVENT) { +#ifdef HIMAX_V2_SENSOR_EN + input_report_abs(private_ts->sensor_pdata->input_sensor_dev, ABS_DISTANCE, ++report_cnt); + I("input report: %d", report_cnt); + if (report_cnt >= REPORT_MAX_COUNT) + report_cnt = 0; + input_sync(private_ts->sensor_pdata->input_sensor_dev); +#else + I(" %s SMART WAKEUP KEY event %d press\n", __func__, KEY_EVENT); + input_report_key(private_ts->input_dev, KEY_EVENT, 1); + input_sync(private_ts->input_dev); + I(" %s SMART WAKEUP KEY event %d release\n", __func__, KEY_EVENT); + input_report_key(private_ts->input_dev, KEY_EVENT, 0); + input_sync(private_ts->input_dev); +#endif + FAKE_POWER_KEY_SEND = true; +#ifdef HX_GESTURE_TRACK + I("gest_start_x= %d, gest_start_y= %d, gest_end_x= %d, gest_end_y= %d\n", gest_start_x, gest_start_y, + gest_end_x, gest_end_y); + I("gest_width= %d, gest_height= %d, gest_mid_x= %d, gest_mid_y= %d\n", gest_width, gest_height, + gest_mid_x, gest_mid_y); + I("gest_up_x= %d, gest_up_y= %d, gest_down_x= %d, gest_down_y= %d\n", hx_gesture_coor[8], hx_gesture_coor[9], + hx_gesture_coor[10], hx_gesture_coor[11]); + I("gest_left_x= %d, gest_left_y= %d, gest_right_x= %d, gest_right_y= %d\n", hx_gesture_coor[12], hx_gesture_coor[13], + hx_gesture_coor[14], hx_gesture_coor[15]); +#endif + g_target_report_data->SMWP_event_chk = 0; + } +} + +#endif + +int himax_report_data_init(void) +{ + if (hx_touch_data->hx_coord_buf != NULL) { + kfree(hx_touch_data->hx_coord_buf); + hx_touch_data->hx_coord_buf = NULL; + } + + if (hx_touch_data->hx_rawdata_buf != NULL) { + kfree(hx_touch_data->hx_rawdata_buf); + hx_touch_data->hx_rawdata_buf = NULL; + } + +#if defined(HX_SMART_WAKEUP) + hx_touch_data->event_size = g_core_fp.fp_get_touch_data_size(); + + if (hx_touch_data->hx_event_buf != NULL) { + kfree(hx_touch_data->hx_event_buf); + hx_touch_data->hx_event_buf = NULL; + } + + if (wake_event_buffer != NULL) { + kfree(wake_event_buffer); + wake_event_buffer = NULL; + } + +#endif + hx_touch_data->touch_all_size = g_core_fp.fp_get_touch_data_size(); + hx_touch_data->raw_cnt_max = ic_data->HX_MAX_PT / 4; + hx_touch_data->raw_cnt_rmd = ic_data->HX_MAX_PT % 4; + /* more than 4 fingers */ + if (hx_touch_data->raw_cnt_rmd != 0x00) { + hx_touch_data->rawdata_size = g_core_fp.fp_cal_data_len(hx_touch_data->raw_cnt_rmd, ic_data->HX_MAX_PT, hx_touch_data->raw_cnt_max); + hx_touch_data->touch_info_size = (ic_data->HX_MAX_PT + hx_touch_data->raw_cnt_max + 2) * 4; + } else { /* less than 4 fingers */ + hx_touch_data->rawdata_size = g_core_fp.fp_cal_data_len(hx_touch_data->raw_cnt_rmd, ic_data->HX_MAX_PT, hx_touch_data->raw_cnt_max); + hx_touch_data->touch_info_size = (ic_data->HX_MAX_PT + hx_touch_data->raw_cnt_max + 1) * 4; + } +#if defined(HX_PEN_FUNC_EN) + hx_touch_data->touch_info_size += PEN_INFO_SZ; +#endif + if ((ic_data->HX_TX_NUM * ic_data->HX_RX_NUM + ic_data->HX_TX_NUM + ic_data->HX_RX_NUM) % hx_touch_data->rawdata_size == 0) + hx_touch_data->rawdata_frame_size = (ic_data->HX_TX_NUM * ic_data->HX_RX_NUM + ic_data->HX_TX_NUM + ic_data->HX_RX_NUM) / hx_touch_data->rawdata_size; + else + hx_touch_data->rawdata_frame_size = (ic_data->HX_TX_NUM * ic_data->HX_RX_NUM + ic_data->HX_TX_NUM + ic_data->HX_RX_NUM) / hx_touch_data->rawdata_size + 1; + + I("%s: rawdata_frame_size = %d\n", __func__, hx_touch_data->rawdata_frame_size); + I("%s: ic_data->HX_MAX_PT:%d, hx_raw_cnt_max:%d, hx_raw_cnt_rmd:%d, g_hx_rawdata_size:%d, hx_touch_data->touch_info_size:%d\n", __func__, ic_data->HX_MAX_PT, hx_touch_data->raw_cnt_max, hx_touch_data->raw_cnt_rmd, hx_touch_data->rawdata_size, hx_touch_data->touch_info_size); + hx_touch_data->hx_coord_buf = kzalloc(sizeof(uint8_t) * (hx_touch_data->touch_info_size), GFP_KERNEL); + + if (hx_touch_data->hx_coord_buf == NULL) + goto mem_alloc_fail; + + if (g_target_report_data == NULL) { + g_target_report_data = kzalloc(sizeof(struct himax_target_report_data), GFP_KERNEL); + if (g_target_report_data == NULL) + goto mem_alloc_fail; + g_target_report_data->x = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + if (g_target_report_data->x == NULL) + goto mem_alloc_fail; + g_target_report_data->y = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + if (g_target_report_data->y == NULL) + goto mem_alloc_fail; + g_target_report_data->w = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + if (g_target_report_data->w == NULL) + goto mem_alloc_fail; + g_target_report_data->finger_id = kzalloc(sizeof(int)*(ic_data->HX_MAX_PT), GFP_KERNEL); + if (g_target_report_data->finger_id == NULL) + goto mem_alloc_fail; +#if defined(HX_PEN_FUNC_EN) + g_target_report_data->p_x = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->p_x == NULL) + goto mem_alloc_fail; + g_target_report_data->p_y = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->p_y == NULL) + goto mem_alloc_fail; + g_target_report_data->p_w = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->p_w == NULL) + goto mem_alloc_fail; + g_target_report_data->pen_id = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->pen_id == NULL) + goto mem_alloc_fail; + g_target_report_data->p_hover = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->p_hover == NULL) + goto mem_alloc_fail; + g_target_report_data->p_tilt_x = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->p_tilt_x == NULL) + goto mem_alloc_fail; + g_target_report_data->p_btn = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->p_btn == NULL) + goto mem_alloc_fail; + g_target_report_data->p_btn2 = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->p_btn2 == NULL) + goto mem_alloc_fail; + g_target_report_data->p_tilt_y = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->p_tilt_y == NULL) + goto mem_alloc_fail; + g_target_report_data->p_on = kzalloc(sizeof(int)*2, GFP_KERNEL); + if (g_target_report_data->p_on == NULL) + goto mem_alloc_fail; + +#endif + } +#ifdef HX_SMART_WAKEUP + g_target_report_data->SMWP_event_chk = 0; + wake_event_buffer = kcalloc(hx_touch_data->event_size, sizeof(uint8_t), GFP_KERNEL); + if (wake_event_buffer == NULL) + goto mem_alloc_fail; +#endif + + hx_touch_data->hx_rawdata_buf = kzalloc(sizeof(uint8_t) * (hx_touch_data->touch_all_size - hx_touch_data->touch_info_size), GFP_KERNEL); + + if (hx_touch_data->hx_rawdata_buf == NULL) + goto mem_alloc_fail; + +#if defined(HX_SMART_WAKEUP) + hx_touch_data->hx_event_buf = kzalloc(sizeof(uint8_t) * (hx_touch_data->event_size), GFP_KERNEL); + + if (hx_touch_data->hx_event_buf == NULL) + goto mem_alloc_fail; + +#endif + return NO_ERR; +mem_alloc_fail: +#if defined(HX_PEN_FUNC_EN) + kfree(g_target_report_data->p_on); + g_target_report_data->p_on = NULL; + kfree(g_target_report_data->p_tilt_y); + g_target_report_data->p_tilt_y = NULL; + kfree(g_target_report_data->p_btn2); + g_target_report_data->p_btn2 = NULL; + kfree(g_target_report_data->p_btn); + g_target_report_data->p_btn = NULL; + kfree(g_target_report_data->p_tilt_x); + g_target_report_data->p_tilt_x = NULL; + kfree(g_target_report_data->p_hover); + g_target_report_data->p_hover = NULL; + kfree(g_target_report_data->pen_id); + g_target_report_data->pen_id = NULL; + kfree(g_target_report_data->p_w); + g_target_report_data->p_w = NULL; + kfree(g_target_report_data->p_y); + g_target_report_data->p_y = NULL; + kfree(g_target_report_data->p_x); + g_target_report_data->p_x = NULL; +#endif + kfree(g_target_report_data->finger_id); + g_target_report_data->finger_id = NULL; + kfree(g_target_report_data->w); + g_target_report_data->w = NULL; + kfree(g_target_report_data->y); + g_target_report_data->y = NULL; + kfree(g_target_report_data->x); + g_target_report_data->x = NULL; + kfree(g_target_report_data); + g_target_report_data = NULL; + +#if defined(HX_SMART_WAKEUP) + kfree(wake_event_buffer); + wake_event_buffer = NULL; + kfree(hx_touch_data->hx_event_buf); + hx_touch_data->hx_event_buf = NULL; +#endif + kfree(hx_touch_data->hx_rawdata_buf); + hx_touch_data->hx_rawdata_buf = NULL; + kfree(hx_touch_data->hx_coord_buf); + hx_touch_data->hx_coord_buf = NULL; + + I("%s: Memory allocate fail!\n", __func__); + return MEM_ALLOC_FAIL; +} +EXPORT_SYMBOL(himax_report_data_init); + +void himax_report_data_deinit(void) +{ +#if defined(HX_PEN_FUNC_EN) + kfree(g_target_report_data->p_on); + g_target_report_data->p_on = NULL; + kfree(g_target_report_data->p_tilt_y); + g_target_report_data->p_tilt_y = NULL; + kfree(g_target_report_data->p_btn2); + g_target_report_data->p_btn2 = NULL; + kfree(g_target_report_data->p_btn); + g_target_report_data->p_btn = NULL; + kfree(g_target_report_data->p_tilt_x); + g_target_report_data->p_tilt_x = NULL; + kfree(g_target_report_data->p_hover); + g_target_report_data->p_hover = NULL; + kfree(g_target_report_data->pen_id); + g_target_report_data->pen_id = NULL; + kfree(g_target_report_data->p_w); + g_target_report_data->p_w = NULL; + kfree(g_target_report_data->p_y); + g_target_report_data->p_y = NULL; + kfree(g_target_report_data->p_x); + g_target_report_data->p_x = NULL; +#endif + kfree(g_target_report_data->finger_id); + g_target_report_data->finger_id = NULL; + kfree(g_target_report_data->w); + g_target_report_data->w = NULL; + kfree(g_target_report_data->y); + g_target_report_data->y = NULL; + kfree(g_target_report_data->x); + g_target_report_data->x = NULL; + kfree(g_target_report_data); + g_target_report_data = NULL; + +#if defined(HX_SMART_WAKEUP) + kfree(wake_event_buffer); + wake_event_buffer = NULL; + kfree(hx_touch_data->hx_event_buf); + hx_touch_data->hx_event_buf = NULL; +#endif + kfree(hx_touch_data->hx_rawdata_buf); + hx_touch_data->hx_rawdata_buf = NULL; + kfree(hx_touch_data->hx_coord_buf); + hx_touch_data->hx_coord_buf = NULL; +} + +/*start ts_work*/ +#if defined(HX_USB_DETECT_GLOBAL) +void himax_cable_detect_func(bool force_renew) +{ + struct himax_ts_data *ts; + + /*u32 connect_status = 0;*/ + uint8_t connect_status = 0; + + connect_status = USB_detect_flag;/* upmu_is_chr_det(); */ + ts = private_ts; + + /* I("Touch: cable status=%d, cable_config=%p, usb_connected=%d\n", connect_status, ts->cable_config, ts->usb_connected); */ + if (ts->cable_config) { + if ((connect_status != ts->usb_connected) || force_renew) { + if (connect_status) { + ts->cable_config[1] = 0x01; + ts->usb_connected = 0x01; + } else { + ts->cable_config[1] = 0x00; + ts->usb_connected = 0x00; + } + + g_core_fp.fp_usb_detect_set(ts->cable_config); + I("%s: Cable status change: 0x%2.2X\n", __func__, ts->usb_connected); + } + + /*else */ + /*I("%s: Cable status is the same as previous one, ignore.\n", __func__); */ + } +} +#endif + +static int himax_ts_work_status(struct himax_ts_data *ts) +{ + /* 1: normal, 2:SMWP */ + int result = HX_REPORT_COORD; + + hx_touch_data->diag_cmd = ts->diag_cmd; + if (hx_touch_data->diag_cmd) + result = HX_REPORT_COORD_RAWDATA; + +#ifdef HX_SMART_WAKEUP + if (atomic_read(&ts->suspend_mode) && (ts->SMWP_enable) && (!hx_touch_data->diag_cmd)) + result = HX_REPORT_SMWP_EVENT; +#endif + /* I("Now Status is %d\n", result); */ + return result; +} + +static int himax_touch_get(struct himax_ts_data *ts, uint8_t *buf, int ts_path, int ts_status) +{ + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + switch (ts_path) { + /*normal*/ + case HX_REPORT_COORD: + if ((HX_HW_RESET_ACTIVATE) +#ifdef HX_ESD_RECOVERY + || (HX_ESD_RESET_ACTIVATE) +#endif + ) { + if (!g_core_fp.fp_read_event_stack(buf, 128)) { + E("%s: can't read data from chip!\n", __func__); + ts_status = HX_TS_GET_DATA_FAIL; + } + } else { + if (!g_core_fp.fp_read_event_stack(buf, hx_touch_data->touch_info_size)) { + E("%s: can't read data from chip!\n", __func__); + ts_status = HX_TS_GET_DATA_FAIL; + } + } + break; +#if defined(HX_SMART_WAKEUP) + + /*SMWP*/ + case HX_REPORT_SMWP_EVENT: + __pm_wakeup_event(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT); + msleep(20); + g_core_fp.fp_burst_enable(0); + + if (!g_core_fp.fp_read_event_stack(buf, hx_touch_data->event_size)) { + E("%s: can't read data from chip!\n", __func__); + ts_status = HX_TS_GET_DATA_FAIL; + } + break; +#endif + case HX_REPORT_COORD_RAWDATA: + if (!g_core_fp.fp_read_event_stack(buf, 128)) { + E("%s: can't read data from chip!\n", __func__); + ts_status = HX_TS_GET_DATA_FAIL; + } + break; + default: + break; + } + + return ts_status; +} + +/* start error_control*/ +static int himax_checksum_cal(struct himax_ts_data *ts, uint8_t *buf, int ts_path, int ts_status) +{ + uint16_t check_sum_cal = 0; + int32_t i = 0; + int length = 0; + int zero_cnt = 0; + int raw_data_sel = 0; + int ret_val = ts_status; + + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + /* Normal */ + switch (ts_path) { + case HX_REPORT_COORD: + length = hx_touch_data->touch_info_size; + break; +#if defined(HX_SMART_WAKEUP) +/* SMWP */ + case HX_REPORT_SMWP_EVENT: + length = (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN); + break; +#endif + case HX_REPORT_COORD_RAWDATA: + length = hx_touch_data->touch_info_size; + break; + default: + I("%s, Neither Normal Nor SMWP error!\n", __func__); + ret_val = HX_PATH_FAIL; + goto END_FUNCTION; + } + + for (i = 0; i < length; i++) { + check_sum_cal += buf[i]; + if (buf[i] == 0x00) + zero_cnt++; + } + + if (check_sum_cal % 0x100 != 0) { + I("[HIMAX TP MSG] point data_checksum not match : check_sum_cal: 0x%02X\n", check_sum_cal); + ret_val = HX_CHKSUM_FAIL; + } else if (zero_cnt == length) { + if (ts->use_irq) + I("[HIMAX TP MSG] All Zero event\n"); + + ret_val = HX_CHKSUM_FAIL; + } else { + raw_data_sel = buf[HX_TOUCH_INFO_POINT_CNT]>>4 & 0x0F; + /*I("%s:raw_out_sel=%x , hx_touch_data->diag_cmd=%x.\n", __func__, raw_data_sel, hx_touch_data->diag_cmd);*/ + if ((raw_data_sel != 0x0F) && (raw_data_sel != hx_touch_data->diag_cmd)) {/*raw data out not match skip it*/ + /*I("%s:raw data out not match.\n", __func__);*/ + if (!hx_touch_data->diag_cmd) { + g_core_fp.fp_read_event_stack(buf, (128-hx_touch_data->touch_info_size));/*Need to clear event stack here*/ + /*I("%s: size =%d, buf[0]=%x ,buf[1]=%x, buf[2]=%x, buf[3]=%x.\n", __func__,(128-hx_touch_data->touch_info_size), buf[0], buf[1], buf[2], buf[3]);*/ + /*I("%s:also clear event stack.\n", __func__);*/ + } + ret_val = HX_READY_SERVE; + } + } + +END_FUNCTION: + if (g_ts_dbg != 0) + I("%s: END, ret_val=%d!\n", __func__, ret_val); + return ret_val; +} + +#ifdef HX_ESD_RECOVERY +#ifdef HX_ZERO_FLASH +void hx_update_dirly_0f(void) +{ + I("It will update fw after esd event in zero flash mode!\n"); + g_core_fp.fp_0f_operation_dirly(); +} +#endif +static int himax_ts_event_check(struct himax_ts_data *ts, uint8_t *buf, int ts_path, int ts_status) +{ + int hx_EB_event = 0; + int hx_EC_event = 0; + int hx_ED_event = 0; + int hx_esd_event = 0; + int hx_zero_event = 0; + int shaking_ret = 0; + + int32_t loop_i = 0; + int length = 0; + int ret_val = ts_status; + + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + /* Normal */ + switch (ts_path) { + case HX_REPORT_COORD: + length = hx_touch_data->touch_info_size; + break; +#if defined(HX_SMART_WAKEUP) +/* SMWP */ + case HX_REPORT_SMWP_EVENT: + length = (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN); + break; +#endif + case HX_REPORT_COORD_RAWDATA: + length = hx_touch_data->touch_info_size; + break; + default: + I("%s, Neither Normal Nor SMWP error!\n", __func__); + ret_val = HX_PATH_FAIL; + goto END_FUNCTION; + } + + if (g_ts_dbg != 0) + I("Now Path=%d, Now status=%d, length=%d\n", ts_path, ts_status, length); + + for (loop_i = 0; loop_i < length; loop_i++) { + if (ts_path == HX_REPORT_COORD || ts_path == HX_REPORT_COORD_RAWDATA) { + /* case 1 ESD recovery flow */ + if (buf[loop_i] == 0xEB) { + hx_EB_event++; + } else if (buf[loop_i] == 0xEC) { + hx_EC_event++; + } else if (buf[loop_i] == 0xED) { + hx_ED_event++; + } else if (buf[loop_i] == 0x00) { /* case 2 ESD recovery flow-Disable */ + hx_zero_event++; + } else { + hx_EB_event = 0; + hx_EC_event = 0; + hx_ED_event = 0; + hx_zero_event = 0; + g_zero_event_count = 0; + } + } + } + + if (hx_EB_event == length) { + hx_esd_event = length; + hx_EB_event_flag++; + I("[HIMAX TP MSG]: ESD event checked - ALL 0xEB.\n"); + } else if (hx_EC_event == length) { + hx_esd_event = length; + hx_EC_event_flag++; + I("[HIMAX TP MSG]: ESD event checked - ALL 0xEC.\n"); + } else if (hx_ED_event == length) { + hx_esd_event = length; + hx_ED_event_flag++; + I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n"); + } +/*#ifdef HX_ZERO_FLASH + * //This is for previous version(a, b) because HW pull TSIX low continuely after watchdog timeout reset + * else if (hx_zero_event == length) { + * //check zero flash status + * if (g_core_fp.fp_0f_esd_check() < 0) { + * g_zero_event_count = 6; + * I("[HIMAX TP MSG]: ESD event checked - ALL Zero in ZF.\n"); + * } else { + * I("[HIMAX TP MSG]: Status check pass in ZF.\n"); + * } + * } + *#endif + */ + else + hx_esd_event = 0; + + if ((hx_esd_event == length || hx_zero_event == length) + && (HX_HW_RESET_ACTIVATE == 0) + && (HX_ESD_RESET_ACTIVATE == 0) + && (hx_touch_data->diag_cmd == 0) + && (ts->in_self_test == 0)) { + shaking_ret = g_core_fp.fp_ic_esd_recovery(hx_esd_event, hx_zero_event, length); + + if (shaking_ret == HX_ESD_EVENT) { + himax_esd_hw_reset(); + ret_val = HX_ESD_EVENT; + } else if (shaking_ret == HX_ZERO_EVENT_COUNT) { + ret_val = HX_ZERO_EVENT_COUNT; + } else { + I("I2C running. Nothing to be done!\n"); + ret_val = HX_IC_RUNNING; + } + } else if (HX_ESD_RESET_ACTIVATE) { /* drop 1st interrupts after chip reset */ + HX_ESD_RESET_ACTIVATE = 0; + I("[HX_ESD_RESET_ACTIVATE]:%s: Back from reset, ready to serve.\n", __func__); + ret_val = HX_ESD_REC_OK; + } + +END_FUNCTION: + if (g_ts_dbg != 0) + I("%s: END, ret_val=%d!\n", __func__, ret_val); + + return ret_val; +} +#endif + +static int himax_err_ctrl(struct himax_ts_data *ts, uint8_t *buf, int ts_path, int ts_status) +{ +#ifdef HX_RST_PIN_FUNC + if (HX_HW_RESET_ACTIVATE) { + /* drop 1st interrupts after chip reset */ + HX_HW_RESET_ACTIVATE = 0; + I("[HX_HW_RESET_ACTIVATE]:%s: Back from reset, ready to serve.\n", __func__); + ts_status = HX_RST_OK; + goto END_FUNCTION; + } +#endif + + ts_status = himax_checksum_cal(ts, buf, ts_path, ts_status); + if (ts_status == HX_CHKSUM_FAIL) { + goto CHK_FAIL; + } else { +#ifdef HX_ESD_RECOVERY + /* continuous N times record, not total N times. */ + g_zero_event_count = 0; +#endif + goto END_FUNCTION; + } + +CHK_FAIL: +#ifdef HX_ESD_RECOVERY + ts_status = himax_ts_event_check(ts, buf, ts_path, ts_status); +#endif + + +END_FUNCTION: + if (g_ts_dbg != 0) + I("%s: END, ts_status=%d!\n", __func__, ts_status); + return ts_status; +} +/* end error_control*/ + +/* start distribute_data*/ +static int himax_distribute_touch_data(uint8_t *buf, int ts_path, int ts_status) +{ + uint8_t hx_state_info_pos = hx_touch_data->touch_info_size - 3; + +#if defined(HX_PEN_FUNC_EN) + hx_state_info_pos -= PEN_INFO_SZ; +#endif + + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + if (ts_path == HX_REPORT_COORD) { + memcpy(hx_touch_data->hx_coord_buf, &buf[0], hx_touch_data->touch_info_size); + + if (buf[hx_state_info_pos] != 0xFF && buf[hx_state_info_pos + 1] != 0xFF) + memcpy(hx_touch_data->hx_state_info, &buf[hx_state_info_pos], 2); + else + memset(hx_touch_data->hx_state_info, 0x00, sizeof(hx_touch_data->hx_state_info)); + + if ((HX_HW_RESET_ACTIVATE) +#ifdef HX_ESD_RECOVERY + || (HX_ESD_RESET_ACTIVATE) +#endif + ) { + memcpy(hx_touch_data->hx_rawdata_buf, &buf[hx_touch_data->touch_info_size], hx_touch_data->touch_all_size - hx_touch_data->touch_info_size); + } + } else if (ts_path == HX_REPORT_COORD_RAWDATA) { + memcpy(hx_touch_data->hx_coord_buf, &buf[0], hx_touch_data->touch_info_size); + + if (buf[hx_state_info_pos] != 0xFF && buf[hx_state_info_pos + 1] != 0xFF) + memcpy(hx_touch_data->hx_state_info, &buf[hx_state_info_pos], 2); + else + memset(hx_touch_data->hx_state_info, 0x00, sizeof(hx_touch_data->hx_state_info)); + + memcpy(hx_touch_data->hx_rawdata_buf, &buf[hx_touch_data->touch_info_size], hx_touch_data->touch_all_size - hx_touch_data->touch_info_size); +#if defined(HX_SMART_WAKEUP) + } else if (ts_path == HX_REPORT_SMWP_EVENT) { + memcpy(hx_touch_data->hx_event_buf, buf, hx_touch_data->event_size); +#endif + } else { + E("%s, Fail Path!\n", __func__); + ts_status = HX_PATH_FAIL; + } + + if (g_ts_dbg != 0) + I("%s: End, ts_status=%d!\n", __func__, ts_status); + return ts_status; +} +/* end assign_data*/ + +/* start parse_report_data*/ +int himax_parse_report_points(struct himax_ts_data *ts, int ts_path, int ts_status) +{ + int x = 0, y = 0, w = 0; +#if defined(HX_PEN_FUNC_EN) + uint8_t p_hover = 0, p_btn = 0, p_btn2 = 0; + int8_t p_tilt_x = 0, p_tilt_y = 0; + int p_x = 0, p_y = 0, p_w = 0; + static uint8_t p_p_on; +#endif + int base = 0; + int32_t loop_i = 0; + + if (g_ts_dbg != 0) + I("%s: start!\n", __func__); + +#if defined(HX_PEN_FUNC_EN) + p_p_on = 0; + base = hx_touch_data->touch_info_size - PEN_INFO_SZ; + + p_x = hx_touch_data->hx_coord_buf[base] << 8 | hx_touch_data->hx_coord_buf[base + 1]; + p_y = (hx_touch_data->hx_coord_buf[base + 2] << 8 | hx_touch_data->hx_coord_buf[base + 3]); + p_w = (hx_touch_data->hx_coord_buf[base + 4] << 8 | hx_touch_data->hx_coord_buf[base + 5]); + p_tilt_x = (int8_t)hx_touch_data->hx_coord_buf[base + 6]; + p_hover = hx_touch_data->hx_coord_buf[base + 7]; + p_btn = hx_touch_data->hx_coord_buf[base + 8]; + p_btn2 = hx_touch_data->hx_coord_buf[base + 9]; + p_tilt_y = (int8_t)hx_touch_data->hx_coord_buf[base + 10]; + + if (g_ts_dbg != 0) { + D("%s: p_x=%d, p_y=%d, p_w=%d\n", __func__, p_x, p_y, p_w); + D("%s: p_tilt_x=%d, p_hover=%d\n", __func__, p_tilt_x, p_hover); + D("%s: p_btn=%d, p_btn2=%d\n", __func__, p_btn, p_btn2); + D("%s: p_tilt_y=%d\n", __func__, p_tilt_y); + } + + if (p_x >= 0 && p_x <= ts->pdata->abs_x_max && p_y >= 0 && p_y <= ts->pdata->abs_y_max) { + g_target_report_data->p_x[0] = p_x; + g_target_report_data->p_y[0] = p_y; + g_target_report_data->p_w[0] = p_w; + g_target_report_data->p_hover[0] = p_hover; + g_target_report_data->pen_id[0] = 1; + g_target_report_data->p_btn[0] = p_btn; + g_target_report_data->p_btn2[0] = p_btn2; + g_target_report_data->p_tilt_x[0] = p_tilt_x; + g_target_report_data->p_tilt_y[0] = p_tilt_y; + g_target_report_data->p_on[0] = 1; + ts->hx_point_num++; + } else {/* report coordinates */ + g_target_report_data->p_x[0] = 0; + g_target_report_data->p_y[0] = 0; + g_target_report_data->p_w[0] = 0; + g_target_report_data->p_hover[0] = 0; + g_target_report_data->pen_id[0] = 0; + g_target_report_data->p_btn[0] = 0; + g_target_report_data->p_btn2[0] = 0; + g_target_report_data->p_tilt_x[0] = 0; + g_target_report_data->p_tilt_y[0] = 0; + g_target_report_data->p_on[0] = 0; + } + + if (g_ts_dbg != 0) { + if (p_p_on != g_target_report_data->p_on[0]) { + I("p_on[0] = %d, hx_point_num=%d\n", + g_target_report_data->p_on[0], + ts->hx_point_num); + p_p_on = g_target_report_data->p_on[0]; + } + } +#endif + + ts->old_finger = ts->pre_finger_mask; + if (ts->hx_point_num == 0) { + if (g_ts_dbg != 0) + I("%s: hx_point_num = 0!\n", __func__); + return ts_status; + } + ts->pre_finger_mask = 0; + hx_touch_data->finger_num = hx_touch_data->hx_coord_buf[ts->coordInfoSize - 4] & 0x0F; + hx_touch_data->finger_on = 1; + AA_press = 1; + + g_target_report_data->finger_num = hx_touch_data->finger_num; + g_target_report_data->finger_on = hx_touch_data->finger_on; + g_target_report_data->ig_count = hx_touch_data->hx_coord_buf[ts->coordInfoSize - 5]; + + if (g_ts_dbg != 0) + I("%s:finger_num = 0x%2X, finger_on = %d\n", __func__, g_target_report_data->finger_num, g_target_report_data->finger_on); + + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + base = loop_i * 4; + x = hx_touch_data->hx_coord_buf[base] << 8 | hx_touch_data->hx_coord_buf[base + 1]; + y = (hx_touch_data->hx_coord_buf[base + 2] << 8 | hx_touch_data->hx_coord_buf[base + 3]); + w = hx_touch_data->hx_coord_buf[(ts->nFinger_support * 4) + loop_i]; + + if (g_ts_dbg != 0) + D("%s: now parsing[%d]:x=%d, y=%d, w=%d\n", __func__, loop_i, x, y, w); + + if (x >= 0 && x <= ts->pdata->abs_x_max && y >= 0 && y <= ts->pdata->abs_y_max) { + hx_touch_data->finger_num--; + + g_target_report_data->x[loop_i] = x; + g_target_report_data->y[loop_i] = y; + g_target_report_data->w[loop_i] = w; + g_target_report_data->finger_id[loop_i] = 1; + + /*I("%s: g_target_report_data->x[loop_i]=%d, g_target_report_data->y[loop_i]=%d, g_target_report_data->w[loop_i]=%d",*/ + /*__func__, g_target_report_data->x[loop_i], g_target_report_data->y[loop_i], g_target_report_data->w[loop_i]); */ + + + if (!ts->first_pressed) { + ts->first_pressed = 1; + I("S1@%d, %d\n", x, y); + } + + ts->pre_finger_data[loop_i][0] = x; + ts->pre_finger_data[loop_i][1] = y; + + ts->pre_finger_mask = ts->pre_finger_mask + (1 << loop_i); + } else {/* report coordinates */ + g_target_report_data->x[loop_i] = x; + g_target_report_data->y[loop_i] = y; + g_target_report_data->w[loop_i] = w; + g_target_report_data->finger_id[loop_i] = 0; + + if (loop_i == 0 && ts->first_pressed == 1) { + ts->first_pressed = 2; + I("E1@%d, %d\n", ts->pre_finger_data[0][0], ts->pre_finger_data[0][1]); + } + } + } + + if (g_ts_dbg != 0) { + for (loop_i = 0; loop_i < 10; loop_i++) + D("DBG X=%d Y=%d ID=%d\n", g_target_report_data->x[loop_i], g_target_report_data->y[loop_i], g_target_report_data->finger_id[loop_i]); + + D("DBG finger number %d\n", g_target_report_data->finger_num); + } + + if (g_ts_dbg != 0) + I("%s: end!\n", __func__); + return ts_status; +} + +static int himax_parse_report_data(struct himax_ts_data *ts, int ts_path, int ts_status) +{ + + if (g_ts_dbg != 0) + I("%s: start now_status=%d!\n", __func__, ts_status); + + + EN_NoiseFilter = (hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 3); + /* I("EN_NoiseFilter=%d\n", EN_NoiseFilter); */ + EN_NoiseFilter = EN_NoiseFilter & 0x01; + /* I("EN_NoiseFilter2=%d\n", EN_NoiseFilter); */ +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) + tpd_key = (hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 4); + + /* All (VK+AA)leave */ + if (tpd_key == 0x0F) + tpd_key = 0x00; + +#endif + p_point_num = ts->hx_point_num; + + if (hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT] == 0xff) + ts->hx_point_num = 0; + else + ts->hx_point_num = hx_touch_data->hx_coord_buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f; + + + switch (ts_path) { + case HX_REPORT_COORD: + ts_status = himax_parse_report_points(ts, ts_path, ts_status); + break; + case HX_REPORT_COORD_RAWDATA: + /* touch monitor rawdata */ + if (debug_data != NULL) { + if (debug_data->fp_set_diag_cmd(ic_data, hx_touch_data)) + I("%s: raw data_checksum not match\n", __func__); + } else { + E("%s,There is no init set_diag_cmd\n", __func__); + } + ts_status = himax_parse_report_points(ts, ts_path, ts_status); + break; +#ifdef HX_SMART_WAKEUP + case HX_REPORT_SMWP_EVENT: + himax_wake_event_parse(ts, ts_status); + break; +#endif + default: + E("%s:Fail Path!\n", __func__); + ts_status = HX_PATH_FAIL; + break; + } + if (g_ts_dbg != 0) + I("%s: end now_status=%d!\n", __func__, ts_status); + return ts_status; +} + +/* end parse_report_data*/ + +static void himax_report_all_leave_event(struct himax_ts_data *ts) +{ + int loop_i = 0; + + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { +#ifndef HX_PROTOCOL_A + input_mt_slot(ts->input_dev, loop_i); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); +#endif + } + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_sync(ts->input_dev); +} + +/* start report_data */ +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) +static void himax_key_report_operation(int tp_key_index, struct himax_ts_data *ts) +{ + uint16_t x_position = 0, y_position = 0; + + if (g_ts_dbg != 0) + I("%s: Entering\n", __func__); + + if (tp_key_index != 0x00) { + I("virtual key index =%x\n", tp_key_index); + + if (tp_key_index == 0x01) { + vk_press = 1; + I("back key pressed\n"); + + if (ts->pdata->virtual_key) { + if (ts->button[0].index) { + x_position = (ts->button[0].x_range_min + ts->button[0].x_range_max) / 2; + y_position = (ts->button[0].y_range_min + ts->button[0].y_range_max) / 2; + } + +#ifdef HX_PROTOCOL_A + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); + input_mt_sync(ts->input_dev); +#else + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); +#endif + } else { + input_report_key(ts->input_dev, KEY_BACK, 1); + } + } else if (tp_key_index == 0x02) { + vk_press = 1; + I("home key pressed\n"); + + if (ts->pdata->virtual_key) { + if (ts->button[1].index) { + x_position = (ts->button[1].x_range_min + ts->button[1].x_range_max) / 2; + y_position = (ts->button[1].y_range_min + ts->button[1].y_range_max) / 2; + } + +#ifdef HX_PROTOCOL_A + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); + input_mt_sync(ts->input_dev); +#else + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); +#endif + } else { + input_report_key(ts->input_dev, KEY_HOME, 1); + } + } else if (tp_key_index == 0x04) { + vk_press = 1; + I("APP_switch key pressed\n"); + + if (ts->pdata->virtual_key) { + if (ts->button[2].index) { + x_position = (ts->button[2].x_range_min + ts->button[2].x_range_max) / 2; + y_position = (ts->button[2].y_range_min + ts->button[2].y_range_max) / 2; + } + +#ifdef HX_PROTOCOL_A + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); + input_mt_sync(ts->input_dev); +#else + input_mt_slot(ts->input_dev, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position); +#endif + } else { + input_report_key(ts->input_dev, KEY_APPSELECT, 1); + } + } + input_sync(ts->input_dev); + } else { /*tp_key_index =0x00*/ + I("virtual key released\n"); + vk_press = 0; +#ifndef HX_PROTOCOL_A + input_mt_slot(ts->input_dev, 0); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); +#else + input_mt_sync(ts->input_dev); +#endif + input_report_key(ts->input_dev, KEY_BACK, 0); + input_report_key(ts->input_dev, KEY_HOME, 0); + input_report_key(ts->input_dev, KEY_APPSELECT, 0); +#ifndef HX_PROTOCOL_A + input_sync(ts->input_dev); +#endif + } +} + +void himax_finger_report_key(struct himax_ts_data *ts) +{ + if (ts->hx_point_num != 0) { + /*Touch KEY*/ + if ((tpd_key_old != 0x00) && (tpd_key == 0x00)) { + /* temp_x[0] = 0xFFFF; + * temp_y[0] = 0xFFFF; + * temp_x[1] = 0xFFFF; + * temp_y[1] = 0xFFFF; + */ + hx_touch_data->finger_on = 0; +#ifdef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, 0); +#endif + himax_key_report_operation(tpd_key, ts); +#ifndef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, 0); +#endif + } + input_sync(ts->input_dev); + } +} + +void himax_finger_leave_key(struct himax_ts_data *ts) +{ + if (tpd_key != 0x00) { + hx_touch_data->finger_on = 1; +#ifdef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, 1); +#endif + himax_key_report_operation(tpd_key, ts); +#ifndef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, 1); +#endif + } else if ((tpd_key_old != 0x00) && (tpd_key == 0x00)) { + hx_touch_data->finger_on = 0; +#ifdef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, 0); +#endif + himax_key_report_operation(tpd_key, ts); +#ifndef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, 0); +#endif + } + input_sync(ts->input_dev); +} + +static void himax_report_key(struct himax_ts_data *ts) +{ + if (ts->hx_point_num != 0) { /* Touch KEY */ + himax_finger_report_key(ts); + } else { /* Key */ + himax_finger_leave_key(ts); + } + + tpd_key_old = tpd_key; + Last_EN_NoiseFilter = EN_NoiseFilter; +} +#endif + +/* start report_point*/ +static void himax_finger_report(struct himax_ts_data *ts) +{ + int i = 0; + bool valid = false; + + + if (g_ts_dbg != 0) { + I("%s:start\n", __func__); + I("hx_touch_data->finger_num=%d\n", hx_touch_data->finger_num); + } + for (i = 0; i < ts->nFinger_support; i++) { + if (g_target_report_data->x[i] >= 0 && g_target_report_data->x[i] <= ts->pdata->abs_x_max && g_target_report_data->y[i] >= 0 && g_target_report_data->y[i] <= ts->pdata->abs_y_max) + valid = true; + else + valid = false; + if (g_ts_dbg != 0) + I("valid=%d\n", valid); + if (valid) { + if (g_ts_dbg != 0) + I("g_target_report_data->x[i]=%d, g_target_report_data->y[i]=%d, g_target_report_data->w[i]=%d\n", g_target_report_data->x[i], g_target_report_data->y[i], g_target_report_data->w[i]); +#ifndef HX_PROTOCOL_A + input_mt_slot(ts->input_dev, i); +#else + input_report_key(ts->input_dev, BTN_TOUCH, 1); +#endif + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, g_target_report_data->w[i]); +#ifndef HX_PROTOCOL_A + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, g_target_report_data->w[i]); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, g_target_report_data->w[i]); +#else + input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i); +#endif + input_report_abs(ts->input_dev, ABS_MT_POSITION_X, g_target_report_data->x[i]); + input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, g_target_report_data->y[i]); +#ifndef HX_PROTOCOL_A + ts->last_slot = i; + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); +#else + input_mt_sync(ts->input_dev); +#endif + } else { +#ifndef HX_PROTOCOL_A + input_mt_slot(ts->input_dev, i); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); +#endif + } + } +#ifndef HX_PROTOCOL_A + input_report_key(ts->input_dev, BTN_TOUCH, 1); +#endif + input_sync(ts->input_dev); + +#if defined(HX_PEN_FUNC_EN) + valid = false; + + if (g_target_report_data->p_x[0] >= 0 && g_target_report_data->p_x[0] <= ts->pdata->abs_x_max + && g_target_report_data->p_y[0] >= 0 && g_target_report_data->p_y[0] <= ts->pdata->abs_y_max + && (g_target_report_data->p_on[0] == 1)) + valid = true; + else + valid = false; + if (g_ts_dbg != 0) + I("pen valid=%d\n", valid); + if (valid) {/*Pen down*/ + if (g_ts_dbg != 0) + I("p_x[i]=%d, p_y[i]=%d, p_w[i]=%d\n", g_target_report_data->p_x[0], g_target_report_data->p_y[0], g_target_report_data->p_w[0]); + + input_report_abs(ts->hx_pen_dev, ABS_X, g_target_report_data->p_x[0]); + input_report_abs(ts->hx_pen_dev, ABS_Y, g_target_report_data->p_y[0]); + input_report_key(ts->hx_pen_dev, BTN_STYLUS, 1); + input_report_abs(ts->hx_pen_dev, ABS_TILT_X, g_target_report_data->p_tilt_x[0]); + input_report_abs(ts->hx_pen_dev, ABS_TILT_Y, g_target_report_data->p_tilt_y[0]); + input_report_key(ts->hx_pen_dev, BTN_TOOL_PEN, 1); + if (g_target_report_data->p_hover[0] == 0) { + input_report_key(ts->hx_pen_dev, BTN_TOUCH, 1); + input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 0); + input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, g_target_report_data->p_w[0]); + } else { + input_report_key(ts->hx_pen_dev, BTN_TOUCH, 0); + input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 1); + input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0); + } + } else {/*Pen up*/ + input_report_key(ts->hx_pen_dev, BTN_STYLUS, 0); + input_report_key(ts->hx_pen_dev, BTN_TOUCH, 0); + input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0); + input_sync(ts->hx_pen_dev); + + input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 0); + input_report_key(ts->hx_pen_dev, BTN_TOOL_RUBBER, 0); + input_report_key(ts->hx_pen_dev, BTN_TOOL_PEN, 0); + input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0); + } + input_sync(ts->hx_pen_dev); + +#endif + + if (g_ts_dbg != 0) + I("%s:end\n", __func__); +} + + +#ifdef HIMAX_PALM_SENSOR_EN +static void himax_palm_detect_func(struct himax_ts_data *ts, bool detected) { + if (detected) { + I("palm detected\n"); + input_report_abs(ts->palm_sensor_pdata->input_sensor_dev, ABS_DISTANCE, 1); + } else { + I("palm leave\n"); + input_report_abs(ts->palm_sensor_pdata->input_sensor_dev, ABS_DISTANCE, 0); + } + input_sync(ts->palm_sensor_pdata->input_sensor_dev); +} +#endif + +static void himax_finger_leave(struct himax_ts_data *ts) +{ +#ifndef HX_PROTOCOL_A + int32_t loop_i = 0; +#endif + + if (g_ts_dbg != 0) + I("%s: start!\n", __func__); + +#ifndef HIMAX_PALM_SENSOR_EN +#if defined(HX_PALM_REPORT) + if (himax_palm_detect(hx_touch_data->hx_coord_buf) == PALM_REPORT) { + I(" %s HX_PALM_REPORT KEY power event press\n", __func__); + input_report_key(ts->input_dev, KEY_POWER, 1); + input_sync(ts->input_dev); + msleep(100); + + I(" %s HX_PALM_REPORT KEY power event release\n", __func__); + input_report_key(ts->input_dev, KEY_POWER, 0); + input_sync(ts->input_dev); + return; + } +#endif +#endif + + hx_touch_data->finger_on = 0; + g_target_report_data->finger_on = 0; + g_target_report_data->finger_num = 0; + AA_press = 0; + +#ifdef HX_PROTOCOL_A + input_mt_sync(ts->input_dev); +#endif +#ifndef HX_PROTOCOL_A + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + input_mt_slot(ts->input_dev, loop_i); + input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); + input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); + } +#endif + if (ts->pre_finger_mask > 0) + ts->pre_finger_mask = 0; + + if (ts->first_pressed == 1) { + ts->first_pressed = 2; + I("E1@%d, %d\n", ts->pre_finger_data[0][0], ts->pre_finger_data[0][1]); + } + + /*if (ts->debug_log_level & BIT(1)) */ + /*himax_log_touch_event(x, y, w, loop_i, EN_NoiseFilter, HX_FINGER_LEAVE); */ + + input_report_key(ts->input_dev, BTN_TOUCH, 0); + input_sync(ts->input_dev); + +#if defined(HX_PEN_FUNC_EN) + input_report_key(ts->hx_pen_dev, BTN_STYLUS, 0); + input_report_key(ts->hx_pen_dev, BTN_TOUCH, 0); + input_report_abs(ts->hx_pen_dev, ABS_PRESSURE, 0); + input_sync(ts->hx_pen_dev); + + input_report_abs(ts->hx_pen_dev, ABS_DISTANCE, 0); + input_report_abs(ts->hx_pen_dev, ABS_TILT_X, 0); + input_report_abs(ts->hx_pen_dev, ABS_TILT_Y, 0); + input_report_key(ts->hx_pen_dev, BTN_TOOL_RUBBER, 0); + input_report_key(ts->hx_pen_dev, BTN_TOOL_PEN, 0); + input_sync(ts->hx_pen_dev); +#endif + + if (g_ts_dbg != 0) + I("%s: end!\n", __func__); + + +} + +static void himax_report_points(struct himax_ts_data *ts) +{ + if (g_ts_dbg != 0) + I("%s: start!\n", __func__); + +#if defined(HX_PALM_REPORT) && defined(HIMAX_PALM_SENSOR_EN) + if (ts->palm_detection_enabled) { + if (himax_palm_detect(hx_touch_data->hx_coord_buf) == PALM_REPORT) { + del_timer(&ts->palm_release_fimer); + himax_palm_detect_func(ts, true); + return; + } else if (himax_palm_detect(hx_touch_data->hx_coord_buf) == PALM_LEAVE_REPORT) { + mod_timer(&ts->palm_release_fimer, + jiffies + msecs_to_jiffies(ts->palm_release_delay_ms)); +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_timeout(&ts->palm_gesture_wakelock, + ts->palm_release_delay_ms); +#else + __pm_wakeup_event(&ts->palm_gesture_wakelock, + ts->palm_release_delay_ms); +#endif + return; + } else if (ts->suspended) + return; + } +#endif + if (ts->hx_point_num != 0) + himax_finger_report(ts); + else + himax_finger_leave(ts); + + Last_EN_NoiseFilter = EN_NoiseFilter; + + if (g_ts_dbg != 0) + I("%s: end!\n", __func__); +} +/* end report_points*/ + +int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status) +{ + if (g_ts_dbg != 0) + I("%s: Entering, ts_status=%d!\n", __func__, ts_status); + + if (ts_path == HX_REPORT_COORD || ts_path == HX_REPORT_COORD_RAWDATA) { + /* Touch Point information */ + himax_report_points(ts); + +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) + /*report key(question mark)*/ + if (tpd_key && tpd_key_old) + himax_report_key(ts); + +#endif +#ifdef HX_SMART_WAKEUP + } else if (ts_path == HX_REPORT_SMWP_EVENT) { + himax_wake_event_report(); +#endif + } else { + E("%s:Fail Path!\n", __func__); + ts_status = HX_PATH_FAIL; + } + + if (g_ts_dbg != 0) + I("%s: END, ts_status=%d!\n", __func__, ts_status); + return ts_status; +} +/* end report_data */ + +static int himax_ts_operation(struct himax_ts_data *ts, int ts_path, int ts_status) +{ + uint8_t hw_reset_check[2]; + + memset(ts->xfer_buff, 0x00, 128 * sizeof(uint8_t)); + memset(hw_reset_check, 0x00, sizeof(hw_reset_check)); + + ts_status = himax_touch_get(ts, ts->xfer_buff, ts_path, ts_status); + if (ts_status == HX_TS_GET_DATA_FAIL) + goto END_FUNCTION; + + ts_status = himax_distribute_touch_data(ts->xfer_buff, ts_path, ts_status); + ts_status = himax_err_ctrl(ts, ts->xfer_buff, ts_path, ts_status); + if (ts_status == HX_REPORT_DATA || ts_status == HX_TS_NORMAL_END) + ts_status = himax_parse_report_data(ts, ts_path, ts_status); + else + goto END_FUNCTION; + + + ts_status = himax_report_data(ts, ts_path, ts_status); + + +END_FUNCTION: + return ts_status; +} + +#ifdef HIMAX_PALM_SENSOR_EN +static void himax_palm_sensor_release_timer_handler(unsigned long data) +{ + himax_palm_detect_func(private_ts, false); +} + +static int _himax_palm_detect_sensor_set_enable(unsigned int enable) +{ + I("Gesture set enable %d!", enable); +/* + * If palm detect function is enabled, interrupt will not disable, IC works in + * normal mode. But in case touch event is reported to input subsystem, skip + * touch event when suspend flag is true. So input subsystem will not take + * wakelock because no one report event. + * In this case, we still need read data from IC, so AP can not enter suspend. + */ + if (enable == 1) { +#ifdef CONFIG_HAS_WAKELOCK + wake_lock(&private_ts->palm_gesture_read_wakelock); +#else + __pm_stay_awake(&private_ts->palm_gesture_read_wakelock); +#endif + g_core_fp.fp_palm_detection_function(1); + private_ts->palm_detection_enabled = true; + } else if (enable == 0) { + if (timer_pending(&private_ts->palm_release_fimer)) { + himax_palm_detect_func(private_ts, false); + del_timer(&private_ts->palm_release_fimer); + } + g_core_fp.fp_palm_detection_function(0); + private_ts->palm_detection_enabled = false; +#ifdef CONFIG_HAS_WAKELOCK + wake_unlock(&private_ts->palm_gesture_read_wakelock); +#else + __pm_relax(&private_ts->palm_gesture_read_wakelock); +#endif + } else + E("unknown enable symbol\n"); + + return 0; +} + +static int himax_palm_detect_sensor_set_enable(struct sensors_classdev *sensors_cdev, + unsigned int enable) +{ + int ret = 0; + + mutex_lock(&private_ts->suspend_resume_mutex); + if (!private_ts->suspended) + ret = _himax_palm_detect_sensor_set_enable(enable); + else { + I("Gesture lazy set enable %d!", enable); + if (enable == 1) + private_ts->palm_detection_lazy_set = PALM_SENSOR_LAZY_SET_ENABLE; + else if (enable == 0) + private_ts->palm_detection_lazy_set = PALM_SENSOR_LAZY_SET_DISABLE; + else + E("unknown enable symbol\n"); + } + mutex_unlock(&private_ts->suspend_resume_mutex); + himax_palm_detect_func(private_ts, false); + + return ret; +} + +static int himax_palm_detect_sensor_init(struct himax_ts_data *data) +{ + struct himax_sensor_platform_data *sensor_pdata; + struct input_dev *sensor_input_dev; + int err; + + sensor_input_dev = input_allocate_device(); + if (!sensor_input_dev) { + E("Failed to allocate device"); + goto exit; + } + + sensor_pdata = devm_kzalloc(&sensor_input_dev->dev, + sizeof(struct himax_sensor_platform_data), + GFP_KERNEL); + if (!sensor_pdata) { + E("Failed to allocate memory"); + goto free_sensor_pdata; + } + data->palm_sensor_pdata = sensor_pdata; + + __set_bit(EV_ABS, sensor_input_dev->evbit); + __set_bit(EV_SYN, sensor_input_dev->evbit); + input_set_abs_params(sensor_input_dev, ABS_DISTANCE, + 0, 5, 0, 0); + sensor_input_dev->name = "palm_detect"; + data->palm_sensor_pdata->input_sensor_dev = sensor_input_dev; + + err = input_register_device(sensor_input_dev); + if (err) { + E("Unable to register device, err=%d", err); + goto free_sensor_input_dev; + } + + sensor_pdata->ps_cdev = palm_sensors_touch_cdev; + sensor_pdata->ps_cdev.sensors_enable = himax_palm_detect_sensor_set_enable; + sensor_pdata->data = data; + + err = sensors_classdev_register(&sensor_input_dev->dev, + &sensor_pdata->ps_cdev); + if (err) + goto unregister_sensor_input_device; + +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_init(&data->palm_gesture_wakelock, WAKE_LOCK_SUSPEND, "palm_detect_wl"); +#else + wakeup_source_init(&data->palm_gesture_wakelock, "palm_detect_wl"); +#endif +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_init(&data->palm_gesture_read_wakelock, WAKE_LOCK_SUSPEND, "palm_read_wl"); +#else + wakeup_source_init(&data->palm_gesture_read_wakelock, "palm_read_wl"); +#endif + + data->palm_release_fimer.function = himax_palm_sensor_release_timer_handler; + init_timer(&data->palm_release_fimer); + data->palm_release_delay_ms = 850; + + return 0; + +unregister_sensor_input_device: + input_unregister_device(data->palm_sensor_pdata->input_sensor_dev); +free_sensor_input_dev: + input_free_device(data->palm_sensor_pdata->input_sensor_dev); +free_sensor_pdata: + devm_kfree(&sensor_input_dev->dev, sensor_pdata); + data->palm_sensor_pdata= NULL; +exit: + return 1; +} + +int himax_palm_detect_sensor_remove(struct himax_ts_data *data) +{ + sensors_classdev_unregister(&data->palm_sensor_pdata->ps_cdev); + input_unregister_device(data->palm_sensor_pdata->input_sensor_dev); + devm_kfree(&data->palm_sensor_pdata->input_sensor_dev->dev, + data->palm_sensor_pdata); +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_destroy(&data->palm_gesture_wakelock); +#else + wakeup_source_trash(&data->palm_gesture_wakelock); +#endif +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_destroy(&data->palm_gesture_read_wakelock); +#else + wakeup_source_trash(&data->palm_gesture_read_wakelock); +#endif + data->palm_sensor_pdata = NULL; + data->palm_detection_enabled = false; + return 0; +} +#endif + +#ifdef HIMAX_V2_SENSOR_EN +static int himax_tap_detect_sensor_set_enable(struct sensors_classdev *sensors_cdev, + unsigned int enable) +{ + int ret = 0; + struct himax_ts_data *ts = private_ts; + + if (enable) { + ts->SMWP_enable = 1; + ts->gesture_cust_en[0] = 1; + I("%s,here:%d, gesture_cust_en[0] = %d\n", __func__, __LINE__, ts->gesture_cust_en[0]); + } else { + ts->SMWP_enable = 0; + ts->gesture_cust_en[0] = 0; + I("%s,here:%d, gesture_cust_en[0] = %d\n", __func__, __LINE__, ts->gesture_cust_en[0]); + } + + g_core_fp.fp_set_SMWP_enable(ts->SMWP_enable, ts->suspended); + HX_SMWP_EN = ts->SMWP_enable; + I("%s: SMART_WAKEUP_enable = %d.\n", __func__, HX_SMWP_EN); + + return ret; +} + +static int himax_tap_detect_sensor_init(struct himax_ts_data *data) +{ + struct himax_tap_sensor_platform_data *sensor_pdata; + struct input_dev *sensor_input_dev; + int err; + + sensor_input_dev = input_allocate_device(); + if (!sensor_input_dev) { + E("Failed to allocate device"); + goto exit; + } + + sensor_pdata = devm_kzalloc(&sensor_input_dev->dev, + sizeof(struct himax_tap_sensor_platform_data), + GFP_KERNEL); + if (!sensor_pdata) { + E("Failed to allocate memory"); + goto free_sensor_pdata; + } + data->sensor_pdata = sensor_pdata; + + __set_bit(EV_ABS, sensor_input_dev->evbit); + __set_bit(EV_SYN, sensor_input_dev->evbit); + input_set_abs_params(sensor_input_dev, ABS_DISTANCE, + 0, REPORT_MAX_COUNT, 0, 0); + sensor_input_dev->name = "double-tap"; + data->sensor_pdata->input_sensor_dev = sensor_input_dev; + + err = input_register_device(sensor_input_dev); + if (err) { + E("Unable to register device, err=%d", err); + goto free_sensor_input_dev; + } + + sensor_pdata->ps_cdev = sensors_touch_cdev; + sensor_pdata->ps_cdev.sensors_enable = himax_tap_detect_sensor_set_enable; + sensor_pdata->data = data; + + err = sensors_classdev_register(&sensor_input_dev->dev, + &sensor_pdata->ps_cdev); + if (err) + goto unregister_sensor_input_device; + + return 0; + +unregister_sensor_input_device: + input_unregister_device(data->sensor_pdata->input_sensor_dev); +free_sensor_input_dev: + input_free_device(data->sensor_pdata->input_sensor_dev); +free_sensor_pdata: + devm_kfree(&sensor_input_dev->dev, sensor_pdata); + data->sensor_pdata= NULL; +exit: + return 1; +} + +int himax_tap_detect_sensor_remove(struct himax_ts_data *data) +{ + sensors_classdev_unregister(&data->sensor_pdata->ps_cdev); + input_unregister_device(data->sensor_pdata->input_sensor_dev); + devm_kfree(&data->sensor_pdata->input_sensor_dev->dev, + data->sensor_pdata); + data->sensor_pdata = NULL; + return 0; +} +#endif + +void himax_ts_work(struct himax_ts_data *ts) +{ + + int ts_status = HX_TS_NORMAL_END; + int ts_path = 0; + + if (debug_data != NULL) + debug_data->fp_ts_dbg_func(ts, HX_FINGER_ON); + +#if defined(HX_USB_DETECT_GLOBAL) + himax_cable_detect_func(false); +#endif + + ts_path = himax_ts_work_status(ts); + switch (ts_path) { + case HX_REPORT_COORD: + ts_status = himax_ts_operation(ts, ts_path, ts_status); + break; + case HX_REPORT_SMWP_EVENT: + ts_status = himax_ts_operation(ts, ts_path, ts_status); + break; + case HX_REPORT_COORD_RAWDATA: + ts_status = himax_ts_operation(ts, ts_path, ts_status); + break; + default: + E("%s:Path Fault! value=%d\n", __func__, ts_path); + goto END_FUNCTION; + } + + if (ts_status == HX_TS_GET_DATA_FAIL) + goto GET_TOUCH_FAIL; + else + goto END_FUNCTION; + +GET_TOUCH_FAIL: + I("%s: Now reset the Touch chip.\n", __func__); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, true); +#else + g_core_fp.fp_system_reset(); +#endif +#if defined(HX_ZERO_FLASH) && defined(HX83102D) + if (g_core_fp.fp_0f_reload_to_active) + g_core_fp.fp_0f_reload_to_active(); +#endif +END_FUNCTION: + if (debug_data != NULL) + debug_data->fp_ts_dbg_func(ts, HX_FINGER_LEAVE); + +} +/*end ts_work*/ +enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer) +{ + struct himax_ts_data *ts; + + + ts = container_of(timer, struct himax_ts_data, timer); + queue_work(ts->himax_wq, &ts->work); + hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL); + return HRTIMER_NORESTART; +} + +#if defined(HX_USB_DETECT_CALLBACK) +static void himax_cable_tp_status_handler_func(int connect_status) +{ + struct himax_ts_data *ts; + + I("Touch: cable change to %d\n", connect_status); + + ts = private_ts; + + if (ts->cable_config) { + if (!atomic_read(&ts->suspend_mode)) { + if (connect_status != ts->usb_connected) { + if (connect_status) { + ts->cable_config[1] = 0x01; + ts->usb_connected = 0x01; + } else { + ts->cable_config[1] = 0x00; + ts->usb_connected = 0x00; + } + + himax_bus_master_write(ts->cable_config, + sizeof(ts->cable_config), HIMAX_I2C_RETRY_TIMES); + I("%s: Cable status change: 0x%2.2X\n", __func__, ts->cable_config[1]); + } else + I("%s: Cable status is the same as previous one, ignore.\n", __func__); + } else { + if (connect_status) + ts->usb_connected = 0x01; + else + ts->usb_connected = 0x00; + + I("%s: Cable status remembered: 0x%2.2X\n", __func__, ts->usb_connected); + } + } +} + +static struct t_cable_status_notifier himax_cable_status_handler = { + .name = "usb_tp_connected", + .func = himax_cable_tp_status_handler_func, +}; + +#endif + +#ifdef HX_AUTO_UPDATE_FW +static void himax_update_register(struct work_struct *work) +{ + I(" %s in\n", __func__); + + if (i_get_FW() != 0) + return; + + if (g_auto_update_flag == true) { + I("Update FW Directly"); + goto UPDATE_FW; + } + + if (himax_auto_update_check() != 0) { + I("%s:Don't run auto update fw, so free allocated!\n", __func__); + kfree(i_CTPM_FW); + i_CTPM_FW = NULL; + return; + } + +UPDATE_FW: + if (i_update_FW() <= 0) + I("Auto update FW fail!\n"); + else + I("It have Updated\n"); + +} +#endif + +#ifndef HX_ZERO_FLASH +static int hx_chk_flash_sts(void) +{ + int rslt = 0; + uint32_t size = 0; + + I("%s: Entering\n", __func__); + if (g_core_fp._diff_overlay_flash() == 1) + size = FW_SIZE_128k; + else + size = FW_SIZE_64k; + + +#ifdef HX_AUTO_UPDATE_FW + g_auto_update_flag = (!g_core_fp.fp_calculateChecksum(false, size)); + g_auto_update_flag |= g_core_fp.fp_flash_lastdata_check(size); +#else + g_core_fp.fp_calculateChecksum(false, size); + g_core_fp.fp_flash_lastdata_check(size); +#endif + + return rslt; +} +#endif + +#if defined(CONFIG_DRM) +extern struct drm_panel *himax_active_panel; +static void himax_fb_register(struct work_struct *work) +{ + int ret = 0; + + struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work_att.work); + + + I("%s in\n", __func__); + ts->fb_notif.notifier_call = drm_notifier_callback; + if (himax_active_panel) + ret = drm_panel_notifier_register(himax_active_panel, &ts->fb_notif); + + if (ret) + E("Unable to register fb_notifier: %d\n", ret); +} +#elif defined(CONFIG_FB) +static void himax_fb_register(struct work_struct *work) +{ + int ret = 0; + + struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work_att.work); + + + I("%s in\n", __func__); + ts->fb_notif.notifier_call = fb_notifier_callback; + ret = fb_register_client(&ts->fb_notif); + + if (ret) + E("Unable to register fb_notifier: %d\n", ret); +} +#endif + +#include +#include + +/* Attribute: path (RO) */ +static ssize_t path_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + ssize_t blen; + const char *path; + + if (!ts) { + pr_err("cannot get himax_ts_data pointer\n"); + return (ssize_t)0; + } + path = kobject_get_path(&ts->dev->kobj, GFP_KERNEL); + blen = scnprintf(buf, PAGE_SIZE, "%s", path ? path : "na"); + kfree(path); + return blen; +} + +/* Attribute: vendor (RO) */ +static ssize_t vendor_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "himax"); +} + +static struct device_attribute touchscreen_attributes[] = { + __ATTR_RO(path), + __ATTR_RO(vendor), + __ATTR_NULL +}; + +#define TSDEV_MINOR_BASE 128 +#define TSDEV_MINOR_MAX 32 + +static int himax_sysfs_touchscreen( + struct himax_ts_data *ts, bool create) +{ + struct device_attribute *attrs = touchscreen_attributes; + int i, error = 0; + static struct class *touchscreen_class; + static struct device *ts_class_dev; + static int minor; + + if (create) { + minor = input_get_new_minor(0x90, + 1, false); + if (minor < 0) + minor = input_get_new_minor(TSDEV_MINOR_BASE, + TSDEV_MINOR_MAX, true); + pr_info("assigned minor %d\n", minor); + + touchscreen_class = class_create(THIS_MODULE, "touchscreen"); + if (IS_ERR(touchscreen_class)) { + error = PTR_ERR(touchscreen_class); + touchscreen_class = NULL; + return error; + } + + ts_class_dev = device_create(touchscreen_class, NULL, + MKDEV(INPUT_MAJOR, minor), + ts, "%s", ts->chip_name); + if (IS_ERR(ts_class_dev)) { + error = PTR_ERR(ts_class_dev); + ts_class_dev = NULL; + return error; + } + for (i = 0; attrs[i].attr.name != NULL; ++i) { + error = device_create_file(ts_class_dev, &attrs[i]); + if (error) + break; + } + + if (error) + goto device_destroy; + } else { + if (!touchscreen_class || !ts_class_dev) + return -ENODEV; + + for (i = 0; attrs[i].attr.name != NULL; ++i) + device_remove_file(ts_class_dev, &attrs[i]); + + device_unregister(ts_class_dev); + class_unregister(touchscreen_class); + } + + return 0; + +device_destroy: + for (--i; i >= 0; --i) + device_remove_file(ts_class_dev, &attrs[i]); + device_destroy(touchscreen_class, MKDEV(INPUT_MAJOR, minor)); + ts_class_dev = NULL; + class_unregister(touchscreen_class); + pr_err("error creating touchscreen class\n"); + + return -ENODEV; +} + +#if defined(HX_USB_DETECT_GLOBAL) +static int charger_notifier_callback(struct notifier_block *nb, + unsigned long val, void *v) { + int ret = 0; + struct power_supply *psy = NULL; + struct himax_ts_data *ts = container_of(nb, struct himax_ts_data, charger_notif); + union power_supply_propval prop; + + psy= power_supply_get_by_name("usb"); + if (!psy) { + E("Couldn't get usbpsy\n"); + return -EINVAL; + } + if (!strcmp(psy->desc->name, "usb")) { + if (psy && ts && val == POWER_SUPPLY_PROP_STATUS) { + ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT,&prop); + if (ret < 0) { + E("Couldn't get POWER_SUPPLY_PROP_ONLINE rc=%d\n", ret); + return ret; + } else { + USB_detect_flag = prop.intval; + //E("usb prop.intval =%d\n", prop.intval); + } + } + } + return 0; +} +#endif + +#if defined(HX_RESUME_SET_FW) +void himax_resume_work_func(struct work_struct *work) +{ + struct himax_ts_data *ts = private_ts; + himax_chip_common_resume(ts); + return; +} +#endif +int himax_chip_common_init(void) +{ + + int i = 0, ret = 0, err = 0, idx = 0; + struct himax_ts_data *ts = private_ts; + struct himax_i2c_platform_data *pdata; + struct himax_chip_entry *entry; + + I("Prepare kernel fp\n"); + kp_getname_kernel = (void *)kallsyms_lookup_name("getname_kernel"); + if (!kp_getname_kernel) { + E("prepare kp_getname_kernel failed!\n"); + /*goto err_dt_platform_data_fail;*/ + } + kp_file_open_name = (void *)kallsyms_lookup_name("file_open_name"); + if (!kp_file_open_name) { + E("prepare kp_file_open_name failed!\n"); + goto err_dt_platform_data_fail; + } +#if defined(__EMBEDDED_FW__) + g_embedded_fw.size = (size_t)_binary___Himax_firmware_bin_end - + (size_t)_binary___Himax_firmware_bin_start; +#endif + ts->xfer_buff = devm_kzalloc(ts->dev, 128 * sizeof(uint8_t), GFP_KERNEL); + if (ts->xfer_buff == NULL) { + err = -ENOMEM; + goto err_dt_platform_data_fail; + } + + I("PDATA START\n"); + pdata = kzalloc(sizeof(struct himax_i2c_platform_data), GFP_KERNEL); + + if (pdata == NULL) { /*Allocate Platform data space*/ + err = -ENOMEM; + goto err_dt_platform_data_fail; + } + + I("ic_data START\n"); + ic_data = kzalloc(sizeof(struct himax_ic_data), GFP_KERNEL); + if (ic_data == NULL) { /*Allocate IC data space*/ + err = -ENOMEM; + goto err_dt_ic_data_fail; + } + + /* allocate report data */ + hx_touch_data = kzalloc(sizeof(struct himax_report_data), GFP_KERNEL); + if (hx_touch_data == NULL) { + err = -ENOMEM; + goto err_alloc_touch_data_failed; + } + + if (himax_parse_dt(ts, pdata) < 0) { + I(" pdata is NULL for DT\n"); + goto err_alloc_dt_pdata_failed; + } + +#ifdef HX_RST_PIN_FUNC + ts->rst_gpio = pdata->gpio_reset; +#endif + if (himax_gpio_power_config(pdata)) { + err = -1; + E("%s: himax_gpio_power_config failed, stop Himax probe\n", __func__); + goto err_himax_gpio_power_config_failed; + } +#ifndef CONFIG_OF + + if (pdata->power) { + ret = pdata->power(1); + + if (ret < 0) { + E("%s: power on failed\n", __func__); + goto err_power_failed; + } + } + +#endif + + i_CTPM_firmware_name = kzalloc(HIMAX_FILE_NAME_LENGTH, GFP_KERNEL); + if (!i_CTPM_firmware_name) { + E("%s: alloc i_CTPM_firmware_name failed\n", __func__); + goto firmware_name_alloc_failed; + } + if (pdata->panel_supplier[0]) + snprintf(i_CTPM_firmware_name, HIMAX_FILE_NAME_LENGTH, "%s_Himax_firmware.bin", + pdata->panel_supplier); + else + snprintf(i_CTPM_firmware_name, HIMAX_FILE_NAME_LENGTH, "Himax_firmware.bin"); + + g_hx_chip_inited = 0; + idx = himax_get_ksym_idx(); + if (idx >= 0) { + if (isEmpty(idx) != 0) { + I("%s: no chip registered, please insmod ic.ko!\n", + __func__); + goto error_ic_detect_failed; + } + entry = get_chip_entry_by_index(idx); + + for (i = 0; i < entry->hx_ic_dt_num; i++) { + if (entry->core_chip_dt[i].fp_chip_detect != NULL) { + if (entry->core_chip_dt[i].fp_chip_detect() + == true) { + I("%s: chip detect found! list_num=%d\n" + , __func__, i); + goto found_hx_chip; + } else { + I("%s: num=%d chip detect NOT found! goto Next\n", __func__, i); + continue; + } + } + } + } else { + I("%s: No available chip exist!\n", __func__); + goto error_ic_detect_failed; + } + + if (i == entry->hx_ic_dt_num) { + E("%s: chip detect failed!\n", __func__); + goto error_ic_detect_failed; + } +found_hx_chip: + if (g_core_fp.fp_chip_init != NULL) { + g_core_fp.fp_chip_init(); + } else { + E("%s: function point of chip_init is NULL!\n", __func__); + goto error_ic_detect_failed; + } + + if (pdata->virtual_key) + ts->button = pdata->virtual_key; + +#ifndef HX_ZERO_FLASH + g_core_fp.fp_read_FW_ver(); + hx_chk_flash_sts(); +#endif + +#ifdef HX_AUTO_UPDATE_FW + if (g_auto_update_flag) + goto FW_force_upgrade; +#endif + + +#ifdef HX_AUTO_UPDATE_FW +FW_force_upgrade: + ts->himax_update_wq = create_singlethread_workqueue("HMX_update_reuqest"); + if (!ts->himax_update_wq) { + E(" allocate himax_update_wq failed\n"); + err = -ENOMEM; + goto err_update_wq_failed; + } + INIT_DELAYED_WORK(&ts->work_update, himax_update_register); + queue_delayed_work(ts->himax_update_wq, &ts->work_update, msecs_to_jiffies(2000)); +#endif +#ifdef HX_ZERO_FLASH + g_auto_update_flag = true; + ts->himax_0f_update_wq = create_singlethread_workqueue("HMX_0f_update_reuqest"); + if (!ts->himax_0f_update_wq) { + E(" allocate himax_0f_update_wq failed\n"); + err = -ENOMEM; + goto err_0f_update_wq_failed; + } + INIT_DELAYED_WORK(&ts->work_0f_update, g_core_fp.fp_0f_operation); + queue_delayed_work(ts->himax_0f_update_wq, &ts->work_0f_update, msecs_to_jiffies(2000)); +#endif + +#ifdef HX_RESUME_SET_FW + ts->ts_int_workqueue = create_singlethread_workqueue("himax_ts_resume_wq"); + if (!ts->ts_int_workqueue) { + E("%s: create ts_resume workqueue failed\n", __func__); + goto err_create_ts_resume_wq_failed; + } +#if defined(__HIMAX_HX83102D_MOD__) + INIT_DELAYED_WORK(&ts->ts_int_work, himax_resume_work_func); +#else + INIT_WORK(&ts->ts_int_work, himax_resume_work_func); +#endif +#endif + /*Himax Power On and Load Config*/ + if (himax_loadSensorConfig(pdata)) { + E("%s: Load Sesnsor configuration failed, unload driver.\n", __func__); + goto err_detect_failed; + } + + g_core_fp.fp_power_on_init(); + calculate_point_number(); + +#ifdef CONFIG_OF + ts->power = pdata->power; +#endif + ts->pdata = pdata; + /*calculate the i2c data size*/ + calcDataSize(); + I("%s: calcDataSize complete\n", __func__); +#ifdef CONFIG_OF + ts->pdata->abs_pressure_min = 0; + ts->pdata->abs_pressure_max = 200; + ts->pdata->abs_width_min = 0; + ts->pdata->abs_width_max = 200; + pdata->cable_config[0] = 0xF0; + pdata->cable_config[1] = 0x00; +#endif + ts->suspended = false; + mutex_init(&ts->suspend_resume_mutex); +#if defined(HX_USB_DETECT_CALLBACK) || defined(HX_USB_DETECT_GLOBAL) + ts->usb_connected = 0x00; + ts->cable_config = pdata->cable_config; + ts->charger_notif.notifier_call = charger_notifier_callback; + ret = power_supply_reg_notifier(&ts->charger_notif); + if (ret) { + E("Unable to register charger_notifier: %d\n",ret); + goto err_register_charger_notify_failed; + } +#endif +#ifdef HX_PROTOCOL_A + ts->protocol_type = PROTOCOL_TYPE_A; +#else + ts->protocol_type = PROTOCOL_TYPE_B; +#endif + I("%s: Use Protocol Type %c\n", __func__, + ts->protocol_type == PROTOCOL_TYPE_A ? 'A' : 'B'); + ret = himax_input_register(ts); + + if (ret) { + E("%s: Unable to register %s input device\n", + __func__, ts->input_dev->name); + goto err_input_register_device_failed; + } + + ts->initialized = true; +#if defined(CONFIG_FB) || defined(CONFIG_DRM) + ts->himax_att_wq = create_singlethread_workqueue("HMX_ATT_reuqest"); + + if (!ts->himax_att_wq) { + E(" allocate himax_att_wq failed\n"); + err = -ENOMEM; + goto err_get_intr_bit_failed; + } + + INIT_DELAYED_WORK(&ts->work_att, himax_fb_register); + queue_delayed_work(ts->himax_att_wq, &ts->work_att, msecs_to_jiffies(15000)); +#endif + +#ifdef HX_SMART_WAKEUP + ts->SMWP_enable = 0; + wakeup_source_init(&ts->ts_SMWP_wake_lock, HIMAX_common_NAME); +#endif +#ifdef HX_HIGH_SENSE + ts->HSEN_enable = 0; +#endif + + /*touch data init*/ + err = himax_report_data_init(); + + if (err) + goto err_report_data_init_failed; + + if (himax_common_proc_init()) { + E(" %s: himax_common proc_init failed!\n", __func__); + goto err_creat_proc_file_failed; + } + himax_sysfs_touchscreen(ts, true); + +#if defined(HX_USB_DETECT_CALLBACK) + + if (ts->cable_config) + cable_detect_register_notifier(&himax_cable_status_handler); + +#endif + +#ifdef HIMAX_PALM_SENSOR_EN + if (himax_palm_detect_sensor_init(ts)) { + E(" %s: himax_palm_detect_sensor_init failed!\n", __func__); + goto err_create_palm_sensor_failed; + } +#endif + +#ifdef HIMAX_V2_SENSOR_EN + if (himax_tap_detect_sensor_init(ts)) { + E(" %s: himax_tap_detect_sensor_init failed!\n", __func__); + goto err_create_tap_sensor_failed; + } +#endif + + himax_ts_register_interrupt(); + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_DEBUG + if (himax_debug_init()) + E(" %s: debug initial failed!\n", __func__); +#endif + +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) + + if (g_auto_update_flag) + himax_int_enable(0); + +#endif + g_hx_chip_inited = true; + return 0; + +#ifdef HIMAX_V2_SENSOR_EN +err_create_tap_sensor_failed: +#endif +#ifdef HIMAX_PALM_SENSOR_EN +err_create_palm_sensor_failed: +#endif +err_creat_proc_file_failed: + himax_report_data_deinit(); +err_report_data_init_failed: +#ifdef HX_SMART_WAKEUP + wakeup_source_trash(&ts->ts_SMWP_wake_lock); +#endif +#if defined(CONFIG_FB) || defined(CONFIG_DRM) + cancel_delayed_work_sync(&ts->work_att); + destroy_workqueue(ts->himax_att_wq); +err_get_intr_bit_failed: +#endif +err_input_register_device_failed: + input_free_device(ts->input_dev); +err_detect_failed: +#ifdef HX_RESUME_SET_FW +#if defined(__HIMAX_HX83102D_MOD__) + cancel_delayed_work_sync(&ts->ts_int_work); +#else + cancel_work_sync(&ts->ts_int_work); +#endif + destroy_workqueue(ts->ts_int_workqueue); +err_create_ts_resume_wq_failed: +#endif +#ifdef HX_ZERO_FLASH + cancel_delayed_work_sync(&ts->work_0f_update); + destroy_workqueue(ts->himax_0f_update_wq); +err_0f_update_wq_failed: +#endif +#ifdef HX_AUTO_UPDATE_FW + if (g_auto_update_flag) { + cancel_delayed_work_sync(&ts->work_update); + destroy_workqueue(ts->himax_update_wq); + } +err_update_wq_failed: +#endif +#if defined(HX_USB_DETECT_GLOBAL) +err_register_charger_notify_failed: + if (ts->charger_notif.notifier_call) + power_supply_unreg_notifier(&ts->charger_notif); +#endif +error_ic_detect_failed: + himax_gpio_power_deconfig(pdata); +firmware_name_alloc_failed: +#ifndef CONFIG_OF +err_power_failed: +#endif +err_himax_gpio_power_config_failed: +err_alloc_dt_pdata_failed: + kfree(hx_touch_data); + hx_touch_data = NULL; +err_alloc_touch_data_failed: + kfree(ic_data); + ic_data = NULL; +err_dt_ic_data_fail: + kfree(pdata); + pdata = NULL; +err_dt_platform_data_fail: + probe_fail_flag = 1; + return err; +} + +void himax_chip_common_deinit(void) +{ + struct himax_ts_data *ts = private_ts; + + himax_ts_unregister_interrupt(); + + himax_sysfs_touchscreen(ts, false); + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_INSPECT + himax_inspect_data_clear(); +#endif + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_DEBUG + himax_debug_remove(); +#endif + + himax_common_proc_deinit(); + himax_report_data_deinit(); + +#ifdef HX_SMART_WAKEUP + wakeup_source_trash(&ts->ts_SMWP_wake_lock); +#endif +#if defined(CONFIG_DRM) + if (himax_active_panel) + if (drm_panel_notifier_unregister(himax_active_panel, &ts->fb_notif)) + E("Error occurred while unregistering drm_notifier.\n"); + cancel_delayed_work_sync(&ts->work_att); + destroy_workqueue(ts->himax_att_wq); +#elif defined(CONFIG_FB) + if (fb_unregister_client(&ts->fb_notif)) + E("Error occurred while unregistering fb_notifier.\n"); + cancel_delayed_work_sync(&ts->work_att); + destroy_workqueue(ts->himax_att_wq); +#endif + input_free_device(ts->input_dev); +#ifdef HX_ZERO_FLASH + cancel_delayed_work_sync(&ts->work_0f_update); + destroy_workqueue(ts->himax_0f_update_wq); +#endif +#ifdef HX_AUTO_UPDATE_FW + cancel_delayed_work_sync(&ts->work_update); + destroy_workqueue(ts->himax_update_wq); +#endif + himax_gpio_power_deconfig(ts->pdata); + if (himax_mcu_cmd_struct_free) + himax_mcu_cmd_struct_free(); + + kfree(hx_touch_data); + hx_touch_data = NULL; + kfree(ic_data); + ic_data = NULL; + kfree(ts->pdata->virtual_key); + ts->pdata->virtual_key = NULL; + kfree(ts->pdata); + ts->pdata = NULL; + kfree(ts); + ts = NULL; + probe_fail_flag = 0; + + I("%s: Common section deinited!\n", __func__); +} + +int _himax_chip_common_suspend(struct himax_ts_data *ts) +{ + if (ts->suspended) { + I("%s: Already suspended. Skipped.\n", __func__); + goto END; + } else { + ts->suspended = true; + I("%s: enter\n", __func__); + } + +#ifdef HIMAX_PALM_SENSOR_EN + if (ts->palm_detection_enabled) { + himax_report_all_leave_event(ts); + atomic_set(&ts->suspend_mode, 1); + I("[himax] %s: palm detect function enable, reject suspend\n", __func__); + goto END; + } +#endif + + if (debug_data != NULL && debug_data->flash_dump_going == true) { + I("[himax] %s: Flash dump is going, reject suspend\n", __func__); + goto END; + } + +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL) +#ifndef HX_RESUME_SEND_CMD + g_core_fp.fp_resend_cmd_func(ts->suspended); +#endif +#endif +#ifdef HX_SMART_WAKEUP + + if (ts->SMWP_enable) { + +#ifdef HX_CODE_OVERLAY + if (ts->in_self_test == 0) + g_core_fp.fp_0f_overlay(2, 0); +#endif + + atomic_set(&ts->suspend_mode, 1); + ts->pre_finger_mask = 0; + FAKE_POWER_KEY_SEND = false; + I("[himax] %s: SMART_WAKEUP enable, reject suspend\n", __func__); + goto END; + } + +#endif + himax_int_enable(0); + himax_report_all_leave_event(ts); + /*if (g_core_fp.fp_suspend_ic_action != NULL)*/ + /*g_core_fp.fp_suspend_ic_action();*/ + + if (!ts->use_irq) { + int32_t cancel_state; + + cancel_state = cancel_work_sync(&ts->work); + if (cancel_state) + himax_int_enable(1); + } + + /*ts->first_pressed = 0;*/ + atomic_set(&ts->suspend_mode, 1); + ts->pre_finger_mask = 0; + + if (ts->pdata) + if (ts->pdata->powerOff3V3 && ts->pdata->power) + ts->pdata->power(0); + +END: + if (ts->in_self_test == 1) + ts->suspend_resume_done = 1; + + I("%s: END\n", __func__); + + return 0; +} + +int himax_chip_common_suspend(struct himax_ts_data *ts) +{ + int ret = 0; + mutex_lock(&ts->suspend_resume_mutex); + ret = _himax_chip_common_suspend(ts); + mutex_unlock(&ts->suspend_resume_mutex); + + return ret; +} + +int _himax_chip_common_resume(struct himax_ts_data *ts) +{ +#if defined(HX_ZERO_FLASH) && defined(HX_RESUME_SET_FW) + int result = 0; +#endif + I("%s: enter\n", __func__); + + if (ts->suspended == false) { + I("%s: It had entered resume, skip this step\n", __func__); + goto END; + } else { + ts->suspended = false; + } + +#ifdef HX_ESD_RECOVERY + /* continuous N times record, not total N times. */ + g_zero_event_count = 0; +#endif + + atomic_set(&ts->suspend_mode, 0); + ts->diag_cmd = 0; +#ifdef HIMAX_PALM_SENSOR_EN + if (ts->palm_detection_enabled) { + I("[himax] %s: palm detect function enable, skip resume\n", __func__); + goto CHECK_LAZY_SET_END; + } +#endif + + if (ts->pdata) + if (ts->pdata->powerOff3V3 && ts->pdata->power) + ts->pdata->power(1); + +#ifndef HX_RESUME_SET_FW +#if defined(HX_RST_PIN_FUNC) && defined(HX_RESUME_HW_RESET) + if (g_core_fp.fp_ic_reset != NULL) + g_core_fp.fp_ic_reset(false, false); +#endif +#endif + +#if defined(HX_ZERO_FLASH) && defined(HX_RESUME_SET_FW) +#ifdef HX_SMART_WAKEUP + if (!ts->SMWP_enable) { +#endif + I("It will update fw after resume in zero flash mode!\n"); + if (g_core_fp.fp_0f_operation_dirly != NULL) { + result = g_core_fp.fp_0f_operation_dirly(); + if (result) { + E("Something is wrong! Skip Update with zero flash!\n"); + goto ESCAPE_0F_UPDATE; + } + } + if (g_core_fp.fp_reload_disable != NULL) + g_core_fp.fp_reload_disable(0); + if (g_core_fp.fp_sense_on != NULL) + g_core_fp.fp_sense_on(0x00); +#ifdef HX_SMART_WAKEUP + } +#endif +#endif +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL) + if (g_core_fp.fp_resend_cmd_func != NULL) + g_core_fp.fp_resend_cmd_func(ts->suspended); + +#ifdef HX_CODE_OVERLAY + if (ts->SMWP_enable && ts->in_self_test == 0) + g_core_fp.fp_0f_overlay(3, 0); +#endif +#endif + himax_report_all_leave_event(ts); + + if (g_core_fp.fp_sense_on != NULL) + g_core_fp.fp_resume_ic_action(); + himax_int_enable(1); +#if defined(HX_ZERO_FLASH) && defined(HX_RESUME_SET_FW) +ESCAPE_0F_UPDATE: +#endif + +#ifdef HIMAX_PALM_SENSOR_EN +CHECK_LAZY_SET_END: + if (ts->palm_detection_lazy_set != PALM_SENSOR_LAZY_SET_NONE) { + _himax_palm_detect_sensor_set_enable( + (ts->palm_detection_lazy_set == PALM_SENSOR_LAZY_SET_ENABLE) ? 1 : 0); + I("%s: Palm sensor lazy set done, clear flag.\n", __func__); + ts->palm_detection_lazy_set = PALM_SENSOR_LAZY_SET_NONE; + } +#endif +END: + if (ts->in_self_test == 1) + ts->suspend_resume_done = 1; + + I("%s: END\n", __func__); + return 0; +} + +int himax_chip_common_resume(struct himax_ts_data *ts) +{ + int ret = 0; + mutex_lock(&ts->suspend_resume_mutex); + ret = _himax_chip_common_resume(ts); + mutex_unlock(&ts->suspend_resume_mutex); + + return ret; +} + diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_common.h b/drivers/input/touchscreen/himax_v3_mmi/himax_common.h old mode 100644 new mode 100755 index 04c7cff83178..4c048f8b3e5e --- a/drivers/input/touchscreen/himax_v3_mmi/himax_common.h +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_common.h @@ -1,546 +1,589 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for common functions - * - * 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. - */ - -#ifndef HIMAX_COMMON_H -#define HIMAX_COMMON_H - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "himax_platform.h" -#include - -#if defined(CONFIG_OF) - #include -#endif - -#define HIMAX_DRIVER_VER "2.0.0.51_HTF065H035_01" - -#define FLASH_DUMP_FILE "/sdcard/HX_Flash_Dump.bin" - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) -#define HX_TP_PROC_2T2R -/*if enable, selftest works in driver*/ -/*#define HX_TP_SELF_TEST_DRIVER*/ -#endif -/*===========Himax Option function=============*/ -#define HX_RST_PIN_FUNC -#define HX_ESD_RECOVERY - -/*#define HX_NEW_EVENT_STACK_FORMAT*/ -/*#define HX_AUTO_UPDATE_FW*/ -/*#define HX_SMART_WAKEUP*/ -/*#define HX_GESTURE_TRACK*/ -#define HX_RESUME_SEND_CMD /*Need to enable on TDDI chipset*/ -/*#define HX_HIGH_SENSE*/ -/*#define HX_PALM_REPORT*/ -/*#define HX_USB_DETECT_GLOBAL*/ - -/* for MTK special platform.If turning on, - * it will report to system by using specific format. - */ -/*#define HX_PROTOCOL_A*/ -#define HX_PROTOCOL_B_3PA - -#define HX_ZERO_FLASH - -/*system suspend-chipset power off, - *oncell chipset need to enable the definition - */ -/*#define HX_RESUME_HW_RESET*/ - -/*for Himax auto-motive chipset - */ -/*#define HX_PON_PIN_SUPPORT*/ - -/*=============================================*/ - -/* Enable it if driver go into suspend/resume twice */ -/*#undef HX_CONFIG_FB*/ - -/* Enable it if driver go into suspend/resume twice */ -/*#undef CONFIG_DRM*/ - -#if defined(HX_CONFIG_FB) -#include -#include -#elif defined(CONFIG_DRM) -#include -#include -#endif - -#define HX_USE_KSYM -#if defined(__HIMAX_MOD__) -#if !defined(HX_USE_KSYM) || !defined(__KERNEL_KALLSYMS_ALL_ENABLED__) - #error Modulized driver must enable HX_USE_KSYM and CONFIG_KALLSYM_ALL -#endif -#endif - -#if defined(HX_ZERO_FLASH) -/* zero flash case, you need to setup the fix_touch_info of module - */ -#define HX_FIX_TOUCH_INFO -#define HX_RESUME_SET_FW -#define HX_CODE_OVERLAY -/*Independent threads run the notification chain notification function resume - */ -#define HX_CONTAINER_SPEED_UP -#else -#define HX_TP_PROC_GUEST_INFO -#endif - -#if defined(HX_AUTO_UPDATE_FW) -/* FW Auto upgrade case, you need to setup the fix_touch_info of module - */ -#define HX_FIX_TOUCH_INFO -#endif - -#if defined(HX_SMART_WAKEUP) -/*This feature need P-sensor driver notified, and FW need to support - */ -/*#define HX_ULTRA_LOW_POWER*/ -#endif - -#if defined(HX_CONTAINER_SPEED_UP) -/*Resume queue delay work time after LCM RST (unit:ms) - */ -#define DELAY_TIME 40 -#endif - -#if defined(HX_CONFIG_FB) -int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data); -#elif defined(CONFIG_DRM) -int drm_notifier_callback(struct notifier_block *self, - unsigned long event, void *data); -#endif - -#define HX_MAX_WRITE_SZ (64 * 1024 + 4) - -#define HX_KEY_MAX_COUNT 4 -#define DEFAULT_RETRY_CNT 3 - -#define HX_85XX_A_SERIES_PWON "HX85xxA" -#define HX_85XX_B_SERIES_PWON "HX85xxB" -#define HX_85XX_C_SERIES_PWON "HX85xxC" -#define HX_85XX_D_SERIES_PWON "HX85xxD" -#define HX_85XX_E_SERIES_PWON "HX85xxE" -#define HX_85XX_ES_SERIES_PWON "HX85xxES" -#define HX_85XX_F_SERIES_PWON "HX85xxF" -#define HX_85XX_H_SERIES_PWON "HX85xxH" -#define HX_83100A_SERIES_PWON "HX83100A" -#define HX_83102A_SERIES_PWON "HX83102A" -#define HX_83102B_SERIES_PWON "HX83102B" -#define HX_83102D_SERIES_PWON "HX83102D" -#define HX_83102E_SERIES_PWON "HX83102E" -#define HX_83103A_SERIES_PWON "HX83103A" -#define HX_83106A_SERIES_PWON "HX83106A" -#define HX_83110A_SERIES_PWON "HX83110A" -#define HX_83110B_SERIES_PWON "HX83110B" -#define HX_83111B_SERIES_PWON "HX83111B" -#define HX_83112A_SERIES_PWON "HX83112A" -#define HX_83112B_SERIES_PWON "HX83112B" -#define HX_83113A_SERIES_PWON "HX83113A" -#define HX_83112D_SERIES_PWON "HX83112D" -#define HX_83112E_SERIES_PWON "HX83112E" -#define HX_83112F_SERIES_PWON "HX83112F" -#define HX_83191A_SERIES_PWON "HX83191A" -#define HX_83192A_SERIES_PWON "HX83192A" - -#define HX_TP_BIN_CHECKSUM_SW 1 -#define HX_TP_BIN_CHECKSUM_HW 2 -#define HX_TP_BIN_CHECKSUM_CRC 3 - -#define SHIFTBITS 5 - -#define FW_SIZE_32k 32768 -#define FW_SIZE_60k 61440 -#define FW_SIZE_64k 65536 -#define FW_SIZE_124k 126976 -#define FW_SIZE_128k 131072 - -#define NO_ERR 0 -#define READY_TO_SERVE 1 -#define WORK_OUT 2 -#define I2C_FAIL -1 -#define HX_INIT_FAIL -1 -#define MEM_ALLOC_FAIL -2 -#define CHECKSUM_FAIL -3 -#define GESTURE_DETECT_FAIL -4 -#define INPUT_REGISTER_FAIL -5 -#define FW_NOT_READY -6 -#define LENGTH_FAIL -7 -#define OPEN_FILE_FAIL -8 -#define PROBE_FAIL -9 -#define ERR_WORK_OUT -10 -#define ERR_STS_WRONG -11 -#define ERR_TEST_FAIL -12 -#define HW_CRC_FAIL 1 - -#define HX_FINGER_ON 1 -#define HX_FINGER_LEAVE 2 - -#if defined(HX_PALM_REPORT) -#define PALM_REPORT 1 -#define NOT_REPORT -1 -#endif - -#define PEN_INFO_SZ 12 - -#if defined(__EMBEDDED_FW__) -extern const uint8_t _binary___Himax_firmware_bin_start[]; -extern const uint8_t _binary___Himax_firmware_bin_end[]; -extern struct firmware g_embedded_fw; -#endif - -enum HX_TS_PATH { - HX_REPORT_COORD = 1, - HX_REPORT_SMWP_EVENT, - HX_REPORT_COORD_RAWDATA, -}; - -enum HX_TS_STATUS { - HX_TS_GET_DATA_FAIL = -4, - HX_ESD_EVENT, - HX_CHKSUM_FAIL, - HX_PATH_FAIL, - HX_TS_NORMAL_END = 0, - HX_ESD_REC_OK, - HX_READY_SERVE, - HX_REPORT_DATA, - HX_ESD_WARNING, - HX_IC_RUNNING, - HX_ZERO_EVENT_COUNT, - HX_RST_OK, -}; - -enum cell_type { - CHIP_IS_ON_CELL, - CHIP_IS_IN_CELL -}; -#if defined(HX_FIX_TOUCH_INFO) -enum fix_touch_info { - FIX_HX_RX_NUM = 32, - FIX_HX_TX_NUM = 18, - FIX_HX_BT_NUM = 0, - FIX_HX_X_RES = 720, - FIX_HX_Y_RES = 1600, - FIX_HX_MAX_PT = 10, - FIX_HX_XY_REVERSE = false, - FIX_HX_INT_IS_EDGE = true, -#if defined(HX_TP_PROC_2T2R) - FIX_HX_RX_NUM_2 = 0, - FIX_HX_TX_NUM_2 = 0, -#endif -}; -#endif - -#if defined(HX_ZERO_FLASH) - #define HX_SPI_OPERATION - #define HX_0F_DEBUG -#endif -struct himax_ic_data { - int vendor_fw_ver; - int vendor_config_ver; - int vendor_touch_cfg_ver; - int vendor_display_cfg_ver; - int vendor_cid_maj_ver; - int vendor_cid_min_ver; - int vendor_panel_ver; - int vendor_sensor_id; - int ic_adc_num; - uint8_t vendor_cus_info[12]; - uint8_t vendor_proj_info[12]; - uint8_t vendor_ic_id[13]; - int HX_RX_NUM; - int HX_TX_NUM; - int HX_BT_NUM; - int HX_X_RES; - int HX_Y_RES; - int HX_MAX_PT; - bool HX_XY_REVERSE; - bool HX_INT_IS_EDGE; - bool HX_PEN_FUNC; -#if defined(HX_TP_PROC_2T2R) - int HX_RX_NUM_2; - int HX_TX_NUM_2; -#endif -}; - -struct himax_virtual_key { - int index; - int keycode; - int x_range_min; - int x_range_max; - int y_range_min; - int y_range_max; -}; - -struct himax_target_report_data { - int *x; - int *y; - int *w; - int *finger_id; - int finger_on; - int finger_num; -#if defined(HX_SMART_WAKEUP) - int SMWP_event_chk; -#endif - - int32_t *p_x; - int32_t *p_y; - int32_t *p_w; - int32_t *pen_id; - uint32_t *p_hover; - int32_t *p_tilt_x; - uint32_t *p_btn; - uint32_t *p_btn2; - int32_t *p_tilt_y; - uint32_t *p_on; - int pre_p_btn; - int pre_p_btn2; - - int ig_count; - -}; - -struct himax_report_data { - int touch_all_size; - int raw_cnt_max; - int raw_cnt_rmd; - int touch_info_size; - uint8_t finger_num; - uint8_t finger_on; - uint8_t *hx_coord_buf; - uint8_t hx_state_info[2]; -#if defined(HX_SMART_WAKEUP) - int event_size; - uint8_t *hx_event_buf; -#endif - - int rawdata_size; - uint8_t diag_cmd; - uint8_t *hx_rawdata_buf; - uint8_t rawdata_frame_size; -}; - -struct himax_ts_data { - bool initialized; - bool suspended; - atomic_t suspend_mode; - uint8_t x_channel; - uint8_t y_channel; - uint8_t useScreenRes; - uint8_t diag_cmd; - char chip_name[30]; - uint8_t chip_cell_type; - - uint8_t protocol_type; - uint8_t first_pressed; - uint8_t coord_data_size; - uint8_t area_data_size; - uint8_t coordInfoSize; - uint8_t raw_data_frame_size; - uint8_t raw_data_nframes; - uint8_t nFinger_support; - uint8_t irq_enabled; - uint8_t diag_self[50]; - - uint16_t finger_pressed; - uint16_t last_slot; - uint16_t pre_finger_mask; - uint16_t old_finger; - int hx_point_num; - - - uint32_t debug_log_level; - uint32_t widthFactor; - uint32_t heightFactor; - uint32_t tw_x_min; - uint32_t tw_x_max; - uint32_t tw_y_min; - uint32_t tw_y_max; - uint32_t pl_x_min; - uint32_t pl_x_max; - uint32_t pl_y_min; - uint32_t pl_y_max; - - int rst_gpio; - int use_irq; - int (*power)(int on); - int pre_finger_data[10][2]; - - struct device *dev; - struct workqueue_struct *himax_wq; - struct work_struct work; - struct input_dev *input_dev; - - struct input_dev *hx_pen_dev; - - struct hrtimer timer; - struct i2c_client *client; - struct himax_i2c_platform_data *pdata; - struct himax_virtual_key *button; - struct mutex rw_lock; - atomic_t irq_state; - spinlock_t irq_lock; - -/******* SPI-start *******/ - struct spi_device *spi; - int hx_irq; - uint8_t *xfer_buff; -/******* SPI-end *******/ - - int in_self_test; - int suspend_resume_done; - int bus_speed; - -#if defined(HX_CONFIG_FB) || defined(CONFIG_DRM) - struct notifier_block fb_notif; - struct workqueue_struct *himax_att_wq; - struct delayed_work work_att; -#endif - - struct workqueue_struct *flash_wq; - struct work_struct flash_work; - -#if defined(HX_AUTO_UPDATE_FW) - struct workqueue_struct *himax_update_wq; - struct delayed_work work_update; -#endif - -#if defined(HX_ZERO_FLASH) - struct workqueue_struct *himax_0f_update_wq; - struct delayed_work work_0f_update; -#endif - -#if defined(HX_CONTAINER_SPEED_UP) - struct workqueue_struct *ts_int_workqueue; - struct delayed_work ts_int_work; -#endif - - struct workqueue_struct *himax_diag_wq; - struct delayed_work himax_diag_delay_wrok; - -#if defined(HX_SMART_WAKEUP) - uint8_t SMWP_enable; - uint8_t gesture_cust_en[26]; - struct wakeup_source ts_SMWP_wake_lock; -#if defined(HX_ULTRA_LOW_POWER) - bool psensor_flag; -#endif -#endif - -#if defined(HX_HIGH_SENSE) - uint8_t HSEN_enable; -#endif - -#if defined(HX_USB_DETECT_GLOBAL) - uint8_t usb_connected; - uint8_t *cable_config; -#endif - -#if defined(HX_TP_PROC_GUEST_INFO) - struct workqueue_struct *guest_info_wq; - struct work_struct guest_info_work; -#endif - - -}; - -struct himax_debug { - bool flash_dump_going; - void (*fp_ts_dbg_func)(struct himax_ts_data *ts, int start); - int (*fp_set_diag_cmd)(struct himax_ic_data *ic_data, - struct himax_report_data *hx_touch_data); -}; - -enum input_protocol_type { - PROTOCOL_TYPE_A = 0x00, - PROTOCOL_TYPE_B = 0x01, -}; - -#if defined(HX_HIGH_SENSE) - void himax_set_HSEN_func(uint8_t HSEN_enable); -#endif - -#if defined(HX_SMART_WAKEUP) -void himax_set_SMWP_func(uint8_t SMWP_enable); - -#define GEST_PTLG_ID_LEN (4) -#define GEST_PTLG_HDR_LEN (4) -#define GEST_PTLG_HDR_ID1 (0xCC) -#define GEST_PTLG_HDR_ID2 (0x44) -#define GEST_PT_MAX_NUM (128) - -extern uint8_t *wake_event_buffer; -#endif - -extern int g_mmi_refcnt; -extern int *g_inspt_crtra_flag; -extern uint32_t g_hx_chip_inited; -/*void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);*/ - -int himax_chip_common_suspend(struct himax_ts_data *ts); -int himax_chip_common_resume(struct himax_ts_data *ts); - -extern struct filename* (*kp_getname_kernel)(const char *filename); -extern struct file * (*kp_file_open_name)(struct filename *name, - int flags, umode_t mode); - -struct himax_core_fp; -extern struct himax_core_fp g_core_fp; -extern struct himax_ts_data *private_ts; -extern struct himax_ic_data *ic_data; -extern struct device *g_device; - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) - int himax_debug_init(void); - int himax_debug_remove(void); -#endif - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_INSPECT) - extern char *g_rslt_data; - extern void (*fp_himax_self_test_init)(void); -#endif - -int himax_parse_dt(struct himax_ts_data *ts, - struct himax_i2c_platform_data *pdata); -int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status); - -int himax_report_data_init(void); - -int himax_dev_set(struct himax_ts_data *ts); -int himax_input_register_device(struct input_dev *input_dev); - -#endif +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for common functions + * + * 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. + */ + +#ifndef HIMAX_COMMON_H +#define HIMAX_COMMON_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "himax_platform.h" +#include +#ifdef HIMAX_PALM_SENSOR_EN +#include +#define SENSOR_TYPE_MOTO_TOUCH_PALM (SENSOR_TYPE_DEVICE_PRIVATE_BASE + 31) +#endif +#ifdef HIMAX_V2_SENSOR_EN +#include +#endif + +#if defined(CONFIG_DRM) + #include +#elif defined(CONFIG_FB) + #include + #include +#elif defined(CONFIG_HAS_EARLYSUSPEND) + #include +#endif + +#ifdef CONFIG_OF + #include +#endif + +#define HIMAX_DRIVER_VER "2.0.0.14_ABCD1234_01" + +#define FLASH_DUMP_FILE "/sdcard/HX_Flash_Dump.bin" + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) + #define HX_TP_PROC_2T2R + /*#define HX_TP_SELF_TEST_DRIVER*/ /*if enable, selftest works in driver*/ +#endif + +#ifdef HIMAX_PALM_SENSOR_EN +struct himax_sensor_platform_data { + struct input_dev *input_sensor_dev; + struct sensors_classdev ps_cdev; + int sensor_opened; + char sensor_data; /* 0 near, 1 far */ + struct himax_ts_data *data; +}; + +enum palm_sensor_lazy_set { + PALM_SENSOR_LAZY_SET_NONE = 0, + PALM_SENSOR_LAZY_SET_ENABLE, + PALM_SENSOR_LAZY_SET_DISABLE, +}; +#endif + +#ifdef HIMAX_V2_SENSOR_EN +struct himax_tap_sensor_platform_data { + struct input_dev *input_sensor_dev; + struct sensors_classdev ps_cdev; + struct himax_ts_data *data; +}; +#endif + +/*===========Himax Option function=============*/ +#define HX_RST_PIN_FUNC +#define HX_RESUME_SEND_CMD +#define HX_ESD_RECOVERY +#define HX_TP_PROC_GUEST_INFO +/*#define HX_SHARP_ENABLE_PON*/ +/*#define HX_NEW_EVENT_STACK_FORMAT*/ +/*#define HX_AUTO_UPDATE_FW*/ +#ifdef HIMAX_V2_SENSOR_EN +#define HX_SMART_WAKEUP +#else +//#define HX_SMART_WAKEUP +#endif +/*#define HX_GESTURE_TRACK*/ +/*#define HX_HIGH_SENSE*/ +#ifdef HIMAX_PALM_SENSOR_EN +#define HX_PALM_REPORT +#else +/*#define HX_PALM_REPORT*/ +#endif +#define HX_USB_DETECT_GLOBAL +/*#define HX_USB_DETECT_CALLBACK*/ +/*#define HX_PROTOCOL_A*/ /* for MTK special platform.If turning on,it will report to system by using specific format. */ +#define HX_RESUME_HW_RESET +#define HX_PROTOCOL_B_3PA +#define HX_FIX_TOUCH_INFO /* if open, you need to change the touch info in the fix_touch_info*/ +/*#define HX_ZERO_FLASH*/ +#define HX_RESUME_SET_FW +/*#if defined(HX_ZERO_FLASH)*/ +/*#define HX_CODE_OVERLAY*/ +/*#define HX_EDGE_LIMIT*/ +/*#endif*/ +/*#define HX_EN_DYNAMIC_NAME*/ /* Support dynamic load fw name ,default is close */ +/*#undef CONFIG_FB*/ /* Enable it if driver go into suspend/resume twice */ +/*#define HX_PEN_FUNC_EN*/ + +/*#define HX_EN_SEL_BUTTON*/ /* Support Self Virtual key ,default is close*/ +/*#define HX_EN_MUT_BUTTON*/ /* Support Mutual Virtual Key ,default is close*/ + +#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) + /*#define HX_PLATFOME_DEFINE_KEY*/ /* for specfic platform to set key(button) */ +#endif +#ifdef HX_USB_DETECT_GLOBAL +#include +#endif + +#if defined(HX_SMART_WAKEUP) +/*#define HX_P_SENSOR*/ +#endif +/*=============================================*/ +#define HX_SPI_MTK_MAX_WRITE_SZ (256 - 4) + +#define HX_KEY_MAX_COUNT 4 +#define DEFAULT_RETRY_CNT 3 + +#define HX_85XX_A_SERIES_PWON "HX85xxA" +#define HX_85XX_B_SERIES_PWON "HX85xxB" +#define HX_85XX_C_SERIES_PWON "HX85xxC" +#define HX_85XX_D_SERIES_PWON "HX85xxD" +#define HX_85XX_E_SERIES_PWON "HX85xxE" +#define HX_85XX_ES_SERIES_PWON "HX85xxES" +#define HX_85XX_F_SERIES_PWON "HX85xxF" +#define HX_85XX_H_SERIES_PWON "HX85xxH" +#define HX_83100A_SERIES_PWON "HX83100A" +#define HX_83102A_SERIES_PWON "HX83102A" +#define HX_83102B_SERIES_PWON "HX83102B" +#define HX_83102D_SERIES_PWON "HX83102D" +#define HX_83102E_SERIES_PWON "HX83102E" +#define HX_83103A_SERIES_PWON "HX83103A" +#define HX_83106A_SERIES_PWON "HX83106A" +#define HX_83110A_SERIES_PWON "HX83110A" +#define HX_83110B_SERIES_PWON "HX83110B" +#define HX_83111B_SERIES_PWON "HX83111B" +#define HX_83112A_SERIES_PWON "HX83112A" +#define HX_83112B_SERIES_PWON "HX83112B" +#define HX_83113A_SERIES_PWON "HX83113A" +#define HX_83112D_SERIES_PWON "HX83112D" +#define HX_83112E_SERIES_PWON "HX83112E" +#define HX_83191A_SERIES_PWON "HX83191A" + +#define HX_TP_BIN_CHECKSUM_SW 1 +#define HX_TP_BIN_CHECKSUM_HW 2 +#define HX_TP_BIN_CHECKSUM_CRC 3 + +#define SHIFTBITS 5 + +#define FW_SIZE_32k 32768 +#define FW_SIZE_60k 61440 +#define FW_SIZE_64k 65536 +#define FW_SIZE_124k 126976 +#define FW_SIZE_128k 131072 + +#define NO_ERR 0 +#define READY_TO_SERVE 1 +#define WORK_OUT 2 +#define I2C_FAIL -1 +#define HX_INIT_FAIL -1 +#define MEM_ALLOC_FAIL -2 +#define CHECKSUM_FAIL -3 +#define GESTURE_DETECT_FAIL -4 +#define INPUT_REGISTER_FAIL -5 +#define FW_NOT_READY -6 +#define LENGTH_FAIL -7 +#define OPEN_FILE_FAIL -8 +#define ERR_WORK_OUT -10 +#define ERR_STS_WRONG -11 +#define ERR_TEST_FAIL -12 +#define HW_CRC_FAIL 1 + +#define HX_FINGER_ON 1 +#define HX_FINGER_LEAVE 2 + +#if defined(HX_PALM_REPORT) +#define PALM_REPORT 1 +#define PALM_LEAVE_REPORT 2 +#define NOT_REPORT -1 +#endif + +#if defined(HX_PEN_FUNC_EN) +#define PEN_INFO_SZ 12 +#endif + +#if defined(__EMBEDDED_FW__) +extern const uint8_t _binary___Himax_firmware_bin_start[]; +extern const uint8_t _binary___Himax_firmware_bin_end[]; +extern struct firmware g_embedded_fw; +#endif + +enum HX_TS_PATH { + HX_REPORT_COORD = 1, + HX_REPORT_SMWP_EVENT, + HX_REPORT_COORD_RAWDATA, +}; + +enum HX_TS_STATUS { + HX_TS_GET_DATA_FAIL = -4, + HX_ESD_EVENT, + HX_CHKSUM_FAIL, + HX_PATH_FAIL, + HX_TS_NORMAL_END = 0, + HX_ESD_REC_OK, + HX_READY_SERVE, + HX_REPORT_DATA, + HX_ESD_WARNING, + HX_IC_RUNNING, + HX_ZERO_EVENT_COUNT, + HX_RST_OK, +}; + +enum cell_type { + CHIP_IS_ON_CELL, + CHIP_IS_IN_CELL +}; +#ifdef HX_FIX_TOUCH_INFO +enum fix_touch_info { + FIX_HX_RX_NUM = 32, + FIX_HX_TX_NUM = 18, + FIX_HX_BT_NUM = 0, + FIX_HX_X_RES = 720, + FIX_HX_Y_RES = 1600, + FIX_HX_MAX_PT = 10, + FIX_HX_XY_REVERSE = false, + FIX_HX_INT_IS_EDGE = true, +#ifdef HX_TP_PROC_2T2R + FIX_HX_RX_NUM_2 = 36, + FIX_HX_TX_NUM_2 = 18, +#endif +}; +#endif + +#ifdef HX_ZERO_FLASH + #define HX_SPI_OPERATION + #define HX_0F_DEBUG +#endif +struct himax_ic_data { + int vendor_fw_ver; + int vendor_config_ver; + int vendor_touch_cfg_ver; + int vendor_display_cfg_ver; + int vendor_cid_maj_ver; + int vendor_cid_min_ver; + int vendor_panel_ver; + int vendor_sensor_id; +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) +#ifdef HX_EN_DYNAMIC_NAME + int vendor_ic_ver; + int vendor_old_ic_ver; + uint8_t vendor_semifac; +#endif +#endif + uint8_t vendor_cus_info[12]; + uint8_t vendor_proj_info[12]; + uint8_t vendor_ic_id[13]; + int HX_RX_NUM; + int HX_TX_NUM; + int HX_BT_NUM; + int HX_X_RES; + int HX_Y_RES; + int HX_MAX_PT; + bool HX_XY_REVERSE; + bool HX_INT_IS_EDGE; +#ifdef HX_TP_PROC_2T2R + int HX_RX_NUM_2; + int HX_TX_NUM_2; +#endif +}; + +struct himax_virtual_key { + int index; + int keycode; + int x_range_min; + int x_range_max; + int y_range_min; + int y_range_max; +}; + +struct himax_target_report_data { + int *x; + int *y; + int *w; + int *finger_id; + int finger_on; + int finger_num; +#ifdef HX_PLATFORM_DEFINE_KEY + int key_size; + int *key_x; + int *key_y; + int *key_w; +#endif +#ifdef HX_SMART_WAKEUP + int SMWP_event_chk; +#endif +#if defined(HX_PEN_FUNC_EN) + int32_t *p_x; + int32_t *p_y; + int32_t *p_w; + int32_t *pen_id; + uint32_t *p_hover; + int32_t *p_tilt_x; + uint32_t *p_btn; + uint32_t *p_btn2; + int32_t *p_tilt_y; + uint32_t *p_on; +#endif + int ig_count; + +}; + +struct himax_report_data { + int touch_all_size; + int raw_cnt_max; + int raw_cnt_rmd; + int touch_info_size; + uint8_t finger_num; + uint8_t finger_on; + uint8_t *hx_coord_buf; + uint8_t hx_state_info[2]; +#if defined(HX_SMART_WAKEUP) + int event_size; + uint8_t *hx_event_buf; +#endif + + int rawdata_size; + uint8_t diag_cmd; + uint8_t *hx_rawdata_buf; + uint8_t rawdata_frame_size; +}; + +struct himax_ts_data { + bool initialized; + bool suspended; + atomic_t suspend_mode; + struct mutex suspend_resume_mutex; + uint8_t x_channel; + uint8_t y_channel; + uint8_t useScreenRes; + uint8_t diag_cmd; + char chip_name[30]; + uint8_t chip_cell_type; + + uint8_t protocol_type; + uint8_t first_pressed; + uint8_t coord_data_size; + uint8_t area_data_size; + uint8_t coordInfoSize; + uint8_t raw_data_frame_size; + uint8_t raw_data_nframes; + uint8_t nFinger_support; + uint8_t irq_enabled; + uint8_t diag_self[50]; + + uint16_t finger_pressed; + uint16_t last_slot; + uint16_t pre_finger_mask; + uint16_t old_finger; + int hx_point_num; + + + uint32_t debug_log_level; + uint32_t widthFactor; + uint32_t heightFactor; + uint32_t tw_x_min; + uint32_t tw_x_max; + uint32_t tw_y_min; + uint32_t tw_y_max; + uint32_t pl_x_min; + uint32_t pl_x_max; + uint32_t pl_y_min; + uint32_t pl_y_max; + + int rst_gpio; + int use_irq; + int (*power)(int on); + int pre_finger_data[10][2]; + bool vdd_1v8_always_on; + + struct device *dev; + struct workqueue_struct *himax_wq; + struct work_struct work; + struct input_dev *input_dev; +#if defined(HX_PEN_FUNC_EN) + struct input_dev *hx_pen_dev; +#endif + struct hrtimer timer; + struct i2c_client *client; + struct himax_i2c_platform_data *pdata; + struct himax_virtual_key *button; + struct mutex rw_lock; + +/******* SPI-start *******/ + struct mutex spi_lock; + struct spi_device *spi; + int hx_irq; + uint8_t *xfer_buff; +/******* SPI-end *******/ + + int in_self_test; + int suspend_resume_done; + int bus_speed; + +#if defined(CONFIG_FB) || defined(CONFIG_DRM) + struct notifier_block fb_notif; + struct workqueue_struct *himax_att_wq; + struct delayed_work work_att; +#elif defined(CONFIG_HAS_EARLYSUSPEND) + struct early_suspend early_suspend; +#endif + + struct workqueue_struct *flash_wq; + struct work_struct flash_work; + +#ifdef HX_AUTO_UPDATE_FW + struct workqueue_struct *himax_update_wq; + struct delayed_work work_update; +#endif + +#ifdef HX_ZERO_FLASH + struct workqueue_struct *himax_0f_update_wq; + struct delayed_work work_0f_update; +#endif +#ifdef HX_RESUME_SET_FW + struct workqueue_struct *ts_int_workqueue; +#if defined(__HIMAX_HX83102D_MOD__) + struct delayed_work ts_int_work; +#else + struct work_struct ts_int_work; +#endif +#endif + + struct workqueue_struct *himax_diag_wq; + struct delayed_work himax_diag_delay_wrok; + +#if defined (HX_SMART_WAKEUP) || defined (HX_CODE_OVERLAY) + uint8_t SMWP_enable; + uint8_t gesture_cust_en[26]; + struct wakeup_source ts_SMWP_wake_lock; +#ifdef HX_P_SENSOR + bool psensor_flag; +#endif +#endif + +#ifdef HX_EDGE_LIMIT + uint8_t edge_limit_enable; + uint8_t edge_limit_en[8]; +#endif + +#ifdef HX_HIGH_SENSE + uint8_t HSEN_enable; +#endif + +#if defined(HX_USB_DETECT_CALLBACK) || defined(HX_USB_DETECT_GLOBAL) + uint8_t usb_connected; + uint8_t *cable_config; + struct notifier_block charger_notif; +#endif + +#ifdef HX_TP_PROC_GUEST_INFO + struct workqueue_struct *guest_info_wq; + struct work_struct guest_info_work; +#endif + +#ifdef HIMAX_PALM_SENSOR_EN + bool palm_detection_enabled; + enum palm_sensor_lazy_set palm_detection_lazy_set; + struct himax_sensor_platform_data *palm_sensor_pdata; + struct timer_list palm_release_fimer; + unsigned int palm_release_delay_ms; +#ifdef CONFIG_HAS_WAKELOCK + struct wake_lock palm_gesture_wakelock; +#else + struct wakeup_source palm_gesture_wakelock; +#endif +#ifdef CONFIG_HAS_WAKELOCK + struct wake_lock palm_gesture_read_wakelock; +#else + struct wakeup_source palm_gesture_read_wakelock; +#endif +#endif + +#ifdef HIMAX_V2_SENSOR_EN + struct himax_tap_sensor_platform_data *sensor_pdata; +#endif + +}; + +struct himax_debug { + bool flash_dump_going; + void (*fp_ts_dbg_func)(struct himax_ts_data *ts, int start); + int (*fp_set_diag_cmd)(struct himax_ic_data *ic_data, struct himax_report_data *hx_touch_data); +}; + +enum input_protocol_type { + PROTOCOL_TYPE_A = 0x00, + PROTOCOL_TYPE_B = 0x01, +}; + +#ifdef HX_HIGH_SENSE + void himax_set_HSEN_func(uint8_t HSEN_enable); +#endif + +#ifdef HX_SMART_WAKEUP +void himax_set_SMWP_func(uint8_t SMWP_enable); + +#define GEST_PTLG_ID_LEN (4) +#define GEST_PTLG_HDR_LEN (4) +#define GEST_PTLG_HDR_ID1 (0xCC) +#define GEST_PTLG_HDR_ID2 (0x44) +#define GEST_PT_MAX_NUM (128) + +extern uint8_t *wake_event_buffer; +#endif + +extern int irq_enable_count; +extern int g_mmi_refcnt; +extern int *g_inspt_crtra_flag; +extern uint32_t g_hx_chip_inited; +/*void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);*/ + +int himax_chip_common_suspend(struct himax_ts_data *ts); +int himax_chip_common_resume(struct himax_ts_data *ts); + +extern struct filename* (*kp_getname_kernel)(const char *filename); +extern struct file * (*kp_file_open_name)(struct filename *name, int flags, umode_t mode); + +struct himax_core_fp; +extern struct himax_core_fp g_core_fp; +extern struct himax_ts_data *private_ts; +extern struct himax_ic_data *ic_data; +extern struct device *g_device; + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_DEBUG + int himax_debug_init(void); + int himax_debug_remove(void); +#endif + +#if defined(HX_PLATFOME_DEFINE_KEY) + void himax_platform_key(void); +#endif + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_INSPECT + extern char *g_rslt_data; + extern void (*fp_himax_self_test_init)(void); +#endif + +int himax_parse_dt(struct himax_ts_data *ts, struct himax_i2c_platform_data *pdata); +int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status); + +int himax_report_data_init(void); + +int himax_dev_set(struct himax_ts_data *ts); +int himax_input_register_device(struct input_dev *input_dev); + +#endif + diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_debug.c b/drivers/input/touchscreen/himax_v3_mmi/himax_debug.c old mode 100644 new mode 100755 index 69303c590542..b41724bd3cb2 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_debug.c +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_debug.c @@ -1,3033 +1,2864 @@ -/* 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; - int HX_RX_NUM_2; - int HX_TX_NUM_2; -#endif - -uint8_t g_diag_arr_num; - -int g_max_mutual; -int g_min_mutual = 0xFFFF; -int g_max_self; -int g_min_self = 0xFFFF; - -/* moved from debug.h */ - -struct proc_dir_entry *himax_proc_vendor_file; -uint8_t byte_length; -uint8_t reg_cmd[4]; -uint8_t cfg_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 diag_max_cnt; -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; -int Flash_Size = 131072; -uint8_t *flash_buffer; -uint8_t g_flash_cmd; -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}; -uint8_t *reg_read_data; - -struct proc_dir_entry *himax_proc_pen_pos_file; - -struct timespec timeStart, timeEnd, timeDelta; -int g_switch_mode; -/* - * Segment : Himax PROC Debug Function - */ - -static ssize_t himax_pen_ops_read(struct file *file, char *buf, - size_t len, loff_t *pos) -{ - int i = 0; - ssize_t ret = 0; - - if (!HX_PROC_SEND_FLAG) { - for (i = 0; i < private_ts->nFinger_support; i++) { - if (g_target_report_data->x[i] >= 0 - && g_target_report_data->x[i] - <= private_ts->pdata->abs_x_max - && g_target_report_data->y[i] >= 0 - && g_target_report_data->y[i] - <= private_ts->pdata->abs_y_max - && private_ts->hx_point_num != 0) { - ret += snprintf(buf_tmp + ret, len - ret, - "%d,%d,", g_target_report_data->x[i], - g_target_report_data->y[i]); - } else { - ret += snprintf(buf_tmp + ret, len - ret, - "65535,65535,"); - } - } - if (g_target_report_data->p_x[0] >= 0 - && g_target_report_data->p_x[0] <= private_ts->pdata->abs_x_max - && g_target_report_data->p_y[0] >= 0 - && g_target_report_data->p_y[0] <= private_ts->pdata->abs_y_max - && (g_target_report_data->p_on[0] == 1)) { - ret += snprintf(buf_tmp + ret, len - ret, "%d,%d,", - g_target_report_data->p_x[0], - g_target_report_data->p_y[0]); - } else { - ret += snprintf(buf_tmp + ret, len - ret, - "65535,65535,"); - } - - ret += snprintf(buf_tmp + ret, len - ret, - "%d,", g_target_report_data->p_w[0]); - - ret += snprintf(buf_tmp + ret, len - ret, - "%d,", g_target_report_data->p_hover[0]); - - if (g_target_report_data->p_btn[0] != 0xff) { - ret += snprintf(buf_tmp + ret, len - ret, - "%d,", g_target_report_data->p_btn[0]); - } else { - ret += snprintf(buf_tmp + ret, len - ret, "0,"); - } - if (g_target_report_data->p_btn2[0] != 0xff) { - ret += snprintf(buf_tmp + ret, len - ret, - "%d,", g_target_report_data->p_btn2[0]); - } else { - ret += snprintf(buf_tmp + ret, len - ret, "0,"); - } - - if (g_target_report_data->p_tilt_x[0] != 0xff) { - ret += snprintf(buf_tmp + ret, len - ret, - "%d,", - g_target_report_data->p_tilt_x[0]); - } else { - ret += snprintf(buf_tmp + ret, len - ret, "0,"); - } - if (g_target_report_data->p_tilt_y[0] != 0xff) { - ret += snprintf(buf_tmp + ret, len - ret, - "%d\n", - g_target_report_data->p_tilt_y[0]); - } else { - ret += snprintf(buf_tmp + ret, len - ret, "0\n"); - } - - if (copy_to_user(buf, buf_tmp, (len > BUF_SIZE)?BUF_SIZE:len)) - I("%s,here:%d\n", __func__, __LINE__); - - HX_PROC_SEND_FLAG = 1; - } else { - HX_PROC_SEND_FLAG = 0; - } - - return ret; -} - -static const struct file_operations himax_proc_pen_pos_ops = { - .owner = THIS_MODULE, - .read = himax_pen_ops_read, -}; - -static ssize_t himax_crc_test_read(char *buf, size_t len) -{ - ssize_t 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) - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "CRC test is Pass!\n"); - else - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "CRC test is Fail!\n"); - - return ret; -} - -static ssize_t himax_vendor_read(struct file *file, char *buf, - size_t len, loff_t *pos) -{ - ssize_t ret = 0; - - if (!HX_PROC_SEND_FLAG) { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "IC = %s\n", private_ts->chip_name); - - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "FW_VER = 0x%2.2X\n", ic_data->vendor_fw_ver); - - if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "CONFIG_VER = 0x%2.2X\n", - ic_data->vendor_config_ver); - } else { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "TOUCH_VER = 0x%2.2X\n", - ic_data->vendor_touch_cfg_ver); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "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) { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "CID_VER = NULL\n"); - } else { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "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) { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "PANEL_VER = NULL\n"); - } else { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "PANEL_VER = 0x%2.2X\n", - ic_data->vendor_panel_ver); - } - if (private_ts->chip_cell_type == CHIP_IS_IN_CELL) { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "Cusomer = %s\n", - ic_data->vendor_cus_info); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "Project = %s\n", - ic_data->vendor_proj_info); - } - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "Himax Touch Driver Version:\n"); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%s\n", - HIMAX_DRIVER_VER); - HX_PROC_SEND_FLAG = 1; - - if (copy_to_user(buf, buf_tmp, (len > BUF_SIZE)?BUF_SIZE:len)) - I("%s,here:%d\n", __func__, __LINE__); - - } else { - HX_PROC_SEND_FLAG = 0; - } - - return ret; -} - -static const struct file_operations himax_proc_vendor_ops = { - .owner = THIS_MODULE, - .read = himax_vendor_read, -}; - -static ssize_t himax_attn_read(char *buf, size_t len) -{ - ssize_t ret = 0; - struct himax_ts_data *ts_data; - - ts_data = private_ts; - - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "attn = %x\n", - himax_int_gpio_read(ts_data->pdata->gpio_irq)); - - return ret; -} - -static ssize_t himax_int_en_read(char *buf, size_t len) -{ - struct himax_ts_data *ts = private_ts; - size_t ret = 0; - - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%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 - return -EINVAL; - - return len; -} - -static ssize_t himax_layout_read(char *buf, size_t len) -{ - struct himax_ts_data *ts = private_ts; - size_t ret = 0; - - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d ", - ts->pdata->abs_x_min); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d ", - ts->pdata->abs_x_max); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d ", - ts->pdata->abs_y_min); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d ", - ts->pdata->abs_y_max); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\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; - } - - 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); - } - - return len; -} - -static ssize_t himax_debug_level_read(char *buf, size_t len) -{ - struct himax_ts_data *ts_data; - size_t ret = 0; - - ts_data = private_ts; - - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d\n", - ts_data->debug_log_level); - - if (copy_to_user(buf, buf_tmp, (len > BUF_SIZE)?BUF_SIZE:len)) - I("%s,here:%d\n", __func__, __LINE__); - - return ret; -} - -static ssize_t himax_debug_level_write(char *buf, size_t len) -{ - struct himax_ts_data *ts; - int i; - - ts = private_ts; - - if (len >= 12) { - I("%s: no command exceeds 12 chars.\n", __func__); - return -EFAULT; - } - - 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("Enable finger debug with raw position mode!\n"); - } - } else { - ts->useScreenRes = 0; - ts->widthFactor = 0; - ts->heightFactor = 0; - } -END_FUNC: - return len; -} - -static ssize_t himax_proc_register_read(char *buf, size_t len) -{ - int ret = 0; - uint16_t loop_i; - - memset(reg_read_data, 0x00, 128 * sizeof(uint8_t)); - - I("himax_register_show: %02X,%02X,%02X,%02X\n", - reg_cmd[3], reg_cmd[2], - reg_cmd[1], reg_cmd[0]); - g_core_fp.fp_register_read(reg_cmd, 128, - reg_read_data, cfg_flag); - - ret += snprintf(buf_tmp + ret, len - ret, - "command: %02X,%02X,%02X,%02X\n", - reg_cmd[3], reg_cmd[2], - reg_cmd[1], reg_cmd[0]); - - for (loop_i = 0; loop_i < 128; loop_i++) { - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "0x%2.2X ", - reg_read_data[loop_i]); - if ((loop_i % 16) == 15) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, "\n"); - - } - - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); - - return ret; -} - -static ssize_t himax_proc_register_write(char *buf, size_t len) -{ - char buff_tmp[16] = {0}; - uint8_t length = 0; - unsigned long result = 0; - uint8_t loop_i = 0; - uint16_t base = 2; - char *data_str = NULL; - uint8_t w_data[20] = {0}; - uint8_t x_pos[20] = {0}; - uint8_t count = 0; - - if (len >= 80) { - I("%s: no command exceeds 80 chars.\n", __func__); - return -EFAULT; - } - - memset(reg_cmd, 0x0, sizeof(reg_cmd)); - - I("himax %s\n", buf); - - if ((buf[0] == 'r' || buf[0] == 'w') - && buf[1] == ':' - && buf[2] == 'x') { - length = strlen(buf); - - /* I("%s: length = %d.\n", __func__,length); */ - for (loop_i = 0; loop_i < length; loop_i++) { - /* find postion of 'x' */ - if (buf[loop_i] == 'x') { - x_pos[count] = loop_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 - base; - cfg_flag = 1; - memcpy(buff_tmp, data_str + base + 1, length); - } else { - cfg_flag = 0; - memcpy(buff_tmp, data_str + 1, length); - } - byte_length = length / 2; - if (!kstrtoul(buff_tmp, 16, &result)) { - for (loop_i = 0; loop_i < byte_length; loop_i++) - reg_cmd[loop_i] = - (uint8_t)(result >> loop_i * 8); - } - - if (strcmp(HX_85XX_H_SERIES_PWON, - private_ts->chip_name) == 0 && cfg_flag == 0) - cfg_flag = 2; - break; - case 'w': - if (buf[3] == 'F' && buf[4] == 'E') { - cfg_flag = 1; - memcpy(buff_tmp, buf + base + 3, length); - } else { - cfg_flag = 0; - memcpy(buff_tmp, buf + 3, length); - } - - if (count < 3) { - byte_length = length / 2; - - if (!kstrtoul(buff_tmp, 16, &result)) { - /* command */ - for (loop_i = 0; loop_i < byte_length; - loop_i++) { - reg_cmd[loop_i] = - (uint8_t)(result >> loop_i * 8); - } - } - - if (!kstrtoul(data_str + 1, 16, &result)) { - /* data */ - for (loop_i = 0; loop_i < byte_length; - loop_i++) { - w_data[loop_i] = - (uint8_t)(result >> loop_i * 8); - } - } - - g_core_fp.fp_register_write(reg_cmd, - byte_length, w_data, cfg_flag); - } else { - for (loop_i = 0; loop_i < count; loop_i++) { - /* parsing addr after 'x' */ - memset(buff_tmp, 0x0, sizeof(buff_tmp)); - if (cfg_flag != 0 && loop_i != 0) - byte_length = 2; - else - byte_length = x_pos[1] - - x_pos[0] - 2;/* original */ - - memcpy(buff_tmp, - buf + x_pos[loop_i] + 1, - byte_length); - - /* I("%s: buff_tmp = %s\n",*/ - /* __func__, buff_tmp);*/ - if (!kstrtoul(buff_tmp, 16, &result)) { - if (loop_i == 0) - reg_cmd[loop_i] = - (uint8_t)(result); - /* I("%s: - * reg_cmd - * = %X\n", __func__, - * reg_cmd[0]); - */ - else - w_data[loop_i - 1] = - (uint8_t)(result); - /* I("%s: w_data[%d] = - * %2X\n", __func__, - * loop_i - 1, - * w_data[loop_i - 1]); - */ - } - } - - byte_length = count - 1; - if (strcmp(HX_85XX_H_SERIES_PWON, - private_ts->chip_name) == 0 && cfg_flag == 0) - cfg_flag = 2; - g_core_fp.fp_register_write(reg_cmd, - byte_length, &w_data[0], cfg_flag); - - } - break; - }; - } - 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 loop_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 (loop_i = 0; loop_i < print_size; loop_i += 8) { - if ((loop_i + 7) >= print_size) { - I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", - loop_i, - buf[loop_i], - loop_i + 1, - buf[loop_i + 1]); - I("P %2d = 0x%2.2X P %2d = 0x%2.2X\n", - loop_i + 2, - buf[loop_i + 2], - loop_i + 3, - buf[loop_i + 3]); - break; - } - - I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", - loop_i, buf[loop_i], loop_i + 1, buf[loop_i + 1]); - I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", - loop_i + 2, buf[loop_i + 2], loop_i + 3, buf[loop_i + 3]); - I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", - loop_i + 4, buf[loop_i + 4], loop_i + 5, buf[loop_i + 5]); - I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", - loop_i + 6, buf[loop_i + 6], loop_i + 7, buf[loop_i + 7]); - I("\n"); - } - kfree(buf); -} - -#define PRT_LOG "Finger %d=> X:%d, Y:%d W:%d, Z:%d, F:%d, Int_Delay_Cnt:%d\n" -void himax_log_touch_event(struct himax_ts_data *ts, int start) -{ - int loop_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 (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { - if (g_target_report_data->x[loop_i] >= 0 - && g_target_report_data->x[loop_i] - <= ts->pdata->abs_x_max - && g_target_report_data->y[loop_i] >= 0 - && g_target_report_data->y[loop_i] - <= ts->pdata->abs_y_max) { - I(PRT_LOG, - loop_i + 1, - g_target_report_data->x[loop_i], - g_target_report_data->y[loop_i], - g_target_report_data->w[loop_i], - g_target_report_data->w[loop_i], - loop_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) { - getnstimeofday(&timeStart); - /* I(" Irq start time = %ld.%06ld s\n", - * timeStart.tv_sec, timeStart.tv_nsec/1000); - */ - } else if (touched == HX_FINGER_LEAVE) { - getnstimeofday(&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", 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__); - } -} - -#define RAW_DOWN_STATUS "status: Raw:F:%02d Down, X:%d, Y:%d, W:%d\n" -#define RAW_UP_STATUS "status: Raw:F:%02d Up, X:%d, Y:%d\n" - -void himax_log_touch_event_detail(struct himax_ts_data *ts, int start) -{ - int loop_i = 0; - - if (start == HX_FINGER_LEAVE) { - for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { - if (((ts->old_finger >> loop_i & 1) == 0) - && ((ts->pre_finger_mask >> loop_i & 1) == 1)) { - if (g_target_report_data->x[loop_i] >= 0 - && g_target_report_data->x[loop_i] - <= ts->pdata->abs_x_max - && g_target_report_data->y[loop_i] >= 0 - && g_target_report_data->y[loop_i] - <= ts->pdata->abs_y_max) { - I(RAW_DOWN_STATUS, loop_i + 1, - g_target_report_data->x[loop_i], - g_target_report_data->y[loop_i], - g_target_report_data->w[loop_i]); - } - } else if ((((ts->old_finger >> loop_i & 1) == 1) - && ((ts->pre_finger_mask >> loop_i & 1) == 0))) { - I(RAW_UP_STATUS, loop_i + 1, - ts->pre_finger_data[loop_i][0], - ts->pre_finger_data[loop_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; -} - -#define PRT_OK_LOG "%s: change mode 0x%4X. str_pw = %2X, end_pw = %2X\n" -#define PRT_FAIL_LOG "%s: change mode failed. str_pw = %2X, end_pw = %2X\n" -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; - - 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; - dsram_flag = false; - cancel_delayed_work(&ts->himax_diag_delay_wrok); - 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_wrok, 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_wrok, 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__); - } - return len; -} - -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; - } - - 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]); - } - } -} - -static void *himax_diag_seq_start(struct seq_file *s, loff_t *pos) -{ - if (*pos >= 1) - return NULL; - - return (void *)((unsigned long) *pos + 1); -} - -static void *himax_diag_seq_next(struct seq_file *s, void *v, loff_t *pos) -{ - return NULL; -} - -static void himax_diag_seq_stop(struct seq_file *s, void *v) -{ - kfree(v); -} - -/* DSRAM thread */ -bool himax_ts_diag_func(void) -{ - int retry = 3; - 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 */ - int dsram_type = process_type; - - 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)); - - I("%s: process type=%d!\n", __func__, process_type); - - g_core_fp.fp_burst_enable(1); - - if (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(); - } - - do { - if (g_core_fp.fp_get_DSRAM_data(info_data, dsram_flag)) - break; - } while (retry-- > 0); - - if (retry <= 0) { - 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 */ - } - - diag_max_cnt++; - - if (dsram_type >= 1 && dsram_type <= 3) { - queue_delayed_work(private_ts->himax_diag_wq, - &private_ts->himax_diag_delay_wrok, 1 / 10 * HZ); - } - 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_diag_stack_read(struct seq_file *s, void *v) -{ - struct himax_ts_data *ts = private_ts; - - 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; -} - -static const struct seq_operations himax_diag_stack_ops = { - .start = himax_diag_seq_start, - .next = himax_diag_seq_next, - .stop = himax_diag_seq_stop, - .show = himax_diag_stack_read, -}; - -static int himax_diag_stack_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &himax_diag_stack_ops); -}; - -static const struct file_operations himax_proc_stack_ops = { - .owner = THIS_MODULE, - .open = himax_diag_stack_open, - .read = seq_read, - .release = seq_release, -}; - -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; - - d_type = (!ts->diag_cmd)?rs:ts->diag_cmd; - - if (!overflow) { - if (!process_type) { - himax_int_enable(0); - g_core_fp.fp_diag_register_set(d_type, 0, false); - - if (!himax_ts_diag_func()) - 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_diag_delta_read(struct seq_file *s, void *v) -{ - return himax_sram_read(s, v, 0x09); -} - -static const struct seq_operations himax_diag_delta_ops = { - .start = himax_diag_seq_start, - .next = himax_diag_seq_next, - .stop = himax_diag_seq_stop, - .show = himax_diag_delta_read, -}; - -static int himax_diag_delta_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &himax_diag_delta_ops); -}; - -static const struct file_operations himax_proc_delta_ops = { - .owner = THIS_MODULE, - .open = himax_diag_delta_open, - .read = seq_read, - .release = seq_release, -}; - -static int himax_diag_dc_read(struct seq_file *s, void *v) -{ - return himax_sram_read(s, v, 0x0A); -} - -static const struct seq_operations himax_diag_dc_ops = { - .start = himax_diag_seq_start, - .next = himax_diag_seq_next, - .stop = himax_diag_seq_stop, - .show = himax_diag_dc_read, -}; -static int himax_diag_dc_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &himax_diag_dc_ops); -}; - -static const struct file_operations himax_proc_dc_ops = { - .owner = THIS_MODULE, - .open = himax_diag_dc_open, - .read = seq_read, - .release = seq_release, -}; - -static int himax_diag_baseline_read(struct seq_file *s, void *v) -{ - return himax_sram_read(s, v, 0x0B); -} - -static const struct seq_operations himax_diag_baseline_ops = { - .start = himax_diag_seq_start, - .next = himax_diag_seq_next, - .stop = himax_diag_seq_stop, - .show = himax_diag_baseline_read, -}; -static int himax_diag_baseline_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &himax_diag_baseline_ops); -}; - -static const struct file_operations himax_proc_baseline_ops = { - .owner = THIS_MODULE, - .open = himax_diag_baseline_open, - .read = seq_read, - .release = seq_release, -}; - -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 defined(HX_RST_PIN_FUNC) - if (buf[0] == '1') - g_core_fp.fp_ic_reset(false, false); - else if (buf[0] == '2') - g_core_fp.fp_ic_reset(false, true); - else if (buf[0] == '3') - g_core_fp.fp_ic_reset(true, false); - else if (buf[0] == '4') - g_core_fp.fp_ic_reset(true, true); - /* else if (buf[0] == '5') */ - /* ESD_HW_REST(); */ -#endif -#if defined(HX_ZERO_FLASH) - if (g_core_fp.fp_0f_reload_to_active) - g_core_fp.fp_0f_reload_to_active(); -#endif - return len; -} - -static ssize_t himax_proc_FW_debug_read(char *buf, size_t len) -{ - ssize_t ret = 0; - uint8_t loop_i = 0; - uint8_t tmp_data[64] = {0}; - - cmd_set[0] = 0x01; - - if (g_core_fp.fp_read_FW_status(cmd_set, tmp_data) == NO_ERR) { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "0x%02X%02X%02X%02X :\t", - cmd_set[5], cmd_set[4], - cmd_set[3], cmd_set[2]); - - for (loop_i = 0; loop_i < cmd_set[1]; loop_i++) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "%5d\t", tmp_data[loop_i]); - - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); - } - - cmd_set[0] = 0x02; - - if (g_core_fp.fp_read_FW_status(cmd_set, tmp_data) == NO_ERR) { - for (loop_i = 0; loop_i < cmd_set[1]; - loop_i = loop_i + 2) { - if ((loop_i % 16) == 0) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "0x%02X%02X%02X%02X :\t", - cmd_set[5], cmd_set[4], - cmd_set[3] + - (((cmd_set[2] + loop_i) >> 8) & 0xFF), - (cmd_set[2] + loop_i) & 0xFF); - - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "%5d\t", tmp_data[loop_i] + - (tmp_data[loop_i + 1] << 8)); - - if ((loop_i % 16) == 14) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, "\n"); - } - } - - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); - - return ret; -} - -static ssize_t himax_proc_DD_debug_read(char *buf, size_t len) -{ - ssize_t ret = 0; - uint8_t tmp_data[64] = {0}; - uint8_t loop_i = 0; - - if (mutual_set_flag == 1) { - if (g_core_fp.fp_read_DD_status(cmd_set, tmp_data) == - NO_ERR) { - for (loop_i = 0; loop_i < cmd_set[0]; - loop_i++) { - if ((loop_i % 8) == 0) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "0x%02X : ", loop_i); - - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, "0x%02X ", - tmp_data[loop_i]); - - if ((loop_i % 8) == 7) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, "\n"); - } - } else { - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Get DD status falied!\n"); - } - } - - ret += snprintf(buf_tmp + ret, len - ret, "\n"); - - return ret; -} - -#define STR_TO_UL_ERR "String to ul is fail in cnt = %d, buf_tmp2 = %s\n" - -static ssize_t himax_proc_DD_debug_write(char *buf, size_t len) -{ - uint8_t i = 0; - uint8_t cnt = 2; - unsigned long result = 0; - char buf_tmp2[4]; - - if (len >= 20) { - I("%s: no command exceeds 20 chars.\n", __func__); - return -EFAULT; - } - - memset(buf_tmp2, 0x0, sizeof(buf_tmp2)); - - if (buf[2] == 'x' && buf[6] == 'x' && buf[10] == 'x') { - mutual_set_flag = 1; - - for (i = 3; i < 12; i = i + 4) { - memcpy(buf_tmp2, buf + i, 2); - - if (!kstrtoul(buf_tmp2, 16, &result)) - cmd_set[cnt] = (uint8_t)result; - else - I(STR_TO_UL_ERR, cnt, buf_tmp2); - - cnt--; - } - - I("cmd_set[2] = %02X, cmd_set[1] = %02X, cmd_set[0] = %02X\n", - cmd_set[2], cmd_set[1], cmd_set[0]); - } else { - mutual_set_flag = 0; - } - - return len; -} - -void setFlashBuffer(void) -{ - flash_buffer = kcalloc(Flash_Size, sizeof(uint8_t), GFP_KERNEL); -} - -void flash_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_proc_flash_read(struct seq_file *s, void *v) -{ - ssize_t ret = 0; - int i; - uint8_t flash_progress = g_flash_progress; - uint8_t flash_cmd = g_flash_cmd; - bool flash_rst = g_flash_dump_rst; - - I("flash_progress = %d\n", flash_progress); - - if (!flash_rst) { - seq_puts(s, "FlashStart:Fail\n"); - seq_puts(s, "FlashEnd\n"); - return ret; - } - - if (flash_progress == START) - seq_puts(s, "Flash dump - Start\n"); - else if (flash_progress == ONGOING) - seq_puts(s, "Flash dump - On-going\n"); - else if (flash_progress == FINISHED) - seq_puts(s, "Flash dump - Finished\n"); - - /*print flash dump data*/ - if (flash_cmd == 1 && flash_progress == FINISHED) { - seq_puts(s, "Start to print flash dump data\n"); - for (i = 0; i < Flash_Size; i++) { - seq_printf(s, "0x%02X,", flash_buffer[i]); - if (i % 16 == 15) - seq_puts(s, "\n"); - } - } - - seq_puts(s, "FlashEnd\n"); - - return ret; -} - -static ssize_t himax_proc_flash_write(struct file *filp, - const char __user *buff, size_t len, loff_t *data) -{ - char buf[80] = {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; - } - - if ((buf[1] == '_') && (buf[2] == '3') && (buf[3] == '2')) - Flash_Size = FW_SIZE_32k; - else if ((buf[1] == '_') && (buf[2] == '6')) { - if (buf[3] == '0') - Flash_Size = FW_SIZE_60k; - else if (buf[3] == '4') - Flash_Size = FW_SIZE_64k; - - } else if ((buf[1] == '_') && (buf[2] == '2')) { - if (buf[3] == '4') - Flash_Size = FW_SIZE_124k; - else if (buf[3] == '8') - Flash_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_flash_cmd = 1; - flash_dump_prog_set(START); - g_flash_dump_rst = true; - queue_work(private_ts->flash_wq, &private_ts->flash_work); - } else if (buf[0] == '2') { - /* 2_32,2_60,2_64,2_24,2_28 for flash size: - * 32k,60k,64k,124k,128k - */ - g_flash_cmd = 2; - flash_dump_prog_set(START); - g_flash_dump_rst = true; - queue_work(private_ts->flash_wq, &private_ts->flash_work); - } - - return len; -} - -static void *himax_flash_dump_seq_start(struct seq_file *s, loff_t *pos) -{ - if (*pos >= 1) - return NULL; - - return (void *)((unsigned long) *pos + 1); -} - -static void *himax_flash_dump_seq_next(struct seq_file *s, void *v, - loff_t *pos) -{ - return NULL; -} - -static void himax_flash_dump_seq_stop(struct seq_file *s, void *v) -{ -} - -static const struct seq_operations himax_flash_dump_seq_ops = { - .start = himax_flash_dump_seq_start, - .next = himax_flash_dump_seq_next, - .stop = himax_flash_dump_seq_stop, - .show = himax_proc_flash_read, -}; -static int himax_flash_dump_proc_open(struct inode *inode, - struct file *file) -{ - return seq_open(file, &himax_flash_dump_seq_ops); -}; - -static const struct file_operations himax_proc_flash_ops = { - .owner = THIS_MODULE, - .open = himax_flash_dump_proc_open, - .read = seq_read, - .write = himax_proc_flash_write, -}; - -void himax_ts_flash_func(void) -{ - uint8_t flash_command = g_flash_cmd; - - himax_int_enable(0); - flash_dump_prog_set(ONGOING); - - /*msleep(100);*/ - I("%s: flash_command = %d enter.\n", __func__, flash_command); - - if (flash_command == 1 || flash_command == 2) { - g_core_fp.fp_flash_dump_func(flash_command, Flash_Size, - flash_buffer); - g_flash_dump_rst = true; - } - - I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n"); - -/* if (flash_command == 2) { - * struct file *fn; - * struct filename *vts_name; - * - * vts_name = kp_getname_kernel(FLASH_DUMP_FILE); - * fn = kp_file_open_name(vts_name, O_CREAT | O_WRONLY, 0); - * - * if (!IS_ERR(fn)) { - * I("%s create file and ready to write\n", __func__); - * fn->f_op->write(fn, flash_buffer, - * Flash_Size * sizeof(uint8_t), &fn->f_pos); - * filp_close(fn, NULL); - * } else { - * E("%s Open file failed!\n", __func__); - * g_flash_dump_rst = false; - * } - * } - */ - himax_int_enable(1); - flash_dump_prog_set(FINISHED); -} - -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') { - g_core_fp.fp_sense_off(true); - I("Sense off\n"); - } else if (buf[0] == '1') { - if (buf[1] == 's') { - g_core_fp.fp_sense_on(0x00); - I("Sense on re-map on, run sram\n"); - } else { - g_core_fp.fp_sense_on(0x01); - I("Sense on re-map off, run flash\n"); - } - } else { - I("Do nothing\n"); - } - - return len; -} - -#if defined(HX_ESD_RECOVERY) -static ssize_t himax_esd_cnt_read(char *buf, size_t len) -{ - size_t ret = 0; - - I("%s: enter, %d\n", __func__, __LINE__); - - ret += snprintf(buf_tmp + ret, len - ret, - "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_esd_cnt_write(char *buf, size_t len) -{ - int i = 0; - - if (len >= 12) { - I("%s: no command exceeds 80 chars.\n", __func__); - return -EFAULT; - } - - I("Clear ESD Flag\n"); - - if (buf[i] == '0') { - hx_EB_event_flag = 0; - hx_EC_event_flag = 0; - hx_ED_event_flag = 0; - } - - return len; -} - -#endif - -#if defined(HX_TP_PROC_GUEST_INFO) -static int printMat(char *temp_buf, size_t len, 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) - ret += snprintf(temp_buf + ret, len - ret, "\n"); - - ret += snprintf(temp_buf + ret, len - ret, "0x%02X\t", - guest_str[i]); - } - return ret; -} - -static int printUnit(char *temp_buf, size_t len, int max_size, - char *info_item, uint8_t *guest_str, int loc) -{ - int ret = loc; - - ret += snprintf(temp_buf + ret, len - ret, "%s:\n", info_item); - ret = printMat(temp_buf, len, max_size, guest_str, ret); - ret += snprintf(temp_buf + ret, len - ret, "\n"); - return ret; -} - -static ssize_t himax_proc_guest_info_read(char *buf, size_t len) -{ - int ret = 0; - int j = 0; - int max_size = 128; - struct hx_guest_info *info = g_guest_info_data; - - I("guest info progress\n"); - - if (g_core_fp.guest_info_get_status()) { - ret += snprintf(buf_tmp + ret, len - ret, "Not Ready\n"); - goto END_FUNCTION; - } else { - if (info->g_guest_info_type == 1) { - for (j = 0; j < 3; j++) { - ret = printUnit(buf_tmp, len, 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(buf_tmp, len, 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(buf_tmp, len, 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; - - ret += snprintf(buf_tmp + ret, - len - ret, "%s:\n", - g_guest_info_item[j]); - - if (info->g_guest_data_type[j] == 0) { - ret += snprintf(buf_tmp + ret, - len - ret, "%s", - info->g_guest_str_in_format[j]); - } else { - ret = printMat(buf_tmp, len, - info->g_guest_data_len[j], - info->g_guest_str_in_format[j], - ret); - } - ret += snprintf(buf_tmp + ret, len - ret, "\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 (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 ssize_t himax_debug_read(struct file *file, char *buf, - size_t len, loff_t *pos) -{ - ssize_t ret = 0; - int i = 0; - - if (!HX_PROC_SEND_FLAG) { - I("%s, Enter\n", __func__); - - memset(buf_tmp, 0, sizeof(buf_tmp)); - if (dbg_cmd_flag) { - if (dbg_func_ptr_r[dbg_cmd_flag]) - ret += dbg_func_ptr_r[dbg_cmd_flag](buf, len); - else - goto END_FUNC_R; - } - - if (debug_level_cmd == 't') { - if (!fw_update_going) { - if (fw_update_complete) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "FW Update Complete "); - else - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "FW Update Fail "); - } else { - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "FW Update Ongoing "); - } - } else if (debug_level_cmd == 'h') { - if (handshaking_result == 0) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Handshaking Result = %d (MCU Running)\n", - handshaking_result); - else if (handshaking_result == 1) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Handshaking Result = %d (MCU Stop)\n", - handshaking_result); - else if (handshaking_result == 2) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Handshaking Result = %d (I2C Error)\n", - handshaking_result); - else - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Handshaking Result = error\n"); - - } else if (debug_level_cmd == 'v') { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "FW_VER = 0x%2.2X\n", ic_data->vendor_fw_ver); - - if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "CONFIG_VER = 0x%2.2X\n", - ic_data->vendor_config_ver); - else { - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "TOUCH_VER = 0x%2.2X\n", - ic_data->vendor_touch_cfg_ver); - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "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) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "CID_VER = NULL\n"); - else - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "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) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "PANEL_VER = NULL\n"); - else - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "PANEL_VER = 0x%2.2X\n", - ic_data->vendor_panel_ver); - if (private_ts->chip_cell_type == CHIP_IS_IN_CELL) { - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Cusomer = %s\n", - ic_data->vendor_cus_info); - - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Project = %s\n", - ic_data->vendor_proj_info); - } - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, "\n"); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "Himax Touch Driver Version:\n"); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "%s\n", HIMAX_DRIVER_VER); - } else if (debug_level_cmd == 'd') { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "Himax Touch IC Information :\n"); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "%s\n", private_ts->chip_name); - - switch (IC_CHECKSUM) { - case HX_TP_BIN_CHECKSUM_SW: - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "IC Checksum : SW\n"); - break; - - case HX_TP_BIN_CHECKSUM_HW: - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "IC Checksum : HW\n"); - break; - - case HX_TP_BIN_CHECKSUM_CRC: - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "IC Checksum : CRC\n"); - break; - - default: - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "IC Checksum error.\n"); - } - - if (ic_data->HX_INT_IS_EDGE) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Driver register Interrupt : EDGE TIRGGER\n"); - else - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Driver register Interrupt : LEVEL TRIGGER\n"); - - if (private_ts->protocol_type == PROTOCOL_TYPE_A) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Protocol : TYPE_A\n"); - else - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Protocol : TYPE_B\n"); - - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "RX Num : %d\n", ic_data->HX_RX_NUM); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "TX Num : %d\n", ic_data->HX_TX_NUM); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "BT Num : %d\n", ic_data->HX_BT_NUM); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "X Resolution : %d\n", ic_data->HX_X_RES); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "Y Resolution : %d\n", ic_data->HX_Y_RES); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "Max Point : %d\n", ic_data->HX_MAX_PT); - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "XY reverse : %d\n", ic_data->HX_XY_REVERSE); -#if defined(HX_TP_PROC_2T2R) - if (Is_2T2R) { - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "2T2R panel\n"); - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "RX Num_2 : %d\n", HX_RX_NUM_2); - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "TX Num_2 : %d\n", HX_TX_NUM_2); - } -#endif - } else if (debug_level_cmd == 'i') { - if (g_core_fp.fp_read_i2c_status()) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "I2C communication is bad.\n"); - else - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "I2C communication is good.\n"); - } else if (debug_level_cmd == 'n') { - /* Edgd = 1, Level = 0 */ - if (g_core_fp.fp_read_ic_trigger_type() == 1) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "IC Interrupt type is edge trigger.\n"); - else if (g_core_fp.fp_read_ic_trigger_type() == 0) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "IC Interrupt type is level trigger.\n"); - else - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Unkown IC trigger type.\n"); - - if (ic_data->HX_INT_IS_EDGE) - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Driver register Interrupt : EDGE TIRGGER\n"); - else - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "Driver register Interrupt : LEVEL TRIGGER\n"); - } else if (debug_level_cmd == 'l') { - ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, - "LotID : "); - for (i = 0; i < 13; i++) { - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, - "%02X", ic_data->vendor_ic_id[i]); - } - ret += snprintf(buf_tmp + ret, - sizeof(buf_tmp) - ret, "\n"); - } - -END_FUNC_R: - if (copy_to_user(buf, buf_tmp, (len > BUF_SIZE)?BUF_SIZE:len)) - I("%s,here:%d\n", __func__, __LINE__); - - HX_PROC_SEND_FLAG = 1; - } else { - HX_PROC_SEND_FLAG = 0; - } - - return ret; -} - -static ssize_t himax_debug_write(struct file *file, const char *buff, - size_t len, loff_t *pos) -{ - char fileName[128]; - char buf[80] = "\0"; - int result = 0; -#if !defined(HX_ZERO_FLASH) - int fw_type = 0; - const struct firmware *fw = NULL; -#endif - - char *str_ptr = NULL; - int str_len = 0; - int i = 0; - - - if (len >= 80) { - I("%s: no command exceeds 80 chars.\n", __func__); - return -EFAULT; - } - - if (copy_from_user(buf, buff, len)) - return -EFAULT; - - buf[strlen(buf) - 1] = 0;/*remove \n*/ - - while (dbg_cmd_str[i]) { - str_ptr = strnstr(buf, dbg_cmd_str[i], len); - if (str_ptr) { - str_len = strlen(dbg_cmd_str[i]); - dbg_cmd_flag = i + 1; - debug_level_cmd = 0; - I("Cmd is correct :%s, dbg_cmd = %d\n", - str_ptr, dbg_cmd_flag); - break; - } - i++; - } - if (!str_ptr) { - I("Cmd is not correct\n"); - dbg_cmd_flag = 0; - } - - 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\n", - buf + str_len + 1, dbg_cmd_par); - } else { - I("No paremeter of this cmd\n"); - } - - if (dbg_cmd_flag) - return len; - - if (buf[0] == 'h') { /* handshaking */ - debug_level_cmd = buf[0]; - himax_int_enable(0); - /* 0:Running, 1:Stop, 2:I2C Fail */ - handshaking_result = g_core_fp.fp_hand_shaking(); - himax_int_enable(1); - return len; - } else if (buf[0] == 'v') { /* firmware version */ - himax_int_enable(0); -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(false, false); -#endif - debug_level_cmd = buf[0]; - g_core_fp.fp_read_FW_ver(); -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(true, false); -#else - g_core_fp.fp_system_reset(); -#endif -#if defined(HX_ZERO_FLASH) - if (g_core_fp.fp_0f_reload_to_active) - g_core_fp.fp_0f_reload_to_active(); -#endif - himax_int_enable(1); - /* himax_check_chip_version(); */ - return len; - } else if (buf[0] == 'd') { /* ic information */ - debug_level_cmd = buf[0]; - return len; - } else if (buf[0] == 't') { - if (buf[1] == 's' - && buf[2] == 'd' - && buf[3] == 'b' - && buf[4] == 'g') { - 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"); - } - goto ENDFUCTION; - } - himax_int_enable(0); - debug_level_cmd = buf[0]; - fw_update_complete = false; - fw_update_going = true; - memset(fileName, 0, 128); - /* parse the file name */ - snprintf(fileName, len - 2, "%s", &buf[2]); - -#if defined(HX_ZERO_FLASH) - I("NOW Running Zero flash update!\n"); - I("%s: upgrade from file(%s) start!\n", __func__, fileName); - result = g_core_fp.fp_0f_op_file_dirly(fileName); - if (result) { - fw_update_complete = false; - I("Zero flash update fail!\n"); - goto ENDFUCTION; - } else { - fw_update_complete = true; - I("Zero flash update complete!\n"); - } - goto firmware_upgrade_done; -#else - I("NOW Running common flow update!\n"); - I("%s: upgrade from file(%s) start!\n", __func__, fileName); - result = request_firmware(&fw, fileName, private_ts->dev); - - if (result < 0) { - I("fail to request_firmware fwpath: %s (ret:%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]); - fw_type = (fw->size) / 1024; - /* start to upgrade */ - himax_int_enable(0); - 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; - - default: - E("%s: Flash command fail: %d\n", __func__, __LINE__); - fw_update_complete = false; - break; - } - release_firmware(fw); - goto firmware_upgrade_done; -#endif - } else if (buf[0] == 'i' && buf[1] == '2' && buf[2] == 'c') { - /* i2c communication */ - debug_level_cmd = 'i'; - return len; - } else if (buf[0] == 'i' && buf[1] == 'n' && buf[2] == 't') { - /* INT trigger */ - debug_level_cmd = 'n'; - return len; -#if defined(HX_ZERO_FLASH) - } else if (buf[0] == 'z') { - result = buf[1] - '0'; - I("check type = %d\n", result); - g_core_fp.fp_0f_operation_check(result); - return len; - } else if (buf[0] == 'p') { - I("NOW debug echo r!\n"); - /* himax_program_sram(); */ - private_ts->himax_0f_update_wq = - create_singlethread_workqueue( - "HMX_update_0f_reuqest_write"); - - if (!private_ts->himax_0f_update_wq) - E(" allocate syn_update_wq failed\n"); - - INIT_DELAYED_WORK(&private_ts->work_0f_update, - g_core_fp.fp_0f_operation); - queue_delayed_work(private_ts->himax_0f_update_wq, - &private_ts->work_0f_update, msecs_to_jiffies(100)); - return len; - } else if (buf[0] == 'x') { - g_core_fp.fp_system_reset(); -#if defined(HX_ZERO_FLASH) - if (g_core_fp.fp_0f_reload_to_active) - g_core_fp.fp_0f_reload_to_active(); -#endif - return len; -#endif - } else if (buf[0] == 'l' && buf[1] == 'o' && buf[2] == 't') { - debug_level_cmd = buf[0]; - g_core_fp.fp_sense_off(true); - g_core_fp.fp_ic_id_read(); - g_core_fp.fp_sense_on(0x01); - return len; - } - /* others,do nothing */ - debug_level_cmd = 0; - return len; - -firmware_upgrade_done: - fw_update_going = false; - g_core_fp.fp_reload_disable(0); - g_core_fp.fp_read_FW_ver(); - g_core_fp.fp_touch_information(); -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(true, false); -#if defined(HX_ZERO_FLASH) - if (g_core_fp.fp_0f_reload_to_active) - g_core_fp.fp_0f_reload_to_active(); -#endif -#else - g_core_fp.fp_sense_on(0x00); -#endif - - himax_int_enable(1); - /* todo himax_chip->tp_firmware_upgrade_proceed = 0; - * todo himax_chip->suspend_state = 0; - * todo enable_irq(himax_chip->irq); - */ -ENDFUCTION: - return len; -} - -static const struct file_operations himax_proc_debug_ops = { - .owner = THIS_MODULE, - .read = himax_debug_read, - .write = himax_debug_write, -}; - -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; -} - -static void himax_ts_flash_work_func(struct work_struct *work) -{ - himax_ts_flash_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(); -} - -void dbg_func_ptr_init(void) -{ - /*debug function ptr init*/ - dbg_func_ptr_r[1] = himax_crc_test_read; - dbg_func_ptr_r[2] = himax_proc_FW_debug_read; - dbg_func_ptr_r[3] = himax_attn_read; - dbg_func_ptr_r[4] = himax_layout_read; - dbg_func_ptr_w[4] = himax_layout_write; - dbg_func_ptr_r[5] = himax_proc_DD_debug_read; - dbg_func_ptr_w[5] = himax_proc_DD_debug_write; -#if defined(HX_ESD_RECOVERY) - dbg_func_ptr_r[6] = himax_esd_cnt_read; - dbg_func_ptr_w[6] = himax_esd_cnt_write; -#endif - dbg_func_ptr_w[7] = himax_sense_on_off_write; - dbg_func_ptr_r[8] = himax_debug_level_read; - dbg_func_ptr_w[8] = himax_debug_level_write; -#if defined(HX_TP_PROC_GUEST_INFO) - dbg_func_ptr_r[9] = himax_proc_guest_info_read; - dbg_func_ptr_w[9] = himax_proc_guest_info_write; -#endif - dbg_func_ptr_r[10] = himax_int_en_read; - dbg_func_ptr_w[10] = himax_int_en_write; - dbg_func_ptr_w[11] = himax_proc_register_write; - dbg_func_ptr_r[11] = himax_proc_register_read; - dbg_func_ptr_w[12] = himax_reset_write; - dbg_func_ptr_w[13] = himax_diag_arrange_write; - dbg_func_ptr_w[14] = himax_diag_cmd_write; -} - -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_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, 0444, - himax_touch_proc_dir, &himax_proc_vendor_ops); - if (himax_proc_vendor_file == NULL) { - E(" %s: proc vendor file create failed!\n", __func__); - goto fail_1; - } - - himax_proc_stack_file = proc_create(HIMAX_PROC_STACK_FILE, 0444, - himax_proc_diag_dir, &himax_proc_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_proc_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_proc_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_proc_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_proc_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_proc_flash_ops); - if (himax_proc_flash_dump_file == NULL) { - E(" %s: proc flash dump file create failed!\n", __func__); - goto fail_4; - } - - if (!ic_data->HX_PEN_FUNC) - goto skip_pen_operation; - - himax_proc_pen_pos_file = proc_create(HIMAX_PROC_PEN_POS_FILE, - 0644, - himax_touch_proc_dir, &himax_proc_pen_pos_ops); - if (himax_proc_pen_pos_file == NULL) { - E(" %s: proc CRC test file create failed!\n", __func__); - goto fail_5; - } -skip_pen_operation: - - return 0; - - /* remove_proc_entry(HIMAX_PROC_PEN_POS_FILE, himax_touch_proc_dir); */ -fail_5: remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir); -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: remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir); -fail_1: - return -ENOMEM; -} - -void himax_touch_proc_deinit(void) -{ - if (ic_data->HX_PEN_FUNC) - remove_proc_entry(HIMAX_PROC_PEN_POS_FILE, - himax_touch_proc_dir); - - 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); - remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_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; - } - - reg_read_data = kzalloc(128 * sizeof(uint8_t), GFP_KERNEL); - if (reg_read_data == 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(); - - ts->flash_wq = create_singlethread_workqueue("himax_flash_wq"); - - if (!ts->flash_wq) { - E("%s: create flash workqueue failed\n", __func__); - goto err_create_flash_dump_wq_failed; - } - - INIT_WORK(&ts->flash_work, himax_ts_flash_work_func); - - g_flash_progress = START; - setFlashBuffer(); - if (flash_buffer == NULL) { - E("%s: flash buffer allocate fail failed\n", __func__); - goto err_flash_buf_alloc_failed; - } - -#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 - - 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_wrok, himax_ts_diag_work_func); - - 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 - - if (himax_touch_proc_init()) - goto err_proc_init_failed; - - return 0; - -err_proc_init_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: - cancel_delayed_work_sync(&ts->himax_diag_delay_wrok); - destroy_workqueue(ts->himax_diag_wq); -err_create_diag_wq_failed: - -#if defined(HX_TP_PROC_GUEST_INFO) - 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 - kfree(flash_buffer); - flash_buffer = NULL; -err_flash_buf_alloc_failed: - destroy_workqueue(ts->flash_wq); -err_create_flash_dump_wq_failed: - kfree(debug_data); - debug_data = NULL; -err_alloc_debug_data_fail: - kfree(reg_read_data); - reg_read_data = 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_wrok); -#if defined(HX_TP_PROC_GUEST_INFO) - destroy_workqueue(ts->guest_info_wq); - if (g_guest_info_data != NULL) - kfree(g_guest_info_data); -#endif - destroy_workqueue(ts->himax_diag_wq); - destroy_workqueue(ts->flash_wq); - - if (debug_data != NULL) - kfree(debug_data); - if (reg_read_data != NULL) - kfree(reg_read_data); - - return 0; -} -EXPORT_SYMBOL(himax_debug_remove); - +/* 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" + +#ifdef HX_TP_PROC_2T2R + bool Is_2T2R; + int HX_RX_NUM_2; + int HX_TX_NUM_2; +#endif + +uint8_t g_diag_arr_num; + +int g_max_mutual; +int g_min_mutual = 0xFFFF; +int g_max_self; +int g_min_self = 0xFFFF; + +/* moved from debug.h */ + +struct proc_dir_entry *himax_proc_vendor_file; +uint8_t byte_length; +uint8_t register_command[4]; +uint8_t cfg_flag; + +struct proc_dir_entry *himax_proc_stack_file; +struct proc_dir_entry *himax_proc_iir_file; +struct proc_dir_entry *himax_proc_dc_file; +struct proc_dir_entry *himax_proc_bank_file; +bool dsram_flag; + +#ifdef 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 diag_max_cnt; +uint8_t hx_state_info[2]; +uint8_t diag_coor[128]; +int32_t diag_self[100]; +int32_t diag_self_new[100]; +int32_t diag_self_old[100]; + +struct proc_dir_entry *himax_proc_debug_file; +bool fw_update_complete; +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; +int Flash_Size = 131072; +uint8_t *flash_buffer; +uint8_t g_flash_cmd; +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}; +uint8_t *reg_read_data = NULL; +#define DEBUG_READ_BUF_SIZE 128 + + +#if defined(HX_PEN_FUNC_EN) + struct proc_dir_entry *himax_proc_pen_pos_file; +#endif + +struct timespec timeStart, timeEnd, timeDelta; +int g_switch_mode; +/* + * Segment : Himax PROC Debug Function + */ + +#if defined(HX_PEN_FUNC_EN) +static ssize_t himax_pen_ops_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + int i = 0; + ssize_t ret = 0; + + if (!HX_PROC_SEND_FLAG) { + for (i = 0; i < private_ts->nFinger_support; i++) { + if (g_target_report_data->x[i] >= 0 && g_target_report_data->x[i] <= private_ts->pdata->abs_x_max + && g_target_report_data->y[i] >= 0 && g_target_report_data->y[i] <= private_ts->pdata->abs_y_max + && private_ts->hx_point_num != 0) { + ret += snprintf(buf_tmp + ret, len - ret, + "%d,%d,", g_target_report_data->x[i], g_target_report_data->y[i]); + } else { + ret += snprintf(buf_tmp + ret, len - ret, + "65535,65535,"); + } + } + if (g_target_report_data->p_x[0] >= 0 && g_target_report_data->p_x[0] <= private_ts->pdata->abs_x_max + && g_target_report_data->p_y[0] >= 0 && g_target_report_data->p_y[0] <= private_ts->pdata->abs_y_max + && (g_target_report_data->p_on[0] == 1)) { + ret += snprintf(buf_tmp + ret, len - ret, + "%d,%d,", g_target_report_data->p_x[0], g_target_report_data->p_y[0]); + } else { + ret += snprintf(buf_tmp + ret, len - ret, + "65535,65535,"); + } + + ret += snprintf(buf_tmp + ret, len - ret, + "%d,", g_target_report_data->p_w[0]); + + ret += snprintf(buf_tmp + ret, len - ret, + "%d,", g_target_report_data->p_hover[0]); + + if (g_target_report_data->p_btn[0] != 0xff) { + ret += snprintf(buf_tmp + ret, len - ret, + "%d,", g_target_report_data->p_btn[0]); + } else { + ret += snprintf(buf_tmp + ret, len - ret, + "0,"); + } + if (g_target_report_data->p_btn2[0] != 0xff) { + ret += snprintf(buf_tmp + ret, len - ret, + "%d,", g_target_report_data->p_btn2[0]); + } else { + ret += snprintf(buf_tmp + ret, len - ret, + "0,"); + } + + if (g_target_report_data->p_tilt_x[0] != 0xff) { + ret += snprintf(buf_tmp + ret, len - ret, + "%d,", g_target_report_data->p_tilt_x[0]); + } else { + ret += snprintf(buf_tmp + ret, len - ret, + "0,"); + } + if (g_target_report_data->p_tilt_y[0] != 0xff) { + ret += snprintf(buf_tmp + ret, len - ret, + "%d\n", g_target_report_data->p_tilt_y[0]); + } else { + ret += snprintf(buf_tmp + ret, len - ret, + "0\n"); + } + + if (copy_to_user(buf, buf_tmp, (len > BUF_SIZE) ? BUF_SIZE : len)) + I("%s,here:%d\n", __func__, __LINE__); + + HX_PROC_SEND_FLAG = 1; + } else { + HX_PROC_SEND_FLAG = 0; + } + + return ret; +} + +static const struct file_operations himax_proc_pen_pos_ops = { + .owner = THIS_MODULE, + .read = himax_pen_ops_read, +}; +#endif + +static ssize_t himax_crc_test_read(char *buf, size_t len) +{ + ssize_t 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) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "CRC test is Pass!\n"); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "CRC test is Fail!\n"); + + return ret; +} + +static ssize_t himax_vendor_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + ssize_t ret = 0; + + if (!HX_PROC_SEND_FLAG) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "FW_VER = 0x%2.2X\n", + ic_data->vendor_fw_ver); + + if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "CONFIG_VER = 0x%2.2X\n", + ic_data->vendor_config_ver); + } else { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "TOUCH_VER = 0x%2.2X\n", + ic_data->vendor_touch_cfg_ver); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "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) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "CID_VER = NULL\n"); + } else { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "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) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "PANEL_VER = NULL\n"); + } else { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "PANEL_VER = 0x%2.2X\n", + ic_data->vendor_panel_ver); + } + if (private_ts->chip_cell_type == CHIP_IS_IN_CELL) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Cusomer = %s\n", ic_data->vendor_cus_info); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Project = %s\n", ic_data->vendor_proj_info); + } +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) +#ifdef HX_EN_DYNAMIC_NAME + if (ic_data->vendor_semifac == 1) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "SEMI_FAC = UMC\n"); + } else if (ic_data->vendor_semifac == 2) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "SEMI_FAC = PSC\n"); + } else { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "SEMI_FAC = NULL\n"); + } +#endif +#endif + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Himax Touch Driver Version:\n"); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%s\n", + HIMAX_DRIVER_VER); + HX_PROC_SEND_FLAG = 1; + + if (copy_to_user(buf, buf_tmp, (len > BUF_SIZE) ? BUF_SIZE : len)) + I("%s,here:%d\n", __func__, __LINE__); + + } else { + HX_PROC_SEND_FLAG = 0; + } + + return ret; +} + +static const struct file_operations himax_proc_vendor_ops = { + .owner = THIS_MODULE, + .read = himax_vendor_read, +}; + +static ssize_t himax_attn_read(char *buf, size_t len) +{ + ssize_t ret = 0; + struct himax_ts_data *ts_data; + + ts_data = private_ts; + + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "attn = %x\n", + himax_int_gpio_read(ts_data->pdata->gpio_irq)); + + return ret; +} + +static ssize_t himax_int_en_read(char *buf, size_t len) +{ + struct himax_ts_data *ts = private_ts; + size_t ret = 0; + + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%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 value, ret = 0; + + if (len >= 12) { + I("%s: no command exceeds 12 chars.\n", __func__); + return -EFAULT; + } + + if (buf[0] == '0') + value = false; + else if (buf[0] == '1') + value = true; + else + return -EINVAL; + + if (value) { + ret = himax_int_en_set(); + + if (ret == 0) { + ts->irq_enabled = 1; + irq_enable_count = 1; + } + } else { + himax_int_enable(0); + free_irq(ts->hx_irq, ts); + ts->irq_enabled = 0; + } + + return len; +} + +static ssize_t himax_layout_read(char *buf, size_t len) +{ + struct himax_ts_data *ts = private_ts; + size_t ret = 0; + + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d ", + ts->pdata->abs_x_min); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d ", + ts->pdata->abs_x_max); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d ", + ts->pdata->abs_y_min); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d ", + ts->pdata->abs_y_max); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\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; + } + + 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); + } + + return len; +} + +static ssize_t himax_debug_level_read(char *buf, size_t len) +{ + struct himax_ts_data *ts_data; + size_t ret = 0; + + ts_data = private_ts; + + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "%d\n", + ts_data->debug_log_level); + + if (copy_to_user(buf, buf_tmp, (len > BUF_SIZE) ? BUF_SIZE : len)) + I("%s,here:%d\n", __func__, __LINE__); + + return ret; +} + +static ssize_t himax_debug_level_write(char *buf, size_t len) +{ + struct himax_ts_data *ts; + int i; + + ts = private_ts; + + if (len >= 12) { + I("%s: no command exceeds 12 chars.\n", __func__); + return -EFAULT; + } + + 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("Enable finger debug with raw position mode!\n"); + } + } else { + ts->useScreenRes = 0; + ts->widthFactor = 0; + ts->heightFactor = 0; + } +END_FUNC: + return len; +} + +static ssize_t himax_proc_register_read(char *buf, size_t len) +{ + int ret = 0; + uint16_t loop_i; + + if(reg_read_data == NULL){ + E("%s reg_read_data is null \n",__func__); + return ret; + } + memset(reg_read_data, 0x00, DEBUG_READ_BUF_SIZE * sizeof(uint8_t)); + + I("himax_register_show: %02X,%02X,%02X,%02X\n", + register_command[3], register_command[2], + register_command[1], register_command[0]); + g_core_fp.fp_register_read(register_command, 128, reg_read_data, + cfg_flag); + ret += snprintf(buf_tmp + ret, len - ret, + "command: %02X,%02X,%02X,%02X\n", + register_command[3], register_command[2], + register_command[1], register_command[0]); + + for (loop_i = 0; loop_i < 128; loop_i++) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "0x%2.2X ", + reg_read_data[loop_i]); + if ((loop_i % 16) == 15) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); + + } + + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); + + return ret; +} + +static ssize_t himax_proc_register_write(char *buf, size_t len) +{ + char buff_tmp[16] = {0}; + uint8_t length = 0; + unsigned long result = 0; + uint8_t loop_i = 0; + uint16_t base = 2; + char *data_str = NULL; + uint8_t w_data[20] = {0}; + uint8_t x_pos[20] = {0}; + uint8_t count = 0; + + if (len >= 80) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + memset(register_command, 0x0, sizeof(register_command)); + + I("himax %s\n", buf); + + if ((buf[0] == 'r' || buf[0] == 'w') && buf[1] == ':' && + buf[2] == 'x') { + length = strlen(buf); + + /* I("%s: length = %d.\n", __func__,length); */ + for (loop_i = 0; loop_i < length; loop_i++) { + /* find postion of 'x' */ + if (buf[loop_i] == 'x') { + x_pos[count] = loop_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 - base; + cfg_flag = 1; + memcpy(buff_tmp, data_str + base + 1, length); + } else { + cfg_flag = 0; + memcpy(buff_tmp, data_str + 1, length); + } + byte_length = length / 2; + if (!kstrtoul(buff_tmp, 16, &result)) { + for (loop_i = 0; loop_i < byte_length; loop_i++) + register_command[loop_i] = + (uint8_t)(result >> loop_i * 8); + } + + if (strcmp(HX_85XX_H_SERIES_PWON, + private_ts->chip_name) == 0 && cfg_flag == 0) + cfg_flag = 2; + break; + case 'w': + if (buf[3] == 'F' && buf[4] == 'E') { + cfg_flag = 1; + memcpy(buff_tmp, buf + base + 3, length); + } else { + cfg_flag = 0; + memcpy(buff_tmp, buf + 3, length); + } + + if (count < 3) { + byte_length = length / 2; + + if (!kstrtoul(buff_tmp, 16, &result)) { + /* command */ + for (loop_i = 0; loop_i < byte_length; + loop_i++) { + register_command[loop_i] = + (uint8_t)(result >> loop_i * 8); + } + } + + if (!kstrtoul(data_str + 1, 16, &result)) { + /* data */ + for (loop_i = 0; loop_i < byte_length; + loop_i++) { + w_data[loop_i] = + (uint8_t)(result >> loop_i * 8); + } + } + + g_core_fp.fp_register_write(register_command, + byte_length, w_data, cfg_flag); + } else { + for (loop_i = 0; loop_i < count; loop_i++) { + /* parsing addr after 'x' */ + memset(buff_tmp, 0x0, sizeof(buff_tmp)); + if (cfg_flag != 0 && loop_i != 0) + byte_length = 2; + else + byte_length = x_pos[1] - + x_pos[0] - 2;/* original */ + memcpy(buff_tmp, buf + x_pos[loop_i] + 1, + byte_length); + + /* I("%s: buff_tmp = %s\n", __func__, + * buff_tmp); + */ + if (!kstrtoul(buff_tmp, 16, &result)) { + if (loop_i == 0) { + register_command[loop_i] + = (uint8_t)(result); + /* I("%s: + * register_command + * = %X\n", __func__, + * register_command[0]); + */ + } else { + w_data[loop_i - 1] = + (uint8_t)(result); + /* I("%s: w_data[%d] = + * %2X\n", __func__, + * loop_i - 1, + * w_data[loop_i - 1]); + */ + } + } + } + + byte_length = count - 1; + if (strcmp(HX_85XX_H_SERIES_PWON, + private_ts->chip_name) == 0 && cfg_flag == 0) + cfg_flag = 2; + g_core_fp.fp_register_write(register_command, + byte_length, &w_data[0], cfg_flag); + + } + break; + }; + } + 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[0]; +} +int32_t *getSelfNewBuffer(void) +{ + return &diag_self_new[0]; +} +int32_t *getSelfOldBuffer(void) +{ + return &diag_self_old[0]; +} +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); +} + +#ifdef 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; + +#ifdef 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; +#ifdef HX_EN_SEL_BUTTON + self_num = ic_data->HX_RX_NUM_2 + + ic_data->HX_TX_NUM_2 + ic_data->HX_BT_NUM; +#else + self_num = ic_data->HX_RX_NUM_2 + ic_data->HX_TX_NUM_2; +#endif + } 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; +#ifdef HX_EN_SEL_BUTTON + self_num = ic_data->HX_RX_NUM + + ic_data->HX_TX_NUM + ic_data->HX_BT_NUM; +#else + self_num = ic_data->HX_RX_NUM + ic_data->HX_TX_NUM; +#endif + } + 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 loop_i = 0; + int print_size = 0; + uint8_t *buf; + + 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); + 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); + 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); + memcpy(buf, hx_touch_data->hx_coord_buf, print_size); + } else { + E("%s:cmd fault\n", __func__); + } + + for (loop_i = 0; loop_i < print_size; loop_i += 8) { + if ((loop_i + 7) >= print_size) { + I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", + loop_i, buf[loop_i], loop_i + 1, buf[loop_i + 1]); + I("P %2d = 0x%2.2X P %2d = 0x%2.2X\n", + loop_i + 2, buf[loop_i + 2], loop_i + 3, buf[loop_i + 3]); + break; + } + + I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", + loop_i, buf[loop_i], loop_i + 1, buf[loop_i + 1]); + I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", + loop_i + 2, buf[loop_i + 2], loop_i + 3, buf[loop_i + 3]); + I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", + loop_i + 4, buf[loop_i + 4], loop_i + 5, buf[loop_i + 5]); + I("P %2d = 0x%2.2X P %2d = 0x%2.2X ", + loop_i + 6, buf[loop_i + 6], loop_i + 7, buf[loop_i + 7]); + I("\n"); + } + kfree(buf); +} +void himax_log_touch_event(struct himax_ts_data *ts, int start) +{ + int loop_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 (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + if (g_target_report_data->x[loop_i] >= 0 + && g_target_report_data->x[loop_i] + <= ts->pdata->abs_x_max + && g_target_report_data->y[loop_i] >= 0 + && g_target_report_data->y[loop_i] + <= ts->pdata->abs_y_max) { + I("Finger %d=> X:%d, Y:%d W:%d, Z:%d, F:%d,Int_Delay_Counter:%d\n", + loop_i + 1, + g_target_report_data->x[loop_i], + g_target_report_data->y[loop_i], + g_target_report_data->w[loop_i], + g_target_report_data->w[loop_i], + loop_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) { + getnstimeofday(&timeStart); + /* I(" Irq start time = %ld.%06ld s\n", + * timeStart.tv_sec, timeStart.tv_nsec/1000); + */ + } else if (touched == HX_FINGER_LEAVE) { + getnstimeofday(&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", 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__); + } +} + +#define RAW_DOWN_STATUS "status: Raw:F:%02d Down, X:%d, Y:%d, W:%d\n" +#define RAW_UP_STATUS "status: Raw:F:%02d Up, X:%d, Y:%d\n" + +void himax_log_touch_event_detail(struct himax_ts_data *ts, int start) +{ + int loop_i = 0; + + if (start == HX_FINGER_LEAVE) { + for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { + if (((ts->old_finger >> loop_i & 1) == 0) && + ((ts->pre_finger_mask >> loop_i & 1) == 1)) { + if (g_target_report_data->x[loop_i] >= 0 + && g_target_report_data->x[loop_i] + <= ts->pdata->abs_x_max + && g_target_report_data->y[loop_i] >= 0 + && g_target_report_data->y[loop_i] + <= ts->pdata->abs_y_max) { + I(RAW_DOWN_STATUS, + loop_i + 1, + g_target_report_data->x[loop_i], + g_target_report_data->y[loop_i], + g_target_report_data->w[loop_i]); + } + } else if ((((ts->old_finger >> loop_i & 1) == 1) && + ((ts->pre_finger_mask >> loop_i & 1) == 0))) { + I(RAW_UP_STATUS, + loop_i + 1, ts->pre_finger_data[loop_i][0], + ts->pre_finger_data[loop_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++); + msleep(50); + } while (count < 50); + + return ERR_WORK_OUT; +} + +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; + + 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; + dsram_flag = false; + cancel_delayed_work(&ts->himax_diag_delay_wrok); + himax_int_enable(1); + g_core_fp.fp_return_event_stack(); + } + g_core_fp.fp_diag_register_set(ts->diag_cmd, 0); + 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 (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); + queue_delayed_work(ts->himax_diag_wq, + &ts->himax_diag_delay_wrok, 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); + } + } + 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("%s: change mode 0x%4X. str_pw = %2X, end_pw = %2X\n", __func__, rst, str_pw, end_pw); + } else + I("%s: change mode failed. str_pw = %2X, end_pw = %2X\n", __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__); + } + return len; +} + +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; + } + + 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]); + */ + +#ifdef 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]); + } + } +} + +static void *himax_diag_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos >= 1) + return NULL; + + return (void *)((unsigned long) *pos + 1); +} + +static void *himax_diag_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + return NULL; +} + +static void himax_diag_seq_stop(struct seq_file *s, void *v) +{ + kfree(v); +} + +/* DSRAM thread */ +bool himax_ts_diag_func(void) +{ + int retry = 3; + 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; + 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 */ + int dsram_type = process_type; + + info_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL); + if (info_data == NULL) + return false; + + memset(info_data, 0, total_size * sizeof(uint8_t)); + + I("%s: process type=%d!\n", __func__, process_type); + + g_core_fp.fp_burst_enable(1); + + if (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(); + } + + do { + if (retry <= 0) { + E("%s Get DSRAM data failed\n", __func__); + kfree(info_data); + return false; + } + if (g_core_fp.fp_get_DSRAM_data(info_data, dsram_flag)) + break; + } while (retry-- > 0); + + 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 = (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 */ + } + + diag_max_cnt++; + + if (dsram_type >= 1 && dsram_type <= 3) { + queue_delayed_work(private_ts->himax_diag_wq, + &private_ts->himax_diag_delay_wrok, 1 / 10 * HZ); + } + 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"); +#ifdef HX_EN_SEL_BUTTON + seq_puts(s, "\n"); + for (loop_i = 0; loop_i < ic_data->HX_BT_NUM; loop_i++) + seq_printf(s, "%6d", diag_self[ic_data->HX_RX_NUM + + ic_data->HX_TX_NUM + loop_i]); +#endif + 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_diag_stack_read(struct seq_file *s, void *v) +{ + struct himax_ts_data *ts = private_ts; + + if (ts->diag_cmd) + himax_diag_print(s, v); + else + seq_puts(s, "Please set raw out select 'echo diag,rs:X > debug'\n\n"); + + return 0; +} + +static const struct seq_operations himax_diag_stack_ops = { + .start = himax_diag_seq_start, + .next = himax_diag_seq_next, + .stop = himax_diag_seq_stop, + .show = himax_diag_stack_read, +}; + +static int himax_diag_stack_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &himax_diag_stack_ops); +}; + +static const struct file_operations himax_proc_stack_ops = { + .owner = THIS_MODULE, + .open = himax_diag_stack_open, + .read = seq_read, + .release = seq_release, +}; + +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; + + d_type = (!ts->diag_cmd)?rs:ts->diag_cmd; + + if (!overflow) { + if (!process_type) { + himax_int_enable(0); + g_core_fp.fp_diag_register_set(d_type, 0); + + if (!himax_ts_diag_func()) + 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); + 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_diag_iir_read(struct seq_file *s, void *v) +{ + return himax_sram_read(s, v, 0x09); +} + +static const struct seq_operations himax_diag_iir_ops = { + .start = himax_diag_seq_start, + .next = himax_diag_seq_next, + .stop = himax_diag_seq_stop, + .show = himax_diag_iir_read, +}; + +static int himax_diag_iir_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &himax_diag_iir_ops); +}; + +static const struct file_operations himax_proc_iir_ops = { + .owner = THIS_MODULE, + .open = himax_diag_iir_open, + .read = seq_read, + .release = seq_release, +}; + +static int himax_diag_dc_read(struct seq_file *s, void *v) +{ + return himax_sram_read(s, v, 0x0A); +} + +static const struct seq_operations himax_diag_dc_ops = { + .start = himax_diag_seq_start, + .next = himax_diag_seq_next, + .stop = himax_diag_seq_stop, + .show = himax_diag_dc_read, +}; +static int himax_diag_dc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &himax_diag_dc_ops); +}; + +static const struct file_operations himax_proc_dc_ops = { + .owner = THIS_MODULE, + .open = himax_diag_dc_open, + .read = seq_read, + .release = seq_release, +}; + +static int himax_diag_bank_read(struct seq_file *s, void *v) +{ + return himax_sram_read(s, v, 0x0B); +} + +static const struct seq_operations himax_diag_bank_ops = { + .start = himax_diag_seq_start, + .next = himax_diag_seq_next, + .stop = himax_diag_seq_stop, + .show = himax_diag_bank_read, +}; +static int himax_diag_bank_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &himax_diag_bank_ops); +}; + +static const struct file_operations himax_proc_bank_ops = { + .owner = THIS_MODULE, + .open = himax_diag_bank_open, + .read = seq_read, + .release = seq_release, +}; + +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; + } + +#ifdef HX_RST_PIN_FUNC + if (buf[0] == '1') + g_core_fp.fp_ic_reset(false, false); + else if (buf[0] == '2') + g_core_fp.fp_ic_reset(false, true); + else if (buf[0] == '3') + g_core_fp.fp_ic_reset(true, false); + else if (buf[0] == '4') + g_core_fp.fp_ic_reset(true, true); + /* else if (buf[0] == '5') */ + /* ESD_HW_REST(); */ +#endif +#if defined(HX_ZERO_FLASH) && defined(HX83102D) + if (g_core_fp.fp_0f_reload_to_active) + g_core_fp.fp_0f_reload_to_active(); +#endif + return len; +} + +static ssize_t himax_proc_FW_debug_read(char *buf, size_t len) +{ + ssize_t ret = 0; + uint8_t loop_i = 0; + uint8_t tmp_data[64] = {0}; + + cmd_set[0] = 0x01; + + if (g_core_fp.fp_read_FW_status(cmd_set, tmp_data) == NO_ERR) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "0x%02X%02X%02X%02X :\t", + cmd_set[5], cmd_set[4], cmd_set[3], cmd_set[2]); + + for (loop_i = 0; loop_i < cmd_set[1]; loop_i++) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "%5d\t", tmp_data[loop_i]); + + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); + } + + cmd_set[0] = 0x02; + + if (g_core_fp.fp_read_FW_status(cmd_set, tmp_data) == NO_ERR) { + for (loop_i = 0; loop_i < cmd_set[1]; + loop_i = loop_i + 2) { + if ((loop_i % 16) == 0) + ret += snprintf(buf_tmp + ret, + sizeof(buf_tmp) - ret, "0x%02X%02X%02X%02X :\t", + cmd_set[5], cmd_set[4], + cmd_set[3] + + (((cmd_set[2] + loop_i) >> 8) & 0xFF), + (cmd_set[2] + loop_i) & 0xFF); + + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "%5d\t", tmp_data[loop_i] + + (tmp_data[loop_i + 1] << 8)); + + if ((loop_i % 16) == 14) + ret += snprintf(buf_tmp + ret, + sizeof(buf_tmp) - ret, "\n"); + } + } + + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); + + return ret; +} + +static ssize_t himax_proc_DD_debug_read(char *buf, size_t len) +{ + ssize_t ret = 0; + uint8_t tmp_data[64] = {0}; + uint8_t loop_i = 0; + + if (mutual_set_flag == 1) { + if (g_core_fp.fp_read_DD_status(cmd_set, tmp_data) == + NO_ERR) { + for (loop_i = 0; loop_i < cmd_set[0]; + loop_i++) { + if ((loop_i % 8) == 0) + ret += snprintf(buf_tmp + ret, + sizeof(buf_tmp) - ret, "0x%02X : ", loop_i); + + ret += snprintf(buf_tmp + ret, + sizeof(buf_tmp) - ret, "0x%02X ", tmp_data[loop_i]); + + if ((loop_i % 8) == 7) + ret += snprintf(buf_tmp + ret, + sizeof(buf_tmp) - ret, "\n"); + } + } else { + ret += snprintf(buf_tmp + ret, + sizeof(buf_tmp) - ret, "Get DD status falied!\n"); + } + } + + ret += snprintf(buf_tmp + ret, len - ret, "\n"); + + return ret; +} + +#define STR_TO_UL_ERR "String to ul is fail in cnt = %d, buf_tmp2 = %s\n" + +static ssize_t himax_proc_DD_debug_write(char *buf, size_t len) +{ + uint8_t i = 0; + uint8_t cnt = 2; + unsigned long result = 0; + char buf_tmp2[4]; + + if (len >= 20) { + I("%s: no command exceeds 20 chars.\n", __func__); + return -EFAULT; + } + + memset(buf_tmp2, 0x0, sizeof(buf_tmp2)); + + if (buf[2] == 'x' && buf[6] == 'x' && buf[10] == 'x') { + mutual_set_flag = 1; + + for (i = 3; i < 12; i = i + 4) { + memcpy(buf_tmp2, buf + i, 2); + + if (!kstrtoul(buf_tmp2, 16, &result)) + cmd_set[cnt] = (uint8_t)result; + else + I(STR_TO_UL_ERR, cnt, buf_tmp2); + + cnt--; + } + + I("cmd_set[2] = %02X, cmd_set[1] = %02X, cmd_set[0] = %02X\n", + cmd_set[2], cmd_set[1], cmd_set[0]); + } else { + mutual_set_flag = 0; + } + + return len; +} + +void setFlashBuffer(void) +{ + flash_buffer = kcalloc(Flash_Size, sizeof(uint8_t), GFP_KERNEL); +} + +void flash_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_proc_flash_read(struct seq_file *s, void *v) +{ + ssize_t ret = 0; + int i; + uint8_t flash_progress = g_flash_progress; + uint8_t flash_cmd = g_flash_cmd; + bool flash_rst = g_flash_dump_rst; + + I("flash_progress = %d\n", flash_progress); + + if (!flash_rst) { + seq_puts(s, "FlashStart:Fail\n"); + seq_puts(s, "FlashEnd\n"); + return ret; + } + + if (flash_progress == START) + seq_puts(s, "Flash dump - Start\n"); + else if (flash_progress == ONGOING) + seq_puts(s, "Flash dump - On-going\n"); + else if (flash_progress == FINISHED) + seq_puts(s, "Flash dump - Finished\n"); + + /*print flash dump data*/ + if (flash_cmd == 1 && flash_progress == FINISHED) { + seq_puts(s, "Start to print flash dump data\n"); + for (i = 0; i < Flash_Size; i++) { + seq_printf(s, "0x%02X,", flash_buffer[i]); + if (i % 16 == 15) + seq_puts(s, "\n"); + } + } + + seq_puts(s, "FlashEnd\n"); + + return ret; +} + +static ssize_t himax_proc_flash_write(struct file *filp, + const char __user *buff, size_t len, loff_t *data) +{ + char buf[80] = {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; + } + + if ((buf[1] == '_') && (buf[2] == '3') && (buf[3] == '2')) + Flash_Size = FW_SIZE_32k; + else if ((buf[1] == '_') && (buf[2] == '6')) { + if (buf[3] == '0') + Flash_Size = FW_SIZE_60k; + else if (buf[3] == '4') + Flash_Size = FW_SIZE_64k; + + } else if ((buf[1] == '_') && (buf[2] == '2')) { + if (buf[3] == '4') + Flash_Size = FW_SIZE_124k; + else if (buf[3] == '8') + Flash_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_flash_cmd = 1; + flash_dump_prog_set(START); + g_flash_dump_rst = true; + queue_work(private_ts->flash_wq, &private_ts->flash_work); + } else if (buf[0] == '2') { + /* 2_32,2_60,2_64,2_24,2_28 for flash size: + * 32k,60k,64k,124k,128k + */ + g_flash_cmd = 2; + flash_dump_prog_set(START); + g_flash_dump_rst = true; + queue_work(private_ts->flash_wq, &private_ts->flash_work); + } + + return len; +} + +static void *himax_flash_dump_seq_start(struct seq_file *s, loff_t *pos) +{ + if (*pos >= 1) + return NULL; + + return (void *)((unsigned long) *pos + 1); +} + +static void *himax_flash_dump_seq_next(struct seq_file *s, void *v, loff_t *pos) +{ + return NULL; +} + +static void himax_flash_dump_seq_stop(struct seq_file *s, void *v) +{ +} + +static const struct seq_operations himax_flash_dump_seq_ops = { + .start = himax_flash_dump_seq_start, + .next = himax_flash_dump_seq_next, + .stop = himax_flash_dump_seq_stop, + .show = himax_proc_flash_read, +}; +static int himax_flash_dump_proc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &himax_flash_dump_seq_ops); +}; + +static const struct file_operations himax_proc_flash_ops = { + .owner = THIS_MODULE, + .open = himax_flash_dump_proc_open, + .read = seq_read, + .write = himax_proc_flash_write, +}; + +void himax_ts_flash_func(void) +{ + uint8_t flash_command = g_flash_cmd; + + himax_int_enable(0); + flash_dump_prog_set(ONGOING); + + /*msleep(100);*/ + I("%s: flash_command = %d enter.\n", __func__, flash_command); + + if (flash_command == 1 || flash_command == 2) { + g_core_fp.fp_flash_dump_func(flash_command, Flash_Size, + flash_buffer); + g_flash_dump_rst = true; + } + + I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n"); + +/* if (flash_command == 2) { + * struct file *fn; + * struct filename *vts_name; + * + * vts_name = kp_getname_kernel(FLASH_DUMP_FILE); + * fn = kp_file_open_name(vts_name, O_CREAT | O_WRONLY, 0); + * + * if (!IS_ERR(fn)) { + * I("%s create file and ready to write\n", __func__); + * fn->f_op->write(fn, flash_buffer, + * Flash_Size * sizeof(uint8_t), &fn->f_pos); + * filp_close(fn, NULL); + * } else { + * E("%s Open file failed!\n", __func__); + * g_flash_dump_rst = false; + * } + * } + */ + himax_int_enable(1); + flash_dump_prog_set(FINISHED); +} + +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') { + g_core_fp.fp_sense_off(true); + I("Sense off\n"); + } else if (buf[0] == '1') { + if (buf[1] == 's') { + g_core_fp.fp_sense_on(0x00); + I("Sense on re-map on, run sram\n"); + } else { + g_core_fp.fp_sense_on(0x01); + I("Sense on re-map off, run flash\n"); + } + } else { + I("Do nothing\n"); + } + + return len; +} + +#ifdef HX_ESD_RECOVERY +static ssize_t himax_esd_cnt_read(char *buf, size_t len) +{ + size_t ret = 0; + + I("%s: enter, %d\n", __func__, __LINE__); + + ret += snprintf(buf_tmp + ret, len - ret, + "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_esd_cnt_write(char *buf, size_t len) +{ + int i = 0; + + if (len >= 12) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + I("Clear ESD Flag\n"); + + if (buf[i] == '0') { + hx_EB_event_flag = 0; + hx_EC_event_flag = 0; + hx_ED_event_flag = 0; + } + + return len; +} + +#endif + +static int printMat(char *temp_buf, size_t len, 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) + ret += snprintf(temp_buf + ret, len - ret, "\n"); + + ret += snprintf(temp_buf + ret, len - ret, "0x%02X\t", + guest_str[i]); + } + return ret; +} + +static int printUnit(char *temp_buf, size_t len, int max_size, char *info_item, + uint8_t *guest_str, int loc) +{ + int ret = loc; + + ret += snprintf(temp_buf + ret, len - ret, "%s:\n", info_item); + ret = printMat(temp_buf, len, max_size, guest_str, ret); + ret += snprintf(temp_buf + ret, len - ret, "\n"); + return ret; +} + +#ifdef HX_TP_PROC_GUEST_INFO +static ssize_t himax_proc_guest_info_read(char *buf, size_t len) +{ + int ret = 0; + int j = 0; + int max_size = 128; + struct hx_guest_info *info = g_guest_info_data; + + I("guest info progress\n"); + + if (g_core_fp.guest_info_get_status()) { + ret += snprintf(buf_tmp + ret, len - ret, + "Not Ready\n"); + goto END_FUNCTION; + } else { + if (info->g_guest_info_type == 1) { + for (j = 0; j < 3; j++) { + ret = printUnit(buf_tmp, len, 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(buf_tmp, len, 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(buf_tmp, len, 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; + ret += snprintf(buf_tmp + ret, + len - ret, "%s:\n", + g_guest_info_item[j]); + if (info->g_guest_data_type[j] == 0) { + ret += snprintf(buf_tmp + ret, + len - ret, "%s", + g_guest_info_data->g_guest_str_in_format[j]); + } else { + ret = printMat(buf_tmp, len, + info->g_guest_data_len[j], + g_guest_info_data->g_guest_str_in_format[j], ret); + } + ret += snprintf(buf_tmp + ret, + len - ret, "\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 (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 ssize_t himax_debug_read(struct file *file, char *buf, + size_t len, loff_t *pos) +{ + ssize_t ret = 0; + int i = 0; + + if (!HX_PROC_SEND_FLAG) { + I("%s, Enter, len = %d\n", __func__, (int)len); + memset(buf_tmp, 0, sizeof(buf_tmp)); + + if (dbg_cmd_flag) { + memset(buf_tmp, 0, sizeof(buf_tmp)); + if (dbg_func_ptr_r[dbg_cmd_flag]) + ret += dbg_func_ptr_r[dbg_cmd_flag](buf, len); + else + goto END_FUNC_R; + } + + if (debug_level_cmd == 't') { + if (fw_update_complete) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "FW Update Complete "); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "FW Update Fail "); + + } else if (debug_level_cmd == 'h') { + if (handshaking_result == 0) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Handshaking Result = %d (MCU Running)\n", + handshaking_result); + else if (handshaking_result == 1) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Handshaking Result = %d (MCU Stop)\n", + handshaking_result); + else if (handshaking_result == 2) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Handshaking Result = %d (I2C Error)\n", + handshaking_result); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Handshaking Result = error\n"); + + } else if (debug_level_cmd == 'v') { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "FW_VER = 0x%2.2X\n", ic_data->vendor_fw_ver); + + if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "CONFIG_VER = 0x%2.2X\n", + ic_data->vendor_config_ver); + else { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "TOUCH_VER = 0x%2.2X\n", + ic_data->vendor_touch_cfg_ver); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "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) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "CID_VER = NULL\n"); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "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) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "PANEL_VER = NULL\n"); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "PANEL_VER = 0x%2.2X\n", + ic_data->vendor_panel_ver); + if (private_ts->chip_cell_type == CHIP_IS_IN_CELL) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Cusomer = %s\n", ic_data->vendor_cus_info); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Project = %s\n", ic_data->vendor_proj_info); + } +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) +#ifdef HX_EN_DYNAMIC_NAME + if (ic_data->vendor_semifac == 1) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "SEMI_FAC = UMC\n"); + else if (ic_data->vendor_semifac == 2) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "SEMI_FAC = PSC\n"); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "SEMI_FAC = NULL\n"); +#endif +#endif + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, "\n"); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Himax Touch Driver Version:\n"); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "%s\n", HIMAX_DRIVER_VER); + } else if (debug_level_cmd == 'd') { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Himax Touch IC Information :\n"); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "%s\n", private_ts->chip_name); + + switch (IC_CHECKSUM) { + case HX_TP_BIN_CHECKSUM_SW: + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "IC Checksum : SW\n"); + break; + + case HX_TP_BIN_CHECKSUM_HW: + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "IC Checksum : HW\n"); + break; + + case HX_TP_BIN_CHECKSUM_CRC: + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "IC Checksum : CRC\n"); + break; + + default: + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "IC Checksum error.\n"); + } + + if (ic_data->HX_INT_IS_EDGE) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Driver register Interrupt : EDGE TIRGGER\n"); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Driver register Interrupt : LEVEL TRIGGER\n"); + + if (private_ts->protocol_type == PROTOCOL_TYPE_A) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Protocol : TYPE_A\n"); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Protocol : TYPE_B\n"); + + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "RX Num : %d\n", ic_data->HX_RX_NUM); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "TX Num : %d\n", ic_data->HX_TX_NUM); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "BT Num : %d\n", ic_data->HX_BT_NUM); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "X Resolution : %d\n", ic_data->HX_X_RES); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Y Resolution : %d\n", ic_data->HX_Y_RES); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Max Point : %d\n", ic_data->HX_MAX_PT); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "XY reverse : %d\n", ic_data->HX_XY_REVERSE); +#ifdef HX_TP_PROC_2T2R + if (Is_2T2R) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "2T2R panel\n"); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "RX Num_2 : %d\n", HX_RX_NUM_2); + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "TX Num_2 : %d\n", HX_TX_NUM_2); + } +#endif + } else if (debug_level_cmd == 'i') { + if (g_core_fp.fp_read_i2c_status()) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "I2C communication is bad.\n"); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "I2C communication is good.\n"); + } else if (debug_level_cmd == 'n') { + /* Edgd = 1, Level = 0 */ + if (g_core_fp.fp_read_ic_trigger_type() == 1) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "IC Interrupt type is edge trigger.\n"); + else if (g_core_fp.fp_read_ic_trigger_type() == 0) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "IC Interrupt type is level trigger.\n"); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Unkown IC trigger type.\n"); + + if (ic_data->HX_INT_IS_EDGE) + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Driver register Interrupt : EDGE TIRGGER\n"); + else + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "Driver register Interrupt : LEVEL TRIGGER\n"); + } else if (debug_level_cmd == 'l') { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "LotID : "); + for (i = 0; i < 13; i++) { + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "%02X", ic_data->vendor_ic_id[i]); + } + ret += snprintf(buf_tmp + ret, sizeof(buf_tmp) - ret, + "\n"); + } + +END_FUNC_R: + if (copy_to_user(buf, buf_tmp, (len > BUF_SIZE) ? BUF_SIZE : len)) + I("%s,here:%d\n", __func__, __LINE__); + + HX_PROC_SEND_FLAG = 1; + } else { + HX_PROC_SEND_FLAG = 0; + } + + return ret; +} + +static ssize_t himax_debug_write(struct file *file, const char *buff, + size_t len, loff_t *pos) +{ + char fileName[128]; + char buf[80] = {0}; + int result = 0; +#ifndef HX_ZERO_FLASH + int fw_type = 0; + const struct firmware *fw = NULL; +#endif + + char *str_ptr = NULL; + int str_len = 0; + int i = 0; + + + if (len >= 80) { + I("%s: no command exceeds 80 chars.\n", __func__); + return -EFAULT; + } + + if (copy_from_user(buf, buff, len)) + return -EFAULT; + + buf[strlen(buf) - 1] = 0;/*remove \n*/ + + while (dbg_cmd_str[i]) { + str_ptr = strnstr(buf, dbg_cmd_str[i], len); + if (str_ptr) { + str_len = strlen(dbg_cmd_str[i]); + dbg_cmd_flag = i + 1; + debug_level_cmd = 0; + I("Cmd is correct :%s, dbg_cmd = %d\n", str_ptr, dbg_cmd_flag); + break; + } + i++; + } + if (!str_ptr) { + I("Cmd is not correct\n"); + dbg_cmd_flag = 0; + } + + if (buf[str_len] == ',') { + dbg_cmd_par = buf + str_len + 1; + if (dbg_func_ptr_w[dbg_cmd_flag]) + dbg_func_ptr_w[dbg_cmd_flag](dbg_cmd_par, len - str_len - 2);/* 2 => '/n' + ','*/ + I("string of paremeter is %s, dbg_cmd_par = %s\n", buf + str_len + 1, dbg_cmd_par); + } else + I("No paremeter of this cmd\n"); + + if (dbg_cmd_flag) + return len; + + if (buf[0] == 'h') { /* handshaking */ + debug_level_cmd = buf[0]; + himax_int_enable(0); + /* 0:Running, 1:Stop, 2:I2C Fail */ + handshaking_result = g_core_fp.fp_hand_shaking(); + himax_int_enable(1); + return len; + } else if (buf[0] == 'v') { /* firmware version */ + himax_int_enable(0); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#endif + debug_level_cmd = buf[0]; + g_core_fp.fp_read_FW_ver(); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(true, false); +#else + g_core_fp.fp_system_reset(); +#endif +#if defined(HX_ZERO_FLASH) && defined(HX83102D) + if (g_core_fp.fp_0f_reload_to_active) + g_core_fp.fp_0f_reload_to_active(); +#endif + himax_int_enable(1); + /* himax_check_chip_version(); */ + return len; + } else if (buf[0] == 'd') { /* ic information */ + debug_level_cmd = buf[0]; + return len; + } else if (buf[0] == 't') { + if (buf[1] == 's' && + buf[2] == 'd' && + buf[3] == 'b' && + buf[4] == 'g' + ) { + 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"); + } + goto ENDFUCTION; + } + himax_int_enable(0); + debug_level_cmd = buf[0]; + fw_update_complete = false; + memset(fileName, 0, 128); + /* parse the file name */ + snprintf(fileName, len - 2, "%s", &buf[2]); + +#ifdef HX_ZERO_FLASH + I("NOW Running Zero flash update!\n"); + I("%s: upgrade from file(%s) start!\n", __func__, fileName); + result = g_core_fp.fp_0f_op_file_dirly(fileName); + if (result) { + fw_update_complete = false; + I("Zero flash update fail!\n"); + goto ENDFUCTION; + } else { + fw_update_complete = true; + I("Zero flash update complete!\n"); + } + goto firmware_upgrade_done; +#else + I("NOW Running common flow update!\n"); + I("%s: upgrade from file(%s) start!\n", __func__, fileName); + result = request_firmware(&fw, fileName, private_ts->dev); + + if (result < 0) { + I("fail to request_firmware fwpath: %s (ret:%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]); + fw_type = (fw->size) / 1024; + /* start to upgrade */ + himax_int_enable(0); + 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; + + default: + E("%s: Flash command fail: %d\n", __func__, __LINE__); + fw_update_complete = false; + break; + } + release_firmware(fw); + goto firmware_upgrade_done; +#endif + } else if (buf[0] == 'i' && buf[1] == '2' && buf[2] == 'c') { + /* i2c communication */ + debug_level_cmd = 'i'; + return len; + } else if (buf[0] == 'i' && buf[1] == 'n' && buf[2] == 't') { + /* INT trigger */ + debug_level_cmd = 'n'; + return len; +#ifdef HX_ZERO_FLASH + } else if (buf[0] == 'z') { + result = buf[1] - '0'; + I("check type = %d\n", result); + g_core_fp.fp_0f_operation_check(result); + return len; + } else if (buf[0] == 'p') { + I("NOW debug echo r!\n"); + /* himax_program_sram(); */ + private_ts->himax_0f_update_wq = + create_singlethread_workqueue("HMX_update_0f_reuqest_write"); + + if (!private_ts->himax_0f_update_wq) + E(" allocate syn_update_wq failed\n"); + + INIT_DELAYED_WORK(&private_ts->work_0f_update, + g_core_fp.fp_0f_operation); + queue_delayed_work(private_ts->himax_0f_update_wq, + &private_ts->work_0f_update, msecs_to_jiffies(100)); + return len; + } else if (buf[0] == 'x') { + g_core_fp.fp_system_reset(); +#if defined(HX_ZERO_FLASH) && defined(HX83102D) + if (g_core_fp.fp_0f_reload_to_active) + g_core_fp.fp_0f_reload_to_active(); +#endif + return len; +#endif + } else if (buf[0] == 'l' && buf[1] == 'o' && buf[2] == 't') { + debug_level_cmd = buf[0]; + g_core_fp.fp_sense_off(true); + g_core_fp.fp_ic_id_read(); + g_core_fp.fp_sense_on(0x01); + return len; + } + /* others,do nothing */ + debug_level_cmd = 0; + return len; + +firmware_upgrade_done: + g_core_fp.fp_reload_disable(0); + g_core_fp.fp_read_FW_ver(); + g_core_fp.fp_touch_information(); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(true, false); +#if defined(HX_ZERO_FLASH) && defined(HX83102D) + if (g_core_fp.fp_0f_reload_to_active) + g_core_fp.fp_0f_reload_to_active(); +#endif +#else + g_core_fp.fp_sense_on(0x00); +#endif + + himax_int_enable(1); + /* todo himax_chip->tp_firmware_upgrade_proceed = 0; + * todo himax_chip->suspend_state = 0; + * todo enable_irq(himax_chip->irq); + */ +ENDFUCTION: + return len; +} + +static const struct file_operations himax_proc_debug_ops = { + .owner = THIS_MODULE, + .read = himax_debug_read, + .write = himax_debug_write, +}; + +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; +} + +static void himax_ts_flash_work_func(struct work_struct *work) +{ + himax_ts_flash_func(); +} +#ifdef 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(); +} + +void dbg_func_ptr_init(void) +{ + /*debug function ptr init*/ + dbg_func_ptr_r[1] = himax_crc_test_read; + dbg_func_ptr_r[2] = himax_proc_FW_debug_read; + dbg_func_ptr_r[3] = himax_attn_read; + dbg_func_ptr_r[4] = himax_layout_read; + dbg_func_ptr_w[4] = himax_layout_write; + dbg_func_ptr_r[5] = himax_proc_DD_debug_read; + dbg_func_ptr_w[5] = himax_proc_DD_debug_write; +#ifdef HX_ESD_RECOVERY + dbg_func_ptr_r[6] = himax_esd_cnt_read; + dbg_func_ptr_w[6] = himax_esd_cnt_write; +#endif + dbg_func_ptr_w[7] = himax_sense_on_off_write; + dbg_func_ptr_r[8] = himax_debug_level_read; + dbg_func_ptr_w[8] = himax_debug_level_write; +#ifdef HX_TP_PROC_GUEST_INFO + dbg_func_ptr_r[9] = himax_proc_guest_info_read; + dbg_func_ptr_w[9] = himax_proc_guest_info_write; +#endif + dbg_func_ptr_r[10] = himax_int_en_read; + dbg_func_ptr_w[10] = himax_int_en_write; + dbg_func_ptr_w[11] = himax_proc_register_write; + dbg_func_ptr_r[11] = himax_proc_register_read; + dbg_func_ptr_w[12] = himax_reset_write; + dbg_func_ptr_w[13] = himax_diag_arrange_write; + dbg_func_ptr_w[14] = himax_diag_cmd_write; +} + +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_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, 0444, + himax_touch_proc_dir, &himax_proc_vendor_ops); + if (himax_proc_vendor_file == NULL) { + E(" %s: proc vendor file create failed!\n", __func__); + goto fail_1; + } + + himax_proc_stack_file = proc_create(HIMAX_PROC_STACK_FILE, 0444, + himax_proc_diag_dir, &himax_proc_stack_ops); + if (himax_proc_stack_file == NULL) { + E(" %s: proc stack file create failed!\n", __func__); + goto fail_2_1; + } + + himax_proc_iir_file = proc_create(HIMAX_PROC_IIR_FILE, 0444, + himax_proc_diag_dir, &himax_proc_iir_ops); + if (himax_proc_iir_file == NULL) { + E(" %s: proc iir 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_proc_dc_ops); + if (himax_proc_dc_file == NULL) { + E(" %s: proc dc file create failed!\n", __func__); + goto fail_2_3; + } + + himax_proc_bank_file = proc_create(HIMAX_PROC_BANK_FILE, 0444, + himax_proc_diag_dir, &himax_proc_bank_ops); + if (himax_proc_bank_file == NULL) { + E(" %s: proc bank 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_proc_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_proc_flash_ops); + if (himax_proc_flash_dump_file == NULL) { + E(" %s: proc flash dump file create failed!\n", __func__); + goto fail_4; + } + +#if defined(HX_PEN_FUNC_EN) + himax_proc_pen_pos_file = proc_create(HIMAX_PROC_PEN_POS_FILE, + 0666, + himax_touch_proc_dir, &himax_proc_pen_pos_ops); + if (himax_proc_pen_pos_file == NULL) { + E(" %s: proc CRC test file create failed!\n", __func__); + goto fail_5; + } +#endif + + return 0; +#if defined(HX_PEN_FUNC_EN) + remove_proc_entry(HIMAX_PROC_PEN_POS_FILE, himax_touch_proc_dir); +fail_5: +#endif +remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir); +fail_4: remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir); +fail_3: remove_proc_entry(HIMAX_PROC_BANK_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_IIR_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_VENDOR_FILE, himax_touch_proc_dir); +fail_1: + return -ENOMEM; +} + +void himax_touch_proc_deinit(void) +{ +#if defined(HX_PEN_FUNC_EN) + remove_proc_entry(HIMAX_PROC_PEN_POS_FILE, himax_touch_proc_dir); +#endif + 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_BANK_FILE, himax_proc_diag_dir); + remove_proc_entry(HIMAX_PROC_DC_FILE, himax_proc_diag_dir); + remove_proc_entry(HIMAX_PROC_IIR_FILE, himax_proc_diag_dir); + remove_proc_entry(HIMAX_PROC_STACK_FILE, himax_proc_diag_dir); + remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir); +} + +int himax_debug_init(void) +{ + struct himax_ts_data *ts = private_ts; + int err = 0; + + I("%s:Enter\n", __func__); + + if (ts == NULL) { + E("%s: ts struct is NULL\n", __func__); + return -EPROBE_DEFER; + } + + reg_read_data = kzalloc(DEBUG_READ_BUF_SIZE * sizeof(uint8_t), GFP_KERNEL); + if (reg_read_data == NULL) { + err = -ENOMEM; + goto err_alloc_reg_read_data_fail; + } + + debug_data = kzalloc(sizeof(struct himax_debug), GFP_KERNEL); + if (debug_data == NULL) { /*Allocate debug data space*/ + err = -ENOMEM; + goto err_alloc_debug_data_fail; + } + + himax_himax_data_init(); + + ts->flash_wq = create_singlethread_workqueue("himax_flash_wq"); + + if (!ts->flash_wq) { + E("%s: create flash workqueue failed\n", __func__); + err = -ENOMEM; + goto err_create_flash_dump_wq_failed; + } + + INIT_WORK(&ts->flash_work, himax_ts_flash_work_func); + + g_flash_progress = START; + setFlashBuffer(); + +#ifdef HX_TP_PROC_GUEST_INFO + + if (g_guest_info_data == NULL) { + g_guest_info_data = kzalloc(sizeof(struct hx_guest_info), + GFP_KERNEL); + 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__); + err = -ENOMEM; + goto err_create_guest_info_wq_failed; + } + INIT_WORK(&ts->guest_info_work, himax_ts_guest_info_work_func); +#endif + + ts->himax_diag_wq = create_singlethread_workqueue("himax_diag"); + + if (!ts->himax_diag_wq) { + E("%s: create diag workqueue failed\n", __func__); + err = -ENOMEM; + goto err_create_diag_wq_failed; + } + + INIT_DELAYED_WORK(&ts->himax_diag_delay_wrok, himax_ts_diag_work_func); + + setMutualBuffer(ic_data->HX_RX_NUM, ic_data->HX_TX_NUM); + if (getMutualBuffer() == NULL) { + E("%s: mutual buffer allocate fail failed\n", __func__); + return MEM_ALLOC_FAIL; + } + + setMutualNewBuffer(ic_data->HX_RX_NUM, ic_data->HX_TX_NUM); + if (getMutualNewBuffer() == NULL) { + E("%s: mutual new buffer allocate fail failed\n", __func__); + return MEM_ALLOC_FAIL; + } + + setMutualOldBuffer(ic_data->HX_RX_NUM, ic_data->HX_TX_NUM); + if (getMutualOldBuffer() == NULL) { + E("%s: mutual old buffer allocate fail failed\n", __func__); + return MEM_ALLOC_FAIL; + } + +#ifdef 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 fail failed\n", + __func__); + return MEM_ALLOC_FAIL; + } + } +#endif + + himax_touch_proc_init(); + + return 0; + + cancel_delayed_work_sync(&ts->himax_diag_delay_wrok); + destroy_workqueue(ts->himax_diag_wq); +err_create_diag_wq_failed: + +#ifdef HX_TP_PROC_GUEST_INFO +err_create_guest_info_wq_failed: + + destroy_workqueue(ts->guest_info_wq); + if (g_guest_info_data != NULL) { + kfree(g_guest_info_data); + g_guest_info_data = NULL; + } +#endif + destroy_workqueue(ts->flash_wq); + +err_create_flash_dump_wq_failed: + kfree(debug_data); + debug_data = NULL; +err_alloc_debug_data_fail: + kfree(reg_read_data); + reg_read_data = NULL; +err_alloc_reg_read_data_fail: + + return err; +} +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_wrok); +#ifdef HX_TP_PROC_GUEST_INFO + destroy_workqueue(ts->guest_info_wq); + if (g_guest_info_data != NULL) + kfree(g_guest_info_data); +#endif + destroy_workqueue(ts->himax_diag_wq); + destroy_workqueue(ts->flash_wq); + + kfree(debug_data); + + return 0; +} +EXPORT_SYMBOL(himax_debug_remove); + diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_debug.h b/drivers/input/touchscreen/himax_v3_mmi/himax_debug.h index 152eac144fe2..586923f9e065 100644 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_debug.h +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_debug.h @@ -1,164 +1,149 @@ -/* 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. - */ - -#ifndef H_HIMAX_DEBUG -#define H_HIMAX_DEBUG - -#include "himax_platform.h" -#include "himax_common.h" - - -#if defined(HX_ESD_RECOVERY) -extern u8 HX_ESD_RESET_ACTIVATE; -extern int hx_EB_event_flag; -extern int hx_EC_event_flag; -extern int hx_ED_event_flag; -#endif - -#define HIMAX_PROC_VENDOR_FILE "vendor" -extern struct proc_dir_entry *himax_proc_vendor_file; - -#define HIMAX_PROC_PEN_POS_FILE "pen_pos" - -int himax_touch_proc_init(void); -void himax_touch_proc_deinit(void); -extern int himax_int_en_set(void); - -extern uint8_t byte_length; -extern uint8_t register_command[4]; -extern uint8_t cfg_flag; - -#define HIMAX_PROC_DIAG_FOLDER "diag" -struct proc_dir_entry *himax_proc_diag_dir; -#define HIMAX_PROC_STACK_FILE "stack" -extern struct proc_dir_entry *himax_proc_stack_file; -#define HIMAX_PROC_DELTA_FILE "delta_s" -extern struct proc_dir_entry *himax_proc_delta_file; -#define HIMAX_PROC_DC_FILE "dc_s" -extern struct proc_dir_entry *himax_proc_dc_file; -#define HIMAX_PROC_BASELINE_FILE "baseline_s" -extern struct proc_dir_entry *himax_proc_baseline_file; - -#if defined(HX_TP_PROC_2T2R) -extern uint32_t *diag_mutual_2; - -int32_t *getMutualBuffer_2(void); -void setMutualBuffer_2(uint8_t x_num, uint8_t y_num); -#endif -extern int32_t *diag_mutual; -extern int32_t *diag_mutual_new; -extern int32_t *diag_mutual_old; -extern uint8_t diag_max_cnt; -extern uint8_t hx_state_info[2]; -extern uint8_t diag_coor[128]; -extern int32_t *diag_self; -extern int32_t *diag_self_new; -extern int32_t *diag_self_old; -int32_t *getMutualBuffer(void); -int32_t *getMutualNewBuffer(void); -int32_t *getMutualOldBuffer(void); -int32_t *getSelfBuffer(void); -int32_t *getSelfNewBuffer(void); -int32_t *getSelfOldBuffer(void); -void setMutualBuffer(uint8_t x_num, uint8_t y_num); -void setMutualNewBuffer(uint8_t x_num, uint8_t y_num); -void setMutualOldBuffer(uint8_t x_num, uint8_t y_num); -uint8_t process_type; -uint8_t mode_flag; -uint8_t overflow; - -#define HIMAX_PROC_DEBUG_FILE "debug" -extern struct proc_dir_entry *himax_proc_debug_file; -extern bool fw_update_complete; -extern int handshaking_result; -extern unsigned char debug_level_cmd; -extern uint8_t cmd_set[8]; -extern uint8_t mutual_set_flag; - -#define HIMAX_PROC_FLASH_DUMP_FILE "flash_dump" -extern struct proc_dir_entry *himax_proc_flash_dump_file; -extern int Flash_Size; -extern uint8_t *flash_buffer; -extern uint8_t g_flash_cmd; -extern uint8_t g_flash_progress; -extern bool g_flash_dump_rst; /*Fail = 0, Pass = 1*/ -void setFlashBuffer(void); - -enum flash_dump_prog { - START, - ONGOING, - FINISHED, -}; - -extern uint32_t **raw_data_array; -extern uint8_t X_NUM4; -extern uint8_t Y_NUM; -extern uint8_t sel_type; - -/* Moved from debug.c */ -extern struct himax_debug *debug_data; -extern unsigned char IC_CHECKSUM; -extern int i2c_error_count; -extern struct proc_dir_entry *himax_touch_proc_dir; - -#if defined(HX_TP_PROC_GUEST_INFO) -extern struct hx_guest_info *g_guest_info_data; -extern char *g_guest_info_item[]; -#endif - -extern int himax_input_register(struct himax_ts_data *ts); -#if defined(HX_TP_PROC_2T2R) -extern bool Is_2T2R; -#endif - -#if defined(HX_RST_PIN_FUNC) -extern void himax_ic_reset(uint8_t loadconfig, uint8_t int_off); -#endif - -#if defined(HX_ZERO_FLASH) -extern char *i_CTPM_firmware_name; -#endif - -extern uint8_t HX_PROC_SEND_FLAG; -extern struct himax_target_report_data *g_target_report_data; -extern struct himax_report_data *hx_touch_data; -extern int g_ts_dbg; - -/* Moved from debug.c end */ -#define BUF_SIZE 1024 -#define CMD_NUM 15 -char *dbg_cmd_str[] = { - "crc_test", - "fw_debug", - "attn", - "layout", - "dd_debug", - "esd_cnt", - "senseonoff", - "debug_level", - "guest_info", - "int_en", - "register", - "reset", - "diag_arr", - "diag", - NULL -}; - -int dbg_cmd_flag; -char *dbg_cmd_par; -ssize_t (*dbg_func_ptr_r[CMD_NUM])(char *buf, size_t len); -ssize_t (*dbg_func_ptr_w[CMD_NUM])(char *buf, size_t len); -#endif +/* 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. + */ + +#ifndef H_HIMAX_DEBUG +#define H_HIMAX_DEBUG + +#include "himax_platform.h" +#include "himax_common.h" + + +#ifdef HX_ESD_RECOVERY + extern u8 HX_ESD_RESET_ACTIVATE; + extern int hx_EB_event_flag; + extern int hx_EC_event_flag; + extern int hx_ED_event_flag; +#endif + +#define HIMAX_PROC_VENDOR_FILE "vendor" +extern struct proc_dir_entry *himax_proc_vendor_file; + +#define HIMAX_PROC_PEN_POS_FILE "pen_pos" + +int himax_touch_proc_init(void); +void himax_touch_proc_deinit(void); +extern int himax_int_en_set(void); + +extern uint8_t byte_length; +extern uint8_t register_command[4]; +extern uint8_t cfg_flag; + +#define HIMAX_PROC_DIAG_FOLDER "diag" +struct proc_dir_entry *himax_proc_diag_dir; +#define HIMAX_PROC_STACK_FILE "stack" +extern struct proc_dir_entry *himax_proc_stack_file; +#define HIMAX_PROC_IIR_FILE "iir_s" +extern struct proc_dir_entry *himax_proc_iir_file; +#define HIMAX_PROC_DC_FILE "dc_s" +extern struct proc_dir_entry *himax_proc_dc_file; +#define HIMAX_PROC_BANK_FILE "bank_s" +extern struct proc_dir_entry *himax_proc_bank_file; + +#ifdef HX_TP_PROC_2T2R + extern uint32_t *diag_mutual_2; + + int32_t *getMutualBuffer_2(void); + void setMutualBuffer_2(uint8_t x_num, uint8_t y_num); +#endif +extern int32_t *diag_mutual; +extern int32_t *diag_mutual_new; +extern int32_t *diag_mutual_old; +extern uint8_t diag_max_cnt; +extern uint8_t hx_state_info[2]; +extern uint8_t diag_coor[128]; +extern int32_t diag_self[100]; +extern int32_t diag_self_new[100]; +extern int32_t diag_self_old[100]; +int32_t *getMutualBuffer(void); +int32_t *getMutualNewBuffer(void); +int32_t *getMutualOldBuffer(void); +int32_t *getSelfBuffer(void); +int32_t *getSelfNewBuffer(void); +int32_t *getSelfOldBuffer(void); +void setMutualBuffer(uint8_t x_num, uint8_t y_num); +void setMutualNewBuffer(uint8_t x_num, uint8_t y_num); +void setMutualOldBuffer(uint8_t x_num, uint8_t y_num); +uint8_t process_type; +uint8_t mode_flag; +uint8_t overflow; + +#define HIMAX_PROC_DEBUG_FILE "debug" +extern struct proc_dir_entry *himax_proc_debug_file; +extern bool fw_update_complete; +extern int handshaking_result; +extern unsigned char debug_level_cmd; +extern uint8_t cmd_set[8]; +extern uint8_t mutual_set_flag; + +#define HIMAX_PROC_FLASH_DUMP_FILE "flash_dump" +extern struct proc_dir_entry *himax_proc_flash_dump_file; +extern int Flash_Size; +extern uint8_t *flash_buffer; +extern uint8_t g_flash_cmd; +extern uint8_t g_flash_progress; +extern bool g_flash_dump_rst; /*Fail = 0, Pass = 1*/ +void setFlashBuffer(void); + +enum flash_dump_prog { + START, + ONGOING, + FINISHED, +}; + +extern uint32_t **raw_data_array; +extern uint8_t X_NUM4; +extern uint8_t Y_NUM; +extern uint8_t sel_type; + +/* Moved from debug.c */ +extern struct himax_debug *debug_data; +extern unsigned char IC_CHECKSUM; +extern int i2c_error_count; +extern struct proc_dir_entry *himax_touch_proc_dir; + +#ifdef HX_TP_PROC_GUEST_INFO +extern struct hx_guest_info *g_guest_info_data; +extern char *g_guest_info_item[]; +#endif + +extern int himax_input_register(struct himax_ts_data *ts); +#ifdef HX_TP_PROC_2T2R + extern bool Is_2T2R; +#endif + +#ifdef HX_RST_PIN_FUNC + extern void himax_ic_reset(uint8_t loadconfig, uint8_t int_off); +#endif + +#if defined(HX_ZERO_FLASH) +extern char *i_CTPM_firmware_name; +#endif + +extern uint8_t HX_PROC_SEND_FLAG; +extern struct himax_target_report_data *g_target_report_data; +extern struct himax_report_data *hx_touch_data; +extern int g_ts_dbg; + +/* Moved from debug.c end */ +#define BUF_SIZE 1024 +#define CMD_NUM 15 +char *dbg_cmd_str[] = {"crc_test", "fw_debug", "attn", "layout", "dd_debug", + "esd_cnt", "senseonoff", "debug_level", "guest_info", "int_en", + "register", "reset", "diag_arr", "diag", NULL}; +int dbg_cmd_flag; +char *dbg_cmd_par; +ssize_t (*dbg_func_ptr_r[CMD_NUM])(char *buf, size_t len); +ssize_t (*dbg_func_ptr_w[CMD_NUM])(char *buf, size_t len); +#endif diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_ic_core.h b/drivers/input/touchscreen/himax_v3_mmi/himax_ic_core.h index 2ee124841f54..f6010d6ac244 100644 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_ic_core.h +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_ic_core.h @@ -1,993 +1,982 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for ic core functions - * - * 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. - */ - -#ifndef __HIMAX_IC_CORE_H__ -#define __HIMAX_IC_CORE_H__ - -#include "himax_platform.h" -#include "himax_common.h" -#include - -#define DATA_LEN_8 8 -#define DATA_LEN_4 4 -#define ADDR_LEN_4 4 -#define FLASH_RW_MAX_LEN 256 -#define FLASH_WRITE_BURST_SZ 8 -#define PROGRAM_SZ 48 -#define MAX_I2C_TRANS_SZ 128 -#define HIMAX_REG_RETRY_TIMES 5 -#define FW_BIN_16K_SZ 0x4000 -#define HIMAX_TOUCH_DATA_SIZE 128 -#define MASK_BIT_0 0x01 -#define MASK_BIT_1 0x02 -#define MASK_BIT_2 0x04 - -#define FW_SECTOR_PER_BLOCK 8 -#define FW_PAGE_PER_SECTOR 64 -#define FW_PAGE_SEZE 128 -#define HX256B 0x100 -#define HX1K 0x400 -#define HX4K 0x1000 -#define HX_32K_SZ 0x8000 -#define HX_40K_SZ 0xA000 -#define HX_48K_SZ 0xC000 -#define HX64K 0x10000 -#define HX124K 0x1f000 -#define HX4000K 0x1000000 - -#define HX_NORMAL_MODE 1 -#define HX_SORTING_MODE 2 -#define HX_CHANGE_MODE_FAIL (-1) -#define HX_RW_REG_FAIL (-1) -#define HX_DRIVER_MAX_IC_NUM 12 - -#if defined(__HIMAX_HX852xG_MOD__) -#define HX_MOD_KSYM_HX852xG HX_MOD_KSYM_HX852xG -#endif - -#if defined(__HIMAX_HX852xH_MOD__) -#define HX_MOD_KSYM_HX852xH HX_MOD_KSYM_HX852xH -#endif - -#if defined(__HIMAX_HX83102_MOD__) -#define HX_MOD_KSYM_HX83102 HX_MOD_KSYM_HX83102 -#endif - -#if defined(__HIMAX_HX83103_MOD__) -#define HX_MOD_KSYM_HX83103 HX_MOD_KSYM_HX83103 -#endif - -#if defined(__HIMAX_HX83106_MOD__) -#define HX_MOD_KSYM_HX83106 HX_MOD_KSYM_HX83106 -#endif - -#if defined(__HIMAX_HX83111_MOD__) -#define HX_MOD_KSYM_HX83111 HX_MOD_KSYM_HX83111 -#endif - -#if defined(__HIMAX_HX83112_MOD__) -#define HX_MOD_KSYM_HX83112 HX_MOD_KSYM_HX83112 -#endif - -#if defined(__HIMAX_HX83191_MOD__) -#define HX_MOD_KSYM_HX83191 HX_MOD_KSYM_HX83191 -#endif - -#if defined(__HIMAX_HX83192_MOD__) -#define HX_MOD_KSYM_HX83192 HX_MOD_KSYM_HX83192 -#endif - -#if defined(__HIMAX_HX83113_MOD__) -#define HX_MOD_KSYM_HX83113 HX_MOD_KSYM_HX83113 -#endif - -/* CORE_INIT */ -/* CORE_IC */ -/* CORE_FW */ -/* CORE_FLASH */ -/* CORE_SRAM */ -/* CORE_DRIVER */ - -#define HX_0F_DEBUG - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_INCELL) - -#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) -extern char *i_CTPM_firmware_name; -#endif - -#if defined(HX_ZERO_FLASH) -extern int g_f_0f_updat; -#endif - -#if defined(HX_TP_PROC_GUEST_INFO) -extern struct hx_guest_info *g_guest_info_data; -#endif - -void himax_mcu_in_cmd_struct_free(void); - -#endif - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_ONCELL) -void himax_mcu_on_cmd_struct_free(void); -#endif - -#if defined(HX_AUTO_UPDATE_FW) -extern int g_i_FW_VER; -extern int g_i_CFG_VER; -extern int g_i_CID_MAJ; -extern int g_i_CID_MIN; -extern unsigned char *i_CTPM_FW; -#endif - -extern unsigned long FW_VER_MAJ_FLASH_ADDR; -extern unsigned long FW_VER_MIN_FLASH_ADDR; -extern unsigned long CFG_VER_MAJ_FLASH_ADDR; -extern unsigned long CFG_VER_MIN_FLASH_ADDR; -extern unsigned long CID_VER_MAJ_FLASH_ADDR; -extern unsigned long CID_VER_MIN_FLASH_ADDR; - -extern unsigned long FW_VER_MAJ_FLASH_LENG; -extern unsigned long FW_VER_MIN_FLASH_LENG; -extern unsigned long CFG_VER_MAJ_FLASH_LENG; -extern unsigned long CFG_VER_MIN_FLASH_LENG; -extern unsigned long CID_VER_MAJ_FLASH_LENG; -extern unsigned long CID_VER_MIN_FLASH_LENG; - -extern unsigned char IC_CHECKSUM; -#if defined(HX_ESD_RECOVERY) -extern int g_zero_event_count; -#endif - -#if defined(HX_RST_PIN_FUNC) -extern u8 HX_HW_RESET_ACTIVATE; -void himax_rst_gpio_set(int pinnum, uint8_t value); -#endif - -#if defined(HX_USB_DETECT_GLOBAL) -void himax_cable_detect_func(bool force_renew); -#endif - -int himax_report_data_init(void); -extern int i2c_error_count; - -#if defined(HX_ESD_RECOVERY) -extern u8 HX_ESD_RESET_ACTIVATE; -#endif - -/* CORE_INIT */ -int himax_mcu_in_cmd_struct_init(void); -void himax_mcu_in_cmd_init(void); - -int himax_mcu_on_cmd_struct_init(void); -void himax_mcu_on_cmd_init(void); -void himax_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len); - -extern void (*himax_mcu_cmd_struct_free)(void); -/* CORE_INIT */ - -#if defined(HX_TP_PROC_GUEST_INFO) -#define HX_GUEST_INFO_FLASH_SADDR 0x20000 -#define HX_GUEST_INFO_SIZE 10 -#define HX_GUEST_INFO_LEN_SIZE 4 -#define HX_GUEST_INFO_ID_SIZE 4 - -struct hx_guest_info { - int g_guest_info_ongoing; /* 0 stop, 1 ongoing */ - uint8_t g_guest_str[10][128]; - uint8_t g_guest_str_in_format[10][128]; - uint8_t g_guest_data_type[10]; - int g_guest_data_len[10]; - int g_guest_info_type; -}; -#endif - -/* CORE_IC */ - #define ic_adr_ahb_addr_byte_0 0x00 - #define ic_adr_ahb_rdata_byte_0 0x08 - #define ic_adr_ahb_access_direction 0x0c - #define ic_adr_conti 0x13 - #define ic_adr_incr4 0x0D - #define ic_adr_i2c_psw_lb 0x31 - #define ic_adr_i2c_psw_ub 0x32 - #define ic_cmd_ahb_access_direction_read 0x00 - #define ic_cmd_conti 0x31 - #define ic_cmd_incr4 0x10 - #define ic_cmd_i2c_psw_lb 0x27 - #define ic_cmd_i2c_psw_ub 0x95 - #define ic_adr_tcon_on_rst 0x80020020 - #define ic_addr_adc_on_rst 0x80020094 - #define ic_adr_psl 0x900000A0 - #define ic_adr_cs_central_state 0x900000A8 - #define ic_cmd_rst 0x00000000 - #define ic_adr_osc_en 0x900880A8 - #define ic_adr_osc_pw 0x900880E0 - - #define on_ic_adr_ahb_addr_byte_0 0x00 - #define on_ic_adr_ahb_rdata_byte_0 0x08 - #define on_ic_adr_ahb_access_direction 0x0c - #define on_ic_adr_conti 0x13 - #define on_ic_adr_incr4 0x0D - #define on_ic_cmd_ahb_access_direction_read 0x00 - #define on_ic_cmd_conti 0x31 - #define on_ic_cmd_incr4 0x10 - #define on_ic_adr_mcu_ctrl 0x82 - #define on_ic_cmd_mcu_on 0x25 - #define on_ic_cmd_mcu_off 0xDA - #define on_ic_adr_sleep_ctrl 0x99 - #define on_ic_cmd_sleep_in 0x80 - #define on_ic_adr_tcon_ctrl 0x80020000 - #define on_ic_cmd_tcon_on 0x00000000 - #define on_ic_adr_wdg_ctrl 0x9000800C - #define on_ic_cmd_wdg_psw 0x0000AC53 - #define on_ic_adr_wdg_cnt_ctrl 0x90008010 - #define on_ic_cmd_wdg_cnt_clr 0x000035CA -/* CORE_IC */ - -/* CORE_FW */ - #define fw_addr_system_reset 0x90000018 - #define fw_addr_safe_mode_release_pw 0x90000098 - #define fw_addr_ctrl_fw 0x9000005c - #define fw_addr_flag_reset_event 0x900000e4 - #define fw_addr_hsen_enable 0x10007F14 - #define fw_addr_smwp_enable 0x10007F10 - #define fw_usb_detect_addr 0x10007F38 - #define fw_addr_program_reload_from 0x00000000 - #define fw_addr_program_reload_to 0x08000000 - #define fw_addr_program_reload_page_write 0x0000fb00 - #define fw_addr_raw_out_sel 0x800204b4 - #define fw_addr_reload_status 0x80050000 - #define fw_addr_reload_crc32_result 0x80050018 - #define fw_addr_reload_addr_from 0x80050020 - #define fw_addr_reload_addr_cmd_beat 0x80050028 - #define fw_data_system_reset 0x00000055 - #define fw_data_safe_mode_release_pw_active 0x00000053 - #define fw_data_safe_mode_release_pw_reset 0x00000000 - #define fw_data_clear 0x00000000 - #define fw_data_fw_stop 0x000000A5 - #define fw_data_program_reload_start 0x0A3C3000 - #define fw_data_program_reload_compare 0x04663000 - #define fw_data_program_reload_break 0x15E75678 - #define fw_addr_selftest_addr_en 0x10007F18 - #define fw_addr_selftest_result_addr 0x10007f24 - #define fw_data_selftest_request 0x00006AA6 - #define fw_addr_criteria_addr 0x10007f1c - #define fw_data_criteria_aa_top 0x64 - #define fw_data_criteria_aa_bot 0x00 - #define fw_data_criteria_key_top 0x64 - #define fw_data_criteria_key_bot 0x00 - #define fw_data_criteria_avg_top 0x64 - #define fw_data_criteria_avg_bot 0x00 - #define fw_addr_set_frame_addr 0x10007294 - #define fw_data_set_frame 0x0000000A - #define fw_data_selftest_ack_hb 0xa6 - #define fw_data_selftest_ack_lb 0x6a - #define fw_data_selftest_pass 0xaa - #define fw_data_normal_cmd 0x00 - #define fw_data_normal_status 0x99 - #define fw_data_sorting_cmd 0xaa - #define fw_data_sorting_status 0xcc - #define fw_data_idle_dis_pwd 0x17 - #define fw_data_idle_en_pwd 0x1f - #define fw_addr_sorting_mode_en 0x10007f04 - #define fw_addr_fw_mode_status 0x10007088 - #define fw_addr_icid_addr 0x900000d0 - #define fw_addr_fw_ver_addr 0x10007004 - #define fw_addr_fw_cfg_addr 0x10007084 - #define fw_addr_fw_vendor_addr 0x10007000 - #define fw_addr_cus_info 0x10007008 - #define fw_addr_proj_info 0x10007014 - #define fw_addr_fw_state_addr 0x900000f8 - #define fw_addr_fw_dbg_msg_addr 0x10007f40 - #define fw_addr_chk_fw_status 0x900000a8 - #define fw_addr_dd_handshak_addr 0x900000fc - #define fw_addr_dd_data_addr 0x10007f80 - #define fw_data_dd_request 0xaa - #define fw_data_dd_ack 0xbb - #define fw_data_rawdata_ready_hb 0xa3 - #define fw_data_rawdata_ready_lb 0x3a - #define fw_addr_ahb_addr 0x11 - #define fw_data_ahb_dis 0x00 - #define fw_data_ahb_en 0x01 - #define fw_addr_event_addr 0x30 - #define fw_func_handshaking_pwd 0xA55AA55A - #define fw_func_handshaking_end 0x77887788 - #define fw_addr_ulpm_33 0x33 - #define fw_addr_ulpm_34 0x34 - #define fw_data_ulpm_11 0x11 - #define fw_data_ulpm_22 0x22 - #define fw_data_ulpm_33 0x33 - #define fw_data_ulpm_aa 0xAA - - #define on_fw_addr_smwp_enable 0xA2 - #define on_fw_usb_detect_addr 0xA4 - #define on_fw_addr_program_reload_from 0x00000000 - #define on_fw_addr_raw_out_sel 0x98 - #define on_fw_addr_flash_checksum 0x80000044 - #define on_fw_data_flash_checksum 0x00000491 - #define on_fw_addr_crc_value 0x80000050 - #define on_fw_data_safe_mode_release_pw_active 0x00000053 - #define on_fw_data_safe_mode_release_pw_reset 0x00000000 - #define on_fw_addr_criteria_addr 0x9A - #define on_fw_data_selftest_pass 0xaa - #define on_fw_addr_reK_crtl 0x8000000C - #define on_fw_data_reK_en 0x02 - #define on_fw_data_reK_dis 0xFD - #define on_fw_data_rst_init 0xF0 - #define on_fw_data_dc_set 0x02 - #define on_fw_data_bank_set 0x03 - #define on_fw_addr_selftest_addr_en 0x98 - #define on_fw_addr_selftest_result_addr 0x9B - #define on_fw_data_selftest_request 0x06 - #define on_fw_data_thx_avg_mul_dc_lsb 0x22 - #define on_fw_data_thx_avg_mul_dc_msb 0x0B - #define on_fw_data_thx_mul_dc_up_low_bud 0x64 - #define on_fw_data_thx_avg_slf_dc_lsb 0x14 - #define on_fw_data_thx_avg_slf_dc_msb 0x05 - #define on_fw_data_thx_slf_dc_up_low_bud 0x64 - #define on_fw_data_thx_slf_bank_up 0x40 - #define on_fw_data_thx_slf_bank_low 0x00 - #define on_fw_data_idle_dis_pwd 0x40 - #define on_fw_data_idle_en_pwd 0x00 - #define on_fw_addr_fw_mode_status 0x99 - #define on_fw_addr_icid_addr 0x900000d0 - #define on_fw_addr_fw_ver_start 0x90 - #define on_fw_data_rawdata_ready_hb 0xa3 - #define on_fw_data_rawdata_ready_lb 0x3a - #define on_fw_addr_ahb_addr 0x11 - #define on_fw_data_ahb_dis 0x00 - #define on_fw_data_ahb_en 0x01 - #define on_fw_addr_event_addr 0x30 -/* CORE_FW */ - -/* CORE_FLASH */ - #define flash_addr_ctrl_base 0x80000000 - #define flash_addr_spi200_trans_fmt (flash_addr_ctrl_base + 0x10) - #define flash_addr_spi200_trans_ctrl (flash_addr_ctrl_base + 0x20) - #define flash_addr_spi200_cmd (flash_addr_ctrl_base + 0x24) - #define flash_addr_spi200_addr (flash_addr_ctrl_base + 0x28) - #define flash_addr_spi200_data (flash_addr_ctrl_base + 0x2c) - #define flash_addr_spi200_fifo_rst (flash_addr_ctrl_base + 0x30) - #define flash_addr_spi200_rst_status (flash_addr_ctrl_base + 0x34) - #define flash_addr_spi200_flash_speed (flash_addr_ctrl_base + 0x40) - #define flash_addr_spi200_bt_num (flash_addr_ctrl_base + 0xe8) - #define flash_data_spi200_txfifo_rst 0x00000004 - #define flash_data_spi200_rxfifo_rst 0x00000002 - #define flash_data_spi200_trans_fmt 0x00020780 - #define flash_data_spi200_trans_ctrl_1 0x42000003 - #define flash_data_spi200_trans_ctrl_2 0x47000000 - #define flash_data_spi200_trans_ctrl_3 0x67000000 - #define flash_data_spi200_trans_ctrl_4 0x610ff000 - #define flash_data_spi200_trans_ctrl_5 0x694002ff - #define flash_data_spi200_trans_ctrl_6 0x42000000 - #define flash_data_spi200_trans_ctrl_7 0x6940020f - #define flash_data_spi200_cmd_1 0x00000005 - #define flash_data_spi200_cmd_2 0x00000006 - #define flash_data_spi200_cmd_3 0x000000C7 - #define flash_data_spi200_cmd_4 0x000000D8 - #define flash_data_spi200_cmd_5 0x00000020 - #define flash_data_spi200_cmd_6 0x00000002 - #define flash_data_spi200_cmd_7 0x0000003b - #define flash_data_spi200_cmd_8 0x00000003 - #define flash_data_spi200_addr 0x00000000 - - #define on_flash_addr_ctrl_base 0x80000000 - #define on_flash_addr_ctrl_auto 0x80000004 - #define on_flash_data_main_erase 0x0000A50D - #define on_flash_data_auto 0xA5 - #define on_flash_data_main_read 0x03 - #define on_flash_data_page_write 0x05 - #define on_flash_data_spp_read 0x10 - #define on_flash_data_sfr_read 0x14 - #define on_flash_addr_ahb_ctrl 0x80000020 - #define on_flash_data_ahb_squit 0x00000001 - #define on_flash_addr_unlock_0 0x00000000 - #define on_flash_addr_unlock_4 0x00000004 - #define on_flash_addr_unlock_8 0x00000008 - #define on_flash_addr_unlock_c 0x0000000C - #define on_flash_data_cmd0 0x28178EA0 - #define on_flash_data_cmd1 0x0A0E03FF - #define on_flash_data_cmd2 0x8C203D0C - #define on_flash_data_cmd3 0x00300263 - #define on_flash_data_lock 0x03400000 -/* CORE_FLASH */ - -/* CORE_SRAM */ - #define sram_adr_mkey 0x100070E8 - #define sram_adr_rawdata_addr 0x10000000 - #define sram_adr_rawdata_end 0x00000000 - #define sram_passwrd_start 0x5AA5 - #define sram_passwrd_end 0xA55A - - #define on_sram_adr_rawdata_addr 0x080002E0 - #define on_sram_adr_rawdata_end 0x00000000 - #define on_sram_cmd_conti 0x44332211 - #define on_sram_cmd_fin 0x00000000 - #define on_sram_passwrd_start 0x5AA5 - #define on_sram_passwrd_end 0xA55A -/* CORE_SRAM */ - -/* CORE_DRIVER */ - #define driver_addr_fw_define_flash_reload 0x10007f00 - #define driver_addr_fw_define_2nd_flash_reload 0x100072c0 - #define driver_data_fw_define_flash_reload_dis 0x0000a55a - #define driver_data_fw_define_flash_reload_en 0x00000000 - #define driver_addr_fw_define_int_is_edge 0x10007088 - #define driver_addr_fw_define_rxnum_txnum_maxpt 0x100070f4 - #define driver_data_fw_define_rxnum_txnum_maxpt_sorting 0x00000008 - #define driver_data_fw_define_rxnum_txnum_maxpt_normal 0x00000014 - #define driver_addr_fw_define_xy_res_enable 0x100070f8 - #define driver_addr_fw_define_x_y_res 0x100070fc - #define driver_data_df_rx 36 - #define driver_data_df_tx 18 - #define driver_data_df_pt 10 - #define driver_data_df_x_res 1080 - #define driver_data_df_y_res 1920 - #define on_driver_addr_fw_define_int_is_edge 0x10007088 - #define on_driver_data_df_rx 28 - #define on_driver_data_df_tx 14 - #define on_driver_data_df_pt 10 - #define on_driver_data_df_x_res 1080 - #define on_driver_data_df_y_res 1920 -#if !defined(HX_NEW_EVENT_STACK_FORMAT) - #define on_driver_addr_fw_rx_tx_maxpt_num 0x0800001C - #define on_driver_addr_fw_xy_rev_int_edge 0x0800000C - #define on_driver_addr_fw_define_x_y_res 0x08000030 -#else - #define on_driver_addr_fw_rx_tx_maxpt_num 0x08000004 - #define on_driver_addr_fw_maxpt_bt_num 0x0800000C - #define on_driver_addr_fw_xy_rev_int_edge 0x08000110 - #define on_driver_addr_fw_define_x_y_res 0x08000010 -#endif - -/* CORE_DRIVER */ - -#if defined(HX_ZERO_FLASH) - #define zf_data_dis_flash_reload 0x00009AA9 - #define zf_addr_system_reset 0x90000018 - #define zf_data_system_reset 0x00000055 - #define zf_data_sram_start_addr 0x08000000 - #define zf_data_cfg_info 0x10007000 - #define zf_data_fw_cfg_1 0x10007084 - #define zf_data_fw_cfg_2 0x10007264 - #define zf_data_fw_cfg_3 0x10007300 - #define zf_data_adc_cfg_1 0x10006A00 - #define zf_data_adc_cfg_2 0x10007B28 - #define zf_data_adc_cfg_3 0x10007AF0 - #define zf_data_map_table 0x10007500 -/* #define zf_data_mode_switch 0x10007294*/ - #define zf_addr_sts_chk 0x900000A8 - #define zf_data_activ_sts 0x05 - #define zf_addr_activ_relod 0x90000048 - #define zf_data_activ_in 0xEC - -#if defined(HX_CODE_OVERLAY) - #define ovl_section_num 3 - #define ovl_gesture_request 0x11 - #define ovl_gesture_reply 0x22 - #define ovl_border_request 0x55 - #define ovl_border_reply 0x66 - #define ovl_sorting_request 0x99 - #define ovl_sorting_reply 0xAA - #define ovl_fault 0xFF -#endif - -struct zf_info { - uint8_t sram_addr[4]; - int write_size; - uint32_t fw_addr; - uint32_t cfg_addr; -}; -#endif - -struct ic_operation { - uint8_t addr_ahb_addr_byte_0[1]; - uint8_t addr_ahb_rdata_byte_0[1]; - uint8_t addr_ahb_access_direction[1]; - uint8_t addr_conti[1]; - uint8_t addr_incr4[1]; - uint8_t adr_i2c_psw_lb[1]; - uint8_t adr_i2c_psw_ub[1]; - uint8_t data_ahb_access_direction_read[1]; - uint8_t data_conti[1]; - uint8_t data_incr4[1]; - uint8_t data_i2c_psw_lb[1]; - uint8_t data_i2c_psw_ub[1]; - uint8_t addr_tcon_on_rst[4]; - uint8_t addr_adc_on_rst[4]; - uint8_t addr_psl[4]; - uint8_t addr_cs_central_state[4]; - uint8_t data_rst[4]; - uint8_t adr_osc_en[4]; - uint8_t adr_osc_pw[4]; -}; - -struct fw_operation { - uint8_t addr_system_reset[4]; - uint8_t addr_safe_mode_release_pw[4]; - uint8_t addr_ctrl_fw_isr[4]; - uint8_t addr_flag_reset_event[4]; - uint8_t addr_hsen_enable[4]; - uint8_t addr_smwp_enable[4]; - uint8_t addr_program_reload_from[4]; - uint8_t addr_program_reload_to[4]; - uint8_t addr_program_reload_page_write[4]; - uint8_t addr_raw_out_sel[4]; - uint8_t addr_reload_status[4]; - uint8_t addr_reload_crc32_result[4]; - uint8_t addr_reload_addr_from[4]; - uint8_t addr_reload_addr_cmd_beat[4]; - uint8_t addr_selftest_addr_en[4]; - uint8_t addr_criteria_addr[4]; - uint8_t addr_set_frame_addr[4]; - uint8_t addr_selftest_result_addr[4]; - uint8_t addr_sorting_mode_en[4]; - uint8_t addr_fw_mode_status[4]; - uint8_t addr_icid_addr[4]; - uint8_t addr_fw_ver_addr[4]; - uint8_t addr_fw_cfg_addr[4]; - uint8_t addr_fw_vendor_addr[4]; - uint8_t addr_cus_info[4]; - uint8_t addr_proj_info[4]; - uint8_t addr_fw_state_addr[4]; - uint8_t addr_fw_dbg_msg_addr[4]; - uint8_t addr_chk_fw_status[4]; - uint8_t addr_dd_handshak_addr[4]; - uint8_t addr_dd_data_addr[4]; - uint8_t data_system_reset[4]; - uint8_t data_safe_mode_release_pw_active[4]; - uint8_t data_safe_mode_release_pw_reset[4]; - uint8_t data_clear[4]; - uint8_t data_fw_stop[4]; - uint8_t data_program_reload_start[4]; - uint8_t data_program_reload_compare[4]; - uint8_t data_program_reload_break[4]; - uint8_t data_selftest_request[4]; - uint8_t data_criteria_aa_top[1]; - uint8_t data_criteria_aa_bot[1]; - uint8_t data_criteria_key_top[1]; - uint8_t data_criteria_key_bot[1]; - uint8_t data_criteria_avg_top[1]; - uint8_t data_criteria_avg_bot[1]; - uint8_t data_set_frame[4]; - uint8_t data_selftest_ack_hb[1]; - uint8_t data_selftest_ack_lb[1]; - uint8_t data_selftest_pass[1]; - uint8_t data_normal_cmd[1]; - uint8_t data_normal_status[1]; - uint8_t data_sorting_cmd[1]; - uint8_t data_sorting_status[1]; - uint8_t data_dd_request[1]; - uint8_t data_dd_ack[1]; - uint8_t data_idle_dis_pwd[1]; - uint8_t data_idle_en_pwd[1]; - uint8_t data_rawdata_ready_hb[1]; - uint8_t data_rawdata_ready_lb[1]; - uint8_t addr_ahb_addr[1]; - uint8_t data_ahb_dis[1]; - uint8_t data_ahb_en[1]; - uint8_t addr_event_addr[1]; - uint8_t addr_usb_detect[4]; - uint8_t addr_ulpm_33[1]; - uint8_t addr_ulpm_34[1]; - uint8_t data_ulpm_11[1]; - uint8_t data_ulpm_22[1]; - uint8_t data_ulpm_33[1]; - uint8_t data_ulpm_aa[1]; -}; - -struct flash_operation { - uint8_t addr_spi200_trans_fmt[4]; - uint8_t addr_spi200_trans_ctrl[4]; - uint8_t addr_spi200_fifo_rst[4]; - uint8_t addr_spi200_rst_status[4]; - uint8_t addr_spi200_flash_speed[4]; - uint8_t addr_spi200_cmd[4]; - uint8_t addr_spi200_addr[4]; - uint8_t addr_spi200_data[4]; - uint8_t addr_spi200_bt_num[4]; - - uint8_t data_spi200_txfifo_rst[4]; - uint8_t data_spi200_rxfifo_rst[4]; - uint8_t data_spi200_trans_fmt[4]; - uint8_t data_spi200_trans_ctrl_1[4]; - uint8_t data_spi200_trans_ctrl_2[4]; - uint8_t data_spi200_trans_ctrl_3[4]; - uint8_t data_spi200_trans_ctrl_4[4]; - uint8_t data_spi200_trans_ctrl_5[4]; - uint8_t data_spi200_trans_ctrl_6[4]; - uint8_t data_spi200_trans_ctrl_7[4]; - uint8_t data_spi200_cmd_1[4]; - uint8_t data_spi200_cmd_2[4]; - uint8_t data_spi200_cmd_3[4]; - uint8_t data_spi200_cmd_4[4]; - uint8_t data_spi200_cmd_5[4]; - uint8_t data_spi200_cmd_6[4]; - uint8_t data_spi200_cmd_7[4]; - uint8_t data_spi200_cmd_8[4]; - uint8_t data_spi200_addr[4]; -}; - -struct sram_operation { - uint8_t addr_mkey[4]; - uint8_t addr_rawdata_addr[4]; - uint8_t addr_rawdata_end[4]; - uint8_t passwrd_start[2]; - uint8_t passwrd_end[2]; -}; - -struct driver_operation { - uint8_t addr_fw_define_flash_reload[4]; - uint8_t addr_fw_define_2nd_flash_reload[4]; - uint8_t addr_fw_define_int_is_edge[4]; - uint8_t addr_fw_define_rxnum_txnum_maxpt[4]; - uint8_t addr_fw_define_xy_res_enable[4]; - uint8_t addr_fw_define_x_y_res[4]; - uint8_t data_df_rx[1]; - uint8_t data_df_tx[1]; - uint8_t data_df_pt[1]; - uint8_t data_df_x_res[2]; - uint8_t data_df_y_res[2]; - uint8_t data_fw_define_flash_reload_dis[4]; - uint8_t data_fw_define_flash_reload_en[4]; - uint8_t data_fw_define_rxnum_txnum_maxpt_sorting[4]; - uint8_t data_fw_define_rxnum_txnum_maxpt_normal[4]; -}; - -struct zf_operation { - uint8_t data_dis_flash_reload[4]; - uint8_t addr_system_reset[4]; - uint8_t data_system_reset[4]; - uint8_t data_sram_start_addr[4]; - uint8_t data_sram_clean[4]; - uint8_t data_cfg_info[4]; - uint8_t data_fw_cfg_1[4]; - uint8_t data_fw_cfg_2[4]; - uint8_t data_fw_cfg_3[4]; - uint8_t data_adc_cfg_1[4]; - uint8_t data_adc_cfg_2[4]; - uint8_t data_adc_cfg_3[4]; - uint8_t data_map_table[4]; -/* uint8_t data_mode_switch[4];*/ - uint8_t addr_sts_chk[4]; - uint8_t data_activ_sts[1]; - uint8_t addr_activ_relod[4]; - uint8_t data_activ_in[1]; -}; - -struct himax_core_command_operation { - struct ic_operation *ic_op; - struct fw_operation *fw_op; - struct flash_operation *flash_op; - struct sram_operation *sram_op; - struct driver_operation *driver_op; - struct zf_operation *zf_op; -}; - -struct on_ic_operation { - uint8_t addr_ahb_addr_byte_0[1]; - uint8_t addr_ahb_rdata_byte_0[1]; - uint8_t addr_ahb_access_direction[1]; - uint8_t addr_conti[1]; - uint8_t addr_incr4[1]; - uint8_t adr_mcu_ctrl[1]; - uint8_t data_ahb_access_direction_read[1]; - uint8_t data_conti[1]; - uint8_t data_incr4[1]; - uint8_t cmd_mcu_on[1]; - uint8_t cmd_mcu_off[1]; - uint8_t adr_sleep_ctrl[1]; - uint8_t cmd_sleep_in[1]; - uint8_t adr_tcon_ctrl[4]; - uint8_t cmd_tcon_on[4]; - uint8_t adr_wdg_ctrl[4]; - uint8_t cmd_wdg_psw[4]; - uint8_t adr_wdg_cnt_ctrl[4]; - uint8_t cmd_wdg_cnt_clr[4]; -}; - -struct on_fw_operation { - uint8_t addr_smwp_enable[1]; - uint8_t addr_program_reload_from[4]; - uint8_t addr_raw_out_sel[1]; - uint8_t addr_flash_checksum[4]; - uint8_t data_flash_checksum[4]; - uint8_t addr_crc_value[4]; - uint8_t addr_reload_status[4]; - uint8_t addr_reload_crc32_result[4]; - uint8_t addr_reload_addr_from[4]; - uint8_t addr_reload_addr_cmd_beat[4]; - uint8_t addr_set_frame_addr[4]; - uint8_t addr_fw_mode_status[1]; - uint8_t addr_icid_addr[4]; - uint8_t addr_fw_ver_start[1]; - uint8_t data_safe_mode_release_pw_active[4]; - uint8_t data_safe_mode_release_pw_reset[4]; - uint8_t data_clear[4]; - uint8_t addr_criteria_addr[1]; - uint8_t data_selftest_pass[1]; - uint8_t addr_reK_crtl[4]; - uint8_t data_reK_en[1]; - uint8_t data_reK_dis[1]; - uint8_t data_rst_init[1]; - uint8_t data_dc_set[1]; - uint8_t data_bank_set[1]; - uint8_t addr_selftest_addr_en[1]; - uint8_t addr_selftest_result_addr[1]; - uint8_t data_selftest_request[1]; - uint8_t data_thx_avg_mul_dc_lsb[1]; - uint8_t data_thx_avg_mul_dc_msb[1]; - uint8_t data_thx_mul_dc_up_low_bud[1]; - uint8_t data_thx_avg_slf_dc_lsb[1]; - uint8_t data_thx_avg_slf_dc_msb[1]; - uint8_t data_thx_slf_dc_up_low_bud[1]; - uint8_t data_thx_slf_bank_up[1]; - uint8_t data_thx_slf_bank_low[1]; - uint8_t data_idle_dis_pwd[1]; - uint8_t data_idle_en_pwd[1]; - uint8_t data_rawdata_ready_hb[1]; - uint8_t data_rawdata_ready_lb[1]; - uint8_t addr_ahb_addr[1]; - uint8_t data_ahb_dis[1]; - uint8_t data_ahb_en[1]; - uint8_t addr_event_addr[1]; - uint8_t addr_usb_detect[1]; -}; - -struct on_flash_operation { - uint8_t addr_ctrl_base[4]; - uint8_t addr_ctrl_auto[4]; - uint8_t data_main_erase[4]; - uint8_t data_auto[1]; - uint8_t data_main_read[1]; - uint8_t data_page_write[1]; - uint8_t data_sfr_read[1]; - uint8_t data_spp_read[1]; - uint8_t addr_ahb_ctrl[4]; - uint8_t data_ahb_squit[4]; - - uint8_t addr_unlock_0[4]; - uint8_t addr_unlock_4[4]; - uint8_t addr_unlock_8[4]; - uint8_t addr_unlock_c[4]; - uint8_t data_cmd0[4]; - uint8_t data_cmd1[4]; - uint8_t data_cmd2[4]; - uint8_t data_cmd3[4]; - uint8_t data_lock[4]; -}; - -struct on_sram_operation { - uint8_t addr_rawdata_addr[4]; - uint8_t addr_rawdata_end[4]; - uint8_t data_conti[4]; - uint8_t data_fin[4]; - uint8_t passwrd_start[2]; - uint8_t passwrd_end[2]; -}; - -struct on_driver_operation { - uint8_t addr_fw_define_int_is_edge[4]; - uint8_t addr_fw_rx_tx_maxpt_num[4]; -#if defined(HX_NEW_EVENT_STACK_FORMAT) - uint8_t addr_fw_maxpt_bt_num[4]; -#endif - uint8_t addr_fw_xy_rev_int_edge[4]; - uint8_t addr_fw_define_x_y_res[4]; - uint8_t data_fw_define_rxnum_txnum_maxpt_sorting[4]; - uint8_t data_fw_define_rxnum_txnum_maxpt_normal[4]; - uint8_t data_df_rx[1]; - uint8_t data_df_tx[1]; - uint8_t data_df_pt[1]; - uint8_t data_df_x_res[2]; - uint8_t data_df_y_res[2]; -}; - -struct himax_on_core_command_operation { - struct on_ic_operation *ic_op; - struct on_fw_operation *fw_op; - struct on_flash_operation *flash_op; - struct on_sram_operation *sram_op; - struct on_driver_operation *driver_op; -}; - -struct himax_chip_detect { - bool (*fp_chip_detect)(void); -}; - -struct himax_chip_entry { - struct himax_chip_detect *core_chip_dt; - uint32_t hx_ic_dt_num; -}; - -struct himax_core_fp { -/* CORE_IC */ - void (*fp_burst_enable)(uint8_t auto_add_4_byte); - int (*fp_register_read)(uint8_t *read_addr, uint32_t read_length, - uint8_t *read_data, uint8_t cfg_flag); - /*int (*fp_flash_write_burst)(uint8_t *reg_byte, uint8_t *write_data);*/ - /*void (*fp_flash_write_burst_lenth)(uint8_t *reg_byte, - * uint8_t *write_data, uint32_t length); - */ - int (*fp_register_write)(uint8_t *write_addr, uint32_t write_length, - uint8_t *write_data, uint8_t cfg_flag); - void (*fp_interface_on)(void); - void (*fp_sense_on)(uint8_t FlashMode); - void (*fp_tcon_on)(void); - bool (*fp_watch_dog_off)(void); - bool (*fp_sense_off)(bool check_en); - void (*fp_sleep_in)(void); - bool (*fp_wait_wip)(int Timing); - void (*fp_init_psl)(void); - void (*fp_resume_ic_action)(void); - void (*fp_suspend_ic_action)(void); - void (*fp_power_on_init)(void); - bool (*fp_dd_clk_set)(bool enable); - void (*fp_dd_reg_en)(bool enable); - bool (*fp_dd_reg_write)(uint8_t addr, uint8_t pa_num, int len, - uint8_t *data, uint8_t bank); - bool (*fp_dd_reg_read)(uint8_t addr, uint8_t pa_num, int len, - uint8_t *data, uint8_t bank); - bool (*fp_ic_id_read)(void); - bool (*fp_slave_tcon_reset)(void); - bool (*fp_slave_adc_reset_slave)(void); - bool (*fp_slave_wdt_off_slave)(void); -/* CORE_IC */ - -/* CORE_FW */ - void (*fp_parse_raw_data)(struct himax_report_data *hx_touch_data, - int mul_num, - int self_num, - uint8_t diag_cmd, - int16_t *mutual_data, - int16_t *self_data); - void (*fp_system_reset)(void); - int (*fp_Calculate_CRC_with_AP)(unsigned char *FW_content, - int CRC_from_FW, - int len); - uint32_t (*fp_check_CRC)(uint8_t *start_addr, int reload_length); - void (*fp_set_reload_cmd)(uint8_t *write_data, - int idx, - uint32_t cmd_from, - uint32_t cmd_to, - uint32_t cmd_beat); - bool (*fp_program_reload)(void); - void (*fp_set_SMWP_enable)(uint8_t SMWP_enable, bool suspended); - void (*fp_set_HSEN_enable)(uint8_t HSEN_enable, bool suspended); - void (*fp_diag_register_set)(uint8_t diag_command, - uint8_t storage_type, bool is_dirly); -#if defined(HX_TP_SELF_TEST_DRIVER) - void (*fp_control_reK)(bool enable); -#endif - int (*fp_chip_self_test)(struct seq_file *s, void *v); - void (*fp_idle_mode)(int disable); - void (*fp_reload_disable)(int disable); - bool (*fp_check_chip_version)(void); - int (*fp_read_ic_trigger_type)(void); - int (*fp_read_i2c_status)(void); - void (*fp_read_FW_ver)(void); - bool (*fp_read_event_stack)(uint8_t *buf, uint8_t length); - void (*fp_return_event_stack)(void); - bool (*fp_calculateChecksum)(bool change_iref, uint32_t size); - int (*fp_read_FW_status)(uint8_t *state_addr, uint8_t *tmp_addr); - void (*fp_irq_switch)(int switch_on); - int (*fp_assign_sorting_mode)(uint8_t *tmp_data); - int (*fp_check_sorting_mode)(uint8_t *tmp_data); - int (*fp_get_max_dc)(void); - uint8_t (*fp_read_DD_status)(uint8_t *cmd_set, uint8_t *tmp_data); - int (*fp_ulpm_in)(void); - int (*fp_black_gest_ctrl)(bool enable); - int (*_diff_overlay_bin)(void); -/* CORE_FW */ - -/* CORE_FLASH */ - void (*fp_chip_erase)(void); - bool (*fp_block_erase)(int start_addr, int length); - bool (*fp_sector_erase)(int start_addr); - void (*fp_flash_programming)(uint8_t *FW_content, int FW_Size); - void (*fp_flash_page_write)(uint8_t *write_addr, int length, - uint8_t *write_data); - int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_32k)(unsigned char *fw, - int len, bool change_iref); - int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_60k)(unsigned char *fw, - int len, bool change_iref); - int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_64k)(unsigned char *fw, - int len, bool change_iref); - int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_124k)(unsigned char *fw, - int len, bool change_iref); - int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_128k)(unsigned char *fw, - int len, bool change_iref); - void (*fp_flash_dump_func)(uint8_t local_flash_command, - int Flash_Size, uint8_t *flash_buffer); - bool (*fp_flash_lastdata_check)(uint32_t size); - bool (*fp_ahb_squit)(void); - void (*fp_flash_read)(uint8_t *r_data, int start_addr, int length); - bool (*fp_sfr_rw)(uint8_t *addr, int length, - uint8_t *data, uint8_t rw_ctrl); - bool (*fp_lock_flash)(void); - bool (*fp_unlock_flash)(void); - void (*fp_init_auto_func)(void); - int (*_diff_overlay_flash)(void); -/* CORE_FLASH */ - -/* CORE_SRAM */ - void (*fp_sram_write)(uint8_t *FW_content); - bool (*fp_sram_verify)(uint8_t *FW_File, int FW_Size); - bool (*fp_get_DSRAM_data)(uint8_t *info_data, bool DSRAM_Flag); -/* CORE_SRAM */ - -/* CORE_DRIVER */ - void (*fp_chip_init)(void); -#if defined(HX_AUTO_UPDATE_FW) - int (*fp_fw_ver_bin)(void); -#endif - void (*fp_pin_reset)(void); - void (*fp_touch_information)(void); - void (*fp_reload_config)(void); - int (*fp_get_touch_data_size)(void); - void (*fp_usb_detect_set)(uint8_t *cable_config); - int (*fp_hand_shaking)(void); - int (*fp_determin_diag_rawdata)(int diag_command); - int (*fp_determin_diag_storage)(int diag_command); - int (*fp_cal_data_len)(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max); - bool (*fp_diag_check_sum)(struct himax_report_data *hx_touch_data); - void (*fp_diag_parse_raw_data)(struct himax_report_data *hx_touch_data, - int mul_num, - int self_num, - uint8_t diag_cmd, - int32_t *mutual_data, - int32_t *self_data); - void (*fp_ic_reset)(uint8_t loadconfig, uint8_t int_off); - int (*fp_ic_esd_recovery)(int hx_esd_event, - int hx_zero_event, int length); - void (*fp_esd_ic_reset)(void); - void (*fp_resend_cmd_func)(bool suspended); -#if defined(HX_TP_PROC_GUEST_INFO) - int (*guest_info_get_status)(void); - int (*read_guest_info)(void); -#endif -/* CORE_DRIVER */ -#if defined(HX_ZERO_FLASH) - void (*fp_clean_sram_0f)(uint8_t *addr, int write_len, int type); - void (*fp_write_sram_0f)(const struct firmware *fw_entry, - uint8_t *addr, - int start_index, - uint32_t write_len); - int (*fp_write_sram_0f_crc)(const struct firmware *fw_entry, - uint8_t *addr, - int start_index, - uint32_t write_len); - void (*fp_firmware_update_0f)(const struct firmware *fw_entry); - int (*fp_0f_operation_dirly)(void); - int (*fp_0f_op_file_dirly)(char *file_name); - void (*fp_0f_operation)(struct work_struct *work); - int (*fp_0f_esd_check)(void); - void (*fp_0f_reload_to_active)(void); -#if defined(HX_0F_DEBUG) - void (*fp_read_sram_0f)(const struct firmware *fw_entry, - uint8_t *addr, - int start_index, - int read_len); - void (*fp_read_all_sram)(uint8_t *addr, int read_len); - void (*fp_firmware_read_0f)(const struct firmware *fw_entry, int type); - void (*fp_0f_operation_check)(int type); -#endif -#if defined(HX_CODE_OVERLAY) - int (*fp_0f_overlay)(int ovl_type, int mode); -#endif -#endif -}; - -#endif +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for ic core functions + * + * 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. + */ + +#ifndef __HIMAX_IC_CORE_H__ +#define __HIMAX_IC_CORE_H__ + +#include "himax_platform.h" +#include "himax_common.h" +#include + +#define DATA_LEN_8 8 +#define DATA_LEN_4 4 +#define ADDR_LEN_4 4 +#define FLASH_RW_MAX_LEN 256 +#define FLASH_WRITE_BURST_SZ 8 +#define PROGRAM_SZ 48 +#define MAX_I2C_TRANS_SZ 128 +#define HIMAX_REG_RETRY_TIMES 5 +#define FW_BIN_16K_SZ 0x4000 +#define HIMAX_TOUCH_DATA_SIZE 128 +#define MASK_BIT_0 0x01 +#define MASK_BIT_1 0x02 +#define MASK_BIT_2 0x04 + +#define FW_SECTOR_PER_BLOCK 8 +#define FW_PAGE_PER_SECTOR 64 +#define FW_PAGE_SEZE 128 +#define HX256B 0x100 +#define HX4K 0x1000 +#define HX_32K_SZ 0x8000 +#define HX_40K_SZ 0xA000 +#define HX_48K_SZ 0xC000 +#define HX64K 0x10000 +#define HX124K 0x1f000 +#define HX4000K 0x1000000 + +#define HX_NORMAL_MODE 1 +#define HX_SORTING_MODE 2 +#define HX_CHANGE_MODE_FAIL (-1) +#define HX_RW_REG_FAIL (-1) +#define HX_DRIVER_MAX_IC_NUM 12 + +#if defined(__HIMAX_HX852xG_MOD__) +#define HX_MOD_KSYM_HX852xG HX_MOD_KSYM_HX852xG +#endif + +#if defined(__HIMAX_HX852xH_MOD__) +#define HX_MOD_KSYM_HX852xH HX_MOD_KSYM_HX852xH +#endif + +#if defined(__HIMAX_HX83102_MOD__) +#define HX_MOD_KSYM_HX83102 HX_MOD_KSYM_HX83102 +#endif + +#if defined(__HIMAX_HX83102D_MOD__) +#define HX_MOD_KSYM_HX83102 HX_MOD_KSYM_HX83102 +#define HX83102D +#endif + +#if defined(__HIMAX_HX83103_MOD__) +#define HX_MOD_KSYM_HX83103 HX_MOD_KSYM_HX83103 +#endif + +#if defined(__HIMAX_HX83106_MOD__) +#define HX_MOD_KSYM_HX83106 HX_MOD_KSYM_HX83106 +#endif + +#if defined(__HIMAX_HX83111_MOD__) +#define HX_MOD_KSYM_HX83111 HX_MOD_KSYM_HX83111 +#endif + +#if defined(__HIMAX_HX83112_MOD__) +#define HX_MOD_KSYM_HX83112 HX_MOD_KSYM_HX83112 +#endif + +#if defined(__HIMAX_HX83191_MOD__) +#define HX_MOD_KSYM_HX83191 HX_MOD_KSYM_HX83191 +#endif + +#if defined(__HIMAX_HX83113_MOD__) +#define HX_MOD_KSYM_HX83113 HX_MOD_KSYM_HX83113 +#endif + +#define CORE_INIT +#define CORE_IC +#define CORE_FW +#define CORE_FLASH +#define CORE_SRAM +#define CORE_DRIVER + +#define HX_0F_DEBUG + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_INCELL + +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) + extern char *i_CTPM_firmware_name; +#endif + +#ifdef HX_ZERO_FLASH + extern int g_f_0f_updat; +#endif + +#ifdef HX_TP_PROC_GUEST_INFO + extern struct hx_guest_info *g_guest_info_data; +#endif + +void himax_mcu_in_cmd_struct_free(void); + +#endif + +#ifdef CONFIG_TOUCHSCREEN_HIMAX_ONCELL + +void himax_mcu_on_cmd_struct_free(void); + +#endif + +#ifdef HX_AUTO_UPDATE_FW +extern int g_i_FW_VER; +extern int g_i_CFG_VER; +extern int g_i_CID_MAJ; +extern int g_i_CID_MIN; +extern unsigned char *i_CTPM_FW; +#endif + +extern unsigned long FW_VER_MAJ_FLASH_ADDR; +extern unsigned long FW_VER_MIN_FLASH_ADDR; +extern unsigned long CFG_VER_MAJ_FLASH_ADDR; +extern unsigned long CFG_VER_MIN_FLASH_ADDR; +extern unsigned long CID_VER_MAJ_FLASH_ADDR; +extern unsigned long CID_VER_MIN_FLASH_ADDR; + +extern unsigned long FW_VER_MAJ_FLASH_LENG; +extern unsigned long FW_VER_MIN_FLASH_LENG; +extern unsigned long CFG_VER_MAJ_FLASH_LENG; +extern unsigned long CFG_VER_MIN_FLASH_LENG; +extern unsigned long CID_VER_MAJ_FLASH_LENG; +extern unsigned long CID_VER_MIN_FLASH_LENG; + +extern unsigned char IC_CHECKSUM; +#ifdef HX_ESD_RECOVERY +extern int g_zero_event_count; +#endif + +#ifdef HX_RST_PIN_FUNC +extern u8 HX_HW_RESET_ACTIVATE; +void himax_rst_gpio_set(int pinnum, uint8_t value); +#endif + +#if defined(HX_USB_DETECT_GLOBAL) +void himax_cable_detect_func(bool force_renew); +#endif + +int himax_report_data_init(void); +extern int i2c_error_count; + +#ifdef HX_ESD_RECOVERY + extern u8 HX_ESD_RESET_ACTIVATE; +#endif + +#ifdef CORE_INIT + int himax_mcu_in_cmd_struct_init(void); + void himax_in_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len); + void himax_mcu_in_cmd_init(void); + + int himax_mcu_on_cmd_struct_init(void); + void himax_on_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len); + void himax_mcu_on_cmd_init(void); + + extern void (*himax_mcu_cmd_struct_free)(void); +#endif + +#ifdef HX_TP_PROC_GUEST_INFO +#define HX_GUEST_INFO_SIZE 10 +#define HX_GUEST_INFO_LEN_SIZE 4 +#define HX_GUEST_INFO_ID_SIZE 4 + +struct hx_guest_info { + int g_guest_info_ongoing; /* 0 stop, 1 ongoing */ + uint8_t g_guest_str[10][128]; + uint8_t g_guest_str_in_format[10][128]; + uint8_t g_guest_data_type[10]; + int g_guest_data_len[10]; + int g_guest_info_type; +}; + +#endif + +#if defined(CORE_IC) + #define ic_adr_ahb_addr_byte_0 0x00 + #define ic_adr_ahb_rdata_byte_0 0x08 + #define ic_adr_ahb_access_direction 0x0c + #define ic_adr_conti 0x13 + #define ic_adr_incr4 0x0D + #define ic_adr_i2c_psw_lb 0x31 + #define ic_adr_i2c_psw_ub 0x32 + #define ic_cmd_ahb_access_direction_read 0x00 + #define ic_cmd_conti 0x31 + #define ic_cmd_incr4 0x10 + #define ic_cmd_i2c_psw_lb 0x27 + #define ic_cmd_i2c_psw_ub 0x95 + #define ic_adr_tcon_on_rst 0x80020020 + #define ic_addr_adc_on_rst 0x80020094 + #define ic_adr_psl 0x900000A0 + #define ic_adr_cs_central_state 0x900000A8 + #define ic_cmd_rst 0x00000000 + #define ic_adr_osc_en 0x900880A8 + #define ic_adr_osc_pw 0x900880E0 + + #define on_ic_adr_ahb_addr_byte_0 0x00 + #define on_ic_adr_ahb_rdata_byte_0 0x08 + #define on_ic_adr_ahb_access_direction 0x0c + #define on_ic_adr_conti 0x13 + #define on_ic_adr_incr4 0x0D + #define on_ic_cmd_ahb_access_direction_read 0x00 + #define on_ic_cmd_conti 0x31 + #define on_ic_cmd_incr4 0x10 + #define on_ic_adr_mcu_ctrl 0x82 + #define on_ic_cmd_mcu_on 0x25 + #define on_ic_cmd_mcu_off 0xDA + #define on_ic_adr_sleep_ctrl 0x99 + #define on_ic_cmd_sleep_in 0x80 + #define on_ic_adr_tcon_ctrl 0x80020000 + #define on_ic_cmd_tcon_on 0x00000000 + #define on_ic_adr_wdg_ctrl 0x9000800C + #define on_ic_cmd_wdg_psw 0x0000AC53 + #define on_ic_adr_wdg_cnt_ctrl 0x90008010 + #define on_ic_cmd_wdg_cnt_clr 0x000035CA +#endif + +#if defined(CORE_FW) + #define fw_addr_system_reset 0x90000018 + #define fw_addr_safe_mode_release_pw 0x90000098 + #define fw_addr_ctrl_fw 0x9000005c + #define fw_addr_flag_reset_event 0x900000e4 + #define fw_addr_hsen_enable 0x10007F14 + #define fw_addr_smwp_enable 0x10007F10 + #define fw_usb_detect_addr 0x10007F38 + #define fw_addr_program_reload_from 0x00000000 + #define fw_addr_program_reload_to 0x08000000 + #define fw_addr_program_reload_page_write 0x0000fb00 + #define fw_addr_raw_out_sel 0x800204b4 + #define fw_addr_reload_status 0x80050000 + #define fw_addr_reload_crc32_result 0x80050018 + #define fw_addr_reload_addr_from 0x80050020 + #define fw_addr_reload_addr_cmd_beat 0x80050028 + #define fw_data_system_reset 0x00000055 + #define fw_data_safe_mode_release_pw_active 0x00000053 + #define fw_data_safe_mode_release_pw_reset 0x00000000 + #define fw_data_clear 0x00000000 + #define fw_data_fw_stop 0x000000A5 + #define fw_data_program_reload_start 0x0A3C3000 + #define fw_data_program_reload_compare 0x04663000 + #define fw_data_program_reload_break 0x15E75678 + #define fw_addr_selftest_addr_en 0x10007F18 + #define fw_addr_selftest_result_addr 0x10007f24 + #define fw_data_selftest_request 0x00006AA6 + #define fw_addr_criteria_addr 0x10007f1c + #define fw_data_criteria_aa_top 0x64 + #define fw_data_criteria_aa_bot 0x00 + #define fw_data_criteria_key_top 0x64 + #define fw_data_criteria_key_bot 0x00 + #define fw_data_criteria_avg_top 0x64 + #define fw_data_criteria_avg_bot 0x00 + #define fw_addr_set_frame_addr 0x10007294 + #define fw_data_set_frame 0x0000000A + #define fw_data_selftest_ack_hb 0xa6 + #define fw_data_selftest_ack_lb 0x6a + #define fw_data_selftest_pass 0xaa + #define fw_data_normal_cmd 0x00 + #define fw_data_normal_status 0x99 + #define fw_data_sorting_cmd 0xaa + #define fw_data_sorting_status 0xcc + #define fw_data_idle_dis_pwd 0x17 + #define fw_data_idle_en_pwd 0x1f + #define fw_addr_sorting_mode_en 0x10007f04 + #define fw_addr_max_dc 0x10007fc8 + #define fw_addr_fw_mode_status 0x10007088 + #define fw_addr_icid_addr 0x900000d0 + #define fw_addr_trigger_addr 0x10007088 + #define fw_addr_fw_ver_addr 0x10007004 + #define fw_addr_fw_cfg_addr 0x10007084 + #define fw_addr_fw_vendor_addr 0x10007000 + #define fw_addr_cus_info 0x10007008 + #define fw_addr_proj_info 0x10007014 + #define fw_addr_fw_state_addr 0x900000f8 + #define fw_addr_fw_dbg_msg_addr 0x10007f40 + #define fw_addr_chk_fw_status 0x900000a8 + #define fw_addr_dd_handshak_addr 0x900000fc + #define fw_addr_dd_data_addr 0x10007f80 + #define fw_data_dd_request 0xaa + #define fw_data_dd_ack 0xbb + #define fw_data_rawdata_ready_hb 0xa3 + #define fw_data_rawdata_ready_lb 0x3a + #define fw_addr_ahb_addr 0x11 + #define fw_data_ahb_dis 0x00 + #define fw_data_ahb_en 0x01 + #define fw_addr_event_addr 0x30 + #define fw_func_handshaking_pwd 0xA55AA55A + #define fw_func_handshaking_end 0x77887788 + #define fw_addr_ulpm_33 0x33 + #define fw_addr_ulpm_34 0x34 + #define fw_data_ulpm_11 0x11 + #define fw_data_ulpm_22 0x22 + #define fw_data_ulpm_33 0x33 + #define fw_data_ulpm_aa 0xAA + + #define fw_func_edge_portrait_pwd 0xA55AA55A + #define fw_func_edge_lsp_left_pwd 0xA11AA11A + #define fw_func_edge_lsp_right_pwd 0xA33AA33A + + #define on_fw_addr_smwp_enable 0xA2 + #define on_fw_usb_detect_addr 0xA4 + #define on_fw_addr_program_reload_from 0x00000000 + #define on_fw_addr_raw_out_sel 0x98 + #define on_fw_addr_flash_checksum 0x80000044 + #define on_fw_data_flash_checksum 0x00000491 + #define on_fw_addr_crc_value 0x80000050 + #define on_fw_data_safe_mode_release_pw_active 0x00000053 + #define on_fw_data_safe_mode_release_pw_reset 0x00000000 + #define on_fw_addr_criteria_addr 0x9A + #define on_fw_data_selftest_pass 0xaa + #define on_fw_addr_reK_crtl 0x8000000C + #define on_fw_data_reK_en 0x02 + #define on_fw_data_reK_dis 0xFD + #define on_fw_data_rst_init 0xF0 + #define on_fw_data_dc_set 0x02 + #define on_fw_data_bank_set 0x03 + #define on_fw_addr_selftest_addr_en 0x98 + #define on_fw_addr_selftest_result_addr 0x9B + #define on_fw_data_selftest_request 0x06 + #define on_fw_data_thx_avg_mul_dc_lsb 0x22 + #define on_fw_data_thx_avg_mul_dc_msb 0x0B + #define on_fw_data_thx_mul_dc_up_low_bud 0x64 + #define on_fw_data_thx_avg_slf_dc_lsb 0x14 + #define on_fw_data_thx_avg_slf_dc_msb 0x05 + #define on_fw_data_thx_slf_dc_up_low_bud 0x64 + #define on_fw_data_thx_slf_bank_up 0x40 + #define on_fw_data_thx_slf_bank_low 0x00 + #define on_fw_data_idle_dis_pwd 0x40 + #define on_fw_data_idle_en_pwd 0x00 + #define on_fw_addr_fw_mode_status 0x99 + #define on_fw_addr_icid_addr 0x900000d0 + #define on_fw_addr_trigger_addr 0x10007088 + #define on_fw_addr_fw_ver_start 0x90 + #define on_fw_data_rawdata_ready_hb 0xa3 + #define on_fw_data_rawdata_ready_lb 0x3a + #define on_fw_addr_ahb_addr 0x11 + #define on_fw_data_ahb_dis 0x00 + #define on_fw_data_ahb_en 0x01 + #define on_fw_addr_event_addr 0x30 +#endif + +#if defined(CORE_FLASH) + #define flash_addr_ctrl_base 0x80000000 + #define flash_addr_spi200_trans_fmt (flash_addr_ctrl_base + 0x10) + #define flash_addr_spi200_trans_ctrl (flash_addr_ctrl_base + 0x20) + #define flash_addr_spi200_cmd (flash_addr_ctrl_base + 0x24) + #define flash_addr_spi200_addr (flash_addr_ctrl_base + 0x28) + #define flash_addr_spi200_data (flash_addr_ctrl_base + 0x2c) + #define flash_addr_spi200_bt_num (flash_addr_ctrl_base + 0xe8) + #define flash_data_spi200_trans_fmt 0x00020780 + #define flash_data_spi200_trans_ctrl_1 0x42000003 + #define flash_data_spi200_trans_ctrl_2 0x47000000 + #define flash_data_spi200_trans_ctrl_3 0x67000000 + #define flash_data_spi200_trans_ctrl_4 0x610ff000 + #define flash_data_spi200_trans_ctrl_5 0x694002ff + #define flash_data_spi200_cmd_1 0x00000005 + #define flash_data_spi200_cmd_2 0x00000006 + #define flash_data_spi200_cmd_3 0x000000C7 + #define flash_data_spi200_cmd_4 0x000000D8 + #define flash_data_spi200_cmd_5 0x00000020 + #define flash_data_spi200_cmd_6 0x00000002 + #define flash_data_spi200_cmd_7 0x0000003b + #define flash_data_spi200_addr 0x00000000 + + #define on_flash_addr_ctrl_base 0x80000000 + #define on_flash_addr_ctrl_auto 0x80000004 + #define on_flash_data_main_erase 0x0000A50D + #define on_flash_data_auto 0xA5 + #define on_flash_data_main_read 0x03 + #define on_flash_data_page_write 0x05 + #define on_flash_data_spp_read 0x10 + #define on_flash_data_sfr_read 0x14 + #define on_flash_addr_ahb_ctrl 0x80000020 + #define on_flash_data_ahb_squit 0x00000001 + #define on_flash_addr_unlock_0 0x00000000 + #define on_flash_addr_unlock_4 0x00000004 + #define on_flash_addr_unlock_8 0x00000008 + #define on_flash_addr_unlock_c 0x0000000C + #define on_flash_data_cmd0 0x28178EA0 + #define on_flash_data_cmd1 0x0A0E03FF + #define on_flash_data_cmd2 0x8C203D0C + #define on_flash_data_cmd3 0x00300263 + #define on_flash_data_lock 0x03400000 +#endif + +#if defined(CORE_SRAM) + #define sram_adr_mkey 0x100070E8 + #define sram_adr_rawdata_addr 0x10000000 + #define sram_adr_rawdata_end 0x00000000 + #define sram_passwrd_start 0x5AA5 + #define sram_passwrd_end 0xA55A + + #define on_sram_adr_rawdata_addr 0x080002E0 + #define on_sram_adr_rawdata_end 0x00000000 + #define on_sram_cmd_conti 0x44332211 + #define on_sram_cmd_fin 0x00000000 + #define on_sram_passwrd_start 0x5AA5 + #define on_sram_passwrd_end 0xA55A +#endif + +#if defined(CORE_DRIVER) + #define driver_addr_fw_define_flash_reload 0x10007f00 + #define driver_addr_fw_define_2nd_flash_reload 0x100072c0 + #define driver_data_fw_define_flash_reload_dis 0x0000a55a + #define driver_data_fw_define_flash_reload_en 0x00000000 + #define driver_addr_fw_define_int_is_edge 0x10007088 + #define driver_addr_fw_define_rxnum_txnum_maxpt 0x100070f4 + #define driver_data_fw_define_rxnum_txnum_maxpt_sorting 0x00000008 + #define driver_data_fw_define_rxnum_txnum_maxpt_normal 0x00000014 + #define driver_addr_fw_define_xy_res_enable 0x100070f8 + #define driver_addr_fw_define_x_y_res 0x100070fc + #define driver_data_df_rx 36 + #define driver_data_df_tx 18 + #define driver_data_df_pt 10 + #define driver_data_df_x_res 1080 + #define driver_data_df_y_res 1920 + #define on_driver_addr_fw_define_int_is_edge 0x10007088 + #define on_driver_data_df_rx 28 + #define on_driver_data_df_tx 14 + #define on_driver_data_df_pt 10 + #define on_driver_data_df_x_res 1080 + #define on_driver_data_df_y_res 1920 +#ifndef HX_NEW_EVENT_STACK_FORMAT + #define on_driver_addr_fw_rx_tx_maxpt_num 0x0800001C + #define on_driver_addr_fw_xy_rev_int_edge 0x0800000C + #define on_driver_addr_fw_define_x_y_res 0x08000030 +#else + #define on_driver_addr_fw_rx_tx_maxpt_num 0x08000004 + #define on_driver_addr_fw_maxpt_bt_num 0x0800000C + #define on_driver_addr_fw_xy_rev_int_edge 0x08000110 + #define on_driver_addr_fw_define_x_y_res 0x08000010 +#endif + +#endif + +#if defined(HX_ZERO_FLASH) + #define zf_addr_dis_flash_reload 0x10007f00 + #define zf_data_dis_flash_reload 0x00009AA9 + #define zf_addr_system_reset 0x90000018 + #define zf_data_system_reset 0x00000055 + #define zf_data_sram_start_addr 0x08000000 + #define zf_data_sram_clean 0x10000000 + #define zf_data_cfg_info 0x10007000 + #define zf_data_fw_cfg_1 0x10007084 + #define zf_data_fw_cfg_2 0x10007264 + #define zf_data_fw_cfg_3 0x10007300 + #define zf_data_adc_cfg_1 0x10006A00 + #define zf_data_adc_cfg_2 0x10007B28 + #define zf_data_adc_cfg_3 0x10007AF0 + #define zf_data_map_table 0x10007500 + #define zf_data_mode_switch 0x10007294 + #define zf_addr_sts_chk 0x900000A8 + #define zf_data_activ_sts 0x05 + #define zf_addr_activ_relod 0x90000048 + #define zf_data_activ_in 0xEC + +#if defined(HX_CODE_OVERLAY) +#if defined(HX83102D) + #define ovl_section_num 3 + #define ovl_gesture_request 0x11 + #define ovl_gesture_reply 0x22 + #define ovl_border_request 0x55 + #define ovl_border_reply 0x66 + #define ovl_sorting_request 0x99 + #define ovl_sorting_reply 0xAA + #define ovl_fault 0xFF +#else + #define ovl_isram_addr 0x20008CE0 + #define ovl_handshaking_addr 0x10007FFC + #define ovl_gesture_request 0x11 + #define ovl_gesture_reply 0x22 + #define ovl_border_request 0x55 + #define ovl_border_reply 0x66 +#endif +#endif + +struct zf_info { + uint8_t sram_addr[4]; + int write_size; + uint32_t fw_addr; + uint32_t cfg_addr; +}; +#endif + +#ifdef HIMAX_PALM_SENSOR_EN + #define palm_detection_register 0x10007FF4 + #define palm_detection_register_enable 0xA55AA55A + #define palm_detection_register_disable 0x00000000 +#endif + +struct ic_operation { + uint8_t addr_ahb_addr_byte_0[1]; + uint8_t addr_ahb_rdata_byte_0[1]; + uint8_t addr_ahb_access_direction[1]; + uint8_t addr_conti[1]; + uint8_t addr_incr4[1]; + uint8_t adr_i2c_psw_lb[1]; + uint8_t adr_i2c_psw_ub[1]; + uint8_t data_ahb_access_direction_read[1]; + uint8_t data_conti[1]; + uint8_t data_incr4[1]; + uint8_t data_i2c_psw_lb[1]; + uint8_t data_i2c_psw_ub[1]; + uint8_t addr_tcon_on_rst[4]; + uint8_t addr_adc_on_rst[4]; + uint8_t addr_psl[4]; + uint8_t addr_cs_central_state[4]; + uint8_t data_rst[4]; + uint8_t adr_osc_en[4]; + uint8_t adr_osc_pw[4]; +}; + +struct fw_operation { + uint8_t addr_system_reset[4]; + uint8_t addr_safe_mode_release_pw[4]; + uint8_t addr_ctrl_fw_isr[4]; + uint8_t addr_flag_reset_event[4]; + uint8_t addr_hsen_enable[4]; + uint8_t addr_smwp_enable[4]; +#ifdef HX_EDGE_LIMIT + uint8_t addr_edge_limit_enable[4]; +#endif +#ifdef HIMAX_PALM_SENSOR_EN + uint8_t addr_palm_detection_enable[4]; +#endif + uint8_t addr_program_reload_from[4]; + uint8_t addr_program_reload_to[4]; + uint8_t addr_program_reload_page_write[4]; + uint8_t addr_raw_out_sel[4]; + uint8_t addr_reload_status[4]; + uint8_t addr_reload_crc32_result[4]; + uint8_t addr_reload_addr_from[4]; + uint8_t addr_reload_addr_cmd_beat[4]; + uint8_t addr_selftest_addr_en[4]; + uint8_t addr_criteria_addr[4]; + uint8_t addr_set_frame_addr[4]; + uint8_t addr_selftest_result_addr[4]; + uint8_t addr_sorting_mode_en[4]; + uint8_t addr_max_dc[4]; + uint8_t addr_fw_mode_status[4]; + uint8_t addr_icid_addr[4]; + uint8_t addr_trigger_addr[4]; + uint8_t addr_fw_ver_addr[4]; + uint8_t addr_fw_cfg_addr[4]; + uint8_t addr_fw_vendor_addr[4]; + uint8_t addr_cus_info[4]; + uint8_t addr_proj_info[4]; + uint8_t addr_fw_state_addr[4]; + uint8_t addr_fw_dbg_msg_addr[4]; + uint8_t addr_chk_fw_status[4]; + uint8_t addr_dd_handshak_addr[4]; + uint8_t addr_dd_data_addr[4]; + uint8_t data_system_reset[4]; + uint8_t data_safe_mode_release_pw_active[4]; + uint8_t data_safe_mode_release_pw_reset[4]; + uint8_t data_clear[4]; + uint8_t data_fw_stop[4]; + uint8_t data_program_reload_start[4]; + uint8_t data_program_reload_compare[4]; + uint8_t data_program_reload_break[4]; + uint8_t data_selftest_request[4]; + uint8_t data_criteria_aa_top[1]; + uint8_t data_criteria_aa_bot[1]; + uint8_t data_criteria_key_top[1]; + uint8_t data_criteria_key_bot[1]; + uint8_t data_criteria_avg_top[1]; + uint8_t data_criteria_avg_bot[1]; + uint8_t data_set_frame[4]; + uint8_t data_selftest_ack_hb[1]; + uint8_t data_selftest_ack_lb[1]; + uint8_t data_selftest_pass[1]; + uint8_t data_normal_cmd[1]; + uint8_t data_normal_status[1]; + uint8_t data_sorting_cmd[1]; + uint8_t data_sorting_status[1]; + uint8_t data_dd_request[1]; + uint8_t data_dd_ack[1]; + uint8_t data_idle_dis_pwd[1]; + uint8_t data_idle_en_pwd[1]; + uint8_t data_rawdata_ready_hb[1]; + uint8_t data_rawdata_ready_lb[1]; + uint8_t addr_ahb_addr[1]; + uint8_t data_ahb_dis[1]; + uint8_t data_ahb_en[1]; + uint8_t addr_event_addr[1]; + uint8_t addr_usb_detect[4]; + uint8_t addr_ulpm_33[1]; + uint8_t addr_ulpm_34[1]; + uint8_t data_ulpm_11[1]; + uint8_t data_ulpm_22[1]; + uint8_t data_ulpm_33[1]; + uint8_t data_ulpm_aa[1]; +}; + +struct flash_operation { + uint8_t addr_spi200_trans_fmt[4]; + uint8_t addr_spi200_trans_ctrl[4]; + uint8_t addr_spi200_cmd[4]; + uint8_t addr_spi200_addr[4]; + uint8_t addr_spi200_data[4]; + uint8_t addr_spi200_bt_num[4]; + + uint8_t data_spi200_trans_fmt[4]; + uint8_t data_spi200_trans_ctrl_1[4]; + uint8_t data_spi200_trans_ctrl_2[4]; + uint8_t data_spi200_trans_ctrl_3[4]; + uint8_t data_spi200_trans_ctrl_4[4]; + uint8_t data_spi200_trans_ctrl_5[4]; + uint8_t data_spi200_cmd_1[4]; + uint8_t data_spi200_cmd_2[4]; + uint8_t data_spi200_cmd_3[4]; + uint8_t data_spi200_cmd_4[4]; + uint8_t data_spi200_cmd_5[4]; + uint8_t data_spi200_cmd_6[4]; + uint8_t data_spi200_cmd_7[4]; + uint8_t data_spi200_addr[4]; +}; + +struct sram_operation { + uint8_t addr_mkey[4]; + uint8_t addr_rawdata_addr[4]; + uint8_t addr_rawdata_end[4]; + uint8_t passwrd_start[2]; + uint8_t passwrd_end[2]; +}; + +struct driver_operation { + uint8_t addr_fw_define_flash_reload[4]; + uint8_t addr_fw_define_2nd_flash_reload[4]; + uint8_t addr_fw_define_int_is_edge[4]; + uint8_t addr_fw_define_rxnum_txnum_maxpt[4]; + uint8_t addr_fw_define_xy_res_enable[4]; + uint8_t addr_fw_define_x_y_res[4]; + uint8_t data_df_rx[1]; + uint8_t data_df_tx[1]; + uint8_t data_df_pt[1]; + uint8_t data_df_x_res[2]; + uint8_t data_df_y_res[2]; + uint8_t data_fw_define_flash_reload_dis[4]; + uint8_t data_fw_define_flash_reload_en[4]; + uint8_t data_fw_define_rxnum_txnum_maxpt_sorting[4]; + uint8_t data_fw_define_rxnum_txnum_maxpt_normal[4]; +}; + +struct zf_operation { + uint8_t addr_dis_flash_reload[4]; + uint8_t data_dis_flash_reload[4]; + uint8_t addr_system_reset[4]; + uint8_t data_system_reset[4]; + uint8_t data_sram_start_addr[4]; + uint8_t data_sram_clean[4]; + uint8_t data_cfg_info[4]; + uint8_t data_fw_cfg_1[4]; + uint8_t data_fw_cfg_2[4]; + uint8_t data_fw_cfg_3[4]; + uint8_t data_adc_cfg_1[4]; + uint8_t data_adc_cfg_2[4]; + uint8_t data_adc_cfg_3[4]; + uint8_t data_map_table[4]; + uint8_t data_mode_switch[4]; + uint8_t addr_sts_chk[4]; + uint8_t data_activ_sts[1]; + uint8_t addr_activ_relod[4]; + uint8_t data_activ_in[1]; +}; + +struct himax_core_command_operation { + struct ic_operation *ic_op; + struct fw_operation *fw_op; + struct flash_operation *flash_op; + struct sram_operation *sram_op; + struct driver_operation *driver_op; + struct zf_operation *zf_op; +}; + +struct on_ic_operation { + uint8_t addr_ahb_addr_byte_0[1]; + uint8_t addr_ahb_rdata_byte_0[1]; + uint8_t addr_ahb_access_direction[1]; + uint8_t addr_conti[1]; + uint8_t addr_incr4[1]; + uint8_t adr_mcu_ctrl[1]; + uint8_t data_ahb_access_direction_read[1]; + uint8_t data_conti[1]; + uint8_t data_incr4[1]; + uint8_t cmd_mcu_on[1]; + uint8_t cmd_mcu_off[1]; + uint8_t adr_sleep_ctrl[1]; + uint8_t cmd_sleep_in[1]; + uint8_t adr_tcon_ctrl[4]; + uint8_t cmd_tcon_on[4]; + uint8_t adr_wdg_ctrl[4]; + uint8_t cmd_wdg_psw[4]; + uint8_t adr_wdg_cnt_ctrl[4]; + uint8_t cmd_wdg_cnt_clr[4]; +}; + +struct on_fw_operation { + uint8_t addr_smwp_enable[1]; + uint8_t addr_program_reload_from[4]; + uint8_t addr_raw_out_sel[1]; + uint8_t addr_flash_checksum[4]; + uint8_t data_flash_checksum[4]; + uint8_t addr_crc_value[4]; + uint8_t addr_reload_status[4]; + uint8_t addr_reload_crc32_result[4]; + uint8_t addr_reload_addr_from[4]; + uint8_t addr_reload_addr_cmd_beat[4]; + uint8_t addr_set_frame_addr[4]; + uint8_t addr_fw_mode_status[1]; + uint8_t addr_icid_addr[4]; + uint8_t addr_trigger_addr[4]; + uint8_t addr_fw_ver_start[1]; + uint8_t data_safe_mode_release_pw_active[4]; + uint8_t data_safe_mode_release_pw_reset[4]; + uint8_t data_clear[4]; + uint8_t addr_criteria_addr[1]; + uint8_t data_selftest_pass[1]; + uint8_t addr_reK_crtl[4]; + uint8_t data_reK_en[1]; + uint8_t data_reK_dis[1]; + uint8_t data_rst_init[1]; + uint8_t data_dc_set[1]; + uint8_t data_bank_set[1]; + uint8_t addr_selftest_addr_en[1]; + uint8_t addr_selftest_result_addr[1]; + uint8_t data_selftest_request[1]; + uint8_t data_thx_avg_mul_dc_lsb[1]; + uint8_t data_thx_avg_mul_dc_msb[1]; + uint8_t data_thx_mul_dc_up_low_bud[1]; + uint8_t data_thx_avg_slf_dc_lsb[1]; + uint8_t data_thx_avg_slf_dc_msb[1]; + uint8_t data_thx_slf_dc_up_low_bud[1]; + uint8_t data_thx_slf_bank_up[1]; + uint8_t data_thx_slf_bank_low[1]; + uint8_t data_idle_dis_pwd[1]; + uint8_t data_idle_en_pwd[1]; + uint8_t data_rawdata_ready_hb[1]; + uint8_t data_rawdata_ready_lb[1]; + uint8_t addr_ahb_addr[1]; + uint8_t data_ahb_dis[1]; + uint8_t data_ahb_en[1]; + uint8_t addr_event_addr[1]; + uint8_t addr_usb_detect[1]; +}; + +struct on_flash_operation { + uint8_t addr_ctrl_base[4]; + uint8_t addr_ctrl_auto[4]; + uint8_t data_main_erase[4]; + uint8_t data_auto[1]; + uint8_t data_main_read[1]; + uint8_t data_page_write[1]; + uint8_t data_sfr_read[1]; + uint8_t data_spp_read[1]; + uint8_t addr_ahb_ctrl[4]; + uint8_t data_ahb_squit[4]; + + uint8_t addr_unlock_0[4]; + uint8_t addr_unlock_4[4]; + uint8_t addr_unlock_8[4]; + uint8_t addr_unlock_c[4]; + uint8_t data_cmd0[4]; + uint8_t data_cmd1[4]; + uint8_t data_cmd2[4]; + uint8_t data_cmd3[4]; + uint8_t data_lock[4]; +}; + +struct on_sram_operation { + uint8_t addr_rawdata_addr[4]; + uint8_t addr_rawdata_end[4]; + uint8_t data_conti[4]; + uint8_t data_fin[4]; + uint8_t passwrd_start[2]; + uint8_t passwrd_end[2]; +}; + +struct on_driver_operation { + uint8_t addr_fw_define_int_is_edge[4]; + uint8_t addr_fw_rx_tx_maxpt_num[4]; +#ifdef HX_NEW_EVENT_STACK_FORMAT + uint8_t addr_fw_maxpt_bt_num[4]; +#endif + uint8_t addr_fw_xy_rev_int_edge[4]; + uint8_t addr_fw_define_x_y_res[4]; + uint8_t data_fw_define_rxnum_txnum_maxpt_sorting[4]; + uint8_t data_fw_define_rxnum_txnum_maxpt_normal[4]; + uint8_t data_df_rx[1]; + uint8_t data_df_tx[1]; + uint8_t data_df_pt[1]; + uint8_t data_df_x_res[2]; + uint8_t data_df_y_res[2]; +}; + +struct himax_on_core_command_operation { + struct on_ic_operation *ic_op; + struct on_fw_operation *fw_op; + struct on_flash_operation *flash_op; + struct on_sram_operation *sram_op; + struct on_driver_operation *driver_op; +}; + +struct himax_chip_detect { + bool (*fp_chip_detect)(void); +}; + +struct himax_chip_entry { + struct himax_chip_detect *core_chip_dt; + uint32_t hx_ic_dt_num; +}; + +struct himax_core_fp { +#ifdef CORE_IC + void (*fp_burst_enable)(uint8_t auto_add_4_byte); + int (*fp_register_read)(uint8_t *read_addr, uint32_t read_length, uint8_t *read_data, uint8_t cfg_flag); + /*int (*fp_flash_write_burst)(uint8_t *reg_byte, uint8_t *write_data);*/ + /*void (*fp_flash_write_burst_lenth)(uint8_t *reg_byte, uint8_t *write_data, uint32_t length);*/ + int (*fp_register_write)(uint8_t *write_addr, uint32_t write_length, uint8_t *write_data, uint8_t cfg_flag); + void (*fp_interface_on)(void); + void (*fp_sense_on)(uint8_t FlashMode); + void (*fp_tcon_on)(void); + bool (*fp_watch_dog_off)(void); + bool (*fp_sense_off)(bool check_en); + void (*fp_sleep_in)(void); + bool (*fp_wait_wip)(int Timing); + void (*fp_init_psl)(void); + void (*fp_resume_ic_action)(void); + void (*fp_suspend_ic_action)(void); + void (*fp_power_on_init)(void); + bool (*fp_dd_clk_set)(bool enable); + void (*fp_dd_reg_en)(bool enable); + bool (*fp_dd_reg_write)(uint8_t addr, uint8_t pa_num, int len, uint8_t *data, uint8_t bank); + bool (*fp_dd_reg_read)(uint8_t addr, uint8_t pa_num, int len, uint8_t *data, uint8_t bank); + bool (*fp_ic_id_read)(void); + bool (*fp_slave_tcon_reset)(void); + bool (*fp_slave_adc_reset_slave)(void); + bool (*fp_slave_wdt_off_slave)(void); +#endif + +#ifdef CORE_FW + void (*fp_parse_raw_data)(struct himax_report_data *hx_touch_data, int mul_num, int self_num, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data); + void (*fp_system_reset)(void); + int (*fp_Calculate_CRC_with_AP)(unsigned char *FW_content, int CRC_from_FW, int len); + uint32_t (*fp_check_CRC)(uint8_t *start_addr, int reload_length); + void (*fp_set_reload_cmd)(uint8_t *write_data, int idx, uint32_t cmd_from, uint32_t cmd_to, uint32_t cmd_beat); + bool (*fp_program_reload)(void); + void (*fp_set_SMWP_enable)(uint8_t SMWP_enable, bool suspended); +#ifdef HX_EDGE_LIMIT + void (*fp_set_edge_limit_enable)(uint8_t edge_limit_enable, bool suspended); +#endif + void (*fp_set_HSEN_enable)(uint8_t HSEN_enable, bool suspended); + void (*fp_diag_register_set)(uint8_t diag_command, uint8_t storage_type); +#ifdef HX_TP_SELF_TEST_DRIVER + void (*fp_control_reK)(bool enable); +#endif + int (*fp_chip_self_test)(void); + void (*fp_idle_mode)(int disable); + void (*fp_reload_disable)(int disable); + bool (*fp_check_chip_version)(void); + int (*fp_read_ic_trigger_type)(void); + int (*fp_read_i2c_status)(void); + void (*fp_read_FW_ver)(void); + bool (*fp_read_event_stack)(uint8_t *buf, uint8_t length); + void (*fp_return_event_stack)(void); + bool (*fp_calculateChecksum)(bool change_iref, uint32_t size); + int (*fp_read_FW_status)(uint8_t *state_addr, uint8_t *tmp_addr); + void (*fp_irq_switch)(int switch_on); + int (*fp_assign_sorting_mode)(uint8_t *tmp_data); + int (*fp_check_sorting_mode)(uint8_t *tmp_data); + int (*fp_switch_mode)(int mode); + int (*fp_get_max_dc)(void); + uint8_t (*fp_read_DD_status)(uint8_t *cmd_set, uint8_t *tmp_data); + int (*fp_ulpm_in)(void); + int (*fp_black_gest_ctrl)(bool enable); + int (*_diff_overlay_bin)(void); +#endif + +#ifdef CORE_FLASH + void (*fp_chip_erase)(void); + bool (*fp_block_erase)(int start_addr, int length); + bool (*fp_sector_erase)(int start_addr); + void (*fp_flash_programming)(uint8_t *FW_content, int FW_Size); + void (*fp_flash_page_write)(uint8_t *write_addr, int length, uint8_t *write_data); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_32k)(unsigned char *fw, int len, bool change_iref); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_60k)(unsigned char *fw, int len, bool change_iref); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_64k)(unsigned char *fw, int len, bool change_iref); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_124k)(unsigned char *fw, int len, bool change_iref); + int (*fp_fts_ctpm_fw_upgrade_with_sys_fs_128k)(unsigned char *fw, int len, bool change_iref); + void (*fp_flash_dump_func)(uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer); + bool (*fp_flash_lastdata_check)(uint32_t size); + bool (*fp_ahb_squit)(void); + void (*fp_flash_read)(uint8_t *r_data, int start_addr, int length); + bool (*fp_sfr_rw)(uint8_t *addr, int length, uint8_t *data, uint8_t rw_ctrl); + bool (*fp_lock_flash)(void); + bool (*fp_unlock_flash)(void); + void (*fp_init_auto_func)(void); + int (*_diff_overlay_flash)(void); +#endif + +#ifdef CORE_SRAM + void (*fp_sram_write)(uint8_t *FW_content); + bool (*fp_sram_verify)(uint8_t *FW_File, int FW_Size); + bool (*fp_get_DSRAM_data)(uint8_t *info_data, bool DSRAM_Flag); +#endif + +#ifdef CORE_DRIVER + void (*fp_chip_init)(void); +#ifdef HX_AUTO_UPDATE_FW + int (*fp_fw_ver_bin)(void); +#endif + void (*fp_pin_reset)(void); + void (*fp_touch_information)(void); + void (*fp_reload_config)(void); + int (*fp_get_touch_data_size)(void); + void (*fp_usb_detect_set)(uint8_t *cable_config); + int (*fp_hand_shaking)(void); + int (*fp_determin_diag_rawdata)(int diag_command); + int (*fp_determin_diag_storage)(int diag_command); + int (*fp_cal_data_len)(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max); + bool (*fp_diag_check_sum)(struct himax_report_data *hx_touch_data); + void (*fp_diag_parse_raw_data)(struct himax_report_data *hx_touch_data, int mul_num, int self_num, uint8_t diag_cmd, int32_t *mutual_data, int32_t *self_data); + void (*fp_ic_reset)(uint8_t loadconfig, uint8_t int_off); + int (*fp_ic_esd_recovery)(int hx_esd_event, int hx_zero_event, int length); + void (*fp_esd_ic_reset)(void); + void (*fp_resend_cmd_func)(bool suspended); +#ifdef HX_TP_PROC_GUEST_INFO + int (*guest_info_get_status)(void); + int (*read_guest_info)(void); +#endif +#endif +#ifdef HX_ZERO_FLASH + void (*fp_clean_sram_0f)(uint8_t *addr, int write_len, int type); + void (*fp_write_sram_0f)(const struct firmware *fw_entry, uint8_t *addr, int start_index, uint32_t write_len); + int (*fp_write_sram_0f_crc)(const struct firmware *fw_entry, uint8_t *addr, int start_index, uint32_t write_len); + void (*fp_firmware_update_0f)(const struct firmware *fw_entry); + int (*fp_0f_operation_dirly)(void); + int (*fp_0f_op_file_dirly)(char *file_name); + void (*fp_0f_operation)(struct work_struct *work); + int (*fp_0f_esd_check)(void); +#if defined(HX83102D) + void (*fp_0f_reload_to_active)(void); +#endif +#ifdef HX_0F_DEBUG + void (*fp_read_sram_0f)(const struct firmware *fw_entry, uint8_t *addr, int start_index, int read_len); + void (*fp_read_all_sram)(uint8_t *addr, int read_len); + void (*fp_firmware_read_0f)(const struct firmware *fw_entry, int type); + void (*fp_0f_operation_check)(int type); +#endif +#ifdef HX_CODE_OVERLAY + int (*fp_0f_overlay)(int ovl_type, int mode); +#endif +#ifdef HIMAX_PALM_SENSOR_EN + int (*fp_palm_detection_function)(int mode); +#endif +#endif +}; + +#endif diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_ic_incell_core.c b/drivers/input/touchscreen/himax_v3_mmi/himax_ic_incell_core.c old mode 100644 new mode 100755 index 1465ffe67811..40a0e6c2f525 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_ic_incell_core.c +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_ic_incell_core.c @@ -1,4731 +1,4069 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for incell ic core functions - * - * 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_ic_core.h" - -struct himax_core_command_operation *g_core_cmd_op; -struct ic_operation *pic_op; -EXPORT_SYMBOL(pic_op); - -struct fw_operation *pfw_op; -EXPORT_SYMBOL(pfw_op); - -struct flash_operation *pflash_op; -EXPORT_SYMBOL(pflash_op); - -struct sram_operation *psram_op; -struct driver_operation *pdriver_op; -EXPORT_SYMBOL(pdriver_op); - -#if defined(HX_ZERO_FLASH) -struct zf_operation *pzf_op; -EXPORT_SYMBOL(pzf_op); -#if defined(HX_CODE_OVERLAY) -uint8_t *ovl_idx; -EXPORT_SYMBOL(ovl_idx); -#endif -#endif - -void (*himax_mcu_cmd_struct_free)(void); -static uint8_t *g_internal_buffer; - -/* CORE_IC */ -/* IC side start*/ -static void himax_mcu_burst_enable(uint8_t auto_add_4_byte) -{ - uint8_t tmp_data[DATA_LEN_4]; - int ret; - - /*I("%s,Entering\n", __func__);*/ - tmp_data[0] = pic_op->data_conti[0]; - - ret = himax_bus_write(pic_op->addr_conti[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } - - tmp_data[0] = (pic_op->data_incr4[0] | auto_add_4_byte); - - ret = himax_bus_write(pic_op->addr_incr4[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } -} - -static int himax_mcu_register_read(uint8_t *read_addr, uint32_t read_length, - uint8_t *read_data, uint8_t cfg_flag) -{ - uint8_t tmp_data[DATA_LEN_4]; - int i = 0; - int address = 0; - int ret = 0; - - /*I("%s,Entering\n",__func__);*/ - - if (cfg_flag == false) { - if (read_length > FLASH_RW_MAX_LEN) { - E("%s: read len over %d!\n", __func__, - FLASH_RW_MAX_LEN); - return LENGTH_FAIL; - } - - if (read_length > DATA_LEN_4) - g_core_fp.fp_burst_enable(1); - else - g_core_fp.fp_burst_enable(0); - - address = (read_addr[3] << 24) - + (read_addr[2] << 16) - + (read_addr[1] << 8) - + read_addr[0]; - i = address; - tmp_data[0] = (uint8_t)i; - tmp_data[1] = (uint8_t)(i >> 8); - tmp_data[2] = (uint8_t)(i >> 16); - tmp_data[3] = (uint8_t)(i >> 24); - - ret = himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], - tmp_data, DATA_LEN_4, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - - tmp_data[0] = pic_op->data_ahb_access_direction_read[0]; - - ret = himax_bus_write(pic_op->addr_ahb_access_direction[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - - ret = himax_bus_read(pic_op->addr_ahb_rdata_byte_0[0], - read_data, - read_length, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - - if (read_length > DATA_LEN_4) - g_core_fp.fp_burst_enable(0); - - } else { - ret = himax_bus_read(read_addr[0], read_data, read_length, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - } - return NO_ERR; -} - -static int himax_mcu_flash_write_burst_lenth(uint8_t *reg_byte, - uint8_t *write_data, uint32_t length) -{ - uint8_t *data_byte; - int ret = 0; - - if (!g_internal_buffer) { - E("%s: internal buffer not initialized!\n", __func__); - return MEM_ALLOC_FAIL; - } - data_byte = g_internal_buffer; - - /* assign addr 4bytes */ - memcpy(data_byte, reg_byte, ADDR_LEN_4); - /* assign data n bytes */ - memcpy(data_byte + ADDR_LEN_4, write_data, length); - - ret = himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], data_byte, - length + ADDR_LEN_4, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: xfer fail!\n", __func__); - return I2C_FAIL; - } - - return NO_ERR; -} - -static int himax_mcu_register_write(uint8_t *write_addr, uint32_t write_length, - uint8_t *write_data, uint8_t cfg_flag) -{ - int address; - uint8_t tmp_addr[4]; - uint8_t *tmp_data; - int total_read_times = 0; - uint32_t max_bus_size = MAX_I2C_TRANS_SZ; - uint32_t total_size_temp = 0; - int i = 0; - int ret = 0; - - /*I("%s,Entering\n", __func__);*/ - if (cfg_flag == 0) { - total_size_temp = write_length; -#if defined(HX_ZERO_FLASH) - max_bus_size = (write_length > HX_MAX_WRITE_SZ - 4) - ? (HX_MAX_WRITE_SZ - 4) - : write_length; -#endif - - tmp_addr[3] = write_addr[3]; - tmp_addr[2] = write_addr[2]; - tmp_addr[1] = write_addr[1]; - tmp_addr[0] = write_addr[0]; - - if (total_size_temp % max_bus_size == 0) - total_read_times = total_size_temp / max_bus_size; - else - total_read_times = total_size_temp / max_bus_size + 1; - - if (write_length > DATA_LEN_4) - g_core_fp.fp_burst_enable(1); - else - g_core_fp.fp_burst_enable(0); - - for (i = 0; i < (total_read_times); i++) { - /* I("[log]write %d time start!\n", i); - * I("[log]addr[3]=0x%02X, addr[2]=0x%02X, - addr[1]=0x%02X, addr[0]=0x%02X!\n", - tmp_addr[3], tmp_addr[2], - tmp_addr[1], tmp_addr[0]); - * I("%s, write addr = 0x%02X%02X%02X%02X\n", - __func__, tmp_addr[3], tmp_addr[2], - tmp_addr[1], tmp_addr[0]); - */ - - if (total_size_temp >= max_bus_size) { - tmp_data = write_data+(i * max_bus_size); - - ret = himax_mcu_flash_write_burst_lenth( - tmp_addr, - tmp_data, - max_bus_size); - if (ret < 0) { - I("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - total_size_temp = total_size_temp - - max_bus_size; - } else { - tmp_data = write_data+(i * max_bus_size); - /* I("last total_size_temp=%d\n", - * total_size_temp % max_bus_size); - */ - ret = himax_mcu_flash_write_burst_lenth( - tmp_addr, - tmp_data, - total_size_temp); - if (ret < 0) { - I("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - } - - /*I("[log]write %d time end!\n", i);*/ - address = ((i+1) * max_bus_size); - tmp_addr[0] = write_addr[0] - + (uint8_t) ((address) & 0x00FF); - - if (tmp_addr[0] < write_addr[0]) - tmp_addr[1] = write_addr[1] - + (uint8_t) ((address>>8) & 0x00FF) - + 1; - else - tmp_addr[1] = write_addr[1] - + (uint8_t) ((address>>8) & 0x00FF); - - udelay(100); - } - } else if (cfg_flag == 1) { - ret = himax_bus_write(write_addr[0], write_data, write_length, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - } else - E("%s: cfg_flag = %d, value is wrong!\n", __func__, cfg_flag); - - return NO_ERR; -} - -static int himax_write_read_reg(uint8_t *tmp_addr, uint8_t *tmp_data, - uint8_t hb, uint8_t lb) -{ - int cnt = 0; - - do { - g_core_fp.fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, 0); - usleep_range(10000, 11000); - g_core_fp.fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); - /* I("%s:Now tmp_data[0]=0x%02X,[1]=0x%02X, - * [2]=0x%02X,[3]=0x%02X\n", - * __func__, tmp_data[0], - * tmp_data[1], tmp_data[2], tmp_data[3]); - */ - } while ((tmp_data[1] != hb && tmp_data[0] != lb) && cnt++ < 100); - - if (cnt >= 100) - return HX_RW_REG_FAIL; - - I("Now register 0x%08X : high byte=0x%02X,low byte=0x%02X\n", - tmp_addr[3], tmp_data[1], tmp_data[0]); - return NO_ERR; -} - -static void himax_mcu_interface_on(void) -{ - uint8_t tmp_data[DATA_LEN_4]; - uint8_t tmp_data2[DATA_LEN_4]; - int cnt = 0; - int ret = 0; - - /* Read a dummy register to wake up I2C.*/ - ret = himax_bus_read(pic_op->addr_ahb_rdata_byte_0[0], tmp_data, - DATA_LEN_4, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) {/* to knock I2C*/ - E("%s: i2c access fail!\n", __func__); - return; - } - - do { - tmp_data[0] = pic_op->data_conti[0]; - - ret = himax_bus_write(pic_op->addr_conti[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } - - tmp_data[0] = pic_op->data_incr4[0]; - - ret = himax_bus_write(pic_op->addr_incr4[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } - - /*Check cmd*/ - himax_bus_read(pic_op->addr_conti[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - himax_bus_read(pic_op->addr_incr4[0], tmp_data2, 1, - HIMAX_I2C_RETRY_TIMES); - - if (tmp_data[0] == pic_op->data_conti[0] - && tmp_data2[0] == pic_op->data_incr4[0]) - break; - - usleep_range(1000, 1100); - } while (++cnt < 10); - - if (cnt > 0) - I("%s:Polling burst mode: %d times\n", __func__, cnt); -} - -#define WIP_PRT_LOG "%s: retry:%d, bf[0]=%d, bf[1]=%d,bf[2]=%d, bf[3]=%d\n" -static bool himax_mcu_wait_wip(int Timing) -{ - uint8_t tmp_data[DATA_LEN_4]; - int retry_cnt = 0; - - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_fmt, - DATA_LEN_4, pflash_op->data_spi200_trans_fmt, 0); - tmp_data[0] = 0x01; - - do { - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, - DATA_LEN_4, - pflash_op->data_spi200_trans_ctrl_1, - 0); - - g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, - DATA_LEN_4, pflash_op->data_spi200_cmd_1, 0); - tmp_data[0] = tmp_data[1] = tmp_data[2] = tmp_data[3] = 0xFF; - g_core_fp.fp_register_read(pflash_op->addr_spi200_data, 4, - tmp_data, 0); - - if ((tmp_data[0] & 0x01) == 0x00) - return true; - - retry_cnt++; - - if (tmp_data[0] != 0x00 - || tmp_data[1] != 0x00 - || tmp_data[2] != 0x00 - || tmp_data[3] != 0x00) - I(WIP_PRT_LOG, - __func__, retry_cnt, tmp_data[0], - tmp_data[1], tmp_data[2], tmp_data[3]); - - if (retry_cnt > 100) { - E("%s: Wait wip error!\n", __func__); - return false; - } - - msleep(Timing); - } while ((tmp_data[0] & 0x01) == 0x01); - - return true; -} - -static void himax_mcu_sense_on(uint8_t FlashMode) -{ - uint8_t tmp_data[DATA_LEN_4]; - int retry = 0; - int ret = 0; - - I("Enter %s\n", __func__); - g_core_fp.fp_interface_on(); - g_core_fp.fp_register_write(pfw_op->addr_ctrl_fw_isr, - sizeof(pfw_op->data_clear), pfw_op->data_clear, 0); - /*msleep(20);*/ - usleep_range(10000, 11000); - if (!FlashMode) { -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(false, false); -#else - g_core_fp.fp_system_reset(); -#endif - } else { - do { - g_core_fp.fp_register_write( - pfw_op->addr_safe_mode_release_pw, - sizeof(pfw_op-> - data_safe_mode_release_pw_active), - pfw_op->data_safe_mode_release_pw_active, - 0); - - g_core_fp.fp_register_read( - pfw_op->addr_flag_reset_event, - DATA_LEN_4, - tmp_data, - 0); - I("%s:Read status from IC = %X,%X\n", __func__, - tmp_data[0], tmp_data[1]); - } while ((tmp_data[1] != 0x01 - || tmp_data[0] != 0x00) - && retry++ < 5); - - if (retry >= 5) { - E("%s: Fail:\n", __func__); -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(false, false); -#else - g_core_fp.fp_system_reset(); -#endif - } else { - I("%s:OK and Read status from IC = %X,%X\n", - __func__, tmp_data[0], tmp_data[1]); - /* reset code*/ - tmp_data[0] = 0x00; - - ret = himax_bus_write(pic_op->adr_i2c_psw_lb[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) - E("%s: i2c access fail!\n", __func__); - - ret = himax_bus_write(pic_op->adr_i2c_psw_ub[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) - E("%s: i2c access fail!\n", __func__); - - g_core_fp.fp_register_write( - pfw_op->addr_safe_mode_release_pw, - sizeof(pfw_op->data_safe_mode_release_pw_reset), - pfw_op->data_safe_mode_release_pw_reset, - 0); - } - } -} - -static bool himax_mcu_sense_off(bool check_en) -{ - uint8_t cnt = 0; - uint8_t tmp_data[DATA_LEN_4]; - int ret = 0; - - do { - tmp_data[0] = pic_op->data_i2c_psw_lb[0]; - - ret = himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - tmp_data[0] = pic_op->data_i2c_psw_ub[0]; - - ret = himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - g_core_fp.fp_register_read(pic_op->addr_cs_central_state, - ADDR_LEN_4, tmp_data, 0); - I("%s: Check enter_save_mode data[0]=%X\n", __func__, - tmp_data[0]); - - if (tmp_data[0] == 0x0C) { - g_core_fp.fp_register_write(pic_op->addr_tcon_on_rst, - DATA_LEN_4, pic_op->data_rst, 0); - usleep_range(1000, 1100); - tmp_data[3] = pic_op->data_rst[3]; - tmp_data[2] = pic_op->data_rst[2]; - tmp_data[1] = pic_op->data_rst[1]; - tmp_data[0] = pic_op->data_rst[0] | 0x01; - g_core_fp.fp_register_write(pic_op->addr_tcon_on_rst, - DATA_LEN_4, tmp_data, 0); - - g_core_fp.fp_register_write(pic_op->addr_adc_on_rst, - DATA_LEN_4, pic_op->data_rst, 0); - usleep_range(1000, 1100); - tmp_data[3] = pic_op->data_rst[3]; - tmp_data[2] = pic_op->data_rst[2]; - tmp_data[1] = pic_op->data_rst[1]; - tmp_data[0] = pic_op->data_rst[0] | 0x01; - g_core_fp.fp_register_write(pic_op->addr_adc_on_rst, - DATA_LEN_4, tmp_data, 0); - goto TRUE_END; - } else { - /*msleep(10);*/ -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(false, false); -#else - g_core_fp.fp_system_reset(); -#endif - } - } while (cnt++ < 15); - - return false; -TRUE_END: - return true; -} - -/*power saving level*/ -static void himax_mcu_init_psl(void) -{ - g_core_fp.fp_register_write(pic_op->addr_psl, - sizeof(pic_op->data_rst), - pic_op->data_rst, 0); - I("%s: power saving level reset OK!\n", __func__); -} - -static void himax_mcu_resume_ic_action(void) -{ - /* Nothing to do */ -} - -static void himax_mcu_suspend_ic_action(void) -{ - /* Nothing to do */ -} - -static void himax_mcu_power_on_init(void) -{ - I("%s:\n", __func__); - g_core_fp.fp_touch_information(); - /*RawOut select initial*/ - g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, - sizeof(pfw_op->data_clear), - pfw_op->data_clear, 0); - /*DSRAM func initial*/ - g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear); - g_core_fp.fp_sense_on(0x00); -} - -static bool himax_mcu_dd_clk_set(bool enable) -{ - uint8_t data[4] = {0}; - - data[0] = (enable)?1:0; - return (g_core_fp.fp_register_write(pic_op->adr_osc_en, - sizeof(pic_op->adr_osc_en), data, 0) == NO_ERR); -} - -static void himax_mcu_dd_reg_en(bool enable) -{ - uint8_t data[4] = {0}; - - g_core_fp.fp_dd_reg_read(0xCB, 8, 1, data, 0); - - if (data[0] != 0x44) { /*need DD Touch PW*/ - data[0] = 0xA5; data[1] = 0x00; - data[2] = 0x00; data[3] = 0x00; - g_core_fp.fp_register_write(pic_op->adr_osc_pw, - DATA_LEN_4, data, 0); - data[0] = 0x00; data[1] = 0x55; - data[2] = 0xAA; data[3] = 0x00; - g_core_fp.fp_dd_reg_write(0xEB, 0, 4, data, 0); - } - - data[0] = 0x00; data[1] = 0x83; - data[2] = 0x11; data[3] = 0x2A; - g_core_fp.fp_dd_reg_write(0xB9, 0, 4, data, 0); -} - -static bool himax_mcu_dd_reg_write(uint8_t addr, uint8_t pa_num, - int len, uint8_t *data, uint8_t bank) -{ - /*Calculate total write length*/ - uint32_t data_len = (((len + pa_num - 1) / 4 - pa_num / 4) + 1) * 4; -// uint8_t w_data[data_len]; - uint8_t *w_data = NULL; - uint8_t tmp_addr[4] = {0}; - uint8_t tmp_data[4] = {0}; -// bool chk_data[data_len]; - bool *chk_data = NULL; - uint32_t chk_idx = 0; - int i = 0; - int ret = -1; - - w_data = kcalloc(data_len, sizeof(uint8_t), GFP_KERNEL); - if (w_data == NULL) { - E("%s, Failed to allocate memory\n", __func__); - } - - chk_data = kcalloc(data_len, sizeof(bool), GFP_KERNEL); - if (chk_data == NULL) { - E("%s, Failed to allocate memory\n", __func__); - } - if (!w_data || !chk_data) - goto alloc_error; -// memset(w_data, 0, data_len * sizeof(uint8_t)); -// memset(chk_data, 0, data_len * sizeof(bool)); - - /*put input data*/ - chk_idx = pa_num % 4; - for (i = 0; i < len; i++) { - w_data[chk_idx] = data[i]; - chk_data[chk_idx++] = true; - } - - /*get original data*/ - chk_idx = (pa_num / 4) * 4; - for (i = 0; i < data_len; i++) { - if (!chk_data[i]) { - g_core_fp.fp_dd_reg_read(addr, - (uint8_t)(chk_idx + i), - 1, - tmp_data, - bank); - - w_data[i] = tmp_data[0]; - chk_data[i] = true; - } - D("%s w_data[%d] = %2X\n", __func__, i, w_data[i]); - } - - tmp_addr[3] = 0x30; - tmp_addr[2] = addr >> 4; - tmp_addr[1] = (addr << 4) | (bank * 4); - tmp_addr[0] = chk_idx; - D("%s Addr = %02X%02X%02X%02X.\n", __func__, - tmp_addr[3], tmp_addr[2], - tmp_addr[1], tmp_addr[0]); - - ret = g_core_fp.fp_register_write(tmp_addr, data_len, w_data, 0); -alloc_error: - if (chk_data) - kfree(chk_data); - if (w_data) - kfree(w_data); - - return (ret == NO_ERR); -} - -static bool himax_mcu_dd_reg_read(uint8_t addr, uint8_t pa_num, int len, - uint8_t *data, uint8_t bank) -{ - uint8_t tmp_addr[4] = {0}; - uint8_t tmp_data[4] = {0}; - int i = 0; - - for (i = 0; i < len; i++) { - tmp_addr[3] = 0x30; - tmp_addr[2] = addr >> 4; - tmp_addr[1] = (addr << 4) | (bank * 4); - tmp_addr[0] = pa_num + i; - - if (g_core_fp.fp_register_read(tmp_addr, - DATA_LEN_4, tmp_data, 0)) - goto READ_FAIL; - - data[i] = tmp_data[0]; - - D("%s Addr = %02X%02X%02X%02X.data = %2X\n", __func__, - tmp_addr[3], - tmp_addr[2], - tmp_addr[1], - tmp_addr[0], - data[i]); - } - return true; - -READ_FAIL: - E("%s Read DD reg Failed.\n", __func__); - return false; -} - -static bool himax_mcu_ic_id_read(void) -{ - int i = 0; - uint8_t data[4] = {0}; - - g_core_fp.fp_dd_clk_set(true); - g_core_fp.fp_dd_reg_en(true); - - for (i = 0; i < 13; i++) { - data[0] = 0x28 + i; - g_core_fp.fp_dd_reg_write(0xBB, 2, 1, data, 0); - data[0] = 0x80; - g_core_fp.fp_dd_reg_write(0xBB, 4, 1, data, 0); - data[0] = 0x00; - g_core_fp.fp_dd_reg_write(0xBB, 4, 1, data, 0); - g_core_fp.fp_dd_reg_read(0xBB, 5, 1, data, 0); - ic_data->vendor_ic_id[i] = data[0]; - I("ic_data->vendor_ic_id[%d] = %02X\n", i, - ic_data->vendor_ic_id[i]); - } - - g_core_fp.fp_dd_clk_set(false); - - return true; -} - -/* IC side end*/ -/* CORE_IC */ - -/* CORE_FW */ -/* FW side start*/ -static void diag_mcu_parse_raw_data(struct himax_report_data *hx_touch_data, - int mul_num, int self_num, uint8_t diag_cmd, - int32_t *mutual_data, int32_t *self_data) -{ - int RawDataLen_word; - int index = 0; - int temp1, temp2, i; - - if (hx_touch_data->hx_rawdata_buf[0] - == pfw_op->data_rawdata_ready_lb[0] - && hx_touch_data->hx_rawdata_buf[1] - == pfw_op->data_rawdata_ready_hb[0] - && hx_touch_data->hx_rawdata_buf[2] > 0 - && hx_touch_data->hx_rawdata_buf[3] == diag_cmd) { - RawDataLen_word = hx_touch_data->rawdata_size / 2; - index = (hx_touch_data->hx_rawdata_buf[2] - 1) - * RawDataLen_word; - - /* I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n",index, - * buf[56], buf[57], buf[58], buf[59], mul_num, self_num); - * I("RawDataLen=%d , RawDataLen_word=%d , - * hx_touch_info_size=%d\n", - * RawDataLen, RawDataLen_word, hx_touch_info_size); - */ - for (i = 0; i < RawDataLen_word; i++) { - temp1 = index + i; - - if (temp1 < mul_num) { /*mutual*/ - mutual_data[index + i] = - ((int8_t)hx_touch_data-> - hx_rawdata_buf[i * 2 + 4 + 1]) * 256 - + hx_touch_data-> - hx_rawdata_buf[i * 2 + 4]; - } else { /*self*/ - temp1 = i + index; - temp2 = self_num + mul_num; - - if (temp1 >= temp2) - break; - - self_data[i + index - mul_num] = - (((int8_t)hx_touch_data-> - hx_rawdata_buf[i * 2 + 4 + 1]) << 8) - + hx_touch_data-> - hx_rawdata_buf[i * 2 + 4]; - } - } - } -} - -static void himax_mcu_system_reset(void) -{ - int ret = 0; -#if defined(HX_PON_PIN_SUPPORT) - g_core_fp.fp_register_write(pfw_op->addr_system_reset, - sizeof(pfw_op->data_system_reset), - pfw_op->data_system_reset, - 0); -#else - uint8_t tmp_data[DATA_LEN_4]; - int retry = 0; - - g_core_fp.fp_interface_on(); - g_core_fp.fp_register_write(pfw_op->addr_ctrl_fw_isr, - sizeof(pfw_op->data_clear), - pfw_op->data_clear, - 0); - do { - /* reset code*/ - /** - * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 - */ - tmp_data[0] = pic_op->data_i2c_psw_lb[0]; - - ret = himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) - E("%s: i2c access fail!\n", __func__); - - /** - * I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 - */ - tmp_data[0] = pic_op->data_i2c_psw_ub[0]; - - ret = himax_bus_write(pic_op->adr_i2c_psw_ub[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) - E("%s: i2c access fail!\n", __func__); - - /** - * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x00 - */ - tmp_data[0] = 0x00; - - ret = himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) - E("%s: i2c access fail!\n", __func__); - - usleep_range(10000, 11000); - - g_core_fp.fp_register_read(pfw_op->addr_flag_reset_event, - DATA_LEN_4, tmp_data, 0); - I("%s:Read status from IC = %X,%X\n", __func__, - tmp_data[0], tmp_data[1]); - } while ((tmp_data[1] != 0x02 || tmp_data[0] != 0x00) && retry++ < 5); -#endif -} - -static int himax_mcu_Calculate_CRC_with_AP(unsigned char *FW_content, - int CRC_from_FW, int len) -{ - int i, j, length = 0; - int fw_data; - int fw_data_2; - int CRC = 0xFFFFFFFF; - int PolyNomial = 0x82F63B78; - - length = len / 4; - - for (i = 0; i < length; i++) { - fw_data = FW_content[i * 4]; - - for (j = 1; j < 4; j++) { - fw_data_2 = FW_content[i * 4 + j]; - fw_data += (fw_data_2) << (8 * j); - } - CRC = fw_data ^ CRC; - for (j = 0; j < 32; j++) { - if ((CRC % 2) != 0) - CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial; - else - CRC = (((CRC >> 1) & 0x7FFFFFFF)); - } - } - - return CRC; -} - -static uint32_t himax_mcu_check_CRC(uint8_t *start_addr, int reload_length) -{ - uint32_t result = 0; - uint8_t tmp_data[DATA_LEN_4]; - int cnt = 0, ret = 0; - int length = reload_length / DATA_LEN_4; - - ret = g_core_fp.fp_register_write(pfw_op->addr_reload_addr_from, - DATA_LEN_4, start_addr, 0); - if (ret < NO_ERR) { - E("%s: i2c access fail!\n", __func__); - return HW_CRC_FAIL; - } - - tmp_data[3] = 0x00; - tmp_data[2] = 0x99; - tmp_data[1] = (length >> 8); - tmp_data[0] = length; - ret = g_core_fp.fp_register_write(pfw_op->addr_reload_addr_cmd_beat, - DATA_LEN_4, tmp_data, 0); - if (ret < NO_ERR) { - E("%s: i2c access fail!\n", __func__); - return HW_CRC_FAIL; - } - cnt = 0; - - do { - ret = g_core_fp.fp_register_read(pfw_op->addr_reload_status, - DATA_LEN_4, tmp_data, 0); - if (ret < NO_ERR) { - E("%s: i2c access fail!\n", __func__); - return HW_CRC_FAIL; - } - - if ((tmp_data[0] & 0x01) != 0x01) { - ret = g_core_fp.fp_register_read( - pfw_op->addr_reload_crc32_result, - DATA_LEN_4, - tmp_data, - 0); - if (ret < NO_ERR) { - E("%s: i2c access fail!\n", __func__); - return HW_CRC_FAIL; - } - I("%s:data[3]=%X,data[2]=%X,data[1]=%X,data[0]=%X\n", - __func__, - tmp_data[3], - tmp_data[2], - tmp_data[1], - tmp_data[0]); - result = ((tmp_data[3] << 24) - + (tmp_data[2] << 16) - + (tmp_data[1] << 8) - + tmp_data[0]); - goto END; - } else { - I("Waiting for HW ready!\n"); - usleep_range(1000, 1100); - } - - } while (cnt++ < 100); -END: - return result; -} - -static void himax_mcu_set_reload_cmd(uint8_t *write_data, int idx, - uint32_t cmd_from, uint32_t cmd_to, uint32_t cmd_beat) -{ - int index = idx * 12; - int i; - - for (i = 3; i >= 0; i--) { - write_data[index + i] = (cmd_from >> (8 * i)); - write_data[index + 4 + i] = (cmd_to >> (8 * i)); - write_data[index + 8 + i] = (cmd_beat >> (8 * i)); - } -} - -static bool himax_mcu_program_reload(void) -{ - return true; -} - -#if defined(HX_ULTRA_LOW_POWER) -static int himax_mcu_ulpm_in(void) -{ - uint8_t tmp_data[4]; - int rtimes = 0; - int ret = 0; - - I("%s:entering\n", __func__); - - /* 34 -> 11 */ - do { - if (rtimes > 10) { - I("%s:1/7 retry over 10 times!\n", __func__); - return false; - } - ret = himax_bus_write(pfw_op->addr_ulpm_34[0], - pfw_op->data_ulpm_11, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi write fail!\n", __func__); - continue; - } - ret = himax_bus_read(pfw_op->addr_ulpm_34[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi read fail!\n", __func__); - continue; - } - - I("%s:retry times %d,addr=0x34,correct 0x11=current 0x%2.2X\n", - __func__, rtimes, tmp_data[0]); - rtimes++; - } while (tmp_data[0] != pfw_op->data_ulpm_11[0]); - - rtimes = 0; - /* 34 -> 11 */ - do { - if (rtimes > 10) { - I("%s:2/7 retry over 10 times!\n", __func__); - return false; - } - ret = himax_bus_write(pfw_op->addr_ulpm_34[0], - pfw_op->data_ulpm_11, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi write fail!\n", __func__); - continue; - } - ret = himax_bus_read(pfw_op->addr_ulpm_34[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi read fail!\n", __func__); - continue; - } - - I("%s:retry times %d,addr=0x34,correct 0x11=current 0x%2.2X\n", - __func__, rtimes, tmp_data[0]); - rtimes++; - } while (tmp_data[0] != pfw_op->data_ulpm_11[0]); - - /* 33 -> 33 */ - rtimes = 0; - do { - if (rtimes > 10) { - I("%s:3/7 retry over 10 times!\n", __func__); - return false; - } - ret = himax_bus_write(pfw_op->addr_ulpm_33[0], - pfw_op->data_ulpm_33, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi write fail!\n", __func__); - continue; - } - ret = himax_bus_read(pfw_op->addr_ulpm_33[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi read fail!\n", __func__); - continue; - } - - I("%s:retry times %d,addr=0x33,correct 0x33=current 0x%2.2X\n", - __func__, rtimes, tmp_data[0]); - rtimes++; - } while (tmp_data[0] != pfw_op->data_ulpm_33[0]); - - /* 34 -> 22 */ - rtimes = 0; - do { - if (rtimes > 10) { - I("%s:4/7 retry over 10 times!\n", __func__); - return false; - } - ret = himax_bus_write(pfw_op->addr_ulpm_34[0], - pfw_op->data_ulpm_22, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi write fail!\n", __func__); - continue; - } - ret = himax_bus_read(pfw_op->addr_ulpm_34[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi read fail!\n", __func__); - continue; - } - - I("%s:retry times %d,addr=0x34,correct 0x22=current 0x%2.2X\n", - __func__, rtimes, tmp_data[0]); - rtimes++; - } while (tmp_data[0] != pfw_op->data_ulpm_22[0]); - - /* 33 -> AA */ - rtimes = 0; - do { - if (rtimes > 10) { - I("%s:5/7 retry over 10 times!\n", __func__); - return false; - } - ret = himax_bus_write(pfw_op->addr_ulpm_33[0], - pfw_op->data_ulpm_aa, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi write fail!\n", __func__); - continue; - } - ret = himax_bus_read(pfw_op->addr_ulpm_33[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi read fail!\n", __func__); - continue; - } - - I("%s:retry times %d,addr=0x33, correct 0xAA=current 0x%2.2X\n", - __func__, rtimes, tmp_data[0]); - rtimes++; - } while (tmp_data[0] != pfw_op->data_ulpm_aa[0]); - - /* 33 -> 33 */ - rtimes = 0; - do { - if (rtimes > 10) { - I("%s:6/7 retry over 10 times!\n", __func__); - return false; - } - ret = himax_bus_write(pfw_op->addr_ulpm_33[0], - pfw_op->data_ulpm_33, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi write fail!\n", __func__); - continue; - } - ret = himax_bus_read(pfw_op->addr_ulpm_33[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi read fail!\n", __func__); - continue; - } - - I("%s:retry times %d,addr=0x33,correct 0x33=current 0x%2.2X\n", - __func__, rtimes, tmp_data[0]); - rtimes++; - } while (tmp_data[0] != pfw_op->data_ulpm_33[0]); - - /* 33 -> AA */ - rtimes = 0; - do { - if (rtimes > 10) { - I("%s:7/7 retry over 10 times!\n", __func__); - return false; - } - ret = himax_bus_write(pfw_op->addr_ulpm_33[0], - pfw_op->data_ulpm_aa, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi write fail!\n", __func__); - continue; - } - ret = himax_bus_read(pfw_op->addr_ulpm_33[0], tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - I("%s: spi read fail!\n", __func__); - continue; - } - - I("%s:retry times %d,addr=0x33,correct 0xAA=current 0x%2.2X\n", - __func__, rtimes, tmp_data[0]); - rtimes++; - } while (tmp_data[0] != pfw_op->data_ulpm_aa[0]); - - I("%s:END\n", __func__); - return true; -} - -static int himax_mcu_black_gest_ctrl(bool enable) -{ - int ret = 0; - - I("%s:enable=%d, ts->is_suspended=%d\n", __func__, - enable, private_ts->suspended); - - if (private_ts->suspended) { - if (enable) { -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(false, false); -#else - I("%s: Please enable TP reset define\n", __func__); -#endif - } else { - g_core_fp.fp_ulpm_in(); - } - } else { - g_core_fp.fp_sense_on(0); - } - return ret; -} -#endif - -static void himax_mcu_set_SMWP_enable(uint8_t SMWP_enable, bool suspended) -{ - uint8_t tmp_data[DATA_LEN_4]; - uint8_t back_data[DATA_LEN_4]; - uint8_t retry_cnt = 0; - - do { - if (SMWP_enable) { - himax_parse_assign_cmd(fw_func_handshaking_pwd, - tmp_data, 4); - g_core_fp.fp_register_write(pfw_op->addr_smwp_enable, - DATA_LEN_4, tmp_data, 0); - himax_parse_assign_cmd(fw_func_handshaking_pwd, - back_data, 4); - } else { - himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - tmp_data, - 4); - g_core_fp.fp_register_write(pfw_op->addr_smwp_enable, - DATA_LEN_4, - tmp_data, - 0); - himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - back_data, - 4); - } - - g_core_fp.fp_register_read(pfw_op->addr_smwp_enable, DATA_LEN_4, - tmp_data, 0); - /*I("%s: tmp_data[0]=%d, SMWP_enable=%d, retry_cnt=%d\n", - * __func__, tmp_data[0],SMWP_enable,retry_cnt); - */ - retry_cnt++; - } while ((tmp_data[3] != back_data[3] - || tmp_data[2] != back_data[2] - || tmp_data[1] != back_data[1] - || tmp_data[0] != back_data[0]) - && retry_cnt < HIMAX_REG_RETRY_TIMES); -} - -static void himax_mcu_set_HSEN_enable(uint8_t HSEN_enable, bool suspended) -{ - uint8_t tmp_data[DATA_LEN_4]; - uint8_t back_data[DATA_LEN_4]; - uint8_t retry_cnt = 0; - - do { - if (HSEN_enable) { - himax_parse_assign_cmd(fw_func_handshaking_pwd, - tmp_data, 4); - g_core_fp.fp_register_write(pfw_op->addr_hsen_enable, - DATA_LEN_4, tmp_data, 0); - himax_parse_assign_cmd(fw_func_handshaking_pwd, - back_data, 4); - } else { - himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - tmp_data, - 4); - - g_core_fp.fp_register_write(pfw_op->addr_hsen_enable, - DATA_LEN_4, tmp_data, 0); - - himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - back_data, - 4); - } - - g_core_fp.fp_register_read(pfw_op->addr_hsen_enable, - DATA_LEN_4, tmp_data, 0); - /*I("%s: tmp_data[0]=%d, HSEN_enable=%d, retry_cnt=%d\n", - * __func__, tmp_data[0],HSEN_enable,retry_cnt); - */ - retry_cnt++; - } while ((tmp_data[3] != back_data[3] - || tmp_data[2] != back_data[2] - || tmp_data[1] != back_data[1] - || tmp_data[0] != back_data[0]) - && retry_cnt < HIMAX_REG_RETRY_TIMES); -} - -static void himax_mcu_usb_detect_set(uint8_t *cable_config) -{ - uint8_t tmp_data[DATA_LEN_4]; - uint8_t back_data[DATA_LEN_4]; - uint8_t retry_cnt = 0; - - do { - if (cable_config[1] == 0x01) { - himax_parse_assign_cmd(fw_func_handshaking_pwd, - tmp_data, 4); - g_core_fp.fp_register_write(pfw_op->addr_usb_detect, - DATA_LEN_4, tmp_data, 0); - himax_parse_assign_cmd(fw_func_handshaking_pwd, - back_data, 4); - I("%s: USB detect status IN!\n", __func__); - } else { - himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - tmp_data, - 4); - g_core_fp.fp_register_write(pfw_op->addr_usb_detect, - DATA_LEN_4, tmp_data, 0); - himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - back_data, - 4); - I("%s: USB detect status OUT!\n", __func__); - } - - g_core_fp.fp_register_read(pfw_op->addr_usb_detect, DATA_LEN_4, - tmp_data, 0); - /*I("%s: tmp_data[0]=%d, USB detect=%d, retry_cnt=%d\n", - * __func__, tmp_data[0],cable_config[1] ,retry_cnt); - */ - retry_cnt++; - } while ((tmp_data[3] != back_data[3] - || tmp_data[2] != back_data[2] - || tmp_data[1] != back_data[1] - || tmp_data[0] != back_data[0]) - && retry_cnt < HIMAX_REG_RETRY_TIMES); -} - -#define PRT_DATA "%s:[3]=0x%2X, [2]=0x%2X, [1]=0x%2X, [0]=0x%2X\n" -static void himax_mcu_diag_register_set(uint8_t diag_command, - uint8_t storage_type, bool is_dirly) -{ - uint8_t tmp_data[DATA_LEN_4]; - uint8_t back_data[DATA_LEN_4]; - uint8_t cnt = 50; - - if (diag_command > 0 && storage_type % 8 > 0 && !is_dirly) - tmp_data[0] = diag_command + 0x08; - else - tmp_data[0] = diag_command; - I("diag_command = %d, tmp_data[0] = %X\n", diag_command, tmp_data[0]); - g_core_fp.fp_interface_on(); - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; - do { - g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, - DATA_LEN_4, tmp_data, 0); - g_core_fp.fp_register_read(pfw_op->addr_raw_out_sel, - DATA_LEN_4, back_data, 0); - I(PRT_DATA, __func__, - back_data[3], - back_data[2], - back_data[1], - back_data[0]); - cnt--; - } while (tmp_data[0] != back_data[0] && cnt > 0); -} - -static int himax_mcu_chip_self_test(struct seq_file *s, void *v) -{ - uint8_t tmp_data[FLASH_WRITE_BURST_SZ]; - uint8_t self_test_info[20]; - int pf_value = 0x00; - uint8_t test_result_id = 0; - int i; - - memset(tmp_data, 0x00, sizeof(tmp_data)); - g_core_fp.fp_interface_on(); - g_core_fp.fp_sense_off(true); - g_core_fp.fp_burst_enable(1); - g_core_fp.fp_register_write(pfw_op->addr_selftest_addr_en, DATA_LEN_4, - pfw_op->data_selftest_request, 0); - /*Set criteria 0x10007F1C [0,1]=aa/up,down=, [2-3]=key/up,down, - * [4-5]=avg/up,down - */ - tmp_data[0] = pfw_op->data_criteria_aa_top[0]; - tmp_data[1] = pfw_op->data_criteria_aa_bot[0]; - tmp_data[2] = pfw_op->data_criteria_key_top[0]; - tmp_data[3] = pfw_op->data_criteria_key_bot[0]; - tmp_data[4] = pfw_op->data_criteria_avg_top[0]; - tmp_data[5] = pfw_op->data_criteria_avg_bot[0]; - tmp_data[6] = 0x00; - tmp_data[7] = 0x00; - g_core_fp.fp_register_write(pfw_op->addr_criteria_addr, - FLASH_WRITE_BURST_SZ, tmp_data, 0); - g_core_fp.fp_register_write(pfw_op->addr_set_frame_addr, - DATA_LEN_4, pfw_op->data_set_frame, 0); - /*Disable IDLE Mode*/ - g_core_fp.fp_idle_mode(1); - /*Diable Flash Reload*/ - g_core_fp.fp_reload_disable(1); - /*start selftest // leave safe mode*/ - g_core_fp.fp_sense_on(0x01); - - /*Hand shaking*/ - for (i = 0; i < 1000; i++) { - g_core_fp.fp_register_read(pfw_op->addr_selftest_addr_en, 4, - tmp_data, 0); - I("%s:data0=0x%2X,data1=0x%2X,data2=0x%2X,data3=0x%2X cnt=%d\n", - __func__, - tmp_data[0], - tmp_data[1], - tmp_data[2], - tmp_data[3], - i); - usleep_range(10000, 11000); - - if (tmp_data[1] == pfw_op->data_selftest_ack_hb[0] - && tmp_data[0] == pfw_op->data_selftest_ack_lb[0]) { - I("%s Data ready goto moving data\n", __func__); - break; - } - } - - g_core_fp.fp_sense_off(true); - msleep(20); - /** - * Read test result ==> bit[2][1][0] = [key][AA][avg] => 0xF = PASS - */ - g_core_fp.fp_register_read(pfw_op->addr_selftest_result_addr, 20, - self_test_info, 0); - test_result_id = self_test_info[0]; - I("%s: check test result, test_result_id=%x, test_result=%x\n", - __func__, test_result_id, self_test_info[0]); - I("raw top 1 = %d\n", self_test_info[3] * 256 + self_test_info[2]); - I("raw top 2 = %d\n", self_test_info[5] * 256 + self_test_info[4]); - I("raw top 3 = %d\n", self_test_info[7] * 256 + self_test_info[6]); - I("raw last 1 = %d\n", self_test_info[9] * 256 + self_test_info[8]); - I("raw last 2 = %d\n", self_test_info[11] * 256 + self_test_info[10]); - I("raw last 3 = %d\n", self_test_info[13] * 256 + self_test_info[12]); - I("raw key 1 = %d\n", self_test_info[15] * 256 + self_test_info[14]); - I("raw key 2 = %d\n", self_test_info[17] * 256 + self_test_info[16]); - I("raw key 3 = %d\n", self_test_info[19] * 256 + self_test_info[18]); - - if (test_result_id == pfw_op->data_selftest_pass[0]) { - I("[Himax]: self-test pass\n"); - seq_puts(s, "Self_Test Pass:\n"); - pf_value = 0x0; - } else { - E("[Himax]: self-test fail\n"); - seq_puts(s, "Self_Test Fail:\n"); - /* E("[Himax]: bank_avg = %d, bank_max = %d,%d,%d, bank_min = - * %d,%d,%d, key = %d,%d,%d\n", - * tmp_data[1], tmp_data[2], - * tmp_data[3], tmp_data[4], - * tmp_data[5], tmp_data[6], - * tmp_data[7], tmp_data[8], - * tmp_data[9], tmp_data[10]); - */ - pf_value = 0x1; - } - - /*Enable IDLE Mode*/ - g_core_fp.fp_idle_mode(0); -#if !defined(HX_ZERO_FLASH) - /* Enable Flash Reload //recovery*/ - g_core_fp.fp_reload_disable(0); -#endif - g_core_fp.fp_sense_on(0x00); - msleep(120); - - return pf_value; -} - -#define PRT_TMP_DATA "%s:[0]=0x%2X,[1]=0x%2X, [2]=0x%2X,[3]=0x%2X\n" -static void himax_mcu_idle_mode(int disable) -{ - int retry = 20; - uint8_t tmp_data[DATA_LEN_4]; - uint8_t switch_cmd = 0x00; - - I("%s:entering\n", __func__); - - do { - I("%s,now %d times!\n", __func__, retry); - g_core_fp.fp_register_read(pfw_op->addr_fw_mode_status, - DATA_LEN_4, tmp_data, 0); - - if (disable) - switch_cmd = pfw_op->data_idle_dis_pwd[0]; - else - switch_cmd = pfw_op->data_idle_en_pwd[0]; - - tmp_data[0] = switch_cmd; - g_core_fp.fp_register_write(pfw_op->addr_fw_mode_status, - DATA_LEN_4, tmp_data, 0); - g_core_fp.fp_register_read(pfw_op->addr_fw_mode_status, - DATA_LEN_4, tmp_data, 0); - - I(PRT_TMP_DATA, - __func__, - tmp_data[0], - tmp_data[1], - tmp_data[2], - tmp_data[3]); - - retry--; - usleep_range(10000, 11000); - } while ((tmp_data[0] != switch_cmd) && retry > 0); - - I("%s: setting OK!\n", __func__); -} - -static void himax_mcu_reload_disable(int disable) -{ - I("%s:entering\n", __func__); - - if (disable) { /*reload disable*/ - g_core_fp.fp_register_write( - pdriver_op->addr_fw_define_flash_reload, - DATA_LEN_4, - pdriver_op->data_fw_define_flash_reload_dis, - 0); - } else { /*reload enable*/ - g_core_fp.fp_register_write( - pdriver_op->addr_fw_define_flash_reload, - DATA_LEN_4, - pdriver_op->data_fw_define_flash_reload_en, - 0); - } - - I("%s: setting OK!\n", __func__); -} - -static bool himax_mcu_check_chip_version(void) -{ - uint8_t tmp_data[DATA_LEN_4]; - uint8_t ret_data = false; - int i = 0; - - for (i = 0; i < 5; i++) { - g_core_fp.fp_register_read(pfw_op->addr_icid_addr, DATA_LEN_4, - tmp_data, 0); - I("%s:Read driver IC ID = %X,%X,%X\n", __func__, - tmp_data[3], tmp_data[2], tmp_data[1]); - - if ((tmp_data[3] == 0x83) - && (tmp_data[2] == 0x10) - && (tmp_data[1] == 0x2a)) { - strlcpy(private_ts->chip_name, - HX_83102A_SERIES_PWON, 30); - ret_data = true; - goto END; - } else { - ret_data = false; - E("%s:Read driver ID register Fail:\n", __func__); - } - } -END: - return ret_data; -} - -static int himax_mcu_read_ic_trigger_type(void) -{ - uint8_t tmp_data[DATA_LEN_4]; - int trigger_type = false; - - g_core_fp.fp_register_read(pdriver_op->addr_fw_define_int_is_edge, - DATA_LEN_4, tmp_data, 0); - - if ((tmp_data[1] & 0x01) == 1) - trigger_type = true; - - return trigger_type; -} - -static int himax_mcu_read_i2c_status(void) -{ - return i2c_error_count; -} - -static void himax_mcu_read_FW_ver(void) -{ - uint8_t data[12]; - uint8_t data_2[DATA_LEN_4]; - int retry = 200; - int reload_status = 0; - - g_core_fp.fp_sense_on(0x00); - - while (reload_status == 0) { - g_core_fp.fp_register_read( - pdriver_op->addr_fw_define_flash_reload, - DATA_LEN_4, - data, - 0); - g_core_fp.fp_register_read( - pdriver_op->addr_fw_define_2nd_flash_reload, - DATA_LEN_4, - data_2, - 0); - - if ((data[1] == 0x3A && data[0] == 0xA3) - || (data_2[1] == 0x72 && data_2[0] == 0xC0)) { - I("reload OK!\n"); - reload_status = 1; - break; - } else if (retry == 0) { - E("reload 20 times! fail,Maybe no or wrong FW in IC\n"); - ic_data->vendor_panel_ver = 0; - ic_data->vendor_fw_ver = 0; - ic_data->vendor_config_ver = 0; - ic_data->vendor_touch_cfg_ver = 0; - ic_data->vendor_display_cfg_ver = 0; - ic_data->vendor_cid_maj_ver = 0; - ic_data->vendor_cid_min_ver = 0; - goto END; - } else { - retry--; - usleep_range(10000, 11000); - if (retry % 10 == 0) - I("reload fail ,delay 10ms retry=%d\n", retry); - } - } - - I("%s:data[0]=0x%2.2X,data[1]=0x%2.2X\n", __func__, data[0], data[1]); - I("%s:data_2[0]=0x%2.2X,data_2[1]=0x%2.2X,reload_status=%d\n", __func__, - data_2[0], data_2[1], reload_status); - /** - * Read FW version - */ - g_core_fp.fp_sense_off(true); - g_core_fp.fp_register_read(pfw_op->addr_fw_ver_addr, DATA_LEN_4, - data, 0); - ic_data->vendor_panel_ver = data[0]; - ic_data->vendor_fw_ver = data[1] << 8 | data[2]; - I("PANEL_VER : %X\n", ic_data->vendor_panel_ver); - I("FW_VER : %X\n", ic_data->vendor_fw_ver); - g_core_fp.fp_register_read(pfw_op->addr_fw_cfg_addr, DATA_LEN_4, - data, 0); - ic_data->vendor_config_ver = data[2] << 8 | data[3]; - /*I("CFG_VER : %X\n",ic_data->vendor_config_ver);*/ - ic_data->vendor_touch_cfg_ver = data[2]; - I("TOUCH_VER : %X\n", ic_data->vendor_touch_cfg_ver); - ic_data->vendor_display_cfg_ver = data[3]; - I("DISPLAY_VER : %X\n", ic_data->vendor_display_cfg_ver); - g_core_fp.fp_register_read(pfw_op->addr_fw_vendor_addr, - DATA_LEN_4, data, 0); - ic_data->vendor_cid_maj_ver = data[2]; - ic_data->vendor_cid_min_ver = data[3]; - I("CID_VER : %X\n", (ic_data->vendor_cid_maj_ver << 8 - | ic_data->vendor_cid_min_ver)); - g_core_fp.fp_register_read(pfw_op->addr_cus_info, 12, data, 0); - memcpy(ic_data->vendor_cus_info, data, 12); - I("Cusomer ID = %s\n", ic_data->vendor_cus_info); - g_core_fp.fp_register_read(pfw_op->addr_proj_info, 12, data, 0); - memcpy(ic_data->vendor_proj_info, data, 12); - I("Project ID = %s\n", ic_data->vendor_proj_info); - -END: - return; -} - -static bool himax_mcu_read_event_stack(uint8_t *buf, uint8_t length) -{ - uint8_t cmd[DATA_LEN_4]; - struct timespec t_start, t_end, t_delta; - int len = length; - int i2c_speed = 0; - int ret = 0; - - /* AHB_I2C Burst Read Off */ - cmd[0] = pfw_op->data_ahb_dis[0]; - - ret = himax_bus_write(pfw_op->addr_ahb_addr[0], cmd, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return 0; - } - if (private_ts->debug_log_level & BIT(2)) - getnstimeofday(&t_start); - - himax_bus_read(pfw_op->addr_event_addr[0], buf, length, - HIMAX_I2C_RETRY_TIMES); - - if (private_ts->debug_log_level & BIT(2)) { - getnstimeofday(&t_end); - t_delta.tv_nsec = (t_end.tv_sec * 1000000000 + t_end.tv_nsec) - - (t_start.tv_sec * 1000000000 + t_start.tv_nsec); - - i2c_speed = (len * 9 * 1000000 - / (int)t_delta.tv_nsec) * 13 / 10; - private_ts->bus_speed = (int)i2c_speed; - } - - /* AHB_I2C Burst Read On */ - cmd[0] = pfw_op->data_ahb_en[0]; - - ret = himax_bus_write(pfw_op->addr_ahb_addr[0], cmd, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return 0; - } - - return 1; -} - -static void himax_mcu_return_event_stack(void) -{ - int retry = 20, i; - uint8_t tmp_data[DATA_LEN_4]; - - I("%s:entering\n", __func__); - - do { - I("now %d times!\n", retry); - - for (i = 0; i < DATA_LEN_4; i++) - tmp_data[i] = psram_op->addr_rawdata_end[i]; - - g_core_fp.fp_register_write(psram_op->addr_rawdata_addr, - DATA_LEN_4, tmp_data, 0); - g_core_fp.fp_register_read(psram_op->addr_rawdata_addr, - DATA_LEN_4, tmp_data, 0); - retry--; - usleep_range(10000, 11000); - } while ((tmp_data[1] != psram_op->addr_rawdata_end[1] - && tmp_data[0] != psram_op->addr_rawdata_end[0]) - && retry > 0); - - I("%s: End of setting!\n", __func__); -} - -static bool himax_mcu_calculateChecksum(bool change_iref, uint32_t size) -{ - uint8_t CRC_result = 0, i; - uint8_t tmp_data[DATA_LEN_4]; - - I("%s:Now size=%d\n", __func__, size); - for (i = 0; i < DATA_LEN_4; i++) - tmp_data[i] = psram_op->addr_rawdata_end[i]; - - CRC_result = g_core_fp.fp_check_CRC(tmp_data, size); - msleep(50); - - if (CRC_result != 0) - I("%s: CRC Fail=%d\n", __func__, CRC_result); - - return (CRC_result == 0) ? true : false; -} - -static int himax_mcu_read_FW_status(uint8_t *state_addr, uint8_t *tmp_addr) -{ - uint8_t i; - uint8_t req_size = 0; - uint8_t status_addr[DATA_LEN_4]; - uint8_t cmd_addr[DATA_LEN_4]; - - if (state_addr[0] == 0x01) { - state_addr[1] = 0x04; - - for (i = 0; i < DATA_LEN_4; i++) { - state_addr[i + 2] = pfw_op->addr_fw_dbg_msg_addr[i]; - status_addr[i] = pfw_op->addr_fw_dbg_msg_addr[i]; - } - - req_size = 0x04; - g_core_fp.fp_register_read(status_addr, req_size, tmp_addr, 0); - } else if (state_addr[0] == 0x02) { - state_addr[1] = 0x30; - - for (i = 0; i < DATA_LEN_4; i++) { - state_addr[i + 2] = pfw_op->addr_fw_dbg_msg_addr[i]; - cmd_addr[i] = pfw_op->addr_fw_dbg_msg_addr[i]; - } - - req_size = 0x30; - g_core_fp.fp_register_read(cmd_addr, req_size, tmp_addr, 0); - } - - return NO_ERR; -} - -static void himax_mcu_irq_switch(int switch_on) -{ - if (switch_on) { - if (private_ts->use_irq) - himax_int_enable(switch_on); - else - hrtimer_start(&private_ts->timer, ktime_set(1, 0), - HRTIMER_MODE_REL); - - } else { - if (private_ts->use_irq) - himax_int_enable(switch_on); - else { - hrtimer_cancel(&private_ts->timer); - cancel_work_sync(&private_ts->work); - } - } -} - -static int himax_mcu_assign_sorting_mode(uint8_t *tmp_data) -{ - I("%s:Now data[3]=0x%2X,data[2]=0x%2X,data[1]=0x%2X,data[0]=0x%2X\n", - __func__, tmp_data[3], tmp_data[2], tmp_data[1], tmp_data[0]); - - g_core_fp.fp_register_write(pfw_op->addr_sorting_mode_en, - DATA_LEN_4, tmp_data, 0); - - return NO_ERR; -} - -static int himax_mcu_check_sorting_mode(uint8_t *tmp_data) -{ - - g_core_fp.fp_register_read(pfw_op->addr_sorting_mode_en, - DATA_LEN_4, tmp_data, 0); - I("%s: tmp_data[0]=%x,tmp_data[1]=%x\n", __func__, - tmp_data[0], tmp_data[1]); - - return NO_ERR; -} - -static uint8_t himax_mcu_read_DD_status(uint8_t *cmd_set, uint8_t *tmp_data) -{ - int cnt = 0; - uint8_t req_size = cmd_set[0]; - - cmd_set[3] = pfw_op->data_dd_request[0]; - g_core_fp.fp_register_write(pfw_op->addr_dd_handshak_addr, - DATA_LEN_4, cmd_set, 0); - I("%s:cmd set[0]=0x%2X,set[1]=0x%2X,set[2]=0x%2X,set[3]=0x%2X\n", - __func__, cmd_set[0], cmd_set[1], cmd_set[2], cmd_set[3]); - - /* Doing hand shaking 0xAA -> 0xBB */ - for (cnt = 0; cnt < 100; cnt++) { - g_core_fp.fp_register_read(pfw_op->addr_dd_handshak_addr, - DATA_LEN_4, tmp_data, 0); - usleep_range(10000, 11000); - - if (tmp_data[3] == pfw_op->data_dd_ack[0]) { - I("%s Data ready goto moving data\n", __func__); - goto FINALIZE; - } else { - if (cnt >= 99) { - I("%s Data not ready in FW\n", __func__); - return FW_NOT_READY; - } - } - } -FINALIZE: - g_core_fp.fp_register_read(pfw_op->addr_dd_data_addr, - req_size, tmp_data, 0); - return NO_ERR; -} -#if defined(HX_AUTO_UPDATE_FW) -static int hx_mcu_diff_overlay_bin(void) -{ - int rslt = 0; - int diff_val = 0; - - diff_val = g_i_FW_VER; - I("%s:Now fw ID is 0x%04X\n", __func__, diff_val); - diff_val = (diff_val >> 12); - I("%s:Now diff value=0x%04X\n", __func__, diff_val); - - if (diff_val == 1) - I("%s:Now size should be 128K!\n", __func__); - else - I("%s:Now size should be 64K!\n", __func__); - rslt = diff_val; - return rslt; -} -#endif - -/* FW side end*/ -/* CORE_FW */ - -/* CORE_FLASH */ -/* FLASH side start*/ -static void himax_mcu_chip_erase(void) -{ - g_core_fp.fp_interface_on(); - - /* Reset power saving level */ - if (g_core_fp.fp_init_psl != NULL) - g_core_fp.fp_init_psl(); - - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_fmt, - DATA_LEN_4, pflash_op->data_spi200_trans_fmt, 0); - - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, - DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_2, 0); - g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, - DATA_LEN_4, pflash_op->data_spi200_cmd_2, 0); - - g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, - DATA_LEN_4, pflash_op->data_spi200_cmd_3, 0); - msleep(2000); - - if (!g_core_fp.fp_wait_wip(100)) - E("%s: Chip_Erase Fail\n", __func__); - -} - -static bool himax_mcu_block_erase(int start_addr, int length) -{ - uint32_t page_prog_start = 0; - uint32_t block_size = 0x10000; - - uint8_t tmp_data[4] = {0}; - - g_core_fp.fp_interface_on(); - - g_core_fp.fp_init_psl(); - - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_fmt, - DATA_LEN_4, pflash_op->data_spi200_trans_fmt, 0); - - for (page_prog_start = start_addr; - page_prog_start < start_addr + length; - page_prog_start = page_prog_start + block_size) { - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, - DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_2, 0); - g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, - DATA_LEN_4, pflash_op->data_spi200_cmd_2, 0); - - tmp_data[3] = (page_prog_start >> 24)&0xFF; - tmp_data[2] = (page_prog_start >> 16)&0xFF; - tmp_data[1] = (page_prog_start >> 8)&0xFF; - tmp_data[0] = page_prog_start&0xFF; - g_core_fp.fp_register_write(pflash_op->addr_spi200_addr, - DATA_LEN_4, tmp_data, 0); - - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, - DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_3, 0); - g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, - DATA_LEN_4, pflash_op->data_spi200_cmd_4, 0); - msleep(1000); - - if (!g_core_fp.fp_wait_wip(100)) { - E("%s:Erase Fail\n", __func__); - return false; - } - } - - I("%s:END\n", __func__); - return true; -} - -static bool himax_mcu_sector_erase(int start_addr) -{ - return true; -} - -static void himax_mcu_flash_programming(uint8_t *FW_content, int FW_Size) -{ - int page_prog_start = 0, i = 0, j = 0, k = 0; - int program_length = PROGRAM_SZ; - uint8_t tmp_data[DATA_LEN_4]; - uint8_t buring_data[FLASH_RW_MAX_LEN]; - int ret = 0; - /* 4 bytes for padding*/ - g_core_fp.fp_interface_on(); - - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_fmt, - DATA_LEN_4, pflash_op->data_spi200_trans_fmt, 0); - - for (page_prog_start = 0; page_prog_start < FW_Size; - page_prog_start += FLASH_RW_MAX_LEN) { - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, - DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_2, 0); - g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, - DATA_LEN_4, pflash_op->data_spi200_cmd_2, 0); - - /*Programmable size = 1 page = 256 bytes,*/ - /*word_number = 256 byte / 4 = 64*/ - g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, - DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_4, 0); - - /* Flash start address 1st : 0x0000_0000*/ - if (page_prog_start < 0x100) { - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = (uint8_t)page_prog_start; - } else if (page_prog_start >= 0x100 - && page_prog_start < 0x10000) { - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = (uint8_t)(page_prog_start >> 8); - tmp_data[0] = (uint8_t)page_prog_start; - } else if (page_prog_start >= 0x10000 - && page_prog_start < 0x1000000) { - tmp_data[3] = 0x00; - tmp_data[2] = (uint8_t)(page_prog_start >> 16); - tmp_data[1] = (uint8_t)(page_prog_start >> 8); - tmp_data[0] = (uint8_t)page_prog_start; - } - g_core_fp.fp_register_write(pflash_op->addr_spi200_addr, - DATA_LEN_4, tmp_data, 0); - - for (i = 0; i < ADDR_LEN_4; i++) - buring_data[i] = pflash_op->addr_spi200_data[i]; - - for (i = page_prog_start, j = 0; - i < 16 + page_prog_start; - i++, j++) { - buring_data[j + ADDR_LEN_4] = FW_content[i]; - } - - ret = himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], - buring_data, - ADDR_LEN_4 + 16, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } - - g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, - DATA_LEN_4, pflash_op->data_spi200_cmd_6, 0); - - for (j = 0; j < 5; j++) { - for (i = (page_prog_start + 16 + (j * 48)), k = 0; - i < (page_prog_start + 16 + (j * 48)) + program_length; - i++, k++) - buring_data[k + ADDR_LEN_4] = FW_content[i]; - - ret = himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], - buring_data, - program_length + ADDR_LEN_4, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } - } - - if (!g_core_fp.fp_wait_wip(1)) - E("%s:Flash_Programming Fail\n", __func__); - - } -} - -static void himax_mcu_flash_page_write(uint8_t *write_addr, int length, - uint8_t *write_data) -{ -} - -static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_32k(unsigned char *fw, - int len, bool change_iref) -{ - /* Not use */ - return 0; -} - -static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_60k(unsigned char *fw, - int len, bool change_iref) -{ - /* Not use */ - return 0; -} - -static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_64k(unsigned char *fw, - int len, bool change_iref) -{ - int burnFW_success = 0; - - if (len != FW_SIZE_64k) { - E("%s: The file size is not 64K bytes\n", __func__); - return false; - } - -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(false, false); -#else - g_core_fp.fp_system_reset(); -#endif - g_core_fp.fp_sense_off(true); - g_core_fp.fp_block_erase(0x00, FW_SIZE_64k); - g_core_fp.fp_flash_programming(fw, FW_SIZE_64k); - - if (g_core_fp.fp_check_CRC(pfw_op->addr_program_reload_from, - FW_SIZE_64k) == 0) - burnFW_success = 1; - - /*RawOut select initial*/ - g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, - sizeof(pfw_op->data_clear), pfw_op->data_clear, 0); - /*DSRAM func initial*/ - g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear); - -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(false, false); -#else - /*System reset*/ - g_core_fp.fp_system_reset(); -#endif - return burnFW_success; -} - -static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_124k(unsigned char *fw, - int len, bool change_iref) -{ - /* Not use */ - return 0; -} - -static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_128k(unsigned char *fw, - int len, bool change_iref) -{ - int burnFW_success = 0; - - if (len != FW_SIZE_128k) { - E("%s: The file size is not 128K bytes\n", __func__); - return false; - } - -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_ic_reset(false, false); -#else - g_core_fp.fp_system_reset(); -#endif - g_core_fp.fp_sense_off(true); - g_core_fp.fp_block_erase(0x00, FW_SIZE_128k); - g_core_fp.fp_flash_programming(fw, FW_SIZE_128k); - - if (g_core_fp.fp_check_CRC(pfw_op->addr_program_reload_from, - FW_SIZE_128k) == 0) - burnFW_success = 1; - - /*RawOut select initial*/ - g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, - sizeof(pfw_op->data_clear), pfw_op->data_clear, 0); - /*DSRAM func initial*/ - g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear); - -/*#if defined(HX_RST_PIN_FUNC) - * g_core_fp.fp_ic_reset(false, false); - *#else - * //System reset - * g_core_fp.fp_system_reset(); - *#endif - */ - return burnFW_success; -} - -static void himax_mcu_flash_dump_func(uint8_t local_flash_command, - int Flash_Size, uint8_t *flash_buffer) -{ - uint8_t tmp_addr[DATA_LEN_4]; - uint8_t buffer[256]; - int page_prog_start = 0; - - g_core_fp.fp_sense_off(true); - g_core_fp.fp_burst_enable(1); - - for (page_prog_start = 0; page_prog_start < Flash_Size; - page_prog_start += 128) { - tmp_addr[0] = page_prog_start % 0x100; - tmp_addr[1] = (page_prog_start >> 8) % 0x100; - tmp_addr[2] = (page_prog_start >> 16) % 0x100; - tmp_addr[3] = page_prog_start / 0x1000000; - himax_mcu_register_read(tmp_addr, 128, buffer, 0); - memcpy(&flash_buffer[page_prog_start], buffer, 128); - } - - g_core_fp.fp_burst_enable(0); - g_core_fp.fp_sense_on(0x01); -} - -static bool himax_mcu_flash_lastdata_check(uint32_t size) -{ - uint8_t tmp_addr[4]; - /* 64K - 0x80, which is the address of - * the last 128bytes in 64K, default value - */ - uint32_t start_addr = 0xFF80; - uint32_t temp_addr = 0; - uint32_t flash_page_len = 0x80; - uint8_t flash_tmp_buffer[128]; - - /* In order to match other size of fw */ - start_addr = size - flash_page_len; - I("%s: Now size is %d, the start_addr is 0x%04X\n", - __func__, size, start_addr); - for (temp_addr = start_addr; temp_addr < (start_addr + flash_page_len); - temp_addr = temp_addr + flash_page_len) { - /*I("temp_addr=%d,tmp_addr[0]=0x%2X, tmp_addr[1]=0x%2X, - * tmp_addr[2]=0x%2X,tmp_addr[3]=0x%2X\n", - * temp_addr,tmp_addr[0], tmp_addr[1], - * tmp_addr[2],tmp_addr[3]); - */ - tmp_addr[0] = temp_addr % 0x100; - tmp_addr[1] = (temp_addr >> 8) % 0x100; - tmp_addr[2] = (temp_addr >> 16) % 0x100; - tmp_addr[3] = temp_addr / 0x1000000; - g_core_fp.fp_register_read(tmp_addr, flash_page_len, - &flash_tmp_buffer[0], 0); - } - - if ((!flash_tmp_buffer[flash_page_len-4]) - && (!flash_tmp_buffer[flash_page_len-3]) - && (!flash_tmp_buffer[flash_page_len-2]) - && (!flash_tmp_buffer[flash_page_len-1])) { - I("Fail, Last four Bytes are:\n"); - I("fbuf[FFFC]=0x%2X,[FFFD]=0x%2X,[FFFE]=0x%2X,[FFFF]=0x%2X\n", - flash_tmp_buffer[flash_page_len-4], - flash_tmp_buffer[flash_page_len-3], - flash_tmp_buffer[flash_page_len-2], - flash_tmp_buffer[flash_page_len-1]); - goto FAIL;/*FAIL*/ - } else if ((flash_tmp_buffer[flash_page_len-4] == 0xFF) - && (flash_tmp_buffer[flash_page_len-3] == 0xFF) - && (flash_tmp_buffer[flash_page_len-2] == 0xFF) - && (flash_tmp_buffer[flash_page_len-1] == 0xFF)) { - I("Fail, Last four Bytes are:\n"); - I("fbuf[FFFC]=0x%2X,[FFFD]=0x%2X,[FFFE]=0x%2X,[FFFF]=0x%2X\n", - flash_tmp_buffer[flash_page_len-4], - flash_tmp_buffer[flash_page_len-3], - flash_tmp_buffer[flash_page_len-2], - flash_tmp_buffer[flash_page_len-1]); - goto FAIL; - } else { - I("fbuf[FFFC]=0x%2X,[FFFD]=0x%2X,[FFFE]=0x%2X,[FFFF]=0x%2X\n", - flash_tmp_buffer[flash_page_len-4], - flash_tmp_buffer[flash_page_len-3], - flash_tmp_buffer[flash_page_len-2], - flash_tmp_buffer[flash_page_len-1]); - return 0;/*PASS*/ - } - return 0; -FAIL: - return 1; -} -static int hx_mcu_diff_overlay_flash(void) -{ - int rslt = 0; - int diff_val = 0; - - diff_val = (ic_data->vendor_fw_ver); - I("%s:Now fw ID is 0x%04X\n", __func__, diff_val); - diff_val = (diff_val >> 12); - I("%s:Now diff value=0x%04X\n", __func__, diff_val); - - if (diff_val == 1) - I("%s:Now size should be 128K!\n", __func__); - else - I("%s:Now size should be 64K!\n", __func__); - rslt = diff_val; - return rslt; -} - -/* FLASH side end*/ -/* CORE_FLASH */ - -/* CORE_SRAM */ -/* SRAM side start*/ -static void himax_mcu_sram_write(uint8_t *FW_content) -{ -} - -static bool himax_mcu_sram_verify(uint8_t *FW_File, int FW_Size) -{ - return true; -} - -static bool himax_mcu_get_DSRAM_data(uint8_t *info_data, bool DSRAM_Flag) -{ - int i = 0; - unsigned char tmp_addr[ADDR_LEN_4]; - unsigned char tmp_data[DATA_LEN_4]; - uint8_t max_i2c_size = MAX_I2C_TRANS_SZ; - uint8_t x_num = ic_data->HX_RX_NUM; - uint8_t y_num = ic_data->HX_TX_NUM; - /*int m_key_num = 0;*/ - int total_size = (x_num * y_num + x_num + y_num) * 2 + 4; - int total_data_size = (x_num * y_num + x_num + y_num) * 2; - int total_size_temp; - /*int mutual_data_size = x_num * y_num * 2;*/ - int total_read_times = 0; - int address = 0; - uint8_t *temp_info_data = NULL; /*max mkey size = 8*/ - uint16_t check_sum_cal = 0; - int fw_run_flag = -1; - - temp_info_data = kcalloc((total_size + 8), sizeof(uint8_t), GFP_KERNEL); - if (temp_info_data == NULL) { - E("%s, Failed to allocate memory\n", __func__); - return false; - } - /* 1. Read number of MKey R100070E8H to determin data size */ - /* m_key_num = ic_data->HX_BT_NUM; */ - /* I("%s,m_key_num=%d\n",__func__ ,m_key_num); */ - /* total_size += m_key_num * 2; */ - /* 2. Start DSRAM Rawdata and Wait Data Ready */ - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = psram_op->passwrd_start[1]; - tmp_data[0] = psram_op->passwrd_start[0]; - fw_run_flag = himax_write_read_reg(psram_op->addr_rawdata_addr, - tmp_data, - psram_op->passwrd_end[1], - psram_op->passwrd_end[0]); - - if (fw_run_flag < 0) { - I("%s Data NOT ready => bypass\n", __func__); - goto FAIL; - } - - /* 3. Read RawData */ - total_size_temp = total_size; - I("%s:data[0]=0x%2X,data[1]=0x%2X,data[2]=0x%2X,data[3]=0x%2X\n", - __func__, - psram_op->addr_rawdata_addr[0], - psram_op->addr_rawdata_addr[1], - psram_op->addr_rawdata_addr[2], - psram_op->addr_rawdata_addr[3]); - - tmp_addr[0] = psram_op->addr_rawdata_addr[0]; - tmp_addr[1] = psram_op->addr_rawdata_addr[1]; - tmp_addr[2] = psram_op->addr_rawdata_addr[2]; - tmp_addr[3] = psram_op->addr_rawdata_addr[3]; - - if (total_size % max_i2c_size == 0) - total_read_times = total_size / max_i2c_size; - else - total_read_times = total_size / max_i2c_size + 1; - - for (i = 0; i < total_read_times; i++) { - address = (psram_op->addr_rawdata_addr[3] << 24) - + (psram_op->addr_rawdata_addr[2] << 16) - + (psram_op->addr_rawdata_addr[1] << 8) - + psram_op->addr_rawdata_addr[0] - + i * max_i2c_size; - /*I("%s address = %08X\n", __func__, address);*/ - - tmp_addr[3] = (uint8_t)((address >> 24) & 0x00FF); - tmp_addr[2] = (uint8_t)((address >> 16) & 0x00FF); - tmp_addr[1] = (uint8_t)((address >> 8) & 0x00FF); - tmp_addr[0] = (uint8_t)((address) & 0x00FF); - - if (total_size_temp >= max_i2c_size) { - g_core_fp.fp_register_read(tmp_addr, max_i2c_size, - &temp_info_data[i * max_i2c_size], 0); - total_size_temp = total_size_temp - max_i2c_size; - } else { - /*I("last total_size_temp=%d\n",total_size_temp);*/ - g_core_fp.fp_register_read(tmp_addr, - total_size_temp % max_i2c_size, - &temp_info_data[i * max_i2c_size], 0); - } - } - - /* 4. FW stop outputing */ - tmp_data[3] = temp_info_data[3]; - tmp_data[2] = temp_info_data[2]; - tmp_data[1] = 0x00; - tmp_data[0] = 0x00; - g_core_fp.fp_register_write(psram_op->addr_rawdata_addr, - DATA_LEN_4, tmp_data, 0); - - /* 5. Data Checksum Check */ - for (i = 2; i < total_size; i += 2)/* 2:PASSWORD NOT included */ - check_sum_cal += (temp_info_data[i + 1] * 256 - + temp_info_data[i]); - - if (check_sum_cal % 0x10000 != 0) { - I("%s check_sum_cal fail=%2X\n", __func__, check_sum_cal); - goto FAIL; - } else { - memcpy(info_data, &temp_info_data[4], - total_data_size * sizeof(uint8_t)); - /*I("%s checksum PASS\n", __func__);*/ - } - kfree(temp_info_data); - return true; -FAIL: - kfree(temp_info_data); - return false; -} -/* SRAM side end*/ -/* CORE_SRAM */ - -/* CORE_DRIVER */ - -static void himax_mcu_init_ic(void) -{ - I("%s: use default incell init.\n", __func__); -} - -#if defined(HX_AUTO_UPDATE_FW) -static int himax_mcu_fw_ver_bin(void) -{ - I("%s: use default incell address.\n", __func__); - if (i_CTPM_FW != NULL) { - I("Catch fw version in bin file!\n"); - g_i_FW_VER = (i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR] << 8) - | i_CTPM_FW[FW_VER_MIN_FLASH_ADDR]; - g_i_CFG_VER = (i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR] << 8) - | i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR]; - g_i_CID_MAJ = i_CTPM_FW[CID_VER_MAJ_FLASH_ADDR]; - g_i_CID_MIN = i_CTPM_FW[CID_VER_MIN_FLASH_ADDR]; - } else { - I("FW data is null!\n"); - return 1; - } - return NO_ERR; -} -#endif - - -#if defined(HX_RST_PIN_FUNC) -static void himax_mcu_pin_reset(void) -{ - I("%s: Now reset the Touch chip.\n", __func__); - himax_rst_gpio_set(private_ts->rst_gpio, 0); - msleep(20); - himax_rst_gpio_set(private_ts->rst_gpio, 1); - msleep(50); -} - -static void himax_mcu_ic_reset(uint8_t loadconfig, uint8_t int_off) -{ - struct himax_ts_data *ts = private_ts; - - HX_HW_RESET_ACTIVATE = 0; - I("%s,status: loadconfig=%d,int_off=%d\n", __func__, - loadconfig, int_off); - - if (ts->rst_gpio >= 0) { - if (int_off) - g_core_fp.fp_irq_switch(0); - - g_core_fp.fp_pin_reset(); - - if (loadconfig) - g_core_fp.fp_reload_config(); - - if (int_off) - g_core_fp.fp_irq_switch(1); - - } -} -#endif - -#if !defined(HX_FIX_TOUCH_INFO) -static uint8_t himax_mcu_tp_info_check(void) -{ - uint8_t rx = pdriver_op->data_df_rx[0]; - uint8_t tx = pdriver_op->data_df_tx[0]; - uint8_t pt = pdriver_op->data_df_pt[0]; - uint16_t x_res = pdriver_op->data_df_x_res[1] << 8 - | pdriver_op->data_df_x_res[0]; - uint16_t y_res = pdriver_op->data_df_y_res[1] << 8 - | pdriver_op->data_df_y_res[0]; - uint8_t err_cnt = 0; - - if (ic_data->HX_RX_NUM < (rx / 2) - || ic_data->HX_RX_NUM > (rx * 3 / 2)) { - ic_data->HX_RX_NUM = rx; - err_cnt |= 0x01; - } - if (ic_data->HX_TX_NUM < (tx / 2) - || ic_data->HX_TX_NUM > (tx * 3 / 2)) { - ic_data->HX_TX_NUM = tx; - err_cnt |= 0x02; - } - if (ic_data->HX_MAX_PT < (pt / 2) - || ic_data->HX_MAX_PT > (pt * 3 / 2)) { - ic_data->HX_MAX_PT = pt; - err_cnt |= 0x04; - } - if (ic_data->HX_Y_RES < (y_res / 2) - || ic_data->HX_Y_RES > (y_res * 3 / 2)) { - ic_data->HX_Y_RES = y_res; - err_cnt |= 0x08; - } - if (ic_data->HX_X_RES < (x_res / 2) - || ic_data->HX_X_RES > (x_res * 3 / 2)) { - ic_data->HX_X_RES = x_res; - err_cnt |= 0x10; - } - return err_cnt; -} -#endif - -static void himax_mcu_touch_information(void) -{ - uint8_t tmp_addr[4] = {0}; - uint8_t tmp_data[4] = {0}; -#if !defined(HX_FIX_TOUCH_INFO) - char data[DATA_LEN_8] = {0}; - uint8_t err_cnt = 0; - - g_core_fp.fp_register_read(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, - DATA_LEN_8, data, 0); - ic_data->HX_RX_NUM = data[2]; - ic_data->HX_TX_NUM = data[3]; - ic_data->HX_MAX_PT = data[4]; - /*I("%s : HX_RX_NUM=%d,ic_data->HX_TX_NUM=%d,ic_data->HX_MAX_PT=%d\n", - * __func__,ic_data->HX_RX_NUM, - * ic_data->HX_TX_NUM,ic_data->HX_MAX_PT); - */ - g_core_fp.fp_register_read(pdriver_op->addr_fw_define_xy_res_enable, - DATA_LEN_4, data, 0); - - /*I("%s : c_data->HX_XY_REVERSE=0x%2.2X\n",__func__,data[1]);*/ - if ((data[1] & 0x04) == 0x04) - ic_data->HX_XY_REVERSE = true; - else - ic_data->HX_XY_REVERSE = false; - - g_core_fp.fp_register_read(pdriver_op->addr_fw_define_x_y_res, - DATA_LEN_4, data, 0); - ic_data->HX_Y_RES = data[0] * 256 + data[1]; - ic_data->HX_X_RES = data[2] * 256 + data[3]; - /*I("%s : ic_data->HX_Y_RES=%d,ic_data->HX_X_RES=%d\n",__func__, - * ic_data->HX_Y_RES,ic_data->HX_X_RES); - */ - - g_core_fp.fp_register_read(pdriver_op->addr_fw_define_int_is_edge, - DATA_LEN_4, data, 0); - /*I("%s : data[0]=0x%2.2X,data[1]=0x%2.2X,data[2]=0x%2.2X, - * data[3]=0x%2.2X\n",__func__,data[0],data[1],data[2],data[3]); - */ - /*I("data[0] & 0x01 = %d\n",(data[0] & 0x01));*/ - if ((data[1] & 0x01) == 1) - ic_data->HX_INT_IS_EDGE = true; - else - ic_data->HX_INT_IS_EDGE = false; - - /*1. Read number of MKey R100070E8H to determin data size*/ - g_core_fp.fp_register_read(psram_op->addr_mkey, DATA_LEN_4, data, 0); - /* I("%s: tmp_data[0] = 0x%02X,tmp_data[1] = 0x%02X,tmp_data[2]=0x%02X, - * tmp_data[3] = 0x%02X\n", - */ - /* __func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]);*/ - ic_data->HX_BT_NUM = data[0] & 0x03; - - err_cnt = himax_mcu_tp_info_check(); - if (err_cnt > 0) - E("TP Info from IC is wrong, err_cnt = 0x%X", err_cnt); -#else - ic_data->HX_RX_NUM = FIX_HX_RX_NUM; - ic_data->HX_TX_NUM = FIX_HX_TX_NUM; - ic_data->HX_BT_NUM = FIX_HX_BT_NUM; - ic_data->HX_X_RES = FIX_HX_X_RES; - ic_data->HX_Y_RES = FIX_HX_Y_RES; - ic_data->HX_MAX_PT = FIX_HX_MAX_PT; - ic_data->HX_XY_REVERSE = FIX_HX_XY_REVERSE; - ic_data->HX_INT_IS_EDGE = FIX_HX_INT_IS_EDGE; -#endif - g_core_fp.fp_ic_id_read(); - I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d\n", __func__, - ic_data->HX_RX_NUM, - ic_data->HX_TX_NUM, - ic_data->HX_MAX_PT); - I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d\n", __func__, - ic_data->HX_XY_REVERSE, - ic_data->HX_Y_RES, - ic_data->HX_X_RES); - I("%s:HX_INT_IS_EDGE =%d\n", __func__, ic_data->HX_INT_IS_EDGE); - - tmp_addr[3] = 0x10; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x71; - tmp_addr[0] = 0x9C; - g_core_fp.fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); - ic_data->HX_PEN_FUNC = tmp_data[3]; - I("%s:HX_PEN_FUNC = %d\n", __func__, ic_data->HX_PEN_FUNC); -} - -static void himax_mcu_reload_config(void) -{ - if (himax_report_data_init()) - E("%s: allocate data fail\n", __func__); - - g_core_fp.fp_sense_on(0x00); -} - -static int himax_mcu_get_touch_data_size(void) -{ - return HIMAX_TOUCH_DATA_SIZE; -} - -static int himax_mcu_hand_shaking(void) -{ - /* 0:Running, 1:Stop, 2:I2C Fail */ - int result = 0; - return result; -} - -static int himax_mcu_determin_diag_rawdata(int diag_command) -{ - return diag_command % 10; -} - -static int himax_mcu_determin_diag_storage(int diag_command) -{ - return diag_command / 10; -} - -static int himax_mcu_cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, - int raw_cnt_max) -{ - int RawDataLen; - - if (raw_cnt_rmd != 0x00) - RawDataLen = MAX_I2C_TRANS_SZ - - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1; - else - RawDataLen = MAX_I2C_TRANS_SZ - - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1; - - return RawDataLen; -} - -static bool himax_mcu_diag_check_sum(struct himax_report_data *hx_touch_data) -{ - uint16_t check_sum_cal = 0; - int i; - - /* Check 128th byte CRC */ - for (i = 0, check_sum_cal = 0; - i < (hx_touch_data->touch_all_size - - hx_touch_data->touch_info_size); - i += 2) { - check_sum_cal += (hx_touch_data->hx_rawdata_buf[i + 1] - * FLASH_RW_MAX_LEN - + hx_touch_data->hx_rawdata_buf[i]); - } - - if (check_sum_cal % HX64K != 0) { - I("%s fail=%2X\n", __func__, check_sum_cal); - return 0; - } - - return 1; -} - -static void himax_mcu_diag_parse_raw_data( - struct himax_report_data *hx_touch_data, - int mul_num, int self_num, uint8_t diag_cmd, - int32_t *mutual_data, int32_t *self_data) -{ - diag_mcu_parse_raw_data(hx_touch_data, mul_num, self_num, - diag_cmd, mutual_data, self_data); -} - -#if defined(HX_ESD_RECOVERY) -static int himax_mcu_ic_esd_recovery(int hx_esd_event, - int hx_zero_event, int length) -{ - int ret_val = NO_ERR; - - if (hx_esd_event == length) { - g_zero_event_count = 0; - ret_val = HX_ESD_EVENT; - } else if (hx_zero_event == length) { - if (g_zero_event_count > 5) { - g_zero_event_count = 0; - I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n"); - ret_val = HX_ESD_EVENT; - } else { - g_zero_event_count++; - I("[HIMAX TP MSG]: ALL Zero event is %d times.\n", - g_zero_event_count); - ret_val = HX_ZERO_EVENT_COUNT; - } - } - - return ret_val; -} - -static void himax_mcu_esd_ic_reset(void) -{ - HX_ESD_RESET_ACTIVATE = 0; -#if defined(HX_RST_PIN_FUNC) - himax_mcu_pin_reset(); -#else - himax_mcu_system_reset(); -#endif - I("%s:\n", __func__); -} -#endif -#if defined(HX_TP_PROC_GUEST_INFO) -char *g_checksum_str = "check sum fail"; -/* char *g_guest_info_item[] = { - * "projectID", - * "CGColor", - * "BarCode", - * "Reserve1", - * "Reserve2", - * "Reserve3", - * "Reserve4", - * "Reserve5", - * "VCOM", - * "Vcom-3Gar", - * NULL - * }; - */ - -static int himax_guest_info_get_status(void) -{ - return g_guest_info_data->g_guest_info_ongoing; -} -static void himax_guest_info_set_status(int setting) -{ - g_guest_info_data->g_guest_info_ongoing = setting; -} - -static int himax_guest_info_read(uint32_t start_addr, - uint8_t *flash_tmp_buffer) -{ - uint32_t temp_addr = 0; - uint8_t tmp_addr[4]; - uint32_t flash_page_len = 0x1000; - /* uint32_t checksum = 0x00; */ - int result = 0; - - - I("%s:Reading guest info in start_addr = 0x%08X !\n", __func__, - start_addr); - - tmp_addr[0] = start_addr % 0x100; - tmp_addr[1] = (start_addr >> 8) % 0x100; - tmp_addr[2] = (start_addr >> 16) % 0x100; - tmp_addr[3] = start_addr / 0x1000000; - I("addr[0]=0x%2X,addr[1]=0x%2X,addr[2]=0x%2X,addr[3]=0x%2X\n", - tmp_addr[0], tmp_addr[1], - tmp_addr[2], tmp_addr[3]); - - result = g_core_fp.fp_check_CRC(tmp_addr, flash_page_len); - I("Checksum = 0x%8X\n", result); - if (result != 0) - goto END_FUNC; - - for (temp_addr = start_addr; - temp_addr < (start_addr + flash_page_len); - temp_addr = temp_addr + 128) { - - /* I("temp_addr=%d,tmp_addr[0]=0x%2X,tmp_addr[1]=0x%2X, - * tmp_addr[2]=0x%2X,tmp_addr[3]=0x%2X\n", - * temp_addr,tmp_addr[0],tmp_addr[1], - * tmp_addr[2],tmp_addr[3]); - */ - tmp_addr[0] = temp_addr % 0x100; - tmp_addr[1] = (temp_addr >> 8) % 0x100; - tmp_addr[2] = (temp_addr >> 16) % 0x100; - tmp_addr[3] = temp_addr / 0x1000000; - g_core_fp.fp_register_read(tmp_addr, 128, - &flash_tmp_buffer[temp_addr - start_addr], false); - /* memcpy(&flash_tmp_buffer[temp_addr - start_addr], - * buffer,128); - */ - } - -END_FUNC: - return result; -} - -static int hx_read_guest_info(void) -{ - /* uint8_t tmp_addr[4]; */ - uint32_t panel_info_addr = HX_GUEST_INFO_FLASH_SADDR; - - uint32_t info_len; - uint32_t flash_page_len = 0x1000;/*4k*/ - uint8_t *flash_tmp_buffer = NULL; - /* uint32_t temp_addr = 0; */ - uint8_t temp_str[128]; - int i = 0; - int custom_info_temp = 0; - int checksum = 0; - - himax_guest_info_set_status(1); - - flash_tmp_buffer = kcalloc(HX_GUEST_INFO_SIZE * flash_page_len, - sizeof(uint8_t), GFP_KERNEL); - if (flash_tmp_buffer == NULL) { - I("%s: Memory allocate fail!\n", __func__); - return MEM_ALLOC_FAIL; - } - - g_core_fp.fp_sense_off(true); - /* g_core_fp.fp_burst_enable(1); */ - - for (custom_info_temp = 0; - custom_info_temp < HX_GUEST_INFO_SIZE; - custom_info_temp++) { - checksum = himax_guest_info_read(panel_info_addr - + custom_info_temp - * flash_page_len, - &flash_tmp_buffer[custom_info_temp * flash_page_len]); - if (checksum != 0) { - E("%s:Checksum Fail! g_checksum_str len=%d\n", __func__, - (int)strlen(g_checksum_str)); - memcpy(&g_guest_info_data-> - g_guest_str_in_format[custom_info_temp][0], - g_checksum_str, (int)strlen(g_checksum_str)); - memcpy(&g_guest_info_data-> - g_guest_str[custom_info_temp][0], - g_checksum_str, (int)strlen(g_checksum_str)); - continue; - } - - info_len = flash_tmp_buffer[custom_info_temp * flash_page_len] - + (flash_tmp_buffer[custom_info_temp - * flash_page_len + 1] << 8) - + (flash_tmp_buffer[custom_info_temp - * flash_page_len + 2] << 16) - + (flash_tmp_buffer[custom_info_temp - * flash_page_len + 3] << 24); - - I("Now custom_info_temp = %d\n", custom_info_temp); - - I("Now size_buff[0]=0x%02X,[1]=0x%02X,[2]=0x%02X,[3]=0x%02X\n", - flash_tmp_buffer[custom_info_temp*flash_page_len], - flash_tmp_buffer[custom_info_temp*flash_page_len + 1], - flash_tmp_buffer[custom_info_temp*flash_page_len + 2], - flash_tmp_buffer[custom_info_temp*flash_page_len + 3]); - - I("Now total length=%d\n", info_len); - - g_guest_info_data->g_guest_data_len[custom_info_temp] = - info_len; - - I("Now custom_info_id [0]=%d,[1]=%d,[2]=%d,[3]=%d\n", - flash_tmp_buffer[custom_info_temp*flash_page_len + 4], - flash_tmp_buffer[custom_info_temp*flash_page_len + 5], - flash_tmp_buffer[custom_info_temp*flash_page_len + 6], - flash_tmp_buffer[custom_info_temp*flash_page_len + 7]); - - g_guest_info_data->g_guest_data_type[custom_info_temp] = - flash_tmp_buffer[custom_info_temp * flash_page_len - + 7]; - - /* if(custom_info_temp < 3) { */ - if (info_len > 128) { - I("%s: info_len=%d\n", __func__, info_len); - info_len = 128; - } - for (i = 0; i < info_len; i++) - temp_str[i] = flash_tmp_buffer[custom_info_temp - * flash_page_len - + HX_GUEST_INFO_LEN_SIZE - + HX_GUEST_INFO_ID_SIZE - + i]; - - I("g_guest_info_data->g_guest_str_in_format[%d]size=%d\n", - custom_info_temp, info_len); - memcpy(&g_guest_info_data-> - g_guest_str_in_format[custom_info_temp][0], - temp_str, info_len); - /*}*/ - - for (i = 0; i < 128; i++) - temp_str[i] = flash_tmp_buffer[custom_info_temp - * flash_page_len - + i]; - - I("g_guest_info_data->g_guest_str[%d] size = %d\n", - custom_info_temp, 128); - memcpy(&g_guest_info_data->g_guest_str[custom_info_temp][0], - temp_str, 128); - /*if(custom_info_temp == 0) - *{ - * for ( i = 0; i< 256 ; i++) { - * if(i % 16 == 0 && i > 0) - * I("\n"); - * I("g_guest_info_data->g_guest_str[%d][%d] - = 0x%02X", custom_info_temp, i, - g_guest_info_data->g_guest_str[ - custom_info_temp][i]); - * } - *} - */ - } - /* himax_burst_enable(private_ts->client, 0); */ - - g_core_fp.fp_sense_on(0x01); - - kfree(flash_tmp_buffer); - himax_guest_info_set_status(0); - return NO_ERR; -} -#endif -/* CORE_DRIVER */ - -#if defined(HX_SMART_WAKEUP)\ - || defined(HX_HIGH_SENSE)\ - || defined(HX_USB_DETECT_GLOBAL) -static void himax_mcu_resend_cmd_func(bool suspended) -{ -#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) - struct himax_ts_data *ts = private_ts; -#endif -#if defined(HX_SMART_WAKEUP) - g_core_fp.fp_set_SMWP_enable(ts->SMWP_enable, suspended); -#endif -#if defined(HX_HIGH_SENSE) - g_core_fp.fp_set_HSEN_enable(ts->HSEN_enable, suspended); -#endif -#if defined(HX_USB_DETECT_GLOBAL) - himax_cable_detect_func(true); -#endif -} -#endif - -#if defined(HX_ZERO_FLASH) -int G_POWERONOF = 1; -EXPORT_SYMBOL(G_POWERONOF); -void hx_dis_rload_0f(int disable) -{ - /*Diable Flash Reload*/ - g_core_fp.fp_register_write(pdriver_op->addr_fw_define_flash_reload, - DATA_LEN_4, pzf_op->data_dis_flash_reload, 0); -} - -void himax_mcu_clean_sram_0f(uint8_t *addr, int write_len, int type) -{ - int total_read_times = 0; - int max_bus_size = MAX_I2C_TRANS_SZ; - int total_size_temp = 0; - int address = 0; - int i = 0; - - uint8_t fix_data = 0x00; - uint8_t tmp_addr[4]; - uint8_t tmp_data[MAX_I2C_TRANS_SZ] = {0}; - - I("%s, Entering\n", __func__); - - max_bus_size = (write_len > HX_MAX_WRITE_SZ - 4) - ? (HX_MAX_WRITE_SZ - 4) - : write_len; - - total_size_temp = write_len; - - g_core_fp.fp_burst_enable(1); - - tmp_addr[3] = addr[3]; - tmp_addr[2] = addr[2]; - tmp_addr[1] = addr[1]; - tmp_addr[0] = addr[0]; - I("%s:addr[3]=0x%2X,addr[2]=0x%2X,addr[1]=0x%2X,addr[0]=0x%2X\n", - __func__, - tmp_addr[3], - tmp_addr[2], - tmp_addr[1], - tmp_addr[0]); - - switch (type) { - case 0: - fix_data = 0x00; - break; - case 1: - fix_data = 0xAA; - break; - case 2: - fix_data = 0xBB; - break; - } - - for (i = 0; i < MAX_I2C_TRANS_SZ; i++) - tmp_data[i] = fix_data; - - I("%s, total size=%d\n", __func__, total_size_temp); - - if (total_size_temp % max_bus_size == 0) - total_read_times = total_size_temp / max_bus_size; - else - total_read_times = total_size_temp / max_bus_size + 1; - - for (i = 0; i < (total_read_times); i++) { - I("[log]write %d time start!\n", i); - if (total_size_temp >= max_bus_size) { - g_core_fp.fp_register_write(tmp_addr, - max_bus_size, tmp_data, 0); - total_size_temp = total_size_temp - max_bus_size; - } else { - I("last total_size_temp=%d\n", total_size_temp); - g_core_fp.fp_register_write(tmp_addr, - total_size_temp % max_bus_size, - tmp_data, 0); - } - address = ((i+1) * max_bus_size); - tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); - tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); - - usleep_range(10000, 11000); - } - - I("%s, END\n", __func__); -} - -void himax_mcu_write_sram_0f(const struct firmware *fw_entry, uint8_t *addr, - int start_index, uint32_t write_len) -{ - int total_read_times = 0; - int max_bus_size = MAX_I2C_TRANS_SZ; - int total_size_temp = 0; - int address = 0; - int i = 0; - - uint8_t tmp_addr[4]; - uint8_t *tmp_data; - - total_size_temp = write_len; - I("%s, Entering - total write size=%d\n", __func__, total_size_temp); - - max_bus_size = (write_len > HX_MAX_WRITE_SZ - 4) - ? (HX_MAX_WRITE_SZ - 4) - : write_len; - - g_core_fp.fp_burst_enable(1); - - tmp_addr[3] = addr[3]; - tmp_addr[2] = addr[2]; - tmp_addr[1] = addr[1]; - tmp_addr[0] = addr[0]; - I("%s, write addr = 0x%02X%02X%02X%02X\n", __func__, - tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); - - /* tmp_data = kcalloc(max_bus_size, sizeof(uint8_t), GFP_KERNEL); - * if (tmp_data == NULL) { - * I("%s: Can't allocate enough buf\n", __func__); - * return; - * } - */ - - /*for(i = 0;i<10;i++) - *{ - * I("[%d] 0x%2.2X", i, tmp_data[i]); - *} - *I("\n"); - */ - if (total_size_temp % max_bus_size == 0) - total_read_times = total_size_temp / max_bus_size; - else - total_read_times = total_size_temp / max_bus_size + 1; - - for (i = 0; i < (total_read_times); i++) { - /*I("[log]write %d time start!\n", i);*/ - /*I("[log]addr[3]=0x%02X, addr[2]=0x%02X, - * addr[1]=0x%02X, - * addr[0]=0x%02X!\n", tmp_addr[3], - * tmp_addr[2], tmp_addr[1], tmp_addr[0]); - */ - - if (total_size_temp >= max_bus_size) { - /*memcpy(tmp_data, &fw_entry->data[start_index+i - * * max_bus_size], max_bus_size); - */ - tmp_data = (uint8_t *)&fw_entry->data[start_index+i - * max_bus_size]; - g_core_fp.fp_register_write(tmp_addr, - max_bus_size, tmp_data, 0); - total_size_temp = total_size_temp - max_bus_size; - } else { - /*memcpy(tmp_data, &fw_entry->data[start_index+i - * * max_bus_size], - * total_size_temp % max_bus_size); - */ - tmp_data = (uint8_t *)&fw_entry->data[start_index+i - * max_bus_size]; - I("last total_size_temp=%d\n", - total_size_temp % max_bus_size); - g_core_fp.fp_register_write(tmp_addr, - total_size_temp % max_bus_size, - tmp_data, 0); - } - - /*I("[log]write %d time end!\n", i);*/ - address = ((i+1) * max_bus_size); - tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); - - if (tmp_addr[0] < addr[0]) - tmp_addr[1] = addr[1] - + (uint8_t) ((address>>8) & 0x00FF) + 1; - else - tmp_addr[1] = addr[1] - + (uint8_t) ((address>>8) & 0x00FF); - - udelay(100); - } - I("%s, End\n", __func__); - /* kfree(tmp_data); */ -} - -int himax_sram_write_crc_check(const struct firmware *fw_entry, uint8_t *addr, - int strt_idx, uint32_t len) -{ - int retry = 0; - int crc = -1; - - do { - g_core_fp.fp_write_sram_0f(fw_entry, addr, strt_idx, len); - crc = g_core_fp.fp_check_CRC(addr, len); - retry++; - I("%s, HW CRC %s in %d time\n", __func__, - (crc == 0) ? "OK" : "Fail", retry); - } while (crc != 0 && retry < 3); - - return crc; -} -int hx_parse_bin_cfg_data(const struct firmware *fw_entry, - struct zf_info *zf_info_arr, uint8_t *FW_buf, - uint8_t *sram_min) -{ - bool flag_1k_header = false; - int part_num = 0; - int i = 0; - uint8_t buf[16]; - int i_max = 0; - int i_min = 0; - uint32_t dsram_base = 0xFFFFFFFF; - uint32_t dsram_max = 0; - int cfg_sz = 0; -#if defined(HX_CODE_OVERLAY) - uint8_t j = 0; - int allovlidx = 0; - - if (ovl_idx == NULL) { - ovl_idx = kzalloc(ovl_section_num, GFP_KERNEL); - if (ovl_idx == NULL) { - E("%s, ovl_idx alloc failed!\n", - __func__); - return -ENOMEM; - } - } else { - memset(ovl_idx, 0, ovl_section_num); - } -#endif - /*int different = 0;*/ - /*int j = 0;*/ - - /*0. check 1k header*/ - if (fw_entry->data[0x00] == 0x00 - && fw_entry->data[0x01] == 0x00 - && fw_entry->data[0x02] == 0x00 - && fw_entry->data[0x03] == 0x00 - && fw_entry->data[0x04] == 0x00 - && fw_entry->data[0x05] == 0x00 - && fw_entry->data[0x06] == 0x00 - && fw_entry->data[0x07] == 0x00 - && fw_entry->data[0x0E] == 0x87) - flag_1k_header = true; - else - flag_1k_header = false; - - /*1. get number of partition*/ - if (flag_1k_header == true) - part_num = fw_entry->data[HX64K + HX1K + 12]; - else - part_num = fw_entry->data[HX64K + 12]; - I("%s, Number of partition is %d\n", __func__, part_num); - if (part_num <= 1) { - E("%s, size of cfg part failed! part_num = %d\n", - __func__, part_num); - return LENGTH_FAIL; - } - - /* i = 0 is fw entity, it need to update by itself*/ - for (i = 1; i < part_num; i++) { - /*3. get all partition*/ - if (flag_1k_header == true) - memcpy(buf, - &fw_entry->data[i * 0x10 + HX64K + HX1K], 16); - else - memcpy(buf, &fw_entry->data[i * 0x10 + HX64K], 16); - memcpy(zf_info_arr[i].sram_addr, buf, 4); - zf_info_arr[i].write_size = buf[7] << 24 - | buf[6] << 16 - | buf[5] << 8 - | buf[4]; - zf_info_arr[i].fw_addr = buf[11] << 24 - | buf[10] << 16 - | buf[9] << 8 - | buf[8]; - zf_info_arr[i].cfg_addr = zf_info_arr[i].sram_addr[0]; - zf_info_arr[i].cfg_addr += zf_info_arr[i].sram_addr[1] << 8; - zf_info_arr[i].cfg_addr += zf_info_arr[i].sram_addr[2] << 16; - zf_info_arr[i].cfg_addr += zf_info_arr[i].sram_addr[3] << 24; - -#if defined(HX_CODE_OVERLAY) - /*overlay section*/ - - if ((buf[15] == 0x55 && buf[14] == 0x66) - || (buf[3] == 0x20 && buf[2] == 0x00 - && buf[1] == 0x8C && buf[0] == 0xE0)) { - I("%s: catch overlay section in index %d\n", - __func__, i); - - /* record index of overlay section */ - allovlidx |= 1< zf_info_arr[i].cfg_addr) { - dsram_base = zf_info_arr[i].cfg_addr; - i_min = i; - } - if (dsram_max < zf_info_arr[i].cfg_addr) { - dsram_max = zf_info_arr[i].cfg_addr; - i_max = i; - } - } - for (i = 0; i < ADDR_LEN_4; i++) - sram_min[i] = zf_info_arr[i_min].sram_addr[i]; - - cfg_sz = (dsram_max - dsram_base) + zf_info_arr[i_max].write_size; - if (cfg_sz % 16 != 0) - cfg_sz = cfg_sz + 16 - (cfg_sz % 16); - - I("%s, cfg_sz = %d!, dsram_base = %X, dsram_max = %X\n", __func__, - cfg_sz, dsram_base, dsram_max); - if (cfg_sz <= FW_BIN_16K_SZ) - memset(FW_buf, 0x00, sizeof(uint8_t) * cfg_sz); - else - memset(FW_buf, 0x00, sizeof(uint8_t) * FW_BIN_16K_SZ); - for (i = 1; i < part_num; i++) { - if (zf_info_arr[i].cfg_addr % 4 != 0) - zf_info_arr[i].cfg_addr = zf_info_arr[i].cfg_addr - - (zf_info_arr[i].cfg_addr % 4); - - I("%s,[%d]SRAM addr=%08X,[%d]fw_addr=%08X,[%d]write_size=%d\n", - __func__, - i, zf_info_arr[i].cfg_addr, - i, zf_info_arr[i].fw_addr, - i, zf_info_arr[i].write_size); - -#if defined(HX_CODE_OVERLAY) - /*overlay section*/ - if (allovlidx & (1<data[zf_info_arr[i].fw_addr], - zf_info_arr[i].write_size); - } - /* debug info */ - /* for (i = 1; i < part_num; i++) { - * different = 0; - * I("--cfg_addr = 0x%08X\n",zf_info_arr[i].cfg_addr); - * I("--bin_addr = 0x%08X\n",zf_info_arr[i].fw_addr); - * I("--write size = %d\n",zf_info_arr[i].write_size); - * for ( j = 0; j < zf_info_arr[i].write_size; j++) { - * if(FW_buf[zf_info_arr[i].cfg_addr - dsram_base + j] != - fw_entry->data[zf_info_arr[i].fw_addr + j]) - * different++; - * } - * I("--There are %d different\n", different); - * } - */ - - return cfg_sz; -} -int himax_zf_part_info(const struct firmware *fw_entry) -{ - bool flag_1k_header = false; - int part_num = 0; - int ret = 0; - uint8_t buf[16]; - struct zf_info *zf_info_arr; - uint8_t *FW_buf; - uint8_t sram_min[4]; - int cfg_crc_sw = 0; - int cfg_crc_hw = 0; - int cfg_sz = 0; - int retry = 3; - -#if defined(HX_CODE_OVERLAY) - uint8_t tmp_addr[4] = {0xFC, 0x7F, 0x00, 0x10}; - uint8_t send_data[4] = {0}; - uint8_t recv_data[4] = {0}; - uint8_t ovl_idx_t = 0; -#endif - - /*0. check 1k header*/ - if (fw_entry->data[0x00] == 0x00 - && fw_entry->data[0x01] == 0x00 - && fw_entry->data[0x02] == 0x00 - && fw_entry->data[0x03] == 0x00 - && fw_entry->data[0x04] == 0x00 - && fw_entry->data[0x05] == 0x00 - && fw_entry->data[0x06] == 0x00 - && fw_entry->data[0x07] == 0x00 - && fw_entry->data[0x0E] == 0x87) - flag_1k_header = true; - else - flag_1k_header = false; - /*1. get number of partition*/ - if (flag_1k_header == true) - part_num = fw_entry->data[HX64K + HX1K + 12]; - else - part_num = fw_entry->data[HX64K + 12]; - I("%s, Number of partition is %d\n", __func__, part_num); - if (part_num <= 0) - part_num = 1; - - /*2. initial struct of array*/ - zf_info_arr = kcalloc(part_num, sizeof(struct zf_info), GFP_KERNEL); - if (zf_info_arr == NULL) { - E("%s, Allocate ZF info array failed!\n", __func__); - ret = MEM_ALLOC_FAIL; - goto ALOC_ZF_INFO_ARR_FAIL; - } - memset(zf_info_arr, 0x0, part_num * sizeof(struct zf_info)); - - FW_buf = kcalloc(FW_BIN_16K_SZ, sizeof(uint8_t), GFP_KERNEL); - if (FW_buf == NULL) { - E("%s, Allocate FW_buf array failed!\n", __func__); - ret = MEM_ALLOC_FAIL; - goto ALOC_FW_BUF_FAIL; - } - - /*3. Find the data in the bin file */ - /*CFG*/ - cfg_sz = hx_parse_bin_cfg_data(fw_entry, zf_info_arr, FW_buf, - sram_min); - I("Now cfg_sz=%d\n", cfg_sz); - if (cfg_sz < 0) { - ret = LENGTH_FAIL; - goto END_FUNC; - } else { - cfg_crc_sw = g_core_fp.fp_Calculate_CRC_with_AP(FW_buf, 0, - cfg_sz); - I("Now cfg_crc_sw=%X\n", cfg_crc_sw); - } - /*Fw Entity*/ - if (flag_1k_header == true) - memcpy(buf, &fw_entry->data[0 * 0x10 + HX64K + HX1K], 16); - else - memcpy(buf, &fw_entry->data[0 * 0x10 + HX64K], 16); - memcpy(zf_info_arr[0].sram_addr, buf, 4); - zf_info_arr[0].write_size = buf[7] << 24 - | buf[6] << 16 - | buf[5] << 8 - | buf[4]; - zf_info_arr[0].fw_addr = buf[11] << 24 - | buf[10] << 16 - | buf[9] << 8 - | buf[8]; - - /* 4. write to sram*/ - if (G_POWERONOF == 1) { - /* FW entity */ - if (himax_sram_write_crc_check(fw_entry, - zf_info_arr[0].sram_addr, - zf_info_arr[0].fw_addr, - zf_info_arr[0].write_size) != 0) { - E("%s, HW CRC FAIL\n", __func__); - } else { - I("%s, HW CRC PASS\n", __func__); - } - - I("Now sram_min[0]=0x%02X,[1]=0x%02X,[2]=0x%02X,[3]=0x%02X\n", - sram_min[0], sram_min[1], sram_min[2], sram_min[3]); - do { - g_core_fp.fp_register_write(sram_min, cfg_sz, - FW_buf, 0); - cfg_crc_hw = g_core_fp.fp_check_CRC(sram_min, cfg_sz); - if (cfg_crc_hw != cfg_crc_sw) { - E("Cfg CRC FAIL,HWCRC=%X,SWCRC=%X,retry=%d\n", - cfg_crc_hw, cfg_crc_sw, retry); - } else - I("Config CRC Pass\n"); - - } while (cfg_crc_hw != cfg_crc_sw && retry-- > 0); - -#if defined(HX_CODE_OVERLAY) - /* ovl_idx[0] - sorting */ - /* ovl_idx[1] - gesture */ - /* ovl_idx[2] - border */ - - ovl_idx_t = ovl_idx[0]; - send_data[0] = ovl_sorting_reply; - - if (private_ts->in_self_test == 0) { -#if defined(HX_SMART_WAKEUP) - if (private_ts->suspended && private_ts->SMWP_enable) { - ovl_idx_t = ovl_idx[1]; - send_data[0] = ovl_gesture_reply; - } else { - ovl_idx_t = ovl_idx[2]; - send_data[0] = ovl_border_reply; - } -#else - ovl_idx_t = ovl_idx[2]; - send_data[0] = ovl_border_reply; -#endif - -#if defined(HX_SMART_WAKEUP) \ - || defined(HX_HIGH_SENSE) \ - || defined(HX_USB_DETECT_GLOBAL) - /*write back system config*/ - g_core_fp.fp_resend_cmd_func(private_ts->suspended); -#endif - } - I("%s: prepare upgrade overlay section = %d\n", - __func__, ovl_idx_t); - - if (zf_info_arr[ovl_idx_t].write_size == 0) { - send_data[0] = ovl_fault; - E("%s, WRONG overlay section, plese check FW!\n", - __func__); - } else { - if (himax_sram_write_crc_check(fw_entry, - zf_info_arr[ovl_idx_t].sram_addr, - zf_info_arr[ovl_idx_t].fw_addr, - zf_info_arr[ovl_idx_t].write_size) != 0) { - send_data[0] = ovl_fault; - E("%s, Overlay HW CRC FAIL\n", __func__); - } else { - I("%s, Overlay HW CRC PASS\n", __func__); - } - } - - retry = 0; - do { - g_core_fp.fp_register_write(tmp_addr, - DATA_LEN_4, send_data, 0); - g_core_fp.fp_register_read(tmp_addr, - DATA_LEN_4, recv_data, 0); - retry++; - } while ((send_data[3] != recv_data[3] - || send_data[2] != recv_data[2] - || send_data[1] != recv_data[1] - || send_data[0] != recv_data[0]) - && retry < HIMAX_REG_RETRY_TIMES); -#endif - - } else { - g_core_fp.fp_clean_sram_0f(zf_info_arr[0].sram_addr, - zf_info_arr[0].write_size, 2); - } - -END_FUNC: - kfree(FW_buf); -ALOC_FW_BUF_FAIL: - kfree(zf_info_arr); -ALOC_ZF_INFO_ARR_FAIL: - return ret; -} - -void himax_mcu_firmware_update_0f(const struct firmware *fw_entry) -{ - int ret = 0; - uint8_t tmp_data[DATA_LEN_4] = {0x01, 0x00, 0x00, 0x00}; - - I("%s,Entering - total FW size=%d\n", __func__, (int)fw_entry->size); - - g_core_fp.fp_register_write(pzf_op->addr_system_reset, 4, - pzf_op->data_system_reset, 0); - - g_core_fp.fp_sense_off(false); - - if ((int)fw_entry->size > HX64K) { - ret = himax_zf_part_info(fw_entry); - } else { - /* first 48K */ - ret = himax_sram_write_crc_check(fw_entry, - pzf_op->data_sram_start_addr, 0, HX_48K_SZ); - if (ret != 0) - E("%s, HW CRC FAIL - Main SRAM 48K\n", __func__); - - /*config info*/ - if (G_POWERONOF == 1) { - ret = himax_sram_write_crc_check(fw_entry, - pzf_op->data_cfg_info, 0xC000, 128); - if (ret != 0) - E("Config info CRC Fail!\n"); - } else { - g_core_fp.fp_clean_sram_0f(pzf_op->data_cfg_info, - 128, 2); - } - - if (G_POWERONOF == 1) { - ret = himax_sram_write_crc_check(fw_entry, - pzf_op->data_fw_cfg_1, 0xC0FE, 528); - if (ret != 0) - E("FW config 1 CRC Fail!\n"); - } else { - g_core_fp.fp_clean_sram_0f(pzf_op->data_fw_cfg_1, - 528, 1); - } - - if (G_POWERONOF == 1) { - ret = himax_sram_write_crc_check(fw_entry, - pzf_op->data_fw_cfg_3, 0xCA00, 128); - if (ret != 0) - E("FW config 3 CRC Fail!\n"); - } else { - g_core_fp.fp_clean_sram_0f(pzf_op->data_fw_cfg_3, - 128, 2); - } - - /*ADC config*/ - if (G_POWERONOF == 1) { - ret = himax_sram_write_crc_check(fw_entry, - pzf_op->data_adc_cfg_1, 0xD640, 1200); - if (ret != 0) - E("ADC config 1 CRC Fail!\n"); - } else { - g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_1, - 1200, 2); - } - - if (G_POWERONOF == 1) { - ret = himax_sram_write_crc_check(fw_entry, - pzf_op->data_adc_cfg_2, 0xD320, 800); - if (ret != 0) - E("ADC config 2 CRC Fail!\n"); - } else { - g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_2, - 800, 2); - } - - /*mapping table*/ - if (G_POWERONOF == 1) { - ret = himax_sram_write_crc_check(fw_entry, - pzf_op->data_map_table, 0xE000, 1536); - if (ret != 0) - E("Mapping table CRC Fail!\n"); - } else { - g_core_fp.fp_clean_sram_0f(pzf_op->data_map_table, - 1536, 2); - } - } - - /* set n frame=0*/ - /*if (G_POWERONOF == 1) - * g_core_fp.fp_write_sram_0f(fw_entry, - pfw_op->addr_set_frame_addr, - 0xC30C, 4); - *else - * g_core_fp.fp_clean_sram_0f(pfw_op->addr_set_frame_addr, 4, 2); - */ - /* reset N frame back to default value 1 for normal mode */ - g_core_fp.fp_register_write(pfw_op->addr_set_frame_addr, 4, - tmp_data, 0); - - I("%s, End\n", __func__); -} - -int hx_0f_op_file_dirly(char *file_name) -{ - int err = NO_ERR, ret; - const struct firmware *fw_entry = NULL; - - - I("%s, Entering,file name = %s\n", __func__, file_name); - - ret = request_firmware(&fw_entry, file_name, private_ts->dev); - if (ret < 0) { -#if defined(__EMBEDDED_FW__) - fw_entry = &g_embedded_fw; - I("%s: Not find FW in userspace, use embedded FW(size:%zu)\n", - __func__, g_embedded_fw.size); -#else - E("%s,%d: error code = %d, file maybe fail\n", - __func__, __LINE__, ret); - return ret; -#endif - } - - himax_int_enable(0); - - if (g_f_0f_updat == 1) { - I("%s:[Warning]Other thread is updating now!\n", __func__); - err = -1; - goto END; - } else { - I("%s:Entering Update Flow!\n", __func__); - g_f_0f_updat = 1; - } - - g_core_fp.fp_firmware_update_0f(fw_entry); - if (ret >= 0) - release_firmware(fw_entry); - - g_f_0f_updat = 0; -END: - I("%s, END\n", __func__); - return err; -} - -int himax_mcu_0f_operation_dirly(void) -{ - int err = NO_ERR, ret; - const struct firmware *fw_entry = NULL; - - I("%s, Entering,file name = %s\n", __func__, i_CTPM_firmware_name); - - ret = request_firmware(&fw_entry, i_CTPM_firmware_name, - private_ts->dev); - if (ret < 0) { -#if defined(__EMBEDDED_FW__) - fw_entry = &g_embedded_fw; - I("%s: Not find FW in userspace, use embedded FW(size:%zu)\n", - __func__, g_embedded_fw.size); -#else - E("%s,%d: error code = %d, file maybe fail\n", - __func__, __LINE__, ret); - return ret; -#endif - } - - himax_int_enable(0); - - if (g_f_0f_updat == 1) { - I("%s:[Warning]Other thread is updating now!\n", __func__); - err = -1; - goto END; - } else { - I("%s:Entering Update Flow!\n", __func__); - g_f_0f_updat = 1; - } - - g_core_fp.fp_firmware_update_0f(fw_entry); - if (ret >= 0) - release_firmware(fw_entry); - - g_f_0f_updat = 0; -END: - I("%s, END\n", __func__); - return err; -} - -void himax_mcu_0f_operation(struct work_struct *work) -{ - int err = NO_ERR; - const struct firmware *fw_entry = NULL; - - I("%s, Entering,file name = %s\n", __func__, i_CTPM_firmware_name); - - err = request_firmware(&fw_entry, i_CTPM_firmware_name, - private_ts->dev); - if (err < 0) { -#if defined(__EMBEDDED_FW__) - fw_entry = &g_embedded_fw; - I("%s: Not find FW in userspace, use embedded FW(size:%zu)", - __func__, g_embedded_fw.size); -#else - E("%s,%d: error code = %d, file maybe fail\n", - __func__, __LINE__, err); - goto END; -#endif - } - - if (g_f_0f_updat == 1) { - I("%s:[Warning]Other thread is updating now!\n", __func__); - goto END; - } else { - I("%s:Entering Update Flow!\n", __func__); - g_f_0f_updat = 1; - } - - himax_int_enable(0); - - g_core_fp.fp_firmware_update_0f(fw_entry); - if (err >= 0) - release_firmware(fw_entry); - - g_core_fp.fp_reload_disable(0); - g_core_fp.fp_read_FW_ver(); - /*msleep (10);*/ - g_core_fp.fp_touch_information(); - /*msleep (10);*/ - g_core_fp.fp_sense_on(0x00); - /*msleep (10);*/ - I("%s:End\n", __func__); - himax_int_enable(1); - - g_f_0f_updat = 0; -END: - I("%s, END\n", __func__); -} - -static int himax_mcu_0f_esd_check(void) -{ - return NO_ERR; -} - - -#if defined(HX_0F_DEBUG) -void himax_mcu_read_sram_0f(const struct firmware *fw_entry, - uint8_t *addr, int start_index, int read_len) -{ - int total_read_times = 0; - int max_bus_size = MAX_I2C_TRANS_SZ; - int total_size_temp = 0; - int total_size = 0; - int address = 0; - int i = 0, j = 0; - int not_same = 0; - - uint8_t tmp_addr[4]; - uint8_t *temp_info_data = NULL; - int *not_same_buff = NULL; - - I("%s, Entering\n", __func__); - - /*g_core_fp.fp_burst_enable(1);*/ - - total_size = read_len; - - total_size_temp = read_len; - -#if defined(HX_SPI_OPERATION) - if (read_len > 2048) - max_bus_size = 2048; - else - max_bus_size = read_len; -#else - if (read_len > 240) - max_bus_size = 240; - else - max_bus_size = read_len; -#endif - - if (total_size % max_bus_size == 0) - total_read_times = total_size / max_bus_size; - else - total_read_times = total_size / max_bus_size + 1; - - I("%s, total size=%d, bus size=%d, read time=%d\n", - __func__, - total_size, - max_bus_size, - total_read_times); - - tmp_addr[3] = addr[3]; - tmp_addr[2] = addr[2]; - tmp_addr[1] = addr[1]; - tmp_addr[0] = addr[0]; - I("%s,addr[3]=0x%2X,addr[2]=0x%2X,addr[1]=0x%2X,addr[0]=0x%2X\n", - __func__, - tmp_addr[3], - tmp_addr[2], - tmp_addr[1], - tmp_addr[0]); - - temp_info_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL); - if (temp_info_data == NULL) { - E("%s, Failed to allocate temp_info_data\n", __func__); - goto err_malloc_temp_info_data; - } - - not_same_buff = kcalloc(total_size, sizeof(int), GFP_KERNEL); - if (not_same_buff == NULL) { - E("%s, Failed to allocate not_same_buff\n", __func__); - goto err_malloc_not_same_buff; - } - - g_core_fp.fp_burst_enable(1); - - for (i = 0; i < (total_read_times); i++) { - if (total_size_temp >= max_bus_size) { - g_core_fp.fp_register_read(tmp_addr, max_bus_size, - &temp_info_data[i*max_bus_size], false); - total_size_temp = total_size_temp - max_bus_size; - } else { - g_core_fp.fp_register_read(tmp_addr, - total_size_temp % max_bus_size, - &temp_info_data[i*max_bus_size], - false); - } - - address = ((i+1) * max_bus_size); - tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); - if (tmp_addr[0] < addr[0]) - tmp_addr[1] = addr[1] - + (uint8_t) ((address>>8) & 0x00FF) + 1; - else - tmp_addr[1] = addr[1] - + (uint8_t) ((address>>8) & 0x00FF); - - /*msleep (10);*/ - } - I("%s,READ Start, start_index = %d\n", __func__, start_index); - - j = start_index; - for (i = 0; i < read_len; i++, j++) { - if (fw_entry->data[j] != temp_info_data[i]) { - not_same++; - not_same_buff[i] = 1; - } - - I("0x%2.2X, ", temp_info_data[i]); - - if (i > 0 && i%16 == 15) - pr_info("\n"); - - } - I("%s,READ END,Not Same count=%d\n", __func__, not_same); - - if (not_same != 0) { - j = start_index; - for (i = 0; i < read_len; i++, j++) { - if (not_same_buff[i] == 1) - I("bin=[%d] 0x%2.2X\n", i, fw_entry->data[j]); - } - for (i = 0; i < read_len; i++, j++) { - if (not_same_buff[i] == 1) - I("sram=[%d] 0x%2.2X\n", i, temp_info_data[i]); - } - } - I("%s,READ END, Not Same count=%d\n", __func__, not_same); - - kfree(not_same_buff); -err_malloc_not_same_buff: - kfree(temp_info_data); -err_malloc_temp_info_data: - return; -} - -void himax_mcu_read_all_sram(uint8_t *addr, int read_len) -{ - int total_read_times = 0; - int max_bus_size = MAX_I2C_TRANS_SZ; - int total_size_temp = 0; - int total_size = 0; - int address = 0; - int i = 0; - /* struct file *fn; */ - /* struct filename *vts_name; */ - - uint8_t tmp_addr[4]; - uint8_t *temp_info_data; - - I("%s, Entering\n", __func__); - - /*g_core_fp.fp_burst_enable(1);*/ - - total_size = read_len; - - total_size_temp = read_len; - - if (total_size % max_bus_size == 0) - total_read_times = total_size / max_bus_size; - else - total_read_times = total_size / max_bus_size + 1; - - I("%s, total size=%d\n", __func__, total_size); - - tmp_addr[3] = addr[3]; - tmp_addr[2] = addr[2]; - tmp_addr[1] = addr[1]; - tmp_addr[0] = addr[0]; - I("%s:addr[3]=0x%2X,addr[2]=0x%2X,addr[1]=0x%2X,addr[0]=0x%2X\n", - __func__, - tmp_addr[3], - tmp_addr[2], - tmp_addr[1], - tmp_addr[0]); - - temp_info_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL); - if (temp_info_data == NULL) { - E("%s, Failed to allocate temp_info_data\n", __func__); - return; - } - - g_core_fp.fp_burst_enable(1); - - for (i = 0; i < (total_read_times); i++) { - if (total_size_temp >= max_bus_size) { - g_core_fp.fp_register_read(tmp_addr, - max_bus_size, - &temp_info_data[i*max_bus_size], - false); - total_size_temp = total_size_temp - max_bus_size; - } else { - g_core_fp.fp_register_read(tmp_addr, - total_size_temp % max_bus_size, - &temp_info_data[i*max_bus_size], - false); - } - - address = ((i+1) * max_bus_size); - tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); - tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); - - /*msleep (10);*/ - } - I("%s,addr[3]=0x%2X,addr[2]=0x%2X,addr[1]=0x%2X,addr[0]=0x%2X\n", - __func__, - tmp_addr[3], - tmp_addr[2], - tmp_addr[1], - tmp_addr[0]); - /*for(i = 0;i 0 && i%16 == 15) - * printk("\n"); - *} - */ - - /* need modify - * I("Now Write File start!\n"); - * vts_name = kp_getname_kernel("/sdcard/dump_dsram.txt"); - * fn = kp_file_open_name(vts_name, O_CREAT | O_WRONLY, 0); - * if (!IS_ERR (fn)) { - * I("%s create file and ready to write\n", __func__); - * fn->f_op->write(fn, temp_info_data, read_len*sizeof (uint8_t), - * &fn->f_pos); - * filp_close (fn, NULL); - * } - * I("Now Write File End!\n"); - */ - - kfree(temp_info_data); - - I("%s, END\n", __func__); - -} - -void himax_mcu_firmware_read_0f(const struct firmware *fw_entry, int type) -{ - uint8_t tmp_addr[4]; - - I("%s, Entering\n", __func__); - if (type == 0) { /* first 48K */ - g_core_fp.fp_read_sram_0f(fw_entry, - pzf_op->data_sram_start_addr, - 0, - HX_48K_SZ); - g_core_fp.fp_read_all_sram(tmp_addr, 0xC000); - } else { /*last 16k*/ - g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_cfg_info, - 0xC000, 132); - - /*FW config*/ - g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_fw_cfg_1, - 0xC0FE, 484); - g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_fw_cfg_2, - 0xC9DE, 36); - g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_fw_cfg_3, - 0xCA00, 72); - - /*ADC config*/ - - g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_1, - 0xD630, 1188); - g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_2, - 0xD318, 792); - - - /*mapping table*/ - g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_map_table, - 0xE000, 1536); - - /* set n frame=0*/ - g_core_fp.fp_read_sram_0f(fw_entry, pfw_op->addr_set_frame_addr, - 0xC30C, 4); - } - - I("%s, END\n", __func__); -} - -void himax_mcu_0f_operation_check(int type) -{ - int err = NO_ERR; - const struct firmware *fw_entry = NULL; - /* char *firmware_name = "himax.bin"; */ - - - I("%s, Entering,file name = %s\n", __func__, i_CTPM_firmware_name); - - err = request_firmware(&fw_entry, i_CTPM_firmware_name, - private_ts->dev); - if (err < 0) { -#if defined(__EMBEDDED_FW__) - fw_entry = &g_embedded_fw; - I("%s: Not find FW in userspace, use embedded FW(size:%zu)\n", - __func__, g_embedded_fw.size); -#else - E("%s,%d: error code = %d\n", __func__, __LINE__, err); - return; -#endif - } - - I("first 4 bytes 0x%2X, 0x%2X, 0x%2X, 0x%2X !\n", - fw_entry->data[0], - fw_entry->data[1], - fw_entry->data[2], - fw_entry->data[3]); - I("next 4 bytes 0x%2X, 0x%2X, 0x%2X, 0x%2X !\n", - fw_entry->data[4], - fw_entry->data[5], - fw_entry->data[6], - fw_entry->data[7]); - I("and next 4 bytes 0x%2X, 0x%2X, 0x%2X, 0x%2X !\n", - fw_entry->data[8], - fw_entry->data[9], - fw_entry->data[10], - fw_entry->data[11]); - - g_core_fp.fp_firmware_read_0f(fw_entry, type); - - if (err >= 0) - release_firmware(fw_entry); - I("%s, END\n", __func__); -} -#endif - -#if defined(HX_CODE_OVERLAY) -int himax_mcu_0f_overlay(int ovl_type, int mode) -{ - return NO_ERR; -} -#endif - -#endif - -/* CORE_INIT */ -/* init start */ -static void himax_mcu_fp_init(void) -{ -/* CORE_IC */ - g_core_fp.fp_burst_enable = himax_mcu_burst_enable; - g_core_fp.fp_register_read = himax_mcu_register_read; - /* - * g_core_fp.fp_flash_write_burst = himax_mcu_flash_write_burst; - */ - /* - * g_core_fp.fp_flash_write_burst_lenth = - * himax_mcu_flash_write_burst_lenth; - */ - g_core_fp.fp_register_write = himax_mcu_register_write; - g_core_fp.fp_interface_on = himax_mcu_interface_on; - g_core_fp.fp_sense_on = himax_mcu_sense_on; - g_core_fp.fp_sense_off = himax_mcu_sense_off; - g_core_fp.fp_wait_wip = himax_mcu_wait_wip; - g_core_fp.fp_init_psl = himax_mcu_init_psl; - g_core_fp.fp_resume_ic_action = himax_mcu_resume_ic_action; - g_core_fp.fp_suspend_ic_action = himax_mcu_suspend_ic_action; - g_core_fp.fp_power_on_init = himax_mcu_power_on_init; - g_core_fp.fp_dd_clk_set = himax_mcu_dd_clk_set; - g_core_fp.fp_dd_reg_en = himax_mcu_dd_reg_en; - g_core_fp.fp_ic_id_read = himax_mcu_ic_id_read; - g_core_fp.fp_dd_reg_write = himax_mcu_dd_reg_write; - g_core_fp.fp_dd_reg_read = himax_mcu_dd_reg_read; -/* CORE_IC */ -/* CORE_FW */ - g_core_fp.fp_system_reset = himax_mcu_system_reset; - g_core_fp.fp_Calculate_CRC_with_AP = himax_mcu_Calculate_CRC_with_AP; - g_core_fp.fp_check_CRC = himax_mcu_check_CRC; - g_core_fp.fp_set_reload_cmd = himax_mcu_set_reload_cmd; - g_core_fp.fp_program_reload = himax_mcu_program_reload; -#if defined(HX_ULTRA_LOW_POWER) - g_core_fp.fp_ulpm_in = himax_mcu_ulpm_in; - g_core_fp.fp_black_gest_ctrl = himax_mcu_black_gest_ctrl; -#endif - g_core_fp.fp_set_SMWP_enable = himax_mcu_set_SMWP_enable; - g_core_fp.fp_set_HSEN_enable = himax_mcu_set_HSEN_enable; - g_core_fp.fp_usb_detect_set = himax_mcu_usb_detect_set; - g_core_fp.fp_diag_register_set = himax_mcu_diag_register_set; - g_core_fp.fp_chip_self_test = himax_mcu_chip_self_test; - g_core_fp.fp_idle_mode = himax_mcu_idle_mode; - g_core_fp.fp_reload_disable = himax_mcu_reload_disable; - g_core_fp.fp_check_chip_version = himax_mcu_check_chip_version; - g_core_fp.fp_read_ic_trigger_type = himax_mcu_read_ic_trigger_type; - g_core_fp.fp_read_i2c_status = himax_mcu_read_i2c_status; - g_core_fp.fp_read_FW_ver = himax_mcu_read_FW_ver; - g_core_fp.fp_read_event_stack = himax_mcu_read_event_stack; - g_core_fp.fp_return_event_stack = himax_mcu_return_event_stack; - g_core_fp.fp_calculateChecksum = himax_mcu_calculateChecksum; - g_core_fp.fp_read_FW_status = himax_mcu_read_FW_status; - g_core_fp.fp_irq_switch = himax_mcu_irq_switch; - g_core_fp.fp_assign_sorting_mode = himax_mcu_assign_sorting_mode; - g_core_fp.fp_check_sorting_mode = himax_mcu_check_sorting_mode; - g_core_fp.fp_read_DD_status = himax_mcu_read_DD_status; -#if defined(HX_AUTO_UPDATE_FW) - g_core_fp._diff_overlay_bin = hx_mcu_diff_overlay_bin; -#endif -/* CORE_FW */ -/* CORE_FLASH */ - g_core_fp.fp_chip_erase = himax_mcu_chip_erase; - g_core_fp.fp_block_erase = himax_mcu_block_erase; - g_core_fp.fp_sector_erase = himax_mcu_sector_erase; - g_core_fp.fp_flash_programming = himax_mcu_flash_programming; - g_core_fp.fp_flash_page_write = himax_mcu_flash_page_write; - g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k = - himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_32k; - g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k = - himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_60k; - g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k = - himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_64k; - g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k = - himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_124k; - g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k = - himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_128k; - g_core_fp.fp_flash_dump_func = himax_mcu_flash_dump_func; - g_core_fp.fp_flash_lastdata_check = himax_mcu_flash_lastdata_check; - g_core_fp._diff_overlay_flash = hx_mcu_diff_overlay_flash; -/* CORE_FLASH */ -/* CORE_SRAM */ - g_core_fp.fp_sram_write = himax_mcu_sram_write; - g_core_fp.fp_sram_verify = himax_mcu_sram_verify; - g_core_fp.fp_get_DSRAM_data = himax_mcu_get_DSRAM_data; -/* CORE_SRAM */ -/* CORE_DRIVER */ - g_core_fp.fp_chip_init = himax_mcu_init_ic; -#if defined(HX_AUTO_UPDATE_FW) - g_core_fp.fp_fw_ver_bin = himax_mcu_fw_ver_bin; -#endif -#if defined(HX_RST_PIN_FUNC) - g_core_fp.fp_pin_reset = himax_mcu_pin_reset; - g_core_fp.fp_ic_reset = himax_mcu_ic_reset; -#endif - g_core_fp.fp_touch_information = himax_mcu_touch_information; - g_core_fp.fp_reload_config = himax_mcu_reload_config; - g_core_fp.fp_get_touch_data_size = himax_mcu_get_touch_data_size; - g_core_fp.fp_hand_shaking = himax_mcu_hand_shaking; - g_core_fp.fp_determin_diag_rawdata = himax_mcu_determin_diag_rawdata; - g_core_fp.fp_determin_diag_storage = himax_mcu_determin_diag_storage; - g_core_fp.fp_cal_data_len = himax_mcu_cal_data_len; - g_core_fp.fp_diag_check_sum = himax_mcu_diag_check_sum; - g_core_fp.fp_diag_parse_raw_data = himax_mcu_diag_parse_raw_data; -#if defined(HX_ESD_RECOVERY) - g_core_fp.fp_ic_esd_recovery = himax_mcu_ic_esd_recovery; - g_core_fp.fp_esd_ic_reset = himax_mcu_esd_ic_reset; -#endif -#if defined(HX_SMART_WAKEUP)\ - || defined(HX_HIGH_SENSE)\ - || defined(HX_USB_DETECT_GLOBAL) - g_core_fp.fp_resend_cmd_func = himax_mcu_resend_cmd_func; -#endif -#if defined(HX_TP_PROC_GUEST_INFO) - g_core_fp.guest_info_get_status = himax_guest_info_get_status; - g_core_fp.read_guest_info = hx_read_guest_info; -#endif -/* CORE_DRIVER */ -#if defined(HX_ZERO_FLASH) - g_core_fp.fp_reload_disable = hx_dis_rload_0f; - g_core_fp.fp_clean_sram_0f = himax_mcu_clean_sram_0f; - g_core_fp.fp_write_sram_0f = himax_mcu_write_sram_0f; - g_core_fp.fp_write_sram_0f_crc = himax_sram_write_crc_check; - g_core_fp.fp_firmware_update_0f = himax_mcu_firmware_update_0f; - g_core_fp.fp_0f_operation = himax_mcu_0f_operation; - g_core_fp.fp_0f_operation_dirly = himax_mcu_0f_operation_dirly; - g_core_fp.fp_0f_op_file_dirly = hx_0f_op_file_dirly; - g_core_fp.fp_0f_esd_check = himax_mcu_0f_esd_check; -#if defined(HX_0F_DEBUG) - g_core_fp.fp_read_sram_0f = himax_mcu_read_sram_0f; - g_core_fp.fp_read_all_sram = himax_mcu_read_all_sram; - g_core_fp.fp_firmware_read_0f = himax_mcu_firmware_read_0f; - g_core_fp.fp_0f_operation_check = himax_mcu_0f_operation_check; -#endif -#if defined(HX_CODE_OVERLAY) - g_core_fp.fp_0f_overlay = himax_mcu_0f_overlay; -#endif -#endif -} - -int himax_mcu_in_cmd_struct_init(void) -{ - int err = 0; - - I("%s: Entering!\n", __func__); - himax_mcu_cmd_struct_free = himax_mcu_in_cmd_struct_free; - - g_core_cmd_op = kzalloc(sizeof(struct himax_core_command_operation), - GFP_KERNEL); - if (g_core_cmd_op == NULL) { - err = -ENOMEM; - goto err_g_core_cmd_op_fail; - } - - g_core_cmd_op->ic_op = kzalloc(sizeof(struct ic_operation), GFP_KERNEL); - if (g_core_cmd_op->ic_op == NULL) { - err = -ENOMEM; - goto err_g_core_cmd_op_ic_op_fail; - } - - g_core_cmd_op->fw_op = kzalloc(sizeof(struct fw_operation), GFP_KERNEL); - if (g_core_cmd_op->fw_op == NULL) { - err = -ENOMEM; - goto err_g_core_cmd_op_fw_op_fail; - } - - g_core_cmd_op->flash_op = kzalloc(sizeof(struct flash_operation), - GFP_KERNEL); - if (g_core_cmd_op->flash_op == NULL) { - err = -ENOMEM; - goto err_g_core_cmd_op_flash_op_fail; - } - - g_core_cmd_op->sram_op = kzalloc(sizeof(struct sram_operation), - GFP_KERNEL); - if (g_core_cmd_op->sram_op == NULL) { - err = -ENOMEM; - goto err_g_core_cmd_op_sram_op_fail; - } - - g_core_cmd_op->driver_op = kzalloc(sizeof(struct driver_operation), - GFP_KERNEL); - if (g_core_cmd_op->driver_op == NULL) { - err = -ENOMEM; - goto err_g_core_cmd_op_driver_op_fail; - } - - pic_op = g_core_cmd_op->ic_op; - pfw_op = g_core_cmd_op->fw_op; - pflash_op = g_core_cmd_op->flash_op; - psram_op = g_core_cmd_op->sram_op; - pdriver_op = g_core_cmd_op->driver_op; -#if defined(HX_ZERO_FLASH) - g_core_cmd_op->zf_op = kzalloc(sizeof(struct zf_operation), - GFP_KERNEL); - if (g_core_cmd_op->zf_op == NULL) { - err = -ENOMEM; - goto err_g_core_cmd_op_zf_op_fail; - } - pzf_op = g_core_cmd_op->zf_op; - -#endif - - g_internal_buffer = kzalloc(sizeof(uint8_t)*HX_MAX_WRITE_SZ, - GFP_KERNEL); - - if (g_internal_buffer == NULL) { - err = -ENOMEM; - goto err_g_core_cmd_op_g_internal_buffer_fail; - } - himax_mcu_fp_init(); - - return NO_ERR; - -err_g_core_cmd_op_g_internal_buffer_fail: -#if defined(HX_ZERO_FLASH) - kfree(g_core_cmd_op->zf_op); - g_core_cmd_op->zf_op = NULL; -err_g_core_cmd_op_zf_op_fail: -#endif - kfree(g_core_cmd_op->driver_op); - g_core_cmd_op->driver_op = NULL; -err_g_core_cmd_op_driver_op_fail: - kfree(g_core_cmd_op->sram_op); - g_core_cmd_op->sram_op = NULL; -err_g_core_cmd_op_sram_op_fail: - kfree(g_core_cmd_op->flash_op); - g_core_cmd_op->flash_op = NULL; -err_g_core_cmd_op_flash_op_fail: - kfree(g_core_cmd_op->fw_op); - g_core_cmd_op->fw_op = NULL; -err_g_core_cmd_op_fw_op_fail: - kfree(g_core_cmd_op->ic_op); - g_core_cmd_op->ic_op = NULL; -err_g_core_cmd_op_ic_op_fail: - kfree(g_core_cmd_op); - g_core_cmd_op = NULL; -err_g_core_cmd_op_fail: - - return err; -} -EXPORT_SYMBOL(himax_mcu_in_cmd_struct_init); - -void himax_mcu_in_cmd_struct_free(void) -{ - pic_op = NULL; - pfw_op = NULL; - pflash_op = NULL; - psram_op = NULL; - pdriver_op = NULL; - kfree(g_internal_buffer); - g_internal_buffer = NULL; -#if defined(HX_ZERO_FLASH) - kfree(g_core_cmd_op->zf_op); - g_core_cmd_op->zf_op = NULL; -#endif - kfree(g_core_cmd_op->driver_op); - g_core_cmd_op->driver_op = NULL; - kfree(g_core_cmd_op->sram_op); - g_core_cmd_op->sram_op = NULL; - kfree(g_core_cmd_op->flash_op); - g_core_cmd_op->flash_op = NULL; - kfree(g_core_cmd_op->fw_op); - g_core_cmd_op->fw_op = NULL; - kfree(g_core_cmd_op->ic_op); - g_core_cmd_op->ic_op = NULL; - kfree(g_core_cmd_op); - g_core_cmd_op = NULL; - - I("%s: release completed\n", __func__); -} - -void himax_mcu_in_cmd_init(void) -{ - I("%s: Entering!\n", __func__); -/* CORE_IC */ - himax_parse_assign_cmd(ic_adr_ahb_addr_byte_0, - pic_op->addr_ahb_addr_byte_0, - sizeof(pic_op->addr_ahb_addr_byte_0)); - himax_parse_assign_cmd(ic_adr_ahb_rdata_byte_0, - pic_op->addr_ahb_rdata_byte_0, - sizeof(pic_op->addr_ahb_rdata_byte_0)); - himax_parse_assign_cmd(ic_adr_ahb_access_direction, - pic_op->addr_ahb_access_direction, - sizeof(pic_op->addr_ahb_access_direction)); - himax_parse_assign_cmd(ic_adr_conti, pic_op->addr_conti, - sizeof(pic_op->addr_conti)); - himax_parse_assign_cmd(ic_adr_incr4, pic_op->addr_incr4, - sizeof(pic_op->addr_incr4)); - himax_parse_assign_cmd(ic_adr_i2c_psw_lb, pic_op->adr_i2c_psw_lb, - sizeof(pic_op->adr_i2c_psw_lb)); - himax_parse_assign_cmd(ic_adr_i2c_psw_ub, pic_op->adr_i2c_psw_ub, - sizeof(pic_op->adr_i2c_psw_ub)); - himax_parse_assign_cmd(ic_cmd_ahb_access_direction_read, - pic_op->data_ahb_access_direction_read, - sizeof(pic_op->data_ahb_access_direction_read)); - himax_parse_assign_cmd(ic_cmd_conti, pic_op->data_conti, - sizeof(pic_op->data_conti)); - himax_parse_assign_cmd(ic_cmd_incr4, pic_op->data_incr4, - sizeof(pic_op->data_incr4)); - himax_parse_assign_cmd(ic_cmd_i2c_psw_lb, pic_op->data_i2c_psw_lb, - sizeof(pic_op->data_i2c_psw_lb)); - himax_parse_assign_cmd(ic_cmd_i2c_psw_ub, pic_op->data_i2c_psw_ub, - sizeof(pic_op->data_i2c_psw_ub)); - himax_parse_assign_cmd(ic_adr_tcon_on_rst, pic_op->addr_tcon_on_rst, - sizeof(pic_op->addr_tcon_on_rst)); - himax_parse_assign_cmd(ic_addr_adc_on_rst, pic_op->addr_adc_on_rst, - sizeof(pic_op->addr_adc_on_rst)); - himax_parse_assign_cmd(ic_adr_psl, pic_op->addr_psl, - sizeof(pic_op->addr_psl)); - himax_parse_assign_cmd(ic_adr_cs_central_state, - pic_op->addr_cs_central_state, - sizeof(pic_op->addr_cs_central_state)); - himax_parse_assign_cmd(ic_cmd_rst, pic_op->data_rst, - sizeof(pic_op->data_rst)); - himax_parse_assign_cmd(ic_adr_osc_en, pic_op->adr_osc_en, - sizeof(pic_op->adr_osc_en)); - himax_parse_assign_cmd(ic_adr_osc_pw, pic_op->adr_osc_pw, - sizeof(pic_op->adr_osc_pw)); -/* CORE_IC */ -/* CORE_FW */ - himax_parse_assign_cmd(fw_addr_system_reset, - pfw_op->addr_system_reset, - sizeof(pfw_op->addr_system_reset)); - himax_parse_assign_cmd(fw_addr_safe_mode_release_pw, - pfw_op->addr_safe_mode_release_pw, - sizeof(pfw_op->addr_safe_mode_release_pw)); - himax_parse_assign_cmd(fw_addr_ctrl_fw, - pfw_op->addr_ctrl_fw_isr, - sizeof(pfw_op->addr_ctrl_fw_isr)); - himax_parse_assign_cmd(fw_addr_flag_reset_event, - pfw_op->addr_flag_reset_event, - sizeof(pfw_op->addr_flag_reset_event)); - himax_parse_assign_cmd(fw_addr_hsen_enable, - pfw_op->addr_hsen_enable, - sizeof(pfw_op->addr_hsen_enable)); - himax_parse_assign_cmd(fw_addr_smwp_enable, - pfw_op->addr_smwp_enable, - sizeof(pfw_op->addr_smwp_enable)); - himax_parse_assign_cmd(fw_addr_program_reload_from, - pfw_op->addr_program_reload_from, - sizeof(pfw_op->addr_program_reload_from)); - himax_parse_assign_cmd(fw_addr_program_reload_to, - pfw_op->addr_program_reload_to, - sizeof(pfw_op->addr_program_reload_to)); - himax_parse_assign_cmd(fw_addr_program_reload_page_write, - pfw_op->addr_program_reload_page_write, - sizeof(pfw_op->addr_program_reload_page_write)); - himax_parse_assign_cmd(fw_addr_raw_out_sel, - pfw_op->addr_raw_out_sel, - sizeof(pfw_op->addr_raw_out_sel)); - himax_parse_assign_cmd(fw_addr_reload_status, - pfw_op->addr_reload_status, - sizeof(pfw_op->addr_reload_status)); - himax_parse_assign_cmd(fw_addr_reload_crc32_result, - pfw_op->addr_reload_crc32_result, - sizeof(pfw_op->addr_reload_crc32_result)); - himax_parse_assign_cmd(fw_addr_reload_addr_from, - pfw_op->addr_reload_addr_from, - sizeof(pfw_op->addr_reload_addr_from)); - himax_parse_assign_cmd(fw_addr_reload_addr_cmd_beat, - pfw_op->addr_reload_addr_cmd_beat, - sizeof(pfw_op->addr_reload_addr_cmd_beat)); - himax_parse_assign_cmd(fw_addr_selftest_addr_en, - pfw_op->addr_selftest_addr_en, - sizeof(pfw_op->addr_selftest_addr_en)); - himax_parse_assign_cmd(fw_addr_criteria_addr, - pfw_op->addr_criteria_addr, - sizeof(pfw_op->addr_criteria_addr)); - himax_parse_assign_cmd(fw_addr_set_frame_addr, - pfw_op->addr_set_frame_addr, - sizeof(pfw_op->addr_set_frame_addr)); - himax_parse_assign_cmd(fw_addr_selftest_result_addr, - pfw_op->addr_selftest_result_addr, - sizeof(pfw_op->addr_selftest_result_addr)); - himax_parse_assign_cmd(fw_addr_sorting_mode_en, - pfw_op->addr_sorting_mode_en, - sizeof(pfw_op->addr_sorting_mode_en)); - himax_parse_assign_cmd(fw_addr_fw_mode_status, - pfw_op->addr_fw_mode_status, - sizeof(pfw_op->addr_fw_mode_status)); - himax_parse_assign_cmd(fw_addr_icid_addr, - pfw_op->addr_icid_addr, - sizeof(pfw_op->addr_icid_addr)); - himax_parse_assign_cmd(fw_addr_fw_ver_addr, - pfw_op->addr_fw_ver_addr, - sizeof(pfw_op->addr_fw_ver_addr)); - himax_parse_assign_cmd(fw_addr_fw_cfg_addr, - pfw_op->addr_fw_cfg_addr, - sizeof(pfw_op->addr_fw_cfg_addr)); - himax_parse_assign_cmd(fw_addr_fw_vendor_addr, - pfw_op->addr_fw_vendor_addr, - sizeof(pfw_op->addr_fw_vendor_addr)); - himax_parse_assign_cmd(fw_addr_cus_info, - pfw_op->addr_cus_info, - sizeof(pfw_op->addr_cus_info)); - himax_parse_assign_cmd(fw_addr_proj_info, - pfw_op->addr_proj_info, - sizeof(pfw_op->addr_proj_info)); - himax_parse_assign_cmd(fw_addr_fw_state_addr, - pfw_op->addr_fw_state_addr, - sizeof(pfw_op->addr_fw_state_addr)); - himax_parse_assign_cmd(fw_addr_fw_dbg_msg_addr, - pfw_op->addr_fw_dbg_msg_addr, - sizeof(pfw_op->addr_fw_dbg_msg_addr)); - himax_parse_assign_cmd(fw_addr_chk_fw_status, - pfw_op->addr_chk_fw_status, - sizeof(pfw_op->addr_chk_fw_status)); - himax_parse_assign_cmd(fw_addr_dd_handshak_addr, - pfw_op->addr_dd_handshak_addr, - sizeof(pfw_op->addr_dd_handshak_addr)); - himax_parse_assign_cmd(fw_addr_dd_data_addr, - pfw_op->addr_dd_data_addr, - sizeof(pfw_op->addr_dd_data_addr)); - himax_parse_assign_cmd(fw_data_system_reset, - pfw_op->data_system_reset, - sizeof(pfw_op->data_system_reset)); - himax_parse_assign_cmd(fw_data_safe_mode_release_pw_active, - pfw_op->data_safe_mode_release_pw_active, - sizeof(pfw_op->data_safe_mode_release_pw_active)); - himax_parse_assign_cmd(fw_data_clear, - pfw_op->data_clear, - sizeof(pfw_op->data_clear)); - himax_parse_assign_cmd(fw_data_clear, - pfw_op->data_clear, - sizeof(pfw_op->data_clear)); - himax_parse_assign_cmd(fw_data_fw_stop, - pfw_op->data_fw_stop, - sizeof(pfw_op->data_fw_stop)); - himax_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, - pfw_op->data_safe_mode_release_pw_reset, - sizeof(pfw_op->data_safe_mode_release_pw_reset)); - himax_parse_assign_cmd(fw_data_program_reload_start, - pfw_op->data_program_reload_start, - sizeof(pfw_op->data_program_reload_start)); - himax_parse_assign_cmd(fw_data_program_reload_compare, - pfw_op->data_program_reload_compare, - sizeof(pfw_op->data_program_reload_compare)); - himax_parse_assign_cmd(fw_data_program_reload_break, - pfw_op->data_program_reload_break, - sizeof(pfw_op->data_program_reload_break)); - himax_parse_assign_cmd(fw_data_selftest_request, - pfw_op->data_selftest_request, - sizeof(pfw_op->data_selftest_request)); - himax_parse_assign_cmd(fw_data_criteria_aa_top, - pfw_op->data_criteria_aa_top, - sizeof(pfw_op->data_criteria_aa_top)); - himax_parse_assign_cmd(fw_data_criteria_aa_bot, - pfw_op->data_criteria_aa_bot, - sizeof(pfw_op->data_criteria_aa_bot)); - himax_parse_assign_cmd(fw_data_criteria_key_top, - pfw_op->data_criteria_key_top, - sizeof(pfw_op->data_criteria_key_top)); - himax_parse_assign_cmd(fw_data_criteria_key_bot, - pfw_op->data_criteria_key_bot, - sizeof(pfw_op->data_criteria_key_bot)); - himax_parse_assign_cmd(fw_data_criteria_avg_top, - pfw_op->data_criteria_avg_top, - sizeof(pfw_op->data_criteria_avg_top)); - himax_parse_assign_cmd(fw_data_criteria_avg_bot, - pfw_op->data_criteria_avg_bot, - sizeof(pfw_op->data_criteria_avg_bot)); - himax_parse_assign_cmd(fw_data_set_frame, - pfw_op->data_set_frame, - sizeof(pfw_op->data_set_frame)); - himax_parse_assign_cmd(fw_data_selftest_ack_hb, - pfw_op->data_selftest_ack_hb, - sizeof(pfw_op->data_selftest_ack_hb)); - himax_parse_assign_cmd(fw_data_selftest_ack_lb, - pfw_op->data_selftest_ack_lb, - sizeof(pfw_op->data_selftest_ack_lb)); - himax_parse_assign_cmd(fw_data_selftest_pass, - pfw_op->data_selftest_pass, - sizeof(pfw_op->data_selftest_pass)); - himax_parse_assign_cmd(fw_data_normal_cmd, - pfw_op->data_normal_cmd, - sizeof(pfw_op->data_normal_cmd)); - himax_parse_assign_cmd(fw_data_normal_status, - pfw_op->data_normal_status, - sizeof(pfw_op->data_normal_status)); - himax_parse_assign_cmd(fw_data_sorting_cmd, - pfw_op->data_sorting_cmd, - sizeof(pfw_op->data_sorting_cmd)); - himax_parse_assign_cmd(fw_data_sorting_status, - pfw_op->data_sorting_status, - sizeof(pfw_op->data_sorting_status)); - himax_parse_assign_cmd(fw_data_dd_request, - pfw_op->data_dd_request, - sizeof(pfw_op->data_dd_request)); - himax_parse_assign_cmd(fw_data_dd_ack, - pfw_op->data_dd_ack, - sizeof(pfw_op->data_dd_ack)); - himax_parse_assign_cmd(fw_data_idle_dis_pwd, - pfw_op->data_idle_dis_pwd, - sizeof(pfw_op->data_idle_dis_pwd)); - himax_parse_assign_cmd(fw_data_idle_en_pwd, - pfw_op->data_idle_en_pwd, - sizeof(pfw_op->data_idle_en_pwd)); - himax_parse_assign_cmd(fw_data_rawdata_ready_hb, - pfw_op->data_rawdata_ready_hb, - sizeof(pfw_op->data_rawdata_ready_hb)); - himax_parse_assign_cmd(fw_data_rawdata_ready_lb, - pfw_op->data_rawdata_ready_lb, - sizeof(pfw_op->data_rawdata_ready_lb)); - himax_parse_assign_cmd(fw_addr_ahb_addr, - pfw_op->addr_ahb_addr, - sizeof(pfw_op->addr_ahb_addr)); - himax_parse_assign_cmd(fw_data_ahb_dis, - pfw_op->data_ahb_dis, - sizeof(pfw_op->data_ahb_dis)); - himax_parse_assign_cmd(fw_data_ahb_en, - pfw_op->data_ahb_en, - sizeof(pfw_op->data_ahb_en)); - himax_parse_assign_cmd(fw_addr_event_addr, - pfw_op->addr_event_addr, - sizeof(pfw_op->addr_event_addr)); - himax_parse_assign_cmd(fw_usb_detect_addr, - pfw_op->addr_usb_detect, - sizeof(pfw_op->addr_usb_detect)); -#if defined(HX_ULTRA_LOW_POWER) - himax_parse_assign_cmd(fw_addr_ulpm_33, pfw_op->addr_ulpm_33, - sizeof(pfw_op->addr_ulpm_33)); - himax_parse_assign_cmd(fw_addr_ulpm_34, pfw_op->addr_ulpm_34, - sizeof(pfw_op->addr_ulpm_34)); - himax_parse_assign_cmd(fw_data_ulpm_11, pfw_op->data_ulpm_11, - sizeof(pfw_op->data_ulpm_11)); - himax_parse_assign_cmd(fw_data_ulpm_22, pfw_op->data_ulpm_22, - sizeof(pfw_op->data_ulpm_22)); - himax_parse_assign_cmd(fw_data_ulpm_33, pfw_op->data_ulpm_33, - sizeof(pfw_op->data_ulpm_33)); - himax_parse_assign_cmd(fw_data_ulpm_aa, pfw_op->data_ulpm_aa, - sizeof(pfw_op->data_ulpm_aa)); -#endif -/* CORE_FW */ -/* CORE_FLASH */ - himax_parse_assign_cmd(flash_addr_spi200_trans_fmt, - pflash_op->addr_spi200_trans_fmt, - sizeof(pflash_op->addr_spi200_trans_fmt)); - himax_parse_assign_cmd(flash_addr_spi200_trans_ctrl, - pflash_op->addr_spi200_trans_ctrl, - sizeof(pflash_op->addr_spi200_trans_ctrl)); - himax_parse_assign_cmd(flash_addr_spi200_fifo_rst, - pflash_op->addr_spi200_fifo_rst, - sizeof(pflash_op->addr_spi200_fifo_rst)); - himax_parse_assign_cmd(flash_addr_spi200_flash_speed, - pflash_op->addr_spi200_flash_speed, - sizeof(pflash_op->addr_spi200_flash_speed)); - himax_parse_assign_cmd(flash_addr_spi200_rst_status, - pflash_op->addr_spi200_rst_status, - sizeof(pflash_op->addr_spi200_rst_status)); - himax_parse_assign_cmd(flash_addr_spi200_cmd, - pflash_op->addr_spi200_cmd, - sizeof(pflash_op->addr_spi200_cmd)); - himax_parse_assign_cmd(flash_addr_spi200_addr, - pflash_op->addr_spi200_addr, - sizeof(pflash_op->addr_spi200_addr)); - himax_parse_assign_cmd(flash_addr_spi200_data, - pflash_op->addr_spi200_data, - sizeof(pflash_op->addr_spi200_data)); - himax_parse_assign_cmd(flash_addr_spi200_bt_num, - pflash_op->addr_spi200_bt_num, - sizeof(pflash_op->addr_spi200_bt_num)); - himax_parse_assign_cmd(flash_data_spi200_trans_fmt, - pflash_op->data_spi200_trans_fmt, - sizeof(pflash_op->data_spi200_trans_fmt)); - himax_parse_assign_cmd(flash_data_spi200_txfifo_rst, - pflash_op->data_spi200_txfifo_rst, - sizeof(pflash_op->data_spi200_txfifo_rst)); - himax_parse_assign_cmd(flash_data_spi200_rxfifo_rst, - pflash_op->data_spi200_rxfifo_rst, - sizeof(pflash_op->data_spi200_rxfifo_rst)); - himax_parse_assign_cmd(flash_data_spi200_trans_ctrl_1, - pflash_op->data_spi200_trans_ctrl_1, - sizeof(pflash_op->data_spi200_trans_ctrl_1)); - himax_parse_assign_cmd(flash_data_spi200_trans_ctrl_2, - pflash_op->data_spi200_trans_ctrl_2, - sizeof(pflash_op->data_spi200_trans_ctrl_2)); - himax_parse_assign_cmd(flash_data_spi200_trans_ctrl_3, - pflash_op->data_spi200_trans_ctrl_3, - sizeof(pflash_op->data_spi200_trans_ctrl_3)); - himax_parse_assign_cmd(flash_data_spi200_trans_ctrl_4, - pflash_op->data_spi200_trans_ctrl_4, - sizeof(pflash_op->data_spi200_trans_ctrl_4)); - himax_parse_assign_cmd(flash_data_spi200_trans_ctrl_5, - pflash_op->data_spi200_trans_ctrl_5, - sizeof(pflash_op->data_spi200_trans_ctrl_5)); - himax_parse_assign_cmd(flash_data_spi200_trans_ctrl_6, - pflash_op->data_spi200_trans_ctrl_6, - sizeof(pflash_op->data_spi200_trans_ctrl_6)); - himax_parse_assign_cmd(flash_data_spi200_trans_ctrl_7, - pflash_op->data_spi200_trans_ctrl_7, - sizeof(pflash_op->data_spi200_trans_ctrl_7)); - himax_parse_assign_cmd(flash_data_spi200_cmd_1, - pflash_op->data_spi200_cmd_1, - sizeof(pflash_op->data_spi200_cmd_1)); - himax_parse_assign_cmd(flash_data_spi200_cmd_2, - pflash_op->data_spi200_cmd_2, - sizeof(pflash_op->data_spi200_cmd_2)); - himax_parse_assign_cmd(flash_data_spi200_cmd_3, - pflash_op->data_spi200_cmd_3, - sizeof(pflash_op->data_spi200_cmd_3)); - himax_parse_assign_cmd(flash_data_spi200_cmd_4, - pflash_op->data_spi200_cmd_4, - sizeof(pflash_op->data_spi200_cmd_4)); - himax_parse_assign_cmd(flash_data_spi200_cmd_5, - pflash_op->data_spi200_cmd_5, - sizeof(pflash_op->data_spi200_cmd_5)); - himax_parse_assign_cmd(flash_data_spi200_cmd_6, - pflash_op->data_spi200_cmd_6, - sizeof(pflash_op->data_spi200_cmd_6)); - himax_parse_assign_cmd(flash_data_spi200_cmd_7, - pflash_op->data_spi200_cmd_7, - sizeof(pflash_op->data_spi200_cmd_7)); - himax_parse_assign_cmd(flash_data_spi200_cmd_8, - pflash_op->data_spi200_cmd_8, - sizeof(pflash_op->data_spi200_cmd_8)); - himax_parse_assign_cmd(flash_data_spi200_addr, - pflash_op->data_spi200_addr, - sizeof(pflash_op->data_spi200_addr)); -/* CORE_FLASH */ -/* CORE_SRAM */ - /* sram start*/ - himax_parse_assign_cmd(sram_adr_mkey, - psram_op->addr_mkey, - sizeof(psram_op->addr_mkey)); - himax_parse_assign_cmd(sram_adr_rawdata_addr, - psram_op->addr_rawdata_addr, - sizeof(psram_op->addr_rawdata_addr)); - himax_parse_assign_cmd(sram_adr_rawdata_end, - psram_op->addr_rawdata_end, - sizeof(psram_op->addr_rawdata_end)); - himax_parse_assign_cmd(sram_passwrd_start, - psram_op->passwrd_start, - sizeof(psram_op->passwrd_start)); - himax_parse_assign_cmd(sram_passwrd_end, - psram_op->passwrd_end, - sizeof(psram_op->passwrd_end)); - /* sram end*/ -/* CORE_SRAM */ -/* CORE_DRIVER */ - himax_parse_assign_cmd(driver_addr_fw_define_flash_reload, - pdriver_op->addr_fw_define_flash_reload, - sizeof(pdriver_op->addr_fw_define_flash_reload)); - himax_parse_assign_cmd(driver_addr_fw_define_2nd_flash_reload, - pdriver_op->addr_fw_define_2nd_flash_reload, - sizeof(pdriver_op->addr_fw_define_2nd_flash_reload)); - himax_parse_assign_cmd(driver_addr_fw_define_int_is_edge, - pdriver_op->addr_fw_define_int_is_edge, - sizeof(pdriver_op->addr_fw_define_int_is_edge)); - himax_parse_assign_cmd(driver_addr_fw_define_rxnum_txnum_maxpt, - pdriver_op->addr_fw_define_rxnum_txnum_maxpt, - sizeof(pdriver_op->addr_fw_define_rxnum_txnum_maxpt)); - himax_parse_assign_cmd(driver_addr_fw_define_xy_res_enable, - pdriver_op->addr_fw_define_xy_res_enable, - sizeof(pdriver_op->addr_fw_define_xy_res_enable)); - himax_parse_assign_cmd(driver_addr_fw_define_x_y_res, - pdriver_op->addr_fw_define_x_y_res, - sizeof(pdriver_op->addr_fw_define_x_y_res)); - himax_parse_assign_cmd(driver_data_df_rx, - pdriver_op->data_df_rx, - sizeof(pdriver_op->data_df_rx)); - himax_parse_assign_cmd(driver_data_df_tx, - pdriver_op->data_df_tx, - sizeof(pdriver_op->data_df_tx)); - himax_parse_assign_cmd(driver_data_df_pt, - pdriver_op->data_df_pt, - sizeof(pdriver_op->data_df_pt)); - himax_parse_assign_cmd(driver_data_df_x_res, - pdriver_op->data_df_x_res, - sizeof(pdriver_op->data_df_x_res)); - himax_parse_assign_cmd(driver_data_df_y_res, - pdriver_op->data_df_y_res, - sizeof(pdriver_op->data_df_y_res)); - himax_parse_assign_cmd(driver_data_fw_define_flash_reload_dis, - pdriver_op->data_fw_define_flash_reload_dis, - sizeof(pdriver_op->data_fw_define_flash_reload_dis)); - himax_parse_assign_cmd(driver_data_fw_define_flash_reload_en, - pdriver_op->data_fw_define_flash_reload_en, - sizeof(pdriver_op->data_fw_define_flash_reload_en)); - himax_parse_assign_cmd( - driver_data_fw_define_rxnum_txnum_maxpt_sorting, - pdriver_op->data_fw_define_rxnum_txnum_maxpt_sorting, - sizeof(pdriver_op->data_fw_define_rxnum_txnum_maxpt_sorting)); - himax_parse_assign_cmd( - driver_data_fw_define_rxnum_txnum_maxpt_normal, - pdriver_op->data_fw_define_rxnum_txnum_maxpt_normal, - sizeof(pdriver_op->data_fw_define_rxnum_txnum_maxpt_normal)); -/* CORE_DRIVER */ -#if defined(HX_ZERO_FLASH) - himax_parse_assign_cmd(zf_data_dis_flash_reload, - pzf_op->data_dis_flash_reload, - sizeof(pzf_op->data_dis_flash_reload)); - himax_parse_assign_cmd(zf_addr_system_reset, - pzf_op->addr_system_reset, - sizeof(pzf_op->addr_system_reset)); - himax_parse_assign_cmd(zf_data_system_reset, - pzf_op->data_system_reset, - sizeof(pzf_op->data_system_reset)); - himax_parse_assign_cmd(zf_data_sram_start_addr, - pzf_op->data_sram_start_addr, - sizeof(pzf_op->data_sram_start_addr)); - himax_parse_assign_cmd(zf_data_cfg_info, - pzf_op->data_cfg_info, - sizeof(pzf_op->data_cfg_info)); - himax_parse_assign_cmd(zf_data_fw_cfg_1, - pzf_op->data_fw_cfg_1, - sizeof(pzf_op->data_fw_cfg_1)); - himax_parse_assign_cmd(zf_data_fw_cfg_2, - pzf_op->data_fw_cfg_2, - sizeof(pzf_op->data_fw_cfg_2)); - himax_parse_assign_cmd(zf_data_fw_cfg_3, - pzf_op->data_fw_cfg_3, - sizeof(pzf_op->data_fw_cfg_3)); - himax_parse_assign_cmd(zf_data_adc_cfg_1, - pzf_op->data_adc_cfg_1, - sizeof(pzf_op->data_adc_cfg_1)); - himax_parse_assign_cmd(zf_data_adc_cfg_2, - pzf_op->data_adc_cfg_2, - sizeof(pzf_op->data_adc_cfg_2)); - himax_parse_assign_cmd(zf_data_adc_cfg_3, - pzf_op->data_adc_cfg_3, - sizeof(pzf_op->data_adc_cfg_3)); - himax_parse_assign_cmd(zf_data_map_table, - pzf_op->data_map_table, - sizeof(pzf_op->data_map_table)); -/* himax_parse_assign_cmd(zf_data_mode_switch, - * pzf_op->data_mode_switch, - * sizeof(pzf_op->data_mode_switch)); - */ - himax_parse_assign_cmd(zf_addr_sts_chk, - pzf_op->addr_sts_chk, - sizeof(pzf_op->addr_sts_chk)); - himax_parse_assign_cmd(zf_data_activ_sts, - pzf_op->data_activ_sts, - sizeof(pzf_op->data_activ_sts)); - himax_parse_assign_cmd(zf_addr_activ_relod, - pzf_op->addr_activ_relod, - sizeof(pzf_op->addr_activ_relod)); - himax_parse_assign_cmd(zf_data_activ_in, - pzf_op->data_activ_in, - sizeof(pzf_op->data_activ_in)); -#endif -} -EXPORT_SYMBOL(himax_mcu_in_cmd_init); - -/* init end*/ -/* CORE_INIT */ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for incell ic core functions + * + * 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_ic_core.h" + +struct himax_core_command_operation *g_core_cmd_op; +struct ic_operation *pic_op; +EXPORT_SYMBOL(pic_op); + +struct fw_operation *pfw_op; +EXPORT_SYMBOL(pfw_op); + +struct flash_operation *pflash_op; +struct sram_operation *psram_op; +struct driver_operation *pdriver_op; +EXPORT_SYMBOL(pdriver_op); + +#ifdef HX_ZERO_FLASH +struct zf_operation *pzf_op; +EXPORT_SYMBOL(pzf_op); +#if defined(HX_CODE_OVERLAY) && defined(HX83102D) +uint8_t *ovl_idx; +EXPORT_SYMBOL(ovl_idx); +#endif +#endif + +void (*himax_mcu_cmd_struct_free)(void); +static uint8_t *g_internal_buffer; + +#ifdef CORE_IC +/* IC side start*/ +static void himax_mcu_burst_enable(uint8_t auto_add_4_byte) +{ + uint8_t tmp_data[DATA_LEN_4]; + + /*I("%s,Entering\n", __func__);*/ + tmp_data[0] = pic_op->data_conti[0]; + + if (himax_bus_write(pic_op->addr_conti[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + tmp_data[0] = (pic_op->data_incr4[0] | auto_add_4_byte); + + if (himax_bus_write(pic_op->addr_incr4[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } +} + +static int himax_mcu_register_read(uint8_t *read_addr, uint32_t read_length, uint8_t *read_data, uint8_t cfg_flag) +{ + uint8_t tmp_data[DATA_LEN_4]; + int i = 0; + int address = 0; + + /*I("%s,Entering\n",__func__);*/ + + if (cfg_flag == false) { + if (read_length > FLASH_RW_MAX_LEN) { + E("%s: read len over %d!\n", __func__, FLASH_RW_MAX_LEN); + return LENGTH_FAIL; + } + + if (read_length > DATA_LEN_4) + g_core_fp.fp_burst_enable(1); + else + g_core_fp.fp_burst_enable(0); + + address = (read_addr[3] << 24) + (read_addr[2] << 16) + (read_addr[1] << 8) + read_addr[0]; + i = address; + tmp_data[0] = (uint8_t)i; + tmp_data[1] = (uint8_t)(i >> 8); + tmp_data[2] = (uint8_t)(i >> 16); + tmp_data[3] = (uint8_t)(i >> 24); + + if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], tmp_data, DATA_LEN_4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + + tmp_data[0] = pic_op->data_ahb_access_direction_read[0]; + + if (himax_bus_write(pic_op->addr_ahb_access_direction[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + + if (himax_bus_read(pic_op->addr_ahb_rdata_byte_0[0], read_data, read_length, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + + if (read_length > DATA_LEN_4) + g_core_fp.fp_burst_enable(0); + + } else { + if (himax_bus_read(read_addr[0], read_data, read_length, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + } + return NO_ERR; +} + +static int himax_mcu_flash_write_burst_lenth(uint8_t *reg_byte, uint8_t *write_data, uint32_t length) +{ + uint8_t *data_byte; + + if (!g_internal_buffer) { + E("%s: internal buffer not initialized!\n", __func__); + return MEM_ALLOC_FAIL; + } + data_byte = g_internal_buffer; + + memcpy(data_byte, reg_byte, ADDR_LEN_4); /* assign addr 4bytes */ + + memcpy(data_byte + ADDR_LEN_4, write_data, length); /* assign data n bytes */ + + if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], data_byte, length + ADDR_LEN_4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: xfer fail!\n", __func__); + return I2C_FAIL; + } + + return NO_ERR; +} + +static int himax_mcu_register_write(uint8_t *write_addr, uint32_t write_length, uint8_t *write_data, uint8_t cfg_flag) +{ + int address; +#if 1 + uint8_t tmp_addr[4]; + uint8_t *tmp_data; + + int total_read_times = 0; + uint32_t max_bus_size = MAX_I2C_TRANS_SZ; + uint32_t total_size_temp = 0; + int i = 0; +#endif + + /*I("%s,Entering\n", __func__);*/ + if (cfg_flag == 0) { + total_size_temp = write_length; +#ifdef __MTK_SPI__ + if (write_length > (HX_SPI_MTK_MAX_WRITE_SZ - 4)) + max_bus_size = HX_SPI_MTK_MAX_WRITE_SZ - 4; +#else + if (write_length > (PACKET_MAX_SZ - 8)) + max_bus_size = PACKET_MAX_SZ - 8; +#endif + else + max_bus_size = write_length; + + tmp_addr[3] = write_addr[3]; + tmp_addr[2] = write_addr[2]; + tmp_addr[1] = write_addr[1]; + tmp_addr[0] = write_addr[0]; + + if (total_size_temp % max_bus_size == 0) + total_read_times = total_size_temp / max_bus_size; + else + total_read_times = total_size_temp / max_bus_size + 1; + + if (write_length > DATA_LEN_4) + g_core_fp.fp_burst_enable(1); + else + g_core_fp.fp_burst_enable(0); + +#if 1 + for (i = 0; i < (total_read_times); i++) { + /* I("[log]write %d time start!\n", i); + * I("[log]addr[3]=0x%02X, addr[2]=0x%02X, addr[1]=0x%02X, addr[0]=0x%02X!\n", tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + * I("%s, write addr = 0x%02X%02X%02X%02X\n", __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + */ + + if (total_size_temp >= max_bus_size) { + tmp_data = write_data+(i * max_bus_size); + if (himax_mcu_flash_write_burst_lenth(tmp_addr, tmp_data, max_bus_size) < 0) { + I("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + total_size_temp = total_size_temp - max_bus_size; + } else { + tmp_data = write_data+(i * max_bus_size); + /* I("last total_size_temp=%d\n", total_size_temp % max_bus_size); */ + if (himax_mcu_flash_write_burst_lenth(tmp_addr, tmp_data, total_size_temp) < 0) { + I("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + } + + /*I("[log]write %d time end!\n", i);*/ + address = ((i+1) * max_bus_size); + tmp_addr[0] = write_addr[0] + (uint8_t) ((address) & 0x00FF); + + if (tmp_addr[0] < write_addr[0]) + tmp_addr[1] = write_addr[1] + (uint8_t) ((address>>8) & 0x00FF) + 1; + else + tmp_addr[1] = write_addr[1] + (uint8_t) ((address>>8) & 0x00FF); + + udelay(100); + } +#else + if (himax_mcu_flash_write_burst_lenth(write_addr, write_data, write_length) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } +#endif + + } else if (cfg_flag == 1) { + if (himax_bus_write(write_addr[0], write_data, write_length, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + } else + E("%s: cfg_flag = %d, value is wrong!\n", __func__, cfg_flag); + + return NO_ERR; +} + +static int himax_write_read_reg(uint8_t *tmp_addr, uint8_t *tmp_data, uint8_t hb, uint8_t lb) +{ + int cnt = 0; + + do { + g_core_fp.fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, 0); + usleep_range(10000, 11000); + g_core_fp.fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); + /* I("%s:Now tmp_data[0]=0x%02X,[1]=0x%02X,[2]=0x%02X,[3]=0x%02X\n", + * __func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + */ + } while ((tmp_data[1] != hb && tmp_data[0] != lb) && cnt++ < 100); + + if (cnt == 99) + return HX_RW_REG_FAIL; + + I("Now register 0x%08X : high byte=0x%02X,low byte=0x%02X\n", tmp_addr[3], tmp_data[1], tmp_data[0]); + return NO_ERR; +} + +static void himax_mcu_interface_on(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t tmp_data2[DATA_LEN_4]; + int cnt = 0; + + /* Read a dummy register to wake up I2C.*/ + if (himax_bus_read(pic_op->addr_ahb_rdata_byte_0[0], tmp_data, DATA_LEN_4, HIMAX_I2C_RETRY_TIMES) < 0) {/* to knock I2C*/ + E("%s: i2c access fail!\n", __func__); + return; + } + + do { + tmp_data[0] = pic_op->data_conti[0]; + + if (himax_bus_write(pic_op->addr_conti[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + tmp_data[0] = pic_op->data_incr4[0]; + + if (himax_bus_write(pic_op->addr_incr4[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + /*Check cmd*/ + himax_bus_read(pic_op->addr_conti[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES); + himax_bus_read(pic_op->addr_incr4[0], tmp_data2, 1, HIMAX_I2C_RETRY_TIMES); + + if (tmp_data[0] == pic_op->data_conti[0] && tmp_data2[0] == pic_op->data_incr4[0]) + break; + + usleep_range(1000, 1100); + } while (++cnt < 10); + + if (cnt > 0) + I("%s:Polling burst mode: %d times\n", __func__, cnt); +} + +static bool himax_mcu_wait_wip(int Timing) +{ + uint8_t tmp_data[DATA_LEN_4]; + int retry_cnt = 0; + + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_fmt, DATA_LEN_4, pflash_op->data_spi200_trans_fmt, 0); + tmp_data[0] = 0x01; + + do { + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_1, 0); + + g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, DATA_LEN_4, pflash_op->data_spi200_cmd_1, 0); + tmp_data[0] = tmp_data[1] = tmp_data[2] = tmp_data[3] = 0xFF; + g_core_fp.fp_register_read(pflash_op->addr_spi200_data, 4, tmp_data, 0); + + if ((tmp_data[0] & 0x01) == 0x00) + return true; + + retry_cnt++; + + if (tmp_data[0] != 0x00 || tmp_data[1] != 0x00 || tmp_data[2] != 0x00 || tmp_data[3] != 0x00) + I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, buffer[1]=%d, buffer[2]=%d, buffer[3]=%d\n", + __func__, retry_cnt, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + + if (retry_cnt > 100) { + E("%s: Wait wip error!\n", __func__); + return false; + } + + msleep(Timing); + } while ((tmp_data[0] & 0x01) == 0x01); + + return true; +} + +static void himax_mcu_sense_on(uint8_t FlashMode) +{ + uint8_t tmp_data[DATA_LEN_4]; + int retry = 0; + + I("Enter %s\n", __func__); + g_core_fp.fp_interface_on(); + g_core_fp.fp_register_write(pfw_op->addr_ctrl_fw_isr, + sizeof(pfw_op->data_clear), pfw_op->data_clear, 0); + /*msleep(20);*/ + usleep_range(10000, 11000); + if (!FlashMode) { +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + g_core_fp.fp_system_reset(); +#endif + } else { + do { + g_core_fp.fp_register_write(pfw_op->addr_safe_mode_release_pw, + sizeof(pfw_op->data_safe_mode_release_pw_active), pfw_op->data_safe_mode_release_pw_active, 0); + + g_core_fp.fp_register_read(pfw_op->addr_flag_reset_event, DATA_LEN_4, tmp_data, 0); + I("%s:Read status from IC = %X,%X\n", __func__, tmp_data[0], tmp_data[1]); + } while ((tmp_data[1] != 0x01 || tmp_data[0] != 0x00) && retry++ < 5); + + if (retry >= 5) { + E("%s: Fail:\n", __func__); +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + g_core_fp.fp_system_reset(); +#endif + } else { + I("%s:OK and Read status from IC = %X,%X\n", __func__, tmp_data[0], tmp_data[1]); + /* reset code*/ + tmp_data[0] = 0x00; + + if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) + E("%s: i2c access fail!\n", __func__); + + if (himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) + E("%s: i2c access fail!\n", __func__); + + g_core_fp.fp_register_write(pfw_op->addr_safe_mode_release_pw, + sizeof(pfw_op->data_safe_mode_release_pw_reset), pfw_op->data_safe_mode_release_pw_reset, 0); + } + } +} + +static bool himax_mcu_sense_off(bool check_en) +{ + uint8_t cnt = 0; + uint8_t tmp_data[DATA_LEN_4]; + + do { + tmp_data[0] = pic_op->data_i2c_psw_lb[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + tmp_data[0] = pic_op->data_i2c_psw_ub[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + g_core_fp.fp_register_read(pic_op->addr_cs_central_state, ADDR_LEN_4, tmp_data, 0); + I("%s: Check enter_save_mode data[0]=%X\n", __func__, tmp_data[0]); + + if (tmp_data[0] == 0x0C) { + g_core_fp.fp_register_write(pic_op->addr_tcon_on_rst, DATA_LEN_4, pic_op->data_rst, 0); + usleep_range(1000, 1100); + tmp_data[3] = pic_op->data_rst[3]; + tmp_data[2] = pic_op->data_rst[2]; + tmp_data[1] = pic_op->data_rst[1]; + tmp_data[0] = pic_op->data_rst[0] | 0x01; + g_core_fp.fp_register_write(pic_op->addr_tcon_on_rst, DATA_LEN_4, tmp_data, 0); + + g_core_fp.fp_register_write(pic_op->addr_adc_on_rst, DATA_LEN_4, pic_op->data_rst, 0); + usleep_range(1000, 1100); + tmp_data[3] = pic_op->data_rst[3]; + tmp_data[2] = pic_op->data_rst[2]; + tmp_data[1] = pic_op->data_rst[1]; + tmp_data[0] = pic_op->data_rst[0] | 0x01; + g_core_fp.fp_register_write(pic_op->addr_adc_on_rst, DATA_LEN_4, tmp_data, 0); + goto TRUE_END; + } else { + /*msleep(10);*/ +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + g_core_fp.fp_system_reset(); +#endif + } + } while (cnt++ < 15); + + return false; +TRUE_END: + return true; +} + +static void himax_mcu_init_psl(void) /*power saving level*/ +{ + g_core_fp.fp_register_write(pic_op->addr_psl, sizeof(pic_op->data_rst), pic_op->data_rst, 0); + I("%s: power saving level reset OK!\n", __func__); +} + +static void himax_mcu_resume_ic_action(void) +{ + /* Nothing to do */ +} + +static void himax_mcu_suspend_ic_action(void) +{ + /* Nothing to do */ +} + +static void himax_mcu_power_on_init(void) +{ + I("%s:\n", __func__); + g_core_fp.fp_touch_information(); + /*RawOut select initial*/ + g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, sizeof(pfw_op->data_clear), pfw_op->data_clear, 0); + /*DSRAM func initial*/ + g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear); + g_core_fp.fp_sense_on(0x00); +} + +static bool himax_mcu_dd_clk_set(bool enable) +{ + uint8_t data[4] = {0}; + + data[0] = (enable)?1:0; + return (g_core_fp.fp_register_write(pic_op->adr_osc_en, sizeof(pic_op->adr_osc_en), data, 0) == NO_ERR); +} + +static void himax_mcu_dd_reg_en(bool enable) +{ + uint8_t data[4] = {0}; + + g_core_fp.fp_dd_reg_read(0xCB, 8, 1, data, 0); + + if (data[0] != 0x44) { /*need DD Touch PW*/ + data[0] = 0xA5; data[1] = 0x00; + data[2] = 0x00; data[3] = 0x00; + g_core_fp.fp_register_write(pic_op->adr_osc_pw, DATA_LEN_4, data, 0); + data[0] = 0x00; data[1] = 0x55; + data[2] = 0xAA; data[3] = 0x00; + g_core_fp.fp_dd_reg_write(0xEB, 0, 4, data, 0); + } + + data[0] = 0x00; data[1] = 0x83; + data[2] = 0x11; data[3] = 0x2A; + g_core_fp.fp_dd_reg_write(0xB9, 0, 4, data, 0); +} + +static bool himax_mcu_dd_reg_write(uint8_t addr, uint8_t pa_num, int len, uint8_t *data, uint8_t bank) +{ + /*Calculate total write length*/ + uint32_t data_len = (((len + pa_num - 1) / 4 - pa_num / 4) + 1) * 4; + uint8_t tmp_addr[4] = {0}; + uint8_t tmp_data[4] = {0}; + uint32_t chk_idx = 0; + int i = 0; + int ret = -1; + + uint8_t *w_data = NULL; + bool *chk_data = NULL; + + w_data = kcalloc(data_len, sizeof(uint8_t), GFP_KERNEL); + if (w_data == NULL) { + E("%s, Failed to allocate memory\n", __func__); + } + + chk_data = kcalloc(data_len, sizeof(bool), GFP_KERNEL); + if (chk_data == NULL) { + E("%s, Failed to allocate memory\n", __func__); + } + if (!w_data || !chk_data) + goto alloc_error; + + /*put input data*/ + chk_idx = pa_num % 4; + for (i = 0; i < len; i++) { + w_data[chk_idx] = data[i]; + chk_data[chk_idx++] = true; + } + + /*get original data*/ + chk_idx = (pa_num / 4) * 4; + for (i = 0; i < data_len; i++) { + if (!chk_data[i]) { + g_core_fp.fp_dd_reg_read(addr, (uint8_t)(chk_idx + i), 1, tmp_data, bank); + w_data[i] = tmp_data[0]; + chk_data[i] = true; + } + D("%s w_data[%d] = %2X\n", __func__, i, w_data[i]); + } + + tmp_addr[3] = 0x30; + tmp_addr[2] = addr >> 4; + tmp_addr[1] = (addr << 4) | (bank * 4); + tmp_addr[0] = chk_idx; + D("%s Addr = %02X%02X%02X%02X.\n", __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + ret = g_core_fp.fp_register_write(tmp_addr, data_len, w_data, 0); +alloc_error: + if (chk_data) + kfree(chk_data); + if (w_data) + kfree(w_data); + return ret; +} + +static bool himax_mcu_dd_reg_read(uint8_t addr, uint8_t pa_num, int len, uint8_t *data, uint8_t bank) +{ + uint8_t tmp_addr[4] = {0}; + uint8_t tmp_data[4] = {0}; + int i = 0; + + for (i = 0; i < len; i++) { + tmp_addr[3] = 0x30; + tmp_addr[2] = addr >> 4; + tmp_addr[1] = (addr << 4) | (bank * 4); + tmp_addr[0] = pa_num + i; + + if (g_core_fp.fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0)) + goto READ_FAIL; + data[i] = tmp_data[0]; + + D("%s Addr = %02X%02X%02X%02X.data = %2X\n", __func__, + tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0], data[i]); + } + return true; + +READ_FAIL: + E("%s Read DD reg Failed.\n", __func__); + return false; +} + +static bool himax_mcu_ic_id_read(void) +{ + int i = 0; + uint8_t data[4] = {0}; + + g_core_fp.fp_dd_clk_set(true); + g_core_fp.fp_dd_reg_en(true); + + for (i = 0; i < 13; i++) { + data[0] = 0x28 + i; + g_core_fp.fp_dd_reg_write(0xBB, 2, 1, data, 0); + data[0] = 0x80; + g_core_fp.fp_dd_reg_write(0xBB, 4, 1, data, 0); + data[0] = 0x00; + g_core_fp.fp_dd_reg_write(0xBB, 4, 1, data, 0); + g_core_fp.fp_dd_reg_read(0xBB, 5, 1, data, 0); + ic_data->vendor_ic_id[i] = data[0]; + I("ic_data->vendor_ic_id[%d] = %02X\n", i, ic_data->vendor_ic_id[i]); + } + + g_core_fp.fp_dd_clk_set(false); + + return true; +} + +/* IC side end*/ +#endif + +#ifdef CORE_FW +/* FW side start*/ +static void diag_mcu_parse_raw_data(struct himax_report_data *hx_touch_data, int mul_num, int self_num, uint8_t diag_cmd, int32_t *mutual_data, int32_t *self_data) +{ + int RawDataLen_word; + int index = 0; + int temp1, temp2, i; + + if (hx_touch_data->hx_rawdata_buf[0] == pfw_op->data_rawdata_ready_lb[0] + && hx_touch_data->hx_rawdata_buf[1] == pfw_op->data_rawdata_ready_hb[0] + && hx_touch_data->hx_rawdata_buf[2] > 0 + && hx_touch_data->hx_rawdata_buf[3] == diag_cmd) { + RawDataLen_word = hx_touch_data->rawdata_size / 2; + index = (hx_touch_data->hx_rawdata_buf[2] - 1) * RawDataLen_word; + + /* I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num); + * I("RawDataLen=%d , RawDataLen_word=%d , hx_touch_info_size=%d\n", RawDataLen, RawDataLen_word, hx_touch_info_size); + */ + for (i = 0; i < RawDataLen_word; i++) { + temp1 = index + i; + + if (temp1 < mul_num) { /*mutual*/ + mutual_data[index + i] = ((int8_t)hx_touch_data->hx_rawdata_buf[i * 2 + 4 + 1]) * 256 + hx_touch_data->hx_rawdata_buf[i * 2 + 4]; + } else { /*self*/ + temp1 = i + index; + temp2 = self_num + mul_num; + + if (temp1 >= temp2) + break; + + self_data[i + index - mul_num] = (((int8_t)hx_touch_data->hx_rawdata_buf[i * 2 + 4 + 1]) << 8) + + hx_touch_data->hx_rawdata_buf[i * 2 + 4]; + } + } + } +} + +static void himax_mcu_system_reset(void) +{ +#ifdef HX_SHARP_ENABLE_PON + g_core_fp.fp_register_write(pfw_op->addr_system_reset, sizeof(pfw_op->data_system_reset), pfw_op->data_system_reset, 0); +#else + uint8_t tmp_data[DATA_LEN_4]; + int retry = 0; + + g_core_fp.fp_interface_on(); + g_core_fp.fp_register_write(pfw_op->addr_ctrl_fw_isr, + sizeof(pfw_op->data_clear), pfw_op->data_clear, 0); + do { + /* reset code*/ + /* =========================================== + * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 + * =========================================== + */ + tmp_data[0] = pic_op->data_i2c_psw_lb[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) + E("%s: i2c access fail!\n", __func__); + + /* =========================================== + * I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 + * =========================================== + */ + tmp_data[0] = pic_op->data_i2c_psw_ub[0]; + + if (himax_bus_write(pic_op->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) + E("%s: i2c access fail!\n", __func__); + + /* =========================================== + * I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x00 + * =========================================== + */ + tmp_data[0] = 0x00; + + if (himax_bus_write(pic_op->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) + E("%s: i2c access fail!\n", __func__); + + usleep_range(10000, 11000); + + g_core_fp.fp_register_read(pfw_op->addr_flag_reset_event, DATA_LEN_4, tmp_data, 0); + I("%s:Read status from IC = %X,%X\n", __func__, tmp_data[0], tmp_data[1]); + } while ((tmp_data[1] != 0x02 || tmp_data[0] != 0x00) && retry++ < 5); +#endif +} + +static int himax_mcu_Calculate_CRC_with_AP(unsigned char *FW_content, int CRC_from_FW, int len) +{ + int i, j, length = 0; + int fw_data; + int fw_data_2; + int CRC = 0xFFFFFFFF; + int PolyNomial = 0x82F63B78; + + length = len / 4; + + for (i = 0; i < length; i++) { + fw_data = FW_content[i * 4]; + + for (j = 1; j < 4; j++) { + fw_data_2 = FW_content[i * 4 + j]; + fw_data += (fw_data_2) << (8 * j); + } + CRC = fw_data ^ CRC; + for (j = 0; j < 32; j++) { + if ((CRC % 2) != 0) + CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial; + else + CRC = (((CRC >> 1) & 0x7FFFFFFF)/*& 0x7FFFFFFF*/); + } + } + + return CRC; +} + +static uint32_t himax_mcu_check_CRC(uint8_t *start_addr, int reload_length) +{ + uint32_t result = 0; + uint8_t tmp_data[DATA_LEN_4]; + int cnt = 0, ret = 0; + int length = reload_length / DATA_LEN_4; + + ret = g_core_fp.fp_register_write(pfw_op->addr_reload_addr_from, DATA_LEN_4, start_addr, 0); + if (ret < NO_ERR) { + E("%s: i2c access fail!\n", __func__); + return HW_CRC_FAIL; + } + + tmp_data[3] = 0x00; tmp_data[2] = 0x99; tmp_data[1] = (length >> 8); tmp_data[0] = length; + ret = g_core_fp.fp_register_write(pfw_op->addr_reload_addr_cmd_beat, DATA_LEN_4, tmp_data, 0); + if (ret < NO_ERR) { + E("%s: i2c access fail!\n", __func__); + return HW_CRC_FAIL; + } + cnt = 0; + + do { + ret = g_core_fp.fp_register_read(pfw_op->addr_reload_status, DATA_LEN_4, tmp_data, 0); + if (ret < NO_ERR) { + E("%s: i2c access fail!\n", __func__); + return HW_CRC_FAIL; + } + + if ((tmp_data[0] & 0x01) != 0x01) { + ret = g_core_fp.fp_register_read(pfw_op->addr_reload_crc32_result, DATA_LEN_4, tmp_data, 0); + if (ret < NO_ERR) { + E("%s: i2c access fail!\n", __func__); + return HW_CRC_FAIL; + } + I("%s: tmp_data[3]=%X, tmp_data[2]=%X, tmp_data[1]=%X, tmp_data[0]=%X\n", __func__, tmp_data[3], tmp_data[2], tmp_data[1], tmp_data[0]); + result = ((tmp_data[3] << 24) + (tmp_data[2] << 16) + (tmp_data[1] << 8) + tmp_data[0]); + goto END; + } else { + I("Waiting for HW ready!\n"); + usleep_range(1000, 1100); + } + + } while (cnt++ < 100); +END: + return result; +} + +static void himax_mcu_set_reload_cmd(uint8_t *write_data, int idx, uint32_t cmd_from, uint32_t cmd_to, uint32_t cmd_beat) +{ + int index = idx * 12; + int i; + + for (i = 3; i >= 0; i--) { + write_data[index + i] = (cmd_from >> (8 * i)); + write_data[index + 4 + i] = (cmd_to >> (8 * i)); + write_data[index + 8 + i] = (cmd_beat >> (8 * i)); + } +} + +static bool himax_mcu_program_reload(void) +{ + return true; +} + +#ifdef HX_P_SENSOR +static int himax_mcu_ulpm_in(void) +{ + uint8_t tmp_data[4]; + int rtimes = 0; + + I("%s:entering\n", __func__); + + /* 34 -> 11 */ + do { + if (rtimes > 10) { + I("%s:1/7 retry over 10 times!\n", __func__); + return false; + } + if (himax_bus_write(pfw_op->addr_ulpm_34[0], pfw_op->data_ulpm_11, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi write fail!\n", __func__); + continue; + } + if (himax_bus_read(pfw_op->addr_ulpm_34[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi read fail!\n", __func__); + continue; + } + + I("%s:retry times %d, addr = 0x34, correct 0x11 = current 0x%2.2X\n", __func__, rtimes, tmp_data[0]); + rtimes++; + } while (tmp_data[0] != pfw_op->data_ulpm_11[0]); + + rtimes = 0; + /* 34 -> 11 */ + do { + if (rtimes > 10) { + I("%s:2/7 retry over 10 times!\n", __func__); + return false; + } + if (himax_bus_write(pfw_op->addr_ulpm_34[0], pfw_op->data_ulpm_11, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi write fail!\n", __func__); + continue; + } + if (himax_bus_read(pfw_op->addr_ulpm_34[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi read fail!\n", __func__); + continue; + } + + I("%s:retry times %d, addr = 0x34, correct 0x11 = current 0x%2.2X\n", __func__, rtimes, tmp_data[0]); + rtimes++; + } while (tmp_data[0] != pfw_op->data_ulpm_11[0]); + + /* 33 -> 33 */ + rtimes = 0; + do { + if (rtimes > 10) { + I("%s:3/7 retry over 10 times!\n", __func__); + return false; + } + if (himax_bus_write(pfw_op->addr_ulpm_33[0], pfw_op->data_ulpm_33, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi write fail!\n", __func__); + continue; + } + if (himax_bus_read(pfw_op->addr_ulpm_33[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi read fail!\n", __func__); + continue; + } + + I("%s:retry times %d, addr = 0x33, correct 0x33 = current 0x%2.2X\n", __func__, rtimes, tmp_data[0]); + rtimes++; + } while (tmp_data[0] != pfw_op->data_ulpm_33[0]); + + /* 34 -> 22 */ + rtimes = 0; + do { + if (rtimes > 10) { + I("%s:4/7 retry over 10 times!\n", __func__); + return false; + } + if (himax_bus_write(pfw_op->addr_ulpm_34[0], pfw_op->data_ulpm_22, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi write fail!\n", __func__); + continue; + } + if (himax_bus_read(pfw_op->addr_ulpm_34[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi read fail!\n", __func__); + continue; + } + + I("%s:retry times %d, addr = 0x34, correct 0x22 = current 0x%2.2X\n", __func__, rtimes, tmp_data[0]); + rtimes++; + } while (tmp_data[0] != pfw_op->data_ulpm_22[0]); + + /* 33 -> AA */ + rtimes = 0; + do { + if (rtimes > 10) { + I("%s:5/7 retry over 10 times!\n", __func__); + return false; + } + if (himax_bus_write(pfw_op->addr_ulpm_33[0], pfw_op->data_ulpm_aa, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi write fail!\n", __func__); + continue; + } + if (himax_bus_read(pfw_op->addr_ulpm_33[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi read fail!\n", __func__); + continue; + } + + I("%s:retry times %d, addr = 0x33, correct 0xAA = current 0x%2.2X\n", __func__, rtimes, tmp_data[0]); + rtimes++; + } while (tmp_data[0] != pfw_op->data_ulpm_aa[0]); + + /* 33 -> 33 */ + rtimes = 0; + do { + if (rtimes > 10) { + I("%s:6/7 retry over 10 times!\n", __func__); + return false; + } + if (himax_bus_write(pfw_op->addr_ulpm_33[0], pfw_op->data_ulpm_33, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi write fail!\n", __func__); + continue; + } + if (himax_bus_read(pfw_op->addr_ulpm_33[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi read fail!\n", __func__); + continue; + } + + I("%s:retry times %d, addr = 0x33, correct 0x33 = current 0x%2.2X\n", __func__, rtimes, tmp_data[0]); + rtimes++; + } while (tmp_data[0] != pfw_op->data_ulpm_33[0]); + + /* 33 -> AA */ + rtimes = 0; + do { + if (rtimes > 10) { + I("%s:7/7 retry over 10 times!\n", __func__); + return false; + } + if (himax_bus_write(pfw_op->addr_ulpm_33[0], pfw_op->data_ulpm_aa, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi write fail!\n", __func__); + continue; + } + if (himax_bus_read(pfw_op->addr_ulpm_33[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + I("%s: spi read fail!\n", __func__); + continue; + } + + I("%s:retry times %d, addr = 0x33, correct 0xAA = current 0x%2.2X\n", __func__, rtimes, tmp_data[0]); + rtimes++; + } while (tmp_data[0] != pfw_op->data_ulpm_aa[0]); + + I("%s:END\n", __func__); + return true; +} + +static int himax_mcu_black_gest_ctrl(bool enable) +{ + int ret = 0; + + I("%s:enable=%d, ts->is_suspended=%d\n", __func__, enable, private_ts->suspended); + + if (private_ts->suspended) { + if (enable) { +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + I("%s: Please enable TP reset define\n", __func__); +#endif + } else { + g_core_fp.fp_ulpm_in(); + } + } else { + g_core_fp.fp_sense_on(0); + } + return ret; +} +#endif + +static void himax_mcu_set_SMWP_enable(uint8_t SMWP_enable, bool suspended) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t back_data[DATA_LEN_4]; + uint8_t retry_cnt = 0; + + do { + if (SMWP_enable) { + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_smwp_enable, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, back_data, 4); + } else { + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_smwp_enable, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, back_data, 4); + } + + g_core_fp.fp_register_read(pfw_op->addr_smwp_enable, DATA_LEN_4, tmp_data, 0); + /*I("%s: tmp_data[0]=%d, SMWP_enable=%d, retry_cnt=%d\n", __func__, tmp_data[0],SMWP_enable,retry_cnt);*/ + retry_cnt++; + } while ((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0]) && retry_cnt < HIMAX_REG_RETRY_TIMES); +} + +#ifdef HX_EDGE_LIMIT +static void himax_mcu_set_edge_limit_enable(uint8_t edge_limit_enable, bool suspended) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t back_data[DATA_LEN_4]; + uint8_t retry_cnt = 0; + + do { + if (edge_limit_enable == 0x01) {/*Portrait*/ + himax_in_parse_assign_cmd(fw_func_edge_portrait_pwd, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_edge_limit_enable, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_func_edge_portrait_pwd, back_data, 4); + } else if (edge_limit_enable == 0x02) {/*Landscape-Right*/ + himax_in_parse_assign_cmd(fw_func_edge_lsp_right_pwd, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_edge_limit_enable, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_func_edge_lsp_right_pwd, back_data, 4); + } else if (edge_limit_enable == 0x03) {/*Landscape-Left*/ + himax_in_parse_assign_cmd(fw_func_edge_lsp_left_pwd, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_edge_limit_enable, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_func_edge_lsp_left_pwd, back_data, 4); + } else { + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_edge_limit_enable, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, back_data, 4); + } + + g_core_fp.fp_register_read(pfw_op->addr_edge_limit_enable, DATA_LEN_4, tmp_data, 0); + I("%s: tmp_data[0]=%d, SMWP_enable=%d, retry_cnt=%d \n", __func__, tmp_data[0], edge_limit_enable, retry_cnt); + retry_cnt++; + } while ((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0]) && retry_cnt < HIMAX_REG_RETRY_TIMES); +} +#endif + +static void himax_mcu_set_HSEN_enable(uint8_t HSEN_enable, bool suspended) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t back_data[DATA_LEN_4]; + uint8_t retry_cnt = 0; + + do { + if (HSEN_enable) { + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_hsen_enable, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, back_data, 4); + } else { + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_hsen_enable, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, back_data, 4); + } + + g_core_fp.fp_register_read(pfw_op->addr_hsen_enable, DATA_LEN_4, tmp_data, 0); + /*I("%s: tmp_data[0]=%d, HSEN_enable=%d, retry_cnt=%d\n", __func__, tmp_data[0],HSEN_enable,retry_cnt);*/ + retry_cnt++; + } while ((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0]) && retry_cnt < HIMAX_REG_RETRY_TIMES); +} + +static void himax_mcu_usb_detect_set(uint8_t *cable_config) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t back_data[DATA_LEN_4]; + uint8_t retry_cnt = 0; + + do { + if (cable_config[1] == 0x01) { + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_usb_detect, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_func_handshaking_pwd, back_data, 4); + I("%s: USB detect status IN!\n", __func__); + } else { + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + g_core_fp.fp_register_write(pfw_op->addr_usb_detect, DATA_LEN_4, tmp_data, 0); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, back_data, 4); + I("%s: USB detect status OUT!\n", __func__); + } + + g_core_fp.fp_register_read(pfw_op->addr_usb_detect, DATA_LEN_4, tmp_data, 0); + /*I("%s: tmp_data[0]=%d, USB detect=%d, retry_cnt=%d\n", __func__, tmp_data[0],cable_config[1] ,retry_cnt);*/ + retry_cnt++; + } while ((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0]) && retry_cnt < HIMAX_REG_RETRY_TIMES); +} + +static void himax_mcu_diag_register_set(uint8_t diag_command, uint8_t storage_type) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t back_data[DATA_LEN_4]; + uint8_t cnt = 50; + + if (diag_command > 0 && storage_type % 8 > 0) + tmp_data[0] = diag_command + 0x08; + else + tmp_data[0] = diag_command; + I("diag_command = %d, tmp_data[0] = %X\n", diag_command, tmp_data[0]); + g_core_fp.fp_interface_on(); + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; + do { + g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, DATA_LEN_4, tmp_data, 0); + g_core_fp.fp_register_read(pfw_op->addr_raw_out_sel, DATA_LEN_4, back_data, 0); + I("%s: back_data[3]=0x%02X,back_data[2]=0x%02X,back_data[1]=0x%02X,back_data[0]=0x%02X!\n", + __func__, back_data[3], back_data[2], back_data[1], back_data[0]); + cnt--; + } while (tmp_data[0] != back_data[0] && cnt > 0); +} + +static int himax_mcu_chip_self_test(void) +{ + uint8_t tmp_data[FLASH_WRITE_BURST_SZ]; + uint8_t self_test_info[20]; + int pf_value = 0x00; + uint8_t test_result_id = 0; + int i; + + memset(tmp_data, 0x00, sizeof(tmp_data)); + g_core_fp.fp_interface_on(); + g_core_fp.fp_sense_off(true); + g_core_fp.fp_burst_enable(1); + g_core_fp.fp_register_write(pfw_op->addr_selftest_addr_en, DATA_LEN_4, pfw_op->data_selftest_request, 0); + /*Set criteria 0x10007F1C [0,1]=aa/up,down=, [2-3]=key/up,down, [4-5]=avg/up,down*/ + tmp_data[0] = pfw_op->data_criteria_aa_top[0]; + tmp_data[1] = pfw_op->data_criteria_aa_bot[0]; + tmp_data[2] = pfw_op->data_criteria_key_top[0]; + tmp_data[3] = pfw_op->data_criteria_key_bot[0]; + tmp_data[4] = pfw_op->data_criteria_avg_top[0]; + tmp_data[5] = pfw_op->data_criteria_avg_bot[0]; + tmp_data[6] = 0x00; + tmp_data[7] = 0x00; + g_core_fp.fp_register_write(pfw_op->addr_criteria_addr, FLASH_WRITE_BURST_SZ, tmp_data, 0); + g_core_fp.fp_register_write(pfw_op->addr_set_frame_addr, DATA_LEN_4, pfw_op->data_set_frame, 0); + /*Disable IDLE Mode*/ + g_core_fp.fp_idle_mode(1); + /*Diable Flash Reload*/ + g_core_fp.fp_reload_disable(1); + /*start selftest // leave safe mode*/ + g_core_fp.fp_sense_on(0x01); + + /*Hand shaking*/ + for (i = 0; i < 1000; i++) { + g_core_fp.fp_register_read(pfw_op->addr_selftest_addr_en, 4, tmp_data, 0); + I("%s: tmp_data[0] = 0x%02X,tmp_data[1] = 0x%02X,tmp_data[2] = 0x%02X,tmp_data[3] = 0x%02X, cnt=%d\n", + __func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3], i); + usleep_range(10000, 11000); + + if (tmp_data[1] == pfw_op->data_selftest_ack_hb[0] && tmp_data[0] == pfw_op->data_selftest_ack_lb[0]) { + I("%s Data ready goto moving data\n", __func__); + break; + } + } + + g_core_fp.fp_sense_off(true); + msleep(20); + /* ===================================== + * Read test result ==> bit[2][1][0] = [key][AA][avg] => 0xF = PASS + * ===================================== + */ + g_core_fp.fp_register_read(pfw_op->addr_selftest_result_addr, 20, self_test_info, 0); + test_result_id = self_test_info[0]; + I("%s: check test result, test_result_id=%x, test_result=%x\n", __func__ + , test_result_id, self_test_info[0]); + I("raw top 1 = %d\n", self_test_info[3] * 256 + self_test_info[2]); + I("raw top 2 = %d\n", self_test_info[5] * 256 + self_test_info[4]); + I("raw top 3 = %d\n", self_test_info[7] * 256 + self_test_info[6]); + I("raw last 1 = %d\n", self_test_info[9] * 256 + self_test_info[8]); + I("raw last 2 = %d\n", self_test_info[11] * 256 + self_test_info[10]); + I("raw last 3 = %d\n", self_test_info[13] * 256 + self_test_info[12]); + I("raw key 1 = %d\n", self_test_info[15] * 256 + self_test_info[14]); + I("raw key 2 = %d\n", self_test_info[17] * 256 + self_test_info[16]); + I("raw key 3 = %d\n", self_test_info[19] * 256 + self_test_info[18]); + + if (test_result_id == pfw_op->data_selftest_pass[0]) { + I("[Himax]: self-test pass\n"); + pf_value = 0x0; + } else { + E("[Himax]: self-test fail\n"); + /* E("[Himax]: bank_avg = %d, bank_max = %d,%d,%d, bank_min = %d,%d,%d, key = %d,%d,%d\n", + * tmp_data[1],tmp_data[2],tmp_data[3],tmp_data[4],tmp_data[5],tmp_data[6],tmp_data[7], + * tmp_data[8],tmp_data[9],tmp_data[10]); + */ + pf_value = 0x1; + } + + /*Enable IDLE Mode*/ + g_core_fp.fp_idle_mode(0); +#ifndef HX_ZERO_FLASH + /* Enable Flash Reload //recovery*/ + g_core_fp.fp_reload_disable(0); +#endif + g_core_fp.fp_sense_on(0x00); + msleep(120); + return pf_value; +} + +static void himax_mcu_idle_mode(int disable) +{ + int retry = 20; + uint8_t tmp_data[DATA_LEN_4]; + uint8_t switch_cmd = 0x00; + + I("%s:entering\n", __func__); + + do { + I("%s,now %d times!\n", __func__, retry); + g_core_fp.fp_register_read(pfw_op->addr_fw_mode_status, DATA_LEN_4, tmp_data, 0); + + if (disable) + switch_cmd = pfw_op->data_idle_dis_pwd[0]; + else + switch_cmd = pfw_op->data_idle_en_pwd[0]; + + tmp_data[0] = switch_cmd; + g_core_fp.fp_register_write(pfw_op->addr_fw_mode_status, DATA_LEN_4, tmp_data, 0); + g_core_fp.fp_register_read(pfw_op->addr_fw_mode_status, DATA_LEN_4, tmp_data, 0); + I("%s:After turn ON/OFF IDLE Mode [0] = 0x%02X,[1] = 0x%02X,[2] = 0x%02X,[3] = 0x%02X\n", + __func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + retry--; + usleep_range(10000, 11000); + } while ((tmp_data[0] != switch_cmd) && retry > 0); + + I("%s: setting OK!\n", __func__); +} + +static void himax_mcu_reload_disable(int disable) +{ + I("%s:entering\n", __func__); + + if (disable) { /*reload disable*/ + g_core_fp.fp_register_write(pdriver_op->addr_fw_define_flash_reload, DATA_LEN_4, pdriver_op->data_fw_define_flash_reload_dis, 0); + } else { /*reload enable*/ + g_core_fp.fp_register_write(pdriver_op->addr_fw_define_flash_reload, DATA_LEN_4, pdriver_op->data_fw_define_flash_reload_en, 0); + } + + I("%s: setting OK!\n", __func__); +} + +static bool himax_mcu_check_chip_version(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t ret_data = false; + int i = 0; + + for (i = 0; i < 5; i++) { + g_core_fp.fp_register_read(pfw_op->addr_icid_addr, DATA_LEN_4, tmp_data, 0); + I("%s:Read driver IC ID = %X,%X,%X\n", __func__, tmp_data[3], tmp_data[2], tmp_data[1]); + + if ((tmp_data[3] == 0x83) && (tmp_data[2] == 0x10) && (tmp_data[1] == 0x2a)) { + strlcpy(private_ts->chip_name, HX_83102A_SERIES_PWON, 30); + ret_data = true; + goto END; + } else { + ret_data = false; + E("%s:Read driver ID register Fail:\n", __func__); + } + } +END: + return ret_data; +} + +static int himax_mcu_read_ic_trigger_type(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + int trigger_type = false; + + g_core_fp.fp_register_read(pfw_op->addr_trigger_addr, DATA_LEN_4, tmp_data, 0); + + if ((tmp_data[1] & 0x01) == 1) + trigger_type = true; + + return trigger_type; +} + +static int himax_mcu_read_i2c_status(void) +{ + return i2c_error_count; +} + +static void himax_mcu_read_FW_ver(void) +{ + uint8_t data[12]; + uint8_t data_2[DATA_LEN_4]; + int retry = 200; + int reload_status = 0; + + g_core_fp.fp_sense_on(0x00); + + while (reload_status == 0) { + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_flash_reload, DATA_LEN_4, data, 0); + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_2nd_flash_reload, DATA_LEN_4, data_2, 0); + + if ((data[1] == 0x3A && data[0] == 0xA3) + || (data_2[1] == 0x72 && data_2[0] == 0xC0)) { + I("reload OK!\n"); + reload_status = 1; + break; + } else if (retry == 0) { + E("reload 20 times! fail\n"); + E("Maybe NOT have FW in chipset\n"); + E("Maybe Wrong FW in chipset\n"); + ic_data->vendor_panel_ver = 0; + ic_data->vendor_fw_ver = 0; + ic_data->vendor_config_ver = 0; + ic_data->vendor_touch_cfg_ver = 0; + ic_data->vendor_display_cfg_ver = 0; + ic_data->vendor_cid_maj_ver = 0; + ic_data->vendor_cid_min_ver = 0; + goto END; + } else { + retry--; + usleep_range(10000, 11000); + if (retry % 10 == 0) + I("reload fail ,delay 10ms retry=%d\n", retry); + } + } + + I("%s : data[0]=0x%2.2X,data[1]=0x%2.2X,data_2[0]=0x%2.2X,data_2[1]=0x%2.2X\n", __func__, data[0], data[1], data_2[0], data_2[1]); + I("reload_status=%d\n", reload_status); + /* ===================================== + * Read FW version + * ===================================== + */ + g_core_fp.fp_sense_off(true); + g_core_fp.fp_register_read(pfw_op->addr_fw_ver_addr, DATA_LEN_4, data, 0); + ic_data->vendor_panel_ver = data[0]; + ic_data->vendor_fw_ver = data[1] << 8 | data[2]; + I("PANEL_VER : %X\n", ic_data->vendor_panel_ver); + I("FW_VER : %X\n", ic_data->vendor_fw_ver); + g_core_fp.fp_register_read(pfw_op->addr_fw_cfg_addr, DATA_LEN_4, data, 0); + ic_data->vendor_config_ver = data[2] << 8 | data[3]; + /*I("CFG_VER : %X\n",ic_data->vendor_config_ver);*/ + ic_data->vendor_touch_cfg_ver = data[2]; + I("TOUCH_VER : %X\n", ic_data->vendor_touch_cfg_ver); + ic_data->vendor_display_cfg_ver = data[3]; + I("DISPLAY_VER : %X\n", ic_data->vendor_display_cfg_ver); + g_core_fp.fp_register_read(pfw_op->addr_fw_vendor_addr, DATA_LEN_4, data, 0); + ic_data->vendor_cid_maj_ver = data[2]; + ic_data->vendor_cid_min_ver = data[3]; + I("CID_VER : %X\n", (ic_data->vendor_cid_maj_ver << 8 | ic_data->vendor_cid_min_ver)); + g_core_fp.fp_register_read(pfw_op->addr_cus_info, 12, data, 0); + memcpy(ic_data->vendor_cus_info, data, 12); + I("Cusomer ID = %s\n", ic_data->vendor_cus_info); + g_core_fp.fp_register_read(pfw_op->addr_proj_info, 12, data, 0); + memcpy(ic_data->vendor_proj_info, data, 12); + I("Project ID = %s\n", ic_data->vendor_proj_info); + +END: + return; +} + +static bool himax_mcu_read_event_stack(uint8_t *buf, uint8_t length) +{ + uint8_t cmd[DATA_LEN_4]; + struct timespec t_start, t_end, t_delta; + int len = length; + int i2c_speed = 0; + + /* AHB_I2C Burst Read Off */ + cmd[0] = pfw_op->data_ahb_dis[0]; + + if (himax_bus_write(pfw_op->addr_ahb_addr[0], cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return 0; + } + if (private_ts->debug_log_level & BIT(2)) + getnstimeofday(&t_start); + + himax_bus_read(pfw_op->addr_event_addr[0], buf, length, HIMAX_I2C_RETRY_TIMES); + + if (private_ts->debug_log_level & BIT(2)) { + getnstimeofday(&t_end); + t_delta.tv_nsec = (t_end.tv_sec * 1000000000 + t_end.tv_nsec) - (t_start.tv_sec * 1000000000 + t_start.tv_nsec); /*ns*/ + i2c_speed = (len * 9 * 1000000 / (int)t_delta.tv_nsec) * 13 / 10; + private_ts->bus_speed = (int)i2c_speed; + } + + /* AHB_I2C Burst Read On */ + cmd[0] = pfw_op->data_ahb_en[0]; + + if (himax_bus_write(pfw_op->addr_ahb_addr[0], cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return 0; + } + + return 1; +} + +static void himax_mcu_return_event_stack(void) +{ + int retry = 20, i; + uint8_t tmp_data[DATA_LEN_4]; + + I("%s:entering\n", __func__); + + do { + I("now %d times!\n", retry); + + for (i = 0; i < DATA_LEN_4; i++) + tmp_data[i] = psram_op->addr_rawdata_end[i]; + + g_core_fp.fp_register_write(psram_op->addr_rawdata_addr, DATA_LEN_4, tmp_data, 0); + g_core_fp.fp_register_read(psram_op->addr_rawdata_addr, DATA_LEN_4, tmp_data, 0); + retry--; + usleep_range(10000, 11000); + } while ((tmp_data[1] != psram_op->addr_rawdata_end[1] && tmp_data[0] != psram_op->addr_rawdata_end[0]) && retry > 0); + + I("%s: End of setting!\n", __func__); +} + +static bool himax_mcu_calculateChecksum(bool change_iref, uint32_t size) +{ + uint8_t CRC_result = 0, i; + uint8_t tmp_data[DATA_LEN_4]; + + I("%s:Now size=%d\n", __func__, size); + for (i = 0; i < DATA_LEN_4; i++) + tmp_data[i] = psram_op->addr_rawdata_end[i]; + + CRC_result = g_core_fp.fp_check_CRC(tmp_data, size); + msleep(50); + + if (CRC_result != 0) + I("%s: CRC Fail=%d\n", __func__, CRC_result); + + return (CRC_result == 0) ? true : false; +} + +static int himax_mcu_read_FW_status(uint8_t *state_addr, uint8_t *tmp_addr) +{ + uint8_t i; + uint8_t req_size = 0; + uint8_t status_addr[DATA_LEN_4]; + uint8_t cmd_addr[DATA_LEN_4]; + + if (state_addr[0] == 0x01) { + state_addr[1] = 0x04; + + for (i = 0; i < DATA_LEN_4; i++) { + state_addr[i + 2] = pfw_op->addr_fw_dbg_msg_addr[i]; + status_addr[i] = pfw_op->addr_fw_dbg_msg_addr[i]; + } + + req_size = 0x04; + g_core_fp.fp_register_read(status_addr, req_size, tmp_addr, 0); + } else if (state_addr[0] == 0x02) { + state_addr[1] = 0x30; + + for (i = 0; i < DATA_LEN_4; i++) { + state_addr[i + 2] = pfw_op->addr_fw_dbg_msg_addr[i]; + cmd_addr[i] = pfw_op->addr_fw_dbg_msg_addr[i]; + } + + req_size = 0x30; + g_core_fp.fp_register_read(cmd_addr, req_size, tmp_addr, 0); + } + + return NO_ERR; +} + +static void himax_mcu_irq_switch(int switch_on) +{ + if (switch_on) { + if (private_ts->use_irq) + himax_int_enable(switch_on); + else + hrtimer_start(&private_ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + + } else { + if (private_ts->use_irq) + himax_int_enable(switch_on); + else { + hrtimer_cancel(&private_ts->timer); + cancel_work_sync(&private_ts->work); + } + } +} + +static int himax_mcu_assign_sorting_mode(uint8_t *tmp_data) +{ + + I("%s:Now tmp_data[3]=0x%02X,tmp_data[2]=0x%02X,tmp_data[1]=0x%02X,tmp_data[0]=0x%02X\n", __func__, tmp_data[3], tmp_data[2], tmp_data[1], tmp_data[0]); + g_core_fp.fp_register_write(pfw_op->addr_sorting_mode_en, DATA_LEN_4, tmp_data, 0); + + return NO_ERR; +} + +static int himax_mcu_check_sorting_mode(uint8_t *tmp_data) +{ + + g_core_fp.fp_register_read(pfw_op->addr_sorting_mode_en, DATA_LEN_4, tmp_data, 0); + I("%s: tmp_data[0]=%x,tmp_data[1]=%x\n", __func__, tmp_data[0], tmp_data[1]); + + return NO_ERR; +} + +static int himax_mcu_switch_mode(int mode) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t mode_wirte_cmd; + uint8_t mode_read_cmd; + int result = -1; + int retry = 200; + + I("%s: Entering\n", __func__); + + if (mode == 0) { /* normal mode */ + mode_wirte_cmd = pfw_op->data_normal_cmd[0]; + mode_read_cmd = pfw_op->data_normal_status[0]; + } else { /* sorting mode */ + mode_wirte_cmd = pfw_op->data_sorting_cmd[0]; + mode_read_cmd = pfw_op->data_sorting_status[0]; + } + + g_core_fp.fp_sense_off(true); + /*g_core_fp.fp_interface_on();*/ + /* clean up FW status */ + g_core_fp.fp_register_write(psram_op->addr_rawdata_addr, DATA_LEN_4, psram_op->addr_rawdata_end, 0); + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = mode_wirte_cmd; + tmp_data[0] = mode_wirte_cmd; + g_core_fp.fp_assign_sorting_mode(tmp_data); + g_core_fp.fp_idle_mode(1); + g_core_fp.fp_reload_disable(1); + + /* To stable the sorting*/ + if (mode) { + g_core_fp.fp_register_write(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, DATA_LEN_4, pdriver_op->data_fw_define_rxnum_txnum_maxpt_sorting, 0); + } else { + g_core_fp.fp_register_write(pfw_op->addr_set_frame_addr, DATA_LEN_4, pfw_op->data_set_frame, 0); + g_core_fp.fp_register_write(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, DATA_LEN_4, pdriver_op->data_fw_define_rxnum_txnum_maxpt_normal, 0); + } + + g_core_fp.fp_sense_on(0x01); + + while (retry != 0) { + I("[%d] %s Read\n", retry, __func__); + g_core_fp.fp_check_sorting_mode(tmp_data); + msleep(100); + I("mode_read_cmd(0)=0x%2.2X,mode_read_cmd(1)=0x%2.2X\n", tmp_data[0], tmp_data[1]); + + if (tmp_data[0] == mode_read_cmd && tmp_data[1] == mode_read_cmd) { + I("Read OK!\n"); + result = 0; + break; + } + + g_core_fp.fp_register_read(pfw_op->addr_chk_fw_status, DATA_LEN_4, tmp_data, 0); + + if (tmp_data[0] == 0x00 && tmp_data[1] == 0x00 && tmp_data[2] == 0x00 && tmp_data[3] == 0x00) { + E("%s,: FW Stop!\n", __func__); + break; + } + + retry--; + } + + if (result == 0) { + if (mode == 0) { /*normal mode*/ + return HX_NORMAL_MODE; + } else { /*sorting mode*/ + return HX_SORTING_MODE; + } + } else { /*change mode fail*/ + return HX_CHANGE_MODE_FAIL; + } +} + +static int himax_mcu_get_max_dc(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + int dc_max = 0; + + g_core_fp.fp_register_read(pfw_op->addr_max_dc, DATA_LEN_4, tmp_data, 0); + I("%s: tmp_data[0]=%x,tmp_data[1]=%x\n", __func__, tmp_data[0], tmp_data[1]); + + dc_max = tmp_data[1] << 8 | tmp_data[0]; + I("%s: dc max = %d\n", __func__, dc_max); + return dc_max; +} + +static uint8_t himax_mcu_read_DD_status(uint8_t *cmd_set, uint8_t *tmp_data) +{ + int cnt = 0; + uint8_t req_size = cmd_set[0]; + + cmd_set[3] = pfw_op->data_dd_request[0]; + g_core_fp.fp_register_write(pfw_op->addr_dd_handshak_addr, DATA_LEN_4, cmd_set, 0); + I("%s: cmd_set[0] = 0x%02X,cmd_set[1] = 0x%02X,cmd_set[2] = 0x%02X,cmd_set[3] = 0x%02X\n", + __func__, cmd_set[0], cmd_set[1], cmd_set[2], cmd_set[3]); + + /* Doing hand shaking 0xAA -> 0xBB */ + for (cnt = 0; cnt < 100; cnt++) { + g_core_fp.fp_register_read(pfw_op->addr_dd_handshak_addr, DATA_LEN_4, tmp_data, 0); + usleep_range(10000, 11000); + + if (tmp_data[3] == pfw_op->data_dd_ack[0]) { + I("%s Data ready goto moving data\n", __func__); + goto FINALIZE; + } else { + if (cnt >= 99) { + I("%s Data not ready in FW\n", __func__); + return FW_NOT_READY; + } + } + } +FINALIZE: + g_core_fp.fp_register_read(pfw_op->addr_dd_data_addr, req_size, tmp_data, 0); + return NO_ERR; +} +#ifdef HX_AUTO_UPDATE_FW +static int hx_mcu_diff_overlay_bin(void) +{ + int rslt = 0; + int diff_val = 0; + + diff_val = g_i_FW_VER; + I("%s:Now fw ID is 0x%04X\n", __func__, diff_val); + diff_val = (diff_val >> 12); + I("%s:Now diff value=0x%04X\n", __func__, diff_val); + + if (diff_val == 1) + I("%s:Now size should be 128K!\n", __func__); + else + I("%s:Now size should be 64K!\n", __func__); + rslt = diff_val; + return rslt; +} +#endif + +/* FW side end*/ +#endif + +#ifdef CORE_FLASH +/* FLASH side start*/ +static void himax_mcu_chip_erase(void) +{ + g_core_fp.fp_interface_on(); + + /* Reset power saving level */ + if (g_core_fp.fp_init_psl != NULL) + g_core_fp.fp_init_psl(); + + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_fmt, DATA_LEN_4, pflash_op->data_spi200_trans_fmt, 0); + + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_2, 0); + g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, DATA_LEN_4, pflash_op->data_spi200_cmd_2, 0); + + g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, DATA_LEN_4, pflash_op->data_spi200_cmd_3, 0); + msleep(2000); + + if (!g_core_fp.fp_wait_wip(100)) + E("%s: Chip_Erase Fail\n", __func__); + +} + +static bool himax_mcu_block_erase(int start_addr, int length) /*complete not yet*/ +{ + uint32_t page_prog_start = 0; + uint32_t block_size = 0x10000; + + uint8_t tmp_data[4] = {0}; + + g_core_fp.fp_interface_on(); + + g_core_fp.fp_init_psl(); + + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_fmt, DATA_LEN_4, pflash_op->data_spi200_trans_fmt, 0); + + for (page_prog_start = start_addr; page_prog_start < start_addr + length; page_prog_start = page_prog_start + block_size) { + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_2, 0); + g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, DATA_LEN_4, pflash_op->data_spi200_cmd_2, 0); + + tmp_data[3] = (page_prog_start >> 24)&0xFF; + tmp_data[2] = (page_prog_start >> 16)&0xFF; + tmp_data[1] = (page_prog_start >> 8)&0xFF; + tmp_data[0] = page_prog_start&0xFF; + g_core_fp.fp_register_write(pflash_op->addr_spi200_addr, DATA_LEN_4, tmp_data, 0); + + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_3, 0); + g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, DATA_LEN_4, pflash_op->data_spi200_cmd_4, 0); + msleep(1000); + + if (!g_core_fp.fp_wait_wip(100)) { + E("%s:Erase Fail\n", __func__); + return false; + } + } + + I("%s:END\n", __func__); + return true; +} + +static bool himax_mcu_sector_erase(int start_addr) +{ + return true; +} + +static void himax_mcu_flash_programming(uint8_t *FW_content, int FW_Size) +{ + int page_prog_start = 0, i = 0, j = 0, k = 0; + int program_length = PROGRAM_SZ; + uint8_t tmp_data[DATA_LEN_4]; + uint8_t buring_data[FLASH_RW_MAX_LEN]; /* Read for flash data, 128K*/ + /* 4 bytes for padding*/ + g_core_fp.fp_interface_on(); + + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_fmt, DATA_LEN_4, pflash_op->data_spi200_trans_fmt, 0); + + for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start += FLASH_RW_MAX_LEN) { + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_2, 0); + g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, DATA_LEN_4, pflash_op->data_spi200_cmd_2, 0); + + /*Programmable size = 1 page = 256 bytes, word_number = 256 byte / 4 = 64*/ + g_core_fp.fp_register_write(pflash_op->addr_spi200_trans_ctrl, DATA_LEN_4, pflash_op->data_spi200_trans_ctrl_4, 0); + + /* Flash start address 1st : 0x0000_0000*/ + if (page_prog_start < 0x100) { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = (uint8_t)page_prog_start; + } else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) { + tmp_data[3] = 0x00; + tmp_data[2] = (uint8_t)(page_prog_start >> 16); + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } + g_core_fp.fp_register_write(pflash_op->addr_spi200_addr, DATA_LEN_4, tmp_data, 0); + + for (i = 0; i < ADDR_LEN_4; i++) + buring_data[i] = pflash_op->addr_spi200_data[i]; + + + for (i = page_prog_start, j = 0; i < 16 + page_prog_start; i++, j++) + buring_data[j + ADDR_LEN_4] = FW_content[i]; + + + if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], buring_data, ADDR_LEN_4 + 16, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + g_core_fp.fp_register_write(pflash_op->addr_spi200_cmd, DATA_LEN_4, pflash_op->data_spi200_cmd_6, 0); + + for (j = 0; j < 5; j++) { + for (i = (page_prog_start + 16 + (j * 48)), k = 0; i < (page_prog_start + 16 + (j * 48)) + program_length; i++, k++) + buring_data[k + ADDR_LEN_4] = FW_content[i]; + + if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], buring_data, program_length + ADDR_LEN_4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + } + + if (!g_core_fp.fp_wait_wip(1)) + E("%s:Flash_Programming Fail\n", __func__); + + } +} + +static void himax_mcu_flash_page_write(uint8_t *write_addr, int length, uint8_t *write_data) +{ +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_32k(unsigned char *fw, int len, bool change_iref) +{ + /* Not use */ + return 0; +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_60k(unsigned char *fw, int len, bool change_iref) +{ + /* Not use */ + return 0; +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_64k(unsigned char *fw, int len, bool change_iref) +{ + int burnFW_success = 0; + + if (len != FW_SIZE_64k) { + E("%s: The file size is not 64K bytes\n", __func__); + return false; + } + +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + g_core_fp.fp_system_reset(); +#endif + g_core_fp.fp_sense_off(true); + g_core_fp.fp_block_erase(0x00, FW_SIZE_64k); + g_core_fp.fp_flash_programming(fw, FW_SIZE_64k); + + if (g_core_fp.fp_check_CRC(pfw_op->addr_program_reload_from, FW_SIZE_64k) == 0) + burnFW_success = 1; + + /*RawOut select initial*/ + g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, sizeof(pfw_op->data_clear), pfw_op->data_clear, 0); + /*DSRAM func initial*/ + g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear); + +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + /*System reset*/ + g_core_fp.fp_system_reset(); +#endif + return burnFW_success; +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_124k(unsigned char *fw, int len, bool change_iref) +{ + /* Not use */ + return 0; +} + +static int himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_128k(unsigned char *fw, int len, bool change_iref) +{ + int burnFW_success = 0; + + if (len != FW_SIZE_128k) { + E("%s: The file size is not 128K bytes\n", __func__); + return false; + } + +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + g_core_fp.fp_system_reset(); +#endif + g_core_fp.fp_sense_off(true); + g_core_fp.fp_block_erase(0x00, FW_SIZE_128k); + g_core_fp.fp_flash_programming(fw, FW_SIZE_128k); + + if (g_core_fp.fp_check_CRC(pfw_op->addr_program_reload_from, FW_SIZE_128k) == 0) + burnFW_success = 1; + + /*RawOut select initial*/ + g_core_fp.fp_register_write(pfw_op->addr_raw_out_sel, sizeof(pfw_op->data_clear), pfw_op->data_clear, 0); + /*DSRAM func initial*/ + g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear); + +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_ic_reset(false, false); +#else + /*System reset*/ + g_core_fp.fp_system_reset(); +#endif + return burnFW_success; +} + +static void himax_mcu_flash_dump_func(uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer) +{ + uint8_t tmp_addr[DATA_LEN_4]; + uint8_t buffer[256]; + int page_prog_start = 0; + + g_core_fp.fp_sense_off(true); + g_core_fp.fp_burst_enable(1); + + for (page_prog_start = 0; page_prog_start < Flash_Size; page_prog_start += 128) { + tmp_addr[0] = page_prog_start % 0x100; + tmp_addr[1] = (page_prog_start >> 8) % 0x100; + tmp_addr[2] = (page_prog_start >> 16) % 0x100; + tmp_addr[3] = page_prog_start / 0x1000000; + himax_mcu_register_read(tmp_addr, 128, buffer, 0); + memcpy(&flash_buffer[page_prog_start], buffer, 128); + } + + g_core_fp.fp_burst_enable(0); + g_core_fp.fp_sense_on(0x01); +} + +static bool himax_mcu_flash_lastdata_check(uint32_t size) +{ + uint8_t tmp_addr[4]; + uint32_t start_addr = 0xFF80; /* 64K - 0x80, which is the address of the last 128bytes in 64K, default value*/ + uint32_t temp_addr = 0; + uint32_t flash_page_len = 0x80; + uint8_t flash_tmp_buffer[128]; + + start_addr = size - flash_page_len; /* In order to match other size of fw*/ + I("%s: Now size is %d, the start_addr is 0x%04X\n", __func__, size, start_addr); + for (temp_addr = start_addr; temp_addr < (start_addr + flash_page_len); temp_addr = temp_addr + flash_page_len) { + /*I("temp_addr=%d,tmp_addr[0]=0x%2X, tmp_addr[1]=0x%2X,tmp_addr[2]=0x%2X,tmp_addr[3]=0x%2X\n", temp_addr,tmp_addr[0], tmp_addr[1], tmp_addr[2],tmp_addr[3]);*/ + tmp_addr[0] = temp_addr % 0x100; + tmp_addr[1] = (temp_addr >> 8) % 0x100; + tmp_addr[2] = (temp_addr >> 16) % 0x100; + tmp_addr[3] = temp_addr / 0x1000000; + g_core_fp.fp_register_read(tmp_addr, flash_page_len, &flash_tmp_buffer[0], 0); + } + + if ((!flash_tmp_buffer[flash_page_len-4]) && (!flash_tmp_buffer[flash_page_len-3]) && (!flash_tmp_buffer[flash_page_len-2]) && (!flash_tmp_buffer[flash_page_len-1])) { + I("Fail, Last four Bytes are flash_buffer[FFFC]=0x%2X,flash_buffer[FFFD]=0x%2X,flash_buffer[FFFE]=0x%2X,flash_buffer[FFFF]=0x%2X\n", + flash_tmp_buffer[flash_page_len-4], flash_tmp_buffer[flash_page_len-3], flash_tmp_buffer[flash_page_len-2], flash_tmp_buffer[flash_page_len-1]); + goto FAIL;/*FAIL*/ + } else if ((flash_tmp_buffer[flash_page_len-4] == 0xFF) && (flash_tmp_buffer[flash_page_len-3] == 0xFF) && (flash_tmp_buffer[flash_page_len-2] == 0xFF) && (flash_tmp_buffer[flash_page_len-1] == 0xFF)) { + I("Fail, Last four Bytes are flash_buffer[FFFC]=0x%2X,flash_buffer[FFFD]=0x%2X,flash_buffer[FFFE]=0x%2X,flash_buffer[FFFF]=0x%2X\n", + flash_tmp_buffer[flash_page_len-4], flash_tmp_buffer[flash_page_len-3], flash_tmp_buffer[flash_page_len-2], flash_tmp_buffer[flash_page_len-1]); + goto FAIL; + } else { + I("flash_buffer[FFFC]=0x%2X,flash_buffer[FFFD]=0x%2X,flash_buffer[FFFE]=0x%2X,flash_buffer[FFFF]=0x%2X\n", + flash_tmp_buffer[flash_page_len-4], flash_tmp_buffer[flash_page_len-3], flash_tmp_buffer[flash_page_len-2], flash_tmp_buffer[flash_page_len-1]); + return 0;/*PASS*/ + } + return 0; +FAIL: + return 1; +} +static int hx_mcu_diff_overlay_flash(void) +{ + int rslt = 0; + int diff_val = 0; + + diff_val = (ic_data->vendor_fw_ver); + I("%s:Now fw ID is 0x%04X\n", __func__, diff_val); + diff_val = (diff_val >> 12); + I("%s:Now diff value=0x%04X\n", __func__, diff_val); + + if (diff_val == 1) + I("%s:Now size should be 128K!\n", __func__); + else + I("%s:Now size should be 64K!\n", __func__); + rslt = diff_val; + return rslt; +} + +/* FLASH side end*/ +#endif + +#ifdef CORE_SRAM +/* SRAM side start*/ +static void himax_mcu_sram_write(uint8_t *FW_content) +{ +} + +static bool himax_mcu_sram_verify(uint8_t *FW_File, int FW_Size) +{ + return true; +} + +static bool himax_mcu_get_DSRAM_data(uint8_t *info_data, bool DSRAM_Flag) +{ + int i = 0; + unsigned char tmp_addr[ADDR_LEN_4]; + unsigned char tmp_data[DATA_LEN_4]; + uint8_t max_i2c_size = MAX_I2C_TRANS_SZ; + uint8_t x_num = ic_data->HX_RX_NUM; + uint8_t y_num = ic_data->HX_TX_NUM; + /*int m_key_num = 0;*/ + int total_size = (x_num * y_num + x_num + y_num) * 2 + 4; + int total_size_temp; + int mutual_data_size = x_num * y_num * 2; + int total_read_times = 0; + int address = 0; + uint8_t *temp_info_data; /*max mkey size = 8*/ + uint16_t check_sum_cal = 0; + int fw_run_flag = -1; + + temp_info_data = kcalloc((total_size + 8), sizeof(uint8_t), GFP_KERNEL); + /* 1. Read number of MKey R100070E8H to determin data size */ + /* m_key_num = ic_data->HX_BT_NUM; */ + /* I("%s,m_key_num=%d\n",__func__ ,m_key_num); */ + /* total_size += m_key_num * 2; */ + /* 2. Start DSRAM Rawdata and Wait Data Ready */ + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = psram_op->passwrd_start[1]; + tmp_data[0] = psram_op->passwrd_start[0]; + fw_run_flag = himax_write_read_reg(psram_op->addr_rawdata_addr, tmp_data, psram_op->passwrd_end[1], psram_op->passwrd_end[0]); + + if (fw_run_flag < 0) { + I("%s Data NOT ready => bypass\n", __func__); + goto FAIL; + } + + /* 3. Read RawData */ + total_size_temp = total_size; + I("%s: tmp_data[0] = 0x%02X,tmp_data[1] = 0x%02X,tmp_data[2] = 0x%02X,tmp_data[3] = 0x%02X\n", + __func__, psram_op->addr_rawdata_addr[0], psram_op->addr_rawdata_addr[1], psram_op->addr_rawdata_addr[2], psram_op->addr_rawdata_addr[3]); + tmp_addr[0] = psram_op->addr_rawdata_addr[0]; + tmp_addr[1] = psram_op->addr_rawdata_addr[1]; + tmp_addr[2] = psram_op->addr_rawdata_addr[2]; + tmp_addr[3] = psram_op->addr_rawdata_addr[3]; + + if (total_size % max_i2c_size == 0) + total_read_times = total_size / max_i2c_size; + else + total_read_times = total_size / max_i2c_size + 1; + + for (i = 0; i < total_read_times; i++) { + address = (psram_op->addr_rawdata_addr[3] << 24) + + (psram_op->addr_rawdata_addr[2] << 16) + + (psram_op->addr_rawdata_addr[1] << 8) + + psram_op->addr_rawdata_addr[0] + i * max_i2c_size; + /*I("%s address = %08X\n", __func__, address);*/ + + tmp_addr[3] = (uint8_t)((address >> 24) & 0x00FF); + tmp_addr[2] = (uint8_t)((address >> 16) & 0x00FF); + tmp_addr[1] = (uint8_t)((address >> 8) & 0x00FF); + tmp_addr[0] = (uint8_t)((address) & 0x00FF); + + if (total_size_temp >= max_i2c_size) { + g_core_fp.fp_register_read(tmp_addr, max_i2c_size, &temp_info_data[i * max_i2c_size], 0); + total_size_temp = total_size_temp - max_i2c_size; + } else { + /*I("last total_size_temp=%d\n",total_size_temp);*/ + g_core_fp.fp_register_read(tmp_addr, total_size_temp % max_i2c_size, &temp_info_data[i * max_i2c_size], 0); + } + } + + /* 4. FW stop outputing */ + tmp_data[3] = temp_info_data[3]; tmp_data[2] = temp_info_data[2]; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + g_core_fp.fp_register_write(psram_op->addr_rawdata_addr, DATA_LEN_4, tmp_data, 0); + + /* 5. Data Checksum Check */ + for (i = 2; i < total_size; i += 2)/* 2:PASSWORD NOT included */ + check_sum_cal += (temp_info_data[i + 1] * 256 + temp_info_data[i]); + + if (check_sum_cal % 0x10000 != 0) { + I("%s check_sum_cal fail=%2X\n", __func__, check_sum_cal); + goto FAIL; + } else { + memcpy(info_data, &temp_info_data[4], mutual_data_size * sizeof(uint8_t)); + /*I("%s checksum PASS\n", __func__);*/ + } + kfree(temp_info_data); + return true; +FAIL: + kfree(temp_info_data); + return false; +} +/* SRAM side end*/ +#endif + +#ifdef CORE_DRIVER + +static void himax_mcu_init_ic(void) +{ + I("%s: use default incell init.\n", __func__); +} + +#ifdef HX_AUTO_UPDATE_FW +static int himax_mcu_fw_ver_bin(void) +{ + I("%s: use default incell address.\n", __func__); + I("%s:Entering!\n", __func__); + if (i_CTPM_FW != NULL) { + I("Catch fw version in bin file!\n"); + g_i_FW_VER = (i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR] << 8) | i_CTPM_FW[FW_VER_MIN_FLASH_ADDR]; + g_i_CFG_VER = (i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR] << 8) | i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR]; + g_i_CID_MAJ = i_CTPM_FW[CID_VER_MAJ_FLASH_ADDR]; + g_i_CID_MIN = i_CTPM_FW[CID_VER_MIN_FLASH_ADDR]; + } else { + I("FW data is null!\n"); + return 1; + } + return NO_ERR; +} +#endif + + +#ifdef HX_RST_PIN_FUNC +static void himax_mcu_pin_reset(void) +{ + I("%s: Now reset the Touch chip,private_ts->vdd_1v8_always_on = %d \n", + __func__,private_ts->vdd_1v8_always_on); + himax_rst_gpio_set(private_ts->rst_gpio, 0); +#if defined(__HIMAX_HX83102_MOD__) + msleep(5); +#else + if(private_ts->vdd_1v8_always_on) + msleep(10); + else + msleep(20); +#endif + himax_rst_gpio_set(private_ts->rst_gpio, 1); +#ifdef HX_ZERO_FLASH +#if defined(__HIMAX_HX83102_MOD__) + msleep(2); +#else + msleep(10); +#endif +#else + msleep(50); +#endif + +} + +static void himax_mcu_ic_reset(uint8_t loadconfig, uint8_t int_off) +{ + struct himax_ts_data *ts = private_ts; + + HX_HW_RESET_ACTIVATE = 0; + I("%s,status: loadconfig=%d,int_off=%d\n", __func__, loadconfig, int_off); + + if (ts->rst_gpio >= 0) { + if (int_off) + g_core_fp.fp_irq_switch(0); + + g_core_fp.fp_pin_reset(); + + if (loadconfig) + g_core_fp.fp_reload_config(); + + if (int_off) + g_core_fp.fp_irq_switch(1); + + } +} +#endif + +#ifndef HX_FIX_TOUCH_INFO +static uint8_t himax_mcu_tp_info_check(void) +{ + uint8_t rx = pdriver_op->data_df_rx[0]; + uint8_t tx = pdriver_op->data_df_tx[0]; + uint8_t pt = pdriver_op->data_df_pt[0]; + uint16_t x_res = pdriver_op->data_df_x_res[1] << 8 | pdriver_op->data_df_x_res[0]; + uint16_t y_res = pdriver_op->data_df_y_res[1] << 8 | pdriver_op->data_df_y_res[0]; + uint8_t err_cnt = 0; + + if (ic_data->HX_RX_NUM < (rx / 2) || ic_data->HX_RX_NUM > (rx * 3 / 2)) { + ic_data->HX_RX_NUM = rx; + err_cnt |= 0x01; + } + if (ic_data->HX_TX_NUM < (tx / 2) || ic_data->HX_TX_NUM > (tx * 3 / 2)) { + ic_data->HX_TX_NUM = tx; + err_cnt |= 0x02; + } + if (ic_data->HX_MAX_PT < (pt / 2) || ic_data->HX_MAX_PT > (pt * 3 / 2)) { + ic_data->HX_MAX_PT = pt; + err_cnt |= 0x04; + } + if (ic_data->HX_Y_RES < (y_res / 2) || ic_data->HX_Y_RES > (y_res * 3 / 2)) { + ic_data->HX_Y_RES = y_res; + err_cnt |= 0x08; + } + if (ic_data->HX_X_RES < (x_res / 2) || ic_data->HX_X_RES > (x_res * 3 / 2)) { + ic_data->HX_X_RES = x_res; + err_cnt |= 0x10; + } + return err_cnt; +} +#endif + +static void himax_mcu_touch_information(void) +{ +#ifndef HX_FIX_TOUCH_INFO + char data[DATA_LEN_8] = {0}; + uint8_t err_cnt = 0; + + I(" DT-%s:touch_info: HX_RX_NUM = %d, HX_TX_NUM = %d, HX_BT_NUM = %d,HX_X_RES = %d,HX_Y_RES = %d, HX_MAX_PT = %d, HX_XY_REVERSE = %d, HX_INT_IS_EDGE = %d\n", __func__, + ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_BT_NUM,ic_data->HX_X_RES,ic_data->HX_Y_RES,ic_data->HX_MAX_PT,ic_data->HX_XY_REVERSE,ic_data->HX_INT_IS_EDGE); + + if ((0 == ic_data->HX_RX_NUM) || (0 == ic_data->HX_TX_NUM) || (0 == ic_data->HX_X_RES) || (0 == ic_data->HX_Y_RES)) { + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, DATA_LEN_8, data, 0); + ic_data->HX_RX_NUM = data[2]; + ic_data->HX_TX_NUM = data[3]; + ic_data->HX_MAX_PT = data[4]; + /*I("%s : HX_RX_NUM=%d,ic_data->HX_TX_NUM=%d,ic_data->HX_MAX_PT=%d\n",__func__,ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_MAX_PT);*/ + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_xy_res_enable, DATA_LEN_4, data, 0); + + /*I("%s : c_data->HX_XY_REVERSE=0x%2.2X\n",__func__,data[1]);*/ + if ((data[1] & 0x04) == 0x04) + ic_data->HX_XY_REVERSE = true; + else + ic_data->HX_XY_REVERSE = false; + + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_x_y_res, DATA_LEN_4, data, 0); + ic_data->HX_Y_RES = data[0] * 256 + data[1]; + ic_data->HX_X_RES = data[2] * 256 + data[3]; + /*I("%s : ic_data->HX_Y_RES=%d,ic_data->HX_X_RES=%d\n",__func__,ic_data->HX_Y_RES,ic_data->HX_X_RES);*/ + + g_core_fp.fp_register_read(pdriver_op->addr_fw_define_int_is_edge, DATA_LEN_4, data, 0); + /*I("%s : data[0]=0x%2.2X,data[1]=0x%2.2X,data[2]=0x%2.2X,data[3]=0x%2.2X\n",__func__,data[0],data[1],data[2],data[3]);*/ + /*I("data[0] & 0x01 = %d\n",(data[0] & 0x01));*/ + if ((data[1] & 0x01) == 1) + ic_data->HX_INT_IS_EDGE = true; + else + ic_data->HX_INT_IS_EDGE = false; + + /*1. Read number of MKey R100070E8H to determin data size*/ + g_core_fp.fp_register_read(psram_op->addr_mkey, DATA_LEN_4, data, 0); + /* I("%s: tmp_data[0] = 0x%02X,tmp_data[1] = 0x%02X,tmp_data[2] = 0x%02X,tmp_data[3] = 0x%02X\n",*/ + /*__func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]);*/ + ic_data->HX_BT_NUM = data[0] & 0x03; + + err_cnt = himax_mcu_tp_info_check(); + if (err_cnt > 0) + E("TP Info from IC is wrong, err_cnt = 0x%X", err_cnt); + } +#else + ic_data->HX_RX_NUM = FIX_HX_RX_NUM; + ic_data->HX_TX_NUM = FIX_HX_TX_NUM; + ic_data->HX_BT_NUM = FIX_HX_BT_NUM; + ic_data->HX_X_RES = FIX_HX_X_RES; + ic_data->HX_Y_RES = FIX_HX_Y_RES; + ic_data->HX_MAX_PT = FIX_HX_MAX_PT; + ic_data->HX_XY_REVERSE = FIX_HX_XY_REVERSE; + ic_data->HX_INT_IS_EDGE = FIX_HX_INT_IS_EDGE; + +#endif + I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d\n", __func__, ic_data->HX_RX_NUM, ic_data->HX_TX_NUM, ic_data->HX_MAX_PT); + I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d\n", __func__, ic_data->HX_XY_REVERSE, ic_data->HX_Y_RES, ic_data->HX_X_RES); + I("%s:HX_INT_IS_EDGE =%d\n", __func__, ic_data->HX_INT_IS_EDGE); +} + +static void himax_mcu_reload_config(void) +{ + if (himax_report_data_init()) + E("%s: allocate data fail\n", __func__); + + g_core_fp.fp_sense_on(0x00); +} + +static int himax_mcu_get_touch_data_size(void) +{ + return HIMAX_TOUCH_DATA_SIZE; +} + +static int himax_mcu_hand_shaking(void) +{ + /* 0:Running, 1:Stop, 2:I2C Fail */ + int result = 0; + return result; +} + +static int himax_mcu_determin_diag_rawdata(int diag_command) +{ + return diag_command % 10; +} + +static int himax_mcu_determin_diag_storage(int diag_command) +{ + return diag_command / 10; +} + +static int himax_mcu_cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max) +{ + int RawDataLen; + + if (raw_cnt_rmd != 0x00) + RawDataLen = MAX_I2C_TRANS_SZ - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1; + else + RawDataLen = MAX_I2C_TRANS_SZ - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1; + + return RawDataLen; +} + +static bool himax_mcu_diag_check_sum(struct himax_report_data *hx_touch_data) +{ + uint16_t check_sum_cal = 0; + int i; + + /* Check 128th byte CRC */ + for (i = 0, check_sum_cal = 0; i < (hx_touch_data->touch_all_size - hx_touch_data->touch_info_size); i += 2) + check_sum_cal += (hx_touch_data->hx_rawdata_buf[i + 1] * FLASH_RW_MAX_LEN + hx_touch_data->hx_rawdata_buf[i]); + + + if (check_sum_cal % HX64K != 0) { + I("%s fail=%2X\n", __func__, check_sum_cal); + return 0; + } + + return 1; +} + +static void himax_mcu_diag_parse_raw_data(struct himax_report_data *hx_touch_data, int mul_num, int self_num, uint8_t diag_cmd, int32_t *mutual_data, int32_t *self_data) +{ + diag_mcu_parse_raw_data(hx_touch_data, mul_num, self_num, diag_cmd, mutual_data, self_data); +} + +#ifdef HX_ESD_RECOVERY +static int himax_mcu_ic_esd_recovery(int hx_esd_event, int hx_zero_event, int length) +{ + int ret_val = NO_ERR; + + if (hx_esd_event == length) { + g_zero_event_count = 0; + ret_val = HX_ESD_EVENT; + } else if (hx_zero_event == length) { + if (g_zero_event_count > 5) { + g_zero_event_count = 0; + I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n"); + ret_val = HX_ESD_EVENT; + } else { + g_zero_event_count++; + I("[HIMAX TP MSG]: ALL Zero event is %d times.\n", g_zero_event_count); + ret_val = HX_ZERO_EVENT_COUNT; + } + } + + return ret_val; +} + +static void himax_mcu_esd_ic_reset(void) +{ + HX_ESD_RESET_ACTIVATE = 0; +#ifdef HX_RST_PIN_FUNC + himax_mcu_pin_reset(); +#else + himax_mcu_system_reset(); +#endif + I("%s:\n", __func__); +} +#endif +#ifdef HX_TP_PROC_GUEST_INFO +char *g_checksum_str = "check sum fail"; +/* char *g_guest_info_item[] = { + * "projectID", + * "CGColor", + * "BarCode", + * "Reserve1", + * "Reserve2", + * "Reserve3", + * "Reserve4", + * "Reserve5", + * "VCOM", + * "Vcom-3Gar", + * NULL + * }; + */ + +static int himax_guest_info_get_status(void) +{ + return g_guest_info_data->g_guest_info_ongoing; +} +static void himax_guest_info_set_status(int setting) +{ + g_guest_info_data->g_guest_info_ongoing = setting; +} + +static int himax_guest_info_read(uint32_t start_addr, uint8_t *flash_tmp_buffer) +{ + uint32_t temp_addr = 0; + uint8_t tmp_addr[4]; + uint32_t flash_page_len = 0x1000; + /* uint32_t checksum = 0x00; */ + int result = 0; + + + I("Reading guest info in start_addr = 0x%08X !\n", start_addr); + + tmp_addr[0] = start_addr % 0x100; + tmp_addr[1] = (start_addr >> 8) % 0x100; + tmp_addr[2] = (start_addr >> 16) % 0x100; + tmp_addr[3] = start_addr / 0x1000000; + I("Now start addr: tmp_addr[0]=0x%2X,tmp_addr[1]=0x%2X,tmp_addr[2]=0x%2X,tmp_addr[3]=0x%2X\n", tmp_addr[0], tmp_addr[1], tmp_addr[2], tmp_addr[3]); + result = g_core_fp.fp_check_CRC(tmp_addr, flash_page_len); + I("Checksum = 0x%8X\n", result); + if (result != 0) + goto END_FUNC; + + for (temp_addr = start_addr; temp_addr < (start_addr + flash_page_len); temp_addr = temp_addr + 128) { + + /* I("temp_addr=%d,tmp_addr[0]=0x%2X,tmp_addr[1]=0x%2X,tmp_addr[2]=0x%2X,tmp_addr[3]=0x%2X\n",temp_addr,tmp_addr[0],tmp_addr[1],tmp_addr[2],tmp_addr[3]); */ + tmp_addr[0] = temp_addr % 0x100; + tmp_addr[1] = (temp_addr >> 8) % 0x100; + tmp_addr[2] = (temp_addr >> 16) % 0x100; + tmp_addr[3] = temp_addr / 0x1000000; + g_core_fp.fp_register_read(tmp_addr, 128, &flash_tmp_buffer[temp_addr - start_addr], false); + /* memcpy(&flash_tmp_buffer[temp_addr - start_addr],buffer,128);*/ + } + +END_FUNC: + return result; +} + +static int hx_read_guest_info(void) +{ + /* uint8_t tmp_addr[4]; */ + uint32_t panel_color_addr = 0x10000;/*64k*/ + + uint32_t info_len; + uint32_t flash_page_len = 0x1000;/*4k*/ + uint8_t *flash_tmp_buffer = NULL; + /* uint32_t temp_addr = 0; */ + uint8_t temp_str[128]; + int i = 0; + int custom_info_temp = 0; + int checksum = 0; + + himax_guest_info_set_status(1); + + flash_tmp_buffer = kcalloc(HX_GUEST_INFO_SIZE * flash_page_len, sizeof(uint8_t), GFP_KERNEL); + if (flash_tmp_buffer == NULL) { + I("%s: Memory allocate fail!\n", __func__); + return MEM_ALLOC_FAIL; + } + + g_core_fp.fp_sense_off(true); + /* g_core_fp.fp_burst_enable(1); */ + + for (custom_info_temp = 0; custom_info_temp < HX_GUEST_INFO_SIZE; custom_info_temp++) { + checksum = himax_guest_info_read(panel_color_addr+custom_info_temp * flash_page_len, &flash_tmp_buffer[custom_info_temp * flash_page_len]); + if (checksum != 0) { + E("%s:Checksum Fail! g_checksum_str len=%d\n", __func__, (int)strlen(g_checksum_str)); + memcpy(&g_guest_info_data->g_guest_str_in_format[custom_info_temp][0], g_checksum_str, (int)strlen(g_checksum_str)); + memcpy(&g_guest_info_data->g_guest_str[custom_info_temp][0], g_checksum_str, (int)strlen(g_checksum_str)); + continue; + } + + info_len = flash_tmp_buffer[custom_info_temp * flash_page_len] + + (flash_tmp_buffer[custom_info_temp*flash_page_len + 1] << 8) + + (flash_tmp_buffer[custom_info_temp*flash_page_len + 2] << 16) + + (flash_tmp_buffer[custom_info_temp*flash_page_len + 3] << 24); + + I("Now custom_info_temp = %d\n", custom_info_temp); + + I("Now size_buff[0]=0x%02X,[1]=0x%02X,[2]=0x%02X,[3]=0x%02X\n" + , flash_tmp_buffer[custom_info_temp*flash_page_len] + , flash_tmp_buffer[custom_info_temp*flash_page_len + 1] + , flash_tmp_buffer[custom_info_temp*flash_page_len + 2] + , flash_tmp_buffer[custom_info_temp*flash_page_len + 3]); + + I("Now total length=%d\n", info_len); + + g_guest_info_data->g_guest_data_len[custom_info_temp] = info_len; + + I("Now custom_info_id [0]=%d,[1]=%d,[2]=%d,[3]=%d\n" + , flash_tmp_buffer[custom_info_temp*flash_page_len + 4] + , flash_tmp_buffer[custom_info_temp*flash_page_len + 5] + , flash_tmp_buffer[custom_info_temp*flash_page_len + 6] + , flash_tmp_buffer[custom_info_temp*flash_page_len + 7]); + + g_guest_info_data->g_guest_data_type[custom_info_temp] = flash_tmp_buffer[custom_info_temp * flash_page_len + 7]; + + /* if(custom_info_temp < 3) { */ + if (info_len > 128) { + I("%s: info_len=%d\n", __func__, info_len); + info_len = 128; + } + for (i = 0; i < info_len; i++) + temp_str[i] = flash_tmp_buffer[custom_info_temp * flash_page_len + HX_GUEST_INFO_LEN_SIZE + HX_GUEST_INFO_ID_SIZE + i]; + I("g_guest_info_data->g_guest_str_in_format[%d] size = %d\n", custom_info_temp, info_len); + memcpy(&g_guest_info_data->g_guest_str_in_format[custom_info_temp][0], temp_str, info_len); + /*}*/ + + for (i = 0; i < 128; i++) + temp_str[i] = flash_tmp_buffer[custom_info_temp * flash_page_len + i]; + + I("g_guest_info_data->g_guest_str[%d] size = %d\n", custom_info_temp, 128); + memcpy(&g_guest_info_data->g_guest_str[custom_info_temp][0], temp_str, 128); + /*if(custom_info_temp == 0) + *{ + * for( i = 0; i< 256 ; i++) + * { + * if(i % 16 == 0 && i > 0) + * I("\n"); + * I("g_guest_info_data->g_guest_str[%d][%d] = 0x%02X",custom_info_temp,i,g_guest_info_data->g_guest_str[custom_info_temp][i]); + * } + *} + */ + } + /* himax_burst_enable(private_ts->client, 0); */ + + g_core_fp.fp_sense_on(0x01); + + kfree(flash_tmp_buffer); + himax_guest_info_set_status(0); + return NO_ERR; +} +#endif +#endif + +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL) +static void himax_mcu_resend_cmd_func(bool suspended) +{ +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) + struct himax_ts_data *ts = private_ts; +#endif +#ifdef HX_SMART_WAKEUP + g_core_fp.fp_set_SMWP_enable(ts->SMWP_enable, suspended); +#endif +#ifdef HX_EDGE_LIMIT + g_core_fp.fp_set_edge_limit_enable(ts->edge_limit_enable, suspended); +#endif +#ifdef HX_HIGH_SENSE + g_core_fp.fp_set_HSEN_enable(ts->HSEN_enable, suspended); +#endif +#ifdef HX_USB_DETECT_GLOBAL + himax_cable_detect_func(true); +#endif +} +#endif + +#ifdef HX_ZERO_FLASH +int G_POWERONOF = 1; +EXPORT_SYMBOL(G_POWERONOF); +void hx_dis_rload_0f(int disable) +{ + /*Diable Flash Reload*/ + g_core_fp.fp_register_write(pzf_op->addr_dis_flash_reload, DATA_LEN_4, pzf_op->data_dis_flash_reload, 0); +} + +void himax_mcu_clean_sram_0f(uint8_t *addr, int write_len, int type) +{ + int total_read_times = 0; + int max_bus_size = MAX_I2C_TRANS_SZ; + int total_size_temp = 0; + int total_size = 0; + int address = 0; + int i = 0; + + uint8_t fix_data = 0x00; + uint8_t tmp_addr[4]; + uint8_t tmp_data[MAX_I2C_TRANS_SZ] = {0}; + + I("%s, Entering\n", __func__); + + total_size = write_len; + +#ifdef __MTK_SPI__ + if (write_len > (HX_SPI_MTK_MAX_WRITE_SZ - 4)) + max_bus_size = (HX_SPI_MTK_MAX_WRITE_SZ - 4); + else + max_bus_size = write_len; +#else + if (total_size > PACKET_MAX_SZ - 8) + max_bus_size = PACKET_MAX_SZ - 8; +#endif + + total_size_temp = write_len; + + g_core_fp.fp_burst_enable(1); + + tmp_addr[3] = addr[3]; + tmp_addr[2] = addr[2]; + tmp_addr[1] = addr[1]; + tmp_addr[0] = addr[0]; + I("%s, write addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n", __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + + switch (type) { + case 0: + fix_data = 0x00; + break; + case 1: + fix_data = 0xAA; + break; + case 2: + fix_data = 0xBB; + break; + } + + for (i = 0; i < MAX_I2C_TRANS_SZ; i++) + tmp_data[i] = fix_data; + + I("%s, total size=%d\n", __func__, total_size); + + if (total_size_temp % max_bus_size == 0) + total_read_times = total_size_temp / max_bus_size; + else + total_read_times = total_size_temp / max_bus_size + 1; + + for (i = 0; i < (total_read_times); i++) { + I("[log]write %d time start!\n", i); + if (total_size_temp >= max_bus_size) { + g_core_fp.fp_register_write(tmp_addr, max_bus_size, tmp_data, 0); + total_size_temp = total_size_temp - max_bus_size; + } else { + I("last total_size_temp=%d\n", total_size_temp); + g_core_fp.fp_register_write(tmp_addr, total_size_temp % max_bus_size, tmp_data, 0); + } + address = ((i+1) * max_bus_size); + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); + tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); + + usleep_range(10000, 11000); + } + + I("%s, END\n", __func__); +} + +void himax_mcu_write_sram_0f(const struct firmware *fw_entry, uint8_t *addr, int start_index, uint32_t write_len) +{ + int total_read_times = 0; + int max_bus_size = MAX_I2C_TRANS_SZ; + int total_size_temp = 0; + int address = 0; + int i = 0; + + uint8_t tmp_addr[4]; + uint8_t *tmp_data; + + total_size_temp = write_len; + I("%s, Entering - total write size=%d\n", __func__, total_size_temp); + +#if defined(HX_SPI_OPERATION) + if (write_len > PACKET_MAX_SZ - 8) + max_bus_size = PACKET_MAX_SZ - 8; + else + max_bus_size = write_len; +#else +#ifdef __MTK_SPI__ + if (write_len > (HX_SPI_MTK_MAX_WRITE_SZ - 4)) + max_bus_size = (HX_SPI_MTK_MAX_WRITE_SZ - 4); + else + max_bus_size = write_len; +#endif +#endif + + g_core_fp.fp_burst_enable(1); + + tmp_addr[3] = addr[3]; + tmp_addr[2] = addr[2]; + tmp_addr[1] = addr[1]; + tmp_addr[0] = addr[0]; + I("%s, write addr = 0x%02X%02X%02X%02X\n", __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + + /* tmp_data = kcalloc(max_bus_size, sizeof(uint8_t), GFP_KERNEL); + * if (tmp_data == NULL) { + * I("%s: Can't allocate enough buf\n", __func__); + * return; + * } + */ + + /*for(i = 0;i<10;i++) + *{ + * I("[%d] 0x%2.2X", i, tmp_data[i]); + *} + *I("\n"); + */ + if (total_size_temp % max_bus_size == 0) + total_read_times = total_size_temp / max_bus_size; + else + total_read_times = total_size_temp / max_bus_size + 1; + + for (i = 0; i < (total_read_times); i++) { + /*I("[log]write %d time start!\n", i);*/ + /*I("[log]addr[3]=0x%02X, addr[2]=0x%02X, addr[1]=0x%02X, addr[0]=0x%02X!\n", tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]);*/ + + if (total_size_temp >= max_bus_size) { + /*memcpy(tmp_data, &fw_entry->data[start_index+i * max_bus_size], max_bus_size);*/ + tmp_data = (uint8_t *)&fw_entry->data[start_index+i * max_bus_size]; + g_core_fp.fp_register_write(tmp_addr, max_bus_size, tmp_data, 0); + total_size_temp = total_size_temp - max_bus_size; + } else { + /*memcpy(tmp_data, &fw_entry->data[start_index+i * max_bus_size], total_size_temp % max_bus_size);*/ + tmp_data = (uint8_t *)&fw_entry->data[start_index+i * max_bus_size]; + I("last total_size_temp=%d\n", total_size_temp % max_bus_size); + g_core_fp.fp_register_write(tmp_addr, total_size_temp % max_bus_size, tmp_data, 0); + } + + /*I("[log]write %d time end!\n", i);*/ + address = ((i+1) * max_bus_size); + tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); + + if (tmp_addr[0] < addr[0]) + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF) + 1; + else + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); + + udelay(100); + } + I("%s, End\n", __func__); + /* kfree(tmp_data); */ +} + +int himax_sram_write_crc_check(const struct firmware *fw_entry, uint8_t *addr, int strt_idx, uint32_t len) +{ + int retry = 0; + int crc = -1; + + do { + g_core_fp.fp_write_sram_0f(fw_entry, addr, strt_idx, len); + crc = g_core_fp.fp_check_CRC(addr, len); + retry++; + I("%s, HW CRC %s in %d time\n", __func__, (crc == 0)?"OK":"Fail", retry); + } while (crc != 0 && retry < 3); + + return crc; +} +#if defined(HX83102D) +int hx_parse_bin_cfg_data(const struct firmware *fw_entry, struct zf_info *zf_info_arr, uint8_t *FW_buf, uint8_t *sram_min) +{ + int part_num = 0; + int i = 0; + uint8_t buf[16]; + int i_max = 0; + int i_min = 0; + uint32_t dsram_base = 0xFFFFFFFF; + uint32_t dsram_max = 0; + int cfg_sz = 0; +#if defined(HX_CODE_OVERLAY) + uint8_t j = 0; + int allovlidx = 0; + + if (ovl_idx == NULL) { + ovl_idx = kzalloc(ovl_section_num, GFP_KERNEL); + if (ovl_idx == NULL) { + E("%s, ovl_idx alloc failed!\n", + __func__); + return -ENOMEM; + } + } else { + memset(ovl_idx, 0, ovl_section_num); + } +#endif + /*1. get number of partition*/ + part_num = fw_entry->data[HX64K + 12]; + I("%s, Number of partition is %d\n", __func__, part_num); + if (part_num <= 1) { + E("%s, size of cfg part failed! part_num = %d\n", + __func__, part_num); + return LENGTH_FAIL; + } + + /* i = 0 is fw entity, it need to update by itself*/ + for (i = 1; i < part_num; i++) { + /*3. get all partition*/ + memcpy(buf, &fw_entry->data[i * 0x10 + HX64K], 16); + memcpy(zf_info_arr[i].sram_addr, buf, 4); + zf_info_arr[i].write_size = buf[7] << 24 + | buf[6] << 16 + | buf[5] << 8 + | buf[4]; + zf_info_arr[i].fw_addr = buf[11] << 24 + | buf[10] << 16 + | buf[9] << 8 + | buf[8]; + zf_info_arr[i].cfg_addr = zf_info_arr[i].sram_addr[0]; + zf_info_arr[i].cfg_addr += zf_info_arr[i].sram_addr[1] << 8; + zf_info_arr[i].cfg_addr += zf_info_arr[i].sram_addr[2] << 16; + zf_info_arr[i].cfg_addr += zf_info_arr[i].sram_addr[3] << 24; + +#if defined(HX_CODE_OVERLAY) + /*overlay section*/ + + if ((buf[15] == 0x55 && buf[14] == 0x66) + || (buf[3] == 0x20 && buf[2] == 0x00 + && buf[1] == 0x8C && buf[0] == 0xE0)) { + I("%s: catch overlay section in index %d\n", + __func__, i); + + /* record index of overlay section */ + allovlidx |= 1< zf_info_arr[i].cfg_addr) { + dsram_base = zf_info_arr[i].cfg_addr; + i_min = i; + } + if (dsram_max < zf_info_arr[i].cfg_addr) { + dsram_max = zf_info_arr[i].cfg_addr; + i_max = i; + } + } + for (i = 0; i < ADDR_LEN_4; i++) + sram_min[i] = zf_info_arr[i_min].sram_addr[i]; + + cfg_sz = (dsram_max - dsram_base) + zf_info_arr[i_max].write_size; + if (cfg_sz % 16 != 0) + cfg_sz = cfg_sz + 16 - (cfg_sz % 16); + + I("%s, cfg_sz = %d!, dsram_base = %X, dsram_max = %X\n", __func__, + cfg_sz, dsram_base, dsram_max); + if (cfg_sz <= FW_BIN_16K_SZ) + memset(FW_buf, 0x00, sizeof(uint8_t) * cfg_sz); + else + memset(FW_buf, 0x00, sizeof(uint8_t) * FW_BIN_16K_SZ); + for (i = 1; i < part_num; i++) { + if (zf_info_arr[i].cfg_addr % 4 != 0) + zf_info_arr[i].cfg_addr = zf_info_arr[i].cfg_addr + - (zf_info_arr[i].cfg_addr % 4); + + I("%s,[%d]SRAM addr=%08X,[%d]fw_addr=%08X,[%d]write_size=%d\n", + __func__, + i, zf_info_arr[i].cfg_addr, + i, zf_info_arr[i].fw_addr, + i, zf_info_arr[i].write_size); + +#if defined(HX_CODE_OVERLAY) + /*overlay section*/ + if (allovlidx & (1<data[zf_info_arr[i].fw_addr], + zf_info_arr[i].write_size); + } + /* debug info */ + /* for (i = 1; i < part_num; i++) { + * different = 0; + * I("--cfg_addr = 0x%08X\n",zf_info_arr[i].cfg_addr); + * I("--bin_addr = 0x%08X\n",zf_info_arr[i].fw_addr); + * I("--write size = %d\n",zf_info_arr[i].write_size); + * for ( j = 0; j < zf_info_arr[i].write_size; j++) { + * if(FW_buf[zf_info_arr[i].cfg_addr - dsram_base + j] != + fw_entry->data[zf_info_arr[i].fw_addr + j]) + * different++; + * } + * I("--There are %d different\n", different); + * } + */ + + return cfg_sz; +} +#else +int hx_parse_bin_cfg_data(const struct firmware *fw_entry, struct zf_info *zf_info_arr, uint8_t *FW_buf, uint8_t *sram_min, uint8_t *ovl_sidx) +{ + int part_num = 0; + int i = 0; + uint8_t buf[16]; + int i_max = 0; + int i_min = 0; + uint32_t dsram_base = 0xFFFFFFFF; + uint32_t dsram_max = 0; + int cfg_sz = 0; + /*int different = 0;*/ + /*int j = 0;*/ + + /*1. get number of partition*/ + part_num = fw_entry->data[HX64K + 12]; + I("%s, Number of partition is %d\n", __func__, part_num); + if (part_num <= 1) { + E("%s, size of cfg part failed! part_num = %d\n", __func__, part_num); + return LENGTH_FAIL; + } + /*2. check struct of array*/ + if (zf_info_arr == NULL || FW_buf == NULL) { + E("%s, Struct is NULL, %p,%p\n", __func__, zf_info_arr, FW_buf); + return MEM_ALLOC_FAIL; + } + + /* i = 0 is fw entity, it need to update by itself*/ + for (i = 1; i < part_num; i++) { + /*3. get all partition*/ + memcpy(buf, &fw_entry->data[i * 0x10 + HX64K], 16); + memcpy(zf_info_arr[i].sram_addr, buf, 4); + zf_info_arr[i].write_size = buf[7] << 24 | buf[6] << 16 | buf[5] << 8 | buf[4]; + zf_info_arr[i].fw_addr = buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8]; + zf_info_arr[i].cfg_addr = zf_info_arr[i].sram_addr[0]; + zf_info_arr[i].cfg_addr += zf_info_arr[i].sram_addr[1] << 8; + zf_info_arr[i].cfg_addr += zf_info_arr[i].sram_addr[2] << 16; + zf_info_arr[i].cfg_addr += zf_info_arr[i].sram_addr[3] << 24; + +#ifdef HX_CODE_OVERLAY + /*overlay section*/ + if (zf_info_arr[i].cfg_addr == ovl_isram_addr) { + if (*ovl_sidx == 0) + *ovl_sidx = i; + + continue; + } +#endif + + if (dsram_base > zf_info_arr[i].cfg_addr) { + dsram_base = zf_info_arr[i].cfg_addr; + i_min = i; + } + if (dsram_max < zf_info_arr[i].cfg_addr) { + dsram_max = zf_info_arr[i].cfg_addr; + i_max = i; + } + } + for (i = 0; i < ADDR_LEN_4; i++) + sram_min[i] = zf_info_arr[i_min].sram_addr[i]; + cfg_sz = (dsram_max - dsram_base) + zf_info_arr[i_max].write_size; + if (cfg_sz % 16 != 0) + cfg_sz = cfg_sz + 16 - (cfg_sz % 16); + + I("%s, cfg_sz = %d!, dsram_base = %X, dsram_max = %X\n", __func__, cfg_sz, dsram_base, dsram_max); + + memset(FW_buf, 0x00, sizeof(uint8_t) * cfg_sz); + for (i = 1; i < part_num; i++) { + if (zf_info_arr[i].cfg_addr % 4 != 0) + zf_info_arr[i].cfg_addr = zf_info_arr[i].cfg_addr - (zf_info_arr[i].cfg_addr % 4); + + I("%s,[%d] SRAM addr = %08X\n", __func__, i, zf_info_arr[i].cfg_addr); + I("%s,[%d] fw_addr = %08X\n", __func__, i, zf_info_arr[i].fw_addr); + I("%s,[%d] write_size = %d\n", __func__, i, zf_info_arr[i].write_size); + +#ifdef HX_CODE_OVERLAY + /*overlay section*/ + if (zf_info_arr[i].cfg_addr == ovl_isram_addr) + continue; +#endif + + memcpy(&FW_buf[zf_info_arr[i].cfg_addr - dsram_base], &fw_entry->data[zf_info_arr[i].fw_addr], zf_info_arr[i].write_size); + } + /* debug info */ + /* for (i = 1; i < part_num; i++) { + * different = 0; + * I("--cfg_addr = 0x%08X\n",zf_info_arr[i].cfg_addr); + * I("--bin_addr = 0x%08X\n",zf_info_arr[i].fw_addr); + * I("--write size = %d\n",zf_info_arr[i].write_size); + * for ( j = 0; j < zf_info_arr[i].write_size; j++) { + * if(FW_buf[zf_info_arr[i].cfg_addr - dsram_base + j] != fw_entry->data[zf_info_arr[i].fw_addr + j]) + * different++; + * } + * I("--There are %d different\n", different); + * } + */ + + return cfg_sz; +} +#endif + +int himax_zf_part_info(const struct firmware *fw_entry) +{ + int part_num = fw_entry->data[HX64K + 12]; + int ret = 0; + uint8_t buf[16]; + struct zf_info *zf_info_arr = NULL; + uint8_t *FW_buf; + uint8_t sram_min[4]; + int cfg_crc_sw = 0; + int cfg_crc_hw = 0; + int cfg_sz = 0; + int retry = 3; + +#if ((defined HX_CODE_OVERLAY) || !(defined HX83102D)) + uint8_t ovl_sidx = 0; +#endif +#if ((defined HX_CODE_OVERLAY) && (defined HX83102D)) + uint8_t ovl_idx_t; +#endif +#if defined(HX83102D) + +#if defined(HX_SMART_WAKEUP) || defined(HX_CODE_OVERLAY) + uint8_t tmp_addr[4] = {0xFC, 0x7F, 0x00, 0x10}; + uint8_t send_data[4] = {0}; + uint8_t recv_data[4] = {0}; +#endif +#else +#ifdef HX_CODE_OVERLAY +#ifdef HX_SMART_WAKEUP + uint8_t tmp_addr[4] = {0xFC, 0x7F, 0x00, 0x10}; + uint8_t send_data[4] = {0}; + uint8_t recv_data[4] = {0}; +#endif +#endif +#endif + + /*1. get number of partition*/ + /*part_num = fw_entry->data[HX64K + 12];*/ + I("%s, Number of partition is %d\n", __func__, part_num); + if (part_num <= 0) + part_num = 1; + + /*2. initial struct of array*/ + zf_info_arr = kcalloc(part_num, sizeof(struct zf_info), GFP_KERNEL); + if (zf_info_arr == NULL) { + E("%s, Allocate ZF info array failed!\n", __func__); + ret = MEM_ALLOC_FAIL; + goto ALOC_ZF_INFO_ARR_FAIL; + } + memset(zf_info_arr, 0x0, part_num * sizeof(struct zf_info)); + FW_buf = kcalloc(FW_BIN_16K_SZ, sizeof(uint8_t), GFP_KERNEL); + if (FW_buf == NULL) { + E("%s, Allocate FW_buf array failed!\n", __func__); + ret = MEM_ALLOC_FAIL; + goto ALOC_FW_BUF_FAIL; + } + + /*3. Find the data in the bin file */ + /*CFG*/ +#if defined(HX83102D) + cfg_sz = hx_parse_bin_cfg_data(fw_entry, zf_info_arr, FW_buf, sram_min); +#else + cfg_sz = hx_parse_bin_cfg_data(fw_entry, zf_info_arr, FW_buf, sram_min, &ovl_sidx); +#endif + I("Now cfg_sz=%d\n", cfg_sz); + if (cfg_sz < 0) { + ret = LENGTH_FAIL; + goto END_FUNC; + } else { + cfg_crc_sw = g_core_fp.fp_Calculate_CRC_with_AP(FW_buf, 0, cfg_sz); + I("Now cfg_crc_sw=%X\n", cfg_crc_sw); + } + /*Fw Entity*/ + memcpy(buf, &fw_entry->data[0 * 0x10 + HX64K], 16); + memcpy(zf_info_arr[0].sram_addr, buf, 4); + zf_info_arr[0].write_size = buf[7] << 24 | buf[6] << 16 | buf[5] << 8 | buf[4]; + zf_info_arr[0].fw_addr = buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8]; + + /* 4. write to sram*/ + if (G_POWERONOF == 1) { + /* FW entity */ + if (himax_sram_write_crc_check(fw_entry, zf_info_arr[0].sram_addr, zf_info_arr[0].fw_addr, zf_info_arr[0].write_size) != 0) + E("%s, HW CRC FAIL\n", __func__); + else + I("%s, HW CRC PASS\n", __func__); + + I("Now sram_min[0]=0x%02X,[1]=0x%02X,[2]=0x%02X,[3]=0x%02X\n", sram_min[0], sram_min[1], sram_min[2], sram_min[3]); + do { + g_core_fp.fp_register_write(sram_min, cfg_sz, FW_buf, 0); + cfg_crc_hw = g_core_fp.fp_check_CRC(sram_min, cfg_sz); + if (cfg_crc_hw != cfg_crc_sw) + E("Config CRC FAIL, HW CRC = %X,SW CRC = %X, retry = %d\n", cfg_crc_hw, cfg_crc_sw, retry); + else + I("Config CRC Pass\n"); + + } while (cfg_crc_hw != cfg_crc_sw && retry-- > 0); + +#ifdef HX_CODE_OVERLAY +#if defined(HX83102D) + /* ovl_idx[0] - sorting */ + /* ovl_idx[1] - gesture */ + /* ovl_idx[2] - border */ + + ovl_idx_t = ovl_idx[0]; + send_data[0] = ovl_sorting_reply; + + if (private_ts->in_self_test == 0) { +#if defined(HX_SMART_WAKEUP) + if (private_ts->suspended && private_ts->SMWP_enable) { + ovl_idx_t = ovl_idx[1]; + send_data[0] = ovl_gesture_reply; + } else { + ovl_idx_t = ovl_idx[2]; + send_data[0] = ovl_border_reply; + } +#else + ovl_idx_t = ovl_idx[2]; + send_data[0] = ovl_border_reply; +#endif +#else + /*do nothing when self testing ??*/ + if (private_ts->in_self_test == 0) { +#ifdef HX_SMART_WAKEUP + /* ovl_sidx - mpap */ + /* ovl_sidx+1 - gesture */ + /* ovl_sidx+2 - border */ + if (private_ts->suspended && private_ts->SMWP_enable) + ovl_sidx = ovl_sidx + 1; + else + ovl_sidx = ovl_sidx + 2; +#else + ovl_sidx = ovl_sidx + 2; +#endif +#endif + + if (himax_sram_write_crc_check(fw_entry, zf_info_arr[ovl_sidx].sram_addr, zf_info_arr[ovl_sidx].fw_addr, zf_info_arr[ovl_sidx].write_size) != 0) + E("%s, Overlay HW CRC FAIL\n", __func__); + else + I("%s, Overlay HW CRC PASS\n", __func__); + +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL) + /*write back system config*/ + g_core_fp.fp_resend_cmd_func(private_ts->suspended); +#endif + +#if defined(HX83102D) + } + I("%s: prepare upgrade overlay section = %d\n", + __func__, ovl_idx_t); + + if (zf_info_arr[ovl_idx_t].write_size == 0) { + send_data[0] = ovl_fault; + E("%s, WRONG overlay section, plese check FW!\n", + __func__); + } else { + if (himax_sram_write_crc_check(fw_entry, + zf_info_arr[ovl_idx_t].sram_addr, + zf_info_arr[ovl_idx_t].fw_addr, + zf_info_arr[ovl_idx_t].write_size) != 0) { + send_data[0] = ovl_fault; + E("%s, Overlay HW CRC FAIL\n", __func__); + } else { + I("%s, Overlay HW CRC PASS\n", __func__); + } + } + + retry = 0; + + do { + g_core_fp.fp_register_write(tmp_addr, DATA_LEN_4, send_data, 0); + g_core_fp.fp_register_read(tmp_addr, DATA_LEN_4, recv_data, 0); + retry++; + } while ((send_data[3] != recv_data[3] || send_data[2] != recv_data[2] || send_data[1] != recv_data[1] || send_data[0] != recv_data[0]) && retry < HIMAX_REG_RETRY_TIMES); +#else +#if defined(HX_SMART_WAKEUP) + /* write overlay handshaking password */ + if (private_ts->SMWP_enable) { + if (private_ts->suspended) + send_data[0] = ovl_gesture_reply; + else + send_data[0] = ovl_border_reply; + + retry = 0; + + do { + g_core_fp.fp_register_write(tmp_addr, DATA_LEN_4, send_data, 0); + g_core_fp.fp_register_read(tmp_addr, DATA_LEN_4, recv_data, 0); + retry++; + } while ((send_data[3] != recv_data[3] || send_data[2] != recv_data[2] || send_data[1] != recv_data[1] || send_data[0] != recv_data[0]) && retry < HIMAX_REG_RETRY_TIMES); + } +#endif + } +#endif +#endif + } else { + g_core_fp.fp_clean_sram_0f(zf_info_arr[0].sram_addr, zf_info_arr[0].write_size, 2); + } + +END_FUNC: + kfree(FW_buf); +ALOC_FW_BUF_FAIL: + kfree(zf_info_arr); +ALOC_ZF_INFO_ARR_FAIL: + return ret; +} + +void himax_mcu_firmware_update_0f(const struct firmware *fw_entry) +{ + int ret = 0; + uint8_t tmp_data[DATA_LEN_4] = {0x01, 0x00, 0x00, 0x00}; + + I("%s,Entering - total FW size=%d\n", __func__, (int)fw_entry->size); + + g_core_fp.fp_register_write(pzf_op->addr_system_reset, 4, pzf_op->data_system_reset, 0); + + g_core_fp.fp_sense_off(false); + + if ((int)fw_entry->size > HX64K) { + ret = himax_zf_part_info(fw_entry); + } else { + /* first 48K */ + if (himax_sram_write_crc_check(fw_entry, pzf_op->data_sram_start_addr, 0, HX_48K_SZ) != 0) + E("%s, HW CRC FAIL - Main SRAM 48K\n", __func__); + + /*config info*/ + if (G_POWERONOF == 1) { + if (himax_sram_write_crc_check(fw_entry, pzf_op->data_cfg_info, 0xC000, 128) != 0) + E("Config info CRC Fail!\n"); + } else { + g_core_fp.fp_clean_sram_0f(pzf_op->data_cfg_info, 128, 2); + } + + if (G_POWERONOF == 1) { + if (himax_sram_write_crc_check(fw_entry, pzf_op->data_fw_cfg_1, 0xC0FE, 528) != 0) + E("FW config 1 CRC Fail!\n"); + } else { + g_core_fp.fp_clean_sram_0f(pzf_op->data_fw_cfg_1, 528, 1); + } + + if (G_POWERONOF == 1) { + if (himax_sram_write_crc_check(fw_entry, pzf_op->data_fw_cfg_3, 0xCA00, 128) != 0) + E("FW config 3 CRC Fail!\n"); + } else { + g_core_fp.fp_clean_sram_0f(pzf_op->data_fw_cfg_3, 128, 2); + } + + /*ADC config*/ + if (G_POWERONOF == 1) { + if (himax_sram_write_crc_check(fw_entry, pzf_op->data_adc_cfg_1, 0xD640, 1200) != 0) + E("ADC config 1 CRC Fail!\n"); + } else { + g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_1, 1200, 2); + } + + if (G_POWERONOF == 1) { + if (himax_sram_write_crc_check(fw_entry, pzf_op->data_adc_cfg_2, 0xD320, 800) != 0) + E("ADC config 2 CRC Fail!\n"); + } else { + g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_2, 800, 2); + } + + /*mapping table*/ + if (G_POWERONOF == 1) { + if (himax_sram_write_crc_check(fw_entry, pzf_op->data_map_table, 0xE000, 1536) != 0) + E("Mapping table CRC Fail!\n"); + } else { + g_core_fp.fp_clean_sram_0f(pzf_op->data_map_table, 1536, 2); + } + } + + /* set n frame=0*/ + /*if (G_POWERONOF == 1) + * g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_mode_switch, 0xC30C, 4); + *else + * g_core_fp.fp_clean_sram_0f(pzf_op->data_mode_switch, 4, 2); + */ + g_core_fp.fp_register_write(pfw_op->addr_set_frame_addr, 4, tmp_data, 0); + + I("%s, End\n", __func__); +} + +int hx_0f_op_file_dirly(char *file_name) +{ + int err = NO_ERR, ret; + const struct firmware *fw_entry = NULL; + + + I("%s, Entering\n", __func__); + I("file name = %s\n", file_name); + ret = request_firmware(&fw_entry, file_name, private_ts->dev); + if (ret < 0) { +#if defined(__EMBEDDED_FW__) + fw_entry = &g_embedded_fw; + I("%s: Couldn't find userspace FW, use embedded FW(size:%zu) instead.\n", __func__, g_embedded_fw.size); +#else + E("%s, fail in line%d error code=%d,file maybe fail\n", __func__, __LINE__, ret); + return ret; +#endif + } + + himax_int_enable(0); + + if (g_f_0f_updat == 1) { + I("%s:[Warning]Other thread is updating now!\n", __func__); + err = -1; + goto END; + } else { + I("%s:Entering Update Flow!\n", __func__); + g_f_0f_updat = 1; + } + + g_core_fp.fp_firmware_update_0f(fw_entry); + if (ret >= 0) + release_firmware(fw_entry); + + g_f_0f_updat = 0; +END: + I("%s, END\n", __func__); + return err; +} + +int himax_mcu_0f_operation_dirly(void) +{ + int err = NO_ERR, ret; + const struct firmware *fw_entry = NULL; + + I("%s, Entering\n", __func__); + I("file name = %s\n", i_CTPM_firmware_name); + ret = request_firmware(&fw_entry, i_CTPM_firmware_name, private_ts->dev); + if (ret < 0) { +#if defined(__EMBEDDED_FW__) + fw_entry = &g_embedded_fw; + I("%s: Couldn't find userspace FW, use embedded FW(size:%zu) instead.\n", __func__, g_embedded_fw.size); +#else + E("%s, fail in line%d error code=%d,file maybe fail\n", __func__, __LINE__, ret); + return ret; +#endif + } + + himax_int_enable(0); + + if (g_f_0f_updat == 1) { + I("%s:[Warning]Other thread is updating now!\n", __func__); + err = -1; + goto END; + } else { + I("%s:Entering Update Flow!\n", __func__); + g_f_0f_updat = 1; + } + + g_core_fp.fp_firmware_update_0f(fw_entry); + if (ret >= 0) + release_firmware(fw_entry); + + g_f_0f_updat = 0; +END: + I("%s, END\n", __func__); + return err; +} + +void himax_mcu_0f_operation(struct work_struct *work) +{ + int err = NO_ERR; + const struct firmware *fw_entry = NULL; + + I("%s, Entering\n", __func__); + I("file name = %s\n", i_CTPM_firmware_name); + err = request_firmware(&fw_entry, i_CTPM_firmware_name, private_ts->dev); + if (err < 0) { +#if defined(__EMBEDDED_FW__) + fw_entry = &g_embedded_fw; + I("%s: Couldn't find userspace FW, use embedded FW(size:%zu) instead.\n", __func__, g_embedded_fw.size); +#else + E("%s, fail in line%d error code=%d,file maybe fail\n", __func__, __LINE__, err); + goto END; +#endif + } + + if (g_f_0f_updat == 1) { + I("%s:[Warning]Other thread is updating now!\n", __func__); + goto END; + } else { + I("%s:Entering Update Flow!\n", __func__); + g_f_0f_updat = 1; + } + + himax_int_enable(0); + + g_core_fp.fp_firmware_update_0f(fw_entry); + if (err >= 0) + release_firmware(fw_entry); + + g_core_fp.fp_reload_disable(0); + g_core_fp.fp_read_FW_ver(); + /*msleep (10);*/ + g_core_fp.fp_touch_information(); + /*msleep (10);*/ + g_core_fp.fp_sense_on(0x00); + /*msleep (10);*/ + I("%s:End\n", __func__); + himax_int_enable(1); + + g_f_0f_updat = 0; +END: + I("%s, END\n", __func__); +} + +static int himax_mcu_0f_esd_check(void) +{ + return NO_ERR; +} + + +#ifdef HX_0F_DEBUG +void himax_mcu_read_sram_0f(const struct firmware *fw_entry, uint8_t *addr, int start_index, int read_len) +{ + int total_read_times = 0; + int max_bus_size = MAX_I2C_TRANS_SZ; + int total_size_temp = 0; + int total_size = 0; + int address = 0; + int i = 0, j = 0; + int not_same = 0; + + uint8_t tmp_addr[4]; + uint8_t *temp_info_data; + int *not_same_buff; + + I("%s, Entering\n", __func__); + + g_core_fp.fp_burst_enable(1); + + total_size = read_len; + + total_size_temp = read_len; + +#if defined(HX_SPI_OPERATION) + if (read_len > 2048) + max_bus_size = 2048; + else + max_bus_size = read_len; +#else + if (read_len > 240) + max_bus_size = 240; + else + max_bus_size = read_len; +#endif + + + temp_info_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL); + not_same_buff = kcalloc(total_size, sizeof(int), GFP_KERNEL); + + + tmp_addr[3] = addr[3]; + tmp_addr[2] = addr[2]; + tmp_addr[1] = addr[1]; + tmp_addr[0] = addr[0]; + I("%s, read addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n", __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + + I("%s, total size=%d\n", __func__, total_size); + + g_core_fp.fp_burst_enable(1); + + if (total_size % max_bus_size == 0) + total_read_times = total_size / max_bus_size; + else + total_read_times = total_size / max_bus_size + 1; + + for (i = 0; i < (total_read_times); i++) { + if (total_size_temp >= max_bus_size) { + g_core_fp.fp_register_read(tmp_addr, max_bus_size, &temp_info_data[i*max_bus_size], false); + total_size_temp = total_size_temp - max_bus_size; + } else { + g_core_fp.fp_register_read(tmp_addr, total_size_temp % max_bus_size, &temp_info_data[i*max_bus_size], false); + } + + address = ((i+1) * max_bus_size); + tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); + if (tmp_addr[0] < addr[0]) + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF) + 1; + else + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); + + /*msleep (10);*/ + } + I("%s, READ Start\n", __func__); + I("%s, start_index = %d\n", __func__, start_index); + j = start_index; + for (i = 0; i < read_len; i++, j++) { + if (fw_entry->data[j] != temp_info_data[i]) { + not_same++; + not_same_buff[i] = 1; + } + + I("0x%2.2X, ", temp_info_data[i]); + + if (i > 0 && i%16 == 15) + pr_info("\n"); + + } + I("%s, READ END\n", __func__); + I("%s, Not Same count=%d\n", __func__, not_same); + if (not_same != 0) { + j = start_index; + for (i = 0; i < read_len; i++, j++) { + if (not_same_buff[i] == 1) + I("bin = [%d] 0x%2.2X\n", i, fw_entry->data[j]); + } + for (i = 0; i < read_len; i++, j++) { + if (not_same_buff[i] == 1) + I("sram = [%d] 0x%2.2X\n", i, temp_info_data[i]); + } + } + I("%s, READ END\n", __func__); + I("%s, Not Same count=%d\n", __func__, not_same); + I("%s, END\n", __func__); + + kfree(not_same_buff); + kfree(temp_info_data); +} + +void himax_mcu_read_all_sram(uint8_t *addr, int read_len) +{ + int total_read_times = 0; + int max_bus_size = MAX_I2C_TRANS_SZ; + int total_size_temp = 0; + int total_size = 0; + int address = 0; + int i = 0; + /* struct file *fn; */ + /* struct filename *vts_name; */ + + uint8_t tmp_addr[4]; + uint8_t *temp_info_data; + + I("%s, Entering\n", __func__); + + g_core_fp.fp_burst_enable(1); + + total_size = read_len; + + total_size_temp = read_len; + + temp_info_data = kcalloc(total_size, sizeof(uint8_t), GFP_KERNEL); + + + tmp_addr[3] = addr[3]; + tmp_addr[2] = addr[2]; + tmp_addr[1] = addr[1]; + tmp_addr[0] = addr[0]; + I("%s, read addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n", __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + + I("%s, total size=%d\n", __func__, total_size); + + if (total_size % max_bus_size == 0) + total_read_times = total_size / max_bus_size; + else + total_read_times = total_size / max_bus_size + 1; + + for (i = 0; i < (total_read_times); i++) { + if (total_size_temp >= max_bus_size) { + g_core_fp.fp_register_read(tmp_addr, max_bus_size, &temp_info_data[i*max_bus_size], false); + total_size_temp = total_size_temp - max_bus_size; + } else { + g_core_fp.fp_register_read(tmp_addr, total_size_temp % max_bus_size, &temp_info_data[i*max_bus_size], false); + } + + address = ((i+1) * max_bus_size); + tmp_addr[1] = addr[1] + (uint8_t) ((address>>8) & 0x00FF); + tmp_addr[0] = addr[0] + (uint8_t) ((address) & 0x00FF); + + /*msleep (10);*/ + } + I("%s, NOW addr tmp_addr[3]=0x%2.2X, tmp_addr[2]=0x%2.2X, tmp_addr[1]=0x%2.2X, tmp_addr[0]=0x%2.2X\n", __func__, tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + /*for(i = 0;i 0 && i%16 == 15) + * printk("\n"); + *} + */ + + /* need modify + * I("Now Write File start!\n"); + * vts_name = kp_getname_kernel("/sdcard/dump_dsram.txt"); + * fn = kp_file_open_name(vts_name, O_CREAT | O_WRONLY, 0); + * if (!IS_ERR (fn)) { + * I("%s create file and ready to write\n", __func__); + * fn->f_op->write (fn, temp_info_data, read_len*sizeof (uint8_t), &fn->f_pos); + * filp_close (fn, NULL); + * } + * I("Now Write File End!\n"); + */ + + I("%s, END\n", __func__); + + kfree(temp_info_data); +} + +void himax_mcu_firmware_read_0f(const struct firmware *fw_entry, int type) +{ + uint8_t tmp_addr[4]; + + I("%s, Entering\n", __func__); + if (type == 0) { /* first 48K */ + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_sram_start_addr, 0, HX_48K_SZ); + g_core_fp.fp_read_all_sram(tmp_addr, 0xC000); + } else { /*last 16k*/ + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_cfg_info, 0xC000, 132); + + /*FW config*/ + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_fw_cfg_1, 0xC0FE, 484); + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_fw_cfg_2, 0xC9DE, 36); + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_fw_cfg_3, 0xCA00, 72); + + /*ADC config*/ + + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_1, 0xD630, 1188); + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_2, 0xD318, 792); + + + /*mapping table*/ + g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_map_table, 0xE000, 1536); + + /* set n frame=0*/ + g_core_fp.fp_read_sram_0f(fw_entry, pfw_op->addr_set_frame_addr, 0xC30C, 4); + } + + I("%s, END\n", __func__); +} + +void himax_mcu_0f_operation_check(int type) +{ + int err = NO_ERR; + const struct firmware *fw_entry = NULL; + /* char *firmware_name = "himax.bin"; */ + + + I("%s, Entering\n", __func__); + I("file name = %s\n", i_CTPM_firmware_name); + + + err = request_firmware(&fw_entry, i_CTPM_firmware_name, private_ts->dev); + if (err < 0) { +#if defined(__EMBEDDED_FW__) + fw_entry = &g_embedded_fw; + I("%s: Couldn't find userspace FW, use embedded FW(size:%zu) instead.\n", __func__, g_embedded_fw.size); +#else + E("%s, fail in line%d error code=%d\n", __func__, __LINE__, err); + return; +#endif + } + + I("first 4 bytes 0x%2X, 0x%2X, 0x%2X, 0x%2X !\n", fw_entry->data[0], fw_entry->data[1], fw_entry->data[2], fw_entry->data[3]); + I("next 4 bytes 0x%2X, 0x%2X, 0x%2X, 0x%2X !\n", fw_entry->data[4], fw_entry->data[5], fw_entry->data[6], fw_entry->data[7]); + I("and next 4 bytes 0x%2X, 0x%2X, 0x%2X, 0x%2X !\n", fw_entry->data[8], fw_entry->data[9], fw_entry->data[10], fw_entry->data[11]); + + g_core_fp.fp_firmware_read_0f(fw_entry, type); + + if (err >= 0) + release_firmware(fw_entry); + I("%s, END\n", __func__); +} +#endif + +#ifdef HX_CODE_OVERLAY +int himax_mcu_0f_overlay(int ovl_type, int mode) +{ + return NO_ERR; +} +#endif + +#endif + + +#ifdef HIMAX_PALM_SENSOR_EN +int himax_mcu_palm_detection(int mode) +{ + uint8_t data_byte[DATA_LEN_4]; + uint8_t tmp_addr[4]; + I("%s: set palm detection mode to %d", __func__, mode); + if (mode) + himax_in_parse_assign_cmd(palm_detection_register_enable, data_byte, 4); + else + himax_in_parse_assign_cmd(palm_detection_register_disable, data_byte, 4); + + g_core_fp.fp_register_write(pfw_op->addr_palm_detection_enable, DATA_LEN_4, data_byte, 0); + g_core_fp.fp_register_read(pfw_op->addr_palm_detection_enable, DATA_LEN_4, tmp_addr, 0); + I("%s: reg=0x%02X%02X%02X%02X.", __func__, tmp_addr[0],tmp_addr[1],tmp_addr[2],tmp_addr[3]); + + return 0; +} +#endif + +#ifdef CORE_INIT +/* init start */ +static void himax_mcu_fp_init(void) +{ +#ifdef CORE_IC + g_core_fp.fp_burst_enable = himax_mcu_burst_enable; + g_core_fp.fp_register_read = himax_mcu_register_read; + /*g_core_fp.fp_flash_write_burst = himax_mcu_flash_write_burst;*/ + /*g_core_fp.fp_flash_write_burst_lenth = himax_mcu_flash_write_burst_lenth;*/ + g_core_fp.fp_register_write = himax_mcu_register_write; + g_core_fp.fp_interface_on = himax_mcu_interface_on; + g_core_fp.fp_sense_on = himax_mcu_sense_on; + g_core_fp.fp_sense_off = himax_mcu_sense_off; + g_core_fp.fp_wait_wip = himax_mcu_wait_wip; + g_core_fp.fp_init_psl = himax_mcu_init_psl; + g_core_fp.fp_resume_ic_action = himax_mcu_resume_ic_action; + g_core_fp.fp_suspend_ic_action = himax_mcu_suspend_ic_action; + g_core_fp.fp_power_on_init = himax_mcu_power_on_init; + g_core_fp.fp_dd_clk_set = himax_mcu_dd_clk_set; + g_core_fp.fp_dd_reg_en = himax_mcu_dd_reg_en; + g_core_fp.fp_ic_id_read = himax_mcu_ic_id_read; + g_core_fp.fp_dd_reg_write = himax_mcu_dd_reg_write; + g_core_fp.fp_dd_reg_read = himax_mcu_dd_reg_read; +#endif +#ifdef CORE_FW + g_core_fp.fp_system_reset = himax_mcu_system_reset; + g_core_fp.fp_Calculate_CRC_with_AP = himax_mcu_Calculate_CRC_with_AP; + g_core_fp.fp_check_CRC = himax_mcu_check_CRC; + g_core_fp.fp_set_reload_cmd = himax_mcu_set_reload_cmd; + g_core_fp.fp_program_reload = himax_mcu_program_reload; +#ifdef HX_P_SENSOR + g_core_fp.fp_ulpm_in = himax_mcu_ulpm_in; + g_core_fp.fp_black_gest_ctrl = himax_mcu_black_gest_ctrl; +#endif + g_core_fp.fp_set_SMWP_enable = himax_mcu_set_SMWP_enable; +#ifdef HX_EDGE_LIMIT + g_core_fp.fp_set_edge_limit_enable = himax_mcu_set_edge_limit_enable; +#endif + g_core_fp.fp_set_HSEN_enable = himax_mcu_set_HSEN_enable; + g_core_fp.fp_usb_detect_set = himax_mcu_usb_detect_set; + g_core_fp.fp_diag_register_set = himax_mcu_diag_register_set; + g_core_fp.fp_chip_self_test = himax_mcu_chip_self_test; + g_core_fp.fp_idle_mode = himax_mcu_idle_mode; + g_core_fp.fp_reload_disable = himax_mcu_reload_disable; + g_core_fp.fp_check_chip_version = himax_mcu_check_chip_version; + g_core_fp.fp_read_ic_trigger_type = himax_mcu_read_ic_trigger_type; + g_core_fp.fp_read_i2c_status = himax_mcu_read_i2c_status; + g_core_fp.fp_read_FW_ver = himax_mcu_read_FW_ver; + g_core_fp.fp_read_event_stack = himax_mcu_read_event_stack; + g_core_fp.fp_return_event_stack = himax_mcu_return_event_stack; + g_core_fp.fp_calculateChecksum = himax_mcu_calculateChecksum; + g_core_fp.fp_read_FW_status = himax_mcu_read_FW_status; + g_core_fp.fp_irq_switch = himax_mcu_irq_switch; + g_core_fp.fp_assign_sorting_mode = himax_mcu_assign_sorting_mode; + g_core_fp.fp_check_sorting_mode = himax_mcu_check_sorting_mode; + g_core_fp.fp_switch_mode = himax_mcu_switch_mode; + g_core_fp.fp_get_max_dc = himax_mcu_get_max_dc; + g_core_fp.fp_read_DD_status = himax_mcu_read_DD_status; +#if defined(HX_AUTO_UPDATE_FW) + g_core_fp._diff_overlay_bin = hx_mcu_diff_overlay_bin; +#endif +#endif +#ifdef CORE_FLASH + g_core_fp.fp_chip_erase = himax_mcu_chip_erase; + g_core_fp.fp_block_erase = himax_mcu_block_erase; + g_core_fp.fp_sector_erase = himax_mcu_sector_erase; + g_core_fp.fp_flash_programming = himax_mcu_flash_programming; + g_core_fp.fp_flash_page_write = himax_mcu_flash_page_write; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_32k; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_60k; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_64k; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_124k; + g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k = himax_mcu_fts_ctpm_fw_upgrade_with_sys_fs_128k; + g_core_fp.fp_flash_dump_func = himax_mcu_flash_dump_func; + g_core_fp.fp_flash_lastdata_check = himax_mcu_flash_lastdata_check; + g_core_fp._diff_overlay_flash = hx_mcu_diff_overlay_flash; +#endif +#ifdef CORE_SRAM + g_core_fp.fp_sram_write = himax_mcu_sram_write; + g_core_fp.fp_sram_verify = himax_mcu_sram_verify; + g_core_fp.fp_get_DSRAM_data = himax_mcu_get_DSRAM_data; +#endif +#ifdef CORE_DRIVER + g_core_fp.fp_chip_init = himax_mcu_init_ic; +#ifdef HX_AUTO_UPDATE_FW + g_core_fp.fp_fw_ver_bin = himax_mcu_fw_ver_bin; +#endif +#ifdef HX_RST_PIN_FUNC + g_core_fp.fp_pin_reset = himax_mcu_pin_reset; + g_core_fp.fp_ic_reset = himax_mcu_ic_reset; +#endif + g_core_fp.fp_touch_information = himax_mcu_touch_information; + g_core_fp.fp_reload_config = himax_mcu_reload_config; + g_core_fp.fp_get_touch_data_size = himax_mcu_get_touch_data_size; + g_core_fp.fp_hand_shaking = himax_mcu_hand_shaking; + g_core_fp.fp_determin_diag_rawdata = himax_mcu_determin_diag_rawdata; + g_core_fp.fp_determin_diag_storage = himax_mcu_determin_diag_storage; + g_core_fp.fp_cal_data_len = himax_mcu_cal_data_len; + g_core_fp.fp_diag_check_sum = himax_mcu_diag_check_sum; + g_core_fp.fp_diag_parse_raw_data = himax_mcu_diag_parse_raw_data; +#ifdef HX_ESD_RECOVERY + g_core_fp.fp_ic_esd_recovery = himax_mcu_ic_esd_recovery; + g_core_fp.fp_esd_ic_reset = himax_mcu_esd_ic_reset; +#endif +#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL) + g_core_fp.fp_resend_cmd_func = himax_mcu_resend_cmd_func; +#endif +#if defined(HX_TP_PROC_GUEST_INFO) + g_core_fp.guest_info_get_status = himax_guest_info_get_status; + g_core_fp.read_guest_info = hx_read_guest_info; +#endif +#endif +#ifdef HX_ZERO_FLASH + g_core_fp.fp_reload_disable = hx_dis_rload_0f; + g_core_fp.fp_clean_sram_0f = himax_mcu_clean_sram_0f; + g_core_fp.fp_write_sram_0f = himax_mcu_write_sram_0f; + g_core_fp.fp_write_sram_0f_crc = himax_sram_write_crc_check; + g_core_fp.fp_firmware_update_0f = himax_mcu_firmware_update_0f; + g_core_fp.fp_0f_operation = himax_mcu_0f_operation; + g_core_fp.fp_0f_operation_dirly = himax_mcu_0f_operation_dirly; + g_core_fp.fp_0f_op_file_dirly = hx_0f_op_file_dirly; + g_core_fp.fp_0f_esd_check = himax_mcu_0f_esd_check; +#ifdef HX_0F_DEBUG + g_core_fp.fp_read_sram_0f = himax_mcu_read_sram_0f; + g_core_fp.fp_read_all_sram = himax_mcu_read_all_sram; + g_core_fp.fp_firmware_read_0f = himax_mcu_firmware_read_0f; + g_core_fp.fp_0f_operation_check = himax_mcu_0f_operation_check; +#endif +#ifdef HX_CODE_OVERLAY + g_core_fp.fp_0f_overlay = himax_mcu_0f_overlay; +#endif +#ifdef HIMAX_PALM_SENSOR_EN + g_core_fp.fp_palm_detection_function = himax_mcu_palm_detection; +#endif +#endif +} + +int himax_mcu_in_cmd_struct_init(void) +{ + int err = 0; + + I("%s: Entering!\n", __func__); + himax_mcu_cmd_struct_free = himax_mcu_in_cmd_struct_free; + + g_core_cmd_op = kzalloc(sizeof(struct himax_core_command_operation), GFP_KERNEL); + if (g_core_cmd_op == NULL) { + err = -ENOMEM; + goto err_g_core_cmd_op_fail; + } + + g_core_cmd_op->ic_op = kzalloc(sizeof(struct ic_operation), GFP_KERNEL); + if (g_core_cmd_op->ic_op == NULL) { + err = -ENOMEM; + goto err_g_core_cmd_op_ic_op_fail; + } + + g_core_cmd_op->fw_op = kzalloc(sizeof(struct fw_operation), GFP_KERNEL); + if (g_core_cmd_op->fw_op == NULL) { + err = -ENOMEM; + goto err_g_core_cmd_op_fw_op_fail; + } + + g_core_cmd_op->flash_op = kzalloc(sizeof(struct flash_operation), GFP_KERNEL); + if (g_core_cmd_op->flash_op == NULL) { + err = -ENOMEM; + goto err_g_core_cmd_op_flash_op_fail; + } + + g_core_cmd_op->sram_op = kzalloc(sizeof(struct sram_operation), GFP_KERNEL); + if (g_core_cmd_op->sram_op == NULL) { + err = -ENOMEM; + goto err_g_core_cmd_op_sram_op_fail; + } + + g_core_cmd_op->driver_op = kzalloc(sizeof(struct driver_operation), GFP_KERNEL); + if (g_core_cmd_op->driver_op == NULL) { + err = -ENOMEM; + goto err_g_core_cmd_op_driver_op_fail; + } + + pic_op = g_core_cmd_op->ic_op; + pfw_op = g_core_cmd_op->fw_op; + pflash_op = g_core_cmd_op->flash_op; + psram_op = g_core_cmd_op->sram_op; + pdriver_op = g_core_cmd_op->driver_op; +#ifdef HX_ZERO_FLASH + g_core_cmd_op->zf_op = kzalloc(sizeof(struct zf_operation), GFP_KERNEL); + if (g_core_cmd_op->zf_op == NULL) { + err = -ENOMEM; + goto err_g_core_cmd_op_zf_op_fail; + } + pzf_op = g_core_cmd_op->zf_op; + +#endif +#ifndef __MTK_SPI__ + g_internal_buffer = kzalloc(sizeof(uint8_t)*(1024 * 48 + ADDR_LEN_4), GFP_KERNEL); +#else + g_internal_buffer = kzalloc(sizeof(uint8_t)*(HX_SPI_MTK_MAX_WRITE_SZ), GFP_KERNEL); +#endif + if (g_internal_buffer == NULL) { + err = -ENOMEM; + goto err_g_core_cmd_op_g_internal_buffer_fail; + } + himax_mcu_fp_init(); + + return NO_ERR; + +err_g_core_cmd_op_g_internal_buffer_fail: +#ifdef HX_ZERO_FLASH + kfree(g_core_cmd_op->zf_op); + g_core_cmd_op->zf_op = NULL; +err_g_core_cmd_op_zf_op_fail: +#endif + kfree(g_core_cmd_op->driver_op); + g_core_cmd_op->driver_op = NULL; +err_g_core_cmd_op_driver_op_fail: + kfree(g_core_cmd_op->sram_op); + g_core_cmd_op->sram_op = NULL; +err_g_core_cmd_op_sram_op_fail: + kfree(g_core_cmd_op->flash_op); + g_core_cmd_op->flash_op = NULL; +err_g_core_cmd_op_flash_op_fail: + kfree(g_core_cmd_op->fw_op); + g_core_cmd_op->fw_op = NULL; +err_g_core_cmd_op_fw_op_fail: + kfree(g_core_cmd_op->ic_op); + g_core_cmd_op->ic_op = NULL; +err_g_core_cmd_op_ic_op_fail: + kfree(g_core_cmd_op); + g_core_cmd_op = NULL; +err_g_core_cmd_op_fail: + + return err; +} +EXPORT_SYMBOL(himax_mcu_in_cmd_struct_init); + +void himax_mcu_in_cmd_struct_free(void) +{ + pic_op = NULL; + pfw_op = NULL; + pflash_op = NULL; + psram_op = NULL; + pdriver_op = NULL; + kfree(g_internal_buffer); + g_internal_buffer = NULL; +#ifdef HX_ZERO_FLASH + kfree(g_core_cmd_op->zf_op); + g_core_cmd_op->zf_op = NULL; +#endif + kfree(g_core_cmd_op->driver_op); + g_core_cmd_op->driver_op = NULL; + kfree(g_core_cmd_op->sram_op); + g_core_cmd_op->sram_op = NULL; + kfree(g_core_cmd_op->flash_op); + g_core_cmd_op->flash_op = NULL; + kfree(g_core_cmd_op->fw_op); + g_core_cmd_op->fw_op = NULL; + kfree(g_core_cmd_op->ic_op); + g_core_cmd_op->ic_op = NULL; + kfree(g_core_cmd_op); + g_core_cmd_op = NULL; +#if defined(HX_EN_DYNAMIC_NAME) + if (i_CTPM_firmware_name != NULL) { + kfree(i_CTPM_firmware_name); + i_CTPM_firmware_name = NULL; + } +#endif + + I("%s: release completed\n", __func__); +} + +void himax_in_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len) +{ + /*I("%s: Entering!\n", __func__);*/ + switch (len) { + case 1: + cmd[0] = addr; + /*I("%s: cmd[0] = 0x%02X\n", __func__, cmd[0]);*/ + break; + + case 2: + cmd[0] = addr % 0x100; + cmd[1] = (addr >> 8) % 0x100; + /*I("%s: cmd[0] = 0x%02X,cmd[1] = 0x%02X\n", __func__, cmd[0], cmd[1]);*/ + break; + + case 4: + cmd[0] = addr % 0x100; + cmd[1] = (addr >> 8) % 0x100; + cmd[2] = (addr >> 16) % 0x100; + cmd[3] = addr / 0x1000000; + /* I("%s: cmd[0] = 0x%02X,cmd[1] = 0x%02X,cmd[2] = 0x%02X,cmd[3] = 0x%02X\n", */ + /* __func__, cmd[0], cmd[1], cmd[2], cmd[3]);*/ + break; + + default: + E("%s: input length fault,len = %d!\n", __func__, len); + } +} +EXPORT_SYMBOL(himax_in_parse_assign_cmd); + +void himax_mcu_in_cmd_init(void) +{ + I("%s: Entering!\n", __func__); + +#ifdef HIMAX_PALM_SENSOR_EN + himax_in_parse_assign_cmd(palm_detection_register, pfw_op->addr_palm_detection_enable, sizeof(pfw_op->addr_palm_detection_enable)); +#endif +#ifdef CORE_IC + himax_in_parse_assign_cmd(ic_adr_ahb_addr_byte_0, pic_op->addr_ahb_addr_byte_0, sizeof(pic_op->addr_ahb_addr_byte_0)); + himax_in_parse_assign_cmd(ic_adr_ahb_rdata_byte_0, pic_op->addr_ahb_rdata_byte_0, sizeof(pic_op->addr_ahb_rdata_byte_0)); + himax_in_parse_assign_cmd(ic_adr_ahb_access_direction, pic_op->addr_ahb_access_direction, sizeof(pic_op->addr_ahb_access_direction)); + himax_in_parse_assign_cmd(ic_adr_conti, pic_op->addr_conti, sizeof(pic_op->addr_conti)); + himax_in_parse_assign_cmd(ic_adr_incr4, pic_op->addr_incr4, sizeof(pic_op->addr_incr4)); + himax_in_parse_assign_cmd(ic_adr_i2c_psw_lb, pic_op->adr_i2c_psw_lb, sizeof(pic_op->adr_i2c_psw_lb)); + himax_in_parse_assign_cmd(ic_adr_i2c_psw_ub, pic_op->adr_i2c_psw_ub, sizeof(pic_op->adr_i2c_psw_ub)); + himax_in_parse_assign_cmd(ic_cmd_ahb_access_direction_read, pic_op->data_ahb_access_direction_read, sizeof(pic_op->data_ahb_access_direction_read)); + himax_in_parse_assign_cmd(ic_cmd_conti, pic_op->data_conti, sizeof(pic_op->data_conti)); + himax_in_parse_assign_cmd(ic_cmd_incr4, pic_op->data_incr4, sizeof(pic_op->data_incr4)); + himax_in_parse_assign_cmd(ic_cmd_i2c_psw_lb, pic_op->data_i2c_psw_lb, sizeof(pic_op->data_i2c_psw_lb)); + himax_in_parse_assign_cmd(ic_cmd_i2c_psw_ub, pic_op->data_i2c_psw_ub, sizeof(pic_op->data_i2c_psw_ub)); + himax_in_parse_assign_cmd(ic_adr_tcon_on_rst, pic_op->addr_tcon_on_rst, sizeof(pic_op->addr_tcon_on_rst)); + himax_in_parse_assign_cmd(ic_addr_adc_on_rst, pic_op->addr_adc_on_rst, sizeof(pic_op->addr_adc_on_rst)); + himax_in_parse_assign_cmd(ic_adr_psl, pic_op->addr_psl, sizeof(pic_op->addr_psl)); + himax_in_parse_assign_cmd(ic_adr_cs_central_state, pic_op->addr_cs_central_state, sizeof(pic_op->addr_cs_central_state)); + himax_in_parse_assign_cmd(ic_cmd_rst, pic_op->data_rst, sizeof(pic_op->data_rst)); + himax_in_parse_assign_cmd(ic_adr_osc_en, pic_op->adr_osc_en, sizeof(pic_op->adr_osc_en)); + himax_in_parse_assign_cmd(ic_adr_osc_pw, pic_op->adr_osc_pw, sizeof(pic_op->adr_osc_pw)); +#endif +#ifdef CORE_FW + himax_in_parse_assign_cmd(fw_addr_system_reset, pfw_op->addr_system_reset, sizeof(pfw_op->addr_system_reset)); + himax_in_parse_assign_cmd(fw_addr_safe_mode_release_pw, pfw_op->addr_safe_mode_release_pw, sizeof(pfw_op->addr_safe_mode_release_pw)); + himax_in_parse_assign_cmd(fw_addr_ctrl_fw, pfw_op->addr_ctrl_fw_isr, sizeof(pfw_op->addr_ctrl_fw_isr)); + himax_in_parse_assign_cmd(fw_addr_flag_reset_event, pfw_op->addr_flag_reset_event, sizeof(pfw_op->addr_flag_reset_event)); + himax_in_parse_assign_cmd(fw_addr_hsen_enable, pfw_op->addr_hsen_enable, sizeof(pfw_op->addr_hsen_enable)); + himax_in_parse_assign_cmd(fw_addr_smwp_enable, pfw_op->addr_smwp_enable, sizeof(pfw_op->addr_smwp_enable)); + himax_in_parse_assign_cmd(fw_addr_program_reload_from, pfw_op->addr_program_reload_from, sizeof(pfw_op->addr_program_reload_from)); + himax_in_parse_assign_cmd(fw_addr_program_reload_to, pfw_op->addr_program_reload_to, sizeof(pfw_op->addr_program_reload_to)); + himax_in_parse_assign_cmd(fw_addr_program_reload_page_write, pfw_op->addr_program_reload_page_write, sizeof(pfw_op->addr_program_reload_page_write)); + himax_in_parse_assign_cmd(fw_addr_raw_out_sel, pfw_op->addr_raw_out_sel, sizeof(pfw_op->addr_raw_out_sel)); + himax_in_parse_assign_cmd(fw_addr_reload_status, pfw_op->addr_reload_status, sizeof(pfw_op->addr_reload_status)); + himax_in_parse_assign_cmd(fw_addr_reload_crc32_result, pfw_op->addr_reload_crc32_result, sizeof(pfw_op->addr_reload_crc32_result)); + himax_in_parse_assign_cmd(fw_addr_reload_addr_from, pfw_op->addr_reload_addr_from, sizeof(pfw_op->addr_reload_addr_from)); + himax_in_parse_assign_cmd(fw_addr_reload_addr_cmd_beat, pfw_op->addr_reload_addr_cmd_beat, sizeof(pfw_op->addr_reload_addr_cmd_beat)); + himax_in_parse_assign_cmd(fw_addr_selftest_addr_en, pfw_op->addr_selftest_addr_en, sizeof(pfw_op->addr_selftest_addr_en)); + himax_in_parse_assign_cmd(fw_addr_criteria_addr, pfw_op->addr_criteria_addr, sizeof(pfw_op->addr_criteria_addr)); + himax_in_parse_assign_cmd(fw_addr_set_frame_addr, pfw_op->addr_set_frame_addr, sizeof(pfw_op->addr_set_frame_addr)); + himax_in_parse_assign_cmd(fw_addr_selftest_result_addr, pfw_op->addr_selftest_result_addr, sizeof(pfw_op->addr_selftest_result_addr)); + himax_in_parse_assign_cmd(fw_addr_sorting_mode_en, pfw_op->addr_sorting_mode_en, sizeof(pfw_op->addr_sorting_mode_en)); + himax_in_parse_assign_cmd(fw_addr_max_dc, pfw_op->addr_max_dc, sizeof(pfw_op->addr_max_dc)); + himax_in_parse_assign_cmd(fw_addr_fw_mode_status, pfw_op->addr_fw_mode_status, sizeof(pfw_op->addr_fw_mode_status)); + himax_in_parse_assign_cmd(fw_addr_icid_addr, pfw_op->addr_icid_addr, sizeof(pfw_op->addr_icid_addr)); + himax_in_parse_assign_cmd(fw_addr_trigger_addr, pfw_op->addr_trigger_addr, sizeof(pfw_op->addr_trigger_addr)); + himax_in_parse_assign_cmd(fw_addr_fw_ver_addr, pfw_op->addr_fw_ver_addr, sizeof(pfw_op->addr_fw_ver_addr)); + himax_in_parse_assign_cmd(fw_addr_fw_cfg_addr, pfw_op->addr_fw_cfg_addr, sizeof(pfw_op->addr_fw_cfg_addr)); + himax_in_parse_assign_cmd(fw_addr_fw_vendor_addr, pfw_op->addr_fw_vendor_addr, sizeof(pfw_op->addr_fw_vendor_addr)); + himax_in_parse_assign_cmd(fw_addr_cus_info, pfw_op->addr_cus_info, sizeof(pfw_op->addr_cus_info)); + himax_in_parse_assign_cmd(fw_addr_proj_info, pfw_op->addr_proj_info, sizeof(pfw_op->addr_proj_info)); + himax_in_parse_assign_cmd(fw_addr_fw_state_addr, pfw_op->addr_fw_state_addr, sizeof(pfw_op->addr_fw_state_addr)); + himax_in_parse_assign_cmd(fw_addr_fw_dbg_msg_addr, pfw_op->addr_fw_dbg_msg_addr, sizeof(pfw_op->addr_fw_dbg_msg_addr)); + himax_in_parse_assign_cmd(fw_addr_chk_fw_status, pfw_op->addr_chk_fw_status, sizeof(pfw_op->addr_chk_fw_status)); + himax_in_parse_assign_cmd(fw_addr_dd_handshak_addr, pfw_op->addr_dd_handshak_addr, sizeof(pfw_op->addr_dd_handshak_addr)); + himax_in_parse_assign_cmd(fw_addr_dd_data_addr, pfw_op->addr_dd_data_addr, sizeof(pfw_op->addr_dd_data_addr)); + himax_in_parse_assign_cmd(fw_data_system_reset, pfw_op->data_system_reset, sizeof(pfw_op->data_system_reset)); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_active, pfw_op->data_safe_mode_release_pw_active, sizeof(pfw_op->data_safe_mode_release_pw_active)); + himax_in_parse_assign_cmd(fw_data_clear, pfw_op->data_clear, sizeof(pfw_op->data_clear)); + himax_in_parse_assign_cmd(fw_data_clear, pfw_op->data_clear, sizeof(pfw_op->data_clear)); + himax_in_parse_assign_cmd(fw_data_fw_stop, pfw_op->data_fw_stop, sizeof(pfw_op->data_fw_stop)); + himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, pfw_op->data_safe_mode_release_pw_reset, sizeof(pfw_op->data_safe_mode_release_pw_reset)); + himax_in_parse_assign_cmd(fw_data_program_reload_start, pfw_op->data_program_reload_start, sizeof(pfw_op->data_program_reload_start)); + himax_in_parse_assign_cmd(fw_data_program_reload_compare, pfw_op->data_program_reload_compare, sizeof(pfw_op->data_program_reload_compare)); + himax_in_parse_assign_cmd(fw_data_program_reload_break, pfw_op->data_program_reload_break, sizeof(pfw_op->data_program_reload_break)); + himax_in_parse_assign_cmd(fw_data_selftest_request, pfw_op->data_selftest_request, sizeof(pfw_op->data_selftest_request)); + himax_in_parse_assign_cmd(fw_data_criteria_aa_top, pfw_op->data_criteria_aa_top, sizeof(pfw_op->data_criteria_aa_top)); + himax_in_parse_assign_cmd(fw_data_criteria_aa_bot, pfw_op->data_criteria_aa_bot, sizeof(pfw_op->data_criteria_aa_bot)); + himax_in_parse_assign_cmd(fw_data_criteria_key_top, pfw_op->data_criteria_key_top, sizeof(pfw_op->data_criteria_key_top)); + himax_in_parse_assign_cmd(fw_data_criteria_key_bot, pfw_op->data_criteria_key_bot, sizeof(pfw_op->data_criteria_key_bot)); + himax_in_parse_assign_cmd(fw_data_criteria_avg_top, pfw_op->data_criteria_avg_top, sizeof(pfw_op->data_criteria_avg_top)); + himax_in_parse_assign_cmd(fw_data_criteria_avg_bot, pfw_op->data_criteria_avg_bot, sizeof(pfw_op->data_criteria_avg_bot)); + himax_in_parse_assign_cmd(fw_data_set_frame, pfw_op->data_set_frame, sizeof(pfw_op->data_set_frame)); + himax_in_parse_assign_cmd(fw_data_selftest_ack_hb, pfw_op->data_selftest_ack_hb, sizeof(pfw_op->data_selftest_ack_hb)); + himax_in_parse_assign_cmd(fw_data_selftest_ack_lb, pfw_op->data_selftest_ack_lb, sizeof(pfw_op->data_selftest_ack_lb)); + himax_in_parse_assign_cmd(fw_data_selftest_pass, pfw_op->data_selftest_pass, sizeof(pfw_op->data_selftest_pass)); + himax_in_parse_assign_cmd(fw_data_normal_cmd, pfw_op->data_normal_cmd, sizeof(pfw_op->data_normal_cmd)); + himax_in_parse_assign_cmd(fw_data_normal_status, pfw_op->data_normal_status, sizeof(pfw_op->data_normal_status)); + himax_in_parse_assign_cmd(fw_data_sorting_cmd, pfw_op->data_sorting_cmd, sizeof(pfw_op->data_sorting_cmd)); + himax_in_parse_assign_cmd(fw_data_sorting_status, pfw_op->data_sorting_status, sizeof(pfw_op->data_sorting_status)); + himax_in_parse_assign_cmd(fw_data_dd_request, pfw_op->data_dd_request, sizeof(pfw_op->data_dd_request)); + himax_in_parse_assign_cmd(fw_data_dd_ack, pfw_op->data_dd_ack, sizeof(pfw_op->data_dd_ack)); + himax_in_parse_assign_cmd(fw_data_idle_dis_pwd, pfw_op->data_idle_dis_pwd, sizeof(pfw_op->data_idle_dis_pwd)); + himax_in_parse_assign_cmd(fw_data_idle_en_pwd, pfw_op->data_idle_en_pwd, sizeof(pfw_op->data_idle_en_pwd)); + himax_in_parse_assign_cmd(fw_data_rawdata_ready_hb, pfw_op->data_rawdata_ready_hb, sizeof(pfw_op->data_rawdata_ready_hb)); + himax_in_parse_assign_cmd(fw_data_rawdata_ready_lb, pfw_op->data_rawdata_ready_lb, sizeof(pfw_op->data_rawdata_ready_lb)); + himax_in_parse_assign_cmd(fw_addr_ahb_addr, pfw_op->addr_ahb_addr, sizeof(pfw_op->addr_ahb_addr)); + himax_in_parse_assign_cmd(fw_data_ahb_dis, pfw_op->data_ahb_dis, sizeof(pfw_op->data_ahb_dis)); + himax_in_parse_assign_cmd(fw_data_ahb_en, pfw_op->data_ahb_en, sizeof(pfw_op->data_ahb_en)); + himax_in_parse_assign_cmd(fw_addr_event_addr, pfw_op->addr_event_addr, sizeof(pfw_op->addr_event_addr)); + himax_in_parse_assign_cmd(fw_usb_detect_addr, pfw_op->addr_usb_detect, sizeof(pfw_op->addr_usb_detect)); +#ifdef HX_P_SENSOR + himax_in_parse_assign_cmd(fw_addr_ulpm_33, pfw_op->addr_ulpm_33, sizeof(pfw_op->addr_ulpm_33)); + himax_in_parse_assign_cmd(fw_addr_ulpm_34, pfw_op->addr_ulpm_34, sizeof(pfw_op->addr_ulpm_34)); + himax_in_parse_assign_cmd(fw_data_ulpm_11, pfw_op->data_ulpm_11, sizeof(pfw_op->data_ulpm_11)); + himax_in_parse_assign_cmd(fw_data_ulpm_22, pfw_op->data_ulpm_22, sizeof(pfw_op->data_ulpm_22)); + himax_in_parse_assign_cmd(fw_data_ulpm_33, pfw_op->data_ulpm_33, sizeof(pfw_op->data_ulpm_33)); + himax_in_parse_assign_cmd(fw_data_ulpm_aa, pfw_op->data_ulpm_aa, sizeof(pfw_op->data_ulpm_aa)); +#endif +#endif +#ifdef CORE_FLASH + himax_in_parse_assign_cmd(flash_addr_spi200_trans_fmt, pflash_op->addr_spi200_trans_fmt, sizeof(pflash_op->addr_spi200_trans_fmt)); + himax_in_parse_assign_cmd(flash_addr_spi200_trans_ctrl, pflash_op->addr_spi200_trans_ctrl, sizeof(pflash_op->addr_spi200_trans_ctrl)); + himax_in_parse_assign_cmd(flash_addr_spi200_cmd, pflash_op->addr_spi200_cmd, sizeof(pflash_op->addr_spi200_cmd)); + himax_in_parse_assign_cmd(flash_addr_spi200_addr, pflash_op->addr_spi200_addr, sizeof(pflash_op->addr_spi200_addr)); + himax_in_parse_assign_cmd(flash_addr_spi200_data, pflash_op->addr_spi200_data, sizeof(pflash_op->addr_spi200_data)); + himax_in_parse_assign_cmd(flash_addr_spi200_bt_num, pflash_op->addr_spi200_bt_num, sizeof(pflash_op->addr_spi200_bt_num)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt, sizeof(pflash_op->data_spi200_trans_fmt)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_1, pflash_op->data_spi200_trans_ctrl_1, sizeof(pflash_op->data_spi200_trans_ctrl_1)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_2, pflash_op->data_spi200_trans_ctrl_2, sizeof(pflash_op->data_spi200_trans_ctrl_2)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_3, pflash_op->data_spi200_trans_ctrl_3, sizeof(pflash_op->data_spi200_trans_ctrl_3)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_4, pflash_op->data_spi200_trans_ctrl_4, sizeof(pflash_op->data_spi200_trans_ctrl_4)); + himax_in_parse_assign_cmd(flash_data_spi200_trans_ctrl_5, pflash_op->data_spi200_trans_ctrl_5, sizeof(pflash_op->data_spi200_trans_ctrl_5)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_1, pflash_op->data_spi200_cmd_1, sizeof(pflash_op->data_spi200_cmd_1)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_2, pflash_op->data_spi200_cmd_2, sizeof(pflash_op->data_spi200_cmd_2)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_3, pflash_op->data_spi200_cmd_3, sizeof(pflash_op->data_spi200_cmd_3)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_4, pflash_op->data_spi200_cmd_4, sizeof(pflash_op->data_spi200_cmd_4)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_5, pflash_op->data_spi200_cmd_5, sizeof(pflash_op->data_spi200_cmd_5)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_6, pflash_op->data_spi200_cmd_6, sizeof(pflash_op->data_spi200_cmd_6)); + himax_in_parse_assign_cmd(flash_data_spi200_cmd_7, pflash_op->data_spi200_cmd_7, sizeof(pflash_op->data_spi200_cmd_7)); + himax_in_parse_assign_cmd(flash_data_spi200_addr, pflash_op->data_spi200_addr, sizeof(pflash_op->data_spi200_addr)); +#endif +#ifdef CORE_SRAM + /* sram start*/ + himax_in_parse_assign_cmd(sram_adr_mkey, psram_op->addr_mkey, sizeof(psram_op->addr_mkey)); + himax_in_parse_assign_cmd(sram_adr_rawdata_addr, psram_op->addr_rawdata_addr, sizeof(psram_op->addr_rawdata_addr)); + himax_in_parse_assign_cmd(sram_adr_rawdata_end, psram_op->addr_rawdata_end, sizeof(psram_op->addr_rawdata_end)); + himax_in_parse_assign_cmd(sram_passwrd_start, psram_op->passwrd_start, sizeof(psram_op->passwrd_start)); + himax_in_parse_assign_cmd(sram_passwrd_end, psram_op->passwrd_end, sizeof(psram_op->passwrd_end)); + /* sram end*/ +#endif +#ifdef CORE_DRIVER + himax_in_parse_assign_cmd(driver_addr_fw_define_flash_reload, pdriver_op->addr_fw_define_flash_reload, sizeof(pdriver_op->addr_fw_define_flash_reload)); + himax_in_parse_assign_cmd(driver_addr_fw_define_2nd_flash_reload, pdriver_op->addr_fw_define_2nd_flash_reload, sizeof(pdriver_op->addr_fw_define_2nd_flash_reload)); + himax_in_parse_assign_cmd(driver_addr_fw_define_int_is_edge, pdriver_op->addr_fw_define_int_is_edge, sizeof(pdriver_op->addr_fw_define_int_is_edge)); + himax_in_parse_assign_cmd(driver_addr_fw_define_rxnum_txnum_maxpt, pdriver_op->addr_fw_define_rxnum_txnum_maxpt, sizeof(pdriver_op->addr_fw_define_rxnum_txnum_maxpt)); + himax_in_parse_assign_cmd(driver_addr_fw_define_xy_res_enable, pdriver_op->addr_fw_define_xy_res_enable, sizeof(pdriver_op->addr_fw_define_xy_res_enable)); + himax_in_parse_assign_cmd(driver_addr_fw_define_x_y_res, pdriver_op->addr_fw_define_x_y_res, sizeof(pdriver_op->addr_fw_define_x_y_res)); + himax_in_parse_assign_cmd(driver_data_df_rx, pdriver_op->data_df_rx, sizeof(pdriver_op->data_df_rx)); + himax_in_parse_assign_cmd(driver_data_df_tx, pdriver_op->data_df_tx, sizeof(pdriver_op->data_df_tx)); + himax_in_parse_assign_cmd(driver_data_df_pt, pdriver_op->data_df_pt, sizeof(pdriver_op->data_df_pt)); + himax_in_parse_assign_cmd(driver_data_df_x_res, pdriver_op->data_df_x_res, sizeof(pdriver_op->data_df_x_res)); + himax_in_parse_assign_cmd(driver_data_df_y_res, pdriver_op->data_df_y_res, sizeof(pdriver_op->data_df_y_res)); + himax_in_parse_assign_cmd(driver_data_fw_define_flash_reload_dis, pdriver_op->data_fw_define_flash_reload_dis, sizeof(pdriver_op->data_fw_define_flash_reload_dis)); + himax_in_parse_assign_cmd(driver_data_fw_define_flash_reload_en, pdriver_op->data_fw_define_flash_reload_en, sizeof(pdriver_op->data_fw_define_flash_reload_en)); + himax_in_parse_assign_cmd(driver_data_fw_define_rxnum_txnum_maxpt_sorting, pdriver_op->data_fw_define_rxnum_txnum_maxpt_sorting, sizeof(pdriver_op->data_fw_define_rxnum_txnum_maxpt_sorting)); + himax_in_parse_assign_cmd(driver_data_fw_define_rxnum_txnum_maxpt_normal, pdriver_op->data_fw_define_rxnum_txnum_maxpt_normal, sizeof(pdriver_op->data_fw_define_rxnum_txnum_maxpt_normal)); +#endif +#ifdef HX_ZERO_FLASH + himax_in_parse_assign_cmd(zf_addr_dis_flash_reload, pzf_op->addr_dis_flash_reload, sizeof(pzf_op->addr_dis_flash_reload)); + himax_in_parse_assign_cmd(zf_data_dis_flash_reload, pzf_op->data_dis_flash_reload, sizeof(pzf_op->data_dis_flash_reload)); + himax_in_parse_assign_cmd(zf_addr_system_reset, pzf_op->addr_system_reset, sizeof(pzf_op->addr_system_reset)); + himax_in_parse_assign_cmd(zf_data_system_reset, pzf_op->data_system_reset, sizeof(pzf_op->data_system_reset)); + himax_in_parse_assign_cmd(zf_data_sram_start_addr, pzf_op->data_sram_start_addr, sizeof(pzf_op->data_sram_start_addr)); + himax_in_parse_assign_cmd(zf_data_sram_clean, pzf_op->data_sram_clean, sizeof(pzf_op->data_sram_clean)); + himax_in_parse_assign_cmd(zf_data_cfg_info, pzf_op->data_cfg_info, sizeof(pzf_op->data_cfg_info)); + himax_in_parse_assign_cmd(zf_data_fw_cfg_1, pzf_op->data_fw_cfg_1, sizeof(pzf_op->data_fw_cfg_1)); + himax_in_parse_assign_cmd(zf_data_fw_cfg_2, pzf_op->data_fw_cfg_2, sizeof(pzf_op->data_fw_cfg_2)); + himax_in_parse_assign_cmd(zf_data_fw_cfg_3, pzf_op->data_fw_cfg_3, sizeof(pzf_op->data_fw_cfg_3)); + himax_in_parse_assign_cmd(zf_data_adc_cfg_1, pzf_op->data_adc_cfg_1, sizeof(pzf_op->data_adc_cfg_1)); + himax_in_parse_assign_cmd(zf_data_adc_cfg_2, pzf_op->data_adc_cfg_2, sizeof(pzf_op->data_adc_cfg_2)); + himax_in_parse_assign_cmd(zf_data_adc_cfg_3, pzf_op->data_adc_cfg_3, sizeof(pzf_op->data_adc_cfg_3)); + himax_in_parse_assign_cmd(zf_data_map_table, pzf_op->data_map_table, sizeof(pzf_op->data_map_table)); + /*himax_in_parse_assign_cmd(zf_data_mode_switch, pzf_op->data_mode_switch, sizeof(pzf_op->data_mode_switch));*/ + himax_in_parse_assign_cmd(zf_addr_sts_chk, pzf_op->addr_sts_chk, sizeof(pzf_op->addr_sts_chk)); + himax_in_parse_assign_cmd(zf_data_activ_sts, pzf_op->data_activ_sts, sizeof(pzf_op->data_activ_sts)); + himax_in_parse_assign_cmd(zf_addr_activ_relod, pzf_op->addr_activ_relod, sizeof(pzf_op->addr_activ_relod)); + himax_in_parse_assign_cmd(zf_data_activ_in, pzf_op->data_activ_in, sizeof(pzf_op->data_activ_in)); +#endif +} +EXPORT_SYMBOL(himax_mcu_in_cmd_init); + +/* init end*/ +#endif diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_inspection.c b/drivers/input/touchscreen/himax_v3_mmi/himax_inspection.c old mode 100644 new mode 100755 index b6df106503f3..cd6be9603a41 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_inspection.c +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_inspection.c @@ -1,2305 +1,2235 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for inspection functions - * - * 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_inspection.h" - -static int g_gap_vertical_partial = 3; -static int *g_gap_vertical_part; -static int g_gap_horizontal_partial = 3; -static int *g_gap_horizontal_part; - -static int g_dc_max; - -static int g_1kind_raw_size; -uint32_t g_rslt_data_len; -int **g_inspection_criteria; -int *g_inspt_crtra_flag; -int *g_test_item_flag; -int do_lpwg_test; -int HX_CRITERIA_ITEM; -int HX_CRITERIA_SIZE; -char *g_rslt_data; -bool file_w_flag; -static char g_file_path[256]; -static char g_rslt_log[256]; -static char g_start_log[256]; -#define FAIL_IN_INDEX "%s: %s FAIL in index %d\n" - -char *g_hx_head_str[] = { - "TP_Info", - "Project_Info", - "TestItem", - "TestCriteria", - NULL -}; - -/*Need to map THP_INSPECTION_ENUM*/ -char *g_himax_inspection_mode[] = { - "HIMAX_OPEN", - "HIMAX_MICRO_OPEN", - "HIMAX_SHORT", - "HIMAX_RAWDATA", - "HIMAX_BPN_RAWDATA", - "HIMAX_SC", - "HIMAX_WEIGHT_NOISE", - "HIMAX_ABS_NOISE", - "HIMAX_SORTING", - "HIMAX_GAPTEST_RAW", - /*"HIMAX_GAPTEST_RAW_X",*/ - /*"HIMAX_GAPTEST_RAW_Y",*/ - - "HIMAX_ACT_IDLE_RAWDATA", - "HIMAX_ACT_IDLE_BPN_RAWDATA", - "HIMAX_ACT_IDLE_NOISE", - - "HIMAX_LPWUG_RAWDATA", - "HIMAX_LPWUG_BPN_RAWDATA", - "HIMAX_LPWUG_WEIGHT_NOISE", - "HIMAX_LPWUG_ABS_NOISE", - "HIMAX_LPWUG_IDLE_RAWDATA", - "HIMAX_LPWUG_IDLE_BPN_RAWDATA", - "HIMAX_LPWUG_IDLE_NOISE", - - "HIMAX_BACK_NORMAL", - NULL -}; - -/* for criteria */ -char *g_hx_inspt_crtra_name[] = { - "CRITERIA_RAW_MIN", - "CRITERIA_RAW_MAX", - "CRITERIA_RAW_BPN_MIN", - "CRITERIA_RAW_BPN_MAX", - "CRITERIA_SC_MIN", - "CRITERIA_SC_MAX", - "CRITERIA_SC_GOLDEN", - "CRITERIA_SHORT_MIN", - "CRITERIA_SHORT_MAX", - "CRITERIA_OPEN_MIN", - "CRITERIA_OPEN_MAX", - "CRITERIA_MICRO_OPEN_MIN", - "CRITERIA_MICRO_OPEN_MAX", - "CRITERIA_NOISE_WT_MIN", - "CRITERIA_NOISE_WT_MAX", - "CRITERIA_NOISE_ABS_MIN", - "CRITERIA_NOISE_ABS_MAX", - "CRITERIA_SORT_MIN", - "CRITERIA_SORT_MAX", - - "CRITERIA_GAP_RAW_HOR_MIN", - "CRITERIA_GAP_RAW_HOR_MAX", - "CRITERIA_GAP_RAW_VER_MIN", - "CRITERIA_GAP_RAW_VER_MAX", - - "ACT_IDLE_NOISE_MIN", - "ACT_IDLE_NOISE_MAX", - "ACT_IDLE_RAWDATA_MIN", - "ACT_IDLE_RAWDATA_MAX", - "ACT_IDLE_RAW_BPN_MIN", - "ACT_IDLE_RAW_BPN_MAX", - - "LPWUG_NOISE_WT_MIN", - "LPWUG_NOISE_WT_MAX", - "LPWUG_NOISE_ABS_MIN", - "LPWUG_NOISE_ABS_MAX", - "LPWUG_RAWDATA_MIN", - "LPWUG_RAWDATA_MAX", - "LPWUG_RAW_BPN_MIN", - "LPWUG_RAW_BPN_MAX", - - "LPWUG_IDLE_NOISE_MIN", - "LPWUG_IDLE_NOISE_MAX", - "LPWUG_IDLE_RAWDATA_MIN", - "LPWUG_IDLE_RAWDATA_MAX", - "LPWUG_IDLE_RAW_BPN_MIN", - "LPWUG_IDLE_RAW_BPN_MAX", - NULL -}; - - -void (*fp_himax_self_test_init)(void) = himax_inspection_init; - - -static void himax_press_powerkey(void) -{ - I(" %s POWER KEY event %x press\n", __func__, KEY_POWER); - input_report_key(private_ts->input_dev, KEY_POWER, 1); - input_sync(private_ts->input_dev); - - msleep(100); - - I(" %s POWER KEY event %x release\n", __func__, KEY_POWER); - input_report_key(private_ts->input_dev, KEY_POWER, 0); - input_sync(private_ts->input_dev); -} - - -static uint8_t NOISEMAX; -static uint8_t g_recal_thx; - -static int arraydata_max1, arraydata_max2, arraydata_max3; -static int arraydata_min1, arraydata_min2, arraydata_min3; - -void himax_get_arraydata_edge(uint32_t *RAW) -{ - int temp, i, j; - int len = ic_data->HX_RX_NUM * ic_data->HX_TX_NUM; -// uint32_t ArrayData[len]; - uint32_t *ArrayData = NULL; - ArrayData = kcalloc(len, sizeof(uint32_t), GFP_KERNEL); - if (ArrayData == NULL) { - E("%s, Failed to allocate memory\n", __func__); - return; - } - - for (i = 0; i < len; i++) - ArrayData[i] = RAW[i]; - for (j = len-1; j > 0; j--) { /*min to max*/ - for (i = 0; i < j; i++) { - if (ArrayData[i] > ArrayData[i+1]) { - temp = ArrayData[i]; - ArrayData[i] = ArrayData[i+1]; - ArrayData[i+1] = temp; - } - } - } - - arraydata_min1 = ArrayData[0]; - arraydata_min2 = ArrayData[1]; - arraydata_min3 = ArrayData[2]; - arraydata_max1 = ArrayData[len-3]; - arraydata_max2 = ArrayData[len-2]; - arraydata_max3 = ArrayData[len-1]; - kfree(ArrayData); -} - -static int hx_test_data_get(uint32_t RAW[], char *start_log, char *result, - int now_item) -{ - uint32_t i; - - ssize_t len = 0; - char *testdata = NULL; - uint32_t SZ_SIZE = g_1kind_raw_size; - - I("%s: Entering, Now type=%s!\n", __func__, - g_himax_inspection_mode[now_item]); - - testdata = kzalloc(sizeof(char) * SZ_SIZE, GFP_KERNEL); - if (testdata == NULL) { - E("%s: Memory allocation falied!\n", __func__); - return MEM_ALLOC_FAIL; - } - - len += snprintf((testdata + len), SZ_SIZE - len, "%s", start_log); - for (i = 0; i < ic_data->HX_TX_NUM*ic_data->HX_RX_NUM; i++) { - if (i > 1 && ((i + 1) % ic_data->HX_RX_NUM) == 0) - len += snprintf((testdata + len), SZ_SIZE - len, - "%5d,\n", RAW[i]); - else - len += snprintf((testdata + len), SZ_SIZE - len, - "%5d,", RAW[i]); - } - len += snprintf((testdata + len), SZ_SIZE - len, "\n%s", result); - - memcpy(&g_rslt_data[0], testdata, len); - g_rslt_data_len = len; - I("%s: g_rslt_data_len=%d!\n", __func__, g_rslt_data_len); - - /* dbg */ - /* for(i = 0; i < SZ_SIZE; i++) - * { - * I("0x%04X, ", g_rslt_data[i + (now_item * SZ_SIZE)]); - * if(i > 0 && (i % 16 == 15)) - * PI("\n"); - * } - */ - - kfree(testdata); - I("%s: End!\n", __func__); - return NO_ERR; -} - -static int himax_switch_mode_inspection(int mode) -{ - uint8_t tmp_addr[4]; - uint8_t tmp_data[4] = {0}; - - I("%s: Entering\n", __func__); - - /*Stop Handshaking*/ - himax_parse_assign_cmd(sram_adr_rawdata_addr, tmp_addr, - sizeof(tmp_addr)); - g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); - - /*Swtich Mode*/ - switch (mode) { - case HX_SORTING: - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = PWD_SORTING_START; - tmp_data[0] = PWD_SORTING_START; - break; - case HX_OPEN: - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = PWD_OPEN_START; - tmp_data[0] = PWD_OPEN_START; - break; - case HX_MICRO_OPEN: - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = PWD_OPEN_START; - tmp_data[0] = PWD_OPEN_START; - break; - case HX_SHORT: - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = PWD_SHORT_START; - tmp_data[0] = PWD_SHORT_START; - break; - - case HX_GAPTEST_RAW: - case HX_RAWDATA: - case HX_BPN_RAWDATA: - case HX_SC: - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = PWD_RAWDATA_START; - tmp_data[0] = PWD_RAWDATA_START; - break; - - case HX_WT_NOISE: - case HX_ABS_NOISE: - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = PWD_NOISE_START; - tmp_data[0] = PWD_NOISE_START; - break; - - case HX_ACT_IDLE_RAWDATA: - case HX_ACT_IDLE_BPN_RAWDATA: - case HX_ACT_IDLE_NOISE: - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = PWD_ACT_IDLE_START; - tmp_data[0] = PWD_ACT_IDLE_START; - break; - - case HX_LP_RAWDATA: - case HX_LP_BPN_RAWDATA: - case HX_LP_ABS_NOISE: - case HX_LP_WT_NOISE: - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = PWD_LP_START; - tmp_data[0] = PWD_LP_START; - break; - case HX_LP_IDLE_RAWDATA: - case HX_LP_IDLE_BPN_RAWDATA: - case HX_LP_IDLE_NOISE: - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = PWD_LP_IDLE_START; - tmp_data[0] = PWD_LP_IDLE_START; - break; - - default: - I("%s,Nothing to be done!\n", __func__); - break; - } - - if (g_core_fp.fp_assign_sorting_mode != NULL) - g_core_fp.fp_assign_sorting_mode(tmp_data); - I("%s: End of setting!\n", __func__); - - return 0; - -} - -static uint32_t himax_get_rawdata(uint32_t RAW[], uint32_t datalen) -{ - uint8_t *tmp_rawdata; - bool get_raw_rlst; - uint8_t retry = 0; - uint32_t i = 0; - uint32_t j = 0; - uint32_t index = 0; - uint32_t Min_DATA = 0xFFFFFFFF; - uint32_t Max_DATA = 0x00000000; - - /* We use two bytes to combine a value of rawdata.*/ - tmp_rawdata = kzalloc(sizeof(uint8_t) * (datalen * 2), GFP_KERNEL); - if (tmp_rawdata == NULL) { - E("%s: Memory allocation falied!\n", __func__); - return HX_INSP_MEMALLCTFAIL; - } - - while (retry < 200) { - get_raw_rlst = g_core_fp.fp_get_DSRAM_data(tmp_rawdata, false); - if (get_raw_rlst) - break; - retry++; - } - - if (retry >= 200) - goto DIRECT_END; - - /* Copy Data*/ - for (i = 0; i < ic_data->HX_TX_NUM*ic_data->HX_RX_NUM; i++) - RAW[i] = tmp_rawdata[(i * 2) + 1] * 256 + tmp_rawdata[(i * 2)]; - - for (j = 0; j < ic_data->HX_RX_NUM; j++) { - if (j == 0) - PI(" RX%2d", j + 1); - else - PI(" RX%2d", j + 1); - } - PI("\n"); - - for (i = 0; i < ic_data->HX_TX_NUM; i++) { - PI("TX%2d", i + 1); - for (j = 0; j < ic_data->HX_RX_NUM; j++) { - PI("%5d ", RAW[index]); - if (RAW[index] > Max_DATA) - Max_DATA = RAW[index]; - - if (RAW[index] < Min_DATA) - Min_DATA = RAW[index]; - - index++; - } - PI("\n"); - } - I("Max = %5d, Min = %5d\n", Max_DATA, Min_DATA); -DIRECT_END: - kfree(tmp_rawdata); - - if (get_raw_rlst) - return HX_INSP_OK; - else - return HX_INSP_EGETRAW; - -} - -static void himax_switch_data_type(uint8_t checktype) -{ - uint8_t datatype = 0x00; - - switch (checktype) { - case HX_SORTING: - datatype = DATA_SORTING; - break; - case HX_OPEN: - datatype = DATA_OPEN; - break; - case HX_MICRO_OPEN: - datatype = DATA_MICRO_OPEN; - break; - case HX_SHORT: - datatype = DATA_SHORT; - break; - case HX_RAWDATA: - case HX_BPN_RAWDATA: - case HX_SC: - case HX_GAPTEST_RAW: - datatype = DATA_RAWDATA; - break; - - case HX_WT_NOISE: - case HX_ABS_NOISE: - datatype = DATA_NOISE; - break; - case HX_BACK_NORMAL: - datatype = DATA_BACK_NORMAL; - break; - case HX_ACT_IDLE_RAWDATA: - case HX_ACT_IDLE_BPN_RAWDATA: - datatype = DATA_ACT_IDLE_RAWDATA; - break; - case HX_ACT_IDLE_NOISE: - datatype = DATA_ACT_IDLE_NOISE; - break; - - case HX_LP_RAWDATA: - case HX_LP_BPN_RAWDATA: - datatype = DATA_LP_RAWDATA; - break; - case HX_LP_WT_NOISE: - case HX_LP_ABS_NOISE: - datatype = DATA_LP_NOISE; - break; - case HX_LP_IDLE_RAWDATA: - case HX_LP_IDLE_BPN_RAWDATA: - datatype = DATA_LP_IDLE_RAWDATA; - break; - case HX_LP_IDLE_NOISE: - datatype = DATA_LP_IDLE_NOISE; - break; - - default: - E("Wrong type=%d\n", checktype); - break; - } - g_core_fp.fp_diag_register_set(datatype, 0x00, false); -} - -static void himax_bank_search_set(uint16_t Nframe, uint8_t checktype) -{ - uint8_t tmp_addr[4]; - uint8_t tmp_data[4]; - - /*skip frame 0x100070F4*/ - himax_parse_assign_cmd(addr_skip_frame, tmp_addr, sizeof(tmp_addr)); - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - - switch (checktype) { - case HX_ACT_IDLE_RAWDATA: - case HX_ACT_IDLE_BPN_RAWDATA: - case HX_ACT_IDLE_NOISE: - tmp_data[0] = BS_ACT_IDLE; - break; - case HX_LP_RAWDATA: - case HX_LP_BPN_RAWDATA: - case HX_LP_ABS_NOISE: - case HX_LP_WT_NOISE: - tmp_data[0] = BS_LPWUG; - break; - case HX_LP_IDLE_RAWDATA: - case HX_LP_IDLE_BPN_RAWDATA: - case HX_LP_IDLE_NOISE: - tmp_data[0] = BS_LP_dile; - break; - case HX_RAWDATA: - case HX_BPN_RAWDATA: - case HX_SC: - tmp_data[0] = BS_RAWDATA; - break; - case HX_WT_NOISE: - case HX_ABS_NOISE: - tmp_data[0] = BS_NOISE; - break; - default: - tmp_data[0] = BS_OPENSHORT; - break; - } - g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); -} - -static void himax_neg_noise_sup(uint8_t *data) -{ - uint8_t tmp_addr[4]; - uint8_t tmp_data[4]; - - /*0x10007FD8 Check support negative value or not */ - himax_parse_assign_cmd(addr_neg_noise_sup, tmp_addr, - sizeof(tmp_addr)); - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - - if ((tmp_data[3] & 0x04) == 0x04) { - himax_parse_assign_cmd(data_neg_noise, tmp_data, - sizeof(tmp_data)); - data[2] = tmp_data[2]; data[3] = tmp_data[3]; - } else - I("%s Not support negative noise\n", __func__); -} - -static void himax_set_N_frame(uint16_t Nframe, uint8_t checktype) -{ - uint8_t tmp_addr[4]; - uint8_t tmp_data[4]; - - himax_bank_search_set(Nframe, checktype); - - /*IIR MAX - 0x10007294*/ - himax_parse_assign_cmd(fw_addr_set_frame_addr, - tmp_addr, sizeof(tmp_addr)); - tmp_data[3] = 0x00; tmp_data[2] = 0x00; - tmp_data[1] = (uint8_t)((Nframe & 0xFF00) >> 8); - tmp_data[0] = (uint8_t)(Nframe & 0x00FF); - g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); - - if (checktype == HX_WT_NOISE || - checktype == HX_ABS_NOISE || - checktype == HX_LP_WT_NOISE || - checktype == HX_LP_ABS_NOISE) - himax_neg_noise_sup(tmp_data); - - g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); -} - -static void himax_get_noise_base(uint8_t checktype)/*Normal Threshold*/ -{ - uint8_t tmp_addr[4]; - uint8_t tmp_data[4]; - - switch (checktype) { - case HX_WT_NOISE: - himax_parse_assign_cmd(addr_normal_noise_thx, - tmp_addr, sizeof(tmp_addr)); - break; - case HX_LP_WT_NOISE: - himax_parse_assign_cmd(addr_lpwug_noise_thx, - tmp_addr, sizeof(tmp_addr)); - break; - default: - I("%s Not support type\n", __func__); - } - - /*normal : 0x1000708F, LPWUG:0x10007093*/ - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - NOISEMAX = tmp_data[3]; - - himax_parse_assign_cmd(addr_recal_thx, - tmp_addr, sizeof(tmp_addr)); - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - g_recal_thx = tmp_data[2];/*0x10007092*/ - I("%s: NOISEMAX=%d, g_recal_thx = %d\n", __func__, - NOISEMAX, g_recal_thx); -} - -static uint16_t himax_get_palm_num(void)/*Palm Number*/ -{ - uint8_t tmp_addr[4]; - uint8_t tmp_data[4]; - uint16_t palm_num; - - himax_parse_assign_cmd(addr_palm_num, - tmp_addr, sizeof(tmp_addr)); - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - palm_num = tmp_data[3];/*0x100070AB*/ - I("%s: palm_num = %d ", __func__, palm_num); - - return palm_num; -} - -static int himax_get_noise_weight_test(uint8_t checktype) -{ - uint8_t tmp_addr[4]; - uint8_t tmp_data[4]; - uint16_t weight = 0; - uint16_t value = 0; - - himax_parse_assign_cmd(addr_weight_sup, - tmp_addr, sizeof(tmp_addr)); - - /*0x100072C8 weighting value*/ - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - if (tmp_data[3] != tmp_addr[1] || tmp_data[2] != tmp_addr[0]) - return FW_NOT_READY; - - value = (tmp_data[1] << 8) | tmp_data[0]; - I("%s: value = %d, %d, %d ", __func__, value, tmp_data[2], tmp_data[3]); - - switch (checktype) { - case HX_WT_NOISE: - himax_parse_assign_cmd(addr_normal_weight_a, - tmp_addr, sizeof(tmp_addr)); - break; - case HX_LP_WT_NOISE: - himax_parse_assign_cmd(addr_lpwug_weight_a, - tmp_addr, sizeof(tmp_addr)); - break; - default: - I("%s Not support type\n", __func__); - } - - /*Normal:0x1000709C, LPWUG:0x100070A0 weighting threshold*/ - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - weight = tmp_data[0]; - - himax_parse_assign_cmd(addr_weight_b, tmp_addr, sizeof(tmp_addr)); - - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - weight = tmp_data[1] * weight;/*0x10007095 weighting threshold*/ - I("%s: weight = %d ", __func__, weight); - - if (value > weight) - return ERR_TEST_FAIL; - else - return 0; -} - -static uint32_t himax_check_mode(uint8_t checktype) -{ - uint8_t tmp_data[4] = {0}; - uint8_t wait_pwd[2] = {0}; - - switch (checktype) { - case HX_SORTING: - wait_pwd[0] = PWD_SORTING_END; - wait_pwd[1] = PWD_SORTING_END; - break; - case HX_OPEN: - wait_pwd[0] = PWD_OPEN_END; - wait_pwd[1] = PWD_OPEN_END; - break; - case HX_MICRO_OPEN: - wait_pwd[0] = PWD_OPEN_END; - wait_pwd[1] = PWD_OPEN_END; - break; - case HX_SHORT: - wait_pwd[0] = PWD_SHORT_END; - wait_pwd[1] = PWD_SHORT_END; - break; - case HX_RAWDATA: - case HX_BPN_RAWDATA: - case HX_SC: - case HX_GAPTEST_RAW: - wait_pwd[0] = PWD_RAWDATA_END; - wait_pwd[1] = PWD_RAWDATA_END; - break; - - case HX_WT_NOISE: - case HX_ABS_NOISE: - wait_pwd[0] = PWD_NOISE_END; - wait_pwd[1] = PWD_NOISE_END; - break; - - case HX_ACT_IDLE_RAWDATA: - case HX_ACT_IDLE_BPN_RAWDATA: - case HX_ACT_IDLE_NOISE: - wait_pwd[0] = PWD_ACT_IDLE_END; - wait_pwd[1] = PWD_ACT_IDLE_END; - break; - - case HX_LP_RAWDATA: - case HX_LP_BPN_RAWDATA: - case HX_LP_ABS_NOISE: - case HX_LP_WT_NOISE: - wait_pwd[0] = PWD_LP_END; - wait_pwd[1] = PWD_LP_END; - break; - case HX_LP_IDLE_RAWDATA: - case HX_LP_IDLE_BPN_RAWDATA: - case HX_LP_IDLE_NOISE: - wait_pwd[0] = PWD_LP_IDLE_END; - wait_pwd[1] = PWD_LP_IDLE_END; - break; - - default: - E("Wrong type=%d\n", checktype); - break; - } - - if (g_core_fp.fp_check_sorting_mode != NULL) - g_core_fp.fp_check_sorting_mode(tmp_data); - - if ((wait_pwd[0] == tmp_data[0]) && (wait_pwd[1] == tmp_data[1])) { - I("Change to mode=%s\n", g_himax_inspection_mode[checktype]); - return 0; - } else { - return 1; - } -} - -#define TEMP_LOG \ -"%s:%s,tmp_data[0]=%x,tmp_data[1]=%x,tmp_data[2]=%x,tmp_data[3]=%x\n" - -static uint32_t himax_wait_sorting_mode(uint8_t checktype) -{ - uint8_t tmp_addr[4] = {0}; - uint8_t tmp_data[4] = {0}; - uint8_t wait_pwd[2] = {0}; - int count = 0; - - switch (checktype) { - case HX_SORTING: - wait_pwd[0] = PWD_SORTING_END; - wait_pwd[1] = PWD_SORTING_END; - break; - case HX_OPEN: - wait_pwd[0] = PWD_OPEN_END; - wait_pwd[1] = PWD_OPEN_END; - break; - case HX_MICRO_OPEN: - wait_pwd[0] = PWD_OPEN_END; - wait_pwd[1] = PWD_OPEN_END; - break; - case HX_SHORT: - wait_pwd[0] = PWD_SHORT_END; - wait_pwd[1] = PWD_SHORT_END; - break; - case HX_RAWDATA: - case HX_BPN_RAWDATA: - case HX_SC: - case HX_GAPTEST_RAW: - wait_pwd[0] = PWD_RAWDATA_END; - wait_pwd[1] = PWD_RAWDATA_END; - break; - case HX_WT_NOISE: - case HX_ABS_NOISE: - wait_pwd[0] = PWD_NOISE_END; - wait_pwd[1] = PWD_NOISE_END; - break; - case HX_ACT_IDLE_RAWDATA: - case HX_ACT_IDLE_BPN_RAWDATA: - case HX_ACT_IDLE_NOISE: - wait_pwd[0] = PWD_ACT_IDLE_END; - wait_pwd[1] = PWD_ACT_IDLE_END; - break; - - case HX_LP_RAWDATA: - case HX_LP_BPN_RAWDATA: - case HX_LP_ABS_NOISE: - case HX_LP_WT_NOISE: - wait_pwd[0] = PWD_LP_END; - wait_pwd[1] = PWD_LP_END; - break; - case HX_LP_IDLE_RAWDATA: - case HX_LP_IDLE_BPN_RAWDATA: - case HX_LP_IDLE_NOISE: - wait_pwd[0] = PWD_LP_IDLE_END; - wait_pwd[1] = PWD_LP_IDLE_END; - break; - - default: - I("No Change Mode and now type=%d\n", checktype); - break; - } - - do { - if (g_core_fp.fp_check_sorting_mode != NULL) - g_core_fp.fp_check_sorting_mode(tmp_data); - if ((wait_pwd[0] == tmp_data[0]) && - (wait_pwd[1] == tmp_data[1])) - return HX_INSP_OK; - - himax_parse_assign_cmd(fw_addr_chk_fw_status, - tmp_addr, sizeof(tmp_addr)); - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - I(TEMP_LOG, __func__, "0x900000A8", - tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); - - himax_parse_assign_cmd(fw_addr_flag_reset_event, - tmp_addr, sizeof(tmp_addr)); - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - I(TEMP_LOG, __func__, "0x900000E4", - tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); - - himax_parse_assign_cmd(fw_addr_fw_dbg_msg_addr, - tmp_addr, sizeof(tmp_addr)); - g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); - I(TEMP_LOG, __func__, "0x10007F40", - tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); - I("Now retry %d times!\n", count++); - msleep(50); - } while (count < 50); - - return HX_INSP_ESWITCHMODE; -} - -static int hx_turn_on_mp_func(int on) -{ - int rslt = 0; - int retry = 3; - uint8_t tmp_addr[4] = {0}; - uint8_t tmp_data[4] = {0}; - uint8_t tmp_read[4] = {0}; - /* char *tmp_chipname = private_ts->chip_name; */ - - himax_parse_assign_cmd(addr_ctrl_mpap_ovl, tmp_addr, - sizeof(tmp_addr)); - if (on) { - I("%s : Turn on!\n", __func__); - if (strcmp(HX_83102D_SERIES_PWON, private_ts->chip_name) == 0) { - I("%s: need to enter Mp mode!\n", __func__); - himax_parse_assign_cmd(PWD_TURN_ON_MPAP_OVL, - tmp_data, sizeof(tmp_data)); - do { - g_core_fp.fp_register_write(tmp_addr, 4, - tmp_data, 0); - usleep_range(10000, 10001); - g_core_fp.fp_register_read(tmp_addr, 4, - tmp_read, false); - - I("%s:read2=0x%02X,read1=0x%02X,read0=0x%02X\n", - __func__, - tmp_read[2], - tmp_read[1], - tmp_read[0]); - - retry--; - } while (((retry > 0) - && (tmp_read[2] != tmp_data[2] - && tmp_read[1] != tmp_data[1] - && tmp_read[0] != tmp_data[0]))); - } else { - I("%s:Nothing to be done!\n", __func__); - } - } else { - I("%s : Turn off!\n", __func__); - if (strcmp(HX_83102D_SERIES_PWON, private_ts->chip_name) == 0) { - I("%s: need to enter Mp mode!\n", __func__); - - himax_parse_assign_cmd(ic_cmd_rst, tmp_data, - sizeof(tmp_data)); - do { - g_core_fp.fp_register_write(tmp_addr, 4, - tmp_data, 0); - usleep_range(10000, 10001); - g_core_fp.fp_register_read(tmp_addr, 4, - tmp_read, false); - - I("%s:read2=0x%02X,read1=0x%02X,read0=0x%02X\n", - __func__, - tmp_read[2], - tmp_read[1], - tmp_read[0]); - - retry--; - } while ((retry > 0) - && (tmp_read[2] != tmp_data[2] - && tmp_read[1] != tmp_data[1] - && tmp_read[0] != tmp_data[0])); - } else { - I("%s Nothing to be done!\n", __func__); - } - } - return rslt; -} - -/* HX_GAP START gap test function */ -/* extern int himax_write_to_ic_flash_flow(uint32_t start_addr,*/ -/* uint32_t *write_data, uint32_t write_len);*/ - -static int himax_gap_test_vertical_setting(void) -{ - g_gap_vertical_part[0] = 0; - g_gap_vertical_part[1] = 4; - g_gap_vertical_part[2] = 8; - - return NO_ERR; -} - -static void himax_cal_gap_data_vertical(int start, int end_idx, int direct, - uint32_t *org_raw, uint32_t *result_raw) -{ - int i = 0; - int rx_num = ic_data->HX_RX_NUM; - - I("%s:start=%d,end_idx=%d\n", __func__, start, end_idx); - - for (i = start; i < (start + rx_num*end_idx); i++) { - if (direct == 0) { /* up - down */ - if (i < start+rx_num) - result_raw[i] = 0; - else - result_raw[i] = org_raw[i-rx_num] - org_raw[i]; - - } else { /* down - up */ - if (i > (start + rx_num*(end_idx-1)-1)) - result_raw[i] = 0; - else - result_raw[i] = org_raw[i+rx_num] - org_raw[i]; - - } - } -} - -static int himax_gap_test_vertical_raw(int test_type, uint32_t *org_raw) -{ - int i_partial = 0; - int tmp_start = 0; - int tmp_end_idx = 0; - uint32_t *result_raw = NULL; - int i = 0; - int ret_val = NO_ERR; - - int tx_num = ic_data->HX_TX_NUM; - int rx_num = ic_data->HX_RX_NUM; - - g_gap_vertical_part = kcalloc(g_gap_vertical_partial, - sizeof(int), GFP_KERNEL); - if (g_gap_vertical_part == NULL) { - E("%s: Memory allocation falied!\n", __func__); - return MEM_ALLOC_FAIL; - } - - result_raw = kcalloc(tx_num*rx_num, sizeof(uint32_t), GFP_KERNEL); - if (result_raw == NULL) { - E("%s: Memory allocation falied!\n", __func__); - ret_val = MEM_ALLOC_FAIL; - goto alloc_result_raw_failed; - } - - himax_gap_test_vertical_setting(); - - I("Print vertical ORG RAW\n"); - for (i = 0; i < tx_num*rx_num; i++) { - I("%04d,", org_raw[i]); - if (i > 0 && i%rx_num == (rx_num-1)) - I("\n"); - } - - for (i_partial = 0; i_partial < g_gap_vertical_partial; i_partial++) { - - tmp_start = g_gap_vertical_part[i_partial]*rx_num; - if (i_partial+1 == g_gap_vertical_partial) - tmp_end_idx = tx_num - g_gap_vertical_part[i_partial]; - else - tmp_end_idx = g_gap_vertical_part[i_partial+1] - - g_gap_vertical_part[i_partial]; - - if (i_partial % 2 == 0) - himax_cal_gap_data_vertical(tmp_start, tmp_end_idx, 0, - org_raw, result_raw); - else - himax_cal_gap_data_vertical(tmp_start, tmp_end_idx, 1, - org_raw, result_raw); - - } - - I("Print Vertical New RAW\n"); - for (i = 0; i < tx_num*rx_num; i++) { - I("%04d,", result_raw[i]); - if (i > 0 && i%rx_num == (rx_num-1)) - I("\n"); - } - - for (i = 0; i < tx_num*rx_num; i++) { - if (result_raw[i] < g_inspection_criteria[IDX_GAP_VER_RAWMIN][i] - && - result_raw[i] > g_inspection_criteria[IDX_GAP_VER_RAWMAX][i]) { - ret_val = NO_ERR - i; - break; - } - } - - /* himax_write_to_ic_flash_flow(0x1A000,result_raw,tx_num*rx_num); */ - kfree(result_raw); -alloc_result_raw_failed: - kfree(g_gap_vertical_part); - g_gap_vertical_part = NULL; - - return ret_val; -} - -static int himax_gap_test_horizontal_setting(void) -{ - g_gap_horizontal_part[0] = 0; - g_gap_horizontal_part[1] = 8; - g_gap_horizontal_part[2] = 24; - - return NO_ERR; -} - -static void himax_cal_gap_data_horizontal(int start, int end_idx, int direct, - uint32_t *org_raw, uint32_t *result_raw) -{ - int i = 0; - int j = 0; - int rx_num = ic_data->HX_RX_NUM; - int tx_num = ic_data->HX_TX_NUM; - - I("start=%d,end_idx=%d\n", start, end_idx); - - for (j = 0; j < tx_num; j++) { - for (i = (start + (j*rx_num)); - i < (start + (j*rx_num) + end_idx); i++) { - /* left - right */ - if (direct == 0) { - if (i == (start + (j*rx_num))) - result_raw[i] = 0; - else - result_raw[i] = - org_raw[i-1] - org_raw[i]; - - } else { /* right - left */ - if (i == ((start + (j*rx_num) + end_idx) - 1)) - result_raw[i] = 0; - else - result_raw[i] = - org_raw[i + 1] - org_raw[i]; - } - } - } -} - -static int himax_gap_test_honrizontal_raw(int test_type, uint32_t *raw) -{ - int rx_num = ic_data->HX_RX_NUM; - int tx_num = ic_data->HX_TX_NUM; - int tmp_start = 0; - int tmp_end_idx = 0; - int i_partial = 0; - uint32_t *result_raw; - int i = 0; - int ret_val = NO_ERR; - - g_gap_horizontal_part = kcalloc(g_gap_horizontal_partial, - sizeof(int), GFP_KERNEL); - if (g_gap_horizontal_part == NULL) { - E("%s: Memory allocation falied!\n", __func__); - return MEM_ALLOC_FAIL; - } - - result_raw = kcalloc(tx_num*rx_num, sizeof(uint32_t), GFP_KERNEL); - if (result_raw == NULL) { - E("%s: Memory allocation falied!\n", __func__); - ret_val = MEM_ALLOC_FAIL; - goto alloc_result_raw_failed; - } - - himax_gap_test_horizontal_setting(); - - I("Print Horizontal ORG RAW\n"); - for (i = 0; i < tx_num*rx_num; i++) { - I("%04d,", raw[i]); - if (i > 0 && i%rx_num == (rx_num-1)) - I("\n"); - } - - for (i_partial = 0; - i_partial < g_gap_horizontal_partial; - i_partial++) { - tmp_start = g_gap_horizontal_part[i_partial]; - if (i_partial+1 == g_gap_horizontal_partial) - tmp_end_idx = rx_num - g_gap_horizontal_part[i_partial]; - else - tmp_end_idx = g_gap_horizontal_part[i_partial+1] - - g_gap_horizontal_part[i_partial]; - - if (i_partial % 2 == 0) - himax_cal_gap_data_horizontal(tmp_start, tmp_end_idx, - 0, raw, result_raw); - else - himax_cal_gap_data_horizontal(tmp_start, tmp_end_idx, - 1, raw, result_raw); - - } - I("Print Horizontal New RAW\n"); - for (i = 0; i < tx_num*rx_num; i++) { - I("%04d,", result_raw[i]); - if (i > 0 && i%rx_num == (rx_num-1)) - I("\n"); - } - - for (i = 0; i < tx_num*rx_num; i++) { - if (result_raw[i] < g_inspection_criteria[IDX_GAP_HOR_RAWMIN][i] - && - result_raw[i] > g_inspection_criteria[IDX_GAP_HOR_RAWMAX][i]) { - ret_val = NO_ERR - i; - break; - } - } - - /* himax_write_to_ic_flash_flow(0x1A800,result_raw,tx_num*rx_num); */ - kfree(result_raw); -alloc_result_raw_failed: - kfree(g_gap_horizontal_part); - g_gap_horizontal_part = NULL; - - return ret_val; -} - -static uint32_t himax_data_campare(uint8_t checktype, uint32_t *RAW, - int ret_val) -{ - int i = 0; - int idx_max = 0; - int idx_min = 0; - int block_num = ic_data->HX_TX_NUM*ic_data->HX_RX_NUM; - uint16_t palm_num = 0; - uint16_t noise_count = 0; - - switch (checktype) { - case HX_SORTING: - idx_min = IDX_SORTMIN; - break; - case HX_OPEN: - idx_max = IDX_OPENMAX; - idx_min = IDX_OPENMIN; - break; - - case HX_MICRO_OPEN: - idx_max = IDX_M_OPENMAX; - idx_min = IDX_M_OPENMIN; - break; - - case HX_SHORT: - idx_max = IDX_SHORTMAX; - idx_min = IDX_SHORTMIN; - break; - - case HX_RAWDATA: - idx_max = IDX_RAWMAX; - idx_min = IDX_RAWMIN; - break; - - case HX_BPN_RAWDATA: - idx_max = IDX_BPN_RAWMAX; - idx_min = IDX_BPN_RAWMIN; - break; - case HX_SC: - idx_max = IDX_SCMAX; - idx_min = IDX_SCMIN; - break; - case HX_WT_NOISE: - idx_max = IDX_WT_NOISEMAX; - idx_min = IDX_WT_NOISEMIN; - break; - case HX_ABS_NOISE: - idx_max = IDX_ABS_NOISEMAX; - idx_min = IDX_ABS_NOISEMIN; - break; - case HX_GAPTEST_RAW: - break; - - case HX_ACT_IDLE_RAWDATA: - idx_max = IDX_ACT_IDLE_RAWDATA_MAX; - idx_min = IDX_ACT_IDLE_RAWDATA_MIN; - break; - - case HX_ACT_IDLE_BPN_RAWDATA: - idx_max = IDX_ACT_IDLE_RAW_BPN_MAX; - idx_min = IDX_ACT_IDLE_RAW_BPN_MIN; - break; - - case HX_ACT_IDLE_NOISE: - idx_max = IDX_ACT_IDLE_NOISE_MAX; - idx_min = IDX_ACT_IDLE_NOISE_MIN; - break; - - case HX_LP_RAWDATA: - idx_max = IDX_LP_RAWDATA_MAX; - idx_min = IDX_LP_RAWDATA_MIN; - break; - - case HX_LP_BPN_RAWDATA: - idx_max = IDX_LP_RAW_BPN_MAX; - idx_min = IDX_LP_RAW_BPN_MIN; - break; - - case HX_LP_WT_NOISE: - idx_max = IDX_LP_WT_NOISEMAX; - idx_min = IDX_LP_WT_NOISEMIN; - break; - - case HX_LP_ABS_NOISE: - idx_max = IDX_LP_NOISE_ABS_MAX; - idx_min = IDX_LP_NOISE_ABS_MIN; - break; - - case HX_LP_IDLE_RAWDATA: - idx_max = IDX_LP_IDLE_RAWDATA_MAX; - idx_min = IDX_LP_IDLE_RAWDATA_MIN; - break; - - case HX_LP_IDLE_BPN_RAWDATA: - idx_max = IDX_LP_IDLE_RAW_BPN_MAX; - idx_min = IDX_LP_IDLE_RAW_BPN_MIN; - break; - - case HX_LP_IDLE_NOISE: - idx_max = IDX_LP_IDLE_NOISE_MAX; - idx_min = IDX_LP_IDLE_NOISE_MIN; - break; - - default: - E("Wrong type=%d\n", checktype); - break; - } - - /*data process*/ - switch (checktype) { - case HX_SORTING: - for (i = 0; i < block_num; i++) - g_inspection_criteria[idx_max][i] = 999999; - break; - case HX_BPN_RAWDATA: - case HX_ACT_IDLE_BPN_RAWDATA: - case HX_LP_BPN_RAWDATA: - case HX_LP_IDLE_BPN_RAWDATA: - for (i = 0; i < block_num; i++) - RAW[i] = (int)RAW[i] * 100 / g_dc_max; - break; - case HX_SC: - for (i = 0; i < block_num; i++) { - RAW[i] = ((int)RAW[i] - - g_inspection_criteria[IDX_SC_GOLDEN][i]) - * 100 / g_inspection_criteria[IDX_SC_GOLDEN][i]; - } - break; - } - - /*data campare*/ - switch (checktype) { - case HX_GAPTEST_RAW: - if ( - himax_gap_test_vertical_raw(HX_GAPTEST_RAW, RAW) != NO_ERR) { - E("%s: HX_GAPTEST_RAW FAIL\n", __func__); - ret_val |= 1 << (checktype + ERR_SFT); - break; - } - if (himax_gap_test_honrizontal_raw(HX_GAPTEST_RAW, RAW) - != NO_ERR) { - E("%s: HX_GAPTEST_RAW FAIL\n", __func__); - ret_val |= 1 << (checktype + ERR_SFT); - break; - } - break; - - case HX_WT_NOISE: - case HX_LP_WT_NOISE: - noise_count = 0; - himax_get_noise_base(checktype); - palm_num = himax_get_palm_num(); - for (i = 0; i < (ic_data->HX_TX_NUM * ic_data->HX_RX_NUM); - i++) { - if ((int)RAW[i] > NOISEMAX) - noise_count++; - } - I("noise_count=%d\n", noise_count); - if (noise_count > palm_num) { - E("%s: noise test FAIL\n", __func__); - ret_val |= 1 << (checktype + ERR_SFT); - break; - } - snprintf(g_start_log, 256 * sizeof(char), "\n Threshold = %d\n", - NOISEMAX); - /*Check weightingt*/ - if (himax_get_noise_weight_test(checktype) < 0) { - I("%s: %s FAIL %X\n", __func__, - g_himax_inspection_mode[checktype], ret_val); - ret_val |= 1 << (checktype + ERR_SFT); - break; - } - - /*Check negative side noise*/ - for (i = 0; i < block_num; i++) { - if ((int)RAW[i] - > (g_inspection_criteria[idx_max][i] - * NOISEMAX / 100) - || (int)RAW[i] - < (g_inspection_criteria[idx_min][i] - * g_recal_thx / 100)) { - E(FAIL_IN_INDEX, __func__, - g_himax_inspection_mode[checktype], i); - ret_val |= 1 << (checktype + ERR_SFT); - break; - } - } - break; - - case HX_LP_IDLE_RAWDATA: - case HX_LP_IDLE_BPN_RAWDATA: - case HX_LP_IDLE_NOISE: - case HX_ACT_IDLE_RAWDATA: - case HX_ACT_IDLE_BPN_RAWDATA: - case HX_ACT_IDLE_NOISE: - block_num = ic_data->ic_adc_num; - case HX_SORTING: - case HX_OPEN: - case HX_MICRO_OPEN: - case HX_SHORT: - case HX_RAWDATA: - case HX_BPN_RAWDATA: - case HX_SC: - case HX_ABS_NOISE: - case HX_LP_RAWDATA: - case HX_LP_BPN_RAWDATA: - case HX_LP_ABS_NOISE: - for (i = 0; i < block_num; i++) { - if ((int)RAW[i] > g_inspection_criteria[idx_max][i] - || (int)RAW[i] < g_inspection_criteria[idx_min][i]) { - E(FAIL_IN_INDEX, __func__, - g_himax_inspection_mode[checktype], i); - ret_val |= 1 << (checktype + ERR_SFT); - break; - } - } - break; - - default: - E("Wrong type=%d\n", checktype); - break; - } - - I("%s: %s %s\n", __func__, g_himax_inspection_mode[checktype], - (ret_val == HX_INSP_OK)?"PASS":"FAIL"); - - return ret_val; -} - -static int himax_get_max_dc(void) -{ - uint8_t tmp_data[DATA_LEN_4]; - uint8_t tmp_addr[DATA_LEN_4]; - int dc_max = 0; - - himax_parse_assign_cmd(addr_max_dc, tmp_addr, sizeof(tmp_addr)); - - g_core_fp.fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); - I("%s: tmp_data[0]=%x,tmp_data[1]=%x\n", __func__, - tmp_data[0], tmp_data[1]); - - dc_max = tmp_data[1] << 8 | tmp_data[0]; - I("%s: dc max = %d\n", __func__, dc_max); - return dc_max; -} - -/* HX_GAP END*/ -static uint32_t mpTestFunc(uint8_t checktype, uint32_t datalen) -{ - uint32_t len = 0; - uint32_t *RAW = NULL; - int n_frame = 0; - uint32_t ret_val = HX_INSP_OK; - - /*uint16_t* pInspectGridData = &gInspectGridData[0];*/ - /*uint16_t* pInspectNoiseData = &gInspectNoiseData[0];*/ - - I("Now Check type = %d\n", checktype); - - RAW = kcalloc(datalen, sizeof(uint32_t), GFP_KERNEL); - if (RAW == NULL) { - E("%s, Failed to allocate memory\n", __func__); - return HX_INSP_MEMALLCTFAIL; - } - - if (himax_check_mode(checktype)) { - /*himax_check_mode(checktype);*/ - - I("Need Change Mode ,target=%s\n", - g_himax_inspection_mode[checktype]); - - g_core_fp.fp_sense_off(true); - hx_turn_on_mp_func(1); - -#if !defined(HX_ZERO_FLASH) - if (g_core_fp.fp_reload_disable != NULL) - g_core_fp.fp_reload_disable(1); -#endif - - himax_switch_mode_inspection(checktype); - - switch (checktype) { - case HX_WT_NOISE: - case HX_ABS_NOISE: - n_frame = NOISEFRAME; - break; - case HX_ACT_IDLE_RAWDATA: - case HX_ACT_IDLE_NOISE: - case HX_ACT_IDLE_BPN_RAWDATA: - n_frame = NORMAL_IDLE_RAWDATA_NOISEFRAME; - break; - case HX_LP_RAWDATA: - case HX_LP_BPN_RAWDATA: - n_frame = LP_RAWDATAFRAME; - break; - case HX_LP_WT_NOISE: - case HX_LP_ABS_NOISE: - n_frame = LP_NOISEFRAME; - break; - case HX_LP_IDLE_RAWDATA: - case HX_LP_IDLE_BPN_RAWDATA: - n_frame = LP_IDLE_RAWDATAFRAME; - break; - case HX_LP_IDLE_NOISE: - n_frame = LP_IDLE_NOISEFRAME; - break; - default: - n_frame = OTHERSFRAME; - } - himax_set_N_frame(n_frame, checktype); - - g_core_fp.fp_sense_on(1); - - } - - ret_val |= himax_wait_sorting_mode(checktype); - if (ret_val) { - E("%s: himax_wait_sorting_mode FAIL\n", __func__); - ret_val |= (1 << (checktype + ERR_SFT)); - goto fail_wait_sorting_mode; - } - himax_switch_data_type(checktype); - - ret_val |= himax_get_rawdata(RAW, datalen); - if (ret_val) { - E("%s: himax_get_rawdata FAIL\n", __func__); - ret_val |= (1 << (checktype + ERR_SFT)); - goto fail_get_rawdata; - } - - /*get Max DC from FW*/ - g_dc_max = himax_get_max_dc(); - - /* back to normal */ - himax_switch_data_type(HX_BACK_NORMAL); - - I("%s: Init OK, start to test!\n", __func__); - - len += snprintf(g_start_log+len, 256 * sizeof(char), "\n%s%s\n", - g_himax_inspection_mode[checktype], ": data as follow!\n"); - - ret_val |= himax_data_campare(checktype, RAW, ret_val); - - himax_get_arraydata_edge(RAW); - - len += snprintf(g_start_log + len, 256 * sizeof(char) - len, - "\n arraydata_min1 = %d,", arraydata_min1); - len += snprintf(g_start_log + len, 256 * sizeof(char) - len, - " arraydata_min2 = %d,", arraydata_min2); - len += snprintf(g_start_log + len, 256 * sizeof(char) - len, - " arraydata_min3 = %d,", arraydata_min3); - len += snprintf(g_start_log + len, 256 * sizeof(char) - len, - "\n arraydata_max1 = %d,", arraydata_max1); - len += snprintf(g_start_log + len, 256 * sizeof(char) - len, - " arraydata_max2 = %d,", arraydata_max2); - len += snprintf(g_start_log + len, 256 * sizeof(char) - len, - " arraydata_max3 = %d\n", arraydata_max3); - - if (!ret_val) {/*PASS*/ - snprintf(g_rslt_log, 256 * sizeof(char), "\n%s%s\n", - g_himax_inspection_mode[checktype], ":Test Pass!"); - I("pass write log\n"); - } else {/*FAIL*/ - snprintf(g_rslt_log, 256 * sizeof(char), "\n%s%s\n", - g_himax_inspection_mode[checktype], ":Test Fail!"); - I("fail write log\n"); - } - - hx_test_data_get(RAW, g_start_log, g_rslt_log, checktype); -fail_get_rawdata: -fail_wait_sorting_mode: - kfree(RAW); - return ret_val; -} - -/* claculate 10's power function */ -static int himax_power_cal(int pow, int number) -{ - int i = 0; - int result = 1; - - for (i = 0; i < pow; i++) - result *= 10; - result = result * number; - - return result; - -} - -/* String to int */ -static int hiamx_parse_str2int(char *str) -{ - int i = 0; - int temp_cal = 0; - int result = 0; - int str_len = strlen(str); - int negtive_flag = 0; - - for (i = 0; i < strlen(str); i++) { - 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); - /* 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; -} - - - - -/* get idx of criteria whe parsing file */ -int hx_find_crtra_id(char *input) -{ - int i = 0; - int result = 0; - - for (i = 0 ; i < HX_CRITERIA_SIZE ; i++) { - if (strcmp(g_hx_inspt_crtra_name[i], input) == 0) { - result = i; - I("find the str=%s,idx=%d\n", - g_hx_inspt_crtra_name[i], i); - break; - } - } - if (i > (HX_CRITERIA_SIZE - 1)) { - E("%s: find Fail!\n", __func__); - return LENGTH_FAIL; - } - - return result; -} - -int hx_print_crtra_after_parsing(void) -{ - int i = 0, j = 0; - int all_mut_len = ic_data->HX_TX_NUM*ic_data->HX_RX_NUM; - - for (i = 0; i < HX_CRITERIA_SIZE; i++) { - I("Now is %s\n", g_hx_inspt_crtra_name[i]); - if (g_inspt_crtra_flag[i] == 1) { - for (j = 0; j < all_mut_len; j++) { - I("%d, ", g_inspection_criteria[i][j]); - if (j % 16 == 15) - PI("\n"); - } - } else { - I("No this Item in this criteria file!\n"); - } - PI("\n"); - } - - return 0; -} - -static int hx_crtra_get(char *result, int himax_count_type, int comprae_data) -{ - int temp = 0; - - temp = hiamx_parse_str2int(result); - - if (temp != -9487) - g_inspection_criteria[himax_count_type][comprae_data] = temp; - else { - I("%s: Parsing Fail in %d, rslt = %d\n", - __func__, comprae_data, temp); - return HX_INSP_EFILE; - } - - if (private_ts->debug_log_level & BIT(4)) { - /* dbg:print all of criteria from parsing file */ - hx_print_crtra_after_parsing(); - } - - return HX_INSP_OK; -} - -static int himax_parse_criteria_str(char *str_data, int hx_str_len) -{ - int err = HX_INSP_OK; - char result[100] = {0}; - char str_rslt[100] = {0}; - int str_rslt_nm = 0; - int result_nm = 0; - char str_len = 0; - char *str_addr = NULL; - int str_flag = 1; - int i, j, k = 0; - int crtra_id = 0; - int mul_num = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM; - int flag = 1; - int temp; - - I("%s,Entering\n", __func__); - - for (str_rslt_nm = 0; str_rslt_nm < hx_str_len; str_rslt_nm++) - str_rslt[str_rslt_nm] = *(str_data + str_rslt_nm); - - crtra_id = hx_find_crtra_id(str_rslt); - if (crtra_id == -1) { - E("Please check criteria file again!\n"); - return HX_INSP_EFILE; - } - g_inspt_crtra_flag[crtra_id] = 1; - - str_data = str_data + hx_str_len + 1; - - for (i = 0; i < mul_num; i++) { - if (i <= mul_num - 2) { - while (flag) { - if (*(str_data + flag) == ',') { - str_addr = str_data + flag; - flag = 1; - break; - } - flag++; - } - if (str_addr == NULL) - continue; - str_flag = 1; - str_len = str_addr - str_data; - for (j = 1; j <= str_len; j++) { - if ((*(str_data+j) == '\r' - || *(str_data+j) == '\n')) { - memset(result, 0, 100); - for (k = 0; k < j ; k++) - result[k] = *(str_data + k); - str_flag = 0; - break; - } - } - if (str_flag) { - memset(result, 0, 100); - for (k = 0; k < str_len; k++) - result[k] = *(str_data + k); - } - err = hx_crtra_get(result, crtra_id, i); - if (err != HX_INSP_OK) { - E("%s:Get crrteria Fail!!\n", __func__); - return HX_INSP_EFILE; - } - str_data = str_addr + 1; - } else{ - temp = 1; - while (*(str_data + temp) <= '9' - && *(str_data + temp) >= '0') - temp++; - str_len = temp; - memset(result, 0, 100); - for (result_nm = 0; result_nm < str_len; result_nm++) - result[result_nm] = *(str_data + result_nm); - - err = hx_crtra_get(result, crtra_id, mul_num - 1); - if (err != HX_INSP_OK) { - E("%s:Get crrteria Fail!\n", __func__); - return HX_INSP_EFILE; - } - } - } - - I("%s,END\n", __func__); - return err; - /* parsing Criteria end */ -} - -static int himax_test_item_parse(char *str_data, int str_size) -{ - int size = str_size; - char *str_ptr = str_data; - char *end_ptr = NULL; - int i = 0; - int ret = HX_INSP_EFILE; - - I("%s,str_data: %p, str_size: %d\n", __func__, str_data, str_size); - - do { - str_ptr = strnstr(str_ptr, "HIMAX", size); - end_ptr = strnstr(str_ptr, "\x0d\x0a", size); - if (str_ptr != NULL && end_ptr != NULL) { - while (g_himax_inspection_mode[i]) { - if (strncmp(str_ptr, g_himax_inspection_mode[i], - end_ptr - str_ptr) == 0) { - I("%s,Find item : %s\n", __func__, - g_himax_inspection_mode[i]); - g_test_item_flag[i] = 1; - ret = HX_INSP_OK; - break; - } - i++; - } - size = str_size - (end_ptr - str_data); - str_ptr = end_ptr++; - i = 0; - } else { - I("%s,Can't find %s or %s\n", __func__, - "HIMAX", "\x0d\x0a"); - break; - } - } while (size > strlen("HIMAX")); - - return ret; -} - - -static int himax_parse_criteria(const struct firmware *file_entry) -{ - int ret = 0; - int i = 0; - int start_str_len = 0; - char *start_ptr = NULL; - - while (g_hx_inspt_crtra_name[i] != NULL) { - - start_ptr = strnstr(file_entry->data, - g_hx_inspt_crtra_name[i], file_entry->size); - - if (start_ptr != NULL) { - I("g_hx_inspt_crtra_name[%d] = %s\n", - i, g_hx_inspt_crtra_name[i]); - start_str_len = strlen(g_hx_inspt_crtra_name[i]); - - ret |= himax_parse_criteria_str(start_ptr, - start_str_len); - } - i++; - } - - return ret; -} - - -static int himax_parse_test_dri_file(const struct firmware *file_entry) -{ - int start_str_len = 0; - int str_size = 0; - char *start_ptr = NULL; - char *end_ptr = NULL; - int i = 0; - int j = 0; - char str[2][60]; /*[0]->Start string, [1]->End string*/ - char *str_tail[2] = {"_Begin]\x0d\x0a", "_End]\x0d\x0a"}; - int ret = HX_INSP_OK; - - while (g_hx_head_str[i]) { - /*compose header string of .dri file*/ - for (j = 0; j < 2; j++) { - strlcpy(str[j], "[", sizeof(str[j])); - strlcat(str[j], g_hx_head_str[i], sizeof(str[j])); - strlcat(str[j], str_tail[j], sizeof(str[j])); - /*I("%s string[%d] : %s\n", __func__, j, str[j]);*/ - } - - /*find each group of .dri file*/ - start_str_len = strlen(str[0]); - start_ptr = strnstr(file_entry->data, str[0], file_entry->size); - end_ptr = strnstr(file_entry->data, str[1], file_entry->size); - str_size = end_ptr - start_ptr - start_str_len; - /*I("%s,String Length = %d\n", __func__, str_size);*/ - - if (start_ptr == NULL || end_ptr == NULL) { - E("%s,Can't find string %s\n", __func__, - g_hx_head_str[i]); - } else { - /*parse each sub group string*/ - /*if (strncmp(g_hx_head_str[i], "Project_Info",*/ - /*strlen(g_hx_head_str[i])) == 0) {*/ - /* get project informaion - Not Use*/ - /*}*/ - if (strncmp(g_hx_head_str[i], "TestItem", - strlen(g_hx_head_str[i])) == 0) { - /*get Test Item*/ - I("%s,Start to parse %s\n", __func__, - g_hx_head_str[i]); - ret |= himax_test_item_parse(start_ptr - + start_str_len, - str_size); - } - /*if (strncmp(g_hx_head_str[i], "TestCriteria_Weight",*/ - /*strlen(g_hx_head_str[i])) == 0) {*/ - /*get Test Criteria Weight - Not Use*/ - /*}*/ - if (strncmp(g_hx_head_str[i], "TestCriteria", - strlen(g_hx_head_str[i])) == 0) { - /*get Test Criteria*/ - I("%s,Start to parse %s\n", __func__, - g_hx_head_str[i]); - ret |= himax_parse_criteria(file_entry); - } - } - i++; - } - - return ret; -} - -static void himax_test_item_chk(int csv_test) -{ - int i = 0; - - if (csv_test) - for (i = 0; i < HX_CRITERIA_ITEM - 1; i++) - g_test_item_flag[i] = 1; - - g_test_item_flag[HX_OPEN] &= - (g_inspt_crtra_flag[IDX_OPENMIN] == 1 - && g_inspt_crtra_flag[IDX_OPENMAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_MICRO_OPEN] &= - (g_inspt_crtra_flag[IDX_M_OPENMIN] == 1 - && g_inspt_crtra_flag[IDX_M_OPENMAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_SHORT] &= - (g_inspt_crtra_flag[IDX_SHORTMIN] == 1 - && g_inspt_crtra_flag[IDX_SHORTMAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_RAWDATA] &= - (g_inspt_crtra_flag[IDX_RAWMIN] == 1 - && g_inspt_crtra_flag[IDX_RAWMAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_BPN_RAWDATA] &= - (g_inspt_crtra_flag[IDX_BPN_RAWMIN] == 1 - && g_inspt_crtra_flag[IDX_BPN_RAWMAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_SC] &= - (g_inspt_crtra_flag[IDX_SCMIN] == 1 - && g_inspt_crtra_flag[IDX_SCMAX] == 1 - && g_inspt_crtra_flag[IDX_SC_GOLDEN] == 1) ? 1 : 0; - - g_test_item_flag[HX_WT_NOISE] &= - (g_inspt_crtra_flag[IDX_WT_NOISEMIN] == 1 - && g_inspt_crtra_flag[IDX_WT_NOISEMAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_ABS_NOISE] &= - (g_inspt_crtra_flag[IDX_ABS_NOISEMIN] == 1 - && g_inspt_crtra_flag[IDX_ABS_NOISEMAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_SORTING] &= - (g_inspt_crtra_flag[IDX_SORTMIN] == 1 - && g_inspt_crtra_flag[IDX_SORTMAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_GAPTEST_RAW] &= - (g_inspt_crtra_flag[IDX_GAP_HOR_RAWMAX] == 1 - && g_inspt_crtra_flag[IDX_GAP_HOR_RAWMIN] == 1 - && g_inspt_crtra_flag[IDX_GAP_VER_RAWMAX] == 1 - && g_inspt_crtra_flag[IDX_GAP_VER_RAWMIN] == 1) ? 1 : 0; - - g_test_item_flag[HX_ACT_IDLE_RAWDATA] &= - (g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MIN] == 1 - && g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_ACT_IDLE_BPN_RAWDATA] &= - (g_inspt_crtra_flag[IDX_ACT_IDLE_RAW_BPN_MIN] == 1 - && g_inspt_crtra_flag[IDX_ACT_IDLE_RAW_BPN_MAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_ACT_IDLE_NOISE] &= - (g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MIN] == 1 - && g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_LP_RAWDATA] &= - (g_inspt_crtra_flag[IDX_LP_RAWDATA_MIN] == 1 - && g_inspt_crtra_flag[IDX_LP_RAWDATA_MAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_LP_BPN_RAWDATA] &= - (g_inspt_crtra_flag[IDX_LP_RAW_BPN_MIN] == 1 - && g_inspt_crtra_flag[IDX_LP_RAW_BPN_MAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_LP_WT_NOISE] &= - (g_inspt_crtra_flag[IDX_LP_WT_NOISEMAX] == 1 - && g_inspt_crtra_flag[IDX_LP_WT_NOISEMIN] == 1) ? 1 : 0; - - g_test_item_flag[HX_LP_ABS_NOISE] &= - (g_inspt_crtra_flag[IDX_LP_NOISE_ABS_MAX] == 1 - && g_inspt_crtra_flag[IDX_LP_NOISE_ABS_MIN] == 1) ? 1 : 0; - - g_test_item_flag[HX_LP_IDLE_RAWDATA] &= - (g_inspt_crtra_flag[IDX_LP_IDLE_RAWDATA_MAX] == 1 - && g_inspt_crtra_flag[IDX_LP_IDLE_RAWDATA_MIN] == 1) ? 1 : 0; - - g_test_item_flag[HX_LP_IDLE_BPN_RAWDATA] &= - (g_inspt_crtra_flag[IDX_LP_IDLE_RAW_BPN_MIN] == 1 - && g_inspt_crtra_flag[IDX_LP_IDLE_RAW_BPN_MAX] == 1) ? 1 : 0; - - g_test_item_flag[HX_LP_IDLE_NOISE] &= - (g_inspt_crtra_flag[IDX_LP_IDLE_NOISE_MAX] == 1 - && g_inspt_crtra_flag[IDX_LP_IDLE_NOISE_MIN] == 1) ? 1 : 0; - - do_lpwg_test = g_test_item_flag[HX_LP_RAWDATA] - | g_test_item_flag[HX_LP_BPN_RAWDATA] - | g_test_item_flag[HX_LP_WT_NOISE] - | g_test_item_flag[HX_LP_ABS_NOISE] - | g_test_item_flag[HX_LP_IDLE_RAWDATA] - | g_test_item_flag[HX_LP_IDLE_BPN_RAWDATA] - | g_test_item_flag[HX_LP_IDLE_NOISE]; - - for (i = 0; i < HX_CRITERIA_ITEM - 1; i++) - I("g_test_item_flag[%d] = %d\n", i, g_test_item_flag[i]); -} - -int hx_get_size_str_arr(char **input) -{ - int i = 0; - int result = 0; - - while (input[i] != NULL) - i++; - - result = i; - if (private_ts->debug_log_level & BIT(4)) - I("There is %d in [0]=%s\n", result, input[0]); - - return result; -} - -static void hx_print_ic_id(void) -{ - uint8_t i; - int len = 0; - char *prt_data = NULL; - - prt_data = kzalloc(sizeof(char) * HX_SZ_ICID, GFP_KERNEL); - if (prt_data == NULL) { - E("%s: Memory allocation falied!\n", __func__); - return; - } - - len += snprintf(prt_data + len, HX_SZ_ICID - len, - "IC ID : "); - for (i = 0; i < 13; i++) { - len += snprintf(prt_data + len, HX_SZ_ICID - len, - "%02X", ic_data->vendor_ic_id[i]); - } - len += snprintf(prt_data + len, HX_SZ_ICID - len, - "\n"); - - memcpy(&g_rslt_data[0], prt_data, len); - g_rslt_data_len = len; - I("%s: g_rslt_data_len=%d!\n", __func__, g_rslt_data_len); - - kfree(prt_data); -} - -static int himax_self_test_data_init(void) -{ - const struct firmware *file_entry = NULL; - struct himax_ts_data *ts = private_ts; - char *file_name_1 = "hx_criteria.dri"; - char *file_name_2 = "hx_criteria.csv"; - int ret = HX_INSP_OK; - int err = 0; - int i = 0; - - /* - * 5: one value will not over than 99999, so get this size of string - * 2: get twice size - */ - g_1kind_raw_size = 5 * ic_data->HX_RX_NUM * ic_data->HX_TX_NUM * 2; - - /* get test item and its items of criteria*/ - HX_CRITERIA_ITEM = hx_get_size_str_arr(g_himax_inspection_mode); - HX_CRITERIA_SIZE = hx_get_size_str_arr(g_hx_inspt_crtra_name); - I("There is %d HX_CRITERIA_ITEM and %d HX_CRITERIA_SIZE\n", - HX_CRITERIA_ITEM, HX_CRITERIA_SIZE); - - /* init criteria data*/ - g_test_item_flag = kcalloc(HX_CRITERIA_ITEM, sizeof(int), GFP_KERNEL); - if (g_test_item_flag == NULL) { - E("%s,%d: Memory allocation falied!\n", __func__, __LINE__); - ret = HX_INSP_MEMALLCTFAIL; - goto err_malloc_test_item_flag; - } - - g_inspt_crtra_flag = kcalloc(HX_CRITERIA_SIZE, sizeof(int), GFP_KERNEL); - if (g_inspt_crtra_flag == NULL) { - E("%s,%d: Memory allocation falied!\n", __func__, __LINE__); - ret = HX_INSP_MEMALLCTFAIL; - goto err_malloc_inspt_crtra_flag; - } - - g_inspection_criteria = kcalloc(HX_CRITERIA_SIZE, - sizeof(int *), GFP_KERNEL); - if (g_inspection_criteria == NULL) { - E("%s,%d: Memory allocation falied!\n", __func__, __LINE__); - ret = HX_INSP_MEMALLCTFAIL; - goto err_malloc_inspection_criteria; - } - - for (i = 0; i < HX_CRITERIA_SIZE; i++) { - g_inspection_criteria[i] = kcalloc((ic_data->HX_TX_NUM - * ic_data->HX_RX_NUM), - sizeof(int), GFP_KERNEL); - if (g_inspection_criteria[i] == NULL) { - E("%s,%d: Memory allocation %d falied!\n", - __func__, __LINE__, i); - ret = HX_INSP_MEMALLCTFAIL; - goto err_malloc_inspection_criteria2; - } - } - - g_rslt_data_len = 0; - if (g_rslt_data == NULL) { - g_rslt_data = kcalloc(g_1kind_raw_size, sizeof(char), - GFP_KERNEL); - if (g_rslt_data == NULL) { - E("%s,%d: Memory allocation falied!\n", - __func__, __LINE__); - ret = HX_INSP_MEMALLCTFAIL; - goto err_malloc_rslt_data; - } - } - I("%s: initialize g_rslt_data, length = %d\n", - __func__, g_1kind_raw_size); - memset(g_rslt_data, 0x00, g_1kind_raw_size * sizeof(char)); - - /* default path is /system/etc/firmware */ - /* request criteria file*/ - err = request_firmware(&file_entry, file_name_1, ts->dev); - if (err < 0) { - E("%s,Fail to get %s\n", __func__, file_name_1); - err = request_firmware(&file_entry, file_name_2, ts->dev); - if (err < 0) { - E("%s,Fail to get %s\n", __func__, file_name_2); - I("No criteria file file"); - ret = HX_INSP_EFILE; - goto err_open_criteria_file; - } else { - I("%s,Success to get %s\n", __func__, file_name_2); - /* parsing criteria from file .csv*/ - ret = himax_parse_criteria(file_entry); - release_firmware(file_entry); - if (ret > 0) - goto err_open_criteria_file; - himax_test_item_chk(true); - } - } else { - /* parsing test file .dri*/ - I("%s,Success to get %s\n", __func__, file_name_1); - ret = himax_parse_test_dri_file(file_entry); - release_firmware(file_entry); - if (ret > 0) - goto err_open_criteria_file; - himax_test_item_chk(false); - } - - if (private_ts->debug_log_level & BIT(4)) { - /* print get criteria string */ - for (i = 0 ; i < HX_CRITERIA_SIZE ; i++) { - if (g_inspt_crtra_flag[i] != 0) - I("%s: [%d]There is String=%s\n", - __func__, i, g_hx_inspt_crtra_name[i]); - } - } - - snprintf(g_file_path, (int)(strlen(HX_RSLT_OUT_PATH) - + strlen(HX_RSLT_OUT_FILE)+1), - "%s%s", HX_RSLT_OUT_PATH, HX_RSLT_OUT_FILE); - - file_w_flag = true; - return ret; - -err_open_criteria_file: - kfree(g_rslt_data); - g_rslt_data = NULL; -err_malloc_rslt_data: - -err_malloc_inspection_criteria2: - for (i = 0; i < HX_CRITERIA_SIZE; i++) { - if (g_inspection_criteria[i] != NULL) { - kfree(g_inspection_criteria[i]); - g_inspection_criteria[i] = NULL; - } - } - kfree(g_inspection_criteria); - g_inspection_criteria = NULL; -err_malloc_inspection_criteria: - kfree(g_inspt_crtra_flag); - g_inspt_crtra_flag = NULL; -err_malloc_inspt_crtra_flag: - kfree(g_test_item_flag); - g_test_item_flag = NULL; -err_malloc_test_item_flag: - return ret; -} - -static void himax_self_test_data_deinit(void) -{ - int i = 0; - - /*dbg*/ - /* for (i = 0; i < HX_CRITERIA_ITEM; i++) - * I("%s:[%d]%d\n", __func__, i, g_inspection_criteria[i]); - */ - - I("%s: release allocated memory\n", __func__); - - for (i = 0; i < HX_CRITERIA_SIZE; i++) { - if (g_inspection_criteria[i] != NULL) { - kfree(g_inspection_criteria[i]); - g_inspection_criteria[i] = NULL; - } - } - kfree(g_inspection_criteria); - g_inspection_criteria = NULL; - - kfree(g_inspt_crtra_flag); - g_inspt_crtra_flag = NULL; - - kfree(g_test_item_flag); - g_test_item_flag = NULL; - I("%s: release finished\n", __func__); - -} - -static int himax_chip_self_test(struct seq_file *s, void *v) -{ - uint32_t ret = HX_INSP_OK; - uint32_t test_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM - + ic_data->HX_TX_NUM + ic_data->HX_RX_NUM; - int i = 0; - uint8_t tmp_addr[DATA_LEN_4] = {0x94, 0x72, 0x00, 0x10}; - uint8_t tmp_data[DATA_LEN_4] = {0x01, 0x00, 0x00, 0x00}; -#if defined(HX_CODE_OVERLAY) - uint8_t normalfw[32] = "Himax_firmware.bin"; - uint8_t mpapfw[32] = "Himax_mpfw.bin"; -#endif - struct file *raw_file = NULL; - struct filename *vts_name = NULL; - mm_segment_t fs; - loff_t pos = 0; - uint32_t rslt = HX_INSP_OK; - - I("%s:IN\n", __func__); - - private_ts->suspend_resume_done = 0; - - ret = himax_self_test_data_init(); - if (ret > 0) { - E("%s: initialize self test failed\n", __func__); - goto END; - } - -#if defined(HX_CODE_OVERLAY) - g_core_fp.fp_0f_op_file_dirly(mpapfw); - g_core_fp.fp_reload_disable(0); - g_core_fp.fp_sense_on(0x00); -#endif - - if (!kp_getname_kernel) { - E("kp_getname_kernel is NULL, not open file!\n"); - file_w_flag = false; - } else - vts_name = kp_getname_kernel(g_file_path); - - if (raw_file == NULL && file_w_flag) { - raw_file = kp_file_open_name(vts_name, - O_TRUNC|O_CREAT|O_RDWR, 0660); - - if (IS_ERR(raw_file)) { - E("%s open file failed = %ld\n", - __func__, PTR_ERR(raw_file)); - file_w_flag = false; - } - } - - fs = get_fs(); - set_fs(get_ds()); - - hx_print_ic_id(); - if (file_w_flag) { - vfs_write(raw_file, g_rslt_data, g_rslt_data_len, &pos); - pos += g_rslt_data_len; - } - - /*Do normal test items*/ - for (i = 0; i < HX_CRITERIA_ITEM; i++) { - if (i < HX_LP_RAWDATA) { - if (g_test_item_flag[i] == 1) { - I("%d. %s Start\n", i, - g_himax_inspection_mode[i]); - rslt = mpTestFunc(i, test_size); - if (file_w_flag && - ((rslt & HX_INSP_EGETRAW) == 0) && - ((rslt & HX_INSP_ESWITCHMODE) == 0)) { - vfs_write(raw_file, g_rslt_data, - g_rslt_data_len, &pos); - pos += g_rslt_data_len; - } - ret |= rslt; - - I("%d. %s End, ret = %d\n", i, - g_himax_inspection_mode[i], ret); - } - } else { - break; - } - } - - /* Press power key and do LPWUG test items*/ - if (do_lpwg_test) { - himax_press_powerkey(); - /* Wait suspend done */ - while (private_ts->suspend_resume_done != 1) - usleep_range(1000, 1001); - private_ts->suspend_resume_done = 0; - - for (; i < HX_CRITERIA_ITEM; i++) { - if (g_test_item_flag[i] == 1) { - I("%d.%s Start\n", i, - g_himax_inspection_mode[i]); - rslt = mpTestFunc(i, test_size); - if (file_w_flag && - ((rslt & HX_INSP_EGETRAW) == 0) && - ((rslt & HX_INSP_ESWITCHMODE) == 0)) { - vfs_write(raw_file, g_rslt_data, - g_rslt_data_len, &pos); - pos += g_rslt_data_len; - } - ret |= rslt; - - I("%d.%s End\n", i, g_himax_inspection_mode[i]); - } - } - himax_press_powerkey(); - /* Wait resume done */ - while (private_ts->suspend_resume_done != 1) - usleep_range(1000, 1001); - } - if (file_w_flag) - filp_close(raw_file, NULL); - set_fs(fs); - -#if defined(HX_CODE_OVERLAY) - private_ts->in_self_test = 0; - g_core_fp.fp_0f_op_file_dirly(normalfw); - hx_turn_on_mp_func(0); - /* set N frame back to default value 1*/ - g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); - g_core_fp.fp_reload_disable(0); - g_core_fp.fp_sense_on(0); -#else - g_core_fp.fp_sense_off(true); - hx_turn_on_mp_func(0); - /*himax_set_N_frame(1, HX_INSPECTION_WT_NOISE);*/ - /* set N frame back to default value 1*/ - g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); -#if !defined(HX_ZERO_FLASH) - if (g_core_fp.fp_reload_disable != NULL) - g_core_fp.fp_reload_disable(0); -#endif - g_core_fp.fp_sense_on(0); -#endif - - if (ret == HX_INSP_OK) - seq_puts(s, "Self_Test Pass:\n"); - else - seq_puts(s, "Self_Test Fail:\n"); - - for (i = 0; i < HX_CRITERIA_ITEM - 1; i++) { - if (g_test_item_flag[i] == 1) { - seq_printf(s, "%s : %s\n", - g_himax_inspection_mode[i], - ((ret & (1 << (i + ERR_SFT))) - == (1 << (i + ERR_SFT))) ? "Fail":"OK"); - } - } - - himax_self_test_data_deinit(); - -END: - I("running status = %X\n", ret); - - /*if (ret != 0)*/ - /*ret = 1;*/ - - I("%s:OUT\n", __func__); - return ret; -} - -void himax_inspect_data_clear(void) -{ - if (!g_rslt_data) { - kfree(g_rslt_data); - g_rslt_data = NULL; - } -} - -void himax_inspection_init(void) -{ - I("%s: enter, %d\n", __func__, __LINE__); - - g_core_fp.fp_chip_self_test = himax_chip_self_test; -} +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for inspection functions + * + * 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_inspection.h" + +static int g_gap_vertical_partial = 3; +static int *g_gap_vertical_part; +static int g_gap_horizontal_partial = 3; +static int *g_gap_horizontal_part; + +static int g_dc_max; + +static int g_1kind_raw_size; +uint32_t g_rslt_data_len; +int **g_inspection_criteria; +int *g_inspt_crtra_flag; +int HX_CRITERIA_ITEM; +int HX_CRITERIA_SIZE; +char *g_rslt_data; +static char g_file_path[256]; +static char g_rslt_log[256]; +static char g_start_log[256]; +char *hx_self_test_file_name = NULL; + +char *g_himax_inspection_mode[] = { + "HIMAX_INSPECTION_OPEN", + "HIMAX_INSPECTION_MICRO_OPEN", + "HIMAX_INSPECTION_SHORT", + "HIMAX_INSPECTION_RAWDATA", + "HIMAX_INSPECTION_BPN_RAWDATA", + "HIMAX_INSPECTION_WEIGHT_NOISE", + "HIMAX_INSPECTION_ABS_NOISE", + "HIMAX_INSPECTION_SORTING", + "HIMAX_INSPECTION_BACK_NORMAL", + + "HIMAX_INSPECTION_GAPTEST_RAW", + + "HIMAX_INSPECTION_ACT_IDLE_RAWDATA", + "HIMAX_INSPECTION_ACT_IDLE_NOISE", + + "HIMAX_INSPECTION_LPWUG_RAWDATA", + "HIMAX_INSPECTION_LPWUG_NOISE", + "HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA", + "HIMAX_INSPECTION_LPWUG_IDLE_NOISE", + NULL +}; + +/* for criteria */ +char *g_hx_inspt_crtra_name[] = { + "CRITERIA_RAW_MIN", + "CRITERIA_RAW_MAX", + "CRITERIA_RAW_BPN_MIN", + "CRITERIA_RAW_BPN_MAX", + "CRITERIA_SHORT_MIN", + "CRITERIA_SHORT_MAX", + "CRITERIA_OPEN_MIN", + "CRITERIA_OPEN_MAX", + "CRITERIA_MICRO_OPEN_MIN", + "CRITERIA_MICRO_OPEN_MAX", + "CRITERIA_NOISE_WT_MIN", + "CRITERIA_NOISE_WT_MAX", + "CRITERIA_NOISE_ABS_MIN", + "CRITERIA_NOISE_ABS_MAX", + "CRITERIA_SORT_MIN", + "CRITERIA_SORT_MAX", + + "CRITERIA_GAP_RAW_HOR_MIN", + "CRITERIA_GAP_RAW_HOR_MAX", + "CRITERIA_GAP_RAW_VER_MIN", + "CRITERIA_GAP_RAW_VER_MAX", + + "ACT_IDLE_NOISE_MIN", + "ACT_IDLE_NOISE_MAX", + "ACT_IDLE_RAWDATA_MIN", + "ACT_IDLE_RAWDATA_MAX", + + "LPWUG_NOISE_MIN", + "LPWUG_NOISE_MAX", + "LPWUG_RAWDATA_MIN", + "LPWUG_RAWDATA_MAX", + "LPWUG_IDLE_NOISE_MIN", + "LPWUG_IDLE_NOISE_MAX", + "LPWUG_IDLE_RAWDATA_MIN", + "LPWUG_IDLE_RAWDATA_MAX", + NULL +}; + + +void (*fp_himax_self_test_init)(void) = himax_inspection_init; + + +static void himax_press_powerkey(void) +{ + I(" %s POWER KEY event %x press\n", __func__, KEY_POWER); + input_report_key(private_ts->input_dev, KEY_POWER, 1); + input_sync(private_ts->input_dev); + + msleep(100); + + I(" %s POWER KEY event %x release\n", __func__, KEY_POWER); + input_report_key(private_ts->input_dev, KEY_POWER, 0); + input_sync(private_ts->input_dev); +} + + +static uint8_t NOISEMAX; +static uint8_t g_recal_thx; + +static int hx_test_data_pop_out(char *rslt_buf, char *filepath) +{ + struct file *raw_file = NULL; + struct filename *vts_name = NULL; + mm_segment_t fs; + loff_t pos = 0; + int ret_val = NO_ERR; + + I("%s: Entering!\n", __func__); + I("data size=0x%04X\n", (uint32_t)strlen(rslt_buf)); + + if (!kp_getname_kernel) { + E("kp_getname_kernel is NULL, not open file!\n"); + return -EIO; + } + vts_name = kp_getname_kernel(filepath); + + if (raw_file == NULL) + raw_file = kp_file_open_name(vts_name, O_TRUNC|O_CREAT|O_RDWR, + 0660); + + if (IS_ERR(raw_file)) { + E("%s open file failed = %ld\n", __func__, PTR_ERR(raw_file)); + ret_val = -EIO; + goto SAVE_DATA_ERR; + } + + fs = get_fs(); + set_fs(get_ds()); + vfs_write(raw_file, rslt_buf, + g_1kind_raw_size * HX_CRITERIA_ITEM * sizeof(char), &pos); + if (raw_file != NULL) + filp_close(raw_file, NULL); + + set_fs(fs); + +SAVE_DATA_ERR: + I("%s: End!\n", __func__); + return ret_val; +} + +static int hx_test_data_get(uint32_t RAW[], char *start_log, char *result, + int now_item) +{ + uint32_t i; + + ssize_t len = 0; + char *testdata = NULL; + uint32_t SZ_SIZE = g_1kind_raw_size; + + I("%s: Entering, Now type=%s!\n", __func__, + g_himax_inspection_mode[now_item]); + + testdata = kzalloc(sizeof(char) * SZ_SIZE, GFP_KERNEL); + if (testdata == NULL) { + E("%s: Memory allocation falied!\n", __func__); + return MEM_ALLOC_FAIL; + } + + len += snprintf((testdata + len), SZ_SIZE - len, "%s", start_log); + for (i = 0; i < ic_data->HX_TX_NUM*ic_data->HX_RX_NUM; i++) { + if (i > 1 && ((i + 1) % ic_data->HX_RX_NUM) == 0) + len += snprintf((testdata + len), SZ_SIZE - len, + "%5d,\n", RAW[i]); + else + len += snprintf((testdata + len), SZ_SIZE - len, + "%5d,", RAW[i]); + } + len += snprintf((testdata + len), SZ_SIZE - len, "\n%s", result); + + memcpy(&g_rslt_data[g_rslt_data_len], testdata, len); + g_rslt_data_len += len; + I("%s: g_rslt_data_len=%d!\n", __func__, g_rslt_data_len); + + /*memcpy(&g_rslt_data[now_item * SZ_SIZE], testdata, SZ_SIZE);*/ + + /* dbg */ + /* for(i = 0; i < SZ_SIZE; i++) + * { + * I("0x%04X, ", g_rslt_data[i + (now_item * SZ_SIZE)]); + * if(i > 0 && (i % 16 == 15)) + * PI("\n"); + * } + */ + + kfree(testdata); + I("%s: End!\n", __func__); + return NO_ERR; + +} + +static int himax_switch_mode_inspection(int mode) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + I("%s: Entering\n", __func__); + + /*Stop Handshaking*/ + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; + tmp_addr[0] = 0x00; tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); + + /*Swtich Mode*/ + switch (mode) { + case HIMAX_INSPECTION_SORTING: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_SORTING_START; + tmp_data[0] = PWD_SORTING_START; + break; + case HIMAX_INSPECTION_OPEN: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_OPEN_START; + tmp_data[0] = PWD_OPEN_START; + break; + case HIMAX_INSPECTION_MICRO_OPEN: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_OPEN_START; + tmp_data[0] = PWD_OPEN_START; + break; + case HIMAX_INSPECTION_SHORT: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_SHORT_START; + tmp_data[0] = PWD_SHORT_START; + break; + + case HIMAX_INSPECTION_GAPTEST_RAW: + case HIMAX_INSPECTION_RAWDATA: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_RAWDATA_START; + tmp_data[0] = PWD_RAWDATA_START; + break; + case HIMAX_INSPECTION_BPN_RAWDATA: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_RAWDATA_START; + tmp_data[0] = PWD_RAWDATA_START; + break; + case HIMAX_INSPECTION_WEIGHT_NOISE: + case HIMAX_INSPECTION_ABS_NOISE: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_NOISE_START; + tmp_data[0] = PWD_NOISE_START; + break; + + case HIMAX_INSPECTION_ACT_IDLE_RAWDATA: + case HIMAX_INSPECTION_ACT_IDLE_NOISE: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_ACT_IDLE_START; + tmp_data[0] = PWD_ACT_IDLE_START; + break; + + case HIMAX_INSPECTION_LPWUG_RAWDATA: + case HIMAX_INSPECTION_LPWUG_NOISE: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_LPWUG_START; + tmp_data[0] = PWD_LPWUG_START; + break; + case HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA: + case HIMAX_INSPECTION_LPWUG_IDLE_NOISE: + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = PWD_LPWUG_IDLE_START; + tmp_data[0] = PWD_LPWUG_IDLE_START; + break; + + default: + I("%s,Nothing to be done!\n", __func__); + break; + } + + if (g_core_fp.fp_assign_sorting_mode != NULL) + g_core_fp.fp_assign_sorting_mode(tmp_data); + I("%s: End of setting!\n", __func__); + + return 0; + +} + +static int himax_get_rawdata(uint32_t RAW[], uint32_t datalen) +{ + uint8_t *tmp_rawdata; + bool get_raw_rlst; + uint8_t retry = 0; + uint32_t i = 0; + uint32_t j = 0; + uint32_t index = 0; + uint32_t Min_DATA = 0xFFFFFFFF; + uint32_t Max_DATA = 0x00000000; + + /* We use two bytes to combine a value of rawdata.*/ + tmp_rawdata = kzalloc(sizeof(uint8_t) * (datalen * 2), GFP_KERNEL); + if (tmp_rawdata == NULL) { + E("%s: Memory allocation falied!\n", __func__); + return MEM_ALLOC_FAIL; + } + + while (retry < 200) { + get_raw_rlst = g_core_fp.fp_get_DSRAM_data(tmp_rawdata, false); + if (get_raw_rlst) + break; + retry++; + } + + if (retry >= 200) + goto DIRECT_END; + + /* Copy Data*/ + for (i = 0; i < ic_data->HX_TX_NUM*ic_data->HX_RX_NUM; i++) + RAW[i] = tmp_rawdata[(i * 2) + 1] * 256 + tmp_rawdata[(i * 2)]; + /* don't output these logs, reduce factory test time + for (j = 0; j < ic_data->HX_RX_NUM; j++) { + if (j == 0) + PI(" RX%2d", j + 1); + else + PI(" RX%2d", j + 1); + } + PI("\n"); + ******* delete these logs *********************/ + + for (i = 0; i < ic_data->HX_TX_NUM; i++) { + /*PI("TX%2d", i + 1);*/ + for (j = 0; j < ic_data->HX_RX_NUM; j++) { + PI("%5d ", RAW[index]); + if (RAW[index] > Max_DATA) + Max_DATA = RAW[index]; + + if (RAW[index] < Min_DATA) + Min_DATA = RAW[index]; + + index++; + } + /*PI("\n");*/ + } + I("Max = %5d, Min = %5d\n", Max_DATA, Min_DATA); +DIRECT_END: + kfree(tmp_rawdata); + + if (get_raw_rlst) + return HX_INSPECT_OK; + else + return HX_INSPECT_EGETRAW; + +} + +static void himax_switch_data_type(uint8_t checktype) +{ + uint8_t datatype = 0x00; + + switch (checktype) { + case HIMAX_INSPECTION_SORTING: + datatype = DATA_SORTING; + break; + case HIMAX_INSPECTION_OPEN: + datatype = DATA_OPEN; + break; + case HIMAX_INSPECTION_MICRO_OPEN: + datatype = DATA_MICRO_OPEN; + break; + case HIMAX_INSPECTION_SHORT: + datatype = DATA_SHORT; + break; + case HIMAX_INSPECTION_RAWDATA: + datatype = DATA_RAWDATA; + break; + case HIMAX_INSPECTION_BPN_RAWDATA: + datatype = DATA_RAWDATA; + break; + case HIMAX_INSPECTION_WEIGHT_NOISE: + case HIMAX_INSPECTION_ABS_NOISE: + datatype = DATA_NOISE; + break; + case HIMAX_INSPECTION_BACK_NORMAL: + datatype = DATA_BACK_NORMAL; + break; + + case HIMAX_INSPECTION_GAPTEST_RAW: + datatype = DATA_RAWDATA; + break; + + case HIMAX_INSPECTION_ACT_IDLE_RAWDATA: + datatype = DATA_ACT_IDLE_RAWDATA; + break; + case HIMAX_INSPECTION_ACT_IDLE_NOISE: + datatype = DATA_ACT_IDLE_NOISE; + break; + + case HIMAX_INSPECTION_LPWUG_RAWDATA: + datatype = DATA_LPWUG_RAWDATA; + break; + case HIMAX_INSPECTION_LPWUG_NOISE: + datatype = DATA_LPWUG_NOISE; + break; + case HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA: + datatype = DATA_LPWUG_IDLE_RAWDATA; + break; + case HIMAX_INSPECTION_LPWUG_IDLE_NOISE: + datatype = DATA_LPWUG_IDLE_NOISE; + break; + + default: + E("Wrong type=%d\n", checktype); + break; + } + g_core_fp.fp_diag_register_set(datatype, 0x00); +} + +static void himax_bank_search_set(uint16_t Nframe, uint8_t checktype) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + /*skip frame*/ + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x70; tmp_addr[0] = 0xF4; + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + + switch (checktype) { + case HIMAX_INSPECTION_ACT_IDLE_RAWDATA: + case HIMAX_INSPECTION_ACT_IDLE_NOISE: + tmp_data[0] = BS_ACT_IDLE; + break; + case HIMAX_INSPECTION_LPWUG_RAWDATA: + case HIMAX_INSPECTION_LPWUG_NOISE: + tmp_data[0] = BS_LPWUG; + break; + case HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA: + case HIMAX_INSPECTION_LPWUG_IDLE_NOISE: + tmp_data[0] = BS_LPWUG_dile; + break; + case HIMAX_INSPECTION_RAWDATA: + case HIMAX_INSPECTION_BPN_RAWDATA: + tmp_data[0] = BS_RAWDATA; + break; + case HIMAX_INSPECTION_WEIGHT_NOISE: + case HIMAX_INSPECTION_ABS_NOISE: + tmp_data[0] = BS_NOISE; + break; + default: + tmp_data[0] = BS_OPENSHORT; + break; + } + g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); +} + +static void himax_neg_noise_sup(uint8_t *data) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + /*0x10007FD8 Check support negative value or not */ + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x7F; tmp_addr[0] = 0xD8; + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + + if ((tmp_data[3] & 0x04) == 0x04) { + data[2] = 0x0C; data[3] = 0x7F; + } else + I("%s Not support negative noise\n", __func__); +} + +static void himax_set_N_frame(uint16_t Nframe, uint8_t checktype) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + himax_bank_search_set(Nframe, checktype); + + /*IIR MAX*/ + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x72; + tmp_addr[0] = 0x94; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = (uint8_t)((Nframe & 0xFF00) >> 8); + tmp_data[0] = (uint8_t)(Nframe & 0x00FF); + g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); + + if (checktype == HIMAX_INSPECTION_WEIGHT_NOISE || + checktype == HIMAX_INSPECTION_ABS_NOISE) + himax_neg_noise_sup(tmp_data); + + g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); +} + +static void himax_get_noise_base(void)/*Normal Threshold*/ +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x70; tmp_addr[0] = 0x8C;/*0x1000708F*/ + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + + NOISEMAX = tmp_data[3]; + + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x70; tmp_addr[0] = 0x90;/*0x10007092*/ + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + + g_recal_thx = tmp_data[2]; + I("%s: NOISEMAX=%d, g_recal_thx = %d\n", __func__, + NOISEMAX, g_recal_thx); +} + +static uint16_t himax_get_palm_num(void)/*Palm Number*/ +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + uint16_t palm_num; + + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x70; tmp_addr[0] = 0xA8;/*0x100070AB*/ + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + palm_num = tmp_data[3]; + I("%s: palm_num = %d ", __func__, palm_num); + + return palm_num; +} + +static int himax_get_noise_weight_test(void) +{ + uint8_t tmp_addr[4]; + uint8_t tmp_data[4]; + uint16_t weight = 0; + uint16_t value = 0; + + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x72; tmp_addr[0] = 0xC8;/*0x100072C8 weighting value*/ + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + if (tmp_data[3] != 0x72 || tmp_data[2] != 0xC8) + return FW_NOT_READY; + + value = (tmp_data[1] << 8) | tmp_data[0]; + I("%s: value = %d, %d, %d ", __func__, value, tmp_data[2], tmp_data[3]); + + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x70; tmp_addr[0] = 0x9C;/*0x1000709C weighting threshold*/ + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + weight = tmp_data[0]; + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x70; tmp_addr[0] = 0x94;/*0x10007095 weighting threshold*/ + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + weight = tmp_data[1] * weight; + I("%s: weight = %d ", __func__, weight); + + if (value > weight) + return ERR_TEST_FAIL; + else + return 0; +} + +static uint32_t himax_check_mode(uint8_t checktype) +{ + uint8_t tmp_data[4] = {0}; + uint8_t wait_pwd[2] = {0}; + + switch (checktype) { + case HIMAX_INSPECTION_SORTING: + wait_pwd[0] = PWD_SORTING_END; + wait_pwd[1] = PWD_SORTING_END; + break; + case HIMAX_INSPECTION_OPEN: + wait_pwd[0] = PWD_OPEN_END; + wait_pwd[1] = PWD_OPEN_END; + break; + case HIMAX_INSPECTION_MICRO_OPEN: + wait_pwd[0] = PWD_OPEN_END; + wait_pwd[1] = PWD_OPEN_END; + break; + case HIMAX_INSPECTION_SHORT: + wait_pwd[0] = PWD_SHORT_END; + wait_pwd[1] = PWD_SHORT_END; + break; + case HIMAX_INSPECTION_RAWDATA: + wait_pwd[0] = PWD_RAWDATA_END; + wait_pwd[1] = PWD_RAWDATA_END; + break; + case HIMAX_INSPECTION_BPN_RAWDATA: + wait_pwd[0] = PWD_RAWDATA_END; + wait_pwd[1] = PWD_RAWDATA_END; + break; + case HIMAX_INSPECTION_WEIGHT_NOISE: + case HIMAX_INSPECTION_ABS_NOISE: + wait_pwd[0] = PWD_NOISE_END; + wait_pwd[1] = PWD_NOISE_END; + break; + + case HIMAX_INSPECTION_ACT_IDLE_RAWDATA: + case HIMAX_INSPECTION_ACT_IDLE_NOISE: + wait_pwd[0] = PWD_ACT_IDLE_END; + wait_pwd[1] = PWD_ACT_IDLE_END; + break; + + case HIMAX_INSPECTION_LPWUG_RAWDATA: + case HIMAX_INSPECTION_LPWUG_NOISE: + wait_pwd[0] = PWD_LPWUG_END; + wait_pwd[1] = PWD_LPWUG_END; + break; + case HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA: + case HIMAX_INSPECTION_LPWUG_IDLE_NOISE: + wait_pwd[0] = PWD_LPWUG_IDLE_END; + wait_pwd[1] = PWD_LPWUG_IDLE_END; + break; + + default: + E("Wrong type=%d\n", checktype); + break; + } + + if (g_core_fp.fp_check_sorting_mode != NULL) + g_core_fp.fp_check_sorting_mode(tmp_data); + + if ((wait_pwd[0] == tmp_data[0]) && (wait_pwd[1] == tmp_data[1])) { + I("Change to mode=%s\n", g_himax_inspection_mode[checktype]); + return 0; + } else { + return 1; + } +} + +#define TEMP_LOG "%s: %s, tmp_data[0]=%x,tmp_data[1]=%x,tmp_data[2]=%x,tmp_data[3]=%x\n" + +static uint32_t himax_wait_sorting_mode(uint8_t checktype) +{ + uint8_t tmp_addr[4] = {0}; + uint8_t tmp_data[4] = {0}; + uint8_t wait_pwd[2] = {0}; + int count = 0; + + switch (checktype) { + case HIMAX_INSPECTION_SORTING: + wait_pwd[0] = PWD_SORTING_END; + wait_pwd[1] = PWD_SORTING_END; + break; + case HIMAX_INSPECTION_OPEN: + wait_pwd[0] = PWD_OPEN_END; + wait_pwd[1] = PWD_OPEN_END; + break; + case HIMAX_INSPECTION_MICRO_OPEN: + wait_pwd[0] = PWD_OPEN_END; + wait_pwd[1] = PWD_OPEN_END; + break; + case HIMAX_INSPECTION_SHORT: + wait_pwd[0] = PWD_SHORT_END; + wait_pwd[1] = PWD_SHORT_END; + break; + case HIMAX_INSPECTION_RAWDATA: + wait_pwd[0] = PWD_RAWDATA_END; + wait_pwd[1] = PWD_RAWDATA_END; + break; + case HIMAX_INSPECTION_BPN_RAWDATA: + wait_pwd[0] = PWD_RAWDATA_END; + wait_pwd[1] = PWD_RAWDATA_END; + break; + case HIMAX_INSPECTION_WEIGHT_NOISE: + case HIMAX_INSPECTION_ABS_NOISE: + wait_pwd[0] = PWD_NOISE_END; + wait_pwd[1] = PWD_NOISE_END; + break; + + case HIMAX_INSPECTION_GAPTEST_RAW: + wait_pwd[0] = PWD_RAWDATA_END; + wait_pwd[1] = PWD_RAWDATA_END; + break; + + case HIMAX_INSPECTION_ACT_IDLE_RAWDATA: + case HIMAX_INSPECTION_ACT_IDLE_NOISE: + wait_pwd[0] = PWD_ACT_IDLE_END; + wait_pwd[1] = PWD_ACT_IDLE_END; + break; + + case HIMAX_INSPECTION_LPWUG_RAWDATA: + case HIMAX_INSPECTION_LPWUG_NOISE: + wait_pwd[0] = PWD_LPWUG_END; + wait_pwd[1] = PWD_LPWUG_END; + break; + case HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA: + case HIMAX_INSPECTION_LPWUG_IDLE_NOISE: + wait_pwd[0] = PWD_LPWUG_IDLE_END; + wait_pwd[1] = PWD_LPWUG_IDLE_END; + break; + + default: + I("No Change Mode and now type=%d\n", checktype); + break; + } + + do { + if (g_core_fp.fp_check_sorting_mode != NULL) + g_core_fp.fp_check_sorting_mode(tmp_data); + if ((wait_pwd[0] == tmp_data[0]) && + (wait_pwd[1] == tmp_data[1])) + return 0; + + + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0xA8; + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + I(TEMP_LOG, __func__, "0x900000A8", + tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0xE4; + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + I(TEMP_LOG, __func__, "0x900000E4", + tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x7F; tmp_addr[0] = 0x40; + g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false); + I(TEMP_LOG, __func__, "0x10007F40", + tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + I("Now retry %d times!\n", count++); + msleep(50); + } while (count < 50); + + return 1; +} + +static int hx_turn_on_mp_func(int on) +{ + int rslt = 0; + int retry = 3; + uint8_t tmp_addr[4] = {0}; + uint8_t tmp_data[4] = {0}; + uint8_t tmp_read[4] = {0}; + /* char *tmp_chipname = private_ts->chip_name; */ + + tmp_addr[3] = 0x10; tmp_addr[2] = 0x00; tmp_addr[1] = 0x73; tmp_addr[0] = 0xEC; + if (on) { + I("%s : Turn on!\n", __func__); + if (strcmp(HX_83102D_SERIES_PWON, private_ts->chip_name) == 0) { + I("%s: need to enter Mp mode!\n", __func__); + tmp_data[3] = 0x00; tmp_data[2] = 0x10; tmp_data[1] = 0x73; tmp_data[0] = 0x80; + do { + g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); + usleep_range(10000, 10001); + g_core_fp.fp_register_read(tmp_addr, 4, tmp_read, false); + I("%s: now read[2]=0x%02X, read[1]=0x%02X, read[0]=0x%02X!\n", + __func__, tmp_read[2], tmp_read[1], tmp_read[0]); + retry--; + } while (((retry > 0) && (tmp_read[2] != tmp_data[2] && tmp_read[1] != tmp_data[1] && tmp_read[0] != tmp_data[0]))); + } else { + I("%s:Nothing to be done!\n", __func__); + } + } else { + I("%s : Turn off!\n", __func__); + if (strcmp(HX_83102D_SERIES_PWON, private_ts->chip_name) == 0) { + I("%s: need to enter Mp mode!\n", __func__); + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + do { + g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); + usleep_range(10000, 10001); + g_core_fp.fp_register_read(tmp_addr, 4, tmp_read, false); + I("%s: now read[2]=0x%02X, read[1]=0x%02X, read[0]=0x%02X!\n", __func__, tmp_read[2], tmp_read[1], tmp_read[0]); + retry--; + } while ((retry > 0) && (tmp_read[2] != tmp_data[2] && tmp_read[1] != tmp_data[1] && tmp_read[0] != tmp_data[0])); + } else { + I("%s Nothing to be done!\n", __func__); + } + } + return rslt; +} + +/* HX_GAP START */ +/* gap test function */ +/* extern int himax_write_to_ic_flash_flow(uint32_t start_addr,uint32_t + * *write_data,uint32_t write_len); + */ + +static int himax_gap_test_vertical_setting(void) +{ + g_gap_vertical_part = kcalloc(g_gap_vertical_partial, + sizeof(int), GFP_KERNEL); + if (g_gap_vertical_part == NULL) { + E("%s: Memory allocation falied!\n", __func__); + return MEM_ALLOC_FAIL; + } + g_gap_vertical_part[0] = 0; + g_gap_vertical_part[1] = 4; + g_gap_vertical_part[2] = 8; + kfree(g_gap_vertical_part); + + return NO_ERR; +} + +static void himax_cal_gap_data_vertical(int start, int end_idx, int direct, + uint32_t *org_raw, uint32_t *result_raw) +{ + int i = 0; + int rx_num = ic_data->HX_RX_NUM; + + I("%s:start=%d\n", __func__, start); + I("%s:end_idx=%d\n", __func__, end_idx); + for (i = start; i < (start + rx_num*end_idx); i++) { + if (direct == 0) { /* up - down */ + if (i < start+rx_num) + result_raw[i] = 0; + else + result_raw[i] = org_raw[i-rx_num] - org_raw[i]; + + } else { /* down - up */ + if (i > (start + rx_num*(end_idx-1)-1)) + result_raw[i] = 0; + else + result_raw[i] = org_raw[i+rx_num] - org_raw[i]; + + } + } +} + +static int himax_gap_test_vertical_raw(int test_type, uint32_t *org_raw) +{ + int i_partial = 0; + int tmp_start = 0; + int tmp_end_idx = 0; + uint32_t *result_raw; + int i = 0; + int ret_val = NO_ERR; + + int tx_num = ic_data->HX_TX_NUM; + int rx_num = ic_data->HX_RX_NUM; + + if (himax_gap_test_vertical_setting()) + return MEM_ALLOC_FAIL; + + I("Print vertical ORG RAW\n"); + for (i = 0; i < tx_num*rx_num; i++) { + I("%04d,", org_raw[i]); + if (i > 0 && i%rx_num == (rx_num-1)) + I("\n"); + } + + result_raw = kcalloc(tx_num*rx_num, sizeof(uint32_t), GFP_KERNEL); + if (result_raw == NULL) { + E("%s: Memory allocation falied!\n", __func__); + goto alloc_result_raw_failed; + } + + for (i_partial = 0; i_partial < g_gap_vertical_partial; i_partial++) { + + tmp_start = g_gap_vertical_part[i_partial]*rx_num; + if (i_partial+1 == g_gap_vertical_partial) + tmp_end_idx = tx_num - g_gap_vertical_part[i_partial]; + else + tmp_end_idx = g_gap_vertical_part[i_partial+1] - + g_gap_vertical_part[i_partial]; + + if (i_partial % 2 == 0) + himax_cal_gap_data_vertical(tmp_start, tmp_end_idx, 0, + org_raw, result_raw); + else + himax_cal_gap_data_vertical(tmp_start, tmp_end_idx, 1, + org_raw, result_raw); + + } + + I("Print Vertical New RAW\n"); + for (i = 0; i < tx_num*rx_num; i++) { + I("%04d,", result_raw[i]); + if (i > 0 && i%rx_num == (rx_num-1)) + I("\n"); + } + + for (i = 0; i < tx_num*rx_num; i++) { + if (result_raw[i] < g_inspection_criteria[IDX_GAP_VER_RAWMIN][i] + && + result_raw[i] > g_inspection_criteria[IDX_GAP_VER_RAWMAX][i]) { + ret_val = NO_ERR - i; + break; + } + } + + /* himax_write_to_ic_flash_flow(0x1A000,result_raw,tx_num*rx_num); */ + kfree(result_raw); +alloc_result_raw_failed: + kfree(g_gap_vertical_part); + g_gap_vertical_part = NULL; + + return ret_val; +} + +static int himax_gap_test_horizontal_setting(void) +{ + g_gap_horizontal_part = kcalloc(g_gap_horizontal_partial, + sizeof(int), GFP_KERNEL); + if (g_gap_horizontal_part == NULL) { + E("%s: Memory allocation falied!\n", __func__); + return MEM_ALLOC_FAIL; + } + g_gap_horizontal_part[0] = 0; + g_gap_horizontal_part[1] = 8; + g_gap_horizontal_part[2] = 24; + + return NO_ERR; +} + +static void himax_cal_gap_data_horizontal(int start, int end_idx, int direct, + uint32_t *org_raw, uint32_t *result_raw) +{ + int i = 0; + int j = 0; + int rx_num = ic_data->HX_RX_NUM; + int tx_num = ic_data->HX_TX_NUM; + + I("start=%d\n", start); + I("end_idx=%d\n", end_idx); + for (j = 0; j < tx_num; j++) { + for (i = (start + (j*rx_num)); + i < (start + (j*rx_num) + end_idx); i++) { + /* left - right */ + if (direct == 0) { + if (i == (start + (j*rx_num))) + result_raw[i] = 0; + else + result_raw[i] = + org_raw[i-1] - org_raw[i]; + + } else { /* right - left */ + if (i == ((start + (j*rx_num) + end_idx) - 1)) + result_raw[i] = 0; + else + result_raw[i] = + org_raw[i + 1] - org_raw[i]; + } + } + } +} + +static int himax_gap_test_honrizontal_raw(int test_type, uint32_t *raw) +{ + int rx_num = ic_data->HX_RX_NUM; + int tx_num = ic_data->HX_TX_NUM; + int tmp_start = 0; + int tmp_end_idx = 0; + int i_partial = 0; + uint32_t *result_raw; + int i = 0; + int ret_val = NO_ERR; + + if (himax_gap_test_horizontal_setting()) + return MEM_ALLOC_FAIL; + + result_raw = kcalloc(ic_data->HX_TX_NUM * ic_data->HX_RX_NUM, + sizeof(uint32_t), GFP_KERNEL); + if (result_raw == NULL) { + E("%s: Memory allocation falied!\n", __func__); + goto alloc_result_raw_failed; + } + + I("Print Horizontal ORG RAW\n"); + for (i = 0; i < tx_num*rx_num; i++) { + I("%04d,", raw[i]); + if (i > 0 && i%rx_num == (rx_num-1)) + I("\n"); + } + + for (i_partial = 0; i_partial < g_gap_horizontal_partial; i_partial++) { + tmp_start = g_gap_horizontal_part[i_partial]; + if (i_partial+1 == g_gap_horizontal_partial) + tmp_end_idx = rx_num - g_gap_horizontal_part[i_partial]; + else + tmp_end_idx = g_gap_horizontal_part[i_partial+1] - + g_gap_horizontal_part[i_partial]; + + if (i_partial % 2 == 0) + himax_cal_gap_data_horizontal(tmp_start, tmp_end_idx, + 0, raw, result_raw); + else + himax_cal_gap_data_horizontal(tmp_start, tmp_end_idx, + 1, raw, result_raw); + + } + I("Print Horizontal New RAW\n"); + for (i = 0; i < tx_num*rx_num; i++) { + I("%04d,", result_raw[i]); + if (i > 0 && i%rx_num == (rx_num-1)) + I("\n"); + } + + for (i = 0; i < tx_num*rx_num; i++) { + if (result_raw[i] < g_inspection_criteria[IDX_GAP_HOR_RAWMIN][i] + && + result_raw[i] > g_inspection_criteria[IDX_GAP_HOR_RAWMAX][i]) { + ret_val = NO_ERR - i; + break; + } + } + + /* himax_write_to_ic_flash_flow(0x1A800,result_raw,tx_num*rx_num); */ + kfree(result_raw); +alloc_result_raw_failed: + kfree(g_gap_horizontal_part); + g_gap_horizontal_part = NULL; + + return ret_val; +} +/* HX_GAP END*/ +#define FAIL_IN_INDEX "%s: %s FAIL in index %d\n" +static uint32_t mpTestFunc(uint8_t checktype, uint32_t datalen) +{ + int32_t ret = 0; + uint32_t i/*, j*/; + uint32_t *RAW = NULL; + uint16_t palm_num = 0; + uint16_t noise_count = 0; + int ret_val = -1; + + /*uint16_t* pInspectGridData = &gInspectGridData[0];*/ + /*uint16_t* pInspectNoiseData = &gInspectNoiseData[0];*/ + I("Now Check type = %d\n", checktype); + + RAW = kcalloc(datalen, sizeof(uint32_t), GFP_KERNEL); + if (RAW == NULL) { + E("%s, Failed to allocate memory\n", __func__); + return HX_INSPECT_MEMALLCTFAIL; + } + + if (himax_check_mode(checktype)) { + /*himax_check_mode(checktype);*/ + + I("Need Change Mode ,target=%s\n", g_himax_inspection_mode[checktype]); + + g_core_fp.fp_sense_off(true); + hx_turn_on_mp_func(1); + +#ifndef HX_ZERO_FLASH + if (g_core_fp.fp_reload_disable != NULL) + g_core_fp.fp_reload_disable(1); +#endif + + himax_switch_mode_inspection(checktype); + + switch (checktype) { + case HIMAX_INSPECTION_SORTING: + himax_set_N_frame(OTHERSFRAME, checktype); + ret_val = HX_INSPECT_EOPEN; + break; + + case HIMAX_INSPECTION_OPEN: + himax_set_N_frame(OTHERSFRAME, checktype); + ret_val = HX_INSPECT_EOPEN; + break; + + case HIMAX_INSPECTION_MICRO_OPEN: + himax_set_N_frame(OTHERSFRAME, checktype); + ret_val = HX_INSPECT_EMOPEN; + break; + + case HIMAX_INSPECTION_SHORT: + himax_set_N_frame(OTHERSFRAME, checktype); + ret_val = HX_INSPECT_ESHORT; + break; + + case HIMAX_INSPECTION_RAWDATA: + himax_set_N_frame(OTHERSFRAME, checktype); + ret_val = HX_INSPECT_ERAW; + break; + + case HIMAX_INSPECTION_BPN_RAWDATA: + himax_set_N_frame(OTHERSFRAME, checktype); + ret_val = HX_INSPECT_ERAW; + break; + + case HIMAX_INSPECTION_WEIGHT_NOISE: + himax_set_N_frame(NOISEFRAME, checktype); + ret_val = HX_INSPECT_WT_ENOISE; + break; + + case HIMAX_INSPECTION_ABS_NOISE: + himax_set_N_frame(NOISEFRAME, checktype); + ret_val = HX_INSPECT_ABS_ENOISE; + break; + + case HIMAX_INSPECTION_GAPTEST_RAW: + himax_set_N_frame(OTHERSFRAME, checktype); + ret_val = HX_INSPECT_EGAP_RAW; + break; + + case HIMAX_INSPECTION_ACT_IDLE_RAWDATA: + himax_set_N_frame(NORMAL_IDLE_RAWDATA_NOISEFRAME, checktype); + ret_val = HX_INSPECT_EACT_IDLE_RAW; + break; + + case HIMAX_INSPECTION_ACT_IDLE_NOISE: + himax_set_N_frame(NORMAL_IDLE_RAWDATA_NOISEFRAME, checktype); + ret_val = HX_INSPECT_EACT_IDLE_NOISE; + break; + + case HIMAX_INSPECTION_LPWUG_RAWDATA: + himax_set_N_frame(OTHERSFRAME, checktype); + ret_val = HX_INSPECT_ELPWUG_RAW; + break; + + case HIMAX_INSPECTION_LPWUG_NOISE: + himax_set_N_frame(LPWUG_NOISEFRAME, checktype); + ret_val = HX_INSPECT_ELPWUG_NOISE; + break; + + case HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA: + himax_set_N_frame(LPWUG_IDLE_RAWDATAFRAME, checktype); + ret_val = HX_INSPECT_ELPWUG_IDLE_RAW; + break; + + case HIMAX_INSPECTION_LPWUG_IDLE_NOISE: + himax_set_N_frame(LPWUG_IDLE_NOISEFRAME, checktype); + ret_val = HX_INSPECT_ELPWUG_IDLE_NOISE; + break; + + default: + E("UNDEFINED test type %d, exit\n", checktype); + ret_val = 0xFFFFFFFF; + break; + } + +/* + * if (checktype == HIMAX_INSPECTION_WEIGHT_NOISE || + * checktype == HIMAX_INSPECTION_ABS_NOISE) { + * himax_set_N_frame(NOISEFRAME, checktype); + * } else if (checktype == HIMAX_INSPECTION_ACT_IDLE_RAWDATA || + * checktype == HIMAX_INSPECTION_ACT_IDLE_NOISE) { + * I("N frame = %d\n", NORMAL_IDLE_RAWDATA_NOISEFRAME); + * himax_set_N_frame(NORMAL_IDLE_RAWDATA_NOISEFRAME, checktype); + * } else if (checktype == HIMAX_INSPECTION_LPWUG_RAWDATA) { + * I("N frame = %d\n", LPWUG_RAWDATAFRAME); + * himax_set_N_frame(LPWUG_RAWDATAFRAME, checktype); + * } else if (checktype == HIMAX_INSPECTION_LPWUG_NOISE) { + * I("N frame = %d\n", LPWUG_NOISEFRAME); + * himax_set_N_frame(LPWUG_NOISEFRAME, checktype); + * } else if (checktype == HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA) { + * I("N frame = %d\n", LPWUG_IDLE_RAWDATAFRAME); + * himax_set_N_frame(LPWUG_IDLE_RAWDATAFRAME, checktype); + * } else if (checktype == HIMAX_INSPECTION_LPWUG_IDLE_NOISE) { + * I("N frame = %d\n", LPWUG_IDLE_NOISEFRAME); + * himax_set_N_frame(LPWUG_IDLE_NOISEFRAME, checktype); + * } else { + * himax_set_N_frame(OTHERSFRAME, checktype); + * } + */ + + g_core_fp.fp_sense_on(1); + + if (ret_val == 0xFFFFFFFF) + return ret_val; + } + + ret = himax_wait_sorting_mode(checktype); + if (ret) { + E("%s: himax_wait_sorting_mode FAIL\n", __func__); + return ret_val; + } + himax_switch_data_type(checktype); + + ret = himax_get_rawdata(RAW, datalen); + if (ret) { + E("%s: himax_get_rawdata FAIL\n", __func__); + return ret_val | ret; + } + + /*get Max DC from FW*/ + g_dc_max = g_core_fp.fp_get_max_dc(); + + /* back to normal */ + himax_switch_data_type(HIMAX_INSPECTION_BACK_NORMAL); + + I("%s: Init OK, start to test!\n", __func__); + + snprintf(g_start_log, 256 * sizeof(char), "\n%s%s\n", + g_himax_inspection_mode[checktype], ": data as follow!\n"); + + /*Check Data*/ + switch (checktype) { + case HIMAX_INSPECTION_SORTING: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] < g_inspection_criteria[IDX_SORTMIN][i]) { + E(FAIL_IN_INDEX, __func__, "sorting mode open test", i); + ret_val = HX_INSPECT_EOPEN; + goto FAIL_END; + } + } + I("%s: sorting mode open test PASS\n", __func__); + break; + + case HIMAX_INSPECTION_OPEN: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_OPENMAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_OPENMIN][i]) { + E(FAIL_IN_INDEX, __func__, "open test", i); + ret_val = HX_INSPECT_EOPEN; + goto FAIL_END; + } + } + I("%s: open test PASS\n", __func__); + break; + + case HIMAX_INSPECTION_MICRO_OPEN: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_M_OPENMAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_M_OPENMIN][i]) { + E(FAIL_IN_INDEX, __func__, "micro open test", i); + ret_val = HX_INSPECT_EMOPEN; + goto FAIL_END; + } + } + I("%s: micro open test PASS\n", __func__); + break; + + case HIMAX_INSPECTION_SHORT: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_SHORTMAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_SHORTMIN][i]) { + E(FAIL_IN_INDEX, __func__, "short test", i); + ret_val = HX_INSPECT_ESHORT; + goto FAIL_END; + } + } + I("%s: short test PASS\n", __func__); + break; + + case HIMAX_INSPECTION_RAWDATA: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + /* I("Now new compare, datalen=%d!\n", + * ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); + */ + if ((int)RAW[i] > g_inspection_criteria[IDX_RAWMAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_RAWMIN][i]) { + E("%s: rawdata test FAIL:RAW[%d]=%d\n", __func__, i, RAW[i]); + I("%s: Now Criteria max=%d,min=%d\n", __func__, + g_inspection_criteria[IDX_RAWMAX][i], + g_inspection_criteria[IDX_RAWMIN][i]); + ret_val = HX_INSPECT_ERAW; + goto FAIL_END; + } + } + I("%s: rawdata test PASS\n", __func__); + break; + + case HIMAX_INSPECTION_BPN_RAWDATA: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + /* I("Now new compare, datalen=%d!\n", + * ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); + */ + RAW[i] = (int)RAW[i] * 100 / g_dc_max; + if ((int)RAW[i] > g_inspection_criteria[IDX_BPN_RAWMAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_BPN_RAWMIN][i]) { + E("%s: rawdata test FAIL:BPN RAW[%d]=%d\n", __func__, i, RAW[i]); + I("%s: Now Criteria max=%d,min=%d\n", __func__, + g_inspection_criteria[IDX_BPN_RAWMAX][i], + g_inspection_criteria[IDX_BPN_RAWMIN][i]); + ret_val = HX_INSPECT_ERAW; + goto FAIL_END; + } + } + I("%s: BPN rawdata test PASS\n", __func__); + break; + + case HIMAX_INSPECTION_WEIGHT_NOISE: + /*I("NOISEMAX=%d\n", NOISEMAX);*/ + noise_count = 0; + himax_get_noise_base(); + palm_num = himax_get_palm_num(); + for (i = 0; i < (ic_data->HX_TX_NUM * ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > NOISEMAX) + noise_count++; + } + I("noise_count=%d\n", noise_count); + if (noise_count > palm_num) { + E("%s: noise test FAIL\n", __func__); + ret_val = HX_INSPECT_WT_ENOISE; + goto FAIL_END; + } + snprintf(g_start_log, 256 * sizeof(char), "\n Threshold = %d\n", NOISEMAX); + /*Check weightingt*/ + ret = himax_get_noise_weight_test(); + if (ret < 0) { + I("%s: noise test FAIL %d\n", __func__, ret); + ret_val = HX_INSPECT_WT_ENOISE; + goto FAIL_END; + } + + /*Check negative side noise*/ + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > (g_inspection_criteria[IDX_WT_NOISEMAX][i] * g_recal_thx / 100) + || (int)RAW[i] < (g_inspection_criteria[IDX_WT_NOISEMIN][i] * g_recal_thx / 100)) { + E(FAIL_IN_INDEX, __func__, "HIMAX_INSPECTION_WEIGHT_NOISE", i); + ret_val = HX_INSPECT_WT_ENOISE; + goto FAIL_END; + } + } + I("%s: noise test(weight) PASS\n", __func__); + break; + + case HIMAX_INSPECTION_ABS_NOISE: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_ABS_NOISEMAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_ABS_NOISEMIN][i]) { + E(FAIL_IN_INDEX, __func__, "HIMAX_INSPECTION_ABS_NOISE", i); + I("%s: Now Criteria max=%d,min=%d\n", __func__, + g_inspection_criteria[IDX_ABS_NOISEMAX][i], + g_inspection_criteria[IDX_ABS_NOISEMIN][i]); + ret_val = HX_INSPECT_ABS_ENOISE; + goto FAIL_END; + } + } + I("%s: noise test(absolute) PASS\n", __func__); + break; + + case HIMAX_INSPECTION_GAPTEST_RAW: + if (himax_gap_test_vertical_raw(HIMAX_INSPECTION_GAPTEST_RAW, RAW) != NO_ERR) { + E("%s: HIMAX_INSPECTION_GAPTEST_RAW FAIL\n", __func__); + ret_val = HX_INSPECT_EGAP_RAW; + goto FAIL_END; + } + if (himax_gap_test_honrizontal_raw(HIMAX_INSPECTION_GAPTEST_RAW, RAW) != NO_ERR) { + E("%s: HIMAX_INSPECTION_GAPTEST_RAW FAIL\n", __func__); + ret_val = HX_INSPECT_EGAP_RAW; + goto FAIL_END; + } + break; + + case HIMAX_INSPECTION_ACT_IDLE_RAWDATA: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_ACT_IDLE_RAWDATA_MAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_ACT_IDLE_RAWDATA_MIN][i]) { + E(FAIL_IN_INDEX, __func__, "HIMAX_INSPECTION_ACT_IDLE_RAWDATA", i); + ret_val = HX_INSPECT_EACT_IDLE_RAW; + goto FAIL_END; + } + } + I("%s: HIMAX_INSPECTION_ACT_IDLE_RAWDATA PASS\n", __func__); + break; + + case HIMAX_INSPECTION_ACT_IDLE_NOISE: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_ACT_IDLE_NOISE_MAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_ACT_IDLE_NOISE_MIN][i]) { + E(FAIL_IN_INDEX, __func__, "HIMAX_INSPECTION_ACT_IDLE_NOISE", i); + ret_val = HX_INSPECT_EACT_IDLE_NOISE; + goto FAIL_END; + } + } + I("%s: HIMAX_INSPECTION_ACT_IDLE_NOISE PASS\n", __func__); + break; + + case HIMAX_INSPECTION_LPWUG_RAWDATA: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_LPWUG_RAWDATA_MAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_LPWUG_RAWDATA_MIN][i]) { + E(FAIL_IN_INDEX, __func__, "HIMAX_INSPECTION_LPWUG_RAWDATA", i); + ret_val = HX_INSPECT_ELPWUG_RAW; + goto FAIL_END; + } + } + I("%s: HIMAX_INSPECTION_LPWUG_RAWDATA PASS\n", __func__); + break; + + case HIMAX_INSPECTION_LPWUG_NOISE: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_LPWUG_NOISE_MAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_LPWUG_NOISE_MIN][i]) { + E(FAIL_IN_INDEX, __func__, "HIMAX_INSPECTION_LPWUG_NOISE", i); + ret_val = HX_INSPECT_ELPWUG_NOISE; + goto FAIL_END; + } + } + I("%s: HIMAX_INSPECTION_LPWUG_NOISE PASS\n", __func__); + break; + + case HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_LPWUG_IDLE_RAWDATA_MAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_LPWUG_IDLE_RAWDATA_MIN][i]) { + E(FAIL_IN_INDEX, __func__, "HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA", i); + ret_val = HX_INSPECT_ELPWUG_IDLE_RAW; + goto FAIL_END; + } + } + I("%s: HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA PASS\n", __func__); + break; + + case HIMAX_INSPECTION_LPWUG_IDLE_NOISE: + for (i = 0; i < (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM); i++) { + if ((int)RAW[i] > g_inspection_criteria[IDX_LPWUG_IDLE_NOISE_MAX][i] + || (int)RAW[i] < g_inspection_criteria[IDX_LPWUG_IDLE_NOISE_MIN][i]) { + E(FAIL_IN_INDEX, __func__, "HIMAX_INSPECTION_LPWUG_IDLE_NOISE", i); + ret_val = HX_INSPECT_ELPWUG_IDLE_NOISE; + goto FAIL_END; + } + } + I("%s: HIMAX_INSPECTION_LPWUG_IDLE_NOISE PASS\n", __func__); + break; + + default: + E("Wrong type=%d\n", checktype); + ret_val = 0xFFFFFFFF; + break; + } + + ret_val = HX_INSPECT_OK; + snprintf(g_rslt_log, 256 * sizeof(char), "\n%s%s\n", + g_himax_inspection_mode[checktype], " Test Pass!\n"); + I("pass write log\n"); + goto END_FUNC; + +FAIL_END: + snprintf(g_rslt_log, 256 * sizeof(char), "\n%s%s\n", + g_himax_inspection_mode[checktype], " Test Fail!\n"); + I("fail write log\n"); +END_FUNC: + hx_test_data_get(RAW, g_start_log, g_rslt_log, checktype); + kfree(RAW); + + return ret_val; +} + +/* claculate 10's power function */ +static int himax_power_cal(int pow, int number) +{ + int i = 0; + int result = 1; + + for (i = 0; i < pow; i++) + result *= 10; + result = result * number; + + return result; + +} + +/* String to int */ +static int hiamx_parse_str2int(char *str) +{ + int i = 0; + int temp_cal = 0; + int result = 0; + int str_len = strlen(str); + int negtive_flag = 0; + + for (i = 0; i < strlen(str); i++) { + 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); + /* 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; +} + + +/* Get sub-string from original string by using some charaters + * return size of result + */ +static int himax_saperate_comma(const struct firmware *file_entry, + char **result, int str_size) +{ + int count = 0; + int str_count = 0; /* now string*/ + int char_count = 0; /* now char count in string*/ + + do { + switch (file_entry->data[count]) { + case ASCII_COMMA: + case ACSII_SPACE: + case ASCII_CR: + case ASCII_LF: + count++; + /* If end of line as above condifiton, + * differencing the count of char. + * If char_count != 0 + * it's meaning this string is parsing over . + * The Next char is belong to next string + */ + if (char_count != 0) { + char_count = 0; + str_count++; + } + break; + default: + result[str_count][char_count++] = + file_entry->data[count]; + count++; + break; + } + } while (count < file_entry->size && str_count < str_size); + + return str_count; +} + +static int hx_diff_str(char *str1, char *str2) +{ + int i = 0; + int result = 0; /* zero is all same, non-zero is not same index*/ + int str1_len = strlen(str1); + int str2_len = strlen(str2); + + if (str1_len != str2_len) { + if (private_ts->debug_log_level & BIT(4)) + I("%s:Size different!\n", __func__); + return LENGTH_FAIL; + } + + for (i = 0; i < str1_len; i++) { + if (str1[i] != str2[i]) { + result = i+1; + I("%s: different in %d!\n", __func__, result); + return result; + } + } + + return result; +} + +/* get idx of criteria whe parsing file */ +int hx_find_crtra_id(char *input) +{ + int i = 0; + int result = 0; + + for (i = 0 ; i < HX_CRITERIA_SIZE ; i++) { + if (hx_diff_str(g_hx_inspt_crtra_name[i], input) == 0) { + result = i; + I("find the str=%s,idx=%d\n", + g_hx_inspt_crtra_name[i], i); + break; + } + } + if (i > (HX_CRITERIA_SIZE - 1)) { + E("%s: find Fail!\n", __func__); + return LENGTH_FAIL; + } + + return result; +} + +int hx_print_crtra_after_parsing(void) +{ + int i = 0, j = 0; + int all_mut_len = ic_data->HX_TX_NUM*ic_data->HX_RX_NUM; + + for (i = 0; i < HX_CRITERIA_SIZE; i++) { + I("Now is %s\n", g_hx_inspt_crtra_name[i]); + if (g_inspt_crtra_flag[i] == 1) { + for (j = 0; j < all_mut_len; j++) { + I("%d, ", g_inspection_criteria[i][j]); + if (j % 16 == 15) + PI("\n"); + } + } else { + I("No this Item in this criteria file!\n"); + } + PI("\n"); + } + + return 0; +} + +static int hx_get_crtra_by_name(char **result, int size_of_result_str) +{ + int i = 0; + /* count of criteria type */ + int count_type = 0; + /* count of criteria data */ + int count_data = 0; + int err = HX_INSPECT_OK; + int all_mut_len = ic_data->HX_TX_NUM*ic_data->HX_RX_NUM; + int temp = 0; + + /* get criteria and assign to a global array(2-Dimensional/int) */ + /* basiclly the size of criteria will be + * (crtra_count * (all_mut_len) + crtra_count) + * but we use file size to be the end of counter + */ + for (i = 0; i < size_of_result_str && result[i] != NULL; i++) { + /* It have get one page(all mutual) criteria data! + * And we should skip the string of criteria name! + */ + if (i == 0 || i == + ((i / (all_mut_len))+(i / (all_mut_len) * (all_mut_len)))) { + count_data = 0; + + if (private_ts->debug_log_level & BIT(4)) + I("Now find str=%s ,idx=%d\n", result[i], i); + + /* check the item of criteria is in criteria file + * or not + */ + count_type = hx_find_crtra_id(result[i]); + if (count_type < 0) { + E("1. %s:Name Not match!\n", __func__); + /* E("can recognize[%d]=%s\n", count_type, + * g_hx_inspt_crtra_name[count_type]); + */ + E("get from file[%d]=%s\n", i, result[i]); + E("Please check criteria file again!\n"); + err = HX_INSPECT_EFILE; + goto END_FUNCTION; + } else { + I("Now str=%s, idx=%d\n", + g_hx_inspt_crtra_name[count_type], count_type); + g_inspt_crtra_flag[count_type] = 1; + } + continue; + } + /* change string to int*/ + temp = hiamx_parse_str2int(result[i]); + if (temp != -9487) + g_inspection_criteria[count_type][count_data] = temp; + else { + E("%s: Parsing Fail in %d\n", __func__, i); + E("in range:[%d]=%s\n", count_type, + g_hx_inspt_crtra_name[count_type]); + E("btw, get from file[%d]=%s\n", i, result[i]); + break; + } + /* dbg + * I("[%d]g_inspection_criteria[%d][%d]=%d\n", + * i, count_type, count_data, + * g_inspection_criteria[count_type][count_data]); + */ + count_data++; + + } + + if (private_ts->debug_log_level & BIT(4)) { + /* dbg:print all of criteria from parsing file */ + hx_print_crtra_after_parsing(); + } + + I("Total loop=%d\n", i); +END_FUNCTION: + return err; +} + +static int himax_parse_criteria_file(void) +{ + int err = HX_INSPECT_OK; + const struct firmware *file_entry = NULL; + char **result; + int i = 0; + int crtra_count = HX_CRITERIA_SIZE; + int data_size = 0; /* The maximum of number Data*/ + int all_mut_len = ic_data->HX_TX_NUM*ic_data->HX_RX_NUM; + int str_max_len = 128; + int result_all_len = 0; + int file_size = 0; + int size_of_result_str = 0; + + I("%s,Entering\n", __func__); + if (hx_self_test_file_name == NULL) { + E("file name is NULL\n"); + hx_self_test_file_name = kzalloc(80, GFP_KERNEL); + if (private_ts->pdata->panel_supplier[0]) + snprintf(hx_self_test_file_name, 60, "%s_hx_criteria.csv", private_ts->pdata->panel_supplier); + else + snprintf(hx_self_test_file_name, 16, "hx_criteria.csv"); + I("%s: Use name %s\n", __func__, hx_self_test_file_name); + } + + I("file name = %s\n", hx_self_test_file_name); + /* default path is /system/etc/firmware */ + err = request_firmware(&file_entry, hx_self_test_file_name, private_ts->dev); + if (err < 0) { + E("%s,fail in line%d error code=%d\n", __func__, __LINE__, err); + err = HX_INSPECT_EFILE; + goto END_FUNC_REQ_FAIL; + } + + /* size of criteria include name string */ + data_size = ((all_mut_len) * crtra_count) + crtra_count; + + /* init the array which store original criteria and include + * name string + */ + result = kcalloc(data_size, sizeof(char *), GFP_KERNEL); + if (result != NULL) { + for (i = 0 ; i < data_size; i++) { + result[i] = kcalloc(str_max_len, sizeof(char), GFP_KERNEL); + if (result[i] == NULL) { + E("%s: rst_arr Memory allocation falied!\n", __func__); + err = HX_INSPECT_MEMALLCTFAIL; + goto rst_arr_mem_alloc_failed; + } + } + } else { + E("%s: Memory allocation falied!\n", __func__); + err = HX_INSPECT_MEMALLCTFAIL; + goto rst_mem_alloc_failed; + } + + result_all_len = data_size; + file_size = file_entry->size; + I("Now result_all_len=%d\n", result_all_len); + I("Now file_size=%d\n", file_size); + + /* dbg */ + if (private_ts->debug_log_level & BIT(4)) { + I("first 4 bytes 0x%2X,0x%2X,0x%2X,0x%2X !\n", + file_entry->data[0], file_entry->data[1], + file_entry->data[2], file_entry->data[3]); + } + + /* parse value in to result array(1-Dimensional/String) */ + size_of_result_str = + himax_saperate_comma(file_entry, result, data_size); + + I("%s: now size_of_result_str=%d\n", __func__, size_of_result_str); + + err = hx_get_crtra_by_name(result, size_of_result_str); + if (err != HX_INSPECT_OK) { + E("%s:Load criteria from file fail, go end!\n", __func__); + goto END_FUNC; + } + + +END_FUNC: +rst_arr_mem_alloc_failed: + for (i = 0 ; i < data_size; i++) + if (result[i] != NULL) + kfree(result[i]); +rst_mem_alloc_failed: + kfree(result); + release_firmware(file_entry); +END_FUNC_REQ_FAIL: + I("%s,END\n", __func__); + return err; + /* parsing Criteria end */ +} + + +int hx_get_size_str_arr(char **input) +{ + int i = 0; + int result = 0; + + while (input[i] != NULL) + i++; + + result = i; + if (private_ts->debug_log_level & BIT(4)) + I("There is %d in [0]=%s\n", result, input[0]); + + return result; +} + +static int himax_self_test_data_init(void) +{ + int ret = HX_INSPECT_OK; + int i = 0; + + /* + * 5: one value will not over than 99999, so get this size of string + * 2: get twice size + */ + g_1kind_raw_size = 5 * ic_data->HX_RX_NUM * ic_data->HX_RX_NUM * 2; + + /* get test item and its items of criteria*/ + HX_CRITERIA_ITEM = hx_get_size_str_arr(g_himax_inspection_mode); + HX_CRITERIA_SIZE = hx_get_size_str_arr(g_hx_inspt_crtra_name); + I("There is %d HX_CRITERIA_ITEM and %d HX_CRITERIA_SIZE\n", + HX_CRITERIA_ITEM, HX_CRITERIA_SIZE); + + /* init criteria data*/ + g_inspt_crtra_flag = kzalloc(HX_CRITERIA_SIZE*sizeof(int), GFP_KERNEL); + g_inspection_criteria = kzalloc(sizeof(int *)*HX_CRITERIA_SIZE, GFP_KERNEL); + if (g_inspt_crtra_flag == NULL || g_inspection_criteria == NULL) { + E("%s: %d, Memory allocation falied!\n", __func__, __LINE__); + return MEM_ALLOC_FAIL; + } + + for (i = 0; i < HX_CRITERIA_SIZE; i++) { + g_inspection_criteria[i] = kcalloc( + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM), sizeof(int), GFP_KERNEL); + if (g_inspection_criteria[i] == NULL) { + E("%s: %d, Memory allocation falied!\n", __func__, __LINE__); + return MEM_ALLOC_FAIL; + } + } + + /* parsing criteria from file*/ + ret = himax_parse_criteria_file(); + + if (private_ts->debug_log_level & BIT(4)) { + /* print get criteria string */ + for (i = 0 ; i < HX_CRITERIA_SIZE ; i++) { + if (g_inspt_crtra_flag[i] != 0) + I("%s: [%d]There is String=%s\n", + __func__, i, g_hx_inspt_crtra_name[i]); + } + } + + if (g_rslt_data == NULL) { + g_rslt_data = kcalloc(g_1kind_raw_size * HX_CRITERIA_ITEM, + sizeof(char), GFP_KERNEL); + I("g_rslt_data is NULL"); + } else { + memset(g_rslt_data, 0x00, g_1kind_raw_size * HX_CRITERIA_ITEM * + sizeof(char)); + } + + 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 ret; +} + +static void himax_self_test_data_deinit(void) +{ + int i = 0; + + /*dbg*/ + /* for (i = 0; i < HX_CRITERIA_ITEM; i++) + * I("%s:[%d]%d\n", __func__, i, g_inspection_criteria[i]); + */ + if (g_inspection_criteria != NULL) { + for (i = 0; i < HX_CRITERIA_SIZE; i++) { + if (g_inspection_criteria[i] != NULL) + kfree(g_inspection_criteria[i]); + } + kfree(g_inspection_criteria); + I("Now it have free the g_inspection_criteria!\n"); + } else { + I("No Need to free g_inspection_criteria!\n"); + } + + g_rslt_data_len = 0; + +} + +static int himax_chip_self_test(void) +{ + uint32_t ret = HX_INSPECT_OK; + uint8_t tmp_addr[DATA_LEN_4] = {0x94, 0x72, 0x00, 0x10}; + uint8_t tmp_data[DATA_LEN_4] = {0x01, 0x00, 0x00, 0x00}; + +#if defined(HIMAX_V2_MULTI_BIN)||defined(HX_CODE_OVERLAY) + uint8_t normalfw[32] = "Himax_firmware.bin"; + uint8_t mpapfw[32] = "Himax_mpfw.bin"; + if (private_ts->pdata->panel_supplier[0]) { + snprintf(normalfw, 32, "%s_Himax_firmware.bin", private_ts->pdata->panel_supplier); + snprintf(mpapfw, 32, "%s_Himax_mpfw.bin", private_ts->pdata->panel_supplier); + } +#endif + + I("%s:IN\n", __func__); + + private_ts->suspend_resume_done = 0; + + ret = himax_self_test_data_init(); + if (ret != HX_INSPECT_OK) { + E("%s: himax_self_test_data_init fail!\n", __func__); + goto END_FUNC; + } + +#if defined(HIMAX_V2_MULTI_BIN)||defined(HX_CODE_OVERLAY) + g_core_fp.fp_0f_op_file_dirly(mpapfw); + g_core_fp.fp_reload_disable(0); + g_core_fp.fp_sense_on(0x00); +#endif + + if (g_inspt_crtra_flag[IDX_OPENMIN] == 1 && + g_inspt_crtra_flag[IDX_OPENMAX] == 1) { + /*1. Open Test*/ + I("[MP_OPEN_TEST_RAW]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_OPEN, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("1. Open Test: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_OPENMIN], + g_inspt_crtra_flag[IDX_OPENMIN]); + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_OPENMAX], + g_inspt_crtra_flag[IDX_OPENMAX]); + } + + if (g_inspt_crtra_flag[IDX_M_OPENMIN] == 1 && + g_inspt_crtra_flag[IDX_M_OPENMAX] == 1) { + /*2. Micro-Open Test*/ + I("[MP_MICRO_OPEN_TEST_RAW]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_MICRO_OPEN, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("2. Micro Open Test: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_M_OPENMIN], + g_inspt_crtra_flag[IDX_M_OPENMIN]); + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_M_OPENMAX], + g_inspt_crtra_flag[IDX_M_OPENMAX]); + } + + if (g_inspt_crtra_flag[IDX_SHORTMIN] == 1 && + g_inspt_crtra_flag[IDX_SHORTMAX] == 1) { + /*3. Short Test*/ + I("[MP_SHORT_TEST_RAW]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_SHORT, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("3. Short Test: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_SHORTMIN], + g_inspt_crtra_flag[IDX_SHORTMIN]); + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_SHORTMAX], + g_inspt_crtra_flag[IDX_SHORTMAX]); + } + + if (g_inspt_crtra_flag[IDX_RAWMIN] == 1 && + g_inspt_crtra_flag[IDX_RAWMAX] == 1) { + /*4. RawData Test*/ + I("==========================================\n"); + I("[MP_RAW_TEST_RAW]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_RAWDATA, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("%d. %s: End %d\n\n\n", HIMAX_INSPECTION_RAWDATA, + g_himax_inspection_mode[HIMAX_INSPECTION_RAWDATA], ret); + } else { + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_RAWMIN], + g_inspt_crtra_flag[IDX_RAWMIN]); + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_RAWMAX], + g_inspt_crtra_flag[IDX_RAWMAX]); + } + + if (g_inspt_crtra_flag[IDX_BPN_RAWMIN] == 1 && + g_inspt_crtra_flag[IDX_BPN_RAWMAX] == 1) { + /*4. RawData BPN Test*/ + I("==========================================\n"); + I("[MP_BPN_RAW_TEST_RAW]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_BPN_RAWDATA, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("%d. %s: End %d\n\n\n", HIMAX_INSPECTION_BPN_RAWDATA, + g_himax_inspection_mode[HIMAX_INSPECTION_BPN_RAWDATA], ret); + } else { + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_BPN_RAWMIN], + g_inspt_crtra_flag[IDX_BPN_RAWMIN]); + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_BPN_RAWMAX], + g_inspt_crtra_flag[IDX_BPN_RAWMAX]); + } + + if (g_inspt_crtra_flag[IDX_WT_NOISEMIN] == 1 && + g_inspt_crtra_flag[IDX_WT_NOISEMAX] == 1) { + /*5. Noise Test by Weighting*/ + I("[MP_NOISE_TEST_WEIGHT]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_WEIGHT_NOISE, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("5. Noise Test: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_WT_NOISEMAX], + g_inspt_crtra_flag[IDX_WT_NOISEMAX]); + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_WT_NOISEMIN], + g_inspt_crtra_flag[IDX_WT_NOISEMIN]); + } + + if (g_inspt_crtra_flag[IDX_ABS_NOISEMIN] == 1 && + g_inspt_crtra_flag[IDX_ABS_NOISEMAX] == 1) { + /*5. Noise Test by per block*/ + I("[MP_NOISE_TEST_ABS]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_ABS_NOISE, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("5. Noise Test: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_ABS_NOISEMAX], + g_inspt_crtra_flag[IDX_ABS_NOISEMAX]); + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_ABS_NOISEMIN], + g_inspt_crtra_flag[IDX_ABS_NOISEMIN]); + } + + if (g_inspt_crtra_flag[IDX_SORTMIN] == 1 && + g_inspt_crtra_flag[IDX_SORTMAX] == 1) { + /*6. Sorting Test*/ + I("[SORTING TEST]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_SORTING, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("6. SORTING TEST: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_SORTMIN], + g_inspt_crtra_flag[IDX_SORTMIN]); + I("Now %s :flag=%d\n", g_hx_inspt_crtra_name[IDX_SORTMAX], + g_inspt_crtra_flag[IDX_SORTMAX]); + } + + if ((g_inspt_crtra_flag[IDX_GAP_HOR_RAWMAX] == 1 && + g_inspt_crtra_flag[IDX_GAP_HOR_RAWMIN] == 1) && + (g_inspt_crtra_flag[IDX_GAP_VER_RAWMAX] == 1 && + g_inspt_crtra_flag[IDX_GAP_VER_RAWMIN] == 1)) { + /*6. GAP Test*/ + I("[MP_GAP_TEST_RAW]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_GAPTEST_RAW, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("6. MP_GAP_TEST_RAW: End %d\n\n\n", ret); + } else { + I("Now %s : HOR flag=%d\n", + g_hx_inspt_crtra_name[IDX_GAP_HOR_RAWMAX], + g_inspt_crtra_flag[IDX_GAP_HOR_RAWMAX]); + I("Now %s : HOR flag=%d\n", + g_hx_inspt_crtra_name[IDX_GAP_HOR_RAWMIN], + g_inspt_crtra_flag[IDX_GAP_HOR_RAWMIN]); + I("Now %s : VERTICAL flag=%d\n", + g_hx_inspt_crtra_name[IDX_GAP_VER_RAWMAX], + g_inspt_crtra_flag[IDX_GAP_VER_RAWMAX]); + I("Now %s : VERTICAL flag=%d\n", + g_hx_inspt_crtra_name[IDX_GAP_VER_RAWMIN], + g_inspt_crtra_flag[IDX_GAP_VER_RAWMIN]); + } + + if (g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MIN] == 1 && + g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MAX] == 1) { + /*7. ACT_IDLE RAWDATA*/ + I("[MP_ACT_IDLE_TEST_RAW]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_ACT_IDLE_RAWDATA, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("7. MP_ACT_IDLE_TEST_RAW: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_ACT_IDLE_RAWDATA_MAX], + g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MAX]); + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_ACT_IDLE_RAWDATA_MIN], + g_inspt_crtra_flag[IDX_ACT_IDLE_RAWDATA_MIN]); + } + + if (g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MIN] == 1 && + g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MAX] == 1) { + /*8. ACT_IDLE NOISE*/ + I("[MP_ACT_IDLE_TEST_NOISE]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_ACT_IDLE_NOISE, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("8. MP_ACT_IDLE_TEST_NOISE: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_ACT_IDLE_NOISE_MAX], + g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MAX]); + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_ACT_IDLE_NOISE_MIN], + g_inspt_crtra_flag[IDX_ACT_IDLE_NOISE_MIN]); + } + + /* check press power key or not for LPWUG test item*/ + if ((g_inspt_crtra_flag[IDX_LPWUG_NOISE_MAX] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_NOISE_MIN] == 1) || + (g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MAX] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MIN] == 1) || + (g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MAX] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MIN] == 1) || + (g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MAX] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MIN] == 1) + ) + himax_press_powerkey(); + +/* Workaround delete */ +#if 0 + /* Wait suspend done */ + while (private_ts->suspend_resume_done != 1) + usleep_range(1000, 1001); + + private_ts->suspend_resume_done = 0; +#endif + + if (g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MIN] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MAX] == 1) { + /*9. LPWUG RAWDATA*/ + I("[MP_LPWUG_TEST_RAW]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_LPWUG_RAWDATA, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("9. MP_LPWUG_TEST_RAW: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_LPWUG_RAWDATA_MIN], + g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MIN]); + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_LPWUG_RAWDATA_MAX], + g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MAX]); + } + + if (g_inspt_crtra_flag[IDX_LPWUG_NOISE_MAX] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_NOISE_MIN] == 1) { + /*10. LPWUG NOISE*/ + I("[MP_LPWUG_TEST_NOISE]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_LPWUG_NOISE, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("10. MP_LPWUG_TEST_NOISE: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_LPWUG_NOISE_MAX], + g_inspt_crtra_flag[IDX_LPWUG_NOISE_MAX]); + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_LPWUG_NOISE_MIN], + g_inspt_crtra_flag[IDX_LPWUG_NOISE_MIN]); + } + + if (g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MIN] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MAX] == 1) { + /*11. LPWUG IDLE RAWDATA*/ + I("[MP_LPWUG_IDLE_TEST_RAW]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("11. MP_LPWUG_IDLE_TEST_RAW: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_LPWUG_IDLE_RAWDATA_MIN], + g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MIN]); + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_LPWUG_IDLE_RAWDATA_MAX], + g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MAX]); + } + + if (g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MIN] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MAX] == 1) { + /*12. LPWUG IDLE RAWDATA*/ + I("[MP_LPWUG_IDLE_TEST_NOISE]\n"); + ret |= mpTestFunc(HIMAX_INSPECTION_LPWUG_IDLE_NOISE, + (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM) + ic_data->HX_TX_NUM + + ic_data->HX_RX_NUM); + I("12. MP_LPWUG_IDLE_TEST_NOISE: End %d\n\n\n", ret); + } else { + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_LPWUG_IDLE_NOISE_MIN], + g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MIN]); + I("Now %s :flag=%d\n", + g_hx_inspt_crtra_name[IDX_LPWUG_IDLE_NOISE_MAX], + g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MAX]); + } + + /* check press power key or not for LPWUG test item*/ + if ((g_inspt_crtra_flag[IDX_LPWUG_NOISE_MAX] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_NOISE_MIN] == 1) || + (g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MAX] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_RAWDATA_MIN] == 1) || + (g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MAX] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_IDLE_NOISE_MIN] == 1) || + (g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MAX] == 1 && + g_inspt_crtra_flag[IDX_LPWUG_IDLE_RAWDATA_MIN] == 1) + ) + himax_press_powerkey(); + + hx_test_data_pop_out(g_rslt_data, g_file_path); + +/* Workaround delete */ +#if 0 + /* Wait resume done */ + while (private_ts->suspend_resume_done != 1) + usleep_range(1000, 1001); +#endif + +#if defined(HIMAX_V2_MULTI_BIN)||defined(HX_CODE_OVERLAY) + private_ts->in_self_test = 0; + g_core_fp.fp_0f_op_file_dirly(normalfw); + hx_turn_on_mp_func(0); + /* set N frame back to default value 1*/ + g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); + g_core_fp.fp_reload_disable(0); + g_core_fp.fp_sense_on(0); +#else + g_core_fp.fp_sense_off(true); + hx_turn_on_mp_func(0); + /*himax_set_N_frame(1, HIMAX_INSPECTION_WEIGHT_NOISE);*/ + /* set N frame back to default value 1*/ + g_core_fp.fp_register_write(tmp_addr, 4, tmp_data, 0); +#ifndef HX_ZERO_FLASH + if (g_core_fp.fp_reload_disable != NULL) + g_core_fp.fp_reload_disable(0); +#endif + g_core_fp.fp_sense_on(0); +#endif + +END_FUNC: + himax_self_test_data_deinit(); + + + I("running status = %d\n", ret); + + /*if (ret != 0)*/ + /*ret = 1;*/ + + I("%s:OUT\n", __func__); + return ret; +} + +void himax_inspect_data_clear(void) +{ + if (!g_rslt_data) { + kfree(g_rslt_data); + g_rslt_data = NULL; + } +} + +void himax_inspection_init(void) +{ + I("%s: enter, %d\n", __func__, __LINE__); + + g_core_fp.fp_chip_self_test = himax_chip_self_test; +} diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_inspection.h b/drivers/input/touchscreen/himax_v3_mmi/himax_inspection.h index e504824de3a4..6b0f5dbfb46d 100644 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_inspection.h +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_inspection.h @@ -1,292 +1,211 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for inspection functions - * - * 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_platform.h" -#include "himax_common.h" -#include "himax_ic_core.h" - -/*#define HX_GAP_TEST*/ -/*#define HX_INSP_LP_TEST*/ -/*#define HX_ACT_IDLE_TEST*/ - -#define HX_RSLT_OUT_PATH "/sdcard/" -#define HX_RSLT_OUT_FILE "hx_test_result.txt" -#define PI(x...) pr_cont(x) -#define HX_SZ_ICID 60 - -#if defined(HX_ESD_RECOVERY) -extern u8 HX_ESD_RESET_ACTIVATE; -#endif - -#define BS_RAWDATA 10 -#define BS_NOISE 10 -#define BS_OPENSHORT 0 -#define BS_LPWUG 1 -#define BS_LP_dile 1 -#define BS_ACT_IDLE 1 - -/* skip notch & dummy */ -#define SKIP_NOTCH_START 5 -#define SKIP_NOTCH_END 10 -/* TX+SKIP_NOTCH_START */ -#define SKIP_DUMMY_START 23 -/* TX+SKIP_NOTCH_END*/ -#define SKIP_DUMMY_END 28 - - -#define NOISEFRAME (BS_NOISE+1) -#define NORMAL_IDLE_RAWDATA_NOISEFRAME 10 -#define LP_RAWDATAFRAME 1 -#define LP_NOISEFRAME 1 -#define LP_IDLE_RAWDATAFRAME 1 -#define LP_IDLE_NOISEFRAME 1 - -#define OTHERSFRAME 2 - -#define UNIFMAX 500 - - -/*Himax MP Password*/ -#define PWD_OPEN_START 0x77 -#define PWD_OPEN_END 0x88 -#define PWD_SHORT_START 0x11 -#define PWD_SHORT_END 0x33 -#define PWD_RAWDATA_START 0x00 -#define PWD_RAWDATA_END 0x99 -#define PWD_NOISE_START 0x00 -#define PWD_NOISE_END 0x99 -#define PWD_SORTING_START 0xAA -#define PWD_SORTING_END 0xCC - - -#define PWD_ACT_IDLE_START 0x22 -#define PWD_ACT_IDLE_END 0x44 - - - -#define PWD_LP_START 0x55 -#define PWD_LP_END 0x66 - -#define PWD_LP_IDLE_START 0x50 -#define PWD_LP_IDLE_END 0x60 - -#define PWD_TURN_ON_MPAP_OVL 0x107380 - -/*Himax DataType*/ -#define DATA_SORTING 0x0A -#define DATA_OPEN 0x0B -#define DATA_MICRO_OPEN 0x0C -#define DATA_SHORT 0x0A -#define DATA_RAWDATA 0x0A -#define DATA_NOISE 0x0F -#define DATA_BACK_NORMAL 0x00 -#define DATA_LP_RAWDATA 0x0C -#define DATA_LP_NOISE 0x0F -#define DATA_ACT_IDLE_RAWDATA 0x0A -#define DATA_ACT_IDLE_NOISE 0x0F -#define DATA_LP_IDLE_RAWDATA 0x0A -#define DATA_LP_IDLE_NOISE 0x0F - -/*Himax Data Ready Password*/ -#define Data_PWD0 0xA5 -#define Data_PWD1 0x5A - -/* ASCII format */ -#define ASCII_LF (0x0A) -#define ASCII_CR (0x0D) -#define ASCII_COMMA (0x2C) -#define ASCII_ZERO (0x30) -#define CHAR_EL '\0' -#define CHAR_NL '\n' -#define ACSII_SPACE (0x20) -/* INSOECTION Setting */ - -void himax_inspection_init(void); -extern int *g_test_item_flag; -extern int HX_CRITERIA_ITEM; -extern int *g_test_item_flag; -extern char *g_himax_inspection_mode[]; - -/*Inspection register*/ -#define addr_normal_noise_thx 0x1000708C -#define addr_lpwug_noise_thx 0x10007090 -#define addr_recal_thx 0x10007090 -#define addr_palm_num 0x100070A8 -#define addr_weight_sup 0x100072C8 -#define addr_normal_weight_a 0x1000709C -#define addr_lpwug_weight_a 0x100070A0 -#define addr_weight_b 0x10007094 -#define addr_max_dc 0x10007FC8 -#define addr_skip_frame 0x100070F4 -#define addr_neg_noise_sup 0x10007FD8 -#define data_neg_noise 0x7F0C0000 -#define addr_ctrl_mpap_ovl 0x100073EC - -/*Need to map *g_himax_inspection_mode[]*/ -enum THP_INSPECTION_ENUM { - HX_OPEN, - HX_MICRO_OPEN, - HX_SHORT, - HX_RAWDATA, - HX_BPN_RAWDATA, - HX_SC, - HX_WT_NOISE, - HX_ABS_NOISE, - HX_SORTING, - - HX_GAPTEST_RAW, - /*HX_GAPTEST_RAW_X,*/ - /*HX_GAPTEST_RAW_Y,*/ - - HX_ACT_IDLE_RAWDATA, - HX_ACT_IDLE_BPN_RAWDATA, - HX_ACT_IDLE_NOISE, -/*LPWUG test must put after Normal test*/ - HX_LP_RAWDATA, - HX_LP_BPN_RAWDATA, - HX_LP_WT_NOISE, - HX_LP_ABS_NOISE, - HX_LP_IDLE_RAWDATA, - HX_LP_IDLE_BPN_RAWDATA, - HX_LP_IDLE_NOISE, - - HX_BACK_NORMAL,/*Must put in the end*/ -}; - - -enum HX_CRITERIA_ENUM { - IDX_RAWMIN = 0, - IDX_RAWMAX, - IDX_BPN_RAWMIN, - IDX_BPN_RAWMAX, - IDX_SCMIN, - IDX_SCMAX, - IDX_SC_GOLDEN, - IDX_SHORTMIN, - IDX_SHORTMAX, - IDX_OPENMIN, - IDX_OPENMAX, - IDX_M_OPENMIN, - IDX_M_OPENMAX, - IDX_WT_NOISEMIN, - IDX_WT_NOISEMAX, - IDX_ABS_NOISEMIN, - IDX_ABS_NOISEMAX, - IDX_SORTMIN, - IDX_SORTMAX, - - IDX_GAP_HOR_RAWMAX, - IDX_GAP_HOR_RAWMIN, - IDX_GAP_VER_RAWMAX, - IDX_GAP_VER_RAWMIN, - - IDX_ACT_IDLE_NOISE_MIN, - IDX_ACT_IDLE_NOISE_MAX, - IDX_ACT_IDLE_RAWDATA_MIN, - IDX_ACT_IDLE_RAWDATA_MAX, - IDX_ACT_IDLE_RAW_BPN_MIN, - IDX_ACT_IDLE_RAW_BPN_MAX, - - IDX_LP_WT_NOISEMIN, - IDX_LP_WT_NOISEMAX, - IDX_LP_NOISE_ABS_MIN, - IDX_LP_NOISE_ABS_MAX, - IDX_LP_RAWDATA_MIN, - IDX_LP_RAWDATA_MAX, - IDX_LP_RAW_BPN_MIN, - IDX_LP_RAW_BPN_MAX, - - IDX_LP_IDLE_NOISE_MIN, - IDX_LP_IDLE_NOISE_MAX, - IDX_LP_IDLE_RAWDATA_MIN, - IDX_LP_IDLE_RAWDATA_MAX, - IDX_LP_IDLE_RAW_BPN_MIN, - IDX_LP_IDLE_RAW_BPN_MAX, -}; - -#define ERR_SFT 4 -/* Error code of Inspection */ -enum HX_INSP_ERR_ENUM { - /* OK */ - HX_INSP_OK = 0, - - /* Criteria file error*/ - HX_INSP_EFILE = 1, - - /* Get raw data errors */ - HX_INSP_EGETRAW = 1 << 1, - - /* Memory allocate errors */ - HX_INSP_MEMALLCTFAIL = 1 << 2, - - /* Switch mode error*/ - HX_INSP_ESWITCHMODE = 1 << 3, - - /* Sensor open error */ - HX_EOPEN = 1 << (HX_OPEN + ERR_SFT), - - /* Sensor micro open error */ - HX_EMOPEN = 1 << (HX_MICRO_OPEN + ERR_SFT), - - /* Sensor short error */ - HX_ESHORT = 1 << (HX_SHORT + ERR_SFT), - - /* Raw data error */ - HX_ERAW = 1 << (HX_RAWDATA + ERR_SFT), - - /* Raw data BPN error */ - HX_EBPNRAW = 1 << (HX_BPN_RAWDATA + ERR_SFT), - - /* Get SC errors */ - HX_ESC = 1 << (HX_SC + ERR_SFT), - - /* Noise error */ - HX_WT_ENOISE = 1 << (HX_WT_NOISE + ERR_SFT), - - /* Noise error */ - HX_ABS_ENOISE = 1 << (HX_ABS_NOISE + ERR_SFT), - - /* Sorting error*/ - HX_ESORT = 1 << (HX_SORTING + ERR_SFT), - - /* Raw Data GAP */ - HX_EGAP_RAW = 1 << (HX_GAPTEST_RAW + ERR_SFT), - - /* ACT_IDLE RAW ERROR */ - HX_EACT_IDLE_RAW = 1 << (HX_ACT_IDLE_RAWDATA + ERR_SFT), - - /* ACT_IDLE NOISE ERROR */ - HX_EACT_IDLE_NOISE = 1 << (HX_ACT_IDLE_NOISE + ERR_SFT), - - /* LPWUG RAW ERROR */ - HX_ELP_RAW = 1 << (HX_LP_RAWDATA + ERR_SFT), - - /* LPWUG NOISE ERROR */ - HX_ELP_WT_NOISE = 1 << (HX_LP_WT_NOISE + ERR_SFT), - - /* LPWUG NOISE ERROR */ - HX_ELP_ABS_NOISE = 1 << (HX_LP_ABS_NOISE + ERR_SFT), - - /* LPWUG IDLE RAW ERROR */ - HX_ELP_IDLE_RAW = 1 << (HX_LP_IDLE_RAWDATA + ERR_SFT), - - /* LPWUG IDLE NOISE ERROR */ - HX_ELP_IDLE_NOISE = 1 << (HX_LP_IDLE_NOISE + ERR_SFT), - HX_EACT_IDLE_BPNRAW = 1 << (HX_ACT_IDLE_BPN_RAWDATA + ERR_SFT), - HX_ELP_BPNRAW = 1 << (HX_LP_BPN_RAWDATA + ERR_SFT), - HX_ELP_IDLE_BPNRAW = 1 << (HX_LP_IDLE_BPN_RAWDATA + ERR_SFT), -}; - -extern void himax_inspect_data_clear(void); +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for inspection functions + * + * 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_platform.h" +#include "himax_common.h" +#include "himax_ic_core.h" + +/*#define HX_GAP_TEST*/ +/*#define HX_INSPECT_LPWUG_TEST*/ +/*#define HX_ACT_IDLE_TEST*/ + +#define HX_RSLT_OUT_PATH "/sdcard/" +#define HX_RSLT_OUT_FILE "hx_test_result.txt" +#define PI(x...) pr_info(x) + +#ifdef HX_ESD_RECOVERY + extern u8 HX_ESD_RESET_ACTIVATE; +#endif + +#define BS_RAWDATA 10 +#define BS_NOISE 10 +#define BS_OPENSHORT 0 +#define BS_LPWUG 1 +#define BS_LPWUG_dile 1 +#define BS_ACT_IDLE 1 + +/* skip notch & dummy */ +#define SKIP_NOTCH_START 5 +#define SKIP_NOTCH_END 10 +/* TX+SKIP_NOTCH_START */ +#define SKIP_DUMMY_START 23 +/* TX+SKIP_NOTCH_END*/ +#define SKIP_DUMMY_END 28 + + +#define NOISEFRAME (BS_NOISE+1) +#define NORMAL_IDLE_RAWDATA_NOISEFRAME 10 +#define LPWUG_RAWDATAFRAME 1 +#define LPWUG_NOISEFRAME 1 +#define LPWUG_IDLE_RAWDATAFRAME 1 +#define LPWUG_IDLE_NOISEFRAME 1 + +#define OTHERSFRAME 2 + +#define UNIFMAX 500 + + +/*Himax MP Password*/ +#define PWD_OPEN_START 0x77 +#define PWD_OPEN_END 0x88 +#define PWD_SHORT_START 0x11 +#define PWD_SHORT_END 0x33 +#define PWD_RAWDATA_START 0x00 +#define PWD_RAWDATA_END 0x99 +#define PWD_NOISE_START 0x00 +#define PWD_NOISE_END 0x99 +#define PWD_SORTING_START 0xAA +#define PWD_SORTING_END 0xCC + + +#define PWD_ACT_IDLE_START 0x22 +#define PWD_ACT_IDLE_END 0x44 + + + +#define PWD_LPWUG_START 0x55 +#define PWD_LPWUG_END 0x66 + +#define PWD_LPWUG_IDLE_START 0x50 +#define PWD_LPWUG_IDLE_END 0x60 + + +/*Himax DataType*/ +#define DATA_SORTING 0x0A +#define DATA_OPEN 0x0B +#define DATA_MICRO_OPEN 0x0C +#define DATA_SHORT 0x0A +#define DATA_RAWDATA 0x0A +#define DATA_NOISE 0x0F +#define DATA_BACK_NORMAL 0x00 +#define DATA_LPWUG_RAWDATA 0x0C +#define DATA_LPWUG_NOISE 0x0F +#define DATA_ACT_IDLE_RAWDATA 0x0A +#define DATA_ACT_IDLE_NOISE 0x0F +#define DATA_LPWUG_IDLE_RAWDATA 0x0A +#define DATA_LPWUG_IDLE_NOISE 0x0F + +/*Himax Data Ready Password*/ +#define Data_PWD0 0xA5 +#define Data_PWD1 0x5A + +/* ASCII format */ +#define ASCII_LF (0x0A) +#define ASCII_CR (0x0D) +#define ASCII_COMMA (0x2C) +#define ASCII_ZERO (0x30) +#define CHAR_EL '\0' +#define CHAR_NL '\n' +#define ACSII_SPACE (0x20) +/* INSOECTION Setting */ +/*extern int HX_CRITERIA_ITEM;*/ +/*extern int HX_CRITERIA_SIZE;*/ +/*extern char *g_file_path;*/ +/*extern char *g_rslt_data;*/ +void himax_inspection_init(void); +extern int *g_inspt_crtra_flag; + +enum THP_INSPECTION_ENUM { + HIMAX_INSPECTION_OPEN, + HIMAX_INSPECTION_MICRO_OPEN, + HIMAX_INSPECTION_SHORT, + HIMAX_INSPECTION_RAWDATA, + HIMAX_INSPECTION_BPN_RAWDATA, + HIMAX_INSPECTION_WEIGHT_NOISE, + HIMAX_INSPECTION_ABS_NOISE, + HIMAX_INSPECTION_SORTING, + HIMAX_INSPECTION_BACK_NORMAL, + + HIMAX_INSPECTION_GAPTEST_RAW, + + HIMAX_INSPECTION_ACT_IDLE_RAWDATA, + HIMAX_INSPECTION_ACT_IDLE_NOISE, + + HIMAX_INSPECTION_LPWUG_RAWDATA, + HIMAX_INSPECTION_LPWUG_NOISE, + HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA, + HIMAX_INSPECTION_LPWUG_IDLE_NOISE, + +}; + + +enum HX_CRITERIA_ENUM { + IDX_RAWMIN = 0, + IDX_RAWMAX, + IDX_BPN_RAWMIN, + IDX_BPN_RAWMAX, + IDX_SHORTMIN, + IDX_SHORTMAX, + IDX_OPENMIN, + IDX_OPENMAX, + IDX_M_OPENMIN, + IDX_M_OPENMAX, + IDX_WT_NOISEMIN, + IDX_WT_NOISEMAX, + IDX_ABS_NOISEMIN, + IDX_ABS_NOISEMAX, + IDX_SORTMIN, + IDX_SORTMAX, + + IDX_GAP_HOR_RAWMAX, + IDX_GAP_HOR_RAWMIN, + IDX_GAP_VER_RAWMAX, + IDX_GAP_VER_RAWMIN, + + IDX_ACT_IDLE_NOISE_MIN, + IDX_ACT_IDLE_NOISE_MAX, + IDX_ACT_IDLE_RAWDATA_MIN, + IDX_ACT_IDLE_RAWDATA_MAX, + + IDX_LPWUG_NOISE_MIN, + IDX_LPWUG_NOISE_MAX, + IDX_LPWUG_RAWDATA_MIN, + IDX_LPWUG_RAWDATA_MAX, + + IDX_LPWUG_IDLE_NOISE_MIN, + IDX_LPWUG_IDLE_NOISE_MAX, + IDX_LPWUG_IDLE_RAWDATA_MIN, + IDX_LPWUG_IDLE_RAWDATA_MAX, + +}; + +/* Error code of Inspection */ +enum HX_INSPECT_ERR_ENUM { + HX_INSPECT_OK = 0x00000000, /* OK */ + HX_INSPECT_EFILE = 0x00000001, /*Criteria file error*/ + HX_INSPECT_ERAW = 0x00000002, /* Raw data error */ + HX_INSPECT_WT_ENOISE = 0x00000004, /* Noise error */ + HX_INSPECT_ABS_ENOISE = 0x00000008, /* Noise error */ + HX_INSPECT_EOPEN = 0x00000010, /* Sensor open error */ + HX_INSPECT_EMOPEN = 0x00000020, /* Sensor micro open error */ + HX_INSPECT_ESHORT = 0x00000040, /* Sensor short error */ + + HX_INSPECT_EGAP_RAW = 0x00000080, /* Raw Data GAP */ + + HX_INSPECT_EACT_IDLE_RAW = 0x00000100, /* ACT_IDLE RAW ERROR */ + HX_INSPECT_EACT_IDLE_NOISE = 0x00000200, /* ACT_IDLE NOISE ERROR */ + + HX_INSPECT_ELPWUG_RAW = 0x00000400, /* LPWUG RAW ERROR */ + HX_INSPECT_ELPWUG_NOISE = 0x00000800, /* LPWUG NOISE ERROR */ + HX_INSPECT_ELPWUG_IDLE_RAW = 0x00001000, /* LPWUG IDLE RAW ERROR */ + HX_INSPECT_ELPWUG_IDLE_NOISE = 0x00002000, /* LPWUG IDLE NOISE ERROR */ + + HX_INSPECT_EGETRAW = 0x00004000, /* Get raw data errors */ + HX_INSPECT_MEMALLCTFAIL = 0x00008000, /* Get raw data errors */ + /*HX_INSPECT_ESPI = , */ /*SPI communication error,no use*/ +}; + +extern void himax_inspect_data_clear(void); +extern char *hx_self_test_file_name; diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_modular.h b/drivers/input/touchscreen/himax_v3_mmi/himax_modular.h deleted file mode 100644 index a73e60df9d0d..000000000000 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_modular.h +++ /dev/null @@ -1,398 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for modularize functions - * - * 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. - */ - -#ifndef __HIMAX_MODULAR_H__ -#define __HIMAX_MODULAR_H__ - -#include "himax_modular_table.h" - -static bool (*this_detect_fp)(void); - -#if defined(HX_USE_KSYM) -static void himax_add_chip_dt(bool (*detect_fp)(void)) -{ - int32_t idx; - struct himax_chip_entry *entry; - - this_detect_fp = detect_fp; - idx = himax_get_ksym_idx(); - if (idx < 0) { - /*TODO: No entry, handle this error*/ - E("%s: no entry exist, please insert ic module first!", - __func__); - } else { - entry = (void *)kallsyms_lookup_name(himax_ksym_lookup[idx]); - if (/*!(entry->core_chip_dt)*/isEmpty(idx) == 1) { - entry->core_chip_dt = kcalloc(HX_DRIVER_MAX_IC_NUM, - sizeof(struct himax_chip_detect), GFP_KERNEL); - if (entry->core_chip_dt == NULL) { - E("%s: Failed to allocate core_chip_dt\n", - __func__); - return; - } - entry->hx_ic_dt_num = 0; - } - entry->core_chip_dt[entry->hx_ic_dt_num++].fp_chip_detect = - detect_fp; - } -} - -#else - -static void himax_add_chip_dt(bool (*detect_fp)(void)) -{ - this_detect_fp = detect_fp; - if (himax_ksym_lookup.core_chip_dt == NULL) { - himax_ksym_lookup.core_chip_dt = kcalloc(HX_DRIVER_MAX_IC_NUM, - sizeof(struct himax_chip_detect), GFP_KERNEL); - if (himax_ksym_lookup.core_chip_dt == NULL) { - E("%s: Failed to allocate core_chip_dt\n", __func__); - return; - } - himax_ksym_lookup.hx_ic_dt_num = 0; - } - - himax_ksym_lookup.core_chip_dt - [himax_ksym_lookup.hx_ic_dt_num].fp_chip_detect = detect_fp; - himax_ksym_lookup.hx_ic_dt_num++; -} - -#endif - -static void free_chip_dt_table(void) -{ - int i, j, idx; - struct himax_chip_entry *entry; - - idx = himax_get_ksym_idx(); - if (idx >= 0) { - if (isEmpty(idx) != 0) { - I("%s: no chip registered or entry clean up\n", - __func__); - return; - } - entry = get_chip_entry_by_index(idx); - - for (i = 0; i < entry->hx_ic_dt_num; i++) { - if (entry->core_chip_dt - [i].fp_chip_detect == this_detect_fp) { - if (i == (entry->hx_ic_dt_num - 1)) { - entry->core_chip_dt - [i].fp_chip_detect = NULL; - entry->hx_ic_dt_num = 0; - } else { - for (j = i; j < entry - ->hx_ic_dt_num; j++) - entry->core_chip_dt - [i].fp_chip_detect = - entry->core_chip_dt - [j].fp_chip_detect; - - entry->core_chip_dt - [j].fp_chip_detect = NULL; - entry->hx_ic_dt_num--; - } - } - } - if (entry->hx_ic_dt_num == 0) { - kfree(entry->core_chip_dt); - entry->core_chip_dt = NULL; - } - } -} - -#if !defined(HX_USE_KSYM) -#define setup_symbol(sym) ({kp_##sym = &(sym); kp_##sym; }) -#define setup_symbol_func(sym) ({kp_##sym = (sym); kp_##sym; }) -#else -#define setup_symbol(sym) ({kp_##sym = (void *)kallsyms_lookup_name(#sym); \ - kp_##sym; }) -#define setup_symbol_func(sym) setup_symbol(sym) -#endif - -#define assert_on_symbol(sym) \ - do { \ - if (!setup_symbol(sym)) { \ - E("%s: setup %s failed!\n", __func__, #sym); \ - ret = -1; \ - } \ - } while (0) - -#define assert_on_symbol_func(sym) \ - do { \ - if (!setup_symbol_func(sym)) { \ - E("%s: setup %s failed!\n", __func__, #sym); \ - ret = -1; \ - } \ - } while (0) -#if !defined(__HIMAX_HX852xH_MOD__) && !defined(__HIMAX_HX852xG_MOD__) -static struct fw_operation **kp_pfw_op; -static struct ic_operation **kp_pic_op; -static struct flash_operation **kp_pflash_op; -static struct driver_operation **kp_pdriver_op; -#endif - -#if defined(HX_ZERO_FLASH) && defined(CONFIG_TOUCHSCREEN_HIMAX_INCELL) -static struct zf_operation **kp_pzf_op; -static int *kp_G_POWERONOF; -#endif - -static unsigned char *kp_IC_CHECKSUM; - -#if defined(HX_ESD_RECOVERY) -static u8 *kp_HX_ESD_RESET_ACTIVATE; -#endif - -#if defined(HX_ZERO_FLASH) && defined(HX_CODE_OVERLAY) -#if defined(CONFIG_TOUCHSCREEN_HIMAX_INCELL) -static uint8_t **kp_ovl_idx; -#endif -#endif - -static unsigned long *kp_FW_VER_MAJ_FLASH_ADDR; -static unsigned long *kp_FW_VER_MIN_FLASH_ADDR; -static unsigned long *kp_CFG_VER_MAJ_FLASH_ADDR; -static unsigned long *kp_CFG_VER_MIN_FLASH_ADDR; -static unsigned long *kp_CID_VER_MAJ_FLASH_ADDR; -static unsigned long *kp_CID_VER_MIN_FLASH_ADDR; - -static unsigned long *kp_FW_VER_MAJ_FLASH_LENG; -static unsigned long *kp_FW_VER_MIN_FLASH_LENG; -static unsigned long *kp_CFG_VER_MAJ_FLASH_LENG; -static unsigned long *kp_CFG_VER_MIN_FLASH_LENG; -static unsigned long *kp_CID_VER_MAJ_FLASH_LENG; -static unsigned long *kp_CID_VER_MIN_FLASH_LENG; - -#if defined(HX_AUTO_UPDATE_FW) - static int *kp_g_i_FW_VER; - static int *kp_g_i_CFG_VER; - static int *kp_g_i_CID_MAJ; - static int *kp_g_i_CID_MIN; - static unsigned char **kp_i_CTPM_FW; -#endif - -#if defined(HX_TP_PROC_2T2R) - static bool *kp_Is_2T2R; -#endif - -#if defined(HX_USB_DETECT_GLOBAL) - static void (*kp_himax_cable_detect_func)(bool force_renew); -#endif - -#if defined(HX_RST_PIN_FUNC) - static void (*kp_himax_rst_gpio_set)(int pinnum, uint8_t value); -#endif - -static struct himax_ts_data **kp_private_ts; -static struct himax_core_fp *kp_g_core_fp; -static struct himax_ic_data **kp_ic_data; - -#if defined(__HIMAX_HX852xH_MOD__) || defined(__HIMAX_HX852xG_MOD__) -#if defined(__HIMAX_HX852xG_MOD__) -static struct on_driver_operation **kp_on_pdriver_op; -#endif -static void (*kp_himax_mcu_on_cmd_init)(void); -static int (*kp_himax_mcu_on_cmd_struct_init)(void); -#else -static void (*kp_himax_mcu_in_cmd_init)(void); -static int (*kp_himax_mcu_in_cmd_struct_init)(void); -#endif -static void (*kp_himax_parse_assign_cmd)(uint32_t addr, uint8_t *cmd, - int len); - -static int (*kp_himax_bus_read)(uint8_t command, uint8_t *data, - uint32_t length, uint8_t toRetry); -static int (*kp_himax_bus_write)(uint8_t command, uint8_t *data, - uint32_t length, uint8_t toRetry); -static int (*kp_himax_bus_write_command)(uint8_t command, uint8_t toRetry); -static void (*kp_himax_int_enable)(int enable); -static int (*kp_himax_ts_register_interrupt)(void); -static uint8_t (*kp_himax_int_gpio_read)(int pinnum); -static int (*kp_himax_gpio_power_config)(struct himax_i2c_platform_data *pdata); - -#if !defined(HX_USE_KSYM) -#if !defined(__HIMAX_HX852xH_MOD__) && !defined(__HIMAX_HX852xG_MOD__) -extern struct fw_operation *pfw_op; -extern struct ic_operation *pic_op; -extern struct flash_operation *pflash_op; -extern struct driver_operation *pdriver_op; -#endif - -#if defined(HX_ZERO_FLASH) && defined(CONFIG_TOUCHSCREEN_HIMAX_INCELL) -extern struct zf_operation *pzf_op; -extern int G_POWERONOF; -#endif - -extern unsigned char IC_CHECKSUM; - -#if defined(HX_ESD_RECOVERY) -extern u8 HX_ESD_RESET_ACTIVATE; -#endif - -#if defined(HX_ZERO_FLASH) && defined(HX_CODE_OVERLAY) -#if defined(CONFIG_TOUCHSCREEN_HIMAX_INCELL) -extern uint8_t *ovl_idx; -#endif -#endif - -extern unsigned long FW_VER_MAJ_FLASH_ADDR; -extern unsigned long FW_VER_MIN_FLASH_ADDR; -extern unsigned long CFG_VER_MAJ_FLASH_ADDR; -extern unsigned long CFG_VER_MIN_FLASH_ADDR; -extern unsigned long CID_VER_MAJ_FLASH_ADDR; -extern unsigned long CID_VER_MIN_FLASH_ADDR; - -extern unsigned long FW_VER_MAJ_FLASH_LENG; -extern unsigned long FW_VER_MIN_FLASH_LENG; -extern unsigned long CFG_VER_MAJ_FLASH_LENG; -extern unsigned long CFG_VER_MIN_FLASH_LENG; -extern unsigned long CID_VER_MAJ_FLASH_LENG; -extern unsigned long CID_VER_MIN_FLASH_LENG; - -#if defined(HX_AUTO_UPDATE_FW) - extern int g_i_FW_VER; - extern int g_i_CFG_VER; - extern int g_i_CID_MAJ; - extern int g_i_CID_MIN; - extern unsigned char *i_CTPM_FW; -#endif - -#if defined(HX_TP_PROC_2T2R) - extern bool Is_2T2R; -#endif - -#if defined(HX_USB_DETECT_GLOBAL) - extern void (himax_cable_detect_func)(bool force_renew); -#endif - -#if defined(HX_RST_PIN_FUNC) - extern void (himax_rst_gpio_set)(int pinnum, uint8_t value); -#endif - -extern struct himax_ts_data *private_ts; -extern struct himax_core_fp g_core_fp; -extern struct himax_ic_data *ic_data; - -#if defined(__HIMAX_HX852xH_MOD__) || defined(__HIMAX_HX852xG_MOD__) -#if defined(__HIMAX_HX852xG_MOD__) -extern struct on_driver_operation *on_pdriver_op; -#endif -extern void (himax_mcu_on_cmd_init)(void); -extern int (himax_mcu_on_cmd_struct_init)(void); -#else -extern void (himax_mcu_in_cmd_init)(void); -extern int (himax_mcu_in_cmd_struct_init)(void); -#endif -extern void (himax_parse_assign_cmd)(uint32_t addr, uint8_t *cmd, int len); - -extern int (himax_bus_read)(uint8_t command, uint8_t *data, uint32_t length, - uint8_t toRetry); -extern int (himax_bus_write)(uint8_t command, uint8_t *data, uint32_t length, - uint8_t toRetry); -extern int (himax_bus_write_command)(uint8_t command, uint8_t toRetry); -extern void (himax_int_enable)(int enable); -extern int (himax_ts_register_interrupt)(void); -extern uint8_t (himax_int_gpio_read)(int pinnum); -extern int (himax_gpio_power_config)(struct himax_i2c_platform_data *pdata); -#endif - -static int32_t himax_ic_setup_external_symbols(void) -{ - int32_t ret = 0; - -#if !defined(__HIMAX_HX852xH_MOD__) && !defined(__HIMAX_HX852xG_MOD__) - assert_on_symbol(pfw_op); - assert_on_symbol(pic_op); - assert_on_symbol(pflash_op); - assert_on_symbol(pdriver_op); -#endif - - assert_on_symbol(private_ts); - assert_on_symbol(g_core_fp); - assert_on_symbol(ic_data); - -#if defined(__HIMAX_HX852xH_MOD__) || defined(__HIMAX_HX852xG_MOD__) -#if defined(__HIMAX_HX852xG_MOD__) - assert_on_symbol(on_pdriver_op); -#endif - assert_on_symbol_func(himax_mcu_on_cmd_init); - assert_on_symbol_func(himax_mcu_on_cmd_struct_init); -#else - assert_on_symbol_func(himax_mcu_in_cmd_init); - assert_on_symbol_func(himax_mcu_in_cmd_struct_init); -#endif - assert_on_symbol_func(himax_parse_assign_cmd); - assert_on_symbol_func(himax_bus_read); - assert_on_symbol_func(himax_bus_write); - assert_on_symbol_func(himax_bus_write_command); - assert_on_symbol_func(himax_int_enable); - assert_on_symbol_func(himax_ts_register_interrupt); - assert_on_symbol_func(himax_int_gpio_read); - assert_on_symbol_func(himax_gpio_power_config); - -#if defined(HX_ZERO_FLASH) && defined(CONFIG_TOUCHSCREEN_HIMAX_INCELL) - assert_on_symbol(pzf_op); - assert_on_symbol(G_POWERONOF); -#endif - - assert_on_symbol(IC_CHECKSUM); - - assert_on_symbol(FW_VER_MAJ_FLASH_ADDR); - assert_on_symbol(FW_VER_MIN_FLASH_ADDR); - assert_on_symbol(CFG_VER_MAJ_FLASH_ADDR); - assert_on_symbol(CFG_VER_MIN_FLASH_ADDR); - assert_on_symbol(CID_VER_MAJ_FLASH_ADDR); - assert_on_symbol(CID_VER_MIN_FLASH_ADDR); - - assert_on_symbol(FW_VER_MAJ_FLASH_LENG); - assert_on_symbol(FW_VER_MIN_FLASH_LENG); - assert_on_symbol(CFG_VER_MAJ_FLASH_LENG); - assert_on_symbol(CFG_VER_MIN_FLASH_LENG); - assert_on_symbol(CID_VER_MAJ_FLASH_LENG); - assert_on_symbol(CID_VER_MIN_FLASH_LENG); - -#if defined(HX_AUTO_UPDATE_FW) - assert_on_symbol(g_i_FW_VER); - assert_on_symbol(g_i_CFG_VER); - assert_on_symbol(g_i_CID_MAJ); - assert_on_symbol(g_i_CID_MIN); - assert_on_symbol(i_CTPM_FW); -#endif - -#if defined(HX_TP_PROC_2T2R) - assert_on_symbol(Is_2T2R); -#endif - -#if defined(HX_USB_DETECT_GLOBAL) - assert_on_symbol_func(himax_cable_detect_func); -#endif - -#if defined(HX_RST_PIN_FUNC) - assert_on_symbol_func(himax_rst_gpio_set); -#endif - -#if defined(HX_ESD_RECOVERY) - assert_on_symbol(HX_ESD_RESET_ACTIVATE); -#endif -#if defined(HX_ZERO_FLASH) && defined(HX_CODE_OVERLAY) -#if defined(CONFIG_TOUCHSCREEN_HIMAX_INCELL) - assert_on_symbol(ovl_idx); -#endif -#endif - return ret; -} - - -#endif diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_modular_table.h b/drivers/input/touchscreen/himax_v3_mmi/himax_modular_table.h index 7bb269116056..180d823d581f 100644 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_modular_table.h +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_modular_table.h @@ -1,156 +1,115 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for modularize functions - * - * 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. - */ - -#ifndef __HIMAX_MODULAR_TABLE_H__ -#define __HIMAX_MODULAR_TABLE_H__ - -#include "himax_ic_core.h" - -#define TO_STR(VAR) #VAR - -enum modular_table { - MODULE_NOT_FOUND = -1, - MODULE_FOUND, - MODULE_EMPTY, -}; - -#if defined(HX_USE_KSYM) -#define DECLARE(sym) struct himax_chip_entry sym; \ - EXPORT_SYMBOL(sym) -static const char * const himax_ksym_lookup[] = { - #if defined(HX_MOD_KSYM_HX852xG) - TO_STR(HX_MOD_KSYM_HX852xG), - #endif - #if defined(HX_MOD_KSYM_HX852xH) - TO_STR(HX_MOD_KSYM_HX852xH), - #endif - #if defined(HX_MOD_KSYM_HX83102) - TO_STR(HX_MOD_KSYM_HX83102), - #endif - #if defined(HX_MOD_KSYM_HX83103) - TO_STR(HX_MOD_KSYM_HX83103), - #endif - #if defined(HX_MOD_KSYM_HX83106) - TO_STR(HX_MOD_KSYM_HX83106), - #endif - #if defined(HX_MOD_KSYM_HX83111) - TO_STR(HX_MOD_KSYM_HX83111), - #endif - #if defined(HX_MOD_KSYM_HX83112) - TO_STR(HX_MOD_KSYM_HX83112), - #endif - #if defined(HX_MOD_KSYM_HX83113) - TO_STR(HX_MOD_KSYM_HX83113), - #endif - #if defined(HX_MOD_KSYM_HX83192) - TO_STR(HX_MOD_KSYM_HX83192), - #endif - #if defined(HX_MOD_KSYM_HX83191) - TO_STR(HX_MOD_KSYM_HX83191), - #endif - NULL -}; - -static struct himax_chip_entry *get_chip_entry_by_index(int32_t idx) -{ - return (void *)kallsyms_lookup_name(himax_ksym_lookup[idx]); -} - -/* - * Return 1 when specified entry is empty, 0 when not, -1 when index error - */ -static int32_t isEmpty(int32_t idx) -{ - int32_t size = sizeof(himax_ksym_lookup) / sizeof(char *); - struct himax_chip_entry *entry; - - if (idx < 0 || idx >= size) - return MODULE_NOT_FOUND; - - entry = get_chip_entry_by_index(idx); - if (entry) - return (entry->core_chip_dt == NULL)?MODULE_EMPTY:MODULE_FOUND; - - return MODULE_NOT_FOUND; -} - -/* - * Search for created entry, if not existed, return 1st - * Return index of himax_ksym_lookup - */ -static int32_t himax_get_ksym_idx(void) -{ - int32_t i, first = -1; - int32_t size = sizeof(himax_ksym_lookup) / sizeof(char *); - struct himax_chip_entry *entry; - - I("%s: symtable size: %d\n", __func__, size); - for (i = 0; i < size; i++) { - if (himax_ksym_lookup[i] == NULL) - break; - - I("%s: %s\n", __func__, himax_ksym_lookup[i]); - entry = get_chip_entry_by_index(i); - if (entry) { - if (first < 0) - first = i; - if (isEmpty(i) == 0) - return i; - } - } - if (first >= 0) - return first; - /*incorrect use state, means no ic defined*/ - return MODULE_NOT_FOUND; -} - -#else -#define DECLARE(sym) -extern struct himax_chip_entry himax_ksym_lookup; - -static struct himax_chip_entry *get_chip_entry_by_index(int32_t idx) -{ - return &himax_ksym_lookup; -} - -static int32_t isEmpty(int32_t idx) -{ - struct himax_chip_entry *entry; - - if (idx < 0) - return MODULE_NOT_FOUND; - - entry = get_chip_entry_by_index(idx); - if (entry) - return (entry->core_chip_dt == NULL)?MODULE_EMPTY:MODULE_FOUND; - - return MODULE_NOT_FOUND; -} - -static int32_t himax_get_ksym_idx(void) -{ - int32_t size; - - size = himax_ksym_lookup.hx_ic_dt_num; - - I("%s: symtable size: %d\n", __func__, size); - return 0; -} - -#endif - - - -#endif +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for modularize functions + * + * 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. + */ + +#ifndef __HIMAX_MODULAR_TABLE_H__ +#define __HIMAX_MODULAR_TABLE_H__ + +#include "himax_ic_core.h" + +#define TO_STR(VAR) #VAR +#define DECLARE(sym) struct himax_chip_entry sym; \ + EXPORT_SYMBOL(sym) + +static const char * const himax_ksym_lookup[] = { + #if defined(HX_MOD_KSYM_HX852xG) + TO_STR(HX_MOD_KSYM_HX852xG), + #endif + #if defined(HX_MOD_KSYM_HX852xH) + TO_STR(HX_MOD_KSYM_HX852xH), + #endif + #if defined(HX_MOD_KSYM_HX83102) + TO_STR(HX_MOD_KSYM_HX83102), + #endif + #if defined(HX_MOD_KSYM_HX83103) + TO_STR(HX_MOD_KSYM_HX83103), + #endif + #if defined(HX_MOD_KSYM_HX83106) + TO_STR(HX_MOD_KSYM_HX83106), + #endif + #if defined(HX_MOD_KSYM_HX83111) + TO_STR(HX_MOD_KSYM_HX83111), + #endif + #if defined(HX_MOD_KSYM_HX83112) + TO_STR(HX_MOD_KSYM_HX83112), + #endif + #if defined(HX_MOD_KSYM_HX83113) + TO_STR(HX_MOD_KSYM_HX83113), + #endif + #if defined(HX_MOD_KSYM_HX83191) + TO_STR(HX_MOD_KSYM_HX83191), + #endif + NULL +}; + +static struct himax_chip_entry *get_chip_entry_by_index(int32_t idx) +{ + return (void *)kallsyms_lookup_name(himax_ksym_lookup[idx]); +} + +enum modular_table { + MODULE_NOT_FOUND = -1, + MODULE_FOUND, + MODULE_EMPTY, +}; + +/* + * Return 1 when specified entry is empty, 0 when not, -1 when index error + */ +static int32_t isEmpty(int32_t idx) +{ + int32_t size = sizeof(himax_ksym_lookup) / sizeof(char *); + struct himax_chip_entry *entry; + + if (idx < 0 || idx >= size) + return MODULE_NOT_FOUND; + + entry = get_chip_entry_by_index(idx); + if (entry) + return (entry->core_chip_dt == NULL)?MODULE_EMPTY:MODULE_FOUND; + + return MODULE_NOT_FOUND; +} + +/* + * Search for created entry, if not existed, return 1st + * Return index of himax_ksym_lookup + */ +static int32_t himax_get_ksym_idx(void) +{ + int32_t i, first = -1; + int32_t size = sizeof(himax_ksym_lookup) / sizeof(char *); + struct himax_chip_entry *entry; + + I("%s: symtable size: %d\n", __func__, size); + for (i = 0; i < size; i++) { + if (himax_ksym_lookup[i] == NULL) + break; + + I("%s: %s\n", __func__, himax_ksym_lookup[i]); + entry = get_chip_entry_by_index(i); + if (entry) { + if (first < 0) + first = i; + if (isEmpty(i) == 0) + return i; + } + } + if (first >= 0) + return first; + /*incorrect use state, means no ic defined*/ + return MODULE_NOT_FOUND; +} + +#endif diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_platform.h b/drivers/input/touchscreen/himax_v3_mmi/himax_platform.h index 6773b0d6cd8f..924b4c8de25f 100644 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_platform.h +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_platform.h @@ -1,143 +1,5 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for QCT platform - * - * 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. - */ - -#ifndef HIMAX_PLATFORM_H -#define HIMAX_PLATFORM_H - -#include -#include -#include -#include -#include -#include -#if defined(CONFIG_HMX_DB) - #include -#endif - -#define HIMAX_SPI_FIFO_POLLING -#define HIMAX_I2C_RETRY_TIMES 3 - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) -#define D(x...) pr_debug("[HXTP] " x) -#define I(x...) pr_info("[HXTP] " x) -#define W(x...) pr_warn("[HXTP][WARNING] " x) -#define E(x...) pr_err("[HXTP][ERROR] " x) -#define DIF(x...) \ -do { \ - if (debug_flag) \ - pr_debug("[HXTP][DEBUG] " x) \ - } while (0) -#else -#define D(x...) -#define I(x...) -#define W(x...) -#define E(x...) -#define DIF(x...) -#endif - -#if defined(CONFIG_HMX_DB) - /* Analog voltage @2.7 V */ -#define HX_VTG_MIN_UV 2700000 -#define HX_VTG_MAX_UV 3300000 -#define HX_ACTIVE_LOAD_UA 15000 -#define HX_LPM_LOAD_UA 10 -/* Digital voltage @1.8 V */ -#define HX_VTG_DIG_MIN_UV 1800000 -#define HX_VTG_DIG_MAX_UV 1800000 -#define HX_ACTIVE_LOAD_DIG_UA 10000 -#define HX_LPM_LOAD_DIG_UA 10 - -#define HX_I2C_VTG_MIN_UV 1800000 -#define HX_I2C_VTG_MAX_UV 1800000 -#define HX_I2C_LOAD_UA 10000 -#define HX_I2C_LPM_LOAD_UA 10 -#endif - -#define HIMAX_common_NAME "himax_tp" -#define HIMAX_I2C_ADDR 0x48 -#define INPUT_DEV_NAME "himax-touchscreen" - -struct himax_i2c_platform_data { - int abs_x_min; - int abs_x_max; - int abs_x_fuzz; - int abs_y_min; - int abs_y_max; - int abs_y_fuzz; - int abs_pressure_min; - int abs_pressure_max; - int abs_pressure_fuzz; - int abs_width_min; - int abs_width_max; - int screenWidth; - int screenHeight; - uint8_t fw_version; - uint8_t tw_id; - uint8_t powerOff3V3; - uint8_t cable_config[2]; - uint8_t protocol_type; - int gpio_irq; - int gpio_reset; - int gpio_3v3_en; - int (*power)(int on); - void (*reset)(void); - struct himax_virtual_key *virtual_key; - struct kobject *vk_obj; - struct kobj_attribute *vk2Use; - - int hx_config_size; -#if defined(CONFIG_HMX_DB) - bool i2c_pull_up; - bool digital_pwr_regulator; - int reset_gpio; - u32 reset_gpio_flags; - int irq_gpio; - u32 irq_gpio_flags; - - struct regulator *vcc_ana; /* For Dragon Board */ - struct regulator *vcc_dig; /* For Dragon Board */ - struct regulator *vcc_i2c; /* For Dragon Board */ -#endif -}; - -extern struct himax_ic_data *ic_data; -extern struct himax_ts_data *private_ts; -int himax_chip_common_init(void); -void himax_chip_common_deinit(void); - -void himax_ts_work(struct himax_ts_data *ts); -enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer); -extern int himax_bus_read(uint8_t command, uint8_t *data, - uint32_t length, uint8_t toRetry); -extern int himax_bus_write(uint8_t command, uint8_t *data, - uint32_t length, uint8_t toRetry); -extern int himax_bus_write_command(uint8_t command, uint8_t toRetry); -extern void himax_int_enable(int enable); -extern int himax_ts_register_interrupt(void); -int himax_ts_unregister_interrupt(void); -extern uint8_t himax_int_gpio_read(int pinnum); - -extern int himax_gpio_power_config(struct himax_i2c_platform_data *pdata); -void himax_gpio_power_deconfig(struct himax_i2c_platform_data *pdata); - -#if defined(HX_CONFIG_FB) -extern int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data); -#elif defined(CONFIG_DRM) -extern int drm_notifier_callback(struct notifier_block *self, - unsigned long event, void *data); -#endif - -#endif +#ifdef __HIMAX_PLATFORM_SPI__ +#include "himax_platform_QCT_SPI.h" +#else +#include "himax_platform_QCT_I2C.h" +#endif diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_I2C.c b/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_I2C.c new file mode 100644 index 000000000000..316e6914d2f8 --- /dev/null +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_I2C.c @@ -0,0 +1,972 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for QCT platform + * + * 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_platform.h" +#include "himax_common.h" + +int i2c_error_count; +int irq_enable_count; +EXPORT_SYMBOL(irq_enable_count); + +int himax_dev_set(struct himax_ts_data *ts) +{ + int ret = 0; + + + ts->input_dev = input_allocate_device(); + + if (ts->input_dev == NULL) { + ret = -ENOMEM; + E("%s: Failed to allocate input device-input_dev\n", __func__); + return ret; + } + + ts->input_dev->name = "himax-touchscreen"; +#if defined(HX_PEN_FUNC_EN) + ts->hx_pen_dev = input_allocate_device(); + + if (ts->hx_pen_dev == NULL) { + ret = -ENOMEM; + E("%s: Failed to allocate input device-hx_pen_dev\n", __func__); + return ret; + } + + ts->hx_pen_dev->name = "himax-pen"; +#endif + return ret; +} +int himax_input_register_device(struct input_dev *input_dev) +{ + return input_register_device(input_dev); +} + +#if defined(HX_PLATFOME_DEFINE_KEY) +void himax_platform_key(void) +{ + I("Nothing to be done! Plz cancel it!\n"); +} +#endif + +void himax_vk_parser(struct device_node *dt, + struct himax_i2c_platform_data *pdata) +{ + u32 data = 0; + uint8_t cnt = 0, i = 0; + uint32_t coords[4] = {0}; + struct device_node *node, *pp = NULL; + struct himax_virtual_key *vk; + + + node = of_parse_phandle(dt, "virtualkey", 0); + + if (node == NULL) { + I(" DT-No vk info in DT\n"); + } else { + while ((pp = of_get_next_child(node, pp))) + cnt++; + + if (!cnt) + return; + + vk = kcalloc(cnt, sizeof(struct himax_virtual_key), GFP_KERNEL); + pp = NULL; + + while ((pp = of_get_next_child(node, pp))) { + if (of_property_read_u32(pp, "idx", &data) == 0) + vk[i].index = data; + + if (of_property_read_u32_array(pp, "range", coords, 4) == 0) { + vk[i].x_range_min = coords[0], vk[i].x_range_max = coords[1]; + vk[i].y_range_min = coords[2], vk[i].y_range_max = coords[3]; + } else { + I(" range faile\n"); + } + + i++; + } + + pdata->virtual_key = vk; + + for (i = 0; i < cnt; i++) + I(" vk[%d] idx:%d x_min:%d, y_max:%d\n", i, pdata->virtual_key[i].index, + pdata->virtual_key[i].x_range_min, pdata->virtual_key[i].y_range_max); + } +} + +int himax_parse_dt(struct himax_ts_data *ts, + struct himax_i2c_platform_data *pdata) +{ + int rc, coords_size = 0; + uint32_t coords[4] = {0}; + struct property *prop; + struct device_node *dt = private_ts->client->dev.of_node; + u32 data = 0; + + + prop = of_find_property(dt, "himax,panel-coords", NULL); + + if (prop) { + coords_size = prop->length / sizeof(u32); + + if (coords_size != 4) + D(" %s:Invalid panel coords size %d\n", __func__, coords_size); + } + + if (of_property_read_u32_array(dt, "himax,panel-coords", coords, coords_size) == 0) { + pdata->abs_x_min = coords[0], pdata->abs_x_max = (coords[1] - 1); + pdata->abs_y_min = coords[2], pdata->abs_y_max = (coords[3] - 1); + I(" DT-%s:panel-coords = %d, %d, %d, %d\n", __func__, pdata->abs_x_min, + pdata->abs_x_max, pdata->abs_y_min, pdata->abs_y_max); + } + + prop = of_find_property(dt, "himax,display-coords", NULL); + + if (prop) { + coords_size = prop->length / sizeof(u32); + + if (coords_size != 4) + D(" %s:Invalid display coords size %d\n", __func__, coords_size); + } + + rc = of_property_read_u32_array(dt, "himax,display-coords", coords, coords_size); + + if (rc && (rc != -EINVAL)) { + D(" %s:Fail to read display-coords %d\n", __func__, rc); + return rc; + } + + pdata->screenWidth = coords[1]; + pdata->screenHeight = coords[3]; + I(" DT-%s:display-coords = (%d, %d)\n", __func__, pdata->screenWidth, + pdata->screenHeight); + pdata->gpio_irq = of_get_named_gpio(dt, "himax,irq-gpio", 0); + + if (!gpio_is_valid(pdata->gpio_irq)) + I(" DT:gpio_irq value is not valid\n"); + +#ifdef HX_SHARP_ENABLE_PON + pdata->gpio_reset = 262; +#else + pdata->gpio_reset = of_get_named_gpio(dt, "himax,rst-gpio", 0); +#endif + + if (!gpio_is_valid(pdata->gpio_reset)) + I(" DT:gpio_rst value is not valid\n"); + +#ifdef HX_SHARP_ENABLE_PON + pdata->gpio_pon = of_get_named_gpio(dt, "himax,pon-gpio", 0); + + if (!gpio_is_valid(pdata->gpio_pon)) + I(" DT:gpio_pon value is not valid\n"); + + + I(" DT:pdata->gpio_pon=%d\n", pdata->gpio_pon); + +#endif + + pdata->gpio_3v3_en = of_get_named_gpio(dt, "himax,3v3-gpio", 0); + + if (!gpio_is_valid(pdata->gpio_3v3_en)) + I(" DT:gpio_3v3_en value is not valid\n"); + + I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d\n", pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en); + + if (of_property_read_u32(dt, "report_type", &data) == 0) { + pdata->protocol_type = data; + I(" DT:protocol_type=%d\n", pdata->protocol_type); + } + + himax_vk_parser(dt, pdata); + return 0; +} +EXPORT_SYMBOL(himax_parse_dt); + +int himax_bus_read(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry) +{ + int retry; + struct i2c_client *client = private_ts->client; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command, + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = length, + .buf = data, + } + }; + mutex_lock(&private_ts->rw_lock); + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 2) == 2) + break; + + /*msleep(20);*/ + } + + if (retry == toRetry) { + E("%s: i2c_read_block retry over %d\n", + __func__, toRetry); + i2c_error_count = toRetry; + mutex_unlock(&private_ts->rw_lock); + return -EIO; + } + + mutex_unlock(&private_ts->rw_lock); + return 0; +} +EXPORT_SYMBOL(himax_bus_read); + +int himax_bus_write(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry) +{ + int retry/*, loop_i*/; + uint8_t buf[length + 1]; + struct i2c_client *client = private_ts->client; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = length + 1, + .buf = buf, + } + }; + + + mutex_lock(&private_ts->rw_lock); + buf[0] = command; + memcpy(buf + 1, data, length); + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) + break; + + /*msleep(20);*/ + } + + if (retry == toRetry) { + E("%s: i2c_write_block retry over %d\n", + __func__, toRetry); + i2c_error_count = toRetry; + mutex_unlock(&private_ts->rw_lock); + return -EIO; + } + + mutex_unlock(&private_ts->rw_lock); + return 0; +} +EXPORT_SYMBOL(himax_bus_write); + +int himax_bus_write_command(uint8_t command, uint8_t toRetry) +{ + return himax_bus_write(command, NULL, 0, toRetry); +} + +int himax_bus_master_write(uint8_t *data, uint32_t length, uint8_t toRetry) +{ + int retry/*, loop_i*/; + uint8_t buf[length]; + struct i2c_client *client = private_ts->client; + struct i2c_msg msg[] = { + { + .addr = client->addr, + .flags = 0, + .len = length, + .buf = buf, + } + }; + + + mutex_lock(&private_ts->rw_lock); + memcpy(buf, data, length); + + for (retry = 0; retry < toRetry; retry++) { + if (i2c_transfer(client->adapter, msg, 1) == 1) + break; + + /*msleep(20);*/ + } + + if (retry == toRetry) { + E("%s: i2c_write_block retry over %d\n", + __func__, toRetry); + i2c_error_count = toRetry; + mutex_unlock(&private_ts->rw_lock); + return -EIO; + } + + mutex_unlock(&private_ts->rw_lock); + return 0; +} +EXPORT_SYMBOL(himax_bus_master_write); + +void himax_int_enable(int enable) +{ + int irqnum = 0; + + + irqnum = private_ts->client->irq; + + if (enable == 1 && irq_enable_count == 0) { + enable_irq(irqnum); + irq_enable_count = 1; + private_ts->irq_enabled = 1; + } else if (enable == 0 && irq_enable_count == 1) { + disable_irq_nosync(irqnum); + irq_enable_count = 0; + private_ts->irq_enabled = 0; + } + + I("irq_enable_count = %d\n", irq_enable_count); +} +EXPORT_SYMBOL(himax_int_enable); + +#ifdef HX_RST_PIN_FUNC +void himax_rst_gpio_set(int pinnum, uint8_t value) +{ + gpio_direction_output(pinnum, value); +} +EXPORT_SYMBOL(himax_rst_gpio_set); +#endif + +uint8_t himax_int_gpio_read(int pinnum) +{ + return gpio_get_value(pinnum); +} + +#if defined(CONFIG_HMX_DB) +static int himax_regulator_configure(struct himax_i2c_platform_data *pdata) +{ + int retval; + struct i2c_client *client = private_ts->client; + + + pdata->vcc_dig = regulator_get(&client->dev, "vdd"); + + if (IS_ERR(pdata->vcc_dig)) { + E("%s: Failed to get regulator vdd\n", + __func__); + retval = PTR_ERR(pdata->vcc_dig); + return retval; + } + + pdata->vcc_ana = regulator_get(&client->dev, "avdd"); + + if (IS_ERR(pdata->vcc_ana)) { + E("%s: Failed to get regulator avdd\n", + __func__); + retval = PTR_ERR(pdata->vcc_ana); + regulator_put(pdata->vcc_dig); + return retval; + } + + return 0; +}; + +static void himax_regulator_deinit(struct himax_i2c_platform_data *pdata) +{ + I("%s: entered.\n", __func__); + + if (!IS_ERR(pdata->vcc_ana)) + regulator_put(pdata->vcc_ana); + + if (!IS_ERR(pdata->vcc_dig)) + regulator_put(pdata->vcc_dig); + + I("%s: regulator put, completed.\n", __func__); +}; + +static int himax_power_on(struct himax_i2c_platform_data *pdata, bool on) +{ + int retval; + + if (on) { + retval = regulator_enable(pdata->vcc_dig); + + if (retval) { + E("%s: Failed to enable regulator vdd\n", + __func__); + return retval; + } + + /*msleep(100);*/ + usleep_range(1000, 1001); + retval = regulator_enable(pdata->vcc_ana); + + if (retval) { + E("%s: Failed to enable regulator avdd\n", + __func__); + regulator_disable(pdata->vcc_dig); + return retval; + } + } else { + regulator_disable(pdata->vcc_dig); + regulator_disable(pdata->vcc_ana); + } + + return 0; +} + +int himax_gpio_power_config(struct himax_i2c_platform_data *pdata) +{ + int error; + struct i2c_client *client = private_ts->client; + + + error = himax_regulator_configure(pdata); + + if (error) { + E("Failed to intialize hardware\n"); + goto err_regulator_not_on; + } + +#ifdef HX_RST_PIN_FUNC + + if (gpio_is_valid(pdata->gpio_reset)) { + /* configure touchscreen reset out gpio */ + error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio"); + + if (error) { + E("unable to request gpio [%d]\n", pdata->gpio_reset); + goto err_regulator_on; + } + + error = gpio_direction_output(pdata->gpio_reset, 0); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_reset_req; + } + } + +#endif + error = himax_power_on(pdata, true); + + if (error) { + E("Failed to power on hardware\n"); + goto err_power_on; + } + + if (gpio_is_valid(pdata->gpio_irq)) { + /* configure touchscreen irq gpio */ + error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq"); + + if (error) { + E("unable to request gpio [%d]\n", + pdata->gpio_irq); + goto err_req_irq_gpio; + } + + error = gpio_direction_input(pdata->gpio_irq); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_irq); + goto err_set_gpio_irq; + } + + client->irq = gpio_to_irq(pdata->gpio_irq); + private_ts->hx_irq = client->irq; + } else { + E("irq gpio not provided\n"); + goto err_req_irq_gpio; + } + + /*msleep(20);*/ + usleep_range(2000, 2001); +#ifdef HX_RST_PIN_FUNC + + if (gpio_is_valid(pdata->gpio_reset)) { + error = gpio_direction_output(pdata->gpio_reset, 1); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_set_gpio_irq; + } + } + +#endif + return 0; +err_set_gpio_irq: + + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); + +err_req_irq_gpio: + himax_power_on(pdata, false); +err_power_on: +#ifdef HX_RST_PIN_FUNC +err_gpio_reset_req: + if (gpio_is_valid(pdata->gpio_reset)) + gpio_free(pdata->gpio_reset); + +err_regulator_on: +#endif + himax_regulator_deinit(pdata); +err_regulator_not_on: + return error; +} + +#else +int himax_gpio_power_config(struct himax_i2c_platform_data *pdata) +{ + int error = 0; + struct i2c_client *client = private_ts->client; +#ifdef HX_RST_PIN_FUNC + + if (pdata->gpio_reset >= 0) { + error = gpio_request(pdata->gpio_reset, "himax-reset"); + + if (error < 0) { + E("%s: request reset pin failed\n", __func__); + goto err_gpio_reset_req; + } + + error = gpio_direction_output(pdata->gpio_reset, 0); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_reset_dir; + } + } + +#endif + +#ifdef HX_SHARP_ENABLE_PON + if (gpio_is_valid(pdata->gpio_pon)) { + error = gpio_request(pdata->gpio_pon, "hmx_pon_gpio"); + + if (error) { + E("unable to request scl gpio [%d]\n", pdata->gpio_pon); + goto err_gpio_pon_req; + } + + error = gpio_direction_output(pdata->gpio_pon, 0); + + I("gpio_pon LOW [%d]\n", pdata->gpio_pon); + + if (error) { + E("unable to set direction for pon gpio [%d]\n", pdata->gpio_pon); + goto err_gpio_pon_dir; + } + } +#endif + + + if (pdata->gpio_3v3_en >= 0) { + error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en"); + + if (error < 0) { + E("%s: request 3v3_en pin failed\n", __func__); + goto err_gpio_3v3_req; + } + + gpio_direction_output(pdata->gpio_3v3_en, 1); + I("3v3_en set 1 get pin = %d\n", gpio_get_value(pdata->gpio_3v3_en)); + } + + if (gpio_is_valid(pdata->gpio_irq)) { + /* configure touchscreen irq gpio */ + error = gpio_request(pdata->gpio_irq, "himax_gpio_irq"); + + if (error) { + E("unable to request gpio [%d]\n", pdata->gpio_irq); + goto err_gpio_irq_req; + } + + error = gpio_direction_input(pdata->gpio_irq); + + if (error) { + E("unable to set direction for gpio [%d]\n", pdata->gpio_irq); + goto err_gpio_irq_set_input; + } + + client->irq = gpio_to_irq(pdata->gpio_irq); + private_ts->hx_irq = client->irq; + } else { + E("irq gpio not provided\n"); + goto err_gpio_irq_req; + } +#ifdef HX_SHARP_ENABLE_PON + msleep(20); +#else + usleep_range(2000, 2001); +#endif + +#ifdef HX_RST_PIN_FUNC + + if (pdata->gpio_reset >= 0) { + error = gpio_direction_output(pdata->gpio_reset, 1); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_reset_set_high; + } + } +#endif + +#ifdef HX_SHARP_ENABLE_PON + msleep(800); + + if (gpio_is_valid(pdata->gpio_pon)) { + + error = gpio_direction_output(pdata->gpio_pon, 1); + + I("gpio_pon HIGH [%d]\n", pdata->gpio_pon); + + if (error) { + E("gpio_pon unable to set direction for gpio [%d]\n", pdata->gpio_pon); + goto err_gpio_pon_set_high; + } + } +#endif + return error; + +#ifdef HX_SHARP_ENABLE_PON +err_gpio_pon_set_high: +#endif +#ifdef HX_RST_PIN_FUNC +err_gpio_reset_set_high: +#endif +err_gpio_irq_set_input: + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); +err_gpio_irq_req: + if (pdata->gpio_3v3_en >= 0) + gpio_free(pdata->gpio_3v3_en); +err_gpio_3v3_req: +#ifdef HX_SHARP_ENABLE_PON +err_gpio_pon_dir: + if (gpio_is_valid(pdata->gpio_pon)) + gpio_free(pdata->gpio_pon); +err_gpio_pon_req: +#endif +#ifdef HX_RST_PIN_FUNC +err_gpio_reset_dir: + if (pdata->gpio_reset >= 0) + gpio_free(pdata->gpio_reset); +err_gpio_reset_req: +#endif + return error; +} + +#endif + +void himax_gpio_power_deconfig(struct himax_i2c_platform_data *pdata) +{ + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); + +#ifdef HX_RST_PIN_FUNC + if (gpio_is_valid(pdata->gpio_reset)) + gpio_free(pdata->gpio_reset); +#endif + +#if defined(CONFIG_HMX_DB) + himax_power_on(pdata, false); + himax_regulator_deinit(pdata); +#else + if (pdata->gpio_3v3_en >= 0) + gpio_free(pdata->gpio_3v3_en); + +#ifdef HX_SHARP_ENABLE_PON + if (gpio_is_valid(pdata->gpio_pon)) + gpio_free(pdata->gpio_pon); +#endif + +#endif +} + +static void himax_ts_isr_func(struct himax_ts_data *ts) +{ + himax_ts_work(ts); +} + +irqreturn_t himax_ts_thread(int irq, void *ptr) +{ + himax_ts_isr_func((struct himax_ts_data *)ptr); + + return IRQ_HANDLED; +} + +static void himax_ts_work_func(struct work_struct *work) +{ + struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work); + + + himax_ts_work(ts); +} + +int himax_int_register_trigger(void) +{ + int ret = 0; + struct himax_ts_data *ts = private_ts; + struct i2c_client *client = private_ts->client; + + if (ic_data->HX_INT_IS_EDGE) { + I("%s edge triiger falling\n ", __func__); + ret = request_threaded_irq(client->irq, NULL, himax_ts_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, ts); + } + + else { + I("%s level trigger low\n ", __func__); + ret = request_threaded_irq(client->irq, NULL, himax_ts_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts); + } + + return ret; +} + +int himax_int_en_set(void) +{ + int ret = NO_ERR; + + + ret = himax_int_register_trigger(); + return ret; +} + +int himax_ts_register_interrupt(void) +{ + struct himax_ts_data *ts = private_ts; + struct i2c_client *client = private_ts->client; + int ret = 0; + + + ts->irq_enabled = 0; + + /* Work functon */ + if (client->irq && private_ts->hx_irq) {/*INT mode*/ + ts->use_irq = 1; + ret = himax_int_register_trigger(); + + if (ret == 0) { + ts->irq_enabled = 1; + irq_enable_count = 1; + I("%s: irq enabled at gpio: %d\n", __func__, client->irq); +#ifdef HX_SMART_WAKEUP + irq_set_irq_wake(client->irq, 1); +#endif + } else { + ts->use_irq = 0; + E("%s: request_irq failed\n", __func__); + } + } else { + I("%s: client->irq is empty, use polling mode.\n", __func__); + } + + if (!ts->use_irq) {/*if use polling mode need to disable HX_ESD_RECOVERY function*/ + ts->himax_wq = create_singlethread_workqueue("himax_touch"); + INIT_WORK(&ts->work, himax_ts_work_func); + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ts->timer.function = himax_ts_timer_func; + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + I("%s: polling mode enabled\n", __func__); + } + + return ret; +} + +int himax_ts_unregister_interrupt(void) +{ + struct himax_ts_data *ts = private_ts; + int ret = 0; + + + I("%s: entered.\n", __func__); + + /* Work functon */ + if (private_ts->hx_irq && ts->use_irq) {/*INT mode*/ +#ifdef HX_SMART_WAKEUP + irq_set_irq_wake(ts->hx_irq, 0); +#endif + free_irq(ts->hx_irq, ts); + I("%s: irq disabled at qpio: %d\n", __func__, private_ts->hx_irq); + } + + if (!ts->use_irq) {/*if use polling mode need to disable HX_ESD_RECOVERY function*/ + hrtimer_cancel(&ts->timer); + cancel_work_sync(&ts->work); + if (ts->himax_wq != NULL) + destroy_workqueue(ts->himax_wq); + I("%s: polling mode destroyed", __func__); + } + + return ret; +} + +static int himax_common_suspend(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + + I("%s: enter\n", __func__); + himax_chip_common_suspend(ts); + return 0; +} + +static int himax_common_resume(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + + I("%s: enter\n", __func__); + himax_chip_common_resume(ts); + return 0; +} + +#if defined(CONFIG_FB) +int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct himax_ts_data *ts = + container_of(self, struct himax_ts_data, fb_notif); + + + I(" %s\n", __func__); + + if (evdata && evdata->data && event == FB_EVENT_BLANK && ts && + ts->client) { + blank = evdata->data; + + switch (*blank) { + case FB_BLANK_UNBLANK: + himax_common_resume(&ts->client->dev); + break; + case FB_BLANK_POWERDOWN: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_NORMAL: + himax_common_suspend(&ts->client->dev); + break; + } + } + + return 0; +} +#endif + +int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + int ret = 0; + struct himax_ts_data *ts; + + I("%s:Enter\n", __func__); + + /* Check I2C functionality */ + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + E("%s: i2c check functionality error\n", __func__); + ret = -ENODEV; + goto err_check_functionality_failed; + } + + ts = kzalloc(sizeof(struct himax_ts_data), GFP_KERNEL); + if (ts == NULL) { + E("%s: allocate himax_ts_data failed\n", __func__); + ret = -ENOMEM; + goto err_alloc_data_failed; + } + + i2c_set_clientdata(client, ts); + ts->client = client; + ts->dev = &client->dev; + mutex_init(&ts->rw_lock); + private_ts = ts; + + ret = himax_chip_common_init(); + +err_alloc_data_failed: +err_check_functionality_failed: + + return ret; +} + +int himax_chip_common_remove(struct i2c_client *client) +{ + if (g_hx_chip_inited) + himax_chip_common_deinit(); + + return 0; +} + +static const struct i2c_device_id himax_common_ts_id[] = { + {HIMAX_common_NAME, 0 }, + {} +}; + +static const struct dev_pm_ops himax_common_pm_ops = { +#if (!defined(CONFIG_FB)) + .suspend = himax_common_suspend, + .resume = himax_common_resume, +#endif +}; + +#ifdef CONFIG_OF +static const struct of_device_id himax_match_table[] = { + {.compatible = "himax,hxcommon" }, + {}, +}; +#else +#define himax_match_table NULL +#endif + +static struct i2c_driver himax_common_driver = { + .id_table = himax_common_ts_id, + .probe = himax_chip_common_probe, + .remove = himax_chip_common_remove, + .driver = { + .name = HIMAX_common_NAME, + .owner = THIS_MODULE, + .of_match_table = himax_match_table, +#ifdef CONFIG_PM + .pm = &himax_common_pm_ops, +#endif + }, +}; + +static int __init himax_common_init(void) +{ + I("Himax common touch panel driver init\n"); + D("Himax check double loading\n"); + if (g_mmi_refcnt++ > 0) { + + I("Himax driver has been loaded! ignoring....\n"); + + return 0; + } + i2c_add_driver(&himax_common_driver); + + return 0; +} + +static void __exit himax_common_exit(void) +{ + i2c_del_driver(&himax_common_driver); +} + +module_init(himax_common_init); +module_exit(himax_common_exit); + +MODULE_DESCRIPTION("Himax_common driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_I2C.h b/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_I2C.h new file mode 100644 index 000000000000..f45c28f9e9b8 --- /dev/null +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_I2C.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for QCT platform + * + * 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. + */ + +#ifndef HIMAX_PLATFORM_H +#define HIMAX_PLATFORM_H + +#include "himax_common.h" + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_HMX_DB) + #include +#endif + + +#define HIMAX_I2C_RETRY_TIMES 3 + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) +#define D(x...) pr_debug("[HXTP] " x) +#define I(x...) pr_info("[HXTP] " x) +#define W(x...) pr_warn("[HXTP][WARNING] " x) +#define E(x...) pr_err("[HXTP][ERROR] " x) +#define DIF(x...) \ +do { \ + if (debug_flag) \ + pr_debug("[HXTP][DEBUG] " x) \ + } while (0) +#else + +#define D(x...) +#define I(x...) +#define W(x...) +#define E(x...) +#define DIF(x...) +#endif + +#if defined(CONFIG_HMX_DB) + + /* Analog voltage @2.7 V */ + #define HX_VTG_MIN_UV 2700000 + #define HX_VTG_MAX_UV 3300000 + #define HX_ACTIVE_LOAD_UA 15000 + #define HX_LPM_LOAD_UA 10 + /* Digital voltage @1.8 V */ + #define HX_VTG_DIG_MIN_UV 1800000 + #define HX_VTG_DIG_MAX_UV 1800000 + #define HX_ACTIVE_LOAD_DIG_UA 10000 + #define HX_LPM_LOAD_DIG_UA 10 + #define HX_I2C_VTG_MIN_UV 1800000 + #define HX_I2C_VTG_MAX_UV 1800000 + #define HX_I2C_LOAD_UA 10000 + #define HX_I2C_LPM_LOAD_UA 10 + +#endif + +#define HIMAX_common_NAME "himax_tp" +#define HIMAX_I2C_ADDR 0x48 +#define INPUT_DEV_NAME "himax-touchscreen" + +struct himax_i2c_platform_data { + int abs_x_min; + int abs_x_max; + int abs_x_fuzz; + int abs_y_min; + int abs_y_max; + int abs_y_fuzz; + int abs_pressure_min; + int abs_pressure_max; + int abs_pressure_fuzz; + int abs_width_min; + int abs_width_max; + int screenWidth; + int screenHeight; + uint8_t fw_version; + uint8_t tw_id; + uint8_t powerOff3V3; + uint8_t cable_config[2]; + uint8_t protocol_type; + int gpio_irq; + int gpio_reset; + int gpio_3v3_en; + int gpio_pon; + int (*power)(int on); + void (*reset)(void); + struct himax_virtual_key *virtual_key; + struct kobject *vk_obj; + struct kobj_attribute *vk2Use; + int hx_config_size; + +#if defined(CONFIG_HMX_DB) + bool i2c_pull_up; + bool digital_pwr_regulator; + int reset_gpio; + u32 reset_gpio_flags; + int irq_gpio; + u32 irq_gpio_flags; + struct regulator *vcc_ana; /* For Dragon Board */ + struct regulator *vcc_dig; /* For Dragon Board */ + struct regulator *vcc_i2c; /* For Dragon Board */ + +#endif + +}; + +extern int irq_enable_count; +extern int himax_bus_read(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry); +extern int himax_bus_write(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry); +extern int himax_bus_write_command(uint8_t command, uint8_t toRetry); +extern int himax_bus_master_write(uint8_t *data, uint32_t length, uint8_t toRetry); +extern void himax_int_enable(int enable); +extern int himax_ts_register_interrupt(void); +int himax_ts_unregister_interrupt(void); +extern uint8_t himax_int_gpio_read(int pinnum); +extern int himax_gpio_power_config(struct himax_i2c_platform_data *pdata); +void himax_gpio_power_deconfig(struct himax_i2c_platform_data *pdata); + +#if defined(CONFIG_FB) + extern int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +#endif + +extern void himax_ts_work(struct himax_ts_data *ts); +extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer); +extern int himax_chip_common_init(void); +extern void himax_chip_common_deinit(void); + +#endif + diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_platform.c b/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_SPI.c old mode 100644 new mode 100755 similarity index 69% rename from drivers/input/touchscreen/himax_v3_mmi/himax_platform.c rename to drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_SPI.c index eaae9ce4a712..5e8896d88f92 --- a/drivers/input/touchscreen/himax_v3_mmi/himax_platform.c +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_SPI.c @@ -1,1130 +1,1160 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for QCT platform - * - * 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_platform.h" -#include "himax_common.h" - -int i2c_error_count; -struct spi_device *spi; - -static uint8_t *gBuffer; - -int himax_dev_set(struct himax_ts_data *ts) -{ - int ret = 0; - - ts->input_dev = input_allocate_device(); - - if (ts->input_dev == NULL) { - ret = -ENOMEM; - E("%s: Failed to allocate input device\n", __func__); - return ret; - } - - ts->input_dev->name = "himax-touchscreen"; - - if (!ic_data->HX_PEN_FUNC) - goto skip_pen_operation; - - ts->hx_pen_dev = input_allocate_device(); - - if (ts->hx_pen_dev == NULL) { - ret = -ENOMEM; - E("%s: Failed to allocate input device-hx_pen_dev\n", __func__); - return ret; - } - - ts->hx_pen_dev->name = "himax-pen"; -skip_pen_operation: - - return ret; -} -int himax_input_register_device(struct input_dev *input_dev) -{ - return input_register_device(input_dev); -} - -void himax_vk_parser(struct device_node *dt, - struct himax_i2c_platform_data *pdata) -{ - u32 data = 0; - uint8_t cnt = 0, i = 0; - uint32_t coords[4] = {0}; - struct device_node *node, *pp = NULL; - struct himax_virtual_key *vk; - - node = of_parse_phandle(dt, "virtualkey", 0); - - if (node == NULL) { - I(" DT-No vk info in DT\n"); - return; - } - while ((pp = of_get_next_child(node, pp))) - cnt++; - - if (!cnt) - return; - - vk = kcalloc(cnt, sizeof(struct himax_virtual_key), GFP_KERNEL); - if (vk == NULL) { - E("%s, vk init fail!\n", __func__); - return; - } - pp = NULL; - - while ((pp = of_get_next_child(node, pp))) { - if (of_property_read_u32(pp, "idx", &data) == 0) - vk[i].index = data; - - if (of_property_read_u32_array(pp, "range", coords, 4) == 0) { - vk[i].x_range_min = coords[0]; - vk[i].x_range_max = coords[1]; - vk[i].y_range_min = coords[2]; - vk[i].y_range_max = coords[3]; - } else { - I(" range faile\n"); - } - - i++; - } - - pdata->virtual_key = vk; - - for (i = 0; i < cnt; i++) - I(" vk[%d] idx:%d x_min:%d, y_max:%d\n", i, - pdata->virtual_key[i].index, - pdata->virtual_key[i].x_range_min, - pdata->virtual_key[i].y_range_max); - -} - -int himax_parse_dt(struct himax_ts_data *ts, - struct himax_i2c_platform_data *pdata) -{ - int rc, coords_size = 0; - uint32_t coords[4] = {0}; - struct property *prop; - struct device_node *dt = ts->dev->of_node; - u32 data = 0; - int ret = 0; - - prop = of_find_property(dt, "himax,panel-coords", NULL); - - if (prop) { - coords_size = prop->length / sizeof(u32); - - if (coords_size != 4) - D(" %s:Invalid panel coords size %d\n", - __func__, coords_size); - } - - ret = of_property_read_u32_array(dt, "himax,panel-coords", - coords, coords_size); - if (ret == 0) { - pdata->abs_x_min = coords[0]; - pdata->abs_x_max = (coords[1] - 1); - pdata->abs_y_min = coords[2]; - pdata->abs_y_max = (coords[3] - 1); - I(" DT-%s:panel-coords = %d, %d, %d, %d\n", __func__, - pdata->abs_x_min, - pdata->abs_x_max, - pdata->abs_y_min, - pdata->abs_y_max); - } - - prop = of_find_property(dt, "himax,display-coords", NULL); - - if (prop) { - coords_size = prop->length / sizeof(u32); - - if (coords_size != 4) - D(" %s:Invalid display coords size %d\n", - __func__, coords_size); - } - - rc = of_property_read_u32_array(dt, "himax,display-coords", - coords, coords_size); - - if (rc && (rc != -EINVAL)) { - D(" %s:Fail to read display-coords %d\n", __func__, rc); - return rc; - } - - pdata->screenWidth = coords[1]; - pdata->screenHeight = coords[3]; - I(" DT-%s:display-coords = (%d, %d)\n", __func__, - pdata->screenWidth, - pdata->screenHeight); - pdata->gpio_irq = of_get_named_gpio(dt, "himax,irq-gpio", 0); - - if (!gpio_is_valid(pdata->gpio_irq)) - I(" DT:gpio_irq value is not valid\n"); - - - pdata->gpio_reset = of_get_named_gpio(dt, "himax,rst-gpio", 0); - - if (!gpio_is_valid(pdata->gpio_reset)) - I(" DT:gpio_rst value is not valid\n"); - - pdata->gpio_3v3_en = of_get_named_gpio(dt, "himax,3v3-gpio", 0); - - if (!gpio_is_valid(pdata->gpio_3v3_en)) - I(" DT:gpio_3v3_en value is not valid\n"); - - I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d\n", - pdata->gpio_irq, - pdata->gpio_reset, - pdata->gpio_3v3_en); - - if (of_property_read_u32(dt, "report_type", &data) == 0) { - pdata->protocol_type = data; - I(" DT:protocol_type=%d\n", pdata->protocol_type); - } - - himax_vk_parser(dt, pdata); - return 0; -} -EXPORT_SYMBOL(himax_parse_dt); - -static ssize_t himax_spi_sync(struct himax_ts_data *ts, - struct spi_message *message) -{ - int status; - - status = spi_sync(ts->spi, message); - - if (status == 0) { - status = message->status; - if (status == 0) - status = message->actual_length; - } - return status; -} - -static int himax_spi_read(uint8_t *command, uint8_t command_len, - uint8_t *data, uint32_t length, uint8_t toRetry) -{ - struct spi_message message; - struct spi_transfer xfer[2]; - int retry; - int error; - - spi_message_init(&message); - memset(xfer, 0, sizeof(xfer)); - - xfer[0].tx_buf = command; - xfer[0].len = command_len; - spi_message_add_tail(&xfer[0], &message); - - xfer[1].rx_buf = data; - xfer[1].len = length; - spi_message_add_tail(&xfer[1], &message); - - for (retry = 0; retry < toRetry; retry++) { - error = spi_sync(private_ts->spi, &message); - if (unlikely(error)) - E("SPI read error: %d\n", error); - else - break; - } - - if (retry == toRetry) { - E("%s: SPI read error retry over %d\n", - __func__, toRetry); - return -EIO; - } - - return 0; -} - -static int himax_spi_write(uint8_t *buf, uint32_t length) -{ - - struct spi_transfer t = { - .tx_buf = buf, - .len = length, - }; - struct spi_message m; - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - - return himax_spi_sync(private_ts, &m); - -} - -int himax_bus_read(uint8_t command, uint8_t *data, - uint32_t length, uint8_t toRetry) -{ - int result = 0; - uint8_t spi_format_buf[3]; - - mutex_lock(&(private_ts->rw_lock)); - spi_format_buf[0] = 0xF3; - spi_format_buf[1] = command; - spi_format_buf[2] = 0x00; - - result = himax_spi_read(&spi_format_buf[0], 3, data, length, toRetry); - mutex_unlock(&(private_ts->rw_lock)); - - return result; -} -EXPORT_SYMBOL(himax_bus_read); - -int himax_bus_write(uint8_t command, uint8_t *data, - uint32_t length, uint8_t toRetry) -{ - uint8_t *spi_format_buf = gBuffer; - int i = 0; - int result = 0; - - mutex_lock(&(private_ts->rw_lock)); - spi_format_buf[0] = 0xF2; - spi_format_buf[1] = command; - - for (i = 0; i < length; i++) - spi_format_buf[i + 2] = data[i]; - - result = himax_spi_write(spi_format_buf, length + 2); - mutex_unlock(&(private_ts->rw_lock)); - - return result; -} -EXPORT_SYMBOL(himax_bus_write); - -int himax_bus_write_command(uint8_t command, uint8_t toRetry) -{ - return himax_bus_write(command, NULL, 0, toRetry); -} - -void himax_int_enable(int enable) -{ - struct himax_ts_data *ts = private_ts; - unsigned long irqflags = 0; - int irqnum = ts->hx_irq; - - spin_lock_irqsave(&ts->irq_lock, irqflags); - I("%s: Entering! irqnum = %d\n", __func__, irqnum); - if (enable == 1 && atomic_read(&ts->irq_state) == 0) { - atomic_set(&ts->irq_state, 1); - enable_irq(irqnum); - private_ts->irq_enabled = 1; - } else if (enable == 0 && atomic_read(&ts->irq_state) == 1) { - atomic_set(&ts->irq_state, 0); - disable_irq_nosync(irqnum); - private_ts->irq_enabled = 0; - } - - I("enable = %d\n", enable); - spin_unlock_irqrestore(&ts->irq_lock, irqflags); -} -EXPORT_SYMBOL(himax_int_enable); - -#if defined(HX_RST_PIN_FUNC) -void himax_rst_gpio_set(int pinnum, uint8_t value) -{ - gpio_direction_output(pinnum, value); -} -EXPORT_SYMBOL(himax_rst_gpio_set); -#endif - -uint8_t himax_int_gpio_read(int pinnum) -{ - return gpio_get_value(pinnum); -} - -#if defined(CONFIG_HMX_DB) -static int himax_regulator_configure(struct himax_i2c_platform_data *pdata) -{ - int retval; - /* struct i2c_client *client = private_ts->client; */ - - pdata->vcc_dig = regulator_get(private_ts->dev, "vdd"); - - if (IS_ERR(pdata->vcc_dig)) { - E("%s: Failed to get regulator vdd\n", - __func__); - retval = PTR_ERR(pdata->vcc_dig); - return retval; - } - - pdata->vcc_ana = regulator_get(private_ts->dev, "avdd"); - - if (IS_ERR(pdata->vcc_ana)) { - E("%s: Failed to get regulator avdd\n", - __func__); - retval = PTR_ERR(pdata->vcc_ana); - regulator_put(pdata->vcc_dig); - return retval; - } - - return 0; -}; - -static void himax_regulator_deinit(struct himax_i2c_platform_data *pdata) -{ - I("%s: entered.\n", __func__); - - if (!IS_ERR(pdata->vcc_ana)) - regulator_put(pdata->vcc_ana); - - if (!IS_ERR(pdata->vcc_dig)) - regulator_put(pdata->vcc_dig); - - I("%s: regulator put, completed.\n", __func__); -}; - -static int himax_power_on(struct himax_i2c_platform_data *pdata, bool on) -{ - int retval; - - if (on) { - retval = regulator_enable(pdata->vcc_dig); - - if (retval) { - E("%s: Failed to enable regulator vdd\n", - __func__); - return retval; - } - - /*msleep(100);*/ - usleep_range(1000, 1001); - retval = regulator_enable(pdata->vcc_ana); - - if (retval) { - E("%s: Failed to enable regulator avdd\n", - __func__); - regulator_disable(pdata->vcc_dig); - return retval; - } - } else { - regulator_disable(pdata->vcc_dig); - regulator_disable(pdata->vcc_ana); - } - - return 0; -} - -int himax_gpio_power_config(struct himax_i2c_platform_data *pdata) -{ - int error; - /* struct i2c_client *client = private_ts->client; */ - - error = himax_regulator_configure(pdata); - - if (error) { - E("Failed to intialize hardware\n"); - goto err_regulator_not_on; - } - -#if defined(HX_RST_PIN_FUNC) - - if (gpio_is_valid(pdata->gpio_reset)) { - /* configure touchscreen reset out gpio */ - error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio"); - - if (error) { - E("unable to request gpio [%d]\n", pdata->gpio_reset); - goto err_regulator_on; - } - - error = gpio_direction_output(pdata->gpio_reset, 0); - - if (error) { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_reset); - goto err_gpio_reset_req; - } - } - -#endif - error = himax_power_on(pdata, true); - - if (error) { - E("Failed to power on hardware\n"); - goto err_power_on; - } - - if (gpio_is_valid(pdata->gpio_irq)) { - /* configure touchscreen irq gpio */ - error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq"); - - if (error) { - E("unable to request gpio [%d]\n", - pdata->gpio_irq); - goto err_req_irq_gpio; - } - - error = gpio_direction_input(pdata->gpio_irq); - - if (error) { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_irq); - goto err_set_gpio_irq; - } - - private_ts->hx_irq = gpio_to_irq(pdata->gpio_irq); - } else { - E("irq gpio not provided\n"); - goto err_req_irq_gpio; - } - - /*msleep(20);*/ - usleep_range(2000, 2001); -#if defined(HX_RST_PIN_FUNC) - - if (gpio_is_valid(pdata->gpio_reset)) { - error = gpio_direction_output(pdata->gpio_reset, 1); - - if (error) { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_reset); - goto err_set_gpio_irq; - } - } - -#endif - return 0; -err_set_gpio_irq: - - if (gpio_is_valid(pdata->gpio_irq)) - gpio_free(pdata->gpio_irq); - -err_req_irq_gpio: - himax_power_on(pdata, false); -err_power_on: -#if defined(HX_RST_PIN_FUNC) -err_gpio_reset_req: - if (gpio_is_valid(pdata->gpio_reset)) - gpio_free(pdata->gpio_reset); - -err_regulator_on: -#endif - himax_regulator_deinit(pdata); -err_regulator_not_on: - return error; -} - -#else -int himax_gpio_power_config(struct himax_i2c_platform_data *pdata) -{ - int error = 0; - /* struct i2c_client *client = private_ts->client; */ -#if defined(HX_RST_PIN_FUNC) - - if (pdata->gpio_reset >= 0) { - error = gpio_request(pdata->gpio_reset, "himax-reset"); - - if (error < 0) { - E("%s: request reset pin failed\n", __func__); - goto err_gpio_reset_req; - } - - error = gpio_direction_output(pdata->gpio_reset, 0); - - if (error) { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_reset); - goto err_gpio_reset_dir; - } - } - -#endif - -#if defined(HX_PON_PIN_SUPPORT) - if (gpio_is_valid(pdata->gpio_pon)) { - error = gpio_request(pdata->gpio_pon, "hmx_pon_gpio"); - - if (error) { - E("unable to request scl gpio [%d]\n", pdata->gpio_pon); - goto err_gpio_pon_req; - } - - error = gpio_direction_output(pdata->gpio_pon, 0); - - I("gpio_pon LOW [%d]\n", pdata->gpio_pon); - - if (error) { - E("unable to set direction for pon gpio [%d]\n", - pdata->gpio_pon); - goto err_gpio_pon_dir; - } - } -#endif - - - if (pdata->gpio_3v3_en >= 0) { - error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en"); - - if (error < 0) { - E("%s: request 3v3_en pin failed\n", __func__); - goto err_gpio_3v3_req; - } - - gpio_direction_output(pdata->gpio_3v3_en, 1); - I("3v3_en set 1 get pin = %d\n", - gpio_get_value(pdata->gpio_3v3_en)); - } - - if (gpio_is_valid(pdata->gpio_irq)) { - /* configure touchscreen irq gpio */ - error = gpio_request(pdata->gpio_irq, "himax_gpio_irq"); - - if (error) { - E("unable to request gpio [%d]\n", pdata->gpio_irq); - goto err_gpio_irq_req; - } - - error = gpio_direction_input(pdata->gpio_irq); - - if (error) { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_irq); - goto err_gpio_irq_set_input; - } - - private_ts->hx_irq = gpio_to_irq(pdata->gpio_irq); - } else { - E("irq gpio not provided\n"); - goto err_gpio_irq_req; - } -#if defined(HX_PON_PIN_SUPPORT) - msleep(20); -#else - usleep_range(2000, 2001); -#endif - -#if defined(HX_RST_PIN_FUNC) - - if (pdata->gpio_reset >= 0) { - error = gpio_direction_output(pdata->gpio_reset, 1); - - if (error) { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_reset); - goto err_gpio_reset_set_high; - } - } -#endif - -#if defined(HX_PON_PIN_SUPPORT) - msleep(800); - - if (gpio_is_valid(pdata->gpio_pon)) { - - error = gpio_direction_output(pdata->gpio_pon, 1); - - I("gpio_pon HIGH [%d]\n", pdata->gpio_pon); - - if (error) { - E("gpio_pon unable to set direction for gpio [%d]\n", - pdata->gpio_pon); - goto err_gpio_pon_set_high; - } - } -#endif - return error; - -#if defined(HX_PON_PIN_SUPPORT) -err_gpio_pon_set_high: -#endif -#if defined(HX_RST_PIN_FUNC) -err_gpio_reset_set_high: -#endif -err_gpio_irq_set_input: - if (gpio_is_valid(pdata->gpio_irq)) - gpio_free(pdata->gpio_irq); -err_gpio_irq_req: - if (pdata->gpio_3v3_en >= 0) - gpio_free(pdata->gpio_3v3_en); -err_gpio_3v3_req: -#if defined(HX_PON_PIN_SUPPORT) -err_gpio_pon_dir: - if (gpio_is_valid(pdata->gpio_pon)) - gpio_free(pdata->gpio_pon); -err_gpio_pon_req: -#endif -#if defined(HX_RST_PIN_FUNC) -err_gpio_reset_dir: - if (pdata->gpio_reset >= 0) - gpio_free(pdata->gpio_reset); -err_gpio_reset_req: -#endif - return error; -} - -#endif - -void himax_gpio_power_deconfig(struct himax_i2c_platform_data *pdata) -{ - if (gpio_is_valid(pdata->gpio_irq)) - gpio_free(pdata->gpio_irq); - -#if defined(HX_RST_PIN_FUNC) - if (gpio_is_valid(pdata->gpio_reset)) - gpio_free(pdata->gpio_reset); -#endif - -#if defined(CONFIG_HMX_DB) - himax_power_on(pdata, false); - himax_regulator_deinit(pdata); -#else - if (pdata->gpio_3v3_en >= 0) - gpio_free(pdata->gpio_3v3_en); - -#if defined(HX_PON_PIN_SUPPORT) - if (gpio_is_valid(pdata->gpio_pon)) - gpio_free(pdata->gpio_pon); -#endif - -#endif -} - -static void himax_ts_isr_func(struct himax_ts_data *ts) -{ - himax_ts_work(ts); -} - -irqreturn_t himax_ts_thread(int irq, void *ptr) -{ - himax_ts_isr_func((struct himax_ts_data *)ptr); - - return IRQ_HANDLED; -} - -static void himax_ts_work_func(struct work_struct *work) -{ - struct himax_ts_data *ts = container_of(work, - struct himax_ts_data, work); - - himax_ts_work(ts); -} - -int himax_int_register_trigger(void) -{ - int ret = 0; - struct himax_ts_data *ts = private_ts; - - if (ic_data->HX_INT_IS_EDGE) { - I("%s edge triiger falling\n", __func__); - ret = request_threaded_irq(ts->hx_irq, NULL, himax_ts_thread, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - HIMAX_common_NAME, ts); - } else { - I("%s level trigger low\n", __func__); - ret = request_threaded_irq(ts->hx_irq, NULL, himax_ts_thread, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, HIMAX_common_NAME, ts); - } - - return ret; -} - -int himax_int_en_set(void) -{ - int ret = NO_ERR; - - ret = himax_int_register_trigger(); - return ret; -} - -int himax_ts_register_interrupt(void) -{ - struct himax_ts_data *ts = private_ts; - /* struct i2c_client *client = private_ts->client; */ - int ret = 0; - - ts->irq_enabled = 0; - - /* Work functon */ - if (private_ts->hx_irq) {/*INT mode*/ - ts->use_irq = 1; - ret = himax_int_register_trigger(); - - if (ret == 0) { - ts->irq_enabled = 1; - atomic_set(&ts->irq_state, 1); - I("%s: irq enabled at gpio: %d\n", __func__, - private_ts->hx_irq); -#if defined(HX_SMART_WAKEUP) - irq_set_irq_wake(private_ts->hx_irq, 1); -#endif - } else { - ts->use_irq = 0; - E("%s: request_irq failed\n", __func__); - } - } else { - I("%s: private_ts->hx_irq is empty, use polling mode.\n", - __func__); - } - - /*if use polling mode need to disable HX_ESD_RECOVERY function*/ - if (!ts->use_irq) { - ts->himax_wq = create_singlethread_workqueue("himax_touch"); - INIT_WORK(&ts->work, himax_ts_work_func); - hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - ts->timer.function = himax_ts_timer_func; - hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); - I("%s: polling mode enabled\n", __func__); - } - - return ret; -} - -int himax_ts_unregister_interrupt(void) -{ - struct himax_ts_data *ts = private_ts; - int ret = 0; - - I("%s: entered.\n", __func__); - - /* Work functon */ - if (private_ts->hx_irq && ts->use_irq) {/*INT mode*/ -#if defined(HX_SMART_WAKEUP) - irq_set_irq_wake(ts->hx_irq, 0); -#endif - free_irq(ts->hx_irq, ts); - I("%s: irq disabled at qpio: %d\n", __func__, - private_ts->hx_irq); - } - - /*if use polling mode need to disable HX_ESD_RECOVERY function*/ - if (!ts->use_irq) { - hrtimer_cancel(&ts->timer); - cancel_work_sync(&ts->work); - if (ts->himax_wq != NULL) - destroy_workqueue(ts->himax_wq); - I("%s: polling mode destroyed", __func__); - } - - return ret; -} - -static int himax_common_suspend(struct device *dev) -{ - struct himax_ts_data *ts = dev_get_drvdata(dev); - - I("%s: enter\n", __func__); -#if defined(CONFIG_DRM) && !defined(HX_CONFIG_FB) - if (!ts->initialized) - return -ECANCELED; -#endif - himax_chip_common_suspend(ts); - return 0; -} -#if !defined(HX_CONTAINER_SPEED_UP) -static int himax_common_resume(struct device *dev) -{ - struct himax_ts_data *ts = dev_get_drvdata(dev); - - I("%s: enter\n", __func__); -#if defined(CONFIG_DRM) && !defined(HX_CONFIG_FB) - /* - * wait until device resume for TDDI - * TDDI: Touch and display Driver IC - */ - if (!ts->initialized) { - if (himax_chip_common_init()) - return -ECANCELED; - } -#endif - himax_chip_common_resume(ts); - return 0; -} -#endif - -#if defined(HX_CONFIG_FB) -int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct fb_event *evdata = data; - int *blank; - struct himax_ts_data *ts = - container_of(self, struct himax_ts_data, fb_notif); - - I(" %s\n", __func__); - - if (evdata && evdata->data && -#if defined(HX_CONTAINER_SPEED_UP) - event == FB_EARLY_EVENT_BLANK -#else - event == FB_EVENT_BLANK -#endif - && ts != NULL && - ts->dev != NULL) { - blank = evdata->data; - - switch (*blank) { - case FB_BLANK_UNBLANK: -#if defined(HX_CONTAINER_SPEED_UP) - queue_delayed_work(ts->ts_int_workqueue, - &ts->ts_int_work, - msecs_to_jiffies(DELAY_TIME)); -#else - himax_common_resume(ts->dev); -#endif - break; - - case FB_BLANK_POWERDOWN: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_NORMAL: - himax_common_suspend(ts->dev); - break; - } - } - - return 0; -} -#elif defined(CONFIG_DRM) -struct drm_panel *himax_active_panel; -static int check_dt(struct device_node *np) -{ - int i; - int count; - struct device_node *node; - struct drm_panel *panel; - - count = of_count_phandle_with_args(np, "panel", NULL); - if (count <= 0) - return 0; - - for (i = 0; i < count; i++) { - node = of_parse_phandle(np, "panel", i); - panel = of_drm_find_panel(node); - of_node_put(node); - if (!IS_ERR(panel)) { - himax_active_panel = panel; - return 0; - } - } - - return -ENODEV; -} - -static int check_default_tp(struct device_node *dt, const char *prop) -{ - const char *active_tp; - const char *compatible; - char *start; - int ret; - - ret = of_property_read_string(dt->parent, prop, &active_tp); - if (ret) { - pr_err(" %s:fail to read %s %d\n", __func__, prop, ret); - return -ENODEV; - } - - ret = of_property_read_string(dt, "compatible", &compatible); - if (ret < 0) { - pr_err(" %s:fail to read %s %d\n", __func__, "compatible", ret); - return -ENODEV; - } - - start = strnstr(active_tp, compatible, strlen(active_tp)); - if (start == NULL) { - pr_err(" %s:no match compatible, %s, %s\n", - __func__, compatible, active_tp); - ret = -ENODEV; - } - - return ret; -} - -int drm_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct drm_panel_notifier *evdata = data; - int *blank; - struct himax_ts_data *ts = - container_of(self, struct himax_ts_data, fb_notif); - - if (!evdata) - return 0; - - D("DRM %s\n", __func__); - - if (evdata->data - && event == DRM_PANEL_EARLY_EVENT_BLANK - && ts != NULL - && ts->dev != NULL) { - blank = evdata->data; - switch (*blank) { - case DRM_PANEL_BLANK_POWERDOWN: - if (!ts->initialized) - return -ECANCELED; - himax_common_suspend(ts->dev); - break; - } - } - - if (evdata->data - && event == DRM_PANEL_EVENT_BLANK - && ts != NULL - && ts->dev != NULL) { - blank = evdata->data; - switch (*blank) { - case DRM_PANEL_BLANK_UNBLANK: -#if defined(HX_CONTAINER_SPEED_UP) - queue_delayed_work(ts->ts_int_workqueue, - &ts->ts_int_work, - msecs_to_jiffies(DELAY_TIME)); -#else - himax_common_resume(ts->dev); -#endif - break; - } - } - - return 0; -} -#endif - -int himax_chip_common_probe(struct spi_device *spi) -{ - struct himax_ts_data *ts; - int ret = 0; - - I("Enter %s\n", __func__); - if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) { - dev_err(&spi->dev, - "%s: Full duplex not supported by host\n", - __func__); - return -EIO; - } -#ifdef CONFIG_DRM -{ - struct device_node *dp = spi->dev.of_node; - if (check_dt(dp)) { - if (!check_default_tp(dp, "qcom,spi-touch-active")) - ret = -EPROBE_DEFER; - else - ret = -ENODEV; - - return ret; - } -} -#endif - gBuffer = kzalloc(sizeof(uint8_t) * HX_MAX_WRITE_SZ, GFP_KERNEL); - if (gBuffer == NULL) { - E("%s: allocate gBuffer failed\n", __func__); - ret = -ENOMEM; - goto err_alloc_gbuffer_failed; - } - - ts = kzalloc(sizeof(struct himax_ts_data), GFP_KERNEL); - if (ts == NULL) { - E("%s: allocate himax_ts_data failed\n", __func__); - ret = -ENOMEM; - goto err_alloc_data_failed; - } - - private_ts = ts; - spi->bits_per_word = 8; - spi->mode = SPI_MODE_3; - spi->chip_select = 0; - - ts->spi = spi; - mutex_init(&ts->rw_lock); - ts->dev = &spi->dev; - dev_set_drvdata(&spi->dev, ts); - spi_set_drvdata(spi, ts); - - ts->initialized = false; - ret = himax_chip_common_init(); - if (ret < 0) - goto err_common_init_failed; - - return ret; - -err_common_init_failed: - kfree(ts); -err_alloc_data_failed: - kfree(gBuffer); - gBuffer = NULL; -err_alloc_gbuffer_failed: - - return ret; -} - -int himax_chip_common_remove(struct spi_device *spi) -{ - struct himax_ts_data *ts = spi_get_drvdata(spi); - - if (g_hx_chip_inited) - himax_chip_common_deinit(); - - ts->spi = NULL; - /* spin_unlock_irq(&ts->spi_lock); */ - spi_set_drvdata(spi, NULL); - kfree(gBuffer); - - I("%s: completed.\n", __func__); - - return 0; -} - -#if (!defined(HX_CONFIG_FB)) && (!defined(CONFIG_DRM)) -static const struct dev_pm_ops himax_common_pm_ops = { - .suspend = himax_common_suspend, - .resume = himax_common_resume, -}; -#endif - -#if defined(CONFIG_OF) -static const struct of_device_id himax_match_table[] = { - {.compatible = "himax,hxcommon" }, - {}, -}; -#else -#define himax_match_table NULL -#endif - -static struct spi_driver himax_common_driver = { - .driver = { - .name = HIMAX_common_NAME, - .owner = THIS_MODULE, - .of_match_table = himax_match_table, - }, - .probe = himax_chip_common_probe, - .remove = himax_chip_common_remove, -}; - -static int __init himax_common_init(void) -{ - I("Himax common touch panel driver init\n"); - D("Himax check double loading\n"); - if (g_mmi_refcnt++ > 0) { - I("Himax driver has been loaded! ignoring....\n"); - return 0; - } - spi_register_driver(&himax_common_driver); - - return 0; -} - -static void __exit himax_common_exit(void) -{ - if (spi) { - spi_unregister_device(spi); - spi = NULL; - } - spi_unregister_driver(&himax_common_driver); -} - -module_init(himax_common_init); -module_exit(himax_common_exit); - -MODULE_DESCRIPTION("Himax_common driver"); -MODULE_LICENSE("GPL"); +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for QCT platform + * + * 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_platform.h" +#include "himax_common.h" + +int i2c_error_count; +int irq_enable_count; +EXPORT_SYMBOL(irq_enable_count); +struct spi_device *spi; + +static uint8_t *gBuffer; + +int himax_dev_set(struct himax_ts_data *ts) +{ + int ret = 0; + + ts->input_dev = input_allocate_device(); + + if (ts->input_dev == NULL) { + ret = -ENOMEM; + E("%s: Failed to allocate input device\n", __func__); + return ret; + } + + ts->input_dev->name = "himax-touchscreen"; + return ret; +} +int himax_input_register_device(struct input_dev *input_dev) +{ + return input_register_device(input_dev); +} + +#if defined(HX_PLATFOME_DEFINE_KEY) +void himax_platform_key(void) +{ + I("Nothing to be done! Plz cancel it!\n"); +} +#endif + +void himax_vk_parser(struct device_node *dt, + struct himax_i2c_platform_data *pdata) +{ + u32 data = 0; + uint8_t cnt = 0, i = 0; + uint32_t coords[4] = {0}; + struct device_node *node, *pp = NULL; + struct himax_virtual_key *vk; + + node = of_parse_phandle(dt, "virtualkey", 0); + + if (node == NULL) { + I(" DT-No vk info in DT\n"); + return; + } + while ((pp = of_get_next_child(node, pp))) + cnt++; + + if (!cnt) + return; + + vk = kcalloc(cnt, sizeof(struct himax_virtual_key), GFP_KERNEL); + if (vk == NULL) { + E("%s, vk init fail!\n", __func__); + return; + } + pp = NULL; + + while ((pp = of_get_next_child(node, pp))) { + if (of_property_read_u32(pp, "idx", &data) == 0) + vk[i].index = data; + + if (of_property_read_u32_array(pp, "range", coords, 4) == 0) { + vk[i].x_range_min = coords[0], vk[i].x_range_max = coords[1]; + vk[i].y_range_min = coords[2], vk[i].y_range_max = coords[3]; + } else { + I(" range faile\n"); + } + + i++; + } + + pdata->virtual_key = vk; + + for (i = 0; i < cnt; i++) + I(" vk[%d] idx:%d x_min:%d, y_max:%d\n", i, pdata->virtual_key[i].index, + pdata->virtual_key[i].x_range_min, pdata->virtual_key[i].y_range_max); + kfree(vk); +} + +int himax_parse_dt(struct himax_ts_data *ts, + struct himax_i2c_platform_data *pdata) +{ + int rc, coords_size = 0; + int touch_info_size = 0; + uint32_t coords[4] = {0}; + uint32_t touch_info[8] = {0}; + struct property *prop; + struct device_node *chosen, *dt = ts->dev->of_node; + u32 data = 0; + + prop = of_find_property(dt, "himax,panel-coords", NULL); + + if (prop) { + coords_size = prop->length / sizeof(u32); + + if (coords_size != 4) + D(" %s:Invalid panel coords size %d\n", __func__, coords_size); + } + + if (of_property_read_u32_array(dt, "himax,panel-coords", coords, coords_size) == 0) { + pdata->abs_x_min = coords[0], pdata->abs_x_max = (coords[1] - 1); + pdata->abs_y_min = coords[2], pdata->abs_y_max = (coords[3] - 1); + I(" DT-%s:panel-coords = %d, %d, %d, %d\n", __func__, pdata->abs_x_min, + pdata->abs_x_max, pdata->abs_y_min, pdata->abs_y_max); + } + + prop = of_find_property(dt, "himax,display-coords", NULL); + + if (prop) { + coords_size = prop->length / sizeof(u32); + + if (coords_size != 4) + D(" %s:Invalid display coords size %d\n", __func__, coords_size); + } + + rc = of_property_read_u32_array(dt, "himax,display-coords", coords, coords_size); + + if (rc && (rc != -EINVAL)) { + D(" %s:Fail to read display-coords %d\n", __func__, rc); + return rc; + } + + pdata->screenWidth = coords[1]; + pdata->screenHeight = coords[3]; + I(" DT-%s:display-coords = (%d, %d)\n", __func__, pdata->screenWidth, + pdata->screenHeight); + pdata->gpio_irq = of_get_named_gpio(dt, "himax,irq-gpio", 0); + + if (!gpio_is_valid(pdata->gpio_irq)) + I(" DT:gpio_irq value is not valid\n"); + + prop = of_find_property(dt, "himax,touch_info", NULL); + if (prop) { + touch_info_size = prop->length / sizeof(u32); + if (touch_info_size != 8) { + D(" %s:Invalid touch_info size %d\n", __func__, touch_info_size); + } else { + rc = of_property_read_u32_array(dt, "himax,touch_info", touch_info, touch_info_size); + if (rc && (rc != -EINVAL)) { + D(" %s:Fail to read touch_info %d\n", __func__, rc); + } else { + ic_data->HX_RX_NUM = touch_info[0]; + ic_data->HX_TX_NUM = touch_info[1]; + ic_data->HX_BT_NUM = touch_info[2]; + ic_data->HX_X_RES = touch_info[3]; + ic_data->HX_Y_RES = touch_info[4]; + ic_data->HX_MAX_PT = touch_info[5]; + ic_data->HX_XY_REVERSE = touch_info[6]; + ic_data->HX_INT_IS_EDGE = touch_info[7]; + D(" %s:success to read touch_info from dts \n", __func__); + } + } + } + + I(" DT-%s:touch_info: HX_RX_NUM = %d, HX_TX_NUM = %d, HX_BT_NUM = %d,HX_X_RES = %d,HX_Y_RES = %d, HX_MAX_PT = %d, HX_XY_REVERSE = %d, HX_INT_IS_EDGE = %d\n", __func__, + ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_BT_NUM,ic_data->HX_X_RES,ic_data->HX_Y_RES,ic_data->HX_MAX_PT,ic_data->HX_XY_REVERSE,ic_data->HX_INT_IS_EDGE); + + + pdata->gpio_reset = of_get_named_gpio(dt, "himax,rst-gpio", 0); + + if (!gpio_is_valid(pdata->gpio_reset)) + I(" DT:gpio_rst value is not valid\n"); + + pdata->gpio_3v3_en = of_get_named_gpio(dt, "himax,3v3-gpio", 0); + + if (!gpio_is_valid(pdata->gpio_3v3_en)) + I(" DT:gpio_3v3_en value is not valid\n"); + + I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d\n", pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en); + + if (of_property_read_u32(dt, "report_type", &data) == 0) { + pdata->protocol_type = data; + I(" DT:protocol_type=%d\n", pdata->protocol_type); + } + + ts->vdd_1v8_always_on = of_property_read_bool(dt, "himax,vdd_1v8_always_on"); + if (ts->vdd_1v8_always_on){ + I(" DT:vdd_1v8_always_on=%d\n", ts->vdd_1v8_always_on); + } + + himax_vk_parser(dt, pdata); + + chosen = of_find_node_by_name(NULL, "chosen"); + if (chosen) { + const char *supplier; + char *s, *d; + int rc; + + rc = of_property_read_string(chosen, "mmi,panel_name", + (const char **)&supplier); + if (rc) { + I("%s: cannot read mmi,panel_name %d\n", + __func__, rc); + } else { + I( "%s: mmi,panel_name %s\n", __func__, supplier); + + /* skip dsi_ part */ + s = (char *)supplier; + d = pdata->panel_supplier; + while (*s != '_') *d++ = *s++; + + I("%s: panel-supplier %s\n", __func__, pdata->panel_supplier); + } + of_node_put(chosen); + } + + return 0; +} +EXPORT_SYMBOL(himax_parse_dt); + +static ssize_t himax_spi_sync(struct himax_ts_data *ts, struct spi_message *message) +{ + int status; + + status = spi_sync(ts->spi, message); + + if (status == 0) { + status = message->status; + if (status == 0) + status = message->actual_length; + } + return status; +} + +static int himax_spi_read(uint8_t *command, uint8_t command_len, uint8_t *data, uint32_t length, uint8_t toRetry) +{ + struct spi_message message; + struct spi_transfer xfer[2]; + int retry; + int error; + + spi_message_init(&message); + memset(xfer, 0, sizeof(xfer)); + + xfer[0].tx_buf = command; + xfer[0].len = command_len; + spi_message_add_tail(&xfer[0], &message); + + xfer[1].rx_buf = data; + xfer[1].len = length; + spi_message_add_tail(&xfer[1], &message); + + for (retry = 0; retry < toRetry; retry++) { + error = spi_sync(private_ts->spi, &message); + if (unlikely(error)) + E("SPI read error: %d\n", error); + else + break; + } + + if (retry == toRetry) { + E("%s: SPI read error retry over %d\n", + __func__, toRetry); + return -EIO; + } + + return 0; +} + +static int himax_spi_write(uint8_t *buf, uint32_t length) +{ +/* + struct spi_transfer t = { + .tx_buf = buf, + .len = length, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + + return himax_spi_sync(private_ts, &m); +*/ + struct spi_transfer t; + struct spi_message m; + + memset(&t, 0, sizeof(struct spi_transfer)); + t.tx_buf = buf; + t.len = length; + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return himax_spi_sync(private_ts, &m); +} + +int himax_bus_read(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry) +{ + int result = 0; + uint8_t spi_format_buf[3]; + + mutex_lock(&(private_ts->spi_lock)); + spi_format_buf[0] = 0xF3; + spi_format_buf[1] = command; + spi_format_buf[2] = 0x00; + + result = himax_spi_read(&spi_format_buf[0], 3, data, length, toRetry); + mutex_unlock(&(private_ts->spi_lock)); + + return result; +} +EXPORT_SYMBOL(himax_bus_read); + +int himax_bus_write(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry) +{ + uint8_t *spi_format_buf = gBuffer; + int i = 0; + int result = 0; + + memset(spi_format_buf, 0, GBUFFER_SZ * sizeof(uint8_t)); + mutex_lock(&(private_ts->spi_lock)); + spi_format_buf[0] = 0xF2; + spi_format_buf[1] = command; + + for (i = 0; i < length; i++) + spi_format_buf[i + 2] = data[i]; + + result = himax_spi_write(spi_format_buf, length + 2); + mutex_unlock(&(private_ts->spi_lock)); + + return result; +} +EXPORT_SYMBOL(himax_bus_write); + +int himax_bus_write_command(uint8_t command, uint8_t toRetry) +{ + return himax_bus_write(command, NULL, 0, toRetry); +} + +int himax_bus_master_write(uint8_t *data, uint32_t length, uint8_t toRetry) +{ + uint8_t *buf = NULL; + + struct spi_transfer t = { + .tx_buf = buf, + .len = length, + }; + struct spi_message m; + int result = 0; + + buf = kcalloc(length, sizeof(uint8_t), GFP_KERNEL); + if (buf == NULL) { + E("%s, Allocate buf failed!\n", __func__); + return -MEM_ALLOC_FAIL; + } + + mutex_lock(&(private_ts->spi_lock)); + memcpy(buf, data, length); + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + result = himax_spi_sync(private_ts, &m); + mutex_unlock(&(private_ts->spi_lock)); + kfree(buf); + + return result; +} +EXPORT_SYMBOL(himax_bus_master_write); + +void himax_int_enable(int enable) +{ + int irqnum = 0; + + irqnum = private_ts->hx_irq; + if (enable == 1 && irq_enable_count == 0) { + enable_irq(irqnum); + irq_enable_count = 1; + private_ts->irq_enabled = 1; + } else if (enable == 0 && irq_enable_count == 1) { + disable_irq_nosync(irqnum); + irq_enable_count = 0; + private_ts->irq_enabled = 0; + } + + I("irq_enable_count = %d\n", irq_enable_count); +} +EXPORT_SYMBOL(himax_int_enable); + +#ifdef HX_RST_PIN_FUNC +void himax_rst_gpio_set(int pinnum, uint8_t value) +{ + gpio_direction_output(pinnum, value); +} +EXPORT_SYMBOL(himax_rst_gpio_set); +#endif + +uint8_t himax_int_gpio_read(int pinnum) +{ + return gpio_get_value(pinnum); +} + +#if defined(CONFIG_HMX_DB) +static int himax_regulator_configure(struct himax_i2c_platform_data *pdata) +{ + int retval; + /* struct i2c_client *client = private_ts->client; */ + + pdata->vcc_dig = regulator_get(private_ts->dev, "vdd"); + + if (IS_ERR(pdata->vcc_dig)) { + E("%s: Failed to get regulator vdd\n", + __func__); + retval = PTR_ERR(pdata->vcc_dig); + return retval; + } + + pdata->vcc_ana = regulator_get(private_ts->dev, "avdd"); + + if (IS_ERR(pdata->vcc_ana)) { + E("%s: Failed to get regulator avdd\n", + __func__); + retval = PTR_ERR(pdata->vcc_ana); + regulator_put(pdata->vcc_dig); + return retval; + } + + return 0; +}; + +static void himax_regulator_deinit(struct himax_i2c_platform_data *pdata) +{ + I("%s: entered.\n", __func__); + + if (!IS_ERR(pdata->vcc_ana)) + regulator_put(pdata->vcc_ana); + + if (!IS_ERR(pdata->vcc_dig)) + regulator_put(pdata->vcc_dig); + + I("%s: regulator put, completed.\n", __func__); +}; + +static int himax_power_on(struct himax_i2c_platform_data *pdata, bool on) +{ + int retval; + + if (on) { + retval = regulator_enable(pdata->vcc_dig); + + if (retval) { + E("%s: Failed to enable regulator vdd\n", + __func__); + return retval; + } + + /*msleep(100);*/ + usleep_range(1000, 1001); + retval = regulator_enable(pdata->vcc_ana); + + if (retval) { + E("%s: Failed to enable regulator avdd\n", + __func__); + regulator_disable(pdata->vcc_dig); + return retval; + } + } else { + regulator_disable(pdata->vcc_dig); + regulator_disable(pdata->vcc_ana); + } + + return 0; +} + +int himax_gpio_power_config(struct himax_i2c_platform_data *pdata) +{ + int error; + /* struct i2c_client *client = private_ts->client; */ + + error = himax_regulator_configure(pdata); + + if (error) { + E("Failed to intialize hardware\n"); + goto err_regulator_not_on; + } + +#ifdef HX_RST_PIN_FUNC + + if (gpio_is_valid(pdata->gpio_reset)) { + /* configure touchscreen reset out gpio */ + error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio"); + + if (error) { + E("unable to request gpio [%d]\n", pdata->gpio_reset); + goto err_regulator_on; + } + + error = gpio_direction_output(pdata->gpio_reset, 0); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_reset_req; + } + } + +#endif + error = himax_power_on(pdata, true); + + if (error) { + E("Failed to power on hardware\n"); + goto err_power_on; + } + + if (gpio_is_valid(pdata->gpio_irq)) { + /* configure touchscreen irq gpio */ + error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq"); + + if (error) { + E("unable to request gpio [%d]\n", + pdata->gpio_irq); + goto err_req_irq_gpio; + } + + error = gpio_direction_input(pdata->gpio_irq); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_irq); + goto err_set_gpio_irq; + } + + private_ts->hx_irq = gpio_to_irq(pdata->gpio_irq); + } else { + E("irq gpio not provided\n"); + goto err_req_irq_gpio; + } + + /*msleep(20);*/ + usleep_range(2000, 2001); +#ifdef HX_RST_PIN_FUNC + + if (gpio_is_valid(pdata->gpio_reset)) { + error = gpio_direction_output(pdata->gpio_reset, 1); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_set_gpio_irq; + } + } + +#endif + return 0; +err_set_gpio_irq: + + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); + +err_req_irq_gpio: + himax_power_on(pdata, false); +err_power_on: +#ifdef HX_RST_PIN_FUNC +err_gpio_reset_req: + if (gpio_is_valid(pdata->gpio_reset)) + gpio_free(pdata->gpio_reset); + +err_regulator_on: +#endif + himax_regulator_deinit(pdata); +err_regulator_not_on: + return error; +} + +#else +int himax_gpio_power_config(struct himax_i2c_platform_data *pdata) +{ + int error = 0; + /* struct i2c_client *client = private_ts->client; */ +#ifdef HX_RST_PIN_FUNC + + if (pdata->gpio_reset >= 0) { + error = gpio_request(pdata->gpio_reset, "himax-reset"); + + if (error < 0) { + E("%s: request reset pin failed\n", __func__); + goto err_gpio_reset_req; + } + + error = gpio_direction_output(pdata->gpio_reset, 0); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_reset_dir; + } + } + +#endif + +#ifdef HX_SHARP_ENABLE_PON + if (gpio_is_valid(pdata->gpio_pon)) { + error = gpio_request(pdata->gpio_pon, "hmx_pon_gpio"); + + if (error) { + E("unable to request scl gpio [%d]\n", pdata->gpio_pon); + goto err_gpio_pon_req; + } + + error = gpio_direction_output(pdata->gpio_pon, 0); + + I("gpio_pon LOW [%d]\n", pdata->gpio_pon); + + if (error) { + E("unable to set direction for pon gpio [%d]\n", pdata->gpio_pon); + goto err_gpio_pon_dir; + } + } +#endif + + + if (pdata->gpio_3v3_en >= 0) { + error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en"); + + if (error < 0) { + E("%s: request 3v3_en pin failed\n", __func__); + goto err_gpio_3v3_req; + } + + gpio_direction_output(pdata->gpio_3v3_en, 1); + I("3v3_en set 1 get pin = %d\n", gpio_get_value(pdata->gpio_3v3_en)); + } + + if (gpio_is_valid(pdata->gpio_irq)) { + /* configure touchscreen irq gpio */ + error = gpio_request(pdata->gpio_irq, "himax_gpio_irq"); + + if (error) { + E("unable to request gpio [%d]\n", pdata->gpio_irq); + goto err_gpio_irq_req; + } + + error = gpio_direction_input(pdata->gpio_irq); + + if (error) { + E("unable to set direction for gpio [%d]\n", pdata->gpio_irq); + goto err_gpio_irq_set_input; + } + + private_ts->hx_irq = gpio_to_irq(pdata->gpio_irq); + } else { + E("irq gpio not provided\n"); + goto err_gpio_irq_req; + } +#ifdef HX_SHARP_ENABLE_PON + msleep(20); +#else + usleep_range(2000, 2001); +#endif + +#ifdef HX_RST_PIN_FUNC + + if (pdata->gpio_reset >= 0) { + error = gpio_direction_output(pdata->gpio_reset, 1); + + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_reset_set_high; + } + } +#endif + +#ifdef HX_SHARP_ENABLE_PON + msleep(800); + + if (gpio_is_valid(pdata->gpio_pon)) { + + error = gpio_direction_output(pdata->gpio_pon, 1); + + I("gpio_pon HIGH [%d]\n", pdata->gpio_pon); + + if (error) { + E("gpio_pon unable to set direction for gpio [%d]\n", pdata->gpio_pon); + goto err_gpio_pon_set_high; + } + } +#endif + return error; + +#ifdef HX_SHARP_ENABLE_PON +err_gpio_pon_set_high: +#endif +#ifdef HX_RST_PIN_FUNC +err_gpio_reset_set_high: +#endif +err_gpio_irq_set_input: + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); +err_gpio_irq_req: + if (pdata->gpio_3v3_en >= 0) + gpio_free(pdata->gpio_3v3_en); +err_gpio_3v3_req: +#ifdef HX_SHARP_ENABLE_PON +err_gpio_pon_dir: + if (gpio_is_valid(pdata->gpio_pon)) + gpio_free(pdata->gpio_pon); +err_gpio_pon_req: +#endif +#ifdef HX_RST_PIN_FUNC +err_gpio_reset_dir: + if (pdata->gpio_reset >= 0) + gpio_free(pdata->gpio_reset); +err_gpio_reset_req: +#endif + return error; +} + +#endif + +void himax_gpio_power_deconfig(struct himax_i2c_platform_data *pdata) +{ + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); + +#ifdef HX_RST_PIN_FUNC + if (gpio_is_valid(pdata->gpio_reset)) + gpio_free(pdata->gpio_reset); +#endif + +#if defined(CONFIG_HMX_DB) + himax_power_on(pdata, false); + himax_regulator_deinit(pdata); +#else + if (pdata->gpio_3v3_en >= 0) + gpio_free(pdata->gpio_3v3_en); + +#ifdef HX_SHARP_ENABLE_PON + if (gpio_is_valid(pdata->gpio_pon)) + gpio_free(pdata->gpio_pon); +#endif + +#endif +} + +static void himax_ts_isr_func(struct himax_ts_data *ts) +{ + himax_ts_work(ts); +} + +irqreturn_t himax_ts_thread(int irq, void *ptr) +{ + himax_ts_isr_func((struct himax_ts_data *)ptr); + + return IRQ_HANDLED; +} + +static void himax_ts_work_func(struct work_struct *work) +{ + struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work); + + himax_ts_work(ts); +} + +int himax_int_register_trigger(void) +{ + int ret = 0; + struct himax_ts_data *ts = private_ts; + + if (ic_data->HX_INT_IS_EDGE) { + I("%s edge triiger falling\n", __func__); + ret = request_threaded_irq(ts->hx_irq, NULL, himax_ts_thread, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, HIMAX_common_NAME, ts); + } else { + I("%s level trigger low\n", __func__); + ret = request_threaded_irq(ts->hx_irq, NULL, himax_ts_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, HIMAX_common_NAME, ts); + } + + return ret; +} + +int himax_int_en_set(void) +{ + int ret = NO_ERR; + + ret = himax_int_register_trigger(); + return ret; +} + +int himax_ts_register_interrupt(void) +{ + struct himax_ts_data *ts = private_ts; + /* struct i2c_client *client = private_ts->client; */ + int ret = 0; + + ts->irq_enabled = 0; + + /* Work functon */ + if (private_ts->hx_irq) {/*INT mode*/ + ts->use_irq = 1; + ret = himax_int_register_trigger(); + + if (ret == 0) { + ts->irq_enabled = 1; + irq_enable_count = 1; + I("%s: irq enabled at gpio: %d\n", __func__, private_ts->hx_irq); +#ifdef HX_SMART_WAKEUP + irq_set_irq_wake(private_ts->hx_irq, 1); +#endif + } else { + ts->use_irq = 0; + E("%s: request_irq failed\n", __func__); + } + } else { + I("%s: private_ts->hx_irq is empty, use polling mode.\n", __func__); + } + + if (!ts->use_irq) {/*if use polling mode need to disable HX_ESD_RECOVERY function*/ + ts->himax_wq = create_singlethread_workqueue("himax_touch"); + INIT_WORK(&ts->work, himax_ts_work_func); + hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ts->timer.function = himax_ts_timer_func; + hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); + I("%s: polling mode enabled\n", __func__); + } + + return ret; +} + +int himax_ts_unregister_interrupt(void) +{ + struct himax_ts_data *ts = private_ts; + int ret = 0; + + I("%s: entered.\n", __func__); + + /* Work functon */ + if (private_ts->hx_irq && ts->use_irq) {/*INT mode*/ +#ifdef HX_SMART_WAKEUP + irq_set_irq_wake(ts->hx_irq, 0); +#endif + free_irq(ts->hx_irq, ts); + I("%s: irq disabled at qpio: %d\n", __func__, private_ts->hx_irq); + } + + if (!ts->use_irq) {/*if use polling mode need to disable HX_ESD_RECOVERY function*/ + hrtimer_cancel(&ts->timer); + cancel_work_sync(&ts->work); + if (ts->himax_wq != NULL) + destroy_workqueue(ts->himax_wq); + I("%s: polling mode destroyed", __func__); + } + + return ret; +} + +static int himax_common_suspend(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + I("%s: enter\n", __func__); +#ifdef CONFIG_DRM + if (!ts->initialized) + return -ECANCELED; +#endif + himax_chip_common_suspend(ts); + return 0; +} + +#if defined(HX_RESUME_SET_FW) +void himax_resume_thread_func(void) +{ + struct himax_ts_data *ts = private_ts; + I("%s: TP resume from thread\n", __func__); +#if defined(__HIMAX_HX83102D_MOD__) + queue_delayed_work(ts->ts_int_workqueue, + &ts->ts_int_work, msecs_to_jiffies(60)); +#else + queue_work(ts->ts_int_workqueue, &ts->ts_int_work); +#endif + return; +} +#endif +static int himax_common_resume(struct device *dev) +{ + struct himax_ts_data *ts = dev_get_drvdata(dev); + + I("%s: enter\n", __func__); +#ifdef CONFIG_DRM + if (!ts->initialized) { + /* + * wait until device resume for TDDI + * TDDI: Touch and display Driver IC + */ + if (himax_chip_common_init()) + return -ECANCELED; + } +#endif +#if defined(HX_RESUME_SET_FW) + himax_resume_thread_func(); +#else + himax_chip_common_resume(ts); +#endif + return 0; +} + +#if defined(CONFIG_DRM) +struct drm_panel *himax_active_panel; +static int check_dt(struct device_node *np) +{ + int i; + int count; + struct device_node *node; + struct drm_panel *panel; + + count = of_count_phandle_with_args(np, "panel", NULL); + if (count <= 0) + return 0; + + for (i = 0; i < count; i++) { + node = of_parse_phandle(np, "panel", i); + panel = of_drm_find_panel(node); + of_node_put(node); + if (!IS_ERR(panel)) { + himax_active_panel = panel; + return 0; + } + } + if (node) + E("%s: %s not actived\n", __func__, node->name); + return -ENODEV; +} + +int drm_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct drm_panel_notifier *evdata = data; + int *blank; + struct himax_ts_data *ts = + container_of(self, struct himax_ts_data, fb_notif); + + if (!evdata) + return 0; + + D("DRM %s\n", __func__); + + if (evdata->data && event == DRM_PANEL_EARLY_EVENT_BLANK && ts != NULL && + ts->dev != NULL) { + blank = evdata->data; + switch (*blank) { + case DRM_PANEL_BLANK_POWERDOWN: + if (!ts->initialized) + return -ECANCELED; + himax_common_suspend(ts->dev); +#ifdef HIMAX_PALM_SENSOR_EN + if (ts->palm_detection_enabled) { + I("%s: palm detection is enabled", __func__); + return 1; + } +#endif +#ifdef HIMAX_V2_SENSOR_EN + if (ts->SMWP_enable) { + I("%s: tap detection is enabled", __func__); + return 1; + } +#endif + break; +#if defined(__HIMAX_HX83102D_MOD__) + case DRM_PANEL_BLANK_UNBLANK: + D("DRM_EARLY_EVENT_BLANK resume.\n"); + himax_common_resume(ts->dev); + return 0; +#endif + } + } + + if (evdata->data && event == DRM_PANEL_EVENT_BLANK && ts != NULL && + ts->dev != NULL) { + blank = evdata->data; + switch (*blank) { + case DRM_PANEL_BLANK_UNBLANK: + himax_common_resume(ts->dev); + break; + } + } + + return 0; +} +#elif defined(CONFIG_FB) +int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct fb_event *evdata = data; + int *blank; + struct himax_ts_data *ts = + container_of(self, struct himax_ts_data, fb_notif); + + I(" %s\n", __func__); + + if (evdata && evdata->data && event == FB_EVENT_BLANK && ts != NULL && + ts->dev != NULL) { + blank = evdata->data; + + switch (*blank) { + case FB_BLANK_UNBLANK: + himax_common_resume(ts->dev); + break; + + case FB_BLANK_POWERDOWN: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_NORMAL: + himax_common_suspend(ts->dev); + break; + } + } + + return 0; +} +#endif + +int himax_chip_common_probe(struct spi_device *spi) +{ + struct himax_ts_data *ts; + int ret = 0; + struct device_node *dp; + + I("Enter %s\n", __func__); + if (spi->master->flags & SPI_MASTER_HALF_DUPLEX) { + dev_err(&spi->dev, + "%s: Full duplex not supported by host\n", __func__); + return -EIO; + } +#ifdef CONFIG_DRM + dp = spi->dev.of_node; + if (check_dt(dp)) { + return -ENODEV; + } +#endif + gBuffer = kzalloc(sizeof(uint8_t) * PACKET_MAX_SZ, GFP_KERNEL); + if (gBuffer == NULL) { + E("%s: allocate gBuffer failed\n", __func__); + ret = -ENOMEM; + goto err_alloc_gbuffer_failed; + } + + ts = kzalloc(sizeof(struct himax_ts_data), GFP_KERNEL); + if (ts == NULL) { + E("%s: allocate himax_ts_data failed\n", __func__); + ret = -ENOMEM; + goto err_alloc_data_failed; + } + + private_ts = ts; + spi->bits_per_word = 8; + spi->mode = SPI_MODE_3; + spi->chip_select = 0; + + ts->spi = spi; + mutex_init(&(ts->spi_lock)); + ts->dev = &spi->dev; + dev_set_drvdata(&spi->dev, ts); + spi_set_drvdata(spi, ts); + + ts->initialized = false; + ret = himax_chip_common_init(); + if (ret < 0) + goto err_alloc_data_failed; + return 0; + +err_alloc_data_failed: + kfree(gBuffer); +err_alloc_gbuffer_failed: + return ret; +} + +int himax_chip_common_remove(struct spi_device *spi) +{ + struct himax_ts_data *ts = spi_get_drvdata(spi); + + if (g_hx_chip_inited) + himax_chip_common_deinit(); + +#if defined(HX_USB_DETECT_GLOBAL) + if (ts->charger_notif.notifier_call) + power_supply_unreg_notifier(&ts->charger_notif); +#endif + ts->spi = NULL; + /* spin_unlock_irq(&ts->spi_lock); */ + spi_set_drvdata(spi, NULL); + kfree(gBuffer); + + I("%s: completed.\n", __func__); + + return 0; +} + +#if (!defined(CONFIG_FB)) && (!defined(CONFIG_DRM)) +static const struct dev_pm_ops himax_common_pm_ops = { + .suspend = himax_common_suspend, + .resume = himax_common_resume, +}; +#endif + +#ifdef CONFIG_OF +static const struct of_device_id himax_match_table[] = { + {.compatible = "himax,hxcommon" }, + {}, +}; +#else +#define himax_match_table NULL +#endif + +static struct spi_driver himax_common_driver = { + .driver = { + .name = HIMAX_common_NAME, + .owner = THIS_MODULE, + .of_match_table = himax_match_table, + }, + .probe = himax_chip_common_probe, + .remove = himax_chip_common_remove, +}; + +static int __init himax_common_init(void) +{ + I("Himax common touch panel driver init\n"); + D("Himax check double loading\n"); + if (g_mmi_refcnt++ > 0) { + I("Himax driver has been loaded! ignoring....\n"); + return 0; + } + spi_register_driver(&himax_common_driver); + + return 0; +} + +static void __exit himax_common_exit(void) +{ + if (spi) { + spi_unregister_device(spi); + spi = NULL; + } + spi_unregister_driver(&himax_common_driver); +} + +module_init(himax_common_init); +module_exit(himax_common_exit); + +MODULE_DESCRIPTION("Himax_common driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_SPI.h b/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_SPI.h new file mode 100755 index 000000000000..459b41e7efc1 --- /dev/null +++ b/drivers/input/touchscreen/himax_v3_mmi/himax_platform_QCT_SPI.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for QCT platform + * + * 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. + */ + +#ifndef HIMAX_PLATFORM_H +#define HIMAX_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_HMX_DB) + #include +#endif + +#define HIMAX_I2C_RETRY_TIMES 3 + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) +#define D(x...) pr_debug("[HXTP] " x) +#define I(x...) pr_info("[HXTP] " x) +#define W(x...) pr_warn("[HXTP][WARNING] " x) +#define E(x...) pr_err("[HXTP][ERROR] " x) +#define DIF(x...) \ +do { \ + if (debug_flag) \ + pr_debug("[HXTP][DEBUG] " x) \ + } while (0) +#else +#define D(x...) +#define I(x...) +#define W(x...) +#define E(x...) +#define DIF(x...) +#endif + +#if defined(CONFIG_HMX_DB) + /* Analog voltage @2.7 V */ +#define HX_VTG_MIN_UV 2700000 +#define HX_VTG_MAX_UV 3300000 +#define HX_ACTIVE_LOAD_UA 15000 +#define HX_LPM_LOAD_UA 10 +/* Digital voltage @1.8 V */ +#define HX_VTG_DIG_MIN_UV 1800000 +#define HX_VTG_DIG_MAX_UV 1800000 +#define HX_ACTIVE_LOAD_DIG_UA 10000 +#define HX_LPM_LOAD_DIG_UA 10 + +#define HX_I2C_VTG_MIN_UV 1800000 +#define HX_I2C_VTG_MAX_UV 1800000 +#define HX_I2C_LOAD_UA 10000 +#define HX_I2C_LPM_LOAD_UA 10 +#endif + +#define HIMAX_common_NAME "himax_tp" +#define HIMAX_I2C_ADDR 0x48 +#define INPUT_DEV_NAME "himax-touchscreen" +#define PACKET_MAX_SZ 4096 +#define GBUFFER_SZ PACKET_MAX_SZ - 2 + +struct himax_i2c_platform_data { + int abs_x_min; + int abs_x_max; + int abs_x_fuzz; + int abs_y_min; + int abs_y_max; + int abs_y_fuzz; + int abs_pressure_min; + int abs_pressure_max; + int abs_pressure_fuzz; + int abs_width_min; + int abs_width_max; + int screenWidth; + int screenHeight; + uint8_t fw_version; + uint8_t tw_id; + uint8_t powerOff3V3; + uint8_t cable_config[2]; + uint8_t protocol_type; + int gpio_irq; + int gpio_reset; + int gpio_3v3_en; + char panel_supplier[16]; + int (*power)(int on); + void (*reset)(void); + struct himax_virtual_key *virtual_key; + struct kobject *vk_obj; + struct kobj_attribute *vk2Use; + + int hx_config_size; +#if defined(CONFIG_HMX_DB) + bool i2c_pull_up; + bool digital_pwr_regulator; + int reset_gpio; + u32 reset_gpio_flags; + int irq_gpio; + u32 irq_gpio_flags; + + struct regulator *vcc_ana; /* For Dragon Board */ + struct regulator *vcc_dig; /* For Dragon Board */ + struct regulator *vcc_i2c; /* For Dragon Board */ +#endif +}; + +extern struct himax_ic_data *ic_data; +extern struct himax_ts_data *private_ts; +int himax_chip_common_init(void); +void himax_chip_common_deinit(void); + +void himax_ts_work(struct himax_ts_data *ts); +enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer); +extern int irq_enable_count; +extern int himax_bus_read(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry); +extern int himax_bus_write(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry); +extern int himax_bus_write_command(uint8_t command, uint8_t toRetry); +extern int himax_bus_master_write(uint8_t *data, uint32_t length, uint8_t toRetry); +extern void himax_int_enable(int enable); +extern int himax_ts_register_interrupt(void); +int himax_ts_unregister_interrupt(void); +extern uint8_t himax_int_gpio_read(int pinnum); + +extern int himax_gpio_power_config(struct himax_i2c_platform_data *pdata); +void himax_gpio_power_deconfig(struct himax_i2c_platform_data *pdata); + +#if defined(CONFIG_DRM) + extern int drm_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +#elif defined(CONFIG_FB) + extern int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +#endif + +#endif diff --git a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_modular.h b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_modular.h new file mode 100644 index 000000000000..3e7a43b9ed4e --- /dev/null +++ b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_modular.h @@ -0,0 +1,275 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for modularize functions + * + * 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. + */ + +#ifndef __HIMAX_MODULAR_H__ +#define __HIMAX_MODULAR_H__ + +#include "himax_modular_table.h" + +static bool (*this_detect_fp)(void); + +static void himax_add_chip_dt(bool (*detect_fp)(void)) +{ + int32_t idx; + struct himax_chip_entry *entry; + + this_detect_fp = detect_fp; + idx = himax_get_ksym_idx(); + if (idx < 0) { + /*TODO: No entry, handle this error*/ + E("%s: no entry exist, please insert ic module first!", __func__); + } else { + entry = (void *)kallsyms_lookup_name(himax_ksym_lookup[idx]); + if (/*!(entry->core_chip_dt)*/isEmpty(idx) == 1) { + entry->core_chip_dt = kcalloc(HX_DRIVER_MAX_IC_NUM, + sizeof(struct himax_chip_detect), GFP_KERNEL); + entry->hx_ic_dt_num = 0; + } + entry->core_chip_dt[entry->hx_ic_dt_num++].fp_chip_detect = detect_fp; + } +} + +static void free_chip_dt_table(void) +{ + int i, j, idx; + struct himax_chip_entry *entry; + + idx = himax_get_ksym_idx(); + if (idx >= 0) { + if (isEmpty(idx) != 0) { + I("%s: no chip registered or entry has been clean up, leave safetly.\n", + __func__); + return; + } + entry = get_chip_entry_by_index(idx); + + for (i = 0; i < entry->hx_ic_dt_num; i++) { + if (entry->core_chip_dt[i].fp_chip_detect == this_detect_fp) { + if (i == (entry->hx_ic_dt_num - 1)) { + entry->core_chip_dt[i].fp_chip_detect = NULL; + entry->hx_ic_dt_num = 0; + } else { + for (j = i; j < entry->hx_ic_dt_num; j++) + entry->core_chip_dt[i].fp_chip_detect = entry->core_chip_dt[j].fp_chip_detect; + + entry->core_chip_dt[j].fp_chip_detect = NULL; + entry->hx_ic_dt_num--; + } + } + } + if (entry->hx_ic_dt_num == 0) { + kfree(entry->core_chip_dt); + entry->core_chip_dt = NULL; + } + } +} + +#define setup_symbol(sym) ({kp_##sym = (void *)kallsyms_lookup_name(#sym); kp_##sym; }) +#define assert_on_symbol(sym) do { \ + if (!setup_symbol(sym)) { \ + E("%s: setup %s failed!\n", __func__, #sym); \ + ret = -1; \ + } \ + } while (0) +#if !defined(__HIMAX_HX852xH_MOD__) && !defined(__HIMAX_HX852xG_MOD__) +static struct fw_operation **kp_pfw_op; +static struct ic_operation **kp_pic_op; +static struct driver_operation **kp_pdriver_op; +#endif +static struct himax_chip_detect **kp_g_core_chip_dt; + +#if defined(HX_ZERO_FLASH) +static struct zf_operation **kp_pzf_op; +static int *kp_G_POWERONOF; +#endif + +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) +#if defined(HX_EN_DYNAMIC_NAME) + static char **kp_i_CTPM_firmware_name; +#endif +#endif + +static unsigned char *kp_IC_CHECKSUM; + +#ifdef HX_ESD_RECOVERY +static u8 *kp_HX_ESD_RESET_ACTIVATE; +#endif + +#if defined(HX_ZERO_FLASH) && defined(HX_CODE_OVERLAY) +#if defined(CONFIG_TOUCHSCREEN_HIMAX_INCELL) +extern uint8_t *ovl_idx; +static uint8_t **kp_ovl_idx; +#endif +#endif + +static unsigned long *kp_FW_VER_MAJ_FLASH_ADDR; +static unsigned long *kp_FW_VER_MIN_FLASH_ADDR; +static unsigned long *kp_CFG_VER_MAJ_FLASH_ADDR; +static unsigned long *kp_CFG_VER_MIN_FLASH_ADDR; +static unsigned long *kp_CID_VER_MAJ_FLASH_ADDR; +static unsigned long *kp_CID_VER_MIN_FLASH_ADDR; + +static unsigned long *kp_FW_VER_MAJ_FLASH_LENG; +static unsigned long *kp_FW_VER_MIN_FLASH_LENG; +static unsigned long *kp_CFG_VER_MAJ_FLASH_LENG; +static unsigned long *kp_CFG_VER_MIN_FLASH_LENG; +static unsigned long *kp_CID_VER_MAJ_FLASH_LENG; +static unsigned long *kp_CID_VER_MIN_FLASH_LENG; + +#ifdef HX_AUTO_UPDATE_FW + static int *kp_g_i_FW_VER; + static int *kp_g_i_CFG_VER; + static int *kp_g_i_CID_MAJ; + static int *kp_g_i_CID_MIN; + static unsigned char **kp_i_CTPM_FW; +#endif + +#ifdef HX_TP_PROC_2T2R + static bool *kp_Is_2T2R; +#endif + +#ifdef HX_USB_DETECT_GLOBAL + static void (*kp_himax_cable_detect_func)(bool force_renew); +#endif + +#ifdef HX_RST_PIN_FUNC + static void (*kp_himax_rst_gpio_set)(int pinnum, uint8_t value); +#endif + +static struct himax_ts_data **kp_private_ts; +static struct himax_core_fp *kp_g_core_fp; +static struct himax_ic_data **kp_ic_data; + +#if defined(__HIMAX_HX852xH_MOD__) || defined(__HIMAX_HX852xG_MOD__) +#if defined(__HIMAX_HX852xG_MOD__) +static struct on_driver_operation **kp_on_pdriver_op; +#endif +static void (*kp_himax_mcu_on_cmd_init)(void); +static int (*kp_himax_mcu_on_cmd_struct_init)(void); +static void (*kp_himax_on_parse_assign_cmd)(uint32_t addr, uint8_t *cmd, int len); +#else +static void (*kp_himax_mcu_in_cmd_init)(void); +static int (*kp_himax_mcu_in_cmd_struct_init)(void); +static void (*kp_himax_in_parse_assign_cmd)(uint32_t addr, uint8_t *cmd, int len); +#endif + +static int *kp_irq_enable_count; +static int (*kp_himax_bus_read)(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry); +static int (*kp_himax_bus_write)(uint8_t command, uint8_t *data, uint32_t length, uint8_t toRetry); +static int (*kp_himax_bus_write_command)(uint8_t command, uint8_t toRetry); +static int (*kp_himax_bus_master_write)(uint8_t *data, uint32_t length, uint8_t toRetry); +static void (*kp_himax_int_enable)(int enable); +static int (*kp_himax_ts_register_interrupt)(void); +static uint8_t (*kp_himax_int_gpio_read)(int pinnum); +static int (*kp_himax_gpio_power_config)(struct himax_i2c_platform_data *pdata); + +static int32_t himax_ic_setup_external_symbols(void) +{ + int32_t ret = 0; + +#if !defined(__HIMAX_HX852xH_MOD__) && !defined(__HIMAX_HX852xG_MOD__) + assert_on_symbol(pfw_op); + assert_on_symbol(pic_op); + assert_on_symbol(pdriver_op); +#endif + assert_on_symbol(g_core_chip_dt); + + assert_on_symbol(private_ts); + assert_on_symbol(g_core_fp); + assert_on_symbol(ic_data); + +#if defined(__HIMAX_HX852xH_MOD__) || defined(__HIMAX_HX852xG_MOD__) +#if defined(__HIMAX_HX852xG_MOD__) + assert_on_symbol(on_pdriver_op); +#endif + assert_on_symbol(himax_mcu_on_cmd_init); + assert_on_symbol(himax_mcu_on_cmd_struct_init); + assert_on_symbol(himax_on_parse_assign_cmd); +#else + assert_on_symbol(himax_mcu_in_cmd_init); + assert_on_symbol(himax_mcu_in_cmd_struct_init); + assert_on_symbol(himax_in_parse_assign_cmd); +#endif + + assert_on_symbol(irq_enable_count); + assert_on_symbol(himax_bus_read); + assert_on_symbol(himax_bus_write); + assert_on_symbol(himax_bus_write_command); + assert_on_symbol(himax_bus_master_write); + assert_on_symbol(himax_int_enable); + assert_on_symbol(himax_ts_register_interrupt); + assert_on_symbol(himax_int_gpio_read); + assert_on_symbol(himax_gpio_power_config); + +#if defined(HX_ZERO_FLASH) + assert_on_symbol(pzf_op); + assert_on_symbol(G_POWERONOF); +#endif + +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) +#if defined(HX_EN_DYNAMIC_NAME) + assert_on_symbol(i_CTPM_firmware_name); +#endif +#endif + assert_on_symbol(IC_CHECKSUM); + + assert_on_symbol(FW_VER_MAJ_FLASH_ADDR); + assert_on_symbol(FW_VER_MIN_FLASH_ADDR); + assert_on_symbol(CFG_VER_MAJ_FLASH_ADDR); + assert_on_symbol(CFG_VER_MIN_FLASH_ADDR); + assert_on_symbol(CID_VER_MAJ_FLASH_ADDR); + assert_on_symbol(CID_VER_MIN_FLASH_ADDR); + + assert_on_symbol(FW_VER_MAJ_FLASH_LENG); + assert_on_symbol(FW_VER_MIN_FLASH_LENG); + assert_on_symbol(CFG_VER_MAJ_FLASH_LENG); + assert_on_symbol(CFG_VER_MIN_FLASH_LENG); + assert_on_symbol(CID_VER_MAJ_FLASH_LENG); + assert_on_symbol(CID_VER_MIN_FLASH_LENG); + +#ifdef HX_AUTO_UPDATE_FW + assert_on_symbol(g_i_FW_VER); + assert_on_symbol(g_i_CFG_VER); + assert_on_symbol(g_i_CID_MAJ); + assert_on_symbol(g_i_CID_MIN); + assert_on_symbol(i_CTPM_FW); +#endif + +#ifdef HX_TP_PROC_2T2R + assert_on_symbol(Is_2T2R); +#endif + +#ifdef HX_USB_DETECT_GLOBAL + assert_on_symbol(himax_cable_detect_func); +#endif + +#ifdef HX_RST_PIN_FUNC + assert_on_symbol(himax_rst_gpio_set); +#endif + +#ifdef HX_ESD_RECOVERY + assert_on_symbol(HX_ESD_RESET_ACTIVATE); +#endif + +#if defined(HX_ZERO_FLASH) && defined(HX_CODE_OVERLAY) +#if defined(CONFIG_TOUCHSCREEN_HIMAX_INCELL) + assert_on_symbol(ovl_idx); +#endif +#endif + return ret; +} + + +#endif diff --git a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/himax_ic_HX83102.h b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/himax_ic_HX83102.h deleted file mode 100644 index 958df628f4f2..000000000000 --- a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/himax_ic_HX83102.h +++ /dev/null @@ -1,58 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for HX83102 chipset - * - * 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_platform.h" -#include "himax_common.h" -#include "himax_ic_core.h" -#include - -#define hx83102ab_fw_addr_sorting_mode_en 0x100007FC -#define hx83102ab_fw_addr_selftest_addr_en 0x100007F8 -#define hx83102ab_data_adc_cfg_1 0x10007B00 -#define hx83102a_data_df_rx 48 -#define hx83102a_data_df_tx 24 -#define hx83102a_data_df_x_res 2160 -#define hx83102a_data_df_y_res 3840 -#define hx83102a_data_adc_num 100 -#define hx83102b_data_df_x_res 720 -#define hx83102b_data_df_y_res 1280 -#define hx83102b_data_adc_num 64 - -#define hx83102d_fw_addr_raw_out_sel 0x800204f4 -#define hx83102d_zf_data_adc_cfg_1 0x10007B00 -#define hx83102d_zf_data_adc_cfg_2 0x10006A00 -#define hx83102d_zf_data_adc_cfg_3 0x10007500 -#define hx83102d_zf_data_bor_prevent_info 0x10007268 -#define hx83102d_zf_data_notch_info 0x10007300 -#define hx83102d_zf_func_info_en 0x10007FD0 -#define hx83102d_zf_po_sub_func 0x10005A00 -#define hx83102d_zf_data_sram_start_addr 0x20000000 -#define hx83102d_data_df_x_res 720 -#define hx83102d_data_df_y_res 1280 -#define hx83102d_adr_osc_en 0x9000009C -#define hx83102d_adr_osc_pw 0x90000280 -#define hx83102d_data_adc_num 48 - -#define hx83102e_fw_addr_raw_out_sel 0x100072EC -#define hx83102e_ic_adr_tcon_rst 0x80020004 -#define hx83102e_data_df_rx 48 -#define hx83102e_data_df_tx 30 -#define hx83102e_data_df_x_res 1200 -#define hx83102e_data_df_y_res 1920 -#define hx83102e_data_adc_num 100 - -#if defined(HX_ESD_RECOVERY) -extern u8 HX_ESD_RESET_ACTIVATE; -#endif diff --git a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/Android.mk b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/Android.mk similarity index 80% rename from drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/Android.mk rename to drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/Android.mk index 54b9d3996cc7..bd817b74490b 100644 --- a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/Android.mk +++ b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/Android.mk @@ -7,10 +7,10 @@ else HIMAX_MMI_IC_MODULE_PATH := $(KERNEL_MODULES_OUT) endif -KERNEL_CFLAGS += CONFIG_INPUT_HIMAX_V3_MMI_IC_NAME=hx83102 +KERNEL_CFLAGS += CONFIG_INPUT_HIMAX_V2_MMI_IC_NAME_D=hx83102d include $(CLEAR_VARS) -LOCAL_MODULE := himax_v3_mmi_hx83102.ko +LOCAL_MODULE := himax_v3_mmi_hx83102d.ko LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(HIMAX_MMI_IC_MODULE_PATH) LOCAL_REQUIRED_MODULES := himax_v3_mmi.ko diff --git a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/Kbuild b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/Kbuild similarity index 59% rename from drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/Kbuild rename to drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/Kbuild index a2f98a71e514..336702c6e39e 100644 --- a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/Kbuild +++ b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/Kbuild @@ -3,15 +3,18 @@ EXTRA_CFLAGS += -Wall EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include \ -I$(TOP)/motorola/kernel/modules/drivers/input/touchscreen/himax_v3_mmi \ -I$(TOP)/motorola/kernel/modules/drivers/input/touchscreen/himax_v3_mmi/support_ic \ - -I$(TOP)/motorola/kernel/modules/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102 + -I$(TOP)/motorola/kernel/modules/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_HIMAX_DEBUG \ -DCONFIG_TOUCHSCREEN_HIMAX_INSPECT EXTRA_CFLAGS += -DCONFIG_TOUCHSCREEN_HIMAX_INCELL +EXTRA_CFLAGS += -DCONFIG_HMX_DB -ifneq ($(filter hx83102,$(CONFIG_INPUT_HIMAX_V3_MMI_IC_NAME)),) -EXTRA_CFLAGS += -D__HIMAX_HX83102_MOD__ +ifneq ($(filter hx83102d,$(CONFIG_INPUT_HIMAX_V2_MMI_IC_NAME_D)),) + EXTRA_CFLAGS += -D__HIMAX_HX83102D_MOD__ + EXTRA_CFLAGS += -DHX_ZERO_FLASH + EXTRA_CFLAGS += -DHX_CODE_OVERLAY endif -obj-m := himax_v3_mmi_hx83102.o -himax_v3_mmi_hx83102-objs += himax_ic_HX83102.o +obj-m := himax_v3_mmi_hx83102d.o +himax_v3_mmi_hx83102d-objs += himax_ic_HX83102d.o diff --git a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/Makefile b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/Makefile similarity index 100% rename from drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/Makefile rename to drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/Makefile diff --git a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/himax_ic_HX83102.c b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/himax_ic_HX83102d.c old mode 100644 new mode 100755 similarity index 53% rename from drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/himax_ic_HX83102.c rename to drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/himax_ic_HX83102d.c index 91e652c48310..2ca679fbc37c --- a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102/himax_ic_HX83102.c +++ b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/himax_ic_HX83102d.c @@ -1,1754 +1,1449 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* Himax Android Driver Sample Code for HX83102 chipset - * - * 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_ic_HX83102.h" -#include "himax_modular.h" - -static void hx83102_chip_init(void) -{ - (*kp_private_ts)->chip_cell_type = CHIP_IS_IN_CELL; - I("%s:IC cell type = %d\n", __func__, (*kp_private_ts)->chip_cell_type); - (*kp_IC_CHECKSUM) = HX_TP_BIN_CHECKSUM_CRC; - /*Himax: Set FW and CFG Flash Address*/ - (*kp_FW_VER_MAJ_FLASH_ADDR) = 49157; /*0x00C005*/ - (*kp_FW_VER_MAJ_FLASH_LENG) = 1; - (*kp_FW_VER_MIN_FLASH_ADDR) = 49158; /*0x00C006*/ - (*kp_FW_VER_MIN_FLASH_LENG) = 1; - (*kp_CFG_VER_MAJ_FLASH_ADDR) = 49408; /*0x00C100*/ - (*kp_CFG_VER_MAJ_FLASH_LENG) = 1; - (*kp_CFG_VER_MIN_FLASH_ADDR) = 49409; /*0x00C101*/ - (*kp_CFG_VER_MIN_FLASH_LENG) = 1; - (*kp_CID_VER_MAJ_FLASH_ADDR) = 49154; /*0x00C002*/ - (*kp_CID_VER_MAJ_FLASH_LENG) = 1; - (*kp_CID_VER_MIN_FLASH_ADDR) = 49155; /*0x00C003*/ - (*kp_CID_VER_MIN_FLASH_LENG) = 1; - /*PANEL_VERSION_ADDR = 49156;*/ /*0x00C004*/ - /*PANEL_VERSION_LENG = 1;*/ -} - -static void hx83102e_chip_init(void) -{ - (*kp_private_ts)->chip_cell_type = CHIP_IS_IN_CELL; - I("%s:IC cell type = %d\n", __func__, (*kp_private_ts)->chip_cell_type); - (*kp_IC_CHECKSUM) = HX_TP_BIN_CHECKSUM_CRC; - /*Himax: Set FW and CFG Flash Address*/ - (*kp_FW_VER_MAJ_FLASH_ADDR) = 59397; /*0x00E805*/ - (*kp_FW_VER_MAJ_FLASH_LENG) = 1; - (*kp_FW_VER_MIN_FLASH_ADDR) = 59398; /*0x00E806*/ - (*kp_FW_VER_MIN_FLASH_LENG) = 1; - (*kp_CFG_VER_MAJ_FLASH_ADDR) = 59648; /*0x00E900*/ - (*kp_CFG_VER_MAJ_FLASH_LENG) = 1; - (*kp_CFG_VER_MIN_FLASH_ADDR) = 59649; /*0x00E901*/ - (*kp_CFG_VER_MIN_FLASH_LENG) = 1; - (*kp_CID_VER_MAJ_FLASH_ADDR) = 59394; /*0x00E802*/ - (*kp_CID_VER_MAJ_FLASH_LENG) = 1; - (*kp_CID_VER_MIN_FLASH_ADDR) = 59395; /*0x00E803*/ - (*kp_CID_VER_MIN_FLASH_LENG) = 1; - /*PANEL_VERSION_ADDR = 59396;*/ /*0x00E804*/ - /*PANEL_VERSION_LENG = 1;*/ -} - -void hx83102_burst_enable(uint8_t auto_add_4_byte) -{ - uint8_t tmp_data[4]; - int ret = 0; - - tmp_data[0] = 0x31; - - ret = kp_himax_bus_write(0x13, tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } - - tmp_data[0] = (0x10 | auto_add_4_byte); - - ret = kp_himax_bus_write(0x0D, tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } -} - -int hx83102_flash_write_burst(uint8_t *reg_byte, uint8_t *write_data) -{ - uint8_t data_byte[8]; - int i = 0, j = 0, ret = 0; - - for (i = 0; i < 4; i++) - data_byte[i] = reg_byte[i]; - for (j = 4; j < 8; j++) - data_byte[j] = write_data[j-4]; - - ret = kp_himax_bus_write(0x00, data_byte, 8, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - return 0; -} - -static int hx83102_register_read(uint8_t *read_addr, int read_length, - uint8_t *read_data) -{ - uint8_t tmp_data[4]; - int i = 0; - int address = 0; - int ret = 0; - - if (read_length > 256) { - E("%s: read len over 256!\n", __func__); - return LENGTH_FAIL; - } - if (read_length > 4) - hx83102_burst_enable(1); - else - hx83102_burst_enable(0); - - address = (read_addr[3] << 24) - + (read_addr[2] << 16) - + (read_addr[1] << 8) - + read_addr[0]; - - i = address; - tmp_data[0] = (uint8_t)i; - tmp_data[1] = (uint8_t)(i >> 8); - tmp_data[2] = (uint8_t)(i >> 16); - tmp_data[3] = (uint8_t)(i >> 24); - - ret = kp_himax_bus_write(0x00, tmp_data, 4, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - tmp_data[0] = 0x00; - - ret = kp_himax_bus_write(0x0C, tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - - ret = kp_himax_bus_read(0x08, read_data, read_length, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return I2C_FAIL; - } - if (read_length > 4) - hx83102_burst_enable(0); - - return 0; -} - -#if defined(HX_RST_PIN_FUNC) -static void hx83102_pin_reset(void) -{ - I("%s: Now reset the Touch chip.\n", __func__); - kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 0); - msleep(20); - kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 1); - msleep(50); -} -#endif - -static bool hx83102_sense_off(bool check_en) -{ - uint8_t cnt = 0; - uint8_t tmp_addr[DATA_LEN_4]; - uint8_t tmp_writ[DATA_LEN_4]; - uint8_t tmp_data[DATA_LEN_4]; - int ret = 0; - - do { - if (cnt == 0 - || (tmp_data[0] != 0xA5 - && tmp_data[0] != 0x00 - && tmp_data[0] != 0x87)) { - tmp_addr[3] = 0x90; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0x5C; - - tmp_writ[3] = 0x00; - tmp_writ[2] = 0x00; - tmp_writ[1] = 0x00; - tmp_writ[0] = 0xA5; - hx83102_flash_write_burst(tmp_addr, tmp_writ); - } - msleep(20); - - /* check fw status */ - tmp_addr[3] = 0x90; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0xA8; - hx83102_register_read(tmp_addr, DATA_LEN_4, tmp_data); - - if (tmp_data[0] != 0x05) { - I("%s: Do not need wait FW, Status = 0x%02X!\n", - __func__, tmp_data[0]); - break; - } - - tmp_addr[3] = 0x90; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0x5C; - hx83102_register_read(tmp_addr, DATA_LEN_4, tmp_data); - I("%s: cnt = %d, data[0] = 0x%02X!\n", __func__, - cnt, tmp_data[0]); - } while (tmp_data[0] != 0x87 && (++cnt < 50) && check_en == true); - - cnt = 0; - - do { - /** - *I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 - */ - tmp_data[0] = 0x27; - ret = kp_himax_bus_write(0x31, tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - /** - *I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 - */ - tmp_data[0] = 0x95; - ret = kp_himax_bus_write(0x32, tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - /** - *Check enter_save_mode - */ - tmp_addr[3] = 0x90; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0xA8; - hx83102_register_read(tmp_addr, ADDR_LEN_4, tmp_data); - I("%s: Check enter_save_mode data[0]=%X\n", - __func__, tmp_data[0]); - - if (tmp_data[0] == 0x0C) { - /** - *Reset TCON - */ - tmp_addr[3] = 0x80; - tmp_addr[2] = 0x02; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0x20; - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x00; - hx83102_flash_write_burst(tmp_addr, tmp_data); - usleep_range(1000, 1001); - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x01; - hx83102_flash_write_burst(tmp_addr, tmp_data); - /** - *Reset ADC - */ - tmp_addr[3] = 0x80; - tmp_addr[2] = 0x02; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0x94; - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x00; - hx83102_flash_write_burst(tmp_addr, tmp_data); - usleep_range(1000, 1001); - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x01; - hx83102_flash_write_burst(tmp_addr, tmp_data); - - return true; - } - usleep_range(10000, 10001); -#if defined(HX_RST_PIN_FUNC) - hx83102_pin_reset(); -#endif - - } while (cnt++ < 15); - - return false; -} - -static bool hx83102ab_sense_off(bool check_en) -{ - uint8_t cnt = 0; - uint8_t tmp_addr[DATA_LEN_4]; - uint8_t tmp_data[DATA_LEN_4]; - int ret = 0; - - do { - /** - *I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 - */ - tmp_data[0] = 0x27; - ret = kp_himax_bus_write(0x31, tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - /** - *I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 - */ - tmp_data[0] = 0x95; - ret = kp_himax_bus_write(0x32, tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - /** - *Check enter_save_mode - */ - tmp_addr[3] = 0x90; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0xA8; - hx83102_register_read(tmp_addr, ADDR_LEN_4, tmp_data); - I("%s: Check enter_save_mode data[0]=%X\n", - __func__, tmp_data[0]); - - if (tmp_data[0] == 0x0C) { - /** - *Reset TCON - */ - tmp_addr[3] = 0x80; - tmp_addr[2] = 0x02; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0x20; - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x00; - hx83102_flash_write_burst(tmp_addr, tmp_data); - usleep_range(1000, 1001); - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x01; - hx83102_flash_write_burst(tmp_addr, tmp_data); - /** - *Reset ADC - */ - tmp_addr[3] = 0x80; - tmp_addr[2] = 0x02; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0x94; - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x00; - hx83102_flash_write_burst(tmp_addr, tmp_data); - usleep_range(1000, 1001); - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x01; - hx83102_flash_write_burst(tmp_addr, tmp_data); - - return true; - } - /*msleep(10);*/ - usleep_range(5000, 5001); -#if defined(HX_RST_PIN_FUNC) - kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 0); - msleep(20); - kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 1); - msleep(50); -#endif - - } while (cnt++ < 5); - - return false; -} - -static void hx83102ab_set_SMWP_enable(uint8_t SMWP_enable, bool suspended) -{ - uint8_t tmp_data[DATA_LEN_4]; - uint8_t back_data[DATA_LEN_4]; - uint8_t retry_cnt = 0; - - kp_g_core_fp->fp_sense_off(true); - - do { - if (SMWP_enable) { - kp_himax_parse_assign_cmd(fw_func_handshaking_pwd, - tmp_data, 4); - kp_g_core_fp->fp_register_write( - (*kp_pfw_op)->addr_smwp_enable, - DATA_LEN_4, - tmp_data, - 0); - kp_himax_parse_assign_cmd(fw_func_handshaking_pwd, - back_data, 4); - } else { - kp_himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - tmp_data, - 4); - kp_g_core_fp->fp_register_write( - (*kp_pfw_op)->addr_smwp_enable, - DATA_LEN_4, - tmp_data, - 0); - kp_himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - back_data, - 4); - } - - kp_g_core_fp->fp_register_read((*kp_pfw_op)->addr_smwp_enable, - DATA_LEN_4, tmp_data, false); - /*I("%s: tmp_data[0]=%d, SMWP_enable=%d, retry_cnt=%d\n", - * __func__, tmp_data[0],SMWP_enable,retry_cnt); - */ - retry_cnt++; - } while ((tmp_data[3] != back_data[3] - || tmp_data[2] != back_data[2] - || tmp_data[1] != back_data[1] - || tmp_data[0] != back_data[0]) - && retry_cnt < HIMAX_REG_RETRY_TIMES); - - kp_g_core_fp->fp_sense_on(0x00); -} - -static void hx83102ab_set_HSEN_enable(uint8_t HSEN_enable, bool suspended) -{ - uint8_t tmp_data[DATA_LEN_4]; - - if (HSEN_enable) { - kp_himax_parse_assign_cmd(fw_func_handshaking_pwd, - tmp_data, 4); - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_hsen_enable, - DATA_LEN_4, tmp_data, 0); - } else { - kp_himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - tmp_data, - 4); - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_hsen_enable, - DATA_LEN_4, tmp_data, 0); - } - - /*I("%s: tmp_data[0]=%d, HSEN_enable=%d, retry_cnt=%d\n", __func__, - * tmp_data[0],HSEN_enable,retry_cnt); - */ -} - -static void hx83102ab_usb_detect_set(uint8_t *cable_config) -{ - uint8_t tmp_data[DATA_LEN_4]; - - if (cable_config[1] == 0x01) { - kp_himax_parse_assign_cmd(fw_func_handshaking_pwd, - tmp_data, 4); - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_usb_detect, - DATA_LEN_4, tmp_data, 0); - I("%s: USB detect status IN!\n", __func__); - } else { - kp_himax_parse_assign_cmd( - fw_data_safe_mode_release_pw_reset, - tmp_data, - 4); - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_usb_detect, - DATA_LEN_4, tmp_data, 0); - I("%s: USB detect status OUT!\n", __func__); - } -} - -static uint8_t hx83102ab_read_DD_status(uint8_t *cmd_set, uint8_t *tmp_data) -{ - int cnt = 0; - uint8_t req_size = cmd_set[0]; - - cmd_set[3] = (*kp_pfw_op)->data_dd_request[0]; - - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_dd_handshak_addr, - DATA_LEN_4, cmd_set, 0); - I("%s:cmd_set[0]=0x%02X,set[1]=0x%02X,set[2]=0x%02X,set[3]=0x%02X\n", - __func__, cmd_set[0], cmd_set[1], cmd_set[2], cmd_set[3]); - - /* Doing hand shaking 0xAA -> 0xBB */ - for (cnt = 0; cnt < 100; cnt++) { - kp_g_core_fp->fp_register_read( - (*kp_pfw_op)->addr_dd_handshak_addr, - DATA_LEN_4, - tmp_data, - false); - usleep_range(10000, 10001); - - if (tmp_data[3] == (*kp_pfw_op)->data_dd_ack[0]) { - I("%s Data ready goto moving data\n", __func__); - break; - } - if (cnt >= 99) { - I("%s Data not ready in FW\n", __func__); - return FW_NOT_READY; - } - } - - kp_g_core_fp->fp_sense_off(true); - kp_g_core_fp->fp_register_read((*kp_pfw_op)->addr_dd_data_addr, - req_size, tmp_data, false); - kp_g_core_fp->fp_sense_on(0x01); - return NO_ERR; -} - -static int hx83102ab_read_FW_status(uint8_t *state_addr, uint8_t *tmp_addr) -{ - uint8_t i; - uint8_t req_size = 0; - uint8_t status_addr[DATA_LEN_4]; /*0x10007F44*/ - uint8_t cmd_addr[DATA_LEN_4]; /*0x900000F8*/ - - if (state_addr[0] == 0x01) { - state_addr[1] = 0x04; - - for (i = 0; i < DATA_LEN_4; i++) { - /* 0x10007F44 */ - state_addr[i + 2] = - (*kp_pfw_op)->addr_fw_dbg_msg_addr[i]; - status_addr[i] = (*kp_pfw_op)->addr_fw_dbg_msg_addr[i]; - } - - req_size = 0x04; - kp_g_core_fp->fp_sense_off(true); - kp_g_core_fp->fp_register_read(status_addr, req_size, - tmp_addr, false); - kp_g_core_fp->fp_sense_on(0x01); - } else if (state_addr[0] == 0x02) { - state_addr[1] = 0x30; - - for (i = 0; i < DATA_LEN_4; i++) { - /* 0x900000F8 */ - state_addr[i + 2] = - (*kp_pfw_op)->addr_fw_state_addr[i]; - cmd_addr[i] = (*kp_pfw_op)->addr_fw_state_addr[i]; - } - - req_size = 0x30; - kp_g_core_fp->fp_register_read(cmd_addr, req_size, - tmp_addr, false); - } - - return NO_ERR; -} - -static void hx83102ab_power_on_init(void) -{ - uint8_t tmp_data[DATA_LEN_4]; - - I("%s:\n", __func__); - kp_himax_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, - tmp_data, 4); - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_raw_out_sel, - DATA_LEN_4, tmp_data, 0); - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_sorting_mode_en, - DATA_LEN_4, tmp_data, 0); - kp_g_core_fp->fp_touch_information(); - kp_g_core_fp->fp_sense_on(0x00); -} - -static int hx83102ab_fts_ctpm_fw_upgrade_with_sys_fs_64k(unsigned char *fw, - int len, bool change_iref) -{ - int burnFW_success = 0; - uint8_t tmp_data[DATA_LEN_4]; - int ret = 0; - - if (len != FW_SIZE_64k) { - E("%s: The file size is not 64K bytes\n", __func__); - return false; - } - -#if defined(HX_RST_PIN_FUNC) - kp_g_core_fp->fp_ic_reset(false, false); -#else - kp_g_core_fp->fp_system_reset(); -#endif - kp_g_core_fp->fp_sense_off(true); - kp_g_core_fp->fp_chip_erase(); - kp_g_core_fp->fp_flash_programming(fw, FW_SIZE_64k); - - ret = kp_g_core_fp->fp_check_CRC( - (*kp_pfw_op)->addr_program_reload_from, - FW_SIZE_64k); - if (ret == 0) - burnFW_success = 1; - - kp_himax_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, - tmp_data, 4); - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_raw_out_sel, - DATA_LEN_4, tmp_data, 0); - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_sorting_mode_en, - DATA_LEN_4, tmp_data, 0); -#if defined(HX_RST_PIN_FUNC) - kp_g_core_fp->fp_ic_reset(false, false); -#else - /*System reset*/ - kp_g_core_fp->fp_system_reset(); -#endif - return burnFW_success; -} - -#if defined(HX_ESD_RECOVERY) -static void hx83102ab_esd_ic_reset(void) -{ - (*kp_HX_ESD_RESET_ACTIVATE) = 1; -#if defined(HX_RST_PIN_FUNC) - kp_g_core_fp->fp_pin_reset(); -#else - kp_g_core_fp->fp_system_reset(); -#endif - I("%s:\n", __func__); -} -#if defined(HX_ZERO_FLASH) -static int hx83102d_0f_esd_check(void) -{ - uint8_t tmp_data[DATA_LEN_4]; - int ret = NO_ERR; - - I("Enter %s\n", __func__); - - kp_g_core_fp->fp_register_read((*kp_pzf_op)->addr_sts_chk, - DATA_LEN_4, tmp_data, 0); - - if (tmp_data[0] != (*kp_pzf_op)->data_activ_sts[0]) { - ret = ERR_STS_WRONG; - I("%s:status : %8X = %2X\n", __func__, - zf_addr_sts_chk, tmp_data[0]); - } - - kp_g_core_fp->fp_register_read((*kp_pzf_op)->addr_activ_relod, - DATA_LEN_4, tmp_data, 0); - - if (tmp_data[0] != (*kp_pzf_op)->data_activ_in[0]) { - ret = ERR_STS_WRONG; - I("%s:status : %8X = %2X\n", __func__, - zf_addr_activ_relod, tmp_data[0]); - } - - return ret; -} -#endif -#endif - -static bool hx83102d_sense_off(bool check_en) -{ - uint8_t cnt = 0; - uint8_t tmp_addr[DATA_LEN_4]; - uint8_t tmp_data[DATA_LEN_4]; - int ret = 0; - - do { - if (cnt == 0 - || (tmp_data[0] != 0xA5 - && tmp_data[0] != 0x00 - && tmp_data[0] != 0x87)) - kp_g_core_fp->fp_register_write( - (*kp_pfw_op)->addr_ctrl_fw_isr, - DATA_LEN_4, - (*kp_pfw_op)->data_fw_stop, - 0); - /*msleep(20);*/ - usleep_range(10000, 10001); - - /* check fw status */ - kp_g_core_fp->fp_register_read( - (*kp_pic_op)->addr_cs_central_state, - ADDR_LEN_4, - tmp_data, - 0); - - if (tmp_data[0] != 0x05) { - I("%s: Do not need wait FW, Status = 0x%02X!\n", - __func__, tmp_data[0]); - break; - } - - kp_g_core_fp->fp_register_read((*kp_pfw_op)->addr_ctrl_fw_isr, - 4, tmp_data, false); - I("%s: cnt = %d, data[0] = 0x%02X!\n", __func__, - cnt, tmp_data[0]); - } while (tmp_data[0] != 0x87 && (++cnt < 10) && check_en == true); - - cnt = 0; - - do { - /* - *I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 - */ - tmp_data[0] = 0x27; - ret = kp_himax_bus_write(0x31, tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - /* - *I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 - */ - tmp_data[0] = 0x95; - ret = kp_himax_bus_write(0x32, tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - /* - *Check enter_save_mode - */ - tmp_addr[3] = 0x90; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0xA8; - hx83102_register_read(tmp_addr, ADDR_LEN_4, tmp_data); - I("%s: Check enter_save_mode data[0]=%X\n", - __func__, tmp_data[0]); - - if (tmp_data[0] == 0x0C) { - /* - *Reset TCON - */ - tmp_addr[3] = 0x80; - tmp_addr[2] = 0x02; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0x20; - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x00; - hx83102_flash_write_burst(tmp_addr, tmp_data); - usleep_range(1000, 1001); - - /* - *Reset ADC - */ - tmp_addr[3] = 0x80; - tmp_addr[2] = 0x02; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0x94; - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x00; - hx83102_flash_write_burst(tmp_addr, tmp_data); - usleep_range(1000, 1001); - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x01; - hx83102_flash_write_burst(tmp_addr, tmp_data); - - return true; - } - /*msleep(10);*/ - usleep_range(5000, 5001); - -#if defined(HX_RST_PIN_FUNC) - kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 0); - msleep(20); - kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 1); - msleep(50); -#endif - - } while (cnt++ < 5); - - return false; -} - -static void hx83102e_sense_on(uint8_t FlashMode) -{ - uint8_t tmp_data[DATA_LEN_4] = {0}; - int ret = 0; - - I("Enter %s\n", __func__); - kp_g_core_fp->fp_interface_on(); - kp_g_core_fp->fp_register_write( - (*kp_pfw_op)->addr_ctrl_fw_isr, - sizeof((*kp_pfw_op)->data_clear), - (*kp_pfw_op)->data_clear, - 0); - /*msleep(20);*/ - usleep_range(10000, 11000); - if (!FlashMode) { -#ifdef HX_RST_PIN_FUNC - kp_g_core_fp->fp_ic_reset(false, false); -#else - kp_g_core_fp->fp_system_reset(); -#endif - } else { - - ret = kp_himax_bus_write( - (*kp_pic_op)->adr_i2c_psw_lb[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) - E("%s: i2c access fail!\n", __func__); - - ret = kp_himax_bus_write( - (*kp_pic_op)->adr_i2c_psw_ub[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) - E("%s: i2c access fail!\n", __func__); - - } -} - -static bool hx83102e_sense_off(bool check_en) -{ - uint8_t cnt = 0; - uint8_t tmp_addr[DATA_LEN_4]; - uint8_t tmp_data[DATA_LEN_4]; - int ret = 0; - - do { - if (cnt == 0 - || (tmp_data[0] != 0xA5 - && tmp_data[0] != 0x00 - && tmp_data[0] != 0x87)) - kp_g_core_fp->fp_register_write( - (*kp_pfw_op)->addr_ctrl_fw_isr, - DATA_LEN_4, - (*kp_pfw_op)->data_fw_stop, - 0); - /*msleep(20);*/ - usleep_range(10000, 10001); - - /* check fw status */ - kp_g_core_fp->fp_register_read( - (*kp_pic_op)->addr_cs_central_state, - ADDR_LEN_4, - tmp_data, 0); - - if (tmp_data[0] != 0x05) { - I("%s: Do not need wait FW, Status = 0x%02X!\n", - __func__, tmp_data[0]); - break; - } - - kp_g_core_fp->fp_register_read((*kp_pfw_op)->addr_ctrl_fw_isr, - 4, tmp_data, false); - I("%s: cnt = %d, data[0] = 0x%02X!\n", __func__, - cnt, tmp_data[0]); - } while (tmp_data[0] != 0x87 && (++cnt < 10) && check_en == true); - - cnt = 0; - - do { - /** - *I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 - */ - tmp_data[0] = 0x27; - ret = kp_himax_bus_write(0x31, tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - /** - *I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 - */ - tmp_data[0] = 0x95; - ret = kp_himax_bus_write(0x32, tmp_data, 1, - HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - - /** - *Check enter_save_mode - */ - tmp_addr[3] = 0x90; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0xA8; - hx83102_register_read(tmp_addr, ADDR_LEN_4, tmp_data); - I("%s: Check enter_save_mode data[0]=%X\n", - __func__, tmp_data[0]); - - if (tmp_data[0] == 0x0C) { - /** - *Reset TCON - */ - tmp_addr[3] = 0x80; - tmp_addr[2] = 0x02; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0x20; - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; - tmp_data[0] = 0x00; - hx83102_flash_write_burst(tmp_addr, tmp_data); - usleep_range(1000, 1001); - return true; - } - /*msleep(10);*/ - usleep_range(5000, 5001); -#if defined(HX_RST_PIN_FUNC) - kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 0); - msleep(20); - kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 1); - msleep(50); -#endif - - } while (cnt++ < 5); - - return false; -} - -static bool hx83102d_dd_clk_set(bool enable) -{ - uint8_t data[4] = {0}; - - data[0] = (enable)?0xDD:0; - return (kp_g_core_fp->fp_register_write((*kp_pic_op)->adr_osc_en, - sizeof((*kp_pic_op)->adr_osc_en), data, 0) == NO_ERR); -} - -static void hx83102d_dd_reg_en(bool enable) -{ - uint8_t data[4] = {0}; - - data[0] = 0xA5; - data[1] = 0x00; - data[2] = 0x00; - data[3] = 0x00; - kp_g_core_fp->fp_register_write((*kp_pic_op)->adr_osc_pw, - DATA_LEN_4, data, 0); - - data[0] = 0xA5; - data[1] = 0x83; - data[2] = 0x10; - data[3] = 0x2D; - kp_g_core_fp->fp_dd_reg_write(0xB9, 0, 4, data, 0); -} - -static bool hx83102d_ic_id_read(void) -{ - int i = 0; - uint8_t data[4] = {0}; - - kp_g_core_fp->fp_dd_clk_set(true); - kp_g_core_fp->fp_dd_reg_en(true); - - for (i = 0; i < 13; i++) { - data[0] = 0x2A + i; - kp_g_core_fp->fp_dd_reg_write(0xBB, 3, 1, data, 0); - data[0] = 0x08; - kp_g_core_fp->fp_dd_reg_write(0xBB, 1, 1, data, 0); - kp_g_core_fp->fp_dd_reg_read(0xBB, 6, 1, data, 0); - (*kp_ic_data)->vendor_ic_id[i] = data[0]; - I("ic_data->vendor_ic_id[%d] = %02X\n", i, - (*kp_ic_data)->vendor_ic_id[i]); - } - - kp_g_core_fp->fp_dd_clk_set(false); - - return true; -} - -#if defined(HX_ZERO_FLASH) -static void himax_hx83102d_reload_to_active(void) -{ - uint8_t addr[DATA_LEN_4] = {0}; - uint8_t data[DATA_LEN_4] = {0}; - uint8_t retry_cnt = 0; - - addr[3] = 0x90; - addr[2] = 0x00; - addr[1] = 0x00; - addr[0] = 0x48; - - do { - data[3] = 0x00; - data[2] = 0x00; - data[1] = 0x00; - data[0] = 0xEC; - kp_g_core_fp->fp_register_write(addr, DATA_LEN_4, data, 0); - usleep_range(1000, 1100); - kp_g_core_fp->fp_register_read(addr, DATA_LEN_4, data, 0); - I("%s: data[1]=%d, data[0]=%d, retry_cnt=%d\n", __func__, - data[1], data[0], retry_cnt); - retry_cnt++; - } while ((data[1] != 0x01 - || data[0] != 0xEC) - && retry_cnt < HIMAX_REG_RETRY_TIMES); -} - -static void himax_hx83102d_resume_ic_action(void) -{ -#if !defined(HX_RESUME_HW_RESET) - himax_hx83102d_reload_to_active(); -#endif -} - -static void himax_hx83102d_suspend_ic_action(void) -{ -#if !defined(HX_RESUME_HW_RESET) - himax_hx83102d_reload_to_active(); -#endif -} - -static void himax_hx83102d_sense_on(uint8_t FlashMode) -{ - uint8_t tmp_data[DATA_LEN_4]; - int retry = 0; - int ret = 0; - - I("Enter %s\n", __func__); - - kp_g_core_fp->fp_interface_on(); - kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_ctrl_fw_isr, - sizeof((*kp_pfw_op)->data_clear), (*kp_pfw_op)->data_clear, 0); - /*msleep(20);*/ - usleep_range(10000, 10001); - if (!FlashMode) { -#if defined(HX_RST_PIN_FUNC) - kp_g_core_fp->fp_ic_reset(false, false); -#else - kp_g_core_fp->fp_system_reset(); -#endif - himax_hx83102d_reload_to_active(); - } else { - himax_hx83102d_reload_to_active(); - do { - kp_g_core_fp->fp_register_write( - (*kp_pfw_op)->addr_safe_mode_release_pw, - sizeof((*kp_pfw_op)-> - data_safe_mode_release_pw_active), - (*kp_pfw_op)->data_safe_mode_release_pw_active, - 0); - - kp_g_core_fp->fp_register_read( - (*kp_pfw_op)->addr_flag_reset_event, - DATA_LEN_4, tmp_data, 0); - I("%s:Read status from IC = %X,%X\n", __func__, - tmp_data[0], tmp_data[1]); - } while ((tmp_data[1] != 0x01 - || tmp_data[0] != 0x00) - && retry++ < 5); - - if (retry >= 5) { - E("%s: Fail:\n", __func__); -#if defined(HX_RST_PIN_FUNC) - kp_g_core_fp->fp_ic_reset(false, false); -#else - kp_g_core_fp->fp_system_reset(); -#endif - himax_hx83102d_reload_to_active(); - } else { - I("%s:OK and Read status from IC = %X,%X\n", __func__, - tmp_data[0], tmp_data[1]); - /* reset code*/ - tmp_data[0] = 0x00; - - ret = kp_himax_bus_write( - (*kp_pic_op)->adr_i2c_psw_lb[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) - E("%s: i2c access fail!\n", __func__); - - ret = kp_himax_bus_write( - (*kp_pic_op)->adr_i2c_psw_ub[0], - tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) - E("%s: i2c access fail!\n", __func__); - - kp_g_core_fp->fp_register_write( - (*kp_pfw_op)->addr_safe_mode_release_pw, - sizeof((*kp_pfw_op)-> - data_safe_mode_release_pw_reset), - (*kp_pfw_op)->data_safe_mode_release_pw_reset, - 0); - } - } -} - -static void hx83102ab_firmware_update_0f(const struct firmware *fw_entry) -{ - uint8_t tmp_addr[4]; - - I("%s, Entering\n", __func__); - - kp_g_core_fp->fp_register_write((*kp_pzf_op)->addr_system_reset, 4, - (*kp_pzf_op)->data_system_reset, 0); - - kp_g_core_fp->fp_sense_off(false); - - /* first 32K */ - /*bin file start*/ - /*isram*/ - kp_g_core_fp->fp_write_sram_0f(fw_entry, - (*kp_pzf_op)->data_sram_start_addr, 0, HX_32K_SZ); - - tmp_addr[3] = 0x10; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x73; - tmp_addr[0] = 0x00; - kp_g_core_fp->fp_write_sram_0f(fw_entry, tmp_addr, 0x8000, (0x200*4)); - - tmp_addr[3] = 0x10; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x68; - tmp_addr[0] = 0x00; - kp_g_core_fp->fp_write_sram_0f(fw_entry, tmp_addr, 0x8800, (0x200*4)); - - /*last 16k*/ - /*config info*/ - tmp_addr[3] = 0x10; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x72; - tmp_addr[0] = 0x04; /*0x10007206 <= size 60,from 0x0000C180*/ - kp_g_core_fp->fp_write_sram_0f(fw_entry, tmp_addr, 0xC178, (84)); - - /*FW config*/ - if ((*kp_G_POWERONOF) == 1) - kp_g_core_fp->fp_write_sram_0f(fw_entry, - (*kp_pzf_op)->data_fw_cfg_1, 0xBFFE, 388); - else - kp_g_core_fp->fp_clean_sram_0f((*kp_pzf_op)->data_fw_cfg_1, - 388, 1); - /*ADC config*/ - if ((*kp_G_POWERONOF) == 1) - kp_g_core_fp->fp_write_sram_0f(fw_entry, - (*kp_pzf_op)->data_adc_cfg_1, 0xe000, (128 * 4)); - else - kp_g_core_fp->fp_clean_sram_0f((*kp_pzf_op)->data_adc_cfg_1, - (128 * 4), 2); - - I("%s, END\n", __func__); -} -#if defined(HX_0F_DEBUG) -static void hx83102ab_firmware_read_0f(const struct firmware *fw_entry, - int type) -{ - uint8_t tmp_addr[4]; - - I("%s, Entering\n", __func__); - if (type == 0) { /* first 32K */ - kp_g_core_fp->fp_read_sram_0f(fw_entry, - (*kp_pzf_op)->data_sram_start_addr, 0, HX_32K_SZ); - tmp_addr[3] = 0x10; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x68; - tmp_addr[0] = 0x00; - kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_addr, - 0x8000, (0x200*4)); - - tmp_addr[3] = 0x10; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x73; - tmp_addr[0] = 0x00; - kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_addr, - 0x8800, (0x200*4)); - - } else { /*last 16k*/ - tmp_addr[3] = 0x10; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x72; - tmp_addr[0] = 0x04; /*0x10007206 <= size 80,from 0x0000C180*/ - kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_addr, - 0xC178, (84)); - - kp_g_core_fp->fp_read_sram_0f(fw_entry, - (*kp_pzf_op)->data_fw_cfg_1, 0xBFFE, 388); - kp_g_core_fp->fp_read_sram_0f(fw_entry, - (*kp_pzf_op)->data_adc_cfg_1, 0xE000, (128*4)); - - } - I("%s, END\n", __func__); -} -static void hx83102d_firmware_read_0f(const struct firmware *fw_entry, - int type) -{ - uint8_t tmp_data[4]; - - I("%s, Entering\n", __func__); - - switch (type) { - case 0: - kp_g_core_fp->fp_read_sram_0f(fw_entry, - (*kp_pzf_op)->data_sram_start_addr, 0, HX_40K_SZ); - break; - case 1: - kp_g_core_fp->fp_read_sram_0f(fw_entry, - (*kp_pzf_op)->data_cfg_info, 0xC000, 132); - break; - case 2: - kp_g_core_fp->fp_read_sram_0f(fw_entry, - (*kp_pzf_op)->data_fw_cfg_1, 0xC0FE, 484); - break; - case 3: - kp_g_core_fp->fp_read_sram_0f(fw_entry, - (*kp_pzf_op)->data_adc_cfg_1, 0xD000, 768); - break; - case 4: - kp_g_core_fp->fp_read_sram_0f(fw_entry, - (*kp_pzf_op)->data_adc_cfg_2, 0xD300, 1536); - break; - case 5: - kp_g_core_fp->fp_read_sram_0f(fw_entry, - (*kp_pzf_op)->data_adc_cfg_3, 0xE000, 1536); - break; - case 6: - kp_himax_parse_assign_cmd(hx83102d_zf_data_bor_prevent_info, - tmp_data, 4); - kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_data, 0xC9E0, 32); - break; - case 7: - kp_himax_parse_assign_cmd(hx83102d_zf_data_notch_info, - tmp_data, 4); - kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_data, - 0xCA00, 128); - break; - case 8: - kp_himax_parse_assign_cmd(hx83102d_zf_func_info_en, - tmp_data, 4); - kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_data, 0xCB00, 12); - break; - case 9: - kp_himax_parse_assign_cmd(hx83102d_zf_po_sub_func, - tmp_data, 4); - kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_data, - 0xA000, HX4K); - break; - default: - break; - } - I("%s, END\n", __func__); -} -#endif - -#if defined(HX_CODE_OVERLAY) -static int hx83102d_0f_overlay(int ovl_type, int mode) -{ - int ret = 0; - uint8_t count = 0; - uint8_t count2 = 0; - const struct firmware *fwp = NULL; - char fwname[32] = "Himax_firmware.bin"; - uint8_t part_num = 0; - uint8_t buf[16]; - uint8_t handshaking_addr[4] = {0xFC, 0x7F, 0x00, 0x10}; - /*uint8_t mpap_addr[4] = {0xEC, 0x73, 0x00, 0x10};*/ - uint8_t ovl_idx_t; - uint8_t request; - uint8_t reply; - uint8_t sram_addr[4] = {0}; - uint32_t offset = 0; - uint32_t size = 0; - uint8_t send_data[4] = {0}; - uint8_t recv_data[4] = {0}; - - ret = request_firmware(&fwp, fwname, (*kp_private_ts)->dev); - if (ret < 0) { - E("%s: request firmware FAIL!!!\n", __func__); - return ret; - } - - /*1. get number of partition*/ - part_num = fwp->data[HX64K + 12]; - if (part_num <= 1) { - E("%s, size of cfg part failed! part_num = %d\n", - __func__, part_num); - return LENGTH_FAIL; - } - - I("%s: overlay section %d\n", __func__, ovl_type-1); - if (ovl_type == 2) { - request = ovl_gesture_request; - reply = ovl_gesture_reply; - } else if (ovl_type == 3) { - request = ovl_border_request; - reply = ovl_border_reply; - } else { - E("%s: error overlay type %d\n", __func__, ovl_type); - return HX_INIT_FAIL; - } - ovl_idx_t = *((*kp_ovl_idx) + ovl_type - 1); - memcpy(buf, &fwp->data[ovl_idx_t * 0x10 + HX64K], 16); - memcpy(sram_addr, buf, 4); - offset = buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8]; - size = buf[7]<<24 | buf[6]<<16 | buf[5]<<8 | buf[4]; - -/* - * if (ovl_type == 1) { - * if (mode == 0) { - * //border overlay when finish self_test - * send_data[3] = 0x00; - * send_data[2] = 0x00; - * send_data[1] = 0x00; - * send_data[0] = 0x00; - * offset = zf_info_arr[2].fw_addr; - * size = zf_info_arr[2].write_size; - * I("%s: self test overlay section 2\n", __func__); - * } else if (mode == 1) { - * //sorting overlay when call self_test - * send_data[3] = 0x00; - * send_data[2] = 0x10; - * send_data[1] = 0x73; - * send_data[0] = 0x80; - * offset = zf_info_arr[0].fw_addr; - * size = zf_info_arr[0].write_size; - * I("%s: self test overlay section 0\n", __func__); - * } - * } - */ - -/* - * if (ovl_type == 1) { - * - * g_core_fp.fp_sense_off(false); - * - * //g_core_fp.fp_register_write(mpap_addr, DATA_LEN_4, - send_data, 0); - * count = 0; - * do { - * g_core_fp.fp_register_write(mpap_addr, DATA_LEN_4, - send_data, 0); - * g_core_fp.fp_register_read(mpap_addr, DATA_LEN_4, - recv_data, 0); - * } while ((recv_data[0] != send_data[0] - * || recv_data[1] != send_data[1] - * || recv_data[2] != send_data[2] - * || recv_data[3] != send_data[3]) - * && count++ < 10); - * - * I("%s: set mpap pw %d times\n", __func__, count); - * - * //g_core_fp.fp_write_sram_0f(fwp, sram_addr, offset, size); - * if (kp_g_core_fp->fp_write_sram_0f_crc(fwp, sram_addr, - offset, size) != 0) - * E("%s, Overlay HW CRC FAIL\n", __func__); - * - * g_core_fp.fp_reload_disable(0); - * - * g_core_fp.fp_sense_on(0x00); - * - * } else { - */ - - count = 0; - do { - kp_g_core_fp->fp_register_read(handshaking_addr, DATA_LEN_4, - recv_data, 0); - } while (recv_data[0] != request && count++ < 10); - - if (count < 10) { - /*g_core_fp.fp_write_sram_0f(fwp, sram_addr, offset, size);*/ - if (kp_g_core_fp->fp_write_sram_0f_crc(fwp, sram_addr, - offset, size) != 0) - E("%s, Overlay HW CRC FAIL\n", __func__); - - send_data[3] = 0x00; - send_data[2] = 0x00; - send_data[1] = 0x00; - send_data[0] = reply; - - count2 = 0; - do { - kp_g_core_fp->fp_register_write(handshaking_addr, - DATA_LEN_4, - send_data, 0); - usleep_range(1000, 1100); - kp_g_core_fp->fp_register_read(handshaking_addr, - DATA_LEN_4, - recv_data, 0); - } while (recv_data[0] != reply && count2++ < 10); - - if (ovl_type == 3) { -#if defined(HX_RST_PIN_FUNC) - kp_g_core_fp->fp_ic_reset(false, false); -#else - kp_g_core_fp->fp_system_reset(); -#endif - } - } - - I("%s: overlay request %d times; reply %d times\n", __func__, - count, count2); - - release_firmware(fwp); - - /* rescue mechanism */ - if (count >= 10) { - kp_g_core_fp->fp_0f_op_file_dirly(fwname); - kp_g_core_fp->fp_reload_disable(0); - kp_g_core_fp->fp_sense_on(0x00); - kp_himax_int_enable(1); - } - - return 0; -} -#endif -#endif - -static bool hx83102e_read_event_stack(uint8_t *buf, uint8_t length) -{ - struct timespec t_start, t_end, t_delta; - int len = length; - int i2c_speed = 0; - - if ((*kp_private_ts)->debug_log_level & BIT(2)) - getnstimeofday(&t_start); - - kp_himax_bus_read((*kp_pfw_op)->addr_event_addr[0], buf, length, - HIMAX_I2C_RETRY_TIMES); - - if ((*kp_private_ts)->debug_log_level & BIT(2)) { - getnstimeofday(&t_end); - t_delta.tv_nsec = (t_end.tv_sec * 1000000000 + t_end.tv_nsec) - - (t_start.tv_sec - * 1000000000 - + t_start.tv_nsec); /*ns*/ - - i2c_speed = (len * 9 * 1000000 - / (int)t_delta.tv_nsec) * 13 / 10; - (*kp_private_ts)->bus_speed = (int)i2c_speed; - } - return 1; -} - -static void himax_hx83102ab_reg_re_init(uint8_t ic_name) -{ - I("%s:Entering!\n", __func__); - kp_himax_parse_assign_cmd(hx83102ab_fw_addr_sorting_mode_en, - (*kp_pfw_op)->addr_sorting_mode_en, - sizeof((*kp_pfw_op)->addr_sorting_mode_en)); - kp_himax_parse_assign_cmd(hx83102ab_fw_addr_selftest_addr_en, - (*kp_pfw_op)->addr_selftest_addr_en, - sizeof((*kp_pfw_op)->addr_selftest_addr_en)); -#if defined(HX_ZERO_FLASH) - kp_himax_parse_assign_cmd(hx83102ab_data_adc_cfg_1, - (*kp_pzf_op)->data_adc_cfg_1, - sizeof((*kp_pzf_op)->data_adc_cfg_1)); -#endif - - if (ic_name == 0x2a) { - kp_himax_parse_assign_cmd(hx83102a_data_df_rx, - (*kp_pdriver_op)->data_df_rx, - sizeof((*kp_pdriver_op)->data_df_rx)); - kp_himax_parse_assign_cmd(hx83102a_data_df_tx, - (*kp_pdriver_op)->data_df_tx, - sizeof((*kp_pdriver_op)->data_df_tx)); - kp_himax_parse_assign_cmd(hx83102a_data_df_x_res, - (*kp_pdriver_op)->data_df_x_res, - sizeof((*kp_pdriver_op)->data_df_x_res)); - kp_himax_parse_assign_cmd(hx83102a_data_df_y_res, - (*kp_pdriver_op)->data_df_y_res, - sizeof((*kp_pdriver_op)->data_df_y_res)); - } else { - kp_himax_parse_assign_cmd(hx83102b_data_df_x_res, - (*kp_pdriver_op)->data_df_x_res, - sizeof((*kp_pdriver_op)->data_df_x_res)); - kp_himax_parse_assign_cmd(hx83102b_data_df_y_res, - (*kp_pdriver_op)->data_df_y_res, - sizeof((*kp_pdriver_op)->data_df_y_res)); - } -} - -static void himax_hx83102ab_func_re_init(void) -{ - I("%s:Entering!\n", __func__); - kp_g_core_fp->fp_chip_init = hx83102_chip_init; - kp_g_core_fp->fp_sense_off = hx83102ab_sense_off; - kp_g_core_fp->fp_set_SMWP_enable = hx83102ab_set_SMWP_enable; - kp_g_core_fp->fp_set_HSEN_enable = hx83102ab_set_HSEN_enable; - kp_g_core_fp->fp_usb_detect_set = hx83102ab_usb_detect_set; - kp_g_core_fp->fp_read_DD_status = hx83102ab_read_DD_status; - kp_g_core_fp->fp_read_FW_status = hx83102ab_read_FW_status; - kp_g_core_fp->fp_power_on_init = hx83102ab_power_on_init; - kp_g_core_fp->fp_fts_ctpm_fw_upgrade_with_sys_fs_64k = - hx83102ab_fts_ctpm_fw_upgrade_with_sys_fs_64k; -#if defined(HX_ESD_RECOVERY) - kp_g_core_fp->fp_esd_ic_reset = hx83102ab_esd_ic_reset; -#endif -#if defined(HX_ZERO_FLASH) - kp_g_core_fp->fp_firmware_update_0f = hx83102ab_firmware_update_0f; -#if defined(HX_0F_DEBUG) - kp_g_core_fp->fp_firmware_read_0f = hx83102ab_firmware_read_0f; -#endif -#endif - -} - -static void himax_hx83102d_reg_re_init(void) -{ - I("%s:Entering!\n", __func__); - kp_himax_parse_assign_cmd(hx83102d_fw_addr_raw_out_sel, - (*kp_pfw_op)->addr_raw_out_sel, - sizeof((*kp_pfw_op)->addr_raw_out_sel)); -#if defined(HX_ZERO_FLASH) - kp_himax_parse_assign_cmd(hx83102d_zf_data_sram_start_addr, - (*kp_pzf_op)->data_sram_start_addr, - sizeof((*kp_pzf_op)->data_sram_start_addr)); - kp_himax_parse_assign_cmd(hx83102d_zf_data_adc_cfg_1, - (*kp_pzf_op)->data_adc_cfg_1, - sizeof((*kp_pzf_op)->data_adc_cfg_1)); - kp_himax_parse_assign_cmd(hx83102d_zf_data_adc_cfg_2, - (*kp_pzf_op)->data_adc_cfg_2, - sizeof((*kp_pzf_op)->data_adc_cfg_2)); - kp_himax_parse_assign_cmd(hx83102d_zf_data_adc_cfg_3, - (*kp_pzf_op)->data_adc_cfg_3, - sizeof((*kp_pzf_op)->data_adc_cfg_3)); -#endif - kp_himax_parse_assign_cmd(hx83102d_data_df_x_res, - (*kp_pdriver_op)->data_df_x_res, - sizeof((*kp_pdriver_op)->data_df_x_res)); - kp_himax_parse_assign_cmd(hx83102d_data_df_y_res, - (*kp_pdriver_op)->data_df_y_res, - sizeof((*kp_pdriver_op)->data_df_y_res)); - kp_himax_parse_assign_cmd(hx83102d_data_df_y_res, - (*kp_pdriver_op)->data_df_y_res, - sizeof((*kp_pdriver_op)->data_df_y_res)); - kp_himax_parse_assign_cmd(hx83102d_adr_osc_en, - (*kp_pic_op)->adr_osc_en, - sizeof((*kp_pic_op)->adr_osc_en)); - kp_himax_parse_assign_cmd(hx83102d_adr_osc_pw, - (*kp_pic_op)->adr_osc_pw, - sizeof((*kp_pic_op)->adr_osc_pw)); -} - -static void himax_hx83102d_func_re_init(void) -{ - I("%s:Entering!\n", __func__); - kp_g_core_fp->fp_chip_init = hx83102_chip_init; - kp_g_core_fp->fp_sense_off = hx83102d_sense_off; - kp_g_core_fp->fp_ic_id_read = hx83102d_ic_id_read; - kp_g_core_fp->fp_dd_clk_set = hx83102d_dd_clk_set; - kp_g_core_fp->fp_dd_reg_en = hx83102d_dd_reg_en; -#if defined(HX_ZERO_FLASH) - /*kp_g_core_fp->fp_firmware_update_0f = hx83102d_firmware_update_0f;*/ - kp_g_core_fp->fp_resume_ic_action = himax_hx83102d_resume_ic_action; - kp_g_core_fp->fp_suspend_ic_action = himax_hx83102d_suspend_ic_action; - kp_g_core_fp->fp_sense_on = himax_hx83102d_sense_on; - kp_g_core_fp->fp_0f_reload_to_active = himax_hx83102d_reload_to_active; -#if defined(HX_0F_DEBUG) - kp_g_core_fp->fp_firmware_read_0f = hx83102d_firmware_read_0f; -#endif -#if defined(HX_CODE_OVERLAY) - kp_g_core_fp->fp_0f_overlay = hx83102d_0f_overlay; -#endif -#if defined(HX_ESD_RECOVERY) - kp_g_core_fp->fp_0f_esd_check = hx83102d_0f_esd_check; -#endif -#endif -} - -static void himax_hx83102e_reg_re_init(void) -{ - I("%s:Entering!\n", __func__); - kp_himax_parse_assign_cmd(hx83102e_fw_addr_raw_out_sel, - (*kp_pfw_op)->addr_raw_out_sel, - sizeof((*kp_pfw_op)->addr_raw_out_sel)); - kp_himax_parse_assign_cmd(hx83102e_data_df_rx, - (*kp_pdriver_op)->data_df_rx, - sizeof((*kp_pdriver_op)->data_df_rx)); - kp_himax_parse_assign_cmd(hx83102e_data_df_tx, - (*kp_pdriver_op)->data_df_tx, - sizeof((*kp_pdriver_op)->data_df_tx)); - kp_himax_parse_assign_cmd(hx83102e_data_df_x_res, - (*kp_pdriver_op)->data_df_x_res, - sizeof((*kp_pdriver_op)->data_df_x_res)); - kp_himax_parse_assign_cmd(hx83102e_data_df_y_res, - (*kp_pdriver_op)->data_df_y_res, - sizeof((*kp_pdriver_op)->data_df_y_res)); - kp_himax_parse_assign_cmd(hx83102e_ic_adr_tcon_rst, - (*kp_pic_op)->addr_tcon_on_rst, - sizeof((*kp_pic_op)->addr_tcon_on_rst)); -} - -static void himax_hx83102e_func_re_init(void) -{ - I("%s:Entering!\n", __func__); - - kp_g_core_fp->fp_chip_init = hx83102e_chip_init; - kp_g_core_fp->fp_sense_on = hx83102e_sense_on; - kp_g_core_fp->fp_sense_off = hx83102e_sense_off; - kp_g_core_fp->fp_read_event_stack = hx83102e_read_event_stack; -} - - -static bool hx83102_chip_detect(void) -{ - uint8_t tmp_data[DATA_LEN_4]; - uint8_t tmp_addr[DATA_LEN_4]; - bool ret_data = false; - int ret = 0; - int i = 0; - - if (himax_ic_setup_external_symbols()) - return false; - -#if defined(HX_RST_PIN_FUNC) - hx83102_pin_reset(); -#endif - - ret = kp_himax_bus_read(0x13, tmp_data, 1, HIMAX_I2C_RETRY_TIMES); - if (ret < 0) { - E("%s: i2c access fail!\n", __func__); - return false; - } - if (hx83102_sense_off(false) == false) { - ret_data = false; - E("%s:hx83102_sense_off Fail:\n", __func__); - return ret_data; - } - - for (i = 0; i < 5; i++) { - tmp_addr[3] = 0x90; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x00; - tmp_addr[0] = 0xD0; - ret = hx83102_register_read(tmp_addr, DATA_LEN_4, tmp_data); - if (ret != 0) { - ret_data = false; - E("%s:hx83102_register_read Fail:\n", __func__); - return ret_data; - } - I("%s:Read driver IC ID = %X,%X,%X\n", __func__, tmp_data[3], - tmp_data[2], tmp_data[1]); /*83,10,2X*/ - - if ((tmp_data[3] == 0x83) - && (tmp_data[2] == 0x10) - && ((tmp_data[1] == 0x2a) - || (tmp_data[1] == 0x2b) - || (tmp_data[1] == 0x2d) - || (tmp_data[1] == 0x2e))) { - if (tmp_data[1] == 0x2a) { - strlcpy((*kp_private_ts)->chip_name, - HX_83102A_SERIES_PWON, 30); - (*kp_ic_data)->ic_adc_num = - hx83102a_data_adc_num; - I("%s:detect IC HX83102A successfully\n", - __func__); - } else if (tmp_data[1] == 0x2b) { - strlcpy((*kp_private_ts)->chip_name, - HX_83102B_SERIES_PWON, 30); - (*kp_ic_data)->ic_adc_num = - hx83102b_data_adc_num; - I("%s:detect IC HX83102B successfully\n", - __func__); - } else if (tmp_data[1] == 0x2d) { - strlcpy((*kp_private_ts)->chip_name, - HX_83102D_SERIES_PWON, 30); - (*kp_ic_data)->ic_adc_num = - hx83102d_data_adc_num; - I("%s:detect IC HX83102D successfully\n", - __func__); - } else { - strlcpy((*kp_private_ts)->chip_name, - HX_83102E_SERIES_PWON, 30); - (*kp_ic_data)->ic_adc_num = - hx83102e_data_adc_num; - I("%s:detect IC HX83102E successfully\n", - __func__); - } - - ret = kp_himax_mcu_in_cmd_struct_init(); - if (ret < 0) { - ret_data = false; - E("%s:cmd_struct_init Fail:\n", __func__); - return ret_data; - } - - kp_himax_mcu_in_cmd_init(); - if ((tmp_data[1] == 0x2a) || (tmp_data[1] == 0x2b)) { - himax_hx83102ab_reg_re_init(tmp_data[1]); - himax_hx83102ab_func_re_init(); - } else if (tmp_data[1] == 0x2d) { - himax_hx83102d_reg_re_init(); - himax_hx83102d_func_re_init(); - } else {/* 0x2e */ - himax_hx83102e_reg_re_init(); - himax_hx83102e_func_re_init(); - } - ret_data = true; - break; - } - - ret_data = false; - E("%s:Read driver ID register Fail:\n", __func__); - E("Could NOT find Himax Chipset\n"); - E("Please check 1.VCCD,VCCA,VSP,VSN\n"); - E("2. LCM_RST,TP_RST\n"); - E("3. Power On Sequence\n"); - - } - - return ret_data; -} - -DECLARE(HX_MOD_KSYM_HX83102); - -static int himax_hx83102_probe(void) -{ - I("%s:Enter\n", __func__); - himax_add_chip_dt(hx83102_chip_detect); - - return 0; -} - -static int himax_hx83102_remove(void) -{ - free_chip_dt_table(); - return 0; -} - -static int __init himax_hx83102_init(void) -{ - int ret = 0; - - I("%s\n", __func__); - ret = himax_hx83102_probe(); - return 0; -} - -static void __exit himax_hx83102_exit(void) -{ - himax_hx83102_remove(); -} - -module_init(himax_hx83102_init); -module_exit(himax_hx83102_exit); - -MODULE_DESCRIPTION("HIMAX HX83102 touch driver"); -MODULE_LICENSE("GPL"); - +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for HX83102 chipset + * + * 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_ic_HX83102d.h" +#include "himax_modular.h" + +static void hx83102_chip_init(void) +{ + (*kp_private_ts)->chip_cell_type = CHIP_IS_IN_CELL; + I("%s:IC cell type = %d\n", __func__, (*kp_private_ts)->chip_cell_type); + (*kp_IC_CHECKSUM) = HX_TP_BIN_CHECKSUM_CRC; + /*Himax: Set FW and CFG Flash Address*/ + (*kp_FW_VER_MAJ_FLASH_ADDR) = 49157; /*0x00C005*/ + (*kp_FW_VER_MAJ_FLASH_LENG) = 1; + (*kp_FW_VER_MIN_FLASH_ADDR) = 49158; /*0x00C006*/ + (*kp_FW_VER_MIN_FLASH_LENG) = 1; + (*kp_CFG_VER_MAJ_FLASH_ADDR) = 49408; /*0x00C100*/ + (*kp_CFG_VER_MAJ_FLASH_LENG) = 1; + (*kp_CFG_VER_MIN_FLASH_ADDR) = 49409; /*0x00C101*/ + (*kp_CFG_VER_MIN_FLASH_LENG) = 1; + (*kp_CID_VER_MAJ_FLASH_ADDR) = 49154; /*0x00C002*/ + (*kp_CID_VER_MAJ_FLASH_LENG) = 1; + (*kp_CID_VER_MIN_FLASH_ADDR) = 49155; /*0x00C003*/ + (*kp_CID_VER_MIN_FLASH_LENG) = 1; + /*PANEL_VERSION_ADDR = 49156;*/ /*0x00C004*/ + /*PANEL_VERSION_LENG = 1;*/ +} + +static void hx83102e_chip_init(void) +{ + (*kp_private_ts)->chip_cell_type = CHIP_IS_IN_CELL; + I("%s:IC cell type = %d\n", __func__, (*kp_private_ts)->chip_cell_type); + (*kp_IC_CHECKSUM) = HX_TP_BIN_CHECKSUM_CRC; + /*Himax: Set FW and CFG Flash Address*/ + (*kp_FW_VER_MAJ_FLASH_ADDR) = 59397; /*0x00E805*/ + (*kp_FW_VER_MAJ_FLASH_LENG) = 1; + (*kp_FW_VER_MIN_FLASH_ADDR) = 59398; /*0x00E806*/ + (*kp_FW_VER_MIN_FLASH_LENG) = 1; + (*kp_CFG_VER_MAJ_FLASH_ADDR) = 59648; /*0x00E900*/ + (*kp_CFG_VER_MAJ_FLASH_LENG) = 1; + (*kp_CFG_VER_MIN_FLASH_ADDR) = 59649; /*0x00E901*/ + (*kp_CFG_VER_MIN_FLASH_LENG) = 1; + (*kp_CID_VER_MAJ_FLASH_ADDR) = 59394; /*0x00E802*/ + (*kp_CID_VER_MAJ_FLASH_LENG) = 1; + (*kp_CID_VER_MIN_FLASH_ADDR) = 59395; /*0x00E803*/ + (*kp_CID_VER_MIN_FLASH_LENG) = 1; + /*PANEL_VERSION_ADDR = 49156;*/ /*0x00C004*/ + /*PANEL_VERSION_LENG = 1;*/ +} + +void hx83102_burst_enable(uint8_t auto_add_4_byte) +{ + uint8_t tmp_data[4]; + + tmp_data[0] = 0x31; + if (kp_himax_bus_write(0x13, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + + tmp_data[0] = (0x10 | auto_add_4_byte); + if (kp_himax_bus_write(0x0D, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } +} + +int hx83102_flash_write_burst(uint8_t *reg_byte, uint8_t *write_data) +{ + uint8_t data_byte[8]; + int i = 0, j = 0; + + for (i = 0; i < 4; i++) + data_byte[i] = reg_byte[i]; + for (j = 4; j < 8; j++) + data_byte[j] = write_data[j-4]; + + if (kp_himax_bus_write(0x00, data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + return 0; +} + +static int hx83102_register_read(uint8_t *read_addr, int read_length, uint8_t *read_data) +{ + uint8_t tmp_data[4]; + int i = 0; + int address = 0; + + if (read_length > 256) { + E("%s: read len over 256!\n", __func__); + return LENGTH_FAIL; + } + if (read_length > 4) + hx83102_burst_enable(1); + else + hx83102_burst_enable(0); + + address = (read_addr[3] << 24) + (read_addr[2] << 16) + (read_addr[1] << 8) + read_addr[0]; + i = address; + tmp_data[0] = (uint8_t)i; + tmp_data[1] = (uint8_t)(i >> 8); + tmp_data[2] = (uint8_t)(i >> 16); + tmp_data[3] = (uint8_t)(i >> 24); + if (kp_himax_bus_write(0x00, tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + tmp_data[0] = 0x00; + if (kp_himax_bus_write(0x0C, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + + if (kp_himax_bus_read(0x08, read_data, read_length, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return I2C_FAIL; + } + if (read_length > 4) + hx83102_burst_enable(0); + + return 0; +} + +#ifdef HX_RST_PIN_FUNC +static void hx83102_pin_reset(void) +{ + I("%s: Now reset the Touch chip.\n", __func__); + kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 0); + msleep(20); + kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 1); + msleep(50); +} +#endif + +static bool hx83102_sense_off(bool check_en) +{ + uint8_t cnt = 0; + uint8_t tmp_addr[DATA_LEN_4]; + uint8_t tmp_writ[DATA_LEN_4]; + uint8_t tmp_data[DATA_LEN_4]; + + do { + if (cnt == 0 || (tmp_data[0] != 0xA5 && tmp_data[0] != 0x00 && tmp_data[0] != 0x87)) { + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x5C; + tmp_writ[3] = 0x00; tmp_writ[2] = 0x00; tmp_writ[1] = 0x00; tmp_writ[0] = 0xA5; + hx83102_flash_write_burst(tmp_addr, tmp_writ); + } + msleep(20); + + /* check fw status */ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0xA8; + hx83102_register_read(tmp_addr, DATA_LEN_4, tmp_data); + + if (tmp_data[0] != 0x05) { + I("%s: Do not need wait FW, Status = 0x%02X!\n", __func__, tmp_data[0]); + break; + } + + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x5C; + hx83102_register_read(tmp_addr, DATA_LEN_4, tmp_data); + I("%s: cnt = %d, data[0] = 0x%02X!\n", __func__, cnt, tmp_data[0]); + } while (tmp_data[0] != 0x87 && (++cnt < 50) && check_en == true); + + cnt = 0; + + + do { + /*=========================================== + *I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 + *=========================================== + */ + tmp_data[0] = 0x27; + if (kp_himax_bus_write(0x31, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /*=========================================== + *I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 + *=========================================== + */ + tmp_data[0] = 0x95; + if (kp_himax_bus_write(0x32, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* ====================== + *Check enter_save_mode + *====================== + */ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0xA8; + hx83102_register_read(tmp_addr, ADDR_LEN_4, tmp_data); + I("%s: Check enter_save_mode data[0]=%X\n", __func__, tmp_data[0]); + + if (tmp_data[0] == 0x0C) { + /*===================================== + *Reset TCON + *===================================== + */ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + hx83102_flash_write_burst(tmp_addr, tmp_data); + usleep_range(1000, 1001); + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + hx83102_flash_write_burst(tmp_addr, tmp_data); + /*===================================== + *Reset ADC + *===================================== + */ + tmp_addr[3] = 0x80; + tmp_addr[2] = 0x02; + tmp_addr[1] = 0x00; + tmp_addr[0] = 0x94; + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = 0x00; + hx83102_flash_write_burst(tmp_addr, tmp_data); + usleep_range(1000, 1001); + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = 0x01; + hx83102_flash_write_burst(tmp_addr, tmp_data); + + return true; + } + usleep_range(10000, 10001); +#ifdef HX_RST_PIN_FUNC + hx83102_pin_reset(); +#endif + + } while (cnt++ < 15); + + return false; +} + +static bool hx83102ab_sense_off(bool check_en) +{ + uint8_t cnt = 0; + uint8_t tmp_addr[DATA_LEN_4]; + uint8_t tmp_data[DATA_LEN_4]; + + do { + /*=========================================== + *I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 + *=========================================== + */ + tmp_data[0] = 0x27; + if (kp_himax_bus_write(0x31, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /*=========================================== + *I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 + *=========================================== + */ + tmp_data[0] = 0x95; + if (kp_himax_bus_write(0x32, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* ====================== + *Check enter_save_mode + *====================== + */ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0xA8; + hx83102_register_read(tmp_addr, ADDR_LEN_4, tmp_data); + I("%s: Check enter_save_mode data[0]=%X\n", __func__, tmp_data[0]); + + if (tmp_data[0] == 0x0C) { + /*===================================== + *Reset TCON + *===================================== + */ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + hx83102_flash_write_burst(tmp_addr, tmp_data); + usleep_range(1000, 1001); + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + hx83102_flash_write_burst(tmp_addr, tmp_data); + /*===================================== + *Reset ADC + *===================================== + */ + tmp_addr[3] = 0x80; + tmp_addr[2] = 0x02; + tmp_addr[1] = 0x00; + tmp_addr[0] = 0x94; + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = 0x00; + hx83102_flash_write_burst(tmp_addr, tmp_data); + usleep_range(1000, 1001); + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = 0x01; + hx83102_flash_write_burst(tmp_addr, tmp_data); + + return true; + } + /*msleep(10);*/ + usleep_range(5000, 5001); +#ifdef HX_RST_PIN_FUNC + kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 0); + msleep(20); + kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 1); + msleep(50); +#endif + + } while (cnt++ < 5); + + return false; +} + +static void hx83102ab_set_SMWP_enable(uint8_t SMWP_enable, bool suspended) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t back_data[DATA_LEN_4]; + uint8_t retry_cnt = 0; + + kp_g_core_fp->fp_sense_off(true); + + do { + if (SMWP_enable) { + kp_himax_in_parse_assign_cmd(fw_func_handshaking_pwd, tmp_data, 4); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_smwp_enable, DATA_LEN_4, tmp_data, 0); + kp_himax_in_parse_assign_cmd(fw_func_handshaking_pwd, back_data, 4); + } else { + kp_himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_smwp_enable, DATA_LEN_4, tmp_data, 0); + kp_himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, back_data, 4); + } + + kp_g_core_fp->fp_register_read((*kp_pfw_op)->addr_smwp_enable, DATA_LEN_4, tmp_data, false); + /*I("%s: tmp_data[0]=%d, SMWP_enable=%d, retry_cnt=%d\n", __func__, tmp_data[0],SMWP_enable,retry_cnt);*/ + retry_cnt++; + } while ((tmp_data[3] != back_data[3] || tmp_data[2] != back_data[2] || tmp_data[1] != back_data[1] || tmp_data[0] != back_data[0]) && retry_cnt < HIMAX_REG_RETRY_TIMES); + + kp_g_core_fp->fp_sense_on(0x00); +} + +static void hx83102ab_set_HSEN_enable(uint8_t HSEN_enable, bool suspended) +{ + uint8_t tmp_data[DATA_LEN_4]; + + if (HSEN_enable) { + kp_himax_in_parse_assign_cmd(fw_func_handshaking_pwd, tmp_data, 4); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_hsen_enable, DATA_LEN_4, tmp_data, 0); + } else { + kp_himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_hsen_enable, DATA_LEN_4, tmp_data, 0); + } + + /*I("%s: tmp_data[0]=%d, HSEN_enable=%d, retry_cnt=%d\n", __func__, tmp_data[0],HSEN_enable,retry_cnt);*/ +} + +static void hx83102ab_usb_detect_set(uint8_t *cable_config) +{ + uint8_t tmp_data[DATA_LEN_4]; + + if (cable_config[1] == 0x01) { + kp_himax_in_parse_assign_cmd(fw_func_handshaking_pwd, tmp_data, 4); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_usb_detect, DATA_LEN_4, tmp_data, 0); + I("%s: USB detect status IN!\n", __func__); + } else { + kp_himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_usb_detect, DATA_LEN_4, tmp_data, 0); + I("%s: USB detect status OUT!\n", __func__); + } +} + +static uint8_t hx83102ab_read_DD_status(uint8_t *cmd_set, uint8_t *tmp_data) +{ + int cnt = 0; + uint8_t req_size = cmd_set[0]; + + cmd_set[3] = (*kp_pfw_op)->data_dd_request[0]; + + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_dd_handshak_addr, DATA_LEN_4, cmd_set, 0); + I("%s: cmd_set[0] = 0x%02X,cmd_set[1] = 0x%02X,cmd_set[2] = 0x%02X,cmd_set[3] = 0x%02X\n", + __func__, cmd_set[0], cmd_set[1], cmd_set[2], cmd_set[3]); + + /* Doing hand shaking 0xAA -> 0xBB */ + for (cnt = 0; cnt < 100; cnt++) { + kp_g_core_fp->fp_register_read((*kp_pfw_op)->addr_dd_handshak_addr, DATA_LEN_4, tmp_data, false); + usleep_range(10000, 10001); + + if (tmp_data[3] == (*kp_pfw_op)->data_dd_ack[0]) { + I("%s Data ready goto moving data\n", __func__); + break; + } + if (cnt >= 99) { + I("%s Data not ready in FW\n", __func__); + return FW_NOT_READY; + } + } + + kp_g_core_fp->fp_sense_off(true); + kp_g_core_fp->fp_register_read((*kp_pfw_op)->addr_dd_data_addr, req_size, tmp_data, false); + kp_g_core_fp->fp_sense_on(0x01); + return NO_ERR; +} + +static int hx83102ab_read_FW_status(uint8_t *state_addr, uint8_t *tmp_addr) +{ + uint8_t i; + uint8_t req_size = 0; + uint8_t status_addr[DATA_LEN_4]; /*0x10007F44*/ + uint8_t cmd_addr[DATA_LEN_4]; /*0x900000F8*/ + + if (state_addr[0] == 0x01) { + state_addr[1] = 0x04; + + for (i = 0; i < DATA_LEN_4; i++) { + /* 0x10007F44 */ + state_addr[i + 2] = (*kp_pfw_op)->addr_fw_dbg_msg_addr[i]; + status_addr[i] = (*kp_pfw_op)->addr_fw_dbg_msg_addr[i]; + } + + req_size = 0x04; + kp_g_core_fp->fp_sense_off(true); + kp_g_core_fp->fp_register_read(status_addr, req_size, tmp_addr, false); + kp_g_core_fp->fp_sense_on(0x01); + } else if (state_addr[0] == 0x02) { + state_addr[1] = 0x30; + + for (i = 0; i < DATA_LEN_4; i++) { + /* 0x900000F8 */ + state_addr[i + 2] = (*kp_pfw_op)->addr_fw_state_addr[i]; + cmd_addr[i] = (*kp_pfw_op)->addr_fw_state_addr[i]; + } + + req_size = 0x30; + kp_g_core_fp->fp_register_read(cmd_addr, req_size, tmp_addr, false); + } + + return NO_ERR; +} + +static void hx83102ab_power_on_init(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + + I("%s:\n", __func__); + kp_himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_raw_out_sel, DATA_LEN_4, tmp_data, 0); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_sorting_mode_en, DATA_LEN_4, tmp_data, 0); + kp_g_core_fp->fp_touch_information(); + kp_g_core_fp->fp_sense_on(0x00); +} + +static int hx83102ab_fts_ctpm_fw_upgrade_with_sys_fs_64k(unsigned char *fw, int len, bool change_iref) +{ + int burnFW_success = 0; + uint8_t tmp_data[DATA_LEN_4]; + + if (len != FW_SIZE_64k) { + E("%s: The file size is not 64K bytes\n", __func__); + return false; + } + +#ifdef HX_RST_PIN_FUNC + kp_g_core_fp->fp_ic_reset(false, false); +#else + kp_g_core_fp->fp_system_reset(); +#endif + kp_g_core_fp->fp_sense_off(true); + kp_g_core_fp->fp_chip_erase(); + kp_g_core_fp->fp_flash_programming(fw, FW_SIZE_64k); + + if (kp_g_core_fp->fp_check_CRC((*kp_pfw_op)->addr_program_reload_from, FW_SIZE_64k) == 0) + burnFW_success = 1; + + kp_himax_in_parse_assign_cmd(fw_data_safe_mode_release_pw_reset, tmp_data, 4); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_raw_out_sel, DATA_LEN_4, tmp_data, 0); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_sorting_mode_en, DATA_LEN_4, tmp_data, 0); +#ifdef HX_RST_PIN_FUNC + kp_g_core_fp->fp_ic_reset(false, false); +#else + /*System reset*/ + kp_g_core_fp->fp_system_reset(); +#endif + return burnFW_success; +} + +#ifdef HX_ESD_RECOVERY +static void hx83102ab_esd_ic_reset(void) +{ + (*kp_HX_ESD_RESET_ACTIVATE) = 1; +#ifdef HX_RST_PIN_FUNC + kp_g_core_fp->fp_pin_reset(); +#else + kp_g_core_fp->fp_system_reset(); +#endif + I("%s:\n", __func__); +} +#if defined(HX_ZERO_FLASH) +static int hx83102d_0f_esd_check(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + int ret = NO_ERR; + + I("Enter %s\n", __func__); + + kp_g_core_fp->fp_register_read((*kp_pzf_op)->addr_sts_chk, DATA_LEN_4, tmp_data, 0); + + if (tmp_data[0] != (*kp_pzf_op)->data_activ_sts[0]) { + ret = ERR_STS_WRONG; + I("%s:status : %8X = %2X\n", __func__, zf_addr_sts_chk, tmp_data[0]); + } + + kp_g_core_fp->fp_register_read((*kp_pzf_op)->addr_activ_relod, DATA_LEN_4, tmp_data, 0); + + if (tmp_data[0] != (*kp_pzf_op)->data_activ_in[0]) { + ret = ERR_STS_WRONG; + I("%s:status : %8X = %2X\n", __func__, zf_addr_activ_relod, tmp_data[0]); + } + + return ret; +} +#endif +#endif + +static bool hx83102d_sense_off(bool check_en) +{ + uint8_t cnt = 0; + uint8_t tmp_addr[DATA_LEN_4]; + uint8_t tmp_data[DATA_LEN_4]; + + do { + if (cnt == 0 || (tmp_data[0] != 0xA5 && tmp_data[0] != 0x00 && tmp_data[0] != 0x87)) + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_ctrl_fw_isr, DATA_LEN_4, (*kp_pfw_op)->data_fw_stop, 0); + /*msleep(20);*/ + usleep_range(10000, 10001); + + /* check fw status */ + kp_g_core_fp->fp_register_read((*kp_pic_op)->addr_cs_central_state, ADDR_LEN_4, tmp_data, 0); + + if (tmp_data[0] != 0x05) { + I("%s: Do not need wait FW, Status = 0x%02X!\n", __func__, tmp_data[0]); + break; + } + + kp_g_core_fp->fp_register_read((*kp_pfw_op)->addr_ctrl_fw_isr, 4, tmp_data, false); + I("%s: cnt = %d, data[0] = 0x%02X!\n", __func__, cnt, tmp_data[0]); + } while (tmp_data[0] != 0x87 && (++cnt < 10) && check_en == true); + + cnt = 0; + + do { + /*=========================================== + *I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27 + *=========================================== + */ + tmp_data[0] = 0x27; + if (kp_himax_bus_write(0x31, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /*=========================================== + *I2C_password[15:8] set Enter safe mode :0x32 ==> 0x95 + *=========================================== + */ + tmp_data[0] = 0x95; + if (kp_himax_bus_write(0x32, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + + /* ====================== + *Check enter_save_mode + *====================== + */ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0xA8; + hx83102_register_read(tmp_addr, ADDR_LEN_4, tmp_data); + I("%s: Check enter_save_mode data[0]=%X\n", __func__, tmp_data[0]); + + if (tmp_data[0] == 0x0C) { + /*===================================== + *Reset TCON + *===================================== + */ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + hx83102_flash_write_burst(tmp_addr, tmp_data); + usleep_range(1000, 1001); + tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + hx83102_flash_write_burst(tmp_addr, tmp_data); + /*===================================== + *Reset ADC + *===================================== + */ + tmp_addr[3] = 0x80; + tmp_addr[2] = 0x02; + tmp_addr[1] = 0x00; + tmp_addr[0] = 0x94; + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = 0x00; + hx83102_flash_write_burst(tmp_addr, tmp_data); + usleep_range(1000, 1001); + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = 0x01; + hx83102_flash_write_burst(tmp_addr, tmp_data); + + return true; + } + /*msleep(10);*/ + usleep_range(5000, 5001); +#ifdef HX_RST_PIN_FUNC + kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 0); + msleep(20); + kp_himax_rst_gpio_set((*kp_private_ts)->rst_gpio, 1); + msleep(50); +#endif + + } while (cnt++ < 5); + + return false; +} + +static bool hx83102d_dd_clk_set(bool enable) +{ + uint8_t data[4] = {0}; + + data[0] = (enable)?0xDD:0; + return (kp_g_core_fp->fp_register_write((*kp_pic_op)->adr_osc_en, + sizeof((*kp_pic_op)->adr_osc_en), data, 0) == NO_ERR); +} + +static void hx83102d_dd_reg_en(bool enable) +{ + uint8_t data[4] = {0}; + + data[0] = 0xA5; data[1] = 0x00; + data[2] = 0x00; data[3] = 0x00; + kp_g_core_fp->fp_register_write((*kp_pic_op)->adr_osc_pw, DATA_LEN_4, data, 0); + + data[0] = 0xA5; data[1] = 0x83; + data[2] = 0x10; data[3] = 0x2D; + kp_g_core_fp->fp_dd_reg_write(0xB9, 0, 4, data, 0); +} + +static bool hx83102d_ic_id_read(void) +{ + int i = 0; + uint8_t data[4] = {0}; + + kp_g_core_fp->fp_dd_clk_set(true); + kp_g_core_fp->fp_dd_reg_en(true); + + for (i = 0; i < 13; i++) { + data[0] = 0x2A + i; + kp_g_core_fp->fp_dd_reg_write(0xBB, 3, 1, data, 0); + data[0] = 0x08; + kp_g_core_fp->fp_dd_reg_write(0xBB, 1, 1, data, 0); + kp_g_core_fp->fp_dd_reg_read(0xBB, 6, 1, data, 0); + (*kp_ic_data)->vendor_ic_id[i] = data[0]; + I("ic_data->vendor_ic_id[%d] = %02X\n", i, (*kp_ic_data)->vendor_ic_id[i]); + } + + kp_g_core_fp->fp_dd_clk_set(false); + + return true; +} + +#if defined(HX_ZERO_FLASH) +static void himax_hx83102d_reload_to_active(void) +{ + uint8_t addr[DATA_LEN_4] = {0}; + uint8_t data[DATA_LEN_4] = {0}; + uint8_t retry_cnt = 0; + + addr[3] = 0x90; + addr[2] = 0x00; + addr[1] = 0x00; + addr[0] = 0x48; + + do { + data[3] = 0x00; + data[2] = 0x00; + data[1] = 0x00; + data[0] = 0xEC; + kp_g_core_fp->fp_register_write(addr, DATA_LEN_4, data, 0); + usleep_range(1000, 1100); + kp_g_core_fp->fp_register_read(addr, DATA_LEN_4, data, 0); + I("%s: data[1]=%d, data[0]=%d, retry_cnt=%d\n", __func__, data[1], data[0], retry_cnt); + retry_cnt++; + } while ((data[1] != 0x01 || data[0] != 0xEC) && retry_cnt < HIMAX_REG_RETRY_TIMES); +} + +static void himax_hx83102d_resume_ic_action(void) +{ +#ifndef HX_RESUME_HW_RESET + himax_hx83102d_reload_to_active(); +#endif +} + +static void himax_hx83102d_suspend_ic_action(void) +{ +#ifndef HX_RESUME_HW_RESET + himax_hx83102d_reload_to_active(); +#endif +} + +static void himax_hx83102d_sense_on(uint8_t FlashMode) +{ + uint8_t tmp_data[DATA_LEN_4]; + int retry = 0; + + I("Enter %s\n", __func__); + + kp_g_core_fp->fp_interface_on(); + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_ctrl_fw_isr, + sizeof((*kp_pfw_op)->data_clear), (*kp_pfw_op)->data_clear, 0); + /*msleep(20);*/ + usleep_range(10000, 10001); + if (!FlashMode) { +#ifdef HX_RST_PIN_FUNC + kp_g_core_fp->fp_ic_reset(false, false); +#else + kp_g_core_fp->fp_system_reset(); +#endif + himax_hx83102d_reload_to_active(); + } else { + himax_hx83102d_reload_to_active(); + do { + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_safe_mode_release_pw, + sizeof((*kp_pfw_op)->data_safe_mode_release_pw_active), (*kp_pfw_op)->data_safe_mode_release_pw_active, 0); + + kp_g_core_fp->fp_register_read((*kp_pfw_op)->addr_flag_reset_event, DATA_LEN_4, tmp_data, 0); + I("%s:Read status from IC = %X,%X\n", __func__, tmp_data[0], tmp_data[1]); + } while ((tmp_data[1] != 0x01 || tmp_data[0] != 0x00) && retry++ < 5); + + if (retry >= 5) { + E("%s: Fail:\n", __func__); +#ifdef HX_RST_PIN_FUNC + kp_g_core_fp->fp_ic_reset(false, false); +#else + kp_g_core_fp->fp_system_reset(); +#endif + himax_hx83102d_reload_to_active(); + } else { + I("%s:OK and Read status from IC = %X,%X\n", __func__, tmp_data[0], tmp_data[1]); + /* reset code*/ + tmp_data[0] = 0x00; + + if (kp_himax_bus_write((*kp_pic_op)->adr_i2c_psw_lb[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) + E("%s: i2c access fail!\n", __func__); + + if (kp_himax_bus_write((*kp_pic_op)->adr_i2c_psw_ub[0], tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) + E("%s: i2c access fail!\n", __func__); + + kp_g_core_fp->fp_register_write((*kp_pfw_op)->addr_safe_mode_release_pw, + sizeof((*kp_pfw_op)->data_safe_mode_release_pw_reset), (*kp_pfw_op)->data_safe_mode_release_pw_reset, 0); + } + } +} + +static void hx83102ab_firmware_update_0f(const struct firmware *fw_entry) +{ + uint8_t tmp_addr[4]; + + I("%s, Entering\n", __func__); + + kp_g_core_fp->fp_register_write((*kp_pzf_op)->addr_system_reset, 4, (*kp_pzf_op)->data_system_reset, 0); + + kp_g_core_fp->fp_sense_off(false); + + /* first 32K */ + /*bin file start*/ + /*isram*/ + kp_g_core_fp->fp_write_sram_0f(fw_entry, (*kp_pzf_op)->data_sram_start_addr, 0, HX_32K_SZ); + + tmp_addr[3] = 0x10; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x73; + tmp_addr[0] = 0x00; + kp_g_core_fp->fp_write_sram_0f(fw_entry, tmp_addr, 0x8000, (0x200*4)); + + tmp_addr[3] = 0x10; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x68; + tmp_addr[0] = 0x00; + kp_g_core_fp->fp_write_sram_0f(fw_entry, tmp_addr, 0x8800, (0x200*4)); + + /*last 16k*/ + /*config info*/ + tmp_addr[3] = 0x10; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x72; + tmp_addr[0] = 0x04; /*0x10007206 <= size 60,from 0x0000C180*/ + kp_g_core_fp->fp_write_sram_0f(fw_entry, tmp_addr, 0xC178, (84)); + + /*FW config*/ + if ((*kp_G_POWERONOF) == 1) + kp_g_core_fp->fp_write_sram_0f(fw_entry, (*kp_pzf_op)->data_fw_cfg_1, 0xBFFE, 388); + else + kp_g_core_fp->fp_clean_sram_0f((*kp_pzf_op)->data_fw_cfg_1, 388, 1); + /*ADC config*/ + if ((*kp_G_POWERONOF) == 1) + kp_g_core_fp->fp_write_sram_0f(fw_entry, (*kp_pzf_op)->data_adc_cfg_1, 0xe000, (128 * 4)); + else + kp_g_core_fp->fp_clean_sram_0f((*kp_pzf_op)->data_adc_cfg_1, (128 * 4), 2); + + I("%s, END\n", __func__); +} +#if defined(HX_0F_DEBUG) +static void hx83102ab_firmware_read_0f(const struct firmware *fw_entry, int type) +{ + uint8_t tmp_addr[4]; + + I("%s, Entering\n", __func__); + if (type == 0) { /* first 32K */ + kp_g_core_fp->fp_read_sram_0f(fw_entry, (*kp_pzf_op)->data_sram_start_addr, 0, HX_32K_SZ); + tmp_addr[3] = 0x10; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x68; + tmp_addr[0] = 0x00; + kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_addr, 0x8000, (0x200*4)); + + tmp_addr[3] = 0x10; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x73; + tmp_addr[0] = 0x00; + kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_addr, 0x8800, (0x200*4)); + + } else { /*last 16k*/ + tmp_addr[3] = 0x10; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x72; + tmp_addr[0] = 0x04; /*0x10007206 <= size 80,from 0x0000C180*/ + kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_addr, 0xC178, (84)); + + kp_g_core_fp->fp_read_sram_0f(fw_entry, (*kp_pzf_op)->data_fw_cfg_1, 0xBFFE, 388); + kp_g_core_fp->fp_read_sram_0f(fw_entry, (*kp_pzf_op)->data_adc_cfg_1, 0xE000, (128*4)); + + } + I("%s, END\n", __func__); +} +static void hx83102d_firmware_read_0f(const struct firmware *fw_entry, int type) +{ + uint8_t tmp_data[4]; + + I("%s, Entering\n", __func__); + + switch (type) { + case 0: + kp_g_core_fp->fp_read_sram_0f(fw_entry, (*kp_pzf_op)->data_sram_start_addr, 0, HX_40K_SZ); + break; + case 1: + kp_g_core_fp->fp_read_sram_0f(fw_entry, (*kp_pzf_op)->data_cfg_info, 0xC000, 132); + break; + case 2: + kp_g_core_fp->fp_read_sram_0f(fw_entry, (*kp_pzf_op)->data_fw_cfg_1, 0xC0FE, 484); + break; + case 3: + kp_g_core_fp->fp_read_sram_0f(fw_entry, (*kp_pzf_op)->data_adc_cfg_1, 0xD000, 768); + break; + case 4: + kp_g_core_fp->fp_read_sram_0f(fw_entry, (*kp_pzf_op)->data_adc_cfg_2, 0xD300, 1536); + break; + case 5: + kp_g_core_fp->fp_read_sram_0f(fw_entry, (*kp_pzf_op)->data_adc_cfg_3, 0xE000, 1536); + break; + case 6: + kp_himax_in_parse_assign_cmd(hx83102d_zf_data_bor_prevent_info, tmp_data, 4); + kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_data, 0xC9E0, 32); + break; + case 7: + kp_himax_in_parse_assign_cmd(hx83102d_zf_data_notch_info, tmp_data, 4); + kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_data, 0xCA00, 128); + break; + case 8: + kp_himax_in_parse_assign_cmd(hx83102d_zf_func_info_en, tmp_data, 4); + kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_data, 0xCB00, 12); + break; + case 9: + kp_himax_in_parse_assign_cmd(hx83102d_zf_po_sub_func, tmp_data, 4); + kp_g_core_fp->fp_read_sram_0f(fw_entry, tmp_data, 0xA000, HX4K); + break; + default: + break; + } + I("%s, END\n", __func__); +} +#endif +#if defined(HX_CODE_OVERLAY) +static int hx83102d_0f_overlay(int ovl_type, int mode) +{ + int ret = 0; + uint8_t count = 0; + uint8_t count2 = 0; + const struct firmware *fwp = NULL; + char fwname[32] = "Himax_firmware.bin"; + uint8_t part_num = 0; + uint8_t buf[16]; + uint8_t handshaking_addr[4] = {0xFC, 0x7F, 0x00, 0x10}; + /*uint8_t mpap_addr[4] = {0xEC, 0x73, 0x00, 0x10};*/ + uint8_t ovl_idx_t; + uint8_t request; + uint8_t reply; + uint8_t sram_addr[4] = {0}; + uint32_t offset = 0; + uint32_t size = 0; + uint8_t send_data[4] = {0}; + uint8_t recv_data[4] = {0}; + + ret = request_firmware(&fwp, fwname, (*kp_private_ts)->dev); + if (ret < 0) { + E("%s: request firmware FAIL!!!\n", __func__); + return ret; + } + + /*1. get number of partition*/ + part_num = fwp->data[HX64K + 12]; + if (part_num <= 1) { + E("%s, size of cfg part failed! part_num = %d\n", + __func__, part_num); + return LENGTH_FAIL; + } + + I("%s: overlay section %d\n", __func__, ovl_type-1); + if (ovl_type == 2) { + request = ovl_gesture_request; + reply = ovl_gesture_reply; + } else if (ovl_type == 3) { + request = ovl_border_request; + reply = ovl_border_reply; + } else { + E("%s: error overlay type %d\n", __func__, ovl_type); + return HX_INIT_FAIL; + } + ovl_idx_t = *((*kp_ovl_idx) + ovl_type - 1); + memcpy(buf, &fwp->data[ovl_idx_t * 0x10 + HX64K], 16); + memcpy(sram_addr, buf, 4); + offset = buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8]; + size = buf[7]<<24 | buf[6]<<16 | buf[5]<<8 | buf[4]; + +/* + * if (ovl_type == 1) { + * if (mode == 0) { + * //border overlay when finish self_test + * send_data[3] = 0x00; + * send_data[2] = 0x00; + * send_data[1] = 0x00; + * send_data[0] = 0x00; + * offset = zf_info_arr[2].fw_addr; + * size = zf_info_arr[2].write_size; + * I("%s: self test overlay section 2\n", __func__); + * } else if (mode == 1) { + * //sorting overlay when call self_test + * send_data[3] = 0x00; + * send_data[2] = 0x10; + * send_data[1] = 0x73; + * send_data[0] = 0x80; + * offset = zf_info_arr[0].fw_addr; + * size = zf_info_arr[0].write_size; + * I("%s: self test overlay section 0\n", __func__); + * } + * } + */ + +/* + * if (ovl_type == 1) { + * + * g_core_fp.fp_sense_off(false); + * + * //g_core_fp.fp_register_write(mpap_addr, DATA_LEN_4, send_data, 0); + * count = 0; + * do { + * g_core_fp.fp_register_write(mpap_addr, DATA_LEN_4, send_data, 0); + * g_core_fp.fp_register_read(mpap_addr, DATA_LEN_4, recv_data, 0); + * } while ((recv_data[0] != send_data[0] || recv_data[1] != send_data[1] || recv_data[2] != send_data[2] || recv_data[3] != send_data[3]) && count++ < 10); + * + * I("%s: set mpap pw %d times\n", __func__, count); + * + * //g_core_fp.fp_write_sram_0f(fwp, sram_addr, offset, size); + * if (kp_g_core_fp->fp_write_sram_0f_crc(fwp, sram_addr, offset, size) != 0) + * E("%s, Overlay HW CRC FAIL\n", __func__); + * + * g_core_fp.fp_reload_disable(0); + * + * g_core_fp.fp_sense_on(0x00); + * + * } else { + */ + + count = 0; + do { + kp_g_core_fp->fp_register_read(handshaking_addr, DATA_LEN_4, recv_data, 0); + } while (recv_data[0] != request && count++ < 10); + + if (count < 10) { + /*g_core_fp.fp_write_sram_0f(fwp, sram_addr, offset, size);*/ + if (kp_g_core_fp->fp_write_sram_0f_crc(fwp, sram_addr, offset, size) != 0) + E("%s, Overlay HW CRC FAIL\n", __func__); + + send_data[3] = 0x00; + send_data[2] = 0x00; + send_data[1] = 0x00; + send_data[0] = reply; + + count2 = 0; + do { + kp_g_core_fp->fp_register_write(handshaking_addr, DATA_LEN_4, send_data, 0); + usleep_range(1000, 1100); + kp_g_core_fp->fp_register_read(handshaking_addr, DATA_LEN_4, recv_data, 0); + } while (recv_data[0] != reply && count2++ < 10); + + if (ovl_type == 3) { +#ifdef HX_RST_PIN_FUNC + kp_g_core_fp->fp_ic_reset(false, false); +#else + kp_g_core_fp->fp_system_reset(); +#endif + } + } + + I("%s: overlay request %d times; reply %d times\n", __func__, count, count2); + + release_firmware(fwp); + + /* rescue mechanism */ + if (count >= 10) { + + kp_g_core_fp->fp_0f_op_file_dirly(fwname); + + kp_g_core_fp->fp_reload_disable(0); + + kp_g_core_fp->fp_sense_on(0x00); + + kp_himax_int_enable(1); + } + + return 0; +} +#endif +#endif + +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) +#if defined(HX_EN_DYNAMIC_NAME) +static void hx83102a_read_ic_ver(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t tmp_addr[DATA_LEN_4]; + + (*kp_ic_data)->vendor_ic_ver = 0xFFFF; + /* Enable read DD */ + tmp_data[0] = 0x00; + tmp_data[1] = 0x83; + tmp_data[2] = 0x10; + tmp_data[3] = 0x2A; + kp_himax_in_parse_assign_cmd(hx83102_ic_b9_en, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, false); + + /* Read DD data */ + kp_himax_in_parse_assign_cmd(hx83102_ic_fw, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); + I("E8=%X\n", tmp_data[0]); + (*kp_ic_data)->vendor_ic_ver = tmp_data[0]; + + I("VENDOR_IC_VER : %X\n", ((*kp_ic_data)->vendor_ic_ver)); +} + +static void hx83102b_read_ic_ver(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t tmp_addr[DATA_LEN_4]; + + (*kp_ic_data)->vendor_ic_ver = 0xFFFF; + /* Enable read DD */ + kp_himax_in_parse_assign_cmd(hx83102b_ic_osc_en, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); + tmp_data[0] = 0x01; + kp_g_core_fp->fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, false); + + tmp_data[0] = 0x00; + tmp_data[1] = 0x83; + tmp_data[2] = 0x10; + tmp_data[3] = 0x2B; + kp_himax_in_parse_assign_cmd(hx83102_ic_b9_en, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, false); + + /* Read DD data */ + kp_himax_in_parse_assign_cmd(hx83102_ic_fw, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); + I("E8=%X\n", tmp_data[0]); + (*kp_ic_data)->vendor_ic_ver = tmp_data[0]; + + /* Disable read DD */ + kp_himax_in_parse_assign_cmd(hx83102b_ic_osc_en, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); + tmp_data[0] = 0x00; + kp_g_core_fp->fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, false); + + I("VENDOR_IC_VER : %X\n", ((*kp_ic_data)->vendor_ic_ver)); +} + +static void hx83102d_read_ic_ver(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t tmp_addr[DATA_LEN_4]; + + (*kp_ic_data)->vendor_ic_ver = 0xFFFF; + /* Enable read DD */ + kp_himax_in_parse_assign_cmd(hx83102d_ic_osc_pw, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); + tmp_data[0] = 0xA5; + kp_g_core_fp->fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, false); + + kp_himax_in_parse_assign_cmd(hx83102d_ic_osc_en, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); + tmp_data[0] = 0xDD; + kp_g_core_fp->fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, false); + + tmp_data[0] = 0x00; + tmp_data[1] = 0x83; + tmp_data[2] = 0x10; + tmp_data[3] = 0x2D; + kp_himax_in_parse_assign_cmd(hx83102_ic_b9_en, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, false); + + /* Read DD data */ + kp_himax_in_parse_assign_cmd(hx83102_ic_fw, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); + I("E8=%X\n", tmp_data[0]); + (*kp_ic_data)->vendor_ic_ver = tmp_data[0]; + + /* Disable read DD */ + kp_himax_in_parse_assign_cmd(hx83102d_ic_osc_en, tmp_addr, sizeof(tmp_addr)); + kp_g_core_fp->fp_register_read(tmp_addr, DATA_LEN_4, tmp_data, 0); + tmp_data[0] = 0x00; + kp_g_core_fp->fp_register_write(tmp_addr, DATA_LEN_4, tmp_data, false); + + I("VENDOR_IC_VER : %X\n", ((*kp_ic_data)->vendor_ic_ver)); +} + +static void hx83102_dynamic_fw_name(uint8_t ic_name) +{ + char firmware_name[64]; + + if (ic_name == 0x2a) + hx83102a_read_ic_ver(); + else if (ic_name == 0x2b) + hx83102b_read_ic_ver(); + else + hx83102d_read_ic_ver(); + + if ((*kp_i_CTPM_firmware_name) != NULL) { + kfree((*kp_i_CTPM_firmware_name)); + (*kp_i_CTPM_firmware_name) = NULL; + } + memset(firmware_name, 0x00, sizeof(firmware_name)); + + if (((*kp_ic_data)->vendor_ic_ver == 0x00) || ((*kp_ic_data)->vendor_ic_ver == 0x21)) { /* Cut 1 */ + memcpy(firmware_name, "Himax_firmware_1.bin", sizeof(char)*strlen("Himax_firmware_1.bin")); + } else if (((*kp_ic_data)->vendor_ic_ver == 0x01) || ((*kp_ic_data)->vendor_ic_ver == 0x11)) { /* Cut 2 */ + memcpy(firmware_name, "Himax_firmware_2.bin", sizeof(char)*strlen("Himax_firmware_2.bin")); + } else { /* Original */ + memcpy(firmware_name, "Himax_firmware.bin", sizeof(char)*strlen("Himax_firmware.bin")); + } + + (*kp_i_CTPM_firmware_name) = kzalloc((sizeof(char)*(strlen(firmware_name)+1)), GFP_KERNEL); + if ((*kp_i_CTPM_firmware_name) != NULL) + memcpy((*kp_i_CTPM_firmware_name), firmware_name, (sizeof(char)*(strlen(firmware_name)+1))); + I("(*kp_i_CTPM_firmware_name) : %s\n", (*kp_i_CTPM_firmware_name)); +} +#endif +#endif + +static bool hx83102e_read_event_stack(uint8_t *buf, uint8_t length) +{ + struct timespec t_start, t_end, t_delta; + int len = length; + int i2c_speed = 0; + + if ((*kp_private_ts)->debug_log_level & BIT(2)) + getnstimeofday(&t_start); + + kp_himax_bus_read((*kp_pfw_op)->addr_event_addr[0], buf, length, HIMAX_I2C_RETRY_TIMES); + + if ((*kp_private_ts)->debug_log_level & BIT(2)) { + getnstimeofday(&t_end); + t_delta.tv_nsec = (t_end.tv_sec * 1000000000 + t_end.tv_nsec) - (t_start.tv_sec * 1000000000 + t_start.tv_nsec); /*ns*/ + i2c_speed = (len * 9 * 1000000 / (int)t_delta.tv_nsec) * 13 / 10; + (*kp_private_ts)->bus_speed = (int)i2c_speed; + } + return 1; +} + +static void himax_hx83102ab_reg_re_init(uint8_t ic_name) +{ + I("%s:Entering!\n", __func__); + kp_himax_in_parse_assign_cmd(hx83102ab_fw_addr_sorting_mode_en, (*kp_pfw_op)->addr_sorting_mode_en, sizeof((*kp_pfw_op)->addr_sorting_mode_en)); + kp_himax_in_parse_assign_cmd(hx83102ab_fw_addr_selftest_addr_en, (*kp_pfw_op)->addr_selftest_addr_en, sizeof((*kp_pfw_op)->addr_selftest_addr_en)); +#ifdef HX_ZERO_FLASH + kp_himax_in_parse_assign_cmd(hx83102ab_data_adc_cfg_1, (*kp_pzf_op)->data_adc_cfg_1, sizeof((*kp_pzf_op)->data_adc_cfg_1)); +#endif + + if (ic_name == 0x2a) { + kp_himax_in_parse_assign_cmd(hx83102a_data_df_rx, (*kp_pdriver_op)->data_df_rx, sizeof((*kp_pdriver_op)->data_df_rx)); + kp_himax_in_parse_assign_cmd(hx83102a_data_df_tx, (*kp_pdriver_op)->data_df_tx, sizeof((*kp_pdriver_op)->data_df_tx)); + kp_himax_in_parse_assign_cmd(hx83102a_data_df_x_res, (*kp_pdriver_op)->data_df_x_res, sizeof((*kp_pdriver_op)->data_df_x_res)); + kp_himax_in_parse_assign_cmd(hx83102a_data_df_y_res, (*kp_pdriver_op)->data_df_y_res, sizeof((*kp_pdriver_op)->data_df_y_res)); + } else { + kp_himax_in_parse_assign_cmd(hx83102b_data_df_x_res, (*kp_pdriver_op)->data_df_x_res, sizeof((*kp_pdriver_op)->data_df_x_res)); + kp_himax_in_parse_assign_cmd(hx83102b_data_df_y_res, (*kp_pdriver_op)->data_df_y_res, sizeof((*kp_pdriver_op)->data_df_y_res)); + } +} + +static void himax_hx83102ab_func_re_init(void) +{ + I("%s:Entering!\n", __func__); + kp_g_core_fp->fp_chip_init = hx83102_chip_init; + kp_g_core_fp->fp_sense_off = hx83102ab_sense_off; + kp_g_core_fp->fp_set_SMWP_enable = hx83102ab_set_SMWP_enable; + kp_g_core_fp->fp_set_HSEN_enable = hx83102ab_set_HSEN_enable; + kp_g_core_fp->fp_usb_detect_set = hx83102ab_usb_detect_set; + kp_g_core_fp->fp_read_DD_status = hx83102ab_read_DD_status; + kp_g_core_fp->fp_read_FW_status = hx83102ab_read_FW_status; + kp_g_core_fp->fp_power_on_init = hx83102ab_power_on_init; + kp_g_core_fp->fp_fts_ctpm_fw_upgrade_with_sys_fs_64k = hx83102ab_fts_ctpm_fw_upgrade_with_sys_fs_64k; +#ifdef HX_ESD_RECOVERY + kp_g_core_fp->fp_esd_ic_reset = hx83102ab_esd_ic_reset; +#endif +#if defined(HX_ZERO_FLASH) + kp_g_core_fp->fp_firmware_update_0f = hx83102ab_firmware_update_0f; +#if defined(HX_0F_DEBUG) + kp_g_core_fp->fp_firmware_read_0f = hx83102ab_firmware_read_0f; +#endif +#endif + +} + +static void himax_hx83102d_reg_re_init(void) +{ + I("%s:Entering!\n", __func__); + kp_himax_in_parse_assign_cmd(hx83102d_fw_addr_raw_out_sel, (*kp_pfw_op)->addr_raw_out_sel, sizeof((*kp_pfw_op)->addr_raw_out_sel)); +#if defined(HX_ZERO_FLASH) + kp_himax_in_parse_assign_cmd(hx83102d_zf_data_sram_start_addr, (*kp_pzf_op)->data_sram_start_addr, sizeof((*kp_pzf_op)->data_sram_start_addr)); + kp_himax_in_parse_assign_cmd(hx83102d_zf_data_adc_cfg_1, (*kp_pzf_op)->data_adc_cfg_1, sizeof((*kp_pzf_op)->data_adc_cfg_1)); + kp_himax_in_parse_assign_cmd(hx83102d_zf_data_adc_cfg_2, (*kp_pzf_op)->data_adc_cfg_2, sizeof((*kp_pzf_op)->data_adc_cfg_2)); + kp_himax_in_parse_assign_cmd(hx83102d_zf_data_adc_cfg_3, (*kp_pzf_op)->data_adc_cfg_3, sizeof((*kp_pzf_op)->data_adc_cfg_3)); +#endif + kp_himax_in_parse_assign_cmd(hx83102d_data_df_x_res, (*kp_pdriver_op)->data_df_x_res, sizeof((*kp_pdriver_op)->data_df_x_res)); + kp_himax_in_parse_assign_cmd(hx83102d_data_df_y_res, (*kp_pdriver_op)->data_df_y_res, sizeof((*kp_pdriver_op)->data_df_y_res)); + kp_himax_in_parse_assign_cmd(hx83102d_data_df_y_res, (*kp_pdriver_op)->data_df_y_res, sizeof((*kp_pdriver_op)->data_df_y_res)); + kp_himax_in_parse_assign_cmd(hx83102d_adr_osc_en, (*kp_pic_op)->adr_osc_en, sizeof((*kp_pic_op)->adr_osc_en)); + kp_himax_in_parse_assign_cmd(hx83102d_adr_osc_pw, (*kp_pic_op)->adr_osc_pw, sizeof((*kp_pic_op)->adr_osc_pw)); +} + +static void himax_hx83102d_func_re_init(void) +{ + I("%s:Entering!\n", __func__); + kp_g_core_fp->fp_chip_init = hx83102_chip_init; + kp_g_core_fp->fp_sense_off = hx83102d_sense_off; + kp_g_core_fp->fp_ic_id_read = hx83102d_ic_id_read; + kp_g_core_fp->fp_dd_clk_set = hx83102d_dd_clk_set; + kp_g_core_fp->fp_dd_reg_en = hx83102d_dd_reg_en; +#if defined(HX_ZERO_FLASH) + /*kp_g_core_fp->fp_firmware_update_0f = hx83102d_firmware_update_0f;*/ + kp_g_core_fp->fp_resume_ic_action = himax_hx83102d_resume_ic_action; + kp_g_core_fp->fp_suspend_ic_action = himax_hx83102d_suspend_ic_action; + kp_g_core_fp->fp_sense_on = himax_hx83102d_sense_on; + kp_g_core_fp->fp_0f_reload_to_active = himax_hx83102d_reload_to_active; +#if defined(HX_0F_DEBUG) + kp_g_core_fp->fp_firmware_read_0f = hx83102d_firmware_read_0f; +#endif +#if defined(HX_CODE_OVERLAY) + kp_g_core_fp->fp_0f_overlay = hx83102d_0f_overlay; +#endif +#ifdef HX_ESD_RECOVERY + kp_g_core_fp->fp_0f_esd_check = hx83102d_0f_esd_check; +#endif +#endif +} + +static void himax_hx83102e_reg_re_init(void) +{ + I("%s:Entering!\n", __func__); + kp_himax_in_parse_assign_cmd(hx83102e_fw_addr_raw_out_sel, (*kp_pfw_op)->addr_raw_out_sel, sizeof((*kp_pfw_op)->addr_raw_out_sel)); + kp_himax_in_parse_assign_cmd(hx83102e_data_df_rx, (*kp_pdriver_op)->data_df_rx, sizeof((*kp_pdriver_op)->data_df_rx)); + kp_himax_in_parse_assign_cmd(hx83102e_data_df_tx, (*kp_pdriver_op)->data_df_tx, sizeof((*kp_pdriver_op)->data_df_tx)); + kp_himax_in_parse_assign_cmd(hx83102e_data_df_x_res, (*kp_pdriver_op)->data_df_x_res, sizeof((*kp_pdriver_op)->data_df_x_res)); + kp_himax_in_parse_assign_cmd(hx83102e_data_df_y_res, (*kp_pdriver_op)->data_df_y_res, sizeof((*kp_pdriver_op)->data_df_y_res)); +} + +static void himax_hx83102e_func_re_init(void) +{ + I("%s:Entering!\n", __func__); + + kp_g_core_fp->fp_chip_init = hx83102e_chip_init; + kp_g_core_fp->fp_sense_off = hx83102d_sense_off; + kp_g_core_fp->fp_read_event_stack = hx83102e_read_event_stack; +} + + +static bool hx83102_chip_detect(void) +{ + uint8_t tmp_data[DATA_LEN_4]; + uint8_t tmp_addr[DATA_LEN_4]; + bool ret_data = false; + int ret = 0; + int i = 0; + + if (himax_ic_setup_external_symbols()) + return false; + +#ifdef HX_RST_PIN_FUNC + hx83102_pin_reset(); +#endif + if (kp_himax_bus_read(0x13, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return false; + } + if (hx83102_sense_off(false) == false) { + ret_data = false; + E("%s:hx83102_sense_off Fail:\n", __func__); + return ret_data; + } + + for (i = 0; i < 5; i++) { + tmp_addr[3] = 0x90; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; + tmp_addr[0] = 0xD0; + if (hx83102_register_read(tmp_addr, DATA_LEN_4, tmp_data) != 0) { + ret_data = false; + E("%s:hx83102_register_read Fail:\n", __func__); + return ret_data; + } + I("%s:Read driver IC ID = %X,%X,%X\n", __func__, tmp_data[3], tmp_data[2], tmp_data[1]); /*83,10,2X*/ + + if ((tmp_data[3] == 0x83) && (tmp_data[2] == 0x10) && ((tmp_data[1] == 0x2a) || (tmp_data[1] == 0x2b) || (tmp_data[1] == 0x2d) || (tmp_data[1] == 0x2e))) { + if (tmp_data[1] == 0x2a) { + strlcpy((*kp_private_ts)->chip_name, HX_83102A_SERIES_PWON, 30); + I("%s:detect IC HX83102A successfully\n", __func__); + } else if (tmp_data[1] == 0x2b) { + strlcpy((*kp_private_ts)->chip_name, HX_83102B_SERIES_PWON, 30); + I("%s:detect IC HX83102B successfully\n", __func__); + } else if (tmp_data[1] == 0x2d) { + strlcpy((*kp_private_ts)->chip_name, HX_83102D_SERIES_PWON, 30); + I("%s:detect IC HX83102D successfully\n", __func__); + } else { + strlcpy((*kp_private_ts)->chip_name, HX_83102E_SERIES_PWON, 30); + I("%s:detect IC HX83102E successfully\n", __func__); + } + + ret = kp_himax_mcu_in_cmd_struct_init(); + if (ret < 0) { + ret_data = false; + E("%s:cmd_struct_init Fail:\n", __func__); + return ret_data; + } + + kp_himax_mcu_in_cmd_init(); + if ((tmp_data[1] == 0x2a) || (tmp_data[1] == 0x2b)) { + himax_hx83102ab_reg_re_init(tmp_data[1]); + himax_hx83102ab_func_re_init(); + } else if (tmp_data[1] == 0x2d) { + himax_hx83102d_reg_re_init(); + himax_hx83102d_func_re_init(); + } else {/* 0x2e */ + himax_hx83102e_reg_re_init(); + himax_hx83102e_func_re_init(); + } + ret_data = true; + break; + } + + ret_data = false; + E("%s:Read driver ID register Fail:\n", __func__); + E("Could NOT find Himax Chipset\n"); + E("Please check 1.VCCD,VCCA,VSP,VSN\n"); + E("2. LCM_RST,TP_RST\n"); + E("3. Power On Sequence\n"); + + } + +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) +#if defined(HX_EN_DYNAMIC_NAME) + hx83102_dynamic_fw_name(tmp_data[1]); +#endif +#endif + + return ret_data; +} + +DECLARE(HX_MOD_KSYM_HX83102); + +static int himax_hx83102_probe(void) +{ + I("%s:Enter\n", __func__); + himax_add_chip_dt(hx83102_chip_detect); + + return 0; +} + +static int himax_hx83102_remove(void) +{ + free_chip_dt_table(); + return 0; +} + +static int __init himax_hx83102_init(void) +{ + int ret = 0; + + I("%s\n", __func__); + ret = himax_hx83102_probe(); + return 0; +} + +static void __exit himax_hx83102_exit(void) +{ + himax_hx83102_remove(); +} + +module_init(himax_hx83102_init); +module_exit(himax_hx83102_exit); + +MODULE_DESCRIPTION("HIMAX HX83102 touch driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/himax_ic_HX83102d.h b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/himax_ic_HX83102d.h new file mode 100755 index 000000000000..ceab657ecdd0 --- /dev/null +++ b/drivers/input/touchscreen/himax_v3_mmi/support_ic/himax_v3_mmi_hx83102d/himax_ic_HX83102d.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Himax Android Driver Sample Code for HX83102 chipset + * + * 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_platform.h" +#include "himax_common.h" +#include "himax_ic_core.h" +#include + +#define hx83102ab_fw_addr_sorting_mode_en 0x100007FC +#define hx83102ab_fw_addr_selftest_addr_en 0x100007F8 +#define hx83102ab_data_adc_cfg_1 0x10007B00 +#define hx83102a_data_df_rx 48 +#define hx83102a_data_df_tx 24 +#define hx83102a_data_df_x_res 2160 +#define hx83102a_data_df_y_res 3840 +#define hx83102b_data_df_x_res 720 +#define hx83102b_data_df_y_res 1280 + +#define hx83102d_fw_addr_raw_out_sel 0x800204f4 +#define hx83102d_zf_data_adc_cfg_1 0x10007B00 +#define hx83102d_zf_data_adc_cfg_2 0x10006A00 +#define hx83102d_zf_data_adc_cfg_3 0x10007500 +#define hx83102d_zf_data_bor_prevent_info 0x10007268 +#define hx83102d_zf_data_notch_info 0x10007300 +#define hx83102d_zf_func_info_en 0x10007FD0 +#define hx83102d_zf_po_sub_func 0x10005A00 +#define hx83102d_zf_data_sram_start_addr 0x20000000 +#define hx83102d_data_df_x_res 720 +#define hx83102d_data_df_y_res 1280 +#define hx83102d_adr_osc_en 0x9000009C +#define hx83102d_adr_osc_pw 0x90000280 + +#define hx83102e_fw_addr_raw_out_sel 0x100072EC +#define hx83102e_data_df_rx 48 +#define hx83102e_data_df_tx 30 +#define hx83102e_data_df_x_res 1200 +#define hx83102e_data_df_y_res 1920 + +#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH) +#ifdef HX_EN_DYNAMIC_NAME +#define hx83102_ic_b9_en 0x300B9000 +#define hx83102_ic_fw 0x300E8006 + +#define hx83102b_ic_osc_en 0x900880A0 +#define hx83102d_ic_osc_en 0x9000009C +#define hx83102d_ic_osc_pw 0x90000280 +#endif +#endif + +#ifdef HX_ESD_RECOVERY + extern u8 HX_ESD_RESET_ACTIVATE; +#endif +