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