input: touchscreen: add raydium touch driver

Supports Raydium WT030 controllers.

Change-Id: I7a98769b1e4f410e8f413a2dcc5bbc57e25f88d0
Signed-off-by: gary-rad-ic <gary.wu@rad-ic.com>
Git-commit: b18c8702a86c87acc232f1d535e208228b551883
Git-repo: https://source.codeaurora.org/quic/la/kernel/msm-4.9/commit/?h=gary-rad-ic/CAF
[vvalluru@codeaurora.org: removed LICENSE, README.md and updated commit text]
Signed-off-by: Venkata Prahlad Valluru <vvalluru@codeaurora.org>
diff --git a/drivers/input/touchscreen/raydium_wt030/Makefile b/drivers/input/touchscreen/raydium_wt030/Makefile
new file mode 100644
index 0000000..d97f4550
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the touchscreen raydium drivers.
+#
+obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_driver.o raydium_sysfs.o raydium_fw_update.o 
+
+obj-$(CONFIG_TOUCHSCREEN_RM_TS_SELFTEST) += drv_interface.o raydium_selftest.o chip_raydium/ic_drv_global.o chip_raydium/ic_drv_interface.o drv_interface.o chip_raydium/f302_ic_control.o chip_raydium/f302_ic_test.o
diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_driver.c b/drivers/input/touchscreen/raydium_wt030/raydium_driver.c
new file mode 100644
index 0000000..d040ae2
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_driver.c
@@ -0,0 +1,2292 @@
+/* drivers/input/touchscreen/raydium_wt030/raydium_driver.c
+ *
+ * Raydium TouchScreen driver.
+ *
+ * Copyright (c) 2010  Raydium tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/device.h>
+#include <linux/kprobes.h>
+#include <asm/traps.h>
+#include <linux/firmware.h>
+#include <linux/of_gpio.h>
+#include "raydium_driver.h"
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif /*end of CONFIG_FB*/
+
+struct raydium_slot_status {
+	unsigned char pt_id;      /*Occupied point ID*/
+	unsigned char need_update;         /*Mark as info need to be updated*/
+	unsigned char pt_report_offset;    /*point info offset in report*/
+};
+/*The first 3 elements are currently occupied. therest is new coming points*/
+struct raydium_slot_status gst_slot[MAX_TOUCH_NUM * 2];
+struct raydium_slot_status gst_slot_init = {0xFF, 0, 0};
+
+#if (defined(CONFIG_RM_SYSFS_DEBUG))
+const struct attribute_group raydium_attr_group;
+#endif /*end of CONFIG_RM_SYSFS_DEBUG*/
+
+unsigned char g_u8_addr;
+unsigned char g_u8_raydium_flag;
+unsigned char g_u8_i2c_mode;
+unsigned char g_u8_upgrade_type;
+unsigned char g_u8_raw_data_type;
+unsigned int g_u32_raw_data_len;    /* 72 bytes*/
+unsigned long g_u32_addr;
+unsigned int g_u32_length;
+unsigned int g_u32_driver_version;
+unsigned char *g_rad_fw_image, *g_rad_init_image;
+unsigned char *g_rad_boot_image, *g_rad_para_image;
+unsigned char *g_rad_testfw_image, *g_rad_testpara_image;
+unsigned char g_u8_table_setting, g_u8_table_init;
+unsigned char g_u8_resetflag;
+#ifdef ESD_SOLUTION_EN
+unsigned char g_u8_checkflag;
+#endif
+#ifdef ENABLE_DUMP_DATA
+unsigned char g_u8_dumpcount;
+unsigned char g_u8_dump_flag;
+unsigned char g_u8_palm_flag;
+unsigned long timeout;
+#endif
+struct raydium_ts_data *g_raydium_ts;
+/*******************************************************************************
+*  Name: raydium_variable_init
+*  Brief:
+*  Input:
+*  Output:
+*  Return:
+*******************************************************************************/
+static void raydium_variable_init(void)
+{
+	g_u8_addr = RAYDIUM_PDA2_PDA_CFG_ADDR;
+	g_u8_raydium_flag = 0;
+	g_u8_i2c_mode = PDA2_MODE;
+	g_u8_upgrade_type = 0;
+	g_u8_raw_data_type = RAYDIUM_FT_UPDATE;
+	g_u32_raw_data_len = 36 * 2;    /* 72 bytes*/
+	g_u32_addr = RAD_CHK_I2C_CMD;
+	g_u32_length = 1;
+	g_u8_table_setting = 0;
+	g_u8_table_init = 0;
+	g_rad_fw_image = NULL;
+	g_rad_init_image = NULL;
+	g_rad_boot_image = NULL;
+	g_rad_para_image = NULL;
+	g_rad_testfw_image = NULL;
+	g_rad_testpara_image = NULL;
+	g_u32_driver_version = ((RAD_MAIN_VERSION <<  24) |
+				(RAD_MINOR_VERSION << 16) |
+				(RAD_CUSTOMER_VERSION));
+	g_u8_resetflag = false;
+#ifdef ESD_SOLUTION_EN
+	g_u8_checkflag = false;
+#endif
+#ifdef ENABLE_DUMP_DATA
+	g_u8_dumpcount = 0;
+	g_u8_dump_flag = false;
+	g_u8_palm_flag = false;
+#endif
+}
+
+
+/*******************************************************************************
+*  Name: raydium_gpio_configure
+*  Brief:
+*  Input:
+*  Output:
+*  Return:
+*******************************************************************************/
+
+static int raydium_gpio_configure(bool on)
+{
+	int i32_err = 0;
+
+	if (on) {
+		if (gpio_is_valid(g_raydium_ts->irq_gpio)) {
+			i32_err = gpio_request(g_raydium_ts->irq_gpio,
+					   "raydium_irq_gpio");
+			if (i32_err) {
+				dev_err(&g_raydium_ts->client->dev,
+					"[touch]irq gpio request failed");
+				goto err_irq_gpio_req;
+			}
+
+			i32_err = gpio_direction_input(g_raydium_ts->irq_gpio);
+			if (i32_err) {
+				dev_err(&g_raydium_ts->client->dev,
+					"[touch]set_direction for irq gpio failed\n");
+				goto err_irq_gpio_dir;
+			}
+		}
+		if (gpio_is_valid(g_raydium_ts->rst_gpio)) {
+			i32_err = gpio_request(g_raydium_ts->rst_gpio,
+					   "raydium_rst_gpio");
+			if (i32_err) {
+				dev_err(&g_raydium_ts->client->dev,
+					"[touch]rst gpio request failed");
+				goto err_irq_gpio_req;
+			}
+
+			i32_err = gpio_direction_output(g_raydium_ts->rst_gpio, 1);
+			if (i32_err) {
+				dev_err(&g_raydium_ts->client->dev,
+					"[touch]set_direction for irq gpio failed\n");
+				goto err_rst_gpio_dir;
+			}
+		}
+	} else {
+		if (gpio_is_valid(g_raydium_ts->irq_gpio))
+			gpio_free(g_raydium_ts->irq_gpio);
+	}
+	return 0;
+err_rst_gpio_dir:
+	if (gpio_is_valid(g_raydium_ts->rst_gpio))
+		gpio_free(g_raydium_ts->rst_gpio);
+	return i32_err;
+err_irq_gpio_dir:
+	if (gpio_is_valid(g_raydium_ts->irq_gpio))
+		gpio_free(g_raydium_ts->irq_gpio);
+err_irq_gpio_req:
+	return i32_err;
+}
+
+/*******************************************************************************
+*  Name: raydium_ts_pinctrl_init
+*  Brief:
+*  Input:
+*  Output:
+*  Return:
+*******************************************************************************/
+#ifdef MSM_NEW_VER
+static int raydium_ts_pinctrl_init(void)
+{
+	int i32_ret;
+
+	/* Get pinctrl if target uses pinctrl */
+	g_raydium_ts->ts_pinctrl = devm_pinctrl_get(&(g_raydium_ts->client->dev));
+	if (IS_ERR_OR_NULL(g_raydium_ts->ts_pinctrl)) {
+		i32_ret = PTR_ERR(g_raydium_ts->ts_pinctrl);
+		pr_err("[touch]target does not use pinctrl %d\n", i32_ret);
+		goto err_pinctrl_get;
+	}
+
+	g_raydium_ts->pinctrl_state_active
+		= pinctrl_lookup_state(g_raydium_ts->ts_pinctrl, PINCTRL_STATE_ACTIVE);
+	if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_active)) {
+		i32_ret = PTR_ERR(g_raydium_ts->pinctrl_state_active);
+		pr_err("[touch]Can not lookup %s pinstate %d\n",
+			PINCTRL_STATE_ACTIVE, i32_ret);
+		goto err_pinctrl_lookup;
+	}
+
+	g_raydium_ts->pinctrl_state_suspend
+		= pinctrl_lookup_state(g_raydium_ts->ts_pinctrl,
+				       PINCTRL_STATE_SUSPEND);
+	if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_suspend)) {
+		i32_ret = PTR_ERR(g_raydium_ts->pinctrl_state_suspend);
+		pr_err("[touch]Can not lookup %s pinstate %d\n",
+			PINCTRL_STATE_SUSPEND, i32_ret);
+		goto err_pinctrl_lookup;
+	}
+
+	g_raydium_ts->pinctrl_state_release
+		= pinctrl_lookup_state(g_raydium_ts->ts_pinctrl,
+				       PINCTRL_STATE_RELEASE);
+	if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_release)) {
+		i32_ret = PTR_ERR(g_raydium_ts->pinctrl_state_release);
+		pr_err("[touch]Can not lookup %s pinstate %d\n",
+			PINCTRL_STATE_RELEASE, i32_ret);
+	}
+
+	return 0;
+
+err_pinctrl_lookup:
+	devm_pinctrl_put(g_raydium_ts->ts_pinctrl);
+err_pinctrl_get:
+	g_raydium_ts->ts_pinctrl = NULL;
+	return i32_ret;
+}
+#endif/*end of MSM_NEW_VER*/
+#ifdef ESD_SOLUTION_EN
+static int raydium_hw_reset_fun(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+	
+	pr_info("[touch]HW reset\n");
+	if ((g_u8_raydium_flag & ENG_MODE) == 0)
+		raydium_irq_control(DISABLE);
+
+	g_u8_resetflag = true;
+	/*HW reset*/
+	gpio_set_value(g_raydium_ts->rst_gpio, 1);
+	gpio_set_value(g_raydium_ts->rst_gpio, 0);
+	msleep(RAYDIUM_RESET_INTERVAL_MSEC);
+	gpio_set_value(g_raydium_ts->rst_gpio, 1);
+
+	g_u8_i2c_mode = PDA2_MODE;
+
+	i32_ret = wait_irq_state(client, 300, 2000);
+	if (i32_ret != ERROR) {
+		msleep(25);
+	}
+
+	if ((g_u8_raydium_flag & ENG_MODE) == 0)
+		raydium_irq_control(ENABLE);
+
+	pr_info("[touch]Raydium HW reset : %d\n", i32_ret);
+	return i32_ret;
+}
+#endif
+int raydium_i2c_pda_set_address(unsigned int u32_address,
+				       unsigned char u8_mode)
+{
+	int i32_ret = 0;
+	unsigned char u8_retry;
+	unsigned char u8_buf[RAD_I2C_PDA_ADDRESS_LENGTH];
+	struct i2c_client *client = g_raydium_ts->client;
+
+	client->addr = RAYDIUM_I2C_EID;
+	u8_buf[0] = (u32_address & 0x0000FF00) >> 8;
+	u8_buf[1] = (u32_address & 0x00FF0000) >> 16;
+	u8_buf[2] = (u32_address & 0xFF000000) >> 24;
+	u8_buf[3] = u8_mode;
+
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		i32_ret = i2c_master_send(client, u8_buf,
+					 RAD_I2C_PDA_ADDRESS_LENGTH);
+		if (i32_ret != RAD_I2C_PDA_ADDRESS_LENGTH) {
+			pr_err("[touch]%s: I2C retry %d\n",
+				__func__, u8_retry + 1);
+			usleep_range(500, 1500);
+		} else {
+			break;
+		}
+	}
+
+	return (i32_ret == RAD_I2C_PDA_ADDRESS_LENGTH) ? i32_ret : -EIO;
+}
+
+/*device attribute raydium_i2c_pda2_mode used*/
+int raydium_i2c_pda_read(struct i2c_client *client,
+				unsigned int u32_addr, unsigned char *u8_r_data,
+				unsigned short u16_length)
+{
+	int i32_ret;
+	unsigned char u8_retry;
+	unsigned char u8_mode = 0x00;
+	unsigned char u8_buf;
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = 1,
+			.buf = &u8_buf,
+		},
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_READ,
+			.len = u16_length,
+			.buf = u8_r_data,
+		},
+	};
+
+	if (u16_length == 4)
+		u8_mode |= RAD_I2C_PDA_MODE_ENABLE |
+			RAD_I2C_PDA_2_MODE_DISABLE |
+			RAD_I2C_PDA_MODE_WORD_MODE;
+	else
+		u8_mode |= RAD_I2C_PDA_MODE_ENABLE |
+			RAD_I2C_PDA_2_MODE_DISABLE;
+
+	u8_mode |= 0x03;
+
+	u8_buf = u32_addr & MASK_8BIT;
+
+	i32_ret = raydium_i2c_pda_set_address(u32_addr, u8_mode);
+	if (i32_ret != RAD_I2C_PDA_ADDRESS_LENGTH)
+		goto exit;
+	usleep_range(50, 80);
+
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		if (i2c_transfer(g_raydium_ts->client->adapter, msg, 2) == 2) {
+			i32_ret = u16_length;
+			break;
+		}
+		pr_err("%s: I2C retry %d\n", __func__, u8_retry + 1);
+		usleep_range(500, 1500);
+	}
+
+	if (u8_retry == SYN_I2C_RETRY_TIMES) {
+		pr_err("%s: I2C read over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+exit:
+	return i32_ret;
+}
+
+int raydium_i2c_pda_write(struct i2c_client *client,
+			unsigned int u32_addr, unsigned char *u8_w_data,
+			unsigned short u16_length)
+{
+	int i32_ret;
+	unsigned char u8_retry;
+	unsigned char u8_mode = 0x00;
+	unsigned char u8_buf[MAX_WRITE_PACKET_SIZE + 1];
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = u16_length + 1,
+			.buf = u8_buf,
+		},
+	};
+
+	if (u16_length > MAX_WRITE_PACKET_SIZE)
+		return -EINVAL;
+
+	if (u16_length == 4)
+		u8_mode |= RAD_I2C_PDA_MODE_ENABLE |
+			RAD_I2C_PDA_2_MODE_DISABLE |
+			RAD_I2C_PDA_MODE_WORD_MODE;
+	else
+		u8_mode |= RAD_I2C_PDA_MODE_ENABLE |
+			RAD_I2C_PDA_2_MODE_DISABLE;
+
+	u8_buf[0] = u32_addr & MASK_8BIT;
+	memcpy(&u8_buf[1], u8_w_data, u16_length);
+
+	i32_ret = raydium_i2c_pda_set_address(u32_addr, u8_mode);
+	if (i32_ret != RAD_I2C_PDA_ADDRESS_LENGTH)
+		goto exit;
+	//usleep_range(50, 80);
+
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		if (i2c_transfer(client->adapter, msg, 1) == 1) {
+			i32_ret = u16_length;
+			break;
+		}
+		pr_err("[touch]%s: I2C retry %d\n", __func__, u8_retry + 1);
+		usleep_range(500, 1500);
+	}
+
+	if (u8_retry == SYN_I2C_RETRY_TIMES) {
+		pr_err("[touch]%s: I2C write over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+exit:
+	return i32_ret;
+}
+
+int raydium_i2c_pda2_set_page(struct i2c_client *client,
+					unsigned int is_suspend,
+					unsigned char u8_page)
+{
+	int i32_ret = -1;
+	unsigned char u8_retry;
+	unsigned int u8_ret = (is_suspend) ? 10 : 2;
+	unsigned char u8_buf[RAYDIUM_I2C_PDA2_PAGE_LENGTH];
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = RAYDIUM_I2C_PDA2_PAGE_LENGTH,
+			.buf = u8_buf,
+		},
+	};
+
+	u8_buf[0] = RAYDIUM_PDA2_PAGE_ADDR;
+	u8_buf[1] = u8_page;
+	for (; u8_ret > 0; u8_ret--) {
+		for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+			if (i2c_transfer(client->adapter, msg, 1) == 1) {
+				i32_ret = RAYDIUM_I2C_PDA2_PAGE_LENGTH;
+				break;
+			}
+			usleep_range(500, 1500);
+	}
+		if (i32_ret == RAYDIUM_I2C_PDA2_PAGE_LENGTH)
+			break;
+		usleep_range(2000, 5000);
+	}
+
+	if (0 == u8_ret) {
+		pr_err("[touch]%s: I2C write over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+
+	return i32_ret;
+}
+
+int raydium_i2c_pda2_read(struct i2c_client *client,
+				 unsigned char u8_addr,
+				 unsigned char *u8_r_data,
+				 unsigned short u16_length)
+{
+	int i32_ret = -1;
+	unsigned char u8_retry;
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = 1,
+			.buf = &u8_addr,
+		},
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_READ,
+			.len = u16_length,
+			.buf = u8_r_data,
+		},
+	};
+	g_u8_i2c_mode = PDA2_MODE;
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		if (i2c_transfer(g_raydium_ts->client->adapter, msg, 2) == 2) {
+			i32_ret = u16_length;
+			break;
+		}
+		usleep_range(500, 1500);
+	}
+
+	if (u8_retry == SYN_I2C_RETRY_TIMES) {
+		pr_err("[touch]%s: I2C read over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+
+	return i32_ret;
+}
+
+int raydium_i2c_pda2_write(struct i2c_client *client,
+				  unsigned char u8_addr,
+				  unsigned char *u8_w_data,
+				  unsigned short u16_length)
+{
+	int i32_ret = -1;
+	unsigned char u8_retry;
+	unsigned char u8_buf[MAX_WRITE_PACKET_SIZE + 1];
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = RAYDIUM_I2C_NID,
+			.flags = RAYDIUM_I2C_WRITE,
+			.len = u16_length + 1,
+			.buf = u8_buf,
+		},
+	};
+
+	if (u16_length > MAX_WRITE_PACKET_SIZE)
+		return -EINVAL;
+	g_u8_i2c_mode = PDA2_MODE;
+	u8_buf[0] = u8_addr;
+	memcpy(&u8_buf[1], u8_w_data, u16_length);
+
+	for (u8_retry = 0; u8_retry < SYN_I2C_RETRY_TIMES; u8_retry++) {
+		if (i2c_transfer(client->adapter, msg, 1) == 1) {
+			i32_ret = u16_length;
+			break;
+		}
+		usleep_range(500, 1500);
+	}
+
+	if (u8_retry == SYN_I2C_RETRY_TIMES) {
+		pr_err("[touch]%s: I2C write over retry limit\n", __func__);
+		i32_ret = -EIO;
+	}
+
+	return i32_ret;
+}
+
+void raydium_irq_control(bool enable)
+{
+	if (enable) {
+		if (g_raydium_ts->irq_enabled) {
+			/*mutex_unlock(&ts->lock);*/
+			dev_info(&g_raydium_ts->client->dev,
+				"[touch]Already enable irq\n");
+			return;
+		}
+
+		/* Clear interrupts first */
+		if (g_raydium_ts->blank != FB_BLANK_POWERDOWN) {
+			if (g_u8_i2c_mode == PDA2_MODE) {
+				mutex_lock(&g_raydium_ts->lock);
+				if (raydium_i2c_pda2_set_page(g_raydium_ts->client,
+						g_raydium_ts->is_suspend,
+						RAYDIUM_PDA2_PAGE_0) < 0)
+					pr_err("[touch]set page fail%s\n",
+						__func__);
+				mutex_unlock(&g_raydium_ts->lock);
+				usleep_range(500, 1500);
+			}
+		}
+		while (g_raydium_ts->irq_desc->depth > 0) {
+			pr_info("[touch]irq enable\n");
+			g_raydium_ts->irq_enabled = true;
+			enable_irq(g_raydium_ts->irq);
+		}
+	} else {
+		if (g_raydium_ts->irq_enabled) {
+			if (g_raydium_ts->irq_desc->depth == 0) {
+				disable_irq(g_raydium_ts->irq);
+				g_raydium_ts->irq_enabled = false;
+				pr_info("[touch]irq disable\n");
+			}
+		}
+	}
+}
+
+#ifdef CONFIG_RM_SYSFS_DEBUG
+
+int raydium_i2c_mode_control(struct i2c_client *client,
+				    unsigned char u8_mode)
+{
+	unsigned char u8_buf[4];
+
+	switch (u8_mode) {
+	case 0:	/* Disable INT flag */
+		pr_info("[touch]RAD INT flag : %d\n", g_raydium_ts->irq_enabled);
+		disable_irq(g_raydium_ts->irq);
+		g_raydium_ts->irq_enabled = false;
+		pr_info("[touch]RAD irq disable\n");
+		break;
+	case 1:	/* Enable INT flag */
+		pr_info("[touch]RAD INT flag : %d\n", g_raydium_ts->irq_enabled);
+		enable_irq(g_raydium_ts->irq);
+		g_raydium_ts->irq_enabled = true;
+		pr_info("[touch]RAD irq enable\n");
+		break;
+	case 2: /* Disable INT by raydium_irq_control */
+		raydium_irq_control(DISABLE);
+		break;
+	case 3: /* Enable INT by raydium_irq_control */
+		raydium_irq_control(ENABLE);
+		break;
+	case 4: /* Show RAD INT depth */
+		pr_info("[touch]RAD INT depth : %d\n", g_raydium_ts->irq_desc->depth);
+		break;
+	case 7:
+		raydium_i2c_pda2_set_page(client,
+			g_raydium_ts->is_suspend , RAYDIUM_PDA2_2_PDA);
+		g_u8_i2c_mode = PDA_MODE;
+		pr_info("[touch]Disable PDA2_MODE\n");
+		break;
+	case 8:
+		raydium_i2c_pda_read(client, RAD_PDA2_CTRL_CMD, u8_buf, 4);
+		u8_buf[0] |= RAD_ENABLE_PDA2 | RAD_ENABLE_SI2;
+		raydium_i2c_pda_write(client, RAD_PDA2_CTRL_CMD, u8_buf, 4);
+		raydium_i2c_pda_set_address(0x50000628, DISABLE);
+
+		g_u8_i2c_mode = PDA2_MODE;
+		pr_info("[touch]Enable PDA2_MODE\n");
+		break;
+	}
+	return 0;
+}
+
+
+const struct attribute_group raydium_attr_group = {
+	.attrs = raydium_attributes
+};
+
+/*create sysfs for debug update firmware*/
+static int raydium_create_sysfs(struct i2c_client *client)
+{
+	int ret = -1;
+
+	ret = sysfs_create_group(&(client->dev.kobj), &raydium_attr_group);
+	if (ret) {
+		pr_err("[touch]failed to register sysfs\n");
+		sysfs_remove_group(&client->dev.kobj, &raydium_attr_group);
+		ret = -EIO;
+	} else {
+		pr_info("[touch]create raydium sysfs attr_group successful\n");
+	}
+	return ret;
+}
+
+static void raydium_release_sysfs(struct i2c_client *client)
+{
+	sysfs_remove_group(&client->dev.kobj, &raydium_attr_group);
+}
+#endif /*end of CONFIG_RM_SYSFS_DEBUG*/
+
+#ifdef ESD_SOLUTION_EN
+int raydium_esd_check(void)
+{
+	int i32_ret = 0;
+	unsigned char u8_esd_status[MAX_TCH_STATUS_PACKET_SIZE];
+	unsigned char u8_w_data[4];
+
+	mutex_lock(&g_raydium_ts->lock);
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client, 
+			g_raydium_ts->is_suspend,
+			RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit;
+		/*read esd status*/
+		i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+				RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR,
+				u8_esd_status, MAX_TCH_STATUS_PACKET_SIZE);
+		if (i32_ret < 0) {
+			pr_err("[touch]%s: failed to read data: %d\n",
+				__func__, __LINE__);
+			goto exit;
+		}
+
+		if (u8_esd_status[POS_FW_STATE] != 0x1A &&
+			u8_esd_status[POS_FW_STATE] != 0xAA) {
+			if (g_u8_resetflag == true) {
+				pr_err("[touch]%s -> filter abnormal irq\n"
+					, __func__);
+				goto exit;
+			}
+			pr_err("[touch]%s -> abnormal irq, FW state = 0x%x\n",
+			__func__, u8_esd_status[POS_FW_STATE]);
+			g_u8_resetflag = false;
+			i32_ret = -1;
+			goto exit;
+
+		}
+		u8_w_data[POS_SEQ] = 0;
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR,
+					u8_w_data, 1);	
+		if (i32_ret < 0) {
+			pr_err("[touch]%s: failed to clear seq: %d\n",
+				__func__, __LINE__);
+			goto exit;
+		}			
+		g_u8_resetflag = false;
+	}
+exit:
+	mutex_unlock(&g_raydium_ts->lock);
+	pr_info("[touch] raydium_esd_check\n");
+	return i32_ret;
+}
+#endif
+
+
+#ifdef ENABLE_DUMP_DATA
+int raydium_dump_data(unsigned char u8_frame, unsigned char u8_type)
+{
+	unsigned char u8_rbuffer[MAX_READ_PACKET_SIZE*2];
+	short i16_data_buffer[MAX_READ_PACKET_SIZE*2];
+	unsigned char u8_w_data[RAYDIUM_FT_CMD_LENGTH];
+	unsigned int u32_target_addr;
+	unsigned int u32_offset;
+	unsigned short u16_read_length;
+	int i32_ret = -1;
+	int i32_retry = 0;
+	unsigned char u8_i, u8_j, u8_k;
+	char write_string[1000];
+
+	pr_info("[touch] %s -> type:%d\n", __func__, u8_type);
+
+	for (u8_i = 0; u8_i < u8_frame; u8_i++) {
+
+		u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+		u8_w_data[RAD_FT_CMD_POS] = u8_type;
+
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					RAYDIUM_PDA2_HOST_CMD_ADDR,
+					u8_w_data, RAYDIUM_FT_CMD_LENGTH);
+
+		memset(u8_rbuffer, 0x00, MAX_READ_PACKET_SIZE*2);
+		/* make sure update flag was set*/
+		for (i32_retry = 0; i32_retry < 5; i32_retry++) {
+			i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+							g_raydium_ts->is_suspend,
+							RAYDIUM_PDA2_PAGE_0);
+			if (i32_ret < 0)
+				goto exit_i2c_error;
+
+			i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+						RAYDIUM_PDA2_HOST_CMD_ADDR,
+						u8_rbuffer,
+						RAYDIUM_FT_CMD_LENGTH);
+			if (i32_ret < 0)
+				goto exit_flag_error;
+
+			if ((u8_rbuffer[RAD_FT_CMD_POS] & RAYDIUM_FT_UPDATE) ==
+			    RAYDIUM_FT_UPDATE)
+				break;
+
+			usleep_range(4500, 5500);
+		}
+
+		if (i32_retry == 5) {
+			i32_ret = -EAGAIN;
+			pr_info("[touch] %s -> flag timeout\n", __func__);
+		}
+
+		u32_offset = 0;
+		u16_read_length = 0;
+#if DATA_MAP_5_5
+		g_u32_raw_data_len = 0x32;
+#else
+		g_u32_raw_data_len = 0x48;
+#endif
+		while (u32_offset < g_u32_raw_data_len) {
+			u16_read_length = g_u32_raw_data_len;
+
+			u32_target_addr = RAD_READ_FT_DATA_CMD + u32_offset;
+
+			i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+							g_raydium_ts->is_suspend,
+							RAYDIUM_PDA2_PAGE_0);
+			if (i32_ret < 0)
+				goto exit_i2c_error;
+
+			*(unsigned int *)u8_rbuffer =
+				(RAD_I2C_PDA_MODE_ENABLE << 24)
+				| ((u32_target_addr & (~MASK_8BIT)) >> 8);
+
+			/*using byte mode to read 4 bytes*/
+			i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					RAYDIUM_PDA2_PDA_CFG_ADDR,
+					u8_rbuffer, 4);
+			if (i32_ret < 0)
+				goto exit_i2c_error;
+
+			i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_ENABLE_PDA);
+			if (i32_ret < 0)
+				goto exit_i2c_error;
+
+			i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+				(unsigned char)(u32_target_addr & MASK_8BIT),
+				u8_rbuffer,
+				u16_read_length);
+
+			if (i32_ret < 0)
+				goto exit_flag_error;
+
+			memcpy((i16_data_buffer + u32_offset),
+				u8_rbuffer,
+				u16_read_length);
+
+			u32_offset += u16_read_length;
+		}
+		pr_info("[touch] frame%d\n", u8_i);
+#if DATA_MAP_5_5
+		for (u8_j = 0; u8_j < 25; u8_j += 5) {
+			pr_info("[touch] %4d, %4d, %4d, %4d, %4d\r\n",
+			i16_data_buffer[u8_j], i16_data_buffer[u8_j+1],
+			i16_data_buffer[u8_j+2], i16_data_buffer[u8_j+3],
+			i16_data_buffer[u8_j+4]);
+		}
+#else
+		for (u8_j = 0; u8_j < 36; u8_j += 6) {
+			pr_info("[touch] %4d, %4d, %4d, %4d, %4d, %4d\r\n",
+			i16_data_buffer[u8_j], i16_data_buffer[u8_j+1],
+			i16_data_buffer[u8_j+2], i16_data_buffer[u8_j+3],
+			i16_data_buffer[u8_j+4], i16_data_buffer[u8_j+5]);
+		}
+#endif
+		/* clear update flag to get next one*/
+		u8_rbuffer[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+		u8_rbuffer[RAD_FT_CMD_POS] = u8_type;
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+				RAYDIUM_PDA2_HOST_CMD_ADDR,
+				u8_rbuffer, RAYDIUM_FT_CMD_LENGTH);
+		if (i32_ret < 0)
+			goto exit_flag_error;
+
+	}
+	return 0;
+exit_i2c_error:
+	pr_info("%s exit_i2c_error return %d\r\n", __func__, i32_ret);
+exit_flag_error:
+	return i32_ret;
+}
+
+static void raydium_dump_data_work(struct work_struct *work)
+{
+
+	int i32_ret = 0;
+	unsigned char u8_data_type;
+	unsigned char u8_w_data[RAYDIUM_FT_CMD_LENGTH];
+
+	/* set mode */
+	memset(u8_w_data, 0x00, RAYDIUM_FT_CMD_LENGTH);
+	pr_info("[touch] raydium_dump_data_work\n");
+
+	disable_irq_nosync(g_raydium_ts->irq);
+	g_raydium_ts->irq_enabled = false;
+
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_FT_MODE;
+
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+				RAYDIUM_PDA2_HOST_CMD_ADDR,
+				u8_w_data, 1);
+	if (i32_ret < 0)
+		goto exit_error;
+	pr_info("[touch] RAYDIUM_HOST_CMD_FT_MODE\n");
+
+	/*baseline*/
+	u8_data_type = 0x02;
+	raydium_dump_data(1, u8_data_type);
+	u8_data_type = 0x04;
+	raydium_dump_data(1, u8_data_type);
+	u8_data_type = 0x10;
+	raydium_dump_data(10, u8_data_type);
+
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_error;
+	u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_TP_MODE;
+
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+				RAYDIUM_PDA2_HOST_CMD_ADDR,
+				u8_w_data, 1);
+
+	u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+	u8_w_data[RAD_FT_CMD_POS] = 0;
+
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+				RAYDIUM_PDA2_HOST_CMD_ADDR,
+				u8_w_data, RAD_FT_CMD_LENGTH);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	enable_irq(g_raydium_ts->irq);
+	g_raydium_ts->irq_enabled = true;
+exit_error:
+	return;
+}
+
+#endif
+#ifdef FILTER_POINTS
+int raydium_pointer_filter(int i32_index,
+			unsigned short u16_diff_x,
+			unsigned short u16_diff_y)
+{
+	if (abs(ts->x_pos[i32_index] - ts->last_x_pos[i32_index]) >  u16_diff_x)
+		return 0;
+	if (abs(ts->y_pos[i32_index] - ts->last_y_pos[i32_index]) >  u16_diff_y)
+		return 0;
+
+	return 1;
+}
+#endif
+
+#ifdef HOST_NOTIFY_EN
+int raydium_notify_function(unsigned short u16_display_mode)
+{
+	int i32_ret = 0;
+	unsigned char u8_rbuffer[4];
+
+	mutex_lock(&g_raydium_ts->lock);
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+						g_raydium_ts->is_suspend,
+						RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit;
+		memset(u8_rbuffer, 0,sizeof(u8_rbuffer));
+
+		u8_rbuffer[0] = RAYDIUM_HOST_CMD_DISPLAY_MODE;
+		u8_rbuffer[2] = (unsigned char) (u16_display_mode & 0x00ff);
+		u8_rbuffer[3] = (unsigned char) ((u16_display_mode & 0xff00) >> 8);
+		pr_info("[touch] display mode %d %d %d\r\n",u16_display_mode,u8_rbuffer[2],u8_rbuffer[3]);
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					RAYDIUM_PDA2_HOST_CMD_ADDR,
+					u8_rbuffer, 4);
+	}
+exit:
+	mutex_unlock(&g_raydium_ts->lock);
+	pr_info("[touch] raydium_notify_function\n");
+	return i32_ret;
+}
+#endif
+static int raydium_touch_report(unsigned char *p_u8_buf,
+				unsigned char u8_points_amount)
+{
+	unsigned char u8_i, u8_j, u8_offset = 0, u8_pt_id;
+	signed short i16_wx, i16_wy;
+	/* number of touch points */
+	unsigned char u8_touch_count = 0;
+	DECLARE_BITMAP(ids, g_raydium_ts->u8_max_touchs);
+
+	bitmap_zero(ids, g_raydium_ts->u8_max_touchs);
+
+	for (u8_i = 0; u8_i < (g_raydium_ts->u8_max_touchs * 2); u8_i++) {
+		gst_slot[u8_i].need_update = 0;
+		gst_slot[u8_i].pt_report_offset = 0;
+	}
+
+	/*Check incoming point info*/
+	for (u8_i = 0; u8_i < u8_points_amount; u8_i++) {
+		u8_pt_id = p_u8_buf[POS_PT_ID + u8_i * LEN_PT];
+		/* Current*/
+		for (u8_j = 0; u8_j < g_raydium_ts->u8_max_touchs; u8_j++) {
+			if (u8_pt_id == gst_slot[u8_j].pt_id) {
+				gst_slot[u8_j].need_update = 1;
+				gst_slot[u8_j].pt_report_offset = u8_i;
+				break;
+			}
+		}
+		/* New coming*/
+		if (u8_j == g_raydium_ts->u8_max_touchs) {
+			for (u8_j = g_raydium_ts->u8_max_touchs;
+				u8_j < (g_raydium_ts->u8_max_touchs * 2); u8_j++) {
+				if (!gst_slot[u8_j].need_update) {
+					gst_slot[u8_j].pt_id = u8_pt_id;
+					gst_slot[u8_j].need_update = 1;
+					gst_slot[u8_j].pt_report_offset = u8_i;
+					pr_info("[touch]x:%d,y:%d\n",
+					p_u8_buf[POS_X_L + u8_offset] |
+					p_u8_buf[POS_X_H + u8_offset] << 8,
+					p_u8_buf[POS_Y_L + u8_offset] |
+					p_u8_buf[POS_Y_H + u8_offset] << 8);
+					break;
+				}
+			}
+		}
+	}
+
+	/*Release slot with non-occupied point*/
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		if (!gst_slot[u8_i].need_update) {
+			input_mt_slot(g_raydium_ts->input_dev, u8_i);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, false);
+			gst_slot[u8_i].pt_id = 0xFF;
+			gst_slot[u8_i].pt_report_offset = 0;
+			gst_slot[u8_i].need_update = 0;
+		}
+	}
+	/*Assign new one to non-occupied slot*/
+	for (u8_i = g_raydium_ts->u8_max_touchs;
+		u8_i < (g_raydium_ts->u8_max_touchs * 2); u8_i++) {
+		if (gst_slot[u8_i].need_update) {
+			for (u8_j = 0; u8_j < g_raydium_ts->u8_max_touchs; u8_j++) {
+				if (!gst_slot[u8_j].need_update) {
+					gst_slot[u8_j] = gst_slot[u8_i];
+					gst_slot[u8_i] = gst_slot_init;
+					break;
+				}
+			}
+		} else {
+			break;
+		}
+	}
+#ifdef FILTER_POINTS
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		if (gst_slot[u8_i].need_update) {
+			u8_offset = gst_slot[u8_i].pt_report_offset * LEN_PT;
+			g_raydium_ts->x_pos[i] =  p_u8_buf[POS_X_L + u8_offset] |
+				p_u8_buf[POS_X_H + u8_offset] << BYTE_SHIFT;
+			g_raydium_ts->y_pos[i] = p_u8_buf[POS_Y_L + u8_offset] |
+				p_u8_buf[POS_Y_H + u8_offset] << BYTE_SHIFT;
+			g_raydium_ts->pressure = p_u8_buf[POS_PRESSURE_L + u8_offset] |
+			p_u8_buf[POS_PRESSURE_H + u8_offset] << BYTE_SHIFT;
+			i16_wx = p_u8_buf[POS_WX_L + u8_offset] |
+				p_u8_buf[POS_WX_H + u8_offset] << BYTE_SHIFT;
+			i16_wy = p_u8_buf[POS_WY_L + u8_offset] |
+				p_u8_buf[POS_WY_H + u8_offset] << BYTE_SHIFT;
+
+		if (!raydium_pointer_filter(g_raydium_ts, u8_i, DELTA_X, DELTA_Y)) {
+			input_mt_slot(g_raydium_ts->input_dev, u8_i);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, true);
+			__set_bit(i, ids);
+
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_POSITION_X, g_raydium_ts->x_pos[u8_i]);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_POSITION_Y, g_raydium_ts->y_pos[u8_i]);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_PRESSURE, g_raydium_ts->pressure);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_TOUCH_MAJOR, max(i16_wx, i16_wy));
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_TOUCH_MINOR, min(i16_wx, i16_wy));
+			input_report_key(g_raydium_ts->input_dev,
+				BTN_TOUCH, 1);
+			input_report_key(g_raydium_ts->input_dev,
+				BTN_TOOL_FINGER, 1);
+			input_sync(g_raydium_ts->input_dev);
+			g_raydium_ts->last_x_pos[u8_i] = g_raydium_ts->x_pos[u8_i];
+			g_raydium_ts->last_y_pos[u8_i] = g_raydium_ts->y_pos[u8_i];
+		} else {
+			g_raydium_ts->x_pos[u8_i] = g_raydium_ts->last_x_pos[u8_i];
+			g_raydium_ts->y_pos[u8_i] = g_raydium_ts->last_y_pos[u8_i];
+		}
+		}
+	}
+
+	if ((gst_slot[0].need_update == 0) &&
+		(gst_slot[1].need_update == 0)) {
+		for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+			if (test_bit(u8_i, ids))
+				continue;
+			input_mt_slot(g_raydium_ts->input_dev, u8_i);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, false);
+		}
+		input_report_key(g_raydium_ts->input_dev, BTN_TOUCH, 0);
+		input_report_key(g_raydium_ts->input_dev, BTN_TOOL_FINGER, 0);
+		input_sync(g_raydium_ts->input_dev);
+	}
+#else
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		if (gst_slot[u8_i].need_update) {
+			u8_offset = gst_slot[u8_i].pt_report_offset * LEN_PT;
+			g_raydium_ts->x_pos[u8_i] = p_u8_buf[POS_X_L + u8_offset] |
+				p_u8_buf[POS_X_H + u8_offset] << BYTE_SHIFT;
+			g_raydium_ts->y_pos[u8_i] = p_u8_buf[POS_Y_L + u8_offset] |
+				p_u8_buf[POS_Y_H + u8_offset] << BYTE_SHIFT;
+			g_raydium_ts->pressure = p_u8_buf[POS_PRESSURE_L + u8_offset] |
+			p_u8_buf[POS_PRESSURE_H + u8_offset] << BYTE_SHIFT;
+			i16_wx = p_u8_buf[POS_WX_L + u8_offset] |
+				p_u8_buf[POS_WX_H + u8_offset] << BYTE_SHIFT;
+			i16_wy = p_u8_buf[POS_WY_L + u8_offset] |
+				p_u8_buf[POS_WY_H + u8_offset] << BYTE_SHIFT;
+
+			input_mt_slot(g_raydium_ts->input_dev, u8_i);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, true);
+			__set_bit(u8_i, ids);
+
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_POSITION_X, g_raydium_ts->x_pos[u8_i]);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_POSITION_Y, g_raydium_ts->y_pos[u8_i]);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_PRESSURE, g_raydium_ts->pressure);
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_TOUCH_MAJOR, max(i16_wx, i16_wy));
+			input_report_abs(g_raydium_ts->input_dev,
+				ABS_MT_TOUCH_MINOR, min(i16_wx, i16_wy));
+
+			u8_touch_count++;
+		}
+	}
+	input_report_key(g_raydium_ts->input_dev,
+				BTN_TOUCH, u8_touch_count > 0);
+	input_report_key(g_raydium_ts->input_dev,
+				BTN_TOOL_FINGER, u8_touch_count > 0);
+
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		if (test_bit(u8_i, ids))
+			continue;
+		input_mt_slot(g_raydium_ts->input_dev, u8_i);
+		input_mt_report_slot_state(g_raydium_ts->input_dev,
+			MT_TOOL_FINGER, false);
+	}
+
+	input_sync(g_raydium_ts->input_dev);
+#endif
+	return 0;
+}
+int raydium_read_touchdata(unsigned char *p_u8_tp_status,  unsigned char *p_u8_buf)
+{
+	int i32_ret = 0;
+	unsigned char u8_points_amount;
+	static unsigned char u8_seq_no;
+	unsigned char u8_retry;
+
+	u8_retry = 3;
+
+	mutex_lock(&g_raydium_ts->lock);
+	while (u8_retry != 0) {
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+		g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0) {
+			msleep(250);
+			u8_retry--;
+		} else
+			break;
+	}
+	if (u8_retry == 0) {
+		pr_err("[touch]%s: failed to set page, hw reset\n", __func__);
+
+		goto reset_error;
+	}
+
+	memset(p_u8_buf, 0, MAX_REPORT_PACKET_SIZE);
+	memset(p_u8_tp_status, 0, MAX_TCH_STATUS_PACKET_SIZE);
+
+	/*read touch point information*/
+	i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+			RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR,
+			p_u8_tp_status, MAX_TCH_STATUS_PACKET_SIZE);
+	if (i32_ret < 0) {
+		pr_err("[touch]%s: failed to read data: %d\n",
+			__func__, __LINE__);
+		goto exit_error;
+	}
+#ifdef ESD_SOLUTION_EN
+	if (p_u8_tp_status[POS_FW_STATE] != 0x1A &&
+		p_u8_tp_status[POS_FW_STATE] != 0xAA) {
+		if (g_u8_resetflag == true) {
+			pr_err("[touch]%s -> filter irq, FW state = 0x%x\n",
+			__func__, p_u8_tp_status[POS_FW_STATE]);
+			i32_ret = -1;
+			g_u8_resetflag = false;
+			goto exit_error;
+		}
+		pr_err("[touch]%s -> abnormal irq, FW state = 0x%x\n",
+		__func__, p_u8_tp_status[POS_FW_STATE]);
+		i32_ret = -1;
+		goto reset_error;
+
+	}
+#endif
+	/* inform IC to prepare next report*/
+	if (u8_seq_no == p_u8_tp_status[POS_SEQ]) {
+		pr_err("%s -> report not updated.\n", __func__);
+		goto exit_error;
+	}
+	u8_points_amount = p_u8_tp_status[POS_PT_AMOUNT];
+
+	if (u8_points_amount > MAX_TOUCH_NUM)
+		goto exit_error;
+
+	/*read touch point report*/
+	/*PDA2 only support word mode*/
+	if (u8_points_amount != 0)
+		i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+				RAYDIUM_PDA2_TCH_RPT_ADDR, p_u8_buf,
+				u8_points_amount * LEN_PT);
+
+	if (i32_ret < 0) {
+		pr_err("[touch]%s: failed to read data: %d\n",
+			__func__, __LINE__);
+		goto exit_error;
+	}
+
+	u8_seq_no = p_u8_tp_status[POS_SEQ];
+	p_u8_tp_status[POS_SEQ] = 0;
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+			RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR, p_u8_tp_status, 1);
+	if (i32_ret < 0) {
+		pr_err("[touch]%s: write data failed: %d\n", __func__, i32_ret);
+		goto exit_error;
+	}
+
+	raydium_touch_report(p_u8_buf, u8_points_amount);
+
+exit_error:
+	mutex_unlock(&g_raydium_ts->lock);
+
+	return i32_ret;
+
+reset_error:
+	mutex_unlock(&g_raydium_ts->lock);
+#ifdef ESD_SOLUTION_EN
+	u8_retry = 3;
+	while (u8_retry != 0) {
+		i32_ret = raydium_hw_reset_fun(g_raydium_ts->client);
+		if (i32_ret < 0) {
+			msleep(100);
+			u8_retry--;
+		} else
+			break;
+	}
+#endif
+	return i32_ret;
+}
+
+static void raydium_work_handler(struct work_struct *work)
+{
+	int i32_ret = 0;
+	unsigned char u8_tp_status[MAX_TCH_STATUS_PACKET_SIZE];
+	unsigned char u8_buf[MAX_REPORT_PACKET_SIZE];
+
+#ifdef GESTURE_EN
+	unsigned char u8_i;
+
+	if ((g_raydium_ts->blank == FB_BLANK_VSYNC_SUSPEND ||
+			g_raydium_ts->blank == FB_BLANK_POWERDOWN) &&
+			(g_u8_resetflag == false)) {
+			input_mt_slot(g_raydium_ts->input_dev, 0);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, 1);
+			input_report_abs(g_raydium_ts->input_dev, ABS_MT_POSITION_X, 100);
+			input_report_abs(g_raydium_ts->input_dev, ABS_MT_POSITION_Y, 100);
+			input_sync(g_raydium_ts->input_dev);
+			usleep_range(9500, 10500);
+			input_mt_slot(g_raydium_ts->input_dev, 0);
+			input_mt_report_slot_state(g_raydium_ts->input_dev,
+				MT_TOOL_FINGER, 0);
+			input_mt_report_pointer_emulation(g_raydium_ts->input_dev, false);
+			input_sync(g_raydium_ts->input_dev);
+			input_report_key(g_raydium_ts->input_dev, KEY_POWER, true);
+			usleep_range(9500, 10500);
+			input_sync(g_raydium_ts->input_dev);
+
+			input_report_key(g_raydium_ts->input_dev, KEY_POWER, false);
+			input_sync(g_raydium_ts->input_dev);
+#ifdef ESD_SOLUTION_EN
+			g_u8_checkflag = true;
+#endif
+			pr_info("[touch]display wake up with g_u8_resetflag false\n");
+	} else {
+
+		if (g_u8_i2c_mode == PDA2_MODE) {
+			i32_ret = raydium_read_touchdata(u8_tp_status, u8_buf);
+			if (i32_ret < 0) {
+				pr_info("[touch]%s, read_touchdata error, ret:%d\n",
+					__func__, i32_ret);
+				return;
+			}
+		}
+		/*when display on can use palm to suspend*/
+		if (g_raydium_ts->blank == FB_BLANK_UNBLANK) {
+			if (u8_tp_status[POS_GES_STATUS] == RAD_PALM_ENABLE) {
+				if (g_raydium_ts->is_palm == 0) {
+					/* release all touches*/
+					for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs;
+						u8_i++) {
+						input_mt_slot(g_raydium_ts->input_dev,
+							       u8_i);
+					input_mt_report_slot_state(
+							       g_raydium_ts->input_dev,
+						MT_TOOL_FINGER, false);
+					}
+					input_mt_report_pointer_emulation(
+							g_raydium_ts->input_dev,
+							false);
+					/*press sleep key*/
+					input_report_key(g_raydium_ts->input_dev,
+						KEY_SLEEP, true);
+					input_sync(g_raydium_ts->input_dev);
+
+					pr_info("[touch]palm_status = %d.\n",
+						u8_tp_status[POS_GES_STATUS]);
+
+					g_raydium_ts->is_palm = 1;
+					/*goto exit;*/
+				}
+			} else if ((u8_tp_status[POS_GES_STATUS]
+				== RAD_PALM_DISABLE)
+				&& (g_raydium_ts->is_palm == 1)) {
+				pr_info("[touch]leave palm mode.\n");
+				input_report_key(g_raydium_ts->input_dev,
+						KEY_SLEEP, false);
+				input_sync(g_raydium_ts->input_dev);
+
+				/*raydium_irq_control(raydium_ts, DISABLE);*/
+				g_raydium_ts->is_palm = 0;
+				/*goto exit;*/
+			}
+		} else if (g_raydium_ts->blank == FB_BLANK_VSYNC_SUSPEND ||
+				g_raydium_ts->blank == FB_BLANK_POWERDOWN) {
+			/*need check small area*/
+			if (u8_tp_status[POS_GES_STATUS] == RAD_WAKE_UP) {
+				input_mt_slot(g_raydium_ts->input_dev, 0);
+				input_mt_report_slot_state(g_raydium_ts->input_dev,
+					MT_TOOL_FINGER, 1);
+				input_report_abs(g_raydium_ts->input_dev,
+						ABS_MT_POSITION_X, 100);
+				input_report_abs(g_raydium_ts->input_dev,
+						ABS_MT_POSITION_Y, 100);
+				input_sync(g_raydium_ts->input_dev);
+				usleep_range(9500, 10500);
+				input_mt_slot(g_raydium_ts->input_dev, 0);
+				input_mt_report_slot_state(g_raydium_ts->input_dev,
+					MT_TOOL_FINGER, 0);
+				input_mt_report_pointer_emulation(
+							g_raydium_ts->input_dev,
+							false);
+				input_sync(g_raydium_ts->input_dev);
+				input_report_key(g_raydium_ts->input_dev, KEY_POWER, true);
+				usleep_range(9500, 10500);
+				input_sync(g_raydium_ts->input_dev);
+
+				input_report_key(g_raydium_ts->input_dev, KEY_POWER, false);
+				input_sync(g_raydium_ts->input_dev);
+				pr_info("[touch]display wake up with g_u8_resetflag true\n");
+				/*goto exit;*/
+			}
+		}
+	}
+#else
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_read_touchdata(u8_tp_status, u8_buf);
+		if (i32_ret < 0) {
+			pr_info("[touch]%s, read_touchdata error, ret:%d\n",
+				__func__, i32_ret);
+		}
+	}
+#endif
+}
+
+/*The raydium device will signal the host about TRIGGER_FALLING.
+ *Processed when the interrupt is asserted.
+ */
+static irqreturn_t raydium_ts_interrupt(int irq, void *dev_id)
+{
+	bool result = false;
+
+	/*For bootloader wrt/erase flash and software reset interrupt*/
+	if ((g_u8_raydium_flag & ENG_MODE) != 0) {
+		disable_irq_nosync(g_raydium_ts->irq);
+		g_raydium_ts->irq_enabled = false;
+		pr_info("[touch]RAD_ENG_MODE\n");
+		g_u8_raydium_flag |= INT_FLAG;
+	} else {
+		if (!work_pending(&g_raydium_ts->work)) {
+			/* Clear interrupts*/
+			result = queue_work(g_raydium_ts->workqueue,
+					&g_raydium_ts->work);
+
+			if (result == false) {
+				/*queue_work fail*/
+				pr_err("[touch]queue_work fail.\n");
+			}
+
+
+		} else {
+			/*work pending*/
+				mutex_lock(&g_raydium_ts->lock);
+				if (raydium_i2c_pda2_set_page(g_raydium_ts->client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0) < 0) {
+
+					pr_err("[touch]%s: failed to set page in work_pending\n",
+					__func__);
+				}
+				mutex_unlock(&g_raydium_ts->lock);
+
+			pr_info("[touch]work_pending\n");
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int raydium_check_i2c_ready(unsigned short *u16_i2c_data)
+{
+	unsigned char u8_buf[4];
+	int i32_ret = -1;
+
+	mutex_lock(&g_raydium_ts->lock);
+
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+				g_raydium_ts->is_suspend,
+				RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		*(unsigned int *)u8_buf =
+			(RAD_I2C_PDA_MODE_ENABLE << 24) |
+			((RAD_CHK_I2C_CMD & (~MASK_8BIT)) >> 8);
+		/*using byte mode to read 4 bytes*/
+		i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+					     RAYDIUM_PDA2_PDA_CFG_ADDR,
+					     u8_buf,
+					     4);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+						g_raydium_ts->is_suspend,
+						RAYDIUM_PDA2_ENABLE_PDA);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		i32_ret = raydium_i2c_pda2_read(
+				g_raydium_ts->client,
+				(unsigned char)(RAD_CHK_I2C_CMD & MASK_8BIT),
+				u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_error;
+		if (u8_buf[3] != 0xF3) {
+			pr_info("[touch]PDA2 read i2c fail\n");
+			g_u8_i2c_mode = PDA_MODE;
+			i32_ret = raydium_i2c_pda_read(g_raydium_ts->client,
+					   RAD_CHK_I2C_CMD, u8_buf,
+					   4);
+			if (i32_ret < 0)
+				goto exit_error;
+		}
+
+	} else {
+		i32_ret = raydium_i2c_pda_read(g_raydium_ts->client,
+					   RAD_CHK_I2C_CMD, u8_buf,
+					   4);
+		if (i32_ret < 0)
+			goto exit_error;
+
+	}
+
+	*u16_i2c_data = u8_buf[3] << 8 | u8_buf[2];
+
+	pr_info("[touch]RAD check I2C : 0x%02X%02X\n", u8_buf[3], u8_buf[2]);
+
+exit_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	return i32_ret;
+}
+
+#if defined(CONFIG_PM)
+static void raydium_ts_do_suspend(void)
+{
+	unsigned char u8_i = 0;
+	g_u8_resetflag = false;
+	if (g_raydium_ts->is_suspend == 1) {
+		pr_info("[touch]Already in suspend state\n");
+		return;
+	}
+
+	/*#ifndef GESTURE_EN*/
+	raydium_irq_control(DISABLE);
+	/*#endif*/
+
+	/*clear workqueue*/
+	if (!cancel_work_sync(&g_raydium_ts->work))
+		pr_info("[touch]workqueue is empty!\n");
+
+	pr_info("[touch]%s.\n", __func__);
+
+	/* release all touches */
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		input_mt_slot(g_raydium_ts->input_dev, u8_i);
+		input_mt_report_slot_state(g_raydium_ts->input_dev,
+					   MT_TOOL_FINGER,
+					   false);
+	}
+	input_mt_report_pointer_emulation(g_raydium_ts->input_dev, false);
+	input_sync(g_raydium_ts->input_dev);
+#ifdef ENABLE_DUMP_DATA
+	if (!g_u8_dumpcount)
+		timeout = jiffies + 2*HZ;
+	if (g_u8_dumpcount < 5)
+		g_u8_dumpcount++;
+	if (g_u8_palm_flag || (time_is_before_jiffies(timeout))) {
+		g_u8_dumpcount = 0;
+		g_u8_palm_flag = false;
+	}
+	if (g_u8_dumpcount == 5) {
+		g_u8_dump_flag = true;
+		g_u8_dumpcount = 0;
+	}
+#endif
+
+#ifdef GESTURE_EN
+	if (device_may_wakeup(&g_raydium_ts->client->dev)) {
+		pr_info("[touch]Device may wakeup\n");
+		if (!enable_irq_wake(g_raydium_ts->irq))
+			g_raydium_ts->irq_wake = 1;
+
+	} else
+		pr_info("[touch]Device not wakeup\n");
+	raydium_irq_control(ENABLE);
+#endif
+
+	g_raydium_ts->is_suspend = 1;
+}
+
+static void raydium_ts_do_resume(void)
+{
+#ifdef ESD_SOLUTION_EN
+	int i32_ret = 0;
+	unsigned char u8_retry = 0;
+#endif
+	unsigned char u8_w_data[4];
+
+	pr_info("[touch]%s, %d.\n", __func__, g_raydium_ts->is_suspend);
+	if (g_raydium_ts->is_suspend == 0) {
+		pr_info("[touch]Already in resume state\n");
+		return;
+	}
+
+	/* clear interrupts*/
+	mutex_lock(&g_raydium_ts->lock);
+	if (raydium_i2c_pda2_set_page(g_raydium_ts->client,
+		g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0) < 0) {
+		pr_err("[ raydium ]%s: failed to set page\n", __func__);
+		mutex_unlock(&g_raydium_ts->lock);
+		return;
+	}
+	/* clear seq num*/
+	u8_w_data[POS_SEQ] = 0;
+	if (raydium_i2c_pda2_write(g_raydium_ts->client,
+		RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR, u8_w_data, 1) < 0) {
+		pr_err("[ raydium ]%s: failed to clear seq\n", __func__);
+		mutex_unlock(&g_raydium_ts->lock);
+		return;
+	}
+	
+	mutex_unlock(&g_raydium_ts->lock);
+
+	/* clear workqueue*/
+	if (!cancel_work_sync(&g_raydium_ts->work))
+		pr_info("[ raydium ]workqueue is empty!\n");
+#ifdef ESD_SOLUTION_EN
+	if (g_u8_checkflag == true) {
+		i32_ret = raydium_esd_check();
+		if (i32_ret < 0) {
+			u8_retry = 3;
+			while (u8_retry != 0) {
+				i32_ret = raydium_hw_reset_fun(g_raydium_ts->client);
+				if (i32_ret < 0) {
+					msleep(100);
+					u8_retry--;
+				} else
+					break;
+			}
+
+		}
+		g_u8_checkflag = false;
+	}
+#endif
+	raydium_irq_control(ENABLE);
+#ifdef ENABLE_DUMP_DATA
+	if (g_u8_dump_flag) {
+		schedule_delayed_work(&g_raydium_ts->dump_work, HZ);
+		g_u8_dump_flag = false;
+	}
+#endif
+#ifdef GESTURE_EN
+	if (device_may_wakeup(&g_raydium_ts->client->dev)) {
+		pr_info("[touch]Device may wakeup\n");
+		if (g_raydium_ts->irq_wake) {
+			disable_irq_wake(g_raydium_ts->irq);
+			g_raydium_ts->irq_wake = 0;
+		}
+	} else
+		pr_info("[touch]Device not wakeup\n");
+#endif
+
+	g_raydium_ts->is_suspend = 0;
+}
+
+static int raydium_ts_suspend(struct device *dev)
+{
+	raydium_ts_do_suspend();
+	return 0;
+}
+
+static int raydium_ts_resume(struct device *dev)
+{
+	raydium_ts_do_resume();
+	return 0;
+}
+
+static const struct dev_pm_ops raydium_ts_pm_ops = {
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
+	.suspend    = raydium_ts_suspend,
+	.resume        = raydium_ts_resume,
+#endif /*end of CONFIG_PM*/
+};
+
+/*used for touch lock feature*/
+static int raydium_ts_open(struct input_dev *input_dev)
+{
+	int i32_ret = 0;
+
+	pr_info("[touch]%s()+\n", __func__);
+
+	pr_info("[touch]ts->blank:%x\n", g_raydium_ts->blank);
+
+	if (g_raydium_ts->is_sleep == 1) {
+		mutex_lock(&g_raydium_ts->lock);
+		if (gpio_is_valid(g_raydium_ts->rst_gpio)) {
+
+			g_u8_resetflag = true;
+			gpio_set_value(g_raydium_ts->rst_gpio, 1);
+			gpio_set_value(g_raydium_ts->rst_gpio, 0);
+			msleep(RAYDIUM_RESET_INTERVAL_MSEC);/*5ms*/
+			gpio_set_value(g_raydium_ts->rst_gpio, 1);
+			msleep(RAYDIUM_RESET_DELAY_MSEC);/*100ms*/
+			g_u8_i2c_mode = PDA2_MODE;
+		}
+		mutex_unlock(&g_raydium_ts->lock);
+		raydium_irq_control(ENABLE);
+		g_raydium_ts->is_sleep = 0;
+		pr_info("[touch]disable touch lock.\n");
+	}
+	return i32_ret;
+}
+
+static void raydium_ts_close(struct input_dev *input_dev)
+{
+	int i32_ret = 0;
+	unsigned char u8_i = 0;
+	unsigned char u8_wbuffer[1];
+
+	pr_info("[touch]%s()+\n", __func__);
+
+	if (g_raydium_ts->is_sleep == 1) {
+		pr_info("[touch]touch lock already enabled.\n");
+		return;
+	}
+
+	raydium_irq_control(DISABLE);
+
+	for (u8_i = 0; u8_i < g_raydium_ts->u8_max_touchs; u8_i++) {
+		input_mt_slot(g_raydium_ts->input_dev, u8_i);
+		input_mt_report_slot_state(g_raydium_ts->input_dev,
+			MT_TOOL_FINGER,
+			false);
+	}
+	input_mt_report_pointer_emulation(g_raydium_ts->input_dev, false);
+	input_sync(g_raydium_ts->input_dev);
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+		g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0) {
+		pr_err("[touch]ret:%d\n", i32_ret);
+		goto exit_i2c_error;
+	}
+	u8_wbuffer[0] = RAYDIUM_HOST_CMD_PWR_SLEEP;
+	i32_ret = raydium_i2c_pda2_write(g_raydium_ts->client,
+		RAYDIUM_PDA2_HOST_CMD_ADDR,
+		u8_wbuffer,
+		1);
+	if (i32_ret < 0) {
+		pr_err("[touch]ret:%d\n", i32_ret);
+		goto exit_i2c_error;
+	}
+
+	mutex_unlock(&g_raydium_ts->lock);
+	g_raydium_ts->is_sleep = 1;
+	pr_info("[touch]enable touch lock.\n");
+	return;
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+}
+
+#else
+static int raydium_ts_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int raydium_ts_resume(struct device *dev)
+{
+	return 0;
+}
+#endif /*end of CONFIG_FB*/
+
+#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;
+
+	if (evdata && evdata->data && event == FB_EVENT_BLANK &&
+	    g_raydium_ts && g_raydium_ts->client) {
+		blank = evdata->data;
+		g_raydium_ts->blank = (*blank);
+		switch (*blank) {
+
+		/*screen on*/
+		case FB_BLANK_UNBLANK:
+			pr_info("[touch]FB_BLANK_UNBLANK\n");
+#ifdef GESTURE_EN
+
+			/* clear palm status */
+
+			g_raydium_ts->is_palm = 0;
+#endif
+#ifdef HOST_NOTIFY_EN
+			raydium_notify_function(ACTIVE_MODE);
+#endif
+			raydium_ts_resume(&g_raydium_ts->client->dev);
+			break;
+
+		/*screen off*/
+		case FB_BLANK_POWERDOWN:
+			pr_info("[touch]FB_BLANK_POWERDOWN\n");
+#ifdef GESTURE_EN
+
+			/* clear palm status */
+
+			g_raydium_ts->is_palm = 0;
+#endif
+#ifdef HOST_NOTIFY_EN
+			raydium_notify_function(SLEEP_MODE);
+#endif
+			raydium_ts_suspend(&g_raydium_ts->client->dev);
+			break;
+
+		/*ambient mode*/
+		case FB_BLANK_VSYNC_SUSPEND:
+			pr_info("[touch]FB_BLANK_VSYNC_SUSPEND\n");
+#ifdef GESTURE_EN
+
+			/* clear palm status */
+
+			g_raydium_ts->is_palm = 0;
+#endif
+#ifdef HOST_NOTIFY_EN
+			raydium_notify_function(AMBIENT_MODE);
+#endif
+			raydium_ts_suspend(&g_raydium_ts->client->dev);
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void raydium_register_notifier(void)
+{
+	memset(&g_raydium_ts->fb_notif, 0, sizeof(g_raydium_ts->fb_notif));
+	g_raydium_ts->fb_notif.notifier_call = fb_notifier_callback;
+
+	/* register on the fb notifier and work with fb*/
+	if (fb_register_client(&g_raydium_ts->fb_notif))
+		pr_err("[touch]register notifier failed\n");
+}
+
+static void raydium_unregister_notifier(void)
+{
+	fb_unregister_client(&g_raydium_ts->fb_notif);
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void raydium_ts_early_suspend(struct early_suspend *handler)
+{
+
+	raydium_ts_do_suspend();
+}
+
+static void raydium_ts_late_resume(struct early_suspend *handler)
+{
+	raydium_ts_do_resume();
+}
+#endif /*end of CONFIG_FB*/
+
+#ifdef CONFIG_OF
+static int raydium_get_dt_coords(struct device *dev, char *name,
+				 struct raydium_ts_platform_data *pdata)
+{
+	u32 coords[COORDS_ARR_SIZE];
+	struct property *prop;
+	struct device_node *np = dev->of_node;
+	int coords_size, rc;
+
+	prop = of_find_property(np, name, NULL);
+	if (!prop)
+		return -EINVAL;
+
+	if (!prop->value)
+		return -ENODATA;
+
+
+	coords_size = prop->length / sizeof(u32);
+	if (coords_size != COORDS_ARR_SIZE) {
+		pr_err("[touch]invalid %s\n", name);
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32_array(np, name, coords, coords_size);
+	if (rc && (rc != -EINVAL)) {
+		pr_err("[touch]unable to read %s\n", name);
+		return rc;
+	}
+
+	if (!strcmp(name, "raydium,display-coords")) {
+		pdata->x_min = coords[0];
+		pdata->y_min = coords[1];
+		pdata->x_max = coords[2];
+		pdata->y_max = coords[3];
+	} else {
+		pr_err("[touch]unsupported property %s\n", name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int raydium_parse_dt(struct device *dev,
+			    struct raydium_ts_platform_data *pdata)
+{
+	struct device_node *np = dev->of_node;
+	int rc = 0;
+	u32 temp_val = 0;
+
+	pdata->name = RAYDIUM_NAME;
+
+	rc = raydium_get_dt_coords(dev, "raydium,display-coords", pdata);
+	if (rc)
+		return rc;
+
+
+	/* reset, irq gpio info */
+	pdata->reset_gpio = of_get_named_gpio_flags(np,
+			    "raydium,reset-gpio",
+			    0,
+			    &pdata->reset_gpio_flags);
+	if (pdata->reset_gpio < 0)
+		return pdata->reset_gpio;
+
+
+	pdata->irq_gpio = of_get_named_gpio_flags(np,
+			  "raydium,irq-gpio",
+			  0,
+			  &pdata->irq_gpio_flags);
+	if (pdata->irq_gpio < 0)
+		return pdata->irq_gpio;
+
+
+	rc = of_property_read_u32(np,
+			"raydium,hard-reset-delay-ms", &temp_val);
+	if (!rc)
+		pdata->hard_rst_dly = temp_val;
+	else
+		return rc;
+
+
+	rc = of_property_read_u32(np,
+			"raydium,soft-reset-delay-ms", &temp_val);
+	if (!rc)
+		pdata->soft_rst_dly = temp_val;
+	else
+		return rc;
+
+
+	rc = of_property_read_u32(np, "raydium,num-max-touches", &temp_val);
+	if (!rc)
+		pdata->num_max_touches = temp_val;
+	else
+		return rc;
+#ifdef FW_MAPPING_BYID_EN
+	rc = of_property_read_u32(np, "raydium,fw_id", &temp_val);
+	if (!rc)
+		pdata->fw_id = temp_val;
+	else
+		return rc;
+#endif
+	return 0;
+}
+#else
+static int raydium_parse_dt(struct device *dev,
+			    struct raydium_ts_platform_data *pdata)
+{
+	return -ENODEV;
+}
+#endif /*end of CONFIG_OF*/
+
+static void raydium_input_set(struct input_dev *input_dev)
+{
+	int ret = 0;
+	unsigned char i;
+
+	input_dev->name = "raydium_ts";/*name need same with .idc*/
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &g_raydium_ts->client->dev;
+	input_dev->open = raydium_ts_open;/*touch lock*/
+	input_dev->close = raydium_ts_close;
+	input_set_drvdata(input_dev, g_raydium_ts);
+
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+	pr_info("[touch]set abs prarams x[%d], y[%d]\n",
+		g_raydium_ts->x_max, g_raydium_ts->y_max);
+
+	/* Multitouch input params setup */
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, 
+				g_raydium_ts->x_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+				g_raydium_ts->y_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, PRESS_MAX, 0, 0);
+	input_set_abs_params(input_dev,
+		ABS_MT_TOUCH_MAJOR, 0, WIDTH_MAX, 0, 0);
+	input_set_abs_params(input_dev,
+		ABS_MT_TOUCH_MINOR, 0, WIDTH_MAX, 0, 0);
+
+	ret = input_mt_init_slots(input_dev, MAX_TOUCH_NUM,
+				  INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+	if (ret)
+		pr_err("[touch]failed to initialize MT slots: %d\n", ret);
+
+	for (i = 0; i < (MAX_TOUCH_NUM * 2); i++)
+		gst_slot[i] = gst_slot_init;
+
+}
+static int raydium_set_resolution(void)
+{
+	unsigned char u8_buf[4];
+	int i32_ret = -1;
+	unsigned int u32_x, u32_y;
+
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+			g_raydium_ts->is_suspend,
+			RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+				RAYDIUM_PDA2_DISPLAY_INFO_ADDR,
+				u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	u32_x = u8_buf[3] << 8 | u8_buf[2];
+	u32_y = u8_buf[1] << 8 | u8_buf[0];
+
+	pr_info("[touch]RAD display info x:%d, y:%d\n", u32_x, u32_y);
+
+	if (u32_x > 300 && u32_y > 300 &&
+			u32_x < 600 && u32_y < 600) {
+		g_raydium_ts->x_max = u32_x - 1;
+		g_raydium_ts->y_max = u32_y - 1;
+	}
+
+exit_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	return i32_ret;
+}
+
+static int raydium_ts_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	struct raydium_ts_platform_data *pdata =
+		(struct raydium_ts_platform_data *)client->dev.platform_data;
+
+	struct input_dev *input_dev;
+	unsigned short u16_i2c_data;
+	int ret = 0;
+
+	pr_info("[touch] probe\n");
+
+	if (client->dev.of_node) {
+		pdata = devm_kzalloc(&client->dev,
+				     sizeof(struct raydium_ts_platform_data),
+				     GFP_KERNEL);
+		if (!pdata) {
+			dev_err(&client->dev,
+				"[touch]failed to allocate memory\n");
+			return -ENOMEM;
+		}
+
+		ret = raydium_parse_dt(&client->dev, pdata);
+		if (ret) {
+			dev_err(&client->dev,
+				"[touch]device tree parsing failed\n");
+			goto parse_dt_failed;
+		}
+	} else
+		pdata = client->dev.platform_data;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		ret = -ENODEV;
+		goto exit_check_functionality_failed;
+	}
+	
+	g_raydium_ts = devm_kzalloc(&client->dev,
+				  sizeof(struct raydium_ts_data),
+				  GFP_KERNEL);
+	if (!g_raydium_ts) {
+		pr_err("[touch]failed to allocate input driver data\n");
+		return -ENOMEM;
+	}
+	
+	raydium_variable_init();
+
+	mutex_init(&g_raydium_ts->lock);
+
+	i2c_set_clientdata(client, g_raydium_ts);
+	g_raydium_ts->irq_enabled = false;
+	g_raydium_ts->irq_wake = false;
+
+	g_raydium_ts->irq_gpio = pdata->irq_gpio;
+	g_raydium_ts->rst_gpio = pdata->reset_gpio;
+	client->irq = g_raydium_ts->irq_gpio;
+	g_raydium_ts->u8_max_touchs = pdata->num_max_touches;
+	g_raydium_ts->client = client;
+	g_raydium_ts->x_max = pdata->x_max - 1;
+	g_raydium_ts->y_max = pdata->y_max - 1;
+	g_raydium_ts->is_suspend = 0;
+	g_raydium_ts->is_sleep = 0;
+#ifdef GESTURE_EN
+	g_raydium_ts->is_palm = 0;
+#endif
+	g_raydium_ts->fw_version = 0;
+	device_init_wakeup(&client->dev, 1);
+
+#ifdef MSM_NEW_VER
+	ret = raydium_ts_pinctrl_init();
+	if (!ret && g_raydium_ts->ts_pinctrl) {
+		/*
+		 * Pinctrl handle is optional. If pinctrl handle is found
+		 * let pins to be configured in active state. If not
+		 * found continue further without error.
+		 */
+		ret = pinctrl_select_state(g_raydium_ts->ts_pinctrl,
+					   g_raydium_ts->pinctrl_state_active);
+		if (ret < 0)
+			pr_err("[touch]failed to set pin to active state\n");
+	}
+#endif /*end of MSM_NEW_VER*/
+
+	ret = raydium_gpio_configure(true);
+	if (ret < 0) {
+		pr_err("[touch]failed to configure the gpios\n");
+		goto err_gpio_req;
+	}
+	/*modify dtsi to 360*/
+	msleep(pdata->soft_rst_dly);
+
+	/*print touch i2c ready*/
+	ret = raydium_check_i2c_ready(&u16_i2c_data);
+	if (ret < 0) {
+		pr_err("[touch]Check I2C failed\n");
+		ret = -ENODEV;
+		goto exit_check_i2c;
+	}
+
+	/*input device initialization*/
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		ret = -ENOMEM;
+		pr_err("[touch]failed to allocate input device\n");
+		goto exit_input_dev_alloc_failed;
+	}
+
+	raydium_set_resolution();
+
+	g_raydium_ts->input_dev = input_dev;
+	raydium_input_set(input_dev);
+
+	ret = input_register_device(input_dev);
+	if (ret) {
+		pr_err("[touch]failed to register input device: %s\n",
+			dev_name(&client->dev));
+		goto exit_input_register_device_failed;
+	}
+
+#ifdef GESTURE_EN
+	input_set_capability(input_dev, EV_KEY, KEY_SLEEP);
+	input_set_capability(input_dev, EV_KEY, KEY_POWER);
+#endif
+
+	/*suspend/resume routine*/
+#if defined(CONFIG_FB)
+	raydium_register_notifier();
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	/*Early-suspend level*/
+	g_raydium_ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	g_raydium_ts->early_suspend.suspend = raydium_ts_early_suspend;
+	g_raydium_ts->early_suspend.resume = raydium_ts_late_resume;
+	register_early_suspend(&g_raydium_ts->early_suspend);
+#endif/*end of CONFIG_FB*/
+
+#ifdef CONFIG_RM_SYSFS_DEBUG
+	raydium_create_sysfs(client);
+#endif/*end of CONFIG_RM_SYSFS_DEBUG*/
+
+	INIT_WORK(&g_raydium_ts->work, raydium_work_handler);
+
+	g_raydium_ts->workqueue = create_singlethread_workqueue("raydium_ts");
+#ifdef ENABLE_DUMP_DATA
+	INIT_DELAYED_WORK(&g_raydium_ts->dump_work, raydium_dump_data_work);
+#endif
+	/*irq_gpio = 13 irqflags = 108*/
+	pr_info("[touch]pdata irq : %d\n", g_raydium_ts->irq_gpio);
+	pr_info("[touch]client irq : %d, pdata flags : %d\n",
+		client->irq, pdata->irqflags);
+
+	g_raydium_ts->irq = gpio_to_irq(pdata->irq_gpio);
+	ret = request_threaded_irq(g_raydium_ts->irq, NULL, raydium_ts_interrupt,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_NO_SUSPEND,
+			client->dev.driver->name, g_raydium_ts);
+
+	if (ret < 0) {
+		pr_err("[touch]raydium_probe: request irq failed\n");
+		goto exit_irq_request_failed;
+	}
+
+	g_raydium_ts->irq_desc = irq_to_desc(g_raydium_ts->irq);
+	g_raydium_ts->irq_enabled = true;
+
+	/*disable_irq then enable_irq for avoid Unbalanced enable for IRQ */
+
+	/*raydium_irq_control(ts, ENABLE);*/
+
+	pr_info("[touch]RAD Touch driver ver :0x%X\n", g_u32_driver_version);
+
+	/*fw update check*/
+	ret = raydium_fw_update_check(u16_i2c_data);
+	if (ret < 0) {
+		pr_err("[touch]FW update check failed\n");
+		ret = -ENODEV;
+		goto exit_irq_request_failed;
+	}
+	return 0;
+
+exit_irq_request_failed:
+#if defined(CONFIG_FB)
+	raydium_unregister_notifier();
+#endif/*end of CONFIG_FB*/
+
+	cancel_work_sync(&g_raydium_ts->work);
+	input_unregister_device(input_dev);
+
+exit_input_register_device_failed:
+	input_free_device(input_dev);
+
+exit_input_dev_alloc_failed:
+exit_check_i2c:
+	if (gpio_is_valid(pdata->reset_gpio))
+		gpio_free(pdata->reset_gpio);
+
+	if (gpio_is_valid(pdata->irq_gpio))
+		gpio_free(pdata->irq_gpio);
+
+err_gpio_req:
+#ifdef MSM_NEW_VER
+	if (g_raydium_ts->ts_pinctrl) {
+		if (IS_ERR_OR_NULL(g_raydium_ts->pinctrl_state_release)) {
+			devm_pinctrl_put(g_raydium_ts->ts_pinctrl);
+			g_raydium_ts->ts_pinctrl = NULL;
+		} else {
+			ret = pinctrl_select_state(g_raydium_ts->ts_pinctrl,
+					g_raydium_ts->pinctrl_state_release);
+			if (ret)
+				pr_err("[touch]pinctrl_select_state failed\n");
+		}
+	}
+#endif/*end of MSM_NEW_VER*/
+
+parse_dt_failed:
+exit_check_functionality_failed:
+	return ret;
+
+}
+
+static int raydium_ts_remove(struct i2c_client *client)
+{
+
+#if defined(CONFIG_FB)
+	raydium_unregister_notifier();
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	unregister_early_suspend(&g_raydium_ts->early_suspend);
+#endif/*end of CONFIG_FB*/
+	input_unregister_device(g_raydium_ts->input_dev);
+	input_free_device(g_raydium_ts->input_dev);
+	gpio_free(g_raydium_ts->rst_gpio);
+
+#ifdef CONFIG_RM_SYSFS_DEBUG
+	raydium_release_sysfs(client);
+#endif /*end of CONFIG_RM_SYSFS_DEBUG*/
+
+	free_irq(client->irq, g_raydium_ts);
+
+	if (gpio_is_valid(g_raydium_ts->rst_gpio))
+		gpio_free(g_raydium_ts->rst_gpio);
+
+	if (gpio_is_valid(g_raydium_ts->irq_gpio))
+		gpio_free(g_raydium_ts->irq_gpio);
+
+	cancel_work_sync(&g_raydium_ts->work);
+	destroy_workqueue(g_raydium_ts->workqueue);
+
+
+	kfree(g_raydium_ts);
+
+	i2c_set_clientdata(client, NULL);
+	return 0;
+}
+
+static const struct i2c_device_id raydium_ts_id[] = {
+	{RAYDIUM_NAME, 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, raydium_ts_id);
+
+#ifdef CONFIG_OF
+static struct of_device_id raydium_match_table[] = {
+	{ .compatible = "raydium,raydium-ts",},
+	{ },
+};
+#else
+#define raydium_match_table NULL
+#endif/*end of CONFIG_OF*/
+
+static struct i2c_driver raydium_ts_driver = {
+	.probe = raydium_ts_probe,
+	.remove = raydium_ts_remove,
+	.id_table = raydium_ts_id,
+	.driver = {
+		.name = RAYDIUM_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = raydium_match_table,
+#if defined(CONFIG_PM)
+		.pm    = &raydium_ts_pm_ops,
+#endif/*end of CONFIG_PM*/
+	},
+};
+
+static int __init raydium_ts_init(void)
+{
+	int ret;
+
+	ret = i2c_add_driver(&raydium_ts_driver);
+	return ret;
+}
+
+static void __exit raydium_ts_exit(void)
+{
+	i2c_del_driver(&raydium_ts_driver);
+}
+
+module_init(raydium_ts_init);
+module_exit(raydium_ts_exit);
+
+MODULE_AUTHOR("Raydium");
+MODULE_DESCRIPTION("Raydium TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_driver.h b/drivers/input/touchscreen/raydium_wt030/raydium_driver.h
new file mode 100644
index 0000000..415e0af
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_driver.h
@@ -0,0 +1,375 @@
+/* drivers/input/touchscreen/raydium_wt030/raydium_driver.h
+ *
+ * Raydium TouchScreen driver.
+ *
+ * Copyright (c) 2010  Raydium tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __LINUX_RAYDIUM_H
+#define __LINUX_RAYDIUM_H
+#define RAYDIUM_NAME "raydium_ts"
+#define COORDS_ARR_SIZE    4
+#define I2C_VTG_MIN_UV    1800000
+#define I2C_VTG_MAX_UV    1800000
+#define RAD_MAIN_VERSION	0x01
+#define RAD_MINOR_VERSION	0x07
+#define RAD_CUSTOMER_VERSION	0x0100
+
+#if defined(CONFIG_TOUCHSCREEN_RM_TS)
+/* IC timing control arguments */
+#define RAYDIUM_POWERON_DELAY_USEC    500
+#define RAYDIUM_RESET_INTERVAL_MSEC   5
+#define RAYDIUM_RESET_RESTORE_USEC    200
+#define RAYDIUM_RESET_DELAY_MSEC      100
+
+/* I2C bus slave address(ID) */
+#define RAYDIUM_I2C_EID    (0x5A)
+#define RAYDIUM_I2C_NID    (0x39)
+
+/* I2C R/W configuration literal */
+#define RAYDIUM_I2C_WRITE       I2C_SMBUS_WRITE
+#define RAYDIUM_I2C_READ        I2C_SMBUS_READ
+#define SYN_I2C_RETRY_TIMES     2
+#define MAX_WRITE_PACKET_SIZE   64
+#define MAX_READ_PACKET_SIZE    64
+
+/* PDA address and bit definition*/
+#define RAD_READ_FT_DATA_CMD        0x2000019C
+/* 1byte, disable:0x00 ; enable:0x20*/
+#define RAD_GESTURE_STATE_CMD       0x200005F4
+#define RAD_GESTURE_DISABLE         0x00
+#define RAD_GESTURE_ENABLE          0x20
+/* 4bytes, [0]:ready ; [1]:type ; [2]:direction*/
+#define RAD_GESTURE_RESULT_CMD      0x200005F0
+#define RAD_CHK_I2C_CMD				0x500009BC
+#define RAD_PDA2_CTRL_CMD           0x50000628
+#define RAD_ENABLE_PDA2             0x04
+#define RAD_ENABLE_SI2				0x02
+
+/* PDA literal */
+#define MASK_8BIT    0xFF
+#define RAD_I2C_PDA_ADDRESS_LENGTH    4
+#define PDA_MODE     1
+#define PDA2_MODE    2
+#define RAD_I2C_PDA_MODE_DISABLE      0x00
+#define RAD_I2C_PDA_MODE_ENABLE       0x80
+/* Using byte mode due to data might be not word-aligment */
+#define RAD_I2C_PDA_MODE_WORD_MODE    0x40
+#define RAD_I2C_PDA_2_MODE_DISABLE    0x20
+#define RAD_PALM_DISABLE    0x00
+#define RAD_PALM_ENABLE     0x01
+#define RAD_WAKE_UP			0x02
+#define RAYDIUM_TEST_FW	0x80
+#define RAYDIUM_TEST_PARA	0x40
+#define RAYDIUM_BOOTLOADER	0x20
+#define RAYDIUM_FIRMWARE	0x10
+#define RAYDIUM_PARA		0x08
+#define RAYDIUM_COMP		0x04
+#define RAYDIUM_BASELINE	0x02
+#define RAYDIUM_INIT		0x01
+#define FAIL          0
+#define ERROR        -1
+#define SUCCESS       1
+#define DISABLE       0
+#define ENABLE        1
+
+/* PDA2 setting */
+/* Page 0 ~ Page A */
+#define MAX_PAGE_AMOUNT    11
+
+/* PDA2 address and setting definition*/
+#define RAYDIUM_PDA2_TCH_RPT_STATUS_ADDR    0x00    /* only in Page 0 */
+#define RAYDIUM_PDA2_TCH_RPT_ADDR           0x01    /* only in Page 0 */
+#define RAYDIUM_PDA2_HOST_CMD_ADDR          0x02    /* only in Page 0 */
+#define RAYDIUM_PDA2_PALM_AREA_ADDR         0x03    /* only in Page 0 */
+#define RAYDIUM_PDA2_GESTURE_RPT_ADDR       0x04    /* only in Page 0 */
+#define RAYDIUM_PDA2_PALM_STATUS_ADDR       0x05    /* only in Page 0 */
+#define RAYDIUM_PDA2_FW_VERSION_ADDR        0x06    /* only in Page 0 */
+#define RAYDIUM_PDA2_PANEL_VERSION_ADDR     0x07    /* only in Page 0 */
+#define RAYDIUM_PDA2_DISPLAY_INFO_ADDR		0x08    /* only in Page 0 */
+#define RAYDIUM_PDA2_PDA_CFG_ADDR           0x09    /* only in Page 0 */
+#define RAYDIUM_PDA2_RAWDATA_ADDR           0x0B    /* only in Page 0 */
+/* Page 0 ~ Page 9 will be directed to Page 0 */
+#define RAYDIUM_PDA2_PAGE_ADDR              0x0A
+#define RAYDIUM_PDA2_PAGE_0                 0x00
+/* temporary switch to PDA once */
+#define RAYDIUM_PDA2_ENABLE_PDA             0x0A
+/* permanently switch to PDA mode */
+#define RAYDIUM_PDA2_2_PDA                  (MAX_PAGE_AMOUNT + 2)
+
+/* Raydium host cmd */
+#define RAYDIUM_HOST_CMD_NO_OP              0x00
+#define RAYDIUM_HOST_CMD_PWR_SLEEP          0x30
+#define RAYDIUM_HOST_CMD_DISPLAY_MODE	0x33
+#define RAYDIUM_HOST_CMD_CALIBRATION        0x5C
+#define RAYDIUM_HOST_CMD_TP_MODE            0x60
+#define RAYDIUM_HOST_CMD_FT_MODE            0x61
+
+/* PDA2 literal */
+/* entry byte + target page byte */
+#define RAYDIUM_I2C_PDA2_PAGE_LENGTH        2
+
+
+/* Touch report */
+#define MAX_TOUCH_NUM                 2
+#define MAX_REPORT_PACKET_SIZE        35
+#define MAX_TCH_STATUS_PACKET_SIZE    4
+#define PRESS_MAX                     0xFFFF
+#define WIDTH_MAX                     0xFFFF
+#define BYTE_SHIFT         8
+
+/* FW update literal */
+#define RAYDIUM_FW_BIN_PATH_LENGTH    256
+
+#define RAD_BOOT_1X_SIZE		0x800
+#define RAD_INIT_1X_SIZE		0x200
+#define RAD_FW_1X_SIZE			0x5000
+#define RAD_PARA_1X_SIZE		0xE4
+#define RAD_TESTFW_1X_SIZE		0x5600
+
+#define RAD_BOOT_2X_SIZE		0x800
+#define RAD_INIT_2X_SIZE		0x200
+#define RAD_FW_2X_SIZE			0x6200
+#define RAD_PARA_2X_SIZE		0x15C
+#define RAD_TESTFW_2X_SIZE		(RAD_FW_2X_SIZE + RAD_PARA_2X_SIZE + 4)
+
+#define RAD_CMD_UPDATE_BIN		0x80
+#define RAD_CMD_UPDATE_END		0x81
+#define RAD_CMD_BURN_FINISH		0x82
+
+/* FT APK literal */
+#define RAD_HOST_CMD_POS    0x00
+#define RAD_FT_CMD_POS      0x01
+#define RAD_FT_CMD_LENGTH   0x02
+
+/* FT APK data type */
+#define RAYDIUM_FT_UPDATE    0x01
+
+/*Raydium system flag*/
+#define INT_FLAG	0x01
+#define ENG_MODE	0x02
+
+/* define display mode */
+#define ACTIVE_MODE     0x00
+#define AMBIENT_MODE    0x01
+#define SLEEP_MODE      0x02
+
+/* Enable sysfs */
+#define CONFIG_RM_SYSFS_DEBUG
+
+/* Gesture switch */
+#define GESTURE_EN
+
+/* Enable FW update */
+/* #define FW_UPDATE_EN */
+/* #define FW_MAPPING_EN */
+#define HOST_NOTIFY_EN
+#define MSM_NEW_VER
+
+/* enable ESD */
+/* #define ESD_SOLUTION_EN */
+/* #define ENABLE_DUMP_DATA */
+/* #define ENABLE_FLASHLOG_BACKUP */
+#ifdef ENABLE_DUMP_DATA
+#define DATA_MAP_5_5 0
+#endif
+
+
+
+#define PINCTRL_STATE_ACTIVE     "pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND    "pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE    "pmx_ts_release"
+
+#if defined(CONFIG_TOUCHSCREEN_RM_TS_SELFTEST)
+#define RAD_SELFTEST
+#endif
+
+struct raydium_ts_data {
+	unsigned int irq;
+	unsigned int irq_gpio;
+	unsigned int rst_gpio;
+	unsigned int x_max;
+	unsigned int y_max;
+#ifdef FILTER_POINTS
+	unsigned int x_pos[2];
+	unsigned int y_pos[2];
+	unsigned int last_x_pos[2];
+	unsigned int last_y_pos[2];
+#else
+	unsigned int x_pos[2];
+	unsigned int y_pos[2];
+#endif
+	unsigned int pressure;
+	unsigned int is_suspend;
+	unsigned int is_sleep;
+#ifdef GESTURE_EN
+	unsigned int is_palm;
+#endif
+	unsigned char u8_max_touchs;
+
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	struct mutex lock;
+	struct work_struct  work;
+	struct workqueue_struct *workqueue;
+	struct irq_desc *irq_desc;
+	bool irq_enabled;
+	bool irq_wake;
+
+#if defined(CONFIG_FB)
+	struct notifier_block fb_notif;
+	int blank;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	struct early_suspend early_suspend;
+#endif /*end of CONFIG_FB*/
+
+	/*struct regulator *vdd;*/
+	struct regulator *vcc_i2c;
+	unsigned int fw_version;
+	unsigned short id;
+	char *vcc_name;
+#ifdef MSM_NEW_VER
+	struct pinctrl *ts_pinctrl;
+	struct pinctrl_state *pinctrl_state_active;
+	struct pinctrl_state *pinctrl_state_suspend;
+	struct pinctrl_state *pinctrl_state_release;
+#endif /*end of MSM_NEW_VER*/
+
+#ifdef ENABLE_DUMP_DATA
+	struct delayed_work dump_work;
+
+#endif /*end of ENABLE_DUMP_DATA*/
+
+};
+struct raydium_platform_data {
+	char *vdd_name;
+	int irq_gpio_number;
+	int reset_gpio_number;
+	int x_max;
+	int y_max;
+};
+
+struct raydium_ts_platform_data {
+	char *name;
+	u32 irqflags;
+	u32 irq_gpio;
+	u32 irq_gpio_flags;
+	u32 reset_gpio;
+	u32 reset_gpio_flags;
+	u32 x_max;
+	u32 y_max;
+	u32 x_min;
+	u32 y_min;
+	u32 hard_rst_dly;
+	u32 soft_rst_dly;
+	u32 num_max_touches;
+	u32 fw_id;
+};
+
+/* TODO: Using struct+memcpy instead of array+offset*/
+enum raydium_pt_report_status {
+	POS_SEQ = 0,/*1:touch, 0:no touch*/
+	POS_PT_AMOUNT,
+	POS_GES_STATUS,
+	POS_FW_STATE,
+};
+
+enum raydium_pt_report_idx {
+	POS_PT_ID = 0,
+	POS_X_L,
+	POS_X_H,
+	POS_Y_L,
+	POS_Y_H,
+	POS_PRESSURE_L,
+	POS_PRESSURE_H,
+	POS_WX_L,
+	POS_WX_H,
+	POS_WY_L,
+	POS_WY_H,
+	LEN_PT = 11
+};
+
+extern int raydium_read_touchdata(unsigned char *tp_status,  unsigned char *buf);
+extern unsigned char raydium_mem_table_setting(void);
+extern int wait_fw_state(struct i2c_client *client, unsigned int u32_addr,
+			 unsigned int u32_state, unsigned long u32_delay_us,
+			 unsigned short u16_retry);
+extern int wait_irq_state(struct i2c_client *client,
+				unsigned int u32_retry_time,
+				unsigned int u32_delay_us);
+extern void raydium_irq_control(bool enable);
+
+extern int raydium_i2c_mode_control(struct i2c_client *client,
+				    unsigned char u8_mode);
+extern int raydium_i2c_pda_read(struct i2c_client *client,
+				unsigned int u32_addr, unsigned char *u8_r_data,
+				unsigned short u16_length);
+extern int raydium_i2c_pda_write(struct i2c_client *client,
+			unsigned int u32_addr, unsigned char *u8_w_data,
+			unsigned short u16_length);
+extern int raydium_i2c_pda2_read(struct i2c_client *client,
+				 unsigned char u8_addr,
+				 unsigned char *u8_r_data,
+				 unsigned short u16_length);
+extern int raydium_i2c_pda2_write(struct i2c_client *client,
+				  unsigned char u8_addr,
+				  unsigned char *u8_w_data,
+				  unsigned short u16_length);
+extern int raydium_i2c_pda2_set_page(struct i2c_client *client,
+				unsigned int is_suspend,
+				unsigned char u8_page);
+extern unsigned char raydium_selftest_stop_mcu(struct i2c_client *client);
+extern int raydium_burn_comp(struct i2c_client *client);
+extern int raydium_burn_fw(struct i2c_client *client);
+extern int raydium_fw_upgrade_with_bin_file(struct i2c_client *client,
+		char *arguments,
+		size_t count,
+		struct device *dev);
+extern int raydium_load_test_fw(struct i2c_client *client);
+extern int raydium_fw_update_check(unsigned short u16_i2c_data);
+extern int raydium_i2c_pda_set_address(unsigned int u32_address,
+				       unsigned char u8_mode);
+extern unsigned char raydium_mem_table_init(unsigned short u16_id);
+extern unsigned char raydium_id_init(unsigned char u8_type);
+
+#ifdef RAD_SELFTEST
+extern int raydium_do_selftest(void);
+#endif
+int raydium_esd_check(void);
+
+extern struct attribute *raydium_attributes[];
+extern const struct attribute_group raydium_attr_group;
+
+extern unsigned char g_u8_raydium_flag;
+extern unsigned char g_u8_addr;
+extern unsigned char g_u8_i2c_mode;
+extern unsigned char g_u8_upgrade_type;
+extern unsigned char g_u8_raw_data_type;
+extern unsigned int g_u32_raw_data_len;    /* 72 bytes*/
+extern unsigned int g_u32_length;
+extern unsigned long g_u32_addr;
+extern unsigned char *g_rad_fw_image, *g_rad_init_image;
+extern unsigned char *g_rad_boot_image, *g_rad_para_image;
+extern unsigned char *g_rad_testfw_image, *g_rad_testpara_image;
+extern unsigned char g_u8_table_setting, g_u8_table_init;
+extern unsigned int g_u32_driver_version;
+extern unsigned char g_u8_resetflag;
+extern struct raydium_ts_data *g_raydium_ts;
+
+#endif
+#endif  /*__LINUX_RAYDIUM_H*/
+
+MODULE_AUTHOR("Raydium");
+MODULE_DESCRIPTION("Raydium TouchScreen driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c b/drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c
new file mode 100644
index 0000000..6cd9bd7
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c
@@ -0,0 +1,1844 @@
+/* drivers/input/touchscreen/raydium_wt030/raydium_fw_update.c
+ *
+ * Raydium TouchScreen driver.
+ *
+ * Copyright (c) 2010  Raydium tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/device.h>
+#include <asm/traps.h>
+#include <linux/firmware.h>
+#include "raydium_driver.h"
+#include "rad_fw_image_20.h"
+#if defined(FW_MAPPING_EN)
+#include "rad_fw_image_21.h"
+#endif
+
+#ifdef ENABLE_FLASHLOG_BACKUP
+unsigned char raydium_turn_on_flash_2X(struct i2c_client *client)
+{
+	unsigned int u32_read = 0;
+	unsigned char u8_buf[4];
+	/*Turn on Flash*/
+	memset(u8_buf, 0,  sizeof(u8_buf));
+	if (raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	u8_buf[0] = 0x20;
+	if (raydium_i2c_pda_write(client, 0x50000914, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	return SUCCESS;
+}
+
+unsigned char  raydium_read_fpc_flash(struct i2c_client *client,
+			unsigned int u32_addr, unsigned char *u8_r_data)
+{
+	unsigned int u32_read;
+	unsigned char u8_buf[4];
+
+	pr_info("[touch]raydium_read_fpc_flash\n");
+
+	if (raydium_i2c_pda_read(client, 0x40000000, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	u8_buf[0] |= 0x40;
+	if (raydium_i2c_pda_write(client, 0x40000000, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	memset(u8_buf, 0,  sizeof(u8_buf));
+	if (raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	u8_buf[0] =  (u32_addr & 0x000000FF);
+	u8_buf[1] = ((u32_addr & 0x0000FF00) >> 8);
+	u8_buf[2] = ((u32_addr & 0x00FF0000) >> 16);
+	u8_buf[3] = ((u32_addr & 0xFF000000) >> 24);
+
+	if (raydium_i2c_pda_write(client, 0x50000910, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	memset(u8_buf, 0,  sizeof(u8_buf));
+	u8_buf[0] = 0x40;
+
+	if (raydium_i2c_pda_write(client, 0x50000914, u8_buf, 4) == ERROR)
+		return ERROR;
+
+	usleep_range(950, 1050);
+
+	if (raydium_i2c_pda_read(client, 0x5000093C, u8_r_data, 4) == ERROR)
+		return ERROR;
+
+	return SUCCESS;
+}
+
+unsigned char raydium_read_flash_log(void)
+{
+	unsigned char u8_buf[4];
+	unsigned int u32_readbuf;
+	unsigned char u8_ret = 0;
+	unsigned char u8_logcount = 0;
+	unsigned int u32_temp = 0;
+	unsigned char u8_i = 0, u8_j = 0;
+
+	raydium_i2c_pda2_set_page(g_raydium_ts->client,
+		g_raydium_ts->is_suspend , RAYDIUM_PDA2_2_PDA);
+	g_u8_i2c_mode = PDA_MODE;
+	pr_info("[touch]Disable PDA2_MODE\n");
+
+	 if ((g_raydium_ts->id  & 0x2000) != 0)
+		raydium_turn_on_flash_2X(g_raydium_ts->client);
+
+	for (u8_i = 0; u8_i < 4; u8_i++) {
+		u32_temp = (0x9000 +  (u8_i*4));
+		raydium_read_fpc_flash(g_raydium_ts->client, u32_temp,  &u32_readbuf);
+		if (u8_i == 0 && u32_readbuf == 0xFFFFFFFF) {
+			pr_info("[touch]Raydium flash no log\n");
+			return FAIL;
+		}
+		pr_info("[touch]Raydium flash 0x%x = 0x%x\n",
+			u32_temp, u32_readbuf);
+		u32_readbuf = u32_readbuf & (~u32_readbuf + 1);
+		pr_info("[touch]Raydium flash reverse = 0x%x\n",
+			u32_readbuf);
+		u32_temp = 1;
+		u8_j = 0;
+		while (u32_readbuf != u32_temp) {
+			u8_j++;
+			u32_temp <<= 1;
+			if (u8_j == 32)
+				break;
+		}
+		if (u8_i == 0) {
+			if ((u8_j > 0) && (u8_j < 32)) {
+				u8_logcount = u8_i*32 + u8_j;
+				pr_info("[touch]logcount = Log%d\n",
+					(u8_logcount-1));
+				break;
+			}
+		} else {
+			if (u8_j < 32) {
+				u8_logcount = u8_i*32 + u8_j;
+				pr_info("[touch]logcount = Log%d\n",
+					(u8_logcount-1));
+				break;
+			}
+		}
+	}
+
+	if (u8_logcount != 0) {
+		u32_temp = (0x9014 + (u8_logcount-1) * 48);
+		raydium_read_fpc_flash(g_raydium_ts->client, u32_temp, u8_buf);
+		pr_info("[touch]Rad log fw version 0x%x.0x%x.0x%x.0x%x\n",
+			u8_buf[0], u8_buf[1], u8_buf[2], u8_buf[3]);
+		if ((g_raydium_ts->id  & 0x2000) != 0)
+			g_raydium_ts->id = 0x2000 | ((u8_buf[0] & 0xF) << 8) | u8_buf[1];
+
+		return SUCCESS;
+	}
+	return FAIL;
+}
+#endif
+unsigned char raydium_mem_table_init(unsigned short u16_id)
+{
+	unsigned int u8_ret = 0;
+
+	pr_info("[touch]Raydium table init 0x%x\n", u16_id);
+
+	 if ((u16_id & 0x2000) != 0) {
+		g_rad_boot_image = kzalloc(RAD_BOOT_2X_SIZE, GFP_KERNEL);
+		g_rad_init_image = kzalloc(RAD_INIT_2X_SIZE, GFP_KERNEL);
+		g_rad_fw_image = kzalloc(RAD_FW_2X_SIZE, GFP_KERNEL);
+		g_rad_para_image = kzalloc(RAD_PARA_2X_SIZE + 4, GFP_KERNEL);
+		g_rad_testfw_image = kzalloc(RAD_TESTFW_2X_SIZE, GFP_KERNEL);
+		g_rad_testpara_image = kzalloc(RAD_PARA_2X_SIZE + 4,
+								GFP_KERNEL);
+		g_u8_table_init = SUCCESS;
+		u8_ret = SUCCESS;
+	}
+
+	return u8_ret;
+}
+
+unsigned char raydium_mem_table_setting(void)
+{
+	unsigned char u8_ret = SUCCESS;
+#ifdef ENABLE_FLASHLOG_BACKUP
+	unsigned char u8_buf[4];
+	static unsigned char u8_readflash;
+#endif
+
+	pr_info("[touch]Raydium ID is 0x%x\n", g_raydium_ts->id);
+
+	switch (g_raydium_ts->id) {
+	case RAD_20:
+		memcpy(g_rad_boot_image, u8_rad_boot_20, RAD_BOOT_2X_SIZE);
+		memcpy(g_rad_init_image, u8_rad_init_20, RAD_INIT_2X_SIZE);
+		memcpy(g_rad_fw_image, u8_rad_fw_20, RAD_FW_2X_SIZE);
+		memcpy(g_rad_testfw_image, u8_rad_testfw_20, RAD_FW_2X_SIZE);
+		memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE,
+			u8_rad_testpara_20, RAD_PARA_2X_SIZE + 4);
+		if (g_rad_boot_image[0x82] >= 4) {
+			memcpy(g_rad_para_image,
+				u8_rad_para_20,
+				RAD_PARA_2X_SIZE + 4);
+			memcpy(g_rad_testpara_image,
+				u8_rad_testpara_20,
+				RAD_PARA_2X_SIZE + 4);
+		} else {
+			memcpy(g_rad_para_image,
+				u8_rad_para_20,
+				RAD_PARA_2X_SIZE);
+			memcpy(g_rad_testpara_image,
+				u8_rad_testpara_20,
+				RAD_PARA_2X_SIZE);
+		}
+		break;
+#if defined(FW_MAPPING_EN)
+	case RAD_21:
+		memcpy(g_rad_boot_image, u8_rad_boot_21, RAD_BOOT_2X_SIZE);
+		memcpy(g_rad_init_image, u8_rad_init_21, RAD_INIT_2X_SIZE);
+		memcpy(g_rad_fw_image, u8_rad_fw_21, RAD_FW_2X_SIZE);
+		memcpy(g_rad_testfw_image, u8_rad_testfw_21, RAD_FW_2X_SIZE);
+		memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE,
+			u8_rad_testpara_21,
+			RAD_PARA_2X_SIZE + 4);
+		if (g_rad_boot_image[0x82] >= 4) {
+			memcpy(g_rad_para_image,
+				u8_rad_para_21,
+				RAD_PARA_2X_SIZE + 4);
+			memcpy(g_rad_testpara_image,
+				u8_rad_testpara_21,
+				RAD_PARA_2X_SIZE + 4);
+		} else {
+			memcpy(g_rad_para_image,
+				u8_rad_para_21,
+				RAD_PARA_2X_SIZE);
+			memcpy(g_rad_testpara_image,
+				u8_rad_testpara_21,
+				RAD_PARA_2X_SIZE);
+		}
+		break;
+#endif
+	default:
+		pr_info("[touch]mapping ic setting use default fw\n");
+#ifdef ENABLE_FLASHLOG_BACKUP
+		if (!u8_readflash) {
+			u8_ret = raydium_read_flash_log();
+			u8_readflash = true;
+
+			raydium_i2c_pda_read(g_raydium_ts->client,
+					RAD_PDA2_CTRL_CMD,
+					u8_buf,
+					4);
+			u8_buf[0] |= RAD_ENABLE_PDA2 | RAD_ENABLE_SI2;
+			raydium_i2c_pda_write(g_raydium_ts->client,
+					RAD_PDA2_CTRL_CMD,
+					u8_buf,
+					4);
+			raydium_i2c_pda_set_address(0x50000628, DISABLE);
+
+			g_u8_i2c_mode = PDA2_MODE;
+			pr_info("[touch]Enable PDA2_MODE\n");
+			raydium_mem_table_setting();
+		} else {
+			if ((g_raydium_ts->id & 0x2000) != 0) {
+				memcpy(g_rad_boot_image,
+					u8_rad_boot_20,
+					RAD_BOOT_2X_SIZE);
+				memcpy(g_rad_init_image,
+					u8_rad_init_20,
+					RAD_INIT_2X_SIZE);
+				memcpy(g_rad_fw_image,
+					u8_rad_fw_20,
+					RAD_FW_2X_SIZE);
+				memcpy(g_rad_testfw_image,
+					u8_rad_testfw_20,
+					RAD_FW_2X_SIZE);
+				memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE,
+					u8_rad_testpara_20,
+					RAD_PARA_2X_SIZE + 4);
+				if (g_rad_boot_image[0x82] >= 4) {
+					memcpy(g_rad_para_image,
+						u8_rad_para_20,
+						RAD_PARA_2X_SIZE + 4);
+					memcpy(g_rad_testpara_image,
+						u8_rad_testpara_20,
+						RAD_PARA_2X_SIZE + 4);
+				} else {
+					memcpy(g_rad_para_image,
+						u8_rad_para_20,
+						RAD_PARA_2X_SIZE);
+					memcpy(g_rad_testpara_image,
+						u8_rad_testpara_20,
+						RAD_PARA_2X_SIZE);
+				}
+				g_raydium_ts->id = RAD_20;
+			}
+		}
+		u8_ret = SUCCESS;
+		break;
+#else
+		if ((g_raydium_ts->id & 0x2000) != 0) {
+			memcpy(g_rad_boot_image,
+				u8_rad_boot_20,
+				RAD_BOOT_2X_SIZE);
+			memcpy(g_rad_init_image,
+				u8_rad_init_20,
+				RAD_INIT_2X_SIZE);
+			memcpy(g_rad_fw_image,
+				u8_rad_fw_20,
+				RAD_FW_2X_SIZE);
+			memcpy(g_rad_testfw_image,
+				u8_rad_testfw_20,
+				RAD_FW_2X_SIZE);
+			memcpy(g_rad_testfw_image + RAD_FW_2X_SIZE,
+				u8_rad_testpara_20,
+				RAD_PARA_2X_SIZE + 4);
+			if (g_rad_boot_image[0x82] >= 4) {
+				memcpy(g_rad_para_image,
+					u8_rad_para_20,
+					RAD_PARA_2X_SIZE + 4);
+				memcpy(g_rad_testpara_image,
+					u8_rad_testpara_20,
+					RAD_PARA_2X_SIZE + 4);
+			} else {
+				memcpy(g_rad_para_image,
+					u8_rad_para_20,
+					RAD_PARA_2X_SIZE);
+				memcpy(g_rad_testpara_image,
+					u8_rad_testpara_20,
+					RAD_PARA_2X_SIZE);
+			}
+			g_raydium_ts->id = RAD_20;
+		}
+		u8_ret = SUCCESS;
+		break;
+#endif
+	}
+
+	g_u8_table_setting = 0;
+	return u8_ret;
+}
+
+unsigned char raydium_id_init(unsigned char u8_type)
+{
+	unsigned int u8_ret = SUCCESS;
+	u8_ret = 0;
+
+
+	switch (u8_type) {
+	case 0:
+		g_raydium_ts->id = RAD_20;
+		u8_ret = SUCCESS;
+		break;
+#if defined(FW_MAPPING_EN)
+	case 1:
+		g_raydium_ts->id = RAD_21;
+		u8_ret = SUCCESS;
+		break;
+#endif
+	}
+
+
+	return u8_ret;
+}
+
+static unsigned int bits_reverse(unsigned int u32_num, unsigned int bit_num)
+{
+	unsigned int reverse = 0, u32_i;
+
+	for (u32_i = 0; u32_i < bit_num; u32_i++) {
+		if (u32_num & (1 << u32_i))
+			reverse |= 1 << ((bit_num - 1) - u32_i);
+	}
+	return reverse;
+}
+
+static unsigned int rc_crc32(const char *buf, unsigned int u32_len,
+			     unsigned int u32_crc)
+{
+	unsigned int u32_i;
+	unsigned char u8_flash_byte, u8_current, u8_j;
+
+	for (u32_i = 0; u32_i < u32_len; u32_i++) {
+		u8_flash_byte = buf[u32_i];
+		u8_current = (unsigned char)bits_reverse(u8_flash_byte, 8);
+		for (u8_j = 0; u8_j < 8; u8_j++) {
+			if ((u32_crc ^ u8_current) & 0x01)
+				u32_crc = (u32_crc >> 1) ^ 0xedb88320;
+			else
+				u32_crc >>= 1;
+			u8_current >>= 1;
+		}
+	}
+	return u32_crc;
+}
+
+int wait_fw_state(struct i2c_client *client, unsigned int u32_addr,
+			 unsigned int u32_state, unsigned long u32_delay_us,
+			 unsigned short u16_retry)
+{
+	unsigned char u8_buf[4];
+	unsigned int u32_read_data;
+	unsigned int u32_min_delay_us = u32_delay_us - 500;
+	unsigned int u32_max_delay_us = u32_delay_us + 500;
+
+	do {
+		if (raydium_i2c_pda_read(client, u32_addr, u8_buf, 4) == ERROR)
+			return ERROR;
+
+		memcpy(&u32_read_data, u8_buf, 4);
+		u16_retry--;
+		usleep_range(u32_min_delay_us, u32_max_delay_us);
+	} while ((u32_read_data != u32_state) && (u16_retry != 0));
+
+	if (u32_read_data != u32_state) {
+		pr_err("[touch]confirm data error : 0x%x\n", u32_read_data);
+		return ERROR;
+	}
+
+	return SUCCESS;
+}
+
+int wait_irq_state(struct i2c_client *client, unsigned int retry_time,
+				unsigned int u32_delay_us)
+{
+	int i32_ret = SUCCESS;
+	unsigned int u32_retry;
+	unsigned int u32_irq_value;
+	unsigned int u32_min_delay_us = u32_delay_us - 500;
+	unsigned int u32_max_delay_us = u32_delay_us + 500;
+
+	u32_retry = retry_time;
+	u32_irq_value = 0;
+	while (u32_retry != 0 && u32_irq_value != 1) {
+		u32_irq_value = gpio_get_value(g_raydium_ts->irq_gpio);
+		usleep_range(u32_min_delay_us, u32_max_delay_us);
+		u32_retry--;
+	}
+	pr_info("[touch]irq_value is %d\n", u32_irq_value);
+
+	if (u32_retry == 0) {
+		pr_err("[touch]%s, FW not ready, retry error!\n", __func__);
+		i32_ret = ERROR;
+	}
+
+	return i32_ret;
+}
+
+int raydium_do_software_reset(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+
+	unsigned char u8_buf[4];
+
+	/*SW reset*/
+	g_u8_resetflag = true;
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = 0x01;
+	pr_info("[touch]SW reset\n");
+	i32_ret = raydium_i2c_pda_write(client, 0x40000004, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit;
+
+	if ((g_raydium_ts->id & 0x2000) != 0)
+		msleep(25);
+exit:
+	return i32_ret;
+}
+
+static int raydium_check_fw_ready(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+	unsigned int u32_retry = 400;
+	unsigned char u8_buf[4];
+
+	u8_buf[1] = 0;
+	while (u8_buf[1] != 0x40 && u32_retry != 0) {
+		i32_ret = raydium_i2c_pda_read(client, 0x50000918, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit;
+
+		u32_retry--;
+		usleep_range(4500, 5500);
+	}
+
+	if (u32_retry == 0) {
+		pr_err("[touch]%s, FW not ready, retry error!\n", __func__);
+		i32_ret = ERROR;
+	} else {
+		pr_info("[touch]%s, FW is ready!!\n", __func__);
+		usleep_range(4500, 5500);
+	}
+
+exit:
+	return i32_ret;
+}
+
+int set_skip_load(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+	unsigned int u32_retry_time = 1000;
+	unsigned char u8_buf[4];
+
+	/*Skip load*/
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = 0x10;
+	u8_buf[1] = 0x08;
+	i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	i32_ret = raydium_do_software_reset(client);
+	if (i32_ret < 0)
+		pr_err("[touch]%s, SW reset error!\n", __func__);
+
+	i32_ret = wait_fw_state(client, 0x20000214, 0x82, 2000, u32_retry_time);
+	if (i32_ret < 0)
+		pr_err("[touch]%s, wait_fw_state error!\n", __func__);
+
+exit_upgrade:
+	return i32_ret;
+}
+
+/*check pram crc32*/
+static int raydium_check_pram_crc_2X(struct i2c_client *client,
+		unsigned int u32_addr,
+		unsigned int u32_len)
+{
+	int i32_ret = SUCCESS;
+	unsigned int u32_crc_addr = u32_addr + u32_len;
+	unsigned int u32_end_addr = u32_crc_addr - 1;
+	unsigned int u32_crc_result, u32_read_data;
+	unsigned int u32_retry = 400;
+	unsigned char u8_buf[4], u8_retry = 3;
+
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = (unsigned char)(u32_addr & 0xFF);
+	u8_buf[1] = (unsigned char)((u32_addr & 0xFF00) >> 8);
+	u8_buf[2] = (unsigned char)(u32_end_addr & 0xFF);
+	u8_buf[3] = (unsigned char)((u32_end_addr & 0xFF00) >> 8);
+
+	i32_ret = raydium_i2c_pda_write(client, 0x50000974, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	u8_buf[3] |= 0x81;
+	i32_ret = raydium_i2c_pda_write(client, 0x5000094C, u8_buf, 4);
+
+	while (u8_buf[3] != 0x80 && u32_retry != 0) {
+		i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		u32_retry--;
+		usleep_range(4500, 5500);
+	}
+	if (u32_retry == 0) {
+		pr_err("[touch]%s, Cal CRC not ready, retry error!\n",
+			__func__);
+		i32_ret = ERROR;
+	}
+
+	i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	memcpy(&u32_crc_result, u8_buf, 4);
+	i32_ret = raydium_i2c_pda_read(client, u32_crc_addr, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	memcpy(&u32_read_data, u8_buf, 4);
+
+	while (u32_read_data != u32_crc_result && u8_retry > 0) {
+		i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_crc_result, u8_buf, 4);
+		usleep_range(1500, 2500);
+		u8_retry--;
+	}
+	if (u32_read_data != u32_crc_result) {
+		pr_err("[touch]check pram crc fail!!\n");
+		pr_err("[touch]u32_read_data 0x%x\n", u32_read_data);
+		pr_err("[touch]u32_crc_result 0x%x\n", u32_crc_result);
+		i32_ret = ERROR;
+		goto exit_upgrade;
+	} else if (u8_retry != 3) {
+		pr_err("[touch]check pram crc pass!!\n");
+		pr_err("[touch]u8_retry : %d\n", u8_retry);
+		pr_err("[touch]u32_read_data 0x%x\n", u32_read_data);
+		pr_err("[touch]u32_crc_result 0x%x\n", u32_crc_result);
+		i32_ret = ERROR;
+		goto exit_upgrade;
+	}
+
+exit_upgrade:
+	return i32_ret;
+}
+
+/* upgrade firmware with image file */
+static int raydium_write_to_pram_2X(struct i2c_client *client,
+		unsigned int u32_fw_addr,
+		unsigned char u8_type)
+{
+	int i32_ret = ERROR;
+	unsigned int u32_fw_size = 0;
+	unsigned char *p_u8_firmware_data = NULL;
+	unsigned int u32_write_offset = 0;
+	unsigned short u16_write_length = 0;
+
+	switch (u8_type) {
+	case RAYDIUM_INIT:
+		u32_fw_size = 0x200;
+		p_u8_firmware_data = g_rad_init_image;
+		break;
+
+	case RAYDIUM_PARA:
+		u32_fw_size = 0x160;
+		p_u8_firmware_data = g_rad_para_image;
+		break;
+
+	case RAYDIUM_FIRMWARE:
+		u32_fw_size = 0x6200;
+		p_u8_firmware_data = g_rad_fw_image;
+		break;
+
+	case RAYDIUM_BOOTLOADER:
+		u32_fw_size = 0x800;
+		p_u8_firmware_data = g_rad_boot_image;
+		break;
+
+	case RAYDIUM_TEST_FW:
+		u32_fw_size = 0x6360;
+		p_u8_firmware_data = g_rad_testfw_image;
+		break;
+	}
+
+	u32_write_offset = 0;
+	while (u32_write_offset < u32_fw_size) {
+		if ((u32_write_offset + MAX_WRITE_PACKET_SIZE) < u32_fw_size)
+			u16_write_length = MAX_WRITE_PACKET_SIZE;
+		else
+			u16_write_length =
+			(unsigned short)(u32_fw_size - u32_write_offset);
+
+		i32_ret = raydium_i2c_pda_write(
+			      client,
+			      (u32_fw_addr + u32_write_offset),
+			      (p_u8_firmware_data + u32_write_offset),
+			      u16_write_length);
+		if (i32_ret < 0)
+			goto exit_upgrate;
+
+		u32_write_offset += (unsigned long)u16_write_length;
+	}
+	u32_fw_addr += u32_write_offset;
+
+exit_upgrate:
+	if (i32_ret < 0) {
+		pr_err("[touch]upgrade failed\n");
+		return i32_ret;
+	}
+	pr_info("[touch]upgrade success\n");
+	return 0;
+}
+
+/* upgrade firmware with image file */
+static int raydium_fw_upgrade_with_image(struct i2c_client *client,
+		unsigned int u32_fw_addr,
+		unsigned char u8_type)
+{
+	int i32_ret = ERROR;
+	unsigned int u32_fw_size = 0;
+	unsigned char *p_u8_firmware_data = NULL;
+	unsigned int u32_write_offset = 0;
+	unsigned short u16_write_length = 0;
+	unsigned int u32_checksum = 0xFFFFFFFF;
+
+	switch (u8_type) {
+	case RAYDIUM_INIT:
+		u32_fw_size = 0x1fc;
+		p_u8_firmware_data = g_rad_init_image;
+		break;
+	case RAYDIUM_PARA:
+		if ((g_raydium_ts->id & 0x2000) != 0)
+			u32_fw_size = 0x158;
+		p_u8_firmware_data = g_rad_para_image;
+		break;
+	case RAYDIUM_FIRMWARE:
+		if ((g_raydium_ts->id & 0x2000) != 0)
+			u32_fw_size = 0x61fc;
+		p_u8_firmware_data = g_rad_fw_image;
+		break;
+	case RAYDIUM_BOOTLOADER:
+		if ((g_raydium_ts->id & 0x2000) != 0)
+			u32_fw_size = 0x7FC;
+		p_u8_firmware_data = g_rad_boot_image;
+		break;
+	case RAYDIUM_TEST_FW:
+		if ((g_raydium_ts->id & 0x2000) != 0)
+			u32_fw_size = 0x635C;
+		p_u8_firmware_data = g_rad_testfw_image;
+		break;
+	}
+
+#if 1
+	pr_info("[touch]CRC 0x%08X\n",
+		*(unsigned int *)(p_u8_firmware_data + u32_fw_size));
+
+	u32_checksum = rc_crc32(p_u8_firmware_data,
+		u32_fw_size, u32_checksum);
+	u32_checksum = bits_reverse(u32_checksum, 32);
+	memcpy((p_u8_firmware_data + u32_fw_size), &u32_checksum, 4);
+	pr_info("[touch]CRC result 0x%08X\n", u32_checksum);
+#endif	
+	u32_fw_size += 4;
+
+	u32_write_offset = 0;
+	while (u32_write_offset < u32_fw_size) {
+		if ((u32_write_offset + MAX_WRITE_PACKET_SIZE) < u32_fw_size)
+			u16_write_length = MAX_WRITE_PACKET_SIZE;
+		else
+			u16_write_length =
+				(unsigned short)
+				(u32_fw_size - u32_write_offset);
+
+		i32_ret = raydium_i2c_pda_write(
+			      client,
+			      (u32_fw_addr + u32_write_offset),
+			      (p_u8_firmware_data + u32_write_offset),
+			      u16_write_length);
+		if (i32_ret < 0)
+			goto exit_upgrate;
+
+		u32_write_offset += (unsigned long)u16_write_length;
+	}
+	u32_fw_addr += u32_write_offset;
+
+exit_upgrate:
+	if (i32_ret < 0) {
+		pr_err("[touch]upgrade failed\n");
+		return i32_ret;
+	}
+	pr_info("[touch]upgrade success\n");
+	return 0;
+}
+static int raydium_boot_upgrade_2X(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+	unsigned char u8_buf[4];
+
+	/*set mcu hold*/
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = 0x20;
+	i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	u8_buf[0] = 0x01;
+	i32_ret = raydium_i2c_pda_write(client, 0x40000004, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	msleep(25);
+
+	/*WRT boot-loader to PRAM first*/
+	memset(u8_buf, 0, sizeof(u8_buf));
+	i32_ret = raydium_i2c_pda_write(client, 0x50000900, u8_buf, 4);
+
+	/*Sending bootloader*/
+	i32_ret = raydium_write_to_pram_2X(client, 0x0000,
+					    RAYDIUM_BOOTLOADER);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	i32_ret = raydium_check_pram_crc_2X(client, 0x000, 0x7FC);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	/*release mcu hold*/
+	/*Skip load*/
+	i32_ret = set_skip_load(client);
+	if (i32_ret < 0)
+		pr_err("[touch]%s, set skip_load error!\n", __func__);
+
+exit_upgrade:
+	return i32_ret;
+}
+
+/* Raydium fireware upgrade flow */
+static int raydium_fw_upgrade_2X(struct i2c_client *client,
+			      unsigned char u8_type,
+			      unsigned char u8_check_crc)
+{
+	int i32_ret = 0;
+	unsigned char u8_buf[4];
+	unsigned short u16_retry = 1000;
+	
+	/*##### wait for boot-loader start #####*/
+	pr_info("[touch]Type is %x\n", u8_type);
+
+	/*read Boot version*/
+	if (raydium_i2c_pda_read(client, 0x80, u8_buf, 4) == ERROR)
+		return ERROR;
+	pr_info("[touch]Boot version is %x\n", u8_buf[2]);
+
+	if (u8_buf[2] >= 4) {
+		if (u8_type != RAYDIUM_COMP) {
+			/*set mcu hold*/
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x20;
+			i32_ret = raydium_i2c_pda_write(client,
+						0x50000918,
+						u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			u8_buf[0] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client,
+						0x40000004,
+						u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			msleep(25);
+		}
+
+		/*#start write data to PRAM*/
+		if (u8_type == RAYDIUM_FIRMWARE) {
+			/* unlock PRAM */
+			u8_buf[0] = 0x27;
+			i32_ret = raydium_i2c_pda_write(client,
+						0x50000900,
+						u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_write_to_pram_2X(client, 0x800,
+							    RAYDIUM_FIRMWARE);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			i32_ret = raydium_write_to_pram_2X(client, 0x6a00,
+							    RAYDIUM_PARA);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			i32_ret = raydium_check_pram_crc_2X(client, 0x800,
+				0x635C);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_BOOTLOADER) {
+			/* unlock PRAM */
+			u8_buf[0] = 0x0E;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000900,
+							u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_write_to_pram_2X(client, 0x0800,
+							    RAYDIUM_BOOTLOADER);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_write_to_pram_2X(client, 0x1000,
+							    RAYDIUM_INIT);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			i32_ret = raydium_check_pram_crc_2X(client, 0x800,
+				0x7FC);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_check_pram_crc_2X(client, 0x1000,
+				0x1FC);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		if (u8_type != RAYDIUM_COMP) {
+			/*release mcu hold*/
+			/*Skip load*/
+			i32_ret = set_skip_load(client);
+			if (i32_ret < 0)
+				pr_err("[touch]%s, set skip_load error!\n",
+					__func__);
+		}
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x01;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000204, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000208, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x2000020C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x01;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000218, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#confirm in burn mode*/
+		if (wait_fw_state(client, 0x20000214, 255,
+				 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, confirm in burn mode\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*Clear BL_CRC*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x10;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = u8_type;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000904, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#set PRAM length (at 'h5000_090C)*/
+		if (u8_type == RAYDIUM_COMP) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x60;
+			u8_buf[1] = 0x6b;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x9c;
+			u8_buf[1] = 0x02;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_FIRMWARE) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x5c;
+			u8_buf[1] = 0x63;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_BOOTLOADER) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x0A;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		/*#set sync_data(0x20000200) = 0 as WRT data finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wait for input unlock key*/
+		if (wait_fw_state(client, 0x20000210, 168, 1000,
+				 u16_retry) == ERROR) {
+			pr_err("[touch]Error, wait for input unlock key\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#unlock key*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xd7;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wrt return data as unlock value*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa8;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*pr_info("[touch]ready burn flash\n");*/
+
+		/*#clr sync_data(0x20000200) = 0 as finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/* wait erase/wrt finish
+		 * confirm burning_state result (gu8I2CSyncData.burning_state =
+		 * BURNING_WRT_FLASH_FINISH at 0x2000020C)
+		 */
+		if (wait_fw_state(client, 0x2000020c, 6, 2000,
+				 u16_retry) == ERROR) {
+			pr_err("[touch]Error, wait erase/wrt finish\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+		pr_info("[touch]Burn flash ok\n");
+
+		if (u8_check_crc) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			i32_ret = raydium_i2c_pda_write(client, 0x20000200,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			/*#wait software reset finish*/
+			msleep(25);
+
+			/* wait sw reset finished 0x20000214 = 0x82 */
+			if (wait_fw_state(client, 0x20000214, 130, 2000,
+					 u16_retry) == ERROR) {
+				pr_err("[touch]Error, wait sw reset finished\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+
+			/*#set test_mode = 1*/
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client, 0x20000218,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			/*#wait crc check finish*/
+			if (wait_fw_state(client, 0x20000208, 2,
+					 2000, u16_retry)
+					== ERROR) {
+				pr_err("[touch]Error, wait crc check finish\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+
+			/*#crc check pass 0x20000214 = 0x81*/
+			if (wait_fw_state(client, 0x20000214, 0x81,
+					 2000, u16_retry)
+					== ERROR) {
+				pr_err("[touch]Error, confirm crc result\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+		}
+
+	} else {
+		/*#set main state as burning mode, normal init state*/
+		/* #sync_data:200h
+		 * main_state:204h
+		 * normal_state:208h
+		 * burning_state:20Ch
+		 */
+		/* #sync_data:210h
+		 * cmd_type:210h
+		 * ret_data:214h
+		 * test_mode:218h
+		 */
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x01;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000204, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000208, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x2000020C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x01;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000218, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#confirm in burn mode*/
+		if (wait_fw_state(client, 0x50000900, 63,
+				 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, confirm in burn mode\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*Clear BL_CRC*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x10;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#write PRAM relative data*/
+		/*#set PRAM type (at 0x50000904), wrt param code*/
+		/* #init_code:0x01,
+		 * baseline:0x02
+		 * COMP:0x04
+		 * param:0x08
+		 * FW:0x10
+		 * bootloader:0x20
+		 */
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = u8_type;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000904, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#set PRAM addr (at 'h5000_0908)*/
+		/* #init_code:0x800
+		 * Baseline:0xA00
+		 * COMP:0xCD4
+		 * para:0xF1C
+		 * FW:0x1000
+		 * BOOT:0x5000
+		*/
+		/*#set PRAM length (at 'h5000_090C)*/
+		if (u8_type == RAYDIUM_INIT) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x6e;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x02;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_BASELINE) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0xcc;
+			u8_buf[1] = 0x6c;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x30;
+			u8_buf[1] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_COMP) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x60;
+			u8_buf[1] = 0x6b;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x9c;
+			u8_buf[1] = 0x02;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_PARA) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x6a;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x5c;
+			u8_buf[1] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_FIRMWARE) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x5c;
+			u8_buf[1] = 0x63;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+		} else if (u8_type == RAYDIUM_BOOTLOADER) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000908,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x00;
+			u8_buf[1] = 0x0A;
+			i32_ret = raydium_i2c_pda_write(client, 0x5000090C,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		/*#set sync_data(0x20000200) = 0 as WRT data finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#Wait bootloader check addr and PRAM unlock*/
+		/*#Confirm ret_data at 0x20000214 is SET_ADDR_READY*/
+		if (wait_fw_state(client, 0x20000214, 161,
+				 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, SET_ADDR_READY\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#Confirm cmd_type at 0x20000210 is WRT_PRAM_DATA*/
+		if (wait_fw_state(client, 0x20000210, 163,
+				 1000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, WRT_PRAM_DATA\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#start write data to PRAM*/
+		if (u8_type == RAYDIUM_INIT) {
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x6E00,
+							    RAYDIUM_INIT);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}  else if (u8_type == RAYDIUM_PARA) {
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x6a00,
+							    RAYDIUM_PARA);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		} else if (u8_type == RAYDIUM_FIRMWARE) {
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x800,
+							    RAYDIUM_FIRMWARE);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x6a00,
+							    RAYDIUM_PARA);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+
+		} else if (u8_type == RAYDIUM_BOOTLOADER) {
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x0800,
+							    RAYDIUM_BOOTLOADER);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+			i32_ret = raydium_fw_upgrade_with_image(client, 0x1000,
+							    RAYDIUM_INIT);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		/*
+		 *set sync_data(0x20000200) = 0 as WRT data finish
+		 *bootloader check checksum
+		 */
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*
+		 * wait(checksum okay) ACK cmd
+		 * (gu8I2CSyncData.cmd_type=0xa5 at 0x20000210)
+		 */
+		if (wait_fw_state(client, 0x20000210,
+				 165, 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, WRT_CHECKSUM_OK\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#confirm ACK cmd result(ret_data=0xa5 at 0x20000214)*/
+		if (wait_fw_state(client, 0x20000214,
+				 165, 1000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, confirm ACK cmd result\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*
+		 * set ACK return data = 0x5A
+		 * adb shell "echo 20000210 1 A5 > /sys/bus/i2c/drivers/
+		 * raydium_ts/1-0039 raydium_i2c_pda_access"
+		 * above command can be ignored, due to previous while loop
+		 * has check its value.
+		 */
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000210, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x5a;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#clr sync_data(0x20000200) = 0 as finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wait for input unlock key*/
+		if (wait_fw_state(client, 0x20000210,
+				 168, 1000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, wait for input unlock key\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		/*#unlock key*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xd7;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa5;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000934, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000938, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x50000624, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wrt return data as unlock value*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0xa8;
+		i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*pr_info("[touch]ready burn flash\n");*/
+
+		/*#clr sync_data(0x20000200) = 0 as finish*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/* wait erase/wrt finish
+		 * confirm burning_state result (gu8I2CSyncData.burning_state =
+		 * BURNING_WRT_FLASH_FINISH at 0x2000020C)
+		 */
+		if (wait_fw_state(client, 0x2000020c,
+				 6, 2000, u16_retry) == ERROR) {
+			dev_err(&g_raydium_ts->client->dev,
+				"[touch]Error, wait erase/wrt finish\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+		pr_info("[touch]Burn flash ok\n");
+
+
+		if (u8_type == RAYDIUM_BOOTLOADER) {
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x10;
+			u8_buf[1] = 0x08;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000918,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		/*#wait software reset finish*/
+		msleep(25);
+
+		/* wait sw reset finished 0x20000214 = 0x82 */
+		if (wait_fw_state(client, 0x20000214,
+				 130, 2000, u16_retry) == ERROR) {
+			pr_err("[touch]Error, wait sw reset finished\n");
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		if (u8_type == RAYDIUM_BASELINE || u8_type == RAYDIUM_COMP ||
+		    u8_type == RAYDIUM_FIRMWARE || u8_check_crc == 1) {
+			/*#set test_mode = 1*/
+			memset(u8_buf, 0, sizeof(u8_buf));
+			u8_buf[0] = 0x01;
+			i32_ret = raydium_i2c_pda_write(client, 0x20000218,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+
+			/*#wait crc check finish*/
+			if (wait_fw_state(client, 0x20000208, 2,
+					 2000, u16_retry) == ERROR) {
+				pr_err("[touch]Error, wait crc check finish\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+
+			/*#crc check pass 0x20000214 = 0x81*/
+			if (wait_fw_state(client, 0x20000214, 0x81,
+					 2000, u16_retry)
+					== ERROR) {
+				pr_err("[touch]Error, confirm crc result\n");
+				i32_ret = ERROR;
+				goto exit_upgrade;
+			}
+		}
+	}
+
+	/*#run to next step*/
+		pr_info("[touch]Type 0x%x => Pass\n", u8_type);
+
+	if (u8_check_crc) {
+		/*#clr sync para*/
+		memset(u8_buf, 0, sizeof(u8_buf));
+		i32_ret = raydium_i2c_pda_write(client, 0x20000210, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_ret = raydium_i2c_pda_write(client, 0x20000214, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_ret = raydium_i2c_pda_write(client, 0x20000218, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+
+		i32_ret = raydium_i2c_pda_write(client, 0x20000200, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		usleep_range(4500, 5500);
+		raydium_i2c_pda_set_address(0x50000628, DISABLE);
+
+		g_u8_i2c_mode = PDA2_MODE;
+
+		pr_info("[touch]Burn FW finish!\n");
+	}
+
+exit_upgrade:
+	return i32_ret;
+}
+
+int raydium_burn_fw(struct i2c_client *client)
+{
+	int i32_ret = 0;
+
+	g_u8_resetflag = true;
+	if ((g_raydium_ts->id & 0x2000) != 0) {
+		pr_info("[touch]start burn function!\n");
+		i32_ret = raydium_boot_upgrade_2X(client);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_ret = raydium_fw_upgrade_2X(client, RAYDIUM_BOOTLOADER, 0);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_ret = raydium_fw_upgrade_2X(client, RAYDIUM_FIRMWARE, 1);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+	}
+
+exit_upgrade:
+	return i32_ret;
+}
+
+int raydium_fw_update_check(unsigned short u16_i2c_data)
+{
+
+	unsigned char u8_rbuffer[4];
+
+	unsigned int u32_fw_version, u32_image_version;
+	int i32_ret = ERROR;
+
+#ifdef FW_UPDATE_EN
+	unsigned char u8_mode_change;
+#endif
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+				g_raydium_ts->is_suspend,
+				RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+				    RAYDIUM_PDA2_FW_VERSION_ADDR,
+				    u8_rbuffer,
+				    4);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	mutex_unlock(&g_raydium_ts->lock);
+
+	u32_fw_version = (u8_rbuffer[0] << 24) | (u8_rbuffer[1] << 16) |
+		(u8_rbuffer[2] << 8) | u8_rbuffer[3];
+	pr_info("[touch]RAD FW ver 0x%.8x\n", u32_fw_version);
+
+	g_raydium_ts->fw_version = u32_fw_version;
+
+	g_raydium_ts->id = ((u16_i2c_data & 0xF) << 12) |
+		((u8_rbuffer[0] & 0xF) << 8) | u8_rbuffer[1];
+
+	raydium_mem_table_init(g_raydium_ts->id);
+	if (raydium_mem_table_setting()) {
+
+		u32_image_version = (g_rad_para_image[0x0004] << 24) |
+			(g_rad_para_image[0x0005] << 16) |
+			(g_rad_para_image[0x0006] << 8) |
+			g_rad_para_image[0x0007];
+
+		pr_info("[touch]RAD Image FW ver : 0x%x\n", u32_image_version);
+	} else {
+		pr_info("[touch]Mem setting failed, Stop fw upgrade!\n");
+		return FAIL;
+	}
+
+#ifdef FW_UPDATE_EN
+	if (u32_fw_version != u32_image_version) {
+		pr_info("[touch]FW need update.\n");
+		raydium_irq_control(DISABLE);
+		if ((g_u8_raydium_flag & ENG_MODE) == 0) {
+			g_u8_raydium_flag |= ENG_MODE;
+			u8_mode_change = 1;
+		}
+		i32_ret = raydium_burn_fw(g_raydium_ts->client);
+		if (i32_ret < 0)
+			pr_err("[touch]FW update fail:%d\n", i32_ret);
+
+		if (u8_mode_change) {
+			g_u8_raydium_flag &= ~ENG_MODE;
+			u8_mode_change = 0;
+		}
+		raydium_irq_control(ENABLE);
+		mutex_lock(&g_raydium_ts->lock);
+		i32_ret = raydium_i2c_pda2_set_page(g_raydium_ts->client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		i32_ret = raydium_i2c_pda2_read(g_raydium_ts->client,
+					    RAYDIUM_PDA2_FW_VERSION_ADDR,
+					    u8_rbuffer,
+					    4);
+		if (i32_ret < 0)
+			goto exit_error;
+
+		mutex_unlock(&g_raydium_ts->lock);
+		u32_fw_version = (u8_rbuffer[0] << 24) |
+			     (u8_rbuffer[1] << 16) |
+			     (u8_rbuffer[2] << 8) |
+			     u8_rbuffer[3];
+		pr_info("[touch]RAD FW ver is 0x%x\n",
+			 u32_fw_version);
+		g_raydium_ts->fw_version = u32_fw_version;
+	} else
+		pr_info("[touch]FW is the latest version.\n");
+#endif
+
+
+	return i32_ret;
+
+exit_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	return i32_ret;
+}
+int raydium_burn_comp(struct i2c_client *client)
+{
+	int i32_ret = FAIL;
+
+	i32_ret = set_skip_load(client);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+
+	if ((g_raydium_ts->id & 0x2000) != 0) {
+		i32_ret = raydium_fw_upgrade_2X(client, RAYDIUM_COMP, 1);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+	}
+	i32_ret = SUCCESS;
+
+exit_upgrade:
+	return i32_ret;
+}
+
+int raydium_load_test_fw(struct i2c_client *client)
+{
+	int i32_ret = SUCCESS;
+	unsigned char u8_buf[4];
+	unsigned int u32_crc_result, u32_read_data;
+
+	/*set mcu hold*/
+	memset(u8_buf, 0, sizeof(u8_buf));
+	u8_buf[0] = 0x20;
+	raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+	raydium_i2c_pda_read(client, 0x40000004, u8_buf, 4);
+	u8_buf[0] |= 0x01;
+	raydium_i2c_pda_write(client, 0x40000004, u8_buf, 4);
+	msleep(25);
+
+
+	i32_ret = raydium_i2c_pda_read(client, 0x40000000, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	u8_buf[3] |= 0x40;
+	i32_ret = raydium_i2c_pda_write(client, 0x40000000, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	i32_ret = raydium_i2c_pda_read(client, 0x40000014, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	u8_buf[0] |= 0x04;
+	u8_buf[1] |= 0x04;
+	i32_ret = raydium_i2c_pda_write(client, 0x40000014, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	memset(u8_buf, 0, sizeof(u8_buf));
+	pr_info("[touch]Raydium WRT test_fw to PRAM\n");
+
+	i32_ret = raydium_i2c_pda_write(client, 0x50000900, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+
+	/*Sending test fw*/
+	if ((g_raydium_ts->id & 0x2000) != 0) {
+		i32_ret = raydium_fw_upgrade_with_image(client,
+			0x800, RAYDIUM_TEST_FW);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+	}
+
+	/*check pram crc data*/
+	if ((g_raydium_ts->id & 0x2000) != 0) {
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[1] = 0x08;
+		u8_buf[2] = 0x5B;
+		u8_buf[3] = 0x6B;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000974, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		u8_buf[3] |= 0x81;
+		i32_ret = raydium_i2c_pda_write(client, 0x5000094C, u8_buf, 4);
+		usleep_range(9500, 10500);
+		i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_crc_result, u8_buf, 4);
+		i32_ret = raydium_i2c_pda_read(client, 0x6B5C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_read_data, u8_buf, 4);
+		if (u32_read_data != u32_crc_result) {
+			pr_err("[touch]check pram fw crc fail!!\n");
+			pr_err("[touch]u32_crc_result 0x%x\n", u32_crc_result);
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		memset(u8_buf, 0, sizeof(u8_buf));
+		u8_buf[0] = 0x60;
+		u8_buf[1] = 0x6B;
+		u8_buf[2] = 0xFB;
+		u8_buf[3] = 0x6D;
+		i32_ret = raydium_i2c_pda_write(client, 0x50000974, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		i32_ret = raydium_i2c_pda_read(client, 0x5000094C, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		u8_buf[3] |= 0x81;
+		i32_ret = raydium_i2c_pda_write(client, 0x5000094C, u8_buf, 4);
+		usleep_range(1000, 2000);
+		i32_ret = raydium_i2c_pda_read(client, 0x50000978, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_crc_result, u8_buf, 4);
+		i32_ret = raydium_i2c_pda_read(client, 0x6DFC, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+		memcpy(&u32_read_data, u8_buf, 4);
+		if (u32_read_data != u32_crc_result) {
+			pr_err("[touch]check pram CB crc fail!!\n");
+			pr_err("[touch]u32_crc_result 0x%x\n", u32_crc_result);
+			i32_ret = ERROR;
+			goto exit_upgrade;
+		}
+
+		i32_ret = raydium_i2c_pda_read(client, 0x80, u8_buf, 4);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		if (u8_buf[2] > 2) {
+			pr_err("[touch]bootloader version %x,!!\n", u8_buf[2]);
+			memset(u8_buf, 0, sizeof(u8_buf));
+
+			u8_buf[1] = 0x04;
+			i32_ret = raydium_i2c_pda_write(client, 0x50000918,
+							 u8_buf, 4);
+			if (i32_ret < 0)
+				goto exit_upgrade;
+		}
+	}
+
+	/*Skip load*/
+	pr_info("[touch]Raydium skip load\n");
+	i32_ret = raydium_i2c_pda_read(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	u8_buf[0] = 0x10;
+	i32_ret = raydium_i2c_pda_write(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	i32_ret = raydium_do_software_reset(client);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	i32_ret = raydium_i2c_pda_read(client, 0x50000918, u8_buf, 4);
+	if (i32_ret < 0)
+		goto exit_upgrade;
+	pr_info("[touch]0x5000918 = 0x%x, 0x%x, 0x%x, 0x%x\n",
+		u8_buf[0], u8_buf[1], u8_buf[2], u8_buf[3]);
+	i32_ret = raydium_check_fw_ready(client);
+
+exit_upgrade:
+	return i32_ret;
+}
+
+MODULE_AUTHOR("Raydium");
+MODULE_DESCRIPTION("Raydium TouchScreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c b/drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c
new file mode 100644
index 0000000..9f08b38
--- /dev/null
+++ b/drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c
@@ -0,0 +1,1454 @@
+/* drivers/input/touchscreen/raydium_wt030/raydium_sysfs.c
+ *
+ * Raydium TouchScreen driver.
+ *
+ * Copyright (c) 2010  Raydium tech Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include "raydium_driver.h"
+
+static ssize_t raydium_touch_calibration_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[1];
+	unsigned short u16_len = 0;
+	int i32_ret = -1;
+	unsigned char u8_retry = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	
+	if (g_raydium_ts->is_suspend)
+		pr_info("[touch]RAD is_suspend at %s\n", __func__);
+
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+
+	u8_rbuffer[0] = RAYDIUM_HOST_CMD_CALIBRATION;
+	i32_ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_HOST_CMD_ADDR,
+				     u8_rbuffer, 1);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+
+	do {
+		if (u8_rbuffer[0] == RAYDIUM_HOST_CMD_NO_OP)
+			break;
+
+		msleep(1000);
+
+		i32_ret = raydium_i2c_pda2_read(client,
+						RAYDIUM_PDA2_HOST_CMD_ADDR,
+						u8_rbuffer, 1);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		pr_info("[touch]RAD %s return 0x%02x!!\n",
+			 __func__, u8_rbuffer[0]);
+	} while (u8_retry++ < (SYN_I2C_RETRY_TIMES * 2));
+
+	memcpy(p_i8_buf, u8_rbuffer, 1);
+
+	u16_len = strlen(p_i8_buf);
+	i32_ret = u16_len + 1;
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+
+	return i32_ret;
+}
+
+static ssize_t raydium_i2c_pda_access_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	unsigned short u16_len = 0;
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_u32_length > 4)
+		return -EINVAL;
+	memset(u8_rbuffer, 0x00, 4);
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda_read(client,
+				g_u32_addr,
+				u8_rbuffer,
+				g_u32_length);
+	mutex_unlock(&g_raydium_ts->lock);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	snprintf(p_i8_buf, PAGE_SIZE, "0x%08X : 0x%02X%02X%02X%02X\n",
+		 (unsigned int)g_u32_addr, u8_rbuffer[3], u8_rbuffer[2],
+		 u8_rbuffer[1], u8_rbuffer[0]);
+	u16_len = strlen(p_i8_buf);
+
+	return u16_len + 1;
+}
+
+static ssize_t raydium_check_i2c_show(struct device *dev,
+				      struct device_attribute *attr,
+				      char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	unsigned short u16_len = 0;
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_info("[touch]RAD is_suspend at %s\n", __func__);
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	if (g_u8_i2c_mode == PDA2_MODE) {
+		i32_ret = raydium_i2c_pda2_set_page(client,
+						 g_raydium_ts->is_suspend,
+						 RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		/*using byte mode to read 4 bytes*/
+		*(unsigned long *)u8_rbuffer = (RAD_I2C_PDA_MODE_ENABLE << 24)
+						| ((RAD_CHK_I2C_CMD &
+						(~MASK_8BIT)) >> 8);
+
+		i32_ret = raydium_i2c_pda2_write(client,
+						RAYDIUM_PDA2_PDA_CFG_ADDR,
+						u8_rbuffer,
+						4);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+		i32_ret = raydium_i2c_pda2_set_page(client,
+				g_raydium_ts->is_suspend,
+				RAYDIUM_PDA2_ENABLE_PDA);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+		i32_ret = raydium_i2c_pda2_read(client,
+			(unsigned char)(RAD_CHK_I2C_CMD & MASK_8BIT),
+			u8_rbuffer, 4);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+	} else {
+		i32_ret = raydium_i2c_pda_read(client, RAD_CHK_I2C_CMD,
+					   u8_rbuffer, 4);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+	}
+
+	snprintf(p_i8_buf, PAGE_SIZE, "[touch]RAD Touch check i2c: %02X%02X\n",
+		u8_rbuffer[3], u8_rbuffer[2]);
+	u16_len = strlen(p_i8_buf);
+	i32_ret = u16_len + 1;
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+	return i32_ret;
+}
+
+static ssize_t raydium_hw_reset_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *p_i8_buf)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	int i32_ret = SUCCESS;
+
+
+	pr_info("[touch]HW reset\n");
+	g_u8_resetflag = true;
+	if ((g_u8_raydium_flag & ENG_MODE) == 0)
+		raydium_irq_control(DISABLE);
+
+	/*HW reset*/
+	if (gpio_is_valid(g_raydium_ts->rst_gpio)) {
+		gpio_set_value(g_raydium_ts->rst_gpio, 1);
+		gpio_set_value(g_raydium_ts->rst_gpio, 0);
+		msleep(RAYDIUM_RESET_INTERVAL_MSEC);
+		gpio_set_value(g_raydium_ts->rst_gpio, 1);
+	}
+
+	g_u8_i2c_mode = PDA2_MODE;
+
+	i32_ret = wait_irq_state(client, 1000, 2000);
+	if (i32_ret != ERROR) {
+		msleep(25);
+	}
+
+	if ((g_u8_raydium_flag & ENG_MODE) == 0)
+		raydium_irq_control(ENABLE);
+
+	snprintf(p_i8_buf, PAGE_SIZE, "Raydium HW Reset : %d\n", i32_ret);
+	pr_info("%s\n", p_i8_buf);
+	return strlen(p_i8_buf) + 1;
+}
+
+static ssize_t raydium_reset_control_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_high;
+
+	if (g_raydium_ts->is_suspend)
+		pr_info("[touch]RAD is_suspend at %s\n", __func__);
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_high);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	g_u8_i2c_mode = PDA2_MODE;
+	g_u8_resetflag = true;
+
+		if (u8_high) {
+			pr_info("[touch]RAD %s set reset gpio to high!!\n",
+				 __func__);
+			gpio_set_value(g_raydium_ts->rst_gpio, 1);
+		} else {
+			pr_info("[touch]RAD %s set reset gpio to low!!\n",
+				 __func__);
+			gpio_set_value(g_raydium_ts->rst_gpio, 0);
+		}
+	return count;
+}
+
+static ssize_t raydium_palm_status_show(struct device *dev,
+					struct device_attribute *attr,
+					char *p_i8_buf)
+{
+	unsigned short u16_len = 0;
+
+	unsigned char u8_tp_status[MAX_TCH_STATUS_PACKET_SIZE];
+	unsigned char u8_tp_buf[MAX_REPORT_PACKET_SIZE];
+
+	raydium_read_touchdata(u8_tp_status, u8_tp_buf);
+	snprintf(p_i8_buf, PAGE_SIZE, "[touch] palm_status : %d\n",
+		u8_tp_status[POS_GES_STATUS]);
+
+	u16_len = strlen(p_i8_buf);
+	return u16_len + 1;
+}
+
+
+static ssize_t raydium_palm_area_store(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t count)
+{
+	int ret = 0;
+	unsigned char w_data[1];
+	unsigned char palm_area = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count > 3)
+		return -EINVAL;
+
+	ret = kstrtou8(buf, 16, &palm_area);
+	pr_info("[touch] input palm area = %d\n", palm_area);
+
+	mutex_lock(&g_raydium_ts->lock);
+	/* unlock PARM */
+
+	ret = raydium_i2c_pda2_set_page(client, g_raydium_ts->is_suspend, RAYDIUM_PDA2_PAGE_0);
+	if (ret < 0) {
+		mutex_unlock(&g_raydium_ts->lock);
+		goto exit_error;
+	}
+
+	w_data[0] = palm_area;
+	ret = raydium_i2c_pda2_write(client,RAYDIUM_PDA2_PALM_AREA_ADDR,
+				w_data, 1);
+	if (ret < 0) {
+		mutex_unlock(&g_raydium_ts->lock);
+		goto exit_error;
+	}
+
+	mutex_unlock(&g_raydium_ts->lock);
+
+exit_error:
+	return count;
+}
+static ssize_t raydium_palm_area_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	unsigned short u16_len = 0;
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_info("[touch]RAD is_suspend at %s\n", __func__);
+
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	i32_ret = raydium_i2c_pda2_read(client, RAYDIUM_PDA2_PALM_AREA_ADDR,
+				    u8_rbuffer, 4);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	snprintf(p_i8_buf, PAGE_SIZE, "RAD Palm area : %02X\n", u8_rbuffer[0]);
+
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+
+	u16_len = strlen(p_i8_buf);
+	i32_ret = u16_len + 1;
+	goto exit_upgrade;
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+
+exit_upgrade:
+	return i32_ret;
+}
+
+static ssize_t raydium_irq_state_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *p_i8_buf)
+{
+	unsigned int u32_irq_value;
+
+	u32_irq_value = gpio_get_value(g_raydium_ts->irq_gpio);
+
+	snprintf(p_i8_buf, PAGE_SIZE, "%d", u32_irq_value);
+	/*pr_info("%s\n", p_i8_buf);*/
+	return strlen(p_i8_buf) + 1;
+}
+
+
+static ssize_t raydium_touch_lock_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_mode;
+	unsigned char u8_wbuffer[1];
+
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_info("[touch]RAD is_suspend at %s\n", __func__);
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_mode);
+	if (i32_ret < 0)
+		return i32_ret;
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	switch (u8_mode) {
+	case 0: /* Disable Touch lock */
+
+		if (g_raydium_ts->is_sleep != 1)
+			break;
+		g_u8_resetflag = true;
+		if (gpio_is_valid(g_raydium_ts->rst_gpio)) {
+			gpio_set_value(g_raydium_ts->rst_gpio, 1);
+			gpio_set_value(g_raydium_ts->rst_gpio, 0);
+			msleep(RAYDIUM_RESET_INTERVAL_MSEC);/*5ms*/
+			gpio_set_value(g_raydium_ts->rst_gpio, 1);
+			msleep(RAYDIUM_RESET_DELAY_MSEC);/*100ms*/
+		}
+		pr_info("[touch]RAD %s disable touch lock!!\n", __func__);
+
+		g_raydium_ts->is_sleep = 0;
+		break;
+
+	case 1: /* Enable Touch lock */
+
+		if (g_raydium_ts->is_sleep == 1)
+			break;
+		i32_ret = raydium_i2c_pda2_set_page(client,
+						 g_raydium_ts->is_suspend,
+						 RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+		/*fw enter sleep mode*/
+		u8_wbuffer[0] = RAYDIUM_HOST_CMD_PWR_SLEEP;
+		i32_ret = raydium_i2c_pda2_write(client,
+						RAYDIUM_PDA2_HOST_CMD_ADDR,
+						u8_wbuffer,
+						1);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		pr_info("[touch]RAD %s enable touch lock!!\n", __func__);
+		g_raydium_ts->is_sleep = 1;
+		break;
+	}
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+	return count;
+}
+
+static ssize_t raydium_check_driver_version_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	/*unsigned char rbuffer[4];*/
+	unsigned short u16_len = 0;
+	int i32_ret = -1;
+
+	snprintf(p_i8_buf, PAGE_SIZE, "RAD Driver Ver: 0x%X\n",
+		 g_u32_driver_version);
+	/*sprintf(p_i8_buf, "RAD Driver Ver: 0x%X\n", g_u32_driver_version);*/
+
+	u16_len = strlen(p_i8_buf);
+	i32_ret = u16_len + 1;
+	return i32_ret;
+}
+
+static ssize_t raydium_check_fw_version_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	unsigned short u16_len = 0;
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	unsigned int fw_version, image_version;
+
+	if (g_raydium_ts->is_suspend)
+		pr_info("[touch]RAD is_suspend at %s\n", __func__);
+
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	i32_ret = raydium_i2c_pda2_read(client, RAYDIUM_PDA2_FW_VERSION_ADDR,
+				    u8_rbuffer, 4);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	snprintf(p_i8_buf, PAGE_SIZE, "RAD Touch FW Ver : %02X%02X%02X%02X\n",
+		u8_rbuffer[0], u8_rbuffer[1], u8_rbuffer[2], u8_rbuffer[3]);
+
+	fw_version = (u8_rbuffer[0] << 24)
+		| (u8_rbuffer[1] << 16)
+		| (u8_rbuffer[2] << 8)
+		| u8_rbuffer[3];
+	pr_info("[touch]RAD FW ver : 0x%x\n", fw_version);
+
+	image_version = (g_rad_para_image[0x0004] << 24) |
+			(g_rad_para_image[0x0005] << 16) |
+			(g_rad_para_image[0x0006] << 8) |
+			g_rad_para_image[0x0007];
+
+	pr_info("[touch]RAD Image FW ver : 0x%x\n", image_version);
+
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+
+	if (fw_version != image_version)
+		pr_info("[touch]%s, FW need upgrade.\n", __func__);
+
+	u16_len = strlen(p_i8_buf);
+	i32_ret = u16_len + 1;
+	goto exit_upgrade;
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+
+exit_upgrade:
+	return i32_ret;
+}
+
+static ssize_t raydium_check_panel_version_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[8];
+	unsigned short u16_len = 0;
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_info("[touch]RAD is_suspend at %s\n", __func__);
+	raydium_irq_control(DISABLE);
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	i32_ret = raydium_i2c_pda2_read(client,
+					RAYDIUM_PDA2_PANEL_VERSION_ADDR,
+					u8_rbuffer, 8);
+	if (i32_ret < 0)
+		goto exit_i2c_error;
+	snprintf(p_i8_buf, PAGE_SIZE,
+		 "RAD Touch Panel Version : %02X%02X%02X%02X%02X%02X\n",
+		u8_rbuffer[0], u8_rbuffer[1], u8_rbuffer[2],
+		u8_rbuffer[3], u8_rbuffer[4], u8_rbuffer[5]);
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+
+	u16_len = strlen(p_i8_buf);
+	i32_ret = u16_len + 1;
+	goto exit_upgrade;
+
+exit_i2c_error:
+	mutex_unlock(&g_raydium_ts->lock);
+	raydium_irq_control(ENABLE);
+exit_upgrade:
+	return i32_ret;
+}
+
+static ssize_t raydium_fw_upgrade_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &g_u8_upgrade_type);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	return count;
+}
+
+static ssize_t raydium_fw_upgrade_show(struct device *dev,
+				       struct device_attribute *attr,
+				       char *p_i8_buf)
+{
+	int i32_ret = 0, i32_result = FAIL;
+	unsigned short u16_len = 0;
+	unsigned char u8_mode_change;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	raydium_irq_control(DISABLE);
+
+	pr_info("[touch]RAD burn type is %d\n", g_u8_upgrade_type);
+
+	if ((g_u8_raydium_flag & ENG_MODE) == 0) {
+		g_u8_raydium_flag |= ENG_MODE;
+		u8_mode_change = 1;
+	}
+
+	if ((g_u8_table_setting == 1) && (g_u8_table_init == 1))
+		raydium_mem_table_setting();
+
+	if (g_u8_upgrade_type == 1) {
+		i32_ret = raydium_burn_fw(client);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_result = SUCCESS;
+	} else if (g_u8_upgrade_type == 2) {
+		i32_ret = raydium_burn_comp(client);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_result = SUCCESS;
+	} else if (g_u8_upgrade_type == 4) {
+		i32_ret = raydium_load_test_fw(client);
+		if (i32_ret < 0)
+			goto exit_upgrade;
+
+		i32_result = SUCCESS;
+	}
+
+exit_upgrade:
+	if (u8_mode_change) {
+		pr_info("[touch]g_u8_raydium_flag : %d", g_u8_raydium_flag);
+		g_u8_raydium_flag &= ~ENG_MODE;
+		u8_mode_change = 0;
+	}
+	raydium_irq_control(ENABLE);
+	g_u8_upgrade_type = 0;
+
+	snprintf(p_i8_buf, PAGE_SIZE, "FW Upgrade result : %d\n", i32_result);
+	u16_len = strlen(p_i8_buf);
+	return u16_len + 1;
+}
+static ssize_t raydium_i2c_pda2_page_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_page = 0;
+	char *temp_buf, *token, *free_temp_buf, *free_token;
+	const char *delim = " ,";
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count < 2)
+		return -EINVAL;
+	temp_buf = kzalloc(count + 1, GFP_KERNEL);
+	if (temp_buf == NULL)
+		return -ENOMEM;
+
+	token = kzalloc(count + 1, GFP_KERNEL);
+	if (token == NULL) {
+		kfree(temp_buf);
+		return -ENOMEM;
+	}
+
+	free_temp_buf = temp_buf;
+	free_token = token;
+
+	strlcpy(temp_buf, p_i8_buf, count);
+
+	token = strsep(&temp_buf, delim);
+
+	if (temp_buf) {
+		pr_err("[touch]input error, extra auguments!n");
+		i32_ret = -EINVAL;
+		goto exit_error;
+	}
+	i32_ret = kstrtou8(token, 16, &u8_page);
+
+	if (i32_ret < 0)
+		goto exit_error;
+
+	mutex_lock(&g_raydium_ts->lock);
+
+	i32_ret = raydium_i2c_pda2_set_page(client, g_raydium_ts->is_suspend, u8_page);
+	if (i32_ret < 0)
+		goto exit_set_error;
+
+	/* TODO: Page check, Due to ISR will change page back to Page_0.
+	 *  Or disable IRQ during PDA2 access period
+	 */
+
+exit_set_error:
+	mutex_unlock(&g_raydium_ts->lock);
+
+exit_error:
+	kfree(free_token);
+	kfree(free_temp_buf);
+	return count;
+}
+
+static ssize_t raydium_flag_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *p_i8_buf)
+{
+	unsigned short u16_len = 0;
+
+	snprintf(p_i8_buf, PAGE_SIZE, "%d", g_u8_raydium_flag);
+	/*pr_info("[touch]RAD flag : %d\n", g_u8_raydium_flag);*/
+	u16_len = strlen(p_i8_buf);
+
+	return u16_len + 1;
+}
+
+static ssize_t raydium_flag_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_flag = 0;
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_flag);
+	if (i32_ret < 0)
+		return i32_ret;
+	g_u8_raydium_flag = u8_flag;
+	return count;
+}
+
+static ssize_t raydium_mem_store(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_type = 0;
+	unsigned int u32_image_version;
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	pr_info("[touch]%s\n", __func__);
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_type);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	if (u8_type > 3) {
+		pr_info("[touch]Input invalid value!!\n");
+		return ERROR;
+	}
+
+	if (g_rad_boot_image != NULL)
+		kfree(g_rad_boot_image);
+	if (g_rad_init_image != NULL)
+		kfree(g_rad_init_image);
+	if (g_rad_fw_image != NULL)
+		kfree(g_rad_fw_image);
+	if (g_rad_para_image != NULL)
+		kfree(g_rad_para_image);
+	if (g_rad_testfw_image != NULL)
+		kfree(g_rad_testfw_image);
+	if (g_rad_testpara_image != NULL)
+		kfree(g_rad_testpara_image);
+
+	if (!raydium_id_init(u8_type)) {
+		pr_info("[touch]Set Raydium id failed!\n");
+		return count;
+	}
+
+	raydium_mem_table_init(g_raydium_ts->id);
+	if (raydium_mem_table_setting()) {
+		u32_image_version = (g_rad_para_image[0x0004] << 24) |
+			(g_rad_para_image[0x0005] << 16) |
+			(g_rad_para_image[0x0006] << 8) |
+			g_rad_para_image[0x0007];
+
+		pr_info("[touch]RAD Image FW ver : 0x%x\n", u32_image_version);
+	} else
+		pr_info("[touch]Mem init failed!\n");
+
+	return count;
+}
+
+static ssize_t raydium_i2c_raw_data_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	char *temp_buf, *token, *free_temp_buf, *free_token;
+	const char *delim = " ,";
+	unsigned char u8_w_data[RAD_FT_CMD_LENGTH];
+
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count < 2)
+		return -EINVAL;
+	temp_buf = kzalloc(count + 1, GFP_KERNEL);
+	if (temp_buf  == NULL) {
+		pr_err("[touch]kzalloc temp_buf failed\n");
+		return -ENOMEM;
+	}
+
+	token = kzalloc(count + 1, GFP_KERNEL);
+	if (token  == NULL) {
+		kfree(temp_buf);
+		return -ENOMEM;
+	}
+
+	free_temp_buf = temp_buf;
+	free_token = token;
+
+	strlcpy(temp_buf, p_i8_buf, count);
+
+	token = strsep(&temp_buf, delim);
+
+	i32_ret = kstrtou8(token, 16, &g_u8_raw_data_type);
+
+	token = strsep(&temp_buf, delim);
+	if (token) {
+		i32_ret = kstrtouint(token, 16, &g_u32_raw_data_len);
+		if (i32_ret < 0)
+			goto exit_error;
+
+
+	} else { /* without length info*/
+		i32_ret = -EINVAL;
+		goto exit_error;
+	}
+
+	if (temp_buf) { /* too much arguments*/
+		i32_ret = -E2BIG;
+		goto exit_error;
+	}
+
+	memset(u8_w_data, 0x00, RAD_FT_CMD_LENGTH);
+
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda2_set_page(client,
+					g_raydium_ts->is_suspend,
+					RAYDIUM_PDA2_PAGE_0);
+	if (i32_ret < 0) {
+		mutex_unlock(&g_raydium_ts->lock);
+		goto exit_error;
+	}
+
+	g_u8_resetflag = true;
+
+	u8_w_data[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+	u8_w_data[RAD_FT_CMD_POS] = g_u8_raw_data_type;
+
+	i32_ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_HOST_CMD_ADDR,
+					u8_w_data, RAD_FT_CMD_LENGTH);
+	mutex_unlock(&g_raydium_ts->lock);
+	if (i32_ret < 0)
+		goto exit_error;
+
+	if (g_u8_raw_data_type == 0) {
+		msleep(10);
+		g_u8_resetflag = false;
+	}
+exit_error:
+	kfree(free_token);
+	kfree(free_temp_buf);
+
+	return count;
+}
+static ssize_t raydium_i2c_raw_data_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[MAX_READ_PACKET_SIZE];
+	unsigned int u32_target_addr;
+	unsigned int u32_offset;
+	unsigned short u16_read_length;
+
+	int i32_ret = -1;
+	int i32_retry = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct raydium_ts_data *ts =
+		(struct raydium_ts_data *)i2c_get_clientdata(client);
+	unsigned char u8_retry_limit = (ts->is_suspend) ? 30 : 3;
+
+	memset(u8_rbuffer, 0x00, MAX_READ_PACKET_SIZE);
+
+	/* make sure update flag was set*/
+	for (i32_retry = 0; i32_retry < u8_retry_limit; i32_retry++) {
+		mutex_lock(&ts->lock);
+		i32_ret = raydium_i2c_pda2_set_page(client,
+						ts->is_suspend,
+						RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		i32_ret = raydium_i2c_pda2_read(client,
+						RAYDIUM_PDA2_HOST_CMD_ADDR,
+						u8_rbuffer,
+						RAD_FT_CMD_LENGTH);
+		mutex_unlock(&ts->lock);
+		if (i32_ret < 0)
+			goto exit_flag_error;
+
+		if ((u8_rbuffer[RAD_FT_CMD_POS] & RAYDIUM_FT_UPDATE) ==
+		    RAYDIUM_FT_UPDATE)
+			break;
+
+		usleep_range(4500, 5500);
+	}
+
+	if (i32_retry == u8_retry_limit) {
+		i32_ret = -EAGAIN;
+		goto exit_flag_error;
+	}
+
+	u32_offset = 0;
+	u16_read_length = 0;
+	while (u32_offset < g_u32_raw_data_len) {
+		if ((u32_offset + MAX_READ_PACKET_SIZE) <
+		    g_u32_raw_data_len)
+			u16_read_length = MAX_READ_PACKET_SIZE;
+		else
+			u16_read_length =
+			(unsigned short)(g_u32_raw_data_len - u32_offset);
+
+		u32_target_addr = RAD_READ_FT_DATA_CMD + u32_offset;
+
+		mutex_lock(&(ts->lock));
+		i32_ret = raydium_i2c_pda2_set_page(client,
+						ts->is_suspend,
+						RAYDIUM_PDA2_PAGE_0);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		*(unsigned int *)u8_rbuffer = (RAD_I2C_PDA_MODE_ENABLE << 24)
+			| ((u32_target_addr & (~MASK_8BIT)) >> 8);
+
+		/*using byte mode to read 4 bytes*/
+		i32_ret = raydium_i2c_pda2_write(client,
+				RAYDIUM_PDA2_PDA_CFG_ADDR, u8_rbuffer, 4);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		i32_ret = raydium_i2c_pda2_set_page(client,
+				ts->is_suspend,
+				RAYDIUM_PDA2_ENABLE_PDA);
+		if (i32_ret < 0)
+			goto exit_i2c_error;
+
+		i32_ret = raydium_i2c_pda2_read(client,
+				(unsigned char)(u32_target_addr & MASK_8BIT),
+				u8_rbuffer,
+				u16_read_length);
+
+		mutex_unlock(&(ts->lock));
+		if (i32_ret < 0)
+			goto exit_flag_error;
+
+		memcpy((p_i8_buf + u32_offset), u8_rbuffer, u16_read_length);
+
+		u32_offset += u16_read_length;
+	}
+
+	/* clear update flag to get next one*/
+	u8_rbuffer[RAD_HOST_CMD_POS] = RAYDIUM_HOST_CMD_NO_OP;
+	u8_rbuffer[RAD_FT_CMD_POS] = g_u8_raw_data_type;
+	mutex_lock(&ts->lock);
+	i32_ret = raydium_i2c_pda2_write(client, RAYDIUM_PDA2_HOST_CMD_ADDR,
+				     u8_rbuffer, RAD_FT_CMD_LENGTH);
+	mutex_unlock(&ts->lock);
+	if (i32_ret < 0)
+		goto exit_flag_error;
+
+	return g_u32_raw_data_len;
+exit_i2c_error:
+	mutex_unlock(&(ts->lock));
+exit_flag_error:
+	return i32_ret;
+}
+static ssize_t raydium_i2c_pda_access_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	char *temp_buf, *token, *free_temp_buf, *free_token;
+	const char *delim = " ,";
+	unsigned char u8_w_data[MAX_WRITE_PACKET_SIZE];
+	unsigned int u32_data_count = 0;
+	unsigned int u32_data_index = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count < 2)
+		return -EINVAL;
+
+	temp_buf = kzalloc(count + 1, GFP_KERNEL);
+	if (temp_buf == NULL)
+		return -ENOMEM;
+
+	token = kzalloc(count + 1, GFP_KERNEL);
+	if (token == NULL) {
+		kfree(temp_buf);
+		return -ENOMEM;
+	}
+
+	free_temp_buf = temp_buf;
+	free_token = token;
+
+	strlcpy(temp_buf, p_i8_buf, count);
+
+	token = strsep(&temp_buf, delim);
+
+	i32_ret = kstrtoul(token, 16, &g_u32_addr);
+
+	token = strsep(&temp_buf, delim);
+	if (token)
+		i32_ret = kstrtouint(token, 16, &u32_data_count);
+	else
+		goto exit_error;
+	if (g_u32_length > MAX_WRITE_PACKET_SIZE)
+		return -EINVAL;
+	g_u32_length = u32_data_count;
+
+	memset(u8_w_data, 0x00, MAX_WRITE_PACKET_SIZE);
+
+	if (temp_buf && u32_data_count) {
+		u32_data_index = 0;
+		while (u32_data_count) {
+			token = strsep(&temp_buf, delim);
+			i32_ret = kstrtou8(token, 16,
+					&u8_w_data[u32_data_index++]);
+			if (i32_ret < 0)
+				goto exit_error;
+			u32_data_count--;
+		}
+		mutex_lock(&g_raydium_ts->lock);
+		i32_ret = raydium_i2c_pda_write(client, g_u32_addr,
+					       u8_w_data, g_u32_length);
+		mutex_unlock(&g_raydium_ts->lock);
+	}
+
+exit_error:
+	kfree(free_token);
+	kfree(free_temp_buf);
+	return count;
+}
+
+static ssize_t raydium_i2c_pda2_mode_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	unsigned char u8_mode;
+
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_raydium_ts->is_suspend)
+		pr_info("[touch]RAD is_suspend at %s\n", __func__);
+
+	/* receive command line arguments string */
+	if (count > 2)
+		return -EINVAL;
+
+	i32_ret = kstrtou8(p_i8_buf, 16, &u8_mode);
+	if (i32_ret < 0)
+		return i32_ret;
+	i32_ret = raydium_i2c_mode_control(client, u8_mode);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	return count;
+}
+
+static ssize_t raydium_i2c_pda2_access_show(struct device *dev,
+		struct device_attribute *attr,
+		char *p_i8_buf)
+{
+	unsigned char u8_rbuffer[4];
+	unsigned short u16_len = 0;
+	int i32_ret = -1;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	if (g_u32_length > 4)
+		return -EINVAL;
+	memset(u8_rbuffer, 0x00, 4);
+
+	mutex_lock(&g_raydium_ts->lock);
+	i32_ret = raydium_i2c_pda2_read(client, g_u8_addr,
+					u8_rbuffer, g_u32_length);
+	mutex_unlock(&g_raydium_ts->lock);
+	if (i32_ret < 0)
+		return i32_ret;
+
+	snprintf(p_i8_buf, PAGE_SIZE, "0x%04X : 0x%02X%02X%02X%02X\n",
+		g_u8_addr, u8_rbuffer[3], u8_rbuffer[2],
+		u8_rbuffer[1], u8_rbuffer[0]);
+	u16_len = strlen(p_i8_buf);
+
+	return u16_len + 1;
+}
+
+static ssize_t raydium_i2c_pda2_access_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	char *temp_buf, *token, *free_temp_buf, *free_token;
+	const char *delim = " ,";
+	unsigned char u8_w_data[MAX_WRITE_PACKET_SIZE];
+	unsigned int u32_data_count = 0;
+	unsigned int u32_data_index = 0;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	/* receive command line arguments string */
+	if (count < 2)
+		return -EINVAL;
+	temp_buf = kzalloc(count + 1, GFP_KERNEL);
+	if (temp_buf  == NULL) {
+		pr_err("[touch]kzalloc temp_buf failed\n");
+		return -ENOMEM;
+	}
+
+	token = kzalloc(count + 1, GFP_KERNEL);
+	if (token  == NULL) {
+		kfree(temp_buf);
+		return -ENOMEM;
+	}
+
+	free_temp_buf = temp_buf;
+	free_token = token;
+
+	strlcpy(temp_buf, p_i8_buf, count);
+
+	token = strsep(&temp_buf, delim);
+
+	i32_ret = kstrtou8(token, 16, &g_u8_addr);
+
+	token = strsep(&temp_buf, delim);
+	if (token)
+		i32_ret = kstrtouint(token, 16, &u32_data_count);
+	else {
+		i32_ret = -EINVAL;
+		goto exit_error;
+	}
+
+	if (u32_data_count > MAX_WRITE_PACKET_SIZE) {
+		i32_ret = -EINVAL;
+		goto exit_error;
+	}
+
+	memset(u8_w_data, 0x00, MAX_WRITE_PACKET_SIZE);
+
+	g_u32_length = u32_data_count;
+
+	if (temp_buf && u32_data_count) {
+		u32_data_index = 0;
+		while (u32_data_count) {
+			token = strsep(&temp_buf, delim);
+			i32_ret = kstrtou8(token, 16,
+					 &u8_w_data[u32_data_index++]);
+			if (i32_ret < 0)
+				goto exit_error;
+			u32_data_count--;
+		}
+
+		mutex_lock(&g_raydium_ts->lock);
+		i32_ret = raydium_i2c_pda2_write(client, g_u8_addr,
+						u8_w_data, g_u32_length);
+		mutex_unlock(&g_raydium_ts->lock);
+		if (i32_ret < 0)
+			goto exit_error;
+	}
+
+exit_error:
+	kfree(free_token);
+	kfree(free_temp_buf);
+	return count;
+}
+
+static ssize_t raydium_receive_fw_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *p_i8_buf, size_t count)
+{
+	int i32_ret = 0;
+	const char *delim = " ,";
+	char *token, *temp_buf, *free_token, *free_temp_buf;
+	static unsigned char *p_u8_firmware_data;
+
+	unsigned char u8_cmd;
+	unsigned long u32_len;
+	static unsigned char u8_type;
+	static unsigned int u32_index;
+
+	if (count == 20) { /*check FW type*/
+		temp_buf = kzalloc(32, GFP_KERNEL);
+		if (temp_buf  == NULL) {
+			pr_err("[touch]kzalloc temp_buf failed\n");
+			return -ENOMEM;
+		}
+
+		token = kzalloc(32, GFP_KERNEL);
+		if (token == NULL) {
+			kfree(temp_buf);
+			return -ENOMEM;
+		}
+
+		free_token = token;
+		free_temp_buf = temp_buf;
+
+		snprintf(temp_buf, PAGE_SIZE, "%s", p_i8_buf);
+		token = strsep(&temp_buf, delim);
+		i32_ret = kstrtou8(token, 16, &u8_cmd);
+		if (i32_ret < 0) {
+			pr_err("[touch]kstrtou8 failed\n");
+			kfree(free_token);
+			kfree(free_temp_buf);
+		}
+
+		token = strsep(&temp_buf, delim);
+		i32_ret = kstrtou8(token, 16, &u8_type);
+		if (i32_ret < 0) {
+			pr_err("[touch]kstrtou8 failed\n");
+			kfree(temp_buf);
+			kfree(token);
+		}
+
+		token = strsep(&temp_buf, delim);
+		i32_ret = kstrtoul(token, 16, &u32_len);
+		if (i32_ret < 0) {
+			pr_err("[touch]kstrtou8 failed\n");
+			kfree(temp_buf);
+			kfree(token);
+		}
+
+		pr_info("[touch]uc_cmd=0x%x, uc_type=0x%x, u16_len=0x%x\n",
+			u8_cmd, u8_type, (unsigned int)u32_len);
+
+		if (u8_cmd == RAD_CMD_UPDATE_BIN) { /*check FW length*/
+			u32_index = 0;
+			if (u8_type == RAYDIUM_BOOTLOADER) {
+				memset(g_rad_boot_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_boot_image;
+			} else if (u8_type == RAYDIUM_INIT) {
+				memset(g_rad_init_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_init_image;
+			} else if (u8_type == RAYDIUM_PARA) {
+				memset(g_rad_para_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_para_image;
+			} else if (u8_type == RAYDIUM_FIRMWARE) {
+				memset(g_rad_fw_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_fw_image;
+			} else if (u8_type == RAYDIUM_TEST_PARA) {
+				memset(g_rad_testpara_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_testpara_image;
+			} else if (u8_type == RAYDIUM_TEST_FW) {
+				memset(g_rad_testfw_image, 0, u32_len);
+				p_u8_firmware_data = g_rad_testfw_image;
+			}
+
+		} else if (u8_cmd == RAD_CMD_UPDATE_END) { /*set buffer finish*/
+			if (((g_raydium_ts->id & 0x2000) == 0x2000)
+					&& (u8_type == RAYDIUM_TEST_FW)) {
+				memcpy((g_rad_testfw_image + RAD_FW_2X_SIZE),
+					g_rad_testpara_image, RAD_PARA_2X_SIZE + 4);
+			}
+
+			u32_index = 0;
+			g_u8_table_setting = 0;
+
+		} else if (u8_cmd == RAD_CMD_BURN_FINISH) { /*free buffer*/
+			u8_type = 0;
+			u32_index = 0;
+			g_u8_table_setting = 1;
+		}
+
+		kfree(free_temp_buf);
+		kfree(free_token);
+	} else  if (count > 10) {	/*start copy FW to array*/
+		memcpy((p_u8_firmware_data + u32_index), p_i8_buf, count);
+		u32_index += count;
+	} else
+		pr_info("[touch]other case, count=%d\n", count);
+
+	return count;
+}
+#ifdef RAD_SELFTEST
+static ssize_t raydium_selftest_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *p_i8_buf)
+{
+	int i32_ret = SUCCESS;
+
+	pr_info("[touch]do selftest\n");
+
+	i32_ret = raydium_do_selftest();
+
+	snprintf(p_i8_buf, PAGE_SIZE, "Raydium do selftest : %d\n", i32_ret);
+
+	return strlen(p_i8_buf) + 1;
+}
+
+#endif
+/* panel calibration cmd (R)
+ *  example:cat raydium_ic_verion
+ */
+static DEVICE_ATTR(raydium_touch_calibration, 0644,
+		   raydium_touch_calibration_show,
+		   NULL);
+
+/* check the i2c (R)
+ *  example:cat raydium_check_i2c
+ */
+static DEVICE_ATTR(raydium_check_i2c, 0644,
+		   raydium_check_i2c_show,
+		   NULL);
+
+/* upgrade configurate and algo firmware from app.bin (W)
+ *  example:echo "offset num_of_bin length *_app.bin [length *_app.bin]"
+ *  > raydium_fw_upgrade_mode
+ */
+static DEVICE_ATTR(raydium_fw_upgrade, 0644,
+		   raydium_fw_upgrade_show,
+		   raydium_fw_upgrade_store);
+
+/* change I2C communication mode (W)
+ *  example:echo 1 > raydium_i2c_pda2_mode ==> enable pda2 mode
+ *        echo 0 > raydium_i2c_pda2_mode ==> disable pda2 mode
+ */
+static DEVICE_ATTR(raydium_i2c_pda2_mode, 0644,
+		   NULL,
+		   raydium_i2c_pda2_mode_store);
+
+/* I2C pda mode (R/W)
+ *  example:    cat raydium_i2c_pda_access ==> read pda address provided by the
+ *		following cmd
+ *		echo ADDRinHEX [DATAinHEX] > raydium_i2c_pda_access ==> write
+ *		pda address [data]
+ */
+static DEVICE_ATTR(raydium_i2c_pda_access, 0644,
+		   raydium_i2c_pda_access_show,
+		   raydium_i2c_pda_access_store);
+
+/* I2C pda2 mode (R/W)
+ *  example:    cat raydium_i2c_pda2_access ==> read pda2 address provided by
+ *		the following cmd
+ *		echo ADDRinHEX [DATAinHEX] > raydium_i2c_pda2_access ==>
+ *		write pda2 address [data]
+ */
+static DEVICE_ATTR(raydium_i2c_pda2_access, 0644,
+		   raydium_i2c_pda2_access_show,
+		   raydium_i2c_pda2_access_store);
+
+/* I2C pda2 mode page (W)
+ *  example:    echo PAGEinHEX > raydium_i2c_pda2_page ==> write pda2 page
+ */
+static DEVICE_ATTR(raydium_i2c_pda2_page, 0644,
+		   NULL,
+		   raydium_i2c_pda2_page_store);
+
+/* I2C read/set FT raw data (R/W)
+ *  example:    cat raydium_i2c_raw_data ==> read raw data with specific length
+ *		of corresponding type provided by the following cmd
+ *              echo DataTypeinHEX RawDataLengthinHEX > raydium_i2c_raw_data
+ *		==> set raw data type and its length
+ */
+static DEVICE_ATTR(raydium_i2c_raw_data, 0644,
+		   raydium_i2c_raw_data_show,
+		   raydium_i2c_raw_data_store);
+
+/* Read interrupt flag cmd (R)
+ *  example:cat raydium_flag
+ */
+static DEVICE_ATTR(raydium_flag, 0644,
+		   raydium_flag_show,
+		   raydium_flag_store);
+
+/* Read interrupt flag cmd (R)
+ *  example:cat raydium_int_flag
+ */
+static DEVICE_ATTR(raydium_int_flag, 0644,
+		   raydium_flag_show,
+		   raydium_flag_store);
+
+/* Read selftest flag cmd (R)
+ *  example:cat raydium_int_flag
+ */
+static DEVICE_ATTR(raydium_selftest_flag, 0644,
+		   raydium_flag_show,
+		   raydium_flag_store);
+
+/* Touch lock (W)
+ *  example:    echo 1 > raydium_i2c_touch_lock ==> enable touch lock
+ *            echo 0 > raydium_i2c_touch_lock ==> disable touch lock
+ */
+static DEVICE_ATTR(raydium_i2c_touch_lock, 0644,
+		   NULL,
+		   raydium_touch_lock_store);
+
+/* show the fw version (R)
+ *  example:cat raydium_fw_version
+ */
+static DEVICE_ATTR(raydium_check_fw_version, 0644,
+		   raydium_check_fw_version_show,
+		   NULL);
+
+/* show the driver version (R)
+ *  example:cat raydium_check_driver_version
+ */
+static DEVICE_ATTR(raydium_check_driver_version, 0644,
+		   raydium_check_driver_version_show,
+		   NULL);
+/* show the panel version (R)
+ *  example:cat raydium_panel_version
+ */
+static DEVICE_ATTR(raydium_check_panel_version, 0644,
+		   raydium_check_panel_version_show,
+		   NULL);
+
+static DEVICE_ATTR(raydium_hw_reset, 0644,
+		   raydium_hw_reset_show,
+		   NULL);
+
+static DEVICE_ATTR(raydium_irq_state, 0644,
+		   raydium_irq_state_show,
+		   NULL);
+static DEVICE_ATTR(raydium_palm_status, 0644,
+		   raydium_palm_status_show,
+		   NULL);
+static DEVICE_ATTR(raydium_palm_area, 0644,
+		   raydium_palm_area_show,
+		   raydium_palm_area_store);
+static DEVICE_ATTR(raydium_reset_control, 0644,
+		   NULL,
+		   raydium_reset_control_store);
+static DEVICE_ATTR(raydium_receive_fw_control, 0644,
+		   NULL,
+		   raydium_receive_fw_store);
+
+static DEVICE_ATTR(raydium_mem_setting, 0644,
+		   NULL,
+		   raydium_mem_store);
+
+#ifdef RAD_SELFTEST
+static DEVICE_ATTR(raydium_do_selftest, 0644,
+		   raydium_selftest_show,
+		   NULL);
+#endif
+/*add your attr in here*/
+struct attribute *raydium_attributes[] = {
+	&dev_attr_raydium_touch_calibration.attr,
+	&dev_attr_raydium_check_i2c.attr,
+	&dev_attr_raydium_i2c_pda2_mode.attr,
+	&dev_attr_raydium_i2c_pda_access.attr,
+	&dev_attr_raydium_i2c_pda2_access.attr,
+	&dev_attr_raydium_i2c_pda2_page.attr,
+	&dev_attr_raydium_i2c_raw_data.attr,
+	&dev_attr_raydium_flag.attr,
+	&dev_attr_raydium_i2c_touch_lock.attr,
+	&dev_attr_raydium_fw_upgrade.attr,
+	&dev_attr_raydium_check_fw_version.attr,
+	&dev_attr_raydium_check_panel_version.attr,
+	&dev_attr_raydium_hw_reset.attr,
+	&dev_attr_raydium_irq_state.attr,
+	&dev_attr_raydium_palm_status.attr,
+	&dev_attr_raydium_palm_area.attr,
+	&dev_attr_raydium_int_flag.attr,
+	&dev_attr_raydium_selftest_flag.attr,
+	&dev_attr_raydium_check_driver_version.attr,
+	&dev_attr_raydium_reset_control.attr,
+	&dev_attr_raydium_receive_fw_control.attr,
+	&dev_attr_raydium_mem_setting.attr,
+#ifdef RAD_SELFTEST	
+	&dev_attr_raydium_do_selftest.attr,
+#endif	
+	NULL
+};
+
+MODULE_AUTHOR("Raydium");
+MODULE_DESCRIPTION("Raydium TouchScreen driver");
+MODULE_LICENSE("GPL");