Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * mainstone-wm97xx.c  --  Mainstone Continuous Touch screen driver for
0004  *                         Wolfson WM97xx AC97 Codecs.
0005  *
0006  * Copyright 2004, 2007 Wolfson Microelectronics PLC.
0007  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
0008  * Parts Copyright : Ian Molton <spyro@f2s.com>
0009  *                   Andrew Zabolotny <zap@homelink.ru>
0010  *
0011  * Notes:
0012  *     This is a wm97xx extended touch driver to capture touch
0013  *     data in a continuous manner on the Intel XScale architecture
0014  *
0015  *  Features:
0016  *       - codecs supported:- WM9705, WM9712, WM9713
0017  *       - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
0018  */
0019 
0020 #include <linux/module.h>
0021 #include <linux/moduleparam.h>
0022 #include <linux/kernel.h>
0023 #include <linux/delay.h>
0024 #include <linux/gpio/consumer.h>
0025 #include <linux/irq.h>
0026 #include <linux/interrupt.h>
0027 #include <linux/io.h>
0028 #include <linux/soc/pxa/cpu.h>
0029 #include <linux/wm97xx.h>
0030 
0031 #include <sound/pxa2xx-lib.h>
0032 
0033 #include <asm/mach-types.h>
0034 
0035 struct continuous {
0036     u16 id;    /* codec id */
0037     u8 code;   /* continuous code */
0038     u8 reads;  /* number of coord reads per read cycle */
0039     u32 speed; /* number of coords per second */
0040 };
0041 
0042 #define WM_READS(sp) ((sp / HZ) + 1)
0043 
0044 static const struct continuous cinfo[] = {
0045     { WM9705_ID2, 0, WM_READS(94),  94  },
0046     { WM9705_ID2, 1, WM_READS(188), 188 },
0047     { WM9705_ID2, 2, WM_READS(375), 375 },
0048     { WM9705_ID2, 3, WM_READS(750), 750 },
0049     { WM9712_ID2, 0, WM_READS(94),  94  },
0050     { WM9712_ID2, 1, WM_READS(188), 188 },
0051     { WM9712_ID2, 2, WM_READS(375), 375 },
0052     { WM9712_ID2, 3, WM_READS(750), 750 },
0053     { WM9713_ID2, 0, WM_READS(94),  94  },
0054     { WM9713_ID2, 1, WM_READS(120), 120 },
0055     { WM9713_ID2, 2, WM_READS(154), 154 },
0056     { WM9713_ID2, 3, WM_READS(188), 188 },
0057 };
0058 
0059 /* continuous speed index */
0060 static int sp_idx;
0061 static struct gpio_desc *gpiod_irq;
0062 
0063 /*
0064  * Pen sampling frequency (Hz) in continuous mode.
0065  */
0066 static int cont_rate = 200;
0067 module_param(cont_rate, int, 0);
0068 MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
0069 
0070 /*
0071  * Pen down detection.
0072  *
0073  * This driver can either poll or use an interrupt to indicate a pen down
0074  * event. If the irq request fails then it will fall back to polling mode.
0075  */
0076 static int pen_int;
0077 module_param(pen_int, int, 0);
0078 MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
0079 
0080 /*
0081  * Pressure readback.
0082  *
0083  * Set to 1 to read back pen down pressure
0084  */
0085 static int pressure;
0086 module_param(pressure, int, 0);
0087 MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
0088 
0089 /*
0090  * AC97 touch data slot.
0091  *
0092  * Touch screen readback data ac97 slot
0093  */
0094 static int ac97_touch_slot = 5;
0095 module_param(ac97_touch_slot, int, 0);
0096 MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
0097 
0098 
0099 /* flush AC97 slot 5 FIFO on pxa machines */
0100 static void wm97xx_acc_pen_up(struct wm97xx *wm)
0101 {
0102     unsigned int count;
0103 
0104     msleep(1);
0105 
0106     if (cpu_is_pxa27x()) {
0107         while (pxa2xx_ac97_read_misr() & (1 << 2))
0108             pxa2xx_ac97_read_modr();
0109     } else if (cpu_is_pxa3xx()) {
0110         for (count = 0; count < 16; count++)
0111             pxa2xx_ac97_read_modr();
0112     }
0113 }
0114 
0115 static int wm97xx_acc_pen_down(struct wm97xx *wm)
0116 {
0117     u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
0118     int reads = 0;
0119     static u16 last, tries;
0120 
0121     /* When the AC97 queue has been drained we need to allow time
0122      * to buffer up samples otherwise we end up spinning polling
0123      * for samples.  The controller can't have a suitably low
0124      * threshold set to use the notifications it gives.
0125      */
0126     msleep(1);
0127 
0128     if (tries > 5) {
0129         tries = 0;
0130         return RC_PENUP;
0131     }
0132 
0133     x = pxa2xx_ac97_read_modr();
0134     if (x == last) {
0135         tries++;
0136         return RC_AGAIN;
0137     }
0138     last = x;
0139     do {
0140         if (reads)
0141             x = pxa2xx_ac97_read_modr();
0142         y = pxa2xx_ac97_read_modr();
0143         if (pressure)
0144             p = pxa2xx_ac97_read_modr();
0145 
0146         dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n",
0147             x, y, p);
0148 
0149         /* are samples valid */
0150         if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
0151             (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
0152             (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
0153             goto up;
0154 
0155         /* coordinate is good */
0156         tries = 0;
0157         input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
0158         input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
0159         input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
0160         input_report_key(wm->input_dev, BTN_TOUCH, (p != 0));
0161         input_sync(wm->input_dev);
0162         reads++;
0163     } while (reads < cinfo[sp_idx].reads);
0164 up:
0165     return RC_PENDOWN | RC_AGAIN;
0166 }
0167 
0168 static int wm97xx_acc_startup(struct wm97xx *wm)
0169 {
0170     int idx = 0, ret = 0;
0171 
0172     /* check we have a codec */
0173     if (wm->ac97 == NULL)
0174         return -ENODEV;
0175 
0176     /* Go you big red fire engine */
0177     for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
0178         if (wm->id != cinfo[idx].id)
0179             continue;
0180         sp_idx = idx;
0181         if (cont_rate <= cinfo[idx].speed)
0182             break;
0183     }
0184     wm->acc_rate = cinfo[sp_idx].code;
0185     wm->acc_slot = ac97_touch_slot;
0186     dev_info(wm->dev,
0187          "mainstone accelerated touchscreen driver, %d samples/sec\n",
0188          cinfo[sp_idx].speed);
0189 
0190     /* IRQ driven touchscreen is used on Palm hardware */
0191     if (machine_is_palmt5() || machine_is_palmtx() || machine_is_palmld()) {
0192         pen_int = 1;
0193         /* There is some obscure mutant of WM9712 interbred with WM9713
0194          * used on Palm HW */
0195         wm->variant = WM97xx_WM1613;
0196     } else if (machine_is_zylonite()) {
0197         pen_int = 1;
0198     }
0199 
0200     if (pen_int) {
0201         gpiod_irq = gpiod_get(wm->dev, "touch", GPIOD_IN);
0202         if (IS_ERR(gpiod_irq))
0203             pen_int = 0;
0204     }
0205 
0206     if (pen_int) {
0207         wm->pen_irq = gpiod_to_irq(gpiod_irq);
0208         irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
0209     }
0210 
0211     /* codec specific irq config */
0212     if (pen_int) {
0213         switch (wm->id) {
0214         case WM9705_ID2:
0215             break;
0216         case WM9712_ID2:
0217         case WM9713_ID2:
0218             /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
0219             wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
0220                        WM97XX_GPIO_POL_HIGH,
0221                        WM97XX_GPIO_STICKY,
0222                        WM97XX_GPIO_WAKE);
0223             wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
0224                        WM97XX_GPIO_POL_HIGH,
0225                        WM97XX_GPIO_NOTSTICKY,
0226                        WM97XX_GPIO_NOWAKE);
0227             break;
0228         default:
0229             dev_err(wm->dev,
0230                 "pen down irq not supported on this device\n");
0231             pen_int = 0;
0232             break;
0233         }
0234     }
0235 
0236     return ret;
0237 }
0238 
0239 static void wm97xx_acc_shutdown(struct wm97xx *wm)
0240 {
0241     /* codec specific deconfig */
0242     if (pen_int) {
0243         if (gpiod_irq)
0244             gpiod_put(gpiod_irq);
0245         wm->pen_irq = 0;
0246     }
0247 }
0248 
0249 static struct wm97xx_mach_ops mainstone_mach_ops = {
0250     .acc_enabled    = 1,
0251     .acc_pen_up = wm97xx_acc_pen_up,
0252     .acc_pen_down   = wm97xx_acc_pen_down,
0253     .acc_startup    = wm97xx_acc_startup,
0254     .acc_shutdown   = wm97xx_acc_shutdown,
0255     .irq_gpio   = WM97XX_GPIO_2,
0256 };
0257 
0258 static int mainstone_wm97xx_probe(struct platform_device *pdev)
0259 {
0260     struct wm97xx *wm = platform_get_drvdata(pdev);
0261 
0262     return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
0263 }
0264 
0265 static int mainstone_wm97xx_remove(struct platform_device *pdev)
0266 {
0267     struct wm97xx *wm = platform_get_drvdata(pdev);
0268 
0269     wm97xx_unregister_mach_ops(wm);
0270 
0271     return 0;
0272 }
0273 
0274 static struct platform_driver mainstone_wm97xx_driver = {
0275     .probe  = mainstone_wm97xx_probe,
0276     .remove = mainstone_wm97xx_remove,
0277     .driver = {
0278         .name   = "wm97xx-touch",
0279     },
0280 };
0281 module_platform_driver(mainstone_wm97xx_driver);
0282 
0283 /* Module information */
0284 MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
0285 MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
0286 MODULE_LICENSE("GPL");