📄 tsc2003_linux.c
字号:
/*
2 * linux/drivers/i2c/chips/tsc2003.c
3 *
4 * Copyright (C) 2005 Bill Gatliff <bgat at billgatliff.com>
5 * Changes for 2.6.20 kernel by Nicholas Chen <nchen at cs.umd.edu>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Driver for TI's TSC2003 I2C Touch Screen Controller
12 */
13
14 //#include <linux/config.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/slab.h>
18 #include <linux/i2c.h>
19 #include <linux/string.h>
20 #include <linux/bcd.h>
21 #include <linux/list.h>
22 #include <linux/device.h>
23 #include <linux/interrupt.h>
24 #include <linux/input.h>
25 #include <linux/delay.h>
26 #include <asm-arm/arch-pxa/irqs.h>
27
28 static unsigned short normal_i2c[]
29 = {0x48, I2C_CLIENT_END };
30
31 I2C_CLIENT_INSMOD_1(tsc2003);
32
33 #define DRIVER_NAME "tsc2003"
34
35 enum tsc2003_pd {
36 PD_POWERDOWN = 0, /* penirq */
37 PD_IREFOFF_ADCON = 1, /* no penirq */
38 PD_IREFON_ADCOFF = 2, /* penirq */
39 PD_IREFON_ADCON = 3, /* no penirq */
40 PD_PENIRQ_ARM = PD_IREFON_ADCOFF,
41 PD_PENIRQ_DISARM = PD_IREFON_ADCON,
42 };
43
44 enum tsc2003_m {
45 M_12BIT = 0,
46 M_8BIT = 1
47 };
48
49 enum tsc2003_cmd {
50 MEAS_TEMP0 = 0,
51 MEAS_VBAT1 = 1,
52 MEAS_IN1 = 2,
53 MEAS_TEMP1 = 4,
54 MEAS_VBAT2 = 5,
55 MEAS_IN2 = 6,
56 ACTIVATE_NX_DRIVERS = 8,
57 ACTIVATE_NY_DRIVERS = 9,
58 ACTIVATE_YNX_DRIVERS = 10,
59 MEAS_XPOS = 12,
60 MEAS_YPOS = 13,
61 MEAS_Z1POS = 14,
62 MEAS_Z2POS = 15
63 };
64
65 #define TSC2003_CMD(cn,pdn,m) (((cn) << 4) | ((pdn) << 2) | ((m) << 1))
66
67 #define ADC_MAX ((1 << 12) - 1)
68
69 struct tsc2003_data {
70 struct i2c_client client;
71 struct device_driver driver;
72 struct input_dev *idev;
73 struct timer_list penirq_timer;
74 struct semaphore sem;
75 struct task_struct *tstask;
76 struct completion tstask_completion;
77 struct completion penirq_completion;
78 enum tsc2003_pd pd;
79 enum tsc2003_m m;
80 int penirq;
81
82 int vbat1;
83 int vbat2;
84 int temp0;
85 int temp1;
86 int in1;
87 int in2;
88 };
89
90 static int tsc2003_i2c_detect (struct i2c_adapter *adapter, int address,
91 int kind);
92
93 static inline int tsc2003_command (struct tsc2003_data *data,
94 enum tsc2003_cmd cmd,
95 enum tsc2003_pd pd)
96 {
97 char c;
98 int ret;
99 down(&data->sem);
100 c = TSC2003_CMD(cmd, pd, data->m);
101 ret = i2c_master_send(&data->client, &c, 1);
102 up(&data->sem);
103 return ret;
104 }
105
106 static int tsc2003_read (struct tsc2003_data *data,
107 enum tsc2003_cmd cmd,
108 enum tsc2003_pd pd,
109 int *val)
110 {
111 char c;
112 char d[2];
113 int ret;
114
115 c = TSC2003_CMD(cmd, pd, data->m);
116 ret = i2c_master_send(&data->client, &c, 1);
117 if (ret <= 0) goto err;
118
119 udelay(20);
120 ret = i2c_master_recv(&data->client, d, data->m == M_12BIT ? 2 : 1);
121 if (ret <= 0) goto err;
122
123 if (val)
124 {
125 *val = d[0];
126 *val <<= 4;
127 if (data->m == M_12BIT)
128 *val += (d[1] >> 4);
129 }
130
131 #if defined(CONFIG_I2C_DEBUG_CHIP)
132 printk(KERN_ERR "%s: val[%x] = %d\n",
133 __FUNCTION__, cmd, (((int)d[0]) << 8) + d[1]);
134 #endif
135
136 return 0;
137 err:
138 if (!ret) ret = -ENODEV;
139 return ret;
140 }
141
142 static inline int tsc2003_read_temp0 (struct tsc2003_data *d, enum
143 tsc2003_pd pd, int *t)
144 {
145 return tsc2003_read(d, MEAS_TEMP0, pd, t);
146 }
147
148 static inline int tsc2003_read_temp1 (struct tsc2003_data *d, enum
149 tsc2003_pd pd, int *t)
150 {
151 return tsc2003_read(d, MEAS_TEMP1, pd, t);
152 }
153
154 static inline int tsc2003_read_xpos (struct tsc2003_data *d, enum
155 tsc2003_pd pd, int *x)
156 {
157 return tsc2003_read(d, MEAS_XPOS, pd, x);
158 }
159
160 static inline int tsc2003_read_ypos (struct tsc2003_data *d, enum
161 tsc2003_pd pd, int *y)
162 {
163 return tsc2003_read(d, MEAS_YPOS, pd, y);
164 }
165
166 static inline int tsc2003_read_pressure (struct tsc2003_data *d, enum
167 tsc2003_pd pd, int *p)
168 {
169 return tsc2003_read(d, MEAS_Z1POS, pd, p);
170 }
171
172 static inline int tsc2003_read_in1 (struct tsc2003_data *d, enum
173 tsc2003_pd pd, int *t)
174 {
175 return tsc2003_read(d, MEAS_IN1, pd, t);
176 }
177
178 static inline int tsc2003_read_in2 (struct tsc2003_data *d, enum
179 tsc2003_pd pd, int *t)
180 {
181 return tsc2003_read(d, MEAS_IN2, pd, t);
182 }
183
184 static inline int tsc2003_read_vbat1 (struct tsc2003_data *d, enum
185 tsc2003_pd pd, int *t)
186 {
187 return tsc2003_read(d, MEAS_VBAT1, pd, t);
188 }
189
190 static inline int tsc2003_read_vbat2 (struct tsc2003_data *d, enum
191 tsc2003_pd pd, int *t)
192 {
193 return tsc2003_read(d, MEAS_VBAT2, pd, t);
194 }
195
196 static inline int tsc2003_powerdown (struct tsc2003_data *d)
197 {
198 /* we don't have a distinct powerdown command,
199 so do a benign read with the PD bits cleared */
200 return tsc2003_read(d, MEAS_IN1, PD_POWERDOWN, 0);
201 }
202
203 void tsc2003_init_client (struct i2c_client *client)
204 {
205 struct tsc2003_data *data = i2c_get_clientdata(client);
206
207 data->pd = PD_PENIRQ_DISARM;
208 data->m = M_8BIT;
209 return;
210 }
211
212 #define PENUP_TIMEOUT 50 /* msec */
213
214 static irqreturn_t tsc2003_penirq (int irq, void *v)
215 {
216 struct tsc2003_data *d = v;
217 complete(&d->penirq_completion);
218 return IRQ_HANDLED;
219 }
220
221 /*
222 static int tsc2003_remove (struct device *dev)
223 {
224 struct tsc2003_data *d = container_of(dev->driver, struct tsc2003_data, driver);
225 free_irq(d->penirq,d);
226 input_unregister_device(d->idev);
227 return 0;
228 }
229 */
230
231 static void tsc2003_pen_up (unsigned long v)
232 {
233 struct tsc2003_data *d = (struct tsc2003_data *)v;
234 input_report_abs(d->idev, ABS_PRESSURE, 0);
235 input_sync(d->idev);
236 return;
237 }
238
239 static inline void tsc2003_restart_pen_up_timer (struct tsc2003_data *d)
240 {
241 mod_timer(&d->penirq_timer, jiffies + (PENUP_TIMEOUT * HZ) / 1000);
242 }
243
244 static int tsc2003ts_thread (void *v)
245 {
246 struct tsc2003_data *d = v;
247 struct task_struct *tsk = current;
248 int ret;
249
250 d->tstask = tsk;
251
252 daemonize(DRIVER_NAME "tsd");
253 allow_signal(SIGKILL);
254
255 complete(&d->tstask_completion);
256
257 #if defined(CONFIG_I2C_DEBUG_CHIP)
258 printk(KERN_INFO "%s: address 0x%x\n",
259 __FUNCTION__, d->client.addr);
260 #endif
261
262 while (!signal_pending(tsk))
263 {
264 unsigned int x, y, p;
265
266 if (!down_interruptible(&d->sem))
267 {
268 d->pd = PD_PENIRQ_DISARM;
269 disable_irq(d->penirq);
270 tsc2003_read_xpos(d, PD_PENIRQ_DISARM, &x);
271 tsc2003_read_ypos(d, PD_PENIRQ_DISARM, &y);
272 tsc2003_read_pressure(d, PD_PENIRQ_DISARM, &p);
273
274 /* non-X-Y driver read to avoid glitch in penirq (errata?) */
275 tsc2003_read_vbat1(d, PD_PENIRQ_DISARM, 0);
276 enable_irq(d->penirq);
277
278
279 input_report_abs(d->idev, ABS_X, 4096 - x);
280 input_report_abs(d->idev, ABS_Y, 4096 - y);
281 input_report_abs(d->idev, ABS_PRESSURE, p);
282 input_sync(d->idev);
283
284
285 do
286 {
287 ret = wait_for_completion_interruptible_timeout(&d->penirq_completion, HZ / 100);
288 if (ret)
289 {
290 if (d->pd == PD_PENIRQ_DISARM)
291 {
292 /* fake penirq, avoid glitch and then start watching for real now */
293 d->pd = PD_PENIRQ_ARM;
294 tsc2003_read_vbat1(d, PD_PENIRQ_ARM, 0);
295 up(&d->sem);
296 }
297 else
298 {
299 /* pen down event, (re)start the pen up timer */
300 tsc2003_restart_pen_up_timer(d);
301 }
302 }
303 else
304 {
305 if (d->pd != PD_PENIRQ_ARM)
306 {
307 /* fake penirq never arrived, which would be the case
308 for a level-triggered irq line */
309 tsc2003_read_vbat1(d, PD_PENIRQ_ARM, 0);
310 d->pd = PD_PENIRQ_ARM;
311 up(&d->sem);
312 }
313 if (timer_pending(&d->penirq_timer))
314 {
315 /* pen is down, time to send (another) sample */
316 break;
317 }
318 else
319 {
320 /* pen is up, nothing to do but wait for it to
321 come down */
322 wait_for_completion_interruptible(&d->penirq_completion);
323 /* pen is down, (re)start the pen up timer */
324 tsc2003_restart_pen_up_timer(d);
325 break;
326 }
327 }
328 }
329 while (!signal_pending(tsk));
330 }
331 }
332
333 d->tstask = NULL;
334 complete_and_exit(&d->tstask_completion, 0);
335 }
336
337 static int tsc2003_idev_open (struct input_dev *idev)
338 {
339 struct tsc2003_data *d = idev->private;
340 int ret = 0;
341
342 if (down_interruptible(&d->sem))
343 return -EINTR;
344
345 if (d->tstask)
346 panic(DRIVER_NAME "tsd already running (!). abort.");
347
348 d->penirq_timer.data = (unsigned long)d;
349 d->penirq_timer.function = tsc2003_pen_up;
350
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -