linux/drivers/input/touchscreen/mainstone-wm97xx.c
<<
>>
Prefs
   1/*
   2 * mainstone-wm97xx.c  --  Mainstone Continuous Touch screen driver for
   3 *                         Wolfson WM97xx AC97 Codecs.
   4 *
   5 * Copyright 2004, 2007 Wolfson Microelectronics PLC.
   6 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
   7 * Parts Copyright : Ian Molton <spyro@f2s.com>
   8 *                   Andrew Zabolotny <zap@homelink.ru>
   9 *
  10 *  This program is free software; you can redistribute  it and/or modify it
  11 *  under  the terms of  the GNU General  Public License as published by the
  12 *  Free Software Foundation;  either version 2 of the  License, or (at your
  13 *  option) any later version.
  14 *
  15 * Notes:
  16 *     This is a wm97xx extended touch driver to capture touch
  17 *     data in a continuous manner on the Intel XScale archictecture
  18 *
  19 *  Features:
  20 *       - codecs supported:- WM9705, WM9712, WM9713
  21 *       - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
  22 *
  23 */
  24
  25#include <linux/module.h>
  26#include <linux/moduleparam.h>
  27#include <linux/kernel.h>
  28#include <linux/init.h>
  29#include <linux/delay.h>
  30#include <linux/irq.h>
  31#include <linux/interrupt.h>
  32#include <linux/wm97xx.h>
  33#include <linux/io.h>
  34#include <linux/gpio.h>
  35
  36#include <mach/regs-ac97.h>
  37
  38#include <asm/mach-types.h>
  39
  40struct continuous {
  41        u16 id;    /* codec id */
  42        u8 code;   /* continuous code */
  43        u8 reads;  /* number of coord reads per read cycle */
  44        u32 speed; /* number of coords per second */
  45};
  46
  47#define WM_READS(sp) ((sp / HZ) + 1)
  48
  49static const struct continuous cinfo[] = {
  50        {WM9705_ID2, 0, WM_READS(94), 94},
  51        {WM9705_ID2, 1, WM_READS(188), 188},
  52        {WM9705_ID2, 2, WM_READS(375), 375},
  53        {WM9705_ID2, 3, WM_READS(750), 750},
  54        {WM9712_ID2, 0, WM_READS(94), 94},
  55        {WM9712_ID2, 1, WM_READS(188), 188},
  56        {WM9712_ID2, 2, WM_READS(375), 375},
  57        {WM9712_ID2, 3, WM_READS(750), 750},
  58        {WM9713_ID2, 0, WM_READS(94), 94},
  59        {WM9713_ID2, 1, WM_READS(120), 120},
  60        {WM9713_ID2, 2, WM_READS(154), 154},
  61        {WM9713_ID2, 3, WM_READS(188), 188},
  62};
  63
  64/* continuous speed index */
  65static int sp_idx;
  66static u16 last, tries;
  67static int irq;
  68
  69/*
  70 * Pen sampling frequency (Hz) in continuous mode.
  71 */
  72static int cont_rate = 200;
  73module_param(cont_rate, int, 0);
  74MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
  75
  76/*
  77 * Pen down detection.
  78 *
  79 * This driver can either poll or use an interrupt to indicate a pen down
  80 * event. If the irq request fails then it will fall back to polling mode.
  81 */
  82static int pen_int;
  83module_param(pen_int, int, 0);
  84MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
  85
  86/*
  87 * Pressure readback.
  88 *
  89 * Set to 1 to read back pen down pressure
  90 */
  91static int pressure;
  92module_param(pressure, int, 0);
  93MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
  94
  95/*
  96 * AC97 touch data slot.
  97 *
  98 * Touch screen readback data ac97 slot
  99 */
 100static int ac97_touch_slot = 5;
 101module_param(ac97_touch_slot, int, 0);
 102MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
 103
 104
 105/* flush AC97 slot 5 FIFO on pxa machines */
 106#ifdef CONFIG_PXA27x
 107static void wm97xx_acc_pen_up(struct wm97xx *wm)
 108{
 109        schedule_timeout_uninterruptible(1);
 110
 111        while (MISR & (1 << 2))
 112                MODR;
 113}
 114#else
 115static void wm97xx_acc_pen_up(struct wm97xx *wm)
 116{
 117        unsigned int count;
 118
 119        schedule_timeout_uninterruptible(1);
 120
 121        for (count = 0; count < 16; count++)
 122                MODR;
 123}
 124#endif
 125
 126static int wm97xx_acc_pen_down(struct wm97xx *wm)
 127{
 128        u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
 129        int reads = 0;
 130
 131        /* When the AC97 queue has been drained we need to allow time
 132         * to buffer up samples otherwise we end up spinning polling
 133         * for samples.  The controller can't have a suitably low
 134         * threashold set to use the notifications it gives.
 135         */
 136        schedule_timeout_uninterruptible(1);
 137
 138        if (tries > 5) {
 139                tries = 0;
 140                return RC_PENUP;
 141        }
 142
 143        x = MODR;
 144        if (x == last) {
 145                tries++;
 146                return RC_AGAIN;
 147        }
 148        last = x;
 149        do {
 150                if (reads)
 151                        x = MODR;
 152                y = MODR;
 153                if (pressure)
 154                        p = MODR;
 155
 156                /* are samples valid */
 157                if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X ||
 158                    (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y ||
 159                    (p & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_PRES)
 160                        goto up;
 161
 162                /* coordinate is good */
 163                tries = 0;
 164                input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
 165                input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
 166                input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
 167                input_report_key(wm->input_dev, BTN_TOUCH, (p != 0));
 168                input_sync(wm->input_dev);
 169                reads++;
 170        } while (reads < cinfo[sp_idx].reads);
 171up:
 172        return RC_PENDOWN | RC_AGAIN;
 173}
 174
 175static int wm97xx_acc_startup(struct wm97xx *wm)
 176{
 177        int idx = 0, ret = 0;
 178
 179        /* check we have a codec */
 180        if (wm->ac97 == NULL)
 181                return -ENODEV;
 182
 183        /* Go you big red fire engine */
 184        for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
 185                if (wm->id != cinfo[idx].id)
 186                        continue;
 187                sp_idx = idx;
 188                if (cont_rate <= cinfo[idx].speed)
 189                        break;
 190        }
 191        wm->acc_rate = cinfo[sp_idx].code;
 192        wm->acc_slot = ac97_touch_slot;
 193        dev_info(wm->dev,
 194                 "mainstone accelerated touchscreen driver, %d samples/sec\n",
 195                 cinfo[sp_idx].speed);
 196
 197        /* IRQ driven touchscreen is used on Palm hardware */
 198        if (machine_is_palmt5() || machine_is_palmtx() || machine_is_palmld()) {
 199                pen_int = 1;
 200                irq = 27;
 201                /* There is some obscure mutant of WM9712 interbred with WM9713
 202                 * used on Palm HW */
 203                wm->variant = WM97xx_WM1613;
 204        } else if (machine_is_mainstone() && pen_int)
 205                irq = 4;
 206
 207        if (irq) {
 208                ret = gpio_request(irq, "Touchscreen IRQ");
 209                if (ret)
 210                        goto out;
 211
 212                ret = gpio_direction_input(irq);
 213                if (ret) {
 214                        gpio_free(irq);
 215                        goto out;
 216                }
 217
 218                wm->pen_irq = gpio_to_irq(irq);
 219                set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
 220        } else /* pen irq not supported */
 221                pen_int = 0;
 222
 223        /* codec specific irq config */
 224        if (pen_int) {
 225                switch (wm->id) {
 226                case WM9705_ID2:
 227                        break;
 228                case WM9712_ID2:
 229                case WM9713_ID2:
 230                        /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
 231                        wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
 232                                           WM97XX_GPIO_POL_HIGH,
 233                                           WM97XX_GPIO_STICKY,
 234                                           WM97XX_GPIO_WAKE);
 235                        wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
 236                                           WM97XX_GPIO_POL_HIGH,
 237                                           WM97XX_GPIO_NOTSTICKY,
 238                                           WM97XX_GPIO_NOWAKE);
 239                        break;
 240                default:
 241                        dev_err(wm->dev,
 242                                "pen down irq not supported on this device\n");
 243                        pen_int = 0;
 244                        break;
 245                }
 246        }
 247
 248out:
 249        return ret;
 250}
 251
 252static void wm97xx_acc_shutdown(struct wm97xx *wm)
 253{
 254        /* codec specific deconfig */
 255        if (pen_int) {
 256                if (irq)
 257                        gpio_free(irq);
 258                wm->pen_irq = 0;
 259        }
 260}
 261
 262static void wm97xx_irq_enable(struct wm97xx *wm, int enable)
 263{
 264        if (enable)
 265                enable_irq(wm->pen_irq);
 266        else
 267                disable_irq_nosync(wm->pen_irq);
 268}
 269
 270static struct wm97xx_mach_ops mainstone_mach_ops = {
 271        .acc_enabled = 1,
 272        .acc_pen_up = wm97xx_acc_pen_up,
 273        .acc_pen_down = wm97xx_acc_pen_down,
 274        .acc_startup = wm97xx_acc_startup,
 275        .acc_shutdown = wm97xx_acc_shutdown,
 276        .irq_enable = wm97xx_irq_enable,
 277        .irq_gpio = WM97XX_GPIO_2,
 278};
 279
 280static int mainstone_wm97xx_probe(struct platform_device *pdev)
 281{
 282        struct wm97xx *wm = platform_get_drvdata(pdev);
 283
 284        return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
 285}
 286
 287static int mainstone_wm97xx_remove(struct platform_device *pdev)
 288{
 289        struct wm97xx *wm = platform_get_drvdata(pdev);
 290
 291        wm97xx_unregister_mach_ops(wm);
 292        return 0;
 293}
 294
 295static struct platform_driver mainstone_wm97xx_driver = {
 296        .probe = mainstone_wm97xx_probe,
 297        .remove = mainstone_wm97xx_remove,
 298        .driver = {
 299                .name = "wm97xx-touch",
 300        },
 301};
 302
 303static int __init mainstone_wm97xx_init(void)
 304{
 305        return platform_driver_register(&mainstone_wm97xx_driver);
 306}
 307
 308static void __exit mainstone_wm97xx_exit(void)
 309{
 310        platform_driver_unregister(&mainstone_wm97xx_driver);
 311}
 312
 313module_init(mainstone_wm97xx_init);
 314module_exit(mainstone_wm97xx_exit);
 315
 316/* Module information */
 317MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
 318MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
 319MODULE_LICENSE("GPL");
 320