Commit 5e75c5f5 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
  Input: gpio_mouse - use standard driver registration method
  Input: mark serio and i8042 as suspended when hibernating too
  Input: add support for generic GPIO-based matrix keypad
  Input: arrange keyboards alphabetically
  Input: gpio-keys - avoid possibility of sleeping in timer function
  Input: gpio-keys - revert 'change timer to workqueue'
  Input: dm355evm_keys - fix kconfig symbol names
  Input: wacom - add DTF720a support and fix rotation on Intuos3
  Input: i8042 - more reset quirks for MSI Wind-clone netbooks
parents d6d46551 eeafa5ef
...@@ -12,6 +12,42 @@ menuconfig INPUT_KEYBOARD ...@@ -12,6 +12,42 @@ menuconfig INPUT_KEYBOARD
if INPUT_KEYBOARD if INPUT_KEYBOARD
config KEYBOARD_AAED2000
tristate "AAED-2000 keyboard"
depends on MACH_AAED2000
select INPUT_POLLDEV
default y
help
Say Y here to enable the keyboard on the Agilent AAED-2000
development board.
To compile this driver as a module, choose M here: the
module will be called aaed2000_kbd.
config KEYBOARD_AMIGA
tristate "Amiga keyboard"
depends on AMIGA
help
Say Y here if you are running Linux on any AMIGA and have a keyboard
attached.
To compile this driver as a module, choose M here: the
module will be called amikbd.
config ATARI_KBD_CORE
bool
config KEYBOARD_ATARI
tristate "Atari keyboard"
depends on ATARI
select ATARI_KBD_CORE
help
Say Y here if you are running Linux on any Atari and have a keyboard
attached.
To compile this driver as a module, choose M here: the
module will be called atakbd.
config KEYBOARD_ATKBD config KEYBOARD_ATKBD
tristate "AT keyboard" if EMBEDDED || !X86 tristate "AT keyboard" if EMBEDDED || !X86
default y default y
...@@ -68,69 +104,14 @@ config KEYBOARD_ATKBD_RDI_KEYCODES ...@@ -68,69 +104,14 @@ config KEYBOARD_ATKBD_RDI_KEYCODES
right-hand column will be interpreted as the key shown in the right-hand column will be interpreted as the key shown in the
left-hand column. left-hand column.
config KEYBOARD_SUNKBD config KEYBOARD_BFIN
tristate "Sun Type 4 and Type 5 keyboard" tristate "Blackfin BF54x keypad support"
select SERIO depends on (BF54x && !BF544)
help
Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
connected either to the Sun keyboard connector or to an serial
(RS-232) port via a simple adapter.
To compile this driver as a module, choose M here: the
module will be called sunkbd.
config KEYBOARD_LKKBD
tristate "DECstation/VAXstation LK201/LK401 keyboard"
select SERIO
help
Say Y here if you want to use a LK201 or LK401 style serial
keyboard. This keyboard is also useable on PCs if you attach
it with the inputattach program. The connector pinout is
described within lkkbd.c.
To compile this driver as a module, choose M here: the
module will be called lkkbd.
config KEYBOARD_LOCOMO
tristate "LoCoMo Keyboard Support"
depends on SHARP_LOCOMO && INPUT_KEYBOARD
help
Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
To compile this driver as a module, choose M here: the
module will be called locomokbd.
config KEYBOARD_XTKBD
tristate "XT keyboard"
select SERIO
help
Say Y here if you want to use the old IBM PC/XT keyboard (or
compatible) on your system. This is only possible with a
parallel port keyboard adapter, you cannot connect it to the
keyboard port on a PC that runs Linux.
To compile this driver as a module, choose M here: the
module will be called xtkbd.
config KEYBOARD_NEWTON
tristate "Newton keyboard"
select SERIO
help
Say Y here if you have a Newton keyboard on a serial port.
To compile this driver as a module, choose M here: the
module will be called newtonkbd.
config KEYBOARD_STOWAWAY
tristate "Stowaway keyboard"
select SERIO
help help
Say Y here if you have a Stowaway keyboard on a serial port. Say Y here if you want to use the BF54x keypad.
Stowaway compatible keyboards like Dicota Input-PDA keyboard
are also supported by this driver.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called stowaway. module will be called bf54x-keys.
config KEYBOARD_CORGI config KEYBOARD_CORGI
tristate "Corgi keyboard" tristate "Corgi keyboard"
...@@ -143,61 +124,50 @@ config KEYBOARD_CORGI ...@@ -143,61 +124,50 @@ config KEYBOARD_CORGI
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called corgikbd. module will be called corgikbd.
config KEYBOARD_SPITZ config KEYBOARD_LKKBD
tristate "Spitz keyboard" tristate "DECstation/VAXstation LK201/LK401 keyboard"
depends on PXA_SHARPSL select SERIO
default y
help help
Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, Say Y here if you want to use a LK201 or LK401 style serial
SL-C3000 and Sl-C3100 series of PDAs. keyboard. This keyboard is also useable on PCs if you attach
it with the inputattach program. The connector pinout is
described within lkkbd.c.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called spitzkbd. module will be called lkkbd.
config KEYBOARD_TOSA config KEYBOARD_EP93XX
tristate "Tosa keyboard" tristate "EP93xx Matrix Keypad support"
depends on MACH_TOSA depends on ARCH_EP93XX
default y
help help
Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) Say Y here to enable the matrix keypad on the Cirrus EP93XX.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called tosakbd. module will be called ep93xx_keypad.
config KEYBOARD_TOSA_USE_EXT_KEYCODES config KEYBOARD_GPIO
bool "Tosa keyboard: use extended keycodes" tristate "GPIO Buttons"
depends on KEYBOARD_TOSA depends on GENERIC_GPIO
default n
help help
Say Y here to enable the tosa keyboard driver to generate extended This driver implements support for buttons connected
(>= 127) keycodes. Be aware, that they can't be correctly interpreted to GPIO pins of various CPUs (and some other chips).
by either console keyboard driver or by Kdrive keybd driver.
Say Y only if you know, what you are doing!
config KEYBOARD_AMIGA Say Y here if your device has buttons connected
tristate "Amiga keyboard" directly to such GPIO pins. Your board-specific
depends on AMIGA setup logic must also provide a platform device,
help with configuration data saying which GPIOs are used.
Say Y here if you are running Linux on any AMIGA and have a keyboard
attached.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called amikbd. module will be called gpio_keys.
config ATARI_KBD_CORE config KEYBOARD_MATRIX
bool tristate "GPIO driven matrix keypad support"
depends on GENERIC_GPIO
config KEYBOARD_ATARI
tristate "Atari keyboard"
depends on ATARI
select ATARI_KBD_CORE
help help
Say Y here if you are running Linux on any Atari and have a keyboard Enable support for GPIO driven matrix keypad.
attached.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called atakbd. module will be called matrix_keypad.
config KEYBOARD_HIL_OLD config KEYBOARD_HIL_OLD
tristate "HP HIL keyboard support (simple driver)" tristate "HP HIL keyboard support (simple driver)"
...@@ -261,20 +231,39 @@ config KEYBOARD_LM8323 ...@@ -261,20 +231,39 @@ config KEYBOARD_LM8323
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called lm8323. module will be called lm8323.
config KEYBOARD_OMAP config KEYBOARD_LOCOMO
tristate "TI OMAP keypad support" tristate "LoCoMo Keyboard Support"
depends on (ARCH_OMAP1 || ARCH_OMAP2) depends on SHARP_LOCOMO
help help
Say Y here if you want to use the OMAP keypad. Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called omap-keypad. module will be called locomokbd.
config KEYBOARD_MAPLE
tristate "Maple bus keyboard"
depends on SH_DREAMCAST && MAPLE
help
Say Y here if you have a Dreamcast console running Linux and have
a keyboard attached to its Maple bus.
To compile this driver as a module, choose M here: the
module will be called maple_keyb.
config KEYBOARD_NEWTON
tristate "Newton keyboard"
select SERIO
help
Say Y here if you have a Newton keyboard on a serial port.
To compile this driver as a module, choose M here: the
module will be called newtonkbd.
config KEYBOARD_PXA27x config KEYBOARD_PXA27x
tristate "PXA27x/PXA3xx keypad support" tristate "PXA27x/PXA3xx keypad support"
depends on PXA27x || PXA3xx depends on PXA27x || PXA3xx
help help
Enable support for PXA27x/PXA3xx keypad controller Enable support for PXA27x/PXA3xx keypad controller.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called pxa27x_keypad. module will be called pxa27x_keypad.
...@@ -288,51 +277,38 @@ config KEYBOARD_PXA930_ROTARY ...@@ -288,51 +277,38 @@ config KEYBOARD_PXA930_ROTARY
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called pxa930_rotary. module will be called pxa930_rotary.
config KEYBOARD_AAED2000 config KEYBOARD_SPITZ
tristate "AAED-2000 keyboard" tristate "Spitz keyboard"
depends on MACH_AAED2000 depends on PXA_SHARPSL
select INPUT_POLLDEV
default y default y
help help
Say Y here to enable the keyboard on the Agilent AAED-2000 Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
development board. SL-C3000 and Sl-C3100 series of PDAs.
To compile this driver as a module, choose M here: the
module will be called aaed2000_kbd.
config KEYBOARD_GPIO
tristate "GPIO Buttons"
depends on GENERIC_GPIO
help
This driver implements support for buttons connected
to GPIO pins of various CPUs (and some other chips).
Say Y here if your device has buttons connected
directly to such GPIO pins. Your board-specific
setup logic must also provide a platform device,
with configuration data saying which GPIOs are used.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called gpio-keys. module will be called spitzkbd.
config KEYBOARD_MAPLE config KEYBOARD_STOWAWAY
tristate "Maple bus keyboard" tristate "Stowaway keyboard"
depends on SH_DREAMCAST && MAPLE select SERIO
help help
Say Y here if you have a Dreamcast console running Linux and have Say Y here if you have a Stowaway keyboard on a serial port.
a keyboard attached to its Maple bus. Stowaway compatible keyboards like Dicota Input-PDA keyboard
are also supported by this driver.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called maple_keyb. module will be called stowaway.
config KEYBOARD_BFIN config KEYBOARD_SUNKBD
tristate "Blackfin BF54x keypad support" tristate "Sun Type 4 and Type 5 keyboard"
depends on (BF54x && !BF544) select SERIO
help help
Say Y here if you want to use the BF54x keypad. Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
connected either to the Sun keyboard connector or to an serial
(RS-232) port via a simple adapter.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called bf54x-keys. module will be called sunkbd.
config KEYBOARD_SH_KEYSC config KEYBOARD_SH_KEYSC
tristate "SuperH KEYSC keypad support" tristate "SuperH KEYSC keypad support"
...@@ -344,13 +320,45 @@ config KEYBOARD_SH_KEYSC ...@@ -344,13 +320,45 @@ config KEYBOARD_SH_KEYSC
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called sh_keysc. module will be called sh_keysc.
config KEYBOARD_EP93XX config KEYBOARD_OMAP
tristate "EP93xx Matrix Keypad support" tristate "TI OMAP keypad support"
depends on ARCH_EP93XX depends on (ARCH_OMAP1 || ARCH_OMAP2)
help help
Say Y here to enable the matrix keypad on the Cirrus EP93XX. Say Y here if you want to use the OMAP keypad.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ep93xx_keypad. module will be called omap-keypad.
config KEYBOARD_TOSA
tristate "Tosa keyboard"
depends on MACH_TOSA
default y
help
Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa)
To compile this driver as a module, choose M here: the
module will be called tosakbd.
config KEYBOARD_TOSA_USE_EXT_KEYCODES
bool "Tosa keyboard: use extended keycodes"
depends on KEYBOARD_TOSA
help
Say Y here to enable the tosa keyboard driver to generate extended
(>= 127) keycodes. Be aware, that they can't be correctly interpreted
by either console keyboard driver or by Kdrive keybd driver.
Say Y only if you know, what you are doing!
config KEYBOARD_XTKBD
tristate "XT keyboard"
select SERIO
help
Say Y here if you want to use the old IBM PC/XT keyboard (or
compatible) on your system. This is only possible with a
parallel port keyboard adapter, you cannot connect it to the
keyboard port on a PC that runs Linux.
To compile this driver as a module, choose M here: the
module will be called xtkbd.
endif endif
...@@ -4,29 +4,30 @@ ...@@ -4,29 +4,30 @@
# Each configuration option enables a list of files. # Each configuration option enables a list of files.
obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o
obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o
obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o
obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o
obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o obj-$(CONFIG_KEYBOARD_LM8323) += lm8323.o
obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o
obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o
obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o
obj-$(CONFIG_KEYBOARD_MAPLE) += maple_keyb.o
obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o
obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o
obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o
obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o
obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o
...@@ -29,7 +29,8 @@ ...@@ -29,7 +29,8 @@
struct gpio_button_data { struct gpio_button_data {
struct gpio_keys_button *button; struct gpio_keys_button *button;
struct input_dev *input; struct input_dev *input;
struct delayed_work work; struct timer_list timer;
struct work_struct work;
}; };
struct gpio_keys_drvdata { struct gpio_keys_drvdata {
...@@ -40,7 +41,7 @@ struct gpio_keys_drvdata { ...@@ -40,7 +41,7 @@ struct gpio_keys_drvdata {
static void gpio_keys_report_event(struct work_struct *work) static void gpio_keys_report_event(struct work_struct *work)
{ {
struct gpio_button_data *bdata = struct gpio_button_data *bdata =
container_of(work, struct gpio_button_data, work.work); container_of(work, struct gpio_button_data, work);
struct gpio_keys_button *button = bdata->button; struct gpio_keys_button *button = bdata->button;
struct input_dev *input = bdata->input; struct input_dev *input = bdata->input;
unsigned int type = button->type ?: EV_KEY; unsigned int type = button->type ?: EV_KEY;
...@@ -50,17 +51,25 @@ static void gpio_keys_report_event(struct work_struct *work) ...@@ -50,17 +51,25 @@ static void gpio_keys_report_event(struct work_struct *work)
input_sync(input); input_sync(input);
} }
static void gpio_keys_timer(unsigned long _data)
{
struct gpio_button_data *data = (struct gpio_button_data *)_data;
schedule_work(&data->work);
}
static irqreturn_t gpio_keys_isr(int irq, void *dev_id) static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{ {
struct gpio_button_data *bdata = dev_id; struct gpio_button_data *bdata = dev_id;
struct gpio_keys_button *button = bdata->button; struct gpio_keys_button *button = bdata->button;
unsigned long delay;
BUG_ON(irq != gpio_to_irq(button->gpio)); BUG_ON(irq != gpio_to_irq(button->gpio));
delay = button->debounce_interval ? if (button->debounce_interval)
msecs_to_jiffies(button->debounce_interval) : 0; mod_timer(&bdata->timer,
schedule_delayed_work(&bdata->work, delay); jiffies + msecs_to_jiffies(button->debounce_interval));
else
schedule_work(&bdata->work);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -107,7 +116,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) ...@@ -107,7 +116,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
bdata->input = input; bdata->input = input;
bdata->button = button; bdata->button = button;
INIT_DELAYED_WORK(&bdata->work, gpio_keys_report_event); setup_timer(&bdata->timer,
gpio_keys_timer, (unsigned long)bdata);
INIT_WORK(&bdata->work, gpio_keys_report_event);
error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); error = gpio_request(button->gpio, button->desc ?: "gpio_keys");
if (error < 0) { if (error < 0) {
...@@ -166,7 +177,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) ...@@ -166,7 +177,9 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
fail2: fail2:
while (--i >= 0) { while (--i >= 0) {
free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
cancel_delayed_work_sync(&ddata->data[i].work); if (pdata->buttons[i].debounce_interval)
del_timer_sync(&ddata->data[i].timer);
cancel_work_sync(&ddata->data[i].work);
gpio_free(pdata->buttons[i].gpio); gpio_free(pdata->buttons[i].gpio);
} }
...@@ -190,7 +203,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) ...@@ -190,7 +203,9 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev)
for (i = 0; i < pdata->nbuttons; i++) { for (i = 0; i < pdata->nbuttons; i++) {
int irq = gpio_to_irq(pdata->buttons[i].gpio); int irq = gpio_to_irq(pdata->buttons[i].gpio);
free_irq(irq, &ddata->data[i]); free_irq(irq, &ddata->data[i]);
cancel_delayed_work_sync(&ddata->data[i].work); if (pdata->buttons[i].debounce_interval)
del_timer_sync(&ddata->data[i].timer);
cancel_work_sync(&ddata->data[i].work);
gpio_free(pdata->buttons[i].gpio); gpio_free(pdata->buttons[i].gpio);
} }
......
/*
* GPIO driven matrix keyboard driver
*
* Copyright (c) 2008 Marek Vasut <marek.vasut@gmail.com>
*
* Based on corgikbd.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/input/matrix_keypad.h>
struct matrix_keypad {
const struct matrix_keypad_platform_data *pdata;
struct input_dev *input_dev;
unsigned short *keycodes;
uint32_t last_key_state[MATRIX_MAX_COLS];
struct delayed_work work;
bool scan_pending;
bool stopped;
spinlock_t lock;
};
/*
* NOTE: normally the GPIO has to be put into HiZ when de-activated to cause
* minmal side effect when scanning other columns, here it is configured to
* be input, and it should work on most platforms.
*/
static void __activate_col(const struct matrix_keypad_platform_data *pdata,
int col, bool on)
{
bool level_on = !pdata->active_low;
if (on) {
gpio_direction_output(pdata->col_gpios[col], level_on);
} else {
gpio_set_value_cansleep(pdata->col_gpios[col], !level_on);
gpio_direction_input(pdata->col_gpios[col]);
}
}
static void activate_col(const struct matrix_keypad_platform_data *pdata,
int col, bool on)
{
__activate_col(pdata, col, on);
if (on && pdata->col_scan_delay_us)
udelay(pdata->col_scan_delay_us);
}
static void activate_all_cols(const struct matrix_keypad_platform_data *pdata,
bool on)
{
int col;
for (col = 0; col < pdata->num_col_gpios; col++)
__activate_col(pdata, col, on);
}
static bool row_asserted(const struct matrix_keypad_platform_data *pdata,
int row)
{
return gpio_get_value_cansleep(pdata->row_gpios[row]) ?
!pdata->active_low : pdata->active_low;
}
static void enable_row_irqs(struct matrix_keypad *keypad)
{
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
for (i = 0; i < pdata->num_row_gpios; i++)
enable_irq(gpio_to_irq(pdata->row_gpios[i]));
}
static void disable_row_irqs(struct matrix_keypad *keypad)
{
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
for (i = 0; i < pdata->num_row_gpios; i++)
disable_irq_nosync(gpio_to_irq(pdata->row_gpios[i]));
}
/*
* This gets the keys from keyboard and reports it to input subsystem
*/
static void matrix_keypad_scan(struct work_struct *work)
{
struct matrix_keypad *keypad =
container_of(work, struct matrix_keypad, work.work);
struct input_dev *input_dev = keypad->input_dev;
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
uint32_t new_state[MATRIX_MAX_COLS];
int row, col, code;
/* de-activate all columns for scanning */
activate_all_cols(pdata, false);
memset(new_state, 0, sizeof(new_state));
/* assert each column and read the row status out */
for (col = 0; col < pdata->num_col_gpios; col++) {
activate_col(pdata, col, true);
for (row = 0; row < pdata->num_row_gpios; row++)
new_state[col] |=
row_asserted(pdata, row) ? (1 << row) : 0;
activate_col(pdata, col, false);
}
for (col = 0; col < pdata->num_col_gpios; col++) {
uint32_t bits_changed;
bits_changed = keypad->last_key_state[col] ^ new_state[col];
if (bits_changed == 0)
continue;
for (row = 0; row < pdata->num_row_gpios; row++) {
if ((bits_changed & (1 << row)) == 0)
continue;
code = (row << 4) + col;
input_event(input_dev, EV_MSC, MSC_SCAN, code);
input_report_key(input_dev,
keypad->keycodes[code],
new_state[col] & (1 << row));
}
}
input_sync(input_dev);
memcpy(keypad->last_key_state, new_state, sizeof(new_state));
activate_all_cols(pdata, true);
/* Enable IRQs again */
spin_lock_irq(&keypad->lock);
keypad->scan_pending = false;
enable_row_irqs(keypad);
spin_unlock_irq(&keypad->lock);
}
static irqreturn_t matrix_keypad_interrupt(int irq, void *id)
{
struct matrix_keypad *keypad = id;
unsigned long flags;
spin_lock_irqsave(&keypad->lock, flags);
/*
* See if another IRQ beaten us to it and scheduled the
* scan already. In that case we should not try to
* disable IRQs again.
*/
if (unlikely(keypad->scan_pending || keypad->stopped))
goto out;
disable_row_irqs(keypad);
keypad->scan_pending = true;
schedule_delayed_work(&keypad->work,
msecs_to_jiffies(keypad->pdata->debounce_ms));
out:
spin_unlock_irqrestore(&keypad->lock, flags);
return IRQ_HANDLED;
}
static int matrix_keypad_start(struct input_dev *dev)
{
struct matrix_keypad *keypad = input_get_drvdata(dev);
keypad->stopped = false;
mb();
/*
* Schedule an immediate key scan to capture current key state;
* columns will be activated and IRQs be enabled after the scan.
*/
schedule_delayed_work(&keypad->work, 0);
return 0;
}
static void matrix_keypad_stop(struct input_dev *dev)
{
struct matrix_keypad *keypad = input_get_drvdata(dev);
keypad->stopped = true;
mb();
flush_work(&keypad->work.work);
/*
* matrix_keypad_scan() will leave IRQs enabled;
* we should disable them now.
*/
disable_row_irqs(keypad);
}
#ifdef CONFIG_PM
static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state)
{
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
matrix_keypad_stop(keypad->input_dev);
if (device_may_wakeup(&pdev->dev))
for (i = 0; i < pdata->num_row_gpios; i++)
enable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
return 0;
}
static int matrix_keypad_resume(struct platform_device *pdev)
{
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
if (device_may_wakeup(&pdev->dev))
for (i = 0; i < pdata->num_row_gpios; i++)
disable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
matrix_keypad_start(keypad->input_dev);
return 0;
}
#else
#define matrix_keypad_suspend NULL
#define matrix_keypad_resume NULL
#endif
static int __devinit init_matrix_gpio(struct platform_device *pdev,
struct matrix_keypad *keypad)
{
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i, err = -EINVAL;
/* initialized strobe lines as outputs, activated */
for (i = 0; i < pdata->num_col_gpios; i++) {
err = gpio_request(pdata->col_gpios[i], "matrix_kbd_col");
if (err) {
dev_err(&pdev->dev,
"failed to request GPIO%d for COL%d\n",
pdata->col_gpios[i], i);
goto err_free_cols;
}
gpio_direction_output(pdata->col_gpios[i], !pdata->active_low);
}
for (i = 0; i < pdata->num_row_gpios; i++) {
err = gpio_request(pdata->row_gpios[i], "matrix_kbd_row");
if (err) {
dev_err(&pdev->dev,
"failed to request GPIO%d for ROW%d\n",
pdata->row_gpios[i], i);
goto err_free_rows;
}
gpio_direction_input(pdata->row_gpios[i]);
}
for (i = 0; i < pdata->num_row_gpios; i++) {
err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
matrix_keypad_interrupt,
IRQF_DISABLED |
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
"matrix-keypad", keypad);
if (err) {
dev_err(&pdev->dev,
"Unable to acquire interrupt for GPIO line %i\n",
pdata->row_gpios[i]);
goto err_free_irqs;
}
}
/* initialized as disabled - enabled by input->open */
disable_row_irqs(keypad);
return 0;
err_free_irqs:
while (--i >= 0)
free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
i = pdata->num_row_gpios;
err_free_rows:
while (--i >= 0)
gpio_free(pdata->row_gpios[i]);
i = pdata->num_col_gpios;
err_free_cols:
while (--i >= 0)
gpio_free(pdata->col_gpios[i]);
return err;
}
static int __devinit matrix_keypad_probe(struct platform_device *pdev)
{
const struct matrix_keypad_platform_data *pdata;
const struct matrix_keymap_data *keymap_data;
struct matrix_keypad *keypad;
struct input_dev *input_dev;
unsigned short *keycodes;
int i;
int err;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "no platform data defined\n");
return -EINVAL;
}
keymap_data = pdata->keymap_data;
if (!keymap_data) {
dev_err(&pdev->dev, "no keymap data defined\n");
return -EINVAL;
}
if (!keymap_data->max_keymap_size) {
dev_err(&pdev->dev, "invalid keymap data supplied\n");
return -EINVAL;
}
keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL);
keycodes = kzalloc(keymap_data->max_keymap_size *
sizeof(keypad->keycodes),
GFP_KERNEL);
input_dev = input_allocate_device();
if (!keypad || !keycodes || !input_dev) {
err = -ENOMEM;
goto err_free_mem;
}
keypad->input_dev = input_dev;
keypad->pdata = pdata;
keypad->keycodes = keycodes;
keypad->stopped = true;
INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan);
spin_lock_init(&keypad->lock);
input_dev->name = pdev->name;
input_dev->id.bustype = BUS_HOST;
input_dev->dev.parent = &pdev->dev;
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_dev->open = matrix_keypad_start;
input_dev->close = matrix_keypad_stop;
input_dev->keycode = keycodes;
input_dev->keycodesize = sizeof(*keycodes);
input_dev->keycodemax = keymap_data->max_keymap_size;
for (i = 0; i < keymap_data->keymap_size; i++) {
unsigned int key = keymap_data->keymap[i];
unsigned int row = KEY_ROW(key);
unsigned int col = KEY_COL(key);
unsigned short code = KEY_VAL(key);
keycodes[(row << 4) + col] = code;
__set_bit(code, input_dev->keybit);
}
__clear_bit(KEY_RESERVED, input_dev->keybit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, keypad);
err = init_matrix_gpio(pdev, keypad);
if (err)
goto err_free_mem;
err = input_register_device(keypad->input_dev);
if (err)
goto err_free_mem;
device_init_wakeup(&pdev->dev, pdata->wakeup);
platform_set_drvdata(pdev, keypad);
return 0;
err_free_mem:
input_free_device(input_dev);
kfree(keycodes);
kfree(keypad);
return err;
}
static int __devexit matrix_keypad_remove(struct platform_device *pdev)
{
struct matrix_keypad *keypad = platform_get_drvdata(pdev);
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
int i;
device_init_wakeup(&pdev->dev, 0);
for (i = 0; i < pdata->num_row_gpios; i++) {
free_irq(gpio_to_irq(pdata->row_gpios[i]), keypad);
gpio_free(pdata->row_gpios[i]);
}
for (i = 0; i < pdata->num_col_gpios; i++)
gpio_free(pdata->col_gpios[i]);
input_unregister_device(keypad->input_dev);
platform_set_drvdata(pdev, NULL);
kfree(keypad->keycodes);
kfree(keypad);
return 0;
}
static struct platform_driver matrix_keypad_driver = {
.probe = matrix_keypad_probe,
.remove = __devexit_p(matrix_keypad_remove),
.suspend = matrix_keypad_suspend,
.resume = matrix_keypad_resume,
.driver = {
.name = "matrix-keypad",
.owner = THIS_MODULE,
},
};
static int __init matrix_keypad_init(void)
{
return platform_driver_register(&matrix_keypad_driver);
}
static void __exit matrix_keypad_exit(void)
{
platform_driver_unregister(&matrix_keypad_driver);
}
module_init(matrix_keypad_init);
module_exit(matrix_keypad_exit);
MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
MODULE_DESCRIPTION("GPIO Driven Matrix Keypad Driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:matrix-keypad");
...@@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev) ...@@ -46,7 +46,7 @@ static void gpio_mouse_scan(struct input_polled_dev *dev)
input_sync(input); input_sync(input);
} }
static int __init gpio_mouse_probe(struct platform_device *pdev) static int __devinit gpio_mouse_probe(struct platform_device *pdev)
{ {
struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data; struct gpio_mouse_platform_data *pdata = pdev->dev.platform_data;
struct input_polled_dev *input_poll; struct input_polled_dev *input_poll;
...@@ -170,10 +170,8 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev) ...@@ -170,10 +170,8 @@ static int __devexit gpio_mouse_remove(struct platform_device *pdev)
return 0; return 0;
} }
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:gpio_mouse");
static struct platform_driver gpio_mouse_device_driver = { static struct platform_driver gpio_mouse_device_driver = {
.probe = gpio_mouse_probe,
.remove = __devexit_p(gpio_mouse_remove), .remove = __devexit_p(gpio_mouse_remove),
.driver = { .driver = {
.name = "gpio_mouse", .name = "gpio_mouse",
...@@ -183,8 +181,7 @@ static struct platform_driver gpio_mouse_device_driver = { ...@@ -183,8 +181,7 @@ static struct platform_driver gpio_mouse_device_driver = {
static int __init gpio_mouse_init(void) static int __init gpio_mouse_init(void)
{ {
return platform_driver_probe(&gpio_mouse_device_driver, return platform_driver_register(&gpio_mouse_device_driver);
gpio_mouse_probe);
} }
module_init(gpio_mouse_init); module_init(gpio_mouse_init);
...@@ -197,3 +194,5 @@ module_exit(gpio_mouse_exit); ...@@ -197,3 +194,5 @@ module_exit(gpio_mouse_exit);
MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>"); MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
MODULE_DESCRIPTION("GPIO mouse driver"); MODULE_DESCRIPTION("GPIO mouse driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio_mouse"); /* work with hotplug and coldplug */
...@@ -392,6 +392,34 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { ...@@ -392,6 +392,34 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = {
DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."),
}, },
}, },
{
.ident = "Acer Aspire One 150",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"),
},
},
{
.ident = "Advent 4211",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"),
DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"),
},
},
{
.ident = "Medion Akoya Mini E1210",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MEDION"),
DMI_MATCH(DMI_PRODUCT_NAME, "E1210"),
},
},
{
.ident = "Mivvy M310",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"),
DMI_MATCH(DMI_PRODUCT_NAME, "N10"),
},
},
{ } { }
}; };
......
...@@ -934,10 +934,11 @@ static bool i8042_suspended; ...@@ -934,10 +934,11 @@ static bool i8042_suspended;
static int i8042_suspend(struct platform_device *dev, pm_message_t state) static int i8042_suspend(struct platform_device *dev, pm_message_t state)
{ {
if (!i8042_suspended && state.event == PM_EVENT_SUSPEND) { if (!i8042_suspended && state.event == PM_EVENT_SUSPEND)
i8042_controller_reset(); i8042_controller_reset();
i8042_suspended = true;
} i8042_suspended = state.event == PM_EVENT_SUSPEND ||
state.event == PM_EVENT_FREEZE;
return 0; return 0;
} }
......
...@@ -935,10 +935,11 @@ static int serio_suspend(struct device *dev, pm_message_t state) ...@@ -935,10 +935,11 @@ static int serio_suspend(struct device *dev, pm_message_t state)
{ {
struct serio *serio = to_serio_port(dev); struct serio *serio = to_serio_port(dev);
if (!serio->suspended && state.event == PM_EVENT_SUSPEND) { if (!serio->suspended && state.event == PM_EVENT_SUSPEND)
serio_cleanup(serio); serio_cleanup(serio);
serio->suspended = true;
} serio->suspended = state.event == PM_EVENT_SUSPEND ||
state.event == PM_EVENT_FREEZE;
return 0; return 0;
} }
......
...@@ -384,6 +384,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) ...@@ -384,6 +384,8 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
wacom_report_key(wcombo, BTN_STYLUS2, 0); wacom_report_key(wcombo, BTN_STYLUS2, 0);
wacom_report_key(wcombo, BTN_TOUCH, 0); wacom_report_key(wcombo, BTN_TOUCH, 0);
wacom_report_abs(wcombo, ABS_WHEEL, 0); wacom_report_abs(wcombo, ABS_WHEEL, 0);
if (wacom->features->type >= INTUOS3S)
wacom_report_abs(wcombo, ABS_Z, 0);
} }
wacom_report_key(wcombo, wacom->tool[idx], 0); wacom_report_key(wcombo, wacom->tool[idx], 0);
wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
...@@ -836,6 +838,7 @@ static struct wacom_features wacom_features[] = { ...@@ -836,6 +838,7 @@ static struct wacom_features wacom_features[] = {
{ "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL },
{ "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL },
{ "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL },
{ "Wacom DTF720a", 8, 6858, 5506, 511, 0, PL },
{ "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU },
{ "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS },
{ "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS },
...@@ -897,8 +900,9 @@ static struct usb_device_id wacom_ids[] = { ...@@ -897,8 +900,9 @@ static struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
......
...@@ -32,8 +32,7 @@ ...@@ -32,8 +32,7 @@
* This driver was tested with firmware revision A4. * This driver was tested with firmware revision A4.
*/ */
#if defined(CONFIG_KEYBOARD_DM355EVM) \ #if defined(CONFIG_INPUT_DM355EVM) || defined(CONFIG_INPUT_DM355EVM_MODULE)
|| defined(CONFIG_KEYBOARD_DM355EVM_MODULE)
#define msp_has_keyboard() true #define msp_has_keyboard() true
#else #else
#define msp_has_keyboard() false #define msp_has_keyboard() false
......
#ifndef _MATRIX_KEYPAD_H
#define _MATRIX_KEYPAD_H
#include <linux/types.h>
#include <linux/input.h>
#define MATRIX_MAX_ROWS 16
#define MATRIX_MAX_COLS 16
#define KEY(row, col, val) ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\
(((col) & (MATRIX_MAX_COLS - 1)) << 16) |\
(val & 0xffff))
#define KEY_ROW(k) (((k) >> 24) & 0xff)
#define KEY_COL(k) (((k) >> 16) & 0xff)
#define KEY_VAL(k) ((k) & 0xffff)
/**
* struct matrix_keymap_data - keymap for matrix keyboards
* @keymap: pointer to array of uint32 values encoded with KEY() macro
* representing keymap
* @keymap_size: number of entries (initialized) in this keymap
* @max_keymap_size: maximum size of keymap supported by the device
*
* This structure is supposed to be used by platform code to supply
* keymaps to drivers that implement matrix-like keypads/keyboards.
*/
struct matrix_keymap_data {
const uint32_t *keymap;
unsigned int keymap_size;
unsigned int max_keymap_size;
};
/**
* struct matrix_keypad_platform_data - platform-dependent keypad data
* @keymap_data: pointer to &matrix_keymap_data
* @row_gpios: array of gpio numbers reporesenting rows
* @col_gpios: array of gpio numbers reporesenting colums
* @num_row_gpios: actual number of row gpios used by device
* @num_col_gpios: actual number of col gpios used by device
* @col_scan_delay_us: delay, measured in microseconds, that is
* needed before we can keypad after activating column gpio
* @debounce_ms: debounce interval in milliseconds
*
* This structure represents platform-specific data that use used by
* matrix_keypad driver to perform proper initialization.
*/
struct matrix_keypad_platform_data {
const struct matrix_keymap_data *keymap_data;
unsigned int row_gpios[MATRIX_MAX_ROWS];
unsigned int col_gpios[MATRIX_MAX_COLS];
unsigned int num_row_gpios;
unsigned int num_col_gpios;
unsigned int col_scan_delay_us;
/* key debounce interval in milli-second */
unsigned int debounce_ms;
bool active_low;
bool wakeup;
};
#endif /* _MATRIX_KEYPAD_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment