Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * power/home/volume button support for
0004  * Microsoft Surface Pro 3/4 tablet.
0005  *
0006  * Copyright (c) 2015 Intel Corporation.
0007  * All rights reserved.
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/init.h>
0013 #include <linux/types.h>
0014 #include <linux/input.h>
0015 #include <linux/acpi.h>
0016 #include <acpi/button.h>
0017 
0018 #define SURFACE_PRO3_BUTTON_HID     "MSHW0028"
0019 #define SURFACE_PRO4_BUTTON_HID     "MSHW0040"
0020 #define SURFACE_BUTTON_OBJ_NAME     "VGBI"
0021 #define SURFACE_BUTTON_DEVICE_NAME  "Surface Pro 3/4 Buttons"
0022 
0023 #define MSHW0040_DSM_REVISION       0x01
0024 #define MSHW0040_DSM_GET_OMPR       0x02    // get OEM Platform Revision
0025 static const guid_t MSHW0040_DSM_UUID =
0026     GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
0027           0x49, 0x80, 0x35);
0028 
0029 #define SURFACE_BUTTON_NOTIFY_TABLET_MODE   0xc8
0030 
0031 #define SURFACE_BUTTON_NOTIFY_PRESS_POWER   0xc6
0032 #define SURFACE_BUTTON_NOTIFY_RELEASE_POWER 0xc7
0033 
0034 #define SURFACE_BUTTON_NOTIFY_PRESS_HOME    0xc4
0035 #define SURFACE_BUTTON_NOTIFY_RELEASE_HOME  0xc5
0036 
0037 #define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP   0xc0
0038 #define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP 0xc1
0039 
0040 #define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN     0xc2
0041 #define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN   0xc3
0042 
0043 MODULE_AUTHOR("Chen Yu");
0044 MODULE_DESCRIPTION("Surface Pro3 Button Driver");
0045 MODULE_LICENSE("GPL v2");
0046 
0047 /*
0048  * Power button, Home button, Volume buttons support is supposed to
0049  * be covered by drivers/input/misc/soc_button_array.c, which is implemented
0050  * according to "Windows ACPI Design Guide for SoC Platforms".
0051  * However surface pro3 seems not to obey the specs, instead it uses
0052  * device VGBI(MSHW0028) for dispatching the events.
0053  * We choose acpi_driver rather than platform_driver/i2c_driver because
0054  * although VGBI has an i2c resource connected to i2c controller, it
0055  * is not embedded in any i2c controller's scope, thus neither platform_device
0056  * will be created, nor i2c_client will be enumerated, we have to use
0057  * acpi_driver.
0058  */
0059 static const struct acpi_device_id surface_button_device_ids[] = {
0060     {SURFACE_PRO3_BUTTON_HID,    0},
0061     {SURFACE_PRO4_BUTTON_HID,    0},
0062     {"", 0},
0063 };
0064 MODULE_DEVICE_TABLE(acpi, surface_button_device_ids);
0065 
0066 struct surface_button {
0067     unsigned int type;
0068     struct input_dev *input;
0069     char phys[32];          /* for input device */
0070     unsigned long pushed;
0071     bool suspended;
0072 };
0073 
0074 static void surface_button_notify(struct acpi_device *device, u32 event)
0075 {
0076     struct surface_button *button = acpi_driver_data(device);
0077     struct input_dev *input;
0078     int key_code = KEY_RESERVED;
0079     bool pressed = false;
0080 
0081     switch (event) {
0082     /* Power button press,release handle */
0083     case SURFACE_BUTTON_NOTIFY_PRESS_POWER:
0084         pressed = true;
0085         fallthrough;
0086     case SURFACE_BUTTON_NOTIFY_RELEASE_POWER:
0087         key_code = KEY_POWER;
0088         break;
0089     /* Home button press,release handle */
0090     case SURFACE_BUTTON_NOTIFY_PRESS_HOME:
0091         pressed = true;
0092         fallthrough;
0093     case SURFACE_BUTTON_NOTIFY_RELEASE_HOME:
0094         key_code = KEY_LEFTMETA;
0095         break;
0096     /* Volume up button press,release handle */
0097     case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP:
0098         pressed = true;
0099         fallthrough;
0100     case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP:
0101         key_code = KEY_VOLUMEUP;
0102         break;
0103     /* Volume down button press,release handle */
0104     case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN:
0105         pressed = true;
0106         fallthrough;
0107     case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN:
0108         key_code = KEY_VOLUMEDOWN;
0109         break;
0110     case SURFACE_BUTTON_NOTIFY_TABLET_MODE:
0111         dev_warn_once(&device->dev, "Tablet mode is not supported\n");
0112         break;
0113     default:
0114         dev_info_ratelimited(&device->dev,
0115                      "Unsupported event [0x%x]\n", event);
0116         break;
0117     }
0118     input = button->input;
0119     if (key_code == KEY_RESERVED)
0120         return;
0121     if (pressed)
0122         pm_wakeup_dev_event(&device->dev, 0, button->suspended);
0123     if (button->suspended)
0124         return;
0125     input_report_key(input, key_code, pressed?1:0);
0126     input_sync(input);
0127 }
0128 
0129 #ifdef CONFIG_PM_SLEEP
0130 static int surface_button_suspend(struct device *dev)
0131 {
0132     struct acpi_device *device = to_acpi_device(dev);
0133     struct surface_button *button = acpi_driver_data(device);
0134 
0135     button->suspended = true;
0136     return 0;
0137 }
0138 
0139 static int surface_button_resume(struct device *dev)
0140 {
0141     struct acpi_device *device = to_acpi_device(dev);
0142     struct surface_button *button = acpi_driver_data(device);
0143 
0144     button->suspended = false;
0145     return 0;
0146 }
0147 #endif
0148 
0149 /*
0150  * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device
0151  * ID (MSHW0040) for the power/volume buttons. Make sure this is the right
0152  * device by checking for the _DSM method and OEM Platform Revision.
0153  *
0154  * Returns true if the driver should bind to this device, i.e. the device is
0155  * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1.
0156  */
0157 static bool surface_button_check_MSHW0040(struct acpi_device *dev)
0158 {
0159     acpi_handle handle = dev->handle;
0160     union acpi_object *result;
0161     u64 oem_platform_rev = 0;   // valid revisions are nonzero
0162 
0163     // get OEM platform revision
0164     result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
0165                      MSHW0040_DSM_REVISION,
0166                      MSHW0040_DSM_GET_OMPR,
0167                      NULL, ACPI_TYPE_INTEGER);
0168 
0169     /*
0170      * If evaluating the _DSM fails, the method is not present. This means
0171      * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we
0172      * should use this driver. We use revision 0 indicating it is
0173      * unavailable.
0174      */
0175 
0176     if (result) {
0177         oem_platform_rev = result->integer.value;
0178         ACPI_FREE(result);
0179     }
0180 
0181     dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev);
0182 
0183     return oem_platform_rev == 0;
0184 }
0185 
0186 
0187 static int surface_button_add(struct acpi_device *device)
0188 {
0189     struct surface_button *button;
0190     struct input_dev *input;
0191     const char *hid = acpi_device_hid(device);
0192     char *name;
0193     int error;
0194 
0195     if (strncmp(acpi_device_bid(device), SURFACE_BUTTON_OBJ_NAME,
0196         strlen(SURFACE_BUTTON_OBJ_NAME)))
0197         return -ENODEV;
0198 
0199     if (!surface_button_check_MSHW0040(device))
0200         return -ENODEV;
0201 
0202     button = kzalloc(sizeof(struct surface_button), GFP_KERNEL);
0203     if (!button)
0204         return -ENOMEM;
0205 
0206     device->driver_data = button;
0207     button->input = input = input_allocate_device();
0208     if (!input) {
0209         error = -ENOMEM;
0210         goto err_free_button;
0211     }
0212 
0213     name = acpi_device_name(device);
0214     strcpy(name, SURFACE_BUTTON_DEVICE_NAME);
0215     snprintf(button->phys, sizeof(button->phys), "%s/buttons", hid);
0216 
0217     input->name = name;
0218     input->phys = button->phys;
0219     input->id.bustype = BUS_HOST;
0220     input->dev.parent = &device->dev;
0221     input_set_capability(input, EV_KEY, KEY_POWER);
0222     input_set_capability(input, EV_KEY, KEY_LEFTMETA);
0223     input_set_capability(input, EV_KEY, KEY_VOLUMEUP);
0224     input_set_capability(input, EV_KEY, KEY_VOLUMEDOWN);
0225 
0226     error = input_register_device(input);
0227     if (error)
0228         goto err_free_input;
0229 
0230     device_init_wakeup(&device->dev, true);
0231     dev_info(&device->dev,
0232             "%s [%s]\n", name, acpi_device_bid(device));
0233     return 0;
0234 
0235  err_free_input:
0236     input_free_device(input);
0237  err_free_button:
0238     kfree(button);
0239     return error;
0240 }
0241 
0242 static int surface_button_remove(struct acpi_device *device)
0243 {
0244     struct surface_button *button = acpi_driver_data(device);
0245 
0246     input_unregister_device(button->input);
0247     kfree(button);
0248     return 0;
0249 }
0250 
0251 static SIMPLE_DEV_PM_OPS(surface_button_pm,
0252         surface_button_suspend, surface_button_resume);
0253 
0254 static struct acpi_driver surface_button_driver = {
0255     .name = "surface_pro3_button",
0256     .class = "SurfacePro3",
0257     .ids = surface_button_device_ids,
0258     .ops = {
0259         .add = surface_button_add,
0260         .remove = surface_button_remove,
0261         .notify = surface_button_notify,
0262     },
0263     .drv.pm = &surface_button_pm,
0264 };
0265 
0266 module_acpi_driver(surface_button_driver);