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