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