Home | History | Annotate | Line # | Download | only in dev
j720ssp.c revision 1.25
      1 /* $NetBSD: j720ssp.c,v 1.25 2005/10/23 15:21:08 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.25 2005/10/23 15:21:08 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 	}
    413 
    414 	return (EPASSTHROUGH);
    415 }
    416 
    417 int
    418 j720kbd_intr(arg)
    419 	void *arg;
    420 {
    421 	struct j720ssp_softc *sc = arg;
    422 
    423 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1);
    424 
    425 	simple_lock(&sc->sc_ssp_status_lock);
    426 	sc->sc_ssp_status |= J720_SSP_STATUS_KBD;
    427 	simple_unlock(&sc->sc_ssp_status_lock);
    428 
    429 	wakeup(&sc->sc_ssp_kthread);
    430 
    431 	return (1);
    432 }
    433 
    434 int
    435 j720tp_intr(arg)
    436 	void *arg;
    437 {
    438 	struct j720ssp_softc *sc = arg;
    439 
    440 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_EDR, 1 << 9);
    441 
    442 	simple_lock(&sc->sc_ssp_status_lock);
    443 	sc->sc_ssp_status |= J720_SSP_STATUS_TP;
    444 	simple_unlock(&sc->sc_ssp_status_lock);
    445 
    446 	j720tp_disable(sc);
    447 	wakeup(&sc->sc_ssp_kthread);
    448 
    449 	return (1);
    450 }
    451 
    452 void
    453 j720kbd_poll(arg)
    454 	void *arg;
    455 {
    456 	struct j720ssp_softc *sc = arg;
    457 	int s, type, value;
    458 	char buf[9], *p;
    459 
    460 	j720kbd_read(sc, buf);
    461 
    462 	for(p = buf; *p; p++) {
    463 		type = *p & 0x80 ? WSCONS_EVENT_KEY_UP :
    464 		    WSCONS_EVENT_KEY_DOWN;
    465 		value = *p & 0x7f;
    466 		s = spltty();
    467 		wskbd_input(sc->sc_wskbddev, type, value);
    468 		splx(s);
    469 		if (type == WSCONS_EVENT_KEY_DOWN &&
    470 		    value == 0x7f) {
    471 			j720ssp_powerstate = ! j720ssp_powerstate;
    472 			config_hook_call(CONFIG_HOOK_POWERCONTROL,
    473 					 CONFIG_HOOK_POWERCONTROL_LCDLIGHT,
    474 					 (void *)j720ssp_powerstate);
    475 		}
    476 	}
    477 
    478 	return;
    479 }
    480 
    481 void
    482 j720kbd_read(sc, buf)
    483 	struct j720ssp_softc *sc;
    484 	char *buf;
    485 {
    486 	int data, count;
    487 #ifdef DEBUG
    488 	u_int32_t oscr;
    489 
    490 	oscr = gettick();
    491 #endif
    492 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000);
    493 
    494 	/* send scan keycode command */
    495 	if (j720ssp_readwrite(sc, 1, 0x900, &data, 100) < 0 ||
    496 	    data != 0x88)
    497 		goto out;
    498 
    499 	/* read numbers of scancode available */
    500 	if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0)
    501 		goto out;
    502 	BIT_INVERT(data);
    503 	count = data;
    504 
    505 	for(; count; count--) {
    506 		if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0)
    507 			goto out;
    508 		BIT_INVERT(data);
    509 		*buf++ = data;
    510 	}
    511 	*buf = 0;
    512 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
    513 
    514 #ifdef DEBUG
    515 	oscr = (u_int32_t)gettick() - oscr;
    516 	j720sspwaitcnt++;
    517 	j720sspwaittime += oscr;
    518 #endif
    519 
    520 	return;
    521 
    522 out:
    523 	*buf = 0;
    524 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
    525 
    526 	/* reset SSP */
    527 	bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307);
    528 	delay(100);
    529 	bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387);
    530 
    531 	printf("j720kbd_read: error %x\n", data);
    532 	return;
    533 }
    534 
    535 int
    536 j720tp_poll(arg)
    537 	void *arg;
    538 {
    539 	struct j720ssp_softc *sc = arg;
    540 	int buf[8], data, i, x, y;
    541 
    542 	/*
    543 	 * If touch panel is not touched anymore,
    544 	 * stop polling and re-enable interrupt
    545 	 */
    546 	if (bus_space_read_4(sc->sc_iot,
    547 	    sc->sc_gpioh, SAGPIO_PLR) & (1 << 9)) {
    548 		wsmouse_input(sc->sc_wsmousedev, 0, 0, 0, 0, 0);
    549 		j720tp_enable(sc);
    550 		return 0;
    551 	}
    552 
    553 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000);
    554 
    555 	/* send read touchpanel command */
    556 	if (j720ssp_readwrite(sc, 1, 0x500, &data, 100) < 0 ||
    557 	    data != 0x88)
    558 		goto out;
    559 
    560 	for(i = 0; i < 8; i++) {
    561 		if (j720ssp_readwrite(sc, 0, 0x8800, &data, 100) < 0)
    562 			goto out;
    563 		BIT_INVERT(data);
    564 		buf[i] = data;
    565 	}
    566 
    567 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
    568 
    569 	buf[6] <<= 8;
    570 	buf[7] <<= 8;
    571 	for(i = 0; i < 3; i++) {
    572 		buf[i] |= buf[6] & 0x300;
    573 		buf[6] >>= 2;
    574 		buf[i + 3] |= buf[7] & 0x300;
    575 		buf[7] >>= 2;
    576 	}
    577 #if 0
    578 	printf("j720tp_poll: %d %d %d  %d %d %d\n", buf[0], buf[1], buf[2],
    579 	    buf[3], buf[4], buf[5]);
    580 #endif
    581 
    582 	/* XXX buf[1], buf[2], ... should also be used */
    583 	tpcalib_trans(&sc->sc_tpcalib, buf[1], buf[4], &x, &y);
    584 	wsmouse_input(sc->sc_wsmousedev, 1, x, y, 0,
    585 	    WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
    586 
    587 	return 1;
    588 
    589 out:
    590 	*buf = 0;
    591 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
    592 
    593 	/* reset SSP */
    594 	bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307);
    595 	delay(100);
    596 	bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387);
    597 	printf("j720tp_poll: error %x\n", data);
    598 
    599 	return 0;
    600 }
    601 
    602 static int
    603 j720tp_enable(arg)
    604 	void *arg;
    605 {
    606 	struct j720ssp_softc *sc = arg;
    607 	int er, s;
    608 
    609 	s = splhigh();
    610 	er = bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER);
    611 	er |= 1 << 9;
    612 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER, er);
    613 	splx(s);
    614 
    615 	return (0);
    616 }
    617 
    618 static void
    619 j720tp_disable(arg)
    620 	void *arg;
    621 {
    622 	struct j720ssp_softc *sc = arg;
    623 	int er, s;
    624 
    625 	s = splhigh();
    626 	er = bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER);
    627 	er &= ~(1 << 9);
    628 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_FER, er);
    629 	splx(s);
    630 }
    631 
    632 static int
    633 j720tp_ioctl(arg, cmd, data, flag, p)
    634 	void *arg;
    635 	u_long cmd;
    636 	caddr_t data;
    637 	int flag;
    638 	struct proc *p;
    639 {
    640 	struct j720ssp_softc *sc = arg;
    641 
    642 	return hpc_tpanel_ioctl(&sc->sc_tpcalib, cmd, data, flag, p);
    643 }
    644 
    645 int
    646 j720lcdparam(ctx, type, id, msg)
    647 	void *ctx;
    648 	int type;
    649 	long id;
    650 	void *msg;
    651 {
    652 	struct j720ssp_softc *sc = ctx;
    653 	int i, s;
    654 	u_int32_t data[2], len;
    655 
    656 	switch (type) {
    657 	case CONFIG_HOOK_GET:
    658 		switch (id) {
    659 		case CONFIG_HOOK_BRIGHTNESS_MAX:
    660 		case CONFIG_HOOK_CONTRAST_MAX:
    661 			*(int *)msg = 255;
    662 			return 1;
    663 		case CONFIG_HOOK_BRIGHTNESS:
    664 			data[0] = 0x6b00;
    665 			data[1] = 0x8800;
    666 			len = 2;
    667 			break;
    668 		case CONFIG_HOOK_CONTRAST:
    669 			data[0] = 0x2b00;
    670 			data[1] = 0x8800;
    671 			len = 2;
    672 			break;
    673 		default:
    674 			return 0;
    675 		}
    676 		break;
    677 
    678 	case CONFIG_HOOK_SET:
    679 		switch (id) {
    680 		case CONFIG_HOOK_BRIGHTNESS:
    681 			if (*(int *)msg >= 0) {
    682 				data[0] = 0xcb00;
    683 				data[1] = *(int *)msg;
    684 				BIT_INVERT(data[1]);
    685 				data[1] <<= 8;
    686 				len = 2;
    687 			} else {
    688 				/* XXX hack */
    689 				data[0] = 0xfb00;
    690 				len = 1;
    691 			}
    692 			break;
    693 		case CONFIG_HOOK_CONTRAST:
    694 			data[0] = 0x8b00;
    695 			data[1] = *(int *)msg;
    696 			BIT_INVERT(data[1]);
    697 			data[1] <<= 8;
    698 			len = 2;
    699 			break;
    700 		default:
    701 			return 0;
    702 		}
    703 
    704 	default:
    705 		return 0;
    706 	}
    707 
    708 	s = splbio();
    709 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000);
    710 
    711 	for (i = 0; i < len; i++) {
    712 		if (j720ssp_readwrite(sc, 1, data[i], &data[i], 500) < 0)
    713 			goto out;
    714 	}
    715 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
    716 	splx(s);
    717 
    718 	if (type == CONFIG_HOOK_SET)
    719 		return 1;
    720 
    721 	BIT_INVERT(data[1]);
    722 	*(int *)msg = data[1];
    723 
    724 	return 1;
    725 
    726 out:
    727 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
    728 
    729 	/* reset SSP */
    730 	bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307);
    731 	delay(100);
    732 	bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387);
    733 	splx(s);
    734 	return 0;
    735 }
    736 
    737 static int
    738 j720ssp_readwrite(sc, drainfifo, in, out, wait)
    739 	struct j720ssp_softc *sc;
    740 	int drainfifo;
    741 	int in;
    742 	int *out;
    743 	int wait;
    744 {
    745 	int timo;
    746 
    747 	timo = 100000;
    748 	while(bus_space_read_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PLR) & 0x400)
    749 		if (--timo == 0) {
    750 			printf("timo0\n");
    751 			return -1;
    752 		}
    753 	if (drainfifo) {
    754 		while(bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) &
    755 		      SR_RNE)
    756 			bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR);
    757 #if 1
    758 		delay(wait);
    759 #endif
    760 	}
    761 
    762 	bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_DR, in);
    763 
    764 	delay(wait);
    765 	timo = 100000;
    766 	while(! (bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_SR) & SR_RNE))
    767 		if (--timo == 0) {
    768 			printf("timo1\n");
    769 			return -1;
    770 		}
    771 
    772 	*out = bus_space_read_4(sc->sc_iot, sc->sc_ssph, SASSP_DR);
    773 
    774 	return 0;
    775 }
    776 
    777 #if 0
    778 int
    779 j720kbd_cnattach(void)
    780 {
    781 	/* XXX defer initialization till j720sspattach */
    782 
    783 	return (0);
    784 }
    785 #endif
    786 
    787 /* ARGSUSED */
    788 void
    789 j720kbd_cngetc(v, type, data)
    790 	void *v;
    791 	u_int *type;
    792 	int *data;
    793 {
    794 	char buf[9];
    795 
    796 	if (j720kbdcons_initstate < 1)
    797 		return;
    798 
    799 	for (;;) {
    800 		j720kbd_read(&j720kbdcons_sc, buf);
    801 
    802 		if (buf[0] != 0) {
    803 			/* XXX we are discarding buffer contents */
    804 			*type = buf[0] & 0x80 ? WSCONS_EVENT_KEY_UP :
    805 			    WSCONS_EVENT_KEY_DOWN;
    806 			*data = buf[0] & 0x7f;
    807 			return;
    808 		}
    809 	}
    810 }
    811 
    812 void
    813 j720kbd_cnpollc(v, on)
    814 	void *v;
    815 	int on;
    816 {
    817 #if 0
    818 	/* XXX */
    819 	struct j720kbd_internal *t = v;
    820 
    821 	pckbc_set_poll(t->t_kbctag, t->t_kbcslot, on);
    822 #endif
    823 }
    824 
    825 void
    826 j720kbd_cnbell(v, pitch, period, volume)
    827 	void *v;
    828 	u_int pitch;
    829 	u_int period;
    830 	u_int volume;
    831 {
    832 }
    833 
    834 int
    835 j720lcdpower(ctx, type, id, msg)
    836 	void *ctx;
    837 	int type;
    838 	long id;
    839 	void *msg;
    840 {
    841 	struct sed1356_softc *sc = ctx;
    842 	struct sa11x0_softc *psc = sc->sc_parent;
    843 	int val;
    844 	u_int32_t reg;
    845 
    846 	if (type != CONFIG_HOOK_POWERCONTROL ||
    847 	    id != CONFIG_HOOK_POWERCONTROL_LCDLIGHT)
    848 		return 0;
    849 
    850 	sed1356_init_brightness(sc, 0);
    851 	sed1356_init_contrast(sc, 0);
    852 
    853 	if (msg) {
    854 		bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 0);
    855 
    856 		reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
    857 		reg |= 0x1;
    858 		bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
    859 		delay(50000);
    860 
    861 		val = sc->sc_contrast;
    862 		config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_CONTRAST, &val);
    863 		delay(100000);
    864 
    865 		reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
    866 		reg |= 0x4;
    867 		bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
    868 
    869 		val = sc->sc_brightness;
    870 		config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
    871 
    872 		reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
    873 		reg |= 0x2;
    874 		bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
    875 	} else {
    876 		reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
    877 		reg &= ~0x2;
    878 		bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
    879 		reg &= ~0x4;
    880 		bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
    881 		delay(100000);
    882 
    883 		val = -2;
    884 		config_hook_call(CONFIG_HOOK_SET, CONFIG_HOOK_BRIGHTNESS, &val);
    885 
    886 		bus_space_write_1(sc->sc_iot, sc->sc_regh, 0x1f0, 1);
    887 
    888 		delay(100000);
    889 		reg = bus_space_read_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR);
    890 		reg &= ~0x1;
    891 		bus_space_write_4(psc->sc_iot, psc->sc_ppch, SAPPC_PSR, reg);
    892 	}
    893 	return 1;
    894 }
    895 
    896 int
    897 hpcarm_apm_getpower(api, parent)
    898 	struct apm_power_info *api;
    899 	void *parent;
    900 {
    901 	int data, pmdata[3], i;
    902 	struct j720ssp_softc *sc = (struct j720ssp_softc *)parent;
    903 
    904 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PCR, 0x2000000);
    905 
    906 	if (j720ssp_readwrite(sc, 1, 0x300, &data, 100) < 0 || data != 0x88)
    907 		goto out;
    908 
    909 	for (i = 0; i < 3; i++) {
    910 		if (j720ssp_readwrite(sc, 0, 0x8800, &pmdata[i], 500) < 0)
    911 			goto out;
    912 		BIT_INVERT(pmdata[i]);
    913 	}
    914 
    915 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
    916 
    917 	bzero(api, sizeof(struct apm_power_info));
    918 	api->ac_state = APM_AC_UNKNOWN;
    919 
    920 	/*
    921 	 * pmdata[0] is the main battery level
    922 	 * pmdata[1] is the backup battery level
    923 	 * pmdata[2] tells which battery is present
    924 	 */
    925 	switch(pmdata[2]) {
    926 	case 14: /* backup battery present */
    927 	case 2:  /* backup battery absent */
    928 		api->battery_state = APM_BATT_CHARGING;
    929 		api->minutes_left = (pmdata[0] * 840) / 170;
    930 		api->battery_life = (pmdata[0] * 100) / 170;
    931 		api->nbattery = 1;
    932 		break;
    933 	case 15: /* backup battery present */
    934 	case 3:  /* backup battery absent */
    935 		api->battery_state = APM_BATT_ABSENT;
    936 		api->battery_life = 0;
    937 		api->nbattery = 0;
    938 		break;
    939 	default:
    940 		api->battery_state = APM_BATT_UNKNOWN;
    941 		break;
    942 	}
    943 
    944 	return 0;
    945 
    946 out:
    947 	bus_space_write_4(sc->sc_iot, sc->sc_gpioh, SAGPIO_PSR, 0x2000000);
    948 
    949 	/* reset SSP */
    950 	bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x307);
    951 	delay(100);
    952 	bus_space_write_4(sc->sc_iot, sc->sc_ssph, SASSP_CR0, 0x387);
    953 
    954 	printf("hpcarm_apm_getpower: error %x\n", data);
    955 	return EIO;
    956 }
    957