mirage_ts.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. #include <linux/config.h>
  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. #include <asm/segment.h>
  46. #include <asm/irq.h>
  47. #include <asm/uaccess.h>
  48. #include <asm/delay.h>
  49. #include <asm/au1000.h>
  50. /*
  51. * Imported interface to Wolfson Codec driver.
  52. */
  53. extern void *wm97xx_ts_get_handle(int which);
  54. extern int wm97xx_ts_ready(void* ts_handle);
  55. extern void wm97xx_ts_set_cal(void* ts_handle, int xscale, int xtrans, int yscale, int ytrans);
  56. extern u16 wm97xx_ts_get_ac97(void* ts_handle, u8 reg);
  57. extern void wm97xx_ts_set_ac97(void* ts_handle, u8 reg, u16 val);
  58. extern int wm97xx_ts_read_data(void* ts_handle, long* x, long* y, long* pressure);
  59. extern void wm97xx_ts_send_data(void* ts_handle, long x, long y, long z);
  60. int wm97xx_comodule_present = 1;
  61. #define TS_NAME "mirage_ts"
  62. #define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
  63. #define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
  64. #define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
  65. #define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
  66. #define PEN_DOWN_IRQ AU1000_GPIO_7
  67. static struct task_struct *ts_task = 0;
  68. static DECLARE_COMPLETION(ts_complete);
  69. static DECLARE_WAIT_QUEUE_HEAD(pendown_wait);
  70. #ifdef CONFIG_WM97XX_FIVEWIRETS
  71. static int release_pressure = 1;
  72. #else
  73. static int release_pressure = 50;
  74. #endif
  75. typedef struct {
  76. long x;
  77. long y;
  78. } DOWN_EVENT;
  79. #define SAMPLE_RATE 50 /* samples per second */
  80. #define PEN_DEBOUNCE 5 /* samples for settling - fn of SAMPLE_RATE */
  81. #define PEN_UP_TIMEOUT 10 /* in seconds */
  82. #define PEN_UP_SETTLE 5 /* samples per second */
  83. static struct {
  84. int xscale;
  85. int xtrans;
  86. int yscale;
  87. int ytrans;
  88. } mirage_ts_cal =
  89. {
  90. #if 0
  91. xscale: 84,
  92. xtrans: -157,
  93. yscale: 66,
  94. ytrans: -150,
  95. #else
  96. xscale: 84,
  97. xtrans: -150,
  98. yscale: 66,
  99. ytrans: -146,
  100. #endif
  101. };
  102. static void pendown_irq(int irqnr, void *devid, struct pt_regs *regs)
  103. {
  104. //DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD));
  105. wake_up(&pendown_wait);
  106. }
  107. static int ts_thread(void *id)
  108. {
  109. static int pen_was_down = 0;
  110. static DOWN_EVENT pen_xy;
  111. long x, y, z;
  112. void *ts; /* handle */
  113. struct task_struct *tsk = current;
  114. int timeout = HZ / SAMPLE_RATE;
  115. ts_task = tsk;
  116. daemonize();
  117. tsk->tty = NULL;
  118. tsk->policy = SCHED_FIFO;
  119. tsk->rt_priority = 1;
  120. strcpy(tsk->comm, "touchscreen");
  121. /* only want to receive SIGKILL */
  122. spin_lock_irq(&tsk->sigmask_lock);
  123. siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
  124. recalc_sigpending(tsk);
  125. spin_unlock_irq(&tsk->sigmask_lock);
  126. /* get handle for codec */
  127. ts = wm97xx_ts_get_handle(0);
  128. /* proceed only after everybody is ready */
  129. wait_event_timeout(pendown_wait, wm97xx_ts_ready(ts), HZ/4);
  130. /* board-specific calibration */
  131. wm97xx_ts_set_cal(ts,
  132. mirage_ts_cal.xscale,
  133. mirage_ts_cal.xtrans,
  134. mirage_ts_cal.yscale,
  135. mirage_ts_cal.ytrans);
  136. /* route Wolfson pendown interrupts to our GPIO */
  137. au_sync();
  138. wm97xx_ts_set_ac97(ts, 0x4c, wm97xx_ts_get_ac97(ts, 0x4c) & ~0x0008);
  139. au_sync();
  140. wm97xx_ts_set_ac97(ts, 0x56, wm97xx_ts_get_ac97(ts, 0x56) & ~0x0008);
  141. au_sync();
  142. wm97xx_ts_set_ac97(ts, 0x52, wm97xx_ts_get_ac97(ts, 0x52) | 0x2008);
  143. au_sync();
  144. for (;;) {
  145. interruptible_sleep_on_timeout(&pendown_wait, timeout);
  146. disable_irq(PEN_DOWN_IRQ);
  147. if (signal_pending(tsk)) {
  148. break;
  149. }
  150. /* read codec */
  151. if (!wm97xx_ts_read_data(ts, &x, &y, &z))
  152. z = 0; /* treat no-data and pen-up the same */
  153. if (signal_pending(tsk)) {
  154. break;
  155. }
  156. if (z >= release_pressure) {
  157. y = ~y; /* top to bottom */
  158. if (pen_was_down > 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX
  159. /* bounce ? */
  160. x = pen_xy.x;
  161. y = pen_xy.y;
  162. --pen_was_down;
  163. } else if (pen_was_down <= 1) {
  164. pen_xy.x = x;
  165. pen_xy.y = y;
  166. if (pen_was_down)
  167. wm97xx_ts_send_data(ts, x, y, z);
  168. pen_was_down = PEN_DEBOUNCE;
  169. }
  170. //wm97xx_ts_send_data(ts, x, y, z);
  171. timeout = HZ / SAMPLE_RATE;
  172. } else {
  173. if (pen_was_down) {
  174. if (--pen_was_down)
  175. z = release_pressure;
  176. else //THXXX
  177. wm97xx_ts_send_data(ts, pen_xy.x, pen_xy.y, z);
  178. }
  179. /* The pendown signal takes some time to settle after
  180. * reading the pen pressure so wait a little
  181. * before enabling the pen.
  182. */
  183. if (! pen_was_down) {
  184. // interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE);
  185. timeout = HZ * PEN_UP_TIMEOUT;
  186. }
  187. }
  188. enable_irq(PEN_DOWN_IRQ);
  189. }
  190. enable_irq(PEN_DOWN_IRQ);
  191. ts_task = NULL;
  192. complete(&ts_complete);
  193. return 0;
  194. }
  195. static int __init ts_mirage_init(void)
  196. {
  197. int ret;
  198. /* pen down signal is connected to GPIO 7 */
  199. ret = request_irq(PEN_DOWN_IRQ, pendown_irq, 0, "ts-pendown", NULL);
  200. if (ret) {
  201. err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ, ret);
  202. return ret;
  203. }
  204. lock_kernel();
  205. ret = kernel_thread(ts_thread, NULL, CLONE_FS | CLONE_FILES);
  206. if (ret < 0) {
  207. unlock_kernel();
  208. return ret;
  209. }
  210. unlock_kernel();
  211. info("Mirage touchscreen IRQ initialized.");
  212. return 0;
  213. }
  214. static void __exit ts_mirage_exit(void)
  215. {
  216. if (ts_task) {
  217. send_sig(SIGKILL, ts_task, 1);
  218. wait_for_completion(&ts_complete);
  219. }
  220. free_irq(PEN_DOWN_IRQ, NULL);
  221. }
  222. module_init(ts_mirage_init);
  223. module_exit(ts_mirage_exit);