summary refs log tree commit diff
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2015-04-21 11:12:42 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2015-04-21 11:12:42 -0700
commit48853389f206b689260ddfd3006816779ca7a52a (patch)
tree8abc3be612779c3252190bc54a38eb0b3c258e19
parent85a3685852d9ac7d92be9d824533c915a4597fa4 (diff)
parentc9eeb5084b27ffede2709e8775827729d0c7c46c (diff)
downloadlinux-48853389f206b689260ddfd3006816779ca7a52a.tar.gz
Merge branch 'next' into for-linus
Prepare second round of updates for 4.1 merge window.
-rw-r--r--Documentation/input/alps.txt9
-rw-r--r--MAINTAINERS8
-rw-r--r--drivers/input/ff-core.c10
-rw-r--r--drivers/input/joystick/xpad.c21
-rw-r--r--drivers/input/keyboard/lm8333.c4
-rw-r--r--drivers/input/mouse/Kconfig12
-rw-r--r--drivers/input/mouse/Makefile1
-rw-r--r--drivers/input/mouse/cyapa.c4
-rw-r--r--drivers/input/mouse/elan_i2c.h3
-rw-r--r--drivers/input/mouse/elan_i2c_core.c38
-rw-r--r--drivers/input/mouse/elan_i2c_i2c.c27
-rw-r--r--drivers/input/mouse/elan_i2c_smbus.c12
-rw-r--r--drivers/input/mouse/psmouse-base.c17
-rw-r--r--drivers/input/mouse/psmouse.h1
-rw-r--r--drivers/input/mouse/vmmouse.c508
-rw-r--r--drivers/input/mouse/vmmouse.h30
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c141
-rw-r--r--drivers/input/touchscreen/elants_i2c.c2
18 files changed, 806 insertions, 42 deletions
diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt
index 92ae734c00c3..e301887d8523 100644
--- a/Documentation/input/alps.txt
+++ b/Documentation/input/alps.txt
@@ -94,6 +94,10 @@ PS/2 packet format
 
 Note that the device never signals overflow condition.
 
+For protocol version 2 devices when the trackpoint is used, and no fingers
+are on the touchpad, the M R L bits signal the combined status of both the
+pointingstick and touchpad buttons.
+
 ALPS Absolute Mode - Protocol Version 1
 --------------------------------------
 
@@ -107,7 +111,7 @@ ALPS Absolute Mode - Protocol Version 1
 ALPS Absolute Mode - Protocol Version 2
 ---------------------------------------
 
- byte 0:  1    ?    ?    ?    1    ?    ?    ?
+ byte 0:  1    ?    ?    ?    1  PSM  PSR  PSL
  byte 1:  0   x6   x5   x4   x3   x2   x1   x0
  byte 2:  0  x10   x9   x8   x7    ?  fin  ges
  byte 3:  0   y9   y8   y7    1    M    R    L
@@ -115,7 +119,8 @@ ALPS Absolute Mode - Protocol Version 2
  byte 5:  0   z6   z5   z4   z3   z2   z1   z0
 
 Protocol Version 2 DualPoint devices send standard PS/2 mouse packets for
-the DualPoint Stick.
+the DualPoint Stick. For non interleaved dualpoint devices the pointingstick
+buttons get reported separately in the PSM, PSR and PSL bits.
 
 Dualpoint device -- interleaved packet format
 ---------------------------------------------
diff --git a/MAINTAINERS b/MAINTAINERS
index c98757d0626f..460ab22db181 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10530,6 +10530,14 @@ L:	linux-kernel@vger.kernel.org
 S:	Maintained
 F:	drivers/misc/vmw_balloon.c
 
+VMWARE VMMOUSE SUBDRIVER
+M:	"VMware Graphics" <linux-graphics-maintainer@vmware.com>
+M:	"VMware, Inc." <pv-drivers@vmware.com>
+L:	linux-input@vger.kernel.org
+S:	Maintained
+F:	drivers/input/mouse/vmmouse.c
+F:	drivers/input/mouse/vmmouse.h
+
 VMWARE VMXNET3 ETHERNET DRIVER
 M:	Shreyas Bhatewara <sbhatewara@vmware.com>
 M:	"VMware, Inc." <pv-drivers@vmware.com>
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c
index f50f6dd92274..b81c88c43452 100644
--- a/drivers/input/ff-core.c
+++ b/drivers/input/ff-core.c
@@ -23,8 +23,6 @@
 
 /* #define DEBUG */
 
-#define pr_fmt(fmt) KBUILD_BASENAME ": " fmt
-
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -116,7 +114,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
 
 	if (effect->type < FF_EFFECT_MIN || effect->type > FF_EFFECT_MAX ||
 	    !test_bit(effect->type, dev->ffbit)) {
-		pr_debug("invalid or not supported effect type in upload\n");
+		dev_dbg(&dev->dev, "invalid or not supported effect type in upload\n");
 		return -EINVAL;
 	}
 
@@ -124,7 +122,7 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect,
 	    (effect->u.periodic.waveform < FF_WAVEFORM_MIN ||
 	     effect->u.periodic.waveform > FF_WAVEFORM_MAX ||
 	     !test_bit(effect->u.periodic.waveform, dev->ffbit))) {
-		pr_debug("invalid or not supported wave form in upload\n");
+		dev_dbg(&dev->dev, "invalid or not supported wave form in upload\n");
 		return -EINVAL;
 	}
 
@@ -246,7 +244,7 @@ static int flush_effects(struct input_dev *dev, struct file *file)
 	struct ff_device *ff = dev->ff;
 	int i;
 
-	pr_debug("flushing now\n");
+	dev_dbg(&dev->dev, "flushing now\n");
 
 	mutex_lock(&ff->mutex);
 
@@ -316,7 +314,7 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
 	int i;
 
 	if (!max_effects) {
-		pr_err("cannot allocate device without any effects\n");
+		dev_err(&dev->dev, "cannot allocate device without any effects\n");
 		return -EINVAL;
 	}
 
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index 3aa2f3f3da5b..61c761156371 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -31,12 +31,14 @@
  *  - the iForce driver    drivers/char/joystick/iforce.c
  *  - the skeleton-driver  drivers/usb/usb-skeleton.c
  *  - Xbox 360 information http://www.free60.org/wiki/Gamepad
+ *  - Xbox One information https://github.com/quantus/xbox-one-controller-protocol
  *
  * Thanks to:
  *  - ITO Takayuki for providing essential xpad information on his website
  *  - Vojtech Pavlik     - iforce driver / input subsystem
  *  - Greg Kroah-Hartman - usb-skeleton driver
  *  - XBOX Linux project - extra USB id's
+ *  - Pekka Pöyry (quantus) - Xbox One controller reverse engineering
  *
  * TODO:
  *  - fine tune axes (especially trigger axes)
@@ -828,6 +830,23 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
 			return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
 
+		case XTYPE_XBOXONE:
+			xpad->odata[0] = 0x09; /* activate rumble */
+			xpad->odata[1] = 0x08;
+			xpad->odata[2] = 0x00;
+			xpad->odata[3] = 0x08; /* continuous effect */
+			xpad->odata[4] = 0x00; /* simple rumble mode */
+			xpad->odata[5] = 0x03; /* L and R actuator only */
+			xpad->odata[6] = 0x00; /* TODO: LT actuator */
+			xpad->odata[7] = 0x00; /* TODO: RT actuator */
+			xpad->odata[8] = strong / 256;	/* left actuator */
+			xpad->odata[9] = weak / 256;	/* right actuator */
+			xpad->odata[10] = 0x80;	/* length of pulse */
+			xpad->odata[11] = 0x00;	/* stop period of pulse */
+			xpad->irq_out->transfer_buffer_length = 12;
+
+			return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
+
 		default:
 			dev_dbg(&xpad->dev->dev,
 				"%s - rumble command sent to unsupported xpad type: %d\n",
@@ -841,7 +860,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect
 
 static int xpad_init_ff(struct usb_xpad *xpad)
 {
-	if (xpad->xtype == XTYPE_UNKNOWN || xpad->xtype == XTYPE_XBOXONE)
+	if (xpad->xtype == XTYPE_UNKNOWN)
 		return 0;
 
 	input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c
index 9081cbef11ea..0ad422b8a260 100644
--- a/drivers/input/keyboard/lm8333.c
+++ b/drivers/input/keyboard/lm8333.c
@@ -1,6 +1,6 @@
 /*
  * LM8333 keypad driver
- * Copyright (C) 2012 Wolfram Sang, Pengutronix <w.sang@pengutronix.de>
+ * Copyright (C) 2012 Wolfram Sang, Pengutronix <kernel@pengutronix.de>
  *
  * 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
@@ -231,6 +231,6 @@ static struct i2c_driver lm8333_driver = {
 };
 module_i2c_driver(lm8333_driver);
 
-MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
 MODULE_DESCRIPTION("LM8333 keyboard driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 4658b5d41dd7..7462d2fc8cfe 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -149,6 +149,18 @@ config MOUSE_PS2_FOCALTECH
 
 	  If unsure, say Y.
 
+config MOUSE_PS2_VMMOUSE
+	bool "Virtual mouse (vmmouse)"
+	depends on MOUSE_PS2 && X86 && HYPERVISOR_GUEST
+	help
+	  Say Y here if you are running under control of VMware hypervisor
+	  (ESXi, Workstation or Fusion). Also make sure that when you enable
+	  this option, you remove the xf86-input-vmmouse user-space driver
+	  or upgrade it to at least xf86-input-vmmouse 13.0.1, which doesn't
+	  load in the presence of an in-kernel vmmouse driver.
+
+	  If unsure, say N.
+
 config MOUSE_SERIAL
 	tristate "Serial mouse"
 	select SERIO
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index 8a9c98e76d9c..793300bfbddd 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -36,6 +36,7 @@ psmouse-$(CONFIG_MOUSE_PS2_SENTELIC)	+= sentelic.o
 psmouse-$(CONFIG_MOUSE_PS2_TRACKPOINT)	+= trackpoint.o
 psmouse-$(CONFIG_MOUSE_PS2_TOUCHKIT)	+= touchkit_ps2.o
 psmouse-$(CONFIG_MOUSE_PS2_CYPRESS)	+= cypress_ps2.o
+psmouse-$(CONFIG_MOUSE_PS2_VMMOUSE)	+= vmmouse.o
 
 elan_i2c-objs := elan_i2c_core.o
 elan_i2c-$(CONFIG_MOUSE_ELAN_I2C_I2C)	+= elan_i2c_i2c.o
diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
index 58f4f6fa4857..efe148474e7f 100644
--- a/drivers/input/mouse/cyapa.c
+++ b/drivers/input/mouse/cyapa.c
@@ -723,7 +723,7 @@ static ssize_t cyapa_update_suspend_scanrate(struct device *dev,
 	} else if (sysfs_streq(buf, OFF_MODE_NAME)) {
 		cyapa->suspend_power_mode = PWR_MODE_OFF;
 	} else if (!kstrtou16(buf, 10, &sleep_time)) {
-		cyapa->suspend_sleep_time = max_t(u16, sleep_time, 1000);
+		cyapa->suspend_sleep_time = min_t(u16, sleep_time, 1000);
 		cyapa->suspend_power_mode =
 			cyapa_sleep_time_to_pwr_cmd(cyapa->suspend_sleep_time);
 	} else {
@@ -840,7 +840,7 @@ static ssize_t cyapa_update_rt_suspend_scanrate(struct device *dev,
 	if (error)
 		return error;
 
-	cyapa->runtime_suspend_sleep_time = max_t(u16, time, 1000);
+	cyapa->runtime_suspend_sleep_time = min_t(u16, time, 1000);
 	cyapa->runtime_suspend_power_mode =
 		cyapa_sleep_time_to_pwr_cmd(cyapa->runtime_suspend_sleep_time);
 
diff --git a/drivers/input/mouse/elan_i2c.h b/drivers/input/mouse/elan_i2c.h
index 9b2dc015f20c..6d5f8a4c1748 100644
--- a/drivers/input/mouse/elan_i2c.h
+++ b/drivers/input/mouse/elan_i2c.h
@@ -25,6 +25,7 @@
 #define ETP_ENABLE_CALIBRATE	0x0002
 #define ETP_DISABLE_CALIBRATE	0x0000
 #define ETP_DISABLE_POWER	0x0001
+#define ETP_PRESSURE_OFFSET	25
 
 /* IAP Firmware handling */
 #define ETP_FW_NAME		"elan_i2c.bin"
@@ -79,6 +80,8 @@ struct elan_transport_ops {
 				struct completion *reset_done);
 
 	int (*get_report)(struct i2c_client *client, u8 *report);
+	int (*get_pressure_adjustment)(struct i2c_client *client,
+				       int *adjustment);
 };
 
 extern const struct elan_transport_ops elan_smbus_ops, elan_i2c_ops;
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index 375d98f47483..fd5068b2542d 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2013 ELAN Microelectronics Corp.
  *
  * Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
- * Version: 1.5.6
+ * Version: 1.5.7
  *
  * Based on cyapa driver:
  * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
@@ -40,8 +40,7 @@
 #include "elan_i2c.h"
 
 #define DRIVER_NAME		"elan_i2c"
-#define ELAN_DRIVER_VERSION	"1.5.6"
-#define ETP_PRESSURE_OFFSET	25
+#define ELAN_DRIVER_VERSION	"1.5.7"
 #define ETP_MAX_PRESSURE	255
 #define ETP_FWIDTH_REDUCE	90
 #define ETP_FINGER_WIDTH	15
@@ -53,6 +52,7 @@
 #define ETP_REPORT_ID_OFFSET	2
 #define ETP_TOUCH_INFO_OFFSET	3
 #define ETP_FINGER_DATA_OFFSET	4
+#define ETP_HOVER_INFO_OFFSET	30
 #define ETP_MAX_REPORT_LEN	34
 
 /* The main device structure */
@@ -81,7 +81,7 @@ struct elan_tp_data {
 	u8			sm_version;
 	u8			iap_version;
 	u16			fw_checksum;
-
+	int			pressure_adjustment;
 	u8			mode;
 
 	bool			irq_wake;
@@ -229,6 +229,11 @@ static int elan_query_device_info(struct elan_tp_data *data)
 	if (error)
 		return error;
 
+	error = data->ops->get_pressure_adjustment(data->client,
+						   &data->pressure_adjustment);
+	if (error)
+		return error;
+
 	return 0;
 }
 
@@ -721,13 +726,13 @@ static const struct attribute_group *elan_sysfs_groups[] = {
  */
 static void elan_report_contact(struct elan_tp_data *data,
 				int contact_num, bool contact_valid,
-				u8 *finger_data)
+				bool hover_event, u8 *finger_data)
 {
 	struct input_dev *input = data->input;
 	unsigned int pos_x, pos_y;
 	unsigned int pressure, mk_x, mk_y;
-	unsigned int area_x, area_y, major, minor, new_pressure;
-
+	unsigned int area_x, area_y, major, minor;
+	unsigned int scaled_pressure;
 
 	if (contact_valid) {
 		pos_x = ((finger_data[0] & 0xf0) << 4) |
@@ -756,15 +761,18 @@ static void elan_report_contact(struct elan_tp_data *data,
 		major = max(area_x, area_y);
 		minor = min(area_x, area_y);
 
-		new_pressure = pressure + ETP_PRESSURE_OFFSET;
-		if (new_pressure > ETP_MAX_PRESSURE)
-			new_pressure = ETP_MAX_PRESSURE;
+		scaled_pressure = pressure + data->pressure_adjustment;
+
+		if (scaled_pressure > ETP_MAX_PRESSURE)
+			scaled_pressure = ETP_MAX_PRESSURE;
 
 		input_mt_slot(input, contact_num);
 		input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
 		input_report_abs(input, ABS_MT_POSITION_X, pos_x);
 		input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y);
-		input_report_abs(input, ABS_MT_PRESSURE, new_pressure);
+		input_report_abs(input, ABS_MT_DISTANCE, hover_event);
+		input_report_abs(input, ABS_MT_PRESSURE,
+				 hover_event ? 0 : scaled_pressure);
 		input_report_abs(input, ABS_TOOL_WIDTH, mk_x);
 		input_report_abs(input, ABS_MT_TOUCH_MAJOR, major);
 		input_report_abs(input, ABS_MT_TOUCH_MINOR, minor);
@@ -780,11 +788,14 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet)
 	u8 *finger_data = &packet[ETP_FINGER_DATA_OFFSET];
 	int i;
 	u8 tp_info = packet[ETP_TOUCH_INFO_OFFSET];
-	bool contact_valid;
+	u8 hover_info = packet[ETP_HOVER_INFO_OFFSET];
+	bool contact_valid, hover_event;
 
+	hover_event = hover_info & 0x40;
 	for (i = 0; i < ETP_MAX_FINGERS; i++) {
 		contact_valid = tp_info & (1U << (3 + i));
-		elan_report_contact(data, i, contact_valid, finger_data);
+		elan_report_contact(data, i, contact_valid, hover_event,
+				    finger_data);
 
 		if (contact_valid)
 			finger_data += ETP_FINGER_DATA_LEN;
@@ -878,6 +889,7 @@ static int elan_setup_input_device(struct elan_tp_data *data)
 			     ETP_FINGER_WIDTH * max_width, 0, 0);
 	input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0,
 			     ETP_FINGER_WIDTH * min_width, 0, 0);
+	input_set_abs_params(input, ABS_MT_DISTANCE, 0, 1, 0, 0);
 
 	data->input = input;
 
diff --git a/drivers/input/mouse/elan_i2c_i2c.c b/drivers/input/mouse/elan_i2c_i2c.c
index 6cf0def6d35e..a0acbbf83bfd 100644
--- a/drivers/input/mouse/elan_i2c_i2c.c
+++ b/drivers/input/mouse/elan_i2c_i2c.c
@@ -41,6 +41,7 @@
 #define ETP_I2C_MAX_X_AXIS_CMD		0x0106
 #define ETP_I2C_MAX_Y_AXIS_CMD		0x0107
 #define ETP_I2C_RESOLUTION_CMD		0x0108
+#define ETP_I2C_PRESSURE_CMD		0x010A
 #define ETP_I2C_IAP_VERSION_CMD		0x0110
 #define ETP_I2C_SET_CMD			0x0300
 #define ETP_I2C_POWER_CMD		0x0307
@@ -364,8 +365,29 @@ static int elan_i2c_get_num_traces(struct i2c_client *client,
 		return error;
 	}
 
-	*x_traces = val[0] - 1;
-	*y_traces = val[1] - 1;
+	*x_traces = val[0];
+	*y_traces = val[1];
+
+	return 0;
+}
+
+static int elan_i2c_get_pressure_adjustment(struct i2c_client *client,
+					    int *adjustment)
+{
+	int error;
+	u8 val[3];
+
+	error = elan_i2c_read_cmd(client, ETP_I2C_PRESSURE_CMD, val);
+	if (error) {
+		dev_err(&client->dev, "failed to get pressure format: %d\n",
+			error);
+		return error;
+	}
+
+	if ((val[0] >> 4) & 0x1)
+		*adjustment = 0;
+	else
+		*adjustment = ETP_PRESSURE_OFFSET;
 
 	return 0;
 }
@@ -602,6 +624,7 @@ const struct elan_transport_ops elan_i2c_ops = {
 	.get_sm_version		= elan_i2c_get_sm_version,
 	.get_product_id		= elan_i2c_get_product_id,
 	.get_checksum		= elan_i2c_get_checksum,
+	.get_pressure_adjustment = elan_i2c_get_pressure_adjustment,
 
 	.get_max		= elan_i2c_get_max,
 	.get_resolution		= elan_i2c_get_resolution,
diff --git a/drivers/input/mouse/elan_i2c_smbus.c b/drivers/input/mouse/elan_i2c_smbus.c
index 06a2bcd1cda2..30ab80dbcdd6 100644
--- a/drivers/input/mouse/elan_i2c_smbus.c
+++ b/drivers/input/mouse/elan_i2c_smbus.c
@@ -268,12 +268,19 @@ static int elan_smbus_get_num_traces(struct i2c_client *client,
 		return error;
 	}
 
-	*x_traces = val[1] - 1;
-	*y_traces = val[2] - 1;
+	*x_traces = val[1];
+	*y_traces = val[2];
 
 	return 0;
 }
 
+static int elan_smbus_get_pressure_adjustment(struct i2c_client *client,
+					      int *adjustment)
+{
+	*adjustment = ETP_PRESSURE_OFFSET;
+	return 0;
+}
+
 static int elan_smbus_iap_get_mode(struct i2c_client *client,
 				   enum tp_mode *mode)
 {
@@ -497,6 +504,7 @@ const struct elan_transport_ops elan_smbus_ops = {
 	.get_sm_version		= elan_smbus_get_sm_version,
 	.get_product_id		= elan_smbus_get_product_id,
 	.get_checksum		= elan_smbus_get_checksum,
+	.get_pressure_adjustment = elan_smbus_get_pressure_adjustment,
 
 	.get_max		= elan_smbus_get_max,
 	.get_resolution		= elan_smbus_get_resolution,
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 27057df7ba74..5bb1658f60c7 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -36,6 +36,7 @@
 #include "sentelic.h"
 #include "cypress_ps2.h"
 #include "focaltech.h"
+#include "vmmouse.h"
 
 #define DRIVER_DESC	"PS/2 mouse driver"
 
@@ -790,6 +791,13 @@ static int psmouse_extensions(struct psmouse *psmouse,
 		}
 	}
 
+	if (psmouse_do_detect(vmmouse_detect, psmouse, set_properties) == 0) {
+		if (max_proto > PSMOUSE_IMEX) {
+			if (!set_properties || vmmouse_init(psmouse) == 0)
+				return PSMOUSE_VMMOUSE;
+		}
+	}
+
 /*
  * Try Kensington ThinkingMouse (we try first, because synaptics probe
  * upsets the thinkingmouse).
@@ -1113,6 +1121,15 @@ static const struct psmouse_protocol psmouse_protocols[] = {
 		.init		= focaltech_init,
 	},
 #endif
+#ifdef CONFIG_MOUSE_PS2_VMMOUSE
+	{
+		.type		= PSMOUSE_VMMOUSE,
+		.name		= VMMOUSE_PSNAME,
+		.alias		= "vmmouse",
+		.detect		= vmmouse_detect,
+		.init		= vmmouse_init,
+	},
+#endif
 	{
 		.type		= PSMOUSE_AUTO,
 		.name		= "auto",
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index d02e1bdc9ae4..ad5a5a1ea872 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -103,6 +103,7 @@ enum psmouse_type {
 	PSMOUSE_SYNAPTICS_RELATIVE,
 	PSMOUSE_CYPRESS,
 	PSMOUSE_FOCALTECH,
+	PSMOUSE_VMMOUSE,
 	PSMOUSE_AUTO		/* This one should always be last */
 };
 
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
new file mode 100644
index 000000000000..e272f06258ce
--- /dev/null
+++ b/drivers/input/mouse/vmmouse.c
@@ -0,0 +1,508 @@
+/*
+ * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors.
+ *
+ * Copyright (C) 2014, VMware, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * Twin device code is hugely inspired by the ALPS driver.
+ * Authors:
+ *   Dmitry Torokhov <dmitry.torokhov@gmail.com>
+ *   Thomas Hellstrom <thellstrom@vmware.com>
+ */
+
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/libps2.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <asm/hypervisor.h>
+
+#include "psmouse.h"
+#include "vmmouse.h"
+
+#define VMMOUSE_PROTO_MAGIC			0x564D5868U
+#define VMMOUSE_PROTO_PORT			0x5658
+
+/*
+ * Main commands supported by the vmmouse hypervisor port.
+ */
+#define VMMOUSE_PROTO_CMD_GETVERSION		10
+#define VMMOUSE_PROTO_CMD_ABSPOINTER_DATA	39
+#define VMMOUSE_PROTO_CMD_ABSPOINTER_STATUS	40
+#define VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND	41
+#define VMMOUSE_PROTO_CMD_ABSPOINTER_RESTRICT   86
+
+/*
+ * Subcommands for VMMOUSE_PROTO_CMD_ABSPOINTER_COMMAND
+ */
+#define VMMOUSE_CMD_ENABLE			0x45414552U
+#define VMMOUSE_CMD_DISABLE			0x000000f5U
+#define VMMOUSE_CMD_REQUEST_RELATIVE		0x4c455252U
+#define VMMOUSE_CMD_REQUEST_ABSOLUTE		0x53424152U
+
+#define VMMOUSE_ERROR				0xffff0000U
+
+#define VMMOUSE_VERSION_ID			0x3442554aU
+
+#define VMMOUSE_RELATIVE_PACKET			0x00010000U
+
+#define VMMOUSE_LEFT_BUTTON			0x20
+#define VMMOUSE_RIGHT_BUTTON			0x10
+#define VMMOUSE_MIDDLE_BUTTON			0x08
+
+/*
+ * VMMouse Restrict command
+ */
+#define VMMOUSE_RESTRICT_ANY                    0x00
+#define VMMOUSE_RESTRICT_CPL0                   0x01
+#define VMMOUSE_RESTRICT_IOPL                   0x02
+
+#define VMMOUSE_MAX_X                           0xFFFF
+#define VMMOUSE_MAX_Y                           0xFFFF
+
+#define VMMOUSE_VENDOR "VMware"
+#define VMMOUSE_NAME   "VMMouse"
+
+/**
+ * struct vmmouse_data - private data structure for the vmmouse driver
+ *
+ * @abs_dev: "Absolute" device used to report absolute mouse movement.
+ * @phys: Physical path for the absolute device.
+ * @dev_name: Name attribute name for the absolute device.
+ */
+struct vmmouse_data {
+	struct input_dev *abs_dev;
+	char phys[32];
+	char dev_name[128];
+};
+
+/**
+ * Hypervisor-specific bi-directional communication channel
+ * implementing the vmmouse protocol. Should never execute on
+ * bare metal hardware.
+ */
+#define VMMOUSE_CMD(cmd, in1, out1, out2, out3, out4)	\
+({							\
+	unsigned long __dummy1, __dummy2;		\
+	__asm__ __volatile__ ("inl %%dx" :		\
+		"=a"(out1),				\
+		"=b"(out2),				\
+		"=c"(out3),				\
+		"=d"(out4),				\
+		"=S"(__dummy1),				\
+		"=D"(__dummy2) :			\
+		"a"(VMMOUSE_PROTO_MAGIC),		\
+		"b"(in1),				\
+		"c"(VMMOUSE_PROTO_CMD_##cmd),		\
+		"d"(VMMOUSE_PROTO_PORT) :		\
+		"memory");		                \
+})
+
+/**
+ * vmmouse_report_button - report button state on the correct input device
+ *
+ * @psmouse:  Pointer to the psmouse struct
+ * @abs_dev:  The absolute input device
+ * @rel_dev:  The relative input device
+ * @pref_dev: The preferred device for reporting
+ * @code:     Button code
+ * @value:    Button value
+ *
+ * Report @value and @code on @pref_dev, unless the button is already
+ * pressed on the other device, in which case the state is reported on that
+ * device.
+ */
+static void vmmouse_report_button(struct psmouse *psmouse,
+				  struct input_dev *abs_dev,
+				  struct input_dev *rel_dev,
+				  struct input_dev *pref_dev,
+				  unsigned int code, int value)
+{
+	if (test_bit(code, abs_dev->key))
+		pref_dev = abs_dev;
+	else if (test_bit(code, rel_dev->key))
+		pref_dev = rel_dev;
+
+	input_report_key(pref_dev, code, value);
+}
+
+/**
+ * vmmouse_report_events - process events on the vmmouse communications channel
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * This function pulls events from the vmmouse communications channel and
+ * reports them on the correct (absolute or relative) input device. When the
+ * communications channel is drained, or if we've processed more than 255
+ * psmouse commands, the function returns PSMOUSE_FULL_PACKET. If there is a
+ * host- or synchronization error, the function returns PSMOUSE_BAD_DATA in
+ * the hope that the caller will reset the communications channel.
+ */
+static psmouse_ret_t vmmouse_report_events(struct psmouse *psmouse)
+{
+	struct input_dev *rel_dev = psmouse->dev;
+	struct vmmouse_data *priv = psmouse->private;
+	struct input_dev *abs_dev = priv->abs_dev;
+	struct input_dev *pref_dev;
+	u32 status, x, y, z;
+	u32 dummy1, dummy2, dummy3;
+	unsigned int queue_length;
+	unsigned int count = 255;
+
+	while (count--) {
+		/* See if we have motion data. */
+		VMMOUSE_CMD(ABSPOINTER_STATUS, 0,
+			    status, dummy1, dummy2, dummy3);
+		if ((status & VMMOUSE_ERROR) == VMMOUSE_ERROR) {
+			psmouse_err(psmouse, "failed to fetch status data\n");
+			/*
+			 * After a few attempts this will result in
+			 * reconnect.
+			 */
+			return PSMOUSE_BAD_DATA;
+		}
+
+		queue_length = status & 0xffff;
+		if (queue_length == 0)
+			break;
+
+		if (queue_length % 4) {
+			psmouse_err(psmouse, "invalid queue length\n");
+			return PSMOUSE_BAD_DATA;
+		}
+
+		/* Now get it */
+		VMMOUSE_CMD(ABSPOINTER_DATA, 4, status, x, y, z);
+
+		/*
+		 * And report what we've got. Prefer to report button
+		 * events on the same device where we report motion events.
+		 * This doesn't work well with the mouse wheel, though. See
+		 * below. Ideally we would want to report that on the
+		 * preferred device as well.
+		 */
+		if (status & VMMOUSE_RELATIVE_PACKET) {
+			pref_dev = rel_dev;
+			input_report_rel(rel_dev, REL_X, (s32)x);
+			input_report_rel(rel_dev, REL_Y, -(s32)y);
+		} else {
+			pref_dev = abs_dev;
+			input_report_abs(abs_dev, ABS_X, x);
+			input_report_abs(abs_dev, ABS_Y, y);
+		}
+
+		/* Xorg seems to ignore wheel events on absolute devices */
+		input_report_rel(rel_dev, REL_WHEEL, -(s8)((u8) z));
+
+		vmmouse_report_button(psmouse, abs_dev, rel_dev,
+				      pref_dev, BTN_LEFT,
+				      status & VMMOUSE_LEFT_BUTTON);
+		vmmouse_report_button(psmouse, abs_dev, rel_dev,
+				      pref_dev, BTN_RIGHT,
+				      status & VMMOUSE_RIGHT_BUTTON);
+		vmmouse_report_button(psmouse, abs_dev, rel_dev,
+				      pref_dev, BTN_MIDDLE,
+				      status & VMMOUSE_MIDDLE_BUTTON);
+		input_sync(abs_dev);
+		input_sync(rel_dev);
+	}
+
+	return PSMOUSE_FULL_PACKET;
+}
+
+/**
+ * vmmouse_process_byte - process data on the ps/2 channel
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * When the ps/2 channel indicates that there is vmmouse data available,
+ * call vmmouse channel processing. Otherwise, continue to accept bytes. If
+ * there is a synchronization or communication data error, return
+ * PSMOUSE_BAD_DATA in the hope that the caller will reset the mouse.
+ */
+static psmouse_ret_t vmmouse_process_byte(struct psmouse *psmouse)
+{
+	unsigned char *packet = psmouse->packet;
+
+	switch (psmouse->pktcnt) {
+	case 1:
+		return (packet[0] & 0x8) == 0x8 ?
+			PSMOUSE_GOOD_DATA : PSMOUSE_BAD_DATA;
+
+	case 2:
+		return PSMOUSE_GOOD_DATA;
+
+	default:
+		return vmmouse_report_events(psmouse);
+	}
+}
+
+/**
+ * vmmouse_disable - Disable vmmouse
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Tries to disable vmmouse mode.
+ */
+static void vmmouse_disable(struct psmouse *psmouse)
+{
+	u32 status;
+	u32 dummy1, dummy2, dummy3, dummy4;
+
+	VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_DISABLE,
+		    dummy1, dummy2, dummy3, dummy4);
+
+	VMMOUSE_CMD(ABSPOINTER_STATUS, 0,
+		    status, dummy1, dummy2, dummy3);
+
+	if ((status & VMMOUSE_ERROR) != VMMOUSE_ERROR)
+		psmouse_warn(psmouse, "failed to disable vmmouse device\n");
+}
+
+/**
+ * vmmouse_enable - Enable vmmouse and request absolute mode.
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Tries to enable vmmouse mode. Performs basic checks and requests
+ * absolute vmmouse mode.
+ * Returns 0 on success, -ENODEV on failure.
+ */
+static int vmmouse_enable(struct psmouse *psmouse)
+{
+	u32 status, version;
+	u32 dummy1, dummy2, dummy3, dummy4;
+
+	/*
+	 * Try enabling the device. If successful, we should be able to
+	 * read valid version ID back from it.
+	 */
+	VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_ENABLE,
+		    dummy1, dummy2, dummy3, dummy4);
+
+	/*
+	 * See if version ID can be retrieved.
+	 */
+	VMMOUSE_CMD(ABSPOINTER_STATUS, 0, status, dummy1, dummy2, dummy3);
+	if ((status & 0x0000ffff) == 0) {
+		psmouse_dbg(psmouse, "empty flags - assuming no device\n");
+		return -ENXIO;
+	}
+
+	VMMOUSE_CMD(ABSPOINTER_DATA, 1 /* single item */,
+		    version, dummy1, dummy2, dummy3);
+	if (version != VMMOUSE_VERSION_ID) {
+		psmouse_dbg(psmouse, "Unexpected version value: %u vs %u\n",
+			    (unsigned) version, VMMOUSE_VERSION_ID);
+		vmmouse_disable(psmouse);
+		return -ENXIO;
+	}
+
+	/*
+	 * Restrict ioport access, if possible.
+	 */
+	VMMOUSE_CMD(ABSPOINTER_RESTRICT, VMMOUSE_RESTRICT_CPL0,
+		    dummy1, dummy2, dummy3, dummy4);
+
+	VMMOUSE_CMD(ABSPOINTER_COMMAND, VMMOUSE_CMD_REQUEST_ABSOLUTE,
+		    dummy1, dummy2, dummy3, dummy4);
+
+	return 0;
+}
+
+/*
+ * Array of supported hypervisors.
+ */
+static const struct hypervisor_x86 *vmmouse_supported_hypervisors[] = {
+	&x86_hyper_vmware,
+#ifdef CONFIG_KVM_GUEST
+	&x86_hyper_kvm,
+#endif
+};
+
+/**
+ * vmmouse_check_hypervisor - Check if we're running on a supported hypervisor
+ */
+static bool vmmouse_check_hypervisor(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vmmouse_supported_hypervisors); i++)
+		if (vmmouse_supported_hypervisors[i] == x86_hyper)
+			return true;
+
+	return false;
+}
+
+/**
+ * vmmouse_detect - Probe whether vmmouse is available
+ *
+ * @psmouse: Pointer to the psmouse struct
+ * @set_properties: Whether to set psmouse name and vendor
+ *
+ * Returns 0 if vmmouse channel is available. Negative error code if not.
+ */
+int vmmouse_detect(struct psmouse *psmouse, bool set_properties)
+{
+	u32 response, version, dummy1, dummy2;
+
+	if (!vmmouse_check_hypervisor()) {
+		psmouse_dbg(psmouse,
+			    "VMMouse not running on supported hypervisor.\n");
+		return -ENXIO;
+	}
+
+	if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) {
+		psmouse_dbg(psmouse, "VMMouse port in use.\n");
+		return -EBUSY;
+	}
+
+	/* Check if the device is present */
+	response = ~VMMOUSE_PROTO_MAGIC;
+	VMMOUSE_CMD(GETVERSION, 0, version, response, dummy1, dummy2);
+	if (response != VMMOUSE_PROTO_MAGIC || version == 0xffffffffU) {
+		release_region(VMMOUSE_PROTO_PORT, 4);
+		return -ENXIO;
+	}
+
+	if (set_properties) {
+		psmouse->vendor = VMMOUSE_VENDOR;
+		psmouse->name = VMMOUSE_NAME;
+		psmouse->model = version;
+	}
+
+	release_region(VMMOUSE_PROTO_PORT, 4);
+
+	return 0;
+}
+
+/**
+ * vmmouse_disconnect - Take down vmmouse driver
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Takes down vmmouse driver and frees resources set up in vmmouse_init().
+ */
+static void vmmouse_disconnect(struct psmouse *psmouse)
+{
+	struct vmmouse_data *priv = psmouse->private;
+
+	vmmouse_disable(psmouse);
+	psmouse_reset(psmouse);
+	input_unregister_device(priv->abs_dev);
+	kfree(priv);
+	release_region(VMMOUSE_PROTO_PORT, 4);
+}
+
+/**
+ * vmmouse_reconnect - Reset the ps/2 - and vmmouse connections
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Attempts to reset the mouse connections. Returns 0 on success and
+ * -1 on failure.
+ */
+static int vmmouse_reconnect(struct psmouse *psmouse)
+{
+	int error;
+
+	psmouse_reset(psmouse);
+	vmmouse_disable(psmouse);
+	error = vmmouse_enable(psmouse);
+	if (error) {
+		psmouse_err(psmouse,
+			    "Unable to re-enable mouse when reconnecting, err: %d\n",
+			    error);
+		return error;
+	}
+
+	return 0;
+}
+
+/**
+ * vmmouse_init - Initialize the vmmouse driver
+ *
+ * @psmouse: Pointer to the psmouse struct
+ *
+ * Requests the device and tries to enable vmmouse mode.
+ * If successful, sets up the input device for relative movement events.
+ * It also allocates another input device and sets it up for absolute motion
+ * events. Returns 0 on success and -1 on failure.
+ */
+int vmmouse_init(struct psmouse *psmouse)
+{
+	struct vmmouse_data *priv;
+	struct input_dev *rel_dev = psmouse->dev, *abs_dev;
+	int error;
+
+	if (!request_region(VMMOUSE_PROTO_PORT, 4, "vmmouse")) {
+		psmouse_dbg(psmouse, "VMMouse port in use.\n");
+		return -EBUSY;
+	}
+
+	psmouse_reset(psmouse);
+	error = vmmouse_enable(psmouse);
+	if (error)
+		goto release_region;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	abs_dev = input_allocate_device();
+	if (!priv || !abs_dev) {
+		error = -ENOMEM;
+		goto init_fail;
+	}
+
+	priv->abs_dev = abs_dev;
+	psmouse->private = priv;
+
+	input_set_capability(rel_dev, EV_REL, REL_WHEEL);
+
+	/* Set up and register absolute device */
+	snprintf(priv->phys, sizeof(priv->phys), "%s/input1",
+		 psmouse->ps2dev.serio->phys);
+
+	/* Mimic name setup for relative device in psmouse-base.c */
+	snprintf(priv->dev_name, sizeof(priv->dev_name), "%s %s %s",
+		 VMMOUSE_PSNAME, VMMOUSE_VENDOR, VMMOUSE_NAME);
+	abs_dev->phys = priv->phys;
+	abs_dev->name = priv->dev_name;
+	abs_dev->id.bustype = BUS_I8042;
+	abs_dev->id.vendor = 0x0002;
+	abs_dev->id.product = PSMOUSE_VMMOUSE;
+	abs_dev->id.version = psmouse->model;
+	abs_dev->dev.parent = &psmouse->ps2dev.serio->dev;
+
+	error = input_register_device(priv->abs_dev);
+	if (error)
+		goto init_fail;
+
+	/* Set absolute device capabilities */
+	input_set_capability(abs_dev, EV_KEY, BTN_LEFT);
+	input_set_capability(abs_dev, EV_KEY, BTN_RIGHT);
+	input_set_capability(abs_dev, EV_KEY, BTN_MIDDLE);
+	input_set_capability(abs_dev, EV_ABS, ABS_X);
+	input_set_capability(abs_dev, EV_ABS, ABS_Y);
+	input_set_abs_params(abs_dev, ABS_X, 0, VMMOUSE_MAX_X, 0, 0);
+	input_set_abs_params(abs_dev, ABS_Y, 0, VMMOUSE_MAX_Y, 0, 0);
+
+	psmouse->protocol_handler = vmmouse_process_byte;
+	psmouse->disconnect = vmmouse_disconnect;
+	psmouse->reconnect = vmmouse_reconnect;
+
+	return 0;
+
+init_fail:
+	vmmouse_disable(psmouse);
+	psmouse_reset(psmouse);
+	input_free_device(abs_dev);
+	kfree(priv);
+	psmouse->private = NULL;
+
+release_region:
+	release_region(VMMOUSE_PROTO_PORT, 4);
+
+	return error;
+}
diff --git a/drivers/input/mouse/vmmouse.h b/drivers/input/mouse/vmmouse.h
new file mode 100644
index 000000000000..6f126017a24c
--- /dev/null
+++ b/drivers/input/mouse/vmmouse.h
@@ -0,0 +1,30 @@
+/*
+ * Driver for Virtual PS/2 Mouse on VMware and QEMU hypervisors.
+ *
+ * Copyright (C) 2014, VMware, Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+#ifndef _VMMOUSE_H
+#define _VMMOUSE_H
+
+#ifdef CONFIG_MOUSE_PS2_VMMOUSE
+#define VMMOUSE_PSNAME  "VirtualPS/2"
+
+int vmmouse_detect(struct psmouse *psmouse, bool set_properties);
+int vmmouse_init(struct psmouse *psmouse);
+#else
+static inline int vmmouse_detect(struct psmouse *psmouse, bool set_properties)
+{
+	return -ENOSYS;
+}
+static inline int vmmouse_init(struct psmouse *psmouse)
+{
+	return -ENOSYS;
+}
+#endif
+
+#endif
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 2875ddf37289..40b98dda8f38 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -14,6 +14,8 @@
  *
  */
 
+#include <linux/acpi.h>
+#include <linux/dmi.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/completion.h>
@@ -2371,7 +2373,7 @@ static void mxt_input_close(struct input_dev *dev)
 }
 
 #ifdef CONFIG_OF
-static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
+static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
 {
 	struct mxt_platform_data *pdata;
 	u32 *keymap;
@@ -2379,7 +2381,7 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
 	int proplen, i, ret;
 
 	if (!client->dev.of_node)
-		return ERR_PTR(-ENODEV);
+		return ERR_PTR(-ENOENT);
 
 	pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
@@ -2410,25 +2412,132 @@ static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
 	return pdata;
 }
 #else
-static struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
+static const struct mxt_platform_data *mxt_parse_dt(struct i2c_client *client)
 {
-	dev_dbg(&client->dev, "No platform data specified\n");
-	return ERR_PTR(-EINVAL);
+	return ERR_PTR(-ENOENT);
+}
+#endif
+
+#ifdef CONFIG_ACPI
+
+struct mxt_acpi_platform_data {
+	const char *hid;
+	struct mxt_platform_data pdata;
+};
+
+static unsigned int samus_touchpad_buttons[] = {
+	KEY_RESERVED,
+	KEY_RESERVED,
+	KEY_RESERVED,
+	BTN_LEFT
+};
+
+static struct mxt_acpi_platform_data samus_platform_data[] = {
+	{
+		/* Touchpad */
+		.hid	= "ATML0000",
+		.pdata	= {
+			.t19_num_keys	= ARRAY_SIZE(samus_touchpad_buttons),
+			.t19_keymap	= samus_touchpad_buttons,
+		},
+	},
+	{
+		/* Touchscreen */
+		.hid	= "ATML0001",
+	},
+	{ }
+};
+
+static const struct dmi_system_id mxt_dmi_table[] = {
+	{
+		/* 2015 Google Pixel */
+		.ident = "Chromebook Pixel 2",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
+		},
+		.driver_data = samus_platform_data,
+	},
+	{ }
+};
+
+static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client)
+{
+	struct acpi_device *adev;
+	const struct dmi_system_id *system_id;
+	const struct mxt_acpi_platform_data *acpi_pdata;
+
+	/*
+	 * Ignore ACPI devices representing bootloader mode.
+	 *
+	 * This is a bit of a hack: Google Chromebook BIOS creates ACPI
+	 * devices for both application and bootloader modes, but we are
+	 * interested in application mode only (if device is in bootloader
+	 * mode we'll end up switching into application anyway). So far
+	 * application mode addresses were all above 0x40, so we'll use it
+	 * as a threshold.
+	 */
+	if (client->addr < 0x40)
+		return ERR_PTR(-ENXIO);
+
+	adev = ACPI_COMPANION(&client->dev);
+	if (!adev)
+		return ERR_PTR(-ENOENT);
+
+	system_id = dmi_first_match(mxt_dmi_table);
+	if (!system_id)
+		return ERR_PTR(-ENOENT);
+
+	acpi_pdata = system_id->driver_data;
+	if (!acpi_pdata)
+		return ERR_PTR(-ENOENT);
+
+	while (acpi_pdata->hid) {
+		if (!strcmp(acpi_device_hid(adev), acpi_pdata->hid))
+			return &acpi_pdata->pdata;
+
+		acpi_pdata++;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+#else
+static const struct mxt_platform_data *mxt_parse_acpi(struct i2c_client *client)
+{
+	return ERR_PTR(-ENOENT);
 }
 #endif
 
+static const struct mxt_platform_data *
+mxt_get_platform_data(struct i2c_client *client)
+{
+	const struct mxt_platform_data *pdata;
+
+	pdata = dev_get_platdata(&client->dev);
+	if (pdata)
+		return pdata;
+
+	pdata = mxt_parse_dt(client);
+	if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT)
+		return pdata;
+
+	pdata = mxt_parse_acpi(client);
+	if (!IS_ERR(pdata) || PTR_ERR(pdata) != -ENOENT)
+		return pdata;
+
+	dev_err(&client->dev, "No platform data specified\n");
+	return ERR_PTR(-EINVAL);
+}
+
 static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct mxt_data *data;
 	const struct mxt_platform_data *pdata;
 	int error;
 
-	pdata = dev_get_platdata(&client->dev);
-	if (!pdata) {
-		pdata = mxt_parse_dt(client);
-		if (IS_ERR(pdata))
-			return PTR_ERR(pdata);
-	}
+	pdata = mxt_get_platform_data(client);
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
 
 	data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
 	if (!data) {
@@ -2536,6 +2645,15 @@ static const struct of_device_id mxt_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mxt_of_match);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id mxt_acpi_id[] = {
+	{ "ATML0000", 0 },	/* Touchpad */
+	{ "ATML0001", 0 },	/* Touchscreen */
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, mxt_acpi_id);
+#endif
+
 static const struct i2c_device_id mxt_id[] = {
 	{ "qt602240_ts", 0 },
 	{ "atmel_mxt_ts", 0 },
@@ -2550,6 +2668,7 @@ static struct i2c_driver mxt_driver = {
 		.name	= "atmel_mxt_ts",
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(mxt_of_match),
+		.acpi_match_table = ACPI_PTR(mxt_acpi_id),
 		.pm	= &mxt_pm_ops,
 	},
 	.probe		= mxt_probe,
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index 43b3c9c2d788..0efd766a545b 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -699,7 +699,7 @@ static int elants_i2c_fw_update(struct elants_data *ts)
 	char *fw_name;
 	int error;
 
-	fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%4x.bin", ts->hw_version);
+	fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version);
 	if (!fw_name)
 		return -ENOMEM;