#include <mach/hardware.h> #include <asm/io.h> #include <asm/irq.h> #include <mach/clock.h> #include <linux/slab.h> #include "os.h" #include "tscr.h" #include "tsc.h" #include <linux/interrupt.h> #include <asm/gpio.h> #include <mach/clock.h> #include "i2c.h" #include <linux/timer.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/input.h> #include <linux/init.h> #include <linux/serio.h> #include <linux/delay.h> #include <linux/hwmon.h> #include <linux/timer.h> #include <linux/platform_device.h> #include <mach/hardware.h> #include <asm/io.h> #include <asm/irq.h> #include <linux/irq.h> #include <linux/interrupt.h> #include <asm/gpio.h> #include <mach/clock.h> #define u8 unsigned char #define u32 unsigned int #define s32 signed int //#define KEY_HOME 102 //#define KEY_BACK 158 //#define KEY_MENU 139 #define TP_I2C_DEVICE_ID 0xc0 #define REPORT_PACKET_LENGTH 8 #define X_MAX 2047 #define Y_MAX 2047 #define AUO_INT_LOW 1 #define TOUCH_INT_PIN GPIO_NUM(3,17) #define down 0 #define up 1 static int lx,ly,lx1,ly1; int ON_TOUCH_INT; int resx=0,resy=0; static int pendown = 0; static int penup=0; static uint32_t irq; /* struct of touch information to the middleware or applications */ typedef struct { u32 u32X; /* X coordinate, 0~2047 */ u32 u32Y; /* Y coordinate, 0~2047 */ u8 u8Finger; /* Number of fingers in the touch event */ u32 u32Dis_X; /* X distance between two fingers */ u32 u32Dis_Y; /* Y distance between two fingers. This value could be negative */ } TOUCH_DATA_st; /* Structure for Input Type*/ struct auo_tp2_ts{ struct input_dev * dev; int xpos; int ypos; char phys[32]; //for raw data or others }; static struct auo_tp2_ts *mic_ts; static struct work_struct work; static struct workqueue_struct *wq; static void microwell_tsc_work(struct work_struct *work); #if 1 struct timer_list CY_timer; void Delay(int ms) { unsigned long j,stamp_1; j=jiffies; stamp_1=j+ ms*HZ/1000; while(1) { j=jiffies; if(j>=stamp_1) return ; } } ///////////////////////////////////////////////////////////////////// /// @brief Calculate the 8-bit checksum of the given data array /// @author Chao-Cheng Wen /// @param[in] msg the pointer to the data /// @param[in] s32Length the length of the data in bytes /// /// Calculate the 8-bit checksum of the given data array. This is a /// simple algorithm to make the sum of data and checksum to be zero. /// The porblem of zero-lossage exists in this algorithm. ///////////////////////////////////////////////////////////////////// u8 Calculate_8BitsChecksum( u8 *msg, s32 s32Length ) { s32 s32Checksum = 0; s32 i; for ( i = 0 ; i < s32Length; i++ ) { s32Checksum += msg[i]; } //printk("_in Calculate_8BitsChecksum____________calc_checksum=0x%x\n___________",( -s32Checksum ) & 0xFF ); return (u8)( ( -s32Checksum ) & 0xFF ); } int Msctpc_getData(struct input_dev *inputp, TOUCH_DATA_st *touchData); void timer_callback() { CY_timer.expires = jiffies + 1000; add_timer(&CY_timer); printk("i am in: timer_callback\n"); } static int timer_start(void) { init_timer(&CY_timer); CY_timer.expires = 1000; add_timer(&CY_timer); return 0; } static int timer_init(void) { init_timer(&CY_timer); CY_timer.expires = 1000; CY_timer.function = timer_callback; add_timer(&CY_timer); return 0; } #endif void delay() { int i,j; for(i=0;i<1000;i++) for(j=0;j<1000;j++); } #define BH_TIMER // added by andely 2009-12-29 #include <linux/spinlock.h> // added by andely 2010-03-08 // CONFIG_SSLTSC_FOR_BATTERY defined in kernel configure file #ifdef CONFIG_SSLTSC_FOR_BATTERY #warning "ssltsc.ko only define for Battery detect!!!" #else #warning "ssltsc.ko define for Battery detect and TSC function!!!" #endif #define PRESSURE_SUPPORT 1 #define TSC_RST_TIMEOUT 0x100 #define TSC_MSR_VAL 0x80 #define TSC_WUR_VAL 0x100 #define TSC_MASK_VAL 0x00FF00FF #define SUPPLY 3347 #define MMT_VBAT (0x00 << 4) #define MMT_AUX (0x03 << 4) #define MMT_AUX1 (0x04 << 4) #define TSC_EN (0x01 << 0) #define TSC_RST (0x01 << 1) #define TSC_GO (0x01 << 2) #define ISR_DR (0x01 << 0) #define TSC_CAL_RESET "reset" #define TSC_CAL_SHOW "show" #define PT_BUF_LEN 3 #define TSC_X_MAX 0x3FF #define TSC_Y_MAX 0x3FF tsc_t buf[PT_BUF_LEN]; int pt_out=0,pt_shift=0; static tsc_cal_t calibrate ={1,0,0,0,1,0,1}; typedef struct { tsc_t hw; uint32_t xpos; uint32_t ypos; uint32_t xold; uint32_t yold; uint32_t xup; uint32_t yup; char phys[32]; TOUCH_DATA_st *touchData; uint32_t irq; spinlock_t spin_lock; struct input_dev *input_dev; /* n us delay between samples. */ uint32_t poll_period; /* TSC bottom half. */ #ifdef BH_TIMER struct hrtimer timer; #elif defined BH_WQ struct workqueue_struct *wq; struct work_struct work; #endif uint32_t pen_touch; //Last pen state: 1> pen down, 0>pen up. uint32_t count; /* debounce fliter */ uint32_t read_cnt; uint32_t read_rep; uint32_t debounce_max; int32_t last_read_x, last_read_y; int32_t debounce_tol_x, debounce_tol_y; uint32_t debounce_tol_p; uint32_t debounce_rep; uint32_t filter_en; int (*filter) (void *data, int32_t * val_x, int32_t * val_y, uint32_t * val_p); } ssltsc_ctx; #define ADC_TIMEOUT 1000 #define ADC_TIMES 100 #define sample_period (10*1000000) uint32_t g_vbat_val; static ssltsc_ctx ts; static tsc_cfg_p cfg; /* TSC configuration. */ int Msctpc_getData(struct input_dev *inputp, TOUCH_DATA_st *touchData) { u8 val[REPORT_PACKET_LENGTH] = {0}; int i=0;int key=0; int errnum=0; u8 Checksum = 0; touchData->u32X = 0; touchData->u32Y = 0; touchData->u32Dis_X = 0; touchData->u32Dis_Y = 0; touchData->u8Finger = 0; penup=0; pendown=0; while(errnum<5) { lx=2048; ly=2048; /* Read 8-bytes data from the TP controller. */ /* By default, the TP controller supports 120k SCL rate and duty cycle is 50% */ // Msctpc_ReadI2C( TP_I2C_DEVICE_ID, &val[0], REPORT_PACKET_LENGTH ); Msctpc_ReadI2C_Seq(TP_I2C_DEVICE_ID, &val[0], REPORT_PACKET_LENGTH ); Checksum = Calculate_8BitsChecksum( val, (REPORT_PACKET_LENGTH-1) ); if ( ( Checksum == val[7] && val[0] == 0x52 ) ) // Check the packet ID(0x52)and checksum { printk("***********************\n"); for(i=0;i<REPORT_PACKET_LENGTH ;i++) { if(i%8==0) printk("\n"); printk("*0x%x\t",val[i]); } printk("***********************\n"); // key=0; if(val[5]==0x1)//menu { if(key==0) { key=KEY_MENU; input_report_key (inputp, KEY_MENU, 1); printk("menu\n"); input_sync(inputp); } continue; } else if(val[5]==0x2)//home { if(key==0) { key=KEY_HOME; input_report_key (inputp, KEY_HOME, 1); printk("home\n"); input_sync(inputp); } continue; } else if(val[5]==0x4)//back { if(key==0) { key=KEY_BACK; input_report_key (inputp, KEY_BACK, 1); printk("back\n"); input_sync(inputp); } continue; } /* parsing the coordinate report packet */ /* MSG20XX EVK report format */ /* * +---------------------------------+ * byte[0] | Packet ID ( 0x52 ) | * +----------------+----------------+ * byte[1] | u32X[11:8] | u32Y[11:8] | * +---------------------------------+ * byte[2] | u32X[7:0] | * +---------------------------------+ * byte[3] | u32Y[7:0] | * +----------------+----------------+ * byte[4] | u32Dis_X[11:8] | u32Dis_Y[11:8] | * +----------------+----------------+ * byte[5] | u32Dis_X[7:0] | * +---------------------------------+ * byte[6] | u32Dis_Y[7:0] | * +---------------------------------+ * byte[7] | Checksum | * +---------------------------------+ */ touchData->u32X = ( val[1] & 0xF0 ) << 4 | val[2]; touchData->u32Y = ( val[1] & 0x0F )<< 8 | val[3]; touchData->u32Dis_X = ( val[4] & 0xF0 ) << 4 | val[5]; touchData->u32Dis_Y = ( val[4] & 0x0F ) << 8 | val[6]; if ( touchData->u32X == 0xFFF && touchData->u32Y == 0xFFF && touchData->u32Dis_X == 0x000&& touchData->u32Dis_Y == 0xFF ) { penup=1; input_report_abs(inputp, ABS_X,-100); input_report_abs(inputp, ABS_Y, 0); input_report_abs (inputp, ABS_PRESSURE, 1); input_report_key (inputp, BTN_TOUCH, 0); printk("one report:x=%d,y=%d\, up\n",lx,ly); input_report_abs(inputp, ABS_PRESSURE, 0); printk("<<<<<<<<<<<pen up!!!!!!!!!,btn=0,pressure=0,sync\n"); input_sync(inputp); printk(" >in Msctpc_getData >>>>>>>>>>Touch-End event\n"); return 0; /* The coordinate report stands for a Touch-End event */ /* Inform the OS or system mailbox that the Touch-End event happened */ } else { //printk(" >>in Msctpc_getData >>>>>>>>>Touch-On-Panel event\n"); lx=touchData->u32X; ly=touchData->u32Y; printk("read one : x=%d,y=%d\n",lx,ly); errnum=0; /* The coordinate report stands for Touch-On-Panel event */ if ( touchData->u32Dis_X == 0 && touchData->u32Dis_Y == 0 ) { /* If the distance values are zero, the TP detects one-finger-touch event */ //printk(">>>>in Msctpc_getData >>>>>>>>>>>>one finger\n"); touchData->u8Finger = 1; if(X_MAX==1023) { lx=1023-(lx>>1); ly=ly>>1; } else if(X_MAX==2047) { lx=2047-lx; } if(pendown==0) { input_report_key (inputp, BTN_TOUCH, 1); printk("<<<<<<<<<<<pen down!!!!!!!!!,btn_touch=1\n"); } input_report_abs(inputp, ABS_X,(lx)); input_report_abs(inputp, ABS_Y, ly); pendown=1; input_report_abs (inputp, ABS_PRESSURE, 1); input_sync(inputp); printk("<x,y,pressure=1,sync\n"); printk("after calibrate and report down: x=%d,y=%d\n",lx,ly); continue; //Msctpc_getData(inputp, touchData); } else if ( touchData->u32Dis_X <= 2047 && touchData->u32Dis_Y <= 2047 ) { /* If the distance values are valid, the TP detects two-finger-touch event */ //printk(">>>>in Msctpc_getData >>>>>>>two finger\n"); touchData->u8Finger = 2; /* lx1=touchData->u32X+touchData->u32Dis_X; ly1=touchData->u32Y+touchData->u32Dis_Y; input_report_abs(inputp, ABS_MT_POSITION_X,1023-(lx>>1)); input_report_abs(inputp, ABS_MT_POSITION_Y, ly>>1); input_report_abs(inputp,ABS_MT_TOUCH_MAJOR, 1); printk("two mulit report1:x=%d,y=%d\,finger=1\n",1023-(lx>>1),ly>>1); input_mt_sync(inputp); input_report_abs(inputp, ABS_MT_POSITION_X,1023-(lx1>>1)); input_report_abs(inputp, ABS_MT_POSITION_Y, ly1>>1); printk("two mulit report2:x=%d,y=%d\,finger=1\n",1023-(lx1>>1),ly1>>1); input_report_abs(inputp,ABS_MT_TOUCH_MAJOR, 1); input_mt_sync(inputp); input_sync(inputp); printk("two -r\n"); continue; */ //Msctpc_getData(inputp, touchData); } else { /* Fetal error */ printk("in Msctpc_getData :Fetal error,discard the data\n"); return -1; /* Discard the invalid coordinate reports due to fetal error. */ } } } else { printk("in Msctpc_getData :Packet error happened. \n"); errnum++; // /* Packet error happened. */ /* Check I2C signal quality and I2C master codes */ } } if(pendown==1) { input_report_key (inputp, BTN_TOUCH, 0); input_report_abs (inputp, ABS_PRESSURE, 0); input_sync(inputp); printk("<<<<<<<<<<<pen up!!!!!!!!!,btn_touch=0,pressure=0,sync\n"); } if(key>0) { input_report_key (inputp, key, 0); printk("%d release\n",key); input_sync(inputp); } //enable_irq(ts.irq); return -2; } static char *ssltsc_name = "SSL TouchScreen"; static int pen_up_flg=0; static float ax = 4.3268f; static float bx = 29.3883f; static float ay = 3.86444f; static float by = 32.08083f; static int use_flag = 0; #if (defined CONFIG_ARCH_OPTIMUS_REPLOID || defined CONFIG_ARCH_OPTIMUS_REPLOID3) /* debounce fliter */ #define X_LIMIT 0x3 #define Y_LIMIT 0x3 #define P_LIMIT 0x144 //#define P_LIMIT 0xFFFF // Disable the Pressure filter. #define TSC_DEBUNCE_MAX 10 #define TSC_DEBUNCE_REP 2 #define TS_POLL_PERIOD (10 * 1000) /* us delay between samples */ #else /* debounce fliter */ #define X_LIMIT 0xA #define Y_LIMIT 0xA #define P_LIMIT 0x1cc //#define P_LIMIT 0xFFFF // Disable the Pressure filter. #define TSC_DEBUNCE_MAX 10 #define TSC_DEBUNCE_REP 2 #define TS_POLL_PERIOD (20 * 1000) /* us delay between samples */ #endif //#define TS_POLL_PERIOD (5 * 1000) /* us delay between samples */ #define IRQ_TSC OPTIMUS_IRQ_TSC #define SSL_TSC_REG_ADDR OPTIMUS_IO_TSC #define TSC_GET_CLK_IN() optimus_get_pclk();//OPTIMUS_CLK_PER1 #ifndef CONFIG_SSLTSC_FOR_BATTERY static int ssltsc_debounce (void *ads, int *val_x, int *val_y, uint32_t * val_p); static int ssltsc_no_filter (void *ads, int *val_x, int *val_y, uint32_t * val_p); static ssize_t ssltsc_parameter_show (struct device *dev, struct device_attribute *attr, char *buf); static ssize_t ssltsc_parameter_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count); static DEVICE_ATTR (parameter, 0664, ssltsc_parameter_show, ssltsc_parameter_store); #endif static ssize_t ssltsc_vbat_show (struct device *dev, struct device_attribute *attr, char *buf); static DEVICE_ATTR (vbat, 0664, ssltsc_vbat_show, NULL); static ssize_t ssltsc_calibrate_set (struct device *dev, struct device_attribute *attr, char *buf); static DEVICE_ATTR (calibrate, 0664, NULL, ssltsc_calibrate_set); static struct attribute_group ssltsc_attr_group = { .attrs = ssltsc_attributes, }; EXPORT_SYMBOL(ssltsc_vbat); static ssize_t ssltsc_vbat_show (struct device *dev, struct device_attribute *attr, char *buf) { uint32_t voltage = ssltsc_vbat(); return sprintf (buf, "%d\n", voltage); } void ssl_calibrate_for_Android(int32_t *x, int32_t *y) { int32_t tx,ty; tx=*x; ty=*y; *x=(calibrate.a*tx + calibrate.b *ty +calibrate.c) / calibrate.div; *y=(calibrate.d*tx + calibrate.e *ty +calibrate.f) / calibrate.div; if ( *x < 0 ) *x = 0; if ( *y < 0 ) *y = 0; if ( *x > TSC_X_MAX ) *x = TSC_X_MAX; if ( *y > TSC_Y_MAX ) *y = TSC_Y_MAX; } static ssize_t ssltsc_calibrate_set (struct device *dev, struct device_attribute *attr, char *buf) { int32_t a,b,c,d,e,f,div; uint32_t x,y; db_tsc("get the argument: %s\n", buf); if (strncmp(buf,TSC_CAL_RESET,sizeof(TSC_CAL_RESET)-1)==0) { db_tsc("will reset the calibration data\n"); calibrate.a=1; calibrate.b=0; calibrate.c=0; calibrate.d=0; calibrate.e=1; calibrate.f=0; calibrate.div=1; goto _exit; } if (strncmp(buf,TSC_CAL_SHOW,sizeof(TSC_CAL_SHOW)-1)==0) { x=100;y=200; ssl_calibrate_for_Android(&x, &y); printk("(100,200) -> (%d, %d)\n", x,y); x=900;y=200; ssl_calibrate_for_Android(&x, &y); printk("(900,200) -> (%d, %d)\n", x,y); x=100;y=800; ssl_calibrate_for_Android(&x, &y); printk("(100,800) -> (%d, %d)\n", x,y); x=900;y=800; ssl_calibrate_for_Android(&x, &y); printk("(900,800) -> (%d, %d)\n", x,y); goto _exit; } sscanf(buf,"%d %d %d %d %d %d %d",&a,&b,&c,&d,&e,&f,&div); if (0==div) { db_err("canot set the div to 0!\n"); goto _exit; } calibrate.a=a; calibrate.b=b; calibrate.c=c; calibrate.d=d; calibrate.e=e; calibrate.f=f; calibrate.div=div; _exit: printk("calibration data:\n %d %d %d %d %d %d %d\n",calibrate.a, calibrate.b,\ calibrate.c,calibrate.d, calibrate.e,calibrate.f,calibrate.div); return -1; } #ifndef CONFIG_SSLTSC_FOR_BATTERY static ssize_t ssltsc_parameter_show (struct device *dev, struct device_attribute *attr, char *buf) { uint32_t clk, pclk; pclk = TSC_GET_CLK_IN (); db_tsc ("parameter show. pclk=%d Hz\n", pclk); clk = TSC_FROM_DIV (pclk, cfg->div); return sprintf (buf, "<SSL TSC parameter 1>\n<debounce>\n filter: %s, (x/y/p): %d/%d/%d/, repeat:%d, max:%d\n<sampling>\n clk:%d Hz, poll:%d us, power mode:0x%x\n", ts.filter_en ? "yes" : "no", ts.debounce_tol_x, ts.debounce_tol_y, ts.debounce_tol_p, ts.debounce_rep, ts.debounce_max, clk, ts.poll_period, cfg->pmd); } static int ssltsc_no_filter (void *ads, int *val_x, int *val_y, uint32_t * val_p) { return TSC_FILTER_OK; } /* * This function have these feature: * 1. while the first data is ready, that means pen down. * 2. while data action, that means need to sync event handler. * 3. while pen up, sync pen up event. And wait for pen down even. * **/ #ifdef BH_TIMER static enum hrtimer_restart ssltsc_timer (struct hrtimer *handle) { ssltsc_ctx *ts_dev = container_of(handle, ssltsc_ctx, timer); //struct input_dev *dev; uint32_t delay; int touchstate;//high is release printk("in ssltsc_timer\n"); spin_lock_irq(ts_dev->spin_lock); printk("0s\n"); ts_dev->touchData=kzalloc(sizeof(TOUCH_DATA_st), GFP_KERNEL); Msctpc_getData( ts_dev->input_dev,ts_dev->touchData ); spin_unlock_irq(ts_dev->spin_lock); return HRTIMER_NORESTART; } #elif defined BH_WQ static void ssltsc_worker (struct work_struct *work) { uint32_t delay; ssltsc_bottom_half (); /* Delay each even. If not, the interrupt come up frequently. At least it will delay 10 ms as 1 jiffes=10ms */ delay = ts.poll_period / 1000000 * HZ; // us to jiffes. if (!delay) delay = 1; schedule_timeout_uninterruptible (delay); enable_irq (ts.irq); if (pen_up_flg) { queue_work (ts.wq, &ts.work); schedule_timeout_uninterruptible (delay); } } #endif #endif static tsc_err tsc_isr_cy (tsc_p t) { //disable_irq(ON_TOUCH_INT); int i; int sumx=0,sumy=0; return TSC_ERR_NONE; } static irqreturn_t ssltsc_irq (int irq, void *dev_id) { uint32_t ret, bf_en; debounce_ret deb_ret; uint32_t irq_flags; printk(">>>>>>>>>enter irq...........\n"); spin_lock_irq(&ts.spin_lock); hrtimer_start (&ts.timer, ktime_set(0,sample_period),HRTIMER_MODE_REL); spin_unlock_irq(&ts.spin_lock); return IRQ_HANDLED; } /* * The functions for inserting/removing us as a module. */ static int __init ssltsc_probe (struct platform_device *dev) { int err; struct input_dev *input_dev; /* Initialise tsc_t structure. */ memset (&ts, 0, sizeof (tsc_t)); printk("in ssltsc_probe,%d\n",gpio_get_value(TOUCH_INT_PIN)); ts.hw.reg = (void __iomem *) ioremap_nocache (SSL_TSC_REG_ADDR, sizeof (tscr_t)); if (ts.hw.reg == NULL) { db_err ("Failed to remap register block \n"); err = -ENOMEM; goto l_iomap; } /* Initial TSC module */ err = (int) tsc_init (&ts.hw); if (err) { db_err ("init tsc failed.\n"); goto l_tsc_init; } pendown = 0; #ifndef CONFIG_SSLTSC_FOR_BATTERY #ifdef BH_TIMER #warning "timer bottom half." /*initial timer. */ hrtimer_init (&ts.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ts.timer.function = ssltsc_timer; db_tsc ("timer bottom half.\n"); #elif defined BH_WQ #warning "work queue bottom half." /*initial work queue. */ INIT_WORK (&ts.work, ssltsc_worker); ts.wq = create_singlethread_workqueue (dev->name); db_tsc ("work queue bottom half.\n"); if (!ts.wq) { db_err ("create wq fail.\n"); err = -EBUSY; goto l_wq_err; } #elif defined BH_NONE #warning "NO bottom half." db_tsc ("no bottom half.\n"); #else #error "****** NO define bottom half.********" #endif #endif platform_set_drvdata(dev, &ts); #ifndef CONFIG_SSLTSC_FOR_BATTERY /*initial input system. */ input_dev = input_allocate_device (); if (!input_dev) { printk (KERN_ERR "Unable to allocate the input device !!\n"); err = -ENOMEM; goto l_input_dev; } ts.input_dev = input_dev; ts.input_dev->evbit[0] = BIT_MASK (EV_SYN) | BIT_MASK (EV_KEY) | BIT_MASK (EV_ABS); ts.input_dev->keybit[BIT_WORD (BTN_TOUCH)] = BIT_MASK (BTN_TOUCH); ts.input_dev->keybit[BIT_WORD (KEY_HOME)] = BIT_MASK (KEY_HOME); ts.input_dev->keybit[BIT_WORD (KEY_BACK)] = BIT_MASK(KEY_BACK)|BIT_MASK(KEY_MENU); ts.input_dev->name = ssltsc_name; snprintf(ts.phys,sizeof(ts.phys),"%s/input0",dev_name(dev)); ts.input_dev->phys = ts.phys; input_set_abs_params (ts.input_dev, ABS_X, 0, X_MAX, 0, 0); input_set_abs_params (ts.input_dev, ABS_Y, 0, Y_MAX, 0, 0); input_set_abs_params (ts.input_dev, ABS_PRESSURE, 0, 1, 0, 0); //input_set_abs_params(ts.input_dev, ABS_HAT0X, 0, X_MAX, 0, 0); //input_set_abs_params(ts.input_dev, ABS_HAT0Y, 0,Y_MAX, 0, 0); /* All went ok, so register to the input system */ err = input_register_device (ts.input_dev); if (err) { db_err ("register input system failed (%d).\n", err); goto l_reg_input; } /* Initial debounce paramter */ ts.debounce_max = TSC_DEBUNCE_MAX; ts.debounce_tol_x = X_LIMIT; ts.debounce_tol_y = Y_LIMIT; ts.debounce_tol_p = P_LIMIT; ts.debounce_rep = TSC_DEBUNCE_REP; ts.filter_en = 1; ts.filter = ssltsc_debounce; ts.poll_period = TS_POLL_PERIOD; cfg = &ssltsc_default_cfg; #else /* Initial debounce paramter */ ts.debounce_max = 10; ts.debounce_tol_x = X_LIMIT; ts.debounce_tol_y = Y_LIMIT; ts.debounce_tol_p = P_LIMIT; ts.debounce_rep = 4; //ts.debounce_rep = 2; ts.filter_en = 1; ts.filter = NULL; ts.poll_period = TS_POLL_PERIOD; cfg = &ssltsc_default_cfg; ts.input_dev = NULL; #endif err = (int) tsc_cfg (&ts.hw, cfg); if (err) { db_err ("cfg tsc failed.\n"); goto l_tsc_cfg; } spin_lock_init(&ts.spin_lock); ON_TOUCH_INT = gpio_to_irq(TOUCH_INT_PIN); if (AUO_INT_LOW) { set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); } else { set_irq_type(irq, IRQ_TYPE_EDGE_RISING); } if (request_irq(ON_TOUCH_INT, ssltsc_irq, IRQF_DISABLED|IRQF_TRIGGER_FALLING, "ssltsc", ts.input_dev)) { printk("request_irq erro\n"); return -1; } else { printk(">>>>>end request_irq\n"); } /* Create sysfs attributes to monitor TSC. */ err = sysfs_create_group (&dev->dev.kobj, &ssltsc_attr_group); if (err) { db_err ("Can't create sysfs attributes!\n "); goto l_sysfs; } printk (KERN_INFO "%s successfully loaded \n", ssltsc_name); return 0; /*Error */ l_sysfs: free_irq (IRQ_TSC, ts.input_dev); l_irq: l_tsc_cfg: input_unregister_device (ts.input_dev); l_reg_input: //input_free_device (ts.input_dev); l_input_dev: #ifdef BH_WQ destroy_workqueue (ts.wq); l_wq_err: #endif tsc_exit (&ts.hw); l_tsc_init: iounmap (ts.hw.reg); l_iomap: db_err ("loaded fail.(%d)\n", err); return err; } static int ssltsc_remove (struct platform_device *dev) { /* Remove sysfs attributes */ sysfs_remove_group (&dev->dev.kobj, &ssltsc_attr_group); /* free irq. */ free_irq (IRQ_TSC, ts.input_dev); /* free timer. */ #ifdef BH_WQ flush_workqueue (ts.wq); destroy_workqueue (ts.wq); #endif /* free module. */ tsc_exit (&ts.hw); #ifndef CONFIG_SSLTSC_FOR_BATTERY /* free input system. */ input_unregister_device (ts.input_dev); //input_free_device (ts.input_dev); #endif /* free memory. */ iounmap (ts.hw.reg); return 0; } void ssltsc_device_release (struct device *dev) { return; } static struct platform_device ssltsc_device = { .name = "ssltsc", .id = -1, .dev = { .release = ssltsc_device_release, } }; static struct platform_driver ssltsc_driver = { .driver = { .name = "ssltsc", .owner = THIS_MODULE, }, .probe = ssltsc_probe, .remove = ssltsc_remove, }; int __init ssltsc_init (void) { int ret; db_tsc ("insmod ssltsc.\n"); #if 1 //device ret = platform_device_register (&ssltsc_device); if (ret) return ret; #endif return platform_driver_register (&ssltsc_driver); } void __exit ssltsc_exit (void) { platform_driver_unregister (&ssltsc_driver); #if 1 //device platform_device_unregister (&ssltsc_device); #endif db_tsc ("rmmod ssltsc.\n"); } module_init (ssltsc_init); module_exit (ssltsc_exit); MODULE_AUTHOR ("Spiritwen@solomon-systech.com"); MODULE_DESCRIPTION ("Optimus TSC Device Driver"); MODULE_LICENSE ("GPL");