Add the ability to load different IPTS firmware per model

Signed-off-by: Dorian Stoll <dorian.stoll@tmsp.io>
This commit is contained in:
Dorian Stoll 2019-09-17 16:55:32 +02:00 committed by Maximilian Luz
parent 292b082b29
commit de86889877
No known key found for this signature in database
GPG key ID: 70EC0937F6C26F02
2 changed files with 738 additions and 84 deletions

View file

@ -1,4 +1,4 @@
From d8171f6c5a5cdaad6171eda7bed33ebcd33c0323 Mon Sep 17 00:00:00 2001
From 22e6d68a0a5c874507cd7af75f6945b2f0b38cf9 Mon Sep 17 00:00:00 2001
From: kitakar5525 <34676735+kitakar5525@users.noreply.github.com>
Date: Tue, 10 Sep 2019 21:52:46 +0900
Subject: [PATCH 05/12] ipts
@ -24,20 +24,27 @@ Subject: [PATCH 05/12] ipts
drivers/hid/hid-multitouch.c | 22 +-
drivers/misc/Kconfig | 1 +
drivers/misc/Makefile | 1 +
drivers/misc/ipts/Kconfig | 9 +
drivers/misc/ipts/Makefile | 13 +
drivers/misc/ipts/Kconfig | 11 +
drivers/misc/ipts/Makefile | 17 +
drivers/misc/ipts/companion/Kconfig | 9 +
drivers/misc/ipts/companion/Makefile | 1 +
drivers/misc/ipts/companion/ipts-surface.c | 82 ++
drivers/misc/ipts/ipts-binary-spec.h | 118 +++
drivers/misc/ipts/ipts-dbgfs.c | 364 +++++++
drivers/misc/ipts/ipts-fw.c | 113 ++
drivers/misc/ipts/ipts-fw.h | 12 +
drivers/misc/ipts/ipts-gfx.c | 185 ++++
drivers/misc/ipts/ipts-gfx.h | 24 +
drivers/misc/ipts/ipts-hid.c | 504 +++++++++
drivers/misc/ipts/ipts-hid.c | 503 +++++++++
drivers/misc/ipts/ipts-hid.h | 34 +
drivers/misc/ipts/ipts-kernel.c | 1050 +++++++++++++++++++
drivers/misc/ipts/ipts-kernel.c | 1042 +++++++++++++++++++
drivers/misc/ipts/ipts-kernel.h | 23 +
drivers/misc/ipts/ipts-mei-msgs.h | 585 +++++++++++
drivers/misc/ipts/ipts-mei.c | 282 +++++
drivers/misc/ipts/ipts-mei.c | 290 ++++++
drivers/misc/ipts/ipts-msg-handler.c | 437 ++++++++
drivers/misc/ipts/ipts-msg-handler.h | 33 +
drivers/misc/ipts/ipts-params.c | 14 +
drivers/misc/ipts/ipts-params.h | 13 +
drivers/misc/ipts/ipts-resource.c | 277 +++++
drivers/misc/ipts/ipts-resource.h | 30 +
drivers/misc/ipts/ipts-sensor-regs.h | 700 +++++++++++++
@ -45,14 +52,20 @@ Subject: [PATCH 05/12] ipts
drivers/misc/ipts/ipts.h | 200 ++++
drivers/misc/mei/hw-me-regs.h | 1 +
drivers/misc/mei/pci-me.c | 1 +
include/linux/intel_ipts_fw.h | 14 +
include/linux/intel_ipts_if.h | 76 ++
42 files changed, 5889 insertions(+), 26 deletions(-)
50 files changed, 6152 insertions(+), 26 deletions(-)
create mode 100644 drivers/gpu/drm/i915/intel_ipts.c
create mode 100644 drivers/gpu/drm/i915/intel_ipts.h
create mode 100644 drivers/misc/ipts/Kconfig
create mode 100644 drivers/misc/ipts/Makefile
create mode 100644 drivers/misc/ipts/companion/Kconfig
create mode 100644 drivers/misc/ipts/companion/Makefile
create mode 100644 drivers/misc/ipts/companion/ipts-surface.c
create mode 100644 drivers/misc/ipts/ipts-binary-spec.h
create mode 100644 drivers/misc/ipts/ipts-dbgfs.c
create mode 100644 drivers/misc/ipts/ipts-fw.c
create mode 100644 drivers/misc/ipts/ipts-fw.h
create mode 100644 drivers/misc/ipts/ipts-gfx.c
create mode 100644 drivers/misc/ipts/ipts-gfx.h
create mode 100644 drivers/misc/ipts/ipts-hid.c
@ -63,11 +76,14 @@ Subject: [PATCH 05/12] ipts
create mode 100644 drivers/misc/ipts/ipts-mei.c
create mode 100644 drivers/misc/ipts/ipts-msg-handler.c
create mode 100644 drivers/misc/ipts/ipts-msg-handler.h
create mode 100644 drivers/misc/ipts/ipts-params.c
create mode 100644 drivers/misc/ipts/ipts-params.h
create mode 100644 drivers/misc/ipts/ipts-resource.c
create mode 100644 drivers/misc/ipts/ipts-resource.h
create mode 100644 drivers/misc/ipts/ipts-sensor-regs.h
create mode 100644 drivers/misc/ipts/ipts-state.h
create mode 100644 drivers/misc/ipts/ipts.h
create mode 100644 include/linux/intel_ipts_fw.h
create mode 100644 include/linux/intel_ipts_if.h
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
@ -85,7 +101,7 @@ index 5794f102f9b8..6ae0e91a213a 100644
i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
i915-$(CONFIG_DRM_I915_SELFTEST) += \
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index f9ce35da4123..c8b88b1b7bd4 100644
index e063e98d1e82..32d648c8adc5 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -31,6 +31,7 @@
@ -96,7 +112,7 @@ index f9ce35da4123..c8b88b1b7bd4 100644
static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node)
{
@@ -4691,6 +4692,64 @@ static const struct file_operations i915_fifo_underrun_reset_ops = {
@@ -4695,6 +4696,64 @@ static const struct file_operations i915_fifo_underrun_reset_ops = {
.llseek = default_llseek,
};
@ -161,7 +177,7 @@ index f9ce35da4123..c8b88b1b7bd4 100644
static const struct drm_info_list i915_debugfs_list[] = {
{"i915_capabilities", i915_capabilities, 0},
{"i915_gem_objects", i915_gem_object_info, 0},
@@ -4769,7 +4828,9 @@ static const struct i915_debugfs_files {
@@ -4773,7 +4832,9 @@ static const struct i915_debugfs_files {
{"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops},
{"i915_ipc_status", &i915_ipc_status_fops},
{"i915_drrs_ctl", &i915_drrs_ctl_fops},
@ -313,7 +329,7 @@ index 6c4d4a21474b..4ab800c3de6d 100644
#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 f92079e19de8..7c2d78044035 100644
index 20cd4c8acecc..6ec301a91e87 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2634,8 +2634,8 @@ void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
@ -1385,10 +1401,10 @@ index af22bbc3d00c..eb1eb0d58c32 100644
obj-$(CONFIG_SRAM) += sram.o
diff --git a/drivers/misc/ipts/Kconfig b/drivers/misc/ipts/Kconfig
new file mode 100644
index 000000000000..360ed3861b82
index 000000000000..a24c4daaed42
--- /dev/null
+++ b/drivers/misc/ipts/Kconfig
@@ -0,0 +1,9 @@
@@ -0,0 +1,11 @@
+config INTEL_IPTS
+ tristate "Intel Precise Touch & Stylus"
+ select INTEL_MEI
@ -1398,25 +1414,141 @@ index 000000000000..360ed3861b82
+ Supported SoCs:
+ Intel Skylake
+ Intel Kabylake
+
+source "drivers/misc/ipts/companion/Kconfig"
diff --git a/drivers/misc/ipts/Makefile b/drivers/misc/ipts/Makefile
new file mode 100644
index 000000000000..1783e9cf13c9
index 000000000000..78bb61933387
--- /dev/null
+++ b/drivers/misc/ipts/Makefile
@@ -0,0 +1,13 @@
@@ -0,0 +1,17 @@
+#
+# Makefile - Intel Precise Touch & Stylus device driver
+# Copyright (c) 2016, Intel Corporation.
+#
+
+obj-$(CONFIG_INTEL_IPTS)+= intel-ipts.o
+intel-ipts-objs += ipts-fw.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-params.o
+intel-ipts-objs += ipts-resource.o
+intel-ipts-objs += ipts-gfx.o
+intel-ipts-$(CONFIG_DEBUG_FS) += ipts-dbgfs.o
+
+obj-y += companion/
diff --git a/drivers/misc/ipts/companion/Kconfig b/drivers/misc/ipts/companion/Kconfig
new file mode 100644
index 000000000000..877a04494779
--- /dev/null
+++ b/drivers/misc/ipts/companion/Kconfig
@@ -0,0 +1,9 @@
+config INTEL_IPTS_SURFACE
+ tristate "IPTS companion driver for Microsoft Surface"
+ depends on INTEL_IPTS
+ depends on ACPI
+ help
+ IPTS companion driver for Microsoft Surface. This driver is responsible
+ for loading firmware using surface-specific hardware IDs.
+
+ If you have a Microsoft Surface using IPTS, select y or m here.
diff --git a/drivers/misc/ipts/companion/Makefile b/drivers/misc/ipts/companion/Makefile
new file mode 100644
index 000000000000..fb4d58935f01
--- /dev/null
+++ b/drivers/misc/ipts/companion/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_INTEL_IPTS_SURFACE)+= ipts-surface.o
diff --git a/drivers/misc/ipts/companion/ipts-surface.c b/drivers/misc/ipts/companion/ipts-surface.c
new file mode 100644
index 000000000000..4d6116dfa728
--- /dev/null
+++ b/drivers/misc/ipts/companion/ipts-surface.c
@@ -0,0 +1,82 @@
+#include <linux/acpi.h>
+#include <linux/firmware.h>
+#include <linux/intel_ipts_fw.h>
+#include <linux/intel_ipts_if.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define IPTS_SURFACE_FW_PATH_FMT "intel/ipts/%s/%s"
+
+int ipts_surface_request_firmware(const struct firmware **fw, const char *name,
+ struct device *device, void *data)
+{
+ char fw_path[MAX_IOCL_FILE_PATH_LEN];
+
+ if (data == NULL) {
+ return -ENOENT;
+ }
+
+ snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_SURFACE_FW_PATH_FMT,
+ (const char *)data, name);
+ return request_firmware(fw, fw_path, device);
+}
+
+static int ipts_surface_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
+
+ if (!adev) {
+ dev_err(&pdev->dev, "Unable to find ACPI info for device\n");
+ return -ENODEV;
+ }
+
+ ret = intel_ipts_add_fw_handler(&ipts_surface_request_firmware,
+ (void *)acpi_device_hid(adev));
+ if (ret) {
+ dev_info(&pdev->dev, "Adding IPTS firmware handler failed, "
+ "error: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ipts_surface_remove(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = intel_ipts_rm_fw_handler(&ipts_surface_request_firmware);
+ if (ret) {
+ dev_info(&pdev->dev, "Removing IPTS firmware handler failed, "
+ "error: %d\n", ret);
+ }
+
+ return 0;
+}
+
+static const struct acpi_device_id ipts_surface_acpi_match[] = {
+ { "MSHW0076", 0 }, /* Surface Book 1 / Surface Studio */
+ { "MSHW0078", 0 }, /* Surface Pro 4 */
+ { "MSHW0079", 0 }, /* Surface Laptop 1 / 2 */
+ { "MSHW0101", 0 }, /* Surface Book 2 15" */
+ { "MSHW0102", 0 }, /* Surface Pro 2017 / 6 */
+ { "MSHW0103", 0 }, /* unknown, but firmware exists */
+ { "MSHW0137", 0 }, /* Surface Book 2 */
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, ipts_surface_acpi_match);
+
+static struct platform_driver ipts_surface_driver = {
+ .probe = ipts_surface_probe,
+ .remove = ipts_surface_remove,
+ .driver = {
+ .name = "ipts_surface",
+ .acpi_match_table = ACPI_PTR(ipts_surface_acpi_match),
+ },
+};
+module_platform_driver(ipts_surface_driver);
+
+MODULE_AUTHOR("Dorian Stoll <dorian.stoll@tmsp.io>");
+MODULE_DESCRIPTION("IPTS companion driver for Microsoft Surface");
+MODULE_LICENSE("GPL v2");
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
@ -1911,6 +2043,143 @@ index 000000000000..7581b21f81e0
+ ipts_dbgfs_deregister(ipts);
+ return -ENODEV;
+}
diff --git a/drivers/misc/ipts/ipts-fw.c b/drivers/misc/ipts/ipts-fw.c
new file mode 100644
index 000000000000..82e6e44c9908
--- /dev/null
+++ b/drivers/misc/ipts/ipts-fw.c
@@ -0,0 +1,113 @@
+#include <linux/firmware.h>
+#include <linux/intel_ipts_fw.h>
+#include <linux/intel_ipts_if.h>
+#include <linux/mutex.h>
+
+#include "ipts.h"
+#include "ipts-fw.h"
+#include "ipts-params.h"
+
+#define IPTS_GENERIC_FW_PATH_FMT "intel/ipts/%s"
+
+/*
+ * This function pointer allows a companion driver to register a custom logic
+ * for loading firmware files. This can be used to detect devices that can
+ * be used for IPTS versioning, but that are not connected over the MEI bus,
+ * and cannot be detected by the ME driver.
+ */
+IPTS_FW_HANDLER(ipts_fw_handler);
+DEFINE_MUTEX(ipts_fw_handler_lock);
+void *ipts_fw_handler_data = NULL;
+
+bool ipts_fw_handler_available(void)
+{
+ bool ret;
+ mutex_lock(&ipts_fw_handler_lock);
+
+ ret = ipts_fw_handler != NULL;
+
+ mutex_unlock(&ipts_fw_handler_lock);
+ return ret;
+}
+
+int intel_ipts_add_fw_handler(IPTS_FW_HANDLER(handler), void *data)
+{
+ int ret = 0;
+ mutex_lock(&ipts_fw_handler_lock);
+
+ if (ipts_fw_handler != NULL) {
+ ret = -EBUSY;
+ goto ipts_add_fw_handler_return;
+ }
+
+ ipts_fw_handler = handler;
+ ipts_fw_handler_data = data;
+
+ipts_add_fw_handler_return:
+
+ mutex_unlock(&ipts_fw_handler_lock);
+ return ret;
+}
+EXPORT_SYMBOL(intel_ipts_add_fw_handler);
+
+int intel_ipts_rm_fw_handler(IPTS_FW_HANDLER(handler))
+{
+ int ret = 0;
+ mutex_lock(&ipts_fw_handler_lock);
+
+ if (ipts_fw_handler == NULL) {
+ ret = 0;
+ goto ipts_rm_fw_handler_return;
+ }
+
+ if (*handler != *ipts_fw_handler) {
+ ret = -EPERM;
+ goto ipts_rm_fw_handler_return;
+ }
+
+ ipts_fw_handler = NULL;
+ ipts_fw_handler_data = NULL;
+
+ipts_rm_fw_handler_return:
+
+ mutex_unlock(&ipts_fw_handler_lock);
+ return ret;
+}
+EXPORT_SYMBOL(intel_ipts_rm_fw_handler);
+
+int ipts_request_firmware(const struct firmware **fw, const char *name,
+ struct device *device)
+{
+ int ret = 0;
+ char fw_path[MAX_IOCL_FILE_PATH_LEN];
+ mutex_lock(&ipts_fw_handler_lock);
+
+ // Check if a firmware handler was registered. If not, skip
+ // forward and try to load the firmware from the legacy path
+ if (ipts_fw_handler == NULL || ipts_modparams.ignore_companion) {
+ goto ipts_request_firmware_fallback;
+ }
+
+ ret = (*ipts_fw_handler)(fw, name, device, ipts_fw_handler_data);
+ if (!ret) {
+ goto ipts_request_firmware_return;
+ }
+
+ipts_request_firmware_fallback:
+
+ // If fallback loading for firmware was disabled, abort.
+ // Return -ENOENT as no firmware file was found.
+ if (ipts_modparams.ignore_fw_fallback) {
+ ret = -ENOENT;
+ goto ipts_request_firmware_return;
+ }
+
+ // No firmware was found by the companion driver, try the generic path now.
+ snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_GENERIC_FW_PATH_FMT, name);
+ ret = request_firmware(fw, fw_path, device);
+
+ipts_request_firmware_return:
+
+ mutex_unlock(&ipts_fw_handler_lock);
+ return ret;
+}
diff --git a/drivers/misc/ipts/ipts-fw.h b/drivers/misc/ipts/ipts-fw.h
new file mode 100644
index 000000000000..4c1c9a0dd77f
--- /dev/null
+++ b/drivers/misc/ipts/ipts-fw.h
@@ -0,0 +1,12 @@
+#ifndef _IPTS_FW_H_
+#define _IPTS_FW_H_
+
+#include <linux/firmware.h>
+
+#include "ipts.h"
+
+int ipts_request_firmware(const struct firmware **fw, const char *name,
+ struct device *device);
+bool ipts_fw_handler_available(void);
+
+#endif // _IPTS_FW_H_
diff --git a/drivers/misc/ipts/ipts-gfx.c b/drivers/misc/ipts/ipts-gfx.c
new file mode 100644
index 000000000000..4989a22227d2
@ -2134,10 +2403,10 @@ index 000000000000..03a5f3551ddf
+#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..84e3fb6c34be
index 000000000000..41c6508f1235
--- /dev/null
+++ b/drivers/misc/ipts/ipts-hid.c
@@ -0,0 +1,504 @@
@@ -0,0 +1,503 @@
+/*
+ * Intel Precise Touch & Stylus HID driver
+ *
@ -2160,16 +2429,15 @@ index 000000000000..84e3fb6c34be
+#include <linux/dmi.h>
+
+#include "ipts.h"
+#include "ipts-fw.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);
+#define HID_DESC_INTEL "intel_desc.bin"
+#define HID_DESC_VENDOR "vendor_desc.bin"
+
+typedef enum output_buffer_payload_type {
+ OUTPUT_BUFFER_PAYLOAD_ERROR = 0,
@ -2228,13 +2496,13 @@ index 000000000000..84e3fb6c34be
+ 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);
+ ret = ipts_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);
+ ret = ipts_request_firmware(&vendor_desc, vendor_desc_path, &ipts->cldev->dev);
+ if (ret) {
+ ipts_dbg(ipts, "error in reading HID Vendor Descriptor\n");
+ } else {
@ -2684,25 +2952,24 @@ index 000000000000..f1b22c912df7
+#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..86fd359d2eed
index 000000000000..5933b190cdaf
--- /dev/null
+++ b/drivers/misc/ipts/ipts-kernel.c
@@ -0,0 +1,1050 @@
@@ -0,0 +1,1042 @@
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+#include <linux/intel_ipts_fw.h>
+#include <linux/intel_ipts_if.h>
+
+#include "ipts.h"
+#include "ipts-fw.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;
@ -2784,10 +3051,7 @@ index 000000000000..86fd359d2eed
+#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_FW_CONFIG_FILE "ipts_fw_config.bin"
+
+#define IPTS_INPUT_ON ((u32)1 << IPTS_INPUT)
+#define IPTS_OUTPUT_ON ((u32)1 << IPTS_OUTPUT)
@ -2802,13 +3066,11 @@ index 000000000000..86fd359d2eed
+ 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);
+ ret = ipts_request_firmware(&fw, fw_name, &ipts->cldev->dev);
+ if (ret) {
+ ipts_err(ipts, "cannot read fw %s\n", fw_path);
+ ipts_err(ipts, "cannot read fw %s\n", fw_name);
+ return ret;
+ }
+
@ -3587,7 +3849,6 @@ index 000000000000..86fd359d2eed
+ 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));
@ -3603,10 +3864,9 @@ index 000000000000..86fd359d2eed
+ 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);
+ ret = ipts_request_firmware(&fw, fw_name, &ipts->cldev->dev);
+ if (ret) {
+ ipts_err(ipts, "cannot read fw %s\n", fw_path);
+ ipts_err(ipts, "cannot read fw %s\n", fw_name);
+ goto error_exit;
+ }
+
@ -3707,7 +3967,7 @@ index 000000000000..86fd359d2eed
+ return ret;
+ }
+
+ ret = request_firmware(&config_fw, config_fw_path, &ipts->cldev->dev);
+ ret = ipts_request_firmware(&config_fw, config_fw_path, &ipts->cldev->dev);
+ if (ret) {
+ ipts_err(ipts, "request firmware error : %d\n", ret);
+ goto close_gpu;
@ -4360,10 +4620,10 @@ index 000000000000..8ca146800a47
+#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..199e49cb8d70
index 000000000000..6fbe257bc7cc
--- /dev/null
+++ b/drivers/misc/ipts/ipts-mei.c
@@ -0,0 +1,282 @@
@@ -0,0 +1,290 @@
+/*
+ * MEI client driver for Intel Precise Touch and Stylus
+ *
@ -4388,7 +4648,9 @@ index 000000000000..199e49cb8d70
+#include <linux/intel_ipts_if.h>
+
+#include "ipts.h"
+#include "ipts-fw.h"
+#include "ipts-hid.h"
+#include "ipts-params.h"
+#include "ipts-msg-handler.h"
+#include "ipts-mei-msgs.h"
+#include "ipts-binary-spec.h"
@ -4540,6 +4802,12 @@ index 000000000000..199e49cb8d70
+ int ret = 0;
+ ipts_info_t *ipts = NULL;
+
+ // Check if a companion driver for firmware loading was registered
+ // If not, defer probing until it was properly registere
+ if (!ipts_fw_handler_available() && !ipts_modparams.ignore_companion) {
+ return -EPROBE_DEFER;
+ }
+
+ pr_info("probing Intel Precise Touch & Stylus\n");
+
+ // setup the DMA BIT mask, the system will choose the best possible
@ -5128,6 +5396,45 @@ index 000000000000..f37d9ad9af8c
+int ipts_restart(ipts_info_t *ipts);
+
+#endif /* _IPTS_MSG_HANDLER_H */
diff --git a/drivers/misc/ipts/ipts-params.c b/drivers/misc/ipts/ipts-params.c
new file mode 100644
index 000000000000..17374039a161
--- /dev/null
+++ b/drivers/misc/ipts/ipts-params.c
@@ -0,0 +1,14 @@
+#include <linux/moduleparam.h>
+
+#include "ipts-params.h"
+
+struct ipts_params ipts_modparams = {
+ .ignore_fw_fallback = false,
+ .ignore_companion = false,
+};
+
+module_param_named(ignore_fw_fallback, ipts_modparams.ignore_fw_fallback, bool, 0400);
+MODULE_PARM_DESC(ignore_fw_fallback, "Don't use the IPTS firmware fallback path");
+
+module_param_named(ignore_companion, ipts_modparams.ignore_companion, bool, 0400);
+MODULE_PARM_DESC(ignore_companion, "Don't use a companion driver to load firmware");
diff --git a/drivers/misc/ipts/ipts-params.h b/drivers/misc/ipts/ipts-params.h
new file mode 100644
index 000000000000..d6f6faaef076
--- /dev/null
+++ b/drivers/misc/ipts/ipts-params.h
@@ -0,0 +1,13 @@
+#ifndef _IPTS_PARAMS_H_
+#define _IPTS_PARAMS_H_
+
+#include <linux/types.h>
+
+struct ipts_params {
+ bool ignore_fw_fallback;
+ bool ignore_companion;
+};
+
+extern struct ipts_params ipts_modparams;
+
+#endif // _IPTS_PARAMS_H_
diff --git a/drivers/misc/ipts/ipts-resource.c b/drivers/misc/ipts/ipts-resource.c
new file mode 100644
index 000000000000..47607ef7c461
@ -6418,6 +6725,26 @@ index e41f9e0a3fdf..e61be367d7e4 100644
{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_PCH12_CFG)},
diff --git a/include/linux/intel_ipts_fw.h b/include/linux/intel_ipts_fw.h
new file mode 100644
index 000000000000..adbfd29459a2
--- /dev/null
+++ b/include/linux/intel_ipts_fw.h
@@ -0,0 +1,14 @@
+#ifndef _INTEL_IPTS_FW_H_
+#define _INTEL_IPTS_FW_H_
+
+#include <linux/firmware.h>
+
+#define MAX_IOCL_FILE_NAME_LEN 80
+#define MAX_IOCL_FILE_PATH_LEN 256
+#define IPTS_FW_HANDLER(name) int(*name)(const struct firmware **, \
+ const char *, struct device *, void *)
+
+int intel_ipts_add_fw_handler(IPTS_FW_HANDLER(handler), void *data);
+int intel_ipts_rm_fw_handler(IPTS_FW_HANDLER(handler));
+
+#endif // _INTEL_IPTS_FW_H_
diff --git a/include/linux/intel_ipts_if.h b/include/linux/intel_ipts_if.h
new file mode 100644
index 000000000000..bad44fb4f233
@ -6501,5 +6828,5 @@ index 000000000000..bad44fb4f233
+
+#endif // INTEL_IPTS_IF_H
--
2.23.0
2.21.0

View file

@ -1,4 +1,4 @@
From 36650ae8bf4456b65601e46b23a3e1595009934e Mon Sep 17 00:00:00 2001
From b67b956e393fffdecb0c0e8588536093ec177757 Mon Sep 17 00:00:00 2001
From: kitakar5525 <34676735+kitakar5525@users.noreply.github.com>
Date: Tue, 10 Sep 2019 21:54:42 +0900
Subject: [PATCH 05/12] ipts
@ -24,20 +24,27 @@ Subject: [PATCH 05/12] ipts
drivers/hid/hid-multitouch.c | 22 +-
drivers/misc/Kconfig | 1 +
drivers/misc/Makefile | 1 +
drivers/misc/ipts/Kconfig | 9 +
drivers/misc/ipts/Makefile | 13 +
drivers/misc/ipts/Kconfig | 11 +
drivers/misc/ipts/Makefile | 17 +
drivers/misc/ipts/companion/Kconfig | 9 +
drivers/misc/ipts/companion/Makefile | 1 +
drivers/misc/ipts/companion/ipts-surface.c | 82 ++
drivers/misc/ipts/ipts-binary-spec.h | 118 +++
drivers/misc/ipts/ipts-dbgfs.c | 364 +++++++
drivers/misc/ipts/ipts-fw.c | 113 ++
drivers/misc/ipts/ipts-fw.h | 12 +
drivers/misc/ipts/ipts-gfx.c | 185 ++++
drivers/misc/ipts/ipts-gfx.h | 24 +
drivers/misc/ipts/ipts-hid.c | 504 +++++++++
drivers/misc/ipts/ipts-hid.c | 503 +++++++++
drivers/misc/ipts/ipts-hid.h | 34 +
drivers/misc/ipts/ipts-kernel.c | 1050 +++++++++++++++++++
drivers/misc/ipts/ipts-kernel.c | 1042 +++++++++++++++++++
drivers/misc/ipts/ipts-kernel.h | 23 +
drivers/misc/ipts/ipts-mei-msgs.h | 585 +++++++++++
drivers/misc/ipts/ipts-mei.c | 282 +++++
drivers/misc/ipts/ipts-mei.c | 290 ++++++
drivers/misc/ipts/ipts-msg-handler.c | 437 ++++++++
drivers/misc/ipts/ipts-msg-handler.h | 33 +
drivers/misc/ipts/ipts-params.c | 14 +
drivers/misc/ipts/ipts-params.h | 13 +
drivers/misc/ipts/ipts-resource.c | 277 +++++
drivers/misc/ipts/ipts-resource.h | 30 +
drivers/misc/ipts/ipts-sensor-regs.h | 700 +++++++++++++
@ -45,14 +52,20 @@ Subject: [PATCH 05/12] ipts
drivers/misc/ipts/ipts.h | 200 ++++
drivers/misc/mei/hw-me-regs.h | 1 +
drivers/misc/mei/pci-me.c | 1 +
include/linux/intel_ipts_fw.h | 14 +
include/linux/intel_ipts_if.h | 76 ++
42 files changed, 5889 insertions(+), 26 deletions(-)
50 files changed, 6152 insertions(+), 26 deletions(-)
create mode 100644 drivers/gpu/drm/i915/intel_ipts.c
create mode 100644 drivers/gpu/drm/i915/intel_ipts.h
create mode 100644 drivers/misc/ipts/Kconfig
create mode 100644 drivers/misc/ipts/Makefile
create mode 100644 drivers/misc/ipts/companion/Kconfig
create mode 100644 drivers/misc/ipts/companion/Makefile
create mode 100644 drivers/misc/ipts/companion/ipts-surface.c
create mode 100644 drivers/misc/ipts/ipts-binary-spec.h
create mode 100644 drivers/misc/ipts/ipts-dbgfs.c
create mode 100644 drivers/misc/ipts/ipts-fw.c
create mode 100644 drivers/misc/ipts/ipts-fw.h
create mode 100644 drivers/misc/ipts/ipts-gfx.c
create mode 100644 drivers/misc/ipts/ipts-gfx.h
create mode 100644 drivers/misc/ipts/ipts-hid.c
@ -63,11 +76,14 @@ Subject: [PATCH 05/12] ipts
create mode 100644 drivers/misc/ipts/ipts-mei.c
create mode 100644 drivers/misc/ipts/ipts-msg-handler.c
create mode 100644 drivers/misc/ipts/ipts-msg-handler.h
create mode 100644 drivers/misc/ipts/ipts-params.c
create mode 100644 drivers/misc/ipts/ipts-params.h
create mode 100644 drivers/misc/ipts/ipts-resource.c
create mode 100644 drivers/misc/ipts/ipts-resource.h
create mode 100644 drivers/misc/ipts/ipts-sensor-regs.h
create mode 100644 drivers/misc/ipts/ipts-state.h
create mode 100644 drivers/misc/ipts/ipts.h
create mode 100644 include/linux/intel_ipts_fw.h
create mode 100644 include/linux/intel_ipts_if.h
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
@ -1387,10 +1403,10 @@ index b9affcdaa3d6..e681e345a9ed 100644
obj-$(CONFIG_SRAM) += sram.o
diff --git a/drivers/misc/ipts/Kconfig b/drivers/misc/ipts/Kconfig
new file mode 100644
index 000000000000..360ed3861b82
index 000000000000..a24c4daaed42
--- /dev/null
+++ b/drivers/misc/ipts/Kconfig
@@ -0,0 +1,9 @@
@@ -0,0 +1,11 @@
+config INTEL_IPTS
+ tristate "Intel Precise Touch & Stylus"
+ select INTEL_MEI
@ -1400,25 +1416,141 @@ index 000000000000..360ed3861b82
+ Supported SoCs:
+ Intel Skylake
+ Intel Kabylake
+
+source "drivers/misc/ipts/companion/Kconfig"
diff --git a/drivers/misc/ipts/Makefile b/drivers/misc/ipts/Makefile
new file mode 100644
index 000000000000..1783e9cf13c9
index 000000000000..78bb61933387
--- /dev/null
+++ b/drivers/misc/ipts/Makefile
@@ -0,0 +1,13 @@
@@ -0,0 +1,17 @@
+#
+# Makefile - Intel Precise Touch & Stylus device driver
+# Copyright (c) 2016, Intel Corporation.
+#
+
+obj-$(CONFIG_INTEL_IPTS)+= intel-ipts.o
+intel-ipts-objs += ipts-fw.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-params.o
+intel-ipts-objs += ipts-resource.o
+intel-ipts-objs += ipts-gfx.o
+intel-ipts-$(CONFIG_DEBUG_FS) += ipts-dbgfs.o
+
+obj-y += companion/
diff --git a/drivers/misc/ipts/companion/Kconfig b/drivers/misc/ipts/companion/Kconfig
new file mode 100644
index 000000000000..877a04494779
--- /dev/null
+++ b/drivers/misc/ipts/companion/Kconfig
@@ -0,0 +1,9 @@
+config INTEL_IPTS_SURFACE
+ tristate "IPTS companion driver for Microsoft Surface"
+ depends on INTEL_IPTS
+ depends on ACPI
+ help
+ IPTS companion driver for Microsoft Surface. This driver is responsible
+ for loading firmware using surface-specific hardware IDs.
+
+ If you have a Microsoft Surface using IPTS, select y or m here.
diff --git a/drivers/misc/ipts/companion/Makefile b/drivers/misc/ipts/companion/Makefile
new file mode 100644
index 000000000000..fb4d58935f01
--- /dev/null
+++ b/drivers/misc/ipts/companion/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_INTEL_IPTS_SURFACE)+= ipts-surface.o
diff --git a/drivers/misc/ipts/companion/ipts-surface.c b/drivers/misc/ipts/companion/ipts-surface.c
new file mode 100644
index 000000000000..4d6116dfa728
--- /dev/null
+++ b/drivers/misc/ipts/companion/ipts-surface.c
@@ -0,0 +1,82 @@
+#include <linux/acpi.h>
+#include <linux/firmware.h>
+#include <linux/intel_ipts_fw.h>
+#include <linux/intel_ipts_if.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define IPTS_SURFACE_FW_PATH_FMT "intel/ipts/%s/%s"
+
+int ipts_surface_request_firmware(const struct firmware **fw, const char *name,
+ struct device *device, void *data)
+{
+ char fw_path[MAX_IOCL_FILE_PATH_LEN];
+
+ if (data == NULL) {
+ return -ENOENT;
+ }
+
+ snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_SURFACE_FW_PATH_FMT,
+ (const char *)data, name);
+ return request_firmware(fw, fw_path, device);
+}
+
+static int ipts_surface_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
+
+ if (!adev) {
+ dev_err(&pdev->dev, "Unable to find ACPI info for device\n");
+ return -ENODEV;
+ }
+
+ ret = intel_ipts_add_fw_handler(&ipts_surface_request_firmware,
+ (void *)acpi_device_hid(adev));
+ if (ret) {
+ dev_info(&pdev->dev, "Adding IPTS firmware handler failed, "
+ "error: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ipts_surface_remove(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = intel_ipts_rm_fw_handler(&ipts_surface_request_firmware);
+ if (ret) {
+ dev_info(&pdev->dev, "Removing IPTS firmware handler failed, "
+ "error: %d\n", ret);
+ }
+
+ return 0;
+}
+
+static const struct acpi_device_id ipts_surface_acpi_match[] = {
+ { "MSHW0076", 0 }, /* Surface Book 1 / Surface Studio */
+ { "MSHW0078", 0 }, /* Surface Pro 4 */
+ { "MSHW0079", 0 }, /* Surface Laptop 1 / 2 */
+ { "MSHW0101", 0 }, /* Surface Book 2 15" */
+ { "MSHW0102", 0 }, /* Surface Pro 2017 / 6 */
+ { "MSHW0103", 0 }, /* unknown, but firmware exists */
+ { "MSHW0137", 0 }, /* Surface Book 2 */
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, ipts_surface_acpi_match);
+
+static struct platform_driver ipts_surface_driver = {
+ .probe = ipts_surface_probe,
+ .remove = ipts_surface_remove,
+ .driver = {
+ .name = "ipts_surface",
+ .acpi_match_table = ACPI_PTR(ipts_surface_acpi_match),
+ },
+};
+module_platform_driver(ipts_surface_driver);
+
+MODULE_AUTHOR("Dorian Stoll <dorian.stoll@tmsp.io>");
+MODULE_DESCRIPTION("IPTS companion driver for Microsoft Surface");
+MODULE_LICENSE("GPL v2");
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
@ -1913,6 +2045,143 @@ index 000000000000..7581b21f81e0
+ ipts_dbgfs_deregister(ipts);
+ return -ENODEV;
+}
diff --git a/drivers/misc/ipts/ipts-fw.c b/drivers/misc/ipts/ipts-fw.c
new file mode 100644
index 000000000000..82e6e44c9908
--- /dev/null
+++ b/drivers/misc/ipts/ipts-fw.c
@@ -0,0 +1,113 @@
+#include <linux/firmware.h>
+#include <linux/intel_ipts_fw.h>
+#include <linux/intel_ipts_if.h>
+#include <linux/mutex.h>
+
+#include "ipts.h"
+#include "ipts-fw.h"
+#include "ipts-params.h"
+
+#define IPTS_GENERIC_FW_PATH_FMT "intel/ipts/%s"
+
+/*
+ * This function pointer allows a companion driver to register a custom logic
+ * for loading firmware files. This can be used to detect devices that can
+ * be used for IPTS versioning, but that are not connected over the MEI bus,
+ * and cannot be detected by the ME driver.
+ */
+IPTS_FW_HANDLER(ipts_fw_handler);
+DEFINE_MUTEX(ipts_fw_handler_lock);
+void *ipts_fw_handler_data = NULL;
+
+bool ipts_fw_handler_available(void)
+{
+ bool ret;
+ mutex_lock(&ipts_fw_handler_lock);
+
+ ret = ipts_fw_handler != NULL;
+
+ mutex_unlock(&ipts_fw_handler_lock);
+ return ret;
+}
+
+int intel_ipts_add_fw_handler(IPTS_FW_HANDLER(handler), void *data)
+{
+ int ret = 0;
+ mutex_lock(&ipts_fw_handler_lock);
+
+ if (ipts_fw_handler != NULL) {
+ ret = -EBUSY;
+ goto ipts_add_fw_handler_return;
+ }
+
+ ipts_fw_handler = handler;
+ ipts_fw_handler_data = data;
+
+ipts_add_fw_handler_return:
+
+ mutex_unlock(&ipts_fw_handler_lock);
+ return ret;
+}
+EXPORT_SYMBOL(intel_ipts_add_fw_handler);
+
+int intel_ipts_rm_fw_handler(IPTS_FW_HANDLER(handler))
+{
+ int ret = 0;
+ mutex_lock(&ipts_fw_handler_lock);
+
+ if (ipts_fw_handler == NULL) {
+ ret = 0;
+ goto ipts_rm_fw_handler_return;
+ }
+
+ if (*handler != *ipts_fw_handler) {
+ ret = -EPERM;
+ goto ipts_rm_fw_handler_return;
+ }
+
+ ipts_fw_handler = NULL;
+ ipts_fw_handler_data = NULL;
+
+ipts_rm_fw_handler_return:
+
+ mutex_unlock(&ipts_fw_handler_lock);
+ return ret;
+}
+EXPORT_SYMBOL(intel_ipts_rm_fw_handler);
+
+int ipts_request_firmware(const struct firmware **fw, const char *name,
+ struct device *device)
+{
+ int ret = 0;
+ char fw_path[MAX_IOCL_FILE_PATH_LEN];
+ mutex_lock(&ipts_fw_handler_lock);
+
+ // Check if a firmware handler was registered. If not, skip
+ // forward and try to load the firmware from the legacy path
+ if (ipts_fw_handler == NULL || ipts_modparams.ignore_companion) {
+ goto ipts_request_firmware_fallback;
+ }
+
+ ret = (*ipts_fw_handler)(fw, name, device, ipts_fw_handler_data);
+ if (!ret) {
+ goto ipts_request_firmware_return;
+ }
+
+ipts_request_firmware_fallback:
+
+ // If fallback loading for firmware was disabled, abort.
+ // Return -ENOENT as no firmware file was found.
+ if (ipts_modparams.ignore_fw_fallback) {
+ ret = -ENOENT;
+ goto ipts_request_firmware_return;
+ }
+
+ // No firmware was found by the companion driver, try the generic path now.
+ snprintf(fw_path, MAX_IOCL_FILE_PATH_LEN, IPTS_GENERIC_FW_PATH_FMT, name);
+ ret = request_firmware(fw, fw_path, device);
+
+ipts_request_firmware_return:
+
+ mutex_unlock(&ipts_fw_handler_lock);
+ return ret;
+}
diff --git a/drivers/misc/ipts/ipts-fw.h b/drivers/misc/ipts/ipts-fw.h
new file mode 100644
index 000000000000..4c1c9a0dd77f
--- /dev/null
+++ b/drivers/misc/ipts/ipts-fw.h
@@ -0,0 +1,12 @@
+#ifndef _IPTS_FW_H_
+#define _IPTS_FW_H_
+
+#include <linux/firmware.h>
+
+#include "ipts.h"
+
+int ipts_request_firmware(const struct firmware **fw, const char *name,
+ struct device *device);
+bool ipts_fw_handler_available(void);
+
+#endif // _IPTS_FW_H_
diff --git a/drivers/misc/ipts/ipts-gfx.c b/drivers/misc/ipts/ipts-gfx.c
new file mode 100644
index 000000000000..4989a22227d2
@ -2136,10 +2405,10 @@ index 000000000000..03a5f3551ddf
+#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..84e3fb6c34be
index 000000000000..41c6508f1235
--- /dev/null
+++ b/drivers/misc/ipts/ipts-hid.c
@@ -0,0 +1,504 @@
@@ -0,0 +1,503 @@
+/*
+ * Intel Precise Touch & Stylus HID driver
+ *
@ -2162,16 +2431,15 @@ index 000000000000..84e3fb6c34be
+#include <linux/dmi.h>
+
+#include "ipts.h"
+#include "ipts-fw.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);
+#define HID_DESC_INTEL "intel_desc.bin"
+#define HID_DESC_VENDOR "vendor_desc.bin"
+
+typedef enum output_buffer_payload_type {
+ OUTPUT_BUFFER_PAYLOAD_ERROR = 0,
@ -2230,13 +2498,13 @@ index 000000000000..84e3fb6c34be
+ 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);
+ ret = ipts_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);
+ ret = ipts_request_firmware(&vendor_desc, vendor_desc_path, &ipts->cldev->dev);
+ if (ret) {
+ ipts_dbg(ipts, "error in reading HID Vendor Descriptor\n");
+ } else {
@ -2686,25 +2954,24 @@ index 000000000000..f1b22c912df7
+#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..86fd359d2eed
index 000000000000..5933b190cdaf
--- /dev/null
+++ b/drivers/misc/ipts/ipts-kernel.c
@@ -0,0 +1,1050 @@
@@ -0,0 +1,1042 @@
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/vmalloc.h>
+#include <linux/intel_ipts_fw.h>
+#include <linux/intel_ipts_if.h>
+
+#include "ipts.h"
+#include "ipts-fw.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;
@ -2786,10 +3053,7 @@ index 000000000000..86fd359d2eed
+#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_FW_CONFIG_FILE "ipts_fw_config.bin"
+
+#define IPTS_INPUT_ON ((u32)1 << IPTS_INPUT)
+#define IPTS_OUTPUT_ON ((u32)1 << IPTS_OUTPUT)
@ -2804,13 +3068,11 @@ index 000000000000..86fd359d2eed
+ 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);
+ ret = ipts_request_firmware(&fw, fw_name, &ipts->cldev->dev);
+ if (ret) {
+ ipts_err(ipts, "cannot read fw %s\n", fw_path);
+ ipts_err(ipts, "cannot read fw %s\n", fw_name);
+ return ret;
+ }
+
@ -3589,7 +3851,6 @@ index 000000000000..86fd359d2eed
+ 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));
@ -3605,10 +3866,9 @@ index 000000000000..86fd359d2eed
+ 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);
+ ret = ipts_request_firmware(&fw, fw_name, &ipts->cldev->dev);
+ if (ret) {
+ ipts_err(ipts, "cannot read fw %s\n", fw_path);
+ ipts_err(ipts, "cannot read fw %s\n", fw_name);
+ goto error_exit;
+ }
+
@ -3709,7 +3969,7 @@ index 000000000000..86fd359d2eed
+ return ret;
+ }
+
+ ret = request_firmware(&config_fw, config_fw_path, &ipts->cldev->dev);
+ ret = ipts_request_firmware(&config_fw, config_fw_path, &ipts->cldev->dev);
+ if (ret) {
+ ipts_err(ipts, "request firmware error : %d\n", ret);
+ goto close_gpu;
@ -4362,10 +4622,10 @@ index 000000000000..8ca146800a47
+#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..199e49cb8d70
index 000000000000..6fbe257bc7cc
--- /dev/null
+++ b/drivers/misc/ipts/ipts-mei.c
@@ -0,0 +1,282 @@
@@ -0,0 +1,290 @@
+/*
+ * MEI client driver for Intel Precise Touch and Stylus
+ *
@ -4390,7 +4650,9 @@ index 000000000000..199e49cb8d70
+#include <linux/intel_ipts_if.h>
+
+#include "ipts.h"
+#include "ipts-fw.h"
+#include "ipts-hid.h"
+#include "ipts-params.h"
+#include "ipts-msg-handler.h"
+#include "ipts-mei-msgs.h"
+#include "ipts-binary-spec.h"
@ -4542,6 +4804,12 @@ index 000000000000..199e49cb8d70
+ int ret = 0;
+ ipts_info_t *ipts = NULL;
+
+ // Check if a companion driver for firmware loading was registered
+ // If not, defer probing until it was properly registere
+ if (!ipts_fw_handler_available() && !ipts_modparams.ignore_companion) {
+ return -EPROBE_DEFER;
+ }
+
+ pr_info("probing Intel Precise Touch & Stylus\n");
+
+ // setup the DMA BIT mask, the system will choose the best possible
@ -5130,6 +5398,45 @@ index 000000000000..f37d9ad9af8c
+int ipts_restart(ipts_info_t *ipts);
+
+#endif /* _IPTS_MSG_HANDLER_H */
diff --git a/drivers/misc/ipts/ipts-params.c b/drivers/misc/ipts/ipts-params.c
new file mode 100644
index 000000000000..17374039a161
--- /dev/null
+++ b/drivers/misc/ipts/ipts-params.c
@@ -0,0 +1,14 @@
+#include <linux/moduleparam.h>
+
+#include "ipts-params.h"
+
+struct ipts_params ipts_modparams = {
+ .ignore_fw_fallback = false,
+ .ignore_companion = false,
+};
+
+module_param_named(ignore_fw_fallback, ipts_modparams.ignore_fw_fallback, bool, 0400);
+MODULE_PARM_DESC(ignore_fw_fallback, "Don't use the IPTS firmware fallback path");
+
+module_param_named(ignore_companion, ipts_modparams.ignore_companion, bool, 0400);
+MODULE_PARM_DESC(ignore_companion, "Don't use a companion driver to load firmware");
diff --git a/drivers/misc/ipts/ipts-params.h b/drivers/misc/ipts/ipts-params.h
new file mode 100644
index 000000000000..d6f6faaef076
--- /dev/null
+++ b/drivers/misc/ipts/ipts-params.h
@@ -0,0 +1,13 @@
+#ifndef _IPTS_PARAMS_H_
+#define _IPTS_PARAMS_H_
+
+#include <linux/types.h>
+
+struct ipts_params {
+ bool ignore_fw_fallback;
+ bool ignore_companion;
+};
+
+extern struct ipts_params ipts_modparams;
+
+#endif // _IPTS_PARAMS_H_
diff --git a/drivers/misc/ipts/ipts-resource.c b/drivers/misc/ipts/ipts-resource.c
new file mode 100644
index 000000000000..47607ef7c461
@ -6420,6 +6727,26 @@ index 541538eff8b1..49ab69d7a273 100644
{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_PCH12_CFG)},
diff --git a/include/linux/intel_ipts_fw.h b/include/linux/intel_ipts_fw.h
new file mode 100644
index 000000000000..adbfd29459a2
--- /dev/null
+++ b/include/linux/intel_ipts_fw.h
@@ -0,0 +1,14 @@
+#ifndef _INTEL_IPTS_FW_H_
+#define _INTEL_IPTS_FW_H_
+
+#include <linux/firmware.h>
+
+#define MAX_IOCL_FILE_NAME_LEN 80
+#define MAX_IOCL_FILE_PATH_LEN 256
+#define IPTS_FW_HANDLER(name) int(*name)(const struct firmware **, \
+ const char *, struct device *, void *)
+
+int intel_ipts_add_fw_handler(IPTS_FW_HANDLER(handler), void *data);
+int intel_ipts_rm_fw_handler(IPTS_FW_HANDLER(handler));
+
+#endif // _INTEL_IPTS_FW_H_
diff --git a/include/linux/intel_ipts_if.h b/include/linux/intel_ipts_if.h
new file mode 100644
index 000000000000..bad44fb4f233
@ -6503,5 +6830,5 @@ index 000000000000..bad44fb4f233
+
+#endif // INTEL_IPTS_IF_H
--
2.23.0
2.21.0