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