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