#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");