From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001 From: Srikant Patnaik Date: Sun, 11 Jan 2015 12:28:04 +0530 Subject: Moved, renamed, and deleted files The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure. --- drivers/input/touchscreen/ssd253x_ts/Kconfig | 16 + drivers/input/touchscreen/ssd253x_ts/Makefile | 32 + drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c | 1827 +++++++++++++++++++++ drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h | 28 + drivers/input/touchscreen/ssd253x_ts/wmt_ts.c | 810 +++++++++ drivers/input/touchscreen/ssd253x_ts/wmt_ts.h | 116 ++ 6 files changed, 2829 insertions(+) create mode 100755 drivers/input/touchscreen/ssd253x_ts/Kconfig create mode 100755 drivers/input/touchscreen/ssd253x_ts/Makefile create mode 100755 drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.c create mode 100755 drivers/input/touchscreen/ssd253x_ts/ssd253x-ts.h create mode 100755 drivers/input/touchscreen/ssd253x_ts/wmt_ts.c create mode 100755 drivers/input/touchscreen/ssd253x_ts/wmt_ts.h (limited to 'drivers/input/touchscreen/ssd253x_ts') 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 +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#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 +#include +#include + +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 = ® + + 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;ipFingerX[No]!=0x0FFF)&&(X!=0x0FFF)) + { + dx=abs(ssl_priv->pFingerX[No]-X); + dy=abs(ssl_priv->pFingerY[No]-Y); + if(dx+dypFingerX[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;iR2x+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;iinput, 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;iFingerNo;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<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;iFingerNo;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;iFingerNo;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 +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#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< 11) + { + return; + } + REG32_VAL(__GPIO_BASE+0x0360) = 1<11) + return -1; + //if (num > 9) + //GPIO_PIN_SHARING_SEL_4BYTE_VAL &= ~BIT4; // gpio10,11 as gpio + REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<= 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< 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 +#include +#include +#include +#include +#include + + +//#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 + + + -- cgit