2 * ideapad-laptop.c - Lenovo IdeaPad ACPI Extras
4 * Copyright © 2010 Intel Corporation
5 * Copyright © 2010 David Woodhouse <dwmw2@infradead.org>
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.
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.
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
23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
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>
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>
43 #define IDEAPAD_RFKILL_DEV_NUM (3)
45 #define BM_CONSERVATION_BIT (5)
47 #define CFG_BT_BIT (16)
48 #define CFG_3G_BIT (17)
49 #define CFG_WIFI_BIT (18)
50 #define CFG_CAMERA_BIT (19)
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 */
60 BMCMD_CONSERVATION_ON = 3,
61 BMCMD_CONSERVATION_OFF = 5,
82 VPCCMD_R_ODD, /* 0x21 */
87 VPCCMD_R_SPECIAL_BUTTONS = 0x31,
88 VPCCMD_W_BL_POWER = 0x33,
91 struct ideapad_rfk_priv {
93 struct ideapad_private *priv;
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;
105 bool has_hw_rfkill_switch;
106 const char *fnesc_guid;
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.");
116 #define IDEAPAD_EC_TIMEOUT (200) /* in ms */
118 static int read_method_int(acpi_handle handle, const char *method, int *val)
121 unsigned long long result;
123 status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
124 if (ACPI_FAILURE(status)) {
133 static int method_gbmd(acpi_handle handle, unsigned long *ret)
137 result = read_method_int(handle, "GBMD", &val);
142 static int method_sbmc(acpi_handle handle, int cmd)
146 status = acpi_execute_simple_method(handle, "SBMC", cmd);
147 return ACPI_FAILURE(status) ? -1 : 0;
150 static int method_vpcr(acpi_handle handle, int cmd, int *ret)
153 unsigned long long result;
154 struct acpi_object_list params;
155 union acpi_object in_obj;
158 params.pointer = &in_obj;
159 in_obj.type = ACPI_TYPE_INTEGER;
160 in_obj.integer.value = cmd;
162 status = acpi_evaluate_integer(handle, "VPCR", ¶ms, &result);
164 if (ACPI_FAILURE(status)) {
173 static int method_vpcw(acpi_handle handle, int cmd, int data)
175 struct acpi_object_list params;
176 union acpi_object in_obj[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;
186 status = acpi_evaluate_object(handle, "VPCW", ¶ms, NULL);
192 static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
195 unsigned long int end_jiffies;
197 if (method_vpcw(handle, 1, cmd))
200 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
201 time_before(jiffies, end_jiffies);) {
203 if (method_vpcr(handle, 1, &val))
206 if (method_vpcr(handle, 0, &val))
212 pr_err("timeout in read_ec_cmd\n");
216 static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
219 unsigned long int end_jiffies;
221 if (method_vpcw(handle, 0, data))
223 if (method_vpcw(handle, 1, cmd))
226 for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
227 time_before(jiffies, end_jiffies);) {
229 if (method_vpcr(handle, 1, &val))
234 pr_err("timeout in %s\n", __func__);
241 static int debugfs_status_show(struct seq_file *s, void *data)
243 struct ideapad_private *priv = s->private;
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");
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");
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");
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",
287 DEFINE_SHOW_ATTRIBUTE(debugfs_status);
289 static int debugfs_cfg_show(struct seq_file *s, void *data)
291 struct ideapad_private *priv = s->private;
294 seq_printf(s, "cfg: N/A\n");
296 seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
298 if (test_bit(CFG_BT_BIT, &priv->cfg))
299 seq_printf(s, "Bluetooth ");
300 if (test_bit(CFG_3G_BIT, &priv->cfg))
301 seq_printf(s, "3G ");
302 if (test_bit(CFG_WIFI_BIT, &priv->cfg))
303 seq_printf(s, "Wireless ");
304 if (test_bit(CFG_CAMERA_BIT, &priv->cfg))
305 seq_printf(s, "Camera ");
306 seq_printf(s, "\nGraphic: ");
307 switch ((priv->cfg)&0x700) {
309 seq_printf(s, "Intel");
312 seq_printf(s, "ATI");
315 seq_printf(s, "Nvidia");
318 seq_printf(s, "Intel and ATI");
321 seq_printf(s, "Intel and Nvidia");
328 DEFINE_SHOW_ATTRIBUTE(debugfs_cfg);
330 static int ideapad_debugfs_init(struct ideapad_private *priv)
334 priv->debug = debugfs_create_dir("ideapad", NULL);
335 if (priv->debug == NULL) {
336 pr_err("failed to create debugfs directory");
340 node = debugfs_create_file("cfg", S_IRUGO, priv->debug, priv,
343 pr_err("failed to create cfg in debugfs");
347 node = debugfs_create_file("status", S_IRUGO, priv->debug, priv,
348 &debugfs_status_fops);
350 pr_err("failed to create status in debugfs");
360 static void ideapad_debugfs_exit(struct ideapad_private *priv)
362 debugfs_remove_recursive(priv->debug);
369 static ssize_t show_ideapad_cam(struct device *dev,
370 struct device_attribute *attr,
373 unsigned long result;
374 struct ideapad_private *priv = dev_get_drvdata(dev);
376 if (read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result))
377 return sprintf(buf, "-1\n");
378 return sprintf(buf, "%lu\n", result);
381 static ssize_t store_ideapad_cam(struct device *dev,
382 struct device_attribute *attr,
383 const char *buf, size_t count)
386 struct ideapad_private *priv = dev_get_drvdata(dev);
390 if (sscanf(buf, "%i", &state) != 1)
392 ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
398 static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
400 static ssize_t show_ideapad_fan(struct device *dev,
401 struct device_attribute *attr,
404 unsigned long result;
405 struct ideapad_private *priv = dev_get_drvdata(dev);
407 if (read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result))
408 return sprintf(buf, "-1\n");
409 return sprintf(buf, "%lu\n", result);
412 static ssize_t store_ideapad_fan(struct device *dev,
413 struct device_attribute *attr,
414 const char *buf, size_t count)
417 struct ideapad_private *priv = dev_get_drvdata(dev);
421 if (sscanf(buf, "%i", &state) != 1)
423 if (state < 0 || state > 4 || state == 3)
425 ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
431 static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan);
433 static ssize_t touchpad_show(struct device *dev,
434 struct device_attribute *attr,
437 struct ideapad_private *priv = dev_get_drvdata(dev);
438 unsigned long result;
440 if (read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &result))
441 return sprintf(buf, "-1\n");
442 return sprintf(buf, "%lu\n", result);
445 /* Switch to RO for now: It might be revisited in the future */
446 static ssize_t __maybe_unused touchpad_store(struct device *dev,
447 struct device_attribute *attr,
448 const char *buf, size_t count)
450 struct ideapad_private *priv = dev_get_drvdata(dev);
454 ret = kstrtobool(buf, &state);
458 ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_TOUCHPAD, state);
464 static DEVICE_ATTR_RO(touchpad);
466 static ssize_t conservation_mode_show(struct device *dev,
467 struct device_attribute *attr,
470 struct ideapad_private *priv = dev_get_drvdata(dev);
471 unsigned long result;
473 if (method_gbmd(priv->adev->handle, &result))
474 return sprintf(buf, "-1\n");
475 return sprintf(buf, "%u\n", test_bit(BM_CONSERVATION_BIT, &result));
478 static ssize_t conservation_mode_store(struct device *dev,
479 struct device_attribute *attr,
480 const char *buf, size_t count)
482 struct ideapad_private *priv = dev_get_drvdata(dev);
486 ret = kstrtobool(buf, &state);
490 ret = method_sbmc(priv->adev->handle, state ?
491 BMCMD_CONSERVATION_ON :
492 BMCMD_CONSERVATION_OFF);
498 static DEVICE_ATTR_RW(conservation_mode);
500 static struct attribute *ideapad_attributes[] = {
501 &dev_attr_camera_power.attr,
502 &dev_attr_fan_mode.attr,
503 &dev_attr_touchpad.attr,
504 &dev_attr_conservation_mode.attr,
508 static umode_t ideapad_is_visible(struct kobject *kobj,
509 struct attribute *attr,
512 struct device *dev = container_of(kobj, struct device, kobj);
513 struct ideapad_private *priv = dev_get_drvdata(dev);
516 if (attr == &dev_attr_camera_power.attr)
517 supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
518 else if (attr == &dev_attr_fan_mode.attr) {
520 supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN,
522 } else if (attr == &dev_attr_conservation_mode.attr) {
523 supported = acpi_has_method(priv->adev->handle, "GBMD") &&
524 acpi_has_method(priv->adev->handle, "SBMC");
528 return supported ? attr->mode : 0;
531 static const struct attribute_group ideapad_attribute_group = {
532 .is_visible = ideapad_is_visible,
533 .attrs = ideapad_attributes
539 struct ideapad_rfk_data {
546 static const struct ideapad_rfk_data ideapad_rfk_data[] = {
547 { "ideapad_wlan", CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
548 { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
549 { "ideapad_3g", CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
552 static int ideapad_rfk_set(void *data, bool blocked)
554 struct ideapad_rfk_priv *priv = data;
555 int opcode = ideapad_rfk_data[priv->dev].opcode;
557 return write_ec_cmd(priv->priv->adev->handle, opcode, !blocked);
560 static const struct rfkill_ops ideapad_rfk_ops = {
561 .set_block = ideapad_rfk_set,
564 static void ideapad_sync_rfk_state(struct ideapad_private *priv)
566 unsigned long hw_blocked = 0;
569 if (priv->has_hw_rfkill_switch) {
570 if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
572 hw_blocked = !hw_blocked;
575 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
577 rfkill_set_hw_state(priv->rfk[i], hw_blocked);
580 static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
583 unsigned long sw_blocked;
586 (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
587 /* Force to enable bluetooth when no_bt_rfkill=1 */
588 write_ec_cmd(priv->adev->handle,
589 ideapad_rfk_data[dev].opcode, 1);
592 priv->rfk_priv[dev].dev = dev;
593 priv->rfk_priv[dev].priv = priv;
595 priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name,
596 &priv->platform_device->dev,
597 ideapad_rfk_data[dev].type,
599 &priv->rfk_priv[dev]);
603 if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,
605 rfkill_init_sw_state(priv->rfk[dev], 0);
607 sw_blocked = !sw_blocked;
608 rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
611 ret = rfkill_register(priv->rfk[dev]);
613 rfkill_destroy(priv->rfk[dev]);
619 static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
624 rfkill_unregister(priv->rfk[dev]);
625 rfkill_destroy(priv->rfk[dev]);
631 static int ideapad_sysfs_init(struct ideapad_private *priv)
633 return sysfs_create_group(&priv->platform_device->dev.kobj,
634 &ideapad_attribute_group);
637 static void ideapad_sysfs_exit(struct ideapad_private *priv)
639 sysfs_remove_group(&priv->platform_device->dev.kobj,
640 &ideapad_attribute_group);
646 static const struct key_entry ideapad_keymap[] = {
647 { KE_KEY, 6, { KEY_SWITCHVIDEOMODE } },
648 { KE_KEY, 7, { KEY_CAMERA } },
649 { KE_KEY, 8, { KEY_MICMUTE } },
650 { KE_KEY, 11, { KEY_F16 } },
651 { KE_KEY, 13, { KEY_WLAN } },
652 { KE_KEY, 16, { KEY_PROG1 } },
653 { KE_KEY, 17, { KEY_PROG2 } },
654 { KE_KEY, 64, { KEY_PROG3 } },
655 { KE_KEY, 65, { KEY_PROG4 } },
656 { KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
657 { KE_KEY, 67, { KEY_TOUCHPAD_ON } },
658 { KE_KEY, 128, { KEY_ESC } },
663 static int ideapad_input_init(struct ideapad_private *priv)
665 struct input_dev *inputdev;
668 inputdev = input_allocate_device();
672 inputdev->name = "Ideapad extra buttons";
673 inputdev->phys = "ideapad/input0";
674 inputdev->id.bustype = BUS_HOST;
675 inputdev->dev.parent = &priv->platform_device->dev;
677 error = sparse_keymap_setup(inputdev, ideapad_keymap, NULL);
679 pr_err("Unable to setup input device keymap\n");
683 error = input_register_device(inputdev);
685 pr_err("Unable to register input device\n");
689 priv->inputdev = inputdev;
693 input_free_device(inputdev);
697 static void ideapad_input_exit(struct ideapad_private *priv)
699 input_unregister_device(priv->inputdev);
700 priv->inputdev = NULL;
703 static void ideapad_input_report(struct ideapad_private *priv,
704 unsigned long scancode)
706 sparse_keymap_report_event(priv->inputdev, scancode, 1, true);
709 static void ideapad_input_novokey(struct ideapad_private *priv)
711 unsigned long long_pressed;
713 if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
716 ideapad_input_report(priv, 17);
718 ideapad_input_report(priv, 16);
721 static void ideapad_check_special_buttons(struct ideapad_private *priv)
723 unsigned long bit, value;
725 read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
727 for (bit = 0; bit < 16; bit++) {
728 if (test_bit(bit, &value)) {
732 /* Thermal Management button */
733 ideapad_input_report(priv, 65);
736 /* OneKey Theater button */
737 ideapad_input_report(priv, 64);
740 pr_info("Unknown special button: %lu\n", bit);
750 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
752 struct ideapad_private *priv = bl_get_data(blightdev);
758 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
763 static int ideapad_backlight_update_status(struct backlight_device *blightdev)
765 struct ideapad_private *priv = bl_get_data(blightdev);
770 if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
771 blightdev->props.brightness))
773 if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
774 blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
780 static const struct backlight_ops ideapad_backlight_ops = {
781 .get_brightness = ideapad_backlight_get_brightness,
782 .update_status = ideapad_backlight_update_status,
785 static int ideapad_backlight_init(struct ideapad_private *priv)
787 struct backlight_device *blightdev;
788 struct backlight_properties props;
789 unsigned long max, now, power;
791 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max))
793 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
795 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
798 memset(&props, 0, sizeof(struct backlight_properties));
799 props.max_brightness = max;
800 props.type = BACKLIGHT_PLATFORM;
801 blightdev = backlight_device_register("ideapad",
802 &priv->platform_device->dev,
804 &ideapad_backlight_ops,
806 if (IS_ERR(blightdev)) {
807 pr_err("Could not register backlight device\n");
808 return PTR_ERR(blightdev);
811 priv->blightdev = blightdev;
812 blightdev->props.brightness = now;
813 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
814 backlight_update_status(blightdev);
819 static void ideapad_backlight_exit(struct ideapad_private *priv)
821 backlight_device_unregister(priv->blightdev);
822 priv->blightdev = NULL;
825 static void ideapad_backlight_notify_power(struct ideapad_private *priv)
828 struct backlight_device *blightdev = priv->blightdev;
832 if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
834 blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
837 static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
841 /* if we control brightness via acpi video driver */
842 if (priv->blightdev == NULL) {
843 read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
847 backlight_force_update(priv->blightdev, BACKLIGHT_UPDATE_HOTKEY);
853 static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
857 /* Without reading from EC touchpad LED doesn't switch state */
858 if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
859 /* Some IdeaPads don't really turn off touchpad - they only
860 * switch the LED state. We (de)activate KBC AUX port to turn
861 * touchpad off and on. We send KEY_TOUCHPAD_OFF and
862 * KEY_TOUCHPAD_ON to not to get out of sync with LED */
864 i8042_command(¶m, value ? I8042_CMD_AUX_ENABLE :
865 I8042_CMD_AUX_DISABLE);
866 ideapad_input_report(priv, value ? 67 : 66);
870 static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
872 struct ideapad_private *priv = data;
873 unsigned long vpc1, vpc2, vpc_bit;
875 if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
877 if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
880 vpc1 = (vpc2 << 8) | vpc1;
881 for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
882 if (test_bit(vpc_bit, &vpc1)) {
885 ideapad_sync_rfk_state(priv);
892 ideapad_input_report(priv, vpc_bit);
895 ideapad_sync_touchpad_state(priv);
898 ideapad_backlight_notify_brightness(priv);
901 ideapad_input_novokey(priv);
904 ideapad_backlight_notify_power(priv);
907 ideapad_check_special_buttons(priv);
910 /* Some IdeaPads report event 1 every ~20
911 * seconds while on battery power; some
912 * report this when changing to/from tablet
913 * mode. Squelch this event.
917 pr_info("Unknown event: %lu\n", vpc_bit);
923 #if IS_ENABLED(CONFIG_ACPI_WMI)
924 static void ideapad_wmi_notify(u32 value, void *context)
928 ideapad_input_report(context, value);
931 pr_info("Unknown WMI event %u\n", value);
937 * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF
938 * always results in 0 on these models, causing ideapad_laptop to wrongly
939 * report all radios as hardware-blocked.
941 static const struct dmi_system_id no_hw_rfkill_list[] = {
943 .ident = "Lenovo RESCUER R720-15IKBN",
945 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
946 DMI_MATCH(DMI_BOARD_NAME, "80WW"),
950 .ident = "Lenovo G40-30",
952 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
953 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G40-30"),
957 .ident = "Lenovo G50-30",
959 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
960 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G50-30"),
964 .ident = "Lenovo V310-14IKB",
966 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
967 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-14IKB"),
971 .ident = "Lenovo V310-14ISK",
973 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
974 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-14ISK"),
978 .ident = "Lenovo V310-15IKB",
980 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
981 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-15IKB"),
985 .ident = "Lenovo V310-15ISK",
987 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
988 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V310-15ISK"),
992 .ident = "Lenovo V510-15IKB",
994 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
995 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo V510-15IKB"),
999 .ident = "Lenovo ideapad 300-15IBR",
1001 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1002 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 300-15IBR"),
1006 .ident = "Lenovo ideapad 300-15IKB",
1008 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1009 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 300-15IKB"),
1013 .ident = "Lenovo ideapad 300S-11IBR",
1015 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1016 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 300S-11BR"),
1020 .ident = "Lenovo ideapad 310-15ABR",
1022 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1023 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15ABR"),
1027 .ident = "Lenovo ideapad 310-15IAP",
1029 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1030 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15IAP"),
1034 .ident = "Lenovo ideapad 310-15IKB",
1036 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1037 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15IKB"),
1041 .ident = "Lenovo ideapad 310-15ISK",
1043 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1044 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad 310-15ISK"),
1048 .ident = "Lenovo ideapad Y700-14ISK",
1050 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1051 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-14ISK"),
1055 .ident = "Lenovo ideapad Y700-15ACZ",
1057 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1058 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-15ACZ"),
1062 .ident = "Lenovo ideapad Y700-15ISK",
1064 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1065 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-15ISK"),
1069 .ident = "Lenovo ideapad Y700 Touch-15ISK",
1071 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1072 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700 Touch-15ISK"),
1076 .ident = "Lenovo ideapad Y700-17ISK",
1078 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1079 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo ideapad Y700-17ISK"),
1083 .ident = "Lenovo Legion Y520-15IKBN",
1085 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1086 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y520-15IKBN"),
1090 .ident = "Lenovo Legion Y720-15IKB",
1092 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1093 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKB"),
1097 .ident = "Lenovo Legion Y720-15IKBN",
1099 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1100 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Y720-15IKBN"),
1104 .ident = "Lenovo Yoga 2 11 / 13 / Pro",
1106 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1107 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"),
1111 .ident = "Lenovo Yoga 2 11 / 13 / Pro",
1113 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1114 DMI_MATCH(DMI_BOARD_NAME, "Yoga2"),
1118 .ident = "Lenovo Yoga 3 1170 / 1470",
1120 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1121 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3"),
1125 .ident = "Lenovo Yoga 3 Pro 1370",
1127 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1128 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 3"),
1132 .ident = "Lenovo Yoga 700",
1134 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1135 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 700"),
1139 .ident = "Lenovo Yoga 900",
1141 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1142 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 900"),
1146 .ident = "Lenovo Yoga 900",
1148 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1149 DMI_MATCH(DMI_BOARD_NAME, "VIUU4"),
1153 .ident = "Lenovo YOGA 910-13IKB",
1155 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1156 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 910-13IKB"),
1160 .ident = "Lenovo YOGA 920-13IKB",
1162 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
1163 DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920-13IKB"),
1169 static int ideapad_acpi_add(struct platform_device *pdev)
1173 struct ideapad_private *priv;
1174 struct acpi_device *adev;
1176 ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
1180 if (read_method_int(adev->handle, "_CFG", &cfg))
1183 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1187 dev_set_drvdata(&pdev->dev, priv);
1190 priv->platform_device = pdev;
1191 priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list);
1193 ret = ideapad_sysfs_init(priv);
1197 ret = ideapad_debugfs_init(priv);
1199 goto debugfs_failed;
1201 ret = ideapad_input_init(priv);
1206 * On some models without a hw-switch (the yoga 2 13 at least)
1207 * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work.
1209 if (!priv->has_hw_rfkill_switch)
1210 write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1);
1212 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1213 if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
1214 ideapad_register_rfkill(priv, i);
1216 ideapad_sync_rfk_state(priv);
1217 ideapad_sync_touchpad_state(priv);
1219 if (acpi_video_get_backlight_type() == acpi_backlight_vendor) {
1220 ret = ideapad_backlight_init(priv);
1221 if (ret && ret != -ENODEV)
1222 goto backlight_failed;
1224 ret = acpi_install_notify_handler(adev->handle,
1225 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
1227 goto notification_failed;
1229 #if IS_ENABLED(CONFIG_ACPI_WMI)
1230 for (i = 0; i < ARRAY_SIZE(ideapad_wmi_fnesc_events); i++) {
1231 ret = wmi_install_notify_handler(ideapad_wmi_fnesc_events[i],
1232 ideapad_wmi_notify, priv);
1234 priv->fnesc_guid = ideapad_wmi_fnesc_events[i];
1238 if (ret != AE_OK && ret != AE_NOT_EXIST)
1239 goto notification_failed_wmi;
1243 #if IS_ENABLED(CONFIG_ACPI_WMI)
1244 notification_failed_wmi:
1245 acpi_remove_notify_handler(priv->adev->handle,
1246 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
1248 notification_failed:
1249 ideapad_backlight_exit(priv);
1251 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1252 ideapad_unregister_rfkill(priv, i);
1253 ideapad_input_exit(priv);
1255 ideapad_debugfs_exit(priv);
1257 ideapad_sysfs_exit(priv);
1261 static int ideapad_acpi_remove(struct platform_device *pdev)
1263 struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
1266 #if IS_ENABLED(CONFIG_ACPI_WMI)
1267 if (priv->fnesc_guid)
1268 wmi_remove_notify_handler(priv->fnesc_guid);
1270 acpi_remove_notify_handler(priv->adev->handle,
1271 ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
1272 ideapad_backlight_exit(priv);
1273 for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
1274 ideapad_unregister_rfkill(priv, i);
1275 ideapad_input_exit(priv);
1276 ideapad_debugfs_exit(priv);
1277 ideapad_sysfs_exit(priv);
1278 dev_set_drvdata(&pdev->dev, NULL);
1283 #ifdef CONFIG_PM_SLEEP
1284 static int ideapad_acpi_resume(struct device *device)
1286 struct ideapad_private *priv;
1290 priv = dev_get_drvdata(device);
1292 ideapad_sync_rfk_state(priv);
1293 ideapad_sync_touchpad_state(priv);
1297 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
1299 static const struct acpi_device_id ideapad_device_ids[] = {
1303 MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
1305 static struct platform_driver ideapad_acpi_driver = {
1306 .probe = ideapad_acpi_add,
1307 .remove = ideapad_acpi_remove,
1309 .name = "ideapad_acpi",
1311 .acpi_match_table = ACPI_PTR(ideapad_device_ids),
1315 module_platform_driver(ideapad_acpi_driver);
1317 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
1318 MODULE_DESCRIPTION("IdeaPad ACPI Extras");
1319 MODULE_LICENSE("GPL");