⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tsc2003_linux.c

📁 the tsc2003 driver C code in linux os
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
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 + -