diff options
author | Gary King <gking@nvidia.com> | 2009-12-23 15:48:19 -0800 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2009-12-23 17:54:08 -0800 |
commit | a79b4f2672df911b59a88e398fb52dd83d601de1 (patch) | |
tree | 95bc34b07368f7c4c5dce1a12aedf5016c22d39f /drivers | |
parent | 69c7efe0d7c958fb17d891ce28259c21e1df9179 (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/Kconfig | 8 | ||||
-rw-r--r-- | drivers/input/keyboard/Makefile | 1 | ||||
-rw-r--r-- | drivers/input/keyboard/tegra-gpio.c | 259 |
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); + |