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