diff options
author | Oleg Keri <ezhi99@gmail.com> | 2018-05-13 19:05:07 +0300 |
---|---|---|
committer | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2018-05-22 12:24:12 +0300 |
commit | 40760717f9cf548e9247f2f94784e72469b175fd (patch) | |
tree | f8d7339cd13c849e6333a7a3a157cab3f7d0b812 /drivers/platform | |
parent | 7caf0c1efd62a755441faa03daa7dd88f0c2150d (diff) | |
download | linux-40760717f9cf548e9247f2f94784e72469b175fd.tar.xz |
platform/x86: ideapad-laptop: Add fn-lock setting
Some of latest Lenovo ideapad laptops do not have UEFI/BIOS setting for
switching fn-lock mode. This commit adds related acpi calls to ideapad
platform driver. However setting is available via sysfs.
Signed-off-by: Oleg Keri <ezhi99@gmail.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/ideapad-laptop.c | 52 |
1 files changed, 49 insertions, 3 deletions
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 97670beb3342..2b3663af1967 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -43,6 +43,7 @@ #define IDEAPAD_RFKILL_DEV_NUM (3) #define BM_CONSERVATION_BIT (5) +#define HA_FNLOCK_BIT (10) #define CFG_BT_BIT (16) #define CFG_3G_BIT (17) @@ -59,6 +60,8 @@ static const char *const ideapad_wmi_fnesc_events[] = { enum { BMCMD_CONSERVATION_ON = 3, BMCMD_CONSERVATION_OFF = 5, + HACMD_FNLOCK_ON = 0xe, + HACMD_FNLOCK_OFF = 0xf, }; enum { @@ -139,11 +142,11 @@ static int method_gbmd(acpi_handle handle, unsigned long *ret) return result; } -static int method_sbmc(acpi_handle handle, int cmd) +static int method_int1(acpi_handle handle, char *method, int cmd) { acpi_status status; - status = acpi_execute_simple_method(handle, "SBMC", cmd); + status = acpi_execute_simple_method(handle, method, cmd); return ACPI_FAILURE(status) ? -1 : 0; } @@ -487,7 +490,7 @@ static ssize_t conservation_mode_store(struct device *dev, if (ret) return ret; - ret = method_sbmc(priv->adev->handle, state ? + ret = method_int1(priv->adev->handle, "SBMC", state ? BMCMD_CONSERVATION_ON : BMCMD_CONSERVATION_OFF); if (ret < 0) @@ -497,11 +500,51 @@ static ssize_t conservation_mode_store(struct device *dev, static DEVICE_ATTR_RW(conservation_mode); +static ssize_t fn_lock_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ideapad_private *priv = dev_get_drvdata(dev); + unsigned long result; + int hals; + int fail = read_method_int(priv->adev->handle, "HALS", &hals); + + if (fail) + return sprintf(buf, "-1\n"); + + result = hals; + return sprintf(buf, "%u\n", test_bit(HA_FNLOCK_BIT, &result)); +} + +static ssize_t fn_lock_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ideapad_private *priv = dev_get_drvdata(dev); + bool state; + int ret; + + ret = kstrtobool(buf, &state); + if (ret) + return ret; + + ret = method_int1(priv->adev->handle, "SALS", state ? + HACMD_FNLOCK_ON : + HACMD_FNLOCK_OFF); + if (ret < 0) + return -EIO; + return count; +} + +static DEVICE_ATTR_RW(fn_lock); + + static struct attribute *ideapad_attributes[] = { &dev_attr_camera_power.attr, &dev_attr_fan_mode.attr, &dev_attr_touchpad.attr, &dev_attr_conservation_mode.attr, + &dev_attr_fn_lock.attr, NULL }; @@ -522,6 +565,9 @@ static umode_t ideapad_is_visible(struct kobject *kobj, } else if (attr == &dev_attr_conservation_mode.attr) { supported = acpi_has_method(priv->adev->handle, "GBMD") && acpi_has_method(priv->adev->handle, "SBMC"); + } else if (attr == &dev_attr_fn_lock.attr) { + supported = acpi_has_method(priv->adev->handle, "HALS") && + acpi_has_method(priv->adev->handle, "SALS"); } else supported = true; |