summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2009-12-23 15:48:19 -0800
committerGary King <gking@nvidia.com>2009-12-23 17:54:08 -0800
commita79b4f2672df911b59a88e398fb52dd83d601de1 (patch)
tree95bc34b07368f7c4c5dce1a12aedf5016c22d39f /drivers
parent69c7efe0d7c958fb17d891ce28259c21e1df9179 (diff)
keyboard: add a keyboard driver for buttons connected to Tegra SoC GPIOs
Change-Id: If8d57293b0d6ba1bbf493f4e5ea1d5cc27eb25bc
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/keyboard/Kconfig8
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/tegra-gpio.c259
3 files changed, 268 insertions, 0 deletions
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 1c415c4dcc95..00653bd143fd 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -340,6 +340,14 @@ config KEYBOARD_TEGRA
Say Y here if you want to use a matrix keyboard connected directly
to the internal keyboard controller on Tegra SoCs
+config KEYBOARD_TEGRA_GPIO
+ boolean "NVIDIA Tegra GPIO button keyboard controller support"
+ depends on ARCH_TEGRA
+ default n
+ help
+ Say Y here if you want to use direct-connected Tegra SoC GPIO buttons
+ as a keyboard
+
config KEYBOARD_TEGRA_NVEC
boolean "NVIDIA Tegra NvEc-compliant embedded controller keyboard"
depends on ARCH_TEGRA && TEGRA_NVEC
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 301a409a33ed..7ceb80599cea 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o
obj-$(CONFIG_KEYBOARD_TEGRA_NVEC) += tegra-nvec.o
+obj-$(CONFIG_KEYBOARD_TEGRA_GPIO) += tegra-gpio.o
diff --git a/drivers/input/keyboard/tegra-gpio.c b/drivers/input/keyboard/tegra-gpio.c
new file mode 100644
index 000000000000..7d44288216c4
--- /dev/null
+++ b/drivers/input/keyboard/tegra-gpio.c
@@ -0,0 +1,259 @@
+/*
+ * drivers/input/keyboard/tegra-gpio.c
+ *
+ * Keyboard class input driver for buttons directly connected to NVIDIA
+ * Tegra SoC GPIOs
+ *
+ * Copyright (c) 2009, NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/kthread.h>
+#include "nvos.h"
+#include "nvodm_services.h"
+#include "nvodm_query_gpio.h"
+#include "nvrm_interrupt.h"
+#include "nvrm_module.h"
+#include "nvrm_gpio.h"
+#include "mach/nvrm_linux.h"
+
+#define DEBUG_NVGPIO_KBD 0
+
+#define logd(x) \
+ do { \
+ if (DEBUG_NVGPIO_KBD) \
+ printk x; \
+ } while (0) \
+
+struct nvgpio_key_info {
+ int port;
+ int pin;
+ int pin_type;
+ int debounce_time;
+ NvRmGpioPinHandle gpio_pin;
+ NvRmGpioInterruptHandle intr_handle;
+ int key_code;
+};
+
+static struct nvgpio_key_info s_nvgpio_key_info[] = {
+ //port, pin, type, bounce, pin, intr, code
+ {'c'-'a', 3, 0, 10, NULL, NULL, KEY_MENU},
+ {'d'-'a', 3, 0, 10, NULL, NULL, KEY_HOME},
+ {'d'-'a', 4, 0, 10, NULL, NULL, KEY_BACK}
+};
+
+static int s_num_pins = sizeof(s_nvgpio_key_info)/sizeof(s_nvgpio_key_info[0]);
+
+struct nvgpio_keyboard {
+ struct input_dev *input_dev;
+ char name[128];
+};
+
+struct nvgpio_keyboard *s_keyboard = NULL;
+static struct platform_device *s_nvgpio_keyboard_device = NULL;
+
+static void do_handle_interrupt(void *args)
+{
+ int key_pressed;
+ NvRmGpioPinState state;
+ struct nvgpio_key_info *key_info = (struct nvgpio_key_info*)args;
+
+ NvRmGpioReadPins(s_hGpioGlobal, &key_info->gpio_pin, &state, 1);
+ key_pressed = (state == NvRmGpioPinState_Low) ? 1 : 0;
+
+ input_report_key(s_keyboard->input_dev, key_info->key_code, key_pressed);
+ logd(("\n***gpio keyboard interrupt, port=%d, pin=%d, key_code=%d, press=%d",
+ key_info->port, key_info->pin, key_info->key_code, key_pressed));
+ NvRmGpioInterruptDone(key_info->intr_handle);
+}
+
+static int nvgpio_keyboard_open(struct input_dev *dev)
+{
+ return 0;
+}
+
+static void nvgpio_keyboard_close(struct input_dev *dev)
+{
+ return;
+}
+
+static int __devinit nvgpio_keyboard_probe(struct platform_device *pdev)
+{
+ int error;
+ NvError nv_err;
+ struct nvgpio_keyboard *keyboard;
+ struct input_dev *input_dev;
+ int i;
+
+ keyboard = kzalloc(sizeof(struct nvgpio_keyboard), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ error = -ENOMEM;
+ if (!keyboard || !input_dev)
+ goto fail;
+
+ keyboard->input_dev = input_dev;
+ input_set_drvdata(input_dev, keyboard);
+ platform_set_drvdata(pdev, input_dev);
+
+ for (i = 0; i < s_num_pins; i++) {
+ nv_err = NvRmGpioAcquirePinHandle(s_hGpioGlobal,
+ s_nvgpio_key_info[i].port, s_nvgpio_key_info[i].pin,
+ &s_nvgpio_key_info[i].gpio_pin);
+ if (nv_err != NvSuccess)
+ goto fail_gpio_init;
+ nv_err = NvRmGpioConfigPins(s_hGpioGlobal,
+ &s_nvgpio_key_info[i].gpio_pin, 1,
+ NvRmGpioPinMode_InputData);
+ if (nv_err != NvSuccess)
+ goto fail_gpio_init;
+ nv_err = NvRmGpioInterruptRegister(s_hGpioGlobal, s_hRmGlobal,
+ s_nvgpio_key_info[i].gpio_pin, do_handle_interrupt,
+ NvRmGpioPinMode_InputInterruptAny,
+ &s_nvgpio_key_info[i],
+ &s_nvgpio_key_info[i].intr_handle,
+ s_nvgpio_key_info[i].debounce_time);
+ if (nv_err != NvSuccess)
+ goto fail_gpio_init;
+ nv_err = NvRmGpioInterruptEnable(s_nvgpio_key_info[i].intr_handle);
+ if (nv_err != NvSuccess)
+ goto fail_gpio_init;
+ }
+
+ if (!strlen(keyboard->name))
+ snprintf(keyboard->name, sizeof(keyboard->name),
+ "nvgpio keyboard");
+
+ input_dev->name = keyboard->name;
+ input_dev->open = nvgpio_keyboard_open;
+ input_dev->close = nvgpio_keyboard_close;
+
+ __set_bit(EV_KEY, input_dev->evbit);
+ for (i = 0; i < s_num_pins; i++) {
+ __set_bit(s_nvgpio_key_info[i].key_code, input_dev->keybit);
+ }
+
+ error = input_register_device(keyboard->input_dev);
+ if (error)
+ goto fail_input_register;
+
+ logd(("\n*****nvgpio_keyboard_probe success"));
+ s_keyboard = keyboard;
+ return 0;
+
+fail_input_register:
+fail_gpio_init:
+ for (i = 0; i < s_num_pins; i++) {
+
+ if (s_nvgpio_key_info[i].intr_handle) {
+ NvRmGpioInterruptMask(s_nvgpio_key_info[i].intr_handle,
+ NV_TRUE);
+ NvRmGpioInterruptUnregister(s_hGpioGlobal, s_hRmGlobal,
+ s_nvgpio_key_info[i].intr_handle);
+ s_nvgpio_key_info[i].intr_handle = NULL;
+ }
+ if (s_nvgpio_key_info[i].gpio_pin) {
+ NvRmGpioReleasePinHandles(s_hGpioGlobal,
+ &s_nvgpio_key_info[i].gpio_pin, 1);
+ s_nvgpio_key_info[i].gpio_pin = NULL;
+ }
+ }
+fail:
+ input_free_device(input_dev);
+ kfree(keyboard);
+ return error;
+}
+
+static int __devexit nvgpio_keyboard_remove(struct platform_device *dev)
+{
+ int i;
+ struct input_dev *input_dev = platform_get_drvdata(dev);
+ struct nvgpio_keyboard *keyboard = platform_get_drvdata(dev);
+
+ for (i = 0; i < s_num_pins; i++) {
+
+ if (s_nvgpio_key_info[i].intr_handle) {
+ NvRmGpioInterruptMask(s_nvgpio_key_info[i].intr_handle,
+ NV_TRUE);
+ NvRmGpioInterruptUnregister(s_hGpioGlobal, s_hRmGlobal,
+ s_nvgpio_key_info[i].intr_handle);
+ s_nvgpio_key_info[i].intr_handle = NULL;
+ }
+ if (s_nvgpio_key_info[i].gpio_pin) {
+ NvRmGpioReleasePinHandles(s_hGpioGlobal,
+ &s_nvgpio_key_info[i].gpio_pin, 1);
+ s_nvgpio_key_info[i].gpio_pin = NULL;
+ }
+ }
+
+ input_free_device(input_dev);
+ kfree(keyboard);
+ return 0;
+}
+
+static struct platform_driver s_nvgpio_keyboard_driver = {
+ .driver = {
+ .name = "nvgpio_keyboard",
+ .owner = THIS_MODULE,
+ },
+ .probe = nvgpio_keyboard_probe,
+ .remove = __devexit_p(nvgpio_keyboard_remove),
+};
+
+static int __init nvgpio_keyboard_init(void)
+{
+ int err;
+
+ err = platform_driver_register(&s_nvgpio_keyboard_driver);
+ if (err)
+ goto error;
+
+ s_nvgpio_keyboard_device = platform_device_alloc("nvgpio_keyboard", -1);
+ err = -ENOMEM;
+ if (!s_nvgpio_keyboard_device)
+ goto error_unregister_driver;
+
+ err = platform_device_add(s_nvgpio_keyboard_device);
+ if (err)
+ goto error_free_device;
+ logd(("\n*****nvgpio_keyboard_init success"));
+ return 0;
+
+error_free_device:
+ platform_device_put(s_nvgpio_keyboard_device);
+error_unregister_driver:
+ platform_driver_unregister(&s_nvgpio_keyboard_driver);
+error:
+ return err;
+}
+
+static void __exit nvgpio_keyboard_exit(void)
+{
+ platform_device_unregister(s_nvgpio_keyboard_device);
+ platform_driver_unregister(&s_nvgpio_keyboard_driver);
+}
+
+module_init(nvgpio_keyboard_init);
+module_exit(nvgpio_keyboard_exit);
+
+#define DRIVER_DESC "Nvidia Gpio keyboard driver"
+#define DRIVER_LICENSE "GPL"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+