| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Acer WMI Laptop Extras |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * Based on acer_acpi: |
|---|
| 7 | 8 | * Copyright (C) 2005-2007 E.M. Smith |
|---|
| 8 | 9 | * Copyright (C) 2007-2008 Carlos Corbacho <cathectic@gmail.com> |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 12 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 13 | | - * (at your option) any later version. |
|---|
| 14 | | - * |
|---|
| 15 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 16 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 17 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 18 | | - * GNU General Public License for more details. |
|---|
| 19 | | - * |
|---|
| 20 | | - * You should have received a copy of the GNU General Public License |
|---|
| 21 | | - * along with this program; if not, write to the Free Software |
|---|
| 22 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 23 | 10 | */ |
|---|
| 24 | 11 | |
|---|
| 25 | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 106 | 93 | {KE_KEY, 0x22, {KEY_PROG2} }, /* Arcade */ |
|---|
| 107 | 94 | {KE_KEY, 0x23, {KEY_PROG3} }, /* P_Key */ |
|---|
| 108 | 95 | {KE_KEY, 0x24, {KEY_PROG4} }, /* Social networking_Key */ |
|---|
| 96 | + {KE_KEY, 0x27, {KEY_HELP} }, |
|---|
| 109 | 97 | {KE_KEY, 0x29, {KEY_PROG3} }, /* P_Key for TM8372 */ |
|---|
| 110 | 98 | {KE_IGNORE, 0x41, {KEY_MUTE} }, |
|---|
| 111 | 99 | {KE_IGNORE, 0x42, {KEY_PREVIOUSSONG} }, |
|---|
| .. | .. |
|---|
| 119 | 107 | {KE_IGNORE, 0x48, {KEY_VOLUMEUP} }, |
|---|
| 120 | 108 | {KE_IGNORE, 0x49, {KEY_VOLUMEDOWN} }, |
|---|
| 121 | 109 | {KE_IGNORE, 0x4a, {KEY_VOLUMEDOWN} }, |
|---|
| 122 | | - {KE_IGNORE, 0x61, {KEY_SWITCHVIDEOMODE} }, |
|---|
| 110 | + /* |
|---|
| 111 | + * 0x61 is KEY_SWITCHVIDEOMODE. Usually this is a duplicate input event |
|---|
| 112 | + * with the "Video Bus" input device events. But sometimes it is not |
|---|
| 113 | + * a dup. Map it to KEY_UNKNOWN instead of using KE_IGNORE so that |
|---|
| 114 | + * udev/hwdb can override it on systems where it is not a dup. |
|---|
| 115 | + */ |
|---|
| 116 | + {KE_KEY, 0x61, {KEY_UNKNOWN} }, |
|---|
| 123 | 117 | {KE_IGNORE, 0x62, {KEY_BRIGHTNESSUP} }, |
|---|
| 124 | 118 | {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} }, |
|---|
| 125 | 119 | {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ |
|---|
| .. | .. |
|---|
| 278 | 272 | |
|---|
| 279 | 273 | struct acer_debug { |
|---|
| 280 | 274 | struct dentry *root; |
|---|
| 281 | | - struct dentry *devices; |
|---|
| 282 | 275 | u32 wmid_devices; |
|---|
| 283 | 276 | }; |
|---|
| 284 | 277 | |
|---|
| .. | .. |
|---|
| 540 | 533 | .matches = { |
|---|
| 541 | 534 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
|---|
| 542 | 535 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"), |
|---|
| 536 | + }, |
|---|
| 537 | + .driver_data = (void *)ACER_CAP_KBD_DOCK, |
|---|
| 538 | + }, |
|---|
| 539 | + { |
|---|
| 540 | + .callback = set_force_caps, |
|---|
| 541 | + .ident = "Acer Aspire Switch V 10 SW5-017", |
|---|
| 542 | + .matches = { |
|---|
| 543 | + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"), |
|---|
| 544 | + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SW5-017"), |
|---|
| 543 | 545 | }, |
|---|
| 544 | 546 | .driver_data = (void *)ACER_CAP_KBD_DOCK, |
|---|
| 545 | 547 | }, |
|---|
| .. | .. |
|---|
| 1057 | 1059 | *value = tmp & 0x1; |
|---|
| 1058 | 1060 | return 0; |
|---|
| 1059 | 1061 | } |
|---|
| 1062 | + fallthrough; |
|---|
| 1060 | 1063 | default: |
|---|
| 1061 | 1064 | return AE_ERROR; |
|---|
| 1062 | 1065 | } |
|---|
| .. | .. |
|---|
| 1381 | 1384 | status = AMW0_get_u32(value, cap); |
|---|
| 1382 | 1385 | break; |
|---|
| 1383 | 1386 | } |
|---|
| 1387 | + fallthrough; |
|---|
| 1384 | 1388 | case ACER_WMID: |
|---|
| 1385 | 1389 | status = WMID_get_u32(value, cap); |
|---|
| 1386 | 1390 | break; |
|---|
| .. | .. |
|---|
| 1423 | 1427 | |
|---|
| 1424 | 1428 | return AMW0_set_u32(value, cap); |
|---|
| 1425 | 1429 | } |
|---|
| 1430 | + fallthrough; |
|---|
| 1426 | 1431 | case ACER_WMID: |
|---|
| 1427 | 1432 | return WMID_set_u32(value, cap); |
|---|
| 1428 | 1433 | case ACER_WMID_v2: |
|---|
| .. | .. |
|---|
| 1432 | 1437 | return wmid_v2_set_u32(value, cap); |
|---|
| 1433 | 1438 | else if (wmi_has_guid(WMID_GUID2)) |
|---|
| 1434 | 1439 | return WMID_set_u32(value, cap); |
|---|
| 1440 | + fallthrough; |
|---|
| 1435 | 1441 | default: |
|---|
| 1436 | 1442 | return AE_BAD_PARAMETER; |
|---|
| 1437 | 1443 | } |
|---|
| .. | .. |
|---|
| 1997 | 2003 | return status; |
|---|
| 1998 | 2004 | } |
|---|
| 1999 | 2005 | |
|---|
| 2000 | | -#define ACER_WMID_ACCEL_HID "BST0001" |
|---|
| 2001 | | - |
|---|
| 2002 | | -static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, |
|---|
| 2003 | | - void *ctx, void **retval) |
|---|
| 2004 | | -{ |
|---|
| 2005 | | - struct acpi_device *dev; |
|---|
| 2006 | | - |
|---|
| 2007 | | - if (!strcmp(ctx, "SENR")) { |
|---|
| 2008 | | - if (acpi_bus_get_device(ah, &dev)) |
|---|
| 2009 | | - return AE_OK; |
|---|
| 2010 | | - if (strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) |
|---|
| 2011 | | - return AE_OK; |
|---|
| 2012 | | - } else |
|---|
| 2013 | | - return AE_OK; |
|---|
| 2014 | | - |
|---|
| 2015 | | - *(acpi_handle *)retval = ah; |
|---|
| 2016 | | - |
|---|
| 2017 | | - return AE_CTRL_TERMINATE; |
|---|
| 2018 | | -} |
|---|
| 2019 | | - |
|---|
| 2020 | | -static int __init acer_wmi_get_handle(const char *name, const char *prop, |
|---|
| 2021 | | - acpi_handle *ah) |
|---|
| 2022 | | -{ |
|---|
| 2023 | | - acpi_status status; |
|---|
| 2024 | | - acpi_handle handle; |
|---|
| 2025 | | - |
|---|
| 2026 | | - BUG_ON(!name || !ah); |
|---|
| 2027 | | - |
|---|
| 2028 | | - handle = NULL; |
|---|
| 2029 | | - status = acpi_get_devices(prop, acer_wmi_get_handle_cb, |
|---|
| 2030 | | - (void *)name, &handle); |
|---|
| 2031 | | - if (ACPI_SUCCESS(status) && handle) { |
|---|
| 2032 | | - *ah = handle; |
|---|
| 2033 | | - return 0; |
|---|
| 2034 | | - } else { |
|---|
| 2035 | | - return -ENODEV; |
|---|
| 2036 | | - } |
|---|
| 2037 | | -} |
|---|
| 2038 | | - |
|---|
| 2039 | 2006 | static int __init acer_wmi_accel_setup(void) |
|---|
| 2040 | 2007 | { |
|---|
| 2008 | + struct acpi_device *adev; |
|---|
| 2041 | 2009 | int err; |
|---|
| 2042 | 2010 | |
|---|
| 2043 | | - err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, &gsensor_handle); |
|---|
| 2044 | | - if (err) |
|---|
| 2045 | | - return err; |
|---|
| 2011 | + adev = acpi_dev_get_first_match_dev("BST0001", NULL, -1); |
|---|
| 2012 | + if (!adev) |
|---|
| 2013 | + return -ENODEV; |
|---|
| 2014 | + |
|---|
| 2015 | + gsensor_handle = acpi_device_handle(adev); |
|---|
| 2016 | + acpi_dev_put(adev); |
|---|
| 2046 | 2017 | |
|---|
| 2047 | 2018 | acer_wmi_accel_dev = input_allocate_device(); |
|---|
| 2048 | 2019 | if (!acer_wmi_accel_dev) |
|---|
| .. | .. |
|---|
| 2266 | 2237 | |
|---|
| 2267 | 2238 | static void remove_debugfs(void) |
|---|
| 2268 | 2239 | { |
|---|
| 2269 | | - debugfs_remove(interface->debug.devices); |
|---|
| 2270 | | - debugfs_remove(interface->debug.root); |
|---|
| 2240 | + debugfs_remove_recursive(interface->debug.root); |
|---|
| 2271 | 2241 | } |
|---|
| 2272 | 2242 | |
|---|
| 2273 | | -static int __init create_debugfs(void) |
|---|
| 2243 | +static void __init create_debugfs(void) |
|---|
| 2274 | 2244 | { |
|---|
| 2275 | 2245 | interface->debug.root = debugfs_create_dir("acer-wmi", NULL); |
|---|
| 2276 | | - if (!interface->debug.root) { |
|---|
| 2277 | | - pr_err("Failed to create debugfs directory"); |
|---|
| 2278 | | - return -ENOMEM; |
|---|
| 2279 | | - } |
|---|
| 2280 | 2246 | |
|---|
| 2281 | | - interface->debug.devices = debugfs_create_u32("devices", S_IRUGO, |
|---|
| 2282 | | - interface->debug.root, |
|---|
| 2283 | | - &interface->debug.wmid_devices); |
|---|
| 2284 | | - if (!interface->debug.devices) |
|---|
| 2285 | | - goto error_debugfs; |
|---|
| 2286 | | - |
|---|
| 2287 | | - return 0; |
|---|
| 2288 | | - |
|---|
| 2289 | | -error_debugfs: |
|---|
| 2290 | | - remove_debugfs(); |
|---|
| 2291 | | - return -ENOMEM; |
|---|
| 2247 | + debugfs_create_u32("devices", S_IRUGO, interface->debug.root, |
|---|
| 2248 | + &interface->debug.wmid_devices); |
|---|
| 2292 | 2249 | } |
|---|
| 2293 | 2250 | |
|---|
| 2294 | 2251 | static int __init acer_wmi_init(void) |
|---|
| .. | .. |
|---|
| 2425 | 2382 | |
|---|
| 2426 | 2383 | if (wmi_has_guid(WMID_GUID2)) { |
|---|
| 2427 | 2384 | interface->debug.wmid_devices = get_wmid_devices(); |
|---|
| 2428 | | - err = create_debugfs(); |
|---|
| 2429 | | - if (err) |
|---|
| 2430 | | - goto error_create_debugfs; |
|---|
| 2385 | + create_debugfs(); |
|---|
| 2431 | 2386 | } |
|---|
| 2432 | 2387 | |
|---|
| 2433 | 2388 | /* Override any initial settings with values from the commandline */ |
|---|
| .. | .. |
|---|
| 2435 | 2390 | |
|---|
| 2436 | 2391 | return 0; |
|---|
| 2437 | 2392 | |
|---|
| 2438 | | -error_create_debugfs: |
|---|
| 2439 | | - platform_device_del(acer_platform_device); |
|---|
| 2440 | 2393 | error_device_add: |
|---|
| 2441 | 2394 | platform_device_put(acer_platform_device); |
|---|
| 2442 | 2395 | error_device_alloc: |
|---|