vrpiu.c revision 1.42
1/* $NetBSD: vrpiu.c,v 1.42 2012/10/27 17:17:56 chs Exp $ */ 2 3/* 4 * Copyright (c) 1999-2003 TAKEMURA Shin All rights reserved. 5 * Copyright (c) 2000-2001 SATO Kazumi, All rights reserved. 6 * Copyright (c) 1999-2001 PocketBSD Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 */ 30 31/* 32 * A/D polling part written by SATO Kazumi. 33 */ 34 35#include <sys/cdefs.h> 36__KERNEL_RCSID(0, "$NetBSD: vrpiu.c,v 1.42 2012/10/27 17:17:56 chs Exp $"); 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/device.h> 41#include <sys/kernel.h> 42#include <sys/callout.h> 43#include <sys/boot_flag.h> 44 45#include <dev/wscons/wsconsio.h> 46#include <dev/wscons/wsmousevar.h> 47 48#include <machine/bus.h> 49#include <machine/platid.h> 50#include <machine/platid_mask.h> 51#include <machine/config_hook.h> 52 53#include <dev/hpc/hpctpanelvar.h> 54 55#include <dev/hpc/hpcbatteryvar.h> 56#include <dev/hpc/hpcbatterytable.h> 57 58#include <hpcmips/vr/vrcpudef.h> 59#include <hpcmips/vr/vripif.h> 60#include <hpcmips/vr/cmureg.h> 61#include <hpcmips/vr/vrpiuvar.h> 62#define PIUB_REG_OFFSSET 0 63#include <hpcmips/vr/vrpiureg.h> 64 65/* 66 * contant and macro definitions 67 */ 68#define VRPIUDEBUG 69#ifdef VRPIUDEBUG 70int vrpiu_debug = 0; 71#define DPRINTF(arg) if (vrpiu_debug) printf arg; 72#define VPRINTF(arg) if (bootverbose || vrpiu_debug) printf arg; 73#else 74#define DPRINTF(arg) 75#define VPRINTF(arg) if (bootverbose) printf arg; 76#endif 77 78#ifndef VRPIU_NO_ADHOC_BATTERY_EVENT 79#define VRPIU_ADHOC_BATTERY_EVENT /* currently... */ 80#endif /* VRPIU_NO_ADHOC_BATTERY_EVENT */ 81 82#ifndef VRPIU_AD_POLL_INTERVAL 83#define VRPIU_AD_POLL_INTERVAL 60 /* interval is 60 sec */ 84#endif /* VRPIU_AD_POLL_INTERTVAL */ 85 86#define PIUSIVL_SCANINTVAL_MIN 333 /* 10msec */ 87#define PIUSIVL_SCANINTVAL_MAX PIUSIVL_SCANINTVAL_MASK /* 60msec */ 88#define VRPIU_TP_SCAN_TIMEOUT (hz/10) /* timeout is 100msec */ 89 90#define TP_INTR (PIUINT_ALLINTR & ~PIUINT_PADADPINTR) 91#define AD_INTR (PIUINT_PADADPINTR) 92 93/* 94 * data types 95 */ 96/* struct vrpiu_softc is defined in vrpiuvar.h */ 97 98/* 99 * function prototypes 100 */ 101static int vrpiumatch(device_t, cfdata_t, void *); 102static void vrpiuattach(device_t, device_t, void *); 103static void vrc4173piuattach(device_t, device_t, void *); 104static void vrpiu_init(struct vrpiu_softc *, void *); 105 106static void vrpiu_write(struct vrpiu_softc *, int, unsigned short); 107static u_short vrpiu_read(struct vrpiu_softc *, int); 108 109static int vrpiu_intr(void *); 110static void vrpiu_tp_intr(struct vrpiu_softc *); 111static void vrpiu_ad_intr(struct vrpiu_softc *); 112#ifdef DEBUG 113static void vrpiu_dump_cntreg(unsigned int); 114#endif 115 116static int vrpiu_tp_enable(void *); 117static int vrpiu_tp_ioctl(void *, u_long, void *, int, struct lwp *); 118static void vrpiu_tp_disable(void *); 119static void vrpiu_tp_up(struct vrpiu_softc *); 120static void vrpiu_tp_timeout(void *); 121int vrpiu_ad_enable(void *); 122void vrpiu_ad_disable(void *); 123static void vrpiu_start_powerstate(void *); 124static void vrpiu_calc_powerstate(struct vrpiu_softc *); 125static void vrpiu_send_battery_event(struct vrpiu_softc *); 126static void vrpiu_power(int, void *); 127static u_int scan_interval(u_int data); 128 129/* mra is defined in mra.c */ 130int mra_Y_AX1_BX2_C(int *y, int ys, int *x1, int x1s, int *x2, int x2s, 131 int n, int scale, int *a, int *b, int *c); 132 133/* 134 * static or global variables 135 */ 136CFATTACH_DECL_NEW(vrpiu, sizeof(struct vrpiu_softc), 137 vrpiumatch, vrpiuattach, NULL, NULL); 138CFATTACH_DECL_NEW(vrc4173piu, sizeof(struct vrpiu_softc), 139 vrpiumatch, vrc4173piuattach, NULL, NULL); 140 141const struct wsmouse_accessops vrpiu_accessops = { 142 vrpiu_tp_enable, 143 vrpiu_tp_ioctl, 144 vrpiu_tp_disable, 145}; 146 147int vrpiu_ad_poll_interval = VRPIU_AD_POLL_INTERVAL; 148 149/* 150 * function definitions 151 */ 152static inline void 153vrpiu_write(struct vrpiu_softc *sc, int port, unsigned short val) 154{ 155 156 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 157} 158 159static inline u_short 160vrpiu_read(struct vrpiu_softc *sc, int port) 161{ 162 163 return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, port)); 164} 165 166static inline u_short 167vrpiu_buf_read(struct vrpiu_softc *sc, int port) 168{ 169 170 return (bus_space_read_2(sc->sc_iot, sc->sc_buf_ioh, port)); 171} 172 173static int 174vrpiumatch(device_t parent, cfdata_t cf, void *aux) 175{ 176 177 return (1); 178} 179 180static void 181vrpiuattach(device_t parent, device_t self, void *aux) 182{ 183 struct vrpiu_softc *sc = device_private(self); 184 185 sc->sc_dev = self; 186 sc->sc_ab_paddata_mask = PIUAB_PADDATA_MASK; 187 sc->sc_pb_paddata_mask = PIUPB_PADDATA_MASK; 188 sc->sc_pb_paddata_max = PIUPB_PADDATA_MAX; 189 vrpiu_init(sc, aux); 190} 191 192static void 193vrc4173piuattach(device_t parent, device_t self, void *aux) 194{ 195 struct vrpiu_softc *sc = device_private(self); 196 197 sc->sc_dev = self; 198 sc->sc_ab_paddata_mask = VRC4173PIUAB_PADDATA_MASK; 199 sc->sc_pb_paddata_mask = VRC4173PIUPB_PADDATA_MASK; 200 sc->sc_pb_paddata_max = VRC4173PIUPB_PADDATA_MAX; 201 vrpiu_init(sc, aux); 202} 203 204static void 205vrpiu_init(struct vrpiu_softc *sc, void *aux) 206{ 207 struct vrip_attach_args *va = aux; 208 struct wsmousedev_attach_args wsmaa; 209 int res; 210 bus_space_tag_t iot = va->va_iot; 211 struct platid_data *p; 212 213 if (va->va_parent_ioh != 0) 214 res = bus_space_subregion(iot, va->va_parent_ioh, va->va_addr, 215 va->va_size, &sc->sc_ioh); 216 else 217 res = bus_space_map(iot, va->va_addr, va->va_size, 0, 218 &sc->sc_ioh); 219 if (res != 0) { 220 printf(": can't map bus space\n"); 221 return; 222 } 223 if (va->va_parent_ioh != 0) 224 res = bus_space_subregion(iot, va->va_parent_ioh, va->va_addr2, 225 va->va_size2, &sc->sc_buf_ioh); 226 else 227 res = bus_space_map(iot, va->va_addr2, va->va_size2, 0, 228 &sc->sc_buf_ioh); 229 if (res != 0) { 230 printf(": can't map second bus space\n"); 231 return; 232 } 233 234 sc->sc_iot = iot; 235 sc->sc_unit = va->va_unit; 236 sc->sc_vrip = va->va_vc; 237 238 sc->sc_interval = scan_interval(WSMOUSE_RES_DEFAULT); 239 if ((p = platid_search_data(&platid, hpcbattery_parameters)) == NULL) 240 sc->sc_battery_spec = NULL; 241 else 242 sc->sc_battery_spec = p->data; 243 244 /* 245 * disable device until vrpiu_enable called 246 */ 247 sc->sc_tpstat = VRPIU_TP_STAT_DISABLE; 248 249 /* initialize touch panel timeout structure */ 250 callout_init(&sc->sc_tptimeout, 0); 251 252 /* initialize calibration context */ 253 tpcalib_init(&sc->sc_tpcalib); 254#if 1 255 /* 256 * XXX, calibrate parameters 257 */ 258 { 259 int i; 260 static const struct { 261 platid_mask_t *mask; 262 struct wsmouse_calibcoords coords; 263 } calibrations[] = { 264 { &platid_mask_MACH_NEC_MCR_700, 265 { 0, 0, 799, 599, 266 4, 267 { { 115, 80, 0, 0 }, 268 { 115, 966, 0, 599 }, 269 { 912, 80, 799, 0 }, 270 { 912, 966, 799, 599 } } } }, 271 { &platid_mask_MACH_NEC_MCR_700A, 272 { 0, 0, 799, 599, 273 4, 274 { { 115, 80, 0, 0 }, 275 { 115, 966, 0, 599 }, 276 { 912, 80, 799, 0 }, 277 { 912, 966, 799, 599 } } } }, 278 { &platid_mask_MACH_NEC_MCR_730, 279 { 0, 0, 799, 599, 280 4, 281 { { 115, 80, 0, 0 }, 282 { 115, 966, 0, 599 }, 283 { 912, 80, 799, 0 }, 284 { 912, 966, 799, 599 } } } }, 285 { &platid_mask_MACH_NEC_MCR_730A, 286 { 0, 0, 799, 599, 287 4, 288 { { 115, 80, 0, 0 }, 289 { 115, 966, 0, 599 }, 290 { 912, 80, 799, 0 }, 291 { 912, 966, 799, 599 } } } }, 292 { NULL, /* samples got on my MC-R500 */ 293 { 0, 0, 639, 239, 294 5, 295 { { 502, 486, 320, 120 }, 296 { 55, 109, 0, 0 }, 297 { 54, 913, 0, 239 }, 298 { 973, 924, 639, 239 }, 299 { 975, 123, 639, 0 } } } }, 300 }; 301 for (i = 0; ; i++) { 302 if (calibrations[i].mask == NULL 303 || platid_match(&platid, calibrations[i].mask)) 304 break; 305 } 306 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 307 (void *)__UNCONST(&calibrations[i].coords), 0, 0); 308 } 309#endif 310 311 /* install interrupt handler and enable interrupt */ 312 if (!(sc->sc_handler = 313 vrip_intr_establish(sc->sc_vrip, sc->sc_unit, 0, IPL_TTY, 314 vrpiu_intr, sc))) { 315 printf (": can't map interrupt line.\n"); 316 return; 317 } 318 319 /* mask level2 interrupt, stop scan sequencer and mask clock to piu */ 320 vrpiu_tp_disable(sc); 321 322 printf("\n"); 323 324 wsmaa.accessops = &vrpiu_accessops; 325 wsmaa.accesscookie = sc; 326 327 /* 328 * attach the wsmouse 329 */ 330 sc->sc_wsmousedev = config_found(sc->sc_dev, &wsmaa, wsmousedevprint); 331 332 /* 333 * power management events 334 */ 335 sc->sc_power_hook = powerhook_establish(device_xname(sc->sc_dev), 336 vrpiu_power, sc); 337 if (sc->sc_power_hook == NULL) 338 aprint_error("%s: WARNING: couldn't establish powerhook\n", 339 device_xname(sc->sc_dev)); 340 341 /* 342 * init A/D port polling. 343 */ 344 sc->sc_battery.n_values = 3; 345 sc->sc_battery.value[0] = -1; 346 sc->sc_battery.value[1] = -1; 347 sc->sc_battery.value[2] = -1; 348 sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval; 349 callout_init(&sc->sc_adpoll, 0); 350 callout_reset(&sc->sc_adpoll, hz, vrpiu_start_powerstate, sc); 351} 352 353/* 354 * calculate interval value 355 * input: WSMOUSE_RES_MIN - WSMOUSE_RES_MAX 356 * output: value for PIUSIVL_REG 357 */ 358static u_int 359scan_interval(u_int data) 360{ 361 int scale; 362 363 if (data < WSMOUSE_RES_MIN) 364 data = WSMOUSE_RES_MIN; 365 366 if (WSMOUSE_RES_MAX < data) 367 data = WSMOUSE_RES_MAX; 368 369 scale = WSMOUSE_RES_MAX - WSMOUSE_RES_MIN; 370 data += WSMOUSE_RES_MIN; 371 372 return PIUSIVL_SCANINTVAL_MIN + 373 (PIUSIVL_SCANINTVAL_MAX - PIUSIVL_SCANINTVAL_MIN) * 374 (scale - data) / scale; 375} 376 377int 378vrpiu_ad_enable(void *v) 379{ 380 struct vrpiu_softc *sc = v; 381 int s; 382 unsigned int cnt; 383 384 DPRINTF(("%s(%d): vrpiu_ad_enable(): interval=0x%03x\n", 385 __FILE__, __LINE__, sc->sc_interval)); 386 if (sc->sc_adstat != VRPIU_AD_STAT_DISABLE) 387 return EBUSY; 388 389 /* supply clock to PIU */ 390 vrip_power(sc->sc_vrip, sc->sc_unit, 1); 391 392 /* set scan interval */ 393 vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval); 394 395 s = spltty(); 396 397 /* clear interrupt status */ 398 vrpiu_write(sc, PIUINT_REG_W, AD_INTR); 399 400 /* Disable -> Standby */ 401 cnt = PIUCNT_PIUPWR | 402 PIUCNT_PIUMODE_COORDINATE | 403 PIUCNT_PADATSTART | PIUCNT_PADATSTOP; 404 vrpiu_write(sc, PIUCNT_REG_W, cnt); 405 406 /* Level2 interrupt register setting */ 407 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 1); 408 409 /* save pen status, touch or release */ 410 cnt = vrpiu_read(sc, PIUCNT_REG_W); 411 412 /* 413 * Enable scan sequencer operation 414 * Standby -> WaitPenTouch 415 */ 416 cnt |= PIUCNT_PIUSEQEN; 417 vrpiu_write(sc, PIUCNT_REG_W, cnt); 418 419 sc->sc_adstat = VRPIU_AD_STAT_ENABLE; 420 421 splx(s); 422 423 return 0; 424} 425 426void 427vrpiu_ad_disable(void *v) 428{ 429 struct vrpiu_softc *sc = v; 430 431 DPRINTF(("%s(%d): vrpiu_ad_disable()\n", __FILE__, __LINE__)); 432 433 /* Set level2 interrupt register to mask interrupts */ 434 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, AD_INTR, 0); 435 436 sc->sc_adstat = VRPIU_AD_STAT_DISABLE; 437 438 if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE){ 439 /* Disable scan sequencer operation and power off */ 440 vrpiu_write(sc, PIUCNT_REG_W, 0); 441 442 /* mask clock to PIU */ 443 vrip_power(sc->sc_vrip, sc->sc_unit, 0); 444 } 445} 446 447int 448vrpiu_tp_enable(void *v) 449{ 450 struct vrpiu_softc *sc = v; 451 int s; 452 unsigned int cnt; 453 454 DPRINTF(("%s(%d): vrpiu_tp_enable(): interval=0x%03x\n", 455 __FILE__, __LINE__, sc->sc_interval)); 456 if (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE) 457 return EBUSY; 458 459 /* supply clock to PIU */ 460 vrip_power(sc->sc_vrip, sc->sc_unit, 1); 461 462 /* set scan interval */ 463 vrpiu_write(sc, PIUSIVL_REG_W, sc->sc_interval); 464 465 s = spltty(); 466 467 /* clear interrupt status */ 468 vrpiu_write(sc, PIUINT_REG_W, TP_INTR); 469 470 /* Disable -> Standby */ 471 cnt = PIUCNT_PIUPWR | 472 PIUCNT_PIUMODE_COORDINATE | 473 PIUCNT_PADATSTART | PIUCNT_PADATSTOP; 474 vrpiu_write(sc, PIUCNT_REG_W, cnt); 475 476 /* Level2 interrupt register setting */ 477 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 1); 478 479 /* save pen status, touch or release */ 480 cnt = vrpiu_read(sc, PIUCNT_REG_W); 481 482 /* 483 * Enable scan sequencer operation 484 * Standby -> WaitPenTouch 485 */ 486 cnt |= PIUCNT_PIUSEQEN; 487 vrpiu_write(sc, PIUCNT_REG_W, cnt); 488 489 /* transit status DISABLE -> TOUCH or RELEASE */ 490 sc->sc_tpstat = (cnt & PIUCNT_PENSTC) ? 491 VRPIU_TP_STAT_TOUCH : VRPIU_TP_STAT_RELEASE; 492 493 splx(s); 494 495 return 0; 496} 497 498void 499vrpiu_tp_disable(void *v) 500{ 501 struct vrpiu_softc *sc = v; 502 503 DPRINTF(("%s(%d): vrpiu_tp_disable()\n", __FILE__, __LINE__)); 504 505 /* Set level2 interrupt register to mask interrupts */ 506 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, TP_INTR, 0); 507 508 sc->sc_tpstat = VRPIU_TP_STAT_DISABLE; 509 510 if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE){ 511 /* Disable scan sequencer operation and power off */ 512 vrpiu_write(sc, PIUCNT_REG_W, 0); 513 514 /* mask clock to PIU */ 515 vrip_power(sc->sc_vrip, sc->sc_unit, 0); 516 } 517} 518 519int 520vrpiu_tp_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 521{ 522 struct vrpiu_softc *sc = v; 523 524 DPRINTF(("%s(%d): vrpiu_tp_ioctl(%08lx)\n", __FILE__, __LINE__, cmd)); 525 526 switch (cmd) { 527 case WSMOUSEIO_SRES: 528 { 529 int tp_enable; 530 int ad_enable; 531 532 tp_enable = (sc->sc_tpstat != VRPIU_TP_STAT_DISABLE); 533 ad_enable = (sc->sc_adstat != VRPIU_AD_STAT_DISABLE); 534 535 if (tp_enable) 536 vrpiu_tp_disable(sc); 537 if (ad_enable) 538 vrpiu_ad_disable(sc); 539 540 sc->sc_interval = scan_interval(*(u_int *)data); 541 DPRINTF(("%s(%d): WSMOUSEIO_SRES: *data=%d, interval=0x%03x\n", 542 __FILE__, __LINE__, *(u_int *)data, sc->sc_interval)); 543 544 if (sc->sc_interval < PIUSIVL_SCANINTVAL_MIN) 545 sc->sc_interval = PIUSIVL_SCANINTVAL_MIN; 546 547 if (PIUSIVL_SCANINTVAL_MAX < sc->sc_interval) 548 sc->sc_interval = PIUSIVL_SCANINTVAL_MAX; 549 550 if (tp_enable) 551 vrpiu_tp_enable(sc); 552 if (ad_enable) 553 vrpiu_ad_enable(sc); 554 } 555 break; 556 557 default: 558 return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, l); 559 } 560 return 0; 561} 562 563/* 564 * PIU AD interrupt handler. 565 */ 566void 567vrpiu_ad_intr(struct vrpiu_softc *sc) 568{ 569 unsigned int i; 570 unsigned int intrstat; 571 572 intrstat = vrpiu_read(sc, PIUINT_REG_W); 573 574 if (sc->sc_adstat == VRPIU_AD_STAT_DISABLE) { 575 /* 576 * the device isn't enabled. just clear interrupt. 577 */ 578 vrpiu_write(sc, PIUINT_REG_W, AD_INTR); 579 return; 580 } 581 582 if (intrstat & PIUINT_PADADPINTR) { 583 sc->sc_battery.value[0] = (unsigned int) 584 vrpiu_buf_read(sc, PIUAB(0)); 585 sc->sc_battery.value[1] = (unsigned int) 586 vrpiu_buf_read(sc, PIUAB(1)); 587 sc->sc_battery.value[2] = (unsigned int) 588 vrpiu_buf_read(sc, PIUAB(2)); 589 } 590 591 if (intrstat & PIUINT_PADADPINTR) { 592 for (i = 0; i < 3; i++) { 593 if (sc->sc_battery.value[i] & PIUAB_VALID) 594 sc->sc_battery.value[i] &= 595 sc->sc_ab_paddata_mask; 596 else 597 sc->sc_battery.value[i] = 0; 598 } 599 vrpiu_calc_powerstate(sc); 600 } 601 vrpiu_write(sc, PIUINT_REG_W, AD_INTR); 602 603 return; 604} 605/* 606 * PIU TP interrupt handler. 607 */ 608void 609vrpiu_tp_intr(struct vrpiu_softc *sc) 610{ 611 unsigned int cnt, i; 612 unsigned int intrstat, page; 613 int tpx0, tpx1, tpy0, tpy1; 614 int x, y, xraw, yraw; 615 616 tpx0 = tpx1 = tpy0 = tpy1 = 0; /* XXX: gcc -Wuninitialized */ 617 618 intrstat = vrpiu_read(sc, PIUINT_REG_W); 619 620 if (sc->sc_tpstat == VRPIU_TP_STAT_DISABLE) { 621 /* 622 * the device isn't enabled. just clear interrupt. 623 */ 624 vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR); 625 return; 626 } 627 628 page = (intrstat & PIUINT_OVP) ? 1 : 0; 629 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 630 tpx0 = vrpiu_buf_read(sc, PIUPB(page, 0)); 631 tpx1 = vrpiu_buf_read(sc, PIUPB(page, 1)); 632 tpy0 = vrpiu_buf_read(sc, PIUPB(page, 2)); 633 tpy1 = vrpiu_buf_read(sc, PIUPB(page, 3)); 634 } 635 636 if (intrstat & PIUINT_PADDLOSTINTR) { 637 page = page ? 0 : 1; 638 for (i = 0; i < 4; i++) 639 vrpiu_buf_read(sc, PIUPB(page, i)); 640 } 641 642 cnt = vrpiu_read(sc, PIUCNT_REG_W); 643#ifdef DEBUG 644 if (vrpiu_debug) 645 vrpiu_dump_cntreg(cnt); 646#endif 647 648 /* clear interrupt status */ 649 vrpiu_write(sc, PIUINT_REG_W, intrstat & TP_INTR); 650 651#if 0 652 DPRINTF(("vrpiu_intr: OVP=%d", page)); 653 if (intrstat & PIUINT_PADCMDINTR) 654 DPRINTF((" CMD")); 655 if (intrstat & PIUINT_PADADPINTR) 656 DPRINTF((" A/D")); 657 if (intrstat & PIUINT_PADPAGE1INTR) 658 DPRINTF((" PAGE1")); 659 if (intrstat & PIUINT_PADPAGE0INTR) 660 DPRINTF((" PAGE0")); 661 if (intrstat & PIUINT_PADDLOSTINTR) 662 DPRINTF((" DLOST")); 663 if (intrstat & PIUINT_PENCHGINTR) 664 DPRINTF((" PENCHG")); 665 DPRINTF(("\n")); 666#endif 667 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 668 /* 669 * just ignore scan data if status isn't Touch. 670 */ 671 if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) { 672 /* reset tp scan timeout */ 673 callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT, 674 vrpiu_tp_timeout, sc); 675 676 if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) && 677 (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) { 678 printf("vrpiu: internal error," 679 " data is not valid!\n"); 680 } else { 681 tpx0 &= sc->sc_pb_paddata_mask; 682 tpx1 &= sc->sc_pb_paddata_mask; 683 tpy0 &= sc->sc_pb_paddata_mask; 684 tpy1 &= sc->sc_pb_paddata_mask; 685#define ISVALID(n, c) ((c) - (c)/5 < (n) && (n) < (c) + (c)/5) 686 if (ISVALID(tpx0 + tpx1, sc->sc_pb_paddata_max) && 687 ISVALID(tpy0 + tpy1, sc->sc_pb_paddata_max)) { 688#if 0 689 DPRINTF(("%04x %04x %04x %04x\n", 690 tpx0, tpx1, tpy0, tpy1)); 691 DPRINTF(("%3d %3d (%4d %4d)->", tpx0, 692 tpy0, tpx0 + tpx1, tpy0 + tpy1)); 693#endif 694 xraw = tpy1 * sc->sc_pb_paddata_max / (tpy0 + tpy1); 695 yraw = tpx1 * sc->sc_pb_paddata_max / (tpx0 + tpx1); 696 DPRINTF(("%3d %3d", xraw, yraw)); 697 698 tpcalib_trans(&sc->sc_tpcalib, xraw, 699 yraw, &x, &y); 700 701 DPRINTF(("->%4d %4d", x, y)); 702 wsmouse_input(sc->sc_wsmousedev, 703 1, /* button 0 down */ 704 x, /* x */ 705 y, /* y */ 706 0, /* z */ 707 0, /* w */ 708 WSMOUSE_INPUT_ABSOLUTE_X | 709 WSMOUSE_INPUT_ABSOLUTE_Y); 710 DPRINTF(("\n")); 711 } 712 } 713 } 714 } 715 716 if (cnt & PIUCNT_PENSTC) { 717 if (sc->sc_tpstat == VRPIU_TP_STAT_RELEASE) { 718 /* 719 * pen touch 720 */ 721 DPRINTF(("PEN TOUCH\n")); 722 sc->sc_tpstat = VRPIU_TP_STAT_TOUCH; 723 /* 724 * We should not report button down event while 725 * we don't know where it occur. 726 */ 727 728 /* set tp scan timeout */ 729 callout_reset(&sc->sc_tptimeout, VRPIU_TP_SCAN_TIMEOUT, 730 vrpiu_tp_timeout, sc); 731 } 732 } else { 733 vrpiu_tp_up(sc); 734 } 735 736 if (intrstat & PIUINT_PADDLOSTINTR) { 737 cnt |= PIUCNT_PIUSEQEN; 738 vrpiu_write(sc, PIUCNT_REG_W, cnt); 739 } 740 741 return; 742} 743 744void 745vrpiu_tp_up(struct vrpiu_softc *sc) 746{ 747 if (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH) { 748 /* 749 * pen release 750 */ 751 DPRINTF(("RELEASE\n")); 752 sc->sc_tpstat = VRPIU_TP_STAT_RELEASE; 753 754 /* clear tp scan timeout */ 755 callout_stop(&sc->sc_tptimeout); 756 757 /* button 0 UP */ 758 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0, 0); 759 } 760} 761 762/* touch panel timeout handler */ 763void 764vrpiu_tp_timeout(void *v) 765{ 766 struct vrpiu_softc *sc = (struct vrpiu_softc *)v; 767 768#ifdef VRPIUDEBUG 769 { 770 unsigned int cnt = vrpiu_read(sc, PIUCNT_REG_W); 771 DPRINTF(("TIMEOUT: stat=%s reg=%s\n", 772 (sc->sc_tpstat == VRPIU_TP_STAT_TOUCH)?"touch":"release", 773 (cnt & PIUCNT_PENSTC)?"touch":"release")); 774 } 775#endif 776 vrpiu_tp_up(sc); 777} 778 779/* 780 * PIU interrupt handler. 781 */ 782int 783vrpiu_intr(void *arg) 784{ 785 struct vrpiu_softc *sc = arg; 786 787 vrpiu_ad_intr(sc); 788 vrpiu_tp_intr(sc); 789 790 return 0; 791} 792 793void 794vrpiu_start_powerstate(void *v) 795{ 796 int mask; 797 struct vrpiu_softc *sc = (struct vrpiu_softc *)v; 798 799 vrpiu_ad_enable(sc); 800 mask = vrpiu_read(sc, PIUAMSK_REG_W); 801 mask &= 0xff8f; /* XXX */ 802 vrpiu_write(sc, PIUAMSK_REG_W, mask); 803 vrpiu_write(sc, PIUASCN_REG_W, PIUACN_ADPSSTART); 804 /* 805 * restart next A/D polling 806 */ 807 callout_reset(&sc->sc_adpoll, hz*vrpiu_ad_poll_interval, 808 vrpiu_start_powerstate, sc); 809} 810 811void 812vrpiu_calc_powerstate(struct vrpiu_softc *sc) 813{ 814 extern void vrgiu_diff_io(void); 815 vrpiu_ad_disable(sc); 816 VPRINTF(("vrpiu:AD: %d, %d, %d\n", 817 sc->sc_battery.value[0], 818 sc->sc_battery.value[1], 819 sc->sc_battery.value[2])); 820 sc->sc_battery.nextpoll = hz*vrpiu_ad_poll_interval; 821 vrpiu_send_battery_event(sc); 822 /* 823 * restart next A/D polling if change polling timming. 824 */ 825 if (sc->sc_battery.nextpoll != hz*vrpiu_ad_poll_interval) 826 callout_reset(&sc->sc_adpoll, sc->sc_battery.nextpoll, 827 vrpiu_start_powerstate, sc); 828 if (bootverbose) 829 vrgiu_diff_io(); 830 831} 832 833static void 834vrpiu_power(int why, void *arg) 835{ 836 struct vrpiu_softc *sc = arg; 837 838 switch (why) { 839 case PWR_STANDBY: 840 case PWR_SUSPEND: 841 break; 842 case PWR_RESUME: 843 callout_reset(&sc->sc_adpoll, hz, 844 vrpiu_start_powerstate, sc); 845 break; 846 } 847} 848 849static void 850vrpiu_send_battery_event(struct vrpiu_softc *sc) 851{ 852#ifdef VRPIU_ADHOC_BATTERY_EVENT 853 static int batteryhigh = 0; 854 static int batterylow = 0; 855 static int critical = 0; 856 857 if (sc->sc_battery_spec == NULL 858 || sc->sc_battery_spec->main_port == -1) 859 return; 860 861 if (sc->sc_battery.value[sc->sc_battery_spec->main_port] 862 <= sc->sc_battery_spec->dc_critical) { 863 batteryhigh = 0; 864 config_hook_call(CONFIG_HOOK_PMEVENT, 865 CONFIG_HOOK_PMEVENT_BATTERY, 866 (void *)CONFIG_HOOK_BATT_CRITICAL); 867 batterylow = 3; 868 if (critical) { 869 config_hook_call(CONFIG_HOOK_PMEVENT, 870 CONFIG_HOOK_PMEVENT_SUSPENDREQ, 871 (void *)0); 872 critical = 0; 873 batterylow = 0; 874 } 875 critical++; 876 } else if (sc->sc_battery.value[sc->sc_battery_spec->main_port] 877 <= sc->sc_battery_spec->dc_20p) { 878 batteryhigh = 0; 879 if (batterylow == 1) 880 config_hook_call(CONFIG_HOOK_PMEVENT, 881 CONFIG_HOOK_PMEVENT_BATTERY, 882 (void *)CONFIG_HOOK_BATT_20P); 883 config_hook_call(CONFIG_HOOK_PMEVENT, 884 CONFIG_HOOK_PMEVENT_BATTERY, 885 (void *)CONFIG_HOOK_BATT_LOW); 886 batterylow = 2; 887 } else if (sc->sc_battery.value[sc->sc_battery_spec->main_port] 888 <= sc->sc_battery_spec->dc_50p) { 889 batteryhigh = 0; 890 if (batterylow == 0) { 891 batterylow = 1; 892 config_hook_call(CONFIG_HOOK_PMEVENT, 893 CONFIG_HOOK_PMEVENT_BATTERY, 894 (void *)CONFIG_HOOK_BATT_50P); 895 } 896 } else if (sc->sc_battery.value[sc->sc_battery_spec->main_port] 897 >= sc->sc_battery_spec->ac_80p) { 898 batterylow = 0; 899 if (batteryhigh == 0) { 900 batteryhigh = 1; 901 config_hook_call(CONFIG_HOOK_PMEVENT, 902 CONFIG_HOOK_PMEVENT_BATTERY, 903 (void *)CONFIG_HOOK_BATT_80P); 904 config_hook_call(CONFIG_HOOK_PMEVENT, 905 CONFIG_HOOK_PMEVENT_BATTERY, 906 (void *)CONFIG_HOOK_BATT_HIGH); 907 } 908 } 909#else /* VRPIU_ADHOC_BATTERY_EVENT */ 910 config_hook_call(CONFIG_HOOK_SET, 911 CONFIG_HOOK_BATTERYVAL, 912 (void *)&sc->sc_battery); 913#endif /* VRPIU_ADHOC_BATTERY_EVENT */ 914} 915 916#ifdef DEBUG 917void 918vrpiu_dump_cntreg(unsigned int cnt) 919{ 920 printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release"); 921 printf(" state="); 922 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan) 923 printf("CmdScan"); 924 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan) 925 printf("IntervalNextScan"); 926 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan) 927 printf("PenDataScan"); 928 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch) 929 printf("WaitPenTouch"); 930 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU) 931 printf("???"); 932 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan) 933 printf("ADPortScan"); 934 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby) 935 printf("Standby"); 936 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable) 937 printf("Disable"); 938 if (cnt & PIUCNT_PADATSTOP) 939 printf(" AutoStop"); 940 if (cnt & PIUCNT_PADATSTART) 941 printf(" AutoStart"); 942 if (cnt & PIUCNT_PADSCANSTOP) 943 printf(" Stop"); 944 if (cnt & PIUCNT_PADSCANSTART) 945 printf(" Start"); 946 if (cnt & PIUCNT_PADSCANTYPE) 947 printf(" ScanPressure"); 948 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER) 949 printf(" A/D"); 950 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE) 951 printf(" Coordinate"); 952 if (cnt & PIUCNT_PIUSEQEN) 953 printf(" SeqEn"); 954 if ((cnt & PIUCNT_PIUPWR) == 0) 955 printf(" PowerOff"); 956 if ((cnt & PIUCNT_PADRST) == 0) 957 printf(" Reset"); 958 printf("\n"); 959} 960#endif 961