summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/intel/hid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/intel/hid.c')
-rw-r--r--drivers/platform/x86/intel/hid.c97
1 files changed, 65 insertions, 32 deletions
diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c
index b6c06b37862e..560cc063198e 100644
--- a/drivers/platform/x86/intel/hid.c
+++ b/drivers/platform/x86/intel/hid.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/string_choices.h>
#include <linux/suspend.h>
#include "../dual_accel_detect.h"
@@ -38,18 +39,24 @@ MODULE_PARM_DESC(enable_sw_tablet_mode,
/* When NOT in tablet mode, VGBS returns with the flag 0x40 */
#define TABLET_MODE_FLAG BIT(6)
+MODULE_DESCRIPTION("Intel HID Event hotkey driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex Hung");
static const struct acpi_device_id intel_hid_ids[] = {
- {"INT33D5", 0},
- {"INTC1051", 0},
- {"INTC1054", 0},
- {"INTC1070", 0},
- {"INTC1076", 0},
- {"INTC1077", 0},
- {"INTC1078", 0},
- {"", 0},
+ { "INT33D5" },
+ { "INTC1051" },
+ { "INTC1054" },
+ { "INTC1070" },
+ { "INTC1076" },
+ { "INTC1077" },
+ { "INTC1078" },
+ { "INTC107B" },
+ { "INTC10CB" },
+ { "INTC10CC" },
+ { "INTC10F1" },
+ { "INTC10F2" },
+ { }
};
MODULE_DEVICE_TABLE(acpi, intel_hid_ids);
@@ -115,6 +122,13 @@ static const struct dmi_system_id button_array_table[] = {
},
},
{
+ .ident = "Lenovo ThinkPad X1 Tablet Gen 1",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X12 Detachable Gen 1"),
+ },
+ },
+ {
.ident = "Lenovo ThinkPad X1 Tablet Gen 2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -128,6 +142,13 @@ static const struct dmi_system_id button_array_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 3"),
},
},
+ {
+ .ident = "Microsoft Surface Go 4",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go 4"),
+ },
+ },
{ }
};
@@ -150,6 +171,24 @@ static const struct dmi_system_id dmi_vgbs_allow_list[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go"),
},
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite Dragonfly G2 Notebook PC"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell Pro Rugged 10 Tablet RA00260"),
+ },
+ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell Pro Rugged 12 Tablet RA02260"),
+ },
+ },
{ }
};
@@ -322,10 +361,8 @@ static int intel_hid_set_enable(struct device *device, bool enable)
acpi_handle handle = ACPI_HANDLE(device);
/* Enable|disable features - power button is always enabled */
- if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN,
- enable)) {
- dev_warn(device, "failed to %sable hotkeys\n",
- enable ? "en" : "dis");
+ if (!intel_hid_execute_method(handle, INTEL_HID_DSM_HDSM_FN, enable)) {
+ dev_warn(device, "failed to %s hotkeys\n", str_enable_disable(enable));
return -EIO;
}
@@ -498,6 +535,7 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
struct platform_device *device = context;
struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
unsigned long long ev_index;
+ struct key_entry *ke;
int err;
/*
@@ -539,11 +577,15 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
if (event == 0xc0 || !priv->array)
return;
- if (!sparse_keymap_entry_from_scancode(priv->array, event)) {
+ ke = sparse_keymap_entry_from_scancode(priv->array, event);
+ if (!ke) {
dev_info(&device->dev, "unknown event 0x%x\n", event);
return;
}
+ if (ke->type == KE_IGNORE)
+ return;
+
wakeup:
pm_wakeup_hard_event(&device->dev);
@@ -620,7 +662,7 @@ static bool button_array_present(struct platform_device *device)
static int intel_hid_probe(struct platform_device *device)
{
acpi_handle handle = ACPI_HANDLE(&device->dev);
- unsigned long long mode;
+ unsigned long long mode, dummy;
struct intel_hid_priv *priv;
acpi_status status;
int err;
@@ -692,18 +734,15 @@ static int intel_hid_probe(struct platform_device *device)
if (err)
goto err_remove_notify;
- if (priv->array) {
- unsigned long long dummy;
-
- intel_button_array_enable(&device->dev, true);
+ intel_button_array_enable(&device->dev, true);
- /* Call button load method to enable HID power button */
- if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN,
- &dummy)) {
- dev_warn(&device->dev,
- "failed to enable HID power button\n");
- }
- }
+ /*
+ * Call button load method to enable HID power button
+ * Always do this since it activates events on some devices without
+ * a button array too.
+ */
+ if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN, &dummy))
+ dev_warn(&device->dev, "failed to enable HID power button\n");
device_init_wakeup(&device->dev, true);
/*
@@ -720,7 +759,7 @@ err_remove_notify:
return err;
}
-static int intel_hid_remove(struct platform_device *device)
+static void intel_hid_remove(struct platform_device *device)
{
acpi_handle handle = ACPI_HANDLE(&device->dev);
@@ -728,12 +767,6 @@ static int intel_hid_remove(struct platform_device *device)
acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler);
intel_hid_set_enable(&device->dev, false);
intel_button_array_enable(&device->dev, false);
-
- /*
- * Even if we failed to shut off the event stream, we can still
- * safely detach from the device.
- */
- return 0;
}
static struct platform_driver intel_hid_pl_driver = {