Module Name:    src
Committed By:   nonaka
Date:           Sun May 30 10:00:28 UTC 2010

Modified Files:
        src/sys/arch/hpcarm/conf: WZERO3 files.pxa2x0
        src/sys/arch/hpcarm/dev: wzero3_reg.h wzero3_ssp.c wzero3_sspvar.h
            wzero3_tp.c
Added Files:
        src/sys/arch/hpcarm/dev: wzero3_keypad.c

Log Message:
Added keypad driver for WS011SH.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/hpcarm/conf/WZERO3
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/hpcarm/conf/files.pxa2x0
cvs rdiff -u -r0 -r1.1 src/sys/arch/hpcarm/dev/wzero3_keypad.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/hpcarm/dev/wzero3_reg.h
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/hpcarm/dev/wzero3_ssp.c \
    src/sys/arch/hpcarm/dev/wzero3_sspvar.h
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/hpcarm/dev/wzero3_tp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/hpcarm/conf/WZERO3
diff -u src/sys/arch/hpcarm/conf/WZERO3:1.4 src/sys/arch/hpcarm/conf/WZERO3:1.5
--- src/sys/arch/hpcarm/conf/WZERO3:1.4	Sun May  9 10:39:59 2010
+++ src/sys/arch/hpcarm/conf/WZERO3	Sun May 30 10:00:27 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: WZERO3,v 1.4 2010/05/09 10:39:59 nonaka Exp $
+#	$NetBSD: WZERO3,v 1.5 2010/05/30 10:00:27 nonaka Exp $
 #
 #	WZERO3 -- Sharp Windows Mobile 5 based PDA
 #
@@ -7,7 +7,7 @@
 
 #options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident 		"GENERIC-$Revision: 1.4 $"
+#ident 		"GENERIC-$Revision: 1.5 $"
 
 # estimated number of users
 maxusers	32
@@ -175,18 +175,22 @@
 lcd* at pxaip?
 wsdisplay* at lcd? console ?
 
-# for touchpad
+# for touchpad, keypad
 wzero3ssp0 at pxaip?
 
 # touchpad
 wzero3tp0 at pxaip?
 wsmouse* at wzero3tp? mux 0
 
-# Keyboard
+# keyboard
 wzero3kbd0 at pxaip?
 hpckbd*	at wzero3kbd?
 wskbd0 at hpckbd? mux 1
 
+# keypad
+wzero3keypad0 at pxaip?
+wskbd1 at wzero3keypad? mux 1
+
 # integrated MMC/SD contoller
 pxamci0 at pxaip? addr 0x41100000 size 0x48
 sdmmc* at pxamci?

Index: src/sys/arch/hpcarm/conf/files.pxa2x0
diff -u src/sys/arch/hpcarm/conf/files.pxa2x0:1.2 src/sys/arch/hpcarm/conf/files.pxa2x0:1.3
--- src/sys/arch/hpcarm/conf/files.pxa2x0:1.2	Sun May  9 10:39:59 2010
+++ src/sys/arch/hpcarm/conf/files.pxa2x0	Sun May 30 10:00:27 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: files.pxa2x0,v 1.2 2010/05/09 10:39:59 nonaka Exp $
+#	$NetBSD: files.pxa2x0,v 1.3 2010/05/30 10:00:27 nonaka Exp $
 #
 # PXA2x0 specific configuration info
 #
@@ -12,7 +12,7 @@
 # W-ZERO3 specific configuration info
 #
 
-# Dedicated SSP unit for touch screen
+# Dedicated SSP unit for touch screen, keypad
 device wzero3ssp
 attach wzero3ssp at pxaip
 file arch/hpcarm/dev/wzero3_ssp.c	wzero3ssp
@@ -26,6 +26,11 @@
 attach wzero3kbd at pxaip
 file arch/hpcarm/dev/wzero3_kbd.c	wzero3kbd
 
+# keypad
+device wzero3keypad: wskbddev
+attach wzero3keypad at pxaip
+file arch/hpcarm/dev/wzero3_keypad.c	wzero3keypad
+
 # touchpad
 device wzero3tp: wsmousedev, hpctpanel
 attach wzero3tp at pxaip

Index: src/sys/arch/hpcarm/dev/wzero3_reg.h
diff -u src/sys/arch/hpcarm/dev/wzero3_reg.h:1.5 src/sys/arch/hpcarm/dev/wzero3_reg.h:1.6
--- src/sys/arch/hpcarm/dev/wzero3_reg.h:1.5	Sun May 23 11:49:16 2010
+++ src/sys/arch/hpcarm/dev/wzero3_reg.h	Sun May 30 10:00:27 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: wzero3_reg.h,v 1.5 2010/05/23 11:49:16 nonaka Exp $	*/
+/*	$NetBSD: wzero3_reg.h,v 1.6 2010/05/30 10:00:27 nonaka Exp $	*/
 
 /*
  * Copyright (c) 2008, 2009, 2010 NONAKA Kimihiro <[email protected]>
@@ -93,7 +93,7 @@
  */
 #define	GPIO_WS011SH_RESET_BUTTON	1	/* In */
 #define	GPIO_WS011SH_POWER_BUTTON	9	/* In */
-#define	GPIO_WS011SH_TENKEY		14	/* In */
+#define	GPIO_WS011SH_KEYPAD		14	/* In */
 #define	GPIO_WS011SH_TOUCH_PANEL	21	/* In */
 #define	GPIO_WS011SH_AK4184_CS		33	/* Out */
 #define	GPIO_WS011SH_USB_HOST_POWER	37	/* Out */

Index: src/sys/arch/hpcarm/dev/wzero3_ssp.c
diff -u src/sys/arch/hpcarm/dev/wzero3_ssp.c:1.3 src/sys/arch/hpcarm/dev/wzero3_ssp.c:1.4
--- src/sys/arch/hpcarm/dev/wzero3_ssp.c:1.3	Sat May 22 15:37:58 2010
+++ src/sys/arch/hpcarm/dev/wzero3_ssp.c	Sun May 30 10:00:27 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: wzero3_ssp.c,v 1.3 2010/05/22 15:37:58 nonaka Exp $	*/
+/*	$NetBSD: wzero3_ssp.c,v 1.4 2010/05/30 10:00:27 nonaka Exp $	*/
 
 /*
  * Copyright (c) 2010 NONAKA Kimihiro <[email protected]>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wzero3_ssp.c,v 1.3 2010/05/22 15:37:58 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wzero3_ssp.c,v 1.4 2010/05/30 10:00:27 nonaka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -50,7 +50,7 @@
 #define WS003SH_SSCR0_MAX1233	0x0000048f	/* 16bit/SPI/div by 5 */
 #define WS007SH_SSCR0_ADS7846	0x000006ab	/* 12bit/Microwire/div by 7 */
 #define WS011SH_SSCR0_AK4184_TP 0x0010068f	/* 32bit/SPI/div by 7 */
-#define WS011SH_SSCR0_AK4184_TENKEY 0x0000068f	/* 16bit/SPI/div by 7 */
+#define WS011SH_SSCR0_AK4184_KEYPAD 0x0000068f	/* 16bit/SPI/div by 7 */
 
 struct wzero3ssp_model;
 struct wzero3ssp_softc {
@@ -72,7 +72,9 @@
 static uint32_t	wzero3ssp_read_ads7846(struct wzero3ssp_softc *, uint32_t);
 static uint32_t	wzero3ssp_read_max1233(struct wzero3ssp_softc *, uint32_t,
 		    uint32_t);
-static uint32_t	wzero3ssp_read_ak4184(struct wzero3ssp_softc *, uint32_t);
+static uint32_t	wzero3ssp_read_ak4184_tp(struct wzero3ssp_softc *, uint32_t);
+static uint16_t	wzero3ssp_read_ak4184_keypad(struct wzero3ssp_softc *, uint32_t,
+		    uint32_t);
 
 static struct wzero3ssp_softc *wzero3ssp_sc;
 
@@ -239,7 +241,8 @@
 			pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS);
 	}
 	if (platid_match(&platid, &platid_mask_MACH_SHARP_WZERO3_WS011SH)) {
-		if (ic != WZERO3_SSP_IC_AK4184)
+		if (ic != WZERO3_SSP_IC_AK4184_TP
+		 && ic != WZERO3_SSP_IC_AK4184_KEYPAD)
 			pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS);
 	}
 
@@ -255,7 +258,7 @@
 		    & SSSR_TNF) != SSSR_TNF)
 			continue;	/* poll */
 		break;
-	case WZERO3_SSP_IC_AK4184:
+	case WZERO3_SSP_IC_AK4184_TP:
 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
 		    WS011SH_SSCR0_AK4184_TP);
@@ -270,6 +273,7 @@
 			continue;	/* poll */
 		break;
 	case WZERO3_SSP_IC_MAX1233:
+	case WZERO3_SSP_IC_AK4184_KEYPAD:
 	case WZERO3_SSP_IC_NUM:
 	default:
 		break;
@@ -297,7 +301,7 @@
 		rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
 		pxa2x0_gpio_set_bit(GPIO_WS007SH_ADS7846_CS);
 		break;
-	case WZERO3_SSP_IC_AK4184:
+	case WZERO3_SSP_IC_AK4184_TP:
 		/* read result of last command */
 		while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR)
 		    & SSSR_RNE) != SSSR_RNE)
@@ -306,6 +310,7 @@
 		pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS);
 		break;
 	case WZERO3_SSP_IC_MAX1233:
+	case WZERO3_SSP_IC_AK4184_KEYPAD:
 	case WZERO3_SSP_IC_NUM:
 	default:
 		rv = 0;
@@ -337,8 +342,10 @@
 		return wzero3ssp_read_ads7846(sc, data);
 	case WZERO3_SSP_IC_MAX1233:
 		return wzero3ssp_read_max1233(sc, data, data2);
-	case WZERO3_SSP_IC_AK4184:
-		return wzero3ssp_read_ak4184(sc, data);
+	case WZERO3_SSP_IC_AK4184_TP:
+		return wzero3ssp_read_ak4184_tp(sc, data);
+	case WZERO3_SSP_IC_AK4184_KEYPAD:
+		return wzero3ssp_read_ak4184_keypad(sc, data, data2);
 	case WZERO3_SSP_IC_NUM:
 	default:
 		aprint_error("%s: invalid IC %d\n", __func__, ic);
@@ -418,7 +425,7 @@
 }
 
 static uint32_t
-wzero3ssp_read_ak4184(struct wzero3ssp_softc *sc, uint32_t cmd)
+wzero3ssp_read_ak4184_tp(struct wzero3ssp_softc *sc, uint32_t cmd)
 {
 	uint32_t rv;
 
@@ -430,6 +437,7 @@
 
 	pxa2x0_gpio_clear_bit(GPIO_WS011SH_AK4184_CS);
 
+	/* clear rx fifo */
 	(void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
 
 	/* send cmd */
@@ -449,3 +457,46 @@
 
 	return rv;
 }
+
+static uint16_t
+wzero3ssp_read_ak4184_keypad(struct wzero3ssp_softc *sc, uint32_t cmd,
+    uint32_t data)
+{
+	uint16_t rv;
+
+	mutex_enter(&sc->sc_mtx);
+
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0);
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0,
+	    WS011SH_SSCR0_AK4184_KEYPAD);
+
+	pxa2x0_gpio_clear_bit(GPIO_WS011SH_AK4184_CS);
+
+	/* clear rx fifo */
+	(void) bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
+
+	/* send cmd */
+	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
+		continue;	/* poll */
+	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SSP_SSDR, (uint16_t)cmd);
+	while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
+		continue;	/* poll */
+	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
+		continue;	/* poll */
+	(void) bus_space_read_2(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
+
+	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_TNF))
+		continue;	/* poll */
+	bus_space_write_2(sc->sc_iot, sc->sc_ioh, SSP_SSDR, (uint16_t)data);
+	while (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_BUSY)
+		continue;	/* poll */
+	while (!(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) & SSSR_RNE))
+		continue;	/* poll */
+	rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, SSP_SSDR);
+
+	pxa2x0_gpio_set_bit(GPIO_WS011SH_AK4184_CS);
+
+	mutex_exit(&sc->sc_mtx);
+
+	return rv;
+}
Index: src/sys/arch/hpcarm/dev/wzero3_sspvar.h
diff -u src/sys/arch/hpcarm/dev/wzero3_sspvar.h:1.3 src/sys/arch/hpcarm/dev/wzero3_sspvar.h:1.4
--- src/sys/arch/hpcarm/dev/wzero3_sspvar.h:1.3	Sat May 22 15:37:58 2010
+++ src/sys/arch/hpcarm/dev/wzero3_sspvar.h	Sun May 30 10:00:27 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: wzero3_sspvar.h,v 1.3 2010/05/22 15:37:58 nonaka Exp $	*/
+/*	$NetBSD: wzero3_sspvar.h,v 1.4 2010/05/30 10:00:27 nonaka Exp $	*/
 
 /*
  * Copyright (c) 2010 NONAKA Kimihiro <[email protected]>
@@ -30,9 +30,10 @@
 #define	_HPCARM_DEV_WZERO3_SSPVAR_H_
 
 enum {
-	WZERO3_SSP_IC_ADS7846,	/* touch screen controller */
-	WZERO3_SSP_IC_MAX1233,	/* touch screen controller */
-	WZERO3_SSP_IC_AK4184,	/* touch screen controller */
+	WZERO3_SSP_IC_ADS7846,
+	WZERO3_SSP_IC_MAX1233,
+	WZERO3_SSP_IC_AK4184_TP,
+	WZERO3_SSP_IC_AK4184_KEYPAD,
 	WZERO3_SSP_IC_NUM
 };
 

Index: src/sys/arch/hpcarm/dev/wzero3_tp.c
diff -u src/sys/arch/hpcarm/dev/wzero3_tp.c:1.4 src/sys/arch/hpcarm/dev/wzero3_tp.c:1.5
--- src/sys/arch/hpcarm/dev/wzero3_tp.c:1.4	Sat May 22 15:37:58 2010
+++ src/sys/arch/hpcarm/dev/wzero3_tp.c	Sun May 30 10:00:27 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: wzero3_tp.c,v 1.4 2010/05/22 15:37:58 nonaka Exp $	*/
+/*	$NetBSD: wzero3_tp.c,v 1.5 2010/05/30 10:00:27 nonaka Exp $	*/
 
 /*
  * Copyright (c) 2010 NONAKA Kimihiro <[email protected]>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wzero3_tp.c,v 1.4 2010/05/22 15:37:58 nonaka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wzero3_tp.c,v 1.5 2010/05/30 10:00:27 nonaka Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -795,7 +795,7 @@
 {
 
 	/* Enable automatic low power mode. */
-	(void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184,
+	(void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_TP,
 	    (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (0<<AKMCTRL_PD_SH), 0);
 }
 
@@ -843,7 +843,7 @@
 		pos->z = 1;
 
 	/* Enable automatic low power mode. */
-	(void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184,
+	(void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_TP,
 	    (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (0<<AKMCTRL_PD_SH), 0);
 
 	return pos->z;
@@ -861,7 +861,7 @@
 {
 
 	/* Enable automatic low power mode. */
-	(void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184,
+	(void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_TP,
 	    (1<<AKMCTRL_STS_SH) | (0<<AKMCTRL_ADR_SH) | (0<<AKMCTRL_PD_SH), 0);
 }
 
@@ -871,14 +871,14 @@
 	uint32_t rv = 0;
 
 	if (dorecv)
-		rv = wzero3ssp_ic_stop(WZERO3_SSP_IC_AK4184);
+		rv = wzero3ssp_ic_stop(WZERO3_SSP_IC_AK4184_TP);
 
 	if (dosend) {
 		/* send dummy command; discard SSDR */
-		(void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184, cmd, 0);
+		(void)wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_TP, cmd, 0);
 
 		/* send the actual command; keep AK4184 enabled */
-		wzero3ssp_ic_start(WZERO3_SSP_IC_AK4184, cmd);
+		wzero3ssp_ic_start(WZERO3_SSP_IC_AK4184_TP, cmd);
 	}
 
 	return rv;

Added files:

Index: src/sys/arch/hpcarm/dev/wzero3_keypad.c
diff -u /dev/null src/sys/arch/hpcarm/dev/wzero3_keypad.c:1.1
--- /dev/null	Sun May 30 10:00:28 2010
+++ src/sys/arch/hpcarm/dev/wzero3_keypad.c	Sun May 30 10:00:27 2010
@@ -0,0 +1,541 @@
+/*	$NetBSD: wzero3_keypad.c,v 1.1 2010/05/30 10:00:27 nonaka Exp $	*/
+
+/*
+ * Copyright (c) 2010 NONAKA Kimihiro <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: wzero3_keypad.c,v 1.1 2010/05/30 10:00:27 nonaka Exp $");
+
+#include "wzero3lcd.h"
+#include "opt_wsdisplay_compat.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/callout.h>
+
+#include <arm/xscale/pxa2x0cpu.h>
+#include <arm/xscale/pxa2x0var.h>
+#include <arm/xscale/pxa2x0_gpio.h>
+
+#include <machine/bus.h>
+#include <machine/bootinfo.h>
+#include <machine/config_hook.h>
+#include <machine/platid.h>
+#include <machine/platid_mask.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wskbdvar.h>
+#include <dev/wscons/wsksymvar.h>
+#include <dev/wscons/wsksymdef.h>
+
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+#include <dev/hpc/pckbd_encode.h>
+#endif
+
+#include <arch/hpcarm/dev/wzero3_reg.h>
+#include <arch/hpcarm/dev/wzero3_sspvar.h>
+
+enum {
+	KD_0,
+	KD_1,
+	KD_2,
+	KD_3,
+	KD_4,
+	KD_5,
+	KD_6,
+	KD_7,
+	KD_8,
+	KD_9,
+	KD_ASTERISK,
+	KD_NUMBER,
+	KD_WINDOWS,
+	KD_OK,
+	KD_ONHOOK,
+	KD_OFFHOOK,
+	KD_CLEAR,
+	KD_MOJI,
+	KD_UP,
+	KD_DOWN,
+	KD_LEFT,
+	KD_RIGHT,
+	KD_CENTER_BUTTON,
+	KD_LSOFT,
+	KD_RSOFT,
+	KD_NUM,
+
+	KD_INVALID = -1
+};
+
+static int ws011sh_keyscan2keydown[32] = {
+	KD_INVALID,
+	KD_CLEAR,
+	KD_INVALID,
+	KD_OK,
+	KD_INVALID,
+	KD_LEFT,
+	KD_INVALID,
+	KD_ONHOOK,
+	KD_INVALID,
+	KD_UP,
+	KD_DOWN,
+	KD_MOJI,
+	KD_INVALID,
+	KD_WINDOWS,
+	KD_INVALID,
+	KD_RIGHT,
+	KD_INVALID,
+	KD_1,
+	KD_4,
+	KD_7,
+	KD_ASTERISK,
+	KD_2,
+	KD_5,
+	KD_8,
+	KD_0,
+	KD_CENTER_BUTTON,
+	KD_INVALID,
+	KD_3,
+	KD_6,
+	KD_9,
+	KD_NUMBER,
+	KD_INVALID,
+};
+
+struct wzero3keypad_softc {
+	device_t sc_dev;
+
+	void *sc_ih;
+	int sc_intr_pin;
+
+	uint32_t sc_okeystat;
+
+	struct callout sc_poll_ch;
+	int sc_poll_interval;
+
+	device_t sc_wskbddev;
+
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+	int sc_rawkbd;
+#endif
+};
+
+static int wzero3keypad_match(device_t, cfdata_t, void *);
+static void wzero3keypad_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(wzero3keypad, sizeof(struct wzero3keypad_softc),
+    wzero3keypad_match, wzero3keypad_attach, NULL, NULL);
+
+static int wzero3keypad_wskbd_enable(void *, int);
+static void wzero3keypad_wskbd_set_leds(void *, int);
+static int wzero3keypad_wskbd_ioctl(void *, u_long, void *, int, struct lwp *);
+
+static const int wzero3keypad_wskbd_keys[] = {
+	82,	/* KD_0: 0 */
+	79,	/* KD_1: 1 */
+	80,	/* KD_2: 2 */
+	81,	/* KD_3: 3 */
+	75,	/* KD_4: 4 */
+	76,	/* KD_5: 5 */
+	77,	/* KD_6: 6 */
+	71,	/* KD_7: 7 */
+	72,	/* KD_8: 8 */
+	73,	/* KD_9: 9 */
+	64,	/* KD_ASTERISK: f6 */
+	65,	/* KD_NUMBER: f7 */
+	221,	/* KD_WINDOWS: Menu */
+	61,	/* KD_OK: f3 */
+	59,	/* KD_ONHOOK: f1 */
+	60,	/* KD_OFFHOOK: f2 */
+	62,	/* KD_CLEAR: f4 */
+	63,	/* KD_MOJI: f5 */
+	200,	/* KD_UP: Up */
+	208,	/* KD_DOWN: Down */
+	203,	/* KD_LEFT: Left */
+	205,	/* KD_RIGHT: Right */
+	156,	/* KD_CENTER_BUTTON: KP_Enter */
+	87,	/* KD_LSOFT: f11 */
+	88,	/* KD_RSOFT: f12 */
+};
+
+static const keysym_t wzero3keypad_wskbd_keydesc[] = {
+	KS_KEYCODE(59),		KS_f1,
+	KS_KEYCODE(60),		KS_f2,
+	KS_KEYCODE(61),		KS_f3,
+	KS_KEYCODE(62),		KS_f4,
+	KS_KEYCODE(63),		KS_f5,
+	KS_KEYCODE(64),		KS_f6,
+	KS_KEYCODE(65),		KS_f7,
+	KS_KEYCODE(71),		KS_7,
+	KS_KEYCODE(72),		KS_8,
+	KS_KEYCODE(73),		KS_9,
+	KS_KEYCODE(75),		KS_4,
+	KS_KEYCODE(76),		KS_5,
+	KS_KEYCODE(77),		KS_6,
+	KS_KEYCODE(79),		KS_1,
+	KS_KEYCODE(80),		KS_2,
+	KS_KEYCODE(81),		KS_3,
+	KS_KEYCODE(82),		KS_0,
+	KS_KEYCODE(87),		KS_f11,
+	KS_KEYCODE(88),		KS_f12,
+	KS_KEYCODE(156),	KS_KP_Enter,
+	KS_KEYCODE(200),	KS_Up,
+	KS_KEYCODE(203),	KS_Left,
+	KS_KEYCODE(205),	KS_Right,
+	KS_KEYCODE(208),	KS_Down,
+	KS_KEYCODE(221),	KS_Menu,
+};
+
+static const struct wscons_keydesc wzero3keypad_wskbd_keydesctab[] = {
+	{ KB_JP, 0,
+	  sizeof(wzero3keypad_wskbd_keydesc) / sizeof(keysym_t),
+	  wzero3keypad_wskbd_keydesc
+	},
+
+	{ 0, 0, 0, 0 }
+};
+
+static const struct wskbd_mapdata wzero3keypad_wskbd_keymapdata = {
+	wzero3keypad_wskbd_keydesctab, KB_JP
+};
+
+static const struct wskbd_accessops wzero3keypad_wskbd_accessops = {
+	wzero3keypad_wskbd_enable,
+	wzero3keypad_wskbd_set_leds,
+	wzero3keypad_wskbd_ioctl,
+};
+
+static int wzero3keypad_intr(void *);
+static void wzero3keypad_poll(void *);
+static void wzero3keypad_poll1(struct wzero3keypad_softc *, int);
+
+static void wzero3keypad_init(struct wzero3keypad_softc *);
+static uint32_t wzero3keypad_getkeydown(struct wzero3keypad_softc *, int);
+
+static const struct wzero3keypad_model {
+	platid_mask_t *platid;
+	int intr_pin;
+} wzero3keypad_table[] = {
+#if 0
+	/* WS007SH */
+	{
+		&platid_mask_MACH_SHARP_WZERO3_WS007SH,
+		-1,	/* XXX */
+	},
+#endif
+	/* WS011SH */
+	{
+		&platid_mask_MACH_SHARP_WZERO3_WS011SH,
+		GPIO_WS011SH_KEYPAD,
+	},
+
+	{ NULL, -1, }
+};
+
+static const struct wzero3keypad_model *
+wzero3keypad_lookup(void)
+{
+	const struct wzero3keypad_model *model;
+
+	for (model = wzero3keypad_table; model->platid != NULL; model++) {
+		if (platid_match(&platid, model->platid)) {
+			return model;
+		}
+	}
+	return NULL;
+}
+
+static int
+wzero3keypad_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+
+	if (strcmp(cf->cf_name, "wzero3keypad") != 0)
+		return 0;
+	if (wzero3keypad_lookup() == NULL)
+		return 0;
+	return 1;
+}
+
+static void
+wzero3keypad_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct wzero3keypad_softc *sc = device_private(self);
+	const struct wzero3keypad_model *model;
+	struct wskbddev_attach_args wska;
+#if NWZERO3LCD > 0
+	extern int screen_rotate;
+#endif
+
+	sc->sc_dev = self;
+	sc->sc_okeystat = 0;
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+	sc->sc_rawkbd = 0;
+#endif
+
+	model = wzero3keypad_lookup();
+	if (model == NULL) {
+		aprint_error(": unknown model\n");
+		return;
+	}
+
+	aprint_normal(": keypad\n");
+	aprint_naive("\n");
+
+	sc->sc_intr_pin = model->intr_pin;
+
+	callout_init(&sc->sc_poll_ch, 0);
+	callout_setfunc(&sc->sc_poll_ch, wzero3keypad_poll, sc);
+	sc->sc_poll_interval = hz / 32;
+
+#if NWZERO3LCD > 0
+	switch (screen_rotate) {
+	default:
+	case 0:
+		break;
+
+	case 270:	/* counter clock-wise */
+		ws011sh_keyscan2keydown[5] = KD_UP;
+		ws011sh_keyscan2keydown[9] = KD_RIGHT;
+		ws011sh_keyscan2keydown[10] = KD_LEFT;
+		ws011sh_keyscan2keydown[15] = KD_DOWN;
+		break;
+	}
+#endif
+
+	/* attach wskbd */
+	wska.console = 0;
+	wska.keymap = &wzero3keypad_wskbd_keymapdata;
+	wska.accessops = &wzero3keypad_wskbd_accessops;
+	wska.accesscookie = sc;
+	sc->sc_wskbddev = config_found_ia(self, "wskbddev", &wska,
+	    wskbddevprint);
+
+	/* setup keypad interrupt */
+	pxa2x0_gpio_set_function(sc->sc_intr_pin, GPIO_IN);
+	sc->sc_ih = pxa2x0_gpio_intr_establish(sc->sc_intr_pin,
+	    IST_EDGE_RISING, IPL_TTY, wzero3keypad_intr, sc);
+	if (sc->sc_ih == NULL) {
+		aprint_error_dev(sc->sc_dev,
+		    "couldn't establish keypad interrupt\n");
+	}
+
+	/* init hardware */
+	wzero3keypad_init(sc);
+}
+
+static int
+wzero3keypad_wskbd_enable(void *arg, int onoff)
+{
+
+	return 0;
+}
+
+static void
+wzero3keypad_wskbd_set_leds(void *arg, int leds)
+{
+
+	/* Nothing to do */
+}
+
+static int
+wzero3keypad_wskbd_ioctl(void *arg, u_long cmd, void *data, int flags,
+    struct lwp *l)
+{
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+	struct wzero3keypad_softc *sc = (struct wzero3keypad_softc *)arg;
+#endif
+
+	switch (cmd) {
+	case WSKBDIO_GTYPE:
+		*(int *)data = WSKBD_TYPE_HPC_KBD;
+		return 0;
+	case WSKBDIO_SETLEDS:
+		return 0;
+	case WSKBDIO_GETLEDS:
+		*(int *)data = 0;
+		return 0;
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+	case WSKBDIO_SETMODE:
+		sc->sc_rawkbd = (*(int *)data == WSKBD_RAW);
+		return 0;
+#endif
+	}
+
+	return EPASSTHROUGH;
+}
+
+static int
+wzero3keypad_intr(void *arg)
+{
+	struct wzero3keypad_softc *sc = (struct wzero3keypad_softc *)arg;
+
+	pxa2x0_gpio_clear_intr(sc->sc_intr_pin);
+
+	wzero3keypad_poll1(sc, 0);
+
+	callout_schedule(&sc->sc_poll_ch, sc->sc_poll_interval);
+
+	return 1;
+}
+
+static void
+wzero3keypad_poll(void *v)
+{
+	struct wzero3keypad_softc *sc = (struct wzero3keypad_softc *)v;
+
+	wzero3keypad_poll1(sc, 1);
+
+	callout_stop(&sc->sc_poll_ch);
+}
+
+static void
+wzero3keypad_poll1(struct wzero3keypad_softc *sc, int doscan)
+{
+	uint32_t keydown;
+	uint32_t diff;
+	int i;
+	int s;
+
+	s = spltty();
+
+	keydown = wzero3keypad_getkeydown(sc, doscan);
+	diff = keydown ^ sc->sc_okeystat;
+	if (diff == 0)
+		goto out;
+
+	for (i = 0; i < KD_NUM; i++) {
+		if (diff & (1 << i)) {
+			int state = keydown & (1 << i);
+			int type = state ? WSCONS_EVENT_KEY_DOWN :
+			    WSCONS_EVENT_KEY_UP;
+			int key = wzero3keypad_wskbd_keys[i];
+#ifdef WSDISPLAY_COMPAT_RAWKBD
+			if (sc->sc_rawkbd) {
+				int n;
+				u_char data[16];
+
+				n = pckbd_encode(type, key, data);
+				wskbd_rawinput(sc->sc_wskbddev, data, n);
+			} else
+#endif
+				wskbd_input(sc->sc_wskbddev, type, key);
+		}
+	}
+	sc->sc_okeystat = keydown;
+
+out:
+	splx(s);
+}
+
+/*----------------------------------------------------------------------------
+ * AK4184 keypad controller for WS011SH
+ */
+/* ak4184 command register */
+#define	AKMCTRL_WR_SH	7
+#define	AKMCTRL_PAGE_SH	6
+#define	AKMCTRL_ADDR_SH	0
+#define	AKMCTRL_WRITE	(0<<AKMCTRL_WR_SH)
+#define	AKMCTRL_READ	(1<<AKMCTRL_WR_SH)
+#define	AKMCTRL_DATA	(0<<AKMCTRL_PAGE_SH)
+#define	AKMCTRL_CTRL	(1<<AKMCTRL_PAGE_SH)
+
+static void
+wzero3keypad_init(struct wzero3keypad_softc *sc)
+{
+	int s;
+
+	s = spltty();
+
+#if 0
+	/*
+	 * - key interrupt enable
+	 * - key touch scan
+	 * - debounce time: 1ms
+	 * - wait 100us for debounce time
+	 */
+	(void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
+	    AKMCTRL_WRITE | AKMCTRL_CTRL | (0<<AKMCTRL_ADDR_SH), 0);
+#endif
+
+	/* unmask all keys & columns */
+	(void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
+	    AKMCTRL_WRITE | AKMCTRL_CTRL | (1<<AKMCTRL_ADDR_SH), 0);
+	(void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
+	    AKMCTRL_WRITE | AKMCTRL_CTRL | (2<<AKMCTRL_ADDR_SH), 0);
+	(void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
+	    AKMCTRL_WRITE | AKMCTRL_CTRL | (3<<AKMCTRL_ADDR_SH), 0);
+
+	/* Enable keypad interrupt (kpdata dummy read) */
+	(void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
+	    AKMCTRL_READ | AKMCTRL_DATA | (1<<AKMCTRL_ADDR_SH), 0);
+
+	splx(s);
+}
+
+static uint32_t
+wzero3keypad_getkeydown(struct wzero3keypad_softc *sc, int doscan)
+{
+	uint32_t keydown = 0;
+	uint16_t status;
+	uint16_t kpdata;
+	int timo;
+
+	if (doscan) {
+		/* host scan */
+		(void) wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
+		    AKMCTRL_WRITE | AKMCTRL_CTRL | (4<<AKMCTRL_ADDR_SH), 0);
+		delay(100);
+	}
+
+	timo = 1000;
+	do {
+		status = wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
+		    AKMCTRL_READ | AKMCTRL_CTRL | (0<<AKMCTRL_ADDR_SH), 0);
+	} while ((status & 0xc000) == 0 && timo-- > 0);
+
+	kpdata = wzero3ssp_ic_send(WZERO3_SSP_IC_AK4184_KEYPAD,
+	    AKMCTRL_READ | AKMCTRL_DATA | (1<<AKMCTRL_ADDR_SH), 0);
+	if ((status & 0xc000) == 0xc000) {
+		if (!(kpdata & 0x8000)) {
+			int i;
+
+			for (i = 0; i < 3; i++) {
+				int key, bits;
+
+				key = kpdata & 0x1f;
+				if (key == 0)
+					break;
+				bits = ws011sh_keyscan2keydown[key];
+				if (bits != KD_INVALID)
+					keydown |= 1 << bits;
+				kpdata >>= 5;
+			}
+		}
+	}
+
+	return keydown;
+}

Reply via email to