vrpiu.c revision 1.2
1/* $NetBSD: vrpiu.c,v 1.2 2000/01/08 02:57:24 takemura 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 40#include <hpcmips/vr/vripvar.h> 41#include <hpcmips/vr/cmureg.h> 42#include <hpcmips/vr/vrpiuvar.h> 43#include <hpcmips/vr/vrpiureg.h> 44 45/* 46 * contant and macro definitions 47 */ 48#define VRPIUDEBUG 49#ifdef VRPIUDEBUG 50int vrpiu_debug = 0; 51#define DPRINTF(arg) if (vrpiu_debug) printf arg; 52#else 53#define DPRINTF(arg) 54#endif 55 56#define SCALE (1024*1024) 57 58/* 59 * data types 60 */ 61/* struct vrpiu_softc is defined in vrpiuvar.h */ 62 63/* 64 * function prototypes 65 */ 66static int vrpiumatch __P((struct device *, struct cfdata *, void *)); 67static void vrpiuattach __P((struct device *, struct device *, void *)); 68 69static void vrpiu_write __P((struct vrpiu_softc *, int, unsigned short)); 70static u_short vrpiu_read __P((struct vrpiu_softc *, int)); 71 72static int vrpiu_intr __P((void *)); 73static void vrpiu_reset_param __P((struct vrpiu_softc *sc)); 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 vrpiu_reset_param(sc); 156#if 1 157 /* 158 * XXX, calibrate parameters 159 */ 160 { 161 static struct sample { 162 int xraw, yraw, x, y; 163 } D[] = { 164 /* samples got on my MC-R500 */ 165 { 502, 486, 320, 120 }, 166 { 55, 109, 0, 0 }, 167 { 54, 913, 0, 239 }, 168 { 973, 924, 639, 239 }, 169 { 975, 123, 639, 0 }, 170 }; 171 int s = sizeof(*D); 172 int n = sizeof(D)/s; 173 174 sc->sc_prmxs = 640; 175 sc->sc_prmys = 240; 176 177 if (mra_Y_AX1_BX2_C(&D->x, s, &D->xraw, s, &D->yraw, s, n, 178 SCALE, &sc->sc_prmax, &sc->sc_prmbx, 179 &sc->sc_prmcx) || 180 mra_Y_AX1_BX2_C(&D->y, s, &D->xraw, s, &D->yraw, s, n, 181 SCALE, &sc->sc_prmay, 182 &sc->sc_prmby, &sc->sc_prmcy)) { 183 printf(": MRA error"); 184 vrpiu_reset_param(sc); 185 } else { 186 DPRINTF(("Ax=%d Bx=%d Cx=%d\n", 187 sc->sc_prmax, sc->sc_prmbx, sc->sc_prmcx)); 188 DPRINTF(("Ay=%d By=%d Cy=%d\n", 189 sc->sc_prmay, sc->sc_prmby, sc->sc_prmcy)); 190 } 191 } 192#endif 193 194 /* install interrupt handler and enable interrupt */ 195 if (!(sc->sc_handler = 196 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY, 197 vrpiu_intr, sc))) { 198 printf (": can't map interrupt line.\n"); 199 return; 200 } 201 202 /* mask level2 interrupt, stop scan sequencer and mask clock to piu */ 203 vrpiu_disable(sc); 204 205 printf("\n"); 206 207 wsmaa.accessops = &vrpiu_accessops; 208 wsmaa.accesscookie = sc; 209 210 /* 211 * attach the wsmouse 212 */ 213 sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint); 214} 215 216int 217vrpiu_enable(v) 218 void *v; 219{ 220 struct vrpiu_softc *sc = v; 221 int s; 222 unsigned int cnt; 223 224 DPRINTF(("%s(%d): vrpiu_enable()\n", __FILE__, __LINE__)); 225 if (sc->sc_stat != VRPIU_STAT_DISABLE) 226 return EBUSY; 227 228 /* supply clock to PIU */ 229 __vrcmu_supply(CMUMSKPIU, 1); 230 231 /* Scan interval 0x7FF is maximum value */ 232 vrpiu_write(sc, PIUSIVL_REG_W, 0x7FF); 233 234 s = spltty(); 235 236 /* clear interrupt status */ 237 vrpiu_write(sc, PIUINT_REG_W, PIUINT_ALLINTR); 238 239 /* Disable -> Standby */ 240 cnt = PIUCNT_PIUPWR | 241 PIUCNT_PIUMODE_COORDINATE | 242 PIUCNT_PADATSTART | PIUCNT_PADATSTOP; 243 vrpiu_write(sc, PIUCNT_REG_W, cnt); 244 245 /* save pen status, touch or release */ 246 cnt = vrpiu_read(sc, PIUCNT_REG_W); 247 248 /* Level2 interrupt register setting */ 249 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR, 1); 250 251 /* 252 * Enable scan sequencer operation 253 * Standby -> WaitPenTouch 254 */ 255 cnt |= PIUCNT_PIUSEQEN; 256 vrpiu_write(sc, PIUCNT_REG_W, cnt); 257 258 /* transit status DISABLE -> TOUCH or RELEASE */ 259 sc->sc_stat = (cnt & PIUCNT_PENSTC) ? 260 VRPIU_STAT_TOUCH : VRPIU_STAT_RELEASE; 261 262 splx(s); 263 264 return 0; 265} 266 267void 268vrpiu_disable(v) 269 void *v; 270{ 271 struct vrpiu_softc *sc = v; 272 273 DPRINTF(("%s(%d): vrpiu_disable()\n", __FILE__, __LINE__)); 274 275 /* Set level2 interrupt register to mask interrupts */ 276 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR, 0); 277 278 sc->sc_stat = VRPIU_STAT_DISABLE; 279 280 /* Disable scan sequencer operation and power off */ 281 vrpiu_write(sc, PIUCNT_REG_W, 0); 282 283 /* mask clock to PIU */ 284 __vrcmu_supply(CMUMSKPIU, 1); 285} 286 287int 288vrpiu_ioctl(v, cmd, data, flag, p) 289 void *v; 290 u_long cmd; 291 caddr_t data; 292 int flag; 293 struct proc *p; 294{ 295 struct vrpiu_softc *sc = v; 296 297 DPRINTF(("%s(%d): vrpiu_ioctl(%08lx)\n", __FILE__, __LINE__, cmd)); 298 299 switch (cmd) { 300 case WSMOUSEIO_GTYPE: 301 *(u_int *)data = WSMOUSE_TYPE_TPANEL; 302 break; 303 304 case WSMOUSEIO_SRES: 305 printf("%s(%d): WSMOUSRIO_SRES is not supported", 306 __FILE__, __LINE__); 307 break; 308 309 default: 310 return (-1); 311 } 312 return (0); 313} 314 315/* 316 * PIU interrupt handler. 317 */ 318int 319vrpiu_intr(arg) 320 void *arg; 321{ 322 struct vrpiu_softc *sc = arg; 323 unsigned int cnt, i; 324 unsigned int intrstat, page; 325 int tpx0, tpx1, tpy0, tpy1; 326 int x, y, xraw, yraw; 327 328 intrstat = vrpiu_read(sc, PIUINT_REG_W); 329 330 if (sc->sc_stat == VRPIU_STAT_DISABLE) { 331 /* 332 * the device isn't enabled. just clear interrupt. 333 */ 334 vrpiu_write(sc, PIUINT_REG_W, intrstat); 335 return (0); 336 } 337 338 page = (intrstat & PIUINT_OVP) ? 1 : 0; 339 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 340 tpx0 = vrpiu_read(sc, PIUPB(page, 0)); 341 tpx1 = vrpiu_read(sc, PIUPB(page, 1)); 342 tpy0 = vrpiu_read(sc, PIUPB(page, 2)); 343 tpy1 = vrpiu_read(sc, PIUPB(page, 3)); 344 } 345 346 if (intrstat & PIUINT_PADDLOSTINTR) { 347 page = page ? 0 : 1; 348 for (i = 0; i < 4; i++) 349 vrpiu_read(sc, PIUPB(page, i)); 350 } 351 352 cnt = vrpiu_read(sc, PIUCNT_REG_W); 353#ifdef DEBUG 354 if (vrpiu_debug) 355 vrpiu_dump_cntreg(cnt); 356#endif 357 358 /* clear interrupt status */ 359 vrpiu_write(sc, PIUINT_REG_W, intrstat); 360 361#if 0 362 DPRINTF(("vrpiu_intr: OVP=%d", page)); 363 if (intrstat & PIUINT_PADCMDINTR) 364 DPRINTF((" CMD")); 365 if (intrstat & PIUINT_PADADPINTR) 366 DPRINTF((" A/D")); 367 if (intrstat & PIUINT_PADPAGE1INTR) 368 DPRINTF((" PAGE1")); 369 if (intrstat & PIUINT_PADPAGE0INTR) 370 DPRINTF((" PAGE0")); 371 if (intrstat & PIUINT_PADDLOSTINTR) 372 DPRINTF((" DLOST")); 373 if (intrstat & PIUINT_PENCHGINTR) 374 DPRINTF((" PENCHG")); 375 DPRINTF(("\n")); 376#endif 377 if (cnt & PIUCNT_PENSTC) { 378 if (sc->sc_stat == VRPIU_STAT_RELEASE) { 379 /* 380 * pen touch 381 */ 382 DPRINTF(("PEN TOUCH\n")); 383 sc->sc_stat = VRPIU_STAT_TOUCH; 384 /* button 0 DOWN */ 385 wsmouse_input(sc->sc_wsmousedev, 386 (1 << 0), 387 0, 0, 0, 0); 388 } 389 } else { 390 if (sc->sc_stat == VRPIU_STAT_TOUCH) { 391 /* 392 * pen release 393 */ 394 DPRINTF(("RELEASE\n")); 395 sc->sc_stat = VRPIU_STAT_RELEASE; 396 /* button 0 UP */ 397 wsmouse_input(sc->sc_wsmousedev, 398 0, 399 0, 0, 0, 0); 400 } 401 } 402 403 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 404 if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) && 405 (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) { 406 printf("vrpiu: internal error, data is not valid!\n"); 407 } else { 408 tpx0 &= PIUPB_PADDATA_MASK; 409 tpx1 &= PIUPB_PADDATA_MASK; 410 tpy0 &= PIUPB_PADDATA_MASK; 411 tpy1 &= PIUPB_PADDATA_MASK; 412#define ISVALID(n, c, m) ((c) - (m) < (n) && (n) < (c) + (m)) 413 if (ISVALID(tpx0 + tpx1, 1024, 200) && 414 ISVALID(tpx0 + tpx1, 1024, 200)) { 415#if 0 416 DPRINTF(("%04x %04x %04x %04x\n", 417 tpx0, tpx1, tpy0, tpy1)); 418 DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0, 419 tpx0 + tpx1, tpy0 + tpy1); 420#endif 421 xraw = tpy1 * 1024 / (tpy0 + tpy1); 422 yraw = tpx1 * 1024 / (tpx0 + tpx1); 423 DPRINTF(("%3d %3d", xraw, yraw)); 424 425 x = (sc->sc_prmax*xraw + sc->sc_prmbx*yraw) / 426 SCALE + sc->sc_prmcx; 427 y = (sc->sc_prmay*xraw + sc->sc_prmby*yraw) / 428 SCALE + sc->sc_prmcy; 429 if (x < 0) x = 0; 430 if (y < 0) y = 0; 431 if (sc->sc_prmxs <= x) 432 x = sc->sc_prmxs - 1; 433 if (sc->sc_prmys <= y) 434 y = sc->sc_prmys - 1; 435 DPRINTF(("->%4d %4d", x, y)); 436 wsmouse_input(sc->sc_wsmousedev, 437 (cnt & PIUCNT_PENSTC) ? 1 : 0, 438 x, /* x */ 439 y, /* y */ 440 0, /* z */ 441 WSMOUSE_INPUT_ABSOLUTE_X | 442 WSMOUSE_INPUT_ABSOLUTE_Y); 443 DPRINTF(("\n")); 444 } 445 } 446 } 447 448 if (intrstat & PIUINT_PADDLOSTINTR) { 449 cnt |= PIUCNT_PIUSEQEN; 450 vrpiu_write(sc, PIUCNT_REG_W, cnt); 451 } 452 453 return 0; 454} 455 456void 457vrpiu_reset_param(sc) 458 struct vrpiu_softc *sc; 459{ 460 sc->sc_prmax = SCALE; 461 sc->sc_prmbx = 0; 462 sc->sc_prmcx = 0; 463 sc->sc_prmxs = PIUPB_PADDATA_MAX; 464 sc->sc_prmay = 0; 465 sc->sc_prmby = SCALE; 466 sc->sc_prmcy = 0; 467 sc->sc_prmys = PIUPB_PADDATA_MAX; 468} 469 470#ifdef DEBUG 471void 472vrpiu_dump_cntreg(cnt) 473 unsigned int cnt; 474{ 475 printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release"); 476 printf(" state="); 477 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan) 478 printf("CmdScan"); 479 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan) 480 printf("IntervalNextScan"); 481 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan) 482 printf("PenDataScan"); 483 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch) 484 printf("WaitPenTouch"); 485 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU) 486 printf("???"); 487 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan) 488 printf("ADPortScan"); 489 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby) 490 printf("Standby"); 491 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable) 492 printf("Disable"); 493 if (cnt & PIUCNT_PADATSTOP) 494 printf(" AutoStop"); 495 if (cnt & PIUCNT_PADATSTART) 496 printf(" AutoStart"); 497 if (cnt & PIUCNT_PADSCANSTOP) 498 printf(" Stop"); 499 if (cnt & PIUCNT_PADSCANSTART) 500 printf(" Start"); 501 if (cnt & PIUCNT_PADSCANTYPE) 502 printf(" ScanPressure"); 503 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER) 504 printf(" A/D"); 505 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE) 506 printf(" Coordinate"); 507 if (cnt & PIUCNT_PIUSEQEN) 508 printf(" SeqEn"); 509 if ((cnt & PIUCNT_PIUPWR) == 0) 510 printf(" PowerOff"); 511 if ((cnt & PIUCNT_PADRST) == 0) 512 printf(" Reset"); 513 printf("\n"); 514} 515#endif 516