1 /* $NetBSD: j720ssp.c,v 1.17 2003/01/03 04:36:29 takemura Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /*- 40 * Copyright (c) 1990 The Regents of the University of California. 41 * All rights reserved. 42 * 43 * This code is derived from software contributed to Berkeley by 44 * William Jolitz and Don Ahn. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. All advertising materials mentioning features or use of this software 55 * must display the following acknowledgement: 56 * This product includes software developed by the University of 57 * California, Berkeley and its contributors. 58 * 4. Neither the name of the University nor the names of its contributors 59 * may be used to endorse or promote products derived from this software 60 * without specific prior written permission. 61 * 62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 72 * SUCH DAMAGE. 73 * 74 * @(#)pccons.c 5.11 (Berkeley) 5/21/91 75 */ 76 77 #include "apm.h" 78 79 #include <sys/param.h> 80 #include <sys/systm.h> 81 #include <sys/device.h> 82 #include <sys/kernel.h> 83 #include <sys/malloc.h> 84 #include <sys/ioctl.h> 85 #include <sys/kthread.h> 86 #include <sys/lock.h> 87 88 #include <machine/bus.h> 89 #include <machine/config_hook.h> 90 #include <machine/bootinfo.h> 91 #include <machine/apmvar.h> 92 93 #include <hpcarm/dev/sed1356var.h> 94 95 #include <arm/sa11x0/sa11x0_var.h> 96 #include <arm/sa11x0/sa11x0_gpioreg.h> 97 #include <arm/sa11x0/sa11x0_ppcreg.h> 98 #include <arm/sa11x0/sa11x0_sspreg.h> 99 100 #include <dev/wscons/wsconsio.h> 101 #include <dev/wscons/wskbdvar.h> 102 #include <dev/wscons/wsksymdef.h> 103 #include <dev/wscons/wsksymvar.h> 104 #include <dev/wscons/wsmousevar.h> 105 #include <dev/hpc/tpcalibvar.h> 106 107 extern const struct wscons_keydesc j720kbd_keydesctab[]; 108 109 struct j720ssp_softc { 110 struct device sc_dev; 111 112 bus_space_tag_t sc_iot; 113 bus_space_handle_t sc_gpioh; 114 bus_space_handle_t sc_ssph; 115 116 struct device *sc_wskbddev; 117 struct device *sc_wsmousedev; 118 struct tpcalib_softc sc_tpcalib; 119 120 void *sc_kbdsi; 121 void *sc_tpsi; 122 int sc_enabled; 123 124 struct proc *sc_ssp_kthread; 125 int sc_ssp_status; 126 struct simplelock sc_ssp_status_lock; 127 }; 128 /* Values for struct softc's sc_ssp_status */ 129 #define J720_SSP_STATUS_NONE 0 130 #define J720_SSP_STATUS_TP 1 131 #define J720_SSP_STATUS_KBD 2 132 133 void j720ssp_create_kthread __P((void *)); 134 void j720ssp_kthread __P((void *)); 135 int j720kbd_intr __P((void *)); 136 int j720tp_intr __P((void *)); 137 void j720kbd_poll __P((void *)); 138 int j720tp_poll __P((void *)); 139 140 int j720lcdparam __P((void *, int, long, void *)); 141 static void j720kbd_read __P((struct j720ssp_softc *, char *)); 142 static int j720ssp_readwrite __P((struct j720ssp_softc *, int, 143 int, int *, int)); 144 145 int j720sspprobe __P((struct device *, struct cfdata *, void *)); 146 void j720sspattach __P((struct device *, struct device *, void *)); 147 148 int j720kbd_submatch __P((struct device *, struct cfdata *, void *)); 149 int j720tp_submatch __P((struct device *, struct cfdata *, void *)); 150 int apm_submatch __P((struct device *, struct cfdata *, void *)); 151 152 int j720kbd_enable __P((void *, int)); 153 void j720kbd_set_leds __P((void *, int)); 154 int j720kbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 155 156 int j720lcdpower(void *, int, long, void *); 157 int hpcarm_apm_getpower __P((struct apm_power_info *, void *)); 158 159 CFATTACH_DECL(j720ssp, sizeof(struct j720ssp_softc), 160 j720sspprobe, j720sspattach, NULL, NULL); 161 162 const struct wskbd_accessops j720kbd_accessops = { 163 j720kbd_enable, 164 j720kbd_set_leds, 165 j720kbd_ioctl, 166 }; 167 168 void j720kbd_cngetc __P((void *, u_int *, int *)); 169 void j720kbd_cnpollc __P((void *, int)); 170 void j720kbd_cnbell __P((void *, u_int, u_int, u_int)); 171 172 const struct wskbd_consops j720kbd_consops = { 173 j720kbd_cngetc, 174 j720kbd_cnpollc, 175 j720kbd_cnbell, 176 }; 177 178 const struct wskbd_mapdata j720kbd_keymapdata = { 179 j720kbd_keydesctab, 180 #ifdef J720KBD_LAYOUT 181 J720KBD_LAYOUT, 182 #else 183 KB_US, 184 #endif 185 }; 186 187 static int j720tp_enable __P((void *)); 188 static int j720tp_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 189 static void j720tp_disable __P((void *)); 190 191 const struct wsmouse_accessops j720tp_accessops = { 192 j720tp_enable, 193 j720tp_ioctl, 194 j720tp_disable, 195 }; 196 197 static int j720ssp_powerstate = 1; 198 199 static struct j720ssp_softc j720kbdcons_sc; 200 static int j720kbdcons_initstate = 0; 201 202 #define DEBUG 203 #ifdef DEBUG 204 int j720sspwaitcnt; 205 int j720sspwaittime; 206 extern int gettick(void); 207 #endif 208 209 #define BIT_INVERT(x) do { \ 210 (x) = ((((x) & 0xf0) >> 4) | (((x) & 0x0f) << 4)); \ 211 (x) = ((((x) & 0xcc) >> 2) | (((x) & 0x33) << 2)); \ 212 (x) = ((((x) & 0xaa) >> 1) | (((x) & 0x55) << 1)); \ 213 } while(0) 214 215 216 int 217 j720sspprobe(parent, cf, aux) 218 struct device *parent; 219 struct cfdata *cf; 220 void *aux; 221 { 222 return (1); 223 } 224 225 void 226 j720sspattach(parent, self, aux) 227 struct device *parent; 228 struct device *self; 229 void *aux; 230 { 231 struct j720ssp_softc *sc = (void *)self; 232 struct sa11x0_softc *psc = (void *)parent; 233 struct sa11x0_attach_args *sa = aux; 234 struct wskbddev_attach_args kbd_args; 235 struct wsmousedev_attach_args mouse_args; 236 #if NAPM > 0 237 struct apm_attach_args apm_args; 238 #endif 239 240 printf("\n"); 241 242 sc->sc_iot = psc->sc_iot; 243 sc->sc_gpioh = psc->sc_gpioh; 244 if (bus_space_map(sc->sc_iot, sa->sa_addr, sa->sa_size, 0, 245 &sc->sc_ssph)) { 246 printf("%s: unable to map SSP registers\n", 247 sc->sc_dev.dv_xname); 248 return; 249 } 250 251 sc->sc_ssp_status = J720_SSP_STATUS_NONE; 252 simple_lock_init(&sc->sc_ssp_status_lock); 253 kthread_create(j720ssp_create_kthread, sc); 254 255 sc->sc_enabled = 0; 256 257 kbd_args.console = 0; 258 259 kbd_args.keymap = &j720kbd_keymapdata; 260 261 kbd_args.accessops = &j720kbd_accessops; 262 kbd_args.accesscookie = sc; 263 264 /* Do console initialization */ 265 if (! (bootinfo->bi_cnuse & BI_CNUSE_SERIAL)) { 266 j720kbdcons_sc = *sc; 267 kbd_args.console = 1; 268 269 wskbd_cnattach(&j720kbd_consops, NULL, &j720kbd_keymapdata); 270 j720kbdcons_initstate = 1; 271 } 272 273 /* 274 * Attach the wskbd, saving a handle to it. 275 * XXX XXX XXX 276 */ 277 sc->sc_wskbddev = config_found_sm(self, &kbd_args, wskbddevprint, 278 j720kbd_submatch); 279 280 #ifdef DEBUG 281 /* Zero the stat counters */ 282 j720sspwaitcnt = 0; 283 j720sspwaittime = 0; 284 #endif 285 286 if (j720kbdcons_initstate == 1) 287 j720kbd_enable(sc, 1); 288 289 mouse_args.accessops = &j720tp_accessops; 290 mouse_args.accesscookie = sc; 291 292 sc->sc_wsmousedev = config_found_sm(self, &mouse_args, 293 wsmousedevprint, j720tp_submatch); 294 tpcalib_init(&sc->sc_tpcalib); 295 296 /* XXX fill in "default" calibrate param */ 297 { 298 static const struct wsmouse_calibcoords j720_default_calib = { 299 0, 0, 639, 239, 300 4, 301 { { 988, 80, 0, 0 }, 302 { 88, 84, 639, 0 }, 303 { 988, 927, 0, 239 }, 304 { 88, 940, 639, 239 } } }; 305 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 306 (caddr_t)&j720_default_calib, 0, 0); 307 } 308 309 j720tp_disable(sc); 310 311 /* Setup touchpad interrupt */ 312 sa11x0_intr_establish(0, 9, 1, IPL_BIO, j720tp_intr, sc); 313 314 /* LCD control is on the same bus */ 315 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, 316 CONFIG_HOOK_SHARE, j720lcdparam, sc); 317 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS, 318 CONFIG_HOOK_SHARE, j720lcdparam, sc); 319 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS_MAX, 320 CONFIG_HOOK_SHARE, j720lcdparam, sc); 321 322 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, 323 CONFIG_HOOK_SHARE, j720lcdparam, sc); 324 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST, 325 CONFIG_HOOK_SHARE, j720lcdparam, sc); 326 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST_MAX, 327 CONFIG_HOOK_SHARE, j720lcdparam, sc); 328 329 #if NAPM > 0 330 /* attach APM emulation */ 331 apm_args.aaa_magic = APM_ATTACH_ARGS_MAGIC; /* magic number */ 332 (void)config_found_sm(self, &apm_args, NULL, apm_submatch); 333 #endif 334 335 return; 336 } 337 338 void 339 j720ssp_create_kthread(arg) 340 void *arg; 341 { 342 struct j720ssp_softc *sc = arg; 343 344 if (kthread_create1(j720ssp_kthread, sc, 345 &sc->sc_ssp_kthread, "j720ssp")) 346 panic("j720ssp_create_kthread"); 347 348 return; 349 } 350 351 void 352 j720ssp_kthread(arg) 353 void *arg; 354 { 355 struct j720ssp_softc *sc = arg; 356 int ssp_status; 357 358 while (1) { 359 if (ssp_status & J720_SSP_STATUS_TP) 360 tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", hz / 25); 361 else 362 tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", 0); 363 364 simple_lock(&sc->sc_ssp_status_lock); 365 ssp_status = sc->sc_ssp_status; 366 sc->sc_ssp_status &= ~J720_SSP_STATUS_KBD; 367 simple_unlock(&sc->sc_ssp_status_lock); 368 369 if (ssp_status & J720_SSP_STATUS_KBD) 370 j720kbd_poll(sc); 371 372 if (ssp_status & J720_SSP_STATUS_TP) { 373 if (j720tp_poll(sc) == 0) { 374 simple_lock(&sc->sc_ssp_status_lock); 375 sc->sc_ssp_status &= ~J720_SSP_STATUS_TP; 376 simple_unlock(&sc->sc_ssp_status_lock); 377 } 378 } 379 } 380 381 /* NOTREACHED */ 382 } 383 384 385 int 386 j720kbd_submatch(parent, cf, aux) 387 struct device *parent; 388 struct cfdata *cf; 389 void *aux; 390 { 391 if (strcmp(cf->cf_name, "wskbd") == 0) 392 return (1); 393 return (0); 394 } 395 396 int 397 j720tp_submatch(parent, cf, aux) 398 struct device *parent; 399 struct cfdata *cf; 400 void *aux; 401 { 402 if (strcmp(cf->cf_name, "wsmouse") == 0) 403 return (1); 404 return (0); 405 } 406 407 int 408 apm_submatch(parent, cf, aux) 409 struct device *parent; 410 struct cfdata *cf; 411 void *aux; 412 { 413 if (strcmp(cf->cf_name, "apm") == 0) 414 return (1); 415 return (0); 416 } 417 418 int 419 j720kbd_enable(v, on) 420 void *v; 421 int on; 422 { 423 struct j720ssp_softc *sc = v; 424 425 if (! sc->sc_enabled) { 426 sc->sc_enabled = 1; 427 428 sa11x0_intr_establish(0, 0, 1, IPL_BIO, j720kbd_intr, sc); 429 } 430 /* XXX */ 431 return (0); 432 } 433 434 void 435 j720kbd_set_leds(v, on) 436 void *v; 437 int on; 438 { 439 /* XXX */ 440 return; 441 } 442 443 int 444 j720kbd_ioctl(v, cmd, data, flag, p) 445 void *v; 446 u_long cmd; 447 caddr_t data; 448 int flag; 449 struct proc *p; 450 { 451 switch (cmd) { 452 case WSKBDIO_GTYPE: 453 *(int *)data = WSKBD_TYPE_HPC_KBD; 454 return 0; 455 } 456 457 return (EPASSTHROUGH); 458 } 459 460 int 461 j720kbd_intr(arg) 462 void *arg; 463 { 464 struct j720ssp_softc *sc = arg; 465 466 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1); 467 468 simple_lock(&sc->sc_ssp_status_lock); 469 sc->sc_ssp_status |= J720_SSP_STATUS_KBD; 470 simple_unlock(&sc->sc_ssp_status_lock); 471 472 wakeup(&sc->sc_ssp_kthread); 473 474 return (1); 475 } 476 477 int 478 j720tp_intr(arg) 479 void *arg; 480 { 481 struct j720ssp_softc *sc = arg; 482 483 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1 << 9); 484 485 simple_lock(&sc->sc_ssp_status_lock); 486 sc->sc_ssp_status |= J720_SSP_STATUS_TP; 487 simple_unlock(&sc->sc_ssp_status_lock); 488 489 j720tp_disable(sc); 490 wakeup(&sc->sc_ssp_kthread); 491 492 return (1); 493 } 494 495 void 496 j720kbd_poll(arg) 497 void *arg; 498 { 499 struct j720ssp_softc *sc = arg; 500 int s, type, value; 501 char buf[9], *p; 502 503 j720kbd_read(sc, buf); 504 505 for(p = buf; *p; p++) { 506 type = *p & 0x80 ? WSCONS_EVENT_KEY_UP : 507 WSCONS_EVENT_KEY_DOWN; 508 value = *p & 0x7f; 509 s = spltty(); 510 wskbd_input(sc->sc_wskbddev, type, value); 511 splx(s); 512 if (type == WSCONS_EVENT_KEY_DOWN && 513 value == 0x7f) { 514 j720ssp_powerstate = ! j720ssp_powerstate; 515 config_hook_call(CONFIG_HOOK_POWERCONTROL, 516 CONFIG_HOOK_POWERCONTROL_LCDLIGHT, 517 (void *)j720ssp_powerstate); 518 } 519 } 520 521 return; 522 } 523 524 void 525 j720kbd_read(sc, buf) 526 struct j720ssp_softc *sc; 527 char *buf; 528 { 529 int data, count; 530 #ifdef DEBUG 531 u_int32_t oscr; 532 533 oscr = gettick(); 534 #endif 535 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 536 537 /* send scan keycode command */ 538 if (j720ssp_readwrite(sc, 1, 0x900, &data, 100) < 0 || 539 data != 0x88) 540 goto out; 541 542 /* read numbers of scancode available */ 543 if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) 544 goto out; 545 BIT_INVERT(data); 546 count = data; 547 548 for(; count; count--) { 549 if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) 550 goto out; 551 BIT_INVERT(data); 552 *buf++ = data; 553 } 554 *buf = 0; 555 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 556 557 #ifdef DEBUG 558 oscr = (u_int32_t)gettick() - oscr; 559 j720sspwaitcnt++; 560 j720sspwaittime += oscr; 561 #endif 562 563 return; 564 565 out: 566 *buf = 0; 567 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 568 569 /* reset SSP */ 570 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 571 delay(100); 572 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 573 574 printf("j720kbd_read: error %x\n", data); 575 return; 576 } 577 578 int 579 j720tp_poll(arg) 580 void *arg; 581 { 582 struct j720ssp_softc *sc = arg; 583 int buf[8], data, i, x, y; 584 585 /* 586 * If touch panel is not touched anymore, 587 * stop polling and re-enable interrupt 588 */ 589 if (bus_space_read_4(sc->sc_iot, 590 sc->sc_gpioh, SAGPIO_PLR) & (1 << 9)) { 591 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0); 592 j720tp_enable(sc); 593 return 0; 594 } 595 596 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 597 598 /* send read touchpanel command */ 599 if (j720ssp_readwrite(sc, 1, 0x500, &data, 100) < 0 || 600 data != 0x88) 601 goto out; 602 603 for(i = 0; i < 8; i++) { 604 if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) 605 goto out; 606 BIT_INVERT(data); 607 buf[i] = data; 608 } 609 610 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 611 612 buf[6] <<= 8; 613 buf[7] <<= 8; 614 for(i = 0; i < 3; i++) { 615 buf[i] |= buf[6] & 0x300; 616 buf[6] >>= 2; 617 buf[i + 3] |= buf[7] & 0x300; 618 buf[7] >>= 2; 619 } 620 #if 0 621 printf("j720tp_poll: %d %d %d %d %d %d\n", buf[0], buf[1], buf[2], 622 buf[3], buf[4], buf[5]); 623 #endif 624 625 /* XXX buf[1], buf[2], ... should also be used */ 626 tpcalib_trans(&sc->sc_tpcalib, buf[1], buf[4], &x, &y); 627 wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, 628 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 629 630 return 1; 631 632 out: 633 *buf = 0; 634 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 635 636 /* reset SSP */ 637 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 638 delay(100); 639 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 640 printf("j720tp_poll: error %x\n", data); 641 642 return 0; 643 } 644 645 static int 646 j720tp_enable(arg) 647 void *arg; 648 { 649 struct j720ssp_softc *sc = arg; 650 int er, s; 651 652 s = splhigh(); 653 er = bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER); 654 er |= 1 << 9; 655 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER, er); 656 splx(s); 657 658 return (0); 659 } 660 661 static void 662 j720tp_disable(arg) 663 void *arg; 664 { 665 struct j720ssp_softc *sc = arg; 666 int er, s; 667 668 s = splhigh(); 669 er = bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER); 670 er &= ~(1 << 9); 671 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER, er); 672 splx(s); 673 } 674 675 static int 676 j720tp_ioctl(arg, cmd, data, flag, p) 677 void *arg; 678 u_long cmd; 679 caddr_t data; 680 int flag; 681 struct proc *p; 682 { 683 struct j720ssp_softc *sc = arg; 684 685 switch (cmd) { 686 case WSMOUSEIO_GTYPE: 687 *(u_int *)data = WSMOUSE_TYPE_TPANEL; 688 return (0); 689 690 case WSMOUSEIO_SCALIBCOORDS: 691 case WSMOUSEIO_GCALIBCOORDS: 692 case WSMOUSEIO_GETID: 693 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p); 694 695 default: 696 return (EPASSTHROUGH); 697 } 698 } 699 700 int 701 j720lcdparam(ctx, type, id, msg) 702 void *ctx; 703 int type; 704 long id; 705 void *msg; 706 { 707 struct j720ssp_softc *sc = ctx; 708 int i, s; 709 u_int32_t data[2], len; 710 711 switch (type) { 712 case CONFIG_HOOK_GET: 713 switch (id) { 714 case CONFIG_HOOK_BRIGHTNESS_MAX: 715 case CONFIG_HOOK_CONTRAST_MAX: 716 *(int *)msg = 255; 717 return 1; 718 case CONFIG_HOOK_BRIGHTNESS: 719 data[0] = 0x6b00; 720 data[1] = 0x8800; 721 len = 2; 722 break; 723 case CONFIG_HOOK_CONTRAST: 724 data[0] = 0x2b00; 725 data[1] = 0x8800; 726 len = 2; 727 break; 728 default: 729 return 0; 730 } 731 break; 732 733 case CONFIG_HOOK_SET: 734 switch (id) { 735 case CONFIG_HOOK_BRIGHTNESS: 736 if (*(int *)msg >= 0) { 737 data[0] = 0xcb00; 738 data[1] = *(int *)msg; 739 BIT_INVERT(data[1]); 740 data[1] <<= 8; 741 len = 2; 742 } else { 743 /* XXX hack */ 744 data[0] = 0xfb00; 745 len = 1; 746 } 747 break; 748 case CONFIG_HOOK_CONTRAST: 749 data[0] = 0x8b00; 750 data[1] = *(int *)msg; 751 BIT_INVERT(data[1]); 752 data[1] <<= 8; 753 len = 2; 754 break; 755 default: 756 return 0; 757 } 758 } 759 760 s = splbio(); 761 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 762 763 for (i = 0; i < len; i++) { 764 if (j720ssp_readwrite(sc, 1, data[i], &data[i], 500) < 0) 765 goto out; 766 } 767 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 768 splx(s); 769 770 if (type == CONFIG_HOOK_SET) 771 return 1; 772 773 BIT_INVERT(data[1]); 774 *(int *)msg = data[1]; 775 776 return 1; 777 778 out: 779 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 780 781 /* reset SSP */ 782 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 783 delay(100); 784 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 785 splx(s); 786 return 0; 787 } 788 789 static int 790 j720ssp_readwrite(sc, drainfifo, in, out, wait) 791 struct j720ssp_softc *sc; 792 int drainfifo; 793 int in; 794 int *out; 795 int wait; 796 { 797 int timo; 798 799 timo = 100000; 800 while(bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PLR) & 0x400) 801 if (--timo == 0) { 802 printf("timo0\n"); 803 return -1; 804 } 805 if (drainfifo) { 806 while(bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & 807 SR_RNE) 808 bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR); 809 #if 1 810 delay(wait); 811 #endif 812 } 813 814 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_DR, in); 815 816 delay(wait); 817 timo = 100000; 818 while(! (bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & SR_RNE)) 819 if (--timo == 0) { 820 printf("timo1\n"); 821 return -1; 822 } 823 824 *out = bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR); 825 826 return 0; 827 } 828 829 #if 0 830 int 831 j720kbd_cnattach(void) 832 { 833 /* XXX defer initialization till j720sspattach */ 834 835 return (0); 836 } 837 #endif 838 839 /* ARGSUSED */ 840 void 841 j720kbd_cngetc(v, type, data) 842 void *v; 843 u_int *type; 844 int *data; 845 { 846 char buf[9]; 847 848 if (j720kbdcons_initstate < 1) 849 return; 850 851 for (;;) { 852 j720kbd_read(&j720kbdcons_sc, buf); 853 854 if (buf[0] != 0) { 855 /* XXX we are discarding buffer contents */ 856 *type = buf[0] & 0x80 ? WSCONS_EVENT_KEY_UP : 857 WSCONS_EVENT_KEY_DOWN; 858 *data = buf[0] & 0x7f; 859 return; 860 } 861 } 862 } 863 864 void 865 j720kbd_cnpollc(v, on) 866 void *v; 867 int on; 868 { 869 #if 0 870 /* XXX */ 871 struct j720kbd_internal *t = v; 872 873 pckbc_set_poll(t->t_kbctag, t->t_kbcslot, on); 874 #endif 875 } 876 877 void 878 j720kbd_cnbell(v, pitch, period, volume) 879 void *v; 880 u_int pitch; 881 u_int period; 882 u_int volume; 883 { 884 } 885 886 int 887 j720lcdpower(ctx, type, id, msg) 888 void *ctx; 889 int type; 890 long id; 891 void *msg; 892 { 893 struct sed1356_softc *sc = ctx; 894 struct sa11x0_softc *psc = sc->sc_parent; 895 int val; 896 u_int32_t reg; 897 898 if (type != CONFIG_HOOK_POWERCONTROL || 899 id != CONFIG_HOOK_POWERCONTROL_LCDLIGHT) 900 return 0; 901 902 sed1356_init_brightness(sc, 0); 903 sed1356_init_contrast(sc, 0); 904 905 if (msg) { 906 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 0); 907 908 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 909 reg |= 0x1; 910 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 911 delay(50000); 912 913 val = sc->sc_contrast; 914 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 915 delay(100000); 916 917 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 918 reg |= 0x4; 919 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 920 921 val = sc->sc_brightness; 922 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 923 924 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 925 reg |= 0x2; 926 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 927 } else { 928 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 929 reg &= ~0x2; 930 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 931 reg &= ~0x4; 932 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 933 delay(100000); 934 935 val = -2; 936 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 937 938 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 1); 939 940 delay(100000); 941 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 942 reg &= ~0x1; 943 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 944 } 945 return 1; 946 } 947 948 int 949 hpcarm_apm_getpower(api, parent) 950 struct apm_power_info *api; 951 void *parent; 952 { 953 int data, pmdata[3], i; 954 struct j720ssp_softc *sc = (struct j720ssp_softc *)parent; 955 956 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 957 958 if (j720ssp_readwrite(sc, 1, 0x300, &data, 100) < 0 || data != 0x88) 959 goto out; 960 961 for (i = 0; i < 3; i++) { 962 if (j720ssp_readwrite(sc, 0, 0x8800, &pmdata[i], 500) < 0) 963 goto out; 964 BIT_INVERT(pmdata[i]); 965 } 966 967 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 968 969 bzero(api, sizeof(struct apm_power_info)); 970 api->ac_state = APM_AC_UNKNOWN; 971 972 /* 973 * pmdata[0] is the main battery level 974 * pmdata[1] is the backup battery level 975 * pmdata[2] tells which battery is present 976 */ 977 switch(pmdata[2]) { 978 case 14: /* backup battery present */ 979 case 2: /* backup battery absent */ 980 api->battery_state = APM_BATT_CHARGING; 981 api->minutes_left = (pmdata[0] * 840) / 170; 982 api->battery_life = (pmdata[0] * 100) / 170; 983 api->nbattery = 1; 984 break; 985 case 15: /* backup battery present */ 986 case 3: /* backup battery absent */ 987 api->battery_state = APM_BATT_ABSENT; 988 api->battery_life = 0; 989 api->nbattery = 0; 990 break; 991 default: 992 api->battery_state = APM_BATT_UNKNOWN; 993 break; 994 } 995 996 return 0; 997 998 out: 999 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 1000 1001 /* reset SSP */ 1002 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 1003 delay(100); 1004 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 1005 1006 printf("hpcarm_apm_getpower: error %x\n", data); 1007 return EIO; 1008 } 1009