Subject: [PATCH] [acpi thermal] Add support setting cooling mode - Add ->t_cooling_mode field to struct acpi_thermal - Implement thermal_set_cooling_mode() - Call on device init (via cooling_mode_init()). Signed-off-by: Patrick Mochel --- drivers/acpi/drivers/thermal/device.c | 32 +++++++++++++++++++++++ drivers/acpi/drivers/thermal/driver.c | 45 ++++++++++++++++++++++++++++++++ drivers/acpi/drivers/thermal/thermal.h | 3 ++ 3 files changed, 80 insertions(+), 0 deletions(-) applies-to: bf4706ace45bed25e999e9ef69668db0fd2af6f6 8094a97d6ff80025c5380984137007ed04c17709 diff --git a/drivers/acpi/drivers/thermal/device.c b/drivers/acpi/drivers/thermal/device.c index c7e2b53..c95ac24 100644 --- a/drivers/acpi/drivers/thermal/device.c +++ b/drivers/acpi/drivers/thermal/device.c @@ -156,3 +156,35 @@ int thermal_get_trips(struct acpi_therma return 0; } + +int thermal_set_cooling_mode(struct acpi_thermal * at, int mode) +{ + acpi_status status; + union acpi_object arg = { + .type = ACPI_TYPE_INTEGER, + .integer = { + .value = mode, + }, + }; + struct acpi_object_list arg_list = { + .count = 1, + .pointer = &arg, + }; + acpi_handle handle = NULL; + + status = acpi_get_handle(at->t_ad->acpi_device->handle, + "_SCP", &handle); + if (ACPI_FAILURE(status)) { + dbg("_SCP not present"); + return -ENODEV; + } + + status = acpi_evaluate_object(handle, NULL, &arg_list, NULL); + if (ACPI_FAILURE(status)) + return -ENODEV; + + at->t_cooling_mode = mode; + + dbg("Cooling mode set to [%s]", mode ? "passive" : "active"); + return 0; +} diff --git a/drivers/acpi/drivers/thermal/driver.c b/drivers/acpi/drivers/thermal/driver.c index 350dc0d..50bc500 100644 --- a/drivers/acpi/drivers/thermal/driver.c +++ b/drivers/acpi/drivers/thermal/driver.c @@ -13,6 +13,49 @@ #include "thermal.h" + +static int cooling_mode_init(struct acpi_thermal * at) +{ + int ret; + + /* + * Set to active cooling mode + */ + ret = thermal_set_cooling_mode(at, THERMAL_MODE_ACT); + if (!ret) { + at->t_cooling_mode = 1; + } else { + struct thermal_active * ta = &at->t_trips.act[0]; + int mode; + + /* + * We can't do active cooling, so choose a fall-back + */ + if (ta->val) { + if (at->t_trips.psv_val) { + if (at->t_trips.psv_temp > ta->temp) + mode = THERMAL_MODE_ACT; + else + mode = THERMAL_MODE_PSV; + } else { + mode = THERMAL_MODE_ACT; + } + } else { + if (at->t_trips.psv_val) { + mode = THERMAL_MODE_PSV; + } else { + /* + * Neither stepped up, so fall back to + * using _CRT (critical). + */ + mode = THERMAL_MODE_CRIT; + } + } + at->t_cooling_mode = mode; + } + return ret; +} + static int thermal_init(struct acpi_thermal * at) { int ret; @@ -31,6 +74,8 @@ static int thermal_init(struct acpi_ther if (ret) return ret; + cooling_mode_init(at); + return 0; } diff --git a/drivers/acpi/drivers/thermal/thermal.h b/drivers/acpi/drivers/thermal/thermal.h index e3dc2c4..2ef4b5f 100644 --- a/drivers/acpi/drivers/thermal/thermal.h +++ b/drivers/acpi/drivers/thermal/thermal.h @@ -61,9 +61,12 @@ struct acpi_thermal { long t_last_temp; struct thermal_trips t_trips; + u32 t_cooling_mode; }; extern int thermal_get_temp(struct acpi_thermal *); extern int thermal_get_trips(struct acpi_thermal * at); +extern int thermal_set_cooling_mode(struct acpi_thermal *, int); + extern long thermal_temp_c(long tempk); --- 0.99.9.GIT