mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-11 00:08:50 +00:00
platform/x86: acer-wmi: add fan speed monitoring for Predator PHN16-71
Support CPU and GPU fan speed monitoring through WMI for Predator PHN16-71. Signed-off-by: SungHwan Jung <onenowy@gmail.com> Link: https://lore.kernel.org/r/20231124094122.100707-3-onenowy@gmail.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
c0ff2c397e
commit
446dd8efa9
@ -178,6 +178,7 @@ config ACER_WMI
|
||||
depends on RFKILL || RFKILL = n
|
||||
depends on ACPI_WMI
|
||||
depends on ACPI_VIDEO || ACPI_VIDEO = n
|
||||
depends on HWMON
|
||||
select INPUT_SPARSEKMAP
|
||||
select LEDS_CLASS
|
||||
select NEW_LEDS
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/input/sparse-keymap.h>
|
||||
#include <acpi/video.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
MODULE_AUTHOR("Carlos Corbacho");
|
||||
MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
|
||||
@ -69,6 +71,8 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
#define ACER_PREDATOR_V4_THERMAL_PROFILE_EC_OFFSET 0x54
|
||||
|
||||
#define ACER_PREDATOR_V4_FAN_SPEED_READ_BIT_MASK GENMASK(20, 8)
|
||||
|
||||
/*
|
||||
* Acer ACPI method GUIDs
|
||||
*/
|
||||
@ -96,6 +100,8 @@ enum acer_wmi_event_ids {
|
||||
|
||||
enum acer_wmi_predator_v4_sys_info_command {
|
||||
ACER_WMID_CMD_GET_PREDATOR_V4_BAT_STATUS = 0x02,
|
||||
ACER_WMID_CMD_GET_PREDATOR_V4_CPU_FAN_SPEED = 0x0201,
|
||||
ACER_WMID_CMD_GET_PREDATOR_V4_GPU_FAN_SPEED = 0x0601,
|
||||
};
|
||||
|
||||
static const struct key_entry acer_wmi_keymap[] __initconst = {
|
||||
@ -241,6 +247,7 @@ struct hotkey_function_type_aa {
|
||||
#define ACER_CAP_TURBO_LED BIT(8)
|
||||
#define ACER_CAP_TURBO_FAN BIT(9)
|
||||
#define ACER_CAP_PLATFORM_PROFILE BIT(10)
|
||||
#define ACER_CAP_FAN_SPEED_READ BIT(11)
|
||||
|
||||
/*
|
||||
* Interface type flags
|
||||
@ -352,7 +359,8 @@ static void __init set_quirks(void)
|
||||
| ACER_CAP_TURBO_FAN;
|
||||
|
||||
if (quirks->predator_v4)
|
||||
interface->capability |= ACER_CAP_PLATFORM_PROFILE;
|
||||
interface->capability |= ACER_CAP_PLATFORM_PROFILE |
|
||||
ACER_CAP_FAN_SPEED_READ;
|
||||
}
|
||||
|
||||
static int __init dmi_matched(const struct dmi_system_id *dmi)
|
||||
@ -1718,6 +1726,26 @@ static int acer_gsensor_event(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acer_get_fan_speed(int fan)
|
||||
{
|
||||
if (quirks->predator_v4) {
|
||||
acpi_status status;
|
||||
u64 fanspeed;
|
||||
|
||||
status = WMI_gaming_execute_u64(
|
||||
ACER_WMID_GET_GAMING_SYS_INFO_METHODID,
|
||||
fan == 0 ? ACER_WMID_CMD_GET_PREDATOR_V4_CPU_FAN_SPEED :
|
||||
ACER_WMID_CMD_GET_PREDATOR_V4_GPU_FAN_SPEED,
|
||||
&fanspeed);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
return FIELD_GET(ACER_PREDATOR_V4_FAN_SPEED_READ_BIT_MASK, fanspeed);
|
||||
}
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/*
|
||||
* Predator series turbo button
|
||||
*/
|
||||
@ -2472,6 +2500,8 @@ static u32 get_wmid_devices(void)
|
||||
return devices;
|
||||
}
|
||||
|
||||
static int acer_wmi_hwmon_init(void);
|
||||
|
||||
/*
|
||||
* Platform device
|
||||
*/
|
||||
@ -2501,8 +2531,17 @@ static int acer_platform_probe(struct platform_device *device)
|
||||
goto error_platform_profile;
|
||||
}
|
||||
|
||||
if (has_cap(ACER_CAP_FAN_SPEED_READ)) {
|
||||
err = acer_wmi_hwmon_init();
|
||||
if (err)
|
||||
goto error_hwmon;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_hwmon:
|
||||
if (platform_profile_support)
|
||||
platform_profile_remove();
|
||||
error_platform_profile:
|
||||
acer_rfkill_exit();
|
||||
error_rfkill:
|
||||
@ -2612,6 +2651,73 @@ static void __init create_debugfs(void)
|
||||
&interface->debug.wmid_devices);
|
||||
}
|
||||
|
||||
static umode_t acer_wmi_hwmon_is_visible(const void *data,
|
||||
enum hwmon_sensor_types type, u32 attr,
|
||||
int channel)
|
||||
{
|
||||
switch (type) {
|
||||
case hwmon_fan:
|
||||
if (acer_get_fan_speed(channel) >= 0)
|
||||
return 0444;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acer_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (type) {
|
||||
case hwmon_fan:
|
||||
ret = acer_get_fan_speed(channel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = ret;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hwmon_channel_info *const acer_wmi_hwmon_info[] = {
|
||||
HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT, HWMON_F_INPUT), NULL
|
||||
};
|
||||
|
||||
static const struct hwmon_ops acer_wmi_hwmon_ops = {
|
||||
.read = acer_wmi_hwmon_read,
|
||||
.is_visible = acer_wmi_hwmon_is_visible,
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info acer_wmi_hwmon_chip_info = {
|
||||
.ops = &acer_wmi_hwmon_ops,
|
||||
.info = acer_wmi_hwmon_info,
|
||||
};
|
||||
|
||||
static int acer_wmi_hwmon_init(void)
|
||||
{
|
||||
struct device *dev = &acer_platform_device->dev;
|
||||
struct device *hwmon;
|
||||
|
||||
hwmon = devm_hwmon_device_register_with_info(dev, "acer",
|
||||
&acer_platform_driver,
|
||||
&acer_wmi_hwmon_chip_info,
|
||||
NULL);
|
||||
|
||||
if (IS_ERR(hwmon)) {
|
||||
dev_err(dev, "Could not register acer hwmon device\n");
|
||||
return PTR_ERR(hwmon);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init acer_wmi_init(void)
|
||||
{
|
||||
int err;
|
||||
|
Loading…
x
Reference in New Issue
Block a user