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