]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - arch/mips/au1000/db1x00/mirage_ts.c
Remove obsolete #include <linux/config.h>
[mirror_ubuntu-jammy-kernel.git] / arch / mips / au1000 / db1x00 / mirage_ts.c
CommitLineData
1da177e4
LT
1/*
2 * linux/arch/mips/au1000/db1x00/mirage_ts.c
3 *
4 * BRIEF MODULE DESCRIPTION
5 * Glue between Mirage board-specific touchscreen pieces
6 * and generic Wolfson Codec touchscreen support.
7 *
8 * Based on pb1100_ts.c used in Hydrogen II.
9 *
10 * Copyright (c) 2003 Embedded Edge, LLC
11 * dan@embeddededge.com
12 *
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.
17 *
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.
28 *
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.
32 */
33
1da177e4
LT
34#include <linux/types.h>
35#include <linux/module.h>
36#include <linux/sched.h>
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/fs.h>
40#include <linux/poll.h>
41#include <linux/proc_fs.h>
42#include <linux/smp.h>
43#include <linux/smp_lock.h>
44#include <linux/wait.h>
45
46#include <asm/segment.h>
47#include <asm/irq.h>
48#include <asm/uaccess.h>
49#include <asm/delay.h>
50#include <asm/au1000.h>
51
52/*
53 * Imported interface to Wolfson Codec driver.
54 */
55extern void *wm97xx_ts_get_handle(int which);
56extern int wm97xx_ts_ready(void* ts_handle);
57extern void wm97xx_ts_set_cal(void* ts_handle, int xscale, int xtrans, int yscale, int ytrans);
58extern u16 wm97xx_ts_get_ac97(void* ts_handle, u8 reg);
59extern void wm97xx_ts_set_ac97(void* ts_handle, u8 reg, u16 val);
60extern int wm97xx_ts_read_data(void* ts_handle, long* x, long* y, long* pressure);
61extern void wm97xx_ts_send_data(void* ts_handle, long x, long y, long z);
62
63int wm97xx_comodule_present = 1;
64
65
66#define TS_NAME "mirage_ts"
67
68#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
69#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
70#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
71#define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
72
73
74#define PEN_DOWN_IRQ AU1000_GPIO_7
75
76static struct task_struct *ts_task = 0;
77static DECLARE_COMPLETION(ts_complete);
78static DECLARE_WAIT_QUEUE_HEAD(pendown_wait);
79
80#ifdef CONFIG_WM97XX_FIVEWIRETS
81static int release_pressure = 1;
82#else
83static int release_pressure = 50;
84#endif
85
86typedef struct {
87 long x;
88 long y;
89} DOWN_EVENT;
90
91#define SAMPLE_RATE 50 /* samples per second */
92#define PEN_DEBOUNCE 5 /* samples for settling - fn of SAMPLE_RATE */
93#define PEN_UP_TIMEOUT 10 /* in seconds */
94#define PEN_UP_SETTLE 5 /* samples per second */
95
96static struct {
97 int xscale;
98 int xtrans;
99 int yscale;
100 int ytrans;
101} mirage_ts_cal =
102{
103#if 0
0f04afb5
RB
104 .xscale = 84,
105 .xtrans = -157,
106 .yscale = 66,
107 .ytrans = -150,
1da177e4 108#else
0f04afb5
RB
109 .xscale = 84,
110 .xtrans = -150,
111 .yscale = 66,
112 .ytrans = -146,
1da177e4
LT
113#endif
114};
115
116
117static void pendown_irq(int irqnr, void *devid, struct pt_regs *regs)
118{
119//DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD));
120 wake_up(&pendown_wait);
121}
122
123static int ts_thread(void *id)
124{
125 static int pen_was_down = 0;
126 static DOWN_EVENT pen_xy;
127 long x, y, z;
128 void *ts; /* handle */
129 struct task_struct *tsk = current;
130 int timeout = HZ / SAMPLE_RATE;
131
132 ts_task = tsk;
133
134 daemonize();
135 tsk->tty = NULL;
136 tsk->policy = SCHED_FIFO;
137 tsk->rt_priority = 1;
138 strcpy(tsk->comm, "touchscreen");
139
140 /* only want to receive SIGKILL */
141 spin_lock_irq(&tsk->sigmask_lock);
142 siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
143 recalc_sigpending(tsk);
144 spin_unlock_irq(&tsk->sigmask_lock);
145
146 /* get handle for codec */
147 ts = wm97xx_ts_get_handle(0);
148
149 /* proceed only after everybody is ready */
150 wait_event_timeout(pendown_wait, wm97xx_ts_ready(ts), HZ/4);
151
152 /* board-specific calibration */
153 wm97xx_ts_set_cal(ts,
154 mirage_ts_cal.xscale,
155 mirage_ts_cal.xtrans,
156 mirage_ts_cal.yscale,
157 mirage_ts_cal.ytrans);
158
159 /* route Wolfson pendown interrupts to our GPIO */
160 au_sync();
161 wm97xx_ts_set_ac97(ts, 0x4c, wm97xx_ts_get_ac97(ts, 0x4c) & ~0x0008);
162 au_sync();
163 wm97xx_ts_set_ac97(ts, 0x56, wm97xx_ts_get_ac97(ts, 0x56) & ~0x0008);
164 au_sync();
165 wm97xx_ts_set_ac97(ts, 0x52, wm97xx_ts_get_ac97(ts, 0x52) | 0x2008);
166 au_sync();
167
168 for (;;) {
169 interruptible_sleep_on_timeout(&pendown_wait, timeout);
170 disable_irq(PEN_DOWN_IRQ);
171 if (signal_pending(tsk)) {
172 break;
173 }
174
175 /* read codec */
176 if (!wm97xx_ts_read_data(ts, &x, &y, &z))
177 z = 0; /* treat no-data and pen-up the same */
178
179 if (signal_pending(tsk)) {
180 break;
181 }
182
183 if (z >= release_pressure) {
184 y = ~y; /* top to bottom */
185 if (pen_was_down > 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX
186 /* bounce ? */
187 x = pen_xy.x;
188 y = pen_xy.y;
189 --pen_was_down;
190 } else if (pen_was_down <= 1) {
191 pen_xy.x = x;
192 pen_xy.y = y;
193 if (pen_was_down)
194 wm97xx_ts_send_data(ts, x, y, z);
195 pen_was_down = PEN_DEBOUNCE;
196 }
197 //wm97xx_ts_send_data(ts, x, y, z);
198 timeout = HZ / SAMPLE_RATE;
199 } else {
200 if (pen_was_down) {
201 if (--pen_was_down)
202 z = release_pressure;
203 else //THXXX
204 wm97xx_ts_send_data(ts, pen_xy.x, pen_xy.y, z);
205 }
206 /* The pendown signal takes some time to settle after
207 * reading the pen pressure so wait a little
208 * before enabling the pen.
209 */
210 if (! pen_was_down) {
211// interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE);
212 timeout = HZ * PEN_UP_TIMEOUT;
213 }
214 }
215 enable_irq(PEN_DOWN_IRQ);
216 }
217 enable_irq(PEN_DOWN_IRQ);
218 ts_task = NULL;
219 complete(&ts_complete);
220 return 0;
221}
222
223static int __init ts_mirage_init(void)
224{
225 int ret;
226
227 /* pen down signal is connected to GPIO 7 */
228
229 ret = request_irq(PEN_DOWN_IRQ, pendown_irq, 0, "ts-pendown", NULL);
230 if (ret) {
231 err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ, ret);
232 return ret;
233 }
234
235 lock_kernel();
236 ret = kernel_thread(ts_thread, NULL, CLONE_FS | CLONE_FILES);
237 if (ret < 0) {
238 unlock_kernel();
239 return ret;
240 }
241 unlock_kernel();
242
243 info("Mirage touchscreen IRQ initialized.");
244
245 return 0;
246}
247
248static void __exit ts_mirage_exit(void)
249{
250 if (ts_task) {
251 send_sig(SIGKILL, ts_task, 1);
252 wait_for_completion(&ts_complete);
253 }
254
255 free_irq(PEN_DOWN_IRQ, NULL);
256}
257
258module_init(ts_mirage_init);
259module_exit(ts_mirage_exit);
260