GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / input / touchscreen / mainstone-wm97xx.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * mainstone-wm97xx.c  --  Mainstone Continuous Touch screen driver for
4  *                         Wolfson WM97xx AC97 Codecs.
5  *
6  * Copyright 2004, 2007 Wolfson Microelectronics PLC.
7  * Author: Liam Girdwood <lrg@slimlogic.co.uk>
8  * Parts Copyright : Ian Molton <spyro@f2s.com>
9  *                   Andrew Zabolotny <zap@homelink.ru>
10  *
11  * Notes:
12  *     This is a wm97xx extended touch driver to capture touch
13  *     data in a continuous manner on the Intel XScale architecture
14  *
15  *  Features:
16  *       - codecs supported:- WM9705, WM9712, WM9713
17  *       - processors supported:- Intel XScale PXA25x, PXA26x, PXA27x
18  */
19
20 #include <linux/module.h>
21 #include <linux/moduleparam.h>
22 #include <linux/kernel.h>
23 #include <linux/delay.h>
24 #include <linux/gpio/consumer.h>
25 #include <linux/irq.h>
26 #include <linux/interrupt.h>
27 #include <linux/io.h>
28 #include <linux/soc/pxa/cpu.h>
29 #include <linux/wm97xx.h>
30
31 #include <sound/pxa2xx-lib.h>
32
33 #include <asm/mach-types.h>
34
35 struct continuous {
36         u16 id;    /* codec id */
37         u8 code;   /* continuous code */
38         u8 reads;  /* number of coord reads per read cycle */
39         u32 speed; /* number of coords per second */
40 };
41
42 #define WM_READS(sp) ((sp / HZ) + 1)
43
44 static const struct continuous cinfo[] = {
45         { WM9705_ID2, 0, WM_READS(94),  94  },
46         { WM9705_ID2, 1, WM_READS(188), 188 },
47         { WM9705_ID2, 2, WM_READS(375), 375 },
48         { WM9705_ID2, 3, WM_READS(750), 750 },
49         { WM9712_ID2, 0, WM_READS(94),  94  },
50         { WM9712_ID2, 1, WM_READS(188), 188 },
51         { WM9712_ID2, 2, WM_READS(375), 375 },
52         { WM9712_ID2, 3, WM_READS(750), 750 },
53         { WM9713_ID2, 0, WM_READS(94),  94  },
54         { WM9713_ID2, 1, WM_READS(120), 120 },
55         { WM9713_ID2, 2, WM_READS(154), 154 },
56         { WM9713_ID2, 3, WM_READS(188), 188 },
57 };
58
59 /* continuous speed index */
60 static int sp_idx;
61 static struct gpio_desc *gpiod_irq;
62
63 /*
64  * Pen sampling frequency (Hz) in continuous mode.
65  */
66 static int cont_rate = 200;
67 module_param(cont_rate, int, 0);
68 MODULE_PARM_DESC(cont_rate, "Sampling rate in continuous mode (Hz)");
69
70 /*
71  * Pen down detection.
72  *
73  * This driver can either poll or use an interrupt to indicate a pen down
74  * event. If the irq request fails then it will fall back to polling mode.
75  */
76 static int pen_int;
77 module_param(pen_int, int, 0);
78 MODULE_PARM_DESC(pen_int, "Pen down detection (1 = interrupt, 0 = polling)");
79
80 /*
81  * Pressure readback.
82  *
83  * Set to 1 to read back pen down pressure
84  */
85 static int pressure;
86 module_param(pressure, int, 0);
87 MODULE_PARM_DESC(pressure, "Pressure readback (1 = pressure, 0 = no pressure)");
88
89 /*
90  * AC97 touch data slot.
91  *
92  * Touch screen readback data ac97 slot
93  */
94 static int ac97_touch_slot = 5;
95 module_param(ac97_touch_slot, int, 0);
96 MODULE_PARM_DESC(ac97_touch_slot, "Touch screen data slot AC97 number");
97
98
99 /* flush AC97 slot 5 FIFO on pxa machines */
100 static void wm97xx_acc_pen_up(struct wm97xx *wm)
101 {
102         unsigned int count;
103
104         msleep(1);
105
106         if (cpu_is_pxa27x()) {
107                 while (pxa2xx_ac97_read_misr() & (1 << 2))
108                         pxa2xx_ac97_read_modr();
109         } else if (cpu_is_pxa3xx()) {
110                 for (count = 0; count < 16; count++)
111                         pxa2xx_ac97_read_modr();
112         }
113 }
114
115 static int wm97xx_acc_pen_down(struct wm97xx *wm)
116 {
117         u16 x, y, p = 0x100 | WM97XX_ADCSEL_PRES;
118         int reads = 0;
119         static u16 last, tries;
120
121         /* When the AC97 queue has been drained we need to allow time
122          * to buffer up samples otherwise we end up spinning polling
123          * for samples.  The controller can't have a suitably low
124          * threshold set to use the notifications it gives.
125          */
126         msleep(1);
127
128         if (tries > 5) {
129                 tries = 0;
130                 return RC_PENUP;
131         }
132
133         x = pxa2xx_ac97_read_modr();
134         if (x == last) {
135                 tries++;
136                 return RC_AGAIN;
137         }
138         last = x;
139         do {
140                 if (reads)
141                         x = pxa2xx_ac97_read_modr();
142                 y = pxa2xx_ac97_read_modr();
143                 if (pressure)
144                         p = pxa2xx_ac97_read_modr();
145
146                 dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n",
147                         x, y, p);
148
149                 /* are samples valid */
150                 if ((x & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_X ||
151                     (y & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_Y ||
152                     (p & WM97XX_ADCSEL_MASK) != WM97XX_ADCSEL_PRES)
153                         goto up;
154
155                 /* coordinate is good */
156                 tries = 0;
157                 input_report_abs(wm->input_dev, ABS_X, x & 0xfff);
158                 input_report_abs(wm->input_dev, ABS_Y, y & 0xfff);
159                 input_report_abs(wm->input_dev, ABS_PRESSURE, p & 0xfff);
160                 input_report_key(wm->input_dev, BTN_TOUCH, (p != 0));
161                 input_sync(wm->input_dev);
162                 reads++;
163         } while (reads < cinfo[sp_idx].reads);
164 up:
165         return RC_PENDOWN | RC_AGAIN;
166 }
167
168 static int wm97xx_acc_startup(struct wm97xx *wm)
169 {
170         int idx = 0, ret = 0;
171
172         /* check we have a codec */
173         if (wm->ac97 == NULL)
174                 return -ENODEV;
175
176         /* Go you big red fire engine */
177         for (idx = 0; idx < ARRAY_SIZE(cinfo); idx++) {
178                 if (wm->id != cinfo[idx].id)
179                         continue;
180                 sp_idx = idx;
181                 if (cont_rate <= cinfo[idx].speed)
182                         break;
183         }
184         wm->acc_rate = cinfo[sp_idx].code;
185         wm->acc_slot = ac97_touch_slot;
186         dev_info(wm->dev,
187                  "mainstone accelerated touchscreen driver, %d samples/sec\n",
188                  cinfo[sp_idx].speed);
189
190         if (pen_int) {
191                 gpiod_irq = gpiod_get(wm->dev, "touch", GPIOD_IN);
192                 if (IS_ERR(gpiod_irq))
193                         pen_int = 0;
194         }
195
196         if (pen_int) {
197                 wm->pen_irq = gpiod_to_irq(gpiod_irq);
198                 irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
199         }
200
201         /* codec specific irq config */
202         if (pen_int) {
203                 switch (wm->id) {
204                 case WM9705_ID2:
205                         break;
206                 case WM9712_ID2:
207                 case WM9713_ID2:
208                         /* use PEN_DOWN GPIO 13 to assert IRQ on GPIO line 2 */
209                         wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
210                                            WM97XX_GPIO_POL_HIGH,
211                                            WM97XX_GPIO_STICKY,
212                                            WM97XX_GPIO_WAKE);
213                         wm97xx_config_gpio(wm, WM97XX_GPIO_2, WM97XX_GPIO_OUT,
214                                            WM97XX_GPIO_POL_HIGH,
215                                            WM97XX_GPIO_NOTSTICKY,
216                                            WM97XX_GPIO_NOWAKE);
217                         break;
218                 default:
219                         dev_err(wm->dev,
220                                 "pen down irq not supported on this device\n");
221                         pen_int = 0;
222                         break;
223                 }
224         }
225
226         return ret;
227 }
228
229 static void wm97xx_acc_shutdown(struct wm97xx *wm)
230 {
231         /* codec specific deconfig */
232         if (pen_int) {
233                 if (gpiod_irq)
234                         gpiod_put(gpiod_irq);
235                 wm->pen_irq = 0;
236         }
237 }
238
239 static struct wm97xx_mach_ops mainstone_mach_ops = {
240         .acc_enabled    = 1,
241         .acc_pen_up     = wm97xx_acc_pen_up,
242         .acc_pen_down   = wm97xx_acc_pen_down,
243         .acc_startup    = wm97xx_acc_startup,
244         .acc_shutdown   = wm97xx_acc_shutdown,
245         .irq_gpio       = WM97XX_GPIO_2,
246 };
247
248 static int mainstone_wm97xx_probe(struct platform_device *pdev)
249 {
250         struct wm97xx *wm = platform_get_drvdata(pdev);
251
252         return wm97xx_register_mach_ops(wm, &mainstone_mach_ops);
253 }
254
255 static void mainstone_wm97xx_remove(struct platform_device *pdev)
256 {
257         struct wm97xx *wm = platform_get_drvdata(pdev);
258
259         wm97xx_unregister_mach_ops(wm);
260 }
261
262 static struct platform_driver mainstone_wm97xx_driver = {
263         .probe  = mainstone_wm97xx_probe,
264         .remove_new = mainstone_wm97xx_remove,
265         .driver = {
266                 .name   = "wm97xx-touch",
267         },
268 };
269 module_platform_driver(mainstone_wm97xx_driver);
270
271 /* Module information */
272 MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
273 MODULE_DESCRIPTION("wm97xx continuous touch driver for mainstone");
274 MODULE_LICENSE("GPL");