summaryrefslogtreecommitdiff
path: root/src/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'src/acpi')
-rw-r--r--src/acpi/acpigen_dptf.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/acpi/acpigen_dptf.c b/src/acpi/acpigen_dptf.c
index 74e91910bb..abd99c1394 100644
--- a/src/acpi/acpigen_dptf.c
+++ b/src/acpi/acpigen_dptf.c
@@ -9,6 +9,7 @@
/* Defaults */
enum {
ART_REVISION = 0,
+ DEFAULT_PRIORITY = 100,
DEFAULT_WEIGHT = 100,
DPTF_MAX_ART_THRESHOLDS = 10,
};
@@ -19,6 +20,12 @@ static int to_acpi_temp(int deg_c)
return deg_c * 10 + 2732;
}
+/* Converts ms to 1/10th second for ACPI */
+static int to_acpi_time(int ms)
+{
+ return ms / 100;
+}
+
/* Writes out a 0-argument non-Serialized Method that returns an Integer */
static void write_simple_return_method(const char *name, int value)
{
@@ -27,6 +34,13 @@ static void write_simple_return_method(const char *name, int value)
acpigen_pop_len(); /* Method */
}
+/* Writes out 'count' ZEROs in a row */
+static void write_zeros(int count)
+{
+ for (; count; --count)
+ acpigen_write_integer(0);
+}
+
/* Return the assigned namestring of any participant */
static const char *namestring_of(enum dptf_participant participant)
{
@@ -164,3 +178,87 @@ void dptf_write_active_policies(const struct dptf_active_policy *policies, int m
write_active_relationship_table(policies, max_count);
write_active_cooling_methods(policies, max_count);
}
+
+/*
+ * This writes out the Thermal Relationship Table, which describes the thermal relationships
+ * between participants in a thermal zone. This information is used to passively cool (i.e.,
+ * throttle) the Source (source of heat), in order to indirectly cool the Target (temperature
+ * sensor).
+ */
+static void write_thermal_relationship_table(const struct dptf_passive_policy *policies,
+ int max_count)
+{
+ char *pkg_count;
+ int i;
+
+ /* Nothing to do */
+ if (!max_count || policies[0].source == DPTF_NONE)
+ return;
+
+ acpigen_write_scope(TOPLEVEL_DPTF_SCOPE);
+
+ /*
+ * A _TRT Revision (TRTR) of 1 means that the 'Priority' field is an arbitrary priority
+ * value to be used for this specific relationship. The priority value determines the
+ * order in which various sources are used in a passive thermal action for a given
+ * target.
+ */
+ acpigen_write_name_integer("TRTR", 1);
+
+ /* Thermal Relationship Table */
+ acpigen_write_method("_TRT", 0);
+
+ /* Return this package */
+ acpigen_emit_byte(RETURN_OP);
+ pkg_count = acpigen_write_package(0);
+
+ for (i = 0; i < max_count; ++i) {
+ /* Stop writing the table once an entry is empty */
+ if (policies[i].source == DPTF_NONE)
+ break;
+
+ /* Keep track of outer package item count */
+ (*pkg_count)++;
+
+ acpigen_write_package(8);
+
+ /* Source, Target, Priority, Sampling Period */
+ acpigen_emit_namestring(namestring_of(policies[i].source));
+ acpigen_emit_namestring(namestring_of(policies[i].target));
+ acpigen_write_integer(DEFAULT_IF_0(policies[i].priority, DEFAULT_PRIORITY));
+ acpigen_write_integer(to_acpi_time(policies[i].period));
+
+ /* Reserved */
+ write_zeros(4);
+
+ acpigen_pop_len(); /* Package */
+ }
+
+ acpigen_pop_len(); /* Package */
+ acpigen_pop_len(); /* Method */
+ acpigen_pop_len(); /* Scope */
+}
+
+/*
+ * When a temperature sensor measures above its the temperature returned in its _PSV Method,
+ * DPTF will begin throttling Sources in order to indirectly cool the sensor.
+ */
+static void write_all_PSV(const struct dptf_passive_policy *policies, int max_count)
+{
+ int i;
+
+ for (i = 0; i < max_count; ++i) {
+ if (policies[i].source == DPTF_NONE)
+ break;
+
+ dptf_write_scope(policies[i].target);
+ write_simple_return_method("_PSV", to_acpi_temp(policies[i].temp));
+ acpigen_pop_len(); /* Scope */
+ }
+}
+
+void dptf_write_passive_policies(const struct dptf_passive_policy *policies, int max_count)
+{
+ write_thermal_relationship_table(policies, max_count);
+ write_all_PSV(policies, max_count);
+}