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