vrpiu.c revision 1.3
1/* $NetBSD: vrpiu.c,v 1.3 2000/01/10 14:08:03 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/dev/tpcalibvar.h> 41#include <hpcmips/vr/vripvar.h> 42#include <hpcmips/vr/cmureg.h> 43#include <hpcmips/vr/vrpiuvar.h> 44#include <hpcmips/vr/vrpiureg.h> 45 46/* 47 * contant and macro definitions 48 */ 49#define VRPIUDEBUG 50#ifdef VRPIUDEBUG 51int vrpiu_debug = 0; 52#define DPRINTF(arg) if (vrpiu_debug) printf arg; 53#else 54#define DPRINTF(arg) 55#endif 56 57/* 58 * data types 59 */ 60/* struct vrpiu_softc is defined in vrpiuvar.h */ 61 62/* 63 * function prototypes 64 */ 65static int vrpiumatch __P((struct device *, struct cfdata *, void *)); 66static void vrpiuattach __P((struct device *, struct device *, void *)); 67 68static void vrpiu_write __P((struct vrpiu_softc *, int, unsigned short)); 69static u_short vrpiu_read __P((struct vrpiu_softc *, int)); 70 71static int vrpiu_intr __P((void *)); 72#ifdef DEBUG 73static void vrpiu_dump_cntreg __P((unsigned int cmd)); 74#endif 75 76static int vrpiu_enable __P((void *)); 77static int vrpiu_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 78static void vrpiu_disable __P((void *)); 79 80/* mra is defined in mra.c */ 81int mra_Y_AX1_BX2_C __P((int *y, int ys, int *x1, int x1s, int *x2, int x2s, 82 int n, int scale, int *a, int *b, int *c)); 83 84/* 85 * static or global variables 86 */ 87struct cfattach vrpiu_ca = { 88 sizeof(struct vrpiu_softc), vrpiumatch, vrpiuattach 89}; 90 91const struct wsmouse_accessops vrpiu_accessops = { 92 vrpiu_enable, 93 vrpiu_ioctl, 94 vrpiu_disable, 95}; 96 97/* 98 * function definitions 99 */ 100static inline void 101vrpiu_write(sc, port, val) 102 struct vrpiu_softc *sc; 103 int port; 104 unsigned short val; 105{ 106 bus_space_write_2(sc->sc_iot, sc->sc_ioh, port, val); 107} 108 109static inline u_short 110vrpiu_read(sc, port) 111 struct vrpiu_softc *sc; 112 int port; 113{ 114 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, port); 115} 116 117static int 118vrpiumatch(parent, cf, aux) 119 struct device *parent; 120 struct cfdata *cf; 121 void *aux; 122{ 123 return 1; 124} 125 126static void 127vrpiuattach(parent, self, aux) 128 struct device *parent; 129 struct device *self; 130 void *aux; 131{ 132 struct vrpiu_softc *sc = (struct vrpiu_softc *)self; 133 struct vrip_attach_args *va = aux; 134 struct wsmousedev_attach_args wsmaa; 135 136 bus_space_tag_t iot = va->va_iot; 137 bus_space_handle_t ioh; 138 139 if (bus_space_map(iot, va->va_addr, 1, 0, &ioh)) { 140 printf(": can't map bus space\n"); 141 return; 142 } 143 144 sc->sc_iot = iot; 145 sc->sc_ioh = ioh; 146 sc->sc_vrip = va->va_vc; 147 148 /* 149 * disable device until vrpiu_enable called 150 */ 151 sc->sc_stat = VRPIU_STAT_DISABLE; 152 153 tpcalib_init(&sc->sc_tpcalib); 154#if 1 155 /* 156 * XXX, calibrate parameters 157 */ 158 { 159 static struct wsmouse_calibcoords D = { 160 /* samples got on my MC-R500 */ 161 0, 0, 639, 239, 162 5, 163 { { 502, 486, 320, 120 }, 164 { 55, 109, 0, 0 }, 165 { 54, 913, 0, 239 }, 166 { 973, 924, 639, 239 }, 167 { 975, 123, 639, 0 } } 168 }; 169 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 170 (caddr_t)&D, 0, 0); 171 } 172#endif 173 174 /* install interrupt handler and enable interrupt */ 175 if (!(sc->sc_handler = 176 vrip_intr_establish(va->va_vc, va->va_intr, IPL_TTY, 177 vrpiu_intr, sc))) { 178 printf (": can't map interrupt line.\n"); 179 return; 180 } 181 182 /* mask level2 interrupt, stop scan sequencer and mask clock to piu */ 183 vrpiu_disable(sc); 184 185 printf("\n"); 186 187 wsmaa.accessops = &vrpiu_accessops; 188 wsmaa.accesscookie = sc; 189 190 /* 191 * attach the wsmouse 192 */ 193 sc->sc_wsmousedev = config_found(self, &wsmaa, wsmousedevprint); 194} 195 196int 197vrpiu_enable(v) 198 void *v; 199{ 200 struct vrpiu_softc *sc = v; 201 int s; 202 unsigned int cnt; 203 204 DPRINTF(("%s(%d): vrpiu_enable()\n", __FILE__, __LINE__)); 205 if (sc->sc_stat != VRPIU_STAT_DISABLE) 206 return EBUSY; 207 208 /* supply clock to PIU */ 209 __vrcmu_supply(CMUMSKPIU, 1); 210 211 /* Scan interval 0x7FF is maximum value */ 212 vrpiu_write(sc, PIUSIVL_REG_W, 0x7FF); 213 214 s = spltty(); 215 216 /* clear interrupt status */ 217 vrpiu_write(sc, PIUINT_REG_W, PIUINT_ALLINTR); 218 219 /* Disable -> Standby */ 220 cnt = PIUCNT_PIUPWR | 221 PIUCNT_PIUMODE_COORDINATE | 222 PIUCNT_PADATSTART | PIUCNT_PADATSTOP; 223 vrpiu_write(sc, PIUCNT_REG_W, cnt); 224 225 /* save pen status, touch or release */ 226 cnt = vrpiu_read(sc, PIUCNT_REG_W); 227 228 /* Level2 interrupt register setting */ 229 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR, 1); 230 231 /* 232 * Enable scan sequencer operation 233 * Standby -> WaitPenTouch 234 */ 235 cnt |= PIUCNT_PIUSEQEN; 236 vrpiu_write(sc, PIUCNT_REG_W, cnt); 237 238 /* transit status DISABLE -> TOUCH or RELEASE */ 239 sc->sc_stat = (cnt & PIUCNT_PENSTC) ? 240 VRPIU_STAT_TOUCH : VRPIU_STAT_RELEASE; 241 242 splx(s); 243 244 return 0; 245} 246 247void 248vrpiu_disable(v) 249 void *v; 250{ 251 struct vrpiu_softc *sc = v; 252 253 DPRINTF(("%s(%d): vrpiu_disable()\n", __FILE__, __LINE__)); 254 255 /* Set level2 interrupt register to mask interrupts */ 256 vrip_intr_setmask2(sc->sc_vrip, sc->sc_handler, PIUINT_ALLINTR, 0); 257 258 sc->sc_stat = VRPIU_STAT_DISABLE; 259 260 /* Disable scan sequencer operation and power off */ 261 vrpiu_write(sc, PIUCNT_REG_W, 0); 262 263 /* mask clock to PIU */ 264 __vrcmu_supply(CMUMSKPIU, 1); 265} 266 267int 268vrpiu_ioctl(v, cmd, data, flag, p) 269 void *v; 270 u_long cmd; 271 caddr_t data; 272 int flag; 273 struct proc *p; 274{ 275 struct vrpiu_softc *sc = v; 276 277 DPRINTF(("%s(%d): vrpiu_ioctl(%08lx)\n", __FILE__, __LINE__, cmd)); 278 279 switch (cmd) { 280 case WSMOUSEIO_GTYPE: 281 *(u_int *)data = WSMOUSE_TYPE_TPANEL; 282 break; 283 284 case WSMOUSEIO_SRES: 285 printf("%s(%d): WSMOUSRIO_SRES is not supported", 286 __FILE__, __LINE__); 287 break; 288 289 case WSMOUSEIO_SCALIBCOORDS: 290 case WSMOUSEIO_GCALIBCOORDS: 291 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p); 292 293 default: 294 return (-1); 295 } 296 return (0); 297} 298 299/* 300 * PIU interrupt handler. 301 */ 302int 303vrpiu_intr(arg) 304 void *arg; 305{ 306 struct vrpiu_softc *sc = arg; 307 unsigned int cnt, i; 308 unsigned int intrstat, page; 309 int tpx0, tpx1, tpy0, tpy1; 310 int x, y, xraw, yraw; 311 312 intrstat = vrpiu_read(sc, PIUINT_REG_W); 313 314 if (sc->sc_stat == VRPIU_STAT_DISABLE) { 315 /* 316 * the device isn't enabled. just clear interrupt. 317 */ 318 vrpiu_write(sc, PIUINT_REG_W, intrstat); 319 return (0); 320 } 321 322 page = (intrstat & PIUINT_OVP) ? 1 : 0; 323 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 324 tpx0 = vrpiu_read(sc, PIUPB(page, 0)); 325 tpx1 = vrpiu_read(sc, PIUPB(page, 1)); 326 tpy0 = vrpiu_read(sc, PIUPB(page, 2)); 327 tpy1 = vrpiu_read(sc, PIUPB(page, 3)); 328 } 329 330 if (intrstat & PIUINT_PADDLOSTINTR) { 331 page = page ? 0 : 1; 332 for (i = 0; i < 4; i++) 333 vrpiu_read(sc, PIUPB(page, i)); 334 } 335 336 cnt = vrpiu_read(sc, PIUCNT_REG_W); 337#ifdef DEBUG 338 if (vrpiu_debug) 339 vrpiu_dump_cntreg(cnt); 340#endif 341 342 /* clear interrupt status */ 343 vrpiu_write(sc, PIUINT_REG_W, intrstat); 344 345#if 0 346 DPRINTF(("vrpiu_intr: OVP=%d", page)); 347 if (intrstat & PIUINT_PADCMDINTR) 348 DPRINTF((" CMD")); 349 if (intrstat & PIUINT_PADADPINTR) 350 DPRINTF((" A/D")); 351 if (intrstat & PIUINT_PADPAGE1INTR) 352 DPRINTF((" PAGE1")); 353 if (intrstat & PIUINT_PADPAGE0INTR) 354 DPRINTF((" PAGE0")); 355 if (intrstat & PIUINT_PADDLOSTINTR) 356 DPRINTF((" DLOST")); 357 if (intrstat & PIUINT_PENCHGINTR) 358 DPRINTF((" PENCHG")); 359 DPRINTF(("\n")); 360#endif 361 if (cnt & PIUCNT_PENSTC) { 362 if (sc->sc_stat == VRPIU_STAT_RELEASE) { 363 /* 364 * pen touch 365 */ 366 DPRINTF(("PEN TOUCH\n")); 367 sc->sc_stat = VRPIU_STAT_TOUCH; 368 /* button 0 DOWN */ 369 wsmouse_input(sc->sc_wsmousedev, 370 (1 << 0), 371 0, 0, 0, 0); 372 } 373 } else { 374 if (sc->sc_stat == VRPIU_STAT_TOUCH) { 375 /* 376 * pen release 377 */ 378 DPRINTF(("RELEASE\n")); 379 sc->sc_stat = VRPIU_STAT_RELEASE; 380 /* button 0 UP */ 381 wsmouse_input(sc->sc_wsmousedev, 382 0, 383 0, 0, 0, 0); 384 } 385 } 386 387 if (intrstat & (PIUINT_PADPAGE0INTR | PIUINT_PADPAGE1INTR)) { 388 if (!((tpx0 & PIUPB_VALID) && (tpx1 & PIUPB_VALID) && 389 (tpy0 & PIUPB_VALID) && (tpy1 & PIUPB_VALID))) { 390 printf("vrpiu: internal error, data is not valid!\n"); 391 } else { 392 tpx0 &= PIUPB_PADDATA_MASK; 393 tpx1 &= PIUPB_PADDATA_MASK; 394 tpy0 &= PIUPB_PADDATA_MASK; 395 tpy1 &= PIUPB_PADDATA_MASK; 396#define ISVALID(n, c, m) ((c) - (m) < (n) && (n) < (c) + (m)) 397 if (ISVALID(tpx0 + tpx1, 1024, 200) && 398 ISVALID(tpx0 + tpx1, 1024, 200)) { 399#if 0 400 DPRINTF(("%04x %04x %04x %04x\n", 401 tpx0, tpx1, tpy0, tpy1)); 402 DPRINTF(("%3d %3d (%4d %4d)->", tpx0, tpy0, 403 tpx0 + tpx1, tpy0 + tpy1); 404#endif 405 xraw = tpy1 * 1024 / (tpy0 + tpy1); 406 yraw = tpx1 * 1024 / (tpx0 + tpx1); 407 DPRINTF(("%3d %3d", xraw, yraw)); 408 409 tpcalib_trans(&sc->sc_tpcalib, 410 xraw, yraw, &x, &y); 411 412 DPRINTF(("->%4d %4d", x, y)); 413 wsmouse_input(sc->sc_wsmousedev, 414 (cnt & PIUCNT_PENSTC) ? 1 : 0, 415 x, /* x */ 416 y, /* y */ 417 0, /* z */ 418 WSMOUSE_INPUT_ABSOLUTE_X | 419 WSMOUSE_INPUT_ABSOLUTE_Y); 420 DPRINTF(("\n")); 421 } 422 } 423 } 424 425 if (intrstat & PIUINT_PADDLOSTINTR) { 426 cnt |= PIUCNT_PIUSEQEN; 427 vrpiu_write(sc, PIUCNT_REG_W, cnt); 428 } 429 430 return 0; 431} 432 433#ifdef DEBUG 434void 435vrpiu_dump_cntreg(cnt) 436 unsigned int cnt; 437{ 438 printf("%s", (cnt & PIUCNT_PENSTC) ? "Touch" : "Release"); 439 printf(" state="); 440 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_CmdScan) 441 printf("CmdScan"); 442 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_IntervalNextScan) 443 printf("IntervalNextScan"); 444 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_PenDataScan) 445 printf("PenDataScan"); 446 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_WaitPenTouch) 447 printf("WaitPenTouch"); 448 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_RFU) 449 printf("???"); 450 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_ADPortScan) 451 printf("ADPortScan"); 452 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Standby) 453 printf("Standby"); 454 if ((cnt & PIUCNT_PADSTATE_MASK) == PIUCNT_PADSTATE_Disable) 455 printf("Disable"); 456 if (cnt & PIUCNT_PADATSTOP) 457 printf(" AutoStop"); 458 if (cnt & PIUCNT_PADATSTART) 459 printf(" AutoStart"); 460 if (cnt & PIUCNT_PADSCANSTOP) 461 printf(" Stop"); 462 if (cnt & PIUCNT_PADSCANSTART) 463 printf(" Start"); 464 if (cnt & PIUCNT_PADSCANTYPE) 465 printf(" ScanPressure"); 466 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_ADCONVERTER) 467 printf(" A/D"); 468 if ((cnt & PIUCNT_PIUMODE_MASK) == PIUCNT_PIUMODE_COORDINATE) 469 printf(" Coordinate"); 470 if (cnt & PIUCNT_PIUSEQEN) 471 printf(" SeqEn"); 472 if ((cnt & PIUCNT_PIUPWR) == 0) 473 printf(" PowerOff"); 474 if ((cnt & PIUCNT_PADRST) == 0) 475 printf(" Reset"); 476 printf("\n"); 477} 478#endif 479