diff options
Diffstat (limited to 'drivers/input/touchscreen/lw86x0_ts/wmt_ts.c')
-rwxr-xr-x | drivers/input/touchscreen/lw86x0_ts/wmt_ts.c | 1165 |
1 files changed, 1165 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/lw86x0_ts/wmt_ts.c b/drivers/input/touchscreen/lw86x0_ts/wmt_ts.c new file mode 100755 index 00000000..505dedfd --- /dev/null +++ b/drivers/input/touchscreen/lw86x0_ts/wmt_ts.c @@ -0,0 +1,1165 @@ +#include <linux/unistd.h> +#include <linux/time.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.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>//add +#include "wmt_ts.h" +#include "lw86x0_ts.h" +//#include "wmt_custom_lw86x0.h" + + +struct i2c_client *l_client = NULL; + + + +///////////////////////////////////////////////////////////////// + +// commands for ui +#define TS_IOC_MAGIC 't' +#define LW86X0_READ_REG _IOWR(TS_IOC_MAGIC, 1, int*) +#define LW86X0_WRITE_REG _IOW(TS_IOC_MAGIC, 2, int*) +#define LW86X0_FLASH_DOWNLOAD _IOW(TS_IOC_MAGIC, 3, int *) +#define LW86X0_FLASH_UPLOAD _IOWR(TS_IOC_MAGIC, 4, int *) +#define LW86X0_CTRL_DEBUG_MODE _IOW(TS_IOC_MAGIC, 5, int *) +#define LW86X0_CTRL_RD_DIFF _IOR(TS_IOC_MAGIC, 6, int *) +#define LW86X0_CTRL_RD_CDC _IOR(TS_IOC_MAGIC, 7, int *) +#define LW86X0_CTRL_RD_AMB _IOR(TS_IOC_MAGIC, 8, int *) +#define LW86X0_CTRL_STOP_TIMER _IOR(TS_IOC_MAGIC, 15, int *) +#define TS_IOC_MAXNR 15 + +// +#define TS_MAJOR 11 +#define TS_DRIVER_NAME "wmtts_touch" +#define TS_NAME "wmtts" +#define WMTTS_PROC_NAME "wmtts_config" + +#define LIGHT_ON_WAIT_TIME 5000 // 5s + +#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 + +struct touch_tp_info { + char name[64]; + unsigned int i2caddr; + int xaxis; // 0:x,1:x swap with y + int xdir; // 1:positive,-1:revert + int ydir; // 1:positive,-1:revert + int finger_num; +}; + + +static struct touch_tp_info l_tp[] = { + {"LW86X0",(0x30>>1), 0, 1, 1}, +}; + +static int irq_gpio; +static int rst_gpio; +static int keyled_gpio = -1; +static int light_level; +static int light_time = 5000; // unit: ms +static int panelres_x; +static int panelres_y; +static int lcd_exchg = 0; +static DECLARE_WAIT_QUEUE_HEAD(queue); +static TS_EVENT g_evLast; +static struct mutex cal_mutex; + +static struct class* l_dev_class = NULL; +static struct device *l_clsdevice = NULL; +extern struct wmtts_device lw86x0_tsdev; +static struct wmtts_device* l_tsdev = &lw86x0_tsdev; +static unsigned char ts_i2c_addr = 0; + +static struct proc_dir_entry* l_tsproc = NULL; +static struct timer_list l_lighttimer; // for shaking +static int l_tskey_btn = 0; // zero to disable touch key, positive to support touch key + +#if 0 +//add +struct tp_infor{ + +char name[64]; +int i2caddr; +int xaxis; +int xdir; +int ydir; +int finger_num; +}; + +//add by jackie +//static int l_tpindex = -1; +static struct tp_infor l_tpinfor[1]; +#endif +///////////////////////////////////////////////////// +// extrenal function +///////////////////////////////////////////////////// +extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); +extern int wmt_setsyspara(char *varname, unsigned char *varval); +///////////////////////////////////////////////////// +static int ts_writeproc( struct file *file, + const char *buffer, + unsigned long count, + void *data ); +static int ts_readproc(char *page, char **start, off_t off, + int count, int *eof, void *data); + + +char g_dbgmode = 0; +int COL_NUM; +int ROW_NUM; +int SKIP_ZERO_POINT; + +int wmt_ts_get_configfilename(char* fname) +{ + sprintf(fname,"%s.cfg",l_tp[0].name); + return 0; +} + +int wmt_ts_get_firmwfilename(char* fname) +{ + sprintf(fname,"%s_fw.bin",l_tp[0].name); + return 0; +} + +int wmt_ts_get_xaxis(void) +{ + return l_tp[0].xaxis; +} + +int wmt_ts_get_xdir(void) +{ + return l_tp[0].xdir; +} + +int wmt_ts_get_ydir(void) +{ + return l_tp[0].ydir; +} + +int wmt_ts_get_fingernum(void) +{ + return l_tp[0].finger_num; +} + + 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_enable_tskey(void) +{ + return l_tskey_btn; +} + +int wmt_ts_enable_keyled(void) +{ + return (keyled_gpio>=0 ? 1:0); +} + + +static void ts_lighttimer_timeout(unsigned long timeout) +{ + // turn off the light + if (20 == keyled_gpio) + { + if (light_level>=0) + { + REG32_VAL(__GPIO_BASE+0x00F0) &= ~BIT4; // output low + dbg("turn off the light!\n"); + } else { + REG32_VAL(__GPIO_BASE+0x00F0) |= BIT4; // output high + dbg("turn off the light!\n"); + } + } +} + + +static void wmt_ts_init_light(void) +{ + if (20 == keyled_gpio) + { + setup_timer(&l_lighttimer, ts_lighttimer_timeout, 0); + // init gpio20 and turn off light + REG32_VAL(__GPIO_BASE+0x00F0) &= ~BIT4; // output low + REG32_VAL(__GPIO_BASE+0x00B0) |= BIT4; // output enable + REG32_VAL(__GPIO_BASE+0x0070) |= BIT4; // enable gpio + REG32_VAL(__GPIO_BASE+0x04F0) |= BIT4; // pull up + REG32_VAL(__GPIO_BASE+0x04B0) |= BIT4; // enable pull up/down + } +} + +void wmt_ts_turnoff_light(void) +{ + if (20 == keyled_gpio) + { + mod_timer(&l_lighttimer, jiffies + msecs_to_jiffies(light_time)); + } +} + +void wmt_ts_turnon_light(void) +{ + if (20 == keyled_gpio) + { + del_timer(&l_lighttimer); + if (light_level >= 0) + { + REG32_VAL(__GPIO_BASE+0x00F0) |= BIT4; // output high + dbg("turn on the light!\n"); + } else { + REG32_VAL(__GPIO_BASE+0x00F0) &= ~BIT4; // output low + dbg("turn on the light!\n"); + } + } +} + +static void wmt_ts_remove_light(void) +{ + if (20 == keyled_gpio) + { + if (light_level >= 0) + { + REG32_VAL(__GPIO_BASE+0x00F0) &= ~BIT4; // output low + } else { + REG32_VAL(__GPIO_BASE+0x00F0) |= BIT4; // output high + } + del_timer(&l_lighttimer); + } +} + +int wmt_is_tsirq_enable(int num) +{ + int val = 0; + + 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(int num) +{ + if (num > 11) + { + return 0; + } + return (REG32_VAL(__GPIO_BASE+0x0360) & (1<<num)) ? 1: 0; +} + +void wmt_clr_int(int num) +{ + if (num > 11) + { + return; + } + REG32_VAL(__GPIO_BASE+0x0360) = 1<<num; +} + +void wmt_tsreset_init(int num) +{ + REG32_VAL(__GPIO_BASE+0x0040) |= (1<<num);//&= ~(1<<num); //enable gpio + REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<num); // out high + REG32_VAL(__GPIO_BASE+0x0080) |= (1<<num); //output enable + msleep(5); + //REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<num); +} + +// 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 +} + +int wmt_set_irq_mode(unsigned int num, int mode) +{ + if(num >11) + return -1; + REG32_VAL(__GPIO_BASE+0x0040) &= ~(1<<num); //enable gpio + if(mode == 0) + { + REG32_VAL(__GPIO_BASE+0x0080) |= (1<<num); //set output + REG32_VAL(__GPIO_BASE+0x04c0) |= (1<<num); //pull down + REG32_VAL(__GPIO_BASE+0x0480) &= ~(1<<num); //enable pull up/down + } + else if(mode == 1) + REG32_VAL(__GPIO_BASE+0x0080) &= ~(1<<num); //set input + //msleep(5); + return 0; +} + + +int wmt_set_gpirq(unsigned int num, int type) +{ + int shift; + int offset; + unsigned long reg; + + 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 GIRQ_LOW: + reg &= ~(1<<(shift*8+2)); + reg &= ~(1<<(shift*8+1)); + reg &= ~(1<<(shift*8)); + break; + case GIRQ_HIGH: + reg &= ~(1<<(shift*8+2)); + reg &= ~(1<<(shift*8+1)); + reg |= (1<<(shift*8)); + break; + case GIRQ_FALLING: + reg &= ~(1<<(shift*8+2)); + reg |= (1<<(shift*8+1)); + reg &= ~(1<<(shift*8)); + break; + case GIRQ_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(unsigned int num) +{ + 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(unsigned int num) +{ + 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"); + if (wmt_ts_enable_keyled()) + wmt_ts_remove_light(); + if (l_tsdev->suspend !=NULL) + { + return l_tsdev->suspend(pdev, state); + } + return 0; +} +static int wmt_ts_resume(struct platform_device *pdev) +{ + klog("ts resume....\n"); + if (wmt_ts_enable_keyled()) + wmt_ts_init_light(); + if (l_tsdev->resume != NULL) + { + return l_tsdev->resume(pdev); + } + return 0; +} + +static int wmt_ts_probe(struct platform_device *pdev) +{ + l_tsproc= create_proc_entry(WMTTS_PROC_NAME, 0666, NULL/*&proc_root*/); + if (l_tsproc != NULL) + { + l_tsproc->read_proc = ts_readproc; + l_tsproc->write_proc = ts_writeproc; + } + if (l_tsdev->probe != NULL) + { + return l_tsdev->probe(pdev); + } + else + { + return 0; + } +} + +static int wmt_ts_remove(struct platform_device *pdev) +{ + if (l_tsproc != NULL) + { + remove_proc_entry(WMTTS_PROC_NAME, NULL); + l_tsproc = NULL; + } + + 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_ts_open(struct inode *inode, struct file *filp) +{ + int ret = 0; + return ret; +} + +static int wmt_ts_close(struct inode *inode, struct file *filp) +{ + return 0; +} + +static unsigned int wmt_ts_poll(struct file *filp, struct poll_table_struct *wait) +{ + return 0; +} + + +void read_diff(rawdata* pdata) +{ + //u16 Buffer[COL_NUM_MAX*ROW_NUM_MAX*2]; + u16 *Buffer; + u16 idx = 0; + int i,j; + u16 addr =0; + pdata->col = COL_NUM; + pdata->row = ROW_NUM; + Buffer = kzalloc(COL_NUM_MAX*ROW_NUM_MAX*2*2, GFP_KERNEL); + if (!Buffer) { + errlog("mem alloc fail.\n"); + return; + } + for(i=0;i<pdata->row;i++) + { + addr = 0x42f2+i*60; + printk("read_diff: addr=0x%04x\n",addr); + for(j=0;j<pdata->col*2;j++) + { + if(lw86x0_read_reg(addr+j, &Buffer[idx],1)!=0) + { + lw86x0_read_reg(addr+j, &Buffer[idx],1); + } + printk("read_diff: Buffer[%d]=0x%04x\n",idx,Buffer[idx]); + idx++; + } + } + for(i=0; i<pdata->col * pdata->row; i++) + { + pdata->data[i] = ((Buffer[i*2]<<8)&0xff00)|(Buffer[i*2+1]&0x00ff); + printk("read_diff: pdata->data[%d]=0x%04x\n",i,pdata->data[i]); + } + kfree(Buffer); +} + +void read_cdc(rawdata* pdata) +{ + int i,j; + u16 addr = 0x2fc8; + u16 idx = 0; + + pdata->col = COL_NUM; + pdata->row = ROW_NUM; + + for(i=0;i<pdata->col;i++) + { + for(j=0;j<pdata->row;j++) + { + printk("read_cdc: addr=0x%04x\n",addr+idx); + if(lw86x0_read_reg(addr+idx, &pdata->data[j*pdata->col+i],1)!=0) + { + lw86x0_read_reg(addr+idx, &pdata->data[j*pdata->col+i],1); + } + printk("read_cdc: pdata->data[%d]=0x%04x\n",j*pdata->col+i,pdata->data[j*pdata->col+i]); + idx++; + } + } +} + +void read_amb(rawdata* pdata) +{ + int i,j; + u16 addr = 0x2E04; + u16 idx = 0; + + pdata->col = COL_NUM; + pdata->row = ROW_NUM; + + for(i=0;i<pdata->col;i++) + { + for(j=0;j<pdata->row;j++) + { + printk("read_amb: addr=0x%04x\n",addr+idx); + if(lw86x0_read_reg(addr+idx, &pdata->data[j*pdata->col+i],1)!=0) + { + lw86x0_read_reg(addr+idx, &pdata->data[j*pdata->col+i],1); + } + printk("read_amb: pdata->data[%d]=0x%04x\n",j*pdata->col+i,pdata->data[j*pdata->col+i]); + idx++; + } + } + + +} + +void lw86x0_flash_write_prepare(void) +{ + lw86x0_stop_timer(1); + lw86x0_write_reg(0x00e2, 0x0300);//#write_en=1 tmr=1 + udelay(1); + //mass erase + lw86x0_write_reg(0x00e2, 0x0305);//#xe=1 mas1=1 + lw86x0_write_reg(0x00e2, 0x0315);//#erase=1 + udelay(5); + lw86x0_write_reg(0x00e2, 0x0395);//#nvstr=1 + mdelay(20); + lw86x0_write_reg(0x00e2, 0x0385);//#erase=0 + udelay(100); + lw86x0_write_reg(0x00e2, 0x0305);//#nvstr=0 + lw86x0_write_reg(0x00e2, 0x0300);//#xe=0 mas1=0 +} + +void lw86x0_flash_write(u8* pbData,u16 start_addr, u16 num) +{ + u16 yaddr = start_addr; + u16 xaddr = (start_addr)&0xFF80;//x addr is a 8bit address + u16 cnt = 0; + while(cnt<num) + { + while(1) + { + lw86x0_write_reg(0x00e3, xaddr);//#xaddr + lw86x0_write_reg(0x00e2, 0x0304);//#xe=1 + lw86x0_write_reg(0x00e2, 0x0324);//#prog=1 + udelay(5); + lw86x0_write_reg(0x00e2, 0x03a4);//#nvstr=1 + udelay(10); + do + { + u16 data = pbData[cnt]; + lw86x0_write_reg(0x00e3, yaddr);//#yaddr + lw86x0_write_reg(0x00e4, data);//#din + lw86x0_write_reg(0x00e2, 0xfbac);//#ye=0 + lw86x0_write_reg(0x00e2, 0x03a4);//#ye=0 + yaddr++; + cnt++; + if(cnt==num) + { + break; + } + }while(yaddr&0x007F); + xaddr+=0x0080; + udelay(20); + lw86x0_write_reg(0x00e2, 0x0384);//#prog=0 + udelay(100); + lw86x0_write_reg(0x00e2, 0x0304);//#nvstr=0 + lw86x0_write_reg(0x00e2, 0x0300);//#xe=0 + if(cnt==num) + { + break; + } + } + } + +} + +void lw86x0_flash_write_finish(u16 total_len) +{ + //write length of FW to last 2 byte of flash + u8 *pLen = (u8 *)&total_len; + lw86x0_flash_write(&(pLen[1]),0x7FFE, 1); + lw86x0_flash_write(&(pLen[0]),0x7FFF, 1); + + lw86x0_write_reg(0x00e2, 0x0300);//#tmr=1 + lw86x0_write_reg(0x00e2, 0x0200);//#tmr=0 + lw86x0_write_reg(0x00e2, 0x02c0);//#nvstr=1 se=1 + lw86x0_write_reg(0x00e2, 0x02eb);//#prog=1 ifren=1 ye=1 mas=1 + lw86x0_write_reg(0x00e2, 0x03eb);//#tmr=1 + lw86x0_write_reg(0x00e2, 0x02eb);//#tmr=0 + lw86x0_write_reg(0x00e2, 0x02c0);//#prog=0 ifren=0 ye=0 mas=0 + lw86x0_write_reg(0x00e2, 0x0200);//#nvstr=0 se=0 + lw86x0_write_reg(0x00e2, 0x0204);//#xe=1 + lw86x0_write_reg(0x00e2, 0x0214);//#erase=1 + udelay(5); + lw86x0_write_reg(0x00e2, 0x0294);//#nvstr=1 + mdelay(20); + lw86x0_write_reg(0x00e2, 0x0284);//#erase=0 + udelay(5); + lw86x0_write_reg(0x00e2, 0x0204);//#nvstr=0 + lw86x0_write_reg(0x00e2, 0x0200);//#xe=0 + lw86x0_write_reg(0x00e2, 0x0000); + lw86x0_write_reg(0x000c, 0xffff); + lw86x0_stop_timer(0); +} + +void lw86x0_flash_read(u8* pbData, u16 start_addr, u16 num) +{ + lw86x0_stop_timer(1); + u16 cnt; + u16 rd_data = 0; + u8 *buf; + for(cnt=0; cnt<num;cnt++) + { + lw86x0_write_reg(0x00e4, 0x0000);//#read data + lw86x0_write_reg(0x00e2, 0x0300);//#tmr=1 + lw86x0_write_reg(0x00e3, start_addr+cnt); + lw86x0_write_reg(0x00e2, 0x034c);//#se=1 ye=1 xe=1 + lw86x0_write_reg(0x00e2, 0x0300);//#se=1 ye=1 xe=1 + lw86x0_read_reg(0x00e4, &rd_data,1); + buf = (u8 *)&rd_data; + pbData[cnt] = buf[1]; + } + lw86x0_stop_timer(0); +} + + +static long wmt_ts_ioctl(/*struct inode * node,*/ struct file *dev, unsigned int cmd, unsigned long arg) +{ + reg_word regword; + //rawdata rdata; + rawdata *rdata; + flash_op f_pkt;//flash packet + + int ret = 0; + char ch; + rdata = kzalloc(sizeof(rawdata), GFP_KERNEL); + if (!rdata) { + errlog("mem alloc fail.\n"); + return -ENOMEM; + } + + if (_IOC_TYPE(cmd) != TS_IOC_MAGIC){ + dbg("CMD ERROR!"); + return -ENOTTY; + } + + if (_IOC_NR(cmd) > TS_IOC_MAXNR){ + dbg("NO SUCH IO CMD!\n"); + return -ENOTTY; + } + + switch (cmd) { + case LW86X0_WRITE_REG: + copy_from_user(®word, (reg_word*)arg, sizeof(regword)); + dbg("write reg[%d] word value 0x%x", regword.uOffset, regword.uValue ); + ret = lw86x0_write_reg(regword.uOffset, regword.uValue); + if (ret != 0) + { + dbg("Faied to write reg. ret 0x%x\n",ret); + } + return 0; + case LW86X0_READ_REG: + copy_from_user(®word, (reg_word*)arg, sizeof(regword)); + ret = lw86x0_read_reg(regword.uOffset, ®word.uValue, 1); + if (ret != 0) + { + dbg("Faied to read reg. ret 0x%x\n",ret); + } + else + { + + dbg("read reg[%d]=0x%04x",regword.uOffset, regword.uValue); + } + copy_to_user((unsigned int*)arg, ®word, sizeof(regword)); + return 0; + case LW86X0_CTRL_DEBUG_MODE: + copy_from_user(&ch, (char*)arg, sizeof(char)); + printk("LW86X0_CTRL_DEBUG_MODE,%c", ch); + if(ch=='1') + { + g_dbgmode = 1; + wmt_disable_gpirq(irq_gpio); + } + else + { + g_dbgmode = 0; + wmt_enable_gpirq(irq_gpio); + } + return 0; + /* + case LW86X0_CTRL_RD_DIFF: + copy_from_user(&rdata, (rawdata*)arg, sizeof(rdata)); + printk("tpd-ioctrl: LW86X0_CTRL_RD_DIFF\n"); + read_diff(&rdata); + copy_to_user((unsigned int*)arg, &rdata, sizeof(rdata)); + return 0; + case LW86X0_CTRL_RD_CDC: + copy_from_user(&rdata, (rawdata*)arg, sizeof(rdata)); + printk("tpd-ioctrl: LW86X0_CTRL_RD_CDC\n"); + read_cdc(&rdata); + copy_to_user((unsigned int*)arg, &rdata, sizeof(rdata)); + return 0; + case LW86X0_CTRL_RD_AMB: + copy_from_user(&rdata, (rawdata*)arg, sizeof(rdata)); + printk("tpd-ioctrl: LW86X0_CTRL_RD_AMB\n"); + read_amb(&rdata); + copy_to_user((unsigned int*)arg, &rdata, sizeof(rdata)); + return 0; + */ + case LW86X0_CTRL_RD_DIFF: + copy_from_user(rdata, (rawdata*)arg, sizeof(*rdata)); + printk("tpd-ioctrl: LW86X0_CTRL_RD_DIFF\n"); + read_diff(rdata); + copy_to_user((unsigned int*)arg, rdata, sizeof(*rdata)); + return 0; + case LW86X0_CTRL_RD_CDC: + copy_from_user(rdata, (rawdata*)arg, sizeof(*rdata)); + printk("tpd-ioctrl: LW86X0_CTRL_RD_CDC\n"); + read_cdc(rdata); + copy_to_user((unsigned int*)arg, rdata, sizeof(*rdata)); + return 0; + case LW86X0_CTRL_RD_AMB: + copy_from_user(rdata, (rawdata*)arg, sizeof(*rdata)); + printk("tpd-ioctrl: LW86X0_CTRL_RD_AMB\n"); + read_amb(rdata); + copy_to_user((unsigned int*)arg, rdata, sizeof(*rdata)); + return 0; + case LW86X0_FLASH_DOWNLOAD: + copy_from_user(&f_pkt, (flash_op*)arg, sizeof(f_pkt)); + if(f_pkt.startaddr==0) + { + lw86x0_flash_write_prepare(); + } + lw86x0_flash_write(f_pkt.data, + f_pkt.startaddr, + f_pkt.pktlen); + printk("dnload: start addr = %04x\n",f_pkt.startaddr); + if(f_pkt.lastpkt==1) + { + u16 write_len = f_pkt.startaddr + f_pkt.pktlen; + lw86x0_flash_write_finish(write_len); + } + return 0; + case LW86X0_FLASH_UPLOAD: + copy_from_user(&f_pkt, (flash_op*)arg, sizeof(f_pkt)); + lw86x0_flash_read(f_pkt.data, f_pkt.startaddr, f_pkt.pktlen); + printk("upload: start addr = %04x\n",f_pkt.startaddr); + printk("\n"); + copy_to_user((int*)arg, &f_pkt, sizeof(f_pkt)); + return 0; + case LW86X0_CTRL_STOP_TIMER: + copy_from_user(&ch, (char*)arg, sizeof(char)); + if(ch == '1') + lw86x0_stop_timer(1); + else + lw86x0_stop_timer(0); + return 0; + } + kfree(rdata); + return -EINVAL; +} + +static ssize_t wmt_ts_read(struct file *filp, char *buf, size_t count, loff_t *l) +{ + return 0; +} + + +static struct file_operations wmt_ts_fops = { + .read = wmt_ts_read, + .poll = wmt_ts_poll, + .unlocked_ioctl = wmt_ts_ioctl, + .open = wmt_ts_open, + .release = wmt_ts_close, +}; + +static int ts_writeproc( struct file *file, + const char *buffer, + unsigned long count, + void *data ) +{ + int calibrate = 0; + int val = 0; + + if (sscanf(buffer, "calibrate=%d\n", &calibrate)) + { + if (1 == calibrate) + { + if((l_tsdev->capacitance_calibrate != NULL) && + (0 == l_tsdev->capacitance_calibrate())) + { + printk(KERN_ALERT "%s calibration successfully!\n", l_tsdev->ts_id); + } else { + printk(KERN_ALERT "%s calibration failed!\n", l_tsdev->ts_id); + } + } + } else if (sscanf(buffer, "out=%d\n", &val)) + { + switch(val) + { + case 1: // reset1 + REG32_VAL(__GPIO_BASE+0x0040) |= (1<<irq_gpio); //enable gpio + REG32_VAL(__GPIO_BASE+0x00C0) |= (1<<irq_gpio); //out high + REG32_VAL(__GPIO_BASE+0x0080) |= (1<<irq_gpio); //set input + break; + case 0: // reset2 + REG32_VAL(__GPIO_BASE+0x0040) |= (1<<irq_gpio); //enable gpio + REG32_VAL(__GPIO_BASE+0x00C0) &= ~(1<<irq_gpio); //out high + REG32_VAL(__GPIO_BASE+0x0080) |= (1<<irq_gpio); //set input + break; + default: + break; + }; + } + return count; +} + +static int ts_readproc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len = 0; + + len = sprintf(page, + "echo calibrate=1 > /proc/wmtts_config to calibrate ts.\n"); + return len; +} + +unsigned char wmt_ts_get_i2caddr(void) +{ + return ts_i2c_addr; +} + +static int wmt_check_touch_env(void) +{ + int ret = 0; + int len = 127; + char retval[128] = {0},*p=NULL,*s=NULL; + int Enable=0; + + // Get u-boot parameter + ret = wmt_getsyspara("wmt.io.touch", retval, &len); + if(ret){ + errlog("Read wmt.io.touch Failed.\n"); + return -EIO; + } + + //check touch enable + p = retval; + sscanf(p,"%d:", &Enable); + if(Enable == 0){ + errlog("Touch Screen Is Disabled.\n"); + return -ENODEV; + } + + //check touch IC name + p = strchr(p,':');p++; + if (strncmp(p, l_tp[0].name, strlen(l_tp[0].name))) { + errlog("Can't find %s!\n", l_tp[0].name); + return -ENODEV; + } + + //get firmware file name + s = strchr(p,':'); + memset(l_tp[0].name,0x00,sizeof(l_tp[0].name)); + strncpy(l_tp[0].name, p, (s-p)); + dbg("ts_fwname=%s\n", l_tp[0].name); + + p = s + 1; + ret = sscanf(p,"%d:%d:%d:%d:%d:%d:%d:%d:%x", + &irq_gpio,&panelres_x,&panelres_y,&rst_gpio, + &(l_tp[0].xaxis),&(l_tp[0].xdir),&(l_tp[0].ydir), + &(l_tp[0].finger_num),&(l_tp[0].i2caddr)); + + dbg("%d;%d;%d;%d;%d;%d;%d;%d;%x;",irq_gpio,panelres_x,panelres_y,rst_gpio, + (l_tp[0].xaxis),(l_tp[0].xdir),(l_tp[0].ydir), + (l_tp[0].finger_num),(l_tp[0].i2caddr)); + + 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; +} +//#if 0 +//add by jackie i2c_board_info +struct i2c_board_info ts_i2c_board_info = { + .type = WMT_TS_I2C_NAME, + .flags = 0x00, + //.addr = 0x18, //WMT_TS_I2C_ADDR,//why error? + .platform_data = NULL, + .archdata = NULL, + .irq = -1, +}; +//add jackie 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_board_info.addr = l_tp[0].i2caddr; + 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; +} +//add by jackie +struct i2c_client* ts_get_i2c_client(void) +{ + return l_client; +} +//add +static int __init wmt_ts_init(void) +{ + int ret = 0; + + if(wmt_check_touch_env()) + return -ENODEV; + +//add by jackie + 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){ + printk(KERN_ERR "Errors to init %s ts IC!!!\n", l_tsdev->ts_id); + return -1; + } + if (wmt_ts_enable_keyled()) + wmt_ts_init_light(); + // 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("wmt ts driver init ok!\n"); + return ret; +} + +//add by jackie +static void ts_i2c_unregister_device(void) +{ + if (l_client != NULL) + { + i2c_unregister_device(l_client); + l_client = NULL; + } +} +//add end + +static void __exit wmt_ts_exit(void) +{ + dbg("%s\n",__FUNCTION__); + + if (wmt_ts_enable_keyled()) + wmt_ts_remove_light(); + l_tsdev->exit(); + mutex_destroy(&cal_mutex); + 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); + ts_i2c_unregister_device(); +} + + +module_init(wmt_ts_init); +module_exit(wmt_ts_exit); + +MODULE_LICENSE("GPL"); + |