Merge tag 'arm-dt-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-microblaze.git] / drivers / platform / x86 / ideapad-laptop.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  ideapad-laptop.c - Lenovo IdeaPad ACPI Extras
4  *
5  *  Copyright © 2010 Intel Corporation
6  *  Copyright © 2010 David Woodhouse <dwmw2@infradead.org>
7  */
8
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10
11 #include <linux/acpi.h>
12 #include <linux/backlight.h>
13 #include <linux/bitops.h>
14 #include <linux/bug.h>
15 #include <linux/debugfs.h>
16 #include <linux/device.h>
17 #include <linux/dmi.h>
18 #include <linux/fb.h>
19 #include <linux/i8042.h>
20 #include <linux/init.h>
21 #include <linux/input.h>
22 #include <linux/input/sparse-keymap.h>
23 #include <linux/jiffies.h>
24 #include <linux/kernel.h>
25 #include <linux/leds.h>
26 #include <linux/module.h>
27 #include <linux/platform_device.h>
28 #include <linux/platform_profile.h>
29 #include <linux/rfkill.h>
30 #include <linux/seq_file.h>
31 #include <linux/sysfs.h>
32 #include <linux/types.h>
33
34 #include <acpi/video.h>
35
36 #include <dt-bindings/leds/common.h>
37
38 #define IDEAPAD_RFKILL_DEV_NUM  3
39
40 #if IS_ENABLED(CONFIG_ACPI_WMI)
41 static const char *const ideapad_wmi_fnesc_events[] = {
42         "26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", /* Yoga 3 */
43         "56322276-8493-4CE8-A783-98C991274F5E", /* Yoga 700 */
44         "8FC0DE0C-B4E4-43FD-B0F3-8871711C1294", /* Legion 5 */
45 };
46 #endif
47
48 enum {
49         CFG_CAP_BT_BIT       = 16,
50         CFG_CAP_3G_BIT       = 17,
51         CFG_CAP_WIFI_BIT     = 18,
52         CFG_CAP_CAM_BIT      = 19,
53         CFG_CAP_TOUCHPAD_BIT = 30,
54 };
55
56 enum {
57         GBMD_CONSERVATION_STATE_BIT = 5,
58 };
59
60 enum {
61         SBMC_CONSERVATION_ON  = 3,
62         SBMC_CONSERVATION_OFF = 5,
63 };
64
65 enum {
66         HALS_KBD_BL_SUPPORT_BIT       = 4,
67         HALS_KBD_BL_STATE_BIT         = 5,
68         HALS_USB_CHARGING_SUPPORT_BIT = 6,
69         HALS_USB_CHARGING_STATE_BIT   = 7,
70         HALS_FNLOCK_SUPPORT_BIT       = 9,
71         HALS_FNLOCK_STATE_BIT         = 10,
72         HALS_HOTKEYS_PRIMARY_BIT      = 11,
73 };
74
75 enum {
76         SALS_KBD_BL_ON        = 0x8,
77         SALS_KBD_BL_OFF       = 0x9,
78         SALS_USB_CHARGING_ON  = 0xa,
79         SALS_USB_CHARGING_OFF = 0xb,
80         SALS_FNLOCK_ON        = 0xe,
81         SALS_FNLOCK_OFF       = 0xf,
82 };
83
84 enum {
85         VPCCMD_R_VPC1 = 0x10,
86         VPCCMD_R_BL_MAX,
87         VPCCMD_R_BL,
88         VPCCMD_W_BL,
89         VPCCMD_R_WIFI,
90         VPCCMD_W_WIFI,
91         VPCCMD_R_BT,
92         VPCCMD_W_BT,
93         VPCCMD_R_BL_POWER,
94         VPCCMD_R_NOVO,
95         VPCCMD_R_VPC2,
96         VPCCMD_R_TOUCHPAD,
97         VPCCMD_W_TOUCHPAD,
98         VPCCMD_R_CAMERA,
99         VPCCMD_W_CAMERA,
100         VPCCMD_R_3G,
101         VPCCMD_W_3G,
102         VPCCMD_R_ODD, /* 0x21 */
103         VPCCMD_W_FAN,
104         VPCCMD_R_RF,
105         VPCCMD_W_RF,
106         VPCCMD_R_FAN = 0x2B,
107         VPCCMD_R_SPECIAL_BUTTONS = 0x31,
108         VPCCMD_W_BL_POWER = 0x33,
109 };
110
111 struct ideapad_dytc_priv {
112         enum platform_profile_option current_profile;
113         struct platform_profile_handler pprof;
114         struct mutex mutex; /* protects the DYTC interface */
115         struct ideapad_private *priv;
116 };
117
118 struct ideapad_rfk_priv {
119         int dev;
120         struct ideapad_private *priv;
121 };
122
123 struct ideapad_private {
124         struct acpi_device *adev;
125         struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
126         struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM];
127         struct platform_device *platform_device;
128         struct input_dev *inputdev;
129         struct backlight_device *blightdev;
130         struct ideapad_dytc_priv *dytc;
131         struct dentry *debug;
132         unsigned long cfg;
133         const char *fnesc_guid;
134         struct {
135                 bool conservation_mode    : 1;
136                 bool dytc                 : 1;
137                 bool fan_mode             : 1;
138                 bool fn_lock              : 1;
139                 bool hw_rfkill_switch     : 1;
140                 bool kbd_bl               : 1;
141                 bool touchpad_ctrl_via_ec : 1;
142                 bool usb_charging         : 1;
143         } features;
144         struct {
145                 bool initialized;
146                 struct led_classdev led;
147                 unsigned int last_brightness;
148         } kbd_bl;
149 };
150
151 static bool no_bt_rfkill;
152 module_param(no_bt_rfkill, bool, 0444);
153 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
154
155 static bool allow_v4_dytc;
156 module_param(allow_v4_dytc, bool, 0444);
157 MODULE_PARM_DESC(allow_v4_dytc, "Enable DYTC version 4 platform-profile support.");
158
159 /*
160  * ACPI Helpers
161  */
162 #define IDEAPAD_EC_TIMEOUT 200 /* in ms */
163
164 static int eval_int(acpi_handle handle, const char *name, unsigned long *res)
165 {
166         unsigned long long result;
167         acpi_status status;
168
169         status = acpi_evaluate_integer(handle, (char *)name, NULL, &result);
170         if (ACPI_FAILURE(status))
171                 return -EIO;
172
173         *res = result;
174
175         return 0;
176 }
177
178 static int exec_simple_method(acpi_handle handle, const char *name, unsigned long arg)
179 {
180         acpi_status status = acpi_execute_simple_method(handle, (char *)name, arg);
181
182         return ACPI_FAILURE(status) ? -EIO : 0;
183 }
184
185 static int eval_gbmd(acpi_handle handle, unsigned long *res)
186 {
187         return eval_int(handle, "GBMD", res);
188 }
189
190 static int exec_sbmc(acpi_handle handle, unsigned long arg)
191 {
192         return exec_simple_method(handle, "SBMC", arg);
193 }
194
195 static int eval_hals(acpi_handle handle, unsigned long *res)
196 {
197         return eval_int(handle, "HALS", res);
198 }
199
200 static int exec_sals(acpi_handle handle, unsigned long arg)
201 {
202         return exec_simple_method(handle, "SALS", arg);
203 }
204
205 static int eval_int_with_arg(acpi_handle handle, const char *name, unsigned long arg, unsigned long *res)
206 {
207         struct acpi_object_list params;
208         unsigned long long result;
209         union acpi_object in_obj;
210         acpi_status status;
211
212         params.count = 1;
213         params.pointer = &in_obj;
214         in_obj.type = ACPI_TYPE_INTEGER;
215         in_obj.integer.value = arg;
216
217         status = acpi_evaluate_integer(handle, (char *)name, &params, &result);
218         if (ACPI_FAILURE(status))
219                 return -EIO;
220
221         if (res)
222                 *res = result;
223
224         return 0;
225 }
226
227 static int eval_dytc(acpi_handle handle, unsigned long cmd, unsigned long *res)
228 {
229         return eval_int_with_arg(handle, "DYTC", cmd, res);
230 }
231
232 static int eval_vpcr(acpi_handle handle, unsigned long cmd, unsigned long *res)
233 {
234         return eval_int_with_arg(handle, "VPCR", cmd, res);
235 }
236
237 static int eval_vpcw(acpi_handle handle, unsigned long cmd, unsigned long data)
238 {
239         struct acpi_object_list params;
240         union acpi_object in_obj[2];
241         acpi_status status;
242
243         params.count = 2;
244         params.pointer = in_obj;
245         in_obj[0].type = ACPI_TYPE_INTEGER;
246         in_obj[0].integer.value = cmd;
247         in_obj[1].type = ACPI_TYPE_INTEGER;
248         in_obj[1].integer.value = data;
249
250         status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
251         if (ACPI_FAILURE(status))
252                 return -EIO;
253
254         return 0;
255 }
256
257 static int read_ec_data(acpi_handle handle, unsigned long cmd, unsigned long *data)
258 {
259         unsigned long end_jiffies, val;
260         int err;
261
262         err = eval_vpcw(handle, 1, cmd);
263         if (err)
264                 return err;
265
266         end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
267
268         while (time_before(jiffies, end_jiffies)) {
269                 schedule();
270
271                 err = eval_vpcr(handle, 1, &val);
272                 if (err)
273                         return err;
274
275                 if (val == 0)
276                         return eval_vpcr(handle, 0, data);
277         }
278
279         acpi_handle_err(handle, "timeout in %s\n", __func__);
280
281         return -ETIMEDOUT;
282 }
283
284 static int write_ec_cmd(acpi_handle handle, unsigned long cmd, unsigned long data)
285 {
286         unsigned long end_jiffies, val;
287         int err;
288
289         err = eval_vpcw(handle, 0, data);
290         if (err)
291                 return err;
292
293         err = eval_vpcw(handle, 1, cmd);
294         if (err)
295                 return err;
296
297         end_jiffies = jiffies + msecs_to_jiffies(IDEAPAD_EC_TIMEOUT) + 1;
298
299         while (time_before(jiffies, end_jiffies)) {
300                 schedule();
301
302                 err = eval_vpcr(handle, 1, &val);
303                 if (err)
304                         return err;
305
306                 if (val == 0)
307                         return 0;
308         }
309
310         acpi_handle_err(handle, "timeout in %s\n", __func__);
311
312         return -ETIMEDOUT;
313 }
314
315 /*
316  * debugfs
317  */
318 static int debugfs_status_show(struct seq_file *s, void *data)
319 {
320         struct ideapad_private *priv = s->private;
321         unsigned long value;
322
323         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))
324                 seq_printf(s, "Backlight max:  %lu\n", value);
325         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))
326                 seq_printf(s, "Backlight now:  %lu\n", value);
327         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))
328                 seq_printf(s, "BL power value: %s (%lu)\n", value ? "on" : "off", value);
329
330         seq_puts(s, "=====================\n");
331
332         if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))
333                 seq_printf(s, "Radio status: %s (%lu)\n", value ? "on" : "off", value);
334         if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))
335                 seq_printf(s, "Wifi status:  %s (%lu)\n", value ? "on" : "off", value);
336         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))
337                 seq_printf(s, "BT status:    %s (%lu)\n", value ? "on" : "off", value);
338         if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))
339                 seq_printf(s, "3G status:    %s (%lu)\n", value ? "on" : "off", value);
340
341         seq_puts(s, "=====================\n");
342
343         if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))
344                 seq_printf(s, "Touchpad status: %s (%lu)\n", value ? "on" : "off", value);
345         if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))
346                 seq_printf(s, "Camera status:   %s (%lu)\n", value ? "on" : "off", value);
347
348         seq_puts(s, "=====================\n");
349
350         if (!eval_gbmd(priv->adev->handle, &value))
351                 seq_printf(s, "GBMD: %#010lx\n", value);
352         if (!eval_hals(priv->adev->handle, &value))
353                 seq_printf(s, "HALS: %#010lx\n", value);
354
355         return 0;
356 }
357 DEFINE_SHOW_ATTRIBUTE(debugfs_status);
358
359 static int debugfs_cfg_show(struct seq_file *s, void *data)
360 {
361         struct ideapad_private *priv = s->private;
362
363         seq_printf(s, "_CFG: %#010lx\n\n", priv->cfg);
364
365         seq_puts(s, "Capabilities:");
366         if (test_bit(CFG_CAP_BT_BIT, &priv->cfg))
367                 seq_puts(s, " bluetooth");
368         if (test_bit(CFG_CAP_3G_BIT, &priv->cfg))
369                 seq_puts(s, " 3G");
370         if (test_bit(CFG_CAP_WIFI_BIT, &priv->cfg))
371                 seq_puts(s, " wifi");
372         if (test_bit(CFG_CAP_CAM_BIT, &priv->cfg))
373                 seq_puts(s, " camera");
374         if (test_bit(CFG_CAP_TOUCHPAD_BIT, &priv->cfg))
375                 seq_puts(s, " touchpad");
376         seq_puts(s, "\n");
377
378         seq_puts(s, "Graphics: ");
379         switch (priv->cfg & 0x700) {
380         case 0x100:
381                 seq_puts(s, "Intel");
382                 break;
383         case 0x200:
384                 seq_puts(s, "ATI");
385                 break;
386         case 0x300:
387                 seq_puts(s, "Nvidia");
388                 break;
389         case 0x400:
390                 seq_puts(s, "Intel and ATI");
391                 break;
392         case 0x500:
393                 seq_puts(s, "Intel and Nvidia");
394                 break;
395         }
396         seq_puts(s, "\n");
397
398         return 0;
399 }
400 DEFINE_SHOW_ATTRIBUTE(debugfs_cfg);
401
402 static void ideapad_debugfs_init(struct ideapad_private *priv)
403 {
404         struct dentry *dir;
405
406         dir = debugfs_create_dir("ideapad", NULL);
407         priv->debug = dir;
408
409         debugfs_create_file("cfg", 0444, dir, priv, &debugfs_cfg_fops);
410         debugfs_create_file("status", 0444, dir, priv, &debugfs_status_fops);
411 }
412
413 static void ideapad_debugfs_exit(struct ideapad_private *priv)
414 {
415         debugfs_remove_recursive(priv->debug);
416         priv->debug = NULL;
417 }
418
419 /*
420  * sysfs
421  */
422 static ssize_t camera_power_show(struct device *dev,
423                                  struct device_attribute *attr,
424                                  char *buf)
425 {
426         struct ideapad_private *priv = dev_get_drvdata(dev);
427         unsigned long result;
428         int err;
429
430         err = read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result);
431         if (err)
432                 return err;
433
434         return sysfs_emit(buf, "%d\n", !!result);
435 }
436
437 static ssize_t camera_power_store(struct device *dev,
438                                   struct device_attribute *attr,
439                                   const char *buf, size_t count)
440 {
441         struct ideapad_private *priv = dev_get_drvdata(dev);
442         bool state;
443         int err;
444
445         err = kstrtobool(buf, &state);
446         if (err)
447                 return err;
448
449         err = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
450         if (err)
451                 return err;
452
453         return count;
454 }
455
456 static DEVICE_ATTR_RW(camera_power);
457
458 static ssize_t conservation_mode_show(struct device *dev,
459                                       struct device_attribute *attr,
460                                       char *buf)
461 {
462         struct ideapad_private *priv = dev_get_drvdata(dev);
463         unsigned long result;
464         int err;
465
466         err = eval_gbmd(priv->adev->handle, &result);
467         if (err)
468                 return err;
469
470         return sysfs_emit(buf, "%d\n", !!test_bit(GBMD_CONSERVATION_STATE_BIT, &result));
471 }
472
473 static ssize_t conservation_mode_store(struct device *dev,
474                                        struct device_attribute *attr,
475                                        const char *buf, size_t count)
476 {
477         struct ideapad_private *priv = dev_get_drvdata(dev);
478         bool state;
479         int err;
480
481         err = kstrtobool(buf, &state);
482         if (err)
483                 return err;
484
485         err = exec_sbmc(priv->adev->handle, state ? SBMC_CONSERVATION_ON : SBMC_CONSERVATION_OFF);
486         if (err)
487                 return err;
488
489         return count;
490 }
491
492 static DEVICE_ATTR_RW(conservation_mode);
493
494 static ssize_t fan_mode_show(struct device *dev,
495                              struct device_attribute *attr,
496                              char *buf)
497 {
498         struct ideapad_private *priv = dev_get_drvdata(dev);
499         unsigned long result;
500         int err;
501
502         err = read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result);
503         if (err)
504                 return err;
505
506         return sysfs_emit(buf, "%lu\n", result);
507 }
508
509 static ssize_t fan_mode_store(struct device *dev,
510                               struct device_attribute *attr,
511                               const char *buf, size_t count)
512 {
513         struct ideapad_private *priv = dev_get_drvdata(dev);
514         unsigned int state;
515         int err;
516
517         err = kstrtouint(buf, 0, &state);
518         if (err)
519                 return err;
520
521         if (state > 4 || state == 3)
522                 return -EINVAL;
523
524         err = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
525         if (err)
526                 return err;
527
528         return count;
529 }
530
531 static DEVICE_ATTR_RW(fan_mode);
532
533 static ssize_t fn_lock_show(struct device *dev,
534                             struct device_attribute *attr,
535                             char *buf)
536 {
537         struct ideapad_private *priv = dev_get_drvdata(dev);
538         unsigned long hals;
539         int err;
540
541         err = eval_hals(priv->adev->handle, &hals);
542         if (err)
543                 return err;
544
545         return sysfs_emit(buf, "%d\n", !!test_bit(HALS_FNLOCK_STATE_BIT, &hals));
546 }
547
548 static ssize_t fn_lock_store(struct device *dev,
549                              struct device_attribute *attr,
550                              const char *buf, size_t count)
551 {
552         struct ideapad_private *priv = dev_get_drvdata(dev);
553         bool state;
554         int err;
555
556         err = kstrtobool(buf, &state);
557         if (err)
558                 return err;
559
560         err = exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
561         if (err)
562                 return err;
563
564         return count;
565 }
566
567 static DEVICE_ATTR_RW(fn_lock);
568
569 static ssize_t touchpad_show(struct device *dev,
570                              struct device_attribute *attr,
571                              char *buf)
572 {
573         struct ideapad_private *priv = dev_get_drvdata(dev);
574         unsigned long result;
575         int err;
576
577         err = read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result);
578         if (err)
579                 return err;
580
581         return sysfs_emit(buf, "%d\n", !!result);
582 }
583
584 static ssize_t touchpad_store(struct device *dev,
585                               struct device_attribute *attr,
586                               const char *buf, size_t count)
587 {
588         struct ideapad_private *priv = dev_get_drvdata(dev);
589         bool state;
590         int err;
591
592         err = kstrtobool(buf, &state);
593         if (err)
594                 return err;
595
596         err = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state);
597         if (err)
598                 return err;
599
600         return count;
601 }
602
603 static DEVICE_ATTR_RW(touchpad);
604
605 static ssize_t usb_charging_show(struct device *dev,
606                                  struct device_attribute *attr,
607                                  char *buf)
608 {
609         struct ideapad_private *priv = dev_get_drvdata(dev);
610         unsigned long hals;
611         int err;
612
613         err = eval_hals(priv->adev->handle, &hals);
614         if (err)
615                 return err;
616
617         return sysfs_emit(buf, "%d\n", !!test_bit(HALS_USB_CHARGING_STATE_BIT, &hals));
618 }
619
620 static ssize_t usb_charging_store(struct device *dev,
621                                   struct device_attribute *attr,
622                                   const char *buf, size_t count)
623 {
624         struct ideapad_private *priv = dev_get_drvdata(dev);
625         bool state;
626         int err;
627
628         err = kstrtobool(buf, &state);
629         if (err)
630                 return err;
631
632         err = exec_sals(priv->adev->handle, state ? SALS_USB_CHARGING_ON : SALS_USB_CHARGING_OFF);
633         if (err)
634                 return err;
635
636         return count;
637 }
638
639 static DEVICE_ATTR_RW(usb_charging);
640
641 static struct attribute *ideapad_attributes[] = {
642         &dev_attr_camera_power.attr,
643         &dev_attr_conservation_mode.attr,
644         &dev_attr_fan_mode.attr,
645         &dev_attr_fn_lock.attr,
646         &dev_attr_touchpad.attr,
647         &dev_attr_usb_charging.attr,
648         NULL
649 };
650
651 static umode_t ideapad_is_visible(struct kobject *kobj,
652                                   struct attribute *attr,
653                                   int idx)
654 {
655         struct device *dev = kobj_to_dev(kobj);
656         struct ideapad_private *priv = dev_get_drvdata(dev);
657         bool supported = true;
658
659         if (attr == &dev_attr_camera_power.attr)
660                 supported = test_bit(CFG_CAP_CAM_BIT, &priv->cfg);
661         else if (attr == &dev_attr_conservation_mode.attr)
662                 supported = priv->features.conservation_mode;
663         else if (attr == &dev_attr_fan_mode.attr)
664                 supported = priv->features.fan_mode;
665         else if (attr == &dev_attr_fn_lock.attr)
666                 supported = priv->features.fn_lock;
667         else if (attr == &dev_attr_touchpad.attr)
668                 supported = priv->features.touchpad_ctrl_via_ec &&
669                             test_bit(CFG_CAP_TOUCHPAD_BIT, &priv->cfg);
670         else if (attr == &dev_attr_usb_charging.attr)
671                 supported = priv->features.usb_charging;
672
673         return supported ? attr->mode : 0;
674 }
675
676 static const struct attribute_group ideapad_attribute_group = {
677         .is_visible = ideapad_is_visible,
678         .attrs = ideapad_attributes
679 };
680
681 /*
682  * DYTC Platform profile
683  */
684 #define DYTC_CMD_QUERY        0 /* To get DYTC status - enable/revision */
685 #define DYTC_CMD_SET          1 /* To enable/disable IC function mode */
686 #define DYTC_CMD_GET          2 /* To get current IC function and mode */
687 #define DYTC_CMD_RESET    0x1ff /* To reset back to default */
688
689 #define DYTC_QUERY_ENABLE_BIT 8  /* Bit        8 - 0 = disabled, 1 = enabled */
690 #define DYTC_QUERY_SUBREV_BIT 16 /* Bits 16 - 27 - sub revision */
691 #define DYTC_QUERY_REV_BIT    28 /* Bits 28 - 31 - revision */
692
693 #define DYTC_GET_FUNCTION_BIT 8  /* Bits  8-11 - function setting */
694 #define DYTC_GET_MODE_BIT     12 /* Bits 12-15 - mode setting */
695
696 #define DYTC_SET_FUNCTION_BIT 12 /* Bits 12-15 - function setting */
697 #define DYTC_SET_MODE_BIT     16 /* Bits 16-19 - mode setting */
698 #define DYTC_SET_VALID_BIT    20 /* Bit     20 - 1 = on, 0 = off */
699
700 #define DYTC_FUNCTION_STD     0  /* Function = 0, standard mode */
701 #define DYTC_FUNCTION_CQL     1  /* Function = 1, lap mode */
702 #define DYTC_FUNCTION_MMC     11 /* Function = 11, desk mode */
703
704 #define DYTC_MODE_PERFORM     2  /* High power mode aka performance */
705 #define DYTC_MODE_LOW_POWER       3  /* Low power mode aka quiet */
706 #define DYTC_MODE_BALANCE   0xF  /* Default mode aka balanced */
707
708 #define DYTC_SET_COMMAND(function, mode, on) \
709         (DYTC_CMD_SET | (function) << DYTC_SET_FUNCTION_BIT | \
710          (mode) << DYTC_SET_MODE_BIT | \
711          (on) << DYTC_SET_VALID_BIT)
712
713 #define DYTC_DISABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 0)
714
715 #define DYTC_ENABLE_CQL DYTC_SET_COMMAND(DYTC_FUNCTION_CQL, DYTC_MODE_BALANCE, 1)
716
717 static int convert_dytc_to_profile(int dytcmode, enum platform_profile_option *profile)
718 {
719         switch (dytcmode) {
720         case DYTC_MODE_LOW_POWER:
721                 *profile = PLATFORM_PROFILE_LOW_POWER;
722                 break;
723         case DYTC_MODE_BALANCE:
724                 *profile =  PLATFORM_PROFILE_BALANCED;
725                 break;
726         case DYTC_MODE_PERFORM:
727                 *profile =  PLATFORM_PROFILE_PERFORMANCE;
728                 break;
729         default: /* Unknown mode */
730                 return -EINVAL;
731         }
732
733         return 0;
734 }
735
736 static int convert_profile_to_dytc(enum platform_profile_option profile, int *perfmode)
737 {
738         switch (profile) {
739         case PLATFORM_PROFILE_LOW_POWER:
740                 *perfmode = DYTC_MODE_LOW_POWER;
741                 break;
742         case PLATFORM_PROFILE_BALANCED:
743                 *perfmode = DYTC_MODE_BALANCE;
744                 break;
745         case PLATFORM_PROFILE_PERFORMANCE:
746                 *perfmode = DYTC_MODE_PERFORM;
747                 break;
748         default: /* Unknown profile */
749                 return -EOPNOTSUPP;
750         }
751
752         return 0;
753 }
754
755 /*
756  * dytc_profile_get: Function to register with platform_profile
757  * handler. Returns current platform profile.
758  */
759 static int dytc_profile_get(struct platform_profile_handler *pprof,
760                             enum platform_profile_option *profile)
761 {
762         struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof);
763
764         *profile = dytc->current_profile;
765         return 0;
766 }
767
768 /*
769  * Helper function - check if we are in CQL mode and if we are
770  *  - disable CQL,
771  *  - run the command
772  *  - enable CQL
773  *  If not in CQL mode, just run the command
774  */
775 static int dytc_cql_command(struct ideapad_private *priv, unsigned long cmd,
776                             unsigned long *output)
777 {
778         int err, cmd_err, cur_funcmode;
779
780         /* Determine if we are in CQL mode. This alters the commands we do */
781         err = eval_dytc(priv->adev->handle, DYTC_CMD_GET, output);
782         if (err)
783                 return err;
784
785         cur_funcmode = (*output >> DYTC_GET_FUNCTION_BIT) & 0xF;
786         /* Check if we're OK to return immediately */
787         if (cmd == DYTC_CMD_GET && cur_funcmode != DYTC_FUNCTION_CQL)
788                 return 0;
789
790         if (cur_funcmode == DYTC_FUNCTION_CQL) {
791                 err = eval_dytc(priv->adev->handle, DYTC_DISABLE_CQL, NULL);
792                 if (err)
793                         return err;
794         }
795
796         cmd_err = eval_dytc(priv->adev->handle, cmd, output);
797         /* Check return condition after we've restored CQL state */
798
799         if (cur_funcmode == DYTC_FUNCTION_CQL) {
800                 err = eval_dytc(priv->adev->handle, DYTC_ENABLE_CQL, NULL);
801                 if (err)
802                         return err;
803         }
804
805         return cmd_err;
806 }
807
808 /*
809  * dytc_profile_set: Function to register with platform_profile
810  * handler. Sets current platform profile.
811  */
812 static int dytc_profile_set(struct platform_profile_handler *pprof,
813                             enum platform_profile_option profile)
814 {
815         struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof);
816         struct ideapad_private *priv = dytc->priv;
817         unsigned long output;
818         int err;
819
820         err = mutex_lock_interruptible(&dytc->mutex);
821         if (err)
822                 return err;
823
824         if (profile == PLATFORM_PROFILE_BALANCED) {
825                 /* To get back to balanced mode we just issue a reset command */
826                 err = eval_dytc(priv->adev->handle, DYTC_CMD_RESET, NULL);
827                 if (err)
828                         goto unlock;
829         } else {
830                 int perfmode;
831
832                 err = convert_profile_to_dytc(profile, &perfmode);
833                 if (err)
834                         goto unlock;
835
836                 /* Determine if we are in CQL mode. This alters the commands we do */
837                 err = dytc_cql_command(priv, DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1),
838                                        &output);
839                 if (err)
840                         goto unlock;
841         }
842
843         /* Success - update current profile */
844         dytc->current_profile = profile;
845
846 unlock:
847         mutex_unlock(&dytc->mutex);
848
849         return err;
850 }
851
852 static void dytc_profile_refresh(struct ideapad_private *priv)
853 {
854         enum platform_profile_option profile;
855         unsigned long output;
856         int err, perfmode;
857
858         mutex_lock(&priv->dytc->mutex);
859         err = dytc_cql_command(priv, DYTC_CMD_GET, &output);
860         mutex_unlock(&priv->dytc->mutex);
861         if (err)
862                 return;
863
864         perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
865
866         if (convert_dytc_to_profile(perfmode, &profile))
867                 return;
868
869         if (profile != priv->dytc->current_profile) {
870                 priv->dytc->current_profile = profile;
871                 platform_profile_notify();
872         }
873 }
874
875 static const struct dmi_system_id ideapad_dytc_v4_allow_table[] = {
876         {
877                 /* Ideapad 5 Pro 16ACH6 */
878                 .matches = {
879                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
880                         DMI_MATCH(DMI_PRODUCT_NAME, "82L5")
881                 }
882         },
883         {
884                 /* Ideapad 5 15ITL05 */
885                 .matches = {
886                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
887                         DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad 5 15ITL05")
888                 }
889         },
890         {}
891 };
892
893 static int ideapad_dytc_profile_init(struct ideapad_private *priv)
894 {
895         int err, dytc_version;
896         unsigned long output;
897
898         if (!priv->features.dytc)
899                 return -ENODEV;
900
901         err = eval_dytc(priv->adev->handle, DYTC_CMD_QUERY, &output);
902         /* For all other errors we can flag the failure */
903         if (err)
904                 return err;
905
906         /* Check DYTC is enabled and supports mode setting */
907         if (!test_bit(DYTC_QUERY_ENABLE_BIT, &output)) {
908                 dev_info(&priv->platform_device->dev, "DYTC_QUERY_ENABLE_BIT returned false\n");
909                 return -ENODEV;
910         }
911
912         dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
913
914         if (dytc_version < 4) {
915                 dev_info(&priv->platform_device->dev, "DYTC_VERSION < 4 is not supported\n");
916                 return -ENODEV;
917         }
918
919         if (dytc_version < 5 &&
920             !(allow_v4_dytc || dmi_check_system(ideapad_dytc_v4_allow_table))) {
921                 dev_info(&priv->platform_device->dev,
922                          "DYTC_VERSION 4 support may not work. Pass ideapad_laptop.allow_v4_dytc=Y on the kernel commandline to enable\n");
923                 return -ENODEV;
924         }
925
926         priv->dytc = kzalloc(sizeof(*priv->dytc), GFP_KERNEL);
927         if (!priv->dytc)
928                 return -ENOMEM;
929
930         mutex_init(&priv->dytc->mutex);
931
932         priv->dytc->priv = priv;
933         priv->dytc->pprof.profile_get = dytc_profile_get;
934         priv->dytc->pprof.profile_set = dytc_profile_set;
935
936         /* Setup supported modes */
937         set_bit(PLATFORM_PROFILE_LOW_POWER, priv->dytc->pprof.choices);
938         set_bit(PLATFORM_PROFILE_BALANCED, priv->dytc->pprof.choices);
939         set_bit(PLATFORM_PROFILE_PERFORMANCE, priv->dytc->pprof.choices);
940
941         /* Create platform_profile structure and register */
942         err = platform_profile_register(&priv->dytc->pprof);
943         if (err)
944                 goto pp_reg_failed;
945
946         /* Ensure initial values are correct */
947         dytc_profile_refresh(priv);
948
949         return 0;
950
951 pp_reg_failed:
952         mutex_destroy(&priv->dytc->mutex);
953         kfree(priv->dytc);
954         priv->dytc = NULL;
955
956         return err;
957 }
958
959 static void ideapad_dytc_profile_exit(struct ideapad_private *priv)
960 {
961         if (!priv->dytc)
962                 return;
963
964         platform_profile_remove();
965         mutex_destroy(&priv->dytc->mutex);
966         kfree(priv->dytc);
967
968         priv->dytc = NULL;
969 }
970
971 /*
972  * Rfkill
973  */
974 struct ideapad_rfk_data {
975         char *name;
976         int cfgbit;
977         int opcode;
978         int type;
979 };
980
981 static const struct ideapad_rfk_data ideapad_rfk_data[] = {
982         { "ideapad_wlan",      CFG_CAP_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
983         { "ideapad_bluetooth", CFG_CAP_BT_BIT,   VPCCMD_W_BT,   RFKILL_TYPE_BLUETOOTH },
984         { "ideapad_3g",        CFG_CAP_3G_BIT,   VPCCMD_W_3G,   RFKILL_TYPE_WWAN },
985 };
986
987 static int ideapad_rfk_set(void *data, bool blocked)
988 {
989         struct ideapad_rfk_priv *priv = data;
990         int opcode = ideapad_rfk_data[priv->dev].opcode;
991
992         return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked);
993 }
994
995 static const struct rfkill_ops ideapad_rfk_ops = {
996         .set_block = ideapad_rfk_set,
997 };
998
999 static void ideapad_sync_rfk_state(struct ideapad_private *priv)
1000 {
1001         unsigned long hw_blocked = 0;
1002         int i;
1003
1004         if (priv->features.hw_rfkill_switch) {
1005                 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
1006                         return;
1007                 hw_blocked = !hw_blocked;
1008         }
1009
1010         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1011                 if (priv->rfk[i])
1012                         rfkill_set_hw_state(priv->rfk[i], hw_blocked);
1013 }
1014
1015 static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
1016 {
1017         unsigned long rf_enabled;
1018         int err;
1019
1020         if (no_bt_rfkill && ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH) {
1021                 /* Force to enable bluetooth when no_bt_rfkill=1 */
1022                 write_ec_cmd(priv->adev->handle, ideapad_rfk_data[dev].opcode, 1);
1023                 return 0;
1024         }
1025
1026         priv->rfk_priv[dev].dev = dev;
1027         priv->rfk_priv[dev].priv = priv;
1028
1029         priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name,
1030                                       &priv->platform_device->dev,
1031                                       ideapad_rfk_data[dev].type,
1032                                       &ideapad_rfk_ops,
1033                                       &priv->rfk_priv[dev]);
1034         if (!priv->rfk[dev])
1035                 return -ENOMEM;
1036
1037         err = read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode - 1, &rf_enabled);
1038         if (err)
1039                 rf_enabled = 1;
1040
1041         rfkill_init_sw_state(priv->rfk[dev], !rf_enabled);
1042
1043         err = rfkill_register(priv->rfk[dev]);
1044         if (err)
1045                 rfkill_destroy(priv->rfk[dev]);
1046
1047         return err;
1048 }
1049
1050 static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
1051 {
1052         if (!priv->rfk[dev])
1053                 return;
1054
1055         rfkill_unregister(priv->rfk[dev]);
1056         rfkill_destroy(priv->rfk[dev]);
1057 }
1058
1059 /*
1060  * Platform device
1061  */
1062 static int ideapad_sysfs_init(struct ideapad_private *priv)
1063 {
1064         return device_add_group(&priv->platform_device->dev,
1065                                 &ideapad_attribute_group);
1066 }
1067
1068 static void ideapad_sysfs_exit(struct ideapad_private *priv)
1069 {
1070         device_remove_group(&priv->platform_device->dev,
1071                             &ideapad_attribute_group);
1072 }
1073
1074 /*
1075  * input device
1076  */
1077 static const struct key_entry ideapad_keymap[] = {
1078         { KE_KEY,   6, { KEY_SWITCHVIDEOMODE } },
1079         { KE_KEY,   7, { KEY_CAMERA } },
1080         { KE_KEY,   8, { KEY_MICMUTE } },
1081         { KE_KEY,  11, { KEY_F16 } },
1082         { KE_KEY,  13, { KEY_WLAN } },
1083         { KE_KEY,  16, { KEY_PROG1 } },
1084         { KE_KEY,  17, { KEY_PROG2 } },
1085         { KE_KEY,  64, { KEY_PROG3 } },
1086         { KE_KEY,  65, { KEY_PROG4 } },
1087         { KE_KEY,  66, { KEY_TOUCHPAD_OFF } },
1088         { KE_KEY,  67, { KEY_TOUCHPAD_ON } },
1089         { KE_KEY, 128, { KEY_ESC } },
1090         { KE_END },
1091 };
1092
1093 static int ideapad_input_init(struct ideapad_private *priv)
1094 {
1095         struct input_dev *inputdev;
1096         int err;
1097
1098         inputdev = input_allocate_device();
1099         if (!inputdev)
1100                 return -ENOMEM;
1101
1102         inputdev->name = "Ideapad extra buttons";
1103         inputdev->phys = "ideapad/input0";
1104         inputdev->id.bustype = BUS_HOST;
1105         inputdev->dev.parent = &priv->platform_device->dev;
1106
1107         err = sparse_keymap_setup(inputdev, ideapad_keymap, NULL);
1108         if (err) {
1109                 dev_err(&priv->platform_device->dev,
1110                         "Could not set up input device keymap: %d\n", err);
1111                 goto err_free_dev;
1112         }
1113
1114         err = input_register_device(inputdev);
1115         if (err) {
1116                 dev_err(&priv->platform_device->dev,
1117                         "Could not register input device: %d\n", err);
1118                 goto err_free_dev;
1119         }
1120
1121         priv->inputdev = inputdev;
1122
1123         return 0;
1124
1125 err_free_dev:
1126         input_free_device(inputdev);
1127
1128         return err;
1129 }
1130
1131 static void ideapad_input_exit(struct ideapad_private *priv)
1132 {
1133         input_unregister_device(priv->inputdev);
1134         priv->inputdev = NULL;
1135 }
1136
1137 static void ideapad_input_report(struct ideapad_private *priv,
1138                                  unsigned long scancode)
1139 {
1140         sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
1141 }
1142
1143 static void ideapad_input_novokey(struct ideapad_private *priv)
1144 {
1145         unsigned long long_pressed;
1146
1147         if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
1148                 return;
1149
1150         if (long_pressed)
1151                 ideapad_input_report(priv, 17);
1152         else
1153                 ideapad_input_report(priv, 16);
1154 }
1155
1156 static void ideapad_check_special_buttons(struct ideapad_private *priv)
1157 {
1158         unsigned long bit, value;
1159
1160         if (read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value))
1161                 return;
1162
1163         for_each_set_bit (bit, &value, 16) {
1164                 switch (bit) {
1165                 case 6: /* Z570 */
1166                 case 0: /* Z580 */
1167                         /* Thermal Management button */
1168                         ideapad_input_report(priv, 65);
1169                         break;
1170                 case 1:
1171                         /* OneKey Theater button */
1172                         ideapad_input_report(priv, 64);
1173                         break;
1174                 default:
1175                         dev_info(&priv->platform_device->dev,
1176                                  "Unknown special button: %lu\n", bit);
1177                         break;
1178                 }
1179         }
1180 }
1181
1182 /*
1183  * backlight
1184  */
1185 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
1186 {
1187         struct ideapad_private *priv = bl_get_data(blightdev);
1188         unsigned long now;
1189         int err;
1190
1191         err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
1192         if (err)
1193                 return err;
1194
1195         return now;
1196 }
1197
1198 static int ideapad_backlight_update_status(struct backlight_device *blightdev)
1199 {
1200         struct ideapad_private *priv = bl_get_data(blightdev);
1201         int err;
1202
1203         err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
1204                            blightdev->props.brightness);
1205         if (err)
1206                 return err;
1207
1208         err = write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
1209                            blightdev->props.power != FB_BLANK_POWERDOWN);
1210         if (err)
1211                 return err;
1212
1213         return 0;
1214 }
1215
1216 static const struct backlight_ops ideapad_backlight_ops = {
1217         .get_brightness = ideapad_backlight_get_brightness,
1218         .update_status = ideapad_backlight_update_status,
1219 };
1220
1221 static int ideapad_backlight_init(struct ideapad_private *priv)
1222 {
1223         struct backlight_device *blightdev;
1224         struct backlight_properties props;
1225         unsigned long max, now, power;
1226         int err;
1227
1228         err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max);
1229         if (err)
1230                 return err;
1231
1232         err = read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
1233         if (err)
1234                 return err;
1235
1236         err = read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power);
1237         if (err)
1238                 return err;
1239
1240         memset(&props, 0, sizeof(props));
1241
1242         props.max_brightness = max;
1243         props.type = BACKLIGHT_PLATFORM;
1244
1245         blightdev = backlight_device_register("ideapad",
1246                                               &priv->platform_device->dev,
1247                                               priv,
1248                                               &ideapad_backlight_ops,
1249                                               &props);
1250         if (IS_ERR(blightdev)) {
1251                 err = PTR_ERR(blightdev);
1252                 dev_err(&priv->platform_device->dev,
1253                         "Could not register backlight device: %d\n", err);
1254                 return err;
1255         }
1256
1257         priv->blightdev = blightdev;
1258         blightdev->props.brightness = now;
1259         blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
1260
1261         backlight_update_status(blightdev);
1262
1263         return 0;
1264 }
1265
1266 static void ideapad_backlight_exit(struct ideapad_private *priv)
1267 {
1268         backlight_device_unregister(priv->blightdev);
1269         priv->blightdev = NULL;
1270 }
1271
1272 static void ideapad_backlight_notify_power(struct ideapad_private *priv)
1273 {
1274         struct backlight_device *blightdev = priv->blightdev;
1275         unsigned long power;
1276
1277         if (!blightdev)
1278                 return;
1279
1280         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
1281                 return;
1282
1283         blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
1284 }
1285
1286 static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
1287 {
1288         unsigned long now;
1289
1290         /* if we control brightness via acpi video driver */
1291         if (!priv->blightdev)
1292                 read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
1293         else
1294                 backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
1295 }
1296
1297 /*
1298  * keyboard backlight
1299  */
1300 static int ideapad_kbd_bl_brightness_get(struct ideapad_private *priv)
1301 {
1302         unsigned long hals;
1303         int err;
1304
1305         err = eval_hals(priv->adev->handle, &hals);
1306         if (err)
1307                 return err;
1308
1309         return !!test_bit(HALS_KBD_BL_STATE_BIT, &hals);
1310 }
1311
1312 static enum led_brightness ideapad_kbd_bl_led_cdev_brightness_get(struct led_classdev *led_cdev)
1313 {
1314         struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led);
1315
1316         return ideapad_kbd_bl_brightness_get(priv);
1317 }
1318
1319 static int ideapad_kbd_bl_brightness_set(struct ideapad_private *priv, unsigned int brightness)
1320 {
1321         int err = exec_sals(priv->adev->handle, brightness ? SALS_KBD_BL_ON : SALS_KBD_BL_OFF);
1322
1323         if (err)
1324                 return err;
1325
1326         priv->kbd_bl.last_brightness = brightness;
1327
1328         return 0;
1329 }
1330
1331 static int ideapad_kbd_bl_led_cdev_brightness_set(struct led_classdev *led_cdev,
1332                                                   enum led_brightness brightness)
1333 {
1334         struct ideapad_private *priv = container_of(led_cdev, struct ideapad_private, kbd_bl.led);
1335
1336         return ideapad_kbd_bl_brightness_set(priv, brightness);
1337 }
1338
1339 static void ideapad_kbd_bl_notify(struct ideapad_private *priv)
1340 {
1341         int brightness;
1342
1343         if (!priv->kbd_bl.initialized)
1344                 return;
1345
1346         brightness = ideapad_kbd_bl_brightness_get(priv);
1347         if (brightness < 0)
1348                 return;
1349
1350         if (brightness == priv->kbd_bl.last_brightness)
1351                 return;
1352
1353         priv->kbd_bl.last_brightness = brightness;
1354
1355         led_classdev_notify_brightness_hw_changed(&priv->kbd_bl.led, brightness);
1356 }
1357
1358 static int ideapad_kbd_bl_init(struct ideapad_private *priv)
1359 {
1360         int brightness, err;
1361
1362         if (!priv->features.kbd_bl)
1363                 return -ENODEV;
1364
1365         if (WARN_ON(priv->kbd_bl.initialized))
1366                 return -EEXIST;
1367
1368         brightness = ideapad_kbd_bl_brightness_get(priv);
1369         if (brightness < 0)
1370                 return brightness;
1371
1372         priv->kbd_bl.last_brightness = brightness;
1373
1374         priv->kbd_bl.led.name                    = "platform::" LED_FUNCTION_KBD_BACKLIGHT;
1375         priv->kbd_bl.led.max_brightness          = 1;
1376         priv->kbd_bl.led.brightness_get          = ideapad_kbd_bl_led_cdev_brightness_get;
1377         priv->kbd_bl.led.brightness_set_blocking = ideapad_kbd_bl_led_cdev_brightness_set;
1378         priv->kbd_bl.led.flags                   = LED_BRIGHT_HW_CHANGED;
1379
1380         err = led_classdev_register(&priv->platform_device->dev, &priv->kbd_bl.led);
1381         if (err)
1382                 return err;
1383
1384         priv->kbd_bl.initialized = true;
1385
1386         return 0;
1387 }
1388
1389 static void ideapad_kbd_bl_exit(struct ideapad_private *priv)
1390 {
1391         if (!priv->kbd_bl.initialized)
1392                 return;
1393
1394         priv->kbd_bl.initialized = false;
1395
1396         led_classdev_unregister(&priv->kbd_bl.led);
1397 }
1398
1399 /*
1400  * module init/exit
1401  */
1402 static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
1403 {
1404         unsigned long value;
1405
1406         if (!priv->features.touchpad_ctrl_via_ec)
1407                 return;
1408
1409         /* Without reading from EC touchpad LED doesn't switch state */
1410         if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
1411                 unsigned char param;
1412                 /*
1413                  * Some IdeaPads don't really turn off touchpad - they only
1414                  * switch the LED state. We (de)activate KBC AUX port to turn
1415                  * touchpad off and on. We send KEY_TOUCHPAD_OFF and
1416                  * KEY_TOUCHPAD_ON to not to get out of sync with LED
1417                  */
1418                 i8042_command(&param, value ? I8042_CMD_AUX_ENABLE : I8042_CMD_AUX_DISABLE);
1419                 ideapad_input_report(priv, value ? 67 : 66);
1420                 sysfs_notify(&priv->platform_device->dev.kobj, NULL, "touchpad");
1421         }
1422 }
1423
1424 static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
1425 {
1426         struct ideapad_private *priv = data;
1427         unsigned long vpc1, vpc2, bit;
1428
1429         if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
1430                 return;
1431
1432         if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
1433                 return;
1434
1435         vpc1 = (vpc2 << 8) | vpc1;
1436
1437         for_each_set_bit (bit, &vpc1, 16) {
1438                 switch (bit) {
1439                 case 13:
1440                 case 11:
1441                 case 8:
1442                 case 7:
1443                 case 6:
1444                         ideapad_input_report(priv, bit);
1445                         break;
1446                 case 10:
1447                         /*
1448                          * This event gets send on a Yoga 300-11IBR when the EC
1449                          * believes that the device has changed between laptop/
1450                          * tent/stand/tablet mode. The EC relies on getting
1451                          * angle info from 2 accelerometers through a special
1452                          * windows service calling a DSM on the DUAL250E ACPI-
1453                          * device. Linux does not do this, making the laptop/
1454                          * tent/stand/tablet mode info unreliable, so we simply
1455                          * ignore these events.
1456                          */
1457                         break;
1458                 case 9:
1459                         ideapad_sync_rfk_state(priv);
1460                         break;
1461                 case 5:
1462                         ideapad_sync_touchpad_state(priv);
1463                         break;
1464                 case 4:
1465                         ideapad_backlight_notify_brightness(priv);
1466                         break;
1467                 case 3:
1468                         ideapad_input_novokey(priv);
1469                         break;
1470                 case 2:
1471                         ideapad_backlight_notify_power(priv);
1472                         break;
1473                 case 1:
1474                         /*
1475                          * Some IdeaPads report event 1 every ~20
1476                          * seconds while on battery power; some
1477                          * report this when changing to/from tablet
1478                          * mode; some report this when the keyboard
1479                          * backlight has changed.
1480                          */
1481                         ideapad_kbd_bl_notify(priv);
1482                         break;
1483                 case 0:
1484                         ideapad_check_special_buttons(priv);
1485                         break;
1486                 default:
1487                         dev_info(&priv->platform_device->dev,
1488                                  "Unknown event: %lu\n", bit);
1489                 }
1490         }
1491 }
1492
1493 #if IS_ENABLED(CONFIG_ACPI_WMI)
1494 static void ideapad_wmi_notify(u32 value, void *context)
1495 {
1496         struct ideapad_private *priv = context;
1497         unsigned long result;
1498
1499         switch (value) {
1500         case 128:
1501                 ideapad_input_report(priv, value);
1502                 break;
1503         case 208:
1504                 if (!eval_hals(priv->adev->handle, &result)) {
1505                         bool state = test_bit(HALS_FNLOCK_STATE_BIT, &result);
1506
1507                         exec_sals(priv->adev->handle, state ? SALS_FNLOCK_ON : SALS_FNLOCK_OFF);
1508                 }
1509                 break;
1510         default:
1511                 dev_info(&priv->platform_device->dev,
1512                          "Unknown WMI event: %u\n", value);
1513         }
1514 }
1515 #endif
1516
1517 /*
1518  * Some ideapads have a hardware rfkill switch, but most do not have one.
1519  * Reading VPCCMD_R_RF always results in 0 on models without a hardware rfkill,
1520  * switch causing ideapad_laptop to wrongly report all radios as hw-blocked.
1521  * There used to be a long list of DMI ids for models without a hw rfkill
1522  * switch here, but that resulted in playing whack a mole.
1523  * More importantly wrongly reporting the wifi radio as hw-blocked, results in
1524  * non working wifi. Whereas not reporting it hw-blocked, when it actually is
1525  * hw-blocked results in an empty SSID list, which is a much more benign
1526  * failure mode.
1527  * So the default now is the much safer option of assuming there is no
1528  * hardware rfkill switch. This default also actually matches most hardware,
1529  * since having a hw rfkill switch is quite rare on modern hardware, so this
1530  * also leads to a much shorter list.
1531  */
1532 static const struct dmi_system_id hw_rfkill_list[] = {
1533         {}
1534 };
1535
1536 static void ideapad_check_features(struct ideapad_private *priv)
1537 {
1538         acpi_handle handle = priv->adev->handle;
1539         unsigned long val;
1540
1541         priv->features.hw_rfkill_switch = dmi_check_system(hw_rfkill_list);
1542
1543         /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */
1544         priv->features.touchpad_ctrl_via_ec = !acpi_dev_present("ELAN0634", NULL, -1);
1545
1546         if (!read_ec_data(handle, VPCCMD_R_FAN, &val))
1547                 priv->features.fan_mode = true;
1548
1549         if (acpi_has_method(handle, "GBMD") && acpi_has_method(handle, "SBMC"))
1550                 priv->features.conservation_mode = true;
1551
1552         if (acpi_has_method(handle, "DYTC"))
1553                 priv->features.dytc = true;
1554
1555         if (acpi_has_method(handle, "HALS") && acpi_has_method(handle, "SALS")) {
1556                 if (!eval_hals(handle, &val)) {
1557                         if (test_bit(HALS_FNLOCK_SUPPORT_BIT, &val))
1558                                 priv->features.fn_lock = true;
1559
1560                         if (test_bit(HALS_KBD_BL_SUPPORT_BIT, &val))
1561                                 priv->features.kbd_bl = true;
1562
1563                         if (test_bit(HALS_USB_CHARGING_SUPPORT_BIT, &val))
1564                                 priv->features.usb_charging = true;
1565                 }
1566         }
1567 }
1568
1569 static int ideapad_acpi_add(struct platform_device *pdev)
1570 {
1571         struct acpi_device *adev = ACPI_COMPANION(&pdev->dev);
1572         struct ideapad_private *priv;
1573         acpi_status status;
1574         unsigned long cfg;
1575         int err, i;
1576
1577         if (!adev || eval_int(adev->handle, "_CFG", &cfg))
1578                 return -ENODEV;
1579
1580         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1581         if (!priv)
1582                 return -ENOMEM;
1583
1584         dev_set_drvdata(&pdev->dev, priv);
1585
1586         priv->cfg = cfg;
1587         priv->adev = adev;
1588         priv->platform_device = pdev;
1589
1590         ideapad_check_features(priv);
1591
1592         err = ideapad_sysfs_init(priv);
1593         if (err)
1594                 return err;
1595
1596         ideapad_debugfs_init(priv);
1597
1598         err = ideapad_input_init(priv);
1599         if (err)
1600                 goto input_failed;
1601
1602         err = ideapad_kbd_bl_init(priv);
1603         if (err) {
1604                 if (err != -ENODEV)
1605                         dev_warn(&pdev->dev, "Could not set up keyboard backlight LED: %d\n", err);
1606                 else
1607                         dev_info(&pdev->dev, "Keyboard backlight control not available\n");
1608         }
1609
1610         /*
1611          * On some models without a hw-switch (the yoga 2 13 at least)
1612          * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
1613          */
1614         if (!priv->features.hw_rfkill_switch)
1615                 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
1616
1617         /* The same for Touchpad */
1618         if (!priv->features.touchpad_ctrl_via_ec)
1619                 write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1);
1620
1621         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1622                 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
1623                         ideapad_register_rfkill(priv, i);
1624
1625         ideapad_sync_rfk_state(priv);
1626         ideapad_sync_touchpad_state(priv);
1627
1628         err = ideapad_dytc_profile_init(priv);
1629         if (err) {
1630                 if (err != -ENODEV)
1631                         dev_warn(&pdev->dev, "Could not set up DYTC interface: %d\n", err);
1632                 else
1633                         dev_info(&pdev->dev, "DYTC interface is not available\n");
1634         }
1635
1636         if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1637                 err = ideapad_backlight_init(priv);
1638                 if (err && err != -ENODEV)
1639                         goto backlight_failed;
1640         }
1641
1642         status = acpi_install_notify_handler(adev->handle,
1643                                              ACPI_DEVICE_NOTIFY,
1644                                              ideapad_acpi_notify, priv);
1645         if (ACPI_FAILURE(status)) {
1646                 err = -EIO;
1647                 goto notification_failed;
1648         }
1649
1650 #if IS_ENABLED(CONFIG_ACPI_WMI)
1651         for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) {
1652                 status = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i],
1653                                                     ideapad_wmi_notify, priv);
1654                 if (ACPI_SUCCESS(status)) {
1655                         priv->fnesc_guid = ideapad_wmi_fnesc_events[i];
1656                         break;
1657                 }
1658         }
1659
1660         if (ACPI_FAILURE(status) && status != AE_NOT_EXIST) {
1661                 err = -EIO;
1662                 goto notification_failed_wmi;
1663         }
1664 #endif
1665
1666         return 0;
1667
1668 #if IS_ENABLED(CONFIG_ACPI_WMI)
1669 notification_failed_wmi:
1670         acpi_remove_notify_handler(priv->adev->handle,
1671                                    ACPI_DEVICE_NOTIFY,
1672                                    ideapad_acpi_notify);
1673 #endif
1674
1675 notification_failed:
1676         ideapad_backlight_exit(priv);
1677
1678 backlight_failed:
1679         ideapad_dytc_profile_exit(priv);
1680
1681         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1682                 ideapad_unregister_rfkill(priv, i);
1683
1684         ideapad_kbd_bl_exit(priv);
1685         ideapad_input_exit(priv);
1686
1687 input_failed:
1688         ideapad_debugfs_exit(priv);
1689         ideapad_sysfs_exit(priv);
1690
1691         return err;
1692 }
1693
1694 static int ideapad_acpi_remove(struct platform_device *pdev)
1695 {
1696         struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
1697         int i;
1698
1699 #if IS_ENABLED(CONFIG_ACPI_WMI)
1700         if (priv->fnesc_guid)
1701                 wmi_remove_notify_handler(priv->fnesc_guid);
1702 #endif
1703
1704         acpi_remove_notify_handler(priv->adev->handle,
1705                                    ACPI_DEVICE_NOTIFY,
1706                                    ideapad_acpi_notify);
1707
1708         ideapad_backlight_exit(priv);
1709         ideapad_dytc_profile_exit(priv);
1710
1711         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1712                 ideapad_unregister_rfkill(priv, i);
1713
1714         ideapad_kbd_bl_exit(priv);
1715         ideapad_input_exit(priv);
1716         ideapad_debugfs_exit(priv);
1717         ideapad_sysfs_exit(priv);
1718
1719         return 0;
1720 }
1721
1722 #ifdef CONFIG_PM_SLEEP
1723 static int ideapad_acpi_resume(struct device *dev)
1724 {
1725         struct ideapad_private *priv = dev_get_drvdata(dev);
1726
1727         ideapad_sync_rfk_state(priv);
1728         ideapad_sync_touchpad_state(priv);
1729
1730         if (priv->dytc)
1731                 dytc_profile_refresh(priv);
1732
1733         return 0;
1734 }
1735 #endif
1736 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
1737
1738 static const struct acpi_device_id ideapad_device_ids[] = {
1739         {"VPC2004", 0},
1740         {"", 0},
1741 };
1742 MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
1743
1744 static struct platform_driver ideapad_acpi_driver = {
1745         .probe = ideapad_acpi_add,
1746         .remove = ideapad_acpi_remove,
1747         .driver = {
1748                 .name   = "ideapad_acpi",
1749                 .pm     = &ideapad_pm,
1750                 .acpi_match_table = ACPI_PTR(ideapad_device_ids),
1751         },
1752 };
1753
1754 module_platform_driver(ideapad_acpi_driver);
1755
1756 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
1757 MODULE_DESCRIPTION("IdeaPad ACPI Extras");
1758 MODULE_LICENSE("GPL");