summaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/intel-vbtn.c
diff options
context:
space:
mode:
authorLinus Torvalds2018-02-07 00:30:52 +0100
committerLinus Torvalds2018-02-07 00:30:52 +0100
commitcbd7b8a76b79a2ff6112ef2e77031b694843b8a1 (patch)
tree41a7e9bae92abe001c36a094b1135f0b93375c31 /drivers/platform/x86/intel-vbtn.c
parentMerge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/l... (diff)
parentplatform/x86: mlx-platform: Fix an ERR_PTR vs NULL issue (diff)
downloadkernel-qcow2-linux-cbd7b8a76b79a2ff6112ef2e77031b694843b8a1.tar.gz
kernel-qcow2-linux-cbd7b8a76b79a2ff6112ef2e77031b694843b8a1.tar.xz
kernel-qcow2-linux-cbd7b8a76b79a2ff6112ef2e77031b694843b8a1.zip
Merge tag 'platform-drivers-x86-v4.16-1' of git://git.infradead.org/linux-platform-drivers-x86
Pull x86 platform-driver updates from Darren Hart: "New model support added for Dell, Ideapad, Acer, Asus, Thinkpad, and GPD laptops. Improvements to the common intel-vbtn driver, including tablet mode, rotate, and front button support. Intel CPU support added for Cannonlake and platform support for Dollar Cove power button. Overhaul of the mellanox platform driver, creating a new platform/mellanox directory for the newly multi-architecture regmap interface. Significant Intel PMC update with CannonLake support, Coffeelake update, CPUID enumeration, module support, new read64 API, refactoring and cleanups. Revert the apple-gmux iGP IO lock, addressing reported issues with non-binary drivers, leaving Nvidia binary driver users to comment out conflicting code. Miscellaneous fixes and cleanups" * tag 'platform-drivers-x86-v4.16-1' of git://git.infradead.org/linux-platform-drivers-x86: (81 commits) platform/x86: mlx-platform: Fix an ERR_PTR vs NULL issue platform/x86: intel_pmc_core: Special case for Coffeelake platform/x86: intel_pmc_core: Add CannonLake PCH support x86/cpu: Add Cannonlake to Intel family platform/x86: intel_pmc_core: Read base address from LPIT ACPI / LPIT: Export lpit_read_residency_count_address() platform/x86: intel-vbtn: Replace License by SDPX identifier platform/x86: intel-vbtn: Remove redundant inclusions platform/x86: intel-vbtn: Support tablet mode switch platform/x86: dell-laptop: Allocate buffer on heap rather than globally platform/x86: intel_pmc_core: Remove unused header file platform/x86: mlx-platform: Add hotplug device unregister to error path platform/x86: mlx-platform: fix module aliases platform/mellanox: mlxreg-hotplug: Add check for negative adapter number platform/x86: mlx-platform: Add IO access verification callbacks platform/x86: mlx-platform: Document pdev_hotplug field platform/x86: mlx-platform: Allow compilation for 32 bit arch platform/mellanox: mlxreg-hotplug: Enable building for ARM platform/mellanox: mlxreg-hotplug: Modify to use a regmap interface platform/mellanox: Group create/destroy with attribute functions ...
Diffstat (limited to 'drivers/platform/x86/intel-vbtn.c')
-rw-r--r--drivers/platform/x86/intel-vbtn.c65
1 files changed, 47 insertions, 18 deletions
diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c
index 58c5ff36523a..b703d6f5b099 100644
--- a/drivers/platform/x86/intel-vbtn.c
+++ b/drivers/platform/x86/intel-vbtn.c
@@ -1,30 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Intel Virtual Button driver for Windows 8.1+
*
* Copyright (C) 2016 AceLan Kao <acelan.kao@canonical.com>
* Copyright (C) 2016 Alex Hung <alex.hung@canonical.com>
- *
- * 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.
- *
*/
+#include <linux/acpi.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
#include <linux/platform_device.h>
-#include <linux/input/sparse-keymap.h>
-#include <linux/acpi.h>
#include <linux/suspend.h>
-#include <acpi/acpi_bus.h>
+
+/* When NOT in tablet mode, VGBS returns with the flag 0x40 */
+#define TABLET_MODE_FLAG 0x40
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AceLan Kao");
@@ -38,10 +29,16 @@ static const struct acpi_device_id intel_vbtn_ids[] = {
static const struct key_entry intel_vbtn_keymap[] = {
{ KE_KEY, 0xC0, { KEY_POWER } }, /* power key press */
{ KE_IGNORE, 0xC1, { KEY_POWER } }, /* power key release */
+ { KE_KEY, 0xC2, { KEY_LEFTMETA } }, /* 'Windows' key press */
+ { KE_KEY, 0xC3, { KEY_LEFTMETA } }, /* 'Windows' key release */
{ KE_KEY, 0xC4, { KEY_VOLUMEUP } }, /* volume-up key press */
{ KE_IGNORE, 0xC5, { KEY_VOLUMEUP } }, /* volume-up key release */
{ KE_KEY, 0xC6, { KEY_VOLUMEDOWN } }, /* volume-down key press */
{ KE_IGNORE, 0xC7, { KEY_VOLUMEDOWN } }, /* volume-down key release */
+ { KE_KEY, 0xC8, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key press */
+ { KE_KEY, 0xC9, { KEY_ROTATE_LOCK_TOGGLE } }, /* rotate-lock key release */
+ { KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */
+ { KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */
{ KE_END },
};
@@ -74,20 +71,35 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
{
struct platform_device *device = context;
struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev);
+ unsigned int val = !(event & 1); /* Even=press, Odd=release */
+ const struct key_entry *ke_rel;
+ bool autorelease;
if (priv->wakeup_mode) {
if (sparse_keymap_entry_from_scancode(priv->input_dev, event)) {
pm_wakeup_hard_event(&device->dev);
return;
}
- } else if (sparse_keymap_report_event(priv->input_dev, event, 1, true)) {
- return;
+ goto out_unknown;
}
+
+ /*
+ * Even press events are autorelease if there is no corresponding odd
+ * release event, or if the odd event is KE_IGNORE.
+ */
+ ke_rel = sparse_keymap_entry_from_scancode(priv->input_dev, event | 1);
+ autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);
+
+ if (sparse_keymap_report_event(priv->input_dev, event, val, autorelease))
+ return;
+
+out_unknown:
dev_dbg(&device->dev, "unknown event index 0x%x\n", event);
}
static int intel_vbtn_probe(struct platform_device *device)
{
+ struct acpi_buffer vgbs_output = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle = ACPI_HANDLE(&device->dev);
struct intel_vbtn_priv *priv;
acpi_status status;
@@ -110,6 +122,23 @@ static int intel_vbtn_probe(struct platform_device *device)
return err;
}
+ /*
+ * VGBS being present and returning something means we have
+ * a tablet mode switch.
+ */
+ status = acpi_evaluate_object(handle, "VGBS", NULL, &vgbs_output);
+ if (ACPI_SUCCESS(status)) {
+ union acpi_object *obj = vgbs_output.pointer;
+
+ if (obj && obj->type == ACPI_TYPE_INTEGER) {
+ int m = !(obj->integer.value & TABLET_MODE_FLAG);
+
+ input_report_switch(priv->input_dev, SW_TABLET_MODE, m);
+ }
+ }
+
+ kfree(vgbs_output.pointer);
+
status = acpi_install_notify_handler(handle,
ACPI_DEVICE_NOTIFY,
notify_handler,