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