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