From a0640925880a5801ae0aac232fae6900a2c44b27 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Mon, 17 Jan 2011 20:40:32 -0800 Subject: Input: tnetv107x-keypad - don't treat NULL clk as an error We should use IS_ERR() when checking whether clk_get() succeeded or not since it returns errors by encoding error codes with ERR_PTR(). Signed-off-by: Jamie Iles Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tnetv107x-keypad.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/tnetv107x-keypad.c b/drivers/input/keyboard/tnetv107x-keypad.c index b4a81ebfab9..c8f097a15d8 100644 --- a/drivers/input/keyboard/tnetv107x-keypad.c +++ b/drivers/input/keyboard/tnetv107x-keypad.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -219,9 +220,9 @@ static int __devinit keypad_probe(struct platform_device *pdev) } kp->clk = clk_get(dev, NULL); - if (!kp->clk) { + if (IS_ERR(kp->clk)) { dev_err(dev, "cannot claim device clock\n"); - error = -EINVAL; + error = PTR_ERR(kp->clk); goto error_clk; } -- cgit v1.2.3-70-g09d2 From ba555461833aa1b5083004492ba97c92d5fccf46 Mon Sep 17 00:00:00 2001 From: Jamie Iles Date: Mon, 17 Jan 2011 20:40:55 -0800 Subject: Input: tnetv107x-ts - don't treat NULL clk as an error We should use IS_ERR() when checking whether clk_get() succeeded or not since it returns errors by encoding error codes with ERR_PTR(). Signed-off-by: Jamie Iles Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/tnetv107x-ts.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/tnetv107x-ts.c b/drivers/input/touchscreen/tnetv107x-ts.c index cf1dba2e267..22a3411e93c 100644 --- a/drivers/input/touchscreen/tnetv107x-ts.c +++ b/drivers/input/touchscreen/tnetv107x-ts.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -289,9 +290,9 @@ static int __devinit tsc_probe(struct platform_device *pdev) } ts->clk = clk_get(dev, NULL); - if (!ts->clk) { + if (IS_ERR(ts->clk)) { dev_err(dev, "cannot claim device clock\n"); - error = -EINVAL; + error = PTR_ERR(ts->clk); goto error_clk; } -- cgit v1.2.3-70-g09d2 From d2763b4f44e16f44cc4156c9591e74df9dcd88be Mon Sep 17 00:00:00 2001 From: Naveen Kumar Gaddipati Date: Mon, 17 Jan 2011 20:40:58 -0800 Subject: Input: bu21013_ts - remove duplicate resolution parameters Remove duplicate display resolution parameters from platform data as one pair is quite enough. Signed-off-by: Naveen Kumar Gaddipati Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 4 ++-- include/linux/input/bu21013.h | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index f7fa9ef4cd6..3c7e60b2f77 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -485,9 +485,9 @@ static int __devinit bu21013_probe(struct i2c_client *client, __set_bit(EV_ABS, in_dev->evbit); input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0, - pdata->x_max_res, 0, 0); + pdata->touch_x_max, 0, 0); input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0, - pdata->y_max_res, 0, 0); + pdata->touch_y_max, 0, 0); input_set_drvdata(in_dev, bu21013_data); error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq, diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h index e470d387dd4..05e03284b92 100644 --- a/include/linux/input/bu21013.h +++ b/include/linux/input/bu21013.h @@ -12,8 +12,6 @@ * @cs_en: pointer to the cs enable function * @cs_dis: pointer to the cs disable function * @irq_read_val: pointer to read the pen irq value function - * @x_max_res: xmax resolution - * @y_max_res: ymax resolution * @touch_x_max: touch x max * @touch_y_max: touch y max * @cs_pin: chip select pin @@ -29,8 +27,6 @@ struct bu21013_platform_device { int (*cs_en)(int reset_pin); int (*cs_dis)(int reset_pin); int (*irq_read_val)(void); - int x_max_res; - int y_max_res; int touch_x_max; int touch_y_max; unsigned int cs_pin; -- cgit v1.2.3-70-g09d2 From 81e78deafb21ba867eb244ab1117726c68d817f8 Mon Sep 17 00:00:00 2001 From: Naveen Kumar Gaddipati Date: Mon, 17 Jan 2011 20:47:31 -0800 Subject: Input: bu21013_ts - added regulator support Add regulator support in ROHM BU21013 touch panel driver. Signed-off-by: Naveen Kumar Gaddipati Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/bu21013_ts.c | 35 +++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c index 3c7e60b2f77..1507ce108d5 100644 --- a/drivers/input/touchscreen/bu21013_ts.c +++ b/drivers/input/touchscreen/bu21013_ts.c @@ -12,6 +12,7 @@ #include #include #include +#include #define PEN_DOWN_INTR 0 #define MAX_FINGERS 2 @@ -139,6 +140,7 @@ * @chip: pointer to the touch panel controller * @in_dev: pointer to the input device structure * @intr_pin: interrupt pin value + * @regulator: pointer to the Regulator used for touch screen * * Touch panel device data structure */ @@ -149,6 +151,7 @@ struct bu21013_ts_data { const struct bu21013_platform_device *chip; struct input_dev *in_dev; unsigned int intr_pin; + struct regulator *regulator; }; /** @@ -456,6 +459,20 @@ static int __devinit bu21013_probe(struct i2c_client *client, bu21013_data->in_dev = in_dev; bu21013_data->chip = pdata; bu21013_data->client = client; + + bu21013_data->regulator = regulator_get(&client->dev, "V-TOUCH"); + if (IS_ERR(bu21013_data->regulator)) { + dev_err(&client->dev, "regulator_get failed\n"); + error = PTR_ERR(bu21013_data->regulator); + goto err_free_mem; + } + + error = regulator_enable(bu21013_data->regulator); + if (error < 0) { + dev_err(&client->dev, "regulator enable failed\n"); + goto err_put_regulator; + } + bu21013_data->touch_stopped = false; init_waitqueue_head(&bu21013_data->wait); @@ -464,7 +481,7 @@ static int __devinit bu21013_probe(struct i2c_client *client, error = pdata->cs_en(pdata->cs_pin); if (error < 0) { dev_err(&client->dev, "chip init failed\n"); - goto err_free_mem; + goto err_disable_regulator; } } @@ -513,6 +530,10 @@ err_free_irq: bu21013_free_irq(bu21013_data); err_cs_disable: pdata->cs_dis(pdata->cs_pin); +err_disable_regulator: + regulator_disable(bu21013_data->regulator); +err_put_regulator: + regulator_put(bu21013_data->regulator); err_free_mem: input_free_device(in_dev); kfree(bu21013_data); @@ -535,6 +556,10 @@ static int __devexit bu21013_remove(struct i2c_client *client) bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin); input_unregister_device(bu21013_data->in_dev); + + regulator_disable(bu21013_data->regulator); + regulator_put(bu21013_data->regulator); + kfree(bu21013_data); device_init_wakeup(&client->dev, false); @@ -561,6 +586,8 @@ static int bu21013_suspend(struct device *dev) else disable_irq(bu21013_data->chip->irq); + regulator_disable(bu21013_data->regulator); + return 0; } @@ -577,6 +604,12 @@ static int bu21013_resume(struct device *dev) struct i2c_client *client = bu21013_data->client; int retval; + retval = regulator_enable(bu21013_data->regulator); + if (retval < 0) { + dev_err(&client->dev, "bu21013 regulator enable failed\n"); + return retval; + } + retval = bu21013_init_chip(bu21013_data); if (retval < 0) { dev_err(&client->dev, "bu21013 controller config failed\n"); -- cgit v1.2.3-70-g09d2 From b0f05aadf1516c166ba301b7a535bc9429ce1961 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Mon, 17 Jan 2011 20:48:18 -0800 Subject: Input: ct82710c - return proper error code for ct82c710_open If request_irq() fails we should return the proper error instead of -1. Signed-off-by: Davidlohr Bueso Signed-off-by: Dmitry Torokhov --- drivers/input/serio/ct82c710.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index 448c7724beb..85281656724 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c @@ -111,9 +111,11 @@ static void ct82c710_close(struct serio *serio) static int ct82c710_open(struct serio *serio) { unsigned char status; + int err; - if (request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL)) - return -1; + err = request_irq(CT82C710_IRQ, ct82c710_interrupt, 0, "ct82c710", NULL); + if (err) + return err; status = inb_p(CT82C710_STATUS); @@ -131,7 +133,7 @@ static int ct82c710_open(struct serio *serio) status &= ~(CT82C710_ENABLE | CT82C710_INTS_ON); outb_p(status, CT82C710_STATUS); free_irq(CT82C710_IRQ, NULL); - return -1; + return -EBUSY; } return 0; -- cgit v1.2.3-70-g09d2 From 48c27016e18f8608c12b7516515ad773093198d8 Mon Sep 17 00:00:00 2001 From: David Engraf Date: Thu, 20 Jan 2011 23:05:17 -0800 Subject: Input: serio - allow registered drivers to get status flag Parse and pass the status byte information to the registered serio drivers as well as the data bytes. Signed-off-by: David Engraf Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serport.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 6e362de3f41..8755f5f3ad3 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -116,14 +116,15 @@ static void serport_ldisc_close(struct tty_struct *tty) /* * serport_ldisc_receive() is called by the low level tty driver when characters - * are ready for us. We forward the characters, one by one to the 'interrupt' - * routine. + * are ready for us. We forward the characters and flags, one by one to the + * 'interrupt' routine. */ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) { struct serport *serport = (struct serport*) tty->disc_data; unsigned long flags; + unsigned int ch_flags; int i; spin_lock_irqsave(&serport->lock, flags); @@ -131,8 +132,23 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c if (!test_bit(SERPORT_ACTIVE, &serport->flags)) goto out; - for (i = 0; i < count; i++) - serio_interrupt(serport->serio, cp[i], 0); + for (i = 0; i < count; i++) { + switch (fp[i]) { + case TTY_FRAME: + ch_flags = SERIO_FRAME; + break; + + case TTY_PARITY: + ch_flags = SERIO_PARITY; + break; + + default: + ch_flags = 0; + break; + } + + serio_interrupt(serport->serio, cp[i], ch_flags); + } out: spin_unlock_irqrestore(&serport->lock, flags); -- cgit v1.2.3-70-g09d2 From 94a8cab8caaa56824981c17b6898b73627e8382f Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 20 Jan 2011 23:09:30 -0800 Subject: Input: gpio_keys - switch to using request_any_context_irq The driver does not require hardirq context and can work with threaded interrupts as well, so let's switch to request_any_context_irq which will select the context that is available for us. Signed-off-by: Philippe Langlais Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 6069abe31e4..eb3006361ee 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -322,7 +322,7 @@ static void gpio_keys_report_event(struct gpio_button_data *bdata) struct gpio_keys_button *button = bdata->button; struct input_dev *input = bdata->input; unsigned int type = button->type ?: EV_KEY; - int state = (gpio_get_value(button->gpio) ? 1 : 0) ^ button->active_low; + int state = (gpio_get_value_cansleep(button->gpio) ? 1 : 0) ^ button->active_low; input_event(input, type, button->code, !!state); input_sync(input); @@ -410,8 +410,8 @@ static int __devinit gpio_keys_setup_key(struct platform_device *pdev, if (!button->can_disable) irqflags |= IRQF_SHARED; - error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata); - if (error) { + error = request_any_context_irq(irq, gpio_keys_isr, irqflags, desc, bdata); + if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", irq, error); goto fail3; -- cgit v1.2.3-70-g09d2 From 11f5b30dacdd77bee1028764d91ad58b6c73d50c Mon Sep 17 00:00:00 2001 From: Rakesh Iyer Date: Wed, 19 Jan 2011 23:38:47 -0800 Subject: Input: tegra-kbc - add tegra keyboard driver This patch adds support for the internal matrix keyboard controller for Nvidia Tegra platforms. Signed-off-by: Rakesh Iyer Reviewed-by: Trilok Soni Signed-off-by: Dmitry Torokhov --- arch/arm/mach-tegra/include/mach/kbc.h | 61 +++ drivers/input/keyboard/Kconfig | 10 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tegra-kbc.c | 727 +++++++++++++++++++++++++++++++++ 4 files changed, 799 insertions(+) create mode 100644 arch/arm/mach-tegra/include/mach/kbc.h create mode 100644 drivers/input/keyboard/tegra-kbc.c (limited to 'drivers/input') diff --git a/arch/arm/mach-tegra/include/mach/kbc.h b/arch/arm/mach-tegra/include/mach/kbc.h new file mode 100644 index 00000000000..66ad2760c62 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/kbc.h @@ -0,0 +1,61 @@ +/* + * Platform definitions for tegra-kbc keyboard input driver + * + * Copyright (c) 2010-2011, 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. + */ + +#ifndef ASMARM_ARCH_TEGRA_KBC_H +#define ASMARM_ARCH_TEGRA_KBC_H + +#include +#include + +#ifdef CONFIG_ARCH_TEGRA_2x_SOC +#define KBC_MAX_GPIO 24 +#define KBC_MAX_KPENT 8 +#else +#define KBC_MAX_GPIO 20 +#define KBC_MAX_KPENT 7 +#endif + +#define KBC_MAX_ROW 16 +#define KBC_MAX_COL 8 +#define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL) + +struct tegra_kbc_pin_cfg { + bool is_row; + unsigned char num; +}; + +struct tegra_kbc_wake_key { + u8 row:4; + u8 col:4; +}; + +struct tegra_kbc_platform_data { + unsigned int debounce_cnt; + unsigned int repeat_cnt; + + unsigned int wake_cnt; /* 0:wake on any key >1:wake on wake_cfg */ + const struct tegra_kbc_wake_key *wake_cfg; + + struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO]; + const struct matrix_keymap_data *keymap_data; + + bool wakeup; +}; +#endif diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 89bd912489e..b7dca74eb9b 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -343,6 +343,16 @@ config KEYBOARD_NOMADIK To compile this driver as a module, choose M here: the module will be called nmk-ske-keypad. +config KEYBOARD_TEGRA + tristate "NVIDIA Tegra internal matrix keyboard controller support" + depends on ARCH_TEGRA + help + Say Y here if you want to use a matrix keyboard connected directly + to the internal keyboard controller on Tegra SoCs. + + To compile this driver as a module, choose M here: the + module will be called tegra-kbc. + config KEYBOARD_OPENCORES tristate "OpenCores Keyboard Controller" help diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 4dd15cf3f78..3456b931e25 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_KEYBOARD_SPEAR) += spear-keyboard.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o +obj-$(CONFIG_KEYBOARD_TEGRA) += tegra-kbc.o obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c new file mode 100644 index 00000000000..939476659ad --- /dev/null +++ b/drivers/input/keyboard/tegra-kbc.c @@ -0,0 +1,727 @@ +/* + * Keyboard class input driver for the NVIDIA Tegra SoC internal matrix + * keyboard controller + * + * Copyright (c) 2009-2011, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KBC_MAX_DEBOUNCE_CNT 0x3ffu + +/* KBC row scan time and delay for beginning the row scan. */ +#define KBC_ROW_SCAN_TIME 16 +#define KBC_ROW_SCAN_DLY 5 + +/* KBC uses a 32KHz clock so a cycle = 1/32Khz */ +#define KBC_CYCLE_USEC 32 + +/* KBC Registers */ + +/* KBC Control Register */ +#define KBC_CONTROL_0 0x0 +#define KBC_FIFO_TH_CNT_SHIFT(cnt) (cnt << 14) +#define KBC_DEBOUNCE_CNT_SHIFT(cnt) (cnt << 4) +#define KBC_CONTROL_FIFO_CNT_INT_EN (1 << 3) +#define KBC_CONTROL_KBC_EN (1 << 0) + +/* KBC Interrupt Register */ +#define KBC_INT_0 0x4 +#define KBC_INT_FIFO_CNT_INT_STATUS (1 << 2) + +#define KBC_ROW_CFG0_0 0x8 +#define KBC_COL_CFG0_0 0x18 +#define KBC_INIT_DLY_0 0x28 +#define KBC_RPT_DLY_0 0x2c +#define KBC_KP_ENT0_0 0x30 +#define KBC_KP_ENT1_0 0x34 +#define KBC_ROW0_MASK_0 0x38 + +#define KBC_ROW_SHIFT 3 + +struct tegra_kbc { + void __iomem *mmio; + struct input_dev *idev; + unsigned int irq; + unsigned int wake_enable_rows; + unsigned int wake_enable_cols; + spinlock_t lock; + unsigned int repoll_dly; + unsigned long cp_dly_jiffies; + const struct tegra_kbc_platform_data *pdata; + unsigned short keycode[KBC_MAX_KEY]; + unsigned short current_keys[KBC_MAX_KPENT]; + unsigned int num_pressed_keys; + struct timer_list timer; + struct clk *clk; +}; + +static const u32 tegra_kbc_default_keymap[] = { + KEY(0, 2, KEY_W), + KEY(0, 3, KEY_S), + KEY(0, 4, KEY_A), + KEY(0, 5, KEY_Z), + KEY(0, 7, KEY_FN), + + KEY(1, 7, KEY_MENU), + + KEY(2, 6, KEY_RIGHTALT), + KEY(2, 7, KEY_LEFTALT), + + KEY(3, 0, KEY_5), + KEY(3, 1, KEY_4), + KEY(3, 2, KEY_R), + KEY(3, 3, KEY_E), + KEY(3, 4, KEY_F), + KEY(3, 5, KEY_D), + KEY(3, 6, KEY_X), + + KEY(4, 0, KEY_7), + KEY(4, 1, KEY_6), + KEY(4, 2, KEY_T), + KEY(4, 3, KEY_H), + KEY(4, 4, KEY_G), + KEY(4, 5, KEY_V), + KEY(4, 6, KEY_C), + KEY(4, 7, KEY_SPACE), + + KEY(5, 0, KEY_9), + KEY(5, 1, KEY_8), + KEY(5, 2, KEY_U), + KEY(5, 3, KEY_Y), + KEY(5, 4, KEY_J), + KEY(5, 5, KEY_N), + KEY(5, 6, KEY_B), + KEY(5, 7, KEY_BACKSLASH), + + KEY(6, 0, KEY_MINUS), + KEY(6, 1, KEY_0), + KEY(6, 2, KEY_O), + KEY(6, 3, KEY_I), + KEY(6, 4, KEY_L), + KEY(6, 5, KEY_K), + KEY(6, 6, KEY_COMMA), + KEY(6, 7, KEY_M), + + KEY(7, 1, KEY_EQUAL), + KEY(7, 2, KEY_RIGHTBRACE), + KEY(7, 3, KEY_ENTER), + KEY(7, 7, KEY_MENU), + + KEY(8, 4, KEY_RIGHTSHIFT), + KEY(8, 5, KEY_LEFTSHIFT), + + KEY(9, 5, KEY_RIGHTCTRL), + KEY(9, 7, KEY_LEFTCTRL), + + KEY(11, 0, KEY_LEFTBRACE), + KEY(11, 1, KEY_P), + KEY(11, 2, KEY_APOSTROPHE), + KEY(11, 3, KEY_SEMICOLON), + KEY(11, 4, KEY_SLASH), + KEY(11, 5, KEY_DOT), + + KEY(12, 0, KEY_F10), + KEY(12, 1, KEY_F9), + KEY(12, 2, KEY_BACKSPACE), + KEY(12, 3, KEY_3), + KEY(12, 4, KEY_2), + KEY(12, 5, KEY_UP), + KEY(12, 6, KEY_PRINT), + KEY(12, 7, KEY_PAUSE), + + KEY(13, 0, KEY_INSERT), + KEY(13, 1, KEY_DELETE), + KEY(13, 3, KEY_PAGEUP), + KEY(13, 4, KEY_PAGEDOWN), + KEY(13, 5, KEY_RIGHT), + KEY(13, 6, KEY_DOWN), + KEY(13, 7, KEY_LEFT), + + KEY(14, 0, KEY_F11), + KEY(14, 1, KEY_F12), + KEY(14, 2, KEY_F8), + KEY(14, 3, KEY_Q), + KEY(14, 4, KEY_F4), + KEY(14, 5, KEY_F3), + KEY(14, 6, KEY_1), + KEY(14, 7, KEY_F7), + + KEY(15, 0, KEY_ESC), + KEY(15, 1, KEY_GRAVE), + KEY(15, 2, KEY_F5), + KEY(15, 3, KEY_TAB), + KEY(15, 4, KEY_F1), + KEY(15, 5, KEY_F2), + KEY(15, 6, KEY_CAPSLOCK), + KEY(15, 7, KEY_F6), +}; + +static const struct matrix_keymap_data tegra_kbc_default_keymap_data = { + .keymap = tegra_kbc_default_keymap, + .keymap_size = ARRAY_SIZE(tegra_kbc_default_keymap), +}; + +static void tegra_kbc_report_released_keys(struct input_dev *input, + unsigned short old_keycodes[], + unsigned int old_num_keys, + unsigned short new_keycodes[], + unsigned int new_num_keys) +{ + unsigned int i, j; + + for (i = 0; i < old_num_keys; i++) { + for (j = 0; j < new_num_keys; j++) + if (old_keycodes[i] == new_keycodes[j]) + break; + + if (j == new_num_keys) + input_report_key(input, old_keycodes[i], 0); + } +} + +static void tegra_kbc_report_pressed_keys(struct input_dev *input, + unsigned char scancodes[], + unsigned short keycodes[], + unsigned int num_pressed_keys) +{ + unsigned int i; + + for (i = 0; i < num_pressed_keys; i++) { + input_event(input, EV_MSC, MSC_SCAN, scancodes[i]); + input_report_key(input, keycodes[i], 1); + } +} + +static void tegra_kbc_report_keys(struct tegra_kbc *kbc) +{ + unsigned char scancodes[KBC_MAX_KPENT]; + unsigned short keycodes[KBC_MAX_KPENT]; + u32 val = 0; + unsigned int i; + unsigned int num_down = 0; + unsigned long flags; + + spin_lock_irqsave(&kbc->lock, flags); + for (i = 0; i < KBC_MAX_KPENT; i++) { + if ((i % 4) == 0) + val = readl(kbc->mmio + KBC_KP_ENT0_0 + i); + + if (val & 0x80) { + unsigned int col = val & 0x07; + unsigned int row = (val >> 3) & 0x0f; + unsigned char scancode = + MATRIX_SCAN_CODE(row, col, KBC_ROW_SHIFT); + + scancodes[num_down] = scancode; + keycodes[num_down++] = kbc->keycode[scancode]; + } + + val >>= 8; + } + spin_unlock_irqrestore(&kbc->lock, flags); + + tegra_kbc_report_released_keys(kbc->idev, + kbc->current_keys, kbc->num_pressed_keys, + keycodes, num_down); + tegra_kbc_report_pressed_keys(kbc->idev, scancodes, keycodes, num_down); + input_sync(kbc->idev); + + memcpy(kbc->current_keys, keycodes, sizeof(kbc->current_keys)); + kbc->num_pressed_keys = num_down; +} + +static void tegra_kbc_keypress_timer(unsigned long data) +{ + struct tegra_kbc *kbc = (struct tegra_kbc *)data; + unsigned long flags; + u32 val; + unsigned int i; + + val = (readl(kbc->mmio + KBC_INT_0) >> 4) & 0xf; + if (val) { + unsigned long dly; + + tegra_kbc_report_keys(kbc); + + /* + * If more than one keys are pressed we need not wait + * for the repoll delay. + */ + dly = (val == 1) ? kbc->repoll_dly : 1; + mod_timer(&kbc->timer, jiffies + msecs_to_jiffies(dly)); + } else { + /* Release any pressed keys and exit the polling loop */ + for (i = 0; i < kbc->num_pressed_keys; i++) + input_report_key(kbc->idev, kbc->current_keys[i], 0); + input_sync(kbc->idev); + + kbc->num_pressed_keys = 0; + + /* All keys are released so enable the keypress interrupt */ + spin_lock_irqsave(&kbc->lock, flags); + val = readl(kbc->mmio + KBC_CONTROL_0); + val |= KBC_CONTROL_FIFO_CNT_INT_EN; + writel(val, kbc->mmio + KBC_CONTROL_0); + spin_unlock_irqrestore(&kbc->lock, flags); + } +} + +static irqreturn_t tegra_kbc_isr(int irq, void *args) +{ + struct tegra_kbc *kbc = args; + u32 val, ctl; + + /* + * Until all keys are released, defer further processing to + * the polling loop in tegra_kbc_keypress_timer + */ + ctl = readl(kbc->mmio + KBC_CONTROL_0); + ctl &= ~KBC_CONTROL_FIFO_CNT_INT_EN; + writel(ctl, kbc->mmio + KBC_CONTROL_0); + + /* + * Quickly bail out & reenable interrupts if the fifo threshold + * count interrupt wasn't the interrupt source + */ + val = readl(kbc->mmio + KBC_INT_0); + writel(val, kbc->mmio + KBC_INT_0); + + if (val & KBC_INT_FIFO_CNT_INT_STATUS) { + /* + * Schedule timer to run when hardware is in continuous + * polling mode. + */ + mod_timer(&kbc->timer, jiffies + kbc->cp_dly_jiffies); + } else { + ctl |= KBC_CONTROL_FIFO_CNT_INT_EN; + writel(ctl, kbc->mmio + KBC_CONTROL_0); + } + + return IRQ_HANDLED; +} + +static void tegra_kbc_setup_wakekeys(struct tegra_kbc *kbc, bool filter) +{ + const struct tegra_kbc_platform_data *pdata = kbc->pdata; + int i; + unsigned int rst_val; + + BUG_ON(pdata->wake_cnt > KBC_MAX_KEY); + rst_val = (filter && pdata->wake_cnt) ? ~0 : 0; + + for (i = 0; i < KBC_MAX_ROW; i++) + writel(rst_val, kbc->mmio + KBC_ROW0_MASK_0 + i * 4); + + if (filter) { + for (i = 0; i < pdata->wake_cnt; i++) { + u32 val, addr; + addr = pdata->wake_cfg[i].row * 4 + KBC_ROW0_MASK_0; + val = readl(kbc->mmio + addr); + val &= ~(1 << pdata->wake_cfg[i].col); + writel(val, kbc->mmio + addr); + } + } +} + +static void tegra_kbc_config_pins(struct tegra_kbc *kbc) +{ + const struct tegra_kbc_platform_data *pdata = kbc->pdata; + int i; + + for (i = 0; i < KBC_MAX_GPIO; i++) { + u32 r_shft = 5 * (i % 6); + u32 c_shft = 4 * (i % 8); + u32 r_mask = 0x1f << r_shift; + u32 c_mask = 0x0f << c_shift; + u32 r_offs = (i / 6) * 4 + KBC_ROW_CFG0_0; + u32 c_offs = (i / 8) * 4 + KBC_COL_CFG0_0; + u32 row_cfg = readl(kbc->mmio + r_offs); + u32 col_cfg = readl(kbc->mmio + c_offs); + + row_cfg &= ~r_mask; + col_cfg &= ~c_mask; + + if (pdata->pin_cfg[i].is_row) + row_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << r_shft; + else + col_cfg |= ((pdata->pin_cfg[i].num << 1) | 1) << c_shft; + + writel(row_cfg, kbc->mmio + r_offs); + writel(col_cfg, kbc->mmio + c_offs); + } +} + +static int tegra_kbc_start(struct tegra_kbc *kbc) +{ + const struct tegra_kbc_platform_data *pdata = kbc->pdata; + unsigned long flags; + unsigned int debounce_cnt; + u32 val = 0; + + clk_enable(kbc->clk); + + /* Reset the KBC controller to clear all previous status.*/ + tegra_periph_reset_assert(kbc->clk); + udelay(100); + tegra_periph_reset_deassert(kbc->clk); + udelay(100); + + tegra_kbc_config_pins(kbc); + tegra_kbc_setup_wakekeys(kbc, false); + + writel(pdata->repeat_cnt, kbc->mmio + KBC_RPT_DLY_0); + + /* Keyboard debounce count is maximum of 12 bits. */ + debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); + val = KBC_DEBOUNCE_CNT_SHIFT(debounce_cnt); + val |= KBC_FIFO_TH_CNT_SHIFT(1); /* set fifo interrupt threshold to 1 */ + val |= KBC_CONTROL_FIFO_CNT_INT_EN; /* interrupt on FIFO threshold */ + val |= KBC_CONTROL_KBC_EN; /* enable */ + writel(val, kbc->mmio + KBC_CONTROL_0); + + /* + * Compute the delay(ns) from interrupt mode to continuous polling + * mode so the timer routine is scheduled appropriately. + */ + val = readl(kbc->mmio + KBC_INIT_DLY_0); + kbc->cp_dly_jiffies = usecs_to_jiffies((val & 0xfffff) * 32); + + kbc->num_pressed_keys = 0; + + /* + * Atomically clear out any remaining entries in the key FIFO + * and enable keyboard interrupts. + */ + spin_lock_irqsave(&kbc->lock, flags); + while (1) { + val = readl(kbc->mmio + KBC_INT_0); + val >>= 4; + if (!val) + break; + + val = readl(kbc->mmio + KBC_KP_ENT0_0); + val = readl(kbc->mmio + KBC_KP_ENT1_0); + } + writel(0x7, kbc->mmio + KBC_INT_0); + spin_unlock_irqrestore(&kbc->lock, flags); + + enable_irq(kbc->irq); + + return 0; +} + +static void tegra_kbc_stop(struct tegra_kbc *kbc) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(&kbc->lock, flags); + val = readl(kbc->mmio + KBC_CONTROL_0); + val &= ~1; + writel(val, kbc->mmio + KBC_CONTROL_0); + spin_unlock_irqrestore(&kbc->lock, flags); + + disable_irq(kbc->irq); + del_timer_sync(&kbc->timer); + + clk_disable(kbc->clk); +} + +static int tegra_kbc_open(struct input_dev *dev) +{ + struct tegra_kbc *kbc = input_get_drvdata(dev); + + return tegra_kbc_start(kbc); +} + +static void tegra_kbc_close(struct input_dev *dev) +{ + struct tegra_kbc *kbc = input_get_drvdata(dev); + + return tegra_kbc_stop(kbc); +} + +static bool __devinit +tegra_kbc_check_pin_cfg(const struct tegra_kbc_platform_data *pdata, + struct device *dev, unsigned int *num_rows) +{ + int i; + + *num_rows = 0; + + for (i = 0; i < KBC_MAX_GPIO; i++) { + const struct tegra_kbc_pin_cfg *pin_cfg = &pdata->pin_cfg[i]; + + if (pin_cfg->is_row) { + if (pin_cfg->num >= KBC_MAX_ROW) { + dev_err(dev, + "pin_cfg[%d]: invalid row number %d\n", + i, pin_cfg->num); + return false; + } + (*num_rows)++; + } else { + if (pin_cfg->num >= KBC_MAX_COL) { + dev_err(dev, + "pin_cfg[%d]: invalid column number %d\n", + i, pin_cfg->num); + return false; + } + } + } + + return true; +} + +static int __devinit tegra_kbc_probe(struct platform_device *pdev) +{ + const struct tegra_kbc_platform_data *pdata = pdev->dev.platform_data; + const struct matrix_keymap_data *keymap_data; + struct tegra_kbc *kbc; + struct input_dev *input_dev; + struct resource *res; + int irq; + int err; + int i; + int num_rows = 0; + unsigned int debounce_cnt; + unsigned int scan_time_rows; + + if (!pdata) + return -EINVAL; + + if (!tegra_kbc_check_pin_cfg(pdata, &pdev->dev, &num_rows)) + return -EINVAL; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to get I/O memory\n"); + return -ENXIO; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "failed to get keyboard IRQ\n"); + return -ENXIO; + } + + kbc = kzalloc(sizeof(*kbc), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!kbc || !input_dev) { + err = -ENOMEM; + goto err_free_mem; + } + + kbc->pdata = pdata; + kbc->idev = input_dev; + kbc->irq = irq; + spin_lock_init(&kbc->lock); + setup_timer(&kbc->timer, tegra_kbc_keypress_timer, (unsigned long)kbc); + + res = request_mem_region(res->start, resource_size(res), pdev->name); + if (!res) { + dev_err(&pdev->dev, "failed to request I/O memory\n"); + err = -EBUSY; + goto err_free_mem; + } + + kbc->mmio = ioremap(res->start, resource_size(res)); + if (!kbc->mmio) { + dev_err(&pdev->dev, "failed to remap I/O memory\n"); + err = -ENXIO; + goto err_free_mem_region; + } + + kbc->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(kbc->clk)) { + dev_err(&pdev->dev, "failed to get keyboard clock\n"); + err = PTR_ERR(kbc->clk); + goto err_iounmap; + } + + kbc->wake_enable_rows = 0; + kbc->wake_enable_cols = 0; + for (i = 0; i < pdata->wake_cnt; i++) { + kbc->wake_enable_rows |= (1 << pdata->wake_cfg[i].row); + kbc->wake_enable_cols |= (1 << pdata->wake_cfg[i].col); + } + + /* + * The time delay between two consecutive reads of the FIFO is + * the sum of the repeat time and the time taken for scanning + * the rows. There is an additional delay before the row scanning + * starts. The repoll delay is computed in milliseconds. + */ + debounce_cnt = min(pdata->debounce_cnt, KBC_MAX_DEBOUNCE_CNT); + scan_time_rows = (KBC_ROW_SCAN_TIME + debounce_cnt) * num_rows; + kbc->repoll_dly = KBC_ROW_SCAN_DLY + scan_time_rows + pdata->repeat_cnt; + kbc->repoll_dly = ((kbc->repoll_dly * KBC_CYCLE_USEC) + 999) / 1000; + + input_dev->name = pdev->name; + input_dev->id.bustype = BUS_HOST; + input_dev->dev.parent = &pdev->dev; + input_dev->open = tegra_kbc_open; + input_dev->close = tegra_kbc_close; + + input_set_drvdata(input_dev, kbc); + + input_dev->evbit[0] = BIT_MASK(EV_KEY); + input_set_capability(input_dev, EV_MSC, MSC_SCAN); + + input_dev->keycode = kbc->keycode; + input_dev->keycodesize = sizeof(kbc->keycode[0]); + input_dev->keycodemax = ARRAY_SIZE(kbc->keycode); + + keymap_data = pdata->keymap_data ?: &tegra_kbc_default_keymap_data; + matrix_keypad_build_keymap(keymap_data, KBC_ROW_SHIFT, + input_dev->keycode, input_dev->keybit); + + err = request_irq(kbc->irq, tegra_kbc_isr, IRQF_TRIGGER_HIGH, + pdev->name, kbc); + if (err) { + dev_err(&pdev->dev, "failed to request keyboard IRQ\n"); + goto err_put_clk; + } + + disable_irq(kbc->irq); + + err = input_register_device(kbc->idev); + if (err) { + dev_err(&pdev->dev, "failed to register input device\n"); + goto err_free_irq; + } + + platform_set_drvdata(pdev, kbc); + device_init_wakeup(&pdev->dev, pdata->wakeup); + + return 0; + +err_free_irq: + free_irq(kbc->irq, pdev); +err_put_clk: + clk_put(kbc->clk); +err_iounmap: + iounmap(kbc->mmio); +err_free_mem_region: + release_mem_region(res->start, resource_size(res)); +err_free_mem: + input_free_device(kbc->idev); + kfree(kbc); + + return err; +} + +static int __devexit tegra_kbc_remove(struct platform_device *pdev) +{ + struct tegra_kbc *kbc = platform_get_drvdata(pdev); + struct resource *res; + + free_irq(kbc->irq, pdev); + clk_put(kbc->clk); + + input_unregister_device(kbc->idev); + iounmap(kbc->mmio); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + + kfree(kbc); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int tegra_kbc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct tegra_kbc *kbc = platform_get_drvdata(pdev); + + if (device_may_wakeup(&pdev->dev)) { + tegra_kbc_setup_wakekeys(kbc, true); + enable_irq_wake(kbc->irq); + /* Forcefully clear the interrupt status */ + writel(0x7, kbc->mmio + KBC_INT_0); + msleep(30); + } else { + mutex_lock(&kbc->idev->mutex); + if (kbc->idev->users) + tegra_kbc_stop(kbc); + mutex_unlock(&kbc->idev->mutex); + } + + return 0; +} + +static int tegra_kbc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct tegra_kbc *kbc = platform_get_drvdata(pdev); + int err = 0; + + if (device_may_wakeup(&pdev->dev)) { + disable_irq_wake(kbc->irq); + tegra_kbc_setup_wakekeys(kbc, false); + } else { + mutex_lock(&kbc->idev->mutex); + if (kbc->idev->users) + err = tegra_kbc_start(kbc); + mutex_unlock(&kbc->idev->mutex); + } + + return err; +} +#endif + +static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume); + +static struct platform_driver tegra_kbc_driver = { + .probe = tegra_kbc_probe, + .remove = __devexit_p(tegra_kbc_remove), + .driver = { + .name = "tegra-kbc", + .owner = THIS_MODULE, + .pm = &tegra_kbc_pm_ops, + }, +}; + +static void __exit tegra_kbc_exit(void) +{ + platform_driver_unregister(&tegra_kbc_driver); +} +module_exit(tegra_kbc_exit); + +static int __init tegra_kbc_init(void) +{ + return platform_driver_register(&tegra_kbc_driver); +} +module_init(tegra_kbc_init); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Rakesh Iyer "); +MODULE_DESCRIPTION("Tegra matrix keyboard controller driver"); +MODULE_ALIAS("platform:tegra-kbc"); -- cgit v1.2.3-70-g09d2 From cb1b145929b5b7e1bdc5f76dd2905df9f89c038e Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 20 Jan 2011 23:05:17 -0800 Subject: Input: sparse-keymap - fix KEY_VSW handling in sparse_keymap_setup We were forgetting to set up device capabilities for KEY_VSW entries. Reported-by: Tapio Vihuri Tested-by: Tapio Vihuri Signed-off-by: Dmitry Torokhov --- drivers/input/sparse-keymap.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/input') diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index a29a7812bd4..7729e547ba6 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -201,6 +201,7 @@ int sparse_keymap_setup(struct input_dev *dev, break; case KE_SW: + case KE_VSW: __set_bit(EV_SW, dev->evbit); __set_bit(entry->sw.code, dev->swbit); break; -- cgit v1.2.3-70-g09d2 From d38acb49b7368ac4e8ec0db0055155be0805db5d Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 24 Jan 2011 09:32:50 -0800 Subject: Input: wacom - add 2 Bamboo Pen and touch models Reported-by: David Foley Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 518782999fe..f44c822caac 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1426,6 +1426,10 @@ static struct wacom_features wacom_features_0xD3 = { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT }; static const struct wacom_features wacom_features_0xD4 = { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 255, 63, BAMBOO_PT }; +static struct wacom_features wacom_features_0xD6 = + { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; +static struct wacom_features wacom_features_0xD7 = + { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; static struct wacom_features wacom_features_0xD8 = { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT }; static struct wacom_features wacom_features_0xDA = @@ -1507,6 +1511,8 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0xD2) }, { USB_DEVICE_WACOM(0xD3) }, { USB_DEVICE_WACOM(0xD4) }, + { USB_DEVICE_WACOM(0xD6) }, + { USB_DEVICE_WACOM(0xD7) }, { USB_DEVICE_WACOM(0xD8) }, { USB_DEVICE_WACOM(0xDA) }, { USB_DEVICE_WACOM(0xDB) }, -- cgit v1.2.3-70-g09d2 From 409550f2902470f0387fe40a7db441526e16b2c0 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 25 Jan 2011 18:03:13 -0800 Subject: Input: wacom - pass touch resolution to clients through input_absinfo Also remove fake ABS_RX/ABS_RY "axes" that were used to report physical dimensions now that we have better way. Signed-off-by: Ping Cheng Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_wac.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index f44c822caac..367fa82a607 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1101,6 +1101,13 @@ void wacom_setup_device_quirks(struct wacom_features *features) } } +static unsigned int wacom_calculate_touch_res(unsigned int logical_max, + unsigned int physical_max) +{ + /* Touch physical dimensions are in 100th of mm */ + return (logical_max * 100) / physical_max; +} + void wacom_setup_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { @@ -1228,8 +1235,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, case TABLETPC: if (features->device_type == BTN_TOOL_DOUBLETAP || features->device_type == BTN_TOOL_TRIPLETAP) { - input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0); - input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0); + input_abs_set_res(input_dev, ABS_X, + wacom_calculate_touch_res(features->x_max, + features->x_phy)); + input_abs_set_res(input_dev, ABS_Y, + wacom_calculate_touch_res(features->y_max, + features->y_phy)); __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); } @@ -1272,6 +1283,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, features->pressure_max, features->pressure_fuzz, 0); + input_abs_set_res(input_dev, ABS_X, + wacom_calculate_touch_res(features->x_max, + features->x_phy)); + input_abs_set_res(input_dev, ABS_Y, + wacom_calculate_touch_res(features->y_max, + features->y_phy)); } else if (features->device_type == BTN_TOOL_PEN) { __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit); -- cgit v1.2.3-70-g09d2 From 7530c4a197f3dd63f1381c1cdf93e4d2b8429ef5 Mon Sep 17 00:00:00 2001 From: Rakesh Iyer Date: Fri, 28 Jan 2011 22:05:14 -0800 Subject: Input: tegra-kbc - fix build error Fix build error introduced by variable name change. Signed-off-by: Rakesh Iyer Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tegra-kbc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 939476659ad..3d3d649be9b 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -355,8 +355,8 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc) for (i = 0; i < KBC_MAX_GPIO; i++) { u32 r_shft = 5 * (i % 6); u32 c_shft = 4 * (i % 8); - u32 r_mask = 0x1f << r_shift; - u32 c_mask = 0x0f << c_shift; + u32 r_mask = 0x1f << r_shft; + u32 c_mask = 0x0f << c_shft; u32 r_offs = (i / 6) * 4 + KBC_ROW_CFG0_0; u32 c_offs = (i / 8) * 4 + KBC_COL_CFG0_0; u32 row_cfg = readl(kbc->mmio + r_offs); -- cgit v1.2.3-70-g09d2 From e7acc84a27fe53b198cd98cc7deaabb5dd0f20c4 Mon Sep 17 00:00:00 2001 From: Rakesh Iyer Date: Fri, 28 Jan 2011 22:05:14 -0800 Subject: Input: tegra-kbc - fix keymap entry for LeftMeta key Correct key mapping for Left Meta key. Signed-off-by: Rakesh Iyer Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/tegra-kbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 3d3d649be9b..ac471b77c18 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -86,7 +86,7 @@ static const u32 tegra_kbc_default_keymap[] = { KEY(0, 5, KEY_Z), KEY(0, 7, KEY_FN), - KEY(1, 7, KEY_MENU), + KEY(1, 7, KEY_LEFTMETA), KEY(2, 6, KEY_RIGHTALT), KEY(2, 7, KEY_LEFTALT), -- cgit v1.2.3-70-g09d2 From baddf58963241307b29e027a9fb28dfe55939db8 Mon Sep 17 00:00:00 2001 From: Alexandre Peixoto Ferreira Date: Fri, 28 Jan 2011 22:05:14 -0800 Subject: Input: synaptics - fix reconnect logic on MT devices synaptics_set_advanced_gesture_mode() affect capabilities bits we should perform comparison after calling this function, otherwise they will never match and we will be forced to perform full reconnect. Signed-off-by: Alexandre Peixoto Ferreira Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index da392c22fc6..fdf089c0c70 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -766,12 +766,6 @@ static int synaptics_reconnect(struct psmouse *psmouse) return -1; } - if (old_priv.identity != priv->identity || - old_priv.model_id != priv->model_id || - old_priv.capabilities != priv->capabilities || - old_priv.ext_cap != priv->ext_cap) - return -1; - if (synaptics_set_absolute_mode(psmouse)) { printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); return -1; @@ -782,6 +776,19 @@ static int synaptics_reconnect(struct psmouse *psmouse) return -1; } + if (old_priv.identity != priv->identity || + old_priv.model_id != priv->model_id || + old_priv.capabilities != priv->capabilities || + old_priv.ext_cap != priv->ext_cap) { + printk(KERN_ERR "Synaptics hardware appears to be different: " + "id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", + old_priv.identity, priv->identity, + old_priv.model_id, priv->model_id, + old_priv.capabilities, priv->capabilities, + old_priv.ext_cap, priv->ext_cap); + return -1; + } + return 0; } -- cgit v1.2.3-70-g09d2 From c63fe0a41fd2374be0ebe93c053820a0eed9cefe Mon Sep 17 00:00:00 2001 From: Alexandre Peixoto Ferreira Date: Fri, 28 Jan 2011 22:05:14 -0800 Subject: Input: synaptics - retry failed resets when reconnecting On some machines, like Dell Studio XPS 16 (1640), touchpad fails to respond to the standard query after first reset but may start responding later, so let's repeat reset sequence several (3) times. Signed-off-by: Alexandre Peixoto Ferreira Signed-off-by: Dmitry Torokhov --- drivers/input/mouse/synaptics.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index fdf089c0c70..aa186cf6c51 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -755,12 +755,21 @@ static int synaptics_reconnect(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; struct synaptics_data old_priv = *priv; + int retry = 0; + int error; - psmouse_reset(psmouse); + do { + psmouse_reset(psmouse); + error = synaptics_detect(psmouse, 0); + } while (error && ++retry < 3); - if (synaptics_detect(psmouse, 0)) + if (error) return -1; + if (retry > 1) + printk(KERN_DEBUG "Synaptics reconnected after %d tries\n", + retry); + if (synaptics_query_hardware(psmouse)) { printk(KERN_ERR "Unable to query Synaptics hardware.\n"); return -1; -- cgit v1.2.3-70-g09d2 From 28a1bc1c0a5a15e72afae1050b227761227b6af2 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Mon, 31 Jan 2011 21:06:38 -0800 Subject: Input: wacom_w8001 - report resolution to userland Serial devices send both pen and touch data through the same logical port. Since we scaled touch to pen maximum, we use pen resolution for touch as well here. This is under the assumption that pen and touch share the same physical surface. In the case when a small physical dimensional difference occurs between pen and touch, we assume the tolerance for touch point precision is higher than pen and the difference is within touch point tolerance. A per-MT tool based resolution mechanism should be introduced if the above assumption does not hold true for the pen and touch devices any more. Signed-off-by: Ping Cheng Reviewed-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/wacom_w8001.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c index 5cb8449c909..c14412ef464 100644 --- a/drivers/input/touchscreen/wacom_w8001.c +++ b/drivers/input/touchscreen/wacom_w8001.c @@ -51,6 +51,10 @@ MODULE_LICENSE("GPL"); #define W8001_PKTLEN_TPCCTL 11 /* control packet */ #define W8001_PKTLEN_TOUCH2FG 13 +/* resolution in points/mm */ +#define W8001_PEN_RESOLUTION 100 +#define W8001_TOUCH_RESOLUTION 10 + struct w8001_coord { u8 rdy; u8 tsw; @@ -198,7 +202,7 @@ static void parse_touchquery(u8 *data, struct w8001_touch_query *query) query->y = 1024; if (query->panel_res) query->x = query->y = (1 << query->panel_res); - query->panel_res = 10; + query->panel_res = W8001_TOUCH_RESOLUTION; } } @@ -394,6 +398,8 @@ static int w8001_setup(struct w8001 *w8001) input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); + input_abs_set_res(dev, ABS_X, W8001_PEN_RESOLUTION); + input_abs_set_res(dev, ABS_Y, W8001_PEN_RESOLUTION); input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0); if (coord.tilt_x && coord.tilt_y) { input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); @@ -418,14 +424,17 @@ static int w8001_setup(struct w8001 *w8001) w8001->max_touch_x = touch.x; w8001->max_touch_y = touch.y; - /* scale to pen maximum */ if (w8001->max_pen_x && w8001->max_pen_y) { + /* if pen is supported scale to pen maximum */ touch.x = w8001->max_pen_x; touch.y = w8001->max_pen_y; + touch.panel_res = W8001_PEN_RESOLUTION; } input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0); input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0); + input_abs_set_res(dev, ABS_X, touch.panel_res); + input_abs_set_res(dev, ABS_Y, touch.panel_res); switch (touch.sensor_id) { case 0: -- cgit v1.2.3-70-g09d2 From e0d5f4c31d4769b8574dfd8c61a1f753f7cfbc2f Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Wed, 2 Feb 2011 22:59:54 -0800 Subject: Input: rotary_encoder - use proper irqflags IORESOURCE_IRQ_* is wrong for irq_request, use the correct IRQF_* instead. Signed-off-by: Alexander Stein Signed-off-by: Dmitry Torokhov --- drivers/input/misc/rotary_encoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 1f8e0108962..7e64d01da2b 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c @@ -176,7 +176,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) /* request the IRQs */ err = request_irq(encoder->irq_a, &rotary_encoder_irq, - IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, DRV_NAME, encoder); if (err) { dev_err(&pdev->dev, "unable to request IRQ %d\n", @@ -185,7 +185,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) } err = request_irq(encoder->irq_b, &rotary_encoder_irq, - IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, DRV_NAME, encoder); if (err) { dev_err(&pdev->dev, "unable to request IRQ %d\n", -- cgit v1.2.3-70-g09d2 From 19e955415398687b79fbf1c072a84c9874b8d576 Mon Sep 17 00:00:00 2001 From: Duncan Laurie Date: Wed, 2 Feb 2011 22:59:54 -0800 Subject: Input: serio - clear pending rescans after sysfs driver rebind When rebinding a serio driver via sysfs drvctl interface it is possible for an interrupt to trigger after the disconnect of the existing driver and before the binding of the new driver. This will cause the serio interrupt handler to queue a rescan event which will disconnect the new driver immediately after it is attached. This change removes pending rescans from the serio event queue after processing the drvctl request but before releasing the serio mutex. Reproduction involves issuing a rebind of device port from psmouse driver to serio_raw driver while generating input to trigger interrupts. Then checking to see if the corresponding i8042/serio4/driver is correctly attached to the serio_raw driver instead of psmouse. Signed-off-by: Duncan Laurie Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index db5b0bca1a1..7c38d1fbabf 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -188,7 +188,8 @@ static void serio_free_event(struct serio_event *event) kfree(event); } -static void serio_remove_duplicate_events(struct serio_event *event) +static void serio_remove_duplicate_events(void *object, + enum serio_event_type type) { struct serio_event *e, *next; unsigned long flags; @@ -196,13 +197,13 @@ static void serio_remove_duplicate_events(struct serio_event *event) spin_lock_irqsave(&serio_event_lock, flags); list_for_each_entry_safe(e, next, &serio_event_list, node) { - if (event->object == e->object) { + if (object == e->object) { /* * If this event is of different type we should not * look further - we only suppress duplicate events * that were sent back-to-back. */ - if (event->type != e->type) + if (type != e->type) break; list_del_init(&e->node); @@ -245,7 +246,7 @@ static void serio_handle_event(struct work_struct *work) break; } - serio_remove_duplicate_events(event); + serio_remove_duplicate_events(event->object, event->type); serio_free_event(event); } @@ -436,10 +437,12 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * } else if (!strncmp(buf, "rescan", count)) { serio_disconnect_port(serio); serio_find_driver(serio); + serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { serio_disconnect_port(serio); error = serio_bind_driver(serio, to_serio_driver(drv)); put_driver(drv); + serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); } else { error = -EINVAL; } -- cgit v1.2.3-70-g09d2 From 9ae4345a46bdb148e32a547e89ff29563a11e127 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 2 Feb 2011 23:04:27 -0800 Subject: Revert "Input: do not pass injected events back to the originating handler" This reverts commit 5fdbe44d033d059cc56c2803e6b4dbd8cb4e5e39. Apparently there exist userspace programs that expect to be able to "loop back" and distribute to readers events written into /dev/input/eventX and this change made for the benefit of SysRq handler broke them. Now that SysRq uses alternative method to suppress filtering of the events it re-injects we can safely revert this change. Reported-by: Kristen Carlson Accardi Cc: stable@kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/input.c b/drivers/input/input.c index f37da09a5e4..b8894a059f8 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -76,7 +76,6 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) * dev->event_lock held and interrupts disabled. */ static void input_pass_event(struct input_dev *dev, - struct input_handler *src_handler, unsigned int type, unsigned int code, int value) { struct input_handler *handler; @@ -95,15 +94,6 @@ static void input_pass_event(struct input_dev *dev, continue; handler = handle->handler; - - /* - * If this is the handler that injected this - * particular event we want to skip it to avoid - * filters firing again and again. - */ - if (handler == src_handler) - continue; - if (!handler->filter) { if (filtered) break; @@ -133,7 +123,7 @@ static void input_repeat_key(unsigned long data) if (test_bit(dev->repeat_key, dev->key) && is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { - input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2); + input_pass_event(dev, EV_KEY, dev->repeat_key, 2); if (dev->sync) { /* @@ -142,7 +132,7 @@ static void input_repeat_key(unsigned long data) * Otherwise assume that the driver will send * SYN_REPORT once it's done. */ - input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); + input_pass_event(dev, EV_SYN, SYN_REPORT, 1); } if (dev->rep[REP_PERIOD]) @@ -175,7 +165,6 @@ static void input_stop_autorepeat(struct input_dev *dev) #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) static int input_handle_abs_event(struct input_dev *dev, - struct input_handler *src_handler, unsigned int code, int *pval) { bool is_mt_event; @@ -219,15 +208,13 @@ static int input_handle_abs_event(struct input_dev *dev, /* Flush pending "slot" event */ if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); - input_pass_event(dev, src_handler, - EV_ABS, ABS_MT_SLOT, dev->slot); + input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); } return INPUT_PASS_TO_HANDLERS; } static void input_handle_event(struct input_dev *dev, - struct input_handler *src_handler, unsigned int type, unsigned int code, int value) { int disposition = INPUT_IGNORE_EVENT; @@ -280,8 +267,7 @@ static void input_handle_event(struct input_dev *dev, case EV_ABS: if (is_event_supported(code, dev->absbit, ABS_MAX)) - disposition = input_handle_abs_event(dev, src_handler, - code, &value); + disposition = input_handle_abs_event(dev, code, &value); break; @@ -339,7 +325,7 @@ static void input_handle_event(struct input_dev *dev, dev->event(dev, type, code, value); if (disposition & INPUT_PASS_TO_HANDLERS) - input_pass_event(dev, src_handler, type, code, value); + input_pass_event(dev, type, code, value); } /** @@ -368,7 +354,7 @@ void input_event(struct input_dev *dev, spin_lock_irqsave(&dev->event_lock, flags); add_input_randomness(type, code, value); - input_handle_event(dev, NULL, type, code, value); + input_handle_event(dev, type, code, value); spin_unlock_irqrestore(&dev->event_lock, flags); } } @@ -398,8 +384,7 @@ void input_inject_event(struct input_handle *handle, rcu_read_lock(); grab = rcu_dereference(dev->grab); if (!grab || grab == handle) - input_handle_event(dev, handle->handler, - type, code, value); + input_handle_event(dev, type, code, value); rcu_read_unlock(); spin_unlock_irqrestore(&dev->event_lock, flags); @@ -612,10 +597,10 @@ static void input_dev_release_keys(struct input_dev *dev) for (code = 0; code <= KEY_MAX; code++) { if (is_event_supported(code, dev->keybit, KEY_MAX) && __test_and_clear_bit(code, dev->key)) { - input_pass_event(dev, NULL, EV_KEY, code, 0); + input_pass_event(dev, EV_KEY, code, 0); } } - input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); + input_pass_event(dev, EV_SYN, SYN_REPORT, 1); } } @@ -890,9 +875,9 @@ int input_set_keycode(struct input_dev *dev, !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && __test_and_clear_bit(old_keycode, dev->key)) { - input_pass_event(dev, NULL, EV_KEY, old_keycode, 0); + input_pass_event(dev, EV_KEY, old_keycode, 0); if (dev->sync) - input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); + input_pass_event(dev, EV_SYN, SYN_REPORT, 1); } out: -- cgit v1.2.3-70-g09d2 From e66a022a80d73b1a5d2e02c9db2c42e8b9853b40 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sat, 11 Dec 2010 20:17:54 +0000 Subject: arm/ixp4xx: Rename FREQ macro to avoid collisions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FREQ is a ridiculously short name for a platform-specific macro in a generic header, and it now conflicts with an enumeration in the gspca/ov519 driver. Also delete conditional reference to ixp4xx_get_board_tick_rate() which is not defined anywhere. Signed-off-by: Ben Hutchings Signed-off-by: Krzysztof HaƂasa --- arch/arm/mach-ixp4xx/common.c | 4 ++-- arch/arm/mach-ixp4xx/include/mach/timex.h | 5 +++-- drivers/input/misc/ixp4xx-beeper.c | 6 +----- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers/input') diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 4dc68d6bb6b..9fd894271d5 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -432,7 +432,7 @@ static struct clocksource clocksource_ixp4xx = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -unsigned long ixp4xx_timer_freq = FREQ; +unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; EXPORT_SYMBOL(ixp4xx_timer_freq); static void __init ixp4xx_clocksource_init(void) { @@ -496,7 +496,7 @@ static struct clock_event_device clockevent_ixp4xx = { static void __init ixp4xx_clockevent_init(void) { - clockevent_ixp4xx.mult = div_sc(FREQ, NSEC_PER_SEC, + clockevent_ixp4xx.mult = div_sc(IXP4XX_TIMER_FREQ, NSEC_PER_SEC, clockevent_ixp4xx.shift); clockevent_ixp4xx.max_delta_ns = clockevent_delta2ns(0xfffffffe, &clockevent_ixp4xx); diff --git a/arch/arm/mach-ixp4xx/include/mach/timex.h b/arch/arm/mach-ixp4xx/include/mach/timex.h index 2c3f93c3eb7..c9e930f2933 100644 --- a/arch/arm/mach-ixp4xx/include/mach/timex.h +++ b/arch/arm/mach-ixp4xx/include/mach/timex.h @@ -10,6 +10,7 @@ * 66.66... MHz. We do a convulted calculation of CLOCK_TICK_RATE b/c the * timer register ignores the bottom 2 bits of the LATCH value. */ -#define FREQ 66666000 -#define CLOCK_TICK_RATE (((FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) +#define IXP4XX_TIMER_FREQ 66666000 +#define CLOCK_TICK_RATE \ + (((IXP4XX_TIMER_FREQ / HZ & ~IXP4XX_OST_RELOAD_MASK) + 1) * HZ) diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c index 9dfd6e5f786..1f38302a595 100644 --- a/drivers/input/misc/ixp4xx-beeper.c +++ b/drivers/input/misc/ixp4xx-beeper.c @@ -69,11 +69,7 @@ static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned } if (value > 20 && value < 32767) -#ifndef FREQ - count = (ixp4xx_get_board_tick_rate() / (value * 4)) - 1; -#else - count = (FREQ / (value * 4)) - 1; -#endif + count = (IXP4XX_TIMER_FREQ / (value * 4)) - 1; ixp4xx_spkr_control(pin, count); -- cgit v1.2.3-70-g09d2 From 0fbc9fdb7e747500111dcc4a5f5f3ceed0360d71 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Feb 2011 00:37:26 -0800 Subject: Input: ads7846 - check proper condition when freeing gpio When driver uses custom pendown detection method gpio_pendown is not set up and so we should not try to free it, otherwise we are presented with: ------------[ cut here ]------------ WARNING: at drivers/gpio/gpiolib.c:1258 gpio_free+0x100/0x12c() Modules linked in: [] (unwind_backtrace+0x0/0xe4) from [](warn_slowpath_common+0x4c/0x64) [] (warn_slowpath_common+0x4c/0x64) from [](warn_slowpath_null+0x18/0x1c) [] (warn_slowpath_null+0x18/0x1c) from [](gpio_free+0x100/0x12c) [] (gpio_free+0x100/0x12c) from [](ads7846_probe+0xa38/0xc5c) [] (ads7846_probe+0xa38/0xc5c) from [](spi_drv_probe+0x18/0x1c) [] (spi_drv_probe+0x18/0x1c) from [](driver_probe_device+0xc8/0x184) [] (driver_probe_device+0xc8/0x184) from [](__driver_attach+0x68/0x8c) [] (__driver_attach+0x68/0x8c) from [](bus_for_each_dev+0x48/0x74) [] (bus_for_each_dev+0x48/0x74) from [](bus_add_driver+0xa0/0x220) [] (bus_add_driver+0xa0/0x220) from [](driver_register+0xa8/0x134) [] (driver_register+0xa8/0x134) from [](do_one_initcall+0xcc/0x1a4) [] (do_one_initcall+0xcc/0x1a4) from [](kernel_init+0x14c/0x214) [] (kernel_init+0x14c/0x214) from [](kernel_thread_exit+0x0/0x8) ---[ end trace 4053287f8a5ec18f ]--- Also rearrange ads7846_setup_pendown() to have only one exit point returning success. Reported-by: Sourav Poddar Acked-by: Wolfram Sang Reviewed-by: Charulatha V Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/ads7846.c | 38 +++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers/input') diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 14ea54b78e4..4bf2316e328 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -941,28 +941,29 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784 struct ads7846_platform_data *pdata = spi->dev.platform_data; int err; - /* REVISIT when the irq can be triggered active-low, or if for some + /* + * REVISIT when the irq can be triggered active-low, or if for some * reason the touchscreen isn't hooked up, we don't need to access * the pendown state. */ - if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { - dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); - return -EINVAL; - } if (pdata->get_pendown_state) { ts->get_pendown_state = pdata->get_pendown_state; - return 0; - } + } else if (gpio_is_valid(pdata->gpio_pendown)) { - err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); - if (err) { - dev_err(&spi->dev, "failed to request pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } + err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); + if (err) { + dev_err(&spi->dev, "failed to request pendown GPIO%d\n", + pdata->gpio_pendown); + return err; + } - ts->gpio_pendown = pdata->gpio_pendown; + ts->gpio_pendown = pdata->gpio_pendown; + + } else { + dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); + return -EINVAL; + } return 0; } @@ -1353,7 +1354,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) err_put_regulator: regulator_put(ts->reg); err_free_gpio: - if (ts->gpio_pendown != -1) + if (!ts->get_pendown_state) gpio_free(ts->gpio_pendown); err_cleanup_filter: if (ts->filter_cleanup) @@ -1383,8 +1384,13 @@ static int __devexit ads7846_remove(struct spi_device *spi) regulator_disable(ts->reg); regulator_put(ts->reg); - if (ts->gpio_pendown != -1) + if (!ts->get_pendown_state) { + /* + * If we are not using specialized pendown method we must + * have been relying on gpio we set up ourselves. + */ gpio_free(ts->gpio_pendown); + } if (ts->filter_cleanup) ts->filter_cleanup(ts->filter_data); -- cgit v1.2.3-70-g09d2 From 4b6d44344000ff3e62faf595e5f89fd8d9e52a94 Mon Sep 17 00:00:00 2001 From: Alexander Strakh Date: Fri, 11 Feb 2011 00:44:41 -0800 Subject: Input: wacom - fix error path in wacom_probe() If we fail to retrieve HID descriptor we need to free allocated URB so jump to proper label to do that. Signed-off-by: Alexander Strakh Acked-by: Henrik Rydberg Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/input') diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index fc381498b79..cf8fb9f5d4a 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -519,7 +519,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i /* Retrieve the physical and logical size for OEM devices */ error = wacom_retrieve_hid_descriptor(intf, features); if (error) - goto fail2; + goto fail3; wacom_setup_device_quirks(features); -- cgit v1.2.3-70-g09d2