Re: [PATCH v2 10/11] platform/x86: asus-wmi: Switch fan boost mode

2019-04-12 Thread Yurii Pavlovskyi
On 12.04.19 10:03, Daniel Drake wrote:
> On Thu, Apr 11, 2019 at 1:47 PM Yurii Pavlovskyi
>  wrote:
>> * 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.
> 
> I'm curious which vendor documentation you're working with here.

That would be user manual for FX505 series, which is pretty minimalistic.
It says it has a fan mode switch key and that's it. Following up on your
comment, I've searched more and actually did found their names hidden in
marketing web page on the website. You're right, they call them balanced,
overboost and silent there.

> From the spec,
> 0 = normal
> 1 = overboost
> 2 = silent

> Also you can use DSTS on the 0x00110018 device to check the exact
> capabilities supported, which you should use to refine which modes can
> be cycled through.
> Bit 0 = overboost supported
> Bit 1 = silent supported
> 
> Thanks
> Daniel
> 

Thanks! I was guessing that the 3 in DSTS must've meant something.

Appreciate your comments! Will definitely implement them. I'm going to post
the v3 patch series approximately middle of next week.

Best regards,
Yurii


Re: [PATCH v2 10/11] platform/x86: asus-wmi: Switch fan boost mode

2019-04-12 Thread Daniel Drake
On Thu, Apr 11, 2019 at 1:47 PM Yurii Pavlovskyi
 wrote:
> * 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.

I'm curious which vendor documentation you're working with here.

>From the spec,
0 = normal
1 = overboost
2 = silent

Also you can use DSTS on the 0x00110018 device to check the exact
capabilities supported, which you should use to refine which modes can
be cycled through.
Bit 0 = overboost supported
Bit 1 = silent supported

Thanks
Daniel


[PATCH v2 10/11] platform/x86: asus-wmi: Switch fan boost mode

2019-04-10 Thread Yurii Pavlovskyi
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_COUNT3
+
 #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, );
+   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, );
+
+   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(_mode, buf, count);
+   if (result < 0)
+   return result;
+
+