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