Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[sfrench/cifs-2.6.git] / drivers / platform / x86 / ideapad-laptop.c
1 /*
2  *  ideapad-laptop.c - Lenovo IdeaPad ACPI Extras
3  *
4  *  Copyright © 2010 Intel Corporation
5  *  Copyright © 2010 David Woodhouse <dwmw2@infradead.org>
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  *  02110-1301, USA.
21  */
22
23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/types.h>
29 #include <linux/acpi.h>
30 #include <linux/rfkill.h>
31 #include <linux/platform_device.h>
32 #include <linux/input.h>
33 #include <linux/input/sparse-keymap.h>
34 #include <linux/backlight.h>
35 #include <linux/fb.h>
36 #include <linux/debugfs.h>
37 #include <linux/seq_file.h>
38 #include <linux/i8042.h>
39 #include <linux/dmi.h>
40 #include <linux/device.h>
41 #include <acpi/video.h>
42
43 #define IDEAPAD_RFKILL_DEV_NUM  (3)
44
45 #define BM_CONSERVATION_BIT (5)
46 #define HA_FNLOCK_BIT       (10)
47
48 #define CFG_BT_BIT      (16)
49 #define CFG_3G_BIT      (17)
50 #define CFG_WIFI_BIT    (18)
51 #define CFG_CAMERA_BIT  (19)
52
53 #if IS_ENABLED(CONFIG_ACPI_WMI)
54 static const char *const ideapad_wmi_fnesc_events[] = {
55         "26CAB2E5-5CF1-46AE-AAC3-4A12B6BA50E6", /* Yoga 3 */
56         "56322276-8493-4CE8-A783-98C991274F5E", /* Yoga 700 */
57 };
58 #endif
59
60 enum {
61         BMCMD_CONSERVATION_ON = 3,
62         BMCMD_CONSERVATION_OFF = 5,
63         HACMD_FNLOCK_ON = 0xe,
64         HACMD_FNLOCK_OFF = 0xf,
65 };
66
67 enum {
68         VPCCMD_R_VPC1 = 0x10,
69         VPCCMD_R_BL_MAX,
70         VPCCMD_R_BL,
71         VPCCMD_W_BL,
72         VPCCMD_R_WIFI,
73         VPCCMD_W_WIFI,
74         VPCCMD_R_BT,
75         VPCCMD_W_BT,
76         VPCCMD_R_BL_POWER,
77         VPCCMD_R_NOVO,
78         VPCCMD_R_VPC2,
79         VPCCMD_R_TOUCHPAD,
80         VPCCMD_W_TOUCHPAD,
81         VPCCMD_R_CAMERA,
82         VPCCMD_W_CAMERA,
83         VPCCMD_R_3G,
84         VPCCMD_W_3G,
85         VPCCMD_R_ODD, /* 0x21 */
86         VPCCMD_W_FAN,
87         VPCCMD_R_RF,
88         VPCCMD_W_RF,
89         VPCCMD_R_FAN = 0x2B,
90         VPCCMD_R_SPECIAL_BUTTONS = 0x31,
91         VPCCMD_W_BL_POWER = 0x33,
92 };
93
94 struct ideapad_rfk_priv {
95         int dev;
96         struct ideapad_private *priv;
97 };
98
99 struct ideapad_private {
100         struct acpi_device *adev;
101         struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
102         struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM];
103         struct platform_device *platform_device;
104         struct input_dev *inputdev;
105         struct backlight_device *blightdev;
106         struct dentry *debug;
107         unsigned long cfg;
108         bool has_hw_rfkill_switch;
109         const char *fnesc_guid;
110 };
111
112 static bool no_bt_rfkill;
113 module_param(no_bt_rfkill, bool, 0444);
114 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
115
116 /*
117  * ACPI Helpers
118  */
119 #define IDEAPAD_EC_TIMEOUT (200) /* in ms */
120
121 static int read_method_int(acpi_handle handle, const char *method, int *val)
122 {
123         acpi_status status;
124         unsigned long long result;
125
126         status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
127         if (ACPI_FAILURE(status)) {
128                 *val = -1;
129                 return -1;
130         }
131         *val = result;
132         return 0;
133
134 }
135
136 static int method_gbmd(acpi_handle handle, unsigned long *ret)
137 {
138         int result, val;
139
140         result = read_method_int(handle, "GBMD", &val);
141         *ret = val;
142         return result;
143 }
144
145 static int method_int1(acpi_handle handle, char *method, int cmd)
146 {
147         acpi_status status;
148
149         status = acpi_execute_simple_method(handle, method, cmd);
150         return ACPI_FAILURE(status) ? -1 : 0;
151 }
152
153 static int method_vpcr(acpi_handle handle, int cmd, int *ret)
154 {
155         acpi_status status;
156         unsigned long long result;
157         struct acpi_object_list params;
158         union acpi_object in_obj;
159
160         params.count = 1;
161         params.pointer = &in_obj;
162         in_obj.type = ACPI_TYPE_INTEGER;
163         in_obj.integer.value = cmd;
164
165         status = acpi_evaluate_integer(handle, "VPCR", &params, &result);
166
167         if (ACPI_FAILURE(status)) {
168                 *ret = -1;
169                 return -1;
170         }
171         *ret = result;
172         return 0;
173
174 }
175
176 static int method_vpcw(acpi_handle handle, int cmd, int data)
177 {
178         struct acpi_object_list params;
179         union acpi_object in_obj[2];
180         acpi_status status;
181
182         params.count = 2;
183         params.pointer = in_obj;
184         in_obj[0].type = ACPI_TYPE_INTEGER;
185         in_obj[0].integer.value = cmd;
186         in_obj[1].type = ACPI_TYPE_INTEGER;
187         in_obj[1].integer.value = data;
188
189         status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
190         if (status != AE_OK)
191                 return -1;
192         return 0;
193 }
194
195 static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
196 {
197         int val;
198         unsigned long int end_jiffies;
199
200         if (method_vpcw(handle, 1, cmd))
201                 return -1;
202
203         for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
204              time_before(jiffies, end_jiffies);) {
205                 schedule();
206                 if (method_vpcr(handle, 1, &val))
207                         return -1;
208                 if (val == 0) {
209                         if (method_vpcr(handle, 0, &val))
210                                 return -1;
211                         *data = val;
212                         return 0;
213                 }
214         }
215         pr_err("timeout in read_ec_cmd\n");
216         return -1;
217 }
218
219 static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
220 {
221         int val;
222         unsigned long int end_jiffies;
223
224         if (method_vpcw(handle, 0, data))
225                 return -1;
226         if (method_vpcw(handle, 1, cmd))
227                 return -1;
228
229         for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
230              time_before(jiffies, end_jiffies);) {
231                 schedule();
232                 if (method_vpcr(handle, 1, &val))
233                         return -1;
234                 if (val == 0)
235                         return 0;
236         }
237         pr_err("timeout in %s\n", __func__);
238         return -1;
239 }
240
241 /*
242  * debugfs
243  */
244 static int debugfs_status_show(struct seq_file *s, void *data)
245 {
246         struct ideapad_private *priv = s->private;
247         unsigned long value;
248
249         if (!priv)
250                 return -EINVAL;
251
252         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))
253                 seq_printf(s, "Backlight max:\t%lu\n", value);
254         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))
255                 seq_printf(s, "Backlight now:\t%lu\n", value);
256         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))
257                 seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
258         seq_printf(s, "=====================\n");
259
260         if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))
261                 seq_printf(s, "Radio status:\t%s(%lu)\n",
262                            value ? "On" : "Off", value);
263         if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))
264                 seq_printf(s, "Wifi status:\t%s(%lu)\n",
265                            value ? "On" : "Off", value);
266         if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))
267                 seq_printf(s, "BT status:\t%s(%lu)\n",
268                            value ? "On" : "Off", value);
269         if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))
270                 seq_printf(s, "3G status:\t%s(%lu)\n",
271                            value ? "On" : "Off", value);
272         seq_printf(s, "=====================\n");
273
274         if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))
275                 seq_printf(s, "Touchpad status:%s(%lu)\n",
276                            value ? "On" : "Off", value);
277         if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))
278                 seq_printf(s, "Camera status:\t%s(%lu)\n",
279                            value ? "On" : "Off", value);
280         seq_puts(s, "=====================\n");
281
282         if (!method_gbmd(priv->adev->handle, &value)) {
283                 seq_printf(s, "Conservation mode:\t%s(%lu)\n",
284                            test_bit(BM_CONSERVATION_BIT, &value) ? "On" : "Off",
285                            value);
286         }
287
288         return 0;
289 }
290 DEFINE_SHOW_ATTRIBUTE(debugfs_status);
291
292 static int debugfs_cfg_show(struct seq_file *s, void *data)
293 {
294         struct ideapad_private *priv = s->private;
295
296         if (!priv) {
297                 seq_printf(s, "cfg: N/A\n");
298         } else {
299                 seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
300                            priv->cfg);
301                 if (test_bit(CFG_BT_BIT, &priv->cfg))
302                         seq_printf(s, "Bluetooth ");
303                 if (test_bit(CFG_3G_BIT, &priv->cfg))
304                         seq_printf(s, "3G ");
305                 if (test_bit(CFG_WIFI_BIT, &priv->cfg))
306                         seq_printf(s, "Wireless ");
307                 if (test_bit(CFG_CAMERA_BIT, &priv->cfg))
308                         seq_printf(s, "Camera ");
309                 seq_printf(s, "\nGraphic: ");
310                 switch ((priv->cfg)&0x700) {
311                 case 0x100:
312                         seq_printf(s, "Intel");
313                         break;
314                 case 0x200:
315                         seq_printf(s, "ATI");
316                         break;
317                 case 0x300:
318                         seq_printf(s, "Nvidia");
319                         break;
320                 case 0x400:
321                         seq_printf(s, "Intel and ATI");
322                         break;
323                 case 0x500:
324                         seq_printf(s, "Intel and Nvidia");
325                         break;
326                 }
327                 seq_printf(s, "\n");
328         }
329         return 0;
330 }
331 DEFINE_SHOW_ATTRIBUTE(debugfs_cfg);
332
333 static int ideapad_debugfs_init(struct ideapad_private *priv)
334 {
335         struct dentry *node;
336
337         priv->debug = debugfs_create_dir("ideapad", NULL);
338         if (priv->debug == NULL) {
339                 pr_err("failed to create debugfs directory");
340                 goto errout;
341         }
342
343         node = debugfs_create_file("cfg", S_IRUGO, priv->debug, priv,
344                                    &debugfs_cfg_fops);
345         if (!node) {
346                 pr_err("failed to create cfg in debugfs");
347                 goto errout;
348         }
349
350         node = debugfs_create_file("status", S_IRUGO, priv->debug, priv,
351                                    &debugfs_status_fops);
352         if (!node) {
353                 pr_err("failed to create status in debugfs");
354                 goto errout;
355         }
356
357         return 0;
358
359 errout:
360         return -ENOMEM;
361 }
362
363 static void ideapad_debugfs_exit(struct ideapad_private *priv)
364 {
365         debugfs_remove_recursive(priv->debug);
366         priv->debug = NULL;
367 }
368
369 /*
370  * sysfs
371  */
372 static ssize_t show_ideapad_cam(struct device *dev,
373                                 struct device_attribute *attr,
374                                 char *buf)
375 {
376         unsigned long result;
377         struct ideapad_private *priv = dev_get_drvdata(dev);
378
379         if (read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result))
380                 return sprintf(buf, "-1\n");
381         return sprintf(buf, "%lu\n", result);
382 }
383
384 static ssize_t store_ideapad_cam(struct device *dev,
385                                  struct device_attribute *attr,
386                                  const char *buf, size_t count)
387 {
388         int ret, state;
389         struct ideapad_private *priv = dev_get_drvdata(dev);
390
391         if (!count)
392                 return 0;
393         if (sscanf(buf, "%i", &state) != 1)
394                 return -EINVAL;
395         ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
396         if (ret < 0)
397                 return -EIO;
398         return count;
399 }
400
401 static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
402
403 static ssize_t show_ideapad_fan(struct device *dev,
404                                 struct device_attribute *attr,
405                                 char *buf)
406 {
407         unsigned long result;
408         struct ideapad_private *priv = dev_get_drvdata(dev);
409
410         if (read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result))
411                 return sprintf(buf, "-1\n");
412         return sprintf(buf, "%lu\n", result);
413 }
414
415 static ssize_t store_ideapad_fan(struct device *dev,
416                                  struct device_attribute *attr,
417                                  const char *buf, size_t count)
418 {
419         int ret, state;
420         struct ideapad_private *priv = dev_get_drvdata(dev);
421
422         if (!count)
423                 return 0;
424         if (sscanf(buf, "%i", &state) != 1)
425                 return -EINVAL;
426         if (state < 0 || state > 4 || state == 3)
427                 return -EINVAL;
428         ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
429         if (ret < 0)
430                 return -EIO;
431         return count;
432 }
433
434 static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan);
435
436 static ssize_t touchpad_show(struct device *dev,
437                              struct device_attribute *attr,
438                              char *buf)
439 {
440         struct ideapad_private *priv = dev_get_drvdata(dev);
441         unsigned long result;
442
443         if (read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result))
444                 return sprintf(buf, "-1\n");
445         return sprintf(buf, "%lu\n", result);
446 }
447
448 /* Switch to RO for now: It might be revisited in the future */
449 static ssize_t __maybe_unused touchpad_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 = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state);
462         if (ret < 0)
463                 return -EIO;
464         return count;
465 }
466
467 static DEVICE_ATTR_RO(touchpad);
468
469 static ssize_t conservation_mode_show(struct device *dev,
470                                 struct device_attribute *attr,
471                                 char *buf)
472 {
473         struct ideapad_private *priv = dev_get_drvdata(dev);
474         unsigned long result;
475
476         if (method_gbmd(priv->adev->handle, &result))
477                 return sprintf(buf, "-1\n");
478         return sprintf(buf, "%u\n", test_bit(BM_CONSERVATION_BIT, &result));
479 }
480
481 static ssize_t conservation_mode_store(struct device *dev,
482                                  struct device_attribute *attr,
483                                  const char *buf, size_t count)
484 {
485         struct ideapad_private *priv = dev_get_drvdata(dev);
486         bool state;
487         int ret;
488
489         ret = kstrtobool(buf, &state);
490         if (ret)
491                 return ret;
492
493         ret = method_int1(priv->adev->handle, "SBMC", state ?
494                                               BMCMD_CONSERVATION_ON :
495                                               BMCMD_CONSERVATION_OFF);
496         if (ret < 0)
497                 return -EIO;
498         return count;
499 }
500
501 static DEVICE_ATTR_RW(conservation_mode);
502
503 static ssize_t fn_lock_show(struct device *dev,
504                             struct device_attribute *attr,
505                             char *buf)
506 {
507         struct ideapad_private *priv = dev_get_drvdata(dev);
508         unsigned long result;
509         int hals;
510         int fail = read_method_int(priv->adev->handle, "HALS", &hals);
511
512         if (fail)
513                 return sprintf(buf, "-1\n");
514
515         result = hals;
516         return sprintf(buf, "%u\n", test_bit(HA_FNLOCK_BIT, &result));
517 }
518
519 static ssize_t fn_lock_store(struct device *dev,
520                              struct device_attribute *attr,
521                              const char *buf, size_t count)
522 {
523         struct ideapad_private *priv = dev_get_drvdata(dev);
524         bool state;
525         int ret;
526
527         ret = kstrtobool(buf, &state);
528         if (ret)
529                 return ret;
530
531         ret = method_int1(priv->adev->handle, "SALS", state ?
532                           HACMD_FNLOCK_ON :
533                           HACMD_FNLOCK_OFF);
534         if (ret < 0)
535                 return -EIO;
536         return count;
537 }
538
539 static DEVICE_ATTR_RW(fn_lock);
540
541
542 static struct attribute *ideapad_attributes[] = {
543         &dev_attr_camera_power.attr,
544         &dev_attr_fan_mode.attr,
545         &dev_attr_touchpad.attr,
546         &dev_attr_conservation_mode.attr,
547         &dev_attr_fn_lock.attr,
548         NULL
549 };
550
551 static umode_t ideapad_is_visible(struct kobject *kobj,
552                                  struct attribute *attr,
553                                  int idx)
554 {
555         struct device *dev = container_of(kobj, struct device, kobj);
556         struct ideapad_private *priv = dev_get_drvdata(dev);
557         bool supported;
558
559         if (attr == &dev_attr_camera_power.attr)
560                 supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
561         else if (attr == &dev_attr_fan_mode.attr) {
562                 unsigned long value;
563                 supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN,
564                                           &value);
565         } else if (attr == &dev_attr_conservation_mode.attr) {
566                 supported = acpi_has_method(priv->adev->handle, "GBMD") &&
567                             acpi_has_method(priv->adev->handle, "SBMC");
568         } else if (attr == &dev_attr_fn_lock.attr) {
569                 supported = acpi_has_method(priv->adev->handle, "HALS") &&
570                         acpi_has_method(priv->adev->handle, "SALS");
571         } else
572                 supported = true;
573
574         return supported ? attr->mode : 0;
575 }
576
577 static const struct attribute_group ideapad_attribute_group = {
578         .is_visible = ideapad_is_visible,
579         .attrs = ideapad_attributes
580 };
581
582 /*
583  * Rfkill
584  */
585 struct ideapad_rfk_data {
586         char *name;
587         int cfgbit;
588         int opcode;
589         int type;
590 };
591
592 static const struct ideapad_rfk_data ideapad_rfk_data[] = {
593         { "ideapad_wlan",    CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
594         { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
595         { "ideapad_3g",        CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
596 };
597
598 static int ideapad_rfk_set(void *data, bool blocked)
599 {
600         struct ideapad_rfk_priv *priv = data;
601         int opcode = ideapad_rfk_data[priv->dev].opcode;
602
603         return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked);
604 }
605
606 static const struct rfkill_ops ideapad_rfk_ops = {
607         .set_block = ideapad_rfk_set,
608 };
609
610 static void ideapad_sync_rfk_state(struct ideapad_private *priv)
611 {
612         unsigned long hw_blocked = 0;
613         int i;
614
615         if (priv->has_hw_rfkill_switch) {
616                 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
617                         return;
618                 hw_blocked = !hw_blocked;
619         }
620
621         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
622                 if (priv->rfk[i])
623                         rfkill_set_hw_state(priv->rfk[i], hw_blocked);
624 }
625
626 static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
627 {
628         int ret;
629         unsigned long sw_blocked;
630
631         if (no_bt_rfkill &&
632             (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
633                 /* Force to enable bluetooth when no_bt_rfkill=1 */
634                 write_ec_cmd(priv->adev->handle,
635                              ideapad_rfk_data[dev].opcode, 1);
636                 return 0;
637         }
638         priv->rfk_priv[dev].dev = dev;
639         priv->rfk_priv[dev].priv = priv;
640
641         priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name,
642                                       &priv->platform_device->dev,
643                                       ideapad_rfk_data[dev].type,
644                                       &ideapad_rfk_ops,
645                                       &priv->rfk_priv[dev]);
646         if (!priv->rfk[dev])
647                 return -ENOMEM;
648
649         if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,
650                          &sw_blocked)) {
651                 rfkill_init_sw_state(priv->rfk[dev], 0);
652         } else {
653                 sw_blocked = !sw_blocked;
654                 rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
655         }
656
657         ret = rfkill_register(priv->rfk[dev]);
658         if (ret) {
659                 rfkill_destroy(priv->rfk[dev]);
660                 return ret;
661         }
662         return 0;
663 }
664
665 static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
666 {
667         if (!priv->rfk[dev])
668                 return;
669
670         rfkill_unregister(priv->rfk[dev]);
671         rfkill_destroy(priv->rfk[dev]);
672 }
673
674 /*
675  * Platform device
676  */
677 static int ideapad_sysfs_init(struct ideapad_private *priv)
678 {
679         return sysfs_create_group(&priv->platform_device->dev.kobj,
680                                     &ideapad_attribute_group);
681 }
682
683 static void ideapad_sysfs_exit(struct ideapad_private *priv)
684 {
685         sysfs_remove_group(&priv->platform_device->dev.kobj,
686                            &ideapad_attribute_group);
687 }
688
689 /*
690  * input device
691  */
692 static const struct key_entry ideapad_keymap[] = {
693         { KE_KEY, 6,  { KEY_SWITCHVIDEOMODE } },
694         { KE_KEY, 7,  { KEY_CAMERA } },
695         { KE_KEY, 8,  { KEY_MICMUTE } },
696         { KE_KEY, 11, { KEY_F16 } },
697         { KE_KEY, 13, { KEY_WLAN } },
698         { KE_KEY, 16, { KEY_PROG1 } },
699         { KE_KEY, 17, { KEY_PROG2 } },
700         { KE_KEY, 64, { KEY_PROG3 } },
701         { KE_KEY, 65, { KEY_PROG4 } },
702         { KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
703         { KE_KEY, 67, { KEY_TOUCHPAD_ON } },
704         { KE_KEY, 128, { KEY_ESC } },
705
706         { KE_END, 0 },
707 };
708
709 static int ideapad_input_init(struct ideapad_private *priv)
710 {
711         struct input_dev *inputdev;
712         int error;
713
714         inputdev = input_allocate_device();
715         if (!inputdev)
716                 return -ENOMEM;
717
718         inputdev->name = "Ideapad extra buttons";
719         inputdev->phys = "ideapad/input0";
720         inputdev->id.bustype = BUS_HOST;
721         inputdev->dev.parent = &priv->platform_device->dev;
722
723         error = sparse_keymap_setup(inputdev, ideapad_keymap, NULL);
724         if (error) {
725                 pr_err("Unable to setup input device keymap\n");
726                 goto err_free_dev;
727         }
728
729         error = input_register_device(inputdev);
730         if (error) {
731                 pr_err("Unable to register input device\n");
732                 goto err_free_dev;
733         }
734
735         priv->inputdev = inputdev;
736         return 0;
737
738 err_free_dev:
739         input_free_device(inputdev);
740         return error;
741 }
742
743 static void ideapad_input_exit(struct ideapad_private *priv)
744 {
745         input_unregister_device(priv->inputdev);
746         priv->inputdev = NULL;
747 }
748
749 static void ideapad_input_report(struct ideapad_private *priv,
750                                  unsigned long scancode)
751 {
752         sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
753 }
754
755 static void ideapad_input_novokey(struct ideapad_private *priv)
756 {
757         unsigned long long_pressed;
758
759         if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
760                 return;
761         if (long_pressed)
762                 ideapad_input_report(priv, 17);
763         else
764                 ideapad_input_report(priv, 16);
765 }
766
767 static void ideapad_check_special_buttons(struct ideapad_private *priv)
768 {
769         unsigned long bit, value;
770
771         read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
772
773         for (bit = 0; bit < 16; bit++) {
774                 if (test_bit(bit, &value)) {
775                         switch (bit) {
776                         case 0: /* Z580 */
777                         case 6: /* Z570 */
778                                 /* Thermal Management button */
779                                 ideapad_input_report(priv, 65);
780                                 break;
781                         case 1:
782                                 /* OneKey Theater button */
783                                 ideapad_input_report(priv, 64);
784                                 break;
785                         default:
786                                 pr_info("Unknown special button: %lu\n", bit);
787                                 break;
788                         }
789                 }
790         }
791 }
792
793 /*
794  * backlight
795  */
796 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
797 {
798         struct ideapad_private *priv = bl_get_data(blightdev);
799         unsigned long now;
800
801         if (!priv)
802                 return -EINVAL;
803
804         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
805                 return -EIO;
806         return now;
807 }
808
809 static int ideapad_backlight_update_status(struct backlight_device *blightdev)
810 {
811         struct ideapad_private *priv = bl_get_data(blightdev);
812
813         if (!priv)
814                 return -EINVAL;
815
816         if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
817                          blightdev->props.brightness))
818                 return -EIO;
819         if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
820                          blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
821                 return -EIO;
822
823         return 0;
824 }
825
826 static const struct backlight_ops ideapad_backlight_ops = {
827         .get_brightness = ideapad_backlight_get_brightness,
828         .update_status = ideapad_backlight_update_status,
829 };
830
831 static int ideapad_backlight_init(struct ideapad_private *priv)
832 {
833         struct backlight_device *blightdev;
834         struct backlight_properties props;
835         unsigned long max, now, power;
836
837         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max))
838                 return -EIO;
839         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
840                 return -EIO;
841         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
842                 return -EIO;
843
844         memset(&props, 0, sizeof(struct backlight_properties));
845         props.max_brightness = max;
846         props.type = BACKLIGHT_PLATFORM;
847         blightdev = backlight_device_register("ideapad",
848                                               &priv->platform_device->dev,
849                                               priv,
850                                               &ideapad_backlight_ops,
851                                               &props);
852         if (IS_ERR(blightdev)) {
853                 pr_err("Could not register backlight device\n");
854                 return PTR_ERR(blightdev);
855         }
856
857         priv->blightdev = blightdev;
858         blightdev->props.brightness = now;
859         blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
860         backlight_update_status(blightdev);
861
862         return 0;
863 }
864
865 static void ideapad_backlight_exit(struct ideapad_private *priv)
866 {
867         backlight_device_unregister(priv->blightdev);
868         priv->blightdev = NULL;
869 }
870
871 static void ideapad_backlight_notify_power(struct ideapad_private *priv)
872 {
873         unsigned long power;
874         struct backlight_device *blightdev = priv->blightdev;
875
876         if (!blightdev)
877                 return;
878         if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
879                 return;
880         blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
881 }
882
883 static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
884 {
885         unsigned long now;
886
887         /* if we control brightness via acpi video driver */
888         if (priv->blightdev == NULL) {
889                 read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
890                 return;
891         }
892
893         backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
894 }
895
896 /*
897  * module init/exit
898  */
899 static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
900 {
901         unsigned long value;
902
903         /* Without reading from EC touchpad LED doesn't switch state */
904         if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
905                 /* Some IdeaPads don't really turn off touchpad - they only
906                  * switch the LED state. We (de)activate KBC AUX port to turn
907                  * touchpad off and on. We send KEY_TOUCHPAD_OFF and
908                  * KEY_TOUCHPAD_ON to not to get out of sync with LED */
909                 unsigned char param;
910                 i8042_command(&param, value ? I8042_CMD_AUX_ENABLE :
911                               I8042_CMD_AUX_DISABLE);
912                 ideapad_input_report(priv, value ? 67 : 66);
913         }
914 }
915
916 static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
917 {
918         struct ideapad_private *priv = data;
919         unsigned long vpc1, vpc2, vpc_bit;
920
921         if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
922                 return;
923         if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
924                 return;
925
926         vpc1 = (vpc2 << 8) | vpc1;
927         for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
928                 if (test_bit(vpc_bit, &vpc1)) {
929                         switch (vpc_bit) {
930                         case 9:
931                                 ideapad_sync_rfk_state(priv);
932                                 break;
933                         case 13:
934                         case 11:
935                         case 8:
936                         case 7:
937                         case 6:
938                                 ideapad_input_report(priv, vpc_bit);
939                                 break;
940                         case 5:
941                                 ideapad_sync_touchpad_state(priv);
942                                 break;
943                         case 4:
944                                 ideapad_backlight_notify_brightness(priv);
945                                 break;
946                         case 3:
947                                 ideapad_input_novokey(priv);
948                                 break;
949                         case 2:
950                                 ideapad_backlight_notify_power(priv);
951                                 break;
952                         case 0:
953                                 ideapad_check_special_buttons(priv);
954                                 break;
955                         case 1:
956                                 /* Some IdeaPads report event 1 every ~20
957                                  * seconds while on battery power; some
958                                  * report this when changing to/from tablet
959                                  * mode. Squelch this event.
960                                  */
961                                 break;
962                         default:
963                                 pr_info("Unknown event: %lu\n", vpc_bit);
964                         }
965                 }
966         }
967 }
968
969 #if IS_ENABLED(CONFIG_ACPI_WMI)
970 static void ideapad_wmi_notify(u32 value, void *context)
971 {
972         switch (value) {
973         case 128:
974                 ideapad_input_report(context, value);
975                 break;
976         default:
977                 pr_info("Unknown WMI event %u\n", value);
978         }
979 }
980 #endif
981
982 /*
983  * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF
984  * always results in 0 on these models, causing ideapad_laptop to wrongly
985  * report all radios as hardware-blocked.
986  */
987 static const struct dmi_system_id no_hw_rfkill_list[] = {
988         {
989                 .ident = "Lenovo RESCUER R720-15IKBN",
990                 .matches = {
991                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
992                         DMI_MATCH(DMI_BOARD_NAME, "80WW"),
993                 },
994         },
995         {
996                 .ident = "Lenovo G40-30",
997                 .matches = {
998                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
999                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G40-30"),
1000                 },
1001         },
1002         {
1003                 .ident = "Lenovo G50-30",
1004                 .matches = {
1005                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1006                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G50-30"),
1007                 },
1008         },
1009         {
1010                 .ident = "Lenovo V310-14IKB",
1011                 .matches = {
1012                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1013                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-14IKB"),
1014                 },
1015         },
1016         {
1017                 .ident = "Lenovo V310-14ISK",
1018                 .matches = {
1019                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1020                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-14ISK"),
1021                 },
1022         },
1023         {
1024                 .ident = "Lenovo V310-15IKB",
1025                 .matches = {
1026                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1027                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-15IKB"),
1028                 },
1029         },
1030         {
1031                 .ident = "Lenovo V310-15ISK",
1032                 .matches = {
1033                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1034                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-15ISK"),
1035                 },
1036         },
1037         {
1038                 .ident = "Lenovo V510-15IKB",
1039                 .matches = {
1040                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1041                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V510-15IKB"),
1042                 },
1043         },
1044         {
1045                 .ident = "Lenovo ideapad 300-15IBR",
1046                 .matches = {
1047                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1048                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 300-15IBR"),
1049                 },
1050         },
1051         {
1052                 .ident = "Lenovo ideapad 300-15IKB",
1053                 .matches = {
1054                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1055                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 300-15IKB"),
1056                 },
1057         },
1058         {
1059                 .ident = "Lenovo ideapad 300S-11IBR",
1060                 .matches = {
1061                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1062                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 300S-11BR"),
1063                 },
1064         },
1065         {
1066                 .ident = "Lenovo ideapad 310-15ABR",
1067                 .matches = {
1068                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1069                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15ABR"),
1070                 },
1071         },
1072         {
1073                 .ident = "Lenovo ideapad 310-15IAP",
1074                 .matches = {
1075                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1076                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15IAP"),
1077                 },
1078         },
1079         {
1080                 .ident = "Lenovo ideapad 310-15IKB",
1081                 .matches = {
1082                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1083                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15IKB"),
1084                 },
1085         },
1086         {
1087                 .ident = "Lenovo ideapad 310-15ISK",
1088                 .matches = {
1089                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1090                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15ISK"),
1091                 },
1092         },
1093         {
1094                 .ident = "Lenovo ideapad Y700-14ISK",
1095                 .matches = {
1096                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1097                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-14ISK"),
1098                 },
1099         },
1100         {
1101                 .ident = "Lenovo ideapad Y700-15ACZ",
1102                 .matches = {
1103                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1104                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-15ACZ"),
1105                 },
1106         },
1107         {
1108                 .ident = "Lenovo ideapad Y700-15ISK",
1109                 .matches = {
1110                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1111                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-15ISK"),
1112                 },
1113         },
1114         {
1115                 .ident = "Lenovo ideapad Y700 Touch-15ISK",
1116                 .matches = {
1117                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1118                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700 Touch-15ISK"),
1119                 },
1120         },
1121         {
1122                 .ident = "Lenovo ideapad Y700-17ISK",
1123                 .matches = {
1124                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1125                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-17ISK"),
1126                 },
1127         },
1128         {
1129                 .ident = "Lenovo ideapad MIIX 720-12IKB",
1130                 .matches = {
1131                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1132                         DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 720-12IKB"),
1133                 },
1134         },
1135         {
1136                 .ident = "Lenovo Legion Y520-15IKB",
1137                 .matches = {
1138                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1139                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKB"),
1140                 },
1141         },
1142         {
1143                 .ident = "Lenovo Y520-15IKBM",
1144                 .matches = {
1145                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1146                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBM"),
1147                 },
1148         },
1149         {
1150                 .ident = "Lenovo Legion Y720-15IKB",
1151                 .matches = {
1152                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1153                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKB"),
1154                 },
1155         },
1156         {
1157                 .ident = "Lenovo Legion Y720-15IKBN",
1158                 .matches = {
1159                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1160                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBN"),
1161                 },
1162         },
1163         {
1164                 .ident = "Lenovo Y720-15IKBM",
1165                 .matches = {
1166                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1167                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBM"),
1168                 },
1169         },
1170         {
1171                 .ident = "Lenovo Yoga 2 11 / 13 / Pro",
1172                 .matches = {
1173                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1174                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"),
1175                 },
1176         },
1177         {
1178                 .ident = "Lenovo Yoga 2 11 / 13 / Pro",
1179                 .matches = {
1180                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1181                         DMI_MATCH(DMI_BOARD_NAME, "Yoga2"),
1182                 },
1183         },
1184         {
1185                 .ident = "Lenovo Yoga 3 1170 / 1470",
1186                 .matches = {
1187                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1188                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3"),
1189                 },
1190         },
1191         {
1192                 .ident = "Lenovo Yoga 3 Pro 1370",
1193                 .matches = {
1194                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1195                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3"),
1196                 },
1197         },
1198         {
1199                 .ident = "Lenovo Yoga 700",
1200                 .matches = {
1201                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1202                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 700"),
1203                 },
1204         },
1205         {
1206                 .ident = "Lenovo Yoga 900",
1207                 .matches = {
1208                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1209                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 900"),
1210                 },
1211         },
1212         {
1213                 .ident = "Lenovo Yoga 900",
1214                 .matches = {
1215                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1216                         DMI_MATCH(DMI_BOARD_NAME, "VIUU4"),
1217                 },
1218         },
1219         {
1220                 .ident = "Lenovo YOGA 910-13IKB",
1221                 .matches = {
1222                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1223                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 910-13IKB"),
1224                 },
1225         },
1226         {
1227                 .ident = "Lenovo YOGA 920-13IKB",
1228                 .matches = {
1229                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1230                         DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920-13IKB"),
1231                 },
1232         },
1233         {
1234                 .ident = "Lenovo Zhaoyang E42-80",
1235                 .matches = {
1236                         DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1237                         DMI_MATCH(DMI_PRODUCT_VERSION, "ZHAOYANG E42-80"),
1238                 },
1239         },
1240         {}
1241 };
1242
1243 static int ideapad_acpi_add(struct platform_device *pdev)
1244 {
1245         int ret, i;
1246         int cfg;
1247         struct ideapad_private *priv;
1248         struct acpi_device *adev;
1249
1250         ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
1251         if (ret)
1252                 return -ENODEV;
1253
1254         if (read_method_int(adev->handle, "_CFG", &cfg))
1255                 return -ENODEV;
1256
1257         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1258         if (!priv)
1259                 return -ENOMEM;
1260
1261         dev_set_drvdata(&pdev->dev, priv);
1262         priv->cfg = cfg;
1263         priv->adev = adev;
1264         priv->platform_device = pdev;
1265         priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list);
1266
1267         ret = ideapad_sysfs_init(priv);
1268         if (ret)
1269                 return ret;
1270
1271         ret = ideapad_debugfs_init(priv);
1272         if (ret)
1273                 goto debugfs_failed;
1274
1275         ret = ideapad_input_init(priv);
1276         if (ret)
1277                 goto input_failed;
1278
1279         /*
1280          * On some models without a hw-switch (the yoga 2 13 at least)
1281          * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
1282          */
1283         if (!priv->has_hw_rfkill_switch)
1284                 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
1285
1286         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1287                 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
1288                         ideapad_register_rfkill(priv, i);
1289
1290         ideapad_sync_rfk_state(priv);
1291         ideapad_sync_touchpad_state(priv);
1292
1293         if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1294                 ret = ideapad_backlight_init(priv);
1295                 if (ret && ret != -ENODEV)
1296                         goto backlight_failed;
1297         }
1298         ret = acpi_install_notify_handler(adev->handle,
1299                 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
1300         if (ret)
1301                 goto notification_failed;
1302
1303 #if IS_ENABLED(CONFIG_ACPI_WMI)
1304         for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) {
1305                 ret = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i],
1306                                                  ideapad_wmi_notify, priv);
1307                 if (ret == AE_OK) {
1308                         priv->fnesc_guid = ideapad_wmi_fnesc_events[i];
1309                         break;
1310                 }
1311         }
1312         if (ret != AE_OK && ret != AE_NOT_EXIST)
1313                 goto notification_failed_wmi;
1314 #endif
1315
1316         return 0;
1317 #if IS_ENABLED(CONFIG_ACPI_WMI)
1318 notification_failed_wmi:
1319         acpi_remove_notify_handler(priv->adev->handle,
1320                 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
1321 #endif
1322 notification_failed:
1323         ideapad_backlight_exit(priv);
1324 backlight_failed:
1325         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1326                 ideapad_unregister_rfkill(priv, i);
1327         ideapad_input_exit(priv);
1328 input_failed:
1329         ideapad_debugfs_exit(priv);
1330 debugfs_failed:
1331         ideapad_sysfs_exit(priv);
1332         return ret;
1333 }
1334
1335 static int ideapad_acpi_remove(struct platform_device *pdev)
1336 {
1337         struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
1338         int i;
1339
1340 #if IS_ENABLED(CONFIG_ACPI_WMI)
1341         if (priv->fnesc_guid)
1342                 wmi_remove_notify_handler(priv->fnesc_guid);
1343 #endif
1344         acpi_remove_notify_handler(priv->adev->handle,
1345                 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
1346         ideapad_backlight_exit(priv);
1347         for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1348                 ideapad_unregister_rfkill(priv, i);
1349         ideapad_input_exit(priv);
1350         ideapad_debugfs_exit(priv);
1351         ideapad_sysfs_exit(priv);
1352         dev_set_drvdata(&pdev->dev, NULL);
1353
1354         return 0;
1355 }
1356
1357 #ifdef CONFIG_PM_SLEEP
1358 static int ideapad_acpi_resume(struct device *device)
1359 {
1360         struct ideapad_private *priv;
1361
1362         if (!device)
1363                 return -EINVAL;
1364         priv = dev_get_drvdata(device);
1365
1366         ideapad_sync_rfk_state(priv);
1367         ideapad_sync_touchpad_state(priv);
1368         return 0;
1369 }
1370 #endif
1371 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
1372
1373 static const struct acpi_device_id ideapad_device_ids[] = {
1374         { "VPC2004", 0},
1375         { "", 0},
1376 };
1377 MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
1378
1379 static struct platform_driver ideapad_acpi_driver = {
1380         .probe = ideapad_acpi_add,
1381         .remove = ideapad_acpi_remove,
1382         .driver = {
1383                 .name   = "ideapad_acpi",
1384                 .pm     = &ideapad_pm,
1385                 .acpi_match_table = ACPI_PTR(ideapad_device_ids),
1386         },
1387 };
1388
1389 module_platform_driver(ideapad_acpi_driver);
1390
1391 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
1392 MODULE_DESCRIPTION("IdeaPad ACPI Extras");
1393 MODULE_LICENSE("GPL");