wzero3_tp.c revision 1.2 1 1.2 nonaka /* $NetBSD: wzero3_tp.c,v 1.2 2010/05/13 21:01:59 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.2 nonaka __KERNEL_RCSID(0, "$NetBSD: wzero3_tp.c,v 1.2 2010/05/13 21:01:59 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.1 nonaka struct wzero3tp_pos {
98 1.1 nonaka int x;
99 1.1 nonaka int y;
100 1.1 nonaka int z; /* touch pressure */
101 1.1 nonaka };
102 1.1 nonaka
103 1.1 nonaka struct wzero3tp_model;
104 1.1 nonaka struct wzero3tp_softc {
105 1.1 nonaka device_t sc_dev;
106 1.1 nonaka const struct wzero3tp_model *sc_model;
107 1.1 nonaka void *sc_gh;
108 1.1 nonaka struct callout sc_tp_poll;
109 1.1 nonaka int sc_enabled;
110 1.1 nonaka int sc_buttons; /* button emulation ? */
111 1.1 nonaka struct device *sc_wsmousedev;
112 1.1 nonaka struct wzero3tp_pos sc_oldpos;
113 1.1 nonaka struct tpcalib_softc sc_tpcalib;
114 1.1 nonaka };
115 1.1 nonaka
116 1.2 nonaka static void nulldrv_init(void);
117 1.2 nonaka static int nulldrv_readpos(struct wzero3tp_pos *);
118 1.2 nonaka static void nulldrv_suspend(void);
119 1.2 nonaka static void nulldrv_resume(void);
120 1.2 nonaka
121 1.2 nonaka static void ws007sh_wait_for_hsync(void);
122 1.2 nonaka
123 1.2 nonaka void max1233_init(void);
124 1.2 nonaka int max1233_readpos(struct wzero3tp_pos *);
125 1.2 nonaka void max1233_suspend(void);
126 1.2 nonaka void max1233_resume(void);
127 1.2 nonaka
128 1.2 nonaka void ads7846_init(void);
129 1.2 nonaka int ads7846_readpos(struct wzero3tp_pos *);
130 1.2 nonaka void ads7846_suspend(void);
131 1.2 nonaka void ads7846_resume(void);
132 1.2 nonaka extern void (*ads7846_wait_for_hsync)(void);
133 1.2 nonaka
134 1.1 nonaka static int wzero3tp_match(device_t, cfdata_t, void *);
135 1.1 nonaka static void wzero3tp_attach(device_t, device_t, void *);
136 1.1 nonaka
137 1.1 nonaka CFATTACH_DECL_NEW(wzero3tp, sizeof(struct wzero3tp_softc),
138 1.1 nonaka wzero3tp_match, wzero3tp_attach, NULL, NULL);
139 1.1 nonaka
140 1.1 nonaka static int wzero3tp_enable(void *);
141 1.1 nonaka static void wzero3tp_disable(void *);
142 1.1 nonaka static bool wzero3tp_suspend(device_t dv, const pmf_qual_t *);
143 1.1 nonaka static bool wzero3tp_resume(device_t dv, const pmf_qual_t *);
144 1.1 nonaka static void wzero3tp_poll(void *);
145 1.1 nonaka static int wzero3tp_irq(void *);
146 1.1 nonaka static int wzero3tp_ioctl(void *, u_long, void *, int, struct lwp *);
147 1.1 nonaka
148 1.1 nonaka static const struct wsmouse_accessops wzero3tp_accessops = {
149 1.1 nonaka wzero3tp_enable,
150 1.1 nonaka wzero3tp_ioctl,
151 1.1 nonaka wzero3tp_disable
152 1.1 nonaka };
153 1.1 nonaka
154 1.1 nonaka struct wzero3tp_model {
155 1.1 nonaka platid_mask_t *platid;
156 1.1 nonaka const char *name;
157 1.1 nonaka int intr_pin;
158 1.1 nonaka const struct wsmouse_calibcoords *calib;
159 1.2 nonaka void (*wait_for_hsync)(void);
160 1.2 nonaka struct chip {
161 1.2 nonaka void (*init)(void);
162 1.2 nonaka int (*readpos)(struct wzero3tp_pos *);
163 1.2 nonaka void (*suspend)(void);
164 1.2 nonaka void (*resume)(void);
165 1.2 nonaka } chip;
166 1.1 nonaka } wzero3tp_table[] = {
167 1.1 nonaka /* WS003SH */
168 1.1 nonaka {
169 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS003SH,
170 1.1 nonaka "WS003SH",
171 1.2 nonaka GPIO_WS003SH_TOUCH_PANEL,
172 1.2 nonaka &ws003sh_default_calib,
173 1.1 nonaka NULL,
174 1.2 nonaka { max1233_init, max1233_readpos,
175 1.2 nonaka max1233_suspend, max1233_resume, },
176 1.1 nonaka },
177 1.1 nonaka /* WS004SH */
178 1.1 nonaka {
179 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS004SH,
180 1.1 nonaka "WS004SH",
181 1.2 nonaka GPIO_WS003SH_TOUCH_PANEL,
182 1.2 nonaka &ws003sh_default_calib,
183 1.1 nonaka NULL,
184 1.2 nonaka { max1233_init, max1233_readpos,
185 1.2 nonaka max1233_suspend, max1233_resume, },
186 1.1 nonaka },
187 1.1 nonaka /* WS007SH */
188 1.1 nonaka {
189 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS007SH,
190 1.1 nonaka "WS007SH",
191 1.1 nonaka GPIO_WS007SH_TOUCH_PANEL,
192 1.1 nonaka &ws007sh_default_calib,
193 1.2 nonaka ws007sh_wait_for_hsync,
194 1.2 nonaka { ads7846_init, ads7846_readpos,
195 1.2 nonaka ads7846_suspend, ads7846_resume, },
196 1.1 nonaka },
197 1.1 nonaka /* WS011SH */
198 1.1 nonaka {
199 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS011SH,
200 1.1 nonaka "WS011SH",
201 1.1 nonaka GPIO_WS011SH_TOUCH_PANEL,
202 1.1 nonaka NULL,
203 1.2 nonaka NULL,
204 1.2 nonaka { nulldrv_init, nulldrv_readpos,
205 1.2 nonaka nulldrv_suspend, nulldrv_resume, },
206 1.1 nonaka },
207 1.2 nonaka #if 0
208 1.1 nonaka /* WS0020H */
209 1.1 nonaka {
210 1.1 nonaka &platid_mask_MACH_SHARP_WZERO3_WS020SH,
211 1.1 nonaka "WS020SH",
212 1.1 nonaka -1,
213 1.1 nonaka NULL,
214 1.2 nonaka NULL,
215 1.2 nonaka { nulldrv_init, nulldrv_readpos,
216 1.2 nonaka nulldrv_suspend, nulldrv_resume, },
217 1.1 nonaka },
218 1.1 nonaka #endif
219 1.1 nonaka {
220 1.2 nonaka NULL, NULL, -1, NULL, NULL,
221 1.2 nonaka { nulldrv_init, nulldrv_readpos,
222 1.2 nonaka nulldrv_suspend, nulldrv_resume, },
223 1.1 nonaka },
224 1.1 nonaka };
225 1.1 nonaka
226 1.1 nonaka static const struct wzero3tp_model *
227 1.1 nonaka wzero3tp_lookup(void)
228 1.1 nonaka {
229 1.1 nonaka const struct wzero3tp_model *model;
230 1.1 nonaka
231 1.1 nonaka for (model = wzero3tp_table; model->platid != NULL; model++) {
232 1.1 nonaka if (platid_match(&platid, model->platid)) {
233 1.1 nonaka return model;
234 1.1 nonaka }
235 1.1 nonaka }
236 1.1 nonaka return NULL;
237 1.1 nonaka }
238 1.1 nonaka
239 1.1 nonaka static int
240 1.1 nonaka wzero3tp_match(device_t parent, cfdata_t cf, void *aux)
241 1.1 nonaka {
242 1.1 nonaka
243 1.1 nonaka if (strcmp(cf->cf_name, "wzero3tp") != 0)
244 1.1 nonaka return 0;
245 1.1 nonaka if (wzero3tp_lookup() == NULL)
246 1.1 nonaka return 0;
247 1.1 nonaka return 1;
248 1.1 nonaka }
249 1.1 nonaka
250 1.1 nonaka static void
251 1.1 nonaka wzero3tp_attach(device_t parent, device_t self, void *aux)
252 1.1 nonaka {
253 1.1 nonaka struct wzero3tp_softc *sc = device_private(self);
254 1.1 nonaka struct wsmousedev_attach_args a;
255 1.1 nonaka
256 1.1 nonaka sc->sc_dev = self;
257 1.1 nonaka
258 1.2 nonaka aprint_normal(": touch panel\n");
259 1.2 nonaka aprint_naive("\n");
260 1.2 nonaka
261 1.1 nonaka sc->sc_model = wzero3tp_lookup();
262 1.2 nonaka if (sc->sc_model == NULL) {
263 1.2 nonaka aprint_error_dev(self, "unknown model\n");
264 1.1 nonaka return;
265 1.2 nonaka }
266 1.1 nonaka
267 1.1 nonaka callout_init(&sc->sc_tp_poll, 0);
268 1.1 nonaka callout_setfunc(&sc->sc_tp_poll, wzero3tp_poll, sc);
269 1.1 nonaka
270 1.2 nonaka if (sc->sc_model->wait_for_hsync)
271 1.2 nonaka ads7846_wait_for_hsync = sc->sc_model->wait_for_hsync;
272 1.2 nonaka
273 1.2 nonaka (*sc->sc_model->chip.init)();
274 1.2 nonaka
275 1.1 nonaka a.accessops = &wzero3tp_accessops;
276 1.1 nonaka a.accesscookie = sc;
277 1.1 nonaka
278 1.1 nonaka sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
279 1.1 nonaka
280 1.1 nonaka /* Initialize calibration, set default parameters. */
281 1.1 nonaka tpcalib_init(&sc->sc_tpcalib);
282 1.2 nonaka if (sc->sc_model->calib) {
283 1.2 nonaka tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
284 1.2 nonaka __UNCONST(sc->sc_model->calib), 0, 0);
285 1.2 nonaka }
286 1.1 nonaka }
287 1.1 nonaka
288 1.1 nonaka static int
289 1.1 nonaka wzero3tp_enable(void *v)
290 1.1 nonaka {
291 1.1 nonaka struct wzero3tp_softc *sc = (struct wzero3tp_softc *)v;
292 1.1 nonaka
293 1.2 nonaka DPRINTF(("%s: %s\n", device_xname(sc->sc_dev), __func__));
294 1.1 nonaka
295 1.1 nonaka if (sc->sc_enabled) {
296 1.1 nonaka DPRINTF(("%s: already enabled\n", device_xname(sc->sc_dev)));
297 1.1 nonaka return EBUSY;
298 1.1 nonaka }
299 1.1 nonaka
300 1.1 nonaka callout_stop(&sc->sc_tp_poll);
301 1.1 nonaka
302 1.1 nonaka if (!pmf_device_register(sc->sc_dev, wzero3tp_suspend, wzero3tp_resume))
303 1.1 nonaka aprint_error_dev(sc->sc_dev,
304 1.1 nonaka "couldn't establish power handler\n");
305 1.1 nonaka
306 1.2 nonaka pxa2x0_gpio_set_function(sc->sc_model->intr_pin, GPIO_IN);
307 1.1 nonaka
308 1.2 nonaka /* XXX */
309 1.2 nonaka if (sc->sc_gh == NULL) {
310 1.2 nonaka sc->sc_gh = pxa2x0_gpio_intr_establish(
311 1.2 nonaka sc->sc_model->intr_pin, IST_EDGE_FALLING, IPL_TTY,
312 1.2 nonaka wzero3tp_irq, sc);
313 1.2 nonaka } else {
314 1.2 nonaka pxa2x0_gpio_intr_unmask(sc->sc_gh);
315 1.1 nonaka }
316 1.1 nonaka
317 1.1 nonaka /* enable interrupts */
318 1.1 nonaka sc->sc_enabled = 1;
319 1.1 nonaka sc->sc_buttons = 0;
320 1.1 nonaka
321 1.1 nonaka return 0;
322 1.1 nonaka }
323 1.1 nonaka
324 1.1 nonaka static void
325 1.1 nonaka wzero3tp_disable(void *v)
326 1.1 nonaka {
327 1.1 nonaka struct wzero3tp_softc *sc = (struct wzero3tp_softc *)v;
328 1.1 nonaka
329 1.2 nonaka DPRINTF(("%s: %s\n", device_xname(sc->sc_dev), __func__));
330 1.1 nonaka
331 1.1 nonaka callout_stop(&sc->sc_tp_poll);
332 1.1 nonaka
333 1.1 nonaka pmf_device_deregister(sc->sc_dev);
334 1.1 nonaka
335 1.2 nonaka pxa2x0_gpio_intr_mask(sc->sc_gh);
336 1.1 nonaka
337 1.1 nonaka /* disable interrupts */
338 1.1 nonaka sc->sc_enabled = 0;
339 1.1 nonaka }
340 1.1 nonaka
341 1.1 nonaka static bool
342 1.1 nonaka wzero3tp_suspend(device_t dv, const pmf_qual_t *qual)
343 1.1 nonaka {
344 1.1 nonaka struct wzero3tp_softc *sc = device_private(dv);
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 sc->sc_enabled = 0;
349 1.2 nonaka pxa2x0_gpio_intr_mask(sc->sc_gh);
350 1.1 nonaka
351 1.1 nonaka callout_stop(&sc->sc_tp_poll);
352 1.1 nonaka
353 1.2 nonaka (*sc->sc_model->chip.suspend)();
354 1.1 nonaka
355 1.2 nonaka pxa2x0_gpio_set_function(sc->sc_model->intr_pin, GPIO_OUT|GPIO_SET);
356 1.1 nonaka
357 1.1 nonaka return true;
358 1.1 nonaka }
359 1.1 nonaka
360 1.1 nonaka static bool
361 1.1 nonaka wzero3tp_resume(device_t dv, const pmf_qual_t *qual)
362 1.1 nonaka {
363 1.1 nonaka struct wzero3tp_softc *sc = device_private(dv);
364 1.1 nonaka
365 1.2 nonaka DPRINTF(("%s: %s\n", device_xname(sc->sc_dev), __func__));
366 1.1 nonaka
367 1.2 nonaka pxa2x0_gpio_set_function(sc->sc_model->intr_pin, GPIO_IN);
368 1.2 nonaka pxa2x0_gpio_intr_mask(sc->sc_gh);
369 1.1 nonaka
370 1.2 nonaka (*sc->sc_model->chip.resume)();
371 1.1 nonaka
372 1.2 nonaka pxa2x0_gpio_intr_unmask(sc->sc_gh);
373 1.1 nonaka sc->sc_enabled = 1;
374 1.1 nonaka
375 1.1 nonaka return true;
376 1.1 nonaka }
377 1.1 nonaka
378 1.1 nonaka static void
379 1.1 nonaka wzero3tp_poll(void *v)
380 1.1 nonaka {
381 1.1 nonaka int s;
382 1.1 nonaka
383 1.1 nonaka s = spltty();
384 1.1 nonaka (void)wzero3tp_irq(v);
385 1.1 nonaka splx(s);
386 1.1 nonaka }
387 1.1 nonaka
388 1.1 nonaka static int
389 1.1 nonaka wzero3tp_irq(void *v)
390 1.1 nonaka {
391 1.1 nonaka struct wzero3tp_softc *sc = (struct wzero3tp_softc *)v;
392 1.1 nonaka struct wzero3tp_pos tp = { 0, 0, 0 };
393 1.1 nonaka int pindown;
394 1.1 nonaka int down;
395 1.1 nonaka int x, y;
396 1.1 nonaka int s;
397 1.1 nonaka
398 1.1 nonaka if (!sc->sc_enabled)
399 1.1 nonaka return 0;
400 1.1 nonaka
401 1.1 nonaka s = splhigh();
402 1.1 nonaka
403 1.2 nonaka pindown = pxa2x0_gpio_get_bit(sc->sc_model->intr_pin) ? 0 : 1;
404 1.1 nonaka DPRINTF(("%s: pindown = %d\n", device_xname(sc->sc_dev), pindown));
405 1.1 nonaka if (pindown) {
406 1.1 nonaka pxa2x0_gpio_intr_mask(sc->sc_gh);
407 1.1 nonaka callout_schedule(&sc->sc_tp_poll, POLL_TIMEOUT_RATE1);
408 1.1 nonaka }
409 1.1 nonaka
410 1.2 nonaka down = (*sc->sc_model->chip.readpos)(&tp);
411 1.1 nonaka DPRINTF(("%s: x = %d, y = %d, z = %d, down = %d\n",
412 1.1 nonaka device_xname(sc->sc_dev), tp.x, tp.y, tp.z, down));
413 1.1 nonaka
414 1.1 nonaka if (!pindown) {
415 1.1 nonaka pxa2x0_gpio_intr_unmask(sc->sc_gh);
416 1.1 nonaka callout_schedule(&sc->sc_tp_poll, POLL_TIMEOUT_RATE0);
417 1.1 nonaka }
418 1.2 nonaka pxa2x0_gpio_clear_intr(sc->sc_model->intr_pin);
419 1.1 nonaka
420 1.1 nonaka splx(s);
421 1.1 nonaka
422 1.1 nonaka if (down) {
423 1.1 nonaka if (!wzero3tp_rawmode) {
424 1.1 nonaka tpcalib_trans(&sc->sc_tpcalib, tp.x, tp.y, &x, &y);
425 1.1 nonaka DPRINTF(("%s: x = %d, y = %d\n",
426 1.1 nonaka device_xname(sc->sc_dev), x, y));
427 1.1 nonaka tp.x = x;
428 1.1 nonaka tp.y = y;
429 1.1 nonaka }
430 1.1 nonaka }
431 1.1 nonaka
432 1.1 nonaka if (!down) {
433 1.1 nonaka /* x/y values are not reliable when pen is up */
434 1.1 nonaka tp = sc->sc_oldpos;
435 1.1 nonaka }
436 1.1 nonaka
437 1.1 nonaka if (down || sc->sc_buttons != down) {
438 1.1 nonaka wsmouse_input(sc->sc_wsmousedev, down, tp.x, tp.y, 0, 0,
439 1.1 nonaka WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
440 1.1 nonaka sc->sc_buttons = down;
441 1.1 nonaka sc->sc_oldpos = tp;
442 1.1 nonaka }
443 1.1 nonaka
444 1.1 nonaka return 1;
445 1.1 nonaka }
446 1.1 nonaka
447 1.1 nonaka static int
448 1.1 nonaka wzero3tp_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
449 1.1 nonaka {
450 1.1 nonaka struct wzero3tp_softc *sc = (struct wzero3tp_softc *)v;
451 1.1 nonaka struct wsmouse_id *id;
452 1.1 nonaka
453 1.1 nonaka switch (cmd) {
454 1.1 nonaka case WSMOUSEIO_GTYPE:
455 1.1 nonaka *(u_int *)data = WSMOUSE_TYPE_TPANEL;
456 1.1 nonaka return 0;
457 1.1 nonaka
458 1.1 nonaka case WSMOUSEIO_GETID:
459 1.1 nonaka /*
460 1.1 nonaka * return unique ID string,
461 1.1 nonaka * "<vendor> <model> <serial number>"
462 1.1 nonaka */
463 1.1 nonaka id = (struct wsmouse_id *)data;
464 1.1 nonaka if (id->type != WSMOUSE_ID_TYPE_UIDSTR)
465 1.1 nonaka return EINVAL;
466 1.1 nonaka snprintf(id->data, WSMOUSE_ID_MAXLEN, "Sharp %s SN000000",
467 1.1 nonaka sc->sc_model->name);
468 1.1 nonaka id->length = strlen(id->data);
469 1.1 nonaka return 0;
470 1.1 nonaka
471 1.1 nonaka case WSMOUSEIO_SCALIBCOORDS:
472 1.1 nonaka case WSMOUSEIO_GCALIBCOORDS:
473 1.1 nonaka return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l);
474 1.1 nonaka }
475 1.1 nonaka
476 1.1 nonaka return EPASSTHROUGH;
477 1.1 nonaka }
478 1.2 nonaka
479 1.2 nonaka /*----------------------------------------------------------------------------
480 1.2 nonaka * null driver
481 1.2 nonaka */
482 1.2 nonaka static void
483 1.2 nonaka nulldrv_init(void)
484 1.2 nonaka {
485 1.2 nonaka
486 1.2 nonaka /* Nothing to do */
487 1.2 nonaka }
488 1.2 nonaka
489 1.2 nonaka static int
490 1.2 nonaka nulldrv_readpos(struct wzero3tp_pos *pos)
491 1.2 nonaka {
492 1.2 nonaka
493 1.2 nonaka pos->x = 0;
494 1.2 nonaka pos->y = 0;
495 1.2 nonaka pos->z = 0;
496 1.2 nonaka
497 1.2 nonaka return 0;
498 1.2 nonaka }
499 1.2 nonaka
500 1.2 nonaka static void
501 1.2 nonaka nulldrv_suspend(void)
502 1.2 nonaka {
503 1.2 nonaka
504 1.2 nonaka /* Nothing to do */
505 1.2 nonaka }
506 1.2 nonaka
507 1.2 nonaka static void
508 1.2 nonaka nulldrv_resume(void)
509 1.2 nonaka {
510 1.2 nonaka
511 1.2 nonaka /* Nothing to do */
512 1.2 nonaka }
513 1.2 nonaka
514 1.2 nonaka /*----------------------------------------------------------------------------
515 1.2 nonaka * model specific functions
516 1.2 nonaka */
517 1.2 nonaka static void
518 1.2 nonaka ws007sh_wait_for_hsync(void)
519 1.2 nonaka {
520 1.2 nonaka
521 1.2 nonaka while (pxa2x0_gpio_get_bit(GPIO_WS007SH_HSYNC) == 0)
522 1.2 nonaka continue;
523 1.2 nonaka while (pxa2x0_gpio_get_bit(GPIO_WS007SH_HSYNC) != 0)
524 1.2 nonaka continue;
525 1.2 nonaka }
526 1.2 nonaka
527 1.2 nonaka /*----------------------------------------------------------------------------
528 1.2 nonaka * MAX1233 touch screen controller for WS003SH/WS004SH
529 1.2 nonaka */
530 1.2 nonaka #define MAXCTRL_ADDR_SH 0 /* Address bit[5:0] */
531 1.2 nonaka #define MAXCTRL_PAGE_SH 6 /* Page bit (0:Data/1:Control) */
532 1.2 nonaka #define MAXCTRL_RW_SH 15 /* R/W bit (0:Write/1:Read) */
533 1.2 nonaka
534 1.2 nonaka /* VREF=2.5V, sets interrupt initiated touch-screen scans
535 1.2 nonaka * 3.5us/sample, 4 data ave., settling time: 100us */
536 1.2 nonaka #define MAX1233_ADCCTRL 0x8b43
537 1.2 nonaka
538 1.2 nonaka void
539 1.2 nonaka max1233_init(void)
540 1.2 nonaka {
541 1.2 nonaka
542 1.2 nonaka /* Enable automatic low power mode. */
543 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
544 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
545 1.2 nonaka 0x0001);
546 1.2 nonaka /* Wait for touch */
547 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
548 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
549 1.2 nonaka MAX1233_ADCCTRL);
550 1.2 nonaka }
551 1.2 nonaka
552 1.2 nonaka void
553 1.2 nonaka max1233_suspend(void)
554 1.2 nonaka {
555 1.2 nonaka
556 1.2 nonaka /* power down. */
557 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
558 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
559 1.2 nonaka 0xc000);
560 1.2 nonaka /* DAC off */
561 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
562 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (2<<MAXCTRL_ADDR_SH),
563 1.2 nonaka 0x8000);
564 1.2 nonaka }
565 1.2 nonaka
566 1.2 nonaka void
567 1.2 nonaka max1233_resume(void)
568 1.2 nonaka {
569 1.2 nonaka
570 1.2 nonaka /* Enable automatic low power mode. */
571 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
572 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
573 1.2 nonaka 0x0001);
574 1.2 nonaka /* Wait for touch */
575 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
576 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),
577 1.2 nonaka MAX1233_ADCCTRL);
578 1.2 nonaka /* DAC on */
579 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
580 1.2 nonaka (0<<MAXCTRL_RW_SH) | (1<<MAXCTRL_PAGE_SH) | (2<<MAXCTRL_ADDR_SH),
581 1.2 nonaka 0x0000);
582 1.2 nonaka }
583 1.2 nonaka
584 1.2 nonaka int
585 1.2 nonaka max1233_readpos(struct wzero3tp_pos *pos)
586 1.2 nonaka {
587 1.2 nonaka uint32_t z1 = 0, z2 = 0, rt;
588 1.2 nonaka uint32_t status;
589 1.2 nonaka int down;
590 1.2 nonaka
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 0x0b43);
594 1.2 nonaka
595 1.2 nonaka while ((status = (wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
596 1.2 nonaka (1<<MAXCTRL_RW_SH)
597 1.2 nonaka | (1<<MAXCTRL_PAGE_SH)
598 1.2 nonaka | (0<<MAXCTRL_ADDR_SH), 0) & 0x4000)) != 0x4000) {
599 1.2 nonaka DPRINTF(("%s: status=%#x\n", __func__, status));
600 1.2 nonaka }
601 1.2 nonaka DPRINTF(("%s: status=%#x\n", __func__, status));
602 1.2 nonaka
603 1.2 nonaka z1 = wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
604 1.2 nonaka (1<<MAXCTRL_RW_SH) | (0<<MAXCTRL_PAGE_SH) | (2<<MAXCTRL_ADDR_SH),0);
605 1.2 nonaka DPRINTF(("%s: first z1=%d\n", __func__, z1));
606 1.2 nonaka
607 1.2 nonaka down = (z1 >= 10);
608 1.2 nonaka if (!down)
609 1.2 nonaka goto out;
610 1.2 nonaka
611 1.2 nonaka pos->x = wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
612 1.2 nonaka (1<<MAXCTRL_RW_SH) | (0<<MAXCTRL_PAGE_SH) | (0<<MAXCTRL_ADDR_SH),0);
613 1.2 nonaka DPRINTF(("%s: x=%d\n", __func__, pos->x));
614 1.2 nonaka pos->y = wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
615 1.2 nonaka (1<<MAXCTRL_RW_SH) | (0<<MAXCTRL_PAGE_SH) | (1<<MAXCTRL_ADDR_SH),0);
616 1.2 nonaka DPRINTF(("%s: y=%d\n", __func__, pos->y));
617 1.2 nonaka z1 = wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
618 1.2 nonaka (1<<MAXCTRL_RW_SH) | (0<<MAXCTRL_PAGE_SH) | (2<<MAXCTRL_ADDR_SH),0);
619 1.2 nonaka DPRINTF(("%s: z1=%d\n", __func__, z1));
620 1.2 nonaka z2 = wzero3ssp_ic_send(WZERO3_SSP_IC_MAX1233,
621 1.2 nonaka (1<<MAXCTRL_RW_SH) | (0<<MAXCTRL_PAGE_SH) | (3<<MAXCTRL_ADDR_SH),0);
622 1.2 nonaka DPRINTF(("%s: z2=%d\n", __func__, z2));
623 1.2 nonaka
624 1.2 nonaka if (z1) {
625 1.2 nonaka rt = 400/*XXX*/;
626 1.2 nonaka rt *= pos->x;
627 1.2 nonaka rt *= (z2 / z1) - 1;
628 1.2 nonaka rt >>= 12;
629 1.2 nonaka } else
630 1.2 nonaka rt = 0;
631 1.2 nonaka DPRINTF(("%s: rt=%d\n", __func__, rt));
632 1.2 nonaka
633 1.2 nonaka /* check that pen is still down */
634 1.2 nonaka if (z1 == 0 || rt == 0)
635 1.2 nonaka down = 0;
636 1.2 nonaka pos->z = down;
637 1.2 nonaka
638 1.2 nonaka out:
639 1.2 nonaka return down;
640 1.2 nonaka }
641 1.2 nonaka
642 1.2 nonaka /*----------------------------------------------------------------------------
643 1.2 nonaka * ADS7846/TSC2046 touch screen controller for WS007SH
644 1.2 nonaka */
645 1.2 nonaka #define ADSCTRL_PD0_SH 0 /* PD0 bit */
646 1.2 nonaka #define ADSCTRL_PD1_SH 1 /* PD1 bit */
647 1.2 nonaka #define ADSCTRL_DFR_SH 2 /* SER/DFR bit */
648 1.2 nonaka #define ADSCTRL_MOD_SH 3 /* Mode bit */
649 1.2 nonaka #define ADSCTRL_ADR_SH 4 /* Address setting */
650 1.2 nonaka #define ADSCTRL_STS_SH 7 /* Start bit */
651 1.2 nonaka
652 1.2 nonaka static uint32_t ads7846_sync(int, int, uint32_t);
653 1.2 nonaka
654 1.2 nonaka void
655 1.2 nonaka ads7846_init(void)
656 1.2 nonaka {
657 1.2 nonaka
658 1.2 nonaka /* Enable automatic low power mode. */
659 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846,
660 1.2 nonaka (4<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH), 0);
661 1.2 nonaka }
662 1.2 nonaka
663 1.2 nonaka void
664 1.2 nonaka ads7846_suspend(void)
665 1.2 nonaka {
666 1.2 nonaka
667 1.2 nonaka /* Turn off reference voltage but leave ADC on. */
668 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846,
669 1.2 nonaka (1<<ADSCTRL_PD1_SH) | (1<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH), 0);
670 1.2 nonaka }
671 1.2 nonaka
672 1.2 nonaka void
673 1.2 nonaka ads7846_resume(void)
674 1.2 nonaka {
675 1.2 nonaka
676 1.2 nonaka /* Enable automatic low power mode. */
677 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846,
678 1.2 nonaka (4<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH), 0);
679 1.2 nonaka }
680 1.2 nonaka
681 1.2 nonaka int
682 1.2 nonaka ads7846_readpos(struct wzero3tp_pos *pos)
683 1.2 nonaka {
684 1.2 nonaka int cmd, cmd0;
685 1.2 nonaka int z0, z1;
686 1.2 nonaka int down;
687 1.2 nonaka
688 1.2 nonaka cmd0 = (1<<ADSCTRL_STS_SH) | (1<<ADSCTRL_PD0_SH) | (1<<ADSCTRL_PD1_SH);
689 1.2 nonaka
690 1.2 nonaka /* check that pen is down */
691 1.2 nonaka cmd = cmd0 | (3<<ADSCTRL_ADR_SH);
692 1.2 nonaka z0 = wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846, cmd, 0);
693 1.2 nonaka DPRINTF(("%s: first z0 = %d\n", __func__, z0));
694 1.2 nonaka
695 1.2 nonaka down = (z0 >= 10);
696 1.2 nonaka if (!down)
697 1.2 nonaka goto out;
698 1.2 nonaka
699 1.2 nonaka /* Y (discard) */
700 1.2 nonaka cmd = cmd0 | (1<<ADSCTRL_ADR_SH);
701 1.2 nonaka (void)ads7846_sync(0, 1, cmd);
702 1.2 nonaka
703 1.2 nonaka /* Y */
704 1.2 nonaka cmd = cmd0 | (1<<ADSCTRL_ADR_SH);
705 1.2 nonaka (void)ads7846_sync(1, 1, cmd);
706 1.2 nonaka
707 1.2 nonaka /* X */
708 1.2 nonaka cmd = cmd0 | (5<<ADSCTRL_ADR_SH);
709 1.2 nonaka pos->y = ads7846_sync(1, 1, cmd);
710 1.2 nonaka DPRINTF(("%s: y = %d\n", __func__, pos->y));
711 1.2 nonaka
712 1.2 nonaka /* Z0 */
713 1.2 nonaka cmd = cmd0 | (3<<ADSCTRL_ADR_SH);
714 1.2 nonaka pos->x = ads7846_sync(1, 1, cmd);
715 1.2 nonaka DPRINTF(("%s: x = %d\n", __func__, pos->x));
716 1.2 nonaka
717 1.2 nonaka /* Z1 */
718 1.2 nonaka cmd = cmd0 | (4<<ADSCTRL_ADR_SH);
719 1.2 nonaka z0 = ads7846_sync(1, 1, cmd);
720 1.2 nonaka z1 = ads7846_sync(1, 0, cmd);
721 1.2 nonaka DPRINTF(("%s: z0 = %d, z1 = %d\n", __func__, z0, z1));
722 1.2 nonaka
723 1.2 nonaka /* check that pen is still down */
724 1.2 nonaka if (z0 == 0 || (pos->x * (z1 - z0) / z0) >= 15000)
725 1.2 nonaka down = 0;
726 1.2 nonaka pos->z = down;
727 1.2 nonaka
728 1.2 nonaka out:
729 1.2 nonaka /* Enable automatic low power mode. */
730 1.2 nonaka cmd = (1<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH);
731 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846, cmd, 0);
732 1.2 nonaka
733 1.2 nonaka return down;
734 1.2 nonaka }
735 1.2 nonaka
736 1.2 nonaka void (*ads7846_wait_for_hsync)(void);
737 1.2 nonaka
738 1.2 nonaka /*
739 1.2 nonaka * Communicate synchronously with the ADS784x touch screen controller.
740 1.2 nonaka */
741 1.2 nonaka static uint32_t
742 1.2 nonaka ads7846_sync(int dorecv, int dosend, uint32_t cmd)
743 1.2 nonaka {
744 1.2 nonaka uint32_t rv = 0;
745 1.2 nonaka
746 1.2 nonaka if (ads7846_wait_for_hsync)
747 1.2 nonaka (*ads7846_wait_for_hsync)();
748 1.2 nonaka
749 1.2 nonaka if (dorecv)
750 1.2 nonaka rv = wzero3ssp_ic_stop(WZERO3_SSP_IC_ADS7846);
751 1.2 nonaka
752 1.2 nonaka if (dosend) {
753 1.2 nonaka /* send dummy command; discard SSDR */
754 1.2 nonaka (void)wzero3ssp_ic_send(WZERO3_SSP_IC_ADS7846, cmd, 0);
755 1.2 nonaka
756 1.2 nonaka /* wait for refresh */
757 1.2 nonaka if (ads7846_wait_for_hsync)
758 1.2 nonaka (*ads7846_wait_for_hsync)();
759 1.2 nonaka
760 1.2 nonaka /* send the actual command; keep ADS784x enabled */
761 1.2 nonaka wzero3ssp_ic_start(WZERO3_SSP_IC_ADS7846, cmd);
762 1.2 nonaka }
763 1.2 nonaka
764 1.2 nonaka return rv;
765 1.2 nonaka }
766