1 /* $NetBSD: j6x0tp.c,v 1.5 2004/05/28 17:52:07 tsarna Exp $ */ 2 3 /* 4 * Copyright (c) 2003 Valeriy E. Ushakov 5 * 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 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: j6x0tp.c,v 1.5 2004/05/28 17:52:07 tsarna Exp $"); 32 33 #include <sys/param.h> 34 #include <sys/kernel.h> 35 #include <sys/device.h> 36 #include <sys/malloc.h> 37 #include <sys/systm.h> 38 #include <sys/callout.h> 39 #ifdef GPROF 40 #include <sys/gmon.h> 41 #endif 42 43 #include "opt_j6x0tp.h" 44 45 #include <dev/wscons/wsconsio.h> 46 #include <dev/wscons/wsmousevar.h> 47 #include <dev/wscons/wskbdvar.h> 48 #include <dev/wscons/wsksymvar.h> 49 #include <dev/wscons/wsksymdef.h> 50 #include <dev/hpc/hpctpanelvar.h> 51 52 #include <machine/platid.h> 53 #include <machine/platid_mask.h> 54 55 #include <machine/intr.h> 56 57 #include <sh3/exception.h> 58 #include <sh3/intcreg.h> 59 #include <sh3/pfcreg.h> 60 #include <sh3/adcreg.h> 61 62 #include <sh3/dev/adcvar.h> 63 64 65 #define J6X0TP_DEBUG 66 #if 0 /* XXX: disabled in favor of local version that uses printf_nolog */ 67 #define DPRINTF_ENABLE 68 #define DPRINTF_DEBUG j6x0tp_debug 69 #define DPRINTF_LEVEL 0 70 #include <machine/debug.h> 71 #else 72 #ifdef J6X0TP_DEBUG 73 volatile int j6x0tp_debug = 0; 74 #define DPRINTF_PRINTF printf_nolog 75 #define DPRINTF(arg) if (j6x0tp_debug) DPRINTF_PRINTF arg 76 #define DPRINTFN(n, arg) if (j6x0tp_debug > (n)) DPRINTF_PRINTF arg 77 #else 78 #define DPRINTF(arg) ((void)0) 79 #define DPRINTFN(n, arg) ((void)0) 80 #endif 81 #endif 82 83 84 /* 85 * PFC bits pertinent to Jornada 6x0 touchpanel 86 */ 87 #define PHDR_TP_PEN_DOWN 0x08 88 89 #define SCPDR_TP_SCAN_ENABLE 0x20 90 #define SCPDR_TP_SCAN_Y 0x02 91 #define SCPDR_TP_SCAN_X 0x01 92 93 /* 94 * A/D converter channels to get x/y from 95 */ 96 #define ADC_CHANNEL_TP_Y 1 97 #define ADC_CHANNEL_TP_X 2 98 99 /* 100 * Default (read: my device :) raw X/Y values for framebuffer edges. 101 * XXX: defopt these? 102 */ 103 #define J6X0TP_FB_LEFT 38 104 #define J6X0TP_FB_RIGHT 950 105 #define J6X0TP_FB_TOP 80 106 #define J6X0TP_FB_BOTTOM 900 107 108 /* 109 * Bottom of the n'th hard icon (n = 1..4) 110 */ 111 #define J6X0TP_HARD_ICON_MAX_Y(n) \ 112 (J6X0TP_FB_TOP + ((J6X0TP_FB_BOTTOM - J6X0TP_FB_TOP) / 4) * (n)) 113 114 115 struct j6x0tp_softc { 116 struct device sc_dev; 117 118 #define J6X0TP_WSMOUSE_ENABLED 0x01 119 #define J6X0TP_WSKBD_ENABLED 0x02 120 int sc_enabled; 121 122 int sc_hard_icon; 123 124 struct callout sc_touch_ch; 125 126 struct device *sc_wsmousedev; 127 struct device *sc_wskbddev; 128 129 struct tpcalib_softc sc_tpcalib; /* calibration info for wsmouse */ 130 }; 131 132 133 /* config machinery */ 134 static int j6x0tp_match(struct device *, struct cfdata *, void *); 135 static void j6x0tp_attach(struct device *, struct device *, void *); 136 static int j6x0tp_wsmouse_submatch(struct device *, struct cfdata *, 137 void *); 138 static int j6x0tp_wskbd_submatch(struct device *, struct cfdata *, 139 void *); 140 141 /* wsmouse accessops */ 142 static int j6x0tp_wsmouse_enable(void *); 143 static int j6x0tp_wsmouse_ioctl(void *, u_long, caddr_t, int, 144 struct proc *); 145 static void j6x0tp_wsmouse_disable(void *); 146 147 /* wskbd accessops */ 148 static int j6x0tp_wskbd_enable(void *, int); 149 static void j6x0tp_wskbd_set_leds(void *, int); 150 static int j6x0tp_wskbd_ioctl(void *, u_long, caddr_t, int, 151 struct proc *); 152 153 /* internal driver routines */ 154 static void j6x0tp_enable(struct j6x0tp_softc *); 155 static void j6x0tp_disable(struct j6x0tp_softc *); 156 static int j6x0tp_set_enable(struct j6x0tp_softc *, int, int); 157 static int j6x0tp_intr(void *); 158 static void j6x0tp_start_polling(void *); 159 static void j6x0tp_stop_polling(struct j6x0tp_softc *); 160 static void j6x0tp_callout_wsmouse(void *); 161 static void j6x0tp_callout_wskbd(void *); 162 static void j6x0tp_wsmouse_input(struct j6x0tp_softc *, int, int); 163 static void j6x0tp_get_raw_xy(int *, int *); 164 static int j6x0tp_get_hard_icon(int, int); 165 166 167 const struct wsmouse_accessops j6x0tp_accessops = { 168 j6x0tp_wsmouse_enable, 169 j6x0tp_wsmouse_ioctl, 170 j6x0tp_wsmouse_disable 171 }; 172 173 static const struct wsmouse_calibcoords j6x0tp_default_calib = { 174 0, 0, 639, 239, 175 4, 176 {{ J6X0TP_FB_LEFT, J6X0TP_FB_TOP, 0, 0 }, 177 { J6X0TP_FB_RIGHT, J6X0TP_FB_TOP, 639, 0 }, 178 { J6X0TP_FB_LEFT, J6X0TP_FB_BOTTOM, 0, 239 }, 179 { J6X0TP_FB_RIGHT, J6X0TP_FB_BOTTOM, 639, 239 }} 180 }; 181 182 const struct wskbd_accessops j6x0tp_wskbd_accessops = { 183 j6x0tp_wskbd_enable, 184 j6x0tp_wskbd_set_leds, 185 j6x0tp_wskbd_ioctl 186 }; 187 188 189 #ifndef J6X0TP_SETTINGS_ICON_KEYSYM 190 #define J6X0TP_SETTINGS_ICON_KEYSYM KS_Home 191 #endif 192 #ifndef J6X0TP_PGUP_ICON_KEYSYM 193 #define J6X0TP_PGUP_ICON_KEYSYM KS_Prior 194 #endif 195 #ifndef J6X0TP_PGDN_ICON_KEYSYM 196 #define J6X0TP_PGDN_ICON_KEYSYM KS_Next 197 #endif 198 #ifndef J6X0TP_SWITCH_ICON_KEYSYM 199 #define J6X0TP_SWITCH_ICON_KEYSYM KS_End 200 #endif 201 202 static const keysym_t j6x0tp_wskbd_keydesc[] = { 203 KS_KEYCODE(1), J6X0TP_SETTINGS_ICON_KEYSYM, 204 KS_KEYCODE(2), J6X0TP_PGUP_ICON_KEYSYM, 205 KS_KEYCODE(3), J6X0TP_PGDN_ICON_KEYSYM, 206 KS_KEYCODE(4), J6X0TP_SWITCH_ICON_KEYSYM 207 }; 208 209 const struct wscons_keydesc j6x0tp_wskbd_keydesctab[] = { 210 { KB_US, 0, 211 sizeof(j6x0tp_wskbd_keydesc)/sizeof(keysym_t), 212 j6x0tp_wskbd_keydesc 213 }, 214 {0, 0, 0, 0} 215 }; 216 217 const struct wskbd_mapdata j6x0tp_wskbd_keymapdata = { 218 j6x0tp_wskbd_keydesctab, KB_US 219 }; 220 221 222 CFATTACH_DECL(j6x0tp, sizeof(struct j6x0tp_softc), 223 j6x0tp_match, j6x0tp_attach, NULL, NULL); 224 225 226 static int 227 j6x0tp_match(struct device *parent, struct cfdata *cf, void *aux) 228 { 229 230 /* 231 * XXX: does platid_mask_MACH_HP_LX matches _JORNADA_6XX too? 232 * Is 620 wired similarly? 233 */ 234 if (!platid_match(&platid, &platid_mask_MACH_HP_JORNADA_6XX)) 235 return (0); 236 237 if (strcmp(cf->cf_name, "j6x0tp") != 0) 238 return (0); 239 240 return (1); 241 } 242 243 244 /* 245 * Attach the touch panel driver and its ws* children. 246 * 247 * Note that we have to use submatch to distinguish between children 248 * because ws{kbd,mouse}_match match unconditionally. 249 */ 250 static void 251 j6x0tp_attach(struct device *parent, struct device *self, void *aux) 252 { 253 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; 254 struct wsmousedev_attach_args wsma; 255 struct wskbddev_attach_args wska; 256 257 printf("\n"); 258 259 sc->sc_enabled = 0; 260 sc->sc_hard_icon = 0; 261 262 /* touch-panel as a pointing device */ 263 wsma.accessops = &j6x0tp_accessops; 264 wsma.accesscookie = sc; 265 266 sc->sc_wsmousedev = config_found_sm(self, &wsma, wsmousedevprint, 267 j6x0tp_wsmouse_submatch); 268 if (sc->sc_wsmousedev == NULL) 269 return; 270 271 /* on-screen "hard icons" as a keyboard device */ 272 wska.console = 0; 273 wska.keymap = &j6x0tp_wskbd_keymapdata; 274 wska.accessops = &j6x0tp_wskbd_accessops; 275 wska.accesscookie = sc; 276 277 sc->sc_wskbddev = config_found_sm(self, &wska, wskbddevprint, 278 j6x0tp_wskbd_submatch); 279 280 /* init calibration, set default parameters */ 281 tpcalib_init(&sc->sc_tpcalib); 282 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 283 (caddr_t)&j6x0tp_default_calib, 0, 0); 284 285 /* used when in polling mode */ 286 callout_init(&sc->sc_touch_ch); 287 288 /* establish interrupt handler, but disable until opened */ 289 intc_intr_establish(SH7709_INTEVT2_IRQ3, IST_EDGE, IPL_TTY, 290 j6x0tp_intr, sc); 291 intc_intr_disable(SH7709_INTEVT2_IRQ3); 292 } 293 294 295 static int 296 j6x0tp_wsmouse_submatch(struct device *parent, struct cfdata *cf, void *aux) 297 { 298 299 return (!strcmp(cf->cf_name, "wsmouse")); 300 } 301 302 303 static int 304 j6x0tp_wskbd_submatch(struct device *parent, struct cfdata *cf, void *aux) 305 { 306 307 return (!strcmp(cf->cf_name, "wskbd")); 308 } 309 310 311 /* 312 * Enable touch panel: we start in interrupt mode. 313 * Must be called as spltty(). 314 */ 315 static void 316 j6x0tp_enable(struct j6x0tp_softc *sc) 317 { 318 319 DPRINTFN(2, ("%s: enable\n", sc->sc_dev.dv_xname)); 320 intc_intr_enable(SH7709_INTEVT2_IRQ3); 321 } 322 323 324 /* 325 * Disable touch panel: disable interrupt, cancel pending callout. 326 * Must be called as spltty(). 327 */ 328 static void 329 j6x0tp_disable(struct j6x0tp_softc *sc) 330 { 331 332 DPRINTFN(2, ("%s: disable\n", sc->sc_dev.dv_xname)); 333 intc_intr_disable(SH7709_INTEVT2_IRQ3); 334 callout_stop(&sc->sc_touch_ch); 335 } 336 337 338 static int 339 j6x0tp_set_enable(struct j6x0tp_softc *sc, int on, int child) 340 { 341 int s = spltty(); 342 343 if (on) { 344 if (!sc->sc_enabled) 345 j6x0tp_enable(sc); 346 sc->sc_enabled |= child; 347 } else { 348 sc->sc_enabled &= ~child; 349 if (!sc->sc_enabled) 350 j6x0tp_disable(sc); 351 } 352 353 splx(s); 354 return (0); 355 } 356 357 358 static int 359 j6x0tp_wsmouse_enable(void *self) 360 { 361 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; 362 363 DPRINTFN(1, ("%s: wsmouse enable\n", sc->sc_dev.dv_xname)); 364 return (j6x0tp_set_enable(sc, 1, J6X0TP_WSMOUSE_ENABLED)); 365 } 366 367 368 static void 369 j6x0tp_wsmouse_disable(void *self) 370 { 371 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; 372 373 DPRINTFN(1, ("%s: wsmouse disable\n", sc->sc_dev.dv_xname)); 374 j6x0tp_set_enable(sc, 0, J6X0TP_WSMOUSE_ENABLED); 375 } 376 377 378 static int 379 j6x0tp_wskbd_enable(void *self, int on) 380 { 381 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; 382 383 DPRINTFN(1, ("%s: wskbd %sable\n", sc->sc_dev.dv_xname, 384 on ? "en" : "dis")); 385 return (j6x0tp_set_enable(sc, on, J6X0TP_WSKBD_ENABLED)); 386 } 387 388 389 static int 390 j6x0tp_intr(void *self) 391 { 392 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; 393 394 uint8_t irr0; 395 uint8_t phdr, touched; 396 unsigned int steady, tremor_timeout; 397 398 irr0 = _reg_read_1(SH7709_IRR0); 399 if ((irr0 & IRR0_IRQ3) == 0) { 400 #ifdef DIAGNOSTIC 401 printf("%s: irr0 %02x?\n", sc->sc_dev.dv_xname, irr0); 402 #endif 403 return (0); 404 } 405 406 if (!sc->sc_enabled) { 407 DPRINTFN(1, ("%s: intr: !sc_enabled\n", sc->sc_dev.dv_xname)); 408 intc_intr_disable(SH7709_INTEVT2_IRQ3); 409 goto served; 410 } 411 412 413 /* 414 * Number of times the "touched" bit should be read 415 * consecutively. 416 */ 417 # define TREMOR_THRESHOLD 0x300 418 419 steady = 0; 420 tremor_timeout = TREMOR_THRESHOLD * 16; /* XXX: arbitrary */ 421 touched = PHDR_TP_PEN_DOWN; /* we start with "touched" state */ 422 423 do { 424 phdr = _reg_read_1(SH7709_PHDR); 425 426 if ((phdr & PHDR_TP_PEN_DOWN) == touched) 427 ++steady; 428 else { 429 steady = 0; 430 touched = phdr & PHDR_TP_PEN_DOWN; 431 } 432 433 if (--tremor_timeout == 0) { 434 DPRINTF(("%s: tremor timeout!\n", 435 sc->sc_dev.dv_xname)); 436 goto served; 437 } 438 } while (steady < TREMOR_THRESHOLD); 439 440 if (touched) { 441 intc_intr_disable(SH7709_INTEVT2_IRQ3); 442 443 /* 444 * ADC readings are not stable yet, so schedule 445 * callout instead of accessing ADC from the interrupt 446 * handler only to immediately delay(). 447 */ 448 callout_reset(&sc->sc_touch_ch, hz/32, 449 j6x0tp_start_polling, sc); 450 } else 451 DPRINTFN(1, ("%s: tremor\n", sc->sc_dev.dv_xname)); 452 served: 453 /* clear the interrupt (XXX: protect access?) */ 454 _reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ3); 455 456 return (1); 457 } 458 459 460 /* 461 * Called from the interrupt handler at spltty() upon first touch. 462 * Decide if we are going to report this touch as a mouse click/drag 463 * or as a key press. 464 */ 465 static void 466 j6x0tp_start_polling(void *self) 467 { 468 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; 469 uint8_t phdr; 470 int do_mouse, do_kbd; 471 int rawx, rawy; 472 int icon; 473 474 phdr = _reg_read_1(SH7709_PHDR); 475 if ((phdr & PHDR_TP_PEN_DOWN) == 0) { 476 DPRINTFN(2, ("%s: start: pen is not down\n", 477 sc->sc_dev.dv_xname)); 478 j6x0tp_stop_polling(sc); 479 } 480 481 j6x0tp_get_raw_xy(&rawx, &rawy); 482 DPRINTFN(2, ("%s: start: %4d %4d -> ", 483 sc->sc_dev.dv_xname, rawx, rawy)); 484 485 do_mouse = sc->sc_enabled & J6X0TP_WSMOUSE_ENABLED; 486 #ifdef J6X0TP_WSMOUSE_EXCLUSIVE 487 if (do_mouse) 488 do_kbd = 0; 489 else 490 #endif 491 do_kbd = sc->sc_enabled & J6X0TP_WSKBD_ENABLED; 492 493 icon = 0; 494 if (do_kbd) 495 icon = j6x0tp_get_hard_icon(rawx, rawy); 496 497 if (icon != 0) { 498 DPRINTFN(2, ("icon %d\n", icon)); 499 sc->sc_hard_icon = icon; 500 wskbd_input(sc->sc_wskbddev, WSCONS_EVENT_KEY_DOWN, icon); 501 callout_reset(&sc->sc_touch_ch, hz/32, 502 j6x0tp_callout_wskbd, sc); 503 } else if (do_mouse) { 504 DPRINTFN(2, ("mouse\n")); 505 j6x0tp_wsmouse_input(sc, rawx, rawy); 506 callout_reset(&sc->sc_touch_ch, hz/32, 507 j6x0tp_callout_wsmouse, sc); 508 } else { 509 DPRINTFN(2, ("ignore\n")); 510 j6x0tp_stop_polling(sc); 511 } 512 } 513 514 515 /* 516 * Re-enable touch panel interrupt. 517 * Called as spltty() when polling code detects pen-up. 518 */ 519 static void 520 j6x0tp_stop_polling(struct j6x0tp_softc *sc) 521 { 522 uint8_t irr0; 523 524 DPRINTFN(2, ("%s: stop\n", sc->sc_dev.dv_xname)); 525 526 /* clear pending interrupt signal before re-enabling the interrupt */ 527 irr0 = _reg_read_1(SH7709_IRR0); 528 if ((irr0 & IRR0_IRQ3) != 0) 529 _reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ3); 530 531 intc_intr_enable(SH7709_INTEVT2_IRQ3); 532 } 533 534 535 /* 536 * We are reporting this touch as a keyboard event. 537 * Poll touch screen waiting for pen-up. 538 */ 539 static void 540 j6x0tp_callout_wskbd(void *self) 541 { 542 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; 543 uint8_t phdr; 544 int s; 545 546 s = spltty(); 547 548 if (!sc->sc_enabled) { 549 DPRINTFN(1, ("%s: wskbd callout: !sc_enabled\n", 550 sc->sc_dev.dv_xname)); 551 splx(s); 552 return; 553 } 554 555 phdr = _reg_read_1(SH7709_PHDR); 556 if ((phdr & PHDR_TP_PEN_DOWN) != 0) { 557 /* 558 * Pen is still down, continue polling. Wskbd's 559 * auto-repeat takes care of repeating the key. 560 */ 561 callout_schedule(&sc->sc_touch_ch, hz/32); 562 } else { 563 wskbd_input(sc->sc_wskbddev, 564 WSCONS_EVENT_KEY_UP, sc->sc_hard_icon); 565 j6x0tp_stop_polling(sc); 566 } 567 splx(s); 568 } 569 570 571 /* 572 * We are reporting this touch as a mouse click/drag. 573 */ 574 static void 575 j6x0tp_callout_wsmouse(void *self) 576 { 577 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; 578 uint8_t phdr; 579 int rawx, rawy; 580 int s; 581 582 s = spltty(); 583 584 if (!sc->sc_enabled) { 585 DPRINTFN(1, ("%s: wsmouse callout: !sc_enabled\n", 586 sc->sc_dev.dv_xname)); 587 splx(s); 588 return; 589 } 590 591 phdr = _reg_read_1(SH7709_PHDR); 592 if ((phdr & PHDR_TP_PEN_DOWN) != 0) { 593 j6x0tp_get_raw_xy(&rawx, &rawy); 594 j6x0tp_wsmouse_input(sc, rawx, rawy); /* mouse dragged */ 595 callout_schedule(&sc->sc_touch_ch, hz/32); 596 } else { 597 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, /* button up */ 598 WSMOUSE_INPUT_DELTA); 599 j6x0tp_stop_polling(sc); 600 } 601 splx(s); 602 } 603 604 605 /* 606 * Report mouse click/drag. 607 */ 608 static void 609 j6x0tp_wsmouse_input(struct j6x0tp_softc *sc, int rawx, int rawy) 610 { 611 int x, y; 612 613 tpcalib_trans(&sc->sc_tpcalib, rawx, rawy, &x, &y); 614 615 DPRINTFN(3, ("%s: %4d %4d -> %3d %3d\n", 616 sc->sc_dev.dv_xname, rawx, rawy, x, y)); 617 618 wsmouse_input(sc->sc_wsmousedev, 619 1, /* button */ 620 x, y, 621 0, /* flags */ 622 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 623 } 624 625 626 /* 627 * Read raw X/Y coordinates from the ADC. 628 * XXX: protect accesses to SCPDR? 629 */ 630 static void 631 j6x0tp_get_raw_xy(int *rawxp, int *rawyp) 632 { 633 uint8_t scpdr; 634 635 /* Y axis */ 636 scpdr = _reg_read_1(SH7709_SCPDR); 637 scpdr |= SCPDR_TP_SCAN_ENABLE; 638 scpdr &= ~SCPDR_TP_SCAN_Y; /* pull low to scan */ 639 _reg_write_1(SH7709_SCPDR, scpdr); 640 delay(10); 641 642 *rawyp = adc_sample_channel(ADC_CHANNEL_TP_Y); 643 644 /* X axis */ 645 scpdr = _reg_read_1(SH7709_SCPDR); 646 scpdr |= SCPDR_TP_SCAN_Y; 647 scpdr &= ~SCPDR_TP_SCAN_X; /* pull low to scan */ 648 _reg_write_1(SH7709_SCPDR, scpdr); 649 delay(10); 650 651 *rawxp = adc_sample_channel(ADC_CHANNEL_TP_X); 652 653 /* restore SCPDR */ 654 scpdr = _reg_read_1(SH7709_SCPDR); 655 scpdr |= SCPDR_TP_SCAN_X; 656 scpdr &= ~SCPDR_TP_SCAN_ENABLE; 657 _reg_write_1(SH7709_SCPDR, scpdr); 658 } 659 660 661 /* 662 * Check if the (rawx, rawy) is inside one of the 4 hard icons. 663 * Return the icon number 1..4, or 0 if not inside an icon. 664 */ 665 static int 666 j6x0tp_get_hard_icon(int rawx, int rawy) 667 { 668 if (rawx <= J6X0TP_FB_RIGHT) 669 return (0); 670 671 if (rawy < J6X0TP_HARD_ICON_MAX_Y(1)) 672 return (1); 673 else if (rawy < J6X0TP_HARD_ICON_MAX_Y(2)) 674 return (2); 675 else if (rawy < J6X0TP_HARD_ICON_MAX_Y(3)) 676 return (3); 677 else 678 return (4); 679 } 680 681 682 static int 683 j6x0tp_wsmouse_ioctl(void *self, u_long cmd, caddr_t data, int flag, 684 struct proc *p) 685 { 686 struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; 687 688 return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, p); 689 } 690 691 692 static int 693 j6x0tp_wskbd_ioctl(void *self, u_long cmd, caddr_t data, int flag, 694 struct proc *p) 695 { 696 /* struct j6x0tp_softc *sc = (struct j6x0tp_softc *)self; */ 697 698 switch (cmd) { 699 case WSKBDIO_GTYPE: 700 *(int *)data = WSKBD_TYPE_HPC_BTN; /* may be use new type? */ 701 return (0); 702 703 case WSKBDIO_GETLEDS: 704 *(int *)data = 0; 705 return (0); 706 707 default: 708 return (EPASSTHROUGH); 709 } 710 } 711 712 713 static void 714 j6x0tp_wskbd_set_leds(void *self, int leds) 715 { 716 717 /* nothing to do*/ 718 return; 719 } 720