diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 07e9e8202..cd57ff0a8 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -943,4 +943,14 @@ config TOUCHSCREEN_ZFORCE
 	  To compile this driver as a module, choose M here: the
 	  module will be called zforce_ts.
 
+config TOUCHSCREEN_AK4183
+	tristate "Yamaha CVP based touchscreens"
+	depends on I2C
+	help
+		Say Y her if you want support for Yamaha CVP
+		touchscreen controllers.
+
+		To compile this driver as a module, choose M here: the
+		module will be called ak4183.
+
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 62801f213..ffcd99373 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -77,3 +77,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE)	+= zylonite-wm97xx.o
 obj-$(CONFIG_TOUCHSCREEN_W90X900)	+= w90p910_ts.o
 obj-$(CONFIG_TOUCHSCREEN_TPS6507X)	+= tps6507x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_ZFORCE)	+= zforce_ts.o
+obj-$(CONFIG_TOUCHSCREEN_AK4183)	+= ymh_ak4183.o
diff --git a/drivers/input/touchscreen/ak4183.c b/drivers/input/touchscreen/ak4183.c
new file mode 100644
index 000000000..279594e1e
--- /dev/null
+++ b/drivers/input/touchscreen/ak4183.c
@@ -0,0 +1,1118 @@
+/* drivers/input/touchscreen/ak4183.c
+ *
+ * Copyright (c) 2016 ASAHI KASEI MICRODEVICES Corporation
+ *
+ *  Author                Date        Revistion
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *	Tsuyoshi Mutsuro	09/07/15	  1.0
+ *                      05/12/16      2.0 Kernel 3.18.XX
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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/slab.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/of_gpio.h>
+#include <linux/input/mt.h>
+
+  #if 0
+#define	ORG_AK4183			1		// used at original program
+#define	YMH_AK4183			0		// used at Yamaha program
+  #else
+#define	ORG_AK4183			0		// used at original program
+#define	YMH_AK4183			1		// used at Yamaha program
+  #endif
+
+  #if	YMH_AK4183
+// add. include files
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+  #endif
+
+#include "ymh_ak4183.h"
+
+//#define	AK4183_DEBUG   				//used at debug mode
+#define	EXCHG_XY_POS		1		// Xpos<--->Ypos
+
+#ifdef AK4183_DEBUG
+#define akdbgprt printk
+#define dbg_printk printk
+#define MSR_RESULT_PR_COUNT   10
+#else
+#define akdbgprt(format, arg...) do {} while (0)
+#define dbg_printk(format, arg...)
+#endif
+
+#define TS_POLL_PERIOD_MSEC  3    /* msec  delay between samples */
+#define TS_SCAN_PERIOD_MSEC  20   /* msec  delay between scan */
+
+#define AK4183_PRESURE_THD			4000	/* Threshold of pressure measurement result */
+
+#define AK4183_MEASURE_WAIT			100		/* Wait time[usec] from command to execution of measurement */
+#define AK4183_MEASURE_COUNT		6
+
+#define AK4183_COMMAND_PENIRQ_ON	0xC0
+#define AK4183_COMMAND_PENIRQ_OFF	0xC4
+#define AK4183_COMMAND_SLEEP		0x72
+#define AK4183_COMMAND_MEASURE_X	0xC4
+#define AK4183_COMMAND_MEASURE_Y	0xD4
+#define AK4183_COMMAND_MEASURE_Z1	0xE4
+#define AK4183_COMMAND_MEASURE_Z2	0xF4
+
+
+#define AK4183_OFFSET_X     0
+#define	AK4183_OFFSET_Y     0
+#define AK4183_GAIN_X	    1024
+#define	AK4183_GAIN_Y	    1024
+#define	AK4183_DISTANCE_X   500		/* This is not used */
+#define AK4183_DISTANCE_Y   500		/* This is not used */
+
+#define AK4183_OFFSET_MIN      0
+#define	AK4183_OFFSET_MAX   2000
+#define AK4183_GAIN_MIN        0
+#define	AK4183_GAIN_MAX	    2000
+#define	AK4183_DISTANCE_MIN   50	/* This is not used */
+#define AK4183_DISTANCE_MAX 2000	/* This is not used */
+#define FT_CYCLE	1
+#define RS_CYCLE	3
+
+struct ts_event {
+	u16 status;
+	u16 xc;
+	u16 yc;
+	u16 xd;		/* This is not used */
+	u16 yd;		/* This is not used */
+	u16 z;
+};
+
+struct cali_data {
+	u16 offset_x;
+	u16 offset_y;
+	u16 gain_x;
+	u16 gain_y;
+	u16 distance_x;		/* This is not used */
+	u16 distance_y;		/* This is not used */
+};
+
+struct ak4183 {
+	struct input_dev	*input;
+	char				phys[32];
+	struct ts_event		tc;
+	struct Gesture_data gd;
+	struct cali_data	caliData;
+	u8 					intervalData[AK4183_MEASURE_COUNT];
+
+	struct i2c_client	*client;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	struct early_suspend early_suspend;
+#endif
+
+	u16				model;
+	u16				x_plate_ohms;
+	u16				y_plate_ohms;
+	u16				x_min, x_max;
+	u16				y_min, y_max;
+	u16				pressure_min, pressure_max;
+
+	int				irq;
+	int				irq_gpio;
+	bool 			msron;
+	wait_queue_head_t	wait;
+
+	unsigned		is_suspended:1;
+
+    #if	YMH_AK4183
+	struct timer_list timer;
+	struct work_struct workq;
+    #endif
+};
+
+static struct ak4183 *gl_ts;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ak4183_early_suspend(struct early_suspend *h);
+static void ak4183_late_resume(struct early_suspend *h);
+#endif
+
+static int set_cali_para(const char *buf)
+{
+	struct ak4183 *ts = gl_ts;
+	char *ptr_data = (char *)buf;
+	char *p;
+	int pt_count = 0;
+	unsigned long val[7];
+
+	akdbgprt("[AK4183] %s(%d)\n",__FUNCTION__,__LINE__);
+
+	while ((p = strsep(&ptr_data, ","))) {
+		if (!*p)
+			break;
+
+		if (pt_count >= 7)
+			break;
+
+		val[pt_count] = simple_strtoul(p, NULL, 10);
+
+		pt_count++;
+	}
+
+	if (pt_count == 7) {
+		if (val[6] == 321) {
+			ts->caliData.offset_x = val[0];
+			ts->caliData.offset_y = val[1];
+			ts->caliData.gain_x = val[2];
+			ts->caliData.gain_y = val[3];
+			if ( ts->caliData.offset_x < AK4183_OFFSET_MIN )
+                  ts->caliData.offset_x = AK4183_OFFSET_MIN;
+			else if ( ts->caliData.offset_x > AK4183_OFFSET_MAX )
+                  ts->caliData.offset_x = AK4183_OFFSET_MAX;
+			if ( ts->caliData.offset_y < AK4183_OFFSET_MIN )
+                  ts->caliData.offset_y = AK4183_OFFSET_MIN;
+			else if ( ts->caliData.offset_y > AK4183_OFFSET_MAX )
+                  ts->caliData.offset_y = AK4183_OFFSET_MAX;
+			if ( ts->caliData.gain_x < AK4183_GAIN_MIN )
+                  ts->caliData.gain_x = AK4183_GAIN_MIN;
+			else if ( ts->caliData.gain_x > AK4183_GAIN_MAX )
+                  ts->caliData.gain_x = AK4183_GAIN_MAX;
+			if ( ts->caliData.gain_y < AK4183_GAIN_MIN )
+                  ts->caliData.gain_y = AK4183_GAIN_MIN;
+			else if ( ts->caliData.gain_y > AK4183_GAIN_MAX )
+                  ts->caliData.gain_y = AK4183_GAIN_MAX;
+			if ( ts->caliData.distance_x < AK4183_DISTANCE_MIN )
+                  ts->caliData.distance_x = AK4183_DISTANCE_MIN;
+			else if ( ts->caliData.distance_x > AK4183_DISTANCE_MAX )
+                  ts->caliData.distance_x = AK4183_DISTANCE_MAX;
+			if ( ts->caliData.distance_y < AK4183_DISTANCE_MIN )
+                  ts->caliData.distance_y = AK4183_DISTANCE_MIN;
+			else if ( ts->caliData.distance_y > AK4183_DISTANCE_MAX )
+                  ts->caliData.distance_y = AK4183_DISTANCE_MAX;
+
+		} else if (val[6] == 123) {
+			ts->caliData.offset_x = AK4183_OFFSET_X;
+			ts->caliData.offset_y = AK4183_OFFSET_Y;
+			ts->caliData.gain_x = AK4183_GAIN_X;
+			ts->caliData.gain_y = AK4183_GAIN_Y;
+			ts->caliData.distance_x = AK4183_DISTANCE_X;
+			ts->caliData.distance_y = AK4183_DISTANCE_Y;
+		}
+		return 0;
+	}
+	return -1;
+}
+
+static ssize_t cali_data_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct ak4183 *ts = gl_ts;
+
+	return sprintf(buf, "%d,%d,%d,%d\n", ts->tc.xc,
+			ts->tc.yc, ts->tc.xd, ts->tc.yd);
+}
+
+static ssize_t cali_data_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	return count;
+}
+
+static ssize_t cali_para_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct ak4183 *ts = gl_ts;
+
+	return sprintf(buf, "%d,%d,%d,%d,%d,%d,321\n",
+			ts->caliData.offset_x,   ts->caliData.offset_y,
+			ts->caliData.gain_x,     ts->caliData.gain_y,
+			ts->caliData.distance_x, ts->caliData.distance_y);
+}
+
+static ssize_t cali_para_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	set_cali_para(buf);
+
+	return count;
+}
+
+static struct device_attribute attrs[] = {
+	__ATTR(cali_data, S_IRUGO, cali_data_show, cali_data_store),
+	__ATTR(cali_para, (S_IRUGO | S_IWUSR | S_IWGRP),cali_para_show,	cali_para_store)
+};
+
+static int FltDataInit(struct ak4183 *ts)
+{
+
+	ts->gd.nCFCount1 = 0;
+	ts->gd.m_isFirstPoint = 0;
+
+	return(0);
+
+}
+
+static u16 MoveDistance(u16 xp1, u16 yp1, u16 xpref, u16 ypref)
+{
+	short	ndx, ndy;
+	u16		nSum;
+
+	if( xp1 == 0x7FFF ){
+		return (10000);
+	}
+
+	ndx = (short)xp1 - (short)xpref;
+	ndy = (short)yp1 - (short)ypref;
+	if( ndx < 0 ) ndx = -ndx;
+	if( ndy < 0 ) ndy = -ndy;
+
+	nSum = (u16)( ndx + ndy );
+
+	return (nSum);
+}
+
+static int FltSingleData(struct ak4183 *ts, u16 *nStatus, u16 *xp, u16 *yp, u16 *z21)
+{
+	u16	nStbThs;
+	u16	i, n, nMin;
+   	static u16 nXp1[SINGLE_FLT_DATA];
+	static u16 nYp1[SINGLE_FLT_DATA];
+	static u16 nZ1[SINGLE_FLT_DATA];
+
+	nStbThs = SINGLE_FLT_DATA - 1;
+
+	nXp1[ts->gd.nCFCount1] = *xp;
+	nYp1[ts->gd.nCFCount1] = *yp;
+	if ( ts->gd.nCFCount1 < nStbThs ) {
+		*nStatus |= 0x10;
+		ts->gd.fltdata_xp.nRefData = *xp;
+		ts->gd.fltdata_yp.nRefData = *yp;
+		if ( ts->gd.nCFCount1 == 0 ) nZ1[0] = 10000;
+		else nZ1[ts->gd.nCFCount1] = MoveDistance(nXp1[ts->gd.nCFCount1], nYp1[ts->gd.nCFCount1],
+                                    ts->gd.fltdata_xp.nRefData, ts->gd.fltdata_yp.nRefData);
+		ts->gd.nCFCount1++;
+
+		return(0);
+	}
+
+	nZ1[nStbThs] = MoveDistance(nXp1[nStbThs], nYp1[nStbThs],
+                            ts->gd.fltdata_xp.nRefData, ts->gd.fltdata_yp.nRefData);
+
+	n = i = nStbThs;
+	nMin = nZ1[i];
+
+	do {
+		i--;
+		if ( nZ1[i] < nMin ) {
+			nMin = nZ1[i];
+			n = i;
+		}
+	}while(i > 0);
+
+	if ( ts->gd.m_isFirstPoint ) {
+		ts->gd.fltdata_xp.nOutData = (nXp1[n] + ts->gd.fltdata_xp.nRefData) / 2;
+		ts->gd.fltdata_yp.nOutData = (nYp1[n] + ts->gd.fltdata_yp.nRefData) / 2;
+	}
+	else {
+		ts->gd.fltdata_xp.nOutData = nXp1[n];
+		ts->gd.fltdata_yp.nOutData = nYp1[n];
+		ts->gd.m_isFirstPoint = 1;
+	}
+	*xp = ts->gd.fltdata_xp.nOutData;
+	*yp = ts->gd.fltdata_yp.nOutData;
+	ts->gd.fltdata_xp.nRefData = ts->gd.fltdata_xp.nOutData;
+	ts->gd.fltdata_yp.nRefData = ts->gd.fltdata_yp.nOutData;
+
+	for ( i = 0 ; i < nStbThs ; i++ ) {
+		if ( i < ( n - 1 ) ) nXp1[i] = 0x7FFF;
+		else  nXp1[i] = nXp1[i+1];
+		nYp1[i] = nYp1[i+1];
+		nZ1[i] = nZ1[i+1];
+	}
+
+	return(0);
+
+}
+
+static int UpdateData(struct ak4183 *ts, u16 *status, u16 *xp, u16 *yp, u16 *z21)
+{
+	int  nTouchNum, nRet;
+
+	if ( *status == 0x02) {		// one touch
+		nRet = FltSingleData( ts, status, xp, yp, z21);
+		if( nRet ) return (nRet);
+		nTouchNum = 1;
+		ts->gd.RS_Count = 0;
+	}else{
+		nTouchNum = 0;
+	}
+
+	return(nTouchNum);
+
+}
+
+static int GetPostion(struct ak4183 *ts, u16 *x1, u16 *y1)
+{
+#if	ORG_AK4183
+	u16 xp1, yp1;
+	u32 xp2, yp2;
+
+	xp1 = ts->tc.xc;
+	yp1 = ts->tc.yc;
+
+	if ( xp1 >= ts->caliData.offset_x  && ts->caliData.gain_x > 0 )
+		xp2 = (u32)(xp1 - ts->caliData.offset_x) * (u32)ts->x_max / (u32)( 4 * ts->caliData.gain_x );
+	else xp2 = 0;
+	if ( yp1 >= ts->caliData.offset_y && ts->caliData.gain_y > 0 )
+		yp2 = (u32)(yp1 - ts->caliData.offset_y) * (u32)ts->y_max / (u32)( 4 * ts->caliData.gain_y );
+	else yp2 = 0;
+
+	*x1 = (u16)xp2;
+	*y1 = (u16)yp2;
+
+#else
+  #if	EXCHG_XY_POS
+	*x1 = ts->tc.yc;
+	*y1 = ts->tc.xc;
+  #else
+	*x1 = ts->tc.xc;
+	*y1 = ts->tc.yc;
+  #endif
+#endif
+
+	return(0);
+
+}
+
+static void ak4183_send_event(void *tsc)
+{
+	struct ak4183	*ts = tsc;
+	struct input_dev *input = ts->input;
+	u16 x1, y1;
+	u16 nTouchNum;
+#ifdef AK4183_DEBUG
+	static int count = 0;
+#endif
+
+	nTouchNum = UpdateData(ts, &(ts->tc.status), &(ts->tc.xc), &(ts->tc.yc), &(ts->tc.z));
+
+	if ( nTouchNum > 0 ) {
+		GetPostion(ts, &x1, &y1);
+		if (x1 > 60000) x1 = 0;
+		if (x1 > ts->x_max) x1 = ts->x_max;
+		if (y1 > 60000) y1 = 0;
+		if (y1 > ts->y_max) y1 = ts->y_max;
+	}
+
+	if ( nTouchNum == 1 ){
+
+#if	ORG_AK4183
+		input_mt_slot(input, 0);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, 1);
+
+		input_report_abs(input, ABS_MT_TOUCH_MAJOR, ((ts->tc.z/10) + 1));
+		input_report_abs(input, ABS_MT_POSITION_X, x1);
+		input_report_abs(input, ABS_MT_POSITION_Y, y1);
+		input_report_abs(input, ABS_PRESSURE, ts->tc.z);
+		input_report_key(input, BTN_TOUCH, 1);
+		input_report_key(input, BTN_TOOL_FINGER, 1);
+#else
+  #if	EXCHG_XY_POS
+		// exchange x<--->y
+		input_report_abs(input, ABS_X, ts->tc.yc);
+		input_report_abs(input, ABS_Y, ts->tc.xc);
+  #else
+		input_report_abs(input, ABS_X, ts->tc.xc);
+		input_report_abs(input, ABS_Y, ts->tc.yc);
+  #endif
+		input_report_abs(input, ABS_PRESSURE, ts->tc.z);
+		input_report_key(input, BTN_TOUCH, 1);
+#endif
+
+#if	ORG_AK4183
+		input_mt_slot(ts->input, 1);
+		input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, 0);
+#endif
+		input_sync(input);
+/*
+		dev_dbg(&ts->client->dev, "One touch: pt1(%4d,%4d), pressure (%4u)\n",
+						x1, y1, ts->tc.z);
+*/
+#ifdef AK4183_DEBUG
+		count++;
+		if ( count == MSR_RESULT_PR_COUNT ) {
+//			akdbgprt("One touch: pt1(%4d,%4d), pressure (%4u)\n", x1, y1, ts->tc.z);
+//			akdbgprt("One touch: pt1(%4d,%4d), pressure (%4u)\n", ts->tc.xc, ts->tc.yc, ts->tc.z);
+			count = 0;
+		}
+#endif
+	}
+
+}
+
+static int ak4183_command(struct ak4183 *tsc, u8 cmd)
+{
+	s32	rt;
+	u8	tx[1];
+
+	tx[0] = cmd;
+
+	rt = i2c_master_send(tsc->client, tx, 1);
+	return (rt);
+}
+
+static int ak4183_measure(struct ak4183 *tsc, int cmd, int count)
+{
+	struct	i2c_msg	xfer[1];
+	int		ret, datalen, i, rdata, min, max, sum, msrdat;
+	u8		data[32];
+	datalen = 2; // read length ( once )
+	if( count > 16 ){
+		return (-EIO);
+	}
+
+	ak4183_command( tsc, cmd );
+
+	udelay(AK4183_MEASURE_WAIT);
+
+	sum = 0;
+	min = 4095;
+	max = 0;
+	// 2 pair of recieved data makes one measurement data.
+	// Where first data has [D11-D4] , second data has [D3-D0 <<4 | Duumy 4bits '0' ].
+	for( i = 0 ; i < count ; i ++ ){
+		xfer[0].addr = tsc->client->addr;
+		xfer[0].flags = I2C_M_RD;
+		xfer[0].len = datalen;
+		xfer[0].buf = &data[i*2];
+		ret = i2c_transfer(tsc->client->adapter, xfer, 1);
+		rdata = ((int)data[2*i] << 4 ) + ((int)data[2*i+1] >> 4);
+		if( rdata < min ) min = rdata;
+		if( rdata > max ) max = rdata;
+		sum += rdata;
+	}
+
+	if( count > 2 ){// throw away Max and Min.
+		sum -= min;
+		sum -= max;
+		msrdat = sum / ( count - 2 );
+	}else{
+		msrdat = sum / count;
+	}
+	return (msrdat);
+}
+
+static int ak4183_read_values(struct ak4183 *tsc)
+{
+	int		rt;
+	long	z1, z2, z21;
+	tsc->tc.status = 2;
+	tsc->tc.xc = ak4183_measure( tsc, AK4183_COMMAND_MEASURE_X, AK4183_MEASURE_COUNT );
+	tsc->tc.yc = ak4183_measure( tsc, AK4183_COMMAND_MEASURE_Y, AK4183_MEASURE_COUNT );
+	z1 = (long)ak4183_measure( tsc, AK4183_COMMAND_MEASURE_Z1, AK4183_MEASURE_COUNT );
+	z2 = (long)ak4183_measure( tsc, AK4183_COMMAND_MEASURE_Z2, AK4183_MEASURE_COUNT );
+	if( ( z1 > 5 ) && ( z2 < 4090 ) ){
+		z21 = (long)tsc->tc.xc * ( z2 - z1 ) / z1;
+	}else{
+		z21 = AK4183_PRESURE_THD + 1;
+	}
+
+	tsc->tc.z = (u16)z21;
+
+  #if	ORG_AK4183
+	rt = ak4183_command(tsc, AK4183_COMMAND_PENIRQ_ON);
+  #else
+	rt = ak4183_command(tsc, AK4183_COMMAND_PENIRQ_OFF);
+  #endif
+
+	if( ( rt < 0 ) || ( z21 > AK4183_PRESURE_THD ) ){
+		tsc->tc.status = 0x12;
+	}else{
+		tsc->tc.status = 0x02;
+	}
+
+	return (0);
+
+}
+
+static int get_pendown_state(
+struct ak4183 *ts)
+{
+  #if	ORG_AK4183
+	return(!gpio_get_value(ts->irq_gpio));
+
+  #else
+	// get z21, z21 < threshold then pen down else pun up judgement
+	long	z1, z2, z21;
+	z1 = (long)ak4183_measure( ts, AK4183_COMMAND_MEASURE_Z1, 3 );
+	z2 = (long)ak4183_measure( ts, AK4183_COMMAND_MEASURE_Z2, 3 );
+	if( ( z1 > 5 ) && ( z2 < 4090 ) ){
+		z21 = 1;
+	}else{
+		z21 = 0;
+	}
+	return z21;
+  #endif
+}
+
+
+static void ak4183_msr_func(struct ak4183 *ts)
+{
+
+	if (unlikely(!get_pendown_state(ts))) {
+		if (ts->gd.RS_Count < RS_CYCLE) {
+			ts->gd.RS_Count++;
+		} else {
+	//		printk("\t[AK4183] %s call input_sync \n", __FUNCTION__);
+			ts->gd.RS_Count = 0;
+
+			FltDataInit(ts);
+
+			enable_irq(ts->irq);
+#if	ORG_AK4183
+			input_mt_slot(ts->input, 0);
+			input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, 0);
+			input_mt_slot(ts->input, 1);
+			input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, 0);
+#endif
+			input_report_abs(ts->input, ABS_PRESSURE, 0);
+			input_report_key(ts->input, BTN_TOUCH, 0);
+#if	ORG_AK4183
+			input_report_key(ts->input, BTN_TOOL_FINGER, 0);
+#endif
+			input_sync(ts->input);
+
+			ts->msron = false;
+		}
+	} else {
+		/* pen is still down, continue with the measurement */
+		dev_dbg(&ts->client->dev, "pen is still down\n");
+		ts->gd.RS_Count = 0;
+
+		ak4183_read_values(ts);
+		if ((ts->tc.status & 2) == 2) {
+			ak4183_send_event(ts);
+		}
+	}
+}
+
+
+static int ak4183_device_init(struct ak4183 *tsc)
+{
+	s32 rt;
+
+#if	ORG_AK4183
+	rt = ak4183_command(tsc, AK4183_COMMAND_PENIRQ_ON);
+	rt = ak4183_command(tsc, AK4183_COMMAND_PENIRQ_ON);
+#else
+	rt = ak4183_command(tsc, AK4183_COMMAND_PENIRQ_OFF);
+	rt = ak4183_command(tsc, AK4183_COMMAND_PENIRQ_OFF);
+#endif
+
+	return rt;
+}
+
+#if	ORG_AK4183
+static irqreturn_t ak4183_hard_irq(int irq, void *handle)
+{
+	struct ak4183 *ts = handle;
+	int pendown;
+
+	if ( ts->msron == false  ) {
+		pendown = get_pendown_state(ts);
+		if ( pendown  ) {
+			akdbgprt("[AK4183] %s IRQ_WAKE_THREAD\n",__FUNCTION__);
+			ts->msron = true;
+			return IRQ_WAKE_THREAD;
+		}
+	}
+
+	return(IRQ_HANDLED);
+
+}
+#endif
+
+#if	ORG_AK4183
+static irqreturn_t ak4183_irq(int irq, void *handle)
+{
+	struct ak4183 *ts = handle;
+
+	akdbgprt("[AK4183] %s(%d)\n",__FUNCTION__,__LINE__);
+
+	while ( ts->msron == true ) {
+		ak4183_msr_func(ts);
+		wait_event_timeout(ts->wait, !ts->msron,
+				   msecs_to_jiffies(TS_POLL_PERIOD_MSEC));
+	}
+
+	return IRQ_HANDLED;
+}
+#endif
+
+#if	YMH_AK4183
+static irqreturn_t ak4183_hard_irq_workq(struct ak4183 *ts)
+{
+	int pendown;
+
+	if ( ts->msron == false  ) {
+		pendown = get_pendown_state(ts);
+		if ( pendown  ) {
+			ts->msron = true;
+			return IRQ_WAKE_THREAD;
+		}
+	}
+	return(IRQ_HANDLED);
+}
+#endif
+
+#if	YMH_AK4183
+static irqreturn_t ak4183_irq_workq(struct ak4183 *ts)
+{
+	while ( ts->msron == true ) {
+		ak4183_msr_func(ts);
+		wait_event_timeout(ts->wait, !ts->msron,
+				   msecs_to_jiffies(TS_POLL_PERIOD_MSEC));
+	}
+	return IRQ_HANDLED;
+}
+#endif
+
+#if	YMH_AK4183
+// work queue job
+static void ak4183_workq(struct work_struct *work)
+{
+	struct	ak4183 *ts;
+
+	ts = container_of(work, struct ak4183, workq);
+	if( ak4183_hard_irq_workq(ts) == IRQ_WAKE_THREAD ){
+		ak4183_irq_workq(ts);
+	}
+}
+#endif
+
+#if	YMH_AK4183
+// from timer object, call work queue
+static void ak4183_poll_job(unsigned long arg)
+{
+	struct ak4183 *ts = (struct ak4183 *)arg;
+	schedule_work(&ts->workq);
+	mod_timer(&ts->timer, jiffies + msecs_to_jiffies(TS_SCAN_PERIOD_MSEC));
+}
+#endif
+
+static int ak4183_ts_open(struct input_dev *dev)
+{
+	akdbgprt("\t[AK4183] %s\n", __FUNCTION__);
+
+	return 0;
+}
+
+static void ak4183_ts_close(struct input_dev *dev)
+{
+	akdbgprt("[AK4183] %s(%d)\n",__FUNCTION__,__LINE__);
+
+	disable_irq(gl_ts->irq);
+
+#if	ORG_AK4183
+	input_mt_slot(gl_ts->input, 0);
+	input_mt_report_slot_state(gl_ts->input, MT_TOOL_FINGER, 0);
+#endif
+	input_sync(gl_ts->input);
+
+
+}
+
+static int ak4183_parse_dt(struct ak4183 *ts)
+{
+	u32 buf[4];
+	struct device *dev;
+	struct device_node *np;
+	int ret;
+
+	dev = &(ts->client->dev);
+	np = dev->of_node;
+
+	if (!np) return -EINVAL;
+
+	ret = of_property_read_u32(np, "ak4183,model", buf);
+	if (ret && (ret != -EINVAL)) {
+		dev_err(dev, "Unable to read ak4183,models\n");
+		dbg_printk("Unable to read ak4183,models\n");
+		ts->model = 4183;
+	}
+	else {
+		ts->model = (u16)buf[0];
+	}
+
+	ret = of_property_read_u32_array(np, "ak4183,coords", buf, 4);
+	if (ret && (ret != -EINVAL)) {
+		dev_err(dev, "Unable to read ak4183,coords\n");
+		dbg_printk("Unable to read ak4183,coords\n");
+		ts->x_min			= 0;
+		ts->y_min			= 0;
+#if	ORG_AK4183
+		ts->x_max			= 800;
+		ts->y_max			= 480;
+#else
+		ts->x_max			= 4096;
+		ts->y_max			= 4096;
+#endif
+	}
+	else {
+		ts->x_min			= (u16)buf[0];
+		ts->y_min			= (u16)buf[1];
+		ts->x_max			= (u16)buf[2];
+		ts->y_max			= (u16)buf[3];
+	}
+
+	akdbgprt("[AK4183] %s coords =(%d,%d)-(%d,%d)\n",__FUNCTION__,
+				(int)ts->x_min, (int)ts->x_max, (int)ts->y_min, (int)ts->y_max);
+
+	ret = of_property_read_u32_array(np, "ak4183,plate_ohms", buf, 2);
+	if (ret && (ret != -EINVAL)) {
+		dev_err(dev, "Unable to read ak4183,plate_ohms\n");
+		dbg_printk("Unable to read ak4183,plate_ohms\n");
+		ts->x_plate_ohms	= 300;
+		ts->y_plate_ohms	= 300;
+	}
+	else {
+		ts->x_plate_ohms	= (u16)buf[0];
+		ts->y_plate_ohms	= (u16)buf[1];
+	}
+
+	ret = of_property_read_u32_array(np, "ak4183,pressure", buf, 2);
+	if (ret && (ret != -EINVAL)) {
+		dev_err(dev, "Unable to read ak4183,pressure\n");
+		dbg_printk("Unable to read ak4183,pressure\n");
+		ts->pressure_min	= 0;
+		ts->pressure_max	= 255;
+	}
+	else {
+		ts->pressure_min	= (u16)buf[0];
+		ts->pressure_max	= (u16)buf[1];
+	}
+
+#if	ORG_AK4183
+	ts->irq_gpio = of_get_named_gpio(np, "ak4183,irq-gpio", 0);
+	if (ts->irq_gpio < 0) {
+		printk(KERN_ERR "ak4183 irq-gpio(%u) is invalid\n", ts->irq_gpio);
+		ts->irq_gpio = -1;
+		return -EINVAL;
+	}
+
+	ret = -1;
+	if (gpio_is_valid(ts->irq_gpio)) {
+		ret = gpio_request(ts->irq_gpio, "ak4183_gpio_irq");
+		if (ret >= 0 ) {
+			ret = gpio_direction_input(ts->irq_gpio);
+		}
+	}
+	if ( ret < 0 ) {
+		printk(KERN_ERR "ak4183 irq-gpio invalid!\n");
+		akdbgprt("[AK4183] %s ak4183 irq-gpio invalid\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	akdbgprt("[AK4183] %s ak4183 irq-gpio success\n", __FUNCTION__);
+#endif
+
+	return 0;
+}
+
+
+
+static int ak4183_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct ak4183 *ts;
+	struct input_dev *input_dev;
+	int n, num_attr;
+	int err;
+
+	akdbgprt("\t[AK4183] %s\n", __FUNCTION__);
+
+	if (!i2c_check_functionality(client->adapter,
+					I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
+					I2C_FUNC_SMBUS_READ_WORD_DATA  |
+					I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+		return -EIO;
+
+	ts = kzalloc(sizeof(struct ak4183), GFP_KERNEL);
+
+	ts->client = client;
+	i2c_set_clientdata(client, ts);
+
+	gl_ts = ts;
+	ts->irq = -1;
+	ts->msron = 0;
+	init_waitqueue_head(&ts->wait);
+
+	err = ak4183_parse_dt(ts);
+	if (err) {
+		dev_err(&client->dev, "Error : Get dts data = %d \n", err);
+		dbg_printk("Error : Get dts data = %d \n", err);
+		goto err_power_failed;
+	}
+	ts->caliData.offset_x = AK4183_OFFSET_X;
+	ts->caliData.offset_y = AK4183_OFFSET_Y;
+	ts->caliData.gain_x	  = AK4183_GAIN_X;
+	ts->caliData.gain_y   = AK4183_GAIN_Y;
+	ts->caliData.distance_x = AK4183_DISTANCE_X;
+	ts->caliData.distance_y = AK4183_DISTANCE_Y;
+
+
+	err = ak4183_device_init(ts);
+
+	if (err < 0 ) {
+		dev_err(&client->dev, "Initialize error = %d \n", err);
+		dbg_printk("Initialize error = %d \n", err);
+		return err;
+	}
+
+	input_dev = input_allocate_device();
+	if (!ts || !input_dev) {
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+	ts->input = input_dev;
+
+#if	ORG_AK4183
+	set_bit(EV_SYN,		ts->input->evbit);
+#endif
+	set_bit(EV_KEY,		ts->input->evbit);
+	set_bit(EV_ABS,		ts->input->evbit);
+	set_bit(BTN_TOUCH,	ts->input->keybit);
+#if	ORG_AK4183
+	set_bit(BTN_TOOL_FINGER, ts->input->keybit);
+#endif
+#ifdef INPUT_PROP_DIRECT
+	set_bit(INPUT_PROP_DIRECT, ts->input->propbit);
+#endif
+
+	snprintf(ts->phys, sizeof(ts->phys),
+		 "%s/input0", dev_name(&client->dev));
+
+	input_dev->name = "ak4183-TouchScreen";
+
+	input_dev->phys = ts->phys;
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &client->dev;
+
+	ts->input->open = ak4183_ts_open;
+	ts->input->close = ak4183_ts_close;
+
+
+#if	YMH_AK4183
+	INIT_WORK(&ts->workq, ak4183_workq);
+
+	init_timer(&ts->timer);
+	setup_timer(&ts->timer, ak4183_poll_job, (unsigned long) ts);
+	ts->timer.expires = jiffies + msecs_to_jiffies(TS_SCAN_PERIOD_MSEC);
+	add_timer(&ts->timer);
+#endif
+
+#if	ORG_AK4183
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X, ts->x_min, ts->x_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, ts->y_min, ts->y_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE,ts->pressure_min, ts->pressure_max,  0, 0);
+
+	input_mt_init_slots(input_dev, 2, 0);
+#else
+	input_set_abs_params(input_dev, ABS_X, 0, 4095, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, 4095, 0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 0, 0);
+#endif
+
+	input_set_drvdata(input_dev, ts);
+
+	err = input_register_device(input_dev);
+	if (err)
+		goto err_free_mem;
+
+	num_attr = ARRAY_SIZE(attrs);
+	for ( n = 0; n < num_attr ; n++) {
+		err = sysfs_create_file(&input_dev->dev.kobj, &attrs[n].attr);
+		if (err < 0) {
+			dev_err(&client->dev, "%s: Failed to create sysfs attributes\n",__func__);
+			dbg_printk("%s: Failed to create sysfs attributes\n",__func__);
+			goto err_sysfs;
+		}
+	}
+
+#if	ORG_AK4183
+	ts->irq = gpio_to_irq(ts->irq_gpio);
+	err = request_threaded_irq(ts->irq, ak4183_hard_irq, ak4183_irq,
+                         IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, ts);
+
+	if (err < 0) {
+		dev_err(&client->dev, "irq %d busy?\n", ts->irq);
+		dbg_printk("irq %d busy?\n", ts->irq);
+		goto err_free_irq;
+	}
+#endif
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	ts->early_suspend.suspend = ak4183_early_suspend;
+	ts->early_suspend.resume = ak4183_late_resume;
+	register_early_suspend(&ts->early_suspend);
+#endif
+
+	akdbgprt("\t[AK4183] %s  OK\n", __FUNCTION__);
+
+	return 0;
+
+err_free_irq:
+	free_irq(ts->irq, ts);
+
+err_sysfs:
+	for (n--; n >= 0; n--) {
+		sysfs_remove_file(&input_dev->dev.kobj, &attrs[n].attr);
+	}
+err_free_mem:
+	input_free_device(input_dev);
+err_power_failed:
+	kfree(ts);
+
+	return err;
+}
+
+static int ak4183_remove(struct i2c_client *client)
+{
+	struct ak4183	*ts = i2c_get_clientdata(client);
+	int  n;
+
+	for ( n = 0; n < ARRAY_SIZE(attrs); n++) {
+		sysfs_remove_file(&ts->input->dev.kobj,	&attrs[n].attr);
+	}
+
+	free_irq(ts->irq, ts);
+	input_unregister_device(ts->input);
+	kfree(ts);
+
+	return 0;
+}
+
+static int ak4183_suspend(struct device *dev)
+{
+	struct ak4183	*ts = dev_get_drvdata(dev);
+	int 			err;
+
+	ts->is_suspended = 1;
+
+	ts->msron = 0;
+	wake_up(&ts->wait);
+	disable_irq(ts->irq);
+
+	err = ak4183_command( ts, AK4183_COMMAND_SLEEP );
+	if (err) {
+		dev_err(dev, "Suspend error = %d \n", err);
+		dbg_printk("Suspend error = %d \n", err);
+	}
+	dev_info(dev, "ak4183_suspend\n");
+
+	return 0;
+}
+
+static int ak4183_resume(struct device *dev)
+{
+	struct ak4183	*ts = dev_get_drvdata(dev);
+	int 			err;
+
+	disable_irq(ts->irq);
+	err = ak4183_device_init(ts);
+	if (err) {
+		dev_err(dev, "Initialize error = %d \n", err);
+		dbg_printk("Initialize error = %d \n", err);
+		return err;
+	}
+	enable_irq(ts->irq);
+
+	ts->is_suspended = 0;
+	dev_info(dev, "ak4183_resume\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ak4183_early_suspend(struct early_suspend *h)
+{
+	struct ak4183 *ts;
+	ts = container_of(h, struct ak4183, early_suspend);
+	ak4183_suspend(ts->client, PMSG_SUSPEND);
+}
+
+static void ak4183_late_resume(struct early_suspend *h)
+{
+	struct ak4183 *ts;
+	ts = container_of(h, struct ak4183, early_suspend);
+	ak4183_resume(ts->client);
+}
+#endif
+
+static struct of_device_id ak4183_i2c_dt_ids[] = {
+    { .compatible = "akm,ak4183"},
+    { }
+};
+
+static struct i2c_device_id ak4183_idtable[] = {
+	{ AK4183_NAME, 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, ak4183_idtable);
+
+static SIMPLE_DEV_PM_OPS(ak4183_pm_ops,
+			 ak4183_suspend, ak4183_resume);
+
+static struct i2c_driver ak4183_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= AK4183_NAME,
+		.of_match_table = ak4183_i2c_dt_ids,
+		.pm	= &ak4183_pm_ops,
+	},
+	.id_table	= ak4183_idtable,
+	.probe		= ak4183_probe,
+	.remove		= ak4183_remove,
+};
+
+static int __init ak4183_init(void)
+{
+	akdbgprt("[AK4183] %s(%d)\n",__FUNCTION__,__LINE__);
+
+	return i2c_add_driver(&ak4183_driver);
+}
+
+static void __exit ak4183_exit(void)
+{
+
+	i2c_del_driver(&ak4183_driver);
+
+}
+
+module_init(ak4183_init);
+module_exit(ak4183_exit);
+
+MODULE_AUTHOR("Junichi Wakasugi <wakasugi.jb@om.asahi-kasei.co.jp>");
+MODULE_DESCRIPTION("AK4183 TouchScreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/ak4183.h b/drivers/input/touchscreen/ak4183.h
new file mode 100644
index 000000000..4ad3fe7ce
--- /dev/null
+++ b/drivers/input/touchscreen/ak4183.h
@@ -0,0 +1,29 @@
+#ifndef __LINUX_I2C_AK4183_H
+#define __LINUX_I2C_AK4183_H
+
+/* ak4183.h */
+
+#define AK4183_NAME "ak4183"
+
+#define SINGLE_FLT_DATA	3
+
+typedef struct {
+	u16	nRefData;
+	u16	nOutData;
+} DUALFLTDATA;
+
+struct Gesture_data {
+
+    u16 m_isFirstPoint;
+
+    u16 MTCount, RS_Count;
+
+// Coordinates Filter
+    u16 nCFCount1;;
+
+	// for Dual Touch Data Filter ( These are not used  )
+    DUALFLTDATA fltdata_xp, fltdata_yp, fltdata_xd, fltdata_yd;	
+
+};
+
+#endif
diff --git a/drivers/input/touchscreen/ymh_ak4183.c b/drivers/input/touchscreen/ymh_ak4183.c
new file mode 100644
index 000000000..ede8e1071
--- /dev/null
+++ b/drivers/input/touchscreen/ymh_ak4183.c
@@ -0,0 +1,923 @@
+/* drivers/input/touchscreen/ak4183.c
+ *
+ * Copyright (c) 2016 ASAHI KASEI MICRODEVICES Corporation
+ *
+ *  Author                Date        Revision
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *	Tsuyoshi Mutsuro	09/07/15	  1.0
+ *                      05/12/16      2.0 Kernel 3.18.XX
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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/slab.h>
+#include <linux/input.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/of_gpio.h>
+#include <linux/input/mt.h>
+
+// add. include files
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include "ymh_ak4183.h"
+
+//#define	AK4183_DEBUG   				//used at debug mode
+
+#ifdef AK4183_DEBUG
+#define akdbgprt printk
+#define dbg_printk printk
+#define MSR_RESULT_PR_COUNT   10
+#else
+#define akdbgprt(format, arg...) do {} while (0)
+#define dbg_printk(format, arg...)
+#endif
+
+#define TS_POLL_PERIOD_MSEC  3    /* msec  delay between samples */
+#define TS_SCAN_PERIOD_MSEC  20   /* msec  delay between scan */
+
+#define AK4183_PRESURE_THD			4000	/* Threshold of pressure measurement result */
+
+#define AK4183_MEASURE_WAIT			100		/* Wait time[usec] from command to execution of measurement */
+#define AK4183_MEASURE_COUNT		6
+
+#define AK4183_COMMAND_PENIRQ_ON	0xC0
+#define AK4183_COMMAND_PENIRQ_OFF	0xC4
+#define AK4183_COMMAND_SLEEP		0x72
+#define AK4183_COMMAND_MEASURE_X	0xC4
+#define AK4183_COMMAND_MEASURE_Y	0xD4
+#define AK4183_COMMAND_MEASURE_Z1	0xE4
+#define AK4183_COMMAND_MEASURE_Z2	0xF4
+
+
+#define AK4183_OFFSET_X     0
+#define	AK4183_OFFSET_Y     0
+#define AK4183_GAIN_X	    1024
+#define	AK4183_GAIN_Y	    1024
+#define	AK4183_DISTANCE_X   500		/* This is not used */
+#define AK4183_DISTANCE_Y   500		/* This is not used */
+
+#define AK4183_OFFSET_MIN      0
+#define	AK4183_OFFSET_MAX   2000
+#define AK4183_GAIN_MIN        0
+#define	AK4183_GAIN_MAX	    2000
+#define	AK4183_DISTANCE_MIN   50	/* This is not used */
+#define AK4183_DISTANCE_MAX 2000	/* This is not used */
+#define FT_CYCLE	1
+#define RS_CYCLE	3
+
+struct ts_event {
+	u16 status;
+	u16 xc;
+	u16 yc;
+	u16 xd;		/* This is not used */
+	u16 yd;		/* This is not used */
+	u16 z;
+};
+
+struct cali_data {
+	u16 offset_x;
+	u16 offset_y;
+	u16 gain_x;
+	u16 gain_y;
+	u16 distance_x;		/* This is not used */
+	u16 distance_y;		/* This is not used */
+};
+
+struct ak4183 {
+	struct input_dev	*input;
+	char				phys[32];
+	struct ts_event		tc;
+	struct Gesture_data gd;
+	struct cali_data	caliData;
+	u8 					intervalData[AK4183_MEASURE_COUNT];
+
+	struct i2c_client	*client;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	struct early_suspend early_suspend;
+#endif
+
+	u16				model;
+	u16				x_plate_ohms;
+	u16				y_plate_ohms;
+	u16				x_min, x_max;
+	u16				y_min, y_max;
+	u16				pressure_min, pressure_max;
+
+	int				irq;
+	int				irq_gpio;
+	bool 			msron;
+	wait_queue_head_t	wait;
+
+	unsigned		is_suspended:1;
+
+	struct timer_list timer;
+	struct work_struct workq;
+};
+
+static struct ak4183 *gl_ts;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ak4183_early_suspend(struct early_suspend *h);
+static void ak4183_late_resume(struct early_suspend *h);
+#endif
+
+static int set_cali_para(const char *buf)
+{
+	struct ak4183 *ts = gl_ts;
+	char *ptr_data = (char *)buf;
+	char *p;
+	int pt_count = 0;
+	unsigned long val[7];
+
+	akdbgprt("[AK4183] %s(%d)\n",__FUNCTION__,__LINE__);
+
+	while ((p = strsep(&ptr_data, ","))) {
+		if (!*p)
+			break;
+
+		if (pt_count >= 7)
+			break;
+
+		val[pt_count] = simple_strtoul(p, NULL, 10);
+
+		pt_count++;
+	}
+
+	if (pt_count == 7) {
+		if (val[6] == 321) {
+			ts->caliData.offset_x = val[0];
+			ts->caliData.offset_y = val[1];
+			ts->caliData.gain_x = val[2];
+			ts->caliData.gain_y = val[3];
+			if ( ts->caliData.offset_x < AK4183_OFFSET_MIN )
+                  ts->caliData.offset_x = AK4183_OFFSET_MIN;
+			else if ( ts->caliData.offset_x > AK4183_OFFSET_MAX )
+                  ts->caliData.offset_x = AK4183_OFFSET_MAX;
+			if ( ts->caliData.offset_y < AK4183_OFFSET_MIN )
+                  ts->caliData.offset_y = AK4183_OFFSET_MIN;
+			else if ( ts->caliData.offset_y > AK4183_OFFSET_MAX )
+                  ts->caliData.offset_y = AK4183_OFFSET_MAX;
+			if ( ts->caliData.gain_x < AK4183_GAIN_MIN )
+                  ts->caliData.gain_x = AK4183_GAIN_MIN;
+			else if ( ts->caliData.gain_x > AK4183_GAIN_MAX )
+                  ts->caliData.gain_x = AK4183_GAIN_MAX;
+			if ( ts->caliData.gain_y < AK4183_GAIN_MIN )
+                  ts->caliData.gain_y = AK4183_GAIN_MIN;
+			else if ( ts->caliData.gain_y > AK4183_GAIN_MAX )
+                  ts->caliData.gain_y = AK4183_GAIN_MAX;
+			if ( ts->caliData.distance_x < AK4183_DISTANCE_MIN )
+                  ts->caliData.distance_x = AK4183_DISTANCE_MIN;
+			else if ( ts->caliData.distance_x > AK4183_DISTANCE_MAX )
+                  ts->caliData.distance_x = AK4183_DISTANCE_MAX;
+			if ( ts->caliData.distance_y < AK4183_DISTANCE_MIN )
+                  ts->caliData.distance_y = AK4183_DISTANCE_MIN;
+			else if ( ts->caliData.distance_y > AK4183_DISTANCE_MAX )
+                  ts->caliData.distance_y = AK4183_DISTANCE_MAX;
+
+		} else if (val[6] == 123) {
+			ts->caliData.offset_x = AK4183_OFFSET_X;
+			ts->caliData.offset_y = AK4183_OFFSET_Y;
+			ts->caliData.gain_x = AK4183_GAIN_X;
+			ts->caliData.gain_y = AK4183_GAIN_Y;
+			ts->caliData.distance_x = AK4183_DISTANCE_X;
+			ts->caliData.distance_y = AK4183_DISTANCE_Y;
+		}
+		return 0;
+	}
+	return -1;
+}
+
+static ssize_t cali_data_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct ak4183 *ts = gl_ts;
+
+	return sprintf(buf, "%d,%d,%d,%d\n", ts->tc.xc,
+			ts->tc.yc, ts->tc.xd, ts->tc.yd);
+}
+
+static ssize_t cali_data_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	return count;
+}
+
+static ssize_t cali_para_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct ak4183 *ts = gl_ts;
+
+	return sprintf(buf, "%d,%d,%d,%d,%d,%d,321\n",
+			ts->caliData.offset_x,   ts->caliData.offset_y,
+			ts->caliData.gain_x,     ts->caliData.gain_y,
+			ts->caliData.distance_x, ts->caliData.distance_y);
+}
+
+static ssize_t cali_para_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	set_cali_para(buf);
+
+	return count;
+}
+
+static struct device_attribute attrs[] = {
+	__ATTR(cali_data, S_IRUGO, cali_data_show, cali_data_store),
+	__ATTR(cali_para, (S_IRUGO | S_IWUSR | S_IWGRP),cali_para_show,	cali_para_store)
+};
+
+static int FltDataInit(struct ak4183 *ts)
+{
+
+	ts->gd.nCFCount1 = 0;
+	ts->gd.m_isFirstPoint = 0;
+
+	return(0);
+}
+
+static u16 MoveDistance(u16 xp1, u16 yp1, u16 xpref, u16 ypref)
+{
+	short	ndx, ndy;
+	u16		nSum;
+
+	if( xp1 == 0x7FFF ){
+		return (10000);
+	}
+
+	ndx = (short)xp1 - (short)xpref;
+	ndy = (short)yp1 - (short)ypref;
+	if( ndx < 0 ) ndx = -ndx;
+	if( ndy < 0 ) ndy = -ndy;
+
+	nSum = (u16)( ndx + ndy );
+
+	return (nSum);
+}
+
+static int FltSingleData(struct ak4183 *ts, u16 *nStatus, u16 *xp, u16 *yp, u16 *z21)
+{
+	u16	nStbThs;
+	u16	i, n, nMin;
+   	static u16 nXp1[SINGLE_FLT_DATA];
+	static u16 nYp1[SINGLE_FLT_DATA];
+	static u16 nZ1[SINGLE_FLT_DATA];
+
+	nStbThs = SINGLE_FLT_DATA - 1;
+
+	nXp1[ts->gd.nCFCount1] = *xp;
+	nYp1[ts->gd.nCFCount1] = *yp;
+	if ( ts->gd.nCFCount1 < nStbThs ) {
+		*nStatus |= 0x10;
+		ts->gd.fltdata_xp.nRefData = *xp;
+		ts->gd.fltdata_yp.nRefData = *yp;
+		if ( ts->gd.nCFCount1 == 0 ) nZ1[0] = 10000;
+		else nZ1[ts->gd.nCFCount1] = MoveDistance(nXp1[ts->gd.nCFCount1], nYp1[ts->gd.nCFCount1],
+                                    ts->gd.fltdata_xp.nRefData, ts->gd.fltdata_yp.nRefData);
+		ts->gd.nCFCount1++;
+
+		return(0);
+	}
+
+	nZ1[nStbThs] = MoveDistance(nXp1[nStbThs], nYp1[nStbThs],
+                            ts->gd.fltdata_xp.nRefData, ts->gd.fltdata_yp.nRefData);
+
+	n = i = nStbThs;
+	nMin = nZ1[i];
+
+	do {
+		i--;
+		if ( nZ1[i] < nMin ) {
+			nMin = nZ1[i];
+			n = i;
+		}
+	}while(i > 0);
+
+	if ( ts->gd.m_isFirstPoint ) {
+		ts->gd.fltdata_xp.nOutData = (nXp1[n] + ts->gd.fltdata_xp.nRefData) / 2;
+		ts->gd.fltdata_yp.nOutData = (nYp1[n] + ts->gd.fltdata_yp.nRefData) / 2;
+	}
+	else {
+		ts->gd.fltdata_xp.nOutData = nXp1[n];
+		ts->gd.fltdata_yp.nOutData = nYp1[n];
+		ts->gd.m_isFirstPoint = 1;
+	}
+	*xp = ts->gd.fltdata_xp.nOutData;
+	*yp = ts->gd.fltdata_yp.nOutData;
+	ts->gd.fltdata_xp.nRefData = ts->gd.fltdata_xp.nOutData;
+	ts->gd.fltdata_yp.nRefData = ts->gd.fltdata_yp.nOutData;
+
+	for ( i = 0 ; i < nStbThs ; i++ ) {
+		if ( i < ( n - 1 ) ) nXp1[i] = 0x7FFF;
+		else  nXp1[i] = nXp1[i+1];
+		nYp1[i] = nYp1[i+1];
+		nZ1[i] = nZ1[i+1];
+	}
+
+	return(0);
+}
+
+static int UpdateData(struct ak4183 *ts, u16 *status, u16 *xp, u16 *yp, u16 *z21)
+{
+	int  nTouchNum, nRet;
+
+	if ( *status == 0x02) {		// one touch
+		nRet = FltSingleData( ts, status, xp, yp, z21);
+		if( nRet ) return (nRet);
+		nTouchNum = 1;
+		ts->gd.RS_Count = 0;
+	}else{
+		nTouchNum = 0;
+	}
+
+	return(nTouchNum);
+}
+
+static int GetPostion(struct ak4183 *ts, u16 *x1, u16 *y1)
+{
+	*x1 = ts->tc.yc;
+	*y1 = ts->tc.xc;
+
+	return(0);
+}
+
+static void ak4183_send_event(void *tsc)
+{
+	struct ak4183	*ts = tsc;
+	struct input_dev *input = ts->input;
+	u16 x1, y1;
+	u16 nTouchNum;
+#ifdef AK4183_DEBUG
+	static int count = 0;
+#endif
+
+	nTouchNum = UpdateData(ts, &(ts->tc.status), &(ts->tc.xc), &(ts->tc.yc), &(ts->tc.z));
+
+	if ( nTouchNum > 0 ) {
+		GetPostion(ts, &x1, &y1);
+		if (x1 > 60000) x1 = 0;
+		if (x1 > ts->x_max) x1 = ts->x_max;
+		if (y1 > 60000) y1 = 0;
+		if (y1 > ts->y_max) y1 = ts->y_max;
+	}
+
+	if ( nTouchNum == 1 ){
+
+		// exchange x<--->y
+		input_report_abs(input, ABS_X, ts->tc.yc);
+		input_report_abs(input, ABS_Y, ts->tc.xc);
+		input_report_abs(input, ABS_PRESSURE, ts->tc.z);
+		input_report_key(input, BTN_TOUCH, 1);
+
+		input_sync(input);
+
+#ifdef AK4183_DEBUG
+		count++;
+		if ( count == MSR_RESULT_PR_COUNT ) {
+//			akdbgprt("One touch: pt1(%4d,%4d), pressure (%4u)\n", x1, y1, ts->tc.z);
+//			akdbgprt("One touch: pt1(%4d,%4d), pressure (%4u)\n", ts->tc.xc, ts->tc.yc, ts->tc.z);
+			count = 0;
+		}
+#endif
+	}
+}
+
+static int ak4183_command(struct ak4183 *tsc, u8 cmd)
+{
+	s32	rt;
+	u8	tx[1];
+
+	tx[0] = cmd;
+
+	rt = i2c_master_send(tsc->client, tx, 1);
+	return (rt);
+}
+
+static int ak4183_measure(struct ak4183 *tsc, int cmd, int count)
+{
+	struct	i2c_msg	xfer[1];
+	int		ret, datalen, i, rdata, min, max, sum, msrdat;
+	u8		data[32];
+	datalen = 2; // read length ( once )
+	if( count > 16 ){
+		return (-EIO);
+	}
+
+	ak4183_command( tsc, cmd );
+
+	udelay(AK4183_MEASURE_WAIT);
+
+	sum = 0;
+	min = 4095;
+	max = 0;
+	// 2 pair of recieved data makes one measurement data.
+	// Where first data has [D11-D4] , second data has [D3-D0 <<4 | Duumy 4bits '0' ].
+	for( i = 0 ; i < count ; i ++ ){
+		xfer[0].addr = tsc->client->addr;
+		xfer[0].flags = I2C_M_RD;
+		xfer[0].len = datalen;
+		xfer[0].buf = &data[i*2];
+		ret = i2c_transfer(tsc->client->adapter, xfer, 1);
+		rdata = ((int)data[2*i] << 4 ) + ((int)data[2*i+1] >> 4);
+		if( rdata < min ) min = rdata;
+		if( rdata > max ) max = rdata;
+		sum += rdata;
+	}
+
+	if( count > 2 ){// throw away Max and Min.
+		sum -= min;
+		sum -= max;
+		msrdat = sum / ( count - 2 );
+	}else{
+		msrdat = sum / count;
+	}
+	return (msrdat);
+}
+
+static int ak4183_read_values(struct ak4183 *tsc)
+{
+	int		rt;
+	long	z1, z2, z21;
+	tsc->tc.status = 2;
+	tsc->tc.xc = ak4183_measure( tsc, AK4183_COMMAND_MEASURE_X, AK4183_MEASURE_COUNT );
+	tsc->tc.yc = ak4183_measure( tsc, AK4183_COMMAND_MEASURE_Y, AK4183_MEASURE_COUNT );
+	z1 = (long)ak4183_measure( tsc, AK4183_COMMAND_MEASURE_Z1, AK4183_MEASURE_COUNT );
+	z2 = (long)ak4183_measure( tsc, AK4183_COMMAND_MEASURE_Z2, AK4183_MEASURE_COUNT );
+	if( ( z1 > 5 ) && ( z2 < 4090 ) ){
+		z21 = (long)tsc->tc.xc * ( z2 - z1 ) / z1;
+	}else{
+		z21 = AK4183_PRESURE_THD + 1;
+	}
+
+	tsc->tc.z = (u16)z21;
+
+	rt = ak4183_command(tsc, AK4183_COMMAND_PENIRQ_OFF);
+
+	if( ( rt < 0 ) || ( z21 > AK4183_PRESURE_THD ) ){
+		tsc->tc.status = 0x12;
+	}else{
+		tsc->tc.status = 0x02;
+	}
+
+	return (0);
+}
+
+static int get_pendown_state(struct ak4183 *ts)
+{
+	// get z21, z21 < threshold then pen down else pun up judgement
+	long	z1, z2, z21;
+	z1 = (long)ak4183_measure( ts, AK4183_COMMAND_MEASURE_Z1, 3 );
+	z2 = (long)ak4183_measure( ts, AK4183_COMMAND_MEASURE_Z2, 3 );
+	if( ( z1 > 5 ) && ( z2 < 4090 ) ){
+		z21 = 1;
+	}else{
+		z21 = 0;
+	}
+	return z21;
+}
+
+
+static void ak4183_msr_func(struct ak4183 *ts)
+{
+
+	if (unlikely(!get_pendown_state(ts))) {
+		if (ts->gd.RS_Count < RS_CYCLE) {
+			ts->gd.RS_Count++;
+		} else {
+			ts->gd.RS_Count = 0;
+
+			FltDataInit(ts);
+
+			enable_irq(ts->irq);
+			input_report_abs(ts->input, ABS_PRESSURE, 0);
+			input_report_key(ts->input, BTN_TOUCH, 0);
+			input_sync(ts->input);
+
+			ts->msron = false;
+		}
+	} else {
+		/* pen is still down, continue with the measurement */
+		dev_dbg(&ts->client->dev, "pen is still down\n");
+		ts->gd.RS_Count = 0;
+
+		ak4183_read_values(ts);
+		if ((ts->tc.status & 2) == 2) {
+			ak4183_send_event(ts);
+		}
+	}
+}
+
+
+static int ak4183_device_init(struct ak4183 *tsc)
+{
+	s32 rt;
+
+	rt = ak4183_command(tsc, AK4183_COMMAND_PENIRQ_OFF);
+	rt = ak4183_command(tsc, AK4183_COMMAND_PENIRQ_OFF);
+
+	return rt;
+}
+
+// not used routine
+static irqreturn_t ak4183_hard_irq(int irq, void *handle)
+{
+	return(IRQ_HANDLED);
+}
+
+// not used routine
+static irqreturn_t ak4183_irq(int irq, void *handle)
+{
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ak4183_hard_irq_workq(struct ak4183 *ts)
+{
+	int pendown;
+
+	if ( ts->msron == false  ) {
+		pendown = get_pendown_state(ts);
+		if ( pendown  ) {
+			ts->msron = true;
+			return IRQ_WAKE_THREAD;
+		}
+	}
+	return(IRQ_HANDLED);
+}
+
+static irqreturn_t ak4183_irq_workq(struct ak4183 *ts)
+{
+	while ( ts->msron == true ) {
+		ak4183_msr_func(ts);
+		wait_event_timeout(ts->wait, !ts->msron,
+				   msecs_to_jiffies(TS_POLL_PERIOD_MSEC));
+	}
+	return IRQ_HANDLED;
+}
+
+// work queue job
+static void ak4183_workq(struct work_struct *work)
+{
+	struct	ak4183 *ts;
+
+	ts = container_of(work, struct ak4183, workq);
+	if( ak4183_hard_irq_workq(ts) == IRQ_WAKE_THREAD ){
+		ak4183_irq_workq(ts);
+	}
+}
+
+// from timer object, call work queue
+static void ak4183_poll_job(unsigned long arg)
+{
+	struct ak4183 *ts = (struct ak4183 *)arg;
+	schedule_work(&ts->workq);
+	mod_timer(&ts->timer, jiffies + msecs_to_jiffies(TS_SCAN_PERIOD_MSEC));
+}
+
+static int ak4183_ts_open(struct input_dev *dev)
+{
+	akdbgprt("\t[AK4183] %s\n", __FUNCTION__);
+
+	return 0;
+}
+
+static void ak4183_ts_close(struct input_dev *dev)
+{
+	akdbgprt("[AK4183] %s(%d)\n",__FUNCTION__,__LINE__);
+
+	disable_irq(gl_ts->irq);
+
+	input_sync(gl_ts->input);
+}
+
+static int ak4183_parse_dt(struct ak4183 *ts)
+{
+	u32 buf[4];
+	struct device *dev;
+	struct device_node *np;
+	int ret;
+
+	dev = &(ts->client->dev);
+	np = dev->of_node;
+
+	if (!np) return -EINVAL;
+
+	ret = of_property_read_u32(np, "ak4183,model", buf);
+	if (ret && (ret != -EINVAL)) {
+		dev_err(dev, "Unable to read ak4183,models\n");
+		dbg_printk("Unable to read ak4183,models\n");
+		ts->model = 4183;
+	}
+	else {
+		ts->model = (u16)buf[0];
+	}
+
+	ret = of_property_read_u32_array(np, "ak4183,coords", buf, 4);
+	if (ret && (ret != -EINVAL)) {
+		dev_err(dev, "Unable to read ak4183,coords\n");
+		dbg_printk("Unable to read ak4183,coords\n");
+		ts->x_min			= 0;
+		ts->y_min			= 0;
+		ts->x_max			= 4096;
+		ts->y_max			= 4096;
+	}
+	else {
+		ts->x_min			= (u16)buf[0];
+		ts->y_min			= (u16)buf[1];
+		ts->x_max			= (u16)buf[2];
+		ts->y_max			= (u16)buf[3];
+	}
+
+	akdbgprt("[AK4183] %s coords =(%d,%d)-(%d,%d)\n",__FUNCTION__,
+				(int)ts->x_min, (int)ts->x_max, (int)ts->y_min, (int)ts->y_max);
+
+	ret = of_property_read_u32_array(np, "ak4183,plate_ohms", buf, 2);
+	if (ret && (ret != -EINVAL)) {
+		dev_err(dev, "Unable to read ak4183,plate_ohms\n");
+		dbg_printk("Unable to read ak4183,plate_ohms\n");
+		ts->x_plate_ohms	= 300;
+		ts->y_plate_ohms	= 300;
+	}
+	else {
+		ts->x_plate_ohms	= (u16)buf[0];
+		ts->y_plate_ohms	= (u16)buf[1];
+	}
+
+	ret = of_property_read_u32_array(np, "ak4183,pressure", buf, 2);
+	if (ret && (ret != -EINVAL)) {
+		dev_err(dev, "Unable to read ak4183,pressure\n");
+		dbg_printk("Unable to read ak4183,pressure\n");
+		ts->pressure_min	= 0;
+		ts->pressure_max	= 255;
+	}
+	else {
+		ts->pressure_min	= (u16)buf[0];
+		ts->pressure_max	= (u16)buf[1];
+	}
+
+	return 0;
+}
+
+static int ak4183_probe(struct i2c_client *client,const struct i2c_device_id *id)
+{
+	struct ak4183 *ts;
+	struct input_dev *input_dev;
+	int n, num_attr;
+	int err;
+
+	akdbgprt("\t[AK4183] %s\n", __FUNCTION__);
+
+	if (!i2c_check_functionality(client->adapter,
+					I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
+					I2C_FUNC_SMBUS_READ_WORD_DATA  |
+					I2C_FUNC_SMBUS_READ_I2C_BLOCK))
+		return -EIO;
+
+	ts = kzalloc(sizeof(struct ak4183), GFP_KERNEL);
+
+	ts->client = client;
+	i2c_set_clientdata(client, ts);
+
+	gl_ts = ts;
+	ts->irq = -1;
+	ts->msron = 0;
+	init_waitqueue_head(&ts->wait);
+
+	err = ak4183_parse_dt(ts);
+	if (err) {
+		dev_err(&client->dev, "Error : Get dts data = %d \n", err);
+		dbg_printk("Error : Get dts data = %d \n", err);
+		goto err_power_failed;
+	}
+	ts->caliData.offset_x = AK4183_OFFSET_X;
+	ts->caliData.offset_y = AK4183_OFFSET_Y;
+	ts->caliData.gain_x	  = AK4183_GAIN_X;
+	ts->caliData.gain_y   = AK4183_GAIN_Y;
+	ts->caliData.distance_x = AK4183_DISTANCE_X;
+	ts->caliData.distance_y = AK4183_DISTANCE_Y;
+
+	err = ak4183_device_init(ts);
+
+	if (err < 0 ) {
+		dev_err(&client->dev, "Initialize error = %d \n", err);
+		dbg_printk("Initialize error = %d \n", err);
+		return err;
+	}
+
+	input_dev = input_allocate_device();
+	if (!ts || !input_dev) {
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+	ts->input = input_dev;
+
+	set_bit(EV_KEY,		ts->input->evbit);
+	set_bit(EV_ABS,		ts->input->evbit);
+	set_bit(BTN_TOUCH,	ts->input->keybit);
+#ifdef INPUT_PROP_DIRECT
+	set_bit(INPUT_PROP_DIRECT, ts->input->propbit);
+#endif
+
+	snprintf(ts->phys, sizeof(ts->phys),
+		 "%s/input0", dev_name(&client->dev));
+
+	input_dev->name = "ak4183-TouchScreen";
+	input_dev->phys = ts->phys;
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &client->dev;
+
+	ts->input->open = ak4183_ts_open;
+	ts->input->close = ak4183_ts_close;
+
+	INIT_WORK(&ts->workq, ak4183_workq);
+
+	init_timer(&ts->timer);
+	setup_timer(&ts->timer, ak4183_poll_job, (unsigned long) ts);
+	ts->timer.expires = jiffies + msecs_to_jiffies(TS_SCAN_PERIOD_MSEC);
+	add_timer(&ts->timer);
+
+	input_set_abs_params(input_dev, ABS_X, 0, 4095, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, 4095, 0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 0, 0);
+
+	input_set_drvdata(input_dev, ts);
+
+	err = input_register_device(input_dev);
+	if (err)
+		goto err_free_mem;
+
+	num_attr = ARRAY_SIZE(attrs);
+	for ( n = 0; n < num_attr ; n++) {
+		err = sysfs_create_file(&input_dev->dev.kobj, &attrs[n].attr);
+		if (err < 0) {
+			dev_err(&client->dev, "%s: Failed to create sysfs attributes\n",__func__);
+			dbg_printk("%s: Failed to create sysfs attributes\n",__func__);
+			goto err_sysfs;
+		}
+	}
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	ts->early_suspend.suspend = ak4183_early_suspend;
+	ts->early_suspend.resume = ak4183_late_resume;
+	register_early_suspend(&ts->early_suspend);
+#endif
+
+	akdbgprt("\t[AK4183] %s  OK\n", __FUNCTION__);
+
+	return 0;
+
+err_free_irq:
+	free_irq(ts->irq, ts);
+
+err_sysfs:
+	for (n--; n >= 0; n--) {
+		sysfs_remove_file(&input_dev->dev.kobj, &attrs[n].attr);
+	}
+err_free_mem:
+	input_free_device(input_dev);
+err_power_failed:
+	kfree(ts);
+
+	return err;
+}
+
+static int ak4183_remove(struct i2c_client *client)
+{
+	struct ak4183	*ts = i2c_get_clientdata(client);
+	int  n;
+
+	for ( n = 0; n < ARRAY_SIZE(attrs); n++) {
+		sysfs_remove_file(&ts->input->dev.kobj,	&attrs[n].attr);
+	}
+
+	free_irq(ts->irq, ts);
+	input_unregister_device(ts->input);
+	kfree(ts);
+
+	return 0;
+}
+
+static int ak4183_suspend(struct device *dev)
+{
+	struct ak4183	*ts = dev_get_drvdata(dev);
+	int 			err;
+
+	ts->is_suspended = 1;
+
+	ts->msron = 0;
+	wake_up(&ts->wait);
+	disable_irq(ts->irq);
+
+	err = ak4183_command( ts, AK4183_COMMAND_SLEEP );
+	if (err) {
+		dev_err(dev, "Suspend error = %d \n", err);
+		dbg_printk("Suspend error = %d \n", err);
+	}
+	dev_info(dev, "ak4183_suspend\n");
+
+	return 0;
+}
+
+static int ak4183_resume(struct device *dev)
+{
+	struct ak4183	*ts = dev_get_drvdata(dev);
+	int 			err;
+
+	disable_irq(ts->irq);
+	err = ak4183_device_init(ts);
+	if (err) {
+		dev_err(dev, "Initialize error = %d \n", err);
+		dbg_printk("Initialize error = %d \n", err);
+		return err;
+	}
+	enable_irq(ts->irq);
+
+	ts->is_suspended = 0;
+	dev_info(dev, "ak4183_resume\n");
+
+	return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ak4183_early_suspend(struct early_suspend *h)
+{
+	struct ak4183 *ts;
+	ts = container_of(h, struct ak4183, early_suspend);
+	ak4183_suspend(ts->client, PMSG_SUSPEND);
+}
+
+static void ak4183_late_resume(struct early_suspend *h)
+{
+	struct ak4183 *ts;
+	ts = container_of(h, struct ak4183, early_suspend);
+	ak4183_resume(ts->client);
+}
+#endif
+
+static struct of_device_id ak4183_i2c_dt_ids[] = {
+    { .compatible = "akm,ak4183"},
+    { }
+};
+
+static struct i2c_device_id ak4183_idtable[] = {
+	{ AK4183_NAME, 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, ak4183_idtable);
+
+static SIMPLE_DEV_PM_OPS(ak4183_pm_ops,
+			 ak4183_suspend, ak4183_resume);
+
+static struct i2c_driver ak4183_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= AK4183_NAME,
+		.of_match_table = ak4183_i2c_dt_ids,
+		.pm	= &ak4183_pm_ops,
+	},
+	.id_table	= ak4183_idtable,
+	.probe		= ak4183_probe,
+	.remove		= ak4183_remove,
+};
+
+static int __init ak4183_init(void)
+{
+	akdbgprt("[AK4183] %s(%d)\n",__FUNCTION__,__LINE__);
+
+	return i2c_add_driver(&ak4183_driver);
+}
+
+static void __exit ak4183_exit(void)
+{
+
+	i2c_del_driver(&ak4183_driver);
+
+}
+
+module_init(ak4183_init);
+module_exit(ak4183_exit);
+
+MODULE_AUTHOR("Junichi Wakasugi <wakasugi.jb@om.asahi-kasei.co.jp>");
+MODULE_DESCRIPTION("AK4183 TouchScreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/ymh_ak4183.h b/drivers/input/touchscreen/ymh_ak4183.h
new file mode 100644
index 000000000..4ad3fe7ce
--- /dev/null
+++ b/drivers/input/touchscreen/ymh_ak4183.h
@@ -0,0 +1,29 @@
+#ifndef __LINUX_I2C_AK4183_H
+#define __LINUX_I2C_AK4183_H
+
+/* ak4183.h */
+
+#define AK4183_NAME "ak4183"
+
+#define SINGLE_FLT_DATA	3
+
+typedef struct {
+	u16	nRefData;
+	u16	nOutData;
+} DUALFLTDATA;
+
+struct Gesture_data {
+
+    u16 m_isFirstPoint;
+
+    u16 MTCount, RS_Count;
+
+// Coordinates Filter
+    u16 nCFCount1;;
+
+	// for Dual Touch Data Filter ( These are not used  )
+    DUALFLTDATA fltdata_xp, fltdata_yp, fltdata_xd, fltdata_yd;	
+
+};
+
+#endif
