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