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