From patchwork Wed Aug 3 02:31:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AceLan Kao X-Patchwork-Id: 655197 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 3s3xsF32gLz9t0t; Wed, 3 Aug 2016 12:31:29 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=TIO81+p6; dkim-atps=neutral Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1bUlxu-0003vE-Tp; Wed, 03 Aug 2016 02:31:26 +0000 Received: from mail-pa0-f67.google.com ([209.85.220.67]) by huckleberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1bUlxn-0003uH-5A for kernel-team@lists.ubuntu.com; Wed, 03 Aug 2016 02:31:19 +0000 Received: by mail-pa0-f67.google.com with SMTP id cf3so13016098pad.2 for ; Tue, 02 Aug 2016 19:31:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id:in-reply-to:references; bh=w08ayUAFZm4NepEx/LZ/PEJXSrPl92qCdDD331M+XIY=; b=TIO81+p6UcZ1Y9Up4vA0fNNV/LFkQ/VttyX3jPlVWSGLYlIAa/AdnD5wX19dOcyBrx y86IW+gX+o+LIpIihJrmGnUXx3aoWUsu0A2oJTz1y+LmnwJIoM3jZnZtWbkk7eNufqWw hyG4ZwaOOV/c7/evWBjMbfTBCxQEASyBAI3dK2IOFQVB0Xwj4V8vPQGOFacGr6JLtzn8 gYR0Y0hNbQuMGVjWtQyR8yC8RRRla90ZL/St+EHo8GpoKmWMx1svWBbo+2+//x1dq1mv pGKZ0G8jiY+4Q1OsXE42sk9pThnpsQjvqhy+oeSAXOEH9y3hWPneBSF6M6Y6jUTXwQXJ 2fVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:subject:date:message-id :in-reply-to:references; bh=w08ayUAFZm4NepEx/LZ/PEJXSrPl92qCdDD331M+XIY=; b=a/AZQ12GA100x8kn9Mw5hCe0MJejH17V6afZ9AmsRviMDC1ZbLX4Sgqa4IqpZ2EKzP wbNsJ5grb7dYFAEit1EYFXdONiKCNZ7uR6Wp6BY3PngVIt1NM2vafxovvhUkJoCdCVqq 9ERDRmDz/wb2AhLZc1SGKcCfc+Q4N0hga8lGzx3tEWX5OEGeZAx+OTD+BKaat3+1nEjo zMAC5HTCYL2+kAOHhT4eIGWOPEptlD1OZv2Ynodj/8VTVrB+WaQLIc8zxV7qb4QoFCy9 JSO1j3l3Wsql0ZW5Wjc94GvHIek0L8D+TC3HjwHHj9bK2ijvtWBDg6jw96ObFMxBV1dk 4Cnw== X-Gm-Message-State: AEkoouv/4492QfmMNDLboeUydO8rEO7RrP9h0rOUvSUnxkabTA+GkJrMSSG35VSvZVIiEA== X-Received: by 10.66.158.104 with SMTP id wt8mr111214670pab.64.1470191477517; Tue, 02 Aug 2016 19:31:17 -0700 (PDT) Received: from localhost ([1.34.161.214]) by smtp.gmail.com with ESMTPSA id 15sm7780163pfz.36.2016.08.02.19.31.16 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 02 Aug 2016 19:31:16 -0700 (PDT) From: AceLan Kao To: kernel-team@lists.ubuntu.com Subject: [PATCH] intel-vbtn: new driver for Intel Virtual Button Date: Wed, 3 Aug 2016 10:31:12 +0800 Message-Id: <1470191472-29133-2-git-send-email-acelan.kao@canonical.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1470191472-29133-1-git-send-email-acelan.kao@canonical.com> References: <1470191472-29133-1-git-send-email-acelan.kao@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: kernel-team-bounces@lists.ubuntu.com BugLink: https://bugs.launchpad.net/bugs/1609204 This driver supports power button event in Intel Virtual Button currently. New Dell XPS 13 requires this driver for the power button. This driver is copied/modified from intel-hid.c Most credit goes to the author of intel-hid.c, Alex Hung Signed-off-by: AceLan Kao Signed-off-by: Darren Hart (cherry picked from commit 332e081225fc2a657aa587c42943d5f5a7dae88b) Signed-off-by: AceLan Kao --- MAINTAINERS | 6 ++ drivers/platform/x86/Kconfig | 12 +++ drivers/platform/x86/Makefile | 1 + drivers/platform/x86/intel-vbtn.c | 188 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 207 insertions(+) create mode 100644 drivers/platform/x86/intel-vbtn.c diff --git a/MAINTAINERS b/MAINTAINERS index 4650f50..76e764f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5529,6 +5529,12 @@ L: platform-driver-x86@vger.kernel.org S: Maintained F: drivers/platform/x86/intel-hid.c +INTEL VIRTUAL BUTTON DRIVER +M: AceLan Kao +L: platform-driver-x86@vger.kernel.org +S: Maintained +F: drivers/platform/x86/intel-vbtn.c + INTEL IDLE DRIVER M: Len Brown L: linux-pm@vger.kernel.org diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 338260b..5c08ade 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -743,6 +743,18 @@ config INTEL_HID_EVENT To compile this driver as a module, choose M here: the module will be called intel_hid. +config INTEL_VBTN + tristate "INTEL VIRTUAL BUTTON" + depends on ACPI + depends on INPUT + select INPUT_SPARSEKMAP + help + This driver provides support for the Intel Virtual Button interface. + Some laptops require this driver for power button support. + + To compile this driver as a module, choose M here: the module will + be called intel_vbtn. + config INTEL_SCU_IPC bool "Intel SCU IPC Support" depends on X86_INTEL_MID diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index d39c3bb..fa1436a 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -42,6 +42,7 @@ obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o obj-$(CONFIG_TOSHIBA_HAPS) += toshiba_haps.o obj-$(CONFIG_TOSHIBA_WMI) += toshiba-wmi.o obj-$(CONFIG_INTEL_HID_EVENT) += intel-hid.o +obj-$(CONFIG_INTEL_VBTN) += intel-vbtn.o obj-$(CONFIG_INTEL_SCU_IPC) += intel_scu_ipc.o obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c new file mode 100644 index 0000000..146d02f --- /dev/null +++ b/drivers/platform/x86/intel-vbtn.c @@ -0,0 +1,188 @@ +/* + * Intel Virtual Button driver for Windows 8.1+ + * + * Copyright (C) 2016 AceLan Kao + * Copyright (C) 2016 Alex Hung + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("AceLan Kao"); + +static const struct acpi_device_id intel_vbtn_ids[] = { + {"INT33D6", 0}, + {"", 0}, +}; + +/* In theory, these are HID usages. */ +static const struct key_entry intel_vbtn_keymap[] = { + { KE_IGNORE, 0xC0, { KEY_POWER } }, /* power key press */ + { KE_KEY, 0xC1, { KEY_POWER } }, /* power key release */ + { KE_END }, +}; + +struct intel_vbtn_priv { + struct input_dev *input_dev; +}; + +static int intel_vbtn_input_setup(struct platform_device *device) +{ + struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); + int ret; + + priv->input_dev = input_allocate_device(); + if (!priv->input_dev) + return -ENOMEM; + + ret = sparse_keymap_setup(priv->input_dev, intel_vbtn_keymap, NULL); + if (ret) + goto err_free_device; + + priv->input_dev->dev.parent = &device->dev; + priv->input_dev->name = "Intel Virtual Button driver"; + priv->input_dev->id.bustype = BUS_HOST; + + ret = input_register_device(priv->input_dev); + if (ret) + goto err_free_device; + + return 0; + +err_free_device: + input_free_device(priv->input_dev); + return ret; +} + +static void intel_vbtn_input_destroy(struct platform_device *device) +{ + struct intel_vbtn_priv *priv = dev_get_drvdata(&device->dev); + + input_unregister_device(priv->input_dev); +} + +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); + + if (!sparse_keymap_report_event(priv->input_dev, event, 1, true)) + dev_info(&device->dev, "unknown event index 0x%x\n", + event); +} + +static int intel_vbtn_probe(struct platform_device *device) +{ + acpi_handle handle = ACPI_HANDLE(&device->dev); + struct intel_vbtn_priv *priv; + acpi_status status; + int err; + + status = acpi_evaluate_object(handle, "VBDL", NULL, NULL); + if (!ACPI_SUCCESS(status)) { + dev_warn(&device->dev, "failed to read Intel Virtual Button driver\n"); + return -ENODEV; + } + + priv = devm_kzalloc(&device->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + dev_set_drvdata(&device->dev, priv); + + err = intel_vbtn_input_setup(device); + if (err) { + pr_err("Failed to setup Intel Virtual Button\n"); + return err; + } + + status = acpi_install_notify_handler(handle, + ACPI_DEVICE_NOTIFY, + notify_handler, + device); + if (ACPI_FAILURE(status)) { + err = -EBUSY; + goto err_remove_input; + } + + return 0; + +err_remove_input: + intel_vbtn_input_destroy(device); + + return err; +} + +static int intel_vbtn_remove(struct platform_device *device) +{ + acpi_handle handle = ACPI_HANDLE(&device->dev); + + intel_vbtn_input_destroy(device); + acpi_remove_notify_handler(handle, ACPI_DEVICE_NOTIFY, notify_handler); + + /* + * 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_vbtn_pl_driver = { + .driver = { + .name = "intel-vbtn", + .acpi_match_table = intel_vbtn_ids, + }, + .probe = intel_vbtn_probe, + .remove = intel_vbtn_remove, +}; +MODULE_DEVICE_TABLE(acpi, intel_vbtn_ids); + +static acpi_status __init +check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + const struct acpi_device_id *ids = context; + struct acpi_device *dev; + + if (acpi_bus_get_device(handle, &dev) != 0) + return AE_OK; + + if (acpi_match_device_ids(dev, ids) == 0) + if (acpi_create_platform_device(dev)) + dev_info(&dev->dev, + "intel-vbtn: created platform device\n"); + + return AE_OK; +} + +static int __init intel_vbtn_init(void) +{ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, check_acpi_dev, NULL, + (void *)intel_vbtn_ids, NULL); + + return platform_driver_register(&intel_vbtn_pl_driver); +} +module_init(intel_vbtn_init); + +static void __exit intel_vbtn_exit(void) +{ + platform_driver_unregister(&intel_vbtn_pl_driver); +} +module_exit(intel_vbtn_exit);