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