Sfoglia il codice sorgente

removing outdated patches

Jake Day 6 anni fa
parent
commit
9619f63485

+ 0 - 211
patches/4.14/acpica.patch

@@ -1,211 +0,0 @@
-diff --git a/drivers/acpi/acpica/dbdisply.c b/drivers/acpi/acpica/dbdisply.c
-index 5a606ea..7b5eb33 100644
---- a/drivers/acpi/acpica/dbdisply.c
-+++ b/drivers/acpi/acpica/dbdisply.c
-@@ -642,9 +642,8 @@ void acpi_db_display_object_type(char *object_arg)
- 		return;
- 	}
- 
--	acpi_os_printf("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n",
--		       ACPI_FORMAT_UINT64(info->address),
--		       info->current_status, info->flags);
-+	acpi_os_printf("ADR: %8.8X%8.8X, Flags: %X\n",
-+		       ACPI_FORMAT_UINT64(info->address), info->flags);
- 
- 	acpi_os_printf("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n",
- 		       info->highest_dstates[0], info->highest_dstates[1],
-diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c
-index d3b6b31..37b0b4c 100644
---- a/drivers/acpi/acpica/evevent.c
-+++ b/drivers/acpi/acpica/evevent.c
-@@ -204,6 +204,7 @@ u32 acpi_ev_fixed_event_detect(void)
- 	u32 fixed_status;
- 	u32 fixed_enable;
- 	u32 i;
-+	acpi_status status;
- 
- 	ACPI_FUNCTION_NAME(ev_fixed_event_detect);
- 
-@@ -211,8 +212,12 @@ u32 acpi_ev_fixed_event_detect(void)
- 	 * Read the fixed feature status and enable registers, as all the cases
- 	 * depend on their values. Ignore errors here.
- 	 */
--	(void)acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
--	(void)acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
-+	status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
-+	status |=
-+	    acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
-+	if (ACPI_FAILURE(status)) {
-+		return (int_status);
-+	}
- 
- 	ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
- 			  "Fixed Event Block: Enable %08X Status %08X\n",
-diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c
-index a8191d2..2ad13d8 100644
---- a/drivers/acpi/acpica/exdebug.c
-+++ b/drivers/acpi/acpica/exdebug.c
-@@ -88,14 +88,13 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
- 		return_VOID;
- 	}
- 
--	/* Null string or newline -- don't emit the line header */
-+	/* Newline -- don't emit the line header */
- 
- 	if (source_desc &&
- 	    (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) &&
- 	    (source_desc->common.type == ACPI_TYPE_STRING)) {
--		if ((source_desc->string.length == 0) ||
--		    ((source_desc->string.length == 1) &&
--		     (*source_desc->string.pointer == '\n'))) {
-+		if ((source_desc->string.length == 1) &&
-+		    (*source_desc->string.pointer == '\n')) {
- 			acpi_os_printf("\n");
- 			return_VOID;
- 		}
-diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c
-index 5026594..573a5f3 100644
---- a/drivers/acpi/acpica/nsdumpdv.c
-+++ b/drivers/acpi/acpica/nsdumpdv.c
-@@ -88,10 +88,9 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
- 		}
- 
- 		ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES,
--				      "    HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
-+				      "    HID: %s, ADR: %8.8X%8.8X\n",
- 				      info->hardware_id.value,
--				      ACPI_FORMAT_UINT64(info->address),
--				      info->current_status));
-+				      ACPI_FORMAT_UINT64(info->address));
- 		ACPI_FREE(info);
- 	}
- 
-diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
-index 1069662..0a9c600 100644
---- a/drivers/acpi/acpica/nsxfname.c
-+++ b/drivers/acpi/acpica/nsxfname.c
-@@ -241,7 +241,7 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
-  *              namespace node and possibly by running several standard
-  *              control methods (Such as in the case of a device.)
-  *
-- * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
-+ * For Device and Processor objects, run the Device _HID, _UID, _CID,
-  * _CLS, _ADR, _sx_w, and _sx_d methods.
-  *
-  * Note: Allocates the return buffer, must be freed by the caller.
-@@ -250,8 +250,9 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
-  * discovery namespace traversal. Therefore, no complex methods can be
-  * executed, especially those that access operation regions. Therefore, do
-  * not add any additional methods that could cause problems in this area.
-- * this was the fate of the _SUB method which was found to cause such
-- * problems and was removed (11/2015).
-+ * Because of this reason support for the following methods has been removed:
-+ * 1) _SUB method was removed (11/2015)
-+ * 2) _STA method was removed (02/2018)
-  *
-  ******************************************************************************/
- 
-@@ -374,20 +375,8 @@ acpi_get_object_info(acpi_handle handle,
- 		 * Notes: none of these methods are required, so they may or may
- 		 * not be present for this device. The Info->Valid bitfield is used
- 		 * to indicate which methods were found and run successfully.
--		 *
--		 * For _STA, if the method does not exist, then (as per the ACPI
--		 * specification), the returned current_status flags will indicate
--		 * that the device is present/functional/enabled. Otherwise, the
--		 * current_status flags reflect the value returned from _STA.
- 		 */
- 
--		/* Execute the Device._STA method */
--
--		status = acpi_ut_execute_STA(node, &info->current_status);
--		if (ACPI_SUCCESS(status)) {
--			valid |= ACPI_VALID_STA;
--		}
--
- 		/* Execute the Device._ADR method */
- 
- 		status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
-diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
-index eb9dfac..11ce4e5 100644
---- a/drivers/acpi/acpica/psargs.c
-+++ b/drivers/acpi/acpica/psargs.c
-@@ -890,6 +890,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
- 						      ACPI_POSSIBLE_METHOD_CALL);
- 
- 			if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) {
-+
-+				/* Free method call op and corresponding namestring sub-ob */
-+
-+				acpi_ps_free_op(arg->common.value.arg);
- 				acpi_ps_free_op(arg);
- 				arg = NULL;
- 				walk_state->arg_count = 1;
-diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
-index b6d58cc..5c00e5e 100644
---- a/drivers/acpi/bus.c
-+++ b/drivers/acpi/bus.c
-@@ -135,6 +135,7 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle,
- 	}
- 	return status;
- }
-+EXPORT_SYMBOL_GPL(acpi_bus_get_status_handle);
- 
- int acpi_bus_get_status(struct acpi_device *device)
- {
-@@ -146,6 +147,12 @@ int acpi_bus_get_status(struct acpi_device *device)
- 		return 0;
- 	}
- 
-+	/* Battery devices must have their deps met before calling _STA */
-+	if (acpi_device_is_battery(device) && device->dep_unmet) {
-+		acpi_set_device_status(device, 0);
-+		return 0;
-+	}
-+
- 	status = acpi_bus_get_status_handle(device->handle, &sta);
- 	if (ACPI_FAILURE(status))
- 		return -ENODEV;
-diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
-index 984c7e8..8472c4a 100644
---- a/drivers/pci/hotplug/acpiphp_ibm.c
-+++ b/drivers/pci/hotplug/acpiphp_ibm.c
-@@ -399,6 +399,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
- 		u32 lvl, void *context, void **rv)
- {
- 	acpi_handle *phandle = (acpi_handle *)context;
-+	unsigned long long current_status = 0;
- 	acpi_status status;
- 	struct acpi_device_info *info;
- 	int retval = 0;
-@@ -410,7 +411,9 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
- 		return retval;
- 	}
- 
--	if (info->current_status && (info->valid & ACPI_VALID_HID) &&
-+	acpi_bus_get_status_handle(handle, &current_status);
-+
-+	if (current_status && (info->valid & ACPI_VALID_HID) &&
- 			(!strcmp(info->hardware_id.string, IBM_HARDWARE_ID1) ||
- 			 !strcmp(info->hardware_id.string, IBM_HARDWARE_ID2))) {
- 		pr_debug("found hardware: %s, handle: %p\n",
-diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
-index 4f077ed..220ef86 100644
---- a/include/acpi/actypes.h
-+++ b/include/acpi/actypes.h
-@@ -1191,7 +1191,6 @@ struct acpi_device_info {
- 	u8 flags;		/* Miscellaneous info */
- 	u8 highest_dstates[4];	/* _sx_d values: 0xFF indicates not valid */
- 	u8 lowest_dstates[5];	/* _sx_w values: 0xFF indicates not valid */
--	u32 current_status;	/* _STA value */
- 	u64 address;	/* _ADR value */
- 	struct acpi_pnp_device_id hardware_id;	/* _HID value */
- 	struct acpi_pnp_device_id unique_id;	/* _UID value */
-@@ -1205,7 +1204,6 @@ struct acpi_device_info {
- 
- /* Flags for Valid field above (acpi_get_object_info) */
- 
--#define ACPI_VALID_STA                  0x0001
- #define ACPI_VALID_ADR                  0x0002
- #define ACPI_VALID_HID                  0x0004
- #define ACPI_VALID_UID                  0x0008

+ 0 - 151
patches/4.14/cameras.patch

@@ -1,151 +0,0 @@
-From d4460b8c7124d6dd878acbd3207e2c41ceec5266 Mon Sep 17 00:00:00 2001
-From: Jake Day <jake@ninebysix.com>
-Date: Thu, 1 Feb 2018 19:25:08 -0500
-Subject: initial support for surface cameras
-
-
-diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
-index 6d22b22..b72b782 100644
---- a/drivers/media/usb/uvc/uvc_driver.c
-+++ b/drivers/media/usb/uvc/uvc_driver.c
-@@ -2277,6 +2277,46 @@ MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
-  * though they are compliant.
-  */
- static const struct usb_device_id uvc_ids[] = {
-+	/* Microsoft Surface Pro 3 Front */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x07be,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Pro 3 Rear */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x07bf,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Pro 4 Cam */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x090c,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Book Cam 1 */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x090b,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Book Cam 2 */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x091a,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
- 	/* LogiLink Wireless Webcam */
- 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
- 				| USB_DEVICE_ID_MATCH_INT_INFO,
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/Kconfig b/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-index 9fb1bff..3954b8c 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-@@ -1,6 +1,6 @@
- config VIDEO_OV5693
-        tristate "Omnivision ov5693 sensor support"
--       depends on I2C && VIDEO_V4L2
-+       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
-        ---help---
-          This is a Video4Linux2 sensor-level driver for the Micron
-          ov5693 5 Mpixel camera.
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.c
-index 1236425..37986f5 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.c
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.c
-@@ -1332,7 +1332,7 @@ static int power_ctrl(struct v4l2_subdev *sd, bool flag)
- 
- static int gpio_ctrl(struct v4l2_subdev *sd, bool flag)
- {
--	int ret;
-+	int ret = 0;
- 	struct ov5693_device *dev = to_ov5693_sensor(sd);
- 
- 	if (!dev || !dev->platform_data)
-@@ -1342,7 +1342,8 @@ static int gpio_ctrl(struct v4l2_subdev *sd, bool flag)
- 	if (dev->platform_data->gpio_ctrl)
- 		return dev->platform_data->gpio_ctrl(sd, flag);
- 
--	ret = dev->platform_data->gpio0_ctrl(sd, flag);
-+	if (dev->platform_data->gpio0_ctrl)
-+		ret = dev->platform_data->gpio0_ctrl(sd, flag);
- 
- 	return ret;
- }
-@@ -1709,7 +1710,7 @@ static int ov5693_detect(struct i2c_client *client)
- 					OV5693_SC_CMMN_CHIP_ID_L, &low);
- 	id = ((((u16) high) << 8) | (u16) low);
- 
--	if (id != OV5693_ID) {
-+	if (id != OV5690_ID && id != OV5693_ID) {
- 		dev_err(&client->dev, "sensor ID error 0x%x\n", id);
- 		return -ENODEV;
- 	}
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-index 8c2e679..a657f94 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-@@ -33,7 +33,7 @@
- #include <linux/v4l2-mediabus.h>
- #include <media/media-entity.h>
- 
--#include "../../include/linux/atomisp_platform.h"
-+#include "../../include/linux/atomisp_gmin_platform.h"
- 
- #define OV5693_NAME		"ov5693"
- 
-@@ -78,7 +78,8 @@
-  * bits 7-0: min f-number denominator
-  */
- #define OV5693_F_NUMBER_RANGE 0x180a180a
--#define OV5693_ID	0x5690
-+#define OV5690_ID	0x5690
-+#define OV5693_ID	0x5693
- 
- #define OV5693_FINE_INTG_TIME_MIN 0
- #define OV5693_FINE_INTG_TIME_MAX_MARGIN 0
-diff --git a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-index edaae93..ca59c4f 100644
---- a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-+++ b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-@@ -296,11 +296,13 @@ static const struct gmin_cfg_var ecs7_vars[] = {
- 	{"INT33BE:00_CsiFmt", "13"},
- 	{"INT33BE:00_CsiBayer", "2"},
- 	{"INT33BE:00_CamClk", "0"},
-+	{"INT33BE:00_ClkSrc", "1"},
- 	{"INT33F0:00_CsiPort", "0"},
- 	{"INT33F0:00_CsiLanes", "1"},
- 	{"INT33F0:00_CsiFmt", "13"},
- 	{"INT33F0:00_CsiBayer", "0"},
- 	{"INT33F0:00_CamClk", "1"},
-+	{"INT33BE:00_I2CAddr", "-1"},
- 	{"gmin_V2P8GPIO", "402"},
- 	{},
- };
-@@ -325,6 +327,8 @@ static const struct {
- 	{ "MRD7", mrd7_vars },
- 	{ "ST70408", ecs7_vars },
- 	{ "VTA0803", i8880_vars },
-+	{ "Surface Book" , ecs7_vars } ,
-+	{ "Surface Pro 4" , ecs7_vars } ,
- };
- 
- 

+ 0 - 6108
patches/4.14/ipts.patch

@@ -1,6108 +0,0 @@
-diff --git a/Documentation/devicetree/bindings/input/hid-over-i2c.txt b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
-index 28e8bd8..4d3da9d 100644
---- a/Documentation/devicetree/bindings/input/hid-over-i2c.txt
-+++ b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
-@@ -31,7 +31,7 @@ device-specific compatible properties, which should be used in addition to the
- 
- - vdd-supply: phandle of the regulator that provides the supply voltage.
- - post-power-on-delay-ms: time required by the device after enabling its regulators
--  before it is ready for communication. Must be used with 'vdd-supply'.
-+  or powering it on, before it is ready for communication.
- 
- Example:
- 
-diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
-index 2e034ef..635b8c6 100644
---- a/drivers/gpu/drm/i915/Makefile
-+++ b/drivers/gpu/drm/i915/Makefile
-@@ -120,6 +120,9 @@ i915-y += dvo_ch7017.o \
- 	  intel_sdvo.o \
- 	  intel_tv.o
- 
-+# intel precise touch & stylus
-+i915-y  += intel_ipts.o
-+
- # Post-mortem debug and GPU hang state capture
- i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
- i915-$(CONFIG_DRM_I915_SELFTEST) += \
-diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
-index 562220e..bd9cb5c 100644
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -51,6 +51,7 @@
- #include "i915_vgpu.h"
- #include "intel_drv.h"
- #include "intel_uc.h"
-+#include "intel_ipts.h"
- 
- static struct drm_driver driver;
- 
-@@ -679,6 +680,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
- 
- 	drm_kms_helper_poll_init(dev);
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915.enable_guc_submission)
-+        intel_ipts_init(dev);
-+
- 	return 0;
- 
- cleanup_gem:
-@@ -1373,6 +1377,9 @@ void i915_driver_unload(struct drm_device *dev)
- 	struct drm_i915_private *dev_priv = to_i915(dev);
- 	struct pci_dev *pdev = dev_priv->drm.pdev;
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915.enable_guc_submission)
-+		intel_ipts_cleanup(dev);
-+
- 	i915_driver_unregister(dev_priv);
- 
- 	if (i915_gem_suspend(dev_priv))
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index 3f81841..8038f63 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -3659,6 +3659,9 @@ void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
- void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
- 					 struct sg_table *pages);
- 
-+struct i915_gem_context *
-+i915_gem_context_create_ipts(struct drm_device *dev);
-+
- static inline struct i915_gem_context *
- __i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id)
- {
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 3b2c053..d305bf0 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -179,7 +179,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
- 	 * the alignment of the buddy allocation will naturally match.
- 	 */
- 	phys = drm_pci_alloc(obj->base.dev,
--			     obj->base.size,
-+			     roundup_pow_of_two(obj->base.size),
- 			     roundup_pow_of_two(obj->base.size));
- 	if (!phys)
- 		return ERR_PTR(-ENOMEM);
-diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
-index 8afd2ce..00871aa 100644
---- a/drivers/gpu/drm/i915/i915_gem_context.c
-+++ b/drivers/gpu/drm/i915/i915_gem_context.c
-@@ -418,6 +418,18 @@ i915_gem_context_create_gvt(struct drm_device *dev)
- 	return ctx;
- }
- 
-+struct i915_gem_context *i915_gem_context_create_ipts(struct drm_device *dev)
-+{
-+	struct drm_i915_private *dev_priv = dev->dev_private;
-+	struct i915_gem_context *ctx;
-+
-+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-+
-+	ctx = i915_gem_create_context(dev_priv, NULL);
-+
-+	return ctx;
-+}
-+
- int i915_gem_contexts_init(struct drm_i915_private *dev_priv)
- {
- 	struct i915_gem_context *ctx;
-diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
-index 48a1e93..75b5cc2 100644
---- a/drivers/gpu/drm/i915/i915_guc_submission.c
-+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
-@@ -87,6 +87,7 @@ static inline bool is_high_priority(struct i915_guc_client* client)
- 
- static int __reserve_doorbell(struct i915_guc_client *client)
- {
-+	struct drm_i915_private *dev_priv = guc_to_i915(client->guc);
- 	unsigned long offset;
- 	unsigned long end;
- 	u16 id;
-@@ -99,10 +100,15 @@ static int __reserve_doorbell(struct i915_guc_client *client)
- 	 * priority contexts, the second half for high-priority ones.
- 	 */
- 	offset = 0;
--	end = GUC_NUM_DOORBELLS/2;
--	if (is_high_priority(client)) {
--		offset = end;
--		end += offset;
-+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
-+		end = GUC_NUM_DOORBELLS;
-+	}
-+	else {
-+		end = GUC_NUM_DOORBELLS/2;
-+		if (is_high_priority(client)) {
-+			offset = end;
-+			end += offset;
-+		}
- 	}
- 
- 	id = find_next_zero_bit(client->guc->doorbell_bitmap, end, offset);
-@@ -331,7 +337,14 @@ static void guc_stage_desc_init(struct intel_guc *guc,
- 	desc = __get_stage_desc(client);
- 	memset(desc, 0, sizeof(*desc));
- 
--	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | GUC_STAGE_DESC_ATTR_KERNEL;
-+	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE;
-+	if ((client->priority == GUC_CLIENT_PRIORITY_KMD_NORMAL) ||
-+			(client->priority == GUC_CLIENT_PRIORITY_KMD_HIGH)) {
-+		desc->attribute  |= GUC_STAGE_DESC_ATTR_KERNEL;
-+	} else {
-+		desc->attribute  |= GUC_STAGE_DESC_ATTR_PCH;
-+	}
-+
- 	desc->stage_id = client->stage_id;
- 	desc->priority = client->priority;
- 	desc->db_id = client->doorbell_id;
-@@ -1159,7 +1172,8 @@ static void guc_interrupts_capture(struct drm_i915_private *dev_priv)
- 		I915_WRITE(RING_MODE_GEN7(engine), irqs);
- 
- 	/* route USER_INTERRUPT to Host, all others are sent to GuC. */
--	irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+	irqs = (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)
-+							<< GEN8_RCS_IRQ_SHIFT |
- 	       GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
- 	/* These three registers have the same bit definitions */
- 	I915_WRITE(GUC_BCS_RCS_IER, ~irqs);
-@@ -1340,3 +1354,47 @@ int intel_guc_resume(struct drm_i915_private *dev_priv)
- 
- 	return intel_guc_send(guc, data, ARRAY_SIZE(data));
- }
-+
-+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv,
-+				    struct i915_gem_context *ctx)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+	struct i915_guc_client *client;
-+
-+	/* client for execbuf submission */
-+	client = guc_client_alloc(dev_priv,
-+				  INTEL_INFO(dev_priv)->ring_mask,
-+				  IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ? GUC_CLIENT_PRIORITY_HIGH : GUC_CLIENT_PRIORITY_NORMAL,
-+				  ctx);
-+	if (!client) {
-+		DRM_ERROR("Failed to create normal GuC client!\n");
-+		return -ENOMEM;
-+	}
-+
-+	guc->ipts_client = client;
-+	intel_guc_sample_forcewake(guc);
-+	guc_init_doorbell_hw(guc);
-+
-+	return 0;
-+}
-+
-+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+
-+	if (!guc->ipts_client)
-+		return;
-+
-+	guc_client_free(guc->ipts_client);
-+	guc->ipts_client = NULL;
-+}
-+
-+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+
-+	int err = __guc_allocate_doorbell(guc, guc->ipts_client->stage_id);
-+
-+	if (err)
-+		DRM_ERROR("Not able to reacquire IPTS doorbell\n");
-+}
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index b63893e..5a0313b 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -36,6 +36,7 @@
- #include "i915_drv.h"
- #include "i915_trace.h"
- #include "intel_drv.h"
-+#include "intel_ipts.h"
- 
- /**
-  * DOC: interrupt handling
-@@ -1319,6 +1320,9 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
- 		tasklet |= i915.enable_guc_submission;
- 	}
- 
-+	if (iir & (GT_RENDER_PIPECTL_NOTIFY_INTERRUPT << test_shift))
-+		intel_ipts_notify_complete();
-+
- 	if (tasklet)
- 		tasklet_hi_schedule(&engine->irq_tasklet);
- }
-@@ -3391,7 +3395,8 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
- {
- 	/* These are interrupts we'll toggle with the ring mask register */
- 	uint32_t gt_interrupts[] = {
--		GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+		GT_RENDER_PIPECTL_NOTIFY_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+			GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
- 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
- 			GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT |
- 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT,
-diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
-index 8ab003d..3cb1ac4 100644
---- a/drivers/gpu/drm/i915/i915_params.c
-+++ b/drivers/gpu/drm/i915/i915_params.c
-@@ -35,7 +35,7 @@ struct i915_params i915 __read_mostly = {
- 	.enable_rc6 = -1,
- 	.enable_dc = -1,
- 	.enable_fbc = -1,
--	.enable_execlists = -1,
-+	.enable_execlists = 0,
- 	.enable_hangcheck = true,
- 	.enable_ppgtt = -1,
- 	.enable_psr = -1,
-@@ -56,8 +56,8 @@ struct i915_params i915 __read_mostly = {
- 	.verbose_state_checks = 1,
- 	.nuclear_pageflip = 0,
- 	.edp_vswing = 0,
--	.enable_guc_loading = 0,
--	.enable_guc_submission = 0,
-+	.enable_guc_loading = 1,
-+	.enable_guc_submission = 1,
- 	.guc_log_level = -1,
- 	.guc_firmware_path = NULL,
- 	.huc_firmware_path = NULL,
-@@ -144,7 +144,7 @@ MODULE_PARM_DESC(enable_ppgtt,
- module_param_named_unsafe(enable_execlists, i915.enable_execlists, int, 0400);
- MODULE_PARM_DESC(enable_execlists,
- 	"Override execlists usage. "
--	"(-1=auto [default], 0=disabled, 1=enabled)");
-+	"(-1=auto, 0=disabled [default], 1=enabled)");
- 
- module_param_named_unsafe(enable_psr, i915.enable_psr, int, 0600);
- MODULE_PARM_DESC(enable_psr, "Enable PSR "
-@@ -225,12 +225,12 @@ MODULE_PARM_DESC(edp_vswing,
- module_param_named_unsafe(enable_guc_loading, i915.enable_guc_loading, int, 0400);
- MODULE_PARM_DESC(enable_guc_loading,
- 		"Enable GuC firmware loading "
--		"(-1=auto, 0=never [default], 1=if available, 2=required)");
-+		"(-1=auto, 0=never, 1=if available [default], 2=required)");
- 
- module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, int, 0400);
- MODULE_PARM_DESC(enable_guc_submission,
- 		"Enable GuC submission "
--		"(-1=auto, 0=never [default], 1=if available, 2=required)");
-+		"(-1=auto, 0=never, 1=if available [default], 2=required)");
- 
- module_param_named(guc_log_level, i915.guc_log_level, int, 0400);
- MODULE_PARM_DESC(guc_log_level,
-diff --git a/drivers/gpu/drm/i915/intel_ipts.c b/drivers/gpu/drm/i915/intel_ipts.c
-new file mode 100644
-index 0000000..f5fa111
---- /dev/null
-+++ b/drivers/gpu/drm/i915/intel_ipts.c
-@@ -0,0 +1,626 @@
-+/*
-+ * Copyright  2016 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#include <linux/intel_ipts_if.h>
-+#include <drm/drmP.h>
-+
-+#include "i915_drv.h"
-+
-+#define SUPPORTED_IPTS_INTERFACE_VERSION	1
-+
-+#define REACQUIRE_DB_THRESHOLD			8
-+#define DB_LOST_CHECK_STEP1_INTERVAL		2000	/* ms */
-+#define DB_LOST_CHECK_STEP2_INTERVAL		500	/* ms */
-+
-+/* intel IPTS ctx for ipts support */
-+typedef struct intel_ipts {
-+	struct drm_device *dev;
-+	struct i915_gem_context *ipts_context;
-+	intel_ipts_callback_t ipts_clbks;
-+
-+	/* buffers' list */
-+	struct {
-+		spinlock_t       lock;
-+		struct list_head list;
-+	} buffers;
-+
-+	void *data;
-+
-+	struct delayed_work reacquire_db_work;
-+	intel_ipts_wq_info_t wq_info;
-+	u32	old_tail;
-+	u32	old_head;
-+	bool	need_reacquire_db;
-+
-+	bool	connected;
-+	bool	initialized;
-+} intel_ipts_t;
-+
-+intel_ipts_t intel_ipts;
-+
-+typedef struct intel_ipts_object {
-+	struct list_head list;
-+	struct drm_i915_gem_object *gem_obj;
-+	void	*cpu_addr;
-+} intel_ipts_object_t;
-+
-+static intel_ipts_object_t *ipts_object_create(size_t size, u32 flags)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	intel_ipts_object_t *obj = NULL;
-+	struct drm_i915_gem_object *gem_obj = NULL;
-+	int ret = 0;
-+
-+	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
-+	if (!obj)
-+		return NULL;
-+
-+	size = roundup(size, PAGE_SIZE);
-+	if (size == 0) {
-+		ret = -EINVAL;
-+		goto err_out;
-+	}
-+
-+	/* Allocate the new object */
-+	gem_obj = i915_gem_object_create(dev_priv, size);
-+	if (gem_obj == NULL) {
-+		ret = -ENOMEM;
-+		goto err_out;
-+	}
-+
-+	if (flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		ret = i915_gem_object_attach_phys(gem_obj, PAGE_SIZE);
-+		if (ret) {
-+			pr_info(">> ipts no contiguous : %d\n", ret);
-+			goto err_out;
-+		}
-+	}
-+
-+	obj->gem_obj = gem_obj;
-+
-+	spin_lock(&intel_ipts.buffers.lock);
-+	list_add_tail(&obj->list, &intel_ipts.buffers.list);
-+	spin_unlock(&intel_ipts.buffers.lock);
-+
-+	return obj;
-+
-+err_out:
-+	if (gem_obj)
-+		i915_gem_free_object(&gem_obj->base);
-+
-+	if (obj)
-+		kfree(obj);
-+
-+	return NULL;
-+}
-+
-+static void ipts_object_free(intel_ipts_object_t* obj)
-+{
-+	spin_lock(&intel_ipts.buffers.lock);
-+	list_del(&obj->list);
-+	spin_unlock(&intel_ipts.buffers.lock);
-+
-+	i915_gem_free_object(&obj->gem_obj->base);
-+	kfree(obj);
-+}
-+
-+static int ipts_object_pin(intel_ipts_object_t* obj,
-+					struct i915_gem_context *ipts_ctx)
-+{
-+	struct i915_address_space *vm = NULL;
-+	struct i915_vma *vma = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	if (ipts_ctx->ppgtt) {
-+		vm = &ipts_ctx->ppgtt->base;
-+	} else {
-+		vm = &dev_priv->ggtt.base;
-+	}
-+
-+	vma = i915_vma_instance(obj->gem_obj, vm, NULL);
-+	if (IS_ERR(vma)) {
-+		DRM_ERROR("cannot find or create vma\n");
-+		return -1;
-+	}
-+
-+	ret = i915_vma_pin(vma, 0, PAGE_SIZE, PIN_USER);
-+
-+	return ret;
-+}
-+
-+static void ipts_object_unpin(intel_ipts_object_t *obj)
-+{
-+	/* TBD: Add support */
-+}
-+
-+static void* ipts_object_map(intel_ipts_object_t *obj)
-+{
-+
-+	return i915_gem_object_pin_map(obj->gem_obj, I915_MAP_WB);
-+}
-+
-+static void ipts_object_unmap(intel_ipts_object_t* obj)
-+{
-+	i915_gem_object_unpin_map(obj->gem_obj);
-+	obj->cpu_addr = NULL;
-+}
-+
-+static int create_ipts_context(void)
-+{
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct intel_ring *pin_ret;
-+	int ret = 0;
-+
-+	/* Initialize the context right away.*/
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return ret;
-+	}
-+
-+	ipts_ctx = i915_gem_context_create_ipts(intel_ipts.dev);
-+	if (IS_ERR(ipts_ctx)) {
-+		DRM_ERROR("Failed to create IPTS context (error %ld)\n",
-+			  PTR_ERR(ipts_ctx));
-+		ret = PTR_ERR(ipts_ctx);
-+		goto err_unlock;
-+	}
-+
-+	ret = execlists_context_deferred_alloc(ipts_ctx, dev_priv->engine[RCS]);
-+	if (ret) {
-+		DRM_DEBUG("lr context allocation failed : %d\n", ret);
-+		goto err_ctx;
-+	}
-+
-+	pin_ret = execlists_context_pin(dev_priv->engine[RCS], ipts_ctx);
-+	if (IS_ERR(pin_ret)) {
-+		DRM_DEBUG("lr context pinning failed :  %ld\n", PTR_ERR(pin_ret));
-+		goto err_ctx;
-+	}
-+
-+	/* Release the mutex */
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	spin_lock_init(&intel_ipts.buffers.lock);
-+	INIT_LIST_HEAD(&intel_ipts.buffers.list);
-+
-+	intel_ipts.ipts_context = ipts_ctx;
-+
-+	return 0;
-+
-+err_ctx:
-+	if (ipts_ctx)
-+		i915_gem_context_put(ipts_ctx);
-+
-+err_unlock:
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return ret;
-+}
-+
-+static void destroy_ipts_context(void)
-+{
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	ipts_ctx = intel_ipts.ipts_context;
-+
-+	/* Initialize the context right away.*/
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return;
-+	}
-+
-+	execlists_context_unpin(dev_priv->engine[RCS], ipts_ctx);
-+	i915_gem_context_put(ipts_ctx);
-+
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+}
-+
-+int intel_ipts_notify_complete(void)
-+{
-+	if (intel_ipts.ipts_clbks.workload_complete)
-+		intel_ipts.ipts_clbks.workload_complete(intel_ipts.data);
-+
-+	return 0;
-+}
-+
-+int intel_ipts_notify_backlight_status(bool backlight_on)
-+{
-+	if (intel_ipts.ipts_clbks.notify_gfx_status) {
-+		if (backlight_on) {
-+			intel_ipts.ipts_clbks.notify_gfx_status(
-+						IPTS_NOTIFY_STA_BACKLIGHT_ON,
-+						intel_ipts.data);
-+			schedule_delayed_work(&intel_ipts.reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+		} else {
-+			intel_ipts.ipts_clbks.notify_gfx_status(
-+						IPTS_NOTIFY_STA_BACKLIGHT_OFF,
-+						intel_ipts.data);
-+			cancel_delayed_work(&intel_ipts.reacquire_db_work);
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+static void intel_ipts_reacquire_db(intel_ipts_t *intel_ipts_p)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts_p->dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return;
-+	}
-+
-+	/* Reacquire the doorbell */
-+	i915_guc_ipts_reacquire_doorbell(intel_ipts_p->dev->dev_private);
-+
-+	mutex_unlock(&intel_ipts_p->dev->struct_mutex);
-+
-+	return;
-+}
-+
-+static int intel_ipts_get_wq_info(uint64_t gfx_handle,
-+						intel_ipts_wq_info_t *wq_info)
-+{
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	*wq_info = intel_ipts.wq_info;
-+
-+	intel_ipts_reacquire_db(&intel_ipts);
-+	schedule_delayed_work(&intel_ipts.reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+
-+	return 0;
-+}
-+
-+static int set_wq_info(void)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct intel_guc *guc = &dev_priv->guc;
-+	struct i915_guc_client *client;
-+	struct guc_process_desc *desc;
-+	void *base = NULL;
-+	intel_ipts_wq_info_t *wq_info;
-+	u64 phy_base = 0;
-+
-+	wq_info = &intel_ipts.wq_info;
-+
-+	client = guc->ipts_client;
-+	if (!client) {
-+		DRM_ERROR("IPTS GuC client is NOT available\n");
-+		return -EINVAL;
-+	}
-+
-+	base = client->vaddr;
-+	desc = (struct guc_process_desc *)((u64)base + client->proc_desc_offset);
-+
-+	desc->wq_base_addr = (u64)base + client->wq_offset;
-+	desc->db_base_addr = (u64)base + client->doorbell_offset;
-+
-+	/* IPTS expects physical addresses to pass it to ME */
-+	phy_base = sg_dma_address(client->vma->pages->sgl);
-+
-+	wq_info->db_addr = desc->db_base_addr;
-+        wq_info->db_phy_addr = phy_base + client->doorbell_offset;
-+        wq_info->db_cookie_offset = offsetof(struct guc_doorbell_info, cookie);
-+        wq_info->wq_addr = desc->wq_base_addr;
-+        wq_info->wq_phy_addr = phy_base + client->wq_offset;
-+        wq_info->wq_head_addr = (u64)&desc->head;
-+        wq_info->wq_head_phy_addr = phy_base + client->proc_desc_offset +
-+					offsetof(struct guc_process_desc, head);
-+        wq_info->wq_tail_addr = (u64)&desc->tail;
-+        wq_info->wq_tail_phy_addr = phy_base + client->proc_desc_offset +
-+					offsetof(struct guc_process_desc, tail);
-+        wq_info->wq_size = desc->wq_size_bytes;
-+
-+	return 0;
-+}
-+
-+static int intel_ipts_init_wq(void)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed\n");
-+		return ret;
-+	}
-+
-+	/* disable IPTS submission */
-+	i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private);
-+
-+	/* enable IPTS submission */
-+	ret = i915_guc_ipts_submission_enable(intel_ipts.dev->dev_private,
-+							intel_ipts.ipts_context);
-+	if (ret) {
-+		DRM_ERROR("i915_guc_ipts_submission_enable failed : %d\n", ret);
-+		goto out;
-+        }
-+
-+	ret = set_wq_info();
-+	if (ret) {
-+		DRM_ERROR("set_wq_info failed\n");
-+		goto out;
-+	}
-+
-+out:
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return ret;
-+}
-+
-+static void intel_ipts_release_wq(void)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed\n");
-+		return;
-+	}
-+
-+	/* disable IPTS submission */
-+	i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private);
-+
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+}
-+
-+static int intel_ipts_map_buffer(u64 gfx_handle, intel_ipts_mapbuffer_t *mapbuf)
-+{
-+	intel_ipts_object_t* obj;
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct i915_address_space *vm = NULL;
-+	struct i915_vma *vma = NULL;
-+	int ret = 0;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	/* Acquire mutex first */
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return -EINVAL;
-+	}
-+
-+	obj = ipts_object_create(mapbuf->size, mapbuf->flags);
-+	if (!obj)
-+		return -ENOMEM;
-+
-+	ipts_ctx = intel_ipts.ipts_context;
-+	ret = ipts_object_pin(obj, ipts_ctx);
-+	if (ret) {
-+		DRM_ERROR("Not able to pin iTouch obj\n");
-+		ipts_object_free(obj);
-+		mutex_unlock(&intel_ipts.dev->struct_mutex);
-+		return -ENOMEM;
-+	}
-+
-+	if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		obj->cpu_addr = obj->gem_obj->phys_handle->vaddr;
-+	} else {
-+		obj->cpu_addr = ipts_object_map(obj);
-+	}
-+
-+	if (ipts_ctx->ppgtt) {
-+		vm = &ipts_ctx->ppgtt->base;
-+	} else {
-+		vm = &dev_priv->ggtt.base;
-+	}
-+
-+	vma = i915_vma_instance(obj->gem_obj, vm, NULL);
-+	if (IS_ERR(vma)) {
-+		DRM_ERROR("cannot find or create vma\n");
-+		return -EINVAL;
-+	}
-+
-+	mapbuf->gfx_addr = (void*)vma->node.start;
-+	mapbuf->cpu_addr = (void*)obj->cpu_addr;
-+	mapbuf->buf_handle = (u64)obj;
-+	if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		mapbuf->phy_addr = (u64)obj->gem_obj->phys_handle->busaddr;
-+	}
-+
-+	/* Release the mutex */
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return 0;
-+}
-+
-+static int intel_ipts_unmap_buffer(uint64_t gfx_handle, uint64_t buf_handle)
-+{
-+	intel_ipts_object_t* obj = (intel_ipts_object_t*)buf_handle;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	if (!obj->gem_obj->phys_handle)
-+		ipts_object_unmap(obj);
-+	ipts_object_unpin(obj);
-+	ipts_object_free(obj);
-+
-+	return 0;
-+}
-+
-+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	if (!intel_ipts.initialized)
-+		return -EIO;
-+
-+	if (ipts_connect && ipts_connect->if_version <=
-+					SUPPORTED_IPTS_INTERFACE_VERSION) {
-+
-+		/* return gpu operations for ipts */
-+		ipts_connect->ipts_ops.get_wq_info = intel_ipts_get_wq_info;
-+		ipts_connect->ipts_ops.map_buffer = intel_ipts_map_buffer;
-+		ipts_connect->ipts_ops.unmap_buffer = intel_ipts_unmap_buffer;
-+		ipts_connect->gfx_version = INTEL_INFO(dev_priv)->gen;
-+		ipts_connect->gfx_handle = (uint64_t)&intel_ipts;
-+
-+		/* save callback and data */
-+		intel_ipts.data = ipts_connect->data;
-+		intel_ipts.ipts_clbks = ipts_connect->ipts_cb;
-+
-+		intel_ipts.connected = true;
-+	} else {
-+		ret = -EINVAL;
-+	}
-+
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(intel_ipts_connect);
-+
-+void intel_ipts_disconnect(uint64_t gfx_handle)
-+{
-+	if (!intel_ipts.initialized)
-+		return;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts ||
-+					intel_ipts.connected == false) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return;
-+	}
-+
-+	intel_ipts.data = 0;
-+	memset(&intel_ipts.ipts_clbks, 0, sizeof(intel_ipts_callback_t));
-+
-+	intel_ipts.connected = false;
-+}
-+EXPORT_SYMBOL_GPL(intel_ipts_disconnect);
-+
-+static void reacquire_db_work_func(struct work_struct *work)
-+{
-+	struct delayed_work *d_work = container_of(work, struct delayed_work,
-+							work);
-+	intel_ipts_t *intel_ipts_p = container_of(d_work, intel_ipts_t,
-+							reacquire_db_work);
-+	u32 head;
-+	u32 tail;
-+	u32 size;
-+	u32 load;
-+
-+	head = *(u32*)intel_ipts_p->wq_info.wq_head_addr;
-+	tail = *(u32*)intel_ipts_p->wq_info.wq_tail_addr;
-+	size = intel_ipts_p->wq_info.wq_size;
-+
-+	if (head >= tail)
-+		load = head - tail;
-+	else
-+		load = head + size - tail;
-+
-+	if (load < REACQUIRE_DB_THRESHOLD) {
-+		intel_ipts_p->need_reacquire_db = false;
-+		goto reschedule_work;
-+	}
-+
-+	if (intel_ipts_p->need_reacquire_db) {
-+		if (intel_ipts_p->old_head == head && intel_ipts_p->old_tail == tail)
-+			intel_ipts_reacquire_db(intel_ipts_p);
-+		intel_ipts_p->need_reacquire_db = false;
-+	} else {
-+		intel_ipts_p->old_head = head;
-+		intel_ipts_p->old_tail = tail;
-+		intel_ipts_p->need_reacquire_db = true;
-+
-+		/* recheck */
-+		schedule_delayed_work(&intel_ipts_p->reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP2_INTERVAL));
-+		return;
-+	}
-+
-+reschedule_work:
-+	schedule_delayed_work(&intel_ipts_p->reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+}
-+
-+/**
-+ * intel_ipts_init - Initialize ipts support
-+ * @dev: drm device
-+ *
-+ * Setup the required structures for ipts.
-+ */
-+int intel_ipts_init(struct drm_device *dev)
-+{
-+	int ret = 0;
-+
-+	pr_info("ipts: initializing ipts\n");
-+
-+	intel_ipts.dev = dev;
-+	INIT_DELAYED_WORK(&intel_ipts.reacquire_db_work, reacquire_db_work_func);
-+
-+	ret = create_ipts_context();
-+	if (ret)
-+		return -ENOMEM;
-+
-+	ret = intel_ipts_init_wq();
-+	if (ret)
-+		return ret;
-+
-+	intel_ipts.initialized = true;
-+	DRM_DEBUG_DRIVER("Intel iTouch framework initialized\n");
-+
-+	return ret;
-+}
-+
-+void intel_ipts_cleanup(struct drm_device *dev)
-+{
-+	intel_ipts_object_t *obj, *n;
-+
-+	if (intel_ipts.dev == dev) {
-+		list_for_each_entry_safe(obj, n, &intel_ipts.buffers.list, list) {
-+			list_del(&obj->list);
-+
-+			if (!obj->gem_obj->phys_handle)
-+				ipts_object_unmap(obj);
-+			ipts_object_unpin(obj);
-+			i915_gem_free_object(&obj->gem_obj->base);
-+			kfree(obj);
-+		}
-+
-+		intel_ipts_release_wq();
-+		destroy_ipts_context();
-+		cancel_delayed_work(&intel_ipts.reacquire_db_work);
-+	}
-+}
-diff --git a/drivers/gpu/drm/i915/intel_ipts.h b/drivers/gpu/drm/i915/intel_ipts.h
-new file mode 100644
-index 0000000..a6965d1
---- /dev/null
-+++ b/drivers/gpu/drm/i915/intel_ipts.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright © 2016 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ */
-+#ifndef _INTEL_IPTS_H_
-+#define _INTEL_IPTS_H_
-+
-+struct drm_device;
-+
-+int intel_ipts_init(struct drm_device *dev);
-+void intel_ipts_cleanup(struct drm_device *dev);
-+int intel_ipts_notify_backlight_status(bool backlight_on);
-+int intel_ipts_notify_complete(void);
-+
-+#endif //_INTEL_IPTS_H_
-diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
-index 6f972e6..f25a439 100644
---- a/drivers/gpu/drm/i915/intel_lrc.c
-+++ b/drivers/gpu/drm/i915/intel_lrc.c
-@@ -211,8 +211,6 @@
- 
- #define WA_TAIL_DWORDS 2
- 
--static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
--					    struct intel_engine_cs *engine);
- static void execlists_init_reg_state(u32 *reg_state,
- 				     struct i915_gem_context *ctx,
- 				     struct intel_engine_cs *engine,
-@@ -819,7 +817,7 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
- 	/* XXX Do we need to preempt to make room for us and our deps? */
- }
- 
--static struct intel_ring *
-+struct intel_ring *
- execlists_context_pin(struct intel_engine_cs *engine,
- 		      struct i915_gem_context *ctx)
- {
-@@ -880,7 +878,7 @@ execlists_context_pin(struct intel_engine_cs *engine,
- 	return ERR_PTR(ret);
- }
- 
--static void execlists_context_unpin(struct intel_engine_cs *engine,
-+void execlists_context_unpin(struct intel_engine_cs *engine,
- 				    struct i915_gem_context *ctx)
- {
- 	struct intel_context *ce = &ctx->engine[engine->id];
-@@ -1810,6 +1808,9 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
- 
- 	logical_ring_setup(engine);
- 
-+	engine->irq_keep_mask |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT
-+							<< GEN8_RCS_IRQ_SHIFT;
-+
- 	if (HAS_L3_DPF(dev_priv))
- 		engine->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
- 
-@@ -2038,7 +2039,7 @@ populate_lr_context(struct i915_gem_context *ctx,
- 	return 0;
- }
- 
--static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
-+int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
- 					    struct intel_engine_cs *engine)
- {
- 	struct drm_i915_gem_object *ctx_obj;
-diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
-index 57ef583..aec97c3 100644
---- a/drivers/gpu/drm/i915/intel_lrc.h
-+++ b/drivers/gpu/drm/i915/intel_lrc.h
-@@ -85,4 +85,12 @@ uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx,
- int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv,
- 				    int enable_execlists);
- 
-+struct intel_ring *
-+execlists_context_pin(struct intel_engine_cs *engine,
-+		      struct i915_gem_context *ctx);
-+void execlists_context_unpin(struct intel_engine_cs *engine,
-+				    struct i915_gem_context *ctx);
-+int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
-+					    struct intel_engine_cs *engine);
-+
- #endif /* _INTEL_LRC_H_ */
-diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
-index 3b1c5d7..98b64e3 100644
---- a/drivers/gpu/drm/i915/intel_panel.c
-+++ b/drivers/gpu/drm/i915/intel_panel.c
-@@ -34,6 +34,7 @@
- #include <linux/moduleparam.h>
- #include <linux/pwm.h>
- #include "intel_drv.h"
-+#include "intel_ipts.h"
- 
- #define CRC_PMIC_PWM_PERIOD_NS	21333
- 
-@@ -719,6 +720,9 @@ static void lpt_disable_backlight(const struct drm_connector_state *old_conn_sta
- 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- 	u32 tmp;
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915.enable_guc_submission)
-+		intel_ipts_notify_backlight_status(false);
-+
- 	intel_panel_actually_set_backlight(old_conn_state, 0);
- 
- 	/*
-@@ -906,6 +910,9 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
- 
- 	/* This won't stick until the above enable. */
- 	intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
-+
-+	if (INTEL_GEN(dev_priv) >= 9 && i915.enable_guc_submission)
-+		intel_ipts_notify_backlight_status(true);
- }
- 
- static void pch_enable_backlight(const struct intel_crtc_state *crtc_state,
-diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h
-index 22ae52b..c7765f9 100644
---- a/drivers/gpu/drm/i915/intel_uc.h
-+++ b/drivers/gpu/drm/i915/intel_uc.h
-@@ -191,6 +191,7 @@ struct intel_guc {
- 	struct ida stage_ids;
- 
- 	struct i915_guc_client *execbuf_client;
-+	struct i915_guc_client *ipts_client;
- 
- 	DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS);
- 	uint32_t db_cacheline;		/* Cyclic counter mod pagesize	*/
-@@ -276,4 +277,9 @@ void intel_huc_select_fw(struct intel_huc *huc);
- void intel_huc_init_hw(struct intel_huc *huc);
- void intel_guc_auth_huc(struct drm_i915_private *dev_priv);
- 
-+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv,
-+				    struct i915_gem_context *ctx);
-+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv);
-+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv);
-+
- #endif
-diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
-index 6598501..a80c018 100644
---- a/drivers/hid/hid-multitouch.c
-+++ b/drivers/hid/hid-multitouch.c
-@@ -140,6 +140,7 @@ struct mt_device {
- 
- static void mt_post_parse_default_settings(struct mt_device *td);
- static void mt_post_parse(struct mt_device *td);
-+static int cc_seen = 0;
- 
- /* classes of device behavior */
- #define MT_CLS_DEFAULT				0x0001
-@@ -588,8 +589,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 			if (field->index >= field->report->maxfield ||
- 			    usage->usage_index >= field->report_count)
- 				return 1;
--			td->cc_index = field->index;
--			td->cc_value_index = usage->usage_index;
-+
-+			if(cc_seen != 1) {
-+				td->cc_index = field->index;
-+				td->cc_value_index = usage->usage_index;
-+				cc_seen++;
-+			}
- 			return 1;
- 		case HID_DG_CONTACTMAX:
- 			/* we don't set td->last_slot_field as contactcount and
-@@ -626,6 +631,16 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 	return 0;
- }
- 
-+static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-+		struct hid_field *field, struct hid_usage *usage,
-+		unsigned long **bit, int *max)
-+{
-+	if (usage->type == EV_KEY || usage->type == EV_ABS)
-+		set_bit(usage->type, hi->input->evbit);
-+
-+	return -1;
-+}
-+
- static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
- {
- 	__s32 quirks = td->mtclass.quirks;
-@@ -942,9 +957,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 	    field->application != HID_DG_TOUCHSCREEN &&
- 	    field->application != HID_DG_PEN &&
- 	    field->application != HID_DG_TOUCHPAD &&
-+		field->application != HID_GD_MOUSE &&
- 	    field->application != HID_GD_KEYBOARD &&
- 	    field->application != HID_GD_SYSTEM_CONTROL &&
- 	    field->application != HID_CP_CONSUMER_CONTROL &&
-+		field->logical != HID_DG_TOUCHSCREEN &&
- 	    field->application != HID_GD_WIRELESS_RADIO_CTLS &&
- 	    !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
- 	      td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP))
-@@ -1007,10 +1024,8 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
- 		return 0;
- 
- 	if (field->application == HID_DG_TOUCHSCREEN ||
--	    field->application == HID_DG_TOUCHPAD) {
--		/* We own these mappings, tell hid-input to ignore them */
--		return -1;
--	}
-+	    field->application == HID_DG_TOUCHPAD)
-+		return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
- 
- 	/* let hid-core decide for the others */
- 	return 0;
-@@ -1153,6 +1168,7 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
- 		suffix = "Pen";
- 		/* force BTN_STYLUS to allow tablet matching in udev */
- 		__set_bit(BTN_STYLUS, hi->input->keybit);
-+        __set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
- 	} else {
- 		switch (field->application) {
- 		case HID_GD_KEYBOARD:
-@@ -1168,9 +1184,10 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
- 			suffix = "Pen";
- 			/* force BTN_STYLUS to allow tablet matching in udev */
- 			__set_bit(BTN_STYLUS, hi->input->keybit);
-+            __set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
- 			break;
- 		case HID_DG_TOUCHSCREEN:
--			/* we do not set suffix = "Touchscreen" */
-+			suffix = "Touchscreen";
- 			break;
- 		case HID_DG_TOUCHPAD:
- 			suffix = "Touchpad";
-@@ -1299,6 +1316,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
- 	td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
- 	td->cc_index = -1;
- 	td->mt_report_id = -1;
-+	cc_seen = 0;
- 	hid_set_drvdata(hdev, td);
- 
- 	td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
-@@ -1345,7 +1363,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
- 	hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
- 
- 	setup_timer(&td->release_timer, mt_expired_timeout, (long)hdev);
--
- 	ret = hid_parse(hdev);
- 	if (ret != 0)
- 		return ret;
-diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
-index 9145c21..71dbae5 100644
---- a/drivers/hid/i2c-hid/i2c-hid.c
-+++ b/drivers/hid/i2c-hid/i2c-hid.c
-@@ -929,11 +929,6 @@ static int i2c_hid_of_probe(struct i2c_client *client,
- 	}
- 	pdata->hid_descriptor_address = val;
- 
--	ret = of_property_read_u32(dev->of_node, "post-power-on-delay-ms",
--				   &val);
--	if (!ret)
--		pdata->post_power_delay_ms = val;
--
- 	return 0;
- }
- 
-@@ -950,6 +945,16 @@ static inline int i2c_hid_of_probe(struct i2c_client *client,
- }
- #endif
- 
-+static void i2c_hid_fwnode_probe(struct i2c_client *client,
-+				 struct i2c_hid_platform_data *pdata)
-+{
-+	u32 val;
-+
-+	if (!device_property_read_u32(&client->dev, "post-power-on-delay-ms",
-+				      &val))
-+		pdata->post_power_delay_ms = val;
-+}
-+
- static int i2c_hid_probe(struct i2c_client *client,
- 			 const struct i2c_device_id *dev_id)
- {
-@@ -993,6 +998,9 @@ static int i2c_hid_probe(struct i2c_client *client,
- 		ihid->pdata = *platform_data;
- 	}
- 
-+	/* 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);
-diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index 8136dc7..3cff7be 100644
---- a/drivers/misc/Kconfig
-+++ b/drivers/misc/Kconfig
-@@ -513,6 +513,7 @@ source "drivers/misc/ti-st/Kconfig"
- source "drivers/misc/lis3lv02d/Kconfig"
- source "drivers/misc/altera-stapl/Kconfig"
- source "drivers/misc/mei/Kconfig"
-+source "drivers/misc/ipts/Kconfig"
- source "drivers/misc/vmw_vmci/Kconfig"
- source "drivers/misc/mic/Kconfig"
- source "drivers/misc/genwqe/Kconfig"
-diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index ad0e64f..a574554 100644
---- a/drivers/misc/Makefile
-+++ b/drivers/misc/Makefile
-@@ -44,6 +44,7 @@ obj-y				+= lis3lv02d/
- obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
- obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
- obj-$(CONFIG_INTEL_MEI)		+= mei/
-+obj-$(CONFIG_INTEL_IPTS)	+= ipts/
- obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
- obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
- obj-$(CONFIG_SRAM)		+= sram.o
-diff --git a/drivers/misc/ipts/Kconfig b/drivers/misc/ipts/Kconfig
-new file mode 100644
-index 0000000..360ed38
---- /dev/null
-+++ b/drivers/misc/ipts/Kconfig
-@@ -0,0 +1,9 @@
-+config INTEL_IPTS
-+	tristate "Intel Precise Touch & Stylus"
-+	select INTEL_MEI
-+	depends on X86 && PCI && HID
-+	help
-+	  Intel Precise Touch & Stylus support
-+	  Supported SoCs:
-+	  Intel Skylake
-+	  Intel Kabylake
-diff --git a/drivers/misc/ipts/Makefile b/drivers/misc/ipts/Makefile
-new file mode 100644
-index 0000000..1783e9c
---- /dev/null
-+++ b/drivers/misc/ipts/Makefile
-@@ -0,0 +1,13 @@
-+#
-+# Makefile - Intel Precise Touch & Stylus device driver
-+# Copyright (c) 2016, Intel Corporation.
-+#
-+
-+obj-$(CONFIG_INTEL_IPTS)+= intel-ipts.o
-+intel-ipts-objs += ipts-mei.o
-+intel-ipts-objs += ipts-hid.o
-+intel-ipts-objs += ipts-msg-handler.o
-+intel-ipts-objs += ipts-kernel.o
-+intel-ipts-objs += ipts-resource.o
-+intel-ipts-objs += ipts-gfx.o
-+intel-ipts-$(CONFIG_DEBUG_FS) += ipts-dbgfs.o
-diff --git a/drivers/misc/ipts/ipts-binary-spec.h b/drivers/misc/ipts/ipts-binary-spec.h
-new file mode 100644
-index 0000000..87d4bc4
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-binary-spec.h
-@@ -0,0 +1,118 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus binary spec
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_BINARY_SPEC_H
-+#define _IPTS_BINARY_SPEC_H
-+
-+#define IPTS_BIN_HEADER_VERSION 2
-+
-+#pragma pack(1)
-+
-+/* we support 16 output buffers(1:feedback, 15:HID) */
-+#define  MAX_NUM_OUTPUT_BUFFERS 16
-+
-+typedef enum {
-+	IPTS_BIN_KERNEL,
-+	IPTS_BIN_RO_DATA,
-+	IPTS_BIN_RW_DATA,
-+	IPTS_BIN_SENSOR_FRAME,
-+	IPTS_BIN_OUTPUT,
-+	IPTS_BIN_DYNAMIC_STATE_HEAP,
-+	IPTS_BIN_PATCH_LOCATION_LIST,
-+	IPTS_BIN_ALLOCATION_LIST,
-+	IPTS_BIN_COMMAND_BUFFER_PACKET,
-+	IPTS_BIN_TAG,
-+} ipts_bin_res_type_t;
-+
-+typedef struct ipts_bin_header {
-+	char str[4];
-+	unsigned int version;
-+
-+#if IPTS_BIN_HEADER_VERSION > 1
-+	unsigned int gfxcore;
-+	unsigned int revid;
-+#endif
-+} ipts_bin_header_t;
-+
-+typedef struct ipts_bin_alloc {
-+	unsigned int handle;
-+	unsigned int reserved;
-+} ipts_bin_alloc_t;
-+
-+typedef struct ipts_bin_alloc_list {
-+	unsigned int num;
-+	ipts_bin_alloc_t alloc[];
-+} ipts_bin_alloc_list_t;
-+
-+typedef struct ipts_bin_cmdbuf {
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_cmdbuf_t;
-+
-+typedef struct ipts_bin_res {
-+	unsigned int handle;
-+	ipts_bin_res_type_t type;
-+	unsigned int initialize;
-+	unsigned int aligned_size;
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_res_t;
-+
-+typedef enum {
-+	IPTS_INPUT,
-+	IPTS_OUTPUT,
-+	IPTS_CONFIGURATION,
-+	IPTS_CALIBRATION,
-+	IPTS_FEATURE,
-+} ipts_bin_io_buffer_type_t;
-+
-+typedef struct ipts_bin_io_header {
-+	char str[10];
-+	unsigned short type;
-+} ipts_bin_io_header_t;
-+
-+typedef struct ipts_bin_res_list {
-+	unsigned int num;
-+	ipts_bin_res_t res[];
-+} ipts_bin_res_list_t;
-+
-+typedef struct ipts_bin_patch {
-+	unsigned int index;
-+	unsigned int reserved1[2];
-+	unsigned int alloc_offset;
-+	unsigned int patch_offset;
-+	unsigned int reserved2;
-+} ipts_bin_patch_t;
-+
-+typedef struct ipts_bin_patch_list {
-+	unsigned int num;
-+	ipts_bin_patch_t patch[];
-+} ipts_bin_patch_list_t;
-+
-+typedef struct ipts_bin_guc_wq_info {
-+	unsigned int batch_offset;
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_guc_wq_info_t;
-+
-+typedef struct ipts_bin_bufid_patch {
-+	unsigned int imm_offset;
-+	unsigned int mem_offset;
-+} ipts_bin_bufid_patch_t;
-+
-+#pragma pack()
-+
-+#endif /* _IPTS_BINARY_SPEC_H */
-diff --git a/drivers/misc/ipts/ipts-dbgfs.c b/drivers/misc/ipts/ipts-dbgfs.c
-new file mode 100644
-index 0000000..1c5c92f
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-dbgfs.c
-@@ -0,0 +1,152 @@
-+/*
-+ * Intel Precise Touch & Stylus device driver
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/debugfs.h>
-+#include <linux/ctype.h>
-+#include <linux/uaccess.h>
-+
-+#include "ipts.h"
-+#include "ipts-sensor-regs.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-state.h"
-+
-+const char sensor_mode_fmt[] = "sensor mode : %01d\n";
-+const char ipts_status_fmt[] = "sensor mode : %01d\nipts state : %01d\n";
-+
-+static ssize_t ipts_dbgfs_mode_read(struct file *fp, char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	char mode[80];
-+	int len = 0;
-+
-+	if (cnt < sizeof(sensor_mode_fmt) - 3)
-+		return -EINVAL;
-+
-+	len = scnprintf(mode, 80, sensor_mode_fmt, ipts->sensor_mode);
-+	if (len < 0)
-+		return -EIO;
-+
-+	return simple_read_from_buffer(ubuf, cnt, ppos, mode, len);
-+}
-+
-+static ssize_t ipts_dbgfs_mode_write(struct file *fp, const char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	ipts_state_t state;
-+	int sensor_mode, len;
-+	char mode[3];
-+
-+	if (cnt == 0 || cnt > 3)
-+		return -EINVAL;
-+
-+	state = ipts_get_state(ipts);
-+	if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED) {
-+		return -EIO;
-+	}
-+
-+	len = cnt;
-+	if (copy_from_user(mode, ubuf, len))
-+		return -EFAULT;
-+
-+	while(len > 0 && (isspace(mode[len-1]) || mode[len-1] == '\n'))
-+		len--;
-+	mode[len] = '\0';
-+
-+	if (sscanf(mode, "%d", &sensor_mode) != 1)
-+		return -EINVAL;
-+
-+	if (sensor_mode != TOUCH_SENSOR_MODE_RAW_DATA &&
-+					sensor_mode != TOUCH_SENSOR_MODE_HID) {
-+		return -EINVAL;
-+	}
-+
-+	if (sensor_mode == ipts->sensor_mode)
-+		return 0;
-+
-+	ipts_switch_sensor_mode(ipts, sensor_mode);
-+
-+	return cnt;
-+}
-+
-+static const struct file_operations ipts_mode_dbgfs_fops = {
-+        .open = simple_open,
-+        .read = ipts_dbgfs_mode_read,
-+        .write = ipts_dbgfs_mode_write,
-+        .llseek = generic_file_llseek,
-+};
-+
-+static ssize_t ipts_dbgfs_status_read(struct file *fp, char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	char status[256];
-+	int len = 0;
-+
-+	if (cnt < sizeof(ipts_status_fmt) - 3)
-+		return -EINVAL;
-+
-+	len = scnprintf(status, 256, ipts_status_fmt, ipts->sensor_mode,
-+						     ipts->state);
-+	if (len < 0)
-+		return -EIO;
-+
-+	return simple_read_from_buffer(ubuf, cnt, ppos, status, len);
-+}
-+
-+static const struct file_operations ipts_status_dbgfs_fops = {
-+        .open = simple_open,
-+        .read = ipts_dbgfs_status_read,
-+        .llseek = generic_file_llseek,
-+};
-+
-+void ipts_dbgfs_deregister(ipts_info_t* ipts)
-+{
-+	if (!ipts->dbgfs_dir)
-+		return;
-+
-+	debugfs_remove_recursive(ipts->dbgfs_dir);
-+	ipts->dbgfs_dir = NULL;
-+}
-+
-+int ipts_dbgfs_register(ipts_info_t* ipts, const char *name)
-+{
-+	struct dentry *dir, *f;
-+
-+	dir = debugfs_create_dir(name, NULL);
-+	if (!dir)
-+		return -ENOMEM;
-+
-+        f = debugfs_create_file("mode", S_IRUSR | S_IWUSR, dir,
-+                                ipts, &ipts_mode_dbgfs_fops);
-+        if (!f) {
-+                ipts_err(ipts, "debugfs mode creation failed\n");
-+                goto err;
-+        }
-+
-+        f = debugfs_create_file("status", S_IRUSR, dir,
-+                                ipts, &ipts_status_dbgfs_fops);
-+        if (!f) {
-+                ipts_err(ipts, "debugfs status creation failed\n");
-+                goto err;
-+        }
-+
-+	ipts->dbgfs_dir = dir;
-+
-+	return 0;
-+err:
-+	ipts_dbgfs_deregister(ipts);
-+	return -ENODEV;
-+}
-diff --git a/drivers/misc/ipts/ipts-gfx.c b/drivers/misc/ipts/ipts-gfx.c
-new file mode 100644
-index 0000000..5172777
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-gfx.c
-@@ -0,0 +1,184 @@
-+/*
-+ *
-+ * Intel Integrated Touch Gfx Interface Layer
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/kthread.h>
-+#include <linux/delay.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-state.h"
-+
-+static void gfx_processing_complete(void *data)
-+{
-+	ipts_info_t *ipts = data;
-+
-+	if (ipts_get_state(ipts) == IPTS_STA_RAW_DATA_STARTED) {
-+		schedule_work(&ipts->raw_data_work);
-+		return;
-+	}
-+
-+	ipts_dbg(ipts, "not ready to handle gfx event\n");
-+}
-+
-+static void notify_gfx_status(u32 status, void *data)
-+{
-+	ipts_info_t *ipts = data;
-+
-+	ipts->gfx_status = status;
-+	schedule_work(&ipts->gfx_status_work);
-+}
-+
-+static int connect_gfx(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	intel_ipts_connect_t ipts_connect;
-+
-+	ipts_connect.if_version = IPTS_INTERFACE_V1;
-+	ipts_connect.ipts_cb.workload_complete = gfx_processing_complete;
-+	ipts_connect.ipts_cb.notify_gfx_status = notify_gfx_status;
-+	ipts_connect.data = (void*)ipts;
-+
-+	ret = intel_ipts_connect(&ipts_connect);
-+	if (ret)
-+		return ret;
-+
-+	/* TODO: gfx version check */
-+	ipts->gfx_info.gfx_handle = ipts_connect.gfx_handle;
-+	ipts->gfx_info.ipts_ops = ipts_connect.ipts_ops;
-+
-+	return ret;
-+}
-+
-+static void disconnect_gfx(ipts_info_t *ipts)
-+{
-+	intel_ipts_disconnect(ipts->gfx_info.gfx_handle);
-+}
-+
-+#ifdef RUN_DBG_THREAD
-+#include "../mei/mei_dev.h"
-+
-+static struct task_struct *dbg_thread;
-+
-+static void ipts_print_dbg_info(ipts_info_t* ipts)
-+{
-+        char fw_sts_str[MEI_FW_STATUS_STR_SZ];
-+	u32 *db, *head, *tail;
-+	intel_ipts_wq_info_t* wq_info;
-+
-+	wq_info = &ipts->resource.wq_info;
-+
-+	mei_fw_status_str(ipts->cldev->bus, fw_sts_str, MEI_FW_STATUS_STR_SZ);
-+	pr_info(">> tdt : fw status : %s\n", fw_sts_str);
-+
-+	db = (u32*)wq_info->db_addr;
-+	head = (u32*)wq_info->wq_head_addr;
-+	tail = (u32*)wq_info->wq_tail_addr;
-+	pr_info(">> == DB s:%x, c:%x ==\n", *db, *(db+1));
-+	pr_info(">> == WQ h:%u, t:%u ==\n", *head, *tail);
-+}
-+
-+static int ipts_dbg_thread(void *data)
-+{
-+	ipts_info_t *ipts = (ipts_info_t *)data;
-+
-+	pr_info(">> start debug thread\n");
-+
-+	while (!kthread_should_stop()) {
-+		if (ipts_get_state(ipts) != IPTS_STA_RAW_DATA_STARTED) {
-+			pr_info("state is not IPTS_STA_RAW_DATA_STARTED : %d\n",
-+							ipts_get_state(ipts));
-+			msleep(5000);
-+			continue;
-+		}
-+
-+		ipts_print_dbg_info(ipts);
-+
-+		msleep(3000);
-+	}
-+
-+	return 0;
-+}
-+#endif
-+
-+int ipts_open_gpu(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ret = connect_gfx(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot connect GPU\n");
-+		return ret;
-+	}
-+
-+	ret = ipts->gfx_info.ipts_ops.get_wq_info(ipts->gfx_info.gfx_handle,
-+							&ipts->resource.wq_info);
-+	if (ret) {
-+		ipts_dbg(ipts, "error in get_wq_info\n");
-+		return ret;
-+	}
-+
-+#ifdef	RUN_DBG_THREAD
-+	dbg_thread = kthread_run(ipts_dbg_thread, (void *)ipts, "ipts_debug");
-+#endif
-+
-+	return 0;
-+}
-+
-+void ipts_close_gpu(ipts_info_t *ipts)
-+{
-+	disconnect_gfx(ipts);
-+
-+#ifdef	RUN_DBG_THREAD
-+	kthread_stop(dbg_thread);
-+#endif
-+}
-+
-+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags)
-+{
-+	intel_ipts_mapbuffer_t *buf;
-+	u64 handle;
-+	int ret;
-+
-+	buf = devm_kzalloc(&ipts->cldev->dev, sizeof(*buf), GFP_KERNEL);
-+	if (!buf)
-+		return NULL;
-+
-+	buf->size = size;
-+	buf->flags = flags;
-+
-+	handle = ipts->gfx_info.gfx_handle;
-+	ret = ipts->gfx_info.ipts_ops.map_buffer(handle, buf);
-+	if (ret) {
-+		devm_kfree(&ipts->cldev->dev, buf);
-+		return NULL;
-+	}
-+
-+	return buf;
-+}
-+
-+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf)
-+{
-+	u64 handle;
-+	int ret;
-+
-+	if (!buf)
-+		return;
-+
-+	handle = ipts->gfx_info.gfx_handle;
-+	ret = ipts->gfx_info.ipts_ops.unmap_buffer(handle, buf->buf_handle);
-+
-+	devm_kfree(&ipts->cldev->dev, buf);
-+}
-diff --git a/drivers/misc/ipts/ipts-gfx.h b/drivers/misc/ipts/ipts-gfx.h
-new file mode 100644
-index 0000000..03a5f35
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-gfx.h
-@@ -0,0 +1,24 @@
-+/*
-+ * Intel Precise Touch & Stylus gpu wrapper
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+
-+#ifndef _IPTS_GFX_H_
-+#define _IPTS_GFX_H_
-+
-+int ipts_open_gpu(ipts_info_t *ipts);
-+void ipts_close_gpu(ipts_info_t *ipts);
-+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags);
-+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf);
-+
-+#endif // _IPTS_GFX_H_
-diff --git a/drivers/misc/ipts/ipts-hid.c b/drivers/misc/ipts/ipts-hid.c
-new file mode 100644
-index 0000000..3b3be61
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-hid.c
-@@ -0,0 +1,456 @@
-+/*
-+ * Intel Precise Touch & Stylus HID driver
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/module.h>
-+#include <linux/firmware.h>
-+#include <linux/hid.h>
-+#include <linux/vmalloc.h>
-+
-+#include "ipts.h"
-+#include "ipts-resource.h"
-+#include "ipts-sensor-regs.h"
-+#include "ipts-msg-handler.h"
-+
-+#define BUS_MEI				0x44
-+
-+#define	HID_DESC_INTEL	"intel/ipts/intel_desc.bin"
-+#define	HID_DESC_VENDOR	"intel/ipts/vendor_desc.bin"
-+MODULE_FIRMWARE(HID_DESC_INTEL);
-+MODULE_FIRMWARE(HID_DESC_VENDOR);
-+
-+typedef enum output_buffer_payload_type {
-+	OUTPUT_BUFFER_PAYLOAD_ERROR = 0,
-+	OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT,
-+	OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT,
-+	OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD,
-+	OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER
-+} output_buffer_payload_type_t;
-+
-+typedef struct kernel_output_buffer_header {
-+	u16 length;
-+	u8 payload_type;
-+	u8 reserved1;
-+	touch_hid_private_data_t hid_private_data;
-+	u8 reserved2[28];
-+	u8 data[0];
-+} kernel_output_buffer_header_t;
-+
-+typedef struct kernel_output_payload_error {
-+	u16 severity;
-+	u16 source;
-+	u8 code[4];
-+	char string[128];
-+} kernel_output_payload_error_t;
-+
-+static int ipts_hid_get_hid_descriptor(ipts_info_t *ipts, u8 **desc, int *size)
-+{
-+	u8 *buf;
-+	int hid_size = 0, ret = 0;
-+	const struct firmware *intel_desc = NULL;
-+	const struct firmware *vendor_desc = NULL;
-+	const char *intel_desc_path = HID_DESC_INTEL;
-+	const char *vendor_desc_path = HID_DESC_VENDOR;
-+
-+	ret = request_firmware(&intel_desc, intel_desc_path, &ipts->cldev->dev);
-+	if (ret) {
-+		goto no_hid;
-+	}
-+	hid_size = intel_desc->size;
-+
-+	ret = request_firmware(&vendor_desc, vendor_desc_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_dbg(ipts, "error in reading HID Vendor Descriptor\n");
-+	} else {
-+		hid_size += vendor_desc->size;
-+	}
-+
-+	ipts_dbg(ipts, "hid size = %d\n", hid_size);
-+	buf = vmalloc(hid_size);
-+	if (buf == NULL) {
-+		ret = -ENOMEM;
-+		goto no_mem;
-+	}
-+
-+	memcpy(buf, intel_desc->data, intel_desc->size);
-+	if (vendor_desc) {
-+		memcpy(&buf[intel_desc->size], vendor_desc->data,
-+							vendor_desc->size);
-+		release_firmware(vendor_desc);
-+	}
-+
-+	release_firmware(intel_desc);
-+
-+	*desc = buf;
-+	*size = hid_size;
-+
-+	return 0;
-+no_mem :
-+	if (vendor_desc)
-+		release_firmware(vendor_desc);
-+	release_firmware(intel_desc);
-+
-+no_hid :
-+	return ret;
-+}
-+
-+static int ipts_hid_parse(struct hid_device *hid)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	int ret = 0, size;
-+	u8 *buf;
-+
-+	ipts_dbg(ipts, "ipts_hid_parse() start\n");
-+	ret = ipts_hid_get_hid_descriptor(ipts, &buf, &size);
-+	if (ret != 0) {
-+		ipts_dbg(ipts, "ipts_hid_ipts_get_hid_descriptor ret %d\n", ret);
-+		return -EIO;
-+	}
-+
-+	ret = hid_parse_report(hid, buf, size);
-+	vfree(buf);
-+	if (ret) {
-+		ipts_err(ipts, "hid_parse_report error : %d\n", ret);
-+		goto out;
-+	}
-+
-+	ipts->hid_desc_ready = true;
-+out:
-+	return ret;
-+}
-+
-+static int ipts_hid_start(struct hid_device *hid)
-+{
-+	return 0;
-+}
-+
-+static void ipts_hid_stop(struct hid_device *hid)
-+{
-+	return;
-+}
-+
-+static int ipts_hid_open(struct hid_device *hid)
-+{
-+	return 0;
-+}
-+
-+static void ipts_hid_close(struct hid_device *hid)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+
-+	ipts->hid_desc_ready = false;
-+
-+	return;
-+}
-+
-+static int ipts_hid_send_hid2me_feedback(ipts_info_t *ipts, u32 fb_data_type,
-+							__u8 *buf, size_t count)
-+{
-+	ipts_buffer_info_t *fb_buf;
-+	touch_feedback_hdr_t *feedback;
-+	u8 *payload;
-+	int header_size;
-+	ipts_state_t state;
-+
-+	header_size = sizeof(touch_feedback_hdr_t);
-+
-+	if (count > ipts->resource.hid2me_buffer_size - header_size)
-+		return -EINVAL;
-+
-+	state = ipts_get_state(ipts);
-+	if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED)
-+		return 0;
-+
-+	fb_buf = ipts_get_hid2me_buffer(ipts);
-+	feedback = (touch_feedback_hdr_t *)fb_buf->addr;
-+	payload = fb_buf->addr + header_size;
-+	memset(feedback, 0, header_size);
-+
-+	feedback->feedback_data_type = fb_data_type;
-+	feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE;
-+	feedback->payload_size_bytes = count;
-+	feedback->buffer_id = TOUCH_HID_2_ME_BUFFER_ID;
-+	feedback->protocol_ver = 0;
-+	feedback->reserved[0] = 0xAC;
-+
-+	/* copy payload */
-+	memcpy(payload, buf, count);
-+
-+	ipts_send_feedback(ipts, TOUCH_HID_2_ME_BUFFER_ID, 0);
-+
-+	return 0;
-+}
-+
-+static int ipts_hid_raw_request(struct hid_device *hid,
-+				unsigned char report_number, __u8 *buf,
-+				size_t count, unsigned char report_type,
-+				int reqtype)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	u32 fb_data_type;
-+
-+	ipts_dbg(ipts, "hid raw request => report %d, request %d\n",
-+						 (int)report_type, reqtype);
-+
-+	if (report_type != HID_FEATURE_REPORT)
-+		return 0;
-+
-+	switch (reqtype) {
-+		case HID_REQ_GET_REPORT:
-+			fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES;
-+			break;
-+		case HID_REQ_SET_REPORT:
-+			fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES;
-+			break;
-+		default:
-+			ipts_err(ipts, "raw request not supprted: %d\n", reqtype);
-+			return -EIO;
-+	}
-+
-+	return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count);
-+}
-+
-+static int ipts_hid_output_report(struct hid_device *hid,
-+					__u8 *buf, size_t count)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	u32 fb_data_type;
-+
-+	ipts_dbg(ipts, "hid output report\n");
-+
-+	fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT;
-+
-+	return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count);
-+}
-+
-+static struct hid_ll_driver ipts_hid_ll_driver = {
-+	.parse = ipts_hid_parse,
-+	.start = ipts_hid_start,
-+	.stop = ipts_hid_stop,
-+	.open = ipts_hid_open,
-+	.close = ipts_hid_close,
-+	.raw_request = ipts_hid_raw_request,
-+	.output_report = ipts_hid_output_report,
-+};
-+
-+int ipts_hid_init(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	struct hid_device *hid;
-+
-+	hid = hid_allocate_device();
-+	if (IS_ERR(hid)) {
-+		ret = PTR_ERR(hid);
-+		goto err_dev;
-+	}
-+
-+	hid->driver_data = ipts;
-+	hid->ll_driver = &ipts_hid_ll_driver;
-+	hid->dev.parent = &ipts->cldev->dev;
-+	hid->bus = BUS_MEI;
-+	hid->version = ipts->device_info.fw_rev;
-+	hid->vendor = ipts->device_info.vendor_id;
-+	hid->product = ipts->device_info.device_id;
-+
-+	snprintf(hid->phys, sizeof(hid->phys), "heci3");
-+	snprintf(hid->name, sizeof(hid->name),
-+		 "%s %04hX:%04hX", "ipts", hid->vendor, hid->product);
-+
-+	ret = hid_add_device(hid);
-+	if (ret) {
-+		if (ret != -ENODEV)
-+			ipts_err(ipts, "can't add hid device: %d\n", ret);
-+		goto err_mem_free;
-+	}
-+
-+	ipts->hid = hid;
-+
-+	return 0;
-+
-+err_mem_free:
-+	hid_destroy_device(hid);
-+err_dev:
-+	return ret;
-+}
-+
-+void ipts_hid_release(ipts_info_t *ipts)
-+{
-+	if (!ipts->hid)
-+			return;
-+	hid_destroy_device(ipts->hid);
-+}
-+
-+int ipts_handle_hid_data(ipts_info_t *ipts,
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp)
-+{
-+	touch_raw_data_hdr_t *raw_header;
-+	ipts_buffer_info_t *buffer_info;
-+	touch_feedback_hdr_t *feedback;
-+	u8 *raw_data;
-+	int touch_data_buffer_index;
-+	int transaction_id;
-+	int ret = 0;
-+
-+	touch_data_buffer_index = (int)hid_rsp->touch_data_buffer_index;
-+	buffer_info = ipts_get_touch_data_buffer_hid(ipts);
-+	raw_header = (touch_raw_data_hdr_t *)buffer_info->addr;
-+	transaction_id = raw_header->hid_private_data.transaction_id;
-+
-+	raw_data = (u8*)raw_header + sizeof(touch_raw_data_hdr_t);
-+	if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_HID_REPORT) {
-+		memcpy(ipts->hid_input_report, raw_data,
-+				raw_header->raw_data_size_bytes);
-+
-+		ret = hid_input_report(ipts->hid, HID_INPUT_REPORT,
-+					(u8*)ipts->hid_input_report,
-+					raw_header->raw_data_size_bytes, 1);
-+		if (ret) {
-+			ipts_err(ipts, "error in hid_input_report : %d\n", ret);
-+		}
-+	} else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_GET_FEATURES) {
-+		/* TODO: implement together with "get feature ioctl" */
-+	} else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_ERROR) {
-+		touch_error_t *touch_err = (touch_error_t *)raw_data;
-+
-+		ipts_err(ipts, "error type : %d, me fw error : %x, err reg : %x\n",
-+				touch_err->touch_error_type,
-+				touch_err->touch_me_fw_error.value,
-+				touch_err->touch_error_register.reg_value);
-+	}
-+
-+	/* send feedback data for HID mode */
-+        buffer_info = ipts_get_feedback_buffer(ipts, touch_data_buffer_index);
-+	feedback = (touch_feedback_hdr_t *)buffer_info->addr;
-+	memset(feedback, 0, sizeof(touch_feedback_hdr_t));
-+	feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE;
-+	feedback->payload_size_bytes = 0;
-+	feedback->buffer_id = touch_data_buffer_index;
-+	feedback->protocol_ver = 0;
-+	feedback->reserved[0] = 0xAC;
-+
-+	ret = ipts_send_feedback(ipts, touch_data_buffer_index, transaction_id);
-+
-+	return ret;
-+}
-+
-+static int handle_outputs(ipts_info_t *ipts, int parallel_idx)
-+{
-+	kernel_output_buffer_header_t *out_buf_hdr;
-+	ipts_buffer_info_t *output_buf, *fb_buf = NULL;
-+	u8 *input_report, *payload;
-+	u32 transaction_id;
-+	int i, payload_size, ret = 0, header_size;
-+
-+	header_size = sizeof(kernel_output_buffer_header_t);
-+	output_buf = ipts_get_output_buffers_by_parallel_id(ipts, parallel_idx);
-+	for (i = 0; i < ipts->resource.num_of_outputs; i++) {
-+		out_buf_hdr = (kernel_output_buffer_header_t*)output_buf[i].addr;
-+		if (out_buf_hdr->length < header_size)
-+			continue;
-+
-+		payload_size = out_buf_hdr->length - header_size;
-+		payload = out_buf_hdr->data;
-+
-+		switch(out_buf_hdr->payload_type) {
-+			case OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT:
-+				input_report = ipts->hid_input_report;
-+				memcpy(input_report, payload, payload_size);
-+				hid_input_report(ipts->hid, HID_INPUT_REPORT,
-+						input_report, payload_size, 1);
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT:
-+				ipts_dbg(ipts, "output hid feature report\n");
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD:
-+				ipts_dbg(ipts, "output kernel load\n");
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER:
-+			{
-+				/* send feedback data for raw data mode */
-+                                fb_buf = ipts_get_feedback_buffer(ipts,
-+								parallel_idx);
-+				transaction_id = out_buf_hdr->
-+						hid_private_data.transaction_id;
-+				memcpy(fb_buf->addr, payload, payload_size);
-+				break;
-+			}
-+			case OUTPUT_BUFFER_PAYLOAD_ERROR:
-+			{
-+				kernel_output_payload_error_t *err_payload;
-+
-+				if (payload_size == 0)
-+					break;
-+
-+				err_payload =
-+					(kernel_output_payload_error_t*)payload;
-+
-+				ipts_err(ipts, "error : severity : %d,"
-+						" source : %d,"
-+						" code : %d:%d:%d:%d\n"
-+						"string %s\n",
-+						err_payload->severity,
-+						err_payload->source,
-+						err_payload->code[0],
-+						err_payload->code[1],
-+						err_payload->code[2],
-+						err_payload->code[3],
-+						err_payload->string);
-+				
-+				break;
-+			}
-+			default:
-+				ipts_err(ipts, "invalid output buffer payload\n");
-+				break;
-+		}
-+	}
-+
-+	if (fb_buf) {
-+		ret = ipts_send_feedback(ipts, parallel_idx, transaction_id);
-+		if (ret)
-+			return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static int handle_output_buffers(ipts_info_t *ipts, int cur_idx, int end_idx)
-+{
-+	int max_num_of_buffers = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	do {
-+		cur_idx++; /* cur_idx has last completed so starts with +1 */
-+		cur_idx %= max_num_of_buffers;
-+		handle_outputs(ipts, cur_idx);
-+	} while (cur_idx != end_idx);
-+
-+	return 0;
-+}
-+
-+int ipts_handle_processed_data(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	int current_buffer_idx;
-+	int last_buffer_idx;
-+
-+	current_buffer_idx = *ipts->last_submitted_id;
-+	last_buffer_idx = ipts->last_buffer_completed;
-+
-+	if (current_buffer_idx == last_buffer_idx)
-+		return 0;
-+
-+	ipts->last_buffer_completed = current_buffer_idx;
-+	handle_output_buffers(ipts, last_buffer_idx, current_buffer_idx);
-+
-+	return ret;
-+}
-diff --git a/drivers/misc/ipts/ipts-hid.h b/drivers/misc/ipts/ipts-hid.h
-new file mode 100644
-index 0000000..f1b22c9
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-hid.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Intel Precise Touch & Stylus HID definition
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_HID_H_
-+#define	_IPTS_HID_H_
-+
-+#define	BUS_MEI				0x44
-+
-+#if 0 /* TODO : we have special report ID. will implement them */
-+#define WRITE_CHANNEL_REPORT_ID		0xa
-+#define READ_CHANNEL_REPORT_ID		0xb
-+#define CONFIG_CHANNEL_REPORT_ID	0xd
-+#define VENDOR_INFO_REPORT_ID		0xF
-+#define SINGLE_TOUCH_REPORT_ID		0x40
-+#endif
-+
-+int ipts_hid_init(ipts_info_t *ipts);
-+void ipts_hid_release(ipts_info_t *ipts);
-+int ipts_handle_hid_data(ipts_info_t *ipts,
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp);
-+
-+#endif /* _IPTS_HID_H_ */
-diff --git a/drivers/misc/ipts/ipts-kernel.c b/drivers/misc/ipts/ipts-kernel.c
-new file mode 100644
-index 0000000..ca5e24c
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-kernel.c
-@@ -0,0 +1,1050 @@
-+#include <linux/module.h>
-+#include <linux/firmware.h>
-+#include <linux/vmalloc.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-resource.h"
-+#include "ipts-binary-spec.h"
-+#include "ipts-state.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-gfx.h"
-+
-+#define MAX_IOCL_FILE_NAME_LEN		80
-+#define MAX_IOCL_FILE_PATH_LEN		256
-+
-+#pragma pack(1)
-+typedef struct bin_data_file_info {
-+    u32 io_buffer_type;
-+    u32 flags;
-+    char file_name[MAX_IOCL_FILE_NAME_LEN];
-+} bin_data_file_info_t;
-+
-+typedef struct bin_fw_info {
-+	char fw_name[MAX_IOCL_FILE_NAME_LEN];
-+
-+	/* list of parameters to load a kernel */
-+	s32 vendor_output;	/* output index. -1 for no use */
-+	u32 num_of_data_files;
-+	bin_data_file_info_t data_file[];
-+} bin_fw_info_t;
-+
-+typedef struct bin_fw_list {
-+	u32 num_of_fws;
-+	bin_fw_info_t fw_info[];
-+} bin_fw_list_t;
-+#pragma pack()
-+
-+/* OpenCL kernel */
-+typedef struct bin_workload {
-+	int cmdbuf_index;
-+	int iobuf_input;
-+	int iobuf_output[MAX_NUM_OUTPUT_BUFFERS];
-+} bin_workload_t;
-+
-+typedef struct bin_buffer {
-+	unsigned int handle;
-+	intel_ipts_mapbuffer_t *buf;
-+	bool no_unmap;	/* only releasing vendor kernel unmaps output buffers */
-+} bin_buffer_t;
-+
-+typedef struct bin_alloc_info {
-+	bin_buffer_t *buffs;
-+	int num_of_allocations;
-+	int num_of_outputs;
-+
-+	int num_of_buffers;
-+} bin_alloc_info_t;
-+
-+typedef struct bin_guc_wq_item {
-+	unsigned int batch_offset;
-+	unsigned int size;
-+	char data[];
-+} bin_guc_wq_item_t;
-+
-+typedef struct bin_kernel_info {
-+	bin_workload_t *wl;
-+	bin_alloc_info_t *alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item;
-+	ipts_bin_bufid_patch_t bufid_patch;
-+
-+	bool is_vendor; /* 1: vendor, 0: postprocessing */
-+} bin_kernel_info_t;
-+
-+typedef struct bin_kernel_list {
-+	intel_ipts_mapbuffer_t *bufid_buf;
-+	int num_of_kernels;
-+	bin_kernel_info_t kernels[];
-+} bin_kernel_list_t;
-+
-+typedef struct bin_parse_info {
-+	u8 *data;
-+	int size;
-+	int parsed;
-+
-+	bin_fw_info_t *fw_info;
-+
-+	/* only used by postprocessing */
-+	bin_kernel_info_t *vendor_kernel;
-+	u32 interested_vendor_output; /* interested vendor output index */
-+} bin_parse_info_t;
-+
-+#define BDW_SURFACE_BASE_ADDRESS		0x6101000e
-+#define SURFACE_STATE_OFFSET_WORD		4
-+#define SBA_OFFSET_BYTES			16384
-+#define LASTSUBMITID_DEFAULT_VALUE		-1
-+
-+#define IPTS_FW_PATH_FMT			"intel/ipts/%s"
-+#define IPTS_FW_CONFIG_FILE			"intel/ipts/ipts_fw_config.bin"
-+
-+MODULE_FIRMWARE(IPTS_FW_CONFIG_FILE);
-+
-+#define IPTS_INPUT_ON				((u32)1 << IPTS_INPUT)
-+#define IPTS_OUTPUT_ON				((u32)1 << IPTS_OUTPUT)
-+#define IPTS_CONFIGURATION_ON			((u32)1 << IPTS_CONFIGURATION)
-+#define IPTS_CALIBRATION_ON			((u32)1 << IPTS_CALIBRATION)
-+#define IPTS_FEATURE_ON				((u32)1 << IPTS_FEATURE)
-+
-+#define	DATA_FILE_FLAG_SHARE			0x00000001
-+#define	DATA_FILE_FLAG_ALLOC_CONTIGUOUS		0x00000002
-+
-+static int bin_read_fw(ipts_info_t *ipts, const char *fw_name,
-+						u8* data, int size)
-+{
-+	const struct firmware *fw = NULL;
-+	char fw_path[MAX_IOCL_FILE_PATH_LEN];
-+	int ret = 0;
-+
-+	snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name);
-+	ret = request_firmware(&fw, fw_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_err(ipts, "cannot read fw %s\n", fw_path);
-+		return ret;
-+	}
-+
-+	if (fw->size > size) {
-+		ipts_dbg(ipts, "too small buffer to contain fw data\n");
-+		ret = -EINVAL;
-+		goto rel_return;
-+	}
-+
-+	memcpy(data, fw->data, fw->size);
-+
-+rel_return:
-+	release_firmware(fw);
-+
-+	return ret;
-+}
-+
-+
-+static bin_data_file_info_t* bin_get_data_file_info(bin_fw_info_t* fw_info,
-+							u32 io_buffer_type)
-+{
-+	int i;
-+
-+	for (i = 0; i < fw_info->num_of_data_files; i++) {
-+		if (fw_info->data_file[i].io_buffer_type == io_buffer_type)
-+			break;
-+	}
-+
-+	if (i == fw_info->num_of_data_files)
-+		return NULL;
-+
-+	return &fw_info->data_file[i];
-+}
-+
-+static inline bool is_shared_data(const bin_data_file_info_t *data_file)
-+{
-+	if (data_file)
-+		return (!!(data_file->flags & DATA_FILE_FLAG_SHARE));
-+
-+	return false;
-+}
-+
-+static inline bool is_alloc_cont_data(const bin_data_file_info_t *data_file)
-+{
-+	if (data_file)
-+		return (!!(data_file->flags & DATA_FILE_FLAG_ALLOC_CONTIGUOUS));
-+
-+	return false;
-+}
-+
-+static inline bool is_parsing_vendor_kernel(const bin_parse_info_t *parse_info)
-+{
-+	/* vendor_kernel == null while loading itself(vendor kernel) */
-+	return parse_info->vendor_kernel == NULL;
-+}
-+
-+static int bin_read_allocation_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info)
-+{
-+	ipts_bin_alloc_list_t *alloc_list;
-+	int alloc_idx, parallel_idx, num_of_parallels, buf_idx, num_of_buffers;
-+	int parsed, size;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+
-+	alloc_list = (ipts_bin_alloc_list_t *)&parse_info->data[parsed];
-+
-+	/* validation check */
-+	if (sizeof(alloc_list->num) > size - parsed)
-+		return -EINVAL;
-+
-+	/* read the number of aloocations */
-+	parsed += sizeof(alloc_list->num);
-+
-+	/* validation check */
-+	if (sizeof(alloc_list->alloc[0]) * alloc_list->num > size - parsed)
-+		return -EINVAL;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	num_of_buffers = num_of_parallels * alloc_list->num + num_of_parallels;
-+
-+	alloc_info->buffs = vmalloc(sizeof(bin_buffer_t) * num_of_buffers);
-+	if (alloc_info->buffs == NULL)
-+		return -ENOMEM;
-+
-+	memset(alloc_info->buffs, 0, sizeof(bin_buffer_t) * num_of_buffers);
-+	for (alloc_idx = 0; alloc_idx < alloc_list->num; alloc_idx++) {
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+								parallel_idx++) {
-+			buf_idx = alloc_idx + (parallel_idx * alloc_list->num);
-+			alloc_info->buffs[buf_idx].handle =
-+					alloc_list->alloc[alloc_idx].handle;
-+
-+		}
-+
-+		parsed += sizeof(alloc_list->alloc[0]);
-+	}
-+
-+	parse_info->parsed = parsed;
-+	alloc_info->num_of_allocations = alloc_list->num;
-+	alloc_info->num_of_buffers = num_of_buffers;
-+
-+	ipts_dbg(ipts, "number of allocations = %d, buffers = %d\n",
-+						alloc_info->num_of_allocations,
-+						alloc_info->num_of_buffers);
-+
-+	return 0;
-+}
-+
-+static void patch_SBA(u32 *buf_addr, u64 gpu_addr, int size)
-+{
-+	u64 *stateBase;
-+	u64 SBA;
-+	u32 inst;
-+	int i;
-+
-+	SBA = gpu_addr + SBA_OFFSET_BYTES;
-+
-+	for (i = 0; i < size/4; i++) {
-+		inst = buf_addr[i];
-+		if (inst == BDW_SURFACE_BASE_ADDRESS) {
-+			stateBase = (u64*)&buf_addr[i + SURFACE_STATE_OFFSET_WORD];
-+			*stateBase |= SBA;
-+			*stateBase |= 0x01; // enable
-+			break;
-+		}
-+	}
-+}
-+
-+static int bin_read_cmd_buffer(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_cmdbuf_t *cmd;
-+	intel_ipts_mapbuffer_t *buf;
-+	int cmdbuf_idx, size, parsed, parallel_idx, num_of_parallels;
-+
-+	size = parse_info->size;
-+	parsed = parse_info->parsed;
-+
-+	cmd = (ipts_bin_cmdbuf_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(cmd->size) > size - parsed)
-+		return -EINVAL;
-+
-+	parsed += sizeof(cmd->size);
-+	if (cmd->size > size - parsed)
-+		return -EINVAL;
-+
-+	ipts_dbg(ipts, "cmd buf size = %d\n", cmd->size);
-+		
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	/* command buffers are located after the other allocations */
-+	cmdbuf_idx = num_of_parallels * alloc_info->num_of_allocations;
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		buf = ipts_map_buffer(ipts, cmd->size, 0);
-+		if (buf == NULL)
-+			return -ENOMEM;
-+
-+		ipts_dbg(ipts, "cmd_idx[%d] = %d, g:0x%p, c:0x%p\n", parallel_idx,
-+					cmdbuf_idx, buf->gfx_addr, buf->cpu_addr);
-+
-+		memcpy((void *)buf->cpu_addr, &(cmd->data[0]), cmd->size);
-+		patch_SBA(buf->cpu_addr, (u64)buf->gfx_addr, cmd->size);
-+		alloc_info->buffs[cmdbuf_idx].buf = buf;
-+		wl[parallel_idx].cmdbuf_index = cmdbuf_idx;
-+
-+		cmdbuf_idx++;
-+	}
-+
-+	parsed += cmd->size;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_find_alloc(ipts_info_t *ipts,
-+					bin_alloc_info_t *alloc_info,
-+					u32 handle)
-+{
-+	int i;
-+
-+	for (i = 0; i < alloc_info->num_of_allocations; i++) {
-+		if (alloc_info->buffs[i].handle == handle)
-+			return i;
-+	}
-+
-+	return -1;
-+}
-+
-+static intel_ipts_mapbuffer_t* bin_get_vendor_kernel_output(
-+						bin_parse_info_t *parse_info,
-+						int parallel_idx)
-+{
-+	bin_kernel_info_t *vendor = parse_info->vendor_kernel;
-+	bin_alloc_info_t *alloc_info;
-+	int buf_idx, vendor_output_idx;
-+
-+	alloc_info = vendor->alloc_info;
-+	vendor_output_idx = parse_info->interested_vendor_output;
-+
-+	if (vendor_output_idx >= alloc_info->num_of_outputs)
-+		return NULL;
-+
-+	buf_idx = vendor->wl[parallel_idx].iobuf_output[vendor_output_idx];
-+	return alloc_info->buffs[buf_idx].buf;
-+}
-+
-+static int bin_read_res_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_res_list_t *res_list;
-+	ipts_bin_res_t *res;
-+	intel_ipts_mapbuffer_t *buf;
-+	bin_data_file_info_t *data_file;
-+	u8 *bin_data;
-+	int i, size, parsed, parallel_idx, num_of_parallels, output_idx = -1;
-+	int buf_idx, num_of_alloc;
-+	u32 buf_size, flags, io_buf_type;
-+	bool initialize;
-+	
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	bin_data = parse_info->data;
-+
-+	res_list = (ipts_bin_res_list_t *)&parse_info->data[parsed];
-+	if (sizeof(res_list->num) > (size - parsed))
-+		return -EINVAL;
-+	parsed += sizeof(res_list->num);
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	ipts_dbg(ipts, "number of resources %u\n", res_list->num);
-+	for (i = 0; i < res_list->num; i++) {
-+		initialize = false; 
-+		io_buf_type = 0;
-+		flags = 0;
-+
-+		/* initial data */
-+		data_file = NULL;
-+
-+		res = (ipts_bin_res_t *)(&(bin_data[parsed]));
-+		if (sizeof(res[0]) > (size - parsed)) {
-+			return -EINVAL;
-+		}
-+
-+		ipts_dbg(ipts, "Resource(%d):handle 0x%08x type %u init %u"
-+				" size %u alsigned %u\n",
-+				i, res->handle, res->type, res->initialize,
-+				res->size, res->aligned_size);
-+                parsed += sizeof(res[0]);
-+
-+		if (res->initialize) {
-+			if (res->size > (size - parsed)) {
-+				return -EINVAL;
-+			}
-+			parsed += res->size;
-+		}
-+
-+		initialize = res->initialize;
-+		if (initialize && res->size > sizeof(ipts_bin_io_header_t)) {
-+			ipts_bin_io_header_t *io_hdr;
-+			io_hdr = (ipts_bin_io_header_t *)(&res->data[0]);
-+			if (strncmp(io_hdr->str, "INTELTOUCH", 10) == 0) {
-+				data_file = bin_get_data_file_info(
-+							parse_info->fw_info,
-+							(u32)io_hdr->type);
-+				switch (io_hdr->type) {
-+				case IPTS_INPUT:
-+					ipts_dbg(ipts, "input detected\n");
-+					io_buf_type = IPTS_INPUT_ON;
-+					flags = IPTS_BUF_FLAG_CONTIGUOUS;
-+					break;
-+				case IPTS_OUTPUT:
-+					ipts_dbg(ipts, "output detected\n");
-+					io_buf_type = IPTS_OUTPUT_ON;
-+					output_idx++;
-+					break;
-+				default:
-+					if ((u32)io_hdr->type > 31) {
-+						ipts_err(ipts,
-+							"invalid io buffer : %u\n",
-+							(u32)io_hdr->type);
-+						continue;
-+					}
-+
-+					if (is_alloc_cont_data(data_file))
-+						flags = IPTS_BUF_FLAG_CONTIGUOUS;
-+
-+					io_buf_type = ((u32)1 << (u32)io_hdr->type);
-+					ipts_dbg(ipts, "special io buffer %u\n",
-+								io_hdr->type);
-+					break;
-+				}
-+
-+				initialize = false;
-+			}
-+		}
-+
-+		num_of_alloc = alloc_info->num_of_allocations;
-+		buf_idx = bin_find_alloc(ipts, alloc_info, res->handle);
-+		if (buf_idx == -1) {
-+			ipts_dbg(ipts, "cannot find alloc info\n");
-+			return -EINVAL;
-+		}
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+					parallel_idx++, buf_idx += num_of_alloc) {
-+			if (!res->aligned_size)
-+				continue;
-+
-+			if (!(parallel_idx == 0 ||
-+				    (io_buf_type && !is_shared_data(data_file))))
-+				continue;
-+
-+			buf_size = res->aligned_size;
-+			if (io_buf_type & IPTS_INPUT_ON) {
-+				buf_size = max_t(u32,
-+						ipts->device_info.frame_size,
-+						buf_size);
-+				wl[parallel_idx].iobuf_input = buf_idx;
-+			} else if (io_buf_type & IPTS_OUTPUT_ON) {
-+				wl[parallel_idx].iobuf_output[output_idx] = buf_idx;
-+
-+				if (!is_parsing_vendor_kernel(parse_info) &&
-+								output_idx > 0) {
-+					ipts_err(ipts,
-+						"postproc with more than one inout"
-+						" is not supported : %d\n", output_idx);
-+					return -EINVAL;
-+				}
-+			}
-+
-+			if (!is_parsing_vendor_kernel(parse_info) &&
-+						io_buf_type & IPTS_OUTPUT_ON) {
-+				buf = bin_get_vendor_kernel_output(
-+								parse_info,
-+								parallel_idx);
-+				alloc_info->buffs[buf_idx].no_unmap = true;
-+			} else
-+				buf = ipts_map_buffer(ipts, buf_size, flags);
-+
-+			if (buf == NULL) {
-+				ipts_dbg(ipts, "ipts_map_buffer failed\n");
-+				return -ENOMEM;
-+			}
-+
-+			if (initialize) {
-+				memcpy((void *)buf->cpu_addr, &(res->data[0]),
-+								res->size);
-+			} else {
-+				if (data_file && strlen(data_file->file_name)) {
-+					bin_read_fw(ipts, data_file->file_name,
-+                                                        buf->cpu_addr, buf_size);
-+				} else if (is_parsing_vendor_kernel(parse_info) ||
-+						!(io_buf_type & IPTS_OUTPUT_ON)) {
-+					memset((void *)buf->cpu_addr, 0, res->size);
-+				}
-+			}
-+
-+			alloc_info->buffs[buf_idx].buf = buf;
-+		}
-+	}
-+
-+        alloc_info->num_of_outputs = output_idx + 1;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_read_patch_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_patch_list_t *patch_list;
-+	ipts_bin_patch_t *patch;
-+	intel_ipts_mapbuffer_t *cmd = NULL;
-+	u8 *batch;
-+	int parsed, size, i, parallel_idx, num_of_parallels, cmd_idx, buf_idx;
-+	unsigned int gtt_offset;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	patch_list = (ipts_bin_patch_list_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(patch_list->num) > (size - parsed)) {
-+		return -EFAULT;
-+	}
-+	parsed += sizeof(patch_list->num);
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	patch = (ipts_bin_patch_t *)(&patch_list->patch[0]);
-+	for (i = 0; i < patch_list->num; i++) {
-+		if (sizeof(patch_list->patch[0]) > (size - parsed)) {
-+			return -EFAULT;
-+		}
-+
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+								parallel_idx++) {
-+			cmd_idx = wl[parallel_idx].cmdbuf_index;
-+			buf_idx = patch[i].index + parallel_idx *
-+						alloc_info->num_of_allocations;
-+
-+			if (alloc_info->buffs[buf_idx].buf == NULL) {
-+				/* buffer shared */
-+				buf_idx = patch[i].index;
-+			}
-+
-+			cmd = alloc_info->buffs[cmd_idx].buf;
-+			batch = (char *)(u64)cmd->cpu_addr;
-+
-+			gtt_offset = 0;
-+			if(alloc_info->buffs[buf_idx].buf != NULL) {
-+				gtt_offset = (u32)(u64)
-+					alloc_info->buffs[buf_idx].buf->gfx_addr;
-+			} 
-+			gtt_offset += patch[i].alloc_offset;
-+
-+			batch += patch[i].patch_offset;
-+			*(u32*)batch = gtt_offset;
-+		}
-+
-+		parsed += sizeof(patch_list->patch[0]);
-+	}
-+
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_read_guc_wq_item(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_guc_wq_item_t **guc_wq_item)
-+{
-+	ipts_bin_guc_wq_info_t *bin_guc_wq;
-+	bin_guc_wq_item_t *item;
-+	u8 *wi_data;
-+	int size, parsed, hdr_size, wi_size;
-+	int i, batch_offset;
-+	
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	bin_guc_wq = (ipts_bin_guc_wq_info_t *)&parse_info->data[parsed];
-+
-+	wi_size = bin_guc_wq->size;
-+	wi_data = bin_guc_wq->data;
-+	batch_offset = bin_guc_wq->batch_offset;
-+	ipts_dbg(ipts, "wi size = %d, bt offset = %d\n", wi_size, batch_offset);
-+	for (i = 0; i < wi_size / sizeof(u32); i++) {
-+		ipts_dbg(ipts, "wi[%d] = 0x%08x\n", i, *((u32*)wi_data + i));
-+	}
-+	hdr_size = sizeof(bin_guc_wq->size) + sizeof(bin_guc_wq->batch_offset);
-+
-+	if (hdr_size > (size - parsed)) {
-+		return -EINVAL;
-+	}
-+	parsed += hdr_size;
-+
-+	item = vmalloc(sizeof(bin_guc_wq_item_t) + wi_size);
-+	if (item == NULL)
-+		return -ENOMEM;
-+
-+	item->size = wi_size;
-+	item->batch_offset = batch_offset;
-+	memcpy(item->data, wi_data, wi_size);
-+
-+	*guc_wq_item = item;
-+
-+	parsed += wi_size;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_setup_guc_workqueue(ipts_info_t *ipts,
-+					bin_kernel_list_t *kernel_list)
-+{
-+	bin_alloc_info_t *alloc_info;
-+	bin_workload_t *wl;
-+	bin_kernel_info_t *kernel;
-+	u8 *wq_start, *wq_addr, *wi_data;
-+	bin_buffer_t *bin_buf;
-+	int wq_size, wi_size, parallel_idx, cmd_idx, k_idx, iter_size;
-+	int i, num_of_parallels, batch_offset, k_num, total_workload;
-+	
-+	wq_addr = (u8*)ipts->resource.wq_info.wq_addr;
-+	wq_size = ipts->resource.wq_info.wq_size;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	total_workload = ipts_get_wq_item_size(ipts);
-+	k_num = kernel_list->num_of_kernels;
-+
-+	iter_size = total_workload * num_of_parallels;
-+	if (wq_size % iter_size) {
-+		ipts_err(ipts, "wq item cannot fit into wq\n");
-+		return -EINVAL;
-+	}
-+
-+	wq_start = wq_addr;
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+							parallel_idx++) {
-+		kernel = &kernel_list->kernels[0];
-+		for (k_idx = 0; k_idx < k_num; k_idx++, kernel++) {
-+			wl = kernel->wl;
-+			alloc_info = kernel->alloc_info;
-+
-+			batch_offset = kernel->guc_wq_item->batch_offset;
-+			wi_size = kernel->guc_wq_item->size;
-+			wi_data = &kernel->guc_wq_item->data[0];
-+			
-+			cmd_idx = wl[parallel_idx].cmdbuf_index;
-+			bin_buf = &alloc_info->buffs[cmd_idx];
-+
-+			/* Patch the WQ Data with proper batch buffer offset */
-+			*(u32*)(wi_data + batch_offset) =
-+				(u32)(unsigned long)(bin_buf->buf->gfx_addr);
-+
-+			memcpy(wq_addr, wi_data, wi_size);
-+
-+			wq_addr += wi_size;
-+		}
-+	}
-+
-+	for (i = 0; i < (wq_size / iter_size) - 1; i++) {
-+		memcpy(wq_addr, wq_start, iter_size);
-+		wq_addr += iter_size;
-+	}
-+
-+	return 0;
-+}
-+
-+static int bin_read_bufid_patch(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					ipts_bin_bufid_patch_t *bufid_patch)
-+{
-+	ipts_bin_bufid_patch_t *patch;
-+	int size, parsed;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	patch = (ipts_bin_bufid_patch_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(ipts_bin_bufid_patch_t) > (size - parsed)) {
-+		ipts_dbg(ipts, "invalid bufid info\n");
-+		return -EINVAL;
-+	}
-+	parsed += sizeof(ipts_bin_bufid_patch_t);
-+
-+	memcpy(bufid_patch, patch, sizeof(ipts_bin_bufid_patch_t));
-+
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_setup_bufid_buffer(ipts_info_t *ipts, bin_kernel_list_t *kernel_list)
-+{
-+	intel_ipts_mapbuffer_t *buf, *cmd_buf;
-+	bin_kernel_info_t *last_kernel;
-+	bin_alloc_info_t *alloc_info;
-+	bin_workload_t *wl;
-+	u8 *batch;
-+	int parallel_idx, num_of_parallels, cmd_idx;
-+	u32 mem_offset, imm_offset;
-+
-+	buf = ipts_map_buffer(ipts, PAGE_SIZE, 0);
-+	if (!buf) {
-+		return -ENOMEM;
-+	}
-+
-+	last_kernel = &kernel_list->kernels[kernel_list->num_of_kernels - 1];
-+
-+	mem_offset = last_kernel->bufid_patch.mem_offset;
-+	imm_offset = last_kernel->bufid_patch.imm_offset;
-+	wl = last_kernel->wl;
-+	alloc_info = last_kernel->alloc_info;
-+
-+	/* Initialize the buffer with default value */
-+        *((u32*)buf->cpu_addr) = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->current_buffer_index = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->last_buffer_completed = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->last_submitted_id = (int*)buf->cpu_addr;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		cmd_idx = wl[parallel_idx].cmdbuf_index;
-+		cmd_buf = alloc_info->buffs[cmd_idx].buf;
-+		batch = (u8*)(u64)cmd_buf->cpu_addr;
-+
-+		*((u32*)(batch + mem_offset)) = (u32)(u64)(buf->gfx_addr);
-+                *((u32*)(batch + imm_offset)) = parallel_idx;
-+	}
-+
-+	kernel_list->bufid_buf = buf;
-+
-+	return 0;
-+}
-+
-+static void unmap_buffers(ipts_info_t *ipts, bin_alloc_info_t *alloc_info)
-+{
-+	bin_buffer_t *buffs;
-+	int i, num_of_buffers;
-+
-+	num_of_buffers = alloc_info->num_of_buffers;
-+	buffs = &alloc_info->buffs[0];
-+
-+	for (i = 0; i < num_of_buffers; i++) {
-+		if (buffs[i].no_unmap != true && buffs[i].buf != NULL)
-+			ipts_unmap_buffer(ipts, buffs[i].buf);
-+	}
-+}
-+
-+static int load_kernel(ipts_info_t *ipts, bin_parse_info_t *parse_info,
-+						bin_kernel_info_t *kernel)
-+{
-+	ipts_bin_header_t *hdr;
-+	bin_workload_t *wl;
-+	bin_alloc_info_t *alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item = NULL;
-+	ipts_bin_bufid_patch_t bufid_patch;
-+	int num_of_parallels, ret;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+        /* check header version and magic numbers */
-+	hdr = (ipts_bin_header_t *)parse_info->data;
-+	if (hdr->version != IPTS_BIN_HEADER_VERSION ||
-+					strncmp(hdr->str, "IOCL", 4) != 0) {
-+		ipts_err(ipts, "binary header is not correct version = %d, "
-+				"string = %c%c%c%c\n", hdr->version,
-+				hdr->str[0], hdr->str[1],
-+				hdr->str[2], hdr->str[3] );
-+		return -EINVAL;
-+	}
-+
-+	parse_info->parsed = sizeof(ipts_bin_header_t);
-+	wl = vmalloc(sizeof(bin_workload_t) * num_of_parallels);
-+	if (wl == NULL)
-+		return -ENOMEM;
-+	memset(wl, 0, sizeof(bin_workload_t) * num_of_parallels);
-+
-+	alloc_info = vmalloc(sizeof(bin_alloc_info_t));
-+	if (alloc_info == NULL) {
-+		vfree(wl);
-+		return -ENOMEM;
-+	}
-+	memset(alloc_info, 0, sizeof(bin_alloc_info_t));
-+
-+        ipts_dbg(ipts, "kernel setup(size : %d)\n", parse_info->size);
-+
-+	ret = bin_read_allocation_list(ipts, parse_info, alloc_info);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_allocation_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_cmd_buffer(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_cmd_buffer\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_res_list(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_res_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_patch_list(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_patch_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_guc_wq_item(ipts, parse_info, &guc_wq_item);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_guc_workqueue\n");
-+		goto setup_error;
-+	}
-+
-+	memset(&bufid_patch, 0, sizeof(bufid_patch));
-+	ret = bin_read_bufid_patch(ipts, parse_info, &bufid_patch);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_bufid_patch\n");
-+		goto setup_error;
-+	}
-+
-+	kernel->wl = wl;
-+	kernel->alloc_info = alloc_info;
-+	kernel->is_vendor = is_parsing_vendor_kernel(parse_info);
-+	kernel->guc_wq_item = guc_wq_item;
-+	memcpy(&kernel->bufid_patch, &bufid_patch, sizeof(bufid_patch));
-+
-+        return 0;
-+
-+setup_error:
-+	vfree(guc_wq_item);
-+
-+	unmap_buffers(ipts, alloc_info);
-+
-+	vfree(alloc_info->buffs);
-+	vfree(alloc_info);
-+	vfree(wl);
-+
-+	return ret;
-+}
-+
-+void bin_setup_input_output(ipts_info_t *ipts, bin_kernel_list_t *kernel_list)
-+{
-+	bin_kernel_info_t *vendor_kernel;
-+	bin_workload_t *wl;
-+	intel_ipts_mapbuffer_t *buf;
-+	bin_alloc_info_t *alloc_info;
-+	int parallel_idx, num_of_parallels, i, buf_idx;
-+
-+	vendor_kernel = &kernel_list->kernels[0];
-+
-+	wl = vendor_kernel->wl;
-+	alloc_info = vendor_kernel->alloc_info;
-+	ipts->resource.num_of_outputs = alloc_info->num_of_outputs;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		buf_idx = wl[parallel_idx].iobuf_input;
-+		buf = alloc_info->buffs[buf_idx].buf;
-+
-+		ipts_dbg(ipts, "in_buf[%d](%d) c:%p, p:%p, g:%p\n",
-+					parallel_idx, buf_idx, (void*)buf->cpu_addr,
-+					(void*)buf->phy_addr, (void*)buf->gfx_addr);
-+
-+		ipts_set_input_buffer(ipts, parallel_idx, buf->cpu_addr,
-+								buf->phy_addr);
-+
-+		for (i = 0; i < alloc_info->num_of_outputs; i++) {
-+			buf_idx = wl[parallel_idx].iobuf_output[i];
-+			buf = alloc_info->buffs[buf_idx].buf;
-+
-+			ipts_dbg(ipts, "out_buf[%d][%d] c:%p, p:%p, g:%p\n",
-+					parallel_idx, i, (void*)buf->cpu_addr,
-+					(void*)buf->phy_addr, (void*)buf->gfx_addr);
-+
-+			ipts_set_output_buffer(ipts, parallel_idx, i,
-+					buf->cpu_addr, buf->phy_addr);
-+		}
-+	}
-+}
-+
-+static void unload_kernel(ipts_info_t *ipts, bin_kernel_info_t *kernel)
-+{
-+	bin_alloc_info_t *alloc_info = kernel->alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item = kernel->guc_wq_item;
-+
-+	if (guc_wq_item) {
-+		vfree(guc_wq_item);
-+	}
-+
-+	if (alloc_info) {
-+		unmap_buffers(ipts, alloc_info);
-+
-+		vfree(alloc_info->buffs);
-+		vfree(alloc_info);
-+	}
-+}
-+
-+static int setup_kernel(ipts_info_t *ipts, bin_fw_list_t *fw_list)
-+{
-+	bin_kernel_list_t *kernel_list = NULL;
-+	bin_kernel_info_t *kernel = NULL;
-+	const struct firmware *fw = NULL;
-+	bin_workload_t *wl;
-+	bin_fw_info_t *fw_info;
-+	char *fw_name, *fw_data;
-+	bin_parse_info_t parse_info;
-+	int ret = 0, kernel_idx = 0, num_of_kernels = 0;
-+	int vendor_output_idx, total_workload = 0;
-+	char fw_path[MAX_IOCL_FILE_PATH_LEN];
-+
-+	num_of_kernels = fw_list->num_of_fws;
-+	kernel_list = vmalloc(sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list));
-+	if (kernel_list == NULL)
-+		return -ENOMEM;
-+
-+	memset(kernel_list, 0, sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list));
-+	kernel_list->num_of_kernels = num_of_kernels;
-+	kernel = &kernel_list->kernels[0];
-+
-+	fw_data = (char *)&fw_list->fw_info[0];
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		fw_info = (bin_fw_info_t *)fw_data;
-+		fw_name = &fw_info->fw_name[0];
-+		vendor_output_idx = fw_info->vendor_output;
-+		snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name);
-+		ret = request_firmware(&fw, (const char *)fw_path, &ipts->cldev->dev);
-+		if (ret) {
-+			ipts_err(ipts, "cannot read fw %s\n", fw_path);
-+			goto error_exit;
-+		}
-+
-+		parse_info.data = (u8*)fw->data;
-+		parse_info.size = fw->size;
-+		parse_info.parsed = 0;
-+		parse_info.fw_info = fw_info;
-+		parse_info.vendor_kernel = (kernel_idx == 0) ? NULL : &kernel[0];
-+		parse_info.interested_vendor_output = vendor_output_idx;
-+
-+		ret = load_kernel(ipts, &parse_info, &kernel[kernel_idx]);
-+		if (ret) {
-+			ipts_err(ipts, "do_setup_kernel error : %d\n", ret);
-+			release_firmware(fw);
-+			goto error_exit;
-+		}
-+
-+		release_firmware(fw);
-+
-+		total_workload += kernel[kernel_idx].guc_wq_item->size;
-+
-+		/* advance to the next kernel */
-+		fw_data += sizeof(bin_fw_info_t);
-+		fw_data += sizeof(bin_data_file_info_t) * fw_info->num_of_data_files;
-+	}
-+
-+	ipts_set_wq_item_size(ipts, total_workload);
-+	
-+	ret = bin_setup_guc_workqueue(ipts, kernel_list);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error setup_guc_workqueue\n");
-+		goto error_exit;
-+	}
-+
-+	ret = bin_setup_bufid_buffer(ipts, kernel_list);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error setup_lastbubmit_buffer\n");
-+		goto error_exit;
-+	}
-+
-+	bin_setup_input_output(ipts, kernel_list);
-+
-+	/* workload is not needed during run-time so free them */
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		wl = kernel[kernel_idx].wl;
-+		vfree(wl);
-+	}
-+
-+	ipts->kernel_handle = (u64)kernel_list;
-+
-+	return 0;
-+
-+error_exit:
-+
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		wl = kernel[kernel_idx].wl;
-+		vfree(wl);
-+		unload_kernel(ipts, &kernel[kernel_idx]);
-+	}
-+
-+	vfree(kernel_list);
-+
-+	return ret;
-+}
-+
-+
-+static void release_kernel(ipts_info_t *ipts)
-+{
-+	bin_kernel_list_t *kernel_list;
-+	bin_kernel_info_t *kernel;
-+	int k_idx, k_num;
-+
-+	kernel_list = (bin_kernel_list_t *)ipts->kernel_handle;
-+	k_num = kernel_list->num_of_kernels;
-+	kernel = &kernel_list->kernels[0];
-+
-+	for (k_idx = 0; k_idx < k_num; k_idx++) {
-+		unload_kernel(ipts, kernel);
-+		kernel++;
-+	}	
-+
-+	ipts_unmap_buffer(ipts, kernel_list->bufid_buf);
-+
-+	vfree(kernel_list);
-+	ipts->kernel_handle = 0;
-+}
-+
-+int ipts_init_kernels(ipts_info_t *ipts)
-+{
-+	const struct firmware *config_fw = NULL;
-+	const char *config_fw_path = IPTS_FW_CONFIG_FILE;
-+	bin_fw_list_t *fw_list;
-+	int ret;
-+
-+	ret = ipts_open_gpu(ipts);
-+	if (ret) {
-+		ipts_err(ipts, "open gpu error : %d\n", ret);
-+		return ret;
-+	}
-+
-+	ret = request_firmware(&config_fw, config_fw_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_err(ipts, "request firmware error : %d\n", ret);
-+		goto close_gpu;
-+	}
-+
-+	fw_list = (bin_fw_list_t *)config_fw->data;
-+	ret = setup_kernel(ipts, fw_list);
-+	if (ret) {
-+		ipts_err(ipts, "setup kernel error : %d\n", ret);
-+		goto close_firmware;
-+	}
-+
-+	release_firmware(config_fw);
-+
-+	return ret;
-+
-+close_firmware:
-+	release_firmware(config_fw);
-+
-+close_gpu:
-+	ipts_close_gpu(ipts);
-+
-+	return ret;
-+}
-+
-+void ipts_release_kernels(ipts_info_t *ipts)
-+{
-+	release_kernel(ipts);
-+	ipts_close_gpu(ipts);
-+}
-diff --git a/drivers/misc/ipts/ipts-kernel.h b/drivers/misc/ipts/ipts-kernel.h
-new file mode 100644
-index 0000000..0e7f139
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-kernel.h
-@@ -0,0 +1,23 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus Linux driver
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _ITPS_GFX_H
-+#define _ITPS_GFX_H
-+
-+int ipts_init_kernels(ipts_info_t *ipts);
-+void ipts_release_kernels(ipts_info_t *ipts);
-+
-+#endif
-diff --git a/drivers/misc/ipts/ipts-mei-msgs.h b/drivers/misc/ipts/ipts-mei-msgs.h
-new file mode 100644
-index 0000000..8ca1468
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-mei-msgs.h
-@@ -0,0 +1,585 @@
-+/*
-+ * Precise Touch HECI Message
-+ *
-+ * Copyright (c) 2013-2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_MEI_MSGS_H_
-+#define _IPTS_MEI_MSGS_H_
-+
-+#include "ipts-sensor-regs.h"
-+
-+#pragma pack(1)
-+
-+
-+// Initial protocol version
-+#define TOUCH_HECI_CLIENT_PROTOCOL_VERSION      10
-+
-+// GUID that identifies the Touch HECI client.
-+#define TOUCH_HECI_CLIENT_GUID  \
-+            {0x3e8d0870, 0x271a, 0x4208, {0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04}}
-+
-+
-+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch
-+#ifndef C_ASSERT
-+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
-+#endif
-+
-+
-+// General Type Defines for compatibility with HID driver and BIOS
-+#ifndef BIT0
-+#define BIT0 1
-+#endif
-+#ifndef BIT1
-+#define BIT1 2
-+#endif
-+#ifndef BIT2
-+#define BIT2 4
-+#endif
-+
-+
-+#define TOUCH_SENSOR_GET_DEVICE_INFO_CMD        0x00000001
-+#define TOUCH_SENSOR_GET_DEVICE_INFO_RSP        0x80000001
-+
-+
-+#define TOUCH_SENSOR_SET_MODE_CMD               0x00000002
-+#define TOUCH_SENSOR_SET_MODE_RSP               0x80000002
-+
-+
-+#define TOUCH_SENSOR_SET_MEM_WINDOW_CMD         0x00000003
-+#define TOUCH_SENSOR_SET_MEM_WINDOW_RSP         0x80000003
-+
-+
-+#define TOUCH_SENSOR_QUIESCE_IO_CMD             0x00000004
-+#define TOUCH_SENSOR_QUIESCE_IO_RSP             0x80000004
-+
-+
-+#define TOUCH_SENSOR_HID_READY_FOR_DATA_CMD     0x00000005
-+#define TOUCH_SENSOR_HID_READY_FOR_DATA_RSP     0x80000005
-+
-+
-+#define TOUCH_SENSOR_FEEDBACK_READY_CMD         0x00000006
-+#define TOUCH_SENSOR_FEEDBACK_READY_RSP         0x80000006
-+
-+
-+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD       0x00000007
-+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP       0x80000007
-+
-+
-+#define TOUCH_SENSOR_NOTIFY_DEV_READY_CMD       0x00000008
-+#define TOUCH_SENSOR_NOTIFY_DEV_READY_RSP       0x80000008
-+
-+
-+#define TOUCH_SENSOR_SET_POLICIES_CMD           0x00000009
-+#define TOUCH_SENSOR_SET_POLICIES_RSP           0x80000009
-+
-+
-+#define TOUCH_SENSOR_GET_POLICIES_CMD           0x0000000A
-+#define TOUCH_SENSOR_GET_POLICIES_RSP           0x8000000A
-+
-+
-+#define TOUCH_SENSOR_RESET_CMD                  0x0000000B
-+#define TOUCH_SENSOR_RESET_RSP                  0x8000000B
-+
-+
-+#define TOUCH_SENSOR_READ_ALL_REGS_CMD          0x0000000C
-+#define TOUCH_SENSOR_READ_ALL_REGS_RSP          0x8000000C
-+
-+
-+#define TOUCH_SENSOR_CMD_ERROR_RSP              0x8FFFFFFF  // M2H: ME sends this message to indicate previous command was unrecognized/unsupported
-+
-+
-+
-+//*******************************************************************
-+//
-+// Touch Sensor Status Codes
-+//
-+//*******************************************************************
-+typedef enum touch_status
-+{
-+    TOUCH_STATUS_SUCCESS = 0,               //  0 Requested operation was successful
-+    TOUCH_STATUS_INVALID_PARAMS,            //  1 Invalid parameter(s) sent
-+    TOUCH_STATUS_ACCESS_DENIED,             //  2 Unable to validate address range
-+    TOUCH_STATUS_CMD_SIZE_ERROR,            //  3 HECI message incorrect size for specified command
-+    TOUCH_STATUS_NOT_READY,                 //  4 Memory window not set or device is not armed for operation
-+    TOUCH_STATUS_REQUEST_OUTSTANDING,       //  5 There is already an outstanding message of the same type, must wait for response before sending another request of that type
-+    TOUCH_STATUS_NO_SENSOR_FOUND,           //  6 Sensor could not be found. Either no sensor is connected, the sensor has not yet initialized, or the system is improperly configured.
-+    TOUCH_STATUS_OUT_OF_MEMORY,             //  7 Not enough memory/storage for requested operation
-+    TOUCH_STATUS_INTERNAL_ERROR,            //  8 Unexpected error occurred
-+    TOUCH_STATUS_SENSOR_DISABLED,           //  9 Used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP to indicate sensor has been disabled or reset and must be reinitialized.
-+    TOUCH_STATUS_COMPAT_CHECK_FAIL,         // 10 Used to indicate compatibility revision check between sensor and ME failed, or protocol ver between ME/HID/Kernels failed.
-+    TOUCH_STATUS_SENSOR_EXPECTED_RESET,     // 11 Indicates sensor went through a reset initiated by ME
-+    TOUCH_STATUS_SENSOR_UNEXPECTED_RESET,   // 12 Indicates sensor went through an unexpected reset
-+    TOUCH_STATUS_RESET_FAILED,              // 13 Requested sensor reset failed to complete
-+    TOUCH_STATUS_TIMEOUT,                   // 14 Operation timed out
-+    TOUCH_STATUS_TEST_MODE_FAIL,            // 15 Test mode pattern did not match expected values
-+    TOUCH_STATUS_SENSOR_FAIL_FATAL,         // 16 Indicates sensor reported fatal error during reset sequence. Further progress is not possible.
-+    TOUCH_STATUS_SENSOR_FAIL_NONFATAL,      // 17 Indicates sensor reported non-fatal error during reset sequence. HID/BIOS logs error and attempts to continue.
-+    TOUCH_STATUS_INVALID_DEVICE_CAPS,       // 18 Indicates sensor reported invalid capabilities, such as not supporting required minimum frequency or I/O mode.
-+    TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS,    // 19 Indicates that command cannot be complete until ongoing Quiesce I/O flow has completed.
-+    TOUCH_STATUS_MAX                        // 20 Invalid value, never returned
-+} touch_status_t;
-+C_ASSERT(sizeof(touch_status_t) == 4);
-+
-+
-+
-+//*******************************************************************
-+//
-+// Defines for message structures used for Host to ME communication
-+//
-+//*******************************************************************
-+
-+
-+typedef enum touch_sensor_mode
-+{
-+    TOUCH_SENSOR_MODE_HID = 0,          // Set mode to HID mode
-+    TOUCH_SENSOR_MODE_RAW_DATA,         // Set mode to Raw Data mode
-+    TOUCH_SENSOR_MODE_SENSOR_DEBUG = 4, // Used like TOUCH_SENSOR_MODE_HID but data coming from sensor is not necessarily a HID packet.
-+    TOUCH_SENSOR_MODE_MAX               // Invalid value
-+} touch_sensor_mode_t;
-+C_ASSERT(sizeof(touch_sensor_mode_t) == 4);
-+
-+typedef struct touch_sensor_set_mode_cmd_data
-+{
-+    touch_sensor_mode_t	sensor_mode;     // Indicate desired sensor mode
-+    u32					Reserved[3];    // For future expansion
-+} touch_sensor_set_mode_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mode_cmd_data_t) == 16);
-+
-+
-+#define TOUCH_SENSOR_MAX_DATA_BUFFERS   16
-+#define TOUCH_HID_2_ME_BUFFER_ID        TOUCH_SENSOR_MAX_DATA_BUFFERS
-+#define TOUCH_HID_2_ME_BUFFER_SIZE_MAX  1024
-+#define TOUCH_INVALID_BUFFER_ID         0xFF
-+
-+typedef struct touch_sensor_set_mem_window_cmd_data
-+{
-+    u32  touch_data_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS];    // Lower 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize
-+    u32  touch_data_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS];    // Upper 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize
-+    u32  tail_offset_addr_lower;                                        // Lower 32 bits of Tail Offset physical address
-+    u32  tail_offset_addr_upper;                                        // Upper 32 bits of Tail Offset physical address, always 32 bit, increment by WorkQueueItemSize
-+    u32  doorbell_cookie_addr_lower;                                    // Lower 32 bits of Doorbell register physical address
-+    u32  doorbell_cookie_addr_upper;                                    // Upper 32 bits of Doorbell register physical address, always 32 bit, increment as integer, rollover to 1
-+    u32  feedback_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS];     // Lower 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize
-+    u32  feedback_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS];     // Upper 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize
-+    u32  hid2me_buffer_addr_lower;                                      // Lower 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize.
-+    u32  hid2me_buffer_addr_upper;                                      // Upper 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize.
-+    u32  hid2me_buffer_size;                                           // Size in bytes of Hid2MeBuffer, can be no bigger than TOUCH_HID_2_ME_BUFFER_SIZE_MAX
-+    u8   reserved1;                                                  // For future expansion
-+    u8   work_queue_item_size;                                          // Size in bytes of the GuC Work Queue Item pointed to by TailOffset
-+    u16  work_queue_size;                                              // Size in bytes of the entire GuC Work Queue
-+    u32  reserved[8];                                                // For future expansion
-+} touch_sensor_set_mem_window_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mem_window_cmd_data_t) == 320);
-+
-+
-+#define TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET BIT0   // indicates GuC got reset and ME must re-read GuC data such as TailOffset and Doorbell Cookie values
-+
-+typedef struct touch_sensor_quiesce_io_cmd_data
-+{
-+    u32  quiesce_flags;   // Optionally set TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET
-+    u32  reserved[2];
-+} touch_sensor_quiesce_io_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_quiesce_io_cmd_data_t) == 12);
-+
-+
-+typedef struct touch_sensor_feedback_ready_cmd_data
-+{
-+    u8   feedback_index;  // Index value from 0 to TOUCH_HID_2_ME_BUFFER_ID used to indicate which Feedback Buffer to use. Using special value TOUCH_HID_2_ME_BUFFER_ID
-+                            // is an indication to ME to get feedback data from the Hid2Me buffer instead of one of the standard Feedback buffers.
-+    u8   reserved1[3];   // For future expansion
-+    u32  transaction_id;  // Transaction ID that was originally passed to host in TOUCH_HID_PRIVATE_DATA. Used to track round trip of a given transaction for performance measurements.
-+    u32  reserved2[2];   // For future expansion
-+} touch_sensor_feedback_ready_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_feedback_ready_cmd_data_t) == 16);
-+
-+
-+#define TOUCH_DEFAULT_DOZE_TIMER_SECONDS    30
-+
-+typedef enum touch_freq_override
-+{
-+    TOUCH_FREQ_OVERRIDE_NONE,   // Do not apply any override
-+    TOUCH_FREQ_OVERRIDE_10MHZ,  // Force frequency to 10MHz (not currently supported)
-+    TOUCH_FREQ_OVERRIDE_17MHZ,  // Force frequency to 17MHz
-+    TOUCH_FREQ_OVERRIDE_30MHZ,  // Force frequency to 30MHz
-+    TOUCH_FREQ_OVERRIDE_50MHZ,  // Force frequency to 50MHz (not currently supported)
-+    TOUCH_FREQ_OVERRIDE_MAX     // Invalid value
-+} touch_freq_override_t;
-+C_ASSERT(sizeof(touch_freq_override_t) == 4);
-+
-+typedef enum touch_spi_io_mode_override
-+{
-+    TOUCH_SPI_IO_MODE_OVERRIDE_NONE,    // Do not apply any override
-+    TOUCH_SPI_IO_MODE_OVERRIDE_SINGLE,  // Force Single I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_DUAL,    // Force Dual I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_QUAD,    // Force Quad I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_MAX      // Invalid value
-+} touch_spi_io_mode_override_t;
-+C_ASSERT(sizeof(touch_spi_io_mode_override_t) == 4);
-+
-+// Debug Policy bits used by TOUCH_POLICY_DATA.DebugOverride
-+#define TOUCH_DBG_POLICY_OVERRIDE_STARTUP_TIMER_DIS BIT0    // Disable sensor startup timer
-+#define TOUCH_DBG_POLICY_OVERRIDE_SYNC_BYTE_DIS     BIT1    // Disable Sync Byte check
-+#define TOUCH_DBG_POLICY_OVERRIDE_ERR_RESET_DIS     BIT2    // Disable error resets
-+
-+typedef struct touch_policy_data
-+{
-+    u32                      reserved0;          // For future expansion.
-+    u32                      doze_timer     :16;  // Value in seconds, after which ME will put the sensor into Doze power state if no activity occurs. Set
-+                                                    // to 0 to disable Doze mode (not recommended). Value will be set to TOUCH_DEFAULT_DOZE_TIMER_SECONDS by
-+                                                    // default.
-+    touch_freq_override_t         freq_override  :3;   // Override frequency requested by sensor
-+    touch_spi_io_mode_override_t  spi_io_override :3;   // Override IO mode requested by sensor
-+    u32                      reserved1     :10;  // For future expansion
-+    u32                      reserved2;          // For future expansion
-+    u32                      debug_override;      // Normally all bits will be zero. Bits will be defined as needed for enabling special debug features
-+} touch_policy_data_t;
-+C_ASSERT(sizeof(touch_policy_data_t) == 16);
-+
-+typedef struct touch_sensor_set_policies_cmd_data
-+{
-+    touch_policy_data_t           policy_data;         // Contains the desired policy to be set
-+} touch_sensor_set_policies_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_policies_cmd_data_t) == 16);
-+
-+
-+typedef enum touch_sensor_reset_type
-+{
-+    TOUCH_SENSOR_RESET_TYPE_HARD,   // Hardware Reset using dedicated GPIO pin
-+    TOUCH_SENSOR_RESET_TYPE_SOFT,   // Software Reset using command written over SPI interface
-+    TOUCH_SENSOR_RESET_TYPE_MAX     // Invalid value
-+} touch_sensor_reset_type_t;
-+C_ASSERT(sizeof(touch_sensor_reset_type_t) == 4);
-+
-+typedef struct touch_sensor_reset_cmd_data
-+{
-+    touch_sensor_reset_type_t reset_type;  // Indicate desired reset type
-+    u32                  reserved;   // For future expansion
-+} touch_sensor_reset_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_reset_cmd_data_t) == 8);
-+
-+
-+//
-+// Host to ME message
-+//
-+typedef struct touch_sensor_msg_h2m
-+{
-+    u32  command_code;
-+    union
-+    {
-+        touch_sensor_set_mode_cmd_data_t        set_mode_cmd_data;
-+        touch_sensor_set_mem_window_cmd_data_t  set_window_cmd_data;
-+        touch_sensor_quiesce_io_cmd_data_t      quiesce_io_cmd_data;
-+        touch_sensor_feedback_ready_cmd_data_t  feedback_ready_cmd_data;
-+        touch_sensor_set_policies_cmd_data_t    set_policies_cmd_data;
-+        touch_sensor_reset_cmd_data_t           reset_cmd_data;
-+    } h2m_data;
-+} touch_sensor_msg_h2m_t;
-+C_ASSERT(sizeof(touch_sensor_msg_h2m_t) == 324);
-+
-+
-+//*******************************************************************
-+//
-+// Defines for message structures used for ME to Host communication
-+//
-+//*******************************************************************
-+
-+// I/O mode values used by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+typedef enum touch_spi_io_mode
-+{
-+    TOUCH_SPI_IO_MODE_SINGLE = 0,   // Sensor set for Single I/O SPI
-+    TOUCH_SPI_IO_MODE_DUAL,         // Sensor set for Dual I/O SPI
-+    TOUCH_SPI_IO_MODE_QUAD,         // Sensor set for Quad I/O SPI
-+    TOUCH_SPI_IO_MODE_MAX           // Invalid value
-+} touch_spi_io_mode_t;
-+C_ASSERT(sizeof(touch_spi_io_mode_t) == 4);
-+
-+//
-+// TOUCH_SENSOR_GET_DEVICE_INFO_RSP code is sent in response to TOUCH_SENSOR_GET_DEVICE_INFO_CMD. This code will be followed
-+// by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:               Command was processed successfully and sensor details are reported.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:        Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_NO_SENSOR_FOUND:       Sensor has not yet been detected. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_DEVICE_CAPS:   Indicates sensor does not support minimum required Frequency or I/O Mode. ME firmware will choose best possible option for the errant
-+//                                          field. Caller should attempt to continue.
-+//      TOUCH_STATUS_COMPAT_CHECK_FAIL:     Indicates TouchIC/ME compatibility mismatch. Caller should attempt to continue.
-+//
-+typedef struct touch_sensor_get_device_info_rsp_data
-+{
-+    u16				vendor_id;               // Touch Sensor vendor ID
-+    u16              device_id;               // Touch Sensor device ID
-+    u32              hw_rev;                  // Touch Sensor Hardware Revision
-+    u32              fw_rev;                  // Touch Sensor Firmware Revision
-+    u32              frame_size;              // Max size of one frame returned by Touch IC in bytes. This data will be TOUCH_RAW_DATA_HDR followed
-+                                                // by a payload. The payload can be raw data or a HID structure depending on mode.
-+    u32              feedback_size;           // Max size of one Feedback structure in bytes
-+    touch_sensor_mode_t	sensor_mode;             // Current operating mode of the sensor
-+    u32              max_touch_points  :8;     // Maximum number of simultaneous touch points that can be reported by sensor
-+    touch_freq_t          spi_frequency    :8;     // SPI bus Frequency supported by sensor and ME firmware
-+    touch_spi_io_mode_t   spi_io_mode       :8;     // SPI bus I/O Mode supported by sensor and ME firmware
-+    u32              reserved0       :8;     // For future expansion
-+    u8               sensor_minor_eds_rev;      // Minor version number of EDS spec supported by sensor (from Compat Rev ID Reg)
-+    u8               sensor_major_eds_rev;      // Major version number of EDS spec supported by sensor (from Compat Rev ID Reg)
-+    u8               me_minor_eds_rev;          // Minor version number of EDS spec supported by ME
-+    u8               me_major_eds_rev;          // Major version number of EDS spec supported by ME
-+    u8               sensor_eds_intf_rev;       // EDS Interface Revision Number supported by sensor (from Compat Rev ID Reg)
-+    u8               me_eds_intf_rev;           // EDS Interface Revision Number supported by ME
-+    u8               kernel_compat_ver;        // EU Kernel Compatibility Version  (from Compat Rev ID Reg)
-+    u8               reserved1;              // For future expansion
-+    u32              reserved2[2];           // For future expansion
-+} touch_sensor_get_device_info_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_get_device_info_rsp_data_t) == 44);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_MODE_RSP code is sent in response to TOUCH_SENSOR_SET_MODE_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_MODE_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and mode was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//
-+typedef struct touch_sensor_set_mode_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_mode_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mode_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_SET_MEM_WINDOW_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_MEM_WINDOW_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and memory window was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//      TOUCH_STATUS_ACCESS_DENIED:     Unable to map host address ranges for DMA.
-+//      TOUCH_STATUS_OUT_OF_MEMORY:     Unable to allocate enough space for needed buffers.
-+//
-+typedef struct touch_sensor_set_mem_window_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_mem_window_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mem_window_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_QUIESCE_IO_RSP code is sent in response to TOUCH_SENSOR_QUIESCE_IO_CMD. This code will be followed
-+// by TOUCH_SENSOR_QUIESCE_IO_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and touch flow has stopped.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//      TOUCH_STATIS_TIMEOUT:                   Indicates ME timed out waiting for Quiesce I/O flow to complete.
-+//
-+typedef struct touch_sensor_quiesce_io_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_quiesce_io_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_quiesce_io_rsp_data_t) == 12);
-+
-+
-+// Reset Reason values used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA
-+typedef enum touch_reset_reason
-+{
-+    TOUCH_RESET_REASON_UNKNOWN = 0,         // Reason for sensor reset is not known
-+    TOUCH_RESET_REASON_FEEDBACK_REQUEST,    // Reset was requested as part of TOUCH_SENSOR_FEEDBACK_READY_CMD
-+    TOUCH_RESET_REASON_HECI_REQUEST,        // Reset was requested via TOUCH_SENSOR_RESET_CMD
-+    TOUCH_RESET_REASON_MAX
-+} touch_reset_reason_t;
-+C_ASSERT(sizeof(touch_reset_reason_t) == 4);
-+
-+//
-+// TOUCH_SENSOR_HID_READY_FOR_DATA_RSP code is sent in response to TOUCH_SENSOR_HID_READY_FOR_DATA_CMD. This code will be followed
-+// by TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and HID data was sent by DMA. This will only be sent in HID mode.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_REQUEST_OUTSTANDING:       Previous request is still outstanding, ME FW cannot handle another request for the same command.
-+//      TOUCH_STATUS_NOT_READY:                 Indicates memory window has not yet been set by BIOS/HID.
-+//      TOUCH_STATUS_SENSOR_DISABLED:           Indicates that ME to HID communication has been stopped either by TOUCH_SENSOR_QUIESCE_IO_CMD or TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD.
-+//      TOUCH_STATUS_SENSOR_UNEXPECTED_RESET:   Sensor signaled a Reset Interrupt. ME did not expect this and has no info about why this occurred.
-+//      TOUCH_STATUS_SENSOR_EXPECTED_RESET:     Sensor signaled a Reset Interrupt. ME either directly requested this reset, or it was expected as part of a defined flow in the EDS.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//      TOUCH_STATUS_TIMEOUT:                   Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//
-+typedef struct touch_sensor_hid_ready_for_data_rsp_data
-+{
-+    u32          data_size;               // Size of the data the ME DMA'd into a RawDataBuffer. Valid only when Status == TOUCH_STATUS_SUCCESS
-+    u8           touch_data_buffer_index;   // Index to indicate which RawDataBuffer was used. Valid only when Status == TOUCH_STATUS_SUCCESS
-+    u8           reset_reason;            // If Status is TOUCH_STATUS_SENSOR_EXPECTED_RESET, ME will provide the cause. See TOUCH_RESET_REASON.
-+    u8           reserved1[2];           // For future expansion
-+    u32          reserved2[5];           // For future expansion
-+} touch_sensor_hid_ready_for_data_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_hid_ready_for_data_rsp_data_t) == 28);
-+
-+
-+//
-+// TOUCH_SENSOR_FEEDBACK_READY_RSP code is sent in response to TOUCH_SENSOR_FEEDBACK_READY_CMD. This code will be followed
-+// by TOUCH_SENSOR_FEEDBACK_READY_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and any feedback or commands were sent to sensor.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//      TOUCH_STATUS_COMPAT_CHECK_FAIL  Indicates ProtocolVer does not match ME supported version. (non-fatal error)
-+//      TOUCH_STATUS_INTERNAL_ERROR:    Unexpected error occurred. This should not normally be seen.
-+//      TOUCH_STATUS_OUT_OF_MEMORY:     Insufficient space to store Calibration Data
-+//
-+typedef struct touch_sensor_feedback_ready_rsp_data
-+{
-+    u8           feedback_index;  // Index value from 0 to TOUCH_SENSOR_MAX_DATA_BUFFERS used to indicate which Feedback Buffer to use
-+    u8           reserved1[3];   // For future expansion
-+    u32          reserved2[6];   // For future expansion
-+} touch_sensor_feedback_ready_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_feedback_ready_rsp_data_t) == 28);
-+
-+
-+//
-+// TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD. This code will be followed
-+// by TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and memory window was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:            Input parameters are out of range.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//
-+typedef struct touch_sensor_clear_mem_window_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_clear_mem_window_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_clear_mem_window_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_NOTIFY_DEV_READY_RSP code is sent in response to TOUCH_SENSOR_NOTIFY_DEV_READY_CMD. This code will be followed
-+// by TOUCH_SENSOR_NOTIFY_DEV_READY_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:               Command was processed successfully and sensor has been detected by ME FW.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:        Command sent did not match expected size.
-+//      TOUCH_STATUS_REQUEST_OUTSTANDING:   Previous request is still outstanding, ME FW cannot handle another request for the same command.
-+//      TOUCH_STATUS_TIMEOUT:               Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//      TOUCH_STATUS_SENSOR_FAIL_FATAL:     Sensor indicated a fatal error, further operation is not possible. Error details can be found in ErrReg.
-+//      TOUCH_STATUS_SENSOR_FAIL_NONFATAL:  Sensor indicated a non-fatal error. Error should be logged by caller and init flow can continue. Error details can be found in ErrReg.
-+//
-+typedef struct touch_sensor_notify_dev_ready_rsp_data
-+{
-+    touch_err_reg_t   err_reg;         // Value of sensor Error Register, field is only valid for Status == TOUCH_STATUS_SENSOR_FAIL_FATAL or TOUCH_STATUS_SENSOR_FAIL_NONFATAL
-+    u32          reserved[2];    // For future expansion
-+} touch_sensor_notify_dev_ready_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_notify_dev_ready_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_SET_POLICIES_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_POLICIES_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//
-+typedef struct touch_sensor_set_policies_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_policies_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_policies_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_GET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_GET_POLICIES_CMD. This code will be followed
-+// by TOUCH_SENSOR_GET_POLICIES_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//
-+typedef struct touch_sensor_get_policies_rsp_data
-+{
-+    touch_policy_data_t   policy_data;         // Contains the current policy
-+} touch_sensor_get_policies_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_get_policies_rsp_data_t) == 16);
-+
-+
-+//
-+// TOUCH_SENSOR_RESET_RSP code is sent in response to TOUCH_SENSOR_RESET_CMD. This code will be followed
-+// by TOUCH_SENSOR_RESET_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and sensor reset was completed.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:            Input parameters are out of range.
-+//      TOUCH_STATUS_TIMEOUT:                   Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//      TOUCH_STATUS_RESET_FAILED:              Sensor generated an invalid or unexpected interrupt.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//
-+typedef struct touch_sensor_reset_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_reset_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_reset_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_READ_ALL_REGS_RSP code is sent in response to TOUCH_SENSOR_READ_ALL_REGS_CMD. This code will be followed
-+// by TOUCH_SENSOR_READ_ALL_REGS_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//
-+typedef struct touch_sensor_read_all_regs_rsp_data
-+{
-+    touch_reg_block_t sensor_regs; // Returns first 64 bytes of register space used for normal touch operation. Does not include test mode register.
-+    u32          reserved[4];
-+} touch_sensor_read_all_regs_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_read_all_regs_rsp_data_t) == 80);
-+
-+//
-+// ME to Host Message
-+//
-+typedef struct touch_sensor_msg_m2h
-+{
-+    u32  command_code;
-+    touch_status_t	status;
-+    union
-+    {
-+        touch_sensor_get_device_info_rsp_data_t     device_info_rsp_data;
-+        touch_sensor_set_mode_rsp_data_t            set_mode_rsp_data;
-+        touch_sensor_set_mem_window_rsp_data_t      set_mem_window_rsp_data;
-+        touch_sensor_quiesce_io_rsp_data_t          quiesce_io_rsp_data;
-+        touch_sensor_hid_ready_for_data_rsp_data_t  hid_ready_for_data_rsp_data;
-+        touch_sensor_feedback_ready_rsp_data_t      feedback_ready_rsp_data;
-+        touch_sensor_clear_mem_window_rsp_data_t    clear_mem_window_rsp_data;
-+        touch_sensor_notify_dev_ready_rsp_data_t    notify_dev_ready_rsp_data;
-+        touch_sensor_set_policies_rsp_data_t        set_policies_rsp_data;
-+        touch_sensor_get_policies_rsp_data_t        get_policies_rsp_data;
-+        touch_sensor_reset_rsp_data_t               reset_rsp_data;
-+	touch_sensor_read_all_regs_rsp_data_t       read_all_regs_rsp_data;
-+    } m2h_data;
-+} touch_sensor_msg_m2h_t;
-+C_ASSERT(sizeof(touch_sensor_msg_m2h_t) == 88);
-+
-+
-+#define TOUCH_MSG_SIZE_MAX_BYTES    (MAX(sizeof(touch_sensor_msg_m2h_t), sizeof(touch_sensor_msg_h2m_t)))
-+
-+#pragma pack()
-+
-+#endif // _IPTS_MEI_MSGS_H_
-diff --git a/drivers/misc/ipts/ipts-mei.c b/drivers/misc/ipts/ipts-mei.c
-new file mode 100644
-index 0000000..39667e7
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-mei.c
-@@ -0,0 +1,282 @@
-+/*
-+ * MEI client driver for Intel Precise Touch and Stylus
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/mei_cl_bus.h>
-+#include <linux/module.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/hid.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/kthread.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-hid.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-mei-msgs.h"
-+#include "ipts-binary-spec.h"
-+#include "ipts-state.h"
-+
-+#define IPTS_DRIVER_NAME	"ipts"
-+#define IPTS_MEI_UUID		UUID_LE(0x3e8d0870, 0x271a, 0x4208, \
-+				0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04)
-+
-+static struct mei_cl_device_id ipts_mei_cl_tbl[] = {
-+	{ "", IPTS_MEI_UUID, MEI_CL_VERSION_ANY},
-+	{}
-+};
-+
-+static ssize_t sensor_mode_show(struct device *dev,
-+				struct device_attribute *attr, char *buf)
-+{
-+	ipts_info_t *ipts;
-+	ipts = dev_get_drvdata(dev);
-+
-+	return sprintf(buf, "%d\n", ipts->sensor_mode);
-+}
-+
-+//TODO: Verify the function implementation
-+static ssize_t sensor_mode_store(struct device *dev,
-+				struct device_attribute *attr, const char *buf,
-+				size_t count)
-+{
-+	int ret;
-+	long val;
-+	ipts_info_t *ipts;
-+
-+	ipts = dev_get_drvdata(dev);
-+	ret = kstrtol(buf, 10, &val);
-+	if (ret)
-+	   return ret;
-+
-+	ipts_dbg(ipts, "try sensor mode = %ld\n", val);
-+
-+	switch (val) {
-+		case TOUCH_SENSOR_MODE_HID:
-+			break;
-+		case TOUCH_SENSOR_MODE_RAW_DATA:
-+			break;
-+		default:
-+			ipts_err(ipts, "sensor mode %ld is not supported\n", val);
-+	}
-+
-+	return count;
-+}
-+
-+static ssize_t device_info_show(struct device *dev,
-+				struct device_attribute *attr, char *buf)
-+{
-+	ipts_info_t *ipts;
-+
-+	ipts = dev_get_drvdata(dev);
-+	return sprintf(buf, "vendor id = 0x%04hX\n"
-+				"device id = 0x%04hX\n"
-+				"HW rev = 0x%08X\n"
-+				"firmware rev = 0x%08X\n",
-+			ipts->device_info.vendor_id, ipts->device_info.device_id,
-+			ipts->device_info.hw_rev, ipts->device_info.fw_rev);
-+}
-+
-+static DEVICE_ATTR_RW(sensor_mode);
-+static DEVICE_ATTR_RO(device_info);
-+
-+static struct attribute *ipts_attrs[] = {
-+	&dev_attr_sensor_mode.attr,
-+	&dev_attr_device_info.attr,
-+	NULL
-+};
-+
-+static const struct attribute_group ipts_grp = {
-+	.attrs = ipts_attrs,
-+};
-+
-+MODULE_DEVICE_TABLE(mei, ipts_mei_cl_tbl);
-+
-+static void raw_data_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, raw_data_work);
-+
-+	ipts_handle_processed_data(ipts);
-+}
-+
-+static void gfx_status_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, gfx_status_work);
-+	ipts_state_t state;
-+	int status = ipts->gfx_status;
-+
-+	ipts_dbg(ipts, "notify gfx status : %d\n", status);
-+
-+	state = ipts_get_state(ipts);
-+
-+	if (state == IPTS_STA_RAW_DATA_STARTED || state == IPTS_STA_HID_STARTED) {
-+		if (status == IPTS_NOTIFY_STA_BACKLIGHT_ON &&
-+					ipts->display_status == false) {
-+			ipts_send_sensor_clear_mem_window_cmd(ipts);
-+			ipts->display_status = true;
-+		} else if (status == IPTS_NOTIFY_STA_BACKLIGHT_OFF &&
-+					ipts->display_status == true) {
-+			ipts_send_sensor_quiesce_io_cmd(ipts);
-+			ipts->display_status = false;
-+		}
-+	}
-+}
-+
-+/* event loop */
-+static int ipts_mei_cl_event_thread(void *data)
-+{
-+	ipts_info_t *ipts = (ipts_info_t *)data;
-+	struct mei_cl_device *cldev = ipts->cldev;
-+	ssize_t msg_len;
-+	touch_sensor_msg_m2h_t m2h_msg;
-+
-+	while (!kthread_should_stop()) {
-+		msg_len = mei_cldev_recv(cldev, (u8*)&m2h_msg, sizeof(m2h_msg));
-+		if (msg_len <= 0) {
-+			ipts_err(ipts, "error in reading m2h msg\n");
-+			continue;
-+		}
-+
-+		if (ipts_handle_resp(ipts, &m2h_msg, msg_len) != 0) {
-+			ipts_err(ipts, "error in handling resp msg\n");
-+		}
-+	}
-+
-+	ipts_dbg(ipts, "!! end event loop !!\n");
-+
-+	return 0;
-+}
-+
-+static void init_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, init_work);
-+
-+	ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA;
-+	ipts->display_status = true;
-+
-+	ipts_start(ipts);
-+}
-+
-+static int ipts_mei_cl_probe(struct mei_cl_device *cldev,
-+			const struct mei_cl_device_id *id)
-+{
-+	int ret = 0;
-+	ipts_info_t *ipts = NULL;
-+
-+	pr_info("probing Intel Precise Touch & Stylus\n");
-+
-+	// setup the DMA BIT mask, the system will choose the best possible
-+	if (dma_coerce_mask_and_coherent(&cldev->dev, DMA_BIT_MASK(64)) == 0) {
-+		pr_info("IPTS using DMA_BIT_MASK(64)\n");
-+	} else if (dma_coerce_mask_and_coherent(&cldev->dev,
-+						DMA_BIT_MASK(32)) == 0) {
-+		pr_info("IPTS using  DMA_BIT_MASK(32)\n");
-+	} else {
-+		pr_err("IPTS: No suitable DMA available\n");
-+		return -EFAULT;
-+	}
-+
-+	ret = mei_cldev_enable(cldev);
-+	if (ret < 0) {
-+		pr_err("cannot enable IPTS\n");
-+		return ret;
-+	}
-+
-+	ipts = devm_kzalloc(&cldev->dev, sizeof(ipts_info_t), GFP_KERNEL);
-+	if (ipts == NULL) {
-+		ret = -ENOMEM;
-+		goto disable_mei;
-+	}
-+	ipts->cldev = cldev;
-+	mei_cldev_set_drvdata(cldev, ipts);
-+
-+	ipts->event_loop = kthread_run(ipts_mei_cl_event_thread, (void*)ipts,
-+							"ipts_event_thread");
-+
-+	if(ipts_dbgfs_register(ipts, "ipts"))
-+		pr_debug("cannot register debugfs for IPTS\n");
-+
-+	INIT_WORK(&ipts->init_work, init_work_func);
-+	INIT_WORK(&ipts->raw_data_work, raw_data_work_func);
-+	INIT_WORK(&ipts->gfx_status_work, gfx_status_work_func);
-+
-+	ret = sysfs_create_group(&cldev->dev.kobj, &ipts_grp);
-+	if (ret != 0) {
-+		pr_debug("cannot create sysfs for IPTS\n");
-+	}
-+
-+	schedule_work(&ipts->init_work);
-+
-+	return 0;
-+
-+disable_mei :
-+	mei_cldev_disable(cldev);
-+	
-+	return ret;
-+}
-+
-+static int ipts_mei_cl_remove(struct mei_cl_device *cldev)
-+{
-+	ipts_info_t *ipts = mei_cldev_get_drvdata(cldev);
-+
-+	ipts_stop(ipts);
-+
-+	sysfs_remove_group(&cldev->dev.kobj, &ipts_grp);
-+	ipts_hid_release(ipts);
-+	ipts_dbgfs_deregister(ipts);
-+	mei_cldev_disable(cldev);
-+
-+	kthread_stop(ipts->event_loop);
-+
-+	pr_info("IPTS removed\n");
-+
-+	return 0;
-+}
-+
-+static struct mei_cl_driver ipts_mei_cl_driver = {
-+	.id_table = ipts_mei_cl_tbl,
-+	.name = IPTS_DRIVER_NAME,
-+	.probe = ipts_mei_cl_probe,
-+	.remove = ipts_mei_cl_remove,
-+};
-+
-+static int ipts_mei_cl_init(void)
-+{
-+	int ret;
-+
-+	pr_info("IPTS %s() is called\n", __func__);
-+
-+	ret = mei_cldev_driver_register(&ipts_mei_cl_driver);
-+	if (ret) {
-+		pr_err("unable to register IPTS mei client driver\n");
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static void __exit ipts_mei_cl_exit(void)
-+{
-+	pr_info("IPTS %s() is called\n", __func__);
-+
-+	mei_cldev_driver_unregister(&ipts_mei_cl_driver);
-+}
-+
-+module_init(ipts_mei_cl_init);
-+module_exit(ipts_mei_cl_exit);
-+
-+MODULE_DESCRIPTION
-+	("Intel(R) Management Engine Interface Client Driver for "\
-+	"Intel Precision Touch and Sylus");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/misc/ipts/ipts-msg-handler.c b/drivers/misc/ipts/ipts-msg-handler.c
-new file mode 100644
-index 0000000..1396ecc
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-msg-handler.c
-@@ -0,0 +1,431 @@
-+#include <linux/mei_cl_bus.h>
-+
-+#include "ipts.h"
-+#include "ipts-hid.h"
-+#include "ipts-resource.h"
-+#include "ipts-mei-msgs.h"
-+
-+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size)
-+{
-+	int ret = 0;
-+	touch_sensor_msg_h2m_t h2m_msg;
-+	int len = 0;
-+
-+	memset(&h2m_msg, 0, sizeof(h2m_msg));
-+
-+	h2m_msg.command_code = cmd;
-+	len = sizeof(h2m_msg.command_code) + data_size;
-+	if (data != NULL && data_size != 0)
-+		memcpy(&h2m_msg.h2m_data, data, data_size); /* copy payload */
-+
-+	ret = mei_cldev_send(ipts->cldev, (u8*)&h2m_msg, len);
-+	if (ret < 0) {
-+		ipts_err(ipts, "mei_cldev_send() error 0x%X:%d\n",
-+							cmd, ret);
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id)
-+{
-+	int ret;
-+	int cmd_len;
-+	touch_sensor_feedback_ready_cmd_data_t fb_ready_cmd;
-+
-+	cmd_len = sizeof(touch_sensor_feedback_ready_cmd_data_t);
-+	memset(&fb_ready_cmd, 0, cmd_len);
-+
-+	fb_ready_cmd.feedback_index = buffer_idx;
-+	fb_ready_cmd.transaction_id = transaction_id;
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_FEEDBACK_READY_CMD,
-+				&fb_ready_cmd, cmd_len);
-+
-+	return ret;
-+}
-+
-+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts)
-+{
-+	int ret;
-+	int cmd_len;
-+	touch_sensor_quiesce_io_cmd_data_t quiesce_io_cmd;
-+
-+	cmd_len = sizeof(touch_sensor_quiesce_io_cmd_data_t);
-+	memset(&quiesce_io_cmd, 0, cmd_len);
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_QUIESCE_IO_CMD,
-+				&quiesce_io_cmd, cmd_len);
-+
-+	return ret;
-+}
-+
-+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts)
-+{
-+	return ipts_handle_cmd(ipts, TOUCH_SENSOR_HID_READY_FOR_DATA_CMD, NULL, 0);
-+}
-+
-+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts)
-+{
-+	return ipts_handle_cmd(ipts, TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD, NULL, 0);
-+}
-+
-+static int check_validity(touch_sensor_msg_m2h_t *m2h_msg, u32 msg_len)
-+{
-+	int ret = 0;
-+	int valid_msg_len = sizeof(m2h_msg->command_code);
-+	u32 cmd_code = m2h_msg->command_code;
-+
-+	switch (cmd_code) {
-+		case TOUCH_SENSOR_SET_MODE_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_mode_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_SET_MEM_WINDOW_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_mem_window_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_QUIESCE_IO_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_quiesce_io_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_hid_ready_for_data_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_FEEDBACK_READY_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_feedback_ready_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_clear_mem_window_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_notify_dev_ready_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_SET_POLICIES_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_policies_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_GET_POLICIES_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_get_policies_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_RESET_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_reset_rsp_data_t);
-+			break;
-+	}
-+
-+	if (valid_msg_len != msg_len) {
-+		return -EINVAL;
-+	}
-+
-+	return ret;
-+}
-+
-+int ipts_start(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	/* TODO : check if we need to do SET_POLICIES_CMD
-+	we need to do this when protocol version doesn't match with reported one
-+	how we keep vendor specific data is the first thing to solve */
-+
-+	ipts_set_state(ipts, IPTS_STA_INIT);
-+	ipts->num_of_parallel_data_buffers = TOUCH_SENSOR_MAX_DATA_BUFFERS;
-+
-+	ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA; /* start with RAW_DATA */
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_NOTIFY_DEV_READY_CMD, NULL, 0);
-+
-+	return ret;
-+}
-+
-+void ipts_stop(ipts_info_t *ipts)
-+{
-+	ipts_state_t old_state;
-+
-+	old_state = ipts_get_state(ipts);
-+	ipts_set_state(ipts, IPTS_STA_STOPPING);
-+
-+	if (old_state < IPTS_STA_RESOURCE_READY)
-+		return;
-+
-+	if (old_state == IPTS_STA_RAW_DATA_STARTED ||
-+					old_state == IPTS_STA_HID_STARTED) {
-+        	ipts_free_default_resource(ipts);
-+		ipts_free_raw_data_resource(ipts);
-+
-+		return;
-+	}
-+}
-+
-+int ipts_restart(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ipts_dbg(ipts, "ipts restart\n");
-+
-+	ipts_stop(ipts);
-+
-+	ipts->retry++;
-+	if (ipts->retry == IPTS_MAX_RETRY && 
-+			ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) {
-+		/* try with HID mode */
-+		ipts->sensor_mode = TOUCH_SENSOR_MODE_HID;
-+	} else if (ipts->retry > IPTS_MAX_RETRY) {
-+		return -EPERM;
-+	}
-+
-+	ipts_send_sensor_quiesce_io_cmd(ipts);
-+	ipts->restart = true;
-+
-+	return ret;
-+}
-+
-+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode)
-+{
-+	int ret = 0;
-+
-+        ipts->new_sensor_mode = new_sensor_mode;
-+	ipts->switch_sensor_mode = true;
-+        ret = ipts_send_sensor_quiesce_io_cmd(ipts);
-+
-+	return ret;
-+}
-+
-+#define rsp_failed(ipts, cmd, status) ipts_err(ipts, \
-+				"0x%08x failed status = %d\n", cmd, status);
-+
-+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg,
-+								u32 msg_len)
-+{
-+	int ret = 0;
-+	int rsp_status = 0;
-+	int cmd_status = 0;
-+	int cmd_len = 0;
-+	u32 cmd;
-+
-+	if (!check_validity(m2h_msg, msg_len)) {
-+		ipts_err(ipts, "wrong rsp\n");
-+		return -EINVAL;
-+	}
-+
-+	rsp_status = m2h_msg->status;
-+	cmd = m2h_msg->command_code;
-+
-+	switch (cmd) {
-+		case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_SENSOR_FAIL_NONFATAL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_status = ipts_handle_cmd(ipts,
-+					TOUCH_SENSOR_GET_DEVICE_INFO_CMD,
-+					NULL, 0);
-+			break;
-+		case TOUCH_SENSOR_GET_DEVICE_INFO_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			memcpy(&ipts->device_info,
-+				&m2h_msg->m2h_data.device_info_rsp_data,
-+				sizeof(touch_sensor_get_device_info_rsp_data_t));
-+
-+			/*
-+			    TODO : support raw_request during HID init.
-+			    Although HID init happens here, technically most of
-+			    reports (for both direction) can be issued only
-+			    after SET_MEM_WINDOWS_CMD since they may require
-+			    ME or touch IC. If ipts vendor requires raw_request
-+			    during HID init, we need to consider to move HID init.
-+			*/
-+			if (ipts->hid_desc_ready == false) {
-+				ret = ipts_hid_init(ipts);
-+				if (ret)
-+					break;
-+			}
-+
-+			cmd_status = ipts_send_sensor_clear_mem_window_cmd(ipts);
-+
-+			break;
-+		case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP:
-+		{
-+			touch_sensor_set_mode_cmd_data_t sensor_mode_cmd;
-+
-+			if (rsp_status != 0 &&
-+					rsp_status != TOUCH_STATUS_TIMEOUT) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			/* allocate default resource : common & hid only */
-+			if (!ipts_is_default_resource_ready(ipts)) {
-+				ret = ipts_allocate_default_resource(ipts);
-+				if (ret)
-+					break;
-+			}
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA &&
-+					!ipts_is_raw_data_resource_ready(ipts)) {
-+				ret = ipts_allocate_raw_data_resource(ipts);
-+				if (ret) {
-+					ipts_free_default_resource(ipts);
-+					break;
-+				}
-+			}
-+
-+			ipts_set_state(ipts, IPTS_STA_RESOURCE_READY);
-+
-+			cmd_len = sizeof(touch_sensor_set_mode_cmd_data_t);
-+			memset(&sensor_mode_cmd, 0, cmd_len);
-+			sensor_mode_cmd.sensor_mode = ipts->sensor_mode;
-+			cmd_status = ipts_handle_cmd(ipts,
-+				TOUCH_SENSOR_SET_MODE_CMD,
-+				&sensor_mode_cmd, cmd_len);
-+			break;
-+		}
-+		case TOUCH_SENSOR_SET_MODE_RSP:
-+		{
-+			touch_sensor_set_mem_window_cmd_data_t smw_cmd;
-+
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_len = sizeof(touch_sensor_set_mem_window_cmd_data_t);
-+			memset(&smw_cmd, 0, cmd_len);
-+			ipts_get_set_mem_window_cmd_data(ipts, &smw_cmd);
-+			cmd_status = ipts_handle_cmd(ipts,
-+				TOUCH_SENSOR_SET_MEM_WINDOW_CMD,
-+				&smw_cmd, cmd_len);
-+			break;
-+		}
-+		case TOUCH_SENSOR_SET_MEM_WINDOW_RSP:
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_status = ipts_send_sensor_hid_ready_for_data_cmd(ipts);
-+			if (cmd_status)
-+				break;
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) {
-+				ipts_set_state(ipts, IPTS_STA_HID_STARTED);
-+			} else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) {
-+				ipts_set_state(ipts, IPTS_STA_RAW_DATA_STARTED);
-+			}
-+
-+			ipts_err(ipts, "touch enabled %d\n", ipts_get_state(ipts));
-+
-+			break;
-+		case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP:
-+		{
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_data;
-+			ipts_state_t state;
-+
-+			if (rsp_status != 0 &&
-+				  rsp_status != TOUCH_STATUS_SENSOR_DISABLED) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			state = ipts_get_state(ipts);
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID &&
-+						state == IPTS_STA_HID_STARTED) {
-+
-+				hid_data = &m2h_msg->m2h_data.hid_ready_for_data_rsp_data;
-+
-+				/* HID mode only uses buffer 0 */
-+				if (hid_data->touch_data_buffer_index != 0)
-+					break;
-+
-+				/* handle hid data */
-+				ipts_handle_hid_data(ipts, hid_data);
-+			}
-+
-+			break;
-+		}
-+		case TOUCH_SENSOR_FEEDBACK_READY_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			if (m2h_msg->m2h_data.feedback_ready_rsp_data.
-+					feedback_index == TOUCH_HID_2_ME_BUFFER_ID)
-+				break;
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) {
-+				cmd_status = ipts_handle_cmd(ipts,
-+					TOUCH_SENSOR_HID_READY_FOR_DATA_CMD,
-+					NULL, 0);
-+			}
-+
-+			/* reset retry since we are getting touch data */
-+			ipts->retry = 0;
-+
-+			break;
-+		case TOUCH_SENSOR_QUIESCE_IO_RSP:
-+		{
-+			ipts_state_t state;
-+
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			state = ipts_get_state(ipts);
-+			if (state == IPTS_STA_STOPPING && ipts->restart) {
-+				ipts_dbg(ipts, "restart\n");
-+			        ipts_start(ipts);
-+				ipts->restart = 0;
-+				break;
-+			}
-+
-+			/* support sysfs debug node for switch sensor mode */
-+			if (ipts->switch_sensor_mode) {
-+				ipts_set_state(ipts, IPTS_STA_INIT);
-+				ipts->sensor_mode = ipts->new_sensor_mode;
-+				ipts->switch_sensor_mode = false;
-+
-+				ipts_send_sensor_clear_mem_window_cmd(ipts);
-+			}
-+
-+			break;
-+		}
-+	}
-+
-+	/* handle error in rsp_status */
-+	if (rsp_status != 0) {
-+		switch (rsp_status) {
-+			case TOUCH_STATUS_SENSOR_EXPECTED_RESET:
-+			case TOUCH_STATUS_SENSOR_UNEXPECTED_RESET:
-+				ipts_dbg(ipts, "sensor reset %d\n", rsp_status);
-+				ipts_restart(ipts);
-+				break;
-+			default:
-+				ipts_dbg(ipts, "cmd : 0x%08x, status %d\n",
-+								cmd,
-+								rsp_status);
-+				break;
-+		}
-+	}
-+
-+	if (cmd_status) {
-+		ipts_restart(ipts);
-+	}
-+
-+	return ret;
-+}
-diff --git a/drivers/misc/ipts/ipts-msg-handler.h b/drivers/misc/ipts/ipts-msg-handler.h
-new file mode 100644
-index 0000000..b8e27d3
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-msg-handler.h
-@@ -0,0 +1,32 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus ME message handler
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_MSG_HANDLER_H
-+#define _IPTS_MSG_HANDLER_H
-+
-+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size);
-+int ipts_start(ipts_info_t *ipts);
-+void ipts_stop(ipts_info_t *ipts);
-+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode);
-+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg,
-+                        					u32 msg_len);
-+int ipts_handle_processed_data(ipts_info_t *ipts);
-+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id);
-+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts);
-+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts);
-+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts);
-+
-+#endif /* _IPTS_MSG_HANDLER_H */
-diff --git a/drivers/misc/ipts/ipts-resource.c b/drivers/misc/ipts/ipts-resource.c
-new file mode 100644
-index 0000000..47607ef
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-resource.c
-@@ -0,0 +1,277 @@
-+#include <linux/dma-mapping.h>
-+
-+#include "ipts.h"
-+#include "ipts-mei-msgs.h"
-+#include "ipts-kernel.h"
-+
-+static void free_common_resource(ipts_info_t *ipts)
-+{
-+	char *addr;
-+	ipts_buffer_info_t *feedback_buffer;
-+	dma_addr_t dma_addr;
-+	u32 buffer_size;
-+	int i, num_of_parallels;
-+
-+	if (ipts->resource.me2hid_buffer) {
-+		devm_kfree(&ipts->cldev->dev, ipts->resource.me2hid_buffer);
-+		ipts->resource.me2hid_buffer = 0;
-+	}
-+
-+	addr = ipts->resource.hid2me_buffer.addr;
-+	dma_addr = ipts->resource.hid2me_buffer.dma_addr;
-+	buffer_size = ipts->resource.hid2me_buffer_size;
-+
-+	if (ipts->resource.hid2me_buffer.addr) {
-+		dmam_free_coherent(&ipts->cldev->dev, buffer_size, addr, dma_addr);
-+		ipts->resource.hid2me_buffer.addr = 0;
-+		ipts->resource.hid2me_buffer.dma_addr = 0;
-+		ipts->resource.hid2me_buffer_size = 0;
-+	}
-+
-+	feedback_buffer = ipts->resource.feedback_buffer;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		if (feedback_buffer[i].addr) {
-+			dmam_free_coherent(&ipts->cldev->dev,
-+				ipts->device_info.feedback_size,
-+				feedback_buffer[i].addr,
-+				feedback_buffer[i].dma_addr);
-+			feedback_buffer[i].addr = 0;
-+			feedback_buffer[i].dma_addr = 0;
-+		}
-+	}
-+}
-+
-+static int allocate_common_resource(ipts_info_t *ipts)
-+{
-+	char *addr, *me2hid_addr;
-+	ipts_buffer_info_t *feedback_buffer;
-+	dma_addr_t dma_addr;
-+	int i, ret = 0, num_of_parallels;
-+	u32 buffer_size;
-+
-+	buffer_size = ipts->device_info.feedback_size;
-+
-+	addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+			buffer_size,
-+			&dma_addr,
-+			GFP_ATOMIC|__GFP_ZERO);
-+	if (addr == NULL)
-+		return -ENOMEM;
-+
-+	me2hid_addr = devm_kzalloc(&ipts->cldev->dev, buffer_size, GFP_KERNEL);
-+	if (me2hid_addr == NULL) {
-+		ret = -ENOMEM;
-+		goto release_resource;
-+	}
-+
-+	ipts->resource.hid2me_buffer.addr = addr;
-+	ipts->resource.hid2me_buffer.dma_addr = dma_addr;
-+	ipts->resource.hid2me_buffer_size = buffer_size;
-+	ipts->resource.me2hid_buffer = me2hid_addr;
-+
-+	feedback_buffer = ipts->resource.feedback_buffer;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		feedback_buffer[i].addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+				ipts->device_info.feedback_size,
-+				&feedback_buffer[i].dma_addr,
-+				GFP_ATOMIC|__GFP_ZERO);
-+
-+		if (feedback_buffer[i].addr == NULL) {
-+			ret = -ENOMEM;
-+			goto release_resource;
-+		}
-+	}
-+
-+	return 0;
-+
-+release_resource:
-+	free_common_resource(ipts);
-+
-+	return ret;
-+}
-+
-+void ipts_free_raw_data_resource(ipts_info_t *ipts)
-+{
-+	if (ipts_is_raw_data_resource_ready(ipts)) {
-+		ipts->resource.raw_data_resource_ready = false;
-+
-+		ipts_release_kernels(ipts);
-+	}
-+}
-+
-+static int allocate_hid_resource(ipts_info_t *ipts)
-+{
-+	ipts_buffer_info_t *buffer_hid;
-+
-+	/* hid mode uses only one touch data buffer */
-+	buffer_hid = &ipts->resource.touch_data_buffer_hid;
-+	buffer_hid->addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+				ipts->device_info.frame_size,
-+				&buffer_hid->dma_addr,
-+				GFP_ATOMIC|__GFP_ZERO);
-+	if (buffer_hid->addr == NULL) {
-+		return -ENOMEM;
-+	}
-+
-+	return 0;
-+}
-+
-+static void free_hid_resource(ipts_info_t *ipts)
-+{
-+	ipts_buffer_info_t *buffer_hid;
-+
-+	buffer_hid = &ipts->resource.touch_data_buffer_hid;
-+	if (buffer_hid->addr) {
-+		dmam_free_coherent(&ipts->cldev->dev,
-+				ipts->device_info.frame_size,
-+				buffer_hid->addr,
-+				buffer_hid->dma_addr);
-+		buffer_hid->addr = 0;
-+		buffer_hid->dma_addr = 0;
-+	}
-+}
-+
-+int ipts_allocate_default_resource(ipts_info_t *ipts)
-+{
-+	int ret;
-+
-+	ret = allocate_common_resource(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot allocate common resource\n");
-+		return ret;
-+	}
-+
-+	ret = allocate_hid_resource(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot allocate hid resource\n");
-+		free_common_resource(ipts);
-+		return ret;
-+	}
-+
-+	ipts->resource.default_resource_ready = true;
-+
-+	return 0;
-+}
-+
-+void ipts_free_default_resource(ipts_info_t *ipts)
-+{
-+	if (ipts_is_default_resource_ready(ipts)) {
-+		ipts->resource.default_resource_ready = false;
-+
-+		free_hid_resource(ipts);
-+		free_common_resource(ipts);
-+	}
-+}
-+
-+int ipts_allocate_raw_data_resource(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ret = ipts_init_kernels(ipts);
-+	if (ret) {
-+		return ret;
-+	}
-+
-+	ipts->resource.raw_data_resource_ready = true;
-+
-+	return 0;
-+}
-+
-+static void get_hid_only_smw_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data,
-+				ipts_resource_t *resrc)
-+{
-+	ipts_buffer_info_t *touch_buf;
-+	ipts_buffer_info_t *feedback_buf;
-+
-+	touch_buf = &resrc->touch_data_buffer_hid;
-+	feedback_buf = &resrc->feedback_buffer[0];
-+
-+	data->touch_data_buffer_addr_lower[0] =
-+				lower_32_bits(touch_buf->dma_addr);
-+	data->touch_data_buffer_addr_upper[0] =
-+				upper_32_bits(touch_buf->dma_addr);
-+	data->feedback_buffer_addr_lower[0] =
-+				lower_32_bits(feedback_buf->dma_addr);
-+	data->feedback_buffer_addr_upper[0] =
-+				upper_32_bits(feedback_buf->dma_addr);
-+}
-+
-+static void get_raw_data_only_smw_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data,
-+				ipts_resource_t *resrc)
-+{
-+	u64 wq_tail_phy_addr;
-+	u64 cookie_phy_addr;
-+	ipts_buffer_info_t *touch_buf;
-+	ipts_buffer_info_t *feedback_buf;
-+	int i, num_of_parallels;
-+
-+	touch_buf = resrc->touch_data_buffer_raw;
-+	feedback_buf = resrc->feedback_buffer;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		data->touch_data_buffer_addr_lower[i] =
-+					lower_32_bits(touch_buf[i].dma_addr);
-+		data->touch_data_buffer_addr_upper[i] =
-+					upper_32_bits(touch_buf[i].dma_addr);
-+		data->feedback_buffer_addr_lower[i] =
-+					lower_32_bits(feedback_buf[i].dma_addr);
-+		data->feedback_buffer_addr_upper[i] =
-+					upper_32_bits(feedback_buf[i].dma_addr);
-+	}
-+
-+	wq_tail_phy_addr = resrc->wq_info.wq_tail_phy_addr;
-+	data->tail_offset_addr_lower = lower_32_bits(wq_tail_phy_addr);
-+	data->tail_offset_addr_upper = upper_32_bits(wq_tail_phy_addr);
-+
-+	cookie_phy_addr = resrc->wq_info.db_phy_addr +
-+						resrc->wq_info.db_cookie_offset;
-+	data->doorbell_cookie_addr_lower = lower_32_bits(cookie_phy_addr);
-+	data->doorbell_cookie_addr_upper = upper_32_bits(cookie_phy_addr);
-+	data->work_queue_size = resrc->wq_info.wq_size;
-+
-+	data->work_queue_item_size = resrc->wq_item_size;
-+}
-+
-+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data)
-+{
-+	ipts_resource_t *resrc = &ipts->resource;
-+
-+	if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA)
-+		get_raw_data_only_smw_cmd_data(ipts, data, resrc);
-+	else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID)
-+		get_hid_only_smw_cmd_data(ipts, data, resrc);
-+
-+	/* hid2me is common for "raw data" and "hid" */
-+	data->hid2me_buffer_addr_lower =
-+				lower_32_bits(resrc->hid2me_buffer.dma_addr);
-+	data->hid2me_buffer_addr_upper =
-+				upper_32_bits(resrc->hid2me_buffer.dma_addr);
-+	data->hid2me_buffer_size = resrc->hid2me_buffer_size;
-+}
-+
-+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx,
-+						u8* cpu_addr, u64 dma_addr)
-+{
-+	ipts_buffer_info_t *touch_buf;
-+
-+	touch_buf = ipts->resource.touch_data_buffer_raw;
-+	touch_buf[parallel_idx].dma_addr = dma_addr;
-+	touch_buf[parallel_idx].addr = cpu_addr;
-+}
-+
-+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx,
-+						u8* cpu_addr, u64 dma_addr)
-+{
-+	ipts_buffer_info_t *output_buf;
-+
-+	output_buf = &ipts->resource.raw_data_mode_output_buffer[parallel_idx][output_idx];
-+
-+	output_buf->dma_addr = dma_addr;
-+	output_buf->addr = cpu_addr;
-+}
-diff --git a/drivers/misc/ipts/ipts-resource.h b/drivers/misc/ipts/ipts-resource.h
-new file mode 100644
-index 0000000..7d66ac7
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-resource.h
-@@ -0,0 +1,30 @@
-+/*
-+ * Intel Precise Touch & Stylus state codes
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_RESOURCE_H_
-+#define _IPTS_RESOURCE_H_
-+
-+int ipts_allocate_default_resource(ipts_info_t *ipts);
-+void ipts_free_default_resource(ipts_info_t *ipts);
-+int ipts_allocate_raw_data_resource(ipts_info_t *ipts);
-+void ipts_free_raw_data_resource(ipts_info_t *ipts);
-+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data);
-+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx,
-+						u8* cpu_addr, u64 dma_addr);
-+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx,
-+						u8* cpu_addr, u64 dma_addr);
-+
-+#endif // _IPTS_RESOURCE_H_
-diff --git a/drivers/misc/ipts/ipts-sensor-regs.h b/drivers/misc/ipts/ipts-sensor-regs.h
-new file mode 100644
-index 0000000..96812b0
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-sensor-regs.h
-@@ -0,0 +1,700 @@
-+/*
-+ * Touch Sensor Register definition
-+ *
-+ * Copyright (c) 2013-2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+
-+#ifndef _TOUCH_SENSOR_REGS_H
-+#define _TOUCH_SENSOR_REGS_H
-+
-+#pragma pack(1)
-+
-+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch
-+#ifndef C_ASSERT
-+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
-+#endif
-+
-+//
-+// Compatibility versions for this header file
-+//
-+#define TOUCH_EDS_REV_MINOR     0
-+#define TOUCH_EDS_REV_MAJOR     1
-+#define TOUCH_EDS_INTF_REV      1
-+#define TOUCH_PROTOCOL_VER      0
-+
-+
-+//
-+// Offset 00h: TOUCH_STS: Status Register
-+// This register is read by the SPI Controller immediately following an interrupt.
-+//
-+#define TOUCH_STS_REG_OFFSET                0x00
-+
-+typedef enum touch_sts_reg_int_type
-+{
-+    TOUCH_STS_REG_INT_TYPE_DATA_AVAIL = 0,  // Touch Data Available
-+    TOUCH_STS_REG_INT_TYPE_RESET_OCCURRED,  // Reset Occurred
-+    TOUCH_STS_REG_INT_TYPE_ERROR_OCCURRED,  // Error Occurred
-+    TOUCH_STS_REG_INT_TYPE_VENDOR_DATA,     // Vendor specific data, treated same as raw frame
-+    TOUCH_STS_REG_INT_TYPE_GET_FEATURES,    // Get Features response data available
-+    TOUCH_STS_REG_INT_TYPE_MAX
-+} touch_sts_reg_int_type_t;
-+C_ASSERT(sizeof(touch_sts_reg_int_type_t) == 4);
-+
-+typedef enum touch_sts_reg_pwr_state
-+{
-+    TOUCH_STS_REG_PWR_STATE_SLEEP = 0,  // Sleep
-+    TOUCH_STS_REG_PWR_STATE_DOZE,       // Doze
-+    TOUCH_STS_REG_PWR_STATE_ARMED,      // Armed
-+    TOUCH_STS_REG_PWR_STATE_SENSING,    // Sensing
-+    TOUCH_STS_REG_PWR_STATE_MAX
-+} touch_sts_reg_pwr_state_t;
-+C_ASSERT(sizeof(touch_sts_reg_pwr_state_t) == 4);
-+
-+typedef enum touch_sts_reg_init_state
-+{
-+    TOUCH_STS_REG_INIT_STATE_READY_FOR_OP = 0,  // Ready for normal operation
-+    TOUCH_STS_REG_INIT_STATE_FW_NEEDED,         // Touch IC needs its Firmware loaded
-+    TOUCH_STS_REG_INIT_STATE_DATA_NEEDED,       // Touch IC needs its Data loaded
-+    TOUCH_STS_REG_INIT_STATE_INIT_ERROR,        // Error info in TOUCH_ERR_REG
-+    TOUCH_STS_REG_INIT_STATE_MAX
-+} touch_sts_reg_init_state_t;
-+C_ASSERT(sizeof(touch_sts_reg_init_state_t) == 4);
-+
-+#define TOUCH_SYNC_BYTE_VALUE   0x5A
-+
-+typedef union touch_sts_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // When set, this indicates the hardware has data that needs to be read.
-+        u32  int_status           :1;
-+        // see TOUCH_STS_REG_INT_TYPE
-+        u32  int_type             :4;
-+        // see TOUCH_STS_REG_PWR_STATE
-+        u32  pwr_state            :2;
-+        // see TOUCH_STS_REG_INIT_STATE
-+        u32  init_state           :2;
-+        // Busy bit indicates that sensor cannot accept writes at this time
-+        u32  busy                :1;
-+        // Reserved
-+        u32  reserved            :14;
-+        // Synchronization bit, should always be TOUCH_SYNC_BYTE_VALUE
-+        u32  sync_byte            :8;
-+    } fields;
-+} touch_sts_reg_t;
-+C_ASSERT(sizeof(touch_sts_reg_t) == 4);
-+
-+
-+//
-+// Offset 04h: TOUCH_FRAME_CHAR: Frame Characteristics Register
-+// This registers describes the characteristics of each data frame read by the SPI Controller in
-+// response to a touch interrupt.
-+//
-+#define TOUCH_FRAME_CHAR_REG_OFFSET         0x04
-+
-+typedef union touch_frame_char_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Micro-Frame Size (MFS):  Indicates the size of a touch micro-frame in byte increments.
-+        // When a micro-frame is to be read for processing (in data mode), this is the total number of
-+        // bytes that must be read per interrupt, split into multiple read commands no longer than RPS.
-+        // Maximum micro-frame size is 256KB.
-+        u32  microframe_size      :18;
-+        // Micro-Frames per Frame (MFPF): Indicates the number of micro-frames per frame. If a
-+        // sensor's frame does not contain micro-frames this value will be 1. Valid values are 1-31.
-+        u32  microframes_per_frame :5;
-+        // Micro-Frame Index (MFI): Indicates the index of the micro-frame within a frame. This allows
-+        // the SPI Controller to maintain synchronization with the sensor and determine when the final
-+        // micro-frame has arrived. Valid values are 1-31.
-+        u32  microframe_index     :5;
-+        // HID/Raw Data: This bit describes whether the data from the sensor is Raw data or a HID
-+        // report. When set, the data is a HID report.
-+        u32  hid_report           :1;
-+        // Reserved
-+        u32  reserved            :3;
-+    } fields;
-+} touch_frame_char_reg_t;
-+C_ASSERT(sizeof(touch_frame_char_reg_t) == 4);
-+
-+
-+//
-+// Offset 08h: Touch Error Register
-+//
-+#define TOUCH_ERR_REG_OFFSET                0x08
-+
-+// bit definition is vendor specific
-+typedef union touch_err_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        u32  invalid_fw           :1;
-+        u32  invalid_data        :1;
-+        u32  self_test_failed       :1;
-+        u32  reserved            :12;
-+        u32  fatal_error          :1;
-+        u32  vendor_errors        :16;
-+    } fields;
-+} touch_err_reg_t;
-+C_ASSERT(sizeof(touch_err_reg_t) == 4);
-+
-+
-+//
-+// Offset 0Ch: RESERVED
-+// This register is reserved for future use.
-+//
-+
-+
-+//
-+// Offset 10h: Touch Identification Register
-+//
-+#define TOUCH_ID_REG_OFFSET                 0x10
-+
-+#define TOUCH_ID_REG_VALUE                  0x43495424
-+
-+// expected value is "$TIC" or 0x43495424
-+typedef u32  touch_id_reg_t;
-+C_ASSERT(sizeof(touch_id_reg_t) == 4);
-+
-+
-+//
-+// Offset 14h: TOUCH_DATA_SZ: Touch Data Size Register
-+// This register describes the maximum size of frames and feedback data
-+//
-+#define TOUCH_DATA_SZ_REG_OFFSET            0x14
-+
-+#define TOUCH_MAX_FRAME_SIZE_INCREMENT      64
-+#define TOUCH_MAX_FEEDBACK_SIZE_INCREMENT   64
-+
-+#define TOUCH_SENSOR_MAX_FRAME_SIZE         (32 * 1024)     // Max allowed frame size 32KB
-+#define TOUCH_SENSOR_MAX_FEEDBACK_SIZE      (16 * 1024)     // Max allowed feedback size 16KB
-+
-+typedef union touch_data_sz_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // This value describes the maximum frame size in 64byte increments.
-+        u32  max_frame_size        :12;
-+        // This value describes the maximum feedback size in 64byte increments.
-+        u32  max_feedback_size     :8;
-+        // Reserved
-+        u32  reserved            :12;
-+    } fields;
-+} touch_data_sz_reg_t;
-+C_ASSERT(sizeof(touch_data_sz_reg_t) == 4);
-+
-+
-+//
-+// Offset 18h: TOUCH_CAPABILITIES: Touch Capabilities Register
-+// This register informs the host as to the capabilities of the touch IC.
-+//
-+#define TOUCH_CAPS_REG_OFFSET               0x18
-+
-+typedef enum touch_caps_reg_read_delay_time
-+{
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_0,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_10uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_50uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_100uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_150uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_250uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_500uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_1mS,
-+} touch_caps_reg_read_delay_time_t;
-+C_ASSERT(sizeof(touch_caps_reg_read_delay_time_t) == 4);
-+
-+#define TOUCH_BULK_DATA_MAX_WRITE_INCREMENT 64
-+
-+typedef union touch_caps_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Reserved for future frequency
-+        u32  reserved0           :1;
-+        // 17 MHz (14 MHz on Atom) Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_17Mhz      :1;
-+        // 30 MHz (25MHz on Atom) Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_30Mhz      :1;
-+        // 50 MHz Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_50Mhz      :1;
-+        // Reserved
-+        u32  reserved1           :4;
-+        // Single I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_single_io   :1;
-+        // Dual I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_dual_io     :1;
-+        // Quad I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_quad_io     :1;
-+        // Bulk Data Area Max Write Size: The amount of data the SPI Controller can write to the bulk
-+        // data area before it has to poll the busy bit. This field is in multiples of 64 bytes. The
-+        // SPI Controller will write the amount of data specified in this field, then check and wait
-+        // for the Status.Busy bit to be zero before writing the next data chunk. This field is 6 bits
-+        // long, allowing for 4KB of contiguous writes w/o a poll of the busy bit. If this field is
-+        // 0x00 the Touch IC has no limit in the amount of data the SPI Controller can write to the
-+        // bulk data area.
-+        u32  bulk_data_max_write    :6;
-+        // Read Delay Timer Value: This field describes the delay the SPI Controller will initiate when
-+        // a read interrupt follows a write data command. Uses values from TOUCH_CAPS_REG_READ_DELAY_TIME
-+        u32  read_delay_timer_value :3;
-+        // Reserved
-+        u32  reserved2           :4;
-+        // Maximum Touch Points: A byte value based on the HID descriptor definition.
-+        u32  max_touch_points      :8;
-+    } fields;
-+} touch_caps_reg_t;
-+C_ASSERT(sizeof(touch_caps_reg_t) == 4);
-+
-+
-+//
-+// Offset 1Ch: TOUCH_CFG: Touch Configuration Register
-+// This register allows the SPI Controller to configure the touch sensor as needed during touch
-+// operations.
-+//
-+#define TOUCH_CFG_REG_OFFSET                0x1C
-+
-+typedef enum touch_cfg_reg_bulk_xfer_size
-+{
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_4B  = 0,   // Bulk Data Transfer Size is 4 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_8B,        // Bulk Data Transfer Size is 8 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_16B,       // Bulk Data Transfer Size is 16 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_32B,       // Bulk Data Transfer Size is 32 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_64B,       // Bulk Data Transfer Size is 64 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_MAX
-+} touch_cfg_reg_bulk_xfer_size_t;
-+C_ASSERT(sizeof(touch_cfg_reg_bulk_xfer_size_t) == 4);
-+
-+// Frequency values used by TOUCH_CFG_REG and TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+typedef enum touch_freq
-+{
-+    TOUCH_FREQ_RSVD = 0,    // Reserved value
-+    TOUCH_FREQ_17MHZ,       // Sensor set for 17MHz operation (14MHz on Atom)
-+    TOUCH_FREQ_30MHZ,       // Sensor set for 30MHz operation (25MHz on Atom)
-+    TOUCH_FREQ_MAX          // Invalid value
-+} touch_freq_t;
-+C_ASSERT(sizeof(touch_freq_t) == 4);
-+
-+typedef union touch_cfg_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Touch Enable (TE):  This bit is used as a HW semaphore for the Touch IC to guarantee to the
-+        // SPI Controller to that (when 0) no sensing operations will occur and only the Reset
-+        // interrupt will be generated. When TE is cleared by the SPI Controller:
-+        //  - TICs must flush all output buffers
-+        //  - TICs must De-assert any pending interrupt
-+        //  - ME must throw away any partial frame and pending interrupt must be cleared/not serviced.
-+        // The SPI Controller will only modify the configuration of the TIC when TE is cleared. TE is
-+        // defaulted to 0h on a power-on reset.
-+        u32  touch_enable         :1;
-+        // Data/HID Packet Mode (DHPM): Raw Data Mode: 0h, HID Packet Mode: 1h
-+        u32  dhpm                :1;
-+        // Bulk Data Transfer Size: This field represents the amount of data written to the Bulk Data
-+        // Area (SPI Offset 0x1000-0x2FFF) in a single SPI write protocol
-+        u32  bulk_xfer_size        :4;
-+        // Frequency Select: Frequency for the TouchIC to run at. Use values from TOUCH_FREQ
-+        u32  freq_select          :3;
-+        // Reserved
-+        u32  reserved            :23;
-+    } fields;
-+} touch_cfg_reg_t;
-+C_ASSERT(sizeof(touch_cfg_reg_t) == 4);
-+
-+
-+//
-+// Offset 20h: TOUCH_CMD: Touch Command Register
-+// This register is used for sending commands to the Touch IC.
-+//
-+#define TOUCH_CMD_REG_OFFSET                0x20
-+
-+typedef enum touch_cmd_reg_code
-+{
-+    TOUCH_CMD_REG_CODE_NOP = 0,             // No Operation
-+    TOUCH_CMD_REG_CODE_SOFT_RESET,          // Soft Reset
-+    TOUCH_CMD_REG_CODE_PREP_4_READ,         // Prepare All Registers for Read
-+    TOUCH_CMD_REG_CODE_GEN_TEST_PACKETS,    // Generate Test Packets according to value in TOUCH_TEST_CTRL_REG
-+    TOUCH_CMD_REG_CODE_MAX
-+} touch_cmd_reg_code_t;
-+C_ASSERT(sizeof(touch_cmd_reg_code_t) == 4);
-+
-+typedef union touch_cmd_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Command Code: See TOUCH_CMD_REG_CODE
-+        u32  command_code :8;
-+        // Reserved
-+        u32  reserved    :24;
-+    } fields;
-+} touch_cmd_reg_t;
-+C_ASSERT(sizeof(touch_cmd_reg_t) == 4);
-+
-+
-+//
-+// Offset 24h: Power Management Control
-+// This register is used for active power management. The Touch IC is allowed to mover from Doze or
-+// Armed to Sensing after a touch has occurred. All other transitions will be made at the request
-+// of the SPI Controller.
-+//
-+#define TOUCH_PWR_MGMT_CTRL_REG_OFFSET      0x24
-+
-+typedef enum touch_pwr_mgmt_ctrl_reg_cmd
-+{
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_NOP = 0,    // No change to power state
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_SLEEP,      // Sleep   - set when the system goes into connected standby
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_DOZE,       // Doze    - set after 300 seconds of inactivity
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_ARMED,      // Armed   - Set by FW when a "finger off" message is received from the EUs
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_SENSING,    // Sensing - not typically set by FW
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_MAX         // Values will result in no change to the power state of the Touch IC
-+} touch_pwr_mgmt_ctrl_reg_cmd_t;
-+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_cmd_t) == 4);
-+
-+typedef union touch_pwr_mgmt_ctrl_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Power State Command: See TOUCH_PWR_MGMT_CTRL_REG_CMD
-+        u32  pwr_state_cmd         :3;
-+        // Reserved
-+        u32  reserved            :29;
-+    } fields;
-+} touch_pwr_mgmt_ctrl_reg_t;
-+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_t) == 4);
-+
-+
-+//
-+// Offset 28h: Vendor HW Information Register
-+// This register is used to relay Intel-assigned vendor ID information to the SPI Controller, which
-+// may be forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_VEN_HW_INFO_REG_OFFSET        0x28
-+
-+typedef union touch_ven_hw_info_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Touch Sensor Vendor ID
-+        u32  vendor_id            :16;
-+        // Touch Sensor Device ID
-+        u32  device_id            :16;
-+    } fields;
-+} touch_ven_hw_info_reg_t;
-+C_ASSERT(sizeof(touch_ven_hw_info_reg_t) == 4);
-+
-+
-+//
-+// Offset 2Ch: HW Revision ID Register
-+// This register is used to relay vendor HW revision information to the SPI Controller which may be
-+// forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_HW_REV_REG_OFFSET             0x2C
-+
-+typedef u32  touch_hw_rev_reg_t;   // bit definition is vendor specific
-+C_ASSERT(sizeof(touch_hw_rev_reg_t) == 4);
-+
-+
-+//
-+// Offset 30h: FW Revision ID Register
-+// This register is used to relay vendor FW revision information to the SPI Controller which may be
-+// forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_FW_REV_REG_OFFSET             0x30
-+
-+typedef u32  touch_fw_rev_reg_t;    // bit definition is vendor specific
-+C_ASSERT(sizeof(touch_fw_rev_reg_t) == 4);
-+
-+
-+//
-+// Offset 34h: Compatibility Revision ID Register
-+// This register is used to relay vendor compatibility information to the SPI Controller which may
-+// be forwarded to SW running on the host CPU. Compatibility Information is a numeric value given
-+// by Intel to the Touch IC vendor based on the major and minor revision of the EDS supported. From
-+// a nomenclature point of view in an x.y revision number of the EDS, the major version is the value
-+// of x and the minor version is the value of y. For example, a Touch IC supporting an EDS version
-+// of 0.61 would contain a major version of 0 and a minor version of 61 in the register.
-+//
-+#define TOUCH_COMPAT_REV_REG_OFFSET             0x34
-+
-+typedef union touch_compat_rev_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // EDS Minor Revision
-+        u8   minor;
-+        // EDS Major Revision
-+        u8   major;
-+        // Interface Revision Number (from EDS)
-+        u8   intf_rev;
-+        // EU Kernel Compatibility Version - vendor specific value
-+        u8   kernel_compat_ver;
-+    } fields;
-+} touch_compat_rev_reg_t;
-+C_ASSERT(sizeof(touch_compat_rev_reg_t) == 4);
-+
-+
-+//
-+// Touch Register Block is the full set of registers from offset 0x00h to 0x3F
-+// This is the entire set of registers needed for normal touch operation. It does not include test
-+// registers such as TOUCH_TEST_CTRL_REG
-+//
-+#define TOUCH_REG_BLOCK_OFFSET              TOUCH_STS_REG_OFFSET
-+
-+typedef struct touch_reg_block
-+{
-+    touch_sts_reg_t         sts_reg;         // 0x00
-+    touch_frame_char_reg_t  frame_char_reg;   // 0x04
-+    touch_err_reg_t         error_reg;       // 0x08
-+    u32                  reserved0;      // 0x0C
-+    touch_id_reg_t          id_reg;          // 0x10
-+    touch_data_sz_reg_t     data_size_reg;    // 0x14
-+    touch_caps_reg_t        caps_reg;        // 0x18
-+    touch_cfg_reg_t         cfg_reg;         // 0x1C
-+    touch_cmd_reg_t         cmd_reg;         // 0x20
-+    touch_pwr_mgmt_ctrl_reg_t  pwm_mgme_ctrl_reg; // 0x24
-+    touch_ven_hw_info_reg_t ven_hw_info_reg;   // 0x28
-+    touch_hw_rev_reg_t      hw_rev_reg;       // 0x2C
-+    touch_fw_rev_reg_t      fw_rev_reg;       // 0x30
-+    touch_compat_rev_reg_t  compat_rev_reg;   // 0x34
-+    u32                  reserved1;      // 0x38
-+    u32                  reserved2;      // 0x3C
-+} touch_reg_block_t;
-+C_ASSERT(sizeof(touch_reg_block_t) == 64);
-+
-+
-+//
-+// Offset 40h: Test Control Register
-+// This register
-+//
-+#define TOUCH_TEST_CTRL_REG_OFFSET              0x40
-+
-+typedef union touch_test_ctrl_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Size of Test Frame in Raw Data Mode: This field specifies the test frame size in raw data
-+        // mode in multiple of 64 bytes. For example, if this field value is 16, the test frame size
-+        // will be 16x64 = 1K.
-+        u32  raw_test_frame_size    :16;
-+        // Number of Raw Data Frames or HID Report Packets Generation. This field represents the number
-+        // of test frames or HID reports to be generated when test mode is enabled. When multiple
-+        // packets/frames are generated, they need be generated at 100 Hz frequency, i.e. 10ms per
-+        // packet/frame.
-+        u32  num_test_frames       :16;
-+    } fields;
-+} touch_test_ctrl_reg_t;
-+C_ASSERT(sizeof(touch_test_ctrl_reg_t) == 4);
-+
-+
-+//
-+// Offsets 0x000 to 0xFFF are reserved for Intel-defined Registers
-+//
-+#define TOUCH_REGISTER_LIMIT                0xFFF
-+
-+
-+//
-+// Data Window: Address 0x1000-0x1FFFF
-+// The data window is reserved for writing and reading large quantities of data to and from the
-+// sensor.
-+//
-+#define TOUCH_DATA_WINDOW_OFFSET            0x1000
-+#define TOUCH_DATA_WINDOW_LIMIT             0x1FFFF
-+
-+#define TOUCH_SENSOR_MAX_OFFSET             TOUCH_DATA_WINDOW_LIMIT
-+
-+
-+//
-+// The following data structures represent the headers defined in the Data Structures chapter of the
-+// Intel Integrated Touch EDS
-+//
-+
-+// Enumeration used in TOUCH_RAW_DATA_HDR
-+typedef enum touch_raw_data_types
-+{
-+    TOUCH_RAW_DATA_TYPE_FRAME = 0,
-+    TOUCH_RAW_DATA_TYPE_ERROR,          // RawData will be the TOUCH_ERROR struct below
-+    TOUCH_RAW_DATA_TYPE_VENDOR_DATA,    // Set when InterruptType is Vendor Data
-+    TOUCH_RAW_DATA_TYPE_HID_REPORT,
-+    TOUCH_RAW_DATA_TYPE_GET_FEATURES,
-+    TOUCH_RAW_DATA_TYPE_MAX
-+} touch_raw_data_types_t;
-+C_ASSERT(sizeof(touch_raw_data_types_t) == 4);
-+
-+// Private data structure. Kernels must copy to HID driver buffer
-+typedef struct touch_hid_private_data
-+{
-+    u32  transaction_id;
-+    u8   reserved[28];
-+} touch_hid_private_data_t;
-+C_ASSERT(sizeof(touch_hid_private_data_t) == 32);
-+
-+// This is the data structure sent from the PCH FW to the EU kernel
-+typedef struct touch_raw_data_hdr
-+{
-+    u32                  data_type;           // use values from TOUCH_RAW_DATA_TYPES
-+    u32                  raw_data_size_bytes;   // The size in bytes of the raw data read from the
-+                                                // sensor, does not include TOUCH_RAW_DATA_HDR. Will
-+                                                // be the sum of all uFrames, or size of TOUCH_ERROR
-+                                                // for if DataType is TOUCH_RAW_DATA_TYPE_ERROR
-+    u32                  buffer_id;           // An ID to qualify with the feedback data to track
-+                                                // buffer usage
-+    u32                  protocol_ver;        // Must match protocol version of the EDS
-+    u8                   kernel_compat_id;     // Copied from the Compatibility Revision ID Reg
-+    u8                   reserved[15];       // Padding to extend header to full 64 bytes and
-+                                                // allow for growth
-+    touch_hid_private_data_t  hid_private_data;     // Private data structure. Kernels must copy to HID
-+                                                // driver buffer
-+} touch_raw_data_hdr_t;
-+C_ASSERT(sizeof(touch_raw_data_hdr_t) == 64);
-+
-+typedef struct touch_raw_data
-+{
-+    touch_raw_data_hdr_t  header;
-+    u8               raw_data[1]; // used to access the raw data as an array and keep the
-+                                    // compilers happy. Actual size of this array is
-+                                    // Header.RawDataSizeBytes
-+} touch_raw_data_t;
-+
-+
-+// The following section describes the data passed in TOUCH_RAW_DATA.RawData when DataType equals
-+// TOUCH_RAW_DATA_TYPE_ERROR
-+// Note: This data structure is also applied to HID mode
-+typedef enum touch_err_types
-+{
-+    TOUCH_RAW_DATA_ERROR = 0,
-+    TOUCH_RAW_ERROR_MAX
-+} touch_err_types_t;
-+C_ASSERT(sizeof(touch_err_types_t) == 4);
-+
-+typedef union touch_me_fw_error
-+{
-+    u32  value;
-+
-+    struct
-+    {
-+        u32 invalid_frame_characteristics : 1;
-+        u32 microframe_index_invalid      : 1;
-+        u32 reserved                    : 30;
-+    } fields;
-+} touch_me_fw_error_t;
-+C_ASSERT(sizeof(touch_me_fw_error_t) == 4);
-+
-+typedef struct touch_error
-+{
-+    u8			touch_error_type; // This must be a value from TOUCH_ERROR_TYPES
-+    u8			reserved[3];
-+    touch_me_fw_error_t	touch_me_fw_error;
-+    touch_err_reg_t	touch_error_register; // Contains the value copied from the Touch Error Reg
-+} touch_error_t;
-+C_ASSERT(sizeof(touch_error_t) == 12);
-+
-+// Enumeration used in TOUCH_FEEDBACK_BUFFER
-+typedef enum touch_feedback_cmd_types
-+{
-+    TOUCH_FEEDBACK_CMD_TYPE_NONE = 0,
-+    TOUCH_FEEDBACK_CMD_TYPE_SOFT_RESET,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_ARMED,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_SENSING,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_SLEEP,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_DOZE,
-+    TOUCH_FEEDBACK_CMD_TYPE_HARD_RESET,
-+    TOUCH_FEEDBACK_CMD_TYPE_MAX
-+} touch_feedback_cmd_types_t;
-+C_ASSERT(sizeof(touch_feedback_cmd_types_t) == 4);
-+
-+// Enumeration used in TOUCH_FEEDBACK_HDR
-+typedef enum touch_feedback_data_types
-+{
-+    TOUCH_FEEDBACK_DATA_TYPE_FEEDBACK = 0,  // This is vendor specific feedback to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES,  // This is a set features command to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES,  // This is a get features command to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT, // This is a HID output report to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_STORE_DATA,    // This is calibration data to be written to system flash
-+    TOUCH_FEEDBACK_DATA_TYPE_MAX
-+} touch_feedback_data_types_t;
-+C_ASSERT(sizeof(touch_feedback_data_types_t) == 4);
-+
-+// This is the data structure sent from the EU kernels back to the ME FW.
-+// In addition to "feedback" data, the FW can execute a "command" described by the command type parameter.
-+// Any payload data will always be sent to the TIC first, then any command will be issued.
-+typedef struct touch_feedback_hdr
-+{
-+    u32  feedback_cmd_type;    // use values from TOUCH_FEEDBACK_CMD_TYPES
-+    u32  payload_size_bytes;   // The amount of data to be written to the sensor, not including the header
-+    u32  buffer_id;           // The ID of the raw data buffer that generated this feedback data
-+    u32  protocol_ver;        // Must match protocol version of the EDS
-+    u32  feedback_data_type;   // use values from TOUCH_FEEDBACK_DATA_TYPES. This is not relevant if PayloadSizeBytes is 0
-+    u32  spi_offest;          // The offset from TOUCH_DATA_WINDOW_OFFSET at which to write the Payload data. Maximum offset is 0x1EFFF.
-+    u8   reserved[40];       // Padding to extend header to full 64 bytes and allow for growth
-+} touch_feedback_hdr_t;
-+C_ASSERT(sizeof(touch_feedback_hdr_t) == 64);
-+
-+typedef struct touch_feedback_buffer
-+{
-+    touch_feedback_hdr_t  Header;
-+    u8               feedback_data[1];    // used to access the feedback data as an array and keep the compilers happy. Actual size of this array is Header.PayloadSizeBytes
-+} touch_feedback_buffer_t;
-+
-+
-+//
-+// This data structure describes the header prepended to all data
-+// written to the touch IC at the bulk data write (TOUCH_DATA_WINDOW_OFFSET + TOUCH_FEEDBACK_HDR.SpiOffest) address.
-+typedef enum touch_write_data_type
-+{
-+    TOUCH_WRITE_DATA_TYPE_FW_LOAD = 0,
-+    TOUCH_WRITE_DATA_TYPE_DATA_LOAD,
-+    TOUCH_WRITE_DATA_TYPE_FEEDBACK,
-+    TOUCH_WRITE_DATA_TYPE_SET_FEATURES,
-+    TOUCH_WRITE_DATA_TYPE_GET_FEATURES,
-+    TOUCH_WRITE_DATA_TYPE_OUTPUT_REPORT,
-+    TOUCH_WRITE_DATA_TYPE_NO_DATA_USE_DEFAULTS,
-+    TOUCH_WRITE_DATA_TYPE_MAX
-+} touch_write_data_type_t;
-+C_ASSERT(sizeof(touch_write_data_type_t) == 4);
-+
-+typedef struct touch_write_hdr
-+{
-+    u32  write_data_type;   // Use values from TOUCH_WRITE_DATA_TYPE
-+    u32  write_data_len;    // This field designates the amount of data to follow
-+} touch_write_hdr_t;
-+C_ASSERT(sizeof(touch_write_hdr_t) == 8);
-+
-+typedef struct touch_write_data
-+{
-+    touch_write_hdr_t header;
-+    u8           write_data[1];   // used to access the write data as an array and keep the compilers happy. Actual size of this array is Header.WriteDataLen
-+} touch_write_data_t;
-+
-+#pragma pack()
-+
-+#endif // _TOUCH_SENSOR_REGS_H
-diff --git a/drivers/misc/ipts/ipts-state.h b/drivers/misc/ipts/ipts-state.h
-new file mode 100644
-index 0000000..39a2eaf
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-state.h
-@@ -0,0 +1,29 @@
-+/*
-+ * Intel Precise Touch & Stylus state codes
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_STATE_H_
-+#define _IPTS_STATE_H_
-+
-+/* ipts driver states */
-+typedef enum ipts_state {
-+	IPTS_STA_NONE,
-+	IPTS_STA_INIT,
-+	IPTS_STA_RESOURCE_READY,
-+	IPTS_STA_HID_STARTED,
-+	IPTS_STA_RAW_DATA_STARTED,
-+	IPTS_STA_STOPPING
-+} ipts_state_t;
-+
-+#endif // _IPTS_STATE_H_
-diff --git a/drivers/misc/ipts/ipts.h b/drivers/misc/ipts/ipts.h
-new file mode 100644
-index 0000000..1fcd021
---- /dev/null
-+++ b/drivers/misc/ipts/ipts.h
-@@ -0,0 +1,200 @@
-+/*
-+ *
-+ * Intel Management Engine Interface (Intel MEI) Client Driver for IPTS
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_H_
-+#define _IPTS_H_
-+
-+#include <linux/types.h>
-+#include <linux/mei_cl_bus.h>
-+#include <linux/hid.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts-mei-msgs.h"
-+#include "ipts-state.h"
-+#include "ipts-binary-spec.h"
-+
-+//#define ENABLE_IPTS_DEBUG		/* enable IPTS debug */
-+
-+#ifdef ENABLE_IPTS_DEBUG
-+
-+#define ipts_info(ipts, format, arg...) do {\
-+	dev_info(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+#define ipts_dbg(ipts, format, arg...) do {\
-+	dev_info(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+//#define RUN_DBG_THREAD
-+
-+#else
-+
-+#define ipts_info(ipts, format, arg...) do {} while(0);
-+#define ipts_dbg(ipts, format, arg...) do {} while(0);
-+
-+#endif
-+
-+#define ipts_err(ipts, format, arg...) do {\
-+	dev_err(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+#define HID_PARALLEL_DATA_BUFFERS	TOUCH_SENSOR_MAX_DATA_BUFFERS
-+
-+#define IPTS_MAX_RETRY			3
-+
-+typedef struct ipts_buffer_info {
-+	char *addr;
-+	dma_addr_t dma_addr;
-+} ipts_buffer_info_t;
-+
-+typedef struct ipts_gfx_info {
-+	u64     gfx_handle;
-+	intel_ipts_ops_t ipts_ops;
-+} ipts_gfx_info_t;
-+
-+typedef struct ipts_resource {
-+	/* ME & Gfx resource */
-+	ipts_buffer_info_t touch_data_buffer_raw[HID_PARALLEL_DATA_BUFFERS];
-+	ipts_buffer_info_t touch_data_buffer_hid;
-+
-+	ipts_buffer_info_t feedback_buffer[HID_PARALLEL_DATA_BUFFERS];
-+
-+	ipts_buffer_info_t hid2me_buffer;
-+	u32 hid2me_buffer_size;
-+
-+	u8 wq_item_size;
-+	intel_ipts_wq_info_t wq_info;
-+
-+	/* ME2HID buffer */
-+	char *me2hid_buffer;
-+
-+	/* Gfx specific resource */
-+	ipts_buffer_info_t raw_data_mode_output_buffer
-+	    [HID_PARALLEL_DATA_BUFFERS][MAX_NUM_OUTPUT_BUFFERS];
-+
-+	int num_of_outputs;
-+
-+	bool default_resource_ready;
-+	bool raw_data_resource_ready;
-+} ipts_resource_t;
-+
-+typedef struct ipts_info {
-+	struct mei_cl_device *cldev;
-+	struct hid_device *hid;
-+
-+	struct work_struct init_work;
-+	struct work_struct raw_data_work;
-+	struct work_struct gfx_status_work;
-+
-+	struct task_struct *event_loop;
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+        struct dentry *dbgfs_dir;
-+#endif
-+
-+	ipts_state_t	state;
-+
-+	touch_sensor_mode_t	sensor_mode;
-+	touch_sensor_get_device_info_rsp_data_t device_info;
-+	ipts_resource_t	resource;
-+	u8		hid_input_report[HID_MAX_BUFFER_SIZE];
-+	int		num_of_parallel_data_buffers;
-+	bool		hid_desc_ready;
-+
-+	int current_buffer_index;
-+	int last_buffer_completed;
-+	int *last_submitted_id;
-+
-+	ipts_gfx_info_t gfx_info;
-+	u64		kernel_handle;
-+	int             gfx_status;
-+	bool		display_status;
-+
-+	bool		switch_sensor_mode;
-+	touch_sensor_mode_t	new_sensor_mode;
-+
-+	int		retry;
-+	bool		restart;
-+} ipts_info_t;
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+int ipts_dbgfs_register(ipts_info_t *ipts, const char *name);
-+void ipts_dbgfs_deregister(ipts_info_t *ipts);
-+#else
-+static int ipts_dbgfs_register(ipts_info_t *ipts, const char *name);
-+static void ipts_dbgfs_deregister(ipts_info_t *ipts);
-+#endif /* CONFIG_DEBUG_FS */
-+
-+/* inline functions */
-+static inline void ipts_set_state(ipts_info_t *ipts, ipts_state_t state)
-+{
-+	ipts->state = state;
-+}
-+
-+static inline ipts_state_t ipts_get_state(const ipts_info_t *ipts)
-+{
-+	return ipts->state;
-+}
-+
-+static inline bool ipts_is_default_resource_ready(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.default_resource_ready;
-+}
-+
-+static inline bool ipts_is_raw_data_resource_ready(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.raw_data_resource_ready;
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_feedback_buffer(ipts_info_t *ipts,
-+								int buffer_idx)
-+{
-+	return &ipts->resource.feedback_buffer[buffer_idx];
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_touch_data_buffer_hid(ipts_info_t *ipts)
-+{
-+	return &ipts->resource.touch_data_buffer_hid;
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_output_buffers_by_parallel_id(
-+							ipts_info_t *ipts,
-+                                                        int parallel_idx)
-+{
-+	return &ipts->resource.raw_data_mode_output_buffer[parallel_idx][0];
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_hid2me_buffer(ipts_info_t *ipts)
-+{
-+	return &ipts->resource.hid2me_buffer;
-+}
-+
-+static inline void ipts_set_wq_item_size(ipts_info_t *ipts, u8 size)
-+{
-+	ipts->resource.wq_item_size = size;
-+}
-+
-+static inline u8 ipts_get_wq_item_size(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.wq_item_size;
-+}
-+
-+static inline int ipts_get_num_of_parallel_buffers(const ipts_info_t *ipts)
-+{
-+	return ipts->num_of_parallel_data_buffers;
-+}
-+
-+#endif // _IPTS_H_
-diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
-index e4b10b2..883b185 100644
---- a/drivers/misc/mei/hw-me-regs.h
-+++ b/drivers/misc/mei/hw-me-regs.h
-@@ -119,6 +119,7 @@
- 
- #define MEI_DEV_ID_SPT        0x9D3A  /* Sunrise Point */
- #define MEI_DEV_ID_SPT_2      0x9D3B  /* Sunrise Point 2 */
-+#define MEI_DEV_ID_SPT_4      0x9D3E  /* Sunrise Point 4 */
- #define MEI_DEV_ID_SPT_H      0xA13A  /* Sunrise Point H */
- #define MEI_DEV_ID_SPT_H_2    0xA13B  /* Sunrise Point H 2 */
- 
-diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
-index c77e08c..5773a6c 100644
---- a/drivers/misc/mei/pci-me.c
-+++ b/drivers/misc/mei/pci-me.c
-@@ -86,6 +86,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
- 
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
-+	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_4, MEI_ME_PCH8_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)},
-diff --git a/include/linux/intel_ipts_if.h b/include/linux/intel_ipts_if.h
-new file mode 100644
-index 0000000..f329bbf
---- /dev/null
-+++ b/include/linux/intel_ipts_if.h
-@@ -0,0 +1,75 @@
-+/*
-+ *
-+ * GFX interface to support Intel Precise Touch & Stylus
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef INTEL_IPTS_IF_H
-+#define INTEL_IPTS_IF_H
-+
-+enum {
-+	IPTS_INTERFACE_V1 = 1,
-+};
-+
-+#define IPTS_BUF_FLAG_CONTIGUOUS	0x01
-+
-+#define IPTS_NOTIFY_STA_BACKLIGHT_OFF	0x00
-+#define IPTS_NOTIFY_STA_BACKLIGHT_ON	0x01
-+
-+typedef struct intel_ipts_mapbuffer {
-+	u32	size;
-+	u32	flags;
-+	void	*gfx_addr;
-+	void	*cpu_addr;
-+	u64	buf_handle;
-+	u64	phy_addr;
-+} intel_ipts_mapbuffer_t;
-+
-+typedef struct intel_ipts_wq_info {
-+	u64 db_addr;
-+	u64 db_phy_addr;
-+	u32 db_cookie_offset;
-+	u32 wq_size;
-+	u64 wq_addr;
-+	u64 wq_phy_addr;
-+	u64 wq_head_addr;	/* head of wq is managed by GPU */
-+	u64 wq_head_phy_addr;	/* head of wq is managed by GPU */
-+	u64 wq_tail_addr;	/* tail of wq is managed by CSME */
-+	u64 wq_tail_phy_addr;	/* tail of wq is managed by CSME */
-+} intel_ipts_wq_info_t;
-+
-+typedef struct intel_ipts_ops {
-+	int (*get_wq_info)(uint64_t gfx_handle, intel_ipts_wq_info_t *wq_info);
-+	int (*map_buffer)(uint64_t gfx_handle, intel_ipts_mapbuffer_t *mapbuffer);
-+	int (*unmap_buffer)(uint64_t gfx_handle, uint64_t buf_handle);
-+} intel_ipts_ops_t;
-+
-+typedef struct intel_ipts_callback {
-+        void (*workload_complete)(void *data);
-+        void (*notify_gfx_status)(u32 status, void *data);
-+} intel_ipts_callback_t;
-+
-+typedef struct intel_ipts_connect {
-+        intel_ipts_callback_t ipts_cb;	/* input : callback addresses */
-+	void *data;			/* input : callback data */
-+        u32 if_version;			/* input : interface version */
-+
-+        u32 gfx_version;		/* output : gfx version */
-+        u64 gfx_handle;			/* output : gfx handle */
-+	intel_ipts_ops_t ipts_ops;	/* output : gfx ops for IPTS */
-+} intel_ipts_connect_t;
-+
-+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect);
-+void intel_ipts_disconnect(uint64_t gfx_handle);
-+
-+#endif // INTEL_IPTS_IF_H

+ 0 - 119
patches/4.14/keyboards_and_covers.patch

@@ -1,119 +0,0 @@
-diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
-index ff539c0..d8cc7b2 100644
---- a/drivers/hid/hid-ids.h
-+++ b/drivers/hid/hid-ids.h
-@@ -760,11 +760,22 @@
- #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1 0x0732
- #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_600  0x0750
- #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500	0x076c
--#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD 0x00e3
--#define USB_DEVICE_ID_MS_SURFACE_PRO_2   0x0799
--#define USB_DEVICE_ID_MS_TOUCH_COVER_2   0x07a7
--#define USB_DEVICE_ID_MS_TYPE_COVER_2    0x07a9
--#define USB_DEVICE_ID_MS_POWER_COVER     0x07da
-+#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD	0x00e3
-+#define USB_DEVICE_ID_MS_SURFACE_PRO_2		0x0799
-+#define USB_DEVICE_ID_MS_TOUCH_COVER_2		0x07a7
-+#define USB_DEVICE_ID_MS_TYPE_COVER_2		0x07a9
-+#define USB_DEVICE_ID_MS_TYPE_COVER_3		0x07de
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3	0x07dc
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1	0x07de
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2	0x07e2
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP	0x07dd
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4	0x07e8
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1	0x07e4
-+#define USB_DEVICE_ID_MS_SURFACE_BOOK		0x07cd
-+#define USB_DEVICE_ID_MS_SURFACE_BOOK_2		0x0922
-+#define USB_DEVICE_ID_MS_SURFACE_LAPTOP		0xf001
-+#define HID_DEVICE_ID_MS_SURFACE_LAPTOP		0xf001
-+#define USB_DEVICE_ID_MS_POWER_COVER		0x07da
- 
- #define USB_VENDOR_ID_MOJO		0x8282
- #define USB_DEVICE_ID_RETRO_ADAPTER	0x3201
-diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
-index 9e8c4d2..bd1b82e 100644
---- a/drivers/hid/hid-multitouch.c
-+++ b/drivers/hid/hid-multitouch.c
-@@ -1594,6 +1594,58 @@ static const struct hid_device_id mt_devices[] = {
- 		HID_USB_DEVICE(USB_VENDOR_ID_LG,
- 			USB_DEVICE_ID_LG_MELFAS_MT) },
- 
-+	/* Microsoft Touch Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_TOUCH_COVER_2) },
-+
-+	/* Microsoft Type Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_2) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_3) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_4) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1) },
-+
-+	/* Microsoft Surface Book */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_SURFACE_BOOK) },
-+
-+	/* Microsoft Surface Book 2 */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_SURFACE_BOOK_2) },
-+
-+	/* Microsoft Surface Laptop */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
-+			USB_VENDOR_ID_MICROSOFT,
-+			HID_DEVICE_ID_MS_SURFACE_LAPTOP) },
-+
-+	/* Microsoft Power Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_POWER_COVER) },
-+
- 	/* MosArt panels */
- 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
- 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
-diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
-index f489a5c..ff88ddc 100644
---- a/drivers/hid/usbhid/hid-quirks.c
-+++ b/drivers/hid/usbhid/hid-quirks.c
-@@ -108,8 +108,18 @@ static const struct hid_blacklist {
- 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL },
- 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
- 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS },
--	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
- 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK_2, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_LAPTOP, HID_QUIRK_NO_INIT_REPORTS },
- 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
- 	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
- 	{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },

+ 0 - 20
patches/4.14/sdcard_reader.patch

@@ -1,20 +0,0 @@
-From a0d8418d70e4411b1dc7837f3368e9b7102703fa Mon Sep 17 00:00:00 2001
-From: Jake Day <jake@ninebysix.com>
-Date: Thu, 1 Feb 2018 19:25:58 -0500
-Subject: fix for surface sd card reader
-
-
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index 8f7d942..3365703 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -4047,7 +4047,8 @@ void usb_enable_lpm(struct usb_device *udev)
- 	if (!udev || !udev->parent ||
- 			udev->speed < USB_SPEED_SUPER ||
- 			!udev->lpm_capable ||
--			udev->state < USB_STATE_DEFAULT)
-+			udev->state < USB_STATE_DEFAULT ||
-+			!udev->bos || !udev->bos->ss_cap)
- 		return;
- 
- 	udev->lpm_disable_count--;

+ 0 - 510
patches/4.14/surfaceacpi.patch

@@ -1,510 +0,0 @@
-diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
-index 51ebc5a..244fa92 100644
---- a/drivers/platform/x86/Kconfig
-+++ b/drivers/platform/x86/Kconfig
-@@ -1155,6 +1155,15 @@ config SURFACE_3_BUTTON
- 	---help---
- 	  This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet.
- 
-+config ACPI_SURFACE
-+	tristate "Microsoft Surface Extras"
-+	depends on ACPI
-+	depends on ACPI_WMI
-+	depends on INPUT
-+	---help---
-+	  This driver adds support for access to certain system events
-+	  on Microsoft Surface devices.
-+
- config INTEL_PUNIT_IPC
- 	tristate "Intel P-Unit IPC Driver"
- 	---help---
-diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
-index 2ba6cb7..bcb0dd9 100644
---- a/drivers/platform/x86/Makefile
-+++ b/drivers/platform/x86/Makefile
-@@ -81,6 +81,7 @@ obj-$(CONFIG_INTEL_PMC_IPC)	+= intel_pmc_ipc.o
- obj-$(CONFIG_SILEAD_DMI)	+= silead_dmi.o
- obj-$(CONFIG_SURFACE_PRO3_BUTTON)	+= surfacepro3_button.o
- obj-$(CONFIG_SURFACE_3_BUTTON)	+= surface3_button.o
-+obj-$(CONFIG_ACPI_SURFACE)	+= surface_acpi.o
- obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
- obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU)	+= intel_bxtwc_tmu.o
- obj-$(CONFIG_INTEL_TELEMETRY)	+= intel_telemetry_core.o \
-diff --git a/drivers/platform/x86/surface_acpi.c b/drivers/platform/x86/surface_acpi.c
-new file mode 100644
-index 0000000..bee15e7
---- /dev/null
-+++ b/drivers/platform/x86/surface_acpi.c
-@@ -0,0 +1,472 @@
-+/*
-+ *  surface_acpi.c - Microsoft Surface ACPI Notify
-+ *
-+ *  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.
-+ *
-+ *  The full GNU General Public License is included in this distribution in
-+ *  the file called "COPYING".
-+ */
-+
-+#define SURFACE_ACPI_VERSION	"0.1"
-+#define SURFACE_GEN_VERSION		0x08
-+#define PROC_SURFACE			"surface"
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/acpi.h>
-+#include <linux/power_supply.h>
-+#include <linux/thermal.h>
-+#include <linux/dmi.h>
-+#include <linux/seq_file.h>
-+#include <acpi/acpi_bus.h>
-+#include <acpi/acpi_drivers.h>
-+
-+MODULE_AUTHOR("Jake Day");
-+MODULE_DESCRIPTION("Microsoft Surface ACPI Notify Driver");
-+MODULE_LICENSE("GPL");
-+
-+#define SUR_METHOD_DSM			"_DSM"
-+#define SUR_METHOD_REG			"_REG"
-+#define SUR_METHOD_STA			"_STA"
-+#define SUR_METHOD_INI			"_INI"
-+#define SUR_METHOD_CRS			"_CRS"
-+
-+#define SUR_QUERY_DEVICE		0x00
-+#define SUR_SET_DVER			0x01
-+#define SUR_GET_BOARD_REVID		0x02
-+#define SUR_BAT1_STATE_CHANGE	0x03
-+#define SUR_BAT1_INFO_CHANGE	0x04
-+#define SUR_PSU_STATE_CHANGE	0x05
-+#define SUR_PSU_INFO_CHANGE		0x06
-+#define SUR_BAT2_STATE_CHANGE	0x07
-+#define SUR_BAT2_INFO_CHANGE	0x08
-+#define SUR_SENSOR_TRIP_POINT	0x09
-+
-+#define REG_AVAILABLE			0x01
-+#define REG_INIT				0x09
-+
-+static char SURFACE_EVENT_GUID[] = "93b666c5-70c6-469f-a215-3d487c91ab3c";
-+static char SUR_SAN_RQST[] = "\\_SB._SAN.RQST";
-+static char SUR_SAN_RQSX[] = "\\_SB._SAN.RQSX";
-+
-+struct surface_acpi_dev {
-+	acpi_handle handle;
-+	acpi_handle rqst_handle;
-+	acpi_handle rqsx_handle;
-+
-+	struct acpi_device *san_dev;
-+	struct acpi_device *ssh_dev;
-+	struct acpi_device *bat1_dev;
-+	struct acpi_device *bat2_dev;
-+	struct acpi_device *psu_dev;
-+
-+	unsigned int bat1_attached:1;
-+	unsigned int bat2_attached:1;
-+	unsigned int psu_registered:1;
-+};
-+
-+static struct surface_acpi_dev *surface_acpi;
-+
-+static struct proc_dir_entry *surface_proc_dir;
-+
-+static acpi_status surface_acpi_check_status(struct acpi_device *dev)
-+{
-+	unsigned long long value;
-+	acpi_status status;
-+
-+	if (acpi_has_method(dev->handle, SUR_METHOD_STA)) {
-+		status = acpi_evaluate_integer(dev->handle,
-+				SUR_METHOD_STA, NULL, &value);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static acpi_status surface_acpi_san_reg(void)
-+{
-+	union acpi_object in_objs[2], out_objs[1];
-+	struct acpi_object_list params;
-+	struct acpi_buffer results;
-+	acpi_status status;
-+
-+	params.count = ARRAY_SIZE(in_objs);
-+	params.pointer = in_objs;
-+	in_objs[0].type = ACPI_TYPE_INTEGER;
-+	in_objs[0].integer.value = REG_INIT;
-+	in_objs[1].type = ACPI_TYPE_INTEGER;
-+	in_objs[1].integer.value = REG_AVAILABLE;
-+	results.length = sizeof(out_objs);
-+	results.pointer = out_objs;
-+
-+	if (acpi_has_method(surface_acpi->handle, SUR_METHOD_REG)) {
-+		status = acpi_evaluate_object(surface_acpi->handle,
-+				SUR_METHOD_REG, &params, &results);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static acpi_status surface_acpi_event_handler(u32 event)
-+{
-+	union acpi_object in_objs[4], out_objs[5];
-+	struct acpi_object_list params;
-+	struct acpi_buffer results;
-+	acpi_status status;
-+
-+	params.count = ARRAY_SIZE(in_objs);
-+	params.pointer = in_objs;
-+	in_objs[0].type = ACPI_TYPE_BUFFER;
-+	in_objs[0].buffer.length = sizeof(SURFACE_EVENT_GUID);
-+	in_objs[0].buffer.pointer = SURFACE_EVENT_GUID;
-+	in_objs[1].type = ACPI_TYPE_INTEGER;
-+	in_objs[1].integer.value = SUR_QUERY_DEVICE;
-+	in_objs[2].type = ACPI_TYPE_INTEGER;
-+	in_objs[2].integer.value = event;
-+	in_objs[3].type = ACPI_TYPE_PACKAGE;
-+	in_objs[3].package.count = 0;
-+	in_objs[3].package.elements = SURFACE_GEN_VERSION;
-+	results.length = sizeof(out_objs);
-+	results.pointer = out_objs;
-+
-+	if (acpi_has_method(surface_acpi->handle, SUR_METHOD_DSM)) {
-+		status = acpi_evaluate_object(surface_acpi->handle,
-+				SUR_METHOD_DSM, &params, &results);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static void surface_acpi_san_load(void)
-+{
-+	acpi_status ret;
-+
-+	ret = surface_acpi_event_handler(SUR_SET_DVER);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error setting Driver Version\n");
-+
-+	ret = surface_acpi_event_handler(SUR_SENSOR_TRIP_POINT);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error setting Sensor Trip Point\n");
-+
-+	ret = surface_acpi_event_handler(SUR_BAT1_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error attaching BAT1\n");
-+	else
-+		surface_acpi->bat1_attached = 1;
-+
-+	ret = surface_acpi_event_handler(SUR_BAT2_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error attaching BAT2\n");
-+	else
-+		surface_acpi->bat2_attached = 1;
-+
-+	ret = surface_acpi_event_handler(SUR_PSU_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error registering PSU\n");
-+	else
-+		surface_acpi->psu_registered = 1;
-+}
-+
-+static acpi_status surface_acpi_ssh_initialize(void)
-+{
-+	acpi_status status;
-+
-+	if (acpi_has_method(surface_acpi->ssh_dev->handle, SUR_METHOD_INI)) {
-+		status = acpi_evaluate_object(surface_acpi->ssh_dev->handle,
-+				SUR_METHOD_INI, NULL, NULL);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static int bat1_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "attached: %d\n", surface_acpi->bat1_attached);
-+	return 0;
-+}
-+
-+static int bat1_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, bat1_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations bat1_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= bat1_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int bat2_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "attached: %d\n", surface_acpi->bat2_attached);
-+	return 0;
-+}
-+
-+static int bat2_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, bat2_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations bat2_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= bat2_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int psu_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "registered: %d\n", surface_acpi->psu_registered);
-+	return 0;
-+}
-+
-+static int psu_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, psu_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations psu_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= psu_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int version_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "driver: %s\n", SURFACE_ACPI_VERSION);
-+	return 0;
-+}
-+
-+static int version_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, version_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations version_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= version_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static void create_surface_proc_entries(void)
-+{
-+	proc_create_data("BAT1", 0, surface_proc_dir,
-+			 &bat1_proc_fops, surface_acpi->bat1_attached);
-+	proc_create_data("BAT2", 0, surface_proc_dir,
-+			 &bat2_proc_fops, surface_acpi->bat2_attached);
-+	proc_create_data("ADP1", 0, surface_proc_dir,
-+			 &psu_proc_fops, surface_acpi->psu_registered);
-+	proc_create_data("version", 0, surface_proc_dir,
-+			 &version_proc_fops, SURFACE_ACPI_VERSION);
-+}
-+
-+static void remove_surface_proc_entries(void)
-+{
-+	remove_proc_entry("BAT1", surface_proc_dir);
-+	remove_proc_entry("BAT2", surface_proc_dir);
-+	remove_proc_entry("ADP1", surface_proc_dir);
-+	remove_proc_entry("version", surface_proc_dir);
-+}
-+
-+static void surface_acpi_notify(struct acpi_device *dev, u32 event)
-+{
-+	pr_info("surface_acpi: Event received %x\n", event);
-+}
-+
-+static void surface_acpi_register_rqst_handler(void)
-+{
-+	acpi_status status;
-+
-+	status = acpi_get_handle(NULL, SUR_SAN_RQST, &surface_acpi->rqst_handle);
-+	if (ACPI_FAILURE(status)) {
-+		pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+	}
-+}
-+
-+static void surface_acpi_register_rqsx_handler(void)
-+{
-+	acpi_status status;
-+
-+	status = acpi_get_handle(NULL, SUR_SAN_RQSX, &surface_acpi->rqsx_handle);
-+	if (ACPI_FAILURE(status)) {
-+		pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+	}
-+}
-+
-+static acpi_status surface_acpi_walk_callback(acpi_handle handle, u32 level,
-+						void *context, void **return_value)
-+{
-+	struct acpi_device_info *info;
-+
-+	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
-+		pr_warn("method: name: %4.4s, args %X\n",
-+			(char *)&info->name, info->param_count);
-+
-+		kfree(info);
-+	}
-+
-+	return AE_OK;
-+}
-+
-+static void surface_acpi_walk_namespace(struct acpi_device *dev)
-+{
-+	acpi_status status;
-+
-+	status = acpi_walk_namespace(ACPI_TYPE_METHOD,
-+			dev->handle, 1, surface_acpi_walk_callback,
-+			NULL, NULL, NULL);
-+	if (ACPI_FAILURE(status))
-+		pr_warn("surface_acpi: Unable to walk acpi resources\n");
-+}
-+
-+static int surface_acpi_add(struct acpi_device *dev)
-+{
-+	if (!surface_acpi)
-+	{
-+		surface_acpi = kzalloc(sizeof(*surface_acpi), GFP_KERNEL);
-+		if (!surface_acpi)
-+			return AE_NO_MEMORY;
-+	}
-+
-+	if (acpi_has_method(dev->handle, SUR_METHOD_DSM))
-+	{
-+		pr_info("surface_acpi: Attaching device MSHW0091\n");
-+
-+		surface_acpi->san_dev = dev;
-+		surface_acpi->handle = dev->handle;
-+
-+		surface_acpi_walk_namespace(surface_acpi->san_dev);
-+		surface_acpi_check_status(surface_acpi->san_dev);
-+
-+		surface_acpi_register_rqst_handler();
-+		surface_acpi_register_rqsx_handler();
-+
-+		surface_acpi_san_reg();
-+		surface_acpi_san_load();
-+
-+		create_surface_proc_entries();
-+	}
-+	else
-+	{
-+		pr_info("surface_acpi: Attaching device MSHW0084\n");
-+
-+		surface_acpi->ssh_dev = dev;
-+
-+		surface_acpi_walk_namespace(surface_acpi->ssh_dev);
-+		surface_acpi_check_status(surface_acpi->ssh_dev);
-+
-+		surface_acpi_ssh_initialize();
-+		//surface_acpi_ssh_load();
-+	}
-+
-+	return AE_OK;
-+}
-+
-+static int surface_acpi_remove(struct acpi_device *dev)
-+{
-+	remove_surface_proc_entries();
-+
-+	return AE_OK;
-+}
-+
-+static const struct acpi_device_id surface_device_ids[] = {
-+	{"MSHW0091", 0},
-+	{"MSHW0084", 0},
-+	{"", 0},
-+};
-+MODULE_DEVICE_TABLE(acpi, surface_device_ids);
-+
-+static struct acpi_driver surface_acpi_driver = {
-+	.name	= "surface_acpi",
-+	.owner	= THIS_MODULE,
-+	.ids	= surface_device_ids,
-+	.flags	= ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-+	.ops	= {
-+		.add	= surface_acpi_add,
-+		.remove = surface_acpi_remove,
-+		.notify = surface_acpi_notify,
-+	},
-+};
-+
-+static int __init surface_acpi_init(void)
-+{
-+	int ret;
-+
-+	pr_info("surface_acpi: Microsoft Surface ACPI Notify version %s\n",
-+	       SURFACE_ACPI_VERSION);
-+
-+	surface_proc_dir = proc_mkdir(PROC_SURFACE, acpi_root_dir);
-+	if (!surface_proc_dir) {
-+		pr_err("surface_acpi: Unable to create proc dir " PROC_SURFACE "\n");
-+		return -ENODEV;
-+	}
-+
-+	ret = acpi_bus_register_driver(&surface_acpi_driver);
-+	if (ret) {
-+		pr_err("surface_acpi: Failed to register ACPI driver: %d\n", ret);
-+		remove_proc_entry(PROC_SURFACE, acpi_root_dir);
-+	}
-+
-+	return ret;
-+}
-+
-+static void __exit surface_acpi_exit(void)
-+{
-+	acpi_bus_unregister_driver(&surface_acpi_driver);
-+	if (surface_proc_dir)
-+		remove_proc_entry(PROC_SURFACE, acpi_root_dir);
-+}
-+
-+module_init(surface_acpi_init);
-+module_exit(surface_acpi_exit);

+ 0 - 36
patches/4.14/surfacedock.patch

@@ -1,36 +0,0 @@
-From 952348ceeaf9c900407762d97b2e024272f01191 Mon Sep 17 00:00:00 2001
-From: Jake Day <jake@ninebysix.com>
-Date: Thu, 1 Feb 2018 19:25:44 -0500
-Subject: support for surface dock
-
-
-diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
-index 05dca3e..59c2fcc 100644
---- a/drivers/net/usb/cdc_ether.c
-+++ b/drivers/net/usb/cdc_ether.c
-@@ -807,13 +807,6 @@ static const struct usb_device_id	products[] = {
- 	.driver_info = 0,
- },
- 
--/* Microsoft Surface 3 dock (based on Realtek RTL8153) */
--{
--	USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM,
--			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
--	.driver_info = 0,
--},
--
- 	/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
- {
- 	USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
-diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
-index d51d9ab..b94ebe9 100644
---- a/drivers/net/usb/r8152.c
-+++ b/drivers/net/usb/r8152.c
-@@ -5310,7 +5310,6 @@ static const struct usb_device_id rtl8152_table[] = {
- 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)},
--	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x304f)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3062)},

+ 0 - 281
patches/4.14/wifi.patch

@@ -1,281 +0,0 @@
-diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
-index 042a1d0..fc9041f 100644
---- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
-+++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
-@@ -200,8 +200,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
- 
- 	do {
- 		/* Check if AMSDU can accommodate this MSDU */
--		if ((skb_aggr->len + skb_src->len + LLC_SNAP_LEN) >
--		    adapter->tx_buf_size)
-+		if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN))
- 			break;
- 
- 		skb_src = skb_dequeue(&pra_list->skb_head);
-diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
-index 68aa0c7..1a883cb 100644
---- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
-+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
-@@ -416,6 +416,9 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
- 
- 	ps_mode = enabled;
- 
-+	mwifiex_dbg(priv->adapter, ERROR, "overriding ps_mode to false\n");
-+	ps_mode = 0;
-+
- 	return mwifiex_drv_set_power(priv, &ps_mode);
- }
- 
-diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
-index 0edc5d6..c0c9c70 100644
---- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
-+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
-@@ -998,6 +998,7 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
- 		if (cmd_node->wait_q_enabled) {
- 			adapter->cmd_wait_q.status = -ETIMEDOUT;
- 			mwifiex_cancel_pending_ioctl(adapter);
-+			adapter->cmd_sent = false;
- 		}
- 	}
- 	if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
-diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
-index e11919d..7f41cf8 100644
---- a/drivers/net/wireless/marvell/mwifiex/init.c
-+++ b/drivers/net/wireless/marvell/mwifiex/init.c
-@@ -60,7 +60,7 @@ static void wakeup_timer_fn(unsigned long data)
- 	adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
- 	mwifiex_cancel_all_pending_cmd(adapter);
- 
--	if (adapter->if_ops.card_reset && !adapter->hs_activated)
-+	if (adapter->if_ops.card_reset)
- 		adapter->if_ops.card_reset(adapter);
- }
- 
-diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
-index ee40b73..c7008bb 100644
---- a/drivers/net/wireless/marvell/mwifiex/main.c
-+++ b/drivers/net/wireless/marvell/mwifiex/main.c
-@@ -164,6 +164,7 @@ void mwifiex_queue_main_work(struct mwifiex_adapter *adapter)
- 	spin_lock_irqsave(&adapter->main_proc_lock, flags);
- 	if (adapter->mwifiex_processing) {
- 		adapter->more_task_flag = true;
-+		adapter->more_rx_task_flag = true;
- 		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
- 	} else {
- 		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-@@ -172,18 +173,20 @@ void mwifiex_queue_main_work(struct mwifiex_adapter *adapter)
- }
- EXPORT_SYMBOL_GPL(mwifiex_queue_main_work);
- 
--static void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter)
-+void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter)
- {
- 	unsigned long flags;
- 
- 	spin_lock_irqsave(&adapter->rx_proc_lock, flags);
- 	if (adapter->rx_processing) {
-+		adapter->more_rx_task_flag = true;
- 		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 	} else {
- 		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 		queue_work(adapter->rx_workqueue, &adapter->rx_work);
- 	}
- }
-+EXPORT_SYMBOL_GPL(mwifiex_queue_rx_work);
- 
- static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
- {
-@@ -193,13 +196,14 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
- 
- 	spin_lock_irqsave(&adapter->rx_proc_lock, flags);
- 	if (adapter->rx_processing || adapter->rx_locked) {
-+		adapter->more_rx_task_flag = true;
- 		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 		goto exit_rx_proc;
- 	} else {
- 		adapter->rx_processing = true;
- 		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 	}
--
-+rx_process_start:
- 	/* Check for Rx data */
- 	while ((skb = skb_dequeue(&adapter->rx_data_q))) {
- 		atomic_dec(&adapter->rx_pending);
-@@ -221,6 +225,11 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
- 		}
- 	}
- 	spin_lock_irqsave(&adapter->rx_proc_lock, flags);
-+	if (adapter->more_rx_task_flag) {
-+		adapter->more_rx_task_flag = false;
-+		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-+		goto rx_process_start;
-+	}
- 	adapter->rx_processing = false;
- 	spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 
-@@ -284,10 +293,10 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
- 				mwifiex_process_hs_config(adapter);
- 			if (adapter->if_ops.process_int_status)
- 				adapter->if_ops.process_int_status(adapter);
-+			if (adapter->rx_work_enabled && adapter->data_received)
-+				mwifiex_queue_rx_work(adapter);
- 		}
- 
--		if (adapter->rx_work_enabled && adapter->data_received)
--			mwifiex_queue_rx_work(adapter);
- 
- 		/* Need to wake up the card ? */
- 		if ((adapter->ps_state == PS_STATE_SLEEP) &&
-diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
-index a76bd79..b3bfb7d 100644
---- a/drivers/net/wireless/marvell/mwifiex/main.h
-+++ b/drivers/net/wireless/marvell/mwifiex/main.h
-@@ -890,6 +890,7 @@ struct mwifiex_adapter {
- 	spinlock_t main_proc_lock;
- 	u32 mwifiex_processing;
- 	u8 more_task_flag;
-+	u8 more_rx_task_flag;
- 	u16 tx_buf_size;
- 	u16 curr_tx_buf_size;
- 	/* sdio single port rx aggregation capability */
-@@ -1662,6 +1663,7 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
- 				int drv_info_size);
- void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
- void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
-+void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter);
- int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action,
- 			      int cmd_type,
- 			      struct mwifiex_ds_wakeup_reason *wakeup_reason);
-diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
-index 9511f5f..4a4737c 100644
---- a/drivers/net/wireless/marvell/mwifiex/pcie.c
-+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
-@@ -1729,6 +1729,16 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
- 	}
- 
- 	rx_len = get_unaligned_le16(skb->data);
-+
-+
-+	if (rx_len == 0) {
-+		mwifiex_dbg(adapter, ERROR,
-+				    "0 byte cmdrsp\n");
-+		mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
-+					   PCI_DMA_FROMDEVICE);
-+		return 0;
-+	}
-+
- 	skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
- 	skb_trim(skb, rx_len);
- 
-diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
-index fb09014..5b8329e 100644
---- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
-+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
-@@ -2313,7 +2313,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
- 		if (ret)
- 			return -1;
- 
--		if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
-+		if (0 && priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
- 			/* Enable IEEE PS by default */
- 			priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
- 			ret = mwifiex_send_cmd(priv,
-@@ -2336,8 +2336,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
- 				return -1;
- 		}
- 
--		mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
--				 HostCmd_ACT_GEN_GET, 0, NULL, true);
-+		//mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
-+		//		 HostCmd_ACT_GEN_GET, 0, NULL, true);
- 	}
- 
- 	/* get tx rate */
-@@ -2369,7 +2369,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
- 	if (ret)
- 		return -1;
- 
--	if (!disable_auto_ds && first_sta &&
-+	if (0 && !disable_auto_ds && first_sta &&
- 	    priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
- 		/* Enable auto deep sleep */
- 		auto_ds.auto_ds = DEEP_SLEEP_ON;
-diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
-index 0fba5b1..4e1687f 100644
---- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
-+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
-@@ -48,9 +48,14 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
- 	struct host_cmd_ds_802_11_ps_mode_enh *pm;
- 	unsigned long flags;
- 
--	mwifiex_dbg(adapter, ERROR,
--		    "CMD_RESP: cmd %#x error, result=%#x\n",
--		    resp->command, resp->result);
-+	if (resp->command == 271 && resp->result == 2){
-+		// ignore this command as the firmware does not support it
-+	}
-+	else {
-+		mwifiex_dbg(adapter, ERROR,
-+				"CMD_RESP: cmd %#x error, result=%#x\n",
-+				resp->command, resp->result);
-+	}
- 
- 	if (adapter->curr_cmd->wait_q_enabled)
- 		adapter->cmd_wait_q.status = -1;
-diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
-index f4f2b9b..bbfa9f3 100644
---- a/drivers/net/wireless/marvell/mwifiex/usb.c
-+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
-@@ -144,6 +144,8 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
- 		skb_queue_tail(&adapter->rx_data_q, skb);
- 		adapter->data_received = true;
- 		atomic_inc(&adapter->rx_pending);
-+		if (adapter->rx_work_enabled)
-+			mwifiex_queue_rx_work(adapter);
- 		break;
- 	default:
- 		mwifiex_dbg(adapter, ERROR,
-diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
-index 68c389c..74efec3 100644
---- a/drivers/pci/pcie/portdrv_pci.c
-+++ b/drivers/pci/pcie/portdrv_pci.c
-@@ -150,6 +150,11 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
- 
- 	pci_save_state(dev);
- 
-+	/*
-+	 * D3cold disabled by default
-+	 */
-+	dev->d3cold_allowed = false;
-+
- 	if (pci_bridge_d3_possible(dev)) {
- 		/*
- 		 * Keep the port resumed 100ms to make sure things like
-diff --git a/net/wireless/sme.c b/net/wireless/sme.c
-index 3dd05a0..ab32ef1 100644
---- a/net/wireless/sme.c
-+++ b/net/wireless/sme.c
-@@ -690,6 +690,11 @@ void __cfg80211_connect_result(struct net_device *dev,
- 		return;
- 	}
- 
-+	if (WARN_ON(!wdev->ssid_len)) {
-+		cfg80211_put_bss(wdev->wiphy, cr->bss);
-+		return;
-+	}
-+
- 	nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, cr,
- 				    GFP_KERNEL);
- 
-@@ -1062,7 +1067,7 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
- 	/*
- 	 * If we have an ssid_len, we're trying to connect or are
- 	 * already connected, so reject a new SSID unless it's the
--	 * same (which is the case for re-association.)
-+	 * same (which is the case for Re-Association.
- 	 */
- 	if (wdev->ssid_len &&
- 	    (wdev->ssid_len != connect->ssid_len ||
-diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl
-old mode 100755
-new mode 100644

+ 0 - 263
patches/4.15/acpica.patch

@@ -1,263 +0,0 @@
-diff --git a/drivers/acpi/acpica/dbdisply.c b/drivers/acpi/acpica/dbdisply.c
-index 5a606ea..7b5eb33 100644
---- a/drivers/acpi/acpica/dbdisply.c
-+++ b/drivers/acpi/acpica/dbdisply.c
-@@ -642,9 +642,8 @@ void acpi_db_display_object_type(char *object_arg)
- 		return;
- 	}
- 
--	acpi_os_printf("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n",
--		       ACPI_FORMAT_UINT64(info->address),
--		       info->current_status, info->flags);
-+	acpi_os_printf("ADR: %8.8X%8.8X, Flags: %X\n",
-+		       ACPI_FORMAT_UINT64(info->address), info->flags);
- 
- 	acpi_os_printf("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n",
- 		       info->highest_dstates[0], info->highest_dstates[1],
-diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c
-index d3b6b31..37b0b4c 100644
---- a/drivers/acpi/acpica/evevent.c
-+++ b/drivers/acpi/acpica/evevent.c
-@@ -204,6 +204,7 @@ u32 acpi_ev_fixed_event_detect(void)
- 	u32 fixed_status;
- 	u32 fixed_enable;
- 	u32 i;
-+	acpi_status status;
- 
- 	ACPI_FUNCTION_NAME(ev_fixed_event_detect);
- 
-@@ -211,8 +212,12 @@ u32 acpi_ev_fixed_event_detect(void)
- 	 * Read the fixed feature status and enable registers, as all the cases
- 	 * depend on their values. Ignore errors here.
- 	 */
--	(void)acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
--	(void)acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
-+	status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
-+	status |=
-+	    acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
-+	if (ACPI_FAILURE(status)) {
-+		return (int_status);
-+	}
- 
- 	ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
- 			  "Fixed Event Block: Enable %08X Status %08X\n",
-diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c
-index a8191d2..2ad13d8 100644
---- a/drivers/acpi/acpica/exdebug.c
-+++ b/drivers/acpi/acpica/exdebug.c
-@@ -88,14 +88,13 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
- 		return_VOID;
- 	}
- 
--	/* Null string or newline -- don't emit the line header */
-+	/* Newline -- don't emit the line header */
- 
- 	if (source_desc &&
- 	    (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) &&
- 	    (source_desc->common.type == ACPI_TYPE_STRING)) {
--		if ((source_desc->string.length == 0) ||
--		    ((source_desc->string.length == 1) &&
--		     (*source_desc->string.pointer == '\n'))) {
-+		if ((source_desc->string.length == 1) &&
-+		    (*source_desc->string.pointer == '\n')) {
- 			acpi_os_printf("\n");
- 			return_VOID;
- 		}
-diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c
-index 5026594..573a5f3 100644
---- a/drivers/acpi/acpica/nsdumpdv.c
-+++ b/drivers/acpi/acpica/nsdumpdv.c
-@@ -88,10 +88,9 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
- 		}
- 
- 		ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES,
--				      "    HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
-+				      "    HID: %s, ADR: %8.8X%8.8X\n",
- 				      info->hardware_id.value,
--				      ACPI_FORMAT_UINT64(info->address),
--				      info->current_status));
-+				      ACPI_FORMAT_UINT64(info->address));
- 		ACPI_FREE(info);
- 	}
- 
-diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
-index 1069662..0a9c600 100644
---- a/drivers/acpi/acpica/nsxfname.c
-+++ b/drivers/acpi/acpica/nsxfname.c
-@@ -241,7 +241,7 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
-  *              namespace node and possibly by running several standard
-  *              control methods (Such as in the case of a device.)
-  *
-- * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
-+ * For Device and Processor objects, run the Device _HID, _UID, _CID,
-  * _CLS, _ADR, _sx_w, and _sx_d methods.
-  *
-  * Note: Allocates the return buffer, must be freed by the caller.
-@@ -250,8 +250,9 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
-  * discovery namespace traversal. Therefore, no complex methods can be
-  * executed, especially those that access operation regions. Therefore, do
-  * not add any additional methods that could cause problems in this area.
-- * this was the fate of the _SUB method which was found to cause such
-- * problems and was removed (11/2015).
-+ * Because of this reason support for the following methods has been removed:
-+ * 1) _SUB method was removed (11/2015)
-+ * 2) _STA method was removed (02/2018)
-  *
-  ******************************************************************************/
- 
-@@ -374,20 +375,8 @@ acpi_get_object_info(acpi_handle handle,
- 		 * Notes: none of these methods are required, so they may or may
- 		 * not be present for this device. The Info->Valid bitfield is used
- 		 * to indicate which methods were found and run successfully.
--		 *
--		 * For _STA, if the method does not exist, then (as per the ACPI
--		 * specification), the returned current_status flags will indicate
--		 * that the device is present/functional/enabled. Otherwise, the
--		 * current_status flags reflect the value returned from _STA.
- 		 */
- 
--		/* Execute the Device._STA method */
--
--		status = acpi_ut_execute_STA(node, &info->current_status);
--		if (ACPI_SUCCESS(status)) {
--			valid |= ACPI_VALID_STA;
--		}
--
- 		/* Execute the Device._ADR method */
- 
- 		status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
-diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
-index eb9dfac..11ce4e5 100644
---- a/drivers/acpi/acpica/psargs.c
-+++ b/drivers/acpi/acpica/psargs.c
-@@ -890,6 +890,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
- 						      ACPI_POSSIBLE_METHOD_CALL);
- 
- 			if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) {
-+
-+				/* Free method call op and corresponding namestring sub-ob */
-+
-+				acpi_ps_free_op(arg->common.value.arg);
- 				acpi_ps_free_op(arg);
- 				arg = NULL;
- 				walk_state->arg_count = 1;
-diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
-index b6d58cc..5c00e5e 100644
---- a/drivers/acpi/bus.c
-+++ b/drivers/acpi/bus.c
-@@ -135,6 +135,7 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle,
- 	}
- 	return status;
- }
-+EXPORT_SYMBOL_GPL(acpi_bus_get_status_handle);
- 
- int acpi_bus_get_status(struct acpi_device *device)
- {
-@@ -146,6 +147,12 @@ int acpi_bus_get_status(struct acpi_device *device)
- 		return 0;
- 	}
- 
-+	/* Battery devices must have their deps met before calling _STA */
-+	if (acpi_device_is_battery(device) && device->dep_unmet) {
-+		acpi_set_device_status(device, 0);
-+		return 0;
-+	}
-+
- 	status = acpi_bus_get_status_handle(device->handle, &sta);
- 	if (ACPI_FAILURE(status))
- 		return -ENODEV;
-diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
-index b0fe527..4c1b90e 100644
---- a/drivers/acpi/scan.c
-+++ b/drivers/acpi/scan.c
-@@ -1565,6 +1565,8 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
- 	device_initialize(&device->dev);
- 	dev_set_uevent_suppress(&device->dev, true);
- 	acpi_init_coherency(device);
-+	/* Assume there are unmet deps until acpi_device_dep_initialize runs */
-+	device->dep_unmet = 1;
- }
- 
- void acpi_device_add_finalize(struct acpi_device *device)
-@@ -1588,6 +1590,14 @@ static int acpi_add_single_object(struct acpi_device **child,
- 	}
- 
- 	acpi_init_device_object(device, handle, type, sta);
-+	/*
-+	 * For ACPI_BUS_TYPE_DEVICE getting the status is delayed till here so
-+	 * that we can call acpi_bus_get_status and use its quirk handling.
-+	 * Note this must be done before the get power-/wakeup_dev-flags calls.
-+	 */
-+	if (type == ACPI_BUS_TYPE_DEVICE)
-+		acpi_bus_get_status(device);
-+
- 	acpi_bus_get_power_flags(device);
- 	acpi_bus_get_wakeup_device_flags(device);
- 
-@@ -1660,9 +1670,11 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
- 			return -ENODEV;
- 
- 		*type = ACPI_BUS_TYPE_DEVICE;
--		status = acpi_bus_get_status_handle(handle, sta);
--		if (ACPI_FAILURE(status))
--			*sta = 0;
-+		/*
-+		 * acpi_add_single_object updates this once we've an acpi_device
-+		 * so that acpi_bus_get_status' quirk handling can be used.
-+		 */
-+		*sta = 0;
- 		break;
- 	case ACPI_TYPE_PROCESSOR:
- 		*type = ACPI_BUS_TYPE_PROCESSOR;
-@@ -1760,6 +1772,8 @@ static void acpi_device_dep_initialize(struct acpi_device *adev)
- 	acpi_status status;
- 	int i;
- 
-+	adev->dep_unmet = 0;
-+
- 	if (!acpi_has_method(adev->handle, "_DEP"))
- 		return;
- 
-diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
-index 984c7e8..8472c4a 100644
---- a/drivers/pci/hotplug/acpiphp_ibm.c
-+++ b/drivers/pci/hotplug/acpiphp_ibm.c
-@@ -399,6 +399,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
- 		u32 lvl, void *context, void **rv)
- {
- 	acpi_handle *phandle = (acpi_handle *)context;
-+	unsigned long long current_status = 0;
- 	acpi_status status;
- 	struct acpi_device_info *info;
- 	int retval = 0;
-@@ -410,7 +411,9 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
- 		return retval;
- 	}
- 
--	if (info->current_status && (info->valid & ACPI_VALID_HID) &&
-+	acpi_bus_get_status_handle(handle, &current_status);
-+
-+	if (current_status && (info->valid & ACPI_VALID_HID) &&
- 			(!strcmp(info->hardware_id.string, IBM_HARDWARE_ID1) ||
- 			 !strcmp(info->hardware_id.string, IBM_HARDWARE_ID2))) {
- 		pr_debug("found hardware: %s, handle: %p\n",
-diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
-index 4f077ed..220ef86 100644
---- a/include/acpi/actypes.h
-+++ b/include/acpi/actypes.h
-@@ -1191,7 +1191,6 @@ struct acpi_device_info {
- 	u8 flags;		/* Miscellaneous info */
- 	u8 highest_dstates[4];	/* _sx_d values: 0xFF indicates not valid */
- 	u8 lowest_dstates[5];	/* _sx_w values: 0xFF indicates not valid */
--	u32 current_status;	/* _STA value */
- 	u64 address;	/* _ADR value */
- 	struct acpi_pnp_device_id hardware_id;	/* _HID value */
- 	struct acpi_pnp_device_id unique_id;	/* _UID value */
-@@ -1205,7 +1204,6 @@ struct acpi_device_info {
- 
- /* Flags for Valid field above (acpi_get_object_info) */
- 
--#define ACPI_VALID_STA                  0x0001
- #define ACPI_VALID_ADR                  0x0002
- #define ACPI_VALID_HID                  0x0004
- #define ACPI_VALID_UID                  0x0008

+ 0 - 150
patches/4.15/cameras.patch

@@ -1,150 +0,0 @@
-From 5549632053d4ae06867f383694553f7af27e40c9 Mon Sep 17 00:00:00 2001
-From: Jake Day <jake@ninebysix.com>
-Date: Fri, 2 Feb 2018 11:07:32 -0500
-Subject: initial support for surface cameras
-
-
-diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
-index 28b91b7..0e5989c 100644
---- a/drivers/media/usb/uvc/uvc_driver.c
-+++ b/drivers/media/usb/uvc/uvc_driver.c
-@@ -2277,6 +2277,46 @@ MODULE_PARM_DESC(timeout, "Streaming control requests timeout");
-  * though they are compliant.
-  */
- static const struct usb_device_id uvc_ids[] = {
-+	/* Microsoft Surface Pro 3 Front */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x07be,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Pro 3 Rear */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x07bf,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Pro 4 Cam */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x090c,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Book Cam 1 */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x090b,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Book Cam 2 */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x091a,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
- 	/* LogiLink Wireless Webcam */
- 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
- 				| USB_DEVICE_ID_MATCH_INT_INFO,
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/Kconfig b/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-index 3f527f2..b882948 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-@@ -1,7 +1,7 @@
- config VIDEO_ATOMISP_OV5693
-        tristate "Omnivision ov5693 sensor support"
- 	depends on ACPI
--       depends on I2C && VIDEO_V4L2
-+	   depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
-        ---help---
- 	 This is a Video4Linux2 sensor-level driver for the Micron
- 	 ov5693 5 Mpixel camera.
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
-index 3e7c385..9b1fc1c 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
-@@ -1320,11 +1320,15 @@ static int power_ctrl(struct v4l2_subdev *sd, bool flag)
- static int gpio_ctrl(struct v4l2_subdev *sd, bool flag)
- {
- 	struct ov5693_device *dev = to_ov5693_sensor(sd);
-+	int ret = 0;
- 
- 	if (!dev || !dev->platform_data)
- 		return -ENODEV;
- 
--	return dev->platform_data->gpio0_ctrl(sd, flag);
-+	if (dev->platform_data->gpio0_ctrl)
-+		ret = dev->platform_data->gpio0_ctrl(sd, flag);
-+
-+	return ret;
- }
- 
- static int __power_up(struct v4l2_subdev *sd)
-@@ -1689,7 +1693,7 @@ static int ov5693_detect(struct i2c_client *client)
- 					OV5693_SC_CMMN_CHIP_ID_L, &low);
- 	id = ((((u16) high) << 8) | (u16) low);
- 
--	if (id != OV5693_ID) {
-+	if (id != OV5690_ID && id != OV5693_ID) {
- 		dev_err(&client->dev, "sensor ID error 0x%x\n", id);
- 		return -ENODEV;
- 	}
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-index 2ea6380..2168daa 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-@@ -29,7 +29,7 @@
- #include <linux/v4l2-mediabus.h>
- #include <media/media-entity.h>
- 
--#include "../../include/linux/atomisp_platform.h"
-+#include "../../include/linux/atomisp_gmin_platform.h"
- 
- #define OV5693_POWER_UP_RETRY_NUM 5
- 
-@@ -72,7 +72,8 @@
-  * bits 7-0: min f-number denominator
-  */
- #define OV5693_F_NUMBER_RANGE 0x180a180a
--#define OV5693_ID	0x5690
-+#define OV5690_ID	0x5690
-+#define OV5693_ID	0x5693
- 
- #define OV5693_FINE_INTG_TIME_MIN 0
- #define OV5693_FINE_INTG_TIME_MAX_MARGIN 0
-diff --git a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-index bf9f34b..6797ba1 100644
---- a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-+++ b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-@@ -251,11 +251,13 @@ static const struct gmin_cfg_var ecs7_vars[] = {
- 	{"INT33BE:00_CsiFmt", "13"},
- 	{"INT33BE:00_CsiBayer", "2"},
- 	{"INT33BE:00_CamClk", "0"},
-+	{"INT33BE:00_ClkSrc", "1"},
- 	{"INT33F0:00_CsiPort", "0"},
- 	{"INT33F0:00_CsiLanes", "1"},
- 	{"INT33F0:00_CsiFmt", "13"},
- 	{"INT33F0:00_CsiBayer", "0"},
- 	{"INT33F0:00_CamClk", "1"},
-+	{"INT33BE:00_I2CAddr", "-1"},
- 	{"gmin_V2P8GPIO", "402"},
- 	{},
- };
-@@ -280,6 +282,8 @@ static const struct {
- 	{ "MRD7", mrd7_vars },
- 	{ "ST70408", ecs7_vars },
- 	{ "VTA0803", i8880_vars },
-+	{ "Surface Book" , ecs7_vars } ,
-+	{ "Surface Pro 4" , ecs7_vars } ,
- };
- 
- 

+ 0 - 6088
patches/4.15/ipts.patch

@@ -1,6088 +0,0 @@
-diff --git a/Documentation/devicetree/bindings/input/hid-over-i2c.txt b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
-index 28e8bd8..4d3da9d 100644
---- a/Documentation/devicetree/bindings/input/hid-over-i2c.txt
-+++ b/Documentation/devicetree/bindings/input/hid-over-i2c.txt
-@@ -31,7 +31,7 @@ device-specific compatible properties, which should be used in addition to the
- 
- - vdd-supply: phandle of the regulator that provides the supply voltage.
- - post-power-on-delay-ms: time required by the device after enabling its regulators
--  before it is ready for communication. Must be used with 'vdd-supply'.
-+  or powering it on, before it is ready for communication.
- 
- Example:
- 
-diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
-index 2acf3b3..ab69d8d 100644
---- a/drivers/gpu/drm/i915/Makefile
-+++ b/drivers/gpu/drm/i915/Makefile
-@@ -123,6 +123,9 @@ i915-y += dvo_ch7017.o \
- 	  intel_sdvo.o \
- 	  intel_tv.o
- 
-+# intel precise touch & stylus
-+i915-y  += intel_ipts.o
-+
- # Post-mortem debug and GPU hang state capture
- i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
- i915-$(CONFIG_DRM_I915_SELFTEST) += \
-diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
-index 62004ea..94bce13 100644
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -51,6 +51,7 @@
- #include "i915_vgpu.h"
- #include "intel_drv.h"
- #include "intel_uc.h"
-+#include "intel_ipts.h"
- 
- static struct drm_driver driver;
- 
-@@ -691,6 +692,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
- 
- 	drm_kms_helper_poll_init(dev);
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc_submission)
-+        intel_ipts_init(dev);
-+
- 	return 0;
- 
- cleanup_gem:
-@@ -1394,6 +1398,9 @@ void i915_driver_unload(struct drm_device *dev)
- 	struct drm_i915_private *dev_priv = to_i915(dev);
- 	struct pci_dev *pdev = dev_priv->drm.pdev;
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc_submission)
-+		intel_ipts_cleanup(dev);
-+
- 	i915_driver_unregister(dev_priv);
- 
- 	if (i915_gem_suspend(dev_priv))
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index e143004..46b6dbe 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -3804,6 +3804,9 @@ void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
- void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
- 					 struct sg_table *pages);
- 
-+struct i915_gem_context *
-+i915_gem_context_create_ipts(struct drm_device *dev);
-+
- static inline struct i915_gem_context *
- __i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id)
- {
-diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
-index f782cf2..a8dd495 100644
---- a/drivers/gpu/drm/i915/i915_gem_context.c
-+++ b/drivers/gpu/drm/i915/i915_gem_context.c
-@@ -449,6 +449,18 @@ destroy_kernel_context(struct i915_gem_context **ctxp)
- 	i915_gem_context_free(ctx);
- }
- 
-+struct i915_gem_context *i915_gem_context_create_ipts(struct drm_device *dev)
-+{
-+	struct drm_i915_private *dev_priv = dev->dev_private;
-+	struct i915_gem_context *ctx;
-+
-+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-+
-+	ctx = i915_gem_create_context(dev_priv, NULL);
-+
-+	return ctx;
-+}
-+
- int i915_gem_contexts_init(struct drm_i915_private *dev_priv)
- {
- 	struct i915_gem_context *ctx;
-diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c
-index f84c267..9c1e595 100644
---- a/drivers/gpu/drm/i915/i915_guc_submission.c
-+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
-@@ -88,6 +88,7 @@ static inline bool is_high_priority(struct i915_guc_client* client)
- 
- static int __reserve_doorbell(struct i915_guc_client *client)
- {
-+	struct drm_i915_private *dev_priv = guc_to_i915(client->guc);
- 	unsigned long offset;
- 	unsigned long end;
- 	u16 id;
-@@ -100,10 +101,15 @@ static int __reserve_doorbell(struct i915_guc_client *client)
- 	 * priority contexts, the second half for high-priority ones.
- 	 */
- 	offset = 0;
--	end = GUC_NUM_DOORBELLS/2;
--	if (is_high_priority(client)) {
--		offset = end;
--		end += offset;
-+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
-+		end = GUC_NUM_DOORBELLS;
-+	}
-+	else {
-+		end = GUC_NUM_DOORBELLS/2;
-+		if (is_high_priority(client)) {
-+			offset = end;
-+			end += offset;
-+		}
- 	}
- 
- 	id = find_next_zero_bit(client->guc->doorbell_bitmap, end, offset);
-@@ -331,7 +337,14 @@ static void guc_stage_desc_init(struct intel_guc *guc,
- 	desc = __get_stage_desc(client);
- 	memset(desc, 0, sizeof(*desc));
- 
--	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE | GUC_STAGE_DESC_ATTR_KERNEL;
-+	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE;
-+	if ((client->priority == GUC_CLIENT_PRIORITY_KMD_NORMAL) ||
-+			(client->priority == GUC_CLIENT_PRIORITY_KMD_HIGH)) {
-+		desc->attribute  |= GUC_STAGE_DESC_ATTR_KERNEL;
-+	} else {
-+		desc->attribute  |= GUC_STAGE_DESC_ATTR_PCH;
-+	}
-+
- 	desc->stage_id = client->stage_id;
- 	desc->priority = client->priority;
- 	desc->db_id = client->doorbell_id;
-@@ -1042,7 +1055,8 @@ static void guc_interrupts_capture(struct drm_i915_private *dev_priv)
- 		I915_WRITE(RING_MODE_GEN7(engine), irqs);
- 
- 	/* route USER_INTERRUPT to Host, all others are sent to GuC. */
--	irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+	irqs = (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)
-+							<< GEN8_RCS_IRQ_SHIFT |
- 	       GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
- 	/* These three registers have the same bit definitions */
- 	I915_WRITE(GUC_BCS_RCS_IER, ~irqs);
-@@ -1176,3 +1190,47 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv)
- 	guc_client_free(guc->execbuf_client);
- 	guc->execbuf_client = NULL;
- }
-+
-+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv,
-+				    struct i915_gem_context *ctx)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+	struct i915_guc_client *client;
-+
-+	/* client for execbuf submission */
-+	client = guc_client_alloc(dev_priv,
-+				  INTEL_INFO(dev_priv)->ring_mask,
-+				  IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv) ? GUC_CLIENT_PRIORITY_HIGH : GUC_CLIENT_PRIORITY_NORMAL,
-+				  ctx);
-+	if (!client) {
-+		DRM_ERROR("Failed to create normal GuC client!\n");
-+		return -ENOMEM;
-+	}
-+
-+	guc->ipts_client = client;
-+	intel_guc_sample_forcewake(guc);
-+	guc_init_doorbell_hw(guc);
-+
-+	return 0;
-+}
-+
-+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+
-+	if (!guc->ipts_client)
-+		return;
-+
-+	guc_client_free(guc->ipts_client);
-+	guc->ipts_client = NULL;
-+}
-+
-+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+
-+	int err = __guc_allocate_doorbell(guc, guc->ipts_client->stage_id);
-+
-+	if (err)
-+		DRM_ERROR("Not able to reacquire IPTS doorbell\n");
-+}
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index f820584..d7d68d7 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -36,6 +36,7 @@
- #include "i915_drv.h"
- #include "i915_trace.h"
- #include "intel_drv.h"
-+#include "intel_ipts.h"
- 
- /**
-  * DOC: interrupt handling
-@@ -1399,6 +1400,9 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
- 		tasklet |= i915_modparams.enable_guc_submission;
- 	}
- 
-+	if (iir & (GT_RENDER_PIPECTL_NOTIFY_INTERRUPT << test_shift))
-+		intel_ipts_notify_complete();
-+
- 	if (tasklet)
- 		tasklet_hi_schedule(&execlists->irq_tasklet);
- }
-@@ -3560,7 +3564,8 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
- {
- 	/* These are interrupts we'll toggle with the ring mask register */
- 	uint32_t gt_interrupts[] = {
--		GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+		GT_RENDER_PIPECTL_NOTIFY_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+			GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
- 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
- 			GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT |
- 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT,
-diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
-index b4faeb6..a906694 100644
---- a/drivers/gpu/drm/i915/i915_params.c
-+++ b/drivers/gpu/drm/i915/i915_params.c
-@@ -101,7 +101,7 @@ i915_param_named_unsafe(enable_ppgtt, int, 0400,
- 
- i915_param_named_unsafe(enable_execlists, int, 0400,
- 	"Override execlists usage. "
--	"(-1=auto [default], 0=disabled, 1=enabled)");
-+	"(-1=auto, 0=disabled [default], 1=enabled)");
- 
- i915_param_named_unsafe(enable_psr, int, 0600,
- 	"Enable PSR "
-@@ -164,11 +164,11 @@ i915_param_named_unsafe(edp_vswing, int, 0400,
- 
- i915_param_named_unsafe(enable_guc_loading, int, 0400,
- 	"Enable GuC firmware loading "
--	"(-1=auto, 0=never [default], 1=if available, 2=required)");
-+	"(-1=auto, 0=never, 1=if available [default], 2=required)");
- 
- i915_param_named_unsafe(enable_guc_submission, int, 0400,
- 	"Enable GuC submission "
--	"(-1=auto, 0=never [default], 1=if available, 2=required)");
-+	"(-1=auto, 0=never, 1=if available [default], 2=required)");
- 
- i915_param_named(guc_log_level, int, 0400,
- 	"GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
-diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
-index c729226..2336695 100644
---- a/drivers/gpu/drm/i915/i915_params.h
-+++ b/drivers/gpu/drm/i915/i915_params.h
-@@ -39,13 +39,13 @@
- 	param(int, enable_dc, -1) \
- 	param(int, enable_fbc, -1) \
- 	param(int, enable_ppgtt, -1) \
--	param(int, enable_execlists, -1) \
-+	param(int, enable_execlists, 0) \
- 	param(int, enable_psr, -1) \
- 	param(int, disable_power_well, -1) \
- 	param(int, enable_ips, 1) \
- 	param(int, invert_brightness, 0) \
--	param(int, enable_guc_loading, 0) \
--	param(int, enable_guc_submission, 0) \
-+	param(int, enable_guc_loading, 1) \
-+	param(int, enable_guc_submission, 1) \
- 	param(int, guc_log_level, -1) \
- 	param(char *, guc_firmware_path, NULL) \
- 	param(char *, huc_firmware_path, NULL) \
-diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
-index 418450b..c1bd36c 100644
---- a/drivers/gpu/drm/i915/intel_guc.h
-+++ b/drivers/gpu/drm/i915/intel_guc.h
-@@ -56,6 +56,7 @@ struct intel_guc {
- 	struct ida stage_ids;
- 
- 	struct i915_guc_client *execbuf_client;
-+	struct i915_guc_client *ipts_client;
- 
- 	DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS);
- 	/* Cyclic counter mod pagesize	*/
-@@ -116,5 +117,9 @@ int intel_guc_suspend(struct drm_i915_private *dev_priv);
- int intel_guc_resume(struct drm_i915_private *dev_priv);
- struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size);
- u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv);
-+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv,
-+				    struct i915_gem_context *ctx);
-+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv);
-+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv);
- 
- #endif
-diff --git a/drivers/gpu/drm/i915/intel_ipts.c b/drivers/gpu/drm/i915/intel_ipts.c
-new file mode 100644
-index 0000000..be9fa6f
---- /dev/null
-+++ b/drivers/gpu/drm/i915/intel_ipts.c
-@@ -0,0 +1,627 @@
-+/*
-+ * Copyright  2016 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#include <linux/intel_ipts_if.h>
-+#include <drm/drmP.h>
-+
-+#include "i915_guc_submission.h"
-+#include "i915_drv.h"
-+
-+#define SUPPORTED_IPTS_INTERFACE_VERSION	1
-+
-+#define REACQUIRE_DB_THRESHOLD			8
-+#define DB_LOST_CHECK_STEP1_INTERVAL		2000	/* ms */
-+#define DB_LOST_CHECK_STEP2_INTERVAL		500	/* ms */
-+
-+/* intel IPTS ctx for ipts support */
-+typedef struct intel_ipts {
-+	struct drm_device *dev;
-+	struct i915_gem_context *ipts_context;
-+	intel_ipts_callback_t ipts_clbks;
-+
-+	/* buffers' list */
-+	struct {
-+		spinlock_t       lock;
-+		struct list_head list;
-+	} buffers;
-+
-+	void *data;
-+
-+	struct delayed_work reacquire_db_work;
-+	intel_ipts_wq_info_t wq_info;
-+	u32	old_tail;
-+	u32	old_head;
-+	bool	need_reacquire_db;
-+
-+	bool	connected;
-+	bool	initialized;
-+} intel_ipts_t;
-+
-+intel_ipts_t intel_ipts;
-+
-+typedef struct intel_ipts_object {
-+	struct list_head list;
-+	struct drm_i915_gem_object *gem_obj;
-+	void	*cpu_addr;
-+} intel_ipts_object_t;
-+
-+static intel_ipts_object_t *ipts_object_create(size_t size, u32 flags)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	intel_ipts_object_t *obj = NULL;
-+	struct drm_i915_gem_object *gem_obj = NULL;
-+	int ret = 0;
-+
-+	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
-+	if (!obj)
-+		return NULL;
-+
-+	size = roundup(size, PAGE_SIZE);
-+	if (size == 0) {
-+		ret = -EINVAL;
-+		goto err_out;
-+	}
-+
-+	/* Allocate the new object */
-+	gem_obj = i915_gem_object_create(dev_priv, size);
-+	if (gem_obj == NULL) {
-+		ret = -ENOMEM;
-+		goto err_out;
-+	}
-+
-+	if (flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		ret = i915_gem_object_attach_phys(gem_obj, PAGE_SIZE);
-+		if (ret) {
-+			pr_info(">> ipts no contiguous : %d\n", ret);
-+			goto err_out;
-+		}
-+	}
-+
-+	obj->gem_obj = gem_obj;
-+
-+	spin_lock(&intel_ipts.buffers.lock);
-+	list_add_tail(&obj->list, &intel_ipts.buffers.list);
-+	spin_unlock(&intel_ipts.buffers.lock);
-+
-+	return obj;
-+
-+err_out:
-+	if (gem_obj)
-+		i915_gem_free_object(&gem_obj->base);
-+
-+	if (obj)
-+		kfree(obj);
-+
-+	return NULL;
-+}
-+
-+static void ipts_object_free(intel_ipts_object_t* obj)
-+{
-+	spin_lock(&intel_ipts.buffers.lock);
-+	list_del(&obj->list);
-+	spin_unlock(&intel_ipts.buffers.lock);
-+
-+	i915_gem_free_object(&obj->gem_obj->base);
-+	kfree(obj);
-+}
-+
-+static int ipts_object_pin(intel_ipts_object_t* obj,
-+					struct i915_gem_context *ipts_ctx)
-+{
-+	struct i915_address_space *vm = NULL;
-+	struct i915_vma *vma = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	if (ipts_ctx->ppgtt) {
-+		vm = &ipts_ctx->ppgtt->base;
-+	} else {
-+		vm = &dev_priv->ggtt.base;
-+	}
-+
-+	vma = i915_vma_instance(obj->gem_obj, vm, NULL);
-+	if (IS_ERR(vma)) {
-+		DRM_ERROR("cannot find or create vma\n");
-+		return -1;
-+	}
-+
-+	ret = i915_vma_pin(vma, 0, PAGE_SIZE, PIN_USER);
-+
-+	return ret;
-+}
-+
-+static void ipts_object_unpin(intel_ipts_object_t *obj)
-+{
-+	/* TBD: Add support */
-+}
-+
-+static void* ipts_object_map(intel_ipts_object_t *obj)
-+{
-+
-+	return i915_gem_object_pin_map(obj->gem_obj, I915_MAP_WB);
-+}
-+
-+static void ipts_object_unmap(intel_ipts_object_t* obj)
-+{
-+	i915_gem_object_unpin_map(obj->gem_obj);
-+	obj->cpu_addr = NULL;
-+}
-+
-+static int create_ipts_context(void)
-+{
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct intel_ring *pin_ret;
-+	int ret = 0;
-+
-+	/* Initialize the context right away.*/
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return ret;
-+	}
-+
-+	ipts_ctx = i915_gem_context_create_ipts(intel_ipts.dev);
-+	if (IS_ERR(ipts_ctx)) {
-+		DRM_ERROR("Failed to create IPTS context (error %ld)\n",
-+			  PTR_ERR(ipts_ctx));
-+		ret = PTR_ERR(ipts_ctx);
-+		goto err_unlock;
-+	}
-+
-+	ret = execlists_context_deferred_alloc(ipts_ctx, dev_priv->engine[RCS]);
-+	if (ret) {
-+		DRM_DEBUG("lr context allocation failed : %d\n", ret);
-+		goto err_ctx;
-+	}
-+
-+	pin_ret = execlists_context_pin(dev_priv->engine[RCS], ipts_ctx);
-+	if (IS_ERR(pin_ret)) {
-+		DRM_DEBUG("lr context pinning failed :  %ld\n", PTR_ERR(pin_ret));
-+		goto err_ctx;
-+	}
-+
-+	/* Release the mutex */
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	spin_lock_init(&intel_ipts.buffers.lock);
-+	INIT_LIST_HEAD(&intel_ipts.buffers.list);
-+
-+	intel_ipts.ipts_context = ipts_ctx;
-+
-+	return 0;
-+
-+err_ctx:
-+	if (ipts_ctx)
-+		i915_gem_context_put(ipts_ctx);
-+
-+err_unlock:
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return ret;
-+}
-+
-+static void destroy_ipts_context(void)
-+{
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	ipts_ctx = intel_ipts.ipts_context;
-+
-+	/* Initialize the context right away.*/
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return;
-+	}
-+
-+	execlists_context_unpin(dev_priv->engine[RCS], ipts_ctx);
-+	i915_gem_context_put(ipts_ctx);
-+
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+}
-+
-+int intel_ipts_notify_complete(void)
-+{
-+	if (intel_ipts.ipts_clbks.workload_complete)
-+		intel_ipts.ipts_clbks.workload_complete(intel_ipts.data);
-+
-+	return 0;
-+}
-+
-+int intel_ipts_notify_backlight_status(bool backlight_on)
-+{
-+	if (intel_ipts.ipts_clbks.notify_gfx_status) {
-+		if (backlight_on) {
-+			intel_ipts.ipts_clbks.notify_gfx_status(
-+						IPTS_NOTIFY_STA_BACKLIGHT_ON,
-+						intel_ipts.data);
-+			schedule_delayed_work(&intel_ipts.reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+		} else {
-+			intel_ipts.ipts_clbks.notify_gfx_status(
-+						IPTS_NOTIFY_STA_BACKLIGHT_OFF,
-+						intel_ipts.data);
-+			cancel_delayed_work(&intel_ipts.reacquire_db_work);
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+static void intel_ipts_reacquire_db(intel_ipts_t *intel_ipts_p)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts_p->dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return;
-+	}
-+
-+	/* Reacquire the doorbell */
-+	i915_guc_ipts_reacquire_doorbell(intel_ipts_p->dev->dev_private);
-+
-+	mutex_unlock(&intel_ipts_p->dev->struct_mutex);
-+
-+	return;
-+}
-+
-+static int intel_ipts_get_wq_info(uint64_t gfx_handle,
-+						intel_ipts_wq_info_t *wq_info)
-+{
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	*wq_info = intel_ipts.wq_info;
-+
-+	intel_ipts_reacquire_db(&intel_ipts);
-+	schedule_delayed_work(&intel_ipts.reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+
-+	return 0;
-+}
-+
-+static int set_wq_info(void)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct intel_guc *guc = &dev_priv->guc;
-+	struct i915_guc_client *client;
-+	struct guc_process_desc *desc;
-+	void *base = NULL;
-+	intel_ipts_wq_info_t *wq_info;
-+	u64 phy_base = 0;
-+
-+	wq_info = &intel_ipts.wq_info;
-+
-+	client = guc->ipts_client;
-+	if (!client) {
-+		DRM_ERROR("IPTS GuC client is NOT available\n");
-+		return -EINVAL;
-+	}
-+
-+	base = client->vaddr;
-+	desc = (struct guc_process_desc *)((u64)base + client->proc_desc_offset);
-+
-+	desc->wq_base_addr = (u64)base + GUC_DB_SIZE;
-+	desc->db_base_addr = (u64)base + client->doorbell_offset;
-+
-+	/* IPTS expects physical addresses to pass it to ME */
-+	phy_base = sg_dma_address(client->vma->pages->sgl);
-+
-+	wq_info->db_addr = desc->db_base_addr;
-+        wq_info->db_phy_addr = phy_base + client->doorbell_offset;
-+        wq_info->db_cookie_offset = offsetof(struct guc_doorbell_info, cookie);
-+        wq_info->wq_addr = desc->wq_base_addr;
-+        wq_info->wq_phy_addr = phy_base + GUC_DB_SIZE;
-+        wq_info->wq_head_addr = (u64)&desc->head;
-+        wq_info->wq_head_phy_addr = phy_base + client->proc_desc_offset +
-+					offsetof(struct guc_process_desc, head);
-+        wq_info->wq_tail_addr = (u64)&desc->tail;
-+        wq_info->wq_tail_phy_addr = phy_base + client->proc_desc_offset +
-+					offsetof(struct guc_process_desc, tail);
-+        wq_info->wq_size = desc->wq_size_bytes;
-+
-+	return 0;
-+}
-+
-+static int intel_ipts_init_wq(void)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed\n");
-+		return ret;
-+	}
-+
-+	/* disable IPTS submission */
-+	i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private);
-+
-+	/* enable IPTS submission */
-+	ret = i915_guc_ipts_submission_enable(intel_ipts.dev->dev_private,
-+							intel_ipts.ipts_context);
-+	if (ret) {
-+		DRM_ERROR("i915_guc_ipts_submission_enable failed : %d\n", ret);
-+		goto out;
-+        }
-+
-+	ret = set_wq_info();
-+	if (ret) {
-+		DRM_ERROR("set_wq_info failed\n");
-+		goto out;
-+	}
-+
-+out:
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return ret;
-+}
-+
-+static void intel_ipts_release_wq(void)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed\n");
-+		return;
-+	}
-+
-+	/* disable IPTS submission */
-+	i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private);
-+
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+}
-+
-+static int intel_ipts_map_buffer(u64 gfx_handle, intel_ipts_mapbuffer_t *mapbuf)
-+{
-+	intel_ipts_object_t* obj;
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct i915_address_space *vm = NULL;
-+	struct i915_vma *vma = NULL;
-+	int ret = 0;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	/* Acquire mutex first */
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return -EINVAL;
-+	}
-+
-+	obj = ipts_object_create(mapbuf->size, mapbuf->flags);
-+	if (!obj)
-+		return -ENOMEM;
-+
-+	ipts_ctx = intel_ipts.ipts_context;
-+	ret = ipts_object_pin(obj, ipts_ctx);
-+	if (ret) {
-+		DRM_ERROR("Not able to pin iTouch obj\n");
-+		ipts_object_free(obj);
-+		mutex_unlock(&intel_ipts.dev->struct_mutex);
-+		return -ENOMEM;
-+	}
-+
-+	if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		obj->cpu_addr = obj->gem_obj->phys_handle->vaddr;
-+	} else {
-+		obj->cpu_addr = ipts_object_map(obj);
-+	}
-+
-+	if (ipts_ctx->ppgtt) {
-+		vm = &ipts_ctx->ppgtt->base;
-+	} else {
-+		vm = &dev_priv->ggtt.base;
-+	}
-+
-+	vma = i915_vma_instance(obj->gem_obj, vm, NULL);
-+	if (IS_ERR(vma)) {
-+		DRM_ERROR("cannot find or create vma\n");
-+		return -EINVAL;
-+	}
-+
-+	mapbuf->gfx_addr = (void*)vma->node.start;
-+	mapbuf->cpu_addr = (void*)obj->cpu_addr;
-+	mapbuf->buf_handle = (u64)obj;
-+	if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		mapbuf->phy_addr = (u64)obj->gem_obj->phys_handle->busaddr;
-+	}
-+
-+	/* Release the mutex */
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return 0;
-+}
-+
-+static int intel_ipts_unmap_buffer(uint64_t gfx_handle, uint64_t buf_handle)
-+{
-+	intel_ipts_object_t* obj = (intel_ipts_object_t*)buf_handle;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	if (!obj->gem_obj->phys_handle)
-+		ipts_object_unmap(obj);
-+	ipts_object_unpin(obj);
-+	ipts_object_free(obj);
-+
-+	return 0;
-+}
-+
-+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	if (!intel_ipts.initialized)
-+		return -EIO;
-+
-+	if (ipts_connect && ipts_connect->if_version <=
-+					SUPPORTED_IPTS_INTERFACE_VERSION) {
-+
-+		/* return gpu operations for ipts */
-+		ipts_connect->ipts_ops.get_wq_info = intel_ipts_get_wq_info;
-+		ipts_connect->ipts_ops.map_buffer = intel_ipts_map_buffer;
-+		ipts_connect->ipts_ops.unmap_buffer = intel_ipts_unmap_buffer;
-+		ipts_connect->gfx_version = INTEL_INFO(dev_priv)->gen;
-+		ipts_connect->gfx_handle = (uint64_t)&intel_ipts;
-+
-+		/* save callback and data */
-+		intel_ipts.data = ipts_connect->data;
-+		intel_ipts.ipts_clbks = ipts_connect->ipts_cb;
-+
-+		intel_ipts.connected = true;
-+	} else {
-+		ret = -EINVAL;
-+	}
-+
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(intel_ipts_connect);
-+
-+void intel_ipts_disconnect(uint64_t gfx_handle)
-+{
-+	if (!intel_ipts.initialized)
-+		return;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts ||
-+					intel_ipts.connected == false) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return;
-+	}
-+
-+	intel_ipts.data = 0;
-+	memset(&intel_ipts.ipts_clbks, 0, sizeof(intel_ipts_callback_t));
-+
-+	intel_ipts.connected = false;
-+}
-+EXPORT_SYMBOL_GPL(intel_ipts_disconnect);
-+
-+static void reacquire_db_work_func(struct work_struct *work)
-+{
-+	struct delayed_work *d_work = container_of(work, struct delayed_work,
-+							work);
-+	intel_ipts_t *intel_ipts_p = container_of(d_work, intel_ipts_t,
-+							reacquire_db_work);
-+	u32 head;
-+	u32 tail;
-+	u32 size;
-+	u32 load;
-+
-+	head = *(u32*)intel_ipts_p->wq_info.wq_head_addr;
-+	tail = *(u32*)intel_ipts_p->wq_info.wq_tail_addr;
-+	size = intel_ipts_p->wq_info.wq_size;
-+
-+	if (head >= tail)
-+		load = head - tail;
-+	else
-+		load = head + size - tail;
-+
-+	if (load < REACQUIRE_DB_THRESHOLD) {
-+		intel_ipts_p->need_reacquire_db = false;
-+		goto reschedule_work;
-+	}
-+
-+	if (intel_ipts_p->need_reacquire_db) {
-+		if (intel_ipts_p->old_head == head && intel_ipts_p->old_tail == tail)
-+			intel_ipts_reacquire_db(intel_ipts_p);
-+		intel_ipts_p->need_reacquire_db = false;
-+	} else {
-+		intel_ipts_p->old_head = head;
-+		intel_ipts_p->old_tail = tail;
-+		intel_ipts_p->need_reacquire_db = true;
-+
-+		/* recheck */
-+		schedule_delayed_work(&intel_ipts_p->reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP2_INTERVAL));
-+		return;
-+	}
-+
-+reschedule_work:
-+	schedule_delayed_work(&intel_ipts_p->reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+}
-+
-+/**
-+ * intel_ipts_init - Initialize ipts support
-+ * @dev: drm device
-+ *
-+ * Setup the required structures for ipts.
-+ */
-+int intel_ipts_init(struct drm_device *dev)
-+{
-+	int ret = 0;
-+
-+	pr_info("ipts: initializing ipts\n");
-+
-+	intel_ipts.dev = dev;
-+	INIT_DELAYED_WORK(&intel_ipts.reacquire_db_work, reacquire_db_work_func);
-+
-+	ret = create_ipts_context();
-+	if (ret)
-+		return -ENOMEM;
-+
-+	ret = intel_ipts_init_wq();
-+	if (ret)
-+		return ret;
-+
-+	intel_ipts.initialized = true;
-+	DRM_DEBUG_DRIVER("Intel iTouch framework initialized\n");
-+
-+	return ret;
-+}
-+
-+void intel_ipts_cleanup(struct drm_device *dev)
-+{
-+	intel_ipts_object_t *obj, *n;
-+
-+	if (intel_ipts.dev == dev) {
-+		list_for_each_entry_safe(obj, n, &intel_ipts.buffers.list, list) {
-+			list_del(&obj->list);
-+
-+			if (!obj->gem_obj->phys_handle)
-+				ipts_object_unmap(obj);
-+			ipts_object_unpin(obj);
-+			i915_gem_free_object(&obj->gem_obj->base);
-+			kfree(obj);
-+		}
-+
-+		intel_ipts_release_wq();
-+		destroy_ipts_context();
-+		cancel_delayed_work(&intel_ipts.reacquire_db_work);
-+	}
-+}
-diff --git a/drivers/gpu/drm/i915/intel_ipts.h b/drivers/gpu/drm/i915/intel_ipts.h
-new file mode 100644
-index 0000000..a6965d1
---- /dev/null
-+++ b/drivers/gpu/drm/i915/intel_ipts.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright © 2016 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ */
-+#ifndef _INTEL_IPTS_H_
-+#define _INTEL_IPTS_H_
-+
-+struct drm_device;
-+
-+int intel_ipts_init(struct drm_device *dev);
-+void intel_ipts_cleanup(struct drm_device *dev);
-+int intel_ipts_notify_backlight_status(bool backlight_on);
-+int intel_ipts_notify_complete(void);
-+
-+#endif //_INTEL_IPTS_H_
-diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
-index e71a8cd..78a35f7 100644
---- a/drivers/gpu/drm/i915/intel_lrc.c
-+++ b/drivers/gpu/drm/i915/intel_lrc.c
-@@ -212,8 +212,6 @@
- #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS)
- #define PREEMPT_ID 0x1
- 
--static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
--					    struct intel_engine_cs *engine);
- static void execlists_init_reg_state(u32 *reg_state,
- 				     struct i915_gem_context *ctx,
- 				     struct intel_engine_cs *engine,
-@@ -1060,7 +1058,7 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio)
- 	spin_unlock_irq(&engine->timeline->lock);
- }
- 
--static struct intel_ring *
-+struct intel_ring *
- execlists_context_pin(struct intel_engine_cs *engine,
- 		      struct i915_gem_context *ctx)
- {
-@@ -1122,7 +1120,7 @@ execlists_context_pin(struct intel_engine_cs *engine,
- 	return ERR_PTR(ret);
- }
- 
--static void execlists_context_unpin(struct intel_engine_cs *engine,
-+void execlists_context_unpin(struct intel_engine_cs *engine,
- 				    struct i915_gem_context *ctx)
- {
- 	struct intel_context *ce = &ctx->engine[engine->id];
-@@ -1981,6 +1979,9 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
- 
- 	logical_ring_setup(engine);
- 
-+	engine->irq_keep_mask |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT
-+							<< GEN8_RCS_IRQ_SHIFT;
-+
- 	if (HAS_L3_DPF(dev_priv))
- 		engine->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
- 
-@@ -2213,7 +2214,7 @@ populate_lr_context(struct i915_gem_context *ctx,
- 	return 0;
- }
- 
--static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
-+int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
- 					    struct intel_engine_cs *engine)
- {
- 	struct drm_i915_gem_object *ctx_obj;
-diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
-index 689fde1..54a076d 100644
---- a/drivers/gpu/drm/i915/intel_lrc.h
-+++ b/drivers/gpu/drm/i915/intel_lrc.h
-@@ -112,4 +112,12 @@ intel_lr_context_descriptor(struct i915_gem_context *ctx,
- int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv,
- 				    int enable_execlists);
- 
-+struct intel_ring *
-+execlists_context_pin(struct intel_engine_cs *engine,
-+		      struct i915_gem_context *ctx);
-+void execlists_context_unpin(struct intel_engine_cs *engine,
-+				    struct i915_gem_context *ctx);
-+int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
-+					    struct intel_engine_cs *engine);
-+
- #endif /* _INTEL_LRC_H_ */
-diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
-index adc51e4..a3294c4 100644
---- a/drivers/gpu/drm/i915/intel_panel.c
-+++ b/drivers/gpu/drm/i915/intel_panel.c
-@@ -34,6 +34,7 @@
- #include <linux/moduleparam.h>
- #include <linux/pwm.h>
- #include "intel_drv.h"
-+#include "intel_ipts.h"
- 
- #define CRC_PMIC_PWM_PERIOD_NS	21333
- 
-@@ -719,6 +720,9 @@ static void lpt_disable_backlight(const struct drm_connector_state *old_conn_sta
- 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- 	u32 tmp;
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc_submission)
-+		intel_ipts_notify_backlight_status(false);
-+
- 	intel_panel_actually_set_backlight(old_conn_state, 0);
- 
- 	/*
-@@ -906,6 +910,9 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
- 
- 	/* This won't stick until the above enable. */
- 	intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
-+
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc_submission)
-+		intel_ipts_notify_backlight_status(true);
- }
- 
- static void pch_enable_backlight(const struct intel_crtc_state *crtc_state,
-diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
-index 3975929..94488a5 100644
---- a/drivers/hid/hid-multitouch.c
-+++ b/drivers/hid/hid-multitouch.c
-@@ -145,6 +145,7 @@ struct mt_device {
- 
- static void mt_post_parse_default_settings(struct mt_device *td);
- static void mt_post_parse(struct mt_device *td);
-+static int cc_seen = 0;
- 
- /* classes of device behavior */
- #define MT_CLS_DEFAULT				0x0001
-@@ -605,8 +606,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 			if (field->index >= field->report->maxfield ||
- 			    usage->usage_index >= field->report_count)
- 				return 1;
--			td->cc_index = field->index;
--			td->cc_value_index = usage->usage_index;
-+
-+			if(cc_seen != 1) {
-+				td->cc_index = field->index;
-+				td->cc_value_index = usage->usage_index;
-+				cc_seen++;
-+			}
- 			return 1;
- 		case HID_DG_CONTACTMAX:
- 			/* we don't set td->last_slot_field as contactcount and
-@@ -643,6 +648,16 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 	return 0;
- }
- 
-+static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-+		struct hid_field *field, struct hid_usage *usage,
-+		unsigned long **bit, int *max)
-+{
-+	if (usage->type == EV_KEY || usage->type == EV_ABS)
-+		set_bit(usage->type, hi->input->evbit);
-+
-+	return -1;
-+}
-+
- static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
- {
- 	__s32 quirks = td->mtclass.quirks;
-@@ -985,9 +1000,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 	    field->application != HID_DG_TOUCHSCREEN &&
- 	    field->application != HID_DG_PEN &&
- 	    field->application != HID_DG_TOUCHPAD &&
-+		field->application != HID_GD_MOUSE &&
- 	    field->application != HID_GD_KEYBOARD &&
- 	    field->application != HID_GD_SYSTEM_CONTROL &&
- 	    field->application != HID_CP_CONSUMER_CONTROL &&
-+		field->logical != HID_DG_TOUCHSCREEN &&
- 	    field->application != HID_GD_WIRELESS_RADIO_CTLS &&
- 	    !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
- 	      td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP))
-@@ -1050,10 +1067,8 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
- 		return 0;
- 
- 	if (field->application == HID_DG_TOUCHSCREEN ||
--	    field->application == HID_DG_TOUCHPAD) {
--		/* We own these mappings, tell hid-input to ignore them */
--		return -1;
--	}
-+	    field->application == HID_DG_TOUCHPAD)
-+		return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
- 
- 	/* let hid-core decide for the others */
- 	return 0;
-@@ -1196,6 +1211,7 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
- 		suffix = "Pen";
- 		/* force BTN_STYLUS to allow tablet matching in udev */
- 		__set_bit(BTN_STYLUS, hi->input->keybit);
-+        __set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
- 	} else {
- 		switch (field->application) {
- 		case HID_GD_KEYBOARD:
-@@ -1211,9 +1227,10 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
- 			suffix = "Pen";
- 			/* force BTN_STYLUS to allow tablet matching in udev */
- 			__set_bit(BTN_STYLUS, hi->input->keybit);
-+            __set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
- 			break;
- 		case HID_DG_TOUCHSCREEN:
--			/* we do not set suffix = "Touchscreen" */
-+			suffix = "Touchscreen";
- 			break;
- 		case HID_DG_TOUCHPAD:
- 			suffix = "Touchpad";
-@@ -1343,6 +1360,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
- 	td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN;
- 	td->cc_index = -1;
- 	td->mt_report_id = -1;
-+	cc_seen = 0;
- 	hid_set_drvdata(hdev, td);
- 
- 	td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
-diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
-index e054ee4..7230243 100644
---- a/drivers/hid/i2c-hid/i2c-hid.c
-+++ b/drivers/hid/i2c-hid/i2c-hid.c
-@@ -934,11 +934,6 @@ static int i2c_hid_of_probe(struct i2c_client *client,
- 	}
- 	pdata->hid_descriptor_address = val;
- 
--	ret = of_property_read_u32(dev->of_node, "post-power-on-delay-ms",
--				   &val);
--	if (!ret)
--		pdata->post_power_delay_ms = val;
--
- 	return 0;
- }
- 
-@@ -955,6 +950,16 @@ static inline int i2c_hid_of_probe(struct i2c_client *client,
- }
- #endif
- 
-+static void i2c_hid_fwnode_probe(struct i2c_client *client,
-+				 struct i2c_hid_platform_data *pdata)
-+{
-+	u32 val;
-+
-+	if (!device_property_read_u32(&client->dev, "post-power-on-delay-ms",
-+				      &val))
-+		pdata->post_power_delay_ms = val;
-+}
-+
- static int i2c_hid_probe(struct i2c_client *client,
- 			 const struct i2c_device_id *dev_id)
- {
-@@ -998,6 +1003,9 @@ static int i2c_hid_probe(struct i2c_client *client,
- 		ihid->pdata = *platform_data;
- 	}
- 
-+	/* 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);
-diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index f1a5c23..3111140 100644
---- a/drivers/misc/Kconfig
-+++ b/drivers/misc/Kconfig
-@@ -503,6 +503,7 @@ source "drivers/misc/ti-st/Kconfig"
- source "drivers/misc/lis3lv02d/Kconfig"
- source "drivers/misc/altera-stapl/Kconfig"
- source "drivers/misc/mei/Kconfig"
-+source "drivers/misc/ipts/Kconfig"
- source "drivers/misc/vmw_vmci/Kconfig"
- source "drivers/misc/mic/Kconfig"
- source "drivers/misc/genwqe/Kconfig"
-diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index 5ca5f64..1673753 100644
---- a/drivers/misc/Makefile
-+++ b/drivers/misc/Makefile
-@@ -43,6 +43,7 @@ obj-y				+= lis3lv02d/
- obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
- obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
- obj-$(CONFIG_INTEL_MEI)		+= mei/
-+obj-$(CONFIG_INTEL_IPTS)	+= ipts/
- obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
- obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
- obj-$(CONFIG_SRAM)		+= sram.o
-diff --git a/drivers/misc/ipts/Kconfig b/drivers/misc/ipts/Kconfig
-new file mode 100644
-index 0000000..360ed38
---- /dev/null
-+++ b/drivers/misc/ipts/Kconfig
-@@ -0,0 +1,9 @@
-+config INTEL_IPTS
-+	tristate "Intel Precise Touch & Stylus"
-+	select INTEL_MEI
-+	depends on X86 && PCI && HID
-+	help
-+	  Intel Precise Touch & Stylus support
-+	  Supported SoCs:
-+	  Intel Skylake
-+	  Intel Kabylake
-diff --git a/drivers/misc/ipts/Makefile b/drivers/misc/ipts/Makefile
-new file mode 100644
-index 0000000..1783e9c
---- /dev/null
-+++ b/drivers/misc/ipts/Makefile
-@@ -0,0 +1,13 @@
-+#
-+# Makefile - Intel Precise Touch & Stylus device driver
-+# Copyright (c) 2016, Intel Corporation.
-+#
-+
-+obj-$(CONFIG_INTEL_IPTS)+= intel-ipts.o
-+intel-ipts-objs += ipts-mei.o
-+intel-ipts-objs += ipts-hid.o
-+intel-ipts-objs += ipts-msg-handler.o
-+intel-ipts-objs += ipts-kernel.o
-+intel-ipts-objs += ipts-resource.o
-+intel-ipts-objs += ipts-gfx.o
-+intel-ipts-$(CONFIG_DEBUG_FS) += ipts-dbgfs.o
-diff --git a/drivers/misc/ipts/ipts-binary-spec.h b/drivers/misc/ipts/ipts-binary-spec.h
-new file mode 100644
-index 0000000..87d4bc4
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-binary-spec.h
-@@ -0,0 +1,118 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus binary spec
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_BINARY_SPEC_H
-+#define _IPTS_BINARY_SPEC_H
-+
-+#define IPTS_BIN_HEADER_VERSION 2
-+
-+#pragma pack(1)
-+
-+/* we support 16 output buffers(1:feedback, 15:HID) */
-+#define  MAX_NUM_OUTPUT_BUFFERS 16
-+
-+typedef enum {
-+	IPTS_BIN_KERNEL,
-+	IPTS_BIN_RO_DATA,
-+	IPTS_BIN_RW_DATA,
-+	IPTS_BIN_SENSOR_FRAME,
-+	IPTS_BIN_OUTPUT,
-+	IPTS_BIN_DYNAMIC_STATE_HEAP,
-+	IPTS_BIN_PATCH_LOCATION_LIST,
-+	IPTS_BIN_ALLOCATION_LIST,
-+	IPTS_BIN_COMMAND_BUFFER_PACKET,
-+	IPTS_BIN_TAG,
-+} ipts_bin_res_type_t;
-+
-+typedef struct ipts_bin_header {
-+	char str[4];
-+	unsigned int version;
-+
-+#if IPTS_BIN_HEADER_VERSION > 1
-+	unsigned int gfxcore;
-+	unsigned int revid;
-+#endif
-+} ipts_bin_header_t;
-+
-+typedef struct ipts_bin_alloc {
-+	unsigned int handle;
-+	unsigned int reserved;
-+} ipts_bin_alloc_t;
-+
-+typedef struct ipts_bin_alloc_list {
-+	unsigned int num;
-+	ipts_bin_alloc_t alloc[];
-+} ipts_bin_alloc_list_t;
-+
-+typedef struct ipts_bin_cmdbuf {
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_cmdbuf_t;
-+
-+typedef struct ipts_bin_res {
-+	unsigned int handle;
-+	ipts_bin_res_type_t type;
-+	unsigned int initialize;
-+	unsigned int aligned_size;
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_res_t;
-+
-+typedef enum {
-+	IPTS_INPUT,
-+	IPTS_OUTPUT,
-+	IPTS_CONFIGURATION,
-+	IPTS_CALIBRATION,
-+	IPTS_FEATURE,
-+} ipts_bin_io_buffer_type_t;
-+
-+typedef struct ipts_bin_io_header {
-+	char str[10];
-+	unsigned short type;
-+} ipts_bin_io_header_t;
-+
-+typedef struct ipts_bin_res_list {
-+	unsigned int num;
-+	ipts_bin_res_t res[];
-+} ipts_bin_res_list_t;
-+
-+typedef struct ipts_bin_patch {
-+	unsigned int index;
-+	unsigned int reserved1[2];
-+	unsigned int alloc_offset;
-+	unsigned int patch_offset;
-+	unsigned int reserved2;
-+} ipts_bin_patch_t;
-+
-+typedef struct ipts_bin_patch_list {
-+	unsigned int num;
-+	ipts_bin_patch_t patch[];
-+} ipts_bin_patch_list_t;
-+
-+typedef struct ipts_bin_guc_wq_info {
-+	unsigned int batch_offset;
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_guc_wq_info_t;
-+
-+typedef struct ipts_bin_bufid_patch {
-+	unsigned int imm_offset;
-+	unsigned int mem_offset;
-+} ipts_bin_bufid_patch_t;
-+
-+#pragma pack()
-+
-+#endif /* _IPTS_BINARY_SPEC_H */
-diff --git a/drivers/misc/ipts/ipts-dbgfs.c b/drivers/misc/ipts/ipts-dbgfs.c
-new file mode 100644
-index 0000000..1c5c92f
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-dbgfs.c
-@@ -0,0 +1,152 @@
-+/*
-+ * Intel Precise Touch & Stylus device driver
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/debugfs.h>
-+#include <linux/ctype.h>
-+#include <linux/uaccess.h>
-+
-+#include "ipts.h"
-+#include "ipts-sensor-regs.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-state.h"
-+
-+const char sensor_mode_fmt[] = "sensor mode : %01d\n";
-+const char ipts_status_fmt[] = "sensor mode : %01d\nipts state : %01d\n";
-+
-+static ssize_t ipts_dbgfs_mode_read(struct file *fp, char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	char mode[80];
-+	int len = 0;
-+
-+	if (cnt < sizeof(sensor_mode_fmt) - 3)
-+		return -EINVAL;
-+
-+	len = scnprintf(mode, 80, sensor_mode_fmt, ipts->sensor_mode);
-+	if (len < 0)
-+		return -EIO;
-+
-+	return simple_read_from_buffer(ubuf, cnt, ppos, mode, len);
-+}
-+
-+static ssize_t ipts_dbgfs_mode_write(struct file *fp, const char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	ipts_state_t state;
-+	int sensor_mode, len;
-+	char mode[3];
-+
-+	if (cnt == 0 || cnt > 3)
-+		return -EINVAL;
-+
-+	state = ipts_get_state(ipts);
-+	if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED) {
-+		return -EIO;
-+	}
-+
-+	len = cnt;
-+	if (copy_from_user(mode, ubuf, len))
-+		return -EFAULT;
-+
-+	while(len > 0 && (isspace(mode[len-1]) || mode[len-1] == '\n'))
-+		len--;
-+	mode[len] = '\0';
-+
-+	if (sscanf(mode, "%d", &sensor_mode) != 1)
-+		return -EINVAL;
-+
-+	if (sensor_mode != TOUCH_SENSOR_MODE_RAW_DATA &&
-+					sensor_mode != TOUCH_SENSOR_MODE_HID) {
-+		return -EINVAL;
-+	}
-+
-+	if (sensor_mode == ipts->sensor_mode)
-+		return 0;
-+
-+	ipts_switch_sensor_mode(ipts, sensor_mode);
-+
-+	return cnt;
-+}
-+
-+static const struct file_operations ipts_mode_dbgfs_fops = {
-+        .open = simple_open,
-+        .read = ipts_dbgfs_mode_read,
-+        .write = ipts_dbgfs_mode_write,
-+        .llseek = generic_file_llseek,
-+};
-+
-+static ssize_t ipts_dbgfs_status_read(struct file *fp, char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	char status[256];
-+	int len = 0;
-+
-+	if (cnt < sizeof(ipts_status_fmt) - 3)
-+		return -EINVAL;
-+
-+	len = scnprintf(status, 256, ipts_status_fmt, ipts->sensor_mode,
-+						     ipts->state);
-+	if (len < 0)
-+		return -EIO;
-+
-+	return simple_read_from_buffer(ubuf, cnt, ppos, status, len);
-+}
-+
-+static const struct file_operations ipts_status_dbgfs_fops = {
-+        .open = simple_open,
-+        .read = ipts_dbgfs_status_read,
-+        .llseek = generic_file_llseek,
-+};
-+
-+void ipts_dbgfs_deregister(ipts_info_t* ipts)
-+{
-+	if (!ipts->dbgfs_dir)
-+		return;
-+
-+	debugfs_remove_recursive(ipts->dbgfs_dir);
-+	ipts->dbgfs_dir = NULL;
-+}
-+
-+int ipts_dbgfs_register(ipts_info_t* ipts, const char *name)
-+{
-+	struct dentry *dir, *f;
-+
-+	dir = debugfs_create_dir(name, NULL);
-+	if (!dir)
-+		return -ENOMEM;
-+
-+        f = debugfs_create_file("mode", S_IRUSR | S_IWUSR, dir,
-+                                ipts, &ipts_mode_dbgfs_fops);
-+        if (!f) {
-+                ipts_err(ipts, "debugfs mode creation failed\n");
-+                goto err;
-+        }
-+
-+        f = debugfs_create_file("status", S_IRUSR, dir,
-+                                ipts, &ipts_status_dbgfs_fops);
-+        if (!f) {
-+                ipts_err(ipts, "debugfs status creation failed\n");
-+                goto err;
-+        }
-+
-+	ipts->dbgfs_dir = dir;
-+
-+	return 0;
-+err:
-+	ipts_dbgfs_deregister(ipts);
-+	return -ENODEV;
-+}
-diff --git a/drivers/misc/ipts/ipts-gfx.c b/drivers/misc/ipts/ipts-gfx.c
-new file mode 100644
-index 0000000..5172777
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-gfx.c
-@@ -0,0 +1,184 @@
-+/*
-+ *
-+ * Intel Integrated Touch Gfx Interface Layer
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/kthread.h>
-+#include <linux/delay.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-state.h"
-+
-+static void gfx_processing_complete(void *data)
-+{
-+	ipts_info_t *ipts = data;
-+
-+	if (ipts_get_state(ipts) == IPTS_STA_RAW_DATA_STARTED) {
-+		schedule_work(&ipts->raw_data_work);
-+		return;
-+	}
-+
-+	ipts_dbg(ipts, "not ready to handle gfx event\n");
-+}
-+
-+static void notify_gfx_status(u32 status, void *data)
-+{
-+	ipts_info_t *ipts = data;
-+
-+	ipts->gfx_status = status;
-+	schedule_work(&ipts->gfx_status_work);
-+}
-+
-+static int connect_gfx(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	intel_ipts_connect_t ipts_connect;
-+
-+	ipts_connect.if_version = IPTS_INTERFACE_V1;
-+	ipts_connect.ipts_cb.workload_complete = gfx_processing_complete;
-+	ipts_connect.ipts_cb.notify_gfx_status = notify_gfx_status;
-+	ipts_connect.data = (void*)ipts;
-+
-+	ret = intel_ipts_connect(&ipts_connect);
-+	if (ret)
-+		return ret;
-+
-+	/* TODO: gfx version check */
-+	ipts->gfx_info.gfx_handle = ipts_connect.gfx_handle;
-+	ipts->gfx_info.ipts_ops = ipts_connect.ipts_ops;
-+
-+	return ret;
-+}
-+
-+static void disconnect_gfx(ipts_info_t *ipts)
-+{
-+	intel_ipts_disconnect(ipts->gfx_info.gfx_handle);
-+}
-+
-+#ifdef RUN_DBG_THREAD
-+#include "../mei/mei_dev.h"
-+
-+static struct task_struct *dbg_thread;
-+
-+static void ipts_print_dbg_info(ipts_info_t* ipts)
-+{
-+        char fw_sts_str[MEI_FW_STATUS_STR_SZ];
-+	u32 *db, *head, *tail;
-+	intel_ipts_wq_info_t* wq_info;
-+
-+	wq_info = &ipts->resource.wq_info;
-+
-+	mei_fw_status_str(ipts->cldev->bus, fw_sts_str, MEI_FW_STATUS_STR_SZ);
-+	pr_info(">> tdt : fw status : %s\n", fw_sts_str);
-+
-+	db = (u32*)wq_info->db_addr;
-+	head = (u32*)wq_info->wq_head_addr;
-+	tail = (u32*)wq_info->wq_tail_addr;
-+	pr_info(">> == DB s:%x, c:%x ==\n", *db, *(db+1));
-+	pr_info(">> == WQ h:%u, t:%u ==\n", *head, *tail);
-+}
-+
-+static int ipts_dbg_thread(void *data)
-+{
-+	ipts_info_t *ipts = (ipts_info_t *)data;
-+
-+	pr_info(">> start debug thread\n");
-+
-+	while (!kthread_should_stop()) {
-+		if (ipts_get_state(ipts) != IPTS_STA_RAW_DATA_STARTED) {
-+			pr_info("state is not IPTS_STA_RAW_DATA_STARTED : %d\n",
-+							ipts_get_state(ipts));
-+			msleep(5000);
-+			continue;
-+		}
-+
-+		ipts_print_dbg_info(ipts);
-+
-+		msleep(3000);
-+	}
-+
-+	return 0;
-+}
-+#endif
-+
-+int ipts_open_gpu(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ret = connect_gfx(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot connect GPU\n");
-+		return ret;
-+	}
-+
-+	ret = ipts->gfx_info.ipts_ops.get_wq_info(ipts->gfx_info.gfx_handle,
-+							&ipts->resource.wq_info);
-+	if (ret) {
-+		ipts_dbg(ipts, "error in get_wq_info\n");
-+		return ret;
-+	}
-+
-+#ifdef	RUN_DBG_THREAD
-+	dbg_thread = kthread_run(ipts_dbg_thread, (void *)ipts, "ipts_debug");
-+#endif
-+
-+	return 0;
-+}
-+
-+void ipts_close_gpu(ipts_info_t *ipts)
-+{
-+	disconnect_gfx(ipts);
-+
-+#ifdef	RUN_DBG_THREAD
-+	kthread_stop(dbg_thread);
-+#endif
-+}
-+
-+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags)
-+{
-+	intel_ipts_mapbuffer_t *buf;
-+	u64 handle;
-+	int ret;
-+
-+	buf = devm_kzalloc(&ipts->cldev->dev, sizeof(*buf), GFP_KERNEL);
-+	if (!buf)
-+		return NULL;
-+
-+	buf->size = size;
-+	buf->flags = flags;
-+
-+	handle = ipts->gfx_info.gfx_handle;
-+	ret = ipts->gfx_info.ipts_ops.map_buffer(handle, buf);
-+	if (ret) {
-+		devm_kfree(&ipts->cldev->dev, buf);
-+		return NULL;
-+	}
-+
-+	return buf;
-+}
-+
-+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf)
-+{
-+	u64 handle;
-+	int ret;
-+
-+	if (!buf)
-+		return;
-+
-+	handle = ipts->gfx_info.gfx_handle;
-+	ret = ipts->gfx_info.ipts_ops.unmap_buffer(handle, buf->buf_handle);
-+
-+	devm_kfree(&ipts->cldev->dev, buf);
-+}
-diff --git a/drivers/misc/ipts/ipts-gfx.h b/drivers/misc/ipts/ipts-gfx.h
-new file mode 100644
-index 0000000..03a5f35
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-gfx.h
-@@ -0,0 +1,24 @@
-+/*
-+ * Intel Precise Touch & Stylus gpu wrapper
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+
-+#ifndef _IPTS_GFX_H_
-+#define _IPTS_GFX_H_
-+
-+int ipts_open_gpu(ipts_info_t *ipts);
-+void ipts_close_gpu(ipts_info_t *ipts);
-+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags);
-+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf);
-+
-+#endif // _IPTS_GFX_H_
-diff --git a/drivers/misc/ipts/ipts-hid.c b/drivers/misc/ipts/ipts-hid.c
-new file mode 100644
-index 0000000..3b3be61
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-hid.c
-@@ -0,0 +1,456 @@
-+/*
-+ * Intel Precise Touch & Stylus HID driver
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/module.h>
-+#include <linux/firmware.h>
-+#include <linux/hid.h>
-+#include <linux/vmalloc.h>
-+
-+#include "ipts.h"
-+#include "ipts-resource.h"
-+#include "ipts-sensor-regs.h"
-+#include "ipts-msg-handler.h"
-+
-+#define BUS_MEI				0x44
-+
-+#define	HID_DESC_INTEL	"intel/ipts/intel_desc.bin"
-+#define	HID_DESC_VENDOR	"intel/ipts/vendor_desc.bin"
-+MODULE_FIRMWARE(HID_DESC_INTEL);
-+MODULE_FIRMWARE(HID_DESC_VENDOR);
-+
-+typedef enum output_buffer_payload_type {
-+	OUTPUT_BUFFER_PAYLOAD_ERROR = 0,
-+	OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT,
-+	OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT,
-+	OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD,
-+	OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER
-+} output_buffer_payload_type_t;
-+
-+typedef struct kernel_output_buffer_header {
-+	u16 length;
-+	u8 payload_type;
-+	u8 reserved1;
-+	touch_hid_private_data_t hid_private_data;
-+	u8 reserved2[28];
-+	u8 data[0];
-+} kernel_output_buffer_header_t;
-+
-+typedef struct kernel_output_payload_error {
-+	u16 severity;
-+	u16 source;
-+	u8 code[4];
-+	char string[128];
-+} kernel_output_payload_error_t;
-+
-+static int ipts_hid_get_hid_descriptor(ipts_info_t *ipts, u8 **desc, int *size)
-+{
-+	u8 *buf;
-+	int hid_size = 0, ret = 0;
-+	const struct firmware *intel_desc = NULL;
-+	const struct firmware *vendor_desc = NULL;
-+	const char *intel_desc_path = HID_DESC_INTEL;
-+	const char *vendor_desc_path = HID_DESC_VENDOR;
-+
-+	ret = request_firmware(&intel_desc, intel_desc_path, &ipts->cldev->dev);
-+	if (ret) {
-+		goto no_hid;
-+	}
-+	hid_size = intel_desc->size;
-+
-+	ret = request_firmware(&vendor_desc, vendor_desc_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_dbg(ipts, "error in reading HID Vendor Descriptor\n");
-+	} else {
-+		hid_size += vendor_desc->size;
-+	}
-+
-+	ipts_dbg(ipts, "hid size = %d\n", hid_size);
-+	buf = vmalloc(hid_size);
-+	if (buf == NULL) {
-+		ret = -ENOMEM;
-+		goto no_mem;
-+	}
-+
-+	memcpy(buf, intel_desc->data, intel_desc->size);
-+	if (vendor_desc) {
-+		memcpy(&buf[intel_desc->size], vendor_desc->data,
-+							vendor_desc->size);
-+		release_firmware(vendor_desc);
-+	}
-+
-+	release_firmware(intel_desc);
-+
-+	*desc = buf;
-+	*size = hid_size;
-+
-+	return 0;
-+no_mem :
-+	if (vendor_desc)
-+		release_firmware(vendor_desc);
-+	release_firmware(intel_desc);
-+
-+no_hid :
-+	return ret;
-+}
-+
-+static int ipts_hid_parse(struct hid_device *hid)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	int ret = 0, size;
-+	u8 *buf;
-+
-+	ipts_dbg(ipts, "ipts_hid_parse() start\n");
-+	ret = ipts_hid_get_hid_descriptor(ipts, &buf, &size);
-+	if (ret != 0) {
-+		ipts_dbg(ipts, "ipts_hid_ipts_get_hid_descriptor ret %d\n", ret);
-+		return -EIO;
-+	}
-+
-+	ret = hid_parse_report(hid, buf, size);
-+	vfree(buf);
-+	if (ret) {
-+		ipts_err(ipts, "hid_parse_report error : %d\n", ret);
-+		goto out;
-+	}
-+
-+	ipts->hid_desc_ready = true;
-+out:
-+	return ret;
-+}
-+
-+static int ipts_hid_start(struct hid_device *hid)
-+{
-+	return 0;
-+}
-+
-+static void ipts_hid_stop(struct hid_device *hid)
-+{
-+	return;
-+}
-+
-+static int ipts_hid_open(struct hid_device *hid)
-+{
-+	return 0;
-+}
-+
-+static void ipts_hid_close(struct hid_device *hid)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+
-+	ipts->hid_desc_ready = false;
-+
-+	return;
-+}
-+
-+static int ipts_hid_send_hid2me_feedback(ipts_info_t *ipts, u32 fb_data_type,
-+							__u8 *buf, size_t count)
-+{
-+	ipts_buffer_info_t *fb_buf;
-+	touch_feedback_hdr_t *feedback;
-+	u8 *payload;
-+	int header_size;
-+	ipts_state_t state;
-+
-+	header_size = sizeof(touch_feedback_hdr_t);
-+
-+	if (count > ipts->resource.hid2me_buffer_size - header_size)
-+		return -EINVAL;
-+
-+	state = ipts_get_state(ipts);
-+	if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED)
-+		return 0;
-+
-+	fb_buf = ipts_get_hid2me_buffer(ipts);
-+	feedback = (touch_feedback_hdr_t *)fb_buf->addr;
-+	payload = fb_buf->addr + header_size;
-+	memset(feedback, 0, header_size);
-+
-+	feedback->feedback_data_type = fb_data_type;
-+	feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE;
-+	feedback->payload_size_bytes = count;
-+	feedback->buffer_id = TOUCH_HID_2_ME_BUFFER_ID;
-+	feedback->protocol_ver = 0;
-+	feedback->reserved[0] = 0xAC;
-+
-+	/* copy payload */
-+	memcpy(payload, buf, count);
-+
-+	ipts_send_feedback(ipts, TOUCH_HID_2_ME_BUFFER_ID, 0);
-+
-+	return 0;
-+}
-+
-+static int ipts_hid_raw_request(struct hid_device *hid,
-+				unsigned char report_number, __u8 *buf,
-+				size_t count, unsigned char report_type,
-+				int reqtype)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	u32 fb_data_type;
-+
-+	ipts_dbg(ipts, "hid raw request => report %d, request %d\n",
-+						 (int)report_type, reqtype);
-+
-+	if (report_type != HID_FEATURE_REPORT)
-+		return 0;
-+
-+	switch (reqtype) {
-+		case HID_REQ_GET_REPORT:
-+			fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES;
-+			break;
-+		case HID_REQ_SET_REPORT:
-+			fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES;
-+			break;
-+		default:
-+			ipts_err(ipts, "raw request not supprted: %d\n", reqtype);
-+			return -EIO;
-+	}
-+
-+	return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count);
-+}
-+
-+static int ipts_hid_output_report(struct hid_device *hid,
-+					__u8 *buf, size_t count)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	u32 fb_data_type;
-+
-+	ipts_dbg(ipts, "hid output report\n");
-+
-+	fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT;
-+
-+	return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count);
-+}
-+
-+static struct hid_ll_driver ipts_hid_ll_driver = {
-+	.parse = ipts_hid_parse,
-+	.start = ipts_hid_start,
-+	.stop = ipts_hid_stop,
-+	.open = ipts_hid_open,
-+	.close = ipts_hid_close,
-+	.raw_request = ipts_hid_raw_request,
-+	.output_report = ipts_hid_output_report,
-+};
-+
-+int ipts_hid_init(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	struct hid_device *hid;
-+
-+	hid = hid_allocate_device();
-+	if (IS_ERR(hid)) {
-+		ret = PTR_ERR(hid);
-+		goto err_dev;
-+	}
-+
-+	hid->driver_data = ipts;
-+	hid->ll_driver = &ipts_hid_ll_driver;
-+	hid->dev.parent = &ipts->cldev->dev;
-+	hid->bus = BUS_MEI;
-+	hid->version = ipts->device_info.fw_rev;
-+	hid->vendor = ipts->device_info.vendor_id;
-+	hid->product = ipts->device_info.device_id;
-+
-+	snprintf(hid->phys, sizeof(hid->phys), "heci3");
-+	snprintf(hid->name, sizeof(hid->name),
-+		 "%s %04hX:%04hX", "ipts", hid->vendor, hid->product);
-+
-+	ret = hid_add_device(hid);
-+	if (ret) {
-+		if (ret != -ENODEV)
-+			ipts_err(ipts, "can't add hid device: %d\n", ret);
-+		goto err_mem_free;
-+	}
-+
-+	ipts->hid = hid;
-+
-+	return 0;
-+
-+err_mem_free:
-+	hid_destroy_device(hid);
-+err_dev:
-+	return ret;
-+}
-+
-+void ipts_hid_release(ipts_info_t *ipts)
-+{
-+	if (!ipts->hid)
-+			return;
-+	hid_destroy_device(ipts->hid);
-+}
-+
-+int ipts_handle_hid_data(ipts_info_t *ipts,
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp)
-+{
-+	touch_raw_data_hdr_t *raw_header;
-+	ipts_buffer_info_t *buffer_info;
-+	touch_feedback_hdr_t *feedback;
-+	u8 *raw_data;
-+	int touch_data_buffer_index;
-+	int transaction_id;
-+	int ret = 0;
-+
-+	touch_data_buffer_index = (int)hid_rsp->touch_data_buffer_index;
-+	buffer_info = ipts_get_touch_data_buffer_hid(ipts);
-+	raw_header = (touch_raw_data_hdr_t *)buffer_info->addr;
-+	transaction_id = raw_header->hid_private_data.transaction_id;
-+
-+	raw_data = (u8*)raw_header + sizeof(touch_raw_data_hdr_t);
-+	if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_HID_REPORT) {
-+		memcpy(ipts->hid_input_report, raw_data,
-+				raw_header->raw_data_size_bytes);
-+
-+		ret = hid_input_report(ipts->hid, HID_INPUT_REPORT,
-+					(u8*)ipts->hid_input_report,
-+					raw_header->raw_data_size_bytes, 1);
-+		if (ret) {
-+			ipts_err(ipts, "error in hid_input_report : %d\n", ret);
-+		}
-+	} else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_GET_FEATURES) {
-+		/* TODO: implement together with "get feature ioctl" */
-+	} else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_ERROR) {
-+		touch_error_t *touch_err = (touch_error_t *)raw_data;
-+
-+		ipts_err(ipts, "error type : %d, me fw error : %x, err reg : %x\n",
-+				touch_err->touch_error_type,
-+				touch_err->touch_me_fw_error.value,
-+				touch_err->touch_error_register.reg_value);
-+	}
-+
-+	/* send feedback data for HID mode */
-+        buffer_info = ipts_get_feedback_buffer(ipts, touch_data_buffer_index);
-+	feedback = (touch_feedback_hdr_t *)buffer_info->addr;
-+	memset(feedback, 0, sizeof(touch_feedback_hdr_t));
-+	feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE;
-+	feedback->payload_size_bytes = 0;
-+	feedback->buffer_id = touch_data_buffer_index;
-+	feedback->protocol_ver = 0;
-+	feedback->reserved[0] = 0xAC;
-+
-+	ret = ipts_send_feedback(ipts, touch_data_buffer_index, transaction_id);
-+
-+	return ret;
-+}
-+
-+static int handle_outputs(ipts_info_t *ipts, int parallel_idx)
-+{
-+	kernel_output_buffer_header_t *out_buf_hdr;
-+	ipts_buffer_info_t *output_buf, *fb_buf = NULL;
-+	u8 *input_report, *payload;
-+	u32 transaction_id;
-+	int i, payload_size, ret = 0, header_size;
-+
-+	header_size = sizeof(kernel_output_buffer_header_t);
-+	output_buf = ipts_get_output_buffers_by_parallel_id(ipts, parallel_idx);
-+	for (i = 0; i < ipts->resource.num_of_outputs; i++) {
-+		out_buf_hdr = (kernel_output_buffer_header_t*)output_buf[i].addr;
-+		if (out_buf_hdr->length < header_size)
-+			continue;
-+
-+		payload_size = out_buf_hdr->length - header_size;
-+		payload = out_buf_hdr->data;
-+
-+		switch(out_buf_hdr->payload_type) {
-+			case OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT:
-+				input_report = ipts->hid_input_report;
-+				memcpy(input_report, payload, payload_size);
-+				hid_input_report(ipts->hid, HID_INPUT_REPORT,
-+						input_report, payload_size, 1);
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT:
-+				ipts_dbg(ipts, "output hid feature report\n");
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD:
-+				ipts_dbg(ipts, "output kernel load\n");
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER:
-+			{
-+				/* send feedback data for raw data mode */
-+                                fb_buf = ipts_get_feedback_buffer(ipts,
-+								parallel_idx);
-+				transaction_id = out_buf_hdr->
-+						hid_private_data.transaction_id;
-+				memcpy(fb_buf->addr, payload, payload_size);
-+				break;
-+			}
-+			case OUTPUT_BUFFER_PAYLOAD_ERROR:
-+			{
-+				kernel_output_payload_error_t *err_payload;
-+
-+				if (payload_size == 0)
-+					break;
-+
-+				err_payload =
-+					(kernel_output_payload_error_t*)payload;
-+
-+				ipts_err(ipts, "error : severity : %d,"
-+						" source : %d,"
-+						" code : %d:%d:%d:%d\n"
-+						"string %s\n",
-+						err_payload->severity,
-+						err_payload->source,
-+						err_payload->code[0],
-+						err_payload->code[1],
-+						err_payload->code[2],
-+						err_payload->code[3],
-+						err_payload->string);
-+				
-+				break;
-+			}
-+			default:
-+				ipts_err(ipts, "invalid output buffer payload\n");
-+				break;
-+		}
-+	}
-+
-+	if (fb_buf) {
-+		ret = ipts_send_feedback(ipts, parallel_idx, transaction_id);
-+		if (ret)
-+			return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static int handle_output_buffers(ipts_info_t *ipts, int cur_idx, int end_idx)
-+{
-+	int max_num_of_buffers = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	do {
-+		cur_idx++; /* cur_idx has last completed so starts with +1 */
-+		cur_idx %= max_num_of_buffers;
-+		handle_outputs(ipts, cur_idx);
-+	} while (cur_idx != end_idx);
-+
-+	return 0;
-+}
-+
-+int ipts_handle_processed_data(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	int current_buffer_idx;
-+	int last_buffer_idx;
-+
-+	current_buffer_idx = *ipts->last_submitted_id;
-+	last_buffer_idx = ipts->last_buffer_completed;
-+
-+	if (current_buffer_idx == last_buffer_idx)
-+		return 0;
-+
-+	ipts->last_buffer_completed = current_buffer_idx;
-+	handle_output_buffers(ipts, last_buffer_idx, current_buffer_idx);
-+
-+	return ret;
-+}
-diff --git a/drivers/misc/ipts/ipts-hid.h b/drivers/misc/ipts/ipts-hid.h
-new file mode 100644
-index 0000000..f1b22c9
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-hid.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Intel Precise Touch & Stylus HID definition
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_HID_H_
-+#define	_IPTS_HID_H_
-+
-+#define	BUS_MEI				0x44
-+
-+#if 0 /* TODO : we have special report ID. will implement them */
-+#define WRITE_CHANNEL_REPORT_ID		0xa
-+#define READ_CHANNEL_REPORT_ID		0xb
-+#define CONFIG_CHANNEL_REPORT_ID	0xd
-+#define VENDOR_INFO_REPORT_ID		0xF
-+#define SINGLE_TOUCH_REPORT_ID		0x40
-+#endif
-+
-+int ipts_hid_init(ipts_info_t *ipts);
-+void ipts_hid_release(ipts_info_t *ipts);
-+int ipts_handle_hid_data(ipts_info_t *ipts,
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp);
-+
-+#endif /* _IPTS_HID_H_ */
-diff --git a/drivers/misc/ipts/ipts-kernel.c b/drivers/misc/ipts/ipts-kernel.c
-new file mode 100644
-index 0000000..ca5e24c
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-kernel.c
-@@ -0,0 +1,1050 @@
-+#include <linux/module.h>
-+#include <linux/firmware.h>
-+#include <linux/vmalloc.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-resource.h"
-+#include "ipts-binary-spec.h"
-+#include "ipts-state.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-gfx.h"
-+
-+#define MAX_IOCL_FILE_NAME_LEN		80
-+#define MAX_IOCL_FILE_PATH_LEN		256
-+
-+#pragma pack(1)
-+typedef struct bin_data_file_info {
-+    u32 io_buffer_type;
-+    u32 flags;
-+    char file_name[MAX_IOCL_FILE_NAME_LEN];
-+} bin_data_file_info_t;
-+
-+typedef struct bin_fw_info {
-+	char fw_name[MAX_IOCL_FILE_NAME_LEN];
-+
-+	/* list of parameters to load a kernel */
-+	s32 vendor_output;	/* output index. -1 for no use */
-+	u32 num_of_data_files;
-+	bin_data_file_info_t data_file[];
-+} bin_fw_info_t;
-+
-+typedef struct bin_fw_list {
-+	u32 num_of_fws;
-+	bin_fw_info_t fw_info[];
-+} bin_fw_list_t;
-+#pragma pack()
-+
-+/* OpenCL kernel */
-+typedef struct bin_workload {
-+	int cmdbuf_index;
-+	int iobuf_input;
-+	int iobuf_output[MAX_NUM_OUTPUT_BUFFERS];
-+} bin_workload_t;
-+
-+typedef struct bin_buffer {
-+	unsigned int handle;
-+	intel_ipts_mapbuffer_t *buf;
-+	bool no_unmap;	/* only releasing vendor kernel unmaps output buffers */
-+} bin_buffer_t;
-+
-+typedef struct bin_alloc_info {
-+	bin_buffer_t *buffs;
-+	int num_of_allocations;
-+	int num_of_outputs;
-+
-+	int num_of_buffers;
-+} bin_alloc_info_t;
-+
-+typedef struct bin_guc_wq_item {
-+	unsigned int batch_offset;
-+	unsigned int size;
-+	char data[];
-+} bin_guc_wq_item_t;
-+
-+typedef struct bin_kernel_info {
-+	bin_workload_t *wl;
-+	bin_alloc_info_t *alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item;
-+	ipts_bin_bufid_patch_t bufid_patch;
-+
-+	bool is_vendor; /* 1: vendor, 0: postprocessing */
-+} bin_kernel_info_t;
-+
-+typedef struct bin_kernel_list {
-+	intel_ipts_mapbuffer_t *bufid_buf;
-+	int num_of_kernels;
-+	bin_kernel_info_t kernels[];
-+} bin_kernel_list_t;
-+
-+typedef struct bin_parse_info {
-+	u8 *data;
-+	int size;
-+	int parsed;
-+
-+	bin_fw_info_t *fw_info;
-+
-+	/* only used by postprocessing */
-+	bin_kernel_info_t *vendor_kernel;
-+	u32 interested_vendor_output; /* interested vendor output index */
-+} bin_parse_info_t;
-+
-+#define BDW_SURFACE_BASE_ADDRESS		0x6101000e
-+#define SURFACE_STATE_OFFSET_WORD		4
-+#define SBA_OFFSET_BYTES			16384
-+#define LASTSUBMITID_DEFAULT_VALUE		-1
-+
-+#define IPTS_FW_PATH_FMT			"intel/ipts/%s"
-+#define IPTS_FW_CONFIG_FILE			"intel/ipts/ipts_fw_config.bin"
-+
-+MODULE_FIRMWARE(IPTS_FW_CONFIG_FILE);
-+
-+#define IPTS_INPUT_ON				((u32)1 << IPTS_INPUT)
-+#define IPTS_OUTPUT_ON				((u32)1 << IPTS_OUTPUT)
-+#define IPTS_CONFIGURATION_ON			((u32)1 << IPTS_CONFIGURATION)
-+#define IPTS_CALIBRATION_ON			((u32)1 << IPTS_CALIBRATION)
-+#define IPTS_FEATURE_ON				((u32)1 << IPTS_FEATURE)
-+
-+#define	DATA_FILE_FLAG_SHARE			0x00000001
-+#define	DATA_FILE_FLAG_ALLOC_CONTIGUOUS		0x00000002
-+
-+static int bin_read_fw(ipts_info_t *ipts, const char *fw_name,
-+						u8* data, int size)
-+{
-+	const struct firmware *fw = NULL;
-+	char fw_path[MAX_IOCL_FILE_PATH_LEN];
-+	int ret = 0;
-+
-+	snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name);
-+	ret = request_firmware(&fw, fw_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_err(ipts, "cannot read fw %s\n", fw_path);
-+		return ret;
-+	}
-+
-+	if (fw->size > size) {
-+		ipts_dbg(ipts, "too small buffer to contain fw data\n");
-+		ret = -EINVAL;
-+		goto rel_return;
-+	}
-+
-+	memcpy(data, fw->data, fw->size);
-+
-+rel_return:
-+	release_firmware(fw);
-+
-+	return ret;
-+}
-+
-+
-+static bin_data_file_info_t* bin_get_data_file_info(bin_fw_info_t* fw_info,
-+							u32 io_buffer_type)
-+{
-+	int i;
-+
-+	for (i = 0; i < fw_info->num_of_data_files; i++) {
-+		if (fw_info->data_file[i].io_buffer_type == io_buffer_type)
-+			break;
-+	}
-+
-+	if (i == fw_info->num_of_data_files)
-+		return NULL;
-+
-+	return &fw_info->data_file[i];
-+}
-+
-+static inline bool is_shared_data(const bin_data_file_info_t *data_file)
-+{
-+	if (data_file)
-+		return (!!(data_file->flags & DATA_FILE_FLAG_SHARE));
-+
-+	return false;
-+}
-+
-+static inline bool is_alloc_cont_data(const bin_data_file_info_t *data_file)
-+{
-+	if (data_file)
-+		return (!!(data_file->flags & DATA_FILE_FLAG_ALLOC_CONTIGUOUS));
-+
-+	return false;
-+}
-+
-+static inline bool is_parsing_vendor_kernel(const bin_parse_info_t *parse_info)
-+{
-+	/* vendor_kernel == null while loading itself(vendor kernel) */
-+	return parse_info->vendor_kernel == NULL;
-+}
-+
-+static int bin_read_allocation_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info)
-+{
-+	ipts_bin_alloc_list_t *alloc_list;
-+	int alloc_idx, parallel_idx, num_of_parallels, buf_idx, num_of_buffers;
-+	int parsed, size;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+
-+	alloc_list = (ipts_bin_alloc_list_t *)&parse_info->data[parsed];
-+
-+	/* validation check */
-+	if (sizeof(alloc_list->num) > size - parsed)
-+		return -EINVAL;
-+
-+	/* read the number of aloocations */
-+	parsed += sizeof(alloc_list->num);
-+
-+	/* validation check */
-+	if (sizeof(alloc_list->alloc[0]) * alloc_list->num > size - parsed)
-+		return -EINVAL;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	num_of_buffers = num_of_parallels * alloc_list->num + num_of_parallels;
-+
-+	alloc_info->buffs = vmalloc(sizeof(bin_buffer_t) * num_of_buffers);
-+	if (alloc_info->buffs == NULL)
-+		return -ENOMEM;
-+
-+	memset(alloc_info->buffs, 0, sizeof(bin_buffer_t) * num_of_buffers);
-+	for (alloc_idx = 0; alloc_idx < alloc_list->num; alloc_idx++) {
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+								parallel_idx++) {
-+			buf_idx = alloc_idx + (parallel_idx * alloc_list->num);
-+			alloc_info->buffs[buf_idx].handle =
-+					alloc_list->alloc[alloc_idx].handle;
-+
-+		}
-+
-+		parsed += sizeof(alloc_list->alloc[0]);
-+	}
-+
-+	parse_info->parsed = parsed;
-+	alloc_info->num_of_allocations = alloc_list->num;
-+	alloc_info->num_of_buffers = num_of_buffers;
-+
-+	ipts_dbg(ipts, "number of allocations = %d, buffers = %d\n",
-+						alloc_info->num_of_allocations,
-+						alloc_info->num_of_buffers);
-+
-+	return 0;
-+}
-+
-+static void patch_SBA(u32 *buf_addr, u64 gpu_addr, int size)
-+{
-+	u64 *stateBase;
-+	u64 SBA;
-+	u32 inst;
-+	int i;
-+
-+	SBA = gpu_addr + SBA_OFFSET_BYTES;
-+
-+	for (i = 0; i < size/4; i++) {
-+		inst = buf_addr[i];
-+		if (inst == BDW_SURFACE_BASE_ADDRESS) {
-+			stateBase = (u64*)&buf_addr[i + SURFACE_STATE_OFFSET_WORD];
-+			*stateBase |= SBA;
-+			*stateBase |= 0x01; // enable
-+			break;
-+		}
-+	}
-+}
-+
-+static int bin_read_cmd_buffer(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_cmdbuf_t *cmd;
-+	intel_ipts_mapbuffer_t *buf;
-+	int cmdbuf_idx, size, parsed, parallel_idx, num_of_parallels;
-+
-+	size = parse_info->size;
-+	parsed = parse_info->parsed;
-+
-+	cmd = (ipts_bin_cmdbuf_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(cmd->size) > size - parsed)
-+		return -EINVAL;
-+
-+	parsed += sizeof(cmd->size);
-+	if (cmd->size > size - parsed)
-+		return -EINVAL;
-+
-+	ipts_dbg(ipts, "cmd buf size = %d\n", cmd->size);
-+		
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	/* command buffers are located after the other allocations */
-+	cmdbuf_idx = num_of_parallels * alloc_info->num_of_allocations;
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		buf = ipts_map_buffer(ipts, cmd->size, 0);
-+		if (buf == NULL)
-+			return -ENOMEM;
-+
-+		ipts_dbg(ipts, "cmd_idx[%d] = %d, g:0x%p, c:0x%p\n", parallel_idx,
-+					cmdbuf_idx, buf->gfx_addr, buf->cpu_addr);
-+
-+		memcpy((void *)buf->cpu_addr, &(cmd->data[0]), cmd->size);
-+		patch_SBA(buf->cpu_addr, (u64)buf->gfx_addr, cmd->size);
-+		alloc_info->buffs[cmdbuf_idx].buf = buf;
-+		wl[parallel_idx].cmdbuf_index = cmdbuf_idx;
-+
-+		cmdbuf_idx++;
-+	}
-+
-+	parsed += cmd->size;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_find_alloc(ipts_info_t *ipts,
-+					bin_alloc_info_t *alloc_info,
-+					u32 handle)
-+{
-+	int i;
-+
-+	for (i = 0; i < alloc_info->num_of_allocations; i++) {
-+		if (alloc_info->buffs[i].handle == handle)
-+			return i;
-+	}
-+
-+	return -1;
-+}
-+
-+static intel_ipts_mapbuffer_t* bin_get_vendor_kernel_output(
-+						bin_parse_info_t *parse_info,
-+						int parallel_idx)
-+{
-+	bin_kernel_info_t *vendor = parse_info->vendor_kernel;
-+	bin_alloc_info_t *alloc_info;
-+	int buf_idx, vendor_output_idx;
-+
-+	alloc_info = vendor->alloc_info;
-+	vendor_output_idx = parse_info->interested_vendor_output;
-+
-+	if (vendor_output_idx >= alloc_info->num_of_outputs)
-+		return NULL;
-+
-+	buf_idx = vendor->wl[parallel_idx].iobuf_output[vendor_output_idx];
-+	return alloc_info->buffs[buf_idx].buf;
-+}
-+
-+static int bin_read_res_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_res_list_t *res_list;
-+	ipts_bin_res_t *res;
-+	intel_ipts_mapbuffer_t *buf;
-+	bin_data_file_info_t *data_file;
-+	u8 *bin_data;
-+	int i, size, parsed, parallel_idx, num_of_parallels, output_idx = -1;
-+	int buf_idx, num_of_alloc;
-+	u32 buf_size, flags, io_buf_type;
-+	bool initialize;
-+	
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	bin_data = parse_info->data;
-+
-+	res_list = (ipts_bin_res_list_t *)&parse_info->data[parsed];
-+	if (sizeof(res_list->num) > (size - parsed))
-+		return -EINVAL;
-+	parsed += sizeof(res_list->num);
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	ipts_dbg(ipts, "number of resources %u\n", res_list->num);
-+	for (i = 0; i < res_list->num; i++) {
-+		initialize = false; 
-+		io_buf_type = 0;
-+		flags = 0;
-+
-+		/* initial data */
-+		data_file = NULL;
-+
-+		res = (ipts_bin_res_t *)(&(bin_data[parsed]));
-+		if (sizeof(res[0]) > (size - parsed)) {
-+			return -EINVAL;
-+		}
-+
-+		ipts_dbg(ipts, "Resource(%d):handle 0x%08x type %u init %u"
-+				" size %u alsigned %u\n",
-+				i, res->handle, res->type, res->initialize,
-+				res->size, res->aligned_size);
-+                parsed += sizeof(res[0]);
-+
-+		if (res->initialize) {
-+			if (res->size > (size - parsed)) {
-+				return -EINVAL;
-+			}
-+			parsed += res->size;
-+		}
-+
-+		initialize = res->initialize;
-+		if (initialize && res->size > sizeof(ipts_bin_io_header_t)) {
-+			ipts_bin_io_header_t *io_hdr;
-+			io_hdr = (ipts_bin_io_header_t *)(&res->data[0]);
-+			if (strncmp(io_hdr->str, "INTELTOUCH", 10) == 0) {
-+				data_file = bin_get_data_file_info(
-+							parse_info->fw_info,
-+							(u32)io_hdr->type);
-+				switch (io_hdr->type) {
-+				case IPTS_INPUT:
-+					ipts_dbg(ipts, "input detected\n");
-+					io_buf_type = IPTS_INPUT_ON;
-+					flags = IPTS_BUF_FLAG_CONTIGUOUS;
-+					break;
-+				case IPTS_OUTPUT:
-+					ipts_dbg(ipts, "output detected\n");
-+					io_buf_type = IPTS_OUTPUT_ON;
-+					output_idx++;
-+					break;
-+				default:
-+					if ((u32)io_hdr->type > 31) {
-+						ipts_err(ipts,
-+							"invalid io buffer : %u\n",
-+							(u32)io_hdr->type);
-+						continue;
-+					}
-+
-+					if (is_alloc_cont_data(data_file))
-+						flags = IPTS_BUF_FLAG_CONTIGUOUS;
-+
-+					io_buf_type = ((u32)1 << (u32)io_hdr->type);
-+					ipts_dbg(ipts, "special io buffer %u\n",
-+								io_hdr->type);
-+					break;
-+				}
-+
-+				initialize = false;
-+			}
-+		}
-+
-+		num_of_alloc = alloc_info->num_of_allocations;
-+		buf_idx = bin_find_alloc(ipts, alloc_info, res->handle);
-+		if (buf_idx == -1) {
-+			ipts_dbg(ipts, "cannot find alloc info\n");
-+			return -EINVAL;
-+		}
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+					parallel_idx++, buf_idx += num_of_alloc) {
-+			if (!res->aligned_size)
-+				continue;
-+
-+			if (!(parallel_idx == 0 ||
-+				    (io_buf_type && !is_shared_data(data_file))))
-+				continue;
-+
-+			buf_size = res->aligned_size;
-+			if (io_buf_type & IPTS_INPUT_ON) {
-+				buf_size = max_t(u32,
-+						ipts->device_info.frame_size,
-+						buf_size);
-+				wl[parallel_idx].iobuf_input = buf_idx;
-+			} else if (io_buf_type & IPTS_OUTPUT_ON) {
-+				wl[parallel_idx].iobuf_output[output_idx] = buf_idx;
-+
-+				if (!is_parsing_vendor_kernel(parse_info) &&
-+								output_idx > 0) {
-+					ipts_err(ipts,
-+						"postproc with more than one inout"
-+						" is not supported : %d\n", output_idx);
-+					return -EINVAL;
-+				}
-+			}
-+
-+			if (!is_parsing_vendor_kernel(parse_info) &&
-+						io_buf_type & IPTS_OUTPUT_ON) {
-+				buf = bin_get_vendor_kernel_output(
-+								parse_info,
-+								parallel_idx);
-+				alloc_info->buffs[buf_idx].no_unmap = true;
-+			} else
-+				buf = ipts_map_buffer(ipts, buf_size, flags);
-+
-+			if (buf == NULL) {
-+				ipts_dbg(ipts, "ipts_map_buffer failed\n");
-+				return -ENOMEM;
-+			}
-+
-+			if (initialize) {
-+				memcpy((void *)buf->cpu_addr, &(res->data[0]),
-+								res->size);
-+			} else {
-+				if (data_file && strlen(data_file->file_name)) {
-+					bin_read_fw(ipts, data_file->file_name,
-+                                                        buf->cpu_addr, buf_size);
-+				} else if (is_parsing_vendor_kernel(parse_info) ||
-+						!(io_buf_type & IPTS_OUTPUT_ON)) {
-+					memset((void *)buf->cpu_addr, 0, res->size);
-+				}
-+			}
-+
-+			alloc_info->buffs[buf_idx].buf = buf;
-+		}
-+	}
-+
-+        alloc_info->num_of_outputs = output_idx + 1;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_read_patch_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_patch_list_t *patch_list;
-+	ipts_bin_patch_t *patch;
-+	intel_ipts_mapbuffer_t *cmd = NULL;
-+	u8 *batch;
-+	int parsed, size, i, parallel_idx, num_of_parallels, cmd_idx, buf_idx;
-+	unsigned int gtt_offset;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	patch_list = (ipts_bin_patch_list_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(patch_list->num) > (size - parsed)) {
-+		return -EFAULT;
-+	}
-+	parsed += sizeof(patch_list->num);
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	patch = (ipts_bin_patch_t *)(&patch_list->patch[0]);
-+	for (i = 0; i < patch_list->num; i++) {
-+		if (sizeof(patch_list->patch[0]) > (size - parsed)) {
-+			return -EFAULT;
-+		}
-+
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+								parallel_idx++) {
-+			cmd_idx = wl[parallel_idx].cmdbuf_index;
-+			buf_idx = patch[i].index + parallel_idx *
-+						alloc_info->num_of_allocations;
-+
-+			if (alloc_info->buffs[buf_idx].buf == NULL) {
-+				/* buffer shared */
-+				buf_idx = patch[i].index;
-+			}
-+
-+			cmd = alloc_info->buffs[cmd_idx].buf;
-+			batch = (char *)(u64)cmd->cpu_addr;
-+
-+			gtt_offset = 0;
-+			if(alloc_info->buffs[buf_idx].buf != NULL) {
-+				gtt_offset = (u32)(u64)
-+					alloc_info->buffs[buf_idx].buf->gfx_addr;
-+			} 
-+			gtt_offset += patch[i].alloc_offset;
-+
-+			batch += patch[i].patch_offset;
-+			*(u32*)batch = gtt_offset;
-+		}
-+
-+		parsed += sizeof(patch_list->patch[0]);
-+	}
-+
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_read_guc_wq_item(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_guc_wq_item_t **guc_wq_item)
-+{
-+	ipts_bin_guc_wq_info_t *bin_guc_wq;
-+	bin_guc_wq_item_t *item;
-+	u8 *wi_data;
-+	int size, parsed, hdr_size, wi_size;
-+	int i, batch_offset;
-+	
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	bin_guc_wq = (ipts_bin_guc_wq_info_t *)&parse_info->data[parsed];
-+
-+	wi_size = bin_guc_wq->size;
-+	wi_data = bin_guc_wq->data;
-+	batch_offset = bin_guc_wq->batch_offset;
-+	ipts_dbg(ipts, "wi size = %d, bt offset = %d\n", wi_size, batch_offset);
-+	for (i = 0; i < wi_size / sizeof(u32); i++) {
-+		ipts_dbg(ipts, "wi[%d] = 0x%08x\n", i, *((u32*)wi_data + i));
-+	}
-+	hdr_size = sizeof(bin_guc_wq->size) + sizeof(bin_guc_wq->batch_offset);
-+
-+	if (hdr_size > (size - parsed)) {
-+		return -EINVAL;
-+	}
-+	parsed += hdr_size;
-+
-+	item = vmalloc(sizeof(bin_guc_wq_item_t) + wi_size);
-+	if (item == NULL)
-+		return -ENOMEM;
-+
-+	item->size = wi_size;
-+	item->batch_offset = batch_offset;
-+	memcpy(item->data, wi_data, wi_size);
-+
-+	*guc_wq_item = item;
-+
-+	parsed += wi_size;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_setup_guc_workqueue(ipts_info_t *ipts,
-+					bin_kernel_list_t *kernel_list)
-+{
-+	bin_alloc_info_t *alloc_info;
-+	bin_workload_t *wl;
-+	bin_kernel_info_t *kernel;
-+	u8 *wq_start, *wq_addr, *wi_data;
-+	bin_buffer_t *bin_buf;
-+	int wq_size, wi_size, parallel_idx, cmd_idx, k_idx, iter_size;
-+	int i, num_of_parallels, batch_offset, k_num, total_workload;
-+	
-+	wq_addr = (u8*)ipts->resource.wq_info.wq_addr;
-+	wq_size = ipts->resource.wq_info.wq_size;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	total_workload = ipts_get_wq_item_size(ipts);
-+	k_num = kernel_list->num_of_kernels;
-+
-+	iter_size = total_workload * num_of_parallels;
-+	if (wq_size % iter_size) {
-+		ipts_err(ipts, "wq item cannot fit into wq\n");
-+		return -EINVAL;
-+	}
-+
-+	wq_start = wq_addr;
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+							parallel_idx++) {
-+		kernel = &kernel_list->kernels[0];
-+		for (k_idx = 0; k_idx < k_num; k_idx++, kernel++) {
-+			wl = kernel->wl;
-+			alloc_info = kernel->alloc_info;
-+
-+			batch_offset = kernel->guc_wq_item->batch_offset;
-+			wi_size = kernel->guc_wq_item->size;
-+			wi_data = &kernel->guc_wq_item->data[0];
-+			
-+			cmd_idx = wl[parallel_idx].cmdbuf_index;
-+			bin_buf = &alloc_info->buffs[cmd_idx];
-+
-+			/* Patch the WQ Data with proper batch buffer offset */
-+			*(u32*)(wi_data + batch_offset) =
-+				(u32)(unsigned long)(bin_buf->buf->gfx_addr);
-+
-+			memcpy(wq_addr, wi_data, wi_size);
-+
-+			wq_addr += wi_size;
-+		}
-+	}
-+
-+	for (i = 0; i < (wq_size / iter_size) - 1; i++) {
-+		memcpy(wq_addr, wq_start, iter_size);
-+		wq_addr += iter_size;
-+	}
-+
-+	return 0;
-+}
-+
-+static int bin_read_bufid_patch(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					ipts_bin_bufid_patch_t *bufid_patch)
-+{
-+	ipts_bin_bufid_patch_t *patch;
-+	int size, parsed;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	patch = (ipts_bin_bufid_patch_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(ipts_bin_bufid_patch_t) > (size - parsed)) {
-+		ipts_dbg(ipts, "invalid bufid info\n");
-+		return -EINVAL;
-+	}
-+	parsed += sizeof(ipts_bin_bufid_patch_t);
-+
-+	memcpy(bufid_patch, patch, sizeof(ipts_bin_bufid_patch_t));
-+
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_setup_bufid_buffer(ipts_info_t *ipts, bin_kernel_list_t *kernel_list)
-+{
-+	intel_ipts_mapbuffer_t *buf, *cmd_buf;
-+	bin_kernel_info_t *last_kernel;
-+	bin_alloc_info_t *alloc_info;
-+	bin_workload_t *wl;
-+	u8 *batch;
-+	int parallel_idx, num_of_parallels, cmd_idx;
-+	u32 mem_offset, imm_offset;
-+
-+	buf = ipts_map_buffer(ipts, PAGE_SIZE, 0);
-+	if (!buf) {
-+		return -ENOMEM;
-+	}
-+
-+	last_kernel = &kernel_list->kernels[kernel_list->num_of_kernels - 1];
-+
-+	mem_offset = last_kernel->bufid_patch.mem_offset;
-+	imm_offset = last_kernel->bufid_patch.imm_offset;
-+	wl = last_kernel->wl;
-+	alloc_info = last_kernel->alloc_info;
-+
-+	/* Initialize the buffer with default value */
-+        *((u32*)buf->cpu_addr) = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->current_buffer_index = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->last_buffer_completed = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->last_submitted_id = (int*)buf->cpu_addr;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		cmd_idx = wl[parallel_idx].cmdbuf_index;
-+		cmd_buf = alloc_info->buffs[cmd_idx].buf;
-+		batch = (u8*)(u64)cmd_buf->cpu_addr;
-+
-+		*((u32*)(batch + mem_offset)) = (u32)(u64)(buf->gfx_addr);
-+                *((u32*)(batch + imm_offset)) = parallel_idx;
-+	}
-+
-+	kernel_list->bufid_buf = buf;
-+
-+	return 0;
-+}
-+
-+static void unmap_buffers(ipts_info_t *ipts, bin_alloc_info_t *alloc_info)
-+{
-+	bin_buffer_t *buffs;
-+	int i, num_of_buffers;
-+
-+	num_of_buffers = alloc_info->num_of_buffers;
-+	buffs = &alloc_info->buffs[0];
-+
-+	for (i = 0; i < num_of_buffers; i++) {
-+		if (buffs[i].no_unmap != true && buffs[i].buf != NULL)
-+			ipts_unmap_buffer(ipts, buffs[i].buf);
-+	}
-+}
-+
-+static int load_kernel(ipts_info_t *ipts, bin_parse_info_t *parse_info,
-+						bin_kernel_info_t *kernel)
-+{
-+	ipts_bin_header_t *hdr;
-+	bin_workload_t *wl;
-+	bin_alloc_info_t *alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item = NULL;
-+	ipts_bin_bufid_patch_t bufid_patch;
-+	int num_of_parallels, ret;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+        /* check header version and magic numbers */
-+	hdr = (ipts_bin_header_t *)parse_info->data;
-+	if (hdr->version != IPTS_BIN_HEADER_VERSION ||
-+					strncmp(hdr->str, "IOCL", 4) != 0) {
-+		ipts_err(ipts, "binary header is not correct version = %d, "
-+				"string = %c%c%c%c\n", hdr->version,
-+				hdr->str[0], hdr->str[1],
-+				hdr->str[2], hdr->str[3] );
-+		return -EINVAL;
-+	}
-+
-+	parse_info->parsed = sizeof(ipts_bin_header_t);
-+	wl = vmalloc(sizeof(bin_workload_t) * num_of_parallels);
-+	if (wl == NULL)
-+		return -ENOMEM;
-+	memset(wl, 0, sizeof(bin_workload_t) * num_of_parallels);
-+
-+	alloc_info = vmalloc(sizeof(bin_alloc_info_t));
-+	if (alloc_info == NULL) {
-+		vfree(wl);
-+		return -ENOMEM;
-+	}
-+	memset(alloc_info, 0, sizeof(bin_alloc_info_t));
-+
-+        ipts_dbg(ipts, "kernel setup(size : %d)\n", parse_info->size);
-+
-+	ret = bin_read_allocation_list(ipts, parse_info, alloc_info);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_allocation_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_cmd_buffer(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_cmd_buffer\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_res_list(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_res_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_patch_list(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_patch_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_guc_wq_item(ipts, parse_info, &guc_wq_item);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_guc_workqueue\n");
-+		goto setup_error;
-+	}
-+
-+	memset(&bufid_patch, 0, sizeof(bufid_patch));
-+	ret = bin_read_bufid_patch(ipts, parse_info, &bufid_patch);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_bufid_patch\n");
-+		goto setup_error;
-+	}
-+
-+	kernel->wl = wl;
-+	kernel->alloc_info = alloc_info;
-+	kernel->is_vendor = is_parsing_vendor_kernel(parse_info);
-+	kernel->guc_wq_item = guc_wq_item;
-+	memcpy(&kernel->bufid_patch, &bufid_patch, sizeof(bufid_patch));
-+
-+        return 0;
-+
-+setup_error:
-+	vfree(guc_wq_item);
-+
-+	unmap_buffers(ipts, alloc_info);
-+
-+	vfree(alloc_info->buffs);
-+	vfree(alloc_info);
-+	vfree(wl);
-+
-+	return ret;
-+}
-+
-+void bin_setup_input_output(ipts_info_t *ipts, bin_kernel_list_t *kernel_list)
-+{
-+	bin_kernel_info_t *vendor_kernel;
-+	bin_workload_t *wl;
-+	intel_ipts_mapbuffer_t *buf;
-+	bin_alloc_info_t *alloc_info;
-+	int parallel_idx, num_of_parallels, i, buf_idx;
-+
-+	vendor_kernel = &kernel_list->kernels[0];
-+
-+	wl = vendor_kernel->wl;
-+	alloc_info = vendor_kernel->alloc_info;
-+	ipts->resource.num_of_outputs = alloc_info->num_of_outputs;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		buf_idx = wl[parallel_idx].iobuf_input;
-+		buf = alloc_info->buffs[buf_idx].buf;
-+
-+		ipts_dbg(ipts, "in_buf[%d](%d) c:%p, p:%p, g:%p\n",
-+					parallel_idx, buf_idx, (void*)buf->cpu_addr,
-+					(void*)buf->phy_addr, (void*)buf->gfx_addr);
-+
-+		ipts_set_input_buffer(ipts, parallel_idx, buf->cpu_addr,
-+								buf->phy_addr);
-+
-+		for (i = 0; i < alloc_info->num_of_outputs; i++) {
-+			buf_idx = wl[parallel_idx].iobuf_output[i];
-+			buf = alloc_info->buffs[buf_idx].buf;
-+
-+			ipts_dbg(ipts, "out_buf[%d][%d] c:%p, p:%p, g:%p\n",
-+					parallel_idx, i, (void*)buf->cpu_addr,
-+					(void*)buf->phy_addr, (void*)buf->gfx_addr);
-+
-+			ipts_set_output_buffer(ipts, parallel_idx, i,
-+					buf->cpu_addr, buf->phy_addr);
-+		}
-+	}
-+}
-+
-+static void unload_kernel(ipts_info_t *ipts, bin_kernel_info_t *kernel)
-+{
-+	bin_alloc_info_t *alloc_info = kernel->alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item = kernel->guc_wq_item;
-+
-+	if (guc_wq_item) {
-+		vfree(guc_wq_item);
-+	}
-+
-+	if (alloc_info) {
-+		unmap_buffers(ipts, alloc_info);
-+
-+		vfree(alloc_info->buffs);
-+		vfree(alloc_info);
-+	}
-+}
-+
-+static int setup_kernel(ipts_info_t *ipts, bin_fw_list_t *fw_list)
-+{
-+	bin_kernel_list_t *kernel_list = NULL;
-+	bin_kernel_info_t *kernel = NULL;
-+	const struct firmware *fw = NULL;
-+	bin_workload_t *wl;
-+	bin_fw_info_t *fw_info;
-+	char *fw_name, *fw_data;
-+	bin_parse_info_t parse_info;
-+	int ret = 0, kernel_idx = 0, num_of_kernels = 0;
-+	int vendor_output_idx, total_workload = 0;
-+	char fw_path[MAX_IOCL_FILE_PATH_LEN];
-+
-+	num_of_kernels = fw_list->num_of_fws;
-+	kernel_list = vmalloc(sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list));
-+	if (kernel_list == NULL)
-+		return -ENOMEM;
-+
-+	memset(kernel_list, 0, sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list));
-+	kernel_list->num_of_kernels = num_of_kernels;
-+	kernel = &kernel_list->kernels[0];
-+
-+	fw_data = (char *)&fw_list->fw_info[0];
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		fw_info = (bin_fw_info_t *)fw_data;
-+		fw_name = &fw_info->fw_name[0];
-+		vendor_output_idx = fw_info->vendor_output;
-+		snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name);
-+		ret = request_firmware(&fw, (const char *)fw_path, &ipts->cldev->dev);
-+		if (ret) {
-+			ipts_err(ipts, "cannot read fw %s\n", fw_path);
-+			goto error_exit;
-+		}
-+
-+		parse_info.data = (u8*)fw->data;
-+		parse_info.size = fw->size;
-+		parse_info.parsed = 0;
-+		parse_info.fw_info = fw_info;
-+		parse_info.vendor_kernel = (kernel_idx == 0) ? NULL : &kernel[0];
-+		parse_info.interested_vendor_output = vendor_output_idx;
-+
-+		ret = load_kernel(ipts, &parse_info, &kernel[kernel_idx]);
-+		if (ret) {
-+			ipts_err(ipts, "do_setup_kernel error : %d\n", ret);
-+			release_firmware(fw);
-+			goto error_exit;
-+		}
-+
-+		release_firmware(fw);
-+
-+		total_workload += kernel[kernel_idx].guc_wq_item->size;
-+
-+		/* advance to the next kernel */
-+		fw_data += sizeof(bin_fw_info_t);
-+		fw_data += sizeof(bin_data_file_info_t) * fw_info->num_of_data_files;
-+	}
-+
-+	ipts_set_wq_item_size(ipts, total_workload);
-+	
-+	ret = bin_setup_guc_workqueue(ipts, kernel_list);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error setup_guc_workqueue\n");
-+		goto error_exit;
-+	}
-+
-+	ret = bin_setup_bufid_buffer(ipts, kernel_list);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error setup_lastbubmit_buffer\n");
-+		goto error_exit;
-+	}
-+
-+	bin_setup_input_output(ipts, kernel_list);
-+
-+	/* workload is not needed during run-time so free them */
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		wl = kernel[kernel_idx].wl;
-+		vfree(wl);
-+	}
-+
-+	ipts->kernel_handle = (u64)kernel_list;
-+
-+	return 0;
-+
-+error_exit:
-+
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		wl = kernel[kernel_idx].wl;
-+		vfree(wl);
-+		unload_kernel(ipts, &kernel[kernel_idx]);
-+	}
-+
-+	vfree(kernel_list);
-+
-+	return ret;
-+}
-+
-+
-+static void release_kernel(ipts_info_t *ipts)
-+{
-+	bin_kernel_list_t *kernel_list;
-+	bin_kernel_info_t *kernel;
-+	int k_idx, k_num;
-+
-+	kernel_list = (bin_kernel_list_t *)ipts->kernel_handle;
-+	k_num = kernel_list->num_of_kernels;
-+	kernel = &kernel_list->kernels[0];
-+
-+	for (k_idx = 0; k_idx < k_num; k_idx++) {
-+		unload_kernel(ipts, kernel);
-+		kernel++;
-+	}	
-+
-+	ipts_unmap_buffer(ipts, kernel_list->bufid_buf);
-+
-+	vfree(kernel_list);
-+	ipts->kernel_handle = 0;
-+}
-+
-+int ipts_init_kernels(ipts_info_t *ipts)
-+{
-+	const struct firmware *config_fw = NULL;
-+	const char *config_fw_path = IPTS_FW_CONFIG_FILE;
-+	bin_fw_list_t *fw_list;
-+	int ret;
-+
-+	ret = ipts_open_gpu(ipts);
-+	if (ret) {
-+		ipts_err(ipts, "open gpu error : %d\n", ret);
-+		return ret;
-+	}
-+
-+	ret = request_firmware(&config_fw, config_fw_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_err(ipts, "request firmware error : %d\n", ret);
-+		goto close_gpu;
-+	}
-+
-+	fw_list = (bin_fw_list_t *)config_fw->data;
-+	ret = setup_kernel(ipts, fw_list);
-+	if (ret) {
-+		ipts_err(ipts, "setup kernel error : %d\n", ret);
-+		goto close_firmware;
-+	}
-+
-+	release_firmware(config_fw);
-+
-+	return ret;
-+
-+close_firmware:
-+	release_firmware(config_fw);
-+
-+close_gpu:
-+	ipts_close_gpu(ipts);
-+
-+	return ret;
-+}
-+
-+void ipts_release_kernels(ipts_info_t *ipts)
-+{
-+	release_kernel(ipts);
-+	ipts_close_gpu(ipts);
-+}
-diff --git a/drivers/misc/ipts/ipts-kernel.h b/drivers/misc/ipts/ipts-kernel.h
-new file mode 100644
-index 0000000..0e7f139
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-kernel.h
-@@ -0,0 +1,23 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus Linux driver
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _ITPS_GFX_H
-+#define _ITPS_GFX_H
-+
-+int ipts_init_kernels(ipts_info_t *ipts);
-+void ipts_release_kernels(ipts_info_t *ipts);
-+
-+#endif
-diff --git a/drivers/misc/ipts/ipts-mei-msgs.h b/drivers/misc/ipts/ipts-mei-msgs.h
-new file mode 100644
-index 0000000..8ca1468
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-mei-msgs.h
-@@ -0,0 +1,585 @@
-+/*
-+ * Precise Touch HECI Message
-+ *
-+ * Copyright (c) 2013-2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_MEI_MSGS_H_
-+#define _IPTS_MEI_MSGS_H_
-+
-+#include "ipts-sensor-regs.h"
-+
-+#pragma pack(1)
-+
-+
-+// Initial protocol version
-+#define TOUCH_HECI_CLIENT_PROTOCOL_VERSION      10
-+
-+// GUID that identifies the Touch HECI client.
-+#define TOUCH_HECI_CLIENT_GUID  \
-+            {0x3e8d0870, 0x271a, 0x4208, {0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04}}
-+
-+
-+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch
-+#ifndef C_ASSERT
-+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
-+#endif
-+
-+
-+// General Type Defines for compatibility with HID driver and BIOS
-+#ifndef BIT0
-+#define BIT0 1
-+#endif
-+#ifndef BIT1
-+#define BIT1 2
-+#endif
-+#ifndef BIT2
-+#define BIT2 4
-+#endif
-+
-+
-+#define TOUCH_SENSOR_GET_DEVICE_INFO_CMD        0x00000001
-+#define TOUCH_SENSOR_GET_DEVICE_INFO_RSP        0x80000001
-+
-+
-+#define TOUCH_SENSOR_SET_MODE_CMD               0x00000002
-+#define TOUCH_SENSOR_SET_MODE_RSP               0x80000002
-+
-+
-+#define TOUCH_SENSOR_SET_MEM_WINDOW_CMD         0x00000003
-+#define TOUCH_SENSOR_SET_MEM_WINDOW_RSP         0x80000003
-+
-+
-+#define TOUCH_SENSOR_QUIESCE_IO_CMD             0x00000004
-+#define TOUCH_SENSOR_QUIESCE_IO_RSP             0x80000004
-+
-+
-+#define TOUCH_SENSOR_HID_READY_FOR_DATA_CMD     0x00000005
-+#define TOUCH_SENSOR_HID_READY_FOR_DATA_RSP     0x80000005
-+
-+
-+#define TOUCH_SENSOR_FEEDBACK_READY_CMD         0x00000006
-+#define TOUCH_SENSOR_FEEDBACK_READY_RSP         0x80000006
-+
-+
-+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD       0x00000007
-+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP       0x80000007
-+
-+
-+#define TOUCH_SENSOR_NOTIFY_DEV_READY_CMD       0x00000008
-+#define TOUCH_SENSOR_NOTIFY_DEV_READY_RSP       0x80000008
-+
-+
-+#define TOUCH_SENSOR_SET_POLICIES_CMD           0x00000009
-+#define TOUCH_SENSOR_SET_POLICIES_RSP           0x80000009
-+
-+
-+#define TOUCH_SENSOR_GET_POLICIES_CMD           0x0000000A
-+#define TOUCH_SENSOR_GET_POLICIES_RSP           0x8000000A
-+
-+
-+#define TOUCH_SENSOR_RESET_CMD                  0x0000000B
-+#define TOUCH_SENSOR_RESET_RSP                  0x8000000B
-+
-+
-+#define TOUCH_SENSOR_READ_ALL_REGS_CMD          0x0000000C
-+#define TOUCH_SENSOR_READ_ALL_REGS_RSP          0x8000000C
-+
-+
-+#define TOUCH_SENSOR_CMD_ERROR_RSP              0x8FFFFFFF  // M2H: ME sends this message to indicate previous command was unrecognized/unsupported
-+
-+
-+
-+//*******************************************************************
-+//
-+// Touch Sensor Status Codes
-+//
-+//*******************************************************************
-+typedef enum touch_status
-+{
-+    TOUCH_STATUS_SUCCESS = 0,               //  0 Requested operation was successful
-+    TOUCH_STATUS_INVALID_PARAMS,            //  1 Invalid parameter(s) sent
-+    TOUCH_STATUS_ACCESS_DENIED,             //  2 Unable to validate address range
-+    TOUCH_STATUS_CMD_SIZE_ERROR,            //  3 HECI message incorrect size for specified command
-+    TOUCH_STATUS_NOT_READY,                 //  4 Memory window not set or device is not armed for operation
-+    TOUCH_STATUS_REQUEST_OUTSTANDING,       //  5 There is already an outstanding message of the same type, must wait for response before sending another request of that type
-+    TOUCH_STATUS_NO_SENSOR_FOUND,           //  6 Sensor could not be found. Either no sensor is connected, the sensor has not yet initialized, or the system is improperly configured.
-+    TOUCH_STATUS_OUT_OF_MEMORY,             //  7 Not enough memory/storage for requested operation
-+    TOUCH_STATUS_INTERNAL_ERROR,            //  8 Unexpected error occurred
-+    TOUCH_STATUS_SENSOR_DISABLED,           //  9 Used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP to indicate sensor has been disabled or reset and must be reinitialized.
-+    TOUCH_STATUS_COMPAT_CHECK_FAIL,         // 10 Used to indicate compatibility revision check between sensor and ME failed, or protocol ver between ME/HID/Kernels failed.
-+    TOUCH_STATUS_SENSOR_EXPECTED_RESET,     // 11 Indicates sensor went through a reset initiated by ME
-+    TOUCH_STATUS_SENSOR_UNEXPECTED_RESET,   // 12 Indicates sensor went through an unexpected reset
-+    TOUCH_STATUS_RESET_FAILED,              // 13 Requested sensor reset failed to complete
-+    TOUCH_STATUS_TIMEOUT,                   // 14 Operation timed out
-+    TOUCH_STATUS_TEST_MODE_FAIL,            // 15 Test mode pattern did not match expected values
-+    TOUCH_STATUS_SENSOR_FAIL_FATAL,         // 16 Indicates sensor reported fatal error during reset sequence. Further progress is not possible.
-+    TOUCH_STATUS_SENSOR_FAIL_NONFATAL,      // 17 Indicates sensor reported non-fatal error during reset sequence. HID/BIOS logs error and attempts to continue.
-+    TOUCH_STATUS_INVALID_DEVICE_CAPS,       // 18 Indicates sensor reported invalid capabilities, such as not supporting required minimum frequency or I/O mode.
-+    TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS,    // 19 Indicates that command cannot be complete until ongoing Quiesce I/O flow has completed.
-+    TOUCH_STATUS_MAX                        // 20 Invalid value, never returned
-+} touch_status_t;
-+C_ASSERT(sizeof(touch_status_t) == 4);
-+
-+
-+
-+//*******************************************************************
-+//
-+// Defines for message structures used for Host to ME communication
-+//
-+//*******************************************************************
-+
-+
-+typedef enum touch_sensor_mode
-+{
-+    TOUCH_SENSOR_MODE_HID = 0,          // Set mode to HID mode
-+    TOUCH_SENSOR_MODE_RAW_DATA,         // Set mode to Raw Data mode
-+    TOUCH_SENSOR_MODE_SENSOR_DEBUG = 4, // Used like TOUCH_SENSOR_MODE_HID but data coming from sensor is not necessarily a HID packet.
-+    TOUCH_SENSOR_MODE_MAX               // Invalid value
-+} touch_sensor_mode_t;
-+C_ASSERT(sizeof(touch_sensor_mode_t) == 4);
-+
-+typedef struct touch_sensor_set_mode_cmd_data
-+{
-+    touch_sensor_mode_t	sensor_mode;     // Indicate desired sensor mode
-+    u32					Reserved[3];    // For future expansion
-+} touch_sensor_set_mode_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mode_cmd_data_t) == 16);
-+
-+
-+#define TOUCH_SENSOR_MAX_DATA_BUFFERS   16
-+#define TOUCH_HID_2_ME_BUFFER_ID        TOUCH_SENSOR_MAX_DATA_BUFFERS
-+#define TOUCH_HID_2_ME_BUFFER_SIZE_MAX  1024
-+#define TOUCH_INVALID_BUFFER_ID         0xFF
-+
-+typedef struct touch_sensor_set_mem_window_cmd_data
-+{
-+    u32  touch_data_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS];    // Lower 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize
-+    u32  touch_data_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS];    // Upper 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize
-+    u32  tail_offset_addr_lower;                                        // Lower 32 bits of Tail Offset physical address
-+    u32  tail_offset_addr_upper;                                        // Upper 32 bits of Tail Offset physical address, always 32 bit, increment by WorkQueueItemSize
-+    u32  doorbell_cookie_addr_lower;                                    // Lower 32 bits of Doorbell register physical address
-+    u32  doorbell_cookie_addr_upper;                                    // Upper 32 bits of Doorbell register physical address, always 32 bit, increment as integer, rollover to 1
-+    u32  feedback_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS];     // Lower 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize
-+    u32  feedback_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS];     // Upper 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize
-+    u32  hid2me_buffer_addr_lower;                                      // Lower 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize.
-+    u32  hid2me_buffer_addr_upper;                                      // Upper 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize.
-+    u32  hid2me_buffer_size;                                           // Size in bytes of Hid2MeBuffer, can be no bigger than TOUCH_HID_2_ME_BUFFER_SIZE_MAX
-+    u8   reserved1;                                                  // For future expansion
-+    u8   work_queue_item_size;                                          // Size in bytes of the GuC Work Queue Item pointed to by TailOffset
-+    u16  work_queue_size;                                              // Size in bytes of the entire GuC Work Queue
-+    u32  reserved[8];                                                // For future expansion
-+} touch_sensor_set_mem_window_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mem_window_cmd_data_t) == 320);
-+
-+
-+#define TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET BIT0   // indicates GuC got reset and ME must re-read GuC data such as TailOffset and Doorbell Cookie values
-+
-+typedef struct touch_sensor_quiesce_io_cmd_data
-+{
-+    u32  quiesce_flags;   // Optionally set TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET
-+    u32  reserved[2];
-+} touch_sensor_quiesce_io_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_quiesce_io_cmd_data_t) == 12);
-+
-+
-+typedef struct touch_sensor_feedback_ready_cmd_data
-+{
-+    u8   feedback_index;  // Index value from 0 to TOUCH_HID_2_ME_BUFFER_ID used to indicate which Feedback Buffer to use. Using special value TOUCH_HID_2_ME_BUFFER_ID
-+                            // is an indication to ME to get feedback data from the Hid2Me buffer instead of one of the standard Feedback buffers.
-+    u8   reserved1[3];   // For future expansion
-+    u32  transaction_id;  // Transaction ID that was originally passed to host in TOUCH_HID_PRIVATE_DATA. Used to track round trip of a given transaction for performance measurements.
-+    u32  reserved2[2];   // For future expansion
-+} touch_sensor_feedback_ready_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_feedback_ready_cmd_data_t) == 16);
-+
-+
-+#define TOUCH_DEFAULT_DOZE_TIMER_SECONDS    30
-+
-+typedef enum touch_freq_override
-+{
-+    TOUCH_FREQ_OVERRIDE_NONE,   // Do not apply any override
-+    TOUCH_FREQ_OVERRIDE_10MHZ,  // Force frequency to 10MHz (not currently supported)
-+    TOUCH_FREQ_OVERRIDE_17MHZ,  // Force frequency to 17MHz
-+    TOUCH_FREQ_OVERRIDE_30MHZ,  // Force frequency to 30MHz
-+    TOUCH_FREQ_OVERRIDE_50MHZ,  // Force frequency to 50MHz (not currently supported)
-+    TOUCH_FREQ_OVERRIDE_MAX     // Invalid value
-+} touch_freq_override_t;
-+C_ASSERT(sizeof(touch_freq_override_t) == 4);
-+
-+typedef enum touch_spi_io_mode_override
-+{
-+    TOUCH_SPI_IO_MODE_OVERRIDE_NONE,    // Do not apply any override
-+    TOUCH_SPI_IO_MODE_OVERRIDE_SINGLE,  // Force Single I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_DUAL,    // Force Dual I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_QUAD,    // Force Quad I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_MAX      // Invalid value
-+} touch_spi_io_mode_override_t;
-+C_ASSERT(sizeof(touch_spi_io_mode_override_t) == 4);
-+
-+// Debug Policy bits used by TOUCH_POLICY_DATA.DebugOverride
-+#define TOUCH_DBG_POLICY_OVERRIDE_STARTUP_TIMER_DIS BIT0    // Disable sensor startup timer
-+#define TOUCH_DBG_POLICY_OVERRIDE_SYNC_BYTE_DIS     BIT1    // Disable Sync Byte check
-+#define TOUCH_DBG_POLICY_OVERRIDE_ERR_RESET_DIS     BIT2    // Disable error resets
-+
-+typedef struct touch_policy_data
-+{
-+    u32                      reserved0;          // For future expansion.
-+    u32                      doze_timer     :16;  // Value in seconds, after which ME will put the sensor into Doze power state if no activity occurs. Set
-+                                                    // to 0 to disable Doze mode (not recommended). Value will be set to TOUCH_DEFAULT_DOZE_TIMER_SECONDS by
-+                                                    // default.
-+    touch_freq_override_t         freq_override  :3;   // Override frequency requested by sensor
-+    touch_spi_io_mode_override_t  spi_io_override :3;   // Override IO mode requested by sensor
-+    u32                      reserved1     :10;  // For future expansion
-+    u32                      reserved2;          // For future expansion
-+    u32                      debug_override;      // Normally all bits will be zero. Bits will be defined as needed for enabling special debug features
-+} touch_policy_data_t;
-+C_ASSERT(sizeof(touch_policy_data_t) == 16);
-+
-+typedef struct touch_sensor_set_policies_cmd_data
-+{
-+    touch_policy_data_t           policy_data;         // Contains the desired policy to be set
-+} touch_sensor_set_policies_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_policies_cmd_data_t) == 16);
-+
-+
-+typedef enum touch_sensor_reset_type
-+{
-+    TOUCH_SENSOR_RESET_TYPE_HARD,   // Hardware Reset using dedicated GPIO pin
-+    TOUCH_SENSOR_RESET_TYPE_SOFT,   // Software Reset using command written over SPI interface
-+    TOUCH_SENSOR_RESET_TYPE_MAX     // Invalid value
-+} touch_sensor_reset_type_t;
-+C_ASSERT(sizeof(touch_sensor_reset_type_t) == 4);
-+
-+typedef struct touch_sensor_reset_cmd_data
-+{
-+    touch_sensor_reset_type_t reset_type;  // Indicate desired reset type
-+    u32                  reserved;   // For future expansion
-+} touch_sensor_reset_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_reset_cmd_data_t) == 8);
-+
-+
-+//
-+// Host to ME message
-+//
-+typedef struct touch_sensor_msg_h2m
-+{
-+    u32  command_code;
-+    union
-+    {
-+        touch_sensor_set_mode_cmd_data_t        set_mode_cmd_data;
-+        touch_sensor_set_mem_window_cmd_data_t  set_window_cmd_data;
-+        touch_sensor_quiesce_io_cmd_data_t      quiesce_io_cmd_data;
-+        touch_sensor_feedback_ready_cmd_data_t  feedback_ready_cmd_data;
-+        touch_sensor_set_policies_cmd_data_t    set_policies_cmd_data;
-+        touch_sensor_reset_cmd_data_t           reset_cmd_data;
-+    } h2m_data;
-+} touch_sensor_msg_h2m_t;
-+C_ASSERT(sizeof(touch_sensor_msg_h2m_t) == 324);
-+
-+
-+//*******************************************************************
-+//
-+// Defines for message structures used for ME to Host communication
-+//
-+//*******************************************************************
-+
-+// I/O mode values used by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+typedef enum touch_spi_io_mode
-+{
-+    TOUCH_SPI_IO_MODE_SINGLE = 0,   // Sensor set for Single I/O SPI
-+    TOUCH_SPI_IO_MODE_DUAL,         // Sensor set for Dual I/O SPI
-+    TOUCH_SPI_IO_MODE_QUAD,         // Sensor set for Quad I/O SPI
-+    TOUCH_SPI_IO_MODE_MAX           // Invalid value
-+} touch_spi_io_mode_t;
-+C_ASSERT(sizeof(touch_spi_io_mode_t) == 4);
-+
-+//
-+// TOUCH_SENSOR_GET_DEVICE_INFO_RSP code is sent in response to TOUCH_SENSOR_GET_DEVICE_INFO_CMD. This code will be followed
-+// by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:               Command was processed successfully and sensor details are reported.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:        Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_NO_SENSOR_FOUND:       Sensor has not yet been detected. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_DEVICE_CAPS:   Indicates sensor does not support minimum required Frequency or I/O Mode. ME firmware will choose best possible option for the errant
-+//                                          field. Caller should attempt to continue.
-+//      TOUCH_STATUS_COMPAT_CHECK_FAIL:     Indicates TouchIC/ME compatibility mismatch. Caller should attempt to continue.
-+//
-+typedef struct touch_sensor_get_device_info_rsp_data
-+{
-+    u16				vendor_id;               // Touch Sensor vendor ID
-+    u16              device_id;               // Touch Sensor device ID
-+    u32              hw_rev;                  // Touch Sensor Hardware Revision
-+    u32              fw_rev;                  // Touch Sensor Firmware Revision
-+    u32              frame_size;              // Max size of one frame returned by Touch IC in bytes. This data will be TOUCH_RAW_DATA_HDR followed
-+                                                // by a payload. The payload can be raw data or a HID structure depending on mode.
-+    u32              feedback_size;           // Max size of one Feedback structure in bytes
-+    touch_sensor_mode_t	sensor_mode;             // Current operating mode of the sensor
-+    u32              max_touch_points  :8;     // Maximum number of simultaneous touch points that can be reported by sensor
-+    touch_freq_t          spi_frequency    :8;     // SPI bus Frequency supported by sensor and ME firmware
-+    touch_spi_io_mode_t   spi_io_mode       :8;     // SPI bus I/O Mode supported by sensor and ME firmware
-+    u32              reserved0       :8;     // For future expansion
-+    u8               sensor_minor_eds_rev;      // Minor version number of EDS spec supported by sensor (from Compat Rev ID Reg)
-+    u8               sensor_major_eds_rev;      // Major version number of EDS spec supported by sensor (from Compat Rev ID Reg)
-+    u8               me_minor_eds_rev;          // Minor version number of EDS spec supported by ME
-+    u8               me_major_eds_rev;          // Major version number of EDS spec supported by ME
-+    u8               sensor_eds_intf_rev;       // EDS Interface Revision Number supported by sensor (from Compat Rev ID Reg)
-+    u8               me_eds_intf_rev;           // EDS Interface Revision Number supported by ME
-+    u8               kernel_compat_ver;        // EU Kernel Compatibility Version  (from Compat Rev ID Reg)
-+    u8               reserved1;              // For future expansion
-+    u32              reserved2[2];           // For future expansion
-+} touch_sensor_get_device_info_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_get_device_info_rsp_data_t) == 44);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_MODE_RSP code is sent in response to TOUCH_SENSOR_SET_MODE_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_MODE_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and mode was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//
-+typedef struct touch_sensor_set_mode_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_mode_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mode_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_SET_MEM_WINDOW_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_MEM_WINDOW_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and memory window was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//      TOUCH_STATUS_ACCESS_DENIED:     Unable to map host address ranges for DMA.
-+//      TOUCH_STATUS_OUT_OF_MEMORY:     Unable to allocate enough space for needed buffers.
-+//
-+typedef struct touch_sensor_set_mem_window_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_mem_window_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mem_window_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_QUIESCE_IO_RSP code is sent in response to TOUCH_SENSOR_QUIESCE_IO_CMD. This code will be followed
-+// by TOUCH_SENSOR_QUIESCE_IO_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and touch flow has stopped.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//      TOUCH_STATIS_TIMEOUT:                   Indicates ME timed out waiting for Quiesce I/O flow to complete.
-+//
-+typedef struct touch_sensor_quiesce_io_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_quiesce_io_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_quiesce_io_rsp_data_t) == 12);
-+
-+
-+// Reset Reason values used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA
-+typedef enum touch_reset_reason
-+{
-+    TOUCH_RESET_REASON_UNKNOWN = 0,         // Reason for sensor reset is not known
-+    TOUCH_RESET_REASON_FEEDBACK_REQUEST,    // Reset was requested as part of TOUCH_SENSOR_FEEDBACK_READY_CMD
-+    TOUCH_RESET_REASON_HECI_REQUEST,        // Reset was requested via TOUCH_SENSOR_RESET_CMD
-+    TOUCH_RESET_REASON_MAX
-+} touch_reset_reason_t;
-+C_ASSERT(sizeof(touch_reset_reason_t) == 4);
-+
-+//
-+// TOUCH_SENSOR_HID_READY_FOR_DATA_RSP code is sent in response to TOUCH_SENSOR_HID_READY_FOR_DATA_CMD. This code will be followed
-+// by TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and HID data was sent by DMA. This will only be sent in HID mode.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_REQUEST_OUTSTANDING:       Previous request is still outstanding, ME FW cannot handle another request for the same command.
-+//      TOUCH_STATUS_NOT_READY:                 Indicates memory window has not yet been set by BIOS/HID.
-+//      TOUCH_STATUS_SENSOR_DISABLED:           Indicates that ME to HID communication has been stopped either by TOUCH_SENSOR_QUIESCE_IO_CMD or TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD.
-+//      TOUCH_STATUS_SENSOR_UNEXPECTED_RESET:   Sensor signaled a Reset Interrupt. ME did not expect this and has no info about why this occurred.
-+//      TOUCH_STATUS_SENSOR_EXPECTED_RESET:     Sensor signaled a Reset Interrupt. ME either directly requested this reset, or it was expected as part of a defined flow in the EDS.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//      TOUCH_STATUS_TIMEOUT:                   Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//
-+typedef struct touch_sensor_hid_ready_for_data_rsp_data
-+{
-+    u32          data_size;               // Size of the data the ME DMA'd into a RawDataBuffer. Valid only when Status == TOUCH_STATUS_SUCCESS
-+    u8           touch_data_buffer_index;   // Index to indicate which RawDataBuffer was used. Valid only when Status == TOUCH_STATUS_SUCCESS
-+    u8           reset_reason;            // If Status is TOUCH_STATUS_SENSOR_EXPECTED_RESET, ME will provide the cause. See TOUCH_RESET_REASON.
-+    u8           reserved1[2];           // For future expansion
-+    u32          reserved2[5];           // For future expansion
-+} touch_sensor_hid_ready_for_data_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_hid_ready_for_data_rsp_data_t) == 28);
-+
-+
-+//
-+// TOUCH_SENSOR_FEEDBACK_READY_RSP code is sent in response to TOUCH_SENSOR_FEEDBACK_READY_CMD. This code will be followed
-+// by TOUCH_SENSOR_FEEDBACK_READY_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and any feedback or commands were sent to sensor.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//      TOUCH_STATUS_COMPAT_CHECK_FAIL  Indicates ProtocolVer does not match ME supported version. (non-fatal error)
-+//      TOUCH_STATUS_INTERNAL_ERROR:    Unexpected error occurred. This should not normally be seen.
-+//      TOUCH_STATUS_OUT_OF_MEMORY:     Insufficient space to store Calibration Data
-+//
-+typedef struct touch_sensor_feedback_ready_rsp_data
-+{
-+    u8           feedback_index;  // Index value from 0 to TOUCH_SENSOR_MAX_DATA_BUFFERS used to indicate which Feedback Buffer to use
-+    u8           reserved1[3];   // For future expansion
-+    u32          reserved2[6];   // For future expansion
-+} touch_sensor_feedback_ready_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_feedback_ready_rsp_data_t) == 28);
-+
-+
-+//
-+// TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD. This code will be followed
-+// by TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and memory window was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:            Input parameters are out of range.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//
-+typedef struct touch_sensor_clear_mem_window_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_clear_mem_window_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_clear_mem_window_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_NOTIFY_DEV_READY_RSP code is sent in response to TOUCH_SENSOR_NOTIFY_DEV_READY_CMD. This code will be followed
-+// by TOUCH_SENSOR_NOTIFY_DEV_READY_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:               Command was processed successfully and sensor has been detected by ME FW.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:        Command sent did not match expected size.
-+//      TOUCH_STATUS_REQUEST_OUTSTANDING:   Previous request is still outstanding, ME FW cannot handle another request for the same command.
-+//      TOUCH_STATUS_TIMEOUT:               Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//      TOUCH_STATUS_SENSOR_FAIL_FATAL:     Sensor indicated a fatal error, further operation is not possible. Error details can be found in ErrReg.
-+//      TOUCH_STATUS_SENSOR_FAIL_NONFATAL:  Sensor indicated a non-fatal error. Error should be logged by caller and init flow can continue. Error details can be found in ErrReg.
-+//
-+typedef struct touch_sensor_notify_dev_ready_rsp_data
-+{
-+    touch_err_reg_t   err_reg;         // Value of sensor Error Register, field is only valid for Status == TOUCH_STATUS_SENSOR_FAIL_FATAL or TOUCH_STATUS_SENSOR_FAIL_NONFATAL
-+    u32          reserved[2];    // For future expansion
-+} touch_sensor_notify_dev_ready_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_notify_dev_ready_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_SET_POLICIES_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_POLICIES_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//
-+typedef struct touch_sensor_set_policies_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_policies_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_policies_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_GET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_GET_POLICIES_CMD. This code will be followed
-+// by TOUCH_SENSOR_GET_POLICIES_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//
-+typedef struct touch_sensor_get_policies_rsp_data
-+{
-+    touch_policy_data_t   policy_data;         // Contains the current policy
-+} touch_sensor_get_policies_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_get_policies_rsp_data_t) == 16);
-+
-+
-+//
-+// TOUCH_SENSOR_RESET_RSP code is sent in response to TOUCH_SENSOR_RESET_CMD. This code will be followed
-+// by TOUCH_SENSOR_RESET_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and sensor reset was completed.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:            Input parameters are out of range.
-+//      TOUCH_STATUS_TIMEOUT:                   Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//      TOUCH_STATUS_RESET_FAILED:              Sensor generated an invalid or unexpected interrupt.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//
-+typedef struct touch_sensor_reset_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_reset_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_reset_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_READ_ALL_REGS_RSP code is sent in response to TOUCH_SENSOR_READ_ALL_REGS_CMD. This code will be followed
-+// by TOUCH_SENSOR_READ_ALL_REGS_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//
-+typedef struct touch_sensor_read_all_regs_rsp_data
-+{
-+    touch_reg_block_t sensor_regs; // Returns first 64 bytes of register space used for normal touch operation. Does not include test mode register.
-+    u32          reserved[4];
-+} touch_sensor_read_all_regs_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_read_all_regs_rsp_data_t) == 80);
-+
-+//
-+// ME to Host Message
-+//
-+typedef struct touch_sensor_msg_m2h
-+{
-+    u32  command_code;
-+    touch_status_t	status;
-+    union
-+    {
-+        touch_sensor_get_device_info_rsp_data_t     device_info_rsp_data;
-+        touch_sensor_set_mode_rsp_data_t            set_mode_rsp_data;
-+        touch_sensor_set_mem_window_rsp_data_t      set_mem_window_rsp_data;
-+        touch_sensor_quiesce_io_rsp_data_t          quiesce_io_rsp_data;
-+        touch_sensor_hid_ready_for_data_rsp_data_t  hid_ready_for_data_rsp_data;
-+        touch_sensor_feedback_ready_rsp_data_t      feedback_ready_rsp_data;
-+        touch_sensor_clear_mem_window_rsp_data_t    clear_mem_window_rsp_data;
-+        touch_sensor_notify_dev_ready_rsp_data_t    notify_dev_ready_rsp_data;
-+        touch_sensor_set_policies_rsp_data_t        set_policies_rsp_data;
-+        touch_sensor_get_policies_rsp_data_t        get_policies_rsp_data;
-+        touch_sensor_reset_rsp_data_t               reset_rsp_data;
-+	touch_sensor_read_all_regs_rsp_data_t       read_all_regs_rsp_data;
-+    } m2h_data;
-+} touch_sensor_msg_m2h_t;
-+C_ASSERT(sizeof(touch_sensor_msg_m2h_t) == 88);
-+
-+
-+#define TOUCH_MSG_SIZE_MAX_BYTES    (MAX(sizeof(touch_sensor_msg_m2h_t), sizeof(touch_sensor_msg_h2m_t)))
-+
-+#pragma pack()
-+
-+#endif // _IPTS_MEI_MSGS_H_
-diff --git a/drivers/misc/ipts/ipts-mei.c b/drivers/misc/ipts/ipts-mei.c
-new file mode 100644
-index 0000000..39667e7
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-mei.c
-@@ -0,0 +1,282 @@
-+/*
-+ * MEI client driver for Intel Precise Touch and Stylus
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/mei_cl_bus.h>
-+#include <linux/module.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/hid.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/kthread.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-hid.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-mei-msgs.h"
-+#include "ipts-binary-spec.h"
-+#include "ipts-state.h"
-+
-+#define IPTS_DRIVER_NAME	"ipts"
-+#define IPTS_MEI_UUID		UUID_LE(0x3e8d0870, 0x271a, 0x4208, \
-+				0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04)
-+
-+static struct mei_cl_device_id ipts_mei_cl_tbl[] = {
-+	{ "", IPTS_MEI_UUID, MEI_CL_VERSION_ANY},
-+	{}
-+};
-+
-+static ssize_t sensor_mode_show(struct device *dev,
-+				struct device_attribute *attr, char *buf)
-+{
-+	ipts_info_t *ipts;
-+	ipts = dev_get_drvdata(dev);
-+
-+	return sprintf(buf, "%d\n", ipts->sensor_mode);
-+}
-+
-+//TODO: Verify the function implementation
-+static ssize_t sensor_mode_store(struct device *dev,
-+				struct device_attribute *attr, const char *buf,
-+				size_t count)
-+{
-+	int ret;
-+	long val;
-+	ipts_info_t *ipts;
-+
-+	ipts = dev_get_drvdata(dev);
-+	ret = kstrtol(buf, 10, &val);
-+	if (ret)
-+	   return ret;
-+
-+	ipts_dbg(ipts, "try sensor mode = %ld\n", val);
-+
-+	switch (val) {
-+		case TOUCH_SENSOR_MODE_HID:
-+			break;
-+		case TOUCH_SENSOR_MODE_RAW_DATA:
-+			break;
-+		default:
-+			ipts_err(ipts, "sensor mode %ld is not supported\n", val);
-+	}
-+
-+	return count;
-+}
-+
-+static ssize_t device_info_show(struct device *dev,
-+				struct device_attribute *attr, char *buf)
-+{
-+	ipts_info_t *ipts;
-+
-+	ipts = dev_get_drvdata(dev);
-+	return sprintf(buf, "vendor id = 0x%04hX\n"
-+				"device id = 0x%04hX\n"
-+				"HW rev = 0x%08X\n"
-+				"firmware rev = 0x%08X\n",
-+			ipts->device_info.vendor_id, ipts->device_info.device_id,
-+			ipts->device_info.hw_rev, ipts->device_info.fw_rev);
-+}
-+
-+static DEVICE_ATTR_RW(sensor_mode);
-+static DEVICE_ATTR_RO(device_info);
-+
-+static struct attribute *ipts_attrs[] = {
-+	&dev_attr_sensor_mode.attr,
-+	&dev_attr_device_info.attr,
-+	NULL
-+};
-+
-+static const struct attribute_group ipts_grp = {
-+	.attrs = ipts_attrs,
-+};
-+
-+MODULE_DEVICE_TABLE(mei, ipts_mei_cl_tbl);
-+
-+static void raw_data_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, raw_data_work);
-+
-+	ipts_handle_processed_data(ipts);
-+}
-+
-+static void gfx_status_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, gfx_status_work);
-+	ipts_state_t state;
-+	int status = ipts->gfx_status;
-+
-+	ipts_dbg(ipts, "notify gfx status : %d\n", status);
-+
-+	state = ipts_get_state(ipts);
-+
-+	if (state == IPTS_STA_RAW_DATA_STARTED || state == IPTS_STA_HID_STARTED) {
-+		if (status == IPTS_NOTIFY_STA_BACKLIGHT_ON &&
-+					ipts->display_status == false) {
-+			ipts_send_sensor_clear_mem_window_cmd(ipts);
-+			ipts->display_status = true;
-+		} else if (status == IPTS_NOTIFY_STA_BACKLIGHT_OFF &&
-+					ipts->display_status == true) {
-+			ipts_send_sensor_quiesce_io_cmd(ipts);
-+			ipts->display_status = false;
-+		}
-+	}
-+}
-+
-+/* event loop */
-+static int ipts_mei_cl_event_thread(void *data)
-+{
-+	ipts_info_t *ipts = (ipts_info_t *)data;
-+	struct mei_cl_device *cldev = ipts->cldev;
-+	ssize_t msg_len;
-+	touch_sensor_msg_m2h_t m2h_msg;
-+
-+	while (!kthread_should_stop()) {
-+		msg_len = mei_cldev_recv(cldev, (u8*)&m2h_msg, sizeof(m2h_msg));
-+		if (msg_len <= 0) {
-+			ipts_err(ipts, "error in reading m2h msg\n");
-+			continue;
-+		}
-+
-+		if (ipts_handle_resp(ipts, &m2h_msg, msg_len) != 0) {
-+			ipts_err(ipts, "error in handling resp msg\n");
-+		}
-+	}
-+
-+	ipts_dbg(ipts, "!! end event loop !!\n");
-+
-+	return 0;
-+}
-+
-+static void init_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, init_work);
-+
-+	ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA;
-+	ipts->display_status = true;
-+
-+	ipts_start(ipts);
-+}
-+
-+static int ipts_mei_cl_probe(struct mei_cl_device *cldev,
-+			const struct mei_cl_device_id *id)
-+{
-+	int ret = 0;
-+	ipts_info_t *ipts = NULL;
-+
-+	pr_info("probing Intel Precise Touch & Stylus\n");
-+
-+	// setup the DMA BIT mask, the system will choose the best possible
-+	if (dma_coerce_mask_and_coherent(&cldev->dev, DMA_BIT_MASK(64)) == 0) {
-+		pr_info("IPTS using DMA_BIT_MASK(64)\n");
-+	} else if (dma_coerce_mask_and_coherent(&cldev->dev,
-+						DMA_BIT_MASK(32)) == 0) {
-+		pr_info("IPTS using  DMA_BIT_MASK(32)\n");
-+	} else {
-+		pr_err("IPTS: No suitable DMA available\n");
-+		return -EFAULT;
-+	}
-+
-+	ret = mei_cldev_enable(cldev);
-+	if (ret < 0) {
-+		pr_err("cannot enable IPTS\n");
-+		return ret;
-+	}
-+
-+	ipts = devm_kzalloc(&cldev->dev, sizeof(ipts_info_t), GFP_KERNEL);
-+	if (ipts == NULL) {
-+		ret = -ENOMEM;
-+		goto disable_mei;
-+	}
-+	ipts->cldev = cldev;
-+	mei_cldev_set_drvdata(cldev, ipts);
-+
-+	ipts->event_loop = kthread_run(ipts_mei_cl_event_thread, (void*)ipts,
-+							"ipts_event_thread");
-+
-+	if(ipts_dbgfs_register(ipts, "ipts"))
-+		pr_debug("cannot register debugfs for IPTS\n");
-+
-+	INIT_WORK(&ipts->init_work, init_work_func);
-+	INIT_WORK(&ipts->raw_data_work, raw_data_work_func);
-+	INIT_WORK(&ipts->gfx_status_work, gfx_status_work_func);
-+
-+	ret = sysfs_create_group(&cldev->dev.kobj, &ipts_grp);
-+	if (ret != 0) {
-+		pr_debug("cannot create sysfs for IPTS\n");
-+	}
-+
-+	schedule_work(&ipts->init_work);
-+
-+	return 0;
-+
-+disable_mei :
-+	mei_cldev_disable(cldev);
-+	
-+	return ret;
-+}
-+
-+static int ipts_mei_cl_remove(struct mei_cl_device *cldev)
-+{
-+	ipts_info_t *ipts = mei_cldev_get_drvdata(cldev);
-+
-+	ipts_stop(ipts);
-+
-+	sysfs_remove_group(&cldev->dev.kobj, &ipts_grp);
-+	ipts_hid_release(ipts);
-+	ipts_dbgfs_deregister(ipts);
-+	mei_cldev_disable(cldev);
-+
-+	kthread_stop(ipts->event_loop);
-+
-+	pr_info("IPTS removed\n");
-+
-+	return 0;
-+}
-+
-+static struct mei_cl_driver ipts_mei_cl_driver = {
-+	.id_table = ipts_mei_cl_tbl,
-+	.name = IPTS_DRIVER_NAME,
-+	.probe = ipts_mei_cl_probe,
-+	.remove = ipts_mei_cl_remove,
-+};
-+
-+static int ipts_mei_cl_init(void)
-+{
-+	int ret;
-+
-+	pr_info("IPTS %s() is called\n", __func__);
-+
-+	ret = mei_cldev_driver_register(&ipts_mei_cl_driver);
-+	if (ret) {
-+		pr_err("unable to register IPTS mei client driver\n");
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static void __exit ipts_mei_cl_exit(void)
-+{
-+	pr_info("IPTS %s() is called\n", __func__);
-+
-+	mei_cldev_driver_unregister(&ipts_mei_cl_driver);
-+}
-+
-+module_init(ipts_mei_cl_init);
-+module_exit(ipts_mei_cl_exit);
-+
-+MODULE_DESCRIPTION
-+	("Intel(R) Management Engine Interface Client Driver for "\
-+	"Intel Precision Touch and Sylus");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/misc/ipts/ipts-msg-handler.c b/drivers/misc/ipts/ipts-msg-handler.c
-new file mode 100644
-index 0000000..1396ecc
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-msg-handler.c
-@@ -0,0 +1,431 @@
-+#include <linux/mei_cl_bus.h>
-+
-+#include "ipts.h"
-+#include "ipts-hid.h"
-+#include "ipts-resource.h"
-+#include "ipts-mei-msgs.h"
-+
-+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size)
-+{
-+	int ret = 0;
-+	touch_sensor_msg_h2m_t h2m_msg;
-+	int len = 0;
-+
-+	memset(&h2m_msg, 0, sizeof(h2m_msg));
-+
-+	h2m_msg.command_code = cmd;
-+	len = sizeof(h2m_msg.command_code) + data_size;
-+	if (data != NULL && data_size != 0)
-+		memcpy(&h2m_msg.h2m_data, data, data_size); /* copy payload */
-+
-+	ret = mei_cldev_send(ipts->cldev, (u8*)&h2m_msg, len);
-+	if (ret < 0) {
-+		ipts_err(ipts, "mei_cldev_send() error 0x%X:%d\n",
-+							cmd, ret);
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id)
-+{
-+	int ret;
-+	int cmd_len;
-+	touch_sensor_feedback_ready_cmd_data_t fb_ready_cmd;
-+
-+	cmd_len = sizeof(touch_sensor_feedback_ready_cmd_data_t);
-+	memset(&fb_ready_cmd, 0, cmd_len);
-+
-+	fb_ready_cmd.feedback_index = buffer_idx;
-+	fb_ready_cmd.transaction_id = transaction_id;
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_FEEDBACK_READY_CMD,
-+				&fb_ready_cmd, cmd_len);
-+
-+	return ret;
-+}
-+
-+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts)
-+{
-+	int ret;
-+	int cmd_len;
-+	touch_sensor_quiesce_io_cmd_data_t quiesce_io_cmd;
-+
-+	cmd_len = sizeof(touch_sensor_quiesce_io_cmd_data_t);
-+	memset(&quiesce_io_cmd, 0, cmd_len);
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_QUIESCE_IO_CMD,
-+				&quiesce_io_cmd, cmd_len);
-+
-+	return ret;
-+}
-+
-+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts)
-+{
-+	return ipts_handle_cmd(ipts, TOUCH_SENSOR_HID_READY_FOR_DATA_CMD, NULL, 0);
-+}
-+
-+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts)
-+{
-+	return ipts_handle_cmd(ipts, TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD, NULL, 0);
-+}
-+
-+static int check_validity(touch_sensor_msg_m2h_t *m2h_msg, u32 msg_len)
-+{
-+	int ret = 0;
-+	int valid_msg_len = sizeof(m2h_msg->command_code);
-+	u32 cmd_code = m2h_msg->command_code;
-+
-+	switch (cmd_code) {
-+		case TOUCH_SENSOR_SET_MODE_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_mode_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_SET_MEM_WINDOW_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_mem_window_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_QUIESCE_IO_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_quiesce_io_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_hid_ready_for_data_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_FEEDBACK_READY_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_feedback_ready_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_clear_mem_window_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_notify_dev_ready_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_SET_POLICIES_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_policies_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_GET_POLICIES_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_get_policies_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_RESET_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_reset_rsp_data_t);
-+			break;
-+	}
-+
-+	if (valid_msg_len != msg_len) {
-+		return -EINVAL;
-+	}
-+
-+	return ret;
-+}
-+
-+int ipts_start(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	/* TODO : check if we need to do SET_POLICIES_CMD
-+	we need to do this when protocol version doesn't match with reported one
-+	how we keep vendor specific data is the first thing to solve */
-+
-+	ipts_set_state(ipts, IPTS_STA_INIT);
-+	ipts->num_of_parallel_data_buffers = TOUCH_SENSOR_MAX_DATA_BUFFERS;
-+
-+	ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA; /* start with RAW_DATA */
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_NOTIFY_DEV_READY_CMD, NULL, 0);
-+
-+	return ret;
-+}
-+
-+void ipts_stop(ipts_info_t *ipts)
-+{
-+	ipts_state_t old_state;
-+
-+	old_state = ipts_get_state(ipts);
-+	ipts_set_state(ipts, IPTS_STA_STOPPING);
-+
-+	if (old_state < IPTS_STA_RESOURCE_READY)
-+		return;
-+
-+	if (old_state == IPTS_STA_RAW_DATA_STARTED ||
-+					old_state == IPTS_STA_HID_STARTED) {
-+        	ipts_free_default_resource(ipts);
-+		ipts_free_raw_data_resource(ipts);
-+
-+		return;
-+	}
-+}
-+
-+int ipts_restart(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ipts_dbg(ipts, "ipts restart\n");
-+
-+	ipts_stop(ipts);
-+
-+	ipts->retry++;
-+	if (ipts->retry == IPTS_MAX_RETRY && 
-+			ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) {
-+		/* try with HID mode */
-+		ipts->sensor_mode = TOUCH_SENSOR_MODE_HID;
-+	} else if (ipts->retry > IPTS_MAX_RETRY) {
-+		return -EPERM;
-+	}
-+
-+	ipts_send_sensor_quiesce_io_cmd(ipts);
-+	ipts->restart = true;
-+
-+	return ret;
-+}
-+
-+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode)
-+{
-+	int ret = 0;
-+
-+        ipts->new_sensor_mode = new_sensor_mode;
-+	ipts->switch_sensor_mode = true;
-+        ret = ipts_send_sensor_quiesce_io_cmd(ipts);
-+
-+	return ret;
-+}
-+
-+#define rsp_failed(ipts, cmd, status) ipts_err(ipts, \
-+				"0x%08x failed status = %d\n", cmd, status);
-+
-+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg,
-+								u32 msg_len)
-+{
-+	int ret = 0;
-+	int rsp_status = 0;
-+	int cmd_status = 0;
-+	int cmd_len = 0;
-+	u32 cmd;
-+
-+	if (!check_validity(m2h_msg, msg_len)) {
-+		ipts_err(ipts, "wrong rsp\n");
-+		return -EINVAL;
-+	}
-+
-+	rsp_status = m2h_msg->status;
-+	cmd = m2h_msg->command_code;
-+
-+	switch (cmd) {
-+		case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_SENSOR_FAIL_NONFATAL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_status = ipts_handle_cmd(ipts,
-+					TOUCH_SENSOR_GET_DEVICE_INFO_CMD,
-+					NULL, 0);
-+			break;
-+		case TOUCH_SENSOR_GET_DEVICE_INFO_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			memcpy(&ipts->device_info,
-+				&m2h_msg->m2h_data.device_info_rsp_data,
-+				sizeof(touch_sensor_get_device_info_rsp_data_t));
-+
-+			/*
-+			    TODO : support raw_request during HID init.
-+			    Although HID init happens here, technically most of
-+			    reports (for both direction) can be issued only
-+			    after SET_MEM_WINDOWS_CMD since they may require
-+			    ME or touch IC. If ipts vendor requires raw_request
-+			    during HID init, we need to consider to move HID init.
-+			*/
-+			if (ipts->hid_desc_ready == false) {
-+				ret = ipts_hid_init(ipts);
-+				if (ret)
-+					break;
-+			}
-+
-+			cmd_status = ipts_send_sensor_clear_mem_window_cmd(ipts);
-+
-+			break;
-+		case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP:
-+		{
-+			touch_sensor_set_mode_cmd_data_t sensor_mode_cmd;
-+
-+			if (rsp_status != 0 &&
-+					rsp_status != TOUCH_STATUS_TIMEOUT) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			/* allocate default resource : common & hid only */
-+			if (!ipts_is_default_resource_ready(ipts)) {
-+				ret = ipts_allocate_default_resource(ipts);
-+				if (ret)
-+					break;
-+			}
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA &&
-+					!ipts_is_raw_data_resource_ready(ipts)) {
-+				ret = ipts_allocate_raw_data_resource(ipts);
-+				if (ret) {
-+					ipts_free_default_resource(ipts);
-+					break;
-+				}
-+			}
-+
-+			ipts_set_state(ipts, IPTS_STA_RESOURCE_READY);
-+
-+			cmd_len = sizeof(touch_sensor_set_mode_cmd_data_t);
-+			memset(&sensor_mode_cmd, 0, cmd_len);
-+			sensor_mode_cmd.sensor_mode = ipts->sensor_mode;
-+			cmd_status = ipts_handle_cmd(ipts,
-+				TOUCH_SENSOR_SET_MODE_CMD,
-+				&sensor_mode_cmd, cmd_len);
-+			break;
-+		}
-+		case TOUCH_SENSOR_SET_MODE_RSP:
-+		{
-+			touch_sensor_set_mem_window_cmd_data_t smw_cmd;
-+
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_len = sizeof(touch_sensor_set_mem_window_cmd_data_t);
-+			memset(&smw_cmd, 0, cmd_len);
-+			ipts_get_set_mem_window_cmd_data(ipts, &smw_cmd);
-+			cmd_status = ipts_handle_cmd(ipts,
-+				TOUCH_SENSOR_SET_MEM_WINDOW_CMD,
-+				&smw_cmd, cmd_len);
-+			break;
-+		}
-+		case TOUCH_SENSOR_SET_MEM_WINDOW_RSP:
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_status = ipts_send_sensor_hid_ready_for_data_cmd(ipts);
-+			if (cmd_status)
-+				break;
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) {
-+				ipts_set_state(ipts, IPTS_STA_HID_STARTED);
-+			} else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) {
-+				ipts_set_state(ipts, IPTS_STA_RAW_DATA_STARTED);
-+			}
-+
-+			ipts_err(ipts, "touch enabled %d\n", ipts_get_state(ipts));
-+
-+			break;
-+		case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP:
-+		{
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_data;
-+			ipts_state_t state;
-+
-+			if (rsp_status != 0 &&
-+				  rsp_status != TOUCH_STATUS_SENSOR_DISABLED) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			state = ipts_get_state(ipts);
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID &&
-+						state == IPTS_STA_HID_STARTED) {
-+
-+				hid_data = &m2h_msg->m2h_data.hid_ready_for_data_rsp_data;
-+
-+				/* HID mode only uses buffer 0 */
-+				if (hid_data->touch_data_buffer_index != 0)
-+					break;
-+
-+				/* handle hid data */
-+				ipts_handle_hid_data(ipts, hid_data);
-+			}
-+
-+			break;
-+		}
-+		case TOUCH_SENSOR_FEEDBACK_READY_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			if (m2h_msg->m2h_data.feedback_ready_rsp_data.
-+					feedback_index == TOUCH_HID_2_ME_BUFFER_ID)
-+				break;
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) {
-+				cmd_status = ipts_handle_cmd(ipts,
-+					TOUCH_SENSOR_HID_READY_FOR_DATA_CMD,
-+					NULL, 0);
-+			}
-+
-+			/* reset retry since we are getting touch data */
-+			ipts->retry = 0;
-+
-+			break;
-+		case TOUCH_SENSOR_QUIESCE_IO_RSP:
-+		{
-+			ipts_state_t state;
-+
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			state = ipts_get_state(ipts);
-+			if (state == IPTS_STA_STOPPING && ipts->restart) {
-+				ipts_dbg(ipts, "restart\n");
-+			        ipts_start(ipts);
-+				ipts->restart = 0;
-+				break;
-+			}
-+
-+			/* support sysfs debug node for switch sensor mode */
-+			if (ipts->switch_sensor_mode) {
-+				ipts_set_state(ipts, IPTS_STA_INIT);
-+				ipts->sensor_mode = ipts->new_sensor_mode;
-+				ipts->switch_sensor_mode = false;
-+
-+				ipts_send_sensor_clear_mem_window_cmd(ipts);
-+			}
-+
-+			break;
-+		}
-+	}
-+
-+	/* handle error in rsp_status */
-+	if (rsp_status != 0) {
-+		switch (rsp_status) {
-+			case TOUCH_STATUS_SENSOR_EXPECTED_RESET:
-+			case TOUCH_STATUS_SENSOR_UNEXPECTED_RESET:
-+				ipts_dbg(ipts, "sensor reset %d\n", rsp_status);
-+				ipts_restart(ipts);
-+				break;
-+			default:
-+				ipts_dbg(ipts, "cmd : 0x%08x, status %d\n",
-+								cmd,
-+								rsp_status);
-+				break;
-+		}
-+	}
-+
-+	if (cmd_status) {
-+		ipts_restart(ipts);
-+	}
-+
-+	return ret;
-+}
-diff --git a/drivers/misc/ipts/ipts-msg-handler.h b/drivers/misc/ipts/ipts-msg-handler.h
-new file mode 100644
-index 0000000..b8e27d3
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-msg-handler.h
-@@ -0,0 +1,32 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus ME message handler
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_MSG_HANDLER_H
-+#define _IPTS_MSG_HANDLER_H
-+
-+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size);
-+int ipts_start(ipts_info_t *ipts);
-+void ipts_stop(ipts_info_t *ipts);
-+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode);
-+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg,
-+                        					u32 msg_len);
-+int ipts_handle_processed_data(ipts_info_t *ipts);
-+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id);
-+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts);
-+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts);
-+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts);
-+
-+#endif /* _IPTS_MSG_HANDLER_H */
-diff --git a/drivers/misc/ipts/ipts-resource.c b/drivers/misc/ipts/ipts-resource.c
-new file mode 100644
-index 0000000..47607ef
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-resource.c
-@@ -0,0 +1,277 @@
-+#include <linux/dma-mapping.h>
-+
-+#include "ipts.h"
-+#include "ipts-mei-msgs.h"
-+#include "ipts-kernel.h"
-+
-+static void free_common_resource(ipts_info_t *ipts)
-+{
-+	char *addr;
-+	ipts_buffer_info_t *feedback_buffer;
-+	dma_addr_t dma_addr;
-+	u32 buffer_size;
-+	int i, num_of_parallels;
-+
-+	if (ipts->resource.me2hid_buffer) {
-+		devm_kfree(&ipts->cldev->dev, ipts->resource.me2hid_buffer);
-+		ipts->resource.me2hid_buffer = 0;
-+	}
-+
-+	addr = ipts->resource.hid2me_buffer.addr;
-+	dma_addr = ipts->resource.hid2me_buffer.dma_addr;
-+	buffer_size = ipts->resource.hid2me_buffer_size;
-+
-+	if (ipts->resource.hid2me_buffer.addr) {
-+		dmam_free_coherent(&ipts->cldev->dev, buffer_size, addr, dma_addr);
-+		ipts->resource.hid2me_buffer.addr = 0;
-+		ipts->resource.hid2me_buffer.dma_addr = 0;
-+		ipts->resource.hid2me_buffer_size = 0;
-+	}
-+
-+	feedback_buffer = ipts->resource.feedback_buffer;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		if (feedback_buffer[i].addr) {
-+			dmam_free_coherent(&ipts->cldev->dev,
-+				ipts->device_info.feedback_size,
-+				feedback_buffer[i].addr,
-+				feedback_buffer[i].dma_addr);
-+			feedback_buffer[i].addr = 0;
-+			feedback_buffer[i].dma_addr = 0;
-+		}
-+	}
-+}
-+
-+static int allocate_common_resource(ipts_info_t *ipts)
-+{
-+	char *addr, *me2hid_addr;
-+	ipts_buffer_info_t *feedback_buffer;
-+	dma_addr_t dma_addr;
-+	int i, ret = 0, num_of_parallels;
-+	u32 buffer_size;
-+
-+	buffer_size = ipts->device_info.feedback_size;
-+
-+	addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+			buffer_size,
-+			&dma_addr,
-+			GFP_ATOMIC|__GFP_ZERO);
-+	if (addr == NULL)
-+		return -ENOMEM;
-+
-+	me2hid_addr = devm_kzalloc(&ipts->cldev->dev, buffer_size, GFP_KERNEL);
-+	if (me2hid_addr == NULL) {
-+		ret = -ENOMEM;
-+		goto release_resource;
-+	}
-+
-+	ipts->resource.hid2me_buffer.addr = addr;
-+	ipts->resource.hid2me_buffer.dma_addr = dma_addr;
-+	ipts->resource.hid2me_buffer_size = buffer_size;
-+	ipts->resource.me2hid_buffer = me2hid_addr;
-+
-+	feedback_buffer = ipts->resource.feedback_buffer;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		feedback_buffer[i].addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+				ipts->device_info.feedback_size,
-+				&feedback_buffer[i].dma_addr,
-+				GFP_ATOMIC|__GFP_ZERO);
-+
-+		if (feedback_buffer[i].addr == NULL) {
-+			ret = -ENOMEM;
-+			goto release_resource;
-+		}
-+	}
-+
-+	return 0;
-+
-+release_resource:
-+	free_common_resource(ipts);
-+
-+	return ret;
-+}
-+
-+void ipts_free_raw_data_resource(ipts_info_t *ipts)
-+{
-+	if (ipts_is_raw_data_resource_ready(ipts)) {
-+		ipts->resource.raw_data_resource_ready = false;
-+
-+		ipts_release_kernels(ipts);
-+	}
-+}
-+
-+static int allocate_hid_resource(ipts_info_t *ipts)
-+{
-+	ipts_buffer_info_t *buffer_hid;
-+
-+	/* hid mode uses only one touch data buffer */
-+	buffer_hid = &ipts->resource.touch_data_buffer_hid;
-+	buffer_hid->addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+				ipts->device_info.frame_size,
-+				&buffer_hid->dma_addr,
-+				GFP_ATOMIC|__GFP_ZERO);
-+	if (buffer_hid->addr == NULL) {
-+		return -ENOMEM;
-+	}
-+
-+	return 0;
-+}
-+
-+static void free_hid_resource(ipts_info_t *ipts)
-+{
-+	ipts_buffer_info_t *buffer_hid;
-+
-+	buffer_hid = &ipts->resource.touch_data_buffer_hid;
-+	if (buffer_hid->addr) {
-+		dmam_free_coherent(&ipts->cldev->dev,
-+				ipts->device_info.frame_size,
-+				buffer_hid->addr,
-+				buffer_hid->dma_addr);
-+		buffer_hid->addr = 0;
-+		buffer_hid->dma_addr = 0;
-+	}
-+}
-+
-+int ipts_allocate_default_resource(ipts_info_t *ipts)
-+{
-+	int ret;
-+
-+	ret = allocate_common_resource(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot allocate common resource\n");
-+		return ret;
-+	}
-+
-+	ret = allocate_hid_resource(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot allocate hid resource\n");
-+		free_common_resource(ipts);
-+		return ret;
-+	}
-+
-+	ipts->resource.default_resource_ready = true;
-+
-+	return 0;
-+}
-+
-+void ipts_free_default_resource(ipts_info_t *ipts)
-+{
-+	if (ipts_is_default_resource_ready(ipts)) {
-+		ipts->resource.default_resource_ready = false;
-+
-+		free_hid_resource(ipts);
-+		free_common_resource(ipts);
-+	}
-+}
-+
-+int ipts_allocate_raw_data_resource(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ret = ipts_init_kernels(ipts);
-+	if (ret) {
-+		return ret;
-+	}
-+
-+	ipts->resource.raw_data_resource_ready = true;
-+
-+	return 0;
-+}
-+
-+static void get_hid_only_smw_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data,
-+				ipts_resource_t *resrc)
-+{
-+	ipts_buffer_info_t *touch_buf;
-+	ipts_buffer_info_t *feedback_buf;
-+
-+	touch_buf = &resrc->touch_data_buffer_hid;
-+	feedback_buf = &resrc->feedback_buffer[0];
-+
-+	data->touch_data_buffer_addr_lower[0] =
-+				lower_32_bits(touch_buf->dma_addr);
-+	data->touch_data_buffer_addr_upper[0] =
-+				upper_32_bits(touch_buf->dma_addr);
-+	data->feedback_buffer_addr_lower[0] =
-+				lower_32_bits(feedback_buf->dma_addr);
-+	data->feedback_buffer_addr_upper[0] =
-+				upper_32_bits(feedback_buf->dma_addr);
-+}
-+
-+static void get_raw_data_only_smw_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data,
-+				ipts_resource_t *resrc)
-+{
-+	u64 wq_tail_phy_addr;
-+	u64 cookie_phy_addr;
-+	ipts_buffer_info_t *touch_buf;
-+	ipts_buffer_info_t *feedback_buf;
-+	int i, num_of_parallels;
-+
-+	touch_buf = resrc->touch_data_buffer_raw;
-+	feedback_buf = resrc->feedback_buffer;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		data->touch_data_buffer_addr_lower[i] =
-+					lower_32_bits(touch_buf[i].dma_addr);
-+		data->touch_data_buffer_addr_upper[i] =
-+					upper_32_bits(touch_buf[i].dma_addr);
-+		data->feedback_buffer_addr_lower[i] =
-+					lower_32_bits(feedback_buf[i].dma_addr);
-+		data->feedback_buffer_addr_upper[i] =
-+					upper_32_bits(feedback_buf[i].dma_addr);
-+	}
-+
-+	wq_tail_phy_addr = resrc->wq_info.wq_tail_phy_addr;
-+	data->tail_offset_addr_lower = lower_32_bits(wq_tail_phy_addr);
-+	data->tail_offset_addr_upper = upper_32_bits(wq_tail_phy_addr);
-+
-+	cookie_phy_addr = resrc->wq_info.db_phy_addr +
-+						resrc->wq_info.db_cookie_offset;
-+	data->doorbell_cookie_addr_lower = lower_32_bits(cookie_phy_addr);
-+	data->doorbell_cookie_addr_upper = upper_32_bits(cookie_phy_addr);
-+	data->work_queue_size = resrc->wq_info.wq_size;
-+
-+	data->work_queue_item_size = resrc->wq_item_size;
-+}
-+
-+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data)
-+{
-+	ipts_resource_t *resrc = &ipts->resource;
-+
-+	if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA)
-+		get_raw_data_only_smw_cmd_data(ipts, data, resrc);
-+	else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID)
-+		get_hid_only_smw_cmd_data(ipts, data, resrc);
-+
-+	/* hid2me is common for "raw data" and "hid" */
-+	data->hid2me_buffer_addr_lower =
-+				lower_32_bits(resrc->hid2me_buffer.dma_addr);
-+	data->hid2me_buffer_addr_upper =
-+				upper_32_bits(resrc->hid2me_buffer.dma_addr);
-+	data->hid2me_buffer_size = resrc->hid2me_buffer_size;
-+}
-+
-+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx,
-+						u8* cpu_addr, u64 dma_addr)
-+{
-+	ipts_buffer_info_t *touch_buf;
-+
-+	touch_buf = ipts->resource.touch_data_buffer_raw;
-+	touch_buf[parallel_idx].dma_addr = dma_addr;
-+	touch_buf[parallel_idx].addr = cpu_addr;
-+}
-+
-+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx,
-+						u8* cpu_addr, u64 dma_addr)
-+{
-+	ipts_buffer_info_t *output_buf;
-+
-+	output_buf = &ipts->resource.raw_data_mode_output_buffer[parallel_idx][output_idx];
-+
-+	output_buf->dma_addr = dma_addr;
-+	output_buf->addr = cpu_addr;
-+}
-diff --git a/drivers/misc/ipts/ipts-resource.h b/drivers/misc/ipts/ipts-resource.h
-new file mode 100644
-index 0000000..7d66ac7
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-resource.h
-@@ -0,0 +1,30 @@
-+/*
-+ * Intel Precise Touch & Stylus state codes
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_RESOURCE_H_
-+#define _IPTS_RESOURCE_H_
-+
-+int ipts_allocate_default_resource(ipts_info_t *ipts);
-+void ipts_free_default_resource(ipts_info_t *ipts);
-+int ipts_allocate_raw_data_resource(ipts_info_t *ipts);
-+void ipts_free_raw_data_resource(ipts_info_t *ipts);
-+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data);
-+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx,
-+						u8* cpu_addr, u64 dma_addr);
-+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx,
-+						u8* cpu_addr, u64 dma_addr);
-+
-+#endif // _IPTS_RESOURCE_H_
-diff --git a/drivers/misc/ipts/ipts-sensor-regs.h b/drivers/misc/ipts/ipts-sensor-regs.h
-new file mode 100644
-index 0000000..96812b0
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-sensor-regs.h
-@@ -0,0 +1,700 @@
-+/*
-+ * Touch Sensor Register definition
-+ *
-+ * Copyright (c) 2013-2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+
-+#ifndef _TOUCH_SENSOR_REGS_H
-+#define _TOUCH_SENSOR_REGS_H
-+
-+#pragma pack(1)
-+
-+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch
-+#ifndef C_ASSERT
-+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
-+#endif
-+
-+//
-+// Compatibility versions for this header file
-+//
-+#define TOUCH_EDS_REV_MINOR     0
-+#define TOUCH_EDS_REV_MAJOR     1
-+#define TOUCH_EDS_INTF_REV      1
-+#define TOUCH_PROTOCOL_VER      0
-+
-+
-+//
-+// Offset 00h: TOUCH_STS: Status Register
-+// This register is read by the SPI Controller immediately following an interrupt.
-+//
-+#define TOUCH_STS_REG_OFFSET                0x00
-+
-+typedef enum touch_sts_reg_int_type
-+{
-+    TOUCH_STS_REG_INT_TYPE_DATA_AVAIL = 0,  // Touch Data Available
-+    TOUCH_STS_REG_INT_TYPE_RESET_OCCURRED,  // Reset Occurred
-+    TOUCH_STS_REG_INT_TYPE_ERROR_OCCURRED,  // Error Occurred
-+    TOUCH_STS_REG_INT_TYPE_VENDOR_DATA,     // Vendor specific data, treated same as raw frame
-+    TOUCH_STS_REG_INT_TYPE_GET_FEATURES,    // Get Features response data available
-+    TOUCH_STS_REG_INT_TYPE_MAX
-+} touch_sts_reg_int_type_t;
-+C_ASSERT(sizeof(touch_sts_reg_int_type_t) == 4);
-+
-+typedef enum touch_sts_reg_pwr_state
-+{
-+    TOUCH_STS_REG_PWR_STATE_SLEEP = 0,  // Sleep
-+    TOUCH_STS_REG_PWR_STATE_DOZE,       // Doze
-+    TOUCH_STS_REG_PWR_STATE_ARMED,      // Armed
-+    TOUCH_STS_REG_PWR_STATE_SENSING,    // Sensing
-+    TOUCH_STS_REG_PWR_STATE_MAX
-+} touch_sts_reg_pwr_state_t;
-+C_ASSERT(sizeof(touch_sts_reg_pwr_state_t) == 4);
-+
-+typedef enum touch_sts_reg_init_state
-+{
-+    TOUCH_STS_REG_INIT_STATE_READY_FOR_OP = 0,  // Ready for normal operation
-+    TOUCH_STS_REG_INIT_STATE_FW_NEEDED,         // Touch IC needs its Firmware loaded
-+    TOUCH_STS_REG_INIT_STATE_DATA_NEEDED,       // Touch IC needs its Data loaded
-+    TOUCH_STS_REG_INIT_STATE_INIT_ERROR,        // Error info in TOUCH_ERR_REG
-+    TOUCH_STS_REG_INIT_STATE_MAX
-+} touch_sts_reg_init_state_t;
-+C_ASSERT(sizeof(touch_sts_reg_init_state_t) == 4);
-+
-+#define TOUCH_SYNC_BYTE_VALUE   0x5A
-+
-+typedef union touch_sts_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // When set, this indicates the hardware has data that needs to be read.
-+        u32  int_status           :1;
-+        // see TOUCH_STS_REG_INT_TYPE
-+        u32  int_type             :4;
-+        // see TOUCH_STS_REG_PWR_STATE
-+        u32  pwr_state            :2;
-+        // see TOUCH_STS_REG_INIT_STATE
-+        u32  init_state           :2;
-+        // Busy bit indicates that sensor cannot accept writes at this time
-+        u32  busy                :1;
-+        // Reserved
-+        u32  reserved            :14;
-+        // Synchronization bit, should always be TOUCH_SYNC_BYTE_VALUE
-+        u32  sync_byte            :8;
-+    } fields;
-+} touch_sts_reg_t;
-+C_ASSERT(sizeof(touch_sts_reg_t) == 4);
-+
-+
-+//
-+// Offset 04h: TOUCH_FRAME_CHAR: Frame Characteristics Register
-+// This registers describes the characteristics of each data frame read by the SPI Controller in
-+// response to a touch interrupt.
-+//
-+#define TOUCH_FRAME_CHAR_REG_OFFSET         0x04
-+
-+typedef union touch_frame_char_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Micro-Frame Size (MFS):  Indicates the size of a touch micro-frame in byte increments.
-+        // When a micro-frame is to be read for processing (in data mode), this is the total number of
-+        // bytes that must be read per interrupt, split into multiple read commands no longer than RPS.
-+        // Maximum micro-frame size is 256KB.
-+        u32  microframe_size      :18;
-+        // Micro-Frames per Frame (MFPF): Indicates the number of micro-frames per frame. If a
-+        // sensor's frame does not contain micro-frames this value will be 1. Valid values are 1-31.
-+        u32  microframes_per_frame :5;
-+        // Micro-Frame Index (MFI): Indicates the index of the micro-frame within a frame. This allows
-+        // the SPI Controller to maintain synchronization with the sensor and determine when the final
-+        // micro-frame has arrived. Valid values are 1-31.
-+        u32  microframe_index     :5;
-+        // HID/Raw Data: This bit describes whether the data from the sensor is Raw data or a HID
-+        // report. When set, the data is a HID report.
-+        u32  hid_report           :1;
-+        // Reserved
-+        u32  reserved            :3;
-+    } fields;
-+} touch_frame_char_reg_t;
-+C_ASSERT(sizeof(touch_frame_char_reg_t) == 4);
-+
-+
-+//
-+// Offset 08h: Touch Error Register
-+//
-+#define TOUCH_ERR_REG_OFFSET                0x08
-+
-+// bit definition is vendor specific
-+typedef union touch_err_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        u32  invalid_fw           :1;
-+        u32  invalid_data        :1;
-+        u32  self_test_failed       :1;
-+        u32  reserved            :12;
-+        u32  fatal_error          :1;
-+        u32  vendor_errors        :16;
-+    } fields;
-+} touch_err_reg_t;
-+C_ASSERT(sizeof(touch_err_reg_t) == 4);
-+
-+
-+//
-+// Offset 0Ch: RESERVED
-+// This register is reserved for future use.
-+//
-+
-+
-+//
-+// Offset 10h: Touch Identification Register
-+//
-+#define TOUCH_ID_REG_OFFSET                 0x10
-+
-+#define TOUCH_ID_REG_VALUE                  0x43495424
-+
-+// expected value is "$TIC" or 0x43495424
-+typedef u32  touch_id_reg_t;
-+C_ASSERT(sizeof(touch_id_reg_t) == 4);
-+
-+
-+//
-+// Offset 14h: TOUCH_DATA_SZ: Touch Data Size Register
-+// This register describes the maximum size of frames and feedback data
-+//
-+#define TOUCH_DATA_SZ_REG_OFFSET            0x14
-+
-+#define TOUCH_MAX_FRAME_SIZE_INCREMENT      64
-+#define TOUCH_MAX_FEEDBACK_SIZE_INCREMENT   64
-+
-+#define TOUCH_SENSOR_MAX_FRAME_SIZE         (32 * 1024)     // Max allowed frame size 32KB
-+#define TOUCH_SENSOR_MAX_FEEDBACK_SIZE      (16 * 1024)     // Max allowed feedback size 16KB
-+
-+typedef union touch_data_sz_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // This value describes the maximum frame size in 64byte increments.
-+        u32  max_frame_size        :12;
-+        // This value describes the maximum feedback size in 64byte increments.
-+        u32  max_feedback_size     :8;
-+        // Reserved
-+        u32  reserved            :12;
-+    } fields;
-+} touch_data_sz_reg_t;
-+C_ASSERT(sizeof(touch_data_sz_reg_t) == 4);
-+
-+
-+//
-+// Offset 18h: TOUCH_CAPABILITIES: Touch Capabilities Register
-+// This register informs the host as to the capabilities of the touch IC.
-+//
-+#define TOUCH_CAPS_REG_OFFSET               0x18
-+
-+typedef enum touch_caps_reg_read_delay_time
-+{
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_0,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_10uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_50uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_100uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_150uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_250uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_500uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_1mS,
-+} touch_caps_reg_read_delay_time_t;
-+C_ASSERT(sizeof(touch_caps_reg_read_delay_time_t) == 4);
-+
-+#define TOUCH_BULK_DATA_MAX_WRITE_INCREMENT 64
-+
-+typedef union touch_caps_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Reserved for future frequency
-+        u32  reserved0           :1;
-+        // 17 MHz (14 MHz on Atom) Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_17Mhz      :1;
-+        // 30 MHz (25MHz on Atom) Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_30Mhz      :1;
-+        // 50 MHz Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_50Mhz      :1;
-+        // Reserved
-+        u32  reserved1           :4;
-+        // Single I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_single_io   :1;
-+        // Dual I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_dual_io     :1;
-+        // Quad I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_quad_io     :1;
-+        // Bulk Data Area Max Write Size: The amount of data the SPI Controller can write to the bulk
-+        // data area before it has to poll the busy bit. This field is in multiples of 64 bytes. The
-+        // SPI Controller will write the amount of data specified in this field, then check and wait
-+        // for the Status.Busy bit to be zero before writing the next data chunk. This field is 6 bits
-+        // long, allowing for 4KB of contiguous writes w/o a poll of the busy bit. If this field is
-+        // 0x00 the Touch IC has no limit in the amount of data the SPI Controller can write to the
-+        // bulk data area.
-+        u32  bulk_data_max_write    :6;
-+        // Read Delay Timer Value: This field describes the delay the SPI Controller will initiate when
-+        // a read interrupt follows a write data command. Uses values from TOUCH_CAPS_REG_READ_DELAY_TIME
-+        u32  read_delay_timer_value :3;
-+        // Reserved
-+        u32  reserved2           :4;
-+        // Maximum Touch Points: A byte value based on the HID descriptor definition.
-+        u32  max_touch_points      :8;
-+    } fields;
-+} touch_caps_reg_t;
-+C_ASSERT(sizeof(touch_caps_reg_t) == 4);
-+
-+
-+//
-+// Offset 1Ch: TOUCH_CFG: Touch Configuration Register
-+// This register allows the SPI Controller to configure the touch sensor as needed during touch
-+// operations.
-+//
-+#define TOUCH_CFG_REG_OFFSET                0x1C
-+
-+typedef enum touch_cfg_reg_bulk_xfer_size
-+{
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_4B  = 0,   // Bulk Data Transfer Size is 4 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_8B,        // Bulk Data Transfer Size is 8 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_16B,       // Bulk Data Transfer Size is 16 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_32B,       // Bulk Data Transfer Size is 32 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_64B,       // Bulk Data Transfer Size is 64 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_MAX
-+} touch_cfg_reg_bulk_xfer_size_t;
-+C_ASSERT(sizeof(touch_cfg_reg_bulk_xfer_size_t) == 4);
-+
-+// Frequency values used by TOUCH_CFG_REG and TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+typedef enum touch_freq
-+{
-+    TOUCH_FREQ_RSVD = 0,    // Reserved value
-+    TOUCH_FREQ_17MHZ,       // Sensor set for 17MHz operation (14MHz on Atom)
-+    TOUCH_FREQ_30MHZ,       // Sensor set for 30MHz operation (25MHz on Atom)
-+    TOUCH_FREQ_MAX          // Invalid value
-+} touch_freq_t;
-+C_ASSERT(sizeof(touch_freq_t) == 4);
-+
-+typedef union touch_cfg_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Touch Enable (TE):  This bit is used as a HW semaphore for the Touch IC to guarantee to the
-+        // SPI Controller to that (when 0) no sensing operations will occur and only the Reset
-+        // interrupt will be generated. When TE is cleared by the SPI Controller:
-+        //  - TICs must flush all output buffers
-+        //  - TICs must De-assert any pending interrupt
-+        //  - ME must throw away any partial frame and pending interrupt must be cleared/not serviced.
-+        // The SPI Controller will only modify the configuration of the TIC when TE is cleared. TE is
-+        // defaulted to 0h on a power-on reset.
-+        u32  touch_enable         :1;
-+        // Data/HID Packet Mode (DHPM): Raw Data Mode: 0h, HID Packet Mode: 1h
-+        u32  dhpm                :1;
-+        // Bulk Data Transfer Size: This field represents the amount of data written to the Bulk Data
-+        // Area (SPI Offset 0x1000-0x2FFF) in a single SPI write protocol
-+        u32  bulk_xfer_size        :4;
-+        // Frequency Select: Frequency for the TouchIC to run at. Use values from TOUCH_FREQ
-+        u32  freq_select          :3;
-+        // Reserved
-+        u32  reserved            :23;
-+    } fields;
-+} touch_cfg_reg_t;
-+C_ASSERT(sizeof(touch_cfg_reg_t) == 4);
-+
-+
-+//
-+// Offset 20h: TOUCH_CMD: Touch Command Register
-+// This register is used for sending commands to the Touch IC.
-+//
-+#define TOUCH_CMD_REG_OFFSET                0x20
-+
-+typedef enum touch_cmd_reg_code
-+{
-+    TOUCH_CMD_REG_CODE_NOP = 0,             // No Operation
-+    TOUCH_CMD_REG_CODE_SOFT_RESET,          // Soft Reset
-+    TOUCH_CMD_REG_CODE_PREP_4_READ,         // Prepare All Registers for Read
-+    TOUCH_CMD_REG_CODE_GEN_TEST_PACKETS,    // Generate Test Packets according to value in TOUCH_TEST_CTRL_REG
-+    TOUCH_CMD_REG_CODE_MAX
-+} touch_cmd_reg_code_t;
-+C_ASSERT(sizeof(touch_cmd_reg_code_t) == 4);
-+
-+typedef union touch_cmd_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Command Code: See TOUCH_CMD_REG_CODE
-+        u32  command_code :8;
-+        // Reserved
-+        u32  reserved    :24;
-+    } fields;
-+} touch_cmd_reg_t;
-+C_ASSERT(sizeof(touch_cmd_reg_t) == 4);
-+
-+
-+//
-+// Offset 24h: Power Management Control
-+// This register is used for active power management. The Touch IC is allowed to mover from Doze or
-+// Armed to Sensing after a touch has occurred. All other transitions will be made at the request
-+// of the SPI Controller.
-+//
-+#define TOUCH_PWR_MGMT_CTRL_REG_OFFSET      0x24
-+
-+typedef enum touch_pwr_mgmt_ctrl_reg_cmd
-+{
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_NOP = 0,    // No change to power state
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_SLEEP,      // Sleep   - set when the system goes into connected standby
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_DOZE,       // Doze    - set after 300 seconds of inactivity
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_ARMED,      // Armed   - Set by FW when a "finger off" message is received from the EUs
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_SENSING,    // Sensing - not typically set by FW
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_MAX         // Values will result in no change to the power state of the Touch IC
-+} touch_pwr_mgmt_ctrl_reg_cmd_t;
-+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_cmd_t) == 4);
-+
-+typedef union touch_pwr_mgmt_ctrl_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Power State Command: See TOUCH_PWR_MGMT_CTRL_REG_CMD
-+        u32  pwr_state_cmd         :3;
-+        // Reserved
-+        u32  reserved            :29;
-+    } fields;
-+} touch_pwr_mgmt_ctrl_reg_t;
-+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_t) == 4);
-+
-+
-+//
-+// Offset 28h: Vendor HW Information Register
-+// This register is used to relay Intel-assigned vendor ID information to the SPI Controller, which
-+// may be forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_VEN_HW_INFO_REG_OFFSET        0x28
-+
-+typedef union touch_ven_hw_info_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Touch Sensor Vendor ID
-+        u32  vendor_id            :16;
-+        // Touch Sensor Device ID
-+        u32  device_id            :16;
-+    } fields;
-+} touch_ven_hw_info_reg_t;
-+C_ASSERT(sizeof(touch_ven_hw_info_reg_t) == 4);
-+
-+
-+//
-+// Offset 2Ch: HW Revision ID Register
-+// This register is used to relay vendor HW revision information to the SPI Controller which may be
-+// forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_HW_REV_REG_OFFSET             0x2C
-+
-+typedef u32  touch_hw_rev_reg_t;   // bit definition is vendor specific
-+C_ASSERT(sizeof(touch_hw_rev_reg_t) == 4);
-+
-+
-+//
-+// Offset 30h: FW Revision ID Register
-+// This register is used to relay vendor FW revision information to the SPI Controller which may be
-+// forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_FW_REV_REG_OFFSET             0x30
-+
-+typedef u32  touch_fw_rev_reg_t;    // bit definition is vendor specific
-+C_ASSERT(sizeof(touch_fw_rev_reg_t) == 4);
-+
-+
-+//
-+// Offset 34h: Compatibility Revision ID Register
-+// This register is used to relay vendor compatibility information to the SPI Controller which may
-+// be forwarded to SW running on the host CPU. Compatibility Information is a numeric value given
-+// by Intel to the Touch IC vendor based on the major and minor revision of the EDS supported. From
-+// a nomenclature point of view in an x.y revision number of the EDS, the major version is the value
-+// of x and the minor version is the value of y. For example, a Touch IC supporting an EDS version
-+// of 0.61 would contain a major version of 0 and a minor version of 61 in the register.
-+//
-+#define TOUCH_COMPAT_REV_REG_OFFSET             0x34
-+
-+typedef union touch_compat_rev_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // EDS Minor Revision
-+        u8   minor;
-+        // EDS Major Revision
-+        u8   major;
-+        // Interface Revision Number (from EDS)
-+        u8   intf_rev;
-+        // EU Kernel Compatibility Version - vendor specific value
-+        u8   kernel_compat_ver;
-+    } fields;
-+} touch_compat_rev_reg_t;
-+C_ASSERT(sizeof(touch_compat_rev_reg_t) == 4);
-+
-+
-+//
-+// Touch Register Block is the full set of registers from offset 0x00h to 0x3F
-+// This is the entire set of registers needed for normal touch operation. It does not include test
-+// registers such as TOUCH_TEST_CTRL_REG
-+//
-+#define TOUCH_REG_BLOCK_OFFSET              TOUCH_STS_REG_OFFSET
-+
-+typedef struct touch_reg_block
-+{
-+    touch_sts_reg_t         sts_reg;         // 0x00
-+    touch_frame_char_reg_t  frame_char_reg;   // 0x04
-+    touch_err_reg_t         error_reg;       // 0x08
-+    u32                  reserved0;      // 0x0C
-+    touch_id_reg_t          id_reg;          // 0x10
-+    touch_data_sz_reg_t     data_size_reg;    // 0x14
-+    touch_caps_reg_t        caps_reg;        // 0x18
-+    touch_cfg_reg_t         cfg_reg;         // 0x1C
-+    touch_cmd_reg_t         cmd_reg;         // 0x20
-+    touch_pwr_mgmt_ctrl_reg_t  pwm_mgme_ctrl_reg; // 0x24
-+    touch_ven_hw_info_reg_t ven_hw_info_reg;   // 0x28
-+    touch_hw_rev_reg_t      hw_rev_reg;       // 0x2C
-+    touch_fw_rev_reg_t      fw_rev_reg;       // 0x30
-+    touch_compat_rev_reg_t  compat_rev_reg;   // 0x34
-+    u32                  reserved1;      // 0x38
-+    u32                  reserved2;      // 0x3C
-+} touch_reg_block_t;
-+C_ASSERT(sizeof(touch_reg_block_t) == 64);
-+
-+
-+//
-+// Offset 40h: Test Control Register
-+// This register
-+//
-+#define TOUCH_TEST_CTRL_REG_OFFSET              0x40
-+
-+typedef union touch_test_ctrl_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Size of Test Frame in Raw Data Mode: This field specifies the test frame size in raw data
-+        // mode in multiple of 64 bytes. For example, if this field value is 16, the test frame size
-+        // will be 16x64 = 1K.
-+        u32  raw_test_frame_size    :16;
-+        // Number of Raw Data Frames or HID Report Packets Generation. This field represents the number
-+        // of test frames or HID reports to be generated when test mode is enabled. When multiple
-+        // packets/frames are generated, they need be generated at 100 Hz frequency, i.e. 10ms per
-+        // packet/frame.
-+        u32  num_test_frames       :16;
-+    } fields;
-+} touch_test_ctrl_reg_t;
-+C_ASSERT(sizeof(touch_test_ctrl_reg_t) == 4);
-+
-+
-+//
-+// Offsets 0x000 to 0xFFF are reserved for Intel-defined Registers
-+//
-+#define TOUCH_REGISTER_LIMIT                0xFFF
-+
-+
-+//
-+// Data Window: Address 0x1000-0x1FFFF
-+// The data window is reserved for writing and reading large quantities of data to and from the
-+// sensor.
-+//
-+#define TOUCH_DATA_WINDOW_OFFSET            0x1000
-+#define TOUCH_DATA_WINDOW_LIMIT             0x1FFFF
-+
-+#define TOUCH_SENSOR_MAX_OFFSET             TOUCH_DATA_WINDOW_LIMIT
-+
-+
-+//
-+// The following data structures represent the headers defined in the Data Structures chapter of the
-+// Intel Integrated Touch EDS
-+//
-+
-+// Enumeration used in TOUCH_RAW_DATA_HDR
-+typedef enum touch_raw_data_types
-+{
-+    TOUCH_RAW_DATA_TYPE_FRAME = 0,
-+    TOUCH_RAW_DATA_TYPE_ERROR,          // RawData will be the TOUCH_ERROR struct below
-+    TOUCH_RAW_DATA_TYPE_VENDOR_DATA,    // Set when InterruptType is Vendor Data
-+    TOUCH_RAW_DATA_TYPE_HID_REPORT,
-+    TOUCH_RAW_DATA_TYPE_GET_FEATURES,
-+    TOUCH_RAW_DATA_TYPE_MAX
-+} touch_raw_data_types_t;
-+C_ASSERT(sizeof(touch_raw_data_types_t) == 4);
-+
-+// Private data structure. Kernels must copy to HID driver buffer
-+typedef struct touch_hid_private_data
-+{
-+    u32  transaction_id;
-+    u8   reserved[28];
-+} touch_hid_private_data_t;
-+C_ASSERT(sizeof(touch_hid_private_data_t) == 32);
-+
-+// This is the data structure sent from the PCH FW to the EU kernel
-+typedef struct touch_raw_data_hdr
-+{
-+    u32                  data_type;           // use values from TOUCH_RAW_DATA_TYPES
-+    u32                  raw_data_size_bytes;   // The size in bytes of the raw data read from the
-+                                                // sensor, does not include TOUCH_RAW_DATA_HDR. Will
-+                                                // be the sum of all uFrames, or size of TOUCH_ERROR
-+                                                // for if DataType is TOUCH_RAW_DATA_TYPE_ERROR
-+    u32                  buffer_id;           // An ID to qualify with the feedback data to track
-+                                                // buffer usage
-+    u32                  protocol_ver;        // Must match protocol version of the EDS
-+    u8                   kernel_compat_id;     // Copied from the Compatibility Revision ID Reg
-+    u8                   reserved[15];       // Padding to extend header to full 64 bytes and
-+                                                // allow for growth
-+    touch_hid_private_data_t  hid_private_data;     // Private data structure. Kernels must copy to HID
-+                                                // driver buffer
-+} touch_raw_data_hdr_t;
-+C_ASSERT(sizeof(touch_raw_data_hdr_t) == 64);
-+
-+typedef struct touch_raw_data
-+{
-+    touch_raw_data_hdr_t  header;
-+    u8               raw_data[1]; // used to access the raw data as an array and keep the
-+                                    // compilers happy. Actual size of this array is
-+                                    // Header.RawDataSizeBytes
-+} touch_raw_data_t;
-+
-+
-+// The following section describes the data passed in TOUCH_RAW_DATA.RawData when DataType equals
-+// TOUCH_RAW_DATA_TYPE_ERROR
-+// Note: This data structure is also applied to HID mode
-+typedef enum touch_err_types
-+{
-+    TOUCH_RAW_DATA_ERROR = 0,
-+    TOUCH_RAW_ERROR_MAX
-+} touch_err_types_t;
-+C_ASSERT(sizeof(touch_err_types_t) == 4);
-+
-+typedef union touch_me_fw_error
-+{
-+    u32  value;
-+
-+    struct
-+    {
-+        u32 invalid_frame_characteristics : 1;
-+        u32 microframe_index_invalid      : 1;
-+        u32 reserved                    : 30;
-+    } fields;
-+} touch_me_fw_error_t;
-+C_ASSERT(sizeof(touch_me_fw_error_t) == 4);
-+
-+typedef struct touch_error
-+{
-+    u8			touch_error_type; // This must be a value from TOUCH_ERROR_TYPES
-+    u8			reserved[3];
-+    touch_me_fw_error_t	touch_me_fw_error;
-+    touch_err_reg_t	touch_error_register; // Contains the value copied from the Touch Error Reg
-+} touch_error_t;
-+C_ASSERT(sizeof(touch_error_t) == 12);
-+
-+// Enumeration used in TOUCH_FEEDBACK_BUFFER
-+typedef enum touch_feedback_cmd_types
-+{
-+    TOUCH_FEEDBACK_CMD_TYPE_NONE = 0,
-+    TOUCH_FEEDBACK_CMD_TYPE_SOFT_RESET,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_ARMED,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_SENSING,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_SLEEP,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_DOZE,
-+    TOUCH_FEEDBACK_CMD_TYPE_HARD_RESET,
-+    TOUCH_FEEDBACK_CMD_TYPE_MAX
-+} touch_feedback_cmd_types_t;
-+C_ASSERT(sizeof(touch_feedback_cmd_types_t) == 4);
-+
-+// Enumeration used in TOUCH_FEEDBACK_HDR
-+typedef enum touch_feedback_data_types
-+{
-+    TOUCH_FEEDBACK_DATA_TYPE_FEEDBACK = 0,  // This is vendor specific feedback to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES,  // This is a set features command to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES,  // This is a get features command to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT, // This is a HID output report to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_STORE_DATA,    // This is calibration data to be written to system flash
-+    TOUCH_FEEDBACK_DATA_TYPE_MAX
-+} touch_feedback_data_types_t;
-+C_ASSERT(sizeof(touch_feedback_data_types_t) == 4);
-+
-+// This is the data structure sent from the EU kernels back to the ME FW.
-+// In addition to "feedback" data, the FW can execute a "command" described by the command type parameter.
-+// Any payload data will always be sent to the TIC first, then any command will be issued.
-+typedef struct touch_feedback_hdr
-+{
-+    u32  feedback_cmd_type;    // use values from TOUCH_FEEDBACK_CMD_TYPES
-+    u32  payload_size_bytes;   // The amount of data to be written to the sensor, not including the header
-+    u32  buffer_id;           // The ID of the raw data buffer that generated this feedback data
-+    u32  protocol_ver;        // Must match protocol version of the EDS
-+    u32  feedback_data_type;   // use values from TOUCH_FEEDBACK_DATA_TYPES. This is not relevant if PayloadSizeBytes is 0
-+    u32  spi_offest;          // The offset from TOUCH_DATA_WINDOW_OFFSET at which to write the Payload data. Maximum offset is 0x1EFFF.
-+    u8   reserved[40];       // Padding to extend header to full 64 bytes and allow for growth
-+} touch_feedback_hdr_t;
-+C_ASSERT(sizeof(touch_feedback_hdr_t) == 64);
-+
-+typedef struct touch_feedback_buffer
-+{
-+    touch_feedback_hdr_t  Header;
-+    u8               feedback_data[1];    // used to access the feedback data as an array and keep the compilers happy. Actual size of this array is Header.PayloadSizeBytes
-+} touch_feedback_buffer_t;
-+
-+
-+//
-+// This data structure describes the header prepended to all data
-+// written to the touch IC at the bulk data write (TOUCH_DATA_WINDOW_OFFSET + TOUCH_FEEDBACK_HDR.SpiOffest) address.
-+typedef enum touch_write_data_type
-+{
-+    TOUCH_WRITE_DATA_TYPE_FW_LOAD = 0,
-+    TOUCH_WRITE_DATA_TYPE_DATA_LOAD,
-+    TOUCH_WRITE_DATA_TYPE_FEEDBACK,
-+    TOUCH_WRITE_DATA_TYPE_SET_FEATURES,
-+    TOUCH_WRITE_DATA_TYPE_GET_FEATURES,
-+    TOUCH_WRITE_DATA_TYPE_OUTPUT_REPORT,
-+    TOUCH_WRITE_DATA_TYPE_NO_DATA_USE_DEFAULTS,
-+    TOUCH_WRITE_DATA_TYPE_MAX
-+} touch_write_data_type_t;
-+C_ASSERT(sizeof(touch_write_data_type_t) == 4);
-+
-+typedef struct touch_write_hdr
-+{
-+    u32  write_data_type;   // Use values from TOUCH_WRITE_DATA_TYPE
-+    u32  write_data_len;    // This field designates the amount of data to follow
-+} touch_write_hdr_t;
-+C_ASSERT(sizeof(touch_write_hdr_t) == 8);
-+
-+typedef struct touch_write_data
-+{
-+    touch_write_hdr_t header;
-+    u8           write_data[1];   // used to access the write data as an array and keep the compilers happy. Actual size of this array is Header.WriteDataLen
-+} touch_write_data_t;
-+
-+#pragma pack()
-+
-+#endif // _TOUCH_SENSOR_REGS_H
-diff --git a/drivers/misc/ipts/ipts-state.h b/drivers/misc/ipts/ipts-state.h
-new file mode 100644
-index 0000000..39a2eaf
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-state.h
-@@ -0,0 +1,29 @@
-+/*
-+ * Intel Precise Touch & Stylus state codes
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_STATE_H_
-+#define _IPTS_STATE_H_
-+
-+/* ipts driver states */
-+typedef enum ipts_state {
-+	IPTS_STA_NONE,
-+	IPTS_STA_INIT,
-+	IPTS_STA_RESOURCE_READY,
-+	IPTS_STA_HID_STARTED,
-+	IPTS_STA_RAW_DATA_STARTED,
-+	IPTS_STA_STOPPING
-+} ipts_state_t;
-+
-+#endif // _IPTS_STATE_H_
-diff --git a/drivers/misc/ipts/ipts.h b/drivers/misc/ipts/ipts.h
-new file mode 100644
-index 0000000..1fcd021
---- /dev/null
-+++ b/drivers/misc/ipts/ipts.h
-@@ -0,0 +1,200 @@
-+/*
-+ *
-+ * Intel Management Engine Interface (Intel MEI) Client Driver for IPTS
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_H_
-+#define _IPTS_H_
-+
-+#include <linux/types.h>
-+#include <linux/mei_cl_bus.h>
-+#include <linux/hid.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts-mei-msgs.h"
-+#include "ipts-state.h"
-+#include "ipts-binary-spec.h"
-+
-+//#define ENABLE_IPTS_DEBUG		/* enable IPTS debug */
-+
-+#ifdef ENABLE_IPTS_DEBUG
-+
-+#define ipts_info(ipts, format, arg...) do {\
-+	dev_info(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+#define ipts_dbg(ipts, format, arg...) do {\
-+	dev_info(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+//#define RUN_DBG_THREAD
-+
-+#else
-+
-+#define ipts_info(ipts, format, arg...) do {} while(0);
-+#define ipts_dbg(ipts, format, arg...) do {} while(0);
-+
-+#endif
-+
-+#define ipts_err(ipts, format, arg...) do {\
-+	dev_err(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+#define HID_PARALLEL_DATA_BUFFERS	TOUCH_SENSOR_MAX_DATA_BUFFERS
-+
-+#define IPTS_MAX_RETRY			3
-+
-+typedef struct ipts_buffer_info {
-+	char *addr;
-+	dma_addr_t dma_addr;
-+} ipts_buffer_info_t;
-+
-+typedef struct ipts_gfx_info {
-+	u64     gfx_handle;
-+	intel_ipts_ops_t ipts_ops;
-+} ipts_gfx_info_t;
-+
-+typedef struct ipts_resource {
-+	/* ME & Gfx resource */
-+	ipts_buffer_info_t touch_data_buffer_raw[HID_PARALLEL_DATA_BUFFERS];
-+	ipts_buffer_info_t touch_data_buffer_hid;
-+
-+	ipts_buffer_info_t feedback_buffer[HID_PARALLEL_DATA_BUFFERS];
-+
-+	ipts_buffer_info_t hid2me_buffer;
-+	u32 hid2me_buffer_size;
-+
-+	u8 wq_item_size;
-+	intel_ipts_wq_info_t wq_info;
-+
-+	/* ME2HID buffer */
-+	char *me2hid_buffer;
-+
-+	/* Gfx specific resource */
-+	ipts_buffer_info_t raw_data_mode_output_buffer
-+	    [HID_PARALLEL_DATA_BUFFERS][MAX_NUM_OUTPUT_BUFFERS];
-+
-+	int num_of_outputs;
-+
-+	bool default_resource_ready;
-+	bool raw_data_resource_ready;
-+} ipts_resource_t;
-+
-+typedef struct ipts_info {
-+	struct mei_cl_device *cldev;
-+	struct hid_device *hid;
-+
-+	struct work_struct init_work;
-+	struct work_struct raw_data_work;
-+	struct work_struct gfx_status_work;
-+
-+	struct task_struct *event_loop;
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+        struct dentry *dbgfs_dir;
-+#endif
-+
-+	ipts_state_t	state;
-+
-+	touch_sensor_mode_t	sensor_mode;
-+	touch_sensor_get_device_info_rsp_data_t device_info;
-+	ipts_resource_t	resource;
-+	u8		hid_input_report[HID_MAX_BUFFER_SIZE];
-+	int		num_of_parallel_data_buffers;
-+	bool		hid_desc_ready;
-+
-+	int current_buffer_index;
-+	int last_buffer_completed;
-+	int *last_submitted_id;
-+
-+	ipts_gfx_info_t gfx_info;
-+	u64		kernel_handle;
-+	int             gfx_status;
-+	bool		display_status;
-+
-+	bool		switch_sensor_mode;
-+	touch_sensor_mode_t	new_sensor_mode;
-+
-+	int		retry;
-+	bool		restart;
-+} ipts_info_t;
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+int ipts_dbgfs_register(ipts_info_t *ipts, const char *name);
-+void ipts_dbgfs_deregister(ipts_info_t *ipts);
-+#else
-+static int ipts_dbgfs_register(ipts_info_t *ipts, const char *name);
-+static void ipts_dbgfs_deregister(ipts_info_t *ipts);
-+#endif /* CONFIG_DEBUG_FS */
-+
-+/* inline functions */
-+static inline void ipts_set_state(ipts_info_t *ipts, ipts_state_t state)
-+{
-+	ipts->state = state;
-+}
-+
-+static inline ipts_state_t ipts_get_state(const ipts_info_t *ipts)
-+{
-+	return ipts->state;
-+}
-+
-+static inline bool ipts_is_default_resource_ready(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.default_resource_ready;
-+}
-+
-+static inline bool ipts_is_raw_data_resource_ready(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.raw_data_resource_ready;
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_feedback_buffer(ipts_info_t *ipts,
-+								int buffer_idx)
-+{
-+	return &ipts->resource.feedback_buffer[buffer_idx];
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_touch_data_buffer_hid(ipts_info_t *ipts)
-+{
-+	return &ipts->resource.touch_data_buffer_hid;
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_output_buffers_by_parallel_id(
-+							ipts_info_t *ipts,
-+                                                        int parallel_idx)
-+{
-+	return &ipts->resource.raw_data_mode_output_buffer[parallel_idx][0];
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_hid2me_buffer(ipts_info_t *ipts)
-+{
-+	return &ipts->resource.hid2me_buffer;
-+}
-+
-+static inline void ipts_set_wq_item_size(ipts_info_t *ipts, u8 size)
-+{
-+	ipts->resource.wq_item_size = size;
-+}
-+
-+static inline u8 ipts_get_wq_item_size(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.wq_item_size;
-+}
-+
-+static inline int ipts_get_num_of_parallel_buffers(const ipts_info_t *ipts)
-+{
-+	return ipts->num_of_parallel_data_buffers;
-+}
-+
-+#endif // _IPTS_H_
-diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
-index e4b10b2..883b185 100644
---- a/drivers/misc/mei/hw-me-regs.h
-+++ b/drivers/misc/mei/hw-me-regs.h
-@@ -119,6 +119,7 @@
- 
- #define MEI_DEV_ID_SPT        0x9D3A  /* Sunrise Point */
- #define MEI_DEV_ID_SPT_2      0x9D3B  /* Sunrise Point 2 */
-+#define MEI_DEV_ID_SPT_4      0x9D3E  /* Sunrise Point 4 */
- #define MEI_DEV_ID_SPT_H      0xA13A  /* Sunrise Point H */
- #define MEI_DEV_ID_SPT_H_2    0xA13B  /* Sunrise Point H 2 */
- 
-diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
-index ea4e152..4d301ba 100644
---- a/drivers/misc/mei/pci-me.c
-+++ b/drivers/misc/mei/pci-me.c
-@@ -86,6 +86,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
- 
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
-+	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_4, MEI_ME_PCH8_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)},
-diff --git a/include/linux/intel_ipts_if.h b/include/linux/intel_ipts_if.h
-new file mode 100644
-index 0000000..f329bbf
---- /dev/null
-+++ b/include/linux/intel_ipts_if.h
-@@ -0,0 +1,75 @@
-+/*
-+ *
-+ * GFX interface to support Intel Precise Touch & Stylus
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef INTEL_IPTS_IF_H
-+#define INTEL_IPTS_IF_H
-+
-+enum {
-+	IPTS_INTERFACE_V1 = 1,
-+};
-+
-+#define IPTS_BUF_FLAG_CONTIGUOUS	0x01
-+
-+#define IPTS_NOTIFY_STA_BACKLIGHT_OFF	0x00
-+#define IPTS_NOTIFY_STA_BACKLIGHT_ON	0x01
-+
-+typedef struct intel_ipts_mapbuffer {
-+	u32	size;
-+	u32	flags;
-+	void	*gfx_addr;
-+	void	*cpu_addr;
-+	u64	buf_handle;
-+	u64	phy_addr;
-+} intel_ipts_mapbuffer_t;
-+
-+typedef struct intel_ipts_wq_info {
-+	u64 db_addr;
-+	u64 db_phy_addr;
-+	u32 db_cookie_offset;
-+	u32 wq_size;
-+	u64 wq_addr;
-+	u64 wq_phy_addr;
-+	u64 wq_head_addr;	/* head of wq is managed by GPU */
-+	u64 wq_head_phy_addr;	/* head of wq is managed by GPU */
-+	u64 wq_tail_addr;	/* tail of wq is managed by CSME */
-+	u64 wq_tail_phy_addr;	/* tail of wq is managed by CSME */
-+} intel_ipts_wq_info_t;
-+
-+typedef struct intel_ipts_ops {
-+	int (*get_wq_info)(uint64_t gfx_handle, intel_ipts_wq_info_t *wq_info);
-+	int (*map_buffer)(uint64_t gfx_handle, intel_ipts_mapbuffer_t *mapbuffer);
-+	int (*unmap_buffer)(uint64_t gfx_handle, uint64_t buf_handle);
-+} intel_ipts_ops_t;
-+
-+typedef struct intel_ipts_callback {
-+        void (*workload_complete)(void *data);
-+        void (*notify_gfx_status)(u32 status, void *data);
-+} intel_ipts_callback_t;
-+
-+typedef struct intel_ipts_connect {
-+        intel_ipts_callback_t ipts_cb;	/* input : callback addresses */
-+	void *data;			/* input : callback data */
-+        u32 if_version;			/* input : interface version */
-+
-+        u32 gfx_version;		/* output : gfx version */
-+        u64 gfx_handle;			/* output : gfx handle */
-+	intel_ipts_ops_t ipts_ops;	/* output : gfx ops for IPTS */
-+} intel_ipts_connect_t;
-+
-+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect);
-+void intel_ipts_disconnect(uint64_t gfx_handle);
-+
-+#endif // INTEL_IPTS_IF_H

+ 0 - 119
patches/4.15/keyboards_and_covers.patch

@@ -1,119 +0,0 @@
-diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
-index a0baa5b..3e03ced8 100644
---- a/drivers/hid/hid-ids.h
-+++ b/drivers/hid/hid-ids.h
-@@ -770,11 +770,22 @@
- #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1 0x0732
- #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_600  0x0750
- #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500	0x076c
--#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD 0x00e3
--#define USB_DEVICE_ID_MS_SURFACE_PRO_2   0x0799
--#define USB_DEVICE_ID_MS_TOUCH_COVER_2   0x07a7
--#define USB_DEVICE_ID_MS_TYPE_COVER_2    0x07a9
--#define USB_DEVICE_ID_MS_POWER_COVER     0x07da
-+#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD	0x00e3
-+#define USB_DEVICE_ID_MS_SURFACE_PRO_2		0x0799
-+#define USB_DEVICE_ID_MS_TOUCH_COVER_2		0x07a7
-+#define USB_DEVICE_ID_MS_TYPE_COVER_2		0x07a9
-+#define USB_DEVICE_ID_MS_TYPE_COVER_3		0x07de
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3	0x07dc
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1	0x07de
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2	0x07e2
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP	0x07dd
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4	0x07e8
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1	0x07e4
-+#define USB_DEVICE_ID_MS_SURFACE_BOOK		0x07cd
-+#define USB_DEVICE_ID_MS_SURFACE_BOOK_2		0x0922
-+#define USB_DEVICE_ID_MS_SURFACE_LAPTOP		0xf001
-+#define HID_DEVICE_ID_MS_SURFACE_LAPTOP		0xf001
-+#define USB_DEVICE_ID_MS_POWER_COVER		0x07da
- 
- #define USB_VENDOR_ID_MOJO		0x8282
- #define USB_DEVICE_ID_RETRO_ADAPTER	0x3201
-diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
-index 65ea23b..00ce3be 100644
---- a/drivers/hid/hid-multitouch.c
-+++ b/drivers/hid/hid-multitouch.c
-@@ -1638,6 +1638,58 @@ static const struct hid_device_id mt_devices[] = {
- 		HID_USB_DEVICE(USB_VENDOR_ID_LG,
- 			USB_DEVICE_ID_LG_MELFAS_MT) },
- 
-+	/* Microsoft Touch Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_TOUCH_COVER_2) },
-+
-+	/* Microsoft Type Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_2) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_3) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_4) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1) },
-+
-+	/* Microsoft Surface Book */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_SURFACE_BOOK) },
-+
-+	/* Microsoft Surface Book 2 */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_SURFACE_BOOK_2) },
-+
-+	/* Microsoft Surface Laptop */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
-+			USB_VENDOR_ID_MICROSOFT,
-+			HID_DEVICE_ID_MS_SURFACE_LAPTOP) },
-+
-+	/* Microsoft Power Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_POWER_COVER) },
-+
- 	/* MosArt panels */
- 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
- 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
-diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
-index 331f7f3..6ff429f 100644
---- a/drivers/hid/usbhid/hid-quirks.c
-+++ b/drivers/hid/usbhid/hid-quirks.c
-@@ -108,8 +108,18 @@ static const struct hid_blacklist {
- 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL },
- 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
- 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS },
--	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
- 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK_2, HID_QUIRK_NO_INIT_REPORTS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_LAPTOP, HID_QUIRK_NO_INIT_REPORTS },
- 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
- 	{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
- 	{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },

+ 0 - 20
patches/4.15/sdcard_reader.patch

@@ -1,20 +0,0 @@
-From fbd83f772a3be3a00bae323f6d71a59b26352c57 Mon Sep 17 00:00:00 2001
-From: Jake Day <jake@ninebysix.com>
-Date: Fri, 2 Feb 2018 11:22:21 -0500
-Subject: fix for surface sd card reader
-
-
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index cf7bbcb..826fdb8 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -4047,7 +4047,8 @@ void usb_enable_lpm(struct usb_device *udev)
- 	if (!udev || !udev->parent ||
- 			udev->speed < USB_SPEED_SUPER ||
- 			!udev->lpm_capable ||
--			udev->state < USB_STATE_DEFAULT)
-+			udev->state < USB_STATE_DEFAULT ||
-+			!udev->bos || !udev->bos->ss_cap)
- 		return;
- 
- 	udev->lpm_disable_count--;

+ 0 - 510
patches/4.15/surfaceacpi.patch

@@ -1,510 +0,0 @@
-diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
-index 51ebc5a..244fa92 100644
---- a/drivers/platform/x86/Kconfig
-+++ b/drivers/platform/x86/Kconfig
-@@ -1155,6 +1155,15 @@ config SURFACE_3_BUTTON
- 	---help---
- 	  This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet.
- 
-+config ACPI_SURFACE
-+	tristate "Microsoft Surface Extras"
-+	depends on ACPI
-+	depends on ACPI_WMI
-+	depends on INPUT
-+	---help---
-+	  This driver adds support for access to certain system events
-+	  on Microsoft Surface devices.
-+
- config INTEL_PUNIT_IPC
- 	tristate "Intel P-Unit IPC Driver"
- 	---help---
-diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
-index 2ba6cb7..bcb0dd9 100644
---- a/drivers/platform/x86/Makefile
-+++ b/drivers/platform/x86/Makefile
-@@ -81,6 +81,7 @@ obj-$(CONFIG_INTEL_PMC_IPC)	+= intel_pmc_ipc.o
- obj-$(CONFIG_SILEAD_DMI)	+= silead_dmi.o
- obj-$(CONFIG_SURFACE_PRO3_BUTTON)	+= surfacepro3_button.o
- obj-$(CONFIG_SURFACE_3_BUTTON)	+= surface3_button.o
-+obj-$(CONFIG_ACPI_SURFACE)	+= surface_acpi.o
- obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
- obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU)	+= intel_bxtwc_tmu.o
- obj-$(CONFIG_INTEL_TELEMETRY)	+= intel_telemetry_core.o \
-diff --git a/drivers/platform/x86/surface_acpi.c b/drivers/platform/x86/surface_acpi.c
-new file mode 100644
-index 0000000..bee15e7
---- /dev/null
-+++ b/drivers/platform/x86/surface_acpi.c
-@@ -0,0 +1,472 @@
-+/*
-+ *  surface_acpi.c - Microsoft Surface ACPI Notify
-+ *
-+ *  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.
-+ *
-+ *  The full GNU General Public License is included in this distribution in
-+ *  the file called "COPYING".
-+ */
-+
-+#define SURFACE_ACPI_VERSION	"0.1"
-+#define SURFACE_GEN_VERSION		0x08
-+#define PROC_SURFACE			"surface"
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/acpi.h>
-+#include <linux/power_supply.h>
-+#include <linux/thermal.h>
-+#include <linux/dmi.h>
-+#include <linux/seq_file.h>
-+#include <acpi/acpi_bus.h>
-+#include <acpi/acpi_drivers.h>
-+
-+MODULE_AUTHOR("Jake Day");
-+MODULE_DESCRIPTION("Microsoft Surface ACPI Notify Driver");
-+MODULE_LICENSE("GPL");
-+
-+#define SUR_METHOD_DSM			"_DSM"
-+#define SUR_METHOD_REG			"_REG"
-+#define SUR_METHOD_STA			"_STA"
-+#define SUR_METHOD_INI			"_INI"
-+#define SUR_METHOD_CRS			"_CRS"
-+
-+#define SUR_QUERY_DEVICE		0x00
-+#define SUR_SET_DVER			0x01
-+#define SUR_GET_BOARD_REVID		0x02
-+#define SUR_BAT1_STATE_CHANGE	0x03
-+#define SUR_BAT1_INFO_CHANGE	0x04
-+#define SUR_PSU_STATE_CHANGE	0x05
-+#define SUR_PSU_INFO_CHANGE		0x06
-+#define SUR_BAT2_STATE_CHANGE	0x07
-+#define SUR_BAT2_INFO_CHANGE	0x08
-+#define SUR_SENSOR_TRIP_POINT	0x09
-+
-+#define REG_AVAILABLE			0x01
-+#define REG_INIT				0x09
-+
-+static char SURFACE_EVENT_GUID[] = "93b666c5-70c6-469f-a215-3d487c91ab3c";
-+static char SUR_SAN_RQST[] = "\\_SB._SAN.RQST";
-+static char SUR_SAN_RQSX[] = "\\_SB._SAN.RQSX";
-+
-+struct surface_acpi_dev {
-+	acpi_handle handle;
-+	acpi_handle rqst_handle;
-+	acpi_handle rqsx_handle;
-+
-+	struct acpi_device *san_dev;
-+	struct acpi_device *ssh_dev;
-+	struct acpi_device *bat1_dev;
-+	struct acpi_device *bat2_dev;
-+	struct acpi_device *psu_dev;
-+
-+	unsigned int bat1_attached:1;
-+	unsigned int bat2_attached:1;
-+	unsigned int psu_registered:1;
-+};
-+
-+static struct surface_acpi_dev *surface_acpi;
-+
-+static struct proc_dir_entry *surface_proc_dir;
-+
-+static acpi_status surface_acpi_check_status(struct acpi_device *dev)
-+{
-+	unsigned long long value;
-+	acpi_status status;
-+
-+	if (acpi_has_method(dev->handle, SUR_METHOD_STA)) {
-+		status = acpi_evaluate_integer(dev->handle,
-+				SUR_METHOD_STA, NULL, &value);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static acpi_status surface_acpi_san_reg(void)
-+{
-+	union acpi_object in_objs[2], out_objs[1];
-+	struct acpi_object_list params;
-+	struct acpi_buffer results;
-+	acpi_status status;
-+
-+	params.count = ARRAY_SIZE(in_objs);
-+	params.pointer = in_objs;
-+	in_objs[0].type = ACPI_TYPE_INTEGER;
-+	in_objs[0].integer.value = REG_INIT;
-+	in_objs[1].type = ACPI_TYPE_INTEGER;
-+	in_objs[1].integer.value = REG_AVAILABLE;
-+	results.length = sizeof(out_objs);
-+	results.pointer = out_objs;
-+
-+	if (acpi_has_method(surface_acpi->handle, SUR_METHOD_REG)) {
-+		status = acpi_evaluate_object(surface_acpi->handle,
-+				SUR_METHOD_REG, &params, &results);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static acpi_status surface_acpi_event_handler(u32 event)
-+{
-+	union acpi_object in_objs[4], out_objs[5];
-+	struct acpi_object_list params;
-+	struct acpi_buffer results;
-+	acpi_status status;
-+
-+	params.count = ARRAY_SIZE(in_objs);
-+	params.pointer = in_objs;
-+	in_objs[0].type = ACPI_TYPE_BUFFER;
-+	in_objs[0].buffer.length = sizeof(SURFACE_EVENT_GUID);
-+	in_objs[0].buffer.pointer = SURFACE_EVENT_GUID;
-+	in_objs[1].type = ACPI_TYPE_INTEGER;
-+	in_objs[1].integer.value = SUR_QUERY_DEVICE;
-+	in_objs[2].type = ACPI_TYPE_INTEGER;
-+	in_objs[2].integer.value = event;
-+	in_objs[3].type = ACPI_TYPE_PACKAGE;
-+	in_objs[3].package.count = 0;
-+	in_objs[3].package.elements = SURFACE_GEN_VERSION;
-+	results.length = sizeof(out_objs);
-+	results.pointer = out_objs;
-+
-+	if (acpi_has_method(surface_acpi->handle, SUR_METHOD_DSM)) {
-+		status = acpi_evaluate_object(surface_acpi->handle,
-+				SUR_METHOD_DSM, &params, &results);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static void surface_acpi_san_load(void)
-+{
-+	acpi_status ret;
-+
-+	ret = surface_acpi_event_handler(SUR_SET_DVER);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error setting Driver Version\n");
-+
-+	ret = surface_acpi_event_handler(SUR_SENSOR_TRIP_POINT);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error setting Sensor Trip Point\n");
-+
-+	ret = surface_acpi_event_handler(SUR_BAT1_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error attaching BAT1\n");
-+	else
-+		surface_acpi->bat1_attached = 1;
-+
-+	ret = surface_acpi_event_handler(SUR_BAT2_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error attaching BAT2\n");
-+	else
-+		surface_acpi->bat2_attached = 1;
-+
-+	ret = surface_acpi_event_handler(SUR_PSU_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error registering PSU\n");
-+	else
-+		surface_acpi->psu_registered = 1;
-+}
-+
-+static acpi_status surface_acpi_ssh_initialize(void)
-+{
-+	acpi_status status;
-+
-+	if (acpi_has_method(surface_acpi->ssh_dev->handle, SUR_METHOD_INI)) {
-+		status = acpi_evaluate_object(surface_acpi->ssh_dev->handle,
-+				SUR_METHOD_INI, NULL, NULL);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static int bat1_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "attached: %d\n", surface_acpi->bat1_attached);
-+	return 0;
-+}
-+
-+static int bat1_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, bat1_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations bat1_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= bat1_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int bat2_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "attached: %d\n", surface_acpi->bat2_attached);
-+	return 0;
-+}
-+
-+static int bat2_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, bat2_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations bat2_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= bat2_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int psu_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "registered: %d\n", surface_acpi->psu_registered);
-+	return 0;
-+}
-+
-+static int psu_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, psu_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations psu_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= psu_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int version_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "driver: %s\n", SURFACE_ACPI_VERSION);
-+	return 0;
-+}
-+
-+static int version_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, version_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations version_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= version_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static void create_surface_proc_entries(void)
-+{
-+	proc_create_data("BAT1", 0, surface_proc_dir,
-+			 &bat1_proc_fops, surface_acpi->bat1_attached);
-+	proc_create_data("BAT2", 0, surface_proc_dir,
-+			 &bat2_proc_fops, surface_acpi->bat2_attached);
-+	proc_create_data("ADP1", 0, surface_proc_dir,
-+			 &psu_proc_fops, surface_acpi->psu_registered);
-+	proc_create_data("version", 0, surface_proc_dir,
-+			 &version_proc_fops, SURFACE_ACPI_VERSION);
-+}
-+
-+static void remove_surface_proc_entries(void)
-+{
-+	remove_proc_entry("BAT1", surface_proc_dir);
-+	remove_proc_entry("BAT2", surface_proc_dir);
-+	remove_proc_entry("ADP1", surface_proc_dir);
-+	remove_proc_entry("version", surface_proc_dir);
-+}
-+
-+static void surface_acpi_notify(struct acpi_device *dev, u32 event)
-+{
-+	pr_info("surface_acpi: Event received %x\n", event);
-+}
-+
-+static void surface_acpi_register_rqst_handler(void)
-+{
-+	acpi_status status;
-+
-+	status = acpi_get_handle(NULL, SUR_SAN_RQST, &surface_acpi->rqst_handle);
-+	if (ACPI_FAILURE(status)) {
-+		pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+	}
-+}
-+
-+static void surface_acpi_register_rqsx_handler(void)
-+{
-+	acpi_status status;
-+
-+	status = acpi_get_handle(NULL, SUR_SAN_RQSX, &surface_acpi->rqsx_handle);
-+	if (ACPI_FAILURE(status)) {
-+		pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+	}
-+}
-+
-+static acpi_status surface_acpi_walk_callback(acpi_handle handle, u32 level,
-+						void *context, void **return_value)
-+{
-+	struct acpi_device_info *info;
-+
-+	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
-+		pr_warn("method: name: %4.4s, args %X\n",
-+			(char *)&info->name, info->param_count);
-+
-+		kfree(info);
-+	}
-+
-+	return AE_OK;
-+}
-+
-+static void surface_acpi_walk_namespace(struct acpi_device *dev)
-+{
-+	acpi_status status;
-+
-+	status = acpi_walk_namespace(ACPI_TYPE_METHOD,
-+			dev->handle, 1, surface_acpi_walk_callback,
-+			NULL, NULL, NULL);
-+	if (ACPI_FAILURE(status))
-+		pr_warn("surface_acpi: Unable to walk acpi resources\n");
-+}
-+
-+static int surface_acpi_add(struct acpi_device *dev)
-+{
-+	if (!surface_acpi)
-+	{
-+		surface_acpi = kzalloc(sizeof(*surface_acpi), GFP_KERNEL);
-+		if (!surface_acpi)
-+			return AE_NO_MEMORY;
-+	}
-+
-+	if (acpi_has_method(dev->handle, SUR_METHOD_DSM))
-+	{
-+		pr_info("surface_acpi: Attaching device MSHW0091\n");
-+
-+		surface_acpi->san_dev = dev;
-+		surface_acpi->handle = dev->handle;
-+
-+		surface_acpi_walk_namespace(surface_acpi->san_dev);
-+		surface_acpi_check_status(surface_acpi->san_dev);
-+
-+		surface_acpi_register_rqst_handler();
-+		surface_acpi_register_rqsx_handler();
-+
-+		surface_acpi_san_reg();
-+		surface_acpi_san_load();
-+
-+		create_surface_proc_entries();
-+	}
-+	else
-+	{
-+		pr_info("surface_acpi: Attaching device MSHW0084\n");
-+
-+		surface_acpi->ssh_dev = dev;
-+
-+		surface_acpi_walk_namespace(surface_acpi->ssh_dev);
-+		surface_acpi_check_status(surface_acpi->ssh_dev);
-+
-+		surface_acpi_ssh_initialize();
-+		//surface_acpi_ssh_load();
-+	}
-+
-+	return AE_OK;
-+}
-+
-+static int surface_acpi_remove(struct acpi_device *dev)
-+{
-+	remove_surface_proc_entries();
-+
-+	return AE_OK;
-+}
-+
-+static const struct acpi_device_id surface_device_ids[] = {
-+	{"MSHW0091", 0},
-+	{"MSHW0084", 0},
-+	{"", 0},
-+};
-+MODULE_DEVICE_TABLE(acpi, surface_device_ids);
-+
-+static struct acpi_driver surface_acpi_driver = {
-+	.name	= "surface_acpi",
-+	.owner	= THIS_MODULE,
-+	.ids	= surface_device_ids,
-+	.flags	= ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-+	.ops	= {
-+		.add	= surface_acpi_add,
-+		.remove = surface_acpi_remove,
-+		.notify = surface_acpi_notify,
-+	},
-+};
-+
-+static int __init surface_acpi_init(void)
-+{
-+	int ret;
-+
-+	pr_info("surface_acpi: Microsoft Surface ACPI Notify version %s\n",
-+	       SURFACE_ACPI_VERSION);
-+
-+	surface_proc_dir = proc_mkdir(PROC_SURFACE, acpi_root_dir);
-+	if (!surface_proc_dir) {
-+		pr_err("surface_acpi: Unable to create proc dir " PROC_SURFACE "\n");
-+		return -ENODEV;
-+	}
-+
-+	ret = acpi_bus_register_driver(&surface_acpi_driver);
-+	if (ret) {
-+		pr_err("surface_acpi: Failed to register ACPI driver: %d\n", ret);
-+		remove_proc_entry(PROC_SURFACE, acpi_root_dir);
-+	}
-+
-+	return ret;
-+}
-+
-+static void __exit surface_acpi_exit(void)
-+{
-+	acpi_bus_unregister_driver(&surface_acpi_driver);
-+	if (surface_proc_dir)
-+		remove_proc_entry(PROC_SURFACE, acpi_root_dir);
-+}
-+
-+module_init(surface_acpi_init);
-+module_exit(surface_acpi_exit);

+ 0 - 36
patches/4.15/surfacedock.patch

@@ -1,36 +0,0 @@
-From 3600aaa37a16777a07aa34672f12e30a1ae4d95b Mon Sep 17 00:00:00 2001
-From: Jake Day <jake@ninebysix.com>
-Date: Fri, 2 Feb 2018 11:21:06 -0500
-Subject: support for surface dock
-
-
-diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
-index 05dca3e..59c2fcc 100644
---- a/drivers/net/usb/cdc_ether.c
-+++ b/drivers/net/usb/cdc_ether.c
-@@ -807,13 +807,6 @@ static const struct usb_device_id	products[] = {
- 	.driver_info = 0,
- },
- 
--/* Microsoft Surface 3 dock (based on Realtek RTL8153) */
--{
--	USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM,
--			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
--	.driver_info = 0,
--},
--
- 	/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
- {
- 	USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
-diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
-index 0657203..0a52ea0 100644
---- a/drivers/net/usb/r8152.c
-+++ b/drivers/net/usb/r8152.c
-@@ -5323,7 +5323,6 @@ static const struct usb_device_id rtl8152_table[] = {
- 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)},
--	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x304f)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3062)},

+ 0 - 281
patches/4.15/wifi.patch

@@ -1,281 +0,0 @@
-diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
-index 042a1d0..fc9041f 100644
---- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
-+++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
-@@ -200,8 +200,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
- 
- 	do {
- 		/* Check if AMSDU can accommodate this MSDU */
--		if ((skb_aggr->len + skb_src->len + LLC_SNAP_LEN) >
--		    adapter->tx_buf_size)
-+		if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN))
- 			break;
- 
- 		skb_src = skb_dequeue(&pra_list->skb_head);
-diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
-index f324011..7f31e43 100644
---- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
-+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
-@@ -416,6 +416,9 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
- 
- 	ps_mode = enabled;
- 
-+	mwifiex_dbg(priv->adapter, ERROR, "overriding ps_mode to false\n");
-+	ps_mode = 0;
-+
- 	return mwifiex_drv_set_power(priv, &ps_mode);
- }
- 
-diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
-index dcc529e..3998ffb 100644
---- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
-+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
-@@ -995,6 +995,7 @@ mwifiex_cmd_timeout_func(struct timer_list *t)
- 		if (cmd_node->wait_q_enabled) {
- 			adapter->cmd_wait_q.status = -ETIMEDOUT;
- 			mwifiex_cancel_pending_ioctl(adapter);
-+			adapter->cmd_sent = false;
- 		}
- 	}
- 	if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
-diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
-index e1aa860..328829b 100644
---- a/drivers/net/wireless/marvell/mwifiex/init.c
-+++ b/drivers/net/wireless/marvell/mwifiex/init.c
-@@ -60,7 +60,7 @@ static void wakeup_timer_fn(struct timer_list *t)
- 	adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
- 	mwifiex_cancel_all_pending_cmd(adapter);
- 
--	if (adapter->if_ops.card_reset && !adapter->hs_activated)
-+	if (adapter->if_ops.card_reset)
- 		adapter->if_ops.card_reset(adapter);
- }
- 
-diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
-index a96bd7e..79b026f 100644
---- a/drivers/net/wireless/marvell/mwifiex/main.c
-+++ b/drivers/net/wireless/marvell/mwifiex/main.c
-@@ -163,6 +163,7 @@ void mwifiex_queue_main_work(struct mwifiex_adapter *adapter)
- 	spin_lock_irqsave(&adapter->main_proc_lock, flags);
- 	if (adapter->mwifiex_processing) {
- 		adapter->more_task_flag = true;
-+		adapter->more_rx_task_flag = true;
- 		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
- 	} else {
- 		spin_unlock_irqrestore(&adapter->main_proc_lock, flags);
-@@ -171,18 +172,20 @@ void mwifiex_queue_main_work(struct mwifiex_adapter *adapter)
- }
- EXPORT_SYMBOL_GPL(mwifiex_queue_main_work);
- 
--static void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter)
-+void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter)
- {
- 	unsigned long flags;
- 
- 	spin_lock_irqsave(&adapter->rx_proc_lock, flags);
- 	if (adapter->rx_processing) {
-+		adapter->more_rx_task_flag = true;
- 		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 	} else {
- 		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 		queue_work(adapter->rx_workqueue, &adapter->rx_work);
- 	}
- }
-+EXPORT_SYMBOL_GPL(mwifiex_queue_rx_work);
- 
- static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
- {
-@@ -192,13 +195,14 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
- 
- 	spin_lock_irqsave(&adapter->rx_proc_lock, flags);
- 	if (adapter->rx_processing || adapter->rx_locked) {
-+		adapter->more_rx_task_flag = true;
- 		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 		goto exit_rx_proc;
- 	} else {
- 		adapter->rx_processing = true;
- 		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 	}
--
-+rx_process_start:
- 	/* Check for Rx data */
- 	while ((skb = skb_dequeue(&adapter->rx_data_q))) {
- 		atomic_dec(&adapter->rx_pending);
-@@ -220,6 +224,11 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter)
- 		}
- 	}
- 	spin_lock_irqsave(&adapter->rx_proc_lock, flags);
-+	if (adapter->more_rx_task_flag) {
-+		adapter->more_rx_task_flag = false;
-+		spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
-+		goto rx_process_start;
-+	}
- 	adapter->rx_processing = false;
- 	spin_unlock_irqrestore(&adapter->rx_proc_lock, flags);
- 
-@@ -283,10 +292,10 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter)
- 				mwifiex_process_hs_config(adapter);
- 			if (adapter->if_ops.process_int_status)
- 				adapter->if_ops.process_int_status(adapter);
-+			if (adapter->rx_work_enabled && adapter->data_received)
-+				mwifiex_queue_rx_work(adapter);
- 		}
- 
--		if (adapter->rx_work_enabled && adapter->data_received)
--			mwifiex_queue_rx_work(adapter);
- 
- 		/* Need to wake up the card ? */
- 		if ((adapter->ps_state == PS_STATE_SLEEP) &&
-diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
-index 154c079..4205344 100644
---- a/drivers/net/wireless/marvell/mwifiex/main.h
-+++ b/drivers/net/wireless/marvell/mwifiex/main.h
-@@ -889,6 +889,7 @@ struct mwifiex_adapter {
- 	spinlock_t main_proc_lock;
- 	u32 mwifiex_processing;
- 	u8 more_task_flag;
-+	u8 more_rx_task_flag;
- 	u16 tx_buf_size;
- 	u16 curr_tx_buf_size;
- 	/* sdio single port rx aggregation capability */
-@@ -1661,6 +1662,7 @@ void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter, void *drv_info,
- 				int drv_info_size);
- void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
- void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
-+void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter);
- int mwifiex_get_wakeup_reason(struct mwifiex_private *priv, u16 action,
- 			      int cmd_type,
- 			      struct mwifiex_ds_wakeup_reason *wakeup_reason);
-diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
-index 9511f5f..4a4737c 100644
---- a/drivers/net/wireless/marvell/mwifiex/pcie.c
-+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
-@@ -1729,6 +1729,16 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
- 	}
- 
- 	rx_len = get_unaligned_le16(skb->data);
-+
-+
-+	if (rx_len == 0) {
-+		mwifiex_dbg(adapter, ERROR,
-+				    "0 byte cmdrsp\n");
-+		mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
-+					   PCI_DMA_FROMDEVICE);
-+		return 0;
-+	}
-+
- 	skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len);
- 	skb_trim(skb, rx_len);
- 
-diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
-index fb09014..5b8329e 100644
---- a/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
-+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmd.c
-@@ -2313,7 +2313,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
- 		if (ret)
- 			return -1;
- 
--		if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
-+		if (0 && priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
- 			/* Enable IEEE PS by default */
- 			priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP;
- 			ret = mwifiex_send_cmd(priv,
-@@ -2336,8 +2336,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
- 				return -1;
- 		}
- 
--		mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
--				 HostCmd_ACT_GEN_GET, 0, NULL, true);
-+		//mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REGION_CFG,
-+		//		 HostCmd_ACT_GEN_GET, 0, NULL, true);
- 	}
- 
- 	/* get tx rate */
-@@ -2369,7 +2369,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
- 	if (ret)
- 		return -1;
- 
--	if (!disable_auto_ds && first_sta &&
-+	if (0 && !disable_auto_ds && first_sta &&
- 	    priv->bss_type != MWIFIEX_BSS_TYPE_UAP) {
- 		/* Enable auto deep sleep */
- 		auto_ds.auto_ds = DEEP_SLEEP_ON;
-diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
-index 1bd4e13..27d2bac 100644
---- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
-+++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c
-@@ -48,9 +48,14 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
- 	struct host_cmd_ds_802_11_ps_mode_enh *pm;
- 	unsigned long flags;
- 
--	mwifiex_dbg(adapter, ERROR,
--		    "CMD_RESP: cmd %#x error, result=%#x\n",
--		    resp->command, resp->result);
-+	if (resp->command == 271 && resp->result == 2){
-+		// ignore this command as the firmware does not support it
-+	}
-+	else {
-+		mwifiex_dbg(adapter, ERROR,
-+				"CMD_RESP: cmd %#x error, result=%#x\n",
-+				resp->command, resp->result);
-+	}
- 
- 	if (adapter->curr_cmd->wait_q_enabled)
- 		adapter->cmd_wait_q.status = -1;
-diff --git a/drivers/net/wireless/marvell/mwifiex/usb.c b/drivers/net/wireless/marvell/mwifiex/usb.c
-index 4bc2448..d20fda1 100644
---- a/drivers/net/wireless/marvell/mwifiex/usb.c
-+++ b/drivers/net/wireless/marvell/mwifiex/usb.c
-@@ -144,6 +144,8 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter,
- 		skb_queue_tail(&adapter->rx_data_q, skb);
- 		adapter->data_received = true;
- 		atomic_inc(&adapter->rx_pending);
-+		if (adapter->rx_work_enabled)
-+			mwifiex_queue_rx_work(adapter);
- 		break;
- 	default:
- 		mwifiex_dbg(adapter, ERROR,
-diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
-index ffbf4e7..3ad81e3 100644
---- a/drivers/pci/pcie/portdrv_pci.c
-+++ b/drivers/pci/pcie/portdrv_pci.c
-@@ -150,6 +150,11 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
- 
- 	pci_save_state(dev);
- 
-+	/*
-+	 * D3cold disabled by default
-+	 */
-+	dev->d3cold_allowed = false;
-+
- 	if (pci_bridge_d3_possible(dev)) {
- 		/*
- 		 * Keep the port resumed 100ms to make sure things like
-diff --git a/net/wireless/sme.c b/net/wireless/sme.c
-index fdb3646..b44b23b 100644
---- a/net/wireless/sme.c
-+++ b/net/wireless/sme.c
-@@ -690,6 +690,11 @@ void __cfg80211_connect_result(struct net_device *dev,
- 		return;
- 	}
- 
-+	if (WARN_ON(!wdev->ssid_len)) {
-+		cfg80211_put_bss(wdev->wiphy, cr->bss);
-+		return;
-+	}
-+
- 	nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, cr,
- 				    GFP_KERNEL);
- 
-@@ -1105,7 +1110,7 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
- 	/*
- 	 * If we have an ssid_len, we're trying to connect or are
- 	 * already connected, so reject a new SSID unless it's the
--	 * same (which is the case for re-association.)
-+	 * same (which is the case for Re-Association.
- 	 */
- 	if (wdev->ssid_len &&
- 	    (wdev->ssid_len != connect->ssid_len ||
-diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl
-old mode 100755
-new mode 100644

+ 0 - 163
patches/4.16/acpica.patch

@@ -1,163 +0,0 @@
-diff --git a/drivers/acpi/acpica/dbdisply.c b/drivers/acpi/acpica/dbdisply.c
-index 5a606ea..7b5eb33 100644
---- a/drivers/acpi/acpica/dbdisply.c
-+++ b/drivers/acpi/acpica/dbdisply.c
-@@ -642,9 +642,8 @@ void acpi_db_display_object_type(char *object_arg)
- 		return;
- 	}
- 
--	acpi_os_printf("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n",
--		       ACPI_FORMAT_UINT64(info->address),
--		       info->current_status, info->flags);
-+	acpi_os_printf("ADR: %8.8X%8.8X, Flags: %X\n",
-+		       ACPI_FORMAT_UINT64(info->address), info->flags);
- 
- 	acpi_os_printf("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n",
- 		       info->highest_dstates[0], info->highest_dstates[1],
-diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c
-index d3b6b31..37b0b4c 100644
---- a/drivers/acpi/acpica/evevent.c
-+++ b/drivers/acpi/acpica/evevent.c
-@@ -204,6 +204,7 @@ u32 acpi_ev_fixed_event_detect(void)
- 	u32 fixed_status;
- 	u32 fixed_enable;
- 	u32 i;
-+	acpi_status status;
- 
- 	ACPI_FUNCTION_NAME(ev_fixed_event_detect);
- 
-@@ -211,8 +212,12 @@ u32 acpi_ev_fixed_event_detect(void)
- 	 * Read the fixed feature status and enable registers, as all the cases
- 	 * depend on their values. Ignore errors here.
- 	 */
--	(void)acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
--	(void)acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
-+	status = acpi_hw_register_read(ACPI_REGISTER_PM1_STATUS, &fixed_status);
-+	status |=
-+	    acpi_hw_register_read(ACPI_REGISTER_PM1_ENABLE, &fixed_enable);
-+	if (ACPI_FAILURE(status)) {
-+		return (int_status);
-+	}
- 
- 	ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
- 			  "Fixed Event Block: Enable %08X Status %08X\n",
-diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c
-index a8191d2..2ad13d8 100644
---- a/drivers/acpi/acpica/exdebug.c
-+++ b/drivers/acpi/acpica/exdebug.c
-@@ -88,14 +88,13 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
- 		return_VOID;
- 	}
- 
--	/* Null string or newline -- don't emit the line header */
-+	/* Newline -- don't emit the line header */
- 
- 	if (source_desc &&
- 	    (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) &&
- 	    (source_desc->common.type == ACPI_TYPE_STRING)) {
--		if ((source_desc->string.length == 0) ||
--		    ((source_desc->string.length == 1) &&
--		     (*source_desc->string.pointer == '\n'))) {
-+		if ((source_desc->string.length == 1) &&
-+		    (*source_desc->string.pointer == '\n')) {
- 			acpi_os_printf("\n");
- 			return_VOID;
- 		}
-diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c
-index 5026594..573a5f3 100644
---- a/drivers/acpi/acpica/nsdumpdv.c
-+++ b/drivers/acpi/acpica/nsdumpdv.c
-@@ -88,10 +88,9 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
- 		}
- 
- 		ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES,
--				      "    HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
-+				      "    HID: %s, ADR: %8.8X%8.8X\n",
- 				      info->hardware_id.value,
--				      ACPI_FORMAT_UINT64(info->address),
--				      info->current_status));
-+				      ACPI_FORMAT_UINT64(info->address));
- 		ACPI_FREE(info);
- 	}
- 
-diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
-index 1069662..0a9c600 100644
---- a/drivers/acpi/acpica/nsxfname.c
-+++ b/drivers/acpi/acpica/nsxfname.c
-@@ -241,7 +241,7 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
-  *              namespace node and possibly by running several standard
-  *              control methods (Such as in the case of a device.)
-  *
-- * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
-+ * For Device and Processor objects, run the Device _HID, _UID, _CID,
-  * _CLS, _ADR, _sx_w, and _sx_d methods.
-  *
-  * Note: Allocates the return buffer, must be freed by the caller.
-@@ -250,8 +250,9 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
-  * discovery namespace traversal. Therefore, no complex methods can be
-  * executed, especially those that access operation regions. Therefore, do
-  * not add any additional methods that could cause problems in this area.
-- * this was the fate of the _SUB method which was found to cause such
-- * problems and was removed (11/2015).
-+ * Because of this reason support for the following methods has been removed:
-+ * 1) _SUB method was removed (11/2015)
-+ * 2) _STA method was removed (02/2018)
-  *
-  ******************************************************************************/
- 
-@@ -374,20 +375,8 @@ acpi_get_object_info(acpi_handle handle,
- 		 * Notes: none of these methods are required, so they may or may
- 		 * not be present for this device. The Info->Valid bitfield is used
- 		 * to indicate which methods were found and run successfully.
--		 *
--		 * For _STA, if the method does not exist, then (as per the ACPI
--		 * specification), the returned current_status flags will indicate
--		 * that the device is present/functional/enabled. Otherwise, the
--		 * current_status flags reflect the value returned from _STA.
- 		 */
- 
--		/* Execute the Device._STA method */
--
--		status = acpi_ut_execute_STA(node, &info->current_status);
--		if (ACPI_SUCCESS(status)) {
--			valid |= ACPI_VALID_STA;
--		}
--
- 		/* Execute the Device._ADR method */
- 
- 		status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
-diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c
-index eb9dfac..11ce4e5 100644
---- a/drivers/acpi/acpica/psargs.c
-+++ b/drivers/acpi/acpica/psargs.c
-@@ -890,6 +890,10 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
- 						      ACPI_POSSIBLE_METHOD_CALL);
- 
- 			if (arg->common.aml_opcode == AML_INT_METHODCALL_OP) {
-+
-+				/* Free method call op and corresponding namestring sub-ob */
-+
-+				acpi_ps_free_op(arg->common.value.arg);
- 				acpi_ps_free_op(arg);
- 				arg = NULL;
- 				walk_state->arg_count = 1;
-diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
-index 4f077ed..220ef86 100644
---- a/include/acpi/actypes.h
-+++ b/include/acpi/actypes.h
-@@ -1191,7 +1191,6 @@ struct acpi_device_info {
- 	u8 flags;		/* Miscellaneous info */
- 	u8 highest_dstates[4];	/* _sx_d values: 0xFF indicates not valid */
- 	u8 lowest_dstates[5];	/* _sx_w values: 0xFF indicates not valid */
--	u32 current_status;	/* _STA value */
- 	u64 address;	/* _ADR value */
- 	struct acpi_pnp_device_id hardware_id;	/* _HID value */
- 	struct acpi_pnp_device_id unique_id;	/* _UID value */
-@@ -1205,7 +1204,6 @@ struct acpi_device_info {
- 
- /* Flags for Valid field above (acpi_get_object_info) */
- 
--#define ACPI_VALID_STA                  0x0001
- #define ACPI_VALID_ADR                  0x0002
- #define ACPI_VALID_HID                  0x0004
- #define ACPI_VALID_UID                  0x0008

+ 0 - 156
patches/4.16/cameras.patch

@@ -1,156 +0,0 @@
-diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
-index fd387bf..35ae5af 100644
---- a/drivers/media/usb/uvc/uvc_driver.c
-+++ b/drivers/media/usb/uvc/uvc_driver.c
-@@ -2353,6 +2353,46 @@ static const struct uvc_device_info uvc_quirk_force_y8 = {
-  * though they are compliant.
-  */
- static const struct usb_device_id uvc_ids[] = {
-+	/* Microsoft Surface Pro 3 Front */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x07be,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Pro 3 Rear */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x07bf,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Pro 4 Cam */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x090c,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Book Cam 1 */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x090b,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Book Cam 2 */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x091a,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
- 	/* LogiLink Wireless Webcam */
- 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
- 				| USB_DEVICE_ID_MATCH_INT_INFO,
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/Kconfig b/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-index 3f527f2..b882948 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-@@ -1,7 +1,7 @@
- config VIDEO_ATOMISP_OV5693
-        tristate "Omnivision ov5693 sensor support"
- 	depends on ACPI
--       depends on I2C && VIDEO_V4L2
-+	   depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
-        ---help---
- 	 This is a Video4Linux2 sensor-level driver for the Micron
- 	 ov5693 5 Mpixel camera.
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
-index 40d01bf..4f33294 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
-@@ -1335,11 +1335,15 @@ static int power_ctrl(struct v4l2_subdev *sd, bool flag)
- static int gpio_ctrl(struct v4l2_subdev *sd, bool flag)
- {
- 	struct ov5693_device *dev = to_ov5693_sensor(sd);
-+	int ret = 0;
- 
- 	if (!dev || !dev->platform_data)
- 		return -ENODEV;
- 
--	return dev->platform_data->gpio0_ctrl(sd, flag);
-+	if (dev->platform_data->gpio0_ctrl)
-+		ret = dev->platform_data->gpio0_ctrl(sd, flag);
-+
-+	return ret;
- }
- 
- static int __power_up(struct v4l2_subdev *sd)
-@@ -1707,7 +1711,7 @@ static int ov5693_detect(struct i2c_client *client)
- 					OV5693_SC_CMMN_CHIP_ID_L, &low);
- 	id = ((((u16) high) << 8) | (u16) low);
- 
--	if (id != OV5693_ID) {
-+	if (id != OV5690_ID && id != OV5693_ID) {
- 		dev_err(&client->dev, "sensor ID error 0x%x\n", id);
- 		return -ENODEV;
- 	}
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-index 68cfcb4..b4616ac 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-@@ -29,7 +29,7 @@
- #include <linux/v4l2-mediabus.h>
- #include <media/media-entity.h>
- 
--#include "../../include/linux/atomisp_platform.h"
-+#include "../../include/linux/atomisp_gmin_platform.h"
- 
- #define OV5693_POWER_UP_RETRY_NUM 5
- 
-@@ -72,7 +72,8 @@
-  * bits 7-0: min f-number denominator
-  */
- #define OV5693_F_NUMBER_RANGE 0x180a180a
--#define OV5693_ID	0x5690
-+#define OV5690_ID	0x5690
-+#define OV5693_ID	0x5693
- 
- #define OV5693_FINE_INTG_TIME_MIN 0
- #define OV5693_FINE_INTG_TIME_MAX_MARGIN 0
-diff --git a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-index d8b7183..d9d8c48 100644
---- a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-+++ b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-@@ -249,11 +249,13 @@ static struct gmin_cfg_var ecs7_vars[] = {
- 	{"INT33BE:00_CsiFmt", "13"},
- 	{"INT33BE:00_CsiBayer", "2"},
- 	{"INT33BE:00_CamClk", "0"},
-+	{"INT33BE:00_ClkSrc", "1"},
- 	{"INT33F0:00_CsiPort", "0"},
- 	{"INT33F0:00_CsiLanes", "1"},
- 	{"INT33F0:00_CsiFmt", "13"},
- 	{"INT33F0:00_CsiBayer", "0"},
- 	{"INT33F0:00_CamClk", "1"},
-+	{"INT33BE:00_I2CAddr", "-1"},
- 	{"gmin_V2P8GPIO", "402"},
- 	{},
- };
-@@ -305,6 +307,20 @@ static const struct dmi_system_id gmin_vars[] = {
- 		},
- 		.driver_data = i8880_vars,
- 	},
-+	{
-+		.ident = "Surface Book",
-+		.matches = {
-+			DMI_MATCH(DMI_BOARD_NAME, "Surface Book"),
-+		},
-+		.driver_data = ecs7_vars,
-+	},
-+	{
-+		.ident = "Surface Pro 4",
-+		.matches = {
-+			DMI_MATCH(DMI_BOARD_NAME, "Surface Pro 4"),
-+		},
-+		.driver_data = ecs7_vars,
-+	},
- 	{}
- };
- 

+ 0 - 6042
patches/4.16/ipts.patch

@@ -1,6042 +0,0 @@
-diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
-index 091aef281963..bb1a328527c2 100644
---- a/drivers/gpu/drm/i915/Makefile
-+++ b/drivers/gpu/drm/i915/Makefile
-@@ -143,6 +143,9 @@ i915-y += dvo_ch7017.o \
- 	  intel_sdvo.o \
- 	  intel_tv.o
- 
-+# intel precise touch & stylus
-+i915-y  += intel_ipts.o
-+
- # Post-mortem debug and GPU hang state capture
- i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
- i915-$(CONFIG_DRM_I915_SELFTEST) += \
-diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
-index f1cd4f0ffc62..86c0f6f542bc 100644
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -52,6 +52,7 @@
- #include "i915_vgpu.h"
- #include "intel_drv.h"
- #include "intel_uc.h"
-+#include "intel_ipts.h"
- 
- static struct drm_driver driver;
- 
-@@ -695,6 +696,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
- 	/* Only enable hotplug handling once the fbdev is fully set up. */
- 	intel_hpd_init(dev_priv);
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc)
-+        intel_ipts_init(dev);
-+
- 	return 0;
- 
- cleanup_gem:
-@@ -1420,6 +1424,9 @@ void i915_driver_unload(struct drm_device *dev)
- 	struct drm_i915_private *dev_priv = to_i915(dev);
- 	struct pci_dev *pdev = dev_priv->drm.pdev;
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc)
-+		intel_ipts_cleanup(dev);
-+
- 	i915_driver_unregister(dev_priv);
- 
- 	if (i915_gem_suspend(dev_priv))
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index 55c6d9077a8a..5afbd961e783 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -3419,6 +3419,9 @@ void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
- void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
- 					 struct sg_table *pages);
- 
-+struct i915_gem_context *
-+i915_gem_context_create_ipts(struct drm_device *dev);
-+
- static inline struct i915_gem_context *
- __i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id)
- {
-diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
-index 0c963fcf31ff..012dba4a853f 100644
---- a/drivers/gpu/drm/i915/i915_gem_context.c
-+++ b/drivers/gpu/drm/i915/i915_gem_context.c
-@@ -449,6 +449,18 @@ destroy_kernel_context(struct i915_gem_context **ctxp)
- 	i915_gem_context_free(ctx);
- }
- 
-+struct i915_gem_context *i915_gem_context_create_ipts(struct drm_device *dev)
-+{
-+	struct drm_i915_private *dev_priv = dev->dev_private;
-+	struct i915_gem_context *ctx;
-+
-+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-+
-+	ctx = i915_gem_create_context(dev_priv, NULL);
-+
-+	return ctx;
-+}
-+
- int i915_gem_contexts_init(struct drm_i915_private *dev_priv)
- {
- 	struct i915_gem_context *ctx;
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index 3517c6548e2c..e2545654d092 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -36,6 +36,7 @@
- #include "i915_drv.h"
- #include "i915_trace.h"
- #include "intel_drv.h"
-+#include "intel_ipts.h"
- 
- /**
-  * DOC: interrupt handling
-@@ -1403,6 +1404,9 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
- 		tasklet |= USES_GUC_SUBMISSION(engine->i915);
- 	}
- 
-+	if (iir & (GT_RENDER_PIPECTL_NOTIFY_INTERRUPT << test_shift))
-+		intel_ipts_notify_complete();
-+
- 	if (tasklet)
- 		tasklet_hi_schedule(&execlists->tasklet);
- }
-@@ -3564,7 +3568,8 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
- {
- 	/* These are interrupts we'll toggle with the ring mask register */
- 	uint32_t gt_interrupts[] = {
--		GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+		GT_RENDER_PIPECTL_NOTIFY_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+			GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
- 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
- 			GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT |
- 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT,
-diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
-index b5f3eb4fa8a3..a8f2b07d03e6 100644
---- a/drivers/gpu/drm/i915/i915_params.c
-+++ b/drivers/gpu/drm/i915/i915_params.c
-@@ -152,7 +152,7 @@ i915_param_named_unsafe(edp_vswing, int, 0400,
- i915_param_named_unsafe(enable_guc, int, 0400,
- 	"Enable GuC load for GuC submission and/or HuC load. "
- 	"Required functionality can be selected using bitmask values. "
--	"(-1=auto, 0=disable [default], 1=GuC submission, 2=HuC load)");
-+	"(-1=auto, 0=disable, 1=GuC submission [default], 2=HuC load)");
- 
- i915_param_named(guc_log_level, int, 0400,
- 	"GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
-diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
-index c96360398072..f8f63f023a95 100644
---- a/drivers/gpu/drm/i915/i915_params.h
-+++ b/drivers/gpu/drm/i915/i915_params.h
-@@ -47,7 +47,7 @@ struct drm_printer;
- 	param(int, disable_power_well, -1) \
- 	param(int, enable_ips, 1) \
- 	param(int, invert_brightness, 0) \
--	param(int, enable_guc, 0) \
-+	param(int, enable_guc, 1) \
- 	param(int, guc_log_level, -1) \
- 	param(char *, guc_firmware_path, NULL) \
- 	param(char *, huc_firmware_path, NULL) \
-diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
-index a29868cd30c7..60fd4544b3f5 100644
---- a/drivers/gpu/drm/i915/intel_dp.c
-+++ b/drivers/gpu/drm/i915/intel_dp.c
-@@ -2504,8 +2504,8 @@ void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
- 		return;
- 
- 	if (mode != DRM_MODE_DPMS_ON) {
--		if (downstream_hpd_needs_d0(intel_dp))
--			return;
-+		//if (downstream_hpd_needs_d0(intel_dp))
-+		//	return;
- 
- 		ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER,
- 					 DP_SET_POWER_D3);
-diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
-index 52856a97477d..dbc05a22e50f 100644
---- a/drivers/gpu/drm/i915/intel_guc.h
-+++ b/drivers/gpu/drm/i915/intel_guc.h
-@@ -64,6 +64,7 @@ struct intel_guc {
- 
- 	struct intel_guc_client *execbuf_client;
- 	struct intel_guc_client *preempt_client;
-+	struct intel_guc_client *ipts_client;
- 
- 	struct guc_preempt_work preempt_work[I915_NUM_ENGINES];
- 	struct workqueue_struct *preempt_wq;
-diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c
-index 4d2409466a3a..870ab4d6c868 100644
---- a/drivers/gpu/drm/i915/intel_guc_submission.c
-+++ b/drivers/gpu/drm/i915/intel_guc_submission.c
-@@ -90,6 +90,7 @@ static inline bool is_high_priority(struct intel_guc_client *client)
- 
- static int reserve_doorbell(struct intel_guc_client *client)
- {
-+	struct drm_i915_private *dev_priv = guc_to_i915(client->guc);
- 	unsigned long offset;
- 	unsigned long end;
- 	u16 id;
-@@ -102,11 +103,16 @@ static int reserve_doorbell(struct intel_guc_client *client)
- 	 * priority contexts, the second half for high-priority ones.
- 	 */
- 	offset = 0;
--	end = GUC_NUM_DOORBELLS / 2;
--	if (is_high_priority(client)) {
--		offset = end;
--		end += offset;
-+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
-+		end = GUC_NUM_DOORBELLS;
- 	}
-+	else {
-+		end = GUC_NUM_DOORBELLS/2;
-+		if (is_high_priority(client)) {
-+			offset = end;
-+			end += offset;
-+		}
-+ 	}
- 
- 	id = find_next_zero_bit(client->guc->doorbell_bitmap, end, offset);
- 	if (id == end)
-@@ -349,8 +355,14 @@ static void guc_stage_desc_init(struct intel_guc *guc,
- 	desc = __get_stage_desc(client);
- 	memset(desc, 0, sizeof(*desc));
- 
--	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE |
--			  GUC_STAGE_DESC_ATTR_KERNEL;
-+	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE;
-+	if ((client->priority == GUC_CLIENT_PRIORITY_KMD_NORMAL) ||
-+			(client->priority == GUC_CLIENT_PRIORITY_KMD_HIGH)) {
-+		desc->attribute  |= GUC_STAGE_DESC_ATTR_KERNEL;
-+	} else {
-+		desc->attribute  |= GUC_STAGE_DESC_ATTR_PCH;
-+	}
-+
- 	if (is_high_priority(client))
- 		desc->attribute |= GUC_STAGE_DESC_ATTR_PREEMPT;
- 	desc->stage_id = client->stage_id;
-@@ -1206,7 +1218,8 @@ static void guc_interrupts_capture(struct drm_i915_private *dev_priv)
- 		I915_WRITE(RING_MODE_GEN7(engine), irqs);
- 
- 	/* route USER_INTERRUPT to Host, all others are sent to GuC. */
--	irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+	irqs = (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)
-+							<< GEN8_RCS_IRQ_SHIFT |
- 	       GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
- 	/* These three registers have the same bit definitions */
- 	I915_WRITE(GUC_BCS_RCS_IER, ~irqs);
-@@ -1334,6 +1347,58 @@ void intel_guc_submission_disable(struct intel_guc *guc)
- 	intel_engines_reset_default_submission(dev_priv);
- }
- 
-+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv,
-+				    struct i915_gem_context *ctx)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+	struct intel_guc_client *client;
-+	int err;
-+	int ret;
-+
-+	/* client for execbuf submission */
-+	client = guc_client_alloc(dev_priv,
-+				  INTEL_INFO(dev_priv)->ring_mask,
-+				  GUC_CLIENT_PRIORITY_NORMAL,
-+				  ctx);
-+	if (IS_ERR(client)) {
-+		DRM_ERROR("Failed to create normal GuC client!\n");
-+		return -ENOMEM;
-+	}
-+
-+	guc->ipts_client = client;
-+
-+	err = intel_guc_sample_forcewake(guc);
-+	if (err)
-+		return err;
-+
-+	ret = create_doorbell(guc->ipts_client);
-+	if (ret)
-+		return ret;
-+
-+	return 0;
-+}
-+
-+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+
-+	if (!guc->ipts_client)
-+		return;
-+
-+	guc_client_free(guc->ipts_client);
-+	guc->ipts_client = NULL;
-+}
-+
-+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+
-+	int err = __guc_allocate_doorbell(guc, guc->ipts_client->stage_id);
-+
-+	if (err)
-+		DRM_ERROR("Not able to reacquire IPTS doorbell\n");
-+}
-+
- #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
- #include "selftests/intel_guc.c"
- #endif
-diff --git a/drivers/gpu/drm/i915/intel_guc_submission.h b/drivers/gpu/drm/i915/intel_guc_submission.h
-index fb081cefef93..71fc7986585a 100644
---- a/drivers/gpu/drm/i915/intel_guc_submission.h
-+++ b/drivers/gpu/drm/i915/intel_guc_submission.h
-@@ -79,5 +79,9 @@ void intel_guc_submission_disable(struct intel_guc *guc);
- void intel_guc_submission_fini(struct intel_guc *guc);
- int intel_guc_preempt_work_create(struct intel_guc *guc);
- void intel_guc_preempt_work_destroy(struct intel_guc *guc);
-+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv,
-+				    struct i915_gem_context *ctx);
-+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv);
-+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv);
- 
- #endif
-diff --git a/drivers/gpu/drm/i915/intel_ipts.c b/drivers/gpu/drm/i915/intel_ipts.c
-new file mode 100644
-index 000000000000..f8cc5eaf033d
---- /dev/null
-+++ b/drivers/gpu/drm/i915/intel_ipts.c
-@@ -0,0 +1,627 @@
-+/*
-+ * Copyright  2016 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#include <linux/intel_ipts_if.h>
-+#include <drm/drmP.h>
-+
-+#include "intel_guc_submission.h"
-+#include "i915_drv.h"
-+
-+#define SUPPORTED_IPTS_INTERFACE_VERSION	1
-+
-+#define REACQUIRE_DB_THRESHOLD			8
-+#define DB_LOST_CHECK_STEP1_INTERVAL		2000	/* ms */
-+#define DB_LOST_CHECK_STEP2_INTERVAL		500	/* ms */
-+
-+/* intel IPTS ctx for ipts support */
-+typedef struct intel_ipts {
-+	struct drm_device *dev;
-+	struct i915_gem_context *ipts_context;
-+	intel_ipts_callback_t ipts_clbks;
-+
-+	/* buffers' list */
-+	struct {
-+		spinlock_t       lock;
-+		struct list_head list;
-+	} buffers;
-+
-+	void *data;
-+
-+	struct delayed_work reacquire_db_work;
-+	intel_ipts_wq_info_t wq_info;
-+	u32	old_tail;
-+	u32	old_head;
-+	bool	need_reacquire_db;
-+
-+	bool	connected;
-+	bool	initialized;
-+} intel_ipts_t;
-+
-+intel_ipts_t intel_ipts;
-+
-+typedef struct intel_ipts_object {
-+	struct list_head list;
-+	struct drm_i915_gem_object *gem_obj;
-+	void	*cpu_addr;
-+} intel_ipts_object_t;
-+
-+static intel_ipts_object_t *ipts_object_create(size_t size, u32 flags)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	intel_ipts_object_t *obj = NULL;
-+	struct drm_i915_gem_object *gem_obj = NULL;
-+	int ret = 0;
-+
-+	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
-+	if (!obj)
-+		return NULL;
-+
-+	size = roundup(size, PAGE_SIZE);
-+	if (size == 0) {
-+		ret = -EINVAL;
-+		goto err_out;
-+	}
-+
-+	/* Allocate the new object */
-+	gem_obj = i915_gem_object_create(dev_priv, size);
-+	if (gem_obj == NULL) {
-+		ret = -ENOMEM;
-+		goto err_out;
-+	}
-+
-+	if (flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		ret = i915_gem_object_attach_phys(gem_obj, PAGE_SIZE);
-+		if (ret) {
-+			pr_info(">> ipts no contiguous : %d\n", ret);
-+			goto err_out;
-+		}
-+	}
-+
-+	obj->gem_obj = gem_obj;
-+
-+	spin_lock(&intel_ipts.buffers.lock);
-+	list_add_tail(&obj->list, &intel_ipts.buffers.list);
-+	spin_unlock(&intel_ipts.buffers.lock);
-+
-+	return obj;
-+
-+err_out:
-+	if (gem_obj)
-+		i915_gem_free_object(&gem_obj->base);
-+
-+	if (obj)
-+		kfree(obj);
-+
-+	return NULL;
-+}
-+
-+static void ipts_object_free(intel_ipts_object_t* obj)
-+{
-+	spin_lock(&intel_ipts.buffers.lock);
-+	list_del(&obj->list);
-+	spin_unlock(&intel_ipts.buffers.lock);
-+
-+	i915_gem_free_object(&obj->gem_obj->base);
-+	kfree(obj);
-+}
-+
-+static int ipts_object_pin(intel_ipts_object_t* obj,
-+					struct i915_gem_context *ipts_ctx)
-+{
-+	struct i915_address_space *vm = NULL;
-+	struct i915_vma *vma = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	if (ipts_ctx->ppgtt) {
-+		vm = &ipts_ctx->ppgtt->base;
-+	} else {
-+		vm = &dev_priv->ggtt.base;
-+	}
-+
-+	vma = i915_vma_instance(obj->gem_obj, vm, NULL);
-+	if (IS_ERR(vma)) {
-+		DRM_ERROR("cannot find or create vma\n");
-+		return -1;
-+	}
-+
-+	ret = i915_vma_pin(vma, 0, PAGE_SIZE, PIN_USER);
-+
-+	return ret;
-+}
-+
-+static void ipts_object_unpin(intel_ipts_object_t *obj)
-+{
-+	/* TBD: Add support */
-+}
-+
-+static void* ipts_object_map(intel_ipts_object_t *obj)
-+{
-+
-+	return i915_gem_object_pin_map(obj->gem_obj, I915_MAP_WB);
-+}
-+
-+static void ipts_object_unmap(intel_ipts_object_t* obj)
-+{
-+	i915_gem_object_unpin_map(obj->gem_obj);
-+	obj->cpu_addr = NULL;
-+}
-+
-+static int create_ipts_context(void)
-+{
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct intel_ring *pin_ret;
-+	int ret = 0;
-+
-+	/* Initialize the context right away.*/
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return ret;
-+	}
-+
-+	ipts_ctx = i915_gem_context_create_ipts(intel_ipts.dev);
-+	if (IS_ERR(ipts_ctx)) {
-+		DRM_ERROR("Failed to create IPTS context (error %ld)\n",
-+			  PTR_ERR(ipts_ctx));
-+		ret = PTR_ERR(ipts_ctx);
-+		goto err_unlock;
-+	}
-+
-+	ret = execlists_context_deferred_alloc(ipts_ctx, dev_priv->engine[RCS]);
-+	if (ret) {
-+		DRM_DEBUG("lr context allocation failed : %d\n", ret);
-+		goto err_ctx;
-+	}
-+
-+	pin_ret = execlists_context_pin(dev_priv->engine[RCS], ipts_ctx);
-+	if (IS_ERR(pin_ret)) {
-+		DRM_DEBUG("lr context pinning failed :  %ld\n", PTR_ERR(pin_ret));
-+		goto err_ctx;
-+	}
-+
-+	/* Release the mutex */
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	spin_lock_init(&intel_ipts.buffers.lock);
-+	INIT_LIST_HEAD(&intel_ipts.buffers.list);
-+
-+	intel_ipts.ipts_context = ipts_ctx;
-+
-+	return 0;
-+
-+err_ctx:
-+	if (ipts_ctx)
-+		i915_gem_context_put(ipts_ctx);
-+
-+err_unlock:
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return ret;
-+}
-+
-+static void destroy_ipts_context(void)
-+{
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	ipts_ctx = intel_ipts.ipts_context;
-+
-+	/* Initialize the context right away.*/
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return;
-+	}
-+
-+	execlists_context_unpin(dev_priv->engine[RCS], ipts_ctx);
-+	i915_gem_context_put(ipts_ctx);
-+
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+}
-+
-+int intel_ipts_notify_complete(void)
-+{
-+	if (intel_ipts.ipts_clbks.workload_complete)
-+		intel_ipts.ipts_clbks.workload_complete(intel_ipts.data);
-+
-+	return 0;
-+}
-+
-+int intel_ipts_notify_backlight_status(bool backlight_on)
-+{
-+	if (intel_ipts.ipts_clbks.notify_gfx_status) {
-+		if (backlight_on) {
-+			intel_ipts.ipts_clbks.notify_gfx_status(
-+						IPTS_NOTIFY_STA_BACKLIGHT_ON,
-+						intel_ipts.data);
-+			schedule_delayed_work(&intel_ipts.reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+		} else {
-+			intel_ipts.ipts_clbks.notify_gfx_status(
-+						IPTS_NOTIFY_STA_BACKLIGHT_OFF,
-+						intel_ipts.data);
-+			cancel_delayed_work(&intel_ipts.reacquire_db_work);
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+static void intel_ipts_reacquire_db(intel_ipts_t *intel_ipts_p)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts_p->dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return;
-+	}
-+
-+	/* Reacquire the doorbell */
-+	i915_guc_ipts_reacquire_doorbell(intel_ipts_p->dev->dev_private);
-+
-+	mutex_unlock(&intel_ipts_p->dev->struct_mutex);
-+
-+	return;
-+}
-+
-+static int intel_ipts_get_wq_info(uint64_t gfx_handle,
-+						intel_ipts_wq_info_t *wq_info)
-+{
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	*wq_info = intel_ipts.wq_info;
-+
-+	intel_ipts_reacquire_db(&intel_ipts);
-+	schedule_delayed_work(&intel_ipts.reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+
-+	return 0;
-+}
-+
-+static int set_wq_info(void)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct intel_guc *guc = &dev_priv->guc;
-+	struct intel_guc_client *client;
-+	struct guc_process_desc *desc;
-+	void *base = NULL;
-+	intel_ipts_wq_info_t *wq_info;
-+	u64 phy_base = 0;
-+
-+	wq_info = &intel_ipts.wq_info;
-+
-+	client = guc->ipts_client;
-+	if (!client) {
-+		DRM_ERROR("IPTS GuC client is NOT available\n");
-+		return -EINVAL;
-+	}
-+
-+	base = client->vaddr;
-+	desc = (struct guc_process_desc *)((u64)base + client->proc_desc_offset);
-+
-+	desc->wq_base_addr = (u64)base + GUC_DB_SIZE;
-+	desc->db_base_addr = (u64)base + client->doorbell_offset;
-+
-+	/* IPTS expects physical addresses to pass it to ME */
-+	phy_base = sg_dma_address(client->vma->pages->sgl);
-+
-+	wq_info->db_addr = desc->db_base_addr;
-+        wq_info->db_phy_addr = phy_base + client->doorbell_offset;
-+        wq_info->db_cookie_offset = offsetof(struct guc_doorbell_info, cookie);
-+        wq_info->wq_addr = desc->wq_base_addr;
-+        wq_info->wq_phy_addr = phy_base + GUC_DB_SIZE;
-+        wq_info->wq_head_addr = (u64)&desc->head;
-+        wq_info->wq_head_phy_addr = phy_base + client->proc_desc_offset +
-+					offsetof(struct guc_process_desc, head);
-+        wq_info->wq_tail_addr = (u64)&desc->tail;
-+        wq_info->wq_tail_phy_addr = phy_base + client->proc_desc_offset +
-+					offsetof(struct guc_process_desc, tail);
-+        wq_info->wq_size = desc->wq_size_bytes;
-+
-+	return 0;
-+}
-+
-+static int intel_ipts_init_wq(void)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed\n");
-+		return ret;
-+	}
-+
-+	/* disable IPTS submission */
-+	i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private);
-+
-+	/* enable IPTS submission */
-+	ret = i915_guc_ipts_submission_enable(intel_ipts.dev->dev_private,
-+							intel_ipts.ipts_context);
-+	if (ret) {
-+		DRM_ERROR("i915_guc_ipts_submission_enable failed : %d\n", ret);
-+		goto out;
-+        }
-+
-+	ret = set_wq_info();
-+	if (ret) {
-+		DRM_ERROR("set_wq_info failed\n");
-+		goto out;
-+	}
-+
-+out:
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return ret;
-+}
-+
-+static void intel_ipts_release_wq(void)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed\n");
-+		return;
-+	}
-+
-+	/* disable IPTS submission */
-+	i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private);
-+
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+}
-+
-+static int intel_ipts_map_buffer(u64 gfx_handle, intel_ipts_mapbuffer_t *mapbuf)
-+{
-+	intel_ipts_object_t* obj;
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct i915_address_space *vm = NULL;
-+	struct i915_vma *vma = NULL;
-+	int ret = 0;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	/* Acquire mutex first */
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return -EINVAL;
-+	}
-+
-+	obj = ipts_object_create(mapbuf->size, mapbuf->flags);
-+	if (!obj)
-+		return -ENOMEM;
-+
-+	ipts_ctx = intel_ipts.ipts_context;
-+	ret = ipts_object_pin(obj, ipts_ctx);
-+	if (ret) {
-+		DRM_ERROR("Not able to pin iTouch obj\n");
-+		ipts_object_free(obj);
-+		mutex_unlock(&intel_ipts.dev->struct_mutex);
-+		return -ENOMEM;
-+	}
-+
-+	if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		obj->cpu_addr = obj->gem_obj->phys_handle->vaddr;
-+	} else {
-+		obj->cpu_addr = ipts_object_map(obj);
-+	}
-+
-+	if (ipts_ctx->ppgtt) {
-+		vm = &ipts_ctx->ppgtt->base;
-+	} else {
-+		vm = &dev_priv->ggtt.base;
-+	}
-+
-+	vma = i915_vma_instance(obj->gem_obj, vm, NULL);
-+	if (IS_ERR(vma)) {
-+		DRM_ERROR("cannot find or create vma\n");
-+		return -EINVAL;
-+	}
-+
-+	mapbuf->gfx_addr = (void*)vma->node.start;
-+	mapbuf->cpu_addr = (void*)obj->cpu_addr;
-+	mapbuf->buf_handle = (u64)obj;
-+	if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		mapbuf->phy_addr = (u64)obj->gem_obj->phys_handle->busaddr;
-+	}
-+
-+	/* Release the mutex */
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return 0;
-+}
-+
-+static int intel_ipts_unmap_buffer(uint64_t gfx_handle, uint64_t buf_handle)
-+{
-+	intel_ipts_object_t* obj = (intel_ipts_object_t*)buf_handle;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	if (!obj->gem_obj->phys_handle)
-+		ipts_object_unmap(obj);
-+	ipts_object_unpin(obj);
-+	ipts_object_free(obj);
-+
-+	return 0;
-+}
-+
-+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	if (!intel_ipts.initialized)
-+		return -EIO;
-+
-+	if (ipts_connect && ipts_connect->if_version <=
-+					SUPPORTED_IPTS_INTERFACE_VERSION) {
-+
-+		/* return gpu operations for ipts */
-+		ipts_connect->ipts_ops.get_wq_info = intel_ipts_get_wq_info;
-+		ipts_connect->ipts_ops.map_buffer = intel_ipts_map_buffer;
-+		ipts_connect->ipts_ops.unmap_buffer = intel_ipts_unmap_buffer;
-+		ipts_connect->gfx_version = INTEL_INFO(dev_priv)->gen;
-+		ipts_connect->gfx_handle = (uint64_t)&intel_ipts;
-+
-+		/* save callback and data */
-+		intel_ipts.data = ipts_connect->data;
-+		intel_ipts.ipts_clbks = ipts_connect->ipts_cb;
-+
-+		intel_ipts.connected = true;
-+	} else {
-+		ret = -EINVAL;
-+	}
-+
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(intel_ipts_connect);
-+
-+void intel_ipts_disconnect(uint64_t gfx_handle)
-+{
-+	if (!intel_ipts.initialized)
-+		return;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts ||
-+					intel_ipts.connected == false) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return;
-+	}
-+
-+	intel_ipts.data = 0;
-+	memset(&intel_ipts.ipts_clbks, 0, sizeof(intel_ipts_callback_t));
-+
-+	intel_ipts.connected = false;
-+}
-+EXPORT_SYMBOL_GPL(intel_ipts_disconnect);
-+
-+static void reacquire_db_work_func(struct work_struct *work)
-+{
-+	struct delayed_work *d_work = container_of(work, struct delayed_work,
-+							work);
-+	intel_ipts_t *intel_ipts_p = container_of(d_work, intel_ipts_t,
-+							reacquire_db_work);
-+	u32 head;
-+	u32 tail;
-+	u32 size;
-+	u32 load;
-+
-+	head = *(u32*)intel_ipts_p->wq_info.wq_head_addr;
-+	tail = *(u32*)intel_ipts_p->wq_info.wq_tail_addr;
-+	size = intel_ipts_p->wq_info.wq_size;
-+
-+	if (head >= tail)
-+		load = head - tail;
-+	else
-+		load = head + size - tail;
-+
-+	if (load < REACQUIRE_DB_THRESHOLD) {
-+		intel_ipts_p->need_reacquire_db = false;
-+		goto reschedule_work;
-+	}
-+
-+	if (intel_ipts_p->need_reacquire_db) {
-+		if (intel_ipts_p->old_head == head && intel_ipts_p->old_tail == tail)
-+			intel_ipts_reacquire_db(intel_ipts_p);
-+		intel_ipts_p->need_reacquire_db = false;
-+	} else {
-+		intel_ipts_p->old_head = head;
-+		intel_ipts_p->old_tail = tail;
-+		intel_ipts_p->need_reacquire_db = true;
-+
-+		/* recheck */
-+		schedule_delayed_work(&intel_ipts_p->reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP2_INTERVAL));
-+		return;
-+	}
-+
-+reschedule_work:
-+	schedule_delayed_work(&intel_ipts_p->reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+}
-+
-+/**
-+ * intel_ipts_init - Initialize ipts support
-+ * @dev: drm device
-+ *
-+ * Setup the required structures for ipts.
-+ */
-+int intel_ipts_init(struct drm_device *dev)
-+{
-+	int ret = 0;
-+
-+	pr_info("ipts: initializing ipts\n");
-+
-+	intel_ipts.dev = dev;
-+	INIT_DELAYED_WORK(&intel_ipts.reacquire_db_work, reacquire_db_work_func);
-+
-+	ret = create_ipts_context();
-+	if (ret)
-+		return -ENOMEM;
-+
-+	ret = intel_ipts_init_wq();
-+	if (ret)
-+		return ret;
-+
-+	intel_ipts.initialized = true;
-+	DRM_DEBUG_DRIVER("Intel iTouch framework initialized\n");
-+
-+	return ret;
-+}
-+
-+void intel_ipts_cleanup(struct drm_device *dev)
-+{
-+	intel_ipts_object_t *obj, *n;
-+
-+	if (intel_ipts.dev == dev) {
-+		list_for_each_entry_safe(obj, n, &intel_ipts.buffers.list, list) {
-+			list_del(&obj->list);
-+
-+			if (!obj->gem_obj->phys_handle)
-+				ipts_object_unmap(obj);
-+			ipts_object_unpin(obj);
-+			i915_gem_free_object(&obj->gem_obj->base);
-+			kfree(obj);
-+		}
-+
-+		intel_ipts_release_wq();
-+		destroy_ipts_context();
-+		cancel_delayed_work(&intel_ipts.reacquire_db_work);
-+	}
-+}
-diff --git a/drivers/gpu/drm/i915/intel_ipts.h b/drivers/gpu/drm/i915/intel_ipts.h
-new file mode 100644
-index 000000000000..a6965d102417
---- /dev/null
-+++ b/drivers/gpu/drm/i915/intel_ipts.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright © 2016 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ */
-+#ifndef _INTEL_IPTS_H_
-+#define _INTEL_IPTS_H_
-+
-+struct drm_device;
-+
-+int intel_ipts_init(struct drm_device *dev);
-+void intel_ipts_cleanup(struct drm_device *dev);
-+int intel_ipts_notify_backlight_status(bool backlight_on);
-+int intel_ipts_notify_complete(void);
-+
-+#endif //_INTEL_IPTS_H_
-diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
-index e0fca035ff78..bf37b1f7887b 100644
---- a/drivers/gpu/drm/i915/intel_lrc.c
-+++ b/drivers/gpu/drm/i915/intel_lrc.c
-@@ -211,8 +211,6 @@
- #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS)
- #define PREEMPT_ID 0x1
- 
--static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
--					    struct intel_engine_cs *engine);
- static void execlists_init_reg_state(u32 *reg_state,
- 				     struct i915_gem_context *ctx,
- 				     struct intel_engine_cs *engine,
-@@ -1116,7 +1114,7 @@ static int __context_pin(struct i915_gem_context *ctx, struct i915_vma *vma)
- 	return i915_vma_pin(vma, 0, GEN8_LR_CONTEXT_ALIGN, flags);
- }
- 
--static struct intel_ring *
-+struct intel_ring *
- execlists_context_pin(struct intel_engine_cs *engine,
- 		      struct i915_gem_context *ctx)
- {
-@@ -1171,7 +1169,7 @@ execlists_context_pin(struct intel_engine_cs *engine,
- 	return ERR_PTR(ret);
- }
- 
--static void execlists_context_unpin(struct intel_engine_cs *engine,
-+void execlists_context_unpin(struct intel_engine_cs *engine,
- 				    struct i915_gem_context *ctx)
- {
- 	struct intel_context *ce = &ctx->engine[engine->id];
-@@ -2020,6 +2018,9 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
- 
- 	logical_ring_setup(engine);
- 
-+	engine->irq_keep_mask |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT
-+							<< GEN8_RCS_IRQ_SHIFT;
-+
- 	if (HAS_L3_DPF(dev_priv))
- 		engine->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
- 
-@@ -2272,7 +2273,7 @@ populate_lr_context(struct i915_gem_context *ctx,
- 	return 0;
- }
- 
--static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
-+int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
- 					    struct intel_engine_cs *engine)
- {
- 	struct drm_i915_gem_object *ctx_obj;
-diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
-index 6d4f9b995a11..dd7c3a1e072e 100644
---- a/drivers/gpu/drm/i915/intel_lrc.h
-+++ b/drivers/gpu/drm/i915/intel_lrc.h
-@@ -107,4 +107,12 @@ intel_lr_context_descriptor(struct i915_gem_context *ctx,
- 	return ctx->engine[engine->id].lrc_desc;
- }
- 
-+struct intel_ring *
-+execlists_context_pin(struct intel_engine_cs *engine,
-+		      struct i915_gem_context *ctx);
-+void execlists_context_unpin(struct intel_engine_cs *engine,
-+				    struct i915_gem_context *ctx);
-+int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
-+					    struct intel_engine_cs *engine);
-+
- #endif /* _INTEL_LRC_H_ */
-diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
-index fa6831f8c004..f3e97dc87b7a 100644
---- a/drivers/gpu/drm/i915/intel_panel.c
-+++ b/drivers/gpu/drm/i915/intel_panel.c
-@@ -34,6 +34,7 @@
- #include <linux/moduleparam.h>
- #include <linux/pwm.h>
- #include "intel_drv.h"
-+#include "intel_ipts.h"
- 
- #define CRC_PMIC_PWM_PERIOD_NS	21333
- 
-@@ -675,6 +676,9 @@ static void lpt_disable_backlight(const struct drm_connector_state *old_conn_sta
- 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- 	u32 tmp;
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc)
-+		intel_ipts_notify_backlight_status(false);
-+
- 	intel_panel_actually_set_backlight(old_conn_state, 0);
- 
- 	/*
-@@ -862,6 +866,9 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
- 
- 	/* This won't stick until the above enable. */
- 	intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
-+
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc)
-+		intel_ipts_notify_backlight_status(true);
- }
- 
- static void pch_enable_backlight(const struct intel_crtc_state *crtc_state,
-diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
-index 2e1736ba2444..f3952d9d6def 100644
---- a/drivers/hid/hid-multitouch.c
-+++ b/drivers/hid/hid-multitouch.c
-@@ -150,6 +150,7 @@ struct mt_device {
- 
- static void mt_post_parse_default_settings(struct mt_device *td);
- static void mt_post_parse(struct mt_device *td);
-+static int cc_seen = 0;
- 
- /* classes of device behavior */
- #define MT_CLS_DEFAULT				0x0001
-@@ -624,8 +625,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 			if (field->index >= field->report->maxfield ||
- 			    usage->usage_index >= field->report_count)
- 				return 1;
--			td->cc_index = field->index;
--			td->cc_value_index = usage->usage_index;
-+
-+			if(cc_seen != 1) {
-+				td->cc_index = field->index;
-+				td->cc_value_index = usage->usage_index;
-+				cc_seen++;
-+			}
- 			return 1;
- 		case HID_DG_AZIMUTH:
- 			hid_map_usage(hi, usage, bit, max,
-@@ -677,6 +682,16 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 	return 0;
- }
- 
-+static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-+		struct hid_field *field, struct hid_usage *usage,
-+		unsigned long **bit, int *max)
-+{
-+	if (usage->type == EV_KEY || usage->type == EV_ABS)
-+		set_bit(usage->type, hi->input->evbit);
-+
-+	return -1;
-+}
-+
- static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
- {
- 	__s32 quirks = td->mtclass.quirks;
-@@ -1077,9 +1092,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 	    field->application != HID_DG_TOUCHSCREEN &&
- 	    field->application != HID_DG_PEN &&
- 	    field->application != HID_DG_TOUCHPAD &&
-+		field->application != HID_GD_MOUSE &&
- 	    field->application != HID_GD_KEYBOARD &&
- 	    field->application != HID_GD_SYSTEM_CONTROL &&
- 	    field->application != HID_CP_CONSUMER_CONTROL &&
-+		field->logical != HID_DG_TOUCHSCREEN &&
- 	    field->application != HID_GD_WIRELESS_RADIO_CTLS &&
- 	    !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
- 	      td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP))
-@@ -1142,10 +1159,8 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
- 		return 0;
- 
- 	if (field->application == HID_DG_TOUCHSCREEN ||
--	    field->application == HID_DG_TOUCHPAD) {
--		/* We own these mappings, tell hid-input to ignore them */
--		return -1;
--	}
-+	    field->application == HID_DG_TOUCHPAD)
-+		return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
- 
- 	/* let hid-core decide for the others */
- 	return 0;
-@@ -1288,6 +1303,7 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
- 		suffix = "Pen";
- 		/* force BTN_STYLUS to allow tablet matching in udev */
- 		__set_bit(BTN_STYLUS, hi->input->keybit);
-+        __set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
- 	} else {
- 		switch (field->application) {
- 		case HID_GD_KEYBOARD:
-@@ -1303,9 +1319,10 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
- 			suffix = "Pen";
- 			/* force BTN_STYLUS to allow tablet matching in udev */
- 			__set_bit(BTN_STYLUS, hi->input->keybit);
-+            __set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
- 			break;
- 		case HID_DG_TOUCHSCREEN:
--			/* we do not set suffix = "Touchscreen" */
-+			suffix = "Touchscreen";
- 			break;
- 		case HID_DG_TOUCHPAD:
- 			suffix = "Touchpad";
-@@ -1436,6 +1453,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
- 	td->cc_index = -1;
- 	td->scantime_index = -1;
- 	td->mt_report_id = -1;
-+	cc_seen = 0;
- 	hid_set_drvdata(hdev, td);
- 
- 	td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
-diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index 03605f8fc0dc..72178d42147b 100644
---- a/drivers/misc/Kconfig
-+++ b/drivers/misc/Kconfig
-@@ -507,6 +507,7 @@ source "drivers/misc/ti-st/Kconfig"
- source "drivers/misc/lis3lv02d/Kconfig"
- source "drivers/misc/altera-stapl/Kconfig"
- source "drivers/misc/mei/Kconfig"
-+source "drivers/misc/ipts/Kconfig"
- source "drivers/misc/vmw_vmci/Kconfig"
- source "drivers/misc/mic/Kconfig"
- source "drivers/misc/genwqe/Kconfig"
-diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index c3c8624f4d95..6cef998bcfd6 100644
---- a/drivers/misc/Makefile
-+++ b/drivers/misc/Makefile
-@@ -43,6 +43,7 @@ obj-y				+= lis3lv02d/
- obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
- obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
- obj-$(CONFIG_INTEL_MEI)		+= mei/
-+obj-$(CONFIG_INTEL_IPTS)	+= ipts/
- obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
- obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
- obj-$(CONFIG_SRAM)		+= sram.o
-diff --git a/drivers/misc/ipts/Kconfig b/drivers/misc/ipts/Kconfig
-new file mode 100644
-index 000000000000..360ed3861b82
---- /dev/null
-+++ b/drivers/misc/ipts/Kconfig
-@@ -0,0 +1,9 @@
-+config INTEL_IPTS
-+	tristate "Intel Precise Touch & Stylus"
-+	select INTEL_MEI
-+	depends on X86 && PCI && HID
-+	help
-+	  Intel Precise Touch & Stylus support
-+	  Supported SoCs:
-+	  Intel Skylake
-+	  Intel Kabylake
-diff --git a/drivers/misc/ipts/Makefile b/drivers/misc/ipts/Makefile
-new file mode 100644
-index 000000000000..1783e9cf13c9
---- /dev/null
-+++ b/drivers/misc/ipts/Makefile
-@@ -0,0 +1,13 @@
-+#
-+# Makefile - Intel Precise Touch & Stylus device driver
-+# Copyright (c) 2016, Intel Corporation.
-+#
-+
-+obj-$(CONFIG_INTEL_IPTS)+= intel-ipts.o
-+intel-ipts-objs += ipts-mei.o
-+intel-ipts-objs += ipts-hid.o
-+intel-ipts-objs += ipts-msg-handler.o
-+intel-ipts-objs += ipts-kernel.o
-+intel-ipts-objs += ipts-resource.o
-+intel-ipts-objs += ipts-gfx.o
-+intel-ipts-$(CONFIG_DEBUG_FS) += ipts-dbgfs.o
-diff --git a/drivers/misc/ipts/ipts-binary-spec.h b/drivers/misc/ipts/ipts-binary-spec.h
-new file mode 100644
-index 000000000000..87d4bc4133c4
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-binary-spec.h
-@@ -0,0 +1,118 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus binary spec
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_BINARY_SPEC_H
-+#define _IPTS_BINARY_SPEC_H
-+
-+#define IPTS_BIN_HEADER_VERSION 2
-+
-+#pragma pack(1)
-+
-+/* we support 16 output buffers(1:feedback, 15:HID) */
-+#define  MAX_NUM_OUTPUT_BUFFERS 16
-+
-+typedef enum {
-+	IPTS_BIN_KERNEL,
-+	IPTS_BIN_RO_DATA,
-+	IPTS_BIN_RW_DATA,
-+	IPTS_BIN_SENSOR_FRAME,
-+	IPTS_BIN_OUTPUT,
-+	IPTS_BIN_DYNAMIC_STATE_HEAP,
-+	IPTS_BIN_PATCH_LOCATION_LIST,
-+	IPTS_BIN_ALLOCATION_LIST,
-+	IPTS_BIN_COMMAND_BUFFER_PACKET,
-+	IPTS_BIN_TAG,
-+} ipts_bin_res_type_t;
-+
-+typedef struct ipts_bin_header {
-+	char str[4];
-+	unsigned int version;
-+
-+#if IPTS_BIN_HEADER_VERSION > 1
-+	unsigned int gfxcore;
-+	unsigned int revid;
-+#endif
-+} ipts_bin_header_t;
-+
-+typedef struct ipts_bin_alloc {
-+	unsigned int handle;
-+	unsigned int reserved;
-+} ipts_bin_alloc_t;
-+
-+typedef struct ipts_bin_alloc_list {
-+	unsigned int num;
-+	ipts_bin_alloc_t alloc[];
-+} ipts_bin_alloc_list_t;
-+
-+typedef struct ipts_bin_cmdbuf {
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_cmdbuf_t;
-+
-+typedef struct ipts_bin_res {
-+	unsigned int handle;
-+	ipts_bin_res_type_t type;
-+	unsigned int initialize;
-+	unsigned int aligned_size;
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_res_t;
-+
-+typedef enum {
-+	IPTS_INPUT,
-+	IPTS_OUTPUT,
-+	IPTS_CONFIGURATION,
-+	IPTS_CALIBRATION,
-+	IPTS_FEATURE,
-+} ipts_bin_io_buffer_type_t;
-+
-+typedef struct ipts_bin_io_header {
-+	char str[10];
-+	unsigned short type;
-+} ipts_bin_io_header_t;
-+
-+typedef struct ipts_bin_res_list {
-+	unsigned int num;
-+	ipts_bin_res_t res[];
-+} ipts_bin_res_list_t;
-+
-+typedef struct ipts_bin_patch {
-+	unsigned int index;
-+	unsigned int reserved1[2];
-+	unsigned int alloc_offset;
-+	unsigned int patch_offset;
-+	unsigned int reserved2;
-+} ipts_bin_patch_t;
-+
-+typedef struct ipts_bin_patch_list {
-+	unsigned int num;
-+	ipts_bin_patch_t patch[];
-+} ipts_bin_patch_list_t;
-+
-+typedef struct ipts_bin_guc_wq_info {
-+	unsigned int batch_offset;
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_guc_wq_info_t;
-+
-+typedef struct ipts_bin_bufid_patch {
-+	unsigned int imm_offset;
-+	unsigned int mem_offset;
-+} ipts_bin_bufid_patch_t;
-+
-+#pragma pack()
-+
-+#endif /* _IPTS_BINARY_SPEC_H */
-diff --git a/drivers/misc/ipts/ipts-dbgfs.c b/drivers/misc/ipts/ipts-dbgfs.c
-new file mode 100644
-index 000000000000..1c5c92f7d4ba
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-dbgfs.c
-@@ -0,0 +1,152 @@
-+/*
-+ * Intel Precise Touch & Stylus device driver
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/debugfs.h>
-+#include <linux/ctype.h>
-+#include <linux/uaccess.h>
-+
-+#include "ipts.h"
-+#include "ipts-sensor-regs.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-state.h"
-+
-+const char sensor_mode_fmt[] = "sensor mode : %01d\n";
-+const char ipts_status_fmt[] = "sensor mode : %01d\nipts state : %01d\n";
-+
-+static ssize_t ipts_dbgfs_mode_read(struct file *fp, char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	char mode[80];
-+	int len = 0;
-+
-+	if (cnt < sizeof(sensor_mode_fmt) - 3)
-+		return -EINVAL;
-+
-+	len = scnprintf(mode, 80, sensor_mode_fmt, ipts->sensor_mode);
-+	if (len < 0)
-+		return -EIO;
-+
-+	return simple_read_from_buffer(ubuf, cnt, ppos, mode, len);
-+}
-+
-+static ssize_t ipts_dbgfs_mode_write(struct file *fp, const char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	ipts_state_t state;
-+	int sensor_mode, len;
-+	char mode[3];
-+
-+	if (cnt == 0 || cnt > 3)
-+		return -EINVAL;
-+
-+	state = ipts_get_state(ipts);
-+	if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED) {
-+		return -EIO;
-+	}
-+
-+	len = cnt;
-+	if (copy_from_user(mode, ubuf, len))
-+		return -EFAULT;
-+
-+	while(len > 0 && (isspace(mode[len-1]) || mode[len-1] == '\n'))
-+		len--;
-+	mode[len] = '\0';
-+
-+	if (sscanf(mode, "%d", &sensor_mode) != 1)
-+		return -EINVAL;
-+
-+	if (sensor_mode != TOUCH_SENSOR_MODE_RAW_DATA &&
-+					sensor_mode != TOUCH_SENSOR_MODE_HID) {
-+		return -EINVAL;
-+	}
-+
-+	if (sensor_mode == ipts->sensor_mode)
-+		return 0;
-+
-+	ipts_switch_sensor_mode(ipts, sensor_mode);
-+
-+	return cnt;
-+}
-+
-+static const struct file_operations ipts_mode_dbgfs_fops = {
-+        .open = simple_open,
-+        .read = ipts_dbgfs_mode_read,
-+        .write = ipts_dbgfs_mode_write,
-+        .llseek = generic_file_llseek,
-+};
-+
-+static ssize_t ipts_dbgfs_status_read(struct file *fp, char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	char status[256];
-+	int len = 0;
-+
-+	if (cnt < sizeof(ipts_status_fmt) - 3)
-+		return -EINVAL;
-+
-+	len = scnprintf(status, 256, ipts_status_fmt, ipts->sensor_mode,
-+						     ipts->state);
-+	if (len < 0)
-+		return -EIO;
-+
-+	return simple_read_from_buffer(ubuf, cnt, ppos, status, len);
-+}
-+
-+static const struct file_operations ipts_status_dbgfs_fops = {
-+        .open = simple_open,
-+        .read = ipts_dbgfs_status_read,
-+        .llseek = generic_file_llseek,
-+};
-+
-+void ipts_dbgfs_deregister(ipts_info_t* ipts)
-+{
-+	if (!ipts->dbgfs_dir)
-+		return;
-+
-+	debugfs_remove_recursive(ipts->dbgfs_dir);
-+	ipts->dbgfs_dir = NULL;
-+}
-+
-+int ipts_dbgfs_register(ipts_info_t* ipts, const char *name)
-+{
-+	struct dentry *dir, *f;
-+
-+	dir = debugfs_create_dir(name, NULL);
-+	if (!dir)
-+		return -ENOMEM;
-+
-+        f = debugfs_create_file("mode", S_IRUSR | S_IWUSR, dir,
-+                                ipts, &ipts_mode_dbgfs_fops);
-+        if (!f) {
-+                ipts_err(ipts, "debugfs mode creation failed\n");
-+                goto err;
-+        }
-+
-+        f = debugfs_create_file("status", S_IRUSR, dir,
-+                                ipts, &ipts_status_dbgfs_fops);
-+        if (!f) {
-+                ipts_err(ipts, "debugfs status creation failed\n");
-+                goto err;
-+        }
-+
-+	ipts->dbgfs_dir = dir;
-+
-+	return 0;
-+err:
-+	ipts_dbgfs_deregister(ipts);
-+	return -ENODEV;
-+}
-diff --git a/drivers/misc/ipts/ipts-gfx.c b/drivers/misc/ipts/ipts-gfx.c
-new file mode 100644
-index 000000000000..51727770e75d
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-gfx.c
-@@ -0,0 +1,184 @@
-+/*
-+ *
-+ * Intel Integrated Touch Gfx Interface Layer
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/kthread.h>
-+#include <linux/delay.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-state.h"
-+
-+static void gfx_processing_complete(void *data)
-+{
-+	ipts_info_t *ipts = data;
-+
-+	if (ipts_get_state(ipts) == IPTS_STA_RAW_DATA_STARTED) {
-+		schedule_work(&ipts->raw_data_work);
-+		return;
-+	}
-+
-+	ipts_dbg(ipts, "not ready to handle gfx event\n");
-+}
-+
-+static void notify_gfx_status(u32 status, void *data)
-+{
-+	ipts_info_t *ipts = data;
-+
-+	ipts->gfx_status = status;
-+	schedule_work(&ipts->gfx_status_work);
-+}
-+
-+static int connect_gfx(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	intel_ipts_connect_t ipts_connect;
-+
-+	ipts_connect.if_version = IPTS_INTERFACE_V1;
-+	ipts_connect.ipts_cb.workload_complete = gfx_processing_complete;
-+	ipts_connect.ipts_cb.notify_gfx_status = notify_gfx_status;
-+	ipts_connect.data = (void*)ipts;
-+
-+	ret = intel_ipts_connect(&ipts_connect);
-+	if (ret)
-+		return ret;
-+
-+	/* TODO: gfx version check */
-+	ipts->gfx_info.gfx_handle = ipts_connect.gfx_handle;
-+	ipts->gfx_info.ipts_ops = ipts_connect.ipts_ops;
-+
-+	return ret;
-+}
-+
-+static void disconnect_gfx(ipts_info_t *ipts)
-+{
-+	intel_ipts_disconnect(ipts->gfx_info.gfx_handle);
-+}
-+
-+#ifdef RUN_DBG_THREAD
-+#include "../mei/mei_dev.h"
-+
-+static struct task_struct *dbg_thread;
-+
-+static void ipts_print_dbg_info(ipts_info_t* ipts)
-+{
-+        char fw_sts_str[MEI_FW_STATUS_STR_SZ];
-+	u32 *db, *head, *tail;
-+	intel_ipts_wq_info_t* wq_info;
-+
-+	wq_info = &ipts->resource.wq_info;
-+
-+	mei_fw_status_str(ipts->cldev->bus, fw_sts_str, MEI_FW_STATUS_STR_SZ);
-+	pr_info(">> tdt : fw status : %s\n", fw_sts_str);
-+
-+	db = (u32*)wq_info->db_addr;
-+	head = (u32*)wq_info->wq_head_addr;
-+	tail = (u32*)wq_info->wq_tail_addr;
-+	pr_info(">> == DB s:%x, c:%x ==\n", *db, *(db+1));
-+	pr_info(">> == WQ h:%u, t:%u ==\n", *head, *tail);
-+}
-+
-+static int ipts_dbg_thread(void *data)
-+{
-+	ipts_info_t *ipts = (ipts_info_t *)data;
-+
-+	pr_info(">> start debug thread\n");
-+
-+	while (!kthread_should_stop()) {
-+		if (ipts_get_state(ipts) != IPTS_STA_RAW_DATA_STARTED) {
-+			pr_info("state is not IPTS_STA_RAW_DATA_STARTED : %d\n",
-+							ipts_get_state(ipts));
-+			msleep(5000);
-+			continue;
-+		}
-+
-+		ipts_print_dbg_info(ipts);
-+
-+		msleep(3000);
-+	}
-+
-+	return 0;
-+}
-+#endif
-+
-+int ipts_open_gpu(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ret = connect_gfx(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot connect GPU\n");
-+		return ret;
-+	}
-+
-+	ret = ipts->gfx_info.ipts_ops.get_wq_info(ipts->gfx_info.gfx_handle,
-+							&ipts->resource.wq_info);
-+	if (ret) {
-+		ipts_dbg(ipts, "error in get_wq_info\n");
-+		return ret;
-+	}
-+
-+#ifdef	RUN_DBG_THREAD
-+	dbg_thread = kthread_run(ipts_dbg_thread, (void *)ipts, "ipts_debug");
-+#endif
-+
-+	return 0;
-+}
-+
-+void ipts_close_gpu(ipts_info_t *ipts)
-+{
-+	disconnect_gfx(ipts);
-+
-+#ifdef	RUN_DBG_THREAD
-+	kthread_stop(dbg_thread);
-+#endif
-+}
-+
-+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags)
-+{
-+	intel_ipts_mapbuffer_t *buf;
-+	u64 handle;
-+	int ret;
-+
-+	buf = devm_kzalloc(&ipts->cldev->dev, sizeof(*buf), GFP_KERNEL);
-+	if (!buf)
-+		return NULL;
-+
-+	buf->size = size;
-+	buf->flags = flags;
-+
-+	handle = ipts->gfx_info.gfx_handle;
-+	ret = ipts->gfx_info.ipts_ops.map_buffer(handle, buf);
-+	if (ret) {
-+		devm_kfree(&ipts->cldev->dev, buf);
-+		return NULL;
-+	}
-+
-+	return buf;
-+}
-+
-+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf)
-+{
-+	u64 handle;
-+	int ret;
-+
-+	if (!buf)
-+		return;
-+
-+	handle = ipts->gfx_info.gfx_handle;
-+	ret = ipts->gfx_info.ipts_ops.unmap_buffer(handle, buf->buf_handle);
-+
-+	devm_kfree(&ipts->cldev->dev, buf);
-+}
-diff --git a/drivers/misc/ipts/ipts-gfx.h b/drivers/misc/ipts/ipts-gfx.h
-new file mode 100644
-index 000000000000..03a5f3551ddf
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-gfx.h
-@@ -0,0 +1,24 @@
-+/*
-+ * Intel Precise Touch & Stylus gpu wrapper
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+
-+#ifndef _IPTS_GFX_H_
-+#define _IPTS_GFX_H_
-+
-+int ipts_open_gpu(ipts_info_t *ipts);
-+void ipts_close_gpu(ipts_info_t *ipts);
-+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags);
-+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf);
-+
-+#endif // _IPTS_GFX_H_
-diff --git a/drivers/misc/ipts/ipts-hid.c b/drivers/misc/ipts/ipts-hid.c
-new file mode 100644
-index 000000000000..3b3be6177648
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-hid.c
-@@ -0,0 +1,456 @@
-+/*
-+ * Intel Precise Touch & Stylus HID driver
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/module.h>
-+#include <linux/firmware.h>
-+#include <linux/hid.h>
-+#include <linux/vmalloc.h>
-+
-+#include "ipts.h"
-+#include "ipts-resource.h"
-+#include "ipts-sensor-regs.h"
-+#include "ipts-msg-handler.h"
-+
-+#define BUS_MEI				0x44
-+
-+#define	HID_DESC_INTEL	"intel/ipts/intel_desc.bin"
-+#define	HID_DESC_VENDOR	"intel/ipts/vendor_desc.bin"
-+MODULE_FIRMWARE(HID_DESC_INTEL);
-+MODULE_FIRMWARE(HID_DESC_VENDOR);
-+
-+typedef enum output_buffer_payload_type {
-+	OUTPUT_BUFFER_PAYLOAD_ERROR = 0,
-+	OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT,
-+	OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT,
-+	OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD,
-+	OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER
-+} output_buffer_payload_type_t;
-+
-+typedef struct kernel_output_buffer_header {
-+	u16 length;
-+	u8 payload_type;
-+	u8 reserved1;
-+	touch_hid_private_data_t hid_private_data;
-+	u8 reserved2[28];
-+	u8 data[0];
-+} kernel_output_buffer_header_t;
-+
-+typedef struct kernel_output_payload_error {
-+	u16 severity;
-+	u16 source;
-+	u8 code[4];
-+	char string[128];
-+} kernel_output_payload_error_t;
-+
-+static int ipts_hid_get_hid_descriptor(ipts_info_t *ipts, u8 **desc, int *size)
-+{
-+	u8 *buf;
-+	int hid_size = 0, ret = 0;
-+	const struct firmware *intel_desc = NULL;
-+	const struct firmware *vendor_desc = NULL;
-+	const char *intel_desc_path = HID_DESC_INTEL;
-+	const char *vendor_desc_path = HID_DESC_VENDOR;
-+
-+	ret = request_firmware(&intel_desc, intel_desc_path, &ipts->cldev->dev);
-+	if (ret) {
-+		goto no_hid;
-+	}
-+	hid_size = intel_desc->size;
-+
-+	ret = request_firmware(&vendor_desc, vendor_desc_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_dbg(ipts, "error in reading HID Vendor Descriptor\n");
-+	} else {
-+		hid_size += vendor_desc->size;
-+	}
-+
-+	ipts_dbg(ipts, "hid size = %d\n", hid_size);
-+	buf = vmalloc(hid_size);
-+	if (buf == NULL) {
-+		ret = -ENOMEM;
-+		goto no_mem;
-+	}
-+
-+	memcpy(buf, intel_desc->data, intel_desc->size);
-+	if (vendor_desc) {
-+		memcpy(&buf[intel_desc->size], vendor_desc->data,
-+							vendor_desc->size);
-+		release_firmware(vendor_desc);
-+	}
-+
-+	release_firmware(intel_desc);
-+
-+	*desc = buf;
-+	*size = hid_size;
-+
-+	return 0;
-+no_mem :
-+	if (vendor_desc)
-+		release_firmware(vendor_desc);
-+	release_firmware(intel_desc);
-+
-+no_hid :
-+	return ret;
-+}
-+
-+static int ipts_hid_parse(struct hid_device *hid)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	int ret = 0, size;
-+	u8 *buf;
-+
-+	ipts_dbg(ipts, "ipts_hid_parse() start\n");
-+	ret = ipts_hid_get_hid_descriptor(ipts, &buf, &size);
-+	if (ret != 0) {
-+		ipts_dbg(ipts, "ipts_hid_ipts_get_hid_descriptor ret %d\n", ret);
-+		return -EIO;
-+	}
-+
-+	ret = hid_parse_report(hid, buf, size);
-+	vfree(buf);
-+	if (ret) {
-+		ipts_err(ipts, "hid_parse_report error : %d\n", ret);
-+		goto out;
-+	}
-+
-+	ipts->hid_desc_ready = true;
-+out:
-+	return ret;
-+}
-+
-+static int ipts_hid_start(struct hid_device *hid)
-+{
-+	return 0;
-+}
-+
-+static void ipts_hid_stop(struct hid_device *hid)
-+{
-+	return;
-+}
-+
-+static int ipts_hid_open(struct hid_device *hid)
-+{
-+	return 0;
-+}
-+
-+static void ipts_hid_close(struct hid_device *hid)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+
-+	ipts->hid_desc_ready = false;
-+
-+	return;
-+}
-+
-+static int ipts_hid_send_hid2me_feedback(ipts_info_t *ipts, u32 fb_data_type,
-+							__u8 *buf, size_t count)
-+{
-+	ipts_buffer_info_t *fb_buf;
-+	touch_feedback_hdr_t *feedback;
-+	u8 *payload;
-+	int header_size;
-+	ipts_state_t state;
-+
-+	header_size = sizeof(touch_feedback_hdr_t);
-+
-+	if (count > ipts->resource.hid2me_buffer_size - header_size)
-+		return -EINVAL;
-+
-+	state = ipts_get_state(ipts);
-+	if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED)
-+		return 0;
-+
-+	fb_buf = ipts_get_hid2me_buffer(ipts);
-+	feedback = (touch_feedback_hdr_t *)fb_buf->addr;
-+	payload = fb_buf->addr + header_size;
-+	memset(feedback, 0, header_size);
-+
-+	feedback->feedback_data_type = fb_data_type;
-+	feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE;
-+	feedback->payload_size_bytes = count;
-+	feedback->buffer_id = TOUCH_HID_2_ME_BUFFER_ID;
-+	feedback->protocol_ver = 0;
-+	feedback->reserved[0] = 0xAC;
-+
-+	/* copy payload */
-+	memcpy(payload, buf, count);
-+
-+	ipts_send_feedback(ipts, TOUCH_HID_2_ME_BUFFER_ID, 0);
-+
-+	return 0;
-+}
-+
-+static int ipts_hid_raw_request(struct hid_device *hid,
-+				unsigned char report_number, __u8 *buf,
-+				size_t count, unsigned char report_type,
-+				int reqtype)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	u32 fb_data_type;
-+
-+	ipts_dbg(ipts, "hid raw request => report %d, request %d\n",
-+						 (int)report_type, reqtype);
-+
-+	if (report_type != HID_FEATURE_REPORT)
-+		return 0;
-+
-+	switch (reqtype) {
-+		case HID_REQ_GET_REPORT:
-+			fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES;
-+			break;
-+		case HID_REQ_SET_REPORT:
-+			fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES;
-+			break;
-+		default:
-+			ipts_err(ipts, "raw request not supprted: %d\n", reqtype);
-+			return -EIO;
-+	}
-+
-+	return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count);
-+}
-+
-+static int ipts_hid_output_report(struct hid_device *hid,
-+					__u8 *buf, size_t count)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	u32 fb_data_type;
-+
-+	ipts_dbg(ipts, "hid output report\n");
-+
-+	fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT;
-+
-+	return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count);
-+}
-+
-+static struct hid_ll_driver ipts_hid_ll_driver = {
-+	.parse = ipts_hid_parse,
-+	.start = ipts_hid_start,
-+	.stop = ipts_hid_stop,
-+	.open = ipts_hid_open,
-+	.close = ipts_hid_close,
-+	.raw_request = ipts_hid_raw_request,
-+	.output_report = ipts_hid_output_report,
-+};
-+
-+int ipts_hid_init(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	struct hid_device *hid;
-+
-+	hid = hid_allocate_device();
-+	if (IS_ERR(hid)) {
-+		ret = PTR_ERR(hid);
-+		goto err_dev;
-+	}
-+
-+	hid->driver_data = ipts;
-+	hid->ll_driver = &ipts_hid_ll_driver;
-+	hid->dev.parent = &ipts->cldev->dev;
-+	hid->bus = BUS_MEI;
-+	hid->version = ipts->device_info.fw_rev;
-+	hid->vendor = ipts->device_info.vendor_id;
-+	hid->product = ipts->device_info.device_id;
-+
-+	snprintf(hid->phys, sizeof(hid->phys), "heci3");
-+	snprintf(hid->name, sizeof(hid->name),
-+		 "%s %04hX:%04hX", "ipts", hid->vendor, hid->product);
-+
-+	ret = hid_add_device(hid);
-+	if (ret) {
-+		if (ret != -ENODEV)
-+			ipts_err(ipts, "can't add hid device: %d\n", ret);
-+		goto err_mem_free;
-+	}
-+
-+	ipts->hid = hid;
-+
-+	return 0;
-+
-+err_mem_free:
-+	hid_destroy_device(hid);
-+err_dev:
-+	return ret;
-+}
-+
-+void ipts_hid_release(ipts_info_t *ipts)
-+{
-+	if (!ipts->hid)
-+			return;
-+	hid_destroy_device(ipts->hid);
-+}
-+
-+int ipts_handle_hid_data(ipts_info_t *ipts,
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp)
-+{
-+	touch_raw_data_hdr_t *raw_header;
-+	ipts_buffer_info_t *buffer_info;
-+	touch_feedback_hdr_t *feedback;
-+	u8 *raw_data;
-+	int touch_data_buffer_index;
-+	int transaction_id;
-+	int ret = 0;
-+
-+	touch_data_buffer_index = (int)hid_rsp->touch_data_buffer_index;
-+	buffer_info = ipts_get_touch_data_buffer_hid(ipts);
-+	raw_header = (touch_raw_data_hdr_t *)buffer_info->addr;
-+	transaction_id = raw_header->hid_private_data.transaction_id;
-+
-+	raw_data = (u8*)raw_header + sizeof(touch_raw_data_hdr_t);
-+	if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_HID_REPORT) {
-+		memcpy(ipts->hid_input_report, raw_data,
-+				raw_header->raw_data_size_bytes);
-+
-+		ret = hid_input_report(ipts->hid, HID_INPUT_REPORT,
-+					(u8*)ipts->hid_input_report,
-+					raw_header->raw_data_size_bytes, 1);
-+		if (ret) {
-+			ipts_err(ipts, "error in hid_input_report : %d\n", ret);
-+		}
-+	} else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_GET_FEATURES) {
-+		/* TODO: implement together with "get feature ioctl" */
-+	} else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_ERROR) {
-+		touch_error_t *touch_err = (touch_error_t *)raw_data;
-+
-+		ipts_err(ipts, "error type : %d, me fw error : %x, err reg : %x\n",
-+				touch_err->touch_error_type,
-+				touch_err->touch_me_fw_error.value,
-+				touch_err->touch_error_register.reg_value);
-+	}
-+
-+	/* send feedback data for HID mode */
-+        buffer_info = ipts_get_feedback_buffer(ipts, touch_data_buffer_index);
-+	feedback = (touch_feedback_hdr_t *)buffer_info->addr;
-+	memset(feedback, 0, sizeof(touch_feedback_hdr_t));
-+	feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE;
-+	feedback->payload_size_bytes = 0;
-+	feedback->buffer_id = touch_data_buffer_index;
-+	feedback->protocol_ver = 0;
-+	feedback->reserved[0] = 0xAC;
-+
-+	ret = ipts_send_feedback(ipts, touch_data_buffer_index, transaction_id);
-+
-+	return ret;
-+}
-+
-+static int handle_outputs(ipts_info_t *ipts, int parallel_idx)
-+{
-+	kernel_output_buffer_header_t *out_buf_hdr;
-+	ipts_buffer_info_t *output_buf, *fb_buf = NULL;
-+	u8 *input_report, *payload;
-+	u32 transaction_id;
-+	int i, payload_size, ret = 0, header_size;
-+
-+	header_size = sizeof(kernel_output_buffer_header_t);
-+	output_buf = ipts_get_output_buffers_by_parallel_id(ipts, parallel_idx);
-+	for (i = 0; i < ipts->resource.num_of_outputs; i++) {
-+		out_buf_hdr = (kernel_output_buffer_header_t*)output_buf[i].addr;
-+		if (out_buf_hdr->length < header_size)
-+			continue;
-+
-+		payload_size = out_buf_hdr->length - header_size;
-+		payload = out_buf_hdr->data;
-+
-+		switch(out_buf_hdr->payload_type) {
-+			case OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT:
-+				input_report = ipts->hid_input_report;
-+				memcpy(input_report, payload, payload_size);
-+				hid_input_report(ipts->hid, HID_INPUT_REPORT,
-+						input_report, payload_size, 1);
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT:
-+				ipts_dbg(ipts, "output hid feature report\n");
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD:
-+				ipts_dbg(ipts, "output kernel load\n");
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER:
-+			{
-+				/* send feedback data for raw data mode */
-+                                fb_buf = ipts_get_feedback_buffer(ipts,
-+								parallel_idx);
-+				transaction_id = out_buf_hdr->
-+						hid_private_data.transaction_id;
-+				memcpy(fb_buf->addr, payload, payload_size);
-+				break;
-+			}
-+			case OUTPUT_BUFFER_PAYLOAD_ERROR:
-+			{
-+				kernel_output_payload_error_t *err_payload;
-+
-+				if (payload_size == 0)
-+					break;
-+
-+				err_payload =
-+					(kernel_output_payload_error_t*)payload;
-+
-+				ipts_err(ipts, "error : severity : %d,"
-+						" source : %d,"
-+						" code : %d:%d:%d:%d\n"
-+						"string %s\n",
-+						err_payload->severity,
-+						err_payload->source,
-+						err_payload->code[0],
-+						err_payload->code[1],
-+						err_payload->code[2],
-+						err_payload->code[3],
-+						err_payload->string);
-+				
-+				break;
-+			}
-+			default:
-+				ipts_err(ipts, "invalid output buffer payload\n");
-+				break;
-+		}
-+	}
-+
-+	if (fb_buf) {
-+		ret = ipts_send_feedback(ipts, parallel_idx, transaction_id);
-+		if (ret)
-+			return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static int handle_output_buffers(ipts_info_t *ipts, int cur_idx, int end_idx)
-+{
-+	int max_num_of_buffers = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	do {
-+		cur_idx++; /* cur_idx has last completed so starts with +1 */
-+		cur_idx %= max_num_of_buffers;
-+		handle_outputs(ipts, cur_idx);
-+	} while (cur_idx != end_idx);
-+
-+	return 0;
-+}
-+
-+int ipts_handle_processed_data(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	int current_buffer_idx;
-+	int last_buffer_idx;
-+
-+	current_buffer_idx = *ipts->last_submitted_id;
-+	last_buffer_idx = ipts->last_buffer_completed;
-+
-+	if (current_buffer_idx == last_buffer_idx)
-+		return 0;
-+
-+	ipts->last_buffer_completed = current_buffer_idx;
-+	handle_output_buffers(ipts, last_buffer_idx, current_buffer_idx);
-+
-+	return ret;
-+}
-diff --git a/drivers/misc/ipts/ipts-hid.h b/drivers/misc/ipts/ipts-hid.h
-new file mode 100644
-index 000000000000..f1b22c912df7
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-hid.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Intel Precise Touch & Stylus HID definition
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_HID_H_
-+#define	_IPTS_HID_H_
-+
-+#define	BUS_MEI				0x44
-+
-+#if 0 /* TODO : we have special report ID. will implement them */
-+#define WRITE_CHANNEL_REPORT_ID		0xa
-+#define READ_CHANNEL_REPORT_ID		0xb
-+#define CONFIG_CHANNEL_REPORT_ID	0xd
-+#define VENDOR_INFO_REPORT_ID		0xF
-+#define SINGLE_TOUCH_REPORT_ID		0x40
-+#endif
-+
-+int ipts_hid_init(ipts_info_t *ipts);
-+void ipts_hid_release(ipts_info_t *ipts);
-+int ipts_handle_hid_data(ipts_info_t *ipts,
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp);
-+
-+#endif /* _IPTS_HID_H_ */
-diff --git a/drivers/misc/ipts/ipts-kernel.c b/drivers/misc/ipts/ipts-kernel.c
-new file mode 100644
-index 000000000000..ca5e24ce579e
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-kernel.c
-@@ -0,0 +1,1050 @@
-+#include <linux/module.h>
-+#include <linux/firmware.h>
-+#include <linux/vmalloc.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-resource.h"
-+#include "ipts-binary-spec.h"
-+#include "ipts-state.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-gfx.h"
-+
-+#define MAX_IOCL_FILE_NAME_LEN		80
-+#define MAX_IOCL_FILE_PATH_LEN		256
-+
-+#pragma pack(1)
-+typedef struct bin_data_file_info {
-+    u32 io_buffer_type;
-+    u32 flags;
-+    char file_name[MAX_IOCL_FILE_NAME_LEN];
-+} bin_data_file_info_t;
-+
-+typedef struct bin_fw_info {
-+	char fw_name[MAX_IOCL_FILE_NAME_LEN];
-+
-+	/* list of parameters to load a kernel */
-+	s32 vendor_output;	/* output index. -1 for no use */
-+	u32 num_of_data_files;
-+	bin_data_file_info_t data_file[];
-+} bin_fw_info_t;
-+
-+typedef struct bin_fw_list {
-+	u32 num_of_fws;
-+	bin_fw_info_t fw_info[];
-+} bin_fw_list_t;
-+#pragma pack()
-+
-+/* OpenCL kernel */
-+typedef struct bin_workload {
-+	int cmdbuf_index;
-+	int iobuf_input;
-+	int iobuf_output[MAX_NUM_OUTPUT_BUFFERS];
-+} bin_workload_t;
-+
-+typedef struct bin_buffer {
-+	unsigned int handle;
-+	intel_ipts_mapbuffer_t *buf;
-+	bool no_unmap;	/* only releasing vendor kernel unmaps output buffers */
-+} bin_buffer_t;
-+
-+typedef struct bin_alloc_info {
-+	bin_buffer_t *buffs;
-+	int num_of_allocations;
-+	int num_of_outputs;
-+
-+	int num_of_buffers;
-+} bin_alloc_info_t;
-+
-+typedef struct bin_guc_wq_item {
-+	unsigned int batch_offset;
-+	unsigned int size;
-+	char data[];
-+} bin_guc_wq_item_t;
-+
-+typedef struct bin_kernel_info {
-+	bin_workload_t *wl;
-+	bin_alloc_info_t *alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item;
-+	ipts_bin_bufid_patch_t bufid_patch;
-+
-+	bool is_vendor; /* 1: vendor, 0: postprocessing */
-+} bin_kernel_info_t;
-+
-+typedef struct bin_kernel_list {
-+	intel_ipts_mapbuffer_t *bufid_buf;
-+	int num_of_kernels;
-+	bin_kernel_info_t kernels[];
-+} bin_kernel_list_t;
-+
-+typedef struct bin_parse_info {
-+	u8 *data;
-+	int size;
-+	int parsed;
-+
-+	bin_fw_info_t *fw_info;
-+
-+	/* only used by postprocessing */
-+	bin_kernel_info_t *vendor_kernel;
-+	u32 interested_vendor_output; /* interested vendor output index */
-+} bin_parse_info_t;
-+
-+#define BDW_SURFACE_BASE_ADDRESS		0x6101000e
-+#define SURFACE_STATE_OFFSET_WORD		4
-+#define SBA_OFFSET_BYTES			16384
-+#define LASTSUBMITID_DEFAULT_VALUE		-1
-+
-+#define IPTS_FW_PATH_FMT			"intel/ipts/%s"
-+#define IPTS_FW_CONFIG_FILE			"intel/ipts/ipts_fw_config.bin"
-+
-+MODULE_FIRMWARE(IPTS_FW_CONFIG_FILE);
-+
-+#define IPTS_INPUT_ON				((u32)1 << IPTS_INPUT)
-+#define IPTS_OUTPUT_ON				((u32)1 << IPTS_OUTPUT)
-+#define IPTS_CONFIGURATION_ON			((u32)1 << IPTS_CONFIGURATION)
-+#define IPTS_CALIBRATION_ON			((u32)1 << IPTS_CALIBRATION)
-+#define IPTS_FEATURE_ON				((u32)1 << IPTS_FEATURE)
-+
-+#define	DATA_FILE_FLAG_SHARE			0x00000001
-+#define	DATA_FILE_FLAG_ALLOC_CONTIGUOUS		0x00000002
-+
-+static int bin_read_fw(ipts_info_t *ipts, const char *fw_name,
-+						u8* data, int size)
-+{
-+	const struct firmware *fw = NULL;
-+	char fw_path[MAX_IOCL_FILE_PATH_LEN];
-+	int ret = 0;
-+
-+	snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name);
-+	ret = request_firmware(&fw, fw_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_err(ipts, "cannot read fw %s\n", fw_path);
-+		return ret;
-+	}
-+
-+	if (fw->size > size) {
-+		ipts_dbg(ipts, "too small buffer to contain fw data\n");
-+		ret = -EINVAL;
-+		goto rel_return;
-+	}
-+
-+	memcpy(data, fw->data, fw->size);
-+
-+rel_return:
-+	release_firmware(fw);
-+
-+	return ret;
-+}
-+
-+
-+static bin_data_file_info_t* bin_get_data_file_info(bin_fw_info_t* fw_info,
-+							u32 io_buffer_type)
-+{
-+	int i;
-+
-+	for (i = 0; i < fw_info->num_of_data_files; i++) {
-+		if (fw_info->data_file[i].io_buffer_type == io_buffer_type)
-+			break;
-+	}
-+
-+	if (i == fw_info->num_of_data_files)
-+		return NULL;
-+
-+	return &fw_info->data_file[i];
-+}
-+
-+static inline bool is_shared_data(const bin_data_file_info_t *data_file)
-+{
-+	if (data_file)
-+		return (!!(data_file->flags & DATA_FILE_FLAG_SHARE));
-+
-+	return false;
-+}
-+
-+static inline bool is_alloc_cont_data(const bin_data_file_info_t *data_file)
-+{
-+	if (data_file)
-+		return (!!(data_file->flags & DATA_FILE_FLAG_ALLOC_CONTIGUOUS));
-+
-+	return false;
-+}
-+
-+static inline bool is_parsing_vendor_kernel(const bin_parse_info_t *parse_info)
-+{
-+	/* vendor_kernel == null while loading itself(vendor kernel) */
-+	return parse_info->vendor_kernel == NULL;
-+}
-+
-+static int bin_read_allocation_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info)
-+{
-+	ipts_bin_alloc_list_t *alloc_list;
-+	int alloc_idx, parallel_idx, num_of_parallels, buf_idx, num_of_buffers;
-+	int parsed, size;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+
-+	alloc_list = (ipts_bin_alloc_list_t *)&parse_info->data[parsed];
-+
-+	/* validation check */
-+	if (sizeof(alloc_list->num) > size - parsed)
-+		return -EINVAL;
-+
-+	/* read the number of aloocations */
-+	parsed += sizeof(alloc_list->num);
-+
-+	/* validation check */
-+	if (sizeof(alloc_list->alloc[0]) * alloc_list->num > size - parsed)
-+		return -EINVAL;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	num_of_buffers = num_of_parallels * alloc_list->num + num_of_parallels;
-+
-+	alloc_info->buffs = vmalloc(sizeof(bin_buffer_t) * num_of_buffers);
-+	if (alloc_info->buffs == NULL)
-+		return -ENOMEM;
-+
-+	memset(alloc_info->buffs, 0, sizeof(bin_buffer_t) * num_of_buffers);
-+	for (alloc_idx = 0; alloc_idx < alloc_list->num; alloc_idx++) {
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+								parallel_idx++) {
-+			buf_idx = alloc_idx + (parallel_idx * alloc_list->num);
-+			alloc_info->buffs[buf_idx].handle =
-+					alloc_list->alloc[alloc_idx].handle;
-+
-+		}
-+
-+		parsed += sizeof(alloc_list->alloc[0]);
-+	}
-+
-+	parse_info->parsed = parsed;
-+	alloc_info->num_of_allocations = alloc_list->num;
-+	alloc_info->num_of_buffers = num_of_buffers;
-+
-+	ipts_dbg(ipts, "number of allocations = %d, buffers = %d\n",
-+						alloc_info->num_of_allocations,
-+						alloc_info->num_of_buffers);
-+
-+	return 0;
-+}
-+
-+static void patch_SBA(u32 *buf_addr, u64 gpu_addr, int size)
-+{
-+	u64 *stateBase;
-+	u64 SBA;
-+	u32 inst;
-+	int i;
-+
-+	SBA = gpu_addr + SBA_OFFSET_BYTES;
-+
-+	for (i = 0; i < size/4; i++) {
-+		inst = buf_addr[i];
-+		if (inst == BDW_SURFACE_BASE_ADDRESS) {
-+			stateBase = (u64*)&buf_addr[i + SURFACE_STATE_OFFSET_WORD];
-+			*stateBase |= SBA;
-+			*stateBase |= 0x01; // enable
-+			break;
-+		}
-+	}
-+}
-+
-+static int bin_read_cmd_buffer(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_cmdbuf_t *cmd;
-+	intel_ipts_mapbuffer_t *buf;
-+	int cmdbuf_idx, size, parsed, parallel_idx, num_of_parallels;
-+
-+	size = parse_info->size;
-+	parsed = parse_info->parsed;
-+
-+	cmd = (ipts_bin_cmdbuf_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(cmd->size) > size - parsed)
-+		return -EINVAL;
-+
-+	parsed += sizeof(cmd->size);
-+	if (cmd->size > size - parsed)
-+		return -EINVAL;
-+
-+	ipts_dbg(ipts, "cmd buf size = %d\n", cmd->size);
-+		
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	/* command buffers are located after the other allocations */
-+	cmdbuf_idx = num_of_parallels * alloc_info->num_of_allocations;
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		buf = ipts_map_buffer(ipts, cmd->size, 0);
-+		if (buf == NULL)
-+			return -ENOMEM;
-+
-+		ipts_dbg(ipts, "cmd_idx[%d] = %d, g:0x%p, c:0x%p\n", parallel_idx,
-+					cmdbuf_idx, buf->gfx_addr, buf->cpu_addr);
-+
-+		memcpy((void *)buf->cpu_addr, &(cmd->data[0]), cmd->size);
-+		patch_SBA(buf->cpu_addr, (u64)buf->gfx_addr, cmd->size);
-+		alloc_info->buffs[cmdbuf_idx].buf = buf;
-+		wl[parallel_idx].cmdbuf_index = cmdbuf_idx;
-+
-+		cmdbuf_idx++;
-+	}
-+
-+	parsed += cmd->size;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_find_alloc(ipts_info_t *ipts,
-+					bin_alloc_info_t *alloc_info,
-+					u32 handle)
-+{
-+	int i;
-+
-+	for (i = 0; i < alloc_info->num_of_allocations; i++) {
-+		if (alloc_info->buffs[i].handle == handle)
-+			return i;
-+	}
-+
-+	return -1;
-+}
-+
-+static intel_ipts_mapbuffer_t* bin_get_vendor_kernel_output(
-+						bin_parse_info_t *parse_info,
-+						int parallel_idx)
-+{
-+	bin_kernel_info_t *vendor = parse_info->vendor_kernel;
-+	bin_alloc_info_t *alloc_info;
-+	int buf_idx, vendor_output_idx;
-+
-+	alloc_info = vendor->alloc_info;
-+	vendor_output_idx = parse_info->interested_vendor_output;
-+
-+	if (vendor_output_idx >= alloc_info->num_of_outputs)
-+		return NULL;
-+
-+	buf_idx = vendor->wl[parallel_idx].iobuf_output[vendor_output_idx];
-+	return alloc_info->buffs[buf_idx].buf;
-+}
-+
-+static int bin_read_res_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_res_list_t *res_list;
-+	ipts_bin_res_t *res;
-+	intel_ipts_mapbuffer_t *buf;
-+	bin_data_file_info_t *data_file;
-+	u8 *bin_data;
-+	int i, size, parsed, parallel_idx, num_of_parallels, output_idx = -1;
-+	int buf_idx, num_of_alloc;
-+	u32 buf_size, flags, io_buf_type;
-+	bool initialize;
-+	
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	bin_data = parse_info->data;
-+
-+	res_list = (ipts_bin_res_list_t *)&parse_info->data[parsed];
-+	if (sizeof(res_list->num) > (size - parsed))
-+		return -EINVAL;
-+	parsed += sizeof(res_list->num);
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	ipts_dbg(ipts, "number of resources %u\n", res_list->num);
-+	for (i = 0; i < res_list->num; i++) {
-+		initialize = false; 
-+		io_buf_type = 0;
-+		flags = 0;
-+
-+		/* initial data */
-+		data_file = NULL;
-+
-+		res = (ipts_bin_res_t *)(&(bin_data[parsed]));
-+		if (sizeof(res[0]) > (size - parsed)) {
-+			return -EINVAL;
-+		}
-+
-+		ipts_dbg(ipts, "Resource(%d):handle 0x%08x type %u init %u"
-+				" size %u alsigned %u\n",
-+				i, res->handle, res->type, res->initialize,
-+				res->size, res->aligned_size);
-+                parsed += sizeof(res[0]);
-+
-+		if (res->initialize) {
-+			if (res->size > (size - parsed)) {
-+				return -EINVAL;
-+			}
-+			parsed += res->size;
-+		}
-+
-+		initialize = res->initialize;
-+		if (initialize && res->size > sizeof(ipts_bin_io_header_t)) {
-+			ipts_bin_io_header_t *io_hdr;
-+			io_hdr = (ipts_bin_io_header_t *)(&res->data[0]);
-+			if (strncmp(io_hdr->str, "INTELTOUCH", 10) == 0) {
-+				data_file = bin_get_data_file_info(
-+							parse_info->fw_info,
-+							(u32)io_hdr->type);
-+				switch (io_hdr->type) {
-+				case IPTS_INPUT:
-+					ipts_dbg(ipts, "input detected\n");
-+					io_buf_type = IPTS_INPUT_ON;
-+					flags = IPTS_BUF_FLAG_CONTIGUOUS;
-+					break;
-+				case IPTS_OUTPUT:
-+					ipts_dbg(ipts, "output detected\n");
-+					io_buf_type = IPTS_OUTPUT_ON;
-+					output_idx++;
-+					break;
-+				default:
-+					if ((u32)io_hdr->type > 31) {
-+						ipts_err(ipts,
-+							"invalid io buffer : %u\n",
-+							(u32)io_hdr->type);
-+						continue;
-+					}
-+
-+					if (is_alloc_cont_data(data_file))
-+						flags = IPTS_BUF_FLAG_CONTIGUOUS;
-+
-+					io_buf_type = ((u32)1 << (u32)io_hdr->type);
-+					ipts_dbg(ipts, "special io buffer %u\n",
-+								io_hdr->type);
-+					break;
-+				}
-+
-+				initialize = false;
-+			}
-+		}
-+
-+		num_of_alloc = alloc_info->num_of_allocations;
-+		buf_idx = bin_find_alloc(ipts, alloc_info, res->handle);
-+		if (buf_idx == -1) {
-+			ipts_dbg(ipts, "cannot find alloc info\n");
-+			return -EINVAL;
-+		}
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+					parallel_idx++, buf_idx += num_of_alloc) {
-+			if (!res->aligned_size)
-+				continue;
-+
-+			if (!(parallel_idx == 0 ||
-+				    (io_buf_type && !is_shared_data(data_file))))
-+				continue;
-+
-+			buf_size = res->aligned_size;
-+			if (io_buf_type & IPTS_INPUT_ON) {
-+				buf_size = max_t(u32,
-+						ipts->device_info.frame_size,
-+						buf_size);
-+				wl[parallel_idx].iobuf_input = buf_idx;
-+			} else if (io_buf_type & IPTS_OUTPUT_ON) {
-+				wl[parallel_idx].iobuf_output[output_idx] = buf_idx;
-+
-+				if (!is_parsing_vendor_kernel(parse_info) &&
-+								output_idx > 0) {
-+					ipts_err(ipts,
-+						"postproc with more than one inout"
-+						" is not supported : %d\n", output_idx);
-+					return -EINVAL;
-+				}
-+			}
-+
-+			if (!is_parsing_vendor_kernel(parse_info) &&
-+						io_buf_type & IPTS_OUTPUT_ON) {
-+				buf = bin_get_vendor_kernel_output(
-+								parse_info,
-+								parallel_idx);
-+				alloc_info->buffs[buf_idx].no_unmap = true;
-+			} else
-+				buf = ipts_map_buffer(ipts, buf_size, flags);
-+
-+			if (buf == NULL) {
-+				ipts_dbg(ipts, "ipts_map_buffer failed\n");
-+				return -ENOMEM;
-+			}
-+
-+			if (initialize) {
-+				memcpy((void *)buf->cpu_addr, &(res->data[0]),
-+								res->size);
-+			} else {
-+				if (data_file && strlen(data_file->file_name)) {
-+					bin_read_fw(ipts, data_file->file_name,
-+                                                        buf->cpu_addr, buf_size);
-+				} else if (is_parsing_vendor_kernel(parse_info) ||
-+						!(io_buf_type & IPTS_OUTPUT_ON)) {
-+					memset((void *)buf->cpu_addr, 0, res->size);
-+				}
-+			}
-+
-+			alloc_info->buffs[buf_idx].buf = buf;
-+		}
-+	}
-+
-+        alloc_info->num_of_outputs = output_idx + 1;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_read_patch_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_patch_list_t *patch_list;
-+	ipts_bin_patch_t *patch;
-+	intel_ipts_mapbuffer_t *cmd = NULL;
-+	u8 *batch;
-+	int parsed, size, i, parallel_idx, num_of_parallels, cmd_idx, buf_idx;
-+	unsigned int gtt_offset;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	patch_list = (ipts_bin_patch_list_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(patch_list->num) > (size - parsed)) {
-+		return -EFAULT;
-+	}
-+	parsed += sizeof(patch_list->num);
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	patch = (ipts_bin_patch_t *)(&patch_list->patch[0]);
-+	for (i = 0; i < patch_list->num; i++) {
-+		if (sizeof(patch_list->patch[0]) > (size - parsed)) {
-+			return -EFAULT;
-+		}
-+
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+								parallel_idx++) {
-+			cmd_idx = wl[parallel_idx].cmdbuf_index;
-+			buf_idx = patch[i].index + parallel_idx *
-+						alloc_info->num_of_allocations;
-+
-+			if (alloc_info->buffs[buf_idx].buf == NULL) {
-+				/* buffer shared */
-+				buf_idx = patch[i].index;
-+			}
-+
-+			cmd = alloc_info->buffs[cmd_idx].buf;
-+			batch = (char *)(u64)cmd->cpu_addr;
-+
-+			gtt_offset = 0;
-+			if(alloc_info->buffs[buf_idx].buf != NULL) {
-+				gtt_offset = (u32)(u64)
-+					alloc_info->buffs[buf_idx].buf->gfx_addr;
-+			} 
-+			gtt_offset += patch[i].alloc_offset;
-+
-+			batch += patch[i].patch_offset;
-+			*(u32*)batch = gtt_offset;
-+		}
-+
-+		parsed += sizeof(patch_list->patch[0]);
-+	}
-+
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_read_guc_wq_item(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_guc_wq_item_t **guc_wq_item)
-+{
-+	ipts_bin_guc_wq_info_t *bin_guc_wq;
-+	bin_guc_wq_item_t *item;
-+	u8 *wi_data;
-+	int size, parsed, hdr_size, wi_size;
-+	int i, batch_offset;
-+	
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	bin_guc_wq = (ipts_bin_guc_wq_info_t *)&parse_info->data[parsed];
-+
-+	wi_size = bin_guc_wq->size;
-+	wi_data = bin_guc_wq->data;
-+	batch_offset = bin_guc_wq->batch_offset;
-+	ipts_dbg(ipts, "wi size = %d, bt offset = %d\n", wi_size, batch_offset);
-+	for (i = 0; i < wi_size / sizeof(u32); i++) {
-+		ipts_dbg(ipts, "wi[%d] = 0x%08x\n", i, *((u32*)wi_data + i));
-+	}
-+	hdr_size = sizeof(bin_guc_wq->size) + sizeof(bin_guc_wq->batch_offset);
-+
-+	if (hdr_size > (size - parsed)) {
-+		return -EINVAL;
-+	}
-+	parsed += hdr_size;
-+
-+	item = vmalloc(sizeof(bin_guc_wq_item_t) + wi_size);
-+	if (item == NULL)
-+		return -ENOMEM;
-+
-+	item->size = wi_size;
-+	item->batch_offset = batch_offset;
-+	memcpy(item->data, wi_data, wi_size);
-+
-+	*guc_wq_item = item;
-+
-+	parsed += wi_size;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_setup_guc_workqueue(ipts_info_t *ipts,
-+					bin_kernel_list_t *kernel_list)
-+{
-+	bin_alloc_info_t *alloc_info;
-+	bin_workload_t *wl;
-+	bin_kernel_info_t *kernel;
-+	u8 *wq_start, *wq_addr, *wi_data;
-+	bin_buffer_t *bin_buf;
-+	int wq_size, wi_size, parallel_idx, cmd_idx, k_idx, iter_size;
-+	int i, num_of_parallels, batch_offset, k_num, total_workload;
-+	
-+	wq_addr = (u8*)ipts->resource.wq_info.wq_addr;
-+	wq_size = ipts->resource.wq_info.wq_size;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	total_workload = ipts_get_wq_item_size(ipts);
-+	k_num = kernel_list->num_of_kernels;
-+
-+	iter_size = total_workload * num_of_parallels;
-+	if (wq_size % iter_size) {
-+		ipts_err(ipts, "wq item cannot fit into wq\n");
-+		return -EINVAL;
-+	}
-+
-+	wq_start = wq_addr;
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+							parallel_idx++) {
-+		kernel = &kernel_list->kernels[0];
-+		for (k_idx = 0; k_idx < k_num; k_idx++, kernel++) {
-+			wl = kernel->wl;
-+			alloc_info = kernel->alloc_info;
-+
-+			batch_offset = kernel->guc_wq_item->batch_offset;
-+			wi_size = kernel->guc_wq_item->size;
-+			wi_data = &kernel->guc_wq_item->data[0];
-+			
-+			cmd_idx = wl[parallel_idx].cmdbuf_index;
-+			bin_buf = &alloc_info->buffs[cmd_idx];
-+
-+			/* Patch the WQ Data with proper batch buffer offset */
-+			*(u32*)(wi_data + batch_offset) =
-+				(u32)(unsigned long)(bin_buf->buf->gfx_addr);
-+
-+			memcpy(wq_addr, wi_data, wi_size);
-+
-+			wq_addr += wi_size;
-+		}
-+	}
-+
-+	for (i = 0; i < (wq_size / iter_size) - 1; i++) {
-+		memcpy(wq_addr, wq_start, iter_size);
-+		wq_addr += iter_size;
-+	}
-+
-+	return 0;
-+}
-+
-+static int bin_read_bufid_patch(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					ipts_bin_bufid_patch_t *bufid_patch)
-+{
-+	ipts_bin_bufid_patch_t *patch;
-+	int size, parsed;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	patch = (ipts_bin_bufid_patch_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(ipts_bin_bufid_patch_t) > (size - parsed)) {
-+		ipts_dbg(ipts, "invalid bufid info\n");
-+		return -EINVAL;
-+	}
-+	parsed += sizeof(ipts_bin_bufid_patch_t);
-+
-+	memcpy(bufid_patch, patch, sizeof(ipts_bin_bufid_patch_t));
-+
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_setup_bufid_buffer(ipts_info_t *ipts, bin_kernel_list_t *kernel_list)
-+{
-+	intel_ipts_mapbuffer_t *buf, *cmd_buf;
-+	bin_kernel_info_t *last_kernel;
-+	bin_alloc_info_t *alloc_info;
-+	bin_workload_t *wl;
-+	u8 *batch;
-+	int parallel_idx, num_of_parallels, cmd_idx;
-+	u32 mem_offset, imm_offset;
-+
-+	buf = ipts_map_buffer(ipts, PAGE_SIZE, 0);
-+	if (!buf) {
-+		return -ENOMEM;
-+	}
-+
-+	last_kernel = &kernel_list->kernels[kernel_list->num_of_kernels - 1];
-+
-+	mem_offset = last_kernel->bufid_patch.mem_offset;
-+	imm_offset = last_kernel->bufid_patch.imm_offset;
-+	wl = last_kernel->wl;
-+	alloc_info = last_kernel->alloc_info;
-+
-+	/* Initialize the buffer with default value */
-+        *((u32*)buf->cpu_addr) = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->current_buffer_index = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->last_buffer_completed = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->last_submitted_id = (int*)buf->cpu_addr;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		cmd_idx = wl[parallel_idx].cmdbuf_index;
-+		cmd_buf = alloc_info->buffs[cmd_idx].buf;
-+		batch = (u8*)(u64)cmd_buf->cpu_addr;
-+
-+		*((u32*)(batch + mem_offset)) = (u32)(u64)(buf->gfx_addr);
-+                *((u32*)(batch + imm_offset)) = parallel_idx;
-+	}
-+
-+	kernel_list->bufid_buf = buf;
-+
-+	return 0;
-+}
-+
-+static void unmap_buffers(ipts_info_t *ipts, bin_alloc_info_t *alloc_info)
-+{
-+	bin_buffer_t *buffs;
-+	int i, num_of_buffers;
-+
-+	num_of_buffers = alloc_info->num_of_buffers;
-+	buffs = &alloc_info->buffs[0];
-+
-+	for (i = 0; i < num_of_buffers; i++) {
-+		if (buffs[i].no_unmap != true && buffs[i].buf != NULL)
-+			ipts_unmap_buffer(ipts, buffs[i].buf);
-+	}
-+}
-+
-+static int load_kernel(ipts_info_t *ipts, bin_parse_info_t *parse_info,
-+						bin_kernel_info_t *kernel)
-+{
-+	ipts_bin_header_t *hdr;
-+	bin_workload_t *wl;
-+	bin_alloc_info_t *alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item = NULL;
-+	ipts_bin_bufid_patch_t bufid_patch;
-+	int num_of_parallels, ret;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+        /* check header version and magic numbers */
-+	hdr = (ipts_bin_header_t *)parse_info->data;
-+	if (hdr->version != IPTS_BIN_HEADER_VERSION ||
-+					strncmp(hdr->str, "IOCL", 4) != 0) {
-+		ipts_err(ipts, "binary header is not correct version = %d, "
-+				"string = %c%c%c%c\n", hdr->version,
-+				hdr->str[0], hdr->str[1],
-+				hdr->str[2], hdr->str[3] );
-+		return -EINVAL;
-+	}
-+
-+	parse_info->parsed = sizeof(ipts_bin_header_t);
-+	wl = vmalloc(sizeof(bin_workload_t) * num_of_parallels);
-+	if (wl == NULL)
-+		return -ENOMEM;
-+	memset(wl, 0, sizeof(bin_workload_t) * num_of_parallels);
-+
-+	alloc_info = vmalloc(sizeof(bin_alloc_info_t));
-+	if (alloc_info == NULL) {
-+		vfree(wl);
-+		return -ENOMEM;
-+	}
-+	memset(alloc_info, 0, sizeof(bin_alloc_info_t));
-+
-+        ipts_dbg(ipts, "kernel setup(size : %d)\n", parse_info->size);
-+
-+	ret = bin_read_allocation_list(ipts, parse_info, alloc_info);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_allocation_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_cmd_buffer(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_cmd_buffer\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_res_list(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_res_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_patch_list(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_patch_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_guc_wq_item(ipts, parse_info, &guc_wq_item);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_guc_workqueue\n");
-+		goto setup_error;
-+	}
-+
-+	memset(&bufid_patch, 0, sizeof(bufid_patch));
-+	ret = bin_read_bufid_patch(ipts, parse_info, &bufid_patch);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_bufid_patch\n");
-+		goto setup_error;
-+	}
-+
-+	kernel->wl = wl;
-+	kernel->alloc_info = alloc_info;
-+	kernel->is_vendor = is_parsing_vendor_kernel(parse_info);
-+	kernel->guc_wq_item = guc_wq_item;
-+	memcpy(&kernel->bufid_patch, &bufid_patch, sizeof(bufid_patch));
-+
-+        return 0;
-+
-+setup_error:
-+	vfree(guc_wq_item);
-+
-+	unmap_buffers(ipts, alloc_info);
-+
-+	vfree(alloc_info->buffs);
-+	vfree(alloc_info);
-+	vfree(wl);
-+
-+	return ret;
-+}
-+
-+void bin_setup_input_output(ipts_info_t *ipts, bin_kernel_list_t *kernel_list)
-+{
-+	bin_kernel_info_t *vendor_kernel;
-+	bin_workload_t *wl;
-+	intel_ipts_mapbuffer_t *buf;
-+	bin_alloc_info_t *alloc_info;
-+	int parallel_idx, num_of_parallels, i, buf_idx;
-+
-+	vendor_kernel = &kernel_list->kernels[0];
-+
-+	wl = vendor_kernel->wl;
-+	alloc_info = vendor_kernel->alloc_info;
-+	ipts->resource.num_of_outputs = alloc_info->num_of_outputs;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		buf_idx = wl[parallel_idx].iobuf_input;
-+		buf = alloc_info->buffs[buf_idx].buf;
-+
-+		ipts_dbg(ipts, "in_buf[%d](%d) c:%p, p:%p, g:%p\n",
-+					parallel_idx, buf_idx, (void*)buf->cpu_addr,
-+					(void*)buf->phy_addr, (void*)buf->gfx_addr);
-+
-+		ipts_set_input_buffer(ipts, parallel_idx, buf->cpu_addr,
-+								buf->phy_addr);
-+
-+		for (i = 0; i < alloc_info->num_of_outputs; i++) {
-+			buf_idx = wl[parallel_idx].iobuf_output[i];
-+			buf = alloc_info->buffs[buf_idx].buf;
-+
-+			ipts_dbg(ipts, "out_buf[%d][%d] c:%p, p:%p, g:%p\n",
-+					parallel_idx, i, (void*)buf->cpu_addr,
-+					(void*)buf->phy_addr, (void*)buf->gfx_addr);
-+
-+			ipts_set_output_buffer(ipts, parallel_idx, i,
-+					buf->cpu_addr, buf->phy_addr);
-+		}
-+	}
-+}
-+
-+static void unload_kernel(ipts_info_t *ipts, bin_kernel_info_t *kernel)
-+{
-+	bin_alloc_info_t *alloc_info = kernel->alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item = kernel->guc_wq_item;
-+
-+	if (guc_wq_item) {
-+		vfree(guc_wq_item);
-+	}
-+
-+	if (alloc_info) {
-+		unmap_buffers(ipts, alloc_info);
-+
-+		vfree(alloc_info->buffs);
-+		vfree(alloc_info);
-+	}
-+}
-+
-+static int setup_kernel(ipts_info_t *ipts, bin_fw_list_t *fw_list)
-+{
-+	bin_kernel_list_t *kernel_list = NULL;
-+	bin_kernel_info_t *kernel = NULL;
-+	const struct firmware *fw = NULL;
-+	bin_workload_t *wl;
-+	bin_fw_info_t *fw_info;
-+	char *fw_name, *fw_data;
-+	bin_parse_info_t parse_info;
-+	int ret = 0, kernel_idx = 0, num_of_kernels = 0;
-+	int vendor_output_idx, total_workload = 0;
-+	char fw_path[MAX_IOCL_FILE_PATH_LEN];
-+
-+	num_of_kernels = fw_list->num_of_fws;
-+	kernel_list = vmalloc(sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list));
-+	if (kernel_list == NULL)
-+		return -ENOMEM;
-+
-+	memset(kernel_list, 0, sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list));
-+	kernel_list->num_of_kernels = num_of_kernels;
-+	kernel = &kernel_list->kernels[0];
-+
-+	fw_data = (char *)&fw_list->fw_info[0];
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		fw_info = (bin_fw_info_t *)fw_data;
-+		fw_name = &fw_info->fw_name[0];
-+		vendor_output_idx = fw_info->vendor_output;
-+		snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name);
-+		ret = request_firmware(&fw, (const char *)fw_path, &ipts->cldev->dev);
-+		if (ret) {
-+			ipts_err(ipts, "cannot read fw %s\n", fw_path);
-+			goto error_exit;
-+		}
-+
-+		parse_info.data = (u8*)fw->data;
-+		parse_info.size = fw->size;
-+		parse_info.parsed = 0;
-+		parse_info.fw_info = fw_info;
-+		parse_info.vendor_kernel = (kernel_idx == 0) ? NULL : &kernel[0];
-+		parse_info.interested_vendor_output = vendor_output_idx;
-+
-+		ret = load_kernel(ipts, &parse_info, &kernel[kernel_idx]);
-+		if (ret) {
-+			ipts_err(ipts, "do_setup_kernel error : %d\n", ret);
-+			release_firmware(fw);
-+			goto error_exit;
-+		}
-+
-+		release_firmware(fw);
-+
-+		total_workload += kernel[kernel_idx].guc_wq_item->size;
-+
-+		/* advance to the next kernel */
-+		fw_data += sizeof(bin_fw_info_t);
-+		fw_data += sizeof(bin_data_file_info_t) * fw_info->num_of_data_files;
-+	}
-+
-+	ipts_set_wq_item_size(ipts, total_workload);
-+	
-+	ret = bin_setup_guc_workqueue(ipts, kernel_list);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error setup_guc_workqueue\n");
-+		goto error_exit;
-+	}
-+
-+	ret = bin_setup_bufid_buffer(ipts, kernel_list);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error setup_lastbubmit_buffer\n");
-+		goto error_exit;
-+	}
-+
-+	bin_setup_input_output(ipts, kernel_list);
-+
-+	/* workload is not needed during run-time so free them */
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		wl = kernel[kernel_idx].wl;
-+		vfree(wl);
-+	}
-+
-+	ipts->kernel_handle = (u64)kernel_list;
-+
-+	return 0;
-+
-+error_exit:
-+
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		wl = kernel[kernel_idx].wl;
-+		vfree(wl);
-+		unload_kernel(ipts, &kernel[kernel_idx]);
-+	}
-+
-+	vfree(kernel_list);
-+
-+	return ret;
-+}
-+
-+
-+static void release_kernel(ipts_info_t *ipts)
-+{
-+	bin_kernel_list_t *kernel_list;
-+	bin_kernel_info_t *kernel;
-+	int k_idx, k_num;
-+
-+	kernel_list = (bin_kernel_list_t *)ipts->kernel_handle;
-+	k_num = kernel_list->num_of_kernels;
-+	kernel = &kernel_list->kernels[0];
-+
-+	for (k_idx = 0; k_idx < k_num; k_idx++) {
-+		unload_kernel(ipts, kernel);
-+		kernel++;
-+	}	
-+
-+	ipts_unmap_buffer(ipts, kernel_list->bufid_buf);
-+
-+	vfree(kernel_list);
-+	ipts->kernel_handle = 0;
-+}
-+
-+int ipts_init_kernels(ipts_info_t *ipts)
-+{
-+	const struct firmware *config_fw = NULL;
-+	const char *config_fw_path = IPTS_FW_CONFIG_FILE;
-+	bin_fw_list_t *fw_list;
-+	int ret;
-+
-+	ret = ipts_open_gpu(ipts);
-+	if (ret) {
-+		ipts_err(ipts, "open gpu error : %d\n", ret);
-+		return ret;
-+	}
-+
-+	ret = request_firmware(&config_fw, config_fw_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_err(ipts, "request firmware error : %d\n", ret);
-+		goto close_gpu;
-+	}
-+
-+	fw_list = (bin_fw_list_t *)config_fw->data;
-+	ret = setup_kernel(ipts, fw_list);
-+	if (ret) {
-+		ipts_err(ipts, "setup kernel error : %d\n", ret);
-+		goto close_firmware;
-+	}
-+
-+	release_firmware(config_fw);
-+
-+	return ret;
-+
-+close_firmware:
-+	release_firmware(config_fw);
-+
-+close_gpu:
-+	ipts_close_gpu(ipts);
-+
-+	return ret;
-+}
-+
-+void ipts_release_kernels(ipts_info_t *ipts)
-+{
-+	release_kernel(ipts);
-+	ipts_close_gpu(ipts);
-+}
-diff --git a/drivers/misc/ipts/ipts-kernel.h b/drivers/misc/ipts/ipts-kernel.h
-new file mode 100644
-index 000000000000..0e7f1393b807
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-kernel.h
-@@ -0,0 +1,23 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus Linux driver
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _ITPS_GFX_H
-+#define _ITPS_GFX_H
-+
-+int ipts_init_kernels(ipts_info_t *ipts);
-+void ipts_release_kernels(ipts_info_t *ipts);
-+
-+#endif
-diff --git a/drivers/misc/ipts/ipts-mei-msgs.h b/drivers/misc/ipts/ipts-mei-msgs.h
-new file mode 100644
-index 000000000000..8ca146800a47
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-mei-msgs.h
-@@ -0,0 +1,585 @@
-+/*
-+ * Precise Touch HECI Message
-+ *
-+ * Copyright (c) 2013-2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_MEI_MSGS_H_
-+#define _IPTS_MEI_MSGS_H_
-+
-+#include "ipts-sensor-regs.h"
-+
-+#pragma pack(1)
-+
-+
-+// Initial protocol version
-+#define TOUCH_HECI_CLIENT_PROTOCOL_VERSION      10
-+
-+// GUID that identifies the Touch HECI client.
-+#define TOUCH_HECI_CLIENT_GUID  \
-+            {0x3e8d0870, 0x271a, 0x4208, {0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04}}
-+
-+
-+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch
-+#ifndef C_ASSERT
-+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
-+#endif
-+
-+
-+// General Type Defines for compatibility with HID driver and BIOS
-+#ifndef BIT0
-+#define BIT0 1
-+#endif
-+#ifndef BIT1
-+#define BIT1 2
-+#endif
-+#ifndef BIT2
-+#define BIT2 4
-+#endif
-+
-+
-+#define TOUCH_SENSOR_GET_DEVICE_INFO_CMD        0x00000001
-+#define TOUCH_SENSOR_GET_DEVICE_INFO_RSP        0x80000001
-+
-+
-+#define TOUCH_SENSOR_SET_MODE_CMD               0x00000002
-+#define TOUCH_SENSOR_SET_MODE_RSP               0x80000002
-+
-+
-+#define TOUCH_SENSOR_SET_MEM_WINDOW_CMD         0x00000003
-+#define TOUCH_SENSOR_SET_MEM_WINDOW_RSP         0x80000003
-+
-+
-+#define TOUCH_SENSOR_QUIESCE_IO_CMD             0x00000004
-+#define TOUCH_SENSOR_QUIESCE_IO_RSP             0x80000004
-+
-+
-+#define TOUCH_SENSOR_HID_READY_FOR_DATA_CMD     0x00000005
-+#define TOUCH_SENSOR_HID_READY_FOR_DATA_RSP     0x80000005
-+
-+
-+#define TOUCH_SENSOR_FEEDBACK_READY_CMD         0x00000006
-+#define TOUCH_SENSOR_FEEDBACK_READY_RSP         0x80000006
-+
-+
-+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD       0x00000007
-+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP       0x80000007
-+
-+
-+#define TOUCH_SENSOR_NOTIFY_DEV_READY_CMD       0x00000008
-+#define TOUCH_SENSOR_NOTIFY_DEV_READY_RSP       0x80000008
-+
-+
-+#define TOUCH_SENSOR_SET_POLICIES_CMD           0x00000009
-+#define TOUCH_SENSOR_SET_POLICIES_RSP           0x80000009
-+
-+
-+#define TOUCH_SENSOR_GET_POLICIES_CMD           0x0000000A
-+#define TOUCH_SENSOR_GET_POLICIES_RSP           0x8000000A
-+
-+
-+#define TOUCH_SENSOR_RESET_CMD                  0x0000000B
-+#define TOUCH_SENSOR_RESET_RSP                  0x8000000B
-+
-+
-+#define TOUCH_SENSOR_READ_ALL_REGS_CMD          0x0000000C
-+#define TOUCH_SENSOR_READ_ALL_REGS_RSP          0x8000000C
-+
-+
-+#define TOUCH_SENSOR_CMD_ERROR_RSP              0x8FFFFFFF  // M2H: ME sends this message to indicate previous command was unrecognized/unsupported
-+
-+
-+
-+//*******************************************************************
-+//
-+// Touch Sensor Status Codes
-+//
-+//*******************************************************************
-+typedef enum touch_status
-+{
-+    TOUCH_STATUS_SUCCESS = 0,               //  0 Requested operation was successful
-+    TOUCH_STATUS_INVALID_PARAMS,            //  1 Invalid parameter(s) sent
-+    TOUCH_STATUS_ACCESS_DENIED,             //  2 Unable to validate address range
-+    TOUCH_STATUS_CMD_SIZE_ERROR,            //  3 HECI message incorrect size for specified command
-+    TOUCH_STATUS_NOT_READY,                 //  4 Memory window not set or device is not armed for operation
-+    TOUCH_STATUS_REQUEST_OUTSTANDING,       //  5 There is already an outstanding message of the same type, must wait for response before sending another request of that type
-+    TOUCH_STATUS_NO_SENSOR_FOUND,           //  6 Sensor could not be found. Either no sensor is connected, the sensor has not yet initialized, or the system is improperly configured.
-+    TOUCH_STATUS_OUT_OF_MEMORY,             //  7 Not enough memory/storage for requested operation
-+    TOUCH_STATUS_INTERNAL_ERROR,            //  8 Unexpected error occurred
-+    TOUCH_STATUS_SENSOR_DISABLED,           //  9 Used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP to indicate sensor has been disabled or reset and must be reinitialized.
-+    TOUCH_STATUS_COMPAT_CHECK_FAIL,         // 10 Used to indicate compatibility revision check between sensor and ME failed, or protocol ver between ME/HID/Kernels failed.
-+    TOUCH_STATUS_SENSOR_EXPECTED_RESET,     // 11 Indicates sensor went through a reset initiated by ME
-+    TOUCH_STATUS_SENSOR_UNEXPECTED_RESET,   // 12 Indicates sensor went through an unexpected reset
-+    TOUCH_STATUS_RESET_FAILED,              // 13 Requested sensor reset failed to complete
-+    TOUCH_STATUS_TIMEOUT,                   // 14 Operation timed out
-+    TOUCH_STATUS_TEST_MODE_FAIL,            // 15 Test mode pattern did not match expected values
-+    TOUCH_STATUS_SENSOR_FAIL_FATAL,         // 16 Indicates sensor reported fatal error during reset sequence. Further progress is not possible.
-+    TOUCH_STATUS_SENSOR_FAIL_NONFATAL,      // 17 Indicates sensor reported non-fatal error during reset sequence. HID/BIOS logs error and attempts to continue.
-+    TOUCH_STATUS_INVALID_DEVICE_CAPS,       // 18 Indicates sensor reported invalid capabilities, such as not supporting required minimum frequency or I/O mode.
-+    TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS,    // 19 Indicates that command cannot be complete until ongoing Quiesce I/O flow has completed.
-+    TOUCH_STATUS_MAX                        // 20 Invalid value, never returned
-+} touch_status_t;
-+C_ASSERT(sizeof(touch_status_t) == 4);
-+
-+
-+
-+//*******************************************************************
-+//
-+// Defines for message structures used for Host to ME communication
-+//
-+//*******************************************************************
-+
-+
-+typedef enum touch_sensor_mode
-+{
-+    TOUCH_SENSOR_MODE_HID = 0,          // Set mode to HID mode
-+    TOUCH_SENSOR_MODE_RAW_DATA,         // Set mode to Raw Data mode
-+    TOUCH_SENSOR_MODE_SENSOR_DEBUG = 4, // Used like TOUCH_SENSOR_MODE_HID but data coming from sensor is not necessarily a HID packet.
-+    TOUCH_SENSOR_MODE_MAX               // Invalid value
-+} touch_sensor_mode_t;
-+C_ASSERT(sizeof(touch_sensor_mode_t) == 4);
-+
-+typedef struct touch_sensor_set_mode_cmd_data
-+{
-+    touch_sensor_mode_t	sensor_mode;     // Indicate desired sensor mode
-+    u32					Reserved[3];    // For future expansion
-+} touch_sensor_set_mode_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mode_cmd_data_t) == 16);
-+
-+
-+#define TOUCH_SENSOR_MAX_DATA_BUFFERS   16
-+#define TOUCH_HID_2_ME_BUFFER_ID        TOUCH_SENSOR_MAX_DATA_BUFFERS
-+#define TOUCH_HID_2_ME_BUFFER_SIZE_MAX  1024
-+#define TOUCH_INVALID_BUFFER_ID         0xFF
-+
-+typedef struct touch_sensor_set_mem_window_cmd_data
-+{
-+    u32  touch_data_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS];    // Lower 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize
-+    u32  touch_data_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS];    // Upper 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize
-+    u32  tail_offset_addr_lower;                                        // Lower 32 bits of Tail Offset physical address
-+    u32  tail_offset_addr_upper;                                        // Upper 32 bits of Tail Offset physical address, always 32 bit, increment by WorkQueueItemSize
-+    u32  doorbell_cookie_addr_lower;                                    // Lower 32 bits of Doorbell register physical address
-+    u32  doorbell_cookie_addr_upper;                                    // Upper 32 bits of Doorbell register physical address, always 32 bit, increment as integer, rollover to 1
-+    u32  feedback_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS];     // Lower 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize
-+    u32  feedback_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS];     // Upper 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize
-+    u32  hid2me_buffer_addr_lower;                                      // Lower 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize.
-+    u32  hid2me_buffer_addr_upper;                                      // Upper 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize.
-+    u32  hid2me_buffer_size;                                           // Size in bytes of Hid2MeBuffer, can be no bigger than TOUCH_HID_2_ME_BUFFER_SIZE_MAX
-+    u8   reserved1;                                                  // For future expansion
-+    u8   work_queue_item_size;                                          // Size in bytes of the GuC Work Queue Item pointed to by TailOffset
-+    u16  work_queue_size;                                              // Size in bytes of the entire GuC Work Queue
-+    u32  reserved[8];                                                // For future expansion
-+} touch_sensor_set_mem_window_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mem_window_cmd_data_t) == 320);
-+
-+
-+#define TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET BIT0   // indicates GuC got reset and ME must re-read GuC data such as TailOffset and Doorbell Cookie values
-+
-+typedef struct touch_sensor_quiesce_io_cmd_data
-+{
-+    u32  quiesce_flags;   // Optionally set TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET
-+    u32  reserved[2];
-+} touch_sensor_quiesce_io_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_quiesce_io_cmd_data_t) == 12);
-+
-+
-+typedef struct touch_sensor_feedback_ready_cmd_data
-+{
-+    u8   feedback_index;  // Index value from 0 to TOUCH_HID_2_ME_BUFFER_ID used to indicate which Feedback Buffer to use. Using special value TOUCH_HID_2_ME_BUFFER_ID
-+                            // is an indication to ME to get feedback data from the Hid2Me buffer instead of one of the standard Feedback buffers.
-+    u8   reserved1[3];   // For future expansion
-+    u32  transaction_id;  // Transaction ID that was originally passed to host in TOUCH_HID_PRIVATE_DATA. Used to track round trip of a given transaction for performance measurements.
-+    u32  reserved2[2];   // For future expansion
-+} touch_sensor_feedback_ready_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_feedback_ready_cmd_data_t) == 16);
-+
-+
-+#define TOUCH_DEFAULT_DOZE_TIMER_SECONDS    30
-+
-+typedef enum touch_freq_override
-+{
-+    TOUCH_FREQ_OVERRIDE_NONE,   // Do not apply any override
-+    TOUCH_FREQ_OVERRIDE_10MHZ,  // Force frequency to 10MHz (not currently supported)
-+    TOUCH_FREQ_OVERRIDE_17MHZ,  // Force frequency to 17MHz
-+    TOUCH_FREQ_OVERRIDE_30MHZ,  // Force frequency to 30MHz
-+    TOUCH_FREQ_OVERRIDE_50MHZ,  // Force frequency to 50MHz (not currently supported)
-+    TOUCH_FREQ_OVERRIDE_MAX     // Invalid value
-+} touch_freq_override_t;
-+C_ASSERT(sizeof(touch_freq_override_t) == 4);
-+
-+typedef enum touch_spi_io_mode_override
-+{
-+    TOUCH_SPI_IO_MODE_OVERRIDE_NONE,    // Do not apply any override
-+    TOUCH_SPI_IO_MODE_OVERRIDE_SINGLE,  // Force Single I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_DUAL,    // Force Dual I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_QUAD,    // Force Quad I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_MAX      // Invalid value
-+} touch_spi_io_mode_override_t;
-+C_ASSERT(sizeof(touch_spi_io_mode_override_t) == 4);
-+
-+// Debug Policy bits used by TOUCH_POLICY_DATA.DebugOverride
-+#define TOUCH_DBG_POLICY_OVERRIDE_STARTUP_TIMER_DIS BIT0    // Disable sensor startup timer
-+#define TOUCH_DBG_POLICY_OVERRIDE_SYNC_BYTE_DIS     BIT1    // Disable Sync Byte check
-+#define TOUCH_DBG_POLICY_OVERRIDE_ERR_RESET_DIS     BIT2    // Disable error resets
-+
-+typedef struct touch_policy_data
-+{
-+    u32                      reserved0;          // For future expansion.
-+    u32                      doze_timer     :16;  // Value in seconds, after which ME will put the sensor into Doze power state if no activity occurs. Set
-+                                                    // to 0 to disable Doze mode (not recommended). Value will be set to TOUCH_DEFAULT_DOZE_TIMER_SECONDS by
-+                                                    // default.
-+    touch_freq_override_t         freq_override  :3;   // Override frequency requested by sensor
-+    touch_spi_io_mode_override_t  spi_io_override :3;   // Override IO mode requested by sensor
-+    u32                      reserved1     :10;  // For future expansion
-+    u32                      reserved2;          // For future expansion
-+    u32                      debug_override;      // Normally all bits will be zero. Bits will be defined as needed for enabling special debug features
-+} touch_policy_data_t;
-+C_ASSERT(sizeof(touch_policy_data_t) == 16);
-+
-+typedef struct touch_sensor_set_policies_cmd_data
-+{
-+    touch_policy_data_t           policy_data;         // Contains the desired policy to be set
-+} touch_sensor_set_policies_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_policies_cmd_data_t) == 16);
-+
-+
-+typedef enum touch_sensor_reset_type
-+{
-+    TOUCH_SENSOR_RESET_TYPE_HARD,   // Hardware Reset using dedicated GPIO pin
-+    TOUCH_SENSOR_RESET_TYPE_SOFT,   // Software Reset using command written over SPI interface
-+    TOUCH_SENSOR_RESET_TYPE_MAX     // Invalid value
-+} touch_sensor_reset_type_t;
-+C_ASSERT(sizeof(touch_sensor_reset_type_t) == 4);
-+
-+typedef struct touch_sensor_reset_cmd_data
-+{
-+    touch_sensor_reset_type_t reset_type;  // Indicate desired reset type
-+    u32                  reserved;   // For future expansion
-+} touch_sensor_reset_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_reset_cmd_data_t) == 8);
-+
-+
-+//
-+// Host to ME message
-+//
-+typedef struct touch_sensor_msg_h2m
-+{
-+    u32  command_code;
-+    union
-+    {
-+        touch_sensor_set_mode_cmd_data_t        set_mode_cmd_data;
-+        touch_sensor_set_mem_window_cmd_data_t  set_window_cmd_data;
-+        touch_sensor_quiesce_io_cmd_data_t      quiesce_io_cmd_data;
-+        touch_sensor_feedback_ready_cmd_data_t  feedback_ready_cmd_data;
-+        touch_sensor_set_policies_cmd_data_t    set_policies_cmd_data;
-+        touch_sensor_reset_cmd_data_t           reset_cmd_data;
-+    } h2m_data;
-+} touch_sensor_msg_h2m_t;
-+C_ASSERT(sizeof(touch_sensor_msg_h2m_t) == 324);
-+
-+
-+//*******************************************************************
-+//
-+// Defines for message structures used for ME to Host communication
-+//
-+//*******************************************************************
-+
-+// I/O mode values used by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+typedef enum touch_spi_io_mode
-+{
-+    TOUCH_SPI_IO_MODE_SINGLE = 0,   // Sensor set for Single I/O SPI
-+    TOUCH_SPI_IO_MODE_DUAL,         // Sensor set for Dual I/O SPI
-+    TOUCH_SPI_IO_MODE_QUAD,         // Sensor set for Quad I/O SPI
-+    TOUCH_SPI_IO_MODE_MAX           // Invalid value
-+} touch_spi_io_mode_t;
-+C_ASSERT(sizeof(touch_spi_io_mode_t) == 4);
-+
-+//
-+// TOUCH_SENSOR_GET_DEVICE_INFO_RSP code is sent in response to TOUCH_SENSOR_GET_DEVICE_INFO_CMD. This code will be followed
-+// by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:               Command was processed successfully and sensor details are reported.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:        Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_NO_SENSOR_FOUND:       Sensor has not yet been detected. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_DEVICE_CAPS:   Indicates sensor does not support minimum required Frequency or I/O Mode. ME firmware will choose best possible option for the errant
-+//                                          field. Caller should attempt to continue.
-+//      TOUCH_STATUS_COMPAT_CHECK_FAIL:     Indicates TouchIC/ME compatibility mismatch. Caller should attempt to continue.
-+//
-+typedef struct touch_sensor_get_device_info_rsp_data
-+{
-+    u16				vendor_id;               // Touch Sensor vendor ID
-+    u16              device_id;               // Touch Sensor device ID
-+    u32              hw_rev;                  // Touch Sensor Hardware Revision
-+    u32              fw_rev;                  // Touch Sensor Firmware Revision
-+    u32              frame_size;              // Max size of one frame returned by Touch IC in bytes. This data will be TOUCH_RAW_DATA_HDR followed
-+                                                // by a payload. The payload can be raw data or a HID structure depending on mode.
-+    u32              feedback_size;           // Max size of one Feedback structure in bytes
-+    touch_sensor_mode_t	sensor_mode;             // Current operating mode of the sensor
-+    u32              max_touch_points  :8;     // Maximum number of simultaneous touch points that can be reported by sensor
-+    touch_freq_t          spi_frequency    :8;     // SPI bus Frequency supported by sensor and ME firmware
-+    touch_spi_io_mode_t   spi_io_mode       :8;     // SPI bus I/O Mode supported by sensor and ME firmware
-+    u32              reserved0       :8;     // For future expansion
-+    u8               sensor_minor_eds_rev;      // Minor version number of EDS spec supported by sensor (from Compat Rev ID Reg)
-+    u8               sensor_major_eds_rev;      // Major version number of EDS spec supported by sensor (from Compat Rev ID Reg)
-+    u8               me_minor_eds_rev;          // Minor version number of EDS spec supported by ME
-+    u8               me_major_eds_rev;          // Major version number of EDS spec supported by ME
-+    u8               sensor_eds_intf_rev;       // EDS Interface Revision Number supported by sensor (from Compat Rev ID Reg)
-+    u8               me_eds_intf_rev;           // EDS Interface Revision Number supported by ME
-+    u8               kernel_compat_ver;        // EU Kernel Compatibility Version  (from Compat Rev ID Reg)
-+    u8               reserved1;              // For future expansion
-+    u32              reserved2[2];           // For future expansion
-+} touch_sensor_get_device_info_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_get_device_info_rsp_data_t) == 44);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_MODE_RSP code is sent in response to TOUCH_SENSOR_SET_MODE_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_MODE_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and mode was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//
-+typedef struct touch_sensor_set_mode_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_mode_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mode_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_SET_MEM_WINDOW_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_MEM_WINDOW_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and memory window was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//      TOUCH_STATUS_ACCESS_DENIED:     Unable to map host address ranges for DMA.
-+//      TOUCH_STATUS_OUT_OF_MEMORY:     Unable to allocate enough space for needed buffers.
-+//
-+typedef struct touch_sensor_set_mem_window_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_mem_window_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mem_window_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_QUIESCE_IO_RSP code is sent in response to TOUCH_SENSOR_QUIESCE_IO_CMD. This code will be followed
-+// by TOUCH_SENSOR_QUIESCE_IO_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and touch flow has stopped.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//      TOUCH_STATIS_TIMEOUT:                   Indicates ME timed out waiting for Quiesce I/O flow to complete.
-+//
-+typedef struct touch_sensor_quiesce_io_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_quiesce_io_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_quiesce_io_rsp_data_t) == 12);
-+
-+
-+// Reset Reason values used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA
-+typedef enum touch_reset_reason
-+{
-+    TOUCH_RESET_REASON_UNKNOWN = 0,         // Reason for sensor reset is not known
-+    TOUCH_RESET_REASON_FEEDBACK_REQUEST,    // Reset was requested as part of TOUCH_SENSOR_FEEDBACK_READY_CMD
-+    TOUCH_RESET_REASON_HECI_REQUEST,        // Reset was requested via TOUCH_SENSOR_RESET_CMD
-+    TOUCH_RESET_REASON_MAX
-+} touch_reset_reason_t;
-+C_ASSERT(sizeof(touch_reset_reason_t) == 4);
-+
-+//
-+// TOUCH_SENSOR_HID_READY_FOR_DATA_RSP code is sent in response to TOUCH_SENSOR_HID_READY_FOR_DATA_CMD. This code will be followed
-+// by TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and HID data was sent by DMA. This will only be sent in HID mode.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_REQUEST_OUTSTANDING:       Previous request is still outstanding, ME FW cannot handle another request for the same command.
-+//      TOUCH_STATUS_NOT_READY:                 Indicates memory window has not yet been set by BIOS/HID.
-+//      TOUCH_STATUS_SENSOR_DISABLED:           Indicates that ME to HID communication has been stopped either by TOUCH_SENSOR_QUIESCE_IO_CMD or TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD.
-+//      TOUCH_STATUS_SENSOR_UNEXPECTED_RESET:   Sensor signaled a Reset Interrupt. ME did not expect this and has no info about why this occurred.
-+//      TOUCH_STATUS_SENSOR_EXPECTED_RESET:     Sensor signaled a Reset Interrupt. ME either directly requested this reset, or it was expected as part of a defined flow in the EDS.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//      TOUCH_STATUS_TIMEOUT:                   Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//
-+typedef struct touch_sensor_hid_ready_for_data_rsp_data
-+{
-+    u32          data_size;               // Size of the data the ME DMA'd into a RawDataBuffer. Valid only when Status == TOUCH_STATUS_SUCCESS
-+    u8           touch_data_buffer_index;   // Index to indicate which RawDataBuffer was used. Valid only when Status == TOUCH_STATUS_SUCCESS
-+    u8           reset_reason;            // If Status is TOUCH_STATUS_SENSOR_EXPECTED_RESET, ME will provide the cause. See TOUCH_RESET_REASON.
-+    u8           reserved1[2];           // For future expansion
-+    u32          reserved2[5];           // For future expansion
-+} touch_sensor_hid_ready_for_data_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_hid_ready_for_data_rsp_data_t) == 28);
-+
-+
-+//
-+// TOUCH_SENSOR_FEEDBACK_READY_RSP code is sent in response to TOUCH_SENSOR_FEEDBACK_READY_CMD. This code will be followed
-+// by TOUCH_SENSOR_FEEDBACK_READY_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and any feedback or commands were sent to sensor.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//      TOUCH_STATUS_COMPAT_CHECK_FAIL  Indicates ProtocolVer does not match ME supported version. (non-fatal error)
-+//      TOUCH_STATUS_INTERNAL_ERROR:    Unexpected error occurred. This should not normally be seen.
-+//      TOUCH_STATUS_OUT_OF_MEMORY:     Insufficient space to store Calibration Data
-+//
-+typedef struct touch_sensor_feedback_ready_rsp_data
-+{
-+    u8           feedback_index;  // Index value from 0 to TOUCH_SENSOR_MAX_DATA_BUFFERS used to indicate which Feedback Buffer to use
-+    u8           reserved1[3];   // For future expansion
-+    u32          reserved2[6];   // For future expansion
-+} touch_sensor_feedback_ready_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_feedback_ready_rsp_data_t) == 28);
-+
-+
-+//
-+// TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD. This code will be followed
-+// by TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and memory window was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:            Input parameters are out of range.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//
-+typedef struct touch_sensor_clear_mem_window_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_clear_mem_window_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_clear_mem_window_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_NOTIFY_DEV_READY_RSP code is sent in response to TOUCH_SENSOR_NOTIFY_DEV_READY_CMD. This code will be followed
-+// by TOUCH_SENSOR_NOTIFY_DEV_READY_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:               Command was processed successfully and sensor has been detected by ME FW.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:        Command sent did not match expected size.
-+//      TOUCH_STATUS_REQUEST_OUTSTANDING:   Previous request is still outstanding, ME FW cannot handle another request for the same command.
-+//      TOUCH_STATUS_TIMEOUT:               Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//      TOUCH_STATUS_SENSOR_FAIL_FATAL:     Sensor indicated a fatal error, further operation is not possible. Error details can be found in ErrReg.
-+//      TOUCH_STATUS_SENSOR_FAIL_NONFATAL:  Sensor indicated a non-fatal error. Error should be logged by caller and init flow can continue. Error details can be found in ErrReg.
-+//
-+typedef struct touch_sensor_notify_dev_ready_rsp_data
-+{
-+    touch_err_reg_t   err_reg;         // Value of sensor Error Register, field is only valid for Status == TOUCH_STATUS_SENSOR_FAIL_FATAL or TOUCH_STATUS_SENSOR_FAIL_NONFATAL
-+    u32          reserved[2];    // For future expansion
-+} touch_sensor_notify_dev_ready_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_notify_dev_ready_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_SET_POLICIES_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_POLICIES_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//
-+typedef struct touch_sensor_set_policies_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_policies_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_policies_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_GET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_GET_POLICIES_CMD. This code will be followed
-+// by TOUCH_SENSOR_GET_POLICIES_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//
-+typedef struct touch_sensor_get_policies_rsp_data
-+{
-+    touch_policy_data_t   policy_data;         // Contains the current policy
-+} touch_sensor_get_policies_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_get_policies_rsp_data_t) == 16);
-+
-+
-+//
-+// TOUCH_SENSOR_RESET_RSP code is sent in response to TOUCH_SENSOR_RESET_CMD. This code will be followed
-+// by TOUCH_SENSOR_RESET_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and sensor reset was completed.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:            Input parameters are out of range.
-+//      TOUCH_STATUS_TIMEOUT:                   Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//      TOUCH_STATUS_RESET_FAILED:              Sensor generated an invalid or unexpected interrupt.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//
-+typedef struct touch_sensor_reset_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_reset_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_reset_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_READ_ALL_REGS_RSP code is sent in response to TOUCH_SENSOR_READ_ALL_REGS_CMD. This code will be followed
-+// by TOUCH_SENSOR_READ_ALL_REGS_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//
-+typedef struct touch_sensor_read_all_regs_rsp_data
-+{
-+    touch_reg_block_t sensor_regs; // Returns first 64 bytes of register space used for normal touch operation. Does not include test mode register.
-+    u32          reserved[4];
-+} touch_sensor_read_all_regs_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_read_all_regs_rsp_data_t) == 80);
-+
-+//
-+// ME to Host Message
-+//
-+typedef struct touch_sensor_msg_m2h
-+{
-+    u32  command_code;
-+    touch_status_t	status;
-+    union
-+    {
-+        touch_sensor_get_device_info_rsp_data_t     device_info_rsp_data;
-+        touch_sensor_set_mode_rsp_data_t            set_mode_rsp_data;
-+        touch_sensor_set_mem_window_rsp_data_t      set_mem_window_rsp_data;
-+        touch_sensor_quiesce_io_rsp_data_t          quiesce_io_rsp_data;
-+        touch_sensor_hid_ready_for_data_rsp_data_t  hid_ready_for_data_rsp_data;
-+        touch_sensor_feedback_ready_rsp_data_t      feedback_ready_rsp_data;
-+        touch_sensor_clear_mem_window_rsp_data_t    clear_mem_window_rsp_data;
-+        touch_sensor_notify_dev_ready_rsp_data_t    notify_dev_ready_rsp_data;
-+        touch_sensor_set_policies_rsp_data_t        set_policies_rsp_data;
-+        touch_sensor_get_policies_rsp_data_t        get_policies_rsp_data;
-+        touch_sensor_reset_rsp_data_t               reset_rsp_data;
-+	touch_sensor_read_all_regs_rsp_data_t       read_all_regs_rsp_data;
-+    } m2h_data;
-+} touch_sensor_msg_m2h_t;
-+C_ASSERT(sizeof(touch_sensor_msg_m2h_t) == 88);
-+
-+
-+#define TOUCH_MSG_SIZE_MAX_BYTES    (MAX(sizeof(touch_sensor_msg_m2h_t), sizeof(touch_sensor_msg_h2m_t)))
-+
-+#pragma pack()
-+
-+#endif // _IPTS_MEI_MSGS_H_
-diff --git a/drivers/misc/ipts/ipts-mei.c b/drivers/misc/ipts/ipts-mei.c
-new file mode 100644
-index 000000000000..39667e75dafd
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-mei.c
-@@ -0,0 +1,282 @@
-+/*
-+ * MEI client driver for Intel Precise Touch and Stylus
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/mei_cl_bus.h>
-+#include <linux/module.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/hid.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/kthread.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-hid.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-mei-msgs.h"
-+#include "ipts-binary-spec.h"
-+#include "ipts-state.h"
-+
-+#define IPTS_DRIVER_NAME	"ipts"
-+#define IPTS_MEI_UUID		UUID_LE(0x3e8d0870, 0x271a, 0x4208, \
-+				0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04)
-+
-+static struct mei_cl_device_id ipts_mei_cl_tbl[] = {
-+	{ "", IPTS_MEI_UUID, MEI_CL_VERSION_ANY},
-+	{}
-+};
-+
-+static ssize_t sensor_mode_show(struct device *dev,
-+				struct device_attribute *attr, char *buf)
-+{
-+	ipts_info_t *ipts;
-+	ipts = dev_get_drvdata(dev);
-+
-+	return sprintf(buf, "%d\n", ipts->sensor_mode);
-+}
-+
-+//TODO: Verify the function implementation
-+static ssize_t sensor_mode_store(struct device *dev,
-+				struct device_attribute *attr, const char *buf,
-+				size_t count)
-+{
-+	int ret;
-+	long val;
-+	ipts_info_t *ipts;
-+
-+	ipts = dev_get_drvdata(dev);
-+	ret = kstrtol(buf, 10, &val);
-+	if (ret)
-+	   return ret;
-+
-+	ipts_dbg(ipts, "try sensor mode = %ld\n", val);
-+
-+	switch (val) {
-+		case TOUCH_SENSOR_MODE_HID:
-+			break;
-+		case TOUCH_SENSOR_MODE_RAW_DATA:
-+			break;
-+		default:
-+			ipts_err(ipts, "sensor mode %ld is not supported\n", val);
-+	}
-+
-+	return count;
-+}
-+
-+static ssize_t device_info_show(struct device *dev,
-+				struct device_attribute *attr, char *buf)
-+{
-+	ipts_info_t *ipts;
-+
-+	ipts = dev_get_drvdata(dev);
-+	return sprintf(buf, "vendor id = 0x%04hX\n"
-+				"device id = 0x%04hX\n"
-+				"HW rev = 0x%08X\n"
-+				"firmware rev = 0x%08X\n",
-+			ipts->device_info.vendor_id, ipts->device_info.device_id,
-+			ipts->device_info.hw_rev, ipts->device_info.fw_rev);
-+}
-+
-+static DEVICE_ATTR_RW(sensor_mode);
-+static DEVICE_ATTR_RO(device_info);
-+
-+static struct attribute *ipts_attrs[] = {
-+	&dev_attr_sensor_mode.attr,
-+	&dev_attr_device_info.attr,
-+	NULL
-+};
-+
-+static const struct attribute_group ipts_grp = {
-+	.attrs = ipts_attrs,
-+};
-+
-+MODULE_DEVICE_TABLE(mei, ipts_mei_cl_tbl);
-+
-+static void raw_data_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, raw_data_work);
-+
-+	ipts_handle_processed_data(ipts);
-+}
-+
-+static void gfx_status_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, gfx_status_work);
-+	ipts_state_t state;
-+	int status = ipts->gfx_status;
-+
-+	ipts_dbg(ipts, "notify gfx status : %d\n", status);
-+
-+	state = ipts_get_state(ipts);
-+
-+	if (state == IPTS_STA_RAW_DATA_STARTED || state == IPTS_STA_HID_STARTED) {
-+		if (status == IPTS_NOTIFY_STA_BACKLIGHT_ON &&
-+					ipts->display_status == false) {
-+			ipts_send_sensor_clear_mem_window_cmd(ipts);
-+			ipts->display_status = true;
-+		} else if (status == IPTS_NOTIFY_STA_BACKLIGHT_OFF &&
-+					ipts->display_status == true) {
-+			ipts_send_sensor_quiesce_io_cmd(ipts);
-+			ipts->display_status = false;
-+		}
-+	}
-+}
-+
-+/* event loop */
-+static int ipts_mei_cl_event_thread(void *data)
-+{
-+	ipts_info_t *ipts = (ipts_info_t *)data;
-+	struct mei_cl_device *cldev = ipts->cldev;
-+	ssize_t msg_len;
-+	touch_sensor_msg_m2h_t m2h_msg;
-+
-+	while (!kthread_should_stop()) {
-+		msg_len = mei_cldev_recv(cldev, (u8*)&m2h_msg, sizeof(m2h_msg));
-+		if (msg_len <= 0) {
-+			ipts_err(ipts, "error in reading m2h msg\n");
-+			continue;
-+		}
-+
-+		if (ipts_handle_resp(ipts, &m2h_msg, msg_len) != 0) {
-+			ipts_err(ipts, "error in handling resp msg\n");
-+		}
-+	}
-+
-+	ipts_dbg(ipts, "!! end event loop !!\n");
-+
-+	return 0;
-+}
-+
-+static void init_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, init_work);
-+
-+	ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA;
-+	ipts->display_status = true;
-+
-+	ipts_start(ipts);
-+}
-+
-+static int ipts_mei_cl_probe(struct mei_cl_device *cldev,
-+			const struct mei_cl_device_id *id)
-+{
-+	int ret = 0;
-+	ipts_info_t *ipts = NULL;
-+
-+	pr_info("probing Intel Precise Touch & Stylus\n");
-+
-+	// setup the DMA BIT mask, the system will choose the best possible
-+	if (dma_coerce_mask_and_coherent(&cldev->dev, DMA_BIT_MASK(64)) == 0) {
-+		pr_info("IPTS using DMA_BIT_MASK(64)\n");
-+	} else if (dma_coerce_mask_and_coherent(&cldev->dev,
-+						DMA_BIT_MASK(32)) == 0) {
-+		pr_info("IPTS using  DMA_BIT_MASK(32)\n");
-+	} else {
-+		pr_err("IPTS: No suitable DMA available\n");
-+		return -EFAULT;
-+	}
-+
-+	ret = mei_cldev_enable(cldev);
-+	if (ret < 0) {
-+		pr_err("cannot enable IPTS\n");
-+		return ret;
-+	}
-+
-+	ipts = devm_kzalloc(&cldev->dev, sizeof(ipts_info_t), GFP_KERNEL);
-+	if (ipts == NULL) {
-+		ret = -ENOMEM;
-+		goto disable_mei;
-+	}
-+	ipts->cldev = cldev;
-+	mei_cldev_set_drvdata(cldev, ipts);
-+
-+	ipts->event_loop = kthread_run(ipts_mei_cl_event_thread, (void*)ipts,
-+							"ipts_event_thread");
-+
-+	if(ipts_dbgfs_register(ipts, "ipts"))
-+		pr_debug("cannot register debugfs for IPTS\n");
-+
-+	INIT_WORK(&ipts->init_work, init_work_func);
-+	INIT_WORK(&ipts->raw_data_work, raw_data_work_func);
-+	INIT_WORK(&ipts->gfx_status_work, gfx_status_work_func);
-+
-+	ret = sysfs_create_group(&cldev->dev.kobj, &ipts_grp);
-+	if (ret != 0) {
-+		pr_debug("cannot create sysfs for IPTS\n");
-+	}
-+
-+	schedule_work(&ipts->init_work);
-+
-+	return 0;
-+
-+disable_mei :
-+	mei_cldev_disable(cldev);
-+	
-+	return ret;
-+}
-+
-+static int ipts_mei_cl_remove(struct mei_cl_device *cldev)
-+{
-+	ipts_info_t *ipts = mei_cldev_get_drvdata(cldev);
-+
-+	ipts_stop(ipts);
-+
-+	sysfs_remove_group(&cldev->dev.kobj, &ipts_grp);
-+	ipts_hid_release(ipts);
-+	ipts_dbgfs_deregister(ipts);
-+	mei_cldev_disable(cldev);
-+
-+	kthread_stop(ipts->event_loop);
-+
-+	pr_info("IPTS removed\n");
-+
-+	return 0;
-+}
-+
-+static struct mei_cl_driver ipts_mei_cl_driver = {
-+	.id_table = ipts_mei_cl_tbl,
-+	.name = IPTS_DRIVER_NAME,
-+	.probe = ipts_mei_cl_probe,
-+	.remove = ipts_mei_cl_remove,
-+};
-+
-+static int ipts_mei_cl_init(void)
-+{
-+	int ret;
-+
-+	pr_info("IPTS %s() is called\n", __func__);
-+
-+	ret = mei_cldev_driver_register(&ipts_mei_cl_driver);
-+	if (ret) {
-+		pr_err("unable to register IPTS mei client driver\n");
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static void __exit ipts_mei_cl_exit(void)
-+{
-+	pr_info("IPTS %s() is called\n", __func__);
-+
-+	mei_cldev_driver_unregister(&ipts_mei_cl_driver);
-+}
-+
-+module_init(ipts_mei_cl_init);
-+module_exit(ipts_mei_cl_exit);
-+
-+MODULE_DESCRIPTION
-+	("Intel(R) Management Engine Interface Client Driver for "\
-+	"Intel Precision Touch and Sylus");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/misc/ipts/ipts-msg-handler.c b/drivers/misc/ipts/ipts-msg-handler.c
-new file mode 100644
-index 000000000000..1396ecc7197f
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-msg-handler.c
-@@ -0,0 +1,431 @@
-+#include <linux/mei_cl_bus.h>
-+
-+#include "ipts.h"
-+#include "ipts-hid.h"
-+#include "ipts-resource.h"
-+#include "ipts-mei-msgs.h"
-+
-+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size)
-+{
-+	int ret = 0;
-+	touch_sensor_msg_h2m_t h2m_msg;
-+	int len = 0;
-+
-+	memset(&h2m_msg, 0, sizeof(h2m_msg));
-+
-+	h2m_msg.command_code = cmd;
-+	len = sizeof(h2m_msg.command_code) + data_size;
-+	if (data != NULL && data_size != 0)
-+		memcpy(&h2m_msg.h2m_data, data, data_size); /* copy payload */
-+
-+	ret = mei_cldev_send(ipts->cldev, (u8*)&h2m_msg, len);
-+	if (ret < 0) {
-+		ipts_err(ipts, "mei_cldev_send() error 0x%X:%d\n",
-+							cmd, ret);
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id)
-+{
-+	int ret;
-+	int cmd_len;
-+	touch_sensor_feedback_ready_cmd_data_t fb_ready_cmd;
-+
-+	cmd_len = sizeof(touch_sensor_feedback_ready_cmd_data_t);
-+	memset(&fb_ready_cmd, 0, cmd_len);
-+
-+	fb_ready_cmd.feedback_index = buffer_idx;
-+	fb_ready_cmd.transaction_id = transaction_id;
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_FEEDBACK_READY_CMD,
-+				&fb_ready_cmd, cmd_len);
-+
-+	return ret;
-+}
-+
-+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts)
-+{
-+	int ret;
-+	int cmd_len;
-+	touch_sensor_quiesce_io_cmd_data_t quiesce_io_cmd;
-+
-+	cmd_len = sizeof(touch_sensor_quiesce_io_cmd_data_t);
-+	memset(&quiesce_io_cmd, 0, cmd_len);
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_QUIESCE_IO_CMD,
-+				&quiesce_io_cmd, cmd_len);
-+
-+	return ret;
-+}
-+
-+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts)
-+{
-+	return ipts_handle_cmd(ipts, TOUCH_SENSOR_HID_READY_FOR_DATA_CMD, NULL, 0);
-+}
-+
-+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts)
-+{
-+	return ipts_handle_cmd(ipts, TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD, NULL, 0);
-+}
-+
-+static int check_validity(touch_sensor_msg_m2h_t *m2h_msg, u32 msg_len)
-+{
-+	int ret = 0;
-+	int valid_msg_len = sizeof(m2h_msg->command_code);
-+	u32 cmd_code = m2h_msg->command_code;
-+
-+	switch (cmd_code) {
-+		case TOUCH_SENSOR_SET_MODE_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_mode_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_SET_MEM_WINDOW_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_mem_window_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_QUIESCE_IO_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_quiesce_io_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_hid_ready_for_data_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_FEEDBACK_READY_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_feedback_ready_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_clear_mem_window_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_notify_dev_ready_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_SET_POLICIES_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_policies_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_GET_POLICIES_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_get_policies_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_RESET_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_reset_rsp_data_t);
-+			break;
-+	}
-+
-+	if (valid_msg_len != msg_len) {
-+		return -EINVAL;
-+	}
-+
-+	return ret;
-+}
-+
-+int ipts_start(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	/* TODO : check if we need to do SET_POLICIES_CMD
-+	we need to do this when protocol version doesn't match with reported one
-+	how we keep vendor specific data is the first thing to solve */
-+
-+	ipts_set_state(ipts, IPTS_STA_INIT);
-+	ipts->num_of_parallel_data_buffers = TOUCH_SENSOR_MAX_DATA_BUFFERS;
-+
-+	ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA; /* start with RAW_DATA */
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_NOTIFY_DEV_READY_CMD, NULL, 0);
-+
-+	return ret;
-+}
-+
-+void ipts_stop(ipts_info_t *ipts)
-+{
-+	ipts_state_t old_state;
-+
-+	old_state = ipts_get_state(ipts);
-+	ipts_set_state(ipts, IPTS_STA_STOPPING);
-+
-+	if (old_state < IPTS_STA_RESOURCE_READY)
-+		return;
-+
-+	if (old_state == IPTS_STA_RAW_DATA_STARTED ||
-+					old_state == IPTS_STA_HID_STARTED) {
-+        	ipts_free_default_resource(ipts);
-+		ipts_free_raw_data_resource(ipts);
-+
-+		return;
-+	}
-+}
-+
-+int ipts_restart(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ipts_dbg(ipts, "ipts restart\n");
-+
-+	ipts_stop(ipts);
-+
-+	ipts->retry++;
-+	if (ipts->retry == IPTS_MAX_RETRY && 
-+			ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) {
-+		/* try with HID mode */
-+		ipts->sensor_mode = TOUCH_SENSOR_MODE_HID;
-+	} else if (ipts->retry > IPTS_MAX_RETRY) {
-+		return -EPERM;
-+	}
-+
-+	ipts_send_sensor_quiesce_io_cmd(ipts);
-+	ipts->restart = true;
-+
-+	return ret;
-+}
-+
-+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode)
-+{
-+	int ret = 0;
-+
-+        ipts->new_sensor_mode = new_sensor_mode;
-+	ipts->switch_sensor_mode = true;
-+        ret = ipts_send_sensor_quiesce_io_cmd(ipts);
-+
-+	return ret;
-+}
-+
-+#define rsp_failed(ipts, cmd, status) ipts_err(ipts, \
-+				"0x%08x failed status = %d\n", cmd, status);
-+
-+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg,
-+								u32 msg_len)
-+{
-+	int ret = 0;
-+	int rsp_status = 0;
-+	int cmd_status = 0;
-+	int cmd_len = 0;
-+	u32 cmd;
-+
-+	if (!check_validity(m2h_msg, msg_len)) {
-+		ipts_err(ipts, "wrong rsp\n");
-+		return -EINVAL;
-+	}
-+
-+	rsp_status = m2h_msg->status;
-+	cmd = m2h_msg->command_code;
-+
-+	switch (cmd) {
-+		case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_SENSOR_FAIL_NONFATAL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_status = ipts_handle_cmd(ipts,
-+					TOUCH_SENSOR_GET_DEVICE_INFO_CMD,
-+					NULL, 0);
-+			break;
-+		case TOUCH_SENSOR_GET_DEVICE_INFO_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			memcpy(&ipts->device_info,
-+				&m2h_msg->m2h_data.device_info_rsp_data,
-+				sizeof(touch_sensor_get_device_info_rsp_data_t));
-+
-+			/*
-+			    TODO : support raw_request during HID init.
-+			    Although HID init happens here, technically most of
-+			    reports (for both direction) can be issued only
-+			    after SET_MEM_WINDOWS_CMD since they may require
-+			    ME or touch IC. If ipts vendor requires raw_request
-+			    during HID init, we need to consider to move HID init.
-+			*/
-+			if (ipts->hid_desc_ready == false) {
-+				ret = ipts_hid_init(ipts);
-+				if (ret)
-+					break;
-+			}
-+
-+			cmd_status = ipts_send_sensor_clear_mem_window_cmd(ipts);
-+
-+			break;
-+		case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP:
-+		{
-+			touch_sensor_set_mode_cmd_data_t sensor_mode_cmd;
-+
-+			if (rsp_status != 0 &&
-+					rsp_status != TOUCH_STATUS_TIMEOUT) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			/* allocate default resource : common & hid only */
-+			if (!ipts_is_default_resource_ready(ipts)) {
-+				ret = ipts_allocate_default_resource(ipts);
-+				if (ret)
-+					break;
-+			}
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA &&
-+					!ipts_is_raw_data_resource_ready(ipts)) {
-+				ret = ipts_allocate_raw_data_resource(ipts);
-+				if (ret) {
-+					ipts_free_default_resource(ipts);
-+					break;
-+				}
-+			}
-+
-+			ipts_set_state(ipts, IPTS_STA_RESOURCE_READY);
-+
-+			cmd_len = sizeof(touch_sensor_set_mode_cmd_data_t);
-+			memset(&sensor_mode_cmd, 0, cmd_len);
-+			sensor_mode_cmd.sensor_mode = ipts->sensor_mode;
-+			cmd_status = ipts_handle_cmd(ipts,
-+				TOUCH_SENSOR_SET_MODE_CMD,
-+				&sensor_mode_cmd, cmd_len);
-+			break;
-+		}
-+		case TOUCH_SENSOR_SET_MODE_RSP:
-+		{
-+			touch_sensor_set_mem_window_cmd_data_t smw_cmd;
-+
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_len = sizeof(touch_sensor_set_mem_window_cmd_data_t);
-+			memset(&smw_cmd, 0, cmd_len);
-+			ipts_get_set_mem_window_cmd_data(ipts, &smw_cmd);
-+			cmd_status = ipts_handle_cmd(ipts,
-+				TOUCH_SENSOR_SET_MEM_WINDOW_CMD,
-+				&smw_cmd, cmd_len);
-+			break;
-+		}
-+		case TOUCH_SENSOR_SET_MEM_WINDOW_RSP:
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_status = ipts_send_sensor_hid_ready_for_data_cmd(ipts);
-+			if (cmd_status)
-+				break;
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) {
-+				ipts_set_state(ipts, IPTS_STA_HID_STARTED);
-+			} else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) {
-+				ipts_set_state(ipts, IPTS_STA_RAW_DATA_STARTED);
-+			}
-+
-+			ipts_err(ipts, "touch enabled %d\n", ipts_get_state(ipts));
-+
-+			break;
-+		case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP:
-+		{
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_data;
-+			ipts_state_t state;
-+
-+			if (rsp_status != 0 &&
-+				  rsp_status != TOUCH_STATUS_SENSOR_DISABLED) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			state = ipts_get_state(ipts);
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID &&
-+						state == IPTS_STA_HID_STARTED) {
-+
-+				hid_data = &m2h_msg->m2h_data.hid_ready_for_data_rsp_data;
-+
-+				/* HID mode only uses buffer 0 */
-+				if (hid_data->touch_data_buffer_index != 0)
-+					break;
-+
-+				/* handle hid data */
-+				ipts_handle_hid_data(ipts, hid_data);
-+			}
-+
-+			break;
-+		}
-+		case TOUCH_SENSOR_FEEDBACK_READY_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			if (m2h_msg->m2h_data.feedback_ready_rsp_data.
-+					feedback_index == TOUCH_HID_2_ME_BUFFER_ID)
-+				break;
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) {
-+				cmd_status = ipts_handle_cmd(ipts,
-+					TOUCH_SENSOR_HID_READY_FOR_DATA_CMD,
-+					NULL, 0);
-+			}
-+
-+			/* reset retry since we are getting touch data */
-+			ipts->retry = 0;
-+
-+			break;
-+		case TOUCH_SENSOR_QUIESCE_IO_RSP:
-+		{
-+			ipts_state_t state;
-+
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			state = ipts_get_state(ipts);
-+			if (state == IPTS_STA_STOPPING && ipts->restart) {
-+				ipts_dbg(ipts, "restart\n");
-+			        ipts_start(ipts);
-+				ipts->restart = 0;
-+				break;
-+			}
-+
-+			/* support sysfs debug node for switch sensor mode */
-+			if (ipts->switch_sensor_mode) {
-+				ipts_set_state(ipts, IPTS_STA_INIT);
-+				ipts->sensor_mode = ipts->new_sensor_mode;
-+				ipts->switch_sensor_mode = false;
-+
-+				ipts_send_sensor_clear_mem_window_cmd(ipts);
-+			}
-+
-+			break;
-+		}
-+	}
-+
-+	/* handle error in rsp_status */
-+	if (rsp_status != 0) {
-+		switch (rsp_status) {
-+			case TOUCH_STATUS_SENSOR_EXPECTED_RESET:
-+			case TOUCH_STATUS_SENSOR_UNEXPECTED_RESET:
-+				ipts_dbg(ipts, "sensor reset %d\n", rsp_status);
-+				ipts_restart(ipts);
-+				break;
-+			default:
-+				ipts_dbg(ipts, "cmd : 0x%08x, status %d\n",
-+								cmd,
-+								rsp_status);
-+				break;
-+		}
-+	}
-+
-+	if (cmd_status) {
-+		ipts_restart(ipts);
-+	}
-+
-+	return ret;
-+}
-diff --git a/drivers/misc/ipts/ipts-msg-handler.h b/drivers/misc/ipts/ipts-msg-handler.h
-new file mode 100644
-index 000000000000..b8e27d30c63e
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-msg-handler.h
-@@ -0,0 +1,32 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus ME message handler
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_MSG_HANDLER_H
-+#define _IPTS_MSG_HANDLER_H
-+
-+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size);
-+int ipts_start(ipts_info_t *ipts);
-+void ipts_stop(ipts_info_t *ipts);
-+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode);
-+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg,
-+                        					u32 msg_len);
-+int ipts_handle_processed_data(ipts_info_t *ipts);
-+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id);
-+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts);
-+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts);
-+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts);
-+
-+#endif /* _IPTS_MSG_HANDLER_H */
-diff --git a/drivers/misc/ipts/ipts-resource.c b/drivers/misc/ipts/ipts-resource.c
-new file mode 100644
-index 000000000000..47607ef7c461
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-resource.c
-@@ -0,0 +1,277 @@
-+#include <linux/dma-mapping.h>
-+
-+#include "ipts.h"
-+#include "ipts-mei-msgs.h"
-+#include "ipts-kernel.h"
-+
-+static void free_common_resource(ipts_info_t *ipts)
-+{
-+	char *addr;
-+	ipts_buffer_info_t *feedback_buffer;
-+	dma_addr_t dma_addr;
-+	u32 buffer_size;
-+	int i, num_of_parallels;
-+
-+	if (ipts->resource.me2hid_buffer) {
-+		devm_kfree(&ipts->cldev->dev, ipts->resource.me2hid_buffer);
-+		ipts->resource.me2hid_buffer = 0;
-+	}
-+
-+	addr = ipts->resource.hid2me_buffer.addr;
-+	dma_addr = ipts->resource.hid2me_buffer.dma_addr;
-+	buffer_size = ipts->resource.hid2me_buffer_size;
-+
-+	if (ipts->resource.hid2me_buffer.addr) {
-+		dmam_free_coherent(&ipts->cldev->dev, buffer_size, addr, dma_addr);
-+		ipts->resource.hid2me_buffer.addr = 0;
-+		ipts->resource.hid2me_buffer.dma_addr = 0;
-+		ipts->resource.hid2me_buffer_size = 0;
-+	}
-+
-+	feedback_buffer = ipts->resource.feedback_buffer;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		if (feedback_buffer[i].addr) {
-+			dmam_free_coherent(&ipts->cldev->dev,
-+				ipts->device_info.feedback_size,
-+				feedback_buffer[i].addr,
-+				feedback_buffer[i].dma_addr);
-+			feedback_buffer[i].addr = 0;
-+			feedback_buffer[i].dma_addr = 0;
-+		}
-+	}
-+}
-+
-+static int allocate_common_resource(ipts_info_t *ipts)
-+{
-+	char *addr, *me2hid_addr;
-+	ipts_buffer_info_t *feedback_buffer;
-+	dma_addr_t dma_addr;
-+	int i, ret = 0, num_of_parallels;
-+	u32 buffer_size;
-+
-+	buffer_size = ipts->device_info.feedback_size;
-+
-+	addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+			buffer_size,
-+			&dma_addr,
-+			GFP_ATOMIC|__GFP_ZERO);
-+	if (addr == NULL)
-+		return -ENOMEM;
-+
-+	me2hid_addr = devm_kzalloc(&ipts->cldev->dev, buffer_size, GFP_KERNEL);
-+	if (me2hid_addr == NULL) {
-+		ret = -ENOMEM;
-+		goto release_resource;
-+	}
-+
-+	ipts->resource.hid2me_buffer.addr = addr;
-+	ipts->resource.hid2me_buffer.dma_addr = dma_addr;
-+	ipts->resource.hid2me_buffer_size = buffer_size;
-+	ipts->resource.me2hid_buffer = me2hid_addr;
-+
-+	feedback_buffer = ipts->resource.feedback_buffer;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		feedback_buffer[i].addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+				ipts->device_info.feedback_size,
-+				&feedback_buffer[i].dma_addr,
-+				GFP_ATOMIC|__GFP_ZERO);
-+
-+		if (feedback_buffer[i].addr == NULL) {
-+			ret = -ENOMEM;
-+			goto release_resource;
-+		}
-+	}
-+
-+	return 0;
-+
-+release_resource:
-+	free_common_resource(ipts);
-+
-+	return ret;
-+}
-+
-+void ipts_free_raw_data_resource(ipts_info_t *ipts)
-+{
-+	if (ipts_is_raw_data_resource_ready(ipts)) {
-+		ipts->resource.raw_data_resource_ready = false;
-+
-+		ipts_release_kernels(ipts);
-+	}
-+}
-+
-+static int allocate_hid_resource(ipts_info_t *ipts)
-+{
-+	ipts_buffer_info_t *buffer_hid;
-+
-+	/* hid mode uses only one touch data buffer */
-+	buffer_hid = &ipts->resource.touch_data_buffer_hid;
-+	buffer_hid->addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+				ipts->device_info.frame_size,
-+				&buffer_hid->dma_addr,
-+				GFP_ATOMIC|__GFP_ZERO);
-+	if (buffer_hid->addr == NULL) {
-+		return -ENOMEM;
-+	}
-+
-+	return 0;
-+}
-+
-+static void free_hid_resource(ipts_info_t *ipts)
-+{
-+	ipts_buffer_info_t *buffer_hid;
-+
-+	buffer_hid = &ipts->resource.touch_data_buffer_hid;
-+	if (buffer_hid->addr) {
-+		dmam_free_coherent(&ipts->cldev->dev,
-+				ipts->device_info.frame_size,
-+				buffer_hid->addr,
-+				buffer_hid->dma_addr);
-+		buffer_hid->addr = 0;
-+		buffer_hid->dma_addr = 0;
-+	}
-+}
-+
-+int ipts_allocate_default_resource(ipts_info_t *ipts)
-+{
-+	int ret;
-+
-+	ret = allocate_common_resource(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot allocate common resource\n");
-+		return ret;
-+	}
-+
-+	ret = allocate_hid_resource(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot allocate hid resource\n");
-+		free_common_resource(ipts);
-+		return ret;
-+	}
-+
-+	ipts->resource.default_resource_ready = true;
-+
-+	return 0;
-+}
-+
-+void ipts_free_default_resource(ipts_info_t *ipts)
-+{
-+	if (ipts_is_default_resource_ready(ipts)) {
-+		ipts->resource.default_resource_ready = false;
-+
-+		free_hid_resource(ipts);
-+		free_common_resource(ipts);
-+	}
-+}
-+
-+int ipts_allocate_raw_data_resource(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ret = ipts_init_kernels(ipts);
-+	if (ret) {
-+		return ret;
-+	}
-+
-+	ipts->resource.raw_data_resource_ready = true;
-+
-+	return 0;
-+}
-+
-+static void get_hid_only_smw_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data,
-+				ipts_resource_t *resrc)
-+{
-+	ipts_buffer_info_t *touch_buf;
-+	ipts_buffer_info_t *feedback_buf;
-+
-+	touch_buf = &resrc->touch_data_buffer_hid;
-+	feedback_buf = &resrc->feedback_buffer[0];
-+
-+	data->touch_data_buffer_addr_lower[0] =
-+				lower_32_bits(touch_buf->dma_addr);
-+	data->touch_data_buffer_addr_upper[0] =
-+				upper_32_bits(touch_buf->dma_addr);
-+	data->feedback_buffer_addr_lower[0] =
-+				lower_32_bits(feedback_buf->dma_addr);
-+	data->feedback_buffer_addr_upper[0] =
-+				upper_32_bits(feedback_buf->dma_addr);
-+}
-+
-+static void get_raw_data_only_smw_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data,
-+				ipts_resource_t *resrc)
-+{
-+	u64 wq_tail_phy_addr;
-+	u64 cookie_phy_addr;
-+	ipts_buffer_info_t *touch_buf;
-+	ipts_buffer_info_t *feedback_buf;
-+	int i, num_of_parallels;
-+
-+	touch_buf = resrc->touch_data_buffer_raw;
-+	feedback_buf = resrc->feedback_buffer;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		data->touch_data_buffer_addr_lower[i] =
-+					lower_32_bits(touch_buf[i].dma_addr);
-+		data->touch_data_buffer_addr_upper[i] =
-+					upper_32_bits(touch_buf[i].dma_addr);
-+		data->feedback_buffer_addr_lower[i] =
-+					lower_32_bits(feedback_buf[i].dma_addr);
-+		data->feedback_buffer_addr_upper[i] =
-+					upper_32_bits(feedback_buf[i].dma_addr);
-+	}
-+
-+	wq_tail_phy_addr = resrc->wq_info.wq_tail_phy_addr;
-+	data->tail_offset_addr_lower = lower_32_bits(wq_tail_phy_addr);
-+	data->tail_offset_addr_upper = upper_32_bits(wq_tail_phy_addr);
-+
-+	cookie_phy_addr = resrc->wq_info.db_phy_addr +
-+						resrc->wq_info.db_cookie_offset;
-+	data->doorbell_cookie_addr_lower = lower_32_bits(cookie_phy_addr);
-+	data->doorbell_cookie_addr_upper = upper_32_bits(cookie_phy_addr);
-+	data->work_queue_size = resrc->wq_info.wq_size;
-+
-+	data->work_queue_item_size = resrc->wq_item_size;
-+}
-+
-+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data)
-+{
-+	ipts_resource_t *resrc = &ipts->resource;
-+
-+	if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA)
-+		get_raw_data_only_smw_cmd_data(ipts, data, resrc);
-+	else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID)
-+		get_hid_only_smw_cmd_data(ipts, data, resrc);
-+
-+	/* hid2me is common for "raw data" and "hid" */
-+	data->hid2me_buffer_addr_lower =
-+				lower_32_bits(resrc->hid2me_buffer.dma_addr);
-+	data->hid2me_buffer_addr_upper =
-+				upper_32_bits(resrc->hid2me_buffer.dma_addr);
-+	data->hid2me_buffer_size = resrc->hid2me_buffer_size;
-+}
-+
-+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx,
-+						u8* cpu_addr, u64 dma_addr)
-+{
-+	ipts_buffer_info_t *touch_buf;
-+
-+	touch_buf = ipts->resource.touch_data_buffer_raw;
-+	touch_buf[parallel_idx].dma_addr = dma_addr;
-+	touch_buf[parallel_idx].addr = cpu_addr;
-+}
-+
-+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx,
-+						u8* cpu_addr, u64 dma_addr)
-+{
-+	ipts_buffer_info_t *output_buf;
-+
-+	output_buf = &ipts->resource.raw_data_mode_output_buffer[parallel_idx][output_idx];
-+
-+	output_buf->dma_addr = dma_addr;
-+	output_buf->addr = cpu_addr;
-+}
-diff --git a/drivers/misc/ipts/ipts-resource.h b/drivers/misc/ipts/ipts-resource.h
-new file mode 100644
-index 000000000000..7d66ac72b475
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-resource.h
-@@ -0,0 +1,30 @@
-+/*
-+ * Intel Precise Touch & Stylus state codes
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_RESOURCE_H_
-+#define _IPTS_RESOURCE_H_
-+
-+int ipts_allocate_default_resource(ipts_info_t *ipts);
-+void ipts_free_default_resource(ipts_info_t *ipts);
-+int ipts_allocate_raw_data_resource(ipts_info_t *ipts);
-+void ipts_free_raw_data_resource(ipts_info_t *ipts);
-+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data);
-+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx,
-+						u8* cpu_addr, u64 dma_addr);
-+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx,
-+						u8* cpu_addr, u64 dma_addr);
-+
-+#endif // _IPTS_RESOURCE_H_
-diff --git a/drivers/misc/ipts/ipts-sensor-regs.h b/drivers/misc/ipts/ipts-sensor-regs.h
-new file mode 100644
-index 000000000000..96812b0eb980
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-sensor-regs.h
-@@ -0,0 +1,700 @@
-+/*
-+ * Touch Sensor Register definition
-+ *
-+ * Copyright (c) 2013-2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+
-+#ifndef _TOUCH_SENSOR_REGS_H
-+#define _TOUCH_SENSOR_REGS_H
-+
-+#pragma pack(1)
-+
-+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch
-+#ifndef C_ASSERT
-+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
-+#endif
-+
-+//
-+// Compatibility versions for this header file
-+//
-+#define TOUCH_EDS_REV_MINOR     0
-+#define TOUCH_EDS_REV_MAJOR     1
-+#define TOUCH_EDS_INTF_REV      1
-+#define TOUCH_PROTOCOL_VER      0
-+
-+
-+//
-+// Offset 00h: TOUCH_STS: Status Register
-+// This register is read by the SPI Controller immediately following an interrupt.
-+//
-+#define TOUCH_STS_REG_OFFSET                0x00
-+
-+typedef enum touch_sts_reg_int_type
-+{
-+    TOUCH_STS_REG_INT_TYPE_DATA_AVAIL = 0,  // Touch Data Available
-+    TOUCH_STS_REG_INT_TYPE_RESET_OCCURRED,  // Reset Occurred
-+    TOUCH_STS_REG_INT_TYPE_ERROR_OCCURRED,  // Error Occurred
-+    TOUCH_STS_REG_INT_TYPE_VENDOR_DATA,     // Vendor specific data, treated same as raw frame
-+    TOUCH_STS_REG_INT_TYPE_GET_FEATURES,    // Get Features response data available
-+    TOUCH_STS_REG_INT_TYPE_MAX
-+} touch_sts_reg_int_type_t;
-+C_ASSERT(sizeof(touch_sts_reg_int_type_t) == 4);
-+
-+typedef enum touch_sts_reg_pwr_state
-+{
-+    TOUCH_STS_REG_PWR_STATE_SLEEP = 0,  // Sleep
-+    TOUCH_STS_REG_PWR_STATE_DOZE,       // Doze
-+    TOUCH_STS_REG_PWR_STATE_ARMED,      // Armed
-+    TOUCH_STS_REG_PWR_STATE_SENSING,    // Sensing
-+    TOUCH_STS_REG_PWR_STATE_MAX
-+} touch_sts_reg_pwr_state_t;
-+C_ASSERT(sizeof(touch_sts_reg_pwr_state_t) == 4);
-+
-+typedef enum touch_sts_reg_init_state
-+{
-+    TOUCH_STS_REG_INIT_STATE_READY_FOR_OP = 0,  // Ready for normal operation
-+    TOUCH_STS_REG_INIT_STATE_FW_NEEDED,         // Touch IC needs its Firmware loaded
-+    TOUCH_STS_REG_INIT_STATE_DATA_NEEDED,       // Touch IC needs its Data loaded
-+    TOUCH_STS_REG_INIT_STATE_INIT_ERROR,        // Error info in TOUCH_ERR_REG
-+    TOUCH_STS_REG_INIT_STATE_MAX
-+} touch_sts_reg_init_state_t;
-+C_ASSERT(sizeof(touch_sts_reg_init_state_t) == 4);
-+
-+#define TOUCH_SYNC_BYTE_VALUE   0x5A
-+
-+typedef union touch_sts_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // When set, this indicates the hardware has data that needs to be read.
-+        u32  int_status           :1;
-+        // see TOUCH_STS_REG_INT_TYPE
-+        u32  int_type             :4;
-+        // see TOUCH_STS_REG_PWR_STATE
-+        u32  pwr_state            :2;
-+        // see TOUCH_STS_REG_INIT_STATE
-+        u32  init_state           :2;
-+        // Busy bit indicates that sensor cannot accept writes at this time
-+        u32  busy                :1;
-+        // Reserved
-+        u32  reserved            :14;
-+        // Synchronization bit, should always be TOUCH_SYNC_BYTE_VALUE
-+        u32  sync_byte            :8;
-+    } fields;
-+} touch_sts_reg_t;
-+C_ASSERT(sizeof(touch_sts_reg_t) == 4);
-+
-+
-+//
-+// Offset 04h: TOUCH_FRAME_CHAR: Frame Characteristics Register
-+// This registers describes the characteristics of each data frame read by the SPI Controller in
-+// response to a touch interrupt.
-+//
-+#define TOUCH_FRAME_CHAR_REG_OFFSET         0x04
-+
-+typedef union touch_frame_char_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Micro-Frame Size (MFS):  Indicates the size of a touch micro-frame in byte increments.
-+        // When a micro-frame is to be read for processing (in data mode), this is the total number of
-+        // bytes that must be read per interrupt, split into multiple read commands no longer than RPS.
-+        // Maximum micro-frame size is 256KB.
-+        u32  microframe_size      :18;
-+        // Micro-Frames per Frame (MFPF): Indicates the number of micro-frames per frame. If a
-+        // sensor's frame does not contain micro-frames this value will be 1. Valid values are 1-31.
-+        u32  microframes_per_frame :5;
-+        // Micro-Frame Index (MFI): Indicates the index of the micro-frame within a frame. This allows
-+        // the SPI Controller to maintain synchronization with the sensor and determine when the final
-+        // micro-frame has arrived. Valid values are 1-31.
-+        u32  microframe_index     :5;
-+        // HID/Raw Data: This bit describes whether the data from the sensor is Raw data or a HID
-+        // report. When set, the data is a HID report.
-+        u32  hid_report           :1;
-+        // Reserved
-+        u32  reserved            :3;
-+    } fields;
-+} touch_frame_char_reg_t;
-+C_ASSERT(sizeof(touch_frame_char_reg_t) == 4);
-+
-+
-+//
-+// Offset 08h: Touch Error Register
-+//
-+#define TOUCH_ERR_REG_OFFSET                0x08
-+
-+// bit definition is vendor specific
-+typedef union touch_err_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        u32  invalid_fw           :1;
-+        u32  invalid_data        :1;
-+        u32  self_test_failed       :1;
-+        u32  reserved            :12;
-+        u32  fatal_error          :1;
-+        u32  vendor_errors        :16;
-+    } fields;
-+} touch_err_reg_t;
-+C_ASSERT(sizeof(touch_err_reg_t) == 4);
-+
-+
-+//
-+// Offset 0Ch: RESERVED
-+// This register is reserved for future use.
-+//
-+
-+
-+//
-+// Offset 10h: Touch Identification Register
-+//
-+#define TOUCH_ID_REG_OFFSET                 0x10
-+
-+#define TOUCH_ID_REG_VALUE                  0x43495424
-+
-+// expected value is "$TIC" or 0x43495424
-+typedef u32  touch_id_reg_t;
-+C_ASSERT(sizeof(touch_id_reg_t) == 4);
-+
-+
-+//
-+// Offset 14h: TOUCH_DATA_SZ: Touch Data Size Register
-+// This register describes the maximum size of frames and feedback data
-+//
-+#define TOUCH_DATA_SZ_REG_OFFSET            0x14
-+
-+#define TOUCH_MAX_FRAME_SIZE_INCREMENT      64
-+#define TOUCH_MAX_FEEDBACK_SIZE_INCREMENT   64
-+
-+#define TOUCH_SENSOR_MAX_FRAME_SIZE         (32 * 1024)     // Max allowed frame size 32KB
-+#define TOUCH_SENSOR_MAX_FEEDBACK_SIZE      (16 * 1024)     // Max allowed feedback size 16KB
-+
-+typedef union touch_data_sz_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // This value describes the maximum frame size in 64byte increments.
-+        u32  max_frame_size        :12;
-+        // This value describes the maximum feedback size in 64byte increments.
-+        u32  max_feedback_size     :8;
-+        // Reserved
-+        u32  reserved            :12;
-+    } fields;
-+} touch_data_sz_reg_t;
-+C_ASSERT(sizeof(touch_data_sz_reg_t) == 4);
-+
-+
-+//
-+// Offset 18h: TOUCH_CAPABILITIES: Touch Capabilities Register
-+// This register informs the host as to the capabilities of the touch IC.
-+//
-+#define TOUCH_CAPS_REG_OFFSET               0x18
-+
-+typedef enum touch_caps_reg_read_delay_time
-+{
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_0,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_10uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_50uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_100uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_150uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_250uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_500uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_1mS,
-+} touch_caps_reg_read_delay_time_t;
-+C_ASSERT(sizeof(touch_caps_reg_read_delay_time_t) == 4);
-+
-+#define TOUCH_BULK_DATA_MAX_WRITE_INCREMENT 64
-+
-+typedef union touch_caps_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Reserved for future frequency
-+        u32  reserved0           :1;
-+        // 17 MHz (14 MHz on Atom) Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_17Mhz      :1;
-+        // 30 MHz (25MHz on Atom) Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_30Mhz      :1;
-+        // 50 MHz Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_50Mhz      :1;
-+        // Reserved
-+        u32  reserved1           :4;
-+        // Single I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_single_io   :1;
-+        // Dual I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_dual_io     :1;
-+        // Quad I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_quad_io     :1;
-+        // Bulk Data Area Max Write Size: The amount of data the SPI Controller can write to the bulk
-+        // data area before it has to poll the busy bit. This field is in multiples of 64 bytes. The
-+        // SPI Controller will write the amount of data specified in this field, then check and wait
-+        // for the Status.Busy bit to be zero before writing the next data chunk. This field is 6 bits
-+        // long, allowing for 4KB of contiguous writes w/o a poll of the busy bit. If this field is
-+        // 0x00 the Touch IC has no limit in the amount of data the SPI Controller can write to the
-+        // bulk data area.
-+        u32  bulk_data_max_write    :6;
-+        // Read Delay Timer Value: This field describes the delay the SPI Controller will initiate when
-+        // a read interrupt follows a write data command. Uses values from TOUCH_CAPS_REG_READ_DELAY_TIME
-+        u32  read_delay_timer_value :3;
-+        // Reserved
-+        u32  reserved2           :4;
-+        // Maximum Touch Points: A byte value based on the HID descriptor definition.
-+        u32  max_touch_points      :8;
-+    } fields;
-+} touch_caps_reg_t;
-+C_ASSERT(sizeof(touch_caps_reg_t) == 4);
-+
-+
-+//
-+// Offset 1Ch: TOUCH_CFG: Touch Configuration Register
-+// This register allows the SPI Controller to configure the touch sensor as needed during touch
-+// operations.
-+//
-+#define TOUCH_CFG_REG_OFFSET                0x1C
-+
-+typedef enum touch_cfg_reg_bulk_xfer_size
-+{
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_4B  = 0,   // Bulk Data Transfer Size is 4 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_8B,        // Bulk Data Transfer Size is 8 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_16B,       // Bulk Data Transfer Size is 16 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_32B,       // Bulk Data Transfer Size is 32 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_64B,       // Bulk Data Transfer Size is 64 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_MAX
-+} touch_cfg_reg_bulk_xfer_size_t;
-+C_ASSERT(sizeof(touch_cfg_reg_bulk_xfer_size_t) == 4);
-+
-+// Frequency values used by TOUCH_CFG_REG and TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+typedef enum touch_freq
-+{
-+    TOUCH_FREQ_RSVD = 0,    // Reserved value
-+    TOUCH_FREQ_17MHZ,       // Sensor set for 17MHz operation (14MHz on Atom)
-+    TOUCH_FREQ_30MHZ,       // Sensor set for 30MHz operation (25MHz on Atom)
-+    TOUCH_FREQ_MAX          // Invalid value
-+} touch_freq_t;
-+C_ASSERT(sizeof(touch_freq_t) == 4);
-+
-+typedef union touch_cfg_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Touch Enable (TE):  This bit is used as a HW semaphore for the Touch IC to guarantee to the
-+        // SPI Controller to that (when 0) no sensing operations will occur and only the Reset
-+        // interrupt will be generated. When TE is cleared by the SPI Controller:
-+        //  - TICs must flush all output buffers
-+        //  - TICs must De-assert any pending interrupt
-+        //  - ME must throw away any partial frame and pending interrupt must be cleared/not serviced.
-+        // The SPI Controller will only modify the configuration of the TIC when TE is cleared. TE is
-+        // defaulted to 0h on a power-on reset.
-+        u32  touch_enable         :1;
-+        // Data/HID Packet Mode (DHPM): Raw Data Mode: 0h, HID Packet Mode: 1h
-+        u32  dhpm                :1;
-+        // Bulk Data Transfer Size: This field represents the amount of data written to the Bulk Data
-+        // Area (SPI Offset 0x1000-0x2FFF) in a single SPI write protocol
-+        u32  bulk_xfer_size        :4;
-+        // Frequency Select: Frequency for the TouchIC to run at. Use values from TOUCH_FREQ
-+        u32  freq_select          :3;
-+        // Reserved
-+        u32  reserved            :23;
-+    } fields;
-+} touch_cfg_reg_t;
-+C_ASSERT(sizeof(touch_cfg_reg_t) == 4);
-+
-+
-+//
-+// Offset 20h: TOUCH_CMD: Touch Command Register
-+// This register is used for sending commands to the Touch IC.
-+//
-+#define TOUCH_CMD_REG_OFFSET                0x20
-+
-+typedef enum touch_cmd_reg_code
-+{
-+    TOUCH_CMD_REG_CODE_NOP = 0,             // No Operation
-+    TOUCH_CMD_REG_CODE_SOFT_RESET,          // Soft Reset
-+    TOUCH_CMD_REG_CODE_PREP_4_READ,         // Prepare All Registers for Read
-+    TOUCH_CMD_REG_CODE_GEN_TEST_PACKETS,    // Generate Test Packets according to value in TOUCH_TEST_CTRL_REG
-+    TOUCH_CMD_REG_CODE_MAX
-+} touch_cmd_reg_code_t;
-+C_ASSERT(sizeof(touch_cmd_reg_code_t) == 4);
-+
-+typedef union touch_cmd_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Command Code: See TOUCH_CMD_REG_CODE
-+        u32  command_code :8;
-+        // Reserved
-+        u32  reserved    :24;
-+    } fields;
-+} touch_cmd_reg_t;
-+C_ASSERT(sizeof(touch_cmd_reg_t) == 4);
-+
-+
-+//
-+// Offset 24h: Power Management Control
-+// This register is used for active power management. The Touch IC is allowed to mover from Doze or
-+// Armed to Sensing after a touch has occurred. All other transitions will be made at the request
-+// of the SPI Controller.
-+//
-+#define TOUCH_PWR_MGMT_CTRL_REG_OFFSET      0x24
-+
-+typedef enum touch_pwr_mgmt_ctrl_reg_cmd
-+{
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_NOP = 0,    // No change to power state
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_SLEEP,      // Sleep   - set when the system goes into connected standby
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_DOZE,       // Doze    - set after 300 seconds of inactivity
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_ARMED,      // Armed   - Set by FW when a "finger off" message is received from the EUs
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_SENSING,    // Sensing - not typically set by FW
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_MAX         // Values will result in no change to the power state of the Touch IC
-+} touch_pwr_mgmt_ctrl_reg_cmd_t;
-+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_cmd_t) == 4);
-+
-+typedef union touch_pwr_mgmt_ctrl_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Power State Command: See TOUCH_PWR_MGMT_CTRL_REG_CMD
-+        u32  pwr_state_cmd         :3;
-+        // Reserved
-+        u32  reserved            :29;
-+    } fields;
-+} touch_pwr_mgmt_ctrl_reg_t;
-+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_t) == 4);
-+
-+
-+//
-+// Offset 28h: Vendor HW Information Register
-+// This register is used to relay Intel-assigned vendor ID information to the SPI Controller, which
-+// may be forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_VEN_HW_INFO_REG_OFFSET        0x28
-+
-+typedef union touch_ven_hw_info_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Touch Sensor Vendor ID
-+        u32  vendor_id            :16;
-+        // Touch Sensor Device ID
-+        u32  device_id            :16;
-+    } fields;
-+} touch_ven_hw_info_reg_t;
-+C_ASSERT(sizeof(touch_ven_hw_info_reg_t) == 4);
-+
-+
-+//
-+// Offset 2Ch: HW Revision ID Register
-+// This register is used to relay vendor HW revision information to the SPI Controller which may be
-+// forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_HW_REV_REG_OFFSET             0x2C
-+
-+typedef u32  touch_hw_rev_reg_t;   // bit definition is vendor specific
-+C_ASSERT(sizeof(touch_hw_rev_reg_t) == 4);
-+
-+
-+//
-+// Offset 30h: FW Revision ID Register
-+// This register is used to relay vendor FW revision information to the SPI Controller which may be
-+// forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_FW_REV_REG_OFFSET             0x30
-+
-+typedef u32  touch_fw_rev_reg_t;    // bit definition is vendor specific
-+C_ASSERT(sizeof(touch_fw_rev_reg_t) == 4);
-+
-+
-+//
-+// Offset 34h: Compatibility Revision ID Register
-+// This register is used to relay vendor compatibility information to the SPI Controller which may
-+// be forwarded to SW running on the host CPU. Compatibility Information is a numeric value given
-+// by Intel to the Touch IC vendor based on the major and minor revision of the EDS supported. From
-+// a nomenclature point of view in an x.y revision number of the EDS, the major version is the value
-+// of x and the minor version is the value of y. For example, a Touch IC supporting an EDS version
-+// of 0.61 would contain a major version of 0 and a minor version of 61 in the register.
-+//
-+#define TOUCH_COMPAT_REV_REG_OFFSET             0x34
-+
-+typedef union touch_compat_rev_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // EDS Minor Revision
-+        u8   minor;
-+        // EDS Major Revision
-+        u8   major;
-+        // Interface Revision Number (from EDS)
-+        u8   intf_rev;
-+        // EU Kernel Compatibility Version - vendor specific value
-+        u8   kernel_compat_ver;
-+    } fields;
-+} touch_compat_rev_reg_t;
-+C_ASSERT(sizeof(touch_compat_rev_reg_t) == 4);
-+
-+
-+//
-+// Touch Register Block is the full set of registers from offset 0x00h to 0x3F
-+// This is the entire set of registers needed for normal touch operation. It does not include test
-+// registers such as TOUCH_TEST_CTRL_REG
-+//
-+#define TOUCH_REG_BLOCK_OFFSET              TOUCH_STS_REG_OFFSET
-+
-+typedef struct touch_reg_block
-+{
-+    touch_sts_reg_t         sts_reg;         // 0x00
-+    touch_frame_char_reg_t  frame_char_reg;   // 0x04
-+    touch_err_reg_t         error_reg;       // 0x08
-+    u32                  reserved0;      // 0x0C
-+    touch_id_reg_t          id_reg;          // 0x10
-+    touch_data_sz_reg_t     data_size_reg;    // 0x14
-+    touch_caps_reg_t        caps_reg;        // 0x18
-+    touch_cfg_reg_t         cfg_reg;         // 0x1C
-+    touch_cmd_reg_t         cmd_reg;         // 0x20
-+    touch_pwr_mgmt_ctrl_reg_t  pwm_mgme_ctrl_reg; // 0x24
-+    touch_ven_hw_info_reg_t ven_hw_info_reg;   // 0x28
-+    touch_hw_rev_reg_t      hw_rev_reg;       // 0x2C
-+    touch_fw_rev_reg_t      fw_rev_reg;       // 0x30
-+    touch_compat_rev_reg_t  compat_rev_reg;   // 0x34
-+    u32                  reserved1;      // 0x38
-+    u32                  reserved2;      // 0x3C
-+} touch_reg_block_t;
-+C_ASSERT(sizeof(touch_reg_block_t) == 64);
-+
-+
-+//
-+// Offset 40h: Test Control Register
-+// This register
-+//
-+#define TOUCH_TEST_CTRL_REG_OFFSET              0x40
-+
-+typedef union touch_test_ctrl_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Size of Test Frame in Raw Data Mode: This field specifies the test frame size in raw data
-+        // mode in multiple of 64 bytes. For example, if this field value is 16, the test frame size
-+        // will be 16x64 = 1K.
-+        u32  raw_test_frame_size    :16;
-+        // Number of Raw Data Frames or HID Report Packets Generation. This field represents the number
-+        // of test frames or HID reports to be generated when test mode is enabled. When multiple
-+        // packets/frames are generated, they need be generated at 100 Hz frequency, i.e. 10ms per
-+        // packet/frame.
-+        u32  num_test_frames       :16;
-+    } fields;
-+} touch_test_ctrl_reg_t;
-+C_ASSERT(sizeof(touch_test_ctrl_reg_t) == 4);
-+
-+
-+//
-+// Offsets 0x000 to 0xFFF are reserved for Intel-defined Registers
-+//
-+#define TOUCH_REGISTER_LIMIT                0xFFF
-+
-+
-+//
-+// Data Window: Address 0x1000-0x1FFFF
-+// The data window is reserved for writing and reading large quantities of data to and from the
-+// sensor.
-+//
-+#define TOUCH_DATA_WINDOW_OFFSET            0x1000
-+#define TOUCH_DATA_WINDOW_LIMIT             0x1FFFF
-+
-+#define TOUCH_SENSOR_MAX_OFFSET             TOUCH_DATA_WINDOW_LIMIT
-+
-+
-+//
-+// The following data structures represent the headers defined in the Data Structures chapter of the
-+// Intel Integrated Touch EDS
-+//
-+
-+// Enumeration used in TOUCH_RAW_DATA_HDR
-+typedef enum touch_raw_data_types
-+{
-+    TOUCH_RAW_DATA_TYPE_FRAME = 0,
-+    TOUCH_RAW_DATA_TYPE_ERROR,          // RawData will be the TOUCH_ERROR struct below
-+    TOUCH_RAW_DATA_TYPE_VENDOR_DATA,    // Set when InterruptType is Vendor Data
-+    TOUCH_RAW_DATA_TYPE_HID_REPORT,
-+    TOUCH_RAW_DATA_TYPE_GET_FEATURES,
-+    TOUCH_RAW_DATA_TYPE_MAX
-+} touch_raw_data_types_t;
-+C_ASSERT(sizeof(touch_raw_data_types_t) == 4);
-+
-+// Private data structure. Kernels must copy to HID driver buffer
-+typedef struct touch_hid_private_data
-+{
-+    u32  transaction_id;
-+    u8   reserved[28];
-+} touch_hid_private_data_t;
-+C_ASSERT(sizeof(touch_hid_private_data_t) == 32);
-+
-+// This is the data structure sent from the PCH FW to the EU kernel
-+typedef struct touch_raw_data_hdr
-+{
-+    u32                  data_type;           // use values from TOUCH_RAW_DATA_TYPES
-+    u32                  raw_data_size_bytes;   // The size in bytes of the raw data read from the
-+                                                // sensor, does not include TOUCH_RAW_DATA_HDR. Will
-+                                                // be the sum of all uFrames, or size of TOUCH_ERROR
-+                                                // for if DataType is TOUCH_RAW_DATA_TYPE_ERROR
-+    u32                  buffer_id;           // An ID to qualify with the feedback data to track
-+                                                // buffer usage
-+    u32                  protocol_ver;        // Must match protocol version of the EDS
-+    u8                   kernel_compat_id;     // Copied from the Compatibility Revision ID Reg
-+    u8                   reserved[15];       // Padding to extend header to full 64 bytes and
-+                                                // allow for growth
-+    touch_hid_private_data_t  hid_private_data;     // Private data structure. Kernels must copy to HID
-+                                                // driver buffer
-+} touch_raw_data_hdr_t;
-+C_ASSERT(sizeof(touch_raw_data_hdr_t) == 64);
-+
-+typedef struct touch_raw_data
-+{
-+    touch_raw_data_hdr_t  header;
-+    u8               raw_data[1]; // used to access the raw data as an array and keep the
-+                                    // compilers happy. Actual size of this array is
-+                                    // Header.RawDataSizeBytes
-+} touch_raw_data_t;
-+
-+
-+// The following section describes the data passed in TOUCH_RAW_DATA.RawData when DataType equals
-+// TOUCH_RAW_DATA_TYPE_ERROR
-+// Note: This data structure is also applied to HID mode
-+typedef enum touch_err_types
-+{
-+    TOUCH_RAW_DATA_ERROR = 0,
-+    TOUCH_RAW_ERROR_MAX
-+} touch_err_types_t;
-+C_ASSERT(sizeof(touch_err_types_t) == 4);
-+
-+typedef union touch_me_fw_error
-+{
-+    u32  value;
-+
-+    struct
-+    {
-+        u32 invalid_frame_characteristics : 1;
-+        u32 microframe_index_invalid      : 1;
-+        u32 reserved                    : 30;
-+    } fields;
-+} touch_me_fw_error_t;
-+C_ASSERT(sizeof(touch_me_fw_error_t) == 4);
-+
-+typedef struct touch_error
-+{
-+    u8			touch_error_type; // This must be a value from TOUCH_ERROR_TYPES
-+    u8			reserved[3];
-+    touch_me_fw_error_t	touch_me_fw_error;
-+    touch_err_reg_t	touch_error_register; // Contains the value copied from the Touch Error Reg
-+} touch_error_t;
-+C_ASSERT(sizeof(touch_error_t) == 12);
-+
-+// Enumeration used in TOUCH_FEEDBACK_BUFFER
-+typedef enum touch_feedback_cmd_types
-+{
-+    TOUCH_FEEDBACK_CMD_TYPE_NONE = 0,
-+    TOUCH_FEEDBACK_CMD_TYPE_SOFT_RESET,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_ARMED,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_SENSING,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_SLEEP,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_DOZE,
-+    TOUCH_FEEDBACK_CMD_TYPE_HARD_RESET,
-+    TOUCH_FEEDBACK_CMD_TYPE_MAX
-+} touch_feedback_cmd_types_t;
-+C_ASSERT(sizeof(touch_feedback_cmd_types_t) == 4);
-+
-+// Enumeration used in TOUCH_FEEDBACK_HDR
-+typedef enum touch_feedback_data_types
-+{
-+    TOUCH_FEEDBACK_DATA_TYPE_FEEDBACK = 0,  // This is vendor specific feedback to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES,  // This is a set features command to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES,  // This is a get features command to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT, // This is a HID output report to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_STORE_DATA,    // This is calibration data to be written to system flash
-+    TOUCH_FEEDBACK_DATA_TYPE_MAX
-+} touch_feedback_data_types_t;
-+C_ASSERT(sizeof(touch_feedback_data_types_t) == 4);
-+
-+// This is the data structure sent from the EU kernels back to the ME FW.
-+// In addition to "feedback" data, the FW can execute a "command" described by the command type parameter.
-+// Any payload data will always be sent to the TIC first, then any command will be issued.
-+typedef struct touch_feedback_hdr
-+{
-+    u32  feedback_cmd_type;    // use values from TOUCH_FEEDBACK_CMD_TYPES
-+    u32  payload_size_bytes;   // The amount of data to be written to the sensor, not including the header
-+    u32  buffer_id;           // The ID of the raw data buffer that generated this feedback data
-+    u32  protocol_ver;        // Must match protocol version of the EDS
-+    u32  feedback_data_type;   // use values from TOUCH_FEEDBACK_DATA_TYPES. This is not relevant if PayloadSizeBytes is 0
-+    u32  spi_offest;          // The offset from TOUCH_DATA_WINDOW_OFFSET at which to write the Payload data. Maximum offset is 0x1EFFF.
-+    u8   reserved[40];       // Padding to extend header to full 64 bytes and allow for growth
-+} touch_feedback_hdr_t;
-+C_ASSERT(sizeof(touch_feedback_hdr_t) == 64);
-+
-+typedef struct touch_feedback_buffer
-+{
-+    touch_feedback_hdr_t  Header;
-+    u8               feedback_data[1];    // used to access the feedback data as an array and keep the compilers happy. Actual size of this array is Header.PayloadSizeBytes
-+} touch_feedback_buffer_t;
-+
-+
-+//
-+// This data structure describes the header prepended to all data
-+// written to the touch IC at the bulk data write (TOUCH_DATA_WINDOW_OFFSET + TOUCH_FEEDBACK_HDR.SpiOffest) address.
-+typedef enum touch_write_data_type
-+{
-+    TOUCH_WRITE_DATA_TYPE_FW_LOAD = 0,
-+    TOUCH_WRITE_DATA_TYPE_DATA_LOAD,
-+    TOUCH_WRITE_DATA_TYPE_FEEDBACK,
-+    TOUCH_WRITE_DATA_TYPE_SET_FEATURES,
-+    TOUCH_WRITE_DATA_TYPE_GET_FEATURES,
-+    TOUCH_WRITE_DATA_TYPE_OUTPUT_REPORT,
-+    TOUCH_WRITE_DATA_TYPE_NO_DATA_USE_DEFAULTS,
-+    TOUCH_WRITE_DATA_TYPE_MAX
-+} touch_write_data_type_t;
-+C_ASSERT(sizeof(touch_write_data_type_t) == 4);
-+
-+typedef struct touch_write_hdr
-+{
-+    u32  write_data_type;   // Use values from TOUCH_WRITE_DATA_TYPE
-+    u32  write_data_len;    // This field designates the amount of data to follow
-+} touch_write_hdr_t;
-+C_ASSERT(sizeof(touch_write_hdr_t) == 8);
-+
-+typedef struct touch_write_data
-+{
-+    touch_write_hdr_t header;
-+    u8           write_data[1];   // used to access the write data as an array and keep the compilers happy. Actual size of this array is Header.WriteDataLen
-+} touch_write_data_t;
-+
-+#pragma pack()
-+
-+#endif // _TOUCH_SENSOR_REGS_H
-diff --git a/drivers/misc/ipts/ipts-state.h b/drivers/misc/ipts/ipts-state.h
-new file mode 100644
-index 000000000000..39a2eaf5f004
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-state.h
-@@ -0,0 +1,29 @@
-+/*
-+ * Intel Precise Touch & Stylus state codes
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_STATE_H_
-+#define _IPTS_STATE_H_
-+
-+/* ipts driver states */
-+typedef enum ipts_state {
-+	IPTS_STA_NONE,
-+	IPTS_STA_INIT,
-+	IPTS_STA_RESOURCE_READY,
-+	IPTS_STA_HID_STARTED,
-+	IPTS_STA_RAW_DATA_STARTED,
-+	IPTS_STA_STOPPING
-+} ipts_state_t;
-+
-+#endif // _IPTS_STATE_H_
-diff --git a/drivers/misc/ipts/ipts.h b/drivers/misc/ipts/ipts.h
-new file mode 100644
-index 000000000000..1fcd02146b50
---- /dev/null
-+++ b/drivers/misc/ipts/ipts.h
-@@ -0,0 +1,200 @@
-+/*
-+ *
-+ * Intel Management Engine Interface (Intel MEI) Client Driver for IPTS
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_H_
-+#define _IPTS_H_
-+
-+#include <linux/types.h>
-+#include <linux/mei_cl_bus.h>
-+#include <linux/hid.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts-mei-msgs.h"
-+#include "ipts-state.h"
-+#include "ipts-binary-spec.h"
-+
-+//#define ENABLE_IPTS_DEBUG		/* enable IPTS debug */
-+
-+#ifdef ENABLE_IPTS_DEBUG
-+
-+#define ipts_info(ipts, format, arg...) do {\
-+	dev_info(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+#define ipts_dbg(ipts, format, arg...) do {\
-+	dev_info(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+//#define RUN_DBG_THREAD
-+
-+#else
-+
-+#define ipts_info(ipts, format, arg...) do {} while(0);
-+#define ipts_dbg(ipts, format, arg...) do {} while(0);
-+
-+#endif
-+
-+#define ipts_err(ipts, format, arg...) do {\
-+	dev_err(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+#define HID_PARALLEL_DATA_BUFFERS	TOUCH_SENSOR_MAX_DATA_BUFFERS
-+
-+#define IPTS_MAX_RETRY			3
-+
-+typedef struct ipts_buffer_info {
-+	char *addr;
-+	dma_addr_t dma_addr;
-+} ipts_buffer_info_t;
-+
-+typedef struct ipts_gfx_info {
-+	u64     gfx_handle;
-+	intel_ipts_ops_t ipts_ops;
-+} ipts_gfx_info_t;
-+
-+typedef struct ipts_resource {
-+	/* ME & Gfx resource */
-+	ipts_buffer_info_t touch_data_buffer_raw[HID_PARALLEL_DATA_BUFFERS];
-+	ipts_buffer_info_t touch_data_buffer_hid;
-+
-+	ipts_buffer_info_t feedback_buffer[HID_PARALLEL_DATA_BUFFERS];
-+
-+	ipts_buffer_info_t hid2me_buffer;
-+	u32 hid2me_buffer_size;
-+
-+	u8 wq_item_size;
-+	intel_ipts_wq_info_t wq_info;
-+
-+	/* ME2HID buffer */
-+	char *me2hid_buffer;
-+
-+	/* Gfx specific resource */
-+	ipts_buffer_info_t raw_data_mode_output_buffer
-+	    [HID_PARALLEL_DATA_BUFFERS][MAX_NUM_OUTPUT_BUFFERS];
-+
-+	int num_of_outputs;
-+
-+	bool default_resource_ready;
-+	bool raw_data_resource_ready;
-+} ipts_resource_t;
-+
-+typedef struct ipts_info {
-+	struct mei_cl_device *cldev;
-+	struct hid_device *hid;
-+
-+	struct work_struct init_work;
-+	struct work_struct raw_data_work;
-+	struct work_struct gfx_status_work;
-+
-+	struct task_struct *event_loop;
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+        struct dentry *dbgfs_dir;
-+#endif
-+
-+	ipts_state_t	state;
-+
-+	touch_sensor_mode_t	sensor_mode;
-+	touch_sensor_get_device_info_rsp_data_t device_info;
-+	ipts_resource_t	resource;
-+	u8		hid_input_report[HID_MAX_BUFFER_SIZE];
-+	int		num_of_parallel_data_buffers;
-+	bool		hid_desc_ready;
-+
-+	int current_buffer_index;
-+	int last_buffer_completed;
-+	int *last_submitted_id;
-+
-+	ipts_gfx_info_t gfx_info;
-+	u64		kernel_handle;
-+	int             gfx_status;
-+	bool		display_status;
-+
-+	bool		switch_sensor_mode;
-+	touch_sensor_mode_t	new_sensor_mode;
-+
-+	int		retry;
-+	bool		restart;
-+} ipts_info_t;
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+int ipts_dbgfs_register(ipts_info_t *ipts, const char *name);
-+void ipts_dbgfs_deregister(ipts_info_t *ipts);
-+#else
-+static int ipts_dbgfs_register(ipts_info_t *ipts, const char *name);
-+static void ipts_dbgfs_deregister(ipts_info_t *ipts);
-+#endif /* CONFIG_DEBUG_FS */
-+
-+/* inline functions */
-+static inline void ipts_set_state(ipts_info_t *ipts, ipts_state_t state)
-+{
-+	ipts->state = state;
-+}
-+
-+static inline ipts_state_t ipts_get_state(const ipts_info_t *ipts)
-+{
-+	return ipts->state;
-+}
-+
-+static inline bool ipts_is_default_resource_ready(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.default_resource_ready;
-+}
-+
-+static inline bool ipts_is_raw_data_resource_ready(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.raw_data_resource_ready;
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_feedback_buffer(ipts_info_t *ipts,
-+								int buffer_idx)
-+{
-+	return &ipts->resource.feedback_buffer[buffer_idx];
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_touch_data_buffer_hid(ipts_info_t *ipts)
-+{
-+	return &ipts->resource.touch_data_buffer_hid;
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_output_buffers_by_parallel_id(
-+							ipts_info_t *ipts,
-+                                                        int parallel_idx)
-+{
-+	return &ipts->resource.raw_data_mode_output_buffer[parallel_idx][0];
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_hid2me_buffer(ipts_info_t *ipts)
-+{
-+	return &ipts->resource.hid2me_buffer;
-+}
-+
-+static inline void ipts_set_wq_item_size(ipts_info_t *ipts, u8 size)
-+{
-+	ipts->resource.wq_item_size = size;
-+}
-+
-+static inline u8 ipts_get_wq_item_size(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.wq_item_size;
-+}
-+
-+static inline int ipts_get_num_of_parallel_buffers(const ipts_info_t *ipts)
-+{
-+	return ipts->num_of_parallel_data_buffers;
-+}
-+
-+#endif // _IPTS_H_
-diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
-index e4b10b2d1a08..883b185c9dbe 100644
---- a/drivers/misc/mei/hw-me-regs.h
-+++ b/drivers/misc/mei/hw-me-regs.h
-@@ -119,6 +119,7 @@
- 
- #define MEI_DEV_ID_SPT        0x9D3A  /* Sunrise Point */
- #define MEI_DEV_ID_SPT_2      0x9D3B  /* Sunrise Point 2 */
-+#define MEI_DEV_ID_SPT_4      0x9D3E  /* Sunrise Point 4 */
- #define MEI_DEV_ID_SPT_H      0xA13A  /* Sunrise Point H */
- #define MEI_DEV_ID_SPT_H_2    0xA13B  /* Sunrise Point H 2 */
- 
-diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
-index ea4e152270a3..4d301ba3f867 100644
---- a/drivers/misc/mei/pci-me.c
-+++ b/drivers/misc/mei/pci-me.c
-@@ -86,6 +86,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
- 
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
-+	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_4, MEI_ME_PCH8_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)},
-diff --git a/include/linux/intel_ipts_if.h b/include/linux/intel_ipts_if.h
-new file mode 100644
-index 000000000000..f329bbfb8079
---- /dev/null
-+++ b/include/linux/intel_ipts_if.h
-@@ -0,0 +1,75 @@
-+/*
-+ *
-+ * GFX interface to support Intel Precise Touch & Stylus
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef INTEL_IPTS_IF_H
-+#define INTEL_IPTS_IF_H
-+
-+enum {
-+	IPTS_INTERFACE_V1 = 1,
-+};
-+
-+#define IPTS_BUF_FLAG_CONTIGUOUS	0x01
-+
-+#define IPTS_NOTIFY_STA_BACKLIGHT_OFF	0x00
-+#define IPTS_NOTIFY_STA_BACKLIGHT_ON	0x01
-+
-+typedef struct intel_ipts_mapbuffer {
-+	u32	size;
-+	u32	flags;
-+	void	*gfx_addr;
-+	void	*cpu_addr;
-+	u64	buf_handle;
-+	u64	phy_addr;
-+} intel_ipts_mapbuffer_t;
-+
-+typedef struct intel_ipts_wq_info {
-+	u64 db_addr;
-+	u64 db_phy_addr;
-+	u32 db_cookie_offset;
-+	u32 wq_size;
-+	u64 wq_addr;
-+	u64 wq_phy_addr;
-+	u64 wq_head_addr;	/* head of wq is managed by GPU */
-+	u64 wq_head_phy_addr;	/* head of wq is managed by GPU */
-+	u64 wq_tail_addr;	/* tail of wq is managed by CSME */
-+	u64 wq_tail_phy_addr;	/* tail of wq is managed by CSME */
-+} intel_ipts_wq_info_t;
-+
-+typedef struct intel_ipts_ops {
-+	int (*get_wq_info)(uint64_t gfx_handle, intel_ipts_wq_info_t *wq_info);
-+	int (*map_buffer)(uint64_t gfx_handle, intel_ipts_mapbuffer_t *mapbuffer);
-+	int (*unmap_buffer)(uint64_t gfx_handle, uint64_t buf_handle);
-+} intel_ipts_ops_t;
-+
-+typedef struct intel_ipts_callback {
-+        void (*workload_complete)(void *data);
-+        void (*notify_gfx_status)(u32 status, void *data);
-+} intel_ipts_callback_t;
-+
-+typedef struct intel_ipts_connect {
-+        intel_ipts_callback_t ipts_cb;	/* input : callback addresses */
-+	void *data;			/* input : callback data */
-+        u32 if_version;			/* input : interface version */
-+
-+        u32 gfx_version;		/* output : gfx version */
-+        u64 gfx_handle;			/* output : gfx handle */
-+	intel_ipts_ops_t ipts_ops;	/* output : gfx ops for IPTS */
-+} intel_ipts_connect_t;
-+
-+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect);
-+void intel_ipts_disconnect(uint64_t gfx_handle);
-+
-+#endif // INTEL_IPTS_IF_H

+ 0 - 116
patches/4.16/keyboards_and_covers.patch

@@ -1,116 +0,0 @@
-diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
-index 9454ac1..ae2f26c 100644
---- a/drivers/hid/hid-ids.h
-+++ b/drivers/hid/hid-ids.h
-@@ -774,11 +774,22 @@
- #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1 0x0732
- #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_600  0x0750
- #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500	0x076c
--#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD 0x00e3
--#define USB_DEVICE_ID_MS_SURFACE_PRO_2   0x0799
--#define USB_DEVICE_ID_MS_TOUCH_COVER_2   0x07a7
--#define USB_DEVICE_ID_MS_TYPE_COVER_2    0x07a9
--#define USB_DEVICE_ID_MS_POWER_COVER     0x07da
-+#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD	0x00e3
-+#define USB_DEVICE_ID_MS_SURFACE_PRO_2		0x0799
-+#define USB_DEVICE_ID_MS_TOUCH_COVER_2		0x07a7
-+#define USB_DEVICE_ID_MS_TYPE_COVER_2		0x07a9
-+#define USB_DEVICE_ID_MS_TYPE_COVER_3		0x07de
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3	0x07dc
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1	0x07de
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2	0x07e2
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP	0x07dd
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4	0x07e8
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1	0x07e4
-+#define USB_DEVICE_ID_MS_SURFACE_BOOK		0x07cd
-+#define USB_DEVICE_ID_MS_SURFACE_BOOK_2		0x0922
-+#define USB_DEVICE_ID_MS_SURFACE_LAPTOP		0xf001
-+#define HID_DEVICE_ID_MS_SURFACE_LAPTOP		0xf001
-+#define USB_DEVICE_ID_MS_POWER_COVER		0x07da
- 
- #define USB_VENDOR_ID_MOJO		0x8282
- #define USB_DEVICE_ID_RETRO_ADAPTER	0x3201
-diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
-index 3b4739bd..82cee6c 100644
---- a/drivers/hid/hid-multitouch.c
-+++ b/drivers/hid/hid-multitouch.c
-@@ -1743,6 +1743,58 @@ static const struct hid_device_id mt_devices[] = {
- 		HID_USB_DEVICE(USB_VENDOR_ID_LG,
- 			USB_DEVICE_ID_LG_MELFAS_MT) },
- 
-+	/* Microsoft Touch Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_TOUCH_COVER_2) },
-+
-+	/* Microsoft Type Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_2) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_3) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_4) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1) },
-+
-+	/* Microsoft Surface Book */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_SURFACE_BOOK) },
-+
-+	/* Microsoft Surface Book 2 */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_SURFACE_BOOK_2) },
-+
-+	/* Microsoft Surface Laptop */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
-+			USB_VENDOR_ID_MICROSOFT,
-+			HID_DEVICE_ID_MS_SURFACE_LAPTOP) },
-+
-+	/* Microsoft Power Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_POWER_COVER) },
-+
- 	/* MosArt panels */
- 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
- 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
-diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
-index e92b77f..3cfadf1 100644
---- a/drivers/hid/hid-quirks.c
-+++ b/drivers/hid/hid-quirks.c
-@@ -110,6 +110,16 @@ static const struct hid_device_id hid_quirks[] = {
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK_2), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_LAPTOP), HID_QUIRK_NO_INIT_REPORTS },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER), HID_QUIRK_MULTI_INPUT },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL), HID_QUIRK_NO_INIT_REPORTS },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD), HID_QUIRK_MULTI_INPUT },

+ 0 - 20
patches/4.16/sdcard_reader.patch

@@ -1,20 +0,0 @@
-From fbd83f772a3be3a00bae323f6d71a59b26352c57 Mon Sep 17 00:00:00 2001
-From: Jake Day <jake@ninebysix.com>
-Date: Fri, 2 Feb 2018 11:22:21 -0500
-Subject: fix for surface sd card reader
-
-
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index cf7bbcb..826fdb8 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -4047,7 +4047,8 @@ void usb_enable_lpm(struct usb_device *udev)
- 	if (!udev || !udev->parent ||
- 			udev->speed < USB_SPEED_SUPER ||
- 			!udev->lpm_capable ||
--			udev->state < USB_STATE_DEFAULT)
-+			udev->state < USB_STATE_DEFAULT ||
-+			!udev->bos || !udev->bos->ss_cap)
- 		return;
- 
- 	udev->lpm_disable_count--;

+ 0 - 510
patches/4.16/surfaceacpi.patch

@@ -1,510 +0,0 @@
-diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
-index 51ebc5a..244fa92 100644
---- a/drivers/platform/x86/Kconfig
-+++ b/drivers/platform/x86/Kconfig
-@@ -1155,6 +1155,15 @@ config SURFACE_3_BUTTON
- 	---help---
- 	  This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet.
- 
-+config ACPI_SURFACE
-+	tristate "Microsoft Surface Extras"
-+	depends on ACPI
-+	depends on ACPI_WMI
-+	depends on INPUT
-+	---help---
-+	  This driver adds support for access to certain system events
-+	  on Microsoft Surface devices.
-+
- config INTEL_PUNIT_IPC
- 	tristate "Intel P-Unit IPC Driver"
- 	---help---
-diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
-index 2ba6cb7..bcb0dd9 100644
---- a/drivers/platform/x86/Makefile
-+++ b/drivers/platform/x86/Makefile
-@@ -81,6 +81,7 @@ obj-$(CONFIG_INTEL_PMC_IPC)	+= intel_pmc_ipc.o
- obj-$(CONFIG_SILEAD_DMI)	+= silead_dmi.o
- obj-$(CONFIG_SURFACE_PRO3_BUTTON)	+= surfacepro3_button.o
- obj-$(CONFIG_SURFACE_3_BUTTON)	+= surface3_button.o
-+obj-$(CONFIG_ACPI_SURFACE)	+= surface_acpi.o
- obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
- obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU)	+= intel_bxtwc_tmu.o
- obj-$(CONFIG_INTEL_TELEMETRY)	+= intel_telemetry_core.o \
-diff --git a/drivers/platform/x86/surface_acpi.c b/drivers/platform/x86/surface_acpi.c
-new file mode 100644
-index 0000000..bee15e7
---- /dev/null
-+++ b/drivers/platform/x86/surface_acpi.c
-@@ -0,0 +1,472 @@
-+/*
-+ *  surface_acpi.c - Microsoft Surface ACPI Notify
-+ *
-+ *  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.
-+ *
-+ *  The full GNU General Public License is included in this distribution in
-+ *  the file called "COPYING".
-+ */
-+
-+#define SURFACE_ACPI_VERSION	"0.1"
-+#define SURFACE_GEN_VERSION		0x08
-+#define PROC_SURFACE			"surface"
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/acpi.h>
-+#include <linux/power_supply.h>
-+#include <linux/thermal.h>
-+#include <linux/dmi.h>
-+#include <linux/seq_file.h>
-+#include <acpi/acpi_bus.h>
-+#include <acpi/acpi_drivers.h>
-+
-+MODULE_AUTHOR("Jake Day");
-+MODULE_DESCRIPTION("Microsoft Surface ACPI Notify Driver");
-+MODULE_LICENSE("GPL");
-+
-+#define SUR_METHOD_DSM			"_DSM"
-+#define SUR_METHOD_REG			"_REG"
-+#define SUR_METHOD_STA			"_STA"
-+#define SUR_METHOD_INI			"_INI"
-+#define SUR_METHOD_CRS			"_CRS"
-+
-+#define SUR_QUERY_DEVICE		0x00
-+#define SUR_SET_DVER			0x01
-+#define SUR_GET_BOARD_REVID		0x02
-+#define SUR_BAT1_STATE_CHANGE	0x03
-+#define SUR_BAT1_INFO_CHANGE	0x04
-+#define SUR_PSU_STATE_CHANGE	0x05
-+#define SUR_PSU_INFO_CHANGE		0x06
-+#define SUR_BAT2_STATE_CHANGE	0x07
-+#define SUR_BAT2_INFO_CHANGE	0x08
-+#define SUR_SENSOR_TRIP_POINT	0x09
-+
-+#define REG_AVAILABLE			0x01
-+#define REG_INIT				0x09
-+
-+static char SURFACE_EVENT_GUID[] = "93b666c5-70c6-469f-a215-3d487c91ab3c";
-+static char SUR_SAN_RQST[] = "\\_SB._SAN.RQST";
-+static char SUR_SAN_RQSX[] = "\\_SB._SAN.RQSX";
-+
-+struct surface_acpi_dev {
-+	acpi_handle handle;
-+	acpi_handle rqst_handle;
-+	acpi_handle rqsx_handle;
-+
-+	struct acpi_device *san_dev;
-+	struct acpi_device *ssh_dev;
-+	struct acpi_device *bat1_dev;
-+	struct acpi_device *bat2_dev;
-+	struct acpi_device *psu_dev;
-+
-+	unsigned int bat1_attached:1;
-+	unsigned int bat2_attached:1;
-+	unsigned int psu_registered:1;
-+};
-+
-+static struct surface_acpi_dev *surface_acpi;
-+
-+static struct proc_dir_entry *surface_proc_dir;
-+
-+static acpi_status surface_acpi_check_status(struct acpi_device *dev)
-+{
-+	unsigned long long value;
-+	acpi_status status;
-+
-+	if (acpi_has_method(dev->handle, SUR_METHOD_STA)) {
-+		status = acpi_evaluate_integer(dev->handle,
-+				SUR_METHOD_STA, NULL, &value);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static acpi_status surface_acpi_san_reg(void)
-+{
-+	union acpi_object in_objs[2], out_objs[1];
-+	struct acpi_object_list params;
-+	struct acpi_buffer results;
-+	acpi_status status;
-+
-+	params.count = ARRAY_SIZE(in_objs);
-+	params.pointer = in_objs;
-+	in_objs[0].type = ACPI_TYPE_INTEGER;
-+	in_objs[0].integer.value = REG_INIT;
-+	in_objs[1].type = ACPI_TYPE_INTEGER;
-+	in_objs[1].integer.value = REG_AVAILABLE;
-+	results.length = sizeof(out_objs);
-+	results.pointer = out_objs;
-+
-+	if (acpi_has_method(surface_acpi->handle, SUR_METHOD_REG)) {
-+		status = acpi_evaluate_object(surface_acpi->handle,
-+				SUR_METHOD_REG, &params, &results);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static acpi_status surface_acpi_event_handler(u32 event)
-+{
-+	union acpi_object in_objs[4], out_objs[5];
-+	struct acpi_object_list params;
-+	struct acpi_buffer results;
-+	acpi_status status;
-+
-+	params.count = ARRAY_SIZE(in_objs);
-+	params.pointer = in_objs;
-+	in_objs[0].type = ACPI_TYPE_BUFFER;
-+	in_objs[0].buffer.length = sizeof(SURFACE_EVENT_GUID);
-+	in_objs[0].buffer.pointer = SURFACE_EVENT_GUID;
-+	in_objs[1].type = ACPI_TYPE_INTEGER;
-+	in_objs[1].integer.value = SUR_QUERY_DEVICE;
-+	in_objs[2].type = ACPI_TYPE_INTEGER;
-+	in_objs[2].integer.value = event;
-+	in_objs[3].type = ACPI_TYPE_PACKAGE;
-+	in_objs[3].package.count = 0;
-+	in_objs[3].package.elements = SURFACE_GEN_VERSION;
-+	results.length = sizeof(out_objs);
-+	results.pointer = out_objs;
-+
-+	if (acpi_has_method(surface_acpi->handle, SUR_METHOD_DSM)) {
-+		status = acpi_evaluate_object(surface_acpi->handle,
-+				SUR_METHOD_DSM, &params, &results);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static void surface_acpi_san_load(void)
-+{
-+	acpi_status ret;
-+
-+	ret = surface_acpi_event_handler(SUR_SET_DVER);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error setting Driver Version\n");
-+
-+	ret = surface_acpi_event_handler(SUR_SENSOR_TRIP_POINT);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error setting Sensor Trip Point\n");
-+
-+	ret = surface_acpi_event_handler(SUR_BAT1_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error attaching BAT1\n");
-+	else
-+		surface_acpi->bat1_attached = 1;
-+
-+	ret = surface_acpi_event_handler(SUR_BAT2_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error attaching BAT2\n");
-+	else
-+		surface_acpi->bat2_attached = 1;
-+
-+	ret = surface_acpi_event_handler(SUR_PSU_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error registering PSU\n");
-+	else
-+		surface_acpi->psu_registered = 1;
-+}
-+
-+static acpi_status surface_acpi_ssh_initialize(void)
-+{
-+	acpi_status status;
-+
-+	if (acpi_has_method(surface_acpi->ssh_dev->handle, SUR_METHOD_INI)) {
-+		status = acpi_evaluate_object(surface_acpi->ssh_dev->handle,
-+				SUR_METHOD_INI, NULL, NULL);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static int bat1_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "attached: %d\n", surface_acpi->bat1_attached);
-+	return 0;
-+}
-+
-+static int bat1_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, bat1_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations bat1_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= bat1_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int bat2_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "attached: %d\n", surface_acpi->bat2_attached);
-+	return 0;
-+}
-+
-+static int bat2_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, bat2_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations bat2_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= bat2_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int psu_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "registered: %d\n", surface_acpi->psu_registered);
-+	return 0;
-+}
-+
-+static int psu_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, psu_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations psu_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= psu_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int version_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "driver: %s\n", SURFACE_ACPI_VERSION);
-+	return 0;
-+}
-+
-+static int version_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, version_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations version_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= version_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static void create_surface_proc_entries(void)
-+{
-+	proc_create_data("BAT1", 0, surface_proc_dir,
-+			 &bat1_proc_fops, surface_acpi->bat1_attached);
-+	proc_create_data("BAT2", 0, surface_proc_dir,
-+			 &bat2_proc_fops, surface_acpi->bat2_attached);
-+	proc_create_data("ADP1", 0, surface_proc_dir,
-+			 &psu_proc_fops, surface_acpi->psu_registered);
-+	proc_create_data("version", 0, surface_proc_dir,
-+			 &version_proc_fops, SURFACE_ACPI_VERSION);
-+}
-+
-+static void remove_surface_proc_entries(void)
-+{
-+	remove_proc_entry("BAT1", surface_proc_dir);
-+	remove_proc_entry("BAT2", surface_proc_dir);
-+	remove_proc_entry("ADP1", surface_proc_dir);
-+	remove_proc_entry("version", surface_proc_dir);
-+}
-+
-+static void surface_acpi_notify(struct acpi_device *dev, u32 event)
-+{
-+	pr_info("surface_acpi: Event received %x\n", event);
-+}
-+
-+static void surface_acpi_register_rqst_handler(void)
-+{
-+	acpi_status status;
-+
-+	status = acpi_get_handle(NULL, SUR_SAN_RQST, &surface_acpi->rqst_handle);
-+	if (ACPI_FAILURE(status)) {
-+		pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+	}
-+}
-+
-+static void surface_acpi_register_rqsx_handler(void)
-+{
-+	acpi_status status;
-+
-+	status = acpi_get_handle(NULL, SUR_SAN_RQSX, &surface_acpi->rqsx_handle);
-+	if (ACPI_FAILURE(status)) {
-+		pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+	}
-+}
-+
-+static acpi_status surface_acpi_walk_callback(acpi_handle handle, u32 level,
-+						void *context, void **return_value)
-+{
-+	struct acpi_device_info *info;
-+
-+	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
-+		pr_warn("method: name: %4.4s, args %X\n",
-+			(char *)&info->name, info->param_count);
-+
-+		kfree(info);
-+	}
-+
-+	return AE_OK;
-+}
-+
-+static void surface_acpi_walk_namespace(struct acpi_device *dev)
-+{
-+	acpi_status status;
-+
-+	status = acpi_walk_namespace(ACPI_TYPE_METHOD,
-+			dev->handle, 1, surface_acpi_walk_callback,
-+			NULL, NULL, NULL);
-+	if (ACPI_FAILURE(status))
-+		pr_warn("surface_acpi: Unable to walk acpi resources\n");
-+}
-+
-+static int surface_acpi_add(struct acpi_device *dev)
-+{
-+	if (!surface_acpi)
-+	{
-+		surface_acpi = kzalloc(sizeof(*surface_acpi), GFP_KERNEL);
-+		if (!surface_acpi)
-+			return AE_NO_MEMORY;
-+	}
-+
-+	if (acpi_has_method(dev->handle, SUR_METHOD_DSM))
-+	{
-+		pr_info("surface_acpi: Attaching device MSHW0091\n");
-+
-+		surface_acpi->san_dev = dev;
-+		surface_acpi->handle = dev->handle;
-+
-+		surface_acpi_walk_namespace(surface_acpi->san_dev);
-+		surface_acpi_check_status(surface_acpi->san_dev);
-+
-+		surface_acpi_register_rqst_handler();
-+		surface_acpi_register_rqsx_handler();
-+
-+		surface_acpi_san_reg();
-+		surface_acpi_san_load();
-+
-+		create_surface_proc_entries();
-+	}
-+	else
-+	{
-+		pr_info("surface_acpi: Attaching device MSHW0084\n");
-+
-+		surface_acpi->ssh_dev = dev;
-+
-+		surface_acpi_walk_namespace(surface_acpi->ssh_dev);
-+		surface_acpi_check_status(surface_acpi->ssh_dev);
-+
-+		surface_acpi_ssh_initialize();
-+		//surface_acpi_ssh_load();
-+	}
-+
-+	return AE_OK;
-+}
-+
-+static int surface_acpi_remove(struct acpi_device *dev)
-+{
-+	remove_surface_proc_entries();
-+
-+	return AE_OK;
-+}
-+
-+static const struct acpi_device_id surface_device_ids[] = {
-+	{"MSHW0091", 0},
-+	{"MSHW0084", 0},
-+	{"", 0},
-+};
-+MODULE_DEVICE_TABLE(acpi, surface_device_ids);
-+
-+static struct acpi_driver surface_acpi_driver = {
-+	.name	= "surface_acpi",
-+	.owner	= THIS_MODULE,
-+	.ids	= surface_device_ids,
-+	.flags	= ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-+	.ops	= {
-+		.add	= surface_acpi_add,
-+		.remove = surface_acpi_remove,
-+		.notify = surface_acpi_notify,
-+	},
-+};
-+
-+static int __init surface_acpi_init(void)
-+{
-+	int ret;
-+
-+	pr_info("surface_acpi: Microsoft Surface ACPI Notify version %s\n",
-+	       SURFACE_ACPI_VERSION);
-+
-+	surface_proc_dir = proc_mkdir(PROC_SURFACE, acpi_root_dir);
-+	if (!surface_proc_dir) {
-+		pr_err("surface_acpi: Unable to create proc dir " PROC_SURFACE "\n");
-+		return -ENODEV;
-+	}
-+
-+	ret = acpi_bus_register_driver(&surface_acpi_driver);
-+	if (ret) {
-+		pr_err("surface_acpi: Failed to register ACPI driver: %d\n", ret);
-+		remove_proc_entry(PROC_SURFACE, acpi_root_dir);
-+	}
-+
-+	return ret;
-+}
-+
-+static void __exit surface_acpi_exit(void)
-+{
-+	acpi_bus_unregister_driver(&surface_acpi_driver);
-+	if (surface_proc_dir)
-+		remove_proc_entry(PROC_SURFACE, acpi_root_dir);
-+}
-+
-+module_init(surface_acpi_init);
-+module_exit(surface_acpi_exit);

+ 0 - 36
patches/4.16/surfacedock.patch

@@ -1,36 +0,0 @@
-From 3600aaa37a16777a07aa34672f12e30a1ae4d95b Mon Sep 17 00:00:00 2001
-From: Jake Day <jake@ninebysix.com>
-Date: Fri, 2 Feb 2018 11:21:06 -0500
-Subject: support for surface dock
-
-
-diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
-index 05dca3e..59c2fcc 100644
---- a/drivers/net/usb/cdc_ether.c
-+++ b/drivers/net/usb/cdc_ether.c
-@@ -807,13 +807,6 @@ static const struct usb_device_id	products[] = {
- 	.driver_info = 0,
- },
- 
--/* Microsoft Surface 3 dock (based on Realtek RTL8153) */
--{
--	USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM,
--			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
--	.driver_info = 0,
--},
--
- 	/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
- {
- 	USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
-diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
-index 0657203..0a52ea0 100644
---- a/drivers/net/usb/r8152.c
-+++ b/drivers/net/usb/r8152.c
-@@ -5323,7 +5323,6 @@ static const struct usb_device_id rtl8152_table[] = {
- 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)},
--	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x304f)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3062)},

+ 0 - 3
patches/4.16/wifi.patch

@@ -1,3 +0,0 @@
-diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl
-old mode 100755
-new mode 100644

+ 0 - 1324
patches/4.17/acpi.patch

@@ -1,1324 +0,0 @@
-diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
-index 566644bb496a..081105a9cfca 100644
---- a/drivers/platform/x86/Kconfig
-+++ b/drivers/platform/x86/Kconfig
-@@ -1158,6 +1158,15 @@ config SURFACE_3_BUTTON
- 	---help---
- 	  This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet.
- 
-+config ACPI_SURFACE
-+	tristate "Microsoft Surface Extras"
-+	depends on ACPI
-+	depends on ACPI_WMI
-+	depends on INPUT
-+	---help---
-+	  This driver adds support for access to certain system events
-+	  on Microsoft Surface devices.
-+
- config INTEL_PUNIT_IPC
- 	tristate "Intel P-Unit IPC Driver"
- 	---help---
-diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
-index 2ba6cb795338..8fd5b93bb20d 100644
---- a/drivers/platform/x86/Makefile
-+++ b/drivers/platform/x86/Makefile
-@@ -81,6 +81,9 @@ obj-$(CONFIG_INTEL_PMC_IPC)	+= intel_pmc_ipc.o
- obj-$(CONFIG_SILEAD_DMI)	+= silead_dmi.o
- obj-$(CONFIG_SURFACE_PRO3_BUTTON)	+= surfacepro3_button.o
- obj-$(CONFIG_SURFACE_3_BUTTON)	+= surface3_button.o
-+obj-$(CONFIG_ACPI_SURFACE)	+= surface_acpi.o
-+obj-$(CONFIG_ACPI_SURFACE)	+= surface_i2c.o
-+obj-$(CONFIG_ACPI_SURFACE)	+= surface_platform.o
- obj-$(CONFIG_INTEL_PUNIT_IPC)  += intel_punit_ipc.o
- obj-$(CONFIG_INTEL_BXTWC_PMIC_TMU)	+= intel_bxtwc_tmu.o
- obj-$(CONFIG_INTEL_TELEMETRY)	+= intel_telemetry_core.o \
-diff --git a/drivers/platform/x86/surface_acpi.c b/drivers/platform/x86/surface_acpi.c
-new file mode 100644
-index 000000000000..c969bda99464
---- /dev/null
-+++ b/drivers/platform/x86/surface_acpi.c
-@@ -0,0 +1,485 @@
-+/*
-+ *  surface_acpi.c - Microsoft Surface ACPI Driver
-+ *
-+ *  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.
-+ *
-+ *  The full GNU General Public License is included in this distribution in
-+ *  the file called "COPYING".
-+ */
-+
-+#define SURFACE_ACPI_VERSION	"0.1"
-+#define SURFACE_GEN_VERSION		0x08
-+#define PROC_SURFACE			"surface"
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/types.h>
-+#include <linux/acpi.h>
-+#include <linux/power_supply.h>
-+#include <linux/thermal.h>
-+#include <linux/dmi.h>
-+#include <linux/seq_file.h>
-+#include <acpi/acpi_bus.h>
-+#include <acpi/acpi_drivers.h>
-+
-+#include "surface_acpi.h"
-+
-+#define SUR_METHOD_DSM			"_DSM"
-+#define SUR_METHOD_REG			"_REG"
-+#define SUR_METHOD_STA			"_STA"
-+#define SUR_METHOD_INI			"_INI"
-+#define SUR_METHOD_CRS			"_CRS"
-+
-+#define SUR_QUERY_DEVICE		0x00
-+#define SUR_SET_DVER			0x01
-+#define SUR_GET_BOARD_REVID		0x02
-+#define SUR_BAT1_STATE_CHANGE	0x03
-+#define SUR_BAT1_INFO_CHANGE	0x04
-+#define SUR_PSU_STATE_CHANGE	0x05
-+#define SUR_PSU_INFO_CHANGE		0x06
-+#define SUR_BAT2_STATE_CHANGE	0x07
-+#define SUR_BAT2_INFO_CHANGE	0x08
-+#define SUR_SENSOR_TRIP_POINT	0x09
-+
-+#define REG_AVAILABLE			0x01
-+#define REG_INIT				0x09
-+
-+static char SURFACE_EVENT_GUID[] = "93b666c5-70c6-469f-a215-3d487c91ab3c";
-+static char SUR_SAN_RQST[] = "\\_SB._SAN.RQST";
-+static char SUR_SAN_RQSX[] = "\\_SB._SAN.RQSX";
-+
-+struct surface_acpi_dev {
-+	acpi_handle handle;
-+	acpi_handle rqst_handle;
-+	acpi_handle rqsx_handle;
-+
-+	struct acpi_device *san_dev;
-+	struct acpi_device *ssh_dev;
-+	struct acpi_device *bat1_dev;
-+	struct acpi_device *bat2_dev;
-+	struct acpi_device *psu_dev;
-+
-+	unsigned int bat1_attached:1;
-+	unsigned int bat2_attached:1;
-+	unsigned int psu_registered:1;
-+};
-+
-+static struct surface_acpi_dev *surface_acpi;
-+
-+static struct proc_dir_entry *surface_proc_dir;
-+
-+static acpi_status surface_acpi_check_status(struct acpi_device *dev)
-+{
-+	unsigned long long value;
-+	acpi_status status;
-+
-+	if (acpi_has_method(dev->handle, SUR_METHOD_STA)) {
-+		status = acpi_evaluate_integer(dev->handle,
-+				SUR_METHOD_STA, NULL, &value);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static acpi_status surface_acpi_san_reg(void)
-+{
-+	union acpi_object in_objs[2], out_objs[1];
-+	struct acpi_object_list params;
-+	struct acpi_buffer results;
-+	acpi_status status;
-+
-+	params.count = ARRAY_SIZE(in_objs);
-+	params.pointer = in_objs;
-+	in_objs[0].type = ACPI_TYPE_INTEGER;
-+	in_objs[0].integer.value = REG_INIT;
-+	in_objs[1].type = ACPI_TYPE_INTEGER;
-+	in_objs[1].integer.value = REG_AVAILABLE;
-+	results.length = sizeof(out_objs);
-+	results.pointer = out_objs;
-+
-+	if (acpi_has_method(surface_acpi->handle, SUR_METHOD_REG)) {
-+		status = acpi_evaluate_object(surface_acpi->handle,
-+				SUR_METHOD_REG, &params, &results);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+acpi_status surface_acpi_event_handler(u32 event)
-+{
-+	union acpi_object in_objs[4], out_objs[5];
-+	struct acpi_object_list params;
-+	struct acpi_buffer results;
-+	acpi_status status;
-+
-+	params.count = ARRAY_SIZE(in_objs);
-+	params.pointer = in_objs;
-+	in_objs[0].type = ACPI_TYPE_BUFFER;
-+	in_objs[0].buffer.length = sizeof(SURFACE_EVENT_GUID);
-+	in_objs[0].buffer.pointer = SURFACE_EVENT_GUID;
-+	in_objs[1].type = ACPI_TYPE_INTEGER;
-+	in_objs[1].integer.value = SUR_QUERY_DEVICE;
-+	in_objs[2].type = ACPI_TYPE_INTEGER;
-+	in_objs[2].integer.value = event;
-+	in_objs[3].type = ACPI_TYPE_PACKAGE;
-+	in_objs[3].package.count = 0;
-+	in_objs[3].package.elements = SURFACE_GEN_VERSION;
-+	results.length = sizeof(out_objs);
-+	results.pointer = out_objs;
-+
-+	if (acpi_has_method(surface_acpi->handle, SUR_METHOD_DSM)) {
-+		status = acpi_evaluate_object(surface_acpi->handle,
-+				SUR_METHOD_DSM, &params, &results);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+EXPORT_SYMBOL(surface_acpi_event_handler);
-+
-+static void surface_acpi_san_load(void)
-+{
-+	acpi_status ret;
-+
-+	ret = surface_acpi_event_handler(SUR_SET_DVER);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error setting Driver Version\n");
-+
-+	ret = surface_acpi_event_handler(SUR_SENSOR_TRIP_POINT);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error setting Sensor Trip Point\n");
-+
-+	ret = surface_acpi_event_handler(SUR_BAT1_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error attaching BAT1\n");
-+	else
-+		surface_acpi->bat1_attached = 1;
-+
-+	ret = surface_acpi_event_handler(SUR_BAT2_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error attaching BAT2\n");
-+	else
-+		surface_acpi->bat2_attached = 1;
-+
-+	ret = surface_acpi_event_handler(SUR_PSU_INFO_CHANGE);
-+	if (ACPI_FAILURE(ret))
-+		pr_err("surface_acpi: Error registering PSU\n");
-+	else
-+		surface_acpi->psu_registered = 1;
-+}
-+
-+static acpi_status surface_acpi_ssh_initialize(void)
-+{
-+	acpi_status status;
-+
-+	if (acpi_has_method(surface_acpi->ssh_dev->handle, SUR_METHOD_INI)) {
-+		status = acpi_evaluate_object(surface_acpi->ssh_dev->handle,
-+				SUR_METHOD_INI, NULL, NULL);
-+
-+		if (ACPI_FAILURE(status)) {
-+			pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+			return AE_ERROR;
-+		}
-+	}
-+	else
-+		return AE_NOT_FOUND;
-+
-+	return AE_OK;
-+}
-+
-+static int bat1_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "attached: %d\n", surface_acpi->bat1_attached);
-+	return 0;
-+}
-+
-+static int bat1_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, bat1_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations bat1_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= bat1_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int bat2_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "attached: %d\n", surface_acpi->bat2_attached);
-+	return 0;
-+}
-+
-+static int bat2_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, bat2_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations bat2_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= bat2_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int psu_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "registered: %d\n", surface_acpi->psu_registered);
-+	return 0;
-+}
-+
-+static int psu_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, psu_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations psu_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= psu_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int version_proc_show(struct seq_file *m, void *v)
-+{
-+	seq_printf(m, "driver: %s\n", SURFACE_ACPI_VERSION);
-+	return 0;
-+}
-+
-+static int version_proc_open(struct inode *inode, struct file *file)
-+{
-+	return single_open(file, version_proc_show, PDE_DATA(inode));
-+}
-+
-+static const struct file_operations version_proc_fops = {
-+	.owner		= THIS_MODULE,
-+	.open		= version_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static void create_surface_proc_entries(void)
-+{
-+	proc_create_data("BAT1", 0, surface_proc_dir,
-+			 &bat1_proc_fops, surface_acpi->bat1_attached);
-+	proc_create_data("BAT2", 0, surface_proc_dir,
-+			 &bat2_proc_fops, surface_acpi->bat2_attached);
-+	proc_create_data("ADP1", 0, surface_proc_dir,
-+			 &psu_proc_fops, surface_acpi->psu_registered);
-+	proc_create_data("version", 0, surface_proc_dir,
-+			 &version_proc_fops, SURFACE_ACPI_VERSION);
-+}
-+
-+static void remove_surface_proc_entries(void)
-+{
-+	remove_proc_entry("BAT1", surface_proc_dir);
-+	remove_proc_entry("BAT2", surface_proc_dir);
-+	remove_proc_entry("ADP1", surface_proc_dir);
-+	remove_proc_entry("version", surface_proc_dir);
-+}
-+
-+static void surface_acpi_notify(struct acpi_device *dev, u32 event)
-+{
-+	pr_info("surface_acpi: Event received %x\n", event);
-+}
-+
-+static void surface_acpi_register_rqst_handler(void)
-+{
-+	acpi_status status;
-+
-+	status = acpi_get_handle(NULL, SUR_SAN_RQST, &surface_acpi->rqst_handle);
-+	if (ACPI_FAILURE(status)) {
-+		pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+	}
-+}
-+
-+static void surface_acpi_register_rqsx_handler(void)
-+{
-+	acpi_status status;
-+
-+	status = acpi_get_handle(NULL, SUR_SAN_RQSX, &surface_acpi->rqsx_handle);
-+	if (ACPI_FAILURE(status)) {
-+		pr_err("surface_acpi: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+	}
-+}
-+
-+static acpi_status surface_acpi_walk_callback(acpi_handle handle, u32 level,
-+						void *context, void **return_value)
-+{
-+	struct acpi_device_info *info;
-+
-+	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
-+		pr_warn("method: name: %4.4s, args %X\n",
-+			(char *)&info->name, info->param_count);
-+
-+		kfree(info);
-+	}
-+
-+	return AE_OK;
-+}
-+
-+static void surface_acpi_walk_namespace(struct acpi_device *dev)
-+{
-+	acpi_status status;
-+
-+	status = acpi_walk_namespace(ACPI_TYPE_METHOD,
-+			dev->handle, 1, surface_acpi_walk_callback,
-+			NULL, NULL, NULL);
-+	if (ACPI_FAILURE(status))
-+		pr_warn("surface_acpi: Unable to walk acpi resources\n");
-+}
-+
-+static int surface_acpi_add(struct acpi_device *dev)
-+{
-+	if (!surface_acpi)
-+	{
-+		surface_acpi = kzalloc(sizeof(*surface_acpi), GFP_KERNEL);
-+		if (!surface_acpi)
-+			return AE_NO_MEMORY;
-+	}
-+
-+	if (acpi_has_method(dev->handle, SUR_METHOD_DSM))
-+	{
-+		pr_info("surface_acpi: Attaching device MSHW0091\n");
-+
-+		surface_acpi->san_dev = dev;
-+		surface_acpi->handle = dev->handle;
-+
-+		surface_acpi_walk_namespace(surface_acpi->san_dev);
-+		surface_acpi_check_status(surface_acpi->san_dev);
-+
-+		surface_acpi_register_rqst_handler();
-+		surface_acpi_register_rqsx_handler();
-+
-+		surface_acpi_san_reg();
-+		surface_acpi_san_load();
-+
-+		create_surface_proc_entries();
-+	}
-+	else if (acpi_has_method(dev->handle, SUR_METHOD_CRS))
-+	{
-+		pr_info("surface_acpi: Attaching device MSHW0084\n");
-+
-+		surface_acpi->ssh_dev = dev;
-+
-+		surface_acpi_walk_namespace(surface_acpi->ssh_dev);
-+		surface_acpi_check_status(surface_acpi->ssh_dev);
-+
-+		surface_acpi_ssh_initialize();
-+		//surface_acpi_ssh_load();
-+	}
-+	else
-+	{
-+		pr_info("surface_acpi: Attaching device\n");
-+	}
-+
-+	device_init_wakeup(&dev->dev, true);
-+
-+	return AE_OK;
-+}
-+
-+static int surface_acpi_remove(struct acpi_device *dev)
-+{
-+	remove_surface_proc_entries();
-+
-+	return AE_OK;
-+}
-+
-+static const struct acpi_device_id surface_device_ids[] = {
-+	{"MSHW0084", 0},
-+	{"MSHW0091", 0},
-+	{"MSHW0124", 0},
-+	{"INT3403", 0},
-+	{"LNXTHERM", 0},
-+	{"PNP0C0A", 0},
-+	{"", 0},
-+};
-+MODULE_DEVICE_TABLE(acpi, surface_device_ids);
-+
-+static struct acpi_driver surface_acpi_driver = {
-+	.name	= "surface_acpi",
-+	.owner	= THIS_MODULE,
-+	.ids	= surface_device_ids,
-+	.flags	= ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-+	.ops	= {
-+		.add	= surface_acpi_add,
-+		.remove = surface_acpi_remove,
-+		.notify = surface_acpi_notify,
-+	},
-+};
-+
-+static int __init surface_acpi_init(void)
-+{
-+	int ret;
-+
-+	pr_info("surface_acpi: Microsoft Surface ACPI Driver version %s\n",
-+	       SURFACE_ACPI_VERSION);
-+
-+	surface_proc_dir = proc_mkdir(PROC_SURFACE, acpi_root_dir);
-+	if (!surface_proc_dir) {
-+		pr_err("surface_acpi: Unable to create proc dir " PROC_SURFACE "\n");
-+		return -ENODEV;
-+	}
-+
-+	ret = acpi_bus_register_driver(&surface_acpi_driver);
-+	if (ret) {
-+		pr_err("surface_acpi: Failed to register ACPI driver: %d\n", ret);
-+		remove_proc_entry(PROC_SURFACE, acpi_root_dir);
-+	}
-+
-+	return ret;
-+}
-+
-+static void __exit surface_acpi_exit(void)
-+{
-+	acpi_bus_unregister_driver(&surface_acpi_driver);
-+	if (surface_proc_dir)
-+		remove_proc_entry(PROC_SURFACE, acpi_root_dir);
-+}
-+
-+module_init(surface_acpi_init);
-+module_exit(surface_acpi_exit);
-+
-+MODULE_AUTHOR("Jake Day");
-+MODULE_DESCRIPTION("Microsoft Surface ACPI Driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/platform/x86/surface_acpi.h b/drivers/platform/x86/surface_acpi.h
-new file mode 100644
-index 000000000000..5b6627c4d6f1
---- /dev/null
-+++ b/drivers/platform/x86/surface_acpi.h
-@@ -0,0 +1,18 @@
-+/*
-+ *  surface_acpi.h - Microsoft Surface ACPI Driver
-+ *
-+ *  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.
-+ *
-+ *  The full GNU General Public License is included in this distribution in
-+ *  the file called "COPYING".
-+ */
-+
-+acpi_status surface_acpi_event_handler(u32 event);
-diff --git a/drivers/platform/x86/surface_i2c.c b/drivers/platform/x86/surface_i2c.c
-new file mode 100644
-index 000000000000..fb2cf0cae72f
---- /dev/null
-+++ b/drivers/platform/x86/surface_i2c.c
-@@ -0,0 +1,696 @@
-+/*
-+ *  surface_i2c.c - Microsoft Surface I2C Driver
-+ *
-+ *  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.
-+ *
-+ *  The full GNU General Public License is included in this distribution in
-+ *  the file called "COPYING".
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/i2c.h>
-+#include <linux/slab.h>
-+#include <linux/acpi.h>
-+#include <linux/module.h>
-+#include <linux/uuid.h>
-+#include <linux/kthread.h>
-+#include <linux/freezer.h>
-+#include <asm/unaligned.h>
-+
-+#include "surface_acpi.h"
-+
-+#define POLL_INTERVAL		(HZ * 2)
-+
-+struct surface_i2c_data {
-+	struct i2c_client *adp1;
-+	struct i2c_client *bat0;
-+	unsigned short notify_version;
-+	struct task_struct *poll_task;
-+	bool kthread_running;
-+	bool charging;
-+	bool bat_charging;
-+	u8 trip_point;
-+	s32 full_capacity;
-+};
-+
-+struct surface_i2c_lookup {
-+	struct surface_i2c_data	*cdata;
-+	unsigned int n;
-+	unsigned int index;
-+	int addr;
-+};
-+
-+struct surface_i2c_handler_data {
-+	struct acpi_connection_info info;
-+	struct i2c_client *client;
-+};
-+
-+struct bix {
-+	u32	revision;
-+	u32	power_unit;
-+	u32	design_capacity;
-+	u32	last_full_charg_capacity;
-+	u32	battery_technology;
-+	u32	design_voltage;
-+	u32	design_capacity_of_warning;
-+	u32	design_capacity_of_low;
-+	u32	cycle_count;
-+	u32	measurement_accuracy;
-+	u32	max_sampling_time;
-+	u32	min_sampling_time;
-+	u32	max_average_interval;
-+	u32	min_average_interval;
-+	u32	battery_capacity_granularity_1;
-+	u32	battery_capacity_granularity_2;
-+	char model[10];
-+	char serial[10];
-+	char type[10];
-+	char OEM[10];
-+} __packed;
-+
-+struct bst {
-+	u32 battery_state;
-+	s32 battery_present_rate;
-+	u32 battery_remaining_capacity;
-+	u32 battery_present_voltage;
-+} __packed;
-+
-+struct gsb_command {
-+	u8 arg0;
-+	u8 arg1;
-+	u8 arg2;
-+} __packed;
-+
-+struct gsb_buffer {
-+	u8 status;
-+	u8 len;
-+	u8 ret;
-+	union {
-+		struct gsb_command cmd;
-+		struct bst bst;
-+		struct bix bix;
-+	} __packed;
-+} __packed;
-+
-+#define ACPI_BATTERY_STATE_DISCHARGING	0x1
-+#define ACPI_BATTERY_STATE_CHARGING		0x2
-+#define ACPI_BATTERY_STATE_CRITICAL		0x4
-+
-+#define surface_i2c_CMD_DEST_BAT0		0x01
-+#define surface_i2c_CMD_DEST_ADP1		0x03
-+
-+#define surface_i2c_CMD_BAT0_STA		0x01
-+#define surface_i2c_CMD_BAT0_BIX		0x02
-+#define surface_i2c_CMD_BAT0_BCT		0x03
-+#define surface_i2c_CMD_BAT0_BTM		0x04
-+#define surface_i2c_CMD_BAT0_BST		0x05
-+#define surface_i2c_CMD_BAT0_BTP		0x06
-+#define surface_i2c_CMD_ADP1_PSR		0x07
-+#define surface_i2c_CMD_BAT0_PSOC		0x09
-+#define surface_i2c_CMD_BAT0_PMAX		0x0A
-+#define surface_i2c_CMD_BAT0_PSRC		0x0B
-+#define surface_i2c_CMD_BAT0_CHGI		0x0C
-+#define surface_i2c_CMD_BAT0_ARTG		0x0D
-+
-+#define surface_i2c_NOTIFY_GET_VERSION	0x00
-+#define surface_i2c_NOTIFY_ADP1			0x01
-+#define surface_i2c_NOTIFY_BAT0_BST		0x02
-+#define surface_i2c_NOTIFY_BAT0_BIX		0x05
-+
-+#define surface_i2c_ADP1_REG_PSR		0x03
-+
-+#define surface_i2c_BAT0_REG_CAPACITY			0x0c
-+#define surface_i2c_BAT0_REG_FULL_CHG_CAPACITY	0x0e
-+#define surface_i2c_BAT0_REG_DESIGN_CAPACITY	0x40
-+#define surface_i2c_BAT0_REG_VOLTAGE			0x08
-+#define surface_i2c_BAT0_REG_RATE				0x14
-+#define surface_i2c_BAT0_REG_OEM				0x45
-+#define surface_i2c_BAT0_REG_TYPE				0x4e
-+#define surface_i2c_BAT0_REG_SERIAL_NO			0x56
-+#define surface_i2c_BAT0_REG_CYCLE_CNT			0x6e
-+
-+#define surface_i2c_EV_2_5				0x1ff
-+
-+static int surface_i2c_read_block(struct i2c_client *client, u8 reg, u8 *buf,
-+				   int len)
-+{
-+	int status, i;
-+
-+	for (i = 0; i < len; i++) {
-+		status = i2c_smbus_read_byte_data(client, reg + i);
-+		if (status < 0) {
-+			buf[i] = 0xff;
-+			continue;
-+		}
-+
-+		buf[i] = (u8)status;
-+	}
-+
-+	return 0;
-+}
-+
-+static int
-+surface_i2c_notify(struct surface_i2c_data *cdata, u8 arg1, u8 arg2,
-+		unsigned int *ret_value)
-+{
-+	/*static const guid_t surface_i2c_guid =
-+	GUID_INIT(0x93b666c5, 0x70c6, 0x469f,
-+		  0xa2, 0x15, 0x3d, 0x48, 0x7c, 0x91, 0xab, 0x3c);*/
-+
-+	struct acpi_device *adev;
-+	acpi_handle handle;
-+	acpi_status status;
-+
-+	handle = ACPI_HANDLE(&cdata->adp1->dev);
-+	if (!handle || acpi_bus_get_device(handle, &adev))
-+		return -ENODEV;
-+
-+	*ret_value = 0;
-+
-+	status = surface_acpi_event_handler(arg2);
-+	if (ACPI_FAILURE(status)) {
-+		pr_err("surface_i2c: ACPI event failure status %s\n",
-+					acpi_format_exception(status));
-+	}
-+
-+	return 0;
-+}
-+
-+static const struct bix default_bix = {
-+	.revision = 0x00,
-+	.power_unit = 0x00,
-+	.design_capacity = 0x1734,
-+	.last_full_charg_capacity = 0x1734,
-+	.battery_technology = 0x01,
-+	.design_voltage = 0x1d92,
-+	.design_capacity_of_warning = 0xc8,
-+	.design_capacity_of_low = 0xc8,
-+	.battery_capacity_granularity_1 = 0x45,
-+	.battery_capacity_granularity_2 = 0x11,
-+	.cycle_count = 0x01,
-+	.measurement_accuracy = 0x00015F90,
-+	.max_sampling_time = 0x03E8,
-+	.min_sampling_time = 0x03E8,
-+	.max_average_interval = 0x03E8,
-+	.min_average_interval = 0x03E8,
-+	.model = "PNP0C0A",
-+	.serial = "1234567890",
-+	.type = "SDS-BAT",
-+	.OEM = "MICROSOFT",
-+};
-+
-+static int surface_i2c_bix(struct surface_i2c_data *cdata, struct bix *bix)
-+{
-+	struct i2c_client *client = cdata->bat0;
-+	int ret;
-+	char buf[10];
-+
-+	*bix = default_bix;
-+
-+	/* get design capacity */
-+	ret = i2c_smbus_read_word_data(client, surface_i2c_BAT0_REG_DESIGN_CAPACITY);
-+	if (ret < 0) {
-+		dev_err(&client->dev, "Error reading design capacity: %d\n", ret);
-+		return ret;
-+	}
-+	bix->design_capacity = le16_to_cpu(ret);
-+
-+	/* get last full charge capacity */
-+	ret = i2c_smbus_read_word_data(client, surface_i2c_BAT0_REG_FULL_CHG_CAPACITY);
-+	if (ret < 0) {
-+		dev_err(&client->dev, "Error reading last full charge capacity: %d\n", ret);
-+		return ret;
-+	}
-+	bix->last_full_charg_capacity = le16_to_cpu(ret);
-+
-+	/* get serial number */
-+	ret = surface_i2c_read_block(client, surface_i2c_BAT0_REG_SERIAL_NO,
-+				      buf, 10);
-+	if (ret) {
-+		dev_err(&client->dev, "Error reading serial no: %d\n", ret);
-+		return ret;
-+	}
-+	memcpy(bix->serial, buf + 7, 3);
-+	memcpy(bix->serial + 3, buf, 6);
-+	bix->serial[9] = '\0';
-+
-+	/* get cycle count */
-+	ret = i2c_smbus_read_word_data(client, surface_i2c_BAT0_REG_CYCLE_CNT);
-+	if (ret < 0) {
-+		dev_err(&client->dev, "Error reading cycle count: %d\n", ret);
-+		return ret;
-+	}
-+	bix->cycle_count = le16_to_cpu(ret);
-+
-+	/* get OEM name */
-+	ret = surface_i2c_read_block(client, surface_i2c_BAT0_REG_OEM, buf, 4);
-+	if (ret) {
-+		dev_err(&client->dev, "Error reading cycle count: %d\n", ret);
-+		return ret;
-+	}
-+	memcpy(bix->OEM, buf, 3);
-+	bix->OEM[4] = '\0';
-+
-+	return 0;
-+}
-+
-+static int surface_i2c_bst(struct surface_i2c_data *cdata, struct bst *bst)
-+{
-+	struct i2c_client *client = cdata->bat0;
-+	int rate, capacity, voltage, state;
-+	s16 tmp;
-+
-+	rate = i2c_smbus_read_word_data(client, surface_i2c_BAT0_REG_RATE);
-+	if (rate < 0)
-+		return rate;
-+
-+	capacity = i2c_smbus_read_word_data(client, surface_i2c_BAT0_REG_CAPACITY);
-+	if (capacity < 0)
-+		return capacity;
-+
-+	voltage = i2c_smbus_read_word_data(client, surface_i2c_BAT0_REG_VOLTAGE);
-+	if (voltage < 0)
-+		return voltage;
-+
-+	tmp = le16_to_cpu(rate);
-+	bst->battery_present_rate = abs((s32)tmp);
-+
-+	state = 0;
-+	if ((s32) tmp > 0)
-+		state |= ACPI_BATTERY_STATE_CHARGING;
-+	else if ((s32) tmp < 0)
-+		state |= ACPI_BATTERY_STATE_DISCHARGING;
-+	bst->battery_state = state;
-+
-+	bst->battery_remaining_capacity = le16_to_cpu(capacity);
-+	bst->battery_present_voltage = le16_to_cpu(voltage);
-+
-+	return 0;
-+}
-+
-+static int surface_i2c_adp_psr(struct surface_i2c_data *cdata)
-+{
-+	struct i2c_client *client = cdata->adp1;
-+	int ret;
-+
-+	ret = i2c_smbus_read_byte_data(client, surface_i2c_ADP1_REG_PSR);
-+	if (ret < 0)
-+		return ret;
-+
-+	return ret;
-+}
-+
-+static int surface_i2c_isr(struct surface_i2c_data *cdata)
-+{
-+	struct bst bst;
-+	struct bix bix;
-+	int ret;
-+	bool status, bat_status;
-+
-+	ret = surface_i2c_adp_psr(cdata);
-+	if (ret < 0)
-+		return ret;
-+
-+	status = ret;
-+
-+	if (status != cdata->charging)
-+		surface_i2c_notify(cdata, cdata->notify_version,
-+				surface_i2c_NOTIFY_ADP1, &ret);
-+
-+	cdata->charging = status;
-+
-+	ret = surface_i2c_bst(cdata, &bst);
-+	if (ret < 0)
-+		return ret;
-+
-+	bat_status = bst.battery_state;
-+
-+	if (bat_status != cdata->bat_charging)
-+		surface_i2c_notify(cdata, cdata->notify_version,
-+				surface_i2c_NOTIFY_BAT0_BST, &ret);
-+
-+	cdata->bat_charging = bat_status;
-+
-+	ret = surface_i2c_bix(cdata, &bix);
-+	if (ret < 0)
-+		return ret;
-+	if (bix.last_full_charg_capacity != cdata->full_capacity)
-+		surface_i2c_notify(cdata, cdata->notify_version,
-+				surface_i2c_NOTIFY_BAT0_BIX, &ret);
-+
-+	cdata->full_capacity = bix.last_full_charg_capacity;
-+
-+	return 0;
-+}
-+
-+static int surface_i2c_poll_task(void *data)
-+{
-+	struct surface_i2c_data *cdata = data;
-+	int ret = 0;
-+
-+	cdata->kthread_running = true;
-+
-+	set_freezable();
-+
-+	while (!kthread_should_stop()) {
-+		schedule_timeout_interruptible(POLL_INTERVAL);
-+		try_to_freeze();
-+		ret = surface_i2c_isr(data);
-+		if (ret)
-+			goto out;
-+	}
-+
-+out:
-+	cdata->kthread_running = false;
-+	return ret;
-+}
-+
-+static acpi_status
-+surface_i2c_space_handler(u32 function, acpi_physical_address command,
-+			u32 bits, u64 *value64,
-+			void *handler_context, void *region_context)
-+{
-+	struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
-+	struct surface_i2c_handler_data *data = handler_context;
-+	struct acpi_connection_info *info = &data->info;
-+	struct acpi_resource_i2c_serialbus *sb;
-+	struct i2c_client *client = data->client;
-+	struct surface_i2c_data *cdata = i2c_get_clientdata(client);
-+	struct acpi_resource *ares;
-+	u32 accessor_type = function >> 16;
-+	acpi_status ret;
-+	int status = 1;
-+
-+	ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
-+	if (ACPI_FAILURE(ret))
-+		return ret;
-+
-+	if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
-+		ret = AE_BAD_PARAMETER;
-+		goto err;
-+	}
-+
-+	sb = &ares->data.i2c_serial_bus;
-+	if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
-+		ret = AE_BAD_PARAMETER;
-+		goto err;
-+	}
-+
-+	if (accessor_type != ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS) {
-+		ret = AE_BAD_PARAMETER;
-+		goto err;
-+	}
-+
-+	if (gsb->cmd.arg0 == surface_i2c_CMD_DEST_ADP1 &&
-+	    gsb->cmd.arg1 == surface_i2c_CMD_ADP1_PSR) {
-+		ret = surface_i2c_adp_psr(cdata);
-+		if (ret >= 0) {
-+			status = ret;
-+			ret = 0;
-+		}
-+		goto out;
-+	}
-+
-+	if (gsb->cmd.arg0 != surface_i2c_CMD_DEST_BAT0) {
-+		ret = AE_BAD_PARAMETER;
-+		goto err;
-+	}
-+
-+	switch (gsb->cmd.arg1) {
-+	case surface_i2c_CMD_BAT0_STA:
-+		status = 1;
-+		ret = 0;
-+		break;
-+	case surface_i2c_CMD_BAT0_BIX:
-+		status = 1;
-+		ret = surface_i2c_bix(cdata, &gsb->bix);
-+		break;
-+	case surface_i2c_CMD_BAT0_BTP:
-+		status = 1;
-+		ret = 0;
-+		cdata->trip_point = gsb->cmd.arg2;
-+		break;
-+	case surface_i2c_CMD_BAT0_BST:
-+		status = 1;
-+		ret = surface_i2c_bst(cdata, &gsb->bst);
-+		break;
-+	default:
-+		pr_info("command(0x%02x) is not supported.\n", gsb->cmd.arg1);
-+		ret = AE_BAD_PARAMETER;
-+		goto err;
-+	}
-+
-+ out:
-+	gsb->ret = status;
-+	gsb->status = 0;
-+
-+ err:
-+	ACPI_FREE(ares);
-+	return ret;
-+}
-+
-+static int surface_i2c_install_space_handler(struct i2c_client *client)
-+{
-+	acpi_handle handle;
-+	struct surface_i2c_handler_data *data;
-+	acpi_status status;
-+
-+	handle = ACPI_HANDLE(&client->dev);
-+
-+	if (!handle)
-+		return -ENODEV;
-+
-+	data = kzalloc(sizeof(struct surface_i2c_handler_data),
-+			    GFP_KERNEL);
-+	if (!data)
-+		return -ENOMEM;
-+
-+	data->client = client;
-+	status = acpi_bus_attach_private_data(handle, (void *)data);
-+	if (ACPI_FAILURE(status)) {
-+		kfree(data);
-+		return -ENOMEM;
-+	}
-+
-+	status = acpi_install_address_space_handler(handle,
-+				ACPI_ADR_SPACE_GSBUS,
-+				&surface_i2c_space_handler,
-+				NULL,
-+				data);
-+	if (ACPI_FAILURE(status)) {
-+		dev_err(&client->dev, "Error installing i2c space handler\n");
-+		acpi_bus_detach_private_data(handle);
-+		kfree(data);
-+		return -ENOMEM;
-+	}
-+
-+	acpi_walk_dep_device_list(handle);
-+	return 0;
-+}
-+
-+static void surface_i2c_remove_space_handler(struct i2c_client *client)
-+{
-+	acpi_handle handle;
-+	struct surface_i2c_handler_data *data;
-+	acpi_status status;
-+
-+	handle = ACPI_HANDLE(&client->dev);
-+
-+	if (!handle)
-+		return;
-+
-+	acpi_remove_address_space_handler(handle,
-+				ACPI_ADR_SPACE_GSBUS,
-+				&surface_i2c_space_handler);
-+
-+	status = acpi_bus_get_private_data(handle, (void **)&data);
-+	if (ACPI_SUCCESS(status))
-+		kfree(data);
-+
-+	acpi_bus_detach_private_data(handle);
-+}
-+
-+static int acpi_find_i2c(struct acpi_resource *ares, void *data)
-+{
-+	struct surface_i2c_lookup *lookup = data;
-+
-+	if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS)
-+		return 1;
-+
-+	if (lookup->n++ == lookup->index && !lookup->addr)
-+		lookup->addr = ares->data.i2c_serial_bus.slave_address;
-+
-+	return 1;
-+}
-+
-+static int surface_i2c_resource_lookup(struct surface_i2c_data *cdata,
-+					unsigned int index)
-+{
-+	struct i2c_client *client = cdata->adp1;
-+	struct acpi_device *adev = ACPI_COMPANION(&client->dev);
-+	struct surface_i2c_lookup lookup = {
-+		.cdata = cdata,
-+		.index = index,
-+	};
-+	struct list_head res_list;
-+	int ret;
-+
-+	INIT_LIST_HEAD(&res_list);
-+
-+	ret = acpi_dev_get_resources(adev, &res_list, acpi_find_i2c, &lookup);
-+	if (ret < 0)
-+		return ret;
-+
-+	acpi_dev_free_resource_list(&res_list);
-+
-+	if (!lookup.addr)
-+		return -ENOENT;
-+
-+	return lookup.addr;
-+}
-+
-+static void surface_i2c_dump_registers(struct i2c_client *client,
-+				    struct i2c_client *bat0)
-+{
-+	char rd_buf[60];
-+	int error, i, c;
-+	char buff[17 * 3 * 2] = {0};
-+
-+	dev_info(&client->dev, "dumping registers 0x00 to 0x7F:\n");
-+
-+	for (i = 0; i < 0x80; i += 0x20) {
-+		memset(rd_buf, 0, sizeof(rd_buf));
-+		error = surface_i2c_read_block(bat0, i, rd_buf, 0x20);
-+		dev_info(&client->dev, " read 0x%02x: %*ph|%*ph\n",
-+			 i,
-+			 0x10, rd_buf,
-+			 0x10, rd_buf + 0x10);
-+		for (c = 0; c < 0x20; c++) {
-+			if (rd_buf[c] >= 0x20 && rd_buf[c] <= 0x7e) {
-+				buff[c * 3 + 0] = ' ';
-+				buff[c * 3 + 1] = rd_buf[c];
-+			} else {
-+				buff[c * 3 + 0] = '-';
-+				buff[c * 3 + 1] = '-';
-+			}
-+			buff[c * 3 + 2] = (c + 1) % 0x10 ? ' ' : '|';
-+		}
-+		buff[0x1f * 3 + 2] = '\0';
-+		dev_info(&client->dev, "ascii 0x%02x: %s\n", i, buff);
-+	}
-+}
-+
-+static int surface_i2c_probe(struct i2c_client *client)
-+{
-+	struct device *dev = &client->dev;
-+	struct i2c_client *bat0;
-+	struct surface_i2c_data *data;
-+	int error, version, addr;
-+
-+	pr_info("surface_i2c: Probing for surface i2c device...\n");
-+
-+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
-+	if (!data)
-+		return -ENOMEM;
-+
-+	data->adp1 = client;
-+	i2c_set_clientdata(client, data);
-+
-+	addr = surface_i2c_resource_lookup(data, 1);
-+	if (addr < 0)
-+		return addr;
-+
-+	bat0 = i2c_new_dummy(client->adapter, addr);
-+	if (!bat0)
-+		return -ENOMEM;
-+
-+	data->bat0 = bat0;
-+	i2c_set_clientdata(bat0, data);
-+
-+	// debugging
-+	surface_i2c_dump_registers(client, bat0);
-+
-+	pr_info("surface_i2c: Attaching device MSHW0124...");
-+
-+	error = surface_i2c_notify(data, 1, surface_i2c_NOTIFY_GET_VERSION, &version);
-+	if (error)
-+		goto out_err;
-+
-+	data->notify_version = version == surface_i2c_EV_2_5;
-+
-+	data->poll_task = kthread_run(surface_i2c_poll_task, data, "surface_i2c_adp");
-+	if (IS_ERR(data->poll_task)) {
-+		error = PTR_ERR(data->poll_task);
-+		dev_err(&client->dev, "Unable to run kthread err %d\n", error);
-+		goto out_err;
-+	}
-+
-+	//error = surface_i2c_install_space_handler(client);
-+	//if (error)
-+	//	goto out_err;
-+
-+	return 0;
-+
-+out_err:
-+	if (data->kthread_running)
-+		kthread_stop(data->poll_task);
-+	i2c_unregister_device(data->bat0);
-+	return error;
-+}
-+
-+static int surface_i2c_remove(struct i2c_client *client)
-+{
-+	struct surface_i2c_data *cdata = i2c_get_clientdata(client);
-+
-+	surface_i2c_remove_space_handler(client);
-+
-+	if (cdata->kthread_running)
-+		kthread_stop(cdata->poll_task);
-+
-+	i2c_unregister_device(cdata->bat0);
-+
-+	return 0;
-+}
-+
-+int surface_i2c_detect(struct i2c_client* client, struct i2c_board_info* board_info)
-+{
-+    pr_info("surface_i2c: Detecting surface_i2c device...");
-+    return 0;
-+}
-+
-+static const struct acpi_device_id surface_i2c_acpi_match[] = {
-+	{ "MSHW0124", 0 },
-+	{ "", 0 }
-+};
-+MODULE_DEVICE_TABLE(acpi, surface_i2c_acpi_match);
-+
-+static const struct i2c_device_id surface_i2c_id[] = {
-+	{ "MSHW0124:00", 0 },
-+	{ "MSHW0124:01", 0 },
-+	{ "", 0 }
-+};
-+MODULE_DEVICE_TABLE(i2c, surface_i2c_id);
-+
-+static struct i2c_driver surface_i2c_driver = {
-+	.probe_new = surface_i2c_probe,
-+	.remove = surface_i2c_remove,
-+	.detect = surface_i2c_detect,
-+	.id_table = surface_i2c_id,
-+	.driver = {
-+		.name = "surface_i2c",
-+		.acpi_match_table = ACPI_PTR(surface_i2c_acpi_match),
-+	},
-+};
-+module_i2c_driver(surface_i2c_driver);
-+
-+MODULE_AUTHOR("Jake Day");
-+MODULE_DESCRIPTION("Microsoft Surface I2C Driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/platform/x86/surface_platform.c b/drivers/platform/x86/surface_platform.c
-new file mode 100644
-index 000000000000..7a84340b04bb
---- /dev/null
-+++ b/drivers/platform/x86/surface_platform.c
-@@ -0,0 +1,67 @@
-+/*
-+ *  surface_platform.c - Microsoft Surface Platform Driver
-+ *
-+ *  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.
-+ *
-+ *  The full GNU General Public License is included in this distribution in
-+ *  the file called "COPYING".
-+ */
-+
-+#include <linux/acpi.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/platform_device.h>
-+#include <linux/power_supply.h>
-+#include <linux/thermal.h>
-+#include <linux/uuid.h>
-+#include <linux/workqueue.h>
-+
-+#include <asm/unaligned.h>
-+
-+struct surface_platform_data {
-+	struct device *dev;
-+};
-+
-+static int surface_platform_probe(struct platform_device *pdev)
-+{
-+	struct surface_platform_data *pdata;
-+
-+	platform_set_drvdata(pdev, pdata);
-+	return 0;
-+}
-+
-+static int surface_platform_remove(struct platform_device *pdev)
-+{
-+	struct surface_platform_data *pdata = platform_get_drvdata(pdev);
-+}
-+
-+static const struct acpi_device_id surface_platform_acpi_match[] = {
-+	{ "MSHW0091", 0 },
-+	{ "INT3403", 0 },
-+	{ "", 0 }
-+};
-+MODULE_DEVICE_TABLE(acpi, surface_platform_acpi_match);
-+
-+static struct platform_driver surface_platform_driver = {
-+	.probe = surface_platform_probe,
-+	.remove = surface_platform_remove,
-+	.driver = {
-+		.name = "surface_platform",
-+		.acpi_match_table = ACPI_PTR(surface_platform_acpi_match),
-+	},
-+};
-+module_platform_driver(surface_platform_driver);
-+
-+MODULE_AUTHOR("Jake Day");
-+MODULE_DESCRIPTION("Microsoft Surface Platform Driver");
-+MODULE_LICENSE("GPL");

+ 0 - 299
patches/4.17/buttons.patch

@@ -1,299 +0,0 @@
-diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
-index 081105a9cfca..a4388b4da98f 100644
---- a/drivers/platform/x86/Kconfig
-+++ b/drivers/platform/x86/Kconfig
-@@ -1158,6 +1158,11 @@ config SURFACE_3_BUTTON
- 	---help---
- 	  This driver handles the power/home/volume buttons on the Microsoft Surface 3 tablet.
- 
-+config SURFACEBOOK2_BUTTON
-+	tristate "Power/home/volume buttons driver for Microsoft Surface Book 2/ Surface Pro (2017) tablet"
-+	---help---
-+	  This driver handles the power and volume buttons on the Microsoft Surface Book 2/ Surface Pro (2017) tablet.
-+
- config ACPI_SURFACE
- 	tristate "Microsoft Surface Extras"
- 	depends on ACPI
-diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
-index 8fd5b93bb20d..28c4cede2d91 100644
---- a/drivers/platform/x86/Makefile
-+++ b/drivers/platform/x86/Makefile
-@@ -81,6 +81,7 @@ obj-$(CONFIG_INTEL_PMC_IPC)	+= intel_pmc_ipc.o
- obj-$(CONFIG_SILEAD_DMI)	+= silead_dmi.o
- obj-$(CONFIG_SURFACE_PRO3_BUTTON)	+= surfacepro3_button.o
- obj-$(CONFIG_SURFACE_3_BUTTON)	+= surface3_button.o
-+obj-$(CONFIG_SURFACEBOOK2_BUTTON) += surfacebook2_button.o
- obj-$(CONFIG_ACPI_SURFACE)	+= surface_acpi.o
- obj-$(CONFIG_ACPI_SURFACE)	+= surface_i2c.o
- obj-$(CONFIG_ACPI_SURFACE)	+= surface_platform.o
-diff --git a/drivers/platform/x86/surfacebook2_button.c b/drivers/platform/x86/surfacebook2_button.c
-new file mode 100644
-index 000000000000..9a23bfd32c97
---- /dev/null
-+++ b/drivers/platform/x86/surfacebook2_button.c
-@@ -0,0 +1,242 @@
-+/*
-+ * Supports for Surface Book 2 and Surface Pro (2017) power and volume
-+ * buttons.
-+ *
-+ * Based on soc_button_array.c:
-+ *
-+ * (C) Copyright 2014 Intel Corporation
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public License
-+ * as published by the Free Software Foundation; version 2
-+ * of the License.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/input.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/acpi.h>
-+#include <linux/gpio/consumer.h>
-+#include <linux/gpio_keys.h>
-+#include <linux/gpio.h>
-+#include <linux/platform_device.h>
-+
-+struct soc_button_info {
-+	const char *name;
-+	int acpi_index;
-+	unsigned int event_type;
-+	unsigned int event_code;
-+	bool autorepeat;
-+	bool wakeup;
-+};
-+
-+/*
-+ * Some of the buttons like volume up/down are auto repeat, while others
-+ * are not. To support both, we register two platform devices, and put
-+ * buttons into them based on whether the key should be auto repeat.
-+ */
-+#define BUTTON_TYPES			2
-+#define SURFACE_METHOD_DSM		"_DSM"
-+
-+struct soc_button_data {
-+	struct platform_device *children[BUTTON_TYPES];
-+};
-+
-+/*
-+ * Get the Nth GPIO number from the ACPI object.
-+ */
-+static int soc_button_lookup_gpio(struct device *dev, int acpi_index)
-+{
-+	struct gpio_desc *desc;
-+	int gpio;
-+
-+	desc = gpiod_get_index(dev, NULL, acpi_index, GPIOD_ASIS);
-+	if (IS_ERR(desc))
-+		return PTR_ERR(desc);
-+
-+	gpio = desc_to_gpio(desc);
-+
-+	gpiod_put(desc);
-+
-+	return gpio;
-+}
-+
-+static struct platform_device *
-+soc_button_device_create(struct platform_device *pdev,
-+			 const struct soc_button_info *button_info,
-+			 bool autorepeat)
-+{
-+	const struct soc_button_info *info;
-+	struct platform_device *pd;
-+	struct gpio_keys_button *gpio_keys;
-+	struct gpio_keys_platform_data *gpio_keys_pdata;
-+	int n_buttons = 0;
-+	int gpio;
-+	int error;
-+
-+	for (info = button_info; info->name; info++)
-+		if (info->autorepeat == autorepeat)
-+			n_buttons++;
-+
-+	gpio_keys_pdata = devm_kzalloc(&pdev->dev,
-+				       sizeof(*gpio_keys_pdata) +
-+					sizeof(*gpio_keys) * n_buttons,
-+				       GFP_KERNEL);
-+	if (!gpio_keys_pdata)
-+		return ERR_PTR(-ENOMEM);
-+
-+	gpio_keys = (void *)(gpio_keys_pdata + 1);
-+	n_buttons = 0;
-+
-+	for (info = button_info; info->name; info++) {
-+		if (info->autorepeat != autorepeat)
-+			continue;
-+
-+		gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
-+		if (!gpio_is_valid(gpio))
-+			continue;
-+
-+		gpio_keys[n_buttons].type = info->event_type;
-+		gpio_keys[n_buttons].code = info->event_code;
-+		gpio_keys[n_buttons].gpio = gpio;
-+		gpio_keys[n_buttons].active_low = 1;
-+		gpio_keys[n_buttons].desc = info->name;
-+		gpio_keys[n_buttons].wakeup = info->wakeup;
-+		/* These devices often use cheap buttons, use 50 ms debounce */
-+		gpio_keys[n_buttons].debounce_interval = 50;
-+		n_buttons++;
-+	}
-+
-+	if (n_buttons == 0) {
-+		error = -ENODEV;
-+		goto err_free_mem;
-+	}
-+
-+	gpio_keys_pdata->buttons = gpio_keys;
-+	gpio_keys_pdata->nbuttons = n_buttons;
-+	gpio_keys_pdata->rep = autorepeat;
-+
-+	pd = platform_device_alloc("gpio-keys", PLATFORM_DEVID_AUTO);
-+	if (!pd) {
-+		error = -ENOMEM;
-+		goto err_free_mem;
-+	}
-+
-+	error = platform_device_add_data(pd, gpio_keys_pdata,
-+					 sizeof(*gpio_keys_pdata));
-+	if (error)
-+		goto err_free_pdev;
-+
-+	error = platform_device_add(pd);
-+	if (error)
-+		goto err_free_pdev;
-+
-+	return pd;
-+
-+err_free_pdev:
-+	platform_device_put(pd);
-+err_free_mem:
-+	devm_kfree(&pdev->dev, gpio_keys_pdata);
-+	return ERR_PTR(error);
-+}
-+
-+static int soc_button_remove(struct platform_device *pdev)
-+{
-+	struct soc_button_data *priv = platform_get_drvdata(pdev);
-+
-+	int i;
-+
-+	for (i = 0; i < BUTTON_TYPES; i++)
-+		if (priv->children[i])
-+			platform_device_unregister(priv->children[i]);
-+
-+	return 0;
-+}
-+
-+static int soc_button_probe(struct platform_device *pdev)
-+{
-+	struct device *dev = &pdev->dev;
-+	const struct acpi_device_id *id;
-+	struct soc_button_info *button_info;
-+	struct soc_button_data *priv;
-+	struct platform_device *pd;
-+	int i;
-+	int error;
-+
-+	id = acpi_match_device(dev->driver->acpi_match_table, dev);
-+	if (!id)
-+		return -ENODEV;
-+
-+	if (!acpi_has_method(ACPI_HANDLE(dev), SURFACE_METHOD_DSM))
-+		return -ENODEV;
-+
-+	button_info = (struct soc_button_info *)id->driver_data;
-+
-+	error = gpiod_count(dev, NULL);
-+	if (error < 0) {
-+		dev_dbg(dev, "no GPIO attached, ignoring...\n");
-+		return -ENODEV;
-+	}
-+
-+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-+	if (!priv)
-+		return -ENOMEM;
-+
-+	platform_set_drvdata(pdev, priv);
-+
-+	for (i = 0; i < BUTTON_TYPES; i++) {
-+		pd = soc_button_device_create(pdev, button_info, i == 0);
-+		if (IS_ERR(pd)) {
-+			error = PTR_ERR(pd);
-+			if (error != -ENODEV) {
-+				soc_button_remove(pdev);
-+				return error;
-+			}
-+			continue;
-+		}
-+
-+		priv->children[i] = pd;
-+	}
-+
-+	if (!priv->children[0] && !priv->children[1])
-+		return -ENODEV;
-+
-+	if (!id->driver_data)
-+		devm_kfree(dev, button_info);
-+
-+	return 0;
-+}
-+
-+/*
-+ * Definition of buttons on the tablet. The ACPI index of each button
-+ * is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
-+ * Platforms"
-+ */
-+static struct soc_button_info soc_button_MSHW0040[] = {
-+	{ "power",       0, EV_KEY, KEY_POWER,      false, true  },
-+	{ "volume_up",   2, EV_KEY, KEY_VOLUMEUP,   true,  false },
-+	{ "volume_down", 4, EV_KEY, KEY_VOLUMEDOWN, true,  false },
-+	{ }
-+};
-+
-+static const struct acpi_device_id soc_button_acpi_match[] = {
-+	{ "MSHW0040", (unsigned long)soc_button_MSHW0040 },
-+	{ }
-+};
-+
-+MODULE_DEVICE_TABLE(acpi, soc_button_acpi_match);
-+
-+static struct platform_driver soc_button_driver_sb2 = {
-+	.probe		= soc_button_probe,
-+	.remove		= soc_button_remove,
-+	.driver		= {
-+		.name = "surfacebook2_button",
-+		.acpi_match_table = ACPI_PTR(soc_button_acpi_match),
-+	},
-+};
-+module_platform_driver(soc_button_driver_sb2);
-+
-+MODULE_AUTHOR("Maximilian Luz");
-+MODULE_DESCRIPTION("Surface Book 2/Surface Pro (2017) Button Driver");
-+MODULE_LICENSE("GPL v2");
-diff --git a/drivers/platform/x86/surfacepro3_button.c b/drivers/platform/x86/surfacepro3_button.c
-index 1b491690ce07..9385262b65be 100644
---- a/drivers/platform/x86/surfacepro3_button.c
-+++ b/drivers/platform/x86/surfacepro3_button.c
-@@ -22,6 +22,7 @@
- #define SURFACE_PRO3_BUTTON_HID		"MSHW0028"
- #define SURFACE_PRO4_BUTTON_HID		"MSHW0040"
- #define SURFACE_BUTTON_OBJ_NAME		"VGBI"
-+#define SURFACE_METHOD_DSM			"_DSM"
- #define SURFACE_BUTTON_DEVICE_NAME	"Surface Pro 3/4 Buttons"
- 
- #define SURFACE_BUTTON_NOTIFY_TABLET_MODE	0xc8
-@@ -158,6 +159,9 @@ static int surface_button_add(struct acpi_device *device)
- 	    strlen(SURFACE_BUTTON_OBJ_NAME)))
- 		return -ENODEV;
- 
-+	if (acpi_has_method(device->handle, SURFACE_METHOD_DSM))
-+		return -ENODEV;
-+
- 	button = kzalloc(sizeof(struct surface_button), GFP_KERNEL);
- 	if (!button)
- 		return -ENOMEM;
-

+ 0 - 156
patches/4.17/cameras.patch

@@ -1,156 +0,0 @@
-diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
-index 2469b49b2b30..d2f77132efea 100644
---- a/drivers/media/usb/uvc/uvc_driver.c
-+++ b/drivers/media/usb/uvc/uvc_driver.c
-@@ -2354,6 +2354,46 @@ static const struct uvc_device_info uvc_quirk_force_y8 = {
-  * though they are compliant.
-  */
- static const struct usb_device_id uvc_ids[] = {
-+	/* Microsoft Surface Pro 3 Front */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x07be,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Pro 3 Rear */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x07bf,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Pro 4 Cam */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x090c,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Book Cam 1 */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x090b,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
-+	/* Microsoft Surface Book Cam 2 */
-+	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
-+				| USB_DEVICE_ID_MATCH_INT_INFO,
-+	  .idVendor             = 0x045e,
-+	  .idProduct            = 0x091a,
-+	  .bInterfaceClass      = USB_CLASS_VIDEO,
-+	  .bInterfaceSubClass   = 1,
-+	  .bInterfaceProtocol   = 1 },
- 	/* LogiLink Wireless Webcam */
- 	{ .match_flags		= USB_DEVICE_ID_MATCH_DEVICE
- 				| USB_DEVICE_ID_MATCH_INT_INFO,
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/Kconfig b/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-index 3f527f2047a7..b8829488ff7a 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/Kconfig
-@@ -1,7 +1,7 @@
- config VIDEO_ATOMISP_OV5693
-        tristate "Omnivision ov5693 sensor support"
- 	depends on ACPI
--       depends on I2C && VIDEO_V4L2
-+	   depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
-        ---help---
- 	 This is a Video4Linux2 sensor-level driver for the Micron
- 	 ov5693 5 Mpixel camera.
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
-index 714297c36b3e..7c1295bf2978 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c
-@@ -1339,11 +1339,15 @@ static int power_ctrl(struct v4l2_subdev *sd, bool flag)
- static int gpio_ctrl(struct v4l2_subdev *sd, bool flag)
- {
- 	struct ov5693_device *dev = to_ov5693_sensor(sd);
-+	int ret = 0;
- 
- 	if (!dev || !dev->platform_data)
- 		return -ENODEV;
- 
--	return dev->platform_data->gpio0_ctrl(sd, flag);
-+	if (dev->platform_data->gpio0_ctrl)
-+		ret = dev->platform_data->gpio0_ctrl(sd, flag);
-+
-+	return ret;
- }
- 
- static int __power_up(struct v4l2_subdev *sd)
-@@ -1711,7 +1715,7 @@ static int ov5693_detect(struct i2c_client *client)
- 					OV5693_SC_CMMN_CHIP_ID_L, &low);
- 	id = ((((u16) high) << 8) | (u16) low);
- 
--	if (id != OV5693_ID) {
-+	if (id != OV5690_ID && id != OV5693_ID) {
- 		dev_err(&client->dev, "sensor ID error 0x%x\n", id);
- 		return -ENODEV;
- 	}
-diff --git a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-index 9058a82455a6..84f8ef6146d6 100644
---- a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-+++ b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h
-@@ -29,7 +29,7 @@
- #include <linux/v4l2-mediabus.h>
- #include <media/media-entity.h>
- 
--#include "../../include/linux/atomisp_platform.h"
-+#include "../../include/linux/atomisp_gmin_platform.h"
- 
- #define OV5693_POWER_UP_RETRY_NUM 5
- 
-@@ -72,7 +72,8 @@
-  * bits 7-0: min f-number denominator
-  */
- #define OV5693_F_NUMBER_RANGE 0x180a180a
--#define OV5693_ID	0x5690
-+#define OV5690_ID	0x5690
-+#define OV5693_ID	0x5693
- 
- #define OV5693_FINE_INTG_TIME_MIN 0
- #define OV5693_FINE_INTG_TIME_MAX_MARGIN 0
-diff --git a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-index 3283c1b05d6a..00b85f54dcc0 100644
---- a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-+++ b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
-@@ -249,11 +249,13 @@ static struct gmin_cfg_var ecs7_vars[] = {
- 	{"INT33BE:00_CsiFmt", "13"},
- 	{"INT33BE:00_CsiBayer", "2"},
- 	{"INT33BE:00_CamClk", "0"},
-+	{"INT33BE:00_ClkSrc", "1"},
- 	{"INT33F0:00_CsiPort", "0"},
- 	{"INT33F0:00_CsiLanes", "1"},
- 	{"INT33F0:00_CsiFmt", "13"},
- 	{"INT33F0:00_CsiBayer", "0"},
- 	{"INT33F0:00_CamClk", "1"},
-+	{"INT33BE:00_I2CAddr", "-1"},
- 	{"gmin_V2P8GPIO", "402"},
- 	{},
- };
-@@ -305,6 +307,20 @@ static const struct dmi_system_id gmin_vars[] = {
- 		},
- 		.driver_data = i8880_vars,
- 	},
-+	{
-+		.ident = "Surface Book",
-+		.matches = {
-+			DMI_MATCH(DMI_BOARD_NAME, "Surface Book"),
-+		},
-+		.driver_data = ecs7_vars,
-+	},
-+	{
-+		.ident = "Surface Pro 4",
-+		.matches = {
-+			DMI_MATCH(DMI_BOARD_NAME, "Surface Pro 4"),
-+		},
-+		.driver_data = ecs7_vars,
-+	},
- 	{}
- };
- 

+ 0 - 6055
patches/4.17/ipts.patch

@@ -1,6055 +0,0 @@
-diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
-index 4eee91a3a236..eb7c3284d23a 100644
---- a/drivers/gpu/drm/i915/Makefile
-+++ b/drivers/gpu/drm/i915/Makefile
-@@ -148,6 +148,9 @@ i915-y += dvo_ch7017.o \
- 	  intel_sdvo.o \
- 	  intel_tv.o
- 
-+# intel precise touch & stylus
-+i915-y  += intel_ipts.o
-+
- # Post-mortem debug and GPU hang state capture
- i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
- i915-$(CONFIG_DRM_I915_SELFTEST) += \
-diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
-index 3b4daafebdcb..31968ebd3132 100644
---- a/drivers/gpu/drm/i915/i915_drv.c
-+++ b/drivers/gpu/drm/i915/i915_drv.c
-@@ -53,6 +53,7 @@
- #include "i915_vgpu.h"
- #include "intel_drv.h"
- #include "intel_uc.h"
-+#include "intel_ipts.h"
- 
- static struct drm_driver driver;
- 
-@@ -713,6 +714,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
- 	/* Only enable hotplug handling once the fbdev is fully set up. */
- 	intel_hpd_init(dev_priv);
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc && i915_modparams.enable_ipts)
-+        intel_ipts_init(dev);
-+
- 	return 0;
- 
- cleanup_gem:
-@@ -1438,6 +1442,9 @@ void i915_driver_unload(struct drm_device *dev)
- 	struct drm_i915_private *dev_priv = to_i915(dev);
- 	struct pci_dev *pdev = dev_priv->drm.pdev;
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc && i915_modparams.enable_ipts)
-+		intel_ipts_cleanup(dev);
-+
- 	i915_driver_unregister(dev_priv);
- 
- 	if (i915_gem_suspend(dev_priv))
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index ce18b6cf6e68..35a63cb44211 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -3461,6 +3461,9 @@ void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
- void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
- 					 struct sg_table *pages);
- 
-+struct i915_gem_context *
-+i915_gem_context_create_ipts(struct drm_device *dev);
-+
- static inline struct i915_gem_context *
- __i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id)
- {
-diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
-index f2cbea7cf940..2e6a63ef5c98 100644
---- a/drivers/gpu/drm/i915/i915_gem_context.c
-+++ b/drivers/gpu/drm/i915/i915_gem_context.c
-@@ -455,6 +455,18 @@ static bool needs_preempt_context(struct drm_i915_private *i915)
- 	return HAS_LOGICAL_RING_PREEMPTION(i915);
- }
- 
-+struct i915_gem_context *i915_gem_context_create_ipts(struct drm_device *dev)
-+{
-+	struct drm_i915_private *dev_priv = dev->dev_private;
-+	struct i915_gem_context *ctx;
-+
-+	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
-+
-+	ctx = i915_gem_create_context(dev_priv, NULL);
-+
-+	return ctx;
-+}
-+
- int i915_gem_contexts_init(struct drm_i915_private *dev_priv)
- {
- 	struct i915_gem_context *ctx;
-diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
-index 633c18785c1e..ef6fbeb9eb54 100644
---- a/drivers/gpu/drm/i915/i915_irq.c
-+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -36,6 +36,7 @@
- #include "i915_drv.h"
- #include "i915_trace.h"
- #include "intel_drv.h"
-+#include "intel_ipts.h"
- 
- /**
-  * DOC: interrupt handling
-@@ -1416,6 +1417,9 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
- 		tasklet |= USES_GUC_SUBMISSION(engine->i915);
- 	}
- 
-+	if (iir & (GT_RENDER_PIPECTL_NOTIFY_INTERRUPT << test_shift))
-+		intel_ipts_notify_complete();
-+
- 	if (tasklet)
- 		tasklet_hi_schedule(&execlists->tasklet);
- }
-@@ -3773,7 +3777,8 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)
- {
- 	/* These are interrupts we'll toggle with the ring mask register */
- 	uint32_t gt_interrupts[] = {
--		GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+		GT_RENDER_PIPECTL_NOTIFY_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+			GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
- 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
- 			GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT |
- 			GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT,
-diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
-index 08108ce5be21..db321ac57fa5 100644
---- a/drivers/gpu/drm/i915/i915_params.c
-+++ b/drivers/gpu/drm/i915/i915_params.c
-@@ -152,7 +152,10 @@ i915_param_named_unsafe(edp_vswing, int, 0400,
- i915_param_named_unsafe(enable_guc, int, 0400,
- 	"Enable GuC load for GuC submission and/or HuC load. "
- 	"Required functionality can be selected using bitmask values. "
--	"(-1=auto, 0=disable [default], 1=GuC submission, 2=HuC load)");
-+	"(-1=auto, 0=disable, 1=GuC submission [default], 2=HuC load)");
-+
-+i915_param_named_unsafe(enable_ipts, bool, 0400,
-+	"Enable IPTS Touchscreen and Pen support (default: true)");
- 
- i915_param_named(guc_log_level, int, 0400,
- 	"GuC firmware logging level. Requires GuC to be loaded. "
-diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h
-index 430f5f9d0ff4..2b80220dbc36 100644
---- a/drivers/gpu/drm/i915/i915_params.h
-+++ b/drivers/gpu/drm/i915/i915_params.h
-@@ -47,7 +47,7 @@ struct drm_printer;
- 	param(int, disable_power_well, -1) \
- 	param(int, enable_ips, 1) \
- 	param(int, invert_brightness, 0) \
--	param(int, enable_guc, 0) \
-+	param(int, enable_guc, 1) \
- 	param(int, guc_log_level, 0) \
- 	param(char *, guc_firmware_path, NULL) \
- 	param(char *, huc_firmware_path, NULL) \
-@@ -69,7 +69,8 @@ struct drm_printer;
- 	param(bool, nuclear_pageflip, false) \
- 	param(bool, enable_dp_mst, true) \
- 	param(bool, enable_dpcd_backlight, false) \
--	param(bool, enable_gvt, false)
-+	param(bool, enable_gvt, false) \
-+	param(bool, enable_ipts, true)
- 
- #define MEMBER(T, member, ...) T member;
- struct i915_params {
-diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
-index b7b4cfdeb974..5163c29ca311 100644
---- a/drivers/gpu/drm/i915/intel_dp.c
-+++ b/drivers/gpu/drm/i915/intel_dp.c
-@@ -2572,8 +2572,8 @@ void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
- 		return;
- 
- 	if (mode != DRM_MODE_DPMS_ON) {
--		if (downstream_hpd_needs_d0(intel_dp))
--			return;
-+		//if (downstream_hpd_needs_d0(intel_dp))
-+		//	return;
- 
- 		ret = drm_dp_dpcd_writeb(&intel_dp->aux, DP_SET_POWER,
- 					 DP_SET_POWER_D3);
-diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
-index b9424ac644ac..154bf44773f4 100644
---- a/drivers/gpu/drm/i915/intel_guc.h
-+++ b/drivers/gpu/drm/i915/intel_guc.h
-@@ -64,6 +64,7 @@ struct intel_guc {
- 
- 	struct intel_guc_client *execbuf_client;
- 	struct intel_guc_client *preempt_client;
-+	struct intel_guc_client *ipts_client;
- 
- 	struct guc_preempt_work preempt_work[I915_NUM_ENGINES];
- 	struct workqueue_struct *preempt_wq;
-diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c
-index 8a8ad2fe158d..db40b8061a16 100644
---- a/drivers/gpu/drm/i915/intel_guc_submission.c
-+++ b/drivers/gpu/drm/i915/intel_guc_submission.c
-@@ -94,6 +94,7 @@ static inline bool is_high_priority(struct intel_guc_client *client)
- 
- static int reserve_doorbell(struct intel_guc_client *client)
- {
-+	struct drm_i915_private *dev_priv = guc_to_i915(client->guc);
- 	unsigned long offset;
- 	unsigned long end;
- 	u16 id;
-@@ -106,11 +107,16 @@ static int reserve_doorbell(struct intel_guc_client *client)
- 	 * priority contexts, the second half for high-priority ones.
- 	 */
- 	offset = 0;
--	end = GUC_NUM_DOORBELLS / 2;
--	if (is_high_priority(client)) {
--		offset = end;
--		end += offset;
-+	if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
-+		end = GUC_NUM_DOORBELLS;
- 	}
-+	else {
-+		end = GUC_NUM_DOORBELLS/2;
-+		if (is_high_priority(client)) {
-+			offset = end;
-+			end += offset;
-+		}
-+ 	}
- 
- 	id = find_next_zero_bit(client->guc->doorbell_bitmap, end, offset);
- 	if (id == end)
-@@ -353,8 +359,14 @@ static void guc_stage_desc_init(struct intel_guc *guc,
- 	desc = __get_stage_desc(client);
- 	memset(desc, 0, sizeof(*desc));
- 
--	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE |
--			  GUC_STAGE_DESC_ATTR_KERNEL;
-+	desc->attribute = GUC_STAGE_DESC_ATTR_ACTIVE;
-+	if ((client->priority == GUC_CLIENT_PRIORITY_KMD_NORMAL) ||
-+			(client->priority == GUC_CLIENT_PRIORITY_KMD_HIGH)) {
-+		desc->attribute  |= GUC_STAGE_DESC_ATTR_KERNEL;
-+	} else {
-+		desc->attribute  |= GUC_STAGE_DESC_ATTR_PCH;
-+	}
-+
- 	if (is_high_priority(client))
- 		desc->attribute |= GUC_STAGE_DESC_ATTR_PREEMPT;
- 	desc->stage_id = client->stage_id;
-@@ -1128,7 +1140,8 @@ static void guc_interrupts_capture(struct drm_i915_private *dev_priv)
- 		I915_WRITE(RING_MODE_GEN7(engine), irqs);
- 
- 	/* route USER_INTERRUPT to Host, all others are sent to GuC. */
--	irqs = GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT |
-+	irqs = (GT_RENDER_USER_INTERRUPT | GT_RENDER_PIPECTL_NOTIFY_INTERRUPT)
-+							<< GEN8_RCS_IRQ_SHIFT |
- 	       GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT;
- 	/* These three registers have the same bit definitions */
- 	I915_WRITE(GUC_BCS_RCS_IER, ~irqs);
-@@ -1257,6 +1270,58 @@ void intel_guc_submission_disable(struct intel_guc *guc)
- 	intel_engines_reset_default_submission(dev_priv);
- }
- 
-+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv,
-+				    struct i915_gem_context *ctx)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+	struct intel_guc_client *client;
-+	int err;
-+	int ret;
-+
-+	/* client for execbuf submission */
-+	client = guc_client_alloc(dev_priv,
-+				  INTEL_INFO(dev_priv)->ring_mask,
-+				  GUC_CLIENT_PRIORITY_NORMAL,
-+				  ctx);
-+	if (IS_ERR(client)) {
-+		DRM_ERROR("Failed to create normal GuC client!\n");
-+		return -ENOMEM;
-+	}
-+
-+	guc->ipts_client = client;
-+
-+	err = intel_guc_sample_forcewake(guc);
-+	if (err)
-+		return err;
-+
-+	ret = create_doorbell(guc->ipts_client);
-+	if (ret)
-+		return ret;
-+
-+	return 0;
-+}
-+
-+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+
-+	if (!guc->ipts_client)
-+		return;
-+
-+	guc_client_free(guc->ipts_client);
-+	guc->ipts_client = NULL;
-+}
-+
-+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv)
-+{
-+	struct intel_guc *guc = &dev_priv->guc;
-+
-+	int err = __guc_allocate_doorbell(guc, guc->ipts_client->stage_id);
-+
-+	if (err)
-+		DRM_ERROR("Not able to reacquire IPTS doorbell\n");
-+}
-+
- #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
- #include "selftests/intel_guc.c"
- #endif
-diff --git a/drivers/gpu/drm/i915/intel_guc_submission.h b/drivers/gpu/drm/i915/intel_guc_submission.h
-index fb081cefef93..71fc7986585a 100644
---- a/drivers/gpu/drm/i915/intel_guc_submission.h
-+++ b/drivers/gpu/drm/i915/intel_guc_submission.h
-@@ -79,5 +79,9 @@ void intel_guc_submission_disable(struct intel_guc *guc);
- void intel_guc_submission_fini(struct intel_guc *guc);
- int intel_guc_preempt_work_create(struct intel_guc *guc);
- void intel_guc_preempt_work_destroy(struct intel_guc *guc);
-+int i915_guc_ipts_submission_enable(struct drm_i915_private *dev_priv,
-+				    struct i915_gem_context *ctx);
-+void i915_guc_ipts_submission_disable(struct drm_i915_private *dev_priv);
-+void i915_guc_ipts_reacquire_doorbell(struct drm_i915_private *dev_priv);
- 
- #endif
-diff --git a/drivers/gpu/drm/i915/intel_ipts.c b/drivers/gpu/drm/i915/intel_ipts.c
-new file mode 100644
-index 000000000000..f8cc5eaf033d
---- /dev/null
-+++ b/drivers/gpu/drm/i915/intel_ipts.c
-@@ -0,0 +1,627 @@
-+/*
-+ * Copyright  2016 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/types.h>
-+#include <linux/module.h>
-+#include <linux/intel_ipts_if.h>
-+#include <drm/drmP.h>
-+
-+#include "intel_guc_submission.h"
-+#include "i915_drv.h"
-+
-+#define SUPPORTED_IPTS_INTERFACE_VERSION	1
-+
-+#define REACQUIRE_DB_THRESHOLD			8
-+#define DB_LOST_CHECK_STEP1_INTERVAL		2000	/* ms */
-+#define DB_LOST_CHECK_STEP2_INTERVAL		500	/* ms */
-+
-+/* intel IPTS ctx for ipts support */
-+typedef struct intel_ipts {
-+	struct drm_device *dev;
-+	struct i915_gem_context *ipts_context;
-+	intel_ipts_callback_t ipts_clbks;
-+
-+	/* buffers' list */
-+	struct {
-+		spinlock_t       lock;
-+		struct list_head list;
-+	} buffers;
-+
-+	void *data;
-+
-+	struct delayed_work reacquire_db_work;
-+	intel_ipts_wq_info_t wq_info;
-+	u32	old_tail;
-+	u32	old_head;
-+	bool	need_reacquire_db;
-+
-+	bool	connected;
-+	bool	initialized;
-+} intel_ipts_t;
-+
-+intel_ipts_t intel_ipts;
-+
-+typedef struct intel_ipts_object {
-+	struct list_head list;
-+	struct drm_i915_gem_object *gem_obj;
-+	void	*cpu_addr;
-+} intel_ipts_object_t;
-+
-+static intel_ipts_object_t *ipts_object_create(size_t size, u32 flags)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	intel_ipts_object_t *obj = NULL;
-+	struct drm_i915_gem_object *gem_obj = NULL;
-+	int ret = 0;
-+
-+	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
-+	if (!obj)
-+		return NULL;
-+
-+	size = roundup(size, PAGE_SIZE);
-+	if (size == 0) {
-+		ret = -EINVAL;
-+		goto err_out;
-+	}
-+
-+	/* Allocate the new object */
-+	gem_obj = i915_gem_object_create(dev_priv, size);
-+	if (gem_obj == NULL) {
-+		ret = -ENOMEM;
-+		goto err_out;
-+	}
-+
-+	if (flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		ret = i915_gem_object_attach_phys(gem_obj, PAGE_SIZE);
-+		if (ret) {
-+			pr_info(">> ipts no contiguous : %d\n", ret);
-+			goto err_out;
-+		}
-+	}
-+
-+	obj->gem_obj = gem_obj;
-+
-+	spin_lock(&intel_ipts.buffers.lock);
-+	list_add_tail(&obj->list, &intel_ipts.buffers.list);
-+	spin_unlock(&intel_ipts.buffers.lock);
-+
-+	return obj;
-+
-+err_out:
-+	if (gem_obj)
-+		i915_gem_free_object(&gem_obj->base);
-+
-+	if (obj)
-+		kfree(obj);
-+
-+	return NULL;
-+}
-+
-+static void ipts_object_free(intel_ipts_object_t* obj)
-+{
-+	spin_lock(&intel_ipts.buffers.lock);
-+	list_del(&obj->list);
-+	spin_unlock(&intel_ipts.buffers.lock);
-+
-+	i915_gem_free_object(&obj->gem_obj->base);
-+	kfree(obj);
-+}
-+
-+static int ipts_object_pin(intel_ipts_object_t* obj,
-+					struct i915_gem_context *ipts_ctx)
-+{
-+	struct i915_address_space *vm = NULL;
-+	struct i915_vma *vma = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	if (ipts_ctx->ppgtt) {
-+		vm = &ipts_ctx->ppgtt->base;
-+	} else {
-+		vm = &dev_priv->ggtt.base;
-+	}
-+
-+	vma = i915_vma_instance(obj->gem_obj, vm, NULL);
-+	if (IS_ERR(vma)) {
-+		DRM_ERROR("cannot find or create vma\n");
-+		return -1;
-+	}
-+
-+	ret = i915_vma_pin(vma, 0, PAGE_SIZE, PIN_USER);
-+
-+	return ret;
-+}
-+
-+static void ipts_object_unpin(intel_ipts_object_t *obj)
-+{
-+	/* TBD: Add support */
-+}
-+
-+static void* ipts_object_map(intel_ipts_object_t *obj)
-+{
-+
-+	return i915_gem_object_pin_map(obj->gem_obj, I915_MAP_WB);
-+}
-+
-+static void ipts_object_unmap(intel_ipts_object_t* obj)
-+{
-+	i915_gem_object_unpin_map(obj->gem_obj);
-+	obj->cpu_addr = NULL;
-+}
-+
-+static int create_ipts_context(void)
-+{
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct intel_ring *pin_ret;
-+	int ret = 0;
-+
-+	/* Initialize the context right away.*/
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return ret;
-+	}
-+
-+	ipts_ctx = i915_gem_context_create_ipts(intel_ipts.dev);
-+	if (IS_ERR(ipts_ctx)) {
-+		DRM_ERROR("Failed to create IPTS context (error %ld)\n",
-+			  PTR_ERR(ipts_ctx));
-+		ret = PTR_ERR(ipts_ctx);
-+		goto err_unlock;
-+	}
-+
-+	ret = execlists_context_deferred_alloc(ipts_ctx, dev_priv->engine[RCS]);
-+	if (ret) {
-+		DRM_DEBUG("lr context allocation failed : %d\n", ret);
-+		goto err_ctx;
-+	}
-+
-+	pin_ret = execlists_context_pin(dev_priv->engine[RCS], ipts_ctx);
-+	if (IS_ERR(pin_ret)) {
-+		DRM_DEBUG("lr context pinning failed :  %ld\n", PTR_ERR(pin_ret));
-+		goto err_ctx;
-+	}
-+
-+	/* Release the mutex */
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	spin_lock_init(&intel_ipts.buffers.lock);
-+	INIT_LIST_HEAD(&intel_ipts.buffers.list);
-+
-+	intel_ipts.ipts_context = ipts_ctx;
-+
-+	return 0;
-+
-+err_ctx:
-+	if (ipts_ctx)
-+		i915_gem_context_put(ipts_ctx);
-+
-+err_unlock:
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return ret;
-+}
-+
-+static void destroy_ipts_context(void)
-+{
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	ipts_ctx = intel_ipts.ipts_context;
-+
-+	/* Initialize the context right away.*/
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return;
-+	}
-+
-+	execlists_context_unpin(dev_priv->engine[RCS], ipts_ctx);
-+	i915_gem_context_put(ipts_ctx);
-+
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+}
-+
-+int intel_ipts_notify_complete(void)
-+{
-+	if (intel_ipts.ipts_clbks.workload_complete)
-+		intel_ipts.ipts_clbks.workload_complete(intel_ipts.data);
-+
-+	return 0;
-+}
-+
-+int intel_ipts_notify_backlight_status(bool backlight_on)
-+{
-+	if (intel_ipts.ipts_clbks.notify_gfx_status) {
-+		if (backlight_on) {
-+			intel_ipts.ipts_clbks.notify_gfx_status(
-+						IPTS_NOTIFY_STA_BACKLIGHT_ON,
-+						intel_ipts.data);
-+			schedule_delayed_work(&intel_ipts.reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+		} else {
-+			intel_ipts.ipts_clbks.notify_gfx_status(
-+						IPTS_NOTIFY_STA_BACKLIGHT_OFF,
-+						intel_ipts.data);
-+			cancel_delayed_work(&intel_ipts.reacquire_db_work);
-+		}
-+	}
-+
-+	return 0;
-+}
-+
-+static void intel_ipts_reacquire_db(intel_ipts_t *intel_ipts_p)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts_p->dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return;
-+	}
-+
-+	/* Reacquire the doorbell */
-+	i915_guc_ipts_reacquire_doorbell(intel_ipts_p->dev->dev_private);
-+
-+	mutex_unlock(&intel_ipts_p->dev->struct_mutex);
-+
-+	return;
-+}
-+
-+static int intel_ipts_get_wq_info(uint64_t gfx_handle,
-+						intel_ipts_wq_info_t *wq_info)
-+{
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	*wq_info = intel_ipts.wq_info;
-+
-+	intel_ipts_reacquire_db(&intel_ipts);
-+	schedule_delayed_work(&intel_ipts.reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+
-+	return 0;
-+}
-+
-+static int set_wq_info(void)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct intel_guc *guc = &dev_priv->guc;
-+	struct intel_guc_client *client;
-+	struct guc_process_desc *desc;
-+	void *base = NULL;
-+	intel_ipts_wq_info_t *wq_info;
-+	u64 phy_base = 0;
-+
-+	wq_info = &intel_ipts.wq_info;
-+
-+	client = guc->ipts_client;
-+	if (!client) {
-+		DRM_ERROR("IPTS GuC client is NOT available\n");
-+		return -EINVAL;
-+	}
-+
-+	base = client->vaddr;
-+	desc = (struct guc_process_desc *)((u64)base + client->proc_desc_offset);
-+
-+	desc->wq_base_addr = (u64)base + GUC_DB_SIZE;
-+	desc->db_base_addr = (u64)base + client->doorbell_offset;
-+
-+	/* IPTS expects physical addresses to pass it to ME */
-+	phy_base = sg_dma_address(client->vma->pages->sgl);
-+
-+	wq_info->db_addr = desc->db_base_addr;
-+        wq_info->db_phy_addr = phy_base + client->doorbell_offset;
-+        wq_info->db_cookie_offset = offsetof(struct guc_doorbell_info, cookie);
-+        wq_info->wq_addr = desc->wq_base_addr;
-+        wq_info->wq_phy_addr = phy_base + GUC_DB_SIZE;
-+        wq_info->wq_head_addr = (u64)&desc->head;
-+        wq_info->wq_head_phy_addr = phy_base + client->proc_desc_offset +
-+					offsetof(struct guc_process_desc, head);
-+        wq_info->wq_tail_addr = (u64)&desc->tail;
-+        wq_info->wq_tail_phy_addr = phy_base + client->proc_desc_offset +
-+					offsetof(struct guc_process_desc, tail);
-+        wq_info->wq_size = desc->wq_size_bytes;
-+
-+	return 0;
-+}
-+
-+static int intel_ipts_init_wq(void)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed\n");
-+		return ret;
-+	}
-+
-+	/* disable IPTS submission */
-+	i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private);
-+
-+	/* enable IPTS submission */
-+	ret = i915_guc_ipts_submission_enable(intel_ipts.dev->dev_private,
-+							intel_ipts.ipts_context);
-+	if (ret) {
-+		DRM_ERROR("i915_guc_ipts_submission_enable failed : %d\n", ret);
-+		goto out;
-+        }
-+
-+	ret = set_wq_info();
-+	if (ret) {
-+		DRM_ERROR("set_wq_info failed\n");
-+		goto out;
-+	}
-+
-+out:
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return ret;
-+}
-+
-+static void intel_ipts_release_wq(void)
-+{
-+	int ret = 0;
-+
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed\n");
-+		return;
-+	}
-+
-+	/* disable IPTS submission */
-+	i915_guc_ipts_submission_disable(intel_ipts.dev->dev_private);
-+
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+}
-+
-+static int intel_ipts_map_buffer(u64 gfx_handle, intel_ipts_mapbuffer_t *mapbuf)
-+{
-+	intel_ipts_object_t* obj;
-+	struct i915_gem_context *ipts_ctx = NULL;
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	struct i915_address_space *vm = NULL;
-+	struct i915_vma *vma = NULL;
-+	int ret = 0;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	/* Acquire mutex first */
-+	ret = i915_mutex_lock_interruptible(intel_ipts.dev);
-+	if (ret) {
-+		DRM_ERROR("i915_mutex_lock_interruptible failed \n");
-+		return -EINVAL;
-+	}
-+
-+	obj = ipts_object_create(mapbuf->size, mapbuf->flags);
-+	if (!obj)
-+		return -ENOMEM;
-+
-+	ipts_ctx = intel_ipts.ipts_context;
-+	ret = ipts_object_pin(obj, ipts_ctx);
-+	if (ret) {
-+		DRM_ERROR("Not able to pin iTouch obj\n");
-+		ipts_object_free(obj);
-+		mutex_unlock(&intel_ipts.dev->struct_mutex);
-+		return -ENOMEM;
-+	}
-+
-+	if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		obj->cpu_addr = obj->gem_obj->phys_handle->vaddr;
-+	} else {
-+		obj->cpu_addr = ipts_object_map(obj);
-+	}
-+
-+	if (ipts_ctx->ppgtt) {
-+		vm = &ipts_ctx->ppgtt->base;
-+	} else {
-+		vm = &dev_priv->ggtt.base;
-+	}
-+
-+	vma = i915_vma_instance(obj->gem_obj, vm, NULL);
-+	if (IS_ERR(vma)) {
-+		DRM_ERROR("cannot find or create vma\n");
-+		return -EINVAL;
-+	}
-+
-+	mapbuf->gfx_addr = (void*)vma->node.start;
-+	mapbuf->cpu_addr = (void*)obj->cpu_addr;
-+	mapbuf->buf_handle = (u64)obj;
-+	if (mapbuf->flags & IPTS_BUF_FLAG_CONTIGUOUS) {
-+		mapbuf->phy_addr = (u64)obj->gem_obj->phys_handle->busaddr;
-+	}
-+
-+	/* Release the mutex */
-+	mutex_unlock(&intel_ipts.dev->struct_mutex);
-+
-+	return 0;
-+}
-+
-+static int intel_ipts_unmap_buffer(uint64_t gfx_handle, uint64_t buf_handle)
-+{
-+	intel_ipts_object_t* obj = (intel_ipts_object_t*)buf_handle;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return -EINVAL;
-+	}
-+
-+	if (!obj->gem_obj->phys_handle)
-+		ipts_object_unmap(obj);
-+	ipts_object_unpin(obj);
-+	ipts_object_free(obj);
-+
-+	return 0;
-+}
-+
-+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect)
-+{
-+	struct drm_i915_private *dev_priv = to_i915(intel_ipts.dev);
-+	int ret = 0;
-+
-+	if (!intel_ipts.initialized)
-+		return -EIO;
-+
-+	if (ipts_connect && ipts_connect->if_version <=
-+					SUPPORTED_IPTS_INTERFACE_VERSION) {
-+
-+		/* return gpu operations for ipts */
-+		ipts_connect->ipts_ops.get_wq_info = intel_ipts_get_wq_info;
-+		ipts_connect->ipts_ops.map_buffer = intel_ipts_map_buffer;
-+		ipts_connect->ipts_ops.unmap_buffer = intel_ipts_unmap_buffer;
-+		ipts_connect->gfx_version = INTEL_INFO(dev_priv)->gen;
-+		ipts_connect->gfx_handle = (uint64_t)&intel_ipts;
-+
-+		/* save callback and data */
-+		intel_ipts.data = ipts_connect->data;
-+		intel_ipts.ipts_clbks = ipts_connect->ipts_cb;
-+
-+		intel_ipts.connected = true;
-+	} else {
-+		ret = -EINVAL;
-+	}
-+
-+	return ret;
-+}
-+EXPORT_SYMBOL_GPL(intel_ipts_connect);
-+
-+void intel_ipts_disconnect(uint64_t gfx_handle)
-+{
-+	if (!intel_ipts.initialized)
-+		return;
-+
-+	if (gfx_handle != (uint64_t)&intel_ipts ||
-+					intel_ipts.connected == false) {
-+		DRM_ERROR("invalid gfx handle\n");
-+		return;
-+	}
-+
-+	intel_ipts.data = 0;
-+	memset(&intel_ipts.ipts_clbks, 0, sizeof(intel_ipts_callback_t));
-+
-+	intel_ipts.connected = false;
-+}
-+EXPORT_SYMBOL_GPL(intel_ipts_disconnect);
-+
-+static void reacquire_db_work_func(struct work_struct *work)
-+{
-+	struct delayed_work *d_work = container_of(work, struct delayed_work,
-+							work);
-+	intel_ipts_t *intel_ipts_p = container_of(d_work, intel_ipts_t,
-+							reacquire_db_work);
-+	u32 head;
-+	u32 tail;
-+	u32 size;
-+	u32 load;
-+
-+	head = *(u32*)intel_ipts_p->wq_info.wq_head_addr;
-+	tail = *(u32*)intel_ipts_p->wq_info.wq_tail_addr;
-+	size = intel_ipts_p->wq_info.wq_size;
-+
-+	if (head >= tail)
-+		load = head - tail;
-+	else
-+		load = head + size - tail;
-+
-+	if (load < REACQUIRE_DB_THRESHOLD) {
-+		intel_ipts_p->need_reacquire_db = false;
-+		goto reschedule_work;
-+	}
-+
-+	if (intel_ipts_p->need_reacquire_db) {
-+		if (intel_ipts_p->old_head == head && intel_ipts_p->old_tail == tail)
-+			intel_ipts_reacquire_db(intel_ipts_p);
-+		intel_ipts_p->need_reacquire_db = false;
-+	} else {
-+		intel_ipts_p->old_head = head;
-+		intel_ipts_p->old_tail = tail;
-+		intel_ipts_p->need_reacquire_db = true;
-+
-+		/* recheck */
-+		schedule_delayed_work(&intel_ipts_p->reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP2_INTERVAL));
-+		return;
-+	}
-+
-+reschedule_work:
-+	schedule_delayed_work(&intel_ipts_p->reacquire_db_work,
-+				msecs_to_jiffies(DB_LOST_CHECK_STEP1_INTERVAL));
-+}
-+
-+/**
-+ * intel_ipts_init - Initialize ipts support
-+ * @dev: drm device
-+ *
-+ * Setup the required structures for ipts.
-+ */
-+int intel_ipts_init(struct drm_device *dev)
-+{
-+	int ret = 0;
-+
-+	pr_info("ipts: initializing ipts\n");
-+
-+	intel_ipts.dev = dev;
-+	INIT_DELAYED_WORK(&intel_ipts.reacquire_db_work, reacquire_db_work_func);
-+
-+	ret = create_ipts_context();
-+	if (ret)
-+		return -ENOMEM;
-+
-+	ret = intel_ipts_init_wq();
-+	if (ret)
-+		return ret;
-+
-+	intel_ipts.initialized = true;
-+	DRM_DEBUG_DRIVER("Intel iTouch framework initialized\n");
-+
-+	return ret;
-+}
-+
-+void intel_ipts_cleanup(struct drm_device *dev)
-+{
-+	intel_ipts_object_t *obj, *n;
-+
-+	if (intel_ipts.dev == dev) {
-+		list_for_each_entry_safe(obj, n, &intel_ipts.buffers.list, list) {
-+			list_del(&obj->list);
-+
-+			if (!obj->gem_obj->phys_handle)
-+				ipts_object_unmap(obj);
-+			ipts_object_unpin(obj);
-+			i915_gem_free_object(&obj->gem_obj->base);
-+			kfree(obj);
-+		}
-+
-+		intel_ipts_release_wq();
-+		destroy_ipts_context();
-+		cancel_delayed_work(&intel_ipts.reacquire_db_work);
-+	}
-+}
-diff --git a/drivers/gpu/drm/i915/intel_ipts.h b/drivers/gpu/drm/i915/intel_ipts.h
-new file mode 100644
-index 000000000000..a6965d102417
---- /dev/null
-+++ b/drivers/gpu/drm/i915/intel_ipts.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Copyright © 2016 Intel Corporation
-+ *
-+ * Permission is hereby granted, free of charge, to any person obtaining a
-+ * copy of this software and associated documentation files (the "Software"),
-+ * to deal in the Software without restriction, including without limitation
-+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
-+ * and/or sell copies of the Software, and to permit persons to whom the
-+ * Software is furnished to do so, subject to the following conditions:
-+ *
-+ * The above copyright notice and this permission notice (including the next
-+ * paragraph) shall be included in all copies or substantial portions of the
-+ * Software.
-+ *
-+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
-+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-+ * IN THE SOFTWARE.
-+ *
-+ */
-+#ifndef _INTEL_IPTS_H_
-+#define _INTEL_IPTS_H_
-+
-+struct drm_device;
-+
-+int intel_ipts_init(struct drm_device *dev);
-+void intel_ipts_cleanup(struct drm_device *dev);
-+int intel_ipts_notify_backlight_status(bool backlight_on);
-+int intel_ipts_notify_complete(void);
-+
-+#endif //_INTEL_IPTS_H_
-diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
-index 8704f7f8d072..3918b3b778db 100644
---- a/drivers/gpu/drm/i915/intel_lrc.c
-+++ b/drivers/gpu/drm/i915/intel_lrc.c
-@@ -162,8 +162,6 @@
- #define WA_TAIL_DWORDS 2
- #define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS)
- 
--static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
--					    struct intel_engine_cs *engine);
- static void execlists_init_reg_state(u32 *reg_state,
- 				     struct i915_gem_context *ctx,
- 				     struct intel_engine_cs *engine,
-@@ -1187,7 +1185,7 @@ static int __context_pin(struct i915_gem_context *ctx, struct i915_vma *vma)
- 	return i915_vma_pin(vma, 0, GEN8_LR_CONTEXT_ALIGN, flags);
- }
- 
--static struct intel_ring *
-+struct intel_ring *
- execlists_context_pin(struct intel_engine_cs *engine,
- 		      struct i915_gem_context *ctx)
- {
-@@ -1240,7 +1238,7 @@ execlists_context_pin(struct intel_engine_cs *engine,
- 	return ERR_PTR(ret);
- }
- 
--static void execlists_context_unpin(struct intel_engine_cs *engine,
-+void execlists_context_unpin(struct intel_engine_cs *engine,
- 				    struct i915_gem_context *ctx)
- {
- 	struct intel_context *ce = &ctx->engine[engine->id];
-@@ -2193,6 +2191,9 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
- 
- 	logical_ring_setup(engine);
- 
-+	engine->irq_keep_mask |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT
-+							<< GEN8_RCS_IRQ_SHIFT;
-+
- 	if (HAS_L3_DPF(dev_priv))
- 		engine->irq_keep_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
- 
-@@ -2455,7 +2456,7 @@ populate_lr_context(struct i915_gem_context *ctx,
- 	return 0;
- }
- 
--static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
-+int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
- 					    struct intel_engine_cs *engine)
- {
- 	struct drm_i915_gem_object *ctx_obj;
-diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
-index 59d7b86012e9..c3d42a5dfe22 100644
---- a/drivers/gpu/drm/i915/intel_lrc.h
-+++ b/drivers/gpu/drm/i915/intel_lrc.h
-@@ -111,4 +111,12 @@ intel_lr_context_descriptor(struct i915_gem_context *ctx,
- 	return ctx->engine[engine->id].lrc_desc;
- }
- 
-+struct intel_ring *
-+execlists_context_pin(struct intel_engine_cs *engine,
-+		      struct i915_gem_context *ctx);
-+void execlists_context_unpin(struct intel_engine_cs *engine,
-+				    struct i915_gem_context *ctx);
-+int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
-+					    struct intel_engine_cs *engine);
-+
- #endif /* _INTEL_LRC_H_ */
-diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
-index 41d00b1603e3..c0de071d19e7 100644
---- a/drivers/gpu/drm/i915/intel_panel.c
-+++ b/drivers/gpu/drm/i915/intel_panel.c
-@@ -34,6 +34,7 @@
- #include <linux/moduleparam.h>
- #include <linux/pwm.h>
- #include "intel_drv.h"
-+#include "intel_ipts.h"
- 
- #define CRC_PMIC_PWM_PERIOD_NS	21333
- 
-@@ -679,6 +680,9 @@ static void lpt_disable_backlight(const struct drm_connector_state *old_conn_sta
- 	struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
- 	u32 tmp;
- 
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc && i915_modparams.enable_ipts)
-+		intel_ipts_notify_backlight_status(false);
-+
- 	intel_panel_actually_set_backlight(old_conn_state, 0);
- 
- 	/*
-@@ -866,6 +870,9 @@ static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
- 
- 	/* This won't stick until the above enable. */
- 	intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
-+
-+	if (INTEL_GEN(dev_priv) >= 9 && i915_modparams.enable_guc && i915_modparams.enable_ipts)
-+		intel_ipts_notify_backlight_status(true);
- }
- 
- static void pch_enable_backlight(const struct intel_crtc_state *crtc_state,
-diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
-index dad2fbb0e3f8..1e561872a17f 100644
---- a/drivers/hid/hid-multitouch.c
-+++ b/drivers/hid/hid-multitouch.c
-@@ -150,6 +150,7 @@ struct mt_device {
- 
- static void mt_post_parse_default_settings(struct mt_device *td);
- static void mt_post_parse(struct mt_device *td);
-+static int cc_seen = 0;
- 
- /* classes of device behavior */
- #define MT_CLS_DEFAULT				0x0001
-@@ -633,8 +634,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 			if (field->index >= field->report->maxfield ||
- 			    usage->usage_index >= field->report_count)
- 				return 1;
--			td->cc_index = field->index;
--			td->cc_value_index = usage->usage_index;
-+
-+			if(cc_seen != 1) {
-+				td->cc_index = field->index;
-+				td->cc_value_index = usage->usage_index;
-+				cc_seen++;
-+			}
- 			return 1;
- 		case HID_DG_AZIMUTH:
- 			hid_map_usage(hi, usage, bit, max,
-@@ -685,6 +690,16 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 	return 0;
- }
- 
-+static int mt_touch_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-+		struct hid_field *field, struct hid_usage *usage,
-+		unsigned long **bit, int *max)
-+{
-+	if (usage->type == EV_KEY || usage->type == EV_ABS)
-+		set_bit(usage->type, hi->input->evbit);
-+
-+	return -1;
-+}
-+
- static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
- {
- 	__s32 quirks = td->mtclass.quirks;
-@@ -1081,9 +1096,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
- 	    field->application != HID_DG_TOUCHSCREEN &&
- 	    field->application != HID_DG_PEN &&
- 	    field->application != HID_DG_TOUCHPAD &&
-+		field->application != HID_GD_MOUSE &&
- 	    field->application != HID_GD_KEYBOARD &&
- 	    field->application != HID_GD_SYSTEM_CONTROL &&
- 	    field->application != HID_CP_CONSUMER_CONTROL &&
-+		field->logical != HID_DG_TOUCHSCREEN &&
- 	    field->application != HID_GD_WIRELESS_RADIO_CTLS &&
- 	    !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
- 	      td->mtclass.quirks & MT_QUIRK_ASUS_CUSTOM_UP))
-@@ -1146,10 +1163,8 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
- 		return 0;
- 
- 	if (field->application == HID_DG_TOUCHSCREEN ||
--	    field->application == HID_DG_TOUCHPAD) {
--		/* We own these mappings, tell hid-input to ignore them */
--		return -1;
--	}
-+	    field->application == HID_DG_TOUCHPAD)
-+		return mt_touch_input_mapped(hdev, hi, field, usage, bit, max);
- 
- 	/* let hid-core decide for the others */
- 	return 0;
-@@ -1292,6 +1307,7 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
- 		suffix = "Pen";
- 		/* force BTN_STYLUS to allow tablet matching in udev */
- 		__set_bit(BTN_STYLUS, hi->input->keybit);
-+        __set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
- 	} else {
- 		switch (field->application) {
- 		case HID_GD_KEYBOARD:
-@@ -1307,9 +1323,10 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
- 			suffix = "Pen";
- 			/* force BTN_STYLUS to allow tablet matching in udev */
- 			__set_bit(BTN_STYLUS, hi->input->keybit);
-+            __set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
- 			break;
- 		case HID_DG_TOUCHSCREEN:
--			/* we do not set suffix = "Touchscreen" */
-+			suffix = "Touchscreen";
- 			break;
- 		case HID_DG_TOUCHPAD:
- 			suffix = "Touchpad";
-@@ -1440,6 +1457,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
- 	td->cc_index = -1;
- 	td->scantime_index = -1;
- 	td->mt_report_id = -1;
-+	cc_seen = 0;
- 	hid_set_drvdata(hdev, td);
- 
- 	td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields),
-diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
-index 5d713008749b..a7b48481cf40 100644
---- a/drivers/misc/Kconfig
-+++ b/drivers/misc/Kconfig
-@@ -506,6 +506,7 @@ source "drivers/misc/ti-st/Kconfig"
- source "drivers/misc/lis3lv02d/Kconfig"
- source "drivers/misc/altera-stapl/Kconfig"
- source "drivers/misc/mei/Kconfig"
-+source "drivers/misc/ipts/Kconfig"
- source "drivers/misc/vmw_vmci/Kconfig"
- source "drivers/misc/mic/Kconfig"
- source "drivers/misc/genwqe/Kconfig"
-diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
-index 20be70c3f118..e99a59131282 100644
---- a/drivers/misc/Makefile
-+++ b/drivers/misc/Makefile
-@@ -43,6 +43,7 @@ obj-y				+= lis3lv02d/
- obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
- obj-$(CONFIG_ALTERA_STAPL)	+=altera-stapl/
- obj-$(CONFIG_INTEL_MEI)		+= mei/
-+obj-$(CONFIG_INTEL_IPTS)	+= ipts/
- obj-$(CONFIG_VMWARE_VMCI)	+= vmw_vmci/
- obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
- obj-$(CONFIG_SRAM)		+= sram.o
-diff --git a/drivers/misc/ipts/Kconfig b/drivers/misc/ipts/Kconfig
-new file mode 100644
-index 000000000000..360ed3861b82
---- /dev/null
-+++ b/drivers/misc/ipts/Kconfig
-@@ -0,0 +1,9 @@
-+config INTEL_IPTS
-+	tristate "Intel Precise Touch & Stylus"
-+	select INTEL_MEI
-+	depends on X86 && PCI && HID
-+	help
-+	  Intel Precise Touch & Stylus support
-+	  Supported SoCs:
-+	  Intel Skylake
-+	  Intel Kabylake
-diff --git a/drivers/misc/ipts/Makefile b/drivers/misc/ipts/Makefile
-new file mode 100644
-index 000000000000..1783e9cf13c9
---- /dev/null
-+++ b/drivers/misc/ipts/Makefile
-@@ -0,0 +1,13 @@
-+#
-+# Makefile - Intel Precise Touch & Stylus device driver
-+# Copyright (c) 2016, Intel Corporation.
-+#
-+
-+obj-$(CONFIG_INTEL_IPTS)+= intel-ipts.o
-+intel-ipts-objs += ipts-mei.o
-+intel-ipts-objs += ipts-hid.o
-+intel-ipts-objs += ipts-msg-handler.o
-+intel-ipts-objs += ipts-kernel.o
-+intel-ipts-objs += ipts-resource.o
-+intel-ipts-objs += ipts-gfx.o
-+intel-ipts-$(CONFIG_DEBUG_FS) += ipts-dbgfs.o
-diff --git a/drivers/misc/ipts/ipts-binary-spec.h b/drivers/misc/ipts/ipts-binary-spec.h
-new file mode 100644
-index 000000000000..87d4bc4133c4
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-binary-spec.h
-@@ -0,0 +1,118 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus binary spec
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_BINARY_SPEC_H
-+#define _IPTS_BINARY_SPEC_H
-+
-+#define IPTS_BIN_HEADER_VERSION 2
-+
-+#pragma pack(1)
-+
-+/* we support 16 output buffers(1:feedback, 15:HID) */
-+#define  MAX_NUM_OUTPUT_BUFFERS 16
-+
-+typedef enum {
-+	IPTS_BIN_KERNEL,
-+	IPTS_BIN_RO_DATA,
-+	IPTS_BIN_RW_DATA,
-+	IPTS_BIN_SENSOR_FRAME,
-+	IPTS_BIN_OUTPUT,
-+	IPTS_BIN_DYNAMIC_STATE_HEAP,
-+	IPTS_BIN_PATCH_LOCATION_LIST,
-+	IPTS_BIN_ALLOCATION_LIST,
-+	IPTS_BIN_COMMAND_BUFFER_PACKET,
-+	IPTS_BIN_TAG,
-+} ipts_bin_res_type_t;
-+
-+typedef struct ipts_bin_header {
-+	char str[4];
-+	unsigned int version;
-+
-+#if IPTS_BIN_HEADER_VERSION > 1
-+	unsigned int gfxcore;
-+	unsigned int revid;
-+#endif
-+} ipts_bin_header_t;
-+
-+typedef struct ipts_bin_alloc {
-+	unsigned int handle;
-+	unsigned int reserved;
-+} ipts_bin_alloc_t;
-+
-+typedef struct ipts_bin_alloc_list {
-+	unsigned int num;
-+	ipts_bin_alloc_t alloc[];
-+} ipts_bin_alloc_list_t;
-+
-+typedef struct ipts_bin_cmdbuf {
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_cmdbuf_t;
-+
-+typedef struct ipts_bin_res {
-+	unsigned int handle;
-+	ipts_bin_res_type_t type;
-+	unsigned int initialize;
-+	unsigned int aligned_size;
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_res_t;
-+
-+typedef enum {
-+	IPTS_INPUT,
-+	IPTS_OUTPUT,
-+	IPTS_CONFIGURATION,
-+	IPTS_CALIBRATION,
-+	IPTS_FEATURE,
-+} ipts_bin_io_buffer_type_t;
-+
-+typedef struct ipts_bin_io_header {
-+	char str[10];
-+	unsigned short type;
-+} ipts_bin_io_header_t;
-+
-+typedef struct ipts_bin_res_list {
-+	unsigned int num;
-+	ipts_bin_res_t res[];
-+} ipts_bin_res_list_t;
-+
-+typedef struct ipts_bin_patch {
-+	unsigned int index;
-+	unsigned int reserved1[2];
-+	unsigned int alloc_offset;
-+	unsigned int patch_offset;
-+	unsigned int reserved2;
-+} ipts_bin_patch_t;
-+
-+typedef struct ipts_bin_patch_list {
-+	unsigned int num;
-+	ipts_bin_patch_t patch[];
-+} ipts_bin_patch_list_t;
-+
-+typedef struct ipts_bin_guc_wq_info {
-+	unsigned int batch_offset;
-+	unsigned int size;
-+	char data[];
-+} ipts_bin_guc_wq_info_t;
-+
-+typedef struct ipts_bin_bufid_patch {
-+	unsigned int imm_offset;
-+	unsigned int mem_offset;
-+} ipts_bin_bufid_patch_t;
-+
-+#pragma pack()
-+
-+#endif /* _IPTS_BINARY_SPEC_H */
-diff --git a/drivers/misc/ipts/ipts-dbgfs.c b/drivers/misc/ipts/ipts-dbgfs.c
-new file mode 100644
-index 000000000000..1c5c92f7d4ba
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-dbgfs.c
-@@ -0,0 +1,152 @@
-+/*
-+ * Intel Precise Touch & Stylus device driver
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/debugfs.h>
-+#include <linux/ctype.h>
-+#include <linux/uaccess.h>
-+
-+#include "ipts.h"
-+#include "ipts-sensor-regs.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-state.h"
-+
-+const char sensor_mode_fmt[] = "sensor mode : %01d\n";
-+const char ipts_status_fmt[] = "sensor mode : %01d\nipts state : %01d\n";
-+
-+static ssize_t ipts_dbgfs_mode_read(struct file *fp, char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	char mode[80];
-+	int len = 0;
-+
-+	if (cnt < sizeof(sensor_mode_fmt) - 3)
-+		return -EINVAL;
-+
-+	len = scnprintf(mode, 80, sensor_mode_fmt, ipts->sensor_mode);
-+	if (len < 0)
-+		return -EIO;
-+
-+	return simple_read_from_buffer(ubuf, cnt, ppos, mode, len);
-+}
-+
-+static ssize_t ipts_dbgfs_mode_write(struct file *fp, const char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	ipts_state_t state;
-+	int sensor_mode, len;
-+	char mode[3];
-+
-+	if (cnt == 0 || cnt > 3)
-+		return -EINVAL;
-+
-+	state = ipts_get_state(ipts);
-+	if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED) {
-+		return -EIO;
-+	}
-+
-+	len = cnt;
-+	if (copy_from_user(mode, ubuf, len))
-+		return -EFAULT;
-+
-+	while(len > 0 && (isspace(mode[len-1]) || mode[len-1] == '\n'))
-+		len--;
-+	mode[len] = '\0';
-+
-+	if (sscanf(mode, "%d", &sensor_mode) != 1)
-+		return -EINVAL;
-+
-+	if (sensor_mode != TOUCH_SENSOR_MODE_RAW_DATA &&
-+					sensor_mode != TOUCH_SENSOR_MODE_HID) {
-+		return -EINVAL;
-+	}
-+
-+	if (sensor_mode == ipts->sensor_mode)
-+		return 0;
-+
-+	ipts_switch_sensor_mode(ipts, sensor_mode);
-+
-+	return cnt;
-+}
-+
-+static const struct file_operations ipts_mode_dbgfs_fops = {
-+        .open = simple_open,
-+        .read = ipts_dbgfs_mode_read,
-+        .write = ipts_dbgfs_mode_write,
-+        .llseek = generic_file_llseek,
-+};
-+
-+static ssize_t ipts_dbgfs_status_read(struct file *fp, char __user *ubuf,
-+						size_t cnt, loff_t *ppos)
-+{
-+	ipts_info_t *ipts = fp->private_data;
-+	char status[256];
-+	int len = 0;
-+
-+	if (cnt < sizeof(ipts_status_fmt) - 3)
-+		return -EINVAL;
-+
-+	len = scnprintf(status, 256, ipts_status_fmt, ipts->sensor_mode,
-+						     ipts->state);
-+	if (len < 0)
-+		return -EIO;
-+
-+	return simple_read_from_buffer(ubuf, cnt, ppos, status, len);
-+}
-+
-+static const struct file_operations ipts_status_dbgfs_fops = {
-+        .open = simple_open,
-+        .read = ipts_dbgfs_status_read,
-+        .llseek = generic_file_llseek,
-+};
-+
-+void ipts_dbgfs_deregister(ipts_info_t* ipts)
-+{
-+	if (!ipts->dbgfs_dir)
-+		return;
-+
-+	debugfs_remove_recursive(ipts->dbgfs_dir);
-+	ipts->dbgfs_dir = NULL;
-+}
-+
-+int ipts_dbgfs_register(ipts_info_t* ipts, const char *name)
-+{
-+	struct dentry *dir, *f;
-+
-+	dir = debugfs_create_dir(name, NULL);
-+	if (!dir)
-+		return -ENOMEM;
-+
-+        f = debugfs_create_file("mode", S_IRUSR | S_IWUSR, dir,
-+                                ipts, &ipts_mode_dbgfs_fops);
-+        if (!f) {
-+                ipts_err(ipts, "debugfs mode creation failed\n");
-+                goto err;
-+        }
-+
-+        f = debugfs_create_file("status", S_IRUSR, dir,
-+                                ipts, &ipts_status_dbgfs_fops);
-+        if (!f) {
-+                ipts_err(ipts, "debugfs status creation failed\n");
-+                goto err;
-+        }
-+
-+	ipts->dbgfs_dir = dir;
-+
-+	return 0;
-+err:
-+	ipts_dbgfs_deregister(ipts);
-+	return -ENODEV;
-+}
-diff --git a/drivers/misc/ipts/ipts-gfx.c b/drivers/misc/ipts/ipts-gfx.c
-new file mode 100644
-index 000000000000..51727770e75d
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-gfx.c
-@@ -0,0 +1,184 @@
-+/*
-+ *
-+ * Intel Integrated Touch Gfx Interface Layer
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/kthread.h>
-+#include <linux/delay.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-state.h"
-+
-+static void gfx_processing_complete(void *data)
-+{
-+	ipts_info_t *ipts = data;
-+
-+	if (ipts_get_state(ipts) == IPTS_STA_RAW_DATA_STARTED) {
-+		schedule_work(&ipts->raw_data_work);
-+		return;
-+	}
-+
-+	ipts_dbg(ipts, "not ready to handle gfx event\n");
-+}
-+
-+static void notify_gfx_status(u32 status, void *data)
-+{
-+	ipts_info_t *ipts = data;
-+
-+	ipts->gfx_status = status;
-+	schedule_work(&ipts->gfx_status_work);
-+}
-+
-+static int connect_gfx(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	intel_ipts_connect_t ipts_connect;
-+
-+	ipts_connect.if_version = IPTS_INTERFACE_V1;
-+	ipts_connect.ipts_cb.workload_complete = gfx_processing_complete;
-+	ipts_connect.ipts_cb.notify_gfx_status = notify_gfx_status;
-+	ipts_connect.data = (void*)ipts;
-+
-+	ret = intel_ipts_connect(&ipts_connect);
-+	if (ret)
-+		return ret;
-+
-+	/* TODO: gfx version check */
-+	ipts->gfx_info.gfx_handle = ipts_connect.gfx_handle;
-+	ipts->gfx_info.ipts_ops = ipts_connect.ipts_ops;
-+
-+	return ret;
-+}
-+
-+static void disconnect_gfx(ipts_info_t *ipts)
-+{
-+	intel_ipts_disconnect(ipts->gfx_info.gfx_handle);
-+}
-+
-+#ifdef RUN_DBG_THREAD
-+#include "../mei/mei_dev.h"
-+
-+static struct task_struct *dbg_thread;
-+
-+static void ipts_print_dbg_info(ipts_info_t* ipts)
-+{
-+        char fw_sts_str[MEI_FW_STATUS_STR_SZ];
-+	u32 *db, *head, *tail;
-+	intel_ipts_wq_info_t* wq_info;
-+
-+	wq_info = &ipts->resource.wq_info;
-+
-+	mei_fw_status_str(ipts->cldev->bus, fw_sts_str, MEI_FW_STATUS_STR_SZ);
-+	pr_info(">> tdt : fw status : %s\n", fw_sts_str);
-+
-+	db = (u32*)wq_info->db_addr;
-+	head = (u32*)wq_info->wq_head_addr;
-+	tail = (u32*)wq_info->wq_tail_addr;
-+	pr_info(">> == DB s:%x, c:%x ==\n", *db, *(db+1));
-+	pr_info(">> == WQ h:%u, t:%u ==\n", *head, *tail);
-+}
-+
-+static int ipts_dbg_thread(void *data)
-+{
-+	ipts_info_t *ipts = (ipts_info_t *)data;
-+
-+	pr_info(">> start debug thread\n");
-+
-+	while (!kthread_should_stop()) {
-+		if (ipts_get_state(ipts) != IPTS_STA_RAW_DATA_STARTED) {
-+			pr_info("state is not IPTS_STA_RAW_DATA_STARTED : %d\n",
-+							ipts_get_state(ipts));
-+			msleep(5000);
-+			continue;
-+		}
-+
-+		ipts_print_dbg_info(ipts);
-+
-+		msleep(3000);
-+	}
-+
-+	return 0;
-+}
-+#endif
-+
-+int ipts_open_gpu(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ret = connect_gfx(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot connect GPU\n");
-+		return ret;
-+	}
-+
-+	ret = ipts->gfx_info.ipts_ops.get_wq_info(ipts->gfx_info.gfx_handle,
-+							&ipts->resource.wq_info);
-+	if (ret) {
-+		ipts_dbg(ipts, "error in get_wq_info\n");
-+		return ret;
-+	}
-+
-+#ifdef	RUN_DBG_THREAD
-+	dbg_thread = kthread_run(ipts_dbg_thread, (void *)ipts, "ipts_debug");
-+#endif
-+
-+	return 0;
-+}
-+
-+void ipts_close_gpu(ipts_info_t *ipts)
-+{
-+	disconnect_gfx(ipts);
-+
-+#ifdef	RUN_DBG_THREAD
-+	kthread_stop(dbg_thread);
-+#endif
-+}
-+
-+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags)
-+{
-+	intel_ipts_mapbuffer_t *buf;
-+	u64 handle;
-+	int ret;
-+
-+	buf = devm_kzalloc(&ipts->cldev->dev, sizeof(*buf), GFP_KERNEL);
-+	if (!buf)
-+		return NULL;
-+
-+	buf->size = size;
-+	buf->flags = flags;
-+
-+	handle = ipts->gfx_info.gfx_handle;
-+	ret = ipts->gfx_info.ipts_ops.map_buffer(handle, buf);
-+	if (ret) {
-+		devm_kfree(&ipts->cldev->dev, buf);
-+		return NULL;
-+	}
-+
-+	return buf;
-+}
-+
-+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf)
-+{
-+	u64 handle;
-+	int ret;
-+
-+	if (!buf)
-+		return;
-+
-+	handle = ipts->gfx_info.gfx_handle;
-+	ret = ipts->gfx_info.ipts_ops.unmap_buffer(handle, buf->buf_handle);
-+
-+	devm_kfree(&ipts->cldev->dev, buf);
-+}
-diff --git a/drivers/misc/ipts/ipts-gfx.h b/drivers/misc/ipts/ipts-gfx.h
-new file mode 100644
-index 000000000000..03a5f3551ddf
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-gfx.h
-@@ -0,0 +1,24 @@
-+/*
-+ * Intel Precise Touch & Stylus gpu wrapper
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+
-+#ifndef _IPTS_GFX_H_
-+#define _IPTS_GFX_H_
-+
-+int ipts_open_gpu(ipts_info_t *ipts);
-+void ipts_close_gpu(ipts_info_t *ipts);
-+intel_ipts_mapbuffer_t *ipts_map_buffer(ipts_info_t *ipts, u32 size, u32 flags);
-+void ipts_unmap_buffer(ipts_info_t *ipts, intel_ipts_mapbuffer_t *buf);
-+
-+#endif // _IPTS_GFX_H_
-diff --git a/drivers/misc/ipts/ipts-hid.c b/drivers/misc/ipts/ipts-hid.c
-new file mode 100644
-index 000000000000..3b3be6177648
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-hid.c
-@@ -0,0 +1,456 @@
-+/*
-+ * Intel Precise Touch & Stylus HID driver
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/module.h>
-+#include <linux/firmware.h>
-+#include <linux/hid.h>
-+#include <linux/vmalloc.h>
-+
-+#include "ipts.h"
-+#include "ipts-resource.h"
-+#include "ipts-sensor-regs.h"
-+#include "ipts-msg-handler.h"
-+
-+#define BUS_MEI				0x44
-+
-+#define	HID_DESC_INTEL	"intel/ipts/intel_desc.bin"
-+#define	HID_DESC_VENDOR	"intel/ipts/vendor_desc.bin"
-+MODULE_FIRMWARE(HID_DESC_INTEL);
-+MODULE_FIRMWARE(HID_DESC_VENDOR);
-+
-+typedef enum output_buffer_payload_type {
-+	OUTPUT_BUFFER_PAYLOAD_ERROR = 0,
-+	OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT,
-+	OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT,
-+	OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD,
-+	OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER
-+} output_buffer_payload_type_t;
-+
-+typedef struct kernel_output_buffer_header {
-+	u16 length;
-+	u8 payload_type;
-+	u8 reserved1;
-+	touch_hid_private_data_t hid_private_data;
-+	u8 reserved2[28];
-+	u8 data[0];
-+} kernel_output_buffer_header_t;
-+
-+typedef struct kernel_output_payload_error {
-+	u16 severity;
-+	u16 source;
-+	u8 code[4];
-+	char string[128];
-+} kernel_output_payload_error_t;
-+
-+static int ipts_hid_get_hid_descriptor(ipts_info_t *ipts, u8 **desc, int *size)
-+{
-+	u8 *buf;
-+	int hid_size = 0, ret = 0;
-+	const struct firmware *intel_desc = NULL;
-+	const struct firmware *vendor_desc = NULL;
-+	const char *intel_desc_path = HID_DESC_INTEL;
-+	const char *vendor_desc_path = HID_DESC_VENDOR;
-+
-+	ret = request_firmware(&intel_desc, intel_desc_path, &ipts->cldev->dev);
-+	if (ret) {
-+		goto no_hid;
-+	}
-+	hid_size = intel_desc->size;
-+
-+	ret = request_firmware(&vendor_desc, vendor_desc_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_dbg(ipts, "error in reading HID Vendor Descriptor\n");
-+	} else {
-+		hid_size += vendor_desc->size;
-+	}
-+
-+	ipts_dbg(ipts, "hid size = %d\n", hid_size);
-+	buf = vmalloc(hid_size);
-+	if (buf == NULL) {
-+		ret = -ENOMEM;
-+		goto no_mem;
-+	}
-+
-+	memcpy(buf, intel_desc->data, intel_desc->size);
-+	if (vendor_desc) {
-+		memcpy(&buf[intel_desc->size], vendor_desc->data,
-+							vendor_desc->size);
-+		release_firmware(vendor_desc);
-+	}
-+
-+	release_firmware(intel_desc);
-+
-+	*desc = buf;
-+	*size = hid_size;
-+
-+	return 0;
-+no_mem :
-+	if (vendor_desc)
-+		release_firmware(vendor_desc);
-+	release_firmware(intel_desc);
-+
-+no_hid :
-+	return ret;
-+}
-+
-+static int ipts_hid_parse(struct hid_device *hid)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	int ret = 0, size;
-+	u8 *buf;
-+
-+	ipts_dbg(ipts, "ipts_hid_parse() start\n");
-+	ret = ipts_hid_get_hid_descriptor(ipts, &buf, &size);
-+	if (ret != 0) {
-+		ipts_dbg(ipts, "ipts_hid_ipts_get_hid_descriptor ret %d\n", ret);
-+		return -EIO;
-+	}
-+
-+	ret = hid_parse_report(hid, buf, size);
-+	vfree(buf);
-+	if (ret) {
-+		ipts_err(ipts, "hid_parse_report error : %d\n", ret);
-+		goto out;
-+	}
-+
-+	ipts->hid_desc_ready = true;
-+out:
-+	return ret;
-+}
-+
-+static int ipts_hid_start(struct hid_device *hid)
-+{
-+	return 0;
-+}
-+
-+static void ipts_hid_stop(struct hid_device *hid)
-+{
-+	return;
-+}
-+
-+static int ipts_hid_open(struct hid_device *hid)
-+{
-+	return 0;
-+}
-+
-+static void ipts_hid_close(struct hid_device *hid)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+
-+	ipts->hid_desc_ready = false;
-+
-+	return;
-+}
-+
-+static int ipts_hid_send_hid2me_feedback(ipts_info_t *ipts, u32 fb_data_type,
-+							__u8 *buf, size_t count)
-+{
-+	ipts_buffer_info_t *fb_buf;
-+	touch_feedback_hdr_t *feedback;
-+	u8 *payload;
-+	int header_size;
-+	ipts_state_t state;
-+
-+	header_size = sizeof(touch_feedback_hdr_t);
-+
-+	if (count > ipts->resource.hid2me_buffer_size - header_size)
-+		return -EINVAL;
-+
-+	state = ipts_get_state(ipts);
-+	if (state != IPTS_STA_RAW_DATA_STARTED && state != IPTS_STA_HID_STARTED)
-+		return 0;
-+
-+	fb_buf = ipts_get_hid2me_buffer(ipts);
-+	feedback = (touch_feedback_hdr_t *)fb_buf->addr;
-+	payload = fb_buf->addr + header_size;
-+	memset(feedback, 0, header_size);
-+
-+	feedback->feedback_data_type = fb_data_type;
-+	feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE;
-+	feedback->payload_size_bytes = count;
-+	feedback->buffer_id = TOUCH_HID_2_ME_BUFFER_ID;
-+	feedback->protocol_ver = 0;
-+	feedback->reserved[0] = 0xAC;
-+
-+	/* copy payload */
-+	memcpy(payload, buf, count);
-+
-+	ipts_send_feedback(ipts, TOUCH_HID_2_ME_BUFFER_ID, 0);
-+
-+	return 0;
-+}
-+
-+static int ipts_hid_raw_request(struct hid_device *hid,
-+				unsigned char report_number, __u8 *buf,
-+				size_t count, unsigned char report_type,
-+				int reqtype)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	u32 fb_data_type;
-+
-+	ipts_dbg(ipts, "hid raw request => report %d, request %d\n",
-+						 (int)report_type, reqtype);
-+
-+	if (report_type != HID_FEATURE_REPORT)
-+		return 0;
-+
-+	switch (reqtype) {
-+		case HID_REQ_GET_REPORT:
-+			fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES;
-+			break;
-+		case HID_REQ_SET_REPORT:
-+			fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES;
-+			break;
-+		default:
-+			ipts_err(ipts, "raw request not supprted: %d\n", reqtype);
-+			return -EIO;
-+	}
-+
-+	return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count);
-+}
-+
-+static int ipts_hid_output_report(struct hid_device *hid,
-+					__u8 *buf, size_t count)
-+{
-+	ipts_info_t *ipts = hid->driver_data;
-+	u32 fb_data_type;
-+
-+	ipts_dbg(ipts, "hid output report\n");
-+
-+	fb_data_type = TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT;
-+
-+	return ipts_hid_send_hid2me_feedback(ipts, fb_data_type, buf, count);
-+}
-+
-+static struct hid_ll_driver ipts_hid_ll_driver = {
-+	.parse = ipts_hid_parse,
-+	.start = ipts_hid_start,
-+	.stop = ipts_hid_stop,
-+	.open = ipts_hid_open,
-+	.close = ipts_hid_close,
-+	.raw_request = ipts_hid_raw_request,
-+	.output_report = ipts_hid_output_report,
-+};
-+
-+int ipts_hid_init(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	struct hid_device *hid;
-+
-+	hid = hid_allocate_device();
-+	if (IS_ERR(hid)) {
-+		ret = PTR_ERR(hid);
-+		goto err_dev;
-+	}
-+
-+	hid->driver_data = ipts;
-+	hid->ll_driver = &ipts_hid_ll_driver;
-+	hid->dev.parent = &ipts->cldev->dev;
-+	hid->bus = BUS_MEI;
-+	hid->version = ipts->device_info.fw_rev;
-+	hid->vendor = ipts->device_info.vendor_id;
-+	hid->product = ipts->device_info.device_id;
-+
-+	snprintf(hid->phys, sizeof(hid->phys), "heci3");
-+	snprintf(hid->name, sizeof(hid->name),
-+		 "%s %04hX:%04hX", "ipts", hid->vendor, hid->product);
-+
-+	ret = hid_add_device(hid);
-+	if (ret) {
-+		if (ret != -ENODEV)
-+			ipts_err(ipts, "can't add hid device: %d\n", ret);
-+		goto err_mem_free;
-+	}
-+
-+	ipts->hid = hid;
-+
-+	return 0;
-+
-+err_mem_free:
-+	hid_destroy_device(hid);
-+err_dev:
-+	return ret;
-+}
-+
-+void ipts_hid_release(ipts_info_t *ipts)
-+{
-+	if (!ipts->hid)
-+			return;
-+	hid_destroy_device(ipts->hid);
-+}
-+
-+int ipts_handle_hid_data(ipts_info_t *ipts,
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp)
-+{
-+	touch_raw_data_hdr_t *raw_header;
-+	ipts_buffer_info_t *buffer_info;
-+	touch_feedback_hdr_t *feedback;
-+	u8 *raw_data;
-+	int touch_data_buffer_index;
-+	int transaction_id;
-+	int ret = 0;
-+
-+	touch_data_buffer_index = (int)hid_rsp->touch_data_buffer_index;
-+	buffer_info = ipts_get_touch_data_buffer_hid(ipts);
-+	raw_header = (touch_raw_data_hdr_t *)buffer_info->addr;
-+	transaction_id = raw_header->hid_private_data.transaction_id;
-+
-+	raw_data = (u8*)raw_header + sizeof(touch_raw_data_hdr_t);
-+	if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_HID_REPORT) {
-+		memcpy(ipts->hid_input_report, raw_data,
-+				raw_header->raw_data_size_bytes);
-+
-+		ret = hid_input_report(ipts->hid, HID_INPUT_REPORT,
-+					(u8*)ipts->hid_input_report,
-+					raw_header->raw_data_size_bytes, 1);
-+		if (ret) {
-+			ipts_err(ipts, "error in hid_input_report : %d\n", ret);
-+		}
-+	} else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_GET_FEATURES) {
-+		/* TODO: implement together with "get feature ioctl" */
-+	} else if (raw_header->data_type == TOUCH_RAW_DATA_TYPE_ERROR) {
-+		touch_error_t *touch_err = (touch_error_t *)raw_data;
-+
-+		ipts_err(ipts, "error type : %d, me fw error : %x, err reg : %x\n",
-+				touch_err->touch_error_type,
-+				touch_err->touch_me_fw_error.value,
-+				touch_err->touch_error_register.reg_value);
-+	}
-+
-+	/* send feedback data for HID mode */
-+        buffer_info = ipts_get_feedback_buffer(ipts, touch_data_buffer_index);
-+	feedback = (touch_feedback_hdr_t *)buffer_info->addr;
-+	memset(feedback, 0, sizeof(touch_feedback_hdr_t));
-+	feedback->feedback_cmd_type = TOUCH_FEEDBACK_CMD_TYPE_NONE;
-+	feedback->payload_size_bytes = 0;
-+	feedback->buffer_id = touch_data_buffer_index;
-+	feedback->protocol_ver = 0;
-+	feedback->reserved[0] = 0xAC;
-+
-+	ret = ipts_send_feedback(ipts, touch_data_buffer_index, transaction_id);
-+
-+	return ret;
-+}
-+
-+static int handle_outputs(ipts_info_t *ipts, int parallel_idx)
-+{
-+	kernel_output_buffer_header_t *out_buf_hdr;
-+	ipts_buffer_info_t *output_buf, *fb_buf = NULL;
-+	u8 *input_report, *payload;
-+	u32 transaction_id;
-+	int i, payload_size, ret = 0, header_size;
-+
-+	header_size = sizeof(kernel_output_buffer_header_t);
-+	output_buf = ipts_get_output_buffers_by_parallel_id(ipts, parallel_idx);
-+	for (i = 0; i < ipts->resource.num_of_outputs; i++) {
-+		out_buf_hdr = (kernel_output_buffer_header_t*)output_buf[i].addr;
-+		if (out_buf_hdr->length < header_size)
-+			continue;
-+
-+		payload_size = out_buf_hdr->length - header_size;
-+		payload = out_buf_hdr->data;
-+
-+		switch(out_buf_hdr->payload_type) {
-+			case OUTPUT_BUFFER_PAYLOAD_HID_INPUT_REPORT:
-+				input_report = ipts->hid_input_report;
-+				memcpy(input_report, payload, payload_size);
-+				hid_input_report(ipts->hid, HID_INPUT_REPORT,
-+						input_report, payload_size, 1);
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_HID_FEATURE_REPORT:
-+				ipts_dbg(ipts, "output hid feature report\n");
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_KERNEL_LOAD:
-+				ipts_dbg(ipts, "output kernel load\n");
-+				break;
-+			case OUTPUT_BUFFER_PAYLOAD_FEEDBACK_BUFFER:
-+			{
-+				/* send feedback data for raw data mode */
-+                                fb_buf = ipts_get_feedback_buffer(ipts,
-+								parallel_idx);
-+				transaction_id = out_buf_hdr->
-+						hid_private_data.transaction_id;
-+				memcpy(fb_buf->addr, payload, payload_size);
-+				break;
-+			}
-+			case OUTPUT_BUFFER_PAYLOAD_ERROR:
-+			{
-+				kernel_output_payload_error_t *err_payload;
-+
-+				if (payload_size == 0)
-+					break;
-+
-+				err_payload =
-+					(kernel_output_payload_error_t*)payload;
-+
-+				ipts_err(ipts, "error : severity : %d,"
-+						" source : %d,"
-+						" code : %d:%d:%d:%d\n"
-+						"string %s\n",
-+						err_payload->severity,
-+						err_payload->source,
-+						err_payload->code[0],
-+						err_payload->code[1],
-+						err_payload->code[2],
-+						err_payload->code[3],
-+						err_payload->string);
-+				
-+				break;
-+			}
-+			default:
-+				ipts_err(ipts, "invalid output buffer payload\n");
-+				break;
-+		}
-+	}
-+
-+	if (fb_buf) {
-+		ret = ipts_send_feedback(ipts, parallel_idx, transaction_id);
-+		if (ret)
-+			return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static int handle_output_buffers(ipts_info_t *ipts, int cur_idx, int end_idx)
-+{
-+	int max_num_of_buffers = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	do {
-+		cur_idx++; /* cur_idx has last completed so starts with +1 */
-+		cur_idx %= max_num_of_buffers;
-+		handle_outputs(ipts, cur_idx);
-+	} while (cur_idx != end_idx);
-+
-+	return 0;
-+}
-+
-+int ipts_handle_processed_data(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	int current_buffer_idx;
-+	int last_buffer_idx;
-+
-+	current_buffer_idx = *ipts->last_submitted_id;
-+	last_buffer_idx = ipts->last_buffer_completed;
-+
-+	if (current_buffer_idx == last_buffer_idx)
-+		return 0;
-+
-+	ipts->last_buffer_completed = current_buffer_idx;
-+	handle_output_buffers(ipts, last_buffer_idx, current_buffer_idx);
-+
-+	return ret;
-+}
-diff --git a/drivers/misc/ipts/ipts-hid.h b/drivers/misc/ipts/ipts-hid.h
-new file mode 100644
-index 000000000000..f1b22c912df7
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-hid.h
-@@ -0,0 +1,34 @@
-+/*
-+ * Intel Precise Touch & Stylus HID definition
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_HID_H_
-+#define	_IPTS_HID_H_
-+
-+#define	BUS_MEI				0x44
-+
-+#if 0 /* TODO : we have special report ID. will implement them */
-+#define WRITE_CHANNEL_REPORT_ID		0xa
-+#define READ_CHANNEL_REPORT_ID		0xb
-+#define CONFIG_CHANNEL_REPORT_ID	0xd
-+#define VENDOR_INFO_REPORT_ID		0xF
-+#define SINGLE_TOUCH_REPORT_ID		0x40
-+#endif
-+
-+int ipts_hid_init(ipts_info_t *ipts);
-+void ipts_hid_release(ipts_info_t *ipts);
-+int ipts_handle_hid_data(ipts_info_t *ipts,
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_rsp);
-+
-+#endif /* _IPTS_HID_H_ */
-diff --git a/drivers/misc/ipts/ipts-kernel.c b/drivers/misc/ipts/ipts-kernel.c
-new file mode 100644
-index 000000000000..ca5e24ce579e
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-kernel.c
-@@ -0,0 +1,1050 @@
-+#include <linux/module.h>
-+#include <linux/firmware.h>
-+#include <linux/vmalloc.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-resource.h"
-+#include "ipts-binary-spec.h"
-+#include "ipts-state.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-gfx.h"
-+
-+#define MAX_IOCL_FILE_NAME_LEN		80
-+#define MAX_IOCL_FILE_PATH_LEN		256
-+
-+#pragma pack(1)
-+typedef struct bin_data_file_info {
-+    u32 io_buffer_type;
-+    u32 flags;
-+    char file_name[MAX_IOCL_FILE_NAME_LEN];
-+} bin_data_file_info_t;
-+
-+typedef struct bin_fw_info {
-+	char fw_name[MAX_IOCL_FILE_NAME_LEN];
-+
-+	/* list of parameters to load a kernel */
-+	s32 vendor_output;	/* output index. -1 for no use */
-+	u32 num_of_data_files;
-+	bin_data_file_info_t data_file[];
-+} bin_fw_info_t;
-+
-+typedef struct bin_fw_list {
-+	u32 num_of_fws;
-+	bin_fw_info_t fw_info[];
-+} bin_fw_list_t;
-+#pragma pack()
-+
-+/* OpenCL kernel */
-+typedef struct bin_workload {
-+	int cmdbuf_index;
-+	int iobuf_input;
-+	int iobuf_output[MAX_NUM_OUTPUT_BUFFERS];
-+} bin_workload_t;
-+
-+typedef struct bin_buffer {
-+	unsigned int handle;
-+	intel_ipts_mapbuffer_t *buf;
-+	bool no_unmap;	/* only releasing vendor kernel unmaps output buffers */
-+} bin_buffer_t;
-+
-+typedef struct bin_alloc_info {
-+	bin_buffer_t *buffs;
-+	int num_of_allocations;
-+	int num_of_outputs;
-+
-+	int num_of_buffers;
-+} bin_alloc_info_t;
-+
-+typedef struct bin_guc_wq_item {
-+	unsigned int batch_offset;
-+	unsigned int size;
-+	char data[];
-+} bin_guc_wq_item_t;
-+
-+typedef struct bin_kernel_info {
-+	bin_workload_t *wl;
-+	bin_alloc_info_t *alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item;
-+	ipts_bin_bufid_patch_t bufid_patch;
-+
-+	bool is_vendor; /* 1: vendor, 0: postprocessing */
-+} bin_kernel_info_t;
-+
-+typedef struct bin_kernel_list {
-+	intel_ipts_mapbuffer_t *bufid_buf;
-+	int num_of_kernels;
-+	bin_kernel_info_t kernels[];
-+} bin_kernel_list_t;
-+
-+typedef struct bin_parse_info {
-+	u8 *data;
-+	int size;
-+	int parsed;
-+
-+	bin_fw_info_t *fw_info;
-+
-+	/* only used by postprocessing */
-+	bin_kernel_info_t *vendor_kernel;
-+	u32 interested_vendor_output; /* interested vendor output index */
-+} bin_parse_info_t;
-+
-+#define BDW_SURFACE_BASE_ADDRESS		0x6101000e
-+#define SURFACE_STATE_OFFSET_WORD		4
-+#define SBA_OFFSET_BYTES			16384
-+#define LASTSUBMITID_DEFAULT_VALUE		-1
-+
-+#define IPTS_FW_PATH_FMT			"intel/ipts/%s"
-+#define IPTS_FW_CONFIG_FILE			"intel/ipts/ipts_fw_config.bin"
-+
-+MODULE_FIRMWARE(IPTS_FW_CONFIG_FILE);
-+
-+#define IPTS_INPUT_ON				((u32)1 << IPTS_INPUT)
-+#define IPTS_OUTPUT_ON				((u32)1 << IPTS_OUTPUT)
-+#define IPTS_CONFIGURATION_ON			((u32)1 << IPTS_CONFIGURATION)
-+#define IPTS_CALIBRATION_ON			((u32)1 << IPTS_CALIBRATION)
-+#define IPTS_FEATURE_ON				((u32)1 << IPTS_FEATURE)
-+
-+#define	DATA_FILE_FLAG_SHARE			0x00000001
-+#define	DATA_FILE_FLAG_ALLOC_CONTIGUOUS		0x00000002
-+
-+static int bin_read_fw(ipts_info_t *ipts, const char *fw_name,
-+						u8* data, int size)
-+{
-+	const struct firmware *fw = NULL;
-+	char fw_path[MAX_IOCL_FILE_PATH_LEN];
-+	int ret = 0;
-+
-+	snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name);
-+	ret = request_firmware(&fw, fw_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_err(ipts, "cannot read fw %s\n", fw_path);
-+		return ret;
-+	}
-+
-+	if (fw->size > size) {
-+		ipts_dbg(ipts, "too small buffer to contain fw data\n");
-+		ret = -EINVAL;
-+		goto rel_return;
-+	}
-+
-+	memcpy(data, fw->data, fw->size);
-+
-+rel_return:
-+	release_firmware(fw);
-+
-+	return ret;
-+}
-+
-+
-+static bin_data_file_info_t* bin_get_data_file_info(bin_fw_info_t* fw_info,
-+							u32 io_buffer_type)
-+{
-+	int i;
-+
-+	for (i = 0; i < fw_info->num_of_data_files; i++) {
-+		if (fw_info->data_file[i].io_buffer_type == io_buffer_type)
-+			break;
-+	}
-+
-+	if (i == fw_info->num_of_data_files)
-+		return NULL;
-+
-+	return &fw_info->data_file[i];
-+}
-+
-+static inline bool is_shared_data(const bin_data_file_info_t *data_file)
-+{
-+	if (data_file)
-+		return (!!(data_file->flags & DATA_FILE_FLAG_SHARE));
-+
-+	return false;
-+}
-+
-+static inline bool is_alloc_cont_data(const bin_data_file_info_t *data_file)
-+{
-+	if (data_file)
-+		return (!!(data_file->flags & DATA_FILE_FLAG_ALLOC_CONTIGUOUS));
-+
-+	return false;
-+}
-+
-+static inline bool is_parsing_vendor_kernel(const bin_parse_info_t *parse_info)
-+{
-+	/* vendor_kernel == null while loading itself(vendor kernel) */
-+	return parse_info->vendor_kernel == NULL;
-+}
-+
-+static int bin_read_allocation_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info)
-+{
-+	ipts_bin_alloc_list_t *alloc_list;
-+	int alloc_idx, parallel_idx, num_of_parallels, buf_idx, num_of_buffers;
-+	int parsed, size;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+
-+	alloc_list = (ipts_bin_alloc_list_t *)&parse_info->data[parsed];
-+
-+	/* validation check */
-+	if (sizeof(alloc_list->num) > size - parsed)
-+		return -EINVAL;
-+
-+	/* read the number of aloocations */
-+	parsed += sizeof(alloc_list->num);
-+
-+	/* validation check */
-+	if (sizeof(alloc_list->alloc[0]) * alloc_list->num > size - parsed)
-+		return -EINVAL;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	num_of_buffers = num_of_parallels * alloc_list->num + num_of_parallels;
-+
-+	alloc_info->buffs = vmalloc(sizeof(bin_buffer_t) * num_of_buffers);
-+	if (alloc_info->buffs == NULL)
-+		return -ENOMEM;
-+
-+	memset(alloc_info->buffs, 0, sizeof(bin_buffer_t) * num_of_buffers);
-+	for (alloc_idx = 0; alloc_idx < alloc_list->num; alloc_idx++) {
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+								parallel_idx++) {
-+			buf_idx = alloc_idx + (parallel_idx * alloc_list->num);
-+			alloc_info->buffs[buf_idx].handle =
-+					alloc_list->alloc[alloc_idx].handle;
-+
-+		}
-+
-+		parsed += sizeof(alloc_list->alloc[0]);
-+	}
-+
-+	parse_info->parsed = parsed;
-+	alloc_info->num_of_allocations = alloc_list->num;
-+	alloc_info->num_of_buffers = num_of_buffers;
-+
-+	ipts_dbg(ipts, "number of allocations = %d, buffers = %d\n",
-+						alloc_info->num_of_allocations,
-+						alloc_info->num_of_buffers);
-+
-+	return 0;
-+}
-+
-+static void patch_SBA(u32 *buf_addr, u64 gpu_addr, int size)
-+{
-+	u64 *stateBase;
-+	u64 SBA;
-+	u32 inst;
-+	int i;
-+
-+	SBA = gpu_addr + SBA_OFFSET_BYTES;
-+
-+	for (i = 0; i < size/4; i++) {
-+		inst = buf_addr[i];
-+		if (inst == BDW_SURFACE_BASE_ADDRESS) {
-+			stateBase = (u64*)&buf_addr[i + SURFACE_STATE_OFFSET_WORD];
-+			*stateBase |= SBA;
-+			*stateBase |= 0x01; // enable
-+			break;
-+		}
-+	}
-+}
-+
-+static int bin_read_cmd_buffer(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_cmdbuf_t *cmd;
-+	intel_ipts_mapbuffer_t *buf;
-+	int cmdbuf_idx, size, parsed, parallel_idx, num_of_parallels;
-+
-+	size = parse_info->size;
-+	parsed = parse_info->parsed;
-+
-+	cmd = (ipts_bin_cmdbuf_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(cmd->size) > size - parsed)
-+		return -EINVAL;
-+
-+	parsed += sizeof(cmd->size);
-+	if (cmd->size > size - parsed)
-+		return -EINVAL;
-+
-+	ipts_dbg(ipts, "cmd buf size = %d\n", cmd->size);
-+		
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	/* command buffers are located after the other allocations */
-+	cmdbuf_idx = num_of_parallels * alloc_info->num_of_allocations;
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		buf = ipts_map_buffer(ipts, cmd->size, 0);
-+		if (buf == NULL)
-+			return -ENOMEM;
-+
-+		ipts_dbg(ipts, "cmd_idx[%d] = %d, g:0x%p, c:0x%p\n", parallel_idx,
-+					cmdbuf_idx, buf->gfx_addr, buf->cpu_addr);
-+
-+		memcpy((void *)buf->cpu_addr, &(cmd->data[0]), cmd->size);
-+		patch_SBA(buf->cpu_addr, (u64)buf->gfx_addr, cmd->size);
-+		alloc_info->buffs[cmdbuf_idx].buf = buf;
-+		wl[parallel_idx].cmdbuf_index = cmdbuf_idx;
-+
-+		cmdbuf_idx++;
-+	}
-+
-+	parsed += cmd->size;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_find_alloc(ipts_info_t *ipts,
-+					bin_alloc_info_t *alloc_info,
-+					u32 handle)
-+{
-+	int i;
-+
-+	for (i = 0; i < alloc_info->num_of_allocations; i++) {
-+		if (alloc_info->buffs[i].handle == handle)
-+			return i;
-+	}
-+
-+	return -1;
-+}
-+
-+static intel_ipts_mapbuffer_t* bin_get_vendor_kernel_output(
-+						bin_parse_info_t *parse_info,
-+						int parallel_idx)
-+{
-+	bin_kernel_info_t *vendor = parse_info->vendor_kernel;
-+	bin_alloc_info_t *alloc_info;
-+	int buf_idx, vendor_output_idx;
-+
-+	alloc_info = vendor->alloc_info;
-+	vendor_output_idx = parse_info->interested_vendor_output;
-+
-+	if (vendor_output_idx >= alloc_info->num_of_outputs)
-+		return NULL;
-+
-+	buf_idx = vendor->wl[parallel_idx].iobuf_output[vendor_output_idx];
-+	return alloc_info->buffs[buf_idx].buf;
-+}
-+
-+static int bin_read_res_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_res_list_t *res_list;
-+	ipts_bin_res_t *res;
-+	intel_ipts_mapbuffer_t *buf;
-+	bin_data_file_info_t *data_file;
-+	u8 *bin_data;
-+	int i, size, parsed, parallel_idx, num_of_parallels, output_idx = -1;
-+	int buf_idx, num_of_alloc;
-+	u32 buf_size, flags, io_buf_type;
-+	bool initialize;
-+	
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	bin_data = parse_info->data;
-+
-+	res_list = (ipts_bin_res_list_t *)&parse_info->data[parsed];
-+	if (sizeof(res_list->num) > (size - parsed))
-+		return -EINVAL;
-+	parsed += sizeof(res_list->num);
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	ipts_dbg(ipts, "number of resources %u\n", res_list->num);
-+	for (i = 0; i < res_list->num; i++) {
-+		initialize = false; 
-+		io_buf_type = 0;
-+		flags = 0;
-+
-+		/* initial data */
-+		data_file = NULL;
-+
-+		res = (ipts_bin_res_t *)(&(bin_data[parsed]));
-+		if (sizeof(res[0]) > (size - parsed)) {
-+			return -EINVAL;
-+		}
-+
-+		ipts_dbg(ipts, "Resource(%d):handle 0x%08x type %u init %u"
-+				" size %u alsigned %u\n",
-+				i, res->handle, res->type, res->initialize,
-+				res->size, res->aligned_size);
-+                parsed += sizeof(res[0]);
-+
-+		if (res->initialize) {
-+			if (res->size > (size - parsed)) {
-+				return -EINVAL;
-+			}
-+			parsed += res->size;
-+		}
-+
-+		initialize = res->initialize;
-+		if (initialize && res->size > sizeof(ipts_bin_io_header_t)) {
-+			ipts_bin_io_header_t *io_hdr;
-+			io_hdr = (ipts_bin_io_header_t *)(&res->data[0]);
-+			if (strncmp(io_hdr->str, "INTELTOUCH", 10) == 0) {
-+				data_file = bin_get_data_file_info(
-+							parse_info->fw_info,
-+							(u32)io_hdr->type);
-+				switch (io_hdr->type) {
-+				case IPTS_INPUT:
-+					ipts_dbg(ipts, "input detected\n");
-+					io_buf_type = IPTS_INPUT_ON;
-+					flags = IPTS_BUF_FLAG_CONTIGUOUS;
-+					break;
-+				case IPTS_OUTPUT:
-+					ipts_dbg(ipts, "output detected\n");
-+					io_buf_type = IPTS_OUTPUT_ON;
-+					output_idx++;
-+					break;
-+				default:
-+					if ((u32)io_hdr->type > 31) {
-+						ipts_err(ipts,
-+							"invalid io buffer : %u\n",
-+							(u32)io_hdr->type);
-+						continue;
-+					}
-+
-+					if (is_alloc_cont_data(data_file))
-+						flags = IPTS_BUF_FLAG_CONTIGUOUS;
-+
-+					io_buf_type = ((u32)1 << (u32)io_hdr->type);
-+					ipts_dbg(ipts, "special io buffer %u\n",
-+								io_hdr->type);
-+					break;
-+				}
-+
-+				initialize = false;
-+			}
-+		}
-+
-+		num_of_alloc = alloc_info->num_of_allocations;
-+		buf_idx = bin_find_alloc(ipts, alloc_info, res->handle);
-+		if (buf_idx == -1) {
-+			ipts_dbg(ipts, "cannot find alloc info\n");
-+			return -EINVAL;
-+		}
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+					parallel_idx++, buf_idx += num_of_alloc) {
-+			if (!res->aligned_size)
-+				continue;
-+
-+			if (!(parallel_idx == 0 ||
-+				    (io_buf_type && !is_shared_data(data_file))))
-+				continue;
-+
-+			buf_size = res->aligned_size;
-+			if (io_buf_type & IPTS_INPUT_ON) {
-+				buf_size = max_t(u32,
-+						ipts->device_info.frame_size,
-+						buf_size);
-+				wl[parallel_idx].iobuf_input = buf_idx;
-+			} else if (io_buf_type & IPTS_OUTPUT_ON) {
-+				wl[parallel_idx].iobuf_output[output_idx] = buf_idx;
-+
-+				if (!is_parsing_vendor_kernel(parse_info) &&
-+								output_idx > 0) {
-+					ipts_err(ipts,
-+						"postproc with more than one inout"
-+						" is not supported : %d\n", output_idx);
-+					return -EINVAL;
-+				}
-+			}
-+
-+			if (!is_parsing_vendor_kernel(parse_info) &&
-+						io_buf_type & IPTS_OUTPUT_ON) {
-+				buf = bin_get_vendor_kernel_output(
-+								parse_info,
-+								parallel_idx);
-+				alloc_info->buffs[buf_idx].no_unmap = true;
-+			} else
-+				buf = ipts_map_buffer(ipts, buf_size, flags);
-+
-+			if (buf == NULL) {
-+				ipts_dbg(ipts, "ipts_map_buffer failed\n");
-+				return -ENOMEM;
-+			}
-+
-+			if (initialize) {
-+				memcpy((void *)buf->cpu_addr, &(res->data[0]),
-+								res->size);
-+			} else {
-+				if (data_file && strlen(data_file->file_name)) {
-+					bin_read_fw(ipts, data_file->file_name,
-+                                                        buf->cpu_addr, buf_size);
-+				} else if (is_parsing_vendor_kernel(parse_info) ||
-+						!(io_buf_type & IPTS_OUTPUT_ON)) {
-+					memset((void *)buf->cpu_addr, 0, res->size);
-+				}
-+			}
-+
-+			alloc_info->buffs[buf_idx].buf = buf;
-+		}
-+	}
-+
-+        alloc_info->num_of_outputs = output_idx + 1;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_read_patch_list(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_alloc_info_t *alloc_info,
-+					bin_workload_t *wl)
-+{
-+	ipts_bin_patch_list_t *patch_list;
-+	ipts_bin_patch_t *patch;
-+	intel_ipts_mapbuffer_t *cmd = NULL;
-+	u8 *batch;
-+	int parsed, size, i, parallel_idx, num_of_parallels, cmd_idx, buf_idx;
-+	unsigned int gtt_offset;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	patch_list = (ipts_bin_patch_list_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(patch_list->num) > (size - parsed)) {
-+		return -EFAULT;
-+	}
-+	parsed += sizeof(patch_list->num);
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	patch = (ipts_bin_patch_t *)(&patch_list->patch[0]);
-+	for (i = 0; i < patch_list->num; i++) {
-+		if (sizeof(patch_list->patch[0]) > (size - parsed)) {
-+			return -EFAULT;
-+		}
-+
-+		for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+								parallel_idx++) {
-+			cmd_idx = wl[parallel_idx].cmdbuf_index;
-+			buf_idx = patch[i].index + parallel_idx *
-+						alloc_info->num_of_allocations;
-+
-+			if (alloc_info->buffs[buf_idx].buf == NULL) {
-+				/* buffer shared */
-+				buf_idx = patch[i].index;
-+			}
-+
-+			cmd = alloc_info->buffs[cmd_idx].buf;
-+			batch = (char *)(u64)cmd->cpu_addr;
-+
-+			gtt_offset = 0;
-+			if(alloc_info->buffs[buf_idx].buf != NULL) {
-+				gtt_offset = (u32)(u64)
-+					alloc_info->buffs[buf_idx].buf->gfx_addr;
-+			} 
-+			gtt_offset += patch[i].alloc_offset;
-+
-+			batch += patch[i].patch_offset;
-+			*(u32*)batch = gtt_offset;
-+		}
-+
-+		parsed += sizeof(patch_list->patch[0]);
-+	}
-+
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_read_guc_wq_item(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					bin_guc_wq_item_t **guc_wq_item)
-+{
-+	ipts_bin_guc_wq_info_t *bin_guc_wq;
-+	bin_guc_wq_item_t *item;
-+	u8 *wi_data;
-+	int size, parsed, hdr_size, wi_size;
-+	int i, batch_offset;
-+	
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	bin_guc_wq = (ipts_bin_guc_wq_info_t *)&parse_info->data[parsed];
-+
-+	wi_size = bin_guc_wq->size;
-+	wi_data = bin_guc_wq->data;
-+	batch_offset = bin_guc_wq->batch_offset;
-+	ipts_dbg(ipts, "wi size = %d, bt offset = %d\n", wi_size, batch_offset);
-+	for (i = 0; i < wi_size / sizeof(u32); i++) {
-+		ipts_dbg(ipts, "wi[%d] = 0x%08x\n", i, *((u32*)wi_data + i));
-+	}
-+	hdr_size = sizeof(bin_guc_wq->size) + sizeof(bin_guc_wq->batch_offset);
-+
-+	if (hdr_size > (size - parsed)) {
-+		return -EINVAL;
-+	}
-+	parsed += hdr_size;
-+
-+	item = vmalloc(sizeof(bin_guc_wq_item_t) + wi_size);
-+	if (item == NULL)
-+		return -ENOMEM;
-+
-+	item->size = wi_size;
-+	item->batch_offset = batch_offset;
-+	memcpy(item->data, wi_data, wi_size);
-+
-+	*guc_wq_item = item;
-+
-+	parsed += wi_size;
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_setup_guc_workqueue(ipts_info_t *ipts,
-+					bin_kernel_list_t *kernel_list)
-+{
-+	bin_alloc_info_t *alloc_info;
-+	bin_workload_t *wl;
-+	bin_kernel_info_t *kernel;
-+	u8 *wq_start, *wq_addr, *wi_data;
-+	bin_buffer_t *bin_buf;
-+	int wq_size, wi_size, parallel_idx, cmd_idx, k_idx, iter_size;
-+	int i, num_of_parallels, batch_offset, k_num, total_workload;
-+	
-+	wq_addr = (u8*)ipts->resource.wq_info.wq_addr;
-+	wq_size = ipts->resource.wq_info.wq_size;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	total_workload = ipts_get_wq_item_size(ipts);
-+	k_num = kernel_list->num_of_kernels;
-+
-+	iter_size = total_workload * num_of_parallels;
-+	if (wq_size % iter_size) {
-+		ipts_err(ipts, "wq item cannot fit into wq\n");
-+		return -EINVAL;
-+	}
-+
-+	wq_start = wq_addr;
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels;
-+							parallel_idx++) {
-+		kernel = &kernel_list->kernels[0];
-+		for (k_idx = 0; k_idx < k_num; k_idx++, kernel++) {
-+			wl = kernel->wl;
-+			alloc_info = kernel->alloc_info;
-+
-+			batch_offset = kernel->guc_wq_item->batch_offset;
-+			wi_size = kernel->guc_wq_item->size;
-+			wi_data = &kernel->guc_wq_item->data[0];
-+			
-+			cmd_idx = wl[parallel_idx].cmdbuf_index;
-+			bin_buf = &alloc_info->buffs[cmd_idx];
-+
-+			/* Patch the WQ Data with proper batch buffer offset */
-+			*(u32*)(wi_data + batch_offset) =
-+				(u32)(unsigned long)(bin_buf->buf->gfx_addr);
-+
-+			memcpy(wq_addr, wi_data, wi_size);
-+
-+			wq_addr += wi_size;
-+		}
-+	}
-+
-+	for (i = 0; i < (wq_size / iter_size) - 1; i++) {
-+		memcpy(wq_addr, wq_start, iter_size);
-+		wq_addr += iter_size;
-+	}
-+
-+	return 0;
-+}
-+
-+static int bin_read_bufid_patch(ipts_info_t *ipts,
-+					bin_parse_info_t *parse_info,
-+					ipts_bin_bufid_patch_t *bufid_patch)
-+{
-+	ipts_bin_bufid_patch_t *patch;
-+	int size, parsed;
-+
-+	parsed = parse_info->parsed;
-+	size = parse_info->size;
-+	patch = (ipts_bin_bufid_patch_t *)&parse_info->data[parsed];
-+
-+	if (sizeof(ipts_bin_bufid_patch_t) > (size - parsed)) {
-+		ipts_dbg(ipts, "invalid bufid info\n");
-+		return -EINVAL;
-+	}
-+	parsed += sizeof(ipts_bin_bufid_patch_t);
-+
-+	memcpy(bufid_patch, patch, sizeof(ipts_bin_bufid_patch_t));
-+
-+	parse_info->parsed = parsed;
-+
-+	return 0;
-+}
-+
-+static int bin_setup_bufid_buffer(ipts_info_t *ipts, bin_kernel_list_t *kernel_list)
-+{
-+	intel_ipts_mapbuffer_t *buf, *cmd_buf;
-+	bin_kernel_info_t *last_kernel;
-+	bin_alloc_info_t *alloc_info;
-+	bin_workload_t *wl;
-+	u8 *batch;
-+	int parallel_idx, num_of_parallels, cmd_idx;
-+	u32 mem_offset, imm_offset;
-+
-+	buf = ipts_map_buffer(ipts, PAGE_SIZE, 0);
-+	if (!buf) {
-+		return -ENOMEM;
-+	}
-+
-+	last_kernel = &kernel_list->kernels[kernel_list->num_of_kernels - 1];
-+
-+	mem_offset = last_kernel->bufid_patch.mem_offset;
-+	imm_offset = last_kernel->bufid_patch.imm_offset;
-+	wl = last_kernel->wl;
-+	alloc_info = last_kernel->alloc_info;
-+
-+	/* Initialize the buffer with default value */
-+        *((u32*)buf->cpu_addr) = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->current_buffer_index = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->last_buffer_completed = LASTSUBMITID_DEFAULT_VALUE;
-+	ipts->last_submitted_id = (int*)buf->cpu_addr;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		cmd_idx = wl[parallel_idx].cmdbuf_index;
-+		cmd_buf = alloc_info->buffs[cmd_idx].buf;
-+		batch = (u8*)(u64)cmd_buf->cpu_addr;
-+
-+		*((u32*)(batch + mem_offset)) = (u32)(u64)(buf->gfx_addr);
-+                *((u32*)(batch + imm_offset)) = parallel_idx;
-+	}
-+
-+	kernel_list->bufid_buf = buf;
-+
-+	return 0;
-+}
-+
-+static void unmap_buffers(ipts_info_t *ipts, bin_alloc_info_t *alloc_info)
-+{
-+	bin_buffer_t *buffs;
-+	int i, num_of_buffers;
-+
-+	num_of_buffers = alloc_info->num_of_buffers;
-+	buffs = &alloc_info->buffs[0];
-+
-+	for (i = 0; i < num_of_buffers; i++) {
-+		if (buffs[i].no_unmap != true && buffs[i].buf != NULL)
-+			ipts_unmap_buffer(ipts, buffs[i].buf);
-+	}
-+}
-+
-+static int load_kernel(ipts_info_t *ipts, bin_parse_info_t *parse_info,
-+						bin_kernel_info_t *kernel)
-+{
-+	ipts_bin_header_t *hdr;
-+	bin_workload_t *wl;
-+	bin_alloc_info_t *alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item = NULL;
-+	ipts_bin_bufid_patch_t bufid_patch;
-+	int num_of_parallels, ret;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+        /* check header version and magic numbers */
-+	hdr = (ipts_bin_header_t *)parse_info->data;
-+	if (hdr->version != IPTS_BIN_HEADER_VERSION ||
-+					strncmp(hdr->str, "IOCL", 4) != 0) {
-+		ipts_err(ipts, "binary header is not correct version = %d, "
-+				"string = %c%c%c%c\n", hdr->version,
-+				hdr->str[0], hdr->str[1],
-+				hdr->str[2], hdr->str[3] );
-+		return -EINVAL;
-+	}
-+
-+	parse_info->parsed = sizeof(ipts_bin_header_t);
-+	wl = vmalloc(sizeof(bin_workload_t) * num_of_parallels);
-+	if (wl == NULL)
-+		return -ENOMEM;
-+	memset(wl, 0, sizeof(bin_workload_t) * num_of_parallels);
-+
-+	alloc_info = vmalloc(sizeof(bin_alloc_info_t));
-+	if (alloc_info == NULL) {
-+		vfree(wl);
-+		return -ENOMEM;
-+	}
-+	memset(alloc_info, 0, sizeof(bin_alloc_info_t));
-+
-+        ipts_dbg(ipts, "kernel setup(size : %d)\n", parse_info->size);
-+
-+	ret = bin_read_allocation_list(ipts, parse_info, alloc_info);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_allocation_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_cmd_buffer(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_cmd_buffer\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_res_list(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_res_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_patch_list(ipts, parse_info, alloc_info, wl);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_patch_list\n");
-+		goto setup_error;
-+	}
-+
-+	ret = bin_read_guc_wq_item(ipts, parse_info, &guc_wq_item);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_guc_workqueue\n");
-+		goto setup_error;
-+	}
-+
-+	memset(&bufid_patch, 0, sizeof(bufid_patch));
-+	ret = bin_read_bufid_patch(ipts, parse_info, &bufid_patch);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error read_bufid_patch\n");
-+		goto setup_error;
-+	}
-+
-+	kernel->wl = wl;
-+	kernel->alloc_info = alloc_info;
-+	kernel->is_vendor = is_parsing_vendor_kernel(parse_info);
-+	kernel->guc_wq_item = guc_wq_item;
-+	memcpy(&kernel->bufid_patch, &bufid_patch, sizeof(bufid_patch));
-+
-+        return 0;
-+
-+setup_error:
-+	vfree(guc_wq_item);
-+
-+	unmap_buffers(ipts, alloc_info);
-+
-+	vfree(alloc_info->buffs);
-+	vfree(alloc_info);
-+	vfree(wl);
-+
-+	return ret;
-+}
-+
-+void bin_setup_input_output(ipts_info_t *ipts, bin_kernel_list_t *kernel_list)
-+{
-+	bin_kernel_info_t *vendor_kernel;
-+	bin_workload_t *wl;
-+	intel_ipts_mapbuffer_t *buf;
-+	bin_alloc_info_t *alloc_info;
-+	int parallel_idx, num_of_parallels, i, buf_idx;
-+
-+	vendor_kernel = &kernel_list->kernels[0];
-+
-+	wl = vendor_kernel->wl;
-+	alloc_info = vendor_kernel->alloc_info;
-+	ipts->resource.num_of_outputs = alloc_info->num_of_outputs;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+
-+	for (parallel_idx = 0; parallel_idx < num_of_parallels; parallel_idx++) {
-+		buf_idx = wl[parallel_idx].iobuf_input;
-+		buf = alloc_info->buffs[buf_idx].buf;
-+
-+		ipts_dbg(ipts, "in_buf[%d](%d) c:%p, p:%p, g:%p\n",
-+					parallel_idx, buf_idx, (void*)buf->cpu_addr,
-+					(void*)buf->phy_addr, (void*)buf->gfx_addr);
-+
-+		ipts_set_input_buffer(ipts, parallel_idx, buf->cpu_addr,
-+								buf->phy_addr);
-+
-+		for (i = 0; i < alloc_info->num_of_outputs; i++) {
-+			buf_idx = wl[parallel_idx].iobuf_output[i];
-+			buf = alloc_info->buffs[buf_idx].buf;
-+
-+			ipts_dbg(ipts, "out_buf[%d][%d] c:%p, p:%p, g:%p\n",
-+					parallel_idx, i, (void*)buf->cpu_addr,
-+					(void*)buf->phy_addr, (void*)buf->gfx_addr);
-+
-+			ipts_set_output_buffer(ipts, parallel_idx, i,
-+					buf->cpu_addr, buf->phy_addr);
-+		}
-+	}
-+}
-+
-+static void unload_kernel(ipts_info_t *ipts, bin_kernel_info_t *kernel)
-+{
-+	bin_alloc_info_t *alloc_info = kernel->alloc_info;
-+	bin_guc_wq_item_t *guc_wq_item = kernel->guc_wq_item;
-+
-+	if (guc_wq_item) {
-+		vfree(guc_wq_item);
-+	}
-+
-+	if (alloc_info) {
-+		unmap_buffers(ipts, alloc_info);
-+
-+		vfree(alloc_info->buffs);
-+		vfree(alloc_info);
-+	}
-+}
-+
-+static int setup_kernel(ipts_info_t *ipts, bin_fw_list_t *fw_list)
-+{
-+	bin_kernel_list_t *kernel_list = NULL;
-+	bin_kernel_info_t *kernel = NULL;
-+	const struct firmware *fw = NULL;
-+	bin_workload_t *wl;
-+	bin_fw_info_t *fw_info;
-+	char *fw_name, *fw_data;
-+	bin_parse_info_t parse_info;
-+	int ret = 0, kernel_idx = 0, num_of_kernels = 0;
-+	int vendor_output_idx, total_workload = 0;
-+	char fw_path[MAX_IOCL_FILE_PATH_LEN];
-+
-+	num_of_kernels = fw_list->num_of_fws;
-+	kernel_list = vmalloc(sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list));
-+	if (kernel_list == NULL)
-+		return -ENOMEM;
-+
-+	memset(kernel_list, 0, sizeof(*kernel) * num_of_kernels + sizeof(*kernel_list));
-+	kernel_list->num_of_kernels = num_of_kernels;
-+	kernel = &kernel_list->kernels[0];
-+
-+	fw_data = (char *)&fw_list->fw_info[0];
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		fw_info = (bin_fw_info_t *)fw_data;
-+		fw_name = &fw_info->fw_name[0];
-+		vendor_output_idx = fw_info->vendor_output;
-+		snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_FW_PATH_FMT, fw_name);
-+		ret = request_firmware(&fw, (const char *)fw_path, &ipts->cldev->dev);
-+		if (ret) {
-+			ipts_err(ipts, "cannot read fw %s\n", fw_path);
-+			goto error_exit;
-+		}
-+
-+		parse_info.data = (u8*)fw->data;
-+		parse_info.size = fw->size;
-+		parse_info.parsed = 0;
-+		parse_info.fw_info = fw_info;
-+		parse_info.vendor_kernel = (kernel_idx == 0) ? NULL : &kernel[0];
-+		parse_info.interested_vendor_output = vendor_output_idx;
-+
-+		ret = load_kernel(ipts, &parse_info, &kernel[kernel_idx]);
-+		if (ret) {
-+			ipts_err(ipts, "do_setup_kernel error : %d\n", ret);
-+			release_firmware(fw);
-+			goto error_exit;
-+		}
-+
-+		release_firmware(fw);
-+
-+		total_workload += kernel[kernel_idx].guc_wq_item->size;
-+
-+		/* advance to the next kernel */
-+		fw_data += sizeof(bin_fw_info_t);
-+		fw_data += sizeof(bin_data_file_info_t) * fw_info->num_of_data_files;
-+	}
-+
-+	ipts_set_wq_item_size(ipts, total_workload);
-+	
-+	ret = bin_setup_guc_workqueue(ipts, kernel_list);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error setup_guc_workqueue\n");
-+		goto error_exit;
-+	}
-+
-+	ret = bin_setup_bufid_buffer(ipts, kernel_list);
-+	if (ret) {
-+        	ipts_dbg(ipts, "error setup_lastbubmit_buffer\n");
-+		goto error_exit;
-+	}
-+
-+	bin_setup_input_output(ipts, kernel_list);
-+
-+	/* workload is not needed during run-time so free them */
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		wl = kernel[kernel_idx].wl;
-+		vfree(wl);
-+	}
-+
-+	ipts->kernel_handle = (u64)kernel_list;
-+
-+	return 0;
-+
-+error_exit:
-+
-+	for (kernel_idx = 0; kernel_idx < num_of_kernels; kernel_idx++) {
-+		wl = kernel[kernel_idx].wl;
-+		vfree(wl);
-+		unload_kernel(ipts, &kernel[kernel_idx]);
-+	}
-+
-+	vfree(kernel_list);
-+
-+	return ret;
-+}
-+
-+
-+static void release_kernel(ipts_info_t *ipts)
-+{
-+	bin_kernel_list_t *kernel_list;
-+	bin_kernel_info_t *kernel;
-+	int k_idx, k_num;
-+
-+	kernel_list = (bin_kernel_list_t *)ipts->kernel_handle;
-+	k_num = kernel_list->num_of_kernels;
-+	kernel = &kernel_list->kernels[0];
-+
-+	for (k_idx = 0; k_idx < k_num; k_idx++) {
-+		unload_kernel(ipts, kernel);
-+		kernel++;
-+	}	
-+
-+	ipts_unmap_buffer(ipts, kernel_list->bufid_buf);
-+
-+	vfree(kernel_list);
-+	ipts->kernel_handle = 0;
-+}
-+
-+int ipts_init_kernels(ipts_info_t *ipts)
-+{
-+	const struct firmware *config_fw = NULL;
-+	const char *config_fw_path = IPTS_FW_CONFIG_FILE;
-+	bin_fw_list_t *fw_list;
-+	int ret;
-+
-+	ret = ipts_open_gpu(ipts);
-+	if (ret) {
-+		ipts_err(ipts, "open gpu error : %d\n", ret);
-+		return ret;
-+	}
-+
-+	ret = request_firmware(&config_fw, config_fw_path, &ipts->cldev->dev);
-+	if (ret) {
-+		ipts_err(ipts, "request firmware error : %d\n", ret);
-+		goto close_gpu;
-+	}
-+
-+	fw_list = (bin_fw_list_t *)config_fw->data;
-+	ret = setup_kernel(ipts, fw_list);
-+	if (ret) {
-+		ipts_err(ipts, "setup kernel error : %d\n", ret);
-+		goto close_firmware;
-+	}
-+
-+	release_firmware(config_fw);
-+
-+	return ret;
-+
-+close_firmware:
-+	release_firmware(config_fw);
-+
-+close_gpu:
-+	ipts_close_gpu(ipts);
-+
-+	return ret;
-+}
-+
-+void ipts_release_kernels(ipts_info_t *ipts)
-+{
-+	release_kernel(ipts);
-+	ipts_close_gpu(ipts);
-+}
-diff --git a/drivers/misc/ipts/ipts-kernel.h b/drivers/misc/ipts/ipts-kernel.h
-new file mode 100644
-index 000000000000..0e7f1393b807
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-kernel.h
-@@ -0,0 +1,23 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus Linux driver
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _ITPS_GFX_H
-+#define _ITPS_GFX_H
-+
-+int ipts_init_kernels(ipts_info_t *ipts);
-+void ipts_release_kernels(ipts_info_t *ipts);
-+
-+#endif
-diff --git a/drivers/misc/ipts/ipts-mei-msgs.h b/drivers/misc/ipts/ipts-mei-msgs.h
-new file mode 100644
-index 000000000000..8ca146800a47
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-mei-msgs.h
-@@ -0,0 +1,585 @@
-+/*
-+ * Precise Touch HECI Message
-+ *
-+ * Copyright (c) 2013-2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_MEI_MSGS_H_
-+#define _IPTS_MEI_MSGS_H_
-+
-+#include "ipts-sensor-regs.h"
-+
-+#pragma pack(1)
-+
-+
-+// Initial protocol version
-+#define TOUCH_HECI_CLIENT_PROTOCOL_VERSION      10
-+
-+// GUID that identifies the Touch HECI client.
-+#define TOUCH_HECI_CLIENT_GUID  \
-+            {0x3e8d0870, 0x271a, 0x4208, {0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04}}
-+
-+
-+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch
-+#ifndef C_ASSERT
-+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
-+#endif
-+
-+
-+// General Type Defines for compatibility with HID driver and BIOS
-+#ifndef BIT0
-+#define BIT0 1
-+#endif
-+#ifndef BIT1
-+#define BIT1 2
-+#endif
-+#ifndef BIT2
-+#define BIT2 4
-+#endif
-+
-+
-+#define TOUCH_SENSOR_GET_DEVICE_INFO_CMD        0x00000001
-+#define TOUCH_SENSOR_GET_DEVICE_INFO_RSP        0x80000001
-+
-+
-+#define TOUCH_SENSOR_SET_MODE_CMD               0x00000002
-+#define TOUCH_SENSOR_SET_MODE_RSP               0x80000002
-+
-+
-+#define TOUCH_SENSOR_SET_MEM_WINDOW_CMD         0x00000003
-+#define TOUCH_SENSOR_SET_MEM_WINDOW_RSP         0x80000003
-+
-+
-+#define TOUCH_SENSOR_QUIESCE_IO_CMD             0x00000004
-+#define TOUCH_SENSOR_QUIESCE_IO_RSP             0x80000004
-+
-+
-+#define TOUCH_SENSOR_HID_READY_FOR_DATA_CMD     0x00000005
-+#define TOUCH_SENSOR_HID_READY_FOR_DATA_RSP     0x80000005
-+
-+
-+#define TOUCH_SENSOR_FEEDBACK_READY_CMD         0x00000006
-+#define TOUCH_SENSOR_FEEDBACK_READY_RSP         0x80000006
-+
-+
-+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD       0x00000007
-+#define TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP       0x80000007
-+
-+
-+#define TOUCH_SENSOR_NOTIFY_DEV_READY_CMD       0x00000008
-+#define TOUCH_SENSOR_NOTIFY_DEV_READY_RSP       0x80000008
-+
-+
-+#define TOUCH_SENSOR_SET_POLICIES_CMD           0x00000009
-+#define TOUCH_SENSOR_SET_POLICIES_RSP           0x80000009
-+
-+
-+#define TOUCH_SENSOR_GET_POLICIES_CMD           0x0000000A
-+#define TOUCH_SENSOR_GET_POLICIES_RSP           0x8000000A
-+
-+
-+#define TOUCH_SENSOR_RESET_CMD                  0x0000000B
-+#define TOUCH_SENSOR_RESET_RSP                  0x8000000B
-+
-+
-+#define TOUCH_SENSOR_READ_ALL_REGS_CMD          0x0000000C
-+#define TOUCH_SENSOR_READ_ALL_REGS_RSP          0x8000000C
-+
-+
-+#define TOUCH_SENSOR_CMD_ERROR_RSP              0x8FFFFFFF  // M2H: ME sends this message to indicate previous command was unrecognized/unsupported
-+
-+
-+
-+//*******************************************************************
-+//
-+// Touch Sensor Status Codes
-+//
-+//*******************************************************************
-+typedef enum touch_status
-+{
-+    TOUCH_STATUS_SUCCESS = 0,               //  0 Requested operation was successful
-+    TOUCH_STATUS_INVALID_PARAMS,            //  1 Invalid parameter(s) sent
-+    TOUCH_STATUS_ACCESS_DENIED,             //  2 Unable to validate address range
-+    TOUCH_STATUS_CMD_SIZE_ERROR,            //  3 HECI message incorrect size for specified command
-+    TOUCH_STATUS_NOT_READY,                 //  4 Memory window not set or device is not armed for operation
-+    TOUCH_STATUS_REQUEST_OUTSTANDING,       //  5 There is already an outstanding message of the same type, must wait for response before sending another request of that type
-+    TOUCH_STATUS_NO_SENSOR_FOUND,           //  6 Sensor could not be found. Either no sensor is connected, the sensor has not yet initialized, or the system is improperly configured.
-+    TOUCH_STATUS_OUT_OF_MEMORY,             //  7 Not enough memory/storage for requested operation
-+    TOUCH_STATUS_INTERNAL_ERROR,            //  8 Unexpected error occurred
-+    TOUCH_STATUS_SENSOR_DISABLED,           //  9 Used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP to indicate sensor has been disabled or reset and must be reinitialized.
-+    TOUCH_STATUS_COMPAT_CHECK_FAIL,         // 10 Used to indicate compatibility revision check between sensor and ME failed, or protocol ver between ME/HID/Kernels failed.
-+    TOUCH_STATUS_SENSOR_EXPECTED_RESET,     // 11 Indicates sensor went through a reset initiated by ME
-+    TOUCH_STATUS_SENSOR_UNEXPECTED_RESET,   // 12 Indicates sensor went through an unexpected reset
-+    TOUCH_STATUS_RESET_FAILED,              // 13 Requested sensor reset failed to complete
-+    TOUCH_STATUS_TIMEOUT,                   // 14 Operation timed out
-+    TOUCH_STATUS_TEST_MODE_FAIL,            // 15 Test mode pattern did not match expected values
-+    TOUCH_STATUS_SENSOR_FAIL_FATAL,         // 16 Indicates sensor reported fatal error during reset sequence. Further progress is not possible.
-+    TOUCH_STATUS_SENSOR_FAIL_NONFATAL,      // 17 Indicates sensor reported non-fatal error during reset sequence. HID/BIOS logs error and attempts to continue.
-+    TOUCH_STATUS_INVALID_DEVICE_CAPS,       // 18 Indicates sensor reported invalid capabilities, such as not supporting required minimum frequency or I/O mode.
-+    TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS,    // 19 Indicates that command cannot be complete until ongoing Quiesce I/O flow has completed.
-+    TOUCH_STATUS_MAX                        // 20 Invalid value, never returned
-+} touch_status_t;
-+C_ASSERT(sizeof(touch_status_t) == 4);
-+
-+
-+
-+//*******************************************************************
-+//
-+// Defines for message structures used for Host to ME communication
-+//
-+//*******************************************************************
-+
-+
-+typedef enum touch_sensor_mode
-+{
-+    TOUCH_SENSOR_MODE_HID = 0,          // Set mode to HID mode
-+    TOUCH_SENSOR_MODE_RAW_DATA,         // Set mode to Raw Data mode
-+    TOUCH_SENSOR_MODE_SENSOR_DEBUG = 4, // Used like TOUCH_SENSOR_MODE_HID but data coming from sensor is not necessarily a HID packet.
-+    TOUCH_SENSOR_MODE_MAX               // Invalid value
-+} touch_sensor_mode_t;
-+C_ASSERT(sizeof(touch_sensor_mode_t) == 4);
-+
-+typedef struct touch_sensor_set_mode_cmd_data
-+{
-+    touch_sensor_mode_t	sensor_mode;     // Indicate desired sensor mode
-+    u32					Reserved[3];    // For future expansion
-+} touch_sensor_set_mode_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mode_cmd_data_t) == 16);
-+
-+
-+#define TOUCH_SENSOR_MAX_DATA_BUFFERS   16
-+#define TOUCH_HID_2_ME_BUFFER_ID        TOUCH_SENSOR_MAX_DATA_BUFFERS
-+#define TOUCH_HID_2_ME_BUFFER_SIZE_MAX  1024
-+#define TOUCH_INVALID_BUFFER_ID         0xFF
-+
-+typedef struct touch_sensor_set_mem_window_cmd_data
-+{
-+    u32  touch_data_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS];    // Lower 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize
-+    u32  touch_data_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS];    // Upper 32 bits of Touch Data Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FrameSize
-+    u32  tail_offset_addr_lower;                                        // Lower 32 bits of Tail Offset physical address
-+    u32  tail_offset_addr_upper;                                        // Upper 32 bits of Tail Offset physical address, always 32 bit, increment by WorkQueueItemSize
-+    u32  doorbell_cookie_addr_lower;                                    // Lower 32 bits of Doorbell register physical address
-+    u32  doorbell_cookie_addr_upper;                                    // Upper 32 bits of Doorbell register physical address, always 32 bit, increment as integer, rollover to 1
-+    u32  feedback_buffer_addr_lower[TOUCH_SENSOR_MAX_DATA_BUFFERS];     // Lower 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize
-+    u32  feedback_buffer_addr_upper[TOUCH_SENSOR_MAX_DATA_BUFFERS];     // Upper 32 bits of Feedback Buffer physical address. Size of each buffer should be TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.FeedbackSize
-+    u32  hid2me_buffer_addr_lower;                                      // Lower 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize.
-+    u32  hid2me_buffer_addr_upper;                                      // Upper 32 bits of dedicated HID to ME communication buffer. Size is Hid2MeBufferSize.
-+    u32  hid2me_buffer_size;                                           // Size in bytes of Hid2MeBuffer, can be no bigger than TOUCH_HID_2_ME_BUFFER_SIZE_MAX
-+    u8   reserved1;                                                  // For future expansion
-+    u8   work_queue_item_size;                                          // Size in bytes of the GuC Work Queue Item pointed to by TailOffset
-+    u16  work_queue_size;                                              // Size in bytes of the entire GuC Work Queue
-+    u32  reserved[8];                                                // For future expansion
-+} touch_sensor_set_mem_window_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mem_window_cmd_data_t) == 320);
-+
-+
-+#define TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET BIT0   // indicates GuC got reset and ME must re-read GuC data such as TailOffset and Doorbell Cookie values
-+
-+typedef struct touch_sensor_quiesce_io_cmd_data
-+{
-+    u32  quiesce_flags;   // Optionally set TOUCH_SENSOR_QUIESCE_FLAG_GUC_RESET
-+    u32  reserved[2];
-+} touch_sensor_quiesce_io_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_quiesce_io_cmd_data_t) == 12);
-+
-+
-+typedef struct touch_sensor_feedback_ready_cmd_data
-+{
-+    u8   feedback_index;  // Index value from 0 to TOUCH_HID_2_ME_BUFFER_ID used to indicate which Feedback Buffer to use. Using special value TOUCH_HID_2_ME_BUFFER_ID
-+                            // is an indication to ME to get feedback data from the Hid2Me buffer instead of one of the standard Feedback buffers.
-+    u8   reserved1[3];   // For future expansion
-+    u32  transaction_id;  // Transaction ID that was originally passed to host in TOUCH_HID_PRIVATE_DATA. Used to track round trip of a given transaction for performance measurements.
-+    u32  reserved2[2];   // For future expansion
-+} touch_sensor_feedback_ready_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_feedback_ready_cmd_data_t) == 16);
-+
-+
-+#define TOUCH_DEFAULT_DOZE_TIMER_SECONDS    30
-+
-+typedef enum touch_freq_override
-+{
-+    TOUCH_FREQ_OVERRIDE_NONE,   // Do not apply any override
-+    TOUCH_FREQ_OVERRIDE_10MHZ,  // Force frequency to 10MHz (not currently supported)
-+    TOUCH_FREQ_OVERRIDE_17MHZ,  // Force frequency to 17MHz
-+    TOUCH_FREQ_OVERRIDE_30MHZ,  // Force frequency to 30MHz
-+    TOUCH_FREQ_OVERRIDE_50MHZ,  // Force frequency to 50MHz (not currently supported)
-+    TOUCH_FREQ_OVERRIDE_MAX     // Invalid value
-+} touch_freq_override_t;
-+C_ASSERT(sizeof(touch_freq_override_t) == 4);
-+
-+typedef enum touch_spi_io_mode_override
-+{
-+    TOUCH_SPI_IO_MODE_OVERRIDE_NONE,    // Do not apply any override
-+    TOUCH_SPI_IO_MODE_OVERRIDE_SINGLE,  // Force Single I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_DUAL,    // Force Dual I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_QUAD,    // Force Quad I/O
-+    TOUCH_SPI_IO_MODE_OVERRIDE_MAX      // Invalid value
-+} touch_spi_io_mode_override_t;
-+C_ASSERT(sizeof(touch_spi_io_mode_override_t) == 4);
-+
-+// Debug Policy bits used by TOUCH_POLICY_DATA.DebugOverride
-+#define TOUCH_DBG_POLICY_OVERRIDE_STARTUP_TIMER_DIS BIT0    // Disable sensor startup timer
-+#define TOUCH_DBG_POLICY_OVERRIDE_SYNC_BYTE_DIS     BIT1    // Disable Sync Byte check
-+#define TOUCH_DBG_POLICY_OVERRIDE_ERR_RESET_DIS     BIT2    // Disable error resets
-+
-+typedef struct touch_policy_data
-+{
-+    u32                      reserved0;          // For future expansion.
-+    u32                      doze_timer     :16;  // Value in seconds, after which ME will put the sensor into Doze power state if no activity occurs. Set
-+                                                    // to 0 to disable Doze mode (not recommended). Value will be set to TOUCH_DEFAULT_DOZE_TIMER_SECONDS by
-+                                                    // default.
-+    touch_freq_override_t         freq_override  :3;   // Override frequency requested by sensor
-+    touch_spi_io_mode_override_t  spi_io_override :3;   // Override IO mode requested by sensor
-+    u32                      reserved1     :10;  // For future expansion
-+    u32                      reserved2;          // For future expansion
-+    u32                      debug_override;      // Normally all bits will be zero. Bits will be defined as needed for enabling special debug features
-+} touch_policy_data_t;
-+C_ASSERT(sizeof(touch_policy_data_t) == 16);
-+
-+typedef struct touch_sensor_set_policies_cmd_data
-+{
-+    touch_policy_data_t           policy_data;         // Contains the desired policy to be set
-+} touch_sensor_set_policies_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_policies_cmd_data_t) == 16);
-+
-+
-+typedef enum touch_sensor_reset_type
-+{
-+    TOUCH_SENSOR_RESET_TYPE_HARD,   // Hardware Reset using dedicated GPIO pin
-+    TOUCH_SENSOR_RESET_TYPE_SOFT,   // Software Reset using command written over SPI interface
-+    TOUCH_SENSOR_RESET_TYPE_MAX     // Invalid value
-+} touch_sensor_reset_type_t;
-+C_ASSERT(sizeof(touch_sensor_reset_type_t) == 4);
-+
-+typedef struct touch_sensor_reset_cmd_data
-+{
-+    touch_sensor_reset_type_t reset_type;  // Indicate desired reset type
-+    u32                  reserved;   // For future expansion
-+} touch_sensor_reset_cmd_data_t;
-+C_ASSERT(sizeof(touch_sensor_reset_cmd_data_t) == 8);
-+
-+
-+//
-+// Host to ME message
-+//
-+typedef struct touch_sensor_msg_h2m
-+{
-+    u32  command_code;
-+    union
-+    {
-+        touch_sensor_set_mode_cmd_data_t        set_mode_cmd_data;
-+        touch_sensor_set_mem_window_cmd_data_t  set_window_cmd_data;
-+        touch_sensor_quiesce_io_cmd_data_t      quiesce_io_cmd_data;
-+        touch_sensor_feedback_ready_cmd_data_t  feedback_ready_cmd_data;
-+        touch_sensor_set_policies_cmd_data_t    set_policies_cmd_data;
-+        touch_sensor_reset_cmd_data_t           reset_cmd_data;
-+    } h2m_data;
-+} touch_sensor_msg_h2m_t;
-+C_ASSERT(sizeof(touch_sensor_msg_h2m_t) == 324);
-+
-+
-+//*******************************************************************
-+//
-+// Defines for message structures used for ME to Host communication
-+//
-+//*******************************************************************
-+
-+// I/O mode values used by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+typedef enum touch_spi_io_mode
-+{
-+    TOUCH_SPI_IO_MODE_SINGLE = 0,   // Sensor set for Single I/O SPI
-+    TOUCH_SPI_IO_MODE_DUAL,         // Sensor set for Dual I/O SPI
-+    TOUCH_SPI_IO_MODE_QUAD,         // Sensor set for Quad I/O SPI
-+    TOUCH_SPI_IO_MODE_MAX           // Invalid value
-+} touch_spi_io_mode_t;
-+C_ASSERT(sizeof(touch_spi_io_mode_t) == 4);
-+
-+//
-+// TOUCH_SENSOR_GET_DEVICE_INFO_RSP code is sent in response to TOUCH_SENSOR_GET_DEVICE_INFO_CMD. This code will be followed
-+// by TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:               Command was processed successfully and sensor details are reported.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:        Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_NO_SENSOR_FOUND:       Sensor has not yet been detected. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_DEVICE_CAPS:   Indicates sensor does not support minimum required Frequency or I/O Mode. ME firmware will choose best possible option for the errant
-+//                                          field. Caller should attempt to continue.
-+//      TOUCH_STATUS_COMPAT_CHECK_FAIL:     Indicates TouchIC/ME compatibility mismatch. Caller should attempt to continue.
-+//
-+typedef struct touch_sensor_get_device_info_rsp_data
-+{
-+    u16				vendor_id;               // Touch Sensor vendor ID
-+    u16              device_id;               // Touch Sensor device ID
-+    u32              hw_rev;                  // Touch Sensor Hardware Revision
-+    u32              fw_rev;                  // Touch Sensor Firmware Revision
-+    u32              frame_size;              // Max size of one frame returned by Touch IC in bytes. This data will be TOUCH_RAW_DATA_HDR followed
-+                                                // by a payload. The payload can be raw data or a HID structure depending on mode.
-+    u32              feedback_size;           // Max size of one Feedback structure in bytes
-+    touch_sensor_mode_t	sensor_mode;             // Current operating mode of the sensor
-+    u32              max_touch_points  :8;     // Maximum number of simultaneous touch points that can be reported by sensor
-+    touch_freq_t          spi_frequency    :8;     // SPI bus Frequency supported by sensor and ME firmware
-+    touch_spi_io_mode_t   spi_io_mode       :8;     // SPI bus I/O Mode supported by sensor and ME firmware
-+    u32              reserved0       :8;     // For future expansion
-+    u8               sensor_minor_eds_rev;      // Minor version number of EDS spec supported by sensor (from Compat Rev ID Reg)
-+    u8               sensor_major_eds_rev;      // Major version number of EDS spec supported by sensor (from Compat Rev ID Reg)
-+    u8               me_minor_eds_rev;          // Minor version number of EDS spec supported by ME
-+    u8               me_major_eds_rev;          // Major version number of EDS spec supported by ME
-+    u8               sensor_eds_intf_rev;       // EDS Interface Revision Number supported by sensor (from Compat Rev ID Reg)
-+    u8               me_eds_intf_rev;           // EDS Interface Revision Number supported by ME
-+    u8               kernel_compat_ver;        // EU Kernel Compatibility Version  (from Compat Rev ID Reg)
-+    u8               reserved1;              // For future expansion
-+    u32              reserved2[2];           // For future expansion
-+} touch_sensor_get_device_info_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_get_device_info_rsp_data_t) == 44);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_MODE_RSP code is sent in response to TOUCH_SENSOR_SET_MODE_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_MODE_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and mode was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//
-+typedef struct touch_sensor_set_mode_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_mode_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mode_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_SET_MEM_WINDOW_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_MEM_WINDOW_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and memory window was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//      TOUCH_STATUS_ACCESS_DENIED:     Unable to map host address ranges for DMA.
-+//      TOUCH_STATUS_OUT_OF_MEMORY:     Unable to allocate enough space for needed buffers.
-+//
-+typedef struct touch_sensor_set_mem_window_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_mem_window_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_mem_window_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_QUIESCE_IO_RSP code is sent in response to TOUCH_SENSOR_QUIESCE_IO_CMD. This code will be followed
-+// by TOUCH_SENSOR_QUIESCE_IO_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and touch flow has stopped.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//      TOUCH_STATIS_TIMEOUT:                   Indicates ME timed out waiting for Quiesce I/O flow to complete.
-+//
-+typedef struct touch_sensor_quiesce_io_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_quiesce_io_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_quiesce_io_rsp_data_t) == 12);
-+
-+
-+// Reset Reason values used in TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA
-+typedef enum touch_reset_reason
-+{
-+    TOUCH_RESET_REASON_UNKNOWN = 0,         // Reason for sensor reset is not known
-+    TOUCH_RESET_REASON_FEEDBACK_REQUEST,    // Reset was requested as part of TOUCH_SENSOR_FEEDBACK_READY_CMD
-+    TOUCH_RESET_REASON_HECI_REQUEST,        // Reset was requested via TOUCH_SENSOR_RESET_CMD
-+    TOUCH_RESET_REASON_MAX
-+} touch_reset_reason_t;
-+C_ASSERT(sizeof(touch_reset_reason_t) == 4);
-+
-+//
-+// TOUCH_SENSOR_HID_READY_FOR_DATA_RSP code is sent in response to TOUCH_SENSOR_HID_READY_FOR_DATA_CMD. This code will be followed
-+// by TOUCH_SENSOR_HID_READY_FOR_DATA_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and HID data was sent by DMA. This will only be sent in HID mode.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_REQUEST_OUTSTANDING:       Previous request is still outstanding, ME FW cannot handle another request for the same command.
-+//      TOUCH_STATUS_NOT_READY:                 Indicates memory window has not yet been set by BIOS/HID.
-+//      TOUCH_STATUS_SENSOR_DISABLED:           Indicates that ME to HID communication has been stopped either by TOUCH_SENSOR_QUIESCE_IO_CMD or TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD.
-+//      TOUCH_STATUS_SENSOR_UNEXPECTED_RESET:   Sensor signaled a Reset Interrupt. ME did not expect this and has no info about why this occurred.
-+//      TOUCH_STATUS_SENSOR_EXPECTED_RESET:     Sensor signaled a Reset Interrupt. ME either directly requested this reset, or it was expected as part of a defined flow in the EDS.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//      TOUCH_STATUS_TIMEOUT:                   Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//
-+typedef struct touch_sensor_hid_ready_for_data_rsp_data
-+{
-+    u32          data_size;               // Size of the data the ME DMA'd into a RawDataBuffer. Valid only when Status == TOUCH_STATUS_SUCCESS
-+    u8           touch_data_buffer_index;   // Index to indicate which RawDataBuffer was used. Valid only when Status == TOUCH_STATUS_SUCCESS
-+    u8           reset_reason;            // If Status is TOUCH_STATUS_SENSOR_EXPECTED_RESET, ME will provide the cause. See TOUCH_RESET_REASON.
-+    u8           reserved1[2];           // For future expansion
-+    u32          reserved2[5];           // For future expansion
-+} touch_sensor_hid_ready_for_data_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_hid_ready_for_data_rsp_data_t) == 28);
-+
-+
-+//
-+// TOUCH_SENSOR_FEEDBACK_READY_RSP code is sent in response to TOUCH_SENSOR_FEEDBACK_READY_CMD. This code will be followed
-+// by TOUCH_SENSOR_FEEDBACK_READY_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and any feedback or commands were sent to sensor.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//      TOUCH_STATUS_COMPAT_CHECK_FAIL  Indicates ProtocolVer does not match ME supported version. (non-fatal error)
-+//      TOUCH_STATUS_INTERNAL_ERROR:    Unexpected error occurred. This should not normally be seen.
-+//      TOUCH_STATUS_OUT_OF_MEMORY:     Insufficient space to store Calibration Data
-+//
-+typedef struct touch_sensor_feedback_ready_rsp_data
-+{
-+    u8           feedback_index;  // Index value from 0 to TOUCH_SENSOR_MAX_DATA_BUFFERS used to indicate which Feedback Buffer to use
-+    u8           reserved1[3];   // For future expansion
-+    u32          reserved2[6];   // For future expansion
-+} touch_sensor_feedback_ready_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_feedback_ready_rsp_data_t) == 28);
-+
-+
-+//
-+// TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP code is sent in response to TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD. This code will be followed
-+// by TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and memory window was set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:            Input parameters are out of range.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//
-+typedef struct touch_sensor_clear_mem_window_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_clear_mem_window_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_clear_mem_window_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_NOTIFY_DEV_READY_RSP code is sent in response to TOUCH_SENSOR_NOTIFY_DEV_READY_CMD. This code will be followed
-+// by TOUCH_SENSOR_NOTIFY_DEV_READY_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:               Command was processed successfully and sensor has been detected by ME FW.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:        Command sent did not match expected size.
-+//      TOUCH_STATUS_REQUEST_OUTSTANDING:   Previous request is still outstanding, ME FW cannot handle another request for the same command.
-+//      TOUCH_STATUS_TIMEOUT:               Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//      TOUCH_STATUS_SENSOR_FAIL_FATAL:     Sensor indicated a fatal error, further operation is not possible. Error details can be found in ErrReg.
-+//      TOUCH_STATUS_SENSOR_FAIL_NONFATAL:  Sensor indicated a non-fatal error. Error should be logged by caller and init flow can continue. Error details can be found in ErrReg.
-+//
-+typedef struct touch_sensor_notify_dev_ready_rsp_data
-+{
-+    touch_err_reg_t   err_reg;         // Value of sensor Error Register, field is only valid for Status == TOUCH_STATUS_SENSOR_FAIL_FATAL or TOUCH_STATUS_SENSOR_FAIL_NONFATAL
-+    u32          reserved[2];    // For future expansion
-+} touch_sensor_notify_dev_ready_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_notify_dev_ready_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_SET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_SET_POLICIES_CMD. This code will be followed
-+// by TOUCH_SENSOR_SET_POLICIES_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:    Input parameters are out of range.
-+//
-+typedef struct touch_sensor_set_policies_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_set_policies_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_set_policies_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_GET_POLICIES_RSP code is sent in response to TOUCH_SENSOR_GET_POLICIES_CMD. This code will be followed
-+// by TOUCH_SENSOR_GET_POLICIES_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//
-+typedef struct touch_sensor_get_policies_rsp_data
-+{
-+    touch_policy_data_t   policy_data;         // Contains the current policy
-+} touch_sensor_get_policies_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_get_policies_rsp_data_t) == 16);
-+
-+
-+//
-+// TOUCH_SENSOR_RESET_RSP code is sent in response to TOUCH_SENSOR_RESET_CMD. This code will be followed
-+// by TOUCH_SENSOR_RESET_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:                   Command was processed successfully and sensor reset was completed.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:            Command sent did not match expected size. Other fields will not contain valid data.
-+//      TOUCH_STATUS_INVALID_PARAMS:            Input parameters are out of range.
-+//      TOUCH_STATUS_TIMEOUT:                   Sensor did not generate a reset interrupt in the time allotted. Could indicate sensor is not connected or malfunctioning.
-+//      TOUCH_STATUS_RESET_FAILED:              Sensor generated an invalid or unexpected interrupt.
-+//      TOUCH_STATUS_QUIESCE_IO_IN_PROGRESS:    Indicates that Quiesce I/O is already in progress and this command cannot be accepted at this time.
-+//
-+typedef struct touch_sensor_reset_rsp_data
-+{
-+    u32          reserved[3];    // For future expansion
-+} touch_sensor_reset_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_reset_rsp_data_t) == 12);
-+
-+
-+//
-+// TOUCH_SENSOR_READ_ALL_REGS_RSP code is sent in response to TOUCH_SENSOR_READ_ALL_REGS_CMD. This code will be followed
-+// by TOUCH_SENSOR_READ_ALL_REGS_RSP_DATA.
-+//
-+// Possible Status values:
-+//      TOUCH_STATUS_SUCCESS:           Command was processed successfully and new policies were set.
-+//      TOUCH_STATUS_CMD_SIZE_ERROR:    Command sent did not match expected size. Other fields will not contain valid data.
-+//
-+typedef struct touch_sensor_read_all_regs_rsp_data
-+{
-+    touch_reg_block_t sensor_regs; // Returns first 64 bytes of register space used for normal touch operation. Does not include test mode register.
-+    u32          reserved[4];
-+} touch_sensor_read_all_regs_rsp_data_t;
-+C_ASSERT(sizeof(touch_sensor_read_all_regs_rsp_data_t) == 80);
-+
-+//
-+// ME to Host Message
-+//
-+typedef struct touch_sensor_msg_m2h
-+{
-+    u32  command_code;
-+    touch_status_t	status;
-+    union
-+    {
-+        touch_sensor_get_device_info_rsp_data_t     device_info_rsp_data;
-+        touch_sensor_set_mode_rsp_data_t            set_mode_rsp_data;
-+        touch_sensor_set_mem_window_rsp_data_t      set_mem_window_rsp_data;
-+        touch_sensor_quiesce_io_rsp_data_t          quiesce_io_rsp_data;
-+        touch_sensor_hid_ready_for_data_rsp_data_t  hid_ready_for_data_rsp_data;
-+        touch_sensor_feedback_ready_rsp_data_t      feedback_ready_rsp_data;
-+        touch_sensor_clear_mem_window_rsp_data_t    clear_mem_window_rsp_data;
-+        touch_sensor_notify_dev_ready_rsp_data_t    notify_dev_ready_rsp_data;
-+        touch_sensor_set_policies_rsp_data_t        set_policies_rsp_data;
-+        touch_sensor_get_policies_rsp_data_t        get_policies_rsp_data;
-+        touch_sensor_reset_rsp_data_t               reset_rsp_data;
-+	touch_sensor_read_all_regs_rsp_data_t       read_all_regs_rsp_data;
-+    } m2h_data;
-+} touch_sensor_msg_m2h_t;
-+C_ASSERT(sizeof(touch_sensor_msg_m2h_t) == 88);
-+
-+
-+#define TOUCH_MSG_SIZE_MAX_BYTES    (MAX(sizeof(touch_sensor_msg_m2h_t), sizeof(touch_sensor_msg_h2m_t)))
-+
-+#pragma pack()
-+
-+#endif // _IPTS_MEI_MSGS_H_
-diff --git a/drivers/misc/ipts/ipts-mei.c b/drivers/misc/ipts/ipts-mei.c
-new file mode 100644
-index 000000000000..39667e75dafd
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-mei.c
-@@ -0,0 +1,282 @@
-+/*
-+ * MEI client driver for Intel Precise Touch and Stylus
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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/mei_cl_bus.h>
-+#include <linux/module.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/hid.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/kthread.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts.h"
-+#include "ipts-hid.h"
-+#include "ipts-msg-handler.h"
-+#include "ipts-mei-msgs.h"
-+#include "ipts-binary-spec.h"
-+#include "ipts-state.h"
-+
-+#define IPTS_DRIVER_NAME	"ipts"
-+#define IPTS_MEI_UUID		UUID_LE(0x3e8d0870, 0x271a, 0x4208, \
-+				0x8e, 0xb5, 0x9a, 0xcb, 0x94, 0x02, 0xae, 0x04)
-+
-+static struct mei_cl_device_id ipts_mei_cl_tbl[] = {
-+	{ "", IPTS_MEI_UUID, MEI_CL_VERSION_ANY},
-+	{}
-+};
-+
-+static ssize_t sensor_mode_show(struct device *dev,
-+				struct device_attribute *attr, char *buf)
-+{
-+	ipts_info_t *ipts;
-+	ipts = dev_get_drvdata(dev);
-+
-+	return sprintf(buf, "%d\n", ipts->sensor_mode);
-+}
-+
-+//TODO: Verify the function implementation
-+static ssize_t sensor_mode_store(struct device *dev,
-+				struct device_attribute *attr, const char *buf,
-+				size_t count)
-+{
-+	int ret;
-+	long val;
-+	ipts_info_t *ipts;
-+
-+	ipts = dev_get_drvdata(dev);
-+	ret = kstrtol(buf, 10, &val);
-+	if (ret)
-+	   return ret;
-+
-+	ipts_dbg(ipts, "try sensor mode = %ld\n", val);
-+
-+	switch (val) {
-+		case TOUCH_SENSOR_MODE_HID:
-+			break;
-+		case TOUCH_SENSOR_MODE_RAW_DATA:
-+			break;
-+		default:
-+			ipts_err(ipts, "sensor mode %ld is not supported\n", val);
-+	}
-+
-+	return count;
-+}
-+
-+static ssize_t device_info_show(struct device *dev,
-+				struct device_attribute *attr, char *buf)
-+{
-+	ipts_info_t *ipts;
-+
-+	ipts = dev_get_drvdata(dev);
-+	return sprintf(buf, "vendor id = 0x%04hX\n"
-+				"device id = 0x%04hX\n"
-+				"HW rev = 0x%08X\n"
-+				"firmware rev = 0x%08X\n",
-+			ipts->device_info.vendor_id, ipts->device_info.device_id,
-+			ipts->device_info.hw_rev, ipts->device_info.fw_rev);
-+}
-+
-+static DEVICE_ATTR_RW(sensor_mode);
-+static DEVICE_ATTR_RO(device_info);
-+
-+static struct attribute *ipts_attrs[] = {
-+	&dev_attr_sensor_mode.attr,
-+	&dev_attr_device_info.attr,
-+	NULL
-+};
-+
-+static const struct attribute_group ipts_grp = {
-+	.attrs = ipts_attrs,
-+};
-+
-+MODULE_DEVICE_TABLE(mei, ipts_mei_cl_tbl);
-+
-+static void raw_data_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, raw_data_work);
-+
-+	ipts_handle_processed_data(ipts);
-+}
-+
-+static void gfx_status_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, gfx_status_work);
-+	ipts_state_t state;
-+	int status = ipts->gfx_status;
-+
-+	ipts_dbg(ipts, "notify gfx status : %d\n", status);
-+
-+	state = ipts_get_state(ipts);
-+
-+	if (state == IPTS_STA_RAW_DATA_STARTED || state == IPTS_STA_HID_STARTED) {
-+		if (status == IPTS_NOTIFY_STA_BACKLIGHT_ON &&
-+					ipts->display_status == false) {
-+			ipts_send_sensor_clear_mem_window_cmd(ipts);
-+			ipts->display_status = true;
-+		} else if (status == IPTS_NOTIFY_STA_BACKLIGHT_OFF &&
-+					ipts->display_status == true) {
-+			ipts_send_sensor_quiesce_io_cmd(ipts);
-+			ipts->display_status = false;
-+		}
-+	}
-+}
-+
-+/* event loop */
-+static int ipts_mei_cl_event_thread(void *data)
-+{
-+	ipts_info_t *ipts = (ipts_info_t *)data;
-+	struct mei_cl_device *cldev = ipts->cldev;
-+	ssize_t msg_len;
-+	touch_sensor_msg_m2h_t m2h_msg;
-+
-+	while (!kthread_should_stop()) {
-+		msg_len = mei_cldev_recv(cldev, (u8*)&m2h_msg, sizeof(m2h_msg));
-+		if (msg_len <= 0) {
-+			ipts_err(ipts, "error in reading m2h msg\n");
-+			continue;
-+		}
-+
-+		if (ipts_handle_resp(ipts, &m2h_msg, msg_len) != 0) {
-+			ipts_err(ipts, "error in handling resp msg\n");
-+		}
-+	}
-+
-+	ipts_dbg(ipts, "!! end event loop !!\n");
-+
-+	return 0;
-+}
-+
-+static void init_work_func(struct work_struct *work)
-+{
-+	ipts_info_t *ipts = container_of(work, ipts_info_t, init_work);
-+
-+	ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA;
-+	ipts->display_status = true;
-+
-+	ipts_start(ipts);
-+}
-+
-+static int ipts_mei_cl_probe(struct mei_cl_device *cldev,
-+			const struct mei_cl_device_id *id)
-+{
-+	int ret = 0;
-+	ipts_info_t *ipts = NULL;
-+
-+	pr_info("probing Intel Precise Touch & Stylus\n");
-+
-+	// setup the DMA BIT mask, the system will choose the best possible
-+	if (dma_coerce_mask_and_coherent(&cldev->dev, DMA_BIT_MASK(64)) == 0) {
-+		pr_info("IPTS using DMA_BIT_MASK(64)\n");
-+	} else if (dma_coerce_mask_and_coherent(&cldev->dev,
-+						DMA_BIT_MASK(32)) == 0) {
-+		pr_info("IPTS using  DMA_BIT_MASK(32)\n");
-+	} else {
-+		pr_err("IPTS: No suitable DMA available\n");
-+		return -EFAULT;
-+	}
-+
-+	ret = mei_cldev_enable(cldev);
-+	if (ret < 0) {
-+		pr_err("cannot enable IPTS\n");
-+		return ret;
-+	}
-+
-+	ipts = devm_kzalloc(&cldev->dev, sizeof(ipts_info_t), GFP_KERNEL);
-+	if (ipts == NULL) {
-+		ret = -ENOMEM;
-+		goto disable_mei;
-+	}
-+	ipts->cldev = cldev;
-+	mei_cldev_set_drvdata(cldev, ipts);
-+
-+	ipts->event_loop = kthread_run(ipts_mei_cl_event_thread, (void*)ipts,
-+							"ipts_event_thread");
-+
-+	if(ipts_dbgfs_register(ipts, "ipts"))
-+		pr_debug("cannot register debugfs for IPTS\n");
-+
-+	INIT_WORK(&ipts->init_work, init_work_func);
-+	INIT_WORK(&ipts->raw_data_work, raw_data_work_func);
-+	INIT_WORK(&ipts->gfx_status_work, gfx_status_work_func);
-+
-+	ret = sysfs_create_group(&cldev->dev.kobj, &ipts_grp);
-+	if (ret != 0) {
-+		pr_debug("cannot create sysfs for IPTS\n");
-+	}
-+
-+	schedule_work(&ipts->init_work);
-+
-+	return 0;
-+
-+disable_mei :
-+	mei_cldev_disable(cldev);
-+	
-+	return ret;
-+}
-+
-+static int ipts_mei_cl_remove(struct mei_cl_device *cldev)
-+{
-+	ipts_info_t *ipts = mei_cldev_get_drvdata(cldev);
-+
-+	ipts_stop(ipts);
-+
-+	sysfs_remove_group(&cldev->dev.kobj, &ipts_grp);
-+	ipts_hid_release(ipts);
-+	ipts_dbgfs_deregister(ipts);
-+	mei_cldev_disable(cldev);
-+
-+	kthread_stop(ipts->event_loop);
-+
-+	pr_info("IPTS removed\n");
-+
-+	return 0;
-+}
-+
-+static struct mei_cl_driver ipts_mei_cl_driver = {
-+	.id_table = ipts_mei_cl_tbl,
-+	.name = IPTS_DRIVER_NAME,
-+	.probe = ipts_mei_cl_probe,
-+	.remove = ipts_mei_cl_remove,
-+};
-+
-+static int ipts_mei_cl_init(void)
-+{
-+	int ret;
-+
-+	pr_info("IPTS %s() is called\n", __func__);
-+
-+	ret = mei_cldev_driver_register(&ipts_mei_cl_driver);
-+	if (ret) {
-+		pr_err("unable to register IPTS mei client driver\n");
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+static void __exit ipts_mei_cl_exit(void)
-+{
-+	pr_info("IPTS %s() is called\n", __func__);
-+
-+	mei_cldev_driver_unregister(&ipts_mei_cl_driver);
-+}
-+
-+module_init(ipts_mei_cl_init);
-+module_exit(ipts_mei_cl_exit);
-+
-+MODULE_DESCRIPTION
-+	("Intel(R) Management Engine Interface Client Driver for "\
-+	"Intel Precision Touch and Sylus");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/misc/ipts/ipts-msg-handler.c b/drivers/misc/ipts/ipts-msg-handler.c
-new file mode 100644
-index 000000000000..1396ecc7197f
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-msg-handler.c
-@@ -0,0 +1,431 @@
-+#include <linux/mei_cl_bus.h>
-+
-+#include "ipts.h"
-+#include "ipts-hid.h"
-+#include "ipts-resource.h"
-+#include "ipts-mei-msgs.h"
-+
-+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size)
-+{
-+	int ret = 0;
-+	touch_sensor_msg_h2m_t h2m_msg;
-+	int len = 0;
-+
-+	memset(&h2m_msg, 0, sizeof(h2m_msg));
-+
-+	h2m_msg.command_code = cmd;
-+	len = sizeof(h2m_msg.command_code) + data_size;
-+	if (data != NULL && data_size != 0)
-+		memcpy(&h2m_msg.h2m_data, data, data_size); /* copy payload */
-+
-+	ret = mei_cldev_send(ipts->cldev, (u8*)&h2m_msg, len);
-+	if (ret < 0) {
-+		ipts_err(ipts, "mei_cldev_send() error 0x%X:%d\n",
-+							cmd, ret);
-+		return ret;
-+	}
-+
-+	return 0;
-+}
-+
-+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id)
-+{
-+	int ret;
-+	int cmd_len;
-+	touch_sensor_feedback_ready_cmd_data_t fb_ready_cmd;
-+
-+	cmd_len = sizeof(touch_sensor_feedback_ready_cmd_data_t);
-+	memset(&fb_ready_cmd, 0, cmd_len);
-+
-+	fb_ready_cmd.feedback_index = buffer_idx;
-+	fb_ready_cmd.transaction_id = transaction_id;
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_FEEDBACK_READY_CMD,
-+				&fb_ready_cmd, cmd_len);
-+
-+	return ret;
-+}
-+
-+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts)
-+{
-+	int ret;
-+	int cmd_len;
-+	touch_sensor_quiesce_io_cmd_data_t quiesce_io_cmd;
-+
-+	cmd_len = sizeof(touch_sensor_quiesce_io_cmd_data_t);
-+	memset(&quiesce_io_cmd, 0, cmd_len);
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_QUIESCE_IO_CMD,
-+				&quiesce_io_cmd, cmd_len);
-+
-+	return ret;
-+}
-+
-+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts)
-+{
-+	return ipts_handle_cmd(ipts, TOUCH_SENSOR_HID_READY_FOR_DATA_CMD, NULL, 0);
-+}
-+
-+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts)
-+{
-+	return ipts_handle_cmd(ipts, TOUCH_SENSOR_CLEAR_MEM_WINDOW_CMD, NULL, 0);
-+}
-+
-+static int check_validity(touch_sensor_msg_m2h_t *m2h_msg, u32 msg_len)
-+{
-+	int ret = 0;
-+	int valid_msg_len = sizeof(m2h_msg->command_code);
-+	u32 cmd_code = m2h_msg->command_code;
-+
-+	switch (cmd_code) {
-+		case TOUCH_SENSOR_SET_MODE_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_mode_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_SET_MEM_WINDOW_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_mem_window_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_QUIESCE_IO_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_quiesce_io_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_hid_ready_for_data_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_FEEDBACK_READY_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_feedback_ready_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_clear_mem_window_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_notify_dev_ready_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_SET_POLICIES_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_set_policies_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_GET_POLICIES_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_get_policies_rsp_data_t);
-+			break;
-+		case TOUCH_SENSOR_RESET_RSP:
-+			valid_msg_len +=
-+				sizeof(touch_sensor_reset_rsp_data_t);
-+			break;
-+	}
-+
-+	if (valid_msg_len != msg_len) {
-+		return -EINVAL;
-+	}
-+
-+	return ret;
-+}
-+
-+int ipts_start(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+	/* TODO : check if we need to do SET_POLICIES_CMD
-+	we need to do this when protocol version doesn't match with reported one
-+	how we keep vendor specific data is the first thing to solve */
-+
-+	ipts_set_state(ipts, IPTS_STA_INIT);
-+	ipts->num_of_parallel_data_buffers = TOUCH_SENSOR_MAX_DATA_BUFFERS;
-+
-+	ipts->sensor_mode = TOUCH_SENSOR_MODE_RAW_DATA; /* start with RAW_DATA */
-+
-+	ret = ipts_handle_cmd(ipts, TOUCH_SENSOR_NOTIFY_DEV_READY_CMD, NULL, 0);
-+
-+	return ret;
-+}
-+
-+void ipts_stop(ipts_info_t *ipts)
-+{
-+	ipts_state_t old_state;
-+
-+	old_state = ipts_get_state(ipts);
-+	ipts_set_state(ipts, IPTS_STA_STOPPING);
-+
-+	if (old_state < IPTS_STA_RESOURCE_READY)
-+		return;
-+
-+	if (old_state == IPTS_STA_RAW_DATA_STARTED ||
-+					old_state == IPTS_STA_HID_STARTED) {
-+        	ipts_free_default_resource(ipts);
-+		ipts_free_raw_data_resource(ipts);
-+
-+		return;
-+	}
-+}
-+
-+int ipts_restart(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ipts_dbg(ipts, "ipts restart\n");
-+
-+	ipts_stop(ipts);
-+
-+	ipts->retry++;
-+	if (ipts->retry == IPTS_MAX_RETRY && 
-+			ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) {
-+		/* try with HID mode */
-+		ipts->sensor_mode = TOUCH_SENSOR_MODE_HID;
-+	} else if (ipts->retry > IPTS_MAX_RETRY) {
-+		return -EPERM;
-+	}
-+
-+	ipts_send_sensor_quiesce_io_cmd(ipts);
-+	ipts->restart = true;
-+
-+	return ret;
-+}
-+
-+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode)
-+{
-+	int ret = 0;
-+
-+        ipts->new_sensor_mode = new_sensor_mode;
-+	ipts->switch_sensor_mode = true;
-+        ret = ipts_send_sensor_quiesce_io_cmd(ipts);
-+
-+	return ret;
-+}
-+
-+#define rsp_failed(ipts, cmd, status) ipts_err(ipts, \
-+				"0x%08x failed status = %d\n", cmd, status);
-+
-+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg,
-+								u32 msg_len)
-+{
-+	int ret = 0;
-+	int rsp_status = 0;
-+	int cmd_status = 0;
-+	int cmd_len = 0;
-+	u32 cmd;
-+
-+	if (!check_validity(m2h_msg, msg_len)) {
-+		ipts_err(ipts, "wrong rsp\n");
-+		return -EINVAL;
-+	}
-+
-+	rsp_status = m2h_msg->status;
-+	cmd = m2h_msg->command_code;
-+
-+	switch (cmd) {
-+		case TOUCH_SENSOR_NOTIFY_DEV_READY_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_SENSOR_FAIL_NONFATAL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_status = ipts_handle_cmd(ipts,
-+					TOUCH_SENSOR_GET_DEVICE_INFO_CMD,
-+					NULL, 0);
-+			break;
-+		case TOUCH_SENSOR_GET_DEVICE_INFO_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			memcpy(&ipts->device_info,
-+				&m2h_msg->m2h_data.device_info_rsp_data,
-+				sizeof(touch_sensor_get_device_info_rsp_data_t));
-+
-+			/*
-+			    TODO : support raw_request during HID init.
-+			    Although HID init happens here, technically most of
-+			    reports (for both direction) can be issued only
-+			    after SET_MEM_WINDOWS_CMD since they may require
-+			    ME or touch IC. If ipts vendor requires raw_request
-+			    during HID init, we need to consider to move HID init.
-+			*/
-+			if (ipts->hid_desc_ready == false) {
-+				ret = ipts_hid_init(ipts);
-+				if (ret)
-+					break;
-+			}
-+
-+			cmd_status = ipts_send_sensor_clear_mem_window_cmd(ipts);
-+
-+			break;
-+		case TOUCH_SENSOR_CLEAR_MEM_WINDOW_RSP:
-+		{
-+			touch_sensor_set_mode_cmd_data_t sensor_mode_cmd;
-+
-+			if (rsp_status != 0 &&
-+					rsp_status != TOUCH_STATUS_TIMEOUT) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			/* allocate default resource : common & hid only */
-+			if (!ipts_is_default_resource_ready(ipts)) {
-+				ret = ipts_allocate_default_resource(ipts);
-+				if (ret)
-+					break;
-+			}
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA &&
-+					!ipts_is_raw_data_resource_ready(ipts)) {
-+				ret = ipts_allocate_raw_data_resource(ipts);
-+				if (ret) {
-+					ipts_free_default_resource(ipts);
-+					break;
-+				}
-+			}
-+
-+			ipts_set_state(ipts, IPTS_STA_RESOURCE_READY);
-+
-+			cmd_len = sizeof(touch_sensor_set_mode_cmd_data_t);
-+			memset(&sensor_mode_cmd, 0, cmd_len);
-+			sensor_mode_cmd.sensor_mode = ipts->sensor_mode;
-+			cmd_status = ipts_handle_cmd(ipts,
-+				TOUCH_SENSOR_SET_MODE_CMD,
-+				&sensor_mode_cmd, cmd_len);
-+			break;
-+		}
-+		case TOUCH_SENSOR_SET_MODE_RSP:
-+		{
-+			touch_sensor_set_mem_window_cmd_data_t smw_cmd;
-+
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_len = sizeof(touch_sensor_set_mem_window_cmd_data_t);
-+			memset(&smw_cmd, 0, cmd_len);
-+			ipts_get_set_mem_window_cmd_data(ipts, &smw_cmd);
-+			cmd_status = ipts_handle_cmd(ipts,
-+				TOUCH_SENSOR_SET_MEM_WINDOW_CMD,
-+				&smw_cmd, cmd_len);
-+			break;
-+		}
-+		case TOUCH_SENSOR_SET_MEM_WINDOW_RSP:
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			cmd_status = ipts_send_sensor_hid_ready_for_data_cmd(ipts);
-+			if (cmd_status)
-+				break;
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) {
-+				ipts_set_state(ipts, IPTS_STA_HID_STARTED);
-+			} else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA) {
-+				ipts_set_state(ipts, IPTS_STA_RAW_DATA_STARTED);
-+			}
-+
-+			ipts_err(ipts, "touch enabled %d\n", ipts_get_state(ipts));
-+
-+			break;
-+		case TOUCH_SENSOR_HID_READY_FOR_DATA_RSP:
-+		{
-+			touch_sensor_hid_ready_for_data_rsp_data_t *hid_data;
-+			ipts_state_t state;
-+
-+			if (rsp_status != 0 &&
-+				  rsp_status != TOUCH_STATUS_SENSOR_DISABLED) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			state = ipts_get_state(ipts);
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID &&
-+						state == IPTS_STA_HID_STARTED) {
-+
-+				hid_data = &m2h_msg->m2h_data.hid_ready_for_data_rsp_data;
-+
-+				/* HID mode only uses buffer 0 */
-+				if (hid_data->touch_data_buffer_index != 0)
-+					break;
-+
-+				/* handle hid data */
-+				ipts_handle_hid_data(ipts, hid_data);
-+			}
-+
-+			break;
-+		}
-+		case TOUCH_SENSOR_FEEDBACK_READY_RSP:
-+			if (rsp_status != 0 &&
-+			  rsp_status != TOUCH_STATUS_COMPAT_CHECK_FAIL) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			if (m2h_msg->m2h_data.feedback_ready_rsp_data.
-+					feedback_index == TOUCH_HID_2_ME_BUFFER_ID)
-+				break;
-+
-+			if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID) {
-+				cmd_status = ipts_handle_cmd(ipts,
-+					TOUCH_SENSOR_HID_READY_FOR_DATA_CMD,
-+					NULL, 0);
-+			}
-+
-+			/* reset retry since we are getting touch data */
-+			ipts->retry = 0;
-+
-+			break;
-+		case TOUCH_SENSOR_QUIESCE_IO_RSP:
-+		{
-+			ipts_state_t state;
-+
-+			if (rsp_status != 0) {
-+				rsp_failed(ipts, cmd, rsp_status);
-+				break;
-+			}
-+
-+			state = ipts_get_state(ipts);
-+			if (state == IPTS_STA_STOPPING && ipts->restart) {
-+				ipts_dbg(ipts, "restart\n");
-+			        ipts_start(ipts);
-+				ipts->restart = 0;
-+				break;
-+			}
-+
-+			/* support sysfs debug node for switch sensor mode */
-+			if (ipts->switch_sensor_mode) {
-+				ipts_set_state(ipts, IPTS_STA_INIT);
-+				ipts->sensor_mode = ipts->new_sensor_mode;
-+				ipts->switch_sensor_mode = false;
-+
-+				ipts_send_sensor_clear_mem_window_cmd(ipts);
-+			}
-+
-+			break;
-+		}
-+	}
-+
-+	/* handle error in rsp_status */
-+	if (rsp_status != 0) {
-+		switch (rsp_status) {
-+			case TOUCH_STATUS_SENSOR_EXPECTED_RESET:
-+			case TOUCH_STATUS_SENSOR_UNEXPECTED_RESET:
-+				ipts_dbg(ipts, "sensor reset %d\n", rsp_status);
-+				ipts_restart(ipts);
-+				break;
-+			default:
-+				ipts_dbg(ipts, "cmd : 0x%08x, status %d\n",
-+								cmd,
-+								rsp_status);
-+				break;
-+		}
-+	}
-+
-+	if (cmd_status) {
-+		ipts_restart(ipts);
-+	}
-+
-+	return ret;
-+}
-diff --git a/drivers/misc/ipts/ipts-msg-handler.h b/drivers/misc/ipts/ipts-msg-handler.h
-new file mode 100644
-index 000000000000..b8e27d30c63e
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-msg-handler.h
-@@ -0,0 +1,32 @@
-+/*
-+ *
-+ * Intel Precise Touch & Stylus ME message handler
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_MSG_HANDLER_H
-+#define _IPTS_MSG_HANDLER_H
-+
-+int ipts_handle_cmd(ipts_info_t *ipts, u32 cmd, void *data, int data_size);
-+int ipts_start(ipts_info_t *ipts);
-+void ipts_stop(ipts_info_t *ipts);
-+int ipts_switch_sensor_mode(ipts_info_t *ipts, int new_sensor_mode);
-+int ipts_handle_resp(ipts_info_t *ipts, touch_sensor_msg_m2h_t *m2h_msg,
-+                        					u32 msg_len);
-+int ipts_handle_processed_data(ipts_info_t *ipts);
-+int ipts_send_feedback(ipts_info_t *ipts, int buffer_idx, u32 transaction_id);
-+int ipts_send_sensor_quiesce_io_cmd(ipts_info_t *ipts);
-+int ipts_send_sensor_hid_ready_for_data_cmd(ipts_info_t *ipts);
-+int ipts_send_sensor_clear_mem_window_cmd(ipts_info_t *ipts);
-+
-+#endif /* _IPTS_MSG_HANDLER_H */
-diff --git a/drivers/misc/ipts/ipts-resource.c b/drivers/misc/ipts/ipts-resource.c
-new file mode 100644
-index 000000000000..47607ef7c461
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-resource.c
-@@ -0,0 +1,277 @@
-+#include <linux/dma-mapping.h>
-+
-+#include "ipts.h"
-+#include "ipts-mei-msgs.h"
-+#include "ipts-kernel.h"
-+
-+static void free_common_resource(ipts_info_t *ipts)
-+{
-+	char *addr;
-+	ipts_buffer_info_t *feedback_buffer;
-+	dma_addr_t dma_addr;
-+	u32 buffer_size;
-+	int i, num_of_parallels;
-+
-+	if (ipts->resource.me2hid_buffer) {
-+		devm_kfree(&ipts->cldev->dev, ipts->resource.me2hid_buffer);
-+		ipts->resource.me2hid_buffer = 0;
-+	}
-+
-+	addr = ipts->resource.hid2me_buffer.addr;
-+	dma_addr = ipts->resource.hid2me_buffer.dma_addr;
-+	buffer_size = ipts->resource.hid2me_buffer_size;
-+
-+	if (ipts->resource.hid2me_buffer.addr) {
-+		dmam_free_coherent(&ipts->cldev->dev, buffer_size, addr, dma_addr);
-+		ipts->resource.hid2me_buffer.addr = 0;
-+		ipts->resource.hid2me_buffer.dma_addr = 0;
-+		ipts->resource.hid2me_buffer_size = 0;
-+	}
-+
-+	feedback_buffer = ipts->resource.feedback_buffer;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		if (feedback_buffer[i].addr) {
-+			dmam_free_coherent(&ipts->cldev->dev,
-+				ipts->device_info.feedback_size,
-+				feedback_buffer[i].addr,
-+				feedback_buffer[i].dma_addr);
-+			feedback_buffer[i].addr = 0;
-+			feedback_buffer[i].dma_addr = 0;
-+		}
-+	}
-+}
-+
-+static int allocate_common_resource(ipts_info_t *ipts)
-+{
-+	char *addr, *me2hid_addr;
-+	ipts_buffer_info_t *feedback_buffer;
-+	dma_addr_t dma_addr;
-+	int i, ret = 0, num_of_parallels;
-+	u32 buffer_size;
-+
-+	buffer_size = ipts->device_info.feedback_size;
-+
-+	addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+			buffer_size,
-+			&dma_addr,
-+			GFP_ATOMIC|__GFP_ZERO);
-+	if (addr == NULL)
-+		return -ENOMEM;
-+
-+	me2hid_addr = devm_kzalloc(&ipts->cldev->dev, buffer_size, GFP_KERNEL);
-+	if (me2hid_addr == NULL) {
-+		ret = -ENOMEM;
-+		goto release_resource;
-+	}
-+
-+	ipts->resource.hid2me_buffer.addr = addr;
-+	ipts->resource.hid2me_buffer.dma_addr = dma_addr;
-+	ipts->resource.hid2me_buffer_size = buffer_size;
-+	ipts->resource.me2hid_buffer = me2hid_addr;
-+
-+	feedback_buffer = ipts->resource.feedback_buffer;
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		feedback_buffer[i].addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+				ipts->device_info.feedback_size,
-+				&feedback_buffer[i].dma_addr,
-+				GFP_ATOMIC|__GFP_ZERO);
-+
-+		if (feedback_buffer[i].addr == NULL) {
-+			ret = -ENOMEM;
-+			goto release_resource;
-+		}
-+	}
-+
-+	return 0;
-+
-+release_resource:
-+	free_common_resource(ipts);
-+
-+	return ret;
-+}
-+
-+void ipts_free_raw_data_resource(ipts_info_t *ipts)
-+{
-+	if (ipts_is_raw_data_resource_ready(ipts)) {
-+		ipts->resource.raw_data_resource_ready = false;
-+
-+		ipts_release_kernels(ipts);
-+	}
-+}
-+
-+static int allocate_hid_resource(ipts_info_t *ipts)
-+{
-+	ipts_buffer_info_t *buffer_hid;
-+
-+	/* hid mode uses only one touch data buffer */
-+	buffer_hid = &ipts->resource.touch_data_buffer_hid;
-+	buffer_hid->addr = dmam_alloc_coherent(&ipts->cldev->dev,
-+				ipts->device_info.frame_size,
-+				&buffer_hid->dma_addr,
-+				GFP_ATOMIC|__GFP_ZERO);
-+	if (buffer_hid->addr == NULL) {
-+		return -ENOMEM;
-+	}
-+
-+	return 0;
-+}
-+
-+static void free_hid_resource(ipts_info_t *ipts)
-+{
-+	ipts_buffer_info_t *buffer_hid;
-+
-+	buffer_hid = &ipts->resource.touch_data_buffer_hid;
-+	if (buffer_hid->addr) {
-+		dmam_free_coherent(&ipts->cldev->dev,
-+				ipts->device_info.frame_size,
-+				buffer_hid->addr,
-+				buffer_hid->dma_addr);
-+		buffer_hid->addr = 0;
-+		buffer_hid->dma_addr = 0;
-+	}
-+}
-+
-+int ipts_allocate_default_resource(ipts_info_t *ipts)
-+{
-+	int ret;
-+
-+	ret = allocate_common_resource(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot allocate common resource\n");
-+		return ret;
-+	}
-+
-+	ret = allocate_hid_resource(ipts);
-+	if (ret) {
-+		ipts_dbg(ipts, "cannot allocate hid resource\n");
-+		free_common_resource(ipts);
-+		return ret;
-+	}
-+
-+	ipts->resource.default_resource_ready = true;
-+
-+	return 0;
-+}
-+
-+void ipts_free_default_resource(ipts_info_t *ipts)
-+{
-+	if (ipts_is_default_resource_ready(ipts)) {
-+		ipts->resource.default_resource_ready = false;
-+
-+		free_hid_resource(ipts);
-+		free_common_resource(ipts);
-+	}
-+}
-+
-+int ipts_allocate_raw_data_resource(ipts_info_t *ipts)
-+{
-+	int ret = 0;
-+
-+	ret = ipts_init_kernels(ipts);
-+	if (ret) {
-+		return ret;
-+	}
-+
-+	ipts->resource.raw_data_resource_ready = true;
-+
-+	return 0;
-+}
-+
-+static void get_hid_only_smw_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data,
-+				ipts_resource_t *resrc)
-+{
-+	ipts_buffer_info_t *touch_buf;
-+	ipts_buffer_info_t *feedback_buf;
-+
-+	touch_buf = &resrc->touch_data_buffer_hid;
-+	feedback_buf = &resrc->feedback_buffer[0];
-+
-+	data->touch_data_buffer_addr_lower[0] =
-+				lower_32_bits(touch_buf->dma_addr);
-+	data->touch_data_buffer_addr_upper[0] =
-+				upper_32_bits(touch_buf->dma_addr);
-+	data->feedback_buffer_addr_lower[0] =
-+				lower_32_bits(feedback_buf->dma_addr);
-+	data->feedback_buffer_addr_upper[0] =
-+				upper_32_bits(feedback_buf->dma_addr);
-+}
-+
-+static void get_raw_data_only_smw_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data,
-+				ipts_resource_t *resrc)
-+{
-+	u64 wq_tail_phy_addr;
-+	u64 cookie_phy_addr;
-+	ipts_buffer_info_t *touch_buf;
-+	ipts_buffer_info_t *feedback_buf;
-+	int i, num_of_parallels;
-+
-+	touch_buf = resrc->touch_data_buffer_raw;
-+	feedback_buf = resrc->feedback_buffer;
-+
-+	num_of_parallels = ipts_get_num_of_parallel_buffers(ipts);
-+	for (i = 0; i < num_of_parallels; i++) {
-+		data->touch_data_buffer_addr_lower[i] =
-+					lower_32_bits(touch_buf[i].dma_addr);
-+		data->touch_data_buffer_addr_upper[i] =
-+					upper_32_bits(touch_buf[i].dma_addr);
-+		data->feedback_buffer_addr_lower[i] =
-+					lower_32_bits(feedback_buf[i].dma_addr);
-+		data->feedback_buffer_addr_upper[i] =
-+					upper_32_bits(feedback_buf[i].dma_addr);
-+	}
-+
-+	wq_tail_phy_addr = resrc->wq_info.wq_tail_phy_addr;
-+	data->tail_offset_addr_lower = lower_32_bits(wq_tail_phy_addr);
-+	data->tail_offset_addr_upper = upper_32_bits(wq_tail_phy_addr);
-+
-+	cookie_phy_addr = resrc->wq_info.db_phy_addr +
-+						resrc->wq_info.db_cookie_offset;
-+	data->doorbell_cookie_addr_lower = lower_32_bits(cookie_phy_addr);
-+	data->doorbell_cookie_addr_upper = upper_32_bits(cookie_phy_addr);
-+	data->work_queue_size = resrc->wq_info.wq_size;
-+
-+	data->work_queue_item_size = resrc->wq_item_size;
-+}
-+
-+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data)
-+{
-+	ipts_resource_t *resrc = &ipts->resource;
-+
-+	if (ipts->sensor_mode == TOUCH_SENSOR_MODE_RAW_DATA)
-+		get_raw_data_only_smw_cmd_data(ipts, data, resrc);
-+	else if (ipts->sensor_mode == TOUCH_SENSOR_MODE_HID)
-+		get_hid_only_smw_cmd_data(ipts, data, resrc);
-+
-+	/* hid2me is common for "raw data" and "hid" */
-+	data->hid2me_buffer_addr_lower =
-+				lower_32_bits(resrc->hid2me_buffer.dma_addr);
-+	data->hid2me_buffer_addr_upper =
-+				upper_32_bits(resrc->hid2me_buffer.dma_addr);
-+	data->hid2me_buffer_size = resrc->hid2me_buffer_size;
-+}
-+
-+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx,
-+						u8* cpu_addr, u64 dma_addr)
-+{
-+	ipts_buffer_info_t *touch_buf;
-+
-+	touch_buf = ipts->resource.touch_data_buffer_raw;
-+	touch_buf[parallel_idx].dma_addr = dma_addr;
-+	touch_buf[parallel_idx].addr = cpu_addr;
-+}
-+
-+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx,
-+						u8* cpu_addr, u64 dma_addr)
-+{
-+	ipts_buffer_info_t *output_buf;
-+
-+	output_buf = &ipts->resource.raw_data_mode_output_buffer[parallel_idx][output_idx];
-+
-+	output_buf->dma_addr = dma_addr;
-+	output_buf->addr = cpu_addr;
-+}
-diff --git a/drivers/misc/ipts/ipts-resource.h b/drivers/misc/ipts/ipts-resource.h
-new file mode 100644
-index 000000000000..7d66ac72b475
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-resource.h
-@@ -0,0 +1,30 @@
-+/*
-+ * Intel Precise Touch & Stylus state codes
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_RESOURCE_H_
-+#define _IPTS_RESOURCE_H_
-+
-+int ipts_allocate_default_resource(ipts_info_t *ipts);
-+void ipts_free_default_resource(ipts_info_t *ipts);
-+int ipts_allocate_raw_data_resource(ipts_info_t *ipts);
-+void ipts_free_raw_data_resource(ipts_info_t *ipts);
-+void ipts_get_set_mem_window_cmd_data(ipts_info_t *ipts,
-+				touch_sensor_set_mem_window_cmd_data_t *data);
-+void ipts_set_input_buffer(ipts_info_t *ipts, int parallel_idx,
-+						u8* cpu_addr, u64 dma_addr);
-+void ipts_set_output_buffer(ipts_info_t *ipts, int parallel_idx, int output_idx,
-+						u8* cpu_addr, u64 dma_addr);
-+
-+#endif // _IPTS_RESOURCE_H_
-diff --git a/drivers/misc/ipts/ipts-sensor-regs.h b/drivers/misc/ipts/ipts-sensor-regs.h
-new file mode 100644
-index 000000000000..96812b0eb980
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-sensor-regs.h
-@@ -0,0 +1,700 @@
-+/*
-+ * Touch Sensor Register definition
-+ *
-+ * Copyright (c) 2013-2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+
-+#ifndef _TOUCH_SENSOR_REGS_H
-+#define _TOUCH_SENSOR_REGS_H
-+
-+#pragma pack(1)
-+
-+// define C_ASSERT macro to check structure size and fail compile for unexpected mismatch
-+#ifndef C_ASSERT
-+#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
-+#endif
-+
-+//
-+// Compatibility versions for this header file
-+//
-+#define TOUCH_EDS_REV_MINOR     0
-+#define TOUCH_EDS_REV_MAJOR     1
-+#define TOUCH_EDS_INTF_REV      1
-+#define TOUCH_PROTOCOL_VER      0
-+
-+
-+//
-+// Offset 00h: TOUCH_STS: Status Register
-+// This register is read by the SPI Controller immediately following an interrupt.
-+//
-+#define TOUCH_STS_REG_OFFSET                0x00
-+
-+typedef enum touch_sts_reg_int_type
-+{
-+    TOUCH_STS_REG_INT_TYPE_DATA_AVAIL = 0,  // Touch Data Available
-+    TOUCH_STS_REG_INT_TYPE_RESET_OCCURRED,  // Reset Occurred
-+    TOUCH_STS_REG_INT_TYPE_ERROR_OCCURRED,  // Error Occurred
-+    TOUCH_STS_REG_INT_TYPE_VENDOR_DATA,     // Vendor specific data, treated same as raw frame
-+    TOUCH_STS_REG_INT_TYPE_GET_FEATURES,    // Get Features response data available
-+    TOUCH_STS_REG_INT_TYPE_MAX
-+} touch_sts_reg_int_type_t;
-+C_ASSERT(sizeof(touch_sts_reg_int_type_t) == 4);
-+
-+typedef enum touch_sts_reg_pwr_state
-+{
-+    TOUCH_STS_REG_PWR_STATE_SLEEP = 0,  // Sleep
-+    TOUCH_STS_REG_PWR_STATE_DOZE,       // Doze
-+    TOUCH_STS_REG_PWR_STATE_ARMED,      // Armed
-+    TOUCH_STS_REG_PWR_STATE_SENSING,    // Sensing
-+    TOUCH_STS_REG_PWR_STATE_MAX
-+} touch_sts_reg_pwr_state_t;
-+C_ASSERT(sizeof(touch_sts_reg_pwr_state_t) == 4);
-+
-+typedef enum touch_sts_reg_init_state
-+{
-+    TOUCH_STS_REG_INIT_STATE_READY_FOR_OP = 0,  // Ready for normal operation
-+    TOUCH_STS_REG_INIT_STATE_FW_NEEDED,         // Touch IC needs its Firmware loaded
-+    TOUCH_STS_REG_INIT_STATE_DATA_NEEDED,       // Touch IC needs its Data loaded
-+    TOUCH_STS_REG_INIT_STATE_INIT_ERROR,        // Error info in TOUCH_ERR_REG
-+    TOUCH_STS_REG_INIT_STATE_MAX
-+} touch_sts_reg_init_state_t;
-+C_ASSERT(sizeof(touch_sts_reg_init_state_t) == 4);
-+
-+#define TOUCH_SYNC_BYTE_VALUE   0x5A
-+
-+typedef union touch_sts_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // When set, this indicates the hardware has data that needs to be read.
-+        u32  int_status           :1;
-+        // see TOUCH_STS_REG_INT_TYPE
-+        u32  int_type             :4;
-+        // see TOUCH_STS_REG_PWR_STATE
-+        u32  pwr_state            :2;
-+        // see TOUCH_STS_REG_INIT_STATE
-+        u32  init_state           :2;
-+        // Busy bit indicates that sensor cannot accept writes at this time
-+        u32  busy                :1;
-+        // Reserved
-+        u32  reserved            :14;
-+        // Synchronization bit, should always be TOUCH_SYNC_BYTE_VALUE
-+        u32  sync_byte            :8;
-+    } fields;
-+} touch_sts_reg_t;
-+C_ASSERT(sizeof(touch_sts_reg_t) == 4);
-+
-+
-+//
-+// Offset 04h: TOUCH_FRAME_CHAR: Frame Characteristics Register
-+// This registers describes the characteristics of each data frame read by the SPI Controller in
-+// response to a touch interrupt.
-+//
-+#define TOUCH_FRAME_CHAR_REG_OFFSET         0x04
-+
-+typedef union touch_frame_char_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Micro-Frame Size (MFS):  Indicates the size of a touch micro-frame in byte increments.
-+        // When a micro-frame is to be read for processing (in data mode), this is the total number of
-+        // bytes that must be read per interrupt, split into multiple read commands no longer than RPS.
-+        // Maximum micro-frame size is 256KB.
-+        u32  microframe_size      :18;
-+        // Micro-Frames per Frame (MFPF): Indicates the number of micro-frames per frame. If a
-+        // sensor's frame does not contain micro-frames this value will be 1. Valid values are 1-31.
-+        u32  microframes_per_frame :5;
-+        // Micro-Frame Index (MFI): Indicates the index of the micro-frame within a frame. This allows
-+        // the SPI Controller to maintain synchronization with the sensor and determine when the final
-+        // micro-frame has arrived. Valid values are 1-31.
-+        u32  microframe_index     :5;
-+        // HID/Raw Data: This bit describes whether the data from the sensor is Raw data or a HID
-+        // report. When set, the data is a HID report.
-+        u32  hid_report           :1;
-+        // Reserved
-+        u32  reserved            :3;
-+    } fields;
-+} touch_frame_char_reg_t;
-+C_ASSERT(sizeof(touch_frame_char_reg_t) == 4);
-+
-+
-+//
-+// Offset 08h: Touch Error Register
-+//
-+#define TOUCH_ERR_REG_OFFSET                0x08
-+
-+// bit definition is vendor specific
-+typedef union touch_err_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        u32  invalid_fw           :1;
-+        u32  invalid_data        :1;
-+        u32  self_test_failed       :1;
-+        u32  reserved            :12;
-+        u32  fatal_error          :1;
-+        u32  vendor_errors        :16;
-+    } fields;
-+} touch_err_reg_t;
-+C_ASSERT(sizeof(touch_err_reg_t) == 4);
-+
-+
-+//
-+// Offset 0Ch: RESERVED
-+// This register is reserved for future use.
-+//
-+
-+
-+//
-+// Offset 10h: Touch Identification Register
-+//
-+#define TOUCH_ID_REG_OFFSET                 0x10
-+
-+#define TOUCH_ID_REG_VALUE                  0x43495424
-+
-+// expected value is "$TIC" or 0x43495424
-+typedef u32  touch_id_reg_t;
-+C_ASSERT(sizeof(touch_id_reg_t) == 4);
-+
-+
-+//
-+// Offset 14h: TOUCH_DATA_SZ: Touch Data Size Register
-+// This register describes the maximum size of frames and feedback data
-+//
-+#define TOUCH_DATA_SZ_REG_OFFSET            0x14
-+
-+#define TOUCH_MAX_FRAME_SIZE_INCREMENT      64
-+#define TOUCH_MAX_FEEDBACK_SIZE_INCREMENT   64
-+
-+#define TOUCH_SENSOR_MAX_FRAME_SIZE         (32 * 1024)     // Max allowed frame size 32KB
-+#define TOUCH_SENSOR_MAX_FEEDBACK_SIZE      (16 * 1024)     // Max allowed feedback size 16KB
-+
-+typedef union touch_data_sz_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // This value describes the maximum frame size in 64byte increments.
-+        u32  max_frame_size        :12;
-+        // This value describes the maximum feedback size in 64byte increments.
-+        u32  max_feedback_size     :8;
-+        // Reserved
-+        u32  reserved            :12;
-+    } fields;
-+} touch_data_sz_reg_t;
-+C_ASSERT(sizeof(touch_data_sz_reg_t) == 4);
-+
-+
-+//
-+// Offset 18h: TOUCH_CAPABILITIES: Touch Capabilities Register
-+// This register informs the host as to the capabilities of the touch IC.
-+//
-+#define TOUCH_CAPS_REG_OFFSET               0x18
-+
-+typedef enum touch_caps_reg_read_delay_time
-+{
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_0,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_10uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_50uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_100uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_150uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_250uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_500uS,
-+    TOUCH_CAPS_REG_READ_DELAY_TIME_1mS,
-+} touch_caps_reg_read_delay_time_t;
-+C_ASSERT(sizeof(touch_caps_reg_read_delay_time_t) == 4);
-+
-+#define TOUCH_BULK_DATA_MAX_WRITE_INCREMENT 64
-+
-+typedef union touch_caps_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Reserved for future frequency
-+        u32  reserved0           :1;
-+        // 17 MHz (14 MHz on Atom) Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_17Mhz      :1;
-+        // 30 MHz (25MHz on Atom) Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_30Mhz      :1;
-+        // 50 MHz Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_50Mhz      :1;
-+        // Reserved
-+        u32  reserved1           :4;
-+        // Single I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_single_io   :1;
-+        // Dual I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_dual_io     :1;
-+        // Quad I/O Supported: 0b - Not supported, 1b - Supported
-+        u32  supported_quad_io     :1;
-+        // Bulk Data Area Max Write Size: The amount of data the SPI Controller can write to the bulk
-+        // data area before it has to poll the busy bit. This field is in multiples of 64 bytes. The
-+        // SPI Controller will write the amount of data specified in this field, then check and wait
-+        // for the Status.Busy bit to be zero before writing the next data chunk. This field is 6 bits
-+        // long, allowing for 4KB of contiguous writes w/o a poll of the busy bit. If this field is
-+        // 0x00 the Touch IC has no limit in the amount of data the SPI Controller can write to the
-+        // bulk data area.
-+        u32  bulk_data_max_write    :6;
-+        // Read Delay Timer Value: This field describes the delay the SPI Controller will initiate when
-+        // a read interrupt follows a write data command. Uses values from TOUCH_CAPS_REG_READ_DELAY_TIME
-+        u32  read_delay_timer_value :3;
-+        // Reserved
-+        u32  reserved2           :4;
-+        // Maximum Touch Points: A byte value based on the HID descriptor definition.
-+        u32  max_touch_points      :8;
-+    } fields;
-+} touch_caps_reg_t;
-+C_ASSERT(sizeof(touch_caps_reg_t) == 4);
-+
-+
-+//
-+// Offset 1Ch: TOUCH_CFG: Touch Configuration Register
-+// This register allows the SPI Controller to configure the touch sensor as needed during touch
-+// operations.
-+//
-+#define TOUCH_CFG_REG_OFFSET                0x1C
-+
-+typedef enum touch_cfg_reg_bulk_xfer_size
-+{
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_4B  = 0,   // Bulk Data Transfer Size is 4 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_8B,        // Bulk Data Transfer Size is 8 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_16B,       // Bulk Data Transfer Size is 16 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_32B,       // Bulk Data Transfer Size is 32 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_64B,       // Bulk Data Transfer Size is 64 bytes
-+    TOUCH_CFG_REG_BULK_XFER_SIZE_MAX
-+} touch_cfg_reg_bulk_xfer_size_t;
-+C_ASSERT(sizeof(touch_cfg_reg_bulk_xfer_size_t) == 4);
-+
-+// Frequency values used by TOUCH_CFG_REG and TOUCH_SENSOR_GET_DEVICE_INFO_RSP_DATA.
-+typedef enum touch_freq
-+{
-+    TOUCH_FREQ_RSVD = 0,    // Reserved value
-+    TOUCH_FREQ_17MHZ,       // Sensor set for 17MHz operation (14MHz on Atom)
-+    TOUCH_FREQ_30MHZ,       // Sensor set for 30MHz operation (25MHz on Atom)
-+    TOUCH_FREQ_MAX          // Invalid value
-+} touch_freq_t;
-+C_ASSERT(sizeof(touch_freq_t) == 4);
-+
-+typedef union touch_cfg_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Touch Enable (TE):  This bit is used as a HW semaphore for the Touch IC to guarantee to the
-+        // SPI Controller to that (when 0) no sensing operations will occur and only the Reset
-+        // interrupt will be generated. When TE is cleared by the SPI Controller:
-+        //  - TICs must flush all output buffers
-+        //  - TICs must De-assert any pending interrupt
-+        //  - ME must throw away any partial frame and pending interrupt must be cleared/not serviced.
-+        // The SPI Controller will only modify the configuration of the TIC when TE is cleared. TE is
-+        // defaulted to 0h on a power-on reset.
-+        u32  touch_enable         :1;
-+        // Data/HID Packet Mode (DHPM): Raw Data Mode: 0h, HID Packet Mode: 1h
-+        u32  dhpm                :1;
-+        // Bulk Data Transfer Size: This field represents the amount of data written to the Bulk Data
-+        // Area (SPI Offset 0x1000-0x2FFF) in a single SPI write protocol
-+        u32  bulk_xfer_size        :4;
-+        // Frequency Select: Frequency for the TouchIC to run at. Use values from TOUCH_FREQ
-+        u32  freq_select          :3;
-+        // Reserved
-+        u32  reserved            :23;
-+    } fields;
-+} touch_cfg_reg_t;
-+C_ASSERT(sizeof(touch_cfg_reg_t) == 4);
-+
-+
-+//
-+// Offset 20h: TOUCH_CMD: Touch Command Register
-+// This register is used for sending commands to the Touch IC.
-+//
-+#define TOUCH_CMD_REG_OFFSET                0x20
-+
-+typedef enum touch_cmd_reg_code
-+{
-+    TOUCH_CMD_REG_CODE_NOP = 0,             // No Operation
-+    TOUCH_CMD_REG_CODE_SOFT_RESET,          // Soft Reset
-+    TOUCH_CMD_REG_CODE_PREP_4_READ,         // Prepare All Registers for Read
-+    TOUCH_CMD_REG_CODE_GEN_TEST_PACKETS,    // Generate Test Packets according to value in TOUCH_TEST_CTRL_REG
-+    TOUCH_CMD_REG_CODE_MAX
-+} touch_cmd_reg_code_t;
-+C_ASSERT(sizeof(touch_cmd_reg_code_t) == 4);
-+
-+typedef union touch_cmd_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Command Code: See TOUCH_CMD_REG_CODE
-+        u32  command_code :8;
-+        // Reserved
-+        u32  reserved    :24;
-+    } fields;
-+} touch_cmd_reg_t;
-+C_ASSERT(sizeof(touch_cmd_reg_t) == 4);
-+
-+
-+//
-+// Offset 24h: Power Management Control
-+// This register is used for active power management. The Touch IC is allowed to mover from Doze or
-+// Armed to Sensing after a touch has occurred. All other transitions will be made at the request
-+// of the SPI Controller.
-+//
-+#define TOUCH_PWR_MGMT_CTRL_REG_OFFSET      0x24
-+
-+typedef enum touch_pwr_mgmt_ctrl_reg_cmd
-+{
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_NOP = 0,    // No change to power state
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_SLEEP,      // Sleep   - set when the system goes into connected standby
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_DOZE,       // Doze    - set after 300 seconds of inactivity
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_ARMED,      // Armed   - Set by FW when a "finger off" message is received from the EUs
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_SENSING,    // Sensing - not typically set by FW
-+    TOUCH_PWR_MGMT_CTRL_REG_CMD_MAX         // Values will result in no change to the power state of the Touch IC
-+} touch_pwr_mgmt_ctrl_reg_cmd_t;
-+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_cmd_t) == 4);
-+
-+typedef union touch_pwr_mgmt_ctrl_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Power State Command: See TOUCH_PWR_MGMT_CTRL_REG_CMD
-+        u32  pwr_state_cmd         :3;
-+        // Reserved
-+        u32  reserved            :29;
-+    } fields;
-+} touch_pwr_mgmt_ctrl_reg_t;
-+C_ASSERT(sizeof(touch_pwr_mgmt_ctrl_reg_t) == 4);
-+
-+
-+//
-+// Offset 28h: Vendor HW Information Register
-+// This register is used to relay Intel-assigned vendor ID information to the SPI Controller, which
-+// may be forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_VEN_HW_INFO_REG_OFFSET        0x28
-+
-+typedef union touch_ven_hw_info_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Touch Sensor Vendor ID
-+        u32  vendor_id            :16;
-+        // Touch Sensor Device ID
-+        u32  device_id            :16;
-+    } fields;
-+} touch_ven_hw_info_reg_t;
-+C_ASSERT(sizeof(touch_ven_hw_info_reg_t) == 4);
-+
-+
-+//
-+// Offset 2Ch: HW Revision ID Register
-+// This register is used to relay vendor HW revision information to the SPI Controller which may be
-+// forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_HW_REV_REG_OFFSET             0x2C
-+
-+typedef u32  touch_hw_rev_reg_t;   // bit definition is vendor specific
-+C_ASSERT(sizeof(touch_hw_rev_reg_t) == 4);
-+
-+
-+//
-+// Offset 30h: FW Revision ID Register
-+// This register is used to relay vendor FW revision information to the SPI Controller which may be
-+// forwarded to SW running on the host CPU.
-+//
-+#define TOUCH_FW_REV_REG_OFFSET             0x30
-+
-+typedef u32  touch_fw_rev_reg_t;    // bit definition is vendor specific
-+C_ASSERT(sizeof(touch_fw_rev_reg_t) == 4);
-+
-+
-+//
-+// Offset 34h: Compatibility Revision ID Register
-+// This register is used to relay vendor compatibility information to the SPI Controller which may
-+// be forwarded to SW running on the host CPU. Compatibility Information is a numeric value given
-+// by Intel to the Touch IC vendor based on the major and minor revision of the EDS supported. From
-+// a nomenclature point of view in an x.y revision number of the EDS, the major version is the value
-+// of x and the minor version is the value of y. For example, a Touch IC supporting an EDS version
-+// of 0.61 would contain a major version of 0 and a minor version of 61 in the register.
-+//
-+#define TOUCH_COMPAT_REV_REG_OFFSET             0x34
-+
-+typedef union touch_compat_rev_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // EDS Minor Revision
-+        u8   minor;
-+        // EDS Major Revision
-+        u8   major;
-+        // Interface Revision Number (from EDS)
-+        u8   intf_rev;
-+        // EU Kernel Compatibility Version - vendor specific value
-+        u8   kernel_compat_ver;
-+    } fields;
-+} touch_compat_rev_reg_t;
-+C_ASSERT(sizeof(touch_compat_rev_reg_t) == 4);
-+
-+
-+//
-+// Touch Register Block is the full set of registers from offset 0x00h to 0x3F
-+// This is the entire set of registers needed for normal touch operation. It does not include test
-+// registers such as TOUCH_TEST_CTRL_REG
-+//
-+#define TOUCH_REG_BLOCK_OFFSET              TOUCH_STS_REG_OFFSET
-+
-+typedef struct touch_reg_block
-+{
-+    touch_sts_reg_t         sts_reg;         // 0x00
-+    touch_frame_char_reg_t  frame_char_reg;   // 0x04
-+    touch_err_reg_t         error_reg;       // 0x08
-+    u32                  reserved0;      // 0x0C
-+    touch_id_reg_t          id_reg;          // 0x10
-+    touch_data_sz_reg_t     data_size_reg;    // 0x14
-+    touch_caps_reg_t        caps_reg;        // 0x18
-+    touch_cfg_reg_t         cfg_reg;         // 0x1C
-+    touch_cmd_reg_t         cmd_reg;         // 0x20
-+    touch_pwr_mgmt_ctrl_reg_t  pwm_mgme_ctrl_reg; // 0x24
-+    touch_ven_hw_info_reg_t ven_hw_info_reg;   // 0x28
-+    touch_hw_rev_reg_t      hw_rev_reg;       // 0x2C
-+    touch_fw_rev_reg_t      fw_rev_reg;       // 0x30
-+    touch_compat_rev_reg_t  compat_rev_reg;   // 0x34
-+    u32                  reserved1;      // 0x38
-+    u32                  reserved2;      // 0x3C
-+} touch_reg_block_t;
-+C_ASSERT(sizeof(touch_reg_block_t) == 64);
-+
-+
-+//
-+// Offset 40h: Test Control Register
-+// This register
-+//
-+#define TOUCH_TEST_CTRL_REG_OFFSET              0x40
-+
-+typedef union touch_test_ctrl_reg
-+{
-+    u32  reg_value;
-+
-+    struct
-+    {
-+        // Size of Test Frame in Raw Data Mode: This field specifies the test frame size in raw data
-+        // mode in multiple of 64 bytes. For example, if this field value is 16, the test frame size
-+        // will be 16x64 = 1K.
-+        u32  raw_test_frame_size    :16;
-+        // Number of Raw Data Frames or HID Report Packets Generation. This field represents the number
-+        // of test frames or HID reports to be generated when test mode is enabled. When multiple
-+        // packets/frames are generated, they need be generated at 100 Hz frequency, i.e. 10ms per
-+        // packet/frame.
-+        u32  num_test_frames       :16;
-+    } fields;
-+} touch_test_ctrl_reg_t;
-+C_ASSERT(sizeof(touch_test_ctrl_reg_t) == 4);
-+
-+
-+//
-+// Offsets 0x000 to 0xFFF are reserved for Intel-defined Registers
-+//
-+#define TOUCH_REGISTER_LIMIT                0xFFF
-+
-+
-+//
-+// Data Window: Address 0x1000-0x1FFFF
-+// The data window is reserved for writing and reading large quantities of data to and from the
-+// sensor.
-+//
-+#define TOUCH_DATA_WINDOW_OFFSET            0x1000
-+#define TOUCH_DATA_WINDOW_LIMIT             0x1FFFF
-+
-+#define TOUCH_SENSOR_MAX_OFFSET             TOUCH_DATA_WINDOW_LIMIT
-+
-+
-+//
-+// The following data structures represent the headers defined in the Data Structures chapter of the
-+// Intel Integrated Touch EDS
-+//
-+
-+// Enumeration used in TOUCH_RAW_DATA_HDR
-+typedef enum touch_raw_data_types
-+{
-+    TOUCH_RAW_DATA_TYPE_FRAME = 0,
-+    TOUCH_RAW_DATA_TYPE_ERROR,          // RawData will be the TOUCH_ERROR struct below
-+    TOUCH_RAW_DATA_TYPE_VENDOR_DATA,    // Set when InterruptType is Vendor Data
-+    TOUCH_RAW_DATA_TYPE_HID_REPORT,
-+    TOUCH_RAW_DATA_TYPE_GET_FEATURES,
-+    TOUCH_RAW_DATA_TYPE_MAX
-+} touch_raw_data_types_t;
-+C_ASSERT(sizeof(touch_raw_data_types_t) == 4);
-+
-+// Private data structure. Kernels must copy to HID driver buffer
-+typedef struct touch_hid_private_data
-+{
-+    u32  transaction_id;
-+    u8   reserved[28];
-+} touch_hid_private_data_t;
-+C_ASSERT(sizeof(touch_hid_private_data_t) == 32);
-+
-+// This is the data structure sent from the PCH FW to the EU kernel
-+typedef struct touch_raw_data_hdr
-+{
-+    u32                  data_type;           // use values from TOUCH_RAW_DATA_TYPES
-+    u32                  raw_data_size_bytes;   // The size in bytes of the raw data read from the
-+                                                // sensor, does not include TOUCH_RAW_DATA_HDR. Will
-+                                                // be the sum of all uFrames, or size of TOUCH_ERROR
-+                                                // for if DataType is TOUCH_RAW_DATA_TYPE_ERROR
-+    u32                  buffer_id;           // An ID to qualify with the feedback data to track
-+                                                // buffer usage
-+    u32                  protocol_ver;        // Must match protocol version of the EDS
-+    u8                   kernel_compat_id;     // Copied from the Compatibility Revision ID Reg
-+    u8                   reserved[15];       // Padding to extend header to full 64 bytes and
-+                                                // allow for growth
-+    touch_hid_private_data_t  hid_private_data;     // Private data structure. Kernels must copy to HID
-+                                                // driver buffer
-+} touch_raw_data_hdr_t;
-+C_ASSERT(sizeof(touch_raw_data_hdr_t) == 64);
-+
-+typedef struct touch_raw_data
-+{
-+    touch_raw_data_hdr_t  header;
-+    u8               raw_data[1]; // used to access the raw data as an array and keep the
-+                                    // compilers happy. Actual size of this array is
-+                                    // Header.RawDataSizeBytes
-+} touch_raw_data_t;
-+
-+
-+// The following section describes the data passed in TOUCH_RAW_DATA.RawData when DataType equals
-+// TOUCH_RAW_DATA_TYPE_ERROR
-+// Note: This data structure is also applied to HID mode
-+typedef enum touch_err_types
-+{
-+    TOUCH_RAW_DATA_ERROR = 0,
-+    TOUCH_RAW_ERROR_MAX
-+} touch_err_types_t;
-+C_ASSERT(sizeof(touch_err_types_t) == 4);
-+
-+typedef union touch_me_fw_error
-+{
-+    u32  value;
-+
-+    struct
-+    {
-+        u32 invalid_frame_characteristics : 1;
-+        u32 microframe_index_invalid      : 1;
-+        u32 reserved                    : 30;
-+    } fields;
-+} touch_me_fw_error_t;
-+C_ASSERT(sizeof(touch_me_fw_error_t) == 4);
-+
-+typedef struct touch_error
-+{
-+    u8			touch_error_type; // This must be a value from TOUCH_ERROR_TYPES
-+    u8			reserved[3];
-+    touch_me_fw_error_t	touch_me_fw_error;
-+    touch_err_reg_t	touch_error_register; // Contains the value copied from the Touch Error Reg
-+} touch_error_t;
-+C_ASSERT(sizeof(touch_error_t) == 12);
-+
-+// Enumeration used in TOUCH_FEEDBACK_BUFFER
-+typedef enum touch_feedback_cmd_types
-+{
-+    TOUCH_FEEDBACK_CMD_TYPE_NONE = 0,
-+    TOUCH_FEEDBACK_CMD_TYPE_SOFT_RESET,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_ARMED,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_SENSING,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_SLEEP,
-+    TOUCH_FEEDBACK_CMD_TYPE_GOTO_DOZE,
-+    TOUCH_FEEDBACK_CMD_TYPE_HARD_RESET,
-+    TOUCH_FEEDBACK_CMD_TYPE_MAX
-+} touch_feedback_cmd_types_t;
-+C_ASSERT(sizeof(touch_feedback_cmd_types_t) == 4);
-+
-+// Enumeration used in TOUCH_FEEDBACK_HDR
-+typedef enum touch_feedback_data_types
-+{
-+    TOUCH_FEEDBACK_DATA_TYPE_FEEDBACK = 0,  // This is vendor specific feedback to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_SET_FEATURES,  // This is a set features command to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_GET_FEATURES,  // This is a get features command to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_OUTPUT_REPORT, // This is a HID output report to be written to the sensor
-+    TOUCH_FEEDBACK_DATA_TYPE_STORE_DATA,    // This is calibration data to be written to system flash
-+    TOUCH_FEEDBACK_DATA_TYPE_MAX
-+} touch_feedback_data_types_t;
-+C_ASSERT(sizeof(touch_feedback_data_types_t) == 4);
-+
-+// This is the data structure sent from the EU kernels back to the ME FW.
-+// In addition to "feedback" data, the FW can execute a "command" described by the command type parameter.
-+// Any payload data will always be sent to the TIC first, then any command will be issued.
-+typedef struct touch_feedback_hdr
-+{
-+    u32  feedback_cmd_type;    // use values from TOUCH_FEEDBACK_CMD_TYPES
-+    u32  payload_size_bytes;   // The amount of data to be written to the sensor, not including the header
-+    u32  buffer_id;           // The ID of the raw data buffer that generated this feedback data
-+    u32  protocol_ver;        // Must match protocol version of the EDS
-+    u32  feedback_data_type;   // use values from TOUCH_FEEDBACK_DATA_TYPES. This is not relevant if PayloadSizeBytes is 0
-+    u32  spi_offest;          // The offset from TOUCH_DATA_WINDOW_OFFSET at which to write the Payload data. Maximum offset is 0x1EFFF.
-+    u8   reserved[40];       // Padding to extend header to full 64 bytes and allow for growth
-+} touch_feedback_hdr_t;
-+C_ASSERT(sizeof(touch_feedback_hdr_t) == 64);
-+
-+typedef struct touch_feedback_buffer
-+{
-+    touch_feedback_hdr_t  Header;
-+    u8               feedback_data[1];    // used to access the feedback data as an array and keep the compilers happy. Actual size of this array is Header.PayloadSizeBytes
-+} touch_feedback_buffer_t;
-+
-+
-+//
-+// This data structure describes the header prepended to all data
-+// written to the touch IC at the bulk data write (TOUCH_DATA_WINDOW_OFFSET + TOUCH_FEEDBACK_HDR.SpiOffest) address.
-+typedef enum touch_write_data_type
-+{
-+    TOUCH_WRITE_DATA_TYPE_FW_LOAD = 0,
-+    TOUCH_WRITE_DATA_TYPE_DATA_LOAD,
-+    TOUCH_WRITE_DATA_TYPE_FEEDBACK,
-+    TOUCH_WRITE_DATA_TYPE_SET_FEATURES,
-+    TOUCH_WRITE_DATA_TYPE_GET_FEATURES,
-+    TOUCH_WRITE_DATA_TYPE_OUTPUT_REPORT,
-+    TOUCH_WRITE_DATA_TYPE_NO_DATA_USE_DEFAULTS,
-+    TOUCH_WRITE_DATA_TYPE_MAX
-+} touch_write_data_type_t;
-+C_ASSERT(sizeof(touch_write_data_type_t) == 4);
-+
-+typedef struct touch_write_hdr
-+{
-+    u32  write_data_type;   // Use values from TOUCH_WRITE_DATA_TYPE
-+    u32  write_data_len;    // This field designates the amount of data to follow
-+} touch_write_hdr_t;
-+C_ASSERT(sizeof(touch_write_hdr_t) == 8);
-+
-+typedef struct touch_write_data
-+{
-+    touch_write_hdr_t header;
-+    u8           write_data[1];   // used to access the write data as an array and keep the compilers happy. Actual size of this array is Header.WriteDataLen
-+} touch_write_data_t;
-+
-+#pragma pack()
-+
-+#endif // _TOUCH_SENSOR_REGS_H
-diff --git a/drivers/misc/ipts/ipts-state.h b/drivers/misc/ipts/ipts-state.h
-new file mode 100644
-index 000000000000..39a2eaf5f004
---- /dev/null
-+++ b/drivers/misc/ipts/ipts-state.h
-@@ -0,0 +1,29 @@
-+/*
-+ * Intel Precise Touch & Stylus state codes
-+ *
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ */
-+
-+#ifndef _IPTS_STATE_H_
-+#define _IPTS_STATE_H_
-+
-+/* ipts driver states */
-+typedef enum ipts_state {
-+	IPTS_STA_NONE,
-+	IPTS_STA_INIT,
-+	IPTS_STA_RESOURCE_READY,
-+	IPTS_STA_HID_STARTED,
-+	IPTS_STA_RAW_DATA_STARTED,
-+	IPTS_STA_STOPPING
-+} ipts_state_t;
-+
-+#endif // _IPTS_STATE_H_
-diff --git a/drivers/misc/ipts/ipts.h b/drivers/misc/ipts/ipts.h
-new file mode 100644
-index 000000000000..1fcd02146b50
---- /dev/null
-+++ b/drivers/misc/ipts/ipts.h
-@@ -0,0 +1,200 @@
-+/*
-+ *
-+ * Intel Management Engine Interface (Intel MEI) Client Driver for IPTS
-+ * Copyright (c) 2016, Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef _IPTS_H_
-+#define _IPTS_H_
-+
-+#include <linux/types.h>
-+#include <linux/mei_cl_bus.h>
-+#include <linux/hid.h>
-+#include <linux/intel_ipts_if.h>
-+
-+#include "ipts-mei-msgs.h"
-+#include "ipts-state.h"
-+#include "ipts-binary-spec.h"
-+
-+//#define ENABLE_IPTS_DEBUG		/* enable IPTS debug */
-+
-+#ifdef ENABLE_IPTS_DEBUG
-+
-+#define ipts_info(ipts, format, arg...) do {\
-+	dev_info(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+#define ipts_dbg(ipts, format, arg...) do {\
-+	dev_info(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+//#define RUN_DBG_THREAD
-+
-+#else
-+
-+#define ipts_info(ipts, format, arg...) do {} while(0);
-+#define ipts_dbg(ipts, format, arg...) do {} while(0);
-+
-+#endif
-+
-+#define ipts_err(ipts, format, arg...) do {\
-+	dev_err(&ipts->cldev->dev, format, ##arg);\
-+} while (0)
-+
-+#define HID_PARALLEL_DATA_BUFFERS	TOUCH_SENSOR_MAX_DATA_BUFFERS
-+
-+#define IPTS_MAX_RETRY			3
-+
-+typedef struct ipts_buffer_info {
-+	char *addr;
-+	dma_addr_t dma_addr;
-+} ipts_buffer_info_t;
-+
-+typedef struct ipts_gfx_info {
-+	u64     gfx_handle;
-+	intel_ipts_ops_t ipts_ops;
-+} ipts_gfx_info_t;
-+
-+typedef struct ipts_resource {
-+	/* ME & Gfx resource */
-+	ipts_buffer_info_t touch_data_buffer_raw[HID_PARALLEL_DATA_BUFFERS];
-+	ipts_buffer_info_t touch_data_buffer_hid;
-+
-+	ipts_buffer_info_t feedback_buffer[HID_PARALLEL_DATA_BUFFERS];
-+
-+	ipts_buffer_info_t hid2me_buffer;
-+	u32 hid2me_buffer_size;
-+
-+	u8 wq_item_size;
-+	intel_ipts_wq_info_t wq_info;
-+
-+	/* ME2HID buffer */
-+	char *me2hid_buffer;
-+
-+	/* Gfx specific resource */
-+	ipts_buffer_info_t raw_data_mode_output_buffer
-+	    [HID_PARALLEL_DATA_BUFFERS][MAX_NUM_OUTPUT_BUFFERS];
-+
-+	int num_of_outputs;
-+
-+	bool default_resource_ready;
-+	bool raw_data_resource_ready;
-+} ipts_resource_t;
-+
-+typedef struct ipts_info {
-+	struct mei_cl_device *cldev;
-+	struct hid_device *hid;
-+
-+	struct work_struct init_work;
-+	struct work_struct raw_data_work;
-+	struct work_struct gfx_status_work;
-+
-+	struct task_struct *event_loop;
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+        struct dentry *dbgfs_dir;
-+#endif
-+
-+	ipts_state_t	state;
-+
-+	touch_sensor_mode_t	sensor_mode;
-+	touch_sensor_get_device_info_rsp_data_t device_info;
-+	ipts_resource_t	resource;
-+	u8		hid_input_report[HID_MAX_BUFFER_SIZE];
-+	int		num_of_parallel_data_buffers;
-+	bool		hid_desc_ready;
-+
-+	int current_buffer_index;
-+	int last_buffer_completed;
-+	int *last_submitted_id;
-+
-+	ipts_gfx_info_t gfx_info;
-+	u64		kernel_handle;
-+	int             gfx_status;
-+	bool		display_status;
-+
-+	bool		switch_sensor_mode;
-+	touch_sensor_mode_t	new_sensor_mode;
-+
-+	int		retry;
-+	bool		restart;
-+} ipts_info_t;
-+
-+#if IS_ENABLED(CONFIG_DEBUG_FS)
-+int ipts_dbgfs_register(ipts_info_t *ipts, const char *name);
-+void ipts_dbgfs_deregister(ipts_info_t *ipts);
-+#else
-+static int ipts_dbgfs_register(ipts_info_t *ipts, const char *name);
-+static void ipts_dbgfs_deregister(ipts_info_t *ipts);
-+#endif /* CONFIG_DEBUG_FS */
-+
-+/* inline functions */
-+static inline void ipts_set_state(ipts_info_t *ipts, ipts_state_t state)
-+{
-+	ipts->state = state;
-+}
-+
-+static inline ipts_state_t ipts_get_state(const ipts_info_t *ipts)
-+{
-+	return ipts->state;
-+}
-+
-+static inline bool ipts_is_default_resource_ready(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.default_resource_ready;
-+}
-+
-+static inline bool ipts_is_raw_data_resource_ready(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.raw_data_resource_ready;
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_feedback_buffer(ipts_info_t *ipts,
-+								int buffer_idx)
-+{
-+	return &ipts->resource.feedback_buffer[buffer_idx];
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_touch_data_buffer_hid(ipts_info_t *ipts)
-+{
-+	return &ipts->resource.touch_data_buffer_hid;
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_output_buffers_by_parallel_id(
-+							ipts_info_t *ipts,
-+                                                        int parallel_idx)
-+{
-+	return &ipts->resource.raw_data_mode_output_buffer[parallel_idx][0];
-+}
-+
-+static inline ipts_buffer_info_t* ipts_get_hid2me_buffer(ipts_info_t *ipts)
-+{
-+	return &ipts->resource.hid2me_buffer;
-+}
-+
-+static inline void ipts_set_wq_item_size(ipts_info_t *ipts, u8 size)
-+{
-+	ipts->resource.wq_item_size = size;
-+}
-+
-+static inline u8 ipts_get_wq_item_size(const ipts_info_t *ipts)
-+{
-+	return ipts->resource.wq_item_size;
-+}
-+
-+static inline int ipts_get_num_of_parallel_buffers(const ipts_info_t *ipts)
-+{
-+	return ipts->num_of_parallel_data_buffers;
-+}
-+
-+#endif // _IPTS_H_
-diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
-index e4b10b2d1a08..883b185c9dbe 100644
---- a/drivers/misc/mei/hw-me-regs.h
-+++ b/drivers/misc/mei/hw-me-regs.h
-@@ -119,6 +119,7 @@
- 
- #define MEI_DEV_ID_SPT        0x9D3A  /* Sunrise Point */
- #define MEI_DEV_ID_SPT_2      0x9D3B  /* Sunrise Point 2 */
-+#define MEI_DEV_ID_SPT_4      0x9D3E  /* Sunrise Point 4 */
- #define MEI_DEV_ID_SPT_H      0xA13A  /* Sunrise Point H */
- #define MEI_DEV_ID_SPT_H_2    0xA13B  /* Sunrise Point H 2 */
- 
-diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
-index ea4e152270a3..4d301ba3f867 100644
---- a/drivers/misc/mei/pci-me.c
-+++ b/drivers/misc/mei/pci-me.c
-@@ -86,6 +86,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
- 
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT, MEI_ME_PCH8_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
-+	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_4, MEI_ME_PCH8_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
- 	{MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)},
-diff --git a/include/linux/intel_ipts_if.h b/include/linux/intel_ipts_if.h
-new file mode 100644
-index 000000000000..f329bbfb8079
---- /dev/null
-+++ b/include/linux/intel_ipts_if.h
-@@ -0,0 +1,75 @@
-+/*
-+ *
-+ * GFX interface to support Intel Precise Touch & Stylus
-+ * Copyright (c) 2016 Intel Corporation.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms and conditions of the GNU General Public License,
-+ * version 2, as published by the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope 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.
-+ *
-+ */
-+
-+#ifndef INTEL_IPTS_IF_H
-+#define INTEL_IPTS_IF_H
-+
-+enum {
-+	IPTS_INTERFACE_V1 = 1,
-+};
-+
-+#define IPTS_BUF_FLAG_CONTIGUOUS	0x01
-+
-+#define IPTS_NOTIFY_STA_BACKLIGHT_OFF	0x00
-+#define IPTS_NOTIFY_STA_BACKLIGHT_ON	0x01
-+
-+typedef struct intel_ipts_mapbuffer {
-+	u32	size;
-+	u32	flags;
-+	void	*gfx_addr;
-+	void	*cpu_addr;
-+	u64	buf_handle;
-+	u64	phy_addr;
-+} intel_ipts_mapbuffer_t;
-+
-+typedef struct intel_ipts_wq_info {
-+	u64 db_addr;
-+	u64 db_phy_addr;
-+	u32 db_cookie_offset;
-+	u32 wq_size;
-+	u64 wq_addr;
-+	u64 wq_phy_addr;
-+	u64 wq_head_addr;	/* head of wq is managed by GPU */
-+	u64 wq_head_phy_addr;	/* head of wq is managed by GPU */
-+	u64 wq_tail_addr;	/* tail of wq is managed by CSME */
-+	u64 wq_tail_phy_addr;	/* tail of wq is managed by CSME */
-+} intel_ipts_wq_info_t;
-+
-+typedef struct intel_ipts_ops {
-+	int (*get_wq_info)(uint64_t gfx_handle, intel_ipts_wq_info_t *wq_info);
-+	int (*map_buffer)(uint64_t gfx_handle, intel_ipts_mapbuffer_t *mapbuffer);
-+	int (*unmap_buffer)(uint64_t gfx_handle, uint64_t buf_handle);
-+} intel_ipts_ops_t;
-+
-+typedef struct intel_ipts_callback {
-+        void (*workload_complete)(void *data);
-+        void (*notify_gfx_status)(u32 status, void *data);
-+} intel_ipts_callback_t;
-+
-+typedef struct intel_ipts_connect {
-+        intel_ipts_callback_t ipts_cb;	/* input : callback addresses */
-+	void *data;			/* input : callback data */
-+        u32 if_version;			/* input : interface version */
-+
-+        u32 gfx_version;		/* output : gfx version */
-+        u64 gfx_handle;			/* output : gfx handle */
-+	intel_ipts_ops_t ipts_ops;	/* output : gfx ops for IPTS */
-+} intel_ipts_connect_t;
-+
-+int intel_ipts_connect(intel_ipts_connect_t *ipts_connect);
-+void intel_ipts_disconnect(uint64_t gfx_handle);
-+
-+#endif // INTEL_IPTS_IF_H

+ 0 - 129
patches/4.17/keyboards_and_covers.patch

@@ -1,129 +0,0 @@
-diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
-index 46f5ecd11bf7..cceb745d2805 100644
---- a/drivers/hid/hid-ids.h
-+++ b/drivers/hid/hid-ids.h
-@@ -791,11 +791,21 @@
- #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1 0x0732
- #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_600  0x0750
- #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500	0x076c
--#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD 0x00e3
--#define USB_DEVICE_ID_MS_SURFACE_PRO_2   0x0799
--#define USB_DEVICE_ID_MS_TOUCH_COVER_2   0x07a7
--#define USB_DEVICE_ID_MS_TYPE_COVER_2    0x07a9
--#define USB_DEVICE_ID_MS_POWER_COVER     0x07da
-+#define USB_DEVICE_ID_MS_COMFORT_KEYBOARD	0x00e3
-+#define USB_DEVICE_ID_MS_SURFACE_PRO_2		0x0799
-+#define USB_DEVICE_ID_MS_TOUCH_COVER_2		0x07a7
-+#define USB_DEVICE_ID_MS_TYPE_COVER_2		0x07a9
-+#define USB_DEVICE_ID_MS_TYPE_COVER_3		0x07de
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3	0x07dc
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1	0x07de
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2	0x07e2
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP	0x07dd
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4	0x07e8
-+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1	0x07e4
-+#define USB_DEVICE_ID_MS_SURFACE_BOOK		0x07cd
-+#define USB_DEVICE_ID_MS_SURFACE_BOOK_2		0x0922
-+#define USB_DEVICE_ID_MS_SURFACE_LAPTOP		0xf001
-+#define USB_DEVICE_ID_MS_POWER_COVER		0x07da
- 
- #define USB_VENDOR_ID_MOJO		0x8282
- #define USB_DEVICE_ID_RETRO_ADAPTER	0x3201
-diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
-index 96e7d3231d2f..e55097221eec 100644
---- a/drivers/hid/hid-microsoft.c
-+++ b/drivers/hid/hid-microsoft.c
-@@ -278,7 +278,8 @@ static const struct hid_device_id ms_devices[] = {
- 		.driver_data = MS_HIDINPUT },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD),
- 		.driver_data = MS_ERGONOMY},
--
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_LAPTOP),
-+		.driver_data = MS_HIDINPUT},
- 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT),
- 		.driver_data = MS_PRESENTER },
- 	{ }
-diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
-index 1e561872a17f..8b7509ed5775 100644
---- a/drivers/hid/hid-multitouch.c
-+++ b/drivers/hid/hid-multitouch.c
-@@ -1744,6 +1744,58 @@ static const struct hid_device_id mt_devices[] = {
- 		HID_USB_DEVICE(USB_VENDOR_ID_LG,
- 			USB_DEVICE_ID_LG_MELFAS_MT) },
- 
-+	/* Microsoft Touch Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_TOUCH_COVER_2) },
-+
-+	/* Microsoft Type Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_2) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_3) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_4) },
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1) },
-+
-+	/* Microsoft Surface Book */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_SURFACE_BOOK) },
-+
-+	/* Microsoft Surface Book 2 */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_SURFACE_BOOK_2) },
-+
-+	/* Microsoft Surface Laptop */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
-+			USB_VENDOR_ID_MICROSOFT,
-+			USB_DEVICE_ID_MS_SURFACE_LAPTOP) },
-+
-+	/* Microsoft Power Cover */
-+	{ .driver_data = MT_CLS_EXPORT_ALL_INPUTS,
-+		MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT,
-+		USB_DEVICE_ID_MS_POWER_COVER) },
-+
- 	/* MosArt panels */
- 	{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
- 		MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
-diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
-index 587e2681a53f..4a5e335006d7 100644
---- a/drivers/hid/hid-quirks.c
-+++ b/drivers/hid/hid-quirks.c
-@@ -111,6 +111,16 @@ static const struct hid_device_id hid_quirks[] = {
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_1), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_1), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_BOOK_2), HID_QUIRK_NO_INIT_REPORTS },
-+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_LAPTOP), HID_QUIRK_ALWAYS_POLL },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER), HID_QUIRK_MULTI_INPUT },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL), HID_QUIRK_NO_INIT_REPORTS },
- 	{ HID_USB_DEVICE(USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD), HID_QUIRK_MULTI_INPUT },

+ 0 - 14
patches/4.17/sdcard_reader.patch

@@ -1,14 +0,0 @@
-diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
-index aa9968d90a48..64d620364093 100644
---- a/drivers/usb/core/hub.c
-+++ b/drivers/usb/core/hub.c
-@@ -4074,7 +4074,8 @@ void usb_enable_lpm(struct usb_device *udev)
- 	if (!udev || !udev->parent ||
- 			udev->speed < USB_SPEED_SUPER ||
- 			!udev->lpm_capable ||
--			udev->state < USB_STATE_DEFAULT)
-+			udev->state < USB_STATE_DEFAULT ||
-+			!udev->bos || !udev->bos->ss_cap)
- 		return;
- 
- 	udev->lpm_disable_count--;

+ 0 - 30
patches/4.17/surfacedock.patch

@@ -1,30 +0,0 @@
-diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
-index 5c42cf81a08b..5eb92c3f3ea3 100644
---- a/drivers/net/usb/cdc_ether.c
-+++ b/drivers/net/usb/cdc_ether.c
-@@ -807,13 +807,6 @@ static const struct usb_device_id	products[] = {
- 	.driver_info = 0,
- },
- 
--/* Microsoft Surface 3 dock (based on Realtek RTL8153) */
--{
--	USB_DEVICE_AND_INTERFACE_INFO(MICROSOFT_VENDOR_ID, 0x07c6, USB_CLASS_COMM,
--			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
--	.driver_info = 0,
--},
--
- 	/* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
- {
- 	USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
-diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
-index 86f7196f9d91..b6434f476679 100644
---- a/drivers/net/usb/r8152.c
-+++ b/drivers/net/usb/r8152.c
-@@ -5322,7 +5322,6 @@ static const struct usb_device_id rtl8152_table[] = {
- 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8152)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07ab)},
--	{REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x07c6)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x304f)},
- 	{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3062)},

+ 0 - 3
patches/4.17/wifi.patch

@@ -1,3 +0,0 @@
-diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl
-old mode 100755
-new mode 100644