1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * power/home/volume button support for 4 * Microsoft Surface Pro 3/4 tablet. 5 * 6 * Copyright (c) 2015 Intel Corporation. 7 * All rights reserved. 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/init.h> 13 #include <linux/string.h> 14 #include <linux/types.h> 15 #include <linux/input.h> 16 #include <linux/acpi.h> 17 #include <acpi/button.h> 18 19 #define SURFACE_PRO3_BUTTON_HID "MSHW0028" 20 #define SURFACE_PRO4_BUTTON_HID "MSHW0040" 21 #define SURFACE_BUTTON_OBJ_NAME "VGBI" 22 #define SURFACE_BUTTON_DEVICE_NAME "Surface Pro 3/4 Buttons" 23 24 #define MSHW0040_DSM_REVISION 0x01 25 #define MSHW0040_DSM_GET_OMPR 0x02 // get OEM Platform Revision 26 static const guid_t MSHW0040_DSM_UUID = 27 GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65, 28 0x49, 0x80, 0x35); 29 30 #define SURFACE_BUTTON_NOTIFY_TABLET_MODE 0xc8 31 32 #define SURFACE_BUTTON_NOTIFY_PRESS_POWER 0xc6 33 #define SURFACE_BUTTON_NOTIFY_RELEASE_POWER 0xc7 34 35 #define SURFACE_BUTTON_NOTIFY_PRESS_HOME 0xc4 36 #define SURFACE_BUTTON_NOTIFY_RELEASE_HOME 0xc5 37 38 #define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP 0xc0 39 #define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP 0xc1 40 41 #define SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN 0xc2 42 #define SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN 0xc3 43 44 MODULE_AUTHOR("Chen Yu"); 45 MODULE_DESCRIPTION("Surface Pro3 Button Driver"); 46 MODULE_LICENSE("GPL v2"); 47 48 /* 49 * Power button, Home button, Volume buttons support is supposed to 50 * be covered by drivers/input/misc/soc_button_array.c, which is implemented 51 * according to "Windows ACPI Design Guide for SoC Platforms". 52 * However surface pro3 seems not to obey the specs, instead it uses 53 * device VGBI(MSHW0028) for dispatching the events. 54 * We choose acpi_driver rather than platform_driver/i2c_driver because 55 * although VGBI has an i2c resource connected to i2c controller, it 56 * is not embedded in any i2c controller's scope, thus neither platform_device 57 * will be created, nor i2c_client will be enumerated, we have to use 58 * acpi_driver. 59 */ 60 static const struct acpi_device_id surface_button_device_ids[] = { 61 {SURFACE_PRO3_BUTTON_HID, 0}, 62 {SURFACE_PRO4_BUTTON_HID, 0}, 63 {"", 0}, 64 }; 65 MODULE_DEVICE_TABLE(acpi, surface_button_device_ids); 66 67 struct surface_button { 68 unsigned int type; 69 struct input_dev *input; 70 char phys[32]; /* for input device */ 71 unsigned long pushed; 72 bool suspended; 73 }; 74 75 static void surface_button_notify(struct acpi_device *device, u32 event) 76 { 77 struct surface_button *button = acpi_driver_data(device); 78 struct input_dev *input; 79 int key_code = KEY_RESERVED; 80 bool pressed = false; 81 82 switch (event) { 83 /* Power button press,release handle */ 84 case SURFACE_BUTTON_NOTIFY_PRESS_POWER: 85 pressed = true; 86 fallthrough; 87 case SURFACE_BUTTON_NOTIFY_RELEASE_POWER: 88 key_code = KEY_POWER; 89 break; 90 /* Home button press,release handle */ 91 case SURFACE_BUTTON_NOTIFY_PRESS_HOME: 92 pressed = true; 93 fallthrough; 94 case SURFACE_BUTTON_NOTIFY_RELEASE_HOME: 95 key_code = KEY_LEFTMETA; 96 break; 97 /* Volume up button press,release handle */ 98 case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP: 99 pressed = true; 100 fallthrough; 101 case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP: 102 key_code = KEY_VOLUMEUP; 103 break; 104 /* Volume down button press,release handle */ 105 case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN: 106 pressed = true; 107 fallthrough; 108 case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN: 109 key_code = KEY_VOLUMEDOWN; 110 break; 111 case SURFACE_BUTTON_NOTIFY_TABLET_MODE: 112 dev_warn_once(&device->dev, "Tablet mode is not supported\n"); 113 break; 114 default: 115 dev_info_ratelimited(&device->dev, 116 "Unsupported event [0x%x]\n", event); 117 break; 118 } 119 input = button->input; 120 if (key_code == KEY_RESERVED) 121 return; 122 if (pressed) 123 pm_wakeup_dev_event(&device->dev, 0, button->suspended); 124 if (button->suspended) 125 return; 126 input_report_key(input, key_code, pressed?1:0); 127 input_sync(input); 128 } 129 130 #ifdef CONFIG_PM_SLEEP 131 static int surface_button_suspend(struct device *dev) 132 { 133 struct acpi_device *device = to_acpi_device(dev); 134 struct surface_button *button = acpi_driver_data(device); 135 136 button->suspended = true; 137 return 0; 138 } 139 140 static int surface_button_resume(struct device *dev) 141 { 142 struct acpi_device *device = to_acpi_device(dev); 143 struct surface_button *button = acpi_driver_data(device); 144 145 button->suspended = false; 146 return 0; 147 } 148 #endif 149 150 /* 151 * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device 152 * ID (MSHW0040) for the power/volume buttons. Make sure this is the right 153 * device by checking for the _DSM method and OEM Platform Revision. 154 * 155 * Returns true if the driver should bind to this device, i.e. the device is 156 * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1. 157 */ 158 static bool surface_button_check_MSHW0040(struct acpi_device *dev) 159 { 160 acpi_handle handle = dev->handle; 161 union acpi_object *result; 162 u64 oem_platform_rev = 0; // valid revisions are nonzero 163 164 // get OEM platform revision 165 result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID, 166 MSHW0040_DSM_REVISION, 167 MSHW0040_DSM_GET_OMPR, 168 NULL, ACPI_TYPE_INTEGER); 169 170 /* 171 * If evaluating the _DSM fails, the method is not present. This means 172 * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we 173 * should use this driver. We use revision 0 indicating it is 174 * unavailable. 175 */ 176 177 if (result) { 178 oem_platform_rev = result->integer.value; 179 ACPI_FREE(result); 180 } 181 182 dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev); 183 184 return oem_platform_rev == 0; 185 } 186 187 188 static int surface_button_add(struct acpi_device *device) 189 { 190 struct surface_button *button; 191 struct input_dev *input; 192 const char *hid = acpi_device_hid(device); 193 int error; 194 195 if (strncmp(acpi_device_bid(device), SURFACE_BUTTON_OBJ_NAME, 196 strlen(SURFACE_BUTTON_OBJ_NAME))) 197 return -ENODEV; 198 199 if (!surface_button_check_MSHW0040(device)) 200 return -ENODEV; 201 202 button = kzalloc(sizeof(struct surface_button), GFP_KERNEL); 203 if (!button) 204 return -ENOMEM; 205 206 device->driver_data = button; 207 button->input = input = input_allocate_device(); 208 if (!input) { 209 error = -ENOMEM; 210 goto err_free_button; 211 } 212 213 strscpy(acpi_device_name(device), SURFACE_BUTTON_DEVICE_NAME); 214 snprintf(button->phys, sizeof(button->phys), "%s/buttons", hid); 215 216 input->name = acpi_device_name(device); 217 input->phys = button->phys; 218 input->id.bustype = BUS_HOST; 219 input->dev.parent = &device->dev; 220 input_set_capability(input, EV_KEY, KEY_POWER); 221 input_set_capability(input, EV_KEY, KEY_LEFTMETA); 222 input_set_capability(input, EV_KEY, KEY_VOLUMEUP); 223 input_set_capability(input, EV_KEY, KEY_VOLUMEDOWN); 224 225 error = input_register_device(input); 226 if (error) 227 goto err_free_input; 228 229 device_init_wakeup(&device->dev, true); 230 dev_info(&device->dev, "%s [%s]\n", acpi_device_name(device), 231 acpi_device_bid(device)); 232 return 0; 233 234 err_free_input: 235 input_free_device(input); 236 err_free_button: 237 kfree(button); 238 return error; 239 } 240 241 static void surface_button_remove(struct acpi_device *device) 242 { 243 struct surface_button *button = acpi_driver_data(device); 244 245 input_unregister_device(button->input); 246 kfree(button); 247 } 248 249 static SIMPLE_DEV_PM_OPS(surface_button_pm, 250 surface_button_suspend, surface_button_resume); 251 252 static struct acpi_driver surface_button_driver = { 253 .name = "surface_pro3_button", 254 .class = "SurfacePro3", 255 .ids = surface_button_device_ids, 256 .ops = { 257 .add = surface_button_add, 258 .remove = surface_button_remove, 259 .notify = surface_button_notify, 260 }, 261 .drv.pm = &surface_button_pm, 262 }; 263 264 module_acpi_driver(surface_button_driver); 265