驱动路径: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函数
1 static irqreturn_t stylus_updown(int irq, void *dev_id)
2 {
3 unsigned long data0;
4 unsigned long data1;
5 int updown;
6
7 if (down_trylock(&ADC_LOCK) == 0) { //判断是否adc可用,down_trylock可以用来获取信号量,不会休眠
8 OwnADC = 1;
9 data0 = ioread32(base_addr+S3C2410_ADCDAT0);
10 data1 = ioread32(base_addr+S3C2410_ADCDAT1);
11
12 updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
13
14 if (updown) { //判断触摸屏是否按下
15 touch_timer_fire(0); //启动adc
16 } else {
17 OwnADC = 0;
18 up(&ADC_LOCK);
19 }
20 }
21
22 return IRQ_HANDLED;
23 }
下面开一下touch_timer_fire是怎么个玩法
24 static void touch_timer_fire(unsigned long data)
25 {
26 unsigned long data0;
27 unsigned long data1;
28 int updown;
29
30 data0 = ioread32(base_addr+S3C2410_ADCDAT0);
31 data1 = ioread32(base_addr+S3C2410_ADCDAT1);
32
33 updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
34
35 if (updown) { //判断现在是否还按下
36 if (count != 0) { //采样完成,count的值我下面会讲解
37 long tmp;
38 //应为是240×320,需要x,y调换一下
39 tmp = xp;
40 xp = yp;
41 yp = tmp;
42 //在stylus_action中取得是连续四次采样的结果需要处以4
43 xp >>= 2;
44 yp >>= 2;
45
46 input_report_abs(dev, ABS_X, xp); //x,y坐标报告
47 input_report_abs(dev, ABS_Y, yp);
48
49 input_report_key(dev, BTN_TOUCH, 1);
50 input_report_abs(dev, ABS_PRESSURE, 1);
51 input_sync(dev); //同步
52 }
53
54 xp = 0; //否则开始采用
55 yp = 0;
56 count = 0;
57
58 iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
59 iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
60 } else { //是否抬起
61 count = 0;
62
63 input_report_key(dev, BTN_TOUCH, 0);
64 input_report_abs(dev, ABS_PRESSURE, 0);
65 input_sync(dev);
66
67 iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
68 if (OwnADC) {
69 OwnADC = 0;
70 up(&ADC_LOCK);
71 }
72 }
73 }
注意:当第一次按下时,count==0,启动ad,当转换完成将触发中断,进入stylus_action中断处理函数,好家伙来看一下哦
74 static irqreturn_t stylus_action(int irq, void *dev_id)
75 {
76 unsigned long data0;
77 unsigned long data1;
78
79 if (OwnADC) {
80 data0 = ioread32(base_addr+S3C2410_ADCDAT0);
81 data1 = ioread32(base_addr+S3C2410_ADCDAT1);
82
83 xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
84 yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
85 count++;
86
87 if (count < (1<<2)) { //如果小于4,继续启动adc
88 iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
89 iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
90 } else { //已经采样了4次,等待1ms后调用touch_timer函数。
91 mod_timer(&touch_timer, jiffies+1);
92 iowrite32(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
93 }
94 }
95
96 return IRQ_HANDLED;
97 }
接下来就得看一下touch_timer在忙些什么请看招。。。。。。。。。。。
static struct timer_list touch_timer =
TIMER_INITIALIZER(touch_timer_fire, 0, 0); 重新初始化
相当于又执行了touch_timer_fire(0);
此时count==4,my ladygaga 现在知道怎么回事了吧。。。。
想一想:如果要实现按键的时候点亮背光,隔一段时间没按键自动熄灭背光该怎么搞呢?
1.首先当然是先配置一下背光的引脚了(假设与GPG4相连)
在s3c2410_ts_connect()中添加s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_OUTP);
2. 编写背光控制函数
static void off_backlight(unsinged long data) //熄灭背光
{
s3c2410_gpio_setpin(S3C2410_GPG4,0);
}
static struct timer_list backlight_control=TIMER_INITIALIZER(off_backlight,0,0);
3.修改touch_timer_fire函数
下面是修改后的代码
98 static void touch_timer_fire(unsigned long data)
99 {
100 unsigned long data0;
101 unsigned long data1;
102 int updown;
103 data0 = ioread32(base_addr+S3C2410_ADCDAT0);
104 data1 = ioread32(base_addr+S3C2410_ADCDAT1);
105 updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));
106 if (updown)//判断是否按下
107 {
108 if (count != 0) //AD采集完成
109 {
110 xp >>= 2;
111 yp >>= 2;
112 input_report_abs(dev, ABS_X, xp);
113 input_report_abs(dev, ABS_Y, yp);
114 input_report_key(dev, BTN_TOUCH, 1);
115 input_report_abs(dev, ABS_PRESSURE, 1);
116 input_sync(dev);
117 //next two lines add by Charistain_huang
118 s3c2410_gpio_setpin(S3C2410_GPG4,1); // light_backlight
119 mod_timer(&backlight_control,jiffies+10*200); //2000ms后执行backlight_control------>off_backlight熄灭背光
120
121 }//否则开始采集
122 xp = 0;
123 yp = 0;
124 count = 0;
125 iowrite32(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
126 iowrite32(ioread32(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);//启动AD转换
127 }
128 else //判断为抬起
129 {
130 count = 0;
131 input_report_key(dev, BTN_TOUCH, 0);
132 input_report_abs(dev, ABS_PRESSURE, 0);
133 input_sync(dev);
134 iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
135
136 }
137 }
ok!!!完美的句号!!