BSP: enable nt36xxx touch driver
authorlijilai <lijilai@huaqin.com>
Tue, 10 Jul 2018 06:08:24 +0000 (14:08 +0800)
committerCosmin Tanislav <demonsingur@gmail.com>
Mon, 22 Apr 2024 17:23:41 +0000 (20:23 +0300)
[9609][WING] touch: enable nt36xxx touch driver

Bug:HQ00000000

Workaround:no

Change-Id: I57acc6af84c0aa2391636247aba1d0815956a0ac
Signed-off-by: Youngmin Nam <youngmin.nam@samsung.com>
20 files changed:
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/nt36672a/Kconfig [deleted file]
drivers/input/touchscreen/nt36672a/Makefile [deleted file]
drivers/input/touchscreen/nt36672a/nt36xxx.c [deleted file]
drivers/input/touchscreen/nt36672a/nt36xxx.h [deleted file]
drivers/input/touchscreen/nt36672a/nt36xxx_ext_proc.c [deleted file]
drivers/input/touchscreen/nt36672a/nt36xxx_fw_update.c [deleted file]
drivers/input/touchscreen/nt36672a/nt36xxx_mem_map.h [deleted file]
drivers/input/touchscreen/nt36672a/nt36xxx_mp_ctrlram.c [deleted file]
drivers/input/touchscreen/nt36672a/nt36xxx_mp_ctrlram.h [deleted file]
drivers/input/touchscreen/nt36xxx/Kconfig [new file with mode: 0755]
drivers/input/touchscreen/nt36xxx/Makefile [new file with mode: 0755]
drivers/input/touchscreen/nt36xxx/nt36xxx.c [new file with mode: 0755]
drivers/input/touchscreen/nt36xxx/nt36xxx.h [new file with mode: 0755]
drivers/input/touchscreen/nt36xxx/nt36xxx_ext_proc.c [new file with mode: 0755]
drivers/input/touchscreen/nt36xxx/nt36xxx_fw_update.c [new file with mode: 0755]
drivers/input/touchscreen/nt36xxx/nt36xxx_mem_map.h [new file with mode: 0755]
drivers/input/touchscreen/nt36xxx/nt36xxx_mp_ctrlram.c [new file with mode: 0755]
drivers/input/touchscreen/nt36xxx/nt36xxx_mp_ctrlram.h [new file with mode: 0755]

index a382f8ac3d71c06e7684a48cbffef37f34c94020..4d155f71e352a4400325dfcb6036249529f533d2 100644 (file)
@@ -1247,4 +1247,5 @@ config TOUCHSCREEN_ROHM_BU21023
          module will be called bu21023_ts.
 
 source "drivers/input/touchscreen/synaptics_dsx/Kconfig"
+source "drivers/input/touchscreen/nt36xxx/Kconfig"
 endif
index 8f7038705ae058ea9a06a11779dd3e022f9463ef..6276fa2df365a51aff4eefad7f0a29cccc0909fb 100644 (file)
@@ -105,3 +105,4 @@ obj-$(CONFIG_TOUCHSCREEN_ZFORCE)    += zforce_ts.o
 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/
diff --git a/drivers/input/touchscreen/nt36672a/Kconfig b/drivers/input/touchscreen/nt36672a/Kconfig
deleted file mode 100755 (executable)
index ad07462..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#
-# Novatek NT36xxx touchscreen driver configuration
-#
-config TOUCHSCREEN_NT36xxx
-       bool "Novatek NT36xxx"
-       default y
-       help
-         Say Y here if you have a Novatek NT36xxx touchscreen connected
-         to your system.
-
-         If unsure, say N.
diff --git a/drivers/input/touchscreen/nt36672a/Makefile b/drivers/input/touchscreen/nt36672a/Makefile
deleted file mode 100755 (executable)
index 88c95a9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the Novatek NT36xxx touchscreen driver.
-#
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_TOUCHSCREEN_NT36xxx) += nt36xxx.o nt36xxx_fw_update.o nt36xxx_ext_proc.o nt36xxx_mp_ctrlram.o
diff --git a/drivers/input/touchscreen/nt36672a/nt36xxx.c b/drivers/input/touchscreen/nt36672a/nt36xxx.c
deleted file mode 100755 (executable)
index 2103fde..0000000
+++ /dev/null
@@ -1,1760 +0,0 @@
-/*
- * Copyright (C) 2010 - 2017 Novatek, Inc.
- *
- * $Revision: 22971 $
- * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-#include <linux/init.h>
-#include <linux/cdev.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/miscdevice.h>
-#include <linux/platform_device.h>
-#include <linux/gfp.h>
-#include <linux/slab.h>
-#include <linux/miscdevice.h>
-#include <linux/list.h>
-#include <linux/device.h>
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/proc_fs.h>
-#include <asm/uaccess.h>
-#include <linux/input/mt.h>
-#include <linux/wakelock.h>
-#include <linux/of_gpio.h>
-#include <linux/of_irq.h>
-
-#if defined(CONFIG_HQ_DEV_INFO)
-#include <linux/dev_info.h>
-#endif
-
-#if defined(CONFIG_FB)
-#include <linux/notifier.h>
-#include <linux/fb.h>
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-#include <linux/earlysuspend.h>
-#endif
-
-#include "nt36xxx.h"
-
-#if NVT_TOUCH_ESD_PROTECT
-#include <linux/jiffies.h>
-
-static struct delayed_work nvt_esd_check_work;
-static struct workqueue_struct *nvt_esd_check_wq;
-static unsigned long irq_timer;
-uint8_t esd_check = false;
-uint8_t esd_retry = 0;
-uint8_t esd_retry_max = 5;
-#endif
-
-#if NVT_TOUCH_EXT_PROC
-extern int32_t nvt_extra_proc_init(void);
-#endif
-
-#if NVT_TOUCH_FW
-extern int32_t nvt_fw_sysfs_init(void);
-extern int32_t nvt_fw_sysfs_deinit(void);
-#endif
-
-#if NVT_TOUCH_MP
-extern int32_t nvt_mp_proc_init(void);
-#endif
-
-struct nvt_ts_data *ts;
-
-static struct workqueue_struct *nvt_wq;
-
-#if BOOT_UPDATE_FIRMWARE
-static struct workqueue_struct *nvt_fwu_wq;
-extern void Boot_Update_Firmware(struct work_struct *work);
-#endif
-
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-static void nvt_ts_early_suspend(struct early_suspend *h);
-static void nvt_ts_late_resume(struct early_suspend *h);
-#endif
-
-#if TOUCH_KEY_NUM > 0
-const uint16_t touch_key_array[TOUCH_KEY_NUM] = {
-       KEY_BACK,
-       KEY_HOME,
-       KEY_MENU
-};
-#endif
-
-#if WAKEUP_GESTURE
-const uint16_t gesture_key_array[] = {
-       KEY_POWER,  //GESTURE_WORD_C
-       KEY_POWER,  //GESTURE_WORD_W
-       KEY_POWER,  //GESTURE_WORD_V
-       KEY_POWER,  //GESTURE_DOUBLE_CLICK
-       KEY_POWER,  //GESTURE_WORD_Z
-       KEY_POWER,  //GESTURE_WORD_M
-       KEY_POWER,  //GESTURE_WORD_O
-       KEY_POWER,  //GESTURE_WORD_e
-       KEY_POWER,  //GESTURE_WORD_S
-       KEY_POWER,  //GESTURE_SLIDE_UP
-       KEY_POWER,  //GESTURE_SLIDE_DOWN
-       KEY_POWER,  //GESTURE_SLIDE_LEFT
-       KEY_POWER,  //GESTURE_SLIDE_RIGHT
-};
-#endif
-
-static uint8_t bTouchIsAwake = 0;
-
-/*******************************************************
-Description:
-       Novatek touchscreen i2c read function.
-
-return:
-       Executive outcomes. 2---succeed. -5---I/O error
-*******************************************************/
-int32_t CTP_I2C_READ(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len)
-{
-       struct i2c_msg msgs[2];
-       int32_t ret = -1;
-       int32_t retries = 0;
-
-       msgs[0].flags = !I2C_M_RD;
-       msgs[0].addr  = address;
-       msgs[0].len   = 1;
-       msgs[0].buf   = &buf[0];
-
-       msgs[1].flags = I2C_M_RD;
-       msgs[1].addr  = address;
-       msgs[1].len   = len - 1;
-       msgs[1].buf   = &buf[1];
-
-       while (retries < 5) {
-               ret = i2c_transfer(client->adapter, msgs, 2);
-               if (ret == 2)   break;
-               retries++;
-       }
-
-       if (unlikely(retries == 5)) {
-               NVT_ERR("error, ret=%d\n", ret);
-               ret = -EIO;
-       }
-
-       return ret;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen i2c write function.
-
-return:
-       Executive outcomes. 1---succeed. -5---I/O error
-*******************************************************/
-int32_t CTP_I2C_WRITE(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len)
-{
-       struct i2c_msg msg;
-       int32_t ret = -1;
-       int32_t retries = 0;
-
-       msg.flags = !I2C_M_RD;
-       msg.addr  = address;
-       msg.len   = len;
-       msg.buf   = buf;
-
-       while (retries < 5) {
-               ret = i2c_transfer(client->adapter, &msg, 1);
-               if (ret == 1)   break;
-               retries++;
-       }
-
-       if (unlikely(retries == 5)) {
-               NVT_ERR("error, ret=%d\n", ret);
-               ret = -EIO;
-       }
-
-       return ret;
-}
-
-
-/*******************************************************
-Description:
-       Novatek touchscreen reset MCU then into idle mode
-    function.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_sw_reset_idle(void)
-{
-       uint8_t buf[4]={0};
-
-       /* ---write i2c cmds to reset idle--- */
-       buf[0]=0x00;
-       buf[1]=0xA5;
-       CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-
-       msleep(15);
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen reset MCU (boot) function.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_bootloader_reset(void)
-{
-       uint8_t buf[8] = {0};
-       NVT_ERR("xlixiang---enter-%s\n", __func__);
-       //---write i2c cmds to reset---
-       buf[0] = 0x00;
-       buf[1] = 0x69;
-       CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-
-       // need 35ms delay after bootloader reset
-       msleep(35);
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen clear FW status function.
-
-return:
-       Executive outcomes. 0---succeed. -1---fail.
-*******************************************************/
-int32_t nvt_clear_fw_status(void)
-{
-       uint8_t buf[8] = {0};
-       int32_t i = 0;
-       const int32_t retry = 20;
-
-       for (i = 0; i < retry; i++) {
-               //---set xdata index to EVENT BUF ADDR---
-               buf[0] = 0xFF;
-               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-               //---clear fw status---
-               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
-               buf[1] = 0x00;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
-
-               //---read fw status---
-               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
-               buf[1] = 0xFF;
-               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
-
-               if (buf[1] == 0x00)
-                       break;
-
-               msleep(10);
-       }
-
-       if (i >= retry) {
-               NVT_ERR("failed, i=%d, buf[1]=0x%02X\n", i, buf[1]);
-               return -1;
-       } else {
-               return 0;
-       }
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen check FW status function.
-
-return:
-       Executive outcomes. 0---succeed. -1---failed.
-*******************************************************/
-int32_t nvt_check_fw_status(void)
-{
-       uint8_t buf[8] = {0};
-       int32_t i = 0;
-       const int32_t retry = 50;
-
-       for (i = 0; i < retry; i++) {
-               //---set xdata index to EVENT BUF ADDR---
-               buf[0] = 0xFF;
-               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-               //---read fw status---
-               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
-               buf[1] = 0x00;
-               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
-
-               if ((buf[1] & 0xF0) == 0xA0)
-                       break;
-
-               msleep(10);
-       }
-
-       if (i >= retry) {
-               NVT_ERR("failed, i=%d, buf[1]=0x%02X\n", i, buf[1]);
-               return -1;
-       } else {
-               return 0;
-       }
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen check FW reset state function.
-
-return:
-       Executive outcomes. 0---succeed. -1---failed.
-*******************************************************/
-int32_t nvt_check_fw_reset_state(RST_COMPLETE_STATE check_reset_state)
-{
-       uint8_t buf[8] = {0};
-       int32_t ret = 0;
-       int32_t retry = 0;
-       NVT_ERR("xlixiang---enter-%s\n", __func__);
-       while (1) {
-               msleep(10);
-               //---read reset state---
-               buf[0] = EVENT_MAP_RESET_COMPLETE;
-               buf[1] = 0x00;
-               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 6);
-
-               if ((buf[1] >= check_reset_state) && (buf[1] <= RESET_STATE_MAX)) {
-                       ret = 0;
-                       break;
-               }
-       
-               retry++;
-               if (check_reset_state <= RESET_STATE_REK) {
-                       if( unlikely(retry > 50)) {
-                               NVT_ERR("error,retry = %d,buf[1] = 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n",retry,buf[1],buf[2], buf[3], buf[4], buf[5]);  
-                               ret = -1;
-                               break;                  
-                       }               
-               }
-               else 
-               {
-                       if(unlikely(retry > 100)) {
-                               NVT_ERR("error, retry=%d, buf[1]=0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", retry, buf[1], buf[2], buf[3], buf[4], buf[5]);
-                               ret = -1;
-                               break;
-                       }
-               }
-       }
-
-       return ret;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen get novatek project id information
-       function.
-
-return:
-       Executive outcomes. 0---success. -1---fail.
-*******************************************************/
-int32_t nvt_read_pid(void)
-{
-       uint8_t buf[3] = {0};
-       int32_t ret = 0;
-
-       //---set xdata index to EVENT BUF ADDR---
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-       //---read project id---
-       buf[0] = EVENT_MAP_PROJECTID;
-       buf[1] = 0x00;
-       buf[2] = 0x00;
-       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 3);
-
-       ts->nvt_pid = (buf[2] << 8) + buf[1];
-
-       NVT_LOG("PID=%04X\n", ts->nvt_pid);
-
-       return ret;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen get firmware related information
-       function.
-
-return:
-       Executive outcomes. 0---success. -1---fail.
-*******************************************************/
-int32_t nvt_get_fw_info(void)
-{
-       uint8_t buf[64] = {0};
-       uint32_t retry_count = 0;
-       int32_t ret = 0;
-
-info_retry:
-       //---set xdata index to EVENT BUF ADDR---
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-       //---read fw info---
-       buf[0] = EVENT_MAP_FWINFO;
-       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 17);
-       ts->fw_ver = buf[1];
-       ts->x_num = buf[3];
-       ts->y_num = buf[4];
-       ts->abs_x_max = (uint16_t)((buf[5] << 8) | buf[6]);
-       ts->abs_y_max = (uint16_t)((buf[7] << 8) | buf[8]);
-       ts->max_button_num = buf[11];
-
-       //---clear x_num, y_num if fw info is broken---
-       if ((buf[1] + buf[2]) != 0xFF) {
-               NVT_ERR("FW info is broken! fw_ver=0x%02X, ~fw_ver=0x%02X\n", buf[1], buf[2]);
-               ts->fw_ver = 0;
-               ts->x_num = 18;
-               ts->y_num = 32;
-               ts->abs_x_max = TOUCH_DEFAULT_MAX_WIDTH;
-               ts->abs_y_max = TOUCH_DEFAULT_MAX_HEIGHT;
-               ts->max_button_num = TOUCH_KEY_NUM;
-
-               if(retry_count < 3) {
-                       retry_count++;
-                       NVT_ERR("retry_count=%d\n", retry_count);
-                       goto info_retry;
-               } else {
-                       NVT_ERR("Set default fw_ver=%d, x_num=%d, y_num=%d, \
-                                       abs_x_max=%d, abs_y_max=%d, max_button_num=%d!\n",
-                                       ts->fw_ver, ts->x_num, ts->y_num,
-                                       ts->abs_x_max, ts->abs_y_max, ts->max_button_num);
-                       ret = -1;
-               }
-       } else {
-               ret = 0;
-       }
-
-       //---Get Novatek PID---
-       nvt_read_pid();
-
-       return ret;
-}
-
-/*******************************************************
-  Create Device Node (Proc Entry)
-*******************************************************/
-#if NVT_TOUCH_PROC
-static struct proc_dir_entry *NVT_proc_entry;
-#define DEVICE_NAME    "NVTflash"
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/NVTflash read function.
-
-return:
-       Executive outcomes. 2---succeed. -5,-14---failed.
-*******************************************************/
-static ssize_t nvt_flash_read(struct file *file, char __user *buff, size_t count, loff_t *offp)
-{
-       uint8_t str[68] = {0};
-       int32_t ret = -1;
-       int32_t retries = 0;
-       int8_t i2c_wr = 0;
-
-       if (count > sizeof(str)) {
-               NVT_ERR("error count=%zu\n", count);
-               return -EFAULT;
-       }
-
-       if (copy_from_user(str, buff, count)) {
-               NVT_ERR("copy from user error\n");
-               return -EFAULT;
-       }
-#if NVT_TOUCH_ESD_PROTECT
-       /*
-        * stop esd check work to avoid case that 0x77 report righ after here to enable esd check again
-        * finally lead to trigger esd recovery bootloader reset
-        */
-       cancel_delayed_work_sync(&nvt_esd_check_work);
-       nvt_esd_check_enable(false);
-#endif
-
-       i2c_wr = str[0] >> 7;
-
-       if (i2c_wr == 0) {      //I2C write
-               while (retries < 20) {
-                       ret = CTP_I2C_WRITE(ts->client, (str[0] & 0x7F), &str[2], str[1]);
-                       if (ret == 1)
-                               break;
-                       else
-                               NVT_ERR("error, retries=%d, ret=%d\n", retries, ret);
-
-                       retries++;
-               }
-
-               if (unlikely(retries == 20)) {
-                       NVT_ERR("error, ret = %d\n", ret);
-                       return -EIO;
-               }
-
-               return ret;
-       } else if (i2c_wr == 1) {       //I2C read
-               while (retries < 20) {
-                       ret = CTP_I2C_READ(ts->client, (str[0] & 0x7F), &str[2], str[1]);
-                       if (ret == 2)
-                               break;
-                       else
-                               NVT_ERR("error, retries=%d, ret=%d\n", retries, ret);
-
-                       retries++;
-               }
-
-               // copy buff to user if i2c transfer
-               if (retries < 20) {
-                       if (copy_to_user(buff, str, count))
-                               return -EFAULT;
-               }
-
-               if (unlikely(retries == 20)) {
-                       NVT_ERR("error, ret = %d\n", ret);
-                       return -EIO;
-               }
-
-               return ret;
-       } else {
-               NVT_ERR("Call error, str[0]=%d\n", str[0]);
-               return -EFAULT;
-       }
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/NVTflash open function.
-
-return:
-       Executive outcomes. 0---succeed. -12---failed.
-*******************************************************/
-static int32_t nvt_flash_open(struct inode *inode, struct file *file)
-{
-       struct nvt_flash_data *dev;
-
-       dev = kmalloc(sizeof(struct nvt_flash_data), GFP_KERNEL);
-       if (dev == NULL) {
-               NVT_ERR("Failed to allocate memory for nvt flash data\n");
-               return -ENOMEM;
-       }
-
-       rwlock_init(&dev->lock);
-       file->private_data = dev;
-
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/NVTflash close function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t nvt_flash_close(struct inode *inode, struct file *file)
-{
-       struct nvt_flash_data *dev = file->private_data;
-
-       if (dev)
-               kfree(dev);
-
-       return 0;
-}
-
-static const struct file_operations nvt_flash_fops = {
-       .owner = THIS_MODULE,
-       .open = nvt_flash_open,
-       .release = nvt_flash_close,
-       .read = nvt_flash_read,
-};
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/NVTflash initial function.
-
-return:
-       Executive outcomes. 0---succeed. -12---failed.
-*******************************************************/
-static int32_t nvt_flash_proc_init(void)
-{
-       NVT_proc_entry = proc_create(DEVICE_NAME, 0444, NULL,&nvt_flash_fops);
-       if (NVT_proc_entry == NULL) {
-               NVT_ERR("Failed!\n");
-               return -ENOMEM;
-       } else {
-               NVT_LOG("Succeeded!\n");
-       }
-
-       NVT_LOG("============================================================\n");
-       NVT_LOG("Create /proc/NVTflash\n");
-       NVT_LOG("============================================================\n");
-
-       return 0;
-}
-#endif
-
-#if WAKEUP_GESTURE
-#define GESTURE_WORD_C                 12
-#define GESTURE_WORD_W                 13
-#define GESTURE_WORD_V                 14
-#define GESTURE_DOUBLE_CLICK   15
-#define GESTURE_WORD_Z                 16
-#define GESTURE_WORD_M                 17
-#define GESTURE_WORD_O                 18
-#define GESTURE_WORD_e                 19
-#define GESTURE_WORD_S                 20
-#define GESTURE_SLIDE_UP               21
-#define GESTURE_SLIDE_DOWN             22
-#define GESTURE_SLIDE_LEFT             23
-#define GESTURE_SLIDE_RIGHT            24
-/* customized gesture id */
-#define DATA_PROTOCOL           30
-
-/* function page definition */
-#define FUNCPAGE_GESTURE         1
-
-static struct wake_lock gestrue_wakelock;
-
-/*******************************************************
-Description:
-       Novatek touchscreen wake up gesture key report function.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_ts_wakeup_gesture_report(uint8_t gesture_id, uint8_t *data)
-{
-       uint32_t keycode = 0;
-       uint8_t func_type = data[2];
-       uint8_t func_id = data[3];
-
-       /* support fw specifal data protocol */
-       if ((gesture_id == DATA_PROTOCOL) && (func_type == FUNCPAGE_GESTURE)) {
-               gesture_id = func_id;
-       } else if (gesture_id > DATA_PROTOCOL) {
-               NVT_ERR("gesture_id %d is invalid, func_type=%d, func_id=%d\n", gesture_id, func_type, func_id);
-               return;
-       }
-
-       NVT_LOG("gesture_id = %d\n", gesture_id);
-
-       switch (gesture_id) {
-               case GESTURE_WORD_C:
-                       NVT_LOG("Gesture : Word-C.\n");
-                       keycode = gesture_key_array[0];
-                       break;
-               case GESTURE_WORD_W:
-                       NVT_LOG("Gesture : Word-W.\n");
-                       keycode = gesture_key_array[1];
-                       break;
-               case GESTURE_WORD_V:
-                       NVT_LOG("Gesture : Word-V.\n");
-                       keycode = gesture_key_array[2];
-                       break;
-               case GESTURE_DOUBLE_CLICK:
-                       NVT_LOG("Gesture : Double Click.\n");
-                       keycode = gesture_key_array[3];
-                       break;
-               case GESTURE_WORD_Z:
-                       NVT_LOG("Gesture : Word-Z.\n");
-                       keycode = gesture_key_array[4];
-                       break;
-               case GESTURE_WORD_M:
-                       NVT_LOG("Gesture : Word-M.\n");
-                       keycode = gesture_key_array[5];
-                       break;
-               case GESTURE_WORD_O:
-                       NVT_LOG("Gesture : Word-O.\n");
-                       keycode = gesture_key_array[6];
-                       break;
-               case GESTURE_WORD_e:
-                       NVT_LOG("Gesture : Word-e.\n");
-                       keycode = gesture_key_array[7];
-                       break;
-               case GESTURE_WORD_S:
-                       NVT_LOG("Gesture : Word-S.\n");
-                       keycode = gesture_key_array[8];
-                       break;
-               case GESTURE_SLIDE_UP:
-                       NVT_LOG("Gesture : Slide UP.\n");
-                       keycode = gesture_key_array[9];
-                       break;
-               case GESTURE_SLIDE_DOWN:
-                       NVT_LOG("Gesture : Slide DOWN.\n");
-                       keycode = gesture_key_array[10];
-                       break;
-               case GESTURE_SLIDE_LEFT:
-                       NVT_LOG("Gesture : Slide LEFT.\n");
-                       keycode = gesture_key_array[11];
-                       break;
-               case GESTURE_SLIDE_RIGHT:
-                       NVT_LOG("Gesture : Slide RIGHT.\n");
-                       keycode = gesture_key_array[12];
-                       break;
-               default:
-                       break;
-       }
-
-       if (keycode > 0) {
-               input_report_key(ts->input_dev, keycode, 1);
-               input_sync(ts->input_dev);
-               input_report_key(ts->input_dev, keycode, 0);
-               input_sync(ts->input_dev);
-       }
-}
-#endif
-
-/*******************************************************
-Description:
-       Novatek touchscreen parse device tree function.
-
-return:
-       n.a.
-*******************************************************/
-#ifdef CONFIG_OF
-static void nvt_parse_dt(struct device *dev)
-{
-       struct device_node *np = dev->of_node;
-
-#if NVT_TOUCH_SUPPORT_HW_RST
-       ts->reset_gpio = of_get_named_gpio_flags(np, "novatek,reset-gpio", 0, &ts->reset_flags);
-       NVT_LOG("novatek,reset-gpio=%d\n", ts->reset_gpio);
-#endif
-       ts->irq_gpio = of_get_named_gpio_flags(np, "novatek,irq-gpio", 0, &ts->irq_flags);
-       NVT_LOG("novatek,irq-gpio=%d\n", ts->irq_gpio);
-
-}
-#else
-static void nvt_parse_dt(struct device *dev)
-{
-#if NVT_TOUCH_SUPPORT_HW_RST
-       ts->reset_gpio = NVTTOUCH_RST_PIN;
-#endif
-       ts->irq_gpio = NVTTOUCH_INT_PIN;
-}
-#endif
-
-/*******************************************************
-Description:
-       Novatek touchscreen config and request gpio
-
-return:
-       Executive outcomes. 0---succeed. not 0---failed.
-*******************************************************/
-static int nvt_gpio_config(struct nvt_ts_data *ts)
-{
-       int32_t ret = 0;
-
-#if NVT_TOUCH_SUPPORT_HW_RST
-       /* request RST-pin (Output/High) */
-       if (gpio_is_valid(ts->reset_gpio)) {
-               ret = gpio_request_one(ts->reset_gpio, GPIOF_OUT_INIT_HIGH, "NVT-tp-rst");
-               if (ret) {
-                       NVT_ERR("Failed to request NVT-tp-rst GPIO\n");
-                       goto err_request_reset_gpio;
-               }
-       }
-#endif
-       /* request INT-pin (Input) */
-       if (gpio_is_valid(ts->irq_gpio)) {
-               ret = gpio_request_one(ts->irq_gpio, GPIOF_IN, "NVT-int");
-               if (ret) {
-                       NVT_ERR("Failed to request NVT-int GPIO\n");
-                       goto err_request_irq_gpio;
-               }
-       }
-
-       return ret;
-
-err_request_irq_gpio:
-#if NVT_TOUCH_SUPPORT_HW_RST
-       gpio_free(ts->reset_gpio);
-err_request_reset_gpio:
-#endif
-       return ret;
-}
-
-#if NVT_TOUCH_ESD_PROTECT
-void nvt_esd_check_enable(uint8_t enable)
-{
-       /* enable/disable esd check flag */
-       esd_check = enable;
-       /* update interrupt timer */
-       irq_timer = jiffies;
-       /* clear esd_retry counter, if protect function is enabled */
-       esd_retry = enable ? 0 : esd_retry;
-}
-
-static uint8_t nvt_fw_recovery(uint8_t *point_data)
-{
-       uint8_t i = 0;
-       uint8_t detected = true;
-
-       /* check pattern */
-       for (i = 1 ; i < 7 ; i++) {
-               if (point_data[i] != 0x77) {
-                       detected = false;
-                       break;
-               }
-       }
-
-       return detected;
-}
-
-static void nvt_esd_check_func(struct work_struct *work)
-{
-       unsigned int timer = jiffies_to_msecs(jiffies - irq_timer);
-
-
-       if (esd_retry >= esd_retry_max)
-               nvt_esd_check_enable(false);
-
-       if ((timer > NVT_TOUCH_ESD_CHECK_PERIOD) && esd_check) {
-               NVT_ERR("do ESD recovery, timer = %d, retry = %d\n", timer, esd_retry);
-               printk("do ESD recovery, timer = %d, retry = %d\n", timer, esd_retry);
-               /* do esd recovery, bootloader reset */
-               nvt_bootloader_reset();
-               /* update interrupt timer */
-               irq_timer = jiffies;
-               /* update esd_retry counter */
-               esd_retry++;
-       }
-
-       queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work,
-                       msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD));
-}
-#endif
-
-#define POINT_DATA_LEN 65
-/*******************************************************
-Description:
-       Novatek touchscreen work function.
-
-return:
-       n.a.
-*******************************************************/
-static void nvt_ts_work_func(struct work_struct *work)
-{
-       int32_t ret = -1;
-       uint8_t point_data[POINT_DATA_LEN + 1] = {0};
-       uint32_t position = 0;
-       uint32_t input_x = 0;
-       uint32_t input_y = 0;
-       uint32_t input_w = 0;
-       uint32_t input_p = 0;
-       uint8_t input_id = 0;
-#if MT_PROTOCOL_B
-       uint8_t press_id[TOUCH_MAX_FINGER_NUM] = {0};
-#endif /* MT_PROTOCOL_B */
-       int32_t i = 0;
-       int32_t finger_cnt = 0;
-
-       mutex_lock(&ts->lock);
-
-       ret = CTP_I2C_READ(ts->client, I2C_FW_Address, point_data, POINT_DATA_LEN + 1);
-       if (ret < 0) {
-               NVT_ERR("CTP_I2C_READ failed.(%d)\n", ret);
-               goto XFER_ERROR;
-       }
-
-#if NVT_TOUCH_ESD_PROTECT
-
-       if (nvt_fw_recovery(point_data)) {
-               nvt_esd_check_enable(true);
-               goto XFER_ERROR;
-       }
-#endif
-
-#if WAKEUP_GESTURE
-       if (bTouchIsAwake == 0) {
-               input_id = (uint8_t)(point_data[1] >> 3);
-               nvt_ts_wakeup_gesture_report(input_id, point_data);
-               enable_irq(ts->client->irq);
-               mutex_unlock(&ts->lock);
-               return;
-       }
-#endif
-
-       finger_cnt = 0;
-
-       for (i = 0; i < ts->max_touch_num; i++) {
-               position = 1 + 6 * i;
-               input_id = (uint8_t)(point_data[position + 0] >> 3);
-               if ((input_id == 0) || (input_id > ts->max_touch_num))
-                       continue;
-
-               if (((point_data[position] & 0x07) == 0x01) || ((point_data[position] & 0x07) == 0x02)) {
-#if NVT_TOUCH_ESD_PROTECT
-               /* update interrupt timer */
-               irq_timer = jiffies;
-#endif
-                       input_x = (uint32_t)(point_data[position + 1] << 4) + (uint32_t) (point_data[position + 3] >> 4);
-                       input_y = (uint32_t)(point_data[position + 2] << 4) + (uint32_t) (point_data[position + 3] & 0x0F);
-                       if ((input_x < 0) || (input_y < 0))
-                               continue;
-                       if ((input_x > ts->abs_x_max) || (input_y > ts->abs_y_max))
-                               continue;
-                       input_w = (uint32_t)(point_data[position + 4]);
-                       if (input_w == 0)
-                               input_w = 1;
-                       if (i < 2) {
-                               input_p = (uint32_t)(point_data[position + 5]) + (uint32_t)(point_data[i + 63] << 8);
-                               if (input_p > TOUCH_FORCE_NUM)
-                                       input_p = TOUCH_FORCE_NUM;
-                       } else {
-                               input_p = (uint32_t)(point_data[position + 5]);
-                       }
-                       if (input_p == 0)
-                               input_p = 1;
-
-#if MT_PROTOCOL_B
-                       press_id[input_id - 1] = 1;
-                       input_mt_slot(ts->input_dev, input_id - 1);
-                       input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
-#else /* MT_PROTOCOL_B */
-                       input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, input_id - 1);
-                       input_report_key(ts->input_dev, BTN_TOUCH, 1);
-#endif /* MT_PROTOCOL_B */
-
-                       input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
-                       input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
-                       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
-                       input_report_abs(ts->input_dev, ABS_MT_PRESSURE, input_p);
-
-#if MT_PROTOCOL_B
-#else /* MT_PROTOCOL_B */
-                       input_mt_sync(ts->input_dev);
-#endif /* MT_PROTOCOL_B */
-
-                       finger_cnt++;
-               }
-       }
-
-#if MT_PROTOCOL_B
-       for (i = 0; i < ts->max_touch_num; i++) {
-               if (press_id[i] != 1) {
-                       input_mt_slot(ts->input_dev, i);
-                       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
-                       input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0);
-                       input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
-               }
-       }
-
-       input_report_key(ts->input_dev, BTN_TOUCH, (finger_cnt > 0));
-#else /* MT_PROTOCOL_B */
-       if (finger_cnt == 0) {
-               input_report_key(ts->input_dev, BTN_TOUCH, 0);
-               input_mt_sync(ts->input_dev);
-       }
-#endif /* MT_PROTOCOL_B */
-
-#if TOUCH_KEY_NUM > 0
-       if (point_data[61] == 0xF8) {
-               for (i = 0; i < ts->max_button_num; i++) {
-                       input_report_key(ts->input_dev, touch_key_array[i], ((point_data[62] >> i) & 0x01));
-               }
-       } else {
-               for (i = 0; i < ts->max_button_num; i++) {
-                       input_report_key(ts->input_dev, touch_key_array[i], 0);
-               }
-       }
-#endif
-
-       input_sync(ts->input_dev);
-
-XFER_ERROR:
-       enable_irq(ts->client->irq);
-
-       mutex_unlock(&ts->lock);
-}
-
-/*******************************************************
-Description:
-       External interrupt service routine.
-
-return:
-       irq execute status.
-*******************************************************/
-static irqreturn_t nvt_ts_irq_handler(int32_t irq, void *dev_id)
-{
-       disable_irq_nosync(ts->client->irq);
-
-#if WAKEUP_GESTURE
-       if (bTouchIsAwake == 0) {
-               wake_lock_timeout(&gestrue_wakelock, msecs_to_jiffies(5000));
-       }
-#endif
-
-       queue_work(nvt_wq, &ts->nvt_work);
-
-       return IRQ_HANDLED;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen check and stop crc reboot loop.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_stop_crc_reboot(void)
-{
-       uint8_t buf[8] = {0};
-       int32_t retry = 0;
-
-       //read dummy buffer to check CRC fail reboot is happening or not
-
-       //---change I2C index to prevent geting 0xFF, but not 0xFC---
-       buf[0] = 0xFF;
-       buf[1] = 0x01;
-       buf[2] = 0xF6;
-       CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
-
-       //---read to check if buf is 0xFC which means IC is in CRC reboot ---
-       buf[0] = 0x4E;
-       CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 4);
-
-       if (((buf[1] == 0xFC) && (buf[2] == 0xFC) && (buf[3] == 0xFC)) ||
-               ((buf[1] == 0xFF) && (buf[2] == 0xFF) && (buf[3] == 0xFF))) {
-
-               //IC is in CRC fail reboot loop, needs to be stopped!
-               for (retry = 5; retry > 0; retry--) {
-
-                       //---write i2c cmds to reset idle : 1st---
-                       buf[0]=0x00;
-                       buf[1]=0xA5;
-                       CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-
-                       //---write i2c cmds to reset idle : 2rd---
-                       buf[0]=0x00;
-                       buf[1]=0xA5;
-                       CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-                       msleep(1);
-
-                       //---clear CRC_ERR_FLAG---
-                       buf[0] = 0xFF;
-                       buf[1] = 0x03;
-                       buf[2] = 0xF1;
-                       CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
-
-                       buf[0] = 0x35;
-                       buf[1] = 0xA5;
-                       CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 2);
-
-                       //---check CRC_ERR_FLAG---
-                       buf[0] = 0xFF;
-                       buf[1] = 0x03;
-                       buf[2] = 0xF1;
-                       CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
-
-                       buf[0] = 0x35;
-                       buf[1] = 0x00;
-                       CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 2);
-
-                       if (buf[1] == 0xA5)
-                               break;
-               }
-               if (retry == 0)
-                       NVT_ERR("CRC auto reboot is not able to be stopped! buf[1]=0x%02X\n", buf[1]);
-       }
-
-       return;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen check chip version trim function.
-
-return:
-       Executive outcomes. 0---NVT IC. -1---not NVT IC.
-*******************************************************/
-static int8_t nvt_ts_check_chip_ver_trim(void)
-{
-       uint8_t buf[8] = {0};
-       int32_t retry = 0;
-       int32_t list = 0;
-       int32_t i = 0;
-       int32_t found_nvt_chip = 0;
-       int32_t ret = -1;
-
-       nvt_bootloader_reset(); // NOT in retry loop
-
-       //---Check for 5 times---
-       for (retry = 5; retry > 0; retry--) {
-               nvt_sw_reset_idle();
-
-               buf[0] = 0x00;
-               buf[1] = 0x35;
-               CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-               msleep(10);
-
-               buf[0] = 0xFF;
-               buf[1] = 0x01;
-               buf[2] = 0xF6;
-               CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
-
-               buf[0] = 0x4E;
-               buf[1] = 0x00;
-               buf[2] = 0x00;
-               buf[3] = 0x00;
-               buf[4] = 0x00;
-               buf[5] = 0x00;
-               buf[6] = 0x00;
-               CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 7);
-               NVT_LOG("buf[1]=0x%02X, buf[2]=0x%02X, buf[3]=0x%02X, buf[4]=0x%02X, buf[5]=0x%02X, buf[6]=0x%02X\n",
-                       buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
-
-               // compare read chip id on supported list
-               for (list = 0; list < (sizeof(trim_id_table) / sizeof(struct nvt_ts_trim_id_table)); list++) {
-                       found_nvt_chip = 0;
-
-                       // compare each byte
-                       for (i = 0; i < NVT_ID_BYTE_MAX; i++) {
-                               if (trim_id_table[list].mask[i]) {
-                                       if (buf[i + 1] != trim_id_table[list].id[i])
-                                               break;
-                               }
-                       }
-
-                       if (i == NVT_ID_BYTE_MAX) {
-                               found_nvt_chip = 1;
-                       }
-
-                       if (found_nvt_chip) {
-                               NVT_LOG("This is NVT touch IC\n");
-#if NVT_TOUCH_FW
-                               if (list == 0) {
-                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36672A");
-                               } else if (list == 9) {
-                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36525");
-                               } else if (list == 10) {
-                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36870");
-                               } else if (list == 11) {
-                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36676F");
-                               } else {
-                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36772");
-                               }
-#endif
-                               ts->mmap = trim_id_table[list].mmap;
-                               ts->carrier_system = trim_id_table[list].carrier_system;
-                               ret = 0;
-                               goto out;
-                       } else {
-                               ts->mmap = NULL;
-                               ret = -1;
-                       }
-               }
-
-               //---Stop CRC check to prevent IC auto reboot---
-               if (((buf[1] == 0xFC) && (buf[2] == 0xFC) && (buf[3] == 0xFC)) ||
-                       ((buf[1] == 0xFF) && (buf[2] == 0xFF) && (buf[3] == 0xFF))) {
-                       nvt_stop_crc_reboot();
-               }
-
-               msleep(10);
-       }
-
-out:
-       return ret;
-}
-
-
-/*******************************************************
-Description:
-       Novatek touchscreen driver probe function.
-
-return:
-       Executive outcomes. 0---succeed. negative---failed
-*******************************************************/
-static int32_t nvt_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
-{
-       int32_t ret = 0;
-#if ((TOUCH_KEY_NUM > 0) || WAKEUP_GESTURE)
-       int32_t retry = 0;
-#endif
-
-       NVT_LOG("start\n");
-
-       ts = kmalloc(sizeof(struct nvt_ts_data), GFP_KERNEL);
-       if (ts == NULL) {
-               NVT_ERR("failed to allocated memory for nvt ts data\n");
-               return -ENOMEM;
-       }
-
-       ts->client = client;
-       i2c_set_clientdata(client, ts);
-
-       //---parse dts---
-       nvt_parse_dt(&client->dev);
-
-       //---request and config GPIOs---
-       ret = nvt_gpio_config(ts);
-       if (ret) {
-               NVT_ERR("gpio config error!\n");
-               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);
-
-       //---check chip version trim---
-       ret = nvt_ts_check_chip_ver_trim();
-       if (ret) {
-               NVT_ERR("chip is not identified\n");
-               ret = -EINVAL;
-               goto err_chipvertrim_failed;
-       }
-
-       mutex_init(&ts->lock);
-
-       mutex_lock(&ts->lock);
-       nvt_bootloader_reset();
-       nvt_check_fw_reset_state(RESET_STATE_INIT);
-       nvt_get_fw_info();
-       mutex_unlock(&ts->lock);
-
-       //---create workqueue---
-       nvt_wq = create_workqueue("nvt_wq");
-       if (!nvt_wq) {
-               NVT_ERR("nvt_wq create workqueue failed\n");
-               ret = -ENOMEM;
-               goto err_create_nvt_wq_failed;
-       }
-       INIT_WORK(&ts->nvt_work, nvt_ts_work_func);
-
-
-       //---allocate input device---
-       ts->input_dev = input_allocate_device();
-       if (ts->input_dev == NULL) {
-               NVT_ERR("allocate input device failed\n");
-               ret = -ENOMEM;
-               goto err_input_dev_alloc_failed;
-       }
-
-       ts->max_touch_num = TOUCH_MAX_FINGER_NUM;
-
-#if TOUCH_KEY_NUM > 0
-       ts->max_button_num = TOUCH_KEY_NUM;
-#endif
-
-       ts->int_trigger_type = INT_TRIGGER_TYPE;
-
-
-       //---set input device info.---
-       ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
-       ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-       ts->input_dev->propbit[0] = BIT(INPUT_PROP_DIRECT);
-
-#if MT_PROTOCOL_B
-       input_mt_init_slots(ts->input_dev, ts->max_touch_num, 0);
-#endif
-
-       input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, TOUCH_FORCE_NUM, 0, 0);    //pressure = TOUCH_FORCE_NUM
-
-#if TOUCH_MAX_FINGER_NUM > 1
-       input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);    //area = 255
-
-       input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max, 0, 0);
-       input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max, 0, 0);
-#if MT_PROTOCOL_B
-       // no need to set ABS_MT_TRACKING_ID, input_mt_init_slots() already set it
-#else
-       input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, ts->max_touch_num, 0, 0);
-#endif //MT_PROTOCOL_B
-#endif //TOUCH_MAX_FINGER_NUM > 1
-
-#if TOUCH_KEY_NUM > 0
-       for (retry = 0; retry < ts->max_button_num; retry++) {
-               input_set_capability(ts->input_dev, EV_KEY, touch_key_array[retry]);
-       }
-#endif
-
-#if WAKEUP_GESTURE
-       for (retry = 0; retry < (sizeof(gesture_key_array) / sizeof(gesture_key_array[0])); retry++) {
-               input_set_capability(ts->input_dev, EV_KEY, gesture_key_array[retry]);
-       }
-       wake_lock_init(&gestrue_wakelock, WAKE_LOCK_SUSPEND, "poll-wake-lock");
-#endif
-
-       sprintf(ts->phys, "input/ts");
-       ts->input_dev->name = NVT_TS_NAME;
-       ts->input_dev->phys = ts->phys;
-       ts->input_dev->id.bustype = BUS_I2C;
-
-       //---register input device---
-       ret = input_register_device(ts->input_dev);
-       if (ret) {
-               NVT_ERR("register input device (%s) failed. ret=%d\n", ts->input_dev->name, ret);
-               goto err_input_register_device_failed;
-       }
-
-       //---set int-pin & request irq---
-       client->irq = gpio_to_irq(ts->irq_gpio);
-       if (client->irq) {
-               NVT_LOG("int_trigger_type=%d\n", ts->int_trigger_type);
-
-#if WAKEUP_GESTURE
-               ret = request_irq(client->irq, nvt_ts_irq_handler, ts->int_trigger_type | IRQF_NO_SUSPEND, client->name, ts);
-#else
-               ret = request_irq(client->irq, nvt_ts_irq_handler, ts->int_trigger_type, client->name, ts);
-#endif
-               if (ret != 0) {
-                       NVT_ERR("request irq failed. ret=%d\n", ret);
-                       goto err_int_request_failed;
-               } else {
-                       disable_irq(client->irq);
-                       NVT_LOG("request irq %d succeed\n", client->irq);
-               }
-       }
-
-#if BOOT_UPDATE_FIRMWARE
-       nvt_fwu_wq = create_singlethread_workqueue("nvt_fwu_wq");
-       if (!nvt_fwu_wq) {
-               NVT_ERR("nvt_fwu_wq create workqueue failed\n");
-               ret = -ENOMEM;
-               goto err_create_nvt_fwu_wq_failed;
-       }
-       INIT_DELAYED_WORK(&ts->nvt_fwu_work, Boot_Update_Firmware);
-       // please make sure boot update start after display reset(RESX) sequence
-       queue_delayed_work(nvt_fwu_wq, &ts->nvt_fwu_work, msecs_to_jiffies(14000));
-#endif
-
-#if NVT_TOUCH_ESD_PROTECT
-       INIT_DELAYED_WORK(&nvt_esd_check_work, nvt_esd_check_func);
-       nvt_esd_check_wq = create_workqueue("nvt_esd_check_wq");
-       queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work,
-       msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD));
-#endif
-       //---set device node---
-#if NVT_TOUCH_PROC
-       ret = nvt_flash_proc_init();
-       if (ret != 0) {
-               NVT_ERR("nvt flash proc init failed. ret=%d\n", ret);
-               goto err_init_NVT_ts;
-       }
-#endif
-
-#if NVT_TOUCH_EXT_PROC
-       ret = nvt_extra_proc_init();
-       if (ret != 0) {
-               NVT_ERR("nvt extra proc init failed. ret=%d\n", ret);
-               goto err_init_NVT_ts;
-       }
-#endif
-
-#if NVT_TOUCH_FW
-       ts->suspended = 0;
-       ts->force_reflash = 0;
-       ts->loading_fw = 0;
-
-       ret = nvt_fw_sysfs_init();
-       if (ret != 0) {
-               NVT_ERR("nvt fw class init failed. ret=%d\n", ret);
-               goto err_init_NVT_ts;
-       }
-#endif
-
-#if NVT_TOUCH_MP
-       ret = nvt_mp_proc_init();
-       if (ret != 0) {
-               NVT_ERR("nvt mp proc init failed. ret=%d\n", ret);
-               goto err_init_NVT_ts;
-       }
-#endif
-
-#if defined(CONFIG_FB)
-       ts->fb_notif.notifier_call = fb_notifier_callback;
-       ret = fb_register_client(&ts->fb_notif);
-       if(ret) {
-               NVT_ERR("register fb_notifier failed. ret=%d\n", ret);
-               goto err_register_fb_notif_failed;
-       }
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-       ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
-       ts->early_suspend.suspend = nvt_ts_early_suspend;
-       ts->early_suspend.resume = nvt_ts_late_resume;
-       ret = register_early_suspend(&ts->early_suspend);
-       if(ret) {
-               NVT_ERR("register early suspend failed. ret=%d\n", ret);
-               goto err_register_early_suspend_failed;
-       }
-#endif
-
-       bTouchIsAwake = 1;
-       NVT_LOG("end\n");
-
-       enable_irq(client->irq);
-
-       return 0;
-
-#if defined(CONFIG_FB)
-err_register_fb_notif_failed:
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-err_register_early_suspend_failed:
-#endif
-#if (NVT_TOUCH_PROC || NVT_TOUCH_EXT_PROC || NVT_TOUCH_MP)
-err_init_NVT_ts:
-#endif
-       free_irq(client->irq, ts);
-#if BOOT_UPDATE_FIRMWARE
-err_create_nvt_fwu_wq_failed:
-#endif
-err_int_request_failed:
-err_input_register_device_failed:
-       input_free_device(ts->input_dev);
-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);
-err_gpio_config_failed:
-       i2c_set_clientdata(client, NULL);
-       kfree(ts);
-       return ret;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen driver release function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t nvt_ts_remove(struct i2c_client *client)
-{
-       //struct nvt_ts_data *ts = i2c_get_clientdata(client);
-
-#if defined(CONFIG_FB)
-       if (fb_unregister_client(&ts->fb_notif))
-               NVT_ERR("Error occurred while unregistering fb_notifier.\n");
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-       unregister_early_suspend(&ts->early_suspend);
-#endif
-
-#if NVT_TOUCH_FW
-       nvt_fw_sysfs_deinit();
-#endif
-
-       mutex_destroy(&ts->lock);
-
-       NVT_LOG("Removing driver...\n");
-
-       free_irq(client->irq, ts);
-       input_unregister_device(ts->input_dev);
-       i2c_set_clientdata(client, NULL);
-       kfree(ts);
-
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen driver suspend function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t nvt_ts_suspend(struct device *dev)
-{
-       uint8_t buf[4] = {0};
-#if MT_PROTOCOL_B
-       uint32_t i = 0;
-#endif
-
-       if (!bTouchIsAwake) {
-               NVT_LOG("Touch is already suspend\n");
-               return 0;
-       }
-
-       mutex_lock(&ts->lock);
-
-       NVT_LOG("start\n");
-#if NVT_TOUCH_FW
-       ts->suspended = 1;
-#endif
-       bTouchIsAwake = 0;
-#if NVT_TOUCH_ESD_PROTECT
-       cancel_delayed_work_sync(&nvt_esd_check_work);
-       nvt_esd_check_enable(false);
-#endif
-
-#if WAKEUP_GESTURE
-       //---write i2c command to enter "wakeup gesture mode"---
-       buf[0] = EVENT_MAP_HOST_CMD;
-       buf[1] = 0x13;
-#if 0 // Do not set 0xFF first, ToDo
-       buf[2] = 0xFF;
-       buf[3] = 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 4);
-#else
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
-#endif
-
-       enable_irq_wake(ts->client->irq);
-
-       NVT_LOG("Enabled touch wakeup gesture\n");
-
-#else // WAKEUP_GESTURE
-
-       disable_irq(ts->client->irq);
-
-       //---write i2c command to enter "deep sleep mode"---
-       buf[0] = EVENT_MAP_HOST_CMD;
-       buf[1] = 0x11;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
-#endif // WAKEUP_GESTURE
-
-       /* release all touches */
-#if MT_PROTOCOL_B
-       for (i = 0; i < ts->max_touch_num; i++) {
-               input_mt_slot(ts->input_dev, i);
-               input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
-               input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0);
-               input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
-       }
-#endif
-       input_report_key(ts->input_dev, BTN_TOUCH, 0);
-#if !MT_PROTOCOL_B
-       input_mt_sync(ts->input_dev);
-#endif
-       input_sync(ts->input_dev);
-
-       msleep(50);
-
-       mutex_unlock(&ts->lock);
-
-       NVT_LOG("end\n");
-
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen driver resume function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t nvt_ts_resume(struct device *dev)
-{
-       int res = 0;
-
-       if (bTouchIsAwake) {
-               NVT_LOG("Touch is already resume\n");
-               return 0;
-       }
-
-       msleep(10);
-
-       mutex_lock(&ts->lock);
-
-       NVT_LOG("start\n");
-       // please make sure display reset(RESX) sequence and mipi dsi cmds sent before this
-#if NVT_TOUCH_SUPPORT_HW_RST
-       gpio_set_value(ts->reset_gpio, 1);
-#endif
-       nvt_bootloader_reset();
-       res = nvt_check_fw_reset_state(RESET_STATE_REK);
-
-       NVT_ERR("xlixiang---enter-%s-----res=%d\n", __func__, res);
-
-#if !WAKEUP_GESTURE
-       enable_irq(ts->client->irq);
-#endif
-
-#if NVT_TOUCH_ESD_PROTECT
-       queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work,
-       msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD));
-#endif
-       bTouchIsAwake = 1;
-#if NVT_TOUCH_FW
-               ts->suspended = 0;
-#endif
-
-       mutex_unlock(&ts->lock);
-
-       NVT_LOG("end\n");
-
-       return 0;
-}
-
-
-#if defined(CONFIG_FB)
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
-{
-       struct fb_event *evdata = data;
-       int *blank;
-       struct nvt_ts_data *ts =
-               container_of(self, struct nvt_ts_data, fb_notif);
-
-       if (evdata && evdata->data && event == FB_EARLY_EVENT_BLANK) {
-               blank = evdata->data;
-               if (*blank == FB_BLANK_POWERDOWN) {
-                       nvt_ts_suspend(&ts->client->dev);
-               }
-       } else if (evdata && evdata->data && event == FB_EVENT_BLANK) {
-               blank = evdata->data;
-               if (*blank == FB_BLANK_UNBLANK ||
-               (*blank == FB_BLANK_NORMAL && 0 == bTouchIsAwake)) {
-                       nvt_ts_resume(&ts->client->dev);
-               }
-       }
-
-       return 0;
-}
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-/*******************************************************
-Description:
-       Novatek touchscreen driver early suspend function.
-
-return:
-       n.a.
-*******************************************************/
-static void nvt_ts_early_suspend(struct early_suspend *h)
-{
-       nvt_ts_suspend(ts->client, PMSG_SUSPEND);
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen driver late resume function.
-
-return:
-       n.a.
-*******************************************************/
-static void nvt_ts_late_resume(struct early_suspend *h)
-{
-       nvt_ts_resume(ts->client);
-}
-#endif
-
-#if 0
-static const struct dev_pm_ops nvt_ts_dev_pm_ops = {
-       .suspend = nvt_ts_suspend,
-       .resume  = nvt_ts_resume,
-};
-#endif
-
-static const struct i2c_device_id nvt_ts_id[] = {
-       { NVT_I2C_NAME, 0 },
-       { }
-};
-
-#ifdef CONFIG_OF
-static struct of_device_id nvt_match_table[] = {
-       { .compatible = "novatek,NVT-ts",},
-       { },
-};
-#endif
-/*
-static struct i2c_board_info __initdata nvt_i2c_boardinfo[] = {
-       {
-               I2C_BOARD_INFO(NVT_I2C_NAME, I2C_FW_Address),
-       },
-};
-*/
-
-static struct i2c_driver nvt_i2c_driver = {
-       .probe          = nvt_ts_probe,
-       .remove         = nvt_ts_remove,
-//     .suspend        = nvt_ts_suspend,
-//     .resume         = nvt_ts_resume,
-       .id_table       = nvt_ts_id,
-       .driver = {
-               .name   = NVT_I2C_NAME,
-               .owner  = THIS_MODULE,
-#if 0
-#ifdef CONFIG_PM
-               .pm = &nvt_ts_dev_pm_ops,
-#endif
-#endif
-#ifdef CONFIG_OF
-               .of_match_table = nvt_match_table,
-#endif
-       },
-};
-
-/*******************************************************
-Description:
-       Driver Install function.
-
-return:
-       Executive Outcomes. 0---succeed. not 0---failed.
-********************************************************/
-static int32_t __init nvt_driver_init(void)
-{
-       int32_t ret = 0;
-
-       NVT_LOG("start\n");
-       //---add i2c driver---
-       ret = i2c_add_driver(&nvt_i2c_driver);
-       if (ret) {
-               pr_err("%s: failed to add i2c driver", __func__);
-               goto err_driver;
-       }
-
-       pr_info("%s: finished\n", __func__);
-
-err_driver:
-       return ret;
-}
-
-/*******************************************************
-Description:
-       Driver uninstall function.
-
-return:
-       n.a.
-********************************************************/
-static void __exit nvt_driver_exit(void)
-{
-       i2c_del_driver(&nvt_i2c_driver);
-
-       if (nvt_wq)
-               destroy_workqueue(nvt_wq);
-
-#if BOOT_UPDATE_FIRMWARE
-       if (nvt_fwu_wq)
-               destroy_workqueue(nvt_fwu_wq);
-#endif
-#if NVT_TOUCH_ESD_PROTECT
-       if (nvt_esd_check_wq)
-               destroy_workqueue(nvt_esd_check_wq);
-#endif
-
-}
-
-//late_initcall(nvt_driver_init);
-module_init(nvt_driver_init);
-module_exit(nvt_driver_exit);
-
-MODULE_DESCRIPTION("Novatek Touchscreen Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/nt36672a/nt36xxx.h b/drivers/input/touchscreen/nt36672a/nt36xxx.h
deleted file mode 100755 (executable)
index 0c17bf3..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2010 - 2017 Novatek, Inc.
- *
- * $Revision: 22971 $
- * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-#ifndef        _LINUX_NVT_TOUCH_H
-#define                _LINUX_NVT_TOUCH_H
-
-#include <linux/i2c.h>
-#include <linux/input.h>
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-#include <linux/earlysuspend.h>
-#endif
-
-#include "nt36xxx_mem_map.h"
-
-#define NVT_DEBUG 1
-
-//---GPIO number---
-#define NVTTOUCH_RST_PIN 980
-#define NVTTOUCH_INT_PIN 943
-
-
-//---INT trigger mode---
-//#define IRQ_TYPE_EDGE_RISING 1
-//#define IRQ_TYPE_EDGE_FALLING 2
-#define INT_TRIGGER_TYPE IRQ_TYPE_EDGE_RISING
-
-
-//---I2C driver info.---
-#define NVT_I2C_NAME "NVT-ts"
-#define I2C_BLDR_Address 0x01
-#define I2C_FW_Address 0x01
-#define I2C_HW_Address 0x62
-
-#if NVT_DEBUG
-#define NVT_LOG(fmt, args...)    pr_err("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args)
-#else
-#define NVT_LOG(fmt, args...)    pr_info("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args)
-#endif
-#define NVT_ERR(fmt, args...)    pr_err("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args)
-
-//---Input device info.---
-#define NVT_TS_NAME "NVTCapacitiveTouchScreen"
-
-
-//---Touch info.---
-#define TOUCH_DEFAULT_MAX_WIDTH 1080
-#define TOUCH_DEFAULT_MAX_HEIGHT 2246
-#define TOUCH_MAX_FINGER_NUM 10
-#define TOUCH_KEY_NUM 0
-#if TOUCH_KEY_NUM > 0
-extern const uint16_t touch_key_array[TOUCH_KEY_NUM];
-#endif
-#define TOUCH_FORCE_NUM 1000
-
-/* Enable only when module have tp reset pin and connected to host */
-#define NVT_TOUCH_SUPPORT_HW_RST 1
-
-//---Customerized func.---
-#define NVT_TOUCH_PROC 1
-#define NVT_TOUCH_EXT_PROC 1
-#define NVT_TOUCH_FW 1
-#define NVT_TOUCH_MP 1
-#define NVT_TOUCH_MP_LENOVO 1
-#define MT_PROTOCOL_B 1
-#define WAKEUP_GESTURE 0
-#if WAKEUP_GESTURE
-extern const uint16_t gesture_key_array[];
-#endif
-#define BOOT_UPDATE_FIRMWARE 0
-#define BOOT_UPDATE_FIRMWARE_NAME "novatek_ts_fw.bin"
-/* ---ESD Protect.--- */
-#define NVT_TOUCH_ESD_PROTECT 1
-#define NVT_TOUCH_ESD_CHECK_PERIOD 2000        /* ms */
-
-struct nvt_ts_data {
-       struct i2c_client *client;
-       struct input_dev *input_dev;
-       struct work_struct nvt_work;
-       struct delayed_work nvt_fwu_work;
-       uint16_t addr;
-       int8_t phys[32];
-#if defined(CONFIG_FB)
-       struct notifier_block fb_notif;
-#elif defined(CONFIG_HAS_EARLYSUSPEND)
-       struct early_suspend early_suspend;
-#endif
-       uint8_t fw_ver;
-       uint8_t x_num;
-       uint8_t y_num;
-       uint16_t abs_x_max;
-       uint16_t abs_y_max;
-       uint8_t max_touch_num;
-       uint8_t max_button_num;
-       uint32_t int_trigger_type;
-       int32_t irq_gpio;
-       uint32_t irq_flags;
-       int32_t reset_gpio;
-       uint32_t reset_flags;
-       struct mutex lock;
-       const struct nvt_ts_mem_map *mmap;
-       uint8_t carrier_system;
-       uint16_t nvt_pid;
-#if NVT_TOUCH_FW
-       int8_t product_id[10];
-       uint8_t suspended;
-       uint8_t force_reflash;
-       uint8_t loading_fw;
-#endif
-};
-
-#if NVT_TOUCH_FW
-#define FW_NAME_MAX_LEN 80
-#define VENDOR_NAME "novatek_ts"
-#endif
-
-#if NVT_TOUCH_PROC
-struct nvt_flash_data{
-       rwlock_t lock;
-       struct i2c_client *client;
-};
-#endif
-
-typedef enum {
-       RESET_STATE_INIT = 0xA0,// IC reset
-       RESET_STATE_REK,                // ReK baseline
-       RESET_STATE_REK_FINISH, // baseline is ready
-       RESET_STATE_NORMAL_RUN,
-       RESET_STATE_MAX  = 0xAF
-} RST_COMPLETE_STATE;
-
-typedef enum {
-    EVENT_MAP_HOST_CMD                      = 0x50,
-    EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE   = 0x51,
-    EVENT_MAP_RESET_COMPLETE                = 0x60,
-    EVENT_MAP_FWINFO                        = 0x78,
-    EVENT_MAP_PROJECTID                     = 0x9A,
-    EVENT_MAP_FWDATE                        = 0x9C,
-} I2C_EVENT_MAP;
-
-#if NVT_TOUCH_MP_LENOVO
-typedef enum {
-    MP_RESULT_SHIFT_SHORT = 0x00,
-    MP_RESULT_SHIFT_SHORT_DIFF,
-    MP_RESULT_SHIFT_SHORT_BASE,
-    MP_RESULT_SHIFT_OPEN,
-    MP_RESULT_SHIFT_RAWDATA,
-    MP_RESULT_SHIFT_CC,
-    MP_RESULT_SHIFT_CC_I,
-    MP_RESULT_SHIFT_CC_Q,
-    MP_RESULT_SHIFT_NOISE,
-    MP_RESULT_SHIFT_DIFF_MAX,
-    MP_RESULT_SHIFT_DIFF_MIN,
-/*  MP_RESULT_SHIFT_READFAIL,*/
-} MP_TEST_RESULT;
-#endif
-
-//---extern structures---
-extern struct nvt_ts_data *ts;
-
-//---extern functions---
-extern int32_t CTP_I2C_READ(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len);
-extern int32_t CTP_I2C_WRITE(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len);
-extern void nvt_bootloader_reset(void);
-extern void nvt_sw_reset_idle(void);
-extern int32_t nvt_check_fw_reset_state(RST_COMPLETE_STATE check_reset_state);
-extern int32_t nvt_get_fw_info(void);
-extern int32_t nvt_clear_fw_status(void);
-extern int32_t nvt_check_fw_status(void);
-
-#if NVT_TOUCH_ESD_PROTECT
-extern void nvt_esd_check_enable(uint8_t enable);
-#endif
-extern void nvt_stop_crc_reboot(void);
-
-#endif /* _LINUX_NVT_TOUCH_H */
diff --git a/drivers/input/touchscreen/nt36672a/nt36xxx_ext_proc.c b/drivers/input/touchscreen/nt36672a/nt36xxx_ext_proc.c
deleted file mode 100755 (executable)
index 00ee7b6..0000000
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * Copyright (C) 2010 - 2017 Novatek, Inc.
- *
- * $Revision: 22971 $
- * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/delay.h>
-
-#include "nt36xxx.h"
-
-#if NVT_TOUCH_EXT_PROC
-#define NVT_FW_VERSION "nvt_fw_version"
-#define NVT_BASELINE "nvt_baseline"
-#define NVT_RAW "nvt_raw"
-#define NVT_DIFF "nvt_diff"
-
-#define I2C_TANSFER_LENGTH  64
-
-#define NORMAL_MODE 0x00
-#define TEST_MODE_1 0x21
-#define TEST_MODE_2 0x22
-#define HANDSHAKING_HOST_READY 0xBB
-
-#define XDATA_SECTOR_SIZE   256
-#define XDATA_BUF_SIZE    2048
-
-static uint8_t xdata_tmp[XDATA_BUF_SIZE] = {0};
-static int32_t xdata[XDATA_BUF_SIZE] = {0};
-static int32_t xdata_i[XDATA_BUF_SIZE] = {0};
-static int32_t xdata_q[XDATA_BUF_SIZE] = {0};
-
-static struct proc_dir_entry *NVT_proc_fw_version_entry;
-static struct proc_dir_entry *NVT_proc_baseline_entry;
-static struct proc_dir_entry *NVT_proc_raw_entry;
-static struct proc_dir_entry *NVT_proc_diff_entry;
-
-/*******************************************************
-Description:
-       Novatek touchscreen change mode function.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_change_mode(uint8_t mode)
-{
-       uint8_t buf[8] = {0};
-
-       //---set xdata index to EVENT BUF ADDR---
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-       //---set mode---
-       buf[0] = EVENT_MAP_HOST_CMD;
-       buf[1] = mode;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
-
-       if (mode == NORMAL_MODE) {
-               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
-               buf[1] = HANDSHAKING_HOST_READY;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
-               msleep(20);
-       }
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen get firmware pipe function.
-
-return:
-       Executive outcomes. 0---pipe 0. 1---pipe 1.
-*******************************************************/
-uint8_t nvt_get_fw_pipe(void)
-{
-       uint8_t buf[8]= {0};
-
-       //---set xdata index to EVENT BUF ADDR---
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-       //---read fw status---
-       buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
-       buf[1] = 0x00;
-       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
-
-       //NVT_LOG("FW pipe=%d, buf[1]=0x%02X\n", (buf[1]&0x01), buf[1]);
-
-       return (buf[1] & 0x01);
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen read mass data function.
-
-return:
-       n.a.
-*******************************************************/
-int32_t nvt_read_mass_data(uint8_t i2c_addr, uint8_t *temp_buf, uint32_t count)
-{
-       int32_t i = 0;
-       int32_t j = 0;
-       int32_t k = 0;
-       uint8_t i2c_buf[I2C_TANSFER_LENGTH + 1] = {0};
-       uint32_t xdata_addr = 0;
-       uint32_t head_addr = 0;
-       int32_t dummy_len = 0;
-       int32_t data_len = 0;
-       int32_t residual_len = 0;
-
-       xdata_addr = (temp_buf[3] << 24) + (temp_buf[4] << 16) + (temp_buf[5] << 8) + temp_buf[6];
-       head_addr = xdata_addr - (xdata_addr % XDATA_SECTOR_SIZE);
-       dummy_len = xdata_addr - head_addr;
-       data_len = (int32_t)((temp_buf[1] << 8) + temp_buf[2]);
-       residual_len = (head_addr + dummy_len + data_len) % XDATA_SECTOR_SIZE;
-
-       if (data_len > XDATA_BUF_SIZE)
-               return -EINVAL;
-
-       for (i = 0; i < ((dummy_len + data_len) / XDATA_SECTOR_SIZE); i++) {
-               i2c_buf[0] = 0xFF;
-               i2c_buf[1] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 16) & 0xFF;
-               i2c_buf[2] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 8) & 0xFF;
-               CTP_I2C_WRITE(ts->client, (uint16_t)i2c_addr, i2c_buf, 3);
-               for (j = 0; j < (XDATA_SECTOR_SIZE / I2C_TANSFER_LENGTH); j++) {
-                       i2c_buf[0] = I2C_TANSFER_LENGTH * j;
-                       CTP_I2C_READ(ts->client, (uint16_t)i2c_addr, i2c_buf, I2C_TANSFER_LENGTH + 1);
-                       for (k = 0; k < I2C_TANSFER_LENGTH; k++) {
-                               xdata_tmp[XDATA_SECTOR_SIZE * i + I2C_TANSFER_LENGTH * j + k] = i2c_buf[k + 1];
-                       }
-               }
-       }
-
-       if (residual_len != 0) {
-               i2c_buf[0] = 0xFF;
-               i2c_buf[1] = ((xdata_addr + data_len - residual_len) >> 16) & 0xFF;
-               i2c_buf[2] = ((xdata_addr + data_len - residual_len) >> 8) & 0xFF;
-               CTP_I2C_WRITE(ts->client, (uint16_t)i2c_addr, i2c_buf, 3);
-               for (j = 0; j < (residual_len / I2C_TANSFER_LENGTH + 1); j++) {
-                       i2c_buf[0] = I2C_TANSFER_LENGTH * j;
-                       CTP_I2C_READ(ts->client, (uint16_t)i2c_addr, i2c_buf, I2C_TANSFER_LENGTH + 1);
-                       for (k = 0; k < I2C_TANSFER_LENGTH; k++) {
-                               xdata_tmp[(dummy_len + data_len - residual_len) + I2C_TANSFER_LENGTH * j + k] = i2c_buf[k + 1];
-                       }
-               }
-       }
-
-       i2c_buf[0] = 0xFF;
-       i2c_buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       i2c_buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, (uint16_t)i2c_addr, i2c_buf, 3);
-
-       for (i = 0; i < data_len; i++) {
-               *(temp_buf + i) = xdata_tmp[dummy_len + i];
-       }
-
-       return  data_len;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen read meta data function.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_read_mdata(uint32_t xdata_addr, uint32_t xdata_btn_addr)
-{
-       int32_t i = 0;
-       int32_t j = 0;
-       int32_t k = 0;
-       uint8_t buf[I2C_TANSFER_LENGTH + 1] = {0};
-       uint32_t head_addr = 0;
-       int32_t dummy_len = 0;
-       int32_t data_len = 0;
-       int32_t residual_len = 0;
-
-       //---set xdata sector address & length---
-       head_addr = xdata_addr - (xdata_addr % XDATA_SECTOR_SIZE);
-       dummy_len = xdata_addr - head_addr;
-       data_len = ts->x_num * ts->y_num * 2;
-       residual_len = (head_addr + dummy_len + data_len) % XDATA_SECTOR_SIZE;
-
-       //printk("head_addr=0x%05X, dummy_len=0x%05X, data_len=0x%05X, residual_len=0x%05X\n", head_addr, dummy_len, data_len, residual_len);
-
-       //read xdata : step 1
-       for (i = 0; i < ((dummy_len + data_len) / XDATA_SECTOR_SIZE); i++) {
-               //---change xdata index---
-               buf[0] = 0xFF;
-               buf[1] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 16) & 0xFF;
-               buf[2] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 8) & 0xFF;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-               //---read xdata by I2C_TANSFER_LENGTH
-               for (j = 0; j < (XDATA_SECTOR_SIZE / I2C_TANSFER_LENGTH); j++) {
-                       //---read data---
-                       buf[0] = I2C_TANSFER_LENGTH * j;
-                       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, I2C_TANSFER_LENGTH + 1);
-
-                       //---copy buf to xdata_tmp---
-                       for (k = 0; k < I2C_TANSFER_LENGTH; k++) {
-                               xdata_tmp[XDATA_SECTOR_SIZE * i + I2C_TANSFER_LENGTH * j + k] = buf[k + 1];
-                               //printk("0x%02X, 0x%04X\n", buf[k+1], (XDATA_SECTOR_SIZE*i + I2C_TANSFER_LENGTH*j + k));
-                       }
-               }
-               //printk("addr=0x%05X\n", (head_addr+XDATA_SECTOR_SIZE*i));
-       }
-
-       //read xdata : step2
-       if (residual_len != 0) {
-               //---change xdata index---
-               buf[0] = 0xFF;
-               buf[1] = ((xdata_addr + data_len - residual_len) >> 16) & 0xFF;
-               buf[2] = ((xdata_addr + data_len - residual_len) >> 8) & 0xFF;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-               //---read xdata by I2C_TANSFER_LENGTH
-               for (j = 0; j < (residual_len / I2C_TANSFER_LENGTH + 1); j++) {
-                       //---read data---
-                       buf[0] = I2C_TANSFER_LENGTH * j;
-                       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, I2C_TANSFER_LENGTH + 1);
-
-                       //---copy buf to xdata_tmp---
-                       for (k = 0; k < I2C_TANSFER_LENGTH; k++) {
-                               xdata_tmp[(dummy_len + data_len - residual_len) + I2C_TANSFER_LENGTH * j + k] = buf[k + 1];
-                               //printk("0x%02X, 0x%04x\n", buf[k+1], ((dummy_len+data_len-residual_len) + I2C_TANSFER_LENGTH*j + k));
-                       }
-               }
-               //printk("addr=0x%05X\n", (xdata_addr+data_len-residual_len));
-       }
-
-       //---remove dummy data and 2bytes-to-1data---
-       for (i = 0; i < (data_len / 2); i++) {
-               xdata[i] = (int16_t)(xdata_tmp[dummy_len + i * 2] + 256 * xdata_tmp[dummy_len + i * 2 + 1]);
-       }
-
-#if TOUCH_KEY_NUM > 0
-       //read button xdata : step3
-       //---change xdata index---
-       buf[0] = 0xFF;
-       buf[1] = (xdata_btn_addr >> 16) & 0xFF;
-       buf[2] = ((xdata_btn_addr >> 8) & 0xFF);
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-       //---read data---
-       buf[0] = (xdata_btn_addr & 0xFF);
-       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, (TOUCH_KEY_NUM * 2 + 1));
-
-       //---2bytes-to-1data---
-       for (i = 0; i < TOUCH_KEY_NUM; i++) {
-               xdata[ts->x_num * ts->y_num + i] = (int16_t)(buf[1 + i * 2] + 256 * buf[1 + i * 2 + 1]);
-       }
-#endif
-
-       //---set xdata index to EVENT BUF ADDR---
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen read meta data from IQ to rss function.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_read_mdata_rss(uint32_t xdata_i_addr, uint32_t xdata_q_addr, uint32_t xdata_btn_i_addr, uint32_t xdata_btn_q_addr)
-{
-       int i = 0;
-
-       nvt_read_mdata(xdata_i_addr, xdata_btn_i_addr);
-       memcpy(xdata_i, xdata, ((ts->x_num * ts->y_num + TOUCH_KEY_NUM) * sizeof(int32_t)));
-
-       nvt_read_mdata(xdata_q_addr, xdata_btn_q_addr);
-       memcpy(xdata_q, xdata, ((ts->x_num * ts->y_num + TOUCH_KEY_NUM) * sizeof(int32_t)));
-
-       for (i = 0; i < (ts->x_num * ts->y_num + TOUCH_KEY_NUM); i++) {
-               xdata[i] = (int32_t)int_sqrt((unsigned long)(xdata_i[i] * xdata_i[i]) + (unsigned long)(xdata_q[i] * xdata_q[i]));
-       }
-}
-
-/*******************************************************
-Description:
-    Novatek touchscreen get meta data function.
-
-return:
-    n.a.
-*******************************************************/
-void nvt_get_mdata(int32_t *buf, uint8_t *m_x_num, uint8_t *m_y_num)
-{
-    *m_x_num = ts->x_num;
-    *m_y_num = ts->y_num;
-    memcpy(buf, xdata, ((ts->x_num * ts->y_num + TOUCH_KEY_NUM) * sizeof(int32_t)));
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen firmware version show function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t c_fw_version_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "fw_ver=%d, x_num=%d, y_num=%d, button_num=%d\n", ts->fw_ver, ts->x_num, ts->y_num, ts->max_button_num);
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen xdata sequence print show
-       function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t c_show(struct seq_file *m, void *v)
-{
-       int32_t i = 0;
-       int32_t j = 0;
-
-       for (i = 0; i < ts->y_num; i++) {
-               for (j = 0; j < ts->x_num; j++) {
-                       seq_printf(m, "%5d, ", xdata[i * ts->x_num + j]);
-               }
-               seq_puts(m, "\n");
-       }
-
-#if TOUCH_KEY_NUM > 0
-       for (i = 0; i < TOUCH_KEY_NUM; i++) {
-               seq_printf(m, "%5d, ", xdata[ts->x_num * ts->y_num + i]);
-       }
-       seq_puts(m, "\n");
-#endif
-
-       seq_printf(m, "\n\n");
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen xdata sequence print start
-       function.
-
-return:
-       Executive outcomes. 1---call next function.
-       NULL---not call next function and sequence loop
-       stop.
-*******************************************************/
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
-       return *pos < 1 ? (void *)1 : NULL;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen xdata sequence print next
-       function.
-
-return:
-       Executive outcomes. NULL---no next and call sequence
-       stop function.
-*******************************************************/
-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
-{
-       ++*pos;
-       return NULL;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen xdata sequence print stop
-       function.
-
-return:
-       n.a.
-*******************************************************/
-static void c_stop(struct seq_file *m, void *v)
-{
-       return;
-}
-
-const struct seq_operations nvt_fw_version_seq_ops = {
-       .start  = c_start,
-       .next   = c_next,
-       .stop   = c_stop,
-       .show   = c_fw_version_show
-};
-
-const struct seq_operations nvt_seq_ops = {
-       .start  = c_start,
-       .next   = c_next,
-       .stop   = c_stop,
-       .show   = c_show
-};
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/nvt_fw_version open
-       function.
-
-return:
-       n.a.
-*******************************************************/
-static int32_t nvt_info_open(struct inode *inode, struct file *file)
-{
-       if (mutex_lock_interruptible(&ts->lock)) {
-               return -ERESTARTSYS;
-       }
-
-       NVT_LOG("++\n");
-#if NVT_TOUCH_ESD_PROTECT
-                       nvt_esd_check_enable(false);
-#endif
-       if (nvt_get_fw_info()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       mutex_unlock(&ts->lock);
-
-       NVT_LOG("--\n");
-
-       return seq_open(file, &nvt_fw_version_seq_ops);
-}
-
-static const struct file_operations nvt_info_proc_fops = {
-       .owner = THIS_MODULE,
-       .open = nvt_info_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release,
-};
-
-static int32_t nvt_fw_version_open(struct inode *inode, struct file *file)
-{
-       if (mutex_lock_interruptible(&ts->lock)) {
-               return -ERESTARTSYS;
-       }
-
-       NVT_LOG("++\n");
-#if NVT_TOUCH_ESD_PROTECT
-               nvt_esd_check_enable(false);
-#endif
-       if (nvt_get_fw_info()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       mutex_unlock(&ts->lock);
-
-       NVT_LOG("--\n");
-
-       return seq_open(file, &nvt_fw_version_seq_ops);
-}
-
-static const struct file_operations nvt_fw_version_fops = {
-       .owner = THIS_MODULE,
-       .open = nvt_fw_version_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release,
-};
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/nvt_baseline open function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t nvt_baseline_open(struct inode *inode, struct file *file)
-{
-       if (mutex_lock_interruptible(&ts->lock)) {
-               return -ERESTARTSYS;
-       }
-
-       NVT_LOG("++\n");
-#if NVT_TOUCH_ESD_PROTECT
-                       nvt_esd_check_enable(false);
-#endif
-       if (nvt_clear_fw_status()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       nvt_change_mode(TEST_MODE_2);
-
-       if (nvt_check_fw_status()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       if (nvt_get_fw_info()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       if (ts->carrier_system) {
-               nvt_read_mdata_rss(ts->mmap->BASELINE_ADDR, ts->mmap->BASELINE_Q_ADDR,
-                               ts->mmap->BASELINE_BTN_ADDR, ts->mmap->BASELINE_BTN_Q_ADDR);
-       } else {
-               nvt_read_mdata(ts->mmap->BASELINE_ADDR, ts->mmap->BASELINE_BTN_ADDR);
-       }
-
-       nvt_change_mode(NORMAL_MODE);
-
-       mutex_unlock(&ts->lock);
-
-       NVT_LOG("--\n");
-
-       return seq_open(file, &nvt_seq_ops);
-}
-
-static const struct file_operations nvt_baseline_fops = {
-       .owner = THIS_MODULE,
-       .open = nvt_baseline_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release,
-};
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/nvt_raw open function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t nvt_raw_open(struct inode *inode, struct file *file)
-{
-       if (mutex_lock_interruptible(&ts->lock)) {
-               return -ERESTARTSYS;
-       }
-
-       NVT_LOG("++\n");
-#if NVT_TOUCH_ESD_PROTECT
-               nvt_esd_check_enable(false);
-#endif
-       if (nvt_clear_fw_status()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       nvt_change_mode(TEST_MODE_2);
-
-       if (nvt_check_fw_status()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       if (nvt_get_fw_info()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       if (ts->carrier_system) {
-               if (nvt_get_fw_pipe() == 0)
-                       nvt_read_mdata_rss(ts->mmap->RAW_PIPE0_ADDR, ts->mmap->RAW_PIPE0_Q_ADDR,
-                               ts->mmap->RAW_BTN_PIPE0_ADDR, ts->mmap->RAW_BTN_PIPE0_Q_ADDR);
-               else
-                       nvt_read_mdata_rss(ts->mmap->RAW_PIPE1_ADDR, ts->mmap->RAW_PIPE1_Q_ADDR,
-                               ts->mmap->RAW_BTN_PIPE1_ADDR, ts->mmap->RAW_BTN_PIPE1_Q_ADDR);
-       } else {
-               if (nvt_get_fw_pipe() == 0)
-                       nvt_read_mdata(ts->mmap->RAW_PIPE0_ADDR, ts->mmap->RAW_BTN_PIPE0_ADDR);
-               else
-                       nvt_read_mdata(ts->mmap->RAW_PIPE1_ADDR, ts->mmap->RAW_BTN_PIPE1_ADDR);
-       }
-
-       nvt_change_mode(NORMAL_MODE);
-
-       mutex_unlock(&ts->lock);
-
-       NVT_LOG("--\n");
-
-       return seq_open(file, &nvt_seq_ops);
-}
-
-static const struct file_operations nvt_raw_fops = {
-       .owner = THIS_MODULE,
-       .open = nvt_raw_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release,
-};
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/nvt_diff open function.
-
-return:
-       Executive outcomes. 0---succeed. negative---failed.
-*******************************************************/
-static int32_t nvt_diff_open(struct inode *inode, struct file *file)
-{
-       if (mutex_lock_interruptible(&ts->lock)) {
-               return -ERESTARTSYS;
-       }
-
-       NVT_LOG("++\n");
-#if NVT_TOUCH_ESD_PROTECT
-               nvt_esd_check_enable(false);
-#endif
-       if (nvt_clear_fw_status()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       nvt_change_mode(TEST_MODE_2);
-
-       if (nvt_check_fw_status()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       if (nvt_get_fw_info()) {
-               mutex_unlock(&ts->lock);
-               return -EAGAIN;
-       }
-
-       if (ts->carrier_system) {
-               if (nvt_get_fw_pipe() == 0)
-                       nvt_read_mdata_rss(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_PIPE0_Q_ADDR,
-                               ts->mmap->DIFF_BTN_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_Q_ADDR);
-               else
-                       nvt_read_mdata_rss(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_PIPE1_Q_ADDR,
-                               ts->mmap->DIFF_BTN_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_Q_ADDR);
-       } else {
-               if (nvt_get_fw_pipe() == 0)
-                       nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR);
-               else
-                       nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR);
-       }
-
-       nvt_change_mode(NORMAL_MODE);
-
-       mutex_unlock(&ts->lock);
-
-       NVT_LOG("--\n");
-
-       return seq_open(file, &nvt_seq_ops);
-}
-
-static const struct file_operations nvt_diff_fops = {
-       .owner = THIS_MODULE,
-       .open = nvt_diff_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release,
-};
-
-/*******************************************************
-Description:
-       Novatek touchscreen extra function proc. file node
-       initial function.
-
-return:
-       Executive outcomes. 0---succeed. -12---failed.
-*******************************************************/
-int32_t nvt_extra_proc_init(void)
-{
-       NVT_proc_fw_version_entry = proc_create(NVT_FW_VERSION, 0444, NULL,&nvt_fw_version_fops);
-       if (NVT_proc_fw_version_entry == NULL) {
-               NVT_ERR("create proc/nvt_fw_version Failed!\n");
-               return -ENOMEM;
-       } else {
-               NVT_LOG("create proc/nvt_fw_version Succeeded!\n");
-       }
-
-       NVT_proc_baseline_entry = proc_create(NVT_BASELINE, 0444, NULL,&nvt_baseline_fops);
-       if (NVT_proc_baseline_entry == NULL) {
-               NVT_ERR("create proc/nvt_baseline Failed!\n");
-               return -ENOMEM;
-       } else {
-               NVT_LOG("create proc/nvt_baseline Succeeded!\n");
-       }
-
-       NVT_proc_raw_entry = proc_create(NVT_RAW, 0444, NULL,&nvt_raw_fops);
-       if (NVT_proc_raw_entry == NULL) {
-               NVT_ERR("create proc/nvt_raw Failed!\n");
-               return -ENOMEM;
-       } else {
-               NVT_LOG("create proc/nvt_raw Succeeded!\n");
-       }
-
-       NVT_proc_diff_entry = proc_create(NVT_DIFF, 0444, NULL,&nvt_diff_fops);
-       if (NVT_proc_diff_entry == NULL) {
-               NVT_ERR("create proc/nvt_diff Failed!\n");
-               return -ENOMEM;
-       } else {
-               NVT_LOG("create proc/nvt_diff Succeeded!\n");
-       }
-
-       return 0;
-}
-#endif
diff --git a/drivers/input/touchscreen/nt36672a/nt36xxx_fw_update.c b/drivers/input/touchscreen/nt36672a/nt36xxx_fw_update.c
deleted file mode 100755 (executable)
index a4bdeb2..0000000
+++ /dev/null
@@ -1,1385 +0,0 @@
-/*
- * Copyright (C) 2010 - 2017 Novatek, Inc.
- *
- * $Revision: 22971 $
- * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-
-#include <linux/delay.h>
-#include <linux/firmware.h>
-
-#include "nt36xxx.h"
-
-#if (BOOT_UPDATE_FIRMWARE || NVT_TOUCH_FW)
-
-#define FW_BIN_SIZE_116KB 118784
-#define FW_BIN_SIZE FW_BIN_SIZE_116KB
-#define FW_BIN_VER_OFFSET 0x1A000
-#define FW_BIN_VER_BAR_OFFSET 0x1A001
-#define FLASH_SECTOR_SIZE 4096
-#define SIZE_64KB 65536
-#define BLOCK_64KB_NUM 4
-
-const struct firmware *fw_entry = NULL;
-
-/*******************************************************
-Description:
-       Novatek touchscreen request update firmware function.
-
-return:
-       Executive outcomes. 0---succeed. -1,-22---failed.
-*******************************************************/
-int32_t update_firmware_request(char *filename)
-{
-       int32_t ret = 0;
-
-       if (NULL == filename) {
-               return -1;
-       }
-
-       NVT_LOG("filename is %s\n", filename);
-
-       ret = request_firmware(&fw_entry, filename, &ts->client->dev);
-       if (ret) {
-               NVT_ERR("firmware load failed, ret=%d\n", ret);
-               return ret;
-       }
-
-       // check bin file size (116kb)
-       if (fw_entry->size != FW_BIN_SIZE) {
-               NVT_ERR("bin file size not match. (%zu)\n", fw_entry->size);
-               return -EINVAL;
-       }
-
-       // check if FW version add FW version bar equals 0xFF
-       if (*(fw_entry->data + FW_BIN_VER_OFFSET) + *(fw_entry->data + FW_BIN_VER_BAR_OFFSET) != 0xFF) {
-               NVT_ERR("bin file FW_VER + FW_VER_BAR should be 0xFF!\n");
-               NVT_ERR("FW_VER=0x%02X, FW_VER_BAR=0x%02X\n", *(fw_entry->data+FW_BIN_VER_OFFSET), *(fw_entry->data+FW_BIN_VER_BAR_OFFSET));
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen release update firmware function.
-
-return:
-       n.a.
-*******************************************************/
-void update_firmware_release(void)
-{
-       if (fw_entry) {
-               release_firmware(fw_entry);
-       }
-       fw_entry=NULL;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen check firmware version function.
-
-return:
-       Executive outcomes. 0---need update. 1---need not
-       update.
-*******************************************************/
-int32_t Check_FW_Ver(void)
-{
-       uint8_t buf[16] = {0};
-       int32_t ret = 0;
-
-       //write i2c index to EVENT BUF ADDR
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
-       if (ret < 0) {
-               NVT_ERR("i2c write error!(%d)\n", ret);
-               return ret;
-       }
-
-       //read Firmware Version
-       buf[0] = EVENT_MAP_FWINFO;
-       buf[1] = 0x00;
-       buf[2] = 0x00;
-       ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3);
-       if (ret < 0) {
-               NVT_ERR("i2c read error!(%d)\n", ret);
-               return ret;
-       }
-
-       NVT_LOG("IC FW Ver = 0x%02X, FW Ver Bar = 0x%02X\n", buf[1], buf[2]);
-       NVT_LOG("Bin FW Ver = 0x%02X, FW ver Bar = 0x%02X\n",
-                       fw_entry->data[FW_BIN_VER_OFFSET], fw_entry->data[FW_BIN_VER_BAR_OFFSET]);
-
-       // check IC FW_VER + FW_VER_BAR equals 0xFF or not, need to update if not
-       if ((buf[1] + buf[2]) != 0xFF) {
-               NVT_ERR("IC FW_VER + FW_VER_BAR not equals to 0xFF!\n");
-               return 0;
-       }
-
-       // compare IC and binary FW version
-       if (buf[1] > fw_entry->data[FW_BIN_VER_OFFSET])
-               return 1;
-       else
-               return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen resume from deep power down function.
-
-return:
-       Executive outcomes. 0---succeed. negative---failed.
-*******************************************************/
-int32_t Resume_PD(void)
-{
-       uint8_t buf[8] = {0};
-       int32_t ret = 0;
-       int32_t retry = 0;
-
-       // Resume Command
-       buf[0] = 0x00;
-       buf[1] = 0xAB;
-       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-       if (ret < 0) {
-               NVT_ERR("Write Enable error!!(%d)\n", ret);
-               return ret;
-       }
-
-       // Check 0xAA (Resume Command)
-       retry = 0;
-       while(1) {
-               msleep(1);
-               buf[0] = 0x00;
-               buf[1] = 0x00;
-               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-               if (ret < 0) {
-                       NVT_ERR("Check 0xAA (Resume Command) error!!(%d)\n", ret);
-                       return ret;
-               }
-               if (buf[1] == 0xAA) {
-                       break;
-               }
-               retry++;
-               if (unlikely(retry > 20)) {
-                       NVT_ERR("Check 0xAA (Resume Command) error!! status=0x%02X\n", buf[1]);
-                       return -1;
-               }
-       }
-       msleep(10);
-
-       NVT_LOG("Resume PD OK\n");
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen check firmware checksum function.
-
-return:
-       Executive outcomes. 0---checksum not match.
-       1---checksum match. -1--- checksum read failed.
-*******************************************************/
-int32_t Check_CheckSum(void)
-{
-       uint8_t buf[64] = {0};
-       uint32_t XDATA_Addr = ts->mmap->READ_FLASH_CHECKSUM_ADDR;
-       int32_t ret = 0;
-       int32_t i = 0;
-       int32_t k = 0;
-       uint16_t WR_Filechksum[BLOCK_64KB_NUM] = {0};
-       uint16_t RD_Filechksum[BLOCK_64KB_NUM] = {0};
-       size_t fw_bin_size = 0;
-       size_t len_in_blk = 0;
-       int32_t retry = 0;
-
-       if (Resume_PD()) {
-               NVT_ERR("Resume PD error!!\n");
-               return -1;
-       }
-
-       fw_bin_size = fw_entry->size;
-
-       for (i = 0; i < BLOCK_64KB_NUM; i++) {
-               if (fw_bin_size > (i * SIZE_64KB)) {
-                       // Calculate WR_Filechksum of each 64KB block
-                       len_in_blk = min(fw_bin_size - i * SIZE_64KB, (size_t)SIZE_64KB);
-                       WR_Filechksum[i] = i + 0x00 + 0x00 + (((len_in_blk - 1) >> 8) & 0xFF) + ((len_in_blk - 1) & 0xFF);
-                       for (k = 0; k < len_in_blk; k++) {
-                               WR_Filechksum[i] += fw_entry->data[k + i * SIZE_64KB];
-                       }
-                       WR_Filechksum[i] = 65535 - WR_Filechksum[i] + 1;
-
-                       // Fast Read Command
-                       buf[0] = 0x00;
-                       buf[1] = 0x07;
-                       buf[2] = i;
-                       buf[3] = 0x00;
-                       buf[4] = 0x00;
-                       buf[5] = ((len_in_blk - 1) >> 8) & 0xFF;
-                       buf[6] = (len_in_blk - 1) & 0xFF;
-                       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7);
-                       if (ret < 0) {
-                               NVT_ERR("Fast Read Command error!!(%d)\n", ret);
-                               return ret;
-                       }
-                       // Check 0xAA (Fast Read Command)
-                       retry = 0;
-                       while (1) {
-                               msleep(80);
-                               buf[0] = 0x00;
-                               buf[1] = 0x00;
-                               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-                               if (ret < 0) {
-                                       NVT_ERR("Check 0xAA (Fast Read Command) error!!(%d)\n", ret);
-                                       return ret;
-                               }
-                               if (buf[1] == 0xAA) {
-                                       break;
-                               }
-                               retry++;
-                               if (unlikely(retry > 5)) {
-                                       NVT_ERR("Check 0xAA (Fast Read Command) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
-                                       return -1;
-                               }
-                       }
-                       // Read Checksum (write addr high byte & middle byte)
-                       buf[0] = 0xFF;
-                       buf[1] = XDATA_Addr >> 16;
-                       buf[2] = (XDATA_Addr >> 8) & 0xFF;
-                       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
-                       if (ret < 0) {
-                               NVT_ERR("Read Checksum (write addr high byte & middle byte) error!!(%d)\n", ret);
-                               return ret;
-                       }
-                       // Read Checksum
-                       buf[0] = (XDATA_Addr) & 0xFF;
-                       buf[1] = 0x00;
-                       buf[2] = 0x00;
-                       ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3);
-                       if (ret < 0) {
-                               NVT_ERR("Read Checksum error!!(%d)\n", ret);
-                               return ret;
-                       }
-
-                       RD_Filechksum[i] = (uint16_t)((buf[2] << 8) | buf[1]);
-                       if (WR_Filechksum[i] != RD_Filechksum[i]) {
-                               NVT_ERR("RD_Filechksum[%d]=0x%04X, WR_Filechksum[%d]=0x%04X\n", i, RD_Filechksum[i], i, WR_Filechksum[i]);
-                               NVT_ERR("firmware checksum not match!!\n");
-                               return 0;
-                       }
-               }
-       }
-
-       NVT_LOG("firmware checksum match\n");
-       return 1;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen initial bootloader and flash
-       block function.
-
-return:
-       Executive outcomes. 0---succeed. negative---failed.
-*******************************************************/
-int32_t Init_BootLoader(void)
-{
-       uint8_t buf[64] = {0};
-       int32_t ret = 0;
-       int32_t retry = 0;
-
-       // SW Reset & Idle
-       nvt_sw_reset_idle();
-
-       // Initiate Flash Block
-       buf[0] = 0x00;
-       buf[1] = 0x00;
-       buf[2] = I2C_FW_Address;
-       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 3);
-       if (ret < 0) {
-               NVT_ERR("Inittial Flash Block error!!(%d)\n", ret);
-               return ret;
-       }
-
-       // Check 0xAA (Initiate Flash Block)
-       retry = 0;
-       while(1) {
-               msleep(1);
-               buf[0] = 0x00;
-               buf[1] = 0x00;
-               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-               if (ret < 0) {
-                       NVT_ERR("Check 0xAA (Inittial Flash Block) error!!(%d)\n", ret);
-                       return ret;
-               }
-               if (buf[1] == 0xAA) {
-                       break;
-               }
-               retry++;
-               if (unlikely(retry > 20)) {
-                       NVT_ERR("Check 0xAA (Inittial Flash Block) error!! status=0x%02X\n", buf[1]);
-                       return -1;
-               }
-       }
-
-       NVT_LOG("Init OK \n");
-       msleep(20);
-
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen erase flash sectors function.
-
-return:
-       Executive outcomes. 0---succeed. negative---failed.
-*******************************************************/
-int32_t Erase_Flash(void)
-{
-       uint8_t buf[64] = {0};
-       int32_t ret = 0;
-       int32_t count = 0;
-       int32_t i = 0;
-       int32_t Flash_Address = 0;
-       int32_t retry = 0;
-
-       // Write Enable
-       buf[0] = 0x00;
-       buf[1] = 0x06;
-       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-       if (ret < 0) {
-               NVT_ERR("Write Enable (for Write Status Register) error!!(%d)\n", ret);
-               return ret;
-       }
-       // Check 0xAA (Write Enable)
-       retry = 0;
-       while (1) {
-               mdelay(1);
-               buf[0] = 0x00;
-               buf[1] = 0x00;
-               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-               if (ret < 0) {
-                       NVT_ERR("Check 0xAA (Write Enable for Write Status Register) error!!(%d)\n", ret);
-                       return ret;
-               }
-               if (buf[1] == 0xAA) {
-                       break;
-               }
-               retry++;
-               if (unlikely(retry > 20)) {
-                       NVT_ERR("Check 0xAA (Write Enable for Write Status Register) error!! status=0x%02X\n", buf[1]);
-                       return -1;
-               }
-       }
-
-       // Write Status Register
-       buf[0] = 0x00;
-       buf[1] = 0x01;
-       buf[2] = 0x00;
-       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 3);
-       if (ret < 0) {
-               NVT_ERR("Write Status Register error!!(%d)\n", ret);
-               return ret;
-       }
-       // Check 0xAA (Write Status Register)
-       retry = 0;
-       while (1) {
-               mdelay(1);
-               buf[0] = 0x00;
-               buf[1] = 0x00;
-               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-               if (ret < 0) {
-                       NVT_ERR("Check 0xAA (Write Status Register) error!!(%d)\n", ret);
-                       return ret;
-               }
-               if (buf[1] == 0xAA) {
-                       break;
-               }
-               retry++;
-               if (unlikely(retry > 20)) {
-                       NVT_ERR("Check 0xAA (Write Status Register) error!! status=0x%02X\n", buf[1]);
-                       return -1;
-               }
-       }
-
-       // Read Status
-       retry = 0;
-       while (1) {
-               mdelay(5);
-               buf[0] = 0x00;
-               buf[1] = 0x05;
-               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-               if (ret < 0) {
-                       NVT_ERR("Read Status (for Write Status Register) error!!(%d)\n", ret);
-                       return ret;
-               }
-
-               // Check 0xAA (Read Status)
-               buf[0] = 0x00;
-               buf[1] = 0x00;
-               buf[2] = 0x00;
-               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3);
-               if (ret < 0) {
-                       NVT_ERR("Check 0xAA (Read Status for Write Status Register) error!!(%d)\n", ret);
-                       return ret;
-               }
-               if ((buf[1] == 0xAA) && (buf[2] == 0x00)) {
-                       break;
-               }
-               retry++;
-               if (unlikely(retry > 100)) {
-                       NVT_ERR("Check 0xAA (Read Status for Write Status Register) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry);
-                       return -1;
-               }
-       }
-
-       if (fw_entry->size % FLASH_SECTOR_SIZE)
-               count = fw_entry->size / FLASH_SECTOR_SIZE + 1;
-       else
-               count = fw_entry->size / FLASH_SECTOR_SIZE;
-
-       for(i = 0; i < count; i++) {
-               // Write Enable
-               buf[0] = 0x00;
-               buf[1] = 0x06;
-               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-               if (ret < 0) {
-                       NVT_ERR("Write Enable error!!(%d,%d)\n", ret, i);
-                       return ret;
-               }
-               // Check 0xAA (Write Enable)
-               retry = 0;
-               while (1) {
-                       mdelay(1);
-                       buf[0] = 0x00;
-                       buf[1] = 0x00;
-                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-                       if (ret < 0) {
-                               NVT_ERR("Check 0xAA (Write Enable) error!!(%d,%d)\n", ret, i);
-                               return ret;
-                       }
-                       if (buf[1] == 0xAA) {
-                               break;
-                       }
-                       retry++;
-                       if (unlikely(retry > 20)) {
-                               NVT_ERR("Check 0xAA (Write Enable) error!! status=0x%02X\n", buf[1]);
-                               return -1;
-                       }
-               }
-
-               Flash_Address = i * FLASH_SECTOR_SIZE;
-
-               // Sector Erase
-               buf[0] = 0x00;
-               buf[1] = 0x20;    // Command : Sector Erase
-               buf[2] = ((Flash_Address >> 16) & 0xFF);
-               buf[3] = ((Flash_Address >> 8) & 0xFF);
-               buf[4] = (Flash_Address & 0xFF);
-               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 5);
-               if (ret < 0) {
-                       NVT_ERR("Sector Erase error!!(%d,%d)\n", ret, i);
-                       return ret;
-               }
-               // Check 0xAA (Sector Erase)
-               retry = 0;
-               while (1) {
-                       mdelay(1);
-                       buf[0] = 0x00;
-                       buf[1] = 0x00;
-                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-                       if (ret < 0) {
-                               NVT_ERR("Check 0xAA (Sector Erase) error!!(%d,%d)\n", ret, i);
-                               return ret;
-                       }
-                       if (buf[1] == 0xAA) {
-                               break;
-                       }
-                       retry++;
-                       if (unlikely(retry > 20)) {
-                               NVT_ERR("Check 0xAA (Sector Erase) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
-                               return -1;
-                       }
-               }
-
-               // Read Status
-               retry = 0;
-               while (1) {
-                       mdelay(5);
-                       buf[0] = 0x00;
-                       buf[1] = 0x05;
-                       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-                       if (ret < 0) {
-                               NVT_ERR("Read Status error!!(%d,%d)\n", ret, i);
-                               return ret;
-                       }
-
-                       // Check 0xAA (Read Status)
-                       buf[0] = 0x00;
-                       buf[1] = 0x00;
-                       buf[2] = 0x00;
-                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3);
-                       if (ret < 0) {
-                               NVT_ERR("Check 0xAA (Read Status) error!!(%d,%d)\n", ret, i);
-                               return ret;
-                       }
-                       if ((buf[1] == 0xAA) && (buf[2] == 0x00)) {
-                               break;
-                       }
-                       retry++;
-                       if (unlikely(retry > 100)) {
-                               NVT_ERR("Check 0xAA (Read Status) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry);
-                               return -1;
-                       }
-               }
-       }
-
-       NVT_LOG("Erase OK \n");
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen write flash sectors function.
-
-return:
-       Executive outcomes. 0---succeed. negative---failed.
-*******************************************************/
-int32_t Write_Flash(void)
-{
-       uint8_t buf[64] = {0};
-       uint32_t XDATA_Addr = ts->mmap->RW_FLASH_DATA_ADDR;
-       uint32_t Flash_Address = 0;
-       int32_t i = 0, j = 0, k = 0;
-       uint8_t tmpvalue = 0;
-       int32_t count = 0;
-       int32_t ret = 0;
-       int32_t retry = 0;
-
-       // change I2C buffer index
-       buf[0] = 0xFF;
-       buf[1] = XDATA_Addr >> 16;
-       buf[2] = (XDATA_Addr >> 8) & 0xFF;
-       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
-       if (ret < 0) {
-               NVT_ERR("change I2C buffer index error!!(%d)\n", ret);
-               return ret;
-       }
-
-       if (fw_entry->size % 256)
-               count = fw_entry->size / 256 + 1;
-       else
-               count = fw_entry->size / 256;
-
-       for (i = 0; i < count; i++) {
-               Flash_Address = i * 256;
-
-               // Write Enable
-               buf[0] = 0x00;
-               buf[1] = 0x06;
-               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-               if (ret < 0) {
-                       NVT_ERR("Write Enable error!!(%d)\n", ret);
-                       return ret;
-               }
-               // Check 0xAA (Write Enable)
-               retry = 0;
-               while (1) {
-                       udelay(100);
-                       buf[0] = 0x00;
-                       buf[1] = 0x00;
-                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-                       if (ret < 0) {
-                               NVT_ERR("Check 0xAA (Write Enable) error!!(%d,%d)\n", ret, i);
-                               return ret;
-                       }
-                       if (buf[1] == 0xAA) {
-                               break;
-                       }
-                       retry++;
-                       if (unlikely(retry > 20)) {
-                               NVT_ERR("Check 0xAA (Write Enable) error!! status=0x%02X\n", buf[1]);
-                               return -1;
-                       }
-               }
-
-               // Write Page : 256 bytes
-               for (j = 0; j < min(fw_entry->size - i * 256, (size_t)256); j += 32) {
-                       buf[0] = (XDATA_Addr + j) & 0xFF;
-                       for (k = 0; k < 32; k++) {
-                               buf[1 + k] = fw_entry->data[Flash_Address + j + k];
-                       }
-                       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 33);
-                       if (ret < 0) {
-                               NVT_ERR("Write Page error!!(%d), j=%d\n", ret, j);
-                               return ret;
-                       }
-               }
-               if (fw_entry->size - Flash_Address >= 256)
-                       tmpvalue=(Flash_Address >> 16) + ((Flash_Address >> 8) & 0xFF) + (Flash_Address & 0xFF) + 0x00 + (255);
-               else
-                       tmpvalue=(Flash_Address >> 16) + ((Flash_Address >> 8) & 0xFF) + (Flash_Address & 0xFF) + 0x00 + (fw_entry->size - Flash_Address - 1);
-
-               for (k = 0;k < min(fw_entry->size - Flash_Address,(size_t)256); k++)
-                       tmpvalue += fw_entry->data[Flash_Address + k];
-
-               tmpvalue = 255 - tmpvalue + 1;
-
-               // Page Program
-               buf[0] = 0x00;
-               buf[1] = 0x02;
-               buf[2] = ((Flash_Address >> 16) & 0xFF);
-               buf[3] = ((Flash_Address >> 8) & 0xFF);
-               buf[4] = (Flash_Address & 0xFF);
-               buf[5] = 0x00;
-               buf[6] = min(fw_entry->size - Flash_Address,(size_t)256) - 1;
-               buf[7] = tmpvalue;
-               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 8);
-               if (ret < 0) {
-                       NVT_ERR("Page Program error!!(%d), i=%d\n", ret, i);
-                       return ret;
-               }
-               // Check 0xAA (Page Program)
-               retry = 0;
-               while (1) {
-                       mdelay(1);
-                       buf[0] = 0x00;
-                       buf[1] = 0x00;
-                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-                       if (ret < 0) {
-                               NVT_ERR("Page Program error!!(%d)\n", ret);
-                               return ret;
-                       }
-                       if (buf[1] == 0xAA || buf[1] == 0xEA) {
-                               break;
-                       }
-                       retry++;
-                       if (unlikely(retry > 20)) {
-                               NVT_ERR("Check 0xAA (Page Program) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
-                               return -1;
-                       }
-               }
-               if (buf[1] == 0xEA) {
-                       NVT_ERR("Page Program error!! i=%d\n", i);
-                       return -3;
-               }
-
-               // Read Status
-               retry = 0;
-               while (1) {
-                       mdelay(5);
-                       buf[0] = 0x00;
-                       buf[1] = 0x05;
-                       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-                       if (ret < 0) {
-                               NVT_ERR("Read Status error!!(%d)\n", ret);
-                               return ret;
-                       }
-
-                       // Check 0xAA (Read Status)
-                       buf[0] = 0x00;
-                       buf[1] = 0x00;
-                       buf[2] = 0x00;
-                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3);
-                       if (ret < 0) {
-                               NVT_ERR("Check 0xAA (Read Status) error!!(%d)\n", ret);
-                               return ret;
-                       }
-                       if (((buf[1] == 0xAA) && (buf[2] == 0x00)) || (buf[1] == 0xEA)) {
-                               break;
-                       }
-                       retry++;
-                       if (unlikely(retry > 100)) {
-                               NVT_ERR("Check 0xAA (Read Status) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry);
-                               return -1;
-                       }
-               }
-               if (buf[1] == 0xEA) {
-                       NVT_ERR("Page Program error!! i=%d\n", i);
-                       return -4;
-               }
-
-               NVT_LOG("Programming...%2d%%\r", ((i * 100) / count));
-       }
-
-       NVT_LOG("Programming...%2d%%\r", 100);
-       NVT_LOG("Program OK         \n");
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen verify checksum of written
-       flash function.
-
-return:
-       Executive outcomes. 0---succeed. negative---failed.
-*******************************************************/
-int32_t Verify_Flash(void)
-{
-       uint8_t buf[64] = {0};
-       uint32_t XDATA_Addr = ts->mmap->READ_FLASH_CHECKSUM_ADDR;
-       int32_t ret = 0;
-       int32_t i = 0;
-       int32_t k = 0;
-       uint16_t WR_Filechksum[BLOCK_64KB_NUM] = {0};
-       uint16_t RD_Filechksum[BLOCK_64KB_NUM] = {0};
-       size_t fw_bin_size = 0;
-       size_t len_in_blk = 0;
-       int32_t retry = 0;
-
-       fw_bin_size = fw_entry->size;
-
-       for (i = 0; i < BLOCK_64KB_NUM; i++) {
-               if (fw_bin_size > (i * SIZE_64KB)) {
-                       // Calculate WR_Filechksum of each 64KB block
-                       len_in_blk = min(fw_bin_size - i * SIZE_64KB, (size_t)SIZE_64KB);
-                       WR_Filechksum[i] = i + 0x00 + 0x00 + (((len_in_blk - 1) >> 8) & 0xFF) + ((len_in_blk - 1) & 0xFF);
-                       for (k = 0; k < len_in_blk; k++) {
-                               WR_Filechksum[i] += fw_entry->data[k + i * SIZE_64KB];
-                       }
-                       WR_Filechksum[i] = 65535 - WR_Filechksum[i] + 1;
-
-                       // Fast Read Command
-                       buf[0] = 0x00;
-                       buf[1] = 0x07;
-                       buf[2] = i;
-                       buf[3] = 0x00;
-                       buf[4] = 0x00;
-                       buf[5] = ((len_in_blk - 1) >> 8) & 0xFF;
-                       buf[6] = (len_in_blk - 1) & 0xFF;
-                       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7);
-                       if (ret < 0) {
-                               NVT_ERR("Fast Read Command error!!(%d)\n", ret);
-                               return ret;
-                       }
-                       // Check 0xAA (Fast Read Command)
-                       retry = 0;
-                       while (1) {
-                               msleep(80);
-                               buf[0] = 0x00;
-                               buf[1] = 0x00;
-                               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-                               if (ret < 0) {
-                                       NVT_ERR("Check 0xAA (Fast Read Command) error!!(%d)\n", ret);
-                                       return ret;
-                               }
-                               if (buf[1] == 0xAA) {
-                                       break;
-                               }
-                               retry++;
-                               if (unlikely(retry > 5)) {
-                                       NVT_ERR("Check 0xAA (Fast Read Command) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
-                                       return -1;
-                               }
-                       }
-                       // Read Checksum (write addr high byte & middle byte)
-                       buf[0] = 0xFF;
-                       buf[1] = XDATA_Addr >> 16;
-                       buf[2] = (XDATA_Addr >> 8) & 0xFF;
-                       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
-                       if (ret < 0) {
-                               NVT_ERR("Read Checksum (write addr high byte & middle byte) error!!(%d)\n", ret);
-                               return ret;
-                       }
-                       // Read Checksum
-                       buf[0] = (XDATA_Addr) & 0xFF;
-                       buf[1] = 0x00;
-                       buf[2] = 0x00;
-                       ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3);
-                       if (ret < 0) {
-                               NVT_ERR("Read Checksum error!!(%d)\n", ret);
-                               return ret;
-                       }
-
-                       RD_Filechksum[i] = (uint16_t)((buf[2] << 8) | buf[1]);
-                       if (WR_Filechksum[i] != RD_Filechksum[i]) {
-                               NVT_ERR("Verify Fail%d!!\n", i);
-                               NVT_ERR("RD_Filechksum[%d]=0x%04X, WR_Filechksum[%d]=0x%04X\n", i, RD_Filechksum[i], i, WR_Filechksum[i]);
-                               return -1;
-                       }
-               }
-       }
-
-       NVT_LOG("Verify OK \n");
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen update firmware function.
-
-return:
-       Executive outcomes. 0---succeed. negative---failed.
-*******************************************************/
-int32_t Update_Firmware(void)
-{
-       int32_t ret = 0;
-
-       //---Stop CRC check to prevent IC auto reboot---
-       nvt_stop_crc_reboot();
-
-       // Step 1 : initial bootloader
-       ret = Init_BootLoader();
-       if (ret) {
-               return ret;
-       }
-
-       // Step 2 : Resume PD
-       ret = Resume_PD();
-       if (ret) {
-               return ret;
-       }
-
-       // Step 3 : Erase
-       ret = Erase_Flash();
-       if (ret) {
-               return ret;
-       }
-
-       // Step 4 : Program
-       ret = Write_Flash();
-       if (ret) {
-               return ret;
-       }
-
-       // Step 5 : Verify
-       ret = Verify_Flash();
-       if (ret) {
-               return ret;
-       }
-
-       //Step 6 : Bootloader Reset
-       nvt_bootloader_reset();
-       nvt_check_fw_reset_state(RESET_STATE_INIT);
-
-       return ret;
-}
-/*******************************************************
-Description:
-       Novatek touchscreen check flash end flag function.
-
-return:
-       Executive outcomes. 0---succeed. 1,negative---failed.
-*******************************************************/
-#define NVT_FLASH_END_FLAG_LEN 3
-#define NVT_FLASH_END_FLAG_ADDR 0x1AFFD
-int32_t nvt_check_flash_end_flag(void)
-{
-       uint8_t buf[8] = {0};
-       uint8_t nvt_end_flag[NVT_FLASH_END_FLAG_LEN + 1] = {0};
-       int32_t ret = 0;
-
-       // Step 1 : initial bootloader
-       ret = Init_BootLoader();
-       if (ret) {
-               return ret;
-       }
-
-       // Step 2 : Resume PD
-       ret = Resume_PD();
-       if (ret) {
-               return ret;
-       }
-
-       // Step 3 : unlock
-       buf[0] = 0x00;
-       buf[1] = 0x35;
-       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
-       if (ret < 0) {
-               NVT_ERR("write unlock error!!(%d)\n", ret);
-               return ret;
-       }
-       msleep(10);
-
-       //Step 4 : Flash Read Command
-       buf[0] = 0x00;
-       buf[1] = 0x03;
-       buf[2] = (NVT_FLASH_END_FLAG_ADDR >> 16) & 0xFF; //Addr_H
-       buf[3] = (NVT_FLASH_END_FLAG_ADDR >> 8) & 0xFF; //Addr_M
-       buf[4] = NVT_FLASH_END_FLAG_ADDR & 0xFF; //Addr_L
-       buf[5] = (NVT_FLASH_END_FLAG_LEN >> 8) & 0xFF; //Len_H
-       buf[6] = NVT_FLASH_END_FLAG_LEN & 0xFF; //Len_L
-       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7);
-       if (ret < 0) {
-               NVT_ERR("write Read Command error!!(%d)\n", ret);
-               return ret;
-       }
-       msleep(10);
-
-       // Check 0xAA (Read Command)
-       buf[0] = 0x00;
-       buf[1] = 0x00;
-       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
-       if (ret < 0) {
-               NVT_ERR("Check 0xAA (Read Command) error!!(%d)\n", ret);
-               return ret;
-       }
-       if (buf[1] != 0xAA) {
-               NVT_ERR("Check 0xAA (Read Command) error!! status=0x%02X\n", buf[1]);
-               return -1;
-       }
-
-       msleep(10);
-
-       //Step 5 : Read Flash Data
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->READ_FLASH_CHECKSUM_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->READ_FLASH_CHECKSUM_ADDR >> 8) & 0xFF;
-       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
-       if (ret < 0) {
-               NVT_ERR("change index error!! (%d)\n", ret);
-               return ret;
-       }
-       msleep(10);
-
-       // Read Back
-       buf[0] = ts->mmap->READ_FLASH_CHECKSUM_ADDR & 0xFF;
-       ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 6);
-       if (ret < 0) {
-               NVT_ERR("Read Back error!! (%d)\n", ret);
-               return ret;
-       }
-
-       //buf[3:5] => NVT End Flag
-       strncpy(nvt_end_flag, &buf[3], NVT_FLASH_END_FLAG_LEN);
-       NVT_LOG("nvt_end_flag=%s (%02X %02X %02X)\n", nvt_end_flag, buf[3], buf[4], buf[5]);
-
-       if (strncmp(nvt_end_flag, "NVT", 3) == 0) {
-               return 0;
-       } else {
-               NVT_ERR("\"NVT\" end flag not found!\n");
-               return 1;
-       }
-}
-#endif
-
-#if BOOT_UPDATE_FIRMWARE
-/*******************************************************
-Description:
-       Novatek touchscreen update firmware when booting
-       function.
-
-return:
-       n.a.
-*******************************************************/
-void Boot_Update_Firmware(struct work_struct *work)
-{
-       int32_t ret = 0;
-
-       char firmware_name[256] = "";
-       sprintf(firmware_name, BOOT_UPDATE_FIRMWARE_NAME);
-
-       // request bin file in "/etc/firmware"
-       ret = update_firmware_request(firmware_name);
-       if (ret) {
-               NVT_ERR("update_firmware_request failed. (%d)\n", ret);
-               return;
-       }
-
-       mutex_lock(&ts->lock);
-#if NVT_TOUCH_ESD_PROTECT
-       nvt_esd_check_enable(false);
-#endif
-#if NVT_TOUCH_FW
-       ts->loading_fw = 1;
-#endif
-       nvt_sw_reset_idle();
-
-       ret = Check_CheckSum();
-
-       if (ret < 0) {  // read firmware checksum failed
-               NVT_ERR("read firmware checksum failed\n");
-               Update_Firmware();
-       } else if ((ret == 0) && (Check_FW_Ver() == 0)) {       // (fw checksum not match) && (bin fw version >= ic fw version)
-               NVT_LOG("firmware version not match\n");
-               Update_Firmware();
-       } else if (nvt_check_flash_end_flag()) {
-               NVT_LOG("check flash end flag failed\n");
-               Update_Firmware();
-       } else {
-               // Bootloader Reset
-               nvt_bootloader_reset();
-               nvt_check_fw_reset_state(RESET_STATE_INIT);
-       }
-
-#if NVT_TOUCH_FW
-       ts->loading_fw = 0;
-#endif
-       mutex_unlock(&ts->lock);
-
-       update_firmware_release();
-}
-#endif /* BOOT_UPDATE_FIRMWARE */
-
-#if NVT_TOUCH_FW
-static ssize_t nvt_poweron_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       bool val;
-
-       mutex_lock(&ts->lock);
-       val = ts->suspended;
-       mutex_unlock(&ts->lock);
-
-       return scnprintf(buf, PAGE_SIZE, "%d\n",
-               val == 0);
-}
-
-static DEVICE_ATTR(poweron, 0444, nvt_poweron_show, NULL);
-
-static ssize_t nvt_ic_ver_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       return scnprintf(buf, PAGE_SIZE, "[FW]%02x,[IC]NT36525\n",
-               ts->fw_ver);
-}
-
-static DEVICE_ATTR(ic_ver, 0444, nvt_ic_ver_show, NULL);
-
-static ssize_t nvt_productinfo_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-/* Update script use as $touch_product_id in fw name ==> (chip id from Lenovo&script) OR (vendor name from Focaltech) OR (project ID from Longcheer&Himax)
-   Project ID ?? ( - Jeter - Hannah)
-   Chip ID ?? (NVT-ts or NVTCapacitiveTouchScreen or NT36xxx) */
-       return scnprintf(buf, PAGE_SIZE, "%s\n",
-               ts->product_id);
-}
-
-static DEVICE_ATTR(productinfo, 0444, nvt_productinfo_show, NULL);
-
-static ssize_t nvt_force_reflash_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
-{
-       unsigned int input;
-
-       if (sscanf(buf, "%u", &input) != 1)
-               return -EINVAL;
-
-       ts->force_reflash = (input == 0) ? false : true;
-
-       return count;
-}
-
-static DEVICE_ATTR(forcereflash, 0220, NULL, nvt_force_reflash_store);
-
-static ssize_t nvt_flashprog_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       return scnprintf(buf, PAGE_SIZE, "%d\n",
-               (ts->loading_fw) ? 1 : 0);
-}
-
-static DEVICE_ATTR(flashprog, 0444, nvt_flashprog_show, NULL);
-
-static ssize_t nvt_do_reflash_store(struct device *dev,
-       struct device_attribute *attr, const char *buf, size_t count)
-{
-       int retval;
-       char prefix[FW_NAME_MAX_LEN] = VENDOR_NAME;
-       char template[FW_NAME_MAX_LEN];
-       char firmware_name[256] = "";
-
-       if (count > FW_NAME_MAX_LEN) {
-               NVT_ERR("FW filename is too long\n");
-               retval = -EINVAL;
-               goto exit;
-       }
-
-       if (ts->suspended) {
-               NVT_ERR("In suspend state, try again later\n");
-               retval = -EINVAL;
-               goto exit;
-       }
-
-       if (ts->loading_fw) {
-               NVT_ERR("In FW flashing state, try again later\n");
-               retval = -EINVAL;
-               goto exit;
-       }
-
-       if (!ts->force_reflash) {
-               if (strncmp(buf, prefix,
-                       strnlen(prefix, sizeof(prefix)))) {
-                       NVT_ERR("FW does not belong to Novatek\n");
-                       retval = -EINVAL;
-                       goto exit;
-               }
-
-               snprintf(template, sizeof(template), "-%s-",
-                                               ts->product_id);
-               if (!strnstr(buf + strnlen(prefix, sizeof(prefix)), template,
-                       count)) {
-                       NVT_ERR("FW does not belong to %s\n", ts->product_id);
-                       retval = -EINVAL;
-                       goto exit;
-               }
-       }
-
-       strlcpy(firmware_name, buf, count);
-       NVT_LOG("FW filename: %s\n", firmware_name);
-
-       retval = update_firmware_request(firmware_name);
-       if (retval) {
-               NVT_ERR("update_firmware_request failed. (%d)\n", retval);
-               goto exit;
-       }
-
-       mutex_lock(&ts->lock);
-#if NVT_TOUCH_ESD_PROTECT
-       nvt_esd_check_enable(false);
-#endif
-       ts->loading_fw = 1;
-       nvt_sw_reset_idle();
-
-       retval = Check_CheckSum();
-
-       if (retval < 0) {
-               NVT_ERR("read firmware checksum failed\n");
-               Update_Firmware();
-       } else if ((retval == 0) && (Check_FW_Ver() == 0)) {
-               NVT_LOG("firmware version not match\n");
-               Update_Firmware();
-       } else if (nvt_check_flash_end_flag()) {
-               NVT_LOG("check flash end flag failed\n");
-               Update_Firmware();
-       } else {
-               /* Bootloader Reset */
-               nvt_bootloader_reset();
-               nvt_check_fw_reset_state(RESET_STATE_INIT);
-       }
-
-       ts->loading_fw = 0;
-       mutex_unlock(&ts->lock);
-
-       update_firmware_release();
-
-       retval = count;
-exit:
-       return retval;
-}
-
-static DEVICE_ATTR(doreflash, 0220, NULL, nvt_do_reflash_store);
-
-static ssize_t nvt_build_id_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-/* Update script use for comparing $str_cfg_id_latest in fw name */
-       uint8_t tmp_buf[4] = {0};
-       uint8_t fw_version = 0;
-       uint8_t date_Y = 0;
-       uint8_t date_M = 0;
-       uint8_t date_D = 0;
-
-       tmp_buf[0] = 0xFF;
-       tmp_buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       tmp_buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, tmp_buf, 3);
-
-       tmp_buf[0] = EVENT_MAP_FWINFO;
-       CTP_I2C_READ(ts->client, I2C_FW_Address, tmp_buf, 2);
-       fw_version = tmp_buf[1];
-
-       tmp_buf[0] = EVENT_MAP_FWDATE;
-       CTP_I2C_READ(ts->client, I2C_FW_Address, tmp_buf, 4);
-       date_Y = tmp_buf[1];
-       date_M = tmp_buf[2];
-       date_D = tmp_buf[3];
-
-       return scnprintf(buf, PAGE_SIZE, "%02x-%02d%02d%02d\n",
-               fw_version, date_Y, date_M, date_D);
-}
-
-static DEVICE_ATTR(buildid, 0444, nvt_build_id_show, NULL);
-
-
-#include <linux/slab.h>
-#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)
-{
-       ssize_t blen;
-       const char *path;
-
-       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, VENDOR_NAME);
-}
-
-static struct device_attribute touchscreen_attributes[] = {
-       __ATTR_RO(path),
-       __ATTR_RO(vendor),
-       __ATTR_NULL
-};
-
-#define TSDEV_MINOR_BASE 128
-#define TSDEV_MINOR_MAX 32
-
-/*******************************************************
-Description:
-       Novatek touchscreen FW function class. file node
-       initial function.
-
-return:
-       Executive outcomes. 0---succeed. -1---failed.
-*******************************************************/
-int32_t nvt_fw_class_init(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);
-               NVT_LOG("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, NVT_I2C_NAME);
-               if (IS_ERR(ts_class_dev)) {
-                       error = PTR_ERR(ts_class_dev);
-                       ts_class_dev = NULL;
-                       return error;
-               }
-
-               for (i = 0; attrs[i].attr.name != NULL; ++i) {
-                       error = device_create_file(ts_class_dev, &attrs[i]);
-                       if (error)
-                               break;
-               }
-
-               if (error)
-                       goto device_destroy;
-               else
-                       NVT_LOG("create /sys/class/touchscreen/%s Succeeded!\n", NVT_I2C_NAME);
-       } 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);
-       NVT_ERR("error creating touchscreen class\n");
-
-       return -ENODEV;
-}
-
-int nvt_fw_sysfs_init(void)
-{
-       int ret;
-       struct i2c_client *client = ts->client;
-
-       ret = nvt_fw_class_init(true);
-       if (ret != 0) {
-               NVT_ERR("fw class init failed. ret=%d\n", ret);
-               return ret;
-       }
-
-       ret = device_create_file(&client->dev, &dev_attr_forcereflash);
-       if (ret) {
-               NVT_ERR("create_file dev_attr_forcereflash failed\n");
-               return ret;
-       }
-
-       ret = device_create_file(&client->dev, &dev_attr_flashprog);
-       if (ret) {
-               NVT_ERR("create_file dev_attr_flashprog failed\n");
-               return ret;
-       }
-       ret = device_create_file(&client->dev, &dev_attr_doreflash);
-       if (ret) {
-               NVT_ERR("create_file dev_attr_doreflash failed\n");
-               return ret;
-       }
-
-       ret = device_create_file(&client->dev, &dev_attr_buildid);
-       if (ret) {
-               NVT_ERR("create_file dev_attr_buildid failed\n");
-               return ret;
-       }
-
-       ret = device_create_file(&client->dev, &dev_attr_productinfo);
-       if (ret) {
-               NVT_ERR("create_file dev_attr_productinfo failed\n");
-               return ret;
-       }
-
-       ret = device_create_file(&client->dev, &dev_attr_poweron);
-       if (ret) {
-               NVT_ERR("create_file dev_attr_poweron failed\n");
-               return ret;
-       }
-
-       ret = device_create_file(&client->dev, &dev_attr_ic_ver);
-       if (ret) {
-               NVT_ERR("create_file dev_attr_ic_ver failed\n");
-               return ret;
-       }
-
-       return 0;
-}
-void nvt_fw_sysfs_deinit(void)
-{
-       struct i2c_client *client = ts->client;
-       device_remove_file(&client->dev, &dev_attr_forcereflash);
-       device_remove_file(&client->dev, &dev_attr_flashprog);
-       device_remove_file(&client->dev, &dev_attr_doreflash);
-       device_remove_file(&client->dev, &dev_attr_buildid);
-       device_remove_file(&client->dev, &dev_attr_productinfo);
-       device_remove_file(&client->dev, &dev_attr_poweron);
-       device_remove_file(&client->dev, &dev_attr_ic_ver);
-       nvt_fw_class_init(false);
-}
-#endif
diff --git a/drivers/input/touchscreen/nt36672a/nt36xxx_mem_map.h b/drivers/input/touchscreen/nt36672a/nt36xxx_mem_map.h
deleted file mode 100755 (executable)
index 723c673..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2010 - 2017 Novatek, Inc.
- *
- * $Revision: 22971 $
- * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-
-struct nvt_ts_mem_map {
-       uint32_t EVENT_BUF_ADDR;
-       uint32_t RAW_PIPE0_ADDR;
-       uint32_t RAW_PIPE0_Q_ADDR;
-       uint32_t RAW_PIPE1_ADDR;
-       uint32_t RAW_PIPE1_Q_ADDR;
-       uint32_t BASELINE_ADDR;
-       uint32_t BASELINE_Q_ADDR;
-       uint32_t BASELINE_BTN_ADDR;
-       uint32_t BASELINE_BTN_Q_ADDR;
-       uint32_t DIFF_PIPE0_ADDR;
-       uint32_t DIFF_PIPE0_Q_ADDR;
-       uint32_t DIFF_PIPE1_ADDR;
-       uint32_t DIFF_PIPE1_Q_ADDR;
-       uint32_t RAW_BTN_PIPE0_ADDR;
-       uint32_t RAW_BTN_PIPE0_Q_ADDR;
-       uint32_t RAW_BTN_PIPE1_ADDR;
-       uint32_t RAW_BTN_PIPE1_Q_ADDR;
-       uint32_t DIFF_BTN_PIPE0_ADDR;
-       uint32_t DIFF_BTN_PIPE0_Q_ADDR;
-       uint32_t DIFF_BTN_PIPE1_ADDR;
-       uint32_t DIFF_BTN_PIPE1_Q_ADDR;
-       uint32_t READ_FLASH_CHECKSUM_ADDR;
-       uint32_t RW_FLASH_DATA_ADDR;
-};
-
-static const struct nvt_ts_mem_map NT36672A_memory_map = {
-       .EVENT_BUF_ADDR           = 0x21C00,
-       .RAW_PIPE0_ADDR           = 0x20000,
-       .RAW_PIPE0_Q_ADDR         = 0,
-       .RAW_PIPE1_ADDR           = 0x23000,
-       .RAW_PIPE1_Q_ADDR         = 0,
-       .BASELINE_ADDR            = 0x20BFC,
-       .BASELINE_Q_ADDR          = 0,
-       .BASELINE_BTN_ADDR        = 0x23BFC,
-       .BASELINE_BTN_Q_ADDR      = 0,
-       .DIFF_PIPE0_ADDR          = 0x206DC,
-       .DIFF_PIPE0_Q_ADDR        = 0,
-       .DIFF_PIPE1_ADDR          = 0x236DC,
-       .DIFF_PIPE1_Q_ADDR        = 0,
-       .RAW_BTN_PIPE0_ADDR       = 0x20510,
-       .RAW_BTN_PIPE0_Q_ADDR     = 0,
-       .RAW_BTN_PIPE1_ADDR       = 0x23510,
-       .RAW_BTN_PIPE1_Q_ADDR     = 0,
-       .DIFF_BTN_PIPE0_ADDR      = 0x20BF0,
-       .DIFF_BTN_PIPE0_Q_ADDR    = 0,
-       .DIFF_BTN_PIPE1_ADDR      = 0x23BF0,
-       .DIFF_BTN_PIPE1_Q_ADDR    = 0,
-       .READ_FLASH_CHECKSUM_ADDR = 0x24000,
-       .RW_FLASH_DATA_ADDR       = 0x24002,
-};
-
-static const struct nvt_ts_mem_map NT36772_memory_map = {
-       .EVENT_BUF_ADDR           = 0x11E00,
-       .RAW_PIPE0_ADDR           = 0x10000,
-       .RAW_PIPE0_Q_ADDR         = 0,
-       .RAW_PIPE1_ADDR           = 0x12000,
-       .RAW_PIPE1_Q_ADDR         = 0,
-       .BASELINE_ADDR            = 0x10E70,
-       .BASELINE_Q_ADDR          = 0,
-       .BASELINE_BTN_ADDR        = 0x12E70,
-       .BASELINE_BTN_Q_ADDR      = 0,
-       .DIFF_PIPE0_ADDR          = 0x10830,
-       .DIFF_PIPE0_Q_ADDR        = 0,
-       .DIFF_PIPE1_ADDR          = 0x12830,
-       .DIFF_PIPE1_Q_ADDR        = 0,
-       .RAW_BTN_PIPE0_ADDR       = 0x10E60,
-       .RAW_BTN_PIPE0_Q_ADDR     = 0,
-       .RAW_BTN_PIPE1_ADDR       = 0x12E60,
-       .RAW_BTN_PIPE1_Q_ADDR     = 0,
-       .DIFF_BTN_PIPE0_ADDR      = 0x10E68,
-       .DIFF_BTN_PIPE0_Q_ADDR    = 0,
-       .DIFF_BTN_PIPE1_ADDR      = 0x12E68,
-       .DIFF_BTN_PIPE1_Q_ADDR    = 0,
-       .READ_FLASH_CHECKSUM_ADDR = 0x14000,
-       .RW_FLASH_DATA_ADDR       = 0x14002,
-};
-
-static const struct nvt_ts_mem_map NT36525_memory_map = {
-       .EVENT_BUF_ADDR           = 0x11A00,
-       .RAW_PIPE0_ADDR           = 0x10000,
-       .RAW_PIPE0_Q_ADDR         = 0,
-       .RAW_PIPE1_ADDR           = 0x12000,
-       .RAW_PIPE1_Q_ADDR         = 0,
-       .BASELINE_ADDR            = 0x10B08,
-       .BASELINE_Q_ADDR          = 0,
-       .BASELINE_BTN_ADDR        = 0x12B08,
-       .BASELINE_BTN_Q_ADDR      = 0,
-       .DIFF_PIPE0_ADDR          = 0x1064C,
-       .DIFF_PIPE0_Q_ADDR        = 0,
-       .DIFF_PIPE1_ADDR          = 0x1264C,
-       .DIFF_PIPE1_Q_ADDR        = 0,
-       .RAW_BTN_PIPE0_ADDR       = 0x10634,
-       .RAW_BTN_PIPE0_Q_ADDR     = 0,
-       .RAW_BTN_PIPE1_ADDR       = 0x12634,
-       .RAW_BTN_PIPE1_Q_ADDR     = 0,
-       .DIFF_BTN_PIPE0_ADDR      = 0x10AFC,
-       .DIFF_BTN_PIPE0_Q_ADDR    = 0,
-       .DIFF_BTN_PIPE1_ADDR      = 0x12AFC,
-       .DIFF_BTN_PIPE1_Q_ADDR    = 0,
-       .READ_FLASH_CHECKSUM_ADDR = 0x14000,
-       .RW_FLASH_DATA_ADDR       = 0x14002,
-};
-
-static const struct nvt_ts_mem_map NT36870_memory_map = {
-       .EVENT_BUF_ADDR           = 0x25000,
-       .RAW_PIPE0_ADDR           = 0x20000,
-       .RAW_PIPE0_Q_ADDR         = 0x204C8,
-       .RAW_PIPE1_ADDR           = 0x23000,
-       .RAW_PIPE1_Q_ADDR         = 0x234C8,
-       .BASELINE_ADDR            = 0x21350,
-       .BASELINE_Q_ADDR          = 0x21818,
-       .BASELINE_BTN_ADDR        = 0x24350,
-       .BASELINE_BTN_Q_ADDR      = 0x24358,
-       .DIFF_PIPE0_ADDR          = 0x209B0,
-       .DIFF_PIPE0_Q_ADDR        = 0x20E78,
-       .DIFF_PIPE1_ADDR          = 0x239B0,
-       .DIFF_PIPE1_Q_ADDR        = 0x23E78,
-       .RAW_BTN_PIPE0_ADDR       = 0x20990,
-       .RAW_BTN_PIPE0_Q_ADDR     = 0x20998,
-       .RAW_BTN_PIPE1_ADDR       = 0x23990,
-       .RAW_BTN_PIPE1_Q_ADDR     = 0x23998,
-       .DIFF_BTN_PIPE0_ADDR      = 0x21340,
-       .DIFF_BTN_PIPE0_Q_ADDR    = 0x21348,
-       .DIFF_BTN_PIPE1_ADDR      = 0x24340,
-       .DIFF_BTN_PIPE1_Q_ADDR    = 0x24348,
-       .READ_FLASH_CHECKSUM_ADDR = 0x24000,
-       .RW_FLASH_DATA_ADDR       = 0x24002,
-};
-
-static const struct nvt_ts_mem_map NT36676F_memory_map = {
-       .EVENT_BUF_ADDR           = 0x11A00,
-       .RAW_PIPE0_ADDR           = 0x10000,
-       .RAW_PIPE0_Q_ADDR         = 0,
-       .RAW_PIPE1_ADDR           = 0x12000,
-       .RAW_PIPE1_Q_ADDR         = 0,
-       .BASELINE_ADDR            = 0x10B08,
-       .BASELINE_Q_ADDR          = 0,
-       .BASELINE_BTN_ADDR        = 0x12B08,
-       .BASELINE_BTN_Q_ADDR      = 0,
-       .DIFF_PIPE0_ADDR          = 0x1064C,
-       .DIFF_PIPE0_Q_ADDR        = 0,
-       .DIFF_PIPE1_ADDR          = 0x1264C,
-       .DIFF_PIPE1_Q_ADDR        = 0,
-       .RAW_BTN_PIPE0_ADDR       = 0x10634,
-       .RAW_BTN_PIPE0_Q_ADDR     = 0,
-       .RAW_BTN_PIPE1_ADDR       = 0x12634,
-       .RAW_BTN_PIPE1_Q_ADDR     = 0,
-       .DIFF_BTN_PIPE0_ADDR      = 0x10AFC,
-       .DIFF_BTN_PIPE0_Q_ADDR    = 0,
-       .DIFF_BTN_PIPE1_ADDR      = 0x12AFC,
-       .DIFF_BTN_PIPE1_Q_ADDR    = 0,
-       .READ_FLASH_CHECKSUM_ADDR = 0x14000,
-       .RW_FLASH_DATA_ADDR       = 0x14002,
-};
-
-#define NVT_ID_BYTE_MAX 6
-struct nvt_ts_trim_id_table {
-       uint8_t id[NVT_ID_BYTE_MAX];
-       uint8_t mask[NVT_ID_BYTE_MAX];
-       const struct nvt_ts_mem_map *mmap;
-       uint8_t carrier_system;
-};
-
-static const struct nvt_ts_trim_id_table trim_id_table[] = {
-       {.id = {0x0A, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
-               .mmap = &NT36672A_memory_map, .carrier_system = 0},
-       {.id = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
-               .mmap = &NT36772_memory_map, .carrier_system = 0},
-       {.id = {0x55, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
-               .mmap = &NT36772_memory_map, .carrier_system = 0},
-       {.id = {0xAA, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
-               .mmap = &NT36772_memory_map, .carrier_system = 0},
-       {.id = {0xAA, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
-               .mmap = &NT36772_memory_map, .carrier_system = 0},
-       {.id = {0xFF, 0xFF, 0xFF, 0x72, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
-               .mmap = &NT36772_memory_map, .carrier_system = 0},
-       {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
-               .mmap = &NT36772_memory_map, .carrier_system = 0},
-       {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
-               .mmap = &NT36772_memory_map, .carrier_system = 0},
-       {.id = {0xFF, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
-               .mmap = &NT36772_memory_map, .carrier_system = 0},
-       {.id = {0xFF, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
-               .mmap = &NT36525_memory_map, .carrier_system = 0},
-       {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x68, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
-               .mmap = &NT36870_memory_map, .carrier_system = 1},
-       {.id = {0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
-               .mmap = &NT36676F_memory_map, .carrier_system = 0}
-};
diff --git a/drivers/input/touchscreen/nt36672a/nt36xxx_mp_ctrlram.c b/drivers/input/touchscreen/nt36672a/nt36xxx_mp_ctrlram.c
deleted file mode 100755 (executable)
index bd8f757..0000000
+++ /dev/null
@@ -1,1902 +0,0 @@
-/*
- * Copyright (C) 2010 - 2017 Novatek, Inc.
- *
- * $Revision: 23067 $
- * $Date: 2018-02-09 11:39:27 +0800 (ι€±δΊ”, 09 δΊŒζœˆ 2018) $
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-
-#include "nt36xxx.h"
-#include "nt36xxx_mp_ctrlram.h"
-
-#if NVT_TOUCH_MP
-
-#define NORMAL_MODE 0x00
-#define TEST_MODE_1 0x21
-#define TEST_MODE_2 0x22
-#define MP_MODE_CC 0x41
-#define FREQ_HOP_DISABLE 0x66
-#define FREQ_HOP_ENABLE 0x65
-
-#define SHORT_TEST_CSV_FILE "/data/local/tmp/ShortTest.csv"
-#define OPEN_TEST_CSV_FILE "/data/local/tmp/OpenTest.csv"
-#define FW_RAWDATA_CSV_FILE "/data/local/tmp/FWMutualTest.csv"
-#define FW_CC_CSV_FILE "/data/local/tmp/FWCCTest.csv"
-#define NOISE_TEST_CSV_FILE "/data/local/tmp/NoiseTest.csv"
-
-#define nvt_mp_seq_printf(m, fmt, args...) do {        \
-       seq_printf(m, fmt, ##args);     \
-       if (!nvt_mp_test_result_printed)        \
-               printk(fmt, ##args);    \
-} while (0)
-
-static uint8_t *RecordResult_Short = NULL;
-static uint8_t *RecordResult_Short_Diff = NULL;
-static uint8_t *RecordResult_Short_Base = NULL;
-static uint8_t *RecordResult_Open = NULL;
-static uint8_t *RecordResult_FWMutual = NULL;
-static uint8_t *RecordResult_FW_CC = NULL;
-static uint8_t *RecordResult_FW_CC_I = NULL;
-static uint8_t *RecordResult_FW_CC_Q = NULL;
-static uint8_t *RecordResult_FW_DiffMax = NULL;
-static uint8_t *RecordResult_FW_DiffMin = NULL;
-
-static int32_t TestResult_Short = 0;
-static int32_t TestResult_Short_Diff = 0;
-static int32_t TestResult_Short_Base = 0;
-static int32_t TestResult_Open = 0;
-static int32_t TestResult_FW_Rawdata = 0;
-static int32_t TestResult_FWMutual = 0;
-static int32_t TestResult_FW_CC = 0;
-static int32_t TestResult_FW_CC_I = 0;
-static int32_t TestResult_FW_CC_Q = 0;
-static int32_t TestResult_Noise = 0;
-static int32_t TestResult_FW_DiffMax = 0;
-static int32_t TestResult_FW_DiffMin = 0;
-
-static int32_t *RawData_Short = NULL;
-static int32_t *RawData_Short_Diff = NULL;
-static int32_t *RawData_Short_Base = NULL;
-static int32_t *RawData_Open = NULL;
-static int32_t *RawData_Diff = NULL;
-static int32_t *RawData_Diff_Min = NULL;
-static int32_t *RawData_Diff_Max = NULL;
-static int32_t *RawData_FWMutual = NULL;
-static int32_t *RawData_FW_CC = NULL;
-static int32_t *RawData_FW_CC_I = NULL;
-static int32_t *RawData_FW_CC_Q = NULL;
-
-static struct proc_dir_entry *NVT_proc_selftest_entry = NULL;
-#if NVT_TOUCH_MP_LENOVO
-static struct proc_dir_entry *NVT_proc_selftest_read_data = NULL;
-#endif
-static int8_t nvt_mp_test_result_printed = 0;
-
-extern void nvt_change_mode(uint8_t mode);
-extern uint8_t nvt_get_fw_pipe(void);
-extern void nvt_read_mdata(uint32_t xdata_addr, uint32_t xdata_btn_addr);
-extern void nvt_get_mdata(int32_t *buf, uint8_t *m_x_num, uint8_t *m_y_num);
-void nvt_mp_parse_dt(struct device_node *root, const char *node_compatible);
-extern int32_t nvt_read_mass_data(uint32_t xdata_addr, uint8_t *temp_buf, uint32_t len);
-
-/*******************************************************
-Description:
-       Novatek touchscreen allocate buffer for mp selftest.
-
-return:
-       Executive outcomes. 0---succeed. -12---Out of memory
-*******************************************************/
-static int nvt_mp_buffer_init(void)
-{
-       size_t RecordResult_BufSize = IC_X_CFG_SIZE * IC_Y_CFG_SIZE + IC_KEY_CFG_SIZE;
-       size_t RawData_BufSize = (IC_X_CFG_SIZE * IC_Y_CFG_SIZE + IC_KEY_CFG_SIZE) * sizeof(int32_t);
-
-       RecordResult_Short = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
-       if (!RecordResult_Short) {
-               NVT_ERR("kzalloc for RecordResult_Short failed!\n");
-               return -ENOMEM;
-       }
-
-       RecordResult_Short_Diff = RecordResult_Short;
-
-       RecordResult_Short_Base = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
-       if (!RecordResult_Short_Base) {
-               NVT_ERR("kzalloc for RecordResult_Short_Base failed!\n");
-               return -ENOMEM;
-       }
-
-       RecordResult_Open = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
-       if (!RecordResult_Open) {
-               NVT_ERR("kzalloc for RecordResult_Open failed!\n");
-               return -ENOMEM;
-       }
-
-       RecordResult_FWMutual = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
-       if (!RecordResult_FWMutual) {
-               NVT_ERR("kzalloc for RecordResult_FWMutual failed!\n");
-               return -ENOMEM;
-       }
-
-       RecordResult_FW_CC = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
-       if (!RecordResult_FW_CC) {
-               NVT_ERR("kzalloc for RecordResult_FW_CC failed!\n");
-               return -ENOMEM;
-       }
-
-       RecordResult_FW_CC_I = RecordResult_FW_CC;
-
-       RecordResult_FW_CC_Q = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
-       if (!RecordResult_FW_CC_Q) {
-               NVT_ERR("kzalloc for RecordResult_FW_CC_Q failed!\n");
-               return -ENOMEM;
-       }
-
-       RecordResult_FW_DiffMax = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
-       if (!RecordResult_FW_DiffMax) {
-               NVT_ERR("kzalloc for RecordResult_FW_DiffMax failed!\n");
-               return -ENOMEM;
-       }
-
-       RecordResult_FW_DiffMin = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
-       if (!RecordResult_FW_DiffMin) {
-               NVT_ERR("kzalloc for RecordResult_FW_DiffMin failed!\n");
-               return -ENOMEM;
-       }
-
-       RawData_Short = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
-       if (!RawData_Short) {
-               NVT_ERR("kzalloc for RawData_Short failed!\n");
-               return -ENOMEM;
-       }
-
-       RawData_Short_Diff = RawData_Short;
-
-       RawData_Short_Base = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
-       if (!RawData_Short_Base) {
-               NVT_ERR("kzalloc for RawData_Short_Base failed!\n");
-               return -ENOMEM;
-       }
-
-       RawData_Open = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
-       if (!RawData_Open) {
-               NVT_ERR("kzalloc for RawData_Open failed!\n");
-               return -ENOMEM;
-       }
-
-       RawData_Diff = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
-       if (!RawData_Diff) {
-               NVT_ERR("kzalloc for RawData_Diff failed!\n");
-               return -ENOMEM;
-       }
-
-       RawData_Diff_Min = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
-       if (!RawData_Diff_Min) {
-               NVT_ERR("kzalloc for RawData_Diff_Min failed!\n");
-               return -ENOMEM;
-       }
-
-       RawData_Diff_Max = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
-       if (!RawData_Diff_Max) {
-               NVT_ERR("kzalloc for RawData_Diff_Max failed!\n");
-               return -ENOMEM;
-       }
-
-       RawData_FWMutual = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
-       if (!RawData_FWMutual) {
-               NVT_ERR("kzalloc for RawData_FWMutual failed!\n");
-               return -ENOMEM;
-       }
-
-       RawData_FW_CC = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
-       if (!RawData_FW_CC) {
-               NVT_ERR("kzalloc for RawData_FW_CC failed!\n");
-               return -ENOMEM;
-       }
-
-       RawData_FW_CC_I = RawData_FW_CC;
-
-       RawData_FW_CC_Q = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
-       if (!RawData_FW_CC_Q) {
-               NVT_ERR("kzalloc for RawData_FW_CC_Q failed!\n");
-               return -ENOMEM;
-       }
-
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen self-test criteria print function.
-
-return:
-       n.a.
-*******************************************************/
-static void nvt_print_lmt_array(int32_t *array, int32_t x_ch, int32_t y_ch)
-{
-       int32_t i = 0;
-       int32_t j = 0;
-#if TOUCH_KEY_NUM > 0
-       int32_t k = 0;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       for (j = 0; j < y_ch; j++) {
-               for(i = 0; i < x_ch; i++) {
-                       printk("%5d, ", array[j * x_ch + i]);
-               }
-               printk("\n");
-       }
-#if TOUCH_KEY_NUM > 0
-       for (k = 0; k < Key_Channel; k++) {
-               printk("%5d, ", array[y_ch * x_ch + k]);
-       }
-       printk("\n");
-#endif /* #if TOUCH_KEY_NUM > 0 */
-}
-
-static void nvt_print_criteria(void)
-{
-       NVT_LOG("++\n");
-
-       if (ts->carrier_system) {
-               //---PS_Config_Lmt_Short_Diff---
-               printk("PS_Config_Lmt_Short_Diff_P:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_Short_Diff_P, X_Channel, Y_Channel);
-               printk("PS_Config_Lmt_Short_Diff_N:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_Short_Diff_N, X_Channel, Y_Channel);
-               //---PS_Config_Lmt_Short_Base---
-               printk("PS_Config_Lmt_Short_Base_P:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_Short_Base_P, X_Channel, Y_Channel);
-               printk("PS_Config_Lmt_Short_Base_N:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_Short_Base_N, X_Channel, Y_Channel);
-       } else {
-               //---PS_Config_Lmt_Short_Rawdata---
-               printk("PS_Config_Lmt_Short_Rawdata_P:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_Short_Rawdata_P, X_Channel, Y_Channel);
-               printk("PS_Config_Lmt_Short_Rawdata_N:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_Short_Rawdata_N, X_Channel, Y_Channel);
-       }
-
-       //---PS_Config_Lmt_Open_Rawdata---
-       printk("PS_Config_Lmt_Open_Rawdata_P:\n");
-       nvt_print_lmt_array(PS_Config_Lmt_Open_Rawdata_P, X_Channel, Y_Channel);
-       printk("PS_Config_Lmt_Open_Rawdata_N:\n");
-       nvt_print_lmt_array(PS_Config_Lmt_Open_Rawdata_N, X_Channel, Y_Channel);
-
-       //---PS_Config_Lmt_FW_Rawdata---
-       printk("PS_Config_Lmt_FW_Rawdata_P:\n");
-       nvt_print_lmt_array(PS_Config_Lmt_FW_Rawdata_P, X_Channel, Y_Channel);
-       printk("PS_Config_Lmt_FW_Rawdata_N:\n");
-       nvt_print_lmt_array(PS_Config_Lmt_FW_Rawdata_N, X_Channel, Y_Channel);
-
-       if (ts->carrier_system) {
-               //---PS_Config_Lmt_FW_CC_I---
-               printk("PS_Config_Lmt_FW_CC_I_P:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_I_P, X_Channel, Y_Channel);
-               printk("PS_Config_Lmt_FW_CC_I_N:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_I_N, X_Channel, Y_Channel);
-               //---PS_Config_Lmt_FW_CC_Q---
-               printk("PS_Config_Lmt_FW_CC_Q_P:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_Q_P, X_Channel, Y_Channel);
-               printk("PS_Config_Lmt_FW_CC_Q_N:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_Q_N, X_Channel, Y_Channel);
-       } else {
-               //---PS_Config_Lmt_FW_CC---
-               printk("PS_Config_Lmt_FW_CC_P:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_P, X_Channel, Y_Channel);
-               printk("PS_Config_Lmt_FW_CC_N:\n");
-               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_N, X_Channel, Y_Channel);
-       }
-
-       //---PS_Config_Lmt_FW_Diff---
-       printk("PS_Config_Lmt_FW_Diff_P:\n");
-       nvt_print_lmt_array(PS_Config_Lmt_FW_Diff_P, X_Channel, Y_Channel);
-       printk("PS_Config_Lmt_FW_Diff_N:\n");
-       nvt_print_lmt_array(PS_Config_Lmt_FW_Diff_N, X_Channel, Y_Channel);
-
-       NVT_LOG("--\n");
-}
-
-static int32_t nvt_save_rawdata_to_csv(int32_t *rawdata, uint8_t x_ch, uint8_t y_ch, const char *file_path, uint32_t offset)
-{
-       int32_t x = 0;
-       int32_t y = 0;
-       int32_t iArrayIndex = 0;
-#if TOUCH_KEY_NUM > 0
-       int32_t k = 0;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       printk("%s:++%s\n", __func__, file_path);
-
-       for (y = 0; y < y_ch; y++) {
-               for (x = 0; x < x_ch; x++) {
-                       iArrayIndex = y * x_ch + x;
-                       printk("%5d, ", rawdata[iArrayIndex]);
-               }
-               printk("\n");
-       }
-#if TOUCH_KEY_NUM > 0
-       for (k = 0; k < Key_Channel; k++) {
-               iArrayIndex = y_ch * x_ch + k;
-               printk("%5d, ", rawdata[iArrayIndex]);
-       }
-       printk("\n");
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       printk("%s:--\n", __func__);
-
-       return 0;
-}
-
-static int32_t nvt_polling_hand_shake_status(void)
-{
-       uint8_t buf[8] = {0};
-       int32_t i = 0;
-       const int32_t retry = 50;
-
-       for (i = 0; i < retry; i++) {
-               //---set xdata index to EVENT BUF ADDR---
-               buf[0] = 0xFF;
-               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-               //---read fw status---
-               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
-               buf[1] = 0x00;
-               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
-
-               if ((buf[1] == 0xA0) || (buf[1] == 0xA1))
-                       break;
-
-               msleep(10);
-       }
-
-       if (i >= retry) {
-               NVT_ERR("polling hand shake status failed, buf[1]=0x%02X\n", buf[1]);
-
-               // Read back 5 bytes from offset EVENT_MAP_HOST_CMD for debug check
-               buf[0] = 0xFF;
-               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-               buf[0] = EVENT_MAP_HOST_CMD;
-               buf[1] = 0x00;
-               buf[2] = 0x00;
-               buf[3] = 0x00;
-               buf[4] = 0x00;
-               buf[5] = 0x00;
-               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 6);
-               NVT_ERR("Read back 5 bytes from offset EVENT_MAP_HOST_CMD: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", buf[1], buf[2], buf[3], buf[4], buf[5]);
-
-               return -1;
-       } else {
-               return 0;
-       }
-}
-
-static int8_t nvt_switch_FreqHopEnDis(uint8_t FreqHopEnDis)
-{
-       uint8_t buf[8] = {0};
-       uint8_t retry = 0;
-       int8_t ret = 0;
-
-       NVT_LOG("++\n");
-
-       for (retry = 0; retry < 20; retry++) {
-               //---set xdata index to EVENT BUF ADDR---
-               buf[0] = 0xFF;
-               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-               //---switch FreqHopEnDis---
-               buf[0] = EVENT_MAP_HOST_CMD;
-               buf[1] = FreqHopEnDis;
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
-
-               msleep(35);
-
-               buf[0] = EVENT_MAP_HOST_CMD;
-               buf[1] = 0xFF;
-               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
-
-               if (buf[1] == 0x00)
-                       break;
-       }
-
-       if (unlikely(retry == 20)) {
-               NVT_ERR("switch FreqHopEnDis 0x%02X failed, buf[1]=0x%02X\n", FreqHopEnDis, buf[1]);
-               ret = -1;
-       }
-
-       NVT_LOG("--\n");
-
-       return ret;
-}
-
-static int32_t nvt_read_baseline(int32_t *xdata)
-{
-       uint8_t x_num = 0;
-       uint8_t y_num = 0;
-       uint32_t x = 0;
-       uint32_t y = 0;
-       int32_t iArrayIndex = 0;
-#if TOUCH_KEY_NUM > 0
-       int32_t k = 0;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       NVT_LOG("++\n");
-
-       nvt_read_mdata(ts->mmap->BASELINE_ADDR, ts->mmap->BASELINE_BTN_ADDR);
-
-       nvt_get_mdata(xdata, &x_num, &y_num);
-
-       for (y = 0; y < y_num; y++) {
-               for (x = 0; x < x_num; x++) {
-                       iArrayIndex = y * x_num + x;
-                       if (ts->carrier_system) {
-                               xdata[iArrayIndex] = (uint16_t)xdata[iArrayIndex];
-                       } else {
-                               xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex];
-                       }
-               }
-       }
-#if TOUCH_KEY_NUM > 0
-       for (k = 0; k < Key_Channel; k++) {
-               iArrayIndex = Y_Channel * X_Channel + k;
-               if (ts->carrier_system) {
-                       xdata[iArrayIndex] = (uint16_t)xdata[iArrayIndex];
-               } else {
-                       xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex];
-               }
-       }
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       printk("%s:\n", __func__);
-       // Save Rawdata to CSV file
-       if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, FW_RAWDATA_CSV_FILE, 0) < 0) {
-               NVT_ERR("save rawdata to CSV file failed\n");
-               return -EAGAIN;
-       }
-
-       NVT_LOG("--\n");
-
-       return 0;
-}
-
-static int32_t nvt_read_CC(int32_t *xdata)
-{
-       uint8_t x_num = 0;
-       uint8_t y_num = 0;
-       uint32_t x = 0;
-       uint32_t y = 0;
-       int32_t iArrayIndex = 0;
-       int32_t xdata_tmp = 0;
-#if TOUCH_KEY_NUM > 0
-       int32_t k = 0;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-       uint32_t rawdata_cc_q_offset = 0;
-
-       NVT_LOG("++\n");
-
-       if (nvt_get_fw_pipe() == 0)
-               nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR);
-       else
-               nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR);
-
-       nvt_get_mdata(xdata, &x_num, &y_num);
-
-       for (y = 0; y < y_num; y++) {
-               for (x = 0; x < x_num; x++) {
-                       iArrayIndex = y * x_num + x;
-                       if (ts->carrier_system) {
-                               xdata_tmp = xdata[iArrayIndex];
-                               RawData_FW_CC_I[iArrayIndex] = (uint8_t)(xdata_tmp & 0xFF);
-                               RawData_FW_CC_Q[iArrayIndex] = (uint8_t)((xdata_tmp >> 8) & 0xFF);
-                       } else {
-                               xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex];
-                       }
-               }
-       }
-#if TOUCH_KEY_NUM > 0
-       for (k = 0; k < Key_Channel; k++) {
-               iArrayIndex = Y_Channel * X_Channel + k;
-               if (ts->carrier_system) {
-                       xdata_tmp = xdata[iArrayIndex];
-                       RawData_FW_CC_I[iArrayIndex] = (uint8_t)(xdata_tmp & 0xFF);
-                       RawData_FW_CC_Q[iArrayIndex] = (uint8_t)((xdata_tmp >> 8) & 0xFF);
-               } else {
-                       xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex];
-               }
-       }
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       printk("%s:\n", __func__);
-       if (ts->carrier_system) {
-               printk("%s:RawData_CC_I:\n", __func__);
-               // Save Rawdata to CSV file
-               if (nvt_save_rawdata_to_csv(RawData_FW_CC_I, X_Channel, Y_Channel, FW_CC_CSV_FILE, 0) < 0) {
-                       NVT_ERR("save rawdata to CSV file failed\n");
-                       return -EAGAIN;
-               }
-#if TOUCH_KEY_NUM > 0
-               rawdata_cc_q_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2 + Key_Channel * 7 + 2;
-#else
-               rawdata_cc_q_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-               printk("%s:RawData_CC_Q:\n", __func__);
-               // Save Rawdata to CSV file
-               if (nvt_save_rawdata_to_csv(RawData_FW_CC_Q, X_Channel, Y_Channel, FW_CC_CSV_FILE, rawdata_cc_q_offset) < 0) {
-                       NVT_ERR("save rawdata to CSV file failed\n");
-                       return -EAGAIN;
-               }
-       } else {
-               // Save Rawdata to CSV file
-               if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, FW_CC_CSV_FILE, 0) < 0) {
-                       NVT_ERR("save rawdata to CSV file failed\n");
-                       return -EAGAIN;
-               }
-       }
-
-       NVT_LOG("--\n");
-
-       return 0;
-}
-
-static void nvt_enable_noise_collect(int32_t frame_num)
-{
-       uint8_t buf[8] = {0};
-
-       //---set xdata index to EVENT BUF ADDR---
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-       //---enable noise collect---
-       buf[0] = EVENT_MAP_HOST_CMD;
-       buf[1] = 0x47;
-       buf[2] = 0xAA;
-       buf[3] = frame_num;
-       buf[4] = 0x00;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 5);
-}
-
-static int32_t nvt_read_fw_noise(int32_t *xdata)
-{
-       uint8_t x_num = 0;
-       uint8_t y_num = 0;
-       uint32_t x = 0;
-       uint32_t y = 0;
-       int32_t iArrayIndex = 0;
-       int32_t frame_num = 0;
-       uint32_t rawdata_diff_min_offset = 0;
-#if TOUCH_KEY_NUM > 0
-       int32_t k = 0;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       NVT_LOG("++\n");
-
-       //---Enter Test Mode---
-       if (nvt_clear_fw_status()) {
-               return -EAGAIN;
-       }
-
-       frame_num = PS_Config_Diff_Test_Frame / 10;
-       if (frame_num <= 0)
-               frame_num = 1;
-       printk("%s: frame_num=%d\n", __func__, frame_num);
-       nvt_enable_noise_collect(frame_num);
-       // need wait PS_Config_Diff_Test_Frame * 8.3ms
-       msleep(frame_num * 83);
-
-       if (nvt_polling_hand_shake_status()) {
-               return -EAGAIN;
-       }
-
-       if (nvt_get_fw_info()) {
-               return -EAGAIN;
-       }
-
-       if (nvt_get_fw_pipe() == 0)
-               nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR);
-       else
-               nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR);
-
-       nvt_get_mdata(xdata, &x_num, &y_num);
-
-       for (y = 0; y < y_num; y++) {
-               for (x = 0; x < x_num; x++) {
-                       iArrayIndex = y * x_num + x;
-                       if (ts->carrier_system) {
-                               RawData_Diff_Max[iArrayIndex] = (uint16_t)xdata[iArrayIndex];
-                               RawData_Diff_Min[iArrayIndex] = 0;
-                       } else {
-                               RawData_Diff_Max[iArrayIndex] = (int8_t)((xdata[iArrayIndex] >> 8) & 0xFF);
-                               RawData_Diff_Min[iArrayIndex] = (int8_t)(xdata[iArrayIndex] & 0xFF);
-                       }
-               }
-       }
-#if TOUCH_KEY_NUM > 0
-       for (k = 0; k < Key_Channel; k++) {
-               iArrayIndex = Y_Channel * X_Channel + k;
-               if (ts->carrier_system) {
-                       RawData_Diff_Max[iArrayIndex] = (uint16_t)xdata[iArrayIndex];
-                       RawData_Diff_Min[iArrayIndex] = 0;
-               } else {
-                       RawData_Diff_Max[iArrayIndex] = (int8_t)((xdata[iArrayIndex] >> 8) & 0xFF);
-                       RawData_Diff_Min[iArrayIndex] = (int8_t)(xdata[iArrayIndex] & 0xFF);
-               }
-       }
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       //---Leave Test Mode---
-       nvt_change_mode(NORMAL_MODE);
-
-       printk("%s:RawData_Diff_Max:\n", __func__);
-       // Save Rawdata to CSV file
-       if (nvt_save_rawdata_to_csv(RawData_Diff_Max, X_Channel, Y_Channel, NOISE_TEST_CSV_FILE, 0) < 0) {
-               NVT_ERR("save rawdata to CSV file failed\n");
-               return -EAGAIN;
-       }
-
-       if (!ts->carrier_system) {
-#if TOUCH_KEY_NUM > 0
-               rawdata_diff_min_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2 + Key_Channel * 7 + 2;
-#else
-               rawdata_diff_min_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-               printk("%s:RawData_Diff_Min:\n", __func__);
-               // Save Rawdata to CSV file
-               if (nvt_save_rawdata_to_csv(RawData_Diff_Min, X_Channel, Y_Channel, NOISE_TEST_CSV_FILE, rawdata_diff_min_offset) < 0) {
-                       NVT_ERR("save rawdata to CSV file failed\n");
-                       return -EAGAIN;
-               }
-       }
-
-       NVT_LOG("--\n");
-
-       return 0;
-}
-
-static void nvt_enable_open_test(void)
-{
-       uint8_t buf[8] = {0};
-
-       //---set xdata index to EVENT BUF ADDR---
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-       //---enable open test---
-       buf[0] = EVENT_MAP_HOST_CMD;
-       buf[1] = 0x45;
-       buf[2] = 0xAA;
-       buf[3] = 0x02;
-       buf[4] = 0x00;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 5);
-}
-
-static void nvt_enable_short_test(void)
-{
-       uint8_t buf[8] = {0};
-
-       //---set xdata index to EVENT BUF ADDR---
-       buf[0] = 0xFF;
-       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
-       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-
-       //---enable short test---
-       buf[0] = EVENT_MAP_HOST_CMD;
-       buf[1] = 0x43;
-       buf[2] = 0xAA;
-       buf[3] = 0x02;
-       buf[4] = 0x00;
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 5);
-}
-
-static int32_t nvt_read_fw_open(int32_t *xdata)
-{
-       uint32_t raw_pipe_addr = 0;
-       uint8_t *rawdata_buf = NULL;
-       uint32_t x = 0;
-       uint32_t y = 0;
-       uint8_t buf[128] = {0};
-#if TOUCH_KEY_NUM > 0
-       uint32_t raw_btn_pipe_addr = 0;
-       int32_t k = 0;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       NVT_LOG("++\n");
-
-       //---Enter Test Mode---
-       if (nvt_clear_fw_status()) {
-               return -EAGAIN;
-       }
-
-       nvt_enable_open_test();
-
-       if (nvt_polling_hand_shake_status()) {
-               return -EAGAIN;
-       }
-
-#if TOUCH_KEY_NUM > 0
-       rawdata_buf = (uint8_t *)kzalloc((IC_X_CFG_SIZE * IC_Y_CFG_SIZE + IC_KEY_CFG_SIZE) * 2, GFP_KERNEL);
-#else
-       rawdata_buf = (uint8_t *)kzalloc(IC_X_CFG_SIZE * IC_Y_CFG_SIZE * 2, GFP_KERNEL);
-#endif /* #if TOUCH_KEY_NUM > 0 */
-       if (!rawdata_buf) {
-               NVT_ERR("kzalloc for rawdata_buf failed!\n");
-               return -ENOMEM;
-       }
-
-       if (nvt_get_fw_pipe() == 0)
-               raw_pipe_addr = ts->mmap->RAW_PIPE0_ADDR;
-       else
-               raw_pipe_addr = ts->mmap->RAW_PIPE1_ADDR;
-
-       for (y = 0; y < IC_Y_CFG_SIZE; y++) {
-               //---change xdata index---
-               buf[0] = 0xFF;
-               buf[1] = (uint8_t)(((raw_pipe_addr + y * IC_X_CFG_SIZE * 2) >> 16) & 0xFF);
-               buf[2] = (uint8_t)(((raw_pipe_addr + y * IC_X_CFG_SIZE * 2) >> 8) & 0xFF);
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-               buf[0] = (uint8_t)((raw_pipe_addr + y * IC_X_CFG_SIZE * 2) & 0xFF);
-               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, IC_X_CFG_SIZE * 2 + 1);
-               memcpy(rawdata_buf + y * IC_X_CFG_SIZE * 2, buf + 1, IC_X_CFG_SIZE * 2);
-       }
-#if TOUCH_KEY_NUM > 0
-       if (nvt_get_fw_pipe() == 0)
-               raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE0_ADDR;
-       else
-               raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE1_ADDR;
-
-       //---change xdata index---
-       buf[0] = 0xFF;
-       buf[1] = (uint8_t)((raw_btn_pipe_addr >> 16) & 0xFF);
-       buf[2] = (uint8_t)((raw_btn_pipe_addr >> 8) & 0xFF);
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-       buf[0] = (uint8_t)(raw_btn_pipe_addr & 0xFF);
-       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, IC_KEY_CFG_SIZE * 2 + 1);
-       memcpy(rawdata_buf + IC_Y_CFG_SIZE * IC_X_CFG_SIZE * 2, buf + 1, IC_KEY_CFG_SIZE * 2);
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       for (y = 0; y < IC_Y_CFG_SIZE; y++) {
-               for (x = 0; x < IC_X_CFG_SIZE; x++) {
-                       if ((AIN_Y[y] != 0xFF) && (AIN_X[x] != 0xFF)) {
-                               xdata[AIN_Y[y] * X_Channel + AIN_X[x]] = (int16_t)((rawdata_buf[(y * IC_X_CFG_SIZE + x) * 2] + 256 * rawdata_buf[(y * IC_X_CFG_SIZE + x) * 2 + 1]));
-                       }
-               }
-       }
-#if TOUCH_KEY_NUM > 0
-       for (k = 0; k < IC_KEY_CFG_SIZE; k++) {
-               if (AIN_KEY[k] != 0xFF)
-                       xdata[Y_Channel * X_Channel + AIN_KEY[k]] = (int16_t)(rawdata_buf[(IC_Y_CFG_SIZE * IC_X_CFG_SIZE + k) * 2] + 256 * rawdata_buf[(IC_Y_CFG_SIZE * IC_X_CFG_SIZE + k) * 2 + 1]);
-       }
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       if (rawdata_buf) {
-               kfree(rawdata_buf);
-               rawdata_buf = NULL;
-       }
-
-       //---Leave Test Mode---
-       nvt_change_mode(NORMAL_MODE);
-
-
-       printk("%s:RawData_Open\n", __func__);
-       // Save RawData to CSV file
-       if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, OPEN_TEST_CSV_FILE, 0) < 0) {
-               NVT_ERR("save rawdata to CSV file failed\n");
-               return -EAGAIN;
-       }
-
-       NVT_LOG("--\n");
-
-       return 0;
-}
-
-static int32_t nvt_read_fw_short(int32_t *xdata)
-{
-       uint32_t raw_pipe_addr = 0;
-       uint8_t *rawdata_buf = NULL;
-       uint32_t x = 0;
-       uint32_t y = 0;
-       uint8_t buf[128] = {0};
-       int32_t iArrayIndex = 0;
-#if TOUCH_KEY_NUM > 0
-       uint32_t raw_btn_pipe_addr = 0;
-       int32_t k = 0;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-       uint32_t rawdata_short_base_offset = 0;
-
-       NVT_LOG("++\n");
-
-       //---Enter Test Mode---
-       if (nvt_clear_fw_status()) {
-               return -EAGAIN;
-       }
-
-       nvt_enable_short_test();
-
-       if (nvt_polling_hand_shake_status()) {
-               return -EAGAIN;
-       }
-
-#if TOUCH_KEY_NUM > 0
-    rawdata_buf = (uint8_t *)kzalloc((X_Channel * Y_Channel + Key_Channel) * 2, GFP_KERNEL);
-#else
-    rawdata_buf = (uint8_t *)kzalloc(X_Channel * Y_Channel * 2, GFP_KERNEL);
-#endif /* #if TOUCH_KEY_NUM > 0 */
-       if (!rawdata_buf) {
-               NVT_ERR("kzalloc for rawdata_buf failed!\n");
-               return -ENOMEM;
-       }
-
-       if (ts->carrier_system) {
-               // to get short diff rawdata at pipe0
-               raw_pipe_addr = ts->mmap->RAW_PIPE0_ADDR;
-       } else {
-               if (nvt_get_fw_pipe() == 0)
-                       raw_pipe_addr = ts->mmap->RAW_PIPE0_ADDR;
-               else
-                       raw_pipe_addr = ts->mmap->RAW_PIPE1_ADDR;
-       }
-
-       for (y = 0; y < Y_Channel; y++) {
-               //---change xdata index---
-               buf[0] = 0xFF;
-               buf[1] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 16) & 0xFF);
-               buf[2] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 8) & 0xFF);
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-               buf[0] = (uint8_t)((raw_pipe_addr + y * X_Channel * 2) & 0xFF);
-               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, X_Channel * 2 + 1);
-               memcpy(rawdata_buf + y * X_Channel * 2, buf + 1, X_Channel * 2);
-       }
-#if TOUCH_KEY_NUM > 0
-       if (ts->carrier_system) {
-               // to get button short diff rawdata at pipe0
-               raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE0_ADDR;
-       } else {
-               if (nvt_get_fw_pipe() == 0)
-                       raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE0_ADDR;
-               else
-                       raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE1_ADDR;
-       }
-
-    //---change xdata index---
-       buf[0] = 0xFF;
-       buf[1] = (uint8_t)((raw_btn_pipe_addr >> 16) & 0xFF);
-       buf[2] = (uint8_t)((raw_btn_pipe_addr >> 8) & 0xFF);
-       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-       buf[0] = (uint8_t)(raw_btn_pipe_addr & 0xFF);
-       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, Key_Channel * 2 + 1);
-       memcpy(rawdata_buf + Y_Channel * X_Channel * 2, buf + 1, Key_Channel * 2);
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       for (y = 0; y < Y_Channel; y++) {
-               for (x = 0; x < X_Channel; x++) {
-                       iArrayIndex = y * X_Channel + x;
-                       xdata[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]);
-               }
-       }
-#if TOUCH_KEY_NUM > 0
-       for (k = 0; k < Key_Channel; k++) {
-               iArrayIndex = Y_Channel * X_Channel + k;
-               xdata[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]);
-       }
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       // for carrier sensing system to get short baseline rawdata
-       if (ts->carrier_system) {
-               // to get short baseline rawdata at pipe1
-               raw_pipe_addr = ts->mmap->RAW_PIPE1_ADDR;
-
-               for (y = 0; y < Y_Channel; y++) {
-                       //---change xdata index---
-                       buf[0] = 0xFF;
-                       buf[1] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 16) & 0xFF);
-                       buf[2] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 8) & 0xFF);
-                       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-                       buf[0] = (uint8_t)((raw_pipe_addr + y * X_Channel * 2) & 0xFF);
-                       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, X_Channel * 2 + 1);
-                       memcpy(rawdata_buf + y * X_Channel * 2, buf + 1, X_Channel * 2);
-               }
-#if TOUCH_KEY_NUM > 0
-               // to get button short baseline rawdata at pipe1
-               raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE1_ADDR;
-
-           //---change xdata index---
-               buf[0] = 0xFF;
-               buf[1] = (uint8_t)((raw_btn_pipe_addr >> 16) & 0xFF);
-               buf[2] = (uint8_t)((raw_btn_pipe_addr >> 8) & 0xFF);
-               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
-               buf[0] = (uint8_t)(raw_btn_pipe_addr & 0xFF);
-               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, Key_Channel * 2 + 1);
-               memcpy(rawdata_buf + Y_Channel * X_Channel * 2, buf + 1, Key_Channel * 2);
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-               for (y = 0; y < Y_Channel; y++) {
-                       for (x = 0; x < X_Channel; x++) {
-                               iArrayIndex = y * X_Channel + x;
-                               RawData_Short_Base[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]);
-                       }
-               }
-#if TOUCH_KEY_NUM > 0
-               for (k = 0; k < Key_Channel; k++) {
-                       iArrayIndex = Y_Channel * X_Channel + k;
-                       RawData_Short_Base[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]);
-               }
-#endif /* #if TOUCH_KEY_NUM > 0 */
-       }
-
-       if (rawdata_buf) {
-               kfree(rawdata_buf);
-               rawdata_buf = NULL;
-       }
-
-       //---Leave Test Mode---
-       nvt_change_mode(NORMAL_MODE);
-
-       if (ts->carrier_system)
-               printk("%s:RawData_Short_Diff:\n", __func__);
-       else
-               printk("%s:RawData_Short\n", __func__);
-       // Save Rawdata to CSV file
-       if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, SHORT_TEST_CSV_FILE, 0) < 0) {
-               NVT_ERR("save rawdata to CSV file failed\n");
-               return -EAGAIN;
-       }
-       if (ts->carrier_system) {
-#if TOUCH_KEY_NUM > 0
-               rawdata_short_base_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2 + Key_Channel * 7 + 2;
-#else
-               rawdata_short_base_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-               printk("%s:RawData_Short_Base:\n", __func__);
-               // Save Rawdata to CSV file
-               if (nvt_save_rawdata_to_csv(RawData_Short_Base, X_Channel, Y_Channel, SHORT_TEST_CSV_FILE, rawdata_short_base_offset) < 0) {
-                       NVT_ERR("save rawdata to CSV file failed\n");
-                       return -EAGAIN;
-               }
-       }
-
-       NVT_LOG("--\n");
-
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen raw data test for each single point function.
-
-return:
-       Executive outcomes. 0---passed. negative---failed.
-*******************************************************/
-static int32_t RawDataTest_SinglePoint_Sub(int32_t rawdata[], uint8_t RecordResult[], uint8_t x_ch, uint8_t y_ch, int32_t Rawdata_Limit_Postive[], int32_t Rawdata_Limit_Negative[])
-{
-       int32_t i = 0;
-       int32_t j = 0;
-#if TOUCH_KEY_NUM > 0
-    int32_t k = 0;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-       int32_t iArrayIndex = 0;
-       bool isPass = true;
-
-       for (j = 0; j < y_ch; j++) {
-               for (i = 0; i < x_ch; i++) {
-                       iArrayIndex = j * x_ch + i;
-
-                       RecordResult[iArrayIndex] = 0x00; // default value for PASS
-
-                       if(rawdata[iArrayIndex] > Rawdata_Limit_Postive[iArrayIndex])
-                               RecordResult[iArrayIndex] |= 0x01;
-
-                       if(rawdata[iArrayIndex] < Rawdata_Limit_Negative[iArrayIndex])
-                               RecordResult[iArrayIndex] |= 0x02;
-               }
-       }
-#if TOUCH_KEY_NUM > 0
-       for (k = 0; k < Key_Channel; k++) {
-               iArrayIndex = y_ch * x_ch + k;
-
-               RecordResult[iArrayIndex] = 0x00; // default value for PASS
-
-               if(rawdata[iArrayIndex] > Rawdata_Limit_Postive[iArrayIndex])
-                       RecordResult[iArrayIndex] |= 0x01;
-
-               if(rawdata[iArrayIndex] < Rawdata_Limit_Negative[iArrayIndex])
-                       RecordResult[iArrayIndex] |= 0x02;
-       }
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       //---Check RecordResult---
-       for (j = 0; j < y_ch; j++) {
-               for (i = 0; i < x_ch; i++) {
-                       if (RecordResult[j * x_ch + i] != 0) {
-                               isPass = false;
-                               break;
-                       }
-               }
-       }
-#if TOUCH_KEY_NUM > 0
-       for (k = 0; k < Key_Channel; k++) {
-               iArrayIndex = y_ch * x_ch + k;
-               if (RecordResult[iArrayIndex] != 0) {
-                       isPass = false;
-                       break;
-               }
-       }
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       if (isPass == false) {
-               return -1; // FAIL
-       } else {
-               return 0; // PASS
-       }
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen print self-test result function.
-
-return:
-       n.a.
-*******************************************************/
-void print_selftest_result(struct seq_file *m, int32_t TestResult, uint8_t RecordResult[], int32_t rawdata[], uint8_t x_len, uint8_t y_len)
-{
-       int32_t i = 0;
-       int32_t j = 0;
-       int32_t iArrayIndex = 0;
-#if TOUCH_KEY_NUM > 0
-       int32_t k = 0;
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-       switch (TestResult) {
-               case 0:
-                       nvt_mp_seq_printf(m, " PASS!\n");
-                       break;
-
-               case 1:
-                       nvt_mp_seq_printf(m, " ERROR! Read Data FAIL!\n");
-                       break;
-
-               case -1:
-                       nvt_mp_seq_printf(m, " FAIL!\n");
-                       nvt_mp_seq_printf(m, "RecordResult:\n");
-                       for (i = 0; i < y_len; i++) {
-                               for (j = 0; j < x_len; j++) {
-                                       iArrayIndex = i * x_len + j;
-                                       nvt_mp_seq_printf(m, "0x%02X, ", RecordResult[iArrayIndex]);
-                               }
-                               nvt_mp_seq_printf(m, "\n");
-                       }
-#if TOUCH_KEY_NUM > 0
-                       for (k = 0; k < Key_Channel; k++) {
-                               iArrayIndex = y_len * x_len + k;
-                               nvt_mp_seq_printf(m, "0x%02X, ", RecordResult[iArrayIndex]);
-                       }
-                       nvt_mp_seq_printf(m, "\n");
-#endif /* #if TOUCH_KEY_NUM > 0 */
-                       nvt_mp_seq_printf(m, "ReadData:\n");
-                       for (i = 0; i < y_len; i++) {
-                               for (j = 0; j < x_len; j++) {
-                                       iArrayIndex = i * x_len + j;
-                                       nvt_mp_seq_printf(m, "%5d, ", rawdata[iArrayIndex]);
-                               }
-                               nvt_mp_seq_printf(m, "\n");
-                       }
-#if TOUCH_KEY_NUM > 0
-                       for (k = 0; k < Key_Channel; k++) {
-                               iArrayIndex = y_len * x_len + k;
-                               nvt_mp_seq_printf(m, "%5d, ", rawdata[iArrayIndex]);
-                       }
-                       nvt_mp_seq_printf(m, "\n");
-#endif /* #if TOUCH_KEY_NUM > 0 */
-                       break;
-       }
-       nvt_mp_seq_printf(m, "\n");
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen self-test sequence print show
-       function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t c_show_selftest(struct seq_file *m, void *v)
-{
-#if NVT_TOUCH_MP_LENOVO
-       MP_TEST_RESULT mp_result = 0;
-#endif
-
-       NVT_LOG("++\n");
-#if !NVT_TOUCH_MP_LENOVO
-       nvt_mp_seq_printf(m, "FW Version: %d\n\n", ts->fw_ver);
-
-       nvt_mp_seq_printf(m, "Short Test");
-       if ((TestResult_Short == 0) || (TestResult_Short == 1)) {
-               print_selftest_result(m, TestResult_Short, RecordResult_Short, RawData_Short, X_Channel, Y_Channel);
-       } else { // TestResult_Short is -1
-               if (ts->carrier_system) {
-                       nvt_mp_seq_printf(m, " FAIL!\n");
-                       if (TestResult_Short_Diff == -1) {
-                               nvt_mp_seq_printf(m, "Short Diff");
-                               print_selftest_result(m, TestResult_Short_Diff, RecordResult_Short_Diff, RawData_Short_Diff, X_Channel, Y_Channel);
-                       }
-                       if (TestResult_Short_Base == -1) {
-                               nvt_mp_seq_printf(m, "Short Base");
-                               print_selftest_result(m, TestResult_Short_Base, RecordResult_Short_Base, RawData_Short_Base, X_Channel, Y_Channel);
-                       }
-               } else {
-                       print_selftest_result(m, TestResult_Short, RecordResult_Short, RawData_Short, X_Channel, Y_Channel);
-               }
-       }
-
-       nvt_mp_seq_printf(m, "Open Test");
-       print_selftest_result(m, TestResult_Open, RecordResult_Open, RawData_Open, X_Channel, Y_Channel);
-
-       nvt_mp_seq_printf(m, "FW Rawdata Test");
-       if ((TestResult_FW_Rawdata == 0) || (TestResult_FW_Rawdata == 1)) {
-                print_selftest_result(m, TestResult_FWMutual, RecordResult_FWMutual, RawData_FWMutual, X_Channel, Y_Channel);
-       } else { // TestResult_FW_Rawdata is -1
-               nvt_mp_seq_printf(m, " FAIL!\n");
-               if (TestResult_FWMutual == -1) {
-                       nvt_mp_seq_printf(m, "FW Mutual");
-                       print_selftest_result(m, TestResult_FWMutual, RecordResult_FWMutual, RawData_FWMutual, X_Channel, Y_Channel);
-               }
-               if (TestResult_FW_CC == -1) {
-                       if (ts->carrier_system) {
-                               if (TestResult_FW_CC_I == -1) {
-                                       nvt_mp_seq_printf(m, "FW CC_I");
-                                       print_selftest_result(m, TestResult_FW_CC_I, RecordResult_FW_CC_I, RawData_FW_CC_I, X_Channel, Y_Channel);
-                               }
-                               if (TestResult_FW_CC_Q == -1) {
-                                       nvt_mp_seq_printf(m, "FW CC_Q");
-                                       print_selftest_result(m, TestResult_FW_CC_Q, RecordResult_FW_CC_Q, RawData_FW_CC_Q, X_Channel, Y_Channel);
-                               }
-                       } else {
-                               nvt_mp_seq_printf(m, "FW CC");
-                               print_selftest_result(m, TestResult_FW_CC, RecordResult_FW_CC, RawData_FW_CC, X_Channel, Y_Channel);
-                       }
-               }
-       }
-
-       nvt_mp_seq_printf(m, "Noise Test");
-       if ((TestResult_Noise == 0) || (TestResult_Noise == 1)) {
-               print_selftest_result(m, TestResult_FW_DiffMax, RecordResult_FW_DiffMax, RawData_Diff_Max, X_Channel, Y_Channel);
-       } else { // TestResult_Noise is -1
-               nvt_mp_seq_printf(m, " FAIL!\n");
-
-               if (TestResult_FW_DiffMax == -1) {
-                       nvt_mp_seq_printf(m, "FW Diff Max");
-                       print_selftest_result(m, TestResult_FW_DiffMax, RecordResult_FW_DiffMax, RawData_Diff_Max, X_Channel, Y_Channel);
-               }
-               if (TestResult_FW_DiffMin == -1) {
-                       nvt_mp_seq_printf(m, "FW Diff Min");
-                       print_selftest_result(m, TestResult_FW_DiffMin, RecordResult_FW_DiffMin, RawData_Diff_Min, X_Channel, Y_Channel);
-               }
-       }
-#else
-       /* short */
-       if (TestResult_Short >= 0)
-               mp_result |= (!!TestResult_Short << MP_RESULT_SHIFT_SHORT);
-       else {
-               if (ts->carrier_system) {
-                       mp_result |= (!!TestResult_Short_Diff << MP_RESULT_SHIFT_SHORT_DIFF);
-                       mp_result |= (!!TestResult_Short_Base << MP_RESULT_SHIFT_SHORT_BASE);
-               } else {
-                       mp_result |= (!!TestResult_Short << MP_RESULT_SHIFT_SHORT);
-               }
-       }
-
-       /* open */
-       mp_result |= (!!TestResult_Open << MP_RESULT_SHIFT_OPEN);
-
-       /* raw data & cc */
-       if (TestResult_FW_Rawdata >= 0)
-               mp_result |= (!!TestResult_FWMutual << MP_RESULT_SHIFT_RAWDATA);
-       else {
-               if (TestResult_FWMutual == -1) {
-                       mp_result |= (!!TestResult_FWMutual << MP_RESULT_SHIFT_RAWDATA);
-               }
-               if (TestResult_FW_CC == -1) {
-                       if (ts->carrier_system) {
-                               mp_result |= (!!TestResult_FW_CC_I << MP_RESULT_SHIFT_CC_I);
-                               mp_result |= (!!TestResult_FW_CC_Q << MP_RESULT_SHIFT_CC_Q);
-                       } else {
-                               mp_result |= (!!TestResult_FW_CC << MP_RESULT_SHIFT_CC);
-                       }
-               }
-       }
-
-       /* noise */
-       if (TestResult_Noise >= 0)
-               mp_result |= (!!TestResult_FW_DiffMax << MP_RESULT_SHIFT_DIFF_MAX);
-       else {
-               if (TestResult_FW_DiffMax == -1) {
-                       mp_result |= (!!TestResult_FW_DiffMax << MP_RESULT_SHIFT_DIFF_MAX);
-               }
-               if (TestResult_FW_DiffMin == -1) {
-                       mp_result |= (!!TestResult_FW_DiffMin << MP_RESULT_SHIFT_DIFF_MIN);
-               }
-       }
-
-       nvt_mp_seq_printf(m, "%d", mp_result);
-#endif
-       nvt_mp_test_result_printed = 1;
-
-       NVT_LOG("--\n");
-
-    return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen self-test sequence print start
-       function.
-
-return:
-       Executive outcomes. 1---call next function.
-       NULL---not call next function and sequence loop
-       stop.
-*******************************************************/
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
-       return *pos < 1 ? (void *)1 : NULL;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen self-test sequence print next
-       function.
-
-return:
-       Executive outcomes. NULL---no next and call sequence
-       stop function.
-*******************************************************/
-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
-{
-       ++*pos;
-       return NULL;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen self-test sequence print stop
-       function.
-
-return:
-       n.a.
-*******************************************************/
-static void c_stop(struct seq_file *m, void *v)
-{
-       return;
-}
-
-const struct seq_operations nvt_selftest_seq_ops = {
-       .start  = c_start,
-       .next   = c_next,
-       .stop   = c_stop,
-       .show   = c_show_selftest
-};
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/nvt_selftest open function.
-
-return:
-       Executive outcomes. 0---succeed. negative---failed.
-*******************************************************/
-static int32_t nvt_selftest_open(struct inode *inode, struct file *file)
-{
-       struct device_node *np = ts->client->dev.of_node;
-       unsigned char mpcriteria[32] = {0};     //novatek-mp-criteria-default
-
-       TestResult_Short = 0;
-       TestResult_Short_Diff = 0;
-       TestResult_Short_Base = 0;
-       TestResult_Open = 0;
-       TestResult_FW_Rawdata = 0;
-       TestResult_FWMutual = 0;
-       TestResult_FW_CC = 0;
-       TestResult_FW_CC_I = 0;
-       TestResult_FW_CC_Q = 0;
-       TestResult_Noise = 0;
-       TestResult_FW_DiffMax = 0;
-       TestResult_FW_DiffMin = 0;
-
-       NVT_LOG("++\n");
-
-       if (mutex_lock_interruptible(&ts->lock)) {
-               return -ERESTARTSYS;
-       }
-#if NVT_TOUCH_ESD_PROTECT
-               nvt_esd_check_enable(false);
-#endif
-
-       if (nvt_get_fw_info()) {
-               mutex_unlock(&ts->lock);
-               NVT_ERR("get fw info failed!\n");
-               return -EAGAIN;
-       }
-
-       /* Parsing criteria from dts */
-       if(of_property_read_bool(np, "novatek,mp-support-dt")) {
-               /*
-                * Parsing Criteria by Novatek PID
-                * The string rule is "novatek-mp-criteria-<nvt_pid>"
-                * nvt_pid is 2 bytes (show hex).
-                *
-                * Ex. nvt_pid = 500A
-                *     mpcriteria = "novatek-mp-criteria-500A"
-                */
-               snprintf(mpcriteria, PAGE_SIZE, "novatek-mp-criteria-%04X", ts->nvt_pid);
-
-               nvt_mp_parse_dt(np, mpcriteria);
-       } else {
-               NVT_LOG("Not found novatek,mp-support-dt, use default setting\n");
-               //---Print Test Criteria---
-               nvt_print_criteria();
-       }
-
-       if (nvt_switch_FreqHopEnDis(FREQ_HOP_DISABLE)) {
-               mutex_unlock(&ts->lock);
-               NVT_ERR("switch frequency hopping disable failed!\n");
-               return -EAGAIN;
-       }
-
-       if (nvt_check_fw_reset_state(RESET_STATE_NORMAL_RUN)) {
-               mutex_unlock(&ts->lock);
-               NVT_ERR("check fw reset state failed!\n");
-               return -EAGAIN;
-       }
-
-       msleep(100);
-
-       //---Enter Test Mode---
-       if (nvt_clear_fw_status()) {
-               mutex_unlock(&ts->lock);
-               NVT_ERR("clear fw status failed!\n");
-               return -EAGAIN;
-       }
-
-       nvt_change_mode(MP_MODE_CC);
-
-       if (nvt_check_fw_status()) {
-               mutex_unlock(&ts->lock);
-               NVT_ERR("check fw status failed!\n");
-               return -EAGAIN;
-       }
-
-       //---FW Rawdata Test---
-       if (nvt_read_baseline(RawData_FWMutual) != 0) {
-               TestResult_FWMutual = 1;
-       } else {
-               TestResult_FWMutual = RawDataTest_SinglePoint_Sub(RawData_FWMutual, RecordResult_FWMutual, X_Channel, Y_Channel,
-                                                                                               PS_Config_Lmt_FW_Rawdata_P, PS_Config_Lmt_FW_Rawdata_N);
-       }
-       if (nvt_read_CC(RawData_FW_CC) != 0) {
-               TestResult_FW_CC = 1;
-               if (ts->carrier_system) {
-                       TestResult_FW_CC_I = 1;
-                       TestResult_FW_CC_Q = 1;
-               }
-       } else {
-               if (ts->carrier_system) {
-                       TestResult_FW_CC_I = RawDataTest_SinglePoint_Sub(RawData_FW_CC_I, RecordResult_FW_CC_I, X_Channel, Y_Channel,
-                                                                                               PS_Config_Lmt_FW_CC_I_P, PS_Config_Lmt_FW_CC_I_N);
-                       TestResult_FW_CC_Q = RawDataTest_SinglePoint_Sub(RawData_FW_CC_Q, RecordResult_FW_CC_Q, X_Channel, Y_Channel,
-                                                                                               PS_Config_Lmt_FW_CC_Q_P, PS_Config_Lmt_FW_CC_Q_N);
-                       if ((TestResult_FW_CC_I == -1) || (TestResult_FW_CC_Q == -1))
-                               TestResult_FW_CC = -1;
-                       else
-                               TestResult_FW_CC = 0;
-               } else {
-                       TestResult_FW_CC = RawDataTest_SinglePoint_Sub(RawData_FW_CC, RecordResult_FW_CC, X_Channel, Y_Channel,
-                                                                                               PS_Config_Lmt_FW_CC_P, PS_Config_Lmt_FW_CC_N);
-               }
-       }
-
-       if ((TestResult_FWMutual == 1) || (TestResult_FW_CC == 1)) {
-               TestResult_FW_Rawdata = 1;
-       } else {
-               if ((TestResult_FWMutual == -1) || (TestResult_FW_CC == -1))
-                       TestResult_FW_Rawdata = -1;
-               else
-                       TestResult_FW_Rawdata = 0;
-       }
-
-       //---Leave Test Mode---
-       nvt_change_mode(NORMAL_MODE);
-
-       //---Noise Test---
-       if (nvt_read_fw_noise(RawData_Diff) != 0) {
-               TestResult_Noise = 1;   // 1: ERROR
-               TestResult_FW_DiffMax = 1;
-               TestResult_FW_DiffMin = 1;
-       } else {
-               TestResult_FW_DiffMax = RawDataTest_SinglePoint_Sub(RawData_Diff_Max, RecordResult_FW_DiffMax, X_Channel, Y_Channel,
-                                                                                       PS_Config_Lmt_FW_Diff_P, PS_Config_Lmt_FW_Diff_N);
-
-               // for carrier sensing system, only positive noise data
-               if (ts->carrier_system) {
-                       TestResult_FW_DiffMin = 0;
-               } else {
-                       TestResult_FW_DiffMin = RawDataTest_SinglePoint_Sub(RawData_Diff_Min, RecordResult_FW_DiffMin, X_Channel, Y_Channel,
-                                                                                               PS_Config_Lmt_FW_Diff_P, PS_Config_Lmt_FW_Diff_N);
-               }
-
-               if ((TestResult_FW_DiffMax == -1) || (TestResult_FW_DiffMin == -1))
-                       TestResult_Noise = -1;
-               else
-                       TestResult_Noise = 0;
-       }
-
-       //--Short Test---
-       if (nvt_read_fw_short(RawData_Short) != 0) {
-               TestResult_Short = 1; // 1:ERROR
-               if (ts->carrier_system) {
-                       TestResult_Short_Diff = 1;
-                       TestResult_Short_Base = 1;
-               }
-       } else {
-               //---Self Test Check --- // 0:PASS, -1:FAIL
-               if (ts->carrier_system) {
-                       TestResult_Short_Diff = RawDataTest_SinglePoint_Sub(RawData_Short_Diff, RecordResult_Short_Diff, X_Channel, Y_Channel,
-                                                                                       PS_Config_Lmt_Short_Diff_P, PS_Config_Lmt_Short_Diff_N);
-                       TestResult_Short_Base = RawDataTest_SinglePoint_Sub(RawData_Short_Base, RecordResult_Short_Base, X_Channel, Y_Channel,
-                                                                                       PS_Config_Lmt_Short_Base_P, PS_Config_Lmt_Short_Base_N);
-
-                       if ((TestResult_Short_Diff == -1) || (TestResult_Short_Base == -1))
-                               TestResult_Short = -1;
-                       else
-                               TestResult_Short = 0;
-               } else {
-                       TestResult_Short = RawDataTest_SinglePoint_Sub(RawData_Short, RecordResult_Short, X_Channel, Y_Channel,
-                                                                                       PS_Config_Lmt_Short_Rawdata_P, PS_Config_Lmt_Short_Rawdata_N);
-               }
-       }
-
-       //---Open Test---
-       if (nvt_read_fw_open(RawData_Open) != 0) {
-               TestResult_Open = 1;    // 1:ERROR
-       } else {
-               //---Self Test Check --- // 0:PASS, -1:FAIL
-               TestResult_Open = RawDataTest_SinglePoint_Sub(RawData_Open, RecordResult_Open, X_Channel, Y_Channel,
-                                                                                       PS_Config_Lmt_Open_Rawdata_P, PS_Config_Lmt_Open_Rawdata_N);
-       }
-
-       //---Reset IC---
-       nvt_bootloader_reset();
-
-       mutex_unlock(&ts->lock);
-
-       NVT_LOG("--\n");
-
-       nvt_mp_test_result_printed = 0;
-
-       return seq_open(file, &nvt_selftest_seq_ops);
-}
-
-static const struct file_operations nvt_selftest_fops = {
-       .owner = THIS_MODULE,
-       .open = nvt_selftest_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release,
-};
-
-#if NVT_TOUCH_MP_LENOVO
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/NVTflash read function.
-
-return:
-       Executive outcomes. 2---succeed. -5,-14---failed.
-*******************************************************/
-static ssize_t nvt_data_read(struct file *file, char __user *buff, size_t count, loff_t *offp)
-{
-       uint8_t *str;
-       int32_t ret = -1;
-       int32_t retries = 0;
-       int8_t i2c_wr = 0;
-       uint8_t i2c_addr = 0;
-       uint32_t data_len = 0;
-
-       NVT_LOG("++\n");
-
-       if (count > (40 * (40 + 4) * 2 + 7)) {
-               NVT_ERR("error count=%zu\n", count);
-               return -EFAULT;
-       }
-
-       str = kmalloc(40 * (40 + 4) * 2 + 7, GFP_KERNEL);
-       if (str == NULL) {
-               NVT_ERR("failed to allocated memory for input data\n");
-               return -ENOMEM;
-       }
-
-       if (copy_from_user(str, buff, count)) {
-               NVT_ERR("copy from user error\n");
-               return -EFAULT;
-       }
-
-#if NVT_TOUCH_ESD_PROTECT
-       nvt_esd_check_enable(false);
-#endif
-
-       i2c_wr = str[0] >> 7;
-       i2c_addr = str[0] & 0x7F;
-       data_len = (int32_t)((str[1] << 8) + str[2]);
-
-       if (i2c_wr == 0) {
-               return -ENOTSUPP;
-       } else if (i2c_wr == 1) {
-               while (retries < 20) {
-                       ret = nvt_read_mass_data(i2c_addr, str, data_len);
-                       if (ret == data_len)
-                               break;
-                       else
-                               NVT_ERR("error, retries=%d, ret=%d, data_len=%d\n", retries, ret, data_len);
-
-                       retries++;
-               }
-
-               if (retries < 20) {
-                       ret = copy_to_user(buff, str, data_len);
-                       if (ret) {
-                               NVT_ERR("error, copy_to_user, ret=%d, data_len=%d\n", ret, data_len);
-                               return -EFAULT;
-                       }
-               }
-
-               if (unlikely(retries == 20)) {
-                       NVT_ERR("error, ret = %d\n", ret);
-                       return -EIO;
-               }
-       } else {
-               NVT_ERR("Call error, str[0]=%d\n", str[0]);
-               return -EFAULT;
-       }
-
-       kfree(str);
-       NVT_LOG("--\n");
-       return ret;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/NVTflash open function.
-
-return:
-       Executive outcomes. 0---succeed. -12---failed.
-*******************************************************/
-static int32_t nvt_data_open(struct inode *inode, struct file *file)
-{
-       struct nvt_flash_data *dev;
-
-       dev = kmalloc(sizeof(struct nvt_flash_data), GFP_KERNEL);
-       if (dev == NULL) {
-               NVT_ERR("Failed to allocate memory for nvt flash data\n");
-               return -ENOMEM;
-       }
-
-       rwlock_init(&dev->lock);
-       file->private_data = dev;
-
-       return 0;
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen /proc/NVTflash close function.
-
-return:
-       Executive outcomes. 0---succeed.
-*******************************************************/
-static int32_t nvt_data_close(struct inode *inode, struct file *file)
-{
-       struct nvt_flash_data *dev = file->private_data;
-
-       if (dev)
-               kfree(dev);
-
-       return 0;
-}
-
-static const struct file_operations nvt_read_data_fops = {
-       .owner = THIS_MODULE,
-       .open = nvt_data_open,
-       .release = nvt_data_close,
-       .read = nvt_data_read,
-};
-#endif
-
-#ifdef CONFIG_OF
-/*******************************************************
-Description:
-       Novatek touchscreen parse AIN setting for array type.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_mp_parse_ain(struct device_node *np, const char *name, uint8_t *array, int32_t size)
-{
-       struct property *data;
-       int32_t len, ret;
-       int32_t tmp[40];
-       int32_t i;
-
-       data = of_find_property(np, name, &len);
-       len /= sizeof(u32);
-
-       if ((!data) || (!len) || (len != size)) {
-               NVT_ERR("error find %s. len=%d\n", name, len);
-       } else {
-               NVT_LOG("%s. len=%d\n", name, len);
-               ret = of_property_read_u32_array(np, name, tmp, len);
-               if (ret) {
-                       NVT_ERR("error reading %s. ret=%d\n", name, ret);
-                       return;
-               }
-
-               for (i = 0; i < len; i++)
-                       array[i] = tmp[i];
-
-#if NVT_DEBUG
-               printk("[NVT-ts] %s = ", name);
-               for (i = 0; i < len; i++) {
-                       printk("%02d ", array[i]);
-               }
-               printk("\n");
-#endif
-       }
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen parse criterion for u32 type.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_mp_parse_u32(struct device_node *np, const char *name, int32_t *para)
-{
-       int32_t ret;
-
-       ret = of_property_read_u32(np, name, para);
-       if (ret)
-               NVT_ERR("error reading %s. ret=%d\n", name, ret);
-       else {
-#if NVT_DEBUG
-               NVT_LOG("%s=%d\n", name, *para);
-#endif
-       }
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen parse criterion for array type.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_mp_parse_array(struct device_node *np, const char *name, int32_t *array,
-               int32_t size)
-{
-       struct property *data;
-       int32_t len, ret;
-#if NVT_DEBUG
-       int32_t i, j, iArrayIndex = 0;
-#endif
-
-       data = of_find_property(np, name, &len);
-       len /= sizeof(u32);
-       if ((!data) || (!len) || (len < size)) {
-               NVT_ERR("error find %s. len=%d\n", name, len);
-       } else {
-               NVT_LOG("%s. len=%d\n", name, len);
-               ret = of_property_read_u32_array(np, name, array, len);
-               if (ret) {
-                       NVT_ERR("error reading %s. ret=%d\n", name, ret);
-                       return;
-               }
-
-#if NVT_DEBUG
-               NVT_LOG("%s =\n", name);
-               for (j = 0; j < Y_Channel; j++) {
-                       printk("[NVT-ts] ");
-                       for (i = 0; i < X_Channel; i++) {
-                               iArrayIndex = j * X_Channel + i;
-                               printk("%5d, ", array[iArrayIndex]);
-                       }
-                       printk("\n");
-               }
-#if TOUCH_KEY_NUM > 0
-               printk("[NVT-ts] ");
-               for (i = 0; i < Key_Channel; i++) {
-                       iArrayIndex++;
-                       printk("%5d, ", array[iArrayIndex]);
-               }
-               printk("\n");
-#endif
-#endif
-       }
-}
-
-/*******************************************************
-Description:
-       Novatek touchscreen parse device tree mp function.
-
-return:
-       n.a.
-*******************************************************/
-void nvt_mp_parse_dt(struct device_node *root, const char *node_compatible)
-{
-       struct device_node *np = root;
-       struct device_node *child = NULL;
-
-       NVT_LOG("Parse mp criteria for node %s\n", node_compatible);
-
-       /* find each MP sub-nodes */
-       for_each_child_of_node(root, child) {
-               /* find the specified node */
-               if (of_device_is_compatible(child, node_compatible)) {
-                       NVT_LOG("found child node %s\n", node_compatible);
-                       np = child;
-                       break;
-               }
-       }
-       if (child == NULL) {
-               NVT_ERR("Not found compatible node %s, use default setting!\n", node_compatible);
-               return;
-       }
-
-       /* MP Config*/
-       nvt_mp_parse_u32(np, "IC_X_CFG_SIZE", &IC_X_CFG_SIZE);
-
-       nvt_mp_parse_u32(np, "IC_Y_CFG_SIZE", &IC_Y_CFG_SIZE);
-
-#if TOUCH_KEY_NUM > 0
-       nvt_mp_parse_u32(np, "IC_KEY_CFG_SIZE", &IC_KEY_CFG_SIZE);
-#endif
-
-       nvt_mp_parse_u32(np, "X_Channel", &X_Channel);
-
-       nvt_mp_parse_u32(np, "Y_Channel", &Y_Channel);
-
-       nvt_mp_parse_ain(np, "AIN_X", AIN_X, IC_X_CFG_SIZE);
-
-       nvt_mp_parse_ain(np, "AIN_Y", AIN_Y, IC_Y_CFG_SIZE);
-
-#if TOUCH_KEY_NUM > 0
-       nvt_mp_parse_ain(np, "AIN_KEY", AIN_KEY, IC_KEY_CFG_SIZE);
-#endif
-
-       /* MP Criteria */
-       if (ts->carrier_system) {
-               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Diff_P", PS_Config_Lmt_Short_Diff_P,
-                               X_Channel * Y_Channel + Key_Channel);
-
-               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Diff_N", PS_Config_Lmt_Short_Diff_N,
-                               X_Channel * Y_Channel + Key_Channel);
-
-               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Base_P", PS_Config_Lmt_Short_Base_P,
-                               X_Channel * Y_Channel + Key_Channel);
-
-               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Base_N", PS_Config_Lmt_Short_Base_N,
-                               X_Channel * Y_Channel + Key_Channel);
-       } else {
-               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Rawdata_P", PS_Config_Lmt_Short_Rawdata_P,
-                               X_Channel * Y_Channel + Key_Channel);
-
-               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Rawdata_N", PS_Config_Lmt_Short_Rawdata_N,
-                               X_Channel * Y_Channel + Key_Channel);
-       }
-
-       nvt_mp_parse_array(np, "PS_Config_Lmt_Open_Rawdata_P", PS_Config_Lmt_Open_Rawdata_P,
-                       X_Channel * Y_Channel + Key_Channel);
-
-       nvt_mp_parse_array(np, "PS_Config_Lmt_Open_Rawdata_N", PS_Config_Lmt_Open_Rawdata_N,
-                       X_Channel * Y_Channel + Key_Channel);
-
-       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Rawdata_P", PS_Config_Lmt_FW_Rawdata_P,
-                       X_Channel * Y_Channel + Key_Channel);
-
-       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Rawdata_N", PS_Config_Lmt_FW_Rawdata_N,
-                       X_Channel * Y_Channel + Key_Channel);
-
-       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_P", PS_Config_Lmt_FW_CC_P,
-                       X_Channel * Y_Channel + Key_Channel);
-
-       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_N", PS_Config_Lmt_FW_CC_N,
-                       X_Channel * Y_Channel + Key_Channel);
-
-       if (ts->carrier_system) {
-               nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_I_P", PS_Config_Lmt_FW_CC_I_P,
-                               X_Channel * Y_Channel + Key_Channel);
-
-               nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_I_N", PS_Config_Lmt_FW_CC_I_N,
-                               X_Channel * Y_Channel + Key_Channel);
-
-               nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_Q_P", PS_Config_Lmt_FW_CC_Q_P,
-                               X_Channel * Y_Channel + Key_Channel);
-
-               nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_Q_N", PS_Config_Lmt_FW_CC_Q_N,
-                               X_Channel * Y_Channel + Key_Channel);
-       }
-
-       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Diff_P", PS_Config_Lmt_FW_Diff_P,
-                       X_Channel * Y_Channel + Key_Channel);
-
-       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Diff_N", PS_Config_Lmt_FW_Diff_N,
-                       X_Channel * Y_Channel + Key_Channel);
-       nvt_mp_parse_u32(np, "PS_Config_Diff_Test_Frame", &PS_Config_Diff_Test_Frame);
-
-       NVT_LOG("Parse mp criteria done!\n");
-}
-#endif
-
-/*******************************************************
-Description:
-       Novatek touchscreen MP function proc. file node
-       initial function.
-
-return:
-       Executive outcomes. 0---succeed. -1---failed.
-*******************************************************/
-int32_t nvt_mp_proc_init(void)
-{
-       int32_t ret = 0;
-
-       NVT_proc_selftest_entry = proc_create("nvt_selftest", 0444, NULL, &nvt_selftest_fops);
-       if (NVT_proc_selftest_entry == NULL) {
-               NVT_ERR("create /proc/nvt_selftest Failed!\n");
-               ret = -1;
-       } else {
-               if(nvt_mp_buffer_init()) {
-                       NVT_ERR("Allocate mp memory failed\n");
-                       ret = -1;
-               }
-               else {
-                       NVT_LOG("create /proc/nvt_selftest Succeeded!\n");
-               }
-               ret = 0;
-       }
-#if NVT_TOUCH_MP_LENOVO
-       if (ret == 0) {
-               NVT_proc_selftest_read_data = proc_create("nvt_read_data", 0444, NULL, &nvt_read_data_fops);
-               if (NVT_proc_selftest_read_data == NULL) {
-                       NVT_ERR("create /proc/nvt_read_data Failed!\n");
-                       ret = -1;
-               } else {
-                       NVT_LOG("create /proc/nvt_read_data Succeeded!\n");
-               }
-       }
-#endif
-       return ret;
-}
-
-#endif /* #if NVT_TOUCH_MP */
diff --git a/drivers/input/touchscreen/nt36672a/nt36xxx_mp_ctrlram.h b/drivers/input/touchscreen/nt36672a/nt36xxx_mp_ctrlram.h
deleted file mode 100755 (executable)
index bd9f949..0000000
+++ /dev/null
@@ -1,740 +0,0 @@
-/*
- * Copyright (C) 2010 - 2017 Novatek, Inc.
- *
- * $Revision: 22971 $
- * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-
-#if NVT_TOUCH_MP
-
-static uint32_t IC_X_CFG_SIZE = 18;
-static uint32_t IC_Y_CFG_SIZE = 36;
-static uint32_t IC_KEY_CFG_SIZE = 4;
-static uint32_t X_Channel = 18;
-static uint32_t Y_Channel = 34;
-static uint32_t Key_Channel = TOUCH_KEY_NUM;
-static uint8_t AIN_X[40] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
-static uint8_t AIN_Y[40] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
-                                                       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 0xFF, 0xFF};
-#if TOUCH_KEY_NUM > 0
-static uint8_t AIN_KEY[8] = {0, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-#endif /* #if TOUCH_KEY_NUM > 0 */
-
-static int32_t PS_Config_Lmt_Short_Rawdata_P[40 * 40] = {
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
-#if TOUCH_KEY_NUM > 0
-       20000,20000,20000,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_Short_Rawdata_N[40 * 40] = {
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
-#if TOUCH_KEY_NUM > 0
-       11550,11550,11550,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_Short_Diff_P[40 * 40] = {
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
-#if TOUCH_KEY_NUM > 0
-       6300,6300,6300,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_Short_Diff_N[40 * 40] = {
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-#if TOUCH_KEY_NUM > 0
-       0,0,0,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_Short_Base_P[40 * 40] = {
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
-#if TOUCH_KEY_NUM > 0
-       2000,2000,2000,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_Short_Base_N[40 * 40] = {
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
-#if TOUCH_KEY_NUM > 0
-       -2000,-2000,-2000,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_Open_Rawdata_P[40 * 40] = {
-       5830,2470,3134,2675,6215, 590, 616, 542, 600,2505,2447,2511,2488,6273,4533,3227,2617,6119,
-       2967,3669,3098,6069,5039,4702,4552,4654,4525,2545,2653,2584,2695,3051,3680,5123,5934,3186,
-       2831,3440,2926,3081,2920,3067,2910,3055,2916,2883,3046,2916,3049,2907,3448,2893,3039,2908,
-       2762,3353,2877,3020,2873,3008,2865,2999,2872,2813,2961,2871,2990,2862,3389,2846,2979,2861,
-       2815,3410,2895,3040,2892,3031,2886,3023,2891,2863,3015,2890,3012,2881,3408,2865,3000,2881,
-       2773,3357,2846,2980,2844,2974,2840,2967,2846,2817,2958,2843,2952,2832,3347,2816,2942,2838,
-       2775,3362,2822,2953,2846,2975,2846,2970,2851,2825,2966,2823,2929,2838,3353,2823,2943,2838,
-       2730,3176,2803,2925,2797,2898,2800,2914,2807,2778,2906,2804,2901,2787,3160,2772,2879,2788,
-       2741,2939,2813,2938,2807,2909,2814,2930,2817,2791,2922,2815,2914,2798,2913,2784,2893,2801,
-       2691,2875,2761,2878,2758,2849,2767,2869,2765,2756,2857,2764,2863,2745,2849,2734,2830,2748,
-       2684,2861,2750,2862,2724,2812,2758,2859,2757,2750,2843,2759,2855,2714,2809,2726,2821,2743,
-       2714,2871,2768,2868,2771,2852,2785,2881,2788,2787,2867,2786,2866,2759,2844,2743,2830,2768,
-       2725,2885,2781,2884,2781,2871,2803,2901,2799,2804,2881,2798,2877,2770,2863,2755,2849,2780,
-       2554,2710,2612,2700,2616,2690,2607,2683,2624,2629,2676,2623,2693,2604,2680,2569,2649,2614,
-       2558,2712,2615,2703,2620,2697,2638,2717,2629,2634,2683,2627,2694,2607,2684,2598,2688,2621,
-       2487,2628,2541,2619,2548,2616,2567,2626,2554,2560,2605,2553,2607,2534,2599,2525,2611,2548,
-       2492,2625,2538,2616,2545,2617,2567,2618,2531,2561,2605,2552,2605,2531,2598,2524,2615,2527,
-       2399,2515,2447,2508,2450,2506,2476,2508,2461,2466,2499,2461,2494,2437,2491,2433,2508,2457,
-       2393,2510,2442,2501,2446,2503,2471,2502,2469,2465,2507,2458,2489,2433,2489,2430,2513,2450,
-       2316,2419,2363,2414,2372,2418,2394,2413,2387,2386,2414,2377,2399,2354,2399,2352,2432,2370,
-       2287,2391,2354,2404,2369,2415,2387,2407,2373,2360,2374,2365,2389,2344,2391,2342,2431,2363,
-       2214,2303,2260,2294,2276,2306,2296,2295,2278,2286,2300,2272,2276,2251,2284,2252,2316,2270,
-       2283,2365,2323,2419,2345,2376,2370,2379,2355,2360,2374,2341,2338,2316,2349,2317,2447,2344,
-       2225,2304,2245,2634,2280,2300,2303,2304,2284,2278,2285,2254,2257,2247,2265,2262,2684,2285,
-       2099,2175,2147,2528,2158,2167,2175,2165,2146,2149,2154,2145,2143,2128,2141,2145,2553,2157,
-       2005,2144,2065,2312,2074,2119,2085,2137,2057,2055,2112,2055,2113,2044,2112,2059,2337,2060,
-       1970,2107,2031,2273,2042,2082,2052,2081,2028,2018,2074,2021,2072,2011,2072,2029,2301,2026,
-       1894,2019,1958,2188,1958,1983,1977,1992,1954,1938,1978,1940,1980,1924,1971,1954,2213,1948,
-       1840,1957,1908,2127,1918,1929,1925,1929,1895,1888,1917,1891,1919,1886,1925,1907,2154,1896,
-       1767,1872,1837,2045,1846,1845,1854,1844,1822,1813,1827,1815,1834,1814,1842,1836,2067,1818,
-       1726,1830,1800,2004,1810,1802,1813,1791,1784,1772,1779,1776,1791,1776,1798,1796,2021,1777,
-       1658,1750,1733,1929,1741,1722,1750,1719,1709,1701,1695,1704,1713,1709,1724,1737,1948,1706,
-       1499,2086,1889,1954,1768,1745,1774,1735,1732,1720,1710,1724,1735,1732,1748,1762,1975,1461,
-       3326,3789,3764,1741,1713,1721,1704,1695,1703,1796,1816,1835,1821,1834,2028,1708,1674,1383,
-#if TOUCH_KEY_NUM > 0
-       13000,13000,13000,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_Open_Rawdata_N[40 * 40] = {
-       3139,1330,1688,1440,3346, 317, 332, 292, 323,1349,1318,1352,1340,3378,2441,1738,1409,3295,
-       1597,1975,1668,3268,2714,2532,2451,2506,2437,1371,1428,1391,1451,1643,1981,2759,3195,1715,
-       1525,1852,1575,1659,1572,1652,1567,1645,1570,1552,1640,1570,1642,1565,1857,1558,1636,1566,
-       1487,1806,1549,1626,1547,1620,1543,1615,1547,1514,1595,1546,1610,1541,1825,1532,1604,1541,
-       1516,1836,1559,1637,1557,1632,1554,1628,1557,1541,1623,1556,1622,1551,1835,1543,1616,1551,
-       1493,1808,1532,1605,1531,1601,1529,1597,1532,1517,1593,1531,1590,1525,1802,1516,1584,1528,
-       1494,1810,1520,1590,1532,1602,1533,1599,1535,1521,1597,1520,1577,1528,1805,1520,1585,1528,
-       1470,1710,1509,1575,1506,1560,1508,1569,1511,1496,1565,1510,1562,1501,1702,1493,1550,1501,
-       1476,1583,1515,1582,1512,1567,1515,1578,1517,1503,1573,1516,1569,1507,1568,1499,1558,1508,
-       1449,1548,1487,1550,1485,1534,1490,1545,1489,1484,1539,1489,1542,1478,1534,1472,1524,1480,
-       1445,1541,1481,1541,1467,1514,1485,1539,1485,1481,1531,1485,1537,1461,1513,1468,1519,1477,
-       1461,1546,1490,1544,1492,1536,1499,1551,1501,1501,1544,1500,1543,1486,1532,1477,1524,1491,
-       1467,1553,1498,1553,1498,1546,1509,1562,1507,1510,1551,1507,1549,1492,1541,1483,1534,1497,
-       1375,1459,1406,1454,1409,1448,1404,1445,1413,1416,1441,1413,1450,1402,1443,1383,1426,1407,
-       1378,1460,1408,1455,1411,1452,1420,1463,1416,1418,1445,1414,1451,1404,1445,1399,1448,1411,
-       1339,1415,1368,1410,1372,1409,1382,1414,1375,1379,1403,1375,1404,1365,1399,1360,1406,1372,
-       1342,1414,1367,1408,1370,1409,1382,1410,1363,1379,1402,1374,1403,1363,1399,1359,1408,1361,
-       1292,1354,1318,1350,1319,1349,1333,1350,1325,1328,1346,1325,1343,1312,1341,1310,1351,1323,
-       1289,1351,1315,1347,1317,1348,1330,1347,1329,1327,1350,1324,1340,1310,1340,1308,1353,1319,
-       1247,1302,1272,1300,1277,1302,1289,1299,1285,1285,1300,1280,1292,1267,1292,1266,1309,1276,
-       1232,1288,1267,1295,1276,1300,1286,1296,1278,1271,1278,1274,1286,1262,1287,1261,1309,1272,
-       1192,1240,1217,1235,1225,1242,1236,1236,1226,1231,1239,1224,1226,1212,1230,1213,1247,1222,
-       1229,1273,1251,1302,1263,1279,1276,1281,1268,1271,1278,1261,1259,1247,1265,1248,1318,1262,
-       1198,1241,1209,1418,1228,1239,1240,1241,1230,1227,1230,1214,1215,1210,1220,1218,1445,1231,
-       1130,1171,1156,1361,1162,1167,1171,1166,1155,1157,1160,1155,1154,1146,1153,1155,1375,1161,
-       1080,1155,1112,1245,1117,1141,1123,1151,1108,1107,1137,1107,1138,1100,1137,1109,1258,1109,
-       1061,1134,1093,1224,1099,1121,1105,1120,1092,1087,1117,1088,1116,1083,1116,1093,1239,1091,
-       1020,1087,1054,1178,1054,1068,1065,1072,1052,1044,1065,1044,1066,1036,1061,1052,1191,1049,
-        991,1054,1028,1145,1033,1039,1036,1038,1020,1016,1032,1018,1033,1015,1037,1027,1160,1021,
-        952,1008, 989,1101, 994, 993, 998, 993, 981, 976, 984, 977, 988, 977, 992, 989,1113, 979,
-        929, 985, 969,1079, 975, 970, 976, 965, 960, 954, 958, 956, 964, 956, 968, 967,1088, 957,
-        893, 942, 933,1039, 938, 927, 942, 926, 920, 916, 912, 918, 922, 920, 928, 935,1049, 918,
-        807,1123,1017,1052, 952, 940, 955, 934, 932, 926, 921, 928, 934, 933, 941, 949,1063, 787,
-       1791,2040,2027, 937, 922, 927, 918, 913, 917, 967, 978, 988, 981, 987,1092, 920, 901, 745,
-#if TOUCH_KEY_NUM > 0
-       6500,6500,6500,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_Rawdata_P[40 * 40] = {
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
-#if TOUCH_KEY_NUM > 0
-       2000,2000,2000,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_Rawdata_N[40 * 40] = {
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
-#if TOUCH_KEY_NUM > 0
-       400,400,400,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_CC_P[40 * 40] = {
-       116,114,119,109,112,106,104,106,103,108,110,108,110,117,113,115,111,113,
-       117,115,118,111,113,111,114,114,109,110,115,114,112,113,112,118,116,119,
-       115,113,116,110,112,109,108,108,107,108,113,111,110,111,110,116,111,115,
-       116,114,117,112,114,110,109,110,108,109,114,111,111,112,111,117,113,116,
-       115,113,116,111,113,110,108,109,107,108,112,111,110,112,111,117,112,116,
-       116,115,118,112,114,111,110,110,108,109,114,112,112,113,112,118,114,117,
-       114,112,115,110,112,108,107,108,106,107,111,110,110,111,110,116,111,115,
-       115,114,117,112,113,110,109,109,108,109,113,111,111,112,111,117,113,116,
-       115,113,116,111,113,110,109,109,108,109,113,111,111,112,111,117,112,116,
-       117,115,118,113,115,112,111,111,110,112,115,112,112,114,113,118,114,117,
-       114,112,115,110,112,109,109,109,107,113,112,110,110,112,110,117,112,115,
-       115,112,116,111,113,110,109,109,108,114,112,110,111,112,111,117,112,115,
-       117,115,118,113,115,112,111,113,110,118,113,112,113,115,113,119,115,118,
-       114,112,116,110,113,110,109,112,108,115,110,110,111,112,111,117,112,115,
-       116,113,117,112,114,111,111,113,109,117,112,111,112,114,112,118,114,117,
-       116,113,117,112,114,111,110,112,109,116,112,111,111,114,112,118,113,116,
-       117,114,119,113,115,112,111,113,110,117,114,112,112,115,113,119,115,117,
-       115,112,116,110,112,110,109,110,108,114,111,109,110,112,111,116,112,114,
-       116,113,118,112,114,111,111,112,110,116,113,111,112,114,112,118,114,116,
-       116,113,117,112,114,111,111,111,110,115,113,111,111,114,112,117,113,115,
-       118,115,119,114,115,113,113,113,111,117,114,112,113,115,113,119,115,117,
-       116,112,117,111,113,110,110,111,109,114,112,110,111,113,112,117,113,115,
-       117,113,118,112,114,111,111,112,109,115,112,111,111,114,112,117,114,116,
-       119,115,120,114,116,114,113,115,111,115,113,113,114,117,115,120,116,118,
-       117,113,118,112,114,112,112,113,110,112,111,111,111,115,113,118,114,116,
-       119,114,119,113,114,113,112,115,111,112,112,112,112,115,114,119,116,119,
-       119,114,118,113,114,112,112,114,110,111,111,111,112,114,114,119,115,119,
-       121,116,120,114,116,114,114,116,112,113,113,113,114,116,115,121,117,120,
-       118,113,117,112,113,111,111,113,109,110,110,110,111,114,113,119,115,118,
-       120,115,119,114,115,113,113,115,111,112,112,112,113,116,114,120,117,119,
-       119,115,119,113,114,113,114,115,111,111,112,111,113,115,114,120,117,119,
-       121,116,121,115,116,114,116,117,113,113,114,113,114,117,115,122,119,121,
-       115,112,116,113,114,112,115,114,110,111,111,111,112,115,113,120,116,118,
-       115,114,120,114,115,112,110,111,110,107,113,113,110,111,111,120,116,118,
-#if TOUCH_KEY_NUM > 0
-       38,38,38,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_CC_N[40 * 40] = {
-       63,61,64,59,60,57,56,57,55,58,59,58,59,63,61,62,60,61,
-       63,62,63,60,61,60,61,61,59,59,62,61,60,61,60,64,62,64,
-       62,61,62,59,60,59,58,58,58,58,61,60,59,60,59,62,60,62,
-       62,61,63,60,61,59,59,59,58,58,61,60,60,61,60,63,61,63,
-       62,61,63,60,61,59,58,59,58,58,60,60,59,60,60,63,60,62,
-       63,62,63,60,61,60,59,59,58,59,61,60,60,61,60,64,61,63,
-       61,60,62,59,60,58,58,58,57,58,60,59,59,60,59,62,60,62,
-       62,61,63,60,61,59,59,59,58,59,61,60,60,60,60,63,61,63,
-       62,61,63,60,61,59,59,59,58,58,61,60,60,60,60,63,61,62,
-       63,62,63,61,62,60,60,60,59,61,62,60,61,61,61,64,61,63,
-       62,60,62,59,60,59,58,59,58,61,60,59,59,60,59,63,60,62,
-       62,61,62,60,61,59,59,59,58,61,60,59,60,60,60,63,60,62,
-       63,62,64,61,62,60,60,61,59,63,61,60,61,62,61,64,62,63,
-       61,60,62,59,61,59,59,60,58,62,59,59,60,60,60,63,60,62,
-       62,61,63,60,61,60,60,61,59,63,60,60,60,61,60,63,61,63,
-       62,61,63,60,61,60,59,60,59,62,60,60,60,61,60,63,61,62,
-       63,62,64,61,62,60,60,61,59,63,61,60,61,62,61,64,62,63,
-       62,60,63,59,61,59,59,59,58,61,60,59,59,60,60,63,60,61,
-       63,61,63,60,61,60,60,60,59,63,61,60,60,61,60,63,61,62,
-       63,61,63,60,61,60,60,60,59,62,61,60,60,61,61,63,61,62,
-       64,62,64,61,62,61,61,61,60,63,61,60,61,62,61,64,62,63,
-       62,60,63,60,61,59,59,60,58,62,61,59,60,61,60,63,61,62,
-       63,61,63,60,61,60,60,61,59,62,60,60,60,61,60,63,61,62,
-       64,62,65,61,62,61,61,62,60,62,61,61,61,63,62,65,63,64,
-       63,61,63,60,61,60,60,61,59,60,60,60,60,62,61,63,62,63,
-       64,61,64,61,61,61,61,62,60,60,60,60,61,62,61,64,62,64,
-       64,61,64,61,61,60,61,61,59,60,60,60,60,62,61,64,62,64,
-       65,62,65,62,62,61,61,62,60,61,61,61,61,63,62,65,63,65,
-       64,61,63,60,61,60,60,61,59,59,59,59,60,61,61,64,62,63,
-       64,62,64,61,62,61,61,62,60,60,60,60,61,62,62,65,63,64,
-       64,62,64,61,62,61,61,62,60,60,60,60,61,62,61,65,63,64,
-       65,62,65,62,63,62,63,63,61,61,61,61,61,63,62,66,64,65,
-       62,60,62,61,61,60,62,61,59,60,60,60,60,62,61,64,63,64,
-       62,61,64,61,62,60,59,60,59,58,61,61,59,60,60,65,62,63,
-#if TOUCH_KEY_NUM > 0
-       9,9,9,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_CC_I_P[40 * 40] = {
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-#if TOUCH_KEY_NUM > 0
-       25,25,25,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_CC_I_N[40 * 40] = {
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-#if TOUCH_KEY_NUM > 0
-       0,0,0,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_CC_Q_P[40 * 40] = {
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
-#if TOUCH_KEY_NUM > 0
-       25,25,25,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_CC_Q_N[40 * 40] = {
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-#if TOUCH_KEY_NUM > 0
-       0,0,0,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_Diff_P[40 * 40] = {
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
-#if TOUCH_KEY_NUM > 0
-       35,35,35,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Lmt_FW_Diff_N[40 *40] = {
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
-#if TOUCH_KEY_NUM > 0
-       -35,-35,-35,
-#endif /* #if TOUCH_KEY_NUM > 0 */
-};
-
-static int32_t PS_Config_Diff_Test_Frame = 50;
-
-#endif /* #if NVT_TOUCH_MP */
diff --git a/drivers/input/touchscreen/nt36xxx/Kconfig b/drivers/input/touchscreen/nt36xxx/Kconfig
new file mode 100755 (executable)
index 0000000..ad07462
--- /dev/null
@@ -0,0 +1,11 @@
+#
+# Novatek NT36xxx touchscreen driver configuration
+#
+config TOUCHSCREEN_NT36xxx
+       bool "Novatek NT36xxx"
+       default y
+       help
+         Say Y here if you have a Novatek NT36xxx touchscreen connected
+         to your system.
+
+         If unsure, say N.
diff --git a/drivers/input/touchscreen/nt36xxx/Makefile b/drivers/input/touchscreen/nt36xxx/Makefile
new file mode 100755 (executable)
index 0000000..88c95a9
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the Novatek NT36xxx touchscreen driver.
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_TOUCHSCREEN_NT36xxx) += nt36xxx.o nt36xxx_fw_update.o nt36xxx_ext_proc.o nt36xxx_mp_ctrlram.o
diff --git a/drivers/input/touchscreen/nt36xxx/nt36xxx.c b/drivers/input/touchscreen/nt36xxx/nt36xxx.c
new file mode 100755 (executable)
index 0000000..8e1b4c7
--- /dev/null
@@ -0,0 +1,1766 @@
+/*
+ * Copyright (C) 2010 - 2017 Novatek, Inc.
+ *
+ * $Revision: 22971 $
+ * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/list.h>
+#include <linux/device.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/proc_fs.h>
+#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+#include <linux/input/mt.h>
+#include <linux/wakelock.h>
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+
+#if defined(CONFIG_HQ_DEV_INFO)
+#include <linux/dev_info.h>
+#endif
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif
+
+#include "nt36xxx.h"
+
+#if NVT_TOUCH_ESD_PROTECT
+#include <linux/jiffies.h>
+
+static struct delayed_work nvt_esd_check_work;
+static struct workqueue_struct *nvt_esd_check_wq;
+static unsigned long irq_timer;
+uint8_t esd_check = false;
+uint8_t esd_retry = 0;
+uint8_t esd_retry_max = 5;
+#endif
+
+#if NVT_TOUCH_EXT_PROC
+extern int32_t nvt_extra_proc_init(void);
+#endif
+
+#if NVT_TOUCH_FW
+extern int32_t nvt_fw_sysfs_init(void);
+extern int32_t nvt_fw_sysfs_deinit(void);
+#endif
+
+#if NVT_TOUCH_MP
+extern int32_t nvt_mp_proc_init(void);
+#endif
+
+struct nvt_ts_data *ts;
+
+static struct workqueue_struct *nvt_wq;
+
+#if BOOT_UPDATE_FIRMWARE
+static struct workqueue_struct *nvt_fwu_wq;
+extern void Boot_Update_Firmware(struct work_struct *work);
+#endif
+
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void nvt_ts_early_suspend(struct early_suspend *h);
+static void nvt_ts_late_resume(struct early_suspend *h);
+#endif
+
+#if TOUCH_KEY_NUM > 0
+const uint16_t touch_key_array[TOUCH_KEY_NUM] = {
+       KEY_BACK,
+       KEY_HOME,
+       KEY_MENU
+};
+#endif
+
+#if WAKEUP_GESTURE
+const uint16_t gesture_key_array[] = {
+       KEY_POWER,  //GESTURE_WORD_C
+       KEY_POWER,  //GESTURE_WORD_W
+       KEY_POWER,  //GESTURE_WORD_V
+       KEY_POWER,  //GESTURE_DOUBLE_CLICK
+       KEY_POWER,  //GESTURE_WORD_Z
+       KEY_POWER,  //GESTURE_WORD_M
+       KEY_POWER,  //GESTURE_WORD_O
+       KEY_POWER,  //GESTURE_WORD_e
+       KEY_POWER,  //GESTURE_WORD_S
+       KEY_POWER,  //GESTURE_SLIDE_UP
+       KEY_POWER,  //GESTURE_SLIDE_DOWN
+       KEY_POWER,  //GESTURE_SLIDE_LEFT
+       KEY_POWER,  //GESTURE_SLIDE_RIGHT
+};
+#endif
+
+static uint8_t bTouchIsAwake = 0;
+
+/*******************************************************
+Description:
+       Novatek touchscreen i2c read function.
+
+return:
+       Executive outcomes. 2---succeed. -5---I/O error
+*******************************************************/
+int32_t CTP_I2C_READ(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len)
+{
+       struct i2c_msg msgs[2];
+       int32_t ret = -1;
+       int32_t retries = 0;
+
+       msgs[0].flags = !I2C_M_RD;
+       msgs[0].addr  = address;
+       msgs[0].len   = 1;
+       msgs[0].buf   = &buf[0];
+
+       msgs[1].flags = I2C_M_RD;
+       msgs[1].addr  = address;
+       msgs[1].len   = len - 1;
+       msgs[1].buf   = &buf[1];
+
+       while (retries < 5) {
+               ret = i2c_transfer(client->adapter, msgs, 2);
+               if (ret == 2)   break;
+               retries++;
+       }
+
+       if (unlikely(retries == 5)) {
+               NVT_ERR("error, ret=%d\n", ret);
+               ret = -EIO;
+       }
+
+       return ret;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen i2c write function.
+
+return:
+       Executive outcomes. 1---succeed. -5---I/O error
+*******************************************************/
+int32_t CTP_I2C_WRITE(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len)
+{
+       struct i2c_msg msg;
+       int32_t ret = -1;
+       int32_t retries = 0;
+
+       msg.flags = !I2C_M_RD;
+       msg.addr  = address;
+       msg.len   = len;
+       msg.buf   = buf;
+
+       while (retries < 5) {
+               ret = i2c_transfer(client->adapter, &msg, 1);
+               if (ret == 1)   break;
+               retries++;
+       }
+
+       if (unlikely(retries == 5)) {
+               NVT_ERR("error, ret=%d\n", ret);
+               ret = -EIO;
+       }
+
+       return ret;
+}
+
+
+/*******************************************************
+Description:
+       Novatek touchscreen reset MCU then into idle mode
+    function.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_sw_reset_idle(void)
+{
+       uint8_t buf[4]={0};
+
+       /* ---write i2c cmds to reset idle--- */
+       buf[0]=0x00;
+       buf[1]=0xA5;
+       CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+
+       msleep(15);
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen reset MCU (boot) function.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_bootloader_reset(void)
+{
+       uint8_t buf[8] = {0};
+       NVT_ERR("xlixiang---enter-%s\n", __func__);
+       //---write i2c cmds to reset---
+       buf[0] = 0x00;
+       buf[1] = 0x69;
+       CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+
+       // need 35ms delay after bootloader reset
+       msleep(35);
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen clear FW status function.
+
+return:
+       Executive outcomes. 0---succeed. -1---fail.
+*******************************************************/
+int32_t nvt_clear_fw_status(void)
+{
+       uint8_t buf[8] = {0};
+       int32_t i = 0;
+       const int32_t retry = 20;
+
+       for (i = 0; i < retry; i++) {
+               //---set xdata index to EVENT BUF ADDR---
+               buf[0] = 0xFF;
+               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+               //---clear fw status---
+               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
+               buf[1] = 0x00;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
+
+               //---read fw status---
+               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
+               buf[1] = 0xFF;
+               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
+
+               if (buf[1] == 0x00)
+                       break;
+
+               msleep(10);
+       }
+
+       if (i >= retry) {
+               NVT_ERR("failed, i=%d, buf[1]=0x%02X\n", i, buf[1]);
+               return -1;
+       } else {
+               return 0;
+       }
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen check FW status function.
+
+return:
+       Executive outcomes. 0---succeed. -1---failed.
+*******************************************************/
+int32_t nvt_check_fw_status(void)
+{
+       uint8_t buf[8] = {0};
+       int32_t i = 0;
+       const int32_t retry = 50;
+
+       for (i = 0; i < retry; i++) {
+               //---set xdata index to EVENT BUF ADDR---
+               buf[0] = 0xFF;
+               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+               //---read fw status---
+               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
+               buf[1] = 0x00;
+               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
+
+               if ((buf[1] & 0xF0) == 0xA0)
+                       break;
+
+               msleep(10);
+       }
+
+       if (i >= retry) {
+               NVT_ERR("failed, i=%d, buf[1]=0x%02X\n", i, buf[1]);
+               return -1;
+       } else {
+               return 0;
+       }
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen check FW reset state function.
+
+return:
+       Executive outcomes. 0---succeed. -1---failed.
+*******************************************************/
+int32_t nvt_check_fw_reset_state(RST_COMPLETE_STATE check_reset_state)
+{
+       uint8_t buf[8] = {0};
+       int32_t ret = 0;
+       int32_t retry = 0;
+       NVT_ERR("xlixiang---enter-%s\n", __func__);
+       while (1) {
+               msleep(10);
+               //---read reset state---
+               buf[0] = EVENT_MAP_RESET_COMPLETE;
+               buf[1] = 0x00;
+               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 6);
+
+               if ((buf[1] >= check_reset_state) && (buf[1] <= RESET_STATE_MAX)) {
+                       ret = 0;
+                       break;
+               }
+       
+               retry++;
+               if (check_reset_state <= RESET_STATE_REK) {
+                       if( unlikely(retry > 50)) {
+                               NVT_ERR("error,retry = %d,buf[1] = 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n",retry,buf[1],buf[2], buf[3], buf[4], buf[5]);  
+                               ret = -1;
+                               break;                  
+                       }               
+               }
+               else 
+               {
+                       if(unlikely(retry > 100)) {
+                               NVT_ERR("error, retry=%d, buf[1]=0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", retry, buf[1], buf[2], buf[3], buf[4], buf[5]);
+                               ret = -1;
+                               break;
+                       }
+               }
+       }
+
+       return ret;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen get novatek project id information
+       function.
+
+return:
+       Executive outcomes. 0---success. -1---fail.
+*******************************************************/
+int32_t nvt_read_pid(void)
+{
+       uint8_t buf[3] = {0};
+       int32_t ret = 0;
+
+       //---set xdata index to EVENT BUF ADDR---
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+       //---read project id---
+       buf[0] = EVENT_MAP_PROJECTID;
+       buf[1] = 0x00;
+       buf[2] = 0x00;
+       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 3);
+
+       ts->nvt_pid = (buf[2] << 8) + buf[1];
+
+       NVT_LOG("PID=%04X\n", ts->nvt_pid);
+
+       return ret;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen get firmware related information
+       function.
+
+return:
+       Executive outcomes. 0---success. -1---fail.
+*******************************************************/
+int32_t nvt_get_fw_info(void)
+{
+       uint8_t buf[64] = {0};
+       uint32_t retry_count = 0;
+       int32_t ret = 0;
+
+info_retry:
+       //---set xdata index to EVENT BUF ADDR---
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+       //---read fw info---
+       buf[0] = EVENT_MAP_FWINFO;
+       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 17);
+       ts->fw_ver = buf[1];
+       ts->x_num = buf[3];
+       ts->y_num = buf[4];
+       ts->abs_x_max = (uint16_t)((buf[5] << 8) | buf[6]);
+       ts->abs_y_max = (uint16_t)((buf[7] << 8) | buf[8]);
+       ts->max_button_num = buf[11];
+
+       //---clear x_num, y_num if fw info is broken---
+       if ((buf[1] + buf[2]) != 0xFF) {
+               NVT_ERR("FW info is broken! fw_ver=0x%02X, ~fw_ver=0x%02X\n", buf[1], buf[2]);
+               ts->fw_ver = 0;
+               ts->x_num = 18;
+               ts->y_num = 32;
+               ts->abs_x_max = TOUCH_DEFAULT_MAX_WIDTH;
+               ts->abs_y_max = TOUCH_DEFAULT_MAX_HEIGHT;
+               ts->max_button_num = TOUCH_KEY_NUM;
+
+               if(retry_count < 3) {
+                       retry_count++;
+                       NVT_ERR("retry_count=%d\n", retry_count);
+                       goto info_retry;
+               } else {
+                       NVT_ERR("Set default fw_ver=%d, x_num=%d, y_num=%d, \
+                                       abs_x_max=%d, abs_y_max=%d, max_button_num=%d!\n",
+                                       ts->fw_ver, ts->x_num, ts->y_num,
+                                       ts->abs_x_max, ts->abs_y_max, ts->max_button_num);
+                       ret = -1;
+               }
+       } else {
+               ret = 0;
+       }
+
+       //---Get Novatek PID---
+       nvt_read_pid();
+
+       return ret;
+}
+
+/*******************************************************
+  Create Device Node (Proc Entry)
+*******************************************************/
+#if NVT_TOUCH_PROC
+static struct proc_dir_entry *NVT_proc_entry;
+#define DEVICE_NAME    "NVTflash"
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/NVTflash read function.
+
+return:
+       Executive outcomes. 2---succeed. -5,-14---failed.
+*******************************************************/
+static ssize_t nvt_flash_read(struct file *file, char __user *buff, size_t count, loff_t *offp)
+{
+       uint8_t str[68] = {0};
+       int32_t ret = -1;
+       int32_t retries = 0;
+       int8_t i2c_wr = 0;
+
+       if (count > sizeof(str)) {
+               NVT_ERR("error count=%zu\n", count);
+               return -EFAULT;
+       }
+
+       if (copy_from_user(str, buff, count)) {
+               NVT_ERR("copy from user error\n");
+               return -EFAULT;
+       }
+#if NVT_TOUCH_ESD_PROTECT
+       /*
+        * stop esd check work to avoid case that 0x77 report righ after here to enable esd check again
+        * finally lead to trigger esd recovery bootloader reset
+        */
+       cancel_delayed_work_sync(&nvt_esd_check_work);
+       nvt_esd_check_enable(false);
+#endif
+
+       i2c_wr = str[0] >> 7;
+
+       if (i2c_wr == 0) {      //I2C write
+               while (retries < 20) {
+                       ret = CTP_I2C_WRITE(ts->client, (str[0] & 0x7F), &str[2], str[1]);
+                       if (ret == 1)
+                               break;
+                       else
+                               NVT_ERR("error, retries=%d, ret=%d\n", retries, ret);
+
+                       retries++;
+               }
+
+               if (unlikely(retries == 20)) {
+                       NVT_ERR("error, ret = %d\n", ret);
+                       return -EIO;
+               }
+
+               return ret;
+       } else if (i2c_wr == 1) {       //I2C read
+               while (retries < 20) {
+                       ret = CTP_I2C_READ(ts->client, (str[0] & 0x7F), &str[2], str[1]);
+                       if (ret == 2)
+                               break;
+                       else
+                               NVT_ERR("error, retries=%d, ret=%d\n", retries, ret);
+
+                       retries++;
+               }
+
+               // copy buff to user if i2c transfer
+               if (retries < 20) {
+                       if (copy_to_user(buff, str, count))
+                               return -EFAULT;
+               }
+
+               if (unlikely(retries == 20)) {
+                       NVT_ERR("error, ret = %d\n", ret);
+                       return -EIO;
+               }
+
+               return ret;
+       } else {
+               NVT_ERR("Call error, str[0]=%d\n", str[0]);
+               return -EFAULT;
+       }
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/NVTflash open function.
+
+return:
+       Executive outcomes. 0---succeed. -12---failed.
+*******************************************************/
+static int32_t nvt_flash_open(struct inode *inode, struct file *file)
+{
+       struct nvt_flash_data *dev;
+
+       dev = kmalloc(sizeof(struct nvt_flash_data), GFP_KERNEL);
+       if (dev == NULL) {
+               NVT_ERR("Failed to allocate memory for nvt flash data\n");
+               return -ENOMEM;
+       }
+
+       rwlock_init(&dev->lock);
+       file->private_data = dev;
+
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/NVTflash close function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t nvt_flash_close(struct inode *inode, struct file *file)
+{
+       struct nvt_flash_data *dev = file->private_data;
+
+       if (dev)
+               kfree(dev);
+
+       return 0;
+}
+
+static const struct file_operations nvt_flash_fops = {
+       .owner = THIS_MODULE,
+       .open = nvt_flash_open,
+       .release = nvt_flash_close,
+       .read = nvt_flash_read,
+};
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/NVTflash initial function.
+
+return:
+       Executive outcomes. 0---succeed. -12---failed.
+*******************************************************/
+static int32_t nvt_flash_proc_init(void)
+{
+       NVT_proc_entry = proc_create(DEVICE_NAME, 0444, NULL,&nvt_flash_fops);
+       if (NVT_proc_entry == NULL) {
+               NVT_ERR("Failed!\n");
+               return -ENOMEM;
+       } else {
+               NVT_LOG("Succeeded!\n");
+       }
+
+       NVT_LOG("============================================================\n");
+       NVT_LOG("Create /proc/NVTflash\n");
+       NVT_LOG("============================================================\n");
+
+       return 0;
+}
+#endif
+
+#if WAKEUP_GESTURE
+#define GESTURE_WORD_C                 12
+#define GESTURE_WORD_W                 13
+#define GESTURE_WORD_V                 14
+#define GESTURE_DOUBLE_CLICK   15
+#define GESTURE_WORD_Z                 16
+#define GESTURE_WORD_M                 17
+#define GESTURE_WORD_O                 18
+#define GESTURE_WORD_e                 19
+#define GESTURE_WORD_S                 20
+#define GESTURE_SLIDE_UP               21
+#define GESTURE_SLIDE_DOWN             22
+#define GESTURE_SLIDE_LEFT             23
+#define GESTURE_SLIDE_RIGHT            24
+/* customized gesture id */
+#define DATA_PROTOCOL           30
+
+/* function page definition */
+#define FUNCPAGE_GESTURE         1
+
+static struct wake_lock gestrue_wakelock;
+
+/*******************************************************
+Description:
+       Novatek touchscreen wake up gesture key report function.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_ts_wakeup_gesture_report(uint8_t gesture_id, uint8_t *data)
+{
+       uint32_t keycode = 0;
+       uint8_t func_type = data[2];
+       uint8_t func_id = data[3];
+
+       /* support fw specifal data protocol */
+       if ((gesture_id == DATA_PROTOCOL) && (func_type == FUNCPAGE_GESTURE)) {
+               gesture_id = func_id;
+       } else if (gesture_id > DATA_PROTOCOL) {
+               NVT_ERR("gesture_id %d is invalid, func_type=%d, func_id=%d\n", gesture_id, func_type, func_id);
+               return;
+       }
+
+       NVT_LOG("gesture_id = %d\n", gesture_id);
+
+       switch (gesture_id) {
+               case GESTURE_WORD_C:
+                       NVT_LOG("Gesture : Word-C.\n");
+                       keycode = gesture_key_array[0];
+                       break;
+               case GESTURE_WORD_W:
+                       NVT_LOG("Gesture : Word-W.\n");
+                       keycode = gesture_key_array[1];
+                       break;
+               case GESTURE_WORD_V:
+                       NVT_LOG("Gesture : Word-V.\n");
+                       keycode = gesture_key_array[2];
+                       break;
+               case GESTURE_DOUBLE_CLICK:
+                       NVT_LOG("Gesture : Double Click.\n");
+                       keycode = gesture_key_array[3];
+                       break;
+               case GESTURE_WORD_Z:
+                       NVT_LOG("Gesture : Word-Z.\n");
+                       keycode = gesture_key_array[4];
+                       break;
+               case GESTURE_WORD_M:
+                       NVT_LOG("Gesture : Word-M.\n");
+                       keycode = gesture_key_array[5];
+                       break;
+               case GESTURE_WORD_O:
+                       NVT_LOG("Gesture : Word-O.\n");
+                       keycode = gesture_key_array[6];
+                       break;
+               case GESTURE_WORD_e:
+                       NVT_LOG("Gesture : Word-e.\n");
+                       keycode = gesture_key_array[7];
+                       break;
+               case GESTURE_WORD_S:
+                       NVT_LOG("Gesture : Word-S.\n");
+                       keycode = gesture_key_array[8];
+                       break;
+               case GESTURE_SLIDE_UP:
+                       NVT_LOG("Gesture : Slide UP.\n");
+                       keycode = gesture_key_array[9];
+                       break;
+               case GESTURE_SLIDE_DOWN:
+                       NVT_LOG("Gesture : Slide DOWN.\n");
+                       keycode = gesture_key_array[10];
+                       break;
+               case GESTURE_SLIDE_LEFT:
+                       NVT_LOG("Gesture : Slide LEFT.\n");
+                       keycode = gesture_key_array[11];
+                       break;
+               case GESTURE_SLIDE_RIGHT:
+                       NVT_LOG("Gesture : Slide RIGHT.\n");
+                       keycode = gesture_key_array[12];
+                       break;
+               default:
+                       break;
+       }
+
+       if (keycode > 0) {
+               input_report_key(ts->input_dev, keycode, 1);
+               input_sync(ts->input_dev);
+               input_report_key(ts->input_dev, keycode, 0);
+               input_sync(ts->input_dev);
+       }
+}
+#endif
+
+/*******************************************************
+Description:
+       Novatek touchscreen parse device tree function.
+
+return:
+       n.a.
+*******************************************************/
+#ifdef CONFIG_OF
+static void nvt_parse_dt(struct device *dev)
+{
+       struct device_node *np = dev->of_node;
+
+#if NVT_TOUCH_SUPPORT_HW_RST
+       ts->reset_gpio = of_get_named_gpio_flags(np, "novatek,reset-gpio", 0, &ts->reset_flags);
+       NVT_LOG("novatek,reset-gpio=%d\n", ts->reset_gpio);
+#endif
+       ts->irq_gpio = of_get_named_gpio_flags(np, "novatek,irq-gpio", 0, &ts->irq_flags);
+       NVT_LOG("novatek,irq-gpio=%d\n", ts->irq_gpio);
+
+}
+#else
+static void nvt_parse_dt(struct device *dev)
+{
+#if NVT_TOUCH_SUPPORT_HW_RST
+       ts->reset_gpio = NVTTOUCH_RST_PIN;
+#endif
+       ts->irq_gpio = NVTTOUCH_INT_PIN;
+}
+#endif
+
+/*******************************************************
+Description:
+       Novatek touchscreen config and request gpio
+
+return:
+       Executive outcomes. 0---succeed. not 0---failed.
+*******************************************************/
+static int nvt_gpio_config(struct nvt_ts_data *ts)
+{
+       int32_t ret = 0;
+       struct pinctrl *pinctrl_vdd;
+
+       pinctrl_vdd = devm_pinctrl_get_select(&ts->client->dev, "on_state");
+       if (IS_ERR(pinctrl_vdd))
+                       NVT_ERR("Failed to on vdd GPIO\n");
+
+#if NVT_TOUCH_SUPPORT_HW_RST
+       /* request RST-pin (Output/High) */
+       if (gpio_is_valid(ts->reset_gpio)) {
+               ret = gpio_request_one(ts->reset_gpio, GPIOF_OUT_INIT_HIGH, "NVT-tp-rst");
+               if (ret) {
+                       NVT_ERR("Failed to request NVT-tp-rst GPIO\n");
+                       goto err_request_reset_gpio;
+               }
+       }
+#endif
+       /* request INT-pin (Input) */
+       if (gpio_is_valid(ts->irq_gpio)) {
+               ret = gpio_request_one(ts->irq_gpio, GPIOF_IN, "NVT-int");
+               if (ret) {
+                       NVT_ERR("Failed to request NVT-int GPIO\n");
+                       goto err_request_irq_gpio;
+               }
+       }
+
+       return ret;
+
+err_request_irq_gpio:
+#if NVT_TOUCH_SUPPORT_HW_RST
+       gpio_free(ts->reset_gpio);
+err_request_reset_gpio:
+#endif
+       return ret;
+}
+
+#if NVT_TOUCH_ESD_PROTECT
+void nvt_esd_check_enable(uint8_t enable)
+{
+       /* enable/disable esd check flag */
+       esd_check = enable;
+       /* update interrupt timer */
+       irq_timer = jiffies;
+       /* clear esd_retry counter, if protect function is enabled */
+       esd_retry = enable ? 0 : esd_retry;
+}
+
+static uint8_t nvt_fw_recovery(uint8_t *point_data)
+{
+       uint8_t i = 0;
+       uint8_t detected = true;
+
+       /* check pattern */
+       for (i = 1 ; i < 7 ; i++) {
+               if (point_data[i] != 0x77) {
+                       detected = false;
+                       break;
+               }
+       }
+
+       return detected;
+}
+
+static void nvt_esd_check_func(struct work_struct *work)
+{
+       unsigned int timer = jiffies_to_msecs(jiffies - irq_timer);
+
+
+       if (esd_retry >= esd_retry_max)
+               nvt_esd_check_enable(false);
+
+       if ((timer > NVT_TOUCH_ESD_CHECK_PERIOD) && esd_check) {
+               NVT_ERR("do ESD recovery, timer = %d, retry = %d\n", timer, esd_retry);
+               printk("do ESD recovery, timer = %d, retry = %d\n", timer, esd_retry);
+               /* do esd recovery, bootloader reset */
+               nvt_bootloader_reset();
+               /* update interrupt timer */
+               irq_timer = jiffies;
+               /* update esd_retry counter */
+               esd_retry++;
+       }
+
+       queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work,
+                       msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD));
+}
+#endif
+
+#define POINT_DATA_LEN 65
+/*******************************************************
+Description:
+       Novatek touchscreen work function.
+
+return:
+       n.a.
+*******************************************************/
+static void nvt_ts_work_func(struct work_struct *work)
+{
+       int32_t ret = -1;
+       uint8_t point_data[POINT_DATA_LEN + 1] = {0};
+       uint32_t position = 0;
+       uint32_t input_x = 0;
+       uint32_t input_y = 0;
+       uint32_t input_w = 0;
+       uint32_t input_p = 0;
+       uint8_t input_id = 0;
+#if MT_PROTOCOL_B
+       uint8_t press_id[TOUCH_MAX_FINGER_NUM] = {0};
+#endif /* MT_PROTOCOL_B */
+       int32_t i = 0;
+       int32_t finger_cnt = 0;
+
+       mutex_lock(&ts->lock);
+
+       ret = CTP_I2C_READ(ts->client, I2C_FW_Address, point_data, POINT_DATA_LEN + 1);
+       if (ret < 0) {
+               NVT_ERR("CTP_I2C_READ failed.(%d)\n", ret);
+               goto XFER_ERROR;
+       }
+
+#if NVT_TOUCH_ESD_PROTECT
+
+       if (nvt_fw_recovery(point_data)) {
+               nvt_esd_check_enable(true);
+               goto XFER_ERROR;
+       }
+#endif
+
+#if WAKEUP_GESTURE
+       if (bTouchIsAwake == 0) {
+               input_id = (uint8_t)(point_data[1] >> 3);
+               nvt_ts_wakeup_gesture_report(input_id, point_data);
+               enable_irq(ts->client->irq);
+               mutex_unlock(&ts->lock);
+               return;
+       }
+#endif
+
+       finger_cnt = 0;
+
+       for (i = 0; i < ts->max_touch_num; i++) {
+               position = 1 + 6 * i;
+               input_id = (uint8_t)(point_data[position + 0] >> 3);
+               if ((input_id == 0) || (input_id > ts->max_touch_num))
+                       continue;
+
+               if (((point_data[position] & 0x07) == 0x01) || ((point_data[position] & 0x07) == 0x02)) {
+#if NVT_TOUCH_ESD_PROTECT
+               /* update interrupt timer */
+               irq_timer = jiffies;
+#endif
+                       input_x = (uint32_t)(point_data[position + 1] << 4) + (uint32_t) (point_data[position + 3] >> 4);
+                       input_y = (uint32_t)(point_data[position + 2] << 4) + (uint32_t) (point_data[position + 3] & 0x0F);
+                       if ((input_x < 0) || (input_y < 0))
+                               continue;
+                       if ((input_x > ts->abs_x_max) || (input_y > ts->abs_y_max))
+                               continue;
+                       input_w = (uint32_t)(point_data[position + 4]);
+                       if (input_w == 0)
+                               input_w = 1;
+                       if (i < 2) {
+                               input_p = (uint32_t)(point_data[position + 5]) + (uint32_t)(point_data[i + 63] << 8);
+                               if (input_p > TOUCH_FORCE_NUM)
+                                       input_p = TOUCH_FORCE_NUM;
+                       } else {
+                               input_p = (uint32_t)(point_data[position + 5]);
+                       }
+                       if (input_p == 0)
+                               input_p = 1;
+
+#if MT_PROTOCOL_B
+                       press_id[input_id - 1] = 1;
+                       input_mt_slot(ts->input_dev, input_id - 1);
+                       input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
+#else /* MT_PROTOCOL_B */
+                       input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, input_id - 1);
+                       input_report_key(ts->input_dev, BTN_TOUCH, 1);
+#endif /* MT_PROTOCOL_B */
+
+                       input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
+                       input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, input_y);
+                       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, input_w);
+                       input_report_abs(ts->input_dev, ABS_MT_PRESSURE, input_p);
+
+#if MT_PROTOCOL_B
+#else /* MT_PROTOCOL_B */
+                       input_mt_sync(ts->input_dev);
+#endif /* MT_PROTOCOL_B */
+
+                       finger_cnt++;
+               }
+       }
+
+#if MT_PROTOCOL_B
+       for (i = 0; i < ts->max_touch_num; i++) {
+               if (press_id[i] != 1) {
+                       input_mt_slot(ts->input_dev, i);
+                       input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+                       input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0);
+                       input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
+               }
+       }
+
+       input_report_key(ts->input_dev, BTN_TOUCH, (finger_cnt > 0));
+#else /* MT_PROTOCOL_B */
+       if (finger_cnt == 0) {
+               input_report_key(ts->input_dev, BTN_TOUCH, 0);
+               input_mt_sync(ts->input_dev);
+       }
+#endif /* MT_PROTOCOL_B */
+
+#if TOUCH_KEY_NUM > 0
+       if (point_data[61] == 0xF8) {
+               for (i = 0; i < ts->max_button_num; i++) {
+                       input_report_key(ts->input_dev, touch_key_array[i], ((point_data[62] >> i) & 0x01));
+               }
+       } else {
+               for (i = 0; i < ts->max_button_num; i++) {
+                       input_report_key(ts->input_dev, touch_key_array[i], 0);
+               }
+       }
+#endif
+
+       input_sync(ts->input_dev);
+
+XFER_ERROR:
+       enable_irq(ts->client->irq);
+
+       mutex_unlock(&ts->lock);
+}
+
+/*******************************************************
+Description:
+       External interrupt service routine.
+
+return:
+       irq execute status.
+*******************************************************/
+static irqreturn_t nvt_ts_irq_handler(int32_t irq, void *dev_id)
+{
+       disable_irq_nosync(ts->client->irq);
+
+#if WAKEUP_GESTURE
+       if (bTouchIsAwake == 0) {
+               wake_lock_timeout(&gestrue_wakelock, msecs_to_jiffies(5000));
+       }
+#endif
+
+       queue_work(nvt_wq, &ts->nvt_work);
+
+       return IRQ_HANDLED;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen check and stop crc reboot loop.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_stop_crc_reboot(void)
+{
+       uint8_t buf[8] = {0};
+       int32_t retry = 0;
+
+       //read dummy buffer to check CRC fail reboot is happening or not
+
+       //---change I2C index to prevent geting 0xFF, but not 0xFC---
+       buf[0] = 0xFF;
+       buf[1] = 0x01;
+       buf[2] = 0xF6;
+       CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
+
+       //---read to check if buf is 0xFC which means IC is in CRC reboot ---
+       buf[0] = 0x4E;
+       CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 4);
+
+       if (((buf[1] == 0xFC) && (buf[2] == 0xFC) && (buf[3] == 0xFC)) ||
+               ((buf[1] == 0xFF) && (buf[2] == 0xFF) && (buf[3] == 0xFF))) {
+
+               //IC is in CRC fail reboot loop, needs to be stopped!
+               for (retry = 5; retry > 0; retry--) {
+
+                       //---write i2c cmds to reset idle : 1st---
+                       buf[0]=0x00;
+                       buf[1]=0xA5;
+                       CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+
+                       //---write i2c cmds to reset idle : 2rd---
+                       buf[0]=0x00;
+                       buf[1]=0xA5;
+                       CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+                       msleep(1);
+
+                       //---clear CRC_ERR_FLAG---
+                       buf[0] = 0xFF;
+                       buf[1] = 0x03;
+                       buf[2] = 0xF1;
+                       CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
+
+                       buf[0] = 0x35;
+                       buf[1] = 0xA5;
+                       CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 2);
+
+                       //---check CRC_ERR_FLAG---
+                       buf[0] = 0xFF;
+                       buf[1] = 0x03;
+                       buf[2] = 0xF1;
+                       CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
+
+                       buf[0] = 0x35;
+                       buf[1] = 0x00;
+                       CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 2);
+
+                       if (buf[1] == 0xA5)
+                               break;
+               }
+               if (retry == 0)
+                       NVT_ERR("CRC auto reboot is not able to be stopped! buf[1]=0x%02X\n", buf[1]);
+       }
+
+       return;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen check chip version trim function.
+
+return:
+       Executive outcomes. 0---NVT IC. -1---not NVT IC.
+*******************************************************/
+static int8_t nvt_ts_check_chip_ver_trim(void)
+{
+       uint8_t buf[8] = {0};
+       int32_t retry = 0;
+       int32_t list = 0;
+       int32_t i = 0;
+       int32_t found_nvt_chip = 0;
+       int32_t ret = -1;
+
+       nvt_bootloader_reset(); // NOT in retry loop
+
+       //---Check for 5 times---
+       for (retry = 5; retry > 0; retry--) {
+               nvt_sw_reset_idle();
+
+               buf[0] = 0x00;
+               buf[1] = 0x35;
+               CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+               msleep(10);
+
+               buf[0] = 0xFF;
+               buf[1] = 0x01;
+               buf[2] = 0xF6;
+               CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
+
+               buf[0] = 0x4E;
+               buf[1] = 0x00;
+               buf[2] = 0x00;
+               buf[3] = 0x00;
+               buf[4] = 0x00;
+               buf[5] = 0x00;
+               buf[6] = 0x00;
+               CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 7);
+               NVT_LOG("buf[1]=0x%02X, buf[2]=0x%02X, buf[3]=0x%02X, buf[4]=0x%02X, buf[5]=0x%02X, buf[6]=0x%02X\n",
+                       buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+
+               // compare read chip id on supported list
+               for (list = 0; list < (sizeof(trim_id_table) / sizeof(struct nvt_ts_trim_id_table)); list++) {
+                       found_nvt_chip = 0;
+
+                       // compare each byte
+                       for (i = 0; i < NVT_ID_BYTE_MAX; i++) {
+                               if (trim_id_table[list].mask[i]) {
+                                       if (buf[i + 1] != trim_id_table[list].id[i])
+                                               break;
+                               }
+                       }
+
+                       if (i == NVT_ID_BYTE_MAX) {
+                               found_nvt_chip = 1;
+                       }
+
+                       if (found_nvt_chip) {
+                               NVT_LOG("This is NVT touch IC\n");
+#if NVT_TOUCH_FW
+                               if (list == 0) {
+                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36672A");
+                               } else if (list == 9) {
+                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36525");
+                               } else if (list == 10) {
+                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36870");
+                               } else if (list == 11) {
+                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36676F");
+                               } else {
+                                       snprintf(ts->product_id, sizeof(ts->product_id), "NT36772");
+                               }
+#endif
+                               ts->mmap = trim_id_table[list].mmap;
+                               ts->carrier_system = trim_id_table[list].carrier_system;
+                               ret = 0;
+                               goto out;
+                       } else {
+                               ts->mmap = NULL;
+                               ret = -1;
+                       }
+               }
+
+               //---Stop CRC check to prevent IC auto reboot---
+               if (((buf[1] == 0xFC) && (buf[2] == 0xFC) && (buf[3] == 0xFC)) ||
+                       ((buf[1] == 0xFF) && (buf[2] == 0xFF) && (buf[3] == 0xFF))) {
+                       nvt_stop_crc_reboot();
+               }
+
+               msleep(10);
+       }
+
+out:
+       return ret;
+}
+
+
+/*******************************************************
+Description:
+       Novatek touchscreen driver probe function.
+
+return:
+       Executive outcomes. 0---succeed. negative---failed
+*******************************************************/
+static int32_t nvt_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       int32_t ret = 0;
+#if ((TOUCH_KEY_NUM > 0) || WAKEUP_GESTURE)
+       int32_t retry = 0;
+#endif
+
+       NVT_LOG("start\n");
+
+       ts = kmalloc(sizeof(struct nvt_ts_data), GFP_KERNEL);
+       if (ts == NULL) {
+               NVT_ERR("failed to allocated memory for nvt ts data\n");
+               return -ENOMEM;
+       }
+
+       ts->client = client;
+       i2c_set_clientdata(client, ts);
+
+       //---parse dts---
+       nvt_parse_dt(&client->dev);
+
+       //---request and config GPIOs---
+       ret = nvt_gpio_config(ts);
+       if (ret) {
+               NVT_ERR("gpio config error!\n");
+               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);
+
+       //---check chip version trim---
+       ret = nvt_ts_check_chip_ver_trim();
+       if (ret) {
+               NVT_ERR("chip is not identified\n");
+               ret = -EINVAL;
+               goto err_chipvertrim_failed;
+       }
+
+       mutex_init(&ts->lock);
+
+       mutex_lock(&ts->lock);
+       nvt_bootloader_reset();
+       nvt_check_fw_reset_state(RESET_STATE_INIT);
+       nvt_get_fw_info();
+       mutex_unlock(&ts->lock);
+
+       //---create workqueue---
+       nvt_wq = create_workqueue("nvt_wq");
+       if (!nvt_wq) {
+               NVT_ERR("nvt_wq create workqueue failed\n");
+               ret = -ENOMEM;
+               goto err_create_nvt_wq_failed;
+       }
+       INIT_WORK(&ts->nvt_work, nvt_ts_work_func);
+
+
+       //---allocate input device---
+       ts->input_dev = input_allocate_device();
+       if (ts->input_dev == NULL) {
+               NVT_ERR("allocate input device failed\n");
+               ret = -ENOMEM;
+               goto err_input_dev_alloc_failed;
+       }
+
+       ts->max_touch_num = TOUCH_MAX_FINGER_NUM;
+
+#if TOUCH_KEY_NUM > 0
+       ts->max_button_num = TOUCH_KEY_NUM;
+#endif
+
+       ts->int_trigger_type = INT_TRIGGER_TYPE;
+
+
+       //---set input device info.---
+       ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
+       ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       ts->input_dev->propbit[0] = BIT(INPUT_PROP_DIRECT);
+
+#if MT_PROTOCOL_B
+       input_mt_init_slots(ts->input_dev, ts->max_touch_num, 0);
+#endif
+
+       input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, TOUCH_FORCE_NUM, 0, 0);    //pressure = TOUCH_FORCE_NUM
+
+#if TOUCH_MAX_FINGER_NUM > 1
+       input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);    //area = 255
+
+       input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, ts->abs_x_max, 0, 0);
+       input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, ts->abs_y_max, 0, 0);
+#if MT_PROTOCOL_B
+       // no need to set ABS_MT_TRACKING_ID, input_mt_init_slots() already set it
+#else
+       input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, ts->max_touch_num, 0, 0);
+#endif //MT_PROTOCOL_B
+#endif //TOUCH_MAX_FINGER_NUM > 1
+
+#if TOUCH_KEY_NUM > 0
+       for (retry = 0; retry < ts->max_button_num; retry++) {
+               input_set_capability(ts->input_dev, EV_KEY, touch_key_array[retry]);
+       }
+#endif
+
+#if WAKEUP_GESTURE
+       for (retry = 0; retry < (sizeof(gesture_key_array) / sizeof(gesture_key_array[0])); retry++) {
+               input_set_capability(ts->input_dev, EV_KEY, gesture_key_array[retry]);
+       }
+       wake_lock_init(&gestrue_wakelock, WAKE_LOCK_SUSPEND, "poll-wake-lock");
+#endif
+
+       sprintf(ts->phys, "input/ts");
+       ts->input_dev->name = NVT_TS_NAME;
+       ts->input_dev->phys = ts->phys;
+       ts->input_dev->id.bustype = BUS_I2C;
+
+       //---register input device---
+       ret = input_register_device(ts->input_dev);
+       if (ret) {
+               NVT_ERR("register input device (%s) failed. ret=%d\n", ts->input_dev->name, ret);
+               goto err_input_register_device_failed;
+       }
+
+       //---set int-pin & request irq---
+       client->irq = gpio_to_irq(ts->irq_gpio);
+       if (client->irq) {
+               NVT_LOG("int_trigger_type=%d\n", ts->int_trigger_type);
+
+#if WAKEUP_GESTURE
+               ret = request_irq(client->irq, nvt_ts_irq_handler, ts->int_trigger_type | IRQF_NO_SUSPEND, client->name, ts);
+#else
+               ret = request_irq(client->irq, nvt_ts_irq_handler, ts->int_trigger_type, client->name, ts);
+#endif
+               if (ret != 0) {
+                       NVT_ERR("request irq failed. ret=%d\n", ret);
+                       goto err_int_request_failed;
+               } else {
+                       disable_irq(client->irq);
+                       NVT_LOG("request irq %d succeed\n", client->irq);
+               }
+       }
+
+#if BOOT_UPDATE_FIRMWARE
+       nvt_fwu_wq = create_singlethread_workqueue("nvt_fwu_wq");
+       if (!nvt_fwu_wq) {
+               NVT_ERR("nvt_fwu_wq create workqueue failed\n");
+               ret = -ENOMEM;
+               goto err_create_nvt_fwu_wq_failed;
+       }
+       INIT_DELAYED_WORK(&ts->nvt_fwu_work, Boot_Update_Firmware);
+       // please make sure boot update start after display reset(RESX) sequence
+       queue_delayed_work(nvt_fwu_wq, &ts->nvt_fwu_work, msecs_to_jiffies(14000));
+#endif
+
+#if NVT_TOUCH_ESD_PROTECT
+       INIT_DELAYED_WORK(&nvt_esd_check_work, nvt_esd_check_func);
+       nvt_esd_check_wq = create_workqueue("nvt_esd_check_wq");
+       queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work,
+       msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD));
+#endif
+       //---set device node---
+#if NVT_TOUCH_PROC
+       ret = nvt_flash_proc_init();
+       if (ret != 0) {
+               NVT_ERR("nvt flash proc init failed. ret=%d\n", ret);
+               goto err_init_NVT_ts;
+       }
+#endif
+
+#if NVT_TOUCH_EXT_PROC
+       ret = nvt_extra_proc_init();
+       if (ret != 0) {
+               NVT_ERR("nvt extra proc init failed. ret=%d\n", ret);
+               goto err_init_NVT_ts;
+       }
+#endif
+
+#if NVT_TOUCH_FW
+       ts->suspended = 0;
+       ts->force_reflash = 0;
+       ts->loading_fw = 0;
+
+       ret = nvt_fw_sysfs_init();
+       if (ret != 0) {
+               NVT_ERR("nvt fw class init failed. ret=%d\n", ret);
+               goto err_init_NVT_ts;
+       }
+#endif
+
+#if NVT_TOUCH_MP
+       ret = nvt_mp_proc_init();
+       if (ret != 0) {
+               NVT_ERR("nvt mp proc init failed. ret=%d\n", ret);
+               goto err_init_NVT_ts;
+       }
+#endif
+
+#if defined(CONFIG_FB)
+       ts->fb_notif.notifier_call = fb_notifier_callback;
+       ret = fb_register_client(&ts->fb_notif);
+       if(ret) {
+               NVT_ERR("register fb_notifier failed. ret=%d\n", ret);
+               goto err_register_fb_notif_failed;
+       }
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+       ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+       ts->early_suspend.suspend = nvt_ts_early_suspend;
+       ts->early_suspend.resume = nvt_ts_late_resume;
+       ret = register_early_suspend(&ts->early_suspend);
+       if(ret) {
+               NVT_ERR("register early suspend failed. ret=%d\n", ret);
+               goto err_register_early_suspend_failed;
+       }
+#endif
+
+       bTouchIsAwake = 1;
+       NVT_LOG("end\n");
+
+       enable_irq(client->irq);
+
+       return 0;
+
+#if defined(CONFIG_FB)
+err_register_fb_notif_failed:
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+err_register_early_suspend_failed:
+#endif
+#if (NVT_TOUCH_PROC || NVT_TOUCH_EXT_PROC || NVT_TOUCH_MP)
+err_init_NVT_ts:
+#endif
+       free_irq(client->irq, ts);
+#if BOOT_UPDATE_FIRMWARE
+err_create_nvt_fwu_wq_failed:
+#endif
+err_int_request_failed:
+err_input_register_device_failed:
+       input_free_device(ts->input_dev);
+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);
+err_gpio_config_failed:
+       i2c_set_clientdata(client, NULL);
+       kfree(ts);
+       return ret;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen driver release function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t nvt_ts_remove(struct i2c_client *client)
+{
+       //struct nvt_ts_data *ts = i2c_get_clientdata(client);
+
+#if defined(CONFIG_FB)
+       if (fb_unregister_client(&ts->fb_notif))
+               NVT_ERR("Error occurred while unregistering fb_notifier.\n");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+       unregister_early_suspend(&ts->early_suspend);
+#endif
+
+#if NVT_TOUCH_FW
+       nvt_fw_sysfs_deinit();
+#endif
+
+       mutex_destroy(&ts->lock);
+
+       NVT_LOG("Removing driver...\n");
+
+       free_irq(client->irq, ts);
+       input_unregister_device(ts->input_dev);
+       i2c_set_clientdata(client, NULL);
+       kfree(ts);
+
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen driver suspend function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t nvt_ts_suspend(struct device *dev)
+{
+       uint8_t buf[4] = {0};
+#if MT_PROTOCOL_B
+       uint32_t i = 0;
+#endif
+
+       if (!bTouchIsAwake) {
+               NVT_LOG("Touch is already suspend\n");
+               return 0;
+       }
+
+       mutex_lock(&ts->lock);
+
+       NVT_LOG("start\n");
+#if NVT_TOUCH_FW
+       ts->suspended = 1;
+#endif
+       bTouchIsAwake = 0;
+#if NVT_TOUCH_ESD_PROTECT
+       cancel_delayed_work_sync(&nvt_esd_check_work);
+       nvt_esd_check_enable(false);
+#endif
+
+#if WAKEUP_GESTURE
+       //---write i2c command to enter "wakeup gesture mode"---
+       buf[0] = EVENT_MAP_HOST_CMD;
+       buf[1] = 0x13;
+#if 0 // Do not set 0xFF first, ToDo
+       buf[2] = 0xFF;
+       buf[3] = 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 4);
+#else
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
+#endif
+
+       enable_irq_wake(ts->client->irq);
+
+       NVT_LOG("Enabled touch wakeup gesture\n");
+
+#else // WAKEUP_GESTURE
+
+       disable_irq(ts->client->irq);
+
+       //---write i2c command to enter "deep sleep mode"---
+       buf[0] = EVENT_MAP_HOST_CMD;
+       buf[1] = 0x11;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
+#endif // WAKEUP_GESTURE
+
+       /* release all touches */
+#if MT_PROTOCOL_B
+       for (i = 0; i < ts->max_touch_num; i++) {
+               input_mt_slot(ts->input_dev, i);
+               input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
+               input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 0);
+               input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
+       }
+#endif
+       input_report_key(ts->input_dev, BTN_TOUCH, 0);
+#if !MT_PROTOCOL_B
+       input_mt_sync(ts->input_dev);
+#endif
+       input_sync(ts->input_dev);
+
+       msleep(50);
+
+       mutex_unlock(&ts->lock);
+
+       NVT_LOG("end\n");
+
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen driver resume function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t nvt_ts_resume(struct device *dev)
+{
+       int res = 0;
+
+       if (bTouchIsAwake) {
+               NVT_LOG("Touch is already resume\n");
+               return 0;
+       }
+
+       msleep(10);
+
+       mutex_lock(&ts->lock);
+
+       NVT_LOG("start\n");
+       // please make sure display reset(RESX) sequence and mipi dsi cmds sent before this
+#if NVT_TOUCH_SUPPORT_HW_RST
+       gpio_set_value(ts->reset_gpio, 1);
+#endif
+       nvt_bootloader_reset();
+       res = nvt_check_fw_reset_state(RESET_STATE_REK);
+
+       NVT_ERR("xlixiang---enter-%s-----res=%d\n", __func__, res);
+
+#if !WAKEUP_GESTURE
+       enable_irq(ts->client->irq);
+#endif
+
+#if NVT_TOUCH_ESD_PROTECT
+       queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work,
+       msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD));
+#endif
+       bTouchIsAwake = 1;
+#if NVT_TOUCH_FW
+               ts->suspended = 0;
+#endif
+
+       mutex_unlock(&ts->lock);
+
+       NVT_LOG("end\n");
+
+       return 0;
+}
+
+
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
+{
+       struct fb_event *evdata = data;
+       int *blank;
+       struct nvt_ts_data *ts =
+               container_of(self, struct nvt_ts_data, fb_notif);
+
+       if (evdata && evdata->data && event == FB_EARLY_EVENT_BLANK) {
+               blank = evdata->data;
+               if (*blank == FB_BLANK_POWERDOWN) {
+                       nvt_ts_suspend(&ts->client->dev);
+               }
+       } else if (evdata && evdata->data && event == FB_EVENT_BLANK) {
+               blank = evdata->data;
+               if (*blank == FB_BLANK_UNBLANK ||
+               (*blank == FB_BLANK_NORMAL && 0 == bTouchIsAwake)) {
+                       nvt_ts_resume(&ts->client->dev);
+               }
+       }
+
+       return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+/*******************************************************
+Description:
+       Novatek touchscreen driver early suspend function.
+
+return:
+       n.a.
+*******************************************************/
+static void nvt_ts_early_suspend(struct early_suspend *h)
+{
+       nvt_ts_suspend(ts->client, PMSG_SUSPEND);
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen driver late resume function.
+
+return:
+       n.a.
+*******************************************************/
+static void nvt_ts_late_resume(struct early_suspend *h)
+{
+       nvt_ts_resume(ts->client);
+}
+#endif
+
+#if 0
+static const struct dev_pm_ops nvt_ts_dev_pm_ops = {
+       .suspend = nvt_ts_suspend,
+       .resume  = nvt_ts_resume,
+};
+#endif
+
+static const struct i2c_device_id nvt_ts_id[] = {
+       { NVT_I2C_NAME, 0 },
+       { }
+};
+
+#ifdef CONFIG_OF
+static struct of_device_id nvt_match_table[] = {
+       { .compatible = "novatek,NVT-ts",},
+       { },
+};
+#endif
+/*
+static struct i2c_board_info __initdata nvt_i2c_boardinfo[] = {
+       {
+               I2C_BOARD_INFO(NVT_I2C_NAME, I2C_FW_Address),
+       },
+};
+*/
+
+static struct i2c_driver nvt_i2c_driver = {
+       .probe          = nvt_ts_probe,
+       .remove         = nvt_ts_remove,
+//     .suspend        = nvt_ts_suspend,
+//     .resume         = nvt_ts_resume,
+       .id_table       = nvt_ts_id,
+       .driver = {
+               .name   = NVT_I2C_NAME,
+               .owner  = THIS_MODULE,
+#if 0
+#ifdef CONFIG_PM
+               .pm = &nvt_ts_dev_pm_ops,
+#endif
+#endif
+#ifdef CONFIG_OF
+               .of_match_table = nvt_match_table,
+#endif
+       },
+};
+
+/*******************************************************
+Description:
+       Driver Install function.
+
+return:
+       Executive Outcomes. 0---succeed. not 0---failed.
+********************************************************/
+static int32_t __init nvt_driver_init(void)
+{
+       int32_t ret = 0;
+
+       NVT_LOG("start\n");
+       //---add i2c driver---
+       ret = i2c_add_driver(&nvt_i2c_driver);
+       if (ret) {
+               pr_err("%s: failed to add i2c driver", __func__);
+               goto err_driver;
+       }
+
+       pr_info("%s: finished\n", __func__);
+
+err_driver:
+       return ret;
+}
+
+/*******************************************************
+Description:
+       Driver uninstall function.
+
+return:
+       n.a.
+********************************************************/
+static void __exit nvt_driver_exit(void)
+{
+       i2c_del_driver(&nvt_i2c_driver);
+
+       if (nvt_wq)
+               destroy_workqueue(nvt_wq);
+
+#if BOOT_UPDATE_FIRMWARE
+       if (nvt_fwu_wq)
+               destroy_workqueue(nvt_fwu_wq);
+#endif
+#if NVT_TOUCH_ESD_PROTECT
+       if (nvt_esd_check_wq)
+               destroy_workqueue(nvt_esd_check_wq);
+#endif
+
+}
+
+//late_initcall(nvt_driver_init);
+module_init(nvt_driver_init);
+module_exit(nvt_driver_exit);
+
+MODULE_DESCRIPTION("Novatek Touchscreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/nt36xxx/nt36xxx.h b/drivers/input/touchscreen/nt36xxx/nt36xxx.h
new file mode 100755 (executable)
index 0000000..0c17bf3
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2010 - 2017 Novatek, Inc.
+ *
+ * $Revision: 22971 $
+ * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+#ifndef        _LINUX_NVT_TOUCH_H
+#define                _LINUX_NVT_TOUCH_H
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+#include "nt36xxx_mem_map.h"
+
+#define NVT_DEBUG 1
+
+//---GPIO number---
+#define NVTTOUCH_RST_PIN 980
+#define NVTTOUCH_INT_PIN 943
+
+
+//---INT trigger mode---
+//#define IRQ_TYPE_EDGE_RISING 1
+//#define IRQ_TYPE_EDGE_FALLING 2
+#define INT_TRIGGER_TYPE IRQ_TYPE_EDGE_RISING
+
+
+//---I2C driver info.---
+#define NVT_I2C_NAME "NVT-ts"
+#define I2C_BLDR_Address 0x01
+#define I2C_FW_Address 0x01
+#define I2C_HW_Address 0x62
+
+#if NVT_DEBUG
+#define NVT_LOG(fmt, args...)    pr_err("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args)
+#else
+#define NVT_LOG(fmt, args...)    pr_info("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args)
+#endif
+#define NVT_ERR(fmt, args...)    pr_err("[%s] %s %d: " fmt, NVT_I2C_NAME, __func__, __LINE__, ##args)
+
+//---Input device info.---
+#define NVT_TS_NAME "NVTCapacitiveTouchScreen"
+
+
+//---Touch info.---
+#define TOUCH_DEFAULT_MAX_WIDTH 1080
+#define TOUCH_DEFAULT_MAX_HEIGHT 2246
+#define TOUCH_MAX_FINGER_NUM 10
+#define TOUCH_KEY_NUM 0
+#if TOUCH_KEY_NUM > 0
+extern const uint16_t touch_key_array[TOUCH_KEY_NUM];
+#endif
+#define TOUCH_FORCE_NUM 1000
+
+/* Enable only when module have tp reset pin and connected to host */
+#define NVT_TOUCH_SUPPORT_HW_RST 1
+
+//---Customerized func.---
+#define NVT_TOUCH_PROC 1
+#define NVT_TOUCH_EXT_PROC 1
+#define NVT_TOUCH_FW 1
+#define NVT_TOUCH_MP 1
+#define NVT_TOUCH_MP_LENOVO 1
+#define MT_PROTOCOL_B 1
+#define WAKEUP_GESTURE 0
+#if WAKEUP_GESTURE
+extern const uint16_t gesture_key_array[];
+#endif
+#define BOOT_UPDATE_FIRMWARE 0
+#define BOOT_UPDATE_FIRMWARE_NAME "novatek_ts_fw.bin"
+/* ---ESD Protect.--- */
+#define NVT_TOUCH_ESD_PROTECT 1
+#define NVT_TOUCH_ESD_CHECK_PERIOD 2000        /* ms */
+
+struct nvt_ts_data {
+       struct i2c_client *client;
+       struct input_dev *input_dev;
+       struct work_struct nvt_work;
+       struct delayed_work nvt_fwu_work;
+       uint16_t addr;
+       int8_t phys[32];
+#if defined(CONFIG_FB)
+       struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+       struct early_suspend early_suspend;
+#endif
+       uint8_t fw_ver;
+       uint8_t x_num;
+       uint8_t y_num;
+       uint16_t abs_x_max;
+       uint16_t abs_y_max;
+       uint8_t max_touch_num;
+       uint8_t max_button_num;
+       uint32_t int_trigger_type;
+       int32_t irq_gpio;
+       uint32_t irq_flags;
+       int32_t reset_gpio;
+       uint32_t reset_flags;
+       struct mutex lock;
+       const struct nvt_ts_mem_map *mmap;
+       uint8_t carrier_system;
+       uint16_t nvt_pid;
+#if NVT_TOUCH_FW
+       int8_t product_id[10];
+       uint8_t suspended;
+       uint8_t force_reflash;
+       uint8_t loading_fw;
+#endif
+};
+
+#if NVT_TOUCH_FW
+#define FW_NAME_MAX_LEN 80
+#define VENDOR_NAME "novatek_ts"
+#endif
+
+#if NVT_TOUCH_PROC
+struct nvt_flash_data{
+       rwlock_t lock;
+       struct i2c_client *client;
+};
+#endif
+
+typedef enum {
+       RESET_STATE_INIT = 0xA0,// IC reset
+       RESET_STATE_REK,                // ReK baseline
+       RESET_STATE_REK_FINISH, // baseline is ready
+       RESET_STATE_NORMAL_RUN,
+       RESET_STATE_MAX  = 0xAF
+} RST_COMPLETE_STATE;
+
+typedef enum {
+    EVENT_MAP_HOST_CMD                      = 0x50,
+    EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE   = 0x51,
+    EVENT_MAP_RESET_COMPLETE                = 0x60,
+    EVENT_MAP_FWINFO                        = 0x78,
+    EVENT_MAP_PROJECTID                     = 0x9A,
+    EVENT_MAP_FWDATE                        = 0x9C,
+} I2C_EVENT_MAP;
+
+#if NVT_TOUCH_MP_LENOVO
+typedef enum {
+    MP_RESULT_SHIFT_SHORT = 0x00,
+    MP_RESULT_SHIFT_SHORT_DIFF,
+    MP_RESULT_SHIFT_SHORT_BASE,
+    MP_RESULT_SHIFT_OPEN,
+    MP_RESULT_SHIFT_RAWDATA,
+    MP_RESULT_SHIFT_CC,
+    MP_RESULT_SHIFT_CC_I,
+    MP_RESULT_SHIFT_CC_Q,
+    MP_RESULT_SHIFT_NOISE,
+    MP_RESULT_SHIFT_DIFF_MAX,
+    MP_RESULT_SHIFT_DIFF_MIN,
+/*  MP_RESULT_SHIFT_READFAIL,*/
+} MP_TEST_RESULT;
+#endif
+
+//---extern structures---
+extern struct nvt_ts_data *ts;
+
+//---extern functions---
+extern int32_t CTP_I2C_READ(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len);
+extern int32_t CTP_I2C_WRITE(struct i2c_client *client, uint16_t address, uint8_t *buf, uint16_t len);
+extern void nvt_bootloader_reset(void);
+extern void nvt_sw_reset_idle(void);
+extern int32_t nvt_check_fw_reset_state(RST_COMPLETE_STATE check_reset_state);
+extern int32_t nvt_get_fw_info(void);
+extern int32_t nvt_clear_fw_status(void);
+extern int32_t nvt_check_fw_status(void);
+
+#if NVT_TOUCH_ESD_PROTECT
+extern void nvt_esd_check_enable(uint8_t enable);
+#endif
+extern void nvt_stop_crc_reboot(void);
+
+#endif /* _LINUX_NVT_TOUCH_H */
diff --git a/drivers/input/touchscreen/nt36xxx/nt36xxx_ext_proc.c b/drivers/input/touchscreen/nt36xxx/nt36xxx_ext_proc.c
new file mode 100755 (executable)
index 0000000..00ee7b6
--- /dev/null
@@ -0,0 +1,716 @@
+/*
+ * Copyright (C) 2010 - 2017 Novatek, Inc.
+ *
+ * $Revision: 22971 $
+ * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+
+#include "nt36xxx.h"
+
+#if NVT_TOUCH_EXT_PROC
+#define NVT_FW_VERSION "nvt_fw_version"
+#define NVT_BASELINE "nvt_baseline"
+#define NVT_RAW "nvt_raw"
+#define NVT_DIFF "nvt_diff"
+
+#define I2C_TANSFER_LENGTH  64
+
+#define NORMAL_MODE 0x00
+#define TEST_MODE_1 0x21
+#define TEST_MODE_2 0x22
+#define HANDSHAKING_HOST_READY 0xBB
+
+#define XDATA_SECTOR_SIZE   256
+#define XDATA_BUF_SIZE    2048
+
+static uint8_t xdata_tmp[XDATA_BUF_SIZE] = {0};
+static int32_t xdata[XDATA_BUF_SIZE] = {0};
+static int32_t xdata_i[XDATA_BUF_SIZE] = {0};
+static int32_t xdata_q[XDATA_BUF_SIZE] = {0};
+
+static struct proc_dir_entry *NVT_proc_fw_version_entry;
+static struct proc_dir_entry *NVT_proc_baseline_entry;
+static struct proc_dir_entry *NVT_proc_raw_entry;
+static struct proc_dir_entry *NVT_proc_diff_entry;
+
+/*******************************************************
+Description:
+       Novatek touchscreen change mode function.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_change_mode(uint8_t mode)
+{
+       uint8_t buf[8] = {0};
+
+       //---set xdata index to EVENT BUF ADDR---
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+       //---set mode---
+       buf[0] = EVENT_MAP_HOST_CMD;
+       buf[1] = mode;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
+
+       if (mode == NORMAL_MODE) {
+               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
+               buf[1] = HANDSHAKING_HOST_READY;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
+               msleep(20);
+       }
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen get firmware pipe function.
+
+return:
+       Executive outcomes. 0---pipe 0. 1---pipe 1.
+*******************************************************/
+uint8_t nvt_get_fw_pipe(void)
+{
+       uint8_t buf[8]= {0};
+
+       //---set xdata index to EVENT BUF ADDR---
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+       //---read fw status---
+       buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
+       buf[1] = 0x00;
+       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
+
+       //NVT_LOG("FW pipe=%d, buf[1]=0x%02X\n", (buf[1]&0x01), buf[1]);
+
+       return (buf[1] & 0x01);
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen read mass data function.
+
+return:
+       n.a.
+*******************************************************/
+int32_t nvt_read_mass_data(uint8_t i2c_addr, uint8_t *temp_buf, uint32_t count)
+{
+       int32_t i = 0;
+       int32_t j = 0;
+       int32_t k = 0;
+       uint8_t i2c_buf[I2C_TANSFER_LENGTH + 1] = {0};
+       uint32_t xdata_addr = 0;
+       uint32_t head_addr = 0;
+       int32_t dummy_len = 0;
+       int32_t data_len = 0;
+       int32_t residual_len = 0;
+
+       xdata_addr = (temp_buf[3] << 24) + (temp_buf[4] << 16) + (temp_buf[5] << 8) + temp_buf[6];
+       head_addr = xdata_addr - (xdata_addr % XDATA_SECTOR_SIZE);
+       dummy_len = xdata_addr - head_addr;
+       data_len = (int32_t)((temp_buf[1] << 8) + temp_buf[2]);
+       residual_len = (head_addr + dummy_len + data_len) % XDATA_SECTOR_SIZE;
+
+       if (data_len > XDATA_BUF_SIZE)
+               return -EINVAL;
+
+       for (i = 0; i < ((dummy_len + data_len) / XDATA_SECTOR_SIZE); i++) {
+               i2c_buf[0] = 0xFF;
+               i2c_buf[1] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 16) & 0xFF;
+               i2c_buf[2] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 8) & 0xFF;
+               CTP_I2C_WRITE(ts->client, (uint16_t)i2c_addr, i2c_buf, 3);
+               for (j = 0; j < (XDATA_SECTOR_SIZE / I2C_TANSFER_LENGTH); j++) {
+                       i2c_buf[0] = I2C_TANSFER_LENGTH * j;
+                       CTP_I2C_READ(ts->client, (uint16_t)i2c_addr, i2c_buf, I2C_TANSFER_LENGTH + 1);
+                       for (k = 0; k < I2C_TANSFER_LENGTH; k++) {
+                               xdata_tmp[XDATA_SECTOR_SIZE * i + I2C_TANSFER_LENGTH * j + k] = i2c_buf[k + 1];
+                       }
+               }
+       }
+
+       if (residual_len != 0) {
+               i2c_buf[0] = 0xFF;
+               i2c_buf[1] = ((xdata_addr + data_len - residual_len) >> 16) & 0xFF;
+               i2c_buf[2] = ((xdata_addr + data_len - residual_len) >> 8) & 0xFF;
+               CTP_I2C_WRITE(ts->client, (uint16_t)i2c_addr, i2c_buf, 3);
+               for (j = 0; j < (residual_len / I2C_TANSFER_LENGTH + 1); j++) {
+                       i2c_buf[0] = I2C_TANSFER_LENGTH * j;
+                       CTP_I2C_READ(ts->client, (uint16_t)i2c_addr, i2c_buf, I2C_TANSFER_LENGTH + 1);
+                       for (k = 0; k < I2C_TANSFER_LENGTH; k++) {
+                               xdata_tmp[(dummy_len + data_len - residual_len) + I2C_TANSFER_LENGTH * j + k] = i2c_buf[k + 1];
+                       }
+               }
+       }
+
+       i2c_buf[0] = 0xFF;
+       i2c_buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       i2c_buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, (uint16_t)i2c_addr, i2c_buf, 3);
+
+       for (i = 0; i < data_len; i++) {
+               *(temp_buf + i) = xdata_tmp[dummy_len + i];
+       }
+
+       return  data_len;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen read meta data function.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_read_mdata(uint32_t xdata_addr, uint32_t xdata_btn_addr)
+{
+       int32_t i = 0;
+       int32_t j = 0;
+       int32_t k = 0;
+       uint8_t buf[I2C_TANSFER_LENGTH + 1] = {0};
+       uint32_t head_addr = 0;
+       int32_t dummy_len = 0;
+       int32_t data_len = 0;
+       int32_t residual_len = 0;
+
+       //---set xdata sector address & length---
+       head_addr = xdata_addr - (xdata_addr % XDATA_SECTOR_SIZE);
+       dummy_len = xdata_addr - head_addr;
+       data_len = ts->x_num * ts->y_num * 2;
+       residual_len = (head_addr + dummy_len + data_len) % XDATA_SECTOR_SIZE;
+
+       //printk("head_addr=0x%05X, dummy_len=0x%05X, data_len=0x%05X, residual_len=0x%05X\n", head_addr, dummy_len, data_len, residual_len);
+
+       //read xdata : step 1
+       for (i = 0; i < ((dummy_len + data_len) / XDATA_SECTOR_SIZE); i++) {
+               //---change xdata index---
+               buf[0] = 0xFF;
+               buf[1] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 16) & 0xFF;
+               buf[2] = ((head_addr + XDATA_SECTOR_SIZE * i) >> 8) & 0xFF;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+               //---read xdata by I2C_TANSFER_LENGTH
+               for (j = 0; j < (XDATA_SECTOR_SIZE / I2C_TANSFER_LENGTH); j++) {
+                       //---read data---
+                       buf[0] = I2C_TANSFER_LENGTH * j;
+                       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, I2C_TANSFER_LENGTH + 1);
+
+                       //---copy buf to xdata_tmp---
+                       for (k = 0; k < I2C_TANSFER_LENGTH; k++) {
+                               xdata_tmp[XDATA_SECTOR_SIZE * i + I2C_TANSFER_LENGTH * j + k] = buf[k + 1];
+                               //printk("0x%02X, 0x%04X\n", buf[k+1], (XDATA_SECTOR_SIZE*i + I2C_TANSFER_LENGTH*j + k));
+                       }
+               }
+               //printk("addr=0x%05X\n", (head_addr+XDATA_SECTOR_SIZE*i));
+       }
+
+       //read xdata : step2
+       if (residual_len != 0) {
+               //---change xdata index---
+               buf[0] = 0xFF;
+               buf[1] = ((xdata_addr + data_len - residual_len) >> 16) & 0xFF;
+               buf[2] = ((xdata_addr + data_len - residual_len) >> 8) & 0xFF;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+               //---read xdata by I2C_TANSFER_LENGTH
+               for (j = 0; j < (residual_len / I2C_TANSFER_LENGTH + 1); j++) {
+                       //---read data---
+                       buf[0] = I2C_TANSFER_LENGTH * j;
+                       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, I2C_TANSFER_LENGTH + 1);
+
+                       //---copy buf to xdata_tmp---
+                       for (k = 0; k < I2C_TANSFER_LENGTH; k++) {
+                               xdata_tmp[(dummy_len + data_len - residual_len) + I2C_TANSFER_LENGTH * j + k] = buf[k + 1];
+                               //printk("0x%02X, 0x%04x\n", buf[k+1], ((dummy_len+data_len-residual_len) + I2C_TANSFER_LENGTH*j + k));
+                       }
+               }
+               //printk("addr=0x%05X\n", (xdata_addr+data_len-residual_len));
+       }
+
+       //---remove dummy data and 2bytes-to-1data---
+       for (i = 0; i < (data_len / 2); i++) {
+               xdata[i] = (int16_t)(xdata_tmp[dummy_len + i * 2] + 256 * xdata_tmp[dummy_len + i * 2 + 1]);
+       }
+
+#if TOUCH_KEY_NUM > 0
+       //read button xdata : step3
+       //---change xdata index---
+       buf[0] = 0xFF;
+       buf[1] = (xdata_btn_addr >> 16) & 0xFF;
+       buf[2] = ((xdata_btn_addr >> 8) & 0xFF);
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+       //---read data---
+       buf[0] = (xdata_btn_addr & 0xFF);
+       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, (TOUCH_KEY_NUM * 2 + 1));
+
+       //---2bytes-to-1data---
+       for (i = 0; i < TOUCH_KEY_NUM; i++) {
+               xdata[ts->x_num * ts->y_num + i] = (int16_t)(buf[1 + i * 2] + 256 * buf[1 + i * 2 + 1]);
+       }
+#endif
+
+       //---set xdata index to EVENT BUF ADDR---
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen read meta data from IQ to rss function.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_read_mdata_rss(uint32_t xdata_i_addr, uint32_t xdata_q_addr, uint32_t xdata_btn_i_addr, uint32_t xdata_btn_q_addr)
+{
+       int i = 0;
+
+       nvt_read_mdata(xdata_i_addr, xdata_btn_i_addr);
+       memcpy(xdata_i, xdata, ((ts->x_num * ts->y_num + TOUCH_KEY_NUM) * sizeof(int32_t)));
+
+       nvt_read_mdata(xdata_q_addr, xdata_btn_q_addr);
+       memcpy(xdata_q, xdata, ((ts->x_num * ts->y_num + TOUCH_KEY_NUM) * sizeof(int32_t)));
+
+       for (i = 0; i < (ts->x_num * ts->y_num + TOUCH_KEY_NUM); i++) {
+               xdata[i] = (int32_t)int_sqrt((unsigned long)(xdata_i[i] * xdata_i[i]) + (unsigned long)(xdata_q[i] * xdata_q[i]));
+       }
+}
+
+/*******************************************************
+Description:
+    Novatek touchscreen get meta data function.
+
+return:
+    n.a.
+*******************************************************/
+void nvt_get_mdata(int32_t *buf, uint8_t *m_x_num, uint8_t *m_y_num)
+{
+    *m_x_num = ts->x_num;
+    *m_y_num = ts->y_num;
+    memcpy(buf, xdata, ((ts->x_num * ts->y_num + TOUCH_KEY_NUM) * sizeof(int32_t)));
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen firmware version show function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t c_fw_version_show(struct seq_file *m, void *v)
+{
+       seq_printf(m, "fw_ver=%d, x_num=%d, y_num=%d, button_num=%d\n", ts->fw_ver, ts->x_num, ts->y_num, ts->max_button_num);
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen xdata sequence print show
+       function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t c_show(struct seq_file *m, void *v)
+{
+       int32_t i = 0;
+       int32_t j = 0;
+
+       for (i = 0; i < ts->y_num; i++) {
+               for (j = 0; j < ts->x_num; j++) {
+                       seq_printf(m, "%5d, ", xdata[i * ts->x_num + j]);
+               }
+               seq_puts(m, "\n");
+       }
+
+#if TOUCH_KEY_NUM > 0
+       for (i = 0; i < TOUCH_KEY_NUM; i++) {
+               seq_printf(m, "%5d, ", xdata[ts->x_num * ts->y_num + i]);
+       }
+       seq_puts(m, "\n");
+#endif
+
+       seq_printf(m, "\n\n");
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen xdata sequence print start
+       function.
+
+return:
+       Executive outcomes. 1---call next function.
+       NULL---not call next function and sequence loop
+       stop.
+*******************************************************/
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+       return *pos < 1 ? (void *)1 : NULL;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen xdata sequence print next
+       function.
+
+return:
+       Executive outcomes. NULL---no next and call sequence
+       stop function.
+*******************************************************/
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       ++*pos;
+       return NULL;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen xdata sequence print stop
+       function.
+
+return:
+       n.a.
+*******************************************************/
+static void c_stop(struct seq_file *m, void *v)
+{
+       return;
+}
+
+const struct seq_operations nvt_fw_version_seq_ops = {
+       .start  = c_start,
+       .next   = c_next,
+       .stop   = c_stop,
+       .show   = c_fw_version_show
+};
+
+const struct seq_operations nvt_seq_ops = {
+       .start  = c_start,
+       .next   = c_next,
+       .stop   = c_stop,
+       .show   = c_show
+};
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/nvt_fw_version open
+       function.
+
+return:
+       n.a.
+*******************************************************/
+static int32_t nvt_info_open(struct inode *inode, struct file *file)
+{
+       if (mutex_lock_interruptible(&ts->lock)) {
+               return -ERESTARTSYS;
+       }
+
+       NVT_LOG("++\n");
+#if NVT_TOUCH_ESD_PROTECT
+                       nvt_esd_check_enable(false);
+#endif
+       if (nvt_get_fw_info()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       mutex_unlock(&ts->lock);
+
+       NVT_LOG("--\n");
+
+       return seq_open(file, &nvt_fw_version_seq_ops);
+}
+
+static const struct file_operations nvt_info_proc_fops = {
+       .owner = THIS_MODULE,
+       .open = nvt_info_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+static int32_t nvt_fw_version_open(struct inode *inode, struct file *file)
+{
+       if (mutex_lock_interruptible(&ts->lock)) {
+               return -ERESTARTSYS;
+       }
+
+       NVT_LOG("++\n");
+#if NVT_TOUCH_ESD_PROTECT
+               nvt_esd_check_enable(false);
+#endif
+       if (nvt_get_fw_info()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       mutex_unlock(&ts->lock);
+
+       NVT_LOG("--\n");
+
+       return seq_open(file, &nvt_fw_version_seq_ops);
+}
+
+static const struct file_operations nvt_fw_version_fops = {
+       .owner = THIS_MODULE,
+       .open = nvt_fw_version_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/nvt_baseline open function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t nvt_baseline_open(struct inode *inode, struct file *file)
+{
+       if (mutex_lock_interruptible(&ts->lock)) {
+               return -ERESTARTSYS;
+       }
+
+       NVT_LOG("++\n");
+#if NVT_TOUCH_ESD_PROTECT
+                       nvt_esd_check_enable(false);
+#endif
+       if (nvt_clear_fw_status()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       nvt_change_mode(TEST_MODE_2);
+
+       if (nvt_check_fw_status()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       if (nvt_get_fw_info()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       if (ts->carrier_system) {
+               nvt_read_mdata_rss(ts->mmap->BASELINE_ADDR, ts->mmap->BASELINE_Q_ADDR,
+                               ts->mmap->BASELINE_BTN_ADDR, ts->mmap->BASELINE_BTN_Q_ADDR);
+       } else {
+               nvt_read_mdata(ts->mmap->BASELINE_ADDR, ts->mmap->BASELINE_BTN_ADDR);
+       }
+
+       nvt_change_mode(NORMAL_MODE);
+
+       mutex_unlock(&ts->lock);
+
+       NVT_LOG("--\n");
+
+       return seq_open(file, &nvt_seq_ops);
+}
+
+static const struct file_operations nvt_baseline_fops = {
+       .owner = THIS_MODULE,
+       .open = nvt_baseline_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/nvt_raw open function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t nvt_raw_open(struct inode *inode, struct file *file)
+{
+       if (mutex_lock_interruptible(&ts->lock)) {
+               return -ERESTARTSYS;
+       }
+
+       NVT_LOG("++\n");
+#if NVT_TOUCH_ESD_PROTECT
+               nvt_esd_check_enable(false);
+#endif
+       if (nvt_clear_fw_status()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       nvt_change_mode(TEST_MODE_2);
+
+       if (nvt_check_fw_status()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       if (nvt_get_fw_info()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       if (ts->carrier_system) {
+               if (nvt_get_fw_pipe() == 0)
+                       nvt_read_mdata_rss(ts->mmap->RAW_PIPE0_ADDR, ts->mmap->RAW_PIPE0_Q_ADDR,
+                               ts->mmap->RAW_BTN_PIPE0_ADDR, ts->mmap->RAW_BTN_PIPE0_Q_ADDR);
+               else
+                       nvt_read_mdata_rss(ts->mmap->RAW_PIPE1_ADDR, ts->mmap->RAW_PIPE1_Q_ADDR,
+                               ts->mmap->RAW_BTN_PIPE1_ADDR, ts->mmap->RAW_BTN_PIPE1_Q_ADDR);
+       } else {
+               if (nvt_get_fw_pipe() == 0)
+                       nvt_read_mdata(ts->mmap->RAW_PIPE0_ADDR, ts->mmap->RAW_BTN_PIPE0_ADDR);
+               else
+                       nvt_read_mdata(ts->mmap->RAW_PIPE1_ADDR, ts->mmap->RAW_BTN_PIPE1_ADDR);
+       }
+
+       nvt_change_mode(NORMAL_MODE);
+
+       mutex_unlock(&ts->lock);
+
+       NVT_LOG("--\n");
+
+       return seq_open(file, &nvt_seq_ops);
+}
+
+static const struct file_operations nvt_raw_fops = {
+       .owner = THIS_MODULE,
+       .open = nvt_raw_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/nvt_diff open function.
+
+return:
+       Executive outcomes. 0---succeed. negative---failed.
+*******************************************************/
+static int32_t nvt_diff_open(struct inode *inode, struct file *file)
+{
+       if (mutex_lock_interruptible(&ts->lock)) {
+               return -ERESTARTSYS;
+       }
+
+       NVT_LOG("++\n");
+#if NVT_TOUCH_ESD_PROTECT
+               nvt_esd_check_enable(false);
+#endif
+       if (nvt_clear_fw_status()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       nvt_change_mode(TEST_MODE_2);
+
+       if (nvt_check_fw_status()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       if (nvt_get_fw_info()) {
+               mutex_unlock(&ts->lock);
+               return -EAGAIN;
+       }
+
+       if (ts->carrier_system) {
+               if (nvt_get_fw_pipe() == 0)
+                       nvt_read_mdata_rss(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_PIPE0_Q_ADDR,
+                               ts->mmap->DIFF_BTN_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_Q_ADDR);
+               else
+                       nvt_read_mdata_rss(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_PIPE1_Q_ADDR,
+                               ts->mmap->DIFF_BTN_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_Q_ADDR);
+       } else {
+               if (nvt_get_fw_pipe() == 0)
+                       nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR);
+               else
+                       nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR);
+       }
+
+       nvt_change_mode(NORMAL_MODE);
+
+       mutex_unlock(&ts->lock);
+
+       NVT_LOG("--\n");
+
+       return seq_open(file, &nvt_seq_ops);
+}
+
+static const struct file_operations nvt_diff_fops = {
+       .owner = THIS_MODULE,
+       .open = nvt_diff_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+/*******************************************************
+Description:
+       Novatek touchscreen extra function proc. file node
+       initial function.
+
+return:
+       Executive outcomes. 0---succeed. -12---failed.
+*******************************************************/
+int32_t nvt_extra_proc_init(void)
+{
+       NVT_proc_fw_version_entry = proc_create(NVT_FW_VERSION, 0444, NULL,&nvt_fw_version_fops);
+       if (NVT_proc_fw_version_entry == NULL) {
+               NVT_ERR("create proc/nvt_fw_version Failed!\n");
+               return -ENOMEM;
+       } else {
+               NVT_LOG("create proc/nvt_fw_version Succeeded!\n");
+       }
+
+       NVT_proc_baseline_entry = proc_create(NVT_BASELINE, 0444, NULL,&nvt_baseline_fops);
+       if (NVT_proc_baseline_entry == NULL) {
+               NVT_ERR("create proc/nvt_baseline Failed!\n");
+               return -ENOMEM;
+       } else {
+               NVT_LOG("create proc/nvt_baseline Succeeded!\n");
+       }
+
+       NVT_proc_raw_entry = proc_create(NVT_RAW, 0444, NULL,&nvt_raw_fops);
+       if (NVT_proc_raw_entry == NULL) {
+               NVT_ERR("create proc/nvt_raw Failed!\n");
+               return -ENOMEM;
+       } else {
+               NVT_LOG("create proc/nvt_raw Succeeded!\n");
+       }
+
+       NVT_proc_diff_entry = proc_create(NVT_DIFF, 0444, NULL,&nvt_diff_fops);
+       if (NVT_proc_diff_entry == NULL) {
+               NVT_ERR("create proc/nvt_diff Failed!\n");
+               return -ENOMEM;
+       } else {
+               NVT_LOG("create proc/nvt_diff Succeeded!\n");
+       }
+
+       return 0;
+}
+#endif
diff --git a/drivers/input/touchscreen/nt36xxx/nt36xxx_fw_update.c b/drivers/input/touchscreen/nt36xxx/nt36xxx_fw_update.c
new file mode 100755 (executable)
index 0000000..a4bdeb2
--- /dev/null
@@ -0,0 +1,1385 @@
+/*
+ * Copyright (C) 2010 - 2017 Novatek, Inc.
+ *
+ * $Revision: 22971 $
+ * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/firmware.h>
+
+#include "nt36xxx.h"
+
+#if (BOOT_UPDATE_FIRMWARE || NVT_TOUCH_FW)
+
+#define FW_BIN_SIZE_116KB 118784
+#define FW_BIN_SIZE FW_BIN_SIZE_116KB
+#define FW_BIN_VER_OFFSET 0x1A000
+#define FW_BIN_VER_BAR_OFFSET 0x1A001
+#define FLASH_SECTOR_SIZE 4096
+#define SIZE_64KB 65536
+#define BLOCK_64KB_NUM 4
+
+const struct firmware *fw_entry = NULL;
+
+/*******************************************************
+Description:
+       Novatek touchscreen request update firmware function.
+
+return:
+       Executive outcomes. 0---succeed. -1,-22---failed.
+*******************************************************/
+int32_t update_firmware_request(char *filename)
+{
+       int32_t ret = 0;
+
+       if (NULL == filename) {
+               return -1;
+       }
+
+       NVT_LOG("filename is %s\n", filename);
+
+       ret = request_firmware(&fw_entry, filename, &ts->client->dev);
+       if (ret) {
+               NVT_ERR("firmware load failed, ret=%d\n", ret);
+               return ret;
+       }
+
+       // check bin file size (116kb)
+       if (fw_entry->size != FW_BIN_SIZE) {
+               NVT_ERR("bin file size not match. (%zu)\n", fw_entry->size);
+               return -EINVAL;
+       }
+
+       // check if FW version add FW version bar equals 0xFF
+       if (*(fw_entry->data + FW_BIN_VER_OFFSET) + *(fw_entry->data + FW_BIN_VER_BAR_OFFSET) != 0xFF) {
+               NVT_ERR("bin file FW_VER + FW_VER_BAR should be 0xFF!\n");
+               NVT_ERR("FW_VER=0x%02X, FW_VER_BAR=0x%02X\n", *(fw_entry->data+FW_BIN_VER_OFFSET), *(fw_entry->data+FW_BIN_VER_BAR_OFFSET));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen release update firmware function.
+
+return:
+       n.a.
+*******************************************************/
+void update_firmware_release(void)
+{
+       if (fw_entry) {
+               release_firmware(fw_entry);
+       }
+       fw_entry=NULL;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen check firmware version function.
+
+return:
+       Executive outcomes. 0---need update. 1---need not
+       update.
+*******************************************************/
+int32_t Check_FW_Ver(void)
+{
+       uint8_t buf[16] = {0};
+       int32_t ret = 0;
+
+       //write i2c index to EVENT BUF ADDR
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
+       if (ret < 0) {
+               NVT_ERR("i2c write error!(%d)\n", ret);
+               return ret;
+       }
+
+       //read Firmware Version
+       buf[0] = EVENT_MAP_FWINFO;
+       buf[1] = 0x00;
+       buf[2] = 0x00;
+       ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3);
+       if (ret < 0) {
+               NVT_ERR("i2c read error!(%d)\n", ret);
+               return ret;
+       }
+
+       NVT_LOG("IC FW Ver = 0x%02X, FW Ver Bar = 0x%02X\n", buf[1], buf[2]);
+       NVT_LOG("Bin FW Ver = 0x%02X, FW ver Bar = 0x%02X\n",
+                       fw_entry->data[FW_BIN_VER_OFFSET], fw_entry->data[FW_BIN_VER_BAR_OFFSET]);
+
+       // check IC FW_VER + FW_VER_BAR equals 0xFF or not, need to update if not
+       if ((buf[1] + buf[2]) != 0xFF) {
+               NVT_ERR("IC FW_VER + FW_VER_BAR not equals to 0xFF!\n");
+               return 0;
+       }
+
+       // compare IC and binary FW version
+       if (buf[1] > fw_entry->data[FW_BIN_VER_OFFSET])
+               return 1;
+       else
+               return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen resume from deep power down function.
+
+return:
+       Executive outcomes. 0---succeed. negative---failed.
+*******************************************************/
+int32_t Resume_PD(void)
+{
+       uint8_t buf[8] = {0};
+       int32_t ret = 0;
+       int32_t retry = 0;
+
+       // Resume Command
+       buf[0] = 0x00;
+       buf[1] = 0xAB;
+       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+       if (ret < 0) {
+               NVT_ERR("Write Enable error!!(%d)\n", ret);
+               return ret;
+       }
+
+       // Check 0xAA (Resume Command)
+       retry = 0;
+       while(1) {
+               msleep(1);
+               buf[0] = 0x00;
+               buf[1] = 0x00;
+               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+               if (ret < 0) {
+                       NVT_ERR("Check 0xAA (Resume Command) error!!(%d)\n", ret);
+                       return ret;
+               }
+               if (buf[1] == 0xAA) {
+                       break;
+               }
+               retry++;
+               if (unlikely(retry > 20)) {
+                       NVT_ERR("Check 0xAA (Resume Command) error!! status=0x%02X\n", buf[1]);
+                       return -1;
+               }
+       }
+       msleep(10);
+
+       NVT_LOG("Resume PD OK\n");
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen check firmware checksum function.
+
+return:
+       Executive outcomes. 0---checksum not match.
+       1---checksum match. -1--- checksum read failed.
+*******************************************************/
+int32_t Check_CheckSum(void)
+{
+       uint8_t buf[64] = {0};
+       uint32_t XDATA_Addr = ts->mmap->READ_FLASH_CHECKSUM_ADDR;
+       int32_t ret = 0;
+       int32_t i = 0;
+       int32_t k = 0;
+       uint16_t WR_Filechksum[BLOCK_64KB_NUM] = {0};
+       uint16_t RD_Filechksum[BLOCK_64KB_NUM] = {0};
+       size_t fw_bin_size = 0;
+       size_t len_in_blk = 0;
+       int32_t retry = 0;
+
+       if (Resume_PD()) {
+               NVT_ERR("Resume PD error!!\n");
+               return -1;
+       }
+
+       fw_bin_size = fw_entry->size;
+
+       for (i = 0; i < BLOCK_64KB_NUM; i++) {
+               if (fw_bin_size > (i * SIZE_64KB)) {
+                       // Calculate WR_Filechksum of each 64KB block
+                       len_in_blk = min(fw_bin_size - i * SIZE_64KB, (size_t)SIZE_64KB);
+                       WR_Filechksum[i] = i + 0x00 + 0x00 + (((len_in_blk - 1) >> 8) & 0xFF) + ((len_in_blk - 1) & 0xFF);
+                       for (k = 0; k < len_in_blk; k++) {
+                               WR_Filechksum[i] += fw_entry->data[k + i * SIZE_64KB];
+                       }
+                       WR_Filechksum[i] = 65535 - WR_Filechksum[i] + 1;
+
+                       // Fast Read Command
+                       buf[0] = 0x00;
+                       buf[1] = 0x07;
+                       buf[2] = i;
+                       buf[3] = 0x00;
+                       buf[4] = 0x00;
+                       buf[5] = ((len_in_blk - 1) >> 8) & 0xFF;
+                       buf[6] = (len_in_blk - 1) & 0xFF;
+                       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7);
+                       if (ret < 0) {
+                               NVT_ERR("Fast Read Command error!!(%d)\n", ret);
+                               return ret;
+                       }
+                       // Check 0xAA (Fast Read Command)
+                       retry = 0;
+                       while (1) {
+                               msleep(80);
+                               buf[0] = 0x00;
+                               buf[1] = 0x00;
+                               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+                               if (ret < 0) {
+                                       NVT_ERR("Check 0xAA (Fast Read Command) error!!(%d)\n", ret);
+                                       return ret;
+                               }
+                               if (buf[1] == 0xAA) {
+                                       break;
+                               }
+                               retry++;
+                               if (unlikely(retry > 5)) {
+                                       NVT_ERR("Check 0xAA (Fast Read Command) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
+                                       return -1;
+                               }
+                       }
+                       // Read Checksum (write addr high byte & middle byte)
+                       buf[0] = 0xFF;
+                       buf[1] = XDATA_Addr >> 16;
+                       buf[2] = (XDATA_Addr >> 8) & 0xFF;
+                       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
+                       if (ret < 0) {
+                               NVT_ERR("Read Checksum (write addr high byte & middle byte) error!!(%d)\n", ret);
+                               return ret;
+                       }
+                       // Read Checksum
+                       buf[0] = (XDATA_Addr) & 0xFF;
+                       buf[1] = 0x00;
+                       buf[2] = 0x00;
+                       ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3);
+                       if (ret < 0) {
+                               NVT_ERR("Read Checksum error!!(%d)\n", ret);
+                               return ret;
+                       }
+
+                       RD_Filechksum[i] = (uint16_t)((buf[2] << 8) | buf[1]);
+                       if (WR_Filechksum[i] != RD_Filechksum[i]) {
+                               NVT_ERR("RD_Filechksum[%d]=0x%04X, WR_Filechksum[%d]=0x%04X\n", i, RD_Filechksum[i], i, WR_Filechksum[i]);
+                               NVT_ERR("firmware checksum not match!!\n");
+                               return 0;
+                       }
+               }
+       }
+
+       NVT_LOG("firmware checksum match\n");
+       return 1;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen initial bootloader and flash
+       block function.
+
+return:
+       Executive outcomes. 0---succeed. negative---failed.
+*******************************************************/
+int32_t Init_BootLoader(void)
+{
+       uint8_t buf[64] = {0};
+       int32_t ret = 0;
+       int32_t retry = 0;
+
+       // SW Reset & Idle
+       nvt_sw_reset_idle();
+
+       // Initiate Flash Block
+       buf[0] = 0x00;
+       buf[1] = 0x00;
+       buf[2] = I2C_FW_Address;
+       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 3);
+       if (ret < 0) {
+               NVT_ERR("Inittial Flash Block error!!(%d)\n", ret);
+               return ret;
+       }
+
+       // Check 0xAA (Initiate Flash Block)
+       retry = 0;
+       while(1) {
+               msleep(1);
+               buf[0] = 0x00;
+               buf[1] = 0x00;
+               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+               if (ret < 0) {
+                       NVT_ERR("Check 0xAA (Inittial Flash Block) error!!(%d)\n", ret);
+                       return ret;
+               }
+               if (buf[1] == 0xAA) {
+                       break;
+               }
+               retry++;
+               if (unlikely(retry > 20)) {
+                       NVT_ERR("Check 0xAA (Inittial Flash Block) error!! status=0x%02X\n", buf[1]);
+                       return -1;
+               }
+       }
+
+       NVT_LOG("Init OK \n");
+       msleep(20);
+
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen erase flash sectors function.
+
+return:
+       Executive outcomes. 0---succeed. negative---failed.
+*******************************************************/
+int32_t Erase_Flash(void)
+{
+       uint8_t buf[64] = {0};
+       int32_t ret = 0;
+       int32_t count = 0;
+       int32_t i = 0;
+       int32_t Flash_Address = 0;
+       int32_t retry = 0;
+
+       // Write Enable
+       buf[0] = 0x00;
+       buf[1] = 0x06;
+       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+       if (ret < 0) {
+               NVT_ERR("Write Enable (for Write Status Register) error!!(%d)\n", ret);
+               return ret;
+       }
+       // Check 0xAA (Write Enable)
+       retry = 0;
+       while (1) {
+               mdelay(1);
+               buf[0] = 0x00;
+               buf[1] = 0x00;
+               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+               if (ret < 0) {
+                       NVT_ERR("Check 0xAA (Write Enable for Write Status Register) error!!(%d)\n", ret);
+                       return ret;
+               }
+               if (buf[1] == 0xAA) {
+                       break;
+               }
+               retry++;
+               if (unlikely(retry > 20)) {
+                       NVT_ERR("Check 0xAA (Write Enable for Write Status Register) error!! status=0x%02X\n", buf[1]);
+                       return -1;
+               }
+       }
+
+       // Write Status Register
+       buf[0] = 0x00;
+       buf[1] = 0x01;
+       buf[2] = 0x00;
+       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 3);
+       if (ret < 0) {
+               NVT_ERR("Write Status Register error!!(%d)\n", ret);
+               return ret;
+       }
+       // Check 0xAA (Write Status Register)
+       retry = 0;
+       while (1) {
+               mdelay(1);
+               buf[0] = 0x00;
+               buf[1] = 0x00;
+               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+               if (ret < 0) {
+                       NVT_ERR("Check 0xAA (Write Status Register) error!!(%d)\n", ret);
+                       return ret;
+               }
+               if (buf[1] == 0xAA) {
+                       break;
+               }
+               retry++;
+               if (unlikely(retry > 20)) {
+                       NVT_ERR("Check 0xAA (Write Status Register) error!! status=0x%02X\n", buf[1]);
+                       return -1;
+               }
+       }
+
+       // Read Status
+       retry = 0;
+       while (1) {
+               mdelay(5);
+               buf[0] = 0x00;
+               buf[1] = 0x05;
+               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+               if (ret < 0) {
+                       NVT_ERR("Read Status (for Write Status Register) error!!(%d)\n", ret);
+                       return ret;
+               }
+
+               // Check 0xAA (Read Status)
+               buf[0] = 0x00;
+               buf[1] = 0x00;
+               buf[2] = 0x00;
+               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3);
+               if (ret < 0) {
+                       NVT_ERR("Check 0xAA (Read Status for Write Status Register) error!!(%d)\n", ret);
+                       return ret;
+               }
+               if ((buf[1] == 0xAA) && (buf[2] == 0x00)) {
+                       break;
+               }
+               retry++;
+               if (unlikely(retry > 100)) {
+                       NVT_ERR("Check 0xAA (Read Status for Write Status Register) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry);
+                       return -1;
+               }
+       }
+
+       if (fw_entry->size % FLASH_SECTOR_SIZE)
+               count = fw_entry->size / FLASH_SECTOR_SIZE + 1;
+       else
+               count = fw_entry->size / FLASH_SECTOR_SIZE;
+
+       for(i = 0; i < count; i++) {
+               // Write Enable
+               buf[0] = 0x00;
+               buf[1] = 0x06;
+               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+               if (ret < 0) {
+                       NVT_ERR("Write Enable error!!(%d,%d)\n", ret, i);
+                       return ret;
+               }
+               // Check 0xAA (Write Enable)
+               retry = 0;
+               while (1) {
+                       mdelay(1);
+                       buf[0] = 0x00;
+                       buf[1] = 0x00;
+                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+                       if (ret < 0) {
+                               NVT_ERR("Check 0xAA (Write Enable) error!!(%d,%d)\n", ret, i);
+                               return ret;
+                       }
+                       if (buf[1] == 0xAA) {
+                               break;
+                       }
+                       retry++;
+                       if (unlikely(retry > 20)) {
+                               NVT_ERR("Check 0xAA (Write Enable) error!! status=0x%02X\n", buf[1]);
+                               return -1;
+                       }
+               }
+
+               Flash_Address = i * FLASH_SECTOR_SIZE;
+
+               // Sector Erase
+               buf[0] = 0x00;
+               buf[1] = 0x20;    // Command : Sector Erase
+               buf[2] = ((Flash_Address >> 16) & 0xFF);
+               buf[3] = ((Flash_Address >> 8) & 0xFF);
+               buf[4] = (Flash_Address & 0xFF);
+               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 5);
+               if (ret < 0) {
+                       NVT_ERR("Sector Erase error!!(%d,%d)\n", ret, i);
+                       return ret;
+               }
+               // Check 0xAA (Sector Erase)
+               retry = 0;
+               while (1) {
+                       mdelay(1);
+                       buf[0] = 0x00;
+                       buf[1] = 0x00;
+                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+                       if (ret < 0) {
+                               NVT_ERR("Check 0xAA (Sector Erase) error!!(%d,%d)\n", ret, i);
+                               return ret;
+                       }
+                       if (buf[1] == 0xAA) {
+                               break;
+                       }
+                       retry++;
+                       if (unlikely(retry > 20)) {
+                               NVT_ERR("Check 0xAA (Sector Erase) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
+                               return -1;
+                       }
+               }
+
+               // Read Status
+               retry = 0;
+               while (1) {
+                       mdelay(5);
+                       buf[0] = 0x00;
+                       buf[1] = 0x05;
+                       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+                       if (ret < 0) {
+                               NVT_ERR("Read Status error!!(%d,%d)\n", ret, i);
+                               return ret;
+                       }
+
+                       // Check 0xAA (Read Status)
+                       buf[0] = 0x00;
+                       buf[1] = 0x00;
+                       buf[2] = 0x00;
+                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3);
+                       if (ret < 0) {
+                               NVT_ERR("Check 0xAA (Read Status) error!!(%d,%d)\n", ret, i);
+                               return ret;
+                       }
+                       if ((buf[1] == 0xAA) && (buf[2] == 0x00)) {
+                               break;
+                       }
+                       retry++;
+                       if (unlikely(retry > 100)) {
+                               NVT_ERR("Check 0xAA (Read Status) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry);
+                               return -1;
+                       }
+               }
+       }
+
+       NVT_LOG("Erase OK \n");
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen write flash sectors function.
+
+return:
+       Executive outcomes. 0---succeed. negative---failed.
+*******************************************************/
+int32_t Write_Flash(void)
+{
+       uint8_t buf[64] = {0};
+       uint32_t XDATA_Addr = ts->mmap->RW_FLASH_DATA_ADDR;
+       uint32_t Flash_Address = 0;
+       int32_t i = 0, j = 0, k = 0;
+       uint8_t tmpvalue = 0;
+       int32_t count = 0;
+       int32_t ret = 0;
+       int32_t retry = 0;
+
+       // change I2C buffer index
+       buf[0] = 0xFF;
+       buf[1] = XDATA_Addr >> 16;
+       buf[2] = (XDATA_Addr >> 8) & 0xFF;
+       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
+       if (ret < 0) {
+               NVT_ERR("change I2C buffer index error!!(%d)\n", ret);
+               return ret;
+       }
+
+       if (fw_entry->size % 256)
+               count = fw_entry->size / 256 + 1;
+       else
+               count = fw_entry->size / 256;
+
+       for (i = 0; i < count; i++) {
+               Flash_Address = i * 256;
+
+               // Write Enable
+               buf[0] = 0x00;
+               buf[1] = 0x06;
+               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+               if (ret < 0) {
+                       NVT_ERR("Write Enable error!!(%d)\n", ret);
+                       return ret;
+               }
+               // Check 0xAA (Write Enable)
+               retry = 0;
+               while (1) {
+                       udelay(100);
+                       buf[0] = 0x00;
+                       buf[1] = 0x00;
+                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+                       if (ret < 0) {
+                               NVT_ERR("Check 0xAA (Write Enable) error!!(%d,%d)\n", ret, i);
+                               return ret;
+                       }
+                       if (buf[1] == 0xAA) {
+                               break;
+                       }
+                       retry++;
+                       if (unlikely(retry > 20)) {
+                               NVT_ERR("Check 0xAA (Write Enable) error!! status=0x%02X\n", buf[1]);
+                               return -1;
+                       }
+               }
+
+               // Write Page : 256 bytes
+               for (j = 0; j < min(fw_entry->size - i * 256, (size_t)256); j += 32) {
+                       buf[0] = (XDATA_Addr + j) & 0xFF;
+                       for (k = 0; k < 32; k++) {
+                               buf[1 + k] = fw_entry->data[Flash_Address + j + k];
+                       }
+                       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 33);
+                       if (ret < 0) {
+                               NVT_ERR("Write Page error!!(%d), j=%d\n", ret, j);
+                               return ret;
+                       }
+               }
+               if (fw_entry->size - Flash_Address >= 256)
+                       tmpvalue=(Flash_Address >> 16) + ((Flash_Address >> 8) & 0xFF) + (Flash_Address & 0xFF) + 0x00 + (255);
+               else
+                       tmpvalue=(Flash_Address >> 16) + ((Flash_Address >> 8) & 0xFF) + (Flash_Address & 0xFF) + 0x00 + (fw_entry->size - Flash_Address - 1);
+
+               for (k = 0;k < min(fw_entry->size - Flash_Address,(size_t)256); k++)
+                       tmpvalue += fw_entry->data[Flash_Address + k];
+
+               tmpvalue = 255 - tmpvalue + 1;
+
+               // Page Program
+               buf[0] = 0x00;
+               buf[1] = 0x02;
+               buf[2] = ((Flash_Address >> 16) & 0xFF);
+               buf[3] = ((Flash_Address >> 8) & 0xFF);
+               buf[4] = (Flash_Address & 0xFF);
+               buf[5] = 0x00;
+               buf[6] = min(fw_entry->size - Flash_Address,(size_t)256) - 1;
+               buf[7] = tmpvalue;
+               ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 8);
+               if (ret < 0) {
+                       NVT_ERR("Page Program error!!(%d), i=%d\n", ret, i);
+                       return ret;
+               }
+               // Check 0xAA (Page Program)
+               retry = 0;
+               while (1) {
+                       mdelay(1);
+                       buf[0] = 0x00;
+                       buf[1] = 0x00;
+                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+                       if (ret < 0) {
+                               NVT_ERR("Page Program error!!(%d)\n", ret);
+                               return ret;
+                       }
+                       if (buf[1] == 0xAA || buf[1] == 0xEA) {
+                               break;
+                       }
+                       retry++;
+                       if (unlikely(retry > 20)) {
+                               NVT_ERR("Check 0xAA (Page Program) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
+                               return -1;
+                       }
+               }
+               if (buf[1] == 0xEA) {
+                       NVT_ERR("Page Program error!! i=%d\n", i);
+                       return -3;
+               }
+
+               // Read Status
+               retry = 0;
+               while (1) {
+                       mdelay(5);
+                       buf[0] = 0x00;
+                       buf[1] = 0x05;
+                       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+                       if (ret < 0) {
+                               NVT_ERR("Read Status error!!(%d)\n", ret);
+                               return ret;
+                       }
+
+                       // Check 0xAA (Read Status)
+                       buf[0] = 0x00;
+                       buf[1] = 0x00;
+                       buf[2] = 0x00;
+                       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3);
+                       if (ret < 0) {
+                               NVT_ERR("Check 0xAA (Read Status) error!!(%d)\n", ret);
+                               return ret;
+                       }
+                       if (((buf[1] == 0xAA) && (buf[2] == 0x00)) || (buf[1] == 0xEA)) {
+                               break;
+                       }
+                       retry++;
+                       if (unlikely(retry > 100)) {
+                               NVT_ERR("Check 0xAA (Read Status) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry);
+                               return -1;
+                       }
+               }
+               if (buf[1] == 0xEA) {
+                       NVT_ERR("Page Program error!! i=%d\n", i);
+                       return -4;
+               }
+
+               NVT_LOG("Programming...%2d%%\r", ((i * 100) / count));
+       }
+
+       NVT_LOG("Programming...%2d%%\r", 100);
+       NVT_LOG("Program OK         \n");
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen verify checksum of written
+       flash function.
+
+return:
+       Executive outcomes. 0---succeed. negative---failed.
+*******************************************************/
+int32_t Verify_Flash(void)
+{
+       uint8_t buf[64] = {0};
+       uint32_t XDATA_Addr = ts->mmap->READ_FLASH_CHECKSUM_ADDR;
+       int32_t ret = 0;
+       int32_t i = 0;
+       int32_t k = 0;
+       uint16_t WR_Filechksum[BLOCK_64KB_NUM] = {0};
+       uint16_t RD_Filechksum[BLOCK_64KB_NUM] = {0};
+       size_t fw_bin_size = 0;
+       size_t len_in_blk = 0;
+       int32_t retry = 0;
+
+       fw_bin_size = fw_entry->size;
+
+       for (i = 0; i < BLOCK_64KB_NUM; i++) {
+               if (fw_bin_size > (i * SIZE_64KB)) {
+                       // Calculate WR_Filechksum of each 64KB block
+                       len_in_blk = min(fw_bin_size - i * SIZE_64KB, (size_t)SIZE_64KB);
+                       WR_Filechksum[i] = i + 0x00 + 0x00 + (((len_in_blk - 1) >> 8) & 0xFF) + ((len_in_blk - 1) & 0xFF);
+                       for (k = 0; k < len_in_blk; k++) {
+                               WR_Filechksum[i] += fw_entry->data[k + i * SIZE_64KB];
+                       }
+                       WR_Filechksum[i] = 65535 - WR_Filechksum[i] + 1;
+
+                       // Fast Read Command
+                       buf[0] = 0x00;
+                       buf[1] = 0x07;
+                       buf[2] = i;
+                       buf[3] = 0x00;
+                       buf[4] = 0x00;
+                       buf[5] = ((len_in_blk - 1) >> 8) & 0xFF;
+                       buf[6] = (len_in_blk - 1) & 0xFF;
+                       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7);
+                       if (ret < 0) {
+                               NVT_ERR("Fast Read Command error!!(%d)\n", ret);
+                               return ret;
+                       }
+                       // Check 0xAA (Fast Read Command)
+                       retry = 0;
+                       while (1) {
+                               msleep(80);
+                               buf[0] = 0x00;
+                               buf[1] = 0x00;
+                               ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+                               if (ret < 0) {
+                                       NVT_ERR("Check 0xAA (Fast Read Command) error!!(%d)\n", ret);
+                                       return ret;
+                               }
+                               if (buf[1] == 0xAA) {
+                                       break;
+                               }
+                               retry++;
+                               if (unlikely(retry > 5)) {
+                                       NVT_ERR("Check 0xAA (Fast Read Command) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
+                                       return -1;
+                               }
+                       }
+                       // Read Checksum (write addr high byte & middle byte)
+                       buf[0] = 0xFF;
+                       buf[1] = XDATA_Addr >> 16;
+                       buf[2] = (XDATA_Addr >> 8) & 0xFF;
+                       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
+                       if (ret < 0) {
+                               NVT_ERR("Read Checksum (write addr high byte & middle byte) error!!(%d)\n", ret);
+                               return ret;
+                       }
+                       // Read Checksum
+                       buf[0] = (XDATA_Addr) & 0xFF;
+                       buf[1] = 0x00;
+                       buf[2] = 0x00;
+                       ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3);
+                       if (ret < 0) {
+                               NVT_ERR("Read Checksum error!!(%d)\n", ret);
+                               return ret;
+                       }
+
+                       RD_Filechksum[i] = (uint16_t)((buf[2] << 8) | buf[1]);
+                       if (WR_Filechksum[i] != RD_Filechksum[i]) {
+                               NVT_ERR("Verify Fail%d!!\n", i);
+                               NVT_ERR("RD_Filechksum[%d]=0x%04X, WR_Filechksum[%d]=0x%04X\n", i, RD_Filechksum[i], i, WR_Filechksum[i]);
+                               return -1;
+                       }
+               }
+       }
+
+       NVT_LOG("Verify OK \n");
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen update firmware function.
+
+return:
+       Executive outcomes. 0---succeed. negative---failed.
+*******************************************************/
+int32_t Update_Firmware(void)
+{
+       int32_t ret = 0;
+
+       //---Stop CRC check to prevent IC auto reboot---
+       nvt_stop_crc_reboot();
+
+       // Step 1 : initial bootloader
+       ret = Init_BootLoader();
+       if (ret) {
+               return ret;
+       }
+
+       // Step 2 : Resume PD
+       ret = Resume_PD();
+       if (ret) {
+               return ret;
+       }
+
+       // Step 3 : Erase
+       ret = Erase_Flash();
+       if (ret) {
+               return ret;
+       }
+
+       // Step 4 : Program
+       ret = Write_Flash();
+       if (ret) {
+               return ret;
+       }
+
+       // Step 5 : Verify
+       ret = Verify_Flash();
+       if (ret) {
+               return ret;
+       }
+
+       //Step 6 : Bootloader Reset
+       nvt_bootloader_reset();
+       nvt_check_fw_reset_state(RESET_STATE_INIT);
+
+       return ret;
+}
+/*******************************************************
+Description:
+       Novatek touchscreen check flash end flag function.
+
+return:
+       Executive outcomes. 0---succeed. 1,negative---failed.
+*******************************************************/
+#define NVT_FLASH_END_FLAG_LEN 3
+#define NVT_FLASH_END_FLAG_ADDR 0x1AFFD
+int32_t nvt_check_flash_end_flag(void)
+{
+       uint8_t buf[8] = {0};
+       uint8_t nvt_end_flag[NVT_FLASH_END_FLAG_LEN + 1] = {0};
+       int32_t ret = 0;
+
+       // Step 1 : initial bootloader
+       ret = Init_BootLoader();
+       if (ret) {
+               return ret;
+       }
+
+       // Step 2 : Resume PD
+       ret = Resume_PD();
+       if (ret) {
+               return ret;
+       }
+
+       // Step 3 : unlock
+       buf[0] = 0x00;
+       buf[1] = 0x35;
+       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
+       if (ret < 0) {
+               NVT_ERR("write unlock error!!(%d)\n", ret);
+               return ret;
+       }
+       msleep(10);
+
+       //Step 4 : Flash Read Command
+       buf[0] = 0x00;
+       buf[1] = 0x03;
+       buf[2] = (NVT_FLASH_END_FLAG_ADDR >> 16) & 0xFF; //Addr_H
+       buf[3] = (NVT_FLASH_END_FLAG_ADDR >> 8) & 0xFF; //Addr_M
+       buf[4] = NVT_FLASH_END_FLAG_ADDR & 0xFF; //Addr_L
+       buf[5] = (NVT_FLASH_END_FLAG_LEN >> 8) & 0xFF; //Len_H
+       buf[6] = NVT_FLASH_END_FLAG_LEN & 0xFF; //Len_L
+       ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7);
+       if (ret < 0) {
+               NVT_ERR("write Read Command error!!(%d)\n", ret);
+               return ret;
+       }
+       msleep(10);
+
+       // Check 0xAA (Read Command)
+       buf[0] = 0x00;
+       buf[1] = 0x00;
+       ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
+       if (ret < 0) {
+               NVT_ERR("Check 0xAA (Read Command) error!!(%d)\n", ret);
+               return ret;
+       }
+       if (buf[1] != 0xAA) {
+               NVT_ERR("Check 0xAA (Read Command) error!! status=0x%02X\n", buf[1]);
+               return -1;
+       }
+
+       msleep(10);
+
+       //Step 5 : Read Flash Data
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->READ_FLASH_CHECKSUM_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->READ_FLASH_CHECKSUM_ADDR >> 8) & 0xFF;
+       ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 3);
+       if (ret < 0) {
+               NVT_ERR("change index error!! (%d)\n", ret);
+               return ret;
+       }
+       msleep(10);
+
+       // Read Back
+       buf[0] = ts->mmap->READ_FLASH_CHECKSUM_ADDR & 0xFF;
+       ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 6);
+       if (ret < 0) {
+               NVT_ERR("Read Back error!! (%d)\n", ret);
+               return ret;
+       }
+
+       //buf[3:5] => NVT End Flag
+       strncpy(nvt_end_flag, &buf[3], NVT_FLASH_END_FLAG_LEN);
+       NVT_LOG("nvt_end_flag=%s (%02X %02X %02X)\n", nvt_end_flag, buf[3], buf[4], buf[5]);
+
+       if (strncmp(nvt_end_flag, "NVT", 3) == 0) {
+               return 0;
+       } else {
+               NVT_ERR("\"NVT\" end flag not found!\n");
+               return 1;
+       }
+}
+#endif
+
+#if BOOT_UPDATE_FIRMWARE
+/*******************************************************
+Description:
+       Novatek touchscreen update firmware when booting
+       function.
+
+return:
+       n.a.
+*******************************************************/
+void Boot_Update_Firmware(struct work_struct *work)
+{
+       int32_t ret = 0;
+
+       char firmware_name[256] = "";
+       sprintf(firmware_name, BOOT_UPDATE_FIRMWARE_NAME);
+
+       // request bin file in "/etc/firmware"
+       ret = update_firmware_request(firmware_name);
+       if (ret) {
+               NVT_ERR("update_firmware_request failed. (%d)\n", ret);
+               return;
+       }
+
+       mutex_lock(&ts->lock);
+#if NVT_TOUCH_ESD_PROTECT
+       nvt_esd_check_enable(false);
+#endif
+#if NVT_TOUCH_FW
+       ts->loading_fw = 1;
+#endif
+       nvt_sw_reset_idle();
+
+       ret = Check_CheckSum();
+
+       if (ret < 0) {  // read firmware checksum failed
+               NVT_ERR("read firmware checksum failed\n");
+               Update_Firmware();
+       } else if ((ret == 0) && (Check_FW_Ver() == 0)) {       // (fw checksum not match) && (bin fw version >= ic fw version)
+               NVT_LOG("firmware version not match\n");
+               Update_Firmware();
+       } else if (nvt_check_flash_end_flag()) {
+               NVT_LOG("check flash end flag failed\n");
+               Update_Firmware();
+       } else {
+               // Bootloader Reset
+               nvt_bootloader_reset();
+               nvt_check_fw_reset_state(RESET_STATE_INIT);
+       }
+
+#if NVT_TOUCH_FW
+       ts->loading_fw = 0;
+#endif
+       mutex_unlock(&ts->lock);
+
+       update_firmware_release();
+}
+#endif /* BOOT_UPDATE_FIRMWARE */
+
+#if NVT_TOUCH_FW
+static ssize_t nvt_poweron_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       bool val;
+
+       mutex_lock(&ts->lock);
+       val = ts->suspended;
+       mutex_unlock(&ts->lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n",
+               val == 0);
+}
+
+static DEVICE_ATTR(poweron, 0444, nvt_poweron_show, NULL);
+
+static ssize_t nvt_ic_ver_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       return scnprintf(buf, PAGE_SIZE, "[FW]%02x,[IC]NT36525\n",
+               ts->fw_ver);
+}
+
+static DEVICE_ATTR(ic_ver, 0444, nvt_ic_ver_show, NULL);
+
+static ssize_t nvt_productinfo_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+/* Update script use as $touch_product_id in fw name ==> (chip id from Lenovo&script) OR (vendor name from Focaltech) OR (project ID from Longcheer&Himax)
+   Project ID ?? ( - Jeter - Hannah)
+   Chip ID ?? (NVT-ts or NVTCapacitiveTouchScreen or NT36xxx) */
+       return scnprintf(buf, PAGE_SIZE, "%s\n",
+               ts->product_id);
+}
+
+static DEVICE_ATTR(productinfo, 0444, nvt_productinfo_show, NULL);
+
+static ssize_t nvt_force_reflash_store(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       unsigned int input;
+
+       if (sscanf(buf, "%u", &input) != 1)
+               return -EINVAL;
+
+       ts->force_reflash = (input == 0) ? false : true;
+
+       return count;
+}
+
+static DEVICE_ATTR(forcereflash, 0220, NULL, nvt_force_reflash_store);
+
+static ssize_t nvt_flashprog_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       return scnprintf(buf, PAGE_SIZE, "%d\n",
+               (ts->loading_fw) ? 1 : 0);
+}
+
+static DEVICE_ATTR(flashprog, 0444, nvt_flashprog_show, NULL);
+
+static ssize_t nvt_do_reflash_store(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       int retval;
+       char prefix[FW_NAME_MAX_LEN] = VENDOR_NAME;
+       char template[FW_NAME_MAX_LEN];
+       char firmware_name[256] = "";
+
+       if (count > FW_NAME_MAX_LEN) {
+               NVT_ERR("FW filename is too long\n");
+               retval = -EINVAL;
+               goto exit;
+       }
+
+       if (ts->suspended) {
+               NVT_ERR("In suspend state, try again later\n");
+               retval = -EINVAL;
+               goto exit;
+       }
+
+       if (ts->loading_fw) {
+               NVT_ERR("In FW flashing state, try again later\n");
+               retval = -EINVAL;
+               goto exit;
+       }
+
+       if (!ts->force_reflash) {
+               if (strncmp(buf, prefix,
+                       strnlen(prefix, sizeof(prefix)))) {
+                       NVT_ERR("FW does not belong to Novatek\n");
+                       retval = -EINVAL;
+                       goto exit;
+               }
+
+               snprintf(template, sizeof(template), "-%s-",
+                                               ts->product_id);
+               if (!strnstr(buf + strnlen(prefix, sizeof(prefix)), template,
+                       count)) {
+                       NVT_ERR("FW does not belong to %s\n", ts->product_id);
+                       retval = -EINVAL;
+                       goto exit;
+               }
+       }
+
+       strlcpy(firmware_name, buf, count);
+       NVT_LOG("FW filename: %s\n", firmware_name);
+
+       retval = update_firmware_request(firmware_name);
+       if (retval) {
+               NVT_ERR("update_firmware_request failed. (%d)\n", retval);
+               goto exit;
+       }
+
+       mutex_lock(&ts->lock);
+#if NVT_TOUCH_ESD_PROTECT
+       nvt_esd_check_enable(false);
+#endif
+       ts->loading_fw = 1;
+       nvt_sw_reset_idle();
+
+       retval = Check_CheckSum();
+
+       if (retval < 0) {
+               NVT_ERR("read firmware checksum failed\n");
+               Update_Firmware();
+       } else if ((retval == 0) && (Check_FW_Ver() == 0)) {
+               NVT_LOG("firmware version not match\n");
+               Update_Firmware();
+       } else if (nvt_check_flash_end_flag()) {
+               NVT_LOG("check flash end flag failed\n");
+               Update_Firmware();
+       } else {
+               /* Bootloader Reset */
+               nvt_bootloader_reset();
+               nvt_check_fw_reset_state(RESET_STATE_INIT);
+       }
+
+       ts->loading_fw = 0;
+       mutex_unlock(&ts->lock);
+
+       update_firmware_release();
+
+       retval = count;
+exit:
+       return retval;
+}
+
+static DEVICE_ATTR(doreflash, 0220, NULL, nvt_do_reflash_store);
+
+static ssize_t nvt_build_id_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+/* Update script use for comparing $str_cfg_id_latest in fw name */
+       uint8_t tmp_buf[4] = {0};
+       uint8_t fw_version = 0;
+       uint8_t date_Y = 0;
+       uint8_t date_M = 0;
+       uint8_t date_D = 0;
+
+       tmp_buf[0] = 0xFF;
+       tmp_buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       tmp_buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, tmp_buf, 3);
+
+       tmp_buf[0] = EVENT_MAP_FWINFO;
+       CTP_I2C_READ(ts->client, I2C_FW_Address, tmp_buf, 2);
+       fw_version = tmp_buf[1];
+
+       tmp_buf[0] = EVENT_MAP_FWDATE;
+       CTP_I2C_READ(ts->client, I2C_FW_Address, tmp_buf, 4);
+       date_Y = tmp_buf[1];
+       date_M = tmp_buf[2];
+       date_D = tmp_buf[3];
+
+       return scnprintf(buf, PAGE_SIZE, "%02x-%02d%02d%02d\n",
+               fw_version, date_Y, date_M, date_D);
+}
+
+static DEVICE_ATTR(buildid, 0444, nvt_build_id_show, NULL);
+
+
+#include <linux/slab.h>
+#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)
+{
+       ssize_t blen;
+       const char *path;
+
+       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, VENDOR_NAME);
+}
+
+static struct device_attribute touchscreen_attributes[] = {
+       __ATTR_RO(path),
+       __ATTR_RO(vendor),
+       __ATTR_NULL
+};
+
+#define TSDEV_MINOR_BASE 128
+#define TSDEV_MINOR_MAX 32
+
+/*******************************************************
+Description:
+       Novatek touchscreen FW function class. file node
+       initial function.
+
+return:
+       Executive outcomes. 0---succeed. -1---failed.
+*******************************************************/
+int32_t nvt_fw_class_init(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);
+               NVT_LOG("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, NVT_I2C_NAME);
+               if (IS_ERR(ts_class_dev)) {
+                       error = PTR_ERR(ts_class_dev);
+                       ts_class_dev = NULL;
+                       return error;
+               }
+
+               for (i = 0; attrs[i].attr.name != NULL; ++i) {
+                       error = device_create_file(ts_class_dev, &attrs[i]);
+                       if (error)
+                               break;
+               }
+
+               if (error)
+                       goto device_destroy;
+               else
+                       NVT_LOG("create /sys/class/touchscreen/%s Succeeded!\n", NVT_I2C_NAME);
+       } 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);
+       NVT_ERR("error creating touchscreen class\n");
+
+       return -ENODEV;
+}
+
+int nvt_fw_sysfs_init(void)
+{
+       int ret;
+       struct i2c_client *client = ts->client;
+
+       ret = nvt_fw_class_init(true);
+       if (ret != 0) {
+               NVT_ERR("fw class init failed. ret=%d\n", ret);
+               return ret;
+       }
+
+       ret = device_create_file(&client->dev, &dev_attr_forcereflash);
+       if (ret) {
+               NVT_ERR("create_file dev_attr_forcereflash failed\n");
+               return ret;
+       }
+
+       ret = device_create_file(&client->dev, &dev_attr_flashprog);
+       if (ret) {
+               NVT_ERR("create_file dev_attr_flashprog failed\n");
+               return ret;
+       }
+       ret = device_create_file(&client->dev, &dev_attr_doreflash);
+       if (ret) {
+               NVT_ERR("create_file dev_attr_doreflash failed\n");
+               return ret;
+       }
+
+       ret = device_create_file(&client->dev, &dev_attr_buildid);
+       if (ret) {
+               NVT_ERR("create_file dev_attr_buildid failed\n");
+               return ret;
+       }
+
+       ret = device_create_file(&client->dev, &dev_attr_productinfo);
+       if (ret) {
+               NVT_ERR("create_file dev_attr_productinfo failed\n");
+               return ret;
+       }
+
+       ret = device_create_file(&client->dev, &dev_attr_poweron);
+       if (ret) {
+               NVT_ERR("create_file dev_attr_poweron failed\n");
+               return ret;
+       }
+
+       ret = device_create_file(&client->dev, &dev_attr_ic_ver);
+       if (ret) {
+               NVT_ERR("create_file dev_attr_ic_ver failed\n");
+               return ret;
+       }
+
+       return 0;
+}
+void nvt_fw_sysfs_deinit(void)
+{
+       struct i2c_client *client = ts->client;
+       device_remove_file(&client->dev, &dev_attr_forcereflash);
+       device_remove_file(&client->dev, &dev_attr_flashprog);
+       device_remove_file(&client->dev, &dev_attr_doreflash);
+       device_remove_file(&client->dev, &dev_attr_buildid);
+       device_remove_file(&client->dev, &dev_attr_productinfo);
+       device_remove_file(&client->dev, &dev_attr_poweron);
+       device_remove_file(&client->dev, &dev_attr_ic_ver);
+       nvt_fw_class_init(false);
+}
+#endif
diff --git a/drivers/input/touchscreen/nt36xxx/nt36xxx_mem_map.h b/drivers/input/touchscreen/nt36xxx/nt36xxx_mem_map.h
new file mode 100755 (executable)
index 0000000..723c673
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2010 - 2017 Novatek, Inc.
+ *
+ * $Revision: 22971 $
+ * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+struct nvt_ts_mem_map {
+       uint32_t EVENT_BUF_ADDR;
+       uint32_t RAW_PIPE0_ADDR;
+       uint32_t RAW_PIPE0_Q_ADDR;
+       uint32_t RAW_PIPE1_ADDR;
+       uint32_t RAW_PIPE1_Q_ADDR;
+       uint32_t BASELINE_ADDR;
+       uint32_t BASELINE_Q_ADDR;
+       uint32_t BASELINE_BTN_ADDR;
+       uint32_t BASELINE_BTN_Q_ADDR;
+       uint32_t DIFF_PIPE0_ADDR;
+       uint32_t DIFF_PIPE0_Q_ADDR;
+       uint32_t DIFF_PIPE1_ADDR;
+       uint32_t DIFF_PIPE1_Q_ADDR;
+       uint32_t RAW_BTN_PIPE0_ADDR;
+       uint32_t RAW_BTN_PIPE0_Q_ADDR;
+       uint32_t RAW_BTN_PIPE1_ADDR;
+       uint32_t RAW_BTN_PIPE1_Q_ADDR;
+       uint32_t DIFF_BTN_PIPE0_ADDR;
+       uint32_t DIFF_BTN_PIPE0_Q_ADDR;
+       uint32_t DIFF_BTN_PIPE1_ADDR;
+       uint32_t DIFF_BTN_PIPE1_Q_ADDR;
+       uint32_t READ_FLASH_CHECKSUM_ADDR;
+       uint32_t RW_FLASH_DATA_ADDR;
+};
+
+static const struct nvt_ts_mem_map NT36672A_memory_map = {
+       .EVENT_BUF_ADDR           = 0x21C00,
+       .RAW_PIPE0_ADDR           = 0x20000,
+       .RAW_PIPE0_Q_ADDR         = 0,
+       .RAW_PIPE1_ADDR           = 0x23000,
+       .RAW_PIPE1_Q_ADDR         = 0,
+       .BASELINE_ADDR            = 0x20BFC,
+       .BASELINE_Q_ADDR          = 0,
+       .BASELINE_BTN_ADDR        = 0x23BFC,
+       .BASELINE_BTN_Q_ADDR      = 0,
+       .DIFF_PIPE0_ADDR          = 0x206DC,
+       .DIFF_PIPE0_Q_ADDR        = 0,
+       .DIFF_PIPE1_ADDR          = 0x236DC,
+       .DIFF_PIPE1_Q_ADDR        = 0,
+       .RAW_BTN_PIPE0_ADDR       = 0x20510,
+       .RAW_BTN_PIPE0_Q_ADDR     = 0,
+       .RAW_BTN_PIPE1_ADDR       = 0x23510,
+       .RAW_BTN_PIPE1_Q_ADDR     = 0,
+       .DIFF_BTN_PIPE0_ADDR      = 0x20BF0,
+       .DIFF_BTN_PIPE0_Q_ADDR    = 0,
+       .DIFF_BTN_PIPE1_ADDR      = 0x23BF0,
+       .DIFF_BTN_PIPE1_Q_ADDR    = 0,
+       .READ_FLASH_CHECKSUM_ADDR = 0x24000,
+       .RW_FLASH_DATA_ADDR       = 0x24002,
+};
+
+static const struct nvt_ts_mem_map NT36772_memory_map = {
+       .EVENT_BUF_ADDR           = 0x11E00,
+       .RAW_PIPE0_ADDR           = 0x10000,
+       .RAW_PIPE0_Q_ADDR         = 0,
+       .RAW_PIPE1_ADDR           = 0x12000,
+       .RAW_PIPE1_Q_ADDR         = 0,
+       .BASELINE_ADDR            = 0x10E70,
+       .BASELINE_Q_ADDR          = 0,
+       .BASELINE_BTN_ADDR        = 0x12E70,
+       .BASELINE_BTN_Q_ADDR      = 0,
+       .DIFF_PIPE0_ADDR          = 0x10830,
+       .DIFF_PIPE0_Q_ADDR        = 0,
+       .DIFF_PIPE1_ADDR          = 0x12830,
+       .DIFF_PIPE1_Q_ADDR        = 0,
+       .RAW_BTN_PIPE0_ADDR       = 0x10E60,
+       .RAW_BTN_PIPE0_Q_ADDR     = 0,
+       .RAW_BTN_PIPE1_ADDR       = 0x12E60,
+       .RAW_BTN_PIPE1_Q_ADDR     = 0,
+       .DIFF_BTN_PIPE0_ADDR      = 0x10E68,
+       .DIFF_BTN_PIPE0_Q_ADDR    = 0,
+       .DIFF_BTN_PIPE1_ADDR      = 0x12E68,
+       .DIFF_BTN_PIPE1_Q_ADDR    = 0,
+       .READ_FLASH_CHECKSUM_ADDR = 0x14000,
+       .RW_FLASH_DATA_ADDR       = 0x14002,
+};
+
+static const struct nvt_ts_mem_map NT36525_memory_map = {
+       .EVENT_BUF_ADDR           = 0x11A00,
+       .RAW_PIPE0_ADDR           = 0x10000,
+       .RAW_PIPE0_Q_ADDR         = 0,
+       .RAW_PIPE1_ADDR           = 0x12000,
+       .RAW_PIPE1_Q_ADDR         = 0,
+       .BASELINE_ADDR            = 0x10B08,
+       .BASELINE_Q_ADDR          = 0,
+       .BASELINE_BTN_ADDR        = 0x12B08,
+       .BASELINE_BTN_Q_ADDR      = 0,
+       .DIFF_PIPE0_ADDR          = 0x1064C,
+       .DIFF_PIPE0_Q_ADDR        = 0,
+       .DIFF_PIPE1_ADDR          = 0x1264C,
+       .DIFF_PIPE1_Q_ADDR        = 0,
+       .RAW_BTN_PIPE0_ADDR       = 0x10634,
+       .RAW_BTN_PIPE0_Q_ADDR     = 0,
+       .RAW_BTN_PIPE1_ADDR       = 0x12634,
+       .RAW_BTN_PIPE1_Q_ADDR     = 0,
+       .DIFF_BTN_PIPE0_ADDR      = 0x10AFC,
+       .DIFF_BTN_PIPE0_Q_ADDR    = 0,
+       .DIFF_BTN_PIPE1_ADDR      = 0x12AFC,
+       .DIFF_BTN_PIPE1_Q_ADDR    = 0,
+       .READ_FLASH_CHECKSUM_ADDR = 0x14000,
+       .RW_FLASH_DATA_ADDR       = 0x14002,
+};
+
+static const struct nvt_ts_mem_map NT36870_memory_map = {
+       .EVENT_BUF_ADDR           = 0x25000,
+       .RAW_PIPE0_ADDR           = 0x20000,
+       .RAW_PIPE0_Q_ADDR         = 0x204C8,
+       .RAW_PIPE1_ADDR           = 0x23000,
+       .RAW_PIPE1_Q_ADDR         = 0x234C8,
+       .BASELINE_ADDR            = 0x21350,
+       .BASELINE_Q_ADDR          = 0x21818,
+       .BASELINE_BTN_ADDR        = 0x24350,
+       .BASELINE_BTN_Q_ADDR      = 0x24358,
+       .DIFF_PIPE0_ADDR          = 0x209B0,
+       .DIFF_PIPE0_Q_ADDR        = 0x20E78,
+       .DIFF_PIPE1_ADDR          = 0x239B0,
+       .DIFF_PIPE1_Q_ADDR        = 0x23E78,
+       .RAW_BTN_PIPE0_ADDR       = 0x20990,
+       .RAW_BTN_PIPE0_Q_ADDR     = 0x20998,
+       .RAW_BTN_PIPE1_ADDR       = 0x23990,
+       .RAW_BTN_PIPE1_Q_ADDR     = 0x23998,
+       .DIFF_BTN_PIPE0_ADDR      = 0x21340,
+       .DIFF_BTN_PIPE0_Q_ADDR    = 0x21348,
+       .DIFF_BTN_PIPE1_ADDR      = 0x24340,
+       .DIFF_BTN_PIPE1_Q_ADDR    = 0x24348,
+       .READ_FLASH_CHECKSUM_ADDR = 0x24000,
+       .RW_FLASH_DATA_ADDR       = 0x24002,
+};
+
+static const struct nvt_ts_mem_map NT36676F_memory_map = {
+       .EVENT_BUF_ADDR           = 0x11A00,
+       .RAW_PIPE0_ADDR           = 0x10000,
+       .RAW_PIPE0_Q_ADDR         = 0,
+       .RAW_PIPE1_ADDR           = 0x12000,
+       .RAW_PIPE1_Q_ADDR         = 0,
+       .BASELINE_ADDR            = 0x10B08,
+       .BASELINE_Q_ADDR          = 0,
+       .BASELINE_BTN_ADDR        = 0x12B08,
+       .BASELINE_BTN_Q_ADDR      = 0,
+       .DIFF_PIPE0_ADDR          = 0x1064C,
+       .DIFF_PIPE0_Q_ADDR        = 0,
+       .DIFF_PIPE1_ADDR          = 0x1264C,
+       .DIFF_PIPE1_Q_ADDR        = 0,
+       .RAW_BTN_PIPE0_ADDR       = 0x10634,
+       .RAW_BTN_PIPE0_Q_ADDR     = 0,
+       .RAW_BTN_PIPE1_ADDR       = 0x12634,
+       .RAW_BTN_PIPE1_Q_ADDR     = 0,
+       .DIFF_BTN_PIPE0_ADDR      = 0x10AFC,
+       .DIFF_BTN_PIPE0_Q_ADDR    = 0,
+       .DIFF_BTN_PIPE1_ADDR      = 0x12AFC,
+       .DIFF_BTN_PIPE1_Q_ADDR    = 0,
+       .READ_FLASH_CHECKSUM_ADDR = 0x14000,
+       .RW_FLASH_DATA_ADDR       = 0x14002,
+};
+
+#define NVT_ID_BYTE_MAX 6
+struct nvt_ts_trim_id_table {
+       uint8_t id[NVT_ID_BYTE_MAX];
+       uint8_t mask[NVT_ID_BYTE_MAX];
+       const struct nvt_ts_mem_map *mmap;
+       uint8_t carrier_system;
+};
+
+static const struct nvt_ts_trim_id_table trim_id_table[] = {
+       {.id = {0x0A, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {1, 0, 0, 1, 1, 1},
+               .mmap = &NT36672A_memory_map, .carrier_system = 0},
+       {.id = {0x55, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
+               .mmap = &NT36772_memory_map, .carrier_system = 0},
+       {.id = {0x55, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
+               .mmap = &NT36772_memory_map, .carrier_system = 0},
+       {.id = {0xAA, 0x00, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
+               .mmap = &NT36772_memory_map, .carrier_system = 0},
+       {.id = {0xAA, 0x72, 0xFF, 0x00, 0x00, 0x00}, .mask = {1, 1, 0, 1, 1, 1},
+               .mmap = &NT36772_memory_map, .carrier_system = 0},
+       {.id = {0xFF, 0xFF, 0xFF, 0x72, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
+               .mmap = &NT36772_memory_map, .carrier_system = 0},
+       {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
+               .mmap = &NT36772_memory_map, .carrier_system = 0},
+       {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x67, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
+               .mmap = &NT36772_memory_map, .carrier_system = 0},
+       {.id = {0xFF, 0xFF, 0xFF, 0x72, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
+               .mmap = &NT36772_memory_map, .carrier_system = 0},
+       {.id = {0xFF, 0xFF, 0xFF, 0x25, 0x65, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
+               .mmap = &NT36525_memory_map, .carrier_system = 0},
+       {.id = {0xFF, 0xFF, 0xFF, 0x70, 0x68, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
+               .mmap = &NT36870_memory_map, .carrier_system = 1},
+       {.id = {0xFF, 0xFF, 0xFF, 0x76, 0x66, 0x03}, .mask = {0, 0, 0, 1, 1, 1},
+               .mmap = &NT36676F_memory_map, .carrier_system = 0}
+};
diff --git a/drivers/input/touchscreen/nt36xxx/nt36xxx_mp_ctrlram.c b/drivers/input/touchscreen/nt36xxx/nt36xxx_mp_ctrlram.c
new file mode 100755 (executable)
index 0000000..ef5174d
--- /dev/null
@@ -0,0 +1,1903 @@
+/*
+ * Copyright (C) 2010 - 2017 Novatek, Inc.
+ *
+ * $Revision: 23067 $
+ * $Date: 2018-02-09 11:39:27 +0800 (ι€±δΊ”, 09 δΊŒζœˆ 2018) $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+
+#include "nt36xxx.h"
+#include "nt36xxx_mp_ctrlram.h"
+
+#if NVT_TOUCH_MP
+
+#define NORMAL_MODE 0x00
+#define TEST_MODE_1 0x21
+#define TEST_MODE_2 0x22
+#define MP_MODE_CC 0x41
+#define FREQ_HOP_DISABLE 0x66
+#define FREQ_HOP_ENABLE 0x65
+
+#define SHORT_TEST_CSV_FILE "/data/local/tmp/ShortTest.csv"
+#define OPEN_TEST_CSV_FILE "/data/local/tmp/OpenTest.csv"
+#define FW_RAWDATA_CSV_FILE "/data/local/tmp/FWMutualTest.csv"
+#define FW_CC_CSV_FILE "/data/local/tmp/FWCCTest.csv"
+#define NOISE_TEST_CSV_FILE "/data/local/tmp/NoiseTest.csv"
+
+#define nvt_mp_seq_printf(m, fmt, args...) do {        \
+       seq_printf(m, fmt, ##args);     \
+       if (!nvt_mp_test_result_printed)        \
+               printk(fmt, ##args);    \
+} while (0)
+
+static uint8_t *RecordResult_Short = NULL;
+static uint8_t *RecordResult_Short_Diff = NULL;
+static uint8_t *RecordResult_Short_Base = NULL;
+static uint8_t *RecordResult_Open = NULL;
+static uint8_t *RecordResult_FWMutual = NULL;
+static uint8_t *RecordResult_FW_CC = NULL;
+static uint8_t *RecordResult_FW_CC_I = NULL;
+static uint8_t *RecordResult_FW_CC_Q = NULL;
+static uint8_t *RecordResult_FW_DiffMax = NULL;
+static uint8_t *RecordResult_FW_DiffMin = NULL;
+
+static int32_t TestResult_Short = 0;
+static int32_t TestResult_Short_Diff = 0;
+static int32_t TestResult_Short_Base = 0;
+static int32_t TestResult_Open = 0;
+static int32_t TestResult_FW_Rawdata = 0;
+static int32_t TestResult_FWMutual = 0;
+static int32_t TestResult_FW_CC = 0;
+static int32_t TestResult_FW_CC_I = 0;
+static int32_t TestResult_FW_CC_Q = 0;
+static int32_t TestResult_Noise = 0;
+static int32_t TestResult_FW_DiffMax = 0;
+static int32_t TestResult_FW_DiffMin = 0;
+
+static int32_t *RawData_Short = NULL;
+static int32_t *RawData_Short_Diff = NULL;
+static int32_t *RawData_Short_Base = NULL;
+static int32_t *RawData_Open = NULL;
+static int32_t *RawData_Diff = NULL;
+static int32_t *RawData_Diff_Min = NULL;
+static int32_t *RawData_Diff_Max = NULL;
+static int32_t *RawData_FWMutual = NULL;
+static int32_t *RawData_FW_CC = NULL;
+static int32_t *RawData_FW_CC_I = NULL;
+static int32_t *RawData_FW_CC_Q = NULL;
+
+static struct proc_dir_entry *NVT_proc_selftest_entry = NULL;
+#if NVT_TOUCH_MP_LENOVO
+static struct proc_dir_entry *NVT_proc_selftest_read_data = NULL;
+#endif
+static int8_t nvt_mp_test_result_printed = 0;
+
+extern void nvt_change_mode(uint8_t mode);
+extern uint8_t nvt_get_fw_pipe(void);
+extern void nvt_read_mdata(uint32_t xdata_addr, uint32_t xdata_btn_addr);
+extern void nvt_get_mdata(int32_t *buf, uint8_t *m_x_num, uint8_t *m_y_num);
+void nvt_mp_parse_dt(struct device_node *root, const char *node_compatible);
+extern int32_t nvt_read_mass_data(uint32_t xdata_addr, uint8_t *temp_buf, uint32_t len);
+
+/*******************************************************
+Description:
+       Novatek touchscreen allocate buffer for mp selftest.
+
+return:
+       Executive outcomes. 0---succeed. -12---Out of memory
+*******************************************************/
+static int nvt_mp_buffer_init(void)
+{
+       size_t RecordResult_BufSize = IC_X_CFG_SIZE * IC_Y_CFG_SIZE + IC_KEY_CFG_SIZE;
+       size_t RawData_BufSize = (IC_X_CFG_SIZE * IC_Y_CFG_SIZE + IC_KEY_CFG_SIZE) * sizeof(int32_t);
+
+       RecordResult_Short = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
+       if (!RecordResult_Short) {
+               NVT_ERR("kzalloc for RecordResult_Short failed!\n");
+               return -ENOMEM;
+       }
+
+       RecordResult_Short_Diff = RecordResult_Short;
+
+       RecordResult_Short_Base = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
+       if (!RecordResult_Short_Base) {
+               NVT_ERR("kzalloc for RecordResult_Short_Base failed!\n");
+               return -ENOMEM;
+       }
+
+       RecordResult_Open = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
+       if (!RecordResult_Open) {
+               NVT_ERR("kzalloc for RecordResult_Open failed!\n");
+               return -ENOMEM;
+       }
+
+       RecordResult_FWMutual = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
+       if (!RecordResult_FWMutual) {
+               NVT_ERR("kzalloc for RecordResult_FWMutual failed!\n");
+               return -ENOMEM;
+       }
+
+       RecordResult_FW_CC = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
+       if (!RecordResult_FW_CC) {
+               NVT_ERR("kzalloc for RecordResult_FW_CC failed!\n");
+               return -ENOMEM;
+       }
+
+       RecordResult_FW_CC_I = RecordResult_FW_CC;
+
+       RecordResult_FW_CC_Q = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
+       if (!RecordResult_FW_CC_Q) {
+               NVT_ERR("kzalloc for RecordResult_FW_CC_Q failed!\n");
+               return -ENOMEM;
+       }
+
+       RecordResult_FW_DiffMax = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
+       if (!RecordResult_FW_DiffMax) {
+               NVT_ERR("kzalloc for RecordResult_FW_DiffMax failed!\n");
+               return -ENOMEM;
+       }
+
+       RecordResult_FW_DiffMin = (uint8_t *)kzalloc(RecordResult_BufSize, GFP_KERNEL);
+       if (!RecordResult_FW_DiffMin) {
+               NVT_ERR("kzalloc for RecordResult_FW_DiffMin failed!\n");
+               return -ENOMEM;
+       }
+
+       RawData_Short = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
+       if (!RawData_Short) {
+               NVT_ERR("kzalloc for RawData_Short failed!\n");
+               return -ENOMEM;
+       }
+
+       RawData_Short_Diff = RawData_Short;
+
+       RawData_Short_Base = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
+       if (!RawData_Short_Base) {
+               NVT_ERR("kzalloc for RawData_Short_Base failed!\n");
+               return -ENOMEM;
+       }
+
+       RawData_Open = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
+       if (!RawData_Open) {
+               NVT_ERR("kzalloc for RawData_Open failed!\n");
+               return -ENOMEM;
+       }
+
+       RawData_Diff = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
+       if (!RawData_Diff) {
+               NVT_ERR("kzalloc for RawData_Diff failed!\n");
+               return -ENOMEM;
+       }
+
+       RawData_Diff_Min = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
+       if (!RawData_Diff_Min) {
+               NVT_ERR("kzalloc for RawData_Diff_Min failed!\n");
+               return -ENOMEM;
+       }
+
+       RawData_Diff_Max = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
+       if (!RawData_Diff_Max) {
+               NVT_ERR("kzalloc for RawData_Diff_Max failed!\n");
+               return -ENOMEM;
+       }
+
+       RawData_FWMutual = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
+       if (!RawData_FWMutual) {
+               NVT_ERR("kzalloc for RawData_FWMutual failed!\n");
+               return -ENOMEM;
+       }
+
+       RawData_FW_CC = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
+       if (!RawData_FW_CC) {
+               NVT_ERR("kzalloc for RawData_FW_CC failed!\n");
+               return -ENOMEM;
+       }
+
+       RawData_FW_CC_I = RawData_FW_CC;
+
+       RawData_FW_CC_Q = (int32_t *)kzalloc(RawData_BufSize, GFP_KERNEL);
+       if (!RawData_FW_CC_Q) {
+               NVT_ERR("kzalloc for RawData_FW_CC_Q failed!\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen self-test criteria print function.
+
+return:
+       n.a.
+*******************************************************/
+static void nvt_print_lmt_array(int32_t *array, int32_t x_ch, int32_t y_ch)
+{
+       int32_t i = 0;
+       int32_t j = 0;
+#if TOUCH_KEY_NUM > 0
+       int32_t k = 0;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       for (j = 0; j < y_ch; j++) {
+               for(i = 0; i < x_ch; i++) {
+                       printk("%5d, ", array[j * x_ch + i]);
+               }
+               printk("\n");
+       }
+#if TOUCH_KEY_NUM > 0
+       for (k = 0; k < Key_Channel; k++) {
+               printk("%5d, ", array[y_ch * x_ch + k]);
+       }
+       printk("\n");
+#endif /* #if TOUCH_KEY_NUM > 0 */
+}
+
+static void nvt_print_criteria(void)
+{
+       NVT_LOG("++\n");
+
+       if (ts->carrier_system) {
+               //---PS_Config_Lmt_Short_Diff---
+               printk("PS_Config_Lmt_Short_Diff_P:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_Short_Diff_P, X_Channel, Y_Channel);
+               printk("PS_Config_Lmt_Short_Diff_N:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_Short_Diff_N, X_Channel, Y_Channel);
+               //---PS_Config_Lmt_Short_Base---
+               printk("PS_Config_Lmt_Short_Base_P:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_Short_Base_P, X_Channel, Y_Channel);
+               printk("PS_Config_Lmt_Short_Base_N:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_Short_Base_N, X_Channel, Y_Channel);
+       } else {
+               //---PS_Config_Lmt_Short_Rawdata---
+               printk("PS_Config_Lmt_Short_Rawdata_P:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_Short_Rawdata_P, X_Channel, Y_Channel);
+               printk("PS_Config_Lmt_Short_Rawdata_N:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_Short_Rawdata_N, X_Channel, Y_Channel);
+       }
+
+       //---PS_Config_Lmt_Open_Rawdata---
+       printk("PS_Config_Lmt_Open_Rawdata_P:\n");
+       nvt_print_lmt_array(PS_Config_Lmt_Open_Rawdata_P, X_Channel, Y_Channel);
+       printk("PS_Config_Lmt_Open_Rawdata_N:\n");
+       nvt_print_lmt_array(PS_Config_Lmt_Open_Rawdata_N, X_Channel, Y_Channel);
+
+       //---PS_Config_Lmt_FW_Rawdata---
+       printk("PS_Config_Lmt_FW_Rawdata_P:\n");
+       nvt_print_lmt_array(PS_Config_Lmt_FW_Rawdata_P, X_Channel, Y_Channel);
+       printk("PS_Config_Lmt_FW_Rawdata_N:\n");
+       nvt_print_lmt_array(PS_Config_Lmt_FW_Rawdata_N, X_Channel, Y_Channel);
+
+       if (ts->carrier_system) {
+               //---PS_Config_Lmt_FW_CC_I---
+               printk("PS_Config_Lmt_FW_CC_I_P:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_I_P, X_Channel, Y_Channel);
+               printk("PS_Config_Lmt_FW_CC_I_N:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_I_N, X_Channel, Y_Channel);
+               //---PS_Config_Lmt_FW_CC_Q---
+               printk("PS_Config_Lmt_FW_CC_Q_P:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_Q_P, X_Channel, Y_Channel);
+               printk("PS_Config_Lmt_FW_CC_Q_N:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_Q_N, X_Channel, Y_Channel);
+       } else {
+               //---PS_Config_Lmt_FW_CC---
+               printk("PS_Config_Lmt_FW_CC_P:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_P, X_Channel, Y_Channel);
+               printk("PS_Config_Lmt_FW_CC_N:\n");
+               nvt_print_lmt_array(PS_Config_Lmt_FW_CC_N, X_Channel, Y_Channel);
+       }
+
+       //---PS_Config_Lmt_FW_Diff---
+       printk("PS_Config_Lmt_FW_Diff_P:\n");
+       nvt_print_lmt_array(PS_Config_Lmt_FW_Diff_P, X_Channel, Y_Channel);
+       printk("PS_Config_Lmt_FW_Diff_N:\n");
+       nvt_print_lmt_array(PS_Config_Lmt_FW_Diff_N, X_Channel, Y_Channel);
+
+       NVT_LOG("--\n");
+}
+
+static int32_t nvt_save_rawdata_to_csv(int32_t *rawdata, uint8_t x_ch, uint8_t y_ch, const char *file_path, uint32_t offset)
+{
+       int32_t x = 0;
+       int32_t y = 0;
+       int32_t iArrayIndex = 0;
+#if TOUCH_KEY_NUM > 0
+       int32_t k = 0;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       printk("%s:++%s\n", __func__, file_path);
+
+       for (y = 0; y < y_ch; y++) {
+               for (x = 0; x < x_ch; x++) {
+                       iArrayIndex = y * x_ch + x;
+                       printk("%5d, ", rawdata[iArrayIndex]);
+               }
+               printk("\n");
+       }
+#if TOUCH_KEY_NUM > 0
+       for (k = 0; k < Key_Channel; k++) {
+               iArrayIndex = y_ch * x_ch + k;
+               printk("%5d, ", rawdata[iArrayIndex]);
+       }
+       printk("\n");
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       printk("%s:--\n", __func__);
+
+       return 0;
+}
+
+static int32_t nvt_polling_hand_shake_status(void)
+{
+       uint8_t buf[8] = {0};
+       int32_t i = 0;
+       const int32_t retry = 50;
+
+       for (i = 0; i < retry; i++) {
+               //---set xdata index to EVENT BUF ADDR---
+               buf[0] = 0xFF;
+               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+               //---read fw status---
+               buf[0] = EVENT_MAP_HANDSHAKING_or_SUB_CMD_BYTE;
+               buf[1] = 0x00;
+               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
+
+               if ((buf[1] == 0xA0) || (buf[1] == 0xA1))
+                       break;
+
+               msleep(10);
+       }
+
+       if (i >= retry) {
+               NVT_ERR("polling hand shake status failed, buf[1]=0x%02X\n", buf[1]);
+
+               // Read back 5 bytes from offset EVENT_MAP_HOST_CMD for debug check
+               buf[0] = 0xFF;
+               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+               buf[0] = EVENT_MAP_HOST_CMD;
+               buf[1] = 0x00;
+               buf[2] = 0x00;
+               buf[3] = 0x00;
+               buf[4] = 0x00;
+               buf[5] = 0x00;
+               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 6);
+               NVT_ERR("Read back 5 bytes from offset EVENT_MAP_HOST_CMD: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n", buf[1], buf[2], buf[3], buf[4], buf[5]);
+
+               return -1;
+       } else {
+               return 0;
+       }
+}
+
+static int8_t nvt_switch_FreqHopEnDis(uint8_t FreqHopEnDis)
+{
+       uint8_t buf[8] = {0};
+       uint8_t retry = 0;
+       int8_t ret = 0;
+
+       NVT_LOG("++\n");
+
+       for (retry = 0; retry < 20; retry++) {
+               //---set xdata index to EVENT BUF ADDR---
+               buf[0] = 0xFF;
+               buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+               buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+               //---switch FreqHopEnDis---
+               buf[0] = EVENT_MAP_HOST_CMD;
+               buf[1] = FreqHopEnDis;
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 2);
+
+               msleep(35);
+
+               buf[0] = EVENT_MAP_HOST_CMD;
+               buf[1] = 0xFF;
+               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, 2);
+
+               if (buf[1] == 0x00)
+                       break;
+       }
+
+       if (unlikely(retry == 20)) {
+               NVT_ERR("switch FreqHopEnDis 0x%02X failed, buf[1]=0x%02X\n", FreqHopEnDis, buf[1]);
+               ret = -1;
+       }
+
+       NVT_LOG("--\n");
+
+       return ret;
+}
+
+static int32_t nvt_read_baseline(int32_t *xdata)
+{
+       uint8_t x_num = 0;
+       uint8_t y_num = 0;
+       uint32_t x = 0;
+       uint32_t y = 0;
+       int32_t iArrayIndex = 0;
+#if TOUCH_KEY_NUM > 0
+       int32_t k = 0;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       NVT_LOG("++\n");
+
+       nvt_read_mdata(ts->mmap->BASELINE_ADDR, ts->mmap->BASELINE_BTN_ADDR);
+
+       nvt_get_mdata(xdata, &x_num, &y_num);
+
+       for (y = 0; y < y_num; y++) {
+               for (x = 0; x < x_num; x++) {
+                       iArrayIndex = y * x_num + x;
+                       if (ts->carrier_system) {
+                               xdata[iArrayIndex] = (uint16_t)xdata[iArrayIndex];
+                       } else {
+                               xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex];
+                       }
+               }
+       }
+#if TOUCH_KEY_NUM > 0
+       for (k = 0; k < Key_Channel; k++) {
+               iArrayIndex = Y_Channel * X_Channel + k;
+               if (ts->carrier_system) {
+                       xdata[iArrayIndex] = (uint16_t)xdata[iArrayIndex];
+               } else {
+                       xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex];
+               }
+       }
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       printk("%s:\n", __func__);
+       // Save Rawdata to CSV file
+       if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, FW_RAWDATA_CSV_FILE, 0) < 0) {
+               NVT_ERR("save rawdata to CSV file failed\n");
+               return -EAGAIN;
+       }
+
+       NVT_LOG("--\n");
+
+       return 0;
+}
+
+static int32_t nvt_read_CC(int32_t *xdata)
+{
+       uint8_t x_num = 0;
+       uint8_t y_num = 0;
+       uint32_t x = 0;
+       uint32_t y = 0;
+       int32_t iArrayIndex = 0;
+       int32_t xdata_tmp = 0;
+#if TOUCH_KEY_NUM > 0
+       int32_t k = 0;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+       uint32_t rawdata_cc_q_offset = 0;
+
+       NVT_LOG("++\n");
+
+       if (nvt_get_fw_pipe() == 0)
+               nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR);
+       else
+               nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR);
+
+       nvt_get_mdata(xdata, &x_num, &y_num);
+
+       for (y = 0; y < y_num; y++) {
+               for (x = 0; x < x_num; x++) {
+                       iArrayIndex = y * x_num + x;
+                       if (ts->carrier_system) {
+                               xdata_tmp = xdata[iArrayIndex];
+                               RawData_FW_CC_I[iArrayIndex] = (uint8_t)(xdata_tmp & 0xFF);
+                               RawData_FW_CC_Q[iArrayIndex] = (uint8_t)((xdata_tmp >> 8) & 0xFF);
+                       } else {
+                               xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex];
+                       }
+               }
+       }
+#if TOUCH_KEY_NUM > 0
+       for (k = 0; k < Key_Channel; k++) {
+               iArrayIndex = Y_Channel * X_Channel + k;
+               if (ts->carrier_system) {
+                       xdata_tmp = xdata[iArrayIndex];
+                       RawData_FW_CC_I[iArrayIndex] = (uint8_t)(xdata_tmp & 0xFF);
+                       RawData_FW_CC_Q[iArrayIndex] = (uint8_t)((xdata_tmp >> 8) & 0xFF);
+               } else {
+                       xdata[iArrayIndex] = (int16_t)xdata[iArrayIndex];
+               }
+       }
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       printk("%s:\n", __func__);
+       if (ts->carrier_system) {
+               printk("%s:RawData_CC_I:\n", __func__);
+               // Save Rawdata to CSV file
+               if (nvt_save_rawdata_to_csv(RawData_FW_CC_I, X_Channel, Y_Channel, FW_CC_CSV_FILE, 0) < 0) {
+                       NVT_ERR("save rawdata to CSV file failed\n");
+                       return -EAGAIN;
+               }
+#if TOUCH_KEY_NUM > 0
+               rawdata_cc_q_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2 + Key_Channel * 7 + 2;
+#else
+               rawdata_cc_q_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+               printk("%s:RawData_CC_Q:\n", __func__);
+               // Save Rawdata to CSV file
+               if (nvt_save_rawdata_to_csv(RawData_FW_CC_Q, X_Channel, Y_Channel, FW_CC_CSV_FILE, rawdata_cc_q_offset) < 0) {
+                       NVT_ERR("save rawdata to CSV file failed\n");
+                       return -EAGAIN;
+               }
+       } else {
+               // Save Rawdata to CSV file
+               if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, FW_CC_CSV_FILE, 0) < 0) {
+                       NVT_ERR("save rawdata to CSV file failed\n");
+                       return -EAGAIN;
+               }
+       }
+
+       NVT_LOG("--\n");
+
+       return 0;
+}
+
+static void nvt_enable_noise_collect(int32_t frame_num)
+{
+       uint8_t buf[8] = {0};
+
+       //---set xdata index to EVENT BUF ADDR---
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+       //---enable noise collect---
+       buf[0] = EVENT_MAP_HOST_CMD;
+       buf[1] = 0x47;
+       buf[2] = 0xAA;
+       buf[3] = frame_num;
+       buf[4] = 0x00;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 5);
+}
+
+static int32_t nvt_read_fw_noise(int32_t *xdata)
+{
+       uint8_t x_num = 0;
+       uint8_t y_num = 0;
+       uint32_t x = 0;
+       uint32_t y = 0;
+       int32_t iArrayIndex = 0;
+       int32_t frame_num = 0;
+       uint32_t rawdata_diff_min_offset = 0;
+#if TOUCH_KEY_NUM > 0
+       int32_t k = 0;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       NVT_LOG("++\n");
+
+       //---Enter Test Mode---
+       if (nvt_clear_fw_status()) {
+               return -EAGAIN;
+       }
+
+       frame_num = PS_Config_Diff_Test_Frame / 10;
+       if (frame_num <= 0)
+               frame_num = 1;
+       printk("%s: frame_num=%d\n", __func__, frame_num);
+       nvt_enable_noise_collect(frame_num);
+       // need wait PS_Config_Diff_Test_Frame * 8.3ms
+       msleep(frame_num * 83);
+
+       if (nvt_polling_hand_shake_status()) {
+               return -EAGAIN;
+       }
+
+       if (nvt_get_fw_info()) {
+               return -EAGAIN;
+       }
+
+       if (nvt_get_fw_pipe() == 0)
+               nvt_read_mdata(ts->mmap->DIFF_PIPE0_ADDR, ts->mmap->DIFF_BTN_PIPE0_ADDR);
+       else
+               nvt_read_mdata(ts->mmap->DIFF_PIPE1_ADDR, ts->mmap->DIFF_BTN_PIPE1_ADDR);
+
+       nvt_get_mdata(xdata, &x_num, &y_num);
+
+       for (y = 0; y < y_num; y++) {
+               for (x = 0; x < x_num; x++) {
+                       iArrayIndex = y * x_num + x;
+                       if (ts->carrier_system) {
+                               RawData_Diff_Max[iArrayIndex] = (uint16_t)xdata[iArrayIndex];
+                               RawData_Diff_Min[iArrayIndex] = 0;
+                       } else {
+                               RawData_Diff_Max[iArrayIndex] = (int8_t)((xdata[iArrayIndex] >> 8) & 0xFF);
+                               RawData_Diff_Min[iArrayIndex] = (int8_t)(xdata[iArrayIndex] & 0xFF);
+                       }
+               }
+       }
+#if TOUCH_KEY_NUM > 0
+       for (k = 0; k < Key_Channel; k++) {
+               iArrayIndex = Y_Channel * X_Channel + k;
+               if (ts->carrier_system) {
+                       RawData_Diff_Max[iArrayIndex] = (uint16_t)xdata[iArrayIndex];
+                       RawData_Diff_Min[iArrayIndex] = 0;
+               } else {
+                       RawData_Diff_Max[iArrayIndex] = (int8_t)((xdata[iArrayIndex] >> 8) & 0xFF);
+                       RawData_Diff_Min[iArrayIndex] = (int8_t)(xdata[iArrayIndex] & 0xFF);
+               }
+       }
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       //---Leave Test Mode---
+       nvt_change_mode(NORMAL_MODE);
+
+       printk("%s:RawData_Diff_Max:\n", __func__);
+       // Save Rawdata to CSV file
+       if (nvt_save_rawdata_to_csv(RawData_Diff_Max, X_Channel, Y_Channel, NOISE_TEST_CSV_FILE, 0) < 0) {
+               NVT_ERR("save rawdata to CSV file failed\n");
+               return -EAGAIN;
+       }
+
+       if (!ts->carrier_system) {
+#if TOUCH_KEY_NUM > 0
+               rawdata_diff_min_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2 + Key_Channel * 7 + 2;
+#else
+               rawdata_diff_min_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+               printk("%s:RawData_Diff_Min:\n", __func__);
+               // Save Rawdata to CSV file
+               if (nvt_save_rawdata_to_csv(RawData_Diff_Min, X_Channel, Y_Channel, NOISE_TEST_CSV_FILE, rawdata_diff_min_offset) < 0) {
+                       NVT_ERR("save rawdata to CSV file failed\n");
+                       return -EAGAIN;
+               }
+       }
+
+       NVT_LOG("--\n");
+
+       return 0;
+}
+
+static void nvt_enable_open_test(void)
+{
+       uint8_t buf[8] = {0};
+
+       //---set xdata index to EVENT BUF ADDR---
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+       //---enable open test---
+       buf[0] = EVENT_MAP_HOST_CMD;
+       buf[1] = 0x45;
+       buf[2] = 0xAA;
+       buf[3] = 0x02;
+       buf[4] = 0x00;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 5);
+}
+
+static void nvt_enable_short_test(void)
+{
+       uint8_t buf[8] = {0};
+
+       //---set xdata index to EVENT BUF ADDR---
+       buf[0] = 0xFF;
+       buf[1] = (ts->mmap->EVENT_BUF_ADDR >> 16) & 0xFF;
+       buf[2] = (ts->mmap->EVENT_BUF_ADDR >> 8) & 0xFF;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+
+       //---enable short test---
+       buf[0] = EVENT_MAP_HOST_CMD;
+       buf[1] = 0x43;
+       buf[2] = 0xAA;
+       buf[3] = 0x02;
+       buf[4] = 0x00;
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 5);
+}
+
+static int32_t nvt_read_fw_open(int32_t *xdata)
+{
+       uint32_t raw_pipe_addr = 0;
+       uint8_t *rawdata_buf = NULL;
+       uint32_t x = 0;
+       uint32_t y = 0;
+       uint8_t buf[128] = {0};
+#if TOUCH_KEY_NUM > 0
+       uint32_t raw_btn_pipe_addr = 0;
+       int32_t k = 0;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       NVT_LOG("++\n");
+
+       //---Enter Test Mode---
+       if (nvt_clear_fw_status()) {
+               return -EAGAIN;
+       }
+
+       nvt_enable_open_test();
+
+       if (nvt_polling_hand_shake_status()) {
+               return -EAGAIN;
+       }
+
+#if TOUCH_KEY_NUM > 0
+       rawdata_buf = (uint8_t *)kzalloc((IC_X_CFG_SIZE * IC_Y_CFG_SIZE + IC_KEY_CFG_SIZE) * 2, GFP_KERNEL);
+#else
+       rawdata_buf = (uint8_t *)kzalloc(IC_X_CFG_SIZE * IC_Y_CFG_SIZE * 2, GFP_KERNEL);
+#endif /* #if TOUCH_KEY_NUM > 0 */
+       if (!rawdata_buf) {
+               NVT_ERR("kzalloc for rawdata_buf failed!\n");
+               return -ENOMEM;
+       }
+
+       if (nvt_get_fw_pipe() == 0)
+               raw_pipe_addr = ts->mmap->RAW_PIPE0_ADDR;
+       else
+               raw_pipe_addr = ts->mmap->RAW_PIPE1_ADDR;
+
+       for (y = 0; y < IC_Y_CFG_SIZE; y++) {
+               //---change xdata index---
+               buf[0] = 0xFF;
+               buf[1] = (uint8_t)(((raw_pipe_addr + y * IC_X_CFG_SIZE * 2) >> 16) & 0xFF);
+               buf[2] = (uint8_t)(((raw_pipe_addr + y * IC_X_CFG_SIZE * 2) >> 8) & 0xFF);
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+               buf[0] = (uint8_t)((raw_pipe_addr + y * IC_X_CFG_SIZE * 2) & 0xFF);
+               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, IC_X_CFG_SIZE * 2 + 1);
+               memcpy(rawdata_buf + y * IC_X_CFG_SIZE * 2, buf + 1, IC_X_CFG_SIZE * 2);
+       }
+#if TOUCH_KEY_NUM > 0
+       if (nvt_get_fw_pipe() == 0)
+               raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE0_ADDR;
+       else
+               raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE1_ADDR;
+
+       //---change xdata index---
+       buf[0] = 0xFF;
+       buf[1] = (uint8_t)((raw_btn_pipe_addr >> 16) & 0xFF);
+       buf[2] = (uint8_t)((raw_btn_pipe_addr >> 8) & 0xFF);
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+       buf[0] = (uint8_t)(raw_btn_pipe_addr & 0xFF);
+       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, IC_KEY_CFG_SIZE * 2 + 1);
+       memcpy(rawdata_buf + IC_Y_CFG_SIZE * IC_X_CFG_SIZE * 2, buf + 1, IC_KEY_CFG_SIZE * 2);
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       for (y = 0; y < IC_Y_CFG_SIZE; y++) {
+               for (x = 0; x < IC_X_CFG_SIZE; x++) {
+                       if ((AIN_Y[y] != 0xFF) && (AIN_X[x] != 0xFF)) {
+                               xdata[AIN_Y[y] * X_Channel + AIN_X[x]] = (int16_t)((rawdata_buf[(y * IC_X_CFG_SIZE + x) * 2] + 256 * rawdata_buf[(y * IC_X_CFG_SIZE + x) * 2 + 1]));
+                       }
+               }
+       }
+#if TOUCH_KEY_NUM > 0
+       for (k = 0; k < IC_KEY_CFG_SIZE; k++) {
+               if (AIN_KEY[k] != 0xFF)
+                       xdata[Y_Channel * X_Channel + AIN_KEY[k]] = (int16_t)(rawdata_buf[(IC_Y_CFG_SIZE * IC_X_CFG_SIZE + k) * 2] + 256 * rawdata_buf[(IC_Y_CFG_SIZE * IC_X_CFG_SIZE + k) * 2 + 1]);
+       }
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       if (rawdata_buf) {
+               kfree(rawdata_buf);
+               rawdata_buf = NULL;
+       }
+
+       //---Leave Test Mode---
+       nvt_change_mode(NORMAL_MODE);
+
+
+       printk("%s:RawData_Open\n", __func__);
+       // Save RawData to CSV file
+       if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, OPEN_TEST_CSV_FILE, 0) < 0) {
+               NVT_ERR("save rawdata to CSV file failed\n");
+               return -EAGAIN;
+       }
+
+       NVT_LOG("--\n");
+
+       return 0;
+}
+
+static int32_t nvt_read_fw_short(int32_t *xdata)
+{
+       uint32_t raw_pipe_addr = 0;
+       uint8_t *rawdata_buf = NULL;
+       uint32_t x = 0;
+       uint32_t y = 0;
+       uint8_t buf[128] = {0};
+       int32_t iArrayIndex = 0;
+#if TOUCH_KEY_NUM > 0
+       uint32_t raw_btn_pipe_addr = 0;
+       int32_t k = 0;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+       uint32_t rawdata_short_base_offset = 0;
+
+       NVT_LOG("++\n");
+
+       //---Enter Test Mode---
+       if (nvt_clear_fw_status()) {
+               return -EAGAIN;
+       }
+
+       nvt_enable_short_test();
+
+       if (nvt_polling_hand_shake_status()) {
+               return -EAGAIN;
+       }
+
+#if TOUCH_KEY_NUM > 0
+    rawdata_buf = (uint8_t *)kzalloc((X_Channel * Y_Channel + Key_Channel) * 2, GFP_KERNEL);
+#else
+    rawdata_buf = (uint8_t *)kzalloc(X_Channel * Y_Channel * 2, GFP_KERNEL);
+#endif /* #if TOUCH_KEY_NUM > 0 */
+       if (!rawdata_buf) {
+               NVT_ERR("kzalloc for rawdata_buf failed!\n");
+               return -ENOMEM;
+       }
+
+       if (ts->carrier_system) {
+               // to get short diff rawdata at pipe0
+               raw_pipe_addr = ts->mmap->RAW_PIPE0_ADDR;
+       } else {
+               if (nvt_get_fw_pipe() == 0)
+                       raw_pipe_addr = ts->mmap->RAW_PIPE0_ADDR;
+               else
+                       raw_pipe_addr = ts->mmap->RAW_PIPE1_ADDR;
+       }
+
+       for (y = 0; y < Y_Channel; y++) {
+               //---change xdata index---
+               buf[0] = 0xFF;
+               buf[1] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 16) & 0xFF);
+               buf[2] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 8) & 0xFF);
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+               buf[0] = (uint8_t)((raw_pipe_addr + y * X_Channel * 2) & 0xFF);
+               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, X_Channel * 2 + 1);
+               memcpy(rawdata_buf + y * X_Channel * 2, buf + 1, X_Channel * 2);
+       }
+#if TOUCH_KEY_NUM > 0
+       if (ts->carrier_system) {
+               // to get button short diff rawdata at pipe0
+               raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE0_ADDR;
+       } else {
+               if (nvt_get_fw_pipe() == 0)
+                       raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE0_ADDR;
+               else
+                       raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE1_ADDR;
+       }
+
+    //---change xdata index---
+       buf[0] = 0xFF;
+       buf[1] = (uint8_t)((raw_btn_pipe_addr >> 16) & 0xFF);
+       buf[2] = (uint8_t)((raw_btn_pipe_addr >> 8) & 0xFF);
+       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+       buf[0] = (uint8_t)(raw_btn_pipe_addr & 0xFF);
+       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, Key_Channel * 2 + 1);
+       memcpy(rawdata_buf + Y_Channel * X_Channel * 2, buf + 1, Key_Channel * 2);
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       for (y = 0; y < Y_Channel; y++) {
+               for (x = 0; x < X_Channel; x++) {
+                       iArrayIndex = y * X_Channel + x;
+                       xdata[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]);
+               }
+       }
+#if TOUCH_KEY_NUM > 0
+       for (k = 0; k < Key_Channel; k++) {
+               iArrayIndex = Y_Channel * X_Channel + k;
+               xdata[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]);
+       }
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       // for carrier sensing system to get short baseline rawdata
+       if (ts->carrier_system) {
+               // to get short baseline rawdata at pipe1
+               raw_pipe_addr = ts->mmap->RAW_PIPE1_ADDR;
+
+               for (y = 0; y < Y_Channel; y++) {
+                       //---change xdata index---
+                       buf[0] = 0xFF;
+                       buf[1] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 16) & 0xFF);
+                       buf[2] = (uint8_t)(((raw_pipe_addr + y * X_Channel * 2) >> 8) & 0xFF);
+                       CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+                       buf[0] = (uint8_t)((raw_pipe_addr + y * X_Channel * 2) & 0xFF);
+                       CTP_I2C_READ(ts->client, I2C_FW_Address, buf, X_Channel * 2 + 1);
+                       memcpy(rawdata_buf + y * X_Channel * 2, buf + 1, X_Channel * 2);
+               }
+#if TOUCH_KEY_NUM > 0
+               // to get button short baseline rawdata at pipe1
+               raw_btn_pipe_addr = ts->mmap->RAW_BTN_PIPE1_ADDR;
+
+           //---change xdata index---
+               buf[0] = 0xFF;
+               buf[1] = (uint8_t)((raw_btn_pipe_addr >> 16) & 0xFF);
+               buf[2] = (uint8_t)((raw_btn_pipe_addr >> 8) & 0xFF);
+               CTP_I2C_WRITE(ts->client, I2C_FW_Address, buf, 3);
+               buf[0] = (uint8_t)(raw_btn_pipe_addr & 0xFF);
+               CTP_I2C_READ(ts->client, I2C_FW_Address, buf, Key_Channel * 2 + 1);
+               memcpy(rawdata_buf + Y_Channel * X_Channel * 2, buf + 1, Key_Channel * 2);
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+               for (y = 0; y < Y_Channel; y++) {
+                       for (x = 0; x < X_Channel; x++) {
+                               iArrayIndex = y * X_Channel + x;
+                               RawData_Short_Base[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]);
+                       }
+               }
+#if TOUCH_KEY_NUM > 0
+               for (k = 0; k < Key_Channel; k++) {
+                       iArrayIndex = Y_Channel * X_Channel + k;
+                       RawData_Short_Base[iArrayIndex] = (int16_t)(rawdata_buf[iArrayIndex * 2] + 256 * rawdata_buf[iArrayIndex * 2 + 1]);
+               }
+#endif /* #if TOUCH_KEY_NUM > 0 */
+       }
+
+       if (rawdata_buf) {
+               kfree(rawdata_buf);
+               rawdata_buf = NULL;
+       }
+
+       //---Leave Test Mode---
+       nvt_change_mode(NORMAL_MODE);
+
+       if (ts->carrier_system)
+               printk("%s:RawData_Short_Diff:\n", __func__);
+       else
+               printk("%s:RawData_Short\n", __func__);
+       // Save Rawdata to CSV file
+       if (nvt_save_rawdata_to_csv(xdata, X_Channel, Y_Channel, SHORT_TEST_CSV_FILE, 0) < 0) {
+               NVT_ERR("save rawdata to CSV file failed\n");
+               return -EAGAIN;
+       }
+       if (ts->carrier_system) {
+#if TOUCH_KEY_NUM > 0
+               rawdata_short_base_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2 + Key_Channel * 7 + 2;
+#else
+               rawdata_short_base_offset = Y_Channel * X_Channel * 7 + Y_Channel * 2;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+               printk("%s:RawData_Short_Base:\n", __func__);
+               // Save Rawdata to CSV file
+               if (nvt_save_rawdata_to_csv(RawData_Short_Base, X_Channel, Y_Channel, SHORT_TEST_CSV_FILE, rawdata_short_base_offset) < 0) {
+                       NVT_ERR("save rawdata to CSV file failed\n");
+                       return -EAGAIN;
+               }
+       }
+
+       NVT_LOG("--\n");
+
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen raw data test for each single point function.
+
+return:
+       Executive outcomes. 0---passed. negative---failed.
+*******************************************************/
+static int32_t RawDataTest_SinglePoint_Sub(int32_t rawdata[], uint8_t RecordResult[], uint8_t x_ch, uint8_t y_ch, int32_t Rawdata_Limit_Postive[], int32_t Rawdata_Limit_Negative[])
+{
+       int32_t i = 0;
+       int32_t j = 0;
+#if TOUCH_KEY_NUM > 0
+    int32_t k = 0;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+       int32_t iArrayIndex = 0;
+       bool isPass = true;
+
+       for (j = 0; j < y_ch; j++) {
+               for (i = 0; i < x_ch; i++) {
+                       iArrayIndex = j * x_ch + i;
+
+                       RecordResult[iArrayIndex] = 0x00; // default value for PASS
+
+                       if(rawdata[iArrayIndex] > Rawdata_Limit_Postive[iArrayIndex])
+                               RecordResult[iArrayIndex] |= 0x01;
+
+                       if(rawdata[iArrayIndex] < Rawdata_Limit_Negative[iArrayIndex])
+                               RecordResult[iArrayIndex] |= 0x02;
+               }
+       }
+#if TOUCH_KEY_NUM > 0
+       for (k = 0; k < Key_Channel; k++) {
+               iArrayIndex = y_ch * x_ch + k;
+
+               RecordResult[iArrayIndex] = 0x00; // default value for PASS
+
+               if(rawdata[iArrayIndex] > Rawdata_Limit_Postive[iArrayIndex])
+                       RecordResult[iArrayIndex] |= 0x01;
+
+               if(rawdata[iArrayIndex] < Rawdata_Limit_Negative[iArrayIndex])
+                       RecordResult[iArrayIndex] |= 0x02;
+       }
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       //---Check RecordResult---
+       for (j = 0; j < y_ch; j++) {
+               for (i = 0; i < x_ch; i++) {
+                       if (RecordResult[j * x_ch + i] != 0) {
+                               isPass = false;
+                               break;
+                       }
+               }
+       }
+#if TOUCH_KEY_NUM > 0
+       for (k = 0; k < Key_Channel; k++) {
+               iArrayIndex = y_ch * x_ch + k;
+               if (RecordResult[iArrayIndex] != 0) {
+                       isPass = false;
+                       break;
+               }
+       }
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       if (isPass == false) {
+               return -1; // FAIL
+       } else {
+               return 0; // PASS
+       }
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen print self-test result function.
+
+return:
+       n.a.
+*******************************************************/
+void print_selftest_result(struct seq_file *m, int32_t TestResult, uint8_t RecordResult[], int32_t rawdata[], uint8_t x_len, uint8_t y_len)
+{
+       int32_t i = 0;
+       int32_t j = 0;
+       int32_t iArrayIndex = 0;
+#if TOUCH_KEY_NUM > 0
+       int32_t k = 0;
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+       switch (TestResult) {
+               case 0:
+                       nvt_mp_seq_printf(m, " PASS!\n");
+                       break;
+
+               case 1:
+                       nvt_mp_seq_printf(m, " ERROR! Read Data FAIL!\n");
+                       break;
+
+               case -1:
+                       nvt_mp_seq_printf(m, " FAIL!\n");
+                       nvt_mp_seq_printf(m, "RecordResult:\n");
+                       for (i = 0; i < y_len; i++) {
+                               for (j = 0; j < x_len; j++) {
+                                       iArrayIndex = i * x_len + j;
+                                       nvt_mp_seq_printf(m, "0x%02X, ", RecordResult[iArrayIndex]);
+                               }
+                               nvt_mp_seq_printf(m, "\n");
+                       }
+#if TOUCH_KEY_NUM > 0
+                       for (k = 0; k < Key_Channel; k++) {
+                               iArrayIndex = y_len * x_len + k;
+                               nvt_mp_seq_printf(m, "0x%02X, ", RecordResult[iArrayIndex]);
+                       }
+                       nvt_mp_seq_printf(m, "\n");
+#endif /* #if TOUCH_KEY_NUM > 0 */
+                       nvt_mp_seq_printf(m, "ReadData:\n");
+                       for (i = 0; i < y_len; i++) {
+                               for (j = 0; j < x_len; j++) {
+                                       iArrayIndex = i * x_len + j;
+                                       nvt_mp_seq_printf(m, "%5d, ", rawdata[iArrayIndex]);
+                               }
+                               nvt_mp_seq_printf(m, "\n");
+                       }
+#if TOUCH_KEY_NUM > 0
+                       for (k = 0; k < Key_Channel; k++) {
+                               iArrayIndex = y_len * x_len + k;
+                               nvt_mp_seq_printf(m, "%5d, ", rawdata[iArrayIndex]);
+                       }
+                       nvt_mp_seq_printf(m, "\n");
+#endif /* #if TOUCH_KEY_NUM > 0 */
+                       break;
+       }
+       nvt_mp_seq_printf(m, "\n");
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen self-test sequence print show
+       function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t c_show_selftest(struct seq_file *m, void *v)
+{
+#if NVT_TOUCH_MP_LENOVO
+       MP_TEST_RESULT mp_result = 0;
+#endif
+
+       NVT_LOG("++\n");
+#if !NVT_TOUCH_MP_LENOVO
+       nvt_mp_seq_printf(m, "FW Version: %d\n\n", ts->fw_ver);
+
+       nvt_mp_seq_printf(m, "Short Test");
+       if ((TestResult_Short == 0) || (TestResult_Short == 1)) {
+               print_selftest_result(m, TestResult_Short, RecordResult_Short, RawData_Short, X_Channel, Y_Channel);
+       } else { // TestResult_Short is -1
+               if (ts->carrier_system) {
+                       nvt_mp_seq_printf(m, " FAIL!\n");
+                       if (TestResult_Short_Diff == -1) {
+                               nvt_mp_seq_printf(m, "Short Diff");
+                               print_selftest_result(m, TestResult_Short_Diff, RecordResult_Short_Diff, RawData_Short_Diff, X_Channel, Y_Channel);
+                       }
+                       if (TestResult_Short_Base == -1) {
+                               nvt_mp_seq_printf(m, "Short Base");
+                               print_selftest_result(m, TestResult_Short_Base, RecordResult_Short_Base, RawData_Short_Base, X_Channel, Y_Channel);
+                       }
+               } else {
+                       print_selftest_result(m, TestResult_Short, RecordResult_Short, RawData_Short, X_Channel, Y_Channel);
+               }
+       }
+
+       nvt_mp_seq_printf(m, "Open Test");
+       print_selftest_result(m, TestResult_Open, RecordResult_Open, RawData_Open, X_Channel, Y_Channel);
+
+       nvt_mp_seq_printf(m, "FW Rawdata Test");
+       if ((TestResult_FW_Rawdata == 0) || (TestResult_FW_Rawdata == 1)) {
+                print_selftest_result(m, TestResult_FWMutual, RecordResult_FWMutual, RawData_FWMutual, X_Channel, Y_Channel);
+       } else { // TestResult_FW_Rawdata is -1
+               nvt_mp_seq_printf(m, " FAIL!\n");
+               if (TestResult_FWMutual == -1) {
+                       nvt_mp_seq_printf(m, "FW Mutual");
+                       print_selftest_result(m, TestResult_FWMutual, RecordResult_FWMutual, RawData_FWMutual, X_Channel, Y_Channel);
+               }
+               if (TestResult_FW_CC == -1) {
+                       if (ts->carrier_system) {
+                               if (TestResult_FW_CC_I == -1) {
+                                       nvt_mp_seq_printf(m, "FW CC_I");
+                                       print_selftest_result(m, TestResult_FW_CC_I, RecordResult_FW_CC_I, RawData_FW_CC_I, X_Channel, Y_Channel);
+                               }
+                               if (TestResult_FW_CC_Q == -1) {
+                                       nvt_mp_seq_printf(m, "FW CC_Q");
+                                       print_selftest_result(m, TestResult_FW_CC_Q, RecordResult_FW_CC_Q, RawData_FW_CC_Q, X_Channel, Y_Channel);
+                               }
+                       } else {
+                               nvt_mp_seq_printf(m, "FW CC");
+                               print_selftest_result(m, TestResult_FW_CC, RecordResult_FW_CC, RawData_FW_CC, X_Channel, Y_Channel);
+                       }
+               }
+       }
+
+       nvt_mp_seq_printf(m, "Noise Test");
+       if ((TestResult_Noise == 0) || (TestResult_Noise == 1)) {
+               print_selftest_result(m, TestResult_FW_DiffMax, RecordResult_FW_DiffMax, RawData_Diff_Max, X_Channel, Y_Channel);
+       } else { // TestResult_Noise is -1
+               nvt_mp_seq_printf(m, " FAIL!\n");
+
+               if (TestResult_FW_DiffMax == -1) {
+                       nvt_mp_seq_printf(m, "FW Diff Max");
+                       print_selftest_result(m, TestResult_FW_DiffMax, RecordResult_FW_DiffMax, RawData_Diff_Max, X_Channel, Y_Channel);
+               }
+               if (TestResult_FW_DiffMin == -1) {
+                       nvt_mp_seq_printf(m, "FW Diff Min");
+                       print_selftest_result(m, TestResult_FW_DiffMin, RecordResult_FW_DiffMin, RawData_Diff_Min, X_Channel, Y_Channel);
+               }
+       }
+#else
+       /* short */
+       if (TestResult_Short >= 0)
+               mp_result |= (!!TestResult_Short << MP_RESULT_SHIFT_SHORT);
+       else {
+               if (ts->carrier_system) {
+                       mp_result |= (!!TestResult_Short_Diff << MP_RESULT_SHIFT_SHORT_DIFF);
+                       mp_result |= (!!TestResult_Short_Base << MP_RESULT_SHIFT_SHORT_BASE);
+               } else {
+                       mp_result |= (!!TestResult_Short << MP_RESULT_SHIFT_SHORT);
+               }
+       }
+
+       /* open */
+       mp_result |= (!!TestResult_Open << MP_RESULT_SHIFT_OPEN);
+
+       /* raw data & cc */
+       if (TestResult_FW_Rawdata >= 0)
+               mp_result |= (!!TestResult_FWMutual << MP_RESULT_SHIFT_RAWDATA);
+       else {
+               if (TestResult_FWMutual == -1) {
+                       mp_result |= (!!TestResult_FWMutual << MP_RESULT_SHIFT_RAWDATA);
+               }
+               if (TestResult_FW_CC == -1) {
+                       if (ts->carrier_system) {
+                               mp_result |= (!!TestResult_FW_CC_I << MP_RESULT_SHIFT_CC_I);
+                               mp_result |= (!!TestResult_FW_CC_Q << MP_RESULT_SHIFT_CC_Q);
+                       } else {
+                               mp_result |= (!!TestResult_FW_CC << MP_RESULT_SHIFT_CC);
+                       }
+               }
+       }
+
+       /* noise */
+       if (TestResult_Noise >= 0)
+               mp_result |= (!!TestResult_FW_DiffMax << MP_RESULT_SHIFT_DIFF_MAX);
+       else {
+               if (TestResult_FW_DiffMax == -1) {
+                       mp_result |= (!!TestResult_FW_DiffMax << MP_RESULT_SHIFT_DIFF_MAX);
+               }
+               if (TestResult_FW_DiffMin == -1) {
+                       mp_result |= (!!TestResult_FW_DiffMin << MP_RESULT_SHIFT_DIFF_MIN);
+               }
+       }
+
+       nvt_mp_seq_printf(m, "%d", mp_result);
+#endif
+       nvt_mp_test_result_printed = 1;
+
+       NVT_LOG("--\n");
+
+    return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen self-test sequence print start
+       function.
+
+return:
+       Executive outcomes. 1---call next function.
+       NULL---not call next function and sequence loop
+       stop.
+*******************************************************/
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+       return *pos < 1 ? (void *)1 : NULL;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen self-test sequence print next
+       function.
+
+return:
+       Executive outcomes. NULL---no next and call sequence
+       stop function.
+*******************************************************/
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+       ++*pos;
+       return NULL;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen self-test sequence print stop
+       function.
+
+return:
+       n.a.
+*******************************************************/
+static void c_stop(struct seq_file *m, void *v)
+{
+       return;
+}
+
+const struct seq_operations nvt_selftest_seq_ops = {
+       .start  = c_start,
+       .next   = c_next,
+       .stop   = c_stop,
+       .show   = c_show_selftest
+};
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/nvt_selftest open function.
+
+return:
+       Executive outcomes. 0---succeed. negative---failed.
+*******************************************************/
+static int32_t nvt_selftest_open(struct inode *inode, struct file *file)
+{
+       struct device_node *np = ts->client->dev.of_node;
+       unsigned char mpcriteria[32] = {0};     //novatek-mp-criteria-default
+
+       TestResult_Short = 0;
+       TestResult_Short_Diff = 0;
+       TestResult_Short_Base = 0;
+       TestResult_Open = 0;
+       TestResult_FW_Rawdata = 0;
+       TestResult_FWMutual = 0;
+       TestResult_FW_CC = 0;
+       TestResult_FW_CC_I = 0;
+       TestResult_FW_CC_Q = 0;
+       TestResult_Noise = 0;
+       TestResult_FW_DiffMax = 0;
+       TestResult_FW_DiffMin = 0;
+
+       NVT_LOG("++\n");
+
+       if (mutex_lock_interruptible(&ts->lock)) {
+               return -ERESTARTSYS;
+       }
+#if NVT_TOUCH_ESD_PROTECT
+               nvt_esd_check_enable(false);
+#endif
+
+       if (nvt_get_fw_info()) {
+               mutex_unlock(&ts->lock);
+               NVT_ERR("get fw info failed!\n");
+               return -EAGAIN;
+       }
+
+       /* Parsing criteria from dts */
+       if(of_property_read_bool(np, "novatek,mp-support-dt")) {
+               /*
+                * Parsing Criteria by Novatek PID
+                * The string rule is "novatek-mp-criteria-<nvt_pid>"
+                * nvt_pid is 2 bytes (show hex).
+                *
+                * Ex. nvt_pid = 500A
+                *     mpcriteria = "novatek-mp-criteria-500A"
+                */
+               snprintf(mpcriteria, PAGE_SIZE, "novatek-mp-criteria-%04X", ts->nvt_pid);
+
+               nvt_mp_parse_dt(np, mpcriteria);
+       } else {
+               NVT_LOG("Not found novatek,mp-support-dt, use default setting\n");
+               //---Print Test Criteria---
+               nvt_print_criteria();
+       }
+
+       if (nvt_switch_FreqHopEnDis(FREQ_HOP_DISABLE)) {
+               mutex_unlock(&ts->lock);
+               NVT_ERR("switch frequency hopping disable failed!\n");
+               return -EAGAIN;
+       }
+
+       if (nvt_check_fw_reset_state(RESET_STATE_NORMAL_RUN)) {
+               mutex_unlock(&ts->lock);
+               NVT_ERR("check fw reset state failed!\n");
+               return -EAGAIN;
+       }
+
+       msleep(100);
+
+       //---Enter Test Mode---
+       if (nvt_clear_fw_status()) {
+               mutex_unlock(&ts->lock);
+               NVT_ERR("clear fw status failed!\n");
+               return -EAGAIN;
+       }
+
+       nvt_change_mode(MP_MODE_CC);
+
+       if (nvt_check_fw_status()) {
+               mutex_unlock(&ts->lock);
+               NVT_ERR("check fw status failed!\n");
+               return -EAGAIN;
+       }
+
+       //---FW Rawdata Test---
+       if (nvt_read_baseline(RawData_FWMutual) != 0) {
+               TestResult_FWMutual = 1;
+       } else {
+               TestResult_FWMutual = RawDataTest_SinglePoint_Sub(RawData_FWMutual, RecordResult_FWMutual, X_Channel, Y_Channel,
+                                                                                               PS_Config_Lmt_FW_Rawdata_P, PS_Config_Lmt_FW_Rawdata_N);
+       }
+       if (nvt_read_CC(RawData_FW_CC) != 0) {
+               TestResult_FW_CC = 1;
+               if (ts->carrier_system) {
+                       TestResult_FW_CC_I = 1;
+                       TestResult_FW_CC_Q = 1;
+               }
+       } else {
+               if (ts->carrier_system) {
+                       TestResult_FW_CC_I = RawDataTest_SinglePoint_Sub(RawData_FW_CC_I, RecordResult_FW_CC_I, X_Channel, Y_Channel,
+                                                                                               PS_Config_Lmt_FW_CC_I_P, PS_Config_Lmt_FW_CC_I_N);
+                       TestResult_FW_CC_Q = RawDataTest_SinglePoint_Sub(RawData_FW_CC_Q, RecordResult_FW_CC_Q, X_Channel, Y_Channel,
+                                                                                               PS_Config_Lmt_FW_CC_Q_P, PS_Config_Lmt_FW_CC_Q_N);
+                       if ((TestResult_FW_CC_I == -1) || (TestResult_FW_CC_Q == -1))
+                               TestResult_FW_CC = -1;
+                       else
+                               TestResult_FW_CC = 0;
+               } else {
+                       TestResult_FW_CC = RawDataTest_SinglePoint_Sub(RawData_FW_CC, RecordResult_FW_CC, X_Channel, Y_Channel,
+                                                                                               PS_Config_Lmt_FW_CC_P, PS_Config_Lmt_FW_CC_N);
+               }
+       }
+
+       if ((TestResult_FWMutual == 1) || (TestResult_FW_CC == 1)) {
+               TestResult_FW_Rawdata = 1;
+       } else {
+               if ((TestResult_FWMutual == -1) || (TestResult_FW_CC == -1))
+                       TestResult_FW_Rawdata = -1;
+               else
+                       TestResult_FW_Rawdata = 0;
+       }
+
+       //---Leave Test Mode---
+       nvt_change_mode(NORMAL_MODE);
+
+       //---Noise Test---
+       if (nvt_read_fw_noise(RawData_Diff) != 0) {
+               TestResult_Noise = 1;   // 1: ERROR
+               TestResult_FW_DiffMax = 1;
+               TestResult_FW_DiffMin = 1;
+       } else {
+               TestResult_FW_DiffMax = RawDataTest_SinglePoint_Sub(RawData_Diff_Max, RecordResult_FW_DiffMax, X_Channel, Y_Channel,
+                                                                                       PS_Config_Lmt_FW_Diff_P, PS_Config_Lmt_FW_Diff_N);
+
+               // for carrier sensing system, only positive noise data
+               if (ts->carrier_system) {
+                       TestResult_FW_DiffMin = 0;
+               } else {
+                       TestResult_FW_DiffMin = RawDataTest_SinglePoint_Sub(RawData_Diff_Min, RecordResult_FW_DiffMin, X_Channel, Y_Channel,
+                                                                                               PS_Config_Lmt_FW_Diff_P, PS_Config_Lmt_FW_Diff_N);
+               }
+
+               if ((TestResult_FW_DiffMax == -1) || (TestResult_FW_DiffMin == -1))
+                       TestResult_Noise = -1;
+               else
+                       TestResult_Noise = 0;
+       }
+
+       //--Short Test---
+       if (nvt_read_fw_short(RawData_Short) != 0) {
+               TestResult_Short = 1; // 1:ERROR
+               if (ts->carrier_system) {
+                       TestResult_Short_Diff = 1;
+                       TestResult_Short_Base = 1;
+               }
+       } else {
+               //---Self Test Check --- // 0:PASS, -1:FAIL
+               if (ts->carrier_system) {
+                       TestResult_Short_Diff = RawDataTest_SinglePoint_Sub(RawData_Short_Diff, RecordResult_Short_Diff, X_Channel, Y_Channel,
+                                                                                       PS_Config_Lmt_Short_Diff_P, PS_Config_Lmt_Short_Diff_N);
+                       TestResult_Short_Base = RawDataTest_SinglePoint_Sub(RawData_Short_Base, RecordResult_Short_Base, X_Channel, Y_Channel,
+                                                                                       PS_Config_Lmt_Short_Base_P, PS_Config_Lmt_Short_Base_N);
+
+                       if ((TestResult_Short_Diff == -1) || (TestResult_Short_Base == -1))
+                               TestResult_Short = -1;
+                       else
+                               TestResult_Short = 0;
+               } else {
+                       TestResult_Short = RawDataTest_SinglePoint_Sub(RawData_Short, RecordResult_Short, X_Channel, Y_Channel,
+                                                                                       PS_Config_Lmt_Short_Rawdata_P, PS_Config_Lmt_Short_Rawdata_N);
+               }
+       }
+
+       //---Open Test---
+       if (nvt_read_fw_open(RawData_Open) != 0) {
+               TestResult_Open = 1;    // 1:ERROR
+       } else {
+               //---Self Test Check --- // 0:PASS, -1:FAIL
+               TestResult_Open = RawDataTest_SinglePoint_Sub(RawData_Open, RecordResult_Open, X_Channel, Y_Channel,
+                                                                                       PS_Config_Lmt_Open_Rawdata_P, PS_Config_Lmt_Open_Rawdata_N);
+       }
+
+       //---Reset IC---
+       nvt_bootloader_reset();
+
+       mutex_unlock(&ts->lock);
+
+       NVT_LOG("--\n");
+
+       nvt_mp_test_result_printed = 0;
+
+       return seq_open(file, &nvt_selftest_seq_ops);
+}
+
+static const struct file_operations nvt_selftest_fops = {
+       .owner = THIS_MODULE,
+       .open = nvt_selftest_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = seq_release,
+};
+
+#if NVT_TOUCH_MP_LENOVO
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/NVTflash read function.
+
+return:
+       Executive outcomes. 2---succeed. -5,-14---failed.
+*******************************************************/
+static ssize_t nvt_data_read(struct file *file, char __user *buff, size_t count, loff_t *offp)
+{
+       uint8_t *str;
+       int32_t ret = -1;
+       int32_t retries = 0;
+       int8_t i2c_wr = 0;
+       uint8_t i2c_addr = 0;
+       uint32_t data_len = 0;
+
+       NVT_LOG("++\n");
+
+       if (count > (40 * (40 + 4) * 2 + 7)) {
+               NVT_ERR("error count=%zu\n", count);
+               return -EFAULT;
+       }
+
+       str = kmalloc(40 * (40 + 4) * 2 + 7, GFP_KERNEL);
+       if (str == NULL) {
+               NVT_ERR("failed to allocated memory for input data\n");
+               return -ENOMEM;
+       }
+
+       if (copy_from_user(str, buff, count)) {
+               NVT_ERR("copy from user error\n");
+               return -EFAULT;
+       }
+
+#if NVT_TOUCH_ESD_PROTECT
+       nvt_esd_check_enable(false);
+#endif
+
+       i2c_wr = str[0] >> 7;
+       i2c_addr = str[0] & 0x7F;
+       data_len = (int32_t)((str[1] << 8) + str[2]);
+
+       if (i2c_wr == 0) {
+               return -ENOTSUPP;
+       } else if (i2c_wr == 1) {
+               while (retries < 20) {
+                       ret = nvt_read_mass_data(i2c_addr, str, data_len);
+                       if (ret == data_len)
+                               break;
+                       else
+                               NVT_ERR("error, retries=%d, ret=%d, data_len=%d\n", retries, ret, data_len);
+
+                       retries++;
+               }
+
+               if (retries < 20) {
+                       ret = copy_to_user(buff, str, data_len);
+                       if (ret) {
+                               NVT_ERR("error, copy_to_user, ret=%d, data_len=%d\n", ret, data_len);
+                               return -EFAULT;
+                       }
+               }
+
+               if (unlikely(retries == 20)) {
+                       NVT_ERR("error, ret = %d\n", ret);
+                       return -EIO;
+               }
+       } else {
+               NVT_ERR("Call error, str[0]=%d\n", str[0]);
+               return -EFAULT;
+       }
+
+       kfree(str);
+       NVT_LOG("--\n");
+       return ret;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/NVTflash open function.
+
+return:
+       Executive outcomes. 0---succeed. -12---failed.
+*******************************************************/
+static int32_t nvt_data_open(struct inode *inode, struct file *file)
+{
+       struct nvt_flash_data *dev;
+
+       dev = kmalloc(sizeof(struct nvt_flash_data), GFP_KERNEL);
+       if (dev == NULL) {
+               NVT_ERR("Failed to allocate memory for nvt flash data\n");
+               return -ENOMEM;
+       }
+
+       rwlock_init(&dev->lock);
+       file->private_data = dev;
+
+       return 0;
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen /proc/NVTflash close function.
+
+return:
+       Executive outcomes. 0---succeed.
+*******************************************************/
+static int32_t nvt_data_close(struct inode *inode, struct file *file)
+{
+       struct nvt_flash_data *dev = file->private_data;
+
+       if (dev)
+               kfree(dev);
+
+       return 0;
+}
+
+static const struct file_operations nvt_read_data_fops = {
+       .owner = THIS_MODULE,
+       .open = nvt_data_open,
+       .release = nvt_data_close,
+       .read = nvt_data_read,
+};
+#endif
+
+#ifdef CONFIG_OF
+/*******************************************************
+Description:
+       Novatek touchscreen parse AIN setting for array type.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_mp_parse_ain(struct device_node *np, const char *name, uint8_t *array, int32_t size)
+{
+       struct property *data;
+       int32_t len, ret;
+       int32_t tmp[40];
+       int32_t i;
+
+       data = of_find_property(np, name, &len);
+       len /= sizeof(u32);
+
+       if ((!data) || (!len) || (len != size)) {
+               NVT_ERR("error find %s. len=%d\n", name, len);
+       } else {
+               NVT_LOG("%s. len=%d\n", name, len);
+               ret = of_property_read_u32_array(np, name, tmp, len);
+               if (ret) {
+                       NVT_ERR("error reading %s. ret=%d\n", name, ret);
+                       return;
+               }
+
+               for (i = 0; i < len; i++)
+                       array[i] = tmp[i];
+
+#if NVT_DEBUG
+               printk("[NVT-ts] %s = ", name);
+               for (i = 0; i < len; i++) {
+                       printk("%02d ", array[i]);
+               }
+               printk("\n");
+#endif
+       }
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen parse criterion for u32 type.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_mp_parse_u32(struct device_node *np, const char *name, int32_t *para)
+{
+       int32_t ret;
+
+       ret = of_property_read_u32(np, name, para);
+       if (ret)
+               NVT_ERR("error reading %s. ret=%d\n", name, ret);
+       else {
+#if NVT_DEBUG
+               NVT_LOG("%s=%d\n", name, *para);
+#endif
+       }
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen parse criterion for array type.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_mp_parse_array(struct device_node *np, const char *name, int32_t *array,
+               int32_t size)
+{
+       struct property *data;
+       int32_t len, ret;
+#if NVT_DEBUG
+       int32_t i, j, iArrayIndex = 0;
+#endif
+
+       data = of_find_property(np, name, &len);
+       len /= sizeof(u32);
+       if ((!data) || (!len) || (len < size)) {
+               NVT_ERR("error find %s. len=%d\n", name, len);
+       } else {
+               NVT_LOG("%s. len=%d\n", name, len);
+               ret = of_property_read_u32_array(np, name, array, len);
+               if (ret) {
+                       NVT_ERR("error reading %s. ret=%d\n", name, ret);
+                       return;
+               }
+
+#if NVT_DEBUG
+               NVT_LOG("%s =\n", name);
+               for (j = 0; j < Y_Channel; j++) {
+                       printk("[NVT-ts] ");
+                       for (i = 0; i < X_Channel; i++) {
+                               iArrayIndex = j * X_Channel + i;
+                               printk("%5d, ", array[iArrayIndex]);
+                       }
+                       printk("\n");
+               }
+#if TOUCH_KEY_NUM > 0
+               printk("[NVT-ts] ");
+               for (i = 0; i < Key_Channel; i++) {
+                       iArrayIndex++;
+                       printk("%5d, ", array[iArrayIndex]);
+               }
+               printk("\n");
+#endif
+#endif
+       }
+}
+
+/*******************************************************
+Description:
+       Novatek touchscreen parse device tree mp function.
+
+return:
+       n.a.
+*******************************************************/
+void nvt_mp_parse_dt(struct device_node *root, const char *node_compatible)
+{
+       struct device_node *np = root;
+       struct device_node *child = NULL;
+
+       NVT_LOG("Parse mp criteria for node %s\n", node_compatible);
+
+       /* find each MP sub-nodes */
+       for_each_child_of_node(root, child) {
+               /* find the specified node */
+               if (of_device_is_compatible(child, node_compatible)) {
+                       NVT_LOG("found child node %s\n", node_compatible);
+                       np = child;
+                       break;
+               }
+       }
+       if (child == NULL) {
+               NVT_ERR("Not found compatible node %s, use default setting!\n", node_compatible);
+               return;
+       }
+
+       /* MP Config*/
+       nvt_mp_parse_u32(np, "IC_X_CFG_SIZE", &IC_X_CFG_SIZE);
+
+       nvt_mp_parse_u32(np, "IC_Y_CFG_SIZE", &IC_Y_CFG_SIZE);
+
+#if TOUCH_KEY_NUM > 0
+       nvt_mp_parse_u32(np, "IC_KEY_CFG_SIZE", &IC_KEY_CFG_SIZE);
+#endif
+
+       nvt_mp_parse_u32(np, "X_Channel", &X_Channel);
+
+       nvt_mp_parse_u32(np, "Y_Channel", &Y_Channel);
+
+       nvt_mp_parse_ain(np, "AIN_X", AIN_X, IC_X_CFG_SIZE);
+
+       nvt_mp_parse_ain(np, "AIN_Y", AIN_Y, IC_Y_CFG_SIZE);
+
+#if TOUCH_KEY_NUM > 0
+       nvt_mp_parse_ain(np, "AIN_KEY", AIN_KEY, IC_KEY_CFG_SIZE);
+#endif
+
+       /* MP Criteria */
+       if (ts->carrier_system) {
+               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Diff_P", PS_Config_Lmt_Short_Diff_P,
+                               X_Channel * Y_Channel + Key_Channel);
+
+               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Diff_N", PS_Config_Lmt_Short_Diff_N,
+                               X_Channel * Y_Channel + Key_Channel);
+
+               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Base_P", PS_Config_Lmt_Short_Base_P,
+                               X_Channel * Y_Channel + Key_Channel);
+
+               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Base_N", PS_Config_Lmt_Short_Base_N,
+                               X_Channel * Y_Channel + Key_Channel);
+       } else {
+               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Rawdata_P", PS_Config_Lmt_Short_Rawdata_P,
+                               X_Channel * Y_Channel + Key_Channel);
+
+               nvt_mp_parse_array(np, "PS_Config_Lmt_Short_Rawdata_N", PS_Config_Lmt_Short_Rawdata_N,
+                               X_Channel * Y_Channel + Key_Channel);
+       }
+
+       nvt_mp_parse_array(np, "PS_Config_Lmt_Open_Rawdata_P", PS_Config_Lmt_Open_Rawdata_P,
+                       X_Channel * Y_Channel + Key_Channel);
+
+       nvt_mp_parse_array(np, "PS_Config_Lmt_Open_Rawdata_N", PS_Config_Lmt_Open_Rawdata_N,
+                       X_Channel * Y_Channel + Key_Channel);
+
+       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Rawdata_P", PS_Config_Lmt_FW_Rawdata_P,
+                       X_Channel * Y_Channel + Key_Channel);
+
+       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Rawdata_N", PS_Config_Lmt_FW_Rawdata_N,
+                       X_Channel * Y_Channel + Key_Channel);
+
+       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_P", PS_Config_Lmt_FW_CC_P,
+                       X_Channel * Y_Channel + Key_Channel);
+
+       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_N", PS_Config_Lmt_FW_CC_N,
+                       X_Channel * Y_Channel + Key_Channel);
+
+       if (ts->carrier_system) {
+               nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_I_P", PS_Config_Lmt_FW_CC_I_P,
+                               X_Channel * Y_Channel + Key_Channel);
+
+               nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_I_N", PS_Config_Lmt_FW_CC_I_N,
+                               X_Channel * Y_Channel + Key_Channel);
+
+               nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_Q_P", PS_Config_Lmt_FW_CC_Q_P,
+                               X_Channel * Y_Channel + Key_Channel);
+
+               nvt_mp_parse_array(np, "PS_Config_Lmt_FW_CC_Q_N", PS_Config_Lmt_FW_CC_Q_N,
+                               X_Channel * Y_Channel + Key_Channel);
+       }
+
+       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Diff_P", PS_Config_Lmt_FW_Diff_P,
+                       X_Channel * Y_Channel + Key_Channel);
+
+       nvt_mp_parse_array(np, "PS_Config_Lmt_FW_Diff_N", PS_Config_Lmt_FW_Diff_N,
+                       X_Channel * Y_Channel + Key_Channel);
+       nvt_mp_parse_u32(np, "PS_Config_Diff_Test_Frame", &PS_Config_Diff_Test_Frame);
+
+       NVT_LOG("Parse mp criteria done!\n");
+}
+#endif
+
+/*******************************************************
+Description:
+       Novatek touchscreen MP function proc. file node
+       initial function.
+
+return:
+       Executive outcomes. 0---succeed. -1---failed.
+*******************************************************/
+int32_t nvt_mp_proc_init(void)
+{
+       int32_t ret = 0;
+
+       NVT_proc_selftest_entry = proc_create("nvt_selftest", 0444, NULL, &nvt_selftest_fops);
+       if (NVT_proc_selftest_entry == NULL) {
+               NVT_ERR("create /proc/nvt_selftest Failed!\n");
+               ret = -1;
+       } else {
+               if(nvt_mp_buffer_init()) {
+                       NVT_ERR("Allocate mp memory failed\n");
+                       ret = -1;
+               }
+               else {
+                       NVT_LOG("create /proc/nvt_selftest Succeeded!\n");
+               }
+               ret = 0;
+       }
+#if NVT_TOUCH_MP_LENOVO
+       if (ret == 0) {
+               NVT_proc_selftest_read_data = proc_create("nvt_read_data", 0444, NULL, &nvt_read_data_fops);
+               if (NVT_proc_selftest_read_data == NULL) {
+                       NVT_ERR("create /proc/nvt_read_data Failed!\n");
+                       ret = -1;
+               } else {
+                       NVT_LOG("create /proc/nvt_read_data Succeeded!\n");
+               }
+       }
+#endif
+       return ret;
+}
+
+#endif /* #if NVT_TOUCH_MP */
diff --git a/drivers/input/touchscreen/nt36xxx/nt36xxx_mp_ctrlram.h b/drivers/input/touchscreen/nt36xxx/nt36xxx_mp_ctrlram.h
new file mode 100755 (executable)
index 0000000..bd9f949
--- /dev/null
@@ -0,0 +1,740 @@
+/*
+ * Copyright (C) 2010 - 2017 Novatek, Inc.
+ *
+ * $Revision: 22971 $
+ * $Date: 2018-02-08 16:05:40 +0800 (ι€±ε››, 08 δΊŒζœˆ 2018) $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#if NVT_TOUCH_MP
+
+static uint32_t IC_X_CFG_SIZE = 18;
+static uint32_t IC_Y_CFG_SIZE = 36;
+static uint32_t IC_KEY_CFG_SIZE = 4;
+static uint32_t X_Channel = 18;
+static uint32_t Y_Channel = 34;
+static uint32_t Key_Channel = TOUCH_KEY_NUM;
+static uint8_t AIN_X[40] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
+static uint8_t AIN_Y[40] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+                                                       18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 0xFF, 0xFF};
+#if TOUCH_KEY_NUM > 0
+static uint8_t AIN_KEY[8] = {0, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+#endif /* #if TOUCH_KEY_NUM > 0 */
+
+static int32_t PS_Config_Lmt_Short_Rawdata_P[40 * 40] = {
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+       6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,6500,
+#if TOUCH_KEY_NUM > 0
+       20000,20000,20000,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_Short_Rawdata_N[40 * 40] = {
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+       4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,4500,
+#if TOUCH_KEY_NUM > 0
+       11550,11550,11550,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_Short_Diff_P[40 * 40] = {
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+       6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,6300,
+#if TOUCH_KEY_NUM > 0
+       6300,6300,6300,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_Short_Diff_N[40 * 40] = {
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+#if TOUCH_KEY_NUM > 0
+       0,0,0,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_Short_Base_P[40 * 40] = {
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+       2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,2000,
+#if TOUCH_KEY_NUM > 0
+       2000,2000,2000,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_Short_Base_N[40 * 40] = {
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+       -2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,-2000,
+#if TOUCH_KEY_NUM > 0
+       -2000,-2000,-2000,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_Open_Rawdata_P[40 * 40] = {
+       5830,2470,3134,2675,6215, 590, 616, 542, 600,2505,2447,2511,2488,6273,4533,3227,2617,6119,
+       2967,3669,3098,6069,5039,4702,4552,4654,4525,2545,2653,2584,2695,3051,3680,5123,5934,3186,
+       2831,3440,2926,3081,2920,3067,2910,3055,2916,2883,3046,2916,3049,2907,3448,2893,3039,2908,
+       2762,3353,2877,3020,2873,3008,2865,2999,2872,2813,2961,2871,2990,2862,3389,2846,2979,2861,
+       2815,3410,2895,3040,2892,3031,2886,3023,2891,2863,3015,2890,3012,2881,3408,2865,3000,2881,
+       2773,3357,2846,2980,2844,2974,2840,2967,2846,2817,2958,2843,2952,2832,3347,2816,2942,2838,
+       2775,3362,2822,2953,2846,2975,2846,2970,2851,2825,2966,2823,2929,2838,3353,2823,2943,2838,
+       2730,3176,2803,2925,2797,2898,2800,2914,2807,2778,2906,2804,2901,2787,3160,2772,2879,2788,
+       2741,2939,2813,2938,2807,2909,2814,2930,2817,2791,2922,2815,2914,2798,2913,2784,2893,2801,
+       2691,2875,2761,2878,2758,2849,2767,2869,2765,2756,2857,2764,2863,2745,2849,2734,2830,2748,
+       2684,2861,2750,2862,2724,2812,2758,2859,2757,2750,2843,2759,2855,2714,2809,2726,2821,2743,
+       2714,2871,2768,2868,2771,2852,2785,2881,2788,2787,2867,2786,2866,2759,2844,2743,2830,2768,
+       2725,2885,2781,2884,2781,2871,2803,2901,2799,2804,2881,2798,2877,2770,2863,2755,2849,2780,
+       2554,2710,2612,2700,2616,2690,2607,2683,2624,2629,2676,2623,2693,2604,2680,2569,2649,2614,
+       2558,2712,2615,2703,2620,2697,2638,2717,2629,2634,2683,2627,2694,2607,2684,2598,2688,2621,
+       2487,2628,2541,2619,2548,2616,2567,2626,2554,2560,2605,2553,2607,2534,2599,2525,2611,2548,
+       2492,2625,2538,2616,2545,2617,2567,2618,2531,2561,2605,2552,2605,2531,2598,2524,2615,2527,
+       2399,2515,2447,2508,2450,2506,2476,2508,2461,2466,2499,2461,2494,2437,2491,2433,2508,2457,
+       2393,2510,2442,2501,2446,2503,2471,2502,2469,2465,2507,2458,2489,2433,2489,2430,2513,2450,
+       2316,2419,2363,2414,2372,2418,2394,2413,2387,2386,2414,2377,2399,2354,2399,2352,2432,2370,
+       2287,2391,2354,2404,2369,2415,2387,2407,2373,2360,2374,2365,2389,2344,2391,2342,2431,2363,
+       2214,2303,2260,2294,2276,2306,2296,2295,2278,2286,2300,2272,2276,2251,2284,2252,2316,2270,
+       2283,2365,2323,2419,2345,2376,2370,2379,2355,2360,2374,2341,2338,2316,2349,2317,2447,2344,
+       2225,2304,2245,2634,2280,2300,2303,2304,2284,2278,2285,2254,2257,2247,2265,2262,2684,2285,
+       2099,2175,2147,2528,2158,2167,2175,2165,2146,2149,2154,2145,2143,2128,2141,2145,2553,2157,
+       2005,2144,2065,2312,2074,2119,2085,2137,2057,2055,2112,2055,2113,2044,2112,2059,2337,2060,
+       1970,2107,2031,2273,2042,2082,2052,2081,2028,2018,2074,2021,2072,2011,2072,2029,2301,2026,
+       1894,2019,1958,2188,1958,1983,1977,1992,1954,1938,1978,1940,1980,1924,1971,1954,2213,1948,
+       1840,1957,1908,2127,1918,1929,1925,1929,1895,1888,1917,1891,1919,1886,1925,1907,2154,1896,
+       1767,1872,1837,2045,1846,1845,1854,1844,1822,1813,1827,1815,1834,1814,1842,1836,2067,1818,
+       1726,1830,1800,2004,1810,1802,1813,1791,1784,1772,1779,1776,1791,1776,1798,1796,2021,1777,
+       1658,1750,1733,1929,1741,1722,1750,1719,1709,1701,1695,1704,1713,1709,1724,1737,1948,1706,
+       1499,2086,1889,1954,1768,1745,1774,1735,1732,1720,1710,1724,1735,1732,1748,1762,1975,1461,
+       3326,3789,3764,1741,1713,1721,1704,1695,1703,1796,1816,1835,1821,1834,2028,1708,1674,1383,
+#if TOUCH_KEY_NUM > 0
+       13000,13000,13000,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_Open_Rawdata_N[40 * 40] = {
+       3139,1330,1688,1440,3346, 317, 332, 292, 323,1349,1318,1352,1340,3378,2441,1738,1409,3295,
+       1597,1975,1668,3268,2714,2532,2451,2506,2437,1371,1428,1391,1451,1643,1981,2759,3195,1715,
+       1525,1852,1575,1659,1572,1652,1567,1645,1570,1552,1640,1570,1642,1565,1857,1558,1636,1566,
+       1487,1806,1549,1626,1547,1620,1543,1615,1547,1514,1595,1546,1610,1541,1825,1532,1604,1541,
+       1516,1836,1559,1637,1557,1632,1554,1628,1557,1541,1623,1556,1622,1551,1835,1543,1616,1551,
+       1493,1808,1532,1605,1531,1601,1529,1597,1532,1517,1593,1531,1590,1525,1802,1516,1584,1528,
+       1494,1810,1520,1590,1532,1602,1533,1599,1535,1521,1597,1520,1577,1528,1805,1520,1585,1528,
+       1470,1710,1509,1575,1506,1560,1508,1569,1511,1496,1565,1510,1562,1501,1702,1493,1550,1501,
+       1476,1583,1515,1582,1512,1567,1515,1578,1517,1503,1573,1516,1569,1507,1568,1499,1558,1508,
+       1449,1548,1487,1550,1485,1534,1490,1545,1489,1484,1539,1489,1542,1478,1534,1472,1524,1480,
+       1445,1541,1481,1541,1467,1514,1485,1539,1485,1481,1531,1485,1537,1461,1513,1468,1519,1477,
+       1461,1546,1490,1544,1492,1536,1499,1551,1501,1501,1544,1500,1543,1486,1532,1477,1524,1491,
+       1467,1553,1498,1553,1498,1546,1509,1562,1507,1510,1551,1507,1549,1492,1541,1483,1534,1497,
+       1375,1459,1406,1454,1409,1448,1404,1445,1413,1416,1441,1413,1450,1402,1443,1383,1426,1407,
+       1378,1460,1408,1455,1411,1452,1420,1463,1416,1418,1445,1414,1451,1404,1445,1399,1448,1411,
+       1339,1415,1368,1410,1372,1409,1382,1414,1375,1379,1403,1375,1404,1365,1399,1360,1406,1372,
+       1342,1414,1367,1408,1370,1409,1382,1410,1363,1379,1402,1374,1403,1363,1399,1359,1408,1361,
+       1292,1354,1318,1350,1319,1349,1333,1350,1325,1328,1346,1325,1343,1312,1341,1310,1351,1323,
+       1289,1351,1315,1347,1317,1348,1330,1347,1329,1327,1350,1324,1340,1310,1340,1308,1353,1319,
+       1247,1302,1272,1300,1277,1302,1289,1299,1285,1285,1300,1280,1292,1267,1292,1266,1309,1276,
+       1232,1288,1267,1295,1276,1300,1286,1296,1278,1271,1278,1274,1286,1262,1287,1261,1309,1272,
+       1192,1240,1217,1235,1225,1242,1236,1236,1226,1231,1239,1224,1226,1212,1230,1213,1247,1222,
+       1229,1273,1251,1302,1263,1279,1276,1281,1268,1271,1278,1261,1259,1247,1265,1248,1318,1262,
+       1198,1241,1209,1418,1228,1239,1240,1241,1230,1227,1230,1214,1215,1210,1220,1218,1445,1231,
+       1130,1171,1156,1361,1162,1167,1171,1166,1155,1157,1160,1155,1154,1146,1153,1155,1375,1161,
+       1080,1155,1112,1245,1117,1141,1123,1151,1108,1107,1137,1107,1138,1100,1137,1109,1258,1109,
+       1061,1134,1093,1224,1099,1121,1105,1120,1092,1087,1117,1088,1116,1083,1116,1093,1239,1091,
+       1020,1087,1054,1178,1054,1068,1065,1072,1052,1044,1065,1044,1066,1036,1061,1052,1191,1049,
+        991,1054,1028,1145,1033,1039,1036,1038,1020,1016,1032,1018,1033,1015,1037,1027,1160,1021,
+        952,1008, 989,1101, 994, 993, 998, 993, 981, 976, 984, 977, 988, 977, 992, 989,1113, 979,
+        929, 985, 969,1079, 975, 970, 976, 965, 960, 954, 958, 956, 964, 956, 968, 967,1088, 957,
+        893, 942, 933,1039, 938, 927, 942, 926, 920, 916, 912, 918, 922, 920, 928, 935,1049, 918,
+        807,1123,1017,1052, 952, 940, 955, 934, 932, 926, 921, 928, 934, 933, 941, 949,1063, 787,
+       1791,2040,2027, 937, 922, 927, 918, 913, 917, 967, 978, 988, 981, 987,1092, 920, 901, 745,
+#if TOUCH_KEY_NUM > 0
+       6500,6500,6500,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_Rawdata_P[40 * 40] = {
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+       1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,1700,
+#if TOUCH_KEY_NUM > 0
+       2000,2000,2000,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_Rawdata_N[40 * 40] = {
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+       700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+#if TOUCH_KEY_NUM > 0
+       400,400,400,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_CC_P[40 * 40] = {
+       116,114,119,109,112,106,104,106,103,108,110,108,110,117,113,115,111,113,
+       117,115,118,111,113,111,114,114,109,110,115,114,112,113,112,118,116,119,
+       115,113,116,110,112,109,108,108,107,108,113,111,110,111,110,116,111,115,
+       116,114,117,112,114,110,109,110,108,109,114,111,111,112,111,117,113,116,
+       115,113,116,111,113,110,108,109,107,108,112,111,110,112,111,117,112,116,
+       116,115,118,112,114,111,110,110,108,109,114,112,112,113,112,118,114,117,
+       114,112,115,110,112,108,107,108,106,107,111,110,110,111,110,116,111,115,
+       115,114,117,112,113,110,109,109,108,109,113,111,111,112,111,117,113,116,
+       115,113,116,111,113,110,109,109,108,109,113,111,111,112,111,117,112,116,
+       117,115,118,113,115,112,111,111,110,112,115,112,112,114,113,118,114,117,
+       114,112,115,110,112,109,109,109,107,113,112,110,110,112,110,117,112,115,
+       115,112,116,111,113,110,109,109,108,114,112,110,111,112,111,117,112,115,
+       117,115,118,113,115,112,111,113,110,118,113,112,113,115,113,119,115,118,
+       114,112,116,110,113,110,109,112,108,115,110,110,111,112,111,117,112,115,
+       116,113,117,112,114,111,111,113,109,117,112,111,112,114,112,118,114,117,
+       116,113,117,112,114,111,110,112,109,116,112,111,111,114,112,118,113,116,
+       117,114,119,113,115,112,111,113,110,117,114,112,112,115,113,119,115,117,
+       115,112,116,110,112,110,109,110,108,114,111,109,110,112,111,116,112,114,
+       116,113,118,112,114,111,111,112,110,116,113,111,112,114,112,118,114,116,
+       116,113,117,112,114,111,111,111,110,115,113,111,111,114,112,117,113,115,
+       118,115,119,114,115,113,113,113,111,117,114,112,113,115,113,119,115,117,
+       116,112,117,111,113,110,110,111,109,114,112,110,111,113,112,117,113,115,
+       117,113,118,112,114,111,111,112,109,115,112,111,111,114,112,117,114,116,
+       119,115,120,114,116,114,113,115,111,115,113,113,114,117,115,120,116,118,
+       117,113,118,112,114,112,112,113,110,112,111,111,111,115,113,118,114,116,
+       119,114,119,113,114,113,112,115,111,112,112,112,112,115,114,119,116,119,
+       119,114,118,113,114,112,112,114,110,111,111,111,112,114,114,119,115,119,
+       121,116,120,114,116,114,114,116,112,113,113,113,114,116,115,121,117,120,
+       118,113,117,112,113,111,111,113,109,110,110,110,111,114,113,119,115,118,
+       120,115,119,114,115,113,113,115,111,112,112,112,113,116,114,120,117,119,
+       119,115,119,113,114,113,114,115,111,111,112,111,113,115,114,120,117,119,
+       121,116,121,115,116,114,116,117,113,113,114,113,114,117,115,122,119,121,
+       115,112,116,113,114,112,115,114,110,111,111,111,112,115,113,120,116,118,
+       115,114,120,114,115,112,110,111,110,107,113,113,110,111,111,120,116,118,
+#if TOUCH_KEY_NUM > 0
+       38,38,38,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_CC_N[40 * 40] = {
+       63,61,64,59,60,57,56,57,55,58,59,58,59,63,61,62,60,61,
+       63,62,63,60,61,60,61,61,59,59,62,61,60,61,60,64,62,64,
+       62,61,62,59,60,59,58,58,58,58,61,60,59,60,59,62,60,62,
+       62,61,63,60,61,59,59,59,58,58,61,60,60,61,60,63,61,63,
+       62,61,63,60,61,59,58,59,58,58,60,60,59,60,60,63,60,62,
+       63,62,63,60,61,60,59,59,58,59,61,60,60,61,60,64,61,63,
+       61,60,62,59,60,58,58,58,57,58,60,59,59,60,59,62,60,62,
+       62,61,63,60,61,59,59,59,58,59,61,60,60,60,60,63,61,63,
+       62,61,63,60,61,59,59,59,58,58,61,60,60,60,60,63,61,62,
+       63,62,63,61,62,60,60,60,59,61,62,60,61,61,61,64,61,63,
+       62,60,62,59,60,59,58,59,58,61,60,59,59,60,59,63,60,62,
+       62,61,62,60,61,59,59,59,58,61,60,59,60,60,60,63,60,62,
+       63,62,64,61,62,60,60,61,59,63,61,60,61,62,61,64,62,63,
+       61,60,62,59,61,59,59,60,58,62,59,59,60,60,60,63,60,62,
+       62,61,63,60,61,60,60,61,59,63,60,60,60,61,60,63,61,63,
+       62,61,63,60,61,60,59,60,59,62,60,60,60,61,60,63,61,62,
+       63,62,64,61,62,60,60,61,59,63,61,60,61,62,61,64,62,63,
+       62,60,63,59,61,59,59,59,58,61,60,59,59,60,60,63,60,61,
+       63,61,63,60,61,60,60,60,59,63,61,60,60,61,60,63,61,62,
+       63,61,63,60,61,60,60,60,59,62,61,60,60,61,61,63,61,62,
+       64,62,64,61,62,61,61,61,60,63,61,60,61,62,61,64,62,63,
+       62,60,63,60,61,59,59,60,58,62,61,59,60,61,60,63,61,62,
+       63,61,63,60,61,60,60,61,59,62,60,60,60,61,60,63,61,62,
+       64,62,65,61,62,61,61,62,60,62,61,61,61,63,62,65,63,64,
+       63,61,63,60,61,60,60,61,59,60,60,60,60,62,61,63,62,63,
+       64,61,64,61,61,61,61,62,60,60,60,60,61,62,61,64,62,64,
+       64,61,64,61,61,60,61,61,59,60,60,60,60,62,61,64,62,64,
+       65,62,65,62,62,61,61,62,60,61,61,61,61,63,62,65,63,65,
+       64,61,63,60,61,60,60,61,59,59,59,59,60,61,61,64,62,63,
+       64,62,64,61,62,61,61,62,60,60,60,60,61,62,62,65,63,64,
+       64,62,64,61,62,61,61,62,60,60,60,60,61,62,61,65,63,64,
+       65,62,65,62,63,62,63,63,61,61,61,61,61,63,62,66,64,65,
+       62,60,62,61,61,60,62,61,59,60,60,60,60,62,61,64,63,64,
+       62,61,64,61,62,60,59,60,59,58,61,61,59,60,60,65,62,63,
+#if TOUCH_KEY_NUM > 0
+       9,9,9,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_CC_I_P[40 * 40] = {
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+#if TOUCH_KEY_NUM > 0
+       25,25,25,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_CC_I_N[40 * 40] = {
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+#if TOUCH_KEY_NUM > 0
+       0,0,0,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_CC_Q_P[40 * 40] = {
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+       25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,
+#if TOUCH_KEY_NUM > 0
+       25,25,25,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_CC_Q_N[40 * 40] = {
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+#if TOUCH_KEY_NUM > 0
+       0,0,0,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_Diff_P[40 * 40] = {
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+       50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,
+#if TOUCH_KEY_NUM > 0
+       35,35,35,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Lmt_FW_Diff_N[40 *40] = {
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+       -50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,-50,
+#if TOUCH_KEY_NUM > 0
+       -35,-35,-35,
+#endif /* #if TOUCH_KEY_NUM > 0 */
+};
+
+static int32_t PS_Config_Diff_Test_Frame = 50;
+
+#endif /* #if NVT_TOUCH_MP */