From patchwork Sun Apr 27 01:14:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrey Danin X-Patchwork-Id: 343142 X-Patchwork-Delegate: twarren@nvidia.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id DC1F51400D8 for ; Sun, 27 Apr 2014 20:40:37 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 2F79A4BBD8; Sun, 27 Apr 2014 12:40:36 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id aBH8YWeFgP51; Sun, 27 Apr 2014 12:40:35 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 78A9B4BBCC; Sun, 27 Apr 2014 12:40:33 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6FCBA4BBCC for ; Sun, 27 Apr 2014 12:40:29 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id r4+M7QKXgZ37 for ; Sun, 27 Apr 2014 12:40:26 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from fallback6.mail.ru (fallback6.mail.ru [94.100.176.134]) by theia.denx.de (Postfix) with ESMTP id 643694BB75 for ; Sun, 27 Apr 2014 12:40:26 +0200 (CEST) Received: from smtp33.i.mail.ru (smtp33.i.mail.ru [94.100.177.93]) by fallback6.mail.ru (mPOP.Fallback_MX) with ESMTP id 956773B86BFD for ; Sun, 27 Apr 2014 14:32:59 +0400 (MSK) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail2; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=/uljSMMP/FeFY6hI6aNxKTWrGL65ANpdUEIPP9hPSQ8=; b=n4hc27/Kx4IuLmNC2TFdnIBkzRB9KoDZLbuA57XZ8vbFoJgr6guud9+0LGMbiwIVy7t0bOKOf6dxcB9IPeH00LcC6e5ehaS2PNc3dudch1EbKJZkihc3vvBVeiajxcJ1Skd6VfRd+zbx0Cyq2gjgO/UYunbhf/mzQWn3KHCkn4I=; Received: from [87.255.14.112] (port=50586 helo=localhost.localdomain) by smtp33.i.mail.ru with esmtpa (envelope-from ) id 1WeMOF-00061u-Iy; Sun, 27 Apr 2014 14:32:55 +0400 From: Andrey Danin To: Tom Warren , u-boot@lists.denx.de Date: Sun, 27 Apr 2014 05:14:28 +0400 Message-Id: <1398561270-25091-5-git-send-email-danindrey@mail.ru> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1398561270-25091-1-git-send-email-danindrey@mail.ru> References: <[PATCH 0/3] ARM: tegra: add nvec keyboard support for paz00> <1398561270-25091-1-git-send-email-danindrey@mail.ru> X-Spam: Not detected X-Mras: Ok Cc: Julian Andres Klode , Stephen Warren , ac100@lists.launchpad.net Subject: [U-Boot] [PATCH v2 4/6] ARM: tegra: nvec: add keyboard support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Signed-off-by: Andrey Danin CC: Stephen Warren CC: Marc Dietrich CC: Julian Andres Klode CC: ac100@lists.launchpad.net --- Changes for v2: - fixed incorrect keys handling in nvec-keyboard driver .../include/asm/arch-tegra/tegra_nvec_keyboard.h | 304 ++++++++++++++++++++ drivers/input/Makefile | 3 + drivers/input/tegra-nvec-kbc.c | 215 ++++++++++++++ include/configs/tegra-common-post.h | 2 + 4 files changed, 524 insertions(+) create mode 100644 arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h create mode 100644 drivers/input/tegra-nvec-kbc.c diff --git a/arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h b/arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h new file mode 100644 index 0000000..5f789f4 --- /dev/null +++ b/arch/arm/include/asm/arch-tegra/tegra_nvec_keyboard.h @@ -0,0 +1,304 @@ +/* + * (C) Copyright 2014 + * Andrey Danin + * (C) Copyright 2009 + * NVIDIA Corporation. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _TEGRA_NVEC_KEYBOARD_H_ +#define _TEGRA_NVEC_KEYBOARD_H_ + +#include + + +/* Keytables */ + +static unsigned short code_tab_102us[] = { + /* 0x00 */ + KEY_GRAVE, + KEY_ESC, + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_0, + KEY_MINUS, + KEY_EQUAL, + KEY_BACKSPACE, + KEY_TAB, + /* 0x10 */ + KEY_Q, + KEY_W, + KEY_E, + KEY_R, + KEY_T, + KEY_Y, + KEY_U, + KEY_I, + KEY_O, + KEY_P, + KEY_LEFTBRACE, + KEY_RIGHTBRACE, + KEY_ENTER, + KEY_LEFTCTRL, + KEY_A, + KEY_S, + /* 0x20 */ + KEY_D, + KEY_F, + KEY_G, + KEY_H, + KEY_J, + KEY_K, + KEY_L, + KEY_SEMICOLON, + KEY_APOSTROPHE, + KEY_GRAVE, + KEY_LEFTSHIFT, + KEY_BACKSLASH, + KEY_Z, + KEY_X, + KEY_C, + KEY_V, + /* 0x30 */ + KEY_B, + KEY_N, + KEY_M, + KEY_COMMA, + KEY_DOT, + KEY_SLASH, + KEY_RIGHTSHIFT, + KEY_KPASTERISK, + KEY_LEFTALT, + KEY_SPACE, + KEY_CAPSLOCK, + KEY_F1, + KEY_F2, + KEY_F3, + KEY_F4, + KEY_F5, + /* 0x40 */ + KEY_F6, + KEY_F7, + KEY_F8, + KEY_F9, + KEY_F10, + KEY_FN, + /* VK_SCROLL */ + 0, + KEY_KP7, + KEY_KP8, + KEY_KP9, + KEY_KPMINUS, + KEY_KP4, + KEY_KP5, + KEY_KP6, + KEY_KPPLUS, + KEY_KP1, + /* 0x50 */ + KEY_KP2, + KEY_KP3, + KEY_KP0, + KEY_KPDOT, + /* VK_SNAPSHOT */ + 0, /* KEY_MENU, */ + KEY_POWER, + /* VK_OEM_102 */ + KEY_102ND, + KEY_F11, + KEY_F12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* 0x60 */ + 0, + 0, + 0, + 0, /* KEY_SEARCH, */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* 0x70 */ + 0, + 0, + 0, + KEY_KP5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + KEY_KP9, +}; + +static unsigned short extcode_tab_us102[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* 0x10 */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* VK_MEDIA_NEXT_TRACK */ + 0, + 0, + 0, + /* VK_RETURN */ + 0, + KEY_RIGHTCTRL, + 0, + 0, + /* 0x20 */ + KEY_MUTE, + /* VK_LAUNCH_APP1 */ + 0, + /* VK_MEDIA_PLAY_PAUSE */ + 0, + 0, + /* VK_MEDIA_STOP */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + /* 0x30 */ + KEY_VOLUMEUP, + 0, + /* VK_BROWSER_HOME */ + 0, + 0, + 0, + /* VK_DIVIDE */ + KEY_KPSLASH, + 0, + /* VK_SNAPSHOT */ + KEY_SYSRQ, + /* VK_RMENU */ + KEY_RIGHTALT, + /* VK_OEM_NV_BACKLIGHT_UP */ + 0, + /* VK_OEM_NV_BACKLIGHT_DN */ + 0, + /* VK_OEM_NV_BACKLIGHT_AUTOTOGGLE */ + 0, + /* VK_OEM_NV_POWER_INFO */ + 0, + /* VK_OEM_NV_WIFI_TOGGLE */ + 0, + /* VK_OEM_NV_DISPLAY_SELECT */ + 0, + /* VK_OEM_NV_AIRPLANE_TOGGLE */ + 0, + /* 0x40 */ + 0, + KEY_LEFT, + 0, + 0, + 0, + 0, + 0, /* KEY_CANCEL, */ + KEY_HOME, + KEY_UP, + KEY_PAGEUP, + 0, + KEY_LEFT, + 0, + KEY_RIGHT, + 0, + KEY_END, + /* 0x50 */ + KEY_DOWN, + KEY_PAGEDOWN, + KEY_INSERT, + KEY_DELETE, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + KEY_LEFTMETA, + 0, + KEY_ESC, + KEY_KPMINUS, + 0, + 0, + 0, + 0, + 0, + 0, + /* VK_BROWSER_SEARCH */ + 0, + /* VK_BROWSER_FAVORITES */ + 0, + /* VK_BROWSER_REFRESH */ + 0, + /* VK_BROWSER_STOP */ + 0, + /* VK_BROWSER_FORWARD */ + 0, + /* VK_BROWSER_BACK */ + 0, + /* VK_LAUNCH_APP2 */ + 0, + /* VK_LAUNCH_MAIL */ + 0, + /* VK_LAUNCH_MEDIA_SELECT */ + 0, +}; + +static unsigned short *code_tabs[] = { code_tab_102us, extcode_tab_us102 }; + + +#endif /* _TEGRA_NVEC_KEYBOARD_H_ */ diff --git a/drivers/input/Makefile b/drivers/input/Makefile index a8e9be2..38c576f 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile @@ -7,6 +7,9 @@ obj-$(CONFIG_I8042_KBD) += i8042.o obj-$(CONFIG_TEGRA_KEYBOARD) += tegra-kbc.o +ifdef CONFIG_SYS_I2C_TEGRA_NVEC +obj-$(CONFIG_TEGRA_NVEC_KEYBOARD) += tegra-nvec-kbc.o +endif obj-$(CONFIG_CROS_EC_KEYB) += cros_ec_keyb.o ifdef CONFIG_PS2KBD obj-y += keyboard.o pc_keyb.o diff --git a/drivers/input/tegra-nvec-kbc.c b/drivers/input/tegra-nvec-kbc.c new file mode 100644 index 0000000..f5832b1 --- /dev/null +++ b/drivers/input/tegra-nvec-kbc.c @@ -0,0 +1,215 @@ +/* + * (C) Copyright 2014 + * Andrey Danin + * (C) Copyright 2011 + * NVIDIA Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + + +enum { + KBC_MAX_KPENT = 8, + KBC_REPEAT_RATE_MS = 30, + KBC_REPEAT_DELAY_MS = 240, +}; + +/* keyboard config/state */ +static struct keyb { + int registered; + struct input_config input; /* The input layer */ + int pressed_keys[KBC_MAX_KPENT]; + int pressed_keys_cnt; +} config; + + +/* 0 - pressed, other - released */ +char keys[256]; + + +/* nvec commands */ +static char enable_kbd[] = { NVEC_KBD, ENABLE_KBD }; +static char reset_kbd[] = { NVEC_PS2, MOUSE_SEND_CMD, MOUSE_RESET, 3 }; +static char clear_leds[] = { NVEC_KBD, SET_LEDS, 0 }; + + +/** + * Check the tegra nvec keyboard, and send any keys that are pressed. + * + * This is called by input_tstc() and input_getc() when they need more + * characters + * + * @param input Input configuration + * @return 1, to indicate that we have something to look at + */ +int tegra_nvec_kbc_check(struct input_config *input) +{ + int i; + + nvec_read_events(); + + config.pressed_keys_cnt = 0; + /* TODO Optimization required */ + for (i = 0; i < sizeof(keys); ++i) { + if (keys[i] == 0 && config.pressed_keys_cnt < KBC_MAX_KPENT) { + config.pressed_keys[config.pressed_keys_cnt] = i; + ++config.pressed_keys_cnt; + } + } + + input_send_keycodes(input, + config.pressed_keys, + config.pressed_keys_cnt); + + return config.pressed_keys_cnt; +} + + +/** + * Test if keys are available to be read + * + * @return 0 if no keys available, 1 if keys are available + */ +static int kbd_tstc(void) +{ + /* Just get input to do this for us */ + return input_tstc(&config.input); +} + + +/** + * Read a key + * + * TODO: U-Boot wants 0 for no key, but Ctrl-@ is a valid key... + * + * @return ASCII key code, or 0 if no key, or -1 if error + */ +static int kbd_getc(void) +{ + /* Just get input to do this for us */ + return input_getc(&config.input); +} + + +int tegra_nvec_process_keyboard_msg(const unsigned char *msg) +{ + int code, state; + int event_type; + int _size; + int key; + + + event_type = nvec_msg_event_type(msg); + if (event_type != NVEC_KEYBOARD) + return -1; + + _size = (msg[0] & (3 << 5)) >> 5; + + if (_size == NVEC_VAR_SIZE) { + debug("Skip unsupported msg (size: %d)\n", _size); + return -1; + } + + if (_size == NVEC_3BYTES) + msg++; + + code = msg[1] & 0x7f; + state = msg[1] & 0x80; + + key = code_tabs[_size][code]; + keys[key] = state; + + return 0; +} + + +int tegra_nvec_enable_kbd_events(void) +{ + if (nvec_do_request(reset_kbd, 4)) { + error("NVEC: failed to reset keyboard\n"); + return -1; + } + if (nvec_do_request(clear_leds, 3)) { + error("NVEC: failed to clear leds\n"); + return -1; + } + if (nvec_do_request(enable_kbd, 2)) { + error("NVEC: failed to enable keyboard\n"); + return -1; + } + + debug("NVEC: keyboard initialization finished\n"); + + return 0; +} + + +static int tegra_nvec_kbc_start(void) +{ + if (config.registered) + return 0; + + struct nvec_periph nvec_keyboard; + memset(&nvec_keyboard, 0, sizeof(nvec_keyboard)); + nvec_keyboard.start = tegra_nvec_enable_kbd_events; + nvec_keyboard.process_msg = tegra_nvec_process_keyboard_msg; + + if (nvec_register_periph(NVEC_KEYBOARD, &nvec_keyboard)) { + error("NVEC: failed to register keyboard perephirial device"); + return -1; + } + + config.registered = 1; + + return 0; +} + + +int drv_keyboard_init(void) +{ + struct stdio_dev dev; + int error; +#ifdef CONFIG_CONSOLE_MUX + char *stdinname = getenv("stdin"); +#endif + + memset(keys, 1, sizeof(keys)); + + config.registered = 0; + + if (input_init(&config.input, 0)) { + printf("nvec kbc: cannot set up input\n"); + return -1; + } + input_set_delays(&config.input, KBC_REPEAT_DELAY_MS, + KBC_REPEAT_RATE_MS); + config.input.read_keys = tegra_nvec_kbc_check; + + memset(&dev, '\0', sizeof(dev)); + strcpy(dev.name, "tegra-nvec-kbc"); + dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + dev.getc = kbd_getc; + dev.tstc = kbd_tstc; + dev.start = tegra_nvec_kbc_start; + + /* Register the device. tegra_nvec_kbc_start() will be called soon */ + error = input_stdio_register(&dev); + if (error) { + printf("nvec kbc: failed to register stdio device, %d\n", + error); + return error; + } +#ifdef CONFIG_CONSOLE_MUX + error = iomux_doenv(stdin, stdinname); + if (error) { + printf("nvec kbc: iomux_doenv failed, %d\n", error); + return error; + } +#endif + return 0; +} diff --git a/include/configs/tegra-common-post.h b/include/configs/tegra-common-post.h index e1a3bbc..efc0ef9 100644 --- a/include/configs/tegra-common-post.h +++ b/include/configs/tegra-common-post.h @@ -106,6 +106,8 @@ #ifdef CONFIG_TEGRA_KEYBOARD #define STDIN_KBD_KBC ",tegra-kbc" +#elif defined(CONFIG_TEGRA_NVEC_KEYBOARD) +#define STDIN_KBD_KBC ",tegra-nvec-kbc" #else #define STDIN_KBD_KBC "" #endif