aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/ideapad-laptop.c41
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
92static bool no_bt_rfkill; 93static bool no_bt_rfkill;
@@ -473,12 +474,14 @@ static struct rfkill_ops ideapad_rfk_ops = {
473 474
474static void ideapad_sync_rfk_state(struct ideapad_private *priv) 475static 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/*
825static 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 */
832static 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