Commit | Line | Data |
---|---|---|
1802d0be | 1 | // SPDX-License-Identifier: GPL-2.0-only |
c55d6282 SP |
2 | /* |
3 | * acpi_lpat.c - LPAT table processing functions | |
4 | * | |
5 | * Copyright (C) 2015 Intel Corporation. All rights reserved. | |
c55d6282 SP |
6 | */ |
7 | ||
c49b43ce | 8 | #include <linux/export.h> |
c55d6282 SP |
9 | #include <linux/acpi.h> |
10 | #include <acpi/acpi_lpat.h> | |
11 | ||
12 | /** | |
13 | * acpi_lpat_raw_to_temp(): Return temperature from raw value through | |
14 | * LPAT conversion table | |
15 | * | |
16 | * @lpat_table: the temperature_raw mapping table structure | |
603fadf3 | 17 | * @raw: the raw value, used as a key to get the temperature from the |
c55d6282 SP |
18 | * above mapping table |
19 | * | |
a06f29b2 | 20 | * A positive converted temperature value will be returned on success, |
c55d6282 SP |
21 | * a negative errno will be returned in error cases. |
22 | */ | |
23 | int acpi_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table, | |
24 | int raw) | |
25 | { | |
26 | int i, delta_temp, delta_raw, temp; | |
27 | struct acpi_lpat *lpat = lpat_table->lpat; | |
28 | ||
29 | for (i = 0; i < lpat_table->lpat_count - 1; i++) { | |
30 | if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) || | |
31 | (raw <= lpat[i].raw && raw >= lpat[i+1].raw)) | |
32 | break; | |
33 | } | |
34 | ||
35 | if (i == lpat_table->lpat_count - 1) | |
36 | return -ENOENT; | |
37 | ||
38 | delta_temp = lpat[i+1].temp - lpat[i].temp; | |
39 | delta_raw = lpat[i+1].raw - lpat[i].raw; | |
40 | temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw; | |
41 | ||
42 | return temp; | |
43 | } | |
44 | EXPORT_SYMBOL_GPL(acpi_lpat_raw_to_temp); | |
45 | ||
46 | /** | |
47 | * acpi_lpat_temp_to_raw(): Return raw value from temperature through | |
48 | * LPAT conversion table | |
49 | * | |
a06f29b2 | 50 | * @lpat_table: the temperature_raw mapping table |
c55d6282 SP |
51 | * @temp: the temperature, used as a key to get the raw value from the |
52 | * above mapping table | |
53 | * | |
a06f29b2 | 54 | * The raw value will be returned on success, |
c55d6282 SP |
55 | * a negative errno will be returned in error cases. |
56 | */ | |
57 | int acpi_lpat_temp_to_raw(struct acpi_lpat_conversion_table *lpat_table, | |
58 | int temp) | |
59 | { | |
60 | int i, delta_temp, delta_raw, raw; | |
61 | struct acpi_lpat *lpat = lpat_table->lpat; | |
62 | ||
63 | for (i = 0; i < lpat_table->lpat_count - 1; i++) { | |
64 | if (temp >= lpat[i].temp && temp <= lpat[i+1].temp) | |
65 | break; | |
66 | } | |
67 | ||
68 | if (i == lpat_table->lpat_count - 1) | |
69 | return -ENOENT; | |
70 | ||
71 | delta_temp = lpat[i+1].temp - lpat[i].temp; | |
72 | delta_raw = lpat[i+1].raw - lpat[i].raw; | |
73 | raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp; | |
74 | ||
75 | return raw; | |
76 | } | |
77 | EXPORT_SYMBOL_GPL(acpi_lpat_temp_to_raw); | |
78 | ||
79 | /** | |
80 | * acpi_lpat_get_conversion_table(): Parse ACPI LPAT table if present. | |
81 | * | |
82 | * @handle: Handle to acpi device | |
83 | * | |
84 | * Parse LPAT table to a struct of type acpi_lpat_table. On success | |
85 | * it returns a pointer to newly allocated table. This table must | |
86 | * be freed by the caller when finished processing, using a call to | |
87 | * acpi_lpat_free_conversion_table. | |
88 | */ | |
89 | struct acpi_lpat_conversion_table *acpi_lpat_get_conversion_table(acpi_handle | |
90 | handle) | |
91 | { | |
92 | struct acpi_lpat_conversion_table *lpat_table = NULL; | |
93 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | |
94 | union acpi_object *obj_p, *obj_e; | |
95 | int *lpat, i; | |
96 | acpi_status status; | |
97 | ||
98 | status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer); | |
99 | if (ACPI_FAILURE(status)) | |
100 | return NULL; | |
101 | ||
102 | obj_p = (union acpi_object *)buffer.pointer; | |
103 | if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) || | |
104 | (obj_p->package.count % 2) || (obj_p->package.count < 4)) | |
105 | goto out; | |
106 | ||
107 | lpat = kcalloc(obj_p->package.count, sizeof(int), GFP_KERNEL); | |
108 | if (!lpat) | |
109 | goto out; | |
110 | ||
111 | for (i = 0; i < obj_p->package.count; i++) { | |
112 | obj_e = &obj_p->package.elements[i]; | |
113 | if (obj_e->type != ACPI_TYPE_INTEGER) { | |
114 | kfree(lpat); | |
115 | goto out; | |
116 | } | |
117 | lpat[i] = (s64)obj_e->integer.value; | |
118 | } | |
119 | ||
120 | lpat_table = kzalloc(sizeof(*lpat_table), GFP_KERNEL); | |
121 | if (!lpat_table) { | |
122 | kfree(lpat); | |
123 | goto out; | |
124 | } | |
125 | ||
126 | lpat_table->lpat = (struct acpi_lpat *)lpat; | |
127 | lpat_table->lpat_count = obj_p->package.count / 2; | |
128 | ||
129 | out: | |
130 | kfree(buffer.pointer); | |
131 | return lpat_table; | |
132 | } | |
133 | EXPORT_SYMBOL_GPL(acpi_lpat_get_conversion_table); | |
134 | ||
135 | /** | |
136 | * acpi_lpat_free_conversion_table(): Free LPAT table. | |
137 | * | |
138 | * @lpat_table: the temperature_raw mapping table structure | |
139 | * | |
140 | * Frees the LPAT table previously allocated by a call to | |
141 | * acpi_lpat_get_conversion_table. | |
142 | */ | |
143 | void acpi_lpat_free_conversion_table(struct acpi_lpat_conversion_table | |
144 | *lpat_table) | |
145 | { | |
146 | if (lpat_table) { | |
147 | kfree(lpat_table->lpat); | |
148 | kfree(lpat_table); | |
149 | } | |
150 | } | |
151 | EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table); |