xref: /netbsd-src/sys/arch/zaurus/dev/zkbd.c (revision 274254cdae52594c1aa480a736aef78313d15c9c)
1 /*	$NetBSD: zkbd.c,v 1.9 2009/01/29 16:00:33 nonaka Exp $	*/
2 /* $OpenBSD: zaurus_kbd.c,v 1.28 2005/12/21 20:36:03 deraadt Exp $ */
3 
4 /*
5  * Copyright (c) 2005 Dale Rahn <drahn@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: zkbd.c,v 1.9 2009/01/29 16:00:33 nonaka Exp $");
22 
23 #include "opt_wsdisplay_compat.h"
24 #include "lcd.h"
25 #if 0	/* XXX */
26 #include "apm.h"
27 #endif
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/device.h>
32 #include <sys/malloc.h>
33 #include <sys/kernel.h>
34 #include <sys/proc.h>
35 #include <sys/signalvar.h>
36 #include <sys/callout.h>
37 
38 #include <arm/xscale/pxa2x0reg.h>
39 #include <arm/xscale/pxa2x0_gpio.h>
40 
41 #include <dev/wscons/wsconsio.h>
42 #include <dev/wscons/wskbdvar.h>
43 #include <dev/wscons/wsksymdef.h>
44 #include <dev/wscons/wsksymvar.h>
45 
46 #include <zaurus/dev/zkbdmap.h>
47 #include <zaurus/zaurus/zaurus_var.h>
48 
49 static const int gpio_sense_pins_c3000[] = {
50 	12,
51 	17,
52 	91,
53 	34,
54 	36,
55 	38,
56 	39,
57 	-1
58 };
59 
60 static const int gpio_strobe_pins_c3000[] = {
61 	88,
62 	23,
63 	24,
64 	25,
65 	26,
66 	27,
67 	52,
68 	103,
69 	107,
70 	-1,
71 	108,
72 	114
73 };
74 
75 static const int stuck_keys[] = {
76 	7,
77 	15,
78 	23,
79 	31
80 };
81 
82 #define REP_DELAY1 400
83 #define REP_DELAYN 100
84 
85 struct zkbd_softc {
86 	device_t sc_dev;
87 
88 	const int *sc_sense_array;
89 	const int *sc_strobe_array;
90 	int sc_nsense;
91 	int sc_nstrobe;
92 
93 	short sc_onkey_pin;
94 	short sc_sync_pin;
95 	short sc_swa_pin;
96 	short sc_swb_pin;
97 	char *sc_okeystate;
98 	char *sc_keystate;
99 	char sc_hinge;		/* 0=open, 1=nonsense, 2=backwards, 3=closed */
100 	char sc_maxkbdcol;
101 
102 	struct callout sc_roll_to;
103 
104 	/* console stuff */
105 	int sc_polling;
106 	int sc_pollUD;
107 	int sc_pollkey;
108 
109 	/* wskbd bits */
110 	struct device *sc_wskbddev;
111 	int sc_rawkbd;
112 #ifdef WSDISPLAY_COMPAT_RAWKBD
113 	const char *sc_xt_keymap;
114 	struct callout sc_rawrepeat_ch;
115 #define MAXKEYS 20
116 	char sc_rep[MAXKEYS];
117 	int sc_nrep;
118 #endif
119 };
120 
121 static struct zkbd_softc *zkbd_sc;
122 
123 static int	zkbd_match(device_t, cfdata_t, void *);
124 static void	zkbd_attach(device_t, device_t, void *);
125 
126 CFATTACH_DECL_NEW(zkbd, sizeof(struct zkbd_softc),
127 	zkbd_match, zkbd_attach, NULL, NULL);
128 
129 static int	zkbd_irq(void *v);
130 static void	zkbd_poll(void *v);
131 static int	zkbd_on(void *v);
132 static int	zkbd_sync(void *v);
133 static int	zkbd_hinge(void *v);
134 static bool	zkbd_resume(device_t dv PMF_FN_ARGS);
135 
136 int zkbd_modstate;
137 
138 static int	zkbd_enable(void *, int);
139 static void	zkbd_set_leds(void *, int);
140 static int	zkbd_ioctl(void *, u_long, void *, int, struct lwp *);
141 #ifdef WSDISPLAY_COMPAT_RAWKBD
142 static void	zkbd_rawrepeat(void *v);
143 #endif
144 
145 static struct wskbd_accessops zkbd_accessops = {
146 	zkbd_enable,
147 	zkbd_set_leds,
148 	zkbd_ioctl,
149 };
150 
151 static void	zkbd_cngetc(void *, u_int *, int *);
152 static void	zkbd_cnpollc(void *, int);
153 
154 static struct wskbd_consops zkbd_consops = {
155 	zkbd_cngetc,
156 	zkbd_cnpollc,
157 };
158 
159 static struct wskbd_mapdata zkbd_keymapdata = {
160 	zkbd_keydesctab,
161 	KB_US,
162 };
163 
164 static int
165 zkbd_match(device_t parent, cfdata_t cf, void *aux)
166 {
167 
168 	if (zkbd_sc)
169 		return 0;
170 
171 	return 1;
172 }
173 
174 static void
175 zkbd_attach(device_t parent, device_t self, void *aux)
176 {
177 	struct zkbd_softc *sc = device_private(self);
178 	struct wskbddev_attach_args a;
179 	int pin, i;
180 
181 	sc->sc_dev = self;
182 	zkbd_sc = sc;
183 
184 	aprint_normal("\n");
185 	aprint_naive("\n");
186 
187 	sc->sc_polling = 0;
188 #ifdef WSDISPLAY_COMPAT_RAWKBD
189 	sc->sc_rawkbd = 0;
190 #endif
191 
192 	callout_init(&sc->sc_roll_to, 0);
193 	callout_setfunc(&sc->sc_roll_to, zkbd_poll, sc);
194 #ifdef WSDISPLAY_COMPAT_RAWKBD
195 	callout_init(&sc->sc_rawrepeat_ch, 0);
196 	callout_setfunc(&sc->sc_rawrepeat_ch, zkbd_rawrepeat, sc);
197 #endif
198 
199 	if (ZAURUS_ISC3000) {
200 		sc->sc_sense_array = gpio_sense_pins_c3000;
201 		sc->sc_strobe_array = gpio_strobe_pins_c3000;
202 		sc->sc_nsense = __arraycount(gpio_sense_pins_c3000);
203 		sc->sc_nstrobe = __arraycount(gpio_strobe_pins_c3000);
204 		sc->sc_maxkbdcol = 10;
205 		sc->sc_onkey_pin = 95;
206 		sc->sc_sync_pin = 16;
207 		sc->sc_swa_pin = 97;
208 		sc->sc_swb_pin = 96;
209 #ifdef WSDISPLAY_COMPAT_RAWKBD
210 		sc->sc_xt_keymap = xt_keymap;
211 #endif
212 	} else {
213 		/* XXX */
214 		return;
215 	}
216 
217 	if (!pmf_device_register(sc->sc_dev, NULL, zkbd_resume))
218 		aprint_error_dev(sc->sc_dev,
219 		    "couldn't establish power handler\n");
220 
221 	sc->sc_okeystate = malloc(sc->sc_nsense * sc->sc_nstrobe,
222 	    M_DEVBUF, M_NOWAIT);
223 	memset(sc->sc_okeystate, 0, sc->sc_nsense * sc->sc_nstrobe);
224 
225 	sc->sc_keystate = malloc(sc->sc_nsense * sc->sc_nstrobe,
226 	    M_DEVBUF, M_NOWAIT);
227 	memset(sc->sc_keystate, 0, sc->sc_nsense * sc->sc_nstrobe);
228 
229 	/* set all the strobe bits */
230 	for (i = 0; i < sc->sc_nstrobe; i++) {
231 		pin = sc->sc_strobe_array[i];
232 		if (pin == -1)
233 			continue;
234 		pxa2x0_gpio_set_function(pin, GPIO_SET|GPIO_OUT);
235 	}
236 
237 	/* set all the sense bits */
238 	for (i = 0; i < sc->sc_nsense; i++) {
239 		pin = sc->sc_sense_array[i];
240 		if (pin == -1)
241 			continue;
242 		pxa2x0_gpio_set_function(pin, GPIO_IN);
243 		pxa2x0_gpio_intr_establish(pin, IST_EDGE_BOTH, IPL_TTY,
244 		    zkbd_irq, sc);
245 	}
246 
247 	pxa2x0_gpio_intr_establish(sc->sc_onkey_pin, IST_EDGE_BOTH, IPL_TTY,
248 	    zkbd_on, sc);
249 	pxa2x0_gpio_intr_establish(sc->sc_sync_pin, IST_EDGE_RISING, IPL_TTY,
250 	    zkbd_sync, sc);
251 	pxa2x0_gpio_intr_establish(sc->sc_swa_pin, IST_EDGE_BOTH, IPL_TTY,
252 	    zkbd_hinge, sc);
253 	pxa2x0_gpio_intr_establish(sc->sc_swb_pin, IST_EDGE_BOTH, IPL_TTY,
254 	    zkbd_hinge, sc);
255 
256 	if (glass_console) {
257 		wskbd_cnattach(&zkbd_consops, sc, &zkbd_keymapdata);
258 		a.console = 1;
259 	} else {
260 		a.console = 0;
261 	}
262 	a.keymap = &zkbd_keymapdata;
263 	a.accessops = &zkbd_accessops;
264 	a.accesscookie = sc;
265 
266 	zkbd_hinge(sc);		/* to initialize sc_hinge */
267 
268 	sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
269 }
270 
271 #ifdef WSDISPLAY_COMPAT_RAWKBD
272 static void
273 zkbd_rawrepeat(void *v)
274 {
275 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
276 	int s;
277 
278 	s = spltty();
279 	wskbd_rawinput(sc->sc_wskbddev, sc->sc_rep, sc->sc_nrep);
280 	splx(s);
281 	callout_schedule(&sc->sc_rawrepeat_ch, hz * REP_DELAYN / 1000);
282 }
283 #endif
284 
285 /* XXX only deal with keys that can be pressed when display is open? */
286 /* XXX are some not in the array? */
287 /* handle keypress interrupt */
288 static int
289 zkbd_irq(void *v)
290 {
291 
292 	zkbd_poll(v);
293 
294 	return 1;
295 }
296 
297 static void
298 zkbd_poll(void *v)
299 {
300 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
301 	int i, j, col, pin, type, keysdown = 0;
302 	int stuck;
303 	int keystate;
304 	int s;
305 #ifdef WSDISPLAY_COMPAT_RAWKBD
306 	int npress = 0, ncbuf = 0, c;
307 	char cbuf[MAXKEYS * 2];
308 #endif
309 
310 	s = spltty();
311 
312 	/* discharge all */
313 	for (i = 0; i < sc->sc_nstrobe; i++) {
314 		pin = sc->sc_strobe_array[i];
315 		if (pin == -1)
316 			continue;
317 		pxa2x0_gpio_clear_bit(pin);
318 		pxa2x0_gpio_set_dir(pin, GPIO_IN);
319 	}
320 
321 	delay(10);
322 	for (col = 0; col < sc->sc_nstrobe; col++) {
323 		pin = sc->sc_strobe_array[col];
324 		if (pin == -1)
325 			continue;
326 
327 		/* activate_col */
328 		pxa2x0_gpio_set_bit(pin);
329 		pxa2x0_gpio_set_dir(pin, GPIO_OUT);
330 
331 		/* wait activate delay */
332 		delay(10);
333 
334 		/* read row */
335 		for (i = 0; i < sc->sc_nsense; i++) {
336 			int bit;
337 
338 			if (sc->sc_sense_array[i] == -1)
339 				continue;
340 			bit = pxa2x0_gpio_get_bit(sc->sc_sense_array[i]);
341 			if (bit && sc->sc_hinge && col < sc->sc_maxkbdcol)
342 				continue;
343 			sc->sc_keystate[i + (col * sc->sc_nsense)] = bit;
344 		}
345 
346 		/* reset_col */
347 		pxa2x0_gpio_set_dir(pin, GPIO_IN);
348 
349 		/* wait discharge delay */
350 		delay(10);
351 	}
352 
353 	/* charge all */
354 	for (i = 0; i < sc->sc_nstrobe; i++) {
355 		pin = sc->sc_strobe_array[i];
356 		if (pin == -1)
357 			continue;
358 		pxa2x0_gpio_set_bit(pin);
359 		pxa2x0_gpio_set_dir(pin, GPIO_OUT);
360 	}
361 
362 	/* force the irqs to clear as we have just played with them. */
363 	for (i = 0; i < sc->sc_nsense; i++) {
364 		pin = sc->sc_sense_array[i];
365 		if (pin == -1)
366 			continue;
367 		pxa2x0_gpio_clear_intr(pin);
368 	}
369 
370 	/* process after resetting interrupt */
371 	zkbd_modstate = (
372 		(sc->sc_keystate[84] ? (1 << 0) : 0) | /* shift */
373 		(sc->sc_keystate[93] ? (1 << 1) : 0) | /* Fn */
374 		(sc->sc_keystate[14] ? (1 << 2) : 0)); /* 'alt' */
375 
376 	for (i = 0; i < sc->sc_nsense * sc->sc_nstrobe; i++) {
377 		stuck = 0;
378 		/* extend  xt_keymap to do this faster. */
379 		/* ignore 'stuck' keys' */
380 		for (j = 0; j < __arraycount(stuck_keys); j++) {
381 			if (stuck_keys[j] == i) {
382 				stuck = 1;
383 				break;
384 			}
385 		}
386 		if (stuck)
387 			continue;
388 
389 		keystate = sc->sc_keystate[i];
390 		keysdown |= keystate; /* if any keys held */
391 
392 #ifdef WSDISPLAY_COMPAT_RAWKBD
393 		if (sc->sc_polling == 0 && sc->sc_rawkbd) {
394 			if ((keystate) || (sc->sc_okeystate[i] != keystate)) {
395 				c = sc->sc_xt_keymap[i];
396 				if (c & 0x80) {
397 					cbuf[ncbuf++] = 0xe0;
398 				}
399 				cbuf[ncbuf] = c & 0x7f;
400 
401 				if (keystate) {
402 					if (c & 0x80) {
403 						sc->sc_rep[npress++] = 0xe0;
404 					}
405 					sc->sc_rep[npress++] = c & 0x7f;
406 				} else {
407 					cbuf[ncbuf] |= 0x80;
408 				}
409 				ncbuf++;
410 				sc->sc_okeystate[i] = keystate;
411 			}
412 		}
413 #endif
414 
415 		if ((!sc->sc_rawkbd) && (sc->sc_okeystate[i] != keystate)) {
416 			type = keystate ? WSCONS_EVENT_KEY_DOWN :
417 			    WSCONS_EVENT_KEY_UP;
418 
419 			if (sc->sc_polling) {
420 				sc->sc_pollkey = i;
421 				sc->sc_pollUD = type;
422 			} else {
423 				wskbd_input(sc->sc_wskbddev, type, i);
424 			}
425 
426 			sc->sc_okeystate[i] = keystate;
427 		}
428 	}
429 
430 #ifdef WSDISPLAY_COMPAT_RAWKBD
431 	if (sc->sc_polling == 0 && sc->sc_rawkbd) {
432 		wskbd_rawinput(sc->sc_wskbddev, cbuf, ncbuf);
433 		sc->sc_nrep = npress;
434 		if (npress != 0)
435 			callout_schedule(&sc->sc_rawrepeat_ch,
436 			    hz * REP_DELAY1 / 1000);
437 		else
438 			callout_stop(&sc->sc_rawrepeat_ch);
439 	}
440 #endif
441 	if (keysdown)
442 		callout_schedule(&sc->sc_roll_to, hz * REP_DELAYN / 1000 / 2);
443 	else
444 		callout_stop(&sc->sc_roll_to);	/* always cancel? */
445 
446 	splx(s);
447 }
448 
449 #if NAPM > 0
450 extern	int kbd_reset;
451 extern	int apm_suspends;
452 static	int zkbdondown;				/* on key is pressed */
453 static	struct timeval zkbdontv = { 0, 0 };	/* last on key event */
454 const	struct timeval zkbdhalttv = { 3, 0 };	/*  3s for safe shutdown */
455 const	struct timeval zkbdsleeptv = { 0, 250000 };	/* .25s for suspend */
456 extern	int lid_suspend;
457 #endif
458 
459 static int
460 zkbd_on(void *v)
461 {
462 #if NAPM > 0
463 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
464 	int down = pxa2x0_gpio_get_bit(sc->sc_onkey_pin) ? 1 : 0;
465 
466 	/*
467 	 * Change run mode depending on how long the key is held down.
468 	 * Ignore the key if it gets pressed while the lid is closed.
469 	 *
470 	 * Keys can bounce and we have to work around missed interrupts.
471 	 * Only the second edge is detected upon exit from sleep mode.
472 	 */
473 	if (down) {
474 		if (sc->sc_hinge == 3) {
475 			zkbdondown = 0;
476 		} else {
477 			microuptime(&zkbdontv);
478 			zkbdondown = 1;
479 		}
480 	} else if (zkbdondown) {
481 		if (ratecheck(&zkbdontv, &zkbdhalttv)) {
482 			if (kbd_reset == 1) {
483 				kbd_reset = 0;
484 				psignal(initproc, SIGUSR1);
485 			}
486 		} else if (ratecheck(&zkbdontv, &zkbdsleeptv)) {
487 			apm_suspends++;
488 		}
489 		zkbdondown = 0;
490 	}
491 #endif
492 	return 1;
493 }
494 
495 static int
496 zkbd_sync(void *v)
497 {
498 
499 	return 1;
500 }
501 
502 static int
503 zkbd_hinge(void *v)
504 {
505 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
506 	int a = pxa2x0_gpio_get_bit(sc->sc_swa_pin) ? 1 : 0;
507 	int b = pxa2x0_gpio_get_bit(sc->sc_swb_pin) ? 2 : 0;
508 #if NLCD > 0
509 	extern void lcd_blank(int);
510 #endif
511 
512 	sc->sc_hinge = a | b;
513 
514 	if (sc->sc_hinge == 3) {
515 #if NAPM > 0
516 		if (lid_suspend)
517 			apm_suspends++;
518 #endif
519 #if NLCD > 0
520 		lcd_blank(1);
521 #endif
522 	} else {
523 #if NLCD > 0
524 		lcd_blank(0);
525 #endif
526 	}
527 
528 	return 1;
529 }
530 
531 static int
532 zkbd_enable(void *v, int on)
533 {
534 
535 	return 0;
536 }
537 
538 void
539 zkbd_set_leds(void *v, int on)
540 {
541 }
542 
543 static int
544 zkbd_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
545 {
546 #ifdef WSDISPLAY_COMPAT_RAWKBD
547 	struct zkbd_softc *sc = (struct zkbd_softc *)v;
548 #endif
549 
550 	switch (cmd) {
551 	case WSKBDIO_GTYPE:
552 		*(int *)data = WSKBD_TYPE_ZAURUS;
553 		return 0;
554 
555 	case WSKBDIO_SETLEDS:
556 		return 0;
557 
558 	case WSKBDIO_GETLEDS:
559 		*(int *)data = 0;
560 		return 0;
561 
562 #ifdef WSDISPLAY_COMPAT_RAWKBD
563 	case WSKBDIO_SETMODE:
564 		sc->sc_rawkbd = *(int *)data == WSKBD_RAW;
565 		callout_stop(&sc->sc_rawrepeat_ch);
566 		return 0;
567 #endif
568 
569 	}
570 	return EPASSTHROUGH;
571 }
572 
573 /* implement polling for zaurus_kbd */
574 static void
575 zkbd_cngetc(void *v, u_int *type, int *data)
576 {
577 	struct zkbd_softc *sc = (struct zkbd_softc *)zkbd_sc;
578 
579 	sc->sc_pollkey = -1;
580 	sc->sc_pollUD = -1;
581 	sc->sc_polling = 1;
582 	while (sc->sc_pollkey == -1) {
583 		zkbd_poll(sc);
584 		DELAY(10000);	/* XXX */
585 	}
586 	sc->sc_polling = 0;
587 	*data = sc->sc_pollkey;
588 	*type = sc->sc_pollUD;
589 }
590 
591 static void
592 zkbd_cnpollc(void *v, int on)
593 {
594 }
595 
596 static bool
597 zkbd_resume(device_t dv PMF_FN_ARGS)
598 {
599 	struct zkbd_softc *sc = device_private(dv);
600 
601 	zkbd_hinge(sc);
602 
603 	return true;
604 }
605