From 9619f634857a3236a28db08b2cb63908235cd7fa Mon Sep 17 00:00:00 2001 From: Jake Day Date: Sun, 30 Dec 2018 09:03:34 -0500 Subject: [PATCH] removing outdated patches --- patches/4.14/acpica.patch | 211 - patches/4.14/cameras.patch | 151 - patches/4.14/ipts.patch | 6108 ----------------------- patches/4.14/keyboards_and_covers.patch | 119 - patches/4.14/sdcard_reader.patch | 20 - patches/4.14/surfaceacpi.patch | 510 -- patches/4.14/surfacedock.patch | 36 - patches/4.14/wifi.patch | 281 -- patches/4.15/acpica.patch | 263 - patches/4.15/cameras.patch | 150 - patches/4.15/ipts.patch | 6088 ---------------------- patches/4.15/keyboards_and_covers.patch | 119 - patches/4.15/sdcard_reader.patch | 20 - patches/4.15/surfaceacpi.patch | 510 -- patches/4.15/surfacedock.patch | 36 - patches/4.15/wifi.patch | 281 -- patches/4.16/acpica.patch | 163 - patches/4.16/cameras.patch | 156 - patches/4.16/ipts.patch | 6042 ---------------------- patches/4.16/keyboards_and_covers.patch | 116 - patches/4.16/sdcard_reader.patch | 20 - patches/4.16/surfaceacpi.patch | 510 -- patches/4.16/surfacedock.patch | 36 - patches/4.16/wifi.patch | 3 - patches/4.17/acpi.patch | 1324 ----- patches/4.17/buttons.patch | 299 -- patches/4.17/cameras.patch | 156 - patches/4.17/ipts.patch | 6055 ---------------------- patches/4.17/keyboards_and_covers.patch | 129 - patches/4.17/sdcard_reader.patch | 14 - patches/4.17/surfacedock.patch | 30 - patches/4.17/wifi.patch | 3 - 32 files changed, 29959 deletions(-) delete mode 100644 patches/4.14/acpica.patch delete mode 100644 patches/4.14/cameras.patch delete mode 100644 patches/4.14/ipts.patch delete mode 100644 patches/4.14/keyboards_and_covers.patch delete mode 100644 patches/4.14/sdcard_reader.patch delete mode 100644 patches/4.14/surfaceacpi.patch delete mode 100644 patches/4.14/surfacedock.patch delete mode 100644 patches/4.14/wifi.patch delete mode 100644 patches/4.15/acpica.patch delete mode 100644 patches/4.15/cameras.patch delete mode 100644 patches/4.15/ipts.patch delete mode 100644 patches/4.15/keyboards_and_covers.patch delete mode 100644 patches/4.15/sdcard_reader.patch delete mode 100644 patches/4.15/surfaceacpi.patch delete mode 100644 patches/4.15/surfacedock.patch delete mode 100644 patches/4.15/wifi.patch delete mode 100644 patches/4.16/acpica.patch delete mode 100644 patches/4.16/cameras.patch delete mode 100644 patches/4.16/ipts.patch delete mode 100644 patches/4.16/keyboards_and_covers.patch delete mode 100644 patches/4.16/sdcard_reader.patch delete mode 100644 patches/4.16/surfaceacpi.patch delete mode 100644 patches/4.16/surfacedock.patch delete mode 100644 patches/4.16/wifi.patch delete mode 100644 patches/4.17/acpi.patch delete mode 100644 patches/4.17/buttons.patch delete mode 100644 patches/4.17/cameras.patch delete mode 100644 patches/4.17/ipts.patch delete mode 100644 patches/4.17/keyboards_and_covers.patch delete mode 100644 patches/4.17/sdcard_reader.patch delete mode 100644 patches/4.17/surfacedock.patch delete mode 100644 patches/4.17/wifi.patch diff --git a/patches/4.14/acpica.patch b/patches/4.14/acpica.patch deleted file mode 100644 index 49b96e7c8..000000000 --- a/patches/4.14/acpica.patch +++ /dev/null @@ -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, ¤t_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 diff --git a/patches/4.14/cameras.patch b/patches/4.14/cameras.patch deleted file mode 100644 index d0a6097a4..000000000 --- a/patches/4.14/cameras.patch +++ /dev/null @@ -1,151 +0,0 @@ -From d4460b8c7124d6dd878acbd3207e2c41ceec5266 Mon Sep 17 00:00:00 2001 -From: Jake Day -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 - #include - --#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 } , - }; - - diff --git a/patches/4.14/ipts.patch b/patches/4.14/ipts.patch deleted file mode 100644 index b08efa64f..000000000 --- a/patches/4.14/ipts.patch +++ /dev/null @@ -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 -+#include -+#include -+#include -+#include -+ -+#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 - #include - #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 -+#include -+#include -+ -+#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 -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+ -+#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 -+ -+#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 -+#include -+#include -+#include -+ -+#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 diff --git a/patches/4.14/keyboards_and_covers.patch b/patches/4.14/keyboards_and_covers.patch deleted file mode 100644 index b99308907..000000000 --- a/patches/4.14/keyboards_and_covers.patch +++ /dev/null @@ -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 }, diff --git a/patches/4.14/sdcard_reader.patch b/patches/4.14/sdcard_reader.patch deleted file mode 100644 index b7ab737bf..000000000 --- a/patches/4.14/sdcard_reader.patch +++ /dev/null @@ -1,20 +0,0 @@ -From a0d8418d70e4411b1dc7837f3368e9b7102703fa Mon Sep 17 00:00:00 2001 -From: Jake Day -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--; diff --git a/patches/4.14/surfaceacpi.patch b/patches/4.14/surfaceacpi.patch deleted file mode 100644 index 6da586d51..000000000 --- a/patches/4.14/surfaceacpi.patch +++ /dev/null @@ -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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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, ¶ms, &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, ¶ms, &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); diff --git a/patches/4.14/surfacedock.patch b/patches/4.14/surfacedock.patch deleted file mode 100644 index b19f2dbf6..000000000 --- a/patches/4.14/surfacedock.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 952348ceeaf9c900407762d97b2e024272f01191 Mon Sep 17 00:00:00 2001 -From: Jake Day -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)}, diff --git a/patches/4.14/wifi.patch b/patches/4.14/wifi.patch deleted file mode 100644 index 416d8fae4..000000000 --- a/patches/4.14/wifi.patch +++ /dev/null @@ -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 diff --git a/patches/4.15/acpica.patch b/patches/4.15/acpica.patch deleted file mode 100644 index 9201b031a..000000000 --- a/patches/4.15/acpica.patch +++ /dev/null @@ -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, ¤t_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 diff --git a/patches/4.15/cameras.patch b/patches/4.15/cameras.patch deleted file mode 100644 index a17ed470c..000000000 --- a/patches/4.15/cameras.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 5549632053d4ae06867f383694553f7af27e40c9 Mon Sep 17 00:00:00 2001 -From: Jake Day -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 - #include - --#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 } , - }; - - diff --git a/patches/4.15/ipts.patch b/patches/4.15/ipts.patch deleted file mode 100644 index 1f24d97b4..000000000 --- a/patches/4.15/ipts.patch +++ /dev/null @@ -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 -+#include -+#include -+#include -+#include -+ -+#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 - #include - #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 -+#include -+#include -+ -+#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 -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+ -+#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 -+ -+#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 -+#include -+#include -+#include -+ -+#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 diff --git a/patches/4.15/keyboards_and_covers.patch b/patches/4.15/keyboards_and_covers.patch deleted file mode 100644 index a3a1f7739..000000000 --- a/patches/4.15/keyboards_and_covers.patch +++ /dev/null @@ -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 }, diff --git a/patches/4.15/sdcard_reader.patch b/patches/4.15/sdcard_reader.patch deleted file mode 100644 index 49d83359f..000000000 --- a/patches/4.15/sdcard_reader.patch +++ /dev/null @@ -1,20 +0,0 @@ -From fbd83f772a3be3a00bae323f6d71a59b26352c57 Mon Sep 17 00:00:00 2001 -From: Jake Day -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--; diff --git a/patches/4.15/surfaceacpi.patch b/patches/4.15/surfaceacpi.patch deleted file mode 100644 index 6da586d51..000000000 --- a/patches/4.15/surfaceacpi.patch +++ /dev/null @@ -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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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, ¶ms, &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, ¶ms, &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); diff --git a/patches/4.15/surfacedock.patch b/patches/4.15/surfacedock.patch deleted file mode 100644 index 8482bebd0..000000000 --- a/patches/4.15/surfacedock.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 3600aaa37a16777a07aa34672f12e30a1ae4d95b Mon Sep 17 00:00:00 2001 -From: Jake Day -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)}, diff --git a/patches/4.15/wifi.patch b/patches/4.15/wifi.patch deleted file mode 100644 index 547778bca..000000000 --- a/patches/4.15/wifi.patch +++ /dev/null @@ -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 diff --git a/patches/4.16/acpica.patch b/patches/4.16/acpica.patch deleted file mode 100644 index 17c85f098..000000000 --- a/patches/4.16/acpica.patch +++ /dev/null @@ -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 diff --git a/patches/4.16/cameras.patch b/patches/4.16/cameras.patch deleted file mode 100644 index fd9c0ef81..000000000 --- a/patches/4.16/cameras.patch +++ /dev/null @@ -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 - #include - --#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, -+ }, - {} - }; - diff --git a/patches/4.16/ipts.patch b/patches/4.16/ipts.patch deleted file mode 100644 index f9761d52a..000000000 --- a/patches/4.16/ipts.patch +++ /dev/null @@ -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 -+#include -+#include -+#include -+#include -+ -+#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 - #include - #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 -+#include -+#include -+ -+#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 -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+ -+#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 -+ -+#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 -+#include -+#include -+#include -+ -+#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 diff --git a/patches/4.16/keyboards_and_covers.patch b/patches/4.16/keyboards_and_covers.patch deleted file mode 100644 index 96195ce58..000000000 --- a/patches/4.16/keyboards_and_covers.patch +++ /dev/null @@ -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 }, diff --git a/patches/4.16/sdcard_reader.patch b/patches/4.16/sdcard_reader.patch deleted file mode 100644 index 49d83359f..000000000 --- a/patches/4.16/sdcard_reader.patch +++ /dev/null @@ -1,20 +0,0 @@ -From fbd83f772a3be3a00bae323f6d71a59b26352c57 Mon Sep 17 00:00:00 2001 -From: Jake Day -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--; diff --git a/patches/4.16/surfaceacpi.patch b/patches/4.16/surfaceacpi.patch deleted file mode 100644 index 6da586d51..000000000 --- a/patches/4.16/surfaceacpi.patch +++ /dev/null @@ -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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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, ¶ms, &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, ¶ms, &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); diff --git a/patches/4.16/surfacedock.patch b/patches/4.16/surfacedock.patch deleted file mode 100644 index 8482bebd0..000000000 --- a/patches/4.16/surfacedock.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 3600aaa37a16777a07aa34672f12e30a1ae4d95b Mon Sep 17 00:00:00 2001 -From: Jake Day -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)}, diff --git a/patches/4.16/wifi.patch b/patches/4.16/wifi.patch deleted file mode 100644 index b7fa9efc5..000000000 --- a/patches/4.16/wifi.patch +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl -old mode 100755 -new mode 100644 diff --git a/patches/4.17/acpi.patch b/patches/4.17/acpi.patch deleted file mode 100644 index 8e96f6376..000000000 --- a/patches/4.17/acpi.patch +++ /dev/null @@ -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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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, ¶ms, &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, ¶ms, &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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+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"); diff --git a/patches/4.17/buttons.patch b/patches/4.17/buttons.patch deleted file mode 100644 index 087f3453c..000000000 --- a/patches/4.17/buttons.patch +++ /dev/null @@ -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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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; - diff --git a/patches/4.17/cameras.patch b/patches/4.17/cameras.patch deleted file mode 100644 index 9e879d178..000000000 --- a/patches/4.17/cameras.patch +++ /dev/null @@ -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 - #include - --#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, -+ }, - {} - }; - diff --git a/patches/4.17/ipts.patch b/patches/4.17/ipts.patch deleted file mode 100644 index 46f79d457..000000000 --- a/patches/4.17/ipts.patch +++ /dev/null @@ -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 -+#include -+#include -+#include -+#include -+ -+#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 - #include - #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 -+#include -+#include -+ -+#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 -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+ -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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 -+ -+#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 -+ -+#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 -+#include -+#include -+#include -+ -+#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 diff --git a/patches/4.17/keyboards_and_covers.patch b/patches/4.17/keyboards_and_covers.patch deleted file mode 100644 index 43af90de2..000000000 --- a/patches/4.17/keyboards_and_covers.patch +++ /dev/null @@ -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 }, diff --git a/patches/4.17/sdcard_reader.patch b/patches/4.17/sdcard_reader.patch deleted file mode 100644 index 1d55b022a..000000000 --- a/patches/4.17/sdcard_reader.patch +++ /dev/null @@ -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--; diff --git a/patches/4.17/surfacedock.patch b/patches/4.17/surfacedock.patch deleted file mode 100644 index 14cffb988..000000000 --- a/patches/4.17/surfacedock.patch +++ /dev/null @@ -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)}, diff --git a/patches/4.17/wifi.patch b/patches/4.17/wifi.patch deleted file mode 100644 index b7fa9efc5..000000000 --- a/patches/4.17/wifi.patch +++ /dev/null @@ -1,3 +0,0 @@ -diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl -old mode 100755 -new mode 100644