1 /* $NetBSD: j720ssp.c,v 1.24 2005/06/28 18:30:00 drochner 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.24 2005/06/28 18:30:00 drochner 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_enable __P((void *, int)); 148 void j720kbd_set_leds __P((void *, int)); 149 int j720kbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 150 151 int j720lcdpower(void *, int, long, void *); 152 int hpcarm_apm_getpower __P((struct apm_power_info *, void *)); 153 154 CFATTACH_DECL(j720ssp, sizeof(struct j720ssp_softc), 155 j720sspprobe, j720sspattach, NULL, NULL); 156 157 const struct wskbd_accessops j720kbd_accessops = { 158 j720kbd_enable, 159 j720kbd_set_leds, 160 j720kbd_ioctl, 161 }; 162 163 void j720kbd_cngetc __P((void *, u_int *, int *)); 164 void j720kbd_cnpollc __P((void *, int)); 165 void j720kbd_cnbell __P((void *, u_int, u_int, u_int)); 166 167 const struct wskbd_consops j720kbd_consops = { 168 j720kbd_cngetc, 169 j720kbd_cnpollc, 170 j720kbd_cnbell, 171 }; 172 173 const struct wskbd_mapdata j720kbd_keymapdata = { 174 j720kbd_keydesctab, 175 #ifdef J720KBD_LAYOUT 176 J720KBD_LAYOUT, 177 #else 178 KB_US, 179 #endif 180 }; 181 182 static int j720tp_enable __P((void *)); 183 static int j720tp_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); 184 static void j720tp_disable __P((void *)); 185 186 const struct wsmouse_accessops j720tp_accessops = { 187 j720tp_enable, 188 j720tp_ioctl, 189 j720tp_disable, 190 }; 191 192 static int j720ssp_powerstate = 1; 193 194 static struct j720ssp_softc j720kbdcons_sc; 195 static int j720kbdcons_initstate = 0; 196 197 #define DEBUG 198 #ifdef DEBUG 199 int j720sspwaitcnt; 200 int j720sspwaittime; 201 extern int gettick(void); 202 #endif 203 204 #define BIT_INVERT(x) do { \ 205 (x) = ((((x) & 0xf0) >> 4) | (((x) & 0x0f) << 4)); \ 206 (x) = ((((x) & 0xcc) >> 2) | (((x) & 0x33) << 2)); \ 207 (x) = ((((x) & 0xaa) >> 1) | (((x) & 0x55) << 1)); \ 208 } while(0) 209 210 211 int 212 j720sspprobe(parent, cf, aux) 213 struct device *parent; 214 struct cfdata *cf; 215 void *aux; 216 { 217 return (1); 218 } 219 220 void 221 j720sspattach(parent, self, aux) 222 struct device *parent; 223 struct device *self; 224 void *aux; 225 { 226 struct j720ssp_softc *sc = (void *)self; 227 struct sa11x0_softc *psc = (void *)parent; 228 struct sa11x0_attach_args *sa = aux; 229 struct wskbddev_attach_args kbd_args; 230 struct wsmousedev_attach_args mouse_args; 231 #if NAPM > 0 232 struct apm_attach_args apm_args; 233 #endif 234 235 printf("\n"); 236 237 sc->sc_iot = psc->sc_iot; 238 sc->sc_gpioh = psc->sc_gpioh; 239 if (bus_space_map(sc->sc_iot, sa->sa_addr, sa->sa_size, 0, 240 &sc->sc_ssph)) { 241 printf("%s: unable to map SSP registers\n", 242 sc->sc_dev.dv_xname); 243 return; 244 } 245 246 sc->sc_ssp_status = J720_SSP_STATUS_NONE; 247 simple_lock_init(&sc->sc_ssp_status_lock); 248 kthread_create(j720ssp_create_kthread, sc); 249 250 sc->sc_enabled = 0; 251 252 kbd_args.console = 0; 253 254 kbd_args.keymap = &j720kbd_keymapdata; 255 256 kbd_args.accessops = &j720kbd_accessops; 257 kbd_args.accesscookie = sc; 258 259 /* Do console initialization */ 260 if (! (bootinfo->bi_cnuse & BI_CNUSE_SERIAL)) { 261 j720kbdcons_sc = *sc; 262 kbd_args.console = 1; 263 264 wskbd_cnattach(&j720kbd_consops, NULL, &j720kbd_keymapdata); 265 j720kbdcons_initstate = 1; 266 } 267 268 /* 269 * Attach the wskbd, saving a handle to it. 270 * XXX XXX XXX 271 */ 272 sc->sc_wskbddev = config_found_ia(self, "wskbddev", &kbd_args, 273 wskbddevprint); 274 275 #ifdef DEBUG 276 /* Zero the stat counters */ 277 j720sspwaitcnt = 0; 278 j720sspwaittime = 0; 279 #endif 280 281 if (j720kbdcons_initstate == 1) 282 j720kbd_enable(sc, 1); 283 284 mouse_args.accessops = &j720tp_accessops; 285 mouse_args.accesscookie = sc; 286 287 sc->sc_wsmousedev = config_found_ia(self, "wsmousedev", &mouse_args, 288 wsmousedevprint); 289 tpcalib_init(&sc->sc_tpcalib); 290 291 /* XXX fill in "default" calibrate param */ 292 { 293 static const struct wsmouse_calibcoords j720_default_calib = { 294 0, 0, 639, 239, 295 4, 296 { { 988, 80, 0, 0 }, 297 { 88, 84, 639, 0 }, 298 { 988, 927, 0, 239 }, 299 { 88, 940, 639, 239 } } }; 300 tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS, 301 __UNCONST(&j720_default_calib), 0, 0); 302 } 303 304 j720tp_disable(sc); 305 306 /* Setup touchpad interrupt */ 307 sa11x0_intr_establish(0, 9, 1, IPL_BIO, j720tp_intr, sc); 308 309 /* LCD control is on the same bus */ 310 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, 311 CONFIG_HOOK_SHARE, j720lcdparam, sc); 312 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS, 313 CONFIG_HOOK_SHARE, j720lcdparam, sc); 314 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_BRIGHTNESS_MAX, 315 CONFIG_HOOK_SHARE, j720lcdparam, sc); 316 317 config_hook(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, 318 CONFIG_HOOK_SHARE, j720lcdparam, sc); 319 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST, 320 CONFIG_HOOK_SHARE, j720lcdparam, sc); 321 config_hook(CONFIG_HOOK_GET, CONFIG_HOOK_CONTRAST_MAX, 322 CONFIG_HOOK_SHARE, j720lcdparam, sc); 323 324 #if NAPM > 0 325 /* attach APM emulation */ 326 apm_args.aaa_magic = APM_ATTACH_ARGS_MAGIC; /* magic number */ 327 (void)config_found_ia(self, "j720sspapm", &apm_args, NULL); 328 #endif 329 330 return; 331 } 332 333 void 334 j720ssp_create_kthread(arg) 335 void *arg; 336 { 337 struct j720ssp_softc *sc = arg; 338 339 if (kthread_create1(j720ssp_kthread, sc, 340 &sc->sc_ssp_kthread, "j720ssp")) 341 panic("j720ssp_create_kthread"); 342 343 return; 344 } 345 346 void 347 j720ssp_kthread(arg) 348 void *arg; 349 { 350 struct j720ssp_softc *sc = arg; 351 int ssp_status; 352 353 while (1) { 354 simple_lock(&sc->sc_ssp_status_lock); 355 ssp_status = sc->sc_ssp_status; 356 sc->sc_ssp_status &= ~J720_SSP_STATUS_KBD; 357 simple_unlock(&sc->sc_ssp_status_lock); 358 359 if (ssp_status & J720_SSP_STATUS_KBD) 360 j720kbd_poll(sc); 361 362 if (ssp_status & J720_SSP_STATUS_TP) { 363 if (j720tp_poll(sc) == 0) { 364 simple_lock(&sc->sc_ssp_status_lock); 365 sc->sc_ssp_status &= ~J720_SSP_STATUS_TP; 366 simple_unlock(&sc->sc_ssp_status_lock); 367 } 368 tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", hz / 25); 369 } else 370 tsleep(&sc->sc_ssp_kthread, PRIBIO, "j720ssp", 0); 371 } 372 373 /* NOTREACHED */ 374 } 375 376 int 377 j720kbd_enable(v, on) 378 void *v; 379 int on; 380 { 381 struct j720ssp_softc *sc = v; 382 383 if (! sc->sc_enabled) { 384 sc->sc_enabled = 1; 385 386 sa11x0_intr_establish(0, 0, 1, IPL_BIO, j720kbd_intr, sc); 387 } 388 /* XXX */ 389 return (0); 390 } 391 392 void 393 j720kbd_set_leds(v, on) 394 void *v; 395 int on; 396 { 397 /* XXX */ 398 return; 399 } 400 401 int 402 j720kbd_ioctl(v, cmd, data, flag, p) 403 void *v; 404 u_long cmd; 405 caddr_t data; 406 int flag; 407 struct proc *p; 408 { 409 switch (cmd) { 410 case WSKBDIO_GTYPE: 411 *(int *)data = WSKBD_TYPE_HPC_KBD; 412 return 0; 413 } 414 415 return (EPASSTHROUGH); 416 } 417 418 int 419 j720kbd_intr(arg) 420 void *arg; 421 { 422 struct j720ssp_softc *sc = arg; 423 424 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1); 425 426 simple_lock(&sc->sc_ssp_status_lock); 427 sc->sc_ssp_status |= J720_SSP_STATUS_KBD; 428 simple_unlock(&sc->sc_ssp_status_lock); 429 430 wakeup(&sc->sc_ssp_kthread); 431 432 return (1); 433 } 434 435 int 436 j720tp_intr(arg) 437 void *arg; 438 { 439 struct j720ssp_softc *sc = arg; 440 441 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1 << 9); 442 443 simple_lock(&sc->sc_ssp_status_lock); 444 sc->sc_ssp_status |= J720_SSP_STATUS_TP; 445 simple_unlock(&sc->sc_ssp_status_lock); 446 447 j720tp_disable(sc); 448 wakeup(&sc->sc_ssp_kthread); 449 450 return (1); 451 } 452 453 void 454 j720kbd_poll(arg) 455 void *arg; 456 { 457 struct j720ssp_softc *sc = arg; 458 int s, type, value; 459 char buf[9], *p; 460 461 j720kbd_read(sc, buf); 462 463 for(p = buf; *p; p++) { 464 type = *p & 0x80 ? WSCONS_EVENT_KEY_UP : 465 WSCONS_EVENT_KEY_DOWN; 466 value = *p & 0x7f; 467 s = spltty(); 468 wskbd_input(sc->sc_wskbddev, type, value); 469 splx(s); 470 if (type == WSCONS_EVENT_KEY_DOWN && 471 value == 0x7f) { 472 j720ssp_powerstate = ! j720ssp_powerstate; 473 config_hook_call(CONFIG_HOOK_POWERCONTROL, 474 CONFIG_HOOK_POWERCONTROL_LCDLIGHT, 475 (void *)j720ssp_powerstate); 476 } 477 } 478 479 return; 480 } 481 482 void 483 j720kbd_read(sc, buf) 484 struct j720ssp_softc *sc; 485 char *buf; 486 { 487 int data, count; 488 #ifdef DEBUG 489 u_int32_t oscr; 490 491 oscr = gettick(); 492 #endif 493 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 494 495 /* send scan keycode command */ 496 if (j720ssp_readwrite(sc, 1, 0x900, &data, 100) < 0 || 497 data != 0x88) 498 goto out; 499 500 /* read numbers of scancode available */ 501 if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) 502 goto out; 503 BIT_INVERT(data); 504 count = data; 505 506 for(; count; count--) { 507 if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) 508 goto out; 509 BIT_INVERT(data); 510 *buf++ = data; 511 } 512 *buf = 0; 513 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 514 515 #ifdef DEBUG 516 oscr = (u_int32_t)gettick() - oscr; 517 j720sspwaitcnt++; 518 j720sspwaittime += oscr; 519 #endif 520 521 return; 522 523 out: 524 *buf = 0; 525 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 526 527 /* reset SSP */ 528 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 529 delay(100); 530 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 531 532 printf("j720kbd_read: error %x\n", data); 533 return; 534 } 535 536 int 537 j720tp_poll(arg) 538 void *arg; 539 { 540 struct j720ssp_softc *sc = arg; 541 int buf[8], data, i, x, y; 542 543 /* 544 * If touch panel is not touched anymore, 545 * stop polling and re-enable interrupt 546 */ 547 if (bus_space_read_4(sc->sc_iot, 548 sc->sc_gpioh, SAGPIO_PLR) & (1 << 9)) { 549 wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0); 550 j720tp_enable(sc); 551 return 0; 552 } 553 554 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 555 556 /* send read touchpanel command */ 557 if (j720ssp_readwrite(sc, 1, 0x500, &data, 100) < 0 || 558 data != 0x88) 559 goto out; 560 561 for(i = 0; i < 8; i++) { 562 if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0) 563 goto out; 564 BIT_INVERT(data); 565 buf[i] = data; 566 } 567 568 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 569 570 buf[6] <<= 8; 571 buf[7] <<= 8; 572 for(i = 0; i < 3; i++) { 573 buf[i] |= buf[6] & 0x300; 574 buf[6] >>= 2; 575 buf[i + 3] |= buf[7] & 0x300; 576 buf[7] >>= 2; 577 } 578 #if 0 579 printf("j720tp_poll: %d %d %d %d %d %d\n", buf[0], buf[1], buf[2], 580 buf[3], buf[4], buf[5]); 581 #endif 582 583 /* XXX buf[1], buf[2], ... should also be used */ 584 tpcalib_trans(&sc->sc_tpcalib, buf[1], buf[4], &x, &y); 585 wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0, 586 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y); 587 588 return 1; 589 590 out: 591 *buf = 0; 592 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 593 594 /* reset SSP */ 595 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 596 delay(100); 597 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 598 printf("j720tp_poll: error %x\n", data); 599 600 return 0; 601 } 602 603 static int 604 j720tp_enable(arg) 605 void *arg; 606 { 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 return (0); 617 } 618 619 static void 620 j720tp_disable(arg) 621 void *arg; 622 { 623 struct j720ssp_softc *sc = arg; 624 int er, s; 625 626 s = splhigh(); 627 er = bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER); 628 er &= ~(1 << 9); 629 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER, er); 630 splx(s); 631 } 632 633 static int 634 j720tp_ioctl(arg, cmd, data, flag, p) 635 void *arg; 636 u_long cmd; 637 caddr_t data; 638 int flag; 639 struct proc *p; 640 { 641 struct j720ssp_softc *sc = arg; 642 643 return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, p); 644 } 645 646 int 647 j720lcdparam(ctx, type, id, msg) 648 void *ctx; 649 int type; 650 long id; 651 void *msg; 652 { 653 struct j720ssp_softc *sc = ctx; 654 int i, s; 655 u_int32_t data[2], len; 656 657 switch (type) { 658 case CONFIG_HOOK_GET: 659 switch (id) { 660 case CONFIG_HOOK_BRIGHTNESS_MAX: 661 case CONFIG_HOOK_CONTRAST_MAX: 662 *(int *)msg = 255; 663 return 1; 664 case CONFIG_HOOK_BRIGHTNESS: 665 data[0] = 0x6b00; 666 data[1] = 0x8800; 667 len = 2; 668 break; 669 case CONFIG_HOOK_CONTRAST: 670 data[0] = 0x2b00; 671 data[1] = 0x8800; 672 len = 2; 673 break; 674 default: 675 return 0; 676 } 677 break; 678 679 case CONFIG_HOOK_SET: 680 switch (id) { 681 case CONFIG_HOOK_BRIGHTNESS: 682 if (*(int *)msg >= 0) { 683 data[0] = 0xcb00; 684 data[1] = *(int *)msg; 685 BIT_INVERT(data[1]); 686 data[1] <<= 8; 687 len = 2; 688 } else { 689 /* XXX hack */ 690 data[0] = 0xfb00; 691 len = 1; 692 } 693 break; 694 case CONFIG_HOOK_CONTRAST: 695 data[0] = 0x8b00; 696 data[1] = *(int *)msg; 697 BIT_INVERT(data[1]); 698 data[1] <<= 8; 699 len = 2; 700 break; 701 default: 702 return 0; 703 } 704 705 default: 706 return 0; 707 } 708 709 s = splbio(); 710 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 711 712 for (i = 0; i < len; i++) { 713 if (j720ssp_readwrite(sc, 1, data[i], &data[i], 500) < 0) 714 goto out; 715 } 716 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 717 splx(s); 718 719 if (type == CONFIG_HOOK_SET) 720 return 1; 721 722 BIT_INVERT(data[1]); 723 *(int *)msg = data[1]; 724 725 return 1; 726 727 out: 728 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 729 730 /* reset SSP */ 731 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 732 delay(100); 733 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 734 splx(s); 735 return 0; 736 } 737 738 static int 739 j720ssp_readwrite(sc, drainfifo, in, out, wait) 740 struct j720ssp_softc *sc; 741 int drainfifo; 742 int in; 743 int *out; 744 int wait; 745 { 746 int timo; 747 748 timo = 100000; 749 while(bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PLR) & 0x400) 750 if (--timo == 0) { 751 printf("timo0\n"); 752 return -1; 753 } 754 if (drainfifo) { 755 while(bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & 756 SR_RNE) 757 bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR); 758 #if 1 759 delay(wait); 760 #endif 761 } 762 763 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_DR, in); 764 765 delay(wait); 766 timo = 100000; 767 while(! (bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & SR_RNE)) 768 if (--timo == 0) { 769 printf("timo1\n"); 770 return -1; 771 } 772 773 *out = bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR); 774 775 return 0; 776 } 777 778 #if 0 779 int 780 j720kbd_cnattach(void) 781 { 782 /* XXX defer initialization till j720sspattach */ 783 784 return (0); 785 } 786 #endif 787 788 /* ARGSUSED */ 789 void 790 j720kbd_cngetc(v, type, data) 791 void *v; 792 u_int *type; 793 int *data; 794 { 795 char buf[9]; 796 797 if (j720kbdcons_initstate < 1) 798 return; 799 800 for (;;) { 801 j720kbd_read(&j720kbdcons_sc, buf); 802 803 if (buf[0] != 0) { 804 /* XXX we are discarding buffer contents */ 805 *type = buf[0] & 0x80 ? WSCONS_EVENT_KEY_UP : 806 WSCONS_EVENT_KEY_DOWN; 807 *data = buf[0] & 0x7f; 808 return; 809 } 810 } 811 } 812 813 void 814 j720kbd_cnpollc(v, on) 815 void *v; 816 int on; 817 { 818 #if 0 819 /* XXX */ 820 struct j720kbd_internal *t = v; 821 822 pckbc_set_poll(t->t_kbctag, t->t_kbcslot, on); 823 #endif 824 } 825 826 void 827 j720kbd_cnbell(v, pitch, period, volume) 828 void *v; 829 u_int pitch; 830 u_int period; 831 u_int volume; 832 { 833 } 834 835 int 836 j720lcdpower(ctx, type, id, msg) 837 void *ctx; 838 int type; 839 long id; 840 void *msg; 841 { 842 struct sed1356_softc *sc = ctx; 843 struct sa11x0_softc *psc = sc->sc_parent; 844 int val; 845 u_int32_t reg; 846 847 if (type != CONFIG_HOOK_POWERCONTROL || 848 id != CONFIG_HOOK_POWERCONTROL_LCDLIGHT) 849 return 0; 850 851 sed1356_init_brightness(sc, 0); 852 sed1356_init_contrast(sc, 0); 853 854 if (msg) { 855 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 0); 856 857 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 858 reg |= 0x1; 859 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 860 delay(50000); 861 862 val = sc->sc_contrast; 863 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val); 864 delay(100000); 865 866 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 867 reg |= 0x4; 868 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 869 870 val = sc->sc_brightness; 871 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 872 873 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 874 reg |= 0x2; 875 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 876 } else { 877 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 878 reg &= ~0x2; 879 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 880 reg &= ~0x4; 881 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 882 delay(100000); 883 884 val = -2; 885 config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val); 886 887 bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 1); 888 889 delay(100000); 890 reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR); 891 reg &= ~0x1; 892 bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg); 893 } 894 return 1; 895 } 896 897 int 898 hpcarm_apm_getpower(api, parent) 899 struct apm_power_info *api; 900 void *parent; 901 { 902 int data, pmdata[3], i; 903 struct j720ssp_softc *sc = (struct j720ssp_softc *)parent; 904 905 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000); 906 907 if (j720ssp_readwrite(sc, 1, 0x300, &data, 100) < 0 || data != 0x88) 908 goto out; 909 910 for (i = 0; i < 3; i++) { 911 if (j720ssp_readwrite(sc, 0, 0x8800, &pmdata[i], 500) < 0) 912 goto out; 913 BIT_INVERT(pmdata[i]); 914 } 915 916 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 917 918 bzero(api, sizeof(struct apm_power_info)); 919 api->ac_state = APM_AC_UNKNOWN; 920 921 /* 922 * pmdata[0] is the main battery level 923 * pmdata[1] is the backup battery level 924 * pmdata[2] tells which battery is present 925 */ 926 switch(pmdata[2]) { 927 case 14: /* backup battery present */ 928 case 2: /* backup battery absent */ 929 api->battery_state = APM_BATT_CHARGING; 930 api->minutes_left = (pmdata[0] * 840) / 170; 931 api->battery_life = (pmdata[0] * 100) / 170; 932 api->nbattery = 1; 933 break; 934 case 15: /* backup battery present */ 935 case 3: /* backup battery absent */ 936 api->battery_state = APM_BATT_ABSENT; 937 api->battery_life = 0; 938 api->nbattery = 0; 939 break; 940 default: 941 api->battery_state = APM_BATT_UNKNOWN; 942 break; 943 } 944 945 return 0; 946 947 out: 948 bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000); 949 950 /* reset SSP */ 951 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307); 952 delay(100); 953 bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387); 954 955 printf("hpcarm_apm_getpower: error %x\n", data); 956 return EIO; 957 } 958