xref: /linux/drivers/platform/x86/lg-laptop.c (revision 5b05bb3f6c5716fab6911e12d60dd1f43ad9806a)
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