From patchwork Thu Apr 11 05:47:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yurii Pavlovskyi X-Patchwork-Id: 10895119 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 213EA1708 for ; Thu, 11 Apr 2019 05:47:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0328C28BC5 for ; Thu, 11 Apr 2019 05:47:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E9E0C28BD4; Thu, 11 Apr 2019 05:47:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 35A6828BC5 for ; Thu, 11 Apr 2019 05:47:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726564AbfDKFrI (ORCPT ); Thu, 11 Apr 2019 01:47:08 -0400 Received: from mail-wr1-f67.google.com ([209.85.221.67]:45074 "EHLO mail-wr1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725782AbfDKFrI (ORCPT ); Thu, 11 Apr 2019 01:47:08 -0400 Received: by mail-wr1-f67.google.com with SMTP id s15so5497307wra.12; Wed, 10 Apr 2019 22:47:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=subject:from:cc:references:message-id:date:user-agent:mime-version :in-reply-to:content-language:content-transfer-encoding; bh=44uZgofqo/TNfvoS6iI9x2taOojCQXaIZtEeHCHIJRQ=; b=MWFohqEj0SUWoyzlueL90hr++T4K+cpW3td0X7kK8/fNIEzCdF05Wo4HuHfOCTYiSm xzlBfXI2QnTKRzNNSyu4Bucaj+Br7LUyD3OuJq1VbfsIuVmyuQzUyJjaUsYFggrKoSic XhWPJ7JGAKNwupWvuSNgW97H8gOZsXR9ORRns+zThusQY9ENUFcxlghZ0x1Wipj6mw/L CzfZQyDKvv0nRGQBagWlTdAJgNBOSQeHhK0QOiJpvT+wgz/L+EwXYWWqLWOAE9ckYJj8 +1ANAbA9G0DisnKDHnGEVUBYQZ7l5ZnLDf2eJXQuG99gITDiTJjTiR+t22+V6bRQL2ne Phaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:cc:references:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=44uZgofqo/TNfvoS6iI9x2taOojCQXaIZtEeHCHIJRQ=; b=fdLTqZhgvruVYc3qqqZaphlU/TfKF0gyarOEH/dYUtgZZCM74ABBbGjZsiohpxi6d4 xLiEwO5bj7PVQkn+B6FDZ/574MOjDakT2RoW+AzxathnLJ/0xCZ1Axb36kJXj6m7J1cI wE8ajZH2vHeYyGlQhyGUdnU+JIXiu5JN3KYfZjU3ouEdIfx2bxVtmolwEKJUJQGgyQx3 i0daC4cZdcqo4q433N8M7pos2EAnKvdoyupCbZz0h36BwCvtx2l88PEa8++lXEmqSTW5 6I1uEPZnCS9XrqLZ+Yjmx6ghKWCcNaItdoniFgAyt5YWEAE93nyrF2g3nrrHDpGjlpd2 Qy0A== X-Gm-Message-State: APjAAAUsW5uIHf7SUsyFdAFfHYa/tMUOI6rbUNYz19QZ/+d2Xh5rD4XY ZN2YBkTx5bO+XMQRFiSGHgyb3IK4qTo= X-Google-Smtp-Source: APXvYqy1HFW7fk9LuaMrJFzFukiqKhtKf9bHqq5fk1qFaco+ZcOE+f1iECG19+/ErpDiYmwpiNa+8Q== X-Received: by 2002:adf:b612:: with SMTP id f18mr18661723wre.236.1554961625705; Wed, 10 Apr 2019 22:47:05 -0700 (PDT) Received: from [192.168.20.141] ([194.99.104.18]) by smtp.gmail.com with ESMTPSA id y127sm5947987wmg.29.2019.04.10.22.47.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 10 Apr 2019 22:47:05 -0700 (PDT) Subject: [PATCH v2 10/11] platform/x86: asus-wmi: Switch fan boost mode From: Yurii Pavlovskyi Cc: Corentin Chary , Darren Hart , Andy Shevchenko , Daniel Drake , acpi4asus-user@lists.sourceforge.net, platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org References: <72b3e0aa-d53a-8a82-1505-f4f00aa2bb46@gmail.com> Message-ID: Date: Thu, 11 Apr 2019 07:47:03 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 In-Reply-To: <72b3e0aa-d53a-8a82-1505-f4f00aa2bb46@gmail.com> Content-Language: en-US To: unlisted-recipients:; (no To-header on input) Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The WMI exposes a write-only device ID where three modes can be switched on some laptops (TUF Gaming FX505GM). There is a hotkey combination Fn-F5 that does have a fan icon which is designed to toggle between these 3 modes. Add a SysFS entry that reads the last written value and updates value in WMI on write and a hotkey handler that toggles the modes. The corresponding DEVS device handler does obviously take 3 possible argument values. Method (SFBM, 1, NotSerialized) { If ((Arg0 == Zero) { .. } If ((Arg0 == One)) { .. } If ((Arg0 == 0x02)) { .. } } ... // DEVS If ((IIA0 == 0x00110018)) { SFBM (IIA1) Return (One) } * 0x00 - is normal, * 0x01 - is obviously turbo by the amount of noise, might be useful to avoid CPU frequency throttling on high load, * 0x02 - the meaning is unknown at the time as modes are not named in the vendor documentation, but it does look like a quiet mode as CPU temperature does increase about 10 degrees on maximum load. Signed-off-by: Yurii Pavlovskyi --- .../ABI/testing/sysfs-platform-asus-wmi | 10 ++ drivers/platform/x86/asus-wmi.c | 119 ++++++++++++++++-- include/linux/platform_data/x86/asus-wmi.h | 1 + 3 files changed, 117 insertions(+), 13 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-platform-asus-wmi b/Documentation/ABI/testing/sysfs-platform-asus-wmi index 300a40519695..2b3184e297a7 100644 --- a/Documentation/ABI/testing/sysfs-platform-asus-wmi +++ b/Documentation/ABI/testing/sysfs-platform-asus-wmi @@ -97,3 +97,13 @@ Description: Write changed RGB keyboard backlight parameters: * 1 - permanently, * 2 - temporarily. + +What: /sys/devices/platform//fan_mode +Date: Apr 2019 +KernelVersion: 5.1 +Contact: "Yurii Pavlovskyi" +Description: + Fan boost mode: + * 0 - normal, + * 1 - turbo, + * 2 - quiet? diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index b4fd200e8335..f0e506feb924 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -69,6 +69,7 @@ MODULE_LICENSE("GPL"); #define NOTIFY_KBD_BRTUP 0xc4 #define NOTIFY_KBD_BRTDWN 0xc5 #define NOTIFY_KBD_BRTTOGGLE 0xc7 +#define NOTIFY_KBD_FBM 0x99 #define ASUS_FAN_DESC "cpu_fan" #define ASUS_FAN_MFUN 0x13 @@ -77,6 +78,8 @@ MODULE_LICENSE("GPL"); #define ASUS_FAN_CTRL_MANUAL 1 #define ASUS_FAN_CTRL_AUTO 2 +#define ASUS_FAN_MODE_COUNT 3 + #define USB_INTEL_XUSB2PR 0xD0 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31 @@ -196,6 +199,9 @@ struct asus_wmi { int asus_hwmon_num_fans; int asus_hwmon_pwm; + bool fan_mode_available; + u8 fan_mode; + bool kbbl_rgb_available; struct asus_kbbl_rgb kbbl_rgb; @@ -1832,6 +1838,87 @@ static int asus_wmi_fan_init(struct asus_wmi *asus) return 0; } +/* Fan mode *******************************************************************/ + +static int fan_mode_check_present(struct asus_wmi *asus) +{ + u32 result; + int err; + + asus->fan_mode_available = false; + + err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_MODE, &result); + if (err) { + if (err == -ENODEV) + return 0; + else + return err; + } + + if (result & ASUS_WMI_DSTS_PRESENCE_BIT) + asus->fan_mode_available = true; + + return 0; +} + +static int fan_mode_write(struct asus_wmi *asus) +{ + int err; + u8 value; + u32 retval; + + value = asus->fan_mode % ASUS_FAN_MODE_COUNT; + pr_info("Set fan mode: %u\n", value); + err = asus_wmi_set_devstate(ASUS_WMI_DEVID_FAN_MODE, value, &retval); + + if (err) { + pr_warn("Failed to set fan mode: %d\n", err); + return err; + } + + if (retval != 1) { + pr_warn("Failed to set fan mode (retval): 0x%x\n", retval); + return -EIO; + } + + return 0; +} + +static int fan_mode_switch_next(struct asus_wmi *asus) +{ + asus->fan_mode = (asus->fan_mode + 1) % ASUS_FAN_MODE_COUNT; + return fan_mode_write(asus); +} + +static ssize_t fan_mode_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct asus_wmi *asus = dev_get_drvdata(dev); + + return show_u8(asus->fan_mode, buf); +} + +static ssize_t fan_mode_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int result; + u8 new_mode; + + struct asus_wmi *asus = dev_get_drvdata(dev); + + result = store_u8(&new_mode, buf, count); + if (result < 0) + return result; + + asus->fan_mode = new_mode % ASUS_FAN_MODE_COUNT; + fan_mode_write(asus); + + return result; +} + +// Fan mode: 0 - normal, 1 - turbo, 2 - quiet? +static DEVICE_ATTR_RW(fan_mode); + /* Backlight ******************************************************************/ static int read_backlight_power(struct asus_wmi *asus) @@ -2083,6 +2170,9 @@ static void asus_wmi_handle_notify(int code, struct asus_wmi *asus) return; } + if (asus->fan_mode_available && code == NOTIFY_KBD_FBM) + fan_mode_switch_next(asus); + if (is_display_toggle(code) && asus->driver->quirks->no_display_toggle) return; @@ -2236,6 +2326,7 @@ static struct attribute *platform_attributes[] = { &dev_attr_touchpad.attr, &dev_attr_lid_resume.attr, &dev_attr_als_enable.attr, + &dev_attr_fan_mode.attr, NULL }; @@ -2257,6 +2348,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, devid = ASUS_WMI_DEVID_LID_RESUME; else if (attr == &dev_attr_als_enable.attr) devid = ASUS_WMI_DEVID_ALS_ENABLE; + else if (attr == &dev_attr_fan_mode.attr) + ok = asus->fan_mode_available; if (devid != -1) ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0); @@ -2281,7 +2374,7 @@ static int asus_wmi_sysfs_init(struct platform_device *device) /* Platform device ************************************************************/ -static int asus_wmi_platform_init(struct asus_wmi *asus) +static void asus_wmi_platform_init(struct asus_wmi *asus) { int rv; @@ -2333,13 +2426,6 @@ static int asus_wmi_platform_init(struct asus_wmi *asus) if (asus->driver->quirks->wapf >= 0) asus_wmi_set_devstate(ASUS_WMI_DEVID_CWAP, asus->driver->quirks->wapf, NULL); - - return asus_wmi_sysfs_init(asus->platform_device); -} - -static void asus_wmi_platform_exit(struct asus_wmi *asus) -{ - asus_wmi_sysfs_exit(asus->platform_device); } /* debugfs ********************************************************************/ @@ -2514,9 +2600,15 @@ static int asus_wmi_add(struct platform_device *pdev) if (wdrv->detect_quirks) wdrv->detect_quirks(asus->driver); - err = asus_wmi_platform_init(asus); + asus_wmi_platform_init(asus); + + err = fan_mode_check_present(asus); if (err) - goto fail_platform; + goto fail_fan_mode; + + err = asus_wmi_sysfs_init(asus->platform_device); + if (err) + goto fail_sysfs; err = asus_wmi_input_init(asus); if (err) @@ -2611,8 +2703,9 @@ static int asus_wmi_add(struct platform_device *pdev) fail_hwmon: asus_wmi_input_exit(asus); fail_input: - asus_wmi_platform_exit(asus); -fail_platform: + asus_wmi_sysfs_exit(asus->platform_device); +fail_sysfs: +fail_fan_mode: kfree(asus); return err; } @@ -2629,7 +2722,7 @@ static int asus_wmi_remove(struct platform_device *device) kbbl_rgb_exit(asus); asus_wmi_rfkill_exit(asus); asus_wmi_debugfs_exit(asus); - asus_wmi_platform_exit(asus); + asus_wmi_sysfs_exit(asus->platform_device); asus_wmi_hwmon_exit(asus); kfree(asus); diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h index 25b7b653e6d2..0f3654b7b8a8 100644 --- a/include/linux/platform_data/x86/asus-wmi.h +++ b/include/linux/platform_data/x86/asus-wmi.h @@ -59,6 +59,7 @@ #define ASUS_WMI_DEVID_LIGHTBAR 0x00050025 #define ASUS_WMI_DEVID_KBD_RGB 0x00100056 #define ASUS_WMI_DEVID_KBD_RGB2 0x00100057 +#define ASUS_WMI_DEVID_FAN_MODE 0x00110018 /* Misc */ #define ASUS_WMI_DEVID_CAMERA 0x00060013