summaryrefslogtreecommitdiff
path: root/drivers/input/touchscreen/ssd253x_ts
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/touchscreen/ssd253x_ts')
-rwxr-xr-xdrivers/input/touchscreen/ssd253x_ts/Kconfig16
-rwxr-xr-xdrivers/input/touchscreen/ssd253x_ts/Makefile32
-rwxr-xr-xdrivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c1827
-rwxr-xr-xdrivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h28
-rwxr-xr-xdrivers/input/touchscreen/ssd253x_ts/wmt_ts.c810
-rwxr-xr-xdrivers/input/touchscreen/ssd253x_ts/wmt_ts.h116
6 files changed, 2829 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/ssd253x_ts/Kconfig b/drivers/input/touchscreen/ssd253x_ts/Kconfig
new file mode 100755
index 00000000..a5d9aa73
--- /dev/null
+++ b/drivers/input/touchscreen/ssd253x_ts/Kconfig
@@ -0,0 +1,16 @@
+#
+# SSD253x capacity touch screen driver configuration
+#
+config TOUCHSCREEN_SSD253X
+ tristate "SSD253X I2C Touchscreen Input Driver Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with touchscreen
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_ts_ssd253x.
+
diff --git a/drivers/input/touchscreen/ssd253x_ts/Makefile b/drivers/input/touchscreen/ssd253x_ts/Makefile
new file mode 100755
index 00000000..d78c8466
--- /dev/null
+++ b/drivers/input/touchscreen/ssd253x_ts/Makefile
@@ -0,0 +1,32 @@
+KERNELDIR=../../../../
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_ts_ssd253x
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := ssd253x-ts.o wmt_ts.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions *.order *.symvers
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
diff --git a/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c b/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c
new file mode 100755
index 00000000..c02392cb
--- /dev/null
+++ b/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c
@@ -0,0 +1,1827 @@
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+//#include <asm/gpio.h>
+#include <asm/irq.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <mach/hardware.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <linux/slab.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+
+#include "ssd253x-ts.h"
+#include "wmt_ts.h"
+
+//#define CONFIG_TOUCHSCREEN_SSL_DEBUG
+#undef CONFIG_TOUCHSCREEN_SSL_DEBUG
+
+#define DEVICE_ID_REG 2
+#define VERSION_ID_REG 3
+#define AUTO_INIT_RST_REG 68
+#define EVENT_STATUS 121
+#define EVENT_MSK_REG 122
+#define IRQ_MSK_REG 123
+#define FINGER01_REG 124
+#define EVENT_STACK 128
+#define EVENT_FIFO_SCLR 135
+#define TIMESTAMP_REG 136
+#define SELFCAP_STATUS_REG 185
+
+#define ON_TOUCH_INT INT_EI11 //GPIO :set the interrupt
+#define DEVICE_NAME "touch_ssd253x"
+#define SSD253X_I2C_ADDR 0x48 //0x48
+
+// SSD2533 Setting
+// Touch Panel Example
+static struct ChipSetting* ssd253xcfgTable = NULL;
+static int l_cfglen = 0;
+
+static struct ChipSetting ssd253xcfgTable_default[]={
+{2,0x06,0x1B,0x28},
+{2,0xd7,0x00,0x00},
+{2,0xd8,0x00,0x07},
+{2,0xdb,0x00,0x01},
+{2,0x30,0x03,0x08},
+{2,0x34,0xd4,0x1e},
+{2,0x57,0x00,0x06},
+{2,0x40,0x00,0xc8},
+{2,0x41,0x00,0x30},
+{2,0x42,0x00,0xc0},
+{2,0x43,0x00,0x30},
+{2,0x44,0x00,0xc0},
+{2,0x45,0x00,0xc0},
+{2,0x46,0x00,0x0f},
+{2,0x5f,0x00,0x00},
+{2,0x2d,0x00,0x00},
+{2,0x66,0x1F,0x38},
+{2,0x67,0x1c,0x92},
+{2,0x25,0x00,0x02},
+};
+
+
+// For SSD2533 Bug Version Only //
+//#define SSD2533FIXEDCODE
+ struct ChipSetting ssd253xcfgTable1[]={
+{ 1, 0xA4, 0x00, 0x00}, //MCU prescaler default=01
+{ 1, 0xD4, 0x08, 0x00}, //Dummy Code
+{ 1, 0xD4, 0x08, 0x00}, //Set Osc frequency default=8, range 0 to F
+};
+
+ struct ChipSetting Reset[]={
+{ 0, 0x04, 0x00, 0x00}, // SSD2533
+};
+
+ struct ChipSetting Resume[]={
+{ 0, 0x04, 0x00, 0x00}, // SSD2533
+{ 1, 0x25, 0x12, 0x00}, // Set Operation Mode //Set from int setting
+};
+
+ struct ChipSetting Suspend[] ={
+{ 1, 0x25, 0x00, 0x00}, // Set Operation Mode
+{ 0, 0x05, 0x00, 0x00}, // SSD2533
+};
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ssd253x_ts_early_suspend(struct early_suspend *h);
+static void ssd253x_ts_late_resume(struct early_suspend *h);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+static irqreturn_t ssd253x_ts_isr(int irq, void *dev_id);
+static enum hrtimer_restart ssd253x_ts_timer(struct hrtimer *timer);
+//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num,int bus_id);
+
+
+static int SSDS53X_SCREEN_MAX_X = 800;
+static int SSDS53X_SCREEN_MAX_Y = 480;
+
+
+
+enum{
+ IC_SSD2533 = 1,
+ IC_SSD2543,
+ IC_SSD2531
+};
+
+static int ic_flag;
+
+static struct workqueue_struct *ssd253x_wq;
+
+int Ssd_Timer1,Ssd_Timer2,Ssd_Timer_flag;
+
+struct ssl_ts_priv {
+ struct input_dev *input;
+ struct hrtimer timer;
+ struct work_struct ssl_work;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+
+ int irq;
+ int use_irq;
+ int FingerNo;
+ int earlysus;
+
+ int FingerX[FINGERNO];
+ int FingerY[FINGERNO];
+ int FingerP[FINGERNO];
+
+ int Resolution;
+ int EventStatus;
+ int FingerDetect;
+
+ int sFingerX[FINGERNO];
+ int sFingerY[FINGERNO];
+ int pFingerX[FINGERNO];
+ int pFingerY[FINGERNO];
+};
+
+static struct ssl_ts_priv* l_ts = NULL;
+struct wmtts_device ssd253x_tsdev;
+static DECLARE_WAIT_QUEUE_HEAD(ts_penup_wait_queue);
+
+#define SD_INIT
+#ifdef SD_INIT
+#define TP_CHR "tp_chr"
+
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+
+static long tp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+static int tp_open(struct inode *inode, struct file *file);
+static int tp_release(struct inode *inode, struct file *file);
+static ssize_t tp_read(struct file *file, char __user *buf, size_t count,loff_t *offset);
+static ssize_t tp_write(struct file *file, const char __user *buf,size_t count, loff_t *offset);
+
+//void InitFromSD(struct i2c_client *client);
+
+//struct ChipSetting _ssd253xcfgTable[200];
+//int sd_init_size=0;
+
+
+//struct i2c_client *g_tp_client;
+
+#endif
+
+
+
+static int ReadRegister(/*struct i2c_client *client,*/uint8_t reg,int ByteNo)
+{
+ unsigned char buf[4];
+ struct i2c_msg msg[2];
+ int ret;
+ struct i2c_client* client = ts_get_i2c_client();
+
+ memset(buf, 0xFF, sizeof(buf));
+ msg[0].addr = SSD253X_I2C_ADDR;
+ msg[0].flags = 0 | I2C_M_NOSTART;
+ msg[0].len = 1;
+ msg[0].buf = &reg;
+
+ msg[1].addr = SSD253X_I2C_ADDR;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = ByteNo;
+ msg[1].buf = buf;
+
+ ret = i2c_transfer(client->adapter, msg, 2);
+ if (ret <= 0)
+ {
+ printk("read the address (0x%x) of the ssd253x fail, ret=%d.\n", reg, ret);
+ return -1;
+ }
+
+ if(ByteNo==1) return (int)((unsigned int)buf[0]<<0);
+ if(ByteNo==2) return (int)((unsigned int)buf[1]<<0)|((unsigned int)buf[0]<<8);
+ if(ByteNo==3) return (int)((unsigned int)buf[2]<<0)|((unsigned int)buf[1]<<8)|((unsigned int)buf[0]<<16);
+ if(ByteNo==4) return (int)((unsigned int)buf[3]<<0)|((unsigned int)buf[2]<<8)|((unsigned int)buf[1]<<16)|(buf[0]<<24);
+ return 0;
+}
+
+static int WriteRegister(/*struct i2c_client *client,*/uint8_t Reg,unsigned char Data1,unsigned char Data2,int ByteNo)
+{
+ struct i2c_msg msg;
+ unsigned char buf[4];
+ int ret;
+ struct i2c_client* client = ts_get_i2c_client();
+
+ buf[0]=Reg;
+ buf[1]=Data1;
+ buf[2]=Data2;
+ buf[3]=0;
+
+ msg.addr = SSD253X_I2C_ADDR;
+ msg.flags = 0;
+ msg.len = ByteNo+1;
+ msg.buf = (char *)buf;
+ ret = i2c_transfer(client->adapter, &msg, 1);
+ if (ret <= 0)
+ {
+ printk(KERN_ERR "write the address (0x%x) of the ssd25xx fail, ret=%d.\n", buf[0], ret);
+ return -1;
+ }
+ return 0;
+
+}
+
+int SSD253xdeviceInit1(void)
+{
+#ifdef SSD2533FIXEDCODE
+ int i;
+ mdelay(600); //SSD2533 ESD2 EEPROM VERSION
+ for(i=0;i<sizeof(ssd253xcfgTable1)/sizeof(ssd253xcfgTable1[0]);i++)
+ {
+ if (WriteRegister(ssd253xcfgTable1[i].Reg,
+ ssd253xcfgTable1[i].Data1,ssd253xcfgTable1[i].Data2,
+ ssd253xcfgTable1[i].No))
+ {
+ return -1;
+ }
+ }
+#endif
+ return 0;
+}
+
+int SSD253xdeviceInit(void)
+{
+ int i;
+
+ for(i=0;i<l_cfglen/*sizeof(ssd253xcfgTable)/sizeof(ssd253xcfgTable[0])*/;i++)
+ {
+ if (WriteRegister(ssd253xcfgTable[i].Reg,
+ ssd253xcfgTable[i].Data1,ssd253xcfgTable[i].Data2,
+ ssd253xcfgTable[i].No))
+ {
+ return -1;
+ }
+ if (0 == i)
+ {
+ msleep(300);
+ }
+ }
+ msleep(300);
+ return 0;
+}
+
+int deviceReset(void)
+{
+ int i;
+
+ i = 0;//just for remove warning message
+ wmt_rst_output(1);
+ mdelay(5);
+ wmt_rst_output(0);
+ mdelay(10);
+ wmt_rst_output(1);
+ msleep(200);
+
+ //if(ic_flag == IC_SSD2533){
+ for(i=0;i<sizeof(Reset)/sizeof(Reset[0]);i++)
+ {
+ if (WriteRegister(Reset[i].Reg,
+ Reset[i].Data1,Reset[i].Data2,
+ Reset[i].No))
+ {
+ return -1;
+ }
+ }
+ //}
+
+ mdelay(100);
+ if (SSD253xdeviceInit1())
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int deviceResume(void)
+{
+ int i;
+ for(i=0;i<sizeof(Resume)/sizeof(Resume[0]);i++)
+ {
+ if (WriteRegister(Resume[i].Reg,
+ Resume[i].Data1,Resume[i].Data2,
+ Resume[i].No))
+ {
+ return -1;
+ }
+ mdelay(100);
+ }
+ return 0;
+}
+
+int deviceSuspend(void)
+{
+ int i;
+ //int timeout=10;
+ //int status;
+
+ for(i=0;i<sizeof(Suspend)/sizeof(Suspend[0]);i++)
+ {
+ if (WriteRegister(Suspend[i].Reg,
+ Suspend[i].Data1,Suspend[i].Data2,
+ Suspend[i].No))
+ {
+ return -1;
+ }
+ mdelay(100);
+ }
+ return 0;
+}
+
+#define Mode RunningAverageMode
+#define Dist RunningAverageDist
+void RunningAverage(unsigned short *xpos,unsigned short *ypos,int No,struct ssl_ts_priv *ssl_priv)
+{
+ int FilterMode[4][2]={{0,8},{5,3},{6,2},{7,1}};
+ int dx,dy;
+ int X,Y;
+
+ X=*xpos;
+ Y=*ypos;
+ if((ssl_priv->pFingerX[No]!=0x0FFF)&&(X!=0x0FFF))
+ {
+ dx=abs(ssl_priv->pFingerX[No]-X);
+ dy=abs(ssl_priv->pFingerY[No]-Y);
+ if(dx+dy<Dist*64)
+ {
+ ssl_priv->pFingerX[No]=(FilterMode[Mode][0]*ssl_priv->pFingerX[No]+FilterMode[Mode][1]*X)/8;
+ ssl_priv->pFingerY[No]=(FilterMode[Mode][0]*ssl_priv->pFingerY[No]+FilterMode[Mode][1]*Y)/8;
+ }
+ else
+ {
+ ssl_priv->pFingerX[No]=X;
+ ssl_priv->pFingerY[No]=Y;
+ }
+ }
+ else
+ {
+ ssl_priv->pFingerX[No]=X;
+ ssl_priv->pFingerY[No]=Y;
+ }
+ *xpos=ssl_priv->pFingerX[No];
+ *ypos=ssl_priv->pFingerY[No];
+}
+
+void FingerCheckSwap(int *FingerX,int *FingerY,int *FingerP,int FingerNo,int *sFingerX,int *sFingerY)
+{
+ int i,j;
+ int index1,index2;
+ int Vx,Vy;
+ int Ux,Uy;
+ int R1x,R1y;
+ int R2x,R2y;
+ for(i=0;i<FingerNo;i++)
+ {
+ index1=i;
+ if( FingerX[index1]!=0xFFF)
+ if(sFingerX[index1]!=0xFFF)
+ {
+ for(j=i+1;j<FingerNo+3;j++)
+ {
+ index2=j%FingerNo;
+ if( FingerX[index2]!=0xFFF)
+ if(sFingerX[index2]!=0xFFF)
+ {
+ Ux=sFingerX[index1]-sFingerX[index2];
+ Uy=sFingerY[index1]-sFingerY[index2];
+ Vx= FingerX[index1]- FingerX[index2];
+ Vy= FingerY[index1]- FingerY[index2];
+
+ R1x=Ux-Vx;
+ R1y=Uy-Vy;
+ R2x=Ux+Vx;
+ R2y=Uy+Vy;
+
+ R1x=R1x*R1x;
+ R1y=R1y*R1y;
+ R2x=R2x*R2x;
+ R2y=R2y*R2y;
+
+ if(R1x+R1y>R2x+R2y)
+ {
+ Ux=FingerX[index1];
+ Uy=FingerY[index1];
+ Vx=FingerP[index1];
+
+ FingerX[index1]=FingerX[index2];
+ FingerY[index1]=FingerY[index2];
+ FingerP[index1]=FingerP[index2];
+
+ FingerX[index2]=Ux;
+ FingerY[index2]=Uy;
+ FingerP[index2]=Vx;
+ }
+ break;
+ }
+ }
+ }
+ }
+ for(i=0;i<FingerNo;i++)
+ {
+ sFingerX[i]=FingerX[i];
+ sFingerY[i]=FingerY[i];
+ }
+}
+
+#ifdef USE_TOUCH_KEY
+static void ssd2533_ts_send_keyevent(struct ssl_ts_priv *ssl_priv,u8 btn_status, int downup)
+{
+
+ switch(btn_status & 0x0f)
+ {
+ case 0x01:
+ input_report_key(ssl_priv->input, KEY_SEARCH, downup);
+ break;
+ case 0x02:
+ input_report_key(ssl_priv->input, KEY_BACK, downup);
+ break;
+ case 0x04:
+ input_report_key(ssl_priv->input, KEY_HOME, downup);
+ break;
+ case 0x08:
+ input_report_key(ssl_priv->input, KEY_MENU, downup);
+ break;
+ default:
+ break;
+ }
+ dbg("send %x %x\n", btn_status, downup);
+}
+#endif
+
+// for ssd2533(no test)
+static int ssd253x_ts_cut_edge0(unsigned short pos,unsigned short x_y)
+{
+ u8 cut_value = 26; //26 cut_value < 32
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ //printk("X: rude data %d\n",pos);
+ if(x_y) //xpos
+ {
+
+ if(pos < 16)
+ pos = cut_value + pos*(48 - cut_value) / 16;
+ else if(pos > (XPOS_MAX - 16) )
+ pos = XPOS_MAX + 16 + (pos - (XPOS_MAX -16))*(48 - cut_value) / 16;
+ else
+ pos = pos + 32;
+
+ pos = SSDS53X_SCREEN_MAX_X * pos / (DRIVENO * 64);
+ //printk("X: changed data %d\n",pos);
+ return pos;
+ }
+ else //ypos
+ {
+ if(pos < 16)
+ pos = cut_value + pos*(48 - cut_value) / 16;
+ else if(pos > (YPOS_MAX - 16) )
+ pos = YPOS_MAX + 16 + (pos - (YPOS_MAX -16))*(48 - cut_value) / 16;
+ else
+ pos = pos + 32;
+ //printk("Y: rude data %d\n",pos);
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (SENSENO * 64);
+ //printk("Y: changed data %d\n",pos);
+ return pos;
+ }
+
+
+}
+
+// for ssd2532
+static int ssd253x_ts_cut_edge1(unsigned short pos,unsigned short x_y)
+{
+ u8 cut_value = 15; //cut_value < 32
+
+ if(pos == 0xfff){
+ return pos;
+ }
+
+ if(x_y){ //xpos 64-->96 //MAX=896
+ pos = pos + cut_value;//????????Ôµ
+ pos = SSDS53X_SCREEN_MAX_X * pos / (790+cut_value*2);//SSDS53X_SCREEN_MAX_X?????Ò±?Ôµ
+ return pos;
+ }else{ //ypos //MAX=576
+ pos = pos + cut_value;//?????ϱ?Ե
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (470+cut_value*2);//SSDS53X_SCREEN_MAX_Y?????±?Ե
+ return pos;
+ }
+}
+
+// for ssd2532,8" ssd253x_pydctp80a1.ts
+// x_y:1--x,0--y
+static int ssd253x_ts_cut_edge2(unsigned short pos,unsigned short x_y)
+{
+ int tpos;
+
+ if (pos == 0xfff){
+ return pos;
+ }
+
+ tpos = pos;
+ if (x_y)
+ {
+ if (tpos<20)
+ {
+ tpos= tpos+18;
+ } else if (tpos>585)
+ {
+ tpos = tpos-18;
+ } else {
+ tpos = (tpos-20)*565/575+30;
+ }
+ pos = tpos;
+ return pos;
+ } else {
+ if (tpos <10)
+ {
+ tpos = tpos+10;
+ } else if (tpos >795)
+ {
+ tpos = 795;
+ } else {
+ tpos = (tpos-10)*775/785+20;
+ }
+ pos = tpos;
+ return pos;
+ }
+
+}
+// for ssd2532
+static int ssd253x_ts_cut_edge3(unsigned short pos,unsigned short x_y)
+{
+ u8 cut_value = 15;
+
+ if(pos == 0xfff){
+ return pos;
+ }
+
+ if(x_y){
+ pos = pos + cut_value;
+ pos = SSDS53X_SCREEN_MAX_X * pos / (896+cut_value*2);
+ return pos;
+ }else{
+ pos = pos + cut_value;
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (576+cut_value*2);
+ return pos;
+ }
+}
+
+// for jun feng TP
+static int ssd253x_ts_cut_edge4(unsigned short pos,unsigned short x_y)
+{
+ unsigned short Cut_Edge_XLeft[64]={
+ 0x0008,0x0009,0x000B,0x000C,0x000D,0x000E,0x0010,0x0011,
+ 0x0012,0x0013,0x0015,0x0016,0x0017,0x0018,0x001A,0x001B,
+ 0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,0x0024,0x0025,
+ 0x0026,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,
+ 0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0032,
+ 0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0038,0x0039,
+ 0x003A,0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,
+ 0x0041,0x0042,0x0043,0x0044,0x0044,0x0045,0x0046,0x0047
+ };
+
+ unsigned short Cut_Edge_XRight[64]={
+ 0x0318,0x0317,0x0315,0x0314,0x0313,0x0312,0x0310,0x030F,
+ 0x030E,0x030D,0x030B,0x030A,0x0309,0x0308,0x0306,0x0305,
+ 0x0304,0x0303,0x0301,0x0300,0x02FF,0x02FE,0x02FC,0x02FB,
+ 0x02FA,0x02FA,0x02F9,0x02F8,0x02F7,0x02F6,0x02F5,0x02F4,
+ 0x02F4,0x02F3,0x02F2,0x02F1,0x02F0,0x02EF,0x02EE,0x02EE,
+ 0x02ED,0x02EC,0x02EB,0x02EA,0x02E9,0x02E8,0x02E8,0x02E7,
+ 0x02E6,0x02E5,0x02E4,0x02E3,0x02E2,0x02E2,0x02E1,0x02E0,
+ 0x02DF,0x02DE,0x02DD,0x02DC,0x02DC,0x02DB,0x02DA,0x02D9
+ };
+
+ unsigned short Cut_Edge_YUp[64]={
+ 0x0006,0x0007,0x0008,0x000A,0x000B,0x000C,0x000D,0x000F,
+ 0x0010,0x0011,0x0012,0x0014,0x0015,0x0016,0x0017,0x0018,
+ 0x001A,0x001B,0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,
+ 0x0022,0x0023,0x0024,0x0025,0x0025,0x0026,0x0027,0x0028,
+ 0x0029,0x0029,0x002A,0x002B,0x002C,0x002C,0x002D,0x002E,
+ 0x002F,0x0030,0x0030,0x0031,0x0032,0x0033,0x0033,0x0034,
+ 0x0035,0x0036,0x0037,0x0037,0x0038,0x0039,0x003A,0x003A,
+ 0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,0x0041
+ };
+
+ unsigned short Cut_Edge_YDown[64]={
+ 0x01DA,0x01D9,0x01D8,0x01D6,0x01D5,0x01D4,0x01D3,0x01D1,
+ 0x01D0,0x01CF,0x01CE,0x01CC,0x01CB,0x01CA,0x01C9,0x01C8,
+ 0x01C6,0x01C5,0x01C4,0x01C3,0x01C1,0x01C0,0x01BF,0x01BE,
+ 0x01BE,0x01BD,0x01BC,0x01BB,0x01BB,0x01BA,0x01B9,0x01B8,
+ 0x01B7,0x01B7,0x01B6,0x01B5,0x01B4,0x01B4,0x01B3,0x01B2,
+ 0x01B1,0x01B0,0x01B0,0x01AF,0x01AE,0x01AD,0x01AD,0x01AC,
+ 0x01AB,0x01AA,0x01A9,0x01A9,0x01A8,0x01A7,0x01A6,0x01A6,
+ 0x01A5,0x01A4,0x01A3,0x01A2,0x01A2,0x01A1,0x01A0,0x019F
+ };
+ int cut_value = 5; //cut_value < 32
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ dbg("X: Raw data %d\n",pos);
+ if (pos >=XPOS_MAX)
+ {
+ pos = XPOS_MAX;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_XLeft[pos]; //Left cut edge
+ }
+ else
+ if ((XPOS_MAX - pos) <64)
+ {
+ pos = Cut_Edge_XRight[XPOS_MAX - pos]; //Right cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSDS53X_SCREEN_MAX_X* pos / (790 + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ dbg("X: Cut edge data %d\n",pos);
+ return pos;
+ }
+ else //ypos
+ {
+
+ dbg("Y: Raw data %d\n",pos);
+ if (pos >=YPOS_MAX)
+ {
+ pos = YPOS_MAX;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_YUp[pos]; //Up cut edge
+ }
+ else
+ if ((YPOS_MAX - pos) <64)
+ {
+ pos = Cut_Edge_YDown[YPOS_MAX - pos]; //Down cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (470 + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ //tpos = pos;
+ //tpos = /*SSDS53X_SCREEN_MAX_Y*/ (800* pos) / (470 + cut_value*2);
+ dbg("XPOS_MAX=%d,\n", XPOS_MAX);
+ dbg("YPOS_MAX=%d,\n",YPOS_MAX);
+ dbg("Y: Cut edge data pos= %d,tpos=%d\n",pos,tpos);
+ }
+
+ return pos;
+ }
+
+
+}
+
+static int ssd253x_ts_cut_edge5(unsigned short pos,unsigned short x_y)
+{
+ unsigned short Cut_Edge_XLeft[64]={
+ 0x0008,0x0009,0x000B,0x000C,0x000D,0x000E,0x0010,0x0011,
+ 0x0012,0x0013,0x0015,0x0016,0x0017,0x0018,0x001A,0x001B,
+ 0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,0x0024,0x0025,
+ 0x0026,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,
+ 0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0032,
+ 0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0038,0x0039,
+ 0x003A,0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,
+ 0x0041,0x0042,0x0043,0x0044,0x0044,0x0045,0x0046,0x0047
+ };
+
+ unsigned short Cut_Edge_XRight[64]={
+ 0x0318,0x0317,0x0315,0x0314,0x0313,0x0312,0x0310,0x030F,
+ 0x030E,0x030D,0x030B,0x030A,0x0309,0x0308,0x0306,0x0305,
+ 0x0304,0x0303,0x0301,0x0300,0x02FF,0x02FE,0x02FC,0x02FB,
+ 0x02FA,0x02FA,0x02F9,0x02F8,0x02F7,0x02F6,0x02F5,0x02F4,
+ 0x02F4,0x02F3,0x02F2,0x02F1,0x02F0,0x02EF,0x02EE,0x02EE,
+ 0x02ED,0x02EC,0x02EB,0x02EA,0x02E9,0x02E8,0x02E8,0x02E7,
+ 0x02E6,0x02E5,0x02E4,0x02E3,0x02E2,0x02E2,0x02E1,0x02E0,
+ 0x02DF,0x02DE,0x02DD,0x02DC,0x02DC,0x02DB,0x02DA,0x02D9
+ };
+
+ unsigned short Cut_Edge_YUp[64]={
+ 0x0006,0x0007,0x0008,0x000A,0x000B,0x000C,0x000D,0x000F,
+ 0x0010,0x0011,0x0012,0x0014,0x0015,0x0016,0x0017,0x0018,
+ 0x001A,0x001B,0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,
+ 0x0022,0x0023,0x0024,0x0025,0x0025,0x0026,0x0027,0x0028,
+ 0x0029,0x0029,0x002A,0x002B,0x002C,0x002C,0x002D,0x002E,
+ 0x002F,0x0030,0x0030,0x0031,0x0032,0x0033,0x0033,0x0034,
+ 0x0035,0x0036,0x0037,0x0037,0x0038,0x0039,0x003A,0x003A,
+ 0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,0x0041
+ };
+
+ unsigned short Cut_Edge_YDown[64]={
+ 0x01DA,0x01D9,0x01D8,0x01D6,0x01D5,0x01D4,0x01D3,0x01D1,
+ 0x01D0,0x01CF,0x01CE,0x01CC,0x01CB,0x01CA,0x01C9,0x01C8,
+ 0x01C6,0x01C5,0x01C4,0x01C3,0x01C1,0x01C0,0x01BF,0x01BE,
+ 0x01BE,0x01BD,0x01BC,0x01BB,0x01BB,0x01BA,0x01B9,0x01B8,
+ 0x01B7,0x01B7,0x01B6,0x01B5,0x01B4,0x01B4,0x01B3,0x01B2,
+ 0x01B1,0x01B0,0x01B0,0x01AF,0x01AE,0x01AD,0x01AD,0x01AC,
+ 0x01AB,0x01AA,0x01A9,0x01A9,0x01A8,0x01A7,0x01A6,0x01A6,
+ 0x01A5,0x01A4,0x01A3,0x01A2,0x01A2,0x01A1,0x01A0,0x019F
+ };
+ u8 cut_value = 20; //cut_value < 32
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ dbg("X: Raw data %d\n",pos);
+ if (pos >=XPOS_MAX)
+ {
+ pos = XPOS_MAX;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_XLeft[pos]; //Left cut edge
+ }
+ else
+ if ((XPOS_MAX - pos) <64)
+ {
+ pos = Cut_Edge_XRight[XPOS_MAX - pos]; //Right cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSDS53X_SCREEN_MAX_X * pos / (XPOS_MAX + cut_value*2);//SSD253X_SCREEN_MAX_X|??????????|? }
+ dbg("X: Cut edge data %d\n",pos);
+ return pos;
+ }
+ }
+ else //ypos
+ {
+
+ dbg("Y: Raw data %d\n",pos);
+ if (pos >=YPOS_MAX)
+ {
+ pos = YPOS_MAX;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_YUp[pos]; //Up cut edge
+ }
+ else
+ if ((YPOS_MAX - pos) <64)
+ {
+ pos = Cut_Edge_YDown[YPOS_MAX - pos]; //Down cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSDS53X_SCREEN_MAX_Y * pos / (YPOS_MAX + cut_value*2);//SSD253X_SCREEN_MAX_X|??????????|? }
+ dbg("Y: Cut edge data %d\n",pos);
+ return pos;
+ }
+ }
+ return -1;
+}
+
+static int ssd253x_ts_cut_edge6(unsigned short pos,unsigned short x_y)
+{
+
+ #define XPOS_MAX_D (DRIVENO -EdgeDisable) *64
+ #define YPOS_MAX_D (SENSENO -EdgeDisable) *64
+ #undef SSD253X_SCREEN_MAX_X
+ #define SSD253X_SCREEN_MAX_X 800
+ #define SSD253X_SCREEN_MAX_Y 480
+
+ u8 cut_value = 20; //cut_value < 32
+ unsigned short Cut_Edge_XLeft[64]={
+ 0x0008,0x0009,0x000B,0x000C,0x000D,0x000E,0x0010,0x0011,
+ 0x0012,0x0013,0x0015,0x0016,0x0017,0x0018,0x001A,0x001B,
+ 0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,0x0024,0x0025,
+ 0x0026,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,
+ 0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0032,
+ 0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0038,0x0039,
+ 0x003A,0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,
+ 0x0041,0x0042,0x0043,0x0044,0x0044,0x0045,0x0046,0x0047
+ };
+
+ unsigned short Cut_Edge_XRight[64]={
+ 0x0318,0x0317,0x0315,0x0314,0x0313,0x0312,0x0310,0x030F,
+ 0x030E,0x030D,0x030B,0x030A,0x0309,0x0308,0x0306,0x0305,
+ 0x0304,0x0303,0x0301,0x0300,0x02FF,0x02FE,0x02FC,0x02FB,
+ 0x02FA,0x02FA,0x02F9,0x02F8,0x02F7,0x02F6,0x02F5,0x02F4,
+ 0x02F4,0x02F3,0x02F2,0x02F1,0x02F0,0x02EF,0x02EE,0x02EE,
+ 0x02ED,0x02EC,0x02EB,0x02EA,0x02E9,0x02E8,0x02E8,0x02E7,
+ 0x02E6,0x02E5,0x02E4,0x02E3,0x02E2,0x02E2,0x02E1,0x02E0,
+ 0x02DF,0x02DE,0x02DD,0x02DC,0x02DC,0x02DB,0x02DA,0x02D9
+ };
+
+ unsigned short Cut_Edge_YUp[64]={
+ 0x0006,0x0007,0x0008,0x000A,0x000B,0x000C,0x000D,0x000F,
+ 0x0010,0x0011,0x0012,0x0014,0x0015,0x0016,0x0017,0x0018,
+ 0x001A,0x001B,0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,
+ 0x0022,0x0023,0x0024,0x0025,0x0025,0x0026,0x0027,0x0028,
+ 0x0029,0x0029,0x002A,0x002B,0x002C,0x002C,0x002D,0x002E,
+ 0x002F,0x0030,0x0030,0x0031,0x0032,0x0033,0x0033,0x0034,
+ 0x0035,0x0036,0x0037,0x0037,0x0038,0x0039,0x003A,0x003A,
+ 0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,0x0041
+ };
+
+ unsigned short Cut_Edge_YDown[64]={
+ 0x01DA,0x01D9,0x01D8,0x01D6,0x01D5,0x01D4,0x01D3,0x01D1,
+ 0x01D0,0x01CF,0x01CE,0x01CC,0x01CB,0x01CA,0x01C9,0x01C8,
+ 0x01C6,0x01C5,0x01C4,0x01C3,0x01C1,0x01C0,0x01BF,0x01BE,
+ 0x01BE,0x01BD,0x01BC,0x01BB,0x01BB,0x01BA,0x01B9,0x01B8,
+ 0x01B7,0x01B7,0x01B6,0x01B5,0x01B4,0x01B4,0x01B3,0x01B2,
+ 0x01B1,0x01B0,0x01B0,0x01AF,0x01AE,0x01AD,0x01AD,0x01AC,
+ 0x01AB,0x01AA,0x01A9,0x01A9,0x01A8,0x01A7,0x01A6,0x01A6,
+ 0x01A5,0x01A4,0x01A3,0x01A2,0x01A2,0x01A1,0x01A0,0x019F
+ };
+
+
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("X: Raw data %d\n",pos);
+ //#endif
+ if (pos >=XPOS_MAX_D)
+ {
+ pos = XPOS_MAX_D;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_XLeft[pos]; //Left cut edge
+ }
+ else
+ if ((XPOS_MAX_D - pos) <64)
+ {
+ pos = Cut_Edge_XRight[XPOS_MAX_D - pos]; //Right cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSD253X_SCREEN_MAX_X * pos / (XPOS_MAX_D + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("X: Cut edge data %d\n",pos);
+ //#endif
+ return pos;
+ }
+ else //ypos
+ {
+
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("Y: Raw data %d\n",pos);
+ //#endif
+ if (pos >=YPOS_MAX_D)
+ {
+ pos = YPOS_MAX_D;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_YUp[pos]; //Up cut edge
+ }
+ else
+ if ((YPOS_MAX_D - pos) <64)
+ {
+ pos = Cut_Edge_YDown[YPOS_MAX_D - pos]; //Down cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSD253X_SCREEN_MAX_Y * pos / (YPOS_MAX_D + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("Y: Cut edge data %d\n",pos);
+ //#endif
+ return pos;
+ }
+ return -1;
+}
+
+static int ssd253x_ts_cut_edge8(unsigned short pos,unsigned short x_y)
+{
+
+ #define XPOS_MAX_D (DRIVENO -EdgeDisable) *64
+ #define YPOS_MAX_D (SENSENO -EdgeDisable) *64
+ #undef SSD253X_SCREEN_MAX_X
+ #define SSD253X_SCREEN_MAX_X 780
+ #undef SSD253X_SCREEN_MAX_Y
+ #define SSD253X_SCREEN_MAX_Y 470
+
+ u8 cut_value = 10;//30; //cut_value < 32
+ unsigned short Cut_Edge_XLeft[64]={
+ 0x0008,0x0009,0x000B,0x000C,0x000D,0x000E,0x0010,0x0011,
+ 0x0012,0x0013,0x0015,0x0016,0x0017,0x0018,0x001A,0x001B,
+ 0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,0x0024,0x0025,
+ 0x0026,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,
+ 0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0032,
+ 0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0038,0x0039,
+ 0x003A,0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,
+ 0x0041,0x0042,0x0043,0x0044,0x0044,0x0045,0x0046,0x0047
+ };
+
+ unsigned short Cut_Edge_XRight[64]={
+ 0x0318,0x0317,0x0315,0x0314,0x0313,0x0312,0x0310,0x030F,
+ 0x030E,0x030D,0x030B,0x030A,0x0309,0x0308,0x0306,0x0305,
+ 0x0304,0x0303,0x0301,0x0300,0x02FF,0x02FE,0x02FC,0x02FB,
+ 0x02FA,0x02FA,0x02F9,0x02F8,0x02F7,0x02F6,0x02F5,0x02F4,
+ 0x02F4,0x02F3,0x02F2,0x02F1,0x02F0,0x02EF,0x02EE,0x02EE,
+ 0x02ED,0x02EC,0x02EB,0x02EA,0x02E9,0x02E8,0x02E8,0x02E7,
+ 0x02E6,0x02E5,0x02E4,0x02E3,0x02E2,0x02E2,0x02E1,0x02E0,
+ 0x02DF,0x02DE,0x02DD,0x02DC,0x02DC,0x02DB,0x02DA,0x02D9
+ };
+
+ unsigned short Cut_Edge_YUp[64]={
+ 0x0006,0x0007,0x0008,0x000A,0x000B,0x000C,0x000D,0x000F,
+ 0x0010,0x0011,0x0012,0x0014,0x0015,0x0016,0x0017,0x0018,
+ 0x001A,0x001B,0x001C,0x001D,0x001F,0x0020,0x0021,0x0022,
+ 0x0022,0x0023,0x0024,0x0025,0x0025,0x0026,0x0027,0x0028,
+ 0x0029,0x0029,0x002A,0x002B,0x002C,0x002C,0x002D,0x002E,
+ 0x002F,0x0030,0x0030,0x0031,0x0032,0x0033,0x0033,0x0034,
+ 0x0035,0x0036,0x0037,0x0037,0x0038,0x0039,0x003A,0x003A,
+ 0x003B,0x003C,0x003D,0x003E,0x003E,0x003F,0x0040,0x0041
+ };
+
+ unsigned short Cut_Edge_YDown[64]={
+ 0x01DA,0x01D9,0x01D8,0x01D6,0x01D5,0x01D4,0x01D3,0x01D1,
+ 0x01D0,0x01CF,0x01CE,0x01CC,0x01CB,0x01CA,0x01C9,0x01C8,
+ 0x01C6,0x01C5,0x01C4,0x01C3,0x01C1,0x01C0,0x01BF,0x01BE,
+ 0x01BE,0x01BD,0x01BC,0x01BB,0x01BB,0x01BA,0x01B9,0x01B8,
+ 0x01B7,0x01B7,0x01B6,0x01B5,0x01B4,0x01B4,0x01B3,0x01B2,
+ 0x01B1,0x01B0,0x01B0,0x01AF,0x01AE,0x01AD,0x01AD,0x01AC,
+ 0x01AB,0x01AA,0x01A9,0x01A9,0x01A8,0x01A7,0x01A6,0x01A6,
+ 0x01A5,0x01A4,0x01A3,0x01A2,0x01A2,0x01A1,0x01A0,0x019F
+ };
+
+
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("X: Raw data %d\n",pos);
+ //#endif
+ if (pos >=XPOS_MAX_D)
+ {
+ pos = XPOS_MAX_D;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_XLeft[pos]; //Left cut edge
+ }
+ else
+ if ((XPOS_MAX_D - pos) <64)
+ {
+ pos = Cut_Edge_XRight[XPOS_MAX_D - pos]; //Right cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSD253X_SCREEN_MAX_X * pos / (XPOS_MAX_D + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("X: Cut edge data %d\n",pos);
+ //#endif
+ return pos;
+ }
+ else //ypos
+ {
+
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("Y: Raw data %d\n",pos);
+ //#endif
+ if (pos >=YPOS_MAX_D)
+ {
+ pos = YPOS_MAX_D;
+ }
+ if (pos<64)
+ {
+ pos = Cut_Edge_YUp[pos]; //Up cut edge
+ }
+ else
+ if ((YPOS_MAX_D - pos) <64)
+ {
+ pos = Cut_Edge_YDown[YPOS_MAX_D - pos]; //Down cut edge
+ }
+ else
+ {
+ pos = pos + cut_value; //
+ pos = SSD253X_SCREEN_MAX_Y * pos / (YPOS_MAX_D + cut_value*2);//SSD253X_SCREEN_MAX_X|?????2????????|?
+ }
+ //#ifdef CONFIG_TS_CUTEDGE_DEBUG
+ dbg("Y: Cut edge data %d\n",pos);
+ //#endif
+ return pos;
+ }
+}
+
+static int ssd253x_ts_cut_edge7(unsigned short pos,unsigned short x_y)
+{
+ unsigned short SENSENO_7 = 15;
+ unsigned short DRIVENO_7 = 20;
+ unsigned short EdgeDisable_7 = 1; // if Edge Disable, set it to 1, else reset to 0, OR SSD2533 set 0
+ unsigned short XPOS_MAX_7 = (DRIVENO_7 -EdgeDisable_7) *64;
+ unsigned short YPOS_MAX_7 = (SENSENO_7 -EdgeDisable_7) *64;
+
+ u8 cut_value = 10; //cut_value < 32
+ dbg("enter...\n");
+
+ if(pos == 0xfff)
+ {
+ return pos;
+ }
+ if(x_y) //xpos
+ {
+ if(pos < 16)
+ pos = cut_value + pos*(48 - cut_value) / 16;
+ else if(pos > (XPOS_MAX_7 - 16) )
+ pos = XPOS_MAX_7 + 16 + (pos - (XPOS_MAX_7 -16))*(48 - cut_value) / 16;
+ else
+ pos = pos + 32;
+ dbg("xpos_b:%d\n", pos);
+ pos = SSDS53X_SCREEN_MAX_X * pos / (DRIVENO_7 * 64);
+ dbg("xpos_a:%d\n", pos);
+ return pos;
+ }
+ else //ypos
+ {
+ if(pos < 16)
+ pos = cut_value + pos*(48 - cut_value) / 16;
+ else if(pos > (YPOS_MAX_7 - 16) )
+ pos = YPOS_MAX_7 + 16 + (pos - (YPOS_MAX_7 -16))*(48 - cut_value) / 16;
+ else
+ pos = pos + 32;
+ dbg("ypos_b:%d\n", pos);
+ pos = SSDS53X_SCREEN_MAX_Y* pos / (SENSENO_7 * 64);
+ dbg("ypos_a:%d\n", pos);
+ return pos;
+ }
+
+
+}
+
+
+static int ssd253x_ts_cut_edge(unsigned short pos,unsigned short x_y)
+{
+ switch (wmt_ts_get_cutedge())
+ {
+ case 0:
+ return ssd253x_ts_cut_edge0(pos,x_y);
+ break;
+ case 1:
+ return ssd253x_ts_cut_edge1(pos,x_y);
+ break;
+ case 2:
+ return ssd253x_ts_cut_edge2(pos,x_y);
+ break;
+ case 3:
+ return ssd253x_ts_cut_edge3(pos,x_y);
+ break;
+ case 4:
+ return ssd253x_ts_cut_edge4(pos,x_y);
+ break;
+ case 5:
+ return ssd253x_ts_cut_edge5(pos,x_y);
+ break;
+ case 6:
+ return ssd253x_ts_cut_edge6(pos,x_y);
+ break;
+ case 7:
+ return ssd253x_ts_cut_edge7(pos,x_y);
+ break;
+ case 8:
+ return ssd253x_ts_cut_edge8(pos,x_y);
+ break;
+ default:
+ return -1;
+ };
+}
+
+#ifdef USE_TOUCH_KEY
+static u8 btn_status_last = 0;
+#endif
+
+static void ssd253x_ts_work(struct work_struct *work)
+{
+ int i;
+ unsigned short xpos=0, ypos=0;
+ int tx,ty;
+ //width=0;
+ int FingerInfo;
+ int EventStatus;
+ int FingerX[FINGERNO];
+ int FingerY[FINGERNO];
+ int FingerP[FINGERNO];
+ int clrFlag=0;
+ int Ssd_Timer;
+ #ifdef USE_TOUCH_KEY
+ u8 btn_status;
+ u8 btn_status_last = 0;
+ #endif
+
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ #ifdef USE_TOUCH_KEY
+ btn_status = ReadRegister(ssl_priv->client,SELFCAP_STATUS_REG, 1);
+ //#ifdef CONFIG_TOUCHSCREEN_SSL_DEBUG
+ dbg("btn pressed:%x\n", btn_status & 0x0f);
+ //#endif
+ if (btn_status_last != btn_status){
+ if(btn_status){
+ btn_status_last = btn_status;
+ ssd2533_ts_send_keyevent(ssl_priv,btn_status, 1);
+ dbg("send %x btn_status_last%d \n", btn_status,btn_status_last);
+ }
+ else{
+ ssd2533_ts_send_keyevent(ssl_priv,btn_status_last, 0);
+ btn_status_last = 0;
+ dbg("btn_status_last %x \n", btn_status_last);
+ }
+ return ;
+ }
+ #endif
+
+ Ssd_Timer = 0;
+ if(ic_flag == IC_SSD2533){
+ if(!Ssd_Timer_flag){
+ Ssd_Timer = ReadRegister(TIMESTAMP_REG,2);
+ if(!Ssd_Timer1){
+ Ssd_Timer1 = Ssd_Timer/1000;
+ }
+
+ Ssd_Timer2 = Ssd_Timer/1000;
+
+
+ if((Ssd_Timer2 - Ssd_Timer1) > 10){
+ WriteRegister(AUTO_INIT_RST_REG,0x00,0x00,1);
+ Ssd_Timer_flag = 1;
+ }
+ }
+ }
+
+ EventStatus = ReadRegister(EVENT_STATUS,2)>>4;
+ ssl_priv->FingerDetect=0;
+ for(i=0;i<ssl_priv->FingerNo;i++){
+ if((EventStatus>>i)&0x1){
+ FingerInfo=ReadRegister(FINGER01_REG+i,4);
+ xpos = ((FingerInfo>>4)&0xF00)|((FingerInfo>>24)&0xFF);
+ ypos = ((FingerInfo>>0)&0xF00)|((FingerInfo>>16)&0xFF);
+ dbg("raw data before cut, F%d:(%d,%d)\n",i,xpos,ypos);
+ if(xpos!=0xFFF){
+ ssl_priv->FingerDetect++;
+ if (wmt_ts_get_cutedge()>=0){
+ xpos = ssd253x_ts_cut_edge(xpos, 1);
+ ypos = ssd253x_ts_cut_edge(ypos, 0);
+ }
+ }else {
+ EventStatus=EventStatus&~(1<<i);
+ clrFlag=1;
+ }
+ }else{
+ xpos=ypos=0xFFF;
+ clrFlag=1;
+ }
+ FingerX[i]=xpos;
+ FingerY[i]=ypos;
+ }
+
+ if(ssl_priv->use_irq==1) wmt_enable_gpirq();
+ if(ssl_priv->use_irq==2)
+ {
+ if(ssl_priv->FingerDetect==0)
+ {
+ wmt_enable_gpirq();
+ } else {
+ hrtimer_start(&ssl_priv->timer, ktime_set(0, MicroTimeTInterupt), HRTIMER_MODE_REL);
+ }
+ }
+ if(ic_flag == IC_SSD2533){
+ if(clrFlag) WriteRegister(EVENT_FIFO_SCLR,0x01,0x00,1);
+ }
+
+ if(ssl_priv->input->id.product==0x2533)
+ if(ssl_priv->input->id.version==0x0101)
+ FingerCheckSwap(FingerX,FingerY,FingerP,ssl_priv->FingerNo,ssl_priv->sFingerX,ssl_priv->sFingerY);
+
+ // report data
+ for(i=0;i<ssl_priv->FingerNo;i++)
+ {
+ xpos=FingerX[i];
+ ypos=FingerY[i];
+ if(ssl_priv->input->id.product==0x2533){
+ if(ssl_priv->input->id.version==0x0101) RunningAverage(&xpos,&ypos,i,ssl_priv);
+ if(ssl_priv->input->id.version==0x0102) RunningAverage(&xpos,&ypos,i,ssl_priv);
+ }
+
+ if(xpos!=0xFFF)
+ {
+ dbg("raw data after cut, F%d:(%d,%d)\n",i,xpos,ypos);
+ switch (wmt_ts_get_xaxis())
+ {
+ case 1:
+ tx = ypos;
+ break;
+ case 0:
+ default:
+ tx = xpos;
+ break;
+ }
+
+ switch (wmt_ts_get_xdir())
+ {
+ case 1:
+ break;
+ case -1:
+ tx = SSDS53X_SCREEN_MAX_Y - tx;
+ break;
+ default:
+ break;
+ };
+
+ if (tx <0){
+ tx = 0;
+ } else if (tx >= SSDS53X_SCREEN_MAX_Y){
+ tx = SSDS53X_SCREEN_MAX_Y-1;
+ }
+ switch (wmt_ts_get_yaxis())
+ {
+
+ case 0:
+ ty = xpos;
+ break;
+ case 1:
+ default:
+ ty = ypos;
+ break;
+ }
+
+ switch (wmt_ts_get_ydir())
+ {
+ case 1:
+ break;
+ case -1:
+ ty = SSDS53X_SCREEN_MAX_X - ty;
+ default:
+ break;
+ }
+
+ if (ty < 0){
+ ty = 0;
+ } else if (ty >=SSDS53X_SCREEN_MAX_X){
+ ty = SSDS53X_SCREEN_MAX_X-1;
+ }
+
+ if (wmt_ts_get_lcdexchg()) {
+ int tmp;
+ tmp = tx;
+ tx = ty;
+ ty = wmt_ts_get_resolvX() - tmp;
+ }
+
+ ssd253x_tsdev.penup = 0;
+ input_report_abs(ssl_priv->input, ABS_MT_POSITION_X, tx);
+ input_report_abs(ssl_priv->input, ABS_MT_POSITION_Y, ty);
+ /*input_report_abs(ssl_priv->input, ABS_MT_POSITION_X, ty);
+ input_report_abs(ssl_priv->input, ABS_MT_POSITION_Y, tx);*/
+ input_mt_sync(ssl_priv->input);
+ dbg("report data x=%d,y=%d\n", tx, ty);
+
+ }
+ else if(ssl_priv->FingerX[i]!=0xFFF){
+ input_mt_sync(ssl_priv->input);
+ //printk("pen up...\n");
+ ssd253x_tsdev.penup = 1;
+ }
+
+ ssl_priv->FingerX[i]=FingerX[i];
+ ssl_priv->FingerY[i]=FingerY[i];
+ }
+
+ ssl_priv->EventStatus=EventStatus;
+ input_sync(ssl_priv->input);
+ if (1 == ssd253x_tsdev.penup){
+ wake_up(&ts_penup_wait_queue);
+ }
+
+}
+
+
+#define TPIC_INT_PLLLING 0
+#define TPIC_INT_INTERUPT 1
+#define TPIC_INT_HYBRID 2
+
+
+static int ssd253x_probe(struct platform_device *pdev)
+{
+ struct ssl_ts_priv *ssl_priv;
+ struct input_dev *ssl_input;
+ int error;
+ int i;
+ //unsigned int prescale;
+
+ //#ifdef SD_INIT
+ // g_tp_client = l_client;
+ //#endif
+
+ SSDS53X_SCREEN_MAX_X = wmt_ts_get_resolvY();
+ SSDS53X_SCREEN_MAX_Y = wmt_ts_get_resolvX();
+
+ ssl_priv = kzalloc(sizeof(*ssl_priv), GFP_KERNEL);
+ if (!ssl_priv)
+ {
+ errlog(" kzalloc Error!\n");
+ error=-ENODEV;
+ goto err0;
+ }
+ l_ts = ssl_priv;
+
+ ssl_input = input_allocate_device();
+ if (!ssl_input)
+ {
+ errlog(" ssd253x_ts_probe: input_allocate_device Error\n");
+ error=-ENODEV;
+ goto freealloc;
+ }
+ ssl_input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT_MASK(EV_SYN) ;
+ set_bit(INPUT_PROP_DIRECT,ssl_input->propbit);
+ ssl_input->name = DEVICE_NAME;
+ ssl_input->id.bustype = BUS_I2C;
+ ssl_input->id.vendor = 0x2878; // Modify for Vendor ID
+
+ ssl_priv->input = ssl_input;
+
+ ssl_priv->FingerNo=wmt_ts_get_fingernum();//FINGERNO;
+ ssl_priv->Resolution=64;
+
+ for(i=0;i<ssl_priv->FingerNo;i++)
+ {
+ ssl_priv->sFingerX[i]=0xFFF;
+ ssl_priv->sFingerY[i]=0xFFF;
+
+ // For Adaptive Running Average
+ ssl_priv->pFingerX[i]=0xFFF;
+ ssl_priv->pFingerY[i]=0xFFF;
+ }
+
+ deviceReset();
+ ssl_input->id.product = ReadRegister(DEVICE_ID_REG,2);
+ ssl_input->id.version = ReadRegister(VERSION_ID_REG,2);
+ ssl_input->id.product = ReadRegister(DEVICE_ID_REG,2);
+
+ ssl_input->id.version = ReadRegister(VERSION_ID_REG,2);
+ klog("SSL Touchscreen Device ID : 0x%04X\n",ssl_input->id.product);
+ klog("SSL Touchscreen Version ID : 0x%04X\n",ssl_input->id.version);
+
+ if(ssl_input->id.product == 0x2531){
+ ic_flag = IC_SSD2531;
+ }else if(ssl_input->id.product == 0x2533) {
+ ic_flag = IC_SSD2533;
+ }else if(ssl_input->id.product == 0x2543) {
+ ic_flag = IC_SSD2543;
+ }
+
+ if(ic_flag == IC_SSD2533) {
+ ssl_priv->use_irq = TPIC_INT_HYBRID;
+ }else if(ic_flag == IC_SSD2543) {
+ ssl_priv->use_irq = TPIC_INT_INTERUPT;
+ }
+
+ SSD253xdeviceInit();
+ if(ic_flag == IC_SSD2533) {
+ WriteRegister(EVENT_FIFO_SCLR,0x01,0x00,1); // clear Event FiFo
+ }
+
+
+ if(ssl_priv->input->id.product==0x2531)
+ ssl_priv->Resolution=32;
+ else if(ssl_priv->input->id.product==0x2533)
+ ssl_priv->Resolution=64;
+
+
+ if (wmt_ts_get_lcdexchg()) {
+ input_set_abs_params(ssl_input, ABS_MT_POSITION_X, 0,wmt_ts_get_resolvY(), 0, 0);
+ input_set_abs_params(ssl_input, ABS_MT_POSITION_Y, 0,wmt_ts_get_resolvX(), 0, 0);
+ } else {
+ input_set_abs_params(ssl_input, ABS_MT_POSITION_X, 0,wmt_ts_get_resolvX(), 0, 0);
+ input_set_abs_params(ssl_input, ABS_MT_POSITION_Y, 0,wmt_ts_get_resolvY(), 0, 0);
+ }
+
+#ifdef USE_TOUCH_KEY
+ set_bit(KEY_MENU, ssl_input->keybit);
+ set_bit(KEY_HOME, ssl_input->keybit);
+ set_bit(KEY_BACK, ssl_input->keybit);
+ set_bit(KEY_SEARCH, ssl_input->keybit);
+ #endif
+ error = input_register_device(ssl_input);
+ if(error)
+ {
+ errlog("input_register_device input Error!\n");
+ error=-ENODEV;
+ goto panel_init_fail;
+ }
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2))
+ {
+ hrtimer_init(&ssl_priv->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ssl_priv->timer.function = ssd253x_ts_timer;
+ //#ifdef CONFIG_TOUCHSCREEN_SSL_DEBUG
+ dbg(" ssd253x_ts_probe: timer_init OK!\n");
+ //#endif
+ }
+
+ ssd253x_wq = create_singlethread_workqueue("ssd253x_wq");
+ INIT_WORK(&ssl_priv->ssl_work, ssd253x_ts_work);
+ error = request_irq(wmt_get_tsirqnum(), ssd253x_ts_isr, IRQF_SHARED, "ssd253x_ts_q", l_ts);
+ if(error){
+ errlog("request_irq Error!\n");
+ error=-ENODEV;
+ goto freeque;
+ }
+
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ wmt_disable_gpirq();
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ssl_priv->early_suspend.suspend = ssd253x_ts_early_suspend;
+ ssl_priv->early_suspend.resume = ssd253x_ts_late_resume;
+ ssl_priv->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN+2;
+ register_early_suspend(&ssl_priv->early_suspend);
+#endif
+ deviceResume();
+ wmt_enable_gpirq();
+ dbg("SSD253X init ok!\n");
+ return 0;
+
+freeque:
+ destroy_workqueue(ssd253x_wq);
+ input_unregister_device(ssl_input);
+panel_init_fail:
+ input_free_device(ssl_input);
+freealloc:
+ kfree(ssl_priv);
+err0:
+ //dev_set_drvdata(&client->dev, NULL);
+ return error;
+}
+
+static int ssd253x_remove(struct platform_device *pdev)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2)) hrtimer_cancel(&ssl_priv->timer);
+
+ //disable int
+ wmt_disable_gpirq();
+ //free irq
+ free_irq(wmt_get_tsirqnum(), l_ts);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ssl_priv->early_suspend);
+#endif
+ // free queue
+ cancel_work_sync (&ssl_priv->ssl_work);
+ flush_workqueue(ssd253x_wq);
+ destroy_workqueue(ssd253x_wq);
+ input_unregister_device(ssl_priv->input);
+ input_free_device(ssl_priv->input);
+ kfree(ssl_priv);
+ l_ts = NULL;
+ return 0;
+}
+
+
+/*
+static int ssd253x_ts_open(struct input_dev *dev)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ deviceResume();
+ if(ssl_priv->use_irq)
+ {
+ wmt_enable_gpirq(); //(ssl_priv->irq);
+ } else {
+ hrtimer_start(&ssl_priv->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+ return 0;
+}
+
+
+static void ssd253x_ts_close(struct input_dev *dev)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ // disable interrupt
+ deviceSuspend();
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2))
+ hrtimer_cancel(&ssl_priv->timer);
+ if((ssl_priv->use_irq==1)||(ssl_priv->use_irq==2))
+ wmt_disable_gpirq();//(ssl_priv->irq);
+}
+*/
+static int ssd253x_resume(struct platform_device *pdev)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ wmt_disable_gpirq();
+ Ssd_Timer_flag = 0;
+ deviceReset();
+ SSD253xdeviceInit();
+ if(ic_flag == IC_SSD2533){
+ WriteRegister(EVENT_FIFO_SCLR,0x01,0x00,1); // clear Event FiFo
+ }
+ deviceResume();
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq();
+
+ if(! ssl_priv->use_irq)
+ {
+ hrtimer_start(&ssl_priv->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+ ssl_priv->earlysus = 0;
+ return 0;
+}
+
+static int ssd253x_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2)) hrtimer_cancel(&ssl_priv->timer);
+ // disable irq
+ wmt_disable_gpirq();
+ Ssd_Timer_flag = 0;
+ if(ic_flag == IC_SSD2533){
+ deviceSuspend();
+ }else if(ic_flag == IC_SSD2543){
+ deviceReset();
+ }
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ssd253x_ts_late_resume(struct early_suspend *h)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ dbg("...\n");
+ if (ssl_priv->earlysus != 0)
+ {
+ wmt_disable_gpirq();
+ Ssd_Timer_flag = 0;
+ deviceReset();
+ SSD253xdeviceInit();
+ WriteRegister(EVENT_FIFO_SCLR,0x01,0x00,1); // clear Event FiFo
+ deviceResume();
+ wmt_set_gpirq(IRQ_TYPE_EDGE_FALLING);
+ wmt_enable_gpirq();
+
+ if(! ssl_priv->use_irq)
+ {
+ hrtimer_start(&ssl_priv->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+ ssl_priv->earlysus = 0;
+ }
+}
+static void ssd253x_ts_early_suspend(struct early_suspend *h)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ ssl_priv->earlysus = 1;
+ if((ssl_priv->use_irq==0)||(ssl_priv->use_irq==2)) hrtimer_cancel(&ssl_priv->timer);
+ // disable irq
+ wmt_disable_gpirq();
+ Ssd_Timer_flag = 0;
+ deviceSuspend();
+
+ return;
+}
+#endif
+
+
+static irqreturn_t ssd253x_ts_isr(int irq, void *dev_id)
+{
+ struct ssl_ts_priv *ssl_priv = l_ts;
+
+ if (wmt_is_tsint())
+ {
+ wmt_clr_int();
+ if (wmt_is_tsirq_enable())
+ {
+ wmt_disable_gpirq();
+ dbg("begin..\n");
+ if(!ssl_priv->earlysus)
+ {
+ queue_work(ssd253x_wq, &ssl_priv->ssl_work);
+ }
+ }
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static enum hrtimer_restart ssd253x_ts_timer(struct hrtimer *timer)
+{
+ struct ssl_ts_priv *ssl_priv = container_of(timer, struct ssl_ts_priv, timer);
+ #ifdef CONFIG_TOUCHSCREEN_SSL_DEBUG
+ printk("+-----------------------------------------+\n");
+ printk("| ssd253x_ts_timer! |\n");
+ printk("+-----------------------------------------+\n");
+ #endif
+ queue_work(ssd253x_wq, &ssl_priv->ssl_work);
+ if(ssl_priv->use_irq==0) hrtimer_start(&ssl_priv->timer, ktime_set(0, MicroTimeTInterupt), HRTIMER_MODE_REL);
+ return HRTIMER_NORESTART;
+}
+
+#ifdef SD_INIT
+static const struct file_operations tp_fops = {
+ .owner = THIS_MODULE,
+ .read = tp_read,
+ .write = tp_write,
+ .unlocked_ioctl = tp_ioctl,
+ .open = tp_open,
+ .release = tp_release,
+};
+
+static struct miscdevice misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = TP_CHR,
+ .fops = &tp_fops,
+};
+#endif
+
+
+static int ssd253x_init(void)
+{
+ char firmwname[60];
+ int i;
+
+ if (deviceReset() != 0)
+ return -1;
+ memset(firmwname,0,sizeof(firmwname));
+ wmt_ts_get_firmwname(firmwname);
+ i = read_firmwarefile(firmwname,&ssd253xcfgTable,0x100);
+ if (i <= 0)
+ {
+ l_cfglen = sizeof(ssd253xcfgTable_default)/sizeof(ssd253xcfgTable_default[0]);
+ ssd253xcfgTable = ssd253xcfgTable_default;
+ dbg("Using the default configure!\n");
+ } else {
+ l_cfglen = i;
+ }
+ Resume[1].No = ssd253xcfgTable[l_cfglen-1].No;
+ Resume[1].Reg = ssd253xcfgTable[l_cfglen-1].Reg;
+ Resume[1].Data1 = ssd253xcfgTable[l_cfglen-1].Data1;
+ Resume[1].Data2 = ssd253xcfgTable[l_cfglen-1].Data2;
+ if (SSD253xdeviceInit()!= 0)
+ {
+ if (i > 0)
+ {
+ kfree(ssd253xcfgTable);
+ }
+ return -1;
+ }
+ // init hardware
+
+#ifdef SD_INIT
+ misc_register(&misc);
+#endif
+
+
+ return 0;
+}
+
+static void ssd253x_exit(void)
+{
+ klog("remove the module\n");
+
+#ifdef SD_INIT
+ misc_deregister(&misc);
+#endif
+
+
+ if (ssd253xcfgTable != ssd253xcfgTable_default)
+ {
+ kfree(ssd253xcfgTable);
+ }
+
+}
+
+static int ssd253x_wait_penup(struct wmtts_device*tsdev)
+{
+ int ret = wait_event_interruptible(
+ ts_penup_wait_queue,
+ (1==tsdev->penup));
+ return ret;
+}
+
+
+struct wmtts_device raysen_tsdev = {
+ .driver_name = "ssd253x_ts",
+ .ts_id = "SSD253X",
+ .init = ssd253x_init,
+ .exit = ssd253x_exit,
+ .probe = ssd253x_probe,
+ .remove = ssd253x_remove,
+ .suspend = ssd253x_suspend,
+ .resume = ssd253x_resume,
+ .wait_penup = ssd253x_wait_penup,
+ .penup = 1,
+};
+
+#ifdef SD_INIT
+static long tp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+static int tp_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static int tp_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static ssize_t tp_read(struct file *file, char __user *buf, size_t count,loff_t *offset)
+{
+ char *kbuf;
+ uint8_t reg;
+ int ByteNo;
+ int readValue;
+ int i;
+
+ kbuf = kmalloc(count,GFP_KERNEL);
+
+ if(copy_from_user(kbuf,buf,1)) {
+ printk("no enough memory!\n");
+ return -1;
+ }
+
+ reg = (uint8_t)kbuf[0];
+ ByteNo = count;
+
+ readValue = ReadRegister( /*g_tp_client, */reg, ByteNo);
+
+ for(i = 0;i < ByteNo;i++){
+ kbuf[i] = (readValue>>(8*i)) & 0xff;
+ }
+
+ if(copy_to_user(buf,kbuf,count)) {
+ printk("no enough memory!\n");
+ return -1;
+ }
+
+ kfree(kbuf);
+
+ return count;
+}
+
+static ssize_t tp_write(struct file *file, const char __user *buf,size_t count, loff_t *offset)
+{
+ char *kbuf;
+
+ kbuf = kmalloc(count,GFP_KERNEL);
+
+ if(copy_from_user(kbuf,buf,count)) {
+ printk("no enough memory!\n");
+ return -1;
+ }
+
+ if(kbuf[1] == 0x01){
+ wmt_rst_output(0);
+ mdelay(5);
+ wmt_rst_output(1);
+ mdelay(20);
+ }
+ else
+ {
+ WriteRegister(/*g_tp_client,*/kbuf[1],kbuf[2],kbuf[3],kbuf[0]);
+ }
+
+ kfree(kbuf);
+
+ return count;
+}
+
+#endif
+
+
+
+
+MODULE_AUTHOR("Solomon Systech Ltd - Design Technology, Icarus Choi");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ssd253x Touchscreen Driver 1.3");
diff --git a/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h b/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h
new file mode 100755
index 00000000..fe6edeae
--- /dev/null
+++ b/drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h
@@ -0,0 +1,28 @@
+/**************************************************************
+ʹÓÃÇ°×¢ÒâͨµÀÊý£¬Çý¶¯Ä¬ÈÏʹÓÃͨµÀÊÇsense
+´óÓÚdrive·ñÔòÐèÒª½«Ê¹Óõ½µÄDRIVENOÓëSENSENOµ÷»»
+´ËÇé¿ö°üÀ¨0x66ºÍ0x67¼Ä´æÆ÷£¬µ«²»±ØÐ޸ġ£
+***************************************************************/
+#ifndef __SSD253X_20125181742_TS_H__
+#define __SSD253X_20125181742_TS_H__
+#define DRIVENO 15
+#define SENSENO 10
+#define EdgeDisable 1 // if Edge Disable, set it to 1, else reset to 0
+#define RunningAverageMode 2 //{0,8},{5,3},{6,2},{7,1}
+#define RunningAverageDist 4 // Threshold Between two consecutive points
+#define MicroTimeTInterupt 10000000 //20000000// 100Hz - 10,000,000us
+#define FINGERNO 10
+
+//#define USE_TOUCH_KEY
+
+#define USE_CUT_EDGE //0x8b must be 0x00; EdgeDisable set 0
+//#undef USE_CUT_EDGE
+
+#ifdef USE_CUT_EDGE
+ #define XPOS_MAX 576 //(DRIVENO - EdgeDisable) *64
+ #define YPOS_MAX 896 //(SENSENO - EdgeDisable) *64
+#endif
+
+
+
+#endif
diff --git a/drivers/input/touchscreen/ssd253x_ts/wmt_ts.c b/drivers/input/touchscreen/ssd253x_ts/wmt_ts.c
new file mode 100755
index 00000000..cf63ca13
--- /dev/null
+++ b/drivers/input/touchscreen/ssd253x_ts/wmt_ts.c
@@ -0,0 +1,810 @@
+#include <linux/unistd.h>
+#include <linux/time.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+//#include <asm/semaphore.h>
+#include <linux/proc_fs.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/proc_fs.h>
+#include <linux/input.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+
+#include <asm/uaccess.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+
+
+#include "wmt_ts.h"
+#include "ssd253x-ts.h"
+
+/////////////////////////////////////////////////////////////////
+
+// commands for ui
+#define TS_IOC_MAGIC 't'
+
+#define TS_IOCTL_CAL_START _IO(TS_IOC_MAGIC, 1)
+#define TS_IOCTL_CAL_DONE _IOW(TS_IOC_MAGIC, 2, int*)
+#define TS_IOCTL_GET_RAWDATA _IOR(TS_IOC_MAGIC, 3, int*)
+#define TS_IOCTL_CAL_QUIT _IOW(TS_IOC_MAGIC, 4, int*)
+#define TS_IOCTL_AUTO_CALIBRATION _IOW(TS_IOC_MAGIC, 5, int*)
+#define TS_IOC_MAXNR 5
+
+//
+#define TS_MAJOR 11
+#define TS_DRIVER_NAME "wmtts_touch"
+#define TS_NAME "wmtts"
+#define WMTTS_PROC_NAME "wmtts_config"
+
+#define EXT_GPIO0 0
+#define EXT_GPIO1 1
+#define EXT_GPIO2 2
+#define EXT_GPIO3 3
+#define EXT_GPIO4 4
+#define EXT_GPIO5 5
+#define EXT_GPIO6 6
+#define EXT_GPIO7 7
+
+typedef struct {
+ int a1;
+ int b1;
+ int c1;
+ int a2;
+ int b2;
+ int c2;
+ int delta;
+}CALIBRATION_PARAMETER, *PCALIBRATION_PARAMETER;
+
+
+static int lcd_exchg = 0;
+static int irq_gpio;
+static int rst_gpio;
+static int panelres_x;
+static int panelres_y;
+static int l_xaxis=0;
+static int l_xdirect=1;
+static int l_yaxis=1;
+static int l_ydirect=1;
+static int l_cutedge=-1;
+static DECLARE_WAIT_QUEUE_HEAD(queue);
+static CALIBRATION_PARAMETER g_CalcParam;
+static TS_EVENT g_evLast;
+static struct mutex cal_mutex;
+static DECLARE_WAIT_QUEUE_HEAD(ts_penup_wait_queue);
+
+extern struct wmtts_device raysen_tsdev;
+static struct wmtts_device* l_tsdev = &raysen_tsdev;
+static struct i2c_client *l_client=NULL;
+static int l_penup = 0; // 1-pen up,0-pen down
+static char l_firmid[21];
+
+/////////////////////////////////////////////////////
+// function declare
+/////////////////////////////////////////////////////
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+
+///////////////////////////////////////////////////////////////////////
+void TouchPanelCalibrateAPoint(
+ int UncalX, //@PARM The uncalibrated X coordinate
+ int UncalY, //@PARM The uncalibrated Y coordinate
+ int *pCalX, //@PARM The calibrated X coordinate
+ int *pCalY //@PARM The calibrated Y coordinate
+ )
+{
+ int x, y;
+ mutex_lock(&cal_mutex);
+ x = (g_CalcParam.a1 * UncalX + g_CalcParam.b1 * UncalY +
+ g_CalcParam.c1) / g_CalcParam.delta;
+ y = (g_CalcParam.a2 * UncalX + g_CalcParam.b2 * UncalY +
+ g_CalcParam.c2) / g_CalcParam.delta;
+
+//klog("afer(%d,%d)(%d,%d)\n", x,y,panelres_x,panelres_y);
+ if ( x < 0 )
+ x = 0;
+
+ if ( y < 0 )
+ y = 0;
+ if (x >= panelres_x)
+ x = panelres_x-1;
+ if (y >= panelres_y)
+ y = panelres_y-1;
+
+ *pCalX = x;
+ *pCalY = y;
+ mutex_unlock(&cal_mutex);
+ return;
+}
+
+static int parse_firmwarefile(const char* filedata, struct ChipSetting** firmarr, int maxlen)
+{
+ char endflag[]="/* End flag */";
+ const char* p = filedata;
+ int val[4];
+ int i = 0;
+ int j = 0;
+ const char* s = NULL;
+
+ // the first {
+ while (*p!='{') p++;
+ p++;
+ s = p;
+ // calculate the number of array
+ while (strncmp(p,endflag,strlen(endflag)))
+ {
+ if (*p=='{')
+ {
+ i++;
+ }
+ p++;
+ };
+ dbg("the number of arry:0x%x\n", i);
+ // alloc the memory for array
+ *firmarr = kzalloc(sizeof(struct ChipSetting)*i, GFP_KERNEL);
+ // parse the value of array
+ p = s;
+ j = 0;
+ while (strncmp(p,endflag,strlen(endflag)))
+ {
+ if (*p=='{')
+ {
+ memset(val,0,sizeof(val));
+ sscanf(p,"{%x,%x,%x,%x}",val,val+1,val+2,val+3);
+ (*firmarr)[j].No = val[0]&0x00FF;
+ (*firmarr)[j].Reg = val[1]&0x00FF;
+ (*firmarr)[j].Data1 = val[2]&0x00FF;
+ (*firmarr)[j].Data2 = val[3]&0x00FF;
+ dbg("arry[0x%x]:%x,%x,%x,%x\n",j,(*firmarr)[j].No,(*firmarr)[j].Reg,(*firmarr)[j].Data1,
+ (*firmarr)[j].Data2);
+ j++;
+ }
+ //p = strchr(p,'}');
+ p++;
+ if (j>=i-2)
+ {
+ dbg("%s",p);
+ }
+
+ };
+ if (i != j)
+ {
+ errlog("Error parsing file(the number of arry not match)!\n");
+ return -1;
+ };
+ dbg("paring firmware file end.\n");
+ return i;
+}
+
+
+static struct device* get_tp_device(void){
+ if(l_client == NULL){
+ errlog("l_client is NULL\n");
+ }
+ return &l_client->dev;
+}
+
+
+//filepath:the path of firmware file;
+//firmdata:store the data from firmware file;
+//maxlen: the max len of firmdata;
+//return:the number of firmware data,negative-parsing error.
+int read_firmwarefile(char* filepath, struct ChipSetting** firmdata, int maxlen)
+{
+ const u8 *data = NULL;
+ int i = 0;
+ int ret = -1;
+ const struct firmware* tpfirmware = NULL;
+
+ klog("ts config file:%s\n",filepath);
+
+
+ ret = request_firmware(&tpfirmware, filepath, get_tp_device());
+ if (ret < 0) {
+ errlog("Failed load tp firmware: %s ret=%d\n", filepath,ret);
+ goto err_end;
+ }
+
+ data = tpfirmware->data;
+
+ i = parse_firmwarefile(data,firmdata,maxlen);
+ if (i <= 0)
+ {
+ errlog("error to parse firmware file.\n");
+ ret = -1;
+ goto error_parse_fw;
+ }
+ ret = i;
+
+
+ dbg("success to read firmware file!\n");;
+
+error_parse_fw:
+ if(tpfirmware){
+ release_firmware(tpfirmware);
+ tpfirmware = NULL;
+ }
+err_end:
+ return ret;
+}
+
+
+ int wmt_ts_get_gpionum(void)
+{
+ return irq_gpio;
+}
+
+int wmt_ts_get_resetgpnum(void)
+{
+ return rst_gpio;
+}
+
+int wmt_ts_get_lcdexchg(void)
+{
+ return lcd_exchg;
+}
+
+int wmt_ts_get_resolvX(void)
+{
+ return panelres_x;
+}
+
+int wmt_ts_get_resolvY(void)
+{
+ return panelres_y;
+}
+
+int wmt_ts_get_xaxis(void)
+{
+ return l_xaxis;
+}
+
+int wmt_ts_get_xdir(void)
+{
+ return l_xdirect;
+}
+
+int wmt_ts_get_yaxis(void)
+{
+ return l_yaxis;
+}
+
+int wmt_ts_get_ydir(void)
+{
+ return l_ydirect;
+}
+
+int wmt_ts_get_cutedge(void)
+{
+ return l_cutedge;
+}
+
+void wmt_ts_get_firmwname(char* firmname)
+{
+ sprintf(firmname,"ssd253x_%s_cfg.tpf",l_firmid);
+}
+
+int wmt_ts_get_fingernum(void)
+{
+ if (!strcmp(l_firmid,"10rs10f1609043psy1"))
+ {
+ return 10;
+ }
+ return 5;
+}
+
+//up:1-pen up,0-pen down
+void wmt_ts_set_penup(int up)
+{
+ l_penup = up;
+}
+
+//
+int wmt_ts_wait_penup(void)
+{
+ int ret = wait_event_interruptible(
+ ts_penup_wait_queue,
+ (1==l_penup));
+ return ret;
+}
+
+// return:1-pen up,0-pen dwon
+int wmt_ts_ispenup(void)
+{
+ return l_penup;
+}
+
+
+void wmt_ts_wakeup_penup(void)
+{
+ wake_up(&ts_penup_wait_queue);
+}
+
+int wmt_is_tsirq_enable(void)
+{
+ int val = 0;
+ int num = irq_gpio;
+
+ if(num > 11)
+ return 0;
+
+ if(num<4)
+ val = REG32_VAL(__GPIO_BASE+0x0300) & (1<<(num*8+7));
+ else if(num >= 4 && num < 8)
+ val = REG32_VAL(__GPIO_BASE+0x0304) & (1<<((num-4)*8+7));
+ else
+ val = REG32_VAL(__GPIO_BASE+0x0308) & (1<<((num-8)*8+7));
+
+ return val?1:0;
+
+}
+
+int wmt_is_tsint(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return 0;
+ }
+ return (REG32_VAL(__GPIO_BASE+0x0360) & (1<<num)) ? 1: 0;
+}
+
+void wmt_clr_int(void)
+{
+ int num = irq_gpio;
+
+ if (num > 11)
+ {
+ return;
+ }
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num;
+}
+
+void wmt_tsreset_init(void)
+{
+ int num = rst_gpio;
+
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num);//&= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<num); // out low
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<num); //output enable
+ msleep(10);
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<num); // out high
+}
+
+// enable:0-disable,1-enable
+void wmt_enable_rst_pull(int enable)
+{
+ if (enable)
+ {
+ REG32_VAL(__GPIO_BASE+0x0480) |= (1<<rst_gpio); //enable pull up/down
+ } else {
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<rst_gpio); //disable pull up/down
+ }
+}
+
+// up:0-pull down,1-pull up
+void wmt_set_rst_pull(int up)
+{
+ if (up)
+ {
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<rst_gpio); //pull up
+ } else {
+ REG32_VAL(__GPIO_BASE+0x04c0) &= ~(1<<rst_gpio); //pull down
+ }
+}
+
+// high:0-low level,1-high level
+void wmt_rst_output(int high)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ if (high)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<rst_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<rst_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<rst_gpio); //set output
+}
+
+void wmt_rst_input(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<rst_gpio); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<rst_gpio); //set input
+}
+
+void wmt_set_intasgp(void)
+{
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<irq_gpio); //enable gpio
+}
+
+// val:1--high,0-low
+void wmt_intgp_out(int val)
+{
+ if (val)
+ {
+ REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<irq_gpio); // high
+ } else {
+ REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<irq_gpio); // low
+ }
+ REG32_VAL(__GPIO_BASE+0x0080) |= (1<<irq_gpio); //set output
+}
+
+void wmt_ts_set_irqinput(void)
+{
+ int num = irq_gpio;
+
+ REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+}
+
+unsigned int wmt_ts_irqinval(void)
+{
+ return REG32_VAL(__GPIO_BASE+0x0000)&(1<<irq_gpio);
+}
+
+int wmt_set_gpirq(int type)
+{
+ int shift;
+ int offset;
+ unsigned long reg;
+ int num = irq_gpio;
+
+ if(num >11)
+ return -1;
+ //if (num > 9)
+ //GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4; // gpio10,11 as gpio
+ REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num); //enable gpio
+ REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input
+ REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull down
+ REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down
+
+ //set gpio irq triger type
+ if(num < 4){//[0,3]
+ shift = num;
+ offset = 0x0300;
+ }else if(num >= 4 && num < 8){//[4,7]
+ shift = num-4;
+ offset = 0x0304;
+ }else{// [8,11]
+ shift = num-8;
+ offset = 0x0308;
+ }
+
+ reg = REG32_VAL(__GPIO_BASE + offset);
+
+ switch(type){
+ case IRQ_TYPE_LEVEL_LOW:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ reg &= ~(1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+ case IRQ_TYPE_EDGE_RISING:
+ reg &= ~(1<<(shift*8+2));
+ reg |= (1<<(shift*8+1));
+ reg |= (1<<(shift*8));
+ break;
+ default://both edge
+ reg |= (1<<(shift*8+2));
+ reg &= ~(1<<(shift*8+1));
+ reg &= ~(1<<(shift*8));
+ break;
+
+ }
+ //reg |= 1<<(shift*8+7);//enable interrupt
+ reg &= ~(1<<(shift*8+7)); //disable int
+
+ REG32_VAL(__GPIO_BASE + offset) = reg;
+ REG32_VAL(__GPIO_BASE+0x0360) = 1<<num; //clear interrupt status
+ msleep(5);
+ return 0;
+}
+
+int wmt_enable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) |= 1<<(num*8+7); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) |= 1<<((num-4)*8+7); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) |= 1<<((num-8)*8+7); //enable interrupt
+
+ return 0;
+}
+
+int wmt_disable_gpirq(void)
+{
+ int num = irq_gpio;
+
+ if(num > 11)
+ return -1;
+
+ if(num<4)
+ REG32_VAL(__GPIO_BASE+0x0300) &= ~(1<<(num*8+7)); //enable interrupt
+ else if(num >= 4 && num < 8)
+ REG32_VAL(__GPIO_BASE+0x0304) &= ~(1<<((num-4)*8+7)); //enable interrupt
+ else
+ REG32_VAL(__GPIO_BASE+0x0308) &= ~(1<<((num-8)*8+7)); //enable interrupt
+
+ return 0;
+}
+
+
+int wmt_get_tsirqnum(void)
+{
+ return IRQ_GPIO;
+}
+
+
+int wmt_ts_set_rawcoord(unsigned short x, unsigned short y)
+{
+ g_evLast.x = x;
+ g_evLast.y = y;
+ //dbg("raw(%d,%d)*\n", x, y);
+ return 0;
+}
+
+static void wmt_ts_platform_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device wmt_ts_plt_device = {
+ .name = TS_DRIVER_NAME,
+ .id = 0,
+ .dev = {
+ .release = wmt_ts_platform_release,
+ },
+// .num_resources = ARRAY_SIZE(wm9715_ts_resources),
+// .resource = wm9715_ts_resources,
+};
+
+static int wmt_ts_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dbg("ts suspend....\n");
+ return l_tsdev->suspend(pdev, state);
+}
+static int wmt_ts_resume(struct platform_device *pdev)
+{
+ dbg("ts resume....\n");
+ return l_tsdev->resume(pdev);
+}
+
+static int wmt_ts_probe(struct platform_device *pdev)
+{
+
+ if (l_tsdev->probe != NULL)
+ return l_tsdev->probe(pdev);
+ else
+ return 0;
+}
+
+static int wmt_ts_remove(struct platform_device *pdev)
+{
+
+ if (l_tsdev->remove != NULL)
+ return l_tsdev->remove(pdev);
+ else
+ return 0;
+}
+
+static struct platform_driver wmt_ts_plt_driver = {
+ .driver = {
+ .name = TS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = wmt_ts_probe,
+ .remove = wmt_ts_remove,
+ .suspend = wmt_ts_suspend,
+ .resume = wmt_ts_resume,
+};
+
+static int wmt_check_touch_env(void)
+{
+ int ret = 0;
+ int len = 150;
+ char retval[150] = {0},*p=NULL;
+ int Enable=0,Gpio=0,PX=0,PY=0;
+ char* s=NULL;
+
+ // Get u-boot parameter
+ ret = wmt_getsyspara("wmt.io.touch", retval, &len);
+ if(ret){
+ errlog("Read wmt.io.touch Failed.\n");
+ return -EIO;
+ }
+ sscanf(retval,"%d:",&Enable);
+ //check touch enable
+ if(Enable == 0){
+ errlog("Touch Screen Is Disabled.\n");
+ return -ENODEV;
+ }
+
+ p = strchr(retval,':');
+ p++;
+ if(strncmp(p, l_tsdev->ts_id,strlen(l_tsdev->ts_id))){//check touch ID
+ errlog("[WMTENV] %s is not found\n", l_tsdev->ts_id);
+ return -ENODEV;
+ }
+ // get firmwareid
+ s = p+strlen(l_tsdev->ts_id)+1; //point to firmware id
+ p = strchr(p,':');
+ memset(l_firmid,0,sizeof(l_firmid));
+ len = p-s;
+ if (len>=20)
+ {
+ len = 19;
+ }
+ strncpy(l_firmid,s,len);
+ p++;
+ sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%d",&Gpio,&PX,&PY,&rst_gpio,
+ &l_xaxis,&l_xdirect,
+ &l_yaxis,&l_ydirect,
+ &l_cutedge);
+
+ irq_gpio = Gpio;
+ panelres_x = PX;
+ panelres_y = PY;
+ dbg("p.x=%d,p.y=%d,gpio=%d,resetgpio=%d,\nx-axis=%d,x_dir=%d,y-axis=%d,y_dir=%d,cutedge=%d\nfirmwareid:%s\n",
+ panelres_x, panelres_y, irq_gpio, rst_gpio,
+ l_xaxis,l_xdirect,l_yaxis,l_ydirect,l_cutedge,
+ l_firmid);
+
+ memset(retval,0,sizeof(retval));
+ ret = wmt_getsyspara("wmt.display.fb0", retval, &len);
+ if (!ret) {
+ int tmp[6];
+ p = retval;
+ sscanf(p, "%d:[%d:%d:%d:%d:%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]);
+ if (tmp[4] > tmp[5])
+ lcd_exchg = 1;
+ }
+
+ return 0;
+}
+
+struct i2c_board_info ts_i2c_board_info = {
+ .type = WMT_TS_I2C_NAME,
+ .flags = 0x00,
+ .addr = WMT_TS_I2C_ADDR,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+static int ts_i2c_register_device (void)
+{
+ struct i2c_board_info *ts_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ //struct i2c_client *client = NULL;
+ ts_i2c_bi = &ts_i2c_board_info;
+ adapter = i2c_get_adapter(1);/*in bus 1*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ l_client = i2c_new_device(adapter, ts_i2c_bi);
+ if (l_client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+static void ts_i2c_unregister_device(void)
+{
+ if (l_client != NULL)
+ {
+ i2c_unregister_device(l_client);
+ l_client = NULL;
+ }
+}
+
+struct i2c_client* ts_get_i2c_client(void)
+{
+ return l_client;
+}
+
+static int __init wmt_ts_init(void)
+{
+ int ret = 0;
+
+ if(wmt_check_touch_env())
+ return -ENODEV;
+
+ if (ts_i2c_register_device()<0)
+ {
+ dbg("Error to run ts_i2c_register_device()!\n");
+ return -1;
+ }
+ mutex_init(&cal_mutex);
+
+ if (l_tsdev->init() < 0){
+ dbg("Errors to init %s ts IC!!!\n", l_tsdev->ts_id);
+ ret = -1;
+ goto err_init;
+ }
+ // Create device node
+/* if (register_chrdev (TS_MAJOR, TS_NAME, &wmt_ts_fops)) {
+ printk (KERN_ERR "wmt touch: unable to get major %d\n", TS_MAJOR);
+ return -EIO;
+ }
+
+ l_dev_class = class_create(THIS_MODULE, TS_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create touch device !!\n");
+ return ret;
+ }
+ l_clsdevice = device_create(l_dev_class, NULL, MKDEV(TS_MAJOR, 0), NULL, TS_NAME);
+ if (IS_ERR(l_clsdevice)){
+ ret = PTR_ERR(l_clsdevice);
+ printk(KERN_ERR "Failed to create device %s !!!",TS_NAME);
+ return ret;
+ }
+*/
+ // register device and driver of platform
+ ret = platform_device_register(&wmt_ts_plt_device);
+ if(ret){
+ errlog("wmt ts plat device register failed!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&wmt_ts_plt_driver);
+ if(ret){
+ errlog("can not register platform_driver_register\n");
+ platform_device_unregister(&wmt_ts_plt_device);
+ return ret;
+ }
+
+ klog("%s driver init ok!\n",l_tsdev->ts_id);
+ return 0;
+err_init:
+ ts_i2c_unregister_device();
+ return ret;
+}
+
+static void __exit wmt_ts_exit(void)
+{
+ dbg("%s\n",__FUNCTION__);
+
+ l_tsdev->exit();
+ platform_driver_unregister(&wmt_ts_plt_driver);
+ platform_device_unregister(&wmt_ts_plt_device);
+ //device_destroy(l_dev_class, MKDEV(TS_MAJOR, 0));
+ //unregister_chrdev(TS_MAJOR, TS_NAME);
+ //class_destroy(l_dev_class);
+ mutex_destroy(&cal_mutex);
+ ts_i2c_unregister_device();
+}
+
+
+module_init(wmt_ts_init);
+module_exit(wmt_ts_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/touchscreen/ssd253x_ts/wmt_ts.h b/drivers/input/touchscreen/ssd253x_ts/wmt_ts.h
new file mode 100755
index 00000000..3506773a
--- /dev/null
+++ b/drivers/input/touchscreen/ssd253x_ts/wmt_ts.h
@@ -0,0 +1,116 @@
+
+#ifndef WMT_TSH_201010191758
+#define WMT_TSH_201010191758
+
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/i2c.h>
+#include <linux/firmware.h>
+
+
+//#define DEBUG_WMT_TS
+#undef dbg
+#ifdef DEBUG_WMT_TS
+#define dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args)
+#else
+#define dbg(fmt, args...)
+#endif
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk("[%s]: " fmt, __FUNCTION__, ## args)
+
+#define WMT_TS_I2C_NAME "ssd253x-ts"
+#define WMT_TS_I2C_ADDR 0x01
+
+//////////////////////////////data type///////////////////////////
+typedef struct {
+ short pressure;
+ short x;
+ short y;
+ //short millisecs;
+} TS_EVENT;
+
+struct wmtts_device
+{
+ //data
+ char* driver_name;
+ char* ts_id;
+ //function
+ int (*init)(void);
+ int (*probe)(struct platform_device *platdev);
+ int (*remove)(struct platform_device *pdev);
+ void (*exit)(void);
+ int (*suspend)(struct platform_device *pdev, pm_message_t state);
+ int (*resume)(struct platform_device *pdev);
+ int (*capacitance_calibrate)(void);
+ int (*wait_penup)(struct wmtts_device*tsdev); // waiting untill penup
+ int penup; // 0--pendown;1--penup
+
+};
+
+struct ChipSetting {
+ char No;
+ char Reg;
+ char Data1;
+ char Data2;
+};
+
+
+//////////////////////////function interface/////////////////////////
+extern int wmt_ts_get_gpionum(void);
+extern int wmt_ts_iscalibrating(void);
+extern int wmt_ts_get_resolvX(void);
+extern int wmt_ts_get_resolvY(void);
+extern int wmt_ts_set_rawcoord(unsigned short x, unsigned short y);
+extern int wmt_set_gpirq(int type);
+extern int wmt_get_tsirqnum(void);
+extern int wmt_disable_gpirq(void);
+extern int wmt_enable_gpirq(void);
+extern int wmt_is_tsirq_enable(void);
+extern int wmt_is_tsint(void);
+extern void wmt_clr_int(void);
+extern void wmt_tsreset_init(void);
+extern int wmt_ts_get_resetgpnum(void);
+extern int wmt_ts_get_lcdexchg(void);
+extern void wmt_enable_rst_pull(int enable);
+extern void wmt_set_rst_pull(int up);
+extern void wmt_rst_output(int high);
+extern void wmt_rst_input(void);
+extern void wmt_set_intasgp(void);
+extern void wmt_intgp_out(int val);
+extern void wmt_ts_set_irqinput(void);
+extern unsigned int wmt_ts_irqinval(void);
+extern void wmt_ts_set_penup(int up);
+extern int wmt_ts_wait_penup(void);
+extern void wmt_ts_wakeup_penup(void);
+extern struct i2c_client* ts_get_i2c_client(void);
+extern int wmt_ts_ispenup(void);
+extern int wmt_ts_get_xaxis(void);
+extern int wmt_ts_get_xdir(void);
+extern int wmt_ts_get_yaxis(void);
+extern int wmt_ts_get_ydir(void);
+extern int wmt_ts_get_cutedge(void);
+extern void wmt_ts_get_firmwname(char* firmname);
+extern int wmt_ts_get_fingernum(void);
+
+extern void TouchPanelCalibrateAPoint(
+ int UncalX, //@PARM The uncalibrated X coordinate
+ int UncalY, //@PARM The uncalibrated Y coordinate
+ int *pCalX, //@PARM The calibrated X coordinate
+ int *pCalY //@PARM The calibrated Y coordinate
+ );
+
+//filepath:the path of firmware file;
+//firmdata:store the data from firmware file;
+//maxlen: the max len of firmdata;
+//return:the number of firmware data,negative-parsing error.
+extern int read_firmwarefile(char* filepath, struct ChipSetting** firmdata, int maxlen);
+
+#endif
+
+
+