Home | History | Annotate | Line # | Download | only in vr
vrpiu.c revision 1.7
      1 /*	$NetBSD: vrpiu.c,v 1.7 2000/12/27 12:22:07 sato 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  * data types
     76  */
     77 /* struct vrpiu_softc is defined in vrpiuvar.h */
     78 
     79 /*
     80  * function prototypes
     81  */
     82 static int	vrpiumatch __P((struct device *, struct cfdata *, void *));
     83 static void	vrpiuattach __P((struct device *, struct device *, void *));
     84 
     85 static void	vrpiu_write __P((struct vrpiu_softc *, int, unsigned short));
     86 static u_short	vrpiu_read __P((struct vrpiu_softc *, int));
     87 
     88 static int	vrpiu_intr __P((void *));
     89 static void	vrpiu_tp_intr __P((struct vrpiu_softc *));
     90 static void	vrpiu_ad_intr __P((struct vrpiu_softc *));
     91 #ifdef DEBUG
     92 static void	vrpiu_dump_cntreg __P((unsigned int cmd));
     93 #endif
     94 
     95 static int	vrpiu_tp_enable __P((void *));
     96 static int	vrpiu_tp_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
     97 static void	vrpiu_tp_disable __P((void *));
     98 int		vrpiu_ad_enable __P((void *));
     99 void		vrpiu_ad_disable __P((void *));
    100 static void	vrpiu_start_powerstate __P((void *));
    101 static void	vrpiu_calc_powerstate __P((struct vrpiu_softc *));
    102 static void	vrpiu_power __P((int, void *));
    103 
    104 /* mra is defined in mra.c */
    105 int mra_Y_AX1_BX2_C __P((int *y, int ys, int *x1, int x1s, int *x2, int x2s,
    106 			 int n, int scale, int *a, int *b, int *c));
    107 
    108 /*
    109  * static or global variables
    110  */
    111 struct cfattach vrpiu_ca = {
    112 	sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
    113 };
    114 
    115 const struct wsmouse_accessops vrpiu_accessops = {
    116 	vrpiu_tp_enable,
    117 	vrpiu_tp_ioctl,
    118 	vrpiu_tp_disable,
    119 };
    120 
    121 int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
    122 
    123 /*
    124  * function definitions
    125  */
    126 static inline void
    127 vrpiu_write(sc, port, val)
    128 	struct vrpiu_softc *sc;
    129 	int port;
    130 	unsigned short val;
    131 {
    132 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
    133 }
    134 
    135 static inline u_short
    136 vrpiu_read(sc, port)
    137 	struct vrpiu_softc *sc;
    138 	int port;
    139 {
    140 	return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port);
    141 }
    142 
    143 static int
    144 vrpiumatch(parent, cf, aux)
    145 	struct device *parent;
    146 	struct cfdata *cf;
    147 	void *aux;
    148 {
    149 	return 1;
    150 }
    151 
    152 static void
    153 vrpiuattach(parent, self, aux)
    154 	struct device *parent;
    155 	struct device *self;
    156 	void *aux;
    157 {
    158 	struct vrpiu_softc *sc = (struct vrpiu_softc *)self;
    159 	struct vrip_attach_args *va = aux;
    160 	struct wsmousedev_attach_args wsmaa;
    161 
    162 	bus_space_tag_t iot = va->va_iot;
    163 	bus_space_handle_t ioh;
    164 
    165 	if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
    166 		printf(": can't map bus space\n");
    167 		return;
    168 	}
    169 
    170 	sc->sc_iot = iot;
    171 	sc->sc_ioh = ioh;
    172 	sc->sc_vrip = va->va_vc;
    173 
    174 	/*
    175 	 * disable device until vrpiu_enable called
    176 	 */
    177 	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
    178 
    179 	tpcalib_init(&sc->sc_tpcalib);
    180 #if 1
    181 	/*
    182 	 * XXX, calibrate parameters
    183 	 */
    184 	{
    185 		int i;
    186 		static const struct {
    187 			platid_mask_t *mask;
    188 			struct wsmouse_calibcoords coords;
    189 		} calibrations[] = {
    190 			{ &platid_mask_MACH_NEC_MCR_700A,
    191 				{ 0, 0, 799, 599,
    192 				  4,
    193 				{ { 115,  80,   0,   0 },
    194 				  { 115, 966,   0, 599 },
    195 				  { 912,  80, 799,   0 },
    196 				  { 912, 966, 799, 599 } } } },
    197 
    198 			{ NULL,		/* samples got on my MC-R500 */
    199 				{ 0, 0, 639, 239,
    200 				5,
    201 				{ { 502, 486, 320, 120 },
    202 				  {  55, 109,   0,   0 },
    203 				  {  54, 913,   0, 239 },
    204 				  { 973, 924, 639, 239 },
    205 				  { 975, 123, 639,   0 } } } },
    206 		};
    207 		for (i = 0; ; i++) {
    208 			if (calibrations[i].mask == NULL
    209 			    || platid_match(&platid, calibrations[i].mask))
    210 				break;
    211 		}
    212 		tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
    213 			      (caddr_t)&calibrations[i].coords, 0, 0);
    214 	}
    215 #endif
    216 
    217 	/* install interrupt handler and enable interrupt */
    218 	if (!(sc->sc_handler =
    219 	      vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
    220 				  vrpiu_intr, sc))) {
    221 		printf (": can't map interrupt line.\n");
    222 		return;
    223 	}
    224 
    225 	/* mask level2 interrupt, stop scan sequencer and mask clock to piu */
    226 	vrpiu_tp_disable(sc);
    227 
    228 	printf("\n");
    229 
    230 	wsmaa.accessops = &vrpiu_accessops;
    231 	wsmaa.accesscookie = sc;
    232 
    233 	/*
    234 	 * attach the wsmouse
    235 	 */
    236 	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
    237 
    238 	/*
    239 	 * power management events
    240 	 */
    241 	sc->sc_power_hook = powerhook_establish(vrpiu_power, sc);
    242 
    243 	/*
    244 	 * init A/D port polling.
    245 	 */
    246 	sc->sc_battery.n_values = 3;
    247 	sc->sc_battery.value[0] = -1;
    248 	sc->sc_battery.value[1] = -1;
    249 	sc->sc_battery.value[2] = -1;
    250 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
    251 	callout_init(&sc->sc_adpoll);
    252 	callout_reset(&sc->sc_adpoll, hz,
    253 			  vrpiu_start_powerstate, sc);
    254 }
    255 
    256 int
    257 vrpiu_ad_enable(v)
    258 	void *v;
    259 {
    260 	struct vrpiu_softc *sc = v;
    261 	int s;
    262 	unsigned int cnt;
    263 
    264 	DPRINTF(("%s(%d): vrpiu_ad_enable()\n", __FILE__, __LINE__));
    265 	if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
    266 		return EBUSY;
    267 
    268 	/* supply clock to PIU */
    269 	__vrcmu_supply(CMUMSKPIU, 1);
    270 
    271 	/* Scan interval 0x7FF is maximum value */
    272 	vrpiu_write(sc, PIUSIVL_REG_W, 0x7FF);
    273 
    274 	s = spltty();
    275 
    276 	/* clear interrupt status */
    277 	vrpiu_write(sc, PIUINT_REG_W, PIUINT_PADADPINTR);
    278 
    279 	/* Disable -> Standby */
    280 	cnt = PIUCNT_PIUPWR |
    281 		PIUCNT_PIUMODE_COORDINATE |
    282 		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
    283 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    284 
    285 	/* Level2 interrupt register setting */
    286 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_PADADPINTR, 1);
    287 
    288 	/* save pen status, touch or release */
    289 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    290 
    291 	/*
    292 	 * Enable scan sequencer operation
    293 	 * Standby -> WaitPenTouch
    294 	 */
    295 	cnt |= PIUCNT_PIUSEQEN;
    296 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    297 
    298 	sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
    299 
    300 	splx(s);
    301 
    302 	return 0;
    303 }
    304 
    305 void
    306 vrpiu_ad_disable(v)
    307 	void *v;
    308 {
    309 	struct vrpiu_softc *sc = v;
    310 
    311 	DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
    312 
    313 	/* Set level2 interrupt register to mask interrupts */
    314 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_PADADPINTR, 0);
    315 
    316 	sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
    317 
    318 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
    319 		/* Disable scan sequencer operation and power off */
    320 		vrpiu_write(sc, PIUCNT_REG_W, 0);
    321 
    322 		/* mask clock to PIU */
    323 		__vrcmu_supply(CMUMSKPIU, 1);
    324 	}
    325 }
    326 
    327 int
    328 vrpiu_tp_enable(v)
    329 	void *v;
    330 {
    331 	struct vrpiu_softc *sc = v;
    332 	int s;
    333 	unsigned int cnt;
    334 
    335 	DPRINTF(("%s(%d): vrpiu_tp_enable()\n", __FILE__, __LINE__));
    336 	if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE)
    337 		return EBUSY;
    338 
    339 	/* supply clock to PIU */
    340 	__vrcmu_supply(CMUMSKPIU, 1);
    341 
    342 	/* Scan interval 0x7FF is maximum value */
    343 	vrpiu_write(sc, PIUSIVL_REG_W, 0x7FF);
    344 
    345 	s = spltty();
    346 
    347 	/* clear interrupt status */
    348 	vrpiu_write(sc, PIUINT_REG_W, PIUINT_ALLINTR&~PIUINT_PADADPINTR);
    349 
    350 	/* Disable -> Standby */
    351 	cnt = PIUCNT_PIUPWR |
    352 		PIUCNT_PIUMODE_COORDINATE |
    353 		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
    354 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    355 
    356 	/* Level2 interrupt register setting */
    357 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR&~PIUINT_PADADPINTR, 1);
    358 
    359 	/* save pen status, touch or release */
    360 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    361 
    362 	/*
    363 	 * Enable scan sequencer operation
    364 	 * Standby -> WaitPenTouch
    365 	 */
    366 	cnt |= PIUCNT_PIUSEQEN;
    367 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    368 
    369 	/* transit status DISABLE -> TOUCH or RELEASE */
    370 	sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ?
    371 		VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE;
    372 
    373 	splx(s);
    374 
    375 	return 0;
    376 }
    377 
    378 void
    379 vrpiu_tp_disable(v)
    380 	void *v;
    381 {
    382 	struct vrpiu_softc *sc = v;
    383 
    384 	DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
    385 
    386 	/* Set level2 interrupt register to mask interrupts */
    387 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR&~PIUINT_PADADPINTR, 0);
    388 
    389 	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
    390 
    391 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
    392 		/* Disable scan sequencer operation and power off */
    393 		vrpiu_write(sc, PIUCNT_REG_W, 0);
    394 
    395 		/* mask clock to PIU */
    396 		__vrcmu_supply(CMUMSKPIU, 1);
    397 	}
    398 }
    399 
    400 int
    401 vrpiu_tp_ioctl(v, cmd, data, flag, p)
    402 	void *v;
    403 	u_long cmd;
    404 	caddr_t data;
    405 	int flag;
    406 	struct proc *p;
    407 {
    408 	struct vrpiu_softc *sc = v;
    409 
    410 	DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
    411 
    412 	switch (cmd) {
    413 	case WSMOUSEIO_GTYPE:
    414 		*(u_int *)data = WSMOUSE_TYPE_TPANEL;
    415 		break;
    416 
    417 	case WSMOUSEIO_SRES:
    418 		printf("%s(%d): WSMOUSRIO_SRES is not supported",
    419 		       __FILE__, __LINE__);
    420 		break;
    421 
    422 	case WSMOUSEIO_SCALIBCOORDS:
    423 	case WSMOUSEIO_GCALIBCOORDS:
    424                 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
    425 
    426 	default:
    427 		return (-1);
    428 	}
    429 	return (0);
    430 }
    431 
    432 /*
    433  * PIU AD interrupt handler.
    434  */
    435 void
    436 vrpiu_ad_intr(sc)
    437 	struct vrpiu_softc *sc;
    438 {
    439 	unsigned int i;
    440 	unsigned int intrstat;
    441 
    442 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
    443 
    444 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
    445 		/*
    446 		 * the device isn't enabled. just clear interrupt.
    447 		 */
    448 		vrpiu_write(sc, PIUINT_REG_W, PIUINT_PADADPINTR);
    449 		return;
    450 	}
    451 
    452 	if (intrstat & PIUINT_PADADPINTR) {
    453 		sc->sc_battery.value[0] = (unsigned int)vrpiu_read(sc, PIUAB(0));
    454 		sc->sc_battery.value[1] = (unsigned int)vrpiu_read(sc, PIUAB(1));
    455 		sc->sc_battery.value[2] = (unsigned int)vrpiu_read(sc, PIUAB(2));
    456 	}
    457 
    458 	if (intrstat & PIUINT_PADADPINTR) {
    459 		for (i = 0; i < 3; i++) {
    460 			if (sc->sc_battery.value[i] & PIUAB_VALID)
    461 				sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
    462 			else
    463 				sc->sc_battery.value[i] = 0;
    464 		}
    465 		vrpiu_calc_powerstate(sc);
    466 	}
    467 	vrpiu_write(sc, PIUINT_REG_W, PIUINT_PADADPINTR);
    468 
    469 	return;
    470 }
    471 /*
    472  * PIU TP interrupt handler.
    473  */
    474 void
    475 vrpiu_tp_intr(sc)
    476 	struct vrpiu_softc *sc;
    477 {
    478 	unsigned int cnt, i;
    479 	unsigned int intrstat, page;
    480 	int tpx0, tpx1, tpy0, tpy1;
    481 	int x, y, xraw, yraw;
    482 
    483 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
    484 
    485 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
    486 	/*
    487 		 * the device isn't enabled. just clear interrupt.
    488 		 */
    489 		vrpiu_write(sc, PIUINT_REG_W, intrstat&~PIUINT_PADADPINTR);
    490 		return;
    491 	}
    492 
    493 	page = (intrstat & PIUINT_OVP) ? 1 : 0;
    494 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
    495 		tpx0 = vrpiu_read(sc, PIUPB(page, 0));
    496 		tpx1 = vrpiu_read(sc, PIUPB(page, 1));
    497 		tpy0 = vrpiu_read(sc, PIUPB(page, 2));
    498 		tpy1 = vrpiu_read(sc, PIUPB(page, 3));
    499 	}
    500 
    501 	if (intrstat & PIUINT_PADDLOSTINTR) {
    502 		page = page ? 0 : 1;
    503 		for (i = 0; i < 4; i++)
    504 			vrpiu_read(sc, PIUPB(page, i));
    505 	}
    506 
    507 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    508 #ifdef DEBUG
    509 	if (vrpiu_debug)
    510 		vrpiu_dump_cntreg(cnt);
    511 #endif
    512 
    513 	/* clear interrupt status */
    514 	vrpiu_write(sc, PIUINT_REG_W, intrstat&~PIUINT_PADADPINTR);
    515 
    516 #if 0
    517 	DPRINTF(("vrpiu_intr: OVP=%d", page));
    518 	if (intrstat & PIUINT_PADCMDINTR)
    519 		DPRINTF((" CMD"));
    520 	if (intrstat & PIUINT_PADADPINTR)
    521 		DPRINTF((" A/D"));
    522 	if (intrstat & PIUINT_PADPAGE1INTR)
    523 		DPRINTF((" PAGE1"));
    524 	if (intrstat & PIUINT_PADPAGE0INTR)
    525 		DPRINTF((" PAGE0"));
    526 	if (intrstat & PIUINT_PADDLOSTINTR)
    527 		DPRINTF((" DLOST"));
    528 	if (intrstat & PIUINT_PENCHGINTR)
    529 		DPRINTF((" PENCHG"));
    530 	DPRINTF(("\n"));
    531 #endif
    532 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
    533 		if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
    534 		      (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
    535 			printf("vrpiu: internal error, data is not valid!\n");
    536 		} else {
    537 			tpx0 &= PIUPB_PADDATA_MASK;
    538 			tpx1 &= PIUPB_PADDATA_MASK;
    539 			tpy0 &= PIUPB_PADDATA_MASK;
    540 			tpy1 &= PIUPB_PADDATA_MASK;
    541 #define ISVALID(n, c, m)	((c) - (m) < (n) && (n) < (c) + (m))
    542 			if (ISVALID(tpx0 + tpx1, 1024, 200) &&
    543 			    ISVALID(tpx0 + tpx1, 1024, 200)) {
    544 #if 0
    545 				DPRINTF(("%04x %04x %04x %04x\n",
    546 					 tpx0, tpx1, tpy0, tpy1));
    547 				DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0,
    548 					 tpx0 + tpx1, tpy0 + tpy1));
    549 #endif
    550 				xraw = tpy1 * 1024 / (tpy0 + tpy1);
    551 				yraw = tpx1 * 1024 / (tpx0 + tpx1);
    552 				DPRINTF(("%3d %3d", xraw, yraw));
    553 
    554 				tpcalib_trans(&sc->sc_tpcalib,
    555 					      xraw, yraw, &x, &y);
    556 
    557 				DPRINTF(("->%4d %4d", x, y));
    558 				wsmouse_input(sc->sc_wsmousedev,
    559 					      (cnt & PIUCNT_PENSTC) ? 1 : 0,
    560 					      x, /* x */
    561 					      y, /* y */
    562 					      0, /* z */
    563 					      WSMOUSE_INPUT_ABSOLUTE_X |
    564 					      WSMOUSE_INPUT_ABSOLUTE_Y);
    565 				DPRINTF(("\n"));
    566 			}
    567 		}
    568 	}
    569 
    570 	if (cnt & PIUCNT_PENSTC) {
    571 		if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
    572 			/*
    573 			 * pen touch
    574 			 */
    575 			DPRINTF(("PEN TOUCH\n"));
    576 			sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
    577 			/*
    578 			 * We should not report button down event while
    579 			 * we don't know where it occur.
    580 			 */
    581 		}
    582 	} else {
    583 		if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
    584 			/*
    585 			 * pen release
    586 			 */
    587 			DPRINTF(("RELEASE\n"));
    588 			sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
    589 			/* button 0 UP */
    590 			wsmouse_input(sc->sc_wsmousedev,
    591 				      0,
    592 				      0, 0, 0, 0);
    593 		}
    594 	}
    595 
    596 	if (intrstat & PIUINT_PADDLOSTINTR) {
    597 		cnt |= PIUCNT_PIUSEQEN;
    598 		vrpiu_write(sc, PIUCNT_REG_W, cnt);
    599 	}
    600 
    601 	return;
    602 }
    603 
    604 /*
    605  * PIU interrupt handler.
    606  */
    607 int
    608 vrpiu_intr(arg)
    609 	void *arg;
    610 {
    611         struct vrpiu_softc *sc = arg;
    612 
    613 	vrpiu_ad_intr(sc);
    614 	vrpiu_tp_intr(sc);
    615 
    616 	return 0;
    617 }
    618 
    619 void
    620 vrpiu_start_powerstate(v)
    621 	void *v;
    622 {
    623 	int mask;
    624 	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
    625 
    626 	vrpiu_ad_enable(sc);
    627 	mask = vrpiu_read(sc, PIUAMSK_REG_W);
    628 	mask &= 0xff8f; /* XXX */
    629 	vrpiu_write(sc, PIUAMSK_REG_W, mask);
    630 	vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
    631 	/*
    632 	 * restart next A/D polling
    633 	 */
    634 	callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
    635 			 vrpiu_start_powerstate, sc);
    636 }
    637 
    638 void
    639 vrpiu_calc_powerstate(sc)
    640 	struct vrpiu_softc *sc;
    641 {
    642 	extern void vrgiu_diff_io __P((void));
    643 	vrpiu_ad_disable(sc);
    644 	VPRINTF(("vrpiu:AD: %d, %d, %d\n",
    645 		sc->sc_battery.value[0],
    646 		sc->sc_battery.value[1],
    647 		sc->sc_battery.value[2]));
    648 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
    649 #ifdef notyet
    650 	config_hook_call(CONFIG_HOOK_SET,
    651 			 CONFIG_HOOK_BATTERYVAL,
    652 			 (void *)&sc->sc_battery);
    653 #endif /* notyet */
    654 	/*
    655 	 * restart next A/D polling if change polling timming.
    656 	 */
    657 	if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
    658 		callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
    659 				 vrpiu_start_powerstate, sc);
    660 	if (bootverbose)
    661 		vrgiu_diff_io();
    662 
    663 }
    664 
    665 static void
    666 vrpiu_power(why, arg)
    667 	int why;
    668 	void *arg;
    669 {
    670 	struct vrpiu_softc *sc = arg;
    671 
    672 	switch (why) {
    673 	case PWR_STANDBY:
    674 	case PWR_SUSPEND:
    675 		break;
    676 	case PWR_RESUME:
    677 		callout_reset(&sc->sc_adpoll, hz,
    678 				  vrpiu_start_powerstate, sc);
    679 		break;
    680 	}
    681 }
    682 
    683 #ifdef DEBUG
    684 void
    685 vrpiu_dump_cntreg(cnt)
    686 	unsigned int cnt;
    687 {
    688 	printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
    689 	printf(" state=");
    690 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
    691 		printf("CmdScan");
    692 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
    693 		printf("IntervalNextScan");
    694 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
    695 		printf("PenDataScan");
    696 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
    697 		printf("WaitPenTouch");
    698 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
    699 		printf("???");
    700 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
    701 		printf("ADPortScan");
    702 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
    703 		printf("Standby");
    704 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
    705 		printf("Disable");
    706 	if (cnt & PIUCNT_PADATSTOP)
    707 		printf(" AutoStop");
    708 	if (cnt & PIUCNT_PADATSTART)
    709 		printf(" AutoStart");
    710 	if (cnt & PIUCNT_PADSCANSTOP)
    711 		printf(" Stop");
    712 	if (cnt & PIUCNT_PADSCANSTART)
    713 		printf(" Start");
    714 	if (cnt & PIUCNT_PADSCANTYPE)
    715 		printf(" ScanPressure");
    716 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
    717 		printf(" A/D");
    718 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
    719 		printf(" Coordinate");
    720 	if (cnt & PIUCNT_PIUSEQEN)
    721 		printf(" SeqEn");
    722 	if ((cnt & PIUCNT_PIUPWR) == 0)
    723 		printf(" PowerOff");
    724 	if ((cnt & PIUCNT_PADRST) == 0)
    725 		printf(" Reset");
    726 	printf("\n");
    727 }
    728 #endif
    729