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