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/array_size.h>
12 #include <linux/bitfield.h>
13 #include <linux/bits.h>
14 #include <linux/compiler_attributes.h>
15 #include <linux/cleanup.h>
16 #include <linux/device.h>
17 #include <linux/dev_printk.h>
18 #include <linux/dmi.h>
19 #include <linux/input.h>
20 #include <linux/input/sparse-keymap.h>
21 #include <linux/kernel.h>
22 #include <linux/leds.h>
23 #include <linux/limits.h>
24 #include <linux/module.h>
25 #include <linux/platform_device.h>
26 #include <linux/string_choices.h>
27 #include <linux/types.h>
28 #include <linux/unaligned.h>
29
30 #include <acpi/battery.h>
31
32 #define LED_DEVICE(_name, max, flag) struct led_classdev _name = { \
33 .name = __stringify(_name), \
34 .max_brightness = max, \
35 .brightness_set = _name##_set, \
36 .brightness_get = _name##_get, \
37 .flags = flag, \
38 }
39
40 MODULE_AUTHOR("Matan Ziv-Av");
41 MODULE_DESCRIPTION("LG WMI Hotkey Driver");
42 MODULE_LICENSE("GPL");
43
44 static bool fw_debug;
45 module_param(fw_debug, bool, 0);
46 MODULE_PARM_DESC(fw_debug, "Enable printing of firmware debug messages");
47
48 #define LG_ADDRESS_SPACE_ID 0x8F
49
50 #define LG_ADDRESS_SPACE_DEBUG_FLAG_ADR 0x00
51 #define LG_ADDRESS_SPACE_HD_AUDIO_POWER_ADDR 0x01
52 #define LG_ADDRESS_SPACE_FAN_MODE_ADR 0x03
53
54 #define LG_ADDRESS_SPACE_DTTM_FLAG_ADR 0x20
55 #define LG_ADDRESS_SPACE_CPU_TEMP_ADR 0x21
56 #define LG_ADDRESS_SPACE_CPU_TRIP_LOW_ADR 0x22
57 #define LG_ADDRESS_SPACE_CPU_TRIP_HIGH_ADR 0x23
58 #define LG_ADDRESS_SPACE_MB_TEMP_ADR 0x24
59 #define LG_ADDRESS_SPACE_MB_TRIP_LOW_ADR 0x25
60 #define LG_ADDRESS_SPACE_MB_TRIP_HIGH_ADR 0x26
61
62 #define LG_ADDRESS_SPACE_DEBUG_MSG_START_ADR 0x3E8
63 #define LG_ADDRESS_SPACE_DEBUG_MSG_END_ADR 0x5E8
64
65 #define LG_NOTIFY_TABLET_MODE_OFF 0x50
66 #define LG_NOTIFY_TABLET_MODE_ON 0x51
67 #define LG_NOTIFY_HOTKEY 0x80
68 #define LG_NOTIFY_THERMAL 0x81
69 #define LG_NOTIFY_MISC 0x82
70
71 #define LG_OREP_READ_EC 0
72 #define LG_OREP_WRITE_EC 1
73 #define LG_OREP_DEBUG 2
74 #define LG_OREP_UPDATE_SYSTEM_STATE 3
75 #define LG_OREP_INTERCEPT_WMI_EVENTS 4
76 #define LG_OREP_WAKE_ON_LAN 6
77
78 #define SB_GGOV_METHOD "\\_SB.GGOV"
79 #define GOV_TLED 0x2020008
80 #define WM_GET 1
81 #define WM_SET 2
82 #define WM_KEY_LIGHT 0x400
83 #define WM_TLED 0x404
84 #define WM_FN_LOCK 0x407
85 #define WM_BATT_LIMIT 0x61
86 #define WM_READER_MODE 0xBF
87 #define WM_FAN_MODE 0x33
88 #define WMBB_USB_CHARGE 0x10B
89 #define WMBB_BATT_LIMIT 0x10C
90
91 #define KBD_LED_BRIGHTNESS_MASK GENMASK(4, 0)
92 #define KBD_LED_BRIGHTNESS_OFF 0x0
93 #define KBD_LED_BRIGHTNESS_HALF 0x2
94 #define KBD_LED_BRIGHTNESS_FULL 0x4
95 #define KBD_LED_MODE_MASK GENMASK(6, 5)
96 #define KBD_LED_MODE_OFF 0x0
97 #define KBD_LED_MODE_ON 0x1
98 #define KBD_LED_STATUS BIT(7)
99 #define KBD_LED_MAGIC_MASK GENMASK(15, 8)
100 /* Exact purpose is unknown, maybe some sort of brightness limit? */
101 #define KBD_LED_MAGIC 0x05
102
103 #define FAN_MODE_LOWER GENMASK(1, 0)
104 #define FAN_MODE_UPPER GENMASK(5, 4)
105
106 #define PLATFORM_NAME "lg-laptop"
107
108 struct lg_wmab_buffer_result {
109 __le32 value;
110 __le32 status;
111 } __packed;
112
113 static struct platform_device *pf_device;
114
115 static int battery_limit_use_wmbb;
116 static bool kbd_backlight_available;
117 static struct led_classdev kbd_backlight;
118 static enum led_brightness get_kbd_backlight_level(struct device *dev);
119
120 static const struct key_entry wmi_keymap[] = {
121 /* Placeholder value send by multiple hotkeys handled by ACPI */
122 { KE_IGNORE, 0x0, { KEY_UNKNOWN }},
123 /* LG control panel */
124 { KE_KEY, 0x70, { KEY_F15 }},
125 /* Touchpad toggle */
126 { KE_KEY, 0x74, { KEY_F21 }},
127 /* Mute Audio, already handled by ACPI */
128 { KE_IGNORE, 0x78, { KEY_MUTE }},
129 /* Read mode */
130 { KE_KEY, 0xf020000, { KEY_F14 }},
131 /* Open settings */
132 { KE_KEY, 0xf070002, { KEY_CONFIG }},
133 /* Keyboard backlight - pressing this key both sends an event and changes backlight level */
134 { KE_KEY, 0x10000000, { KEY_F16 }},
135 /* Hotkey combination pressed */
136 { KE_IGNORE, 0x30010000, { KEY_UNKNOWN }},
137 /* Hotkey combination released */
138 { KE_IGNORE, 0x30010001, { KEY_UNKNOWN }},
139 /* Change fan mode */
140 { KE_KEY, 0x30010051, { KEY_PERFORMANCE }},
141 /* Disable camera */
142 { KE_KEY, 0x40020000, { KEY_CAMERA_ACCESS_TOGGLE }},
143 /* Mute microphone */
144 { KE_KEY, 0x40020001, { KEY_MICMUTE }},
145 /* Fn-Lock */
146 { KE_KEY, 0x40030001, { KEY_FN_ESC }},
147 {KE_END, 0}
148 };
149
lg_laptop_execute_orep(acpi_handle handle,u64 command,u64 value,unsigned long long * result)150 static int lg_laptop_execute_orep(acpi_handle handle, u64 command, u64 value,
151 unsigned long long *result)
152 {
153 union acpi_object objs[] = {
154 {
155 .integer = {
156 .type = ACPI_TYPE_INTEGER,
157 .value = command,
158 },
159 },
160 {
161 .integer = {
162 .type = ACPI_TYPE_INTEGER,
163 .value = value,
164 },
165 }
166 };
167 struct acpi_object_list args = {
168 .count = ARRAY_SIZE(objs),
169 .pointer = objs,
170 };
171 acpi_status status;
172
173 status = acpi_evaluate_integer(handle, "OREP", &args, result);
174 if (ACPI_FAILURE(status))
175 return -EIO;
176
177 return 0;
178 }
179
ggov(u32 arg0)180 static int ggov(u32 arg0)
181 {
182 union acpi_object args[1];
183 union acpi_object *r;
184 acpi_status status;
185 acpi_handle handle;
186 struct acpi_object_list arg;
187 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
188 int res;
189
190 args[0].type = ACPI_TYPE_INTEGER;
191 args[0].integer.value = arg0;
192
193 status = acpi_get_handle(NULL, (acpi_string) SB_GGOV_METHOD, &handle);
194 if (ACPI_FAILURE(status)) {
195 pr_err("Cannot get handle");
196 return -ENODEV;
197 }
198
199 arg.count = 1;
200 arg.pointer = args;
201
202 status = acpi_evaluate_object(handle, NULL, &arg, &buffer);
203 if (ACPI_FAILURE(status)) {
204 acpi_handle_err(handle, "GGOV: call failed.\n");
205 return -EINVAL;
206 }
207
208 r = buffer.pointer;
209 if (r->type != ACPI_TYPE_INTEGER) {
210 kfree(r);
211 return -EINVAL;
212 }
213
214 res = r->integer.value;
215 kfree(r);
216
217 return res;
218 }
219
lg_wmab_get(struct device * dev,u32 method,u32 * result)220 static int lg_wmab_get(struct device *dev, u32 method, u32 *result)
221 {
222 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
223 union acpi_object in[] = {
224 {
225 .integer = {
226 .type = ACPI_TYPE_INTEGER,
227 .value = method,
228 },
229 },
230 {
231 .integer = {
232 .type = ACPI_TYPE_INTEGER,
233 .value = WM_GET,
234 },
235 },
236 {
237 .integer = {
238 .type = ACPI_TYPE_INTEGER,
239 .value = 0,
240 },
241 },
242 };
243 struct lg_wmab_buffer_result *buffer_result;
244 struct acpi_object_list input = {
245 .count = ARRAY_SIZE(in),
246 .pointer = in,
247 };
248 acpi_status status;
249
250 status = acpi_evaluate_object(ACPI_HANDLE(dev), "WMAB", &input, &buffer);
251 if (ACPI_FAILURE(status))
252 return -EIO;
253
254 union acpi_object *obj __free(kfree) = buffer.pointer;
255
256 if (!obj)
257 return -ENODATA;
258
259 switch (obj->type) {
260 case ACPI_TYPE_INTEGER:
261 *result = obj->integer.value;
262 return 0;
263 case ACPI_TYPE_BUFFER:
264 if (obj->buffer.length != sizeof(*buffer_result))
265 return -EPROTO;
266
267 buffer_result = (struct lg_wmab_buffer_result *)obj->buffer.pointer;
268 if (get_unaligned_le32(&buffer_result->status))
269 return -EIO;
270
271 *result = get_unaligned_le32(&buffer_result->value);
272 return 0;
273 default:
274 return -EPROTO;
275 }
276 }
277
lg_wmab_set(struct device * dev,u32 method,u32 arg)278 static int lg_wmab_set(struct device *dev, u32 method, u32 arg)
279 {
280 union acpi_object in[] = {
281 {
282 .integer = {
283 .type = ACPI_TYPE_INTEGER,
284 .value = method,
285 },
286 },
287 {
288 .integer = {
289 .type = ACPI_TYPE_INTEGER,
290 .value = WM_SET,
291 },
292 },
293 {
294 .integer = {
295 .type = ACPI_TYPE_INTEGER,
296 .value = arg,
297 },
298 },
299 };
300 struct acpi_object_list input = {
301 .count = ARRAY_SIZE(in),
302 .pointer = in,
303 };
304 acpi_status status;
305
306 status = acpi_evaluate_object(ACPI_HANDLE(dev), "WMAB", &input, NULL);
307 if (ACPI_FAILURE(status))
308 return -EIO;
309
310 return 0;
311 }
312
lg_wmbb(struct device * dev,u32 method_id,u32 arg1,u32 arg2)313 static union acpi_object *lg_wmbb(struct device *dev, u32 method_id, u32 arg1, u32 arg2)
314 {
315 union acpi_object args[3];
316 acpi_status status;
317 struct acpi_object_list arg;
318 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
319 u8 buf[32];
320
321 *(u32 *)buf = method_id;
322 *(u32 *)(buf + 4) = arg1;
323 *(u32 *)(buf + 16) = arg2;
324 args[0].type = ACPI_TYPE_INTEGER;
325 args[0].integer.value = 0; /* ignored */
326 args[1].type = ACPI_TYPE_INTEGER;
327 args[1].integer.value = 1; /* Must be 1 or 2. Does not matter which */
328 args[2].type = ACPI_TYPE_BUFFER;
329 args[2].buffer.length = 32;
330 args[2].buffer.pointer = buf;
331
332 arg.count = 3;
333 arg.pointer = args;
334
335 status = acpi_evaluate_object(ACPI_HANDLE(dev), "WMBB", &arg, &buffer);
336 if (ACPI_FAILURE(status)) {
337 dev_err(dev, "WMBB: call failed.\n");
338 return NULL;
339 }
340
341 return (union acpi_object *)buffer.pointer;
342 }
343
fan_mode_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)344 static ssize_t fan_mode_store(struct device *dev,
345 struct device_attribute *attr,
346 const char *buffer, size_t count)
347 {
348 unsigned long value;
349 int ret;
350
351 ret = kstrtoul(buffer, 10, &value);
352 if (ret)
353 return ret;
354 if (value >= 3)
355 return -EINVAL;
356
357 ret = lg_wmab_set(dev, WM_FAN_MODE, FIELD_PREP(FAN_MODE_LOWER, value) |
358 FIELD_PREP(FAN_MODE_UPPER, value));
359 if (ret < 0)
360 return ret;
361
362 return count;
363 }
364
fan_mode_show(struct device * dev,struct device_attribute * attr,char * buffer)365 static ssize_t fan_mode_show(struct device *dev,
366 struct device_attribute *attr, char *buffer)
367 {
368 u32 mode;
369 int ret;
370
371 ret = lg_wmab_get(dev, WM_FAN_MODE, &mode);
372 if (ret < 0)
373 return ret;
374
375 return sysfs_emit(buffer, "%lu\n", FIELD_GET(FAN_MODE_LOWER, mode));
376 }
377
usb_charge_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)378 static ssize_t usb_charge_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_wmbb(dev, WMBB_USB_CHARGE, WM_SET, value);
391 if (!r)
392 return -EIO;
393
394 kfree(r);
395 return count;
396 }
397
usb_charge_show(struct device * dev,struct device_attribute * attr,char * buffer)398 static ssize_t usb_charge_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_wmbb(dev, WMBB_USB_CHARGE, WM_GET, 0);
405 if (!r)
406 return -EIO;
407
408 if (r->type != ACPI_TYPE_BUFFER) {
409 kfree(r);
410 return -EIO;
411 }
412
413 status = !!r->buffer.pointer[0x10];
414
415 kfree(r);
416
417 return sysfs_emit(buffer, "%d\n", status);
418 }
419
reader_mode_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)420 static ssize_t reader_mode_store(struct device *dev,
421 struct device_attribute *attr,
422 const char *buffer, size_t count)
423 {
424 bool value;
425 int ret;
426
427 ret = kstrtobool(buffer, &value);
428 if (ret)
429 return ret;
430
431 ret = lg_wmab_set(dev, WM_READER_MODE, value);
432 if (ret < 0)
433 return ret;
434
435 return count;
436 }
437
reader_mode_show(struct device * dev,struct device_attribute * attr,char * buffer)438 static ssize_t reader_mode_show(struct device *dev,
439 struct device_attribute *attr, char *buffer)
440 {
441 u32 status;
442 int ret;
443
444 ret = lg_wmab_get(dev, WM_READER_MODE, &status);
445 if (ret < 0)
446 return ret;
447
448 return sysfs_emit(buffer, "%d\n", !!status);
449 }
450
fn_lock_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)451 static ssize_t fn_lock_store(struct device *dev,
452 struct device_attribute *attr,
453 const char *buffer, size_t count)
454 {
455 bool value;
456 int ret;
457
458 ret = kstrtobool(buffer, &value);
459 if (ret)
460 return ret;
461
462 ret = lg_wmab_set(dev, WM_FN_LOCK, value);
463 if (ret < 0)
464 return ret;
465
466 return count;
467 }
468
fn_lock_show(struct device * dev,struct device_attribute * attr,char * buffer)469 static ssize_t fn_lock_show(struct device *dev,
470 struct device_attribute *attr, char *buffer)
471 {
472 u32 status;
473 int ret;
474
475 ret = lg_wmab_get(dev, WM_FN_LOCK, &status);
476 if (ret < 0)
477 return ret;
478
479 return sysfs_emit(buffer, "%d\n", !!status);
480 }
481
charge_control_end_threshold_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)482 static ssize_t charge_control_end_threshold_store(struct device *dev,
483 struct device_attribute *attr,
484 const char *buf, size_t count)
485 {
486 unsigned long value;
487 int ret;
488
489 ret = kstrtoul(buf, 10, &value);
490 if (ret)
491 return ret;
492
493 if (value == 100 || value == 80) {
494 union acpi_object *r;
495
496 if (battery_limit_use_wmbb) {
497 r = lg_wmbb(&pf_device->dev, WMBB_BATT_LIMIT, WM_SET, value);
498 if (!r)
499 return -EIO;
500
501 kfree(r);
502 } else {
503 ret = lg_wmab_set(&pf_device->dev, WM_BATT_LIMIT, value);
504 if (ret < 0)
505 return ret;
506 }
507
508 return count;
509 }
510
511 return -EINVAL;
512 }
513
charge_control_end_threshold_show(struct device * device,struct device_attribute * attr,char * buf)514 static ssize_t charge_control_end_threshold_show(struct device *device,
515 struct device_attribute *attr,
516 char *buf)
517 {
518 union acpi_object *r;
519 u32 status;
520 int ret;
521
522 if (battery_limit_use_wmbb) {
523 r = lg_wmbb(&pf_device->dev, WMBB_BATT_LIMIT, WM_GET, 0);
524 if (!r)
525 return -EIO;
526
527 if (r->type != ACPI_TYPE_BUFFER) {
528 kfree(r);
529 return -EIO;
530 }
531
532 status = r->buffer.pointer[0x10];
533 kfree(r);
534 } else {
535 ret = lg_wmab_get(&pf_device->dev, WM_BATT_LIMIT, &status);
536 if (ret < 0)
537 return ret;
538 }
539
540 if (status != 80 && status != 100)
541 status = 0;
542
543 return sysfs_emit(buf, "%d\n", status);
544 }
545
battery_care_limit_show(struct device * dev,struct device_attribute * attr,char * buffer)546 static ssize_t battery_care_limit_show(struct device *dev,
547 struct device_attribute *attr,
548 char *buffer)
549 {
550 return charge_control_end_threshold_show(dev, attr, buffer);
551 }
552
battery_care_limit_store(struct device * dev,struct device_attribute * attr,const char * buffer,size_t count)553 static ssize_t battery_care_limit_store(struct device *dev,
554 struct device_attribute *attr,
555 const char *buffer, size_t count)
556 {
557 return charge_control_end_threshold_store(dev, attr, buffer, count);
558 }
559
560 static DEVICE_ATTR_RW(fan_mode);
561 static DEVICE_ATTR_RW(usb_charge);
562 static DEVICE_ATTR_RW(reader_mode);
563 static DEVICE_ATTR_RW(fn_lock);
564 static DEVICE_ATTR_RW(charge_control_end_threshold);
565 static DEVICE_ATTR_RW(battery_care_limit);
566
lg_battery_add(struct power_supply * battery,struct acpi_battery_hook * hook)567 static int lg_battery_add(struct power_supply *battery, struct acpi_battery_hook *hook)
568 {
569 if (device_create_file(&battery->dev,
570 &dev_attr_charge_control_end_threshold))
571 return -ENODEV;
572
573 return 0;
574 }
575
lg_battery_remove(struct power_supply * battery,struct acpi_battery_hook * hook)576 static int lg_battery_remove(struct power_supply *battery, struct acpi_battery_hook *hook)
577 {
578 device_remove_file(&battery->dev,
579 &dev_attr_charge_control_end_threshold);
580 return 0;
581 }
582
583 static struct acpi_battery_hook battery_hook = {
584 .add_battery = lg_battery_add,
585 .remove_battery = lg_battery_remove,
586 .name = "LG Battery Extension",
587 };
588
589 static struct attribute *dev_attributes[] = {
590 &dev_attr_fan_mode.attr,
591 &dev_attr_usb_charge.attr,
592 &dev_attr_reader_mode.attr,
593 &dev_attr_fn_lock.attr,
594 &dev_attr_battery_care_limit.attr,
595 NULL
596 };
597
598 static const struct attribute_group dev_attribute_group = {
599 .attrs = dev_attributes,
600 };
601
tpad_led_set(struct led_classdev * cdev,enum led_brightness brightness)602 static void tpad_led_set(struct led_classdev *cdev,
603 enum led_brightness brightness)
604 {
605 lg_wmab_set(cdev->dev->parent, WM_TLED, brightness > LED_OFF);
606 }
607
tpad_led_get(struct led_classdev * cdev)608 static enum led_brightness tpad_led_get(struct led_classdev *cdev)
609 {
610 return ggov(GOV_TLED) > 0 ? LED_ON : LED_OFF;
611 }
612
613 static LED_DEVICE(tpad_led, 1, 0);
614
kbd_backlight_set(struct led_classdev * cdev,enum led_brightness brightness)615 static void kbd_backlight_set(struct led_classdev *cdev,
616 enum led_brightness brightness)
617 {
618 /* Must always be written */
619 u32 value = KBD_LED_STATUS;
620 u32 mode, bright;
621
622 if (brightness <= LED_OFF) {
623 mode = KBD_LED_MODE_OFF;
624 bright = KBD_LED_BRIGHTNESS_OFF;
625 } else {
626 mode = KBD_LED_MODE_ON;
627 if (brightness >= LED_FULL)
628 bright = KBD_LED_BRIGHTNESS_FULL;
629 else
630 bright = KBD_LED_BRIGHTNESS_HALF;
631 }
632
633 value |= FIELD_PREP(KBD_LED_BRIGHTNESS_MASK, bright);
634 value |= FIELD_PREP(KBD_LED_MODE_MASK, mode);
635
636 lg_wmab_set(cdev->dev->parent, WM_KEY_LIGHT, value);
637 }
638
get_kbd_backlight_level(struct device * dev)639 static enum led_brightness get_kbd_backlight_level(struct device *dev)
640 {
641 u32 value;
642 int ret;
643
644 ret = lg_wmab_get(dev, WM_KEY_LIGHT, &value);
645 if (ret < 0)
646 return LED_OFF;
647
648 if (FIELD_GET(KBD_LED_MAGIC_MASK, value) != KBD_LED_MAGIC)
649 return LED_OFF;
650
651 if (FIELD_GET(KBD_LED_MODE_MASK, value) == KBD_LED_MODE_OFF)
652 return LED_OFF;
653
654 switch (FIELD_GET(KBD_LED_BRIGHTNESS_MASK, value)) {
655 case KBD_LED_BRIGHTNESS_FULL:
656 return LED_FULL;
657 case KBD_LED_BRIGHTNESS_HALF:
658 return LED_HALF;
659 default:
660 return LED_OFF;
661 }
662 }
663
kbd_backlight_get(struct led_classdev * cdev)664 static enum led_brightness kbd_backlight_get(struct led_classdev *cdev)
665 {
666 return get_kbd_backlight_level(cdev->dev->parent);
667 }
668
669 static LED_DEVICE(kbd_backlight, 255, LED_BRIGHT_HW_CHANGED);
670
671 static struct platform_driver pf_driver = {
672 .driver = {
673 .name = PLATFORM_NAME,
674 }
675 };
676
lg_laptop_get_event_data(acpi_handle handle,u32 value,u32 * data)677 static int lg_laptop_get_event_data(acpi_handle handle, u32 value, u32 *data)
678 {
679 union acpi_object objs[] = {
680 {
681 .integer = {
682 .type = ACPI_TYPE_INTEGER,
683 .value = value,
684 },
685 }
686 };
687 struct acpi_object_list args = {
688 .count = ARRAY_SIZE(objs),
689 .pointer = objs,
690 };
691 unsigned long long result;
692 acpi_status status;
693
694 status = acpi_evaluate_integer(handle, "_WED", &args, &result);
695 if (ACPI_FAILURE(status))
696 return -EIO;
697
698 if (result > U32_MAX)
699 return -EPROTO;
700
701 *data = result;
702
703 return 0;
704 }
705
lg_laptop_handle_input_event(struct input_dev * input_dev,u32 value,u32 data)706 static void lg_laptop_handle_input_event(struct input_dev *input_dev, u32 value, u32 data)
707 {
708 unsigned int kbd_brightness;
709
710 switch (value) {
711 case LG_NOTIFY_HOTKEY:
712 sparse_keymap_report_event(input_dev, data, 1, true);
713 break;
714 case LG_NOTIFY_THERMAL:
715 /* Currently not supported */
716 break;
717 case LG_NOTIFY_MISC:
718 switch (data) {
719 case 0x10000000:
720 if (!kbd_backlight_available)
721 break;
722
723 kbd_brightness = get_kbd_backlight_level(kbd_backlight.dev->parent);
724 led_classdev_notify_brightness_hw_changed(&kbd_backlight, kbd_brightness);
725 break;
726 default:
727 sparse_keymap_report_event(input_dev, data, 1, true);
728 }
729 break;
730 default:
731 break;
732 }
733 }
734
lg_laptop_notify_handler(acpi_handle handle,u32 value,void * context)735 static void lg_laptop_notify_handler(acpi_handle handle, u32 value, void *context)
736 {
737 struct input_dev *input_dev = context;
738 u32 data;
739 int ret;
740
741 switch (value) {
742 case LG_NOTIFY_TABLET_MODE_OFF:
743 case LG_NOTIFY_TABLET_MODE_ON:
744 /* Already handled by intel-hid */
745 return;
746 case LG_NOTIFY_HOTKEY:
747 case LG_NOTIFY_THERMAL:
748 case LG_NOTIFY_MISC:
749 ret = lg_laptop_get_event_data(handle, value, &data);
750 if (ret < 0) {
751 dev_notice(input_dev->dev.parent, "Failed to get event data: %d\n", ret);
752 return;
753 }
754
755 dev_dbg(input_dev->dev.parent, "Received event %u (%u)\n", value, data);
756
757 lg_laptop_handle_input_event(input_dev, value, data);
758 return;
759 default:
760 dev_notice(input_dev->dev.parent, "Received unknown event %u\n", value);
761 }
762 };
763
lg_laptop_remove_notify_handler(void * context)764 static void lg_laptop_remove_notify_handler(void *context)
765 {
766 acpi_handle handle = context;
767
768 acpi_remove_notify_handler(handle, ACPI_ALL_NOTIFY, lg_laptop_notify_handler);
769 }
770
lg_laptop_reenable_wmi_events(void * context)771 static void lg_laptop_reenable_wmi_events(void *context)
772 {
773 acpi_handle handle = context;
774 unsigned long long dummy;
775
776 lg_laptop_execute_orep(handle, LG_OREP_INTERCEPT_WMI_EVENTS, 0, &dummy);
777 }
778
lg_laptop_input_init(struct device * dev,acpi_handle handle)779 static int lg_laptop_input_init(struct device *dev, acpi_handle handle)
780 {
781 struct input_dev *input_dev;
782 unsigned long long result;
783 acpi_status status;
784 int ret;
785
786 if (!acpi_has_method(handle, "_WED"))
787 return 0;
788
789 input_dev = devm_input_allocate_device(dev);
790 if (!input_dev)
791 return -ENOMEM;
792
793 input_dev->name = "LG WMI hotkeys";
794 input_dev->phys = "wmi/input0";
795 input_dev->id.bustype = BUS_HOST;
796 ret = sparse_keymap_setup(input_dev, wmi_keymap, NULL);
797 if (ret < 0)
798 return ret;
799
800 ret = input_register_device(input_dev);
801 if (ret < 0)
802 return ret;
803
804 status = acpi_install_notify_handler(handle, ACPI_ALL_NOTIFY, lg_laptop_notify_handler,
805 input_dev);
806 if (ACPI_FAILURE(status))
807 return -EIO;
808
809 ret = devm_add_action_or_reset(dev, lg_laptop_remove_notify_handler, handle);
810 if (ret < 0)
811 return ret;
812
813 if (acpi_has_method(handle, "OREP")) {
814 ret = lg_laptop_execute_orep(handle, LG_OREP_INTERCEPT_WMI_EVENTS, 1, &result);
815 if (ret < 0)
816 return ret;
817 if (result)
818 return -EIO;
819
820 ret = devm_add_action_or_reset(dev, lg_laptop_reenable_wmi_events, handle);
821 if (ret < 0)
822 return ret;
823 }
824
825 return 0;
826 }
827
lg_laptop_address_space_write(struct device * dev,acpi_physical_address address,size_t size,u64 value)828 static acpi_status lg_laptop_address_space_write(struct device *dev, acpi_physical_address address,
829 size_t size, u64 value)
830 {
831 u8 byte;
832
833 /* Ignore any debug messages */
834 if (address >= LG_ADDRESS_SPACE_DEBUG_MSG_START_ADR &&
835 address <= LG_ADDRESS_SPACE_DEBUG_MSG_END_ADR)
836 return AE_OK;
837
838 if (size != sizeof(byte))
839 return AE_BAD_PARAMETER;
840
841 byte = value & 0xFF;
842
843 switch (address) {
844 case LG_ADDRESS_SPACE_HD_AUDIO_POWER_ADDR:
845 /*
846 * The HD audio power field is not affected by the DTTM flag,
847 * so we have to manually check fw_debug.
848 */
849 if (fw_debug)
850 dev_dbg(dev, "HD audio power %s\n", str_enabled_disabled(byte));
851
852 return AE_OK;
853 case LG_ADDRESS_SPACE_FAN_MODE_ADR:
854 /*
855 * The fan mode field is not affected by the DTTM flag, so we
856 * have to manually check fw_debug.
857 */
858 if (fw_debug)
859 dev_dbg(dev, "Fan mode set to mode %u\n", byte);
860
861 return AE_OK;
862 case LG_ADDRESS_SPACE_CPU_TEMP_ADR:
863 dev_dbg(dev, "CPU temperature is %u °C\n", byte);
864 return AE_OK;
865 case LG_ADDRESS_SPACE_CPU_TRIP_LOW_ADR:
866 dev_dbg(dev, "CPU lower trip point set to %u °C\n", byte);
867 return AE_OK;
868 case LG_ADDRESS_SPACE_CPU_TRIP_HIGH_ADR:
869 dev_dbg(dev, "CPU higher trip point set to %u °C\n", byte);
870 return AE_OK;
871 case LG_ADDRESS_SPACE_MB_TEMP_ADR:
872 dev_dbg(dev, "Motherboard temperature is %u °C\n", byte);
873 return AE_OK;
874 case LG_ADDRESS_SPACE_MB_TRIP_LOW_ADR:
875 dev_dbg(dev, "Motherboard lower trip point set to %u °C\n", byte);
876 return AE_OK;
877 case LG_ADDRESS_SPACE_MB_TRIP_HIGH_ADR:
878 dev_dbg(dev, "Motherboard higher trip point set to %u °C\n", byte);
879 return AE_OK;
880 default:
881 dev_notice_ratelimited(dev, "Ignoring write to unknown opregion address %llu\n",
882 address);
883 return AE_OK;
884 }
885 }
886
lg_laptop_address_space_read(struct device * dev,acpi_physical_address address,size_t size,u64 * value)887 static acpi_status lg_laptop_address_space_read(struct device *dev, acpi_physical_address address,
888 size_t size, u64 *value)
889 {
890 if (size != 1)
891 return AE_BAD_PARAMETER;
892
893 switch (address) {
894 case LG_ADDRESS_SPACE_DEBUG_FLAG_ADR:
895 /* Debug messages are already printed using the standard ACPI Debug object */
896 *value = 0x00;
897 return AE_OK;
898 case LG_ADDRESS_SPACE_DTTM_FLAG_ADR:
899 *value = fw_debug;
900 return AE_OK;
901 default:
902 dev_notice_ratelimited(dev, "Attempt to read unknown opregion address %llu\n",
903 address);
904 return AE_BAD_PARAMETER;
905 }
906 }
907
lg_laptop_address_space_handler(u32 function,acpi_physical_address address,u32 bits,u64 * value,void * handler_context,void * region_context)908 static acpi_status lg_laptop_address_space_handler(u32 function, acpi_physical_address address,
909 u32 bits, u64 *value, void *handler_context,
910 void *region_context)
911 {
912 struct device *dev = handler_context;
913 size_t size;
914
915 if (bits % BITS_PER_BYTE)
916 return AE_BAD_PARAMETER;
917
918 size = bits / BITS_PER_BYTE;
919
920 switch (function) {
921 case ACPI_READ:
922 return lg_laptop_address_space_read(dev, address, size, value);
923 case ACPI_WRITE:
924 return lg_laptop_address_space_write(dev, address, size, *value);
925 default:
926 return AE_BAD_PARAMETER;
927 }
928 }
929
lg_laptop_remove_address_space_handler(void * data)930 static void lg_laptop_remove_address_space_handler(void *data)
931 {
932 struct acpi_device *device = data;
933
934 acpi_remove_address_space_handler(device->handle, LG_ADDRESS_SPACE_ID,
935 &lg_laptop_address_space_handler);
936 }
937
acpi_probe(struct platform_device * pdev)938 static int acpi_probe(struct platform_device *pdev)
939 {
940 struct platform_device_info pdev_info = {
941 .name = PLATFORM_NAME,
942 .id = PLATFORM_DEVID_NONE,
943 };
944 struct acpi_device *device;
945 acpi_status status;
946 int ret;
947 const char *product;
948 int year = 2017;
949
950 if (pf_device)
951 return 0;
952
953 device = ACPI_COMPANION(&pdev->dev);
954 if (!device)
955 return -ENODEV;
956
957 pdev_info.fwnode = acpi_fwnode_handle(device),
958
959 status = acpi_install_address_space_handler(device->handle, LG_ADDRESS_SPACE_ID,
960 &lg_laptop_address_space_handler,
961 NULL, &pdev->dev);
962 if (ACPI_FAILURE(status))
963 return -ENODEV;
964
965 ret = devm_add_action_or_reset(&pdev->dev, lg_laptop_remove_address_space_handler,
966 device);
967 if (ret < 0)
968 return ret;
969
970 ret = platform_driver_register(&pf_driver);
971 if (ret)
972 return ret;
973
974 pf_device = platform_device_register_full(&pdev_info);
975 if (IS_ERR(pf_device)) {
976 ret = PTR_ERR(pf_device);
977 pf_device = NULL;
978 pr_err("unable to register platform device\n");
979 goto out_platform_registered;
980 }
981 product = dmi_get_system_info(DMI_PRODUCT_NAME);
982 if (product && strlen(product) > 4)
983 switch (product[4]) {
984 case '5':
985 if (strlen(product) > 5)
986 switch (product[5]) {
987 case 'N':
988 year = 2021;
989 break;
990 case '0':
991 year = 2016;
992 break;
993 default:
994 year = 2022;
995 }
996 break;
997 case '6':
998 year = 2016;
999 break;
1000 case '7':
1001 year = 2017;
1002 break;
1003 case '8':
1004 year = 2018;
1005 break;
1006 case '9':
1007 year = 2019;
1008 break;
1009 case '0':
1010 if (strlen(product) > 5)
1011 switch (product[5]) {
1012 case 'N':
1013 year = 2020;
1014 break;
1015 case 'P':
1016 year = 2021;
1017 break;
1018 case 'Q':
1019 year = 2022;
1020 break;
1021 case 'R':
1022 year = 2023;
1023 break;
1024 case 'S':
1025 year = 2024;
1026 break;
1027 default:
1028 year = 2025;
1029 }
1030 break;
1031 default:
1032 year = 2019;
1033 }
1034 pr_info("product: %s year: %d\n", product ?: "unknown", year);
1035
1036 if (year >= 2019)
1037 battery_limit_use_wmbb = 1;
1038
1039 /* LEDs are optional */
1040 ret = devm_led_classdev_register(&pdev->dev, &kbd_backlight);
1041 if (ret < 0)
1042 kbd_backlight_available = false;
1043 else
1044 kbd_backlight_available = true;
1045
1046 devm_led_classdev_register(&pdev->dev, &tpad_led);
1047
1048 ret = lg_laptop_input_init(&pdev->dev, device->handle);
1049 if (ret < 0)
1050 goto out_platform_device;
1051
1052 ret = sysfs_create_group(&pf_device->dev.kobj, &dev_attribute_group);
1053 if (ret)
1054 goto out_platform_device;
1055
1056 battery_hook_register(&battery_hook);
1057
1058 return 0;
1059
1060 out_platform_device:
1061 platform_device_unregister(pf_device);
1062 out_platform_registered:
1063 platform_driver_unregister(&pf_driver);
1064 return ret;
1065 }
1066
acpi_remove(struct platform_device * pdev)1067 static void acpi_remove(struct platform_device *pdev)
1068 {
1069 sysfs_remove_group(&pf_device->dev.kobj, &dev_attribute_group);
1070
1071 battery_hook_unregister(&battery_hook);
1072 platform_device_unregister(pf_device);
1073 pf_device = NULL;
1074 platform_driver_unregister(&pf_driver);
1075 }
1076
1077 static const struct acpi_device_id device_ids[] = {
1078 {"LGEX0820", 0},
1079 {"", 0}
1080 };
1081 MODULE_DEVICE_TABLE(acpi, device_ids);
1082
1083 static struct platform_driver acpi_driver = {
1084 .probe = acpi_probe,
1085 .remove = acpi_remove,
1086 .driver = {
1087 .name = "LG Gram Laptop Support",
1088 .acpi_match_table = device_ids,
1089 },
1090 };
1091
1092 module_platform_driver(acpi_driver);
1093