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