1*c7fb772bSthorpej /* $NetBSD: wzero3_keypad.c,v 1.6 2021/08/07 16:18:53 thorpej Exp $ */
29f093235Snonaka
32388feefSnonaka /*-
42388feefSnonaka * Copyright (C) 2010 NONAKA Kimihiro <nonaka@netbsd.org>
59f093235Snonaka * All rights reserved.
69f093235Snonaka *
79f093235Snonaka * Redistribution and use in source and binary forms, with or without
89f093235Snonaka * modification, are permitted provided that the following conditions
99f093235Snonaka * are met:
109f093235Snonaka * 1. Redistributions of source code must retain the above copyright
119f093235Snonaka * notice, this list of conditions and the following disclaimer.
129f093235Snonaka * 2. Redistributions in binary form must reproduce the above copyright
139f093235Snonaka * notice, this list of conditions and the following disclaimer in the
149f093235Snonaka * documentation and/or other materials provided with the distribution.
159f093235Snonaka *
162388feefSnonaka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
172388feefSnonaka * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
182388feefSnonaka * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
192388feefSnonaka * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
202388feefSnonaka * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
212388feefSnonaka * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
222388feefSnonaka * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
232388feefSnonaka * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
242388feefSnonaka * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
252388feefSnonaka * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
269f093235Snonaka */
279f093235Snonaka
289f093235Snonaka #include <sys/cdefs.h>
29*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: wzero3_keypad.c,v 1.6 2021/08/07 16:18:53 thorpej Exp $");
309f093235Snonaka
319f093235Snonaka #include "wzero3lcd.h"
329f093235Snonaka #include "opt_wsdisplay_compat.h"
339f093235Snonaka
349f093235Snonaka #include <sys/param.h>
359f093235Snonaka #include <sys/systm.h>
369f093235Snonaka #include <sys/device.h>
379f093235Snonaka #include <sys/kernel.h>
389f093235Snonaka #include <sys/callout.h>
399edf49b0Sdyoung #include <sys/bus.h>
409f093235Snonaka
419f093235Snonaka #include <arm/xscale/pxa2x0cpu.h>
429f093235Snonaka #include <arm/xscale/pxa2x0var.h>
439f093235Snonaka #include <arm/xscale/pxa2x0_gpio.h>
449f093235Snonaka
459f093235Snonaka #include <machine/bootinfo.h>
469f093235Snonaka #include <machine/config_hook.h>
479f093235Snonaka #include <machine/platid.h>
489f093235Snonaka #include <machine/platid_mask.h>
499f093235Snonaka
509f093235Snonaka #include <dev/wscons/wsconsio.h>
519f093235Snonaka #include <dev/wscons/wskbdvar.h>
529f093235Snonaka #include <dev/wscons/wsksymvar.h>
539f093235Snonaka #include <dev/wscons/wsksymdef.h>
549f093235Snonaka
559f093235Snonaka #ifdef WSDISPLAY_COMPAT_RAWKBD
569f093235Snonaka #include <dev/hpc/pckbd_encode.h>
579f093235Snonaka #endif
589f093235Snonaka
599f093235Snonaka #include <arch/hpcarm/dev/wzero3_reg.h>
609f093235Snonaka #include <arch/hpcarm/dev/wzero3_sspvar.h>
619f093235Snonaka
629f093235Snonaka enum {
639f093235Snonaka KD_0,
649f093235Snonaka KD_1,
659f093235Snonaka KD_2,
669f093235Snonaka KD_3,
679f093235Snonaka KD_4,
689f093235Snonaka KD_5,
699f093235Snonaka KD_6,
709f093235Snonaka KD_7,
719f093235Snonaka KD_8,
729f093235Snonaka KD_9,
739f093235Snonaka KD_ASTERISK,
749f093235Snonaka KD_NUMBER,
759f093235Snonaka KD_WINDOWS,
769f093235Snonaka KD_OK,
779f093235Snonaka KD_ONHOOK,
789f093235Snonaka KD_OFFHOOK,
799f093235Snonaka KD_CLEAR,
809f093235Snonaka KD_MOJI,
819f093235Snonaka KD_UP,
829f093235Snonaka KD_DOWN,
839f093235Snonaka KD_LEFT,
849f093235Snonaka KD_RIGHT,
859f093235Snonaka KD_CENTER_BUTTON,
869f093235Snonaka KD_LSOFT,
879f093235Snonaka KD_RSOFT,
889f093235Snonaka KD_NUM,
899f093235Snonaka
909f093235Snonaka KD_INVALID = -1
919f093235Snonaka };
929f093235Snonaka
939f093235Snonaka static int ws011sh_keyscan2keydown[32] = {
949f093235Snonaka KD_INVALID,
959f093235Snonaka KD_CLEAR,
969f093235Snonaka KD_INVALID,
979f093235Snonaka KD_OK,
989f093235Snonaka KD_INVALID,
999f093235Snonaka KD_LEFT,
1009f093235Snonaka KD_INVALID,
1019f093235Snonaka KD_ONHOOK,
1029f093235Snonaka KD_INVALID,
1039f093235Snonaka KD_UP,
1049f093235Snonaka KD_DOWN,
1059f093235Snonaka KD_MOJI,
1069f093235Snonaka KD_INVALID,
1079f093235Snonaka KD_WINDOWS,
1089f093235Snonaka KD_INVALID,
1099f093235Snonaka KD_RIGHT,
1109f093235Snonaka KD_INVALID,
1119f093235Snonaka KD_1,
1129f093235Snonaka KD_4,
1139f093235Snonaka KD_7,
1149f093235Snonaka KD_ASTERISK,
1159f093235Snonaka KD_2,
1169f093235Snonaka KD_5,
1179f093235Snonaka KD_8,
1189f093235Snonaka KD_0,
1199f093235Snonaka KD_CENTER_BUTTON,
1209f093235Snonaka KD_INVALID,
1219f093235Snonaka KD_3,
1229f093235Snonaka KD_6,
1239f093235Snonaka KD_9,
1249f093235Snonaka KD_NUMBER,
1259f093235Snonaka KD_INVALID,
1269f093235Snonaka };
1279f093235Snonaka
1289f093235Snonaka struct wzero3keypad_softc {
1299f093235Snonaka device_t sc_dev;
1309f093235Snonaka
1319f093235Snonaka void *sc_ih;
1329f093235Snonaka int sc_intr_pin;
1339f093235Snonaka
1349f093235Snonaka uint32_t sc_okeystat;
1359f093235Snonaka
1369f093235Snonaka struct callout sc_poll_ch;
1379f093235Snonaka int sc_poll_interval;
1389f093235Snonaka
1399f093235Snonaka device_t sc_wskbddev;
1409f093235Snonaka
1419f093235Snonaka #ifdef WSDISPLAY_COMPAT_RAWKBD
1429f093235Snonaka int sc_rawkbd;
1439f093235Snonaka #endif
1449f093235Snonaka };
1459f093235Snonaka
1469f093235Snonaka static int wzero3keypad_match(device_t, cfdata_t, void *);
1479f093235Snonaka static void wzero3keypad_attach(device_t, device_t, void *);
1489f093235Snonaka
1499f093235Snonaka CFATTACH_DECL_NEW(wzero3keypad, sizeof(struct wzero3keypad_softc),
1509f093235Snonaka wzero3keypad_match, wzero3keypad_attach, NULL, NULL);
1519f093235Snonaka
1529f093235Snonaka static int wzero3keypad_wskbd_enable(void *, int);
1539f093235Snonaka static void wzero3keypad_wskbd_set_leds(void *, int);
1549f093235Snonaka static int wzero3keypad_wskbd_ioctl(void *, u_long, void *, int, struct lwp *);
1559f093235Snonaka
1569f093235Snonaka static const int wzero3keypad_wskbd_keys[] = {
1579f093235Snonaka 82, /* KD_0: 0 */
1589f093235Snonaka 79, /* KD_1: 1 */
1599f093235Snonaka 80, /* KD_2: 2 */
1609f093235Snonaka 81, /* KD_3: 3 */
1619f093235Snonaka 75, /* KD_4: 4 */
1629f093235Snonaka 76, /* KD_5: 5 */
1639f093235Snonaka 77, /* KD_6: 6 */
1649f093235Snonaka 71, /* KD_7: 7 */
1659f093235Snonaka 72, /* KD_8: 8 */
1669f093235Snonaka 73, /* KD_9: 9 */
1679f093235Snonaka 64, /* KD_ASTERISK: f6 */
1689f093235Snonaka 65, /* KD_NUMBER: f7 */
1699f093235Snonaka 221, /* KD_WINDOWS: Menu */
1709f093235Snonaka 61, /* KD_OK: f3 */
1719f093235Snonaka 59, /* KD_ONHOOK: f1 */
1729f093235Snonaka 60, /* KD_OFFHOOK: f2 */
1739f093235Snonaka 62, /* KD_CLEAR: f4 */
1749f093235Snonaka 63, /* KD_MOJI: f5 */
1759f093235Snonaka 200, /* KD_UP: Up */
1769f093235Snonaka 208, /* KD_DOWN: Down */
1779f093235Snonaka 203, /* KD_LEFT: Left */
1789f093235Snonaka 205, /* KD_RIGHT: Right */
1799f093235Snonaka 156, /* KD_CENTER_BUTTON: KP_Enter */
1809f093235Snonaka 87, /* KD_LSOFT: f11 */
1819f093235Snonaka 88, /* KD_RSOFT: f12 */
1829f093235Snonaka };
1839f093235Snonaka
1849f093235Snonaka static const keysym_t wzero3keypad_wskbd_keydesc[] = {
1859f093235Snonaka KS_KEYCODE(59), KS_f1,
1869f093235Snonaka KS_KEYCODE(60), KS_f2,
1879f093235Snonaka KS_KEYCODE(61), KS_f3,
1889f093235Snonaka KS_KEYCODE(62), KS_f4,
1899f093235Snonaka KS_KEYCODE(63), KS_f5,
1909f093235Snonaka KS_KEYCODE(64), KS_f6,
1919f093235Snonaka KS_KEYCODE(65), KS_f7,
1929f093235Snonaka KS_KEYCODE(71), KS_7,
1939f093235Snonaka KS_KEYCODE(72), KS_8,
1949f093235Snonaka KS_KEYCODE(73), KS_9,
1959f093235Snonaka KS_KEYCODE(75), KS_4,
1969f093235Snonaka KS_KEYCODE(76), KS_5,
1979f093235Snonaka KS_KEYCODE(77), KS_6,
1989f093235Snonaka KS_KEYCODE(79), KS_1,
1999f093235Snonaka KS_KEYCODE(80), KS_2,
2009f093235Snonaka KS_KEYCODE(81), KS_3,
2019f093235Snonaka KS_KEYCODE(82), KS_0,
2029f093235Snonaka KS_KEYCODE(87), KS_f11,
2039f093235Snonaka KS_KEYCODE(88), KS_f12,
2049f093235Snonaka KS_KEYCODE(156), KS_KP_Enter,
2059f093235Snonaka KS_KEYCODE(200), KS_Up,
2069f093235Snonaka KS_KEYCODE(203), KS_Left,
2079f093235Snonaka KS_KEYCODE(205), KS_Right,
2089f093235Snonaka KS_KEYCODE(208), KS_Down,
2099f093235Snonaka KS_KEYCODE(221), KS_Menu,
2109f093235Snonaka };
2119f093235Snonaka
2129f093235Snonaka static const struct wscons_keydesc wzero3keypad_wskbd_keydesctab[] = {
2139f093235Snonaka { KB_JP, 0,
2149f093235Snonaka sizeof(wzero3keypad_wskbd_keydesc) / sizeof(keysym_t),
2159f093235Snonaka wzero3keypad_wskbd_keydesc
2169f093235Snonaka },
2179f093235Snonaka
2189f093235Snonaka { 0, 0, 0, 0 }
2199f093235Snonaka };
2209f093235Snonaka
2219f093235Snonaka static const struct wskbd_mapdata wzero3keypad_wskbd_keymapdata = {
2229f093235Snonaka wzero3keypad_wskbd_keydesctab, KB_JP
2239f093235Snonaka };
2249f093235Snonaka
2259f093235Snonaka static const struct wskbd_accessops wzero3keypad_wskbd_accessops = {
2269f093235Snonaka wzero3keypad_wskbd_enable,
2279f093235Snonaka wzero3keypad_wskbd_set_leds,
2289f093235Snonaka wzero3keypad_wskbd_ioctl,
2299f093235Snonaka };
2309f093235Snonaka
2319f093235Snonaka static int wzero3keypad_intr(void *);
2329f093235Snonaka static void wzero3keypad_poll(void *);
2339f093235Snonaka static void wzero3keypad_poll1(struct wzero3keypad_softc *, int);
2349f093235Snonaka
2359f093235Snonaka static void wzero3keypad_init(struct wzero3keypad_softc *);
2369f093235Snonaka static uint32_t wzero3keypad_getkeydown(struct wzero3keypad_softc *, int);
2379f093235Snonaka
2389f093235Snonaka static const struct wzero3keypad_model {
2399f093235Snonaka platid_mask_t *platid;
2409f093235Snonaka int intr_pin;
2419f093235Snonaka } wzero3keypad_table[] = {
2429f093235Snonaka #if 0
2439f093235Snonaka /* WS007SH */
2449f093235Snonaka {
2459f093235Snonaka &platid_mask_MACH_SHARP_WZERO3_WS007SH,
2469f093235Snonaka -1, /* XXX */
2479f093235Snonaka },
2489f093235Snonaka #endif
2499f093235Snonaka /* WS011SH */
2509f093235Snonaka {
2519f093235Snonaka &platid_mask_MACH_SHARP_WZERO3_WS011SH,
2529f093235Snonaka GPIO_WS011SH_KEYPAD,
2539f093235Snonaka },
2549f093235Snonaka
2559f093235Snonaka { NULL, -1, }
2569f093235Snonaka };
2579f093235Snonaka
2589f093235Snonaka static const struct wzero3keypad_model *
wzero3keypad_lookup(void)2599f093235Snonaka wzero3keypad_lookup(void)
2609f093235Snonaka {
2619f093235Snonaka const struct wzero3keypad_model *model;
2629f093235Snonaka
2639f093235Snonaka for (model = wzero3keypad_table; model->platid != NULL; model++) {
2649f093235Snonaka if (platid_match(&platid, model->platid)) {
2659f093235Snonaka return model;
2669f093235Snonaka }
2679f093235Snonaka }
2689f093235Snonaka return NULL;
2699f093235Snonaka }
2709f093235Snonaka
2719f093235Snonaka static int
wzero3keypad_match(device_t parent,cfdata_t cf,void * aux)272cbab9cadSchs wzero3keypad_match(device_t parent, cfdata_t cf, void *aux)
2739f093235Snonaka {
2749f093235Snonaka
2759f093235Snonaka if (strcmp(cf->cf_name, "wzero3keypad") != 0)
2769f093235Snonaka return 0;
2779f093235Snonaka if (wzero3keypad_lookup() == NULL)
2789f093235Snonaka return 0;
2799f093235Snonaka return 1;
2809f093235Snonaka }
2819f093235Snonaka
2829f093235Snonaka static void
wzero3keypad_attach(device_t parent,device_t self,void * aux)283cbab9cadSchs wzero3keypad_attach(device_t parent, device_t self, void *aux)
2849f093235Snonaka {
2859f093235Snonaka struct wzero3keypad_softc *sc = device_private(self);
2869f093235Snonaka const struct wzero3keypad_model *model;
2879f093235Snonaka struct wskbddev_attach_args wska;
2889f093235Snonaka #if NWZERO3LCD > 0
2899f093235Snonaka extern int screen_rotate;
2909f093235Snonaka #endif
2919f093235Snonaka
2929f093235Snonaka sc->sc_dev = self;
2939f093235Snonaka sc->sc_okeystat = 0;
2949f093235Snonaka #ifdef WSDISPLAY_COMPAT_RAWKBD
2959f093235Snonaka sc->sc_rawkbd = 0;
2969f093235Snonaka #endif
2979f093235Snonaka
2989f093235Snonaka model = wzero3keypad_lookup();
2999f093235Snonaka if (model == NULL) {
3009f093235Snonaka aprint_error(": unknown model\n");
3019f093235Snonaka return;
3029f093235Snonaka }
3039f093235Snonaka
3049f093235Snonaka aprint_normal(": keypad\n");
3059f093235Snonaka aprint_naive("\n");
3069f093235Snonaka
3079f093235Snonaka sc->sc_intr_pin = model->intr_pin;
3089f093235Snonaka
3099f093235Snonaka callout_init(&sc->sc_poll_ch, 0);
3109f093235Snonaka callout_setfunc(&sc->sc_poll_ch, wzero3keypad_poll, sc);
3119f093235Snonaka sc->sc_poll_interval = hz / 32;
3129f093235Snonaka
3139f093235Snonaka #if NWZERO3LCD > 0
3149f093235Snonaka switch (screen_rotate) {
3159f093235Snonaka default:
3169f093235Snonaka case 0:
3179f093235Snonaka break;
3189f093235Snonaka
3199f093235Snonaka case 270: /* counter clock-wise */
3209f093235Snonaka ws011sh_keyscan2keydown[5] = KD_UP;
3219f093235Snonaka ws011sh_keyscan2keydown[9] = KD_RIGHT;
3229f093235Snonaka ws011sh_keyscan2keydown[10] = KD_LEFT;
3239f093235Snonaka ws011sh_keyscan2keydown[15] = KD_DOWN;
3249f093235Snonaka break;
3259f093235Snonaka }
3269f093235Snonaka #endif
3279f093235Snonaka
3289f093235Snonaka /* attach wskbd */
3299f093235Snonaka wska.console = 0;
3309f093235Snonaka wska.keymap = &wzero3keypad_wskbd_keymapdata;
3319f093235Snonaka wska.accessops = &wzero3keypad_wskbd_accessops;
3329f093235Snonaka wska.accesscookie = sc;
333*c7fb772bSthorpej sc->sc_wskbddev = config_found(self, &wska, wskbddevprint, CFARGS_NONE);
3349f093235Snonaka
3359f093235Snonaka /* setup keypad interrupt */
3369f093235Snonaka pxa2x0_gpio_set_function(sc->sc_intr_pin, GPIO_IN);
3379f093235Snonaka sc->sc_ih = pxa2x0_gpio_intr_establish(sc->sc_intr_pin,
3389f093235Snonaka IST_EDGE_RISING, IPL_TTY, wzero3keypad_intr, sc);
3399f093235Snonaka if (sc->sc_ih == NULL) {
3409f093235Snonaka aprint_error_dev(sc->sc_dev,
3419f093235Snonaka "couldn't establish keypad interrupt\n");
3429f093235Snonaka }
3439f093235Snonaka
3449f093235Snonaka /* init hardware */
3459f093235Snonaka wzero3keypad_init(sc);
3469f093235Snonaka }
3479f093235Snonaka
3489f093235Snonaka static int
wzero3keypad_wskbd_enable(void * arg,int onoff)3499f093235Snonaka wzero3keypad_wskbd_enable(void *arg, int onoff)
3509f093235Snonaka {
3519f093235Snonaka
3529f093235Snonaka return 0;
3539f093235Snonaka }
3549f093235Snonaka
3559f093235Snonaka static void
wzero3keypad_wskbd_set_leds(void * arg,int leds)3569f093235Snonaka wzero3keypad_wskbd_set_leds(void *arg, int leds)
3579f093235Snonaka {
3589f093235Snonaka
3599f093235Snonaka /* Nothing to do */
3609f093235Snonaka }
3619f093235Snonaka
3629f093235Snonaka static int
wzero3keypad_wskbd_ioctl(void * arg,u_long cmd,void * data,int flags,struct lwp * l)3639f093235Snonaka wzero3keypad_wskbd_ioctl(void *arg, u_long cmd, void *data, int flags,
3649f093235Snonaka struct lwp *l)
3659f093235Snonaka {
3669f093235Snonaka #ifdef WSDISPLAY_COMPAT_RAWKBD
3679f093235Snonaka struct wzero3keypad_softc *sc = (struct wzero3keypad_softc *)arg;
3689f093235Snonaka #endif
3699f093235Snonaka
3709f093235Snonaka switch (cmd) {
3719f093235Snonaka case WSKBDIO_GTYPE:
3729f093235Snonaka *(int *)data = WSKBD_TYPE_HPC_KBD;
3739f093235Snonaka return 0;
3749f093235Snonaka case WSKBDIO_SETLEDS:
3759f093235Snonaka return 0;
3769f093235Snonaka case WSKBDIO_GETLEDS:
3779f093235Snonaka *(int *)data = 0;
3789f093235Snonaka return 0;
3799f093235Snonaka #ifdef WSDISPLAY_COMPAT_RAWKBD
3809f093235Snonaka case WSKBDIO_SETMODE:
3819f093235Snonaka sc->sc_rawkbd = (*(int *)data == WSKBD_RAW);
3829f093235Snonaka return 0;
3839f093235Snonaka #endif
3849f093235Snonaka }
3859f093235Snonaka
3869f093235Snonaka return EPASSTHROUGH;
3879f093235Snonaka }
3889f093235Snonaka
3899f093235Snonaka static int
wzero3keypad_intr(void * arg)3909f093235Snonaka wzero3keypad_intr(void *arg)
3919f093235Snonaka {
3929f093235Snonaka struct wzero3keypad_softc *sc = (struct wzero3keypad_softc *)arg;
3939f093235Snonaka
3949f093235Snonaka pxa2x0_gpio_clear_intr(sc->sc_intr_pin);
3959f093235Snonaka
3969f093235Snonaka wzero3keypad_poll1(sc, 0);
3979f093235Snonaka
3989f093235Snonaka callout_schedule(&sc->sc_poll_ch, sc->sc_poll_interval);
3999f093235Snonaka
4009f093235Snonaka return 1;
4019f093235Snonaka }
4029f093235Snonaka
4039f093235Snonaka static void
wzero3keypad_poll(void * v)4049f093235Snonaka wzero3keypad_poll(void *v)
4059f093235Snonaka {
4069f093235Snonaka struct wzero3keypad_softc *sc = (struct wzero3keypad_softc *)v;
4079f093235Snonaka
4089f093235Snonaka wzero3keypad_poll1(sc, 1);
4099f093235Snonaka
4109f093235Snonaka callout_stop(&sc->sc_poll_ch);
4119f093235Snonaka }
4129f093235Snonaka
4139f093235Snonaka static void
wzero3keypad_poll1(struct wzero3keypad_softc * sc,int doscan)4149f093235Snonaka wzero3keypad_poll1(struct wzero3keypad_softc *sc, int doscan)
4159f093235Snonaka {
4169f093235Snonaka uint32_t keydown;
4179f093235Snonaka uint32_t diff;
4189f093235Snonaka int i;
4199f093235Snonaka int s;
4209f093235Snonaka
4219f093235Snonaka s = spltty();
4229f093235Snonaka
4239f093235Snonaka keydown = wzero3keypad_getkeydown(sc, doscan);
4249f093235Snonaka diff = keydown ^ sc->sc_okeystat;
4259f093235Snonaka if (diff == 0)
4269f093235Snonaka goto out;
4279f093235Snonaka
4289f093235Snonaka for (i = 0; i < KD_NUM; i++) {
4299f093235Snonaka if (diff & (1 << i)) {
4309f093235Snonaka int state = keydown & (1 << i);
4319f093235Snonaka int type = state ? WSCONS_EVENT_KEY_DOWN :
4329f093235Snonaka WSCONS_EVENT_KEY_UP;
4339f093235Snonaka int key = wzero3keypad_wskbd_keys[i];
4349f093235Snonaka #ifdef WSDISPLAY_COMPAT_RAWKBD
4359f093235Snonaka if (sc->sc_rawkbd) {
4369f093235Snonaka int n;
4379f093235Snonaka u_char data[16];
4389f093235Snonaka
4399f093235Snonaka n = pckbd_encode(type, key, data);
4409f093235Snonaka wskbd_rawinput(sc->sc_wskbddev, data, n);
4419f093235Snonaka } else
4429f093235Snonaka #endif
4439f093235Snonaka wskbd_input(sc->sc_wskbddev, type, key);
4449f093235Snonaka }
4459f093235Snonaka }
4469f093235Snonaka sc->sc_okeystat = keydown;
4479f093235Snonaka
4489f093235Snonaka out:
4499f093235Snonaka splx(s);
4509f093235Snonaka }
4519f093235Snonaka
4529f093235Snonaka /*----------------------------------------------------------------------------
4539f093235Snonaka * AK4184 keypad controller for WS011SH
4549f093235Snonaka */
4559f093235Snonaka /* ak4184 command register */
4569f093235Snonaka #define AKMCTRL_WR_SH 7
4579f093235Snonaka #define AKMCTRL_PAGE_SH 6
4589f093235Snonaka #define AKMCTRL_ADDR_SH 0
4599f093235Snonaka #define AKMCTRL_WRITE (0<<AKMCTRL_WR_SH)
4609f093235Snonaka #define AKMCTRL_READ (1<<AKMCTRL_WR_SH)
4619f093235Snonaka #define AKMCTRL_DATA (0<<AKMCTRL_PAGE_SH)
4629f093235Snonaka #define AKMCTRL_CTRL (1<<AKMCTRL_PAGE_SH)
4639f093235Snonaka
4649f093235Snonaka static void
wzero3keypad_init(struct wzero3keypad_softc * sc)4659f093235Snonaka wzero3keypad_init(struct wzero3keypad_softc *sc)
4669f093235Snonaka {
4679f093235Snonaka int s;
4689f093235Snonaka
4699f093235Snonaka s = spltty();
4709f093235Snonaka
4719f093235Snonaka #if 0
4729f093235Snonaka /*
4739f093235Snonaka * - key interrupt enable
4749f093235Snonaka * - key touch scan
4759f093235Snonaka * - debounce time: 1ms
4769f093235Snonaka * - wait 100us for debounce time
4779f093235Snonaka */
4789f093235Snonaka (void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
4799f093235Snonaka AKMCTRL_WRITE | AKMCTRL_CTRL | (0<<AKMCTRL_ADDR_SH), 0);
4809f093235Snonaka #endif
4819f093235Snonaka
4829f093235Snonaka /* unmask all keys & columns */
4839f093235Snonaka (void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
4849f093235Snonaka AKMCTRL_WRITE | AKMCTRL_CTRL | (1<<AKMCTRL_ADDR_SH), 0);
4859f093235Snonaka (void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
4869f093235Snonaka AKMCTRL_WRITE | AKMCTRL_CTRL | (2<<AKMCTRL_ADDR_SH), 0);
4879f093235Snonaka (void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
4889f093235Snonaka AKMCTRL_WRITE | AKMCTRL_CTRL | (3<<AKMCTRL_ADDR_SH), 0);
4899f093235Snonaka
4909f093235Snonaka /* Enable keypad interrupt (kpdata dummy read) */
4919f093235Snonaka (void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
4929f093235Snonaka AKMCTRL_READ | AKMCTRL_DATA | (1<<AKMCTRL_ADDR_SH), 0);
4939f093235Snonaka
4949f093235Snonaka splx(s);
4959f093235Snonaka }
4969f093235Snonaka
4979f093235Snonaka static uint32_t
wzero3keypad_getkeydown(struct wzero3keypad_softc * sc,int doscan)4989f093235Snonaka wzero3keypad_getkeydown(struct wzero3keypad_softc *sc, int doscan)
4999f093235Snonaka {
5009f093235Snonaka uint32_t keydown = 0;
5019f093235Snonaka uint16_t status;
5029f093235Snonaka uint16_t kpdata;
5039f093235Snonaka int timo;
5049f093235Snonaka
5059f093235Snonaka if (doscan) {
5069f093235Snonaka /* host scan */
5079f093235Snonaka (void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
5089f093235Snonaka AKMCTRL_WRITE | AKMCTRL_CTRL | (4<<AKMCTRL_ADDR_SH), 0);
5099f093235Snonaka delay(100);
5109f093235Snonaka }
5119f093235Snonaka
5129f093235Snonaka timo = 1000;
5139f093235Snonaka do {
5149f093235Snonaka status = wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
5159f093235Snonaka AKMCTRL_READ | AKMCTRL_CTRL | (0<<AKMCTRL_ADDR_SH), 0);
5169f093235Snonaka } while ((status & 0xc000) == 0 && timo-- > 0);
5179f093235Snonaka
5189f093235Snonaka kpdata = wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
5199f093235Snonaka AKMCTRL_READ | AKMCTRL_DATA | (1<<AKMCTRL_ADDR_SH), 0);
5209f093235Snonaka if ((status & 0xc000) == 0xc000) {
5219f093235Snonaka if (!(kpdata & 0x8000)) {
5229f093235Snonaka int i;
5239f093235Snonaka
5249f093235Snonaka for (i = 0; i < 3; i++) {
5259f093235Snonaka int key, bits;
5269f093235Snonaka
5279f093235Snonaka key = kpdata & 0x1f;
5289f093235Snonaka if (key == 0)
5299f093235Snonaka break;
5309f093235Snonaka bits = ws011sh_keyscan2keydown[key];
5319f093235Snonaka if (bits != KD_INVALID)
5329f093235Snonaka keydown |= 1 << bits;
5339f093235Snonaka kpdata >>= 5;
5349f093235Snonaka }
5359f093235Snonaka }
5369f093235Snonaka }
5379f093235Snonaka
5389f093235Snonaka return keydown;
5399f093235Snonaka }
540