1 /* $NetBSD: j720ssp.c,v 1.9 2002/09/13 22:44:58 manu 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 <sys/param.h> 78 #include <sys/systm.h> 79 #include <sys/device.h> 80 #include <sys/kernel.h> 81 #include <sys/malloc.h> 82 #include <sys/ioctl.h> 83 #include <sys/kthread.h> 84 #include <sys/lock.h> 85 86 #include <machine/bus.h> 87 #include <machine/config_hook.h> 88 #include <machine/bootinfo.h> 89 90 #include <hpcarm/dev/sed1356var.h> 91 92 #include <arm/sa11x0/sa11x0_var.h> 93 #include <arm/sa11x0/sa11x0_gpioreg.h> 94 #include <arm/sa11x0/sa11x0_ppcreg.h> 95 #include <arm/sa11x0/sa11x0_sspreg.h> 96 97 #include <dev/wscons/wsconsio.h> 98 #include <dev/wscons/wskbdvar.h> 99 #include <dev/wscons/wsksymdef.h> 100 #include <dev/wscons/wsksymvar.h> 101 #include <dev/wscons/wsmousevar.h> 102 #include <dev/hpc/tpcalibvar.h> 103 104 extern const struct wscons_keydesc j720kbd_keydesctab[]; 105 106 struct j720ssp_softc { 107 struct device sc_dev; 108 109 bus_space_tag_t sc_iot; 110 bus_space_handle_t sc_gpioh; 111 bus_space_handle_t sc_ssph; 112 113 struct device *sc_wskbddev; 114 struct device *sc_wsmousedev; 115 struct tpcalib_softc sc_tpcalib; 116 117 void *sc_kbdsi; 118 void *sc_tpsi; 119 int sc_enabled; 120 121 struct proc *sc_ssp_kthread; 122 int sc_ssp_status; 123 struct simplelock sc_ssp_status_lock; 124 }; 125 /* Values for struct softc's sc_ssp_status */ 126 #define J720_SSP_STATUS_NONE 0 127 #define J720_SSP_STATUS_TP 1 128 #define J720_SSP_STATUS_KBD 2 129 130 void j720ssp_create_kthread(void *); 131 void j720ssp_kthread(void *); 132 int j720kbd_intr(void *); 133 int j720tp_intr(void *); 134 void j720kbd_poll(void *); 135 int j720tp_poll(void *); 136 137 int j720lcdparam(void *, int, long, void *); 138 static void j720kbd_read(struct j720ssp_softc *, char *); 139 static int j720ssp_readwrite(struct j720ssp_softc *, int, int, int *, int); 140 141 int j720sspprobe(struct device *, struct cfdata *, void *); 142 void j720sspattach(struct device *, struct device *, void *); 143 144 int j720kbd_submatch(struct device *, struct cfdata *, void *); 145 int j720tp_submatch(struct device *, struct cfdata *, void *); 146 147 int j720kbd_enable(void *, int); 148 void j720kbd_set_leds(void *, int); 149 int j720kbd_ioctl(void *, u_long, caddr_t, int, struct proc *); 150 151 struct cfattach j720ssp_ca = { 152 sizeof(struct j720ssp_softc), j720sspprobe, j720sspattach, 153 }; 154 155 const struct wskbd_accessops j720kbd_accessops = { 156 j720kbd_enable, 157 j720kbd_set_leds, 158 j720kbd_ioctl, 159 }; 160 161 void j720kbd_cngetc(void *, u_int *, int *); 162 void j720kbd_cnpollc(void *, int); 163 void j720kbd_cnbell(void *, u_int, u_int, u_int); 164 165 const struct wskbd_consops j720kbd_consops = { 166 j720kbd_cngetc, 167 j720kbd_cnpollc, 168 j720kbd_cnbell, 169 }; 170 171 const struct wskbd_mapdata j720kbd_keymapdata = { 172 j720kbd_keydesctab, 173 #ifdef J720KBD_LAYOUT 174 J720KBD_LAYOUT, 175 #else 176 KB_US, 177 #endif 178 }; 179 180 static int j720tp_enable(void *); 181 static int j720tp_ioctl(void *, u_long, caddr_t, int, struct proc *); 182 static void j720tp_disable(void *); 183 184 const struct wsmouse_accessops j720tp_accessops = { 185 j720tp_enable, 186 j720tp_ioctl, 187 j720tp_disable, 188 }; 189 190 static int j720ssp_powerstate = 1; 191 192 static struct j720ssp_softc j720kbdcons_sc; 193 static int j720kbdcons_initstate = 0; 194 195 #define DEBUG 196 #ifdef DEBUG 197 int j720sspwaitcnt; 198 int j720sspwaittime; 199 extern int gettick(); 200 #endif 201 202 #define BIT_INVERT(x) do { \ 203 (x) = ((((x) & 0xf0) >> 4) | (((x) & 0x0f) << 4)); \ 204 (x) = ((((x) & 0xcc) >> 2) | (((x) & 0x33) << 2)); \ 205 (x) = ((((x) & 0xaa) >> 1) | (((x) & 0x55) << 1)); \ 206 } while(0) 207 208 int 209 j720sspprobe(struct device *parent, struct cfdata *cf, void *aux) 210 { 211 return (1); 212 } 213 214 void 215 j720sspattach(struct device *parent, struct device *self, void *aux) 216 { 217 struct j720ssp_softc *sc = (void *)self; 218 struct sa11x0_softc *psc = (void *)parent; 219 struct sa11x0_attach_args *sa = aux; 220 struct wskbddev_attach_args a; 221 struct wsmousedev_attach_args ma; 222 223 printf("\n"); 224 225 sc->sc_iot = psc->sc_iot; 226 sc->sc_gpioh = psc->sc_gpioh; 227 if (bus_space_map(sc->sc_iot, sa->sa_addr, sa->sa_size, 0, 228 &sc->sc_ssph)) { 229 printf("%s: unable to map SSP registers\n", 230 sc->sc_dev.dv_xname); 231 return; 232 } 233 234 sc->sc_ssp_status = J720_SSP_STATUS_NONE; 235 simple_lock_init(&sc->sc_ssp_status_lock); 236 kthread_create(j720ssp_create_kthread, sc); 237 238 sc->sc_enabled = 0; 239 240 a.console = 0; 241 242 a.keymap = &j720kbd_keymapdata; 243 244 a.accessops = &j720kbd_accessops; 245 a.accesscookie = sc; 246 247 /* Do console initialization */ 248 if (! (bootinfo->bi_cnuse & BI_CNUSE_SERIAL)) { 249 j720kbdcons_sc = *sc; 250 a.console = 1; 251 252 wskbd_cnattach(&j720kbd_consops, NULL, &j720kbd_keymapdata); 253 j720kbdcons_initstate = 1; 254 } 255 256 /* 257 * Attach the wskbd, saving a handle to it. 258 * XXX XXX XXX 259 */ 260 sc->sc_wskbddev = config_found_sm(self, &a, wskbddevprint, 261 j720kbd_submatch); 262 263 #ifdef DEBUG 264 /* Zero the stat counters */ 265 j720sspwaitcnt = 0; 266 j720sspwaittime = 0; 267 #endif 268 269 if (j720kbdcons_initstate == 1) 270 j720kbd_enable(sc, 1); 271 272 ma.accessops = &j720tp_accessops; 273 ma.accesscookie = sc; 274 275 sc->sc_wsmousedev = config_found_sm(self, &ma, wsmousedevprint, 276 j720tp_submatch); 277 tpcalib_init(&sc->sc_tpcalib); 278 279 /* XXX fill in "default" calibrate param */ 280 { 281 static const struct wsmouse_calibcoords j720_default_calib = { 282 0, 0, 639, 239, 283 4, 284 { { 988, 80, 0, 0 }, 285 { 88, 84, 639, 0 }, 286 { 988, 927, 0, 239 }, 287 { 88, 940, 639, 239 } } }; 288 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 289 (caddr_t)&j720_default_calib, 0, 0); 290 } 291 292 j720tp_disable(sc); 293 294 /* Setup touchpad interrupt */ 295 sa11x0_intr_establish(0, 9, 1, IPL_BIO, j720tp_intr, sc); 296 297 /* LCD control is on the same bus */ 298 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, 299 CONFIG_HOOK_SHARE, j720lcdparam, sc); 300 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS, 301 CONFIG_HOOK_SHARE, j720lcdparam, sc); 302 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS_MAX, 303 CONFIG_HOOK_SHARE, j720lcdparam, sc); 304 305 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, 306 CONFIG_HOOK_SHARE, j720lcdparam, sc); 307 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST, 308 CONFIG_HOOK_SHARE, j720lcdparam, sc); 309 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST_MAX, 310 CONFIG_HOOK_SHARE, j720lcdparam, sc); 311 } 312 313 void 314 j720ssp_create_kthread(arg) 315 void *arg; 316 { 317 struct j720ssp_softc *sc = arg; 318 319 if (kthread_create1(j720ssp_kthread, sc, 320 &sc->sc_ssp_kthread, "j720ssp")) 321 panic("j720ssp_create_kthread"); 322 323 return; 324 } 325 326 void 327 j720ssp_kthread(arg) 328 void *arg; 329 { 330 struct j720ssp_softc *sc = arg; 331 int ssp_status; 332 333 while (1) { 334 if (ssp_status & J720_SSP_STATUS_TP) 335 tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", hz / 25); 336 else 337 tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", 0); 338 339 simple_lock(&sc->sc_ssp_status_lock); 340 ssp_status = sc->sc_ssp_status; 341 sc->sc_ssp_status &= ~J720_SSP_STATUS_KBD; 342 simple_unlock(&sc->sc_ssp_status_lock); 343 344 if (ssp_status & J720_SSP_STATUS_KBD) 345 j720kbd_poll(sc); 346 347 if (ssp_status & J720_SSP_STATUS_TP) { 348 if (j720tp_poll(sc) == 0) { 349 simple_lock(&sc->sc_ssp_status_lock); 350 sc->sc_ssp_status &= ~J720_SSP_STATUS_TP; 351 simple_unlock(&sc->sc_ssp_status_lock); 352 } 353 } 354 } 355 356 /* NOTREACHED */ 357 } 358 359 360 int 361 j720kbd_submatch(struct device *parant, struct cfdata *cf, void *aux) { 362 363 if (strcmp(cf->cf_driver->cd_name, "wskbd") == 0) 364 return (1); 365 return (0); 366 } 367 368 int 369 j720tp_submatch(struct device *parant, struct cfdata *cf, void *aux) { 370 371 if (strcmp(cf->cf_driver->cd_name, "wsmouse") == 0) 372 return (1); 373 return (0); 374 } 375 376 int 377 j720kbd_enable(void *v, int on) 378 { 379 struct j720ssp_softc *sc = v; 380 381 if (! sc->sc_enabled) { 382 sc->sc_enabled = 1; 383 384 sa11x0_intr_establish(0, 0, 1, IPL_BIO, j720kbd_intr, sc); 385 } 386 /* XXX */ 387 return (0); 388 } 389 390 void 391 j720kbd_set_leds(void *v, int on) 392 { 393 /* XXX */ 394 return; 395 } 396 397 int 398 j720kbd_ioctl(v, cmd, data, flag, p) 399 void *v; 400 u_long cmd; 401 caddr_t data; 402 int flag; 403 struct proc *p; 404 { 405 switch (cmd) { 406 case WSKBDIO_GTYPE: 407 *(int *)data = WSKBD_TYPE_HPC_KBD; 408 return 0; 409 } 410 411 return (EPASSTHROUGH); 412 } 413 414 int 415 j720kbd_intr(void *arg) 416 { 417 struct j720ssp_softc *sc = arg; 418 419 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1); 420 421 simple_lock(&sc->sc_ssp_status_lock); 422 sc->sc_ssp_status |= J720_SSP_STATUS_KBD; 423 simple_unlock(&sc->sc_ssp_status_lock); 424 425 wakeup(&sc->sc_ssp_kthread); 426 427 return (1); 428 } 429 430 int 431 j720tp_intr(void *arg) 432 { 433 struct j720ssp_softc *sc = arg; 434 435 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1 << 9); 436 437 simple_lock(&sc->sc_ssp_status_lock); 438 sc->sc_ssp_status |= J720_SSP_STATUS_TP; 439 simple_unlock(&sc->sc_ssp_status_lock); 440 441 j720tp_disable(sc); 442 wakeup(&sc->sc_ssp_kthread); 443 444 return (1); 445 } 446 447 void 448 j720kbd_poll(void *arg) 449 { 450 struct j720ssp_softc *sc = arg; 451 int s, type, value; 452 char buf[9], *p; 453 454 j720kbd_read(sc, buf); 455 456 for(p = buf; *p; p++) { 457 type = *p & 0x80 ? WSCONS_EVENT_KEY_UP : 458 WSCONS_EVENT_KEY_DOWN; 459 value = *p & 0x7f; 460 s = spltty(); 461 wskbd_input(sc->sc_wskbddev, type, value); 462 splx(s); 463 if (type == WSCONS_EVENT_KEY_DOWN && 464 value == 0x7f) { 465 j720ssp_powerstate = ! j720ssp_powerstate; 466 config_hook_call(CONFIG_HOOK_POWERCONTROL, 467 CONFIG_HOOK_POWERCONTROL_LCDLIGHT, 468 (void *)j720ssp_powerstate); 469 } 470 } 471 472 return; 473 } 474 475 void 476 j720kbd_read(struct j720ssp_softc *sc, char *buf) 477 { 478 int data, count; 479 #ifdef DEBUG 480 u_int32_t oscr; 481 482 oscr = gettick(); 483 #endif 484 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 485 486 /* send scan keycode command */ 487 if (j720ssp_readwrite(sc, 1, 0x900, &data, 100) < 0 || 488 data != 0x88) 489 goto out; 490 491 /* read numbers of scancode available */ 492 if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) 493 goto out; 494 BIT_INVERT(data); 495 count = data; 496 497 for(; count; count--) { 498 if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) 499 goto out; 500 BIT_INVERT(data); 501 *buf++ = data; 502 } 503 *buf = 0; 504 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 505 506 #ifdef DEBUG 507 oscr = (u_int32_t)gettick() - oscr; 508 j720sspwaitcnt++; 509 j720sspwaittime += oscr; 510 #endif 511 512 return; 513 514 out: 515 *buf = 0; 516 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 517 518 /* reset SSP */ 519 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 520 delay(100); 521 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 522 printf("j720kbd_read: error %x\n", data); 523 } 524 525 int 526 j720tp_poll(void *arg) 527 { 528 struct j720ssp_softc *sc = arg; 529 int buf[8], data, i, x, y; 530 531 /* 532 * If touch panel is not touched anymore, 533 * stop polling and re-enable interrupt 534 */ 535 if (bus_space_read_4(sc->sc_iot, 536 sc->sc_gpioh, SAGPIO_PLR) & (1 << 9)) { 537 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0); 538 j720tp_enable(sc); 539 return 0; 540 } 541 542 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 543 544 /* send read touchpanel command */ 545 if (j720ssp_readwrite(sc, 1, 0x500, &data, 100) < 0 || 546 data != 0x88) 547 goto out; 548 549 for(i = 0; i < 8; i++) { 550 if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) 551 goto out; 552 BIT_INVERT(data); 553 buf[i] = data; 554 } 555 556 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 557 558 buf[6] <<= 8; 559 buf[7] <<= 8; 560 for(i = 0; i < 3; i++) { 561 buf[i] |= buf[6] & 0x300; 562 buf[6] >>= 2; 563 buf[i + 3] |= buf[7] & 0x300; 564 buf[7] >>= 2; 565 } 566 #if 0 567 printf("j720tp_poll: %d %d %d %d %d %d\n", buf[0], buf[1], buf[2], 568 buf[3], buf[4], buf[5]); 569 #endif 570 571 /* XXX buf[1], buf[2], ... should also be used */ 572 tpcalib_trans(&sc->sc_tpcalib, buf[1], buf[4], &x, &y); 573 wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, 574 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 575 576 return 1; 577 578 out: 579 *buf = 0; 580 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 581 582 /* reset SSP */ 583 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 584 delay(100); 585 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 586 printf("j720tp_poll: error %x\n", data); 587 588 return 0; 589 } 590 591 static int 592 j720tp_enable(void *arg) { 593 struct j720ssp_softc *sc = arg; 594 int er, s; 595 596 s = splhigh(); 597 er = bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER); 598 er |= 1 << 9; 599 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER, er); 600 splx(s); 601 602 return (0); 603 } 604 605 static void 606 j720tp_disable(void *arg) { 607 struct j720ssp_softc *sc = arg; 608 int er, s; 609 610 s = splhigh(); 611 er = bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER); 612 er &= ~(1 << 9); 613 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER, er); 614 splx(s); 615 } 616 617 static int 618 j720tp_ioctl(void *arg, u_long cmd, caddr_t data, int flag, struct proc *p) { 619 struct j720ssp_softc *sc = arg; 620 621 switch (cmd) { 622 case WSMOUSEIO_GTYPE: 623 *(u_int *)data = WSMOUSE_TYPE_TPANEL; 624 return (0); 625 626 case WSMOUSEIO_SCALIBCOORDS: 627 case WSMOUSEIO_GCALIBCOORDS: 628 return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, p); 629 630 default: 631 return (EPASSTHROUGH); 632 } 633 } 634 635 int 636 j720lcdparam(void *ctx, int type, long id, void *msg) 637 { 638 struct j720ssp_softc *sc = ctx; 639 int i, s; 640 u_int32_t data[2], len; 641 642 switch (type) { 643 case CONFIG_HOOK_GET: 644 switch (id) { 645 case CONFIG_HOOK_BRIGHTNESS_MAX: 646 case CONFIG_HOOK_CONTRAST_MAX: 647 *(int *)msg = 255; 648 return 1; 649 case CONFIG_HOOK_BRIGHTNESS: 650 data[0] = 0x6b00; 651 data[1] = 0x8800; 652 len = 2; 653 break; 654 case CONFIG_HOOK_CONTRAST: 655 data[0] = 0x2b00; 656 data[1] = 0x8800; 657 len = 2; 658 break; 659 default: 660 return 0; 661 } 662 break; 663 664 case CONFIG_HOOK_SET: 665 switch (id) { 666 case CONFIG_HOOK_BRIGHTNESS: 667 if (*(int *)msg >= 0) { 668 data[0] = 0xcb00; 669 data[1] = *(int *)msg; 670 BIT_INVERT(data[1]); 671 data[1] <<= 8; 672 len = 2; 673 } else { 674 /* XXX hack */ 675 data[0] = 0xfb00; 676 len = 1; 677 } 678 break; 679 case CONFIG_HOOK_CONTRAST: 680 data[0] = 0x8b00; 681 data[1] = *(int *)msg; 682 BIT_INVERT(data[1]); 683 data[1] <<= 8; 684 len = 2; 685 break; 686 default: 687 return 0; 688 } 689 } 690 691 s = splbio(); 692 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 693 694 for (i = 0; i < len; i++) { 695 if (j720ssp_readwrite(sc, 1, data[i], &data[i], 500) < 0) 696 goto out; 697 } 698 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 699 splx(s); 700 701 if (type == CONFIG_HOOK_SET) 702 return 1; 703 704 BIT_INVERT(data[1]); 705 *(int *)msg = data[1]; 706 707 return 1; 708 709 out: 710 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 711 712 /* reset SSP */ 713 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 714 delay(100); 715 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 716 splx(s); 717 return 0; 718 } 719 720 static int 721 j720ssp_readwrite(sc, drainfifo, in, out, wait) 722 struct j720ssp_softc *sc; 723 int drainfifo; 724 int in; 725 int *out; 726 int wait; 727 { 728 int timo; 729 730 timo = 100000; 731 while(bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PLR) & 0x400) 732 if (--timo == 0) { 733 printf("timo0\n"); 734 return -1; 735 } 736 if (drainfifo) { 737 while(bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & 738 SR_RNE) 739 bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR); 740 #if 1 741 delay(wait); 742 #endif 743 } 744 745 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_DR, in); 746 747 delay(wait); 748 timo = 100000; 749 while(! (bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & SR_RNE)) 750 if (--timo == 0) { 751 printf("timo1\n"); 752 return -1; 753 } 754 755 *out = bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR); 756 757 return 0; 758 } 759 760 #if 0 761 int 762 j720kbd_cnattach() 763 { 764 /* XXX defer initialization till j720sspattach */ 765 766 return (0); 767 } 768 #endif 769 770 /* ARGSUSED */ 771 void 772 j720kbd_cngetc(void *v, u_int *type, int *data) 773 { 774 char buf[9]; 775 776 if (j720kbdcons_initstate < 1) 777 return; 778 779 for (;;) { 780 j720kbd_read(&j720kbdcons_sc, buf); 781 782 if (buf[0] != 0) { 783 /* XXX we are discarding buffer contents */ 784 *type = buf[0] & 0x80 ? WSCONS_EVENT_KEY_UP : 785 WSCONS_EVENT_KEY_DOWN; 786 *data = buf[0] & 0x7f; 787 return; 788 } 789 } 790 } 791 792 void 793 j720kbd_cnpollc(void *v, int on) 794 { 795 #if 0 796 /* XXX */ 797 struct j720kbd_internal *t = v; 798 799 pckbc_set_poll(t->t_kbctag, t->t_kbcslot, on); 800 #endif 801 } 802 803 void 804 j720kbd_cnbell(void *v, u_int pitch, u_int period, u_int volume) 805 { 806 } 807 808 int 809 j720lcdpower(void *ctx, int type, long id, void *msg) 810 { 811 struct sed1356_softc *sc = ctx; 812 struct sa11x0_softc *psc = sc->sc_parent; 813 int val; 814 u_int32_t reg; 815 816 if (type != CONFIG_HOOK_POWERCONTROL || 817 id != CONFIG_HOOK_POWERCONTROL_LCDLIGHT) 818 return 0; 819 820 sed1356_init_brightness(sc, 0); 821 sed1356_init_contrast(sc, 0); 822 823 if (msg) { 824 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 0); 825 826 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 827 reg |= 0x1; 828 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 829 delay(50000); 830 831 val = sc->sc_contrast; 832 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 833 delay(100000); 834 835 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 836 reg |= 0x4; 837 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 838 839 val = sc->sc_brightness; 840 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 841 842 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 843 reg |= 0x2; 844 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 845 } else { 846 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 847 reg &= ~0x2; 848 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 849 reg &= ~0x4; 850 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 851 delay(100000); 852 853 val = -2; 854 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 855 856 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 1); 857 858 delay(100000); 859 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 860 reg &= ~0x1; 861 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 862 } 863 return 1; 864 } 865