static void omap_ts_timer(unsigned long data) { unsigned long flags; spin_lock_irqsave(&ts_omap.lock, flags); if (!ts_omap.dev->penup()) { if (!ts_omap.touched) { DEBUG_TS("omap_ts_timer: pen down\n"); input_report_key(&(ts_omap.inputdevice), BTN_TOUCH, 1); } ts_omap.touched = 1; omap_ts_read(); ts_omap.ts_timer.expires = jiffies + HZ / 100; add_timer(&(ts_omap.ts_timer)); } else { if (ts_omap.touched) { DEBUG_TS("omap_ts_timer: pen up\n"); ts_omap.touched = 0; input_report_abs(&(ts_omap.inputdevice), ABS_X, 0); input_report_abs(&(ts_omap.inputdevice), ABS_Y, 0); input_report_abs(&(ts_omap.inputdevice), ABS_PRESSURE, 0); input_sync(&(ts_omap.inputdevice)); input_report_key(&(ts_omap.inputdevice), BTN_TOUCH, 0); } if (!ts_omap.irq_enabled) { ts_omap.irq_enabled = 1; enable_irq(ts_omap.irq); } } spin_unlock_irqrestore(&ts_omap.lock, flags); }
static exception_t s3c6410_touchscreen_write(conf_object_t *opaque, generic_address_t offset, uint32_t* buf, size_t count) { struct s3c6410_touchscreen_device *dev = opaque->obj; s3c6410_touchscreen_status* status = dev->status; touchscreen_reg_t* regs = dev->regs; uint32_t val = *(uint32_t*)buf; DEBUG_TS("In %s, offset=0x%x data=0x%x\n", __FUNCTION__, offset, val); switch(offset) { case 0x0: regs->adccon = val; // 0x7E00_B000 status->adcbit = GET_RESSEL(regs->adccon); if((regs->adctsc & TSC_AUTO_PST) && (regs->adccon & ENABLE_START)){ if(status->adc_con < 0){ create_thread_scheduler(1000, Periodic_sched, adc_interrupt, opaque, &status->adc_con); } /* * TSC_AUTO_PST is open, waiting for opening ENABLE_START, * conversion start, but adc conversion that we need not simulate */ } regs->adccon &= ~ENABLE_START; break; case 0x4: regs->adctsc = val; // 0x7E00_B004 if(~(regs->adctsc & TSC_AUTO_PST)){ if(status->adc_con >= 0){ del_thread_scheduler(status->adc_con); status->adc_con = -1; } } break; case 0x8: regs->adcdly = val; // 0x7E00_B008 break; case 0x0C: regs->adcdat0 = val; // 0x7E00_B00C break; case 0x10: regs->adcdat1 = val; // 0x7E00_B010 break; case 0x14: regs->adcupdn = val; // 0x7E00_B014 break; case 0x18: regs->adcclrint = val; // 0x7E00_B018 break; case 0x20: regs->adcclrintpndnup = val; // 0x7E00_B020 break; default: printf("Can not write the register at 0x%x in touchscreen\n", offset); return 0; } return No_exp; }
static void touchscreen_update_status(conf_object_t* object, int *Pen_buffer) { s3c6410_touchscreen_device* dev_ts = (s3c6410_touchscreen_device*)object->obj; touchscreen_reg_t* regs = dev_ts->regs; s3c6410_touchscreen_status* status = dev_ts->status; /************************************************************************************** The origin of touchscreen coordinates and the LCD coordinate transformation as follows: XT = ((XL * (XTmax - XTmin)) / W + XTmin YT = ((YL * (YTmax - YTmin)) / W + YTmin XT for the origin of touch screen coordinates. XL for the LCD coordinate. Xtmin, Xtmax, Ytmin, Ytmax:The minimum and maximum values on the Y-axis direction for touchscreen. W for the LCD's width. H for the LCD's height. ***************************************************************************************/ int xmin = 2; //XTmin int xrange = 1023; //XTmax - XTmin int ymin = 2; // YTmin int yrange = 1023;//YTmax - YTmin //int lcd_width = 800;//W int lcd_width = 320;//W //int lcd_height = 480;// H int lcd_height = 480;// H int lcd_x;// XL int lcd_y;// YL int stylus = status->stylus; lcd_x = Pen_buffer[0]; lcd_y = Pen_buffer[1]; //coordinate transformation status->x = ((lcd_x * xrange) / lcd_width) + xmin; status->y = ((lcd_y * yrange) / lcd_height) + ymin; status->event = Pen_buffer[4]; status->stylus = Pen_buffer[5]; // set touchscreen status in regs DEBUG_TS("x = %d, y = %d, envent = %d, stylus = %d\n", status->x, status->y, status->event, status->stylus); if(regs->adctsc == 0xd3 && stylus != status->stylus){ /* send interrupt */ s3c6410_touchscreen_raise(object, 62); /* set ADCUPDN */ if(status->stylus) regs->adcupdn &= 0x2; /* Stylus Up Interrupt history */ else regs->adcupdn &= 0x1; /* Stylus Down Interrupt history */ } }
static int omap_ts_read(void) { u16 data[4] = { 0, 0, 0, 0 }; ts_omap.dev->read(data); input_report_abs(&(ts_omap.inputdevice), ABS_X, data[0]); input_report_abs(&(ts_omap.inputdevice), ABS_Y, data[1]); input_report_abs(&(ts_omap.inputdevice), ABS_PRESSURE, data[2]); input_sync(&(ts_omap.inputdevice)); DEBUG_TS("omap_ts_read: read x=%d,y=%d,p=%d\n", data[0], data[1], data[2]); return 0; }
static exception_t s3c6410_touchscreen_read(conf_object_t *opaque, generic_address_t offset, void* buf, size_t count) { struct s3c6410_touchscreen_device *dev = opaque->obj; s3c6410_touchscreen_status* status = dev->status; touchscreen_reg_t* regs = dev->regs; DBG("In %s, offset=0x%x\n", __FUNCTION__, offset); switch(offset) { case 0x0: /* End of adc conversion */ regs->adccon |= ECFLG; *(uint32_t*)buf = regs->adccon; // 0x7E00_B000 break; case 0x4: *(uint32_t*)buf = regs->adctsc; // 0x7E00_B004 break; case 0x8: *(uint32_t*)buf = regs->adcdly; // 0x7E00_B008 break; case 0x0C: if(status->adcbit) regs->adcdat0 = (status->x & 0x3ff) | (regs->adcdat0 & ~0x3ff); else regs->adcdat0 = (status->x & 0xfff) | (regs->adcdat0 & ~0xfff); if(status->stylus == 0) // DOWN and set regs regs->adcdat0 &= ~(1 << 15); else regs->adcdat0 |= (status->stylus << 15); *(uint32_t*)buf = regs->adcdat0; // 0x7E00_B00C break; case 0x10: if(status->adcbit) regs->adcdat1 = (status->y & 0x3ff) | (regs->adcdat1 & ~0x3ff); else regs->adcdat1 = (status->y & 0xfff) | (regs->adcdat1 & ~0xfff);; if(status->stylus == 0) // DOWN and set regs regs->adcdat1 &= ~(1 << 15); else regs->adcdat1 |= (status->stylus << 15); *(uint32_t*)buf = regs->adcdat1; // 0x7E00_B010 break; case 0x14: *(uint32_t*)buf = regs->adcupdn; // 0x7E00_B014 break; case 0x18: printf("ADCCLRINT is Write Only\n"); break; case 0x20: printf("ADCCLRINTPNDNUP is Write Only\n"); break; default: printf("Can not read the register at 0x%x in touchscreen\n", offset); return 0; } DEBUG_TS("In %s, offset=0x%x data=0x%x\n", __FUNCTION__, offset, *(uint32_t*)buf); return No_exp; }