Skip to content

Commit 3ed1734

Browse files
Daniel Leeij-intel
authored andcommitted
platform/x86: lg-laptop: Fix WMAB call in fan_mode_store()
When WMAB is called to set the fan mode, the new mode is read from either bits 0-1 or bits 4-5 (depending on the value of some other EC register). Thus when WMAB is called with bits 4-5 zeroed and called again with bits 0-1 zeroed, the second call undoes the effect of the first call. This causes writes to /sys/devices/platform/lg-laptop/fan_mode to have no effect (and causes reads to always report a status of zero). Fix this by calling WMAB once, with the mode set in bits 0,1 and 4,5. When the fan mode is returned from WMAB it always has this form, so there is no need to preserve the other bits. As a bonus, the driver now supports the "Performance" fan mode seen in the LG-provided Windows control app, which provides less aggressive CPU throttling but louder fan noise and shorter battery life. Also, correct the documentation to reflect that 0 corresponds to the default mode (what the Windows app calls "Optimal") and 1 corresponds to the silent mode. Fixes: dbf0c5a ("platform/x86: Add LG Gram laptop special features driver") Link: https://bugzilla.kernel.org/show_bug.cgi?id=204913#c4 Signed-off-by: Daniel Lee <dany97@live.ca> Link: https://patch.msgid.link/MN2PR06MB55989CB10E91C8DA00EE868DDC1CA@MN2PR06MB5598.namprd06.prod.outlook.com Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
1 parent a15b5ae commit 3ed1734

2 files changed

Lines changed: 16 additions & 22 deletions

File tree

Documentation/admin-guide/laptops/lg-laptop.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ This value is reset to 100 when the kernel boots.
4848
Fan mode
4949
--------
5050

51-
Writing 1/0 to /sys/devices/platform/lg-laptop/fan_mode disables/enables
52-
the fan silent mode.
51+
Writing 0/1/2 to /sys/devices/platform/lg-laptop/fan_mode sets fan mode to
52+
Optimal/Silent/Performance respectively.
5353

5454

5555
USB charge

drivers/platform/x86/lg-laptop.c

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
99

1010
#include <linux/acpi.h>
11+
#include <linux/bitfield.h>
1112
#include <linux/bits.h>
1213
#include <linux/device.h>
1314
#include <linux/dev_printk.h>
@@ -75,6 +76,9 @@ MODULE_PARM_DESC(fw_debug, "Enable printing of firmware debug messages");
7576
#define WMBB_USB_CHARGE 0x10B
7677
#define WMBB_BATT_LIMIT 0x10C
7778

79+
#define FAN_MODE_LOWER GENMASK(1, 0)
80+
#define FAN_MODE_UPPER GENMASK(5, 4)
81+
7882
#define PLATFORM_NAME "lg-laptop"
7983

8084
MODULE_ALIAS("wmi:" WMI_EVENT_GUID0);
@@ -274,29 +278,19 @@ static ssize_t fan_mode_store(struct device *dev,
274278
struct device_attribute *attr,
275279
const char *buffer, size_t count)
276280
{
277-
bool value;
281+
unsigned long value;
278282
union acpi_object *r;
279-
u32 m;
280283
int ret;
281284

282-
ret = kstrtobool(buffer, &value);
285+
ret = kstrtoul(buffer, 10, &value);
283286
if (ret)
284287
return ret;
288+
if (value >= 3)
289+
return -EINVAL;
285290

286-
r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0);
287-
if (!r)
288-
return -EIO;
289-
290-
if (r->type != ACPI_TYPE_INTEGER) {
291-
kfree(r);
292-
return -EIO;
293-
}
294-
295-
m = r->integer.value;
296-
kfree(r);
297-
r = lg_wmab(dev, WM_FAN_MODE, WM_SET, (m & 0xffffff0f) | (value << 4));
298-
kfree(r);
299-
r = lg_wmab(dev, WM_FAN_MODE, WM_SET, (m & 0xfffffff0) | value);
291+
r = lg_wmab(dev, WM_FAN_MODE, WM_SET,
292+
FIELD_PREP(FAN_MODE_LOWER, value) |
293+
FIELD_PREP(FAN_MODE_UPPER, value));
300294
kfree(r);
301295

302296
return count;
@@ -305,7 +299,7 @@ static ssize_t fan_mode_store(struct device *dev,
305299
static ssize_t fan_mode_show(struct device *dev,
306300
struct device_attribute *attr, char *buffer)
307301
{
308-
unsigned int status;
302+
unsigned int mode;
309303
union acpi_object *r;
310304

311305
r = lg_wmab(dev, WM_FAN_MODE, WM_GET, 0);
@@ -317,10 +311,10 @@ static ssize_t fan_mode_show(struct device *dev,
317311
return -EIO;
318312
}
319313

320-
status = r->integer.value & 0x01;
314+
mode = FIELD_GET(FAN_MODE_LOWER, r->integer.value);
321315
kfree(r);
322316

323-
return sysfs_emit(buffer, "%d\n", status);
317+
return sysfs_emit(buffer, "%d\n", mode);
324318
}
325319

326320
static ssize_t usb_charge_store(struct device *dev,

0 commit comments

Comments
 (0)