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