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

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input: (75 commits)
  Input: wacom - specify Cinitq supported tools
  Input: ab8500-ponkey - fix IRQ freeing in error path
  Input: adp5588-keys - use more obvious i2c_device_id name string
  Input: ad7877 - switch to using threaded IRQ
  Input: ad7877 - use attribute group to control visibility of attributes
  Input: serio - add support for PS2Mult multiplexer protocol
  Input: wacom - properly enable runtime PM
  Input: ad7877 - filter events where pressure is beyond the maximum
  Input: ad7877 - implement EV_KEY:BTN_TOUCH reporting
  Input: ad7877 - implement specified chip select behavior
  Input: hp680_ts_input - use cancel_delayed_work_sync()
  Input: mousedev - correct lockdep annotation
  Input: ads7846 - switch to using threaded IRQ
  Input: serio - support multiple child devices per single parent
  Input: synaptics - simplify pass-through port handling
  Input: add ROHM BU21013 touch panel controller support
  Input: omap4-keypad - wake-up on events & long presses
  Input: omap4-keypad - fix interrupt line configuration
  Input: omap4-keypad - SYSCONFIG register configuration
  Input: omap4-keypad - use platform device helpers
  ...
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index fcb587f..cac83a6 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -18,12 +18,14 @@
 #include <linux/amba/pl022.h>
 #include <linux/spi/spi.h>
 #include <linux/mfd/ab8500.h>
+#include <linux/input/matrix_keypad.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
 #include <plat/pincfg.h>
 #include <plat/i2c.h>
+#include <plat/ske.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
@@ -49,6 +51,24 @@
 	GPIO11_I2C2_SCL,
 	GPIO229_I2C3_SDA,
 	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)
@@ -148,12 +168,120 @@
 	&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 */
 static struct platform_device *platform_devs[] __initdata = {
 	&u8500_i2c0_device,
 	&ux500_i2c1_device,
 	&ux500_i2c2_device,
 	&ux500_i2c3_device,
+	&ux500_ske_keypad_device,
 };
 
 static void __init u8500_init_machine(void)
@@ -168,6 +296,7 @@
 	ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data;
 	ux500_i2c2_device.dev.platform_data = &u8500_i2c2_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;
 
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index d8ab7f1..1675047 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -477,6 +477,7 @@
 	CLK(sdi5,	"sdi5",		NULL),
 	CLK(uart2,	"uart2",	NULL),
 	CLK(ske,	"ske",		NULL),
+	CLK(ske,	"nmk-ske-keypad",	NULL),
 	CLK(sdi2,	"sdi2",		NULL),
 	CLK(i2c0,	"nmk-i2c.0",	NULL),
 	CLK(fsmc,	"fsmc",		NULL),
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 40032fe..cbbe69a 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -292,3 +292,23 @@
 	dma40_resources[1].start = U8500_DMA_LCPA_BASE_ED;
 	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,
+};
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index 33a120c..b91a4d1 100644
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -26,6 +26,7 @@
 extern struct platform_device u8500_i2c0_device;
 extern struct platform_device u8500_i2c4_device;
 extern struct platform_device u8500_dma40_device;
+extern struct platform_device ux500_ske_keypad_device;
 
 extern struct amba_device u8500_sdi0_device;
 extern struct amba_device u8500_sdi1_device;
diff --git a/arch/arm/mach-ux500/pins-db8500.h b/arch/arm/mach-ux500/pins-db8500.h
index 66f8761..f923764 100644
--- a/arch/arm/mach-ux500/pins-db8500.h
+++ b/arch/arm/mach-ux500/pins-db8500.h
@@ -459,82 +459,82 @@
 #define GPIO152_KP_O9		PIN_CFG(152, ALT_C)
 
 #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_U2_RXD		PIN_CFG(153, ALT_C)
 
 #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_U2_TXD		PIN_CFG(154, ALT_C)
 
 #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_STMAPE_CLK	PIN_CFG(155, ALT_C)
 
 #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_STMAPE_DAT3	PIN_CFG(156, ALT_C)
 
 #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_STMAPE_DAT2	PIN_CFG(157, ALT_C)
 
 #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_STMAPE_DAT1	PIN_CFG(158, ALT_C)
 
 #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_STMAPE_DAT0	PIN_CFG(159, ALT_C)
 
 #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_NONE		PIN_CFG(160, ALT_C)
 
 #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_UARTMOD_RXD	PIN_CFG(161, ALT_C)
 
 #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_UARTMOD_TXD	PIN_CFG(162, ALT_C)
 
 #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_STMMOD_CLK	PIN_CFG(163, ALT_C)
 
 #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_STMMOD_DAT3	PIN_CFG(164, ALT_C)
 
 #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_STMMOD_DAT2	PIN_CFG(165, ALT_C)
 
 #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_STMMOD_DAT1	PIN_CFG(166, ALT_C)
 
 #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_STMMOD_DAT0	PIN_CFG(167, ALT_C)
 
 #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_NONE		PIN_CFG(168, ALT_C)
 
diff --git a/arch/arm/plat-nomadik/include/plat/ske.h b/arch/arm/plat-nomadik/include/plat/ske.h
new file mode 100644
index 0000000..31382fb
--- /dev/null
+++ b/arch/arm/plat-nomadik/include/plat/ske.h
@@ -0,0 +1,50 @@
+/*
+ * 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*/
diff --git a/arch/arm/plat-omap/include/plat/omap4-keypad.h b/arch/arm/plat-omap/include/plat/omap4-keypad.h
new file mode 100644
index 0000000..2b1d9bc
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/omap4-keypad.h
@@ -0,0 +1,14 @@
+#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
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index a7ca752..e95d7876 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -175,8 +175,7 @@
  */
 
 struct getset_keycode_data {
-	unsigned int scancode;
-	unsigned int keycode;
+	struct input_keymap_entry ke;
 	int error;
 };
 
@@ -184,32 +183,50 @@
 {
 	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 */
 }
 
 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);
 
-	return d.error ?: d.keycode;
+	return d.error ?: d.ke.keycode;
 }
 
 static int setkeycode_helper(struct input_handle *handle, void *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 */
 }
 
 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);
 
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index f3019f5..eaa5d3e 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -566,10 +566,16 @@
 static bool sysrq_down;
 static int sysrq_alt_use;
 static int sysrq_alt;
+static DEFINE_SPINLOCK(sysrq_event_lock);
 
 static bool sysrq_filter(struct input_handle *handle, unsigned int type,
 		         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)
 		goto out;
 
@@ -601,7 +607,10 @@
 	}
 
 out:
-	return sysrq_down;
+	suppress = sysrq_down;
+	spin_unlock(&sysrq_event_lock);
+
+	return suppress;
 }
 
 static int sysrq_connect(struct input_handler *handler,
@@ -652,8 +661,8 @@
 }
 
 /*
- * We are matching on KEY_LEFTALT insteard of KEY_SYSRQ because not all
- * keyboards have SysRq ikey predefined and so user may add it to keymap
+ * We are matching on KEY_LEFTALT instead of KEY_SYSRQ because not all
+ * keyboards have SysRq key predefined and so user may add it to keymap
  * later, but we expect all such keyboards to have left alt.
  */
 static const struct input_device_id sysrq_ids[] = {
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 7832b6e..515345b 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1780,6 +1780,11 @@
 		    hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST)
 			return true;
 		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 &&
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 3ee999d..3341baa 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -299,6 +299,10 @@
 #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003
 #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_DEVICE_ID_UGCI_DRIVING	0x0010
 #define USB_DEVICE_ID_UGCI_FLYING	0x0020
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 834ef47..bb0b365 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -68,39 +68,52 @@
 #define map_key_clear(c)	hid_map_usage_clear(hidinput, usage, &bit, \
 		&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 1;
-
-	return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
+	return (usage->hid & (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;
-
-	return code == keycode;
+	/*
+	 * We should exclude unmapped usages when doing lookup by keycode.
+	 */
+	return (usage->type == EV_KEY && usage->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,
-					   unsigned int scancode,
-					   unsigned int keycode)
+					   hid_usage_cmp_t match,
+					   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_usage *usage;
 
 	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
 		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
 			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;
-					if (usage->type == EV_KEY &&
-						match_scancode(usage->hid, scancode) &&
-						match_keycode(usage->code, keycode))
-						return usage;
+					if (usage->type == EV_KEY || usage->type == 0) {
+						if (match(usage, cur_idx, value)) {
+							if (usage_idx)
+								*usage_idx = cur_idx;
+							return usage;
+						}
+						cur_idx++;
+					}
 				}
 			}
 		}
@@ -108,39 +121,68 @@
 	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,
-			       unsigned int scancode, unsigned int *keycode)
+			       struct input_keymap_entry *ke)
 {
 	struct hid_device *hid = input_get_drvdata(dev);
 	struct hid_usage *usage;
+	unsigned int scancode, index;
 
-	usage = hidinput_find_key(hid, scancode, 0);
+	usage = hidinput_locate_usage(hid, ke, &index);
 	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 -EINVAL;
 }
 
 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_usage *usage;
-	int old_keycode;
 
-	usage = hidinput_find_key(hid, scancode, 0);
+	usage = hidinput_locate_usage(hid, ke, NULL);
 	if (usage) {
-		old_keycode = usage->code;
-		usage->code = keycode;
+		*old_keycode = usage->type == EV_KEY ?
+				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);
-		dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
-		/* Set the keybit for the old keycode if the old keycode is used
-		 * by another key */
-		if (hidinput_find_key (hid, 0, old_keycode))
-			set_bit(old_keycode, dev->keybit);
+		dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n",
+			usage->code, usage->hid);
+
+		/*
+		 * 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;
 	}
@@ -835,8 +877,8 @@
 					hid->ll_driver->hidinput_input_event;
 				input_dev->open = hidinput_open;
 				input_dev->close = hidinput_close;
-				input_dev->setkeycode = hidinput_setkeycode;
-				input_dev->getkeycode = hidinput_getkeycode;
+				input_dev->setkeycode_new = hidinput_setkeycode;
+				input_dev->getkeycode_new = hidinput_getkeycode;
 
 				input_dev->name = hid->name;
 				input_dev->phys = hid->phys;
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 535fea4..e3f7fc6 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -534,6 +534,80 @@
 }
 #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,
 			   void __user *p, int compat_mode)
 {
@@ -580,25 +654,6 @@
 
 		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:
 		return input_ff_erase(dev, (int)(unsigned long) p, file);
 
@@ -620,7 +675,6 @@
 
 	/* Now check variable-length commands */
 #define EVIOC_MASK_SIZE(nr)	((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
-
 	switch (EVIOC_MASK_SIZE(cmd)) {
 
 	case EVIOCGKEY(0):
@@ -654,6 +708,12 @@
 			return -EFAULT;
 
 		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 */
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
index 7392992..422aa0a 100644
--- a/drivers/input/gameport/emu10k1-gp.c
+++ b/drivers/input/gameport/emu10k1-gp.c
@@ -59,44 +59,52 @@
 
 static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	int ioport, iolen;
 	struct emu *emu;
 	struct gameport *port;
-
-	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;
+	int error;
 
 	emu = kzalloc(sizeof(struct emu), GFP_KERNEL);
 	port = gameport_allocate_port();
 	if (!emu || !port) {
 		printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
-		release_region(ioport, iolen);
-		kfree(emu);
-		gameport_free_port(port);
-		return -ENOMEM;
+		error = -ENOMEM;
+		goto err_out_free;
 	}
 
-	emu->io = ioport;
-	emu->size = iolen;
+	error = pci_enable_device(pdev);
+	if (error)
+		goto err_out_free;
+
+	emu->io = pci_resource_start(pdev, 0);
+	emu->size = pci_resource_len(pdev, 0);
+
 	emu->dev = pdev;
 	emu->gameport = port;
 
 	gameport_set_name(port, "EMU10K1");
 	gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
 	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);
 
 	gameport_register_port(port);
 
 	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)
@@ -106,6 +114,8 @@
 	gameport_unregister_port(emu->gameport);
 	release_region(emu->io, emu->size);
 	kfree(emu);
+
+	pci_disable_device(pdev);
 }
 
 static struct pci_driver emu_driver = {
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
index 14d3f3e..a3b70ff 100644
--- a/drivers/input/gameport/fm801-gp.c
+++ b/drivers/input/gameport/fm801-gp.c
@@ -133,11 +133,11 @@
 {
 	struct fm801_gp *gp = pci_get_drvdata(pci);
 
-	if (gp) {
-		gameport_unregister_port(gp->gameport);
-		release_resource(gp->res_port);
-		kfree(gp);
-	}
+	gameport_unregister_port(gp->gameport);
+	release_resource(gp->res_port);
+	kfree(gp);
+
+	pci_disable_device(pci);
 }
 
 static const struct pci_device_id fm801_gp_id_table[] = {
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 7919c25..d092ef9 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -171,7 +171,7 @@
 	if (code == ABS_MT_SLOT) {
 		/*
 		 * "Stage" the event; we'll flush it later, when we
-		 * get actiual touch data.
+		 * get actual touch data.
 		 */
 		if (*pval >= 0 && *pval < dev->mtsize)
 			dev->slot = *pval;
@@ -188,7 +188,7 @@
 		pold = &mtslot->abs[code - ABS_MT_FIRST];
 	} else {
 		/*
-		 * Bypass filtering for multitouch events when
+		 * Bypass filtering for multi-touch events when
 		 * not employing slots.
 		 */
 		pold = NULL;
@@ -634,78 +634,141 @@
 	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) {
-		case 1:
-			return ((u8 *)dev->keycode)[scancode];
+	case 1:
+		return ((u8 *)dev->keycode)[index];
 
-		case 2:
-			return ((u16 *)dev->keycode)[scancode];
+	case 2:
+		return ((u16 *)dev->keycode)[index];
 
-		default:
-			return ((u32 *)dev->keycode)[scancode];
+	default:
+		return ((u32 *)dev->keycode)[index];
 	}
 }
 
 static int input_default_getkeycode(struct input_dev *dev,
-				    unsigned int scancode,
-				    unsigned int *keycode)
+				    struct input_keymap_entry *ke)
 {
+	unsigned int index;
+	int error;
+
 	if (!dev->keycodesize)
 		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;
 
-	*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;
 }
 
 static int input_default_setkeycode(struct input_dev *dev,
-				    unsigned int scancode,
-				    unsigned int keycode)
+				    const struct input_keymap_entry *ke,
+				    unsigned int *old_keycode)
 {
-	int old_keycode;
+	unsigned int index;
+	int error;
 	int i;
 
-	if (scancode >= dev->keycodemax)
-		return -EINVAL;
-
 	if (!dev->keycodesize)
 		return -EINVAL;
 
-	if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
+	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;
+
+	if (dev->keycodesize < sizeof(dev->keycode) &&
+			(ke->keycode >> (dev->keycodesize * 8)))
 		return -EINVAL;
 
 	switch (dev->keycodesize) {
 		case 1: {
 			u8 *k = (u8 *)dev->keycode;
-			old_keycode = k[scancode];
-			k[scancode] = keycode;
+			*old_keycode = k[index];
+			k[index] = ke->keycode;
 			break;
 		}
 		case 2: {
 			u16 *k = (u16 *)dev->keycode;
-			old_keycode = k[scancode];
-			k[scancode] = keycode;
+			*old_keycode = k[index];
+			k[index] = ke->keycode;
 			break;
 		}
 		default: {
 			u32 *k = (u32 *)dev->keycode;
-			old_keycode = k[scancode];
-			k[scancode] = keycode;
+			*old_keycode = k[index];
+			k[index] = ke->keycode;
 			break;
 		}
 	}
 
-	__clear_bit(old_keycode, dev->keybit);
-	__set_bit(keycode, dev->keybit);
+	__clear_bit(*old_keycode, dev->keybit);
+	__set_bit(ke->keycode, dev->keybit);
 
 	for (i = 0; i < dev->keycodemax; i++) {
-		if (input_fetch_keycode(dev, i) == old_keycode) {
-			__set_bit(old_keycode, dev->keybit);
+		if (input_fetch_keycode(dev, i) == *old_keycode) {
+			__set_bit(*old_keycode, dev->keybit);
 			break; /* Setting the bit twice is useless, so break */
 		}
 	}
@@ -716,53 +779,86 @@
 /**
  * input_get_keycode - retrieve keycode currently mapped to a given scancode
  * @dev: input device which keymap is being queried
- * @scancode: scancode (or its equivalent for device in question) for which
- *	keycode is needed
- * @keycode: result
+ * @ke: keymap entry
  *
  * 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,
-		      unsigned int scancode, unsigned int *keycode)
+int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke)
 {
 	unsigned long flags;
 	int retval;
 
 	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;
 }
 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
- * @scancode: scancode (or its equivalent for device in question)
- * @keycode: new keycode to be assigned to the scancode
+ * @ke: new keymap entry
  *
  * This function should be called by anyone needing to update current
  * keymap. Presently keyboard and evdev handlers use it.
  */
 int input_set_keycode(struct input_dev *dev,
-		      unsigned int scancode, unsigned int keycode)
+		      const struct input_keymap_entry *ke)
 {
 	unsigned long flags;
 	unsigned int old_keycode;
 	int retval;
 
-	if (keycode > KEY_MAX)
+	if (ke->keycode > KEY_MAX)
 		return -EINVAL;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
 
-	retval = dev->getkeycode(dev, scancode, &old_keycode);
-	if (retval)
-		goto out;
+	if (dev->setkeycode) {
+		/*
+		 * Support for legacy drivers, that don't implement the new
+		 * ioctls
+		 */
+		unsigned int scancode;
 
-	retval = dev->setkeycode(dev, scancode, keycode);
+		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);
+	}
+
 	if (retval)
 		goto out;
 
@@ -1601,7 +1697,7 @@
  *
  * 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
- * 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)
 {
@@ -1759,11 +1855,11 @@
 		dev->rep[REP_PERIOD] = 33;
 	}
 
-	if (!dev->getkeycode)
-		dev->getkeycode = input_default_getkeycode;
+	if (!dev->getkeycode && !dev->getkeycode_new)
+		dev->getkeycode_new = input_default_getkeycode;
 
-	if (!dev->setkeycode)
-		dev->setkeycode = input_default_setkeycode;
+	if (!dev->setkeycode && !dev->setkeycode_new)
+		dev->setkeycode_new = input_default_setkeycode;
 
 	dev_set_name(&dev->dev, "input%ld",
 		     (unsigned long) atomic_inc_return(&input_no) - 1);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index aa037fe..0426630 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -327,6 +327,16 @@
 	  To compile this driver as a module, choose M here: the
 	  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
 	tristate "OpenCores Keyboard Controller"
 	help
@@ -424,6 +434,15 @@
 	  To compile this driver as a module, choose M here: the
 	  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
 	tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
 	depends on TWL4030_CORE
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 504b591..c13809c 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -28,7 +28,9 @@
 obj-$(CONFIG_KEYBOARD_MAX7359)		+= max7359_keypad.o
 obj-$(CONFIG_KEYBOARD_MCS)		+= mcs_touchkey.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_OMAP4)		+= omap4-keypad.o
 obj-$(CONFIG_KEYBOARD_OPENCORES)	+= opencores-kbd.o
 obj-$(CONFIG_KEYBOARD_PXA27x)		+= pxa27x_keypad.o
 obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)	+= pxa930_rotary.o
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index d6918cb..b92d1cd 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -660,7 +660,7 @@
 #endif
 
 static const struct i2c_device_id adp5588_id[] = {
-	{ KBUILD_MODNAME, 0 },
+	{ "adp5588-keys", 0 },
 	{ "adp5587-keys", 0 },
 	{ }
 };
diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
index 19fa94a..fed31e0 100644
--- a/drivers/input/keyboard/hil_kbd.c
+++ b/drivers/input/keyboard/hil_kbd.c
@@ -570,6 +570,8 @@
 	{ 0 }
 };
 
+MODULE_DEVICE_TABLE(serio, hil_dev_ids);
+
 static struct serio_driver hil_serio_drv = {
 	.driver		= {
 		.name	= "hil_dev",
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
new file mode 100644
index 0000000..6e0f230
--- /dev/null
+++ b/drivers/input/keyboard/nomadik-ske-keypad.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ *
+ * License terms:GNU General Public License (GPL) version 2
+ *
+ * Keypad controller driver for the SKE (Scroll Key Encoder) module used in
+ * the Nomadik 8815 and Ux500 platforms.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include <plat/ske.h>
+
+/* SKE_CR bits */
+#define SKE_KPMLT	(0x1 << 6)
+#define SKE_KPCN	(0x7 << 3)
+#define SKE_KPASEN	(0x1 << 2)
+#define SKE_KPASON	(0x1 << 7)
+
+/* SKE_IMSC bits */
+#define SKE_KPIMA	(0x1 << 2)
+
+/* SKE_ICR bits */
+#define SKE_KPICS	(0x1 << 3)
+#define SKE_KPICA	(0x1 << 2)
+
+/* SKE_RIS bits */
+#define SKE_KPRISA	(0x1 << 2)
+
+#define SKE_KEYPAD_ROW_SHIFT	3
+#define SKE_KPD_KEYMAP_SIZE	(8 * 8)
+
+/* keypad auto scan registers */
+#define SKE_ASR0	0x20
+#define SKE_ASR1	0x24
+#define SKE_ASR2	0x28
+#define SKE_ASR3	0x2C
+
+#define SKE_NUM_ASRX_REGISTERS	(4)
+
+/**
+ * struct ske_keypad  - data structure used by keypad driver
+ * @irq:	irq no
+ * @reg_base:	ske regsiters base address
+ * @input:	pointer to input device object
+ * @board:	keypad platform device
+ * @keymap:	matrix scan code table for keycodes
+ * @clk:	clock structure pointer
+ */
+struct ske_keypad {
+	int irq;
+	void __iomem *reg_base;
+	struct input_dev *input;
+	const struct ske_keypad_platform_data *board;
+	unsigned short keymap[SKE_KPD_KEYMAP_SIZE];
+	struct clk *clk;
+	spinlock_t ske_keypad_lock;
+};
+
+static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr,
+		u8 mask, u8 data)
+{
+	u32 ret;
+
+	spin_lock(&keypad->ske_keypad_lock);
+
+	ret = readl(keypad->reg_base + addr);
+	ret &= ~mask;
+	ret |= data;
+	writel(ret, keypad->reg_base + addr);
+
+	spin_unlock(&keypad->ske_keypad_lock);
+}
+
+/*
+ * ske_keypad_chip_init: init keypad controller configuration
+ *
+ * Enable Multi key press detection, auto scan mode
+ */
+static int __devinit ske_keypad_chip_init(struct ske_keypad *keypad)
+{
+	u32 value;
+	int timeout = 50;
+
+	/* check SKE_RIS to be 0 */
+	while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--)
+		cpu_relax();
+
+	if (!timeout)
+		return -EINVAL;
+
+	/*
+	 * set debounce value
+	 * keypad dbounce is configured in DBCR[15:8]
+	 * dbounce value in steps of 32/32.768 ms
+	 */
+	spin_lock(&keypad->ske_keypad_lock);
+	value = readl(keypad->reg_base + SKE_DBCR);
+	value = value & 0xff;
+	value |= ((keypad->board->debounce_ms * 32000)/32768) << 8;
+	writel(value, keypad->reg_base + SKE_DBCR);
+	spin_unlock(&keypad->ske_keypad_lock);
+
+	/* enable multi key detection */
+	ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPMLT);
+
+	/*
+	 * set up the number of columns
+	 * KPCN[5:3] defines no. of keypad columns to be auto scanned
+	 */
+	value = (keypad->board->kcol - 1) << 3;
+	ske_keypad_set_bits(keypad, SKE_CR, SKE_KPCN, value);
+
+	/* clear keypad interrupt for auto(and pending SW) scans */
+	ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA | SKE_KPICS);
+
+	/* un-mask keypad interrupts */
+	ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
+
+	/* enable automatic scan */
+	ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPASEN);
+
+	return 0;
+}
+
+static void ske_keypad_read_data(struct ske_keypad *keypad)
+{
+	struct input_dev *input = keypad->input;
+	u16 status;
+	int col = 0, row = 0, code;
+	int ske_asr, ske_ris, key_pressed, i;
+
+	/*
+	 * Read the auto scan registers
+	 *
+	 * Each SKE_ASRx (x=0 to x=3) contains two row values.
+	 * lower byte contains row value for column 2*x,
+	 * upper byte contains row value for column 2*x + 1
+	 */
+	for (i = 0; i < SKE_NUM_ASRX_REGISTERS; i++) {
+		ske_asr = readl(keypad->reg_base + SKE_ASR0 + (4 * i));
+		if (!ske_asr)
+			continue;
+
+		/* now that ASRx is zero, find out the column x and row y*/
+		if (ske_asr & 0xff) {
+			col = i * 2;
+			status = ske_asr & 0xff;
+		} else {
+			col = (i * 2) + 1;
+			status = (ske_asr & 0xff00) >> 8;
+		}
+
+		/* find out the row */
+		row = __ffs(status);
+
+		code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT);
+		ske_ris = readl(keypad->reg_base + SKE_RIS);
+		key_pressed = ske_ris & SKE_KPRISA;
+
+		input_event(input, EV_MSC, MSC_SCAN, code);
+		input_report_key(input, keypad->keymap[code], key_pressed);
+		input_sync(input);
+	}
+}
+
+static irqreturn_t ske_keypad_irq(int irq, void *dev_id)
+{
+	struct ske_keypad *keypad = dev_id;
+	int retries = 20;
+
+	/* disable auto scan interrupt; mask the interrupt generated */
+	ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
+	ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA);
+
+	while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --retries)
+		msleep(5);
+
+	if (retries) {
+		/* SKEx registers are stable and can be read */
+		ske_keypad_read_data(keypad);
+	}
+
+	/* enable auto scan interrupts */
+	ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit ske_keypad_probe(struct platform_device *pdev)
+{
+	const struct ske_keypad_platform_data *plat = pdev->dev.platform_data;
+	struct ske_keypad *keypad;
+	struct input_dev *input;
+	struct resource *res;
+	int irq;
+	int error;
+
+	if (!plat) {
+		dev_err(&pdev->dev, "invalid keypad platform data\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "failed to get keypad irq\n");
+		return -EINVAL;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "missing platform resources\n");
+		return -EINVAL;
+	}
+
+	keypad = kzalloc(sizeof(struct ske_keypad), GFP_KERNEL);
+	input = input_allocate_device();
+	if (!keypad || !input) {
+		dev_err(&pdev->dev, "failed to allocate keypad memory\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	keypad->irq = irq;
+	keypad->board = plat;
+	keypad->input = input;
+	spin_lock_init(&keypad->ske_keypad_lock);
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "failed to request I/O memory\n");
+		error = -EBUSY;
+		goto err_free_mem;
+	}
+
+	keypad->reg_base = ioremap(res->start, resource_size(res));
+	if (!keypad->reg_base) {
+		dev_err(&pdev->dev, "failed to remap I/O memory\n");
+		error = -ENXIO;
+		goto err_free_mem_region;
+	}
+
+	keypad->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(keypad->clk)) {
+		dev_err(&pdev->dev, "failed to get clk\n");
+		error = PTR_ERR(keypad->clk);
+		goto err_iounmap;
+	}
+
+	input->id.bustype = BUS_HOST;
+	input->name = "ux500-ske-keypad";
+	input->dev.parent = &pdev->dev;
+
+	input->keycode = keypad->keymap;
+	input->keycodesize = sizeof(keypad->keymap[0]);
+	input->keycodemax = ARRAY_SIZE(keypad->keymap);
+
+	input_set_capability(input, EV_MSC, MSC_SCAN);
+
+	__set_bit(EV_KEY, input->evbit);
+	if (!plat->no_autorepeat)
+		__set_bit(EV_REP, input->evbit);
+
+	matrix_keypad_build_keymap(plat->keymap_data, SKE_KEYPAD_ROW_SHIFT,
+			input->keycode, input->keybit);
+
+	clk_enable(keypad->clk);
+
+	/* go through board initialization helpers */
+	if (keypad->board->init)
+		keypad->board->init();
+
+	error = ske_keypad_chip_init(keypad);
+	if (error) {
+		dev_err(&pdev->dev, "unable to init keypad hardware\n");
+		goto err_clk_disable;
+	}
+
+	error = request_threaded_irq(keypad->irq, NULL, ske_keypad_irq,
+				     IRQF_ONESHOT, "ske-keypad", keypad);
+	if (error) {
+		dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq);
+		goto err_clk_disable;
+	}
+
+	error = input_register_device(input);
+	if (error) {
+		dev_err(&pdev->dev,
+				"unable to register input device: %d\n", error);
+		goto err_free_irq;
+	}
+
+	if (plat->wakeup_enable)
+		device_init_wakeup(&pdev->dev, true);
+
+	platform_set_drvdata(pdev, keypad);
+
+	return 0;
+
+err_free_irq:
+	free_irq(keypad->irq, keypad);
+err_clk_disable:
+	clk_disable(keypad->clk);
+	clk_put(keypad->clk);
+err_iounmap:
+	iounmap(keypad->reg_base);
+err_free_mem_region:
+	release_mem_region(res->start, resource_size(res));
+err_free_mem:
+	input_free_device(input);
+	kfree(keypad);
+	return error;
+}
+
+static int __devexit ske_keypad_remove(struct platform_device *pdev)
+{
+	struct ske_keypad *keypad = platform_get_drvdata(pdev);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	free_irq(keypad->irq, keypad);
+
+	input_unregister_device(keypad->input);
+
+	clk_disable(keypad->clk);
+	clk_put(keypad->clk);
+
+	if (keypad->board->exit)
+		keypad->board->exit();
+
+	iounmap(keypad->reg_base);
+	release_mem_region(res->start, resource_size(res));
+	kfree(keypad);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ske_keypad_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ske_keypad *keypad = platform_get_drvdata(pdev);
+	int irq = platform_get_irq(pdev, 0);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(irq);
+	else
+		ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
+
+	return 0;
+}
+
+static int ske_keypad_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ske_keypad *keypad = platform_get_drvdata(pdev);
+	int irq = platform_get_irq(pdev, 0);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(irq);
+	else
+		ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
+
+	return 0;
+}
+
+static const struct dev_pm_ops ske_keypad_dev_pm_ops = {
+	.suspend = ske_keypad_suspend,
+	.resume = ske_keypad_resume,
+};
+#endif
+
+struct platform_driver ske_keypad_driver = {
+	.driver = {
+		.name = "nmk-ske-keypad",
+		.owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &ske_keypad_dev_pm_ops,
+#endif
+	},
+	.probe = ske_keypad_probe,
+	.remove = __devexit_p(ske_keypad_remove),
+};
+
+static int __init ske_keypad_init(void)
+{
+	return platform_driver_probe(&ske_keypad_driver, ske_keypad_probe);
+}
+module_init(ske_keypad_init);
+
+static void __exit ske_keypad_exit(void)
+{
+	platform_driver_unregister(&ske_keypad_driver);
+}
+module_exit(ske_keypad_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>");
+MODULE_DESCRIPTION("Nomadik Scroll-Key-Encoder Keypad Driver");
+MODULE_ALIAS("platform:nomadik-ske-keypad");
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
new file mode 100644
index 0000000..45bd097
--- /dev/null
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -0,0 +1,318 @@
+/*
+ * 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");
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
index fb16b5e..09bef79 100644
--- a/drivers/input/keyboard/twl4030_keypad.c
+++ b/drivers/input/keyboard/twl4030_keypad.c
@@ -406,23 +406,22 @@
 	if (error) {
 		dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n",
 			kp->irq);
-		goto err3;
+		goto err2;
 	}
 
 	/* Enable KP and TO interrupts now. */
 	reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO);
 	if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) {
 		error = -EIO;
-		goto err4;
+		goto err3;
 	}
 
 	platform_set_drvdata(pdev, kp);
 	return 0;
 
-err4:
+err3:
 	/* mask all events - we don't care about the result */
 	(void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1);
-err3:
 	free_irq(kp->irq, NULL);
 err2:
 	input_unregister_device(input);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index b49e233..b99b8cb 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -22,6 +22,16 @@
 	  To compile this driver as a module, choose M here: the module
 	  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
 	tristate "Analog Devices AD714x Capacitance Touch Sensor"
 	help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 19ccca7..1fe1f6c 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -5,6 +5,7 @@
 # Each configuration option enables a list of files.
 
 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_I2C)		+= ad714x-i2c.o
 obj-$(CONFIG_INPUT_AD714X_SPI)		+= ad714x-spi.o
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
new file mode 100644
index 0000000..3d3288a
--- /dev/null
+++ b/drivers/input/misc/ab8500-ponkey.c
@@ -0,0 +1,157 @@
+/*
+ * 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");
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
index 2325765..0b0e9be 100644
--- a/drivers/input/misc/ati_remote2.c
+++ b/drivers/input/misc/ati_remote2.c
@@ -483,51 +483,88 @@
 }
 
 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);
 	unsigned int mode;
-	int index;
+	int offset;
+	unsigned int index;
+	unsigned int scancode;
 
-	mode = scancode >> 8;
-	if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask))
-		return -EINVAL;
+	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+		index = ke->index;
+		if (index >= ATI_REMOTE2_MODES *
+				ARRAY_SIZE(ati_remote2_key_table))
+			return -EINVAL;
 
-	index = ati_remote2_lookup(scancode & 0xFF);
-	if (index < 0)
-		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;
 
-	*keycode = ar2->keycode[mode][index];
+		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;
+	}
+
+	ke->keycode = ar2->keycode[mode][offset];
+	ke->len = sizeof(scancode);
+	memcpy(&ke->scancode, &scancode, sizeof(scancode));
+	ke->index = index;
+
 	return 0;
 }
 
 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);
-	unsigned int mode, old_keycode;
-	int index;
+	unsigned int mode;
+	int offset;
+	unsigned int index;
+	unsigned int scancode;
 
-	mode = scancode >> 8;
-	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 *
+				ARRAY_SIZE(ati_remote2_key_table))
+			return -EINVAL;
 
-	index = ati_remote2_lookup(scancode & 0xFF);
-	if (index < 0)
-		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;
 
-	old_keycode = ar2->keycode[mode][index];
-	ar2->keycode[mode][index] = keycode;
-	__set_bit(keycode, idev->keybit);
+		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][offset];
+	ar2->keycode[mode][offset] = ke->keycode;
+	__set_bit(ke->keycode, idev->keybit);
 
 	for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
 		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;
 		}
 	}
 
-	__clear_bit(old_keycode, idev->keybit);
+	__clear_bit(*old_keycode, idev->keybit);
 
 	return 0;
 }
@@ -575,8 +612,8 @@
 	idev->open = ati_remote2_open;
 	idev->close = ati_remote2_close;
 
-	idev->getkeycode = ati_remote2_getkeycode;
-	idev->setkeycode = ati_remote2_setkeycode;
+	idev->getkeycode_new = ati_remote2_getkeycode;
+	idev->setkeycode_new = ati_remote2_setkeycode;
 
 	idev->name = ar2->name;
 	idev->phys = ar2->phys;
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c
index bf170f6..f459471 100644
--- a/drivers/input/misc/powermate.c
+++ b/drivers/input/misc/powermate.c
@@ -280,7 +280,7 @@
 
 	pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL);
 	if (!pm->configcr)
-		return -1;
+		return -ENOMEM;
 
 	return 0;
 }
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 4831120..04d9bf3 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -699,7 +699,7 @@
 
 	psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
 	if (!etd)
-		return -1;
+		return -ENOMEM;
 
 	etd->parity[0] = 1;
 	for (i = 1; i < 256; i++)
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 73a7af2..cd9d0c9 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -1584,10 +1584,10 @@
 	if (!new_dev)
 		return -ENOMEM;
 
-	while (serio->child) {
+	while (!list_empty(&serio->children)) {
 		if (++retry > 3) {
 			printk(KERN_WARNING
-				"psmouse: failed to destroy child port, "
+				"psmouse: failed to destroy children ports, "
 				"protocol change aborted.\n");
 			input_free_device(new_dev);
 			return -EIO;
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 96b70a4..2e300a4 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -294,7 +294,29 @@
 	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;
 }
@@ -315,9 +337,8 @@
 
 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 psmouse *child = serio_get_drvdata(priv->pt_port);
 
 	/* adjust the touchpad to child's choice of protocol */
 	if (child) {
@@ -345,6 +366,8 @@
 	strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
 	strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
 	serio->write = synaptics_pt_write;
+	serio->start = synaptics_pt_start;
+	serio->stop = synaptics_pt_stop;
 	serio->parent = psmouse->ps2dev.serio;
 
 	psmouse->pt_activate = synaptics_pt_activate;
@@ -578,9 +601,10 @@
 		if (unlikely(priv->pkt_type == SYN_NEWABS))
 			priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 
-		if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) {
-			if (psmouse->ps2dev.serio->child)
-				synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet);
+		if (SYN_CAP_PASS_THROUGH(priv->capabilities) &&
+		    synaptics_is_pt_packet(psmouse->packet)) {
+			if (priv->pt_port)
+				synaptics_pass_pt_packet(priv->pt_port, psmouse->packet);
 		} else
 			synaptics_process_packet(psmouse);
 
@@ -731,7 +755,7 @@
 
 	psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
 	if (!priv)
-		return -1;
+		return -ENOMEM;
 
 	psmouse_reset(psmouse);
 
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
index b6aa7d2..613a365 100644
--- a/drivers/input/mouse/synaptics.h
+++ b/drivers/input/mouse/synaptics.h
@@ -110,6 +110,8 @@
 	unsigned char pkt_type;			/* packet type - old, new, etc */
 	unsigned char mode;			/* current mode byte */
 	int scroll;
+
+	struct serio *pt_port;			/* Pass-through serio port */
 };
 
 void synaptics_module_init(void);
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 0643e49..54b2fa8 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -303,7 +303,7 @@
 
 	psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
 	if (!psmouse->private)
-		return -1;
+		return -ENOMEM;
 
 	psmouse->vendor = "IBM";
 	psmouse->name = "TrackPoint";
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 31ec726..2a00ddf 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -867,7 +867,7 @@
 	spin_lock_init(&mousedev->client_lock);
 	mutex_init(&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);
 
 	if (minor == MOUSEDEV_MIX)
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 3bfe8fa..6256233 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -226,4 +226,13 @@
 	  To compile this driver as a module, choose M here;
 	  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
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 84c80bf..dbbe376 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -18,6 +18,7 @@
 obj-$(CONFIG_HP_SDC)		+= hp_sdc.o
 obj-$(CONFIG_HIL_MLC)		+= hp_sdc_mlc.o hil_mlc.o
 obj-$(CONFIG_SERIO_PCIPS2)	+= pcips2.o
+obj-$(CONFIG_SERIO_PS2MULT)	+= ps2mult.o
 obj-$(CONFIG_SERIO_MACEPS2)	+= maceps2.o
 obj-$(CONFIG_SERIO_LIBPS2)	+= libps2.o
 obj-$(CONFIG_SERIO_RAW)		+= serio_raw.o
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index f585131..18db5a8 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -1063,7 +1063,7 @@
 #ifdef CONFIG_X86
 static void i8042_dritek_enable(void)
 {
-	char param = 0x90;
+	unsigned char param = 0x90;
 	int error;
 
 	error = i8042_command(&param, 0x1059);
diff --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c
new file mode 100644
index 0000000..6bce22e
--- /dev/null
+++ b/drivers/input/serio/ps2mult.c
@@ -0,0 +1,318 @@
+/*
+ * 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);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index c3b626e..405bf21 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -37,7 +37,6 @@
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
-#include <linux/freezer.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Serio abstraction core");
@@ -56,7 +55,7 @@
 static void serio_add_port(struct serio *serio);
 static int serio_reconnect_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 int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
@@ -152,7 +151,7 @@
 enum serio_event_type {
 	SERIO_RESCAN_PORT,
 	SERIO_RECONNECT_PORT,
-	SERIO_RECONNECT_CHAIN,
+	SERIO_RECONNECT_SUBTREE,
 	SERIO_REGISTER_PORT,
 	SERIO_ATTACH_DRIVER,
 };
@@ -292,8 +291,8 @@
 			serio_find_driver(event->object);
 			break;
 
-		case SERIO_RECONNECT_CHAIN:
-			serio_reconnect_chain(event->object);
+		case SERIO_RECONNECT_SUBTREE:
+			serio_reconnect_subtree(event->object);
 			break;
 
 		case SERIO_ATTACH_DRIVER:
@@ -330,12 +329,10 @@
 }
 
 /*
- * 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
- * only one child registration request can be pending. Additionally, children
- * are registered by driver's connect() handler so there can't be a grandchild
- * pending registration together with a child.
+ * Children 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)
 {
@@ -449,7 +446,7 @@
 	if (!strncmp(buf, "none", count)) {
 		serio_disconnect_port(serio);
 	} else if (!strncmp(buf, "reconnect", count)) {
-		serio_reconnect_chain(serio);
+		serio_reconnect_subtree(serio);
 	} else if (!strncmp(buf, "rescan", count)) {
 		serio_disconnect_port(serio);
 		serio_find_driver(serio);
@@ -516,6 +513,8 @@
 	__module_get(THIS_MODULE);
 
 	INIT_LIST_HEAD(&serio->node);
+	INIT_LIST_HEAD(&serio->child_node);
+	INIT_LIST_HEAD(&serio->children);
 	spin_lock_init(&serio->lock);
 	mutex_init(&serio->drv_mutex);
 	device_initialize(&serio->dev);
@@ -538,12 +537,13 @@
  */
 static void serio_add_port(struct serio *serio)
 {
+	struct serio *parent = serio->parent;
 	int error;
 
-	if (serio->parent) {
-		serio_pause_rx(serio->parent);
-		serio->parent->child = serio;
-		serio_continue_rx(serio->parent);
+	if (parent) {
+		serio_pause_rx(parent);
+		list_add_tail(&serio->child_node, &parent->children);
+		serio_continue_rx(parent);
 	}
 
 	list_add_tail(&serio->node, &serio_list);
@@ -559,15 +559,14 @@
 }
 
 /*
- * serio_destroy_port() completes deregistration process and removes
+ * serio_destroy_port() completes unregistration process and removes
  * port from the system
  */
 static void serio_destroy_port(struct serio *serio)
 {
 	struct serio *child;
 
-	child = serio_get_pending_child(serio);
-	if (child) {
+	while ((child = serio_get_pending_child(serio)) != NULL) {
 		serio_remove_pending_events(child);
 		put_device(&child->dev);
 	}
@@ -577,7 +576,7 @@
 
 	if (serio->parent) {
 		serio_pause_rx(serio->parent);
-		serio->parent->child = NULL;
+		list_del_init(&serio->child_node);
 		serio_continue_rx(serio->parent);
 		serio->parent = NULL;
 	}
@@ -609,46 +608,82 @@
 }
 
 /*
- * 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 {
-		if (serio_reconnect_port(serio)) {
-			/* Ok, old children are now gone, we are done */
-			break;
+		error = serio_reconnect_port(s);
+		if (!error) {
+			/*
+			 * 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
- * all child ports are unbound and destroyed.
+ * all children ports are unbound and destroyed.
  */
 static void serio_disconnect_port(struct serio *serio)
 {
-	struct serio *s, *parent;
+	struct serio *s = serio;
 
-	if (serio->child) {
+	/*
+	 * 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);
+
 		/*
-		 * Children ports should be disconnected and destroyed
-		 * first, staring with the leaf one, since we don't want
-		 * to do recursion
+		 * Prune this leaf node unless it is the one we
+		 * started with.
 		 */
-		for (s = serio; s->child; s = s->child)
-			/* empty */;
-
-		do {
-			parent = s->parent;
+		if (s != serio) {
+			struct serio *parent = s->parent;
 
 			device_release_driver(&s->dev);
 			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);
 }
@@ -661,7 +696,7 @@
 
 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);
 
@@ -689,14 +724,16 @@
 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)
 {
+	struct serio *s, *next;
+
 	mutex_lock(&serio_mutex);
-	if (serio->child) {
-		serio_disconnect_port(serio->child);
-		serio_destroy_port(serio->child);
+	list_for_each_entry_safe(s, next, &serio->children, child_node) {
+		serio_disconnect_port(s);
+		serio_destroy_port(s);
 	}
 	mutex_unlock(&serio_mutex);
 }
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c
index 0142483..a29a7812 100644
--- a/drivers/input/sparse-keymap.c
+++ b/drivers/input/sparse-keymap.c
@@ -22,6 +22,37 @@
 MODULE_LICENSE("GPL v2");
 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
  * @dev: Input device using sparse keymap
@@ -64,16 +95,36 @@
 }
 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,
-				    unsigned int scancode,
-				    unsigned int *keycode)
+				    struct input_keymap_entry *ke)
 {
 	const struct key_entry *key;
 
 	if (dev->keycode) {
-		key = sparse_keymap_entry_from_scancode(dev, scancode);
+		key = sparse_keymap_locate(dev, ke);
 		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;
 		}
 	}
@@ -82,20 +133,19 @@
 }
 
 static int sparse_keymap_setkeycode(struct input_dev *dev,
-				    unsigned int scancode,
-				    unsigned int keycode)
+				    const struct input_keymap_entry *ke,
+				    unsigned int *old_keycode)
 {
 	struct key_entry *key;
-	int old_keycode;
 
 	if (dev->keycode) {
-		key = sparse_keymap_entry_from_scancode(dev, scancode);
+		key = sparse_keymap_locate(dev, ke);
 		if (key && key->type == KE_KEY) {
-			old_keycode = key->keycode;
-			key->keycode = keycode;
-			set_bit(keycode, dev->keybit);
-			if (!sparse_keymap_entry_from_keycode(dev, old_keycode))
-				clear_bit(old_keycode, dev->keybit);
+			*old_keycode = key->keycode;
+			key->keycode = ke->keycode;
+			set_bit(ke->keycode, dev->keybit);
+			if (!sparse_keymap_entry_from_keycode(dev, *old_keycode))
+				clear_bit(*old_keycode, dev->keybit);
 			return 0;
 		}
 	}
@@ -159,15 +209,14 @@
 
 	dev->keycode = map;
 	dev->keycodemax = map_size;
-	dev->getkeycode = sparse_keymap_getkeycode;
-	dev->setkeycode = sparse_keymap_setkeycode;
+	dev->getkeycode_new = sparse_keymap_getkeycode;
+	dev->setkeycode_new = sparse_keymap_setkeycode;
 
 	return 0;
 
  err_out:
 	kfree(map);
 	return error;
-
 }
 EXPORT_SYMBOL(sparse_keymap_setup);
 
diff --git a/drivers/input/tablet/Kconfig b/drivers/input/tablet/Kconfig
index effb49e..58a8775 100644
--- a/drivers/input/tablet/Kconfig
+++ b/drivers/input/tablet/Kconfig
@@ -49,6 +49,17 @@
           To compile this driver as a module, choose M here: the
           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
 	tristate "KB Gear JamStudio tablet support (USB)"
 	depends on USB_ARCH_HAS_HCD
diff --git a/drivers/input/tablet/Makefile b/drivers/input/tablet/Makefile
index ce8b9a9..3f6c252 100644
--- a/drivers/input/tablet/Makefile
+++ b/drivers/input/tablet/Makefile
@@ -8,5 +8,6 @@
 obj-$(CONFIG_TABLET_USB_ACECAD)	+= acecad.o
 obj-$(CONFIG_TABLET_USB_AIPTEK)	+= aiptek.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_WACOM)	+= wacom.o
diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c
new file mode 100644
index 0000000..6504b62
--- /dev/null
+++ b/drivers/input/tablet/hanwang.c
@@ -0,0 +1,446 @@
+/*
+ *  USB Hanwang tablet support
+ *
+ *  Copyright (c) 2010 Xing Wei <weixing@hanwang.com.cn>
+ *
+ */
+
+/*
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb/input.h>
+
+#define DRIVER_AUTHOR   "Xing Wei <weixing@hanwang.com.cn>"
+#define DRIVER_DESC     "USB Hanwang tablet driver"
+#define DRIVER_LICENSE  "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+#define USB_VENDOR_ID_HANWANG		0x0b57
+#define HANWANG_TABLET_INT_CLASS	0x0003
+#define HANWANG_TABLET_INT_SUB_CLASS	0x0001
+#define HANWANG_TABLET_INT_PROTOCOL	0x0002
+
+#define ART_MASTER_PKGLEN_MAX	10
+
+/* device IDs */
+#define STYLUS_DEVICE_ID	0x02
+#define TOUCH_DEVICE_ID		0x03
+#define CURSOR_DEVICE_ID	0x06
+#define ERASER_DEVICE_ID	0x0A
+#define PAD_DEVICE_ID		0x0F
+
+/* match vendor and interface info  */
+#define HANWANG_TABLET_DEVICE(vend, cl, sc, pr) \
+	.match_flags = USB_DEVICE_ID_MATCH_VENDOR \
+		| USB_DEVICE_ID_MATCH_INT_INFO, \
+	.idVendor = (vend), \
+	.bInterfaceClass = (cl), \
+	.bInterfaceSubClass = (sc), \
+	.bInterfaceProtocol = (pr)
+
+enum hanwang_tablet_type {
+	HANWANG_ART_MASTER_III,
+	HANWANG_ART_MASTER_HD,
+};
+
+struct hanwang {
+	unsigned char *data;
+	dma_addr_t data_dma;
+	struct input_dev *dev;
+	struct usb_device *usbdev;
+	struct urb *irq;
+	const struct hanwang_features *features;
+	unsigned int current_tool;
+	unsigned int current_id;
+	char name[64];
+	char phys[32];
+};
+
+struct hanwang_features {
+	unsigned short pid;
+	char *name;
+	enum hanwang_tablet_type type;
+	int pkg_len;
+	int max_x;
+	int max_y;
+	int max_tilt_x;
+	int max_tilt_y;
+	int max_pressure;
+};
+
+static const struct hanwang_features features_array[] = {
+	{ 0x8528, "Hanwang Art Master III 0906", HANWANG_ART_MASTER_III,
+	  ART_MASTER_PKGLEN_MAX, 0x5757, 0x3692, 0x3f, 0x7f, 2048 },
+	{ 0x8529, "Hanwang Art Master III 0604", HANWANG_ART_MASTER_III,
+	  ART_MASTER_PKGLEN_MAX, 0x3d84, 0x2672, 0x3f, 0x7f, 2048 },
+	{ 0x852a, "Hanwang Art Master III 1308", HANWANG_ART_MASTER_III,
+	  ART_MASTER_PKGLEN_MAX, 0x7f00, 0x4f60, 0x3f, 0x7f, 2048 },
+	{ 0x8401, "Hanwang Art Master HD 5012", HANWANG_ART_MASTER_HD,
+	  ART_MASTER_PKGLEN_MAX, 0x678e, 0x4150, 0x3f, 0x7f, 1024 },
+};
+
+static const int hw_eventtypes[] = {
+	EV_KEY, EV_ABS, EV_MSC,
+};
+
+static const int hw_absevents[] = {
+	ABS_X, ABS_Y, ABS_TILT_X, ABS_TILT_Y, ABS_WHEEL,
+	ABS_RX, ABS_RY, ABS_PRESSURE, ABS_MISC,
+};
+
+static const int hw_btnevents[] = {
+	BTN_STYLUS, BTN_STYLUS2, BTN_TOOL_PEN, BTN_TOOL_RUBBER,
+	BTN_TOOL_MOUSE, BTN_TOOL_FINGER,
+	BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8,
+};
+
+static const int hw_mscevents[] = {
+	MSC_SERIAL,
+};
+
+static void hanwang_parse_packet(struct hanwang *hanwang)
+{
+	unsigned char *data = hanwang->data;
+	struct input_dev *input_dev = hanwang->dev;
+	struct usb_device *dev = hanwang->usbdev;
+	enum hanwang_tablet_type type = hanwang->features->type;
+	int i;
+	u16 x, y, p;
+
+	switch (data[0]) {
+	case 0x02:	/* data packet */
+		switch (data[1]) {
+		case 0x80:	/* tool prox out */
+			hanwang->current_id = 0;
+			input_report_key(input_dev, hanwang->current_tool, 0);
+			break;
+
+		case 0xc2:	/* first time tool prox in */
+			switch (data[3] & 0xf0) {
+			case 0x20:	/* art_master III */
+			case 0x30:	/* art_master_HD */
+				hanwang->current_id = STYLUS_DEVICE_ID;
+				hanwang->current_tool = BTN_TOOL_PEN;
+				input_report_key(input_dev, BTN_TOOL_PEN, 1);
+				break;
+			case 0xa0:	/* art_master III */
+			case 0xb0:	/* art_master_HD */
+				hanwang->current_id = ERASER_DEVICE_ID;
+				hanwang->current_tool = BTN_TOOL_RUBBER;
+				input_report_key(input_dev, BTN_TOOL_RUBBER, 1);
+				break;
+			default:
+				hanwang->current_id = 0;
+				dev_dbg(&dev->dev,
+					"unknown tablet tool %02x ", data[0]);
+				break;
+			}
+			break;
+
+		default:	/* tool data packet */
+			x = (data[2] << 8) | data[3];
+			y = (data[4] << 8) | data[5];
+
+			switch (type) {
+			case HANWANG_ART_MASTER_III:
+				p = (data[6] << 3) |
+				    ((data[7] & 0xc0) >> 5) |
+				    (data[1] & 0x01);
+				break;
+
+			case HANWANG_ART_MASTER_HD:
+				p = (data[7] >> 6) | (data[6] << 2);
+				break;
+
+			default:
+				p = 0;
+				break;
+			}
+
+			input_report_abs(input_dev, ABS_X,
+						le16_to_cpup((__le16 *)&x));
+			input_report_abs(input_dev, ABS_Y,
+						le16_to_cpup((__le16 *)&y));
+			input_report_abs(input_dev, ABS_PRESSURE,
+						le16_to_cpup((__le16 *)&p));
+			input_report_abs(input_dev, ABS_TILT_X, data[7] & 0x3f);
+			input_report_abs(input_dev, ABS_TILT_Y, data[8] & 0x7f);
+			input_report_key(input_dev, BTN_STYLUS, data[1] & 0x02);
+			input_report_key(input_dev, BTN_STYLUS2, data[1] & 0x04);
+			break;
+		}
+		input_report_abs(input_dev, ABS_MISC, hanwang->current_id);
+		input_event(input_dev, EV_MSC, MSC_SERIAL,
+				hanwang->features->pid);
+		break;
+
+	case 0x0c:
+		/* roll wheel */
+		hanwang->current_id = PAD_DEVICE_ID;
+
+		switch (type) {
+		case HANWANG_ART_MASTER_III:
+			input_report_key(input_dev, BTN_TOOL_FINGER, data[1] ||
+							data[2] || data[3]);
+			input_report_abs(input_dev, ABS_WHEEL, data[1]);
+			input_report_key(input_dev, BTN_0, data[2]);
+			for (i = 0; i < 8; i++)
+				input_report_key(input_dev,
+					 BTN_1 + i, data[3] & (1 << i));
+			break;
+
+		case HANWANG_ART_MASTER_HD:
+			input_report_key(input_dev, BTN_TOOL_FINGER, data[1] ||
+					data[2] || data[3] || data[4] ||
+					data[5] || data[6]);
+			input_report_abs(input_dev, ABS_RX,
+					((data[1] & 0x1f) << 8) | data[2]);
+			input_report_abs(input_dev, ABS_RY,
+					((data[3] & 0x1f) << 8) | data[4]);
+			input_report_key(input_dev, BTN_0, data[5] & 0x01);
+			for (i = 0; i < 4; i++) {
+				input_report_key(input_dev,
+					 BTN_1 + i, data[5] & (1 << i));
+				input_report_key(input_dev,
+					 BTN_5 + i, data[6] & (1 << i));
+			}
+			break;
+		}
+
+		input_report_abs(input_dev, ABS_MISC, hanwang->current_id);
+		input_event(input_dev, EV_MSC, MSC_SERIAL, 0xffffffff);
+		break;
+
+	default:
+		dev_dbg(&dev->dev, "error packet  %02x ", data[0]);
+		break;
+	}
+
+	input_sync(input_dev);
+}
+
+static void hanwang_irq(struct urb *urb)
+{
+	struct hanwang *hanwang = urb->context;
+	struct usb_device *dev = hanwang->usbdev;
+	int retval;
+
+	switch (urb->status) {
+	case 0:
+		/* success */;
+		hanwang_parse_packet(hanwang);
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dev_err(&dev->dev, "%s - urb shutting down with status: %d",
+			__func__, urb->status);
+		return;
+	default:
+		dev_err(&dev->dev, "%s - nonzero urb status received: %d",
+			__func__, urb->status);
+		break;
+	}
+
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval)
+		dev_err(&dev->dev, "%s - usb_submit_urb failed with result %d",
+			__func__, retval);
+}
+
+static int hanwang_open(struct input_dev *dev)
+{
+	struct hanwang *hanwang = input_get_drvdata(dev);
+
+	hanwang->irq->dev = hanwang->usbdev;
+	if (usb_submit_urb(hanwang->irq, GFP_KERNEL))
+		return -EIO;
+
+	return 0;
+}
+
+static void hanwang_close(struct input_dev *dev)
+{
+	struct hanwang *hanwang = input_get_drvdata(dev);
+
+	usb_kill_urb(hanwang->irq);
+}
+
+static bool get_features(struct usb_device *dev, struct hanwang *hanwang)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(features_array); i++) {
+		if (le16_to_cpu(dev->descriptor.idProduct) ==
+				features_array[i].pid) {
+			hanwang->features = &features_array[i];
+			return true;
+		}
+	}
+
+	return false;
+}
+
+
+static int hanwang_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct usb_endpoint_descriptor *endpoint;
+	struct hanwang *hanwang;
+	struct input_dev *input_dev;
+	int error;
+	int i;
+
+	hanwang = kzalloc(sizeof(struct hanwang), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!hanwang || !input_dev) {
+		error = -ENOMEM;
+		goto fail1;
+	}
+
+	if (!get_features(dev, hanwang)) {
+		error = -ENXIO;
+		goto fail1;
+	}
+
+	hanwang->data = usb_alloc_coherent(dev, hanwang->features->pkg_len,
+					GFP_KERNEL, &hanwang->data_dma);
+	if (!hanwang->data) {
+		error = -ENOMEM;
+		goto fail1;
+	}
+
+	hanwang->irq = usb_alloc_urb(0, GFP_KERNEL);
+	if (!hanwang->irq) {
+		error = -ENOMEM;
+		goto fail2;
+	}
+
+	hanwang->usbdev = dev;
+	hanwang->dev = input_dev;
+
+	usb_make_path(dev, hanwang->phys, sizeof(hanwang->phys));
+	strlcat(hanwang->phys, "/input0", sizeof(hanwang->phys));
+
+	strlcpy(hanwang->name, hanwang->features->name, sizeof(hanwang->name));
+	input_dev->name = hanwang->name;
+	input_dev->phys = hanwang->phys;
+	usb_to_input_id(dev, &input_dev->id);
+	input_dev->dev.parent = &intf->dev;
+
+	input_set_drvdata(input_dev, hanwang);
+
+	input_dev->open = hanwang_open;
+	input_dev->close = hanwang_close;
+
+	for (i = 0; i < ARRAY_SIZE(hw_eventtypes); ++i)
+		__set_bit(hw_eventtypes[i], input_dev->evbit);
+
+	for (i = 0; i < ARRAY_SIZE(hw_absevents); ++i)
+		__set_bit(hw_absevents[i], input_dev->absbit);
+
+	for (i = 0; i < ARRAY_SIZE(hw_btnevents); ++i)
+		__set_bit(hw_btnevents[i], input_dev->keybit);
+
+	for (i = 0; i < ARRAY_SIZE(hw_mscevents); ++i)
+		__set_bit(hw_mscevents[i], input_dev->mscbit);
+
+	input_set_abs_params(input_dev, ABS_X,
+			     0, hanwang->features->max_x, 4, 0);
+	input_set_abs_params(input_dev, ABS_Y,
+			     0, hanwang->features->max_y, 4, 0);
+	input_set_abs_params(input_dev, ABS_TILT_X,
+			     0, hanwang->features->max_tilt_x, 0, 0);
+	input_set_abs_params(input_dev, ABS_TILT_Y,
+			     0, hanwang->features->max_tilt_y, 0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE,
+			     0, hanwang->features->max_pressure, 0, 0);
+
+	endpoint = &intf->cur_altsetting->endpoint[0].desc;
+	usb_fill_int_urb(hanwang->irq, dev,
+			usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+			hanwang->data, hanwang->features->pkg_len,
+			hanwang_irq, hanwang, endpoint->bInterval);
+	hanwang->irq->transfer_dma = hanwang->data_dma;
+	hanwang->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	error = input_register_device(hanwang->dev);
+	if (error)
+		goto fail3;
+
+	usb_set_intfdata(intf, hanwang);
+
+	return 0;
+
+ fail3:	usb_free_urb(hanwang->irq);
+ fail2:	usb_free_coherent(dev, hanwang->features->pkg_len,
+			hanwang->data, hanwang->data_dma);
+ fail1:	input_free_device(input_dev);
+	kfree(hanwang);
+	return error;
+
+}
+
+static void hanwang_disconnect(struct usb_interface *intf)
+{
+	struct hanwang *hanwang = usb_get_intfdata(intf);
+
+	input_unregister_device(hanwang->dev);
+	usb_free_urb(hanwang->irq);
+	usb_free_coherent(interface_to_usbdev(intf),
+			hanwang->features->pkg_len, hanwang->data,
+			hanwang->data_dma);
+	kfree(hanwang);
+	usb_set_intfdata(intf, NULL);
+}
+
+static const struct usb_device_id hanwang_ids[] = {
+	{ HANWANG_TABLET_DEVICE(USB_VENDOR_ID_HANWANG, HANWANG_TABLET_INT_CLASS,
+		HANWANG_TABLET_INT_SUB_CLASS, HANWANG_TABLET_INT_PROTOCOL) },
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, hanwang_ids);
+
+static struct usb_driver hanwang_driver = {
+	.name		= "hanwang",
+	.probe		= hanwang_probe,
+	.disconnect	= hanwang_disconnect,
+	.id_table	= hanwang_ids,
+};
+
+static int __init hanwang_init(void)
+{
+	return usb_register(&hanwang_driver);
+}
+
+static void __exit hanwang_exit(void)
+{
+	usb_deregister(&hanwang_driver);
+}
+
+module_init(hanwang_init);
+module_exit(hanwang_exit);
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h
index 284dfaa..de5adb1 100644
--- a/drivers/input/tablet/wacom.h
+++ b/drivers/input/tablet/wacom.h
@@ -118,6 +118,7 @@
 extern const struct usb_device_id wacom_ids[];
 
 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,
 				    struct wacom_wac *wacom_wac);
 #endif
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index b35876e..fc38149 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -120,14 +120,16 @@
 
 out:
 	mutex_unlock(&wacom->lock);
-	if (retval)
-		usb_autopm_put_interface(wacom->intf);
+	usb_autopm_put_interface(wacom->intf);
 	return retval;
 }
 
 static void wacom_close(struct input_dev *dev)
 {
 	struct wacom *wacom = input_get_drvdata(dev);
+	int autopm_error;
+
+	autopm_error = usb_autopm_get_interface(wacom->intf);
 
 	mutex_lock(&wacom->lock);
 	usb_kill_urb(wacom->irq);
@@ -135,7 +137,8 @@
 	wacom->intf->needs_remote_wakeup = 0;
 	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,
@@ -196,17 +199,30 @@
 							features->pktlen = WACOM_PKGLEN_TPC2FG;
 							features->device_type = BTN_TOOL_TRIPLETAP;
 						}
-						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;
+						if (features->type == BAMBOO_PT) {
+							/* need to reset back */
+							features->pktlen = WACOM_PKGLEN_BBTOUCH;
+							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->x_phy =
+								get_unaligned_le16(&report[i + 5]);
+							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) {
 						/* penabled only accepts exact bytes of data */
 						if (features->type == TABLETPC2FG)
 							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+						if (features->type == BAMBOO_PT)
+							features->pktlen = WACOM_PKGLEN_BBFUN;
 						features->device_type = BTN_TOOL_PEN;
 						features->x_max =
 							get_unaligned_le16(&report[i + 3]);
@@ -235,6 +251,15 @@
 							features->y_phy =
 								get_unaligned_le16(&report[i + 6]);
 							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 {
 							features->y_max =
 								features->x_max;
@@ -246,6 +271,8 @@
 						/* penabled only accepts exact bytes of data */
 						if (features->type == TABLETPC2FG)
 							features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+						if (features->type == BAMBOO_PT)
+							features->pktlen = WACOM_PKGLEN_BBFUN;
 						features->device_type = BTN_TOOL_PEN;
 						features->y_max =
 							get_unaligned_le16(&report[i + 3]);
@@ -296,8 +323,9 @@
 	if (!rep_data)
 		return error;
 
-	/* ask to report tablet data if it is 2FGT or not a Tablet PC */
-	if (features->device_type == BTN_TOOL_TRIPLETAP) {
+	/* ask to report tablet data if it is 2FGT Tablet PC or
+	 * not a Tablet PC */
+	if (features->type == TABLETPC2FG) {
 		do {
 			rep_data[0] = 3;
 			rep_data[1] = 4;
@@ -309,7 +337,7 @@
 					WAC_HID_FEATURE_REPORT, report_id,
 					rep_data, 3);
 		} while ((error < 0 || rep_data[1] != 4) && limit++ < 5);
-	} else if (features->type != TABLETPC && features->type != TABLETPC2FG) {
+	} else if (features->type != TABLETPC) {
 		do {
 			rep_data[0] = 2;
 			rep_data[1] = 2;
@@ -334,11 +362,16 @@
 	struct usb_host_interface *interface = intf->cur_altsetting;
 	struct hid_descriptor *hid_desc;
 
-	/* default device to penabled */
+	/* default features */
 	features->device_type = BTN_TOOL_PEN;
+	features->x_fuzz = 4;
+	features->y_fuzz = 4;
+	features->pressure_fuzz = 0;
+	features->distance_fuzz = 0;
 
-	/* only Tablet PCs need to retrieve the info */
-	if ((features->type != TABLETPC) && (features->type != TABLETPC2FG))
+	/* 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;
 
 	if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
@@ -353,12 +386,6 @@
 	if (error)
 		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:
 	return error;
 }
@@ -494,9 +521,11 @@
 	if (error)
 		goto fail2;
 
+	wacom_setup_device_quirks(features);
+
 	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 */
 		strlcat(wacom_wac->name,
 			features->device_type == BTN_TOOL_PEN ?
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 47fd7a0..b3252ef 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -857,6 +857,134 @@
 	return retval;
 }
 
+static int wacom_bpt_touch(struct wacom_wac *wacom)
+{
+	struct wacom_features *features = &wacom->features;
+	struct input_dev *input = wacom->input;
+	unsigned char *data = wacom->data;
+	int sp = 0, sx = 0, sy = 0, count = 0;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		int p = data[9 * i + 2];
+		input_mt_slot(input, i);
+		/*
+		 * Touch events need to be disabled while stylus is
+		 * in proximity because user's hand is resting on touchpad
+		 * and sending unwanted events.  User expects tablet buttons
+		 * to continue working though.
+		 */
+		if (p && !wacom->shared->stylus_in_proximity) {
+			int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff;
+			int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff;
+			if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
+				x <<= 5;
+				y <<= 5;
+			}
+			input_report_abs(input, ABS_MT_PRESSURE, p);
+			input_report_abs(input, ABS_MT_POSITION_X, x);
+			input_report_abs(input, ABS_MT_POSITION_Y, y);
+			if (wacom->id[i] < 0)
+				wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID;
+			if (!count++)
+				sp = p, sx = x, sy = y;
+		} else {
+			wacom->id[i] = -1;
+		}
+		input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]);
+	}
+
+	input_report_key(input, BTN_TOUCH, count > 0);
+	input_report_key(input, BTN_TOOL_FINGER, count == 1);
+	input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2);
+
+	input_report_abs(input, ABS_PRESSURE, sp);
+	input_report_abs(input, ABS_X, sx);
+	input_report_abs(input, ABS_Y, sy);
+
+	input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
+	input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
+	input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
+	input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
+
+	input_sync(input);
+
+	return 0;
+}
+
+static int wacom_bpt_pen(struct wacom_wac *wacom)
+{
+	struct input_dev *input = wacom->input;
+	unsigned char *data = wacom->data;
+	int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
+
+	/*
+	 * Similar to Graphire protocol, data[1] & 0x20 is proximity and
+	 * data[1] & 0x18 is tool ID.  0x30 is safety check to ignore
+	 * 2 unused tool ID's.
+	 */
+	prox = (data[1] & 0x30) == 0x30;
+
+	/*
+	 * All reports shared between PEN and RUBBER tool must be
+	 * forced to a known starting value (zero) when transitioning to
+	 * out-of-prox.
+	 *
+	 * If not reset then, to userspace, it will look like lost events
+	 * if new tool comes in-prox with same values as previous tool sent.
+	 *
+	 * Hardware does report zero in most out-of-prox cases but not all.
+	 */
+	if (prox) {
+		if (!wacom->shared->stylus_in_proximity) {
+			if (data[1] & 0x08) {
+				wacom->tool[0] = BTN_TOOL_RUBBER;
+				wacom->id[0] = ERASER_DEVICE_ID;
+			} else {
+				wacom->tool[0] = BTN_TOOL_PEN;
+				wacom->id[0] = STYLUS_DEVICE_ID;
+			}
+			wacom->shared->stylus_in_proximity = true;
+		}
+		x = le16_to_cpup((__le16 *)&data[2]);
+		y = le16_to_cpup((__le16 *)&data[4]);
+		p = le16_to_cpup((__le16 *)&data[6]);
+		d = data[8];
+		pen = data[1] & 0x01;
+		btn1 = data[1] & 0x02;
+		btn2 = data[1] & 0x04;
+	}
+
+	input_report_key(input, BTN_TOUCH, pen);
+	input_report_key(input, BTN_STYLUS, btn1);
+	input_report_key(input, BTN_STYLUS2, btn2);
+
+	input_report_abs(input, ABS_X, x);
+	input_report_abs(input, ABS_Y, y);
+	input_report_abs(input, ABS_PRESSURE, p);
+	input_report_abs(input, ABS_DISTANCE, d);
+
+	if (!prox) {
+		wacom->id[0] = 0;
+		wacom->shared->stylus_in_proximity = false;
+	}
+
+	input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */
+	input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
+
+	return 1;
+}
+
+static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
+{
+	if (len == WACOM_PKGLEN_BBTOUCH)
+		return wacom_bpt_touch(wacom);
+	else if (len == WACOM_PKGLEN_BBFUN)
+		return wacom_bpt_pen(wacom);
+
+	return 0;
+}
+
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
 {
 	bool sync;
@@ -902,6 +1030,10 @@
 		sync = wacom_tpc_irq(wacom_wac, len);
 		break;
 
+	case BAMBOO_PT:
+		sync = wacom_bpt_irq(wacom_wac, len);
+		break;
+
 	default:
 		sync = false;
 		break;
@@ -911,26 +1043,17 @@
 		input_sync(wacom_wac->input);
 }
 
-static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
+static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
 {
 	struct input_dev *input_dev = wacom_wac->input;
 
 	input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
-	input_set_capability(input_dev, EV_REL, REL_WHEEL);
-
-	__set_bit(BTN_LEFT, input_dev->keybit);
-	__set_bit(BTN_RIGHT, input_dev->keybit);
-	__set_bit(BTN_MIDDLE, input_dev->keybit);
-	__set_bit(BTN_SIDE, input_dev->keybit);
-	__set_bit(BTN_EXTRA, input_dev->keybit);
 
 	__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
 	__set_bit(BTN_TOOL_PEN, input_dev->keybit);
-	__set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
 	__set_bit(BTN_TOOL_BRUSH, input_dev->keybit);
 	__set_bit(BTN_TOOL_PENCIL, input_dev->keybit);
 	__set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
-	__set_bit(BTN_TOOL_LENS, input_dev->keybit);
 	__set_bit(BTN_STYLUS, input_dev->keybit);
 	__set_bit(BTN_STYLUS2, input_dev->keybit);
 
@@ -939,10 +1062,55 @@
 	input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
 	input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
 	input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+}
+
+static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
+{
+	struct input_dev *input_dev = wacom_wac->input;
+
+	input_set_capability(input_dev, EV_REL, REL_WHEEL);
+
+	wacom_setup_cintiq(wacom_wac);
+
+	__set_bit(BTN_LEFT, input_dev->keybit);
+	__set_bit(BTN_RIGHT, input_dev->keybit);
+	__set_bit(BTN_MIDDLE, input_dev->keybit);
+	__set_bit(BTN_SIDE, input_dev->keybit);
+	__set_bit(BTN_EXTRA, input_dev->keybit);
+	__set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+	__set_bit(BTN_TOOL_LENS, input_dev->keybit);
+
 	input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
 	input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
 }
 
+void wacom_setup_device_quirks(struct wacom_features *features)
+{
+
+	/* 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;
+	}
+
+	/* these device have multiple inputs */
+	if (features->type == TABLETPC || features->type == TABLETPC2FG ||
+	    features->type == BAMBOO_PT)
+		features->quirks |= WACOM_QUIRK_MULTI_INPUT;
+
+	/* quirks for bamboo touch */
+	if (features->type == BAMBOO_PT &&
+	    features->device_type == BTN_TOOL_TRIPLETAP) {
+		features->x_max <<= 5;
+		features->y_max <<= 5;
+		features->x_fuzz <<= 5;
+		features->y_fuzz <<= 5;
+		features->pressure_max = 256;
+		features->pressure_fuzz = 16;
+		features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
+	}
+}
+
 void wacom_setup_input_capabilities(struct input_dev *input_dev,
 				    struct wacom_wac *wacom_wac)
 {
@@ -953,9 +1121,12 @@
 
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 
-	input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
-	input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_X, 0, features->x_max,
+			     features->x_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, features->y_max,
+			     features->y_fuzz, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max,
+			     features->pressure_fuzz, 0);
 
 	__set_bit(ABS_MISC, input_dev->absbit);
 
@@ -1005,9 +1176,19 @@
 		__set_bit(BTN_9, input_dev->keybit);
 		/* fall through */
 
+	case CINTIQ:
+		for (i = 0; i < 8; i++)
+			__set_bit(BTN_0 + i, input_dev->keybit);
+		__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+
+		input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+		input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+		wacom_setup_cintiq(wacom_wac);
+		break;
+
 	case INTUOS3:
 	case INTUOS3L:
-	case CINTIQ:
 		__set_bit(BTN_4, input_dev->keybit);
 		__set_bit(BTN_5, input_dev->keybit);
 		__set_bit(BTN_6, input_dev->keybit);
@@ -1078,6 +1259,38 @@
 	case PENPARTNER:
 		__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
 		break;
+
+	case BAMBOO_PT:
+		__clear_bit(ABS_MISC, input_dev->absbit);
+
+		if (features->device_type == BTN_TOOL_TRIPLETAP) {
+			__set_bit(BTN_LEFT, input_dev->keybit);
+			__set_bit(BTN_FORWARD, input_dev->keybit);
+			__set_bit(BTN_BACK, input_dev->keybit);
+			__set_bit(BTN_RIGHT, input_dev->keybit);
+
+			__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+			__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+
+			input_mt_create_slots(input_dev, 2);
+			input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+					     0, features->x_max,
+					     features->x_fuzz, 0);
+			input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+					     0, features->y_max,
+					     features->y_fuzz, 0);
+			input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+					     0, features->pressure_max,
+					     features->pressure_fuzz, 0);
+			input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
+					     MAX_TRACKING_ID, 0, 0);
+		} else if (features->device_type == BTN_TOOL_PEN) {
+			__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+			__set_bit(BTN_TOOL_PEN, input_dev->keybit);
+			__set_bit(BTN_STYLUS, input_dev->keybit);
+			__set_bit(BTN_STYLUS2, input_dev->keybit);
+		}
+		break;
 	}
 }
 
@@ -1215,6 +1428,14 @@
 	{ "Wacom ISDv4 E3",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG };
 static const struct wacom_features wacom_features_0x47 =
 	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS };
+static struct wacom_features wacom_features_0xD0 =
+	{ "Wacom Bamboo 2FG",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD1 =
+	{ "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD2 =
+	{ "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD3 =
+	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
 
 #define USB_DEVICE_WACOM(prod)					\
 	USB_DEVICE(USB_VENDOR_ID_WACOM, prod),			\
@@ -1279,6 +1500,10 @@
 	{ USB_DEVICE_WACOM(0xC6) },
 	{ USB_DEVICE_WACOM(0xC7) },
 	{ USB_DEVICE_WACOM(0xCE) },
+	{ USB_DEVICE_WACOM(0xD0) },
+	{ USB_DEVICE_WACOM(0xD1) },
+	{ USB_DEVICE_WACOM(0xD2) },
+	{ USB_DEVICE_WACOM(0xD3) },
 	{ USB_DEVICE_WACOM(0xF0) },
 	{ USB_DEVICE_WACOM(0xCC) },
 	{ USB_DEVICE_WACOM(0x90) },
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index 99e1a54..00ca015 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -21,6 +21,7 @@
 #define WACOM_PKGLEN_INTUOS	10
 #define WACOM_PKGLEN_TPC1FG	 5
 #define WACOM_PKGLEN_TPC2FG	14
+#define WACOM_PKGLEN_BBTOUCH	20
 
 /* device IDs */
 #define STYLUS_DEVICE_ID	0x02
@@ -37,6 +38,13 @@
 #define WACOM_REPORT_TPC1FG		6
 #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 {
 	PENPARTNER = 0,
 	GRAPHIRE,
@@ -44,6 +52,7 @@
 	PTU,
 	PL,
 	DTU,
+	BAMBOO_PT,
 	INTUOS,
 	INTUOS3S,
 	INTUOS3,
@@ -73,6 +82,11 @@
 	int y_phy;
 	unsigned char unit;
 	unsigned char unitExpo;
+	int x_fuzz;
+	int y_fuzz;
+	int pressure_fuzz;
+	int distance_fuzz;
+	unsigned quirks;
 };
 
 struct wacom_shared {
@@ -86,6 +100,7 @@
 	int id[3];
 	__u32 serial[2];
 	int last_finger;
+	int trk_id;
 	struct wacom_features features;
 	struct wacom_shared *shared;
 	struct input_dev *input;
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 0069d97..0ea361f 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -98,6 +98,18 @@
 	  To compile this driver as a module, choose M here: the
 	  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
 	tristate "cy8ctmg110 touchscreen"
 	depends on I2C
@@ -214,6 +226,16 @@
 	  To compile this driver as a module, choose M here: the
 	  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
 	tristate "MELFAS MCS-5000 touchscreen"
 	depends on I2C
@@ -250,6 +272,18 @@
 	  To compile this driver as a module, choose M here: the
 	  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
 	tristate "ICS MicroClock MK712 touchscreen"
 	help
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 28217e1..99b353c 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -14,6 +14,7 @@
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.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_DA9034)	+= da9034-ts.o
 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO)	+= dynapro.o
@@ -23,6 +24,8 @@
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.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_MCS5000)	+= mcs5000_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MIGOR)		+= migor_ts.o
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index 5f0221c..a1952fc 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -191,13 +191,12 @@
 	struct spi_message	msg;
 
 	struct mutex		mutex;
-	unsigned		disabled:1;	/* P: mutex */
-	unsigned		gpio3:1;	/* P: mutex */
-	unsigned		gpio4:1;	/* P: mutex */
+	bool			disabled;	/* P: mutex */
+	bool			gpio3;		/* P: mutex */
+	bool			gpio4;		/* P: mutex */
 
 	spinlock_t		lock;
 	struct timer_list	timer;		/* P: lock */
-	unsigned		pending:1;	/* P: lock */
 
 	/*
 	 * DMA (thus cache coherency maintenance) requires the
@@ -206,8 +205,8 @@
 	u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned;
 };
 
-static int gpio3;
-module_param(gpio3, int, 0);
+static bool gpio3;
+module_param(gpio3, bool, 0);
 MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3");
 
 /*
@@ -230,6 +229,7 @@
 			AD7877_READADD(reg));
 	req->xfer[0].tx_buf = &req->command;
 	req->xfer[0].len = 2;
+	req->xfer[0].cs_change = 1;
 
 	req->xfer[1].rx_buf = &req->sample;
 	req->xfer[1].len = 2;
@@ -295,20 +295,25 @@
 
 	req->xfer[0].tx_buf = &req->reset;
 	req->xfer[0].len = 2;
+	req->xfer[0].cs_change = 1;
 
 	req->xfer[1].tx_buf = &req->ref_on;
 	req->xfer[1].len = 2;
 	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].len = 2;
 	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].len = 2;
+	req->xfer[3].cs_change = 1;
 
 	req->xfer[4].tx_buf = &ts->cmd_crtl2;	/*REF OFF*/
 	req->xfer[4].len = 2;
+	req->xfer[4].cs_change = 1;
 
 	req->xfer[5].tx_buf = &ts->cmd_crtl1;	/*DEFAULT*/
 	req->xfer[5].len = 2;
@@ -327,7 +332,7 @@
 	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;
 	unsigned Rt;
@@ -354,11 +359,25 @@
 		Rt /= z1;
 		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_Y, y);
 		input_report_abs(input_dev, ABS_PRESSURE, Rt);
 		input_sync(input_dev);
+
+		return 0;
 	}
+
+	return -EINVAL;
 }
 
 static inline void ad7877_ts_event_release(struct ad7877 *ts)
@@ -366,72 +385,56 @@
 	struct input_dev *input_dev = ts->input;
 
 	input_report_abs(input_dev, ABS_PRESSURE, 0);
+	input_report_key(input_dev, BTN_TOUCH, 0);
 	input_sync(input_dev);
 }
 
 static void ad7877_timer(unsigned long handle)
 {
 	struct ad7877 *ts = (void *)handle;
+	unsigned long flags;
 
+	spin_lock_irqsave(&ts->lock, flags);
 	ad7877_ts_event_release(ts);
+	spin_unlock_irqrestore(&ts->lock, flags);
 }
 
 static irqreturn_t ad7877_irq(int irq, void *handle)
 {
 	struct ad7877 *ts = handle;
 	unsigned long flags;
-	int status;
+	int error;
 
-	/*
-	 * The repeated conversion sequencer controlled by TMR kicked off
-	 * too fast. We ignore the last and process the sample sequence
-	 * currently in the queue. It can't be older than 9.4ms, and we
-	 * need to avoid that ts->msg doesn't get issued twice while in work.
-	 */
+	error = spi_sync(ts->spi, &ts->msg);
+	if (error) {
+		dev_err(&ts->spi->dev, "spi_sync --> %d\n", error);
+		goto out;
+	}
 
 	spin_lock_irqsave(&ts->lock, flags);
-	if (!ts->pending) {
-		ts->pending = 1;
-
-		status = spi_async(ts->spi, &ts->msg);
-		if (status)
-			dev_err(&ts->spi->dev, "spi_sync --> %d\n", status);
-	}
+	error = ad7877_process_data(ts);
+	if (!error)
+		mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
 	spin_unlock_irqrestore(&ts->lock, flags);
 
+out:
 	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)
 {
 	mutex_lock(&ts->mutex);
 
 	if (!ts->disabled) {
-		ts->disabled = 1;
+		ts->disabled = true;
 		disable_irq(ts->spi->irq);
 
-		/* Wait for spi_async callback */
-		while (ts->pending)
-			msleep(1);
-
 		if (del_timer_sync(&ts->timer))
 			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
 	 */
 
@@ -443,7 +446,7 @@
 	mutex_lock(&ts->mutex);
 
 	if (ts->disabled) {
-		ts->disabled = 0;
+		ts->disabled = false;
 		enable_irq(ts->spi->irq);
 	}
 
@@ -453,7 +456,7 @@
 #define SHOW(name) static ssize_t \
 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, \
 			AD7877_READ_CHAN(name)); \
 	if (v < 0) \
@@ -473,7 +476,7 @@
 static ssize_t ad7877_disable_show(struct device *dev,
 				     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);
 }
@@ -503,7 +506,7 @@
 static ssize_t ad7877_dac_show(struct device *dev,
 				     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);
 }
@@ -533,7 +536,7 @@
 static ssize_t ad7877_gpio3_show(struct device *dev,
 				     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);
 }
@@ -564,7 +567,7 @@
 static ssize_t ad7877_gpio4_show(struct device *dev,
 				     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);
 }
@@ -597,16 +600,35 @@
 	&dev_attr_temp2.attr,
 	&dev_attr_aux1.attr,
 	&dev_attr_aux2.attr,
+	&dev_attr_aux3.attr,
 	&dev_attr_bat1.attr,
 	&dev_attr_bat2.attr,
 	&dev_attr_disable.attr,
 	&dev_attr_dac.attr,
+	&dev_attr_gpio3.attr,
 	&dev_attr_gpio4.attr,
 	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 = {
-	.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)
@@ -635,22 +657,25 @@
 
 	spi_message_init(m);
 
-	m->complete = ad7877_callback;
 	m->context = ts;
 
 	ts->xfer[0].tx_buf = &ts->cmd_crtl1;
 	ts->xfer[0].len = 2;
+	ts->xfer[0].cs_change = 1;
 
 	spi_message_add_tail(&ts->xfer[0], m);
 
 	ts->xfer[1].tx_buf = &ts->cmd_dummy; /* Send ZERO */
 	ts->xfer[1].len = 2;
+	ts->xfer[1].cs_change = 1;
 
 	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].len = 2;
+		if (i < (AD7877_NR_SENSE - 1))
+			ts->xfer[i + 2].cs_change = 1;
 		spi_message_add_tail(&ts->xfer[i + 2], m);
 	}
 }
@@ -718,6 +743,8 @@
 	input_dev->phys = ts->phys;
 	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(ABS_X, input_dev->absbit);
 	__set_bit(ABS_Y, input_dev->absbit);
@@ -752,8 +779,9 @@
 
 	/* Request AD7877 /DAV GPIO interrupt */
 
-	err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING,
-			spi->dev.driver->name, ts);
+	err = request_threaded_irq(spi->irq, NULL, ad7877_irq,
+				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+				   spi->dev.driver->name, ts);
 	if (err) {
 		dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
 		goto err_free_mem;
@@ -763,20 +791,12 @@
 	if (err)
 		goto err_free_irq;
 
-	err = device_create_file(&spi->dev,
-				 gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
+	err = input_register_device(input_dev);
 	if (err)
 		goto err_remove_attr_group;
 
-	err = input_register_device(input_dev);
-	if (err)
-		goto err_remove_attr;
-
 	return 0;
 
-err_remove_attr:
-	device_remove_file(&spi->dev,
-			   gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
 err_remove_attr_group:
 	sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
 err_free_irq:
@@ -790,11 +810,9 @@
 
 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);
-	device_remove_file(&spi->dev,
-			   gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
 
 	ad7877_disable(ts);
 	free_irq(ts->spi->irq, ts);
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 1603193..14ea54b 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -17,9 +17,11 @@
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <linux/types.h>
 #include <linux/hwmon.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
@@ -52,22 +54,23 @@
  * files.
  */
 
-#define TS_POLL_DELAY	(1 * 1000000)	/* ns delay before the first sample */
-#define TS_POLL_PERIOD	(5 * 1000000)	/* ns delay between samples */
+#define TS_POLL_DELAY	1	/* ms delay before the first sample */
+#define TS_POLL_PERIOD	5	/* ms delay between samples */
 
 /* this driver doesn't aim at the peak continuous sample rate */
 #define	SAMPLE_BITS	(8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
 
 struct ts_event {
-	/* For portability, we can't read 12 bit values using SPI (which
-	 * would make the controller deliver them as native byteorder u16
+	/*
+	 * For portability, we can't read 12 bit values using SPI (which
+	 * would make the controller deliver them as native byte order u16
 	 * with msbs zeroed).  Instead, we read them as two 8-bit values,
 	 * *** WHICH NEED BYTESWAPPING *** and range adjustment.
 	 */
 	u16	x;
 	u16	y;
 	u16	z1, z2;
-	int	ignore;
+	bool	ignore;
 	u8	x_buf[3];
 	u8	y_buf[3];
 };
@@ -110,8 +113,11 @@
 
 	struct spi_transfer	xfer[18];
 	struct spi_message	msg[5];
-	struct spi_message	*last_msg;
-	int			msg_idx;
+	int			msg_count;
+	wait_queue_head_t	wait;
+
+	bool			pendown;
+
 	int			read_cnt;
 	int			read_rep;
 	int			last_read;
@@ -122,14 +128,10 @@
 
 	u16			penirq_recheck_delay_usecs;
 
-	spinlock_t		lock;
-	struct hrtimer		timer;
-	unsigned		pendown:1;	/* P: lock */
-	unsigned		pending:1;	/* P: lock */
-// FIXME remove "irq_disabled"
-	unsigned		irq_disabled:1;	/* P: lock */
-	unsigned		disabled:1;
-	unsigned		is_suspended:1;
+	struct mutex		lock;
+	bool			stopped;	/* P: lock */
+	bool			disabled;	/* P: lock */
+	bool			suspended;	/* P: lock */
 
 	int			(*filter)(void *data, int data_idx, int *val);
 	void			*filter_data;
@@ -165,7 +167,7 @@
 #define	ADS_12_BIT		(0 << 3)
 #define	ADS_SER			(1 << 2)	/* non-differential */
 #define	ADS_DFR			(0 << 2)	/* differential */
-#define	ADS_PD10_PDOWN		(0 << 0)	/* lowpower mode + penirq */
+#define	ADS_PD10_PDOWN		(0 << 0)	/* low power mode + penirq */
 #define	ADS_PD10_ADC_ON		(1 << 0)	/* ADC on */
 #define	ADS_PD10_REF_ON		(2 << 0)	/* vREF on + penirq */
 #define	ADS_PD10_ALL_ON		(3 << 0)	/* ADC + vREF on */
@@ -193,6 +195,78 @@
 #define	REF_ON	(READ_12BIT_DFR(x, 1, 1))
 #define	REF_OFF	(READ_12BIT_DFR(y, 0, 0))
 
+/* Must be called with ts->lock held */
+static void ads7846_stop(struct ads7846 *ts)
+{
+	if (!ts->disabled && !ts->suspended) {
+		/* Signal IRQ thread to stop polling and disable the handler. */
+		ts->stopped = true;
+		mb();
+		wake_up(&ts->wait);
+		disable_irq(ts->spi->irq);
+	}
+}
+
+/* Must be called with ts->lock held */
+static void ads7846_restart(struct ads7846 *ts)
+{
+	if (!ts->disabled && !ts->suspended) {
+		/* Tell IRQ thread that it may poll the device. */
+		ts->stopped = false;
+		mb();
+		enable_irq(ts->spi->irq);
+	}
+}
+
+/* Must be called with ts->lock held */
+static void __ads7846_disable(struct ads7846 *ts)
+{
+	ads7846_stop(ts);
+	regulator_disable(ts->reg);
+
+	/*
+	 * We know the chip's in low power mode since we always
+	 * leave it that way after every request
+	 */
+}
+
+/* Must be called with ts->lock held */
+static void __ads7846_enable(struct ads7846 *ts)
+{
+	regulator_enable(ts->reg);
+	ads7846_restart(ts);
+}
+
+static void ads7846_disable(struct ads7846 *ts)
+{
+	mutex_lock(&ts->lock);
+
+	if (!ts->disabled) {
+
+		if  (!ts->suspended)
+			__ads7846_disable(ts);
+
+		ts->disabled = true;
+	}
+
+	mutex_unlock(&ts->lock);
+}
+
+static void ads7846_enable(struct ads7846 *ts)
+{
+	mutex_lock(&ts->lock);
+
+	if (ts->disabled) {
+
+		ts->disabled = false;
+
+		if (!ts->suspended)
+			__ads7846_enable(ts);
+	}
+
+	mutex_unlock(&ts->lock);
+}
+
 /*--------------------------------------------------------------------------*/
 
 /*
@@ -219,23 +293,15 @@
 	struct spi_transfer	xfer[2];
 };
 
-static void ads7846_enable(struct ads7846 *ts);
-static void ads7846_disable(struct ads7846 *ts);
-
-static int device_suspended(struct device *dev)
-{
-	struct ads7846 *ts = dev_get_drvdata(dev);
-	return ts->is_suspended || ts->disabled;
-}
-
 static int ads7846_read12_ser(struct device *dev, unsigned command)
 {
-	struct spi_device	*spi = to_spi_device(dev);
-	struct ads7846		*ts = dev_get_drvdata(dev);
-	struct ser_req		*req = kzalloc(sizeof *req, GFP_KERNEL);
-	int			status;
-	int			use_internal;
+	struct spi_device *spi = to_spi_device(dev);
+	struct ads7846 *ts = dev_get_drvdata(dev);
+	struct ser_req *req;
+	int status;
+	int use_internal;
 
+	req = kzalloc(sizeof *req, GFP_KERNEL);
 	if (!req)
 		return -ENOMEM;
 
@@ -282,11 +348,11 @@
 	CS_CHANGE(req->xfer[5]);
 	spi_message_add_tail(&req->xfer[5], &req->msg);
 
-	ts->irq_disabled = 1;
-	disable_irq(spi->irq);
+	mutex_lock(&ts->lock);
+	ads7846_stop(ts);
 	status = spi_sync(spi, &req->msg);
-	ts->irq_disabled = 0;
-	enable_irq(spi->irq);
+	ads7846_restart(ts);
+	mutex_unlock(&ts->lock);
 
 	if (status == 0) {
 		/* on-wire is a must-ignore bit, a BE12 value, then padding */
@@ -301,11 +367,12 @@
 
 static int ads7845_read12_ser(struct device *dev, unsigned command)
 {
-	struct spi_device	*spi = to_spi_device(dev);
-	struct ads7846		*ts = dev_get_drvdata(dev);
-	struct ads7845_ser_req	*req = kzalloc(sizeof *req, GFP_KERNEL);
-	int			status;
+	struct spi_device *spi = to_spi_device(dev);
+	struct ads7846 *ts = dev_get_drvdata(dev);
+	struct ads7845_ser_req *req;
+	int status;
 
+	req = kzalloc(sizeof *req, GFP_KERNEL);
 	if (!req)
 		return -ENOMEM;
 
@@ -317,11 +384,11 @@
 	req->xfer[0].len = 3;
 	spi_message_add_tail(&req->xfer[0], &req->msg);
 
-	ts->irq_disabled = 1;
-	disable_irq(spi->irq);
+	mutex_lock(&ts->lock);
+	ads7846_stop(ts);
 	status = spi_sync(spi, &req->msg);
-	ts->irq_disabled = 0;
-	enable_irq(spi->irq);
+	ads7846_restart(ts);
+	mutex_unlock(&ts->lock);
 
 	if (status == 0) {
 		/* BE12 value, then padding */
@@ -374,6 +441,7 @@
 	/* external resistors may scale vAUX into 0..vREF */
 	retval *= ts->vref_mv;
 	retval = retval >> 12;
+
 	return retval;
 }
 
@@ -384,13 +452,13 @@
 	/* ads7846 has a resistor ladder to scale this signal down */
 	if (ts->model == 7846)
 		retval *= 4;
+
 	return retval;
 }
 
 SHOW(in0_input, vaux, vaux_adjust)
 SHOW(in1_input, vbatt, vbatt_adjust)
 
-
 static struct attribute *ads7846_attributes[] = {
 	&dev_attr_temp0.attr,
 	&dev_attr_temp1.attr,
@@ -498,17 +566,12 @@
 }
 #endif
 
-static int is_pen_down(struct device *dev)
-{
-	struct ads7846	*ts = dev_get_drvdata(dev);
-
-	return ts->pendown;
-}
-
 static ssize_t ads7846_pen_down_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%u\n", is_pen_down(dev));
+	struct ads7846 *ts = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%u\n", ts->pendown);
 }
 
 static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
@@ -516,7 +579,7 @@
 static ssize_t ads7846_disable_show(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
-	struct ads7846	*ts = dev_get_drvdata(dev);
+	struct ads7846 *ts = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%u\n", ts->disabled);
 }
@@ -531,15 +594,11 @@
 	if (strict_strtoul(buf, 10, &i))
 		return -EINVAL;
 
-	spin_lock_irq(&ts->lock);
-
 	if (i)
 		ads7846_disable(ts);
 	else
 		ads7846_enable(ts);
 
-	spin_unlock_irq(&ts->lock);
-
 	return count;
 }
 
@@ -569,23 +628,141 @@
 {
 }
 
-/*
- * PENIRQ only kicks the timer.  The timer only reissues the SPI transfer,
- * to retrieve touchscreen status.
- *
- * The SPI transfer completion callback does the real work.  It reports
- * touchscreen events and reactivates the timer (or IRQ) as appropriate.
- */
-
-static void ads7846_rx(void *ads)
+static int ads7846_debounce_filter(void *ads, int data_idx, int *val)
 {
-	struct ads7846		*ts = ads;
-	struct ads7846_packet	*packet = ts->packet;
-	unsigned		Rt;
-	u16			x, y, z1, z2;
+	struct ads7846 *ts = ads;
 
-	/* ads7846_rx_val() did in-place conversion (including byteswap) from
-	 * on-the-wire format as part of debouncing to get stable readings.
+	if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) {
+		/* Start over collecting consistent readings. */
+		ts->read_rep = 0;
+		/*
+		 * Repeat it, if this was the first read or the read
+		 * wasn't consistent enough.
+		 */
+		if (ts->read_cnt < ts->debounce_max) {
+			ts->last_read = *val;
+			ts->read_cnt++;
+			return ADS7846_FILTER_REPEAT;
+		} else {
+			/*
+			 * Maximum number of debouncing reached and still
+			 * not enough number of consistent readings. Abort
+			 * the whole sample, repeat it in the next sampling
+			 * period.
+			 */
+			ts->read_cnt = 0;
+			return ADS7846_FILTER_IGNORE;
+		}
+	} else {
+		if (++ts->read_rep > ts->debounce_rep) {
+			/*
+			 * Got a good reading for this coordinate,
+			 * go for the next one.
+			 */
+			ts->read_cnt = 0;
+			ts->read_rep = 0;
+			return ADS7846_FILTER_OK;
+		} else {
+			/* Read more values that are consistent. */
+			ts->read_cnt++;
+			return ADS7846_FILTER_REPEAT;
+		}
+	}
+}
+
+static int ads7846_no_filter(void *ads, int data_idx, int *val)
+{
+	return ADS7846_FILTER_OK;
+}
+
+static int ads7846_get_value(struct ads7846 *ts, struct spi_message *m)
+{
+	struct spi_transfer *t =
+		list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+
+	if (ts->model == 7845) {
+		return be16_to_cpup((__be16 *)&(((char*)t->rx_buf)[1])) >> 3;
+	} else {
+		/*
+		 * adjust:  on-wire is a must-ignore bit, a BE12 value, then
+		 * padding; built from two 8 bit values written msb-first.
+		 */
+		return be16_to_cpup((__be16 *)t->rx_buf) >> 3;
+	}
+}
+
+static void ads7846_update_value(struct spi_message *m, int val)
+{
+	struct spi_transfer *t =
+		list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+
+	*(u16 *)t->rx_buf = val;
+}
+
+static void ads7846_read_state(struct ads7846 *ts)
+{
+	struct ads7846_packet *packet = ts->packet;
+	struct spi_message *m;
+	int msg_idx = 0;
+	int val;
+	int action;
+	int error;
+
+	while (msg_idx < ts->msg_count) {
+
+		ts->wait_for_sync();
+
+		m = &ts->msg[msg_idx];
+		error = spi_sync(ts->spi, m);
+		if (error) {
+			dev_err(&ts->spi->dev, "spi_async --> %d\n", error);
+			packet->tc.ignore = true;
+			return;
+		}
+
+		/*
+		 * Last message is power down request, no need to convert
+		 * or filter the value.
+		 */
+		if (msg_idx < ts->msg_count - 1) {
+
+			val = ads7846_get_value(ts, m);
+
+			action = ts->filter(ts->filter_data, msg_idx, &val);
+			switch (action) {
+			case ADS7846_FILTER_REPEAT:
+				continue;
+
+			case ADS7846_FILTER_IGNORE:
+				packet->tc.ignore = true;
+				msg_idx = ts->msg_count - 1;
+				continue;
+
+			case ADS7846_FILTER_OK:
+				ads7846_update_value(m, val);
+				packet->tc.ignore = false;
+				msg_idx++;
+				break;
+
+			default:
+				BUG();
+			}
+		} else {
+			msg_idx++;
+		}
+	}
+}
+
+static void ads7846_report_state(struct ads7846 *ts)
+{
+	struct ads7846_packet *packet = ts->packet;
+	unsigned int Rt;
+	u16 x, y, z1, z2;
+
+	/*
+	 * ads7846_get_value() does in-place conversion (including byte swap)
+	 * from on-the-wire format as part of debouncing to get stable
+	 * readings.
 	 */
 	if (ts->model == 7845) {
 		x = *(u16 *)packet->tc.x_buf;
@@ -623,19 +800,19 @@
 		Rt = 0;
 	}
 
-	/* Sample found inconsistent by debouncing or pressure is beyond
+	/*
+	 * Sample found inconsistent by debouncing or pressure is beyond
 	 * the maximum. Don't report it to user space, repeat at least
 	 * once more the measurement
 	 */
 	if (packet->tc.ignore || Rt > ts->pressure_max) {
 		dev_vdbg(&ts->spi->dev, "ignored %d pressure %d\n",
 			 packet->tc.ignore, Rt);
-		hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
-			      HRTIMER_MODE_REL);
 		return;
 	}
 
-	/* Maybe check the pendown state before reporting. This discards
+	/*
+	 * Maybe check the pendown state before reporting. This discards
 	 * false readings when the pen is lifted.
 	 */
 	if (ts->penirq_recheck_delay_usecs) {
@@ -644,8 +821,9 @@
 			Rt = 0;
 	}
 
-	/* NOTE: We can't rely on the pressure to determine the pen down
-	 * state, even this controller has a pressure sensor.  The pressure
+	/*
+	 * NOTE: We can't rely on the pressure to determine the pen down
+	 * state, even this controller has a pressure sensor. The pressure
 	 * value can fluctuate for quite a while after lifting the pen and
 	 * in some cases may not even settle at the expected value.
 	 *
@@ -655,15 +833,15 @@
 	if (Rt) {
 		struct input_dev *input = ts->input;
 
-		if (!ts->pendown) {
-			input_report_key(input, BTN_TOUCH, 1);
-			ts->pendown = 1;
-			dev_vdbg(&ts->spi->dev, "DOWN\n");
-		}
-
 		if (ts->swap_xy)
 			swap(x, y);
 
+		if (!ts->pendown) {
+			input_report_key(input, BTN_TOUCH, 1);
+			ts->pendown = true;
+			dev_vdbg(&ts->spi->dev, "DOWN\n");
+		}
+
 		input_report_abs(input, ABS_X, x);
 		input_report_abs(input, ABS_Y, y);
 		input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt);
@@ -671,246 +849,94 @@
 		input_sync(input);
 		dev_vdbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt);
 	}
-
-	hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
-			HRTIMER_MODE_REL);
 }
 
-static int ads7846_debounce(void *ads, int data_idx, int *val)
+static irqreturn_t ads7846_hard_irq(int irq, void *handle)
 {
-	struct ads7846		*ts = ads;
+	struct ads7846 *ts = handle;
 
-	if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) {
-		/* Start over collecting consistent readings. */
-		ts->read_rep = 0;
-		/* Repeat it, if this was the first read or the read
-		 * wasn't consistent enough. */
-		if (ts->read_cnt < ts->debounce_max) {
-			ts->last_read = *val;
-			ts->read_cnt++;
-			return ADS7846_FILTER_REPEAT;
-		} else {
-			/* Maximum number of debouncing reached and still
-			 * not enough number of consistent readings. Abort
-			 * the whole sample, repeat it in the next sampling
-			 * period.
-			 */
-			ts->read_cnt = 0;
-			return ADS7846_FILTER_IGNORE;
-		}
-	} else {
-		if (++ts->read_rep > ts->debounce_rep) {
-			/* Got a good reading for this coordinate,
-			 * go for the next one. */
-			ts->read_cnt = 0;
-			ts->read_rep = 0;
-			return ADS7846_FILTER_OK;
-		} else {
-			/* Read more values that are consistent. */
-			ts->read_cnt++;
-			return ADS7846_FILTER_REPEAT;
-		}
-	}
+	return get_pendown_state(ts) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
 }
 
-static int ads7846_no_filter(void *ads, int data_idx, int *val)
-{
-	return ADS7846_FILTER_OK;
-}
-
-static void ads7846_rx_val(void *ads)
-{
-	struct ads7846 *ts = ads;
-	struct ads7846_packet *packet = ts->packet;
-	struct spi_message *m;
-	struct spi_transfer *t;
-	int val;
-	int action;
-	int status;
-
-	m = &ts->msg[ts->msg_idx];
-	t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
-
-	if (ts->model == 7845) {
-		val = be16_to_cpup((__be16 *)&(((char*)t->rx_buf)[1])) >> 3;
-	} else {
-		/* adjust:  on-wire is a must-ignore bit, a BE12 value, then
-		 * padding; built from two 8 bit values written msb-first.
-		 */
-		val = be16_to_cpup((__be16 *)t->rx_buf) >> 3;
-	}
-
-	action = ts->filter(ts->filter_data, ts->msg_idx, &val);
-	switch (action) {
-	case ADS7846_FILTER_REPEAT:
-		break;
-	case ADS7846_FILTER_IGNORE:
-		packet->tc.ignore = 1;
-		/* Last message will contain ads7846_rx() as the
-		 * completion function.
-		 */
-		m = ts->last_msg;
-		break;
-	case ADS7846_FILTER_OK:
-		*(u16 *)t->rx_buf = val;
-		packet->tc.ignore = 0;
-		m = &ts->msg[++ts->msg_idx];
-		break;
-	default:
-		BUG();
-	}
-	ts->wait_for_sync();
-	status = spi_async(ts->spi, m);
-	if (status)
-		dev_err(&ts->spi->dev, "spi_async --> %d\n",
-				status);
-}
-
-static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
-{
-	struct ads7846	*ts = container_of(handle, struct ads7846, timer);
-	int		status = 0;
-
-	spin_lock(&ts->lock);
-
-	if (unlikely(!get_pendown_state(ts) ||
-		     device_suspended(&ts->spi->dev))) {
-		if (ts->pendown) {
-			struct input_dev *input = ts->input;
-
-			input_report_key(input, BTN_TOUCH, 0);
-			input_report_abs(input, ABS_PRESSURE, 0);
-			input_sync(input);
-
-			ts->pendown = 0;
-			dev_vdbg(&ts->spi->dev, "UP\n");
-		}
-
-		/* measurement cycle ended */
-		if (!device_suspended(&ts->spi->dev)) {
-			ts->irq_disabled = 0;
-			enable_irq(ts->spi->irq);
-		}
-		ts->pending = 0;
-	} else {
-		/* pen is still down, continue with the measurement */
-		ts->msg_idx = 0;
-		ts->wait_for_sync();
-		status = spi_async(ts->spi, &ts->msg[0]);
-		if (status)
-			dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
-	}
-
-	spin_unlock(&ts->lock);
-	return HRTIMER_NORESTART;
-}
 
 static irqreturn_t ads7846_irq(int irq, void *handle)
 {
 	struct ads7846 *ts = handle;
-	unsigned long flags;
 
-	spin_lock_irqsave(&ts->lock, flags);
-	if (likely(get_pendown_state(ts))) {
-		if (!ts->irq_disabled) {
-			/* The ARM do_simple_IRQ() dispatcher doesn't act
-			 * like the other dispatchers:  it will report IRQs
-			 * even after they've been disabled.  We work around
-			 * that here.  (The "generic irq" framework may help...)
-			 */
-			ts->irq_disabled = 1;
-			disable_irq_nosync(ts->spi->irq);
-			ts->pending = 1;
-			hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
-					HRTIMER_MODE_REL);
-		}
+	/* Start with a small delay before checking pendown state */
+	msleep(TS_POLL_DELAY);
+
+	while (!ts->stopped && get_pendown_state(ts)) {
+
+		/* pen is down, continue with the measurement */
+		ads7846_read_state(ts);
+
+		if (!ts->stopped)
+			ads7846_report_state(ts);
+
+		wait_event_timeout(ts->wait, ts->stopped,
+				   msecs_to_jiffies(TS_POLL_PERIOD));
 	}
-	spin_unlock_irqrestore(&ts->lock, flags);
+
+	if (ts->pendown) {
+		struct input_dev *input = ts->input;
+
+		input_report_key(input, BTN_TOUCH, 0);
+		input_report_abs(input, ABS_PRESSURE, 0);
+		input_sync(input);
+
+		ts->pendown = false;
+		dev_vdbg(&ts->spi->dev, "UP\n");
+	}
 
 	return IRQ_HANDLED;
 }
 
-/*--------------------------------------------------------------------------*/
-
-/* Must be called with ts->lock held */
-static void ads7846_disable(struct ads7846 *ts)
-{
-	if (ts->disabled)
-		return;
-
-	ts->disabled = 1;
-
-	/* are we waiting for IRQ, or polling? */
-	if (!ts->pending) {
-		ts->irq_disabled = 1;
-		disable_irq(ts->spi->irq);
-	} else {
-		/* the timer will run at least once more, and
-		 * leave everything in a clean state, IRQ disabled
-		 */
-		while (ts->pending) {
-			spin_unlock_irq(&ts->lock);
-			msleep(1);
-			spin_lock_irq(&ts->lock);
-		}
-	}
-
-	regulator_disable(ts->reg);
-
-	/* we know the chip's in lowpower mode since we always
-	 * leave it that way after every request
-	 */
-}
-
-/* Must be called with ts->lock held */
-static void ads7846_enable(struct ads7846 *ts)
-{
-	if (!ts->disabled)
-		return;
-
-	regulator_enable(ts->reg);
-
-	ts->disabled = 0;
-	ts->irq_disabled = 0;
-	enable_irq(ts->spi->irq);
-}
-
 static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
 {
 	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
-	spin_lock_irq(&ts->lock);
+	mutex_lock(&ts->lock);
 
-	ts->is_suspended = 1;
-	ads7846_disable(ts);
+	if (!ts->suspended) {
 
-	spin_unlock_irq(&ts->lock);
+		if (!ts->disabled)
+			__ads7846_disable(ts);
 
-	if (device_may_wakeup(&ts->spi->dev))
-		enable_irq_wake(ts->spi->irq);
+		if (device_may_wakeup(&ts->spi->dev))
+			enable_irq_wake(ts->spi->irq);
+
+		ts->suspended = true;
+	}
+
+	mutex_unlock(&ts->lock);
 
 	return 0;
-
 }
 
 static int ads7846_resume(struct spi_device *spi)
 {
 	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
-	if (device_may_wakeup(&ts->spi->dev))
-		disable_irq_wake(ts->spi->irq);
+	mutex_lock(&ts->lock);
 
-	spin_lock_irq(&ts->lock);
+	if (ts->suspended) {
 
-	ts->is_suspended = 0;
-	ads7846_enable(ts);
+		ts->suspended = false;
 
-	spin_unlock_irq(&ts->lock);
+		if (device_may_wakeup(&ts->spi->dev))
+			disable_irq_wake(ts->spi->irq);
+
+		if (!ts->disabled)
+			__ads7846_enable(ts);
+	}
+
+	mutex_unlock(&ts->lock);
 
 	return 0;
 }
 
-static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts)
+static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
 {
 	struct ads7846_platform_data *pdata = spi->dev.platform_data;
 	int err;
@@ -932,146 +958,40 @@
 	err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
 	if (err) {
 		dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
-				pdata->gpio_pendown);
+			pdata->gpio_pendown);
 		return err;
 	}
 
 	ts->gpio_pendown = pdata->gpio_pendown;
+
 	return 0;
 }
 
-static int __devinit ads7846_probe(struct spi_device *spi)
+/*
+ * Set up the transfers to read touchscreen state; this assumes we
+ * use formula #2 for pressure, not #3.
+ */
+static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts,
+				const struct ads7846_platform_data *pdata)
 {
-	struct ads7846 *ts;
-	struct ads7846_packet *packet;
-	struct input_dev *input_dev;
-	const struct ads7846_platform_data *pdata = spi->dev.platform_data;
-	struct spi_message *m;
-	struct spi_transfer *x;
-	unsigned long irq_flags;
-	int vref;
-	int err;
-
-	if (!spi->irq) {
-		dev_dbg(&spi->dev, "no IRQ?\n");
-		return -ENODEV;
-	}
-
-	if (!pdata) {
-		dev_dbg(&spi->dev, "no platform data?\n");
-		return -ENODEV;
-	}
-
-	/* don't exceed max specified sample rate */
-	if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
-		dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
-				(spi->max_speed_hz/SAMPLE_BITS)/1000);
-		return -EINVAL;
-	}
-
-	/* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
-	 * that even if the hardware can do that, the SPI controller driver
-	 * may not.  So we stick to very-portable 8 bit words, both RX and TX.
-	 */
-	spi->bits_per_word = 8;
-	spi->mode = SPI_MODE_0;
-	err = spi_setup(spi);
-	if (err < 0)
-		return err;
-
-	ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
-	packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!ts || !packet || !input_dev) {
-		err = -ENOMEM;
-		goto err_free_mem;
-	}
-
-	dev_set_drvdata(&spi->dev, ts);
-
-	ts->packet = packet;
-	ts->spi = spi;
-	ts->input = input_dev;
-	ts->vref_mv = pdata->vref_mv;
-	ts->swap_xy = pdata->swap_xy;
-
-	hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	ts->timer.function = ads7846_timer;
-
-	spin_lock_init(&ts->lock);
-
-	ts->model = pdata->model ? : 7846;
-	ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
-	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
-	ts->pressure_max = pdata->pressure_max ? : ~0;
-
-	if (pdata->filter != NULL) {
-		if (pdata->filter_init != NULL) {
-			err = pdata->filter_init(pdata, &ts->filter_data);
-			if (err < 0)
-				goto err_free_mem;
-		}
-		ts->filter = pdata->filter;
-		ts->filter_cleanup = pdata->filter_cleanup;
-	} else if (pdata->debounce_max) {
-		ts->debounce_max = pdata->debounce_max;
-		if (ts->debounce_max < 2)
-			ts->debounce_max = 2;
-		ts->debounce_tol = pdata->debounce_tol;
-		ts->debounce_rep = pdata->debounce_rep;
-		ts->filter = ads7846_debounce;
-		ts->filter_data = ts;
-	} else
-		ts->filter = ads7846_no_filter;
-
-	err = setup_pendown(spi, ts);
-	if (err)
-		goto err_cleanup_filter;
-
-	if (pdata->penirq_recheck_delay_usecs)
-		ts->penirq_recheck_delay_usecs =
-				pdata->penirq_recheck_delay_usecs;
-
-	ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
-
-	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
-	snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
-
-	input_dev->name = ts->name;
-	input_dev->phys = ts->phys;
-	input_dev->dev.parent = &spi->dev;
-
-	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-	input_set_abs_params(input_dev, ABS_X,
-			pdata->x_min ? : 0,
-			pdata->x_max ? : MAX_12BIT,
-			0, 0);
-	input_set_abs_params(input_dev, ABS_Y,
-			pdata->y_min ? : 0,
-			pdata->y_max ? : MAX_12BIT,
-			0, 0);
-	input_set_abs_params(input_dev, ABS_PRESSURE,
-			pdata->pressure_min, pdata->pressure_max, 0, 0);
-
-	vref = pdata->keep_vref_on;
+	struct spi_message *m = &ts->msg[0];
+	struct spi_transfer *x = ts->xfer;
+	struct ads7846_packet *packet = ts->packet;
+	int vref = pdata->keep_vref_on;
 
 	if (ts->model == 7873) {
-		/* The AD7873 is almost identical to the ADS7846
+		/*
+		 * The AD7873 is almost identical to the ADS7846
 		 * keep VREF off during differential/ratiometric
-		 * conversion modes
+		 * conversion modes.
 		 */
 		ts->model = 7846;
 		vref = 0;
 	}
 
-	/* set up the transfers to read touchscreen state; this assumes we
-	 * use formula #2 for pressure, not #3.
-	 */
-	m = &ts->msg[0];
-	x = ts->xfer;
-
+	ts->msg_count = 1;
 	spi_message_init(m);
+	m->context = ts;
 
 	if (ts->model == 7845) {
 		packet->read_y_cmd[0] = READ_Y(vref);
@@ -1094,7 +1014,8 @@
 		spi_message_add_tail(x, m);
 	}
 
-	/* the first sample after switching drivers can be low quality;
+	/*
+	 * The first sample after switching drivers can be low quality;
 	 * optionally discard it, using a second one after the signals
 	 * have had enough time to stabilize.
 	 */
@@ -1112,11 +1033,10 @@
 		spi_message_add_tail(x, m);
 	}
 
-	m->complete = ads7846_rx_val;
-	m->context = ts;
-
+	ts->msg_count++;
 	m++;
 	spi_message_init(m);
+	m->context = ts;
 
 	if (ts->model == 7845) {
 		x++;
@@ -1156,13 +1076,12 @@
 		spi_message_add_tail(x, m);
 	}
 
-	m->complete = ads7846_rx_val;
-	m->context = ts;
-
 	/* turn y+ off, x- on; we'll use formula #2 */
 	if (ts->model == 7846) {
+		ts->msg_count++;
 		m++;
 		spi_message_init(m);
+		m->context = ts;
 
 		x++;
 		packet->read_z1 = READ_Z1(vref);
@@ -1190,11 +1109,10 @@
 			spi_message_add_tail(x, m);
 		}
 
-		m->complete = ads7846_rx_val;
-		m->context = ts;
-
+		ts->msg_count++;
 		m++;
 		spi_message_init(m);
+		m->context = ts;
 
 		x++;
 		packet->read_z2 = READ_Z2(vref);
@@ -1221,14 +1139,13 @@
 			x->len = 2;
 			spi_message_add_tail(x, m);
 		}
-
-		m->complete = ads7846_rx_val;
-		m->context = ts;
 	}
 
 	/* power down */
+	ts->msg_count++;
 	m++;
 	spi_message_init(m);
+	m->context = ts;
 
 	if (ts->model == 7845) {
 		x++;
@@ -1251,11 +1168,119 @@
 
 	CS_CHANGE(*x);
 	spi_message_add_tail(x, m);
+}
 
-	m->complete = ads7846_rx;
-	m->context = ts;
+static int __devinit ads7846_probe(struct spi_device *spi)
+{
+	struct ads7846 *ts;
+	struct ads7846_packet *packet;
+	struct input_dev *input_dev;
+	struct ads7846_platform_data *pdata = spi->dev.platform_data;
+	unsigned long irq_flags;
+	int err;
 
-	ts->last_msg = m;
+	if (!spi->irq) {
+		dev_dbg(&spi->dev, "no IRQ?\n");
+		return -ENODEV;
+	}
+
+	if (!pdata) {
+		dev_dbg(&spi->dev, "no platform data?\n");
+		return -ENODEV;
+	}
+
+	/* don't exceed max specified sample rate */
+	if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
+		dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
+				(spi->max_speed_hz/SAMPLE_BITS)/1000);
+		return -EINVAL;
+	}
+
+	/* We'd set TX word size 8 bits and RX word size to 13 bits ... except
+	 * that even if the hardware can do that, the SPI controller driver
+	 * may not.  So we stick to very-portable 8 bit words, both RX and TX.
+	 */
+	spi->bits_per_word = 8;
+	spi->mode = SPI_MODE_0;
+	err = spi_setup(spi);
+	if (err < 0)
+		return err;
+
+	ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
+	packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ts || !packet || !input_dev) {
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	dev_set_drvdata(&spi->dev, ts);
+
+	ts->packet = packet;
+	ts->spi = spi;
+	ts->input = input_dev;
+	ts->vref_mv = pdata->vref_mv;
+	ts->swap_xy = pdata->swap_xy;
+
+	mutex_init(&ts->lock);
+	init_waitqueue_head(&ts->wait);
+
+	ts->model = pdata->model ? : 7846;
+	ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
+	ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
+	ts->pressure_max = pdata->pressure_max ? : ~0;
+
+	if (pdata->filter != NULL) {
+		if (pdata->filter_init != NULL) {
+			err = pdata->filter_init(pdata, &ts->filter_data);
+			if (err < 0)
+				goto err_free_mem;
+		}
+		ts->filter = pdata->filter;
+		ts->filter_cleanup = pdata->filter_cleanup;
+	} else if (pdata->debounce_max) {
+		ts->debounce_max = pdata->debounce_max;
+		if (ts->debounce_max < 2)
+			ts->debounce_max = 2;
+		ts->debounce_tol = pdata->debounce_tol;
+		ts->debounce_rep = pdata->debounce_rep;
+		ts->filter = ads7846_debounce_filter;
+		ts->filter_data = ts;
+	} else {
+		ts->filter = ads7846_no_filter;
+	}
+
+	err = ads7846_setup_pendown(spi, ts);
+	if (err)
+		goto err_cleanup_filter;
+
+	if (pdata->penirq_recheck_delay_usecs)
+		ts->penirq_recheck_delay_usecs =
+				pdata->penirq_recheck_delay_usecs;
+
+	ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
+
+	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
+	snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
+
+	input_dev->name = ts->name;
+	input_dev->phys = ts->phys;
+	input_dev->dev.parent = &spi->dev;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_set_abs_params(input_dev, ABS_X,
+			pdata->x_min ? : 0,
+			pdata->x_max ? : MAX_12BIT,
+			0, 0);
+	input_set_abs_params(input_dev, ABS_Y,
+			pdata->y_min ? : 0,
+			pdata->y_max ? : MAX_12BIT,
+			0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE,
+			pdata->pressure_min, pdata->pressure_max, 0, 0);
+
+	ads7846_setup_spi_msg(ts, pdata);
 
 	ts->reg = regulator_get(&spi->dev, "vcc");
 	if (IS_ERR(ts->reg)) {
@@ -1271,16 +1296,17 @@
 	}
 
 	irq_flags = pdata->irq_flags ? : IRQF_TRIGGER_FALLING;
+	irq_flags |= IRQF_ONESHOT;
 
-	err = request_irq(spi->irq, ads7846_irq, irq_flags,
-			  spi->dev.driver->name, ts);
-
+	err = request_threaded_irq(spi->irq, ads7846_hard_irq, ads7846_irq,
+				   irq_flags, spi->dev.driver->name, ts);
 	if (err && !pdata->irq_flags) {
 		dev_info(&spi->dev,
 			"trying pin change workaround on irq %d\n", spi->irq);
-		err = request_irq(spi->irq, ads7846_irq,
-				  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-				  spi->dev.driver->name, ts);
+		irq_flags |= IRQF_TRIGGER_RISING;
+		err = request_threaded_irq(spi->irq,
+				  ads7846_hard_irq, ads7846_irq,
+				  irq_flags, spi->dev.driver->name, ts);
 	}
 
 	if (err) {
@@ -1294,7 +1320,8 @@
 
 	dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
 
-	/* take a first sample, leaving nPENIRQ active and vREF off; avoid
+	/*
+	 * Take a first sample, leaving nPENIRQ active and vREF off; avoid
 	 * the touchscreen, in case it's not connected.
 	 */
 	if (ts->model == 7845)
@@ -1340,20 +1367,18 @@
 
 static int __devexit ads7846_remove(struct spi_device *spi)
 {
-	struct ads7846		*ts = dev_get_drvdata(&spi->dev);
+	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
 	device_init_wakeup(&spi->dev, false);
 
-	ads784x_hwmon_unregister(spi, ts);
-	input_unregister_device(ts->input);
-
-	ads7846_suspend(spi, PMSG_SUSPEND);
-
 	sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group);
 
+	ads7846_disable(ts);
 	free_irq(ts->spi->irq, ts);
-	/* suspend left the IRQ disabled */
-	enable_irq(ts->spi->irq);
+
+	input_unregister_device(ts->input);
+
+	ads784x_hwmon_unregister(spi, ts);
 
 	regulator_disable(ts->reg);
 	regulator_put(ts->reg);
@@ -1368,6 +1393,7 @@
 	kfree(ts);
 
 	dev_dbg(&spi->dev, "unregistered touchscreen\n");
+
 	return 0;
 }
 
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
new file mode 100644
index 0000000..ccde586
--- /dev/null
+++ b/drivers/input/touchscreen/bu21013_ts.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * License terms:GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
+#include <linux/input/bu21013.h>
+#include <linux/slab.h>
+
+#define PEN_DOWN_INTR	0
+#define MAX_FINGERS	2
+#define RESET_DELAY	30
+#define PENUP_TIMEOUT	(10)
+#define DELTA_MIN	16
+#define MASK_BITS	0x03
+#define SHIFT_8		8
+#define SHIFT_2		2
+#define LENGTH_OF_BUFFER	11
+#define I2C_RETRY_COUNT	5
+
+#define BU21013_SENSORS_BTN_0_7_REG	0x70
+#define BU21013_SENSORS_BTN_8_15_REG	0x71
+#define BU21013_SENSORS_BTN_16_23_REG	0x72
+#define BU21013_X1_POS_MSB_REG		0x73
+#define BU21013_X1_POS_LSB_REG		0x74
+#define BU21013_Y1_POS_MSB_REG		0x75
+#define BU21013_Y1_POS_LSB_REG		0x76
+#define BU21013_X2_POS_MSB_REG		0x77
+#define BU21013_X2_POS_LSB_REG		0x78
+#define BU21013_Y2_POS_MSB_REG		0x79
+#define BU21013_Y2_POS_LSB_REG		0x7A
+#define BU21013_INT_CLR_REG		0xE8
+#define BU21013_INT_MODE_REG		0xE9
+#define BU21013_GAIN_REG		0xEA
+#define BU21013_OFFSET_MODE_REG		0xEB
+#define BU21013_XY_EDGE_REG		0xEC
+#define BU21013_RESET_REG		0xED
+#define BU21013_CALIB_REG		0xEE
+#define BU21013_DONE_REG		0xEF
+#define BU21013_SENSOR_0_7_REG		0xF0
+#define BU21013_SENSOR_8_15_REG		0xF1
+#define BU21013_SENSOR_16_23_REG	0xF2
+#define BU21013_POS_MODE1_REG		0xF3
+#define BU21013_POS_MODE2_REG		0xF4
+#define BU21013_CLK_MODE_REG		0xF5
+#define BU21013_IDLE_REG		0xFA
+#define BU21013_FILTER_REG		0xFB
+#define BU21013_TH_ON_REG		0xFC
+#define BU21013_TH_OFF_REG		0xFD
+
+
+#define BU21013_RESET_ENABLE		0x01
+
+#define BU21013_SENSORS_EN_0_7		0x3F
+#define BU21013_SENSORS_EN_8_15		0xFC
+#define BU21013_SENSORS_EN_16_23	0x1F
+
+#define BU21013_POS_MODE1_0		0x02
+#define BU21013_POS_MODE1_1		0x04
+#define BU21013_POS_MODE1_2		0x08
+
+#define BU21013_POS_MODE2_ZERO		0x01
+#define BU21013_POS_MODE2_AVG1		0x02
+#define BU21013_POS_MODE2_AVG2		0x04
+#define BU21013_POS_MODE2_EN_XY		0x08
+#define BU21013_POS_MODE2_EN_RAW	0x10
+#define BU21013_POS_MODE2_MULTI		0x80
+
+#define BU21013_CLK_MODE_DIV		0x01
+#define BU21013_CLK_MODE_EXT		0x02
+#define BU21013_CLK_MODE_CALIB		0x80
+
+#define BU21013_IDLET_0			0x01
+#define BU21013_IDLET_1			0x02
+#define BU21013_IDLET_2			0x04
+#define BU21013_IDLET_3			0x08
+#define BU21013_IDLE_INTERMIT_EN	0x10
+
+#define BU21013_DELTA_0_6	0x7F
+#define BU21013_FILTER_EN	0x80
+
+#define BU21013_INT_MODE_LEVEL	0x00
+#define BU21013_INT_MODE_EDGE	0x01
+
+#define BU21013_GAIN_0		0x01
+#define BU21013_GAIN_1		0x02
+#define BU21013_GAIN_2		0x04
+
+#define BU21013_OFFSET_MODE_DEFAULT	0x00
+#define BU21013_OFFSET_MODE_MOVE	0x01
+#define BU21013_OFFSET_MODE_DISABLE	0x02
+
+#define BU21013_TH_ON_0		0x01
+#define BU21013_TH_ON_1		0x02
+#define BU21013_TH_ON_2		0x04
+#define BU21013_TH_ON_3		0x08
+#define BU21013_TH_ON_4		0x10
+#define BU21013_TH_ON_5		0x20
+#define BU21013_TH_ON_6		0x40
+#define BU21013_TH_ON_7		0x80
+#define BU21013_TH_ON_MAX	0xFF
+
+#define BU21013_TH_OFF_0	0x01
+#define BU21013_TH_OFF_1	0x02
+#define BU21013_TH_OFF_2	0x04
+#define BU21013_TH_OFF_3	0x08
+#define BU21013_TH_OFF_4	0x10
+#define BU21013_TH_OFF_5	0x20
+#define BU21013_TH_OFF_6	0x40
+#define BU21013_TH_OFF_7	0x80
+#define BU21013_TH_OFF_MAX	0xFF
+
+#define BU21013_X_EDGE_0	0x01
+#define BU21013_X_EDGE_1	0x02
+#define BU21013_X_EDGE_2	0x04
+#define BU21013_X_EDGE_3	0x08
+#define BU21013_Y_EDGE_0	0x10
+#define BU21013_Y_EDGE_1	0x20
+#define BU21013_Y_EDGE_2	0x40
+#define BU21013_Y_EDGE_3	0x80
+
+#define BU21013_DONE	0x01
+#define BU21013_NUMBER_OF_X_SENSORS	(6)
+#define BU21013_NUMBER_OF_Y_SENSORS	(11)
+
+#define DRIVER_TP	"bu21013_tp"
+
+/**
+ * struct bu21013_ts_data - touch panel data structure
+ * @client: pointer to the i2c client
+ * @wait: variable to wait_queue_head_t structure
+ * @touch_stopped: touch stop flag
+ * @chip: pointer to the touch panel controller
+ * @in_dev: pointer to the input device structure
+ * @intr_pin: interrupt pin value
+ *
+ * Touch panel device data structure
+ */
+struct bu21013_ts_data {
+	struct i2c_client *client;
+	wait_queue_head_t wait;
+	bool touch_stopped;
+	const struct bu21013_platform_device *chip;
+	struct input_dev *in_dev;
+	unsigned int intr_pin;
+};
+
+/**
+ * bu21013_read_block_data(): read the touch co-ordinates
+ * @data: bu21013_ts_data structure pointer
+ * @buf: byte pointer
+ *
+ * Read the touch co-ordinates using i2c read block into buffer
+ * and returns integer.
+ */
+static int bu21013_read_block_data(struct bu21013_ts_data *data, u8 *buf)
+{
+	int ret, i;
+
+	for (i = 0; i < I2C_RETRY_COUNT; i++) {
+		ret = i2c_smbus_read_i2c_block_data
+			(data->client, BU21013_SENSORS_BTN_0_7_REG,
+				LENGTH_OF_BUFFER, buf);
+		if (ret == LENGTH_OF_BUFFER)
+			return 0;
+	}
+	return -EINVAL;
+}
+
+/**
+ * bu21013_do_touch_report(): Get the touch co-ordinates
+ * @data: bu21013_ts_data structure pointer
+ *
+ * Get the touch co-ordinates from touch sensor registers and writes
+ * into device structure and returns integer.
+ */
+static int bu21013_do_touch_report(struct bu21013_ts_data *data)
+{
+	u8	buf[LENGTH_OF_BUFFER];
+	unsigned int pos_x[2], pos_y[2];
+	bool	has_x_sensors, has_y_sensors;
+	int	finger_down_count = 0;
+	int	i;
+
+	if (data == NULL)
+		return -EINVAL;
+
+	if (bu21013_read_block_data(data, buf) < 0)
+		return -EINVAL;
+
+	has_x_sensors = hweight32(buf[0] & BU21013_SENSORS_EN_0_7);
+	has_y_sensors = hweight32(((buf[1] & BU21013_SENSORS_EN_8_15) |
+		((buf[2] & BU21013_SENSORS_EN_16_23) << SHIFT_8)) >> SHIFT_2);
+	if (!has_x_sensors || !has_y_sensors)
+		return 0;
+
+	for (i = 0; i < MAX_FINGERS; i++) {
+		const u8 *p = &buf[4 * i + 3];
+		unsigned int x = p[0] << SHIFT_2 | (p[1] & MASK_BITS);
+		unsigned int y = p[2] << SHIFT_2 | (p[3] & MASK_BITS);
+		if (x == 0 || y == 0)
+			continue;
+		pos_x[finger_down_count] = x;
+		pos_y[finger_down_count] = y;
+		finger_down_count++;
+	}
+
+	if (finger_down_count) {
+		if (finger_down_count == 2 &&
+		    (abs(pos_x[0] - pos_x[1]) < DELTA_MIN ||
+		     abs(pos_y[0] - pos_y[1]) < DELTA_MIN)) {
+			return 0;
+		}
+
+		for (i = 0; i < finger_down_count; i++) {
+			if (data->chip->x_flip)
+				pos_x[i] = data->chip->touch_x_max - pos_x[i];
+			if (data->chip->y_flip)
+				pos_y[i] = data->chip->touch_y_max - pos_y[i];
+
+			input_report_abs(data->in_dev,
+					 ABS_MT_POSITION_X, pos_x[i]);
+			input_report_abs(data->in_dev,
+					 ABS_MT_POSITION_Y, pos_y[i]);
+			input_mt_sync(data->in_dev);
+		}
+	} else
+		input_mt_sync(data->in_dev);
+
+	input_sync(data->in_dev);
+
+	return 0;
+}
+/**
+ * bu21013_gpio_irq() - gpio thread function for touch interrupt
+ * @irq: irq value
+ * @device_data: void pointer
+ *
+ * This gpio thread function for touch interrupt
+ * and returns irqreturn_t.
+ */
+static irqreturn_t bu21013_gpio_irq(int irq, void *device_data)
+{
+	struct bu21013_ts_data *data = device_data;
+	struct i2c_client *i2c = data->client;
+	int retval;
+
+	do {
+		retval = bu21013_do_touch_report(data);
+		if (retval < 0) {
+			dev_err(&i2c->dev, "bu21013_do_touch_report failed\n");
+			return IRQ_NONE;
+		}
+
+		data->intr_pin = data->chip->irq_read_val();
+		if (data->intr_pin == PEN_DOWN_INTR)
+			wait_event_timeout(data->wait, data->touch_stopped,
+					   msecs_to_jiffies(2));
+	} while (!data->intr_pin && !data->touch_stopped);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * bu21013_init_chip() - power on sequence for the bu21013 controller
+ * @data: device structure pointer
+ *
+ * This function is used to power on
+ * the bu21013 controller and returns integer.
+ */
+static int bu21013_init_chip(struct bu21013_ts_data *data)
+{
+	int retval;
+	struct i2c_client *i2c = data->client;
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_RESET_REG,
+					BU21013_RESET_ENABLE);
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_RESET reg write failed\n");
+		return retval;
+	}
+	msleep(RESET_DELAY);
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_0_7_REG,
+					BU21013_SENSORS_EN_0_7);
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_SENSOR_0_7 reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_8_15_REG,
+						BU21013_SENSORS_EN_8_15);
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_SENSOR_8_15 reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_16_23_REG,
+						BU21013_SENSORS_EN_16_23);
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_SENSOR_16_23 reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE1_REG,
+				(BU21013_POS_MODE1_0 | BU21013_POS_MODE1_1));
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_POS_MODE1 reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE2_REG,
+			(BU21013_POS_MODE2_ZERO | BU21013_POS_MODE2_AVG1 |
+			BU21013_POS_MODE2_AVG2 | BU21013_POS_MODE2_EN_RAW |
+			BU21013_POS_MODE2_MULTI));
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_POS_MODE2 reg write failed\n");
+		return retval;
+	}
+
+	if (data->chip->ext_clk)
+		retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG,
+			(BU21013_CLK_MODE_EXT | BU21013_CLK_MODE_CALIB));
+	else
+		retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG,
+			(BU21013_CLK_MODE_DIV | BU21013_CLK_MODE_CALIB));
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_CLK_MODE reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_IDLE_REG,
+				(BU21013_IDLET_0 | BU21013_IDLE_INTERMIT_EN));
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_IDLE reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_MODE_REG,
+						BU21013_INT_MODE_LEVEL);
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_INT_MODE reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_FILTER_REG,
+						(BU21013_DELTA_0_6 |
+							BU21013_FILTER_EN));
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_FILTER reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_ON_REG,
+					BU21013_TH_ON_5);
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_TH_ON reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG,
+				BU21013_TH_OFF_4 || BU21013_TH_OFF_3);
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_GAIN_REG,
+					(BU21013_GAIN_0 | BU21013_GAIN_1));
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_GAIN reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_OFFSET_MODE_REG,
+					BU21013_OFFSET_MODE_DEFAULT);
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_OFFSET_MODE reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_XY_EDGE_REG,
+				(BU21013_X_EDGE_0 | BU21013_X_EDGE_2 |
+				BU21013_Y_EDGE_1 | BU21013_Y_EDGE_3));
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_XY_EDGE reg write failed\n");
+		return retval;
+	}
+
+	retval = i2c_smbus_write_byte_data(i2c, BU21013_DONE_REG,
+							BU21013_DONE);
+	if (retval < 0) {
+		dev_err(&i2c->dev, "BU21013_REG_DONE reg write failed\n");
+		return retval;
+	}
+
+	return 0;
+}
+
+/**
+ * bu21013_free_irq() - frees IRQ registered for touchscreen
+ * @bu21013_data: device structure pointer
+ *
+ * This function signals interrupt thread to stop processing and
+ * frees interrupt.
+ */
+static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data)
+{
+	bu21013_data->touch_stopped = true;
+	wake_up(&bu21013_data->wait);
+	free_irq(bu21013_data->chip->irq, bu21013_data);
+}
+
+/**
+ * bu21013_probe() - initializes the i2c-client touchscreen driver
+ * @client: i2c client structure pointer
+ * @id: i2c device id pointer
+ *
+ * This function used to initializes the i2c-client touchscreen
+ * driver and returns integer.
+ */
+static int __devinit bu21013_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	struct bu21013_ts_data *bu21013_data;
+	struct input_dev *in_dev;
+	const struct bu21013_platform_device *pdata =
+					client->dev.platform_data;
+	int error;
+
+	if (!i2c_check_functionality(client->adapter,
+					I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_err(&client->dev, "i2c smbus byte data not supported\n");
+		return -EIO;
+	}
+
+	if (!pdata) {
+		dev_err(&client->dev, "platform data not defined\n");
+		return -EINVAL;
+	}
+
+	bu21013_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL);
+	in_dev = input_allocate_device();
+	if (!bu21013_data || !in_dev) {
+		dev_err(&client->dev, "device memory alloc failed\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	bu21013_data->in_dev = in_dev;
+	bu21013_data->chip = pdata;
+	bu21013_data->client = client;
+	bu21013_data->touch_stopped = false;
+	init_waitqueue_head(&bu21013_data->wait);
+
+	/* configure the gpio pins */
+	if (pdata->cs_en) {
+		error = pdata->cs_en(pdata->cs_pin);
+		if (error < 0) {
+			dev_err(&client->dev, "chip init failed\n");
+			goto err_free_mem;
+		}
+	}
+
+	/* configure the touch panel controller */
+	error = bu21013_init_chip(bu21013_data);
+	if (error) {
+		dev_err(&client->dev, "error in bu21013 config\n");
+		goto err_cs_disable;
+	}
+
+	/* register the device to input subsystem */
+	in_dev->name = DRIVER_TP;
+	in_dev->id.bustype = BUS_I2C;
+	in_dev->dev.parent = &client->dev;
+
+	__set_bit(EV_SYN, in_dev->evbit);
+	__set_bit(EV_KEY, in_dev->evbit);
+	__set_bit(EV_ABS, in_dev->evbit);
+
+	input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0,
+						pdata->x_max_res, 0, 0);
+	input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0,
+						pdata->y_max_res, 0, 0);
+	input_set_drvdata(in_dev, bu21013_data);
+
+	error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq,
+				     IRQF_TRIGGER_FALLING | IRQF_SHARED,
+				     DRIVER_TP, bu21013_data);
+	if (error) {
+		dev_err(&client->dev, "request irq %d failed\n", pdata->irq);
+		goto err_cs_disable;
+	}
+
+	error = input_register_device(in_dev);
+	if (error) {
+		dev_err(&client->dev, "failed to register input device\n");
+		goto err_free_irq;
+	}
+
+	device_init_wakeup(&client->dev, pdata->wakeup);
+	i2c_set_clientdata(client, bu21013_data);
+
+	return 0;
+
+err_free_irq:
+	bu21013_free_irq(bu21013_data);
+err_cs_disable:
+	pdata->cs_dis(pdata->cs_pin);
+err_free_mem:
+	input_free_device(bu21013_data->in_dev);
+	kfree(bu21013_data);
+
+	return error;
+}
+/**
+ * bu21013_remove() - removes the i2c-client touchscreen driver
+ * @client: i2c client structure pointer
+ *
+ * This function uses to remove the i2c-client
+ * touchscreen driver and returns integer.
+ */
+static int __devexit bu21013_remove(struct i2c_client *client)
+{
+	struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);
+
+	bu21013_free_irq(bu21013_data);
+
+	bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin);
+
+	input_unregister_device(bu21013_data->in_dev);
+	kfree(bu21013_data);
+
+	device_init_wakeup(&client->dev, false);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/**
+ * bu21013_suspend() - suspend the touch screen controller
+ * @dev: pointer to device structure
+ *
+ * This function is used to suspend the
+ * touch panel controller and returns integer
+ */
+static int bu21013_suspend(struct device *dev)
+{
+	struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev);
+	struct i2c_client *client = bu21013_data->client;
+
+	bu21013_data->touch_stopped = true;
+	if (device_may_wakeup(&client->dev))
+		enable_irq_wake(bu21013_data->chip->irq);
+	else
+		disable_irq(bu21013_data->chip->irq);
+
+	return 0;
+}
+
+/**
+ * bu21013_resume() - resume the touch screen controller
+ * @dev: pointer to device structure
+ *
+ * This function is used to resume the touch panel
+ * controller and returns integer.
+ */
+static int bu21013_resume(struct device *dev)
+{
+	struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev);
+	struct i2c_client *client = bu21013_data->client;
+	int retval;
+
+	retval = bu21013_init_chip(bu21013_data);
+	if (retval < 0) {
+		dev_err(&client->dev, "bu21013 controller config failed\n");
+		return retval;
+	}
+
+	bu21013_data->touch_stopped = false;
+
+	if (device_may_wakeup(&client->dev))
+		disable_irq_wake(bu21013_data->chip->irq);
+	else
+		enable_irq(bu21013_data->chip->irq);
+
+	return 0;
+}
+
+static const struct dev_pm_ops bu21013_dev_pm_ops = {
+	.suspend = bu21013_suspend,
+	.resume  = bu21013_resume,
+};
+#endif
+
+static const struct i2c_device_id bu21013_id[] = {
+	{ DRIVER_TP, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, bu21013_id);
+
+static struct i2c_driver bu21013_driver = {
+	.driver	= {
+		.name	=	DRIVER_TP,
+		.owner	=	THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	=	&bu21013_dev_pm_ops,
+#endif
+	},
+	.probe		=	bu21013_probe,
+	.remove		=	__devexit_p(bu21013_remove),
+	.id_table	=	bu21013_id,
+};
+
+/**
+ * bu21013_init() - initializes the bu21013 touchscreen driver
+ *
+ * This function used to initializes the bu21013
+ * touchscreen driver and returns integer.
+ */
+static int __init bu21013_init(void)
+{
+	return i2c_add_driver(&bu21013_driver);
+}
+
+/**
+ * bu21013_exit() - de-initializes the bu21013 touchscreen driver
+ *
+ * This function uses to de-initializes the bu21013
+ * touchscreen driver and returns none.
+ */
+static void __exit bu21013_exit(void)
+{
+	i2c_del_driver(&bu21013_driver);
+}
+
+module_init(bu21013_init);
+module_exit(bu21013_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>");
+MODULE_DESCRIPTION("bu21013 touch screen controller driver");
diff --git a/drivers/input/touchscreen/cy8ctmg110_ts.c b/drivers/input/touchscreen/cy8ctmg110_ts.c
index 5ec0946..d0c3a72 100644
--- a/drivers/input/touchscreen/cy8ctmg110_ts.c
+++ b/drivers/input/touchscreen/cy8ctmg110_ts.c
@@ -206,9 +206,9 @@
 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
 	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,
-			CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 0, 0);
+			CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
 
 	if (ts->reset_pin) {
 		err = gpio_request(ts->reset_pin, NULL);
diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
index a89700e..498bd62 100644
--- a/drivers/input/touchscreen/hp680_ts_input.c
+++ b/drivers/input/touchscreen/hp680_ts_input.c
@@ -107,8 +107,7 @@
 	return 0;
 
  fail2:	free_irq(HP680_TS_IRQ, NULL);
-	cancel_delayed_work(&work);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&work);
  fail1:	input_free_device(hp680_ts_dev);
 	return err;
 }
@@ -116,8 +115,7 @@
 static void __exit hp680_ts_exit(void)
 {
 	free_irq(HP680_TS_IRQ, NULL);
-	cancel_delayed_work(&work);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&work);
 	input_unregister_device(hp680_ts_dev);
 }
 
diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c
new file mode 100644
index 0000000..c0307b2
--- /dev/null
+++ b/drivers/input/touchscreen/intel-mid-touch.c
@@ -0,0 +1,687 @@
+/*
+ * Intel MID Resistive Touch Screen Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
+ *			    Ramesh Agarwal (ramesh.agarwal@intel.com)
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * TODO:
+ *	review conversion of r/m/w sequences
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/param.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <asm/intel_scu_ipc.h>
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_ID1		0x00 /* PMIC ID1 register */
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_INT		0x04 /* PMIC interrupt register */
+#define PMIC_REG_MINT		0x05 /* PMIC interrupt mask register */
+
+/* ADC Interrupt registers */
+#define PMIC_REG_ADCINT		0x5F /* ADC interrupt register */
+#define PMIC_REG_MADCINT	0x60 /* ADC interrupt mask register */
+
+/* ADC Control registers */
+#define PMIC_REG_ADCCNTL1	0x61 /* ADC control register */
+
+/* ADC Channel Selection registers */
+#define PMICADDR0		0xA4
+#define END_OF_CHANNEL		0x1F
+
+/* ADC Result register */
+#define PMIC_REG_ADCSNS0H	0x64
+
+/* ADC channels for touch screen */
+#define MRST_TS_CHAN10		0xA /* Touch screen X+ connection */
+#define MRST_TS_CHAN11		0xB /* Touch screen X- connection */
+#define MRST_TS_CHAN12		0xC /* Touch screen Y+ connection */
+#define MRST_TS_CHAN13		0xD /* Touch screen Y- connection */
+
+/* Touch screen channel BIAS constants */
+#define MRST_XBIAS		0x20
+#define MRST_YBIAS		0x40
+#define MRST_ZBIAS		0x80
+
+/* Touch screen coordinates */
+#define MRST_X_MIN		10
+#define MRST_X_MAX		1024
+#define MRST_X_FUZZ		5
+#define MRST_Y_MIN		10
+#define MRST_Y_MAX		1024
+#define MRST_Y_FUZZ		5
+#define MRST_PRESSURE_MIN	0
+#define MRST_PRESSURE_NOMINAL	50
+#define MRST_PRESSURE_MAX	100
+
+#define WAIT_ADC_COMPLETION	10 /* msec */
+
+/* PMIC ADC round robin delays */
+#define ADC_LOOP_DELAY0		0x0 /* Continuous loop */
+#define ADC_LOOP_DELAY1		0x1 /* 4.5  ms approximate */
+
+/* PMIC Vendor Identifiers */
+#define PMIC_VENDOR_FS		0 /* PMIC vendor FreeScale */
+#define PMIC_VENDOR_MAXIM	1 /* PMIC vendor MAXIM */
+#define PMIC_VENDOR_NEC		2 /* PMIC vendor NEC */
+#define MRSTOUCH_MAX_CHANNELS	32 /* Maximum ADC channels */
+
+/* Touch screen device structure */
+struct mrstouch_dev {
+	struct device *dev; /* device associated with touch screen */
+	struct input_dev *input;
+	char phys[32];
+	u16 asr;		/* Address selection register */
+	int irq;
+	unsigned int vendor;	/* PMIC vendor */
+	unsigned int rev;	/* PMIC revision */
+
+	int (*read_prepare)(struct mrstouch_dev *tsdev);
+	int (*read)(struct mrstouch_dev *tsdev, u16 *x, u16 *y, u16 *z);
+	int (*read_finish)(struct mrstouch_dev *tsdev);
+};
+
+
+/*************************** NEC and Maxim Interface ************************/
+
+static int mrstouch_nec_adc_read_prepare(struct mrstouch_dev *tsdev)
+{
+	return intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0, 0x20);
+}
+
+/*
+ * Enables PENDET interrupt.
+ */
+static int mrstouch_nec_adc_read_finish(struct mrstouch_dev *tsdev)
+{
+	int err;
+
+	err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x20, 0x20);
+	if (!err)
+		err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, 0, 0x05);
+
+	return err;
+}
+
+/*
+ * Reads PMIC ADC touch screen result
+ * Reads ADC storage registers for higher 7 and lower 3 bits and
+ * converts the two readings into a single value and turns off gain bit
+ */
+static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
+{
+	int err;
+	u16 result;
+	u32 res;
+
+	result = PMIC_REG_ADCSNS0H + offset;
+
+	if (chan == MRST_TS_CHAN12)
+		result += 4;
+
+	err = intel_scu_ipc_ioread32(result, &res);
+	if (err)
+		return err;
+
+	/* Mash the bits up */
+
+	*vp = (res & 0xFF) << 3;	/* Highest 7 bits */
+	*vp |= (res >> 8) & 0x07;	/* Lower 3 bits */
+	*vp &= 0x3FF;
+
+	res >>= 16;
+
+	*vm = (res & 0xFF) << 3;	/* Highest 7 bits */
+	*vm |= (res >> 8) & 0x07;	/* Lower 3 bits */
+	*vm &= 0x3FF;
+
+	return 0;
+}
+
+/*
+ * Enables X, Y and Z bias values
+ * Enables YPYM for X channels and XPXM for Y channels
+ */
+static int mrstouch_ts_bias_set(uint offset, uint bias)
+{
+	int count;
+	u16 chan, start;
+	u16 reg[4];
+	u8 data[4];
+
+	chan = PMICADDR0 + offset;
+	start = MRST_TS_CHAN10;
+
+	for (count = 0; count <= 3; count++) {
+		reg[count] = chan++;
+		data[count] = bias | (start + count);
+	}
+
+	return intel_scu_ipc_writev(reg, data, 4);
+}
+
+/* To read touch screen channel values */
+static int mrstouch_nec_adc_read(struct mrstouch_dev *tsdev,
+				 u16 *x, u16 *y, u16 *z)
+{
+	int err;
+	u16 xm, ym, zm;
+
+	/* configure Y bias for X channels */
+	err = mrstouch_ts_bias_set(tsdev->asr, MRST_YBIAS);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* read x+ and x- channels */
+	err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, x, &xm);
+	if (err)
+		goto ipc_error;
+
+	/* configure x bias for y channels */
+	err = mrstouch_ts_bias_set(tsdev->asr, MRST_XBIAS);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* read y+ and y- channels */
+	err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, y, &ym);
+	if (err)
+		goto ipc_error;
+
+	/* configure z bias for x and y channels */
+	err = mrstouch_ts_bias_set(tsdev->asr, MRST_ZBIAS);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* read z+ and z- channels */
+	err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, z, &zm);
+	if (err)
+		goto ipc_error;
+
+	return 0;
+
+ipc_error:
+	dev_err(tsdev->dev, "ipc error during adc read\n");
+	return err;
+}
+
+
+/*************************** Freescale Interface ************************/
+
+static int mrstouch_fs_adc_read_prepare(struct mrstouch_dev *tsdev)
+{
+	int err, count;
+	u16 chan;
+	u16 reg[5];
+	u8 data[5];
+
+	/* Stop the ADC */
+	err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
+	if (err)
+		goto ipc_error;
+
+	chan = PMICADDR0 + tsdev->asr;
+
+	/* Set X BIAS */
+	for (count = 0; count <= 3; count++) {
+		reg[count] = chan++;
+		data[count] = 0x2A;
+	}
+	reg[count] =  chan++; /* Dummy */
+	data[count] = 0;
+
+	err = intel_scu_ipc_writev(reg, data, 5);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* Set Y BIAS */
+	for (count = 0; count <= 3; count++) {
+		reg[count] = chan++;
+		data[count] = 0x4A;
+	}
+	reg[count] = chan++; /* Dummy */
+	data[count] = 0;
+
+	err = intel_scu_ipc_writev(reg, data, 5);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	/* Set Z BIAS */
+	err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
+	if (err)
+		goto ipc_error;
+
+	msleep(WAIT_ADC_COMPLETION);
+
+	return 0;
+
+ipc_error:
+	dev_err(tsdev->dev, "ipc error during %s\n", __func__);
+	return err;
+}
+
+static int mrstouch_fs_adc_read(struct mrstouch_dev *tsdev,
+				u16 *x, u16 *y, u16 *z)
+{
+	int err;
+	u16 result;
+	u16 reg[4];
+	u8 data[4];
+
+	result = PMIC_REG_ADCSNS0H + tsdev->asr;
+
+	reg[0] = result + 4;
+	reg[1] = result + 5;
+	reg[2] = result + 16;
+	reg[3] = result + 17;
+
+	err = intel_scu_ipc_readv(reg, data, 4);
+	if (err)
+		goto ipc_error;
+
+	*x = data[0] << 3; /* Higher 7 bits */
+	*x |= data[1] & 0x7; /* Lower 3 bits */
+	*x &= 0x3FF;
+
+	*y = data[2] << 3; /* Higher 7 bits */
+	*y |= data[3] & 0x7; /* Lower 3 bits */
+	*y &= 0x3FF;
+
+	/* Read Z value */
+	reg[0] = result + 28;
+	reg[1] = result + 29;
+
+	err = intel_scu_ipc_readv(reg, data, 4);
+	if (err)
+		goto ipc_error;
+
+	*z = data[0] << 3; /* Higher 7 bits */
+	*z |= data[1] & 0x7; /* Lower 3 bits */
+	*z &= 0x3FF;
+
+	return 0;
+
+ipc_error:
+	dev_err(tsdev->dev, "ipc error during %s\n", __func__);
+	return err;
+}
+
+static int mrstouch_fs_adc_read_finish(struct mrstouch_dev *tsdev)
+{
+	int err, count;
+	u16 chan;
+	u16 reg[5];
+	u8 data[5];
+
+	/* Clear all TS channels */
+	chan = PMICADDR0 + tsdev->asr;
+	for (count = 0; count <= 4; count++) {
+		reg[count] = chan++;
+		data[count] = 0;
+	}
+	err = intel_scu_ipc_writev(reg, data, 5);
+	if (err)
+		goto ipc_error;
+
+	for (count = 0; count <= 4; count++) {
+		reg[count] = chan++;
+		data[count] = 0;
+	}
+	err = intel_scu_ipc_writev(reg, data, 5);
+	if (err)
+		goto ipc_error;
+
+	err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
+	if (err)
+		goto ipc_error;
+
+	/* Start ADC */
+	err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
+	if (err)
+		goto ipc_error;
+
+	return 0;
+
+ipc_error:
+	dev_err(tsdev->dev, "ipc error during %s\n", __func__);
+	return err;
+}
+
+static void mrstouch_report_event(struct input_dev *input,
+			unsigned int x, unsigned int y, unsigned int z)
+{
+	if (z > MRST_PRESSURE_NOMINAL) {
+		/* Pen touched, report button touch and coordinates */
+		input_report_key(input, BTN_TOUCH, 1);
+		input_report_abs(input, ABS_X, x);
+		input_report_abs(input, ABS_Y, y);
+	} else {
+		input_report_key(input, BTN_TOUCH, 0);
+	}
+
+	input_report_abs(input, ABS_PRESSURE, z);
+	input_sync(input);
+}
+
+/* PENDET interrupt handler */
+static irqreturn_t mrstouch_pendet_irq(int irq, void *dev_id)
+{
+	struct mrstouch_dev *tsdev = dev_id;
+	u16 x, y, z;
+
+	/*
+	 * Should we lower thread priority? Probably not, since we are
+	 * not spinning but sleeping...
+	 */
+
+	if (tsdev->read_prepare(tsdev))
+		goto out;
+
+	do {
+		if (tsdev->read(tsdev, &x, &y, &z))
+			break;
+
+		mrstouch_report_event(tsdev->input, x, y, z);
+	} while (z > MRST_PRESSURE_NOMINAL);
+
+	tsdev->read_finish(tsdev);
+
+out:
+	return IRQ_HANDLED;
+}
+
+/* Utility to read PMIC ID */
+static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
+{
+	int err;
+	u8 r;
+
+	err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
+	if (err)
+		return err;
+
+	*vendor = r & 0x7;
+	*rev = (r >> 3) & 0x7;
+
+	return 0;
+}
+
+/*
+ * Parse ADC channels to find end of the channel configured by other ADC user
+ * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
+ */
+static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
+{
+	int err, i, found;
+	u8 r8;
+
+	found = -1;
+
+	for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
+		if (found >= 0)
+			break;
+
+		err = intel_scu_ipc_ioread8(PMICADDR0 + i, &r8);
+		if (err)
+			return err;
+
+		if (r8 == END_OF_CHANNEL) {
+			found = i;
+			break;
+		}
+	}
+	if (found < 0)
+		return 0;
+
+	if (tsdev->vendor == PMIC_VENDOR_FS) {
+		if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
+			return -ENOSPC;
+	} else {
+		if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
+			return -ENOSPC;
+	}
+	return found;
+}
+
+
+/*
+ * Writes touch screen channels to ADC address selection registers
+ */
+static int __devinit mrstouch_ts_chan_set(uint offset)
+{
+	u16 chan;
+
+	int ret, count;
+
+	chan = PMICADDR0 + offset;
+	for (count = 0; count <= 3; count++) {
+		ret = intel_scu_ipc_iowrite8(chan++, MRST_TS_CHAN10 + count);
+		if (ret)
+			return ret;
+	}
+	return intel_scu_ipc_iowrite8(chan++, END_OF_CHANNEL);
+}
+
+/* Initialize ADC */
+static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev)
+{
+	int err, start;
+	u8 ra, rm;
+
+	err = mrstouch_read_pmic_id(&tsdev->vendor, &tsdev->rev);
+	if (err) {
+		dev_err(tsdev->dev, "Unable to read PMIC id\n");
+		return err;
+	}
+
+	switch (tsdev->vendor) {
+	case PMIC_VENDOR_NEC:
+	case PMIC_VENDOR_MAXIM:
+		tsdev->read_prepare = mrstouch_nec_adc_read_prepare;
+		tsdev->read = mrstouch_nec_adc_read;
+		tsdev->read_finish = mrstouch_nec_adc_read_finish;
+		break;
+
+	case PMIC_VENDOR_FS:
+		tsdev->read_prepare = mrstouch_fs_adc_read_prepare;
+		tsdev->read = mrstouch_fs_adc_read;
+		tsdev->read_finish = mrstouch_fs_adc_read_finish;
+		break;
+
+	default:
+		dev_err(tsdev->dev,
+			"Unsupported touchscreen: %d\n", tsdev->vendor);
+		return -ENXIO;
+	}
+
+	start = mrstouch_chan_parse(tsdev);
+	if (start < 0) {
+		dev_err(tsdev->dev, "Unable to parse channels\n");
+		return start;
+	}
+
+	tsdev->asr = start;
+
+	/*
+	 * ADC power on, start, enable PENDET and set loop delay
+	 * ADC loop delay is set to 4.5 ms approximately
+	 * Loop delay more than this results in jitter in adc readings
+	 * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
+	 * interrupt generation sometimes.
+	 */
+
+	if (tsdev->vendor == PMIC_VENDOR_FS) {
+		ra = 0xE0 | ADC_LOOP_DELAY0;
+		rm = 0x5;
+	} else {
+		/* NEC and MAXIm not consistent with loop delay 0 */
+		ra = 0xE0 | ADC_LOOP_DELAY1;
+		rm = 0x0;
+
+		/* configure touch screen channels */
+		err = mrstouch_ts_chan_set(tsdev->asr);
+		if (err)
+			return err;
+	}
+
+	err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
+	if (err)
+		return err;
+
+	err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+
+/* Probe function for touch screen driver */
+static int __devinit mrstouch_probe(struct platform_device *pdev)
+{
+	struct mrstouch_dev *tsdev;
+	struct input_dev *input;
+	int err;
+	int irq;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no interrupt assigned\n");
+		return -EINVAL;
+	}
+
+	tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
+	input = input_allocate_device();
+	if (!tsdev || !input) {
+		dev_err(&pdev->dev, "unable to allocate memory\n");
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	tsdev->dev = &pdev->dev;
+	tsdev->input = input;
+	tsdev->irq = irq;
+
+	snprintf(tsdev->phys, sizeof(tsdev->phys),
+		 "%s/input0", dev_name(tsdev->dev));
+
+	err = mrstouch_adc_init(tsdev);
+	if (err) {
+		dev_err(&pdev->dev, "ADC initialization failed\n");
+		goto err_free_mem;
+	}
+
+	input->name = "mrst_touchscreen";
+	input->phys = tsdev->phys;
+	input->dev.parent = tsdev->dev;
+
+	input->id.vendor = tsdev->vendor;
+	input->id.version = tsdev->rev;
+
+	input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	input_set_abs_params(tsdev->input, ABS_X,
+			     MRST_X_MIN, MRST_X_MAX, MRST_X_FUZZ, 0);
+	input_set_abs_params(tsdev->input, ABS_Y,
+			     MRST_Y_MIN, MRST_Y_MAX, MRST_Y_FUZZ, 0);
+	input_set_abs_params(tsdev->input, ABS_PRESSURE,
+			     MRST_PRESSURE_MIN, MRST_PRESSURE_MAX, 0, 0);
+
+	err = request_threaded_irq(tsdev->irq, NULL, mrstouch_pendet_irq,
+				   0, "mrstouch", tsdev);
+	if (err) {
+		dev_err(tsdev->dev, "unable to allocate irq\n");
+		goto err_free_mem;
+	}
+
+	err = input_register_device(tsdev->input);
+	if (err) {
+		dev_err(tsdev->dev, "unable to register input device\n");
+		goto err_free_irq;
+	}
+
+	platform_set_drvdata(pdev, tsdev);
+	return 0;
+
+err_free_irq:
+	free_irq(tsdev->irq, tsdev);
+err_free_mem:
+	input_free_device(input);
+	kfree(tsdev);
+	return err;
+}
+
+static int __devexit mrstouch_remove(struct platform_device *pdev)
+{
+	struct mrstouch_dev *tsdev = platform_get_drvdata(pdev);
+
+	free_irq(tsdev->irq, tsdev);
+	input_unregister_device(tsdev->input);
+	kfree(tsdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver mrstouch_driver = {
+	.driver = {
+		.name	= "pmic_touch",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= mrstouch_probe,
+	.remove		= __devexit_p(mrstouch_remove),
+};
+
+static int __init mrstouch_init(void)
+{
+	return platform_driver_register(&mrstouch_driver);
+}
+module_init(mrstouch_init);
+
+static void __exit mrstouch_exit(void)
+{
+	platform_driver_unregister(&mrstouch_driver);
+}
+module_exit(mrstouch_exit);
+
+MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
+MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
new file mode 100644
index 0000000..dcf803f
--- /dev/null
+++ b/drivers/input/touchscreen/lpc32xx_ts.c
@@ -0,0 +1,411 @@
+/*
+ * LPC32xx built-in touchscreen driver
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+/*
+ * Touchscreen controller register offsets
+ */
+#define LPC32XX_TSC_STAT			0x00
+#define LPC32XX_TSC_SEL				0x04
+#define LPC32XX_TSC_CON				0x08
+#define LPC32XX_TSC_FIFO			0x0C
+#define LPC32XX_TSC_DTR				0x10
+#define LPC32XX_TSC_RTR				0x14
+#define LPC32XX_TSC_UTR				0x18
+#define LPC32XX_TSC_TTR				0x1C
+#define LPC32XX_TSC_DXP				0x20
+#define LPC32XX_TSC_MIN_X			0x24
+#define LPC32XX_TSC_MAX_X			0x28
+#define LPC32XX_TSC_MIN_Y			0x2C
+#define LPC32XX_TSC_MAX_Y			0x30
+#define LPC32XX_TSC_AUX_UTR			0x34
+#define LPC32XX_TSC_AUX_MIN			0x38
+#define LPC32XX_TSC_AUX_MAX			0x3C
+
+#define LPC32XX_TSC_STAT_FIFO_OVRRN		(1 << 8)
+#define LPC32XX_TSC_STAT_FIFO_EMPTY		(1 << 7)
+
+#define LPC32XX_TSC_SEL_DEFVAL			0x0284
+
+#define LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4	(0x1 << 11)
+#define LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(s)	((10 - (s)) << 7)
+#define LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(s)	((10 - (s)) << 4)
+#define LPC32XX_TSC_ADCCON_POWER_UP		(1 << 2)
+#define LPC32XX_TSC_ADCCON_AUTO_EN		(1 << 0)
+
+#define LPC32XX_TSC_FIFO_TS_P_LEVEL		(1 << 31)
+#define LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(x)	(((x) & 0x03FF0000) >> 16)
+#define LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(y)	((y) & 0x000003FF)
+
+#define LPC32XX_TSC_ADCDAT_VALUE_MASK		0x000003FF
+
+#define LPC32XX_TSC_MIN_XY_VAL			0x0
+#define LPC32XX_TSC_MAX_XY_VAL			0x3FF
+
+#define MOD_NAME "ts-lpc32xx"
+
+#define tsc_readl(dev, reg) \
+	__raw_readl((dev)->tsc_base + (reg))
+#define tsc_writel(dev, reg, val) \
+	__raw_writel((val), (dev)->tsc_base + (reg))
+
+struct lpc32xx_tsc {
+	struct input_dev *dev;
+	void __iomem *tsc_base;
+	int irq;
+	struct clk *clk;
+};
+
+static void lpc32xx_fifo_clear(struct lpc32xx_tsc *tsc)
+{
+	while (!(tsc_readl(tsc, LPC32XX_TSC_STAT) &
+			LPC32XX_TSC_STAT_FIFO_EMPTY))
+		tsc_readl(tsc, LPC32XX_TSC_FIFO);
+}
+
+static irqreturn_t lpc32xx_ts_interrupt(int irq, void *dev_id)
+{
+	u32 tmp, rv[4], xs[4], ys[4];
+	int idx;
+	struct lpc32xx_tsc *tsc = dev_id;
+	struct input_dev *input = tsc->dev;
+
+	tmp = tsc_readl(tsc, LPC32XX_TSC_STAT);
+
+	if (tmp & LPC32XX_TSC_STAT_FIFO_OVRRN) {
+		/* FIFO overflow - throw away samples */
+		lpc32xx_fifo_clear(tsc);
+		return IRQ_HANDLED;
+	}
+
+	/*
+	 * Gather and normalize 4 samples. Pen-up events may have less
+	 * than 4 samples, but its ok to pop 4 and let the last sample
+	 * pen status check drop the samples.
+	 */
+	idx = 0;
+	while (idx < 4 &&
+	       !(tsc_readl(tsc, LPC32XX_TSC_STAT) &
+			LPC32XX_TSC_STAT_FIFO_EMPTY)) {
+		tmp = tsc_readl(tsc, LPC32XX_TSC_FIFO);
+		xs[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
+			LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(tmp);
+		ys[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
+			LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(tmp);
+		rv[idx] = tmp;
+		idx++;
+	}
+
+	/* Data is only valid if pen is still down in last sample */
+	if (!(rv[3] & LPC32XX_TSC_FIFO_TS_P_LEVEL) && idx == 4) {
+		/* Use average of 2nd and 3rd sample for position */
+		input_report_abs(input, ABS_X, (xs[1] + xs[2]) / 2);
+		input_report_abs(input, ABS_Y, (ys[1] + ys[2]) / 2);
+		input_report_key(input, BTN_TOUCH, 1);
+	} else {
+		input_report_key(input, BTN_TOUCH, 0);
+	}
+
+	input_sync(input);
+
+	return IRQ_HANDLED;
+}
+
+static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc)
+{
+	/* Disable auto mode */
+	tsc_writel(tsc, LPC32XX_TSC_CON,
+		   tsc_readl(tsc, LPC32XX_TSC_CON) &
+			     ~LPC32XX_TSC_ADCCON_AUTO_EN);
+
+	clk_disable(tsc->clk);
+}
+
+static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc)
+{
+	u32 tmp;
+
+	clk_enable(tsc->clk);
+
+	tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP;
+
+	/* Set the TSC FIFO depth to 4 samples @ 10-bits per sample (max) */
+	tmp = LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 |
+	      LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(10) |
+	      LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(10);
+	tsc_writel(tsc, LPC32XX_TSC_CON, tmp);
+
+	/* These values are all preset */
+	tsc_writel(tsc, LPC32XX_TSC_SEL, LPC32XX_TSC_SEL_DEFVAL);
+	tsc_writel(tsc, LPC32XX_TSC_MIN_X, LPC32XX_TSC_MIN_XY_VAL);
+	tsc_writel(tsc, LPC32XX_TSC_MAX_X, LPC32XX_TSC_MAX_XY_VAL);
+	tsc_writel(tsc, LPC32XX_TSC_MIN_Y, LPC32XX_TSC_MIN_XY_VAL);
+	tsc_writel(tsc, LPC32XX_TSC_MAX_Y, LPC32XX_TSC_MAX_XY_VAL);
+
+	/* Aux support is not used */
+	tsc_writel(tsc, LPC32XX_TSC_AUX_UTR, 0);
+	tsc_writel(tsc, LPC32XX_TSC_AUX_MIN, 0);
+	tsc_writel(tsc, LPC32XX_TSC_AUX_MAX, 0);
+
+	/*
+	 * Set sample rate to about 240Hz per X/Y pair. A single measurement
+	 * consists of 4 pairs which gives about a 60Hz sample rate based on
+	 * a stable 32768Hz clock source. Values are in clocks.
+	 * Rate is (32768 / (RTR + XCONV + RTR + YCONV + DXP + TTR + UTR) / 4
+	 */
+	tsc_writel(tsc, LPC32XX_TSC_RTR, 0x2);
+	tsc_writel(tsc, LPC32XX_TSC_DTR, 0x2);
+	tsc_writel(tsc, LPC32XX_TSC_TTR, 0x10);
+	tsc_writel(tsc, LPC32XX_TSC_DXP, 0x4);
+	tsc_writel(tsc, LPC32XX_TSC_UTR, 88);
+
+	lpc32xx_fifo_clear(tsc);
+
+	/* Enable automatic ts event capture */
+	tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN);
+}
+
+static int lpc32xx_ts_open(struct input_dev *dev)
+{
+	struct lpc32xx_tsc *tsc = input_get_drvdata(dev);
+
+	lpc32xx_setup_tsc(tsc);
+
+	return 0;
+}
+
+static void lpc32xx_ts_close(struct input_dev *dev)
+{
+	struct lpc32xx_tsc *tsc = input_get_drvdata(dev);
+
+	lpc32xx_stop_tsc(tsc);
+}
+
+static int __devinit lpc32xx_ts_probe(struct platform_device *pdev)
+{
+	struct lpc32xx_tsc *tsc;
+	struct input_dev *input;
+	struct resource *res;
+	resource_size_t size;
+	int irq;
+	int error;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Can't get memory resource\n");
+		return -ENOENT;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "Can't get interrupt resource\n");
+		return irq;
+	}
+
+	tsc = kzalloc(sizeof(*tsc), GFP_KERNEL);
+	input = input_allocate_device();
+	if (!tsc || !input) {
+		dev_err(&pdev->dev, "failed allocating memory\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	tsc->dev = input;
+	tsc->irq = irq;
+
+	size = resource_size(res);
+
+	if (!request_mem_region(res->start, size, pdev->name)) {
+		dev_err(&pdev->dev, "TSC registers are not free\n");
+		error = -EBUSY;
+		goto err_free_mem;
+	}
+
+	tsc->tsc_base = ioremap(res->start, size);
+	if (!tsc->tsc_base) {
+		dev_err(&pdev->dev, "Can't map memory\n");
+		error = -ENOMEM;
+		goto err_release_mem;
+	}
+
+	tsc->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(tsc->clk)) {
+		dev_err(&pdev->dev, "failed getting clock\n");
+		error = PTR_ERR(tsc->clk);
+		goto err_unmap;
+	}
+
+	input->name = MOD_NAME;
+	input->phys = "lpc32xx/input0";
+	input->id.bustype = BUS_HOST;
+	input->id.vendor = 0x0001;
+	input->id.product = 0x0002;
+	input->id.version = 0x0100;
+	input->dev.parent = &pdev->dev;
+	input->open = lpc32xx_ts_open;
+	input->close = lpc32xx_ts_close;
+
+	input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_set_abs_params(input, ABS_X, LPC32XX_TSC_MIN_XY_VAL,
+			     LPC32XX_TSC_MAX_XY_VAL, 0, 0);
+	input_set_abs_params(input, ABS_Y, LPC32XX_TSC_MIN_XY_VAL,
+			     LPC32XX_TSC_MAX_XY_VAL, 0, 0);
+
+	input_set_drvdata(input, tsc);
+
+	error = request_irq(tsc->irq, lpc32xx_ts_interrupt,
+			    IRQF_DISABLED, pdev->name, tsc);
+	if (error) {
+		dev_err(&pdev->dev, "failed requesting interrupt\n");
+		goto err_put_clock;
+	}
+
+	error = input_register_device(input);
+	if (error) {
+		dev_err(&pdev->dev, "failed registering input device\n");
+		goto err_free_irq;
+	}
+
+	platform_set_drvdata(pdev, tsc);
+	device_init_wakeup(&pdev->dev, 1);
+
+	return 0;
+
+err_free_irq:
+	free_irq(tsc->irq, tsc);
+err_put_clock:
+	clk_put(tsc->clk);
+err_unmap:
+	iounmap(tsc->tsc_base);
+err_release_mem:
+	release_mem_region(res->start, size);
+err_free_mem:
+	input_free_device(input);
+	kfree(tsc);
+
+	return error;
+}
+
+static int __devexit lpc32xx_ts_remove(struct platform_device *pdev)
+{
+	struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	device_init_wakeup(&pdev->dev, 0);
+	free_irq(tsc->irq, tsc);
+
+	input_unregister_device(tsc->dev);
+
+	clk_put(tsc->clk);
+
+	iounmap(tsc->tsc_base);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(tsc);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int lpc32xx_ts_suspend(struct device *dev)
+{
+	struct lpc32xx_tsc *tsc = dev_get_drvdata(dev);
+	struct input_dev *input = tsc->dev;
+
+	/*
+	 * Suspend and resume can be called when the device hasn't been
+	 * enabled. If there are no users that have the device open, then
+	 * avoid calling the TSC stop and start functions as the TSC
+	 * isn't yet clocked.
+	 */
+	mutex_lock(&input->mutex);
+
+	if (input->users) {
+		if (device_may_wakeup(dev))
+			enable_irq_wake(tsc->irq);
+		else
+			lpc32xx_stop_tsc(tsc);
+	}
+
+	mutex_unlock(&input->mutex);
+
+	return 0;
+}
+
+static int lpc32xx_ts_resume(struct device *dev)
+{
+	struct lpc32xx_tsc *tsc = dev_get_drvdata(dev);
+	struct input_dev *input = tsc->dev;
+
+	mutex_lock(&input->mutex);
+
+	if (input->users) {
+		if (device_may_wakeup(dev))
+			disable_irq_wake(tsc->irq);
+		else
+			lpc32xx_setup_tsc(tsc);
+	}
+
+	mutex_unlock(&input->mutex);
+
+	return 0;
+}
+
+static const struct dev_pm_ops lpc32xx_ts_pm_ops = {
+	.suspend	= lpc32xx_ts_suspend,
+	.resume		= lpc32xx_ts_resume,
+};
+#define LPC32XX_TS_PM_OPS (&lpc32xx_ts_pm_ops)
+#else
+#define LPC32XX_TS_PM_OPS NULL
+#endif
+
+static struct platform_driver lpc32xx_ts_driver = {
+	.probe		= lpc32xx_ts_probe,
+	.remove		= __devexit_p(lpc32xx_ts_remove),
+	.driver		= {
+		.name	= MOD_NAME,
+		.owner	= THIS_MODULE,
+		.pm	= LPC32XX_TS_PM_OPS,
+	},
+};
+
+static int __init lpc32xx_ts_init(void)
+{
+	return platform_driver_register(&lpc32xx_ts_driver);
+}
+module_init(lpc32xx_ts_init);
+
+static void __exit lpc32xx_ts_exit(void)
+{
+	platform_driver_unregister(&lpc32xx_ts_driver);
+}
+module_exit(lpc32xx_ts_exit);
+
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com");
+MODULE_DESCRIPTION("LPC32XX TSC Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lpc32xx_ts");
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 6085d12..8feb7f3 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -350,7 +350,7 @@
  err_tcirq:
 	free_irq(ts.irq_tc, ts.input);
  err_inputdev:
-	input_unregister_device(ts.input);
+	input_free_device(ts.input);
  err_iomap:
 	iounmap(ts.io);
  err_clk:
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
index 656148e..ae88e13 100644
--- a/drivers/input/touchscreen/stmpe-ts.c
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -268,7 +268,7 @@
 	struct stmpe_touch *ts;
 	struct input_dev *idev;
 	struct stmpe_ts_platform_data *ts_pdata = NULL;
-	int ret = 0;
+	int ret;
 	int ts_irq;
 
 	ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
@@ -276,12 +276,16 @@
 		return ts_irq;
 
 	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
-	if (!ts)
+	if (!ts) {
+		ret = -ENOMEM;
 		goto err_out;
+	}
 
 	idev = input_allocate_device();
-	if (!idev)
+	if (!idev) {
+		ret = -ENOMEM;
 		goto err_free_ts;
+	}
 
 	platform_set_drvdata(pdev, ts);
 	ts->stmpe = stmpe;
@@ -361,7 +365,6 @@
 	platform_set_drvdata(pdev, NULL);
 
 	input_unregister_device(ts->idev);
-	input_free_device(ts->idev);
 
 	kfree(ts);
 
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c
index a644d18..c8c136c 100644
--- a/drivers/input/touchscreen/tps6507x-ts.c
+++ b/drivers/input/touchscreen/tps6507x-ts.c
@@ -335,6 +335,7 @@
 		dev_err(tsc->dev, "schedule failed");
 		goto err2;
 	 }
+	platform_set_drvdata(pdev, tps6507x_dev);
 
 	return 0;
 
@@ -358,7 +359,7 @@
 	cancel_delayed_work_sync(&tsc->work);
 	destroy_workqueue(tsc->wq);
 
-	input_free_device(input_dev);
+	input_unregister_device(input_dev);
 
 	tps6507x_dev->ts = NULL;
 	kfree(tsc);
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index be23780..80467f2 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -265,7 +265,7 @@
 				   const struct i2c_device_id *id)
 {
 	struct tsc2007 *ts;
-	struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data;
+	struct tsc2007_platform_data *pdata = client->dev.platform_data;
 	struct input_dev *input_dev;
 	int err;
 
diff --git a/drivers/input/touchscreen/wacom_w8001.c b/drivers/input/touchscreen/wacom_w8001.c
index 56dc35c..9ae4c7b 100644
--- a/drivers/input/touchscreen/wacom_w8001.c
+++ b/drivers/input/touchscreen/wacom_w8001.c
@@ -2,6 +2,7 @@
  * Wacom W8001 penabled serial touchscreen driver
  *
  * Copyright (c) 2008 Jaya Kumar
+ * Copyright (c) 2010 Red Hat, Inc.
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License. See the file COPYING in the main directory of this archive for
@@ -30,11 +31,24 @@
 #define W8001_LEAD_BYTE		0x80
 #define W8001_TAB_MASK		0x40
 #define W8001_TAB_BYTE		0x40
+/* set in first byte of touch data packets */
+#define W8001_TOUCH_MASK	(0x10 | W8001_LEAD_MASK)
+#define W8001_TOUCH_BYTE	(0x10 | W8001_LEAD_BYTE)
 
 #define W8001_QUERY_PACKET	0x20
 
 #define W8001_CMD_START		'1'
 #define W8001_CMD_QUERY		'*'
+#define W8001_CMD_TOUCHQUERY	'%'
+
+/* length of data packets in bytes, depends on device. */
+#define W8001_PKTLEN_TOUCH93	5
+#define W8001_PKTLEN_TOUCH9A	7
+#define W8001_PKTLEN_TPCPEN	9
+#define W8001_PKTLEN_TPCCTL	11	/* control packet */
+#define W8001_PKTLEN_TOUCH2FG	13
+
+#define MAX_TRACKING_ID		0xFF	/* arbitrarily chosen */
 
 struct w8001_coord {
 	u8 rdy;
@@ -48,6 +62,15 @@
 	u8 tilt_y;
 };
 
+/* touch query reply packet */
+struct w8001_touch_query {
+	u8 panel_res;
+	u8 capacity_res;
+	u8 sensor_id;
+	u16 x;
+	u16 y;
+};
+
 /*
  * Per-touchscreen data.
  */
@@ -62,6 +85,9 @@
 	unsigned char response[W8001_MAX_LENGTH];
 	unsigned char data[W8001_MAX_LENGTH];
 	char phys[32];
+	int type;
+	unsigned int pktlen;
+	int trkid[2];
 };
 
 static void parse_data(u8 *data, struct w8001_coord *coord)
@@ -88,11 +114,98 @@
 	coord->tilt_y = data[8] & 0x7F;
 }
 
+static void parse_touch(struct w8001 *w8001)
+{
+	static int trkid;
+	struct input_dev *dev = w8001->dev;
+	unsigned char *data = w8001->data;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		input_mt_slot(dev, i);
+
+		if (data[0] & (1 << i)) {
+			int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
+			int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
+			/* data[5,6] and [11,12] is finger capacity */
+
+			input_report_abs(dev, ABS_MT_POSITION_X, x);
+			input_report_abs(dev, ABS_MT_POSITION_Y, y);
+			input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
+			if (w8001->trkid[i] < 0)
+				w8001->trkid[i] = trkid++ & MAX_TRACKING_ID;
+		} else {
+			w8001->trkid[i] = -1;
+		}
+		input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]);
+	}
+
+	input_sync(dev);
+}
+
+static void parse_touchquery(u8 *data, struct w8001_touch_query *query)
+{
+	memset(query, 0, sizeof(*query));
+
+	query->panel_res = data[1];
+	query->sensor_id = data[2] & 0x7;
+	query->capacity_res = data[7];
+
+	query->x = data[3] << 9;
+	query->x |= data[4] << 2;
+	query->x |= (data[2] >> 5) & 0x3;
+
+	query->y = data[5] << 9;
+	query->y |= data[6] << 2;
+	query->y |= (data[2] >> 3) & 0x3;
+}
+
+static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
+{
+	struct input_dev *dev = w8001->dev;
+
+	/*
+	 * We have 1 bit for proximity (rdy) and 3 bits for tip, side,
+	 * side2/eraser. If rdy && f2 are set, this can be either pen + side2,
+	 * or eraser. assume
+	 * - if dev is already in proximity and f2 is toggled → pen + side2
+	 * - if dev comes into proximity with f2 set → eraser
+	 * If f2 disappears after assuming eraser, fake proximity out for
+	 * eraser and in for pen.
+	 */
+
+	if (!w8001->type) {
+		w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+	} else if (w8001->type == BTN_TOOL_RUBBER) {
+		if (!coord->f2) {
+			input_report_abs(dev, ABS_PRESSURE, 0);
+			input_report_key(dev, BTN_TOUCH, 0);
+			input_report_key(dev, BTN_STYLUS, 0);
+			input_report_key(dev, BTN_STYLUS2, 0);
+			input_report_key(dev, BTN_TOOL_RUBBER, 0);
+			input_sync(dev);
+			w8001->type = BTN_TOOL_PEN;
+		}
+	} else {
+		input_report_key(dev, BTN_STYLUS2, coord->f2);
+	}
+
+	input_report_abs(dev, ABS_X, coord->x);
+	input_report_abs(dev, ABS_Y, coord->y);
+	input_report_abs(dev, ABS_PRESSURE, coord->pen_pressure);
+	input_report_key(dev, BTN_TOUCH, coord->tsw);
+	input_report_key(dev, BTN_STYLUS, coord->f1);
+	input_report_key(dev, w8001->type, coord->rdy);
+	input_sync(dev);
+
+	if (!coord->rdy)
+		w8001->type = 0;
+}
+
 static irqreturn_t w8001_interrupt(struct serio *serio,
 				   unsigned char data, unsigned int flags)
 {
 	struct w8001 *w8001 = serio_get_drvdata(serio);
-	struct input_dev *dev = w8001->dev;
 	struct w8001_coord coord;
 	unsigned char tmp;
 
@@ -105,26 +218,45 @@
 		}
 		break;
 
-	case 8:
+	case W8001_PKTLEN_TOUCH93 - 1:
+	case W8001_PKTLEN_TOUCH9A - 1:
+		/* ignore one-finger touch packet. */
+		if (w8001->pktlen == w8001->idx)
+			w8001->idx = 0;
+		break;
+
+	/* Pen coordinates packet */
+	case W8001_PKTLEN_TPCPEN - 1:
 		tmp = w8001->data[0] & W8001_TAB_MASK;
 		if (unlikely(tmp == W8001_TAB_BYTE))
 			break;
 
+		tmp = (w8001->data[0] & W8001_TOUCH_BYTE);
+		if (tmp == W8001_TOUCH_BYTE)
+			break;
+
 		w8001->idx = 0;
 		parse_data(w8001->data, &coord);
-		input_report_abs(dev, ABS_X, coord.x);
-		input_report_abs(dev, ABS_Y, coord.y);
-		input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure);
-		input_report_key(dev, BTN_TOUCH, coord.tsw);
-		input_sync(dev);
+		report_pen_events(w8001, &coord);
 		break;
 
-	case 10:
+	/* control packet */
+	case W8001_PKTLEN_TPCCTL - 1:
+		tmp = (w8001->data[0] & W8001_TOUCH_MASK);
+		if (tmp == W8001_TOUCH_BYTE)
+			break;
+
 		w8001->idx = 0;
 		memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH);
 		w8001->response_type = W8001_QUERY_PACKET;
 		complete(&w8001->cmd_done);
 		break;
+
+	/* 2 finger touch packet */
+	case W8001_PKTLEN_TOUCH2FG - 1:
+		w8001->idx = 0;
+		parse_touch(w8001);
+		break;
 	}
 
 	return IRQ_HANDLED;
@@ -167,6 +299,38 @@
 	input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
 	input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
 
+	error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true);
+	if (!error) {
+		struct w8001_touch_query touch;
+
+		parse_touchquery(w8001->response, &touch);
+
+		switch (touch.sensor_id) {
+		case 0:
+		case 2:
+			w8001->pktlen = W8001_PKTLEN_TOUCH93;
+			break;
+		case 1:
+		case 3:
+		case 4:
+			w8001->pktlen = W8001_PKTLEN_TOUCH9A;
+			break;
+		case 5:
+			w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
+
+			input_mt_create_slots(dev, 2);
+			input_set_abs_params(dev, ABS_MT_TRACKING_ID,
+						0, MAX_TRACKING_ID, 0, 0);
+			input_set_abs_params(dev, ABS_MT_POSITION_X,
+						0, touch.x, 0, 0);
+			input_set_abs_params(dev, ABS_MT_POSITION_Y,
+						0, touch.y, 0, 0);
+			input_set_abs_params(dev, ABS_MT_TOOL_TYPE,
+						0, 0, 0, 0);
+			break;
+		}
+	}
+
 	return w8001_command(w8001, W8001_CMD_START, false);
 }
 
@@ -208,6 +372,7 @@
 	w8001->serio = serio;
 	w8001->id = serio->id.id;
 	w8001->dev = input_dev;
+	w8001->trkid[0] = w8001->trkid[1] = -1;
 	init_completion(&w8001->cmd_done);
 	snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
 
@@ -221,6 +386,10 @@
 
 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN);
+	input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER);
+	input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS);
+	input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2);
 
 	serio_set_drvdata(serio, w8001);
 	err = serio_open(serio, drv);
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index cbfef1e..6b75c9f 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -125,6 +125,8 @@
 {
 	int power_adc = 0, auxval;
 	u16 power = 0;
+	int rc = 0;
+	int timeout = 0;
 
 	/* get codec */
 	mutex_lock(&wm->codec_mutex);
@@ -143,7 +145,9 @@
 
 	/* Turn polling mode on to read AUX ADC */
 	wm->pen_probably_down = 1;
-	wm->codec->poll_sample(wm, adcsel, &auxval);
+
+	while (rc != RC_VALID && timeout++ < 5)
+		rc = wm->codec->poll_sample(wm, adcsel, &auxval);
 
 	if (power_adc)
 		wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
@@ -152,8 +156,15 @@
 
 	wm->pen_probably_down = 0;
 
+	if (timeout >= 5) {
+		dev_err(wm->dev,
+			"timeout reading auxadc %d, disabling digitiser\n",
+			adcsel);
+		wm->codec->dig_enable(wm, false);
+	}
+
 	mutex_unlock(&wm->codec_mutex);
-	return auxval & 0xfff;
+	return (rc == RC_VALID ? auxval & 0xfff : -EBUSY);
 }
 EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
 
@@ -684,8 +695,7 @@
  touch_reg_err:
 	platform_device_put(wm->touch_dev);
  touch_err:
-	platform_device_unregister(wm->battery_dev);
-	wm->battery_dev = NULL;
+	platform_device_del(wm->battery_dev);
  batt_reg_err:
 	platform_device_put(wm->battery_dev);
  batt_err:
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index 7961d59..c06b4d5 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -25,14 +25,56 @@
 #define IR_KEYPRESS_TIMEOUT 250
 
 /**
+ * ir_create_table() - initializes a scancode table
+ * @rc_tab:	the ir_scancode_table to initialize
+ * @name:	name to assign to the table
+ * @ir_type:	ir type to assign to the new table
+ * @size:	initial size of the table
+ * @return:	zero on success or a negative error code
+ *
+ * This routine will initialize the ir_scancode_table and will allocate
+ * memory to hold at least the specified number elements.
+ */
+static int ir_create_table(struct ir_scancode_table *rc_tab,
+			   const char *name, u64 ir_type, size_t size)
+{
+	rc_tab->name = name;
+	rc_tab->ir_type = ir_type;
+	rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode));
+	rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
+	rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL);
+	if (!rc_tab->scan)
+		return -ENOMEM;
+
+	IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+		   rc_tab->size, rc_tab->alloc);
+	return 0;
+}
+
+/**
+ * ir_free_table() - frees memory allocated by a scancode table
+ * @rc_tab:	the table whose mappings need to be freed
+ *
+ * This routine will free memory alloctaed for key mappings used by given
+ * scancode table.
+ */
+static void ir_free_table(struct ir_scancode_table *rc_tab)
+{
+	rc_tab->size = 0;
+	kfree(rc_tab->scan);
+	rc_tab->scan = NULL;
+}
+
+/**
  * ir_resize_table() - resizes a scancode table if necessary
  * @rc_tab:	the ir_scancode_table to resize
+ * @gfp_flags:	gfp flags to use when allocating memory
  * @return:	zero on success or a negative error code
  *
  * This routine will shrink the ir_scancode_table if it has lots of
  * unused entries and grow it if it is full.
  */
-static int ir_resize_table(struct ir_scancode_table *rc_tab)
+static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags)
 {
 	unsigned int oldalloc = rc_tab->alloc;
 	unsigned int newalloc = oldalloc;
@@ -57,7 +99,7 @@
 	if (newalloc == oldalloc)
 		return 0;
 
-	newscan = kmalloc(newalloc, GFP_ATOMIC);
+	newscan = kmalloc(newalloc, gfp_flags);
 	if (!newscan) {
 		IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc);
 		return -ENOMEM;
@@ -72,26 +114,78 @@
 }
 
 /**
- * ir_do_setkeycode() - internal function to set a keycode in the
- *			scancode->keycode table
+ * ir_update_mapping() - set a keycode in the scancode->keycode table
  * @dev:	the struct input_dev device descriptor
- * @rc_tab:	the struct ir_scancode_table to set the keycode in
- * @scancode:	the scancode for the ir command
- * @keycode:	the keycode for the ir command
- * @resize:	whether the keytable may be shrunk
- * @return:	-EINVAL if the keycode could not be inserted, otherwise zero.
+ * @rc_tab:	scancode table to be adjusted
+ * @index:	index of the mapping that needs to be updated
+ * @keycode:	the desired keycode
+ * @return:	previous keycode assigned to the mapping
  *
- * This routine is used internally to manipulate the scancode->keycode table.
- * The caller has to hold @rc_tab->lock.
+ * This routine is used to update scancode->keycopde mapping at given
+ * position.
  */
-static int ir_do_setkeycode(struct input_dev *dev,
-			    struct ir_scancode_table *rc_tab,
-			    unsigned scancode, unsigned keycode,
-			    bool resize)
+static unsigned int ir_update_mapping(struct input_dev *dev,
+				      struct ir_scancode_table *rc_tab,
+				      unsigned int index,
+				      unsigned int new_keycode)
+{
+	int old_keycode = rc_tab->scan[index].keycode;
+	int i;
+
+	/* Did the user wish to remove the mapping? */
+	if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
+		IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
+			   index, rc_tab->scan[index].scancode);
+		rc_tab->len--;
+		memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1],
+			(rc_tab->len - index) * sizeof(struct ir_scancode));
+	} else {
+		IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
+			   index,
+			   old_keycode == KEY_RESERVED ? "New" : "Replacing",
+			   rc_tab->scan[index].scancode, new_keycode);
+		rc_tab->scan[index].keycode = new_keycode;
+		__set_bit(new_keycode, dev->keybit);
+	}
+
+	if (old_keycode != KEY_RESERVED) {
+		/* A previous mapping was updated... */
+		__clear_bit(old_keycode, dev->keybit);
+		/* ... but another scancode might use the same keycode */
+		for (i = 0; i < rc_tab->len; i++) {
+			if (rc_tab->scan[i].keycode == old_keycode) {
+				__set_bit(old_keycode, dev->keybit);
+				break;
+			}
+		}
+
+		/* Possibly shrink the keytable, failure is not a problem */
+		ir_resize_table(rc_tab, GFP_ATOMIC);
+	}
+
+	return old_keycode;
+}
+
+/**
+ * ir_locate_scancode() - set a keycode in the scancode->keycode table
+ * @ir_dev:	the struct ir_input_dev device descriptor
+ * @rc_tab:	scancode table to be searched
+ * @scancode:	the desired scancode
+ * @resize:	controls whether we allowed to resize the table to
+ *		accomodate not yet present scancodes
+ * @return:	index of the mapping containing scancode in question
+ *		or -1U in case of failure.
+ *
+ * This routine is used to locate given scancode in ir_scancode_table.
+ * If scancode is not yet present the routine will allocate a new slot
+ * for it.
+ */
+static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev,
+					  struct ir_scancode_table *rc_tab,
+					  unsigned int scancode,
+					  bool resize)
 {
 	unsigned int i;
-	int old_keycode = KEY_RESERVED;
-	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
 
 	/*
 	 * Unfortunately, some hardware-based IR decoders don't provide
@@ -100,65 +194,34 @@
 	 * the provided IR with another one, it is needed to allow loading
 	 * IR tables from other remotes. So,
 	 */
-	if (ir_dev->props && ir_dev->props->scanmask) {
+	if (ir_dev->props && ir_dev->props->scanmask)
 		scancode &= ir_dev->props->scanmask;
-	}
 
 	/* First check if we already have a mapping for this ir command */
 	for (i = 0; i < rc_tab->len; i++) {
+		if (rc_tab->scan[i].scancode == scancode)
+			return i;
+
 		/* Keytable is sorted from lowest to highest scancode */
-		if (rc_tab->scan[i].scancode > scancode)
+		if (rc_tab->scan[i].scancode >= scancode)
 			break;
-		else if (rc_tab->scan[i].scancode < scancode)
-			continue;
-
-		old_keycode = rc_tab->scan[i].keycode;
-		rc_tab->scan[i].keycode = keycode;
-
-		/* Did the user wish to remove the mapping? */
-		if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN) {
-			IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
-				   i, scancode);
-			rc_tab->len--;
-			memmove(&rc_tab->scan[i], &rc_tab->scan[i + 1],
-				(rc_tab->len - i) * sizeof(struct ir_scancode));
-		}
-
-		/* Possibly shrink the keytable, failure is not a problem */
-		ir_resize_table(rc_tab);
-		break;
 	}
 
-	if (old_keycode == KEY_RESERVED && keycode != KEY_RESERVED) {
-		/* No previous mapping found, we might need to grow the table */
-		if (resize && ir_resize_table(rc_tab))
-			return -ENOMEM;
+	/* No previous mapping found, we might need to grow the table */
+	if (rc_tab->size == rc_tab->len) {
+		if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC))
+			return -1U;
+	}
 
-		IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n",
-			   i, scancode, keycode);
-
-		/* i is the proper index to insert our new keycode */
+	/* i is the proper index to insert our new keycode */
+	if (i < rc_tab->len)
 		memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i],
 			(rc_tab->len - i) * sizeof(struct ir_scancode));
-		rc_tab->scan[i].scancode = scancode;
-		rc_tab->scan[i].keycode = keycode;
-		rc_tab->len++;
-		set_bit(keycode, dev->keybit);
-	} else {
-		IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
-			   i, scancode, keycode);
-		/* A previous mapping was updated... */
-		clear_bit(old_keycode, dev->keybit);
-		/* ...but another scancode might use the same keycode */
-		for (i = 0; i < rc_tab->len; i++) {
-			if (rc_tab->scan[i].keycode == old_keycode) {
-				set_bit(old_keycode, dev->keybit);
-				break;
-			}
-		}
-	}
+	rc_tab->scan[i].scancode = scancode;
+	rc_tab->scan[i].keycode = KEY_RESERVED;
+	rc_tab->len++;
 
-	return 0;
+	return i;
 }
 
 /**
@@ -171,17 +234,41 @@
  * This routine is used to handle evdev EVIOCSKEY ioctl.
  */
 static int ir_setkeycode(struct input_dev *dev,
-			 unsigned int scancode, unsigned int keycode)
+			 const struct input_keymap_entry *ke,
+			 unsigned int *old_keycode)
 {
-	int rc;
-	unsigned long flags;
 	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
 	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+	unsigned int index;
+	unsigned int scancode;
+	int retval;
+	unsigned long flags;
 
 	spin_lock_irqsave(&rc_tab->lock, flags);
-	rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode, true);
+
+	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+		index = ke->index;
+		if (index >= rc_tab->len) {
+			retval = -EINVAL;
+			goto out;
+		}
+	} else {
+		retval = input_scancode_to_scalar(ke, &scancode);
+		if (retval)
+			goto out;
+
+		index = ir_establish_scancode(ir_dev, rc_tab, scancode, true);
+		if (index >= rc_tab->len) {
+			retval = -ENOMEM;
+			goto out;
+		}
+	}
+
+	*old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode);
+
+out:
 	spin_unlock_irqrestore(&rc_tab->lock, flags);
-	return rc;
+	return retval;
 }
 
 /**
@@ -189,32 +276,73 @@
  * @dev:	the struct input_dev device descriptor
  * @to:		the struct ir_scancode_table to copy entries to
  * @from:	the struct ir_scancode_table to copy entries from
- * @return:	-EINVAL if all keycodes could not be inserted, otherwise zero.
+ * @return:	-ENOMEM if all keycodes could not be inserted, otherwise zero.
  *
  * This routine is used to handle table initialization.
  */
-static int ir_setkeytable(struct input_dev *dev,
-			  struct ir_scancode_table *to,
+static int ir_setkeytable(struct ir_input_dev *ir_dev,
 			  const struct ir_scancode_table *from)
 {
-	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
 	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
-	unsigned long flags;
-	unsigned int i;
-	int rc = 0;
+	unsigned int i, index;
+	int rc;
 
-	spin_lock_irqsave(&rc_tab->lock, flags);
+	rc = ir_create_table(&ir_dev->rc_tab,
+			     from->name, from->ir_type, from->size);
+	if (rc)
+		return rc;
+
+	IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+		   rc_tab->size, rc_tab->alloc);
+
 	for (i = 0; i < from->size; i++) {
-		rc = ir_do_setkeycode(dev, to, from->scan[i].scancode,
-				      from->scan[i].keycode, false);
-		if (rc)
+		index = ir_establish_scancode(ir_dev, rc_tab,
+					      from->scan[i].scancode, false);
+		if (index >= rc_tab->len) {
+			rc = -ENOMEM;
 			break;
+		}
+
+		ir_update_mapping(ir_dev->input_dev, rc_tab, index,
+				  from->scan[i].keycode);
 	}
-	spin_unlock_irqrestore(&rc_tab->lock, flags);
+
+	if (rc)
+		ir_free_table(rc_tab);
+
 	return rc;
 }
 
 /**
+ * ir_lookup_by_scancode() - locate mapping by scancode
+ * @rc_tab:	the &struct ir_scancode_table to search
+ * @scancode:	scancode to look for in the table
+ * @return:	index in the table, -1U if not found
+ *
+ * This routine performs binary search in RC keykeymap table for
+ * given scancode.
+ */
+static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab,
+					  unsigned int scancode)
+{
+	unsigned int start = 0;
+	unsigned int end = rc_tab->len - 1;
+	unsigned int mid;
+
+	while (start <= end) {
+		mid = (start + end) / 2;
+		if (rc_tab->scan[mid].scancode < scancode)
+			start = mid + 1;
+		else if (rc_tab->scan[mid].scancode > scancode)
+			end = mid - 1;
+		else
+			return mid;
+	}
+
+	return -1U;
+}
+
+/**
  * ir_getkeycode() - get a keycode from the scancode->keycode table
  * @dev:	the struct input_dev device descriptor
  * @scancode:	the desired scancode
@@ -224,36 +352,46 @@
  * This routine is used to handle evdev EVIOCGKEY ioctl.
  */
 static int ir_getkeycode(struct input_dev *dev,
-			 unsigned int scancode, unsigned int *keycode)
+			 struct input_keymap_entry *ke)
 {
-	int start, end, mid;
-	unsigned long flags;
-	int key = KEY_RESERVED;
 	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
 	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+	struct ir_scancode *entry;
+	unsigned long flags;
+	unsigned int index;
+	unsigned int scancode;
+	int retval;
 
 	spin_lock_irqsave(&rc_tab->lock, flags);
-	start = 0;
-	end = rc_tab->len - 1;
-	while (start <= end) {
-		mid = (start + end) / 2;
-		if (rc_tab->scan[mid].scancode < scancode)
-			start = mid + 1;
-		else if (rc_tab->scan[mid].scancode > scancode)
-			end = mid - 1;
-		else {
-			key = rc_tab->scan[mid].keycode;
-			break;
-		}
+
+	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+		index = ke->index;
+	} else {
+		retval = input_scancode_to_scalar(ke, &scancode);
+		if (retval)
+			goto out;
+
+		index = ir_lookup_by_scancode(rc_tab, scancode);
 	}
+
+	if (index >= rc_tab->len) {
+		if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
+			IR_dprintk(1, "unknown key for scancode 0x%04x\n",
+				   scancode);
+		retval = -EINVAL;
+		goto out;
+	}
+
+	entry = &rc_tab->scan[index];
+
+	ke->index = index;
+	ke->keycode = entry->keycode;
+	ke->len = sizeof(entry->scancode);
+	memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
+
+out:
 	spin_unlock_irqrestore(&rc_tab->lock, flags);
-
-	if (key == KEY_RESERVED)
-		IR_dprintk(1, "unknown key for scancode 0x%04x\n",
-			   scancode);
-
-	*keycode = key;
-	return 0;
+	return retval;
 }
 
 /**
@@ -268,12 +406,24 @@
  */
 u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
 {
-	int keycode;
+	struct ir_input_dev *ir_dev = input_get_drvdata(dev);
+	struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+	unsigned int keycode;
+	unsigned int index;
+	unsigned long flags;
 
-	ir_getkeycode(dev, scancode, &keycode);
+	spin_lock_irqsave(&rc_tab->lock, flags);
+
+	index = ir_lookup_by_scancode(rc_tab, scancode);
+	keycode = index < rc_tab->len ?
+			rc_tab->scan[index].keycode : KEY_RESERVED;
+
+	spin_unlock_irqrestore(&rc_tab->lock, flags);
+
 	if (keycode != KEY_RESERVED)
 		IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
 			   dev->name, scancode, keycode);
+
 	return keycode;
 }
 EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
@@ -453,8 +603,8 @@
 		goto out_dev;
 	}
 
-	input_dev->getkeycode = ir_getkeycode;
-	input_dev->setkeycode = ir_setkeycode;
+	input_dev->getkeycode_new = ir_getkeycode;
+	input_dev->setkeycode_new = ir_setkeycode;
 	input_set_drvdata(input_dev, ir_dev);
 	ir_dev->input_dev = input_dev;
 
@@ -462,12 +612,6 @@
 	spin_lock_init(&ir_dev->keylock);
 	setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev);
 
-	ir_dev->rc_tab.name = rc_tab->name;
-	ir_dev->rc_tab.ir_type = rc_tab->ir_type;
-	ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size *
-						  sizeof(struct ir_scancode));
-	ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL);
-	ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode);
 	if (props) {
 		ir_dev->props = props;
 		if (props->open)
@@ -476,23 +620,14 @@
 			input_dev->close = ir_close;
 	}
 
-	if (!ir_dev->rc_tab.scan) {
-		rc = -ENOMEM;
-		goto out_name;
-	}
-
-	IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
-		   ir_dev->rc_tab.size, ir_dev->rc_tab.alloc);
-
 	set_bit(EV_KEY, input_dev->evbit);
 	set_bit(EV_REP, input_dev->evbit);
 	set_bit(EV_MSC, input_dev->evbit);
 	set_bit(MSC_SCAN, input_dev->mscbit);
 
-	if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) {
-		rc = -ENOMEM;
-		goto out_table;
-	}
+	rc = ir_setkeytable(ir_dev, rc_tab);
+	if (rc)
+		goto out_name;
 
 	rc = ir_register_class(input_dev);
 	if (rc < 0)
@@ -522,7 +657,7 @@
 out_event:
 	ir_unregister_class(input_dev);
 out_table:
-	kfree(ir_dev->rc_tab.scan);
+	ir_free_table(&ir_dev->rc_tab);
 out_name:
 	kfree(ir_dev->driver_name);
 out_dev:
@@ -540,7 +675,6 @@
 void ir_input_unregister(struct input_dev *input_dev)
 {
 	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-	struct ir_scancode_table *rc_tab;
 
 	if (!ir_dev)
 		return;
@@ -552,10 +686,7 @@
 		if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
 			ir_raw_event_unregister(input_dev);
 
-	rc_tab = &ir_dev->rc_tab;
-	rc_tab->size = 0;
-	kfree(rc_tab->scan);
-	rc_tab->scan = NULL;
+	ir_free_table(&ir_dev->rc_tab);
 
 	ir_unregister_class(input_dev);
 
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index defa786..b8c4b80 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -338,6 +338,21 @@
 	},
 };
 
+static struct resource ab8500_poweronkey_db_resources[] = {
+	{
+		.name	= "ONKEY_DBF",
+		.start	= AB8500_INT_PON_KEY1DB_F,
+		.end	= AB8500_INT_PON_KEY1DB_F,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "ONKEY_DBR",
+		.start	= AB8500_INT_PON_KEY1DB_R,
+		.end	= AB8500_INT_PON_KEY1DB_R,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
 static struct mfd_cell ab8500_devs[] = {
 	{
 		.name = "ab8500-gpadc",
@@ -354,6 +369,11 @@
 	{ .name = "ab8500-usb", },
 	{ .name = "ab8500-pwm", },
 	{ .name = "ab8500-regulator", },
+	{
+		.name = "ab8500-poweron-key",
+		.num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
+		.resources = ab8500_poweronkey_db_resources,
+	},
 };
 
 int __devinit ab8500_init(struct ab8500 *ab8500)
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 335311a..8e03e76 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -139,8 +139,6 @@
 
 source "drivers/staging/xgifb/Kconfig"
 
-source "drivers/staging/mrst-touchscreen/Kconfig"
-
 source "drivers/staging/msm/Kconfig"
 
 source "drivers/staging/lirc/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index e3f1e1b..0e7d755 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -51,7 +51,6 @@
 obj-$(CONFIG_TI_ST)		+= ti-st/
 obj-$(CONFIG_ADIS16255)		+= adis16255/
 obj-$(CONFIG_FB_XGI)		+= xgifb/
-obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH)	+= mrst-touchscreen/
 obj-$(CONFIG_MSM_STAGING)	+= msm/
 obj-$(CONFIG_EASYCAP)		+= easycap/
 obj-$(CONFIG_SOLO6X10)		+= solo6x10/
diff --git a/drivers/staging/mrst-touchscreen/Kconfig b/drivers/staging/mrst-touchscreen/Kconfig
deleted file mode 100644
index c2af492..0000000
--- a/drivers/staging/mrst-touchscreen/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config TOUCHSCREEN_INTEL_MID
-	tristate "Intel MID platform resistive touchscreen"
-	depends on INTEL_SCU_IPC
-	default y
-	help
-	  Say Y here if you have a Intel MID based touchscreen
-	  If unsure, say N.
diff --git a/drivers/staging/mrst-touchscreen/Makefile b/drivers/staging/mrst-touchscreen/Makefile
deleted file mode 100644
index 2d638b0..0000000
--- a/drivers/staging/mrst-touchscreen/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o
-
-
diff --git a/drivers/staging/mrst-touchscreen/TODO b/drivers/staging/mrst-touchscreen/TODO
deleted file mode 100644
index 7157028..0000000
--- a/drivers/staging/mrst-touchscreen/TODO
+++ /dev/null
@@ -1,2 +0,0 @@
-- Move the driver to not think it is SPI (requires fixing some of the SFI
-  and firmware side)
diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
deleted file mode 100644
index abba22f..0000000
--- a/drivers/staging/mrst-touchscreen/intel-mid-touch.c
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * intel_mid_touch.c - Intel MID Resistive Touch Screen Driver
- *
- * Copyright (C) 2008 Intel Corp
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * 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; version 2 of the License.
- *
- * 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; ifnot, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
- * 			    Ramesh Agarwal (ramesh.agarwal@intel.com)
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * TODO:
- *	kill off mrstouch_debug eventually
- *	review conversion of r/m/w sequences
- *	Replace interrupt mutex abuse
- *	Kill of mrstouchdevp pointer
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/param.h>
-#include <linux/spi/spi.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <asm/intel_scu_ipc.h>
-
-
-#if defined(MRSTOUCH_DEBUG)
-#define mrstouch_debug(fmt, args...)\
-	do { \
-		printk(KERN_DEBUG "\n[MRSTOUCH(%d)] - ", __LINE__); \
-		printk(KERN_DEBUG fmt, ##args); \
-	} while (0);
-#else
-#define mrstouch_debug(fmt, args...)
-#endif
-
-/* PMIC Interrupt registers */
-#define PMIC_REG_ID1   0x00 /*PMIC ID1 register */
-
-/* PMIC Interrupt registers */
-#define PMIC_REG_INT   0x04 /*PMIC interrupt register */
-#define PMIC_REG_MINT  0x05 /*PMIC interrupt mask register */
-
-/* ADC Interrupt registers */
-#define PMIC_REG_ADCINT   0x5F /*ADC interrupt register */
-#define PMIC_REG_MADCINT  0x60 /*ADC interrupt mask register */
-
-/* ADC Control registers */
-#define PMIC_REG_ADCCNTL1    0x61 /*ADC control register */
-
-/* ADC Channel Selection registers */
-#define PMICADDR0     0xA4
-#define END_OF_CHANNEL 0x1F
-
-/* ADC Result register */
-#define PMIC_REG_ADCSNS0H   0x64
-
-/* ADC channels for touch screen */
-#define MRST_TS_CHAN10   0xA /* Touch screen X+ connection */
-#define MRST_TS_CHAN11   0xB /* Touch screen X- connection */
-#define MRST_TS_CHAN12   0xC /* Touch screen Y+ connection */
-#define MRST_TS_CHAN13   0xD /* Touch screen Y- connection */
-
-/* Touch screen coordinate constants */
-#define TOUCH_PRESSURE   	50
-#define TOUCH_PRESSURE_FS	100
-
-#define XMOVE_LIMIT	5
-#define YMOVE_LIMIT	5
-#define XYMOVE_CNT	3
-
-#define MAX_10BIT	((1<<10)-1)
-
-/* Touch screen channel BIAS constants */
-#define XBIAS		0x20
-#define YBIAS		0x40
-#define ZBIAS		0x80
-
-/* Touch screen coordinates */
-#define MIN_X		10
-#define MAX_X		1024
-#define MIN_Y		10
-#define MAX_Y		1024
-#define WAIT_ADC_COMPLETION 10
-
-/* PMIC ADC round robin delays */
-#define ADC_LOOP_DELAY0 0x0 /* Continuous loop */
-#define ADC_LOOP_DELAY1 0x1 /* 4.5  ms approximate */
-
-/* PMIC Vendor Identifiers */
-#define PMIC_VENDOR_FS  0 /* PMIC vendor FreeScale */
-#define PMIC_VENDOR_MAXIM 1 /* PMIC vendor MAXIM */
-#define PMIC_VENDOR_NEC 2 /* PMIC vendor NEC */
-#define MRSTOUCH_MAX_CHANNELS 32 /* Maximum ADC channels */
-
-/* Touch screen device structure */
-struct mrstouch_dev {
-	struct spi_device *spi; /* SPI device associated with touch screen */
-	struct input_dev *input; /* input device for touchscreen*/
-	char 		phys[32]; /* Device name */
-	struct task_struct *pendet_thrd; /* PENDET interrupt handler */
-	struct mutex lock; /* Sync between interrupt and PENDET handler */
-	bool            busy; /* Busy flag */
-	u16             asr; /* Address selection register */
-	int             irq;    /* Touch screen IRQ # */
-	uint		vendor;  /* PMIC vendor */
-	uint		rev;  /* PMIC revision */
-	bool		suspended; /* Device suspended status */
-	bool		disabled;  /* Device disabled status */
-	u16		x;  /* X coordinate */
-	u16		y;  /* Y coordinate */
-	bool		pendown;  /* PEN position */
-} ;
-
-
-/* Global Pointer to Touch screen device */
-static struct mrstouch_dev *mrstouchdevp;
-
-/* Utility to read PMIC ID */
-static int mrstouch_pmic_id(uint *vendor, uint *rev)
-{
-	int err;
-	u8 r;
-
-	err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
-	if (err)
-		return err;
-
-	*vendor = r & 0x7;
-	*rev = (r >> 3) & 0x7;
-
-	return 0;
-}
-
-/*
- * Parse ADC channels to find end of the channel configured by other ADC user
- * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
- */
-static int mrstouch_chan_parse(struct mrstouch_dev *tsdev)
-{
-	int err, i, j, found;
-	u32 r32;
-
-	found = -1;
-
-	for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
-		if (found >= 0)
-			break;
-
-		err = intel_scu_ipc_ioread32(PMICADDR0, &r32);
-		if (err)
-			return err;
-
-		for (j = 0; j < 32; j+= 8) {
-			if (((r32 >> j) & 0xFF) == END_OF_CHANNEL) {
-				found = i;
-				break;
-			}
-		}
-	}
-	if (found < 0)
-		return 0;
-
-	if (tsdev->vendor == PMIC_VENDOR_FS) {
-		if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
-			return -ENOSPC;
-	} else {
-		if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
-			return -ENOSPC;
-	}
-	return found;
-}
-
-/* Utility to enable/disable pendet.
- * pendet set to true enables PENDET interrupt
- * pendet set to false disables PENDET interrupt
- * Also clears RND mask bit
-*/
-static int pendet_enable(struct mrstouch_dev *tsdev, bool pendet)
-{
-	u16 reg;
-	u8 r;
-	u8 pendet_enabled = 0;
-	int retry = 0;
-	int err;
-
-	err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, &reg);
-	if (err)
-		return err;
-
-	if (pendet) {
-		reg &= ~0x0005;
-		reg |= 0x2000; /* Enable pendet */
-	} else
-		reg &= 0xDFFF; /* Disable pendet */
-
-	/* Set MADCINT and update ADCCNTL1 (next reg byte) */
-	err = intel_scu_ipc_iowrite16(PMIC_REG_MADCINT, reg);
-	if (!pendet || err)
-		return err;
-
-	/*
-	 * Sometimes even after the register write succeeds
-	 * the PMIC register value is not updated. Retry few iterations
-	 * to enable pendet.
-	 */
-
-	err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
-	pendet_enabled = (r >> 5) & 0x01;
-
-	retry = 0;
-	while (!err && !pendet_enabled) {
-		retry++;
-		msleep(10);
-		err = intel_scu_ipc_iowrite8(PMIC_REG_ADCCNTL1, reg >> 8);
-		if (err)
-			break;
-		err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
-		if (err == 0)
-			pendet_enabled = (r >> 5) & 0x01;
-		if (retry >= 10) {
-			dev_err(&tsdev->spi->dev, "Touch screen disabled.\n");
-			return -EIO;
-		}
-	}
-	return 0;
-}
-
-/* To read PMIC ADC touch screen result
- * Reads ADC storage registers for higher 7 and lower 3 bits
- * converts the two readings to single value and turns off gain bit
- */
-static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
-{
-	int err;
-	u16 result;
-	u32 res;
-
-	result = PMIC_REG_ADCSNS0H + offset;
-
-	if (chan == MRST_TS_CHAN12)
-		result += 4;
-
-	err = intel_scu_ipc_ioread32(result, &res);
-	if (err)
-		return err;
-
-	/* Mash the bits up */
-
-	*vp = (res & 0xFF) << 3;	/* Highest 7 bits */
-	*vp |= (res >> 8) & 0x07;	/* Lower 3 bits */
-	*vp &= 0x3FF;
-
-	res >>= 16;
-
-	*vm = (res & 0xFF) << 3;	/* Highest 7 bits */
-	*vm |= (res >> 8) & 0x07;	/* Lower 3 bits */
-	*vm &= 0x3FF;
-
-	return 0;
-}
-
-/* To configure touch screen channels
- * Writes touch screen channels to ADC address selection registers
- */
-static int mrstouch_ts_chan_set(uint offset)
-{
-	int count;
-	u16 chan;
-	u16 reg[5];
-	u8 data[5];
-
-	chan = PMICADDR0 + offset;
-	for (count = 0; count <= 3; count++) {
-		reg[count] = chan++;
-		data[count] = MRST_TS_CHAN10 + count;
-	}
-	reg[count] = chan;
-	data[count] = END_OF_CHANNEL;
-
-	return intel_scu_ipc_writev(reg, data, 5);
-}
-
-/* Initialize ADC */
-static int mrstouch_adc_init(struct mrstouch_dev *tsdev)
-{
-	int err, start;
-	u8 ra, rm;
-
-	err = mrstouch_pmic_id(&tsdev->vendor, &tsdev->rev);
-	if (err) {
-		dev_err(&tsdev->spi->dev, "Unable to read PMIC id\n");
-		return err;
-	}
-
-	start = mrstouch_chan_parse(tsdev);
-	if (start < 0) {
-		dev_err(&tsdev->spi->dev, "Unable to parse channels\n");
-		return start;
-	}
-
-	tsdev->asr = start;
-
-	mrstouch_debug("Channel offset(%d): 0x%X\n", tsdev->asr, tsdev->vendor);
-
-	/* ADC power on, start, enable PENDET and set loop delay
-	 * ADC loop delay is set to 4.5 ms approximately
-	 * Loop delay more than this results in jitter in adc readings
-	 * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
-	 * interrupt generation sometimes.
-	 */
-
-	if (tsdev->vendor == PMIC_VENDOR_FS) {
-		ra = 0xE0 | ADC_LOOP_DELAY0;
-		rm = 0x5;
-	} else {
-		/* NEC and MAXIm not consistent with loop delay 0 */
-		ra = 0xE0 | ADC_LOOP_DELAY1;
-		rm = 0x0;
-
-		/* configure touch screen channels */
-		err = mrstouch_ts_chan_set(tsdev->asr);
-		if (err)
-			return err;
-	}
-	err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
-	if (err == 0)
-		err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
-	return err;
-}
-
-/* Reports x,y coordinates to event subsystem */
-static void mrstouch_report_xy(struct mrstouch_dev *tsdev, u16 x, u16 y, u16 z)
-{
-	int xdiff, ydiff;
-
-	if (tsdev->pendown && z <= TOUCH_PRESSURE) {
-		/* Pen removed, report button release */
-		mrstouch_debug("BTN REL(%d)", z);
-		input_report_key(tsdev->input, BTN_TOUCH, 0);
-		tsdev->pendown = false;
-	}
-
-	xdiff = abs(x - tsdev->x);
-	ydiff = abs(y - tsdev->y);
-
-	/*
-	if x and y values changes for XYMOVE_CNT readings it is considered
-	as stylus is moving. This is required to differentiate between stylus
-	movement and jitter
-	*/
-	if (x < MIN_X || x > MAX_X || y < MIN_Y || y > MAX_Y) {
-		/* Spurious values, release button if touched and return */
-		if (tsdev->pendown) {
-			mrstouch_debug("BTN REL(%d)", z);
-			input_report_key(tsdev->input, BTN_TOUCH, 0);
-			tsdev->pendown = false;
-		}
-		return;
-	} else if (xdiff >= XMOVE_LIMIT || ydiff >= YMOVE_LIMIT) {
-		tsdev->x = x;
-		tsdev->y = y;
-
-		input_report_abs(tsdev->input, ABS_X, x);
-		input_report_abs(tsdev->input, ABS_Y, y);
-		input_sync(tsdev->input);
-	}
-
-
-	if (!tsdev->pendown && z > TOUCH_PRESSURE) {
-		/* Pen touched, report button touch */
-		mrstouch_debug("BTN TCH(%d, %d, %d)", x, y, z);
-		input_report_key(tsdev->input, BTN_TOUCH, 1);
-		tsdev->pendown = true;
-	}
-}
-
-
-/* Utility to start ADC, used by freescale handler */
-static int pendet_mask(void)
-{
-	return 	intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
-}
-
-/* Utility to stop ADC, used by freescale handler */
-static int pendet_umask(void)
-{
-	return 	intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
-}
-
-/* Utility to read ADC, used by freescale handler */
-static int mrstouch_pmic_fs_adc_read(struct mrstouch_dev *tsdev)
-{
-	int err;
-	u16 x, y, z, result;
-	u16 reg[4];
-	u8 data[4];
-
-	result = PMIC_REG_ADCSNS0H + tsdev->asr;
-
-	reg[0] = result + 4;
-	reg[1] = result + 5;
-	reg[2] = result + 16;
-	reg[3] = result + 17;
-
-	err = intel_scu_ipc_readv(reg, data, 4);
-	if (err)
-		goto ipc_error;
-
-	x = data[0] << 3; /* Higher 7 bits */
-	x |= data[1] & 0x7; /* Lower 3 bits */
-	x &= 0x3FF;
-
-	y = data[2] << 3; /* Higher 7 bits */
-	y |= data[3] & 0x7; /* Lower 3 bits */
-	y &= 0x3FF;
-
-	/* Read Z value */
-	reg[0] = result + 28;
-	reg[1] = result + 29;
-
-	err = intel_scu_ipc_readv(reg, data, 4);
-	if (err)
-		goto ipc_error;
-
-	z = data[0] << 3; /* Higher 7 bits */
-	z |= data[1] & 0x7; /* Lower 3 bits */
-	z &= 0x3FF;
-
-#if defined(MRSTOUCH_PRINT_XYZP)
-	mrstouch_debug("X: %d, Y: %d, Z: %d", x, y, z);
-#endif
-
-	if (z >= TOUCH_PRESSURE_FS) {
-		mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE - 1); /* Pen Removed */
-		return TOUCH_PRESSURE - 1;
-	} else {
-		mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE + 1); /* Pen Touched */
-		return TOUCH_PRESSURE + 1;
-	}
-
-	return 0;
-
-ipc_error:
-	dev_err(&tsdev->spi->dev, "ipc error during fs_adc read\n");
-	return err;
-}
-
-/* To handle free scale pmic pendet interrupt */
-static int pmic0_pendet(void *dev_id)
-{
-	int err, count;
-	u16 chan;
-	unsigned int touched;
-	struct mrstouch_dev *tsdev = (struct mrstouch_dev *)dev_id;
-	u16 reg[5];
-	u8 data[5];
-
-	chan = PMICADDR0 + tsdev->asr;
-
-	/* Set X BIAS */
-	for (count = 0; count <= 3; count++) {
-		reg[count] = chan++;
-		data[count] = 0x2A;
-	}
-	reg[count] =  chan++; /* Dummy */
-	data[count] = 0;
-
-	err = intel_scu_ipc_writev(reg, data, 5);
-	if (err)
-		goto ipc_error;
-
-	msleep(WAIT_ADC_COMPLETION);
-
-	/* Set Y BIAS */
-	for (count = 0; count <= 3; count++) {
-		reg[count] = chan++;
-		data[count] = 0x4A;
-	}
-	reg[count] = chan++; /* Dummy */
-	data[count] = 0;
-
-	err = intel_scu_ipc_writev(reg, data, 5);
-	if (err)
-		goto ipc_error;
-
-	msleep(WAIT_ADC_COMPLETION);
-
-	/* Set Z BIAS */
-	err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
-	if (err)
-		goto ipc_error;
-
-	msleep(WAIT_ADC_COMPLETION);
-
-	/*Read touch screen channels till pen removed
-	 * Freescale reports constant value of z for all points
-	 * z is high when screen is not touched and low when touched
-	 * Map high z value to not touched and low z value to pen touched
-	 */
-	touched = mrstouch_pmic_fs_adc_read(tsdev);
-	while (touched > TOUCH_PRESSURE) {
-		touched = mrstouch_pmic_fs_adc_read(tsdev);
-		msleep(WAIT_ADC_COMPLETION);
-	}
-
-	/* Clear all TS channels */
-	chan = PMICADDR0 + tsdev->asr;
-	for (count = 0; count <= 4; count++) {
-		reg[count] = chan++;
-		data[count] = 0;
-	}
-	err = intel_scu_ipc_writev(reg, data, 5);
-	if (err)
-		goto ipc_error;
-
-	for (count = 0; count <= 4; count++) {
-		reg[count] = chan++;
-		data[count] = 0;
-	}
-	err = intel_scu_ipc_writev(reg, data, 5);
-	if (err)
-		goto ipc_error;
-
-	err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
-	if (err)
-		goto ipc_error;
-
-	return 0;
-
-ipc_error:
-	dev_err(&tsdev->spi->dev, "ipc error during pendet\n");
-	return err;
-}
-
-
-/* To enable X, Y and Z bias values
- * Enables YPYM for X channels and XPXM for Y channels
- */
-static int mrstouch_ts_bias_set(uint offset, uint bias)
-{
-	int count;
-	u16 chan, start;
-	u16 reg[4];
-	u8 data[4];
-
-	chan = PMICADDR0 + offset;
-	start = MRST_TS_CHAN10;
-
-	for (count = 0; count <= 3; count++) {
-		reg[count] = chan++;
-		data[count] = bias | (start + count);
-	}
-	return intel_scu_ipc_writev(reg, data, 4);
-}
-
-/* To read touch screen channel values */
-static int mrstouch_adc_read(struct mrstouch_dev *tsdev)
-{
-	int err;
-	u16 xp, xm, yp, ym, zp, zm;
-
-	/* configure Y bias for X channels */
-	err = mrstouch_ts_bias_set(tsdev->asr, YBIAS);
-	if (err)
-		goto ipc_error;
-
-	msleep(WAIT_ADC_COMPLETION);
-
-	/* read x+ and x- channels */
-	err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &xp, &xm);
-	if (err)
-		goto ipc_error;
-
-	/* configure x bias for y channels */
-	err = mrstouch_ts_bias_set(tsdev->asr, XBIAS);
-	if (err)
-		goto ipc_error;
-
-	msleep(WAIT_ADC_COMPLETION);
-
-	/* read y+ and y- channels */
-	err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, &yp, &ym);
-	if (err)
-		goto ipc_error;
-
-	/* configure z bias for x and y channels */
-	err = mrstouch_ts_bias_set(tsdev->asr, ZBIAS);
-	if (err)
-		goto ipc_error;
-
-	msleep(WAIT_ADC_COMPLETION);
-
-	/* read z+ and z- channels */
-	err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &zp, &zm);
-	if (err)
-		goto ipc_error;
-
-#if defined(MRSTOUCH_PRINT_XYZP)
-	printk(KERN_INFO "X+: %d, Y+: %d, Z+: %d\n", xp, yp, zp);
-#endif
-
-#if defined(MRSTOUCH_PRINT_XYZM)
-	printk(KERN_INFO "X-: %d, Y-: %d, Z-: %d\n", xm, ym, zm);
-#endif
-
-	mrstouch_report_xy(tsdev, xp, yp, zp); /* report x and y to eventX */
-
-	return zp;
-
-ipc_error:
-	dev_err(&tsdev->spi->dev, "ipc error during adc read\n");
-	return err;
-}
-
-/* PENDET interrupt handler function for NEC and MAXIM */
-static void pmic12_pendet(void *data)
-{
-	unsigned int touched;
-	struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
-
-	/* read touch screen channels till pen removed */
-	do {
-		touched = mrstouch_adc_read(tsdev);
-	} while (touched > TOUCH_PRESSURE);
-}
-
-/* Handler to process PENDET interrupt */
-int mrstouch_pendet(void *data)
-{
-	struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
-	while (1) {
-		/* Wait for PENDET interrupt */
-		if (mutex_lock_interruptible(&tsdev->lock)) {
-			msleep(WAIT_ADC_COMPLETION);
-			continue;
-		}
-
-		if (tsdev->busy)
-			return 0;
-
-		tsdev->busy = true;
-
-		if (tsdev->vendor == PMIC_VENDOR_NEC ||
-			tsdev->vendor == PMIC_VENDOR_MAXIM) {
-			/* PENDET must be disabled in NEC before reading ADC */
-			pendet_enable(tsdev,false); /* Disbale PENDET */
-			pmic12_pendet(tsdev);
-			pendet_enable(tsdev, true); /*Enable PENDET */
-		} else if (tsdev->vendor == PMIC_VENDOR_FS) {
-			pendet_umask(); /* Stop ADC */
-			pmic0_pendet(tsdev);
-			pendet_mask(); /* Stop ADC */
-		} else
-		dev_err(&tsdev->spi->dev, "Unsupported touchscreen: %d\n",
-				tsdev->vendor);
-
-		tsdev->busy = false;
-
-	}
-	return 0;
-}
-
-/* PENDET interrupt handler */
-static irqreturn_t pendet_intr_handler(int irq, void *handle)
-{
-	struct mrstouch_dev *tsdev = (struct mrstouch_dev *)handle;
-
-	mutex_unlock(&tsdev->lock);
-	return IRQ_HANDLED;
-}
-
-/* Intializes input device and registers with input subsystem */
-static int ts_input_dev_init(struct mrstouch_dev *tsdev, struct spi_device *spi)
-{
-	int err = 0;
-
-	mrstouch_debug("%s", __func__);
-
-	tsdev->input = input_allocate_device();
-	if (!tsdev->input) {
-		dev_err(&tsdev->spi->dev, "Unable to allocate input device.\n");
-		return -EINVAL;
-	}
-
-	tsdev->input->name = "mrst_touchscreen";
-	snprintf(tsdev->phys, sizeof(tsdev->phys),
-			"%s/input0", dev_name(&spi->dev));
-	tsdev->input->phys = tsdev->phys;
-	tsdev->input->dev.parent = &spi->dev;
-
-	tsdev->input->id.vendor = tsdev->vendor;
-	tsdev->input->id.version = tsdev->rev;
-
-	tsdev->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-	tsdev->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-
-	input_set_abs_params(tsdev->input, ABS_X, MIN_X, MIN_Y, 0, 0);
-	input_set_abs_params(tsdev->input, ABS_Y, MIN_X, MIN_Y, 0, 0);
-
-	err = input_register_device(tsdev->input);
-	if (err) {
-		dev_err(&tsdev->spi->dev, "unable to register input device\n");
-		input_free_device(tsdev->input);
-		return err;
-	}
-
-	mrstouch_debug("%s", "mrstouch initialized");
-
-	return 0;
-
-}
-
-/* Probe function for touch screen driver */
-static int __devinit mrstouch_probe(struct spi_device *mrstouch_spi)
-{
-	int err;
-	unsigned int myirq;
-	struct mrstouch_dev *tsdev;
-
-	mrstouch_debug("%s(%p)", __func__, mrstouch_spi);
-
-	mrstouchdevp = NULL;
-	myirq = mrstouch_spi->irq;
-
-	if (!mrstouch_spi->irq) {
-		dev_err(&mrstouch_spi->dev, "no interrupt assigned\n");
-		return -EINVAL;
-	}
-
-	tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
-	if (!tsdev) {
-		dev_err(&mrstouch_spi->dev, "unable to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	tsdev->irq = myirq;
-	mrstouchdevp = tsdev;
-
-	err = mrstouch_adc_init(tsdev);
-	if (err) {
-		dev_err(&mrstouch_spi->dev, "ADC init failed\n");
-		goto mrstouch_err_free_mem;
-	}
-
-	dev_set_drvdata(&mrstouch_spi->dev, tsdev);
-	tsdev->spi = mrstouch_spi;
-
-	err = ts_input_dev_init(tsdev, mrstouch_spi);
-	if (err) {
-		dev_err(&tsdev->spi->dev, "ts_input_dev_init failed");
-		goto mrstouch_err_free_mem;
-	}
-
-	mutex_init(&tsdev->lock);
-	mutex_lock(&tsdev->lock)
-
-	mrstouch_debug("Requesting IRQ-%d", myirq);
-	err = request_irq(myirq, pendet_intr_handler,
-				0, "mrstouch", tsdev);
-	if (err) {
-		dev_err(&tsdev->spi->dev, "unable to allocate irq\n");
-		goto mrstouch_err_free_mem;
-	}
-
-	tsdev->pendet_thrd = kthread_run(mrstouch_pendet,
-				(void *)tsdev, "pendet handler");
-	if (IS_ERR(tsdev->pendet_thrd)) {
-		dev_err(&tsdev->spi->dev, "kthread_run failed\n");
-		err = PTR_ERR(tsdev->pendet_thrd);
-		goto mrstouch_err_free_mem;
-	}
-	mrstouch_debug("%s", "Driver initialized");
-	return 0;
-
-mrstouch_err_free_mem:
-	kfree(tsdev);
-	return err;
-}
-
-static int mrstouch_suspend(struct spi_device *spi, pm_message_t msg)
-{
-	mrstouch_debug("%s", __func__);
-	mrstouchdevp->suspended = 1;
-	return 0;
-}
-
-static int mrstouch_resume(struct spi_device *spi)
-{
-	mrstouch_debug("%s", __func__);
-	mrstouchdevp->suspended = 0;
-	return 0;
-}
-
-static int mrstouch_remove(struct spi_device *spi)
-{
-	mrstouch_debug("%s", __func__);
-	free_irq(mrstouchdevp->irq, mrstouchdevp);
-	input_unregister_device(mrstouchdevp->input);
-	input_free_device(mrstouchdevp->input);
-	if (mrstouchdevp->pendet_thrd)
-		kthread_stop(mrstouchdevp->pendet_thrd);
-	kfree(mrstouchdevp);
-	return 0;
-}
-
-static struct spi_driver mrstouch_driver = {
-	.driver = {
-		.name   = "pmic_touch",
-		.bus    = &spi_bus_type,
-		.owner  = THIS_MODULE,
-	},
-	.probe          = mrstouch_probe,
-	.suspend        = mrstouch_suspend,
-	.resume         = mrstouch_resume,
-	.remove         = mrstouch_remove,
-};
-
-static int __init mrstouch_module_init(void)
-{
-	int err;
-
-	mrstouch_debug("%s", __func__);
-	err = spi_register_driver(&mrstouch_driver);
-	if (err) {
-		mrstouch_debug("%s(%d)", "SPI PENDET failed", err);
-		return -1;
-	}
-
-	return 0;
-}
-
-static void __exit mrstouch_module_exit(void)
-{
-	mrstouch_debug("%s", __func__);
-	spi_unregister_driver(&mrstouch_driver);
-	return;
-}
-
-module_init(mrstouch_module_init);
-module_exit(mrstouch_module_exit);
-
-MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
-MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
-MODULE_LICENSE("GPL");
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 361d1cc..b65a6f4 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -53,9 +53,7 @@
 #define to_gameport_port(d)	container_of(d, struct gameport, dev)
 
 struct gameport_driver {
-
-	void *private;
-	char *description;
+	const char *description;
 
 	int (*connect)(struct gameport *, struct gameport_driver *drv);
 	int (*reconnect)(struct gameport *);
diff --git a/include/linux/input.h b/include/linux/input.h
index d6ae176..51af441 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -34,7 +34,7 @@
  * Protocol version.
  */
 
-#define EV_VERSION		0x010000
+#define EV_VERSION		0x010001
 
 /*
  * IOCTLs (0x00 - 0x7f)
@@ -56,25 +56,50 @@
 	__s32 resolution;
 };
 
+/**
+ * struct input_keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls
+ * @scancode: scancode represented in machine-endian form.
+ * @len: length of the scancode that resides in @scancode buffer.
+ * @index: index in the keymap, may be used instead of scancode
+ * @flags: allows to specify how kernel should handle the request. For
+ *	example, setting INPUT_KEYMAP_BY_INDEX flag indicates that kernel
+ *	should perform lookup in keymap by @index instead of @scancode
+ * @keycode: key code assigned to this scancode
+ *
+ * The structure is used to retrieve and modify keymap data. Users have
+ * option of performing lookup either by @scancode itself or by @index
+ * in keymap entry. EVIOCGKEYCODE will also return scancode or index
+ * (depending on which element was used to perform lookup).
+ */
+struct input_keymap_entry {
+#define INPUT_KEYMAP_BY_INDEX	(1 << 0)
+	__u8  flags;
+	__u8  len;
+	__u16 index;
+	__u32 keycode;
+	__u8  scancode[32];
+};
+
 #define EVIOCGVERSION		_IOR('E', 0x01, int)			/* get driver version */
 #define EVIOCGID		_IOR('E', 0x02, struct input_id)	/* get device ID */
 #define EVIOCGREP		_IOR('E', 0x03, unsigned int[2])	/* get repeat settings */
 #define EVIOCSREP		_IOW('E', 0x03, unsigned int[2])	/* set repeat settings */
-#define EVIOCGKEYCODE		_IOR('E', 0x04, unsigned int[2])	/* get keycode */
-#define EVIOCSKEYCODE		_IOW('E', 0x04, unsigned int[2])	/* set keycode */
+
+#define EVIOCGKEYCODE		_IOR('E', 0x04, struct input_keymap_entry)	/* get keycode */
+#define EVIOCSKEYCODE		_IOW('E', 0x04, struct input_keymap_entry)	/* set keycode */
 
 #define EVIOCGNAME(len)		_IOC(_IOC_READ, 'E', 0x06, len)		/* get device name */
 #define EVIOCGPHYS(len)		_IOC(_IOC_READ, 'E', 0x07, len)		/* get physical location */
 #define EVIOCGUNIQ(len)		_IOC(_IOC_READ, 'E', 0x08, len)		/* get unique identifier */
 
-#define EVIOCGKEY(len)		_IOC(_IOC_READ, 'E', 0x18, len)		/* get global keystate */
+#define EVIOCGKEY(len)		_IOC(_IOC_READ, 'E', 0x18, len)		/* get global key state */
 #define EVIOCGLED(len)		_IOC(_IOC_READ, 'E', 0x19, len)		/* get all LEDs */
 #define EVIOCGSND(len)		_IOC(_IOC_READ, 'E', 0x1a, len)		/* get all sounds status */
 #define EVIOCGSW(len)		_IOC(_IOC_READ, 'E', 0x1b, len)		/* get all switch states */
 
 #define EVIOCGBIT(ev,len)	_IOC(_IOC_READ, 'E', 0x20 + ev, len)	/* get event bits */
-#define EVIOCGABS(abs)		_IOR('E', 0x40 + abs, struct input_absinfo)		/* get abs value/limits */
-#define EVIOCSABS(abs)		_IOW('E', 0xc0 + abs, struct input_absinfo)		/* set abs value/limits */
+#define EVIOCGABS(abs)		_IOR('E', 0x40 + abs, struct input_absinfo)	/* get abs value/limits */
+#define EVIOCSABS(abs)		_IOW('E', 0xc0 + abs, struct input_absinfo)	/* set abs value/limits */
 
 #define EVIOCSFF		_IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))	/* send a force effect to a force feedback device */
 #define EVIOCRMFF		_IOW('E', 0x81, int)			/* Erase a force effect */
@@ -1088,13 +1113,13 @@
  * @keycodemax: size of keycode table
  * @keycodesize: size of elements in keycode table
  * @keycode: map of scancodes to keycodes for this device
+ * @getkeycode: optional legacy method to retrieve current keymap.
  * @setkeycode: optional method to alter current keymap, used to implement
  *	sparse keymaps. If not supplied default mechanism will be used.
  *	The method is being called while holding event_lock and thus must
  *	not sleep
- * @getkeycode: optional method to retrieve current keymap. If not supplied
- *	default mechanism will be used. The method is being called while
- *	holding event_lock and thus must not sleep
+ * @getkeycode_new: transition method
+ * @setkeycode_new: transition method
  * @ff: force feedback structure associated with the device if device
  *	supports force feedback effects
  * @repeat_key: stores key code of the last key pressed; used to implement
@@ -1168,10 +1193,16 @@
 	unsigned int keycodemax;
 	unsigned int keycodesize;
 	void *keycode;
+
 	int (*setkeycode)(struct input_dev *dev,
 			  unsigned int scancode, unsigned int keycode);
 	int (*getkeycode)(struct input_dev *dev,
 			  unsigned int scancode, unsigned int *keycode);
+	int (*setkeycode_new)(struct input_dev *dev,
+			      const struct input_keymap_entry *ke,
+			      unsigned int *old_keycode);
+	int (*getkeycode_new)(struct input_dev *dev,
+			      struct input_keymap_entry *ke);
 
 	struct ff_device *ff;
 
@@ -1478,10 +1509,12 @@
 INPUT_GENERATE_ABS_ACCESSORS(flat, flat)
 INPUT_GENERATE_ABS_ACCESSORS(res, resolution)
 
-int input_get_keycode(struct input_dev *dev,
-		      unsigned int scancode, unsigned int *keycode);
+int input_scancode_to_scalar(const struct input_keymap_entry *ke,
+			     unsigned int *scancode);
+
+int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke);
 int input_set_keycode(struct input_dev *dev,
-		      unsigned int scancode, unsigned int keycode);
+		      const struct input_keymap_entry *ke);
 
 extern struct class input_class;
 
diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h
new file mode 100644
index 0000000..e470d38
--- /dev/null
+++ b/include/linux/input/bu21013.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * License terms:GNU General Public License (GPL) version 2
+ */
+
+#ifndef _BU21013_H
+#define _BU21013_H
+
+/**
+ * struct bu21013_platform_device - Handle the platform data
+ * @cs_en:	pointer to the cs enable function
+ * @cs_dis:	pointer to the cs disable function
+ * @irq_read_val:    pointer to read the pen irq value function
+ * @x_max_res: xmax resolution
+ * @y_max_res: ymax resolution
+ * @touch_x_max: touch x max
+ * @touch_y_max: touch y max
+ * @cs_pin: chip select pin
+ * @irq: irq pin
+ * @ext_clk: external clock flag
+ * @x_flip: x flip flag
+ * @y_flip: y flip flag
+ * @wakeup: wakeup flag
+ *
+ * This is used to handle the platform data
+ */
+struct bu21013_platform_device {
+	int (*cs_en)(int reset_pin);
+	int (*cs_dis)(int reset_pin);
+	int (*irq_read_val)(void);
+	int x_max_res;
+	int y_max_res;
+	int touch_x_max;
+	int touch_y_max;
+	unsigned int cs_pin;
+	unsigned int irq;
+	bool ext_clk;
+	bool x_flip;
+	bool y_flip;
+	bool wakeup;
+};
+
+#endif
diff --git a/include/linux/serio.h b/include/linux/serio.h
index b555256..e26f478 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -41,7 +41,9 @@
 	int (*start)(struct serio *);
 	void (*stop)(struct serio *);
 
-	struct serio *parent, *child;
+	struct serio *parent;
+	struct list_head child_node;	/* Entry in parent->children list */
+	struct list_head children;
 	unsigned int depth;		/* level of nesting in serio hierarchy */
 
 	struct serio_driver *drv;	/* accessed from interrupt, must be protected by serio->lock and serio->sem */
@@ -54,10 +56,9 @@
 #define to_serio_port(d)	container_of(d, struct serio, dev)
 
 struct serio_driver {
-	void *private;
-	char *description;
+	const char *description;
 
-	struct serio_device_id *id_table;
+	const struct serio_device_id *id_table;
 	bool manual_bind;
 
 	void (*write_wakeup)(struct serio *);
@@ -197,5 +198,6 @@
 #define SERIO_W8001	0x39
 #define SERIO_DYNAPRO	0x3a
 #define SERIO_HAMPSHIRE	0x3b
+#define SERIO_PS2MULT	0x3c
 
 #endif
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index a9c041d..9b201ec 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -35,7 +35,7 @@
 	unsigned int		len;	/* Used number of entries */
 	unsigned int		alloc;	/* Size of *scan in bytes */
 	u64			ir_type;
-	char			*name;
+	const char		*name;
 	spinlock_t		lock;
 };