platform/surface: Move Surface Pro 3 Button driver to platform/surface
authorMaximilian Luz <luzmaximilian@gmail.com>
Fri, 9 Oct 2020 14:11:28 +0000 (16:11 +0200)
committerHans de Goede <hdegoede@redhat.com>
Tue, 27 Oct 2020 11:51:24 +0000 (12:51 +0100)
Move the Surface Pro 3 Button driver from platform/x86 to the newly
created platform/surface directory.

Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: Chen Yu <yu.c.chen@intel.com>
Link: https://lore.kernel.org/r/20201009141128.683254-6-luzmaximilian@gmail.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
MAINTAINERS
drivers/platform/surface/Kconfig
drivers/platform/surface/Makefile
drivers/platform/surface/surfacepro3_button.c [new file with mode: 0644]
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/surfacepro3_button.c [deleted file]

index e8bc7fd..57b0707 100644 (file)
@@ -11663,7 +11663,7 @@ MICROSOFT SURFACE PRO 3 BUTTON DRIVER
 M:     Chen Yu <yu.c.chen@intel.com>
 L:     platform-driver-x86@vger.kernel.org
 S:     Supported
-F:     drivers/platform/x86/surfacepro3_button.c
+F:     drivers/platform/surface/surfacepro3_button.c
 
 MICROTEK X6 SCANNER
 M:     Oliver Neukum <oliver@neukum.org>
index ac1c749..10902ea 100644 (file)
@@ -40,4 +40,10 @@ config SURFACE_3_POWER_OPREGION
          This driver provides support for ACPI operation
          region of the Surface 3 battery platform driver.
 
+config SURFACE_PRO3_BUTTON
+       tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3/4 tablet"
+       depends on ACPI && INPUT
+       help
+         This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3/4 tablet.
+
 endif # SURFACE_PLATFORMS
index 4940d4d..dcb1df0 100644 (file)
@@ -7,3 +7,4 @@
 obj-$(CONFIG_SURFACE3_WMI)             += surface3-wmi.o
 obj-$(CONFIG_SURFACE_3_BUTTON)         += surface3_button.o
 obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o
+obj-$(CONFIG_SURFACE_PRO3_BUTTON)      += surfacepro3_button.o
diff --git a/drivers/platform/surface/surfacepro3_button.c b/drivers/platform/surface/surfacepro3_button.c
new file mode 100644 (file)
index 0000000..d8afed5
--- /dev/null
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * power/home/volume button support for
+ * Microsoft Surface Pro 3/4 tablet.
+ *
+ * Copyright (c) 2015 Intel Corporation.
+ * All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/acpi.h>
+#include <acpi/button.h>
+
+#define SURFACE_PRO3_BUTTON_HID                "MSHW0028"
+#define SURFACE_PRO4_BUTTON_HID                "MSHW0040"
+#define SURFACE_BUTTON_OBJ_NAME                "VGBI"
+#define SURFACE_BUTTON_DEVICE_NAME     "Surface Pro 3/4 Buttons"
+
+#define MSHW0040_DSM_REVISION          0x01
+#define MSHW0040_DSM_GET_OMPR          0x02    // get OEM Platform Revision
+static const guid_t MSHW0040_DSM_UUID =
+       GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
+                 0x49, 0x80, 0x35);
+
+#define SURFACE_BUTTON_NOTIFY_TABLET_MODE      0xc8
+
+#define SURFACE_BUTTON_NOTIFY_PRESS_POWER      0xc6
+#define SURFACE_BUTTON_NOTIFY_RELEASE_POWER    0xc7
+
+#define SURFACE_BUTTON_NOTIFY_PRESS_HOME       0xc4
+#define SURFACE_BUTTON_NOTIFY_RELEASE_HOME     0xc5
+
+#define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP  0xc0
+#define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP        0xc1
+
+#define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN                0xc2
+#define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN      0xc3
+
+ACPI_MODULE_NAME("surface pro 3 button");
+
+MODULE_AUTHOR("Chen Yu");
+MODULE_DESCRIPTION("Surface Pro3 Button Driver");
+MODULE_LICENSE("GPL v2");
+
+/*
+ * Power button, Home button, Volume buttons support is supposed to
+ * be covered by drivers/input/misc/soc_button_array.c, which is implemented
+ * according to "Windows ACPI Design Guide for SoC Platforms".
+ * However surface pro3 seems not to obey the specs, instead it uses
+ * device VGBI(MSHW0028) for dispatching the events.
+ * We choose acpi_driver rather than platform_driver/i2c_driver because
+ * although VGBI has an i2c resource connected to i2c controller, it
+ * is not embedded in any i2c controller's scope, thus neither platform_device
+ * will be created, nor i2c_client will be enumerated, we have to use
+ * acpi_driver.
+ */
+static const struct acpi_device_id surface_button_device_ids[] = {
+       {SURFACE_PRO3_BUTTON_HID,    0},
+       {SURFACE_PRO4_BUTTON_HID,    0},
+       {"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, surface_button_device_ids);
+
+struct surface_button {
+       unsigned int type;
+       struct input_dev *input;
+       char phys[32];                  /* for input device */
+       unsigned long pushed;
+       bool suspended;
+};
+
+static void surface_button_notify(struct acpi_device *device, u32 event)
+{
+       struct surface_button *button = acpi_driver_data(device);
+       struct input_dev *input;
+       int key_code = KEY_RESERVED;
+       bool pressed = false;
+
+       switch (event) {
+       /* Power button press,release handle */
+       case SURFACE_BUTTON_NOTIFY_PRESS_POWER:
+               pressed = true;
+               fallthrough;
+       case SURFACE_BUTTON_NOTIFY_RELEASE_POWER:
+               key_code = KEY_POWER;
+               break;
+       /* Home button press,release handle */
+       case SURFACE_BUTTON_NOTIFY_PRESS_HOME:
+               pressed = true;
+               fallthrough;
+       case SURFACE_BUTTON_NOTIFY_RELEASE_HOME:
+               key_code = KEY_LEFTMETA;
+               break;
+       /* Volume up button press,release handle */
+       case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP:
+               pressed = true;
+               fallthrough;
+       case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP:
+               key_code = KEY_VOLUMEUP;
+               break;
+       /* Volume down button press,release handle */
+       case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN:
+               pressed = true;
+               fallthrough;
+       case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN:
+               key_code = KEY_VOLUMEDOWN;
+               break;
+       case SURFACE_BUTTON_NOTIFY_TABLET_MODE:
+               dev_warn_once(&device->dev, "Tablet mode is not supported\n");
+               break;
+       default:
+               dev_info_ratelimited(&device->dev,
+                                    "Unsupported event [0x%x]\n", event);
+               break;
+       }
+       input = button->input;
+       if (key_code == KEY_RESERVED)
+               return;
+       if (pressed)
+               pm_wakeup_dev_event(&device->dev, 0, button->suspended);
+       if (button->suspended)
+               return;
+       input_report_key(input, key_code, pressed?1:0);
+       input_sync(input);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int surface_button_suspend(struct device *dev)
+{
+       struct acpi_device *device = to_acpi_device(dev);
+       struct surface_button *button = acpi_driver_data(device);
+
+       button->suspended = true;
+       return 0;
+}
+
+static int surface_button_resume(struct device *dev)
+{
+       struct acpi_device *device = to_acpi_device(dev);
+       struct surface_button *button = acpi_driver_data(device);
+
+       button->suspended = false;
+       return 0;
+}
+#endif
+
+/*
+ * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device
+ * ID (MSHW0040) for the power/volume buttons. Make sure this is the right
+ * device by checking for the _DSM method and OEM Platform Revision.
+ *
+ * Returns true if the driver should bind to this device, i.e. the device is
+ * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1.
+ */
+static bool surface_button_check_MSHW0040(struct acpi_device *dev)
+{
+       acpi_handle handle = dev->handle;
+       union acpi_object *result;
+       u64 oem_platform_rev = 0;       // valid revisions are nonzero
+
+       // get OEM platform revision
+       result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
+                                        MSHW0040_DSM_REVISION,
+                                        MSHW0040_DSM_GET_OMPR,
+                                        NULL, ACPI_TYPE_INTEGER);
+
+       /*
+        * If evaluating the _DSM fails, the method is not present. This means
+        * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we
+        * should use this driver. We use revision 0 indicating it is
+        * unavailable.
+        */
+
+       if (result) {
+               oem_platform_rev = result->integer.value;
+               ACPI_FREE(result);
+       }
+
+       dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev);
+
+       return oem_platform_rev == 0;
+}
+
+
+static int surface_button_add(struct acpi_device *device)
+{
+       struct surface_button *button;
+       struct input_dev *input;
+       const char *hid = acpi_device_hid(device);
+       char *name;
+       int error;
+
+       if (strncmp(acpi_device_bid(device), SURFACE_BUTTON_OBJ_NAME,
+           strlen(SURFACE_BUTTON_OBJ_NAME)))
+               return -ENODEV;
+
+       if (!surface_button_check_MSHW0040(device))
+               return -ENODEV;
+
+       button = kzalloc(sizeof(struct surface_button), GFP_KERNEL);
+       if (!button)
+               return -ENOMEM;
+
+       device->driver_data = button;
+       button->input = input = input_allocate_device();
+       if (!input) {
+               error = -ENOMEM;
+               goto err_free_button;
+       }
+
+       name = acpi_device_name(device);
+       strcpy(name, SURFACE_BUTTON_DEVICE_NAME);
+       snprintf(button->phys, sizeof(button->phys), "%s/buttons", hid);
+
+       input->name = name;
+       input->phys = button->phys;
+       input->id.bustype = BUS_HOST;
+       input->dev.parent = &device->dev;
+       input_set_capability(input, EV_KEY, KEY_POWER);
+       input_set_capability(input, EV_KEY, KEY_LEFTMETA);
+       input_set_capability(input, EV_KEY, KEY_VOLUMEUP);
+       input_set_capability(input, EV_KEY, KEY_VOLUMEDOWN);
+
+       error = input_register_device(input);
+       if (error)
+               goto err_free_input;
+
+       device_init_wakeup(&device->dev, true);
+       dev_info(&device->dev,
+                       "%s [%s]\n", name, acpi_device_bid(device));
+       return 0;
+
+ err_free_input:
+       input_free_device(input);
+ err_free_button:
+       kfree(button);
+       return error;
+}
+
+static int surface_button_remove(struct acpi_device *device)
+{
+       struct surface_button *button = acpi_driver_data(device);
+
+       input_unregister_device(button->input);
+       kfree(button);
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(surface_button_pm,
+               surface_button_suspend, surface_button_resume);
+
+static struct acpi_driver surface_button_driver = {
+       .name = "surface_pro3_button",
+       .class = "SurfacePro3",
+       .ids = surface_button_device_ids,
+       .ops = {
+               .add = surface_button_add,
+               .remove = surface_button_remove,
+               .notify = surface_button_notify,
+       },
+       .drv.pm = &surface_button_pm,
+};
+
+module_acpi_driver(surface_button_driver);
index 8417ee0..6083f82 100644 (file)
@@ -870,12 +870,6 @@ config INTEL_VBTN
          To compile this driver as a module, choose M here: the module will
          be called intel_vbtn.
 
-config SURFACE_PRO3_BUTTON
-       tristate "Power/home/volume buttons driver for Microsoft Surface Pro 3/4 tablet"
-       depends on ACPI && INPUT
-       help
-         This driver handles the power/home/volume buttons on the Microsoft Surface Pro 3/4 tablet.
-
 config MSI_LAPTOP
        tristate "MSI Laptop Extras"
        depends on ACPI
index ffa31f5..aeff497 100644 (file)
@@ -81,9 +81,6 @@ obj-$(CONFIG_INTEL_MENLOW)            += intel_menlow.o
 obj-$(CONFIG_INTEL_OAKTRAIL)           += intel_oaktrail.o
 obj-$(CONFIG_INTEL_VBTN)               += intel-vbtn.o
 
-# Microsoft
-obj-$(CONFIG_SURFACE_PRO3_BUTTON)      += surfacepro3_button.o
-
 # MSI
 obj-$(CONFIG_MSI_LAPTOP)       += msi-laptop.o
 obj-$(CONFIG_MSI_WMI)          += msi-wmi.o
diff --git a/drivers/platform/x86/surfacepro3_button.c b/drivers/platform/x86/surfacepro3_button.c
deleted file mode 100644 (file)
index d8afed5..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * power/home/volume button support for
- * Microsoft Surface Pro 3/4 tablet.
- *
- * Copyright (c) 2015 Intel Corporation.
- * All rights reserved.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/input.h>
-#include <linux/acpi.h>
-#include <acpi/button.h>
-
-#define SURFACE_PRO3_BUTTON_HID                "MSHW0028"
-#define SURFACE_PRO4_BUTTON_HID                "MSHW0040"
-#define SURFACE_BUTTON_OBJ_NAME                "VGBI"
-#define SURFACE_BUTTON_DEVICE_NAME     "Surface Pro 3/4 Buttons"
-
-#define MSHW0040_DSM_REVISION          0x01
-#define MSHW0040_DSM_GET_OMPR          0x02    // get OEM Platform Revision
-static const guid_t MSHW0040_DSM_UUID =
-       GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
-                 0x49, 0x80, 0x35);
-
-#define SURFACE_BUTTON_NOTIFY_TABLET_MODE      0xc8
-
-#define SURFACE_BUTTON_NOTIFY_PRESS_POWER      0xc6
-#define SURFACE_BUTTON_NOTIFY_RELEASE_POWER    0xc7
-
-#define SURFACE_BUTTON_NOTIFY_PRESS_HOME       0xc4
-#define SURFACE_BUTTON_NOTIFY_RELEASE_HOME     0xc5
-
-#define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP  0xc0
-#define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP        0xc1
-
-#define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN                0xc2
-#define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN      0xc3
-
-ACPI_MODULE_NAME("surface pro 3 button");
-
-MODULE_AUTHOR("Chen Yu");
-MODULE_DESCRIPTION("Surface Pro3 Button Driver");
-MODULE_LICENSE("GPL v2");
-
-/*
- * Power button, Home button, Volume buttons support is supposed to
- * be covered by drivers/input/misc/soc_button_array.c, which is implemented
- * according to "Windows ACPI Design Guide for SoC Platforms".
- * However surface pro3 seems not to obey the specs, instead it uses
- * device VGBI(MSHW0028) for dispatching the events.
- * We choose acpi_driver rather than platform_driver/i2c_driver because
- * although VGBI has an i2c resource connected to i2c controller, it
- * is not embedded in any i2c controller's scope, thus neither platform_device
- * will be created, nor i2c_client will be enumerated, we have to use
- * acpi_driver.
- */
-static const struct acpi_device_id surface_button_device_ids[] = {
-       {SURFACE_PRO3_BUTTON_HID,    0},
-       {SURFACE_PRO4_BUTTON_HID,    0},
-       {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, surface_button_device_ids);
-
-struct surface_button {
-       unsigned int type;
-       struct input_dev *input;
-       char phys[32];                  /* for input device */
-       unsigned long pushed;
-       bool suspended;
-};
-
-static void surface_button_notify(struct acpi_device *device, u32 event)
-{
-       struct surface_button *button = acpi_driver_data(device);
-       struct input_dev *input;
-       int key_code = KEY_RESERVED;
-       bool pressed = false;
-
-       switch (event) {
-       /* Power button press,release handle */
-       case SURFACE_BUTTON_NOTIFY_PRESS_POWER:
-               pressed = true;
-               fallthrough;
-       case SURFACE_BUTTON_NOTIFY_RELEASE_POWER:
-               key_code = KEY_POWER;
-               break;
-       /* Home button press,release handle */
-       case SURFACE_BUTTON_NOTIFY_PRESS_HOME:
-               pressed = true;
-               fallthrough;
-       case SURFACE_BUTTON_NOTIFY_RELEASE_HOME:
-               key_code = KEY_LEFTMETA;
-               break;
-       /* Volume up button press,release handle */
-       case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP:
-               pressed = true;
-               fallthrough;
-       case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP:
-               key_code = KEY_VOLUMEUP;
-               break;
-       /* Volume down button press,release handle */
-       case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN:
-               pressed = true;
-               fallthrough;
-       case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN:
-               key_code = KEY_VOLUMEDOWN;
-               break;
-       case SURFACE_BUTTON_NOTIFY_TABLET_MODE:
-               dev_warn_once(&device->dev, "Tablet mode is not supported\n");
-               break;
-       default:
-               dev_info_ratelimited(&device->dev,
-                                    "Unsupported event [0x%x]\n", event);
-               break;
-       }
-       input = button->input;
-       if (key_code == KEY_RESERVED)
-               return;
-       if (pressed)
-               pm_wakeup_dev_event(&device->dev, 0, button->suspended);
-       if (button->suspended)
-               return;
-       input_report_key(input, key_code, pressed?1:0);
-       input_sync(input);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int surface_button_suspend(struct device *dev)
-{
-       struct acpi_device *device = to_acpi_device(dev);
-       struct surface_button *button = acpi_driver_data(device);
-
-       button->suspended = true;
-       return 0;
-}
-
-static int surface_button_resume(struct device *dev)
-{
-       struct acpi_device *device = to_acpi_device(dev);
-       struct surface_button *button = acpi_driver_data(device);
-
-       button->suspended = false;
-       return 0;
-}
-#endif
-
-/*
- * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device
- * ID (MSHW0040) for the power/volume buttons. Make sure this is the right
- * device by checking for the _DSM method and OEM Platform Revision.
- *
- * Returns true if the driver should bind to this device, i.e. the device is
- * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1.
- */
-static bool surface_button_check_MSHW0040(struct acpi_device *dev)
-{
-       acpi_handle handle = dev->handle;
-       union acpi_object *result;
-       u64 oem_platform_rev = 0;       // valid revisions are nonzero
-
-       // get OEM platform revision
-       result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
-                                        MSHW0040_DSM_REVISION,
-                                        MSHW0040_DSM_GET_OMPR,
-                                        NULL, ACPI_TYPE_INTEGER);
-
-       /*
-        * If evaluating the _DSM fails, the method is not present. This means
-        * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we
-        * should use this driver. We use revision 0 indicating it is
-        * unavailable.
-        */
-
-       if (result) {
-               oem_platform_rev = result->integer.value;
-               ACPI_FREE(result);
-       }
-
-       dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev);
-
-       return oem_platform_rev == 0;
-}
-
-
-static int surface_button_add(struct acpi_device *device)
-{
-       struct surface_button *button;
-       struct input_dev *input;
-       const char *hid = acpi_device_hid(device);
-       char *name;
-       int error;
-
-       if (strncmp(acpi_device_bid(device), SURFACE_BUTTON_OBJ_NAME,
-           strlen(SURFACE_BUTTON_OBJ_NAME)))
-               return -ENODEV;
-
-       if (!surface_button_check_MSHW0040(device))
-               return -ENODEV;
-
-       button = kzalloc(sizeof(struct surface_button), GFP_KERNEL);
-       if (!button)
-               return -ENOMEM;
-
-       device->driver_data = button;
-       button->input = input = input_allocate_device();
-       if (!input) {
-               error = -ENOMEM;
-               goto err_free_button;
-       }
-
-       name = acpi_device_name(device);
-       strcpy(name, SURFACE_BUTTON_DEVICE_NAME);
-       snprintf(button->phys, sizeof(button->phys), "%s/buttons", hid);
-
-       input->name = name;
-       input->phys = button->phys;
-       input->id.bustype = BUS_HOST;
-       input->dev.parent = &device->dev;
-       input_set_capability(input, EV_KEY, KEY_POWER);
-       input_set_capability(input, EV_KEY, KEY_LEFTMETA);
-       input_set_capability(input, EV_KEY, KEY_VOLUMEUP);
-       input_set_capability(input, EV_KEY, KEY_VOLUMEDOWN);
-
-       error = input_register_device(input);
-       if (error)
-               goto err_free_input;
-
-       device_init_wakeup(&device->dev, true);
-       dev_info(&device->dev,
-                       "%s [%s]\n", name, acpi_device_bid(device));
-       return 0;
-
- err_free_input:
-       input_free_device(input);
- err_free_button:
-       kfree(button);
-       return error;
-}
-
-static int surface_button_remove(struct acpi_device *device)
-{
-       struct surface_button *button = acpi_driver_data(device);
-
-       input_unregister_device(button->input);
-       kfree(button);
-       return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(surface_button_pm,
-               surface_button_suspend, surface_button_resume);
-
-static struct acpi_driver surface_button_driver = {
-       .name = "surface_pro3_button",
-       .class = "SurfacePro3",
-       .ids = surface_button_device_ids,
-       .ops = {
-               .add = surface_button_add,
-               .remove = surface_button_remove,
-               .notify = surface_button_notify,
-       },
-       .drv.pm = &surface_button_pm,
-};
-
-module_acpi_driver(surface_button_driver);