2 * linux/arch/mips/au1000/db1x00/mirage_ts.c
4 * BRIEF MODULE DESCRIPTION
5 * Glue between Mirage board-specific touchscreen pieces
6 * and generic Wolfson Codec touchscreen support.
8 * Based on pb1100_ts.c used in Hydrogen II.
10 * Copyright (c) 2003 Embedded Edge, LLC
11 * dan@embeddededge.com
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
21 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
34 #include <linux/config.h>
35 #include <linux/types.h>
36 #include <linux/module.h>
37 #include <linux/sched.h>
38 #include <linux/kernel.h>
39 #include <linux/init.h>
41 #include <linux/poll.h>
42 #include <linux/proc_fs.h>
43 #include <linux/smp.h>
44 #include <linux/smp_lock.h>
45 #include <linux/wait.h>
47 #include <asm/segment.h>
49 #include <asm/uaccess.h>
50 #include <asm/delay.h>
51 #include <asm/au1000.h>
54 * Imported interface to Wolfson Codec driver.
56 extern void *wm97xx_ts_get_handle(int which
);
57 extern int wm97xx_ts_ready(void* ts_handle
);
58 extern void wm97xx_ts_set_cal(void* ts_handle
, int xscale
, int xtrans
, int yscale
, int ytrans
);
59 extern u16
wm97xx_ts_get_ac97(void* ts_handle
, u8 reg
);
60 extern void wm97xx_ts_set_ac97(void* ts_handle
, u8 reg
, u16 val
);
61 extern int wm97xx_ts_read_data(void* ts_handle
, long* x
, long* y
, long* pressure
);
62 extern void wm97xx_ts_send_data(void* ts_handle
, long x
, long y
, long z
);
64 int wm97xx_comodule_present
= 1;
67 #define TS_NAME "mirage_ts"
69 #define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
70 #define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
71 #define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
72 #define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
75 #define PEN_DOWN_IRQ AU1000_GPIO_7
77 static struct task_struct
*ts_task
= 0;
78 static DECLARE_COMPLETION(ts_complete
);
79 static DECLARE_WAIT_QUEUE_HEAD(pendown_wait
);
81 #ifdef CONFIG_WM97XX_FIVEWIRETS
82 static int release_pressure
= 1;
84 static int release_pressure
= 50;
92 #define SAMPLE_RATE 50 /* samples per second */
93 #define PEN_DEBOUNCE 5 /* samples for settling - fn of SAMPLE_RATE */
94 #define PEN_UP_TIMEOUT 10 /* in seconds */
95 #define PEN_UP_SETTLE 5 /* samples per second */
118 static void pendown_irq(int irqnr
, void *devid
, struct pt_regs
*regs
)
120 //DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD));
121 wake_up(&pendown_wait
);
124 static int ts_thread(void *id
)
126 static int pen_was_down
= 0;
127 static DOWN_EVENT pen_xy
;
129 void *ts
; /* handle */
130 struct task_struct
*tsk
= current
;
131 int timeout
= HZ
/ SAMPLE_RATE
;
137 tsk
->policy
= SCHED_FIFO
;
138 tsk
->rt_priority
= 1;
139 strcpy(tsk
->comm
, "touchscreen");
141 /* only want to receive SIGKILL */
142 spin_lock_irq(&tsk
->sigmask_lock
);
143 siginitsetinv(&tsk
->blocked
, sigmask(SIGKILL
));
144 recalc_sigpending(tsk
);
145 spin_unlock_irq(&tsk
->sigmask_lock
);
147 /* get handle for codec */
148 ts
= wm97xx_ts_get_handle(0);
150 /* proceed only after everybody is ready */
151 wait_event_timeout(pendown_wait
, wm97xx_ts_ready(ts
), HZ
/4);
153 /* board-specific calibration */
154 wm97xx_ts_set_cal(ts
,
155 mirage_ts_cal
.xscale
,
156 mirage_ts_cal
.xtrans
,
157 mirage_ts_cal
.yscale
,
158 mirage_ts_cal
.ytrans
);
160 /* route Wolfson pendown interrupts to our GPIO */
162 wm97xx_ts_set_ac97(ts
, 0x4c, wm97xx_ts_get_ac97(ts
, 0x4c) & ~0x0008);
164 wm97xx_ts_set_ac97(ts
, 0x56, wm97xx_ts_get_ac97(ts
, 0x56) & ~0x0008);
166 wm97xx_ts_set_ac97(ts
, 0x52, wm97xx_ts_get_ac97(ts
, 0x52) | 0x2008);
170 interruptible_sleep_on_timeout(&pendown_wait
, timeout
);
171 disable_irq(PEN_DOWN_IRQ
);
172 if (signal_pending(tsk
)) {
177 if (!wm97xx_ts_read_data(ts
, &x
, &y
, &z
))
178 z
= 0; /* treat no-data and pen-up the same */
180 if (signal_pending(tsk
)) {
184 if (z
>= release_pressure
) {
185 y
= ~y
; /* top to bottom */
186 if (pen_was_down
> 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX
191 } else if (pen_was_down
<= 1) {
195 wm97xx_ts_send_data(ts
, x
, y
, z
);
196 pen_was_down
= PEN_DEBOUNCE
;
198 //wm97xx_ts_send_data(ts, x, y, z);
199 timeout
= HZ
/ SAMPLE_RATE
;
203 z
= release_pressure
;
205 wm97xx_ts_send_data(ts
, pen_xy
.x
, pen_xy
.y
, z
);
207 /* The pendown signal takes some time to settle after
208 * reading the pen pressure so wait a little
209 * before enabling the pen.
211 if (! pen_was_down
) {
212 // interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE);
213 timeout
= HZ
* PEN_UP_TIMEOUT
;
216 enable_irq(PEN_DOWN_IRQ
);
218 enable_irq(PEN_DOWN_IRQ
);
220 complete(&ts_complete
);
224 static int __init
ts_mirage_init(void)
228 /* pen down signal is connected to GPIO 7 */
230 ret
= request_irq(PEN_DOWN_IRQ
, pendown_irq
, 0, "ts-pendown", NULL
);
232 err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ
, ret
);
237 ret
= kernel_thread(ts_thread
, NULL
, CLONE_FS
| CLONE_FILES
);
244 info("Mirage touchscreen IRQ initialized.");
249 static void __exit
ts_mirage_exit(void)
252 send_sig(SIGKILL
, ts_task
, 1);
253 wait_for_completion(&ts_complete
);
256 free_irq(PEN_DOWN_IRQ
, NULL
);
259 module_init(ts_mirage_init
);
260 module_exit(ts_mirage_exit
);