xref: /netbsd-src/sys/arch/hpcmips/vr/vrpiu.c (revision bcc8ec9959e7b01e313d813067bfb43a3ad70551)
1 /*	$NetBSD: vrpiu.c,v 1.8 2001/01/08 09:50:08 takemura Exp $	*/
2 
3 /*
4  * Copyright (c) 1999 Shin Takemura All rights reserved.
5  * Copyright (c) 2000 SATO Kazumi, All rights reserved.
6  * Copyright (c) 1999,2000 PocketBSD Project. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 
31 /*
32  * A/D polling part written by SATO Kazumi.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
38 #include <sys/kernel.h>
39 #include <sys/callout.h>
40 #include <sys/boot_flag.h>
41 
42 #include <dev/wscons/wsconsio.h>
43 #include <dev/wscons/wsmousevar.h>
44 
45 #include <machine/bus.h>
46 #include <machine/platid.h>
47 #include <machine/platid_mask.h>
48 #include <machine/config_hook.h>
49 
50 #include <hpcmips/hpcmips/machdep.h>
51 #include <hpcmips/dev/tpcalibvar.h>
52 
53 #include <hpcmips/vr/vripvar.h>
54 #include <hpcmips/vr/cmureg.h>
55 #include <hpcmips/vr/vrpiuvar.h>
56 #include <hpcmips/vr/vrpiureg.h>
57 
58 /*
59  * contant and macro definitions
60  */
61 #define VRPIUDEBUG
62 #ifdef VRPIUDEBUG
63 int	vrpiu_debug = 0;
64 #define	DPRINTF(arg) if (vrpiu_debug) printf arg;
65 #define	VPRINTF(arg) if (bootverbose || vrpiu_debug) printf arg;
66 #else
67 #define	DPRINTF(arg)
68 #define	VPRINTF(arg) if (bootverbose) printf arg;
69 #endif
70 
71 #ifndef VRPIU_AD_POLL_INTERVAL
72 #define VRPIU_AD_POLL_INTERVAL	60	/* interval is 60 sec */
73 #endif /* VRPIU_AD_POLL_INTERTVAL */
74 
75 #define	PIUSIVL_SCANINTVAL_MIN	333			/* 10msec	*/
76 #define	PIUSIVL_SCANINTVAL_MAX	PIUSIVL_SCANINTVAL_MASK	/* 60msec	*/
77 
78 #define TP_INTR	(PIUINT_ALLINTR & ~PIUINT_PADADPINTR)
79 #define AD_INTR	(PIUINT_PADADPINTR)
80 
81 /*
82  * data types
83  */
84 /* struct vrpiu_softc is defined in vrpiuvar.h */
85 
86 /*
87  * function prototypes
88  */
89 static int	vrpiumatch __P((struct device *, struct cfdata *, void *));
90 static void	vrpiuattach __P((struct device *, struct device *, void *));
91 
92 static void	vrpiu_write __P((struct vrpiu_softc *, int, unsigned short));
93 static u_short	vrpiu_read __P((struct vrpiu_softc *, int));
94 
95 static int	vrpiu_intr __P((void *));
96 static void	vrpiu_tp_intr __P((struct vrpiu_softc *));
97 static void	vrpiu_ad_intr __P((struct vrpiu_softc *));
98 #ifdef DEBUG
99 static void	vrpiu_dump_cntreg __P((unsigned int cmd));
100 #endif
101 
102 static int	vrpiu_tp_enable __P((void *));
103 static int	vrpiu_tp_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
104 static void	vrpiu_tp_disable __P((void *));
105 int		vrpiu_ad_enable __P((void *));
106 void		vrpiu_ad_disable __P((void *));
107 static void	vrpiu_start_powerstate __P((void *));
108 static void	vrpiu_calc_powerstate __P((struct vrpiu_softc *));
109 static void	vrpiu_power __P((int, void *));
110 static u_int	scan_interval __P((u_int data));
111 
112 /* mra is defined in mra.c */
113 int mra_Y_AX1_BX2_C __P((int *y, int ys, int *x1, int x1s, int *x2, int x2s,
114 			 int n, int scale, int *a, int *b, int *c));
115 
116 /*
117  * static or global variables
118  */
119 struct cfattach vrpiu_ca = {
120 	sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
121 };
122 
123 const struct wsmouse_accessops vrpiu_accessops = {
124 	vrpiu_tp_enable,
125 	vrpiu_tp_ioctl,
126 	vrpiu_tp_disable,
127 };
128 
129 int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
130 
131 /*
132  * function definitions
133  */
134 static inline void
135 vrpiu_write(sc, port, val)
136 	struct vrpiu_softc *sc;
137 	int port;
138 	unsigned short val;
139 {
140 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
141 }
142 
143 static inline u_short
144 vrpiu_read(sc, port)
145 	struct vrpiu_softc *sc;
146 	int port;
147 {
148 	return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
149 }
150 
151 static int
152 vrpiumatch(parent, cf, aux)
153 	struct device *parent;
154 	struct cfdata *cf;
155 	void *aux;
156 {
157 	return 1;
158 }
159 
160 static void
161 vrpiuattach(parent, self, aux)
162 	struct device *parent;
163 	struct device *self;
164 	void *aux;
165 {
166 	struct vrpiu_softc *sc = (struct vrpiu_softc *)self;
167 	struct vrip_attach_args *va = aux;
168 	struct wsmousedev_attach_args wsmaa;
169 
170 	bus_space_tag_t iot = va->va_iot;
171 	bus_space_handle_t ioh;
172 
173 	if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
174 		printf(": can't map bus space\n");
175 		return;
176 	}
177 
178 	sc->sc_iot = iot;
179 	sc->sc_ioh = ioh;
180 	sc->sc_vrip = va->va_vc;
181 
182 	sc->sc_interval = scan_interval(WSMOUSE_RES_DEFAULT);
183 
184 	/*
185 	 * disable device until vrpiu_enable called
186 	 */
187 	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
188 
189 	tpcalib_init(&sc->sc_tpcalib);
190 #if 1
191 	/*
192 	 * XXX, calibrate parameters
193 	 */
194 	{
195 		int i;
196 		static const struct {
197 			platid_mask_t *mask;
198 			struct wsmouse_calibcoords coords;
199 		} calibrations[] = {
200 			{ &platid_mask_MACH_NEC_MCR_700A,
201 				{ 0, 0, 799, 599,
202 				  4,
203 				{ { 115,  80,   0,   0 },
204 				  { 115, 966,   0, 599 },
205 				  { 912,  80, 799,   0 },
206 				  { 912, 966, 799, 599 } } } },
207 
208 			{ NULL,		/* samples got on my MC-R500 */
209 				{ 0, 0, 639, 239,
210 				5,
211 				{ { 502, 486, 320, 120 },
212 				  {  55, 109,   0,   0 },
213 				  {  54, 913,   0, 239 },
214 				  { 973, 924, 639, 239 },
215 				  { 975, 123, 639,   0 } } } },
216 		};
217 		for (i = 0; ; i++) {
218 			if (calibrations[i].mask == NULL
219 			    || platid_match(&platid, calibrations[i].mask))
220 				break;
221 		}
222 		tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
223 			      (caddr_t)&calibrations[i].coords, 0, 0);
224 	}
225 #endif
226 
227 	/* install interrupt handler and enable interrupt */
228 	if (!(sc->sc_handler =
229 	      vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
230 				  vrpiu_intr, sc))) {
231 		printf (": can't map interrupt line.\n");
232 		return;
233 	}
234 
235 	/* mask level2 interrupt, stop scan sequencer and mask clock to piu */
236 	vrpiu_tp_disable(sc);
237 
238 	printf("\n");
239 
240 	wsmaa.accessops = &vrpiu_accessops;
241 	wsmaa.accesscookie = sc;
242 
243 	/*
244 	 * attach the wsmouse
245 	 */
246 	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
247 
248 	/*
249 	 * power management events
250 	 */
251 	sc->sc_power_hook = powerhook_establish(vrpiu_power, sc);
252 
253 	/*
254 	 * init A/D port polling.
255 	 */
256 	sc->sc_battery.n_values = 3;
257 	sc->sc_battery.value[0] = -1;
258 	sc->sc_battery.value[1] = -1;
259 	sc->sc_battery.value[2] = -1;
260 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
261 	callout_init(&sc->sc_adpoll);
262 	callout_reset(&sc->sc_adpoll, hz,
263 			  vrpiu_start_powerstate, sc);
264 }
265 
266 /*
267  * calculate interval value
268  *  input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
269  * output: value for PIUSIVL_REG
270  */
271 static u_int
272 scan_interval(u_int data)
273 {
274 	int scale;
275 
276 	if (data < WSMOUSE_RES_MIN)
277 		data = WSMOUSE_RES_MIN;
278 
279 	if (WSMOUSE_RES_MAX < data)
280 		data = WSMOUSE_RES_MAX;
281 
282 	scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN;
283 	data += WSMOUSE_RES_MIN;
284 
285 	return PIUSIVL_SCANINTVAL_MIN +
286 	    (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) *
287 	    (scale - data) / scale;
288 }
289 
290 int
291 vrpiu_ad_enable(v)
292 	void *v;
293 {
294 	struct vrpiu_softc *sc = v;
295 	int s;
296 	unsigned int cnt;
297 
298 	DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
299 	    __FILE__, __LINE__, sc->sc_interval));
300 	if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
301 		return EBUSY;
302 
303 	/* supply clock to PIU */
304 	__vrcmu_supply(CMUMSKPIU, 1);
305 
306 	/* set scan interval */
307 	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
308 
309 	s = spltty();
310 
311 	/* clear interrupt status */
312 	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
313 
314 	/* Disable -> Standby */
315 	cnt = PIUCNT_PIUPWR |
316 		PIUCNT_PIUMODE_COORDINATE |
317 		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
318 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
319 
320 	/* Level2 interrupt register setting */
321 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1);
322 
323 	/* save pen status, touch or release */
324 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
325 
326 	/*
327 	 * Enable scan sequencer operation
328 	 * Standby -> WaitPenTouch
329 	 */
330 	cnt |= PIUCNT_PIUSEQEN;
331 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
332 
333 	sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
334 
335 	splx(s);
336 
337 	return 0;
338 }
339 
340 void
341 vrpiu_ad_disable(v)
342 	void *v;
343 {
344 	struct vrpiu_softc *sc = v;
345 
346 	DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
347 
348 	/* Set level2 interrupt register to mask interrupts */
349 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0);
350 
351 	sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
352 
353 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
354 		/* Disable scan sequencer operation and power off */
355 		vrpiu_write(sc, PIUCNT_REG_W, 0);
356 
357 		/* mask clock to PIU */
358 		__vrcmu_supply(CMUMSKPIU, 1);
359 	}
360 }
361 
362 int
363 vrpiu_tp_enable(v)
364 	void *v;
365 {
366 	struct vrpiu_softc *sc = v;
367 	int s;
368 	unsigned int cnt;
369 
370 	DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n",
371 	    __FILE__, __LINE__, sc->sc_interval));
372 	if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE)
373 		return EBUSY;
374 
375 	/* supply clock to PIU */
376 	__vrcmu_supply(CMUMSKPIU, 1);
377 
378 	/* set scan interval */
379 	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
380 
381 	s = spltty();
382 
383 	/* clear interrupt status */
384 	vrpiu_write(sc, PIUINT_REG_W, TP_INTR);
385 
386 	/* Disable -> Standby */
387 	cnt = PIUCNT_PIUPWR |
388 		PIUCNT_PIUMODE_COORDINATE |
389 		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
390 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
391 
392 	/* Level2 interrupt register setting */
393 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1);
394 
395 	/* save pen status, touch or release */
396 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
397 
398 	/*
399 	 * Enable scan sequencer operation
400 	 * Standby -> WaitPenTouch
401 	 */
402 	cnt |= PIUCNT_PIUSEQEN;
403 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
404 
405 	/* transit status DISABLE -> TOUCH or RELEASE */
406 	sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ?
407 		VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE;
408 
409 	splx(s);
410 
411 	return 0;
412 }
413 
414 void
415 vrpiu_tp_disable(v)
416 	void *v;
417 {
418 	struct vrpiu_softc *sc = v;
419 
420 	DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
421 
422 	/* Set level2 interrupt register to mask interrupts */
423 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0);
424 
425 	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
426 
427 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
428 		/* Disable scan sequencer operation and power off */
429 		vrpiu_write(sc, PIUCNT_REG_W, 0);
430 
431 		/* mask clock to PIU */
432 		__vrcmu_supply(CMUMSKPIU, 1);
433 	}
434 }
435 
436 int
437 vrpiu_tp_ioctl(v, cmd, data, flag, p)
438 	void *v;
439 	u_long cmd;
440 	caddr_t data;
441 	int flag;
442 	struct proc *p;
443 {
444 	struct vrpiu_softc *sc = v;
445 
446 	DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
447 
448 	switch (cmd) {
449 	case WSMOUSEIO_GTYPE:
450 		*(u_int *)data = WSMOUSE_TYPE_TPANEL;
451 		break;
452 
453 	case WSMOUSEIO_SRES:
454 	    {
455 		int tp_enable;
456 		int ad_enable;
457 
458 		tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE);
459 		ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE);
460 
461 		if (tp_enable)
462 			vrpiu_tp_disable(sc);
463 		if (ad_enable)
464 			vrpiu_ad_disable(sc);
465 
466 		sc->sc_interval = scan_interval(*(u_int *)data);
467 		DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
468 		    __FILE__, __LINE__, *(u_int *)data, sc->sc_interval));
469 
470 		if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN)
471 			sc->sc_interval = PIUSIVL_SCANINTVAL_MIN;
472 
473 		if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval)
474 			sc->sc_interval = PIUSIVL_SCANINTVAL_MAX;
475 
476 		if (tp_enable)
477 			vrpiu_tp_enable(sc);
478 		if (ad_enable)
479 			vrpiu_ad_enable(sc);
480 	    }
481 	    break;
482 
483 	case WSMOUSEIO_SCALIBCOORDS:
484 	case WSMOUSEIO_GCALIBCOORDS:
485                 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
486 
487 	default:
488 		return (-1);
489 	}
490 	return (0);
491 }
492 
493 /*
494  * PIU AD interrupt handler.
495  */
496 void
497 vrpiu_ad_intr(sc)
498 	struct vrpiu_softc *sc;
499 {
500 	unsigned int i;
501 	unsigned int intrstat;
502 
503 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
504 
505 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
506 		/*
507 		 * the device isn't enabled. just clear interrupt.
508 		 */
509 		vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
510 		return;
511 	}
512 
513 	if (intrstat & PIUINT_PADADPINTR) {
514 		sc->sc_battery.value[0] = (unsigned int)vrpiu_read(sc, PIUAB(0));
515 		sc->sc_battery.value[1] = (unsigned int)vrpiu_read(sc, PIUAB(1));
516 		sc->sc_battery.value[2] = (unsigned int)vrpiu_read(sc, PIUAB(2));
517 	}
518 
519 	if (intrstat & PIUINT_PADADPINTR) {
520 		for (i = 0; i < 3; i++) {
521 			if (sc->sc_battery.value[i] & PIUAB_VALID)
522 				sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
523 			else
524 				sc->sc_battery.value[i] = 0;
525 		}
526 		vrpiu_calc_powerstate(sc);
527 	}
528 	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
529 
530 	return;
531 }
532 /*
533  * PIU TP interrupt handler.
534  */
535 void
536 vrpiu_tp_intr(sc)
537 	struct vrpiu_softc *sc;
538 {
539 	unsigned int cnt, i;
540 	unsigned int intrstat, page;
541 	int tpx0, tpx1, tpy0, tpy1;
542 	int x, y, xraw, yraw;
543 
544 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
545 
546 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
547 	/*
548 		 * the device isn't enabled. just clear interrupt.
549 		 */
550 		vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
551 		return;
552 	}
553 
554 	page = (intrstat & PIUINT_OVP) ? 1 : 0;
555 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
556 		tpx0 = vrpiu_read(sc, PIUPB(page, 0));
557 		tpx1 = vrpiu_read(sc, PIUPB(page, 1));
558 		tpy0 = vrpiu_read(sc, PIUPB(page, 2));
559 		tpy1 = vrpiu_read(sc, PIUPB(page, 3));
560 	}
561 
562 	if (intrstat & PIUINT_PADDLOSTINTR) {
563 		page = page ? 0 : 1;
564 		for (i = 0; i < 4; i++)
565 			vrpiu_read(sc, PIUPB(page, i));
566 	}
567 
568 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
569 #ifdef DEBUG
570 	if (vrpiu_debug)
571 		vrpiu_dump_cntreg(cnt);
572 #endif
573 
574 	/* clear interrupt status */
575 	vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
576 
577 #if 0
578 	DPRINTF(("vrpiu_intr: OVP=%d", page));
579 	if (intrstat & PIUINT_PADCMDINTR)
580 		DPRINTF((" CMD"));
581 	if (intrstat & PIUINT_PADADPINTR)
582 		DPRINTF((" A/D"));
583 	if (intrstat & PIUINT_PADPAGE1INTR)
584 		DPRINTF((" PAGE1"));
585 	if (intrstat & PIUINT_PADPAGE0INTR)
586 		DPRINTF((" PAGE0"));
587 	if (intrstat & PIUINT_PADDLOSTINTR)
588 		DPRINTF((" DLOST"));
589 	if (intrstat & PIUINT_PENCHGINTR)
590 		DPRINTF((" PENCHG"));
591 	DPRINTF(("\n"));
592 #endif
593 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
594 		if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
595 		      (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
596 			printf("vrpiu: internal error, data is not valid!\n");
597 		} else {
598 			tpx0 &= PIUPB_PADDATA_MASK;
599 			tpx1 &= PIUPB_PADDATA_MASK;
600 			tpy0 &= PIUPB_PADDATA_MASK;
601 			tpy1 &= PIUPB_PADDATA_MASK;
602 #define ISVALID(n, c, m)	((c) - (m) < (n) && (n) < (c) + (m))
603 			if (ISVALID(tpx0 + tpx1, 1024, 200) &&
604 			    ISVALID(tpx0 + tpx1, 1024, 200)) {
605 #if 0
606 				DPRINTF(("%04x %04x %04x %04x\n",
607 					 tpx0, tpx1, tpy0, tpy1));
608 				DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0,
609 					 tpx0 + tpx1, tpy0 + tpy1));
610 #endif
611 				xraw = tpy1 * 1024 / (tpy0 + tpy1);
612 				yraw = tpx1 * 1024 / (tpx0 + tpx1);
613 				DPRINTF(("%3d %3d", xraw, yraw));
614 
615 				tpcalib_trans(&sc->sc_tpcalib,
616 					      xraw, yraw, &x, &y);
617 
618 				DPRINTF(("->%4d %4d", x, y));
619 				wsmouse_input(sc->sc_wsmousedev,
620 					      (cnt & PIUCNT_PENSTC) ? 1 : 0,
621 					      x, /* x */
622 					      y, /* y */
623 					      0, /* z */
624 					      WSMOUSE_INPUT_ABSOLUTE_X |
625 					      WSMOUSE_INPUT_ABSOLUTE_Y);
626 				DPRINTF(("\n"));
627 			}
628 		}
629 	}
630 
631 	if (cnt & PIUCNT_PENSTC) {
632 		if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
633 			/*
634 			 * pen touch
635 			 */
636 			DPRINTF(("PEN TOUCH\n"));
637 			sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
638 			/*
639 			 * We should not report button down event while
640 			 * we don't know where it occur.
641 			 */
642 		}
643 	} else {
644 		if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
645 			/*
646 			 * pen release
647 			 */
648 			DPRINTF(("RELEASE\n"));
649 			sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
650 			/* button 0 UP */
651 			wsmouse_input(sc->sc_wsmousedev,
652 				      0,
653 				      0, 0, 0, 0);
654 		}
655 	}
656 
657 	if (intrstat & PIUINT_PADDLOSTINTR) {
658 		cnt |= PIUCNT_PIUSEQEN;
659 		vrpiu_write(sc, PIUCNT_REG_W, cnt);
660 	}
661 
662 	return;
663 }
664 
665 /*
666  * PIU interrupt handler.
667  */
668 int
669 vrpiu_intr(arg)
670 	void *arg;
671 {
672         struct vrpiu_softc *sc = arg;
673 
674 	vrpiu_ad_intr(sc);
675 	vrpiu_tp_intr(sc);
676 
677 	return 0;
678 }
679 
680 void
681 vrpiu_start_powerstate(v)
682 	void *v;
683 {
684 	int mask;
685 	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
686 
687 	vrpiu_ad_enable(sc);
688 	mask = vrpiu_read(sc, PIUAMSK_REG_W);
689 	mask &= 0xff8f; /* XXX */
690 	vrpiu_write(sc, PIUAMSK_REG_W, mask);
691 	vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
692 	/*
693 	 * restart next A/D polling
694 	 */
695 	callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
696 			 vrpiu_start_powerstate, sc);
697 }
698 
699 void
700 vrpiu_calc_powerstate(sc)
701 	struct vrpiu_softc *sc;
702 {
703 	extern void vrgiu_diff_io __P((void));
704 	vrpiu_ad_disable(sc);
705 	VPRINTF(("vrpiu:AD: %d, %d, %d\n",
706 		sc->sc_battery.value[0],
707 		sc->sc_battery.value[1],
708 		sc->sc_battery.value[2]));
709 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
710 #ifdef notyet
711 	config_hook_call(CONFIG_HOOK_SET,
712 			 CONFIG_HOOK_BATTERYVAL,
713 			 (void *)&sc->sc_battery);
714 #endif /* notyet */
715 	/*
716 	 * restart next A/D polling if change polling timming.
717 	 */
718 	if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
719 		callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
720 				 vrpiu_start_powerstate, sc);
721 	if (bootverbose)
722 		vrgiu_diff_io();
723 
724 }
725 
726 static void
727 vrpiu_power(why, arg)
728 	int why;
729 	void *arg;
730 {
731 	struct vrpiu_softc *sc = arg;
732 
733 	switch (why) {
734 	case PWR_STANDBY:
735 	case PWR_SUSPEND:
736 		break;
737 	case PWR_RESUME:
738 		callout_reset(&sc->sc_adpoll, hz,
739 				  vrpiu_start_powerstate, sc);
740 		break;
741 	}
742 }
743 
744 #ifdef DEBUG
745 void
746 vrpiu_dump_cntreg(cnt)
747 	unsigned int cnt;
748 {
749 	printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
750 	printf(" state=");
751 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
752 		printf("CmdScan");
753 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
754 		printf("IntervalNextScan");
755 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
756 		printf("PenDataScan");
757 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
758 		printf("WaitPenTouch");
759 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
760 		printf("???");
761 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
762 		printf("ADPortScan");
763 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
764 		printf("Standby");
765 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
766 		printf("Disable");
767 	if (cnt & PIUCNT_PADATSTOP)
768 		printf(" AutoStop");
769 	if (cnt & PIUCNT_PADATSTART)
770 		printf(" AutoStart");
771 	if (cnt & PIUCNT_PADSCANSTOP)
772 		printf(" Stop");
773 	if (cnt & PIUCNT_PADSCANSTART)
774 		printf(" Start");
775 	if (cnt & PIUCNT_PADSCANTYPE)
776 		printf(" ScanPressure");
777 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
778 		printf(" A/D");
779 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
780 		printf(" Coordinate");
781 	if (cnt & PIUCNT_PIUSEQEN)
782 		printf(" SeqEn");
783 	if ((cnt & PIUCNT_PIUPWR) == 0)
784 		printf(" PowerOff");
785 	if ((cnt & PIUCNT_PADRST) == 0)
786 		printf(" Reset");
787 	printf("\n");
788 }
789 #endif
790