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