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