Commit 49327ad2 authored by Dmitry Torokhov's avatar Dmitry Torokhov

Merge branch 'next' into for-linus

parents f9ce6eb5 6521d0bf
...@@ -18,12 +18,14 @@ ...@@ -18,12 +18,14 @@
#include <linux/amba/pl022.h> #include <linux/amba/pl022.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/mfd/ab8500.h> #include <linux/mfd/ab8500.h>
#include <linux/input/matrix_keypad.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <plat/pincfg.h> #include <plat/pincfg.h>
#include <plat/i2c.h> #include <plat/i2c.h>
#include <plat/ske.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/setup.h> #include <mach/setup.h>
...@@ -47,6 +49,24 @@ static pin_cfg_t mop500_pins[] = { ...@@ -47,6 +49,24 @@ static pin_cfg_t mop500_pins[] = {
GPIO11_I2C2_SCL, GPIO11_I2C2_SCL,
GPIO229_I2C3_SDA, GPIO229_I2C3_SDA,
GPIO230_I2C3_SCL, GPIO230_I2C3_SCL,
/* SKE keypad */
GPIO153_KP_I7,
GPIO154_KP_I6,
GPIO155_KP_I5,
GPIO156_KP_I4,
GPIO157_KP_O7,
GPIO158_KP_O6,
GPIO159_KP_O5,
GPIO160_KP_O4,
GPIO161_KP_I3,
GPIO162_KP_I2,
GPIO163_KP_I1,
GPIO164_KP_I0,
GPIO165_KP_O3,
GPIO166_KP_O2,
GPIO167_KP_O1,
GPIO168_KP_O0,
}; };
static void ab4500_spi_cs_control(u32 command) static void ab4500_spi_cs_control(u32 command)
...@@ -134,12 +154,120 @@ static struct amba_device *amba_devs[] __initdata = { ...@@ -134,12 +154,120 @@ static struct amba_device *amba_devs[] __initdata = {
&u8500_ssp0_device, &u8500_ssp0_device,
}; };
static const unsigned int ux500_keymap[] = {
KEY(2, 5, KEY_END),
KEY(4, 1, KEY_POWER),
KEY(3, 5, KEY_VOLUMEDOWN),
KEY(1, 3, KEY_3),
KEY(5, 2, KEY_RIGHT),
KEY(5, 0, KEY_9),
KEY(0, 5, KEY_MENU),
KEY(7, 6, KEY_ENTER),
KEY(4, 5, KEY_0),
KEY(6, 7, KEY_2),
KEY(3, 4, KEY_UP),
KEY(3, 3, KEY_DOWN),
KEY(6, 4, KEY_SEND),
KEY(6, 2, KEY_BACK),
KEY(4, 2, KEY_VOLUMEUP),
KEY(5, 5, KEY_1),
KEY(4, 3, KEY_LEFT),
KEY(3, 2, KEY_7),
};
static const struct matrix_keymap_data ux500_keymap_data = {
.keymap = ux500_keymap,
.keymap_size = ARRAY_SIZE(ux500_keymap),
};
/*
* Nomadik SKE keypad
*/
#define ROW_PIN_I0 164
#define ROW_PIN_I1 163
#define ROW_PIN_I2 162
#define ROW_PIN_I3 161
#define ROW_PIN_I4 156
#define ROW_PIN_I5 155
#define ROW_PIN_I6 154
#define ROW_PIN_I7 153
#define COL_PIN_O0 168
#define COL_PIN_O1 167
#define COL_PIN_O2 166
#define COL_PIN_O3 165
#define COL_PIN_O4 160
#define COL_PIN_O5 159
#define COL_PIN_O6 158
#define COL_PIN_O7 157
#define SKE_KPD_MAX_ROWS 8
#define SKE_KPD_MAX_COLS 8
static int ske_kp_rows[] = {
ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
};
/*
* ske_set_gpio_row: request and set gpio rows
*/
static int ske_set_gpio_row(int gpio)
{
int ret;
ret = gpio_request(gpio, "ske-kp");
if (ret < 0) {
pr_err("ske_set_gpio_row: gpio request failed\n");
return ret;
}
ret = gpio_direction_output(gpio, 1);
if (ret < 0) {
pr_err("ske_set_gpio_row: gpio direction failed\n");
gpio_free(gpio);
}
return ret;
}
/*
* ske_kp_init - enable the gpio configuration
*/
static int ske_kp_init(void)
{
int ret, i;
for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
ret = ske_set_gpio_row(ske_kp_rows[i]);
if (ret < 0) {
pr_err("ske_kp_init: failed init\n");
return ret;
}
}
return 0;
}
static struct ske_keypad_platform_data ske_keypad_board = {
.init = ske_kp_init,
.keymap_data = &ux500_keymap_data,
.no_autorepeat = true,
.krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */
.kcol = SKE_KPD_MAX_COLS,
.debounce_ms = 40, /* in millsecs */
};
/* add any platform devices here - TODO */ /* add any platform devices here - TODO */
static struct platform_device *platform_devs[] __initdata = { static struct platform_device *platform_devs[] __initdata = {
&u8500_i2c0_device, &u8500_i2c0_device,
&ux500_i2c1_device, &ux500_i2c1_device,
&ux500_i2c2_device, &ux500_i2c2_device,
&ux500_i2c3_device, &ux500_i2c3_device,
&ux500_ske_keypad_device,
}; };
static void __init u8500_init_machine(void) static void __init u8500_init_machine(void)
...@@ -154,6 +282,7 @@ static void __init u8500_init_machine(void) ...@@ -154,6 +282,7 @@ static void __init u8500_init_machine(void)
ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data; ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data;
ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data; ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data;
ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data; ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data;
ux500_ske_keypad_device.dev.platform_data = &ske_keypad_board;
u8500_ssp0_device.dev.platform_data = &ssp0_platform_data; u8500_ssp0_device.dev.platform_data = &ssp0_platform_data;
......
...@@ -477,6 +477,7 @@ static struct clk_lookup u8500_common_clks[] = { ...@@ -477,6 +477,7 @@ static struct clk_lookup u8500_common_clks[] = {
CLK(sdi5, "sdi5", NULL), CLK(sdi5, "sdi5", NULL),
CLK(uart2, "uart2", NULL), CLK(uart2, "uart2", NULL),
CLK(ske, "ske", NULL), CLK(ske, "ske", NULL),
CLK(ske, "nmk-ske-keypad", NULL),
CLK(sdi2, "sdi2", NULL), CLK(sdi2, "sdi2", NULL),
CLK(i2c0, "nmk-i2c.0", NULL), CLK(i2c0, "nmk-i2c.0", NULL),
CLK(fsmc, "fsmc", NULL), CLK(fsmc, "fsmc", NULL),
......
...@@ -216,3 +216,23 @@ void dma40_u8500ed_fixup(void) ...@@ -216,3 +216,23 @@ void dma40_u8500ed_fixup(void)
dma40_resources[1].start = U8500_DMA_LCPA_BASE_ED; dma40_resources[1].start = U8500_DMA_LCPA_BASE_ED;
dma40_resources[1].end = U8500_DMA_LCPA_BASE_ED + 2 * SZ_1K - 1; dma40_resources[1].end = U8500_DMA_LCPA_BASE_ED + 2 * SZ_1K - 1;
} }
struct resource keypad_resources[] = {
[0] = {
.start = U8500_SKE_BASE,
.end = U8500_SKE_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_DB8500_KB,
.end = IRQ_DB8500_KB,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device ux500_ske_keypad_device = {
.name = "nmk-ske-keypad",
.id = -1,
.num_resources = ARRAY_SIZE(keypad_resources),
.resource = keypad_resources,
};
...@@ -26,6 +26,7 @@ extern struct platform_device ux500_i2c3_device; ...@@ -26,6 +26,7 @@ extern struct platform_device ux500_i2c3_device;
extern struct platform_device u8500_i2c0_device; extern struct platform_device u8500_i2c0_device;
extern struct platform_device u8500_i2c4_device; extern struct platform_device u8500_i2c4_device;
extern struct platform_device u8500_dma40_device; extern struct platform_device u8500_dma40_device;
extern struct platform_device ux500_ske_keypad_device;
void dma40_u8500ed_fixup(void); void dma40_u8500ed_fixup(void);
......
...@@ -459,82 +459,82 @@ ...@@ -459,82 +459,82 @@
#define GPIO152_KP_O9 PIN_CFG(152, ALT_C) #define GPIO152_KP_O9 PIN_CFG(152, ALT_C)
#define GPIO153_GPIO PIN_CFG(153, GPIO) #define GPIO153_GPIO PIN_CFG(153, GPIO)
#define GPIO153_KP_I7 PIN_CFG(153, ALT_A) #define GPIO153_KP_I7 PIN_CFG_PULL(153, ALT_A, DOWN)
#define GPIO153_LCD_D24 PIN_CFG(153, ALT_B) #define GPIO153_LCD_D24 PIN_CFG(153, ALT_B)
#define GPIO153_U2_RXD PIN_CFG(153, ALT_C) #define GPIO153_U2_RXD PIN_CFG(153, ALT_C)
#define GPIO154_GPIO PIN_CFG(154, GPIO) #define GPIO154_GPIO PIN_CFG(154, GPIO)
#define GPIO154_KP_I6 PIN_CFG(154, ALT_A) #define GPIO154_KP_I6 PIN_CFG_PULL(154, ALT_A, DOWN)
#define GPIO154_LCD_D25 PIN_CFG(154, ALT_B) #define GPIO154_LCD_D25 PIN_CFG(154, ALT_B)
#define GPIO154_U2_TXD PIN_CFG(154, ALT_C) #define GPIO154_U2_TXD PIN_CFG(154, ALT_C)
#define GPIO155_GPIO PIN_CFG(155, GPIO) #define GPIO155_GPIO PIN_CFG(155, GPIO)
#define GPIO155_KP_I5 PIN_CFG(155, ALT_A) #define GPIO155_KP_I5 PIN_CFG_PULL(155, ALT_A, DOWN)
#define GPIO155_LCD_D26 PIN_CFG(155, ALT_B) #define GPIO155_LCD_D26 PIN_CFG(155, ALT_B)
#define GPIO155_STMAPE_CLK PIN_CFG(155, ALT_C) #define GPIO155_STMAPE_CLK PIN_CFG(155, ALT_C)
#define GPIO156_GPIO PIN_CFG(156, GPIO) #define GPIO156_GPIO PIN_CFG(156, GPIO)
#define GPIO156_KP_I4 PIN_CFG(156, ALT_A) #define GPIO156_KP_I4 PIN_CFG_PULL(156, ALT_A, DOWN)
#define GPIO156_LCD_D27 PIN_CFG(156, ALT_B) #define GPIO156_LCD_D27 PIN_CFG(156, ALT_B)
#define GPIO156_STMAPE_DAT3 PIN_CFG(156, ALT_C) #define GPIO156_STMAPE_DAT3 PIN_CFG(156, ALT_C)
#define GPIO157_GPIO PIN_CFG(157, GPIO) #define GPIO157_GPIO PIN_CFG(157, GPIO)
#define GPIO157_KP_O7 PIN_CFG(157, ALT_A) #define GPIO157_KP_O7 PIN_CFG_PULL(157, ALT_A, UP)
#define GPIO157_LCD_D28 PIN_CFG(157, ALT_B) #define GPIO157_LCD_D28 PIN_CFG(157, ALT_B)
#define GPIO157_STMAPE_DAT2 PIN_CFG(157, ALT_C) #define GPIO157_STMAPE_DAT2 PIN_CFG(157, ALT_C)
#define GPIO158_GPIO PIN_CFG(158, GPIO) #define GPIO158_GPIO PIN_CFG(158, GPIO)
#define GPIO158_KP_O6 PIN_CFG(158, ALT_A) #define GPIO158_KP_O6 PIN_CFG_PULL(158, ALT_A, UP)
#define GPIO158_LCD_D29 PIN_CFG(158, ALT_B) #define GPIO158_LCD_D29 PIN_CFG(158, ALT_B)
#define GPIO158_STMAPE_DAT1 PIN_CFG(158, ALT_C) #define GPIO158_STMAPE_DAT1 PIN_CFG(158, ALT_C)
#define GPIO159_GPIO PIN_CFG(159, GPIO) #define GPIO159_GPIO PIN_CFG(159, GPIO)
#define GPIO159_KP_O5 PIN_CFG(159, ALT_A) #define GPIO159_KP_O5 PIN_CFG_PULL(159, ALT_A, UP)
#define GPIO159_LCD_D30 PIN_CFG(159, ALT_B) #define GPIO159_LCD_D30 PIN_CFG(159, ALT_B)
#define GPIO159_STMAPE_DAT0 PIN_CFG(159, ALT_C) #define GPIO159_STMAPE_DAT0 PIN_CFG(159, ALT_C)
#define GPIO160_GPIO PIN_CFG(160, GPIO) #define GPIO160_GPIO PIN_CFG(160, GPIO)
#define GPIO160_KP_O4 PIN_CFG(160, ALT_A) #define GPIO160_KP_O4 PIN_CFG_PULL(160, ALT_A, UP)
#define GPIO160_LCD_D31 PIN_CFG(160, ALT_B) #define GPIO160_LCD_D31 PIN_CFG(160, ALT_B)
#define GPIO160_NONE PIN_CFG(160, ALT_C) #define GPIO160_NONE PIN_CFG(160, ALT_C)
#define GPIO161_GPIO PIN_CFG(161, GPIO) #define GPIO161_GPIO PIN_CFG(161, GPIO)
#define GPIO161_KP_I3 PIN_CFG(161, ALT_A) #define GPIO161_KP_I3 PIN_CFG_PULL(161, ALT_A, DOWN)
#define GPIO161_LCD_D32 PIN_CFG(161, ALT_B) #define GPIO161_LCD_D32 PIN_CFG(161, ALT_B)
#define GPIO161_UARTMOD_RXD PIN_CFG(161, ALT_C) #define GPIO161_UARTMOD_RXD PIN_CFG(161, ALT_C)
#define GPIO162_GPIO PIN_CFG(162, GPIO) #define GPIO162_GPIO PIN_CFG(162, GPIO)
#define GPIO162_KP_I2 PIN_CFG(162, ALT_A) #define GPIO162_KP_I2 PIN_CFG_PULL(162, ALT_A, DOWN)
#define GPIO162_LCD_D33 PIN_CFG(162, ALT_B) #define GPIO162_LCD_D33 PIN_CFG(162, ALT_B)
#define GPIO162_UARTMOD_TXD PIN_CFG(162, ALT_C) #define GPIO162_UARTMOD_TXD PIN_CFG(162, ALT_C)
#define GPIO163_GPIO PIN_CFG(163, GPIO) #define GPIO163_GPIO PIN_CFG(163, GPIO)
#define GPIO163_KP_I1 PIN_CFG(163, ALT_A) #define GPIO163_KP_I1 PIN_CFG_PULL(163, ALT_A, DOWN)
#define GPIO163_LCD_D34 PIN_CFG(163, ALT_B) #define GPIO163_LCD_D34 PIN_CFG(163, ALT_B)
#define GPIO163_STMMOD_CLK PIN_CFG(163, ALT_C) #define GPIO163_STMMOD_CLK PIN_CFG(163, ALT_C)
#define GPIO164_GPIO PIN_CFG(164, GPIO) #define GPIO164_GPIO PIN_CFG(164, GPIO)
#define GPIO164_KP_I0 PIN_CFG(164, ALT_A) #define GPIO164_KP_I0 PIN_CFG_PULL(164, ALT_A, UP)
#define GPIO164_LCD_D35 PIN_CFG(164, ALT_B) #define GPIO164_LCD_D35 PIN_CFG(164, ALT_B)
#define GPIO164_STMMOD_DAT3 PIN_CFG(164, ALT_C) #define GPIO164_STMMOD_DAT3 PIN_CFG(164, ALT_C)
#define GPIO165_GPIO PIN_CFG(165, GPIO) #define GPIO165_GPIO PIN_CFG(165, GPIO)
#define GPIO165_KP_O3 PIN_CFG(165, ALT_A) #define GPIO165_KP_O3 PIN_CFG_PULL(165, ALT_A, UP)
#define GPIO165_LCD_D36 PIN_CFG(165, ALT_B) #define GPIO165_LCD_D36 PIN_CFG(165, ALT_B)
#define GPIO165_STMMOD_DAT2 PIN_CFG(165, ALT_C) #define GPIO165_STMMOD_DAT2 PIN_CFG(165, ALT_C)
#define GPIO166_GPIO PIN_CFG(166, GPIO) #define GPIO166_GPIO PIN_CFG(166, GPIO)
#define GPIO166_KP_O2 PIN_CFG(166, ALT_A) #define GPIO166_KP_O2 PIN_CFG_PULL(166, ALT_A, UP)
#define GPIO166_LCD_D37 PIN_CFG(166, ALT_B) #define GPIO166_LCD_D37 PIN_CFG(166, ALT_B)
#define GPIO166_STMMOD_DAT1 PIN_CFG(166, ALT_C) #define GPIO166_STMMOD_DAT1 PIN_CFG(166, ALT_C)
#define GPIO167_GPIO PIN_CFG(167, GPIO) #define GPIO167_GPIO PIN_CFG(167, GPIO)
#define GPIO167_KP_O1 PIN_CFG(167, ALT_A) #define GPIO167_KP_O1 PIN_CFG_PULL(167, ALT_A, UP)
#define GPIO167_LCD_D38 PIN_CFG(167, ALT_B) #define GPIO167_LCD_D38 PIN_CFG(167, ALT_B)
#define GPIO167_STMMOD_DAT0 PIN_CFG(167, ALT_C) #define GPIO167_STMMOD_DAT0 PIN_CFG(167, ALT_C)
#define GPIO168_GPIO PIN_CFG(168, GPIO) #define GPIO168_GPIO PIN_CFG(168, GPIO)
#define GPIO168_KP_O0 PIN_CFG(168, ALT_A) #define GPIO168_KP_O0 PIN_CFG_PULL(168, ALT_A, UP)
#define GPIO168_LCD_D39 PIN_CFG(168, ALT_B) #define GPIO168_LCD_D39 PIN_CFG(168, ALT_B)
#define GPIO168_NONE PIN_CFG(168, ALT_C) #define GPIO168_NONE PIN_CFG(168, ALT_C)
......
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
* Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
*
* ux500 Scroll key and Keypad Encoder (SKE) header
*/
#ifndef __SKE_H
#define __SKE_H
#include <linux/input/matrix_keypad.h>
/* register definitions for SKE peripheral */
#define SKE_CR 0x00
#define SKE_VAL0 0x04
#define SKE_VAL1 0x08
#define SKE_DBCR 0x0C
#define SKE_IMSC 0x10
#define SKE_RIS 0x14
#define SKE_MIS 0x18
#define SKE_ICR 0x1C
/*
* Keypad module
*/
/**
* struct keypad_platform_data - structure for platform specific data
* @init: pointer to keypad init function
* @exit: pointer to keypad deinitialisation function
* @keymap_data: matrix scan code table for keycodes
* @krow: maximum number of rows
* @kcol: maximum number of columns
* @debounce_ms: platform specific debounce time
* @no_autorepeat: flag for auto repetition
* @wakeup_enable: allow waking up the system
*/
struct ske_keypad_platform_data {
int (*init)(void);
int (*exit)(void);
const struct matrix_keymap_data *keymap_data;
u8 krow;
u8 kcol;
u8 debounce_ms;
bool no_autorepeat;
bool wakeup_enable;
};
#endif /*__SKE_KPD_H*/
#ifndef ARCH_ARM_PLAT_OMAP4_KEYPAD_H
#define ARCH_ARM_PLAT_OMAP4_KEYPAD_H
#include <linux/input/matrix_keypad.h>
struct omap4_keypad_platform_data {
const struct matrix_keymap_data *keymap_data;
u8 rows;
u8 cols;
};
extern int omap4_keyboard_init(struct omap4_keypad_platform_data *);
#endif
...@@ -175,8 +175,7 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier); ...@@ -175,8 +175,7 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
*/ */
struct getset_keycode_data { struct getset_keycode_data {
unsigned int scancode; struct input_keymap_entry ke;
unsigned int keycode;
int error; int error;
}; };
...@@ -184,32 +183,50 @@ static int getkeycode_helper(struct input_handle *handle, void *data) ...@@ -184,32 +183,50 @@ static int getkeycode_helper(struct input_handle *handle, void *data)
{ {
struct getset_keycode_data *d = data; struct getset_keycode_data *d = data;
d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode); d->error = input_get_keycode(handle->dev, &d->ke);
return d->error == 0; /* stop as soon as we successfully get one */ return d->error == 0; /* stop as soon as we successfully get one */
} }
int getkeycode(unsigned int scancode) int getkeycode(unsigned int scancode)
{ {
struct getset_keycode_data d = { scancode, 0, -ENODEV }; struct getset_keycode_data d = {
.ke = {
.flags = 0,
.len = sizeof(scancode),
.keycode = 0,
},
.error = -ENODEV,
};
memcpy(d.ke.scancode, &scancode, sizeof(scancode));
input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper); input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
return d.error ?: d.keycode; return d.error ?: d.ke.keycode;
} }
static int setkeycode_helper(struct input_handle *handle, void *data) static int setkeycode_helper(struct input_handle *handle, void *data)
{ {
struct getset_keycode_data *d = data; struct getset_keycode_data *d = data;
d->error = input_set_keycode(handle->dev, d->scancode, d->keycode); d->error = input_set_keycode(handle->dev, &d->ke);
return d->error == 0; /* stop as soon as we successfully set one */ return d->error == 0; /* stop as soon as we successfully set one */
} }
int setkeycode(unsigned int scancode, unsigned int keycode) int setkeycode(unsigned int scancode, unsigned int keycode)
{ {
struct getset_keycode_data d = { scancode, keycode, -ENODEV }; struct getset_keycode_data d = {
.ke = {
.flags = 0,
.len = sizeof(scancode),
.keycode = keycode,
},
.error = -ENODEV,
};
memcpy(d.ke.scancode, &scancode, sizeof(scancode));
input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper); input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
......
...@@ -566,10 +566,16 @@ static const unsigned char sysrq_xlate[KEY_MAX + 1] = ...@@ -566,10 +566,16 @@ static const unsigned char sysrq_xlate[KEY_MAX + 1] =
static bool sysrq_down; static bool sysrq_down;
static int sysrq_alt_use; static int sysrq_alt_use;
static int sysrq_alt; static int sysrq_alt;
static DEFINE_SPINLOCK(sysrq_event_lock);
static bool sysrq_filter(struct input_handle *handle, unsigned int type, static bool sysrq_filter(struct input_handle *handle, unsigned int type,
unsigned int code, int value) unsigned int code, int value)
{ {
bool suppress;
/* We are called with interrupts disabled, just take the lock */
spin_lock(&sysrq_event_lock);
if (type != EV_KEY) if (type != EV_KEY)
goto out; goto out;
...@@ -601,7 +607,10 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type, ...@@ -601,7 +607,10 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type,
} }
out: out:
return sysrq_down; suppress = sysrq_down;
spin_unlock(&sysrq_event_lock);
return suppress;
} }
static int sysrq_connect(struct input_handler *handler, static int sysrq_connect(struct input_handler *handler,
...@@ -652,8 +661,8 @@ static void sysrq_disconnect(struct input_handle *handle) ...@@ -652,8 +661,8 @@ static void sysrq_disconnect(struct input_handle *handle)
} }
/* /*
* We are matching on KEY_LEFTALT insteard of KEY_SYSRQ because not all * We are matching on KEY_LEFTALT instead of KEY_SYSRQ because not all
* keyboards have SysRq ikey predefined and so user may add it to keymap * keyboards have SysRq key predefined and so user may add it to keymap
* later, but we expect all such keyboards to have left alt. * later, but we expect all such keyboards to have left alt.
*/ */
static const struct input_device_id sysrq_ids[] = { static const struct input_device_id sysrq_ids[] = {
......
...@@ -1766,6 +1766,11 @@ static bool hid_ignore(struct hid_device *hdev) ...@@ -1766,6 +1766,11 @@ static bool hid_ignore(struct hid_device *hdev)
hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST) hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST)
return true; return true;
break; break;
case USB_VENDOR_ID_HANWANG:
if (hdev->product >= USB_DEVICE_ID_HANWANG_TABLET_FIRST &&
hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST)
return true;
break;
} }
if (hdev->type == HID_TYPE_USBMOUSE && if (hdev->type == HID_TYPE_USBMOUSE &&
......
...@@ -291,6 +291,10 @@ ...@@ -291,6 +291,10 @@
#define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003 #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003
#define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008 #define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008
#define USB_VENDOR_ID_HANWANG 0x0b57
#define USB_DEVICE_ID_HANWANG_TABLET_FIRST 0x5000
#define USB_DEVICE_ID_HANWANG_TABLET_LAST 0x8fff
#define USB_VENDOR_ID_HAPP 0x078b #define USB_VENDOR_ID_HAPP 0x078b
#define USB_DEVICE_ID_UGCI_DRIVING 0x0010 #define USB_DEVICE_ID_UGCI_DRIVING 0x0010
#define USB_DEVICE_ID_UGCI_FLYING 0x0020 #define USB_DEVICE_ID_UGCI_FLYING 0x0020
......
...@@ -68,39 +68,52 @@ static const struct { ...@@ -68,39 +68,52 @@ static const struct {
#define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ #define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \
&max, EV_KEY, (c)) &max, EV_KEY, (c))
static inline int match_scancode(unsigned int code, unsigned int scancode) static bool match_scancode(struct hid_usage *usage,
unsigned int cur_idx, unsigned int scancode)
{ {
if (scancode == 0) return (usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
return 1;
return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
} }
static inline int match_keycode(unsigned int code, unsigned int keycode) static bool match_keycode(struct hid_usage *usage,
unsigned int cur_idx, unsigned int keycode)
{ {
if (keycode == 0) /*
return 1; * We should exclude unmapped usages when doing lookup by keycode.
*/
return (usage->type == EV_KEY && usage->code == keycode);
}
return code == keycode; static bool match_index(struct hid_usage *usage,
unsigned int cur_idx, unsigned int idx)
{
return cur_idx == idx;
} }
typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage,
unsigned int cur_idx, unsigned int val);
static struct hid_usage *hidinput_find_key(struct hid_device *hid, static struct hid_usage *hidinput_find_key(struct hid_device *hid,
unsigned int scancode, hid_usage_cmp_t match,
unsigned int keycode) unsigned int value,
unsigned int *usage_idx)
{ {
int i, j, k; unsigned int i, j, k, cur_idx = 0;
struct hid_report *report; struct hid_report *report;
struct hid_usage *usage; struct hid_usage *usage;
for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
list_for_each_entry(report, &hid->report_enum[k].report_list, list) { list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
for (i = 0; i < report->maxfield; i++) { for (i = 0; i < report->maxfield; i++) {
for ( j = 0; j < report->field[i]->maxusage; j++) { for (j = 0; j < report->field[i]->maxusage; j++) {
usage = report->field[i]->usage + j; usage = report->field[i]->usage + j;
if (usage->type == EV_KEY && if (usage->type == EV_KEY || usage->type == 0) {
match_scancode(usage->hid, scancode) && if (match(usage, cur_idx, value)) {
match_keycode(usage->code, keycode)) if (usage_idx)
return usage; *usage_idx = cur_idx;
return usage;
}
cur_idx++;
}
} }
} }
} }
...@@ -108,39 +121,68 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid, ...@@ -108,39 +121,68 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid,
return NULL; return NULL;
} }
static struct hid_usage *hidinput_locate_usage(struct hid_device *hid,
const struct input_keymap_entry *ke,
unsigned int *index)
{
struct hid_usage *usage;
unsigned int scancode;
if (ke->flags & INPUT_KEYMAP_BY_INDEX)
usage = hidinput_find_key(hid, match_index, ke->index, index);
else if (input_scancode_to_scalar(ke, &scancode) == 0)
usage = hidinput_find_key(hid, match_scancode, scancode, index);
else
usage = NULL;
return usage;
}
static int hidinput_getkeycode(struct input_dev *dev, static int hidinput_getkeycode(struct input_dev *dev,
unsigned int scancode, unsigned int *keycode) struct input_keymap_entry *ke)
{ {
struct hid_device *hid = input_get_drvdata(dev); struct hid_device *hid = input_get_drvdata(dev);
struct hid_usage *usage; struct hid_usage *usage;
unsigned int scancode, index;
usage = hidinput_find_key(hid, scancode, 0); usage = hidinput_locate_usage(hid, ke, &index);
if (usage) { if (usage) {
*keycode = usage->code; ke->keycode = usage->type == EV_KEY ?
usage->code : KEY_RESERVED;
ke->index = index;
scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE);
ke->len = sizeof(scancode);
memcpy(ke->scancode, &scancode, sizeof(scancode));
return 0; return 0;
} }
return -EINVAL; return -EINVAL;
} }
static int hidinput_setkeycode(struct input_dev *dev, static int hidinput_setkeycode(struct input_dev *dev,
unsigned int scancode, unsigned int keycode) const struct input_keymap_entry *ke,
unsigned int *old_keycode)
{ {
struct hid_device *hid = input_get_drvdata(dev); struct hid_device *hid = input_get_drvdata(dev);
struct hid_usage *usage; struct hid_usage *usage;
int old_keycode;
usage = hidinput_find_key(hid, scancode, 0); usage = hidinput_locate_usage(hid, ke, NULL);
if (usage) { if (usage) {
old_keycode = usage->code; *old_keycode = usage->type == EV_KEY ?
usage->code = keycode; usage->code : KEY_RESERVED;
usage->code = ke->keycode;
clear_bit(old_keycode, dev->keybit); clear_bit(*old_keycode, dev->keybit);
set_bit(usage->code, dev->keybit); set_bit(usage->code, dev->keybit);
dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n",
/* Set the keybit for the old keycode if the old keycode is used usage->code, usage->hid);
* by another key */
if (hidinput_find_key (hid, 0, old_keycode)) /*
set_bit(old_keycode, dev->keybit); * Set the keybit for the old keycode if the old keycode is used
* by another key
*/
if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL))
set_bit(*old_keycode, dev->keybit);
return 0; return 0;
} }
...@@ -748,8 +790,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) ...@@ -748,8 +790,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
hid->ll_driver->hidinput_input_event; hid->ll_driver->hidinput_input_event;
input_dev->open = hidinput_open; input_dev->open = hidinput_open;
input_dev->close = hidinput_close; input_dev->close = hidinput_close;
input_dev->setkeycode = hidinput_setkeycode; input_dev->setkeycode_new = hidinput_setkeycode;
input_dev->getkeycode = hidinput_getkeycode; input_dev->getkeycode_new = hidinput_getkeycode;
input_dev->name = hid->name; input_dev->name = hid->name;
input_dev->phys = hid->phys; input_dev->phys = hid->phys;
......
...@@ -534,6 +534,80 @@ static int handle_eviocgbit(struct input_dev *dev, ...@@ -534,6 +534,80 @@ static int handle_eviocgbit(struct input_dev *dev,
} }
#undef OLD_KEY_MAX #undef OLD_KEY_MAX
static int evdev_handle_get_keycode(struct input_dev *dev,
void __user *p, size_t size)
{
struct input_keymap_entry ke;
int error;
memset(&ke, 0, sizeof(ke));
if (size == sizeof(unsigned int[2])) {
/* legacy case */
int __user *ip = (int __user *)p;
if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
return -EFAULT;
ke.len = sizeof(unsigned int);
ke.flags = 0;
error = input_get_keycode(dev, &ke);
if (error)
return error;
if (put_user(ke.keycode, ip + 1))
return -EFAULT;
} else {
size = min(size, sizeof(ke));
if (copy_from_user(&ke, p, size))
return -EFAULT;
error = input_get_keycode(dev, &ke);
if (error)
return error;
if (copy_to_user(p, &ke, size))
return -EFAULT;
}
return 0;
}
static int evdev_handle_set_keycode(struct input_dev *dev,
void __user *p, size_t size)
{
struct input_keymap_entry ke;
memset(&ke, 0, sizeof(ke));
if (size == sizeof(unsigned int[2])) {
/* legacy case */
int __user *ip = (int __user *)p;
if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
return -EFAULT;
if (get_user(ke.keycode, ip + 1))
return -EFAULT;
ke.len = sizeof(unsigned int);
ke.flags = 0;
} else {
size = min(size, sizeof(ke));
if (copy_from_user(&ke, p, size))
return -EFAULT;
if (ke.len > sizeof(ke.scancode))
return -EINVAL;
}
return input_set_keycode(dev, &ke);
}
static long evdev_do_ioctl(struct file *file, unsigned int cmd, static long evdev_do_ioctl(struct file *file, unsigned int cmd,
void __user *p, int compat_mode) void __user *p, int compat_mode)
{ {
...@@ -580,25 +654,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, ...@@ -580,25 +654,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
return 0; return 0;
case EVIOCGKEYCODE:
if (get_user(t, ip))
return -EFAULT;
error = input_get_keycode(dev, t, &v);
if (error)
return error;
if (put_user(v, ip + 1))
return -EFAULT;
return 0;
case EVIOCSKEYCODE:
if (get_user(t, ip) || get_user(v, ip + 1))
return -EFAULT;
return input_set_keycode(dev, t, v);
case EVIOCRMFF: case EVIOCRMFF:
return input_ff_erase(dev, (int)(unsigned long) p, file); return input_ff_erase(dev, (int)(unsigned long) p, file);
...@@ -620,7 +675,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, ...@@ -620,7 +675,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
/* Now check variable-length commands */ /* Now check variable-length commands */
#define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) #define EVIOC_MASK_SIZE(nr) ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
switch (EVIOC_MASK_SIZE(cmd)) { switch (EVIOC_MASK_SIZE(cmd)) {
case EVIOCGKEY(0): case EVIOCGKEY(0):
...@@ -654,6 +708,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, ...@@ -654,6 +708,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
return -EFAULT; return -EFAULT;
return error; return error;
case EVIOC_MASK_SIZE(EVIOCGKEYCODE):
return evdev_handle_get_keycode(dev, p, size);
case EVIOC_MASK_SIZE(EVIOCSKEYCODE):
return evdev_handle_set_keycode(dev, p, size);
} }
/* Multi-number variable-length handlers */ /* Multi-number variable-length handlers */
......
...@@ -59,44 +59,52 @@ MODULE_DEVICE_TABLE(pci, emu_tbl); ...@@ -59,44 +59,52 @@ MODULE_DEVICE_TABLE(pci, emu_tbl);
static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent) static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
int ioport, iolen;
struct emu *emu; struct emu *emu;
struct gameport *port; struct gameport *port;
int error;
if (pci_enable_device(pdev))
return -EBUSY;
ioport = pci_resource_start(pdev, 0);
iolen = pci_resource_len(pdev, 0);
if (!request_region(ioport, iolen, "emu10k1-gp"))
return -EBUSY;
emu = kzalloc(sizeof(struct emu), GFP_KERNEL); emu = kzalloc(sizeof(struct emu), GFP_KERNEL);
port = gameport_allocate_port(); port = gameport_allocate_port();
if (!emu || !port) { if (!emu || !port) {
printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n"); printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
release_region(ioport, iolen); error = -ENOMEM;
kfree(emu); goto err_out_free;
gameport_free_port(port);
return -ENOMEM;
} }
emu->io = ioport; error = pci_enable_device(pdev);
emu->size = iolen; if (error)
goto err_out_free;
emu->io = pci_resource_start(pdev, 0);
emu->size = pci_resource_len(pdev, 0);
emu->dev = pdev; emu->dev = pdev;
emu->gameport = port; emu->gameport = port;
gameport_set_name(port, "EMU10K1"); gameport_set_name(port, "EMU10K1");
gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
port->dev.parent = &pdev->dev; port->dev.parent = &pdev->dev;
port->io = ioport; port->io = emu->io;
if (!request_region(emu->io, emu->size, "emu10k1-gp")) {
printk(KERN_ERR "emu10k1-gp: unable to grab region 0x%x-0x%x\n",
emu->io, emu->io + emu->size - 1);
error = -EBUSY;
goto err_out_disable_dev;
}
pci_set_drvdata(pdev, emu); pci_set_drvdata(pdev, emu);
gameport_register_port(port); gameport_register_port(port);
return 0; return 0;
err_out_disable_dev:
pci_disable_device(pdev);
err_out_free:
gameport_free_port(port);
kfree(emu);
return error;
} }
static void __devexit emu_remove(struct pci_dev *pdev) static void __devexit emu_remove(struct pci_dev *pdev)
...@@ -106,6 +114,8 @@ static void __devexit emu_remove(struct pci_dev *pdev) ...@@ -106,6 +114,8 @@ static void __devexit emu_remove(struct pci_dev *pdev)
gameport_unregister_port(emu->gameport); gameport_unregister_port(emu->gameport);
release_region(emu->io, emu->size); release_region(emu->io, emu->size);
kfree(emu); kfree(emu);
pci_disable_device(pdev);
} }
static struct pci_driver emu_driver = { static struct pci_driver emu_driver = {
......
...@@ -133,11 +133,11 @@ static void __devexit fm801_gp_remove(struct pci_dev *pci) ...@@ -133,11 +133,11 @@ static void __devexit fm801_gp_remove(struct pci_dev *pci)
{ {
struct fm801_gp *gp = pci_get_drvdata(pci); struct fm801_gp *gp = pci_get_drvdata(pci);
if (gp) { gameport_unregister_port(gp->gameport);
gameport_unregister_port(gp->gameport); release_resource(gp->res_port);
release_resource(gp->res_port); kfree(gp);
kfree(gp);
} pci_disable_device(pci);
} }
static const struct pci_device_id fm801_gp_id_table[] = { static const struct pci_device_id fm801_gp_id_table[] = {
......
...@@ -171,7 +171,7 @@ static int input_handle_abs_event(struct input_dev *dev, ...@@ -171,7 +171,7 @@ static int input_handle_abs_event(struct input_dev *dev,
if (code == ABS_MT_SLOT) { if (code == ABS_MT_SLOT) {
/* /*
* "Stage" the event; we'll flush it later, when we * "Stage" the event; we'll flush it later, when we
* get actiual touch data. * get actual touch data.
*/ */
if (*pval >= 0 && *pval < dev->mtsize) if (*pval >= 0 && *pval < dev->mtsize)
dev->slot = *pval; dev->slot = *pval;
...@@ -188,7 +188,7 @@ static int input_handle_abs_event(struct input_dev *dev, ...@@ -188,7 +188,7 @@ static int input_handle_abs_event(struct input_dev *dev,
pold = &mtslot->abs[code - ABS_MT_FIRST]; pold = &mtslot->abs[code - ABS_MT_FIRST];
} else { } else {
/* /*
* Bypass filtering for multitouch events when * Bypass filtering for multi-touch events when
* not employing slots. * not employing slots.
*/ */
pold = NULL; pold = NULL;
...@@ -634,78 +634,141 @@ static void input_disconnect_device(struct input_dev *dev) ...@@ -634,78 +634,141 @@ static void input_disconnect_device(struct input_dev *dev)
spin_unlock_irq(&dev->event_lock); spin_unlock_irq(&dev->event_lock);
} }
static int input_fetch_keycode(struct input_dev *dev, int scancode) /**
* input_scancode_to_scalar() - converts scancode in &struct input_keymap_entry
* @ke: keymap entry containing scancode to be converted.
* @scancode: pointer to the location where converted scancode should
* be stored.
*
* This function is used to convert scancode stored in &struct keymap_entry
* into scalar form understood by legacy keymap handling methods. These
* methods expect scancodes to be represented as 'unsigned int'.
*/
int input_scancode_to_scalar(const struct input_keymap_entry *ke,
unsigned int *scancode)
{
switch (ke->len) {
case 1:
*scancode = *((u8 *)ke->scancode);
break;
case 2:
*scancode = *((u16 *)ke->scancode);
break;
case 4:
*scancode = *((u32 *)ke->scancode);
break;
default:
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL(input_scancode_to_scalar);
/*
* Those routines handle the default case where no [gs]etkeycode() is
* defined. In this case, an array indexed by the scancode is used.
*/
static unsigned int input_fetch_keycode(struct input_dev *dev,
unsigned int index)
{ {
switch (dev->keycodesize) { switch (dev->keycodesize) {
case 1: case 1:
return ((u8 *)dev->keycode)[scancode]; return ((u8 *)dev->keycode)[index];
case 2: case 2:
return ((u16 *)dev->keycode)[scancode]; return ((u16 *)dev->keycode)[index];
default: default:
return ((u32 *)dev->keycode)[scancode]; return ((u32 *)dev->keycode)[index];
} }
} }
static int input_default_getkeycode(struct input_dev *dev, static int input_default_getkeycode(struct input_dev *dev,
unsigned int scancode, struct input_keymap_entry *ke)
unsigned int *keycode)
{ {
unsigned int index;
int error;
if (!dev->keycodesize) if (!dev->keycodesize)
return -EINVAL; return -EINVAL;
if (scancode >= dev->keycodemax) if (ke->flags & INPUT_KEYMAP_BY_INDEX)
index = ke->index;
else {
error = input_scancode_to_scalar(ke, &index);
if (error)
return error;
}
if (index >= dev->keycodemax)
return -EINVAL; return -EINVAL;
*keycode = input_fetch_keycode(dev, scancode); ke->keycode = input_fetch_keycode(dev, index);
ke->index = index;
ke->len = sizeof(index);
memcpy(ke->scancode, &index, sizeof(index));
return 0; return 0;
} }
static int input_default_setkeycode(struct input_dev *dev, static int input_default_setkeycode(struct input_dev *dev,
unsigned int scancode, const struct input_keymap_entry *ke,
unsigned int keycode) unsigned int *old_keycode)
{ {
int old_keycode; unsigned int index;
int error;
int i; int i;
if (scancode >= dev->keycodemax) if (!dev->keycodesize)
return -EINVAL; return -EINVAL;
if (!dev->keycodesize) if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
index = ke->index;
} else {
error = input_scancode_to_scalar(ke, &index);
if (error)
return error;
}
if (index >= dev->keycodemax)
return -EINVAL; return -EINVAL;
if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8))) if (dev->keycodesize < sizeof(dev->keycode) &&
(ke->keycode >> (dev->keycodesize * 8)))
return -EINVAL; return -EINVAL;
switch (dev->keycodesize) { switch (dev->keycodesize) {
case 1: { case 1: {
u8 *k = (u8 *)dev->keycode; u8 *k = (u8 *)dev->keycode;
old_keycode = k[scancode]; *old_keycode = k[index];
k[scancode] = keycode; k[index] = ke->keycode;
break; break;
} }
case 2: { case 2: {
u16 *k = (u16 *)dev->keycode; u16 *k = (u16 *)dev->keycode;
old_keycode = k[scancode]; *old_keycode = k[index];
k[scancode] = keycode; k[index] = ke->keycode;
break; break;
} }
default: { default: {
u32 *k = (u32 *)dev->keycode; u32 *k = (u32 *)dev->keycode;
old_keycode = k[scancode]; *old_keycode = k[index];
k[scancode] = keycode; k[index] = ke->keycode;
break; break;
} }
} }
__clear_bit(old_keycode, dev->keybit); __clear_bit(*old_keycode, dev->keybit);
__set_bit(keycode, dev->keybit); __set_bit(ke->keycode, dev->keybit);
for (i = 0; i < dev->keycodemax; i++) { for (i = 0; i < dev->keycodemax; i++) {
if (input_fetch_keycode(dev, i) == old_keycode) { if (input_fetch_keycode(dev, i) == *old_keycode) {
__set_bit(old_keycode, dev->keybit); __set_bit(*old_keycode, dev->keybit);
break; /* Setting the bit twice is useless, so break */ break; /* Setting the bit twice is useless, so break */
} }
} }
...@@ -716,53 +779,86 @@ static int input_default_setkeycode(struct input_dev *dev, ...@@ -716,53 +779,86 @@ static int input_default_setkeycode(struct input_dev *dev,
/** /**
* input_get_keycode - retrieve keycode currently mapped to a given scancode * input_get_keycode - retrieve keycode currently mapped to a given scancode
* @dev: input device which keymap is being queried * @dev: input device which keymap is being queried
* @scancode: scancode (or its equivalent for device in question) for which * @ke: keymap entry
* keycode is needed
* @keycode: result
* *
* This function should be called by anyone interested in retrieving current * This function should be called by anyone interested in retrieving current
* keymap. Presently keyboard and evdev handlers use it. * keymap. Presently evdev handlers use it.
*/ */
int input_get_keycode(struct input_dev *dev, int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke)
unsigned int scancode, unsigned int *keycode)
{ {
unsigned long flags; unsigned long flags;
int retval; int retval;
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
retval = dev->getkeycode(dev, scancode, keycode);
spin_unlock_irqrestore(&dev->event_lock, flags);
if (dev->getkeycode) {
/*
* Support for legacy drivers, that don't implement the new
* ioctls
*/
u32 scancode = ke->index;
memcpy(ke->scancode, &scancode, sizeof(scancode));
ke->len = sizeof(scancode);
retval = dev->getkeycode(dev, scancode, &ke->keycode);
} else {
retval = dev->getkeycode_new(dev, ke);
}
spin_unlock_irqrestore(&dev->event_lock, flags);
return retval; return retval;
} }
EXPORT_SYMBOL(input_get_keycode); EXPORT_SYMBOL(input_get_keycode);
/** /**
* input_get_keycode - assign new keycode to a given scancode * input_set_keycode - attribute a keycode to a given scancode
* @dev: input device which keymap is being updated * @dev: input device which keymap is being updated
* @scancode: scancode (or its equivalent for device in question) * @ke: new keymap entry
* @keycode: new keycode to be assigned to the scancode
* *
* This function should be called by anyone needing to update current * This function should be called by anyone needing to update current
* keymap. Presently keyboard and evdev handlers use it. * keymap. Presently keyboard and evdev handlers use it.
*/ */
int input_set_keycode(struct input_dev *dev, int input_set_keycode(struct input_dev *dev,
unsigned int scancode, unsigned int keycode) const struct input_keymap_entry *ke)
{ {
unsigned long flags; unsigned long flags;
unsigned int old_keycode; unsigned int old_keycode;
int retval; int retval;
if (keycode > KEY_MAX) if (ke->keycode > KEY_MAX)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
retval = dev->getkeycode(dev, scancode, &old_keycode); if (dev->setkeycode) {
if (retval) /*
goto out; * Support for legacy drivers, that don't implement the new
* ioctls
*/
unsigned int scancode;
retval = input_scancode_to_scalar(ke, &scancode);
if (retval)
goto out;
/*
* We need to know the old scancode, in order to generate a
* keyup effect, if the set operation happens successfully
*/
if (!dev->getkeycode) {
retval = -EINVAL;
goto out;
}
retval = dev->getkeycode(dev, scancode, &old_keycode);
if (retval)
goto out;
retval = dev->setkeycode(dev, scancode, ke->keycode);
} else {
retval = dev->setkeycode_new(dev, ke, &old_keycode);
}
retval = dev->setkeycode(dev, scancode, keycode);
if (retval) if (retval)
goto out; goto out;
...@@ -1601,7 +1697,7 @@ EXPORT_SYMBOL(input_free_device); ...@@ -1601,7 +1697,7 @@ EXPORT_SYMBOL(input_free_device);
* *
* This function allocates all necessary memory for MT slot handling in the * This function allocates all necessary memory for MT slot handling in the
* input device, and adds ABS_MT_SLOT to the device capabilities. All slots * input device, and adds ABS_MT_SLOT to the device capabilities. All slots
* are initially marked as unused iby setting ABS_MT_TRACKING_ID to -1. * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1.
*/ */
int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots) int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
{ {
...@@ -1759,11 +1855,11 @@ int input_register_device(struct input_dev *dev) ...@@ -1759,11 +1855,11 @@ int input_register_device(struct input_dev *dev)
dev->rep[REP_PERIOD] = 33; dev->rep[REP_PERIOD] = 33;
} }
if (!dev->getkeycode) if (!dev->getkeycode && !dev->getkeycode_new)
dev->getkeycode = input_default_getkeycode; dev->getkeycode_new = input_default_getkeycode;
if (!dev->setkeycode) if (!dev->setkeycode && !dev->setkeycode_new)
dev->setkeycode = input_default_setkeycode; dev->setkeycode_new = input_default_setkeycode;
dev_set_name(&dev->dev, "input%ld", dev_set_name(&dev->dev, "input%ld",
(unsigned long) atomic_inc_return(&input_no) - 1); (unsigned long) atomic_inc_return(&input_no) - 1);
......
...@@ -327,6 +327,16 @@ config KEYBOARD_NEWTON ...@@ -327,6 +327,16 @@ config KEYBOARD_NEWTON
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 newtonkbd. module will be called newtonkbd.
config KEYBOARD_NOMADIK
tristate "ST-Ericsson Nomadik SKE keyboard"
depends on PLAT_NOMADIK
help
Say Y here if you want to use a keypad provided on the SKE controller
used on the Ux500 and Nomadik platforms
To compile this driver as a module, choose M here: the
module will be called nmk-ske-keypad.
config KEYBOARD_OPENCORES config KEYBOARD_OPENCORES
tristate "OpenCores Keyboard Controller" tristate "OpenCores Keyboard Controller"
help help
...@@ -424,6 +434,15 @@ config KEYBOARD_OMAP ...@@ -424,6 +434,15 @@ config KEYBOARD_OMAP
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 omap-keypad.
config KEYBOARD_OMAP4
tristate "TI OMAP4 keypad support"
depends on ARCH_OMAP4
help
Say Y here if you want to use the OMAP4 keypad.
To compile this driver as a module, choose M here: the
module will be called omap4-keypad.
config KEYBOARD_TWL4030 config KEYBOARD_TWL4030
tristate "TI TWL4030/TWL5030/TPS659x0 keypad support" tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
depends on TWL4030_CORE depends on TWL4030_CORE
......
...@@ -28,7 +28,9 @@ obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o ...@@ -28,7 +28,9 @@ obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o
obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
obj-$(CONFIG_KEYBOARD_OMAP4) += omap4-keypad.o
obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.o obj-$(CONFIG_KEYBOARD_OPENCORES) += opencores-kbd.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
......
...@@ -660,7 +660,7 @@ static const struct dev_pm_ops adp5588_dev_pm_ops = { ...@@ -660,7 +660,7 @@ static const struct dev_pm_ops adp5588_dev_pm_ops = {
#endif #endif
static const struct i2c_device_id adp5588_id[] = { static const struct i2c_device_id adp5588_id[] = {
{ KBUILD_MODNAME, 0 }, { "adp5588-keys", 0 },
{ "adp5587-keys", 0 }, { "adp5587-keys", 0 },
{ } { }
}; };
......
...@@ -570,6 +570,8 @@ static struct serio_device_id hil_dev_ids[] = { ...@@ -570,6 +570,8 @@ static struct serio_device_id hil_dev_ids[] = {
{ 0 } { 0 }
}; };
MODULE_DEVICE_TABLE(serio, hil_dev_ids);
static struct serio_driver hil_serio_drv = { static struct serio_driver hil_serio_drv = {
.driver = { .driver = {
.name = "hil_dev", .name = "hil_dev",
......
This diff is collapsed.
/*
* OMAP4 Keypad Driver
*
* Copyright (C) 2010 Texas Instruments
*
* Author: Abraham Arce <x0066660@ti.com>
* Initial Code: Syed Rafiuddin <rafiuddin.syed@ti.com>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/input.h>
#include <linux/slab.h>
#include <plat/omap4-keypad.h>
/* OMAP4 registers */
#define OMAP4_KBD_REVISION 0x00
#define OMAP4_KBD_SYSCONFIG 0x10
#define OMAP4_KBD_SYSSTATUS 0x14
#define OMAP4_KBD_IRQSTATUS 0x18
#define OMAP4_KBD_IRQENABLE 0x1C
#define OMAP4_KBD_WAKEUPENABLE 0x20
#define OMAP4_KBD_PENDING 0x24
#define OMAP4_KBD_CTRL 0x28
#define OMAP4_KBD_DEBOUNCINGTIME 0x2C
#define OMAP4_KBD_LONGKEYTIME 0x30
#define OMAP4_KBD_TIMEOUT 0x34
#define OMAP4_KBD_STATEMACHINE 0x38
#define OMAP4_KBD_ROWINPUTS 0x3C
#define OMAP4_KBD_COLUMNOUTPUTS 0x40
#define OMAP4_KBD_FULLCODE31_0 0x44
#define OMAP4_KBD_FULLCODE63_32 0x48
/* OMAP4 bit definitions */
#define OMAP4_DEF_IRQENABLE_EVENTEN (1 << 0)
#define OMAP4_DEF_IRQENABLE_LONGKEY (1 << 1)
#define OMAP4_DEF_IRQENABLE_TIMEOUTEN (1 << 2)
#define OMAP4_DEF_WUP_EVENT_ENA (1 << 0)
#define OMAP4_DEF_WUP_LONG_KEY_ENA (1 << 1)
#define OMAP4_DEF_CTRL_NOSOFTMODE (1 << 1)
#define OMAP4_DEF_CTRLPTVVALUE (1 << 2)
#define OMAP4_DEF_CTRLPTV (1 << 1)
/* OMAP4 values */
#define OMAP4_VAL_IRQDISABLE 0x00
#define OMAP4_VAL_DEBOUNCINGTIME 0x07
#define OMAP4_VAL_FUNCTIONALCFG 0x1E
#define OMAP4_MASK_IRQSTATUSDISABLE 0xFFFF
struct omap4_keypad {
struct input_dev *input;
void __iomem *base;
int irq;
unsigned int rows;
unsigned int cols;
unsigned int row_shift;
unsigned char key_state[8];
unsigned short keymap[];
};
static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data)
{
__raw_writel(OMAP4_VAL_FUNCTIONALCFG,
keypad_data->base + OMAP4_KBD_CTRL);
__raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
__raw_writel(OMAP4_VAL_IRQDISABLE,
keypad_data->base + OMAP4_KBD_IRQSTATUS);
__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
keypad_data->base + OMAP4_KBD_IRQENABLE);
__raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
}
/* Interrupt handler */
static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
{
struct omap4_keypad *keypad_data = dev_id;
struct input_dev *input_dev = keypad_data->input;
unsigned char key_state[ARRAY_SIZE(keypad_data->key_state)];
unsigned int col, row, code, changed;
u32 *new_state = (u32 *) key_state;
/* Disable interrupts */
__raw_writel(OMAP4_VAL_IRQDISABLE,
keypad_data->base + OMAP4_KBD_IRQENABLE);
*new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
*(new_state + 1) = __raw_readl(keypad_data->base
+ OMAP4_KBD_FULLCODE63_32);
for (row = 0; row < keypad_data->rows; row++) {
changed = key_state[row] ^ keypad_data->key_state[row];
if (!changed)
continue;
for (col = 0; col < keypad_data->cols; col++) {
if (changed & (1 << col)) {
code = MATRIX_SCAN_CODE(row, col,
keypad_data->row_shift);
input_event(input_dev, EV_MSC, MSC_SCAN, code);
input_report_key(input_dev,
keypad_data->keymap[code],
key_state[row] & (1 << col));
}
}
}
input_sync(input_dev);
memcpy(keypad_data->key_state, key_state,
sizeof(keypad_data->key_state));
/* clear pending interrupts */
__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
keypad_data->base + OMAP4_KBD_IRQSTATUS);
/* enable interrupts */
__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
keypad_data->base + OMAP4_KBD_IRQENABLE);
return IRQ_HANDLED;
}
static int __devinit omap4_keypad_probe(struct platform_device *pdev)
{
const struct omap4_keypad_platform_data *pdata;
struct omap4_keypad *keypad_data;
struct input_dev *input_dev;
struct resource *res;
resource_size_t size;
unsigned int row_shift, max_keys;
int irq;
int error;
/* platform data */
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "no platform data defined\n");
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no base address specified\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0);
if (!irq) {
dev_err(&pdev->dev, "no keyboard irq assigned\n");
return -EINVAL;
}
if (!pdata->keymap_data) {
dev_err(&pdev->dev, "no keymap data defined\n");
return -EINVAL;
}
row_shift = get_count_order(pdata->cols);
max_keys = pdata->rows << row_shift;
keypad_data = kzalloc(sizeof(struct omap4_keypad) +
max_keys * sizeof(keypad_data->keymap[0]),
GFP_KERNEL);
if (!keypad_data) {
dev_err(&pdev->dev, "keypad_data memory allocation failed\n");
return -ENOMEM;
}
size = resource_size(res);
res = request_mem_region(res->start, size, pdev->name);
if (!res) {
dev_err(&pdev->dev, "can't request mem region\n");
error = -EBUSY;
goto err_free_keypad;
}
keypad_data->base = ioremap(res->start, resource_size(res));
if (!keypad_data->base) {
dev_err(&pdev->dev, "can't ioremap mem resource\n");
error = -ENOMEM;
goto err_release_mem;
}
keypad_data->irq = irq;
keypad_data->row_shift = row_shift;
keypad_data->rows = pdata->rows;
keypad_data->cols = pdata->cols;
/* input device allocation */
keypad_data->input = input_dev = input_allocate_device();
if (!input_dev) {
error = -ENOMEM;
goto err_unmap;
}
input_dev->name = pdev->name;
input_dev->dev.parent = &pdev->dev;
input_dev->id.bustype = BUS_HOST;
input_dev->id.vendor = 0x0001;
input_dev->id.product = 0x0001;
input_dev->id.version = 0x0001;
input_dev->keycode = keypad_data->keymap;
input_dev->keycodesize = sizeof(keypad_data->keymap[0]);
input_dev->keycodemax = max_keys;
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(EV_REP, input_dev->evbit);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);
input_set_drvdata(input_dev, keypad_data);
matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
input_dev->keycode, input_dev->keybit);
omap4_keypad_config(keypad_data);
error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
IRQF_TRIGGER_RISING,
"omap4-keypad", keypad_data);
if (error) {
dev_err(&pdev->dev, "failed to register interrupt\n");
goto err_free_input;
}
error = input_register_device(keypad_data->input);
if (error < 0) {
dev_err(&pdev->dev, "failed to register input device\n");
goto err_free_irq;
}
platform_set_drvdata(pdev, keypad_data);
return 0;
err_free_irq:
free_irq(keypad_data->irq, keypad_data);
err_free_input:
input_free_device(input_dev);
err_unmap:
iounmap(keypad_data->base);
err_release_mem:
release_mem_region(res->start, size);
err_free_keypad:
kfree(keypad_data);
return error;
}
static int __devexit omap4_keypad_remove(struct platform_device *pdev)
{
struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
struct resource *res;
free_irq(keypad_data->irq, keypad_data);
input_unregister_device(keypad_data->input);
iounmap(keypad_data->base);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
kfree(keypad_data);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver omap4_keypad_driver = {
.probe = omap4_keypad_probe,
.remove = __devexit_p(omap4_keypad_remove),
.driver = {
.name = "omap4-keypad",
.owner = THIS_MODULE,
},
};
static int __init omap4_keypad_init(void)
{
return platform_driver_register(&omap4_keypad_driver);
}
module_init(omap4_keypad_init);
static void __exit omap4_keypad_exit(void)
{
platform_driver_unregister(&omap4_keypad_driver);
}
module_exit(omap4_keypad_exit);
MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("OMAP4 Keypad Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:omap4-keypad");
...@@ -406,23 +406,22 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev) ...@@ -406,23 +406,22 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev)
if (error) { if (error) {
dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n", dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n",
kp->irq); kp->irq);
goto err3; goto err2;
} }
/* Enable KP and TO interrupts now. */ /* Enable KP and TO interrupts now. */
reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO); reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO);
if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) { if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) {
error = -EIO; error = -EIO;
goto err4; goto err3;
} }
platform_set_drvdata(pdev, kp); platform_set_drvdata(pdev, kp);
return 0; return 0;
err4: err3:
/* mask all events - we don't care about the result */ /* mask all events - we don't care about the result */
(void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1); (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1);
err3:
free_irq(kp->irq, NULL); free_irq(kp->irq, NULL);
err2: err2:
input_unregister_device(input); input_unregister_device(input);
......
...@@ -22,6 +22,16 @@ config INPUT_88PM860X_ONKEY ...@@ -22,6 +22,16 @@ config INPUT_88PM860X_ONKEY
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called 88pm860x_onkey. will be called 88pm860x_onkey.
config INPUT_AB8500_PONKEY
tristate "AB8500 Pon (PowerOn) Key"
depends on AB8500_CORE
help
Say Y here to use the PowerOn Key for ST-Ericsson's AB8500
Mix-Sig PMIC.
To compile this driver as a module, choose M here: the module
will be called ab8500-ponkey.
config INPUT_AD714X config INPUT_AD714X
tristate "Analog Devices AD714x Capacitance Touch Sensor" tristate "Analog Devices AD714x Capacitance Touch Sensor"
help help
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
# Each configuration option enables a list of files. # Each configuration option enables a list of files.
obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o
obj-$(CONFIG_INPUT_AB8500_PONKEY) += ab8500-ponkey.o
obj-$(CONFIG_INPUT_AD714X) += ad714x.o obj-$(CONFIG_INPUT_AD714X) += ad714x.o
obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o obj-$(CONFIG_INPUT_AD714X_I2C) += ad714x-i2c.o
obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o obj-$(CONFIG_INPUT_AD714X_SPI) += ad714x-spi.o
......
/*
* Copyright (C) ST-Ericsson SA 2010
*
* License Terms: GNU General Public License v2
* Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
*
* AB8500 Power-On Key handler
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/mfd/ab8500.h>
#include <linux/slab.h>
/**
* struct ab8500_ponkey - ab8500 ponkey information
* @input_dev: pointer to input device
* @ab8500: ab8500 parent
* @irq_dbf: irq number for falling transition
* @irq_dbr: irq number for rising transition
*/
struct ab8500_ponkey {
struct input_dev *idev;
struct ab8500 *ab8500;
int irq_dbf;
int irq_dbr;
};
/* AB8500 gives us an interrupt when ONKEY is held */
static irqreturn_t ab8500_ponkey_handler(int irq, void *data)
{
struct ab8500_ponkey *ponkey = data;
if (irq == ponkey->irq_dbf)
input_report_key(ponkey->idev, KEY_POWER, true);
else if (irq == ponkey->irq_dbr)
input_report_key(ponkey->idev, KEY_POWER, false);
input_sync(ponkey->idev);
return IRQ_HANDLED;
}
static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)
{
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct ab8500_ponkey *ponkey;
struct input_dev *input;
int irq_dbf, irq_dbr;
int error;
irq_dbf = platform_get_irq_byname(pdev, "ONKEY_DBF");
if (irq_dbf < 0) {
dev_err(&pdev->dev, "No IRQ for ONKEY_DBF, error=%d\n", irq_dbf);
return irq_dbf;
}
irq_dbr = platform_get_irq_byname(pdev, "ONKEY_DBR");
if (irq_dbr < 0) {
dev_err(&pdev->dev, "No IRQ for ONKEY_DBR, error=%d\n", irq_dbr);
return irq_dbr;
}
ponkey = kzalloc(sizeof(struct ab8500_ponkey), GFP_KERNEL);
input = input_allocate_device();
if (!ponkey || !input) {
error = -ENOMEM;
goto err_free_mem;
}
ponkey->idev = input;
ponkey->ab8500 = ab8500;
ponkey->irq_dbf = irq_dbf;
ponkey->irq_dbr = irq_dbr;
input->name = "AB8500 POn(PowerOn) Key";
input->dev.parent = &pdev->dev;
input_set_capability(input, EV_KEY, KEY_POWER);
error = request_any_context_irq(ponkey->irq_dbf, ab8500_ponkey_handler,
0, "ab8500-ponkey-dbf", ponkey);
if (error < 0) {
dev_err(ab8500->dev, "Failed to request dbf IRQ#%d: %d\n",
ponkey->irq_dbf, error);
goto err_free_mem;
}
error = request_any_context_irq(ponkey->irq_dbr, ab8500_ponkey_handler,
0, "ab8500-ponkey-dbr", ponkey);
if (error < 0) {
dev_err(ab8500->dev, "Failed to request dbr IRQ#%d: %d\n",
ponkey->irq_dbr, error);
goto err_free_dbf_irq;
}
error = input_register_device(ponkey->idev);
if (error) {
dev_err(ab8500->dev, "Can't register input device: %d\n", error);
goto err_free_dbr_irq;
}
platform_set_drvdata(pdev, ponkey);
return 0;
err_free_dbr_irq:
free_irq(ponkey->irq_dbr, ponkey);
err_free_dbf_irq:
free_irq(ponkey->irq_dbf, ponkey);
err_free_mem:
input_free_device(input);
kfree(ponkey);
return error;
}
static int __devexit ab8500_ponkey_remove(struct platform_device *pdev)
{
struct ab8500_ponkey *ponkey = platform_get_drvdata(pdev);
free_irq(ponkey->irq_dbf, ponkey);
free_irq(ponkey->irq_dbr, ponkey);
input_unregister_device(ponkey->idev);
kfree(ponkey);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver ab8500_ponkey_driver = {
.driver = {
.name = "ab8500-poweron-key",
.owner = THIS_MODULE,
},
.probe = ab8500_ponkey_probe,
.remove = __devexit_p(ab8500_ponkey_remove),
};
static int __init ab8500_ponkey_init(void)
{
return platform_driver_register(&ab8500_ponkey_driver);
}
module_init(ab8500_ponkey_init);
static void __exit ab8500_ponkey_exit(void)
{
platform_driver_unregister(&ab8500_ponkey_driver);
}
module_exit(ab8500_ponkey_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>");
MODULE_DESCRIPTION("ST-Ericsson AB8500 Power-ON(Pon) Key driver");
...@@ -483,51 +483,88 @@ static void ati_remote2_complete_key(struct urb *urb) ...@@ -483,51 +483,88 @@ static void ati_remote2_complete_key(struct urb *urb)
} }
static int ati_remote2_getkeycode(struct input_dev *idev, static int ati_remote2_getkeycode(struct input_dev *idev,
unsigned int scancode, unsigned int *keycode) struct input_keymap_entry *ke)
{ {
struct ati_remote2 *ar2 = input_get_drvdata(idev); struct ati_remote2 *ar2 = input_get_drvdata(idev);
unsigned int mode; unsigned int mode;
int index; int offset;
unsigned int index;
unsigned int scancode;
if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
index = ke->index;
if (index >= ATI_REMOTE2_MODES *
ARRAY_SIZE(ati_remote2_key_table))
return -EINVAL;
mode = ke->index / ARRAY_SIZE(ati_remote2_key_table);
offset = ke->index % ARRAY_SIZE(ati_remote2_key_table);
scancode = (mode << 8) + ati_remote2_key_table[offset].hw_code;
} else {
if (input_scancode_to_scalar(ke, &scancode))
return -EINVAL;
mode = scancode >> 8;
if (mode > ATI_REMOTE2_PC)
return -EINVAL;
offset = ati_remote2_lookup(scancode & 0xff);
if (offset < 0)
return -EINVAL;
index = mode * ARRAY_SIZE(ati_remote2_key_table) + offset;
}
mode = scancode >> 8; ke->keycode = ar2->keycode[mode][offset];
if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) ke->len = sizeof(scancode);
return -EINVAL; memcpy(&ke->scancode, &scancode, sizeof(scancode));
ke->index = index;
index = ati_remote2_lookup(scancode & 0xFF);
if (index < 0)
return -EINVAL;
*keycode = ar2->keycode[mode][index];
return 0; return 0;
} }
static int ati_remote2_setkeycode(struct input_dev *idev, static int ati_remote2_setkeycode(struct input_dev *idev,
unsigned int scancode, unsigned int keycode) const struct input_keymap_entry *ke,
unsigned int *old_keycode)
{ {
struct ati_remote2 *ar2 = input_get_drvdata(idev); struct ati_remote2 *ar2 = input_get_drvdata(idev);
unsigned int mode, old_keycode; unsigned int mode;
int index; int offset;
unsigned int index;
mode = scancode >> 8; unsigned int scancode;
if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask))
return -EINVAL; if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
if (ke->index >= ATI_REMOTE2_MODES *
index = ati_remote2_lookup(scancode & 0xFF); ARRAY_SIZE(ati_remote2_key_table))
if (index < 0) return -EINVAL;
return -EINVAL;
mode = ke->index / ARRAY_SIZE(ati_remote2_key_table);
offset = ke->index % ARRAY_SIZE(ati_remote2_key_table);
} else {
if (input_scancode_to_scalar(ke, &scancode))
return -EINVAL;
mode = scancode >> 8;
if (mode > ATI_REMOTE2_PC)
return -EINVAL;
offset = ati_remote2_lookup(scancode & 0xff);
if (offset < 0)
return -EINVAL;
}
old_keycode = ar2->keycode[mode][index]; *old_keycode = ar2->keycode[mode][offset];
ar2->keycode[mode][index] = keycode; ar2->keycode[mode][offset] = ke->keycode;
__set_bit(keycode, idev->keybit); __set_bit(ke->keycode, idev->keybit);
for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) { for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) { for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
if (ar2->keycode[mode][index] == old_keycode) if (ar2->keycode[mode][index] == *old_keycode)
return 0; return 0;
} }
} }
__clear_bit(old_keycode, idev->keybit); __clear_bit(*old_keycode, idev->keybit);
return 0; return 0;
} }
...@@ -575,8 +612,8 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2) ...@@ -575,8 +612,8 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
idev->open = ati_remote2_open; idev->open = ati_remote2_open;
idev->close = ati_remote2_close; idev->close = ati_remote2_close;
idev->getkeycode = ati_remote2_getkeycode; idev->getkeycode_new = ati_remote2_getkeycode;
idev->setkeycode = ati_remote2_setkeycode; idev->setkeycode_new = ati_remote2_setkeycode;
idev->name = ar2->name; idev->name = ar2->name;
idev->phys = ar2->phys; idev->phys = ar2->phys;
......
...@@ -280,7 +280,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev ...@@ -280,7 +280,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL); pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL);
if (!pm->configcr) if (!pm->configcr)
return -1; return -ENOMEM;
return 0; return 0;
} }
......
...@@ -699,7 +699,7 @@ int elantech_init(struct psmouse *psmouse) ...@@ -699,7 +699,7 @@ int elantech_init(struct psmouse *psmouse)
psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL); psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
if (!etd) if (!etd)
return -1; return -ENOMEM;
etd->parity[0] = 1; etd->parity[0] = 1;
for (i = 1; i < 256; i++) for (i = 1; i < 256; i++)
......
...@@ -1584,10 +1584,10 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co ...@@ -1584,10 +1584,10 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
if (!new_dev) if (!new_dev)
return -ENOMEM; return -ENOMEM;
while (serio->child) { while (!list_empty(&serio->children)) {
if (++retry > 3) { if (++retry > 3) {
printk(KERN_WARNING printk(KERN_WARNING
"psmouse: failed to destroy child port, " "psmouse: failed to destroy children ports, "
"protocol change aborted.\n"); "protocol change aborted.\n");
input_free_device(new_dev); input_free_device(new_dev);
return -EIO; return -EIO;
......
...@@ -294,7 +294,29 @@ static int synaptics_pt_write(struct serio *serio, unsigned char c) ...@@ -294,7 +294,29 @@ static int synaptics_pt_write(struct serio *serio, unsigned char c)
return 0; return 0;
} }
static inline int synaptics_is_pt_packet(unsigned char *buf) static int synaptics_pt_start(struct serio *serio)
{
struct psmouse *parent = serio_get_drvdata(serio->parent);
struct synaptics_data *priv = parent->private;
serio_pause_rx(parent->ps2dev.serio);
priv->pt_port = serio;
serio_continue_rx(parent->ps2dev.serio);
return 0;
}
static void synaptics_pt_stop(struct serio *serio)
{
struct psmouse *parent = serio_get_drvdata(serio->parent);
struct synaptics_data *priv = parent->private;
serio_pause_rx(parent->ps2dev.serio);
priv->pt_port = NULL;
serio_continue_rx(parent->ps2dev.serio);
}
static int synaptics_is_pt_packet(unsigned char *buf)
{ {
return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
} }
...@@ -315,9 +337,8 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet ...@@ -315,9 +337,8 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
static void synaptics_pt_activate(struct psmouse *psmouse) static void synaptics_pt_activate(struct psmouse *psmouse)
{ {
struct serio *ptport = psmouse->ps2dev.serio->child;
struct psmouse *child = serio_get_drvdata(ptport);
struct synaptics_data *priv = psmouse->private; struct synaptics_data *priv = psmouse->private;
struct psmouse *child = serio_get_drvdata(priv->pt_port);
/* adjust the touchpad to child's choice of protocol */ /* adjust the touchpad to child's choice of protocol */
if (child) { if (child) {
...@@ -345,6 +366,8 @@ static void synaptics_pt_create(struct psmouse *psmouse) ...@@ -345,6 +366,8 @@ static void synaptics_pt_create(struct psmouse *psmouse)
strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name)); strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name)); strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
serio->write = synaptics_pt_write; serio->write = synaptics_pt_write;
serio->start = synaptics_pt_start;
serio->stop = synaptics_pt_stop;
serio->parent = psmouse->ps2dev.serio; serio->parent = psmouse->ps2dev.serio;
psmouse->pt_activate = synaptics_pt_activate; psmouse->pt_activate = synaptics_pt_activate;
...@@ -578,9 +601,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse) ...@@ -578,9 +601,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
if (unlikely(priv->pkt_type == SYN_NEWABS)) if (unlikely(priv->pkt_type == SYN_NEWABS))
priv->pkt_type = synaptics_detect_pkt_type(psmouse); priv->pkt_type = synaptics_detect_pkt_type(psmouse);
if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) { if (SYN_CAP_PASS_THROUGH(priv->capabilities) &&
if (psmouse->ps2dev.serio->child) synaptics_is_pt_packet(psmouse->packet)) {
synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet); if (priv->pt_port)
synaptics_pass_pt_packet(priv->pt_port, psmouse->packet);
} else } else
synaptics_process_packet(psmouse); synaptics_process_packet(psmouse);
...@@ -731,7 +755,7 @@ int synaptics_init(struct psmouse *psmouse) ...@@ -731,7 +755,7 @@ int synaptics_init(struct psmouse *psmouse)
psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL); psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
if (!priv) if (!priv)
return -1; return -ENOMEM;
psmouse_reset(psmouse); psmouse_reset(psmouse);
......
...@@ -110,6 +110,8 @@ struct synaptics_data { ...@@ -110,6 +110,8 @@ struct synaptics_data {
unsigned char pkt_type; /* packet type - old, new, etc */ unsigned char pkt_type; /* packet type - old, new, etc */
unsigned char mode; /* current mode byte */ unsigned char mode; /* current mode byte */
int scroll; int scroll;
struct serio *pt_port; /* Pass-through serio port */
}; };
void synaptics_module_init(void); void synaptics_module_init(void);
......
...@@ -303,7 +303,7 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) ...@@ -303,7 +303,7 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
if (!psmouse->private) if (!psmouse->private)
return -1; return -ENOMEM;
psmouse->vendor = "IBM"; psmouse->vendor = "IBM";
psmouse->name = "TrackPoint"; psmouse->name = "TrackPoint";
......
...@@ -866,7 +866,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev, ...@@ -866,7 +866,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
spin_lock_init(&mousedev->client_lock); spin_lock_init(&mousedev->client_lock);
mutex_init(&mousedev->mutex); mutex_init(&mousedev->mutex);
lockdep_set_subclass(&mousedev->mutex, lockdep_set_subclass(&mousedev->mutex,
minor == MOUSEDEV_MIX ? MOUSEDEV_MIX : 0); minor == MOUSEDEV_MIX ? SINGLE_DEPTH_NESTING : 0);
init_waitqueue_head(&mousedev->wait); init_waitqueue_head(&mousedev->wait);
if (minor == MOUSEDEV_MIX) if (minor == MOUSEDEV_MIX)
......
...@@ -226,4 +226,13 @@ config SERIO_AMS_DELTA ...@@ -226,4 +226,13 @@ config SERIO_AMS_DELTA
To compile this driver as a module, choose M here; To compile this driver as a module, choose M here;
the module will be called ams_delta_serio. the module will be called ams_delta_serio.
config SERIO_PS2MULT
tristate "TQC PS/2 multiplexer"
help
Say Y here if you have the PS/2 line multiplexer like the one
present on TQC boads.
To compile this driver as a module, choose M here: the
module will be called ps2mult.
endif endif
...@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o ...@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIO_GSCPS2) += gscps2.o
obj-$(CONFIG_HP_SDC) += hp_sdc.o obj-$(CONFIG_HP_SDC) += hp_sdc.o
obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o obj-$(CONFIG_HIL_MLC) += hp_sdc_mlc.o hil_mlc.o
obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o obj-$(CONFIG_SERIO_PCIPS2) += pcips2.o
obj-$(CONFIG_SERIO_PS2MULT) += ps2mult.o
obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o
obj-$(CONFIG_SERIO_LIBPS2) += libps2.o obj-$(CONFIG_SERIO_LIBPS2) += libps2.o
obj-$(CONFIG_SERIO_RAW) += serio_raw.o obj-$(CONFIG_SERIO_RAW) += serio_raw.o
......
...@@ -1063,7 +1063,7 @@ static long i8042_panic_blink(int state) ...@@ -1063,7 +1063,7 @@ static long i8042_panic_blink(int state)
#ifdef CONFIG_X86 #ifdef CONFIG_X86
static void i8042_dritek_enable(void) static void i8042_dritek_enable(void)
{ {
char param = 0x90; unsigned char param = 0x90;
int error; int error;
error = i8042_command(&param, 0x1059); error = i8042_command(&param, 0x1059);
......
/*
* TQC PS/2 Multiplexer driver
*
* Copyright (C) 2010 Dmitry Eremin-Solenikov
*
* 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/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/serio.h>
MODULE_AUTHOR("Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>");
MODULE_DESCRIPTION("TQC PS/2 Multiplexer driver");
MODULE_LICENSE("GPL");
#define PS2MULT_KB_SELECTOR 0xA0
#define PS2MULT_MS_SELECTOR 0xA1
#define PS2MULT_ESCAPE 0x7D
#define PS2MULT_BSYNC 0x7E
#define PS2MULT_SESSION_START 0x55
#define PS2MULT_SESSION_END 0x56
struct ps2mult_port {
struct serio *serio;
unsigned char sel;
bool registered;
};
#define PS2MULT_NUM_PORTS 2
#define PS2MULT_KBD_PORT 0
#define PS2MULT_MOUSE_PORT 1
struct ps2mult {
struct serio *mx_serio;
struct ps2mult_port ports[PS2MULT_NUM_PORTS];
spinlock_t lock;
struct ps2mult_port *in_port;
struct ps2mult_port *out_port;
bool escape;
};
/* First MUST come PS2MULT_NUM_PORTS selectors */
static const unsigned char ps2mult_controls[] = {
PS2MULT_KB_SELECTOR, PS2MULT_MS_SELECTOR,
PS2MULT_ESCAPE, PS2MULT_BSYNC,
PS2MULT_SESSION_START, PS2MULT_SESSION_END,
};
static const struct serio_device_id ps2mult_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_PS2MULT,
.id = SERIO_ANY,
.extra = SERIO_ANY,
},
{ 0 }
};
MODULE_DEVICE_TABLE(serio, ps2mult_serio_ids);
static void ps2mult_select_port(struct ps2mult *psm, struct ps2mult_port *port)
{
struct serio *mx_serio = psm->mx_serio;
serio_write(mx_serio, port->sel);
psm->out_port = port;
dev_dbg(&mx_serio->dev, "switched to sel %02x\n", port->sel);
}
static int ps2mult_serio_write(struct serio *serio, unsigned char data)
{
struct serio *mx_port = serio->parent;
struct ps2mult *psm = serio_get_drvdata(mx_port);
struct ps2mult_port *port = serio->port_data;
bool need_escape;
unsigned long flags;
spin_lock_irqsave(&psm->lock, flags);
if (psm->out_port != port)
ps2mult_select_port(psm, port);
need_escape = memchr(ps2mult_controls, data, sizeof(ps2mult_controls));
dev_dbg(&serio->dev,
"write: %s%02x\n", need_escape ? "ESC " : "", data);
if (need_escape)
serio_write(mx_port, PS2MULT_ESCAPE);
serio_write(mx_port, data);
spin_unlock_irqrestore(&psm->lock, flags);
return 0;
}
static int ps2mult_serio_start(struct serio *serio)
{
struct ps2mult *psm = serio_get_drvdata(serio->parent);
struct ps2mult_port *port = serio->port_data;
unsigned long flags;
spin_lock_irqsave(&psm->lock, flags);
port->registered = true;
spin_unlock_irqrestore(&psm->lock, flags);
return 0;
}
static void ps2mult_serio_stop(struct serio *serio)
{
struct ps2mult *psm = serio_get_drvdata(serio->parent);
struct ps2mult_port *port = serio->port_data;
unsigned long flags;
spin_lock_irqsave(&psm->lock, flags);
port->registered = false;
spin_unlock_irqrestore(&psm->lock, flags);
}
static int ps2mult_create_port(struct ps2mult *psm, int i)
{
struct serio *mx_serio = psm->mx_serio;
struct serio *serio;
serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (!serio)
return -ENOMEM;
strlcpy(serio->name, "TQC PS/2 Multiplexer", sizeof(serio->name));
snprintf(serio->phys, sizeof(serio->phys),
"%s/port%d", mx_serio->phys, i);
serio->id.type = SERIO_8042;
serio->write = ps2mult_serio_write;
serio->start = ps2mult_serio_start;
serio->stop = ps2mult_serio_stop;
serio->parent = psm->mx_serio;
serio->port_data = &psm->ports[i];
psm->ports[i].serio = serio;
return 0;
}
static void ps2mult_reset(struct ps2mult *psm)
{
unsigned long flags;
spin_lock_irqsave(&psm->lock, flags);
serio_write(psm->mx_serio, PS2MULT_SESSION_END);
serio_write(psm->mx_serio, PS2MULT_SESSION_START);
ps2mult_select_port(psm, &psm->ports[PS2MULT_KBD_PORT]);
spin_unlock_irqrestore(&psm->lock, flags);
}
static int ps2mult_connect(struct serio *serio, struct serio_driver *drv)
{
struct ps2mult *psm;
int i;
int error;
if (!serio->write)
return -EINVAL;
psm = kzalloc(sizeof(*psm), GFP_KERNEL);
if (!psm)
return -ENOMEM;
spin_lock_init(&psm->lock);
psm->mx_serio = serio;
for (i = 0; i < PS2MULT_NUM_PORTS; i++) {
psm->ports[i].sel = ps2mult_controls[i];
error = ps2mult_create_port(psm, i);
if (error)
goto err_out;
}
psm->in_port = psm->out_port = &psm->ports[PS2MULT_KBD_PORT];
serio_set_drvdata(serio, psm);
error = serio_open(serio, drv);
if (error)
goto err_out;
ps2mult_reset(psm);
for (i = 0; i < PS2MULT_NUM_PORTS; i++) {
struct serio *s = psm->ports[i].serio;
dev_info(&serio->dev, "%s port at %s\n", s->name, serio->phys);
serio_register_port(s);
}
return 0;
err_out:
while (--i >= 0)
kfree(psm->ports[i].serio);
kfree(serio);
return error;
}
static void ps2mult_disconnect(struct serio *serio)
{
struct ps2mult *psm = serio_get_drvdata(serio);
/* Note that serio core already take care of children ports */
serio_write(serio, PS2MULT_SESSION_END);
serio_close(serio);
kfree(psm);
serio_set_drvdata(serio, NULL);
}
static int ps2mult_reconnect(struct serio *serio)
{
struct ps2mult *psm = serio_get_drvdata(serio);
ps2mult_reset(psm);
return 0;
}
static irqreturn_t ps2mult_interrupt(struct serio *serio,
unsigned char data, unsigned int dfl)
{
struct ps2mult *psm = serio_get_drvdata(serio);
struct ps2mult_port *in_port;
unsigned long flags;
dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, dfl);
spin_lock_irqsave(&psm->lock, flags);
if (psm->escape) {
psm->escape = false;
in_port = psm->in_port;
if (in_port->registered)
serio_interrupt(in_port->serio, data, dfl);
goto out;
}
switch (data) {
case PS2MULT_ESCAPE:
dev_dbg(&serio->dev, "ESCAPE\n");
psm->escape = true;
break;
case PS2MULT_BSYNC:
dev_dbg(&serio->dev, "BSYNC\n");
psm->in_port = psm->out_port;
break;
case PS2MULT_SESSION_START:
dev_dbg(&serio->dev, "SS\n");
break;
case PS2MULT_SESSION_END:
dev_dbg(&serio->dev, "SE\n");
break;
case PS2MULT_KB_SELECTOR:
dev_dbg(&serio->dev, "KB\n");
psm->in_port = &psm->ports[PS2MULT_KBD_PORT];
break;
case PS2MULT_MS_SELECTOR:
dev_dbg(&serio->dev, "MS\n");
psm->in_port = &psm->ports[PS2MULT_MOUSE_PORT];
break;
default:
in_port = psm->in_port;
if (in_port->registered)
serio_interrupt(in_port->serio, data, dfl);
break;
}
out:
spin_unlock_irqrestore(&psm->lock, flags);
return IRQ_HANDLED;
}
static struct serio_driver ps2mult_drv = {
.driver = {
.name = "ps2mult",
},
.description = "TQC PS/2 Multiplexer driver",
.id_table = ps2mult_serio_ids,
.interrupt = ps2mult_interrupt,
.connect = ps2mult_connect,
.disconnect = ps2mult_disconnect,
.reconnect = ps2mult_reconnect,
};
static int __init ps2mult_init(void)
{
return serio_register_driver(&ps2mult_drv);
}
static void __exit ps2mult_exit(void)
{
serio_unregister_driver(&ps2mult_drv);
}
module_init(ps2mult_init);
module_exit(ps2mult_exit);
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/freezer.h>
MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Serio abstraction core"); MODULE_DESCRIPTION("Serio abstraction core");
...@@ -56,7 +55,7 @@ static struct bus_type serio_bus; ...@@ -56,7 +55,7 @@ static struct bus_type serio_bus;
static void serio_add_port(struct serio *serio); static void serio_add_port(struct serio *serio);
static int serio_reconnect_port(struct serio *serio); static int serio_reconnect_port(struct serio *serio);
static void serio_disconnect_port(struct serio *serio); static void serio_disconnect_port(struct serio *serio);
static void serio_reconnect_chain(struct serio *serio); static void serio_reconnect_subtree(struct serio *serio);
static void serio_attach_driver(struct serio_driver *drv); static void serio_attach_driver(struct serio_driver *drv);
static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
...@@ -152,7 +151,7 @@ static void serio_find_driver(struct serio *serio) ...@@ -152,7 +151,7 @@ static void serio_find_driver(struct serio *serio)
enum serio_event_type { enum serio_event_type {
SERIO_RESCAN_PORT, SERIO_RESCAN_PORT,
SERIO_RECONNECT_PORT, SERIO_RECONNECT_PORT,
SERIO_RECONNECT_CHAIN, SERIO_RECONNECT_SUBTREE,
SERIO_REGISTER_PORT, SERIO_REGISTER_PORT,
SERIO_ATTACH_DRIVER, SERIO_ATTACH_DRIVER,
}; };
...@@ -292,8 +291,8 @@ static void serio_handle_event(void) ...@@ -292,8 +291,8 @@ static void serio_handle_event(void)
serio_find_driver(event->object); serio_find_driver(event->object);
break; break;
case SERIO_RECONNECT_CHAIN: case SERIO_RECONNECT_SUBTREE:
serio_reconnect_chain(event->object); serio_reconnect_subtree(event->object);
break; break;
case SERIO_ATTACH_DRIVER: case SERIO_ATTACH_DRIVER:
...@@ -330,12 +329,10 @@ static void serio_remove_pending_events(void *object) ...@@ -330,12 +329,10 @@ static void serio_remove_pending_events(void *object)
} }
/* /*
* Destroy child serio port (if any) that has not been fully registered yet. * Locate child serio port (if any) that has not been fully registered yet.
* *
* Note that we rely on the fact that port can have only one child and therefore * Children are registered by driver's connect() handler so there can't be a
* only one child registration request can be pending. Additionally, children * grandchild pending registration together with a child.
* are registered by driver's connect() handler so there can't be a grandchild
* pending registration together with a child.
*/ */
static struct serio *serio_get_pending_child(struct serio *parent) static struct serio *serio_get_pending_child(struct serio *parent)
{ {
...@@ -449,7 +446,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * ...@@ -449,7 +446,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
if (!strncmp(buf, "none", count)) { if (!strncmp(buf, "none", count)) {
serio_disconnect_port(serio); serio_disconnect_port(serio);
} else if (!strncmp(buf, "reconnect", count)) { } else if (!strncmp(buf, "reconnect", count)) {
serio_reconnect_chain(serio); serio_reconnect_subtree(serio);
} else if (!strncmp(buf, "rescan", count)) { } else if (!strncmp(buf, "rescan", count)) {
serio_disconnect_port(serio); serio_disconnect_port(serio);
serio_find_driver(serio); serio_find_driver(serio);
...@@ -516,6 +513,8 @@ static void serio_init_port(struct serio *serio) ...@@ -516,6 +513,8 @@ static void serio_init_port(struct serio *serio)
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
INIT_LIST_HEAD(&serio->node); INIT_LIST_HEAD(&serio->node);
INIT_LIST_HEAD(&serio->child_node);
INIT_LIST_HEAD(&serio->children);
spin_lock_init(&serio->lock); spin_lock_init(&serio->lock);
mutex_init(&serio->drv_mutex); mutex_init(&serio->drv_mutex);
device_initialize(&serio->dev); device_initialize(&serio->dev);
...@@ -538,12 +537,13 @@ static void serio_init_port(struct serio *serio) ...@@ -538,12 +537,13 @@ static void serio_init_port(struct serio *serio)
*/ */
static void serio_add_port(struct serio *serio) static void serio_add_port(struct serio *serio)
{ {
struct serio *parent = serio->parent;
int error; int error;
if (serio->parent) { if (parent) {
serio_pause_rx(serio->parent); serio_pause_rx(parent);
serio->parent->child = serio; list_add_tail(&serio->child_node, &parent->children);
serio_continue_rx(serio->parent); serio_continue_rx(parent);
} }
list_add_tail(&serio->node, &serio_list); list_add_tail(&serio->node, &serio_list);
...@@ -559,15 +559,14 @@ static void serio_add_port(struct serio *serio) ...@@ -559,15 +559,14 @@ static void serio_add_port(struct serio *serio)
} }
/* /*
* serio_destroy_port() completes deregistration process and removes * serio_destroy_port() completes unregistration process and removes
* port from the system * port from the system
*/ */
static void serio_destroy_port(struct serio *serio) static void serio_destroy_port(struct serio *serio)
{ {
struct serio *child; struct serio *child;
child = serio_get_pending_child(serio); while ((child = serio_get_pending_child(serio)) != NULL) {
if (child) {
serio_remove_pending_events(child); serio_remove_pending_events(child);
put_device(&child->dev); put_device(&child->dev);
} }
...@@ -577,7 +576,7 @@ static void serio_destroy_port(struct serio *serio) ...@@ -577,7 +576,7 @@ static void serio_destroy_port(struct serio *serio)
if (serio->parent) { if (serio->parent) {
serio_pause_rx(serio->parent); serio_pause_rx(serio->parent);
serio->parent->child = NULL; list_del_init(&serio->child_node);
serio_continue_rx(serio->parent); serio_continue_rx(serio->parent);
serio->parent = NULL; serio->parent = NULL;
} }
...@@ -609,46 +608,82 @@ static int serio_reconnect_port(struct serio *serio) ...@@ -609,46 +608,82 @@ static int serio_reconnect_port(struct serio *serio)
} }
/* /*
* Reconnect serio port and all its children (re-initialize attached devices) * Reconnect serio port and all its children (re-initialize attached
* devices).
*/ */
static void serio_reconnect_chain(struct serio *serio) static void serio_reconnect_subtree(struct serio *root)
{ {
struct serio *s = root;
int error;
do { do {
if (serio_reconnect_port(serio)) { error = serio_reconnect_port(s);
/* Ok, old children are now gone, we are done */ if (!error) {
break; /*
* Reconnect was successful, move on to do the
* first child.
*/
if (!list_empty(&s->children)) {
s = list_first_entry(&s->children,
struct serio, child_node);
continue;
}
} }
serio = serio->child;
} while (serio); /*
* Either it was a leaf node or reconnect failed and it
* became a leaf node. Continue reconnecting starting with
* the next sibling of the parent node.
*/
while (s != root) {
struct serio *parent = s->parent;
if (!list_is_last(&s->child_node, &parent->children)) {
s = list_entry(s->child_node.next,
struct serio, child_node);
break;
}
s = parent;
}
} while (s != root);
} }
/* /*
* serio_disconnect_port() unbinds a port from its driver. As a side effect * serio_disconnect_port() unbinds a port from its driver. As a side effect
* all child ports are unbound and destroyed. * all children ports are unbound and destroyed.
*/ */
static void serio_disconnect_port(struct serio *serio) static void serio_disconnect_port(struct serio *serio)
{ {
struct serio *s, *parent; struct serio *s = serio;
/*
* Children ports should be disconnected and destroyed
* first; we travel the tree in depth-first order.
*/
while (!list_empty(&serio->children)) {
/* Locate a leaf */
while (!list_empty(&s->children))
s = list_first_entry(&s->children,
struct serio, child_node);
if (serio->child) {
/* /*
* Children ports should be disconnected and destroyed * Prune this leaf node unless it is the one we
* first, staring with the leaf one, since we don't want * started with.
* to do recursion
*/ */
for (s = serio; s->child; s = s->child) if (s != serio) {
/* empty */; struct serio *parent = s->parent;
do {
parent = s->parent;
device_release_driver(&s->dev); device_release_driver(&s->dev);
serio_destroy_port(s); serio_destroy_port(s);
} while ((s = parent) != serio);
s = parent;
}
} }
/* /*
* Ok, no children left, now disconnect this port * OK, no children left, now disconnect this port.
*/ */
device_release_driver(&serio->dev); device_release_driver(&serio->dev);
} }
...@@ -661,7 +696,7 @@ EXPORT_SYMBOL(serio_rescan); ...@@ -661,7 +696,7 @@ EXPORT_SYMBOL(serio_rescan);
void serio_reconnect(struct serio *serio) void serio_reconnect(struct serio *serio)
{ {
serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN); serio_queue_event(serio, NULL, SERIO_RECONNECT_SUBTREE);
} }
EXPORT_SYMBOL(serio_reconnect); EXPORT_SYMBOL(serio_reconnect);
...@@ -689,14 +724,16 @@ void serio_unregister_port(struct serio *serio) ...@@ -689,14 +724,16 @@ void serio_unregister_port(struct serio *serio)
EXPORT_SYMBOL(serio_unregister_port); EXPORT_SYMBOL(serio_unregister_port);
/* /*
* Safely unregisters child port if one is present. * Safely unregisters children ports if they are present.
*/ */
void serio_unregister_child_port(struct serio *serio) void serio_unregister_child_port(struct serio *serio)
{ {
struct serio *s, *next;
mutex_lock(&serio_mutex); mutex_lock(&serio_mutex);
if (serio->child) { list_for_each_entry_safe(s, next, &serio->children, child_node) {
serio_disconnect_port(serio->child); serio_disconnect_port(s);
serio_destroy_port(serio->child); serio_destroy_port(s);
} }
mutex_unlock(&serio_mutex); mutex_unlock(&serio_mutex);
} }
......
...@@ -22,6 +22,37 @@ MODULE_DESCRIPTION("Generic support for sparse keymaps"); ...@@ -22,6 +22,37 @@ MODULE_DESCRIPTION("Generic support for sparse keymaps");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_VERSION("0.1"); MODULE_VERSION("0.1");
static unsigned int sparse_keymap_get_key_index(struct input_dev *dev,
const struct key_entry *k)
{
struct key_entry *key;
unsigned int idx = 0;
for (key = dev->keycode; key->type != KE_END; key++) {
if (key->type == KE_KEY) {
if (key == k)
break;
idx++;
}
}
return idx;
}
static struct key_entry *sparse_keymap_entry_by_index(struct input_dev *dev,
unsigned int index)
{
struct key_entry *key;
unsigned int key_cnt = 0;
for (key = dev->keycode; key->type != KE_END; key++)
if (key->type == KE_KEY)
if (key_cnt++ == index)
return key;
return NULL;
}
/** /**
* sparse_keymap_entry_from_scancode - perform sparse keymap lookup * sparse_keymap_entry_from_scancode - perform sparse keymap lookup
* @dev: Input device using sparse keymap * @dev: Input device using sparse keymap
...@@ -64,16 +95,36 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev, ...@@ -64,16 +95,36 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
} }
EXPORT_SYMBOL(sparse_keymap_entry_from_keycode); EXPORT_SYMBOL(sparse_keymap_entry_from_keycode);
static struct key_entry *sparse_keymap_locate(struct input_dev *dev,
const struct input_keymap_entry *ke)
{
struct key_entry *key;
unsigned int scancode;
if (ke->flags & INPUT_KEYMAP_BY_INDEX)
key = sparse_keymap_entry_by_index(dev, ke->index);
else if (input_scancode_to_scalar(ke, &scancode) == 0)
key = sparse_keymap_entry_from_scancode(dev, scancode);
else
key = NULL;
return key;
}
static int sparse_keymap_getkeycode(struct input_dev *dev, static int sparse_keymap_getkeycode(struct input_dev *dev,
unsigned int scancode, struct input_keymap_entry *ke)
unsigned int *keycode)
{ {
const struct key_entry *key; const struct key_entry *key;
if (dev->keycode) { if (dev->keycode) {
key = sparse_keymap_entry_from_scancode(dev, scancode); key = sparse_keymap_locate(dev, ke);
if (key && key->type == KE_KEY) { if (key && key->type == KE_KEY) {
*keycode = key->keycode; ke->keycode = key->keycode;
if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
ke->index =
sparse_keymap_get_key_index(dev, key);
ke->len = sizeof(key->code);
memcpy(ke->scancode, &key->code, sizeof(key->code));
return 0; return 0;
} }
} }
...@@ -82,20 +133,19 @@ static int sparse_keymap_getkeycode(struct input_dev *dev, ...@@ -82,20 +133,19 @@ static int sparse_keymap_getkeycode(struct input_dev *dev,
} }
static int sparse_keymap_setkeycode(struct input_dev *dev, static int sparse_keymap_setkeycode(struct input_dev *dev,
unsigned int scancode, const struct input_keymap_entry *ke,
unsigned int keycode) unsigned int *old_keycode)
{ {
struct key_entry *key; struct key_entry *key;
int old_keycode;
if (dev->keycode) { if (dev->keycode) {
key = sparse_keymap_entry_from_scancode(dev, scancode); key = sparse_keymap_locate(dev, ke);
if (key && key->type == KE_KEY) { if (key && key->type == KE_KEY) {
old_keycode = key->keycode; *old_keycode = key->keycode;
key->keycode = keycode; key->keycode = ke->keycode;
set_bit(keycode, dev->keybit); set_bit(ke->keycode, dev->keybit);
if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) if (!sparse_keymap_entry_from_keycode(dev, *old_keycode))
clear_bit(old_keycode, dev->keybit); clear_bit(*old_keycode, dev->keybit);
return 0; return 0;
} }
} }
...@@ -159,15 +209,14 @@ int sparse_keymap_setup(struct input_dev *dev, ...@@ -159,15 +209,14 @@ int sparse_keymap_setup(struct input_dev *dev,
dev->keycode = map; dev->keycode = map;
dev->keycodemax = map_size; dev->keycodemax = map_size;
dev->getkeycode = sparse_keymap_getkeycode; dev->getkeycode_new = sparse_keymap_getkeycode;
dev->setkeycode = sparse_keymap_setkeycode; dev->setkeycode_new = sparse_keymap_setkeycode;
return 0; return 0;
err_out: err_out:
kfree(map); kfree(map);
return error; return error;
} }
EXPORT_SYMBOL(sparse_keymap_setup); EXPORT_SYMBOL(sparse_keymap_setup);
......
...@@ -49,6 +49,17 @@ config TABLET_USB_GTCO ...@@ -49,6 +49,17 @@ config TABLET_USB_GTCO
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 gtco. module will be called gtco.
config TABLET_USB_HANWANG
tristate "Hanwang Art Master III tablet support (USB)"
depends on USB_ARCH_HAS_HCD
select USB
help
Say Y here if you want to use the USB version of the Hanwang Art
Master III tablet.
To compile this driver as a module, choose M here: the
module will be called hanwang.
config TABLET_USB_KBTAB config TABLET_USB_KBTAB
tristate "KB Gear JamStudio tablet support (USB)" tristate "KB Gear JamStudio tablet support (USB)"
depends on USB_ARCH_HAS_HCD depends on USB_ARCH_HAS_HCD
......
...@@ -8,5 +8,6 @@ wacom-objs := wacom_wac.o wacom_sys.o ...@@ -8,5 +8,6 @@ wacom-objs := wacom_wac.o wacom_sys.o
obj-$(CONFIG_TABLET_USB_ACECAD) += acecad.o obj-$(CONFIG_TABLET_USB_ACECAD) += acecad.o
obj-$(CONFIG_TABLET_USB_AIPTEK) += aiptek.o obj-$(CONFIG_TABLET_USB_AIPTEK) += aiptek.o
obj-$(CONFIG_TABLET_USB_GTCO) += gtco.o obj-$(CONFIG_TABLET_USB_GTCO) += gtco.o
obj-$(CONFIG_TABLET_USB_HANWANG) += hanwang.o
obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o
obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o
This diff is collapsed.
...@@ -118,6 +118,7 @@ struct wacom { ...@@ -118,6 +118,7 @@ struct wacom {
extern const struct usb_device_id wacom_ids[]; extern const struct usb_device_id wacom_ids[];
void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
void wacom_setup_device_quirks(struct wacom_features *features);
void wacom_setup_input_capabilities(struct input_dev *input_dev, void wacom_setup_input_capabilities(struct input_dev *input_dev,
struct wacom_wac *wacom_wac); struct wacom_wac *wacom_wac);
#endif #endif
...@@ -120,14 +120,16 @@ static int wacom_open(struct input_dev *dev) ...@@ -120,14 +120,16 @@ static int wacom_open(struct input_dev *dev)
out: out:
mutex_unlock(&wacom->lock); mutex_unlock(&wacom->lock);
if (retval) usb_autopm_put_interface(wacom->intf);
usb_autopm_put_interface(wacom->intf);
return retval; return retval;
} }
static void wacom_close(struct input_dev *dev) static void wacom_close(struct input_dev *dev)
{ {
struct wacom *wacom = input_get_drvdata(dev); struct wacom *wacom = input_get_drvdata(dev);
int autopm_error;
autopm_error = usb_autopm_get_interface(wacom->intf);
mutex_lock(&wacom->lock); mutex_lock(&wacom->lock);
usb_kill_urb(wacom->irq); usb_kill_urb(wacom->irq);
...@@ -135,7 +137,8 @@ static void wacom_close(struct input_dev *dev) ...@@ -135,7 +137,8 @@ static void wacom_close(struct input_dev *dev)
wacom->intf->needs_remote_wakeup = 0; wacom->intf->needs_remote_wakeup = 0;
mutex_unlock(&wacom->lock); mutex_unlock(&wacom->lock);
usb_autopm_put_interface(wacom->intf); if (!autopm_error)
usb_autopm_put_interface(wacom->intf);
} }
static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
...@@ -196,17 +199,30 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi ...@@ -196,17 +199,30 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
features->pktlen = WACOM_PKGLEN_TPC2FG; features->pktlen = WACOM_PKGLEN_TPC2FG;
features->device_type = BTN_TOOL_TRIPLETAP; features->device_type = BTN_TOOL_TRIPLETAP;
} }
features->x_max = if (features->type == BAMBOO_PT) {
get_unaligned_le16(&report[i + 3]); /* need to reset back */
features->x_phy = features->pktlen = WACOM_PKGLEN_BBTOUCH;
get_unaligned_le16(&report[i + 6]); features->device_type = BTN_TOOL_TRIPLETAP;
features->unit = report[i + 9]; features->x_phy =
features->unitExpo = report[i + 11]; get_unaligned_le16(&report[i + 5]);
i += 12; features->x_max =
get_unaligned_le16(&report[i + 8]);
i += 15;
} else {
features->x_max =
get_unaligned_le16(&report[i + 3]);
features->x_phy =
get_unaligned_le16(&report[i + 6]);
features->unit = report[i + 9];
features->unitExpo = report[i + 11];
i += 12;
}
} else if (pen) { } else if (pen) {
/* penabled only accepts exact bytes of data */ /* penabled only accepts exact bytes of data */
if (features->type == TABLETPC2FG) if (features->type == TABLETPC2FG)
features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->pktlen = WACOM_PKGLEN_GRAPHIRE;
if (features->type == BAMBOO_PT)
features->pktlen = WACOM_PKGLEN_BBFUN;
features->device_type = BTN_TOOL_PEN; features->device_type = BTN_TOOL_PEN;
features->x_max = features->x_max =
get_unaligned_le16(&report[i + 3]); get_unaligned_le16(&report[i + 3]);
...@@ -235,6 +251,15 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi ...@@ -235,6 +251,15 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
features->y_phy = features->y_phy =
get_unaligned_le16(&report[i + 6]); get_unaligned_le16(&report[i + 6]);
i += 7; i += 7;
} else if (features->type == BAMBOO_PT) {
/* need to reset back */
features->pktlen = WACOM_PKGLEN_BBTOUCH;
features->device_type = BTN_TOOL_TRIPLETAP;
features->y_phy =
get_unaligned_le16(&report[i + 3]);
features->y_max =
get_unaligned_le16(&report[i + 6]);
i += 12;
} else { } else {
features->y_max = features->y_max =
features->x_max; features->x_max;
...@@ -246,6 +271,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi ...@@ -246,6 +271,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
/* penabled only accepts exact bytes of data */ /* penabled only accepts exact bytes of data */
if (features->type == TABLETPC2FG) if (features->type == TABLETPC2FG)
features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->pktlen = WACOM_PKGLEN_GRAPHIRE;
if (features->type == BAMBOO_PT)
features->pktlen = WACOM_PKGLEN_BBFUN;
features->device_type = BTN_TOOL_PEN; features->device_type = BTN_TOOL_PEN;
features->y_max = features->y_max =
get_unaligned_le16(&report[i + 3]); get_unaligned_le16(&report[i + 3]);
...@@ -296,8 +323,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat ...@@ -296,8 +323,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
if (!rep_data) if (!rep_data)
return error; return error;
/* ask to report tablet data if it is 2FGT or not a Tablet PC */ /* ask to report tablet data if it is 2FGT Tablet PC or
if (features->device_type == BTN_TOOL_TRIPLETAP) { * not a Tablet PC */
if (features->type == TABLETPC2FG) {
do { do {
rep_data[0] = 3; rep_data[0] = 3;
rep_data[1] = 4; rep_data[1] = 4;
...@@ -309,7 +337,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat ...@@ -309,7 +337,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
WAC_HID_FEATURE_REPORT, report_id, WAC_HID_FEATURE_REPORT, report_id,
rep_data, 3); rep_data, 3);
} while ((error < 0 || rep_data[1] != 4) && limit++ < 5); } while ((error < 0 || rep_data[1] != 4) && limit++ < 5);
} else if (features->type != TABLETPC && features->type != TABLETPC2FG) { } else if (features->type != TABLETPC) {
do { do {
rep_data[0] = 2; rep_data[0] = 2;
rep_data[1] = 2; rep_data[1] = 2;
...@@ -334,11 +362,16 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, ...@@ -334,11 +362,16 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
struct usb_host_interface *interface = intf->cur_altsetting; struct usb_host_interface *interface = intf->cur_altsetting;
struct hid_descriptor *hid_desc; struct hid_descriptor *hid_desc;
/* default device to penabled */ /* default features */
features->device_type = BTN_TOOL_PEN; features->device_type = BTN_TOOL_PEN;
features->x_fuzz = 4;
/* only Tablet PCs need to retrieve the info */ features->y_fuzz = 4;
if ((features->type != TABLETPC) && (features->type != TABLETPC2FG)) features->pressure_fuzz = 0;
features->distance_fuzz = 0;
/* only Tablet PCs and Bamboo P&T need to retrieve the info */
if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) &&
(features->type != BAMBOO_PT))
goto out; goto out;
if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
...@@ -353,12 +386,6 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, ...@@ -353,12 +386,6 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
if (error) if (error)
goto out; goto out;
/* touch device found but size is not defined. use default */
if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
features->x_max = 1023;
features->y_max = 1023;
}
out: out:
return error; return error;
} }
...@@ -494,9 +521,11 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -494,9 +521,11 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
if (error) if (error)
goto fail2; goto fail2;
wacom_setup_device_quirks(features);
strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
if (features->type == TABLETPC || features->type == TABLETPC2FG) { if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
/* Append the device type to the name */ /* Append the device type to the name */
strlcat(wacom_wac->name, strlcat(wacom_wac->name,
features->device_type == BTN_TOOL_PEN ? features->device_type == BTN_TOOL_PEN ?
......
This diff is collapsed.
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define WACOM_PKGLEN_INTUOS 10 #define WACOM_PKGLEN_INTUOS 10
#define WACOM_PKGLEN_TPC1FG 5 #define WACOM_PKGLEN_TPC1FG 5
#define WACOM_PKGLEN_TPC2FG 14 #define WACOM_PKGLEN_TPC2FG 14
#define WACOM_PKGLEN_BBTOUCH 20
/* device IDs */ /* device IDs */
#define STYLUS_DEVICE_ID 0x02 #define STYLUS_DEVICE_ID 0x02
...@@ -37,6 +38,13 @@ ...@@ -37,6 +38,13 @@
#define WACOM_REPORT_TPC1FG 6 #define WACOM_REPORT_TPC1FG 6
#define WACOM_REPORT_TPC2FG 13 #define WACOM_REPORT_TPC2FG 13
/* device quirks */
#define WACOM_QUIRK_MULTI_INPUT 0x0001
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0002
/* largest reported tracking id */
#define MAX_TRACKING_ID 0xfff
enum { enum {
PENPARTNER = 0, PENPARTNER = 0,
GRAPHIRE, GRAPHIRE,
...@@ -44,6 +52,7 @@ enum { ...@@ -44,6 +52,7 @@ enum {
PTU, PTU,
PL, PL,
DTU, DTU,
BAMBOO_PT,
INTUOS, INTUOS,
INTUOS3S, INTUOS3S,
INTUOS3, INTUOS3,
...@@ -73,6 +82,11 @@ struct wacom_features { ...@@ -73,6 +82,11 @@ struct wacom_features {
int y_phy; int y_phy;
unsigned char unit; unsigned char unit;
unsigned char unitExpo; unsigned char unitExpo;
int x_fuzz;
int y_fuzz;
int pressure_fuzz;
int distance_fuzz;
unsigned quirks;
}; };
struct wacom_shared { struct wacom_shared {
...@@ -86,6 +100,7 @@ struct wacom_wac { ...@@ -86,6 +100,7 @@ struct wacom_wac {
int id[3]; int id[3];
__u32 serial[2]; __u32 serial[2];
int last_finger; int last_finger;
int trk_id;
struct wacom_features features; struct wacom_features features;
struct wacom_shared *shared; struct wacom_shared *shared;
struct input_dev *input; struct input_dev *input;
......
...@@ -98,6 +98,18 @@ config TOUCHSCREEN_BITSY ...@@ -98,6 +98,18 @@ config TOUCHSCREEN_BITSY
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 h3600_ts_input. module will be called h3600_ts_input.
config TOUCHSCREEN_BU21013
tristate "BU21013 based touch panel controllers"
depends on I2C
help
Say Y here if you have a bu21013 touchscreen connected to
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called bu21013_ts.
config TOUCHSCREEN_CY8CTMG110 config TOUCHSCREEN_CY8CTMG110
tristate "cy8ctmg110 touchscreen" tristate "cy8ctmg110 touchscreen"
depends on I2C depends on I2C
...@@ -214,6 +226,16 @@ config TOUCHSCREEN_WACOM_W8001 ...@@ -214,6 +226,16 @@ config TOUCHSCREEN_WACOM_W8001
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 wacom_w8001. module will be called wacom_w8001.
config TOUCHSCREEN_LPC32XX
tristate "LPC32XX touchscreen controller"
depends on ARCH_LPC32XX
help
Say Y here if you have a LPC32XX device and want
to support the built-in touchscreen.
To compile this driver as a module, choose M here: the
module will be called lpc32xx_ts.
config TOUCHSCREEN_MCS5000 config TOUCHSCREEN_MCS5000
tristate "MELFAS MCS-5000 touchscreen" tristate "MELFAS MCS-5000 touchscreen"
depends on I2C depends on I2C
...@@ -250,6 +272,18 @@ config TOUCHSCREEN_INEXIO ...@@ -250,6 +272,18 @@ config TOUCHSCREEN_INEXIO
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 inexio. module will be called inexio.
config TOUCHSCREEN_INTEL_MID
tristate "Intel MID platform resistive touchscreen"
depends on INTEL_SCU_IPC
help
Say Y here if you have a Intel MID based touchscreen in
your system.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called intel_mid_touch.
config TOUCHSCREEN_MK712 config TOUCHSCREEN_MK712
tristate "ICS MicroClock MK712 touchscreen" tristate "ICS MicroClock MK712 touchscreen"
help help
......
...@@ -14,6 +14,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o ...@@ -14,6 +14,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
...@@ -23,6 +24,8 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o ...@@ -23,6 +24,8 @@ obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
......
...@@ -191,13 +191,12 @@ struct ad7877 { ...@@ -191,13 +191,12 @@ struct ad7877 {
struct spi_message msg; struct spi_message msg;
struct mutex mutex; struct mutex mutex;
unsigned disabled:1; /* P: mutex */ bool disabled; /* P: mutex */
unsigned gpio3:1; /* P: mutex */ bool gpio3; /* P: mutex */
unsigned gpio4:1; /* P: mutex */ bool gpio4; /* P: mutex */
spinlock_t lock; spinlock_t lock;
struct timer_list timer; /* P: lock */ struct timer_list timer; /* P: lock */
unsigned pending:1; /* P: lock */
/* /*
* DMA (thus cache coherency maintenance) requires the * DMA (thus cache coherency maintenance) requires the
...@@ -206,8 +205,8 @@ struct ad7877 { ...@@ -206,8 +205,8 @@ struct ad7877 {
u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned; u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned;
}; };
static int gpio3; static bool gpio3;
module_param(gpio3, int, 0); module_param(gpio3, bool, 0);
MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3"); MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3");
/* /*
...@@ -230,6 +229,7 @@ static int ad7877_read(struct spi_device *spi, u16 reg) ...@@ -230,6 +229,7 @@ static int ad7877_read(struct spi_device *spi, u16 reg)
AD7877_READADD(reg)); AD7877_READADD(reg));
req->xfer[0].tx_buf = &req->command; req->xfer[0].tx_buf = &req->command;
req->xfer[0].len = 2; req->xfer[0].len = 2;
req->xfer[0].cs_change = 1;
req->xfer[1].rx_buf = &req->sample; req->xfer[1].rx_buf = &req->sample;
req->xfer[1].len = 2; req->xfer[1].len = 2;
...@@ -295,20 +295,25 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command) ...@@ -295,20 +295,25 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command)
req->xfer[0].tx_buf = &req->reset; req->xfer[0].tx_buf = &req->reset;
req->xfer[0].len = 2; req->xfer[0].len = 2;
req->xfer[0].cs_change = 1;
req->xfer[1].tx_buf = &req->ref_on; req->xfer[1].tx_buf = &req->ref_on;
req->xfer[1].len = 2; req->xfer[1].len = 2;
req->xfer[1].delay_usecs = ts->vref_delay_usecs; req->xfer[1].delay_usecs = ts->vref_delay_usecs;
req->xfer[1].cs_change = 1;
req->xfer[2].tx_buf = &req->command; req->xfer[2].tx_buf = &req->command;
req->xfer[2].len = 2; req->xfer[2].len = 2;
req->xfer[2].delay_usecs = ts->vref_delay_usecs; req->xfer[2].delay_usecs = ts->vref_delay_usecs;
req->xfer[2].cs_change = 1;
req->xfer[3].rx_buf = &req->sample; req->xfer[3].rx_buf = &req->sample;
req->xfer[3].len = 2; req->xfer[3].len = 2;
req->xfer[3].cs_change = 1;
req->xfer[4].tx_buf = &ts->cmd_crtl2; /*REF OFF*/ req->xfer[4].tx_buf = &ts->cmd_crtl2; /*REF OFF*/
req->xfer[4].len = 2; req->xfer[4].len = 2;
req->xfer[4].cs_change = 1;
req->xfer[5].tx_buf = &ts->cmd_crtl1; /*DEFAULT*/ req->xfer[5].tx_buf = &ts->cmd_crtl1; /*DEFAULT*/
req->xfer[5].len = 2; req->xfer[5].len = 2;
...@@ -327,7 +332,7 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command) ...@@ -327,7 +332,7 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command)
return status ? : sample; return status ? : sample;
} }
static void ad7877_rx(struct ad7877 *ts) static int ad7877_process_data(struct ad7877 *ts)
{ {
struct input_dev *input_dev = ts->input; struct input_dev *input_dev = ts->input;
unsigned Rt; unsigned Rt;
...@@ -354,11 +359,25 @@ static void ad7877_rx(struct ad7877 *ts) ...@@ -354,11 +359,25 @@ static void ad7877_rx(struct ad7877 *ts)
Rt /= z1; Rt /= z1;
Rt = (Rt + 2047) >> 12; Rt = (Rt + 2047) >> 12;
/*
* Sample found inconsistent, pressure is beyond
* the maximum. Don't report it to user space.
*/
if (Rt > ts->pressure_max)
return -EINVAL;
if (!timer_pending(&ts->timer))
input_report_key(input_dev, BTN_TOUCH, 1);
input_report_abs(input_dev, ABS_X, x); input_report_abs(input_dev, ABS_X, x);
input_report_abs(input_dev, ABS_Y, y); input_report_abs(input_dev, ABS_Y, y);
input_report_abs(input_dev, ABS_PRESSURE, Rt); input_report_abs(input_dev, ABS_PRESSURE, Rt);
input_sync(input_dev); input_sync(input_dev);
return 0;
} }
return -EINVAL;
} }
static inline void ad7877_ts_event_release(struct ad7877 *ts) static inline void ad7877_ts_event_release(struct ad7877 *ts)
...@@ -366,72 +385,56 @@ static inline void ad7877_ts_event_release(struct ad7877 *ts) ...@@ -366,72 +385,56 @@ static inline void ad7877_ts_event_release(struct ad7877 *ts)
struct input_dev *input_dev = ts->input; struct input_dev *input_dev = ts->input;
input_report_abs(input_dev, ABS_PRESSURE, 0); input_report_abs(input_dev, ABS_PRESSURE, 0);
input_report_key(input_dev, BTN_TOUCH, 0);
input_sync(input_dev); input_sync(input_dev);
} }
static void ad7877_timer(unsigned long handle) static void ad7877_timer(unsigned long handle)
{ {
struct ad7877 *ts = (void *)handle; struct ad7877 *ts = (void *)handle;
unsigned long flags;
spin_lock_irqsave(&ts->lock, flags);
ad7877_ts_event_release(ts); ad7877_ts_event_release(ts);
spin_unlock_irqrestore(&ts->lock, flags);
} }
static irqreturn_t ad7877_irq(int irq, void *handle) static irqreturn_t ad7877_irq(int irq, void *handle)
{ {
struct ad7877 *ts = handle; struct ad7877 *ts = handle;
unsigned long flags; unsigned long flags;
int status; int error;
/* error = spi_sync(ts->spi, &ts->msg);
* The repeated conversion sequencer controlled by TMR kicked off if (error) {
* too fast. We ignore the last and process the sample sequence dev_err(&ts->spi->dev, "spi_sync --> %d\n", error);
* currently in the queue. It can't be older than 9.4ms, and we goto out;
* need to avoid that ts->msg doesn't get issued twice while in work. }
*/
spin_lock_irqsave(&ts->lock, flags); spin_lock_irqsave(&ts->lock, flags);
if (!ts->pending) { error = ad7877_process_data(ts);
ts->pending = 1; if (!error)
mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
status = spi_async(ts->spi, &ts->msg);
if (status)
dev_err(&ts->spi->dev, "spi_sync --> %d\n", status);
}
spin_unlock_irqrestore(&ts->lock, flags); spin_unlock_irqrestore(&ts->lock, flags);
out:
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void ad7877_callback(void *_ts)
{
struct ad7877 *ts = _ts;
spin_lock_irq(&ts->lock);
ad7877_rx(ts);
ts->pending = 0;
mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
spin_unlock_irq(&ts->lock);
}
static void ad7877_disable(struct ad7877 *ts) static void ad7877_disable(struct ad7877 *ts)
{ {
mutex_lock(&ts->mutex); mutex_lock(&ts->mutex);
if (!ts->disabled) { if (!ts->disabled) {
ts->disabled = 1; ts->disabled = true;
disable_irq(ts->spi->irq); disable_irq(ts->spi->irq);
/* Wait for spi_async callback */
while (ts->pending)
msleep(1);
if (del_timer_sync(&ts->timer)) if (del_timer_sync(&ts->timer))
ad7877_ts_event_release(ts); ad7877_ts_event_release(ts);
} }
/* we know the chip's in lowpower mode since we always /*
* We know the chip's in lowpower mode since we always
* leave it that way after every request * leave it that way after every request
*/ */
...@@ -443,7 +446,7 @@ static void ad7877_enable(struct ad7877 *ts) ...@@ -443,7 +446,7 @@ static void ad7877_enable(struct ad7877 *ts)
mutex_lock(&ts->mutex); mutex_lock(&ts->mutex);
if (ts->disabled) { if (ts->disabled) {
ts->disabled = 0; ts->disabled = false;
enable_irq(ts->spi->irq); enable_irq(ts->spi->irq);
} }
...@@ -453,7 +456,7 @@ static void ad7877_enable(struct ad7877 *ts) ...@@ -453,7 +456,7 @@ static void ad7877_enable(struct ad7877 *ts)
#define SHOW(name) static ssize_t \ #define SHOW(name) static ssize_t \
name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \ { \
struct ad7877 *ts = dev_get_drvdata(dev); \ struct ad7877 *ts = dev_get_drvdata(dev); \
ssize_t v = ad7877_read_adc(ts->spi, \ ssize_t v = ad7877_read_adc(ts->spi, \
AD7877_READ_CHAN(name)); \ AD7877_READ_CHAN(name)); \
if (v < 0) \ if (v < 0) \
...@@ -473,7 +476,7 @@ SHOW(temp2) ...@@ -473,7 +476,7 @@ SHOW(temp2)
static ssize_t ad7877_disable_show(struct device *dev, static ssize_t ad7877_disable_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct ad7877 *ts = dev_get_drvdata(dev); struct ad7877 *ts = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", ts->disabled); return sprintf(buf, "%u\n", ts->disabled);
} }
...@@ -503,7 +506,7 @@ static DEVICE_ATTR(disable, 0664, ad7877_disable_show, ad7877_disable_store); ...@@ -503,7 +506,7 @@ static DEVICE_ATTR(disable, 0664, ad7877_disable_show, ad7877_disable_store);
static ssize_t ad7877_dac_show(struct device *dev, static ssize_t ad7877_dac_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct ad7877 *ts = dev_get_drvdata(dev); struct ad7877 *ts = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", ts->dac); return sprintf(buf, "%u\n", ts->dac);
} }
...@@ -533,7 +536,7 @@ static DEVICE_ATTR(dac, 0664, ad7877_dac_show, ad7877_dac_store); ...@@ -533,7 +536,7 @@ static DEVICE_ATTR(dac, 0664, ad7877_dac_show, ad7877_dac_store);
static ssize_t ad7877_gpio3_show(struct device *dev, static ssize_t ad7877_gpio3_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct ad7877 *ts = dev_get_drvdata(dev); struct ad7877 *ts = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", ts->gpio3); return sprintf(buf, "%u\n", ts->gpio3);
} }
...@@ -564,7 +567,7 @@ static DEVICE_ATTR(gpio3, 0664, ad7877_gpio3_show, ad7877_gpio3_store); ...@@ -564,7 +567,7 @@ static DEVICE_ATTR(gpio3, 0664, ad7877_gpio3_show, ad7877_gpio3_store);
static ssize_t ad7877_gpio4_show(struct device *dev, static ssize_t ad7877_gpio4_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct ad7877 *ts = dev_get_drvdata(dev); struct ad7877 *ts = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", ts->gpio4); return sprintf(buf, "%u\n", ts->gpio4);
} }
...@@ -597,16 +600,35 @@ static struct attribute *ad7877_attributes[] = { ...@@ -597,16 +600,35 @@ static struct attribute *ad7877_attributes[] = {
&dev_attr_temp2.attr, &dev_attr_temp2.attr,
&dev_attr_aux1.attr, &dev_attr_aux1.attr,
&dev_attr_aux2.attr, &dev_attr_aux2.attr,
&dev_attr_aux3.attr,
&dev_attr_bat1.attr, &dev_attr_bat1.attr,
&dev_attr_bat2.attr, &dev_attr_bat2.attr,
&dev_attr_disable.attr, &dev_attr_disable.attr,
&dev_attr_dac.attr, &dev_attr_dac.attr,
&dev_attr_gpio3.attr,
&dev_attr_gpio4.attr, &dev_attr_gpio4.attr,
NULL NULL
}; };
static mode_t ad7877_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
mode_t mode = attr->mode;
if (attr == &dev_attr_aux3.attr) {
if (gpio3)
mode = 0;
} else if (attr == &dev_attr_gpio3.attr) {
if (!gpio3)
mode = 0;
}
return mode;
}
static const struct attribute_group ad7877_attr_group = { static const struct attribute_group ad7877_attr_group = {
.attrs = ad7877_attributes, .is_visible = ad7877_attr_is_visible,
.attrs = ad7877_attributes,
}; };
static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts) static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
...@@ -635,22 +657,25 @@ static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts) ...@@ -635,22 +657,25 @@ static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
spi_message_init(m); spi_message_init(m);
m->complete = ad7877_callback;
m->context = ts; m->context = ts;
ts->xfer[0].tx_buf = &ts->cmd_crtl1; ts->xfer[0].tx_buf = &ts->cmd_crtl1;
ts->xfer[0].len = 2; ts->xfer[0].len = 2;
ts->xfer[0].cs_change = 1;
spi_message_add_tail(&ts->xfer[0], m); spi_message_add_tail(&ts->xfer[0], m);
ts->xfer[1].tx_buf = &ts->cmd_dummy; /* Send ZERO */ ts->xfer[1].tx_buf = &ts->cmd_dummy; /* Send ZERO */
ts->xfer[1].len = 2; ts->xfer[1].len = 2;
ts->xfer[1].cs_change = 1;
spi_message_add_tail(&ts->xfer[1], m); spi_message_add_tail(&ts->xfer[1], m);
for (i = 0; i < 11; i++) { for (i = 0; i < AD7877_NR_SENSE; i++) {
ts->xfer[i + 2].rx_buf = &ts->conversion_data[AD7877_SEQ_YPOS + i]; ts->xfer[i + 2].rx_buf = &ts->conversion_data[AD7877_SEQ_YPOS + i];
ts->xfer[i + 2].len = 2; ts->xfer[i + 2].len = 2;
if (i < (AD7877_NR_SENSE - 1))
ts->xfer[i + 2].cs_change = 1;
spi_message_add_tail(&ts->xfer[i + 2], m); spi_message_add_tail(&ts->xfer[i + 2], m);
} }
} }
...@@ -718,6 +743,8 @@ static int __devinit ad7877_probe(struct spi_device *spi) ...@@ -718,6 +743,8 @@ static int __devinit ad7877_probe(struct spi_device *spi)
input_dev->phys = ts->phys; input_dev->phys = ts->phys;
input_dev->dev.parent = &spi->dev; input_dev->dev.parent = &spi->dev;
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(EV_ABS, input_dev->evbit); __set_bit(EV_ABS, input_dev->evbit);
__set_bit(ABS_X, input_dev->absbit); __set_bit(ABS_X, input_dev->absbit);
__set_bit(ABS_Y, input_dev->absbit); __set_bit(ABS_Y, input_dev->absbit);
...@@ -752,8 +779,9 @@ static int __devinit ad7877_probe(struct spi_device *spi) ...@@ -752,8 +779,9 @@ static int __devinit ad7877_probe(struct spi_device *spi)
/* Request AD7877 /DAV GPIO interrupt */ /* Request AD7877 /DAV GPIO interrupt */
err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING, err = request_threaded_irq(spi->irq, NULL, ad7877_irq,
spi->dev.driver->name, ts); IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
spi->dev.driver->name, ts);
if (err) { if (err) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
goto err_free_mem; goto err_free_mem;
...@@ -763,20 +791,12 @@ static int __devinit ad7877_probe(struct spi_device *spi) ...@@ -763,20 +791,12 @@ static int __devinit ad7877_probe(struct spi_device *spi)
if (err) if (err)
goto err_free_irq; goto err_free_irq;
err = device_create_file(&spi->dev,
gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
if (err)
goto err_remove_attr_group;
err = input_register_device(input_dev); err = input_register_device(input_dev);
if (err) if (err)
goto err_remove_attr; goto err_remove_attr_group;
return 0; return 0;
err_remove_attr:
device_remove_file(&spi->dev,
gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
err_remove_attr_group: err_remove_attr_group:
sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group); sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
err_free_irq: err_free_irq:
...@@ -790,11 +810,9 @@ static int __devinit ad7877_probe(struct spi_device *spi) ...@@ -790,11 +810,9 @@ static int __devinit ad7877_probe(struct spi_device *spi)
static int __devexit ad7877_remove(struct spi_device *spi) static int __devexit ad7877_remove(struct spi_device *spi)
{ {
struct ad7877 *ts = dev_get_drvdata(&spi->dev); struct ad7877 *ts = dev_get_drvdata(&spi->dev);
sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group); sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
device_remove_file(&spi->dev,
gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
ad7877_disable(ts); ad7877_disable(ts);
free_irq(ts->spi->irq, ts); free_irq(ts->spi->irq, ts);
......
This diff is collapsed.
This diff is collapsed.
...@@ -206,9 +206,9 @@ static int __devinit cy8ctmg110_probe(struct i2c_client *client, ...@@ -206,9 +206,9 @@ static int __devinit cy8ctmg110_probe(struct i2c_client *client,
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(input_dev, ABS_X, input_set_abs_params(input_dev, ABS_X,
CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 0, 0); CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0);
input_set_abs_params(input_dev, ABS_Y, input_set_abs_params(input_dev, ABS_Y,
CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 0, 0); CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
if (ts->reset_pin) { if (ts->reset_pin) {
err = gpio_request(ts->reset_pin, NULL); err = gpio_request(ts->reset_pin, NULL);
......
...@@ -107,8 +107,7 @@ static int __init hp680_ts_init(void) ...@@ -107,8 +107,7 @@ static int __init hp680_ts_init(void)
return 0; return 0;
fail2: free_irq(HP680_TS_IRQ, NULL); fail2: free_irq(HP680_TS_IRQ, NULL);
cancel_delayed_work(&work); cancel_delayed_work_sync(&work);
flush_scheduled_work();
fail1: input_free_device(hp680_ts_dev); fail1: input_free_device(hp680_ts_dev);
return err; return err;
} }
...@@ -116,8 +115,7 @@ static int __init hp680_ts_init(void) ...@@ -116,8 +115,7 @@ static int __init hp680_ts_init(void)
static void __exit hp680_ts_exit(void) static void __exit hp680_ts_exit(void)
{ {
free_irq(HP680_TS_IRQ, NULL); free_irq(HP680_TS_IRQ, NULL);
cancel_delayed_work(&work); cancel_delayed_work_sync(&work);
flush_scheduled_work();
input_unregister_device(hp680_ts_dev); input_unregister_device(hp680_ts_dev);
} }
......
This diff is collapsed.
...@@ -350,7 +350,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev) ...@@ -350,7 +350,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
err_tcirq: err_tcirq:
free_irq(ts.irq_tc, ts.input); free_irq(ts.irq_tc, ts.input);
err_inputdev: err_inputdev:
input_unregister_device(ts.input); input_free_device(ts.input);
err_iomap: err_iomap:
iounmap(ts.io); iounmap(ts.io);
err_clk: err_clk:
......
...@@ -268,7 +268,7 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev) ...@@ -268,7 +268,7 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev)
struct stmpe_touch *ts; struct stmpe_touch *ts;
struct input_dev *idev; struct input_dev *idev;
struct stmpe_ts_platform_data *ts_pdata = NULL; struct stmpe_ts_platform_data *ts_pdata = NULL;
int ret = 0; int ret;
int ts_irq; int ts_irq;
ts_irq = platform_get_irq_byname(pdev, "FIFO_TH"); ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
...@@ -276,12 +276,16 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev) ...@@ -276,12 +276,16 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev)
return ts_irq; return ts_irq;
ts = kzalloc(sizeof(*ts), GFP_KERNEL); ts = kzalloc(sizeof(*ts), GFP_KERNEL);
if (!ts) if (!ts) {
ret = -ENOMEM;
goto err_out; goto err_out;
}
idev = input_allocate_device(); idev = input_allocate_device();
if (!idev) if (!idev) {
ret = -ENOMEM;
goto err_free_ts; goto err_free_ts;
}
platform_set_drvdata(pdev, ts); platform_set_drvdata(pdev, ts);
ts->stmpe = stmpe; ts->stmpe = stmpe;
...@@ -361,7 +365,6 @@ static int __devexit stmpe_ts_remove(struct platform_device *pdev) ...@@ -361,7 +365,6 @@ static int __devexit stmpe_ts_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
input_unregister_device(ts->idev); input_unregister_device(ts->idev);
input_free_device(ts->idev);
kfree(ts); kfree(ts);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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