驱动路径:drivers/input/touchscreen/s3c2410_ts.c
在static int __init s3c2410ts_init(void)函数中注册了两个中断
1.if (request_irq(IRQ_ADC, stylus_action, IRQF_SHARED|IRQF_SAMPLE_RANDOM,
"s3c2410_action", dev))
2.if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
"s3c2410_action", dev))
中断处理函数stylus_action和stylus_updown。当点击触摸屏时进入该函数,在该函数中启动ad转换,转换完成就触发中断进入stylus_action在stylus_action中读取数据。
首先来看一下stylus_updown函数
static irqreturn_t stylus_updown(int irq, void *dev_id)
{
unsigned long data0;
unsigned long data1;
int updown;
if (down_trylock(&ADC_LOCK) == 0) { //判断是否adc可用,down_trylock可以用来获取信号量,不会休眠
OwnADC = 1;
data0 = ioread32(base_addr+S3C2410_ADCDAT0);
data1 = ioread32(base_addr+S3C2410_ADCDAT1);
updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
if (updown) { //判断触摸屏是否按下
touch_timer_fire(0); //启动adc
} else {
OwnADC = 0;
up(&ADC_LOCK);
}
}
return IRQ_HANDLED;
}
下面开一下touch_timer_fire是怎么个玩法
static void touch_timer_fire(unsigned long data)
{
unsigned long data0;
unsigned long data1;
int updown;
data0 = ioread32(base_addr+S3C2410_ADCDAT0);
data1 = ioread32(base_addr+S3C2410_ADCDAT1);
updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
if (updown) { //判断现在是否还按下
if (count != 0) { //采样完成,count的值我下面会讲解
long tmp;
//应为是240×320,需要x,y调换一下
tmp = xp;
xp = yp;
yp = tmp;
//在stylus_action中取得是连续四次采样的结果需要处以4
xp >>= 2;
yp >>= 2;
input_report_abs(dev, ABS_X, xp); //x,y坐标报告
input_report_abs(dev, ABS_Y, yp);
input_report_key(dev, BTN_TOUCH, 1);
input_report_abs(dev, ABS_PRESSURE, 1);
input_sync(dev); //同步
}
xp = 0; //否则开始采用
yp = 0;
count = 0;
iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else { //是否抬起
count = 0;
input_report_key(dev, BTN_TOUCH, 0);
input_report_abs(dev, ABS_PRESSURE, 0);
input_sync(dev);
iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
if (OwnADC) {
OwnADC = 0;
up(&ADC_LOCK);
}
}
}
注意:当第一次按下时,count==0,启动ad,当转换完成将触发中断,进入stylus_action中断处理函数,好家伙来看一下哦
static irqreturn_t stylus_action(int irq, void *dev_id)
{
unsigned long data0;
unsigned long data1;
if (OwnADC) {
data0 = ioread32(base_addr+S3C2410_ADCDAT0);
data1 = ioread32(base_addr+S3C2410_ADCDAT1);
xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
count++;
if (count < (1<<2)) { //如果小于4,继续启动adc
iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else { //已经采样了4次,等待1ms后调用touch_timer函数。
mod_timer(&touch_timer, jiffies+1);
iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
}
}
return IRQ_HANDLED;
}
接下来就得看一下touch_timer在忙些什么请看招。。。。。。。。。。。
static struct timer_list touch_timer =
TIMER_INITIALIZER(touch_timer_fire, 0, 0); 重新初始化