Input: enable touch atmel_mXT224E

touchscreen:
Device Drivers  --->
Input device support  --->
[*]   Touchscreens  --->
[*]   Atmel mXT224E based touchscreens

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 07e9e82..9ebc0d2 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -943,4 +943,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called zforce_ts.
 
+config TOUCHSCREEN_MXT224E
+	tristate "Atmel mXT224E based touchscreens"
+	depends on I2C
+	help
+	  Say Y here if you have a TPS6507x based touchscreen
+	  controller.
+
+	  If unsure, say N.
+
+	  module will be called atmel_mXT224E.
+
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 62801f2..c343315 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -77,3 +77,4 @@
 obj-$(CONFIG_TOUCHSCREEN_W90X900)	+= w90p910_ts.o
 obj-$(CONFIG_TOUCHSCREEN_TPS6507X)	+= tps6507x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_ZFORCE)	+= zforce_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MXT224E)	+= atmel_mXT224E.o
diff --git a/drivers/input/touchscreen/atmel_mXT224E.c b/drivers/input/touchscreen/atmel_mXT224E.c
new file mode 100644
index 0000000..0a7fab2
--- /dev/null
+++ b/drivers/input/touchscreen/atmel_mXT224E.c
@@ -0,0 +1,1473 @@
+/* drivers/input/touchscreen/atmel_mXT224E.c - ATMEL Touch driver
+ *
+ * Copyright (C) 2008 ATMEL
+ * Copyright (C) 2011 Huawei Corporation.
+ *
+ * Based on touchscreen code from Atmel Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/jiffies.h>
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/bitops.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+
+#include <linux/kthread.h>
+
+#ifdef TS_ATMEL_DEBUG
+#define TS_DEBUG_ATMEL(fmt, args...) pr_info(fmt, ##args)
+#else
+#define TS_DEBUG_ATMEL(fmt, args...)
+#endif
+
+#define ATMEL_MXT224E_NAME "atmel_mxt224e"
+
+#define INFO_BLK_FID                            0
+#define INFO_BLK_VID                            1
+#define INFO_BLK_VER                            2
+#define INFO_BLK_BUILD                          3
+#define INFO_BLK_XSIZE                          4
+#define INFO_BLK_YSIZE                          5
+#define INFO_BLK_OBJS                           6
+
+#define OBJ_TABLE_TYPE                          0
+#define OBJ_TABLE_LSB                           1
+#define OBJ_TABLE_MSB                           2
+#define OBJ_TABLE_SIZE                          3
+#define OBJ_TABLE_INSTANCES                     4
+#define OBJ_TABLE_RIDS                          5
+
+#define RESERVED_T0                               0u
+#define RESERVED_T1                               1u
+#define DEBUG_DELTAS_T2                           2u
+#define DEBUG_REFERENCES_T3                       3u
+#define DEBUG_SIGNALS_T4                          4u
+#define GEN_MESSAGEPROCESSOR_T5                   5u
+#define GEN_COMMANDPROCESSOR_T6                   6u
+#define GEN_POWERCONFIG_T7                        7u
+#define GEN_ACQUISITIONCONFIG_T8                  8u
+#define TOUCH_MULTITOUCHSCREEN_T9                 9u
+#define TOUCH_SINGLETOUCHSCREEN_T10               10u
+#define TOUCH_XSLIDER_T11                         11u
+#define TOUCH_YSLIDER_T12                         12u
+#define TOUCH_XWHEEL_T13                          13u
+#define TOUCH_YWHEEL_T14                          14u
+#define TOUCH_KEYARRAY_T15                        15u
+#define PROCG_SIGNALFILTER_T16                    16u
+#define PROCI_LINEARIZATIONTABLE_T17              17u
+#define SPT_COMCONFIG_T18                         18u
+#define SPT_GPIOPWM_T19                           19u
+#define PROCI_GRIPFACESUPPRESSION_T20             20u
+#define RESERVED_T21                              21u
+#define PROCG_NOISESUPPRESSION_T22                22u
+#define TOUCH_PROXIMITY_T23                       23u
+#define PROCI_ONETOUCHGESTUREPROCESSOR_T24        24u
+#define SPT_SELFTEST_T25                          25u
+#define DEBUG_CTERANGE_T26                        26u
+#define PROCI_TWOTOUCHGESTUREPROCESSOR_T27        27u
+#define SPT_CTECONFIG_T28                         28u
+#define SPT_GPI_T29                               29u
+#define SPT_GATE_T30                              30u
+#define TOUCH_KEYSET_T31                          31u
+#define TOUCH_XSLIDERSET_T32                      32u
+#define DIAGNOSTIC_T37                            37u
+#define PROCI_GRIPSUPPRESSION_T40                 40u
+#define PROCI_TOUCHSUPPRESSION_T42                42u
+#define SPT_CTECONFIG_T46                         46u
+#define PROCI_STYLUS_T47                          47u
+#define PROCG_NOISESUPPRESSION_T48                48u
+
+#define T37_PAGE_SIZE                           128
+
+#define T37_TCH_FLAG_SIZE                       80
+#define T37_TCH_FLAG_IDX                        0
+#define T37_ATCH_FLAG_IDX                       40
+
+#define T37_MODE                                0
+#define T37_PAGE                                1
+#define T37_DATA                                2 /* n bytes */
+
+#define T37_PAGE_NUM0                           0
+#define T37_PAGE_NUM1                           1
+#define T37_PAGE_NUM2                           2
+#define T37_PAGE_NUM3                           3
+
+#define MSG_RID                                 0
+
+#define T6_CFG_RESET                            0
+#define T6_CFG_BACKUPNV                         1
+#define T6_CFG_CALIBRATE                        2
+#define T6_CFG_REPORTALL                        3
+/* Reserved */
+#define T6_CFG_DIAG                             5
+
+#define T6_CFG_DIAG_CMD_PAGEUP                  0x01
+#define T6_CFG_DIAG_CMD_PAGEDOWN                0x02
+#define T6_CFG_DIAG_CMD_DELTAS                  0x10
+#define T6_CFG_DIAG_CMD_REF                     0x11
+#define T6_CFG_DIAG_CMD_CTE                     0x31
+#define T6_CFG_DIAG_CMD_TCH                     0xF3
+
+#define T6_MSG_STATUS                           1
+#define T6_MSG_CHECKSUM                         2 /* three bytes */
+
+#define T6_MSG_STATUS_COMSERR                   BIT(2)
+#define T6_MSG_STATUS_CFGERR                    BIT(3)
+#define T6_MSG_STATUS_CAL                       BIT(4)
+#define T6_MSG_STATUS_SIGERR                    BIT(5)
+#define T6_MSG_STATUS_OFL                       BIT(6)
+#define T6_MSG_STATUS_RESET                     BIT(7)
+
+#define T7_CFG_IDLEACQINT                       0
+#define T7_CFG_ACTVACQINT                       1
+#define T7_CFG_ACTV2IDLETO                      2
+
+#define T8_CFG_CHRGTIME                         0
+/* Reserved */
+#define T8_CFG_TCHDRIFT                         2
+#define T8_CFG_DRIFTST                          3
+#define T8_CFG_TCHAUTOCAL                       4
+#define T8_CFG_SYNC                             5
+#define T8_CFG_ATCHCALST                        6
+#define T8_CFG_ATCHCALSTHR                      7
+#define T8_CFG_ATCHFRCCALTHR                    8 /* FW v2.x */
+#define T8_CFG_ATCHFRCCALRATIO                  9 /* FW v2.x */
+
+#define T9_CFG_CTRL                             0
+#define T9_CFG_XORIGIN                          1
+#define T9_CFG_YORIGIN                          2
+#define T9_CFG_XSIZE                            3
+#define T9_CFG_YSIZE                            4
+#define T9_CFG_AKSCFG                           5
+#define T9_CFG_BLEN                             6
+#define T9_CFG_TCHTHR                           7
+#define T9_CFG_TCHDI                            8
+#define T9_CFG_ORIENT                           9
+#define T9_CFG_MRGTIMEOUT                       10
+#define T9_CFG_MOVHYSTI                         11
+#define T9_CFG_MOVHYSTN                         12
+#define T9_CFG_MOVFILTER                        13
+#define T9_CFG_NUMTOUCH                         14
+#define T9_CFG_MRGHYST                          15
+#define T9_CFG_MRGTHR                           16
+#define T9_CFG_AMPHYST                          17
+#define T9_CFG_XRANGE                           18 /* two bytes */
+#define T9_CFG_YRANGE                           20 /* two bytes */
+#define T9_CFG_XLOCLIP                          22
+#define T9_CFG_XHICLIP                          23
+#define T9_CFG_YLOCLIP                          24
+#define T9_CFG_YHICLIP                          25
+#define T9_CFG_XEDGECTRL                        26
+#define T9_CFG_XEDGEDIST                        27
+#define T9_CFG_YEDGECTRL                        28
+#define T9_CFG_YEDGEDIST                        29
+#define T9_CFG_JUMPLIMIT                        30
+#define T9_CFG_TCHHYST                          31 /* FW v2.x */
+
+#define T9_MSG_STATUS                           1
+#define T9_MSG_XPOSMSB                          2
+#define T9_MSG_YPOSMSB                          3
+#define T9_MSG_XYPOSLSB                         4
+#define T9_MSG_TCHAREA                          5
+#define T9_MSG_TCHAMPLITUDE                     6
+#define T9_MSG_TCHVECTOR                        7
+
+#define T9_MSG_STATUS_UNGRIP                    BIT(0) /* FW v2.x */
+#define T9_MSG_STATUS_SUPPRESS                  BIT(1)
+#define T9_MSG_STATUS_AMP                       BIT(2)
+#define T9_MSG_STATUS_VECTOR                    BIT(3)
+#define T9_MSG_STATUS_MOVE                      BIT(4)
+#define T9_MSG_STATUS_RELEASE                   BIT(5)
+#define T9_MSG_STATUS_PRESS                     BIT(6)
+#define T9_MSG_STATUS_DETECT                    BIT(7)
+
+#define T20_CFG_CTRL                            0
+#define T20_CFG_XLOGRIP                         1
+#define T20_CFG_XHIGRIP                         2
+#define T20_CFG_YLOGRIP                         3
+#define T20_CFG_YHIGRIP                         4
+#define T20_CFG_MAXTCHS                         5
+/* Reserved */
+#define T20_CFG_SZTHR1                          7
+#define T20_CFG_SZTHR2                          8
+#define T20_CFG_SHPTHR1                         9
+#define T20_CFG_SHPTHR2                         10
+#define T20_CFG_SHPEXTTO                        11
+
+#define T20_MSG_STATUS                          1
+
+#define T20_MSG_STATUS_FACESUP                  BIT(0)
+
+#define T22_CFG_CTRL                            0
+/* Reserved */
+#define T22_CFG_GCAFUL                          3 /* two bytes */
+#define T22_CFG_GCAFLL                          5 /* two bytes */
+#define T22_CFG_ACTVGCAFVALID                   7
+#define T22_CFG_NOISETHR                        8
+/* Reserved */
+#define T22_CFG_FREQHOPSCALE                    10
+#define T22_CFG_FREQ                            11 /* five bytes */
+#define T22_CFG_IDLEGCAFVAILD                   16
+
+#define T22_MSG_STATUS                          1
+#define T22_MSG_GCAFDEPTH                       2
+#define T22_MSG_FREQINDEX                       3
+
+#define T22_MSG_STATUS_FHCHG                    BIT(0)
+#define T22_MSG_STATUS_GCAFERR                  BIT(2)
+#define T22_MSG_STATUS_FHERR                    BIT(3)
+#define T22_MSG_STATUS_GCAFCHG                  BIT(4)
+
+#define T19_CFG_CTRL                            0
+#define T19_CFG_REPORTMASK                      1
+#define T19_CFG_DIR                             2
+#define T19_CFG_INTPULLUP                       3
+#define T19_CFG_OUT                             4
+#define T19_CFG_WAKE                            5
+#define T19_CFG_PWM                             6
+#define T19_CFG_PERIOD                          7
+#define T19_CFG_DUTY0                           8
+#define T19_CFG_DUTY1                           9
+#define T19_CFG_DUTY2                           10
+#define T19_CFG_DUTY3                           11
+#define T19_CFG_TRIGGER0                        12
+#define T19_CFG_TRIGGER1                        13
+#define T19_CFG_TRIGGER2                        14
+#define T19_CFG_TRIGGER3                        15
+
+#define T19_CFG_CTRL_ENABLE                     BIT(0)
+#define T19_CFG_CTRL_RPTEN                      BIT(1)
+#define T19_CFG_CTRL_FORCERPT                   BIT(2)
+
+#define T19_MSG_STATUS                          1
+
+#define T25_CFG_CTRL                            0
+#define T25_CFG_CMD                             1
+
+#define T25_MSG_STATUS                          1
+#define T25_MSG_INFO                            2 /* five bytes */
+
+#define T28_CFG_CTRL                            0
+#define T28_CFG_CMD                             1
+#define T28_CFG_MODE                            2
+#define T28_CFG_IDLEGCAFDEPTH                   3
+#define T28_CFG_ACTVGCAFDEPTH                   4
+#define T28_CFG_VOLTAGE                         5
+
+#define T28_CFG_MODE0_X                         16
+#define T28_CFG_MODE0_Y                         14
+
+#define T28_MSG_STATUS                          1
+
+#define T48_NOISESUPPRESSION_CFG	1
+
+/* cable_config[] of atmel_i2c_platform_data */
+/* config[] of atmel_config_data */
+#define CB_TCHTHR                               0
+#define CB_NOISETHR                             1
+#define CB_IDLEGCAFDEPTH                        2
+#define CB_ACTVGCAFDEPTH                        3
+
+#define NC_TCHTHR                               0
+#define NC_TCHDI                                1
+#define NC_NOISETHR                             2
+
+/* filter_level */
+#define FL_XLOGRIPMIN                           0
+#define FL_XLOGRIPMAX                           1
+#define FL_XHIGRIPMIN                           2
+#define FL_XHIGRIPMAX                           3
+
+struct info_id_t {
+    uint8_t family_id;
+    uint8_t variant_id;
+    uint8_t version;
+    uint8_t build;
+    uint8_t matrix_x_size;
+    uint8_t matrix_y_size;
+    uint8_t num_declared_objects;
+};
+
+struct object_t {
+    uint8_t object_type;
+    uint16_t i2c_address;
+    uint8_t size;
+    uint8_t instances;
+    uint8_t num_report_ids;
+    uint8_t report_ids;
+};
+
+struct atmel_virtual_key {
+    int keycode;
+    int range_min;
+    int range_max;
+};
+
+struct atmel_finger_data {
+    int x;
+    int y;
+    int w;
+    int z;
+};
+
+struct atmel_i2c_platform_data {
+    uint16_t version;
+    uint16_t source;
+    uint16_t abs_x_min;
+    uint16_t abs_x_max;
+    uint16_t abs_y_min;
+    uint16_t abs_y_max;
+    uint8_t abs_pressure_min;
+    uint8_t abs_pressure_max;
+    uint8_t abs_width_min;
+    uint8_t abs_width_max;
+    uint8_t abs_area_min;
+    uint8_t abs_area_max;
+    int gpio_irq;
+    int gpio_reset;
+    int (*power)(int on);
+    u8 config_T6[6];
+    u8 config_T7[3];
+    u8 config_T8[10];
+    u8 config_T9[35];
+    u8 config_T15[11];
+    u8 config_T19[16];
+    u8 config_T20[12];
+    u8 config_T22[17];
+    u8 config_T23[15];
+    u8 config_T24[19];
+    u8 config_T25[14];
+    u8 config_T27[7];
+    u8 config_T28[6];
+    u8 config_T40[5];
+    u8 config_T42[8];
+    u8 config_T46[9];
+    u8 config_T47[10];
+    u8 config_T48[54];
+    u8 object_crc[3];
+    u8 cable_config[4];
+    u8 cable_config_T7[3];
+    u8 cable_config_T8[10];
+    u8 cable_config_T9[35];
+    u8 cable_config_T22[17];
+    u8 cable_config_T28[6];
+    u8 cable_config_T46[9];
+    u8 cable_config_T48[54];
+    u8 noise_config[3];
+    u16 filter_level[4];
+    u8 GCAF_level[5];
+    u8 ATCH_NOR[6];
+    u8 ATCH_NOR_20S[6];
+};
+
+struct atmel_config_data {
+    int8_t config[4];
+    int8_t *config_T7;
+    int8_t *config_T8;
+    int8_t *config_T9;
+    int8_t *config_T22;
+    int8_t *config_T28;
+    int8_t *config_T46;
+    int8_t *config_T48;
+};
+
+#define ATMEL_I2C_RETRY_TIMES 10
+
+/* config_setting */
+#define NONE                                    0
+#define CONNECTED                               1
+struct atmel_ts_data {
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	struct atmel_i2c_platform_data *pdata;
+	struct workqueue_struct *atmel_wq;
+	struct work_struct work;
+	int (*power) (int on);
+	struct info_id_t *id;
+	struct object_t *object_table;
+	struct iomux_block *gpio_block;
+	struct block_config *gpio_block_config;
+	uint8_t finger_count;
+	uint16_t abs_x_min;
+	uint16_t abs_x_max;
+	uint16_t abs_y_min;
+	uint16_t abs_y_max;
+	uint8_t abs_area_min;
+	uint8_t abs_area_max;
+	uint8_t abs_width_min;
+	uint8_t abs_width_max;
+	uint8_t abs_pressure_min;
+	uint8_t abs_pressure_max;
+	uint8_t first_pressed;
+	struct atmel_finger_data finger_data[10];
+	uint8_t finger_type;
+	uint8_t finger_support;
+	uint16_t finger_pressed;
+	uint8_t face_suppression;
+	uint8_t grip_suppression;
+	uint8_t noise_status[2];
+	uint16_t *filter_level;
+	uint8_t calibration_confirm;
+	uint64_t timestamp;
+	struct atmel_config_data config_setting[2];
+	int8_t noise_config[3];
+	uint8_t status;
+	uint8_t GCAF_sample;
+	uint8_t *GCAF_level;
+	uint8_t noisethr;
+	uint8_t noisethr_config;
+	uint8_t diag_command;
+	uint8_t *ATCH_EXT;
+	int8_t *ATCH_NOR;
+	int8_t *ATCH_NOR_20S;
+	int pre_data[11];
+	/*unlock flag used to indicate calibration after unlock system*/
+	int unlock_flag;
+
+	/*For usb detect*/
+	struct work_struct usb_work;
+	struct notifier_block nb;
+	unsigned long usb_event;
+	struct mutex lock;
+};
+
+static struct atmel_ts_data *private_ts;
+
+#define LDO_POWR_VOLTAGE 2700000 /*2.7v*/
+static	struct regulator		*LDO;
+
+int i2c_atmel_read(struct i2c_client *client, uint16_t address, uint8_t *data, uint8_t length)
+{
+	int retry, ret;
+	uint8_t addr[2];
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 2,
+			.buf = addr,
+		},
+		{
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = length,
+			.buf = data,
+		}
+	};
+	addr[0] = address & 0xFF;
+	addr[1] = (address >> 8) & 0xFF;
+
+	for (retry = 0; retry < ATMEL_I2C_RETRY_TIMES; retry++) {
+		ret = i2c_transfer(client->adapter, msg, 2);
+		if ((ret == 2) || (ret == -ERESTARTSYS))
+			break;
+		mdelay(10);
+	}
+	if (retry == ATMEL_I2C_RETRY_TIMES) {
+		dev_err(&client->dev,  "k3ts, %s: i2c_read_block retry over %d\n", __func__,
+			ATMEL_I2C_RETRY_TIMES);
+		return -EIO;
+	}
+	return 0;
+}
+
+int i2c_atmel_write(struct i2c_client *client, uint16_t address, uint8_t *data, uint8_t length)
+{
+	int retry, loop_i, ret;
+	uint8_t buf[length + 2];
+
+	struct i2c_msg msg[] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = length + 2,
+			.buf = buf,
+		}
+	};
+
+	buf[0] = address & 0xFF;
+	buf[1] = (address >> 8) & 0xFF;
+
+	for (loop_i = 0; loop_i < length; loop_i++)
+		buf[loop_i + 2] = data[loop_i];
+
+	for (retry = 0; retry < ATMEL_I2C_RETRY_TIMES; retry++) {
+		ret = i2c_transfer(client->adapter, msg, 1);
+		if ((ret == 1) || (ret == -ERESTARTSYS))
+			break;
+		mdelay(10);
+	}
+
+	if (retry == ATMEL_I2C_RETRY_TIMES) {
+		dev_err(&client->dev, "k3ts, %s: i2c_write_block retry over %d\n", __func__,
+			ATMEL_I2C_RETRY_TIMES);
+		return -EIO;
+	}
+	return 0;
+
+}
+
+int i2c_atmel_write_byte_data(struct i2c_client *client, uint16_t address, uint8_t value)
+{
+	i2c_atmel_write(client, address, &value, 1);
+	return 0;
+}
+
+uint16_t get_object_address(struct atmel_ts_data *ts, uint8_t object_type)
+{
+	uint8_t loop_i;
+	for (loop_i = 0; loop_i < ts->id->num_declared_objects; loop_i++) {
+		if (ts->object_table[loop_i].object_type == object_type)
+			return ts->object_table[loop_i].i2c_address;
+	}
+	return 0;
+}
+uint8_t get_object_size(struct atmel_ts_data *ts, uint8_t object_type)
+{
+	uint8_t loop_i;
+	for (loop_i = 0; loop_i < ts->id->num_declared_objects; loop_i++) {
+		if (ts->object_table[loop_i].object_type == object_type)
+			return ts->object_table[loop_i].size;
+	}
+	return 0;
+}
+
+uint8_t get_object_size_from_address(struct atmel_ts_data *ts, int address)
+{
+	uint8_t loop_i;
+	for (loop_i = 0; loop_i < ts->id->num_declared_objects; loop_i++) {
+		if (ts->object_table[loop_i].i2c_address == address)
+			return ts->object_table[loop_i].size;
+	}
+	return 0;
+}
+
+uint8_t get_rid(struct atmel_ts_data *ts, uint8_t object_type)
+{
+	uint8_t loop_i;
+	for (loop_i = 0; loop_i < ts->id->num_declared_objects; loop_i++) {
+		if (ts->object_table[loop_i].object_type == object_type)
+			return ts->object_table[loop_i].report_ids;
+	}
+	return 0;
+}
+
+static void check_calibration(struct atmel_ts_data *ts)
+{
+	uint8_t data[T37_DATA + T37_TCH_FLAG_SIZE];
+	uint8_t loop_i, loop_j, x_limit = 0, check_mask, tch_ch = 0, atch_ch = 0;
+
+	memset(data, 0xFF, sizeof(data));
+	i2c_atmel_write_byte_data(ts->client,
+		get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+		T6_CFG_DIAG, T6_CFG_DIAG_CMD_TCH);
+
+	for (loop_i = 0;
+		!(data[T37_MODE] == T6_CFG_DIAG_CMD_TCH && data[T37_PAGE] == T37_PAGE_NUM0) && loop_i < 10; loop_i++) {
+		msleep(5);
+		i2c_atmel_read(ts->client,
+			get_object_address(ts, DIAGNOSTIC_T37), data, 2);
+	}
+
+	if (loop_i == 10)
+		dev_err(&ts->client->dev, "k3ts, %s: Diag data not ready\n", __func__);
+
+	i2c_atmel_read(ts->client, get_object_address(ts, DIAGNOSTIC_T37), data,
+		T37_DATA + T37_TCH_FLAG_SIZE);
+	if (data[T37_MODE] == T6_CFG_DIAG_CMD_TCH &&
+		data[T37_PAGE] == T37_PAGE_NUM0) {
+		x_limit = T28_CFG_MODE0_X + ts->config_setting[NONE].config_T28[T28_CFG_MODE];
+		x_limit = x_limit << 1;
+		if (x_limit <= 40) {
+			for (loop_i = 0; loop_i < x_limit; loop_i += 2) {
+				for (loop_j = 0; loop_j < BITS_PER_BYTE; loop_j++) {
+					check_mask = BIT_MASK(loop_j);
+					if (data[T37_DATA + T37_TCH_FLAG_IDX + loop_i] &
+						check_mask)
+						tch_ch++;
+					if (data[T37_DATA + T37_TCH_FLAG_IDX + loop_i + 1] &
+						check_mask)
+						tch_ch++;
+					if (data[T37_DATA + T37_ATCH_FLAG_IDX + loop_i] &
+						check_mask)
+						atch_ch++;
+					if (data[T37_DATA + T37_ATCH_FLAG_IDX + loop_i + 1] &
+						check_mask)
+						atch_ch++;
+				}
+			}
+		}
+	}
+	i2c_atmel_write_byte_data(ts->client,
+		get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+		T6_CFG_DIAG, T6_CFG_DIAG_CMD_PAGEUP);
+
+	if (tch_ch && (atch_ch == 0)) {
+		if (jiffies > (ts->timestamp + HZ/2) && (ts->calibration_confirm == 1)) {
+			ts->calibration_confirm = 2;
+		}
+		if (ts->calibration_confirm < 2)
+			ts->calibration_confirm = 1;
+		ts->timestamp = jiffies;
+	} else if (atch_ch > 1 || tch_ch > 8) {
+		ts->calibration_confirm = 0;
+		i2c_atmel_write_byte_data(ts->client,
+			get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+			T6_CFG_CALIBRATE, 0x55);
+	}
+}
+
+static void confirm_calibration(struct atmel_ts_data *ts)
+{
+	i2c_atmel_write(ts->client,
+		get_object_address(ts, GEN_ACQUISITIONCONFIG_T8) +
+		T8_CFG_TCHAUTOCAL, ts->ATCH_NOR_20S, 6);
+	ts->pre_data[0] = 2;
+}
+
+static void msg_process_finger_data_x10y10bit(struct atmel_finger_data *fdata, uint8_t *data)
+{
+    fdata->x = data[T9_MSG_XPOSMSB] << 2 | data[T9_MSG_XYPOSLSB] >> 6;
+    fdata->y = data[T9_MSG_YPOSMSB] << 2 | (data[T9_MSG_XYPOSLSB] & 0x0C) >>2;
+    fdata->w = data[T9_MSG_TCHAREA];
+    fdata->z = data[T9_MSG_TCHAMPLITUDE];
+}
+static void msg_process_finger_data_x10y12bit(struct atmel_finger_data *fdata, uint8_t *data)
+{
+    fdata->x = data[T9_MSG_XPOSMSB] << 2 | data[T9_MSG_XYPOSLSB] >> 6;
+    fdata->y = data[T9_MSG_YPOSMSB] << 4 | (data[T9_MSG_XYPOSLSB] & 0x0F) ;
+    fdata->w = data[T9_MSG_TCHAREA];
+    fdata->z = data[T9_MSG_TCHAMPLITUDE];
+}
+
+static void msg_process_multitouch(struct atmel_ts_data *ts, uint8_t *data, uint8_t idx)
+{
+	if (ts->calibration_confirm < 2 && ts->id->version == 0x10)
+		check_calibration(ts);
+    if(ts->abs_y_max >= 1024) {
+        msg_process_finger_data_x10y12bit(&ts->finger_data[idx], data);
+    } else {
+        msg_process_finger_data_x10y10bit(&ts->finger_data[idx], data);
+    }
+	if (data[T9_MSG_STATUS] & T9_MSG_STATUS_RELEASE) {
+		if (ts->grip_suppression & BIT(idx))
+			ts->grip_suppression &= ~BIT(idx);
+		if (ts->finger_pressed & BIT(idx)) {
+			ts->finger_count--;
+			ts->finger_pressed &= ~BIT(idx);
+			if (!ts->first_pressed) {
+				if (!ts->finger_count)
+					ts->first_pressed = 1;
+			}
+			if (ts->pre_data[0] < 2 && ts->unlock_flag != 1) {
+
+				if (ts->finger_count) {
+					i2c_atmel_write_byte_data(ts->client,
+						get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+						T6_CFG_CALIBRATE, 0x55);
+				} else if (!ts->finger_count && ts->pre_data[0] == 1)
+					ts->pre_data[0] = 0;
+			}
+		}
+	} else if ((data[T9_MSG_STATUS] & (T9_MSG_STATUS_DETECT | T9_MSG_STATUS_PRESS))
+	&& !(ts->finger_pressed & BIT(idx))) {
+		if (ts->id->version >= 0x10 && ts->pre_data[0] < 2) {
+			if (jiffies > (ts->timestamp + 20 * HZ)) {
+				confirm_calibration(ts);
+			}
+		}
+		if (!(ts->grip_suppression & BIT(idx))) {
+			ts->finger_count++;
+			ts->finger_pressed |= BIT(idx);
+			if (ts->id->version >= 0x10 && ts->pre_data[0] < 2) {
+				ts->pre_data[idx + 1] = ts->finger_data[idx].x;
+                ts->pre_data[idx + 2] = ts->finger_data[idx].y;
+				if (ts->finger_count == ts->finger_support) {
+					i2c_atmel_write_byte_data(ts->client,
+						get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+						T6_CFG_CALIBRATE, 0x55);
+				} else if (!ts->pre_data[0] && ts->finger_count == 1)
+						ts->pre_data[0] = 1;
+			}
+		}
+	} else if ((data[T9_MSG_STATUS] & (T9_MSG_STATUS_DETECT|T9_MSG_STATUS_PRESS))
+		&& ts->pre_data[0] < 2 && ts->unlock_flag != 1) {
+            if (ts->finger_count == 1 && ts->pre_data[0] &&
+                 (idx == 0 && ((abs(ts->finger_data[idx].y - ts->pre_data[idx + 2]) > 50)
+                  || (abs(ts->finger_data[idx].x - ts->pre_data[idx + 1]) > 50))))
+            {
+                ts->unlock_flag = 1;
+                ts->calibration_confirm = 2;
+            }
+      }
+
+}
+
+static void compatible_input_report(struct input_dev *idev,
+				struct atmel_finger_data *fdata, uint8_t press, uint8_t last)
+{
+	if (!press) {
+		input_mt_sync(idev);
+		/*input_report_key(idev, BTN_TOUCH, 0);*/
+		input_report_key(idev, BTN_TOUCH, 1);
+
+	} else {
+		TS_DEBUG_ATMEL("k3ts, %s: Touch report_key x = %d, y = %d, z = %d, w = %d\n ", __func__,
+			fdata->x, fdata->y, fdata->z, fdata->w);
+		input_report_abs(idev, ABS_MT_TOUCH_MAJOR, fdata->z);
+		input_report_abs(idev, ABS_MT_WIDTH_MAJOR, fdata->w);
+		input_report_abs(idev, ABS_MT_POSITION_X, fdata->x);
+		input_report_abs(idev, ABS_MT_POSITION_Y, fdata->y);
+		input_mt_sync(idev);
+    }
+}
+
+
+
+static void multi_input_report(struct atmel_ts_data *ts)
+{
+	uint8_t loop_i, finger_report = 0;
+
+	for (loop_i = 0; loop_i < ts->finger_support; loop_i++) {
+		if (ts->finger_pressed & BIT(loop_i)) {
+			compatible_input_report(ts->input_dev, &ts->finger_data[loop_i],
+				1, (ts->finger_count == ++finger_report));
+		}
+	}
+}
+static irqreturn_t atmel_interrupt_fun(int irq, void *dev_id)
+{
+	int ret;
+	struct atmel_ts_data *ts = dev_id;
+	uint8_t data[7];
+	int8_t report_type;
+	uint8_t msg_byte_num = 7;
+
+	memset(data, 0x0, sizeof(data));
+
+	mutex_lock(&ts->lock);
+	ret = i2c_atmel_read(ts->client, get_object_address(ts,
+		GEN_MESSAGEPROCESSOR_T5), data, 7);
+
+	report_type = data[MSG_RID] - ts->finger_type;
+	if (report_type >= 0 && report_type < ts->finger_support) {
+		msg_process_multitouch(ts, data, report_type);
+	} else {
+		if (data[MSG_RID] == get_rid(ts, GEN_COMMANDPROCESSOR_T6)) {
+			if (data[1] & 0x10) {
+				ts->timestamp = jiffies;
+		}
+		if (data[1] & 0x80) {
+			msleep(100);
+
+			i2c_atmel_write_byte_data(ts->client,
+				get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+				T6_CFG_CALIBRATE, 0x55);
+		}
+		msg_byte_num = 5;
+	}
+	if (data[MSG_RID] == get_rid(ts, PROCI_TOUCHSUPPRESSION_T42)) {
+			if (ts->calibration_confirm < 2 && ts->id->version == 0x10) {
+				i2c_atmel_write_byte_data(ts->client,
+					get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+					T6_CFG_CALIBRATE, 0x55);
+			}
+			ts->face_suppression = data[T20_MSG_STATUS];
+			printk(KERN_INFO "Touch Face suppression %s: ",
+			ts->face_suppression ? "Active" : "Inactive");
+			msg_byte_num = 2;
+		}
+	}
+    if (!ts->finger_count || ts->face_suppression) {
+		ts->finger_pressed = 0;
+		ts->finger_count = 0;
+		compatible_input_report(ts->input_dev, NULL, 0, 1);
+	} else {
+		multi_input_report(ts);
+    }
+    input_sync(ts->input_dev);
+    mutex_unlock(&ts->lock);
+
+    return IRQ_HANDLED;
+}
+
+static int read_object_table(struct atmel_ts_data *ts)
+{
+	uint8_t i, type_count = 0;
+	uint8_t data[6];
+	memset(data, 0x0, sizeof(data));
+
+	ts->object_table = kzalloc(sizeof(struct object_t)*ts->id->num_declared_objects, GFP_KERNEL);
+	if (ts->object_table == NULL) {
+		dev_err(&ts->client->dev, "k3ts, %s: allocate object_table failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < ts->id->num_declared_objects; i++) {
+		i2c_atmel_read(ts->client, i * 6 + 0x07, data, 6);
+		ts->object_table[i].object_type = data[OBJ_TABLE_TYPE];
+		ts->object_table[i].i2c_address =
+			data[OBJ_TABLE_LSB] | data[OBJ_TABLE_MSB] << 8;
+		ts->object_table[i].size = data[OBJ_TABLE_SIZE] + 1;
+		ts->object_table[i].instances = data[OBJ_TABLE_INSTANCES];
+		ts->object_table[i].num_report_ids = data[OBJ_TABLE_RIDS];
+		if (data[OBJ_TABLE_RIDS]) {
+			ts->object_table[i].report_ids = type_count + 1;
+			type_count += data[OBJ_TABLE_RIDS];
+		}
+		if (data[OBJ_TABLE_TYPE] == TOUCH_MULTITOUCHSCREEN_T9)
+			ts->finger_type = ts->object_table[i].report_ids;
+	}
+
+	return 0;
+}
+
+struct atmel_i2c_platform_data *atmel_ts_get_pdata(struct i2c_client *client)
+{
+	struct device_node *node = client->dev.of_node;
+	struct atmel_i2c_platform_data *pdata = client->dev.platform_data;
+	u32 data[8];
+
+	if (pdata)
+		return pdata;
+
+	if (!node)
+		return NULL;
+
+	pdata = devm_kzalloc(&client->dev, sizeof(struct atmel_i2c_platform_data),
+				GFP_KERNEL);
+	pdata->gpio_irq = of_get_named_gpio(node, "atmel-ts,gpio-irq", 0);
+	pdata->gpio_reset = of_get_named_gpio(node, "atmel-ts,gpio-reset", 0);
+
+	of_property_read_u32_array(node, "atmel-ts,abs", &data[0], 8);
+	pdata->abs_x_min = data[0];
+	pdata->abs_x_max = data[1];
+	pdata->abs_y_min = data[2];
+	pdata->abs_y_max = data[3];
+	pdata->abs_pressure_min = data[4];
+	pdata->abs_pressure_max = data[5];
+	pdata->abs_width_min = data[6];
+	pdata->abs_width_max = data[7];
+
+	of_property_read_u8_array(node, "atmel-ts,cfg_t6", &pdata->config_T6[0], 6);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t7", &pdata->config_T7[0], 3);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t8", &pdata->config_T8[0], 10);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t9", &pdata->config_T9[0], 35);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t15", &pdata->config_T15[0], 11);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t19", &pdata->config_T19[0], 16);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t23", &pdata->config_T23[0], 15);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t25", &pdata->config_T25[0], 14);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t40", &pdata->config_T40[0], 5);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t42", &pdata->config_T42[0], 8);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t46", &pdata->config_T46[0], 9);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t47", &pdata->config_T47[0], 10);
+	of_property_read_u8_array(node, "atmel-ts,cfg_t48", &pdata->config_T48[0], 54);
+	of_property_read_u8_array(node, "atmel-ts,object_crc", &pdata->object_crc[0], 3);
+	of_property_read_u8_array(node, "atmel-ts,cable_config", &pdata->cable_config[0], 4);
+	of_property_read_u8_array(node, "atmel-ts,cable_config_t7", &pdata->cable_config_T7[0], 3);
+	of_property_read_u8_array(node, "atmel-ts,cable_config_t8", &pdata->cable_config_T8[0], 10);
+	of_property_read_u8_array(node, "atmel-ts,cable_config_t46", &pdata->cable_config_T46[0], 9);
+	of_property_read_u8_array(node, "atmel-ts,cable_config_t48", &pdata->cable_config_T48[0], 54);
+	of_property_read_u8_array(node, "atmel-ts,noise_config", &pdata->noise_config[0], 3);
+	of_property_read_u16_array(node, "atmel-ts,filter_level", &pdata->filter_level[0], 4);
+	of_property_read_u8_array(node, "atmel-ts,gcaf_level", &pdata->GCAF_level[0], 5);
+	of_property_read_u8_array(node, "atmel-ts,atch_nor", &pdata->ATCH_NOR[0], 6);
+	of_property_read_u8_array(node, "atmel-ts,atch_nor_20s", &pdata->ATCH_NOR_20S[0], 6);
+
+	return pdata;
+}
+
+static int atmel_ts_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct atmel_ts_data *ts;
+	struct atmel_i2c_platform_data *pdata;
+	int ret = 0, intr = 0;
+	uint8_t loop_i;
+	struct i2c_msg msg[2];
+	uint8_t data[16];
+	uint8_t CRC_check = 0;
+
+	client->dev.init_name = "atmel-ts";
+	LDO = regulator_get(&client->dev, "ldo");
+	if (IS_ERR(LDO)) {
+		dev_err(&client->dev, "no regulator found\n");
+		LDO = NULL;
+	} else {
+		ret = regulator_enable(LDO);
+		if (!ret)
+			ret = regulator_set_voltage(LDO, LDO_POWR_VOLTAGE, LDO_POWR_VOLTAGE);
+		if (ret)
+			dev_err(&client->dev, "k3ts, %s: failed to set LDO\n", __func__);
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "k3ts, %s: need I2C_FUNC_I2C\n", __func__);
+		ret = -ENODEV;
+		goto err_check_functionality_failed;
+	}
+
+	ts = kzalloc(sizeof(struct atmel_ts_data), GFP_KERNEL);
+	if (ts == NULL) {
+		ret = -ENOMEM;
+		goto err_alloc_data_failed;
+	}
+
+	ts->unlock_flag = 0;
+	mutex_init(&ts->lock);
+
+	ts->atmel_wq = create_singlethread_workqueue("atmel_wq");
+	if (!ts->atmel_wq) {
+		dev_err(&client->dev, "k3ts, %s: create workqueue failed\n", __func__);
+		ret = -ENOMEM;
+		goto err_cread_wq_failed;
+	}
+
+	ts->client = client;
+	i2c_set_clientdata(client, ts);
+
+	pdata = atmel_ts_get_pdata(client);
+	ts->pdata = pdata;
+
+	if (pdata) {
+		ts->power = pdata->power;
+		intr = pdata->gpio_irq;
+		client->irq = gpio_to_irq(intr);
+	}
+	if (ts->power)
+		ret = ts->power(1);
+	ret = gpio_request(intr, "gpio_tp_intr");
+	if (ret) {
+		dev_err(&client->dev, "gpio_request %d failed\n", intr);
+		goto err_request_gpio_failed;
+	}
+	ret = gpio_direction_input(intr);
+	if (ret) {
+		dev_err(&client->dev, "k3ts, %s: gpio_direction_input failed %d\n", __func__, intr);
+		goto err_gpio_direction_failed;
+	}
+
+	ret = gpio_request(ts->pdata->gpio_reset, "gpio_tp_reset");
+	if (ret) {
+		dev_err(&client->dev, "k3ts, %s: gpio_request failed %d, ret = %d\n",
+			__func__, ts->pdata->gpio_reset, ret);
+		goto err_request_gpio_reset_failed;
+	}
+
+	gpio_direction_output(ts->pdata->gpio_reset, 1);
+	mdelay(5);
+	gpio_direction_output(ts->pdata->gpio_reset, 0);
+	mdelay(10);
+	gpio_direction_output(ts->pdata->gpio_reset, 1);
+	mdelay(50);
+
+	for (loop_i = 0; loop_i < 10; loop_i++) {
+		if (!gpio_get_value(intr))
+			break;
+		msleep(10);
+	}
+
+	if (loop_i == 10)
+		dev_err(&client->dev, "k3ts, %s: No Messages\n", __func__);
+
+	/* read message*/
+	msg[0].addr = ts->client->addr;
+	msg[0].flags = I2C_M_RD;
+	msg[0].len = 7;
+	msg[0].buf = data;
+	ret = i2c_transfer(client->adapter, msg, 1);
+
+	if (ret < 0) {
+		dev_err(&client->dev,  "k3ts, %s: No Atmel chip inside\n", __func__);
+		goto err_detect_failed;
+	}
+	if (ts->power)
+		ret = ts->power(2);
+
+	if (data[MSG_RID] == 0x01 &&
+		(data[T6_MSG_STATUS] & (T6_MSG_STATUS_SIGERR|T6_MSG_STATUS_COMSERR))) {
+		dev_err(&client->dev, "k3ts, %s: init err: %x\n", __func__, data[1]);
+		goto err_detect_failed;
+	} else {
+		for (loop_i = 0; loop_i < 10; loop_i++) {
+			if (gpio_get_value(intr)) {
+				dev_err(&client->dev, "k3ts, %s: No more message\n", __func__);
+				break;
+			}
+			ret = i2c_transfer(client->adapter, msg, 1);
+			msleep(10);
+		}
+	}
+
+	/* Read the info block data. */
+	ts->id = kzalloc(sizeof(struct info_id_t), GFP_KERNEL);
+	if (ts->id == NULL) {
+		dev_err(&client->dev, "k3ts, %s: allocate info_id_t failed\n", __func__);
+		goto err_alloc_failed;
+	}
+	ret = i2c_atmel_read(client, 0x00, data, 7);
+
+	ts->id->family_id = data[INFO_BLK_FID];
+	ts->id->variant_id = data[INFO_BLK_VID];
+	if (ts->id->family_id == 0x80 && ts->id->variant_id == 0x10)
+		ts->id->version = data[INFO_BLK_VER] + 6;
+	else
+		ts->id->version = data[INFO_BLK_VER];
+
+	ts->id->build = data[INFO_BLK_BUILD];
+	ts->id->matrix_x_size = data[INFO_BLK_XSIZE];
+	ts->id->matrix_y_size = data[INFO_BLK_YSIZE];
+	ts->id->num_declared_objects = data[INFO_BLK_OBJS];
+
+	/* Read object table. */
+	ret = read_object_table(ts);
+	if (ret < 0)
+		goto err_read_table_failed;
+
+
+	if (pdata) {
+		ts->finger_support = pdata->config_T9[T9_CFG_NUMTOUCH];
+
+		/* OBJECT CONFIG CRC check */
+		if (pdata->object_crc[0]) {
+			ret = i2c_atmel_write_byte_data(client,
+						get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+						T6_CFG_CALIBRATE, 0x55);
+			for (loop_i = 0; loop_i < 10; loop_i++) {
+				if (!gpio_get_value(intr)) {
+					ret = i2c_atmel_read(ts->client, get_object_address(ts,
+								GEN_MESSAGEPROCESSOR_T5), data, 5);
+					if (data[MSG_RID] == get_rid(ts, GEN_COMMANDPROCESSOR_T6))
+						break;
+				}
+				msleep(10);
+			}
+			if (loop_i == 10)
+				dev_err(&client->dev, "k3ts, %s: No checksum read\n", __func__);
+			else {
+				dev_info(&client->dev, "k3ts, %s:  CRC print : %x, %x, %x\n", __func__,
+							data[T6_MSG_CHECKSUM + 0], data[T6_MSG_CHECKSUM + 1], data[T6_MSG_CHECKSUM + 2]);
+				for (loop_i = 0; loop_i < 3; loop_i++) {
+					if (pdata->object_crc[loop_i] != data[T6_MSG_CHECKSUM + loop_i]) {
+						dev_err(&client->dev,
+							"k3ts, %s: CRC Error: %x, %x\n", __func__,
+							pdata->object_crc[loop_i],
+							data[T6_MSG_CHECKSUM + loop_i]);
+						break;
+					}
+				}
+				if (loop_i == 3) {
+					dev_info(&client->dev, "k3ts, %s: CRC passed: ", __func__);
+					for (loop_i = 0; loop_i < 3; loop_i++)
+						pr_info("0x%2.2X ", pdata->object_crc[loop_i]);
+					pr_info("\n");
+					CRC_check = 1;/*means CRC check OK*/
+				}
+			}
+		}
+		ts->abs_x_min = pdata->abs_x_min;
+		ts->abs_x_max = pdata->abs_x_max;
+		ts->abs_y_min = pdata->abs_y_min;
+		ts->abs_y_max = pdata->abs_y_max;
+		ts->abs_pressure_min = pdata->abs_pressure_min;
+		ts->abs_pressure_max = pdata->abs_pressure_max;
+		ts->abs_width_min = pdata->abs_width_min;
+		ts->abs_width_max = pdata->abs_width_max;
+
+		ts->GCAF_level = pdata->GCAF_level;
+		if (ts->id->version >= 0x10) {
+			ts->ATCH_EXT = &pdata->config_T8[6];
+			ts->timestamp = jiffies + 60 * HZ;
+		}
+		ts->ATCH_NOR = pdata->ATCH_NOR;
+		ts->ATCH_NOR_20S = pdata->ATCH_NOR_20S;
+		ts->filter_level = pdata->filter_level;
+
+		ts->config_setting[NONE].config_T7
+			= ts->config_setting[CONNECTED].config_T7
+			= pdata->config_T7;
+		ts->config_setting[NONE].config_T8 = pdata->config_T8;
+		ts->config_setting[CONNECTED].config_T8 = pdata->cable_config_T8;
+		ts->config_setting[NONE].config_T9 = pdata->config_T9;
+		ts->config_setting[NONE].config_T22 = pdata->config_T22;
+		ts->config_setting[NONE].config_T28 = pdata->config_T28;
+		ts->config_setting[NONE].config_T46 = pdata->config_T46;
+		ts->config_setting[NONE].config_T48 = pdata->config_T48;
+		ts->config_setting[CONNECTED].config_T46 = pdata->cable_config_T46;
+		ts->config_setting[CONNECTED].config_T48 = pdata->cable_config_T48;
+
+		if (pdata->noise_config[0])
+			for (loop_i = 0; loop_i < 3; loop_i++)
+				ts->noise_config[loop_i] = pdata->noise_config[loop_i];
+
+		if (pdata->cable_config[0]) {
+			ts->config_setting[NONE].config[CB_TCHTHR] =
+				pdata->config_T9[T9_CFG_TCHTHR];
+			ts->config_setting[NONE].config[CB_NOISETHR] =
+				pdata->config_T22[T22_CFG_NOISETHR];
+			ts->config_setting[NONE].config[CB_IDLEGCAFDEPTH] =
+				pdata->config_T28[T28_CFG_IDLEGCAFDEPTH];
+			ts->config_setting[NONE].config[CB_ACTVGCAFDEPTH] =
+				pdata->config_T28[T28_CFG_ACTVGCAFDEPTH];
+			for (loop_i = 0; loop_i < 4; loop_i++)
+				ts->config_setting[CONNECTED].config[loop_i] =
+					pdata->cable_config[loop_i];
+			ts->GCAF_sample =
+				ts->config_setting[CONNECTED].config[CB_ACTVGCAFDEPTH];
+			if (ts->id->version >= 0x20)
+				ts->noisethr = pdata->cable_config[CB_TCHTHR] -
+					pdata->config_T9[T9_CFG_TCHHYST];
+			else
+				ts->noisethr = pdata->cable_config[CB_TCHTHR];
+			ts->noisethr_config =
+				ts->config_setting[CONNECTED].config[CB_NOISETHR];
+		} else {
+			if (pdata->cable_config_T7[0])
+				ts->config_setting[CONNECTED].config_T7 =
+					pdata->cable_config_T7;
+			if (pdata->cable_config_T8[0])
+				ts->config_setting[CONNECTED].config_T8 =
+					pdata->cable_config_T8;
+			if (pdata->cable_config_T9[0]) {
+				ts->config_setting[CONNECTED].config_T9 =
+					pdata->cable_config_T9;
+				ts->config_setting[CONNECTED].config_T22 =
+					pdata->cable_config_T22;
+				ts->config_setting[CONNECTED].config_T28 =
+					pdata->cable_config_T28;
+				ts->GCAF_sample =
+					ts->config_setting[CONNECTED].config_T28[T28_CFG_ACTVGCAFDEPTH];
+			}
+			if (ts->status == CONNECTED)
+				ts->noisethr = (ts->id->version >= 0x20) ?
+					pdata->cable_config_T9[T9_CFG_TCHTHR] - pdata->cable_config_T9[T9_CFG_TCHHYST] :
+					pdata->cable_config_T9[T9_CFG_TCHTHR];
+			else
+				ts->noisethr = (ts->id->version >= 0x20) ?
+					pdata->config_T9[T9_CFG_TCHTHR] - pdata->config_T9[T9_CFG_TCHHYST] :
+					pdata->config_T9[T9_CFG_TCHTHR];
+			ts->noisethr_config = pdata->cable_config_T22[T22_CFG_NOISETHR];
+
+		}
+
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, GEN_COMMANDPROCESSOR_T6),
+			pdata->config_T6,
+			get_object_size(ts, GEN_COMMANDPROCESSOR_T6));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, GEN_POWERCONFIG_T7),
+			pdata->config_T7,
+			get_object_size(ts, GEN_POWERCONFIG_T7));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, GEN_ACQUISITIONCONFIG_T8),
+			pdata->config_T8,
+			get_object_size(ts, GEN_ACQUISITIONCONFIG_T8));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, TOUCH_MULTITOUCHSCREEN_T9),
+			pdata->config_T9,
+			get_object_size(ts, TOUCH_MULTITOUCHSCREEN_T9));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, TOUCH_KEYARRAY_T15),
+			pdata->config_T15,
+			get_object_size(ts, TOUCH_KEYARRAY_T15));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, SPT_GPIOPWM_T19),
+			pdata->config_T19,
+			get_object_size(ts, SPT_GPIOPWM_T19));
+
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, PROCI_GRIPSUPPRESSION_T40),
+			pdata->config_T40,
+			get_object_size(ts, PROCI_GRIPSUPPRESSION_T40));
+
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, PROCI_TOUCHSUPPRESSION_T42),
+			pdata->config_T42,
+			get_object_size(ts, PROCI_TOUCHSUPPRESSION_T42));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, PROCG_NOISESUPPRESSION_T48),
+			pdata->config_T48,
+			get_object_size(ts, PROCG_NOISESUPPRESSION_T48));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, TOUCH_PROXIMITY_T23),
+			pdata->config_T23,
+			get_object_size(ts, TOUCH_PROXIMITY_T23));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, SPT_SELFTEST_T25),
+			pdata->config_T25,
+			get_object_size(ts, SPT_SELFTEST_T25));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, SPT_CTECONFIG_T46),
+			pdata->config_T46,
+			get_object_size(ts, SPT_CTECONFIG_T46));
+		i2c_atmel_write(ts->client,
+			get_object_address(ts, PROCI_STYLUS_T47),
+			pdata->config_T47,
+			get_object_size(ts, PROCI_STYLUS_T47));
+
+		ret = i2c_atmel_write_byte_data(client,
+					get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+					T6_CFG_BACKUPNV, 0x55);
+
+		for (loop_i = 0; loop_i < 10; loop_i++) {
+			if (!gpio_get_value(intr))
+				break;
+			dev_err(&client->dev,  "k3ts, %s: wait for Message(%d)\n", __func__, loop_i + 1);
+			msleep(10);
+		}
+
+		i2c_atmel_read(client,
+			get_object_address(ts, GEN_MESSAGEPROCESSOR_T5), data, 7);
+
+		ret = i2c_atmel_write_byte_data(client,
+					get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+					T6_CFG_RESET, 0x11);/*reset*/
+		msleep(100);
+
+		if (ts->status == CONNECTED) {
+			if (ts->config_setting[CONNECTED].config_T8 != NULL)
+				i2c_atmel_write(ts->client,
+					get_object_address(ts, GEN_ACQUISITIONCONFIG_T8),
+					ts->config_setting[CONNECTED].config_T8,
+					get_object_size(ts, GEN_ACQUISITIONCONFIG_T8));
+			if (ts->config_setting[CONNECTED].config_T46 != NULL)
+		                i2c_atmel_write(ts->client,
+					get_object_address(ts, SPT_CTECONFIG_T46),
+					ts->config_setting[CONNECTED].config_T46,
+					get_object_size(ts, SPT_CTECONFIG_T46));
+			if (ts->config_setting[CONNECTED].config_T48 != NULL) {
+				i2c_atmel_write(ts->client,
+					get_object_address(ts, PROCG_NOISESUPPRESSION_T48),
+					ts->config_setting[CONNECTED].config_T48,
+					get_object_size(ts, PROCG_NOISESUPPRESSION_T48));
+		}
+        }
+    }
+	ts->calibration_confirm = 0;
+	ts->input_dev = input_allocate_device();
+	if (ts->input_dev == NULL) {
+		ret = -ENOMEM;
+		dev_err(&client->dev, "k3ts, %s: Failed to allocate input device\n", __func__);
+		goto err_input_dev_alloc_failed;
+	}
+	/*Modified by z181527 for Debug Only*/
+	ts->input_dev->name = "synaptics"/*"atmel-touchscreen"*/;
+	set_bit(EV_SYN, ts->input_dev->evbit);
+	set_bit(EV_KEY, ts->input_dev->evbit);
+	set_bit(BTN_TOUCH, ts->input_dev->keybit);
+	set_bit(BTN_2, ts->input_dev->keybit);
+	set_bit(EV_ABS, ts->input_dev->evbit);
+	set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
+	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
+		ts->abs_x_min, ts->abs_x_max, 0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
+		ts->abs_y_min, ts->abs_y_max, 0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+		ts->abs_pressure_min, ts->abs_pressure_max,
+		0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+		ts->abs_width_min, ts->abs_width_max, 0, 0);
+
+	ret = input_register_device(ts->input_dev);
+	if (ret) {
+		dev_err(&client->dev,
+			"k3ts, %s: atmel_ts_probe: Unable to register %s input device\n", __func__,
+			ts->input_dev->name);
+		goto err_input_register_device_failed;
+	}
+
+	ret = request_threaded_irq(client->irq, NULL, atmel_interrupt_fun,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+			client->name, ts);
+	if (ret)
+		dev_err(&client->dev, "k3ts, %s: request_irq failed\n", __func__);
+
+	private_ts = ts;
+
+	dev_info(&client->dev, "k3ts, %s: probe %s successfully\n", __func__,
+			ts->input_dev->name);
+
+	return 0;
+
+err_input_register_device_failed:
+	input_free_device(ts->input_dev);
+err_input_dev_alloc_failed:
+err_read_table_failed:
+	kfree(ts->id);
+err_alloc_failed:
+err_detect_failed:
+err_gpio_direction_failed:
+err_request_gpio_reset_failed:
+	gpio_free(ts->pdata->gpio_reset);
+	gpio_free(intr);
+err_request_gpio_failed:
+	destroy_workqueue(ts->atmel_wq);
+err_cread_wq_failed:
+	kfree(ts);
+err_alloc_data_failed:
+err_check_functionality_failed:
+	if (LDO != NULL) {
+		regulator_disable(LDO);
+		regulator_put(LDO);
+	}
+	return ret;
+}
+
+static int atmel_ts_remove(struct i2c_client *client)
+{
+	struct atmel_ts_data *ts = i2c_get_clientdata(client);
+
+	free_irq(client->irq, ts);
+
+	destroy_workqueue(ts->atmel_wq);
+	input_unregister_device(ts->input_dev);
+	kfree(ts);
+
+	regulator_disable(LDO);
+	regulator_put(LDO);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int atmel_ts_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct atmel_ts_data *ts = i2c_get_clientdata(client);
+	struct atmel_i2c_platform_data *pdata = ts->pdata;
+	uint8_t data[7];
+	int ret = 0;
+
+	mutex_lock(&ts->lock);
+	ts->finger_pressed = 0;
+	ts->finger_count = 0;
+	ts->first_pressed = 0;
+
+	if (ts->id->version >= 0x10) {
+		ts->pre_data[0] = 0;
+		ret = i2c_atmel_write(ts->client,
+				get_object_address(ts, GEN_ACQUISITIONCONFIG_T8) + T8_CFG_ATCHCALST,
+				ts->ATCH_EXT, 4);
+		if (ret < 0)
+			pr_err("k3ts, %s: failed to write config T8\n", __func__);
+	}
+
+	ret = i2c_atmel_write_byte_data(client,
+			get_object_address(ts, GEN_POWERCONFIG_T7) + T7_CFG_IDLEACQINT, 0x0);
+	if (ret < 0)
+		pr_err("k3ts, %s: failed to write config T7\n", __func__);
+
+	ret = i2c_atmel_write_byte_data(client,
+			get_object_address(ts, GEN_POWERCONFIG_T7) + T7_CFG_ACTVACQINT, 0x0);
+	if (ret < 0)
+		pr_err("k3ts, %s: failed to write config T7\n", __func__);
+
+	/* Read T5 until gpio_irq is HIGH level */
+	if (!gpio_get_value(pdata->gpio_irq)) {
+		ret = i2c_atmel_read(ts->client, get_object_address(ts,
+			GEN_MESSAGEPROCESSOR_T5), data, 7);
+		if (ret < 0) {
+			pr_err("k3ts, %s: failed to read T5\n", __func__);
+		}
+	}
+
+	mutex_unlock(&ts->lock);
+
+	pr_info("[%s]: -\n", __func__);
+	return 0;
+}
+
+static int atmel_ts_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct atmel_ts_data *ts = i2c_get_clientdata(client);
+	int ret = 0;
+
+	pr_info("[%s]: +\n", __func__);
+
+	mutex_lock(&ts->lock);
+	if (ts->id->version >= 0x10)
+		ts->timestamp = jiffies;
+
+	ts->unlock_flag = 0;
+
+	ret = i2c_atmel_write(ts->client,
+			get_object_address(ts, GEN_POWERCONFIG_T7),
+			ts->config_setting[ts->status].config_T7,
+			get_object_size(ts, GEN_POWERCONFIG_T7));
+	if (ret < 0)
+		pr_err("k3ts, %s: failed to write config T7\n", __func__);
+
+	ts->calibration_confirm = 0;
+	msleep(1);
+
+	ret = i2c_atmel_write(ts->client,
+			get_object_address(ts, GEN_ACQUISITIONCONFIG_T8) +
+			T8_CFG_TCHAUTOCAL, ts->ATCH_NOR, 6);
+	if (ret < 0)
+		pr_err("k3ts, %s: failed to write config T8\n", __func__);
+
+	ret = i2c_atmel_write_byte_data(client,
+			get_object_address(ts, GEN_COMMANDPROCESSOR_T6) +
+			T6_CFG_CALIBRATE, 0x55);
+	if (ret < 0)
+		pr_err("k3ts, %s: failed to write config T6\n", __func__);
+
+	mutex_unlock(&ts->lock);
+
+	pr_info("[%s]: -\n", __func__);
+
+	return 0;
+}
+#endif
+static SIMPLE_DEV_PM_OPS(atmel_ts_pm_ops, atmel_ts_suspend, atmel_ts_resume);
+
+static const struct i2c_device_id atml_ts_i2c_id[] = {
+	{ ATMEL_MXT224E_NAME, 0 },
+	{ }
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_ts_dt_ids[] = {
+	{ .compatible = "atmel,ts-mxt224e", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, atmel_ts_dt_ids);
+#endif
+
+static struct i2c_driver atmel_ts_driver = {
+	.id_table = atml_ts_i2c_id,
+	.probe = atmel_ts_probe,
+	.remove = atmel_ts_remove,
+	.driver = {
+		.of_match_table = of_match_ptr(atmel_ts_dt_ids),
+		.name = ATMEL_MXT224E_NAME,
+		.pm	= &atmel_ts_pm_ops,
+	},
+};
+module_i2c_driver(atmel_ts_driver);
+
+MODULE_DESCRIPTION("ATMEL Touch driver");
+MODULE_LICENSE("GPL");