summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/acpi/acpigen_dptf.c37
-rw-r--r--src/drivers/intel/dptf/chip.h1
-rw-r--r--src/drivers/intel/dptf/dptf.c1
-rw-r--r--src/include/acpi/acpigen_dptf.h27
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);