vrpiu.c revision 1.5
1/* $NetBSD: vrpiu.c,v 1.5 2000/06/13 05:59:55 matt Exp $ */ 2 3/* 4 * Copyright (c) 1999 Shin Takemura All rights reserved. 5 * Copyright (c) 1999 PocketBSD Project. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/device.h> 33#include <sys/kernel.h> 34 35#include <dev/wscons/wsconsio.h> 36#include <dev/wscons/wsmousevar.h> 37 38#include <machine/bus.h> 39#include <machine/platid.h> 40#include <machine/platid_mask.h> 41 42#include <hpcmips/dev/tpcalibvar.h> 43#include <hpcmips/vr/vripvar.h> 44#include <hpcmips/vr/cmureg.h> 45#include <hpcmips/vr/vrpiuvar.h> 46#include <hpcmips/vr/vrpiureg.h> 47 48/* 49 * contant and macro definitions 50 */ 51#define VRPIUDEBUG 52#ifdef VRPIUDEBUG 53int vrpiu_debug = 0; 54#define DPRINTF(arg) if (vrpiu_debug) printf arg; 55#else 56#define DPRINTF(arg) 57#endif 58 59/* 60 * data types 61 */ 62/* struct vrpiu_softc is defined in vrpiuvar.h */ 63 64/* 65 * function prototypes 66 */ 67static int vrpiumatch __P((struct device *, struct cfdata *, void *)); 68static void vrpiuattach __P((struct device *, struct device *, void *)); 69 70static void vrpiu_write __P((struct vrpiu_softc *, int, unsigned short)); 71static u_short vrpiu_read __P((struct vrpiu_softc *, int)); 72 73static int vrpiu_intr __P((void *)); 74#ifdef DEBUG 75static void vrpiu_dump_cntreg __P((unsigned int cmd)); 76#endif 77 78static int vrpiu_enable __P((void *)); 79static int vrpiu_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 80static void vrpiu_disable __P((void *)); 81 82/* mra is defined in mra.c */ 83int mra_Y_AX1_BX2_C __P((int *y, int ys, int *x1, int x1s, int *x2, int x2s, 84 int n, int scale, int *a, int *b, int *c)); 85 86/* 87 * static or global variables 88 */ 89struct cfattach vrpiu_ca = { 90 sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach 91}; 92 93const struct wsmouse_accessops vrpiu_accessops = { 94 vrpiu_enable, 95 vrpiu_ioctl, 96 vrpiu_disable, 97}; 98 99/* 100 * function definitions 101 */ 102static inline void 103vrpiu_write(sc, port, val) 104 struct vrpiu_softc *sc; 105 int port; 106 unsigned short val; 107{ 108 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 109} 110 111static inline u_short 112vrpiu_read(sc, port) 113 struct vrpiu_softc *sc; 114 int port; 115{ 116 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port); 117} 118 119static int 120vrpiumatch(parent, cf, aux) 121 struct device *parent; 122 struct cfdata *cf; 123 void *aux; 124{ 125 return 1; 126} 127 128static void 129vrpiuattach(parent, self, aux) 130 struct device *parent; 131 struct device *self; 132 void *aux; 133{ 134 struct vrpiu_softc *sc = (struct vrpiu_softc *)self; 135 struct vrip_attach_args *va = aux; 136 struct wsmousedev_attach_args wsmaa; 137 138 bus_space_tag_t iot = va->va_iot; 139 bus_space_handle_t ioh; 140 141 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) { 142 printf(": can't map bus space\n"); 143 return; 144 } 145 146 sc->sc_iot = iot; 147 sc->sc_ioh = ioh; 148 sc->sc_vrip = va->va_vc; 149 150 /* 151 * disable device until vrpiu_enable called 152 */ 153 sc->sc_stat = VRPIU_STAT_DISABLE; 154 155 tpcalib_init(&sc->sc_tpcalib); 156#if 1 157 /* 158 * XXX, calibrate parameters 159 */ 160 { 161 int i; 162 static const struct { 163 platid_mask_t *mask; 164 struct wsmouse_calibcoords coords; 165 } calibrations[] = { 166 { &platid_mask_MACH_NEC_MCR_700A, 167 { 0, 0, 799, 599, 168 4, 169 { { 115, 80, 0, 0 }, 170 { 115, 966, 0, 599 }, 171 { 912, 80, 799, 0 }, 172 { 912, 966, 799, 599 } } } }, 173 174 { NULL, /* samples got on my MC-R500 */ 175 { 0, 0, 639, 239, 176 5, 177 { { 502, 486, 320, 120 }, 178 { 55, 109, 0, 0 }, 179 { 54, 913, 0, 239 }, 180 { 973, 924, 639, 239 }, 181 { 975, 123, 639, 0 } } } }, 182 }; 183 for (i = 0; ; i++) { 184 if (calibrations[i].mask == NULL 185 || platid_match(&platid, calibrations[i].mask)) 186 break; 187 } 188 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 189 (caddr_t)&calibrations[i].coords, 0, 0); 190 } 191#endif 192 193 /* install interrupt handler and enable interrupt */ 194 if (!(sc->sc_handler = 195 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY, 196 vrpiu_intr, sc))) { 197 printf (": can't map interrupt line.\n"); 198 return; 199 } 200 201 /* mask level2 interrupt, stop scan sequencer and mask clock to piu */ 202 vrpiu_disable(sc); 203 204 printf("\n"); 205 206 wsmaa.accessops = &vrpiu_accessops; 207 wsmaa.accesscookie = sc; 208 209 /* 210 * attach the wsmouse 211 */ 212 sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint); 213} 214 215int 216vrpiu_enable(v) 217 void *v; 218{ 219 struct vrpiu_softc *sc = v; 220 int s; 221 unsigned int cnt; 222 223 DPRINTF(("%s(%d): vrpiu_enable()\n", __FILE__, __LINE__)); 224 if (sc->sc_stat != VRPIU_STAT_DISABLE) 225 return EBUSY; 226 227 /* supply clock to PIU */ 228 __vrcmu_supply(CMUMSKPIU, 1); 229 230 /* Scan interval 0x7FF is maximum value */ 231 vrpiu_write(sc, PIUSIVL_REG_W, 0x7FF); 232 233 s = spltty(); 234 235 /* clear interrupt status */ 236 vrpiu_write(sc, PIUINT_REG_W, PIUINT_ALLINTR); 237 238 /* Disable -> Standby */ 239 cnt = PIUCNT_PIUPWR | 240 PIUCNT_PIUMODE_COORDINATE | 241 PIUCNT_PADATSTART | PIUCNT_PADATSTOP; 242 vrpiu_write(sc, PIUCNT_REG_W, cnt); 243 244 /* save pen status, touch or release */ 245 cnt = vrpiu_read(sc, PIUCNT_REG_W); 246 247 /* Level2 interrupt register setting */ 248 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR, 1); 249 250 /* 251 * Enable scan sequencer operation 252 * Standby -> WaitPenTouch 253 */ 254 cnt |= PIUCNT_PIUSEQEN; 255 vrpiu_write(sc, PIUCNT_REG_W, cnt); 256 257 /* transit status DISABLE -> TOUCH or RELEASE */ 258 sc->sc_stat = (cnt & PIUCNT_PENSTC) ? 259 VRPIU_STAT_TOUCH : VRPIU_STAT_RELEASE; 260 261 splx(s); 262 263 return 0; 264} 265 266void 267vrpiu_disable(v) 268 void *v; 269{ 270 struct vrpiu_softc *sc = v; 271 272 DPRINTF(("%s(%d): vrpiu_disable()\n", __FILE__, __LINE__)); 273 274 /* Set level2 interrupt register to mask interrupts */ 275 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR, 0); 276 277 sc->sc_stat = VRPIU_STAT_DISABLE; 278 279 /* Disable scan sequencer operation and power off */ 280 vrpiu_write(sc, PIUCNT_REG_W, 0); 281 282 /* mask clock to PIU */ 283 __vrcmu_supply(CMUMSKPIU, 1); 284} 285 286int 287vrpiu_ioctl(v, cmd, data, flag, p) 288 void *v; 289 u_long cmd; 290 caddr_t data; 291 int flag; 292 struct proc *p; 293{ 294 struct vrpiu_softc *sc = v; 295 296 DPRINTF(("%s(%d): vrpiu_ioctl(%08lx)\n", __FILE__, __LINE__, cmd)); 297 298 switch (cmd) { 299 case WSMOUSEIO_GTYPE: 300 *(u_int *)data = WSMOUSE_TYPE_TPANEL; 301 break; 302 303 case WSMOUSEIO_SRES: 304 printf("%s(%d): WSMOUSRIO_SRES is not supported", 305 __FILE__, __LINE__); 306 break; 307 308 case WSMOUSEIO_SCALIBCOORDS: 309 case WSMOUSEIO_GCALIBCOORDS: 310 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p); 311 312 default: 313 return (-1); 314 } 315 return (0); 316} 317 318/* 319 * PIU interrupt handler. 320 */ 321int 322vrpiu_intr(arg) 323 void *arg; 324{ 325 struct vrpiu_softc *sc = arg; 326 unsigned int cnt, i; 327 unsigned int intrstat, page; 328 int tpx0, tpx1, tpy0, tpy1; 329 int x, y, xraw, yraw; 330 331 intrstat = vrpiu_read(sc, PIUINT_REG_W); 332 333 if (sc->sc_stat == VRPIU_STAT_DISABLE) { 334 /* 335 * the device isn't enabled. just clear interrupt. 336 */ 337 vrpiu_write(sc, PIUINT_REG_W, intrstat); 338 return (0); 339 } 340 341 page = (intrstat & PIUINT_OVP) ? 1 : 0; 342 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 343 tpx0 = vrpiu_read(sc, PIUPB(page, 0)); 344 tpx1 = vrpiu_read(sc, PIUPB(page, 1)); 345 tpy0 = vrpiu_read(sc, PIUPB(page, 2)); 346 tpy1 = vrpiu_read(sc, PIUPB(page, 3)); 347 } 348 349 if (intrstat & PIUINT_PADDLOSTINTR) { 350 page = page ? 0 : 1; 351 for (i = 0; i < 4; i++) 352 vrpiu_read(sc, PIUPB(page, i)); 353 } 354 355 cnt = vrpiu_read(sc, PIUCNT_REG_W); 356#ifdef DEBUG 357 if (vrpiu_debug) 358 vrpiu_dump_cntreg(cnt); 359#endif 360 361 /* clear interrupt status */ 362 vrpiu_write(sc, PIUINT_REG_W, intrstat); 363 364#if 0 365 DPRINTF(("vrpiu_intr: OVP=%d", page)); 366 if (intrstat & PIUINT_PADCMDINTR) 367 DPRINTF((" CMD")); 368 if (intrstat & PIUINT_PADADPINTR) 369 DPRINTF((" A/D")); 370 if (intrstat & PIUINT_PADPAGE1INTR) 371 DPRINTF((" PAGE1")); 372 if (intrstat & PIUINT_PADPAGE0INTR) 373 DPRINTF((" PAGE0")); 374 if (intrstat & PIUINT_PADDLOSTINTR) 375 DPRINTF((" DLOST")); 376 if (intrstat & PIUINT_PENCHGINTR) 377 DPRINTF((" PENCHG")); 378 DPRINTF(("\n")); 379#endif 380 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 381 if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) && 382 (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) { 383 printf("vrpiu: internal error, data is not valid!\n"); 384 } else { 385 tpx0 &= PIUPB_PADDATA_MASK; 386 tpx1 &= PIUPB_PADDATA_MASK; 387 tpy0 &= PIUPB_PADDATA_MASK; 388 tpy1 &= PIUPB_PADDATA_MASK; 389#define ISVALID(n, c, m) ((c) - (m) < (n) && (n) < (c) + (m)) 390 if (ISVALID(tpx0 + tpx1, 1024, 200) && 391 ISVALID(tpx0 + tpx1, 1024, 200)) { 392#if 0 393 DPRINTF(("%04x %04x %04x %04x\n", 394 tpx0, tpx1, tpy0, tpy1)); 395 DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0, 396 tpx0 + tpx1, tpy0 + tpy1)); 397#endif 398 xraw = tpy1 * 1024 / (tpy0 + tpy1); 399 yraw = tpx1 * 1024 / (tpx0 + tpx1); 400 DPRINTF(("%3d %3d", xraw, yraw)); 401 402 tpcalib_trans(&sc->sc_tpcalib, 403 xraw, yraw, &x, &y); 404 405 DPRINTF(("->%4d %4d", x, y)); 406 wsmouse_input(sc->sc_wsmousedev, 407 (cnt & PIUCNT_PENSTC) ? 1 : 0, 408 x, /* x */ 409 y, /* y */ 410 0, /* z */ 411 WSMOUSE_INPUT_ABSOLUTE_X | 412 WSMOUSE_INPUT_ABSOLUTE_Y); 413 DPRINTF(("\n")); 414 } 415 } 416 } 417 418 if (cnt & PIUCNT_PENSTC) { 419 if (sc->sc_stat == VRPIU_STAT_RELEASE) { 420 /* 421 * pen touch 422 */ 423 DPRINTF(("PEN TOUCH\n")); 424 sc->sc_stat = VRPIU_STAT_TOUCH; 425 /* 426 * We should not report button down event while 427 * we don't know where it occur. 428 */ 429 } 430 } else { 431 if (sc->sc_stat == VRPIU_STAT_TOUCH) { 432 /* 433 * pen release 434 */ 435 DPRINTF(("RELEASE\n")); 436 sc->sc_stat = VRPIU_STAT_RELEASE; 437 /* button 0 UP */ 438 wsmouse_input(sc->sc_wsmousedev, 439 0, 440 0, 0, 0, 0); 441 } 442 } 443 444 if (intrstat & PIUINT_PADDLOSTINTR) { 445 cnt |= PIUCNT_PIUSEQEN; 446 vrpiu_write(sc, PIUCNT_REG_W, cnt); 447 } 448 449 return 0; 450} 451 452#ifdef DEBUG 453void 454vrpiu_dump_cntreg(cnt) 455 unsigned int cnt; 456{ 457 printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release"); 458 printf(" state="); 459 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan) 460 printf("CmdScan"); 461 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan) 462 printf("IntervalNextScan"); 463 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan) 464 printf("PenDataScan"); 465 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch) 466 printf("WaitPenTouch"); 467 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU) 468 printf("???"); 469 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan) 470 printf("ADPortScan"); 471 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby) 472 printf("Standby"); 473 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable) 474 printf("Disable"); 475 if (cnt & PIUCNT_PADATSTOP) 476 printf(" AutoStop"); 477 if (cnt & PIUCNT_PADATSTART) 478 printf(" AutoStart"); 479 if (cnt & PIUCNT_PADSCANSTOP) 480 printf(" Stop"); 481 if (cnt & PIUCNT_PADSCANSTART) 482 printf(" Start"); 483 if (cnt & PIUCNT_PADSCANTYPE) 484 printf(" ScanPressure"); 485 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER) 486 printf(" A/D"); 487 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE) 488 printf(" Coordinate"); 489 if (cnt & PIUCNT_PIUSEQEN) 490 printf(" SeqEn"); 491 if ((cnt & PIUCNT_PIUPWR) == 0) 492 printf(" PowerOff"); 493 if ((cnt & PIUCNT_PADRST) == 0) 494 printf(" Reset"); 495 printf("\n"); 496} 497#endif 498