1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * lg-laptop.c - LG Gram ACPI features and hotkeys Driver 4 * 5 * Copyright (C) 2018 Matan Ziv-Av <matan@svgalib.org> 6 */ 7 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 10 #include <linux/acpi.h> 11 #include <linux/dmi.h> 12 #include <linux/input.h> 13 #include <linux/input/sparse-keymap.h> 14 #include <linux/kernel.h> 15 #include <linux/leds.h> 16 #include <linux/module.h> 17 #include <linux/platform_device.h> 18 #include <linux/types.h> 19 20 #define LED_DEVICE(_name, max, flag) struct led_classdev _name = { \ 21 .name = __stringify(_name), \ 22 .max_brightness = max, \ 23 .brightness_set = _name##_set, \ 24 .brightness_get = _name##_get, \ 25 .flags = flag, \ 26 } 27 28 MODULE_AUTHOR("Matan Ziv-Av"); 29 MODULE_DESCRIPTION("LG WMI Hotkey Driver"); 30 MODULE_LICENSE("GPL"); 31 32 #define WMI_EVENT_GUID0 "E4FB94F9-7F2B-4173-AD1A-CD1D95086248" 33 #define WMI_EVENT_GUID1 "023B133E-49D1-4E10-B313-698220140DC2" 34 #define WMI_EVENT_GUID2 "37BE1AC0-C3F2-4B1F-BFBE-8FDEAF2814D6" 35 #define WMI_EVENT_GUID3 "911BAD44-7DF8-4FBB-9319-BABA1C4B293B" 36 #define WMI_METHOD_WMAB "C3A72B38-D3EF-42D3-8CBB-D5A57049F66D" 37 #define WMI_METHOD_WMBB "2B4F501A-BD3C-4394-8DCF-00A7D2BC8210" 38 #define WMI_EVENT_GUID WMI_EVENT_GUID0 39 40 #define WMAB_METHOD "\\XINI.WMAB" 41 #define WMBB_METHOD "\\XINI.WMBB" 42 #define SB_GGOV_METHOD "\\_SB.GGOV" 43 #define GOV_TLED 0x2020008 44 #define WM_GET 1 45 #define WM_SET 2 46 #define WM_KEY_LIGHT 0x400 47 #define WM_TLED 0x404 48 #define WM_FN_LOCK 0x407 49 #define WM_BATT_LIMIT 0x61 50 #define WM_READER_MODE 0xBF 51 #define WM_FAN_MODE 0x33 52 #define WMBB_USB_CHARGE 0x10B 53 #define WMBB_BATT_LIMIT 0x10C 54 55 #define PLATFORM_NAME "lg-laptop" 56 57 MODULE_ALIAS("wmi:" WMI_EVENT_GUID0); 58 MODULE_ALIAS("wmi:" WMI_EVENT_GUID1); 59 MODULE_ALIAS("wmi:" WMI_EVENT_GUID2); 60 MODULE_ALIAS("wmi:" WMI_EVENT_GUID3); 61 MODULE_ALIAS("wmi:" WMI_METHOD_WMAB); 62 MODULE_ALIAS("wmi:" WMI_METHOD_WMBB); 63 64 static struct platform_device *pf_device; 65 static struct input_dev *wmi_input_dev; 66 67 static u32 inited; 68 #define INIT_INPUT_WMI_0 0x01 69 #define INIT_INPUT_WMI_2 0x02 70 #define INIT_INPUT_ACPI 0x04 71 #define INIT_SPARSE_KEYMAP 0x80 72 73 static int battery_limit_use_wmbb; 74 static struct led_classdev kbd_backlight; 75 static enum led_brightness get_kbd_backlight_level(void); 76 77 static const struct key_entry wmi_keymap[] = { 78 {KE_KEY, 0x70, {KEY_F15} }, /* LG control panel (F1) */ 79 {KE_KEY, 0x74, {KEY_F21} }, /* Touchpad toggle (F5) */ 80 {KE_KEY, 0xf020000, {KEY_F14} }, /* Read mode (F9) */ 81 {KE_KEY, 0x10000000, {KEY_F16} },/* Keyboard backlight (F8) - pressing 82 * this key both sends an event and 83 * changes backlight level. 84 */ 85 {KE_KEY, 0x80, {KEY_RFKILL} }, 86 {KE_END, 0} 87 }; 88 89 static int ggov(u32 arg0) 90 { 91 union acpi_object args[1]; 92 union acpi_object *r; 93 acpi_status status; 94 acpi_handle handle; 95 struct acpi_object_list arg; 96 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 97 int res; 98 99 args[0].type = ACPI_TYPE_INTEGER; 100 args[0].integer.value = arg0; 101 102 status = acpi_get_handle(NULL, (acpi_string) SB_GGOV_METHOD, &handle); 103 if (ACPI_FAILURE(status)) { 104 pr_err("Cannot get handle"); 105 return -ENODEV; 106 } 107 108 arg.count = 1; 109 arg.pointer = args; 110 111 status = acpi_evaluate_object(handle, NULL, &arg, &buffer); 112 if (ACPI_FAILURE(status)) { 113 acpi_handle_err(handle, "GGOV: call failed.\n"); 114 return -EINVAL; 115 } 116 117 r = buffer.pointer; 118 if (r->type != ACPI_TYPE_INTEGER) { 119 kfree(r); 120 return -EINVAL; 121 } 122 123 res = r->integer.value; 124 kfree(r); 125 126 return res; 127 } 128 129 static union acpi_object *lg_wmab(u32 method, u32 arg1, u32 arg2) 130 { 131 union acpi_object args[3]; 132 acpi_status status; 133 acpi_handle handle; 134 struct acpi_object_list arg; 135 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 136 137 args[0].type = ACPI_TYPE_INTEGER; 138 args[0].integer.value = method; 139 args[1].type = ACPI_TYPE_INTEGER; 140 args[1].integer.value = arg1; 141 args[2].type = ACPI_TYPE_INTEGER; 142 args[2].integer.value = arg2; 143 144 status = acpi_get_handle(NULL, (acpi_string) WMAB_METHOD, &handle); 145 if (ACPI_FAILURE(status)) { 146 pr_err("Cannot get handle"); 147 return NULL; 148 } 149 150 arg.count = 3; 151 arg.pointer = args; 152 153 status = acpi_evaluate_object(handle, NULL, &arg, &buffer); 154 if (ACPI_FAILURE(status)) { 155 acpi_handle_err(handle, "WMAB: call failed.\n"); 156 return NULL; 157 } 158 159 return buffer.pointer; 160 } 161 162 static union acpi_object *lg_wmbb(u32 method_id, u32 arg1, u32 arg2) 163 { 164 union acpi_object args[3]; 165 acpi_status status; 166 acpi_handle handle; 167 struct acpi_object_list arg; 168 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 169 u8 buf[32]; 170 171 *(u32 *)buf = method_id; 172 *(u32 *)(buf + 4) = arg1; 173 *(u32 *)(buf + 16) = arg2; 174 args[0].type = ACPI_TYPE_INTEGER; 175 args[0].integer.value = 0; /* ignored */ 176 args[1].type = ACPI_TYPE_INTEGER; 177 args[1].integer.value = 1; /* Must be 1 or 2. Does not matter which */ 178 args[2].type = ACPI_TYPE_BUFFER; 179 args[2].buffer.length = 32; 180 args[2].buffer.pointer = buf; 181 182 status = acpi_get_handle(NULL, (acpi_string)WMBB_METHOD, &handle); 183 if (ACPI_FAILURE(status)) { 184 pr_err("Cannot get handle"); 185 return NULL; 186 } 187 188 arg.count = 3; 189 arg.pointer = args; 190 191 status = acpi_evaluate_object(handle, NULL, &arg, &buffer); 192 if (ACPI_FAILURE(status)) { 193 acpi_handle_err(handle, "WMAB: call failed.\n"); 194 return NULL; 195 } 196 197 return (union acpi_object *)buffer.pointer; 198 } 199 200 static void wmi_notify(u32 value, void *context) 201 { 202 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 203 union acpi_object *obj; 204 acpi_status status; 205 long data = (long)context; 206 207 pr_debug("event guid %li\n", data); 208 status = wmi_get_event_data(value, &response); 209 if (ACPI_FAILURE(status)) { 210 pr_err("Bad event status 0x%x\n", status); 211 return; 212 } 213 214 obj = (union acpi_object *)response.pointer; 215 if (!obj) 216 return; 217 218 if (obj->type == ACPI_TYPE_INTEGER) { 219 int eventcode = obj->integer.value; 220 struct key_entry *key; 221 222 if (eventcode == 0x10000000) { 223 led_classdev_notify_brightness_hw_changed( 224 &kbd_backlight, get_kbd_backlight_level()); 225 } else { 226 key = sparse_keymap_entry_from_scancode( 227 wmi_input_dev, eventcode); 228 if (key && key->type == KE_KEY) 229 sparse_keymap_report_entry(wmi_input_dev, 230 key, 1, true); 231 } 232 } 233 234 pr_debug("Type: %i Eventcode: 0x%llx\n", obj->type, 235 obj->integer.value); 236 kfree(response.pointer); 237 } 238 239 static void wmi_input_setup(void) 240 { 241 acpi_status status; 242 243 wmi_input_dev = input_allocate_device(); 244 if (wmi_input_dev) { 245 wmi_input_dev->name = "LG WMI hotkeys"; 246 wmi_input_dev->phys = "wmi/input0"; 247 wmi_input_dev->id.bustype = BUS_HOST; 248 249 if (sparse_keymap_setup(wmi_input_dev, wmi_keymap, NULL) || 250 input_register_device(wmi_input_dev)) { 251 pr_info("Cannot initialize input device"); 252 input_free_device(wmi_input_dev); 253 return; 254 } 255 256 inited |= INIT_SPARSE_KEYMAP; 257 status = wmi_install_notify_handler(WMI_EVENT_GUID0, wmi_notify, 258 (void *)0); 259 if (ACPI_SUCCESS(status)) 260 inited |= INIT_INPUT_WMI_0; 261 262 status = wmi_install_notify_handler(WMI_EVENT_GUID2, wmi_notify, 263 (void *)2); 264 if (ACPI_SUCCESS(status)) 265 inited |= INIT_INPUT_WMI_2; 266 } else { 267 pr_info("Cannot allocate input device"); 268 } 269 } 270 271 static void acpi_notify(struct acpi_device *device, u32 event) 272 { 273 struct key_entry *key; 274 275 acpi_handle_debug(device->handle, "notify: %d\n", event); 276 if (inited & INIT_SPARSE_KEYMAP) { 277 key = sparse_keymap_entry_from_scancode(wmi_input_dev, 0x80); 278 if (key && key->type == KE_KEY) 279 sparse_keymap_report_entry(wmi_input_dev, key, 1, true); 280 } 281 } 282 283 static ssize_t fan_mode_store(struct device *dev, 284 struct device_attribute *attr, 285 const char *buffer, size_t count) 286 { 287 bool value; 288 union acpi_object *r; 289 u32 m; 290 int ret; 291 292 ret = kstrtobool(buffer, &value); 293 if (ret) 294 return ret; 295 296 r = lg_wmab(WM_FAN_MODE, WM_GET, 0); 297 if (!r) 298 return -EIO; 299 300 if (r->type != ACPI_TYPE_INTEGER) { 301 kfree(r); 302 return -EIO; 303 } 304 305 m = r->integer.value; 306 kfree(r); 307 r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xffffff0f) | (value << 4)); 308 kfree(r); 309 r = lg_wmab(WM_FAN_MODE, WM_SET, (m & 0xfffffff0) | value); 310 kfree(r); 311 312 return count; 313 } 314 315 static ssize_t fan_mode_show(struct device *dev, 316 struct device_attribute *attr, char *buffer) 317 { 318 unsigned int status; 319 union acpi_object *r; 320 321 r = lg_wmab(WM_FAN_MODE, WM_GET, 0); 322 if (!r) 323 return -EIO; 324 325 if (r->type != ACPI_TYPE_INTEGER) { 326 kfree(r); 327 return -EIO; 328 } 329 330 status = r->integer.value & 0x01; 331 kfree(r); 332 333 return sysfs_emit(buffer, "%d\n", status); 334 } 335 336 static ssize_t usb_charge_store(struct device *dev, 337 struct device_attribute *attr, 338 const char *buffer, size_t count) 339 { 340 bool value; 341 union acpi_object *r; 342 int ret; 343 344 ret = kstrtobool(buffer, &value); 345 if (ret) 346 return ret; 347 348 r = lg_wmbb(WMBB_USB_CHARGE, WM_SET, value); 349 if (!r) 350 return -EIO; 351 352 kfree(r); 353 return count; 354 } 355 356 static ssize_t usb_charge_show(struct device *dev, 357 struct device_attribute *attr, char *buffer) 358 { 359 unsigned int status; 360 union acpi_object *r; 361 362 r = lg_wmbb(WMBB_USB_CHARGE, WM_GET, 0); 363 if (!r) 364 return -EIO; 365 366 if (r->type != ACPI_TYPE_BUFFER) { 367 kfree(r); 368 return -EIO; 369 } 370 371 status = !!r->buffer.pointer[0x10]; 372 373 kfree(r); 374 375 return sysfs_emit(buffer, "%d\n", status); 376 } 377 378 static ssize_t reader_mode_store(struct device *dev, 379 struct device_attribute *attr, 380 const char *buffer, size_t count) 381 { 382 bool value; 383 union acpi_object *r; 384 int ret; 385 386 ret = kstrtobool(buffer, &value); 387 if (ret) 388 return ret; 389 390 r = lg_wmab(WM_READER_MODE, WM_SET, value); 391 if (!r) 392 return -EIO; 393 394 kfree(r); 395 return count; 396 } 397 398 static ssize_t reader_mode_show(struct device *dev, 399 struct device_attribute *attr, char *buffer) 400 { 401 unsigned int status; 402 union acpi_object *r; 403 404 r = lg_wmab(WM_READER_MODE, WM_GET, 0); 405 if (!r) 406 return -EIO; 407 408 if (r->type != ACPI_TYPE_INTEGER) { 409 kfree(r); 410 return -EIO; 411 } 412 413 status = !!r->integer.value; 414 415 kfree(r); 416 417 return sysfs_emit(buffer, "%d\n", status); 418 } 419 420 static ssize_t fn_lock_store(struct device *dev, 421 struct device_attribute *attr, 422 const char *buffer, size_t count) 423 { 424 bool value; 425 union acpi_object *r; 426 int ret; 427 428 ret = kstrtobool(buffer, &value); 429 if (ret) 430 return ret; 431 432 r = lg_wmab(WM_FN_LOCK, WM_SET, value); 433 if (!r) 434 return -EIO; 435 436 kfree(r); 437 return count; 438 } 439 440 static ssize_t fn_lock_show(struct device *dev, 441 struct device_attribute *attr, char *buffer) 442 { 443 unsigned int status; 444 union acpi_object *r; 445 446 r = lg_wmab(WM_FN_LOCK, WM_GET, 0); 447 if (!r) 448 return -EIO; 449 450 if (r->type != ACPI_TYPE_BUFFER) { 451 kfree(r); 452 return -EIO; 453 } 454 455 status = !!r->buffer.pointer[0]; 456 kfree(r); 457 458 return sysfs_emit(buffer, "%d\n", status); 459 } 460 461 static ssize_t battery_care_limit_store(struct device *dev, 462 struct device_attribute *attr, 463 const char *buffer, size_t count) 464 { 465 unsigned long value; 466 int ret; 467 468 ret = kstrtoul(buffer, 10, &value); 469 if (ret) 470 return ret; 471 472 if (value == 100 || value == 80) { 473 union acpi_object *r; 474 475 if (battery_limit_use_wmbb) 476 r = lg_wmbb(WMBB_BATT_LIMIT, WM_SET, value); 477 else 478 r = lg_wmab(WM_BATT_LIMIT, WM_SET, value); 479 if (!r) 480 return -EIO; 481 482 kfree(r); 483 return count; 484 } 485 486 return -EINVAL; 487 } 488 489 static ssize_t battery_care_limit_show(struct device *dev, 490 struct device_attribute *attr, 491 char *buffer) 492 { 493 unsigned int status; 494 union acpi_object *r; 495 496 if (battery_limit_use_wmbb) { 497 r = lg_wmbb(WMBB_BATT_LIMIT, WM_GET, 0); 498 if (!r) 499 return -EIO; 500 501 if (r->type != ACPI_TYPE_BUFFER) { 502 kfree(r); 503 return -EIO; 504 } 505 506 status = r->buffer.pointer[0x10]; 507 } else { 508 r = lg_wmab(WM_BATT_LIMIT, WM_GET, 0); 509 if (!r) 510 return -EIO; 511 512 if (r->type != ACPI_TYPE_INTEGER) { 513 kfree(r); 514 return -EIO; 515 } 516 517 status = r->integer.value; 518 } 519 kfree(r); 520 if (status != 80 && status != 100) 521 status = 0; 522 523 return sysfs_emit(buffer, "%d\n", status); 524 } 525 526 static DEVICE_ATTR_RW(fan_mode); 527 static DEVICE_ATTR_RW(usb_charge); 528 static DEVICE_ATTR_RW(reader_mode); 529 static DEVICE_ATTR_RW(fn_lock); 530 static DEVICE_ATTR_RW(battery_care_limit); 531 532 static struct attribute *dev_attributes[] = { 533 &dev_attr_fan_mode.attr, 534 &dev_attr_usb_charge.attr, 535 &dev_attr_reader_mode.attr, 536 &dev_attr_fn_lock.attr, 537 &dev_attr_battery_care_limit.attr, 538 NULL 539 }; 540 541 static const struct attribute_group dev_attribute_group = { 542 .attrs = dev_attributes, 543 }; 544 545 static void tpad_led_set(struct led_classdev *cdev, 546 enum led_brightness brightness) 547 { 548 union acpi_object *r; 549 550 r = lg_wmab(WM_TLED, WM_SET, brightness > LED_OFF); 551 kfree(r); 552 } 553 554 static enum led_brightness tpad_led_get(struct led_classdev *cdev) 555 { 556 return ggov(GOV_TLED) > 0 ? LED_ON : LED_OFF; 557 } 558 559 static LED_DEVICE(tpad_led, 1, 0); 560 561 static void kbd_backlight_set(struct led_classdev *cdev, 562 enum led_brightness brightness) 563 { 564 u32 val; 565 union acpi_object *r; 566 567 val = 0x22; 568 if (brightness <= LED_OFF) 569 val = 0; 570 if (brightness >= LED_FULL) 571 val = 0x24; 572 r = lg_wmab(WM_KEY_LIGHT, WM_SET, val); 573 kfree(r); 574 } 575 576 static enum led_brightness get_kbd_backlight_level(void) 577 { 578 union acpi_object *r; 579 int val; 580 581 r = lg_wmab(WM_KEY_LIGHT, WM_GET, 0); 582 583 if (!r) 584 return LED_OFF; 585 586 if (r->type != ACPI_TYPE_BUFFER || r->buffer.pointer[1] != 0x05) { 587 kfree(r); 588 return LED_OFF; 589 } 590 591 switch (r->buffer.pointer[0] & 0x27) { 592 case 0x24: 593 val = LED_FULL; 594 break; 595 case 0x22: 596 val = LED_HALF; 597 break; 598 default: 599 val = LED_OFF; 600 } 601 602 kfree(r); 603 604 return val; 605 } 606 607 static enum led_brightness kbd_backlight_get(struct led_classdev *cdev) 608 { 609 return get_kbd_backlight_level(); 610 } 611 612 static LED_DEVICE(kbd_backlight, 255, LED_BRIGHT_HW_CHANGED); 613 614 static void wmi_input_destroy(void) 615 { 616 if (inited & INIT_INPUT_WMI_2) 617 wmi_remove_notify_handler(WMI_EVENT_GUID2); 618 619 if (inited & INIT_INPUT_WMI_0) 620 wmi_remove_notify_handler(WMI_EVENT_GUID0); 621 622 if (inited & INIT_SPARSE_KEYMAP) 623 input_unregister_device(wmi_input_dev); 624 625 inited &= ~(INIT_INPUT_WMI_0 | INIT_INPUT_WMI_2 | INIT_SPARSE_KEYMAP); 626 } 627 628 static struct platform_driver pf_driver = { 629 .driver = { 630 .name = PLATFORM_NAME, 631 } 632 }; 633 634 static int acpi_add(struct acpi_device *device) 635 { 636 int ret; 637 const char *product; 638 int year = 2017; 639 640 if (pf_device) 641 return 0; 642 643 ret = platform_driver_register(&pf_driver); 644 if (ret) 645 return ret; 646 647 pf_device = platform_device_register_simple(PLATFORM_NAME, 648 PLATFORM_DEVID_NONE, 649 NULL, 0); 650 if (IS_ERR(pf_device)) { 651 ret = PTR_ERR(pf_device); 652 pf_device = NULL; 653 pr_err("unable to register platform device\n"); 654 goto out_platform_registered; 655 } 656 product = dmi_get_system_info(DMI_PRODUCT_NAME); 657 if (product && strlen(product) > 4) 658 switch (product[4]) { 659 case '5': 660 case '6': 661 year = 2016; 662 break; 663 case '7': 664 year = 2017; 665 break; 666 case '8': 667 year = 2018; 668 break; 669 case '9': 670 year = 2019; 671 break; 672 case '0': 673 if (strlen(product) > 5) 674 switch (product[5]) { 675 case 'N': 676 year = 2020; 677 break; 678 case 'P': 679 year = 2021; 680 break; 681 default: 682 year = 2022; 683 } 684 break; 685 default: 686 year = 2019; 687 } 688 pr_info("product: %s year: %d\n", product, year); 689 690 if (year >= 2019) 691 battery_limit_use_wmbb = 1; 692 693 ret = sysfs_create_group(&pf_device->dev.kobj, &dev_attribute_group); 694 if (ret) 695 goto out_platform_device; 696 697 /* LEDs are optional */ 698 led_classdev_register(&pf_device->dev, &kbd_backlight); 699 led_classdev_register(&pf_device->dev, &tpad_led); 700 701 wmi_input_setup(); 702 703 return 0; 704 705 out_platform_device: 706 platform_device_unregister(pf_device); 707 out_platform_registered: 708 platform_driver_unregister(&pf_driver); 709 return ret; 710 } 711 712 static int acpi_remove(struct acpi_device *device) 713 { 714 sysfs_remove_group(&pf_device->dev.kobj, &dev_attribute_group); 715 716 led_classdev_unregister(&tpad_led); 717 led_classdev_unregister(&kbd_backlight); 718 719 wmi_input_destroy(); 720 platform_device_unregister(pf_device); 721 pf_device = NULL; 722 platform_driver_unregister(&pf_driver); 723 724 return 0; 725 } 726 727 static const struct acpi_device_id device_ids[] = { 728 {"LGEX0815", 0}, 729 {"", 0} 730 }; 731 MODULE_DEVICE_TABLE(acpi, device_ids); 732 733 static struct acpi_driver acpi_driver = { 734 .name = "LG Gram Laptop Support", 735 .class = "lg-laptop", 736 .ids = device_ids, 737 .ops = { 738 .add = acpi_add, 739 .remove = acpi_remove, 740 .notify = acpi_notify, 741 }, 742 .owner = THIS_MODULE, 743 }; 744 745 static int __init acpi_init(void) 746 { 747 int result; 748 749 result = acpi_bus_register_driver(&acpi_driver); 750 if (result < 0) { 751 pr_debug("Error registering driver\n"); 752 return -ENODEV; 753 } 754 755 return 0; 756 } 757 758 static void __exit acpi_exit(void) 759 { 760 acpi_bus_unregister_driver(&acpi_driver); 761 } 762 763 module_init(acpi_init); 764 module_exit(acpi_exit); 765