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