wzero3_tp.c revision 1.8 1 1.8 chs /* $NetBSD: wzero3_tp.c,v 1.8 2012/10/27 17:17:52 chs Exp $ */
2 1.1 nonaka
3 1.7 nonaka /*-
4 1.7 nonaka * Copyright (C) 2010 NONAKA Kimihiro <nonaka (at) netbsd.org>
5 1.1 nonaka * All rights reserved.
6 1.1 nonaka *
7 1.1 nonaka * Redistribution and use in source and binary forms, with or without
8 1.1 nonaka * modification, are permitted provided that the following conditions
9 1.1 nonaka * are met:
10 1.1 nonaka * 1. Redistributions of source code must retain the above copyright
11 1.1 nonaka * notice, this list of conditions and the following disclaimer.
12 1.1 nonaka * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 nonaka * notice, this list of conditions and the following disclaimer in the
14 1.1 nonaka * documentation and/or other materials provided with the distribution.
15 1.1 nonaka *
16 1.7 nonaka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.7 nonaka * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.7 nonaka * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.7 nonaka * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.7 nonaka * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.7 nonaka * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.7 nonaka * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.7 nonaka * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.7 nonaka * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.7 nonaka * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.1 nonaka */
27 1.1 nonaka
28 1.1 nonaka #include <sys/cdefs.h>
29 1.8 chs __KERNEL_RCSID(0, "$NetBSD: wzero3_tp.c,v 1.8 2012/10/27 17:17:52 chs Exp $");
30 1.1 nonaka
31 1.1 nonaka #include <sys/types.h>
32 1.1 nonaka #include <sys/param.h>
33 1.1 nonaka #include <sys/systm.h>
34 1.1 nonaka #include <sys/device.h>
35 1.1 nonaka #include <sys/malloc.h>
36 1.1 nonaka #include <sys/kernel.h>
37 1.1 nonaka #include <sys/callout.h>
38 1.1 nonaka
39 1.1 nonaka #include <machine/bootinfo.h>
40 1.1 nonaka #include <machine/platid.h>
41 1.1 nonaka #include <machine/platid_mask.h>
42 1.1 nonaka
43 1.1 nonaka #include <dev/wscons/wsconsio.h>
44 1.1 nonaka #include <dev/wscons/wsmousevar.h>
45 1.1 nonaka #include <dev/wscons/wsdisplayvar.h>
46 1.1 nonaka
47 1.1 nonaka #include <dev/hpc/hpcfbio.h>
48 1.1 nonaka #include <dev/hpc/hpctpanelvar.h>
49 1.1 nonaka
50 1.1 nonaka #include <arm/xscale/pxa2x0cpu.h>
51 1.1 nonaka #include <arm/xscale/pxa2x0reg.h>
52 1.1 nonaka #include <arm/xscale/pxa2x0var.h>
53 1.1 nonaka #include <arm/xscale/xscalereg.h>
54 1.1 nonaka #include <arm/xscale/pxa2x0_lcd.h>
55 1.1 nonaka #include <arm/xscale/pxa2x0_gpio.h>
56 1.1 nonaka
57 1.1 nonaka #include <hpcarm/dev/wzero3_reg.h>
58 1.1 nonaka #include <hpcarm/dev/wzero3_sspvar.h>
59 1.1 nonaka
60 1.1 nonaka #ifdef WZERO3TP_DEBUG
61 1.1 nonaka #define DPRINTF(s) printf s
62 1.1 nonaka #else
63 1.1 nonaka #define DPRINTF(s)
64 1.1 nonaka #endif
65 1.1 nonaka
66 1.2 nonaka #define POLL_TIMEOUT_RATE0 ((hz * 150) / 1000)
67 1.2 nonaka #define POLL_TIMEOUT_RATE1 ((hz + 99) / 100) /* XXX every tick */
68 1.1 nonaka
69 1.1 nonaka /* Settable via sysctl. */
70 1.1 nonaka int wzero3tp_rawmode;
71 1.1 nonaka
72 1.2 nonaka static const struct wsmouse_calibcoords ws003sh_default_calib = {
73 1.2 nonaka 0, 0, 479, 639, /* minx, miny, maxx, maxy */
74 1.2 nonaka 5, /* samplelen */
75 1.2 nonaka {
76 1.2 nonaka { 2028, 2004, 240, 320 }, /* rawx, rawy, x, y */
77 1.2 nonaka { 3312, 705, 48, 64 },
78 1.2 nonaka { 3316, 3371, 48, 576 },
79 1.2 nonaka { 739, 3392, 432, 576 },
80 1.2 nonaka { 749, 673, 432, 64 },
81 1.2 nonaka }
82 1.2 nonaka };
83 1.2 nonaka
84 1.1 nonaka static const struct wsmouse_calibcoords ws007sh_default_calib = {
85 1.1 nonaka 0, 0, 479, 639, /* minx, miny, maxx, maxy */
86 1.1 nonaka 5, /* samplelen */
87 1.1 nonaka {
88 1.1 nonaka { 2050, 2024, 240, 320 }, /* rawx, rawy, x, y */
89 1.1 nonaka { 578, 3471, 48, 64 },
90 1.1 nonaka { 578, 582, 48, 576 },
91 1.1 nonaka { 3432, 582, 432, 576 },
92 1.1 nonaka { 3432, 3471, 432, 64 },
93 1.1 nonaka }
94 1.1 nonaka };
95 1.1 nonaka
96 1.4 nonaka static const struct wsmouse_calibcoords ws011sh_default_calib = {
97 1.4 nonaka 0, 0, 479, 799, /* minx, miny, maxx, maxy */
98 1.4 nonaka 5, /* samplelen */
99 1.4 nonaka {
100 1.4 nonaka { 2126, 2048, 240, 400 }, /* rawx, rawy, x, y */
101 1.4 nonaka { 527, 3464, 48, 80 },
102 1.4 nonaka { 3628, 3376, 48, 720 },
103 1.4 nonaka { 3351, 595, 432, 720 },
104 1.4 nonaka { 554, 562, 432, 80 },
105 1.4 nonaka }
106 1.4 nonaka };
107 1.4 nonaka
108 1.1 nonaka struct wzero3tp_pos {
109 1.1 nonaka int x;
110 1.1 nonaka int y;
111 1.1 nonaka int z; /* touch pressure */
112 1.1 nonaka };
113 1.1 nonaka
114 1.1 nonaka struct wzero3tp_model;
115 1.1 nonaka struct wzero3tp_softc {
116 1.1 nonaka device_t sc_dev;
117 1.1 nonaka const struct wzero3tp_model *sc_model;
118 1.1 nonaka void *sc_gh;
119 1.1 nonaka struct callout sc_tp_poll;
120 1.1 nonaka int sc_enabled;
121 1.1 nonaka int sc_buttons; /* button emulation ? */
122 1.8 chs device_t sc_wsmousedev;
123 1.1 nonaka struct wzero3tp_pos sc_oldpos;
124 1.1 nonaka struct tpcalib_softc sc_tpcalib;
125 1.1 nonaka };
126 1.1 nonaka
127 1.2 nonaka static void nulldrv_init(void);
128 1.2 nonaka static int nulldrv_readpos(struct wzero3tp_pos *);
129 1.2 nonaka static void nulldrv_suspend(void);
130 1.2 nonaka static void nulldrv_resume(void);
131 1.2 nonaka
132 1.2 nonaka static void ws007sh_wait_for_hsync(void);
133 1.2 nonaka
134 1.2 nonaka void max1233_init(void);
135 1.2 nonaka int max1233_readpos(struct wzero3tp_pos *);
136 1.2 nonaka void max1233_suspend(void);
137 1.2 nonaka void max1233_resume(void);
138 1.2 nonaka
139 1.2 nonaka void ads7846_init(void);
140 1.2 nonaka int ads7846_readpos(struct wzero3tp_pos *);
141 1.2 nonaka void ads7846_suspend(void);
142 1.2 nonaka void ads7846_resume(void);
143 1.2 nonaka extern void (*ads7846_wait_for_hsync)(void);
144 1.2 nonaka
145 1.4 nonaka void ak4184_init(void);
146 1.4 nonaka int ak4184_readpos(struct wzero3tp_pos *);
147 1.4 nonaka void ak4184_suspend(void);
148 1.4 nonaka void ak4184_resume(void);
149 1.4 nonaka
150 1.1 nonaka static int wzero3tp_match(device_t, cfdata_t, void *);
151 1.1 nonaka static void wzero3tp_attach(device_t, device_t, void *);
152 1.1 nonaka
153 1.1 nonaka CFATTACH_DECL_NEW(wzero3tp, sizeof(struct wzero3tp_softc),
154 1.1 nonaka wzero3tp_match, wzero3tp_attach, NULL, NULL);
155 1.1 nonaka
156 1.1 nonaka static int wzero3tp_enable(void *);
157 1.1 nonaka static void wzero3tp_disable(void *);
158 1.1 nonaka static bool wzero3tp_suspend(device_t dv, const pmf_qual_t *);
159 1.1 nonaka static bool wzero3tp_resume(device_t dv, const pmf_qual_t *);
160 1.1 nonaka static void wzero3tp_poll(void *);
161 1.1 nonaka static int wzero3tp_irq(void *);
162 1.1 nonaka static int wzero3tp_ioctl(void *, u_long, void *, int, struct lwp *);
163 1.1 nonaka
164 1.1 nonaka static const struct wsmouse_accessops wzero3tp_accessops = {
165 1.1 nonaka wzero3tp_enable,
166 1.1 nonaka wzero3tp_ioctl,
167 1.1 nonaka wzero3tp_disable
168 1.1 nonaka };
169 1.1 nonaka
170 1.1 nonaka struct wzero3tp_model {
171 1.1 nonaka platid_mask_t *platid;
172 1.1 nonaka const char *name;
173 1.1 nonaka int intr_pin;
174 1.1 nonaka const struct wsmouse_calibcoords *calib;
175 1.2 nonaka void (*wait_for_hsync)(void);
176 1.2 nonaka struct chip {
177 1.2 nonaka void (*init)(void);
178 1.2 nonaka int (*readpos)(struct wzero3tp_pos *);
179 1.2 nonaka void (*suspend)(void);
180 1.2 nonaka void (*resume)(void);
181 1.2 nonaka } chip;
182 1.1 nonaka } wzero3tp_table[] = {
183 1.1 nonaka /* WS003SH */
184 1.1 nonaka {
185 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS003SH,
186 1.1 nonaka "WS003SH",
187 1.2 nonaka GPIO_WS003SH_TOUCH_PANEL,
188 1.2 nonaka &ws003sh_default_calib,
189 1.1 nonaka NULL,
190 1.2 nonaka { max1233_init, max1233_readpos,
191 1.2 nonaka max1233_suspend, max1233_resume, },
192 1.1 nonaka },
193 1.1 nonaka /* WS004SH */
194 1.1 nonaka {
195 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS004SH,
196 1.1 nonaka "WS004SH",
197 1.2 nonaka GPIO_WS003SH_TOUCH_PANEL,
198 1.2 nonaka &ws003sh_default_calib,
199 1.1 nonaka NULL,
200 1.2 nonaka { max1233_init, max1233_readpos,
201 1.2 nonaka max1233_suspend, max1233_resume, },
202 1.1 nonaka },
203 1.1 nonaka /* WS007SH */
204 1.1 nonaka {
205 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS007SH,
206 1.1 nonaka "WS007SH",
207 1.1 nonaka GPIO_WS007SH_TOUCH_PANEL,
208 1.1 nonaka &ws007sh_default_calib,
209 1.2 nonaka ws007sh_wait_for_hsync,
210 1.2 nonaka { ads7846_init, ads7846_readpos,
211 1.2 nonaka ads7846_suspend, ads7846_resume, },
212 1.1 nonaka },
213 1.1 nonaka /* WS011SH */
214 1.1 nonaka {
215 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS011SH,
216 1.1 nonaka "WS011SH",
217 1.1 nonaka GPIO_WS011SH_TOUCH_PANEL,
218 1.4 nonaka &ws011sh_default_calib,
219 1.1 nonaka NULL,
220 1.4 nonaka { ak4184_init, ak4184_readpos,
221 1.4 nonaka ak4184_suspend, ak4184_resume, },
222 1.1 nonaka },
223 1.2 nonaka #if 0
224 1.1 nonaka /* WS0020H */
225 1.1 nonaka {
226 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS020SH,
227 1.1 nonaka "WS020SH",
228 1.1 nonaka -1,
229 1.1 nonaka NULL,
230 1.2 nonaka NULL,
231 1.2 nonaka { nulldrv_init, nulldrv_readpos,
232 1.2 nonaka nulldrv_suspend, nulldrv_resume, },
233 1.1 nonaka },
234 1.1 nonaka #endif
235 1.1 nonaka {
236 1.2 nonaka NULL, NULL, -1, NULL, NULL,
237 1.2 nonaka { nulldrv_init, nulldrv_readpos,
238 1.2 nonaka nulldrv_suspend, nulldrv_resume, },
239 1.1 nonaka },
240 1.1 nonaka };
241 1.1 nonaka
242 1.1 nonaka static const struct wzero3tp_model *
243 1.1 nonaka wzero3tp_lookup(void)
244 1.1 nonaka {
245 1.1 nonaka const struct wzero3tp_model *model;
246 1.1 nonaka
247 1.1 nonaka for (model = wzero3tp_table; model->platid != NULL; model++) {
248 1.1 nonaka if (platid_match(&platid, model->platid)) {
249 1.1 nonaka return model;
250 1.1 nonaka }
251 1.1 nonaka }
252 1.1 nonaka return NULL;
253 1.1 nonaka }
254 1.1 nonaka
255 1.1 nonaka static int
256 1.1 nonaka wzero3tp_match(device_t parent, cfdata_t cf, void *aux)
257 1.1 nonaka {
258 1.1 nonaka
259 1.1 nonaka if (strcmp(cf->cf_name, "wzero3tp") != 0)
260 1.1 nonaka return 0;
261 1.1 nonaka if (wzero3tp_lookup() == NULL)
262 1.1 nonaka return 0;
263 1.1 nonaka return 1;
264 1.1 nonaka }
265 1.1 nonaka
266 1.1 nonaka static void
267 1.1 nonaka wzero3tp_attach(device_t parent, device_t self, void *aux)
268 1.1 nonaka {
269 1.1 nonaka struct wzero3tp_softc *sc = device_private(self);
270 1.1 nonaka struct wsmousedev_attach_args a;
271 1.1 nonaka
272 1.1 nonaka sc->sc_dev = self;
273 1.1 nonaka
274 1.2 nonaka aprint_normal(": touch panel\n");
275 1.2 nonaka aprint_naive("\n");
276 1.2 nonaka
277 1.1 nonaka sc->sc_model = wzero3tp_lookup();
278 1.2 nonaka if (sc->sc_model == NULL) {
279 1.2 nonaka aprint_error_dev(self, "unknown model\n");
280 1.1 nonaka return;
281 1.2 nonaka }
282 1.1 nonaka
283 1.1 nonaka callout_init(&sc->sc_tp_poll, 0);
284 1.1 nonaka callout_setfunc(&sc->sc_tp_poll, wzero3tp_poll, sc);
285 1.1 nonaka
286 1.2 nonaka if (sc->sc_model->wait_for_hsync)
287 1.2 nonaka ads7846_wait_for_hsync = sc->sc_model->wait_for_hsync;
288 1.2 nonaka
289 1.2 nonaka (*sc->sc_model->chip.init)();
290 1.2 nonaka
291 1.1 nonaka a.accessops = &wzero3tp_accessops;
292 1.1 nonaka a.accesscookie = sc;
293 1.1 nonaka
294 1.1 nonaka sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
295 1.1 nonaka
296 1.1 nonaka /* Initialize calibration, set default parameters. */
297 1.1 nonaka tpcalib_init(&sc->sc_tpcalib);
298 1.2 nonaka if (sc->sc_model->calib) {
299 1.2 nonaka tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
300 1.2 nonaka __UNCONST(sc->sc_model->calib), 0, 0);
301 1.2 nonaka }
302 1.1 nonaka }
303 1.1 nonaka
304 1.1 nonaka static int
305 1.1 nonaka wzero3tp_enable(void *v)
306 1.1 nonaka {
307 1.1 nonaka struct wzero3tp_softc *sc = (struct wzero3tp_softc *)v;
308 1.1 nonaka
309 1.2 nonaka DPRINTF(("%s: %s\n", device_xname(sc->sc_dev), __func__));
310 1.1 nonaka
311 1.1 nonaka if (sc->sc_enabled) {
312 1.1 nonaka DPRINTF(("%s: already enabled\n", device_xname(sc->sc_dev)));
313 1.1 nonaka return EBUSY;
314 1.1 nonaka }
315 1.1 nonaka
316 1.1 nonaka callout_stop(&sc->sc_tp_poll);
317 1.1 nonaka
318 1.1 nonaka if (!pmf_device_register(sc->sc_dev, wzero3tp_suspend, wzero3tp_resume))
319 1.1 nonaka aprint_error_dev(sc->sc_dev,
320 1.1 nonaka "couldn't establish power handler\n");
321 1.1 nonaka
322 1.2 nonaka pxa2x0_gpio_set_function(sc->sc_model->intr_pin, GPIO_IN);
323 1.1 nonaka
324 1.2 nonaka /* XXX */
325 1.2 nonaka if (sc->sc_gh == NULL) {
326 1.2 nonaka sc->sc_gh = pxa2x0_gpio_intr_establish(
327 1.2 nonaka sc->sc_model->intr_pin, IST_EDGE_FALLING, IPL_TTY,
328 1.2 nonaka wzero3tp_irq, sc);
329 1.2 nonaka } else {
330 1.2 nonaka pxa2x0_gpio_intr_unmask(sc->sc_gh);
331 1.1 nonaka }
332 1.1 nonaka
333 1.1 nonaka /* enable interrupts */
334 1.1 nonaka sc->sc_enabled = 1;
335 1.1 nonaka sc->sc_buttons = 0;
336 1.1 nonaka
337 1.1 nonaka return 0;
338 1.1 nonaka }
339 1.1 nonaka
340 1.1 nonaka static void
341 1.1 nonaka wzero3tp_disable(void *v)
342 1.1 nonaka {
343 1.1 nonaka struct wzero3tp_softc *sc = (struct wzero3tp_softc *)v;
344 1.1 nonaka
345 1.2 nonaka DPRINTF(("%s: %s\n", device_xname(sc->sc_dev), __func__));
346 1.1 nonaka
347 1.1 nonaka callout_stop(&sc->sc_tp_poll);
348 1.1 nonaka
349 1.1 nonaka pmf_device_deregister(sc->sc_dev);
350 1.1 nonaka
351 1.2 nonaka pxa2x0_gpio_intr_mask(sc->sc_gh);
352 1.1 nonaka
353 1.1 nonaka /* disable interrupts */
354 1.1 nonaka sc->sc_enabled = 0;
355 1.1 nonaka }
356 1.1 nonaka
357 1.1 nonaka static bool
358 1.1 nonaka wzero3tp_suspend(device_t dv, const pmf_qual_t *qual)
359 1.1 nonaka {
360 1.1 nonaka struct wzero3tp_softc *sc = device_private(dv);
361 1.1 nonaka
362 1.2 nonaka DPRINTF(("%s: %s\n", device_xname(sc->sc_dev), __func__));
363 1.1 nonaka
364 1.1 nonaka sc->sc_enabled = 0;
365 1.2 nonaka pxa2x0_gpio_intr_mask(sc->sc_gh);
366 1.1 nonaka
367 1.1 nonaka callout_stop(&sc->sc_tp_poll);
368 1.1 nonaka
369 1.2 nonaka (*sc->sc_model->chip.suspend)();
370 1.1 nonaka
371 1.2 nonaka pxa2x0_gpio_set_function(sc->sc_model->intr_pin, GPIO_OUT|GPIO_SET);
372 1.1 nonaka
373 1.1 nonaka return true;
374 1.1 nonaka }
375 1.1 nonaka
376 1.1 nonaka static bool
377 1.1 nonaka wzero3tp_resume(device_t dv, const pmf_qual_t *qual)
378 1.1 nonaka {
379 1.1 nonaka struct wzero3tp_softc *sc = device_private(dv);
380 1.1 nonaka
381 1.2 nonaka DPRINTF(("%s: %s\n", device_xname(sc->sc_dev), __func__));
382 1.1 nonaka
383 1.2 nonaka pxa2x0_gpio_set_function(sc->sc_model->intr_pin, GPIO_IN);
384 1.2 nonaka pxa2x0_gpio_intr_mask(sc->sc_gh);
385 1.1 nonaka
386 1.2 nonaka (*sc->sc_model->chip.resume)();
387 1.1 nonaka
388 1.2 nonaka pxa2x0_gpio_intr_unmask(sc->sc_gh);
389 1.1 nonaka sc->sc_enabled = 1;
390 1.1 nonaka
391 1.1 nonaka return true;
392 1.1 nonaka }
393 1.1 nonaka
394 1.1 nonaka static void
395 1.1 nonaka wzero3tp_poll(void *v)
396 1.1 nonaka {
397 1.1 nonaka int s;
398 1.1 nonaka
399 1.1 nonaka s = spltty();
400 1.1 nonaka (void)wzero3tp_irq(v);
401 1.1 nonaka splx(s);
402 1.1 nonaka }
403 1.1 nonaka
404 1.1 nonaka static int
405 1.1 nonaka wzero3tp_irq(void *v)
406 1.1 nonaka {
407 1.1 nonaka struct wzero3tp_softc *sc = (struct wzero3tp_softc *)v;
408 1.1 nonaka struct wzero3tp_pos tp = { 0, 0, 0 };
409 1.1 nonaka int pindown;
410 1.1 nonaka int down;
411 1.1 nonaka int x, y;
412 1.1 nonaka int s;
413 1.1 nonaka
414 1.1 nonaka if (!sc->sc_enabled)
415 1.1 nonaka return 0;
416 1.1 nonaka
417 1.1 nonaka s = splhigh();
418 1.1 nonaka
419 1.2 nonaka pindown = pxa2x0_gpio_get_bit(sc->sc_model->intr_pin) ? 0 : 1;
420 1.1 nonaka DPRINTF(("%s: pindown = %d\n", device_xname(sc->sc_dev), pindown));
421 1.1 nonaka if (pindown) {
422 1.1 nonaka pxa2x0_gpio_intr_mask(sc->sc_gh);
423 1.1 nonaka callout_schedule(&sc->sc_tp_poll, POLL_TIMEOUT_RATE1);
424 1.1 nonaka }
425 1.1 nonaka
426 1.2 nonaka down = (*sc->sc_model->chip.readpos)(&tp);
427 1.1 nonaka DPRINTF(("%s: x = %d, y = %d, z = %d, down = %d\n",
428 1.1 nonaka device_xname(sc->sc_dev), tp.x, tp.y, tp.z, down));
429 1.1 nonaka
430 1.1 nonaka if (!pindown) {
431 1.1 nonaka pxa2x0_gpio_intr_unmask(sc->sc_gh);
432 1.1 nonaka callout_schedule(&sc->sc_tp_poll, POLL_TIMEOUT_RATE0);
433 1.1 nonaka }
434 1.2 nonaka pxa2x0_gpio_clear_intr(sc->sc_model->intr_pin);
435 1.1 nonaka
436 1.1 nonaka splx(s);
437 1.1 nonaka
438 1.1 nonaka if (down) {
439 1.1 nonaka if (!wzero3tp_rawmode) {
440 1.1 nonaka tpcalib_trans(&sc->sc_tpcalib, tp.x, tp.y, &x, &y);
441 1.1 nonaka DPRINTF(("%s: x = %d, y = %d\n",
442 1.1 nonaka device_xname(sc->sc_dev), x, y));
443 1.1 nonaka tp.x = x;
444 1.1 nonaka tp.y = y;
445 1.1 nonaka }
446 1.1 nonaka }
447 1.1 nonaka
448 1.1 nonaka if (!down) {
449 1.1 nonaka /* x/y values are not reliable when pen is up */
450 1.1 nonaka tp = sc->sc_oldpos;
451 1.1 nonaka }
452 1.1 nonaka
453 1.1 nonaka if (down || sc->sc_buttons != down) {
454 1.1 nonaka wsmouse_input(sc->sc_wsmousedev, down, tp.x, tp.y, 0, 0,
455 1.1 nonaka WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
456 1.1 nonaka sc->sc_buttons = down;
457 1.1 nonaka sc->sc_oldpos = tp;
458 1.1 nonaka }
459 1.1 nonaka
460 1.1 nonaka return 1;
461 1.1 nonaka }
462 1.1 nonaka
463 1.1 nonaka static int
464 1.1 nonaka wzero3tp_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
465 1.1 nonaka {
466 1.1 nonaka struct wzero3tp_softc *sc = (struct wzero3tp_softc *)v;
467 1.1 nonaka struct wsmouse_id *id;
468 1.1 nonaka
469 1.1 nonaka switch (cmd) {
470 1.1 nonaka case WSMOUSEIO_GTYPE:
471 1.1 nonaka *(u_int *)data = WSMOUSE_TYPE_TPANEL;
472 1.1 nonaka return 0;
473 1.1 nonaka
474 1.1 nonaka case WSMOUSEIO_GETID:
475 1.1 nonaka /*
476 1.1 nonaka * return unique ID string,
477 1.1 nonaka * "<vendor> <model> <serial number>"
478 1.1 nonaka */
479 1.1 nonaka id = (struct wsmouse_id *)data;
480 1.1 nonaka if (id->type != WSMOUSE_ID_TYPE_UIDSTR)
481 1.1 nonaka return EINVAL;
482 1.1 nonaka snprintf(id->data, WSMOUSE_ID_MAXLEN, "Sharp %s SN000000",
483 1.1 nonaka sc->sc_model->name);
484 1.1 nonaka id->length = strlen(id->data);
485 1.1 nonaka return 0;
486 1.1 nonaka
487 1.1 nonaka case WSMOUSEIO_SCALIBCOORDS:
488 1.1 nonaka case WSMOUSEIO_GCALIBCOORDS:
489 1.1 nonaka return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l);
490 1.1 nonaka }
491 1.1 nonaka
492 1.1 nonaka return EPASSTHROUGH;
493 1.1 nonaka }
494 1.2 nonaka
495 1.2 nonaka /*----------------------------------------------------------------------------
496 1.2 nonaka * null driver
497 1.2 nonaka */
498 1.2 nonaka static void
499 1.2 nonaka nulldrv_init(void)
500 1.2 nonaka {
501 1.2 nonaka
502 1.2 nonaka /* Nothing to do */
503 1.2 nonaka }
504 1.2 nonaka
505 1.2 nonaka static int
506 1.2 nonaka nulldrv_readpos(struct wzero3tp_pos *pos)
507 1.2 nonaka {
508 1.2 nonaka
509 1.2 nonaka pos->x = 0;
510 1.2 nonaka pos->y = 0;
511 1.2 nonaka pos->z = 0;
512 1.2 nonaka
513 1.2 nonaka return 0;
514 1.2 nonaka }
515 1.2 nonaka
516 1.2 nonaka static void
517 1.2 nonaka nulldrv_suspend(void)
518 1.2 nonaka {
519 1.2 nonaka
520 1.2 nonaka /* Nothing to do */
521 1.2 nonaka }
522 1.2 nonaka
523 1.2 nonaka static void
524 1.2 nonaka nulldrv_resume(void)
525 1.2 nonaka {
526 1.2 nonaka
527 1.2 nonaka /* Nothing to do */
528 1.2 nonaka }
529 1.2 nonaka
530 1.2 nonaka /*----------------------------------------------------------------------------
531 1.2 nonaka * model specific functions
532 1.2 nonaka */
533 1.2 nonaka static void
534 1.2 nonaka ws007sh_wait_for_hsync(void)
535 1.2 nonaka {
536 1.2 nonaka
537 1.2 nonaka while (pxa2x0_gpio_get_bit(GPIO_WS007SH_HSYNC) == 0)
538 1.2 nonaka continue;
539 1.2 nonaka while (pxa2x0_gpio_get_bit(GPIO_WS007SH_HSYNC) != 0)
540 1.2 nonaka continue;
541 1.2 nonaka }
542 1.2 nonaka
543 1.2 nonaka /*----------------------------------------------------------------------------
544 1.2 nonaka * MAX1233 touch screen controller for WS003SH/WS004SH
545 1.2 nonaka */
546 1.2 nonaka #define MAXCTRL_ADDR_SH 0 /* Address bit[5:0] */
547 1.2 nonaka #define MAXCTRL_PAGE_SH 6 /* Page bit (0:Data/1:Control) */
548 1.2 nonaka #define MAXCTRL_RW_SH 15 /* R/W bit (0:Write/1:Read) */
549 1.2 nonaka
550 1.2 nonaka /* VREF=2.5V, sets interrupt initiated touch-screen scans
551 1.6 tsutsui * 3.5us/sample, 16 data ave., 12 bit, settling time: 100us */
552 1.6 tsutsui #define MAX1233_ADCCTRL 0x8be3
553 1.2 nonaka
554 1.2 nonaka void
555 1.2 nonaka max1233_init(void)
556 1.2 nonaka {
557 1.2 nonaka
558 1.2 nonaka /* Enable automatic low power mode. */
559 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
560 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
561 1.2 nonaka 0x0001);
562 1.2 nonaka /* Wait for touch */
563 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
564 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
565 1.2 nonaka MAX1233_ADCCTRL);
566 1.6 tsutsui /* DAC on */
567 1.6 tsutsui (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
568 1.6 tsutsui (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (2<<MAXCTRL_ADDR_SH),
569 1.6 tsutsui 0x0000);
570 1.2 nonaka }
571 1.2 nonaka
572 1.2 nonaka void
573 1.2 nonaka max1233_suspend(void)
574 1.2 nonaka {
575 1.2 nonaka
576 1.2 nonaka /* power down. */
577 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
578 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
579 1.2 nonaka 0xc000);
580 1.2 nonaka /* DAC off */
581 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
582 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (2<<MAXCTRL_ADDR_SH),
583 1.2 nonaka 0x8000);
584 1.2 nonaka }
585 1.2 nonaka
586 1.2 nonaka void
587 1.2 nonaka max1233_resume(void)
588 1.2 nonaka {
589 1.2 nonaka
590 1.2 nonaka /* Enable automatic low power mode. */
591 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
592 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
593 1.2 nonaka 0x0001);
594 1.2 nonaka /* Wait for touch */
595 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
596 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
597 1.2 nonaka MAX1233_ADCCTRL);
598 1.2 nonaka /* DAC on */
599 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
600 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (2<<MAXCTRL_ADDR_SH),
601 1.2 nonaka 0x0000);
602 1.2 nonaka }
603 1.2 nonaka
604 1.2 nonaka int
605 1.2 nonaka max1233_readpos(struct wzero3tp_pos *pos)
606 1.2 nonaka {
607 1.6 tsutsui uint32_t x, y, z1 = 0, z2 = 0, rt;
608 1.2 nonaka uint32_t status;
609 1.2 nonaka int down;
610 1.2 nonaka
611 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
612 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
613 1.3 nonaka 0x0bf3);
614 1.6 tsutsui DELAY(300);
615 1.2 nonaka
616 1.2 nonaka while ((status = (wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
617 1.2 nonaka (1<<MAXCTRL_RW_SH)
618 1.2 nonaka | (1<<MAXCTRL_PAGE_SH)
619 1.2 nonaka | (0<<MAXCTRL_ADDR_SH), 0) & 0x4000)) != 0x4000) {
620 1.2 nonaka DPRINTF(("%s: status=%#x\n", __func__, status));
621 1.6 tsutsui DELAY(10);
622 1.2 nonaka }
623 1.2 nonaka DPRINTF(("%s: status=%#x\n", __func__, status));
624 1.2 nonaka
625 1.6 tsutsui x = wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
626 1.2 nonaka (1<<MAXCTRL_RW_SH) | (0<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),0);
627 1.6 tsutsui DPRINTF(("%s: x=%d\n", __func__, x));
628 1.6 tsutsui y = wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
629 1.2 nonaka (1<<MAXCTRL_RW_SH) | (0<<MAXCTRL_PAGE_SH) | (1<<MAXCTRL_ADDR_SH),0);
630 1.6 tsutsui DPRINTF(("%s: y=%d\n", __func__, y));
631 1.2 nonaka z1 = wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
632 1.2 nonaka (1<<MAXCTRL_RW_SH) | (0<<MAXCTRL_PAGE_SH) | (2<<MAXCTRL_ADDR_SH),0);
633 1.2 nonaka DPRINTF(("%s: z1=%d\n", __func__, z1));
634 1.2 nonaka z2 = wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
635 1.2 nonaka (1<<MAXCTRL_RW_SH) | (0<<MAXCTRL_PAGE_SH) | (3<<MAXCTRL_ADDR_SH),0);
636 1.2 nonaka DPRINTF(("%s: z2=%d\n", __func__, z2));
637 1.2 nonaka
638 1.6 tsutsui if (z1 >= 10) {
639 1.4 nonaka rt = 400 /* XXX: X plate ohms */;
640 1.6 tsutsui rt *= x;
641 1.2 nonaka rt *= (z2 / z1) - 1;
642 1.2 nonaka rt >>= 12;
643 1.2 nonaka } else
644 1.2 nonaka rt = 0;
645 1.2 nonaka DPRINTF(("%s: rt=%d\n", __func__, rt));
646 1.2 nonaka
647 1.6 tsutsui down = (rt != 0);
648 1.6 tsutsui if (down) {
649 1.6 tsutsui pos->x = x;
650 1.6 tsutsui pos->y = y;
651 1.6 tsutsui }
652 1.2 nonaka pos->z = down;
653 1.2 nonaka
654 1.2 nonaka return down;
655 1.2 nonaka }
656 1.2 nonaka
657 1.2 nonaka /*----------------------------------------------------------------------------
658 1.2 nonaka * ADS7846/TSC2046 touch screen controller for WS007SH
659 1.2 nonaka */
660 1.4 nonaka #define ADSCTRL_PD0_SH 0 /* PD0 bit */
661 1.4 nonaka #define ADSCTRL_PD1_SH 1 /* PD1 bit */
662 1.4 nonaka #define ADSCTRL_DFR_SH 2 /* SER/DFR bit */
663 1.4 nonaka #define ADSCTRL_MOD_SH 3 /* Mode bit */
664 1.4 nonaka #define ADSCTRL_ADR_SH 4 /* Address setting */
665 1.4 nonaka #define ADSCTRL_STS_SH 7 /* Start bit */
666 1.2 nonaka
667 1.2 nonaka static uint32_t ads7846_sync(int, int, uint32_t);
668 1.2 nonaka
669 1.2 nonaka void
670 1.2 nonaka ads7846_init(void)
671 1.2 nonaka {
672 1.2 nonaka
673 1.2 nonaka /* Enable automatic low power mode. */
674 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846,
675 1.2 nonaka (4<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH), 0);
676 1.2 nonaka }
677 1.2 nonaka
678 1.2 nonaka void
679 1.2 nonaka ads7846_suspend(void)
680 1.2 nonaka {
681 1.2 nonaka
682 1.2 nonaka /* Turn off reference voltage but leave ADC on. */
683 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846,
684 1.2 nonaka (1<<ADSCTRL_PD1_SH) | (1<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH), 0);
685 1.2 nonaka }
686 1.2 nonaka
687 1.2 nonaka void
688 1.2 nonaka ads7846_resume(void)
689 1.2 nonaka {
690 1.2 nonaka
691 1.2 nonaka /* Enable automatic low power mode. */
692 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846,
693 1.2 nonaka (4<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH), 0);
694 1.2 nonaka }
695 1.2 nonaka
696 1.2 nonaka int
697 1.2 nonaka ads7846_readpos(struct wzero3tp_pos *pos)
698 1.2 nonaka {
699 1.2 nonaka int cmd, cmd0;
700 1.2 nonaka int z0, z1;
701 1.2 nonaka int down;
702 1.2 nonaka
703 1.2 nonaka cmd0 = (1<<ADSCTRL_STS_SH) | (1<<ADSCTRL_PD0_SH) | (1<<ADSCTRL_PD1_SH);
704 1.2 nonaka
705 1.2 nonaka /* check that pen is down */
706 1.2 nonaka cmd = cmd0 | (3<<ADSCTRL_ADR_SH);
707 1.2 nonaka z0 = wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846, cmd, 0);
708 1.2 nonaka DPRINTF(("%s: first z0 = %d\n", __func__, z0));
709 1.2 nonaka
710 1.2 nonaka down = (z0 >= 10);
711 1.2 nonaka if (!down)
712 1.2 nonaka goto out;
713 1.2 nonaka
714 1.2 nonaka /* Y (discard) */
715 1.2 nonaka cmd = cmd0 | (1<<ADSCTRL_ADR_SH);
716 1.2 nonaka (void)ads7846_sync(0, 1, cmd);
717 1.2 nonaka
718 1.2 nonaka /* Y */
719 1.2 nonaka cmd = cmd0 | (1<<ADSCTRL_ADR_SH);
720 1.2 nonaka (void)ads7846_sync(1, 1, cmd);
721 1.2 nonaka
722 1.2 nonaka /* X */
723 1.2 nonaka cmd = cmd0 | (5<<ADSCTRL_ADR_SH);
724 1.2 nonaka pos->y = ads7846_sync(1, 1, cmd);
725 1.2 nonaka DPRINTF(("%s: y = %d\n", __func__, pos->y));
726 1.2 nonaka
727 1.2 nonaka /* Z0 */
728 1.2 nonaka cmd = cmd0 | (3<<ADSCTRL_ADR_SH);
729 1.2 nonaka pos->x = ads7846_sync(1, 1, cmd);
730 1.2 nonaka DPRINTF(("%s: x = %d\n", __func__, pos->x));
731 1.2 nonaka
732 1.2 nonaka /* Z1 */
733 1.2 nonaka cmd = cmd0 | (4<<ADSCTRL_ADR_SH);
734 1.2 nonaka z0 = ads7846_sync(1, 1, cmd);
735 1.2 nonaka z1 = ads7846_sync(1, 0, cmd);
736 1.2 nonaka DPRINTF(("%s: z0 = %d, z1 = %d\n", __func__, z0, z1));
737 1.2 nonaka
738 1.2 nonaka /* check that pen is still down */
739 1.2 nonaka if (z0 == 0 || (pos->x * (z1 - z0) / z0) >= 15000)
740 1.2 nonaka down = 0;
741 1.2 nonaka pos->z = down;
742 1.2 nonaka
743 1.2 nonaka out:
744 1.2 nonaka /* Enable automatic low power mode. */
745 1.2 nonaka cmd = (1<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH);
746 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846, cmd, 0);
747 1.2 nonaka
748 1.2 nonaka return down;
749 1.2 nonaka }
750 1.2 nonaka
751 1.2 nonaka void (*ads7846_wait_for_hsync)(void);
752 1.2 nonaka
753 1.2 nonaka /*
754 1.2 nonaka * Communicate synchronously with the ADS784x touch screen controller.
755 1.2 nonaka */
756 1.2 nonaka static uint32_t
757 1.2 nonaka ads7846_sync(int dorecv, int dosend, uint32_t cmd)
758 1.2 nonaka {
759 1.2 nonaka uint32_t rv = 0;
760 1.2 nonaka
761 1.2 nonaka if (ads7846_wait_for_hsync)
762 1.2 nonaka (*ads7846_wait_for_hsync)();
763 1.2 nonaka
764 1.2 nonaka if (dorecv)
765 1.2 nonaka rv = wzero3ssp_ic_stop(WZERO3_SSP_IC_ADS7846);
766 1.2 nonaka
767 1.2 nonaka if (dosend) {
768 1.2 nonaka /* send dummy command; discard SSDR */
769 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846, cmd, 0);
770 1.2 nonaka
771 1.2 nonaka /* wait for refresh */
772 1.2 nonaka if (ads7846_wait_for_hsync)
773 1.2 nonaka (*ads7846_wait_for_hsync)();
774 1.2 nonaka
775 1.2 nonaka /* send the actual command; keep ADS784x enabled */
776 1.2 nonaka wzero3ssp_ic_start(WZERO3_SSP_IC_ADS7846, cmd);
777 1.2 nonaka }
778 1.2 nonaka
779 1.2 nonaka return rv;
780 1.2 nonaka }
781 1.4 nonaka
782 1.4 nonaka /*----------------------------------------------------------------------------
783 1.4 nonaka * AK4184 touch screen controller for WS011SH
784 1.4 nonaka */
785 1.4 nonaka #define AKMCTRL_PD_SH 12 /* Power down bit */
786 1.4 nonaka #define AKMCTRL_ADR_SH 13 /* Address setting bits */
787 1.4 nonaka #define AKMCTRL_STS_SH 15 /* Start bit */
788 1.4 nonaka
789 1.4 nonaka static uint32_t ak4184_sync(int, int, uint32_t);
790 1.4 nonaka
791 1.4 nonaka void
792 1.4 nonaka ak4184_init(void)
793 1.4 nonaka {
794 1.4 nonaka
795 1.4 nonaka /* Enable automatic low power mode. */
796 1.5 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_TP,
797 1.4 nonaka (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (0<<AKMCTRL_PD_SH), 0);
798 1.4 nonaka }
799 1.4 nonaka
800 1.4 nonaka int
801 1.4 nonaka ak4184_readpos(struct wzero3tp_pos *pos)
802 1.4 nonaka {
803 1.4 nonaka u_int rt;
804 1.4 nonaka int z1, z2;
805 1.4 nonaka
806 1.4 nonaka /* X (discard) */
807 1.4 nonaka (void)ak4184_sync(0, 1,
808 1.4 nonaka (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH));
809 1.4 nonaka
810 1.4 nonaka /* X */
811 1.4 nonaka (void)ak4184_sync(1, 1,
812 1.4 nonaka (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH));
813 1.4 nonaka
814 1.4 nonaka /* Y */
815 1.4 nonaka pos->x = ak4184_sync(1, 1,
816 1.4 nonaka (1<<AKMCTRL_STS_SH) | (1<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH));
817 1.4 nonaka DPRINTF(("%s: x=%d\n", __func__, pos->x));
818 1.4 nonaka pos->y = ak4184_sync(1, 1,
819 1.4 nonaka (1<<AKMCTRL_STS_SH) | (2<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH));
820 1.4 nonaka DPRINTF(("%s: y=%d\n", __func__, pos->y));
821 1.4 nonaka z1 = ak4184_sync(1, 1,
822 1.4 nonaka (1<<AKMCTRL_STS_SH) | (3<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH));
823 1.4 nonaka DPRINTF(("%s: z1=%d\n", __func__, z1));
824 1.4 nonaka z2 = ak4184_sync(1, 0,
825 1.4 nonaka (1<<AKMCTRL_STS_SH) | (3<<AKMCTRL_ADR_SH) | (1<<AKMCTRL_PD_SH));
826 1.4 nonaka DPRINTF(("%s: z2=%d\n", __func__, z2));
827 1.4 nonaka
828 1.4 nonaka if (z1 >= 10) {
829 1.4 nonaka rt = 400 /* XXX: X plate ohms */;
830 1.4 nonaka rt *= pos->x;
831 1.4 nonaka rt *= (z2 / z1) - 1;
832 1.4 nonaka rt >>= 12;
833 1.4 nonaka } else
834 1.4 nonaka rt = 0;
835 1.4 nonaka DPRINTF(("%s: rt=%d\n", __func__, rt));
836 1.4 nonaka
837 1.4 nonaka /* check that pen is still down */
838 1.4 nonaka if (z1 == 0 || rt == 0)
839 1.4 nonaka pos->z = 0;
840 1.4 nonaka else
841 1.4 nonaka pos->z = 1;
842 1.4 nonaka
843 1.4 nonaka /* Enable automatic low power mode. */
844 1.5 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_TP,
845 1.4 nonaka (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (0<<AKMCTRL_PD_SH), 0);
846 1.4 nonaka
847 1.4 nonaka return pos->z;
848 1.4 nonaka }
849 1.4 nonaka
850 1.4 nonaka void
851 1.4 nonaka ak4184_suspend(void)
852 1.4 nonaka {
853 1.4 nonaka
854 1.4 nonaka /* Nothing to do */
855 1.4 nonaka }
856 1.4 nonaka
857 1.4 nonaka void
858 1.4 nonaka ak4184_resume(void)
859 1.4 nonaka {
860 1.4 nonaka
861 1.4 nonaka /* Enable automatic low power mode. */
862 1.5 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_TP,
863 1.4 nonaka (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (0<<AKMCTRL_PD_SH), 0);
864 1.4 nonaka }
865 1.4 nonaka
866 1.4 nonaka static uint32_t
867 1.4 nonaka ak4184_sync(int dorecv, int dosend, uint32_t cmd)
868 1.4 nonaka {
869 1.4 nonaka uint32_t rv = 0;
870 1.4 nonaka
871 1.4 nonaka if (dorecv)
872 1.5 nonaka rv = wzero3ssp_ic_stop(WZERO3_SSP_IC_AK4184_TP);
873 1.4 nonaka
874 1.4 nonaka if (dosend) {
875 1.4 nonaka /* send dummy command; discard SSDR */
876 1.5 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_TP, cmd, 0);
877 1.4 nonaka
878 1.4 nonaka /* send the actual command; keep AK4184 enabled */
879 1.5 nonaka wzero3ssp_ic_start(WZERO3_SSP_IC_AK4184_TP, cmd);
880 1.4 nonaka }
881 1.4 nonaka
882 1.4 nonaka return rv;
883 1.4 nonaka }
884