diff options
-rw-r--r-- | src/acpi/acpigen_dptf.c | 37 | ||||
-rw-r--r-- | src/drivers/intel/dptf/chip.h | 1 | ||||
-rw-r--r-- | src/drivers/intel/dptf/dptf.c | 1 | ||||
-rw-r--r-- | src/include/acpi/acpigen_dptf.h | 27 |
4 files changed, 66 insertions, 0 deletions
diff --git a/src/acpi/acpigen_dptf.c b/src/acpi/acpigen_dptf.c index c18caf673e..6caf8bfcaf 100644 --- a/src/acpi/acpigen_dptf.c +++ b/src/acpi/acpigen_dptf.c @@ -12,6 +12,7 @@ enum { ART_REVISION = 0, DEFAULT_PRIORITY = 100, + DEFAULT_TRIP_POINT = 0xFFFFFFFFull, DEFAULT_WEIGHT = 100, DPTF_MAX_ART_THRESHOLDS = 10, }; @@ -321,3 +322,39 @@ void dptf_write_charger_perf(const struct dptf_charger_perf *states, int max_cou acpigen_pop_len(); /* Method PPSS */ acpigen_pop_len(); /* Scope */ } + +void dptf_write_fan_perf(const struct dptf_fan_perf *states, int max_count) +{ + char *pkg_count; + int i; + + if (!max_count || !states[0].percent) + return; + + dptf_write_scope(DPTF_FAN); + + /* _FPS - Fan Performance States */ + acpigen_write_name("_FPS"); + pkg_count = acpigen_write_package(0); + + for (i = 0; i < max_count; ++i) { + /* + * Some _FPS tables do include a last entry where Percent is 0, but Power is + * called out, so this table is finished when both are zero. + */ + if (!states[i].percent && !states[i].power) + break; + + (*pkg_count)++; + acpigen_write_package(5); + acpigen_write_integer(states[i].percent); + acpigen_write_integer(DEFAULT_TRIP_POINT); + acpigen_write_integer(states[i].speed); + acpigen_write_integer(states[i].noise_level); + acpigen_write_integer(states[i].power); + acpigen_pop_len(); /* inner Package */ + } + + acpigen_pop_len(); /* Package */ + acpigen_pop_len(); /* Scope */ +} diff --git a/src/drivers/intel/dptf/chip.h b/src/drivers/intel/dptf/chip.h index 528ba8354e..cc4ae47caf 100644 --- a/src/drivers/intel/dptf/chip.h +++ b/src/drivers/intel/dptf/chip.h @@ -14,6 +14,7 @@ struct drivers_intel_dptf_config { struct { struct dptf_charger_perf charger_perf[DPTF_MAX_CHARGER_PERF_STATES]; + struct dptf_fan_perf fan_perf[DPTF_MAX_FAN_PERF_STATES]; } controls; }; diff --git a/src/drivers/intel/dptf/dptf.c b/src/drivers/intel/dptf/dptf.c index a20087fff3..bfc04200e0 100644 --- a/src/drivers/intel/dptf/dptf.c +++ b/src/drivers/intel/dptf/dptf.c @@ -74,6 +74,7 @@ static void dptf_fill_ssdt(const struct device *dev) /* Controls */ dptf_write_charger_perf(config->controls.charger_perf, DPTF_MAX_CHARGER_PERF_STATES); + dptf_write_fan_perf(config->controls.fan_perf, DPTF_MAX_FAN_PERF_STATES); printk(BIOS_INFO, "\\_SB.DPTF: %s at %s\n", dev->chip_ops->name, dev_path(dev)); } diff --git a/src/include/acpi/acpigen_dptf.h b/src/include/acpi/acpigen_dptf.h index 7588752aac..3452f79578 100644 --- a/src/include/acpi/acpigen_dptf.h +++ b/src/include/acpi/acpigen_dptf.h @@ -32,6 +32,10 @@ enum { /* Maximum found by automatic inspection (awk) */ DPTF_MAX_CHARGER_PERF_STATES = 10, + DPTF_MAX_FAN_PERF_STATES = 10, + + /* From ACPI spec 6.3 */ + DPTF_FIELD_UNUSED = 0xFFFFFFFFull, }; /* Active Policy */ @@ -87,6 +91,18 @@ struct dptf_charger_perf { uint16_t raw_perf; }; +/* Different levels of fan activity, chosen by active policies */ +struct dptf_fan_perf { + /* Fan percentage level */ + uint8_t percent; + /* Fan speed, in RPM */ + uint16_t speed; + /* Noise level, in 0.1 dBs */ + uint16_t noise_level; + /* Power in mA */ + uint16_t power; +}; + /* * This function provides tables of temperature and corresponding fan or percent. When the * temperature thresholds are met (_AC0 - _AC9), the fan is driven to corresponding percentage @@ -115,6 +131,17 @@ void dptf_write_critical_policies(const struct dptf_critical_policy *policies, i */ void dptf_write_charger_perf(const struct dptf_charger_perf *perf, int max_count); +/* + * This function writes an ACPI table describing various performance levels possible for active + * policies. They indicate, for a given fan percentage level: + * 1) What the corresponding speed is (in RPM) + * 2) The expected noise level (in tenths of decibels AKA centibels, or DPTF_FIELD_UNUSED) + * 3) The power consumption (in mW, or DPTF_FIELD_UNUSED to indicate this field is unused). + * 4) The corresponding active cooling trip point (from _ART) (typically left as + * DPTF_FIELD_UNUSED). + */ +void dptf_write_fan_perf(const struct dptf_fan_perf *perf, int max_count); + /* Helper method to open the scope for a given participant. */ void dptf_write_scope(enum dptf_participant participant); |