input: touchscreen: synaptics_3200: Update Synaptics 3200 driver

* HTC kernel version: m7-kk-3.4.10-17db3b4

Change-Id: Icfc4997d7d6f6257c8f947f2d50eb455481f8832
diff --git a/drivers/input/touchscreen/rmi_dev.c b/drivers/input/touchscreen/rmi_dev.c
index 78aface..212d014 100644
--- a/drivers/input/touchscreen/rmi_dev.c
+++ b/drivers/input/touchscreen/rmi_dev.c
@@ -122,6 +122,17 @@
 	return ret_value;
 }
 
+/*
+ * rmi_char_dev_write: - use to write data into RMI stream
+ *
+ * @filep : file structure for write
+ * @buf: user-level buffer pointer contains data to be written
+ * @count: number of byte be be written
+ * @f_pos: offset (starting register address)
+ *
+ * @return number of bytes written from user buffer (buf) if succeeds
+ *         negative number if error occurs.
+ */
 static ssize_t rmi_char_dev_write(struct file *filp, const char __user *buf,
 		size_t count, loff_t *f_pos)
 {
diff --git a/drivers/input/touchscreen/synaptics_3200.c b/drivers/input/touchscreen/synaptics_3200.c
index 3b92511..eb22f5d 100644
--- a/drivers/input/touchscreen/synaptics_3200.c
+++ b/drivers/input/touchscreen/synaptics_3200.c
@@ -27,15 +27,25 @@
 #include <linux/slab.h>
 #include <linux/rmi.h>
 #include <mach/board.h>
+#include <mach/board_htc.h>
 #include <mach/msm_hsusb.h>
 #include <asm/gpio.h>
 #include <linux/input/mt.h>
 #include <linux/pl_sensor.h>
+#include <linux/async.h>
+#include <linux/firmware.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
 
 #define SYN_I2C_RETRY_TIMES 10
+#define SYN_UPDATE_RETRY_TIMES 5
 #define SHIFT_BITS 10
 #define SYN_WIRELESS_DEBUG
 
+#define SYN_FW_NAME "tp_SYN.img"
+#define SYN_FW_TIMEOUT (30000)
+static DEFINE_MUTEX(syn_fw_mutex);
+
 struct synaptics_ts_data {
 	uint16_t addr;
 	struct i2c_client *client;
@@ -54,9 +64,11 @@
 	uint8_t finger_support;
 	uint16_t finger_pressed;
 	int (*power)(int on);
+	int (*lpm_power)(int on);
 	struct early_suspend early_suspend;
 	int pre_finger_data[11][4];
 	uint32_t debug_log_level;
+	uint32_t enable_noise_log;
 	uint32_t raw_base;
 	uint32_t raw_ref;
 	uint64_t timestamp;
@@ -70,6 +82,7 @@
 	uint16_t tap_suppression;
 	uint8_t ambiguous_state;
 	uint8_t diag_command;
+	uint8_t disable_CBC;
 	uint8_t cable_support;
 	uint8_t cable_config;
 	uint8_t key_number;
@@ -109,6 +122,7 @@
 	uint8_t multitouch_calibration;
 	uint32_t width_factor;
 	uint32_t height_factor;
+	uint8_t finger_func_idx;
 	uint8_t psensor_detection;
 	uint8_t psensor_resume_enable;
 	uint8_t psensor_phone_enable;
@@ -117,6 +131,11 @@
 	struct work_struct  psensor_work;
 	struct workqueue_struct *syn_psensor_wq;
 	struct synaptics_virtual_key *button;
+	wait_queue_head_t syn_fw_wait;
+	atomic_t syn_fw_condition;
+	uint8_t block_touch_time_near;
+	uint8_t block_touch_time_far;
+	uint8_t block_touch_event;
 };
 
 #ifdef CONFIG_HAS_EARLYSUSPEND
@@ -139,6 +158,41 @@
 
 extern unsigned int get_tamper_sf(void);
 
+static DEFINE_MUTEX(syn_block_mutex);
+static void syn_block_touch(struct synaptics_ts_data *ts, int enable)
+{
+	mutex_lock(&syn_block_mutex);
+	ts->block_touch_event = enable;
+	mutex_unlock(&syn_block_mutex);
+	printk(KERN_INFO "[TP] Block Touch Event:%d\n", enable);
+}
+
+static void syn_block_touch_work_func(struct work_struct *dummy)
+{
+	struct synaptics_ts_data *ts = gl_ts;
+	syn_block_touch(ts, 0);
+}
+static DECLARE_DELAYED_WORK(syn_block_touch_work, syn_block_touch_work_func);
+
+static void syn_handle_block_touch(struct synaptics_ts_data *ts, int enable)
+{
+	int ret;
+	if (ts->block_touch_event) {
+		ret = __cancel_delayed_work(&syn_block_touch_work);
+		syn_block_touch(ts, 0);
+	}
+	if (enable) {
+		if (ts->block_touch_time_near && enable == 1) {
+			ret = schedule_delayed_work(&syn_block_touch_work, HZ*ts->block_touch_time_near/1000);
+			syn_block_touch(ts, 1);
+		}
+		if (ts->block_touch_time_far && enable == 2) {
+			ret = schedule_delayed_work(&syn_block_touch_work, HZ*ts->block_touch_time_far/1000);
+			syn_block_touch(ts, 1);
+		}
+	}
+}
+
 static void syn_page_select(struct i2c_client *client, uint8_t page)
 {
 	struct synaptics_ts_data *ts = i2c_get_clientdata(client);
@@ -367,33 +421,13 @@
 	else
 		return -1;
 }
-static int get_int_mask(uint8_t number, uint8_t offset)
-{
-	uint8_t i, mask = 0;
-	for (i = 0; i < number; i++)
-		mask |= BIT(i);
-	return mask << offset;
-}
 
-static uint32_t syn_crc(uint16_t *data, uint16_t len)
-{
-	uint32_t sum1, sum2;
-	sum1 = sum2 = 0xFFFF;
-	while (len--) {
-		sum1 += *data++;
-		sum2 += sum1;
-		sum1 = (sum1 & 0xFFFF) + (sum1 >> 16);
-		sum2 = (sum2 & 0xFFFF) + (sum2 >> 16);
-	}
-	return sum1 | (sum2 << 16);
-}
-
-static int wait_flash_interrupt(struct synaptics_ts_data *ts, int attr)
+static int wait_flash_interrupt(struct synaptics_ts_data *ts, int attr, int fw)
 {
 	uint8_t data = 0;
 	int i, ret;
 
-	for (i = 0; i < 5; i++) {
+	for (i = 0; i < 5000; i++) {
 #ifdef SYN_FLASH_PROGRAMMING_LOG
 		printk(KERN_INFO "[TP] ATT: %d\n", gpio_get_value(attr));
 #endif
@@ -409,26 +443,38 @@
 				break;
 			}
 		}
-		hr_msleep(20);
+		if (fw)
+			mdelay(2);
+		else
+			hr_msleep(2);
 	}
 
-	if (i == 5 && syn_panel_version == 0) {
+	if (i == 5000 && syn_panel_version == 0) {
 		ret = i2c_syn_read(ts->client, get_address_base(ts, 0x01, DATA_BASE) + 1, &data, 1);
 		if (ret < 0)
 			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:2", __func__);
-	} else if (i == 5) {
+	} else if (i == 5000) {
 		printk(KERN_INFO "[TP] wait_flash_interrupt: interrupt over time!\n");
 		return SYN_PROCESS_ERR;
 	}
 
-	ret = i2c_syn_read(ts->client,
-		get_address_base(ts, 0x34, DATA_BASE) + 18, &data, 1);
+	if (ts->package_id < 3400)
+		ret = i2c_syn_read(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 0x12, &data, 1);
+	else
+		ret = i2c_syn_read(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 0x3, &data, 1);
 	if (ret < 0)
 		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:3", __func__);
 	
-	if (data != 0x80) {
-		printk(KERN_INFO "[TP] wait_flash_interrupt: block config fail!\n");
+	if (!(data & 0x80)) {
+		printk(KERN_INFO "[TP] Not in program enable mode, F34_data = %x\n", data);
+		ret = i2c_syn_read(ts->client,
+			get_address_base(ts, 0x01, DATA_BASE), &data, 1);
+		printk(KERN_INFO "[TP] Not in program enable mode, 01_data = %x\n", data);
 		return SYN_PROCESS_ERR;
+	} else if (data != 0x80) {
+		printk(KERN_INFO "[TP] Not in program enable mode, data = %x\n", data);
 	}
 	return 0;
 }
@@ -436,124 +482,45 @@
 static int enable_flash_programming(struct synaptics_ts_data *ts, int attr)
 {
 	int ret;
-	uint8_t data[2];
+	uint8_t data[2] = {0};
 
+	if (attr) {
+		if (!gpio_get_value(attr)) {
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x01, DATA_BASE) + 1, data, 1);
+			if (ret < 0)
+				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
+			printk(KERN_INFO "[TP] %s: clear gpio_irq before enter bootloader mode, data = %x\n", __func__, data[0]);
+		}
+	}
 	
 	ret = i2c_syn_read(ts->client,
 		get_address_base(ts, 0x34, QUERY_BASE), data, 2);
 	if (ret < 0)
 		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
-	
 
-	ret = i2c_syn_write(ts->client,
-		get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
-	if (ret < 0)
-		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
-
-	ret = i2c_syn_write_byte_data(ts->client,
-		get_address_base(ts, 0x34, DATA_BASE) + 18, 0x0F);
-	if (ret < 0)
-		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
-
-	ret = wait_flash_interrupt(ts, attr);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int crc_comparison(struct synaptics_ts_data *ts, uint32_t config_crc, int attr)
-{
-	int ret;
-	uint8_t data[17];
-	uint32_t flash_crc;
-#ifdef SYN_FLASH_PROGRAMMING_LOG
-	uint8_t i, j;
-
-	for (i = 0; i < 0x20; i++) {
-		data[0] = i;
-		data[1] = 0x00;
-#else
-		data[0] = 0x1F;
-		data[1] = 0x00;
-#endif
+	if (ts->package_id < 3400)
 		ret = i2c_syn_write(ts->client,
-			get_address_base(ts, 0x34, DATA_BASE), data, 2);
-		if (ret < 0)
-			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:1", __func__);
-
-		ret = i2c_syn_write_byte_data(ts->client,
-			get_address_base(ts, 0x34, DATA_BASE) + 18, 0x05);
-		if (ret < 0)
-			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
-
-		ret = wait_flash_interrupt(ts, attr);
-		if (ret < 0)
-			return ret;
-
-		ret = i2c_syn_read(ts->client,
-			get_address_base(ts, 0x34, DATA_BASE) + 2, data, 17);
-		if (ret < 0)
-			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:3", __func__);
-
-		memcpy(&flash_crc, &data[12], 4);
-
-#ifdef SYN_FLASH_PROGRAMMING_LOG
-		printk(KERN_INFO "[TP] config_crc = %X, flash_crc = %X\n", config_crc, flash_crc);
-		for (j = 0; j < 0x11; j++)
-			printk(KERN_INFO " %d:%X ", j, data[j]);
-		printk(KERN_INFO "\n");
-	}
-#endif
-
-	if (flash_crc == config_crc)
-		return 0;
+			get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
 	else
-		return 1;
-}
-
-static int program_config(struct synaptics_ts_data *ts, uint8_t *config, int attr)
-{
-	int ret;
-	uint8_t data[19];
-	uint16_t i;
-
-	ret = i2c_syn_read(ts->client,
-		get_address_base(ts, 0x34, QUERY_BASE), data, 2);
-	
-	if (ret < 0)
-		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
-
-	ret = i2c_syn_write(ts->client,
-		get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
+		ret = i2c_syn_write(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 1, data, 2);
 	if (ret < 0)
 		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
 
-	
-	ret = i2c_syn_write_byte_data(ts->client,
-		get_address_base(ts, 0x34, DATA_BASE) + 18, 0x07);
+	if (ts->package_id < 3400)
+		ret = i2c_syn_write_byte_data(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 18, 0x0F);
+	else
+		ret = i2c_syn_write_byte_data(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 2, 0x0F);
 	if (ret < 0)
 		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
 
-	ret = wait_flash_interrupt(ts, attr);
+	ret = wait_flash_interrupt(ts, attr, 0);
 	if (ret < 0)
 		return ret;
 
-	for (i = 0; i < 0x20; i++) {
-		data[0] = i & 0xFF;
-		data[1] = (i & 0xFF00) >> 8;
-		memcpy(&data[2], &config[16 * i], 16);
-		data[18] = 0x06;
-		ret = i2c_syn_write(ts->client,
-			get_address_base(ts, 0x34, DATA_BASE), data, 19);
-		if (ret < 0)
-			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:4", __func__);
-
-		ret = wait_flash_interrupt(ts, attr);
-		if (ret < 0)
-			return ret;
-	}
-
 	return 0;
 }
 
@@ -588,6 +555,319 @@
 	}
 }
 
+
+static int program_fw_img(struct synaptics_ts_data *ts,
+			  const uint8_t *imgbuf, const uint16_t filelength)
+{
+	uint8_t data[20] = {0};
+	uint16_t blocksize, fwcnt, cfgcnt ,i;
+	int ret;
+
+	if (syn_pdt_scan(ts, SYN_BL_PAGE) < 0) {
+		printk(KERN_ERR "[TP] TOUCH_ERR:%s: PDT scan fail\n", __func__);
+		return -1;
+	}
+	
+	i2c_syn_read(ts->client, get_address_base(ts, 0x34, QUERY_BASE), data, 2);
+
+	
+	if (ts->package_id < 3400)
+		i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE) + 0x2, data, 2);
+	else
+		i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE) + 0x1, data, 2);
+
+	
+	printk(KERN_INFO "[TP][FW] Erase firmware and config\n");
+	data[0] = 0x03;
+	if (ts->package_id < 3400)
+		i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE) + 0x12, data, 1);
+	else
+		i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE) + 0x2, data, 1);
+	ret = wait_flash_interrupt(ts, ts->gpio_irq, 1);
+	if (ret < 0)
+		return ret;
+
+	
+	memset(data, 0x0, sizeof(data));
+	if (ts->package_id < 3400)
+		i2c_syn_read(ts->client, get_address_base(ts, 0x34, QUERY_BASE) + 0x3, data, 6);
+	else
+		i2c_syn_read(ts->client, get_address_base(ts, 0x34, QUERY_BASE) + 0x2, data, 6);
+	blocksize = data[0] | data[1] << 8;
+	fwcnt     = data[2] | data[3] << 8;
+	cfgcnt    = data[4] | data[5] << 8;
+#ifdef SYN_FLASH_PROGRAMMING_LOG
+	printk(KERN_INFO "[TP][FW]Block size: %x, FW Block count: %x, Configure count: %x\n",
+		blocksize, fwcnt, cfgcnt);
+#endif
+
+	
+	printk(KERN_INFO "[TP][FW] Program firmware\n");
+	for (i = 0; i < fwcnt; i++)
+	{
+		data[0] = i & 0xFF;
+		data[1] = (i & 0xFF00) >> 8;
+		memcpy(&data[2], &imgbuf[0x100 + (i * blocksize)], blocksize);
+		data[2 + blocksize] = 0x02;
+
+		i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE), data, 3 + blocksize);
+
+		
+		ret = wait_flash_interrupt(ts, ts->gpio_irq, 1);
+		if (ret < 0)
+			return ret;
+	}
+	
+	printk(KERN_INFO "[TP][FW] Program config\n");
+	for (i = 0; i < cfgcnt; i++) {
+		data[0] = i & 0xFF;
+		data[1] = (i & 0xFF00) >> 8;
+		memcpy(&data[2],
+			&imgbuf[0x100 + (fwcnt* blocksize) + (i * blocksize)], blocksize);
+		data[2 + blocksize] = 0x06;
+
+		i2c_syn_write(ts->client, get_address_base(ts, 0x34, DATA_BASE), data, 3 + blocksize);
+
+		
+		ret = wait_flash_interrupt(ts, ts->gpio_irq, 1);
+		if (ret < 0)
+			return ret;
+	}
+
+	
+	printk(KERN_INFO "[TP][FW] Disable flash programming\n");
+	disable_flash_programming(ts, 1);
+	return 0;
+}
+
+static int syn_firmware_update(struct synaptics_ts_data *ts)
+{
+	int ret = 0, i = 0;
+	uint prnum = 0;
+	uint8_t  start_addr = 0;
+	u8 *pos, *pos_end;
+	char prstr[10] = {0};
+	const struct firmware *fw;
+
+	ret = request_firmware(&fw, SYN_FW_NAME, &ts->client->dev);
+	if (fw == NULL) {
+		printk(KERN_INFO"[TP][FW] No firmware file, ignored firmware update\n");
+		goto SYN_FW_REQUEST_FAILUE;
+	}
+	else if (ret) {
+		printk(KERN_INFO"[TP][FW] Request_firmware failed, ret = %d\n", ret);
+		goto SYN_FW_REQUEST_FAILUE;
+	}
+	if (fw->data[0] == 'T' && fw->data[1] == 'P') {
+		pos = strchr(fw->data, 'R');				
+
+		pos_end    = strchr(fw->data, '\n');                    
+		start_addr = pos_end - fw->data + 1;
+		memcpy(prstr, &fw->data[(pos - fw->data + 1)], 7);
+		ret        = strict_strtoul(prstr, 10, (unsigned long*)&prnum);
+		if (ret < 0) {
+			printk(KERN_INFO "[TP][FW] TP tag parse failed %s, %d\n", prstr, prnum);
+			goto SYN_FW_CHECK_FAILURE;
+		}
+
+		printk(KERN_INFO "[TP][FW] size=%d, pr=%u\n",
+			(fw->size-(pos_end - fw->data + 1)), prnum);
+
+		if (prnum != ts->packrat_number) {
+			printk(KERN_INFO "[TP][FW] PR number is not the same, firmware update...\n");
+
+			mutex_lock(&syn_fw_mutex);	
+			for (i = 0; i < 5; i++) {
+				if (!enable_flash_programming(ts, ts->gpio_irq)) {
+					printk(KERN_INFO "[TP][FW] Enable flash ok\n");
+					break;
+				}
+				hr_msleep(20);
+			}
+			if (i == 5) {
+				printk(KERN_ERR "[TP][FW] TOUCH_ERR: syn_eanbl_flash retry 5 time Faile\n");
+				ret = -1;
+				goto SYN_FW_FAILUE;
+			}
+
+			if (!program_fw_img(ts, &fw->data[start_addr],
+					    fw->size - start_addr )) {
+				printk(KERN_INFO "[TP][FW] update successfully\n");
+				release_firmware(fw);
+			} else {
+				printk(KERN_INFO "[TP][FW] update failed\n");
+				ret = -2;
+				goto SYN_FW_FAILUE;
+			}
+			mutex_unlock(&syn_fw_mutex);
+		} else {
+			printk(KERN_INFO "[TP][FW] PR number is the same. Ignored\n");
+			ret = 1;
+			goto SYN_FW_PRCHECK_NOT_ALLOW;
+		}
+	} else {
+		printk(KERN_INFO "[TP][FW]Miss TP firmware tag. Ignored\n");
+		ret = 2;
+		goto SYN_FW_CHECK_FAILURE;
+	}
+
+	return 0;
+
+SYN_FW_FAILUE:
+SYN_FW_PRCHECK_NOT_ALLOW:
+SYN_FW_CHECK_FAILURE:
+SYN_FW_REQUEST_FAILUE:
+	release_firmware(fw);
+
+	return ret;
+}
+
+static int syn_fw_update_init(void *arg)
+{
+	int ret;
+	struct synaptics_ts_data *ts = (struct synaptics_ts_data *)arg;
+	printk(KERN_INFO "[TP][FW] %s\n", __func__);
+	ret = syn_firmware_update(ts);
+	if (ret)
+		printk(KERN_INFO "[TP][FW] Bypassed firmware update, ret = %d\n", ret);
+	atomic_set(&ts->syn_fw_condition, 1);
+	wake_up(&ts->syn_fw_wait);
+
+	return ret;
+}
+
+static int get_int_mask(uint8_t number, uint8_t offset)
+{
+	uint8_t i, mask = 0;
+	for (i = 0; i < number; i++)
+		mask |= BIT(i);
+	return mask << offset;
+}
+
+static uint32_t syn_crc(uint16_t *data, uint16_t len)
+{
+	uint32_t sum1, sum2;
+	sum1 = sum2 = 0xFFFF;
+	while (len--) {
+		sum1 += *data++;
+		sum2 += sum1;
+		sum1 = (sum1 & 0xFFFF) + (sum1 >> 16);
+		sum2 = (sum2 & 0xFFFF) + (sum2 >> 16);
+	}
+	return sum1 | (sum2 << 16);
+}
+
+static int crc_comparison(struct synaptics_ts_data *ts, uint32_t config_crc, int attr)
+{
+	int ret;
+	uint8_t data[17];
+	uint32_t flash_crc;
+#ifdef SYN_FLASH_PROGRAMMING_LOG
+	uint8_t i, j;
+
+	for (i = 0; i < 0x20; i++) {
+		data[0] = i;
+		data[1] = 0x00;
+#else
+		data[0] = 0x1F;
+		data[1] = 0x00;
+#endif
+		ret = i2c_syn_write(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE), data, 2);
+		if (ret < 0)
+			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:1", __func__);
+
+		if (ts->package_id < 3400)
+			ret = i2c_syn_write_byte_data(ts->client,
+				get_address_base(ts, 0x34, DATA_BASE) + 18, 0x05);
+		else
+			ret = i2c_syn_write_byte_data(ts->client,
+				get_address_base(ts, 0x34, DATA_BASE) + 2, 0x05);
+		if (ret < 0)
+			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
+
+		ret = wait_flash_interrupt(ts, attr, 0);
+		if (ret < 0)
+			return ret;
+
+		if (ts->package_id < 3400)
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x34, DATA_BASE) + 2, data, 17);
+		else
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x34, DATA_BASE) + 1, data, 17);
+		if (ret < 0)
+			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:3", __func__);
+
+		memcpy(&flash_crc, &data[12], 4);
+
+#ifdef SYN_FLASH_PROGRAMMING_LOG
+		printk(KERN_INFO "[TP] config_crc = %X, flash_crc = %X\n", config_crc, flash_crc);
+		for (j = 0; j < 0x11; j++)
+			printk(KERN_INFO " %d:%X ", j, data[j]);
+		printk(KERN_INFO "\n");
+	}
+#endif
+
+	if (flash_crc == config_crc)
+		return 0;
+	else
+		return 1;
+}
+
+static int program_config(struct synaptics_ts_data *ts, uint8_t *config, int attr)
+{
+	int ret;
+	uint8_t data[19];
+	uint16_t i;
+
+	ret = i2c_syn_read(ts->client,
+		get_address_base(ts, 0x34, QUERY_BASE), data, 2);
+	
+	if (ret < 0)
+		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
+
+	if (ts->package_id < 3400)
+		ret = i2c_syn_write(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
+	else
+		ret = i2c_syn_write(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 1, data, 2);
+	if (ret < 0)
+		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
+
+	
+	if (ts->package_id < 3400)
+		ret = i2c_syn_write_byte_data(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 18, 0x07);
+	else
+		ret = i2c_syn_write_byte_data(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 2, 0x07);
+	if (ret < 0)
+		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
+
+	ret = wait_flash_interrupt(ts, attr, 0);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < 0x20; i++) {
+		data[0] = i & 0xFF;
+		data[1] = (i & 0xFF00) >> 8;
+		memcpy(&data[2], &config[16 * i], 16);
+		data[18] = 0x06;
+		ret = i2c_syn_write(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE), data, 19);
+		if (ret < 0)
+			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:4", __func__);
+
+		ret = wait_flash_interrupt(ts, attr, 0);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int syn_config_update(struct synaptics_ts_data *ts, int attr)
 {
 	uint8_t retry;
@@ -648,7 +928,7 @@
 
 static int syn_get_tw_vendor(struct synaptics_ts_data *ts, int attr)
 {
-	uint8_t data[2] = {0};
+	uint8_t data[6] = {0};
 	int ret;
 
 	ret = enable_flash_programming(ts, attr);
@@ -665,20 +945,36 @@
 
 	memcpy(&data, &ts->tw_pin_mask, sizeof(ts->tw_pin_mask));
 	printk(KERN_INFO "[TP] tw mask = %X %X , %X\n", data[0], data[1], ts->tw_pin_mask);
-	i2c_syn_write(ts->client,
-		get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
-	i2c_syn_write(ts->client,
-		get_address_base(ts, 0x34, DATA_BASE) + 4, data, 2);
-	i2c_syn_write_byte_data(ts->client,
-		get_address_base(ts, 0x34, DATA_BASE) + 18, 0x08);
+	data[2] = data[0];
+	data[3] = data[1];
+	if (ts->package_id < 3400) {
+		i2c_syn_write(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 2, data, 2);
+		i2c_syn_write(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 4, data, 2);
+		i2c_syn_write_byte_data(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 18, 0x08);
+	} else {
+		i2c_syn_write(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 1, data, 4);
+		i2c_syn_write_byte_data(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 2, 0x08);
+	}
 
-	if (wait_flash_interrupt(ts, attr) < 0)
+	if (wait_flash_interrupt(ts, attr, 0) < 0)
 		return disable_flash_programming(ts, -1);
 
-	i2c_syn_read(ts->client,
-		get_address_base(ts, 0x34, DATA_BASE) + 6, data, 2);
-	ts->tw_vendor = (data[1] << 8) | data[0];
-	printk(KERN_INFO "[TP] tw vendor= %x %x\n", data[1], data[0]);
+	if (ts->package_id < 3400) {
+		i2c_syn_read(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 6, data, 2);
+		ts->tw_vendor = (data[1] << 8) | data[0];
+		printk(KERN_INFO "[TP] tw vendor= %x %x\n", data[1], data[0]);
+	} else {
+		i2c_syn_read(ts->client,
+			get_address_base(ts, 0x34, DATA_BASE) + 1, data, 6);
+		ts->tw_vendor = (data[5] << 8) | data[4];
+		printk(KERN_INFO "[TP] tw vendor= %x %x\n", data[5], data[4]);
+	}
 
 	return 0;
 }
@@ -702,6 +998,7 @@
 	set_bit(KEY_MENU, ts->input_dev->keybit);
 	set_bit(KEY_SEARCH, ts->input_dev->keybit);
 	set_bit(KEY_APP_SWITCH, ts->input_dev->keybit);
+	set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
 
 	printk(KERN_INFO "[TP] input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n",
 		ts->layout[0], ts->layout[1], ts->layout[2], ts->layout[3]);
@@ -820,7 +1117,6 @@
 			}
 		}
 	}
-
 	return count;
 }
 
@@ -854,6 +1150,10 @@
 		if(i!=count-2)
 			ts->debug_log_level <<= 4;
 	}
+	if (ts->debug_log_level & BIT(17))
+		ts->enable_noise_log = 1;
+	else
+		ts->enable_noise_log = 0;
 
 	return count;
 }
@@ -889,7 +1189,7 @@
 	}
 
 	wait_event_interruptible_timeout(syn_data_ready_wq,
-					 atomic_read(&ts->data_ready), 50);
+					atomic_read(&ts->data_ready), 50);
 
 	for (i = 0; i < ts->y_channel; i++) {
 		for (j = 0; j < ts->x_channel; j++) {
@@ -900,7 +1200,6 @@
 		}
 		count += sprintf(buf + count, "\n");
 	}
-
 	return count;
 }
 
@@ -920,12 +1219,119 @@
 static DEVICE_ATTR(diag, (S_IWUSR|S_IRUGO),
 	syn_diag_show, syn_diag_store);
 
+static ssize_t syn_cbc_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct synaptics_ts_data *ts;
+	int ret;
+	uint8_t data = 0, update = 0;
+	ts = gl_ts;
+	if (buf[0] == '0') {
+		if (ts->package_id < 3400) {
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, &data, 1);
+			if ((data & 0x10) == 0) {
+				data |= 0x10;
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, data);
+				update = 1;
+			}
+		} else {
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, &data, 1);
+			if ((data & 0x20) == 0) {
+				data |= 0x20;
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, data);
+				update = 1;
+			}
+		}
+		if (ts->button) {
+			if (ts->package_id < 3400) {
+				ret = i2c_syn_read(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, &data, 1);
+				if ((data & 0x10) == 0) {
+					data |= 0x10;
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, data);
+					update = 1;
+				}
+			} else {
+				ret = i2c_syn_read(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, &data, 1);
+				if ((data & 0x10) == 0) {
+					data |= 0x10;
+					ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, data);
+					update = 1;
+				}
+			}
+		}
+		if (update) {
+			ret = i2c_syn_write_byte_data(ts->client,
+				get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+		}
+		ts->disable_CBC = 0;
+	} else if (buf[0] == '1') {
+		if (ts->package_id < 3400) {
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, &data, 1);
+			if (data & 0x10) {
+				data &= 0xEF;
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, data);
+				update = 1;
+			}
+		} else {
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, &data, 1);
+			if (data & 0x20) {
+				data &= 0xDF;
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, data);
+				update = 1;
+			}
+		}
+		if (ts->button) {
+			if (ts->package_id < 3400) {
+				ret = i2c_syn_read(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, &data, 1);
+				if (data & 0x10) {
+					data &= 0xEF;
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, data);
+					update = 1;
+				}
+			} else {
+				ret = i2c_syn_read(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, &data, 1);
+				if (data & 0x10) {
+					data &= 0xEF;
+					ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, data);
+					update = 1;
+				}
+			}
+		}
+		if (update) {
+			ret = i2c_syn_write_byte_data(ts->client,
+				get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+		}
+		ts->disable_CBC = 1;
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(disable_cbc, (S_IWUSR|S_IRUGO),
+	NULL, syn_cbc_store);
+
 static ssize_t syn_unlock_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct synaptics_ts_data *ts;
 	int unlock = -1;
-	int ret;
+	int ret = 0;
 
 	ts = gl_ts;
 
@@ -935,7 +1341,7 @@
 	printk(KERN_INFO "[TP] Touch: unlock change to %d\n", unlock);
 
 	if (unlock == 2 && ts->first_pressed && ts->pre_finger_data[0][0] < 2) {
-		ts->pre_finger_data[0][0] = 2;
+			ts->pre_finger_data[0][0] = 2;
 		if(ts->psensor_detection) {
 			if(ts->psensor_resume_enable == 1) {
 				printk(KERN_INFO "[TP] %s: Disable P-sensor by Touch\n", __func__);
@@ -947,14 +1353,64 @@
 			}
 		}
 		if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
+#ifdef SYN_CALIBRATION_CONTROL
+			ret = i2c_syn_write_byte_data(ts->client,
+				get_address_base(ts, 0x54, CONTROL_BASE) + 0x10, 0x0);
+			if (ret < 0)
+				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:1", __func__);
+
+			if (ts->energy_ratio_relaxation) {
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE), 0x0);
+				if (ret < 0)
+					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
+			}
+
+			if (ts->saturation_bef_unlock) {
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x02, ts->saturation_aft_unlock & 0xFF);
+				if (ret < 0)
+					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x03, (ts->saturation_aft_unlock & 0xFF00) >> 8);
+				if (ret < 0)
+					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:4", __func__);
+				printk(KERN_INFO "[TP] %s: unlock confirmed. set saturation: %x\n"
+					, __func__, ts->saturation_aft_unlock);
+			}
+
+			if ( ts->PixelTouchThreshold_bef_unlock ) {
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x04, ts->PixelTouchThreshold_aft_unlock);
+				if (ret < 0)
+					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "F54_ANALOG_CTRL03 Pixel Touch Threshold", __func__);
+				printk(KERN_INFO "[TP] %s: set F54_ANALOG_CTRL03 Pixel Touch Threshold: %x\n", __func__, ts->PixelTouchThreshold_aft_unlock);
+			}
+
+
+			ret = i2c_syn_write_byte_data(ts->client,
+				get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+			if (ret < 0)
+				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:5", __func__);
+
+			if (ts->multitouch_calibration) {
+				if (ts->package_id < 3400) {
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, ts->finger_func_idx, COMMAND_BASE), 0x01);
+					if (ret < 0)
+						return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:6", __func__);
+					printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+				}
+			}
+#endif
 			if (ts->large_obj_check) {
 				if (ts->package_id == 2200) {
 					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x26, ts->default_large_obj);
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x26, ts->default_large_obj);
 
 				} else {
 					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x29, ts->default_large_obj);
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x29, ts->default_large_obj);
 				}
 				if (ret < 0)
 					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:7", __func__);
@@ -965,11 +1421,11 @@
 			if (ts->segmentation_bef_unlock) {
 				if (ts->package_id == 2200) {
 					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x25, ts->segmentation_aft_unlock);
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x25, ts->segmentation_aft_unlock);
 
 				} else {
 					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x22, ts->segmentation_aft_unlock);
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x22, ts->segmentation_aft_unlock);
 				}
 				if (ret < 0)
 					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:8", __func__);
@@ -980,10 +1436,10 @@
 			if (ts->threshold_bef_unlock) {
 				if (ts->package_id == 2200) {
 					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x0A, ts->threshold_aft_unlock);
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0A, ts->threshold_aft_unlock);
 				} else {
 					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x0C, ts->threshold_aft_unlock);
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0C, ts->threshold_aft_unlock);
 				}
 				if (ret < 0)
 					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:9", __func__);
@@ -1378,7 +1834,8 @@
 		)
 		return -ENOMEM;
 	if (get_address_base(gl_ts, 0x54, FUNCTION))
-		if (sysfs_create_file(android_touch_kobj, &dev_attr_diag.attr))
+		if (sysfs_create_file(android_touch_kobj, &dev_attr_diag.attr) ||
+			sysfs_create_file(android_touch_kobj, &dev_attr_disable_cbc.attr))
 			return -ENOMEM;
 
 #ifdef SYN_WIRELESS_DEBUG
@@ -1387,7 +1844,7 @@
 		printk(KERN_INFO "[TP]%s: Failed to obtain touchpad IRQ %d. Code: %d.", __func__, ts->gpio_irq, ret);
 		return ret;
 	}
-	if (ts->gpio_reset) {
+	if (ts->gpio_reset && !ts->i2c_err_handler_en) {
 		ret = gpio_request(ts->gpio_reset, "synaptics_reset");
 		if (ret)
 			printk(KERN_INFO "[TP]%s: Failed to obtain reset pin: %d. Code: %d.", __func__, ts->gpio_reset, ret);
@@ -1444,38 +1901,47 @@
 		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:1", __func__);
 	if (ts->pre_finger_data[0][0] < 2) {
 		if (ts->large_obj_check) {
-			if (ts->package_id == 2200) {
-				ret = i2c_syn_write_byte_data(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x26, ts->default_large_obj & 0x7F);
-			} else {
-				ret = i2c_syn_write_byte_data(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x29, ts->default_large_obj & 0x7F);
+			if (ts->package_id < 3400) {
+				if (ts->package_id == 2200) {
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x26, ts->default_large_obj & 0x7F);
+				} else {
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x29, ts->default_large_obj & 0x7F);
+				}
+				if (ret < 0)
+					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
+				printk(KERN_INFO "[TP] %s: set large obj suppression register to: %x\n", __func__, ts->default_large_obj & 0x7F);
 			}
-			if (ret < 0)
-				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:2", __func__);
-			printk(KERN_INFO "[TP] %s: set large obj suppression register to: %x\n", __func__, ts->default_large_obj & 0x7F);
 		}
 
 		if (ts->segmentation_bef_unlock) {
-			if (ts->package_id == 2200) {
-				ret = i2c_syn_write_byte_data(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x25, ts->segmentation_bef_unlock);
-			} else {
-				ret = i2c_syn_write_byte_data(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x22, ts->segmentation_bef_unlock);
+			if (ts->package_id < 3400) {
+				if (ts->package_id == 2200) {
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x25, ts->segmentation_bef_unlock);
+				} else {
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x22, ts->segmentation_bef_unlock);
+				}
+				if (ret < 0)
+					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
+				printk(KERN_INFO "[TP] %s: set segmentation aggressiveness to: %x\n", __func__, ts->segmentation_bef_unlock);
 			}
-			if (ret < 0)
-				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:3", __func__);
-			printk(KERN_INFO "[TP] %s: set segmentation aggressiveness to: %x\n", __func__, ts->segmentation_bef_unlock);
 		}
 
 		if (ts->threshold_bef_unlock) {
-			if (ts->package_id == 2200) {
-				ret = i2c_syn_write_byte_data(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x0A, ts->threshold_bef_unlock);
+			if (ts->package_id < 3400) {
+				if (ts->package_id == 2200) {
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0A, ts->threshold_bef_unlock);
+				} else {
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0C, ts->threshold_bef_unlock);
+				}
 			} else {
 				ret = i2c_syn_write_byte_data(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x0C, ts->threshold_bef_unlock);
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x01, ts->threshold_bef_unlock);
 			}
 			if (ret < 0)
 				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:4", __func__);
@@ -1511,25 +1977,62 @@
 		}
 	}
 
+#ifdef SYN_CALIBRATION_CONTROL
+	if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
+		if (ts->pre_finger_data[0][0] >= 2 || ts->mfg_flag == 1) {
+			ret = i2c_syn_write_byte_data(ts->client,
+				get_address_base(ts, 0x54, CONTROL_BASE) + 0x10, 0x0);
+			if (ret < 0)
+				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:6", __func__);
+
+			ret = i2c_syn_write_byte_data(ts->client,
+				get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+			if (ret < 0)
+				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:7", __func__);
+
+			printk(KERN_INFO "[TP] %s: Touch init: set fast relaxation to 0x0\n", __func__);
+		}
+	}
+#endif
+
 	return ret;
 }
 
 static void synaptics_ts_finger_func(struct synaptics_ts_data *ts)
 {
 	int ret;
-	uint8_t buf[((ts->finger_support * 21 + 3) / 4)];
+	uint8_t buf[ts->finger_support * 8 ], noise_index[10], noise_state = 0;
+	static int x_pos[10] = {0}, y_pos[10] = {0};
 
 	memset(buf, 0x0, sizeof(buf));
-	ret = i2c_syn_read(ts->client,
-		get_address_base(ts, 0x11, DATA_BASE), buf, sizeof(buf));
+	memset(noise_index, 0x0, sizeof(noise_index));
+	if (ts->package_id < 3400)
+		ret = i2c_syn_read(ts->client,
+			get_address_base(ts, 0x01, DATA_BASE) + 2, buf, sizeof(buf));
+	else {
+		ret = i2c_syn_read(ts->client,
+			get_address_base(ts, ts->finger_func_idx, DATA_BASE), buf, sizeof(buf));
+		ret = i2c_syn_read(ts->client,
+			get_address_base(ts, 0x54, DATA_BASE) + 8, &noise_state, 1);
+		if (noise_state == 2) {
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x54, DATA_BASE) + 4, noise_index, sizeof(noise_index));
+			ts->debug_log_level |= BIT(17);
+		} else {
+			if (!ts->enable_noise_log)
+				ts->debug_log_level &= ~BIT(17);
+		}
+	}
 	if (ret < 0) {
 		i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
 	} else {
 		int finger_data[ts->finger_support][4];
-		int base = (ts->finger_support + 3) / 4;
+		int base = 0;
 		uint8_t i, j;
 		uint16_t finger_press_changed = 0, finger_release_changed = 0, finger_pressed = 0;
 
+		if (ts->package_id < 3400)
+			base = (ts->finger_support + 3) / 4;
 		ts->finger_count = 0;
 		if (ts->debug_log_level & BIT(0)) {
 			printk(KERN_INFO "[TP] Touch:");
@@ -1538,7 +2041,12 @@
 			printk(KERN_INFO "\n");
 		}
 		for (i = 0; i < ts->finger_support; i++) {
-			uint8_t finger_state = buf[(i / 4)] >> ((i * 2) % 8);
+			uint8_t finger_state;
+			if (ts->package_id < 3400)
+				finger_state = buf[(i / 4)] >> ((i * 2) % 8);
+			else
+				finger_state = buf[i * 8];
+
 			if (finger_state & 0x03) {
 				finger_pressed |= BIT(i);
 				ts->finger_count++;
@@ -1547,6 +2055,7 @@
 				else if (finger_state == 0x03)
 					printk(KERN_INFO "[TP] Finger state[%d] = 0x03\n", i);
 			}
+
 #ifdef SYN_FILTER_CONTROL
 			else if ((ts->grip_suppression | ts->grip_b_suppression) & BIT(i)) {
 				ts->grip_suppression &= ~BIT(i);
@@ -1565,19 +2074,26 @@
 		if(ts->debug_log_level & BIT(3)) {
 			for(i = 0; i < ts->finger_support; i++) {
 				if (finger_release_changed & BIT(i) ) {
-					uint32_t flip_flag = SYNAPTICS_FLIP_X;
-					uint8_t pos_mask = 0x0f;
-					for (j = 0; j < 2; j++) {
-						finger_data[i][j]
-							= (buf[base+2] & pos_mask) >> (j * 4) |
-							(uint16_t)buf[base + j] << 4;
-						if (ts->flags & flip_flag)
-							finger_data[i][j] = ts->max[j] - finger_data[i][j];
-						flip_flag <<= 1;
-						pos_mask <<= 4;
+					if (ts->package_id < 3400) {
+						uint32_t flip_flag = SYNAPTICS_FLIP_X;
+						uint8_t pos_mask = 0x0f;
+						for (j = 0; j < 2; j++) {
+							finger_data[i][j]
+								= (buf[base+2] & pos_mask) >> (j * 4) |
+								(uint16_t)buf[base + j] << 4;
+							if (ts->flags & flip_flag)
+								finger_data[i][j] = ts->max[j] - finger_data[i][j];
+							flip_flag <<= 1;
+							pos_mask <<= 4;
+						}
+						finger_data[i][2] = (buf[base+3] >> 4 & 0x0F) + (buf[base+3] & 0x0F);
+						finger_data[i][3] = buf[base+4];
+					} else {
+						finger_data[i][0] = (buf[base+2] << 8) + buf[base+1];
+						finger_data[i][1] = (buf[base+4] << 8) + buf[base+3];
+						finger_data[i][2] = buf[base+6] + buf[base+7];
+						finger_data[i][3] = buf[base+5];
 					}
-					finger_data[i][2] = (buf[base+3] >> 4 & 0x0F) + (buf[base+3] & 0x0F);
-					finger_data[i][3] = buf[base+4];
 
 					if (ts->flags & SYNAPTICS_SWAP_XY)
 						swap(finger_data[i][0], finger_data[i][1]);
@@ -1587,13 +2103,13 @@
 					if(ts->width_factor && ts->height_factor){
 						printk(KERN_INFO
 							"[TP] Screen:F[%02d]:Up, X=%d, Y=%d, W=%d, Z=%d\n",
-							i+1, (finger_data[i][0]*ts->width_factor)>>SHIFT_BITS,
-							(finger_data[i][1]*ts->height_factor)>>SHIFT_BITS,
+							i+1, (x_pos[i]*ts->width_factor)>>SHIFT_BITS,
+							(y_pos[i]*ts->height_factor)>>SHIFT_BITS,
 							finger_data[i][2], finger_data[i][3]);
 					} else {
 						printk(KERN_INFO
 							"[TP] Raw:F[%02d]:Up, X=%d, Y=%d, W=%d, Z=%d\n",
-							i+1, finger_data[i][0], finger_data[i][1],
+							i+1, x_pos[i], y_pos[i],
 							finger_data[i][2], finger_data[i][3]);
 					}
 				}
@@ -1620,6 +2136,11 @@
 					input_report_abs(ts->input_dev, ABS_MT_POSITION, 1 << 31);
 				}
 				input_mt_sync(ts->input_dev);
+			} else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
+				if (ts->support_htc_event) {
+					input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, 0);
+					input_report_abs(ts->input_dev, ABS_MT_POSITION, 1 << 31);
+				}
 			}
 			else if (ts->htc_event == SYN_AND_REPORT_TYPE_HTC) {
 				input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, 0);
@@ -1638,22 +2159,32 @@
 		}
 
 		if (ts->pre_finger_data[0][0] < 2 || finger_pressed) {
-			base = (ts->finger_support + 3) / 4;
+			if (ts->package_id < 3400)
+				base = (ts->finger_support + 3) / 4;
+			else
+				base = 0;
 			for (i = 0; i < ts->finger_support; i++) {
 				uint32_t flip_flag = SYNAPTICS_FLIP_X;
 				if ((finger_pressed | finger_release_changed) & BIT(i)) {
-					uint8_t pos_mask = 0x0f;
-					for (j = 0; j < 2; j++) {
-						finger_data[i][j]
-							= (buf[base+2] & pos_mask) >> (j * 4) |
-							(uint16_t)buf[base + j] << 4;
-						if (ts->flags & flip_flag)
-							finger_data[i][j] = ts->max[j] - finger_data[i][j];
-						flip_flag <<= 1;
-						pos_mask <<= 4;
+					if (ts->package_id < 3400) {
+						uint8_t pos_mask = 0x0f;
+						for (j = 0; j < 2; j++) {
+							finger_data[i][j]
+								= (buf[base+2] & pos_mask) >> (j * 4) |
+								(uint16_t)buf[base + j] << 4;
+							if (ts->flags & flip_flag)
+								finger_data[i][j] = ts->max[j] - finger_data[i][j];
+							flip_flag <<= 1;
+							pos_mask <<= 4;
+						}
+						finger_data[i][2] = (buf[base+3] >> 4 & 0x0F) + (buf[base+3] & 0x0F);
+						finger_data[i][3] = buf[base+4];
+					} else {
+						finger_data[i][0] = (buf[base+2] << 8) + buf[base+1];
+						finger_data[i][1] = (buf[base+4] << 8) + buf[base+3];
+						finger_data[i][2] = buf[base+6] + buf[base+7];
+						finger_data[i][3] = buf[base+5];
 					}
-					finger_data[i][2] = (buf[base+3] >> 4 & 0x0F) + (buf[base+3] & 0x0F);
-					finger_data[i][3] = buf[base+4];
 
 					if (ts->flags & SYNAPTICS_SWAP_XY)
 						swap(finger_data[i][0], finger_data[i][1]);
@@ -1666,7 +2197,7 @@
 							if (ts->finger_count == 0)
 								ts->first_pressed = 1;
 							printk(KERN_INFO "[TP] E%d@%d, %d\n", i + 1,
-							finger_data[i][0], finger_data[i][1]);
+							x_pos[i], y_pos[i]);
 						}
 					}
 #ifdef SYN_FILTER_CONTROL
@@ -1704,7 +2235,7 @@
 								ts->tap_suppression &= ~BIT(i);
 							} else {
 								finger_pressed &= ~BIT(i);
-								if (ts->debug_log_level & (BIT(1) | BIT(3)))
+								if (ts->debug_log_level & BIT(1))
 									printk(KERN_INFO
 										"[TP] Filtered Finger %d=> X:%d, Y:%d w:%d, z:%d\n",
 										i + 1, finger_data[i][0], finger_data[i][1],
@@ -1714,57 +2245,60 @@
 					}
 
 					if ((finger_pressed & BIT(i)) == BIT(i)) {
-						finger_pressed &= ~BIT(i);
-
-						if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
-							if (ts->support_htc_event) {
+						if (ts->block_touch_event == 0) {
+							if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
+								if (ts->support_htc_event) {
+									input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
+										finger_data[i][3] << 16 | finger_data[i][2]);
+									input_report_abs(ts->input_dev, ABS_MT_POSITION,
+										(finger_pressed == 0) << 31 |
+										finger_data[i][0] << 16 | finger_data[i][1]);
+								}
+								input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
+								input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+									finger_data[i][3]);
+								input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+									finger_data[i][2]);
+								input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+									finger_data[i][2]);
+								input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+									finger_data[i][0]);
+								input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+									finger_data[i][1]);
+								input_mt_sync(ts->input_dev);
+							} else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
+								if (ts->support_htc_event) {
+									input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
+										finger_data[i][3] << 16 | finger_data[i][2]);
+									input_report_abs(ts->input_dev, ABS_MT_POSITION,
+										(finger_pressed == 0) << 31 |
+										finger_data[i][0] << 16 | finger_data[i][1]);
+								}
+								input_mt_slot(ts->input_dev, i);
+								input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
+								1);
+								input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+									finger_data[i][3]);
+								input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+									finger_data[i][2]);
+								input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+									finger_data[i][2]);
+								input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+									finger_data[i][0]);
+								input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+									finger_data[i][1]);
+							} else if (ts->htc_event == SYN_AND_REPORT_TYPE_HTC) {
+								input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
 								input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
 									finger_data[i][3] << 16 | finger_data[i][2]);
 								input_report_abs(ts->input_dev, ABS_MT_POSITION,
 									(finger_pressed == 0) << 31 |
 									finger_data[i][0] << 16 | finger_data[i][1]);
 							}
-							input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
-							input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-								finger_data[i][3]);
-							input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-								finger_data[i][2]);
-							input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-								finger_data[i][2]);
-							input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-								finger_data[i][0]);
-							input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-								finger_data[i][1]);
-							input_mt_sync(ts->input_dev);
-						} else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
-							if (ts->support_htc_event) {
-								input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
-									finger_data[i][3] << 16 | finger_data[i][2]);
-								input_report_abs(ts->input_dev, ABS_MT_POSITION,
-									(finger_pressed == 0) << 31 |
-									finger_data[i][0] << 16 | finger_data[i][1]);
-							}
-							input_mt_slot(ts->input_dev, i);
-							input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
-							1);
-							input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-								finger_data[i][3]);
-							input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-								finger_data[i][2]);
-							input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-								finger_data[i][2]);
-							input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-								finger_data[i][0]);
-							input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-								finger_data[i][1]);
-						} else if (ts->htc_event == SYN_AND_REPORT_TYPE_HTC) {
-							input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
-							input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE,
-								finger_data[i][3] << 16 | finger_data[i][2]);
-							input_report_abs(ts->input_dev, ABS_MT_POSITION,
-								(finger_pressed == 0) << 31 |
-								finger_data[i][0] << 16 | finger_data[i][1]);
 						}
+						x_pos[i] = finger_data[i][0];
+						y_pos[i] = finger_data[i][1];
+						finger_pressed &= ~BIT(i);
 
 						if ((finger_press_changed & BIT(i)) && ts->debug_log_level & BIT(3)) {
 							if(ts->width_factor && ts->height_factor){
@@ -1779,6 +2313,8 @@
 									i+1, finger_data[i][0], finger_data[i][1],
 									finger_data[i][2], finger_data[i][3]);
 							}
+							if ((ts->block_touch_time_near | ts->block_touch_time_far) && ts->block_touch_event)
+								printk(KERN_INFO "[TP] Block This Event!!\n");
 						}
 
 						if (ts->pre_finger_data[0][0] < 2) {
@@ -1790,6 +2326,20 @@
 									printk(KERN_INFO "[TP] S%d@%d, %d\n", i + 1,
 										finger_data[i][0], finger_data[i][1]);
 								if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
+#ifdef SYN_CALIBRATION_CONTROL
+									if (ts->multitouch_calibration) {
+										if (ts->finger_count == ts->finger_support) {
+											if (ts->package_id < 3400) {
+												ret = i2c_syn_write_byte_data(ts->client,
+													get_address_base(ts, ts->finger_func_idx, COMMAND_BASE), 0x01);
+												if (ret < 0)
+													i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:Rezero_1", __func__);
+												printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+											}
+										} else if (!ts->pre_finger_data[0][0] && ts->finger_count > 1)
+											ts->pre_finger_data[0][0] = 1;
+									}
+#endif
 								}
 							}
 						}
@@ -1807,14 +2357,38 @@
 
 						if (ts->debug_log_level & BIT(1))
 							printk(KERN_INFO
-								"[TP] Finger %d=> X:%d, Y:%d w:%d, z:%d\n",
+								"[TP] Finger %d=> X:%d, Y:%d W:%d, Z:%d\n",
 								i + 1, finger_data[i][0], finger_data[i][1],
 								finger_data[i][2], finger_data[i][3]);
+						if (ts->debug_log_level & BIT(17))
+							printk(KERN_INFO
+								"[TP] Finger %d=> X:%d, Y:%d W:%d, Z:%d, IM:%d, CIDIM:%d, Freq:%d, NS:%d\n",
+								i + 1, finger_data[i][0], finger_data[i][1], finger_data[i][2],
+								finger_data[i][3], noise_index[1] | noise_index[0],
+								noise_index[6] | noise_index[5], noise_index[9], noise_index[4]);
+					}
+					if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
+#ifdef SYN_CALIBRATION_CONTROL
+						if (ts->multitouch_calibration) {
+							if ((finger_release_changed & BIT(i)) && ts->pre_finger_data[0][0] == 1) {
+								if (ts->package_id < 3400) {
+									ret = i2c_syn_write_byte_data(ts->client,
+										get_address_base(ts, ts->finger_func_idx, COMMAND_BASE), 0x01);
+									if (ret < 0)
+										i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:Rezero_2", __func__);
+									printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+								}
+							}
+						}
+#endif
 					}
 					if (!ts->finger_count)
 						ts->pre_finger_data[0][0] = 0;
 				}
-				base += 5;
+				if (ts->package_id < 3400)
+					base += 5;
+				else
+					base += 8;
 			}
 #ifdef SYN_FILTER_CONTROL
 			if (ts->filter_level[0] && ts->grip_suppression) {
@@ -1862,89 +2436,58 @@
 static void synaptics_ts_button_func(struct synaptics_ts_data *ts)
 {
 	int ret;
-	uint8_t data = 0;
+	uint8_t data = 0, idx = 0;
 	uint16_t x_position = 0, y_position = 0;
 
 	ret = i2c_syn_read(ts->client,
 		get_address_base(ts, 0x1A, DATA_BASE), &data, 1);
 	if (data) {
-		if (data & 0x01) {
-			printk("[TP] back key pressed\n");
-			vk_press = 1;
-			if (ts->button) {
-				if (ts->button[0].index) {
-					x_position = (ts->button[0].x_range_min + ts->button[0].x_range_max) / 2;
-					y_position = (ts->button[0].y_range_min + ts->button[0].y_range_max) / 2;
-				}
+		vk_press = 1;
+		if (ts->button) {
+			idx =	(data == 0x01 ? 0:
+				 data == 0x02 ? 1:
+				 data == 0x04 ? 2:
+				 100);
+
+			if (idx == 100) {
+				vk_press = 0;
+				pr_err("[TP] vk_data:%#x, idx=%d", data, idx);
+				return;
 			}
-			if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
-				input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
-				input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-					x_position);
-				input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-					y_position);
-				input_mt_sync(ts->input_dev);
-			} else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
-				input_mt_slot(ts->input_dev, 0);
-				input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
-				1);
-				input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-					x_position);
-				input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-					y_position);
-			}
+			x_position = (ts->button[idx].x_range_min + ts->button[idx].x_range_max) / 2;
+			y_position = (ts->button[idx].y_range_min + ts->button[idx].y_range_max) / 2;
 		}
-		else if (data & 0x02) {
-			printk("[TP] home key pressed\n");
-			vk_press = 1;
-			if (ts->button) {
-				if (ts->button[1].index) {
-					x_position = (ts->button[1].x_range_min + ts->button[1].x_range_max) / 2;
-					y_position = (ts->button[1].y_range_min + ts->button[1].y_range_max) / 2;
-				}
-			}
-			if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
-				input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
-				input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-					x_position);
-				input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-					y_position);
-				input_mt_sync(ts->input_dev);
-			} else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
-				input_mt_slot(ts->input_dev, 0);
-				input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
-				1);
-				input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-					100);
-				input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-					x_position);
-				input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-					y_position);
-			}
+		data == 0x01 ? pr_info("[TP] back key pressed, vk=%x\n", data) :
+		data == 0x02 ? pr_info("[TP] home key pressed, vk=%x\n", data) :
+		data == 0x04 ? pr_info("[TP] app key pressed , vk=%x\n", data) :
+		pr_info("[TP] vk=%#x\n", data);
+
+		if (ts->support_htc_event) {
+			input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, 100 << 16 | 100);
+			input_report_abs(ts->input_dev, ABS_MT_POSITION, x_position << 16 | y_position);
 		}
-	}else {
+		switch (ts->htc_event) {
+		case SYN_AND_REPORT_TYPE_A:
+			input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
+			break;
+		case SYN_AND_REPORT_TYPE_B:
+			input_mt_slot(ts->input_dev, 0);
+			input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1);
+			break;
+	}
+		input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 100);
+		input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 100);
+		input_report_abs(ts->input_dev, ABS_MT_PRESSURE, 100);
+		input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x_position);
+		input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y_position);
+		switch (ts->htc_event) {
+		case SYN_AND_REPORT_TYPE_A:
+			input_mt_sync(ts->input_dev);
+			break;
+		case SYN_AND_REPORT_TYPE_B:
+			break;
+		}
+	} else {
 		printk("[TP] virtual key released\n");
 		vk_press = 0;
 		if (ts->htc_event == SYN_AND_REPORT_TYPE_A) {
@@ -1955,6 +2498,10 @@
 			input_mt_sync(ts->input_dev);
 		}
 		else if (ts->htc_event == SYN_AND_REPORT_TYPE_B) {
+			if (ts->support_htc_event) {
+				input_report_abs(ts->input_dev, ABS_MT_AMPLITUDE, 0);
+				input_report_abs(ts->input_dev, ABS_MT_POSITION, 1 << 31);
+			}
 			input_mt_slot(ts->input_dev, 0);
 			input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
 		}
@@ -1996,7 +2543,7 @@
 	if (ret < 0) {
 		i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r", __func__);
 	} else {
-		if (buf & get_address_base(ts, 0x11, INTR_SOURCE))
+		if (buf & get_address_base(ts, ts->finger_func_idx, INTR_SOURCE))
 			synaptics_ts_finger_func(ts);
 		if (buf & get_address_base(ts, 0x01, INTR_SOURCE))
 			synaptics_ts_status_func(ts);
@@ -2022,13 +2569,7 @@
 	if (ret < 0) {
 		i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r", __func__);
 	} else {
-		if (buf & get_address_base(ts, 0x1A, INTR_SOURCE)) {
-			if (!ts->finger_count)
-				synaptics_ts_button_func(ts);
-			else
-				printk("[TP] Ignore VK interrupt due to 2d points did not leave\n");
-		}
-		if (buf & get_address_base(ts, 0x11, INTR_SOURCE)) {
+		if (buf & get_address_base(ts, ts->finger_func_idx, INTR_SOURCE)) {
 			if (!vk_press) {
 				synaptics_ts_finger_func(ts);
 				if(ts->debug_log_level & BIT(2)) {
@@ -2039,6 +2580,12 @@
 				}
 			}
 		}
+		if (buf & get_address_base(ts, 0x1A, INTR_SOURCE)) {
+			if (!ts->finger_count)
+				synaptics_ts_button_func(ts);
+			else
+				printk("[TP] Ignore VK interrupt due to 2d points did not leave\n");
+		}
 		if (buf & get_address_base(ts, 0x01, INTR_SOURCE))
 			synaptics_ts_status_func(ts);
 		if (buf & get_address_base(ts, 0x54, INTR_SOURCE))
@@ -2065,7 +2612,7 @@
 
 	printk(KERN_INFO "[TP] Touch: cable change to %d\n", connect_status);
 
-	if (connect_status)
+	if ((connect_status > 0) || (connect_status == CONNECT_TYPE_UNKNOWN))
 		connect_status = 1;
 	ret = i2c_syn_read(ts->client, get_address_base(ts, 0x01, CONTROL_BASE), &data, 1);
 	if (ret < 0) {
@@ -2106,12 +2653,14 @@
 		ts->psensor_status, status);
 
 	if(ts->psensor_detection) {
-		if(status == 3 && ts->psensor_resume_enable >= 1) {
-			if(!(ts->psensor_status==1 && ts->psensor_resume_enable==1)) {
-				ret = i2c_syn_write_byte_data(ts->client, get_address_base(ts, 0x11, COMMAND_BASE), 0x01);
-				if (ret < 0)
-					i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:Rezero_1", __func__);
-				printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+		if((status & PSENSOR_STATUS) == 3 && ts->psensor_resume_enable >= 1) {
+			if(!((ts->psensor_status & PSENSOR_STATUS)==1 && ts->psensor_resume_enable==1)) {
+				if (ts->package_id < 3400) {
+					ret = i2c_syn_write_byte_data(ts->client, get_address_base(ts, ts->finger_func_idx, COMMAND_BASE), 0x01);
+					if (ret < 0)
+						i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "w:Rezero_1", __func__);
+					printk(KERN_INFO "[TP] %s: Touch Calibration Confirmed, rezero\n", __func__);
+				}
 			}
 
 			if(ts->psensor_resume_enable == 1)
@@ -2121,8 +2670,17 @@
 		}
 	}
 
-	if (ts->psensor_status == 0) {
-		if (status == 1)
+	if (ts->block_touch_time_near | ts->block_touch_time_far) {
+		if (status == (PHONE_STATUS | 2)) {
+			syn_handle_block_touch(ts, 1);
+		} else if (status == (PHONE_STATUS | 3) && ts->psensor_status != (PHONE_STATUS | 1)) {
+			syn_handle_block_touch(ts, 2);
+		} else if (status == (PHONE_STATUS | 0))
+			syn_handle_block_touch(ts, 0);
+	}
+
+	if ((ts->psensor_status & PSENSOR_STATUS) == 0) {
+		if ((status & PSENSOR_STATUS) == 1)
 			ts->psensor_status = status;
 		else
 			ts->psensor_status = 0;
@@ -2130,7 +2688,7 @@
 		ts->psensor_status = status;
 
 	if(ts->psensor_detection) {
-		if(ts->psensor_status == 0) {
+		if((ts->psensor_status & PSENSOR_STATUS) == 0) {
 			ts->psensor_resume_enable = 0;
 			ts->psensor_phone_enable = 0;
 		}
@@ -2163,6 +2721,11 @@
 		ts->num_function += num_function[i];
 	}
 
+	if (ts->address_table != NULL) {
+		kfree(ts->address_table);
+		ts->address_table = NULL;
+	}
+
 	if (ts->address_table == NULL) {
 		ts->address_table = kzalloc(sizeof(struct function_t) * ts->num_function, GFP_KERNEL);
 		if (ts->address_table == NULL) {
@@ -2207,6 +2770,10 @@
 		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
 	ts->package_id = data[1] << 8 | data[0];
 	printk(KERN_INFO "[TP] %s: package_id: %d\n", __func__, ts->package_id);
+	if (ts->package_id >= 3400)
+		ts->finger_func_idx = 0x12;
+	else
+		ts->finger_func_idx = 0x11;
 
 	ret = i2c_syn_read(ts->client, get_address_base(ts, 0x01, QUERY_BASE) + 18, data, 3);
 	if (ret < 0)
@@ -2244,22 +2811,33 @@
 {
 	uint8_t data[4] = {0}, i, num_channel, *buf;
 	int ret = 0;
-	ret = i2c_syn_read(ts->client, get_address_base(ts, 0x11, QUERY_BASE) + 1, data, 1);
-	if (ret < 0)
-		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
-	if ((data[0] & 0x07) == 5)
-		ts->finger_support = 10;
-	else if ((data[0] & 0x07) < 5)
-		ts->finger_support = (data[0] & 0x07) + 1;
-	else {
-		printk(KERN_INFO "[TP] %s: number of fingers not define: %x\n",
-			__func__, data[0] & 0x07);
-		return SYN_PROCESS_ERR;
+
+	if (ts->package_id < 3400) {
+		ret = i2c_syn_read(ts->client, get_address_base(ts, ts->finger_func_idx, QUERY_BASE) + 1, data, 1);
+		if (ret < 0)
+			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
+		if ((data[0] & 0x07) == 5)
+			ts->finger_support = 10;
+		else if ((data[0] & 0x07) < 5)
+			ts->finger_support = (data[0] & 0x07) + 1;
+		else {
+			printk(KERN_INFO "[TP] %s: number of fingers not define: %x\n",
+				__func__, data[0] & 0x07);
+			return SYN_PROCESS_ERR;
+		}
+	} else {
+		ret = i2c_syn_read(ts->client, get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 7, data, 2);
+		if (ret < 0)
+			return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:1", __func__);
+		ts->finger_support = data[1];
 	}
 
 	printk(KERN_INFO "[TP] %s: finger_support: %d\n", __func__, ts->finger_support);
 
-	ret = i2c_syn_read(ts->client, get_address_base(ts, 0x11, CONTROL_BASE) + 6, data, 4);
+	if (ts->package_id < 3400)
+		ret = i2c_syn_read(ts->client, get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 6, data, 4);
+	else
+		ret = i2c_syn_read(ts->client, get_address_base(ts, ts->finger_func_idx, CONTROL_BASE), data, 4);
 	if (ret < 0)
 		return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:2", __func__);
 
@@ -2321,44 +2899,50 @@
 	}
 	if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
 		if (ts->large_obj_check) {
-			if (ts->package_id == 2200) {
-				ret = i2c_syn_read(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x26, &ts->default_large_obj, 1);
-			} else {
-				ret = i2c_syn_read(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x29, &ts->default_large_obj, 1);
+			if (ts->package_id < 3400) {
+				if (ts->package_id == 2200) {
+					ret = i2c_syn_read(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x26, &ts->default_large_obj, 1);
+				} else {
+					ret = i2c_syn_read(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x29, &ts->default_large_obj, 1);
+				}
+				if (ret < 0)
+						return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:6", __func__);
+				printk(KERN_INFO "[TP] %s: ts->default_large_obj: %x\n", __func__, ts->default_large_obj);
 			}
-			if (ret < 0)
-					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:6", __func__);
-			printk(KERN_INFO "[TP] %s: ts->default_large_obj: %x\n", __func__, ts->default_large_obj);
 		}
 
 		if (ts->segmentation_bef_unlock) {
-			if (ts->package_id == 2200) {
-				ret = i2c_syn_read(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x25, &ts->segmentation_aft_unlock, 1);
+			if (ts->package_id < 3400) {
+				if (ts->package_id == 2200) {
+					ret = i2c_syn_read(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x25, &ts->segmentation_aft_unlock, 1);
 
-			} else {
-				ret = i2c_syn_read(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x22, &ts->segmentation_aft_unlock, 1);
+				} else {
+					ret = i2c_syn_read(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x22, &ts->segmentation_aft_unlock, 1);
+				}
+				if (ret < 0)
+					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:7", __func__);
+				printk(KERN_INFO "[TP] %s: ts->segmentation_aft_unlock: %x\n", __func__, ts->segmentation_aft_unlock);
 			}
-			if (ret < 0)
-				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:7", __func__);
-			printk(KERN_INFO "[TP] %s: ts->segmentation_aft_unlock: %x\n", __func__, ts->segmentation_aft_unlock);
 		}
 
 		if (ts->threshold_bef_unlock) {
-			if (ts->package_id == 2200) {
-				ret = i2c_syn_read(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x0A, &ts->threshold_aft_unlock, 1);
+			if (ts->package_id < 3400) {
+				if (ts->package_id == 2200) {
+					ret = i2c_syn_read(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0A, &ts->threshold_aft_unlock, 1);
 
-			} else {
-				ret = i2c_syn_read(ts->client,
-					get_address_base(ts, 0x11, CONTROL_BASE) + 0x0C, &ts->threshold_aft_unlock, 1);
+				} else {
+					ret = i2c_syn_read(ts->client,
+						get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0C, &ts->threshold_aft_unlock, 1);
+				}
+				if (ret < 0)
+					return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:8", __func__);
+				printk(KERN_INFO "[TP] %s: ts->z_threshold_aft_unlock: %x\n", __func__, ts->threshold_aft_unlock);
 			}
-			if (ret < 0)
-				return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "r:8", __func__);
-			printk(KERN_INFO "[TP] %s: ts->z_threshold_aft_unlock: %x\n", __func__, ts->threshold_aft_unlock);
 		}
 
 		if (ts->saturation_bef_unlock) {
@@ -2382,47 +2966,44 @@
 	return 0;
 }
 
-static int synaptics_ts_probe(
-	struct i2c_client *client, const struct i2c_device_id *id)
+static int syn_probe_init(void *arg)
 {
-	struct synaptics_ts_data *ts;
-	uint8_t i;
-	int ret = 0;
+	struct synaptics_ts_data *ts = (struct synaptics_ts_data *)arg;
 	struct synaptics_i2c_rmi_platform_data *pdata;
-	uint8_t data = 0;
+	int ret = 0;
+	uint8_t data = 0, i;
+	uint16_t wait_time = SYN_FW_TIMEOUT;
 
 	printk(KERN_INFO "[TP] %s: enter", __func__);
-	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-		printk(KERN_ERR "[TP] TOUCH_ERR: synaptics_ts_probe: need I2C_FUNC_I2C\n");
-		ret = -ENODEV;
-		goto err_check_functionality_failed;
-	}
-
-	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
-	if (ts == NULL) {
-		ret = -ENOMEM;
-		goto err_alloc_data_failed;
-	}
-	ts->client = client;
-	i2c_set_clientdata(client, ts);
-	pdata = client->dev.platform_data;
+	pdata = ts->client->dev.platform_data;
 
 	if (pdata == NULL) {
 		printk(KERN_INFO "[TP] pdata is NULL\n");
 		goto err_get_platform_data_fail;
 	}
 
-	ret = i2c_syn_read(ts->client, 0x00EE, &data, 1);
-	if (ret < 0) {
-		printk(KERN_INFO "[TP] No Synaptics chip\n");
-		goto err_detect_failed;
+	if (board_build_flag() == MFG_BUILD) {
+		wait_time = SYN_FW_TIMEOUT;
+		wait_event_interruptible_timeout(ts->syn_fw_wait, atomic_read(&ts->syn_fw_condition),
+							msecs_to_jiffies(wait_time));
+	}
+	ts->block_touch_event = 0;
+	ts->i2c_err_handler_en = pdata->i2c_err_handler_en;
+	if (ts->i2c_err_handler_en) {
+		ts->gpio_reset = pdata->gpio_reset;
+		ts->use_irq = 1;
+		if (ts->gpio_reset) {
+			ret = gpio_request(ts->gpio_reset, "synaptics_reset");
+			if (ret)
+				printk(KERN_INFO "[TP]%s: Failed to obtain reset pin: %d. Code: %d.", __func__, ts->gpio_reset, ret);
+		}
 	}
 
 	for (i = 0; i < 10; i++) {
-		ret = i2c_syn_read(ts->client, SYN_F01DATA_BASEADDR, &data, 1);
+		ret = i2c_syn_read(ts->client, get_address_base(ts, 0x01, DATA_BASE), &data, 1);
 		if (ret < 0) {
 			i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "read device status failed!", __func__);
-			goto err_detect_failed;
+			goto err_init_failed;
 		}
 		if (data & 0x44) {
 			hr_msleep(20);
@@ -2431,7 +3012,7 @@
 #endif
 		} else if (data & 0x40) {
 			printk(KERN_ERR "[TP] TOUCH_ERR: synaptics probe: F01_data: %x touch controller stay in bootloader mode!\n", data);
-			goto err_detect_failed;
+			goto err_init_failed;
 		} else
 			break;
 	}
@@ -2440,11 +3021,6 @@
 		uint8_t num = 0;
 		printk(KERN_INFO "[TP] synaptics probe: touch controller doesn't enter UI mode! F01_data: %x\n", data);
 
-		if (syn_pdt_scan(ts, SYN_BL_PAGE) < 0) {
-			printk(KERN_ERR "[TP] TOUCH_ERR: PDT scan fail\n");
-			goto err_init_failed;
-		}
-
 		if (pdata) {
 			while (pdata->default_config != 1) {
 				if (pdata->default_config == 0) {
@@ -2468,18 +3044,23 @@
 					"config version and CRC but touch controller always stay in bootloader mode\n");
 			pdata = pdata - num;
 		}
-
-		if (ts->address_table != NULL) {
-			kfree(ts->address_table);
-			ts->address_table = NULL;
-		}
 	}
 
 	if (syn_pdt_scan(ts, SYN_MAX_PAGE) < 0) {
 		printk(KERN_ERR "[TP] TOUCH_ERR: PDT scan fail\n");
 		goto err_init_failed;
 	}
+	if (board_mfg_mode() == MFG_MODE_OFFMODE_CHARGING) {
+		printk(KERN_INFO "[TP] %s: offmode charging. Set touch chip to sleep mode and skip touch driver probe\n", __func__);
+		ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x01, CONTROL_BASE), 0x01); 
+		if (ret < 0)
+			i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "sleep: 0x01", __func__);
+		ret = -ENODEV;
+		goto err_check_offmode_charging;
+	}
 
+	ts->finger_func_idx = 0x11;
 	if (syn_get_version(ts) < 0) {
 		printk(KERN_ERR "[TP] TOUCH_ERR: syn_get_version fail\n");
 		goto err_init_failed;
@@ -2489,10 +3070,13 @@
 		while (pdata->packrat_number && pdata->packrat_number > ts->packrat_number) {
 			pdata++;
 		}
-
 		if (pdata->tw_pin_mask) {
 			ts->tw_pin_mask = pdata->tw_pin_mask;
-			ret = syn_get_tw_vendor(ts, pdata->gpio_irq);
+			for (i=0; i<SYN_UPDATE_RETRY_TIMES; i++) {
+				ret = syn_get_tw_vendor(ts, pdata->gpio_irq);
+				if (ret == 0)
+					break;
+			}
 			if (ret < 0) {
 				printk(KERN_ERR "[TP] TOUCH_ERR: syn_get_tw_vendor fail\n");
 				goto err_init_failed;
@@ -2502,7 +3086,6 @@
 		while (pdata->sensor_id > 0 && pdata->sensor_id != (SENSOR_ID_CHECKING_EN | ts->tw_vendor)) {
 			pdata++;
 		}
-
 		printk(KERN_INFO "[TP] synaptics_ts_probe: pdata->version = %x, pdata->packrat_number = %d,"
 				" pdata->sensor_id = %x\n", pdata->version, pdata->packrat_number, pdata->sensor_id);
 
@@ -2512,6 +3095,7 @@
 		}
 
 		ts->power = pdata->power;
+		ts->lpm_power = pdata->lpm_power;
 		ts->flags = pdata->flags;
 		ts->htc_event = pdata->report_type;
 		ts->filter_level = pdata->filter_level;
@@ -2529,6 +3113,8 @@
 		ts->multitouch_calibration = pdata->multitouch_calibration;
 		ts->psensor_detection = pdata->psensor_detection;
 		ts->PixelTouchThreshold_bef_unlock = pdata->PixelTouchThreshold_bef_unlock;
+		ts->block_touch_time_near = pdata->block_touch_time_near;
+		ts->block_touch_time_far = pdata->block_touch_time_far;
 #ifdef SYN_CABLE_CONTROL
 		ts->cable_support = pdata->cable_support; 
 #endif
@@ -2538,7 +3124,11 @@
 	}
 
 #ifndef SYN_DISABLE_CONFIG_UPDATE
-	ret = syn_config_update(ts, pdata->gpio_irq);
+	for (i=0; i<SYN_UPDATE_RETRY_TIMES; i++) {
+		ret = syn_config_update(ts, pdata->gpio_irq);
+		if (ret >= 0)
+			break;
+	}
 	if (ret < 0) {
 		printk(KERN_ERR "[TP] TOUCH_ERR: syn_config_update fail\n");
 		goto err_init_failed;
@@ -2640,22 +3230,22 @@
 	gl_ts = ts;
 
 	ts->irq_enabled = 0;
-	if (client->irq) {
+	if (ts->client->irq) {
 		ts->use_irq = 1;
-		ret = request_threaded_irq(client->irq, NULL, synaptics_irq_thread,
-			IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts);
+		ret = request_threaded_irq(ts->client->irq, NULL, synaptics_irq_thread,
+			IRQF_TRIGGER_LOW | IRQF_ONESHOT, ts->client->name, ts);
 		if (ret == 0) {
 			ts->irq_enabled = 1;
 			ret = i2c_syn_read(ts->client,
 				get_address_base(ts, 0x01, CONTROL_BASE) + 1, &ts->intr_bit, 1);
 			if (ret < 0) {
-				free_irq(client->irq, ts);
+				free_irq(ts->client->irq, ts);
 				i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "get interrupt bit failed", __func__);
 				goto err_get_intr_bit_failed;
 			}
 			printk(KERN_INFO "[TP] %s: interrupt enable: %x\n", __func__, ts->intr_bit);
 		} else {
-			dev_err(&client->dev, "[TP] TOUCH_ERR: request_irq failed\n");
+			dev_err(&ts->client->dev, "[TP] TOUCH_ERR: request_irq failed\n");
 			ts->use_irq = 0;
 		}
 	}
@@ -2685,7 +3275,7 @@
 		usb_register_notifier(&cable_status_handler);
 		
 		ret = i2c_syn_read(ts->client,
-			get_address_base(ts, 0x11, CONTROL_BASE), &ts->cable_config, 1);
+			get_address_base(ts, ts->finger_func_idx, CONTROL_BASE), &ts->cable_config, 1);
 		if (ret < 0) {
 			printk(KERN_ERR "[TP] TOUCH_ERR: get cable config failed\n");
 			goto err_get_cable_config_failed;
@@ -2728,12 +3318,71 @@
 	if(ts->temp_report_data != NULL)
 		kfree(ts->temp_report_data);
 err_init_failed:
+err_check_offmode_charging:
 	if(ts->address_table != NULL)
 		kfree(ts->address_table);
-err_detect_failed:
 err_get_platform_data_fail:
 	kfree(ts);
 
+	return ret;
+}
+
+static int synaptics_ts_probe(
+	struct i2c_client *client, const struct i2c_device_id *id)
+{
+	struct synaptics_ts_data *ts;
+	struct synaptics_i2c_rmi_platform_data *pdata;
+	int ret = 0;
+	uint8_t data = 0;
+
+	printk(KERN_INFO "[TP] %s: enter", __func__);
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		printk(KERN_ERR "[TP] TOUCH_ERR: synaptics_ts_probe: need I2C_FUNC_I2C\n");
+		ret = -ENODEV;
+		goto err_check_functionality_failed;
+	}
+
+	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+	if (ts == NULL) {
+		ret = -ENOMEM;
+		goto err_alloc_data_failed;
+	}
+	ts->client = client;
+	i2c_set_clientdata(client, ts);
+	pdata = client->dev.platform_data;
+
+	if (pdata == NULL) {
+		printk(KERN_INFO "[TP] pdata is NULL\n");
+		goto err_get_platform_data_fail;
+	}
+
+	ret = i2c_syn_read(ts->client, 0x00EE, &data, 1);
+	if (ret < 0) {
+		printk(KERN_INFO "[TP] No Synaptics chip\n");
+		goto err_detect_failed;
+	}
+	if (syn_pdt_scan(ts, SYN_BL_PAGE) < 0) {
+		printk(KERN_ERR "[TP] TOUCH_ERR: PDT scan fail\n");
+		goto err_detect_failed;
+	}
+	if (board_build_flag() == MFG_BUILD) {
+		ts->gpio_irq = pdata->gpio_irq;
+		if (syn_get_version(ts) < 0) {
+			printk(KERN_ERR "[TP] TOUCH_ERR: syn_get_version fail\n");
+			goto err_detect_failed;
+		}
+
+		init_waitqueue_head(&ts->syn_fw_wait);
+		atomic_set(&ts->syn_fw_condition, 0);
+		kthread_run(syn_fw_update_init, (void *)ts, "SYN_FW_UPDATE");
+	}
+
+	kthread_run(syn_probe_init, (void *)ts, "SYN_PROBE_INIT");
+	return 0;
+
+err_detect_failed:
+err_get_platform_data_fail:
+	kfree(ts);
 err_alloc_data_failed:
 err_check_functionality_failed:
 	return ret;
@@ -2768,7 +3417,8 @@
 
 static int synaptics_ts_suspend(struct i2c_client *client, pm_message_t mesg)
 {
-	int ret;
+	int ret = 0;
+	uint8_t data = 0, update = 0;
 	struct synaptics_ts_data *ts = i2c_get_clientdata(client);
 	printk(KERN_INFO "[TP] %s: enter\n", __func__);
 
@@ -2788,69 +3438,175 @@
 		}
 	}
 
-	if (ts->psensor_status == 0) {
+	if ((ts->psensor_status & PSENSOR_STATUS) == 0) {
 		ts->pre_finger_data[0][0] = 0;
 		if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT) {
 			ts->first_pressed = 0;
+#ifdef SYN_CALIBRATION_CONTROL
+			if (ts->mfg_flag != 1) {
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x10, ts->relaxation);
+				if (ret < 0)
+					i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "fast relaxation", __func__);
+
+				if (ts->energy_ratio_relaxation) {
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, 0x54, CONTROL_BASE), 0x20);
+					if (ret < 0)
+						i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "energy ratio relaxation", __func__);
+				}
+
+				if (ts->saturation_bef_unlock) {
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, 0x54, CONTROL_BASE) + 0x02, ts->saturation_bef_unlock & 0xFF);
+					if (ret < 0)
+						return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "saturation capacitance", __func__);
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, 0x54, CONTROL_BASE) + 0x03, (ts->saturation_bef_unlock & 0xFF00) >> 8);
+					if (ret < 0)
+						return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "saturation capacitance", __func__);
+					printk(KERN_INFO "[TP] touch suspend, saturation capacitance: %x\n", ts->saturation_bef_unlock);
+				}
+
+				if ( ts->PixelTouchThreshold_bef_unlock ) {
+					if (ts->package_id <= 3400 ) {
+						ret = i2c_syn_write_byte_data(ts->client,
+							get_address_base(ts, 0x54, CONTROL_BASE) + 0x04, ts->PixelTouchThreshold_bef_unlock );
+						if (ret < 0)
+							return i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "F54_ANALOG_CTRL03 Pixel Touch Threshold", __func__);
+						printk(KERN_INFO "[TP] touch suspend, set F54_ANALOG_CTRL03 Pixel Touch Threshold: %x\n", ts->PixelTouchThreshold_bef_unlock);
+					}
+				}
+
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+				if (ret < 0)
+					i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "force update", __func__);
+				printk(KERN_INFO "[TP] touch suspend, fast relasxation: %x\n", ts->relaxation);
+			}
+#endif
 
 			if (ts->large_obj_check) {
-				if (ts->package_id == 2200) {
-					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x26, ts->default_large_obj & 0x7F);
+				if (ts->package_id < 3400) {
+					if (ts->package_id == 2200) {
+						ret = i2c_syn_write_byte_data(ts->client,
+							get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x26, ts->default_large_obj & 0x7F);
 
-				} else {
-					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x29, ts->default_large_obj & 0x7F);
+					} else {
+						ret = i2c_syn_write_byte_data(ts->client,
+							get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x29, ts->default_large_obj & 0x7F);
+					}
+					if (ret < 0)
+						i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "large obj suppression", __func__);
+					printk(KERN_INFO "[TP] touch suspend, set large obj suppression: %x\n", ts->default_large_obj & 0x7F);
 				}
-				if (ret < 0)
-					i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "large obj suppression", __func__);
-				printk(KERN_INFO "[TP] touch suspend, set large obj suppression: %x\n", ts->default_large_obj & 0x7F);
 			}
 
 			if (ts->segmentation_bef_unlock) {
-				if (ts->package_id == 2200) {
-					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x25, ts->segmentation_bef_unlock);
-				} else {
-					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x22, ts->segmentation_bef_unlock);
+				if (ts->package_id < 3400) {
+					if (ts->package_id == 2200) {
+						ret = i2c_syn_write_byte_data(ts->client,
+							get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x25, ts->segmentation_bef_unlock);
+					} else {
+						ret = i2c_syn_write_byte_data(ts->client,
+							get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x22, ts->segmentation_bef_unlock);
+					}
+					if (ret < 0)
+						i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "segmentation aggressiveness", __func__);
+					printk(KERN_INFO "[TP] touch suspend, set segmentation aggressiveness: %x\n", ts->segmentation_bef_unlock);
 				}
-				if (ret < 0)
-					i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "segmentation aggressiveness", __func__);
-				printk(KERN_INFO "[TP] touch suspend, set segmentation aggressiveness: %x\n", ts->segmentation_bef_unlock);
 			}
 
 			if (ts->threshold_bef_unlock) {
-				if (ts->package_id == 2200) {
-					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x0A, ts->threshold_bef_unlock);
+				if (ts->package_id < 3400) {
+					if (ts->package_id == 2200) {
+						ret = i2c_syn_write_byte_data(ts->client,
+							get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0A, ts->threshold_bef_unlock);
 
-				} else {
-					ret = i2c_syn_write_byte_data(ts->client,
-						get_address_base(ts, 0x11, CONTROL_BASE) + 0x0C, ts->threshold_bef_unlock);
+					} else {
+						ret = i2c_syn_write_byte_data(ts->client,
+							get_address_base(ts, ts->finger_func_idx, CONTROL_BASE) + 0x0C, ts->threshold_bef_unlock);
+					}
+					if (ret < 0)
+						i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "Z Touch threshold", __func__);
+					printk(KERN_INFO "[TP] touch suspend, set Z Touch threshold: %x\n", ts->threshold_bef_unlock);
 				}
-				if (ret < 0)
-					i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "Z Touch threshold", __func__);
-				printk(KERN_INFO "[TP] touch suspend, set Z Touch threshold: %x\n", ts->threshold_bef_unlock);
 			}
 		}
 	}
 	else if(ts->psensor_detection)
 		ts->psensor_phone_enable = 1;
 
+#ifdef CONFIG_PWRKEY_STATUS_API
 	if (ts->packrat_number < SYNAPTICS_FW_NOCAL_PACKRAT)
 		printk(KERN_INFO "[TP][PWR][STATE] get power key state = %d\n", getPowerKeyState());
+#endif
+	if (ts->disable_CBC) {
+		if (ts->package_id < 3400) {
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, &data, 1);
+			if ((data & 0x10) == 0) {
+				printk(KERN_INFO "[TP] %s: CBC disabled : %d", __func__, ts->package_id);
+				data |= 0x10;
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x07, data);
+				update = 1;
+			}
+		} else {
+			ret = i2c_syn_read(ts->client,
+				get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, &data, 1);
+			if ((data & 0x20) == 0) {
+				printk(KERN_INFO "[TP] %s: CBC disabled : %d", __func__, ts->package_id);
+				data |= 0x20;
+				ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x1E, data);
+				update = 1;
+			}
+		}
+		if (ts->button) {
+			if (ts->package_id < 3400) {
+				ret = i2c_syn_read(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, &data, 1);
+				if ((data & 0x10) == 0) {
+					printk(KERN_INFO "[TP] %s: 0D CBC disabled : %d", __func__, ts->package_id);
+					data |= 0x10;
+					ret = i2c_syn_write_byte_data(ts->client,
+						get_address_base(ts, 0x54, CONTROL_BASE) + 0x56, data);
+					update = 1;
+				}
+			} else {
+				ret = i2c_syn_read(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, &data, 1);
+				if ((data & 0x10) == 0) {
+					printk(KERN_INFO "[TP] %s: 0D CBC disabled : %x", __func__, ts->package_id);
+					data |= 0x10;
+					ret = i2c_syn_write_byte_data(ts->client,
+					get_address_base(ts, 0x54, CONTROL_BASE) + 0x19, data);
+					update = 1;
+				}
+			}
+		}
+		if (update) {
+			ret = i2c_syn_write_byte_data(ts->client,
+				get_address_base(ts, 0x54, COMMAND_BASE), 0x04);
+		}
+		ts->disable_CBC = 0;
+	}
 
 	if (ts->power)
 		ts->power(0);
 	else {
-		if (ts->packrat_number >= SYNAPTICS_FW_NOCAL_PACKRAT) {
+		if (ts->packrat_number >= SYNAPTICS_FW_2IN1_PACKRAT) {
 			ret = i2c_syn_write_byte_data(client,
-					get_address_base(ts, 0x01, CONTROL_BASE), 0x01); 
+				get_address_base(ts, 0x01, CONTROL_BASE), 0x01); 
 			if (ret < 0)
 				i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "sleep: 0x01", __func__);
 		} else {
-			if (ts->psensor_status > 0 && getPowerKeyState() == 0) {
+			if ((ts->psensor_status & PSENSOR_STATUS) > 0
+#ifdef CONFIG_PWRKEY_STATUS_API
+			&& getPowerKeyState() == 0
+#endif
+			 ) {
 				ret = i2c_syn_write_byte_data(client,
 					get_address_base(ts, 0x01, CONTROL_BASE), 0x02); 
 				if (ret < 0)
@@ -2862,7 +3618,14 @@
 					i2c_syn_error_handler(ts, ts->i2c_err_handler_en, "sleep: 0x01", __func__);
 			}
 		}
+		if (ts->lpm_power)
+			ts->lpm_power(1);
 	}
+
+	if ((ts->block_touch_time_near | ts->block_touch_time_far) && ts->block_touch_event) {
+		syn_handle_block_touch(ts, 0);
+	}
+
 	return 0;
 }
 
@@ -2883,6 +3646,8 @@
 		}
 #endif
 	} else {
+		if (ts->lpm_power)
+			ts->lpm_power(0);
 		ret = i2c_syn_write_byte_data(client,
 			get_address_base(ts, 0x01, CONTROL_BASE), 0x00); 
 		if (ret < 0)
@@ -2902,13 +3667,13 @@
 		input_report_abs(ts->input_dev, ABS_MT_POSITION, 1 << 31);
 	}
 	if (ts->psensor_detection) {
-		if(ts->psensor_status == 0) {
+		if((ts->psensor_status & PSENSOR_STATUS) == 0) {
 			ts->psensor_resume_enable = 1;
 			printk(KERN_INFO "[TP] %s: Enable P-sensor by Touch\n", __func__);
 			psensor_enable_by_touch_driver(1);
 		}
 		else if(ts->psensor_phone_enable == 0) {
-			if(ts->psensor_status != 3)
+			if((ts->psensor_status & PSENSOR_STATUS) != 3)
 				ts->psensor_resume_enable = 2;
 
 			ts->psensor_phone_enable = 1;
@@ -2959,9 +3724,15 @@
 	},
 };
 
+static void __devinit synaptics_ts_init_async(void *unused, async_cookie_t cookie)
+{
+	i2c_add_driver(&synaptics_ts_driver);
+}
+
 static int __devinit synaptics_ts_init(void)
 {
-	return i2c_add_driver(&synaptics_ts_driver);
+	async_schedule(synaptics_ts_init_async, NULL);
+	return 0;
 }
 
 static void __exit synaptics_ts_exit(void)
diff --git a/include/linux/synaptics_i2c_rmi.h b/include/linux/synaptics_i2c_rmi.h
index e66d982..cb54bdb 100644
--- a/include/linux/synaptics_i2c_rmi.h
+++ b/include/linux/synaptics_i2c_rmi.h
@@ -25,6 +25,7 @@
 #define SYNAPTICS_3200_NAME "synaptics-3200"
 #define SYNAPTICS_FW_3_2_PACKRAT 1115999
 #define SYNAPTICS_FW_NOCAL_PACKRAT 1293981
+#define SYNAPTICS_FW_2IN1_PACKRAT 1396865
 
 
 #define SYN_CONFIG_SIZE 32 * 16
@@ -50,6 +51,8 @@
 #define CUS_LIFT_CTRL		3
 
 #define SENSOR_ID_CHECKING_EN	1 << 16
+#define PSENSOR_STATUS		0x03
+#define PHONE_STATUS		0x04
 
 enum {
 	SYNAPTICS_FLIP_X = 1UL << 0,
@@ -80,6 +83,7 @@
 				/* If non-zero another array entry follows */
 	int (*power)(int on);	/* Only valid in first array entry */
 #ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_3K
+	int (*lpm_power)(int on);
 	struct synaptics_virtual_key *virtual_key;
 	uint8_t virtual_key_num;
 	struct kobject *vk_obj;
@@ -146,6 +150,8 @@
 	uint8_t multitouch_calibration;
 	uint8_t psensor_detection;
 	uint8_t PixelTouchThreshold_bef_unlock;
+	uint8_t block_touch_time_near;
+	uint8_t block_touch_time_far;
 #endif
 };