Home | History | Annotate | Line # | Download | only in vr
vrpiu.c revision 1.11
      1 /*	$NetBSD: vrpiu.c,v 1.11 2001/02/22 18:38:05 uch 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_700A,
    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 		{ NULL,		/* samples got on my MC-R500 */
    216 		  { 0, 0, 639, 239,
    217 		    5,
    218 		    { { 502, 486, 320, 120 },
    219 		      {  55, 109,   0,   0 },
    220 		      {  54, 913,   0, 239 },
    221 		      { 973, 924, 639, 239 },
    222 		      { 975, 123, 639,   0 } } } },
    223 	    };
    224 	    for (i = 0; ; i++) {
    225 		if (calibrations[i].mask == NULL
    226 		    || platid_match(&platid, calibrations[i].mask))
    227 		    break;
    228 	    }
    229 	    tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
    230 			  (caddr_t)&calibrations[i].coords, 0, 0);
    231 	}
    232 #endif
    233 
    234 	/* install interrupt handler and enable interrupt */
    235 	if (!(sc->sc_handler =
    236 	    vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY,
    237 				vrpiu_intr, sc))) {
    238 	    printf (": can't map interrupt line.\n");
    239 	    return;
    240 	}
    241 
    242 	/* mask level2 interrupt, stop scan sequencer and mask clock to piu */
    243 	vrpiu_tp_disable(sc);
    244 
    245 	printf("\n");
    246 
    247 	wsmaa.accessops = &vrpiu_accessops;
    248 	wsmaa.accesscookie = sc;
    249 
    250 	/*
    251 	 * attach the wsmouse
    252 	 */
    253 	sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint);
    254 
    255 	/*
    256 	 * power management events
    257 	 */
    258 	sc->sc_power_hook = powerhook_establish(vrpiu_power, sc);
    259 
    260 	/*
    261 	 * init A/D port polling.
    262 	 */
    263 	sc->sc_battery.n_values = 3;
    264 	sc->sc_battery.value[0] = -1;
    265 	sc->sc_battery.value[1] = -1;
    266 	sc->sc_battery.value[2] = -1;
    267 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
    268 	callout_init(&sc->sc_adpoll);
    269 	callout_reset(&sc->sc_adpoll, hz, vrpiu_start_powerstate, sc);
    270 }
    271 
    272 /*
    273  * calculate interval value
    274  *  input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX
    275  * output: value for PIUSIVL_REG
    276  */
    277 static u_int
    278 scan_interval(u_int data)
    279 {
    280 	int scale;
    281 
    282 	if (data < WSMOUSE_RES_MIN)
    283 	    data = WSMOUSE_RES_MIN;
    284 
    285 	if (WSMOUSE_RES_MAX < data)
    286 	    data = WSMOUSE_RES_MAX;
    287 
    288 	scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN;
    289 	data += WSMOUSE_RES_MIN;
    290 
    291 	return PIUSIVL_SCANINTVAL_MIN +
    292 	    (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) *
    293 	    (scale - data) / scale;
    294 }
    295 
    296 int
    297 vrpiu_ad_enable(v)
    298 	void *v;
    299 {
    300 	struct vrpiu_softc *sc = v;
    301 	int s;
    302 	unsigned int cnt;
    303 
    304 	DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n",
    305 		 __FILE__, __LINE__, sc->sc_interval));
    306 	if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE)
    307 	    return EBUSY;
    308 
    309 	/* supply clock to PIU */
    310 	__vrcmu_supply(CMUMSKPIU, 1);
    311 
    312 	/* set scan interval */
    313 	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
    314 
    315 	s = spltty();
    316 
    317 	/* clear interrupt status */
    318 	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
    319 
    320 	/* Disable -> Standby */
    321 	cnt = PIUCNT_PIUPWR |
    322 		PIUCNT_PIUMODE_COORDINATE |
    323 		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
    324 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    325 
    326 	/* Level2 interrupt register setting */
    327 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1);
    328 
    329 	/* save pen status, touch or release */
    330 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    331 
    332 	/*
    333 	 * Enable scan sequencer operation
    334 	 * Standby -> WaitPenTouch
    335 	 */
    336 	cnt |= PIUCNT_PIUSEQEN;
    337 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    338 
    339 	sc->sc_adstat = VRPIU_AD_STAT_ENABLE;
    340 
    341 	splx(s);
    342 
    343 	return 0;
    344 }
    345 
    346 void
    347 vrpiu_ad_disable(v)
    348 	void *v;
    349 {
    350 	struct vrpiu_softc *sc = v;
    351 
    352 	DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__));
    353 
    354 	/* Set level2 interrupt register to mask interrupts */
    355 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0);
    356 
    357 	sc->sc_adstat = VRPIU_AD_STAT_DISABLE;
    358 
    359 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){
    360 	    /* Disable scan sequencer operation and power off */
    361 	    vrpiu_write(sc, PIUCNT_REG_W, 0);
    362 
    363 	    /* mask clock to PIU */
    364 	    __vrcmu_supply(CMUMSKPIU, 1);
    365 	}
    366 }
    367 
    368 int
    369 vrpiu_tp_enable(v)
    370 	void *v;
    371 {
    372 	struct vrpiu_softc *sc = v;
    373 	int s;
    374 	unsigned int cnt;
    375 
    376 	DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n",
    377 		 __FILE__, __LINE__, sc->sc_interval));
    378 	if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE)
    379 	    return EBUSY;
    380 
    381 	/* supply clock to PIU */
    382 	__vrcmu_supply(CMUMSKPIU, 1);
    383 
    384 	/* set scan interval */
    385 	vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval);
    386 
    387 	s = spltty();
    388 
    389 	/* clear interrupt status */
    390 	vrpiu_write(sc, PIUINT_REG_W, TP_INTR);
    391 
    392 	/* Disable -> Standby */
    393 	cnt = PIUCNT_PIUPWR |
    394 		PIUCNT_PIUMODE_COORDINATE |
    395 		PIUCNT_PADATSTART | PIUCNT_PADATSTOP;
    396 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    397 
    398 	/* Level2 interrupt register setting */
    399 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1);
    400 
    401 	/* save pen status, touch or release */
    402 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    403 
    404 	/*
    405 	 * Enable scan sequencer operation
    406 	 * Standby -> WaitPenTouch
    407 	 */
    408 	cnt |= PIUCNT_PIUSEQEN;
    409 	vrpiu_write(sc, PIUCNT_REG_W, cnt);
    410 
    411 	/* transit status DISABLE -> TOUCH or RELEASE */
    412 	sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ?
    413 		VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE;
    414 
    415 	splx(s);
    416 
    417 	return 0;
    418 }
    419 
    420 void
    421 vrpiu_tp_disable(v)
    422 	void *v;
    423 {
    424 	struct vrpiu_softc *sc = v;
    425 
    426 	DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__));
    427 
    428 	/* Set level2 interrupt register to mask interrupts */
    429 	vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0);
    430 
    431 	sc->sc_tpstat = VRPIU_TP_STAT_DISABLE;
    432 
    433 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){
    434 	    /* Disable scan sequencer operation and power off */
    435 	    vrpiu_write(sc, PIUCNT_REG_W, 0);
    436 
    437 	    /* mask clock to PIU */
    438 	    __vrcmu_supply(CMUMSKPIU, 1);
    439 	}
    440 }
    441 
    442 int
    443 vrpiu_tp_ioctl(v, cmd, data, flag, p)
    444 	void *v;
    445 	u_long cmd;
    446 	caddr_t data;
    447 	int flag;
    448 	struct proc *p;
    449 {
    450 	struct vrpiu_softc *sc = v;
    451 
    452 	DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd));
    453 
    454 	switch (cmd) {
    455 	case WSMOUSEIO_GTYPE:
    456 	    *(u_int *)data = WSMOUSE_TYPE_TPANEL;
    457 	    break;
    458 
    459 	case WSMOUSEIO_SRES:
    460 	    {
    461 		int tp_enable;
    462 		int ad_enable;
    463 
    464 		tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE);
    465 		ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE);
    466 
    467 		if (tp_enable)
    468 		    vrpiu_tp_disable(sc);
    469 		if (ad_enable)
    470 		    vrpiu_ad_disable(sc);
    471 
    472 		sc->sc_interval = scan_interval(*(u_int *)data);
    473 		DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n",
    474 		    __FILE__, __LINE__, *(u_int *)data, sc->sc_interval));
    475 
    476 		if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN)
    477 		    sc->sc_interval = PIUSIVL_SCANINTVAL_MIN;
    478 
    479 		if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval)
    480 		    sc->sc_interval = PIUSIVL_SCANINTVAL_MAX;
    481 
    482 		if (tp_enable)
    483 		    vrpiu_tp_enable(sc);
    484 		if (ad_enable)
    485 		     vrpiu_ad_enable(sc);
    486 	    }
    487 	    break;
    488 
    489 	case WSMOUSEIO_SCALIBCOORDS:
    490 	case WSMOUSEIO_GCALIBCOORDS:
    491             return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
    492 
    493 	default:
    494 	    return (-1);
    495 	}
    496 	return (0);
    497 }
    498 
    499 /*
    500  * PIU AD interrupt handler.
    501  */
    502 void
    503 vrpiu_ad_intr(sc)
    504 	struct vrpiu_softc *sc;
    505 {
    506 	unsigned int i;
    507 	unsigned int intrstat;
    508 
    509 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
    510 
    511 	if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) {
    512 	    /*
    513 	     * the device isn't enabled. just clear interrupt.
    514 	     */
    515 	    vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
    516 	    return;
    517 	}
    518 
    519 	if (intrstat & PIUINT_PADADPINTR) {
    520 	    sc->sc_battery.value[0] = (unsigned int)vrpiu_read(sc, PIUAB(0));
    521 	    sc->sc_battery.value[1] = (unsigned int)vrpiu_read(sc, PIUAB(1));
    522 	    sc->sc_battery.value[2] = (unsigned int)vrpiu_read(sc, PIUAB(2));
    523 	}
    524 
    525 	if (intrstat & PIUINT_PADADPINTR) {
    526 	    for (i = 0; i < 3; i++) {
    527 		if (sc->sc_battery.value[i] & PIUAB_VALID)
    528 		    sc->sc_battery.value[i] &= PIUAB_PADDATA_MASK;
    529 		else
    530 		    sc->sc_battery.value[i] = 0;
    531 	    }
    532 	    vrpiu_calc_powerstate(sc);
    533 	}
    534 	vrpiu_write(sc, PIUINT_REG_W, AD_INTR);
    535 
    536 	return;
    537 }
    538 /*
    539  * PIU TP interrupt handler.
    540  */
    541 void
    542 vrpiu_tp_intr(sc)
    543 	struct vrpiu_softc *sc;
    544 {
    545 	unsigned int cnt, i;
    546 	unsigned int intrstat, page;
    547 	int tpx0, tpx1, tpy0, tpy1;
    548 	int x, y, xraw, yraw;
    549 
    550 	intrstat = vrpiu_read(sc, PIUINT_REG_W);
    551 
    552 	if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) {
    553 	    /*
    554 	     * the device isn't enabled. just clear interrupt.
    555 	     */
    556 	    vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
    557 	    return;
    558 	}
    559 
    560 	page = (intrstat & PIUINT_OVP) ? 1 : 0;
    561 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
    562 	    tpx0 = vrpiu_read(sc, PIUPB(page, 0));
    563 	    tpx1 = vrpiu_read(sc, PIUPB(page, 1));
    564 	    tpy0 = vrpiu_read(sc, PIUPB(page, 2));
    565 	    tpy1 = vrpiu_read(sc, PIUPB(page, 3));
    566 	}
    567 
    568 	if (intrstat & PIUINT_PADDLOSTINTR) {
    569 	    page = page ? 0 : 1;
    570 	    for (i = 0; i < 4; i++)
    571 		vrpiu_read(sc, PIUPB(page, i));
    572 	}
    573 
    574 	cnt = vrpiu_read(sc, PIUCNT_REG_W);
    575 #ifdef DEBUG
    576 	if (vrpiu_debug)
    577 	    vrpiu_dump_cntreg(cnt);
    578 #endif
    579 
    580 	/* clear interrupt status */
    581 	vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR);
    582 
    583 #if 0
    584 	DPRINTF(("vrpiu_intr: OVP=%d", page));
    585 	if (intrstat & PIUINT_PADCMDINTR)
    586 	    DPRINTF((" CMD"));
    587 	if (intrstat & PIUINT_PADADPINTR)
    588 	    DPRINTF((" A/D"));
    589 	if (intrstat & PIUINT_PADPAGE1INTR)
    590 	    DPRINTF((" PAGE1"));
    591 	if (intrstat & PIUINT_PADPAGE0INTR)
    592 	    DPRINTF((" PAGE0"));
    593 	if (intrstat & PIUINT_PADDLOSTINTR)
    594 	    DPRINTF((" DLOST"));
    595 	if (intrstat & PIUINT_PENCHGINTR)
    596 	    DPRINTF((" PENCHG"));
    597 	DPRINTF(("\n"));
    598 #endif
    599 	if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) {
    600 	    /*
    601 	     * just ignore scan data if status isn't Touch.
    602 	     */
    603 	    if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
    604 		/* reset tp scan timeout	*/
    605 		callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
    606 			      vrpiu_tp_timeout, sc);
    607 
    608 		if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) &&
    609 		    (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) {
    610 		    printf("vrpiu: internal error, data is not valid!\n");
    611 		} else {
    612 		    tpx0 &= PIUPB_PADDATA_MASK;
    613 		    tpx1 &= PIUPB_PADDATA_MASK;
    614 		    tpy0 &= PIUPB_PADDATA_MASK;
    615 		    tpy1 &= PIUPB_PADDATA_MASK;
    616 #define ISVALID(n, c, m)	((c) - (m) < (n) && (n) < (c) + (m))
    617 		    if (ISVALID(tpx0 + tpx1, 1024, 200) &&
    618 			ISVALID(tpy0 + tpy1, 1024, 200)) {
    619 #if 0
    620 			DPRINTF(("%04x %04x %04x %04x\n",
    621 				 tpx0, tpx1, tpy0, tpy1));
    622 			DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0,
    623 				 tpx0 + tpx1, tpy0 + tpy1));
    624 #endif
    625 			xraw = tpy1 * 1024 / (tpy0 + tpy1);
    626 			yraw = tpx1 * 1024 / (tpx0 + tpx1);
    627 			DPRINTF(("%3d %3d", xraw, yraw));
    628 
    629 			tpcalib_trans(&sc->sc_tpcalib, xraw, yraw, &x, &y);
    630 
    631 			DPRINTF(("->%4d %4d", x, y));
    632 			wsmouse_input(sc->sc_wsmousedev,
    633 				      1, /* button 0 down */
    634 				      x, /* x */
    635 				      y, /* y */
    636 				      0, /* z */
    637 				      WSMOUSE_INPUT_ABSOLUTE_X |
    638 				      WSMOUSE_INPUT_ABSOLUTE_Y);
    639 			DPRINTF(("\n"));
    640 		    }
    641 		}
    642 	    }
    643 	}
    644 
    645 	if (cnt & PIUCNT_PENSTC) {
    646 	    if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) {
    647 		/*
    648 		 * pen touch
    649 		 */
    650 		DPRINTF(("PEN TOUCH\n"));
    651 		sc->sc_tpstat = VRPIU_TP_STAT_TOUCH;
    652 		/*
    653 		 * We should not report button down event while
    654 		 * we don't know where it occur.
    655 		 */
    656 
    657 		/* set tp scan timeout	*/
    658 		callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT,
    659 			      vrpiu_tp_timeout, sc);
    660 	    }
    661 	} else {
    662 	    vrpiu_tp_up(sc);
    663 	}
    664 
    665 	if (intrstat & PIUINT_PADDLOSTINTR) {
    666 	    cnt |= PIUCNT_PIUSEQEN;
    667 	    vrpiu_write(sc, PIUCNT_REG_W, cnt);
    668 	}
    669 
    670 	return;
    671 }
    672 
    673 void
    674 vrpiu_tp_up(sc)
    675 	struct vrpiu_softc *sc;
    676 {
    677 	if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) {
    678 	    /*
    679 	     * pen release
    680 	     */
    681 	    DPRINTF(("RELEASE\n"));
    682 	    sc->sc_tpstat = VRPIU_TP_STAT_RELEASE;
    683 
    684 	    /* clear tp scan timeout	*/
    685 	    callout_stop(&sc->sc_tptimeout);
    686 
    687 	    /* button 0 UP */
    688 	    wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0);
    689 	}
    690 }
    691 
    692 /* touch panel timeout handler */
    693 void
    694 vrpiu_tp_timeout(v)
    695 	void *v;
    696 {
    697 	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
    698 
    699 #ifdef VRPIUDEBUG
    700 	{
    701 	    unsigned int cnt = vrpiu_read(sc, PIUCNT_REG_W);
    702 	    DPRINTF(("TIMEOUT: stat=%s  reg=%s\n",
    703 		(sc->sc_tpstat == VRPIU_TP_STAT_TOUCH)?"touch":"release",
    704 		(cnt & PIUCNT_PENSTC)?"touch":"release"));
    705 	}
    706 #endif
    707 	vrpiu_tp_up(sc);
    708 }
    709 
    710 /*
    711  * PIU interrupt handler.
    712  */
    713 int
    714 vrpiu_intr(arg)
    715 	void *arg;
    716 {
    717         struct vrpiu_softc *sc = arg;
    718 
    719 	vrpiu_ad_intr(sc);
    720 	vrpiu_tp_intr(sc);
    721 
    722 	return 0;
    723 }
    724 
    725 void
    726 vrpiu_start_powerstate(v)
    727 	void *v;
    728 {
    729 	int mask;
    730 	struct vrpiu_softc *sc = (struct vrpiu_softc *)v;
    731 
    732 	vrpiu_ad_enable(sc);
    733 	mask = vrpiu_read(sc, PIUAMSK_REG_W);
    734 	mask &= 0xff8f; /* XXX */
    735 	vrpiu_write(sc, PIUAMSK_REG_W, mask);
    736 	vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART);
    737 	/*
    738 	 * restart next A/D polling
    739 	 */
    740 	callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval,
    741 		      vrpiu_start_powerstate, sc);
    742 }
    743 
    744 void
    745 vrpiu_calc_powerstate(sc)
    746 	struct vrpiu_softc *sc;
    747 {
    748 	extern void vrgiu_diff_io __P((void));
    749 	vrpiu_ad_disable(sc);
    750 	VPRINTF(("vrpiu:AD: %d, %d, %d\n",
    751 		sc->sc_battery.value[0],
    752 		sc->sc_battery.value[1],
    753 		sc->sc_battery.value[2]));
    754 	sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval;
    755 #ifdef notyet
    756 	config_hook_call(CONFIG_HOOK_SET,
    757 			 CONFIG_HOOK_BATTERYVAL,
    758 			 (void *)&sc->sc_battery);
    759 #endif /* notyet */
    760 	/*
    761 	 * restart next A/D polling if change polling timming.
    762 	 */
    763 	if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval)
    764 	    callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll,
    765 			  vrpiu_start_powerstate, sc);
    766 	if (bootverbose)
    767 	    vrgiu_diff_io();
    768 
    769 }
    770 
    771 static void
    772 vrpiu_power(why, arg)
    773 	int why;
    774 	void *arg;
    775 {
    776 	struct vrpiu_softc *sc = arg;
    777 
    778 	switch (why) {
    779 	case PWR_STANDBY:
    780 	case PWR_SUSPEND:
    781 	    break;
    782 	case PWR_RESUME:
    783 	    callout_reset(&sc->sc_adpoll, hz,
    784 			  vrpiu_start_powerstate, sc);
    785 	    break;
    786 	}
    787 }
    788 
    789 #ifdef DEBUG
    790 void
    791 vrpiu_dump_cntreg(cnt)
    792 	unsigned int cnt;
    793 {
    794 	printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release");
    795 	printf(" state=");
    796 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan)
    797 	    printf("CmdScan");
    798 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan)
    799 	    printf("IntervalNextScan");
    800 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan)
    801 	    printf("PenDataScan");
    802 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch)
    803 	    printf("WaitPenTouch");
    804 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU)
    805 	    printf("???");
    806 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan)
    807 	    printf("ADPortScan");
    808 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby)
    809 	    printf("Standby");
    810 	if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable)
    811 	    printf("Disable");
    812 	if (cnt & PIUCNT_PADATSTOP)
    813 	    printf(" AutoStop");
    814 	if (cnt & PIUCNT_PADATSTART)
    815 	    printf(" AutoStart");
    816 	if (cnt & PIUCNT_PADSCANSTOP)
    817 	    printf(" Stop");
    818 	if (cnt & PIUCNT_PADSCANSTART)
    819 	    printf(" Start");
    820 	if (cnt & PIUCNT_PADSCANTYPE)
    821 	    printf(" ScanPressure");
    822 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER)
    823 	    printf(" A/D");
    824 	if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE)
    825 	    printf(" Coordinate");
    826 	if (cnt & PIUCNT_PIUSEQEN)
    827 	    printf(" SeqEn");
    828 	if ((cnt & PIUCNT_PIUPWR) == 0)
    829 	    printf(" PowerOff");
    830 	if ((cnt & PIUCNT_PADRST) == 0)
    831 	    printf(" Reset");
    832 	printf("\n");
    833 }
    834 #endif
    835