(CR):[Kane]:[factory]add second supplier himax TP driver.
authorhq_qiaoquanbin_tmp <qiaoquanbin@huaqin.com>
Tue, 23 Oct 2018 09:57:23 +0000 (17:57 +0800)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:23:44 +0000 (20:23 +0300)
add second supplier himax TP driver.

bug:(CR)

Change-Id: Ia50833f4ea4f292529b009f8e4e78d03bc433b96
Signed-off-by: hq_qiaoquanbin_tmp <qiaoquanbin@huaqin.com>
25 files changed:
arch/arm64/boot/dts/exynos/exynos9609-robusta2_evb.dts
arch/arm64/boot/dts/exynos/exynos9609-wing.dts
arch/arm64/boot/dts/exynos/himax-hx83112a-i2c.dtsi [new file with mode: 0755]
arch/arm64/configs/robusta2_evb_defconfig
drivers/input/touchscreen/Kconfig [changed mode: 0644->0755]
drivers/input/touchscreen/Makefile [changed mode: 0644->0755]
drivers/input/touchscreen/hxchipset/Kconfig [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/Makefile [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_common.c [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_common.h [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_debug.c [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_debug.h [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_ic.c [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_ic.h [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_ic_HX83102.c [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_ic_HX83102.h [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_ic_HX83112.h [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_ic_core.h [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_ic_incell_core.c [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_inspection.c [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_inspection.h [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_platform.c [new file with mode: 0755]
drivers/input/touchscreen/hxchipset/himax_platform.h [new file with mode: 0755]
drivers/input/touchscreen/nt36xxx/nt36xxx.c

index b1e7f068699fcbc994345d02c464de8c6d9bed29..d131682943b0b75d662f805bae33d418435aea02 100755 (executable)
@@ -19,6 +19,7 @@
 #include "exynos9610-display-lcd.dtsi"
 #include "exynos9610-robusta2-camera.dtsi"
 #include "novatek-nt36xxx-i2c.dtsi"
+#include "himax-hx83112a-i2c.dtsi"
 #include "wing-sensor.dtsi"
 #include "exynos9610-robusta2-motor.dtsi"
 
index 901b6997bce22e1ac9c1091b9c8ea4117be56e77..9ba2198a31fee30a83c41d147f9f86a9baf50084 100755 (executable)
@@ -18,6 +18,7 @@
 #include "modem-ss360ap-sit-pdata.dtsi"
 #include "exynos9610-display-lcd.dtsi"
 #include "novatek-nt36xxx-i2c.dtsi"
+#include "himax-hx83112a-i2c.dtsi"
 #include "wing-sensor.dtsi"
 #include "exynos9610-robusta2-motor.dtsi"
 
diff --git a/arch/arm64/boot/dts/exynos/himax-hx83112a-i2c.dtsi b/arch/arm64/boot/dts/exynos/himax-hx83112a-i2c.dtsi
new file mode 100755 (executable)
index 0000000..188c7f9
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+*      himax dtsi
+*/
+
+&i2c_4 {
+       status = "ok";
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       himax@48 {
+               compatible = "himax,hxcommon";
+               reg = <0x48>;
+               himax,panel-coords = <0 1080 0 2520>;
+               himax,display-coords = <0 1080 0 2520>;
+               himax,irq-gpio = <&gpa2 4 0>;
+               himax,rst-gpio = <&gpa1 3 0>;
+               report_type = <1>;
+       };
+};
index cfdbe6800869140ab5ff3d4b73985e9e63da4e9b..b83e85d3c29976ba1b0fb7ae3f65abddb527d82c 100755 (executable)
@@ -256,6 +256,13 @@ CONFIG_TABLET_USB_GTCO=y
 CONFIG_TABLET_USB_HANWANG=y
 CONFIG_TABLET_USB_KBTAB=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y
+CONFIG_TOUCHSCREEN_HIMAX_COMMON=y
+CONFIG_TOUCHSCREEN_HIMAX_INCELL=y
+CONFIG_TOUCHSCREEN_HIMAX_IC_HX83102=y
+CONFIG_TOUCHSCREEN_HIMAX_IC_HX83112=y
+CONFIG_TOUCHSCREEN_HIMAX_INSPECT=y
+CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_KEYCHORD=y
 CONFIG_INPUT_UINPUT=y
old mode 100644 (file)
new mode 100755 (executable)
index 4d155f7..d392cf5
@@ -1248,4 +1248,16 @@ config TOUCHSCREEN_ROHM_BU21023
 
 source "drivers/input/touchscreen/synaptics_dsx/Kconfig"
 source "drivers/input/touchscreen/nt36xxx/Kconfig"
+
+config TOUCHSCREEN_HIMAX_CHIPSET
+       bool "Himax touchpanel CHIPSET"
+       depends on I2C
+       help
+         Say Y here if you have a Himax CHIPSET touchscreen.
+         HIMAX controllers are multi touch controllers which can
+         report 10 touches at a time.
+
+          If unsure, say N.
+
+source "drivers/input/touchscreen/hxchipset/Kconfig"
 endif
old mode 100644 (file)
new mode 100755 (executable)
index 6276fa2..3f54ca0
@@ -106,3 +106,4 @@ obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50)      += colibri-vf50-ts.o
 obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
 obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_DSX) += synaptics_dsx/
 obj-$(CONFIG_TOUCHSCREEN_NT36xxx) += nt36xxx/
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET)        += hxchipset/
diff --git a/drivers/input/touchscreen/hxchipset/Kconfig b/drivers/input/touchscreen/hxchipset/Kconfig
new file mode 100755 (executable)
index 0000000..6709861
--- /dev/null
@@ -0,0 +1,40 @@
+#
+# Himax Touchscreen driver configuration
+#
+
+config TOUCHSCREEN_HIMAX_COMMON
+               tristate "HIMAX chipset i2c touchscreen"
+               depends on TOUCHSCREEN_HIMAX_CHIPSET
+               help
+               This enables support for HIMAX CHIPSET over I2C based touchscreens.
+
+# ***************** In-cell Start *****************
+config TOUCHSCREEN_HIMAX_INCELL
+               tristate "HIMAX chipset in-cell function"
+               depends on TOUCHSCREEN_HIMAX_COMMON
+               help
+               This enables support for HIMAX CHIPSET of in-cell function.
+
+config TOUCHSCREEN_HIMAX_IC_HX83112
+               tristate "HIMAX chipset HX83112 function"
+               depends on TOUCHSCREEN_HIMAX_INCELL
+               help
+               This enables support for HIMAX CHIPSET of HX83112.
+
+config TOUCHSCREEN_HIMAX_IC_HX83102
+               tristate "HIMAX chipset HX83102 function"
+               depends on TOUCHSCREEN_HIMAX_INCELL
+               help
+               This enables support for HIMAX CHIPSET of HX83102.
+# ***************** In-cell End *******************
+
+config TOUCHSCREEN_HIMAX_DEBUG
+               tristate "HIMAX debug function"
+               depends on TOUCHSCREEN_HIMAX_COMMON
+               help
+               This enables support for HIMAX debug function.
+config TOUCHSCREEN_HIMAX_INSPECT
+               tristate "HIMAX inspect function"
+               depends on TOUCHSCREEN_HIMAX_COMMON
+               help
+               This enables support for HIMAX debug function.
\ No newline at end of file
diff --git a/drivers/input/touchscreen/hxchipset/Makefile b/drivers/input/touchscreen/hxchipset/Makefile
new file mode 100755 (executable)
index 0000000..967fef6
--- /dev/null
@@ -0,0 +1,7 @@
+# Makefile for the Himax touchscreen drivers.
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_INCELL)         +=      himax_ic_incell_core.o
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_IC_HX83112)     +=      himax_ic_HX83112.o
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_IC_HX83102)     +=      himax_ic_HX83102.o
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_COMMON)         +=      himax_common.o himax_platform.o
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)          +=      himax_debug.o
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_INSPECT)                +=      himax_inspection.o
\ No newline at end of file
diff --git a/drivers/input/touchscreen/hxchipset/himax_common.c b/drivers/input/touchscreen/hxchipset/himax_common.c
new file mode 100755 (executable)
index 0000000..98867c9
--- /dev/null
@@ -0,0 +1,2841 @@
+/*  Himax Android Driver Sample Code for common functions
+
+    Copyright (C) 2018 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"
+
+#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};
+#endif
+
+#define SUPPORT_FINGER_DATA_CHECKSUM 0x0F
+#define TS_WAKE_LOCK_TIMEOUT (2 * HZ)
+#define FRAME_COUNT 5
+
+#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH)
+char *i_CTPM_firmware_name = "Himax_firmware.bin";
+bool g_auto_update_flag = false;
+#endif
+#if defined(HX_AUTO_UPDATE_FW)
+unsigned char *i_CTPM_FW = NULL;
+int i_CTPM_FW_len;
+int g_i_FW_VER = 0;
+int g_i_CFG_VER = 0;
+int g_i_CID_MAJ = 0; /*GUEST ID*/
+int g_i_CID_MIN = 0; /*VER for GUEST*/
+#endif
+#ifdef HX_ZERO_FLASH
+int g_f_0f_updat = 0;
+#endif
+
+struct himax_ts_data *private_ts;
+struct himax_ic_data *ic_data;
+struct himax_report_data *hx_touch_data;
+struct himax_core_fp g_core_fp;
+struct himax_debug *debug_data;
+
+struct proc_dir_entry *himax_touch_proc_dir;
+#define HIMAX_PROC_TOUCH_FOLDER "android_touch"
+#ifdef CONFIG_TOUCHSCREEN_HIMAX_DEBUG
+       extern int himax_debug_init(void);
+       extern int himax_debug_remove(void);
+#endif
+/*ts_work about start*/
+struct himax_target_report_data *g_target_report_data = NULL;
+int himax_report_data(struct himax_ts_data *ts, int ts_path, int ts_status);
+static void himax_report_all_leave_event(struct himax_ts_data *ts);
+/*ts_work about end*/
+static int     HX_TOUCH_INFO_POINT_CNT;
+
+unsigned long  FW_VER_MAJ_FLASH_ADDR;
+unsigned long  FW_VER_MIN_FLASH_ADDR;
+unsigned long  CFG_VER_MAJ_FLASH_ADDR;
+unsigned long  CFG_VER_MIN_FLASH_ADDR;
+unsigned long  CID_VER_MAJ_FLASH_ADDR;
+unsigned long  CID_VER_MIN_FLASH_ADDR;
+/*unsigned long        PANEL_VERSION_ADDR;*/
+
+unsigned long  FW_VER_MAJ_FLASH_LENG;
+unsigned long  FW_VER_MIN_FLASH_LENG;
+unsigned long  CFG_VER_MAJ_FLASH_LENG;
+unsigned long  CFG_VER_MIN_FLASH_LENG;
+unsigned long  CID_VER_MAJ_FLASH_LENG;
+unsigned long  CID_VER_MIN_FLASH_LENG;
+/*unsigned long        PANEL_VERSION_LENG;*/
+
+unsigned long  FW_CFG_VER_FLASH_ADDR;
+
+unsigned char  IC_CHECKSUM = 0;
+
+#ifdef HX_ESD_RECOVERY
+       u8 HX_ESD_RESET_ACTIVATE = 0;
+       int hx_EB_event_flag = 0;
+       int hx_EC_event_flag = 0;
+       int hx_ED_event_flag = 0;
+       int g_zero_event_count = 0;
+#endif
+u8     HX_HW_RESET_ACTIVATE = 0;
+
+#if defined(HX_PLATFOME_DEFINE_KEY)
+       extern void himax_platform_key(void);
+#endif
+
+extern int himax_parse_dt(struct himax_ts_data *ts,
+                                               struct himax_i2c_platform_data *pdata);
+
+static uint8_t AA_press = 0x00;
+static uint8_t EN_NoiseFilter = 0x00;
+static uint8_t Last_EN_NoiseFilter = 0x00;
+
+static int     p_point_num = 0xFFFF;
+#if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON)
+static uint8_t vk_press = 0x00;
+static int     tpd_key = 0x00;
+static int     tpd_key_old = 0x00;
+#endif
+static int     probe_fail_flag;
+#ifdef HX_USB_DETECT_GLOBAL
+       bool USB_detect_flag;
+#endif
+
+#if 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 himax_report_data_init(void);
+
+extern bool hx83102_chip_detect (void);
+extern bool hx83112_chip_detect (void);
+extern int himax_dev_set(struct himax_ts_data *ts);
+extern int himax_input_register_device(struct input_dev *input_dev);
+extern char *hx_self_test_file_name;
+
+int g_ts_dbg = 0;
+
+/* 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;
+
+extern char *g_rslt_data;
+#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;
+#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 = 0;
+#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];
+       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_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,
+};
+
+#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 = kzalloc(len, 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 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 = kzalloc(len, 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 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 = kzalloc(len, 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 struct file_operations himax_proc_Gesture_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_GESTURE_read,
+       .write = himax_GESTURE_write,
+};
+#endif
+
+#ifdef CONFIG_TOUCHSCREEN_HIMAX_INSPECT
+extern void (*fp_himax_self_test_init)(void);
+#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, (S_IRUGO | S_IWUSR | S_IWGRP),
+                                                       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, (S_IRUGO), himax_touch_proc_dir, &himax_proc_self_raw_ops);
+       if (himax_proc_self_raw_file == NULL) {
+               E(" %s: proc self_test file create failed!\n", __func__);
+               goto fail_2;
+       }
+
+#ifdef HX_HIGH_SENSE
+       himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, (S_IWUSR | S_IRUGO | S_IWUGO),
+                                                                          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_3;
+       }
+
+#endif
+#ifdef HX_SMART_WAKEUP
+       himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, (S_IWUSR | S_IRUGO | S_IWUGO),
+                                                                          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_4;
+       }
+
+       himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, (S_IWUSR | S_IRUGO | S_IWUGO),
+                                                                                 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_5;
+       }
+#endif
+       return 0;
+#ifdef HX_SMART_WAKEUP
+       remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir);
+fail_5:
+       remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir);
+fail_4:
+#endif
+#ifdef HX_HIGH_SENSE
+       remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir);
+fail_3:
+#endif
+       remove_proc_entry(HIMAX_PROC_SELF_TEST_RAW_FILE, himax_touch_proc_dir);
+fail_2:
+       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_SMART_WAKEUP
+       remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir);
+#endif
+#ifdef HX_HIGH_SENSE
+       remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir);
+#endif
+}
+
+/* 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) {
+               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) {
+               return NO_ERR;
+       } else {
+               ret = INPUT_REGISTER_FAIL;
+       }
+
+input_device_fail:
+       I("%s, input device register fail!\n", __func__);
+       return ret;
+}
+
+static void calcDataSize(uint8_t finger_num)
+{
+       struct himax_ts_data *ts_data = private_ts;
+       ts_data->coord_data_size = 4 * finger_num;
+       ts_data->area_data_size = ((finger_num / 4) + (finger_num % 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)
+{
+       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("Need to update!\n");
+                       return NO_ERR;
+               }       else {
+                       I("No need to update!\n");
+                       return 1;
+               }
+       } else {
+               E("FW bin fail!\n");
+               return 1;
+       }
+}
+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) {
+               E("%s,fail in line%d error code=%d\n", __func__, __LINE__, ret);
+               return OPEN_FILE_FAIL;
+       }
+
+       if (image != NULL) {
+               i_CTPM_FW_len = image->size;
+               i_CTPM_FW = kzalloc(sizeof(char)*i_CTPM_FW_len, 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;
+       }
+
+       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;
+               } /*upgrade fail*/
+       } 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);
+
+#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;
+#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;
+       int j = 0, gesture_pos = 0, gesture_flag = 0;
+
+       if (g_ts_dbg != 0)
+               I("%s: Entering!, ts_status=%d\n", __func__, ts_status);
+
+       buf = kzalloc(hx_touch_data->event_size * sizeof(uint8_t), GFP_KERNEL);
+       if (buf == NULL) {
+               return -ENOMEM;
+       }
+
+       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) {
+               kfree(buf);
+               return 0;
+       }
+
+       if (buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1 ||
+               buf[GEST_PTLG_ID_LEN + 1] != GEST_PTLG_HDR_ID2) {
+               kfree(buf);
+               return 0;
+       }
+
+#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
+
+       kfree(buf);
+
+       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;
+               return 0;
+       } else {
+               g_target_report_data->SMWP_event_chk = gest_key_def[gesture_pos];
+               return gesture_pos;
+       }
+}
+
+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);
+               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);
+       }
+
+       if (hx_touch_data->hx_rawdata_buf != NULL) {
+               kfree(hx_touch_data->hx_rawdata_buf);
+       }
+
+#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);
+       }
+
+#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_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;
+       }
+#ifdef HX_SMART_WAKEUP
+       g_target_report_data->SMWP_event_chk = 0;
+#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:
+       kfree(g_target_report_data->x);
+       kfree(g_target_report_data->y);
+       kfree(g_target_report_data->w);
+       kfree(g_target_report_data->finger_id);
+       kfree(g_target_report_data);
+       g_target_report_data = NULL;
+       kfree(hx_touch_data->hx_coord_buf);
+       kfree(hx_touch_data->hx_rawdata_buf);
+#if defined(HX_SMART_WAKEUP)
+       kfree(hx_touch_data->hx_event_buf);
+#endif
+       I("%s: Memory allocate fail!\n", __func__);
+       return MEM_ALLOC_FAIL;
+}
+
+/*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;
+       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) && (!FAKE_POWER_KEY_SEND) && (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;
+                               goto END_FUNCTION;
+                       }
+                       break;
+               } 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;
+                               goto END_FUNCTION;
+                       }
+                       break;
+               }
+#if defined(HX_SMART_WAKEUP)
+
+       /*SMWP*/
+       case HX_REPORT_SMWP_EVENT:
+               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;
+                       goto END_FUNCTION;
+               }
+               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;
+                       goto END_FUNCTION;
+               }
+               break;
+       default:
+               break;
+       }
+
+END_FUNCTION:
+       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 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] checksum fail : check_sum_cal: 0x%02X\n", check_sum_cal);
+               ret_val = HX_CHKSUM_FAIL;
+       } else if (zero_cnt == length) {
+               I("[HIMAX TP MSG] All Zero event\n");
+               ret_val = HX_CHKSUM_FAIL;
+       }
+
+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
+               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;
+       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 (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;
+       int y = 0;
+       int w = 0;
+       int base = 0;
+       int32_t loop_i = 0;
+
+       if (g_ts_dbg != 0)
+               I("%s: start! \n", __func__);
+
+
+       ts->old_finger = ts->pre_finger_mask;
+       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;
+
+       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;
+
+       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: coordinate dump fail and bypass with checksum err\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_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_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, hx_touch_data->finger_on);
+#endif
+                       himax_key_report_operation(tpd_key, ts);
+               }
+
+#ifndef HX_PROTOCOL_A
+               input_report_key(ts->input_dev, BTN_TOUCH, hx_touch_data->finger_on);
+#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, hx_touch_data->finger_on);
+#endif
+               himax_key_report_operation(tpd_key, ts);
+       } 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, hx_touch_data->finger_on);
+#endif
+               himax_key_report_operation(tpd_key, ts);
+       }
+
+#ifndef HX_PROTOCOL_A
+       input_report_key(ts->input_dev, BTN_TOUCH, hx_touch_data->finger_on);
+#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);
+#endif
+                       input_report_key(ts->input_dev, BTN_TOUCH, g_target_report_data->finger_on);
+                       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, g_target_report_data->w[i]);
+                       input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 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]);
+#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 {
+                       input_mt_slot(ts->input_dev, i);
+                       input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
+               }
+       }
+
+       input_report_key(ts->input_dev, BTN_TOUCH, g_target_report_data->finger_on);
+       input_sync(ts->input_dev);
+
+       if (g_ts_dbg != 0)
+               I("%s:end\n", __func__);
+}
+
+static void himax_finger_leave(struct himax_ts_data *ts)
+{
+       int32_t loop_i = 0;
+
+       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;
+       AA_press = 0;
+
+#ifdef HX_PROTOCOL_A
+       input_mt_sync(ts->input_dev);
+#endif
+
+       for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
+               if (((ts->pre_finger_mask >> loop_i) & 1) == 1) {
+                       input_mt_slot(ts->input_dev, loop_i);
+                       input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
+               }
+       }
+
+       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, hx_touch_data->finger_on);
+       input_sync(ts->input_dev);
+
+       if (g_ts_dbg != 0)
+               I("%s: end! \n", __func__);
+       return;
+}
+
+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) {
+               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;
+               }
+
+               /* 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) {
+               wake_lock_timeout(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT);
+               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];
+       uint8_t buf[128];
+
+       memset(buf, 0x00, sizeof(buf));
+       memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
+
+       ts_status = himax_touch_get(ts, buf, ts_path, ts_status);
+       if (ts_status == HX_TS_GET_DATA_FAIL)
+               goto END_FUNCTION;
+
+       ts_status = himax_err_ctrl(ts, buf, ts_path, ts_status);
+       if (ts_status == HX_REPORT_DATA || ts_status == HX_TS_NORMAL_END) {
+               ts_status = himax_distribute_touch_data(buf, ts_path, ts_status);
+               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;
+               break;
+       }
+
+       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);
+#endif
+END_FUNCTION:
+       if (debug_data != NULL)
+               debug_data->fp_ts_dbg_func(ts, HX_FINGER_LEAVE);
+
+       return;
+}
+/*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) {
+               return ;
+       }
+
+UPDATE_FW:
+       if (i_update_FW() <= 0) {
+               I("Auto update FW fail!\n");
+       }       else {
+               I("It have Updated\n");
+       }
+}
+#endif
+
+
+#ifdef 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
+
+static const char *himax_ic_type_to_string (void) {
+       switch (private_ts->chip_cell_type) {
+       case CHIP_IS_IN_CELL: return "hx83112a";
+       default: return "hxxxxxx";
+       }
+}
+
+static int himax_fw_updater (struct himax_ts_data *ts, const char *fileName) {
+       const struct firmware *fw = NULL;
+       int fw_type = 0;
+       int result;
+
+       himax_int_enable(0);
+
+       result = request_firmware(&fw, fileName, 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;
+       I("Now FW size is : %dk\n", fw_type);
+       switch (fw_type) {
+       case 32:
+               result = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_32k(
+                       (unsigned char *)fw->data, fw->size, false);
+               if (result == 0)
+                       E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+               else
+                       I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+               break;
+       case 60:
+               result = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_60k(
+                       (unsigned char *)fw->data, fw->size, false);
+               if (result == 0)
+                       E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+               else
+                       I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+               break;
+       case 64:
+               result = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_64k(
+                       (unsigned char *)fw->data, fw->size, false);
+               if (result == 0)
+                       E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+               else
+                       I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+               break;
+       case 124:
+               result = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_124k(
+                       (unsigned char *)fw->data, fw->size, false);
+               if (result == 0)
+                       E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+               else
+                       I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+               break;
+       case 128:
+               result = g_core_fp.fp_fts_ctpm_fw_upgrade_with_sys_fs_128k(
+                       (unsigned char *)fw->data, fw->size, false);
+               if (result == 0)
+                       E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+               else
+                       I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+               break;
+       default:
+               E("%s: Flash command fail: %d\n", __func__, __LINE__);
+               break;
+       }
+       release_firmware(fw);
+       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);
+#else
+       g_core_fp.fp_sense_on(0);
+#endif
+       himax_int_enable(1);
+
+       return (result <= 0) ? -1 : 0;
+}
+
+static ssize_t himax_sysfs_poweron_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct himax_ts_data *ts = i2c_get_clientdata(to_i2c_client(dev));
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n",
+               ((atomic_read(&ts->suspend_mode) == 1) ? 0 : 1));
+}
+
+static ssize_t himax_sysfs_flashprog_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct himax_ts_data *ts = i2c_get_clientdata(to_i2c_client(dev));
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&ts->flash_mode));
+}
+
+static ssize_t himax_sysfs_productinfo_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return scnprintf(buf, PAGE_SIZE, "%s\n", himax_ic_type_to_string());
+}
+
+static ssize_t himax_sysfs_buildid_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%X-%02X%02X\n",
+               ic_data->vendor_fw_ver,
+               ic_data->vendor_touch_cfg_ver,
+               ic_data->vendor_display_cfg_ver);
+}
+
+static ssize_t himax_sysfs_force_reflash_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       unsigned int input;
+       struct himax_ts_data *ts = i2c_get_clientdata(to_i2c_client(dev));
+
+       if (sscanf(buf, "%u", &input) != 1)
+               return -EINVAL;
+
+       if (input != 1)
+               return -EINVAL;
+
+       ts->force_update = true;
+
+       return count;
+}
+
+static ssize_t himax_sysfs_do_reflash_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       int retval;
+       char prefix[HX_FILENAME_SIZE] = "himax";
+       char template[HX_FILENAME_SIZE];
+       char filename[HX_FILENAME_SIZE];
+       struct himax_ts_data *ts = i2c_get_clientdata(to_i2c_client(dev));
+
+       if (count > HX_FILENAME_SIZE) {
+               E("%s: FW filename is too long\n", __func__);
+               retval = -EINVAL;
+               goto exit;
+       }
+
+       if (!ts->force_update) {
+               if (strncmp(buf, prefix,
+                       strnlen(prefix, sizeof(prefix)))) {
+                       E("%s: FW does not belong to Himax\n", __func__);
+                       retval = -EINVAL;
+                       goto exit;
+               }
+
+               snprintf(template, sizeof(template), "-%s-",
+                                               himax_ic_type_to_string());
+               if (!strnstr(buf + strnlen(prefix, sizeof(prefix)), template,
+                       count)) {
+                       E("%s: FW does not belong to %s\n",
+                               __func__,
+                               himax_ic_type_to_string());
+                       retval = -EINVAL;
+                       goto exit;
+               }
+       }
+
+       strlcpy(filename, buf, count);
+       D("%s: FW filename: %s\n", __func__, filename);
+
+       atomic_set(&ts->flash_mode, 1);
+       retval = himax_fw_updater(ts, filename);
+       atomic_set(&ts->flash_mode, 0);
+       if (retval < 0) {
+               E("%s: Failed to do reflash\n", __func__);
+               goto exit;
+       }
+
+       retval = count;
+
+exit:
+       ts->force_update = false;
+       return retval;
+}
+
+static struct device_attribute attrs[] = {
+       __ATTR(poweron, S_IRUSR | S_IRGRP,
+                       himax_sysfs_poweron_show,
+                       NULL),
+       __ATTR(productinfo, S_IRUGO,
+                       himax_sysfs_productinfo_show,
+                       NULL),
+       __ATTR(buildid, S_IRUGO,
+                       himax_sysfs_buildid_show,
+                       NULL),
+       __ATTR(flashprog, S_IRUSR | S_IRGRP,
+                       himax_sysfs_flashprog_show,
+                       NULL),
+       __ATTR(doreflash, S_IWUSR | S_IWGRP,
+                       NULL,
+                       himax_sysfs_do_reflash_store),
+       __ATTR(forcereflash, S_IWUSR | S_IWGRP,
+                       NULL,
+                       himax_sysfs_force_reflash_store),
+};
+
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+
+/* 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->client->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(ts->client->addr,
+                                               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, himax_ic_type_to_string());
+               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;
+}
+
+int himax_chip_common_init(void)
+{
+
+       int ret = 0, err = 0;
+       struct himax_ts_data *ts = private_ts;
+       struct himax_i2c_platform_data *pdata;
+       int attr_count;
+
+       I("PDATA START\n");
+       pdata = kzalloc(sizeof(*pdata), 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(*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) < 0) {
+               I(" GPIO and power config failed\n");
+               goto err_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
+
+       if (IC_HX83102 == ic_data->ic_type_val) {
+               I("[%s][%d]:is hx83102_chip_detect\n", __func__, __LINE__);
+               hx83102_chip_detect();
+       } else {
+               I("[%s][%d]:is hx83112_chip_detect\n", __func__, __LINE__);
+               hx83112_chip_detect();
+       }
+
+       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;
+       }
+
+#ifdef HX_AUTO_UPDATE_FW
+       g_auto_update_flag = (!g_core_fp.fp_calculateChecksum(false));
+       g_auto_update_flag |= g_core_fp.fp_flash_lastdata_check();
+       if (g_auto_update_flag)
+               goto FW_force_upgrade;
+#endif
+#ifndef HX_ZERO_FLASH
+       g_core_fp.fp_read_FW_ver();
+#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 syn_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");
+       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
+
+       /*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;
+       ts->x_channel = ic_data->HX_RX_NUM;
+       ts->y_channel = ic_data->HX_TX_NUM;
+       ts->nFinger_support = ic_data->HX_MAX_PT;
+       /*calculate the i2c data size*/
+       calcDataSize(ts->nFinger_support);
+       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;
+#if defined(HX_USB_DETECT_CALLBACK) || defined(HX_USB_DETECT_GLOBAL)
+       ts->usb_connected = 0x00;
+       ts->cable_config = pdata->cable_config;
+#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;
+       }
+
+#ifdef CONFIG_FB
+       ts->himax_att_wq = create_singlethread_workqueue("HMX_ATT_reuqest");
+
+       if (!ts->himax_att_wq) {
+               E(" allocate syn_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;
+       wake_lock_init(&ts->ts_SMWP_wake_lock, WAKE_LOCK_SUSPEND, 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;
+       }
+
+    for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               ret = sysfs_create_file(&ts->client->dev.kobj,
+                       &attrs[attr_count].attr);
+               if (ret < 0) {
+                       E("%s: Failed to create sysfs attributes\n", __func__);
+                       goto err_sysfs;
+               }
+    }
+
+    himax_sysfs_touchscreen(ts, true);
+
+#if defined(HX_USB_DETECT_CALLBACK)
+
+       if (ts->cable_config)   {
+               cable_detect_register_notifier(&himax_cable_status_handler);
+       }
+
+#endif
+       err = himax_ts_register_interrupt();
+
+       if (err) {
+               goto err_register_interrupt_failed;
+       }
+
+#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
+       return 0;
+err_register_interrupt_failed:
+       remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL);
+err_sysfs:
+       attr_count = ARRAY_SIZE(attrs);
+       for (attr_count--; attr_count >= 0; attr_count--) {
+               sysfs_remove_file(&ts->client->dev.kobj,
+                       &attrs[attr_count].attr);
+       }
+err_creat_proc_file_failed:
+err_report_data_init_failed:
+#ifdef HX_SMART_WAKEUP
+       wake_lock_destroy(&ts->ts_SMWP_wake_lock);
+#endif
+#ifdef CONFIG_FB
+       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_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:
+       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
+#ifndef CONFIG_OF
+err_power_failed:
+#endif
+err_gpio_power_config_failed:
+err_alloc_dt_pdata_failed:
+       kfree(hx_touch_data);
+err_alloc_touch_data_failed:
+       kfree(ic_data);
+err_dt_ic_data_fail:
+       kfree(pdata);
+err_dt_platform_data_fail:
+       kfree(ts);
+       probe_fail_flag = 1;
+       return err;
+}
+
+void himax_chip_common_deinit(void)
+{
+       struct himax_ts_data *ts = private_ts;
+       int attr_count = ARRAY_SIZE(attrs);
+
+#ifdef CONFIG_TOUCHSCREEN_HIMAX_DEBUG
+       himax_debug_remove();
+#endif
+
+       remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL);
+       himax_common_proc_deinit();
+
+       if (!ts->use_irq) {
+               hrtimer_cancel(&ts->timer);
+               destroy_workqueue(ts->himax_wq);
+       }
+
+       himax_sysfs_touchscreen(ts, false);
+       for (attr_count--; attr_count >= 0; attr_count--) {
+               sysfs_remove_file(&ts->client->dev.kobj,
+                       &attrs[attr_count].attr);
+       }
+
+#ifdef HX_SMART_WAKEUP
+       wake_lock_destroy(&ts->ts_SMWP_wake_lock);
+#endif
+#ifdef 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
+       if (gpio_is_valid(ts->pdata->gpio_irq))
+               gpio_free(ts->pdata->gpio_irq);
+#ifdef HX_RST_PIN_FUNC
+       if (gpio_is_valid(ts->pdata->gpio_reset))
+               gpio_free(ts->pdata->gpio_reset);
+#endif
+
+       kfree(hx_touch_data);
+       kfree(ic_data);
+       kfree(ts->pdata);
+       kfree(ts);
+       probe_fail_flag = 0;
+
+       return;
+}
+
+int himax_chip_common_suspend(struct himax_ts_data *ts)
+{
+       int ret;
+
+       if (ts->suspended) {
+               I("%s: Already suspended. Skipped. \n", __func__);
+               return 0;
+       } 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__);
+               return 0;
+       }
+
+#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) {
+               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__);
+               return 0;
+       }
+
+#endif
+       himax_int_enable(0);
+       g_core_fp.fp_suspend_ic_action();
+
+       if (!ts->use_irq) {
+               ret = cancel_work_sync(&ts->work);
+
+               if (ret) {
+                       himax_int_enable(1);
+               }
+       }
+
+       /*ts->first_pressed = 0;*/
+       atomic_set(&ts->suspend_mode, 1);
+       ts->pre_finger_mask = 0;
+
+       if (ts->pdata->powerOff3V3 && ts->pdata->power) {
+               ts->pdata->power(0);
+       }
+
+       I("%s: END \n", __func__);
+       return 0;
+}
+
+int himax_chip_common_resume(struct himax_ts_data *ts)
+{
+#if defined(HX_RST_PIN_FUNC) && defined(HX_RESUME_HW_RESET) && defined(HX_ZERO_FLASH)
+       int result = 0;
+#endif
+       I("%s: enter \n", __func__);
+
+       if (ts->suspended == false) {
+               I("%s: It had entered resume, skip this step \n", __func__);
+               return 0;
+       } else {
+               ts->suspended = false;
+       }
+
+       atomic_set(&ts->suspend_mode, 0);
+
+       if (ts->pdata->powerOff3V3 && ts->pdata->power) {
+               ts->pdata->power(1);
+       }
+
+#if defined(HX_SMART_WAKEUP) || defined(HX_HIGH_SENSE) || defined(HX_USB_DETECT_GLOBAL)
+       g_core_fp.fp_resend_cmd_func(ts->suspended);
+#elif defined(HX_RST_PIN_FUNC) && defined(HX_RESUME_HW_RESET)
+       g_core_fp.fp_ic_reset(false, false);
+#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);
+#endif
+#endif
+       himax_report_all_leave_event(ts);
+
+       g_core_fp.fp_resume_ic_action();
+       himax_int_enable(1);
+#if defined(HX_RST_PIN_FUNC) && defined(HX_RESUME_HW_RESET) && defined(HX_ZERO_FLASH)
+ESCAPE_0F_UPDATE:
+#endif
+       I("%s: END \n", __func__);
+       return 0;
+}
+
diff --git a/drivers/input/touchscreen/hxchipset/himax_common.h b/drivers/input/touchscreen/hxchipset/himax_common.h
new file mode 100755 (executable)
index 0000000..b230d1d
--- /dev/null
@@ -0,0 +1,408 @@
+/*  Himax Android Driver Sample Code for common functions
+
+    Copyright (C) 2018 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 <asm/segment.h>
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/async.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/input/mt.h>
+#include <linux/firmware.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/pm_wakeup.h>
+#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
+#include "himax_platform.h"
+
+#if defined(CONFIG_FB)
+       #include <linux/notifier.h>
+       #include <linux/fb.h>
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+       #include <linux/earlysuspend.h>
+#endif
+
+#ifdef CONFIG_OF
+       #include <linux/of_gpio.h>
+#endif
+
+#define HIMAX_DRIVER_VER "1.2.2.50_moto_05"
+
+#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
+/*===========Himax Option function=============*/
+#define HX_RST_PIN_FUNC
+#define HX_RESUME_SEND_CMD
+#define HX_ESD_RECOVERY
+#define HX_AUTO_UPDATE_FW
+/*#define HX_SMART_WAKEUP*/
+/*#define HX_GESTURE_TRACK*/
+/*#define HX_HIGH_SENSE*/
+/*#define HX_PALM_REPORT*/
+/*#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 CONFIG_CHIP_DTCFG*/
+/*#undef CONFIG_FB*/ /* Enable it if driver go into suspend/resume twice */
+
+/*#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
+
+#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_83103A_SERIES_PWON          "HX83103A"
+#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_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 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 HW_CRC_FAIL 1
+
+#define HX_FINGER_ON   1
+#define HX_FINGER_LEAVE        2
+
+#define HX_FILENAME_SIZE       80
+
+#if defined(HX_PALM_REPORT)
+#define PALM_REPORT 1
+#define NOT_REPORT -1
+#endif
+
+#define IC_HX83102     102
+
+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 = 36,
+       FIX_HX_TX_NUM = 18,
+       FIX_HX_BT_NUM = 0,
+       FIX_HX_X_RES = 720,
+       FIX_HX_Y_RES = 1520,
+       FIX_HX_MAX_PT = 10,
+       FIX_HX_XY_REVERSE = true,
+       FIX_HX_INT_IS_EDGE = true,
+#ifdef HX_TP_PROC_2T2R
+       FIX_HX_RX_NUM_2 = 0,
+       FIX_HX_TX_NUM_2 = 0,
+#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;
+       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
+       int ic_type_val;
+};
+
+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
+};
+
+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 suspended;
+       bool force_update;
+       atomic_t suspend_mode;
+       atomic_t flash_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 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;
+/******* SPI-end *******/
+
+       int in_self_test;
+
+#if defined(CONFIG_FB)
+       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
+
+       struct workqueue_struct *himax_diag_wq;
+       struct delayed_work himax_diag_delay_wrok;
+
+#ifdef HX_SMART_WAKEUP
+       uint8_t SMWP_enable;
+       uint8_t gesture_cust_en[26];
+       struct wake_lock ts_SMWP_wake_lock;
+#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;
+#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)
+#endif
+
+extern int irq_enable_count;
+
+/*void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);*/
+
+extern int himax_chip_common_suspend(struct himax_ts_data *ts);
+extern int himax_chip_common_resume(struct himax_ts_data *ts);
+
+#endif
+
diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.c b/drivers/input/touchscreen/hxchipset/himax_debug.c
new file mode 100755 (executable)
index 0000000..1050e90
--- /dev/null
@@ -0,0 +1,2719 @@
+/*     Himax Android Driver Sample Code for debug nodes
+
+       Copyright (C) 2018 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"
+
+extern struct himax_ic_data *ic_data;
+extern struct himax_ts_data *private_ts;
+extern struct himax_core_fp g_core_fp;
+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;
+
+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
+
+#ifdef HX_TP_PROC_2T2R
+       bool Is_2T2R = false;
+       int HX_RX_NUM_2 = 0;
+       int HX_TX_NUM_2 = 0;
+#endif
+
+#if defined(HX_ZERO_FLASH)
+extern char *i_CTPM_firmware_name;
+#endif
+
+uint8_t g_diag_arr_num = 0;
+
+extern uint8_t HX_PROC_SEND_FLAG;
+
+int g_max_mutual = 0;
+int g_min_mutual = 0xFFFF;
+int g_max_self = 0;
+int g_min_self = 0xFFFF;
+
+
+struct timespec timeStart, timeEnd, timeDelta;
+int g_switch_mode = 0;
+/* =============================================================================================================
+
+       Segment : Himax PROC Debug Function
+
+============================================================================================================= */
+static ssize_t himax_CRC_test_read(struct file *file, char *buf,
+                                                                               size_t len, loff_t *pos)
+{
+       ssize_t ret = 0;
+       uint8_t result = 0;
+       char *temp_buf;
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+               g_core_fp.fp_sense_off();
+               msleep(20);
+               result = g_core_fp.fp_calculateChecksum(false);
+               g_core_fp.fp_sense_on(0x01);
+
+               if (result) {
+                       ret += snprintf(temp_buf + ret, len - ret, "CRC test is Pass! \n");
+               } else {
+                       ret += snprintf(temp_buf + ret, len - ret, "CRC test is Fail! \n");
+               }
+
+               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_CRC_test_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_CRC_test_read,
+};
+
+static ssize_t himax_vendor_read(struct file *file, char *buf,
+                                                                       size_t len, loff_t *pos)
+{
+       ssize_t ret = 0;
+       char *temp_buf;
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+               ret += snprintf(temp_buf + ret, len - ret, "FW_VER = 0x%2.2X \n", ic_data->vendor_fw_ver);
+
+               if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) {
+                       ret += snprintf(temp_buf + ret, len - ret, "CONFIG_VER = 0x%2.2X \n", ic_data->vendor_config_ver);
+               } else {
+                       ret += snprintf(temp_buf + ret, len - ret, "TOUCH_VER = 0x%2.2X \n", ic_data->vendor_touch_cfg_ver);
+                       ret += snprintf(temp_buf + ret, len - 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(temp_buf + ret, len - ret, "CID_VER = NULL\n");
+               } else {
+                       ret += snprintf(temp_buf + ret, len - 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(temp_buf + ret, len - ret, "PANEL_VER = NULL\n");
+               } else {
+                       ret += snprintf(temp_buf + ret, len - ret, "PANEL_VER = 0x%2.2X \n", ic_data->vendor_panel_ver);
+               }
+
+               ret += snprintf(temp_buf + ret, len - ret, "\n");
+               ret += snprintf(temp_buf + ret, len - ret, "Himax Touch Driver Version:\n");
+               ret += snprintf(temp_buf + ret, len - ret, "%s \n", HIMAX_DRIVER_VER);
+               HX_PROC_SEND_FLAG = 1;
+
+               if (copy_to_user(buf, temp_buf, len)) {
+                       I("%s,here:%d\n", __func__, __LINE__);
+               }
+
+               kfree(temp_buf);
+       } else {
+               HX_PROC_SEND_FLAG = 0;
+       }
+
+       return ret;
+}
+
+static struct file_operations himax_proc_vendor_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_vendor_read,
+};
+
+static ssize_t himax_attn_read(struct file *file, char *buf,
+                                                               size_t len, loff_t *pos)
+{
+       ssize_t ret = 0;
+       struct himax_ts_data *ts_data;
+       char *temp_buf;
+       ts_data = private_ts;
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+               ret += snprintf(temp_buf + ret, len - ret, "attn = %x\n", himax_int_gpio_read(ts_data->pdata->gpio_irq));
+
+               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_attn_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_attn_read,
+};
+
+static ssize_t himax_int_en_read(struct file *file, char *buf,
+                                                                       size_t len, loff_t *pos)
+{
+       struct himax_ts_data *ts = private_ts;
+       size_t ret = 0;
+       char *temp_buf;
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+               ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->irq_enabled);
+               ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+               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 ssize_t himax_int_en_write(struct file *file, const char *buff,
+                                                                       size_t len, loff_t *pos)
+{
+       struct himax_ts_data *ts = private_ts;
+       char buf_tmp[12] = {0};
+       int value, ret = 0;
+
+       if (len >= 12) {
+               I("%s: no command exceeds 12 chars.\n", __func__);
+               return -EFAULT;
+       }
+
+       if (copy_from_user(buf_tmp, buff, len)) {
+               return -EFAULT;
+       }
+
+       if (buf_tmp[0] == '0') {
+               value = false;
+       } else if (buf_tmp[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->client->irq, ts);
+               ts->irq_enabled = 0;
+       }
+
+       return len;
+}
+
+static struct file_operations himax_proc_int_en_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_int_en_read,
+       .write = himax_int_en_write,
+};
+
+static ssize_t himax_layout_read(struct file *file, char *buf,
+                                                                       size_t len, loff_t *pos)
+{
+       struct himax_ts_data *ts = private_ts;
+       size_t ret = 0;
+       char *temp_buf;
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+               ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->pdata->abs_x_min);
+               ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->pdata->abs_x_max);
+               ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->pdata->abs_y_min);
+               ret += snprintf(temp_buf + ret, len - ret, "%d ", ts->pdata->abs_y_max);
+               ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+               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 ssize_t himax_layout_write(struct file *file, const char *buff,
+                                                                       size_t len, loff_t *pos)
+{
+       struct himax_ts_data *ts = private_ts;
+       char buf_tmp[5];
+       int i = 0, j = 0, k = 0, ret;
+       unsigned long value;
+       int layout[4] = {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;
+       }
+
+       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];
+               ts->pdata->abs_y_min = layout[2];
+               ts->pdata->abs_y_max = layout[3];
+               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 struct file_operations himax_proc_layout_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_layout_read,
+       .write = himax_layout_write,
+};
+
+static ssize_t himax_debug_level_read(struct file *file, char *buf,
+                                                                               size_t len, loff_t *pos)
+{
+       struct himax_ts_data *ts_data;
+       size_t ret = 0;
+       char *temp_buf;
+       ts_data = private_ts;
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+               ret += snprintf(temp_buf + ret, len - ret, "%d\n", ts_data->debug_log_level);
+
+               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 ssize_t himax_debug_level_write(struct file *file, const char *buff,
+                                                                               size_t len, loff_t *pos)
+{
+       struct himax_ts_data *ts;
+       char buf_tmp[11];
+       int i;
+       ts = private_ts;
+
+       if (len >= 12) {
+               I("%s: no command exceeds 12 chars.\n", __func__);
+               return -EFAULT;
+       }
+
+       if (copy_from_user(buf_tmp, buff, len)) {
+               return -EFAULT;
+       }
+
+       ts->debug_log_level = 0;
+
+       for (i = 0; i < len - 1; i++) {
+               if (buf_tmp[i] >= '0' && buf_tmp[i] <= '9')
+                       ts->debug_log_level |= (buf_tmp[i] - '0');
+               else if (buf_tmp[i] >= 'A' && buf_tmp[i] <= 'F')
+                       ts->debug_log_level |= (buf_tmp[i] - 'A' + 10);
+               else if (buf_tmp[i] >= 'a' && buf_tmp[i] <= 'f')
+                       ts->debug_log_level |= (buf_tmp[i] - 'a' + 10);
+
+               if (i != len - 2)
+                       ts->debug_log_level <<= 4;
+       }
+
+       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;
+       }
+
+       return len;
+}
+
+static struct file_operations himax_proc_debug_level_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_debug_level_read,
+       .write = himax_debug_level_write,
+};
+
+static ssize_t himax_proc_register_read(struct file *file, char *buf,
+                                                                               size_t len, loff_t *pos)
+{
+       int ret = 0;
+       uint16_t loop_i;
+       uint8_t data[128];
+       char *temp_buf;
+       memset(data, 0x00, sizeof(data));
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+               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, data, cfg_flag);
+               ret += snprintf(temp_buf + 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(temp_buf + ret, len - ret, "0x%2.2X ", data[loop_i]);
+                       if ((loop_i % 16) == 15)
+                               ret += snprintf(temp_buf + ret, len - ret, "\n");
+               }
+
+               ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+               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 ssize_t himax_proc_register_write(struct file *file, const char *buff,
+               size_t len, loff_t *pos)
+{
+       char buf[80] = {0};
+       char buf_tmp[16];
+       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];
+       uint8_t x_pos[20];
+       uint8_t count = 0;
+
+       if (len >= 80) {
+               I("%s: no command exceeds 80 chars.\n", __func__);
+               return -EFAULT;
+       }
+
+       if (copy_from_user(buf, buff, len)) {
+               return -EFAULT;
+       }
+
+       memset(buf_tmp, 0x0, sizeof(buf_tmp));
+       memset(w_data, 0x0, sizeof(w_data));
+       memset(x_pos, 0x0, sizeof(x_pos));
+       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) - 1;
+
+               if (buf[0] == 'r') {
+                       if (buf[3] == 'F' && buf[4] == 'E' && length == 4) {
+                               length = length - base;
+                               cfg_flag = 1;
+                               memcpy(buf_tmp, data_str + base + 1, length);
+                       } else {
+                               cfg_flag = 0;
+                               memcpy(buf_tmp, data_str + 1, length);
+                       }
+
+                       byte_length = length / 2;
+
+                       if (!kstrtoul(buf_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;
+               } else if (buf[0] == 'w') {
+                       if (buf[3] == 'F' && buf[4] == 'E') {
+                               cfg_flag = 1;
+                               memcpy(buf_tmp, buf + base + 3, length);
+                       } else {
+                               cfg_flag = 0;
+                               memcpy(buf_tmp, buf + 3, length);
+                       }
+
+                       if (count < 3) {
+                               byte_length = length / 2;
+
+                               if (!kstrtoul(buf_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(buf_tmp, 0x0, sizeof(buf_tmp));
+                                       if (cfg_flag != 0 && loop_i != 0)
+                                               byte_length = 2;
+                                       else
+                                               byte_length = x_pos[1] - x_pos[0] - 2; /* original */
+
+                                       memcpy(buf_tmp, buf + x_pos[loop_i] + 1, byte_length);
+
+                                       /* I("%s: buf_tmp = %s\n", __func__,buf_tmp); */
+                                       if (!kstrtoul(buf_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);
+                       }
+               } else {
+                       return len;
+               }
+       }
+
+       return len;
+}
+
+static struct file_operations himax_proc_register_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_proc_register_read,
+       .write = himax_proc_register_write,
+};
+
+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];
+}
+uint8_t getXChannel(void)
+{
+       return x_channel;
+}
+uint8_t getYChannel(void)
+{
+       return y_channel;
+}
+void setXChannel(uint8_t x)
+{
+       x_channel = x;
+}
+void setYChannel(uint8_t y)
+{
+       y_channel = y;
+}
+void setMutualBuffer(void)
+{
+       diag_mutual = kzalloc(x_channel * y_channel * sizeof(int32_t), GFP_KERNEL);
+}
+void setMutualNewBuffer(void)
+{
+       diag_mutual_new = kzalloc(x_channel * y_channel * sizeof(int32_t), GFP_KERNEL);
+}
+void setMutualOldBuffer(void)
+{
+       diag_mutual_old = kzalloc(x_channel * y_channel * sizeof(int32_t), GFP_KERNEL);
+}
+
+#ifdef HX_TP_PROC_2T2R
+int32_t *getMutualBuffer_2(void)
+{
+       return diag_mutual_2;
+}
+uint8_t getXChannel_2(void)
+{
+       return x_channel_2;
+}
+uint8_t getYChannel_2(void)
+{
+       return y_channel_2;
+}
+void setXChannel_2(uint8_t x)
+{
+       x_channel_2 = x;
+}
+void setYChannel_2(uint8_t y)
+{
+       y_channel_2 = y;
+}
+void setMutualBuffer_2(void)
+{
+       diag_mutual_2 = kzalloc(x_channel_2 * y_channel_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 = getXChannel_2() * getYChannel_2();
+#ifdef HX_EN_SEL_BUTTON
+                       self_num = getXChannel_2() + getYChannel_2() + ic_data->HX_BT_NUM;
+#else
+                       self_num = getXChannel_2() + getYChannel_2();
+#endif
+               } else
+#endif
+               {
+                       mutual_data = getMutualBuffer();
+                       self_data = getSelfBuffer();
+                       /*      initiallize the block number of mutual and self */
+                       mul_num = getXChannel() * getYChannel();
+#ifdef HX_EN_SEL_BUTTON
+                       self_num = getXChannel() + getYChannel() + ic_data->HX_BT_NUM;
+#else
+                       self_num = getXChannel() + getYChannel();
+#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) */
+extern struct himax_target_report_data *g_target_report_data;
+extern struct himax_report_data *hx_touch_data;
+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_info_size;
+               buf = kzalloc(hx_touch_data->touch_info_size*sizeof(uint8_t), GFP_KERNEL);
+               memcpy(buf, hx_touch_data->hx_coord_buf, hx_touch_data->touch_info_size);
+       } else if (hx_touch_data->diag_cmd > 0) {
+               print_size = hx_touch_data->touch_all_size;
+               buf = kzalloc(hx_touch_data->touch_info_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, hx_touch_data->touch_all_size - hx_touch_data->touch_info_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("%s: over flow\n", __func__);
+                       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 (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\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);
+                       }
+               }
+       } 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);
+       } else {
+               I("%s : wrong input!\n", __func__);
+       }
+}
+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("status: Raw:F:%02d Down, X:%d, Y:%d, W:%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]);
+                               }
+                       } else if ((((ts->old_finger >> loop_i & 1) == 1) && ((ts->pre_finger_mask >> loop_i & 1) == 0))) {
+                               I("status: Raw:F:%02d Up, X:%d, Y:%d\n", 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)
+{
+       switch (ts->debug_log_level) {
+       case 1:
+               himax_log_touch_data(start);
+               break;
+       case 2:
+               himax_log_touch_event(ts, start);
+               break;
+       case 4:
+               himax_log_touch_int_devation(start);
+               break;
+       case 8:
+               himax_log_touch_event_detail(ts, start);
+               break;
+       }
+}
+
+/* #endif */
+static ssize_t himax_diag_arrange_write(struct file *file, const char *buff,
+                                                                               size_t len, loff_t *pos)
+{
+       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;
+       }
+
+       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 < (x_channel * y_channel); 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 < (x_channel + y_channel); 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];
+       }
+}
+
+/* print first step which is row */
+static struct file_operations himax_proc_diag_arrange_ops = {
+       .owner = THIS_MODULE,
+       .write = himax_diag_arrange_write,
+};
+static void print_state_info(struct seq_file *s)
+{
+       /* seq_printf(s, "State_info_2bytes:%3d, %3d\n",hx_state_info[0],hx_state_info[1]); */
+       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);
+}
+
+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 * x_channel]);
+       else
+               seq_printf(s, "%6d", diag_mutual[i + j * x_channel]);
+}
+
+/* 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 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 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 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_printf(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_printf(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)
+{
+}
+
+static int himax_diag_seq_read(struct seq_file *s, void *v)
+{
+       struct himax_ts_data *ts = private_ts;
+       size_t ret = 0;
+       uint32_t loop_i;
+       uint16_t mutual_num, self_num, width;
+       int dsram_type = 0;
+       dsram_type = ts->diag_cmd / 10;
+
+#ifdef HX_TP_PROC_2T2R
+       if (Is_2T2R && (ts->diag_cmd >= 4 && ts->diag_cmd <= 6)) {
+               mutual_num      = x_channel_2 * y_channel_2;
+               self_num        = x_channel_2 + y_channel_2; /* don't add KEY_COUNT */
+               width           = x_channel_2;
+               seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel_2, y_channel_2);
+       } else
+#endif
+       {
+               mutual_num      = x_channel * y_channel;
+               self_num        = x_channel + y_channel; /* don't add KEY_COUNT */
+               width           = x_channel;
+               seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel, y_channel);
+       }
+
+       /*      start to show out the raw data in adb shell */
+       if ((ts->diag_cmd >= 1 && ts->diag_cmd <= 3) || (ts->diag_cmd == 7)) {
+               himax_diag_arrange(s);
+               seq_printf(s, "\n");
+#ifdef HX_EN_SEL_BUTTON
+               seq_printf(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_printf(s, "ChannelEnd");
+               seq_printf(s, "\n");
+#ifdef HX_TP_PROC_2T2R
+       } else if (Is_2T2R && ts->diag_cmd >= 4 && ts->diag_cmd <= 6) {
+               for (loop_i = 0; loop_i < mutual_num; loop_i++) {
+                       seq_printf(s, "%4d", diag_mutual_2[loop_i]);
+
+                       if ((loop_i % width) == (width - 1))
+                               seq_printf(s, " %4d\n", diag_self[width + loop_i / width]);
+               }
+
+               seq_printf(s, "\n");
+
+               for (loop_i = 0; loop_i < width; loop_i++) {
+                       seq_printf(s, "%4d", diag_self[loop_i]);
+
+                       if (((loop_i) % width) == (width - 1))
+                               seq_printf(s, "\n");
+               }
+
+#ifdef HX_EN_SEL_BUTTON
+               seq_printf(s, "\n");
+
+               for (loop_i = 0; loop_i < ic_data->HX_BT_NUM; loop_i++)
+                       seq_printf(s, "%4d", diag_self[ic_data->HX_RX_NUM_2 + ic_data->HX_TX_NUM_2 + loop_i]);
+
+#endif
+               seq_printf(s, "ChannelEnd");
+               seq_printf(s, "\n");
+#endif
+       } else if (ts->diag_cmd == 8) {
+               for (loop_i = 0; loop_i < 128 ; loop_i++) {
+                       if ((loop_i % 16) == 0)
+                               seq_printf(s, "LineStart:");
+
+                       seq_printf(s, "%4x", diag_coor[loop_i]);
+
+                       if ((loop_i % 16) == 15)
+                               seq_printf(s, "\n");
+               }
+       } else if (dsram_type > 0 && dsram_type <= 8) {
+               himax_diag_arrange(s);
+               seq_printf(s, "\n ChannelEnd");
+               seq_printf(s, "\n");
+       }
+
+       if ((ts->diag_cmd >= 1 && ts->diag_cmd <= 7) || dsram_type > 0) {
+               /* 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);
+       return ret;
+}
+static struct seq_operations himax_diag_seq_ops = {
+       .start  = himax_diag_seq_start,
+       .next   = himax_diag_seq_next,
+       .stop   = himax_diag_seq_stop,
+       .show   = himax_diag_seq_read,
+};
+static int himax_diag_proc_open(struct inode *inode, struct file *file)
+{
+       return seq_open(file, &himax_diag_seq_ops);
+};
+bool DSRAM_Flag = false;
+
+/* DSRAM thread */
+bool himax_ts_diag_func(void)
+{
+       struct himax_ts_data *ts = private_ts;
+       int i = 0, j = 0;
+       unsigned int index = 0;
+       int total_size = (y_channel * x_channel + y_channel + x_channel) * 2;
+       uint8_t *info_data;
+       int32_t *mutual_data;
+       int32_t *mutual_data_new;
+       int32_t *mutual_data_old;
+       int32_t *self_data;
+       int32_t *self_data_new;
+       int32_t *self_data_old;
+       int32_t new_data;
+       /* 1:common dsram,2:100 frame Max,3:N-(N-1)frame */
+       int dsram_type = 0;
+       char temp_buf[20];
+       char write_buf[total_size * 3];
+
+       mutual_data = NULL;
+       mutual_data_new = NULL;
+       mutual_data_old = NULL;
+       self_data = NULL;
+       self_data_new = NULL;
+       self_data_old = NULL;
+
+       info_data = kzalloc(total_size * sizeof(uint8_t), GFP_KERNEL);
+       if (info_data == NULL)
+               return false;
+
+       memset(write_buf, '\0', sizeof(write_buf));
+       memset(info_data, 0, total_size * sizeof(uint8_t));
+       dsram_type = ts->diag_cmd / 10;
+       I("%s:Entering ts->diag_cmd=%d!\n", __func__, ts->diag_cmd);
+
+       if (dsram_type == 8) {
+               dsram_type = 1;
+               I("%s Sorting Mode run sram type1 ! \n", __func__);
+       }
+
+       g_core_fp.fp_burst_enable(1);
+
+       if (dsram_type == 1 || dsram_type == 2 || dsram_type == 4) {
+               mutual_data = getMutualBuffer();
+               self_data = getSelfBuffer();
+       } else if (dsram_type == 3) {
+               mutual_data = getMutualBuffer();
+               mutual_data_new = getMutualNewBuffer();
+               mutual_data_old = getMutualOldBuffer();
+               self_data = getSelfBuffer();
+               self_data_new = getSelfNewBuffer();
+               self_data_old = getSelfOldBuffer();
+       }
+
+       if (g_core_fp.fp_get_DSRAM_data(info_data, DSRAM_Flag) == false)
+               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 || dsram_type == 4) {
+                               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 || dsram_type == 4) {
+                       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);
+       } else if (dsram_type == 4) {
+               for (i = 0; i < x_channel * y_channel; i++) {
+                       memset(temp_buf, '\0', sizeof(temp_buf));
+
+                       if (i == (x_channel * y_channel - 1)) {
+                               snprintf(temp_buf, sizeof(temp_buf), "%4d\t", mutual_data[i]);
+                               snprintf(temp_buf, sizeof(temp_buf), "%4d\n", self_data[x_channel + y_channel - 1]);
+                               I("%s :i = %d 3\n", __func__, i);
+                       } else if (i % x_channel == (x_channel - 1)) {
+                               snprintf(temp_buf, sizeof(temp_buf), "%4d\t", mutual_data[i]);
+                               snprintf(temp_buf, sizeof(temp_buf), "%4d\n", self_data[x_channel + (i / x_channel) + 1]);
+                       } else {
+                               snprintf(temp_buf, sizeof(temp_buf), "%4d\t", mutual_data[i]);
+                       }
+//                     strlcat(&write_buf[i*strlen(temp_buf)], temp_buf, strlen(temp_buf));
+               }
+
+               for (i = 0; i < x_channel; i++) {
+                       memset(temp_buf, '\0', sizeof(temp_buf));
+                       if (i == x_channel - 1)
+                               snprintf(temp_buf, sizeof(temp_buf), "%4d\n", self_data[i]);
+                       else
+                               snprintf(temp_buf, sizeof(temp_buf), "%4d\t", self_data[i]);
+//                     strlcat(&write_buf[(i+x_channel * y_channel)*strlen(temp_buf)], temp_buf, strlen(temp_buf));
+               }
+
+               /* save raw data in file */
+               if (!IS_ERR(diag_sram_fn)) {
+                       I("%s create file and ready to write\n", __func__);
+                       diag_sram_fn->f_op->write(diag_sram_fn, write_buf, sizeof(write_buf), &diag_sram_fn->f_pos);
+                       write_counter++;
+
+                       if (write_counter < write_max_count) {
+                               queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1 / 10 * HZ);
+                       } else {
+                               filp_close(diag_sram_fn, NULL);
+                               write_counter = 0;
+                       }
+               }
+       }
+       return true;
+}
+
+static ssize_t himax_diag_write(struct file *filp, const char __user *buff, size_t len, loff_t *data)
+{
+       struct himax_ts_data *ts = private_ts;
+       char messages[80] = {0};
+       /*struct filename *vts_name;*/
+       uint8_t command[2] = {0x00, 0x00};
+       uint8_t receive[1];
+       /* 0: common , other: dsram*/
+       int storage_type = 0;
+       /* 1:IIR,2:DC,3:Bank,4:IIR2,5:IIR2_N,6:FIR2,7:Baseline,8:dump coord */
+       int rawdata_type = 0;
+       memset(receive, 0x00, sizeof(receive));
+
+       if (len >= 80) {
+               I("%s: no command exceeds 80 chars.\n", __func__);
+               return -EFAULT;
+       }
+
+       if (copy_from_user(messages, buff, len)) {
+               return -EFAULT;
+       }
+
+       I("%s:g_switch_mode = %d\n", __func__, g_switch_mode);
+
+       if (messages[1] == 0x0A) {
+               ts->diag_cmd = messages[0] - '0';
+       } else {
+               ts->diag_cmd = (messages[0] - '0') * 10 + (messages[1] - '0');
+       }
+
+       storage_type = g_core_fp.fp_determin_diag_storage(ts->diag_cmd);
+       rawdata_type = g_core_fp.fp_determin_diag_rawdata(ts->diag_cmd);
+
+       if (ts->diag_cmd > 0 && rawdata_type == 0) {
+               I("[Himax]ts->diag_cmd=0x%x ,storage_type=%d, rawdata_type=%d! Maybe no support!\n"
+                 , ts->diag_cmd, storage_type, rawdata_type);
+               ts->diag_cmd = 0x00;
+       } else {
+               I("[Himax]ts->diag_cmd=0x%x ,storage_type=%d, rawdata_type=%d\n", ts->diag_cmd, storage_type, rawdata_type);
+       }
+
+       memset(diag_mutual, 0x00, x_channel * y_channel * sizeof(int32_t)); /* Set data 0 */
+       memset(diag_self, 0x00, sizeof(diag_self));
+       if (storage_type == 0 && rawdata_type > 0 && rawdata_type < 8) {
+               I("%s,common\n", __func__);
+
+               if (DSRAM_Flag) {
+                       /* 1. Clear DSRAM flag */
+                       DSRAM_Flag = false;
+                       /* 2. Stop DSRAM thread */
+                       cancel_delayed_work(&private_ts->himax_diag_delay_wrok);
+                       /* 3. Enable ISR */
+                       himax_int_enable(1);
+                       /*(4) FW leave sram and return to event stack*/
+                       g_core_fp.fp_return_event_stack();
+               }
+
+               if (g_switch_mode == 2) {
+                       g_core_fp.fp_idle_mode(0);
+                       g_switch_mode = g_core_fp.fp_switch_mode(0);
+               }
+
+               if (ts->diag_cmd == 0x04) {
+#if defined(HX_TP_PROC_2T2R)
+                       command[0] = ts->diag_cmd;
+#else
+                       ts->diag_cmd = 0x00;
+                       command[0] = 0x00;
+#endif
+               } else {
+                       command[0] = ts->diag_cmd;
+               }
+
+               g_core_fp.fp_diag_register_set(command[0], storage_type);
+       } else if (storage_type > 0 && storage_type < 8 && rawdata_type > 0 && rawdata_type < 8) {
+               I("%s,dsram\n", __func__);
+               diag_max_cnt = 0;
+
+               /* 0. set diag flag */
+               if (DSRAM_Flag) {
+                       /* (1) Clear DSRAM flag */
+                       DSRAM_Flag = false;
+                       /* (2) Stop DSRAM thread */
+                       cancel_delayed_work(&private_ts->himax_diag_delay_wrok);
+                       /* (3) Enable ISR */
+                       himax_int_enable(1);
+                       /*(4) FW leave sram and return to event stack*/
+                       g_core_fp.fp_return_event_stack();
+               }
+
+               /* close sorting if turn on*/
+               if (g_switch_mode == 2) {
+                       g_core_fp.fp_idle_mode(0);
+                       g_switch_mode = g_core_fp.fp_switch_mode(0);
+               }
+
+               command[0] = rawdata_type;/* ts->diag_cmd; */
+               g_core_fp.fp_diag_register_set(command[0], storage_type);
+               /* 1. Disable ISR */
+               himax_int_enable(0);
+#if 0
+               /* Open file for save raw data log */
+               if (storage_type == 4) {
+                       switch (rawdata_type) {
+                       case 1:
+                               vts_name = getname_kernel(IIR_DUMP_FILE);
+                               diag_sram_fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0);
+                               break;
+
+                       case 2:
+                               vts_name = getname_kernel(DC_DUMP_FILE);
+                               diag_sram_fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0);
+                               break;
+
+                       case 3:
+                               vts_name = getname_kernel(BANK_DUMP_FILE);
+                               diag_sram_fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0);
+                               break;
+
+                       default:
+                               I("%s raw data type is not true. raw data type is %d \n", __func__, rawdata_type);
+                       }
+               }
+#endif
+               /* 2. Start DSRAM thread */
+               queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 2 * HZ / 100);
+               I("%s: Start get raw data in DSRAM\n", __func__);
+
+               if (storage_type == 4)
+                       msleep(6000);
+
+               /* 3. Set DSRAM flag */
+               DSRAM_Flag = true;
+       } else if (storage_type == 8) {
+               I("Soritng mode!\n");
+
+               if (DSRAM_Flag) {
+                       /* 1. Clear DSRAM flag */
+                       DSRAM_Flag = false;
+                       /* 2. Stop DSRAM thread */
+                       cancel_delayed_work(&private_ts->himax_diag_delay_wrok);
+                       /* 3. Enable ISR */
+                       himax_int_enable(1);
+                       /*(4) FW leave sram and return to event stack*/
+                       g_core_fp.fp_return_event_stack();
+               }
+
+               g_core_fp.fp_idle_mode(1);
+               g_switch_mode = g_core_fp.fp_switch_mode(1);
+
+               if (g_switch_mode == 2) {
+                       g_core_fp.fp_diag_register_set(command[0], storage_type);
+               }
+
+               queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 2 * HZ / 100);
+               DSRAM_Flag = true;
+       } else {
+               /* set diag flag */
+               if (DSRAM_Flag) {
+                       I("return and cancel sram thread!\n");
+                       /* (1) Clear DSRAM flag */
+                       DSRAM_Flag = false;
+                       /* (2) Stop DSRAM thread */
+                       cancel_delayed_work(&private_ts->himax_diag_delay_wrok);
+                       /* (3) Enable ISR */
+                       himax_int_enable(1);
+                       /*(4) FW leave sram and return to event stack*/
+                       g_core_fp.fp_return_event_stack();
+               }
+
+               if (g_switch_mode == 2) {
+                       g_core_fp.fp_idle_mode(0);
+                       g_switch_mode = g_core_fp.fp_switch_mode(0);
+               }
+
+               if (ts->diag_cmd != 0x00) {
+                       E("[Himax]ts->diag_cmd error!diag_command=0x%x so reset\n", ts->diag_cmd);
+                       command[0] = 0x00;
+
+                       if (ts->diag_cmd != 0x08)
+                               ts->diag_cmd = 0x00;
+
+                       g_core_fp.fp_diag_register_set(command[0], storage_type);
+               } else {
+                       command[0] = 0x00;
+                       ts->diag_cmd = 0x00;
+                       g_core_fp.fp_diag_register_set(command[0], storage_type);
+                       I("return to normal ts->diag_cmd=0x%x\n", ts->diag_cmd);
+               }
+       }
+       return len;
+}
+
+static struct file_operations himax_proc_diag_ops = {
+       .owner = THIS_MODULE,
+       .open = himax_diag_proc_open,
+       .read = seq_read,
+       .write = himax_diag_write,
+};
+
+static ssize_t himax_reset_write(struct file *file, const char *buff,
+                                                                size_t len, loff_t *pos)
+{
+       char buf_tmp[12];
+
+       if (len >= 12) {
+               I("%s: no command exceeds 12 chars.\n", __func__);
+               return -EFAULT;
+       }
+
+       if (copy_from_user(buf_tmp, buff, len)) {
+               return -EFAULT;
+       }
+
+#ifdef HX_RST_PIN_FUNC
+
+       if (buf_tmp[0] == '1') {
+               g_core_fp.fp_ic_reset(false, false);
+       } else if (buf_tmp[0] == '2') {
+               g_core_fp.fp_ic_reset(false, true);
+       } else if (buf_tmp[0] == '3') {
+               g_core_fp.fp_ic_reset(true, false);
+       } else if (buf_tmp[0] == '4') {
+               g_core_fp.fp_ic_reset(true, true);
+       }
+       /* else if (buf_tmp[0] == '5') */
+       /*      ESD_HW_REST(); */
+#endif
+       return len;
+}
+
+static struct file_operations himax_proc_reset_ops = {
+       .owner = THIS_MODULE,
+       .write = himax_reset_write,
+};
+
+static ssize_t himax_debug_read(struct file *file, char *buf,
+                                                               size_t len, loff_t *pos)
+{
+       size_t ret = 0;
+       char *temp_buf;
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+
+               if (debug_level_cmd == 't') {
+                       if (fw_update_complete) {
+                               ret += snprintf(temp_buf + ret, len - ret, "FW Update Complete ");
+                       } else {
+                               ret += snprintf(temp_buf + ret, len - ret, "FW Update Fail ");
+                       }
+               } else if (debug_level_cmd == 'h') {
+                       if (handshaking_result == 0) {
+                               ret += snprintf(temp_buf + ret, len - ret, "Handshaking Result = %d (MCU Running)\n", handshaking_result);
+                       } else if (handshaking_result == 1) {
+                               ret += snprintf(temp_buf + ret, len - ret, "Handshaking Result = %d (MCU Stop)\n", handshaking_result);
+                       } else if (handshaking_result == 2) {
+                               ret += snprintf(temp_buf + ret, len - ret, "Handshaking Result = %d (I2C Error)\n", handshaking_result);
+                       } else {
+                               ret += snprintf(temp_buf + ret, len - ret, "Handshaking Result = error \n");
+                       }
+               } else if (debug_level_cmd == 'v') {
+                       ret += snprintf(temp_buf + ret, len - ret, "FW_VER = 0x%2.2X \n", ic_data->vendor_fw_ver);
+
+                       if (private_ts->chip_cell_type == CHIP_IS_ON_CELL) {
+                               ret += snprintf(temp_buf + ret, len - ret, "CONFIG_VER = 0x%2.2X \n", ic_data->vendor_config_ver);
+                       } else {
+                               ret += snprintf(temp_buf + ret, len - ret, "TOUCH_VER = 0x%2.2X \n", ic_data->vendor_touch_cfg_ver);
+                               ret += snprintf(temp_buf + ret, len - 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(temp_buf + ret, len - ret, "CID_VER = NULL\n");
+                       else
+                               ret += snprintf(temp_buf + ret, len - 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(temp_buf + ret, len - ret, "PANEL_VER = NULL\n");
+                       else
+                               ret += snprintf(temp_buf + ret, len - ret, "PANEL_VER = 0x%2.2X \n", ic_data->vendor_panel_ver);
+
+                       ret += snprintf(temp_buf + ret, len - ret, "\n");
+                       ret += snprintf(temp_buf + ret, len - ret, "Himax Touch Driver Version:\n");
+                       ret += snprintf(temp_buf + ret, len - ret, "%s \n", HIMAX_DRIVER_VER);
+               } else if (debug_level_cmd == 'd') {
+                       ret += snprintf(temp_buf + ret, len - ret, "Himax Touch IC Information :\n");
+                       ret += snprintf(temp_buf + ret, len - ret, "%s \n", private_ts->chip_name);
+
+                       switch (IC_CHECKSUM) {
+                       case HX_TP_BIN_CHECKSUM_SW:
+                               ret += snprintf(temp_buf + ret, len - ret, "IC Checksum : SW\n");
+                               break;
+
+                       case HX_TP_BIN_CHECKSUM_HW:
+                               ret += snprintf(temp_buf + ret, len - ret, "IC Checksum : HW\n");
+                               break;
+
+                       case HX_TP_BIN_CHECKSUM_CRC:
+                               ret += snprintf(temp_buf + ret, len - ret, "IC Checksum : CRC\n");
+                               break;
+
+                       default:
+                               ret += snprintf(temp_buf + ret, len - ret, "IC Checksum error.\n");
+                       }
+
+                       if (ic_data->HX_INT_IS_EDGE) {
+                               ret += snprintf(temp_buf + ret, len - ret, "Driver register Interrupt : EDGE TIRGGER\n");
+                       } else {
+                               ret += snprintf(temp_buf + ret, len - ret, "Driver register Interrupt : LEVEL TRIGGER\n");
+                       }
+                       if (private_ts->protocol_type == PROTOCOL_TYPE_A) {
+                               ret += snprintf(temp_buf + ret, len - ret, "Protocol : TYPE_A\n");
+                       } else {
+                               ret += snprintf(temp_buf + ret, len - ret, "Protocol : TYPE_B\n");
+                       }
+
+                       ret += snprintf(temp_buf + ret, len - ret, "RX Num : %d\n", ic_data->HX_RX_NUM);
+                       ret += snprintf(temp_buf + ret, len - ret, "TX Num : %d\n", ic_data->HX_TX_NUM);
+                       ret += snprintf(temp_buf + ret, len - ret, "BT Num : %d\n", ic_data->HX_BT_NUM);
+                       ret += snprintf(temp_buf + ret, len - ret, "X Resolution : %d\n", ic_data->HX_X_RES);
+                       ret += snprintf(temp_buf + ret, len - ret, "Y Resolution : %d\n", ic_data->HX_Y_RES);
+                       ret += snprintf(temp_buf + ret, len - ret, "Max Point : %d\n", ic_data->HX_MAX_PT);
+                       ret += snprintf(temp_buf + ret, len - ret, "XY reverse : %d\n", ic_data->HX_XY_REVERSE);
+#ifdef HX_TP_PROC_2T2R
+                       if (Is_2T2R) {
+                               ret += snprintf(temp_buf + ret, len - ret, "2T2R panel\n");
+                               ret += snprintf(temp_buf + ret, len - ret, "RX Num_2 : %d\n", HX_RX_NUM_2);
+                               ret += snprintf(temp_buf + ret, len - 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(temp_buf + ret, len - ret, "I2C communication is bad.\n");
+                       else
+                               ret += snprintf(temp_buf + ret, len - ret, "I2C communication is good.\n");
+               } else if (debug_level_cmd == 'n') {
+                       if (g_core_fp.fp_read_ic_trigger_type() == 1) /* Edgd = 1, Level = 0 */
+                               ret += snprintf(temp_buf + ret, len - ret, "IC Interrupt type is edge trigger.\n");
+                       else if (g_core_fp.fp_read_ic_trigger_type() == 0)
+                               ret += snprintf(temp_buf + ret, len - ret, "IC Interrupt type is level trigger.\n");
+                       else
+                               ret += snprintf(temp_buf + ret, len - ret, "Unkown IC trigger type.\n");
+
+                       if (ic_data->HX_INT_IS_EDGE)
+                               ret += snprintf(temp_buf + ret, len - ret, "Driver register Interrupt : EDGE TIRGGER\n");
+                       else
+                               ret += snprintf(temp_buf + ret, len - ret, "Driver register Interrupt : LEVEL TRIGGER\n");
+               }
+
+               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;
+}
+
+extern int g_ts_dbg;
+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
+
+
+       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] == 'h') { /* handshaking */
+               debug_level_cmd = buf[0];
+               himax_int_enable(0);
+               handshaking_result = g_core_fp.fp_hand_shaking(); /* 0:Running, 1:Stop, 2:I2C Fail */
+               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
+               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 commutation */
+               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();
+               return len;
+#endif
+       } else { /* 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);
+#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 struct file_operations himax_proc_debug_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_debug_read,
+       .write = himax_debug_write,
+};
+
+static ssize_t himax_proc_FW_debug_read(struct file *file, char *buf,
+                                                                               size_t len, loff_t *pos)
+{
+       ssize_t ret = 0;
+       uint8_t loop_i = 0;
+       uint8_t tmp_data[64];
+       char *temp_buf;
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+               cmd_set[0] = 0x01;
+
+               if (g_core_fp.fp_read_FW_status(cmd_set, tmp_data) == NO_ERR) {
+                       ret += snprintf(temp_buf + ret, len - 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(temp_buf + ret, len - ret, "%5d\t", tmp_data[loop_i]);
+                       }
+
+                       ret += snprintf(temp_buf + ret, len - 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(temp_buf + ret, len - 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(temp_buf + ret, len - ret, "%5d\t", tmp_data[loop_i] + (tmp_data[loop_i + 1] << 8));
+
+                               if ((loop_i % 16) == 14)
+                                       ret += snprintf(temp_buf + ret, len - ret, "\n");
+                       }
+               }
+
+               ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+               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_fw_debug_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_proc_FW_debug_read,
+};
+
+static ssize_t himax_proc_DD_debug_read(struct file *file, char *buf,
+                                                                               size_t len, loff_t *pos)
+{
+       ssize_t ret = 0;
+       uint8_t tmp_data[64];
+       uint8_t loop_i = 0;
+       char *temp_buf;
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+
+               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(temp_buf + ret, len - ret, "0x%02X : ", loop_i);
+
+                                       ret += snprintf(temp_buf + ret, len - ret, "0x%02X ", tmp_data[loop_i]);
+
+                                       if ((loop_i % 8) == 7)
+                                               ret += snprintf(temp_buf + ret, len - ret, "\n");
+                               }
+                       }
+               }
+
+               ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+               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 ssize_t himax_proc_DD_debug_write(struct file *file, const char *buff,
+               size_t len, loff_t *pos)
+{
+       uint8_t i = 0;
+       uint8_t cnt = 2;
+       unsigned long result = 0;
+       char buf_tmp[20];
+       char buf_tmp2[4];
+
+       if (len >= 20) {
+               I("%s: no command exceeds 20 chars.\n", __func__);
+               return -EFAULT;
+       }
+
+       if (copy_from_user(buf_tmp, buff, len)) {
+               return -EFAULT;
+       }
+
+       memset(buf_tmp2, 0x0, sizeof(buf_tmp2));
+
+       if (buf_tmp[2] == 'x' && buf_tmp[6] == 'x' && buf_tmp[10] == 'x') {
+               mutual_set_flag = 1;
+
+               for (i = 3; i < 12; i = i + 4) {
+                       memcpy(buf_tmp2, buf_tmp + i, 2);
+
+                       if (!kstrtoul(buf_tmp2, 16, &result))
+                               cmd_set[cnt] = (uint8_t)result;
+                       else
+                               I("String to oul is fail in cnt = %d, buf_tmp2 = %s\n", 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;
+}
+
+static struct file_operations himax_proc_dd_debug_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_proc_DD_debug_read,
+       .write = himax_proc_DD_debug_write,
+};
+
+uint8_t getFlashCommand(void)
+{
+       return flash_command;
+}
+
+static uint8_t getFlashDumpProgress(void)
+{
+       return flash_progress;
+}
+
+static uint8_t getFlashDumpComplete(void)
+{
+       return flash_dump_complete;
+}
+
+static uint8_t getFlashDumpFail(void)
+{
+       return flash_dump_fail;
+}
+
+uint8_t getSysOperation(void)
+{
+       return sys_operation;
+}
+
+static uint8_t getFlashReadStep(void)
+{
+       return flash_read_step;
+}
+
+bool getFlashDumpGoing(void)
+{
+       return flash_dump_going;
+}
+
+void setFlashBuffer(void)
+{
+       flash_buffer = kzalloc(Flash_Size * sizeof(uint8_t), GFP_KERNEL);
+}
+
+void setSysOperation(uint8_t operation)
+{
+       sys_operation = operation;
+}
+
+void setFlashDumpProgress(uint8_t progress)
+{
+       flash_progress = progress;
+       /* I("setFlashDumpProgress : progress = %d ,flash_progress = %d \n",progress,flash_progress); */
+}
+
+void setFlashDumpComplete(uint8_t status)
+{
+       flash_dump_complete = status;
+}
+
+void setFlashDumpFail(uint8_t fail)
+{
+       flash_dump_fail = fail;
+}
+
+static void setFlashCommand(uint8_t command)
+{
+       flash_command = command;
+}
+
+static void setFlashReadStep(uint8_t step)
+{
+       flash_read_step = step;
+}
+
+void setFlashDumpGoing(bool going)
+{
+       flash_dump_going = going;
+       debug_data->flash_dump_going = going;
+}
+
+static ssize_t himax_proc_flash_read(struct file *file, char *buf,
+                                                                        size_t len, loff_t *pos)
+{
+       ssize_t ret = 0;
+       int loop_i;
+       uint8_t local_flash_read_step = 0;
+       uint8_t local_flash_complete = 0;
+       uint8_t local_flash_progress = 0;
+       uint8_t local_flash_command = 0;
+       uint8_t local_flash_fail = 0;
+       char *temp_buf;
+       local_flash_complete = getFlashDumpComplete();
+       local_flash_progress = getFlashDumpProgress();
+       local_flash_command = getFlashCommand();
+       local_flash_fail = getFlashDumpFail();
+       I("flash_progress = %d \n", local_flash_progress);
+
+       if (!HX_PROC_SEND_FLAG) {
+               temp_buf = kzalloc(len, GFP_KERNEL);
+
+               if (local_flash_fail) {
+                       ret += snprintf(temp_buf + ret, len - ret, "FlashStart:Fail \n");
+                       ret += snprintf(temp_buf + ret, len - ret, "FlashEnd");
+                       ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+                       if (copy_to_user(buf, temp_buf, len))
+                               I("%s,here:%d\n", __func__, __LINE__);
+
+                       kfree(temp_buf);
+                       HX_PROC_SEND_FLAG = 1;
+                       return ret;
+               }
+
+               if (!local_flash_complete) {
+                       ret += snprintf(temp_buf + ret, len - ret, "FlashStart:Ongoing:0x%2.2x \n", flash_progress);
+                       ret += snprintf(temp_buf + ret, len - ret, "FlashEnd");
+                       ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+                       if (copy_to_user(buf, temp_buf, len))
+                               I("%s,here:%d\n", __func__, __LINE__);
+
+                       kfree(temp_buf);
+                       HX_PROC_SEND_FLAG = 1;
+                       return ret;
+               }
+
+               if (local_flash_command == 1 && local_flash_complete) {
+                       ret += snprintf(temp_buf + ret, len - ret, "FlashStart:Complete \n");
+                       ret += snprintf(temp_buf + ret, len - ret, "FlashEnd");
+                       ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+                       if (copy_to_user(buf, temp_buf, len))
+                               I("%s,here:%d\n", __func__, __LINE__);
+
+                       kfree(temp_buf);
+                       HX_PROC_SEND_FLAG = 1;
+                       return ret;
+               }
+
+               if (local_flash_command == 3 && local_flash_complete) {
+                       ret += snprintf(temp_buf + ret, len - ret, "FlashStart: \n");
+
+                       for (loop_i = 0; loop_i < 128; loop_i++) {
+                               ret += snprintf(temp_buf + ret, len - ret, "x%2.2x", flash_buffer[loop_i]);
+
+                               if ((loop_i % 16) == 15) {
+                                       ret += snprintf(temp_buf + ret, len - ret, "\n");
+                               }
+                       }
+
+                       ret += snprintf(temp_buf + ret, len - ret, "FlashEnd");
+                       ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+                       if (copy_to_user(buf, temp_buf, len))
+                               I("%s,here:%d\n", __func__, __LINE__);
+
+                       kfree(temp_buf);
+                       HX_PROC_SEND_FLAG = 1;
+                       return ret;
+               }
+
+               /* flash command == 0 , report the data */
+               local_flash_read_step = getFlashReadStep();
+               ret += snprintf(temp_buf + ret, len - ret, "FlashStart:%2.2x \n", local_flash_read_step);
+
+               for (loop_i = 0; loop_i < 1024; loop_i++) {
+                       ret += snprintf(temp_buf + ret, len - ret, "x%2.2X", flash_buffer[local_flash_read_step * 1024 + loop_i]);
+
+                       if ((loop_i % 16) == 15) {
+                               ret += snprintf(temp_buf + ret, len - ret, "\n");
+                       }
+               }
+
+               ret += snprintf(temp_buf + ret, len - ret, "FlashEnd");
+               ret += snprintf(temp_buf + ret, len - ret, "\n");
+
+               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 ssize_t himax_proc_flash_write(struct file *file, const char *buff,
+                                                                         size_t len, loff_t *pos)
+{
+       char buf_tmp[6];
+       unsigned long result = 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;
+       }
+
+       memset(buf_tmp, 0x0, sizeof(buf_tmp));
+       I("%s: buf = %s\n", __func__, buf);
+
+       if (getSysOperation() == 1) {
+               E("%s: PROC is busy , return!\n", __func__);
+               return len;
+       }
+
+       if (buf[0] == '0') {
+               setFlashCommand(0);
+
+               if (buf[1] == ':' && buf[2] == 'x') {
+                       memcpy(buf_tmp, buf + 3, 2);
+                       I("%s: read_Step = %s\n", __func__, buf_tmp);
+
+                       if (!kstrtoul(buf_tmp, 16, &result)) {
+                               I("%s: read_Step = %lu \n", __func__, result);
+                               setFlashReadStep(result);
+                       }
+               }
+       } else if (buf[0] == '1') { /*   1_32,1_60,1_64,1_24,1_28 for flash size 32k,60k,64k,124k,128k */
+               setSysOperation(1);
+               setFlashCommand(1);
+               setFlashDumpProgress(0);
+               setFlashDumpComplete(0);
+               setFlashDumpFail(0);
+
+               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;
+                       }
+               }
+               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 */
+               setSysOperation(1);
+               setFlashCommand(2);
+               setFlashDumpProgress(0);
+               setFlashDumpComplete(0);
+               setFlashDumpFail(0);
+
+               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;
+                       }
+               }
+               queue_work(private_ts->flash_wq, &private_ts->flash_work);
+       }
+
+       return len;
+}
+
+static struct file_operations himax_proc_flash_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_proc_flash_read,
+       .write = himax_proc_flash_write,
+};
+
+void himax_ts_flash_func(void)
+{
+       uint8_t local_flash_command = 0;
+       himax_int_enable(0);
+       setFlashDumpGoing(true);
+       /* sector = getFlashDumpSector(); */
+       /* page = getFlashDumpPage(); */
+       local_flash_command = getFlashCommand();
+       msleep(100);
+       I("%s: local_flash_command = %d enter.\n", __func__, local_flash_command);
+
+       if ((local_flash_command == 1 || local_flash_command == 2) || (local_flash_command == 0x0F)) {
+               g_core_fp.fp_flash_dump_func(local_flash_command, Flash_Size, flash_buffer);
+       }
+
+       I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n");
+
+#if 0
+       if (local_flash_command == 2) {
+               struct file *fn;
+               struct filename *vts_name;
+               vts_name = getname_kernel(FLASH_DUMP_FILE);
+               fn = 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);
+               }
+       }
+#endif
+
+       himax_int_enable(1);
+       setFlashDumpGoing(false);
+       setFlashDumpComplete(1);
+       setSysOperation(0);
+       return;
+       /*       Flash_Dump_i2c_transfer_error:
+
+               himax_int_enable(1);
+               setFlashDumpGoing(false);
+               setFlashDumpComplete(0);
+               setFlashDumpFail(1);
+               setSysOperation(0);
+               return;
+       */
+}
+
+
+
+static ssize_t himax_sense_on_off_write(struct file *file, const char *buff,
+                                                                               size_t len, loff_t *pos)
+{
+       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') {
+               g_core_fp.fp_sense_off();
+               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;
+}
+
+static struct file_operations himax_proc_sense_on_off_ops = {
+       .owner = THIS_MODULE,
+       .write = himax_sense_on_off_write,
+};
+
+#ifdef HX_ESD_RECOVERY
+static ssize_t himax_esd_cnt_read(struct file *file, char *buf,
+                                                                 size_t len, loff_t *pos)
+{
+       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);
+               ret += snprintf(temp_buf + 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);
+
+               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 ssize_t himax_esd_cnt_write(struct file *file, const char *buff,
+                                                                  size_t len, loff_t *pos)
+{
+       int i = 0;
+       char buf[12] = {0};
+
+       if (len >= 12) {
+               I("%s: no command exceeds 80 chars.\n", __func__);
+               return -EFAULT;
+       }
+
+       if (copy_from_user(buf, buff, len)) {
+               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;
+}
+
+static struct file_operations himax_proc_esd_cnt_ops = {
+       .owner = THIS_MODULE,
+       .read = himax_esd_cnt_read,
+       .write = himax_esd_cnt_write,
+};
+#endif
+
+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();
+}
+
+static void himax_ts_diag_work_func(struct work_struct *work)
+{
+       himax_ts_diag_func();
+}
+
+int himax_touch_proc_init(void)
+{
+       himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE, (S_IWUSR | S_IRUGO),
+                                                                 himax_touch_proc_dir, &himax_proc_debug_level_ops);
+       if (himax_proc_debug_level_file == NULL) {
+               E(" %s: proc debug_level file create failed!\n", __func__);
+               goto fail_1;
+       }
+
+       himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, (S_IRUGO),
+                                                                                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_2;
+       }
+
+       himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE, (S_IRUGO),
+                                                                          himax_touch_proc_dir, &himax_proc_attn_ops);
+       if (himax_proc_attn_file == NULL) {
+               E(" %s: proc attn file create failed!\n", __func__);
+               goto fail_3;
+       }
+
+       himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE, (S_IWUSR | S_IRUGO),
+                                                                                himax_touch_proc_dir, &himax_proc_int_en_ops);
+       if (himax_proc_int_en_file == NULL) {
+               E(" %s: proc int en file create failed!\n", __func__);
+               goto fail_4;
+       }
+
+       himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE, (S_IWUSR | S_IRUGO),
+                                                                                himax_touch_proc_dir, &himax_proc_layout_ops);
+       if (himax_proc_layout_file == NULL) {
+               E(" %s: proc layout file create failed!\n", __func__);
+               goto fail_5;
+       }
+
+       himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE, (S_IWUSR),
+                                                                               himax_touch_proc_dir, &himax_proc_reset_ops);
+       if (himax_proc_reset_file == NULL) {
+               E(" %s: proc reset file create failed!\n", __func__);
+               goto fail_6;
+       }
+
+       himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE, (S_IWUSR | S_IRUGO),
+                                                                          himax_touch_proc_dir, &himax_proc_diag_ops);
+       if (himax_proc_diag_file == NULL) {
+               E(" %s: proc diag file create failed!\n", __func__);
+               goto fail_7;
+       }
+
+       himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE, (S_IWUSR | S_IRUGO),
+                                                                  himax_touch_proc_dir, &himax_proc_diag_arrange_ops);
+       if (himax_proc_diag_arrange_file == NULL) {
+               E(" %s: proc diag file create failed!\n", __func__);
+               goto fail_7_1;
+       }
+
+       himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE, (S_IWUSR | S_IRUGO),
+                                                                                  himax_touch_proc_dir, &himax_proc_register_ops);
+       if (himax_proc_register_file == NULL) {
+               E(" %s: proc register file create failed!\n", __func__);
+               goto fail_8;
+       }
+
+       himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE, (S_IWUSR | S_IRUGO),
+                                                                               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_9;
+       }
+
+       himax_proc_fw_debug_file = proc_create(HIMAX_PROC_FW_DEBUG_FILE, (S_IWUSR | S_IRUGO),
+                                                                                  himax_touch_proc_dir, &himax_proc_fw_debug_ops);
+       if (himax_proc_fw_debug_file == NULL) {
+               E(" %s: proc fw debug file create failed!\n", __func__);
+               goto fail_9_1;
+       }
+
+       himax_proc_dd_debug_file = proc_create(HIMAX_PROC_DD_DEBUG_FILE, (S_IWUSR | S_IRUGO),
+                                                                                  himax_touch_proc_dir, &himax_proc_dd_debug_ops);
+       if (himax_proc_dd_debug_file == NULL) {
+               E(" %s: proc DD debug file create failed!\n", __func__);
+               goto fail_9_2;
+       }
+
+       himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE, (S_IWUSR | S_IRUGO),
+                                                                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_10;
+       }
+
+       himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE, (S_IWUSR | S_IRUGO | S_IWUGO),
+                                                                  himax_touch_proc_dir, &himax_proc_sense_on_off_ops);
+       if (himax_proc_SENSE_ON_OFF_file == NULL) {
+               E(" %s: proc SENSE_ON_OFF file create failed!\n", __func__);
+               goto fail_16;
+       }
+
+#ifdef HX_ESD_RECOVERY
+       himax_proc_ESD_cnt_file = proc_create(HIMAX_PROC_ESD_CNT_FILE, (S_IWUSR | S_IRUGO | S_IWUGO),
+                                                                                 himax_touch_proc_dir, &himax_proc_esd_cnt_ops);
+
+       if (himax_proc_ESD_cnt_file == NULL) {
+               E(" %s: proc ESD cnt file create failed!\n", __func__);
+               goto fail_17;
+       }
+
+#endif
+       himax_proc_CRC_test_file = proc_create(HIMAX_PROC_CRC_TEST_FILE, (S_IWUSR | S_IRUGO | S_IWUGO),
+                                                                                  himax_touch_proc_dir, &himax_proc_CRC_test_ops);
+
+       if (himax_proc_CRC_test_file == NULL) {
+               E(" %s: proc CRC test file create failed!\n", __func__);
+               goto fail_18;
+       }
+
+       return 0 ;
+fail_18:
+#ifdef HX_ESD_RECOVERY
+       remove_proc_entry(HIMAX_PROC_ESD_CNT_FILE, himax_touch_proc_dir);
+fail_17:
+#endif
+       remove_proc_entry(HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir);
+fail_16: remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir);
+fail_10: remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir);
+fail_9:        remove_proc_entry(HIMAX_PROC_FW_DEBUG_FILE, himax_touch_proc_dir);
+fail_9_1: remove_proc_entry(HIMAX_PROC_DD_DEBUG_FILE, himax_touch_proc_dir);
+fail_9_2: remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir);
+fail_8:        remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir);
+fail_7:        remove_proc_entry(HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir);
+fail_7_1: remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir);
+fail_6:        remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir);
+fail_5: remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir);
+fail_4: remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir);
+fail_3: remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir);
+fail_2: remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir);
+fail_1:
+       return -ENOMEM;
+}
+
+void himax_touch_proc_deinit(void)
+{
+       remove_proc_entry(HIMAX_PROC_CRC_TEST_FILE, himax_touch_proc_dir);
+#ifdef HX_ESD_RECOVERY
+       remove_proc_entry(HIMAX_PROC_ESD_CNT_FILE, himax_touch_proc_dir);
+#endif
+       remove_proc_entry(HIMAX_PROC_SENSE_ON_OFF_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_FW_DEBUG_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_DD_DEBUG_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir);
+       remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_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;
+       }
+
+       debug_data = kzalloc(sizeof(*debug_data), 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);
+       setSysOperation(0);
+       setFlashBuffer();
+
+       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);
+
+       setXChannel(ic_data->HX_RX_NUM); /*X channel*/
+       setYChannel(ic_data->HX_TX_NUM); /*Y channel*/
+       setMutualBuffer();
+       setMutualNewBuffer();
+       setMutualOldBuffer();
+
+       if (getMutualBuffer() == NULL) {
+               E("%s: mutual buffer allocate fail failed\n", __func__);
+               return MEM_ALLOC_FAIL;
+       }
+#ifdef HX_TP_PROC_2T2R
+
+       if (Is_2T2R) {
+               setXChannel_2(ic_data->HX_RX_NUM_2); /*X channel*/
+               setYChannel_2(ic_data->HX_TX_NUM_2); /*Y channel*/
+               setMutualBuffer_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:
+
+       destroy_workqueue(ts->flash_wq);
+err_create_flash_dump_wq_failed:
+
+err_alloc_debug_data_fail:
+
+       return err;
+}
+
+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);
+       destroy_workqueue(ts->himax_diag_wq);
+       destroy_workqueue(ts->flash_wq);
+
+       kfree(debug_data);
+
+       return 0;
+}
+
diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.h b/drivers/input/touchscreen/hxchipset/himax_debug.h
new file mode 100755 (executable)
index 0000000..90d634e
--- /dev/null
@@ -0,0 +1,154 @@
+/*  Himax Android Driver Sample Code for debug nodes
+
+    Copyright (C) 2018 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_DEBUG_LEVEL_FILE    "debug_level"
+#define HIMAX_PROC_VENDOR_FILE         "vendor"
+#define HIMAX_PROC_ATTN_FILE           "attn"
+#define HIMAX_PROC_INT_EN_FILE         "int_en"
+#define HIMAX_PROC_LAYOUT_FILE         "layout"
+#define HIMAX_PROC_CRC_TEST_FILE               "CRC_test"
+
+static struct proc_dir_entry *himax_proc_debug_level_file;
+static struct proc_dir_entry *himax_proc_vendor_file;
+static struct proc_dir_entry *himax_proc_attn_file;
+static struct proc_dir_entry *himax_proc_int_en_file;
+static struct proc_dir_entry *himax_proc_layout_file;
+static struct proc_dir_entry *himax_proc_CRC_test_file;
+
+int himax_touch_proc_init(void);
+void himax_touch_proc_deinit(void);
+extern int himax_int_en_set(void);
+
+#define HIMAX_PROC_REGISTER_FILE       "register"
+struct proc_dir_entry *himax_proc_register_file = NULL;
+uint8_t byte_length = 0;
+uint8_t register_command[4];
+uint8_t cfg_flag = 0;
+
+#define HIMAX_PROC_DIAG_FILE   "diag"
+struct proc_dir_entry *himax_proc_diag_file = NULL;
+#define HIMAX_PROC_DIAG_ARR_FILE       "diag_arr"
+struct proc_dir_entry *himax_proc_diag_arrange_file = NULL;
+struct file *diag_sram_fn;
+uint8_t write_counter = 0;
+uint8_t write_max_count = 30;
+#define IIR_DUMP_FILE "/sdcard/HX_IIR_Dump.txt"
+#define DC_DUMP_FILE "/sdcard/HX_DC_Dump.txt"
+#define BANK_DUMP_FILE "/sdcard/HX_BANK_Dump.txt"
+#ifdef HX_TP_PROC_2T2R
+       static uint8_t x_channel_2;
+       static uint8_t y_channel_2;
+       static uint32_t *diag_mutual_2;
+       int32_t *getMutualBuffer_2(void);
+       uint8_t         getXChannel_2(void);
+       uint8_t         getYChannel_2(void);
+       void    setMutualBuffer_2(void);
+       void    setXChannel_2(uint8_t x);
+       void    setYChannel_2(uint8_t y);
+#endif
+uint8_t x_channel              = 0;
+uint8_t y_channel              = 0;
+int32_t *diag_mutual = NULL;
+int32_t *diag_mutual_new = NULL;
+int32_t *diag_mutual_old = NULL;
+uint8_t diag_max_cnt = 0;
+uint8_t hx_state_info[2] = {0};
+uint8_t diag_coor[128];
+int32_t diag_self[100] = {0};
+int32_t diag_self_new[100] = {0};
+int32_t diag_self_old[100] = {0};
+int32_t *getMutualBuffer(void);
+int32_t *getMutualNewBuffer(void);
+int32_t *getMutualOldBuffer(void);
+int32_t *getSelfBuffer(void);
+int32_t *getSelfNewBuffer(void);
+int32_t *getSelfOldBuffer(void);
+uint8_t        getXChannel(void);
+uint8_t        getYChannel(void);
+void   setMutualBuffer(void);
+void   setMutualNewBuffer(void);
+void   setMutualOldBuffer(void);
+void   setXChannel(uint8_t x);
+void   setYChannel(uint8_t y);
+
+#define HIMAX_PROC_DEBUG_FILE  "debug"
+struct proc_dir_entry *himax_proc_debug_file = NULL;
+#define HIMAX_PROC_FW_DEBUG_FILE       "FW_debug"
+struct proc_dir_entry *himax_proc_fw_debug_file = NULL;
+#define HIMAX_PROC_DD_DEBUG_FILE       "DD_debug"
+struct proc_dir_entry *himax_proc_dd_debug_file = NULL;
+bool   fw_update_complete = false;
+int handshaking_result = 0;
+unsigned char debug_level_cmd = 0;
+uint8_t cmd_set[8];
+uint8_t mutual_set_flag = 0;
+
+#define HIMAX_PROC_FLASH_DUMP_FILE     "flash_dump"
+struct proc_dir_entry *himax_proc_flash_dump_file = NULL;
+static int Flash_Size = 131072;
+static uint8_t *flash_buffer;
+static uint8_t flash_command;
+static uint8_t flash_read_step;
+static uint8_t flash_progress;
+static uint8_t flash_dump_complete;
+static uint8_t flash_dump_fail;
+static uint8_t sys_operation;
+static bool    flash_dump_going;
+static uint8_t getFlashDumpComplete(void);
+static uint8_t getFlashDumpFail(void);
+static uint8_t getFlashDumpProgress(void);
+static uint8_t getFlashReadStep(void);
+uint8_t getFlashCommand(void);
+uint8_t getSysOperation(void);
+static void setFlashCommand(uint8_t command);
+static void setFlashReadStep(uint8_t step);
+void setFlashBuffer(void);
+void setFlashDumpComplete(uint8_t complete);
+void setFlashDumpFail(uint8_t fail);
+void setFlashDumpProgress(uint8_t progress);
+void setSysOperation(uint8_t operation);
+void setFlashDumpGoing(bool going);
+bool getFlashDumpGoing(void);
+
+
+uint32_t **raw_data_array;
+uint8_t X_NUM = 0, Y_NUM = 0;
+uint8_t sel_type = 0x0D;
+
+#define HIMAX_PROC_RESET_FILE          "reset"
+struct proc_dir_entry *himax_proc_reset_file           = NULL;
+
+#define HIMAX_PROC_SENSE_ON_OFF_FILE "SenseOnOff"
+struct proc_dir_entry *himax_proc_SENSE_ON_OFF_file = NULL;
+
+#ifdef HX_ESD_RECOVERY
+       #define HIMAX_PROC_ESD_CNT_FILE "ESD_cnt"
+       struct proc_dir_entry *himax_proc_ESD_cnt_file = NULL;
+#endif
+
+#endif
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.c b/drivers/input/touchscreen/hxchipset/himax_ic.c
new file mode 100755 (executable)
index 0000000..e2934c2
--- /dev/null
@@ -0,0 +1,2381 @@
+/* Himax Android Driver Sample Code for HMX83100 chipset
+*
+* Copyright (C) 2015 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.h"
+
+const struct firmware *i_TP_CRC_FW_128K;
+const struct firmware *i_TP_CRC_FW_64K;
+const struct firmware *i_TP_CRC_FW_124K;
+const struct firmware *i_TP_CRC_FW_60K;
+
+unsigned long FW_VER_MAJ_FLASH_ADDR;
+unsigned long FW_VER_MAJ_FLASH_LENG;
+unsigned long FW_VER_MIN_FLASH_ADDR;
+unsigned long FW_VER_MIN_FLASH_LENG;
+unsigned long CFG_VER_MAJ_FLASH_ADDR;
+unsigned long CFG_VER_MAJ_FLASH_LENG;
+unsigned long CFG_VER_MIN_FLASH_ADDR;
+unsigned long CFG_VER_MIN_FLASH_LENG;
+
+unsigned char IC_TYPE;
+unsigned char IC_CHECKSUM;
+
+ /*0:Running, 1:Stop, 2:I2C Fail*/
+int himax_hand_shaking(struct i2c_client *client)
+{
+       int ret, result;
+       uint8_t hw_reset_check[1];
+       uint8_t hw_reset_check_2[1];
+       uint8_t buf0[2];
+       uint8_t IC_STATUS_CHECK = 0xAA;
+
+       memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
+       memset(hw_reset_check_2, 0x00, sizeof(hw_reset_check_2));
+
+       buf0[0] = 0xF2;
+       if (IC_STATUS_CHECK == 0xAA) {
+               buf0[1] = 0xAA;
+               IC_STATUS_CHECK = 0x55;
+       } else {
+               buf0[1] = 0x55;
+               IC_STATUS_CHECK = 0xAA;
+       }
+
+       ret = i2c_himax_master_write(client,
+       buf0, 2, HIMAX_I2C_RETRY_TIMES);
+       if (ret < 0) {
+               E("[Himax]:write 0xF2 failed line: %d\n", __LINE__);
+               goto work_func_send_i2c_msg_fail;
+       }
+       msleep(50);
+
+       buf0[0] = 0xF2;
+       buf0[1] = 0x00;
+       ret = i2c_himax_master_write(client,
+       buf0, 2, HIMAX_I2C_RETRY_TIMES);
+       if (ret < 0) {
+               E("[Himax]:write 0x92 failed line: %d\n", __LINE__);
+               goto work_func_send_i2c_msg_fail;
+       }
+       usleep_range(1999, 2000);
+
+       ret = i2c_himax_read(client, 0xD1,
+       hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES);
+       if (ret < 0) {
+               E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n", __LINE__);
+               goto work_func_send_i2c_msg_fail;
+       }
+
+       if (IC_STATUS_CHECK != hw_reset_check[0]) {
+               usleep_range(1999, 2000);
+               ret = i2c_himax_read(client, 0xD1,
+               hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES);
+               if (ret < 0) {
+                       E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n",
+                       __LINE__);
+                       goto work_func_send_i2c_msg_fail;
+               }
+
+               if (hw_reset_check[0] == hw_reset_check_2[0])
+                       result = 1;
+               else
+                       result = 0;
+
+       } else {
+               result = 0;
+       }
+
+       return result;
+
+work_func_send_i2c_msg_fail:
+       return 2;
+}
+
+void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+
+       if (diag_command != 0)
+               diag_command = diag_command + 5;
+
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
+       tmp_addr[1] = 0x01; tmp_addr[0] = 0x80;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = diag_command;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+}
+
+void himax_flash_dump_func(struct i2c_client *client,
+uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
+{
+       /*struct himax_ts_data *ts =
+       container_of(work, struct himax_ts_data, flash_work);*/
+       /*uint8_t sector = 0;*/
+       /*uint8_t page = 0;*/
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+       uint8_t out_buffer[20];
+       uint8_t in_buffer[260];
+       int page_prog_start = 0;
+       int i = 0;
+
+       himax_sense_off(client);
+       himax_burst_enable(client, 0);
+       /*=============Dump Flash Start=============*/
+       /*=====================================*/
+       /* SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780*/
+       /*=====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+       tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       for (page_prog_start = 0 ; page_prog_start < Flash_Size;
+               page_prog_start = page_prog_start + 256) {
+               /*=====================================
+               SPI Transfer Control
+               Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
+               Set read start address  : 0x8000_0028 ==> 0x0000_0000
+               Set command                        : 0x8000_0024 ==> 0x0000_003B
+               =====================================*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+               tmp_data[3] = 0x69; tmp_data[2] = 0x40;
+               tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+               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;
+               }
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               /*=====================================
+               AHB_I2C Burst Read
+               Set SPI data register : 0x8000_002C ==> 0x00
+               =====================================*/
+               out_buffer[0] = 0x2C;
+               out_buffer[1] = 0x00;
+               out_buffer[2] = 0x00;
+               out_buffer[3] = 0x80;
+               i2c_himax_write(client, 0x00, out_buffer, 4, 3);
+
+               /*=====================================
+               Read access : 0x0C ==> 0x00
+               =====================================*/
+               out_buffer[0] = 0x00;
+               i2c_himax_write(client, 0x0C, out_buffer, 1, 3);
+
+               /*=====================================
+               Read 128 bytes two times
+               =====================================*/
+               i2c_himax_read(client, 0x08, in_buffer, 128, 3);
+               for (i = 0 ; i < 128 ; i++)
+                       flash_buffer[i + page_prog_start]
+                       = in_buffer[i];
+
+               i2c_himax_read(client, 0x08 , in_buffer, 128, 3);
+               for (i = 0 ; i < 128 ; i++)
+                       flash_buffer[(i + 128) + page_prog_start]
+                       = in_buffer[i];
+
+               I("%s:Verify Progress: %x\n", __func__, page_prog_start);
+       }
+
+/*=============Dump Flash End=============*/
+               /*//msleep(100);
+               for( i=0 ; i<8 ;i++)
+               {
+                       for(j=0 ; j<64 ; j++)
+                       {
+                               setFlashDumpProgress(i*32 + j);
+                       }
+               }
+               */
+       himax_sense_on(client, 0x01);
+
+       return;
+
+}
+
+int himax_chip_self_test(struct i2c_client *client)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[128];
+       int pf_value = 0x00;
+       uint8_t test_result_id = 0;
+       int j;
+
+       memset(tmp_addr, 0x00, sizeof(tmp_addr));
+       memset(tmp_data, 0x00, sizeof(tmp_data));
+
+       himax_interface_on(client);
+       himax_sense_off(client);
+
+       /*Set criteria*/
+       himax_burst_enable(client, 1);
+
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+       tmp_addr[1] = 0x80; tmp_addr[0] = 0x94;
+       tmp_data[3] = 0x14; tmp_data[2] = 0xC8;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       tmp_data[7] = 0x13; tmp_data[6] = 0x60;
+       tmp_data[5] = 0x0A; tmp_data[4] = 0x99;
+
+       himax_flash_write_burst_length(client, tmp_addr, tmp_data, 8);
+
+       /*start selftest*/
+       /* 0x9008_805C ==> 0x0000_0001*/
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+       tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       himax_sense_on(client, 1);
+
+       msleep(2000);
+
+       himax_sense_off(client);
+       msleep(20);
+
+       /*=====================================
+       Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF
+       =====================================*/
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+       tmp_addr[1] = 0x80; tmp_addr[0] = 0x78;
+       himax_register_read(client, tmp_addr, 1, tmp_data);
+
+       test_result_id = tmp_data[0];
+
+       I("%s: check test result, test_result_id=%x, test_result=%x\n",
+       __func__ , test_result_id, tmp_data[0]);
+
+       if (test_result_id == 0xF) {
+               I("[Himax]: self-test pass\n");
+               pf_value = 0x1;
+       } else {
+               E("[Himax]: self-test fail\n");
+               pf_value = 0x0;
+       }
+       himax_burst_enable(client, 1);
+
+       for (j = 0 ; j < 10 ; j++) {
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+               tmp_addr[3] = 0x90; tmp_addr[2] = 0x06;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C;
+               himax_register_read(client, tmp_addr, 1, tmp_data);
+               I("[Himax]: 9006000C = %d\n", tmp_data[0]);
+               if (tmp_data[0] != 0) {
+                       tmp_data[3] = 0x90; tmp_data[2] = 0x06;
+                       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+                       if (i2c_himax_write(client, 0x00,
+                       tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+                               E("%s: i2c access fail!\n", __func__);
+                       }
+                       tmp_data[0] = 0x00;
+                       if (i2c_himax_write(client, 0x0C,
+                       tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+                               E("%s: i2c access fail!\n", __func__);
+                       }
+                               i2c_himax_read(client, 0x08,
+                               tmp_data, 124, HIMAX_I2C_RETRY_TIMES);
+               } else {
+                       break;
+               }
+       }
+
+       himax_sense_on(client, 1);
+       msleep(120);
+
+       return pf_value;
+}
+
+void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+
+       himax_burst_enable(client, 0);
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+       tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+}
+void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data)
+{
+       uint8_t tmp_addr[4];
+
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+       tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
+       himax_register_read(client, tmp_addr, 1, tmp_data);
+}
+
+void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+       tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+}
+
+void himax_get_SMWP_enable(struct i2c_client *client,
+uint8_t *tmp_data)
+{
+       uint8_t tmp_addr[4];
+
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+       tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
+       himax_register_read(client, tmp_addr, 1, tmp_data);
+}
+
+int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte)
+{
+       uint8_t tmp_data[4];
+       int err = -1;
+
+       tmp_data[0] = 0x31;
+
+       if (i2c_himax_write(client, 0x13,
+       tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return err;
+       }
+
+       tmp_data[0] = (0x10 | auto_add_4_byte);
+       if (i2c_himax_write(client, 0x0D,
+       tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return err;
+       }
+       return 0;
+
+}
+
+void himax_register_read(struct i2c_client *client,
+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;
+       }
+       if (read_length > 1)
+               himax_burst_enable(client, 1);
+       else
+               himax_burst_enable(client, 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 (i2c_himax_write(client, 0x00,
+       tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+       tmp_data[0] = 0x00;
+       if (i2c_himax_write(client, 0x0C,
+       tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+       if (i2c_himax_read(client, 0x08,
+       read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+       if (read_length > 1)
+               himax_burst_enable(client, 0);
+}
+
+void himax_flash_read(struct i2c_client *client,
+uint8_t *reg_byte, uint8_t *read_data)
+{
+       uint8_t tmpbyte[2];
+
+       if (i2c_himax_write(client, 0x00,
+       &reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(client, 0x01,
+       &reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(client, 0x02,
+       &reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(client, 0x03,
+       &reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       tmpbyte[0] = 0x00;
+       if (i2c_himax_write(client, 0x0C,
+       &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_read(client, 0x08,
+       &read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_read(client, 0x09,
+       &read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_read(client, 0x0A,
+       &read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_read(client, 0x0B,
+       &read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_read(client, 0x18,
+       &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       } /* No bus request*/
+
+       if (i2c_himax_read(client, 0x0F,
+       &tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       } /* idle state*/
+
+}
+
+void himax_flash_write_burst(struct i2c_client *client,
+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 (i2c_himax_write(client, 0x00,
+               data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+}
+
+int himax_flash_write_burst_length(struct i2c_client *client,
+uint8_t *reg_byte, uint8_t *write_data, int length)
+{
+       uint8_t data_byte[256];
+       int i = 0, j = 0, err = -1;
+
+       for (i = 0 ; i < 4 ; i++)
+               data_byte[i] = reg_byte[i];
+
+       for (j = 4 ; j < length + 4 ; j++)
+               data_byte[j] = write_data[j - 4];
+
+       if (i2c_himax_write(client, 0x00,
+       data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return err;
+       }
+       return 0;
+}
+
+int himax_register_write(struct i2c_client *client,
+uint8_t *write_addr, int write_length, uint8_t *write_data)
+{
+       int i = 0, address = 0;
+       int ret = 0, err = -1;
+
+       address = (write_addr[3] << 24) +
+                               (write_addr[2] << 16) +
+                               (write_addr[1] << 8) +
+                               write_addr[0];
+
+       for (i = address ; i < address + write_length * 4;
+               i = i + 4) {
+               if (write_length > 1) {
+                       ret = himax_burst_enable(client, 1);
+                       if (ret)
+                               return err;
+               } else {
+                       ret = himax_burst_enable(client, 0);
+                       if (ret)
+                               return err;
+               }
+       ret = himax_flash_write_burst_length(client,
+               write_addr, write_data, write_length * 4);
+       if (ret < 0)
+               return err;
+       }
+
+       return 0;
+}
+
+void himax_sense_off(struct i2c_client *client)
+{
+       uint8_t wdt_off = 0x00;
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[5];
+
+       himax_burst_enable(client, 0);
+
+       while (wdt_off == 0x00) {
+               /* 0x9000_800C ==> 0x0000_AC53*/
+               tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0xAC; tmp_data[0] = 0x53;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               /*=====================================*/
+               /* Read Watch Dog disable password :
+               0x9000_800C ==> 0x0000_AC53 */
+               /*=====================================*/
+               tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
+               himax_register_read(client, tmp_addr, 1, tmp_data);
+
+               /*Check WDT*/
+               if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC
+               && tmp_data[2] == 0x00 && tmp_data[3] == 0x00)
+                       wdt_off = 0x01;
+               else
+                       wdt_off = 0x00;
+       }
+
+       /* VCOM         //0x9008_806C ==> 0x0000_0001*/
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+       tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       msleep(20);
+
+       /* 0x9000_0010 ==> 0x0000_00DA*/
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0xDA;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       /*=====================================
+       Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA
+       =====================================*/
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       himax_register_read(client, tmp_addr, 1, tmp_data);
+       I("%s: CPU clock off password data[0]=%x",
+       __func__, tmp_data[0]);
+       I(" data[1]=%x data[2]=%x data[3]=%x\n",
+       tmp_data[1], tmp_data[2], tmp_data[3]);
+
+}
+
+void himax_interface_on(struct i2c_client *client)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[5];
+
+    /*=====================================
+       Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000
+       =====================================*/
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+       himax_flash_read(client, tmp_addr, tmp_data); /*avoid RD/WR fail*/
+}
+
+bool wait_wip(struct i2c_client *client, int Timing)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+       uint8_t in_buffer[10];
+       /*uint8_t out_buffer[20];*/
+       int retry_cnt = 0;
+
+       /*=====================================
+       SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+       tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       in_buffer[0] = 0x01;
+
+       do {
+               /*=====================================
+               SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003
+               =====================================*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+               tmp_data[3] = 0x42; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x03;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               /*=====================================
+               SPI Command : 0x8000_0024 ==> 0x0000_0005
+               read 0x8000_002C for 0x01, means wait success
+               =====================================*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x05;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               in_buffer[0] = in_buffer[1] =
+               in_buffer[2] = in_buffer[3] = 0xFF;
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+               himax_register_read(client, tmp_addr, 1, in_buffer);
+
+               if ((in_buffer[0] & 0x01) == 0x00)
+                       return true;
+
+               retry_cnt++;
+
+               if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00
+               || in_buffer[2] != 0x00 || in_buffer[3] != 0x00){
+                       I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, ",
+                       __func__, retry_cnt, in_buffer[0]);
+                       I("buffer[1]=%d, buffer[2]=%d, buffer[3]=%d\n",
+                       in_buffer[1], in_buffer[2], in_buffer[3]);
+               }
+               if (retry_cnt > 100) {
+                       E("%s: Wait wip error!\n", __func__);
+                       return false;
+               }
+               msleep(Timing);
+       } while ((in_buffer[0] & 0x01) == 0x01);
+       return true;
+}
+
+void himax_sense_on(struct i2c_client *client, uint8_t FlashMode)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[128];
+
+       himax_interface_on(client);
+       himax_burst_enable(client, 0);
+       /*CPU reset*/
+       /* 0x9000_0014 ==> 0x0000_00CA*/
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0xCA;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       /*=====================================
+       Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA
+       =====================================*/
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+       himax_register_read(client, tmp_addr, 1, tmp_data);
+
+       I("%s: check pull low CPU reset signal  data[0]=%x data[1]=%x ",
+       __func__, tmp_data[0], tmp_data[1]);
+       I("data[2]=%x data[3]=%x\n",
+       tmp_data[2], tmp_data[3]);
+
+       /* 0x9000_0014 ==> 0x0000_0000*/
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       /*=====================================
+       Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000
+       =====================================*/
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+       himax_register_read(client, tmp_addr, 1, tmp_data);
+
+       I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x ",
+       __func__, tmp_data[0], tmp_data[1]);
+       I("data[2]=%x data[3]=%x\n",
+       tmp_data[2], tmp_data[3]);
+
+       /*=====================================
+       Reset TCON
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
+       tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+       usleep_range(9999, 10000);
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
+       tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       if (FlashMode == 0x00) { /*SRAM*/
+               /*=====================================
+                                       Re-map
+               =====================================*/
+               tmp_addr[3] = 0x90; 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] = 0xF1;
+               himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
+               I("%s:83100_Chip_Re-map ON\n", __func__);
+       } else {
+               /*=====================================
+                                       Re-map off
+               =====================================*/
+               tmp_addr[3] = 0x90; 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;
+               himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
+               I("%s:83100_Chip_Re-map OFF\n", __func__);
+       }
+       /*=====================================
+                               CPU clock on
+       =====================================*/
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
+
+}
+
+void himax_chip_erase(struct i2c_client *client)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+
+       himax_burst_enable(client, 0);
+
+       /*=====================================
+       SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+       tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       /*=====================================
+       Chip Erase
+       Write Enable :
+       1. 0x8000_0020 ==> 0x4700_0000
+       2. 0x8000_0024 ==> 0x0000_0006
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+       tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       /*=====================================
+       Chip Erase
+       Erase Command : 0x8000_0024 ==> 0x0000_00C7
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0xC7;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       msleep(2000);
+
+       if (!wait_wip(client, 100))
+               E("%s:83100_Chip_Erase Fail\n", __func__);
+
+}
+
+bool himax_block_erase(struct i2c_client *client)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+
+       himax_burst_enable(client, 0);
+
+       /*=====================================
+       SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+       tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       /*=====================================
+       Chip Erase
+       Write Enable :
+       1. 0x8000_0020 ==> 0x4700_0000
+       2. 0x8000_0024 ==> 0x0000_0006
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+       tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       /*=====================================
+       Block Erase
+       Erase Command :
+       0x8000_0028 ==> 0x0000_0000 //SPI addr
+       0x8000_0020 ==> 0x6700_0000 //control
+       0x8000_0024 ==> 0x0000_0052 //BE
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+       tmp_data[3] = 0x67; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x52;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       msleep(1000);
+
+       if (!wait_wip(client, 100)) {
+               E("%s:83100_Erase Fail\n", __func__);
+               return false;
+       } else {
+               return true;
+       }
+
+}
+
+bool himax_sector_erase(struct i2c_client *client, int start_addr)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+       int page_prog_start = 0;
+
+       himax_burst_enable(client, 0);
+
+       /*=====================================
+       SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+       tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+       for (page_prog_start = start_addr;
+       page_prog_start < start_addr + 0x0F000;
+       page_prog_start = page_prog_start + 0x1000) {
+               /*=====================================
+               Chip Erase
+               Write Enable :
+               1. 0x8000_0020 ==> 0x4700_0000
+               2. 0x8000_0024 ==> 0x0000_0006
+               =====================================*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+               tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               /*=====================================
+               Sector Erase
+               Erase Command :
+               0x8000_0028 ==> 0x0000_0000 //SPI addr
+               0x8000_0020 ==> 0x6700_0000 //control
+               0x8000_0024 ==> 0x0000_0020 //SE
+               =====================================*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+               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;
+               }
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+               tmp_data[3] = 0x67; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x20;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               msleep(200);
+
+               if (!wait_wip(client, 100)) {
+                       E("%s:83100_Erase Fail\n", __func__);
+                       return false;
+               }
+       }
+       return true;
+}
+
+void himax_sram_write(struct i2c_client *client, uint8_t *FW_content)
+{
+       int i = 0;
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[64];
+       int FW_length = 0x4000; /* 0x4000 = 16K bin file */
+
+       /*himax_sense_off(client);*/
+
+       for (i = 0; i < FW_length; i = i + 64) {
+               himax_burst_enable(client, 1);
+
+               if (i < 0x100) {
+                       tmp_addr[3] = 0x08;
+                       tmp_addr[2] = 0x00;
+                       tmp_addr[1] = 0x00;
+                       tmp_addr[0] = i;
+               } else if (i >= 0x100 && i < 0x10000) {
+                       tmp_addr[3] = 0x08;
+                       tmp_addr[2] = 0x00;
+                       tmp_addr[1] = (i >> 8);
+                       tmp_addr[0] = i;
+               }
+
+               memcpy(&tmp_data[0], &FW_content[i], 64);
+               himax_flash_write_burst_length(client, tmp_addr, tmp_data, 64);
+
+       }
+
+       if (!wait_wip(client, 100))
+               E("%s:83100_Sram_Write Fail\n", __func__);
+}
+
+bool himax_sram_verify(struct i2c_client *client,
+uint8_t *FW_File, int FW_Size)
+{
+       int i = 0;
+       uint8_t out_buffer[20];
+       uint8_t in_buffer[128];
+       uint8_t *get_fw_content;
+
+       get_fw_content = kzalloc(0x4000 * sizeof(uint8_t), GFP_KERNEL);
+
+       for (i = 0 ; i < 0x4000 ; i = i + 128) {
+               himax_burst_enable(client, 1);
+
+               /*=====================================
+                               AHB_I2C Burst Read
+               =====================================*/
+               if (i < 0x100) {
+                       out_buffer[3] = 0x08;
+                       out_buffer[2] = 0x00;
+                       out_buffer[1] = 0x00;
+                       out_buffer[0] = i;
+               } else if (i >= 0x100 && i < 0x10000) {
+                       out_buffer[3] = 0x08;
+                       out_buffer[2] = 0x00;
+                       out_buffer[1] = (i >> 8);
+                       out_buffer[0] = i;
+               }
+
+               if (i2c_himax_write(client, 0x00, out_buffer,
+               4, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return false;
+               }
+
+               out_buffer[0] = 0x00;
+               if (i2c_himax_write(client, 0x0C, out_buffer,
+               1, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return false;
+               }
+
+               if (i2c_himax_read(client, 0x08, in_buffer,
+               128, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return false;
+               }
+               memcpy(&get_fw_content[i], &in_buffer[0], 128);
+       }
+
+       for (i = 0 ; i < FW_Size ; i++) {
+               if (FW_File[i] != get_fw_content[i]) {
+                       E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n",
+                       __func__, i, get_fw_content[i], FW_File[i]);
+                       return false;
+               }
+       }
+
+       kfree(get_fw_content);
+
+       return true;
+}
+
+void himax_flash_programming(struct i2c_client *client,
+uint8_t *FW_content, int FW_Size)
+{
+       int page_prog_start = 0;
+       int program_length = 48;
+       int i = 0, j = 0, k = 0;
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+       /* // Read for flash data, 128K //4 bytes for 0x80002C padding */
+       uint8_t buring_data[256];
+
+       /*himax_interface_on(client);*/
+       himax_burst_enable(client, 0);
+
+       /*=====================================
+       SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+       tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+       for (page_prog_start = 0 ; page_prog_start < FW_Size;
+       page_prog_start = page_prog_start + 256) {
+               /*msleep(5);*/
+               /*=====================================
+               Write Enable :
+               1. 0x8000_0020 ==> 0x4700_0000
+               2. 0x8000_0024 ==> 0x0000_0006
+               =====================================*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+               tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               /*=====================================
+               SPI Transfer Control
+               Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000
+               Set read start address  : 0x8000_0028 ==> 0x0000_0000
+               =====================================*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+               tmp_data[3] = 0x61; tmp_data[2] = 0x0F;
+               tmp_data[1] = 0xF0; tmp_data[0] = 0x00;
+               /*data bytes should be 0x6100_0000 +
+               ((word_number)*4-1)*4096 = 0x6100_0000 +
+               0xFF000 = 0x610F_F000
+               Programmable size = 1 page = 256 bytes,
+               word_number = 256 byte / 4 = 64*/
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+               /* tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+               // 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;
+               }
+
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               /*=====================================
+               Send 16 bytes data : 0x8000_002C ==> 16 bytes data
+               =====================================*/
+               buring_data[0] = 0x2C;
+               buring_data[1] = 0x00;
+               buring_data[2] = 0x00;
+               buring_data[3] = 0x80;
+
+               for (i = /*0*/page_prog_start, j = 0;
+                       i < 16 + page_prog_start/**/;
+                       i++, j++) {     /* <------ bin file*/
+
+                       buring_data[j + 4] = FW_content[i];
+               }
+
+               if (i2c_himax_write(client, 0x00, buring_data,
+                       20, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return;
+               }
+               /*=====================================
+               Write command : 0x8000_0024 ==> 0x0000_0002
+               =====================================*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x02;
+               himax_flash_write_burst(client, tmp_addr, tmp_data);
+
+               /*=====================================
+               Send 240 bytes data : 0x8000_002C ==> 240 bytes data
+               =====================================*/
+
+               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++) {  /*<------ bin file*/
+                               buring_data[k+4] = FW_content[i];/*(byte)i;*/
+                       }
+
+                       if (i2c_himax_write(client, 0x00, buring_data,
+                               program_length + 4,
+                               HIMAX_I2C_RETRY_TIMES) < 0) {
+                               E("%s: i2c access fail!\n", __func__);
+                               return;
+                       }
+
+               }
+
+               if (!wait_wip(client, 1))
+                       E("%s:83100_Flash_Programming Fail\n", __func__);
+       }
+}
+
+bool himax_check_chip_version(struct i2c_client *client)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+       uint8_t ret_data = 0x00;
+       int i = 0;
+       int ret = 0;
+
+       himax_sense_off(client);
+
+       for (i = 0 ; i < 5 ; i++) {
+               /* 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001)
+               (Lock register R/W from driver) */
+               tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+               ret = himax_register_write(client, tmp_addr, 1, tmp_data);
+               if (ret)
+                       return false;
+
+               /* 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000)*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
+               tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+               ret = himax_register_write(client, tmp_addr, 1, tmp_data);
+               if (ret)
+                       return false;
+
+               /* 3. Read driver ID register RF4H 1 byte (0x8001_F401)
+               //        Driver register RF4H 1 byte value = 0x84H,
+               read back value will become 0x84848484 */
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
+               tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01;
+               himax_register_read(client, tmp_addr, 1, tmp_data);
+               ret_data = tmp_data[0];
+
+               I("%s:Read driver IC ID = %X\n", __func__, ret_data);
+               if (ret_data == 0x84) {
+                       IC_TYPE         = HX_83100_SERIES_PWON;
+                       /*himax_sense_on(client, 0x01);*/
+                       ret_data = true;
+                       break;
+
+               } else {
+                       ret_data = false;
+                       E("%s:Read driver ID register Fail:\n", __func__);
+               }
+       }
+       /* 4. After read finish, set DDREG_Req = 0
+       (0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver)*/
+       tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+       himax_register_write(client, tmp_addr, 1, tmp_data);
+       /*himax_sense_on(client, 0x01);*/
+       return ret_data;
+}
+
+/*#if 1*/
+int himax_check_CRC(struct i2c_client *client, int mode)
+{
+       bool burnFW_success = false;
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+       int tmp_value;
+       int CRC_value = 0;
+
+       memset(tmp_data, 0x00, sizeof(tmp_data));
+       if (i_TP_CRC_FW_60K == NULL) {
+               I("%s: i_TP_CRC_FW_60K = NULL\n", __func__);
+               return 0;
+       } else if (i_TP_CRC_FW_64K == NULL) {
+               I("%s: i_TP_CRC_FW_64K = NULL\n", __func__);
+               return 0;
+       } else if (i_TP_CRC_FW_124K == NULL) {
+               I("%s: i_TP_CRC_FW_124K = NULL\n", __func__);
+               return 0;
+       } else if (i_TP_CRC_FW_128K == NULL) {
+               I("%s: i_TP_CRC_FW_128K = NULL\n", __func__);
+               return 0;
+       }
+
+       if (1) {
+               if (mode == fw_image_60k) {
+                       himax_sram_write(client,
+                       (unsigned char *)i_TP_CRC_FW_60K->data);
+                       burnFW_success = himax_sram_verify(client,
+                       (unsigned char *)i_TP_CRC_FW_60K->data, 0x4000);
+               } else if (mode == fw_image_64k) {
+                       himax_sram_write(client,
+                       (unsigned char *)i_TP_CRC_FW_64K->data);
+                       burnFW_success = himax_sram_verify(client,
+                       (unsigned char *)i_TP_CRC_FW_64K->data, 0x4000);
+               } else if (mode == fw_image_124k) {
+                       himax_sram_write(client,
+                       (unsigned char *)i_TP_CRC_FW_124K->data);
+                       burnFW_success = himax_sram_verify(client,
+                       (unsigned char *)i_TP_CRC_FW_124K->data, 0x4000);
+               } else if (mode == fw_image_128k) {
+                       himax_sram_write(client,
+                       (unsigned char *)i_TP_CRC_FW_128K->data);
+                       burnFW_success = himax_sram_verify(client,
+                       (unsigned char *)i_TP_CRC_FW_128K->data, 0x4000);
+               }
+               if (burnFW_success) {
+                       I("%s: Start to do CRC FW mode=%d\n", __func__, mode);
+                       himax_sense_on(client, 0x00);   /* run CRC firmware*/
+
+                       while (true) {
+                               msleep(100);
+                               tmp_addr[3] = 0x90;
+                               tmp_addr[2] = 0x08;
+                               tmp_addr[1] = 0x80;
+                               tmp_addr[0] = 0x94;
+                               himax_register_read(client,
+                               tmp_addr, 1, tmp_data);
+
+                               I("%s: CRC from firmware is %x, %x, %x, %x\n",
+                               __func__, tmp_data[3], tmp_data[2],
+                               tmp_data[1], tmp_data[0]);
+/*
+                               if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF
+                               && tmp_data[1] == 0xFF && tmp_data[0] == 0xFF) {
+                               } else
+                                       break;
+                               */
+                               if (!(tmp_data[3] == 0xFF
+                               && tmp_data[2] == 0xFF
+                               && tmp_data[1] == 0xFF
+                               && tmp_data[0] == 0xFF)) {
+                                       break;
+                               }
+                       }
+
+                       CRC_value = tmp_data[3];
+
+                       tmp_value = tmp_data[2] << 8;
+                       CRC_value += tmp_value;
+
+                       tmp_value = tmp_data[1] << 16;
+                       CRC_value += tmp_value;
+
+                       tmp_value = tmp_data[0] << 24;
+                       CRC_value += tmp_value;
+
+                       I("%s: CRC Value is %x\n", __func__, CRC_value);
+
+                       /*Close Remapping*/
+                       /*=====================================
+                       Re-map close
+                       =====================================*/
+                       tmp_addr[3] = 0x90; 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;
+                       himax_flash_write_burst_length(client,
+                       tmp_addr, tmp_data, 4);
+                       return CRC_value;
+
+               } else {
+                       E("%s: SRAM write fail\n", __func__);
+                       return 0;
+               }
+       } else
+               I("%s: NO CRC Check File\n", __func__);
+
+       return 0;
+}
+
+bool Calculate_CRC_with_AP(unsigned char *FW_content,
+int CRC_from_FW, int mode)
+{
+       uint8_t tmp_data[4];
+       int i, j;
+       int fw_data;
+       int fw_data_2;
+       int CRC = 0xFFFFFFFF;
+       int PolyNomial = 0x82F63B78;
+       int length = 0;
+
+       if (mode == fw_image_128k)
+               length = 0x8000;
+       else if (mode == fw_image_124k)
+               length = 0x7C00;
+       else if (mode == fw_image_64k)
+               length = 0x4000;
+       else /*if (mode == fw_image_60k)*/
+               length = 0x3C00;
+
+       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);
+               }
+       }
+
+       I("%s: CRC calculate from bin file is %x\n", __func__, CRC);
+
+       tmp_data[0] = (uint8_t)(CRC >> 24);
+       tmp_data[1] = (uint8_t)(CRC >> 16);
+       tmp_data[2] = (uint8_t)(CRC >> 8);
+       tmp_data[3] = (uint8_t) CRC;
+
+       CRC = tmp_data[0];
+       CRC += tmp_data[1] << 8;
+       CRC += tmp_data[2] << 16;
+       CRC += tmp_data[3] << 24;
+
+       I("%s: CRC calculate from bin file REVERSE %x\n", __func__, CRC);
+       I("%s: CRC calculate from FWis %x\n", __func__, CRC_from_FW);
+       if (CRC_from_FW == CRC)
+               return true;
+       else
+               return false;
+}
+/*#endif*/
+
+int himax_load_CRC_bin_file(struct i2c_client *client)
+{
+       int err = 0;
+       char *CRC_60_firmware_name = "HX_CRC_60.bin";
+       char *CRC_64_firmware_name = "HX_CRC_64.bin";
+       char *CRC_124_firmware_name = "HX_CRC_124.bin";
+       char *CRC_128_firmware_name = "HX_CRC_128.bin";
+
+       I("%s,Entering\n", __func__);
+       if (i_TP_CRC_FW_60K == NULL)    {
+               I("load file name = %s\n", CRC_60_firmware_name);
+               err = request_firmware(&i_TP_CRC_FW_60K,
+               CRC_60_firmware_name, private_ts->dev);
+               if (err < 0) {
+                       E("%s,fail in line%d error code=%d\n",
+                       __func__, __LINE__, err);
+                       err = -1;
+                       goto request_60k_fw_fail;
+               }
+       } else
+               I("%s already load i_TP_CRC_FW_60K\n", __func__);
+
+       if (i_TP_CRC_FW_64K == NULL)    {
+               I("load file name = %s\n", CRC_64_firmware_name);
+               err = request_firmware(&i_TP_CRC_FW_64K,
+               CRC_64_firmware_name, private_ts->dev);
+               if (err < 0) {
+                       E("%s,fail in line%d error code=%d\n",
+                       __func__, __LINE__, err);
+                       err = -2;
+                       goto request_64k_fw_fail;
+               }
+       } else
+               I("%s already load i_TP_CRC_FW_64K\n", __func__);
+
+       if (i_TP_CRC_FW_124K == NULL) {
+               I("load file name = %s\n", CRC_124_firmware_name);
+               err = request_firmware(&i_TP_CRC_FW_124K,
+               CRC_124_firmware_name, private_ts->dev);
+               if (err < 0) {
+                       E("%s,fail in line%d error code=%d\n",
+                       __func__, __LINE__, err);
+                       err = -3;
+                       goto request_124k_fw_fail;
+               }
+       } else
+               I("%s already load i_TP_CRC_FW_124K\n", __func__);
+
+       if (i_TP_CRC_FW_128K == NULL) {
+               I("load file name = %s\n", CRC_128_firmware_name);
+               err = request_firmware(&i_TP_CRC_FW_128K,
+               CRC_128_firmware_name, private_ts->dev);
+               if (err < 0) {
+                       E("%s,fail in line%d error code=%d\n",
+                       __func__, __LINE__, err);
+                       err = -4;
+                       goto request_128k_fw_fail;
+               }
+       } else
+               I("%s already load  i_TP_CRC_FW_128K\n", __func__);
+
+       return err;
+
+request_128k_fw_fail:
+       release_firmware(i_TP_CRC_FW_124K);
+request_124k_fw_fail:
+       release_firmware(i_TP_CRC_FW_64K);
+request_64k_fw_fail:
+       release_firmware(i_TP_CRC_FW_60K);
+request_60k_fw_fail:
+       return err;
+}
+int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
+{
+       int CRC_from_FW = 0;
+       int burnFW_success = 0;
+
+       if (len != 0x10000) {/*64k*/
+               E("%s: The file size is not 64K bytes\n", __func__);
+               return false;
+       }
+       himax_sense_off(client);
+       msleep(500);
+       himax_interface_on(client);
+       if (!himax_sector_erase(client, 0x00000)) {
+               E("%s:Sector erase fail!Please restart the IC.\n", __func__);
+               return false;
+       }
+       himax_flash_programming(client, fw, 0x0F000);
+
+       /*burnFW_success = himax_83100_Verify(fw, len);
+       if(burnFW_success==false)
+               return burnFW_success;*/
+
+       CRC_from_FW = himax_check_CRC(client, fw_image_60k);
+       burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_60k);
+       /*himax_sense_on(client, 0x01);*/
+       return burnFW_success;
+}
+
+int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
+{
+       int CRC_from_FW = 0;
+       int burnFW_success = 0;
+
+       if (len != 0x10000) {   /*64k*/
+               E("%s: The file size is not 64K bytes\n", __func__);
+               return false;
+       }
+       himax_sense_off(client);
+       msleep(500);
+       himax_interface_on(client);
+       himax_chip_erase(client);
+       himax_flash_programming(client, fw, len);
+
+       /*burnFW_success = himax_83100_Verify(fw, len);
+       if(burnFW_success==false)
+               return burnFW_success;*/
+
+       CRC_from_FW = himax_check_CRC(client, fw_image_64k);
+       burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_64k);
+       /*himax_sense_on(client, 0x01);*/
+       return burnFW_success;
+}
+
+int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
+{
+       int CRC_from_FW = 0;
+       int burnFW_success = 0;
+
+       if (len != 0x20000) {   /*128k*/
+               E("%s: The file size is not 128K bytes\n", __func__);
+               return false;
+       }
+       himax_sense_off(client);
+       msleep(500);
+       himax_interface_on(client);
+       if (!himax_block_erase(client)) {
+               E("%s:Block erase fail!Please restart the IC.\n", __func__);
+               return false;
+       }
+       if (!himax_sector_erase(client, 0x10000)) {
+               E("%s:Sector erase fail!Please restart the IC.\n", __func__);
+               return false;
+       }
+       himax_flash_programming(client, fw, 0x1F000);
+
+       /*burnFW_success = himax_83100_Verify(fw, len);
+       if(burnFW_success==false)
+               return burnFW_success;*/
+
+       CRC_from_FW = himax_check_CRC(client, fw_image_124k);
+       burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_124k);
+       /*himax_sense_on(client, 0x01);*/
+       return burnFW_success;
+}
+
+int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
+{
+       int CRC_from_FW = 0;
+       int burnFW_success = 0;
+
+       if (len != 0x20000) {   /*128k*/
+               E("%s: The file size is not 128K bytes\n", __func__);
+               return false;
+       }
+       himax_sense_off(client);
+       msleep(500);
+       himax_interface_on(client);
+       himax_chip_erase(client);
+
+       himax_flash_programming(client, fw, len);
+
+       /*burnFW_success = himax_83100_Verify(fw, len);
+       if(burnFW_success==false)
+               return burnFW_success;*/
+
+       CRC_from_FW = himax_check_CRC(client, fw_image_128k);
+       burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_128k);
+       /*himax_sense_on(client, 0x01); */
+       return burnFW_success;
+}
+
+void himax_touch_information(struct i2c_client *client)
+{
+       uint8_t cmd[4];
+       char data[12] = {0};
+
+       I("%s:IC_TYPE =%d\n", __func__, IC_TYPE);
+
+       if (IC_TYPE == HX_83100_SERIES_PWON) {
+               cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xF8;
+               himax_register_read(client, cmd, 1, data);
+
+               ic_data->HX_RX_NUM                              = data[1];
+               ic_data->HX_TX_NUM                              = data[2];
+               ic_data->HX_MAX_PT                              = data[3];
+
+               cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xFC;
+               himax_register_read(client, cmd, 1, data);
+
+               if ((data[1] & 0x04) == 0x04)
+                       ic_data->HX_XY_REVERSE = true;
+               else
+                       ic_data->HX_XY_REVERSE = false;
+
+               ic_data->HX_Y_RES = data[3]*256;
+               cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x01; cmd[0] = 0x00;
+               himax_register_read(client, cmd, 1, data);
+               ic_data->HX_Y_RES = ic_data->HX_Y_RES + data[0];
+               ic_data->HX_X_RES = data[1]*256 + data[2];
+               cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x8C;
+               himax_register_read(client, cmd, 1, data);
+               if ((data[0] & 0x01) == 1)
+                       ic_data->HX_INT_IS_EDGE = true;
+               else
+                       ic_data->HX_INT_IS_EDGE = false;
+
+               if (ic_data->HX_RX_NUM > 40)
+                       ic_data->HX_RX_NUM = 29;
+               if (ic_data->HX_TX_NUM > 20)
+                       ic_data->HX_TX_NUM = 16;
+               if (ic_data->HX_MAX_PT > 10)
+                       ic_data->HX_MAX_PT = 10;
+               if (ic_data->HX_Y_RES > 2000)
+                       ic_data->HX_Y_RES = 1280;
+               if (ic_data->HX_X_RES > 2000)
+                       ic_data->HX_X_RES = 720;
+#ifdef HX_EN_MUT_BUTTON
+               cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xE8;
+               himax_register_read(client, cmd, 1, data);
+               ic_data->HX_BT_NUM                              = data[3];
+#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);
+       } else {
+               ic_data->HX_RX_NUM                              = 0;
+               ic_data->HX_TX_NUM                              = 0;
+               ic_data->HX_BT_NUM                              = 0;
+               ic_data->HX_X_RES                               = 0;
+               ic_data->HX_Y_RES                               = 0;
+               ic_data->HX_MAX_PT                              = 0;
+               ic_data->HX_XY_REVERSE          = false;
+               ic_data->HX_INT_IS_EDGE         = false;
+       }
+}
+
+void himax_read_FW_ver(struct i2c_client *client)
+{
+       uint8_t cmd[4];
+       uint8_t data[64];
+
+       /*=====================================
+       Read FW version : 0x0000_E303
+       =====================================*/
+       cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x00;
+       himax_register_read(client, cmd, 1, data);
+
+       ic_data->vendor_config_ver = data[3] << 8;
+
+       cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x04;
+       himax_register_read(client, cmd, 1, data);
+
+       ic_data->vendor_config_ver = data[0] | ic_data->vendor_config_ver;
+       I("CFG_VER : %X\n", ic_data->vendor_config_ver);
+
+       cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x28;
+       himax_register_read(client, cmd, 1, data);
+
+       ic_data->vendor_fw_ver = data[0]<<8 | data[1];
+       I("FW_VER : %X\n", ic_data->vendor_fw_ver);
+
+}
+
+bool himax_ic_package_check(struct i2c_client *client)
+{
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
+       uint8_t cmd[3];
+       uint8_t data[3];
+
+       memset(cmd, 0x00, sizeof(cmd));
+       memset(data, 0x00, sizeof(data));
+
+       if (i2c_himax_read(client, 0xD1, cmd, 3, HIMAX_I2C_RETRY_TIMES) < 0)
+               return false;
+
+       if (i2c_himax_read(client, 0x31, data, 3, HIMAX_I2C_RETRY_TIMES) < 0)
+               return false;
+
+       if ((data[0] == 0x85 && data[1] == 0x29)) {
+               IC_TYPE = HX_85XX_F_SERIES_PWON;
+               IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+               /*Himax: Set FW and CFG Flash Address*/
+               FW_VER_MAJ_FLASH_ADDR = 64901;  /*0xFD85*/
+               FW_VER_MAJ_FLASH_LENG = 1;
+               FW_VER_MIN_FLASH_ADDR = 64902;  /*0xFD86*/
+               FW_VER_MIN_FLASH_LENG = 1;
+               CFG_VER_MAJ_FLASH_ADDR = 64928;   /*0xFDA0*/
+               CFG_VER_MAJ_FLASH_LENG = 12;
+               CFG_VER_MIN_FLASH_ADDR = 64940;   /*0xFDAC*/
+               CFG_VER_MIN_FLASH_LENG = 12;
+               I("Himax IC package 852x F\n");
+       }
+       if ((data[0] == 0x85 && data[1] == 0x30)
+               || (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29)) {
+               IC_TYPE = HX_85XX_E_SERIES_PWON;
+               IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+               /*Himax: Set FW and CFG Flash Address*/
+               FW_VER_MAJ_FLASH_ADDR = 133;    /*0x0085*/
+               FW_VER_MAJ_FLASH_LENG = 1;
+               FW_VER_MIN_FLASH_ADDR = 134;  /*0x0086*/
+               FW_VER_MIN_FLASH_LENG = 1;
+               CFG_VER_MAJ_FLASH_ADDR = 160;   /*0x00A0*/
+               CFG_VER_MAJ_FLASH_LENG = 12;
+               CFG_VER_MIN_FLASH_ADDR = 172;   /*0x00AC*/
+               CFG_VER_MIN_FLASH_LENG = 12;
+               I("Himax IC package 852x E\n");
+       } else if ((data[0] == 0x85 && data[1] == 0x31)) {
+               IC_TYPE = HX_85XX_ES_SERIES_PWON;
+               IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+               /*Himax: Set FW and CFG Flash Address*/
+               FW_VER_MAJ_FLASH_ADDR = 133;  /*0x0085*/
+               FW_VER_MAJ_FLASH_LENG = 1;
+               FW_VER_MIN_FLASH_ADDR = 134;  /*0x0086*/
+               FW_VER_MIN_FLASH_LENG = 1;
+               CFG_VER_MAJ_FLASH_ADDR = 160;   /*0x00A0*/
+               CFG_VER_MAJ_FLASH_LENG = 12;
+               CFG_VER_MIN_FLASH_ADDR = 172;   /*0x00AC*/
+               CFG_VER_MIN_FLASH_LENG = 12;
+               I("Himax IC package 852x ES\n");
+       } else if ((data[0] == 0x85 && data[1] == 0x28)
+               || (cmd[0] == 0x04 && cmd[1] == 0x85
+               && (cmd[2] == 0x26 || cmd[2] == 0x27
+               || cmd[2] == 0x28))) {
+               IC_TYPE = HX_85XX_D_SERIES_PWON;
+               IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+               /*Himax: Set FW and CFG Flash Address*/
+               FW_VER_MAJ_FLASH_ADDR = 133;    /*0x0085*/
+               FW_VER_MAJ_FLASH_LENG = 1;
+               FW_VER_MIN_FLASH_ADDR = 134;   /*0x0086*/
+               FW_VER_MIN_FLASH_LENG = 1;
+               CFG_VER_MAJ_FLASH_ADDR = 160;  /*0x00A0*/
+               CFG_VER_MAJ_FLASH_LENG = 12;
+               CFG_VER_MIN_FLASH_ADDR = 172;  /* 0x00AC*/
+               CFG_VER_MIN_FLASH_LENG = 12;
+               I("Himax IC package 852x D\n");
+       } else if ((data[0] == 0x85 && data[1] == 0x23) ||
+               (cmd[0] == 0x03 && cmd[1] == 0x85 &&
+               (cmd[2] == 0x26 || cmd[2] == 0x27 ||
+               cmd[2] == 0x28 || cmd[2] == 0x29))) {
+               IC_TYPE = HX_85XX_C_SERIES_PWON;
+               IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
+               /*Himax: Set FW and CFG Flash Address*/
+               FW_VER_MAJ_FLASH_ADDR = 133;                   /*0x0085*/
+               FW_VER_MAJ_FLASH_LENG = 1;
+               FW_VER_MIN_FLASH_ADDR = 134;                   /*0x0086*/
+               FW_VER_MIN_FLASH_LENG = 1;
+               CFG_VER_MAJ_FLASH_ADDR = 135;                   /*0x0087*/
+               CFG_VER_MAJ_FLASH_LENG = 12;
+               CFG_VER_MIN_FLASH_ADDR = 147;                   /*0x0093*/
+               CFG_VER_MIN_FLASH_LENG = 12;
+               I("Himax IC package 852x C\n");
+       } else if ((data[0] == 0x85 && data[1] == 0x26) ||
+               (cmd[0] == 0x02 && cmd[1] == 0x85 &&
+               (cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) {
+               IC_TYPE                = HX_85XX_B_SERIES_PWON;
+               IC_CHECKSUM            = HX_TP_BIN_CHECKSUM_SW;
+               /*Himax: Set FW and CFG Flash Address*/
+               FW_VER_MAJ_FLASH_ADDR = 133;                   /*0x0085*/
+               FW_VER_MAJ_FLASH_LENG = 1;
+               FW_VER_MIN_FLASH_ADDR = 728;                   /*0x02D8*/
+               FW_VER_MIN_FLASH_LENG = 1;
+               CFG_VER_MAJ_FLASH_ADDR = 692;                   /*0x02B4*/
+               CFG_VER_MAJ_FLASH_LENG = 3;
+               CFG_VER_MIN_FLASH_ADDR = 704;                   /*0x02C0*/
+               CFG_VER_MIN_FLASH_LENG = 3;
+               I("Himax IC package 852x B\n");
+       } else if ((data[0] == 0x85 && data[1] == 0x20) || (cmd[0] == 0x01 &&
+               cmd[1] == 0x85 && cmd[2] == 0x19)) {
+               IC_TYPE     = HX_85XX_A_SERIES_PWON;
+               IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
+               I("Himax IC package 852x A\n");
+       } else {
+               E("Himax IC package incorrect!!\n");
+       }
+#else
+               IC_TYPE = HX_83100_SERIES_PWON;
+               IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+               /*Himax: Set FW and CFG Flash Address*/
+               FW_VER_MAJ_FLASH_ADDR = 57384;   /*0xE028*/
+               FW_VER_MAJ_FLASH_LENG = 1;
+               FW_VER_MIN_FLASH_ADDR = 57385;   /*0xE029*/
+               FW_VER_MIN_FLASH_LENG = 1;
+               CFG_VER_MAJ_FLASH_ADDR = 58115;  /*0xE303*/
+               CFG_VER_MAJ_FLASH_LENG = 1;
+               CFG_VER_MIN_FLASH_ADDR = 58116;  /*0xE304*/
+               CFG_VER_MIN_FLASH_LENG = 1;
+               I("Himax IC package 83100_in\n");
+
+#endif
+       return true;
+}
+
+void himax_read_event_stack(struct i2c_client *client,
+uint8_t *buf, uint8_t length)
+{
+       uint8_t cmd[4];
+
+       cmd[3] = 0x90; cmd[2] = 0x06;
+       cmd[1] = 0x00; cmd[0] = 0x00;
+       if (i2c_himax_write(client, 0x00,
+               cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+       }
+
+       cmd[0] = 0x00;
+       if (i2c_himax_write(client, 0x0C,
+               cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+       }
+
+       i2c_himax_read(client, 0x08,
+       buf, length, HIMAX_I2C_RETRY_TIMES);
+}
+
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
+static void himax_83100_Flash_Write(uint8_t *reg_byte, uint8_t *write_data)
+{
+       uint8_t tmpbyte[2];
+
+       if (i2c_himax_write(private_ts->client, 0x00,
+               &reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client, 0x01,
+               &reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client, 0x02,
+               &reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client,
+               0x03, &reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client,
+               0x04, &write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client,
+               0x05, &write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client,
+               0x06, &write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client,
+               0x07, &write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (isBusrtOn == false) {
+               tmpbyte[0] = 0x01;
+               if (i2c_himax_write(private_ts->client,
+                       0x0C, &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return;
+               }
+       }
+}
+#endif
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
+static void himax_83100_Flash_Burst_Write
+(uint8_t *reg_byte, uint8_t *write_data)
+{
+    /*uint8_t tmpbyte[2];*/
+       int i = 0;
+
+       if (i2c_himax_write(private_ts->client, 0x00,
+               &reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client, 0x01,
+               &reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client, 0x02,
+               &reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+       if (i2c_himax_write(private_ts->client, 0x03,
+               &reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+       }
+
+    /*Write 256 bytes with continue burst mode*/
+       for (i = 0 ; i < 256 ; i = i + 4) {
+               if (i2c_himax_write(private_ts->client,
+                       0x04, &write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return;
+               }
+
+               if (i2c_himax_write(private_ts->client, 0x05,
+                       &write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return;
+               }
+
+               if (i2c_himax_write(private_ts->client, 0x06,
+                       &write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return;
+               }
+
+               if (i2c_himax_write(private_ts->client, 0x07,
+                       &write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return;
+               }
+       }
+
+    /*if (isBusrtOn == false)
+    {
+       tmpbyte[0] = 0x01;
+               if (i2c_himax_write(private_ts->client,
+               0x0C, &tmpbyte[0], 1, 3) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return;
+    }*/
+
+}
+#endif
+
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
+static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+       uint8_t out_buffer[20];
+       uint8_t in_buffer[260];
+
+       int fail_addr = 0, fail_cnt = 0;
+       int page_prog_start = 0;
+       int i = 0;
+
+       himax_interface_on(private_ts->client);
+       himax_burst_enable(private_ts->client, 0);
+
+       /*=====================================
+       SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+       =====================================*/
+       tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+       tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+       himax_83100_Flash_Write(tmp_addr, tmp_data);
+
+       for (page_prog_start = 0; page_prog_start < FW_Size;
+       page_prog_start = page_prog_start + 256) {
+               /*=====================================
+               SPI Transfer Control
+               Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
+               Set read start address  : 0x8000_0028 ==> 0x0000_0000
+               Set command                        : 0x8000_0024 ==> 0x0000_003B
+               =====================================*/
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+               tmp_data[3] = 0x69; tmp_data[2] = 0x40;
+               tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
+               himax_83100_Flash_Write(tmp_addr, tmp_data);
+
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+               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;
+               }
+               himax_83100_Flash_Write(tmp_addr, tmp_data);
+
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+               tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
+               himax_83100_Flash_Write(tmp_addr, tmp_data);
+
+               /*==================================
+               AHB_I2C Burst Read
+               Set SPI data register : 0x8000_002C ==> 0x00
+               ==================================*/
+               out_buffer[0] = 0x2C;
+               out_buffer[1] = 0x00;
+               out_buffer[2] = 0x00;
+               out_buffer[3] = 0x80;
+               i2c_himax_write(private_ts->client, 0x00,
+               out_buffer, 4, HIMAX_I2C_RETRY_TIMES);
+
+               /*==================================
+               Read access : 0x0C ==> 0x00
+               ==================================*/
+               out_buffer[0] = 0x00;
+               i2c_himax_write(private_ts->client, 0x0C,
+               out_buffer, 1, HIMAX_I2C_RETRY_TIMES);
+
+               /*==================================
+               Read 128 bytes two times
+               ==================================*/
+               i2c_himax_read(private_ts->client, 0x08,
+               in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
+               for (i = 0; i < 128; i++)
+                       flash_buffer[i + page_prog_start] = in_buffer[i];
+
+               i2c_himax_read(private_ts->client, 0x08,
+               in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
+               for (i = 0; i < 128; i++)
+                       flash_buffer[(i + 128)
+                       + page_prog_start] = in_buffer[i];
+
+               /*tmp_addr[3] = 0x80;
+               tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+               himax_register_read(tmp_addr, 32, out in_buffer);
+               for (int i = 0; i < 128; i++)
+                         flash_buffer[i + page_prog_start] = in_buffer[i];
+               tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+               himax_register_read(tmp_addr, 32, out in_buffer);
+               for (int i = 0; i < 128; i++)
+                         flash_buffer[i + page_prog_start] = in_buffer[i];
+               */
+               I("%s:Verify Progress: %x\n", __func__, page_prog_start);
+       }
+
+       fail_cnt = 0;
+       for (i = 0; i < FW_Size; i++) {
+               if (FW_File[i] != flash_buffer[i]) {
+                       if (fail_cnt == 0)
+                               fail_addr = i;
+
+                       fail_cnt++;
+                       /*E("%s Fail Block:%x\n", __func__, i);
+                       return false;*/
+               }
+       }
+       if (fail_cnt > 0) {
+               E("%s:Start Fail Block:%x and fail block count=%x\n",
+               __func__, fail_addr, fail_cnt);
+               return false;
+       }
+
+       I("%s:Byte read verify pass.\n", __func__);
+       return true;
+
+}
+#endif
+
+void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data)
+{
+       int i;
+       int cnt = 0;
+       unsigned char tmp_addr[4];
+       unsigned char tmp_data[4];
+       uint8_t max_i2c_size = 32;
+       int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2;
+       int total_size_4bytes = total_size / 4;
+       int total_read_times = 0;
+       unsigned long address = 0x08000468;
+
+       tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
+       tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+       tmp_data[1] = 0x5A; tmp_data[0] = 0xA5;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+       do {
+               cnt++;
+               himax_register_read(client, tmp_addr, 1, tmp_data);
+               usleep_range(9999, 10000);
+       } while ((tmp_data[1] != 0xA5 || tmp_data[0] != 0x5A) && cnt < 100);
+       tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x04; tmp_addr[0] = 0x68;
+       if (total_size_4bytes % max_i2c_size == 0)
+               total_read_times = total_size_4bytes / max_i2c_size;
+       else
+               total_read_times = total_size_4bytes / max_i2c_size + 1;
+
+       for (i = 0 ; i < (total_read_times) ; i++) {
+               if (total_size_4bytes >= max_i2c_size) {
+                       himax_register_read(client, tmp_addr,
+                       max_i2c_size,
+                       &info_data[i*max_i2c_size*4]);
+                       total_size_4bytes = total_size_4bytes - max_i2c_size;
+               } else {
+                       himax_register_read(client, tmp_addr,
+                       total_size_4bytes % max_i2c_size,
+                       &info_data[i*max_i2c_size*4]);
+               }
+               address += max_i2c_size * 4;
+               tmp_addr[1] = (uint8_t)((address>>8) & 0x00FF);
+               tmp_addr[0] = (uint8_t)((address) & 0x00FF);
+       }
+       tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
+       tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
+       tmp_data[3] = 0x11; tmp_data[2] = 0x22;
+       tmp_data[1] = 0x33; tmp_data[0] = 0x44;
+       himax_flash_write_burst(client, tmp_addr, tmp_data);
+}
+/*ts_work*/
+int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max)
+{
+       int RawDataLen;
+
+       if (raw_cnt_rmd != 0x00)
+               RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1;
+       else
+               RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1;
+
+       return RawDataLen;
+}
+
+bool read_event_stack(struct i2c_client *client, uint8_t *buf, int length)
+{
+       uint8_t cmd[4];
+
+       if (length > 56)
+               length = 124;
+       /*=====================
+       AHB I2C Burst Read
+       =====================*/
+       cmd[0] = 0x31;
+       if (i2c_himax_write(client, 0x13, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               goto err_workqueue_out;
+       }
+
+       cmd[0] = 0x10;
+       if (i2c_himax_write(client, 0x0D, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               goto err_workqueue_out;
+       }
+       /*=====================
+       Read event stack
+       =====================*/
+       cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00;
+       if (i2c_himax_write(client, 0x00, cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               goto err_workqueue_out;
+       }
+
+       cmd[0] = 0x00;
+       if (i2c_himax_write(client, 0x0C, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               goto err_workqueue_out;
+       }
+       i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES);
+       return 1;
+
+err_workqueue_out:
+       return 0;
+}
+
+bool post_read_event_stack(struct i2c_client *client)
+{
+       return 1;
+}
+bool diag_check_sum(uint8_t hx_touch_info_size,
+uint8_t *buf) /*return checksum value*/
+{
+       uint16_t check_sum_cal = 0;
+       int i;
+
+       /*Check 124th byte CRC*/
+       for (i = hx_touch_info_size, check_sum_cal = 0 ; i < 124 ; i = i + 2)
+               check_sum_cal += (buf[i + 1] * 256 + buf[i]);
+
+       if (check_sum_cal % 0x10000 != 0) {
+               I("%s:diag chksum fail!check_sum_cal=%X,hx_touchinfo_sz=%d,\n",
+               __func__, check_sum_cal, hx_touch_info_size);
+               return 0;
+       }
+       return 1;
+}
+
+void diag_parse_raw_data(int hx_touch_info_size,
+int RawDataLen, int mul_num, int self_num, uint8_t *buf,
+uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data)
+{
+       int RawDataLen_word;
+       int index = 0;
+       int temp1, temp2, i;
+
+       if (buf[hx_touch_info_size] == 0x3A &&
+               buf[hx_touch_info_size + 1] == 0xA3 &&
+               buf[hx_touch_info_size + 2] > 0 &&
+               buf[hx_touch_info_size + 3] == diag_cmd + 5) {
+               RawDataLen_word = RawDataLen / 2;
+               index = (buf[hx_touch_info_size + 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);*/
+               for (i = 0; i < RawDataLen_word; i++) {
+                       temp1 = index + i;
+
+                       if (temp1 < mul_num) { /*mutual*/
+                                       /*4: RawData Header, 1:HSB */
+                                       mutual_data[index + i]
+                                       = buf[i*2 + hx_touch_info_size + 4 + 1]
+                                       * 256
+                                       + buf[i * 2 + hx_touch_info_size + 4];
+                       } else { /*self*/
+                               temp1 = i + index;
+                               temp2 = self_num + mul_num;
+
+                               if (temp1 >= temp2)
+                                       break;
+
+                               /*4: RawData Header*/
+                               self_data[i + index - mul_num]
+                               = buf[i * 2 + hx_touch_info_size + 4];
+                               self_data[i + index - mul_num + 1]
+                               = buf[i * 2 + hx_touch_info_size + 4 + 1];
+                       }
+               }
+       } else {
+               I("[HIMAX TP MSG]%s: header format is wrong!\n", __func__);
+                       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);
+       }
+}
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.h b/drivers/input/touchscreen/hxchipset/himax_ic.h
new file mode 100755 (executable)
index 0000000..ce7d0d4
--- /dev/null
@@ -0,0 +1,148 @@
+/* Himax Android Driver Sample Code for HMX83100 chipset
+*
+* Copyright (C) 2015 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 <linux/slab.h>
+
+#define HX_85XX_A_SERIES_PWON          1
+#define HX_85XX_B_SERIES_PWON          2
+#define HX_85XX_C_SERIES_PWON          3
+#define HX_85XX_D_SERIES_PWON          4
+#define HX_85XX_E_SERIES_PWON          5
+#define HX_85XX_ES_SERIES_PWON         6
+#define HX_85XX_F_SERIES_PWON          7
+#define HX_83100_SERIES_PWON           8
+
+#define HX_TP_BIN_CHECKSUM_SW          1
+#define HX_TP_BIN_CHECKSUM_HW          2
+#define HX_TP_BIN_CHECKSUM_CRC 3
+
+enum fw_image_type {
+       fw_image_60k    = 0x01,
+       fw_image_64k,
+       fw_image_124k,
+       fw_image_128k,
+};
+
+int himax_hand_shaking(struct i2c_client *client);
+void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable);
+void himax_get_SMWP_enable(struct i2c_client *client, uint8_t *tmp_data);
+void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable);
+void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data);
+void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command);
+
+void himax_flash_dump_func(struct i2c_client *client,
+uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer);
+
+int himax_chip_self_test(struct i2c_client *client);
+
+/*himax_83100_BURST_INC0_EN*/
+int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte);
+
+/*RegisterRead83100*/
+void himax_register_read(struct i2c_client *client,
+       uint8_t *read_addr, int read_length, uint8_t *read_data);
+
+/*himax_83100_Flash_Read*/
+void himax_flash_read(struct i2c_client *client,
+       uint8_t *reg_byte, uint8_t *read_data);
+
+/*himax_83100_Flash_Write_Burst*/
+void himax_flash_write_burst(struct i2c_client *client,
+       uint8_t *reg_byte, uint8_t *write_data);
+
+/*himax_83100_Flash_Write_Burst_length*/
+int himax_flash_write_burst_length(struct i2c_client *client,
+       uint8_t *reg_byte, uint8_t *write_data, int length);
+
+/*RegisterWrite83100*/
+int himax_register_write(struct i2c_client *client,
+       uint8_t *write_addr, int write_length, uint8_t *write_data);
+
+/*himax_83100_SenseOff*/
+void himax_sense_off(struct i2c_client *client);
+/*himax_83100_Interface_on*/
+void himax_interface_on(struct i2c_client *client);
+bool wait_wip(struct i2c_client *client, int Timing);
+
+/*himax_83100_SenseOn*/
+void himax_sense_on(struct i2c_client *client,
+       uint8_t FlashMode);
+
+/*himax_83100_Chip_Erase*/
+void himax_chip_erase(struct i2c_client *client);
+/*himax_83100_Block_Erase*/
+bool himax_block_erase(struct i2c_client *client);
+
+/*himax_83100_Sector_Erase*/
+bool himax_sector_erase(struct i2c_client *client, int start_addr);
+
+/*himax_83100_Sram_Write*/
+void himax_sram_write(struct i2c_client *client, uint8_t *FW_content);
+
+/*himax_83100_Sram_Verify*/
+bool himax_sram_verify(struct i2c_client *client,
+       uint8_t *FW_File, int FW_Size);
+
+/*himax_83100_Flash_Programming*/
+void himax_flash_programming(struct i2c_client *client,
+       uint8_t *FW_content, int FW_Size);
+
+/*himax_83100_CheckChipVersion*/
+bool himax_check_chip_version(struct i2c_client *client);
+
+/*himax_83100_Check_CRC*/
+int himax_check_CRC(struct i2c_client *client, int mode);
+
+bool Calculate_CRC_with_AP(unsigned char *FW_content,
+       int CRC_from_FW, int mode);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client,
+       unsigned char *fw, int len, bool change_iref);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client,
+       unsigned char *fw, int len, bool change_iref);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client,
+       unsigned char *fw, int len, bool change_iref);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client,
+       unsigned char *fw, int len, bool change_iref);
+
+void himax_touch_information(struct i2c_client *client);
+void himax_read_FW_ver(struct i2c_client *client);
+bool himax_ic_package_check(struct i2c_client *client);
+
+void himax_read_event_stack(struct i2c_client *client,
+       uint8_t *buf, uint8_t length);
+
+int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max);
+bool read_event_stack(struct i2c_client *client, uint8_t *buf_ts, int length);
+bool post_read_event_stack(struct i2c_client *client);
+
+/*return checksum value*/
+bool diag_check_sum(uint8_t hx_touch_info_size, uint8_t *buf_ts);
+
+void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen,
+       int mul_num, int self_num, uint8_t *buf_ts,
+       uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data);
+
+void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data);
+extern struct himax_ts_data *private_ts;
+extern struct himax_ic_data *ic_data;
+
+int himax_load_CRC_bin_file(struct i2c_client *client);
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_HX83102.c b/drivers/input/touchscreen/hxchipset/himax_ic_HX83102.c
new file mode 100755 (executable)
index 0000000..d873564
--- /dev/null
@@ -0,0 +1,568 @@
+/*  Himax Android Driver Sample Code for HX83102 chipset
+
+    Copyright (C) 2018 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"
+extern struct himax_ts_data *private_ts;
+extern struct himax_core_fp g_core_fp;
+extern struct fw_operation *pfw_op;
+#if defined(HX_ZERO_FLASH)
+extern struct zf_operation *pzf_op;
+extern struct ic_operation *pic_op;
+extern int G_POWERONOF;
+#endif
+
+
+extern unsigned char IC_CHECKSUM;
+extern bool DSRAM_Flag;
+
+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;
+
+#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
+
+#ifdef HX_TP_PROC_2T2R
+       extern bool Is_2T2R;
+#endif
+
+#ifdef HX_USB_DETECT_GLOBAL
+       extern void himax_cable_detect_func(bool force_renew);
+#endif
+
+#ifdef HX_RST_PIN_FUNC
+       extern void himax_rst_gpio_set(int pinnum, uint8_t value);
+#endif
+
+static void hx83102_chip_init(void)
+{
+       private_ts->chip_cell_type = CHIP_IS_IN_CELL;
+       I("%s:IC cell type = %d\n", __func__, private_ts->chip_cell_type);
+       IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+       /*Himax: Set FW and CFG Flash Address*/
+       FW_VER_MAJ_FLASH_ADDR   = 49157;  /*0x00C005*/
+       FW_VER_MAJ_FLASH_LENG   = 1;
+       FW_VER_MIN_FLASH_ADDR   = 49158;  /*0x00C006*/
+       FW_VER_MIN_FLASH_LENG   = 1;
+       CFG_VER_MAJ_FLASH_ADDR  = 49408;  /*0x00C100*/
+       CFG_VER_MAJ_FLASH_LENG  = 1;
+       CFG_VER_MIN_FLASH_ADDR  = 49409;  /*0x00C101*/
+       CFG_VER_MIN_FLASH_LENG  = 1;
+       CID_VER_MAJ_FLASH_ADDR  = 49154;  /*0x00C002*/
+       CID_VER_MAJ_FLASH_LENG  = 1;
+       CID_VER_MIN_FLASH_ADDR  = 49155;  /*0x00C003*/
+       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 (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 (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 (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 (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 (himax_bus_write(0x0C, tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return I2C_FAIL;
+       }
+
+       if (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;
+}
+
+static bool hx83102_sense_off(void)
+{
+       uint8_t cnt = 0;
+       uint8_t tmp_addr[FOUR_BYTE_DATA_SZ];
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+
+       do {
+               /*===========================================
+                I2C_password[7:0] set Enter safe mode : 0x31 ==> 0x27
+               ===========================================*/
+               tmp_data[0] = 0x27;
+               if (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 (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, FOUR_BYTE_ADDR_SZ, 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);
+                       msleep(1);
+                       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);
+                       msleep(1);
+                       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;
+               } else {
+                       msleep(10);
+#ifdef HX_RST_PIN_FUNC
+                       himax_rst_gpio_set(private_ts->rst_gpio, 0);
+                       msleep(20);
+                       himax_rst_gpio_set(private_ts->rst_gpio, 1);
+                       msleep(50);
+#endif
+               }
+       } while (cnt++ < 15);
+
+       return false;
+}
+
+#if defined(HX_ZERO_FLASH)
+static void himax_hx83102d_reload_to_active(void)
+{
+       uint8_t addr[FOUR_BYTE_DATA_SZ] = {0};
+       uint8_t data[FOUR_BYTE_DATA_SZ] = {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;
+               g_core_fp.fp_flash_write_burst(addr, data);
+
+               g_core_fp.fp_register_read(addr, FOUR_BYTE_DATA_SZ, 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[FOUR_BYTE_DATA_SZ];
+       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, false);
+       msleep(20);
+
+       if (!FlashMode) {
+#ifdef HX_RST_PIN_FUNC
+               g_core_fp.fp_ic_reset(false, false);
+#else
+               g_core_fp.fp_system_reset();
+#endif
+               himax_hx83102d_reload_to_active();
+       } else {
+               himax_hx83102d_reload_to_active();
+               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, false);
+
+                       g_core_fp.fp_register_read(pfw_op->addr_flag_reset_event, FOUR_BYTE_DATA_SZ, 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
+                       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 (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, false);
+               }
+       }
+}
+
+static void hx83102d_firmware_update_0f(const struct firmware *fw_entry)
+{
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ] = {0};
+       int retry = 0;
+       int crc = -1;
+
+       I("%s, Entering \n", __func__);
+
+       g_core_fp.fp_register_write(pzf_op->addr_system_reset,  4,  pzf_op->data_system_reset,  false);
+
+       g_core_fp.fp_sense_off();
+
+       /* first 40K - isram */
+       do {
+               g_core_fp.fp_write_sram_0f (fw_entry, pzf_op->data_sram_start_addr, 0, HX_40K_SZ);
+               crc = g_core_fp.fp_check_CRC (pzf_op->data_sram_start_addr,  HX_40K_SZ);
+               if (crc == 0) {
+                       I("%s, HW CRC OK in %d time \n", __func__, retry);
+                       break;
+               } else {
+                       E("%s, HW CRC FAIL in %d time !\n", __func__, retry);
+               }
+               retry++;
+       } while (crc != 0 && retry < 3);
+
+       if (crc != 0) {
+               E("Last time CRC Fail!\n");
+               return;
+       }
+
+       /* clean
+       if (G_POWERONOF == 1) {
+               g_core_fp.fp_clean_sram_0f(pzf_op->data_sram_clean, HX_32K_SZ, 0);
+       } */
+
+       /*last 16k*/
+       /*config info*/
+       if (G_POWERONOF == 1) {
+               g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_cfg_info, 0xC000, 132);
+       } else {
+               g_core_fp.fp_clean_sram_0f(pzf_op->data_cfg_info, 132, 2);
+       }
+       /*FW config*/
+       if (G_POWERONOF == 1) {
+               g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_fw_cfg_1, 0xC0FE, 484);
+       } else {
+               g_core_fp.fp_clean_sram_0f(pzf_op->data_fw_cfg_1, 484, 1);
+       }
+       /*ADC config*/
+       if (G_POWERONOF == 1) {
+               g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_adc_cfg_1, 0xD000, 768);
+       } else {
+               g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_1, 768, 2);
+       }
+
+       if (G_POWERONOF == 1) {
+               g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_adc_cfg_2, 0xD300, 1536);
+       } else {
+               g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_2, 1536, 2);
+       }
+
+       if (G_POWERONOF == 1) {
+               g_core_fp.fp_write_sram_0f(fw_entry, pzf_op->data_adc_cfg_3, 0xE000, 1536);
+       } else {
+               g_core_fp.fp_clean_sram_0f(pzf_op->data_adc_cfg_3, 1536, 2);
+       }
+
+       /*border prevent info*/
+       himax_in_parse_assign_cmd(hx83102d_zf_data_bor_prevent_info, tmp_data, 4);
+       if (G_POWERONOF == 1) {
+               g_core_fp.fp_write_sram_0f(fw_entry, tmp_data, 0xC9E0, 32);
+       } else {
+               g_core_fp.fp_clean_sram_0f(tmp_data, 32, 2);
+       }
+       /*notch info*/
+       himax_in_parse_assign_cmd(hx83102d_zf_data_notch_info, tmp_data, 4);
+       if (G_POWERONOF == 1) {
+               g_core_fp.fp_write_sram_0f(fw_entry, tmp_data, 0xCA00, 128);
+       } else {
+               g_core_fp.fp_clean_sram_0f(tmp_data, 128, 2);
+       }
+       /*enable func info*/
+       himax_in_parse_assign_cmd(hx83102d_zf_func_info_en, tmp_data, 4);
+       if (G_POWERONOF == 1) {
+               g_core_fp.fp_write_sram_0f(fw_entry, tmp_data, 0xCB00, 12);
+       } else {
+               g_core_fp.fp_clean_sram_0f(tmp_data, 12, 2);
+       }
+       /*power on sub func*/
+       himax_in_parse_assign_cmd(hx83102d_zf_po_sub_func, tmp_data, 4);
+       if (G_POWERONOF == 1) {
+               retry = 0;
+               do {
+                       g_core_fp.fp_write_sram_0f(fw_entry, tmp_data, 0xA000, HX4K);
+                       crc = g_core_fp.fp_check_CRC (tmp_data, HX4K);
+                       if (crc == 0) {
+                               I("%s, power on sub func CRC OK in %d time \n", __func__, retry);
+                               break;
+                       } else {
+                               E("%s, HW CRC FAIL in %d time !\n", __func__, retry);
+                               I("%s, data[3] = %2X,data[2] = %2X,data[1] = %2X,data[0] = %2X !\n", __func__,
+                               tmp_data[3], tmp_data[2], tmp_data[1], tmp_data[0]);
+                       }
+                       retry++;
+               } while (crc != 0 && retry < 3);
+       } else {
+               g_core_fp.fp_clean_sram_0f(tmp_data, 4096, 2);
+       }
+
+       I("%s, END \n", __func__);
+}
+
+#if defined(HX_0F_DEBUG)
+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:
+               g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_sram_start_addr, 0, HX_40K_SZ);
+               break;
+       case 1:
+               g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_cfg_info, 0xC000, 132);
+               break;
+       case 2:
+               g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_fw_cfg_1, 0xC0FE, 484);
+               break;
+       case 3:
+               g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_1, 0xD000, 768);
+               break;
+       case 4:
+               g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_2, 0xD300, 1536);
+               break;
+       case 5:
+               g_core_fp.fp_read_sram_0f(fw_entry, pzf_op->data_adc_cfg_3, 0xE000, 1536);
+               break;
+       case 6:
+               himax_in_parse_assign_cmd(hx83102d_zf_data_bor_prevent_info, tmp_data, 4);
+               g_core_fp.fp_read_sram_0f(fw_entry, tmp_data, 0xC9E0, 32);
+               break;
+       case 7:
+               himax_in_parse_assign_cmd(hx83102d_zf_data_notch_info, tmp_data, 4);
+               g_core_fp.fp_read_sram_0f(fw_entry, tmp_data, 0xCA00, 128);
+               break;
+       case 8:
+               himax_in_parse_assign_cmd(hx83102d_zf_func_info_en, tmp_data, 4);
+               g_core_fp.fp_read_sram_0f(fw_entry, tmp_data, 0xCB00, 12);
+               break;
+       case 9:
+               himax_in_parse_assign_cmd(hx83102d_zf_po_sub_func, tmp_data, 4);
+               g_core_fp.fp_read_sram_0f(fw_entry, tmp_data, 0xA000, HX4K);
+               break;
+       default:
+               break;
+       }
+       I("%s, END \n", __func__);
+}
+#endif
+#endif
+
+static void himax_hx83102d_reg_re_init(void)
+{
+       I("%s:Entering!\n", __func__);
+       himax_in_parse_assign_cmd(hx83102d_fw_addr_raw_out_sel, pfw_op->addr_raw_out_sel, sizeof(pfw_op->addr_raw_out_sel));
+#if defined(HX_ZERO_FLASH)
+       himax_in_parse_assign_cmd(hx83102d_zf_data_sram_start_addr, pzf_op->data_sram_start_addr, sizeof(pzf_op->data_sram_start_addr));
+       himax_in_parse_assign_cmd(hx83102d_zf_data_adc_cfg_1, pzf_op->data_adc_cfg_1, sizeof(pzf_op->data_adc_cfg_1));
+       himax_in_parse_assign_cmd(hx83102d_zf_data_adc_cfg_2, pzf_op->data_adc_cfg_2, sizeof(pzf_op->data_adc_cfg_2));
+       himax_in_parse_assign_cmd(hx83102d_zf_data_adc_cfg_3, pzf_op->data_adc_cfg_3, sizeof(pzf_op->data_adc_cfg_3));
+#endif
+}
+
+static void himax_hx83102d_func_re_init(void)
+{
+       I("%s:Entering!\n", __func__);
+       g_core_fp.fp_chip_init = hx83102_chip_init;
+#if defined(HX_ZERO_FLASH)
+       g_core_fp.fp_firmware_update_0f = hx83102d_firmware_update_0f;
+       g_core_fp.fp_resume_ic_action = himax_hx83102d_resume_ic_action;
+       g_core_fp.fp_suspend_ic_action = himax_hx83102d_suspend_ic_action;
+       g_core_fp.fp_sense_on = himax_hx83102d_sense_on;
+#if defined(HX_0F_DEBUG)
+       g_core_fp.fp_firmware_read_0f = hx83102d_firmware_read_0f;
+#endif
+#endif
+
+}
+
+bool hx83102_chip_detect(void)
+{
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+       uint8_t tmp_addr[FOUR_BYTE_DATA_SZ];
+       bool ret_data = false;
+       int i = 0;
+
+       I("[%s][%d]:enter\n", __func__, __LINE__);
+
+       msleep(50);
+
+       himax_mcu_in_cmd_struct_init();
+       himax_mcu_in_cmd_init();
+
+       himax_hx83102d_reg_re_init();
+       himax_hx83102d_func_re_init();
+
+       hx83102_sense_off();
+
+       for (i = 0; i < 5; i++) {
+               tmp_addr[3] = 0x90;
+               tmp_addr[2] = 0x00;
+               tmp_addr[1] = 0x00;
+               tmp_addr[0] = 0xD0;
+               hx83102_register_read(tmp_addr, FOUR_BYTE_DATA_SZ, tmp_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] == 0x2d)) {
+                       strlcpy(private_ts->chip_name, HX_83102D_SERIES_PWON, 30);
+                       I("[%s][%d]:IC name = %s\n", __func__, __LINE__, private_ts->chip_name);
+
+                       I("Himax IC package %x%x%x in\n",  tmp_data[3],  tmp_data[2],  tmp_data[1]);
+                       ret_data = true;
+                       break;
+               } else {
+                       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;
+}
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_HX83102.h b/drivers/input/touchscreen/hxchipset/himax_ic_HX83102.h
new file mode 100755 (executable)
index 0000000..8513c99
--- /dev/null
@@ -0,0 +1,39 @@
+/*  Himax Android Driver Sample Code for HX83102 chipset
+
+    Copyright (C) 2018 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 <linux/slab.h>
+
+#define hx83102ab_fw_addr_sorting_mode_en              0x100007FC
+#define hx83102ab_fw_addr_selftest_addr_en             0x100007F8
+#define hx83102ab_data_adc_cfg_1                       0x10007B00
+
+#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
+
+
+#ifdef HX_ESD_RECOVERY
+       extern u8 HX_ESD_RESET_ACTIVATE;
+#endif
+
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c b/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.c
new file mode 100755 (executable)
index 0000000..bb17eb4
--- /dev/null
@@ -0,0 +1,316 @@
+/*  Himax Android Driver Sample Code for HX83112 chipset
+
+    Copyright (C) 2018 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_HX83112.h"
+extern struct himax_ts_data *private_ts;
+extern struct himax_core_fp g_core_fp;
+extern struct ic_operation *pic_op;
+extern struct fw_operation *pfw_op;
+#ifdef HX_ZERO_FLASH
+extern struct zf_operation *pzf_op;
+#endif
+
+extern int i2c_error_count;
+extern unsigned char IC_TYPE;
+extern unsigned char IC_CHECKSUM;
+extern bool DSRAM_Flag;
+
+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;
+
+#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
+
+#ifdef HX_TP_PROC_2T2R
+       extern bool Is_2T2R;
+#endif
+
+#ifdef HX_USB_DETECT_GLOBAL
+extern void himax_cable_detect_func (bool force_renew);
+#endif
+
+
+static void hx83112_chip_init (void)
+{
+
+       private_ts->chip_cell_type = CHIP_IS_IN_CELL;
+       I ("%s:IC cell type = %d\n",  __func__,  private_ts->chip_cell_type);
+       IC_CHECKSUM                     = HX_TP_BIN_CHECKSUM_CRC;
+       /*Himax: Set FW and CFG Flash Address*/
+       FW_VER_MAJ_FLASH_ADDR   = 49157;  /*0x00C005*/
+       FW_VER_MAJ_FLASH_LENG   = 1;
+       FW_VER_MIN_FLASH_ADDR   = 49158;  /*0x00C006*/
+       FW_VER_MIN_FLASH_LENG   = 1;
+       CFG_VER_MAJ_FLASH_ADDR  = 49408;  /*0x00C100*/
+       CFG_VER_MAJ_FLASH_LENG  = 1;
+       CFG_VER_MIN_FLASH_ADDR  = 49409;  /*0x00C101*/
+       CFG_VER_MIN_FLASH_LENG  = 1;
+       CID_VER_MAJ_FLASH_ADDR  = 49154;  /*0x00C002*/
+       CID_VER_MAJ_FLASH_LENG  = 1;
+       CID_VER_MIN_FLASH_ADDR  = 49155;  /*0x00C003*/
+       CID_VER_MIN_FLASH_LENG  = 1;
+}
+
+static bool hx83112_sense_off(void)
+{
+       uint8_t cnt = 0;
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+
+       do {
+               /*===========================================
+                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__);
+                       return false;
+               }
+
+               /*===========================================
+                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__);
+                       return false;
+               }
+
+               /*===========================================
+                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__);
+                       return false;
+               }
+
+               /*===========================================
+                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__);
+                       return false;
+               }
+
+               /*===========================================
+                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__);
+                       return false;
+               }
+
+               /* ======================
+                Check enter_save_mode
+                ======================*/
+               g_core_fp.fp_register_read(pic_op->addr_cs_central_state, FOUR_BYTE_ADDR_SZ, tmp_data, 0);
+               I("%s: Check enter_save_mode data[0]=%X \n", __func__, tmp_data[0]);
+
+               if (tmp_data[0] == 0x0C) {
+                       /*=====================================
+                        Reset TCON
+                       =====================================*/
+                       g_core_fp.fp_flash_write_burst(pic_op->addr_tcon_on_rst, pic_op->data_rst);
+                       msleep(1);
+                       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_flash_write_burst(pic_op->addr_tcon_on_rst, tmp_data);
+                       /*=====================================
+                        Reset ADC
+                       =====================================*/
+                       g_core_fp.fp_flash_write_burst(pic_op->addr_adc_on_rst, pic_op->data_rst);
+                       msleep(1);
+                       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_flash_write_burst(pic_op->addr_adc_on_rst, tmp_data);
+                       return true;
+               } else {
+                       msleep(10);
+#ifdef HX_RST_PIN_FUNC
+                       g_core_fp.fp_ic_reset(false, false);
+#endif
+               }
+       } while (cnt++ < 15);
+
+       return false;
+}
+
+static void hx83112_func_re_init (void)
+{
+       g_core_fp.fp_sense_off = hx83112_sense_off;
+       g_core_fp.fp_chip_init = hx83112_chip_init;
+}
+
+static void hx83112_reg_re_init (void)
+{
+}
+
+bool hx83112_chip_detect (void)
+{
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+       bool ret_data = false;
+       int i = 0;
+       himax_mcu_in_cmd_struct_init();
+       himax_mcu_in_cmd_init();
+
+       hx83112_reg_re_init();
+       hx83112_func_re_init();
+
+       g_core_fp.fp_sense_off();
+
+       for (i = 0; i < 5; i++) {
+               g_core_fp.fp_register_read (pfw_op->addr_icid_addr,  FOUR_BYTE_DATA_SZ,  tmp_data,  false);
+               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] == 0x11) && ((tmp_data[1] == 0x2a) || (tmp_data[1] == 0x2b) || (tmp_data[1] == 0x2e))) {
+                       if (tmp_data[1] == 0x2a) {
+                               strlcpy (private_ts->chip_name,  HX_83112A_SERIES_PWON,  30);
+                       } else if (tmp_data[1] == 0x2b) {
+                               strlcpy (private_ts->chip_name,  HX_83112B_SERIES_PWON,  30);
+                       }
+
+                       I("%s:IC name = %s\n", __func__, private_ts->chip_name);
+
+                       I("Himax IC package %x%x%x in\n",  tmp_data[3],  tmp_data[2],  tmp_data[1]);
+                       ret_data = true;
+                       break;
+               } else {
+                       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;
+}
+
+#if 0
+#ifdef CONFIG_CHIP_DTCFG
+static int himax_hx83112_probe(struct platform_device *pdev)
+{
+       I("%s:Enter\n", __func__);
+       g_core_fp.fp_chip_detect = hx83112_chip_detect;
+
+       return 0;
+}
+
+static int himax_hx83112_remove(struct platform_device *pdev)
+{
+       g_core_fp.fp_chip_detect = NULL;
+       g_core_fp.fp_chip_init = NULL;
+       return 0;
+}
+
+
+#ifdef CONFIG_OF
+static const struct of_device_id himax_hx83112_mttable[] = {
+       { .compatible = "himax,hx83112"},
+       { },
+};
+#else
+#define himax_hx83112_mttabl NULL
+#endif
+
+static struct platform_driver himax_hx83112_driver = {
+       .probe  = himax_hx83112_probe,
+       .remove = himax_hx83112_remove,
+       .driver = {
+               .name           = "HIMAX_HX83112",
+               .owner          = THIS_MODULE,
+               .of_match_table = himax_hx83112_mttable,
+       },
+};
+
+static int __init himax_hx83112_init(void)
+{
+       I("%s\n", __func__);
+       platform_driver_register(&himax_hx83112_driver);
+       return 0;
+}
+
+static void __exit himax_hx83112_exit(void)
+{
+       platform_driver_unregister(&himax_hx83112_driver);
+}
+
+#else
+static int himax_hx83112_probe(void)
+{
+       I("%s:Enter\n", __func__);
+
+       g_core_fp.fp_chip_detect = hx83112_chip_detect;
+
+       return 0;
+}
+
+static int himax_hx83112_remove(void)
+{
+       g_core_fp.fp_chip_detect = NULL;
+       g_core_fp.fp_chip_init = NULL;
+       return 0;
+}
+
+static int __init himax_hx83112_init(void)
+{
+       int ret = 0;
+
+       I("%s\n", __func__);
+       ret = himax_hx83112_probe();
+       return 0;
+}
+
+static void __exit himax_hx83112_exit(void)
+{
+       himax_hx83112_remove();
+}
+#endif
+
+module_init(himax_hx83112_init);
+module_exit(himax_hx83112_exit);
+
+MODULE_DESCRIPTION("HIMAX HX83112 touch driver");
+MODULE_LICENSE("GPL");
+#endif
+
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.h b/drivers/input/touchscreen/hxchipset/himax_ic_HX83112.h
new file mode 100755 (executable)
index 0000000..f861ad5
--- /dev/null
@@ -0,0 +1,19 @@
+/*  Himax Android Driver Sample Code for HX83112 chipset
+
+    Copyright (C) 2018 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 <linux/slab.h>
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_core.h b/drivers/input/touchscreen/hxchipset/himax_ic_core.h
new file mode 100755 (executable)
index 0000000..83a18a7
--- /dev/null
@@ -0,0 +1,717 @@
+#include "himax_platform.h"
+#include "himax_common.h"
+#include <linux/slab.h>
+
+#define EIGHT_BYTE_DATA_SZ     8
+#define FOUR_BYTE_DATA_SZ     4
+#define FOUR_BYTE_ADDR_SZ     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 CORE_INIT
+#define CORE_IC
+#define CORE_FW
+#define CORE_FLASH
+#define CORE_SRAM
+#define CORE_DRIVER
+
+#define HX_0F_DEBUG
+
+#ifdef HX_ESD_RECOVERY
+       extern u8 HX_ESD_RESET_ACTIVATE;
+#endif
+
+#ifdef CORE_INIT
+       void himax_mcu_in_cmd_struct_init(void);
+       /*void himax_mcu_in_cmd_struct_free(void);*/
+       void himax_in_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len);
+       void himax_mcu_in_cmd_init(void);
+
+       void himax_mcu_on_cmd_struct_init(void);
+       /*static void himax_mcu_on_cmd_struct_free(void);*/
+       void himax_on_parse_assign_cmd(uint32_t addr, uint8_t *cmd, int len);
+       void himax_mcu_on_cmd_init(void);
+#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 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_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_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_fw_state_addr                0x900000f8
+       #define fw_addr_fw_dbg_msg_addr              0x10007f44
+       #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 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_cmd_conti         0x44332211
+       #define sram_cmd_fin           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               0x10007089
+       #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             0x100070fa
+       #define driver_addr_fw_define_x_y_res                   0x100070fc
+
+       #define on_driver_addr_fw_define_int_is_edge               0x10007089
+       #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
+#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
+
+struct zf_info{
+       uint8_t sram_addr[4];
+       int write_size;
+       uint32_t fw_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];
+};
+
+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_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_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_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];
+};
+
+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  data_conti[4];
+       uint8_t  data_fin[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_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];
+       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];
+};
+
+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_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);
+       void (*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)(void);
+       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);
+#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);
+       bool (*fp_Calculate_CRC_with_AP)(unsigned char *FW_content, int CRC_from_FW, int mode);
+       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);
+#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);
+       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);
+       uint8_t (*fp_read_DD_status)(uint8_t *cmd_set, uint8_t *tmp_data);
+#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)(void);
+       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);
+#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
+    bool (*fp_chip_detect)(void);
+    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);
+#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);
+       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);
+#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
+#endif
+};
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic_incell_core.c b/drivers/input/touchscreen/hxchipset/himax_ic_incell_core.c
new file mode 100755 (executable)
index 0000000..e4d0864
--- /dev/null
@@ -0,0 +1,2775 @@
+
+#include "himax_ic_core.h"
+
+#if defined(HX_AUTO_UPDATE_FW) || defined(HX_ZERO_FLASH)
+       extern char *i_CTPM_firmware_name;
+#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
+#ifdef HX_ZERO_FLASH
+extern int g_f_0f_updat;
+#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 struct himax_ic_data *ic_data;
+extern struct himax_ts_data *private_ts;
+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;
+       extern void himax_rst_gpio_set(int pinnum, uint8_t value);
+#endif
+
+#if defined(HX_USB_DETECT_GLOBAL)
+extern void himax_cable_detect_func(bool force_renew);
+#endif
+
+extern int himax_report_data_init(void);
+extern int i2c_error_count;
+
+struct himax_core_command_operation *g_core_cmd_op = NULL;
+struct ic_operation *pic_op = NULL;
+struct fw_operation *pfw_op = NULL;
+struct flash_operation *pflash_op = NULL;
+struct sram_operation *psram_op = NULL;
+struct driver_operation *pdriver_op = NULL;
+#ifdef HX_ZERO_FLASH
+struct zf_operation *pzf_op = NULL;
+#endif
+
+extern struct himax_core_fp g_core_fp;
+
+#ifdef CORE_IC
+/* IC side start*/
+static void himax_mcu_burst_enable(uint8_t auto_add_4_byte)
+{
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+       /*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[FOUR_BYTE_DATA_SZ];
+       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 > FOUR_BYTE_DATA_SZ) {
+                       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, FOUR_BYTE_DATA_SZ, 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 > FOUR_BYTE_DATA_SZ) {
+                       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(uint8_t *reg_byte, uint8_t *write_data)
+{
+       uint8_t data_byte[FLASH_WRITE_BURST_SZ];
+       int i = 0, j = 0;
+       int data_byte_sz = sizeof(data_byte);
+
+       for (i = 0; i < FOUR_BYTE_ADDR_SZ; i++) {
+               data_byte[i] = reg_byte[i];
+       }
+
+       for (j = FOUR_BYTE_ADDR_SZ; j < data_byte_sz; j++) {
+               data_byte[j] = write_data[j - FOUR_BYTE_ADDR_SZ];
+       }
+
+       if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], data_byte, data_byte_sz, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               return I2C_FAIL;
+       }
+       return NO_ERR;
+}
+
+static void himax_mcu_flash_write_burst_lenth(uint8_t *reg_byte, uint8_t *write_data, uint32_t length)
+{
+       uint8_t *data_byte;
+       int i = 0, j = 0;
+
+       /* if (length + FOUR_BYTE_ADDR_SZ > FLASH_RW_MAX_LEN) {
+               E("%s: write len over %d!\n", __func__, FLASH_RW_MAX_LEN);
+               return;
+       } */
+
+       data_byte = kzalloc(sizeof(uint8_t)*(length + 4), GFP_KERNEL);
+
+       for (i = 0; i < FOUR_BYTE_ADDR_SZ; i++) {
+               data_byte[i] = reg_byte[i];
+       }
+
+       for (j = FOUR_BYTE_ADDR_SZ; j < length + FOUR_BYTE_ADDR_SZ; j++) {
+               data_byte[j] = write_data[j - FOUR_BYTE_ADDR_SZ];
+       }
+
+       if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], data_byte, length + FOUR_BYTE_ADDR_SZ, HIMAX_I2C_RETRY_TIMES) < 0) {
+               E("%s: i2c access fail!\n", __func__);
+               kfree(data_byte);
+               return;
+       }
+       kfree(data_byte);
+}
+
+static void himax_mcu_register_write(uint8_t *write_addr, uint32_t write_length, uint8_t *write_data, uint8_t cfg_flag)
+{
+       int i, address;
+
+       /*I("%s,Entering \n", __func__);*/
+       if (cfg_flag == false) {
+               address = (write_addr[3] << 24) + (write_addr[2] << 16) + (write_addr[1] << 8) + write_addr[0];
+
+               for (i = address; i < address + write_length; i++) {
+                       if (write_length > FOUR_BYTE_DATA_SZ) {
+                               g_core_fp.fp_burst_enable(1);
+                       } else {
+                               g_core_fp.fp_burst_enable(0);
+                       }
+
+                       g_core_fp.fp_flash_write_burst_lenth(write_addr, write_data, write_length);
+               }
+       } else if (cfg_flag == true) {
+               if (himax_bus_write(write_addr[0], write_data, write_length, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return;
+               }
+       } else {
+               E("%s: cfg_flag = %d, value is wrong!\n", __func__, cfg_flag);
+               return;
+       }
+}
+
+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_flash_write_burst(tmp_addr, tmp_data);
+               msleep(10);
+               g_core_fp.fp_register_read(tmp_addr, 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[FOUR_BYTE_DATA_SZ];
+       uint8_t tmp_data2[FOUR_BYTE_DATA_SZ];
+       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, FOUR_BYTE_DATA_SZ, 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;
+               }
+
+               msleep(1);
+       } 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[FOUR_BYTE_DATA_SZ];
+       int retry_cnt = 0;
+
+       g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt);
+       tmp_data[0] = 0x01;
+
+       do {
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_1);
+
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_1);
+               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[FOUR_BYTE_DATA_SZ];
+       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, false);
+       msleep(20);
+
+       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, false);
+
+                       g_core_fp.fp_register_read(pfw_op->addr_flag_reset_event, FOUR_BYTE_DATA_SZ, 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, false);
+               }
+       }
+}
+
+static bool himax_mcu_sense_off(void)
+{
+       uint8_t cnt = 0;
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+
+       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, FOUR_BYTE_ADDR_SZ, 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_flash_write_burst(pic_op->addr_tcon_on_rst, pic_op->data_rst);
+                       msleep(1);
+                       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_flash_write_burst(pic_op->addr_tcon_on_rst, tmp_data);
+
+                       g_core_fp.fp_flash_write_burst(pic_op->addr_adc_on_rst, pic_op->data_rst);
+                       msleep(1);
+                       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_flash_write_burst(pic_op->addr_adc_on_rst, tmp_data);
+                       return true;
+               } else {
+                       msleep(10);
+#ifdef HX_RST_PIN_FUNC
+                       g_core_fp.fp_ic_reset(false, false);
+#endif
+               }
+       } while (cnt++ < 15);
+
+       return false;
+}
+
+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, false);
+       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, false);
+       /*DSRAM func initial*/
+       g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear);
+       g_core_fp.fp_sense_on(0x00);
+}
+
+/* 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)
+{
+       g_core_fp.fp_register_write(pfw_op->addr_system_reset, sizeof(pfw_op->data_system_reset), pfw_op->data_system_reset, false);
+}
+
+static bool himax_mcu_Calculate_CRC_with_AP(unsigned char *FW_content, int CRC_from_FW, int mode)
+{
+       return true;
+}
+
+static uint32_t himax_mcu_check_CRC(uint8_t *start_addr, int reload_length)
+{
+       uint32_t result = 0;
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+       int cnt = 0, ret = 0;
+       int length = reload_length / FOUR_BYTE_DATA_SZ;
+
+       ret = g_core_fp.fp_flash_write_burst(pfw_op->addr_reload_addr_from, start_addr);
+       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_flash_write_burst(pfw_op->addr_reload_addr_cmd_beat, tmp_data);
+       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, FOUR_BYTE_DATA_SZ, 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, FOUR_BYTE_DATA_SZ, 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]);
+                       break;
+               } else {
+                       I("Waiting for HW ready!\n");
+                       msleep(1);
+               }
+
+       } while (cnt++ < 100);
+
+       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;
+}
+
+static void himax_mcu_set_SMWP_enable(uint8_t SMWP_enable, bool suspended)
+{
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+       uint8_t back_data[FOUR_BYTE_DATA_SZ];
+       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_flash_write_burst(pfw_op->addr_smwp_enable, tmp_data);
+                       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_flash_write_burst(pfw_op->addr_smwp_enable, tmp_data);
+                       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, FOUR_BYTE_DATA_SZ, 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[FOUR_BYTE_DATA_SZ];
+       uint8_t back_data[FOUR_BYTE_DATA_SZ];
+       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_flash_write_burst(pfw_op->addr_hsen_enable, tmp_data);
+                       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_flash_write_burst(pfw_op->addr_hsen_enable, tmp_data);
+                       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, FOUR_BYTE_DATA_SZ, 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[FOUR_BYTE_DATA_SZ];
+       uint8_t back_data[FOUR_BYTE_DATA_SZ];
+       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_flash_write_burst(pfw_op->addr_usb_detect, tmp_data);
+                       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_flash_write_burst(pfw_op->addr_usb_detect, tmp_data);
+                       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, FOUR_BYTE_DATA_SZ, 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[FOUR_BYTE_DATA_SZ];
+       uint8_t back_data[FOUR_BYTE_DATA_SZ];
+       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_flash_write_burst(pfw_op->addr_raw_out_sel, tmp_data);
+               g_core_fp.fp_register_read(pfw_op->addr_raw_out_sel, FOUR_BYTE_DATA_SZ, 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();
+       g_core_fp.fp_burst_enable(1);
+       g_core_fp.fp_flash_write_burst(pfw_op->addr_selftest_addr_en, pfw_op->data_selftest_request);
+       /*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_flash_write_burst_lenth(pfw_op->addr_criteria_addr, tmp_data, FLASH_WRITE_BURST_SZ);
+       g_core_fp.fp_flash_write_burst(pfw_op->addr_set_frame_addr, pfw_op->data_set_frame);
+       /*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);
+               msleep(10);
+
+               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();
+       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[FOUR_BYTE_DATA_SZ];
+       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, FOUR_BYTE_DATA_SZ, 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_flash_write_burst(pfw_op->addr_fw_mode_status, tmp_data);
+               g_core_fp.fp_register_read(pfw_op->addr_fw_mode_status, FOUR_BYTE_DATA_SZ, 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--;
+               msleep(10);
+       } 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_flash_write_burst(pdriver_op->addr_fw_define_flash_reload, pdriver_op->data_fw_define_flash_reload_dis);
+       } else { /*reload enable*/
+               g_core_fp.fp_flash_write_burst(pdriver_op->addr_fw_define_flash_reload, pdriver_op->data_fw_define_flash_reload_en);
+       }
+
+       I("%s: setting OK!\n", __func__);
+}
+
+static bool himax_mcu_check_chip_version(void)
+{
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+       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, FOUR_BYTE_DATA_SZ, 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;
+                       break;
+               } else {
+                       ret_data = false;
+                       E("%s:Read driver ID register Fail:\n", __func__);
+               }
+       }
+
+       return ret_data;
+}
+
+static int himax_mcu_read_ic_trigger_type(void)
+{
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+       int trigger_type = false;
+       g_core_fp.fp_register_read(pfw_op->addr_trigger_addr, FOUR_BYTE_DATA_SZ, 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[FOUR_BYTE_DATA_SZ];
+       uint8_t data_2[FOUR_BYTE_DATA_SZ];
+       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, FOUR_BYTE_DATA_SZ, data, 0);
+               g_core_fp.fp_register_read(pdriver_op->addr_fw_define_2nd_flash_reload, FOUR_BYTE_DATA_SZ, 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;
+                       return;
+               } else {
+                       retry--;
+                       msleep(10);
+                       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();
+       g_core_fp.fp_register_read(pfw_op->addr_fw_ver_addr, FOUR_BYTE_DATA_SZ, 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, FOUR_BYTE_DATA_SZ, 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, FOUR_BYTE_DATA_SZ, 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));
+}
+
+static bool himax_mcu_read_event_stack(uint8_t *buf, uint8_t length)
+{
+       uint8_t cmd[FOUR_BYTE_DATA_SZ];
+       /*  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;
+       }
+
+       himax_bus_read(pfw_op->addr_event_addr[0], buf, length, HIMAX_I2C_RETRY_TIMES);
+       /*  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[FOUR_BYTE_DATA_SZ];
+       I("%s:entering\n", __func__);
+
+       do {
+               I("now %d times!\n", retry);
+
+               for (i = 0; i < FOUR_BYTE_DATA_SZ; i++) {
+                       tmp_data[i] = psram_op->addr_rawdata_end[i];
+               }
+
+               g_core_fp.fp_flash_write_burst(psram_op->addr_rawdata_addr, tmp_data);
+               g_core_fp.fp_register_read(psram_op->addr_rawdata_addr, FOUR_BYTE_DATA_SZ, tmp_data, 0);
+               retry--;
+               msleep(10);
+       } 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)
+{
+       uint8_t CRC_result = 0, i;
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+
+       for (i = 0; i < FOUR_BYTE_DATA_SZ; i++) {
+               tmp_data[i] = psram_op->addr_rawdata_end[i];
+       }
+
+       CRC_result = g_core_fp.fp_check_CRC(tmp_data, FW_SIZE_64k);
+       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[FOUR_BYTE_DATA_SZ];
+       uint8_t cmd_addr[FOUR_BYTE_DATA_SZ];
+
+       if (state_addr[0] == 0x01) {
+               state_addr[1] = 0x04;
+
+               for (i = 0; i < FOUR_BYTE_DATA_SZ; 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 < FOUR_BYTE_DATA_SZ; 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_flash_write_burst(pfw_op->addr_sorting_mode_en, tmp_data);
+
+       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, FOUR_BYTE_DATA_SZ, 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[FOUR_BYTE_DATA_SZ];
+       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();
+       /*g_core_fp.fp_interface_on();*/
+       /* clean up FW status */
+       g_core_fp.fp_flash_write_burst(psram_op->addr_rawdata_addr, psram_op->addr_rawdata_end);
+       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_flash_write_burst(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, pdriver_op->data_fw_define_rxnum_txnum_maxpt_sorting);
+       } else {
+               g_core_fp.fp_flash_write_burst(pfw_op->addr_set_frame_addr, pfw_op->data_set_frame);
+               g_core_fp.fp_flash_write_burst(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, pdriver_op->data_fw_define_rxnum_txnum_maxpt_normal);
+       }
+
+       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, FOUR_BYTE_DATA_SZ, 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 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, FOUR_BYTE_DATA_SZ, 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, FOUR_BYTE_DATA_SZ, tmp_data, 0);
+               msleep(10);
+
+               if (tmp_data[3] == pfw_op->data_dd_ack[0]) {
+                       I("%s Data ready goto moving data\n", __func__);
+                       break;
+               } else {
+                       if (cnt >= 99) {
+                               I("%s Data not ready in FW \n", __func__);
+                               return FW_NOT_READY;
+                       }
+               }
+       }
+
+       g_core_fp.fp_register_read(pfw_op->addr_dd_data_addr, req_size, tmp_data, 0);
+       return NO_ERR;
+}
+/* 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_flash_write_burst(pflash_op->addr_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt);
+
+       g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_2);
+       g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_2);
+
+       g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_3);
+       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_flash_write_burst(pflash_op->addr_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt);
+
+       for (page_prog_start = start_addr; page_prog_start < start_addr + length; page_prog_start = page_prog_start + block_size) {
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_2);
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_2);
+
+               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_flash_write_burst(pflash_op->addr_spi200_addr, tmp_data);
+
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_3);
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_4);
+               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[FOUR_BYTE_DATA_SZ];
+       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_flash_write_burst(pflash_op->addr_spi200_trans_fmt, pflash_op->data_spi200_trans_fmt);
+
+       for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start += FLASH_RW_MAX_LEN) {
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_2);
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_2);
+
+                /*Programmable size = 1 page = 256 bytes, word_number = 256 byte / 4 = 64*/
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_trans_ctrl, pflash_op->data_spi200_trans_ctrl_4);
+
+               /* 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_flash_write_burst(pflash_op->addr_spi200_addr, tmp_data);
+
+               for (i = 0; i < FOUR_BYTE_ADDR_SZ; 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 + FOUR_BYTE_ADDR_SZ] = FW_content[i];
+               }
+
+               if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], buring_data, FOUR_BYTE_ADDR_SZ + 16, HIMAX_I2C_RETRY_TIMES) < 0) {
+                       E("%s: i2c access fail!\n", __func__);
+                       return;
+               }
+
+               g_core_fp.fp_flash_write_burst(pflash_op->addr_spi200_cmd, pflash_op->data_spi200_cmd_6);
+
+               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 + FOUR_BYTE_ADDR_SZ] = FW_content[i];
+                       }
+
+                       if (himax_bus_write(pic_op->addr_ahb_addr_byte_0[0], buring_data, program_length + FOUR_BYTE_ADDR_SZ, 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();
+       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, false);
+       /*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)
+{
+       /* Not use */
+       return 0;
+}
+
+static void himax_mcu_flash_dump_func(uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
+{
+       uint8_t tmp_addr[FOUR_BYTE_DATA_SZ];
+       uint8_t buffer[256];
+       int page_prog_start = 0;
+       g_core_fp.fp_sense_off();
+       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(void)
+{
+       uint8_t tmp_addr[4];
+       uint32_t start_addr = 0xFF80;
+       uint32_t temp_addr = 0;
+       uint32_t flash_page_len = 0x80;
+       uint8_t flash_tmp_buffer[128];
+
+       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]);
+               return 1;/*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]);
+               return 1;
+       } 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*/
+       }
+}
+/* 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[FOUR_BYTE_ADDR_SZ];
+       unsigned char tmp_data[FOUR_BYTE_DATA_SZ];
+       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 = kzalloc(sizeof(uint8_t) * (total_size + 8), 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__);
+               kfree(temp_info_data);
+               return false;
+       }
+
+       /* 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 */
+       /*I("DSRAM_Flag=%d\n",DSRAM_Flag);*/
+       if (DSRAM_Flag == false || private_ts->diag_cmd == 0) {
+               /*I("Return to Event Stack!\n");*/
+               g_core_fp.fp_flash_write_burst(psram_op->addr_rawdata_addr, psram_op->data_fin);
+       } else {
+               /*I("Continue to SRAM!\n");*/
+               g_core_fp.fp_flash_write_burst(psram_op->addr_rawdata_addr, psram_op->data_conti);
+       }
+
+       /* 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);
+               kfree(temp_info_data);
+               return false;
+       } 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;
+}
+/* SRAM side end*/
+#endif
+
+#ifdef CORE_DRIVER
+static bool himax_mcu_detect_ic(void)
+{
+       I("%s: use default incell detect.\n", __func__);
+
+       return 0;
+}
+
+
+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.\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 = 1;
+       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
+
+static void himax_mcu_touch_information(void)
+{
+#ifndef HX_FIX_TOUCH_INFO
+       char data[EIGHT_BYTE_DATA_SZ] = {0};
+
+       g_core_fp.fp_register_read(pdriver_op->addr_fw_define_rxnum_txnum_maxpt, EIGHT_BYTE_DATA_SZ, 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, FOUR_BYTE_DATA_SZ, 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, FOUR_BYTE_DATA_SZ, 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, FOUR_BYTE_DATA_SZ, 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;
+       }
+
+       if (ic_data->HX_RX_NUM > 40) {
+               ic_data->HX_RX_NUM = 32;
+       }
+
+       if (ic_data->HX_TX_NUM > 20) {
+               ic_data->HX_TX_NUM = 18;
+       }
+
+       if (ic_data->HX_MAX_PT > 10) {
+               ic_data->HX_MAX_PT = 10;
+       }
+
+       if (ic_data->HX_Y_RES > 2000) {
+               ic_data->HX_Y_RES = 1280;
+       }
+
+       if (ic_data->HX_X_RES > 2000) {
+               ic_data->HX_X_RES = 720;
+       }
+
+       /*1. Read number of MKey R100070E8H to determin data size*/
+       g_core_fp.fp_register_read(psram_op->addr_mkey, FOUR_BYTE_DATA_SZ, 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;
+#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 (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;
+               goto END_FUNCTION;
+       }
+
+       if (hx_esd_event == length) {
+               g_zero_event_count = 0;
+               ret_val = HX_ESD_EVENT;
+               goto END_FUNCTION;
+       } else if (hx_zero_event == length) {
+               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;
+               goto END_FUNCTION;
+       }
+
+END_FUNCTION:
+       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();
+#endif
+       I("%s:\n", __func__);
+}
+#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_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;
+
+void hx_dis_rload_0f(int disable)
+{
+       /*Diable Flash Reload*/
+       g_core_fp.fp_flash_write_burst (pzf_op->addr_dis_flash_reload,  pzf_op->data_dis_flash_reload);
+}
+
+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;
+
+       if (total_size > 4096) {
+               max_bus_size = 4096;
+       }
+
+       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_flash_write_burst_lenth (tmp_addr, tmp_data,  max_bus_size);
+                       total_size_temp = total_size_temp - max_bus_size;
+               } else {
+                       I("last total_size_temp=%d\n", total_size_temp);
+                       g_core_fp.fp_flash_write_burst_lenth (tmp_addr, tmp_data,  total_size_temp % max_bus_size);
+               }
+               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, 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 > 4096) {
+               max_bus_size = 4096;
+       } else {
+               max_bus_size = write_len;
+       }
+#else
+       if (write_len > 240) {
+               max_bus_size = 240;
+       } else {
+               max_bus_size = write_len;
+       }
+#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 = kzalloc (sizeof (uint8_t) * max_bus_size, 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);
+                       g_core_fp.fp_flash_write_burst_lenth (tmp_addr, tmp_data,  max_bus_size);
+                       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);
+                       I("last total_size_temp=%d\n", total_size_temp % max_bus_size);
+                       g_core_fp.fp_flash_write_burst_lenth (tmp_addr, tmp_data,  total_size_temp % max_bus_size);
+               }
+
+               /*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 himax_zf_part_info(const struct firmware *fw_entry)
+{
+       int part_num = 0;
+       int ret = 0;
+       int i = 0;
+       uint8_t buf[16];
+       struct zf_info *zf_info_arr;
+
+       /*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 = kzalloc(part_num * sizeof(struct zf_info), GFP_KERNEL);
+       if (zf_info_arr == NULL) {
+               E("%s, Allocate ZF info array failed!\n", __func__);
+               return MEM_ALLOC_FAIL;
+       }
+
+       for (i = 0; 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[5] << 8 | buf[4];
+               zf_info_arr[i].fw_addr = buf[9] << 8 | buf[8];
+               I("%s,[%d] SRAM addr = %02X%02X%02X%02X!\n", __func__, i, zf_info_arr[i].sram_addr[3], zf_info_arr[i].sram_addr[2],
+                                                                                                                                                                                               zf_info_arr[i].sram_addr[1], zf_info_arr[i].sram_addr[0]);
+               I("%s,[%d] fw_addr = %04X!\n", __func__, i, zf_info_arr[i].fw_addr);
+               I("%s,[%d] write_size = %d!\n", __func__, i, zf_info_arr[i].write_size);
+
+               /*4. write to sram*/
+               if (G_POWERONOF == 1) {
+                       if (himax_sram_write_crc_check(fw_entry, zf_info_arr[i].sram_addr, zf_info_arr[i].fw_addr, zf_info_arr[i].write_size) != 0) {
+                               E("%s, HW CRC FAIL\n", __func__);
+                       }
+    } else {
+                       g_core_fp.fp_clean_sram_0f(zf_info_arr[i].sram_addr, zf_info_arr[i].write_size, 2);
+               }
+       }
+
+       kfree (zf_info_arr);
+
+       return ret;
+}
+
+void himax_mcu_firmware_update_0f(const struct firmware *fw_entry)
+{
+       int ret = 0;
+
+       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,  false);
+
+       g_core_fp.fp_sense_off();
+
+       /* 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__);
+       if ((int)fw_entry->size > HX64K) {
+               ret = himax_zf_part_info(fw_entry);
+       } else {
+               /*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, 0xC100, 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);
+       }
+
+       /*DSRAM func initial*/
+       g_core_fp.fp_assign_sorting_mode(pfw_op->data_clear);
+
+       I("%s, End \n", __func__);
+}
+
+int hx_0f_op_file_dirly(char *file_name)
+{
+       int err = NO_ERR;
+       const struct firmware *fw_entry = NULL;
+
+
+       I("%s, Entering \n", __func__);
+       I("file name = %s\n", file_name);
+       err = request_firmware (&fw_entry, file_name, private_ts->dev);
+       if (err < 0) {
+               E("%s, fail in line%d error code=%d,file maybe fail\n", __func__, __LINE__, err);
+               return err;
+       }
+
+       himax_int_enable (0);
+
+       if (g_f_0f_updat == 1) {
+               I("%s:[Warning]Other thread is updating now!\n", __func__);
+               err = -1;
+               return err;
+       } else {
+               I("%s:Entering Update Flow!\n", __func__);
+               g_f_0f_updat = 1;
+       }
+
+       g_core_fp.fp_firmware_update_0f (fw_entry);
+       release_firmware (fw_entry);
+
+       g_f_0f_updat = 0;
+       I("%s, END \n", __func__);
+       return err;
+}
+
+int himax_mcu_0f_operation_dirly(void)
+{
+       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) {
+               E("%s, fail in line%d error code=%d,file maybe fail\n", __func__, __LINE__, err);
+               return err;
+       }
+
+       himax_int_enable (0);
+
+       if (g_f_0f_updat == 1) {
+               I("%s:[Warning]Other thread is updating now!\n", __func__);
+               err = -1;
+               return err;
+       } else {
+               I("%s:Entering Update Flow!\n", __func__);
+               g_f_0f_updat = 1;
+       }
+
+       g_core_fp.fp_firmware_update_0f (fw_entry);
+       release_firmware (fw_entry);
+
+       g_f_0f_updat = 0;
+       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) {
+               E("%s, fail in line%d error code=%d,file maybe fail\n", __func__, __LINE__, err);
+               return ;
+       }
+
+       if (g_f_0f_updat == 1) {
+               I("%s:[Warning]Other thread is updating now!\n", __func__);
+               return ;
+       } 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);
+       release_firmware (fw_entry);
+
+       g_core_fp.fp_reload_disable(0);
+       msleep (10);
+       g_core_fp.fp_read_FW_ver();
+       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;
+       I("%s, END \n", __func__);
+       return ;
+}
+
+static int himax_mcu_0f_esd_check(void)
+{
+       uint8_t tmp_data[FOUR_BYTE_DATA_SZ];
+       int ret = NO_ERR;
+
+       I("Enter %s\n", __func__);
+
+       g_core_fp.fp_register_read(pzf_op->addr_sts_chk, FOUR_BYTE_DATA_SZ, tmp_data, 0);
+
+       if (tmp_data[0] != pzf_op->data_activ_sts[0]) {
+               ret = ERR_STS_WRONG;
+               I("%s:status : %8X = %2X\n", __func__, zf_addr_sts_chk, tmp_data[0]);
+       }
+
+       g_core_fp.fp_register_read(pzf_op->addr_activ_relod, FOUR_BYTE_DATA_SZ, tmp_data, 0);
+
+       if (tmp_data[0] != 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;
+}
+
+
+#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 = kzalloc (sizeof (uint8_t) * total_size, GFP_KERNEL);
+       not_same_buff = kzalloc (sizeof (int) * total_size, 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) {
+                       printk ("\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 = kzalloc (sizeof (uint8_t) * total_size, 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<read_len;i++)
+       {
+               I("0x%2.2X, ", temp_info_data[i]);
+
+               if (i > 0 && i%16 == 15)
+                       printk("\n");
+       }*/
+
+       /* need modify
+       I("Now Write File start!\n");
+       vts_name = getname_kernel("/sdcard/dump_dsram.txt");
+       fn = 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, pzf_op->data_mode_switch, 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) {
+               E("%s, fail in line%d error code=%d\n", __func__, __LINE__, err);
+               return ;
+       }
+
+       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);
+
+       release_firmware(fw_entry);
+       I("%s, END \n", __func__);
+       return ;
+}
+#endif
+
+#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;
+#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;
+       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_switch_mode = himax_mcu_switch_mode;
+       g_core_fp.fp_read_DD_status = himax_mcu_read_DD_status;
+#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;
+#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_detect = himax_mcu_detect_ic;
+       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
+#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_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
+#endif
+}
+
+void himax_mcu_in_cmd_struct_init(void)
+{
+       I("%s: Entering!\n", __func__);
+       g_core_cmd_op = kzalloc(sizeof(struct himax_core_command_operation), GFP_KERNEL);
+       g_core_cmd_op->ic_op = kzalloc(sizeof(struct ic_operation), GFP_KERNEL);
+       g_core_cmd_op->fw_op = kzalloc(sizeof(struct fw_operation), GFP_KERNEL);
+       g_core_cmd_op->flash_op = kzalloc(sizeof(struct flash_operation), GFP_KERNEL);
+       g_core_cmd_op->sram_op = kzalloc(sizeof(struct sram_operation), GFP_KERNEL);
+       g_core_cmd_op->driver_op = kzalloc(sizeof(struct driver_operation), GFP_KERNEL);
+       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);
+       pzf_op = g_core_cmd_op->zf_op;
+#endif
+       himax_mcu_fp_init();
+}
+
+/*
+static 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_core_cmd_op);
+       kfree(g_core_cmd_op->ic_op);
+       kfree(g_core_cmd_op->flash_op);
+       kfree(g_core_cmd_op->sram_op);
+       kfree(g_core_cmd_op->driver_op);
+}
+*/
+
+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);
+       }
+}
+
+void himax_mcu_in_cmd_init(void)
+{
+       I("%s: Entering!\n", __func__);
+#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));
+#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_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_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_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));
+#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_cmd_conti, psram_op->data_conti, sizeof(psram_op->data_conti));
+       himax_in_parse_assign_cmd(sram_cmd_fin, psram_op->data_fin, sizeof(psram_op->data_fin));
+       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_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_2, 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
+}
+
+/* init end*/
+#endif
diff --git a/drivers/input/touchscreen/hxchipset/himax_inspection.c b/drivers/input/touchscreen/hxchipset/himax_inspection.c
new file mode 100755 (executable)
index 0000000..4714a3f
--- /dev/null
@@ -0,0 +1,1259 @@
+#include "himax_inspection.h"
+
+char *hx_self_test_file_name = NULL;
+
+extern struct himax_core_fp g_core_fp;
+extern struct himax_ts_data *private_ts;
+extern struct himax_ic_data *ic_data;
+
+void himax_inspection_init(void);
+
+void (*fp_himax_self_test_init)(void) = himax_inspection_init;
+
+#ifdef HX_ESD_RECOVERY
+       extern u8 HX_ESD_RESET_ACTIVATE;
+#endif
+
+#ifdef HX_INSPECT_LPWUG_TEST
+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);
+
+    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);
+}
+#endif
+static uint8_t NOISEMAX;
+
+#if 0
+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));
+       vts_name = getname_kernel(filepath);
+
+       raw_file = 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, 0x1000 * 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;
+}
+#endif
+
+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 = 0x1000;
+
+       I("%s: Entering, Now type=%s!\n", __func__, g_himax_inspection_mode[now_item]);
+
+       testdata = kzalloc(sizeof(char) * SZ_SIZE, GFP_KERNEL);
+
+       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))
+                       printk("\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_flash_write_burst_lenth(tmp_addr, tmp_data, 4);
+
+       /*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;
+#ifdef HX_GAP_TEST
+       case HIMAX_INSPECTION_GAPTEST_RAW:
+#endif
+       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_NOISE:
+               tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = PWD_NOISE_START; tmp_data[0] = PWD_NOISE_START;
+               break;
+#ifdef HX_ACT_IDLE_TEST
+       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;
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       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;
+#endif
+       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_addr[4];
+       uint8_t tmp_data[4];
+       uint8_t *tmp_rawdata;
+       uint8_t retry = 0;
+       uint16_t checksum_cal;
+       uint32_t i = 0;
+
+       uint8_t max_i2c_size = 128;
+       int address = 0;
+       int total_read_times = 0;
+       int total_size = datalen * 2 + 4;
+       int total_size_temp;
+#if 1
+       uint32_t j = 0;
+       uint32_t index = 0;
+       uint32_t Min_DATA = 0xFFFFFFFF;
+       uint32_t Max_DATA = 0x00000000;
+#endif
+
+       tmp_rawdata = kzalloc(sizeof(uint8_t) * (datalen * 2), GFP_KERNEL);
+
+       /*1 Set Data Ready PWD*/
+       while (retry < 300) {
+               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] = Data_PWD1;
+               tmp_data[0] = Data_PWD0;
+               g_core_fp.fp_flash_write_burst_lenth(tmp_addr, tmp_data, 4);
+
+               g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false);
+               if ((tmp_data[0] == Data_PWD0 && tmp_data[1] == Data_PWD1) ||
+                       (tmp_data[0] == Data_PWD1 && tmp_data[1] == Data_PWD0)) {
+                       break;
+               }
+
+               retry++;
+               msleep(1);
+       }
+
+       if (retry >= 200) {
+               kfree(tmp_rawdata);
+               return 1;
+       } else {
+               retry = 0;
+       }
+
+       while (retry < 200) {
+               if (tmp_data[0] == Data_PWD1 && tmp_data[1] == Data_PWD0) {
+                       break;
+               }
+
+               retry++;
+               msleep(1);
+               g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false);
+       }
+
+       if (retry >= 200) {
+               kfree(tmp_rawdata);
+               return 1;
+       } else {
+               retry = 0;
+       }
+
+       /*2 Read Data from SRAM*/
+       while (retry < 10) {
+               checksum_cal = 0;
+               total_size_temp = total_size;
+               tmp_addr[3] = 0x10;     tmp_addr[2] = 0x00;     tmp_addr[1] = 0x00;     tmp_addr[0] = 0x00;
+
+               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++) {
+                       if (total_size_temp >= max_i2c_size) {
+                               g_core_fp.fp_register_read(tmp_addr, max_i2c_size, &tmp_rawdata[i*max_i2c_size], false);
+                               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, &tmp_rawdata[i*max_i2c_size], false);
+                       }
+
+                       address = ((i+1)*max_i2c_size);
+                       tmp_addr[1] = (uint8_t)((address>>8)&0x00FF);
+                       tmp_addr[0] = (uint8_t)((address)&0x00FF);
+               }
+
+               /*3 Check Checksum*/
+               for (i = 2 ; i < datalen * 2 + 4 ; i = i + 2) {
+                       checksum_cal += tmp_rawdata[i + 1] * 256 + tmp_rawdata[i];
+               }
+
+               if (checksum_cal == 0) {
+                       break;
+               }
+
+               retry++;
+       }
+
+       if (checksum_cal != 0) {
+               E("%s: Get rawdata checksum fail!\n", __func__);
+               kfree(tmp_rawdata);
+               return HX_CHKSUM_FAIL;
+       }
+
+       /*4 Copy Data*/
+       for (i = 0 ; i < ic_data->HX_TX_NUM * ic_data->HX_RX_NUM ; i++) {
+               RAW[i] = tmp_rawdata[(i * 2) + 1 + 4] * 256 + tmp_rawdata[(i * 2) + 4];
+       }
+
+#if 1
+       for (j = 0; j < ic_data->HX_RX_NUM; j++) {
+               if (j == 0) {
+                       printk("      RX%2d", j + 1);
+               } else {
+                       printk("  RX%2d", j + 1);
+               }
+       }
+       printk("\n");
+
+       for (i = 0 ; i < ic_data->HX_TX_NUM ; i++) {
+               printk("TX%2d", i + 1);
+               for (j = 0 ; j < ic_data->HX_RX_NUM ; j++) {
+                       printk("%5d ", RAW[index]);
+                       if (RAW[index] > Max_DATA) {
+                               Max_DATA = RAW[index];
+                       }
+                       if (RAW[index] < Min_DATA) {
+                               Min_DATA = RAW[index];
+                       }
+                       index++;
+               }
+               printk("\n");
+       }
+       I("Max = %5d, Min = %5d \n", Max_DATA, Min_DATA);
+#endif
+
+       kfree(tmp_rawdata);
+       return HX_INSPECT_OK;
+}
+
+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_NOISE:
+               datatype = DATA_NOISE;
+               break;
+       case HIMAX_INSPECTION_BACK_NORMAL:
+               datatype = DATA_BACK_NORMAL;
+               break;
+#ifdef HX_GAP_TEST
+       case HIMAX_INSPECTION_GAPTEST_RAW:
+               datatype = DATA_RAWDATA;
+               break;
+#endif
+#ifdef HX_ACT_IDLE_TEST
+       case HIMAX_INSPECTION_ACT_IDLE_RAWDATA:
+               datatype = DATA_ACT_IDLE_RAWDATA;
+               break;
+       case HIMAX_INSPECTION_ACT_IDLE_NOISE:
+               datatype = DATA_ACT_IDLE_NOISE;
+               break;
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       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;
+#endif
+       default:
+               E("Wrong type=%d\n", checktype);
+               break;
+       }
+       g_core_fp.fp_diag_register_set(datatype, 0x00);
+}
+
+static void himax_set_N_frame(uint16_t Nframe, uint8_t checktype)
+{
+       uint8_t tmp_addr[4];
+       uint8_t tmp_data[4];
+
+       /*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_flash_write_burst_lenth(tmp_addr, 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) {
+#ifdef HX_ACT_IDLE_TEST
+       case HIMAX_INSPECTION_ACT_IDLE_RAWDATA:
+       case HIMAX_INSPECTION_ACT_IDLE_NOISE:
+               tmp_data[0] = BS_ACT_IDLE;
+               break;
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       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;
+#endif
+       case HIMAX_INSPECTION_RAWDATA:
+       case HIMAX_INSPECTION_NOISE:
+               tmp_data[0] = BS_RAWDATANOISE;
+               break;
+       default:
+               tmp_data[0] = BS_OPENSHORT;
+               break;
+       }
+       g_core_fp.fp_flash_write_burst_lenth(tmp_addr, tmp_data, 4);
+}
+
+static void himax_get_noise_base(void)
+{
+       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;
+       g_core_fp.fp_register_read(tmp_addr, 4, tmp_data, false);
+
+       g_inspection_criteria[IDX_NOISEMAX][0] = tmp_data[3];
+       I("%s: g_inspection_criteria[IDX_NOISEMAX]=%d\n", __func__, g_inspection_criteria[IDX_NOISEMAX][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_NOISE:
+               wait_pwd[0] = PWD_NOISE_END;
+               wait_pwd[1] = PWD_NOISE_END;
+               break;
+#ifdef HX_ACT_IDLE
+       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;
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       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;
+#endif
+       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;
+       }
+}
+
+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_NOISE:
+               wait_pwd[0] = PWD_NOISE_END;
+               wait_pwd[1] = PWD_NOISE_END;
+               break;
+#ifdef HX_GAP_TEST
+       case HIMAX_INSPECTION_GAPTEST_RAW:
+               wait_pwd[0] = PWD_RAWDATA_END;
+               wait_pwd[1] = PWD_RAWDATA_END;
+               break;
+#endif
+#ifdef HX_ACT_IDLE_TEST
+       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;
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       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;
+#endif
+       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("%s: 0x900000A8, tmp_data[0]=%x,tmp_data[1]=%x,tmp_data[2]=%x,tmp_data[3]=%x \n", __func__, 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("%s: 0x900000E4, tmp_data[0]=%x,tmp_data[1]=%x,tmp_data[2]=%x,tmp_data[3]=%x \n", __func__, 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("%s: 0x10007F40,tmp_data[0]=%x,tmp_data[1]=%x,tmp_data[2]=%x,tmp_data[3]=%x \n", __func__, 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;
+}
+#if 0
+static int himax_check_notch(int index)
+{
+       if (SKIP_NOTCH_START < 0 && SKIP_NOTCH_END < 0 && SKIP_DUMMY_START < 0 && SKIP_DUMMY_START < 0) {
+               /* no support notch */
+               return 0;
+       }
+       if ((index >= SKIP_NOTCH_START) && (index <= SKIP_NOTCH_END))
+               return 1;
+       else if ((index >= SKIP_DUMMY_START) && (index <= SKIP_DUMMY_END))
+               return 1;
+       else
+               return 0;
+}
+#endif
+static uint32_t mpTestFunc(uint8_t checktype, uint32_t datalen)
+{
+       uint32_t i/*, j*/, ret = 0;
+       uint32_t RAW[datalen];
+       char *rslt_log;
+       char *start_log;
+       int ret_val;
+
+       /*uint16_t* pInspectGridData = &gInspectGridData[0];*/
+       /*uint16_t* pInspectNoiseData = &gInspectNoiseData[0];*/
+       I("Now Check type = %d\n", checktype);
+
+       if (himax_check_mode(checktype)) {
+               I("Need Change Mode ,target=%s\n", g_himax_inspection_mode[checktype]);
+
+               g_core_fp.fp_sense_off();
+
+#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);
+
+               if (checktype == HIMAX_INSPECTION_NOISE) {
+                       himax_set_N_frame(NOISEFRAME, checktype);
+                       himax_get_noise_base();
+#ifdef HX_ACT_IDLE_TEST
+               } else if (checktype == HIMAX_INSPECTION_ACT_IDLE_RAWDATA || checktype == HIMAX_INSPECTION_ACT_IDLE_NOISE) {
+                       I("N frame = %d\n", 10);
+                       himax_set_N_frame(10, checktype);
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+               } else if (checktype >= HIMAX_INSPECTION_LPWUG_RAWDATA) {
+                       I("N frame = %d\n", 1);
+                       himax_set_N_frame(1, checktype);
+#endif
+               } else {
+                       himax_set_N_frame(2, checktype);
+               }
+
+               g_core_fp.fp_sense_on(1);
+
+               ret = himax_wait_sorting_mode(checktype);
+               if (ret) {
+                       E("%s: himax_wait_sorting_mode FAIL\n", __func__);
+                       return ret;
+               }
+       }
+
+       himax_switch_data_type(checktype);
+
+       ret = himax_get_rawdata(RAW, datalen);
+       if (ret) {
+               E("%s: himax_get_rawdata FAIL\n", __func__);
+               return ret;
+       }
+
+       /* back to normal */
+       himax_switch_data_type(HIMAX_INSPECTION_BACK_NORMAL);
+
+       I("%s: Init OK, start to test!\n", __func__);
+       rslt_log = kzalloc(256 * sizeof(char), GFP_KERNEL);
+       start_log = kzalloc(256 * sizeof(char), GFP_KERNEL);
+
+       snprintf(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 (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       if ((int)RAW[i] < g_inspection_criteria[IDX_SORTMIN][i]) {
+                               E("%s: sorting mode open test FAIL\n", __func__);
+                               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 (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       if ((int)RAW[i] > g_inspection_criteria[IDX_OPENMAX][i] || (int)RAW[i] < g_inspection_criteria[IDX_OPENMIN][i]) {
+                               E("%s: open test FAIL\n", __func__);
+                               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 (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       if ((int)RAW[i] > g_inspection_criteria[IDX_M_OPENMAX][i] || (int)RAW[i] < g_inspection_criteria[IDX_M_OPENMIN][i]) {
+                               E("%s: open test FAIL\n", __func__);
+                               ret_val = HX_INSPECT_EMOPEN;
+                               goto FAIL_END;
+                       }
+               }
+               I("%s: 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 (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       if ((int)RAW[i] > g_inspection_criteria[IDX_SHORTMAX][i] || (int)RAW[i] < g_inspection_criteria[IDX_SHORTMIN][i]) {
+                               E("%s: short test FAIL\n", __func__);
+                               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 (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       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_NOISE:
+               I("NOISEMAX=%d\n", NOISEMAX);
+               for (i = 0 ; i < (ic_data->HX_TX_NUM * ic_data->HX_RX_NUM) ; i++) {
+                       /*if (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       if ((int)RAW[i] > g_inspection_criteria[IDX_NOISEMAX][i]) {
+                               I("g_inspection_criteria[IDX_NOISEMAX][%d]=%d\n", i, g_inspection_criteria[IDX_NOISEMAX][i]);
+                               I("RAW[%d]=%d\n", i, RAW[i]);
+                               E("%s: noise test FAIL\n", __func__);
+                               ret_val = HX_INSPECT_ENOISE;
+                               goto FAIL_END;
+                       }
+               }
+               I("%s: noise test PASS\n", __func__);
+               break;
+#ifdef HX_GAP_TEST
+       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;
+#endif
+#ifdef HX_ACT_IDLE_TEST
+       case HIMAX_INSPECTION_ACT_IDLE_RAWDATA:
+               for (i = 0 ; i < (ic_data->HX_TX_NUM * ic_data->HX_RX_NUM) ; i++) {
+                       /*if (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       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("%s: HIMAX_INSPECTION_ACT_IDLE_RAWDATA FAIL\n", __func__);
+                               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 (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       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("%s: HIMAX_INSPECTION_ACT_IDLE_NOISE FAIL\n", __func__);
+                               ret_val = HX_INSPECT_EACT_IDLE_NOISE;
+                               goto FAIL_END;
+                       }
+               }
+               I("%s: HIMAX_INSPECTION_ACT_IDLE_NOISE PASS\n", __func__);
+               break;
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       case HIMAX_INSPECTION_LPWUG_RAWDATA:
+               for (i = 0 ; i < (ic_data->HX_TX_NUM * ic_data->HX_RX_NUM) ; i++) {
+                       /*if (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       if ((int)RAW[i] > g_inspection_criteria[IDX_LPWUG_RAWDATA_MAX][i] || (int)RAW[i] < g_inspection_criteria[IDX_LPWUG_RAWDATA_MIN][i]) {
+                               E("%s: HIMAX_INSPECTION_LPWUG_RAWDATA FAIL\n", __func__);
+                               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 (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       if ((int)RAW[i] > g_inspection_criteria[IDX_LPWUG_NOISE_MAX][i] || (int)RAW[i] < g_inspection_criteria[IDX_LPWUG_NOISE_MIN][i]) {
+                               E("%s: HIMAX_INSPECTION_LPWUG_NOISE FAIL\n", __func__);
+                               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 (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       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("%s: HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA FAIL\n", __func__);
+                               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 (himax_check_notch(i)) {
+                               continue;
+                       }*/
+                       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("%s: HIMAX_INSPECTION_LPWUG_IDLE_NOISE FAIL\n", __func__);
+                               ret_val = HX_INSPECT_ELPWUG_IDLE_NOISE;
+                               goto FAIL_END;
+                       }
+               }
+               I("%s: HIMAX_INSPECTION_LPWUG_IDLE_NOISE PASS\n", __func__);
+               break;
+#endif
+       default:
+               E("Wrong type=%d\n", checktype);
+               break;
+       }
+
+       ret_val = HX_INSPECT_OK;
+       snprintf(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(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, start_log, rslt_log, checktype);
+       kfree(rslt_log);
+       return ret_val;
+}
+
+/* parsing Criteria start */
+static int himax_get_criteria_size(void)
+{
+       int result = 0;
+
+       result = HX_CRITERIA_SIZE;
+
+       return result;
+}
+
+/* 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] == '-') {
+                       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;
+}
+
+#if 0
+static int himax_count_comma(const struct firmware *file_entry)
+{
+       int i = 0;
+       int result = 0;
+       for (i = 0; i < file_entry->size; i++) {
+               if (file_entry->data[i] == ASCII_COMMA)
+                       result++;
+       }
+       return result;
+}
+#endif
+
+/* Get sub-string from original string by using some charaters */
+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 0;
+}
+
+static int hx_diff_str(char *str1, char *str2)
+{
+       int i = 0;
+       int err = -1;
+       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) {
+               I("%s:Size different!\n", __func__);
+               return err;
+       }
+
+       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;
+}
+
+static int hx_get_crtra_by_name(char **result)
+{
+       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 crtra_count = himax_get_criteria_size();
+       int all_mut_len = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM;
+       /* get criteria and assign to a global array(2-Dimensional/int) */
+       for (i = 0 ; i < (crtra_count * (all_mut_len) + crtra_count) ; 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;
+                       /* change to next type */
+                       if (i != 0)
+                               count_type++;
+                       if (hx_diff_str(g_hx_inspt_crtra_name[count_type], result[i]) != 0) {
+                               E("%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;
+                               return err;
+                       }
+                       continue;
+               }
+               /* change string to int*/
+               g_inspection_criteria[count_type][count_data] = hiamx_parse_str2int(result[i]);
+               /* dbg
+               I("[%d]g_inspection_criteria[%d][%d]=%d\n", i, count_type, count_data, g_inspection_criteria[count_type][count_data]);
+               */
+               count_data++;
+
+       }
+
+       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 = himax_get_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;
+
+       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);
+               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);
+
+       /* 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 = kzalloc(data_size * sizeof(char *), GFP_KERNEL);
+       for (i = 0 ; i < data_size ; i++)
+               result[i] = kzalloc(str_max_len * sizeof(char), GFP_KERNEL);
+
+       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 */
+       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) */
+       himax_saperate_comma(file_entry, result, data_size);
+
+       err = hx_get_crtra_by_name(result);
+       if (err != HX_INSPECT_OK) {
+               E("%s:Load criteria from file fail, go end!\n", __func__);
+               goto END_FUNC;
+       }
+
+       /* for dbg
+       for (i = 0; i < (((ic_data->HX_TX_NUM*ic_data->HX_RX_NUM)*6)+6); i++)
+       {
+               if (i%32 ==0 && i >0)
+                       I("\n");
+               I("[%d]%s", i, result[i]);
+       }*/
+END_FUNC:
+       for (i = 0 ; i < data_size ; i++)
+               kfree(result[i]);
+       kfree(result);
+       release_firmware(file_entry);
+END_FUNC_REQ_FAIL:
+       I("%s,END \n", __func__);
+       return err;
+}
+/* parsing Criteria end */
+
+int himax_self_test_data_init(void)
+{
+       int ret = HX_INSPECT_OK;
+       int i = 0;
+       g_rslt_data_len = 0;
+
+       g_inspection_criteria = kzalloc(sizeof(int *) * HX_CRITERIA_SIZE, GFP_KERNEL);
+       for (i = 0 ; i < HX_CRITERIA_SIZE ; i++) {
+               g_inspection_criteria[i] = kzalloc(sizeof(int) * (ic_data->HX_TX_NUM*ic_data->HX_RX_NUM), GFP_KERNEL);
+       }
+       ret = himax_parse_criteria_file();
+
+       g_file_path = kzalloc(256 * sizeof(char), GFP_KERNEL);
+       /*memset(g_rslt_data, '\0', 0x1000 * HX_CRITERIA_ITEM * sizeof(char));*/
+       snprintf(g_file_path, 256 * sizeof(char), "%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++) {
+                       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");
+       }
+       kfree(g_file_path);
+}
+
+int himax_chip_self_test(void)
+{
+       uint32_t ret = HX_INSPECT_OK;
+       I("%s:IN\n", __func__);
+
+       ret = himax_self_test_data_init();
+       if (ret != HX_INSPECT_OK) {
+               E("himax_self_test_data_init fail!\n");
+               goto END_FUNC;
+       }
+
+       /*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);
+
+       /*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);
+
+       /*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);
+
+       /*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);
+
+       /*5. Noise Test*/
+       I("[MP_NOISE_TEST_RAW]\n");
+       ret += mpTestFunc(HIMAX_INSPECTION_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);
+
+#ifdef HX_GAP_TEST
+       /*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);
+#endif
+
+#ifdef HX_ACT_IDLE_TEST
+       /*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);
+
+       /*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);
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       himax_press_powerkey();
+
+       /*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);
+
+       /*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);
+
+       /*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);
+
+       /*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);
+
+       himax_press_powerkey();
+#endif
+       /*hx_test_data_pop_out(g_rslt_data, g_file_path);*/
+       g_core_fp.fp_sense_off();
+       himax_set_N_frame(1, HIMAX_INSPECTION_NOISE);
+#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);
+
+END_FUNC:
+       himax_self_test_data_deinit();
+
+
+       I("thp_afe_inspect_OUT = %d \n", ret);
+
+       if (ret != 0)
+               ret = 1;
+
+       I("%s:OUT\n", __func__);
+       return ret;
+}
+
+void himax_inspection_init(void)
+{
+       I("%s: enter, %d \n", __func__, __LINE__);
+       HX_CRITERIA_ITEM = 5;
+#ifdef HX_GAP_TEST
+       HX_CRITERIA_ITEM += 1;
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       HX_CRITERIA_ITEM += 4;
+#endif
+#ifdef HX_ACT_IDLE_TEST
+       HX_CRITERIA_ITEM += 2;
+#endif
+       /* Noise Just one criteria*/
+       HX_CRITERIA_SIZE = HX_CRITERIA_ITEM * 2 - 1;
+       I("There is %d HX_CRITERIA_ITEM and %d HX_CRITERIA_SIZE\n", HX_CRITERIA_ITEM, HX_CRITERIA_SIZE);
+
+       g_rslt_data = kzalloc(0x1000 * HX_CRITERIA_ITEM * sizeof(char), GFP_KERNEL);
+
+       g_core_fp.fp_chip_self_test = himax_chip_self_test;
+
+       return;
+}
diff --git a/drivers/input/touchscreen/hxchipset/himax_inspection.h b/drivers/input/touchscreen/hxchipset/himax_inspection.h
new file mode 100755 (executable)
index 0000000..d8c318d
--- /dev/null
@@ -0,0 +1,238 @@
+
+#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"
+char *g_file_path;
+char *g_rslt_data;
+uint32_t g_rslt_data_len = 0;
+
+
+#define BS_RAWDATANOISE        10
+#define BS_OPENSHORT   0
+
+#ifdef HX_INSPECT_LPWUG_TEST
+#define        BS_LPWUG        1
+#define        BS_LPWUG_dile   1
+#endif
+
+#ifdef HX_ACT_IDLE_TEST
+#define        BS_ACT_IDLE     1
+#endif
+
+/* 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_RAWDATANOISE+1)
+#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
+
+#ifdef HX_ACT_IDLE_TEST
+#define PWD_ACT_IDLE_START             0x22
+#define PWD_ACT_IDLE_END               0x44
+#endif
+
+#ifdef HX_INSPECT_LPWUG_TEST
+#define PWD_LPWUG_START        0x55
+#define PWD_LPWUG_END  0x66
+
+#define PWD_LPWUG_IDLE_START   0x50
+#define PWD_LPWUG_IDLE_END     0x60
+#endif
+
+/*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 */
+int HX_CRITERIA_ITEM;
+int HX_CRITERIA_SIZE;
+
+typedef enum {
+       HIMAX_INSPECTION_OPEN,
+       HIMAX_INSPECTION_MICRO_OPEN,
+       HIMAX_INSPECTION_SHORT,
+       HIMAX_INSPECTION_RAWDATA,
+       HIMAX_INSPECTION_NOISE,
+       HIMAX_INSPECTION_SORTING,
+       HIMAX_INSPECTION_BACK_NORMAL,
+#ifdef HX_GAP_TEST
+       HIMAX_INSPECTION_GAPTEST_RAW,
+#endif
+#ifdef HX_ACT_IDLE_TEST
+       HIMAX_INSPECTION_ACT_IDLE_RAWDATA,
+       HIMAX_INSPECTION_ACT_IDLE_NOISE,
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       HIMAX_INSPECTION_LPWUG_RAWDATA,
+       HIMAX_INSPECTION_LPWUG_NOISE,
+       HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA,
+       HIMAX_INSPECTION_LPWUG_IDLE_NOISE,
+#endif
+} THP_INSPECTION_ENUM;
+
+char *g_himax_inspection_mode[] = {
+       "HIMAX_INSPECTION_OPEN",
+       "HIMAX_INSPECTION_MICRO_OPEN",
+       "HIMAX_INSPECTION_SHORT",
+       "HIMAX_INSPECTION_RAWDATA",
+       "HIMAX_INSPECTION_NOISE",
+       "HIMAX_INSPECTION_SORTING",
+       "HIMAX_INSPECTION_BACK_NORMAL",
+#ifdef HX_GAP_TEST
+       "HIMAX_INSPECTION_GAPTEST_RAW",
+#endif
+#ifdef HX_ACT_IDLE_TEST
+       "HIMAX_INSPECTION_ACT_IDLE_RAWDATA",
+       "HIMAX_INSPECTION_ACT_IDLE_NOISE",
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       "HIMAX_INSPECTION_LPWUG_RAWDATA",
+       "HIMAX_INSPECTION_LPWUG_NOISE",
+       "HIMAX_INSPECTION_LPWUG_IDLE_RAWDATA",
+       "HIMAX_INSPECTION_LPWUG_IDLE_NOISE",
+#endif
+};
+
+/* for criteria */
+int **g_inspection_criteria;
+char *g_hx_inspt_crtra_name[] = {
+       "CRITERIA_RAW_MIN",
+       "CRITERIA_RAW_MAX",
+       "CRITERIA_SHORT_MIN",
+       "CRITERIA_SHORT_MAX",
+       "CRITERIA_OPEN_MIN",
+       "CRITERIA_OPEN_MAX",
+       "CRITERIA_MICRO_OPEN_MIN",
+       "CRITERIA_MICRO_OPEN_MAX",
+       "CRITERIA_NOISE",
+       "CRITERIA_SORT_MIN",
+       "CRITERIA_SORT_MAX",
+#ifdef HX_GAP_TEST
+       "CRITERIA_GAP_RAW_MIN",
+       "CRITERIA_GAP_RAW_MAX",
+#endif
+#ifdef HX_ACT_IDLE_TEST
+       "ACT_IDLE_NOISE_MIN",
+       "ACT_IDLE_NOISE_MAX",
+       "ACT_IDLE_RAWDATA_MIN",
+       "ACT_IDLE_RAWDATA_MAX",
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       "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"
+#endif
+};
+typedef enum {
+       IDX_RAWMIN              = 0,
+       IDX_RAWMAX,
+       IDX_SHORTMIN,
+       IDX_SHORTMAX,
+       IDX_OPENMIN,
+       IDX_OPENMAX,
+       IDX_M_OPENMIN,
+       IDX_M_OPENMAX,
+       IDX_NOISEMAX,
+       IDX_SORTMIN,
+       IDX_SORTMAX,
+#ifdef HX_GAP_TEST
+       IDX_GAP_RAWMAX,
+       IDX_GAP_RAWMIN,
+#endif
+#ifdef HX_ACT_IDLE_TEST
+       IDX_ACT_IDLE_NOISE_MIN,
+       IDX_ACT_IDLE_NOISE_MAX,
+       IDX_ACT_IDLE_RAWDATA_MIN,
+       IDX_ACT_IDLE_RAWDATA_MAX,
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       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,
+#endif
+} HX_CRITERIA_ENUM;
+
+/* Error code of Inspection */
+typedef enum {
+       HX_INSPECT_OK   = 0,               /* OK */
+       HX_INSPECT_ESPI = 1 << 1,        /* SPI communication error */
+       HX_INSPECT_ERAW = 2 << 1,        /* Raw data error */
+       HX_INSPECT_ENOISE = 3 << 1,        /* Noise error */
+       HX_INSPECT_EOPEN = 4 << 1,        /* Sensor open error */
+       HX_INSPECT_EMOPEN = 5 << 1,        /* Sensor micro open error */
+       HX_INSPECT_ESHORT = 6 << 1,        /* Sensor short error */
+#ifdef HX_GAP_TEST
+       HX_INSPECT_EGAP_RAW = 8 << 1,        /* Sensor short error */
+#endif
+#ifdef HX_ACT_IDLE_TEST
+       HX_INSPECT_EACT_IDLE_RAW = 9 << 1,                 /* ACT_IDLE RAW ERROR */
+       HX_INSPECT_EACT_IDLE_NOISE = 10 << 1,              /* ACT_IDLE NOISE ERROR */
+#endif
+#ifdef HX_INSPECT_LPWUG_TEST
+       HX_INSPECT_ELPWUG_RAW = 11 << 1,                   /* LPWUG RAW ERROR */
+       HX_INSPECT_ELPWUG_NOISE = 12 << 1,                 /* LPWUG NOISE ERROR */
+       HX_INSPECT_ELPWUG_IDLE_RAW = 13 << 1,              /* LPWUG IDLE RAW ERROR */
+       HX_INSPECT_ELPWUG_IDLE_NOISE = 14 << 1,            /* LPWUG IDLE NOISE ERROR */
+#endif
+       HX_INSPECT_EFILE = 15 << 1,                                     /*Criteria file error*/
+       HX_INSPECT_EOTHER = 16 << 1,    /* All other errors */
+} HX_INSPECT_ERR_ENUM;
diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.c b/drivers/input/touchscreen/hxchipset/himax_platform.c
new file mode 100755 (executable)
index 0000000..696b0b0
--- /dev/null
@@ -0,0 +1,804 @@
+/*  Himax Android Driver Sample Code for QCT platform
+
+    Copyright (C) 2018 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 = 0;
+int irq_enable_count = 0;
+
+extern struct himax_ic_data *ic_data;
+extern struct himax_ts_data *private_ts;
+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);
+
+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;
+       } else {
+               while ((pp = of_get_next_child(node, pp)))
+                       cnt++;
+
+               if (!cnt)
+                       return;
+
+               vk = kzalloc(cnt * (sizeof *vk), 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, ic_type_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];
+               pdata->abs_y_min = coords[2], pdata->abs_y_max = coords[3];
+               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);
+
+       rc = of_property_read_u32(dt, "himax,ic-type", &ic_type_data);
+
+       if (rc && (rc != -EINVAL)) {
+               D("[%s][%d]:Fail to read himax,ic-type %d\n", __func__, __LINE__, rc);
+               ic_data->ic_type_val = 0;
+       } else {
+               I("[%s][%d]:Read driver IC type = %d, return %d\n", __func__, __LINE__, ic_type_data, rc);
+               ic_data->ic_type_val = ic_type_data;
+       }
+
+       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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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++;
+               private_ts->irq_enabled = 1;
+       } else if (enable == 0 && irq_enable_count == 1) {
+               disable_irq_nosync(irqnum);
+               irq_enable_count--;
+               private_ts->irq_enabled = 0;
+       }
+
+       I("irq_enable_count = %d\n", irq_enable_count);
+}
+
+#ifdef HX_RST_PIN_FUNC
+void himax_rst_gpio_set(int pinnum, uint8_t value)
+{
+       gpio_direction_output(pinnum, value);
+}
+#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_ana);
+               return retval;
+       }
+
+       return 0;
+};
+
+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);
+               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_gpio_reset_req;
+       }
+
+       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_power_on;
+               }
+
+               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_req;
+               }
+
+               client->irq = gpio_to_irq(pdata->gpio_irq);
+       } else {
+               E("irq gpio not provided\n");
+               goto err_power_on;
+       }
+
+       msleep(20);
+#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_gpio_irq_req;
+               }
+       }
+
+#endif
+       return 0;
+err_gpio_irq_req:
+
+       if (gpio_is_valid(pdata->gpio_irq))
+               gpio_free(pdata->gpio_irq);
+
+err_power_on:
+       himax_power_on(pdata, false);
+err_gpio_reset_req:
+#ifdef HX_RST_PIN_FUNC
+
+       if (gpio_is_valid(pdata->gpio_reset))
+               gpio_free(pdata->gpio_reset);
+
+err_regulator_on:
+#endif
+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;
+       struct pinctrl *pinctrl_vdd;
+#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__);
+                       return error;
+               }
+       }
+
+#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_3v3_en_request;
+               }
+
+               gpio_direction_output(pdata->gpio_3v3_en, 1);
+               I("3v3_en 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_irq_request;
+               }
+
+               error = gpio_direction_input(pdata->gpio_irq);
+
+               if (error) {
+                       E("unable to set direction for gpio [%d]\n", pdata->gpio_irq);
+                       goto err_irq_set_direction;
+               }
+
+               client->irq = gpio_to_irq(pdata->gpio_irq);
+       } else {
+               E("irq gpio not provided\n");
+               goto err_irq_request;
+       }
+       pinctrl_vdd = devm_pinctrl_get_select(&client->dev, "on_state");
+       if (IS_ERR(pinctrl_vdd))
+               E("Failed to on vdd GPIO\n");
+#ifdef HX_RST_PIN_FUNC
+
+       if (pdata->gpio_reset >= 0) {
+               error = gpio_direction_output(pdata->gpio_reset, 0);
+               if (error) {
+                       E("unable to set direction for gpio [%d]\n",
+                               pdata->gpio_reset);
+                       goto err_rst_set_value;
+                       }
+               msleep(20);
+               error = gpio_direction_output(pdata->gpio_reset, 1);
+
+               if (error) {
+                       E("unable to set direction for gpio [%d]\n",
+                         pdata->gpio_reset);
+                       goto err_rst_set_value;
+               }
+       }
+
+#endif
+       return 0;
+#ifdef HX_RST_PIN_FUNC
+       err_rst_set_value:
+#endif
+       err_irq_set_direction:
+       if (gpio_is_valid(pdata->gpio_irq))
+               gpio_free(pdata->gpio_irq);
+       err_irq_request:
+       if (gpio_is_valid(pdata->gpio_3v3_en))
+               gpio_free(pdata->gpio_3v3_en);
+       err_3v3_en_request:
+       if (gpio_is_valid(pdata->gpio_reset))
+               gpio_free(pdata->gpio_reset);
+
+       return error;
+}
+
+#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) {/*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 qpio: %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;
+}
+
+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)
+{
+       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 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");
+       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/hxchipset/himax_platform.h b/drivers/input/touchscreen/hxchipset/himax_platform.h
new file mode 100755 (executable)
index 0000000..7694a4c
--- /dev/null
@@ -0,0 +1,130 @@
+/*  Himax Android Driver Sample Code for QCT platform
+
+    Copyright (C) 2018 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 <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/gpio.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#if defined(CONFIG_HMX_DB)
+       #include <linux/regulator/consumer.h>
+#endif
+
+#define HIMAX_I2C_RETRY_TIMES 10
+
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+#define D(x...) printk("[HXTP] " x)
+#define I(x...) printk("[HXTP] " x)
+#define W(x...) printk("[HXTP][WARNING] " x)
+#define E(x...) printk("[HXTP][ERROR] " x)
+#define DIF(x...) \
+do { \
+       if (debug_flag) \
+               printk("[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 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);
+extern uint8_t himax_int_gpio_read(int pinnum);
+
+extern int himax_gpio_power_config(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
+
+#endif
index 8e1b4c72b45bbafbc3e18ac270c1886a71dd8a17..1b770f568f2192e0c1b930e601cfc171e5c739bf 100755 (executable)
@@ -1200,6 +1200,12 @@ static int32_t nvt_ts_probe(struct i2c_client *client, const struct i2c_device_i
 #endif
 
        NVT_LOG("start\n");
+       //---check i2c func.---
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               NVT_ERR("i2c_check_functionality failed. (no I2C_FUNC_I2C)\n");
+               ret = -ENODEV;
+               goto err_check_functionality_failed;
+       }
 
        ts = kmalloc(sizeof(struct nvt_ts_data), GFP_KERNEL);
        if (ts == NULL) {
@@ -1220,13 +1226,6 @@ static int32_t nvt_ts_probe(struct i2c_client *client, const struct i2c_device_i
                goto err_gpio_config_failed;
        }
 
-       //---check i2c func.---
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               NVT_ERR("i2c_check_functionality failed. (no I2C_FUNC_I2C)\n");
-               ret = -ENODEV;
-               goto err_check_functionality_failed;
-       }
-
        // need 10ms delay after POR(power on reset)
        msleep(10);
 
@@ -1439,11 +1438,18 @@ err_input_dev_alloc_failed:
 err_create_nvt_wq_failed:
        mutex_destroy(&ts->lock);
 err_chipvertrim_failed:
-err_check_functionality_failed:
-       gpio_free(ts->irq_gpio);
+#if NVT_TOUCH_SUPPORT_HW_RST
+       if (gpio_is_valid(ts->reset_gpio))
+               gpio_free(ts->reset_gpio);
+#endif
+       if (gpio_is_valid(ts->irq_gpio))
+               gpio_free(ts->irq_gpio);
 err_gpio_config_failed:
        i2c_set_clientdata(client, NULL);
        kfree(ts);
+err_check_functionality_failed:
+
+       NVT_LOG("exit %s abnormal end\n",__func__);
        return ret;
 }