Home | History | Annotate | Line # | Download | only in vr
vrpiu.c revision 1.16
      1 /*	$NetBSD: vrpiu.c,v 1.16 2001/09/24 14:29:30 takemura Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1999-2001 Shin Takemura All rights reserved.
      5  * Copyright (c) 2000-2001 SATO Kazumi, All rights reserved.
      6  * Copyright (c) 1999-2001 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 <dev/hpc/tpcalibvar.h>
     51 
     52 #include <dev/hpc/hpcbatteryvar.h>
     53 #include <dev/hpc/hpcbatterytable.h>
     54 
     55 #include <hpcmips/hpcmips/machdep.h>
     56 #include <hpcmips/vr/vripvar.h>
     57 #include <hpcmips/vr/cmureg.h>
     58 #include <hpcmips/vr/vrpiuvar.h>
     59 #include <hpcmips/vr/vrpiureg.h>
     60 
     61 /*
     62  * contant and macro definitions
     63  */
     64 #define VRPIUDEBUG
     65 #ifdef VRPIUDEBUG
     66 int	vrpiu_debug = 0;
     67 #define	DPRINTF(arg) if (vrpiu_debug) printf arg;
     68 #define	VPRINTF(arg) if (bootverbose || vrpiu_debug) printf arg;
     69 #else
     70 #define	DPRINTF(arg)
     71 #define	VPRINTF(arg) if (bootverbose) printf arg;
     72 #endif
     73 
     74 #ifndef VRPIU_NO_ADHOC_BATTERY_EVENT
     75 #define VRPIU_ADHOC_BATTERY_EVENT	/* currently... */
     76 #endif /* VRPIU_NO_ADHOC_BATTERY_EVENT */
     77 
     78 #ifndef VRPIU_AD_POLL_INTERVAL
     79 #define VRPIU_AD_POLL_INTERVAL	60	/* interval is 60 sec */
     80 #endif /* VRPIU_AD_POLL_INTERTVAL */
     81 
     82 #define	PIUSIVL_SCANINTVAL_MIN	333			/* 10msec	*/
     83 #define	PIUSIVL_SCANINTVAL_MAX	PIUSIVL_SCANINTVAL_MASK	/* 60msec	*/
     84 #define VRPIU_TP_SCAN_TIMEOUT	(hz/10)		/* timeout is 100msec	*/
     85 
     86 #define TP_INTR	(PIUINT_ALLINTR & ~PIUINT_PADADPINTR)
     87 #define AD_INTR	(PIUINT_PADADPINTR)
     88 
     89 /*
     90  * data types
     91  */
     92 /* struct vrpiu_softc is defined in vrpiuvar.h */
     93 
     94 /*
     95  * function prototypes
     96  */
     97 static int	vrpiumatch(struct device *, struct cfdata *, void *);
     98 static void	vrpiuattach(struct device *, struct device *, void *);
     99 
    100 static void	vrpiu_write(struct vrpiu_softc *, int, unsigned short);
    101 static u_short	vrpiu_read(struct vrpiu_softc *, int);
    102 
    103 static int	vrpiu_intr(void *);
    104 static void	vrpiu_tp_intr(struct vrpiu_softc *);
    105 static void	vrpiu_ad_intr(struct vrpiu_softc *);
    106 #ifdef DEBUG
    107 static void	vrpiu_dump_cntreg(unsigned int);
    108 #endif
    109 
    110 static int	vrpiu_tp_enable(void *);
    111 static int	vrpiu_tp_ioctl(void *, u_long, caddr_t, int, struct proc *);
    112 static void	vrpiu_tp_disable(void *);
    113 static void	vrpiu_tp_up(struct vrpiu_softc *);
    114 static void	vrpiu_tp_timeout(void *);
    115 int		vrpiu_ad_enable(void *);
    116 void		vrpiu_ad_disable(void *);
    117 static void	vrpiu_start_powerstate(void *);
    118 static void	vrpiu_calc_powerstate(struct vrpiu_softc *);
    119 static void	vrpiu_send_battery_event(struct vrpiu_softc *);
    120 static void	vrpiu_power(int, void *);
    121 static u_int	scan_interval(u_int data);
    122 
    123 /* mra is defined in mra.c */
    124 int mra_Y_AX1_BX2_C(int *y, int ys, int *x1, int x1s, int *x2, int x2s,
    125     int n, int scale, int *a, int *b, int *c);
    126 
    127 /*
    128  * static or global variables
    129  */
    130 struct cfattach vrpiu_ca = {
    131 	sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach
    132 };
    133 
    134 const struct wsmouse_accessops vrpiu_accessops = {
    135 	vrpiu_tp_enable,
    136 	vrpiu_tp_ioctl,
    137 	vrpiu_tp_disable,
    138 };
    139 
    140 int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL;
    141 
    142 /*
    143  * function definitions
    144  */
    145 static inline void
    146 vrpiu_write(struct vrpiu_softc *sc, int port, unsigned short val)
    147 {
    148 
    149 	bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val);
    150 }
    151 
    152 static inline u_short
    153 vrpiu_read(struct vrpiu_softc *sc, int port)
    154 {
    155 
    156 	return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port));
    157 }
    158 
    159 static int
    160 vrpiumatch(struct device *parent, struct cfdata *cf, void *aux)
    161 {
    162 
    163 	return (1);
    164 }
    165 
    166 static void
    167 vrpiuattach(struct device *parent, struct device *self, void *aux)
    168 {
    169 	struct vrpiu_softc *sc = (struct vrpiu_softc *)self;
    170 	struct vrip_attach_args *va = aux;
    171 	struct wsmousedev_attach_args wsmaa;
    172 
    173 	bus_space_tag_t iot = va->va_iot;
    174 	bus_space_handle_t ioh;
    175 	struct platid_data *p;
    176 
    177 	if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) {
    178 		printf(": can't map bus space\n");
    179 		return;
    180 	}
    181 
    182 	sc->sc_iot = iot;
    183 	sc->sc_ioh = ioh;
    184 	sc->sc_vrip = va->va_vc;
    185 
    186 	sc->sc_interval = scan_interval(WSMOUSE_RES_DEFAULT);
    187 	if ((p = platid_search_data(&platid, hpcbattery_parameters)) == NULL)
    188 		sc->sc_battery_spec = NULL;
    189 	else
    190 		sc->sc_battery_spec  = p->data;
    191 
    192 	/*
    193 	 * disable device until vrpiu_enable called
    194 	 */
    195 	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
    196 
    197 	/* initialize touch panel timeout structure	*/
    198 	callout_init(&sc->sc_tptimeout);
    199 
    200 	/* initialize calibration context	*/
    201 	tpcalib_init(&sc->sc_tpcalib);
    202 #if 1
    203 	/*
    204 	 * XXX, calibrate parameters
    205 	 */
    206 	{
    207 		int i;
    208 		static const struct {
    209 			platid_mask_t *mask;
    210 			struct wsmouse_calibcoords coords;
    211 		} calibrations[] = {
    212 			{ &platid_mask_MACH_NEC_MCR_700,
    213 			  { 0, 0, 799, 599,
    214 			    4,
    215 			    { { 115,  80,   0,   0 },
    216 			      { 115, 966,   0, 599 },
    217 			      { 912,  80, 799,   0 },
    218 			      { 912, 966, 799, 599 } } } },
    219 			{ &platid_mask_MACH_NEC_MCR_700A,
    220 			  { 0, 0, 799, 599,
    221 			    4,
    222 			    { { 115,  80,   0,   0 },
    223 			      { 115, 966,   0, 599 },
    224 			      { 912,  80, 799,   0 },
    225 			      { 912, 966, 799, 599 } } } },
    226 			{ &platid_mask_MACH_NEC_MCR_730,
    227 			  { 0, 0, 799, 599,
    228 			    4,
    229 			    { { 115,  80,   0,   0 },
    230 			      { 115, 966,   0, 599 },
    231 			      { 912,  80, 799,   0 },
    232 			      { 912, 966, 799, 599 } } } },
    233 			{ NULL,		/* samples got on my MC-R500 */
    234 			  { 0, 0, 639, 239,
    235 			    5,
    236 			    { { 502, 486, 320, 120 },
    237 			      {  55, 109,   0,   0 },
    238 			      {  54, 913,   0, 239 },
    239 			      { 973, 924, 639, 239 },
    240 			      { 975, 123, 639,   0 } } } },
    241 		};
    242 		for (i = 0; ; i++) {
    243 			if (calibrations[i].mask == NULL
    244 			    || platid_match(&platid, calibrations[i].mask))
    245 				break;
    246 		}
    247 		tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
    248 		    (caddr_t)&calibrations[i].coords, 0, 0);
    249 	}
    250 #endif
    251 
    252 	/* install interrupt handler and enable interrupt */
    253 	if (!(sc->sc_handler =
    254 	    vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
    255 		vrpiu_intr, sc))) {
    256 		printf (": can't map interrupt line.\n");
    257 		return;
    258 	}
    259 
    260 	/* mask level2 interrupt, stop scan sequencer and mask clock to piu */
    261 	vrpiu_tp_disable(sc);
    262 
    263 	printf("\n");
    264 
    265 	wsmaa.accessops = &vrpiu_accessops;
    266 	wsmaa.accesscookie = sc;
    267 
    268 	/*
    269 	 * attach the wsmouse
    270 	 */
    271 	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
    272 
    273 	/*
    274 	 * power management events
    275 	 */
    276 	sc->sc_power_hook = powerhook_establish(vrpiu_power, sc);
    277 
    278 	/*
    279 	 * init A/D port polling.
    280 	 */
    281 	sc->sc_battery.n_values = 3;
    282 	sc->sc_battery.value[0] = -1;
    283 	sc->sc_battery.value[1] = -1;
    284 	sc->sc_battery.value[2] = -1;
    285 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
    286 	callout_init(&sc->sc_adpoll);
    287 	callout_reset(&sc->sc_adpoll, hz, vrpiu_start_powerstate, sc);
    288 }
    289 
    290 /*
    291  * calculate interval value
    292  *  input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
    293  * output: value for PIUSIVL_REG
    294  */
    295 static u_int
    296 scan_interval(u_int data)
    297 {
    298 	int scale;
    299 
    300 	if (data < WSMOUSE_RES_MIN)
    301 		data = WSMOUSE_RES_MIN;
    302 
    303 	if (WSMOUSE_RES_MAX < data)
    304 		data = WSMOUSE_RES_MAX;
    305 
    306 	scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN;
    307 	data += WSMOUSE_RES_MIN;
    308 
    309 	return PIUSIVL_SCANINTVAL_MIN +
    310 	    (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) *
    311 	    (scale - data) / scale;
    312 }
    313 
    314 int
    315 vrpiu_ad_enable(void *v)
    316 {
    317 	struct vrpiu_softc *sc = v;
    318 	int s;
    319 	unsigned int cnt;
    320 
    321 	DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
    322 	    __FILE__, __LINE__, sc->sc_interval));
    323 	if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
    324 		return EBUSY;
    325 
    326 	/* supply clock to PIU */
    327 	__vrcmu_supply(CMUMSKPIU, 1);
    328 
    329 	/* set scan interval */
    330 	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
    331 
    332 	s = spltty();
    333 
    334 	/* clear interrupt status */
    335 	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
    336 
    337 	/* Disable -> Standby */
    338 	cnt = PIUCNT_PIUPWR |
    339 	    PIUCNT_PIUMODE_COORDINATE |
    340 	    PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
    341 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    342 
    343 	/* Level2 interrupt register setting */
    344 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1);
    345 
    346 	/* save pen status, touch or release */
    347 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    348 
    349 	/*
    350 	 * Enable scan sequencer operation
    351 	 * Standby -> WaitPenTouch
    352 	 */
    353 	cnt |= PIUCNT_PIUSEQEN;
    354 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    355 
    356 	sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
    357 
    358 	splx(s);
    359 
    360 	return 0;
    361 }
    362 
    363 void
    364 vrpiu_ad_disable(void *v)
    365 {
    366 	struct vrpiu_softc *sc = v;
    367 
    368 	DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
    369 
    370 	/* Set level2 interrupt register to mask interrupts */
    371 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0);
    372 
    373 	sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
    374 
    375 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
    376 		/* Disable scan sequencer operation and power off */
    377 		vrpiu_write(sc, PIUCNT_REG_W, 0);
    378 
    379 		/* mask clock to PIU */
    380 		__vrcmu_supply(CMUMSKPIU, 0);
    381 	}
    382 }
    383 
    384 int
    385 vrpiu_tp_enable(void *v)
    386 {
    387 	struct vrpiu_softc *sc = v;
    388 	int s;
    389 	unsigned int cnt;
    390 
    391 	DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n",
    392 	    __FILE__, __LINE__, sc->sc_interval));
    393 	if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE)
    394 		return EBUSY;
    395 
    396 	/* supply clock to PIU */
    397 	__vrcmu_supply(CMUMSKPIU, 1);
    398 
    399 	/* set scan interval */
    400 	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
    401 
    402 	s = spltty();
    403 
    404 	/* clear interrupt status */
    405 	vrpiu_write(sc, PIUINT_REG_W, TP_INTR);
    406 
    407 	/* Disable -> Standby */
    408 	cnt = PIUCNT_PIUPWR |
    409 	    PIUCNT_PIUMODE_COORDINATE |
    410 	    PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
    411 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    412 
    413 	/* Level2 interrupt register setting */
    414 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1);
    415 
    416 	/* save pen status, touch or release */
    417 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    418 
    419 	/*
    420 	 * Enable scan sequencer operation
    421 	 * Standby -> WaitPenTouch
    422 	 */
    423 	cnt |= PIUCNT_PIUSEQEN;
    424 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    425 
    426 	/* transit status DISABLE -> TOUCH or RELEASE */
    427 	sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ?
    428 	    VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE;
    429 
    430 	splx(s);
    431 
    432 	return 0;
    433 }
    434 
    435 void
    436 vrpiu_tp_disable(void *v)
    437 {
    438 	struct vrpiu_softc *sc = v;
    439 
    440 	DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
    441 
    442 	/* Set level2 interrupt register to mask interrupts */
    443 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0);
    444 
    445 	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
    446 
    447 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
    448 		/* Disable scan sequencer operation and power off */
    449 		vrpiu_write(sc, PIUCNT_REG_W, 0);
    450 
    451 		/* mask clock to PIU */
    452 		__vrcmu_supply(CMUMSKPIU, 0);
    453 	}
    454 }
    455 
    456 int
    457 vrpiu_tp_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
    458 {
    459 	struct vrpiu_softc *sc = v;
    460 
    461 	DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
    462 
    463 	switch (cmd) {
    464 	case WSMOUSEIO_GTYPE:
    465 		*(u_int *)data = WSMOUSE_TYPE_TPANEL;
    466 		break;
    467 
    468 	case WSMOUSEIO_SRES:
    469 	{
    470 		int tp_enable;
    471 		int ad_enable;
    472 
    473 		tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE);
    474 		ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE);
    475 
    476 		if (tp_enable)
    477 			vrpiu_tp_disable(sc);
    478 		if (ad_enable)
    479 			vrpiu_ad_disable(sc);
    480 
    481 		sc->sc_interval = scan_interval(*(u_int *)data);
    482 		DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
    483 		    __FILE__, __LINE__, *(u_int *)data, sc->sc_interval));
    484 
    485 		if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN)
    486 			sc->sc_interval = PIUSIVL_SCANINTVAL_MIN;
    487 
    488 		if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval)
    489 			sc->sc_interval = PIUSIVL_SCANINTVAL_MAX;
    490 
    491 		if (tp_enable)
    492 			vrpiu_tp_enable(sc);
    493 		if (ad_enable)
    494 			vrpiu_ad_enable(sc);
    495 	}
    496 	break;
    497 
    498 	case WSMOUSEIO_SCALIBCOORDS:
    499 	case WSMOUSEIO_GCALIBCOORDS:
    500 		return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
    501 
    502 	default:
    503 		return (-1);
    504 	}
    505 	return (0);
    506 }
    507 
    508 /*
    509  * PIU AD interrupt handler.
    510  */
    511 void
    512 vrpiu_ad_intr(struct vrpiu_softc *sc)
    513 {
    514 	unsigned int i;
    515 	unsigned int intrstat;
    516 
    517 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
    518 
    519 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
    520 		/*
    521 		 * the device isn't enabled. just clear interrupt.
    522 		 */
    523 		vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
    524 		return;
    525 	}
    526 
    527 	if (intrstat & PIUINT_PADADPINTR) {
    528 		sc->sc_battery.value[0] = (unsigned int)
    529 		    vrpiu_read(sc, PIUAB(0));
    530 		sc->sc_battery.value[1] = (unsigned int)
    531 		    vrpiu_read(sc, PIUAB(1));
    532 		sc->sc_battery.value[2] = (unsigned int)
    533 		    vrpiu_read(sc, PIUAB(2));
    534 	}
    535 
    536 	if (intrstat & PIUINT_PADADPINTR) {
    537 		for (i = 0; i < 3; i++) {
    538 			if (sc->sc_battery.value[i] & PIUAB_VALID)
    539 				sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
    540 			else
    541 				sc->sc_battery.value[i] = 0;
    542 		}
    543 		vrpiu_calc_powerstate(sc);
    544 	}
    545 	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
    546 
    547 	return;
    548 }
    549 /*
    550  * PIU TP interrupt handler.
    551  */
    552 void
    553 vrpiu_tp_intr(struct vrpiu_softc *sc)
    554 {
    555 	unsigned int cnt, i;
    556 	unsigned int intrstat, page;
    557 	int tpx0, tpx1, tpy0, tpy1;
    558 	int x, y, xraw, yraw;
    559 
    560 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
    561 
    562 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
    563 		/*
    564 		 * the device isn't enabled. just clear interrupt.
    565 		 */
    566 		vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
    567 		return;
    568 	}
    569 
    570 	page = (intrstat & PIUINT_OVP) ? 1 : 0;
    571 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
    572 		tpx0 = vrpiu_read(sc, PIUPB(page, 0));
    573 		tpx1 = vrpiu_read(sc, PIUPB(page, 1));
    574 		tpy0 = vrpiu_read(sc, PIUPB(page, 2));
    575 		tpy1 = vrpiu_read(sc, PIUPB(page, 3));
    576 	}
    577 
    578 	if (intrstat & PIUINT_PADDLOSTINTR) {
    579 		page = page ? 0 : 1;
    580 		for (i = 0; i < 4; i++)
    581 			vrpiu_read(sc, PIUPB(page, i));
    582 	}
    583 
    584 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    585 #ifdef DEBUG
    586 	if (vrpiu_debug)
    587 		vrpiu_dump_cntreg(cnt);
    588 #endif
    589 
    590 	/* clear interrupt status */
    591 	vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
    592 
    593 #if 0
    594 	DPRINTF(("vrpiu_intr: OVP=%d", page));
    595 	if (intrstat & PIUINT_PADCMDINTR)
    596 		DPRINTF((" CMD"));
    597 	if (intrstat & PIUINT_PADADPINTR)
    598 		DPRINTF((" A/D"));
    599 	if (intrstat & PIUINT_PADPAGE1INTR)
    600 		DPRINTF((" PAGE1"));
    601 	if (intrstat & PIUINT_PADPAGE0INTR)
    602 		DPRINTF((" PAGE0"));
    603 	if (intrstat & PIUINT_PADDLOSTINTR)
    604 		DPRINTF((" DLOST"));
    605 	if (intrstat & PIUINT_PENCHGINTR)
    606 		DPRINTF((" PENCHG"));
    607 	DPRINTF(("\n"));
    608 #endif
    609 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
    610 		/*
    611 		 * just ignore scan data if status isn't Touch.
    612 		 */
    613 		if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
    614 			/* reset tp scan timeout	*/
    615 			callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
    616 			    vrpiu_tp_timeout, sc);
    617 
    618 			if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
    619 			    (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
    620 				printf("vrpiu: internal error,"
    621 				    " data is not valid!\n");
    622 			} else {
    623 				tpx0 &= PIUPB_PADDATA_MASK;
    624 				tpx1 &= PIUPB_PADDATA_MASK;
    625 				tpy0 &= PIUPB_PADDATA_MASK;
    626 				tpy1 &= PIUPB_PADDATA_MASK;
    627 #define ISVALID(n, c, m)	((c) - (m) < (n) && (n) < (c) + (m))
    628 				if (ISVALID(tpx0 + tpx1, 1024, 200) &&
    629 				    ISVALID(tpy0 + tpy1, 1024, 200)) {
    630 #if 0
    631 					DPRINTF(("%04x %04x %04x %04x\n",
    632 					    tpx0, tpx1, tpy0, tpy1));
    633 					DPRINTF(("%3d %3d (%4d %4d)->", tpx0,
    634 					    tpy0, tpx0 + tpx1, tpy0 + tpy1));
    635 #endif
    636 					xraw = tpy1 * 1024 / (tpy0 + tpy1);
    637 					yraw = tpx1 * 1024 / (tpx0 + tpx1);
    638 					DPRINTF(("%3d %3d", xraw, yraw));
    639 
    640 					tpcalib_trans(&sc->sc_tpcalib, xraw,
    641 					    yraw, &x, &y);
    642 
    643 					DPRINTF(("->%4d %4d", x, y));
    644 					wsmouse_input(sc->sc_wsmousedev,
    645 					    1, /* button 0 down */
    646 					    x, /* x */
    647 					    y, /* y */
    648 					    0, /* z */
    649 					    WSMOUSE_INPUT_ABSOLUTE_X |
    650 					    WSMOUSE_INPUT_ABSOLUTE_Y);
    651 					DPRINTF(("\n"));
    652 				}
    653 			}
    654 		}
    655 	}
    656 
    657 	if (cnt & PIUCNT_PENSTC) {
    658 		if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
    659 			/*
    660 			 * pen touch
    661 			 */
    662 			DPRINTF(("PEN TOUCH\n"));
    663 			sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
    664 			/*
    665 			 * We should not report button down event while
    666 			 * we don't know where it occur.
    667 			 */
    668 
    669 			/* set tp scan timeout	*/
    670 			callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
    671 			    vrpiu_tp_timeout, sc);
    672 		}
    673 	} else {
    674 		vrpiu_tp_up(sc);
    675 	}
    676 
    677 	if (intrstat & PIUINT_PADDLOSTINTR) {
    678 		cnt |= PIUCNT_PIUSEQEN;
    679 		vrpiu_write(sc, PIUCNT_REG_W, cnt);
    680 	}
    681 
    682 	return;
    683 }
    684 
    685 void
    686 vrpiu_tp_up(struct vrpiu_softc *sc)
    687 {
    688 	if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
    689 		/*
    690 		 * pen release
    691 		 */
    692 		DPRINTF(("RELEASE\n"));
    693 		sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
    694 
    695 		/* clear tp scan timeout	*/
    696 		callout_stop(&sc->sc_tptimeout);
    697 
    698 		/* button 0 UP */
    699 		wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0);
    700 	}
    701 }
    702 
    703 /* touch panel timeout handler */
    704 void
    705 vrpiu_tp_timeout(void *v)
    706 {
    707 	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
    708 
    709 #ifdef VRPIUDEBUG
    710 	{
    711 		unsigned int cnt = vrpiu_read(sc, PIUCNT_REG_W);
    712 		DPRINTF(("TIMEOUT: stat=%s  reg=%s\n",
    713 		    (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH)?"touch":"release",
    714 		    (cnt & PIUCNT_PENSTC)?"touch":"release"));
    715 	}
    716 #endif
    717 	vrpiu_tp_up(sc);
    718 }
    719 
    720 /*
    721  * PIU interrupt handler.
    722  */
    723 int
    724 vrpiu_intr(void *arg)
    725 {
    726         struct vrpiu_softc *sc = arg;
    727 
    728 	vrpiu_ad_intr(sc);
    729 	vrpiu_tp_intr(sc);
    730 
    731 	return 0;
    732 }
    733 
    734 void
    735 vrpiu_start_powerstate(void *v)
    736 {
    737 	int mask;
    738 	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
    739 
    740 	vrpiu_ad_enable(sc);
    741 	mask = vrpiu_read(sc, PIUAMSK_REG_W);
    742 	mask &= 0xff8f; /* XXX */
    743 	vrpiu_write(sc, PIUAMSK_REG_W, mask);
    744 	vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
    745 	/*
    746 	 * restart next A/D polling
    747 	 */
    748 	callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
    749 	    vrpiu_start_powerstate, sc);
    750 }
    751 
    752 void
    753 vrpiu_calc_powerstate(struct vrpiu_softc *sc)
    754 {
    755 	extern void vrgiu_diff_io(void);
    756 	vrpiu_ad_disable(sc);
    757 	VPRINTF(("vrpiu:AD: %d, %d, %d\n",
    758 	    sc->sc_battery.value[0],
    759 	    sc->sc_battery.value[1],
    760 	    sc->sc_battery.value[2]));
    761 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
    762 	vrpiu_send_battery_event(sc);
    763 	/*
    764 	 * restart next A/D polling if change polling timming.
    765 	 */
    766 	if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
    767 		callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
    768 		    vrpiu_start_powerstate, sc);
    769 	if (bootverbose)
    770 		vrgiu_diff_io();
    771 
    772 }
    773 
    774 static void
    775 vrpiu_power(int why, void *arg)
    776 {
    777 	struct vrpiu_softc *sc = arg;
    778 
    779 	switch (why) {
    780 	case PWR_STANDBY:
    781 	case PWR_SUSPEND:
    782 		break;
    783 	case PWR_RESUME:
    784 		callout_reset(&sc->sc_adpoll, hz,
    785 		    vrpiu_start_powerstate, sc);
    786 		break;
    787 	}
    788 }
    789 
    790 static void
    791 vrpiu_send_battery_event(struct vrpiu_softc *sc)
    792 {
    793 #ifdef VRPIU_ADHOC_BATTERY_EVENT
    794 	static int batteryhigh = 0;
    795 	static int batterylow = 0;
    796 	static int critical = 0;
    797 
    798 	if (sc->sc_battery_spec == NULL
    799 	    || sc->sc_battery_spec->main_port == -1)
    800 		return;
    801 
    802 	if (sc->sc_battery.value[sc->sc_battery_spec->main_port]
    803 	    <= sc->sc_battery_spec->dc_critical) {
    804 		batteryhigh = 0;
    805 		config_hook_call(CONFIG_HOOK_PMEVENT,
    806 		    CONFIG_HOOK_PMEVENT_BATTERY,
    807 		    (void *)CONFIG_HOOK_BATT_CRITICAL);
    808 		batterylow = 3;
    809 		if (critical) {
    810 			config_hook_call(CONFIG_HOOK_PMEVENT,
    811 			    CONFIG_HOOK_PMEVENT_SUSPENDREQ,
    812 			    (void *)0);
    813 			critical = 0;
    814 			batterylow = 0;
    815 		}
    816 		critical++;
    817 	} else if (sc->sc_battery.value[sc->sc_battery_spec->main_port]
    818 	    <= sc->sc_battery_spec->dc_20p) {
    819 		batteryhigh = 0;
    820 		if (batterylow == 1)
    821 			config_hook_call(CONFIG_HOOK_PMEVENT,
    822 			    CONFIG_HOOK_PMEVENT_BATTERY,
    823 			    (void *)CONFIG_HOOK_BATT_20P);
    824 		config_hook_call(CONFIG_HOOK_PMEVENT,
    825 		    CONFIG_HOOK_PMEVENT_BATTERY,
    826 		    (void *)CONFIG_HOOK_BATT_LOW);
    827 		batterylow = 2;
    828 	} else if (sc->sc_battery.value[sc->sc_battery_spec->main_port]
    829 	    <= sc->sc_battery_spec->dc_50p) {
    830 		batteryhigh = 0;
    831 		if (batterylow == 0) {
    832 			batterylow = 1;
    833 			config_hook_call(CONFIG_HOOK_PMEVENT,
    834 			    CONFIG_HOOK_PMEVENT_BATTERY,
    835 			    (void *)CONFIG_HOOK_BATT_50P);
    836 		}
    837 	} else if (sc->sc_battery.value[sc->sc_battery_spec->main_port]
    838 	    >= sc->sc_battery_spec->ac_80p) {
    839 		batterylow = 0;
    840 		if (batteryhigh == 0) {
    841 			batteryhigh = 1;
    842 			config_hook_call(CONFIG_HOOK_PMEVENT,
    843 			    CONFIG_HOOK_PMEVENT_BATTERY,
    844 			    (void *)CONFIG_HOOK_BATT_80P);
    845 			config_hook_call(CONFIG_HOOK_PMEVENT,
    846 			    CONFIG_HOOK_PMEVENT_BATTERY,
    847 			    (void *)CONFIG_HOOK_BATT_HIGH);
    848 		}
    849 	}
    850 #else /* VRPIU_ADHOC_BATTERY_EVENT */
    851 	config_hook_call(CONFIG_HOOK_SET,
    852 	    CONFIG_HOOK_BATTERYVAL,
    853 	    (void *)&sc->sc_battery);
    854 #endif /* VRPIU_ADHOC_BATTERY_EVENT */
    855 }
    856 
    857 #ifdef DEBUG
    858 void
    859 vrpiu_dump_cntreg(unsigned int cnt)
    860 {
    861 	printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
    862 	printf(" state=");
    863 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
    864 		printf("CmdScan");
    865 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
    866 		printf("IntervalNextScan");
    867 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
    868 		printf("PenDataScan");
    869 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
    870 		printf("WaitPenTouch");
    871 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
    872 		printf("???");
    873 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
    874 		printf("ADPortScan");
    875 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
    876 		printf("Standby");
    877 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
    878 		printf("Disable");
    879 	if (cnt & PIUCNT_PADATSTOP)
    880 		printf(" AutoStop");
    881 	if (cnt & PIUCNT_PADATSTART)
    882 		printf(" AutoStart");
    883 	if (cnt & PIUCNT_PADSCANSTOP)
    884 		printf(" Stop");
    885 	if (cnt & PIUCNT_PADSCANSTART)
    886 		printf(" Start");
    887 	if (cnt & PIUCNT_PADSCANTYPE)
    888 		printf(" ScanPressure");
    889 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
    890 		printf(" A/D");
    891 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
    892 		printf(" Coordinate");
    893 	if (cnt & PIUCNT_PIUSEQEN)
    894 		printf(" SeqEn");
    895 	if ((cnt & PIUCNT_PIUPWR) == 0)
    896 		printf(" PowerOff");
    897 	if ((cnt & PIUCNT_PADRST) == 0)
    898 		printf(" Reset");
    899 	printf("\n");
    900 }
    901 #endif
    902