vrpiu.c revision 1.32
1/* $NetBSD: vrpiu.c,v 1.32 2003/12/27 07:28:21 shin 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.32 2003/12/27 07:28:21 shin 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/tpcalibvar.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 70int 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 */ 101static int vrpiumatch(struct device *, struct cfdata *, void *); 102static void vrpiuattach(struct device *, struct device *, void *); 103static void vrc4173piuattach(struct device *, struct device *, void *); 104static void vrpiu_init(struct vrpiu_softc *, void *); 105 106static void vrpiu_write(struct vrpiu_softc *, int, unsigned short); 107static u_short vrpiu_read(struct vrpiu_softc *, int); 108 109static int vrpiu_intr(void *); 110static void vrpiu_tp_intr(struct vrpiu_softc *); 111static void vrpiu_ad_intr(struct vrpiu_softc *); 112#ifdef DEBUG 113static void vrpiu_dump_cntreg(unsigned int); 114#endif 115 116static int vrpiu_tp_enable(void *); 117static int vrpiu_tp_ioctl(void *, u_long, caddr_t, int, struct proc *); 118static void vrpiu_tp_disable(void *); 119static void vrpiu_tp_up(struct vrpiu_softc *); 120static void vrpiu_tp_timeout(void *); 121int vrpiu_ad_enable(void *); 122void vrpiu_ad_disable(void *); 123static void vrpiu_start_powerstate(void *); 124static void vrpiu_calc_powerstate(struct vrpiu_softc *); 125static void vrpiu_send_battery_event(struct vrpiu_softc *); 126static void vrpiu_power(int, void *); 127static u_int scan_interval(u_int data); 128 129/* mra is defined in mra.c */ 130int 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 */ 136CFATTACH_DECL(vrpiu, sizeof(struct vrpiu_softc), 137 vrpiumatch, vrpiuattach, NULL, NULL); 138CFATTACH_DECL(vrc4173piu, sizeof(struct vrpiu_softc), 139 vrpiumatch, vrc4173piuattach, NULL, NULL); 140 141const struct wsmouse_accessops vrpiu_accessops = { 142 vrpiu_tp_enable, 143 vrpiu_tp_ioctl, 144 vrpiu_tp_disable, 145}; 146 147int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL; 148 149/* 150 * function definitions 151 */ 152static inline void 153vrpiu_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 159static inline u_short 160vrpiu_read(struct vrpiu_softc *sc, int port) 161{ 162 163 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port)); 164} 165 166static inline u_short 167vrpiu_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 173static int 174vrpiumatch(struct device *parent, struct cfdata *cf, void *aux) 175{ 176 177 return (1); 178} 179 180static void 181vrpiuattach(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 191static void 192vrc4173piuattach(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 202static void 203vrpiu_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); 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 (caddr_t)&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(vrpiu_power, sc); 334 335 /* 336 * init A/D port polling. 337 */ 338 sc->sc_battery.n_values = 3; 339 sc->sc_battery.value[0] = -1; 340 sc->sc_battery.value[1] = -1; 341 sc->sc_battery.value[2] = -1; 342 sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval; 343 callout_init(&sc->sc_adpoll); 344 callout_reset(&sc->sc_adpoll, hz, vrpiu_start_powerstate, sc); 345} 346 347/* 348 * calculate interval value 349 * input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX 350 * output: value for PIUSIVL_REG 351 */ 352static u_int 353scan_interval(u_int data) 354{ 355 int scale; 356 357 if (data < WSMOUSE_RES_MIN) 358 data = WSMOUSE_RES_MIN; 359 360 if (WSMOUSE_RES_MAX < data) 361 data = WSMOUSE_RES_MAX; 362 363 scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN; 364 data += WSMOUSE_RES_MIN; 365 366 return PIUSIVL_SCANINTVAL_MIN + 367 (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) * 368 (scale - data) / scale; 369} 370 371int 372vrpiu_ad_enable(void *v) 373{ 374 struct vrpiu_softc *sc = v; 375 int s; 376 unsigned int cnt; 377 378 DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n", 379 __FILE__, __LINE__, sc->sc_interval)); 380 if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE) 381 return EBUSY; 382 383 /* supply clock to PIU */ 384 vrip_power(sc->sc_vrip, sc->sc_unit, 1); 385 386 /* set scan interval */ 387 vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval); 388 389 s = spltty(); 390 391 /* clear interrupt status */ 392 vrpiu_write(sc, PIUINT_REG_W, AD_INTR); 393 394 /* Disable -> Standby */ 395 cnt = PIUCNT_PIUPWR | 396 PIUCNT_PIUMODE_COORDINATE | 397 PIUCNT_PADATSTART | PIUCNT_PADATSTOP; 398 vrpiu_write(sc, PIUCNT_REG_W, cnt); 399 400 /* Level2 interrupt register setting */ 401 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1); 402 403 /* save pen status, touch or release */ 404 cnt = vrpiu_read(sc, PIUCNT_REG_W); 405 406 /* 407 * Enable scan sequencer operation 408 * Standby -> WaitPenTouch 409 */ 410 cnt |= PIUCNT_PIUSEQEN; 411 vrpiu_write(sc, PIUCNT_REG_W, cnt); 412 413 sc->sc_adstat = VRPIU_AD_STAT_ENABLE; 414 415 splx(s); 416 417 return 0; 418} 419 420void 421vrpiu_ad_disable(void *v) 422{ 423 struct vrpiu_softc *sc = v; 424 425 DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__)); 426 427 /* Set level2 interrupt register to mask interrupts */ 428 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0); 429 430 sc->sc_adstat = VRPIU_AD_STAT_DISABLE; 431 432 if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){ 433 /* Disable scan sequencer operation and power off */ 434 vrpiu_write(sc, PIUCNT_REG_W, 0); 435 436 /* mask clock to PIU */ 437 vrip_power(sc->sc_vrip, sc->sc_unit, 0); 438 } 439} 440 441int 442vrpiu_tp_enable(void *v) 443{ 444 struct vrpiu_softc *sc = v; 445 int s; 446 unsigned int cnt; 447 448 DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n", 449 __FILE__, __LINE__, sc->sc_interval)); 450 if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE) 451 return EBUSY; 452 453 /* supply clock to PIU */ 454 vrip_power(sc->sc_vrip, sc->sc_unit, 1); 455 456 /* set scan interval */ 457 vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval); 458 459 s = spltty(); 460 461 /* clear interrupt status */ 462 vrpiu_write(sc, PIUINT_REG_W, TP_INTR); 463 464 /* Disable -> Standby */ 465 cnt = PIUCNT_PIUPWR | 466 PIUCNT_PIUMODE_COORDINATE | 467 PIUCNT_PADATSTART | PIUCNT_PADATSTOP; 468 vrpiu_write(sc, PIUCNT_REG_W, cnt); 469 470 /* Level2 interrupt register setting */ 471 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1); 472 473 /* save pen status, touch or release */ 474 cnt = vrpiu_read(sc, PIUCNT_REG_W); 475 476 /* 477 * Enable scan sequencer operation 478 * Standby -> WaitPenTouch 479 */ 480 cnt |= PIUCNT_PIUSEQEN; 481 vrpiu_write(sc, PIUCNT_REG_W, cnt); 482 483 /* transit status DISABLE -> TOUCH or RELEASE */ 484 sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ? 485 VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE; 486 487 splx(s); 488 489 return 0; 490} 491 492void 493vrpiu_tp_disable(void *v) 494{ 495 struct vrpiu_softc *sc = v; 496 497 DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__)); 498 499 /* Set level2 interrupt register to mask interrupts */ 500 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0); 501 502 sc->sc_tpstat = VRPIU_TP_STAT_DISABLE; 503 504 if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){ 505 /* Disable scan sequencer operation and power off */ 506 vrpiu_write(sc, PIUCNT_REG_W, 0); 507 508 /* mask clock to PIU */ 509 vrip_power(sc->sc_vrip, sc->sc_unit, 0); 510 } 511} 512 513int 514vrpiu_tp_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 515{ 516 struct vrpiu_softc *sc = v; 517 518 DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd)); 519 520 switch (cmd) { 521 case WSMOUSEIO_GTYPE: 522 *(u_int *)data = WSMOUSE_TYPE_TPANEL; 523 break; 524 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 case WSMOUSEIO_SCALIBCOORDS: 556 case WSMOUSEIO_GCALIBCOORDS: 557 case WSMOUSEIO_GETID: 558 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p); 559 560 default: 561 return (EPASSTHROUGH); 562 } 563 return (0); 564} 565 566/* 567 * PIU AD interrupt handler. 568 */ 569void 570vrpiu_ad_intr(struct vrpiu_softc *sc) 571{ 572 unsigned int i; 573 unsigned int intrstat; 574 575 intrstat = vrpiu_read(sc, PIUINT_REG_W); 576 577 if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) { 578 /* 579 * the device isn't enabled. just clear interrupt. 580 */ 581 vrpiu_write(sc, PIUINT_REG_W, AD_INTR); 582 return; 583 } 584 585 if (intrstat & PIUINT_PADADPINTR) { 586 sc->sc_battery.value[0] = (unsigned int) 587 vrpiu_buf_read(sc, PIUAB(0)); 588 sc->sc_battery.value[1] = (unsigned int) 589 vrpiu_buf_read(sc, PIUAB(1)); 590 sc->sc_battery.value[2] = (unsigned int) 591 vrpiu_buf_read(sc, PIUAB(2)); 592 } 593 594 if (intrstat & PIUINT_PADADPINTR) { 595 for (i = 0; i < 3; i++) { 596 if (sc->sc_battery.value[i] & PIUAB_VALID) 597 sc->sc_battery.value[i] &= 598 sc->sc_ab_paddata_mask; 599 else 600 sc->sc_battery.value[i] = 0; 601 } 602 vrpiu_calc_powerstate(sc); 603 } 604 vrpiu_write(sc, PIUINT_REG_W, AD_INTR); 605 606 return; 607} 608/* 609 * PIU TP interrupt handler. 610 */ 611void 612vrpiu_tp_intr(struct vrpiu_softc *sc) 613{ 614 unsigned int cnt, i; 615 unsigned int intrstat, page; 616 int tpx0, tpx1, tpy0, tpy1; 617 int x, y, xraw, yraw; 618 619 tpx0 = tpx1 = tpy0 = tpy1 = 0; /* XXX: gcc -Wuninitialized */ 620 621 intrstat = vrpiu_read(sc, PIUINT_REG_W); 622 623 if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) { 624 /* 625 * the device isn't enabled. just clear interrupt. 626 */ 627 vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR); 628 return; 629 } 630 631 page = (intrstat & PIUINT_OVP) ? 1 : 0; 632 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 633 tpx0 = vrpiu_buf_read(sc, PIUPB(page, 0)); 634 tpx1 = vrpiu_buf_read(sc, PIUPB(page, 1)); 635 tpy0 = vrpiu_buf_read(sc, PIUPB(page, 2)); 636 tpy1 = vrpiu_buf_read(sc, PIUPB(page, 3)); 637 } 638 639 if (intrstat & PIUINT_PADDLOSTINTR) { 640 page = page ? 0 : 1; 641 for (i = 0; i < 4; i++) 642 vrpiu_buf_read(sc, PIUPB(page, i)); 643 } 644 645 cnt = vrpiu_read(sc, PIUCNT_REG_W); 646#ifdef DEBUG 647 if (vrpiu_debug) 648 vrpiu_dump_cntreg(cnt); 649#endif 650 651 /* clear interrupt status */ 652 vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR); 653 654#if 0 655 DPRINTF(("vrpiu_intr: OVP=%d", page)); 656 if (intrstat & PIUINT_PADCMDINTR) 657 DPRINTF((" CMD")); 658 if (intrstat & PIUINT_PADADPINTR) 659 DPRINTF((" A/D")); 660 if (intrstat & PIUINT_PADPAGE1INTR) 661 DPRINTF((" PAGE1")); 662 if (intrstat & PIUINT_PADPAGE0INTR) 663 DPRINTF((" PAGE0")); 664 if (intrstat & PIUINT_PADDLOSTINTR) 665 DPRINTF((" DLOST")); 666 if (intrstat & PIUINT_PENCHGINTR) 667 DPRINTF((" PENCHG")); 668 DPRINTF(("\n")); 669#endif 670 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 671 /* 672 * just ignore scan data if status isn't Touch. 673 */ 674 if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) { 675 /* reset tp scan timeout */ 676 callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT, 677 vrpiu_tp_timeout, sc); 678 679 if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) && 680 (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) { 681 printf("vrpiu: internal error," 682 " data is not valid!\n"); 683 } else { 684 tpx0 &= sc->sc_pb_paddata_mask; 685 tpx1 &= sc->sc_pb_paddata_mask; 686 tpy0 &= sc->sc_pb_paddata_mask; 687 tpy1 &= sc->sc_pb_paddata_mask; 688#define ISVALID(n, c) ((c) - (c)/5 < (n) && (n) < (c) + (c)/5) 689 if (ISVALID(tpx0 + tpx1, sc->sc_pb_paddata_max) && 690 ISVALID(tpy0 + tpy1, sc->sc_pb_paddata_max)) { 691#if 0 692 DPRINTF(("%04x %04x %04x %04x\n", 693 tpx0, tpx1, tpy0, tpy1)); 694 DPRINTF(("%3d %3d (%4d %4d)->", tpx0, 695 tpy0, tpx0 + tpx1, tpy0 + tpy1)); 696#endif 697 xraw = tpy1 * sc->sc_pb_paddata_max / (tpy0 + tpy1); 698 yraw = tpx1 * sc->sc_pb_paddata_max / (tpx0 + tpx1); 699 DPRINTF(("%3d %3d", xraw, yraw)); 700 701 tpcalib_trans(&sc->sc_tpcalib, xraw, 702 yraw, &x, &y); 703 704 DPRINTF(("->%4d %4d", x, y)); 705 wsmouse_input(sc->sc_wsmousedev, 706 1, /* button 0 down */ 707 x, /* x */ 708 y, /* y */ 709 0, /* z */ 710 WSMOUSE_INPUT_ABSOLUTE_X | 711 WSMOUSE_INPUT_ABSOLUTE_Y); 712 DPRINTF(("\n")); 713 } 714 } 715 } 716 } 717 718 if (cnt & PIUCNT_PENSTC) { 719 if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) { 720 /* 721 * pen touch 722 */ 723 DPRINTF(("PEN TOUCH\n")); 724 sc->sc_tpstat = VRPIU_TP_STAT_TOUCH; 725 /* 726 * We should not report button down event while 727 * we don't know where it occur. 728 */ 729 730 /* set tp scan timeout */ 731 callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT, 732 vrpiu_tp_timeout, sc); 733 } 734 } else { 735 vrpiu_tp_up(sc); 736 } 737 738 if (intrstat & PIUINT_PADDLOSTINTR) { 739 cnt |= PIUCNT_PIUSEQEN; 740 vrpiu_write(sc, PIUCNT_REG_W, cnt); 741 } 742 743 return; 744} 745 746void 747vrpiu_tp_up(struct vrpiu_softc *sc) 748{ 749 if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) { 750 /* 751 * pen release 752 */ 753 DPRINTF(("RELEASE\n")); 754 sc->sc_tpstat = VRPIU_TP_STAT_RELEASE; 755 756 /* clear tp scan timeout */ 757 callout_stop(&sc->sc_tptimeout); 758 759 /* button 0 UP */ 760 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0); 761 } 762} 763 764/* touch panel timeout handler */ 765void 766vrpiu_tp_timeout(void *v) 767{ 768 struct vrpiu_softc *sc = (struct vrpiu_softc *)v; 769 770#ifdef VRPIUDEBUG 771 { 772 unsigned int cnt = vrpiu_read(sc, PIUCNT_REG_W); 773 DPRINTF(("TIMEOUT: stat=%s reg=%s\n", 774 (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH)?"touch":"release", 775 (cnt & PIUCNT_PENSTC)?"touch":"release")); 776 } 777#endif 778 vrpiu_tp_up(sc); 779} 780 781/* 782 * PIU interrupt handler. 783 */ 784int 785vrpiu_intr(void *arg) 786{ 787 struct vrpiu_softc *sc = arg; 788 789 vrpiu_ad_intr(sc); 790 vrpiu_tp_intr(sc); 791 792 return 0; 793} 794 795void 796vrpiu_start_powerstate(void *v) 797{ 798 int mask; 799 struct vrpiu_softc *sc = (struct vrpiu_softc *)v; 800 801 vrpiu_ad_enable(sc); 802 mask = vrpiu_read(sc, PIUAMSK_REG_W); 803 mask &= 0xff8f; /* XXX */ 804 vrpiu_write(sc, PIUAMSK_REG_W, mask); 805 vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART); 806 /* 807 * restart next A/D polling 808 */ 809 callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval, 810 vrpiu_start_powerstate, sc); 811} 812 813void 814vrpiu_calc_powerstate(struct vrpiu_softc *sc) 815{ 816 extern void vrgiu_diff_io(void); 817 vrpiu_ad_disable(sc); 818 VPRINTF(("vrpiu:AD: %d, %d, %d\n", 819 sc->sc_battery.value[0], 820 sc->sc_battery.value[1], 821 sc->sc_battery.value[2])); 822 sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval; 823 vrpiu_send_battery_event(sc); 824 /* 825 * restart next A/D polling if change polling timming. 826 */ 827 if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval) 828 callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll, 829 vrpiu_start_powerstate, sc); 830 if (bootverbose) 831 vrgiu_diff_io(); 832 833} 834 835static void 836vrpiu_power(int why, void *arg) 837{ 838 struct vrpiu_softc *sc = arg; 839 840 switch (why) { 841 case PWR_STANDBY: 842 case PWR_SUSPEND: 843 break; 844 case PWR_RESUME: 845 callout_reset(&sc->sc_adpoll, hz, 846 vrpiu_start_powerstate, sc); 847 break; 848 } 849} 850 851static void 852vrpiu_send_battery_event(struct vrpiu_softc *sc) 853{ 854#ifdef VRPIU_ADHOC_BATTERY_EVENT 855 static int batteryhigh = 0; 856 static int batterylow = 0; 857 static int critical = 0; 858 859 if (sc->sc_battery_spec == NULL 860 || sc->sc_battery_spec->main_port == -1) 861 return; 862 863 if (sc->sc_battery.value[sc->sc_battery_spec->main_port] 864 <= sc->sc_battery_spec->dc_critical) { 865 batteryhigh = 0; 866 config_hook_call(CONFIG_HOOK_PMEVENT, 867 CONFIG_HOOK_PMEVENT_BATTERY, 868 (void *)CONFIG_HOOK_BATT_CRITICAL); 869 batterylow = 3; 870 if (critical) { 871 config_hook_call(CONFIG_HOOK_PMEVENT, 872 CONFIG_HOOK_PMEVENT_SUSPENDREQ, 873 (void *)0); 874 critical = 0; 875 batterylow = 0; 876 } 877 critical++; 878 } else if (sc->sc_battery.value[sc->sc_battery_spec->main_port] 879 <= sc->sc_battery_spec->dc_20p) { 880 batteryhigh = 0; 881 if (batterylow == 1) 882 config_hook_call(CONFIG_HOOK_PMEVENT, 883 CONFIG_HOOK_PMEVENT_BATTERY, 884 (void *)CONFIG_HOOK_BATT_20P); 885 config_hook_call(CONFIG_HOOK_PMEVENT, 886 CONFIG_HOOK_PMEVENT_BATTERY, 887 (void *)CONFIG_HOOK_BATT_LOW); 888 batterylow = 2; 889 } else if (sc->sc_battery.value[sc->sc_battery_spec->main_port] 890 <= sc->sc_battery_spec->dc_50p) { 891 batteryhigh = 0; 892 if (batterylow == 0) { 893 batterylow = 1; 894 config_hook_call(CONFIG_HOOK_PMEVENT, 895 CONFIG_HOOK_PMEVENT_BATTERY, 896 (void *)CONFIG_HOOK_BATT_50P); 897 } 898 } else if (sc->sc_battery.value[sc->sc_battery_spec->main_port] 899 >= sc->sc_battery_spec->ac_80p) { 900 batterylow = 0; 901 if (batteryhigh == 0) { 902 batteryhigh = 1; 903 config_hook_call(CONFIG_HOOK_PMEVENT, 904 CONFIG_HOOK_PMEVENT_BATTERY, 905 (void *)CONFIG_HOOK_BATT_80P); 906 config_hook_call(CONFIG_HOOK_PMEVENT, 907 CONFIG_HOOK_PMEVENT_BATTERY, 908 (void *)CONFIG_HOOK_BATT_HIGH); 909 } 910 } 911#else /* VRPIU_ADHOC_BATTERY_EVENT */ 912 config_hook_call(CONFIG_HOOK_SET, 913 CONFIG_HOOK_BATTERYVAL, 914 (void *)&sc->sc_battery); 915#endif /* VRPIU_ADHOC_BATTERY_EVENT */ 916} 917 918#ifdef DEBUG 919void 920vrpiu_dump_cntreg(unsigned int cnt) 921{ 922 printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release"); 923 printf(" state="); 924 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan) 925 printf("CmdScan"); 926 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan) 927 printf("IntervalNextScan"); 928 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan) 929 printf("PenDataScan"); 930 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch) 931 printf("WaitPenTouch"); 932 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU) 933 printf("???"); 934 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan) 935 printf("ADPortScan"); 936 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby) 937 printf("Standby"); 938 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable) 939 printf("Disable"); 940 if (cnt & PIUCNT_PADATSTOP) 941 printf(" AutoStop"); 942 if (cnt & PIUCNT_PADATSTART) 943 printf(" AutoStart"); 944 if (cnt & PIUCNT_PADSCANSTOP) 945 printf(" Stop"); 946 if (cnt & PIUCNT_PADSCANSTART) 947 printf(" Start"); 948 if (cnt & PIUCNT_PADSCANTYPE) 949 printf(" ScanPressure"); 950 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER) 951 printf(" A/D"); 952 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE) 953 printf(" Coordinate"); 954 if (cnt & PIUCNT_PIUSEQEN) 955 printf(" SeqEn"); 956 if ((cnt & PIUCNT_PIUPWR) == 0) 957 printf(" PowerOff"); 958 if ((cnt & PIUCNT_PADRST) == 0) 959 printf(" Reset"); 960 printf("\n"); 961} 962#endif 963