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 architecture
  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         * threshold 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                dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n",
 157                        x, y, p);
 158
 159                /* are samples valid */
 160                if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
 161                    (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
 162                    (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
 163                        goto up;
 164
 165                /* coordinate is good */
 166                tries = 0;
 167                input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
 168                input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
 169                input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
 170                input_report_key(wm->input_dev, BTN_TOUCH, (p != 0));
 171                input_sync(wm->input_dev);
 172                reads++;
 173        } while (reads < cinfo[sp_idx].reads);
 174up:
 175        return RC_PENDOWN | RC_AGAIN;
 176}
 177
 178static int wm97xx_acc_startup(struct wm97xx *wm)
 179{
 180        int idx = 0, ret = 0;
 181
 182        /* check we have a codec */
 183        if (wm->ac97 == NULL)
 184                return -ENODEV;
 185
 186        /* Go you big red fire engine */
 187        for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
 188                if (wm->id != cinfo[idx].id)
 189                        continue;
 190                sp_idx = idx;
 191                if (cont_rate <= cinfo[idx].speed)
 192                        break;
 193        }
 194        wm->acc_rate = cinfo[sp_idx].code;
 195        wm->acc_slot = ac97_touch_slot;
 196        dev_info(wm->dev,
 197                 "mainstone accelerated touchscreen driver, %d samples/sec\n",
 198                 cinfo[sp_idx].speed);
 199
 200        /* IRQ driven touchscreen is used on Palm hardware */
 201        if (machine_is_palmt5() || machine_is_palmtx() || machine_is_palmld()) {
 202                pen_int = 1;
 203                irq = 27;
 204                /* There is some obscure mutant of WM9712 interbred with WM9713
 205                 * used on Palm HW */
 206                wm->variant = WM97xx_WM1613;
 207        } else if (machine_is_mainstone() && pen_int)
 208                irq = 4;
 209
 210        if (irq) {
 211                ret = gpio_request(irq, "Touchscreen IRQ");
 212                if (ret)
 213                        goto out;
 214
 215                ret = gpio_direction_input(irq);
 216                if (ret) {
 217                        gpio_free(irq);
 218                        goto out;
 219                }
 220
 221                wm->pen_irq = gpio_to_irq(irq);
 222                irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
 223        } else /* pen irq not supported */
 224                pen_int = 0;
 225
 226        /* codec specific irq config */
 227        if (pen_int) {
 228                switch (wm->id) {
 229                case WM9705_ID2:
 230                        break;
 231                case WM9712_ID2:
 232                case WM9713_ID2:
 233                        /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
 234                        wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
 235                                           WM97XX_GPIO_POL_HIGH,
 236                                           WM97XX_GPIO_STICKY,
 237                                           WM97XX_GPIO_WAKE);
 238                        wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
 239                                           WM97XX_GPIO_POL_HIGH,
 240                                           WM97XX_GPIO_NOTSTICKY,
 241                                           WM97XX_GPIO_NOWAKE);
 242                        break;
 243                default:
 244                        dev_err(wm->dev,
 245                                "pen down irq not supported on this device\n");
 246                        pen_int = 0;
 247                        break;
 248                }
 249        }
 250
 251out:
 252        return ret;
 253}
 254
 255static void wm97xx_acc_shutdown(struct wm97xx *wm)
 256{
 257        /* codec specific deconfig */
 258        if (pen_int) {
 259                if (irq)
 260                        gpio_free(irq);
 261                wm->pen_irq = 0;
 262        }
 263}
 264
 265static void wm97xx_irq_enable(struct wm97xx *wm, int enable)
 266{
 267        if (enable)
 268                enable_irq(wm->pen_irq);
 269        else
 270                disable_irq_nosync(wm->pen_irq);
 271}
 272
 273static struct wm97xx_mach_ops mainstone_mach_ops = {
 274        .acc_enabled = 1,
 275        .acc_pen_up = wm97xx_acc_pen_up,
 276        .acc_pen_down = wm97xx_acc_pen_down,
 277        .acc_startup = wm97xx_acc_startup,
 278        .acc_shutdown = wm97xx_acc_shutdown,
 279        .irq_enable = wm97xx_irq_enable,
 280        .irq_gpio = WM97XX_GPIO_2,
 281};
 282
 283static int mainstone_wm97xx_probe(struct platform_device *pdev)
 284{
 285        struct wm97xx *wm = platform_get_drvdata(pdev);
 286
 287        return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
 288}
 289
 290static int mainstone_wm97xx_remove(struct platform_device *pdev)
 291{
 292        struct wm97xx *wm = platform_get_drvdata(pdev);
 293
 294        wm97xx_unregister_mach_ops(wm);
 295        return 0;
 296}
 297
 298static struct platform_driver mainstone_wm97xx_driver = {
 299        .probe = mainstone_wm97xx_probe,
 300        .remove = mainstone_wm97xx_remove,
 301        .driver = {
 302                .name = "wm97xx-touch",
 303        },
 304};
 305module_platform_driver(mainstone_wm97xx_driver);
 306
 307/* Module information */
 308MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
 309MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
 310MODULE_LICENSE("GPL");
 311