summaryrefslogtreecommitdiffstats
path: root/arch/mips/au1000/db1x00
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/au1000/db1x00
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/mips/au1000/db1x00')
-rw-r--r--arch/mips/au1000/db1x00/Makefile9
-rw-r--r--arch/mips/au1000/db1x00/board_setup.c127
-rw-r--r--arch/mips/au1000/db1x00/init.c74
-rw-r--r--arch/mips/au1000/db1x00/irqmap.c72
-rw-r--r--arch/mips/au1000/db1x00/mirage_ts.c261
5 files changed, 543 insertions, 0 deletions
diff --git a/arch/mips/au1000/db1x00/Makefile b/arch/mips/au1000/db1x00/Makefile
new file mode 100644
index 00000000000..4c7d763f211
--- /dev/null
+++ b/arch/mips/au1000/db1x00/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright 2000 MontaVista Software Inc.
+# Author: MontaVista Software, Inc.
+# ppopov@mvista.com or source@mvista.com
+#
+# Makefile for the Alchemy Semiconductor Db1x00 board.
+
+lib-y := init.o board_setup.o irqmap.o
+obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o
diff --git a/arch/mips/au1000/db1x00/board_setup.c b/arch/mips/au1000/db1x00/board_setup.c
new file mode 100644
index 00000000000..ac05ba0ff63
--- /dev/null
+++ b/arch/mips/au1000/db1x00/board_setup.c
@@ -0,0 +1,127 @@
+/*
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Alchemy Db1x00 board setup.
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/mc146818rtc.h>
+#include <linux/delay.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-db1x00/db1x00.h>
+
+/* not correct for db1550 */
+static BCSR * const bcsr = (BCSR *)0xAE000000;
+
+void board_reset (void)
+{
+ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
+ au_writel(0x00000000, 0xAE00001C);
+}
+
+void __init board_setup(void)
+{
+ u32 pin_func;
+
+ pin_func = 0;
+ /* not valid for 1550 */
+#ifdef CONFIG_AU1X00_USB_DEVICE
+ // 2nd USB port is USB device
+ pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000);
+ au_writel(pin_func, SYS_PINFUNC);
+#endif
+
+#if defined(CONFIG_IRDA) && (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
+ /* set IRFIRSEL instead of GPIO15 */
+ pin_func = au_readl(SYS_PINFUNC) | (u32)((1<<8));
+ au_writel(pin_func, SYS_PINFUNC);
+ /* power off until the driver is in use */
+ bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK;
+ bcsr->resets |= BCSR_RESETS_IRDA_MODE_OFF;
+ au_sync();
+#endif
+ au_writel(0, 0xAE000010); /* turn off pcmcia power */
+
+#ifdef CONFIG_MIPS_MIRAGE
+ /* enable GPIO[31:0] inputs */
+ au_writel(0, SYS_PININPUTEN);
+
+ /* GPIO[20] is output, tristate the other input primary GPIO's */
+ au_writel((u32)(~(1<<20)), SYS_TRIOUTCLR);
+
+ /* set GPIO[210:208] instead of SSI_0 */
+ pin_func = au_readl(SYS_PINFUNC) | (u32)(1);
+
+ /* set GPIO[215:211] for LED's */
+ pin_func |= (u32)((5<<2));
+
+ /* set GPIO[214:213] for more LED's */
+ pin_func |= (u32)((5<<12));
+
+ /* set GPIO[207:200] instead of PCMCIA/LCD */
+ pin_func |= (u32)((3<<17));
+ au_writel(pin_func, SYS_PINFUNC);
+
+ /* Enable speaker amplifier. This should
+ * be part of the audio driver.
+ */
+ au_writel(au_readl(GPIO2_DIR) | 0x200, GPIO2_DIR);
+ au_writel(0x02000200, GPIO2_OUTPUT);
+#endif
+
+ au_sync();
+
+#ifdef CONFIG_MIPS_DB1000
+ printk("AMD Alchemy Au1000/Db1000 Board\n");
+#endif
+#ifdef CONFIG_MIPS_DB1500
+ printk("AMD Alchemy Au1500/Db1500 Board\n");
+#endif
+#ifdef CONFIG_MIPS_DB1100
+ printk("AMD Alchemy Au1100/Db1100 Board\n");
+#endif
+#ifdef CONFIG_MIPS_BOSPORUS
+ printk("AMD Alchemy Bosporus Board\n");
+#endif
+#ifdef CONFIG_MIPS_MIRAGE
+ printk("AMD Alchemy Mirage Board\n");
+#endif
+#ifdef CONFIG_MIPS_DB1550
+ printk("AMD Alchemy Au1550/Db1550 Board\n");
+#endif
+}
diff --git a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c
new file mode 100644
index 00000000000..51eee94a5e8
--- /dev/null
+++ b/arch/mips/au1000/db1x00/init.c
@@ -0,0 +1,74 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * PB1000 board setup
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: MontaVista Software, Inc.
+ * ppopov@mvista.com or source@mvista.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+extern void __init prom_init_cmdline(void);
+extern char *prom_getenv(char *envname);
+
+const char *get_system_type(void)
+{
+#ifdef CONFIG_MIPS_BOSPORUS
+ return "Alchemy Bosporus Gateway Reference";
+#else
+ return "Alchemy Db1x00";
+#endif
+}
+
+void __init prom_init(void)
+{
+ unsigned char *memsize_str;
+ unsigned long memsize;
+
+ prom_argc = fw_arg0;
+ prom_argv = (char **) fw_arg1;
+ prom_envp = (char **) fw_arg2;
+
+ mips_machgroup = MACH_GROUP_ALCHEMY;
+ mips_machtype = MACH_DB1000; /* set the platform # */
+
+ prom_init_cmdline();
+
+ memsize_str = prom_getenv("memsize");
+ if (!memsize_str)
+ memsize = 0x04000000;
+ else
+ memsize = simple_strtol(memsize_str, NULL, 0);
+ add_memory_region(0, memsize, BOOT_MEM_RAM);
+}
diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c
new file mode 100644
index 00000000000..8f6ef0dbe1f
--- /dev/null
+++ b/arch/mips/au1000/db1x00/irqmap.c
@@ -0,0 +1,72 @@
+/*
+ * BRIEF MODULE DESCRIPTION
+ * Au1xxx irq map table
+ *
+ * Copyright 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/mach-au1x00/au1000.h>
+
+au1xxx_irq_map_t au1xxx_irq_map[] = {
+
+#ifndef CONFIG_MIPS_MIRAGE
+#ifdef CONFIG_MIPS_DB1550
+ { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
+ { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
+#else
+ { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */
+ { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */
+ { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
+
+ { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */
+ { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */
+ { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
+#endif
+#else
+ { AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */
+#endif
+
+};
+
+int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
diff --git a/arch/mips/au1000/db1x00/mirage_ts.c b/arch/mips/au1000/db1x00/mirage_ts.c
new file mode 100644
index 00000000000..ade35e43200
--- /dev/null
+++ b/arch/mips/au1000/db1x00/mirage_ts.c
@@ -0,0 +1,261 @@
+/*
+ * linux/arch/mips/au1000/db1x00/mirage_ts.c
+ *
+ * BRIEF MODULE DESCRIPTION
+ * Glue between Mirage board-specific touchscreen pieces
+ * and generic Wolfson Codec touchscreen support.
+ *
+ * Based on pb1100_ts.c used in Hydrogen II.
+ *
+ * Copyright (c) 2003 Embedded Edge, LLC
+ * dan@embeddededge.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/proc_fs.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/wait.h>
+
+#include <asm/segment.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+#include <asm/au1000.h>
+
+/*
+ * Imported interface to Wolfson Codec driver.
+ */
+extern void *wm97xx_ts_get_handle(int which);
+extern int wm97xx_ts_ready(void* ts_handle);
+extern void wm97xx_ts_set_cal(void* ts_handle, int xscale, int xtrans, int yscale, int ytrans);
+extern u16 wm97xx_ts_get_ac97(void* ts_handle, u8 reg);
+extern void wm97xx_ts_set_ac97(void* ts_handle, u8 reg, u16 val);
+extern int wm97xx_ts_read_data(void* ts_handle, long* x, long* y, long* pressure);
+extern void wm97xx_ts_send_data(void* ts_handle, long x, long y, long z);
+
+int wm97xx_comodule_present = 1;
+
+
+#define TS_NAME "mirage_ts"
+
+#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
+#define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
+
+
+#define PEN_DOWN_IRQ AU1000_GPIO_7
+
+static struct task_struct *ts_task = 0;
+static DECLARE_COMPLETION(ts_complete);
+static DECLARE_WAIT_QUEUE_HEAD(pendown_wait);
+
+#ifdef CONFIG_WM97XX_FIVEWIRETS
+static int release_pressure = 1;
+#else
+static int release_pressure = 50;
+#endif
+
+typedef struct {
+ long x;
+ long y;
+} DOWN_EVENT;
+
+#define SAMPLE_RATE 50 /* samples per second */
+#define PEN_DEBOUNCE 5 /* samples for settling - fn of SAMPLE_RATE */
+#define PEN_UP_TIMEOUT 10 /* in seconds */
+#define PEN_UP_SETTLE 5 /* samples per second */
+
+static struct {
+ int xscale;
+ int xtrans;
+ int yscale;
+ int ytrans;
+} mirage_ts_cal =
+{
+#if 0
+ xscale: 84,
+ xtrans: -157,
+ yscale: 66,
+ ytrans: -150,
+#else
+ xscale: 84,
+ xtrans: -150,
+ yscale: 66,
+ ytrans: -146,
+#endif
+};
+
+
+static void pendown_irq(int irqnr, void *devid, struct pt_regs *regs)
+{
+//DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD));
+ wake_up(&pendown_wait);
+}
+
+static int ts_thread(void *id)
+{
+ static int pen_was_down = 0;
+ static DOWN_EVENT pen_xy;
+ long x, y, z;
+ void *ts; /* handle */
+ struct task_struct *tsk = current;
+ int timeout = HZ / SAMPLE_RATE;
+
+ ts_task = tsk;
+
+ daemonize();
+ tsk->tty = NULL;
+ tsk->policy = SCHED_FIFO;
+ tsk->rt_priority = 1;
+ strcpy(tsk->comm, "touchscreen");
+
+ /* only want to receive SIGKILL */
+ spin_lock_irq(&tsk->sigmask_lock);
+ siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
+ recalc_sigpending(tsk);
+ spin_unlock_irq(&tsk->sigmask_lock);
+
+ /* get handle for codec */
+ ts = wm97xx_ts_get_handle(0);
+
+ /* proceed only after everybody is ready */
+ wait_event_timeout(pendown_wait, wm97xx_ts_ready(ts), HZ/4);
+
+ /* board-specific calibration */
+ wm97xx_ts_set_cal(ts,
+ mirage_ts_cal.xscale,
+ mirage_ts_cal.xtrans,
+ mirage_ts_cal.yscale,
+ mirage_ts_cal.ytrans);
+
+ /* route Wolfson pendown interrupts to our GPIO */
+ au_sync();
+ wm97xx_ts_set_ac97(ts, 0x4c, wm97xx_ts_get_ac97(ts, 0x4c) & ~0x0008);
+ au_sync();
+ wm97xx_ts_set_ac97(ts, 0x56, wm97xx_ts_get_ac97(ts, 0x56) & ~0x0008);
+ au_sync();
+ wm97xx_ts_set_ac97(ts, 0x52, wm97xx_ts_get_ac97(ts, 0x52) | 0x2008);
+ au_sync();
+
+ for (;;) {
+ interruptible_sleep_on_timeout(&pendown_wait, timeout);
+ disable_irq(PEN_DOWN_IRQ);
+ if (signal_pending(tsk)) {
+ break;
+ }
+
+ /* read codec */
+ if (!wm97xx_ts_read_data(ts, &x, &y, &z))
+ z = 0; /* treat no-data and pen-up the same */
+
+ if (signal_pending(tsk)) {
+ break;
+ }
+
+ if (z >= release_pressure) {
+ y = ~y; /* top to bottom */
+ if (pen_was_down > 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX
+ /* bounce ? */
+ x = pen_xy.x;
+ y = pen_xy.y;
+ --pen_was_down;
+ } else if (pen_was_down <= 1) {
+ pen_xy.x = x;
+ pen_xy.y = y;
+ if (pen_was_down)
+ wm97xx_ts_send_data(ts, x, y, z);
+ pen_was_down = PEN_DEBOUNCE;
+ }
+ //wm97xx_ts_send_data(ts, x, y, z);
+ timeout = HZ / SAMPLE_RATE;
+ } else {
+ if (pen_was_down) {
+ if (--pen_was_down)
+ z = release_pressure;
+ else //THXXX
+ wm97xx_ts_send_data(ts, pen_xy.x, pen_xy.y, z);
+ }
+ /* The pendown signal takes some time to settle after
+ * reading the pen pressure so wait a little
+ * before enabling the pen.
+ */
+ if (! pen_was_down) {
+// interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE);
+ timeout = HZ * PEN_UP_TIMEOUT;
+ }
+ }
+ enable_irq(PEN_DOWN_IRQ);
+ }
+ enable_irq(PEN_DOWN_IRQ);
+ ts_task = NULL;
+ complete(&ts_complete);
+ return 0;
+}
+
+static int __init ts_mirage_init(void)
+{
+ int ret;
+
+ /* pen down signal is connected to GPIO 7 */
+
+ ret = request_irq(PEN_DOWN_IRQ, pendown_irq, 0, "ts-pendown", NULL);
+ if (ret) {
+ err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ, ret);
+ return ret;
+ }
+
+ lock_kernel();
+ ret = kernel_thread(ts_thread, NULL, CLONE_FS | CLONE_FILES);
+ if (ret < 0) {
+ unlock_kernel();
+ return ret;
+ }
+ unlock_kernel();
+
+ info("Mirage touchscreen IRQ initialized.");
+
+ return 0;
+}
+
+static void __exit ts_mirage_exit(void)
+{
+ if (ts_task) {
+ send_sig(SIGKILL, ts_task, 1);
+ wait_for_completion(&ts_complete);
+ }
+
+ free_irq(PEN_DOWN_IRQ, NULL);
+}
+
+module_init(ts_mirage_init);
+module_exit(ts_mirage_exit);
+