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