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