Merge branch 'mhi-net-immutable' of https://git.kernel.org/pub/scm/linux/kernel/git...
[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/kernel.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/types.h>
15 #include <linux/acpi.h>
16 #include <linux/rfkill.h>
17 #include <linux/platform_device.h>
18 #include <linux/input.h>
19 #include <linux/input/sparse-keymap.h>
20 #include <linux/backlight.h>
21 #include <linux/fb.h>
22 #include <linux/debugfs.h>
23 #include <linux/seq_file.h>
24 #include <linux/i8042.h>
25 #include <linux/dmi.h>
26 #include <linux/device.h>
27 #include <acpi/video.h>
28
29 #define IDEAPAD_RFKILL_DEV_NUM  (3)
30
31 #define BM_CONSERVATION_BIT (5)
32 #define HA_FNLOCK_BIT       (10)
33
34 #define CFG_BT_BIT      (16)
35 #define CFG_3G_BIT      (17)
36 #define CFG_WIFI_BIT    (18)
37 #define CFG_CAMERA_BIT  (19)
38
39 #if IS_ENABLED(CONFIG_ACPI_WMI)
40 static const char *const ideapad_wmi_fnesc_events[] = {
41         "26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", /* Yoga 3 */
42         "56322276-8493-4CE8-A783-98C991274F5E", /* Yoga 700 */
43 };
44 #endif
45
46 enum {
47         BMCMD_CONSERVATION_ON = 3,
48         BMCMD_CONSERVATION_OFF = 5,
49         HACMD_FNLOCK_ON = 0xe,
50         HACMD_FNLOCK_OFF = 0xf,
51 };
52
53 enum {
54         VPCCMD_R_VPC1 = 0x10,
55         VPCCMD_R_BL_MAX,
56         VPCCMD_R_BL,
57         VPCCMD_W_BL,
58         VPCCMD_R_WIFI,
59         VPCCMD_W_WIFI,
60         VPCCMD_R_BT,
61         VPCCMD_W_BT,
62         VPCCMD_R_BL_POWER,
63         VPCCMD_R_NOVO,
64         VPCCMD_R_VPC2,
65         VPCCMD_R_TOUCHPAD,
66         VPCCMD_W_TOUCHPAD,
67         VPCCMD_R_CAMERA,
68         VPCCMD_W_CAMERA,
69         VPCCMD_R_3G,
70         VPCCMD_W_3G,
71         VPCCMD_R_ODD, /* 0x21 */
72         VPCCMD_W_FAN,
73         VPCCMD_R_RF,
74         VPCCMD_W_RF,
75         VPCCMD_R_FAN = 0x2B,
76         VPCCMD_R_SPECIAL_BUTTONS = 0x31,
77         VPCCMD_W_BL_POWER = 0x33,
78 };
79
80 struct ideapad_rfk_priv {
81         int dev;
82         struct ideapad_private *priv;
83 };
84
85 struct ideapad_private {
86         struct acpi_device *adev;
87         struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
88         struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM];
89         struct platform_device *platform_device;
90         struct input_dev *inputdev;
91         struct backlight_device *blightdev;
92         struct dentry *debug;
93         unsigned long cfg;
94         bool has_hw_rfkill_switch;
95         bool has_touchpad_switch;
96         const char *fnesc_guid;
97 };
98
99 static bool no_bt_rfkill;
100 module_param(no_bt_rfkill, bool, 0444);
101 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
102
103 /*
104  * ACPI Helpers
105  */
106 #define IDEAPAD_EC_TIMEOUT (200) /* in ms */
107
108 static int read_method_int(acpi_handle handle, const char *method, int *val)
109 {
110         acpi_status status;
111         unsigned long long result;
112
113         status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
114         if (ACPI_FAILURE(status)) {
115                 *val = -1;
116                 return -1;
117         }
118         *val = result;
119         return 0;
120
121 }
122
123 static int method_gbmd(acpi_handle handle, unsigned long *ret)
124 {
125         int result, val;
126
127         result = read_method_int(handle, "GBMD", &val);
128         *ret = val;
129         return result;
130 }
131
132 static int method_int1(acpi_handle handle, char *method, int cmd)
133 {
134         acpi_status status;
135
136         status = acpi_execute_simple_method(handle, method, cmd);
137         return ACPI_FAILURE(status) ? -1 : 0;
138 }
139
140 static int method_vpcr(acpi_handle handle, int cmd, int *ret)
141 {
142         acpi_status status;
143         unsigned long long result;
144         struct acpi_object_list params;
145         union acpi_object in_obj;
146
147         params.count = 1;
148         params.pointer = &in_obj;
149         in_obj.type = ACPI_TYPE_INTEGER;
150         in_obj.integer.value = cmd;
151
152         status = acpi_evaluate_integer(handle, "VPCR", &params, &result);
153
154         if (ACPI_FAILURE(status)) {
155                 *ret = -1;
156                 return -1;
157         }
158         *ret = result;
159         return 0;
160
161 }
162
163 static int method_vpcw(acpi_handle handle, int cmd, int data)
164 {
165         struct acpi_object_list params;
166         union acpi_object in_obj[2];
167         acpi_status status;
168
169         params.count = 2;
170         params.pointer = in_obj;
171         in_obj[0].type = ACPI_TYPE_INTEGER;
172         in_obj[0].integer.value = cmd;
173         in_obj[1].type = ACPI_TYPE_INTEGER;
174         in_obj[1].integer.value = data;
175
176         status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
177         if (status != AE_OK)
178                 return -1;
179         return 0;
180 }
181
182 static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
183 {
184         int val;
185         unsigned long int end_jiffies;
186
187         if (method_vpcw(handle, 1, cmd))
188                 return -1;
189
190         for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
191              time_before(jiffies, end_jiffies);) {
192                 schedule();
193                 if (method_vpcr(handle, 1, &val))
194                         return -1;
195                 if (val == 0) {
196                         if (method_vpcr(handle, 0, &val))
197                                 return -1;
198                         *data = val;
199                         return 0;
200                 }
201         }
202         pr_err("timeout in %s\n", __func__);
203         return -1;
204 }
205
206 static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
207 {
208         int val;
209         unsigned long int end_jiffies;
210
211         if (method_vpcw(handle, 0, data))
212                 return -1;
213         if (method_vpcw(handle, 1, cmd))
214                 return -1;
215
216         for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
217              time_before(jiffies, end_jiffies);) {
218                 schedule();
219                 if (method_vpcr(handle, 1, &val))
220                         return -1;
221                 if (val == 0)
222                         return 0;
223         }
224         pr_err("timeout in %s\n", __func__);
225         return -1;
226 }
227
228 /*
229  * debugfs
230  */
231 static int debugfs_status_show(struct seq_file *s, void *data)
232 {
233         struct ideapad_private *priv = s->private;
234         unsigned long value;
235
236         if (!priv)
237                 return -EINVAL;
238
239         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))
240                 seq_printf(s, "Backlight max:\t%lu\n", value);
241         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))
242                 seq_printf(s, "Backlight now:\t%lu\n", value);
243         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))
244                 seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
245         seq_printf(s, "=====================\n");
246
247         if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))
248                 seq_printf(s, "Radio status:\t%s(%lu)\n",
249                            value ? "On" : "Off", value);
250         if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))
251                 seq_printf(s, "Wifi status:\t%s(%lu)\n",
252                            value ? "On" : "Off", value);
253         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))
254                 seq_printf(s, "BT status:\t%s(%lu)\n",
255                            value ? "On" : "Off", value);
256         if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))
257                 seq_printf(s, "3G status:\t%s(%lu)\n",
258                            value ? "On" : "Off", value);
259         seq_printf(s, "=====================\n");
260
261         if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))
262                 seq_printf(s, "Touchpad status:%s(%lu)\n",
263                            value ? "On" : "Off", value);
264         if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))
265                 seq_printf(s, "Camera status:\t%s(%lu)\n",
266                            value ? "On" : "Off", value);
267         seq_puts(s, "=====================\n");
268
269         if (!method_gbmd(priv->adev->handle, &value)) {
270                 seq_printf(s, "Conservation mode:\t%s(%lu)\n",
271                            test_bit(BM_CONSERVATION_BIT, &value) ? "On" : "Off",
272                            value);
273         }
274
275         return 0;
276 }
277 DEFINE_SHOW_ATTRIBUTE(debugfs_status);
278
279 static int debugfs_cfg_show(struct seq_file *s, void *data)
280 {
281         struct ideapad_private *priv = s->private;
282
283         if (!priv) {
284                 seq_printf(s, "cfg: N/A\n");
285         } else {
286                 seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
287                            priv->cfg);
288                 if (test_bit(CFG_BT_BIT, &priv->cfg))
289                         seq_printf(s, "Bluetooth ");
290                 if (test_bit(CFG_3G_BIT, &priv->cfg))
291                         seq_printf(s, "3G ");
292                 if (test_bit(CFG_WIFI_BIT, &priv->cfg))
293                         seq_printf(s, "Wireless ");
294                 if (test_bit(CFG_CAMERA_BIT, &priv->cfg))
295                         seq_printf(s, "Camera ");
296                 seq_printf(s, "\nGraphic: ");
297                 switch ((priv->cfg)&0x700) {
298                 case 0x100:
299                         seq_printf(s, "Intel");
300                         break;
301                 case 0x200:
302                         seq_printf(s, "ATI");
303                         break;
304                 case 0x300:
305                         seq_printf(s, "Nvidia");
306                         break;
307                 case 0x400:
308                         seq_printf(s, "Intel and ATI");
309                         break;
310                 case 0x500:
311                         seq_printf(s, "Intel and Nvidia");
312                         break;
313                 }
314                 seq_printf(s, "\n");
315         }
316         return 0;
317 }
318 DEFINE_SHOW_ATTRIBUTE(debugfs_cfg);
319
320 static void ideapad_debugfs_init(struct ideapad_private *priv)
321 {
322         struct dentry *dir;
323
324         dir = debugfs_create_dir("ideapad", NULL);
325         priv->debug = dir;
326
327         debugfs_create_file("cfg", S_IRUGO, dir, priv, &debugfs_cfg_fops);
328         debugfs_create_file("status", S_IRUGO, dir, priv, &debugfs_status_fops);
329 }
330
331 static void ideapad_debugfs_exit(struct ideapad_private *priv)
332 {
333         debugfs_remove_recursive(priv->debug);
334         priv->debug = NULL;
335 }
336
337 /*
338  * sysfs
339  */
340 static ssize_t show_ideapad_cam(struct device *dev,
341                                 struct device_attribute *attr,
342                                 char *buf)
343 {
344         unsigned long result;
345         struct ideapad_private *priv = dev_get_drvdata(dev);
346
347         if (read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result))
348                 return sprintf(buf, "-1\n");
349         return sprintf(buf, "%lu\n", result);
350 }
351
352 static ssize_t store_ideapad_cam(struct device *dev,
353                                  struct device_attribute *attr,
354                                  const char *buf, size_t count)
355 {
356         int ret, state;
357         struct ideapad_private *priv = dev_get_drvdata(dev);
358
359         if (!count)
360                 return 0;
361         if (sscanf(buf, "%i", &state) != 1)
362                 return -EINVAL;
363         ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
364         if (ret < 0)
365                 return -EIO;
366         return count;
367 }
368
369 static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
370
371 static ssize_t show_ideapad_fan(struct device *dev,
372                                 struct device_attribute *attr,
373                                 char *buf)
374 {
375         unsigned long result;
376         struct ideapad_private *priv = dev_get_drvdata(dev);
377
378         if (read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result))
379                 return sprintf(buf, "-1\n");
380         return sprintf(buf, "%lu\n", result);
381 }
382
383 static ssize_t store_ideapad_fan(struct device *dev,
384                                  struct device_attribute *attr,
385                                  const char *buf, size_t count)
386 {
387         int ret, state;
388         struct ideapad_private *priv = dev_get_drvdata(dev);
389
390         if (!count)
391                 return 0;
392         if (sscanf(buf, "%i", &state) != 1)
393                 return -EINVAL;
394         if (state < 0 || state > 4 || state == 3)
395                 return -EINVAL;
396         ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
397         if (ret < 0)
398                 return -EIO;
399         return count;
400 }
401
402 static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan);
403
404 static ssize_t touchpad_show(struct device *dev,
405                              struct device_attribute *attr,
406                              char *buf)
407 {
408         struct ideapad_private *priv = dev_get_drvdata(dev);
409         unsigned long result;
410
411         if (read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result))
412                 return sprintf(buf, "-1\n");
413         return sprintf(buf, "%lu\n", result);
414 }
415
416 /* Switch to RO for now: It might be revisited in the future */
417 static ssize_t __maybe_unused touchpad_store(struct device *dev,
418                                              struct device_attribute *attr,
419                                              const char *buf, size_t count)
420 {
421         struct ideapad_private *priv = dev_get_drvdata(dev);
422         bool state;
423         int ret;
424
425         ret = kstrtobool(buf, &state);
426         if (ret)
427                 return ret;
428
429         ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state);
430         if (ret < 0)
431                 return -EIO;
432         return count;
433 }
434
435 static DEVICE_ATTR_RO(touchpad);
436
437 static ssize_t conservation_mode_show(struct device *dev,
438                                 struct device_attribute *attr,
439                                 char *buf)
440 {
441         struct ideapad_private *priv = dev_get_drvdata(dev);
442         unsigned long result;
443
444         if (method_gbmd(priv->adev->handle, &result))
445                 return sprintf(buf, "-1\n");
446         return sprintf(buf, "%u\n", test_bit(BM_CONSERVATION_BIT, &result));
447 }
448
449 static ssize_t conservation_mode_store(struct device *dev,
450                                  struct device_attribute *attr,
451                                  const char *buf, size_t count)
452 {
453         struct ideapad_private *priv = dev_get_drvdata(dev);
454         bool state;
455         int ret;
456
457         ret = kstrtobool(buf, &state);
458         if (ret)
459                 return ret;
460
461         ret = method_int1(priv->adev->handle, "SBMC", state ?
462                                               BMCMD_CONSERVATION_ON :
463                                               BMCMD_CONSERVATION_OFF);
464         if (ret < 0)
465                 return -EIO;
466         return count;
467 }
468
469 static DEVICE_ATTR_RW(conservation_mode);
470
471 static ssize_t fn_lock_show(struct device *dev,
472                             struct device_attribute *attr,
473                             char *buf)
474 {
475         struct ideapad_private *priv = dev_get_drvdata(dev);
476         unsigned long result;
477         int hals;
478         int fail = read_method_int(priv->adev->handle, "HALS", &hals);
479
480         if (fail)
481                 return sprintf(buf, "-1\n");
482
483         result = hals;
484         return sprintf(buf, "%u\n", test_bit(HA_FNLOCK_BIT, &result));
485 }
486
487 static ssize_t fn_lock_store(struct device *dev,
488                              struct device_attribute *attr,
489                              const char *buf, size_t count)
490 {
491         struct ideapad_private *priv = dev_get_drvdata(dev);
492         bool state;
493         int ret;
494
495         ret = kstrtobool(buf, &state);
496         if (ret)
497                 return ret;
498
499         ret = method_int1(priv->adev->handle, "SALS", state ?
500                           HACMD_FNLOCK_ON :
501                           HACMD_FNLOCK_OFF);
502         if (ret < 0)
503                 return -EIO;
504         return count;
505 }
506
507 static DEVICE_ATTR_RW(fn_lock);
508
509
510 static struct attribute *ideapad_attributes[] = {
511         &dev_attr_camera_power.attr,
512         &dev_attr_fan_mode.attr,
513         &dev_attr_touchpad.attr,
514         &dev_attr_conservation_mode.attr,
515         &dev_attr_fn_lock.attr,
516         NULL
517 };
518
519 static umode_t ideapad_is_visible(struct kobject *kobj,
520                                  struct attribute *attr,
521                                  int idx)
522 {
523         struct device *dev = container_of(kobj, struct device, kobj);
524         struct ideapad_private *priv = dev_get_drvdata(dev);
525         bool supported;
526
527         if (attr == &dev_attr_camera_power.attr)
528                 supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
529         else if (attr == &dev_attr_fan_mode.attr) {
530                 unsigned long value;
531                 supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN,
532                                           &value);
533         } else if (attr == &dev_attr_conservation_mode.attr) {
534                 supported = acpi_has_method(priv->adev->handle, "GBMD") &&
535                             acpi_has_method(priv->adev->handle, "SBMC");
536         } else if (attr == &dev_attr_fn_lock.attr) {
537                 supported = acpi_has_method(priv->adev->handle, "HALS") &&
538                         acpi_has_method(priv->adev->handle, "SALS");
539         } else if (attr == &dev_attr_touchpad.attr)
540                 supported = priv->has_touchpad_switch;
541         else
542                 supported = true;
543
544         return supported ? attr->mode : 0;
545 }
546
547 static const struct attribute_group ideapad_attribute_group = {
548         .is_visible = ideapad_is_visible,
549         .attrs = ideapad_attributes
550 };
551
552 /*
553  * Rfkill
554  */
555 struct ideapad_rfk_data {
556         char *name;
557         int cfgbit;
558         int opcode;
559         int type;
560 };
561
562 static const struct ideapad_rfk_data ideapad_rfk_data[] = {
563         { "ideapad_wlan",    CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
564         { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
565         { "ideapad_3g",        CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
566 };
567
568 static int ideapad_rfk_set(void *data, bool blocked)
569 {
570         struct ideapad_rfk_priv *priv = data;
571         int opcode = ideapad_rfk_data[priv->dev].opcode;
572
573         return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked);
574 }
575
576 static const struct rfkill_ops ideapad_rfk_ops = {
577         .set_block = ideapad_rfk_set,
578 };
579
580 static void ideapad_sync_rfk_state(struct ideapad_private *priv)
581 {
582         unsigned long hw_blocked = 0;
583         int i;
584
585         if (priv->has_hw_rfkill_switch) {
586                 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
587                         return;
588                 hw_blocked = !hw_blocked;
589         }
590
591         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
592                 if (priv->rfk[i])
593                         rfkill_set_hw_state(priv->rfk[i], hw_blocked);
594 }
595
596 static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
597 {
598         int ret;
599         unsigned long sw_blocked;
600
601         if (no_bt_rfkill &&
602             (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
603                 /* Force to enable bluetooth when no_bt_rfkill=1 */
604                 write_ec_cmd(priv->adev->handle,
605                              ideapad_rfk_data[dev].opcode, 1);
606                 return 0;
607         }
608         priv->rfk_priv[dev].dev = dev;
609         priv->rfk_priv[dev].priv = priv;
610
611         priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name,
612                                       &priv->platform_device->dev,
613                                       ideapad_rfk_data[dev].type,
614                                       &ideapad_rfk_ops,
615                                       &priv->rfk_priv[dev]);
616         if (!priv->rfk[dev])
617                 return -ENOMEM;
618
619         if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,
620                          &sw_blocked)) {
621                 rfkill_init_sw_state(priv->rfk[dev], 0);
622         } else {
623                 sw_blocked = !sw_blocked;
624                 rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
625         }
626
627         ret = rfkill_register(priv->rfk[dev]);
628         if (ret) {
629                 rfkill_destroy(priv->rfk[dev]);
630                 return ret;
631         }
632         return 0;
633 }
634
635 static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
636 {
637         if (!priv->rfk[dev])
638                 return;
639
640         rfkill_unregister(priv->rfk[dev]);
641         rfkill_destroy(priv->rfk[dev]);
642 }
643
644 /*
645  * Platform device
646  */
647 static int ideapad_sysfs_init(struct ideapad_private *priv)
648 {
649         return sysfs_create_group(&priv->platform_device->dev.kobj,
650                                     &ideapad_attribute_group);
651 }
652
653 static void ideapad_sysfs_exit(struct ideapad_private *priv)
654 {
655         sysfs_remove_group(&priv->platform_device->dev.kobj,
656                            &ideapad_attribute_group);
657 }
658
659 /*
660  * input device
661  */
662 static const struct key_entry ideapad_keymap[] = {
663         { KE_KEY, 6,  { KEY_SWITCHVIDEOMODE } },
664         { KE_KEY, 7,  { KEY_CAMERA } },
665         { KE_KEY, 8,  { KEY_MICMUTE } },
666         { KE_KEY, 11, { KEY_F16 } },
667         { KE_KEY, 13, { KEY_WLAN } },
668         { KE_KEY, 16, { KEY_PROG1 } },
669         { KE_KEY, 17, { KEY_PROG2 } },
670         { KE_KEY, 64, { KEY_PROG3 } },
671         { KE_KEY, 65, { KEY_PROG4 } },
672         { KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
673         { KE_KEY, 67, { KEY_TOUCHPAD_ON } },
674         { KE_KEY, 128, { KEY_ESC } },
675
676         { KE_END, 0 },
677 };
678
679 static int ideapad_input_init(struct ideapad_private *priv)
680 {
681         struct input_dev *inputdev;
682         int error;
683
684         inputdev = input_allocate_device();
685         if (!inputdev)
686                 return -ENOMEM;
687
688         inputdev->name = "Ideapad extra buttons";
689         inputdev->phys = "ideapad/input0";
690         inputdev->id.bustype = BUS_HOST;
691         inputdev->dev.parent = &priv->platform_device->dev;
692
693         error = sparse_keymap_setup(inputdev, ideapad_keymap, NULL);
694         if (error) {
695                 pr_err("Unable to setup input device keymap\n");
696                 goto err_free_dev;
697         }
698
699         error = input_register_device(inputdev);
700         if (error) {
701                 pr_err("Unable to register input device\n");
702                 goto err_free_dev;
703         }
704
705         priv->inputdev = inputdev;
706         return 0;
707
708 err_free_dev:
709         input_free_device(inputdev);
710         return error;
711 }
712
713 static void ideapad_input_exit(struct ideapad_private *priv)
714 {
715         input_unregister_device(priv->inputdev);
716         priv->inputdev = NULL;
717 }
718
719 static void ideapad_input_report(struct ideapad_private *priv,
720                                  unsigned long scancode)
721 {
722         sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
723 }
724
725 static void ideapad_input_novokey(struct ideapad_private *priv)
726 {
727         unsigned long long_pressed;
728
729         if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
730                 return;
731         if (long_pressed)
732                 ideapad_input_report(priv, 17);
733         else
734                 ideapad_input_report(priv, 16);
735 }
736
737 static void ideapad_check_special_buttons(struct ideapad_private *priv)
738 {
739         unsigned long bit, value;
740
741         read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
742
743         for (bit = 0; bit < 16; bit++) {
744                 if (test_bit(bit, &value)) {
745                         switch (bit) {
746                         case 0: /* Z580 */
747                         case 6: /* Z570 */
748                                 /* Thermal Management button */
749                                 ideapad_input_report(priv, 65);
750                                 break;
751                         case 1:
752                                 /* OneKey Theater button */
753                                 ideapad_input_report(priv, 64);
754                                 break;
755                         default:
756                                 pr_info("Unknown special button: %lu\n", bit);
757                                 break;
758                         }
759                 }
760         }
761 }
762
763 /*
764  * backlight
765  */
766 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
767 {
768         struct ideapad_private *priv = bl_get_data(blightdev);
769         unsigned long now;
770
771         if (!priv)
772                 return -EINVAL;
773
774         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
775                 return -EIO;
776         return now;
777 }
778
779 static int ideapad_backlight_update_status(struct backlight_device *blightdev)
780 {
781         struct ideapad_private *priv = bl_get_data(blightdev);
782
783         if (!priv)
784                 return -EINVAL;
785
786         if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
787                          blightdev->props.brightness))
788                 return -EIO;
789         if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
790                          blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
791                 return -EIO;
792
793         return 0;
794 }
795
796 static const struct backlight_ops ideapad_backlight_ops = {
797         .get_brightness = ideapad_backlight_get_brightness,
798         .update_status = ideapad_backlight_update_status,
799 };
800
801 static int ideapad_backlight_init(struct ideapad_private *priv)
802 {
803         struct backlight_device *blightdev;
804         struct backlight_properties props;
805         unsigned long max, now, power;
806
807         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max))
808                 return -EIO;
809         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
810                 return -EIO;
811         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
812                 return -EIO;
813
814         memset(&props, 0, sizeof(struct backlight_properties));
815         props.max_brightness = max;
816         props.type = BACKLIGHT_PLATFORM;
817         blightdev = backlight_device_register("ideapad",
818                                               &priv->platform_device->dev,
819                                               priv,
820                                               &ideapad_backlight_ops,
821                                               &props);
822         if (IS_ERR(blightdev)) {
823                 pr_err("Could not register backlight device\n");
824                 return PTR_ERR(blightdev);
825         }
826
827         priv->blightdev = blightdev;
828         blightdev->props.brightness = now;
829         blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
830         backlight_update_status(blightdev);
831
832         return 0;
833 }
834
835 static void ideapad_backlight_exit(struct ideapad_private *priv)
836 {
837         backlight_device_unregister(priv->blightdev);
838         priv->blightdev = NULL;
839 }
840
841 static void ideapad_backlight_notify_power(struct ideapad_private *priv)
842 {
843         unsigned long power;
844         struct backlight_device *blightdev = priv->blightdev;
845
846         if (!blightdev)
847                 return;
848         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
849                 return;
850         blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
851 }
852
853 static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
854 {
855         unsigned long now;
856
857         /* if we control brightness via acpi video driver */
858         if (priv->blightdev == NULL) {
859                 read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
860                 return;
861         }
862
863         backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
864 }
865
866 /*
867  * module init/exit
868  */
869 static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
870 {
871         unsigned long value;
872
873         if (!priv->has_touchpad_switch)
874                 return;
875
876         /* Without reading from EC touchpad LED doesn't switch state */
877         if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
878                 /* Some IdeaPads don't really turn off touchpad - they only
879                  * switch the LED state. We (de)activate KBC AUX port to turn
880                  * touchpad off and on. We send KEY_TOUCHPAD_OFF and
881                  * KEY_TOUCHPAD_ON to not to get out of sync with LED */
882                 unsigned char param;
883                 i8042_command(&param, value ? I8042_CMD_AUX_ENABLE :
884                               I8042_CMD_AUX_DISABLE);
885                 ideapad_input_report(priv, value ? 67 : 66);
886         }
887 }
888
889 static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
890 {
891         struct ideapad_private *priv = data;
892         unsigned long vpc1, vpc2, vpc_bit;
893
894         if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
895                 return;
896         if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
897                 return;
898
899         vpc1 = (vpc2 << 8) | vpc1;
900         for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
901                 if (test_bit(vpc_bit, &vpc1)) {
902                         switch (vpc_bit) {
903                         case 9:
904                                 ideapad_sync_rfk_state(priv);
905                                 break;
906                         case 13:
907                         case 11:
908                         case 8:
909                         case 7:
910                         case 6:
911                                 ideapad_input_report(priv, vpc_bit);
912                                 break;
913                         case 5:
914                                 ideapad_sync_touchpad_state(priv);
915                                 break;
916                         case 4:
917                                 ideapad_backlight_notify_brightness(priv);
918                                 break;
919                         case 3:
920                                 ideapad_input_novokey(priv);
921                                 break;
922                         case 2:
923                                 ideapad_backlight_notify_power(priv);
924                                 break;
925                         case 0:
926                                 ideapad_check_special_buttons(priv);
927                                 break;
928                         case 1:
929                                 /* Some IdeaPads report event 1 every ~20
930                                  * seconds while on battery power; some
931                                  * report this when changing to/from tablet
932                                  * mode. Squelch this event.
933                                  */
934                                 break;
935                         default:
936                                 pr_info("Unknown event: %lu\n", vpc_bit);
937                         }
938                 }
939         }
940 }
941
942 #if IS_ENABLED(CONFIG_ACPI_WMI)
943 static void ideapad_wmi_notify(u32 value, void *context)
944 {
945         switch (value) {
946         case 128:
947                 ideapad_input_report(context, value);
948                 break;
949         default:
950                 pr_info("Unknown WMI event %u\n", value);
951         }
952 }
953 #endif
954
955 /*
956  * Some ideapads have a hardware rfkill switch, but most do not have one.
957  * Reading VPCCMD_R_RF always results in 0 on models without a hardware rfkill,
958  * switch causing ideapad_laptop to wrongly report all radios as hw-blocked.
959  * There used to be a long list of DMI ids for models without a hw rfkill
960  * switch here, but that resulted in playing whack a mole.
961  * More importantly wrongly reporting the wifi radio as hw-blocked, results in
962  * non working wifi. Whereas not reporting it hw-blocked, when it actually is
963  * hw-blocked results in an empty SSID list, which is a much more benign
964  * failure mode.
965  * So the default now is the much safer option of assuming there is no
966  * hardware rfkill switch. This default also actually matches most hardware,
967  * since having a hw rfkill switch is quite rare on modern hardware, so this
968  * also leads to a much shorter list.
969  */
970 static const struct dmi_system_id hw_rfkill_list[] = {
971         {}
972 };
973
974 static int ideapad_acpi_add(struct platform_device *pdev)
975 {
976         int ret, i;
977         int cfg;
978         struct ideapad_private *priv;
979         struct acpi_device *adev;
980
981         ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
982         if (ret)
983                 return -ENODEV;
984
985         if (read_method_int(adev->handle, "_CFG", &cfg))
986                 return -ENODEV;
987
988         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
989         if (!priv)
990                 return -ENOMEM;
991
992         dev_set_drvdata(&pdev->dev, priv);
993         priv->cfg = cfg;
994         priv->adev = adev;
995         priv->platform_device = pdev;
996         priv->has_hw_rfkill_switch = dmi_check_system(hw_rfkill_list);
997
998         /* Most ideapads with ELAN0634 touchpad don't use EC touchpad switch */
999         priv->has_touchpad_switch = !acpi_dev_present("ELAN0634", NULL, -1);
1000
1001         ret = ideapad_sysfs_init(priv);
1002         if (ret)
1003                 return ret;
1004
1005         ideapad_debugfs_init(priv);
1006
1007         ret = ideapad_input_init(priv);
1008         if (ret)
1009                 goto input_failed;
1010
1011         /*
1012          * On some models without a hw-switch (the yoga 2 13 at least)
1013          * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
1014          */
1015         if (!priv->has_hw_rfkill_switch)
1016                 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
1017
1018         /* The same for Touchpad */
1019         if (!priv->has_touchpad_switch)
1020                 write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, 1);
1021
1022         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1023                 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
1024                         ideapad_register_rfkill(priv, i);
1025
1026         ideapad_sync_rfk_state(priv);
1027         ideapad_sync_touchpad_state(priv);
1028
1029         if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1030                 ret = ideapad_backlight_init(priv);
1031                 if (ret && ret != -ENODEV)
1032                         goto backlight_failed;
1033         }
1034         ret = acpi_install_notify_handler(adev->handle,
1035                 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
1036         if (ret)
1037                 goto notification_failed;
1038
1039 #if IS_ENABLED(CONFIG_ACPI_WMI)
1040         for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) {
1041                 ret = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i],
1042                                                  ideapad_wmi_notify, priv);
1043                 if (ret == AE_OK) {
1044                         priv->fnesc_guid = ideapad_wmi_fnesc_events[i];
1045                         break;
1046                 }
1047         }
1048         if (ret != AE_OK && ret != AE_NOT_EXIST)
1049                 goto notification_failed_wmi;
1050 #endif
1051
1052         return 0;
1053 #if IS_ENABLED(CONFIG_ACPI_WMI)
1054 notification_failed_wmi:
1055         acpi_remove_notify_handler(priv->adev->handle,
1056                 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
1057 #endif
1058 notification_failed:
1059         ideapad_backlight_exit(priv);
1060 backlight_failed:
1061         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1062                 ideapad_unregister_rfkill(priv, i);
1063         ideapad_input_exit(priv);
1064 input_failed:
1065         ideapad_debugfs_exit(priv);
1066         ideapad_sysfs_exit(priv);
1067         return ret;
1068 }
1069
1070 static int ideapad_acpi_remove(struct platform_device *pdev)
1071 {
1072         struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
1073         int i;
1074
1075 #if IS_ENABLED(CONFIG_ACPI_WMI)
1076         if (priv->fnesc_guid)
1077                 wmi_remove_notify_handler(priv->fnesc_guid);
1078 #endif
1079         acpi_remove_notify_handler(priv->adev->handle,
1080                 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
1081         ideapad_backlight_exit(priv);
1082         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1083                 ideapad_unregister_rfkill(priv, i);
1084         ideapad_input_exit(priv);
1085         ideapad_debugfs_exit(priv);
1086         ideapad_sysfs_exit(priv);
1087         dev_set_drvdata(&pdev->dev, NULL);
1088
1089         return 0;
1090 }
1091
1092 #ifdef CONFIG_PM_SLEEP
1093 static int ideapad_acpi_resume(struct device *device)
1094 {
1095         struct ideapad_private *priv;
1096
1097         if (!device)
1098                 return -EINVAL;
1099         priv = dev_get_drvdata(device);
1100
1101         ideapad_sync_rfk_state(priv);
1102         ideapad_sync_touchpad_state(priv);
1103         return 0;
1104 }
1105 #endif
1106 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
1107
1108 static const struct acpi_device_id ideapad_device_ids[] = {
1109         { "VPC2004", 0},
1110         { "", 0},
1111 };
1112 MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
1113
1114 static struct platform_driver ideapad_acpi_driver = {
1115         .probe = ideapad_acpi_add,
1116         .remove = ideapad_acpi_remove,
1117         .driver = {
1118                 .name   = "ideapad_acpi",
1119                 .pm     = &ideapad_pm,
1120                 .acpi_match_table = ACPI_PTR(ideapad_device_ids),
1121         },
1122 };
1123
1124 module_platform_driver(ideapad_acpi_driver);
1125
1126 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
1127 MODULE_DESCRIPTION("IdeaPad ACPI Extras");
1128 MODULE_LICENSE("GPL");