static void s3c2410_adc_stylus_action(void) { rt_uint32_t data0; rt_uint32_t data1; data0 = ADCDAT0; data1 = ADCDAT1; ts.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK; ts.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK; ts.count ++; if (ts.count < (1<<ts.shift)) { ADCTSC = S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST; ADCCON |= S3C2410_ADCCON_ENABLE_START; } else { if (touch->first_down_report) { report_touch_input(1); ts.xp = 0; ts.yp = 0; ts.count = 0; touch->first_down_report = 0; } /* start timer */ rt_timer_start(touch->poll_timer); ADCTSC = WAIT4INT(1); } SUBSRCPND |= BIT_SUB_ADC; }
static void s3c2410_intc_stylus_updown(void) { rt_uint32_t data0; rt_uint32_t data1; int updown; data0 = ADCDAT0; data1 = ADCDAT1; updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); /* rt_kprintf("stylus: %s\n", updown? "down" : "up"); */ if (updown) { touch_timer_fire(0); } else { /* stop timer */ rt_timer_stop(touch->poll_timer); touch->first_down_report = RT_TRUE; if (ts.xp >= 0 && ts.yp >= 0) { report_touch_input(updown); } ts.count = 0; ADCTSC = WAIT4INT(0); } SUBSRCPND |= BIT_SUB_TC; }
static int s3c2410ts_resume(struct platform_device *pdev) { struct s3c2410_ts_mach_info *info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data; clk_enable(adc_clock); mdelay(1); ts_filter_chain_clear(ts.chain); enable_irq(IRQ_ADC); enable_irq(IRQ_TC); if ((info->presc&0xff) > 0) writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF), base_addr+S3C2410_ADCCON); else writel(0,base_addr+S3C2410_ADCCON); /* Initialise registers */ if ((info->delay & 0xffff) > 0) writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY); writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC); return 0; }
/* RT-Thread Device Interface */ static rt_err_t rtgui_touch_init(rt_device_t dev) { /* init touch screen structure */ rt_memset(&ts, 0, sizeof(struct s3c2410ts)); ts.delay = 50000; ts.presc = 9; ts.shift = 2; ts.count = 0; ts.xp = ts.yp = 0; ADCCON = S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(ts.presc); ADCDLY = ts.delay; ADCTSC = WAIT4INT(0); rt_hw_interrupt_install(INTADC, rt_touch_handler, RT_NULL); rt_hw_interrupt_umask(INTADC); /* clear interrupt */ INTPND |= (1ul << INTADC); SUBSRCPND |= BIT_SUB_TC; SUBSRCPND |= BIT_SUB_ADC; /* install interrupt handler */ INTSUBMSK &= ~BIT_SUB_ADC; INTSUBMSK &= ~BIT_SUB_TC; touch->first_down_report = RT_TRUE; return RT_EOK; }
static irqreturn_t stylus_action(int irqno, void *param) { unsigned long data0; unsigned long data1; data0 = readl(ts_base + S3C_ADCDAT0); data1 = readl(ts_base + S3C_ADCDAT1); if (ts->resol_bit == 12) { ts->xp += S3C_ADCDAT0_XPDATA_MASK_12BIT - (data0 & S3C_ADCDAT0_XPDATA_MASK_12BIT); ts->yp += data1 & S3C_ADCDAT1_YPDATA_MASK_12BIT; } else { ts->xp += data0 & S3C_ADCDAT0_XPDATA_MASK; ts->yp += data1 & S3C_ADCDAT1_YPDATA_MASK; } ts->count++; if (ts->count < (1<<ts->shift)) { writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base + S3C_ADCTSC); writel(readl(ts_base + S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base + S3C_ADCCON); } else { mod_timer(&touch_timer, jiffies + 1); writel(WAIT4INT(1), ts_base + S3C_ADCTSC); } if (ts->s3c_adc_con == ADC_TYPE_2) { __raw_writel(0x0, ts_base+S3C_ADCCLRWK); __raw_writel(0x0, ts_base+S3C_ADCCLRINT); } return IRQ_HANDLED; }
static irqreturn_t stylus_updown(int irq, void *dev_id) { unsigned long data0; unsigned long data1; int event_type; data0 = readl(base_addr+S3C2410_ADCDAT0); data1 = readl(base_addr+S3C2410_ADCDAT1); ts.is_down = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN)); event_type = ts.is_down ? 'D' : 'U'; if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)&event_type, sizeof(int)) != sizeof(int))) /* should not happen */ printk(KERN_ERR __FILE__": stylus_updown lost event!\n"); if (ts.is_down) s3c2410_ts_start_adc_conversion(); else writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC); mod_timer(&event_send_timer, jiffies + 1); return IRQ_HANDLED; }
static irqreturn_t stylus_action(int irq, void *dev_id) { int buf[3]; /* Grab the ADC results. */ buf[1] = readl(base_addr + S3C2410_ADCDAT0) & S3C2410_ADCDAT0_XPDATA_MASK; buf[2] = readl(base_addr + S3C2410_ADCDAT1) & S3C2410_ADCDAT1_YPDATA_MASK; switch (ts_filter_chain_feed(ts.chain, &buf[1])) { case 0: /* The filter wants more points. */ s3c2410_ts_start_adc_conversion(); return IRQ_HANDLED; case 1: /* We have a point from the filters or no filtering enabled. */ buf[0] = 'P'; break; default: printk(KERN_ERR __FILE__ ":%d Invalid ts_filter_chain_feed return value.\n", __LINE__); case -1: /* Error. Ignore the event. */ ts_filter_chain_clear(ts.chain); writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC); return IRQ_HANDLED; }; if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)buf, sizeof(int) * 3) != sizeof(int) * 3)) printk(KERN_ERR __FILE__":stylus_action bug.\n"); writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC); mod_timer(&event_send_timer, jiffies + 1); return IRQ_HANDLED; }
static int s3c_ts_resume(struct platform_device *pdev) { clk_enable(ts_clock); writel(adccon, ts_base+S3C_ADCCON); writel(adctsc, ts_base+S3C_ADCTSC); writel(adcdly, ts_base+S3C_ADCDLY); writel(WAIT4INT(0), ts_base+S3C_ADCTSC); enable_irq(IRQ_ADC1); enable_irq(IRQ_PENDN1); return 0; }
static irqreturn_t stylus_action(int irqno, void *param) { unsigned long data0; unsigned long data1; data0 = readl(ts_base+S3C_ADCDAT0); data1 = readl(ts_base+S3C_ADCDAT1); if (ts->resol_bit == 12) { #if defined(CONFIG_TOUCHSCREEN_NEW) ts->yp += S3C_ADCDAT0_XPDATA_MASK_12BIT - (data0 & S3C_ADCDAT0_XPDATA_MASK_12BIT); ts->xp += S3C_ADCDAT1_YPDATA_MASK_12BIT - (data1 & S3C_ADCDAT1_YPDATA_MASK_12BIT); #else /* CONFIG_TOUCHSCREEN_NEW */ #ifndef CONFIG_CPU_S5PV210_EVT1 ts->xp += data0 & S3C_ADCDAT0_XPDATA_MASK_12BIT; #else /* !CONFIG_CPU_S5PV210_EVT1 */ #if defined(CONFIG_MACH_MANGO210) ts->xp += data0 & S3C_ADCDAT0_XPDATA_MASK_12BIT; #else ts->xp += S3C_ADCDAT0_XPDATA_MASK_12BIT - (data0 & S3C_ADCDAT0_XPDATA_MASK_12BIT); #endif #endif /* !CONFIG_CPU_S5PV210_EVT1 */ ts->yp += data1 & S3C_ADCDAT1_YPDATA_MASK_12BIT; #endif /* CONFIG_TOUCHSCREEN_NEW */ } else { #if defined(CONFIG_TOUCHSCREEN_NEW) ts->yp += S3C_ADCDAT0_XPDATA_MASK - (data0 & S3C_ADCDAT0_XPDATA_MASK); ts->xp += S3C_ADCDAT1_YPDATA_MASK - (data1 & S3C_ADCDAT1_YPDATA_MASK); #else /* CONFIG_TOUCHSCREEN_NEW */ ts->xp += data0 & S3C_ADCDAT0_XPDATA_MASK; ts->yp += data1 & S3C_ADCDAT1_YPDATA_MASK; #endif /* CONFIG_TOUCHSCREEN_NEW */ } ts->count++; if (ts->count < (1<<ts->shift)) { writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base+S3C_ADCTSC); writel(readl(ts_base+S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base+S3C_ADCCON); } else { mod_timer(&touch_timer, jiffies+1); writel(WAIT4INT(1), ts_base+S3C_ADCTSC); } if (ts->s3c_adc_con == ADC_TYPE_2) { __raw_writel(0x0, ts_base+S3C_ADCCLRWK); __raw_writel(0x0, ts_base+S3C_ADCCLRINT); } return IRQ_HANDLED; }
static int s3c_ts_resume(struct platform_device *pdev) { clk_enable(ts_clock); #ifdef CONFIG_TOUCHSCREEN_USEAD1 writel(readl(ts_base0 + S3C_ADCCON) | 0x20000, ts_base0 + S3C_ADCCON); #endif writel(adccon, ts_base+S3C_ADCCON); writel(adctsc, ts_base+S3C_ADCTSC); writel(adcdly, ts_base+S3C_ADCDLY); writel(WAIT4INT(0), ts_base+S3C_ADCTSC); enable_irq(IRQ_ADC); enable_irq(IRQ_PENDN); return 0; }
static void touch_timer_fire(unsigned long data) { unsigned long data0, data1; int updown; int x, y; s3c_adc_lock(); data0 = readl(ts_base+S3C_ADCDAT0); data1 = readl(ts_base+S3C_ADCDAT1); updown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN)); if (updown) { if (ts->count) { x = (int)ts->xp/ts->count; y = (int)ts->yp/ts->count; input_report_abs(ts->dev, ABS_X, x); input_report_abs(ts->dev, ABS_Y, y); input_report_abs(ts->dev, ABS_PRESSURE, 1); input_report_key(ts->dev, BTN_TOUCH, 1); input_sync(ts->dev); } ts->xp = 0; ts->yp = 0; ts->count = 0; writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base + S3C_ADCTSC); writel(readl(ts_base+S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base + S3C_ADCCON); } else { ts->count = 0; input_report_abs(ts->dev, ABS_PRESSURE, 0); input_report_key(ts->dev, BTN_TOUCH, 0); input_sync(ts->dev); writel(WAIT4INT(0), ts_base+S3C_ADCTSC); } s3c_adc_unlock(); }
static void touch_timer_fire(unsigned long data) { unsigned long data0; unsigned long data1; int updown; #ifdef CONFIG_ANDROID int x,y; #ifndef CONFIG_CPU_S5PV210_EVT1 #ifdef CONFIG_TOUCHSCREEN_NEW int a0,a1,a2,a3,a4,a5,a6; a0=11; a1=3004; a2=-9542528; a3=-4300; a4=4; a5=61817184; a6=65536; #else /* CONFIG_TOUCHSCREEN_NEW */ a0=5171; a1=9; a2=-17497920; a3=-12; a4=-4659; a5=52871808; a6=65536; #endif /* CONFIG_TOUCHSCREEN_NEW */ #endif /* !CONFIG_CPU_S5PV210_EVT1 */ #endif /* CONFIG_ANDROID */ data0 = readl(ts_base+S3C_ADCDAT0); data1 = readl(ts_base+S3C_ADCDAT1); updown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN)); if (updown) { if (ts->count) { #ifdef CONFIG_TOUCHSCREEN_S3C_DEBUG { struct timeval tv; do_gettimeofday(&tv); printk(KERN_INFO "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts->xp, ts->yp); } #endif #ifdef CONFIG_ANDROID #ifndef CONFIG_CPU_S5PV210_EVT1 x=(int) ts->xp; y=(int) ts->yp; ts->xp=(long) ((a2+(a0*x)+(a1*y))/a6) * 800/480; ts->yp=(long) ((a5+(a3*x)+(a4*y))/a6) * 480/800; //printk("x=%d, y=%d\n",(int) ts->xp,(int) ts->yp); if (ts->xp!=ts->xp_old || ts->yp!=ts->yp_old) { input_report_abs(ts->dev, ABS_X, ts->xp); input_report_abs(ts->dev, ABS_Y, ts->yp); input_report_abs(ts->dev, ABS_Z, 0); input_report_key(ts->dev, BTN_TOUCH, 1); // input_report_abs(ts->dev, ABS_PRESSURE, 1); input_sync(ts->dev); } ts->xp_old=ts->xp; ts->yp_old=ts->yp; #else /* !CONFIG_CPU_S5PV210_EVT1 */ x=(int) ts->xp/ts->count; y=(int) ts->yp/ts->count; #if defined(CONFIG_FB_S3C_LTE480WV) y = 4000 - y; #endif /* CONFIG_FB_S3C_LTE480WV */ //printk("Cordinates x=%d, y=%d\n",(int) x,(int) y); input_report_abs(ts->dev, ABS_X, x); input_report_abs(ts->dev, ABS_Y, y); input_report_abs(ts->dev, ABS_Z, 0); input_report_key(ts->dev, BTN_TOUCH, 1); input_sync(ts->dev); #endif /* !CONFIG_CPU_S5PV210_EVT1 */ #else /* CONFIG_ANDROID */ input_report_abs(ts->dev, ABS_X, ts->xp); input_report_abs(ts->dev, ABS_Y, ts->yp); input_report_key(ts->dev, BTN_TOUCH, 1); input_report_abs(ts->dev, ABS_PRESSURE, 1); input_sync(ts->dev); #endif /* CONFIG_ANDROID */ } ts->xp = 0; ts->yp = 0; ts->count = 0; writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base+S3C_ADCTSC); writel(readl(ts_base+S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base+S3C_ADCCON); } else { ts->count = 0; #ifdef CONFIG_ANDROID #ifdef CONFIG_CPU_S5PV210_EVT1 input_report_abs(ts->dev, ABS_X, ts->xp); input_report_abs(ts->dev, ABS_Y, ts->yp); #else /* CONFIG_CPU_S5PV210_EVT1 */ input_report_abs(ts->dev, ABS_X, ts->xp_old); input_report_abs(ts->dev, ABS_Y, ts->yp_old); #endif /* CONFIG_CPU_S5PV210_EVT1 */ input_report_abs(ts->dev, ABS_Z, 0); #endif /* CONFIG_ANDROID */ input_report_key(ts->dev, BTN_TOUCH, 0); #ifndef CONFIG_ANDROID input_report_abs(ts->dev, ABS_PRESSURE, 0); #endif /* !CONFIG_ANDROID */ input_sync(ts->dev); writel(WAIT4INT(0), ts_base+S3C_ADCTSC); } }
/* * The functions for inserting/removing us as a module. */ static int __init s3c_ts_probe(struct platform_device *pdev) { struct resource *res; struct device *dev; struct input_dev *input_dev; struct s3c_ts_mach_info *s3c_ts_cfg; int ret, size; int irq_flags = 0; #ifdef CONFIG_TOUCHSCREEN_ADC1 int tmp; #endif dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(dev, "no memory resource specified\n"); return -ENOENT; } size = (res->end - res->start) + 1; ts_mem = request_mem_region(res->start, size, pdev->name); if (ts_mem == NULL) { dev_err(dev, "failed to get memory region\n"); ret = -ENOENT; goto err_req; } ts_base = ioremap(res->start, size); #ifdef CONFIG_TOUCHSCREEN_ADC1 //Set TSADCCON0 bit 17 tmp = readl(ts_base); tmp |= (0x01 << 17); writel(tmp, ts_base); //remap ts_base to 0xE1701000 iounmap(ts_base); release_resource(ts_mem); ts_mem = request_mem_region(res->start + 0x1000, size, pdev->name); ts_base = ioremap(res->start + 0x1000, size); printk("remap to 0xE1701000. done\n"); #endif if (ts_base == NULL) { dev_err(dev, "failed to ioremap() region\n"); ret = -EINVAL; goto err_map; } ts_clock = clk_get(&pdev->dev, "adc"); if (IS_ERR(ts_clock)) { dev_err(dev, "failed to find watchdog clock source\n"); ret = PTR_ERR(ts_clock); goto err_clk; } clk_enable(ts_clock); s3c_ts_cfg = s3c_ts_get_platdata(&pdev->dev); if ((s3c_ts_cfg->presc & 0xff) > 0) writel(S3C_ADCCON_PRSCEN | S3C_ADCCON_PRSCVL(s3c_ts_cfg->presc & 0xFF), ts_base+S3C_ADCCON); else writel(0, ts_base + S3C_ADCCON); /* Initialise registers */ if ((s3c_ts_cfg->delay & 0xffff) > 0) writel(s3c_ts_cfg->delay & 0xffff, ts_base + S3C_ADCDLY); if (s3c_ts_cfg->resol_bit == 12) { switch (s3c_ts_cfg->s3c_adc_con) { case ADC_TYPE_2: writel(readl(ts_base + S3C_ADCCON) | S3C_ADCCON_RESSEL_12BIT, ts_base + S3C_ADCCON); break; case ADC_TYPE_1: writel(readl(ts_base + S3C_ADCCON) | S3C_ADCCON_RESSEL_12BIT_1, ts_base + S3C_ADCCON); break; default: dev_err(dev, "this type of AP isn't supported !\n"); break; } } writel(WAIT4INT(0), ts_base + S3C_ADCTSC); ts = kzalloc(sizeof(struct s3c_ts_info), GFP_KERNEL); input_dev = input_allocate_device(); if (!input_dev) { ret = -ENOMEM; goto err_alloc; } ts->dev = input_dev; ts->dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); ts->dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); if (s3c_ts_cfg->resol_bit == 12) { input_set_abs_params(ts->dev, ABS_X, 0, 0xFFF, 0, 0); input_set_abs_params(ts->dev, ABS_Y, 0, 0xFFF, 0, 0); } else { input_set_abs_params(ts->dev, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(ts->dev, ABS_Y, 0, 0x3FF, 0, 0); } input_set_abs_params(ts->dev, ABS_PRESSURE, 0, 1, 0, 0); sprintf(ts->phys, "input-ts"); ts->dev->name = s3c_ts_name; ts->dev->phys = ts->phys; ts->dev->id.bustype = BUS_RS232; ts->dev->id.vendor = 0xDEAD; ts->dev->id.product = 0xBEEF; ts->dev->id.version = S3C_TSVERSION; ts->shift = s3c_ts_cfg->oversampling_shift; ts->resol_bit = s3c_ts_cfg->resol_bit; ts->s3c_adc_con = s3c_ts_cfg->s3c_adc_con; /* For IRQ_PENDUP */ ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (ts_irq == NULL) { dev_err(dev, "no irq resource specified\n"); ret = -ENOENT; goto err_irq; } ret = request_irq(ts_irq->start, stylus_updown, irq_flags, "s3c_updown", ts); if (ret != 0) { dev_err(dev, "s3c_ts.c: Could not allocate ts IRQ_PENDN !\n"); ret = -EIO; goto err_irq; } /* For IRQ_ADC */ ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (ts_irq == NULL) { dev_err(dev, "no irq resource specified\n"); ret = -ENOENT; goto err_irq; } ret = request_irq(ts_irq->start, stylus_action, irq_flags, "s3c_action", ts); if (ret != 0) { dev_err(dev, "s3c_ts.c: Could not allocate ts IRQ_ADC !\n"); ret = -EIO; goto err_irq; } printk(KERN_INFO "%s got loaded successfully : %d bits\n", s3c_ts_name, s3c_ts_cfg->resol_bit); /* All went ok, so register to the input system */ ret = input_register_device(ts->dev); if (ret) { dev_err(dev, "Could not register input device(touchscreen)!\n"); ret = -EIO; goto fail; } return 0; fail: free_irq(ts_irq->start, ts->dev); free_irq(ts_irq->end, ts->dev); err_irq: input_free_device(input_dev); kfree(ts); err_alloc: clk_disable(ts_clock); clk_put(ts_clock); err_clk: iounmap(ts_base); err_map: release_resource(ts_mem); kfree(ts_mem); err_req: return ret; }
static void touch_timer_fire(unsigned long data) { unsigned long data0; unsigned long data1; int updown; unsigned long dist; #ifdef CONFIG_S3CTS_ANDROID unsigned long xtemp, ytemp; #endif data0 = readl(ts_base+S3C_ADCDAT0); data1 = readl(ts_base+S3C_ADCDAT1); updown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN)); if (updown) { if (ts->count) { #ifdef CONFIG_TOUCHSCREEN_S3C_DEBUG { struct timeval tv; do_gettimeofday(&tv); printk(KERN_INFO "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts->xp, ts->yp); } #endif // If you want calibrate touch screen, #if set 1 to 0. #if 1 xtemp = ts->xp; ytemp = ts->yp; if( !last_flag ) { last = ts; last_flag = 1; } dist = sqr( xtemp - last->xp ) + sqr( ytemp - last->yp ); if ( dist > delta ) { return; } ts->xp = ( pointercal[2] + pointercal[0]*xtemp + pointercal[1]*ytemp ) / pointercal[6]; ts->yp = ( pointercal[5] + pointercal[3]*xtemp + pointercal[4]*ytemp ) / pointercal[6]; #ifdef CONFIG_ANDROID_TOUCHSCREEN_S3C_DEBUG printk("pre: x, y = %ld, %ld\n", ts->xp, ts->yp); #endif if( ts->xp > 65500 ) ts->xp = 1; if( ts->xp > ANDROID_TS_RESOLUTION_X ) ts->xp = ANDROID_TS_RESOLUTION_X-1; else if(ts->xp < 0) ts->xp = 1; if( ts->yp > ANDROID_TS_RESOLUTION_Y ) ts->yp = ANDROID_TS_RESOLUTION_Y-1; else if(ts->yp < 0) ts->yp = 1; if( (ts->xp <= ANDROID_TS_RESOLUTION_X-1) && (ts->xp >= 1) ) { input_report_abs(ts->dev, ABS_X, ts->xp); input_report_abs(ts->dev, ABS_Y, ts->yp); input_report_key(ts->dev, BTN_TOUCH, 1); input_report_abs(ts->dev, ABS_PRESSURE, 1); input_sync(ts->dev); #ifdef CONFIG_ANDROID_TOUCHSCREEN_S3C_DEBUG printk("x, y = %ld, %ld\n", ts->xp, ts->yp); #endif } #else input_report_abs(ts->dev, ABS_X, ts->xp); input_report_abs(ts->dev, ABS_Y, ts->yp); input_report_key(ts->dev, BTN_TOUCH, 1); input_report_abs(ts->dev, ABS_PRESSURE, 1); input_sync(ts->dev); printk("x, y = %d, %d\n", ts->xp, ts->yp); #endif } ts->xp = 0; ts->yp = 0; ts->count = 0; writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base + S3C_ADCTSC); writel(readl(ts_base+S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base + S3C_ADCCON); } else { ts->count = 0; last_flag = 0; // input_report_abs(ts->dev, ABS_X, ts->xp); // input_report_abs(ts->dev, ABS_Y, ts->yp); // input_report_abs(ts->dev, ABS_Z, 0); // input_report_key(ts->dev, BTN_TOUCH, 0); // input_sync(ts->dev); input_report_key(ts->dev, BTN_TOUCH, 0); input_report_abs(ts->dev, ABS_PRESSURE, 0); input_sync(ts->dev); writel(WAIT4INT(0), ts_base+S3C_ADCTSC); } }
static int __init s3c2410ts_probe(struct platform_device *pdev) { int rc; struct s3c2410_ts_mach_info *info; struct input_dev *input_dev; int ret = 0; dev_info(&pdev->dev, "Starting\n"); info = (struct s3c2410_ts_mach_info *)pdev->dev.platform_data; if (!info) { dev_err(&pdev->dev, "Hm... too bad: no platform data for ts\n"); return -EINVAL; } #ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG printk(DEBUG_LVL "Entering s3c2410ts_init\n"); #endif adc_clock = clk_get(NULL, "adc"); if (!adc_clock) { dev_err(&pdev->dev, "failed to get adc clock source\n"); return -ENOENT; } clk_enable(adc_clock); #ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG printk(DEBUG_LVL "got and enabled clock\n"); #endif base_addr = ioremap(S3C2410_PA_ADC,0x20); if (base_addr == NULL) { dev_err(&pdev->dev, "Failed to remap register block\n"); ret = -ENOMEM; goto bail0; } /* If we acutally are a S3C2410: Configure GPIOs */ if (!strcmp(pdev->name, "s3c2410-ts")) s3c2410_ts_connect(); if ((info->presc & 0xff) > 0) writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF), base_addr + S3C2410_ADCCON); else writel(0, base_addr+S3C2410_ADCCON); /* Initialise registers */ if ((info->delay & 0xffff) > 0) writel(info->delay & 0xffff, base_addr + S3C2410_ADCDLY); writel(WAIT4INT(0), base_addr + S3C2410_ADCTSC); /* Initialise input stuff */ memset(&ts, 0, sizeof(struct s3c2410ts)); input_dev = input_allocate_device(); if (!input_dev) { dev_err(&pdev->dev, "Unable to allocate the input device\n"); ret = -ENOMEM; goto bail1; } ts.dev = input_dev; ts.dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); ts.dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0); input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0); ts.dev->name = s3c2410ts_name; ts.dev->id.bustype = BUS_RS232; ts.dev->id.vendor = 0xDEAD; ts.dev->id.product = 0xBEEF; ts.dev->id.version = S3C2410TSVERSION; ts.state = TS_STATE_STANDBY; ts.event_fifo = kfifo_alloc(TS_EVENT_FIFO_SIZE, GFP_KERNEL, NULL); if (IS_ERR(ts.event_fifo)) { ret = -EIO; goto bail2; } /* create the filter chain set up for the 2 coordinates we produce */ ts.chain = ts_filter_chain_create(pdev, info->filter_config, 2); if (IS_ERR(ts.chain)) goto bail2; ts_filter_chain_clear(ts.chain); /* Get irqs */ if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM, "s3c2410_action", ts.dev)) { dev_err(&pdev->dev, "Could not allocate ts IRQ_ADC !\n"); iounmap(base_addr); ret = -EIO; goto bail3; } if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM, "s3c2410_action", ts.dev)) { dev_err(&pdev->dev, "Could not allocate ts IRQ_TC !\n"); free_irq(IRQ_ADC, ts.dev); iounmap(base_addr); ret = -EIO; goto bail4; } dev_info(&pdev->dev, "Successfully loaded\n"); /* All went ok, so register to the input system */ rc = input_register_device(ts.dev); if (rc) { ret = -EIO; goto bail5; } return 0; bail5: free_irq(IRQ_TC, ts.dev); free_irq(IRQ_ADC, ts.dev); clk_disable(adc_clock); iounmap(base_addr); disable_irq(IRQ_TC); bail4: disable_irq(IRQ_ADC); bail3: ts_filter_chain_destroy(ts.chain); kfifo_free(ts.event_fifo); bail2: input_unregister_device(ts.dev); bail1: iounmap(base_addr); bail0: return ret; }
static void touch_timer_fire(unsigned long data) { unsigned long data0; unsigned long data1; int updown; #ifdef CONFIG_ANDROID int x,y; #endif /* CONFIG_ANDROID */ data0 = readl(ts_base+S3C_ADCDAT0); data1 = readl(ts_base+S3C_ADCDAT1); updown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN)); if (updown) { if (ts->count) { #ifdef CONFIG_TOUCHSCREEN_S3C_DEBUG { struct timeval tv; do_gettimeofday(&tv); printk(KERN_INFO "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts->xp, ts->yp); } #endif #ifdef CONFIG_ANDROID x=(int) ts->xp/ts->count; y=(int) ts->yp/ts->count; #if defined(CONFIG_FB_S3C_LTE480WV) || defined(CONFIG_FB_S3C_UTLCD7B) y = 4000 - y; #endif /* CONFIG_FB_S3C_LTE480WV */ input_report_abs(ts->dev, ABS_X, x); input_report_abs(ts->dev, ABS_Y, y); input_report_abs(ts->dev, ABS_Z, 0); input_report_key(ts->dev, BTN_TOUCH, 1); input_sync(ts->dev); #else /* CONFIG_ANDROID */ input_report_abs(ts->dev, ABS_X, ts->xp); input_report_abs(ts->dev, ABS_Y, ts->yp); input_report_key(ts->dev, BTN_TOUCH, 1); input_report_abs(ts->dev, ABS_PRESSURE, 1); input_sync(ts->dev); #endif /* CONFIG_ANDROID */ } ts->xp = 0; ts->yp = 0; ts->count = 0; writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base+S3C_ADCTSC); writel(readl(ts_base+S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base+S3C_ADCCON); } else { ts->count = 0; #ifdef CONFIG_ANDROID input_report_abs(ts->dev, ABS_X, ts->xp); input_report_abs(ts->dev, ABS_Y, ts->yp); input_report_abs(ts->dev, ABS_Z, 0); #endif /* CONFIG_ANDROID */ input_report_key(ts->dev, BTN_TOUCH, 0); #ifndef CONFIG_ANDROID input_report_abs(ts->dev, ABS_PRESSURE, 0); #endif /* !CONFIG_ANDROID */ input_sync(ts->dev); writel(WAIT4INT(0), ts_base+S3C_ADCTSC); } }
/* * The functions for inserting/removing us as a module. */ static int __init s3c_ts_probe(struct platform_device *pdev) { struct resource *res; struct device *dev; struct input_dev *input_dev; struct s3c_ts_mach_info *s3c_ts_cfg; int ret, size; int irq_flags = 0; dev = &pdev->dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { dev_err(dev, "no memory resource specified\n"); return -ENOENT; } size = (res->end - res->start) + 1; ts_mem = request_mem_region(res->start, size, pdev->name); if (ts_mem == NULL) { dev_err(dev, "failed to get memory region\n"); ret = -ENOENT; goto err_req; } ts_base = ioremap(res->start, size); if (ts_base == NULL) { dev_err(dev, "failed to ioremap() region\n"); ret = -EINVAL; goto err_map; } ts_clock = clk_get(&pdev->dev, "adc"); if (IS_ERR(ts_clock)) { dev_err(dev, "failed to find watchdog clock source\n"); ret = PTR_ERR(ts_clock); goto err_clk; } clk_enable(ts_clock); s3c_ts_cfg = s3c_ts_get_platdata(&pdev->dev); if ((s3c_ts_cfg->presc&0xff) > 0) writel(S3C_ADCCON_PRSCEN | S3C_ADCCON_PRSCVL(s3c_ts_cfg->presc&0xFF),\ ts_base+S3C_ADCCON); else writel(0, ts_base+S3C_ADCCON); /* Initialise registers */ if ((s3c_ts_cfg->delay&0xffff) > 0) writel(s3c_ts_cfg->delay & 0xffff, ts_base+S3C_ADCDLY); if (s3c_ts_cfg->resol_bit == 12) { switch (s3c_ts_cfg->s3c_adc_con) { case ADC_TYPE_2: writel(readl(ts_base+S3C_ADCCON)|S3C_ADCCON_RESSEL_12BIT, ts_base+S3C_ADCCON); break; case ADC_TYPE_1: writel(readl(ts_base+S3C_ADCCON)|S3C_ADCCON_RESSEL_12BIT_1, ts_base+S3C_ADCCON); break; default: dev_err(dev, "Touchscreen over this type of AP isn't supported !\n"); break; } } writel(WAIT4INT(0), ts_base+S3C_ADCTSC); ts = kzalloc(sizeof(struct s3c_ts_info), GFP_KERNEL); input_dev = input_allocate_device(); if (!input_dev) { ret = -ENOMEM; goto err_alloc; } ts->dev = input_dev; ts->dev->evbit[0] = ts->dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); ts->dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); if (s3c_ts_cfg->resol_bit==12) { #ifdef CONFIG_ANDROID #ifndef CONFIG_CPU_S5PV210_EVT1 input_set_abs_params(ts->dev, ABS_X, 0, 800, 0, 0); input_set_abs_params(ts->dev, ABS_Y, 0, 480, 0, 0); // input_set_abs_params(ts->dev, ABS_Z, 0, 0, 0, 0); set_bit(0,ts->dev->evbit); set_bit(1,ts->dev->evbit); set_bit(2,ts->dev->evbit); set_bit(3,ts->dev->evbit); set_bit(5,ts->dev->evbit); set_bit(0,ts->dev->relbit); set_bit(1,ts->dev->relbit); set_bit(0,ts->dev->absbit); set_bit(1,ts->dev->absbit); set_bit(2,ts->dev->absbit); set_bit(0,ts->dev->swbit); for (err=0; err < 512; err++) set_bit(err,ts->dev->keybit); input_event(ts->dev,5,0,1); #else /* !CONFIG_CPU_S5PV210_EVT1 */ input_set_abs_params(ts->dev, ABS_X, X_COOR_MIN, X_COOR_MAX, X_COOR_FUZZ, 0); input_set_abs_params(ts->dev, ABS_Y, Y_COOR_MIN, Y_COOR_MAX, Y_COOR_FUZZ, 0); #endif /* !CONFIG_CPU_S5PV210_EVT1 */ #else /* CONFIG_ANDROID */ input_set_abs_params(ts->dev, ABS_X, 0, 0xFFF, 0, 0); input_set_abs_params(ts->dev, ABS_Y, 0, 0xFFF, 0, 0); #endif /* CONFIG_ANDROID */ } else { input_set_abs_params(ts->dev, ABS_X, 0, 0x3FF, 0, 0); input_set_abs_params(ts->dev, ABS_Y, 0, 0x3FF, 0, 0); } input_set_abs_params(ts->dev, ABS_PRESSURE, 0, 1, 0, 0); sprintf(ts->phys, "input(ts)"); ts->dev->name = s3c_ts_name; ts->dev->phys = ts->phys; ts->dev->id.bustype = BUS_RS232; ts->dev->id.vendor = 0xDEAD; ts->dev->id.product = 0xBEEF; ts->dev->id.version = S3C_TSVERSION; ts->shift = s3c_ts_cfg->oversampling_shift; ts->resol_bit = s3c_ts_cfg->resol_bit; ts->s3c_adc_con = s3c_ts_cfg->s3c_adc_con; #ifdef CONFIG_HAS_EARLYSUSPEND ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; ts->early_suspend.suspend = ts_early_suspend; ts->early_suspend.resume =ts_late_resume; register_early_suspend(&ts->early_suspend); #endif /* CONFIG_HAS_EARLYSUSPEND */ /* For IRQ_PENDUP */ ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (ts_irq == NULL) { dev_err(dev, "no irq resource specified\n"); ret = -ENOENT; goto err_irq; } ret = request_irq(ts_irq->start, stylus_updown, irq_flags, "s3c_updown", ts); if (ret != 0) { dev_err(dev, "s3c_ts.c: Could not allocate ts IRQ_PENDN !\n"); ret = -EIO; goto err_irq; } /* For IRQ_ADC */ ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (ts_irq == NULL) { dev_err(dev, "no irq resource specified\n"); ret = -ENOENT; goto err_irq; } ret = request_irq(ts_irq->start, stylus_action, irq_flags, "s3c_action", ts); if (ret != 0) { dev_err(dev, "s3c_ts.c: Could not allocate ts IRQ_ADC !\n"); ret = -EIO; goto err_irq; } printk(KERN_INFO "%s got loaded successfully : %d bits\n", s3c_ts_name, s3c_ts_cfg->resol_bit); /* All went ok, so register to the input system */ ret = input_register_device(ts->dev); if (ret) { dev_err(dev, "s3c_ts.c: Could not register input device(touchscreen)!\n"); ret = -EIO; goto fail; } return 0; fail: free_irq(ts_irq->start, ts->dev); free_irq(ts_irq->end, ts->dev); err_irq: input_free_device(input_dev); kfree(ts); err_alloc: clk_disable(ts_clock); clk_put(ts_clock); err_clk: iounmap(ts_base); err_map: release_resource(ts_mem); kfree(ts_mem); err_req: return ret; }