123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /*
- * 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);
|