Merge branch 'for-4.19/multitouch-multiaxis' into for-linus

Multitouch updates:

- Dial support
- Palm rejection for touchscreens
- a few small assorted fixes
diff --git a/Documentation/devicetree/bindings/input/hid-over-i2c.txt b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
index 4d3da9d..89e6ab8 100644
--- a/Documentation/devicetree/bindings/input/hid-over-i2c.txt
+++ b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
@@ -26,7 +26,8 @@
 
 - compatible:
   * "wacom,w9013" (Wacom W9013 digitizer). Supports:
-    - vdd-supply
+    - vdd-supply (3.3V)
+    - vddl-supply (1.8V)
     - post-power-on-delay-ms
 
 - vdd-supply: phandle of the regulator that provides the supply voltage.
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index a49a104..61e1953 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -207,6 +207,16 @@
 	- Vengeance K90
 	- Scimitar PRO RGB
 
+config HID_COUGAR
+	tristate "Cougar devices"
+	depends on HID
+	help
+	Support for Cougar devices that are not fully compliant with the
+	HID standard.
+
+	Supported devices:
+	- Cougar 500k Gaming Keyboard
+
 config HID_PRODIKEYS
 	tristate "Prodikeys PC-MIDI Keyboard support"
 	depends on HID && SND
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 511e1cb..bd7ac53 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -35,6 +35,7 @@
 obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
 obj-$(CONFIG_HID_CMEDIA)	+= hid-cmedia.o
 obj-$(CONFIG_HID_CORSAIR)	+= hid-corsair.o
+obj-$(CONFIG_HID_COUGAR)	+= hid-cougar.o
 obj-$(CONFIG_HID_CP2112)	+= hid-cp2112.o
 obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
 obj-$(CONFIG_HID_DRAGONRISE)	+= hid-dr.o
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 5de6f18..3da354a 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1950,6 +1950,29 @@ static int hid_bus_match(struct device *dev, struct device_driver *drv)
 	return hid_match_device(hdev, hdrv) != NULL;
 }
 
+/**
+ * hid_compare_device_paths - check if both devices share the same path
+ * @hdev_a: hid device
+ * @hdev_b: hid device
+ * @separator: char to use as separator
+ *
+ * Check if two devices share the same path up to the last occurrence of
+ * the separator char. Both paths must exist (i.e., zero-length paths
+ * don't match).
+ */
+bool hid_compare_device_paths(struct hid_device *hdev_a,
+			      struct hid_device *hdev_b, char separator)
+{
+	int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys;
+	int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys;
+
+	if (n1 != n2 || n1 <= 0 || n2 <= 0)
+		return false;
+
+	return !strncmp(hdev_a->phys, hdev_b->phys, n1);
+}
+EXPORT_SYMBOL_GPL(hid_compare_device_paths);
+
 static int hid_device_probe(struct device *dev)
 {
 	struct hid_driver *hdrv = to_hid_driver(dev->driver);
diff --git a/drivers/hid/hid-cougar.c b/drivers/hid/hid-cougar.c
new file mode 100644
index 0000000..ad2e87d
--- /dev/null
+++ b/drivers/hid/hid-cougar.c
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  HID driver for Cougar 500k Gaming Keyboard
+ *
+ *  Copyright (c) 2018 Daniel M. Lambea <dmlambea@gmail.com>
+ */
+
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+MODULE_AUTHOR("Daniel M. Lambea <dmlambea@gmail.com>");
+MODULE_DESCRIPTION("Cougar 500k Gaming Keyboard");
+MODULE_LICENSE("GPL");
+MODULE_INFO(key_mappings, "G1-G6 are mapped to F13-F18");
+
+static int cougar_g6_is_space = 1;
+module_param_named(g6_is_space, cougar_g6_is_space, int, 0600);
+MODULE_PARM_DESC(g6_is_space,
+	"If set, G6 programmable key sends SPACE instead of F18 (0=off, 1=on) (default=1)");
+
+
+#define COUGAR_VENDOR_USAGE	0xff00ff00
+
+#define COUGAR_FIELD_CODE	1
+#define COUGAR_FIELD_ACTION	2
+
+#define COUGAR_KEY_G1		0x83
+#define COUGAR_KEY_G2		0x84
+#define COUGAR_KEY_G3		0x85
+#define COUGAR_KEY_G4		0x86
+#define COUGAR_KEY_G5		0x87
+#define COUGAR_KEY_G6		0x78
+#define COUGAR_KEY_FN		0x0d
+#define COUGAR_KEY_MR		0x6f
+#define COUGAR_KEY_M1		0x80
+#define COUGAR_KEY_M2		0x81
+#define COUGAR_KEY_M3		0x82
+#define COUGAR_KEY_LEDS		0x67
+#define COUGAR_KEY_LOCK		0x6e
+
+
+/* Default key mappings. The special key COUGAR_KEY_G6 is defined first
+ * because it is more frequent to use the spacebar rather than any other
+ * special keys. Depending on the value of the parameter 'g6_is_space',
+ * the mapping will be updated in the probe function.
+ */
+static unsigned char cougar_mapping[][2] = {
+	{ COUGAR_KEY_G6,   KEY_SPACE },
+	{ COUGAR_KEY_G1,   KEY_F13 },
+	{ COUGAR_KEY_G2,   KEY_F14 },
+	{ COUGAR_KEY_G3,   KEY_F15 },
+	{ COUGAR_KEY_G4,   KEY_F16 },
+	{ COUGAR_KEY_G5,   KEY_F17 },
+	{ COUGAR_KEY_LOCK, KEY_SCREENLOCK },
+/* The following keys are handled by the hardware itself, so no special
+ * treatment is required:
+	{ COUGAR_KEY_FN, KEY_RESERVED },
+	{ COUGAR_KEY_MR, KEY_RESERVED },
+	{ COUGAR_KEY_M1, KEY_RESERVED },
+	{ COUGAR_KEY_M2, KEY_RESERVED },
+	{ COUGAR_KEY_M3, KEY_RESERVED },
+	{ COUGAR_KEY_LEDS, KEY_RESERVED },
+*/
+	{ 0, 0 },
+};
+
+struct cougar_shared {
+	struct list_head list;
+	struct kref kref;
+	bool enabled;
+	struct hid_device *dev;
+	struct input_dev *input;
+};
+
+struct cougar {
+	bool special_intf;
+	struct cougar_shared *shared;
+};
+
+static LIST_HEAD(cougar_udev_list);
+static DEFINE_MUTEX(cougar_udev_list_lock);
+
+static void cougar_fix_g6_mapping(struct hid_device *hdev)
+{
+	int i;
+
+	for (i = 0; cougar_mapping[i][0]; i++) {
+		if (cougar_mapping[i][0] == COUGAR_KEY_G6) {
+			cougar_mapping[i][1] =
+				cougar_g6_is_space ? KEY_SPACE : KEY_F18;
+			hid_info(hdev, "G6 mapped to %s\n",
+				 cougar_g6_is_space ? "space" : "F18");
+			return;
+		}
+	}
+	hid_warn(hdev, "no mapping defined for G6/spacebar");
+}
+
+/*
+ * Constant-friendly rdesc fixup for mouse interface
+ */
+static __u8 *cougar_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+				 unsigned int *rsize)
+{
+	if (rdesc[2] == 0x09 && rdesc[3] == 0x02 &&
+	    (rdesc[115] | rdesc[116] << 8) >= HID_MAX_USAGES) {
+		hid_info(hdev,
+			"usage count exceeds max: fixing up report descriptor\n");
+		rdesc[115] = ((HID_MAX_USAGES-1) & 0xff);
+		rdesc[116] = ((HID_MAX_USAGES-1) >> 8);
+	}
+	return rdesc;
+}
+
+static struct cougar_shared *cougar_get_shared_data(struct hid_device *hdev)
+{
+	struct cougar_shared *shared;
+
+	/* Try to find an already-probed interface from the same device */
+	list_for_each_entry(shared, &cougar_udev_list, list) {
+		if (hid_compare_device_paths(hdev, shared->dev, '/')) {
+			kref_get(&shared->kref);
+			return shared;
+		}
+	}
+	return NULL;
+}
+
+static void cougar_release_shared_data(struct kref *kref)
+{
+	struct cougar_shared *shared = container_of(kref,
+						    struct cougar_shared, kref);
+
+	mutex_lock(&cougar_udev_list_lock);
+	list_del(&shared->list);
+	mutex_unlock(&cougar_udev_list_lock);
+
+	kfree(shared);
+}
+
+static void cougar_remove_shared_data(void *resource)
+{
+	struct cougar *cougar = resource;
+
+	if (cougar->shared) {
+		kref_put(&cougar->shared->kref, cougar_release_shared_data);
+		cougar->shared = NULL;
+	}
+}
+
+/*
+ * Bind the device group's shared data to this cougar struct.
+ * If no shared data exists for this group, create and initialize it.
+ */
+static int cougar_bind_shared_data(struct hid_device *hdev, struct cougar *cougar)
+{
+	struct cougar_shared *shared;
+	int error = 0;
+
+	mutex_lock(&cougar_udev_list_lock);
+
+	shared = cougar_get_shared_data(hdev);
+	if (!shared) {
+		shared = kzalloc(sizeof(*shared), GFP_KERNEL);
+		if (!shared) {
+			error = -ENOMEM;
+			goto out;
+		}
+
+		kref_init(&shared->kref);
+		shared->dev = hdev;
+		list_add_tail(&shared->list, &cougar_udev_list);
+	}
+
+	cougar->shared = shared;
+
+	error = devm_add_action(&hdev->dev, cougar_remove_shared_data, cougar);
+	if (error) {
+		mutex_unlock(&cougar_udev_list_lock);
+		cougar_remove_shared_data(cougar);
+		return error;
+	}
+
+out:
+	mutex_unlock(&cougar_udev_list_lock);
+	return error;
+}
+
+static int cougar_probe(struct hid_device *hdev,
+			const struct hid_device_id *id)
+{
+	struct cougar *cougar;
+	struct hid_input *next, *hidinput = NULL;
+	unsigned int connect_mask;
+	int error;
+
+	cougar = devm_kzalloc(&hdev->dev, sizeof(*cougar), GFP_KERNEL);
+	if (!cougar)
+		return -ENOMEM;
+	hid_set_drvdata(hdev, cougar);
+
+	error = hid_parse(hdev);
+	if (error) {
+		hid_err(hdev, "parse failed\n");
+		goto fail;
+	}
+
+	if (hdev->collection->usage == COUGAR_VENDOR_USAGE) {
+		cougar->special_intf = true;
+		connect_mask = HID_CONNECT_HIDRAW;
+	} else
+		connect_mask = HID_CONNECT_DEFAULT;
+
+	error = hid_hw_start(hdev, connect_mask);
+	if (error) {
+		hid_err(hdev, "hw start failed\n");
+		goto fail;
+	}
+
+	error = cougar_bind_shared_data(hdev, cougar);
+	if (error)
+		goto fail_stop_and_cleanup;
+
+	/* The custom vendor interface will use the hid_input registered
+	 * for the keyboard interface, in order to send translated key codes
+	 * to it.
+	 */
+	if (hdev->collection->usage == HID_GD_KEYBOARD) {
+		cougar_fix_g6_mapping(hdev);
+		list_for_each_entry_safe(hidinput, next, &hdev->inputs, list) {
+			if (hidinput->registered && hidinput->input != NULL) {
+				cougar->shared->input = hidinput->input;
+				cougar->shared->enabled = true;
+				break;
+			}
+		}
+	} else if (hdev->collection->usage == COUGAR_VENDOR_USAGE) {
+		error = hid_hw_open(hdev);
+		if (error)
+			goto fail_stop_and_cleanup;
+	}
+	return 0;
+
+fail_stop_and_cleanup:
+	hid_hw_stop(hdev);
+fail:
+	hid_set_drvdata(hdev, NULL);
+	return error;
+}
+
+/*
+ * Convert events from vendor intf to input key events
+ */
+static int cougar_raw_event(struct hid_device *hdev, struct hid_report *report,
+			    u8 *data, int size)
+{
+	struct cougar *cougar;
+	unsigned char code, action;
+	int i;
+
+	cougar = hid_get_drvdata(hdev);
+	if (!cougar->special_intf || !cougar->shared ||
+	    !cougar->shared->input || !cougar->shared->enabled)
+		return 0;
+
+	code = data[COUGAR_FIELD_CODE];
+	action = data[COUGAR_FIELD_ACTION];
+	for (i = 0; cougar_mapping[i][0]; i++) {
+		if (code == cougar_mapping[i][0]) {
+			input_event(cougar->shared->input, EV_KEY,
+				    cougar_mapping[i][1], action);
+			input_sync(cougar->shared->input);
+			return 0;
+		}
+	}
+	hid_warn(hdev, "unmapped special key code %x: ignoring\n", code);
+	return 0;
+}
+
+static void cougar_remove(struct hid_device *hdev)
+{
+	struct cougar *cougar = hid_get_drvdata(hdev);
+
+	if (cougar) {
+		/* Stop the vendor intf to process more events */
+		if (cougar->shared)
+			cougar->shared->enabled = false;
+		if (cougar->special_intf)
+			hid_hw_close(hdev);
+	}
+	hid_hw_stop(hdev);
+}
+
+static struct hid_device_id cougar_id_table[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SOLID_YEAR,
+			 USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD) },
+	{}
+};
+MODULE_DEVICE_TABLE(hid, cougar_id_table);
+
+static struct hid_driver cougar_driver = {
+	.name			= "cougar",
+	.id_table		= cougar_id_table,
+	.report_fixup		= cougar_report_fixup,
+	.probe			= cougar_probe,
+	.remove			= cougar_remove,
+	.raw_event		= cougar_raw_event,
+};
+
+module_hid_driver(cougar_driver);
diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c
index 803a725..07e26c3 100644
--- a/drivers/hid/hid-elan.c
+++ b/drivers/hid/hid-elan.c
@@ -19,38 +19,49 @@
 
 #include "hid-ids.h"
 
+#define ELAN_MT_I2C		0x5d
 #define ELAN_SINGLE_FINGER	0x81
 #define ELAN_MT_FIRST_FINGER	0x82
 #define ELAN_MT_SECOND_FINGER	0x83
 #define ELAN_INPUT_REPORT_SIZE	8
+#define ELAN_I2C_REPORT_SIZE	32
+#define ELAN_FINGER_DATA_LEN	5
+#define ELAN_MAX_FINGERS	5
+#define ELAN_MAX_PRESSURE	255
+#define ELAN_TP_USB_INTF	1
+
+#define ELAN_FEATURE_REPORT	0x0d
+#define ELAN_FEATURE_SIZE	5
+#define ELAN_PARAM_MAX_X	6
+#define ELAN_PARAM_MAX_Y	7
+#define ELAN_PARAM_RES		8
 
 #define ELAN_MUTE_LED_REPORT	0xBC
 #define ELAN_LED_REPORT_SIZE	8
 
-struct elan_touchpad_settings {
-	u8 max_fingers;
-	u16 max_x;
-	u16 max_y;
-	u8 max_area_x;
-	u8 max_area_y;
-	u8 max_w;
-	int usb_bInterfaceNumber;
-};
+#define ELAN_HAS_LED		BIT(0)
 
 struct elan_drvdata {
 	struct input_dev *input;
 	u8 prev_report[ELAN_INPUT_REPORT_SIZE];
 	struct led_classdev mute_led;
 	u8 mute_led_state;
-	struct elan_touchpad_settings *settings;
+	u16 max_x;
+	u16 max_y;
+	u16 res_x;
+	u16 res_y;
 };
 
 static int is_not_elan_touchpad(struct hid_device *hdev)
 {
-	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-	struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+	if (hdev->bus == BUS_USB) {
+		struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
 
-	return (intf->altsetting->desc.bInterfaceNumber != drvdata->settings->usb_bInterfaceNumber);
+		return (intf->altsetting->desc.bInterfaceNumber !=
+			ELAN_TP_USB_INTF);
+	}
+
+	return 0;
 }
 
 static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -62,12 +73,86 @@ static int elan_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 
 	if (field->report->id == ELAN_SINGLE_FINGER ||
 	    field->report->id == ELAN_MT_FIRST_FINGER ||
-	    field->report->id == ELAN_MT_SECOND_FINGER)
+	    field->report->id == ELAN_MT_SECOND_FINGER ||
+	    field->report->id == ELAN_MT_I2C)
 		return -1;
 
 	return 0;
 }
 
+static int elan_get_device_param(struct hid_device *hdev,
+				 unsigned char *dmabuf, unsigned char param)
+{
+	int ret;
+
+	dmabuf[0] = ELAN_FEATURE_REPORT;
+	dmabuf[1] = 0x05;
+	dmabuf[2] = 0x03;
+	dmabuf[3] = param;
+	dmabuf[4] = 0x01;
+
+	ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf,
+				 ELAN_FEATURE_SIZE, HID_FEATURE_REPORT,
+				 HID_REQ_SET_REPORT);
+	if (ret != ELAN_FEATURE_SIZE) {
+		hid_err(hdev, "Set report error for parm %d: %d\n", param, ret);
+		return ret;
+	}
+
+	ret = hid_hw_raw_request(hdev, ELAN_FEATURE_REPORT, dmabuf,
+				 ELAN_FEATURE_SIZE, HID_FEATURE_REPORT,
+				 HID_REQ_GET_REPORT);
+	if (ret != ELAN_FEATURE_SIZE) {
+		hid_err(hdev, "Get report error for parm %d: %d\n", param, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static unsigned int elan_convert_res(char val)
+{
+	/*
+	 * (value from firmware) * 10 + 790 = dpi
+	 * dpi * 10 / 254 = dots/mm
+	 */
+	return (val * 10 + 790) * 10 / 254;
+}
+
+static int elan_get_device_params(struct hid_device *hdev)
+{
+	struct elan_drvdata *drvdata = hid_get_drvdata(hdev);
+	unsigned char *dmabuf;
+	int ret;
+
+	dmabuf = kmalloc(ELAN_FEATURE_SIZE, GFP_KERNEL);
+	if (!dmabuf)
+		return -ENOMEM;
+
+	ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_X);
+	if (ret)
+		goto err;
+
+	drvdata->max_x = (dmabuf[4] << 8) | dmabuf[3];
+
+	ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_MAX_Y);
+	if (ret)
+		goto err;
+
+	drvdata->max_y = (dmabuf[4] << 8) | dmabuf[3];
+
+	ret = elan_get_device_param(hdev, dmabuf, ELAN_PARAM_RES);
+	if (ret)
+		goto err;
+
+	drvdata->res_x = elan_convert_res(dmabuf[3]);
+	drvdata->res_y = elan_convert_res(dmabuf[4]);
+
+err:
+	kfree(dmabuf);
+	return ret;
+}
+
 static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
 {
 	int ret;
@@ -77,6 +162,10 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
 	if (is_not_elan_touchpad(hdev))
 		return 0;
 
+	ret = elan_get_device_params(hdev);
+	if (ret)
+		return ret;
+
 	input = devm_input_allocate_device(&hdev->dev);
 	if (!input)
 		return -ENOMEM;
@@ -90,25 +179,25 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
 	input->id.version = hdev->version;
 	input->dev.parent = &hdev->dev;
 
-	input_set_abs_params(input, ABS_MT_POSITION_X, 0,
-			     drvdata->settings->max_x, 0, 0);
-	input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
-			     drvdata->settings->max_y, 0, 0);
-	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
-			     drvdata->settings->max_fingers, 0, 0);
-	input_set_abs_params(input, ABS_TOOL_WIDTH, 0,
-			     drvdata->settings->max_w, 0, 0);
+	input_set_abs_params(input, ABS_MT_POSITION_X, 0, drvdata->max_x,
+			     0, 0);
+	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, drvdata->max_y,
+			     0, 0);
+	input_set_abs_params(input, ABS_MT_PRESSURE, 0, ELAN_MAX_PRESSURE,
+			     0, 0);
 
 	__set_bit(BTN_LEFT, input->keybit);
 	__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
 
-	ret = input_mt_init_slots(input, drvdata->settings->max_fingers,
-				  INPUT_MT_POINTER);
+	ret = input_mt_init_slots(input, ELAN_MAX_FINGERS, INPUT_MT_POINTER);
 	if (ret) {
 		hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
 		return ret;
 	}
 
+	input_abs_set_res(input, ABS_X, drvdata->res_x);
+	input_abs_set_res(input, ABS_Y, drvdata->res_y);
+
 	ret = input_register_device(input);
 	if (ret) {
 		hid_err(hdev, "Failed to register elan input device: %d\n",
@@ -126,7 +215,7 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
 				unsigned int slot_num)
 {
 	struct input_dev *input = drvdata->input;
-	int x, y, w;
+	int x, y, p;
 
 	bool active = !!data;
 
@@ -134,17 +223,17 @@ static void elan_report_mt_slot(struct elan_drvdata *drvdata, u8 *data,
 	input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
 	if (active) {
 		x = ((data[0] & 0xF0) << 4) | data[1];
-		y = drvdata->settings->max_y -
+		y = drvdata->max_y -
 		    (((data[0] & 0x07) << 8) | data[2]);
-		w = data[4];
+		p = data[4];
 
 		input_report_abs(input, ABS_MT_POSITION_X, x);
 		input_report_abs(input, ABS_MT_POSITION_Y, y);
-		input_report_abs(input, ABS_TOOL_WIDTH, w);
+		input_report_abs(input, ABS_MT_PRESSURE, p);
 	}
 }
 
-static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
+static void elan_usb_report_input(struct elan_drvdata *drvdata, u8 *data)
 {
 	int i;
 	struct input_dev *input = drvdata->input;
@@ -162,7 +251,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
 	 * byte 5: x8  x7  x6  x5  x4  x3  x2  x1
 	 * byte 6: y8  y7  y6  y5  y4  y3  y2  y1
 	 * byte 7: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
-	 * byte 8: w8  w7  w6  w5  w4  w3  w2  w1
+	 * byte 8: p8  p7  p6  p5  p4  p3  p2  p1
 	 *
 	 * packet structure for ELAN_MT_SECOND_FINGER:
 	 *
@@ -171,19 +260,21 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
 	 * byte 3: x8  x7  x6  x5  x4  x3  x2  x1
 	 * byte 4: y8  y7  y6  y5  y4  y3  y2  y1
 	 * byte 5: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
-	 * byte 6: w8  w7  w6  w5  w4  w3  w2  w1
+	 * byte 6: p8  p7  p6  p5  p4  p3  p2  p1
 	 * byte 7: 0   0   0   0   0   0   0   0
 	 * byte 8: 0   0   0   0   0   0   0   0
 	 *
 	 * f5-f1: finger touch bits
 	 * L: clickpad button
-	 * sy / sx: not sure yet, but this looks like rectangular
-	 * area for finger
-	 * w: looks like finger width
+	 * sy / sx: finger width / height expressed in traces, the total number
+	 *          of traces can be queried by doing a HID_REQ_SET_REPORT
+	 *          { 0x0d, 0x05, 0x03, 0x05, 0x01 } followed by a GET, in the
+	 *          returned buf, buf[3]=no-x-traces, buf[4]=no-y-traces.
+	 * p: pressure
 	 */
 
 	if (data[0] == ELAN_SINGLE_FINGER) {
-		for (i = 0; i < drvdata->settings->max_fingers; i++) {
+		for (i = 0; i < ELAN_MAX_FINGERS; i++) {
 			if (data[2] & BIT(i + 3))
 				elan_report_mt_slot(drvdata, data + 3, i);
 			else
@@ -210,7 +301,7 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
 		if (prev_report[0] != ELAN_MT_FIRST_FINGER)
 			return;
 
-		for (i = 0; i < drvdata->settings->max_fingers; i++) {
+		for (i = 0; i < ELAN_MAX_FINGERS; i++) {
 			if (prev_report[2] & BIT(i + 3)) {
 				if (!first) {
 					first = 1;
@@ -229,6 +320,46 @@ static void elan_report_input(struct elan_drvdata *drvdata, u8 *data)
 	input_sync(input);
 }
 
+static void elan_i2c_report_input(struct elan_drvdata *drvdata, u8 *data)
+{
+	struct input_dev *input = drvdata->input;
+	u8 *finger_data;
+	int i;
+
+	/*
+	 * Elan MT touchpads in i2c mode send finger data in the same format
+	 * as in USB mode, but then with all fingers in a single packet.
+	 *
+	 * packet structure for ELAN_MT_I2C:
+	 *
+	 * byte     1: 1   0   0   1   1   1   0   1   // 0x5d
+	 * byte     2: f5  f4  f3  f2  f1  0   0   L
+	 * byte     3: x12 x11 x10 x9  0?  y11 y10 y9
+	 * byte     4: x8  x7  x6  x5  x4  x3  x2  x1
+	 * byte     5: y8  y7  y6  y5  y4  y3  y2  y1
+	 * byte     6: sy4 sy3 sy2 sy1 sx4 sx3 sx2 sx1
+	 * byte     7: p8  p7  p6  p5  p4  p3  p2  p1
+	 * byte  8-12: Same as byte 3-7 for second finger down
+	 * byte 13-17: Same as byte 3-7 for third finger down
+	 * byte 18-22: Same as byte 3-7 for fourth finger down
+	 * byte 23-27: Same as byte 3-7 for fifth finger down
+	 */
+
+	finger_data = data + 2;
+	for (i = 0; i < ELAN_MAX_FINGERS; i++) {
+		if (data[1] & BIT(i + 3)) {
+			elan_report_mt_slot(drvdata, finger_data, i);
+			finger_data += ELAN_FINGER_DATA_LEN;
+		} else {
+			elan_report_mt_slot(drvdata, NULL, i);
+		}
+	}
+
+	input_report_key(input, BTN_LEFT, data[1] & 0x01);
+	input_mt_sync_frame(input);
+	input_sync(input);
+}
+
 static int elan_raw_event(struct hid_device *hdev,
 			  struct hid_report *report, u8 *data, int size)
 {
@@ -241,11 +372,16 @@ static int elan_raw_event(struct hid_device *hdev,
 	    data[0] == ELAN_MT_FIRST_FINGER ||
 	    data[0] == ELAN_MT_SECOND_FINGER) {
 		if (size == ELAN_INPUT_REPORT_SIZE) {
-			elan_report_input(drvdata, data);
+			elan_usb_report_input(drvdata, data);
 			return 1;
 		}
 	}
 
+	if (data[0] == ELAN_MT_I2C && size == ELAN_I2C_REPORT_SIZE) {
+		elan_i2c_report_input(drvdata, data);
+		return 1;
+	}
+
 	return 0;
 }
 
@@ -343,7 +479,6 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (!drvdata)
 		return -ENOMEM;
 
-	drvdata->settings = (struct elan_touchpad_settings *)id->driver_data;
 	hid_set_drvdata(hdev, drvdata);
 
 	ret = hid_parse(hdev);
@@ -371,9 +506,11 @@ static int elan_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	if (ret)
 		goto err;
 
-	ret = elan_init_mute_led(hdev);
-	if (ret)
-		goto err;
+	if (id->driver_data & ELAN_HAS_LED) {
+		ret = elan_init_mute_led(hdev);
+		if (ret)
+			goto err;
+	}
 
 	return 0;
 err:
@@ -386,22 +523,14 @@ static void elan_remove(struct hid_device *hdev)
 	hid_hw_stop(hdev);
 }
 
-static const struct elan_touchpad_settings hp_x2_10_touchpad_data = {
-	.max_fingers = 5,
-	.max_x = 2930,
-	.max_y = 1250,
-	.max_area_x = 15,
-	.max_area_y = 15,
-	.max_w = 255,
-	.usb_bInterfaceNumber = 1,
-};
-
 static const struct hid_device_id elan_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2),
+	  .driver_data = ELAN_HAS_LED },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2_10_COVER),
-		(kernel_ulong_t)&hp_x2_10_touchpad_data},
+	  .driver_data = ELAN_HAS_LED },
+	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_TOSHIBA_CLICK_L9W) },
 	{ }
 };
-
 MODULE_DEVICE_TABLE(hid, elan_devices);
 
 static struct hid_driver elan_driver = {
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index c7981dd..79bdf0c 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -369,6 +369,8 @@
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001	0xa001
 
 #define USB_VENDOR_ID_ELAN		0x04f3
+#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W	0x0401
+#define USB_DEVICE_ID_HP_X2		0x074d
 #define USB_DEVICE_ID_HP_X2_10_COVER	0x0755
 
 #define USB_VENDOR_ID_ELECOM		0x056e
@@ -1001,6 +1003,9 @@
 #define USB_VENDOR_ID_SINO_LITE			0x1345
 #define USB_DEVICE_ID_SINO_LITE_CONTROLLER	0x3008
 
+#define USB_VENDOR_ID_SOLID_YEAR			0x060b
+#define USB_DEVICE_ID_COUGAR_500K_GAMING_KEYBOARD	0x500a
+
 #define USB_VENDOR_ID_SOUNDGRAPH	0x15c2
 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_FIRST	0x0034
 #define USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST	0x0046
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index eae0cb3..2ce194a 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -1002,18 +1002,18 @@ static int i2c_hid_probe(struct i2c_client *client,
 		return client->irq;
 	}
 
-	ihid = kzalloc(sizeof(struct i2c_hid), GFP_KERNEL);
+	ihid = devm_kzalloc(&client->dev, sizeof(*ihid), GFP_KERNEL);
 	if (!ihid)
 		return -ENOMEM;
 
 	if (client->dev.of_node) {
 		ret = i2c_hid_of_probe(client, &ihid->pdata);
 		if (ret)
-			goto err;
+			return ret;
 	} else if (!platform_data) {
 		ret = i2c_hid_acpi_pdata(client, &ihid->pdata);
 		if (ret)
-			goto err;
+			return ret;
 	} else {
 		ihid->pdata = *platform_data;
 	}
@@ -1021,21 +1021,20 @@ static int i2c_hid_probe(struct i2c_client *client,
 	/* Parse platform agnostic common properties from ACPI / device tree */
 	i2c_hid_fwnode_probe(client, &ihid->pdata);
 
-	ihid->pdata.supply = devm_regulator_get(&client->dev, "vdd");
-	if (IS_ERR(ihid->pdata.supply)) {
-		ret = PTR_ERR(ihid->pdata.supply);
-		if (ret != -EPROBE_DEFER)
-			dev_err(&client->dev, "Failed to get regulator: %d\n",
-				ret);
-		goto err;
-	}
+	ihid->pdata.supplies[0].supply = "vdd";
+	ihid->pdata.supplies[1].supply = "vddl";
 
-	ret = regulator_enable(ihid->pdata.supply);
-	if (ret < 0) {
-		dev_err(&client->dev, "Failed to enable regulator: %d\n",
-			ret);
-		goto err;
-	}
+	ret = devm_regulator_bulk_get(&client->dev,
+				      ARRAY_SIZE(ihid->pdata.supplies),
+				      ihid->pdata.supplies);
+	if (ret)
+		return ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ihid->pdata.supplies),
+				    ihid->pdata.supplies);
+	if (ret < 0)
+		return ret;
+
 	if (ihid->pdata.post_power_delay_ms)
 		msleep(ihid->pdata.post_power_delay_ms);
 
@@ -1122,11 +1121,9 @@ static int i2c_hid_probe(struct i2c_client *client,
 	pm_runtime_disable(&client->dev);
 
 err_regulator:
-	regulator_disable(ihid->pdata.supply);
-
-err:
+	regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
+			       ihid->pdata.supplies);
 	i2c_hid_free_buffers(ihid);
-	kfree(ihid);
 	return ret;
 }
 
@@ -1148,9 +1145,8 @@ static int i2c_hid_remove(struct i2c_client *client)
 	if (ihid->bufsize)
 		i2c_hid_free_buffers(ihid);
 
-	regulator_disable(ihid->pdata.supply);
-
-	kfree(ihid);
+	regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
+			       ihid->pdata.supplies);
 
 	return 0;
 }
@@ -1201,9 +1197,8 @@ static int i2c_hid_suspend(struct device *dev)
 			hid_warn(hid, "Failed to enable irq wake: %d\n",
 				wake_status);
 	} else {
-		ret = regulator_disable(ihid->pdata.supply);
-		if (ret < 0)
-			hid_warn(hid, "Failed to disable supply: %d\n", ret);
+		regulator_bulk_disable(ARRAY_SIZE(ihid->pdata.supplies),
+				       ihid->pdata.supplies);
 	}
 
 	return 0;
@@ -1218,9 +1213,11 @@ static int i2c_hid_resume(struct device *dev)
 	int wake_status;
 
 	if (!device_may_wakeup(&client->dev)) {
-		ret = regulator_enable(ihid->pdata.supply);
-		if (ret < 0)
-			hid_warn(hid, "Failed to enable supply: %d\n", ret);
+		ret = regulator_bulk_enable(ARRAY_SIZE(ihid->pdata.supplies),
+					    ihid->pdata.supplies);
+		if (ret)
+			hid_warn(hid, "Failed to enable supplies: %d\n", ret);
+
 		if (ihid->pdata.post_power_delay_ms)
 			msleep(ihid->pdata.post_power_delay_ms);
 	} else if (ihid->irq_wake_enabled) {
diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c
index 9a60ec1..bfbca7ec 100644
--- a/drivers/hid/intel-ish-hid/ipc/ipc.c
+++ b/drivers/hid/intel-ish-hid/ipc/ipc.c
@@ -907,8 +907,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
 	struct ishtp_device *dev;
 	int	i;
 
-	dev = kzalloc(sizeof(struct ishtp_device) + sizeof(struct ish_hw),
-		GFP_KERNEL);
+	dev = devm_kzalloc(&pdev->dev,
+			   sizeof(struct ishtp_device) + sizeof(struct ish_hw),
+			   GFP_KERNEL);
 	if (!dev)
 		return NULL;
 
@@ -925,7 +926,9 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
 	for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) {
 		struct wr_msg_ctl_info	*tx_buf;
 
-		tx_buf = kzalloc(sizeof(struct wr_msg_ctl_info), GFP_KERNEL);
+		tx_buf = devm_kzalloc(&pdev->dev,
+				      sizeof(struct wr_msg_ctl_info),
+				      GFP_KERNEL);
 		if (!tx_buf) {
 			/*
 			 * IPC buffers may be limited or not available
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index a2c53ea..050f987 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -95,6 +95,13 @@ static int ish_init(struct ishtp_device *dev)
 	return 0;
 }
 
+static const struct pci_device_id ish_invalid_pci_ids[] = {
+	/* Mehlow platform special pci ids */
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA309)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xA30A)},
+	{}
+};
+
 /**
  * ish_probe() - PCI driver probe callback
  * @pdev:	pci device
@@ -110,6 +117,10 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	struct ish_hw *hw;
 	int	ret;
 
+	/* Check for invalid platforms for ISH support */
+	if (pci_dev_present(ish_invalid_pci_ids))
+		return -ENODEV;
+
 	/* enable pci dev */
 	ret = pci_enable_device(pdev);
 	if (ret) {
@@ -172,7 +183,6 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	free_irq(pdev->irq, dev);
 free_device:
 	pci_iounmap(pdev, hw->mem_addr);
-	kfree(dev);
 release_regions:
 	pci_release_regions(pdev);
 disable_device:
@@ -202,7 +212,6 @@ static void ish_remove(struct pci_dev *pdev)
 	pci_release_regions(pdev);
 	pci_clear_master(pdev);
 	pci_disable_device(pdev);
-	kfree(ishtp_dev);
 }
 
 static struct device __maybe_unused *ish_resume_device;
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index d679753..ffe59a1 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -703,18 +703,6 @@ struct wacom_hdev_data {
 static LIST_HEAD(wacom_udev_list);
 static DEFINE_MUTEX(wacom_udev_list_lock);
 
-static bool compare_device_paths(struct hid_device *hdev_a,
-		struct hid_device *hdev_b, char separator)
-{
-	int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys;
-	int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys;
-
-	if (n1 != n2 || n1 <= 0 || n2 <= 0)
-		return false;
-
-	return !strncmp(hdev_a->phys, hdev_b->phys, n1);
-}
-
 static bool wacom_are_sibling(struct hid_device *hdev,
 		struct hid_device *sibling)
 {
@@ -737,10 +725,10 @@ static bool wacom_are_sibling(struct hid_device *hdev,
 	 * the same physical parent device path.
 	 */
 	if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) {
-		if (!compare_device_paths(hdev, sibling, '/'))
+		if (!hid_compare_device_paths(hdev, sibling, '/'))
 			return false;
 	} else {
-		if (!compare_device_paths(hdev, sibling, '.'))
+		if (!hid_compare_device_paths(hdev, sibling, '.'))
 			return false;
 	}
 
@@ -787,7 +775,7 @@ static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
 
 	/* Try to find an already-probed interface from the same device */
 	list_for_each_entry(data, &wacom_udev_list, list) {
-		if (compare_device_paths(hdev, data->dev, '/')) {
+		if (hid_compare_device_paths(hdev, data->dev, '/')) {
 			kref_get(&data->kref);
 			return data;
 		}
diff --git a/include/linux/hid.h b/include/linux/hid.h
index aee2815..834e646 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -901,6 +901,8 @@ const struct hid_device_id *hid_match_id(const struct hid_device *hdev,
 					 const struct hid_device_id *id);
 const struct hid_device_id *hid_match_device(struct hid_device *hdev,
 					     struct hid_driver *hdrv);
+bool hid_compare_device_paths(struct hid_device *hdev_a,
+			      struct hid_device *hdev_b, char separator);
 s32 hid_snto32(__u32 value, unsigned n);
 __u32 hid_field_extract(const struct hid_device *hid, __u8 *report,
 		     unsigned offset, unsigned n);
diff --git a/include/linux/platform_data/i2c-hid.h b/include/linux/platform_data/i2c-hid.h
index 1fb0882..c628bb5 100644
--- a/include/linux/platform_data/i2c-hid.h
+++ b/include/linux/platform_data/i2c-hid.h
@@ -12,14 +12,13 @@
 #ifndef __LINUX_I2C_HID_H
 #define __LINUX_I2C_HID_H
 
+#include <linux/regulator/consumer.h>
 #include <linux/types.h>
 
-struct regulator;
-
 /**
  * struct i2chid_platform_data - used by hid over i2c implementation.
  * @hid_descriptor_address: i2c register where the HID descriptor is stored.
- * @supply: regulator for powering on the device.
+ * @supplies: regulators for powering on the device.
  * @post_power_delay_ms: delay after powering on before device is usable.
  *
  * Note that it is the responsibility of the platform driver (or the acpi 5.0
@@ -35,7 +34,7 @@ struct regulator;
  */
 struct i2c_hid_platform_data {
 	u16 hid_descriptor_address;
-	struct regulator *supply;
+	struct regulator_bulk_data supplies[2];
 	int post_power_delay_ms;
 };