diff options
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/ideapad-laptop.c | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index b4c495a62eec..b0e3a2eef0ac 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c | |||
@@ -87,6 +87,7 @@ struct ideapad_private { | |||
87 | struct backlight_device *blightdev; | 87 | struct backlight_device *blightdev; |
88 | struct dentry *debug; | 88 | struct dentry *debug; |
89 | unsigned long cfg; | 89 | unsigned long cfg; |
90 | bool has_hw_rfkill_switch; | ||
90 | }; | 91 | }; |
91 | 92 | ||
92 | static bool no_bt_rfkill; | 93 | static bool no_bt_rfkill; |
@@ -473,12 +474,14 @@ static struct rfkill_ops ideapad_rfk_ops = { | |||
473 | 474 | ||
474 | static void ideapad_sync_rfk_state(struct ideapad_private *priv) | 475 | static void ideapad_sync_rfk_state(struct ideapad_private *priv) |
475 | { | 476 | { |
476 | unsigned long hw_blocked; | 477 | unsigned long hw_blocked = 0; |
477 | int i; | 478 | int i; |
478 | 479 | ||
479 | if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) | 480 | if (priv->has_hw_rfkill_switch) { |
480 | return; | 481 | if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked)) |
481 | hw_blocked = !hw_blocked; | 482 | return; |
483 | hw_blocked = !hw_blocked; | ||
484 | } | ||
482 | 485 | ||
483 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 486 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) |
484 | if (priv->rfk[i]) | 487 | if (priv->rfk[i]) |
@@ -821,14 +824,17 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) | |||
821 | } | 824 | } |
822 | } | 825 | } |
823 | 826 | ||
824 | /* Blacklist for devices where the ideapad rfkill interface does not work */ | 827 | /* |
825 | static struct dmi_system_id rfkill_blacklist[] = { | 828 | * Some ideapads don't have a hardware rfkill switch, reading VPCCMD_R_RF |
826 | /* The Lenovo Yoga 2 11 always reports everything as blocked */ | 829 | * always results in 0 on these models, causing ideapad_laptop to wrongly |
830 | * report all radios as hardware-blocked. | ||
831 | */ | ||
832 | static struct dmi_system_id no_hw_rfkill_list[] = { | ||
827 | { | 833 | { |
828 | .ident = "Lenovo Yoga 2 11", | 834 | .ident = "Lenovo Yoga 2 11 / 13 / Pro", |
829 | .matches = { | 835 | .matches = { |
830 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 836 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
831 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2 11"), | 837 | DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"), |
832 | }, | 838 | }, |
833 | }, | 839 | }, |
834 | {} | 840 | {} |
@@ -856,6 +862,7 @@ static int ideapad_acpi_add(struct platform_device *pdev) | |||
856 | priv->cfg = cfg; | 862 | priv->cfg = cfg; |
857 | priv->adev = adev; | 863 | priv->adev = adev; |
858 | priv->platform_device = pdev; | 864 | priv->platform_device = pdev; |
865 | priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list); | ||
859 | 866 | ||
860 | ret = ideapad_sysfs_init(priv); | 867 | ret = ideapad_sysfs_init(priv); |
861 | if (ret) | 868 | if (ret) |
@@ -869,11 +876,17 @@ static int ideapad_acpi_add(struct platform_device *pdev) | |||
869 | if (ret) | 876 | if (ret) |
870 | goto input_failed; | 877 | goto input_failed; |
871 | 878 | ||
872 | if (!dmi_check_system(rfkill_blacklist)) { | 879 | /* |
873 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | 880 | * On some models without a hw-switch (the yoga 2 13 at least) |
874 | if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) | 881 | * VPCCMD_W_RF must be explicitly set to 1 for the wifi to work. |
875 | ideapad_register_rfkill(priv, i); | 882 | */ |
876 | } | 883 | if (!priv->has_hw_rfkill_switch) |
884 | write_ec_cmd(priv->adev->handle, VPCCMD_W_RF, 1); | ||
885 | |||
886 | for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) | ||
887 | if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg)) | ||
888 | ideapad_register_rfkill(priv, i); | ||
889 | |||
877 | ideapad_sync_rfk_state(priv); | 890 | ideapad_sync_rfk_state(priv); |
878 | ideapad_sync_touchpad_state(priv); | 891 | ideapad_sync_touchpad_state(priv); |
879 | 892 | ||