vrpiu.c revision 1.9
1/*	$NetBSD: vrpiu.c,v 1.9 2001/01/20 12:24:22 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
63int	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 */
89static int	vrpiumatch __P((struct device *, struct cfdata *, void *));
90static void	vrpiuattach __P((struct device *, struct device *, void *));
91
92static void	vrpiu_write __P((struct vrpiu_softc *, int, unsigned short));
93static u_short	vrpiu_read __P((struct vrpiu_softc *, int));
94
95static int	vrpiu_intr __P((void *));
96static void	vrpiu_tp_intr __P((struct vrpiu_softc *));
97static void	vrpiu_ad_intr __P((struct vrpiu_softc *));
98#ifdef DEBUG
99static void	vrpiu_dump_cntreg __P((unsigned int cmd));
100#endif
101
102static int	vrpiu_tp_enable __P((void *));
103static int	vrpiu_tp_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
104static void	vrpiu_tp_disable __P((void *));
105int		vrpiu_ad_enable __P((void *));
106void		vrpiu_ad_disable __P((void *));
107static void	vrpiu_start_powerstate __P((void *));
108static void	vrpiu_calc_powerstate __P((struct vrpiu_softc *));
109static void	vrpiu_power __P((int, void *));
110static u_int	scan_interval __P((u_int data));
111
112/* mra is defined in mra.c */
113int 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 */
119struct cfattach vrpiu_ca = {
120	sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
121};
122
123const struct wsmouse_accessops vrpiu_accessops = {
124	vrpiu_tp_enable,
125	vrpiu_tp_ioctl,
126	vrpiu_tp_disable,
127};
128
129int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
130
131/*
132 * function definitions
133 */
134static inline void
135vrpiu_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
143static inline u_short
144vrpiu_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
151static int
152vrpiumatch(parent, cf, aux)
153	struct device *parent;
154	struct cfdata *cf;
155	void *aux;
156{
157	return 1;
158}
159
160static void
161vrpiuattach(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, vrpiu_start_powerstate, sc);
263}
264
265/*
266 * calculate interval value
267 *  input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
268 * output: value for PIUSIVL_REG
269 */
270static u_int
271scan_interval(u_int data)
272{
273	int scale;
274
275	if (data < WSMOUSE_RES_MIN)
276	    data = WSMOUSE_RES_MIN;
277
278	if (WSMOUSE_RES_MAX < data)
279	    data = WSMOUSE_RES_MAX;
280
281	scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN;
282	data += WSMOUSE_RES_MIN;
283
284	return PIUSIVL_SCANINTVAL_MIN +
285	    (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) *
286	    (scale - data) / scale;
287}
288
289int
290vrpiu_ad_enable(v)
291	void *v;
292{
293	struct vrpiu_softc *sc = v;
294	int s;
295	unsigned int cnt;
296
297	DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
298		 __FILE__, __LINE__, sc->sc_interval));
299	if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
300	    return EBUSY;
301
302	/* supply clock to PIU */
303	__vrcmu_supply(CMUMSKPIU, 1);
304
305	/* set scan interval */
306	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
307
308	s = spltty();
309
310	/* clear interrupt status */
311	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
312
313	/* Disable -> Standby */
314	cnt = PIUCNT_PIUPWR |
315		PIUCNT_PIUMODE_COORDINATE |
316		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
317	vrpiu_write(sc, PIUCNT_REG_W, cnt);
318
319	/* Level2 interrupt register setting */
320	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1);
321
322	/* save pen status, touch or release */
323	cnt = vrpiu_read(sc, PIUCNT_REG_W);
324
325	/*
326	 * Enable scan sequencer operation
327	 * Standby -> WaitPenTouch
328	 */
329	cnt |= PIUCNT_PIUSEQEN;
330	vrpiu_write(sc, PIUCNT_REG_W, cnt);
331
332	sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
333
334	splx(s);
335
336	return 0;
337}
338
339void
340vrpiu_ad_disable(v)
341	void *v;
342{
343	struct vrpiu_softc *sc = v;
344
345	DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
346
347	/* Set level2 interrupt register to mask interrupts */
348	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0);
349
350	sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
351
352	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
353	    /* Disable scan sequencer operation and power off */
354	    vrpiu_write(sc, PIUCNT_REG_W, 0);
355
356	    /* mask clock to PIU */
357	    __vrcmu_supply(CMUMSKPIU, 1);
358	}
359}
360
361int
362vrpiu_tp_enable(v)
363	void *v;
364{
365	struct vrpiu_softc *sc = v;
366	int s;
367	unsigned int cnt;
368
369	DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n",
370		 __FILE__, __LINE__, sc->sc_interval));
371	if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE)
372	    return EBUSY;
373
374	/* supply clock to PIU */
375	__vrcmu_supply(CMUMSKPIU, 1);
376
377	/* set scan interval */
378	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
379
380	s = spltty();
381
382	/* clear interrupt status */
383	vrpiu_write(sc, PIUINT_REG_W, TP_INTR);
384
385	/* Disable -> Standby */
386	cnt = PIUCNT_PIUPWR |
387		PIUCNT_PIUMODE_COORDINATE |
388		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
389	vrpiu_write(sc, PIUCNT_REG_W, cnt);
390
391	/* Level2 interrupt register setting */
392	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1);
393
394	/* save pen status, touch or release */
395	cnt = vrpiu_read(sc, PIUCNT_REG_W);
396
397	/*
398	 * Enable scan sequencer operation
399	 * Standby -> WaitPenTouch
400	 */
401	cnt |= PIUCNT_PIUSEQEN;
402	vrpiu_write(sc, PIUCNT_REG_W, cnt);
403
404	/* transit status DISABLE -> TOUCH or RELEASE */
405	sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ?
406		VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE;
407
408	splx(s);
409
410	return 0;
411}
412
413void
414vrpiu_tp_disable(v)
415	void *v;
416{
417	struct vrpiu_softc *sc = v;
418
419	DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
420
421	/* Set level2 interrupt register to mask interrupts */
422	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0);
423
424	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
425
426	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
427	    /* Disable scan sequencer operation and power off */
428	    vrpiu_write(sc, PIUCNT_REG_W, 0);
429
430	    /* mask clock to PIU */
431	    __vrcmu_supply(CMUMSKPIU, 1);
432	}
433}
434
435int
436vrpiu_tp_ioctl(v, cmd, data, flag, p)
437	void *v;
438	u_long cmd;
439	caddr_t data;
440	int flag;
441	struct proc *p;
442{
443	struct vrpiu_softc *sc = v;
444
445	DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
446
447	switch (cmd) {
448	case WSMOUSEIO_GTYPE:
449	    *(u_int *)data = WSMOUSE_TYPE_TPANEL;
450	    break;
451
452	case WSMOUSEIO_SRES:
453	    {
454		int tp_enable;
455		int ad_enable;
456
457		tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE);
458		ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE);
459
460		if (tp_enable)
461		    vrpiu_tp_disable(sc);
462		if (ad_enable)
463		    vrpiu_ad_disable(sc);
464
465		sc->sc_interval = scan_interval(*(u_int *)data);
466		DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
467		    __FILE__, __LINE__, *(u_int *)data, sc->sc_interval));
468
469		if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN)
470		    sc->sc_interval = PIUSIVL_SCANINTVAL_MIN;
471
472		if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval)
473		    sc->sc_interval = PIUSIVL_SCANINTVAL_MAX;
474
475		if (tp_enable)
476		    vrpiu_tp_enable(sc);
477		if (ad_enable)
478		     vrpiu_ad_enable(sc);
479	    }
480	    break;
481
482	case WSMOUSEIO_SCALIBCOORDS:
483	case WSMOUSEIO_GCALIBCOORDS:
484            return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
485
486	default:
487	    return (-1);
488	}
489	return (0);
490}
491
492/*
493 * PIU AD interrupt handler.
494 */
495void
496vrpiu_ad_intr(sc)
497	struct vrpiu_softc *sc;
498{
499	unsigned int i;
500	unsigned int intrstat;
501
502	intrstat = vrpiu_read(sc, PIUINT_REG_W);
503
504	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
505	    /*
506	     * the device isn't enabled. just clear interrupt.
507	     */
508	    vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
509	    return;
510	}
511
512	if (intrstat & PIUINT_PADADPINTR) {
513	    sc->sc_battery.value[0] = (unsigned int)vrpiu_read(sc, PIUAB(0));
514	    sc->sc_battery.value[1] = (unsigned int)vrpiu_read(sc, PIUAB(1));
515	    sc->sc_battery.value[2] = (unsigned int)vrpiu_read(sc, PIUAB(2));
516	}
517
518	if (intrstat & PIUINT_PADADPINTR) {
519	    for (i = 0; i < 3; i++) {
520		if (sc->sc_battery.value[i] & PIUAB_VALID)
521		    sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
522		else
523		    sc->sc_battery.value[i] = 0;
524	    }
525	    vrpiu_calc_powerstate(sc);
526	}
527	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
528
529	return;
530}
531/*
532 * PIU TP interrupt handler.
533 */
534void
535vrpiu_tp_intr(sc)
536	struct vrpiu_softc *sc;
537{
538	unsigned int cnt, i;
539	unsigned int intrstat, page;
540	int tpx0, tpx1, tpy0, tpy1;
541	int x, y, xraw, yraw;
542
543	intrstat = vrpiu_read(sc, PIUINT_REG_W);
544
545	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
546	    /*
547	     * the device isn't enabled. just clear interrupt.
548	     */
549	    vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
550	    return;
551	}
552
553	page = (intrstat & PIUINT_OVP) ? 1 : 0;
554	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
555	    tpx0 = vrpiu_read(sc, PIUPB(page, 0));
556	    tpx1 = vrpiu_read(sc, PIUPB(page, 1));
557	    tpy0 = vrpiu_read(sc, PIUPB(page, 2));
558	    tpy1 = vrpiu_read(sc, PIUPB(page, 3));
559	}
560
561	if (intrstat & PIUINT_PADDLOSTINTR) {
562	    page = page ? 0 : 1;
563	    for (i = 0; i < 4; i++)
564		vrpiu_read(sc, PIUPB(page, i));
565	}
566
567	cnt = vrpiu_read(sc, PIUCNT_REG_W);
568#ifdef DEBUG
569	if (vrpiu_debug)
570	    vrpiu_dump_cntreg(cnt);
571#endif
572
573	/* clear interrupt status */
574	vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
575
576#if 0
577	DPRINTF(("vrpiu_intr: OVP=%d", page));
578	if (intrstat & PIUINT_PADCMDINTR)
579	    DPRINTF((" CMD"));
580	if (intrstat & PIUINT_PADADPINTR)
581	    DPRINTF((" A/D"));
582	if (intrstat & PIUINT_PADPAGE1INTR)
583	    DPRINTF((" PAGE1"));
584	if (intrstat & PIUINT_PADPAGE0INTR)
585	    DPRINTF((" PAGE0"));
586	if (intrstat & PIUINT_PADDLOSTINTR)
587	    DPRINTF((" DLOST"));
588	if (intrstat & PIUINT_PENCHGINTR)
589	    DPRINTF((" PENCHG"));
590	DPRINTF(("\n"));
591#endif
592	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
593	    if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
594		(tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
595		printf("vrpiu: internal error, data is not valid!\n");
596	    } else {
597		tpx0 &= PIUPB_PADDATA_MASK;
598		tpx1 &= PIUPB_PADDATA_MASK;
599		tpy0 &= PIUPB_PADDATA_MASK;
600		tpy1 &= PIUPB_PADDATA_MASK;
601#define ISVALID(n, c, m)	((c) - (m) < (n) && (n) < (c) + (m))
602		if (ISVALID(tpx0 + tpx1, 1024, 200) &&
603		    ISVALID(tpx0 + tpx1, 1024, 200)) {
604#if 0
605		    DPRINTF(("%04x %04x %04x %04x\n",
606			tpx0, tpx1, tpy0, tpy1));
607		    DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0,
608			tpx0 + tpx1, tpy0 + tpy1));
609#endif
610		    xraw = tpy1 * 1024 / (tpy0 + tpy1);
611		    yraw = tpx1 * 1024 / (tpx0 + tpx1);
612		    DPRINTF(("%3d %3d", xraw, yraw));
613
614		    tpcalib_trans(&sc->sc_tpcalib, xraw, yraw, &x, &y);
615
616		    DPRINTF(("->%4d %4d", x, y));
617		    wsmouse_input(sc->sc_wsmousedev,
618			(cnt & PIUCNT_PENSTC) ? 1 : 0,
619			x, /* x */
620			y, /* y */
621			0, /* z */
622			WSMOUSE_INPUT_ABSOLUTE_X |
623			WSMOUSE_INPUT_ABSOLUTE_Y);
624		    DPRINTF(("\n"));
625		}
626	    }
627	}
628
629	if (cnt & PIUCNT_PENSTC) {
630	    if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
631		/*
632		 * pen touch
633		 */
634		DPRINTF(("PEN TOUCH\n"));
635		sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
636		/*
637		 * We should not report button down event while
638		 * we don't know where it occur.
639		 */
640	    }
641	} else {
642	    if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
643		/*
644		 * pen release
645		 */
646		DPRINTF(("RELEASE\n"));
647		sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
648		/* button 0 UP */
649		wsmouse_input(sc->sc_wsmousedev,
650		    0,
651		    0, 0, 0, 0);
652	    }
653	}
654
655	if (intrstat & PIUINT_PADDLOSTINTR) {
656	    cnt |= PIUCNT_PIUSEQEN;
657	    vrpiu_write(sc, PIUCNT_REG_W, cnt);
658	}
659
660	return;
661}
662
663/*
664 * PIU interrupt handler.
665 */
666int
667vrpiu_intr(arg)
668	void *arg;
669{
670        struct vrpiu_softc *sc = arg;
671
672	vrpiu_ad_intr(sc);
673	vrpiu_tp_intr(sc);
674
675	return 0;
676}
677
678void
679vrpiu_start_powerstate(v)
680	void *v;
681{
682	int mask;
683	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
684
685	vrpiu_ad_enable(sc);
686	mask = vrpiu_read(sc, PIUAMSK_REG_W);
687	mask &= 0xff8f; /* XXX */
688	vrpiu_write(sc, PIUAMSK_REG_W, mask);
689	vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
690	/*
691	 * restart next A/D polling
692	 */
693	callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
694		      vrpiu_start_powerstate, sc);
695}
696
697void
698vrpiu_calc_powerstate(sc)
699	struct vrpiu_softc *sc;
700{
701	extern void vrgiu_diff_io __P((void));
702	vrpiu_ad_disable(sc);
703	VPRINTF(("vrpiu:AD: %d, %d, %d\n",
704		sc->sc_battery.value[0],
705		sc->sc_battery.value[1],
706		sc->sc_battery.value[2]));
707	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
708#ifdef notyet
709	config_hook_call(CONFIG_HOOK_SET,
710			 CONFIG_HOOK_BATTERYVAL,
711			 (void *)&sc->sc_battery);
712#endif /* notyet */
713	/*
714	 * restart next A/D polling if change polling timming.
715	 */
716	if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
717	    callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
718			  vrpiu_start_powerstate, sc);
719	if (bootverbose)
720	    vrgiu_diff_io();
721
722}
723
724static void
725vrpiu_power(why, arg)
726	int why;
727	void *arg;
728{
729	struct vrpiu_softc *sc = arg;
730
731	switch (why) {
732	case PWR_STANDBY:
733	case PWR_SUSPEND:
734	    break;
735	case PWR_RESUME:
736	    callout_reset(&sc->sc_adpoll, hz,
737			  vrpiu_start_powerstate, sc);
738	    break;
739	}
740}
741
742#ifdef DEBUG
743void
744vrpiu_dump_cntreg(cnt)
745	unsigned int cnt;
746{
747	printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
748	printf(" state=");
749	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
750	    printf("CmdScan");
751	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
752	    printf("IntervalNextScan");
753	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
754	    printf("PenDataScan");
755	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
756	    printf("WaitPenTouch");
757	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
758	    printf("???");
759	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
760	    printf("ADPortScan");
761	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
762	    printf("Standby");
763	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
764	    printf("Disable");
765	if (cnt & PIUCNT_PADATSTOP)
766	    printf(" AutoStop");
767	if (cnt & PIUCNT_PADATSTART)
768	    printf(" AutoStart");
769	if (cnt & PIUCNT_PADSCANSTOP)
770	    printf(" Stop");
771	if (cnt & PIUCNT_PADSCANSTART)
772	    printf(" Start");
773	if (cnt & PIUCNT_PADSCANTYPE)
774	    printf(" ScanPressure");
775	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
776	    printf(" A/D");
777	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
778	    printf(" Coordinate");
779	if (cnt & PIUCNT_PIUSEQEN)
780	    printf(" SeqEn");
781	if ((cnt & PIUCNT_PIUPWR) == 0)
782	    printf(" PowerOff");
783	if ((cnt & PIUCNT_PADRST) == 0)
784	    printf(" Reset");
785	printf("\n");
786}
787#endif
788