1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2021-2023 Realtek Corporation
3 */
4
5 #include <linux/acpi.h>
6 #include <linux/uuid.h>
7
8 #include "acpi.h"
9 #include "debug.h"
10
11 static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
12 0x82, 0xBD, 0xFE, 0x86,
13 0x07, 0x80, 0x3A, 0xA7);
14
rtw89_acpi_traversal_object(struct rtw89_dev * rtwdev,const union acpi_object * obj,u8 * pos)15 static u32 rtw89_acpi_traversal_object(struct rtw89_dev *rtwdev,
16 const union acpi_object *obj, u8 *pos)
17 {
18 const union acpi_object *elm;
19 unsigned int i;
20 u32 sub_len;
21 u32 len = 0;
22 u8 *tmp;
23
24 switch (obj->type) {
25 case ACPI_TYPE_INTEGER:
26 if (pos)
27 pos[len] = obj->integer.value;
28
29 len++;
30 break;
31 case ACPI_TYPE_BUFFER:
32 if (unlikely(obj->buffer.length == 0)) {
33 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
34 "%s: invalid buffer type\n", __func__);
35 goto err;
36 }
37
38 if (pos)
39 memcpy(pos, obj->buffer.pointer, obj->buffer.length);
40
41 len += obj->buffer.length;
42 break;
43 case ACPI_TYPE_PACKAGE:
44 if (unlikely(obj->package.count == 0)) {
45 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
46 "%s: invalid package type\n", __func__);
47 goto err;
48 }
49
50 for (i = 0; i < obj->package.count; i++) {
51 elm = &obj->package.elements[i];
52 tmp = pos ? pos + len : NULL;
53
54 sub_len = rtw89_acpi_traversal_object(rtwdev, elm, tmp);
55 if (unlikely(sub_len == 0))
56 goto err;
57
58 len += sub_len;
59 }
60 break;
61 default:
62 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: unhandled type: %d\n",
63 __func__, obj->type);
64 goto err;
65 }
66
67 return len;
68
69 err:
70 return 0;
71 }
72
rtw89_acpi_calculate_object_length(struct rtw89_dev * rtwdev,const union acpi_object * obj)73 static u32 rtw89_acpi_calculate_object_length(struct rtw89_dev *rtwdev,
74 const union acpi_object *obj)
75 {
76 return rtw89_acpi_traversal_object(rtwdev, obj, NULL);
77 }
78
79 static struct rtw89_acpi_data *
rtw89_acpi_evaluate_method(struct rtw89_dev * rtwdev,const char * method)80 rtw89_acpi_evaluate_method(struct rtw89_dev *rtwdev, const char *method)
81 {
82 struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
83 struct rtw89_acpi_data *data = NULL;
84 acpi_handle root, handle;
85 union acpi_object *obj;
86 acpi_status status;
87 u32 len;
88
89 root = ACPI_HANDLE(rtwdev->dev);
90 if (!root) {
91 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
92 "acpi (%s): failed to get root\n", method);
93 return NULL;
94 }
95
96 #if defined(__linux__)
97 status = acpi_get_handle(root, (acpi_string)method, &handle);
98 #elif defined(__FreeBSD__)
99 status = acpi_get_handle(root, method, &handle);
100 #endif
101 if (ACPI_FAILURE(status)) {
102 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
103 "acpi (%s): failed to get handle\n", method);
104 return NULL;
105 }
106
107 status = acpi_evaluate_object(handle, NULL, NULL, &buf);
108 if (ACPI_FAILURE(status)) {
109 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
110 "acpi (%s): failed to evaluate object\n", method);
111 return NULL;
112 }
113
114 obj = buf.pointer;
115 len = rtw89_acpi_calculate_object_length(rtwdev, obj);
116 if (unlikely(len == 0)) {
117 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
118 "acpi (%s): failed to traversal obj len\n", method);
119 goto out;
120 }
121
122 data = kzalloc(struct_size(data, buf, len), GFP_KERNEL);
123 if (!data)
124 goto out;
125
126 data->len = len;
127 rtw89_acpi_traversal_object(rtwdev, obj, data->buf);
128
129 out:
130 ACPI_FREE(obj);
131 return data;
132 }
133
134 static
rtw89_acpi_dsm_get_value(struct rtw89_dev * rtwdev,union acpi_object * obj,u8 * value)135 int rtw89_acpi_dsm_get_value(struct rtw89_dev *rtwdev, union acpi_object *obj,
136 u8 *value)
137 {
138 if (obj->type != ACPI_TYPE_INTEGER) {
139 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
140 "acpi: expect integer but type: %d\n", obj->type);
141 return -EINVAL;
142 }
143
144 *value = (u8)obj->integer.value;
145 return 0;
146 }
147
chk_acpi_policy_6ghz_sig(const struct rtw89_acpi_policy_6ghz * p)148 static bool chk_acpi_policy_6ghz_sig(const struct rtw89_acpi_policy_6ghz *p)
149 {
150 return p->signature[0] == 0x00 &&
151 p->signature[1] == 0xE0 &&
152 p->signature[2] == 0x4C;
153 }
154
155 static
rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_6ghz ** policy_6ghz)156 int rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev *rtwdev,
157 union acpi_object *obj,
158 struct rtw89_acpi_policy_6ghz **policy_6ghz)
159 {
160 const struct rtw89_acpi_policy_6ghz *ptr;
161 u32 expect_len;
162 u32 len;
163
164 if (obj->type != ACPI_TYPE_BUFFER) {
165 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
166 "acpi: expect buffer but type: %d\n", obj->type);
167 return -EINVAL;
168 }
169
170 len = obj->buffer.length;
171 if (len < sizeof(*ptr)) {
172 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
173 __func__, len);
174 return -EINVAL;
175 }
176
177 ptr = (typeof(ptr))obj->buffer.pointer;
178 if (!chk_acpi_policy_6ghz_sig(ptr)) {
179 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
180 return -EINVAL;
181 }
182
183 expect_len = struct_size(ptr, country_list, ptr->country_count);
184 if (len < expect_len) {
185 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: expect %u but length: %u\n",
186 __func__, expect_len, len);
187 return -EINVAL;
188 }
189
190 *policy_6ghz = kmemdup(ptr, expect_len, GFP_KERNEL);
191 if (!*policy_6ghz)
192 return -ENOMEM;
193
194 rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz: ", *policy_6ghz,
195 expect_len);
196 return 0;
197 }
198
chk_acpi_policy_6ghz_sp_sig(const struct rtw89_acpi_policy_6ghz_sp * p)199 static bool chk_acpi_policy_6ghz_sp_sig(const struct rtw89_acpi_policy_6ghz_sp *p)
200 {
201 return p->signature[0] == 0x52 &&
202 p->signature[1] == 0x54 &&
203 p->signature[2] == 0x4B &&
204 p->signature[3] == 0x07;
205 }
206
207 static
rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_6ghz_sp ** policy)208 int rtw89_acpi_dsm_get_policy_6ghz_sp(struct rtw89_dev *rtwdev,
209 union acpi_object *obj,
210 struct rtw89_acpi_policy_6ghz_sp **policy)
211 {
212 const struct rtw89_acpi_policy_6ghz_sp *ptr;
213 u32 buf_len;
214
215 if (obj->type != ACPI_TYPE_BUFFER) {
216 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
217 "acpi: expect buffer but type: %d\n", obj->type);
218 return -EINVAL;
219 }
220
221 buf_len = obj->buffer.length;
222 if (buf_len < sizeof(*ptr)) {
223 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
224 __func__, buf_len);
225 return -EINVAL;
226 }
227
228 ptr = (typeof(ptr))obj->buffer.pointer;
229 if (!chk_acpi_policy_6ghz_sp_sig(ptr)) {
230 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
231 return -EINVAL;
232 }
233
234 *policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
235 if (!*policy)
236 return -ENOMEM;
237
238 rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz_sp: ", *policy,
239 sizeof(*ptr));
240 return 0;
241 }
242
chk_acpi_policy_6ghz_vlp_sig(const struct rtw89_acpi_policy_6ghz_vlp * p)243 static bool chk_acpi_policy_6ghz_vlp_sig(const struct rtw89_acpi_policy_6ghz_vlp *p)
244 {
245 return p->signature[0] == 0x52 &&
246 p->signature[1] == 0x54 &&
247 p->signature[2] == 0x4B &&
248 p->signature[3] == 0x0B;
249 }
250
251 static
rtw89_acpi_dsm_get_policy_6ghz_vlp(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_6ghz_vlp ** policy)252 int rtw89_acpi_dsm_get_policy_6ghz_vlp(struct rtw89_dev *rtwdev,
253 union acpi_object *obj,
254 struct rtw89_acpi_policy_6ghz_vlp **policy)
255 {
256 const struct rtw89_acpi_policy_6ghz_vlp *ptr;
257 u32 buf_len;
258
259 if (obj->type != ACPI_TYPE_BUFFER) {
260 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
261 "acpi: expect buffer but type: %d\n", obj->type);
262 return -EINVAL;
263 }
264
265 buf_len = obj->buffer.length;
266 if (buf_len < sizeof(*ptr)) {
267 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
268 __func__, buf_len);
269 return -EINVAL;
270 }
271
272 ptr = (typeof(ptr))obj->buffer.pointer;
273 if (!chk_acpi_policy_6ghz_vlp_sig(ptr)) {
274 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
275 return -EINVAL;
276 }
277
278 *policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
279 if (!*policy)
280 return -ENOMEM;
281
282 rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz_vlp: ", *policy,
283 sizeof(*ptr));
284 return 0;
285 }
286
chk_acpi_policy_tas_sig(const struct rtw89_acpi_policy_tas * p)287 static bool chk_acpi_policy_tas_sig(const struct rtw89_acpi_policy_tas *p)
288 {
289 return p->signature[0] == 0x52 &&
290 p->signature[1] == 0x54 &&
291 p->signature[2] == 0x4B &&
292 p->signature[3] == 0x05;
293 }
294
rtw89_acpi_dsm_get_policy_tas(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_tas ** policy)295 static int rtw89_acpi_dsm_get_policy_tas(struct rtw89_dev *rtwdev,
296 union acpi_object *obj,
297 struct rtw89_acpi_policy_tas **policy)
298 {
299 const struct rtw89_acpi_policy_tas *ptr;
300 u32 buf_len;
301
302 if (obj->type != ACPI_TYPE_BUFFER) {
303 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
304 "acpi: expect buffer but type: %d\n", obj->type);
305 return -EINVAL;
306 }
307
308 buf_len = obj->buffer.length;
309 if (buf_len < sizeof(*ptr)) {
310 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
311 __func__, buf_len);
312 return -EINVAL;
313 }
314
315 ptr = (typeof(ptr))obj->buffer.pointer;
316 if (!chk_acpi_policy_tas_sig(ptr)) {
317 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
318 return -EINVAL;
319 }
320
321 *policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
322 if (!*policy)
323 return -ENOMEM;
324
325 rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_tas: ", *policy,
326 sizeof(*ptr));
327 return 0;
328 }
329
330 static
chk_acpi_policy_reg_rules_sig(const struct rtw89_acpi_policy_reg_rules * p)331 bool chk_acpi_policy_reg_rules_sig(const struct rtw89_acpi_policy_reg_rules *p)
332 {
333 return p->signature[0] == 0x52 &&
334 p->signature[1] == 0x54 &&
335 p->signature[2] == 0x4B &&
336 p->signature[3] == 0x0A;
337 }
338
339 static
rtw89_acpi_dsm_get_policy_reg_rules(struct rtw89_dev * rtwdev,union acpi_object * obj,struct rtw89_acpi_policy_reg_rules ** policy)340 int rtw89_acpi_dsm_get_policy_reg_rules(struct rtw89_dev *rtwdev,
341 union acpi_object *obj,
342 struct rtw89_acpi_policy_reg_rules **policy)
343 {
344 const struct rtw89_acpi_policy_reg_rules *ptr;
345 u32 buf_len;
346
347 if (obj->type != ACPI_TYPE_BUFFER) {
348 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
349 "acpi: expect buffer but type: %d\n", obj->type);
350 return -EINVAL;
351 }
352
353 buf_len = obj->buffer.length;
354 if (buf_len < sizeof(*ptr)) {
355 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
356 __func__, buf_len);
357 return -EINVAL;
358 }
359
360 ptr = (typeof(ptr))obj->buffer.pointer;
361 if (!chk_acpi_policy_reg_rules_sig(ptr)) {
362 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__);
363 return -EINVAL;
364 }
365
366 *policy = kmemdup(ptr, sizeof(*ptr), GFP_KERNEL);
367 if (!*policy)
368 return -ENOMEM;
369
370 rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_reg_rules: ", *policy,
371 sizeof(*ptr));
372 return 0;
373 }
374
rtw89_acpi_evaluate_dsm(struct rtw89_dev * rtwdev,enum rtw89_acpi_dsm_func func,struct rtw89_acpi_dsm_result * res)375 int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
376 enum rtw89_acpi_dsm_func func,
377 struct rtw89_acpi_dsm_result *res)
378 {
379 union acpi_object *obj;
380 int ret;
381
382 obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid,
383 0, func, NULL);
384 if (!obj) {
385 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
386 "acpi dsm fail to evaluate func: %d\n", func);
387 return -ENOENT;
388 }
389
390 if (func == RTW89_ACPI_DSM_FUNC_6G_BP)
391 ret = rtw89_acpi_dsm_get_policy_6ghz(rtwdev, obj,
392 &res->u.policy_6ghz);
393 else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP)
394 ret = rtw89_acpi_dsm_get_policy_6ghz_sp(rtwdev, obj,
395 &res->u.policy_6ghz_sp);
396 else if (func == RTW89_ACPI_DSM_FUNC_6GHZ_VLP_SUP)
397 ret = rtw89_acpi_dsm_get_policy_6ghz_vlp(rtwdev, obj,
398 &res->u.policy_6ghz_vlp);
399 else if (func == RTW89_ACPI_DSM_FUNC_TAS_EN)
400 ret = rtw89_acpi_dsm_get_policy_tas(rtwdev, obj, &res->u.policy_tas);
401 else if (func == RTW89_ACPI_DSM_FUNC_REG_RULES_EN)
402 ret = rtw89_acpi_dsm_get_policy_reg_rules(rtwdev, obj,
403 &res->u.policy_reg_rules);
404 else
405 ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value);
406
407 ACPI_FREE(obj);
408 return ret;
409 }
410
rtw89_acpi_evaluate_rtag(struct rtw89_dev * rtwdev,struct rtw89_acpi_rtag_result * res)411 int rtw89_acpi_evaluate_rtag(struct rtw89_dev *rtwdev,
412 struct rtw89_acpi_rtag_result *res)
413 {
414 #if defined(__linux__)
415 const struct rtw89_acpi_data *data;
416 #elif defined(__FreeBSD__)
417 struct rtw89_acpi_data *data;
418 #endif
419 u32 buf_len;
420 int ret = 0;
421
422 data = rtw89_acpi_evaluate_method(rtwdev, "RTAG");
423 if (!data)
424 return -EIO;
425
426 buf_len = data->len;
427 if (buf_len != sizeof(*res)) {
428 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
429 __func__, buf_len);
430 ret = -EINVAL;
431 goto out;
432 }
433
434 *res = *(struct rtw89_acpi_rtag_result *)data->buf;
435
436 rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "antenna_gain: ", res, sizeof(*res));
437
438 out:
439 kfree(data);
440 return ret;
441 }
442
rtw89_acpi_sar_get_subband(struct rtw89_dev * rtwdev,u32 center_freq)443 enum rtw89_acpi_sar_subband rtw89_acpi_sar_get_subband(struct rtw89_dev *rtwdev,
444 u32 center_freq)
445 {
446 switch (center_freq) {
447 default:
448 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
449 "center freq %u to ACPI SAR subband is unhandled\n",
450 center_freq);
451 fallthrough;
452 case 2412 ... 2484:
453 return RTW89_ACPI_SAR_2GHZ_SUBBAND;
454 case 5180 ... 5240:
455 return RTW89_ACPI_SAR_5GHZ_SUBBAND_1;
456 case 5250 ... 5320:
457 return RTW89_ACPI_SAR_5GHZ_SUBBAND_2;
458 case 5500 ... 5720:
459 return RTW89_ACPI_SAR_5GHZ_SUBBAND_2E;
460 case 5745 ... 5885:
461 return RTW89_ACPI_SAR_5GHZ_SUBBAND_3_4;
462 case 5955 ... 6155:
463 return RTW89_ACPI_SAR_6GHZ_SUBBAND_5_L;
464 case 6175 ... 6415:
465 return RTW89_ACPI_SAR_6GHZ_SUBBAND_5_H;
466 case 6435 ... 6515:
467 return RTW89_ACPI_SAR_6GHZ_SUBBAND_6;
468 case 6535 ... 6695:
469 return RTW89_ACPI_SAR_6GHZ_SUBBAND_7_L;
470 case 6715 ... 6855:
471 return RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H;
472
473 /* freq 6875 (ch 185, 20MHz) spans RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H
474 * and RTW89_ACPI_SAR_6GHZ_SUBBAND_8, so directly describe it with
475 * struct rtw89_6ghz_span.
476 */
477
478 case 6895 ... 7115:
479 return RTW89_ACPI_SAR_6GHZ_SUBBAND_8;
480 }
481 }
482
rtw89_acpi_sar_subband_to_band(struct rtw89_dev * rtwdev,enum rtw89_acpi_sar_subband subband)483 enum rtw89_band rtw89_acpi_sar_subband_to_band(struct rtw89_dev *rtwdev,
484 enum rtw89_acpi_sar_subband subband)
485 {
486 switch (subband) {
487 default:
488 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
489 "ACPI SAR subband %u to band is unhandled\n", subband);
490 fallthrough;
491 case RTW89_ACPI_SAR_2GHZ_SUBBAND:
492 return RTW89_BAND_2G;
493 case RTW89_ACPI_SAR_5GHZ_SUBBAND_1:
494 return RTW89_BAND_5G;
495 case RTW89_ACPI_SAR_5GHZ_SUBBAND_2:
496 return RTW89_BAND_5G;
497 case RTW89_ACPI_SAR_5GHZ_SUBBAND_2E:
498 return RTW89_BAND_5G;
499 case RTW89_ACPI_SAR_5GHZ_SUBBAND_3_4:
500 return RTW89_BAND_5G;
501 case RTW89_ACPI_SAR_6GHZ_SUBBAND_5_L:
502 return RTW89_BAND_6G;
503 case RTW89_ACPI_SAR_6GHZ_SUBBAND_5_H:
504 return RTW89_BAND_6G;
505 case RTW89_ACPI_SAR_6GHZ_SUBBAND_6:
506 return RTW89_BAND_6G;
507 case RTW89_ACPI_SAR_6GHZ_SUBBAND_7_L:
508 return RTW89_BAND_6G;
509 case RTW89_ACPI_SAR_6GHZ_SUBBAND_7_H:
510 return RTW89_BAND_6G;
511 case RTW89_ACPI_SAR_6GHZ_SUBBAND_8:
512 return RTW89_BAND_6G;
513 }
514 }
515
rtw89_acpi_sar_rfpath_to_hp_antidx(enum rtw89_rf_path rfpath)516 static u8 rtw89_acpi_sar_rfpath_to_hp_antidx(enum rtw89_rf_path rfpath)
517 {
518 switch (rfpath) {
519 default:
520 case RF_PATH_B:
521 return 0;
522 case RF_PATH_A:
523 return 1;
524 }
525 }
526
rtw89_acpi_sar_rfpath_to_rt_antidx(enum rtw89_rf_path rfpath)527 static u8 rtw89_acpi_sar_rfpath_to_rt_antidx(enum rtw89_rf_path rfpath)
528 {
529 switch (rfpath) {
530 default:
531 case RF_PATH_A:
532 return 0;
533 case RF_PATH_B:
534 return 1;
535 }
536 }
537
rtw89_acpi_sar_normalize_hp_val(u8 v)538 static s16 rtw89_acpi_sar_normalize_hp_val(u8 v)
539 {
540 static const u8 bias = 10;
541 static const u8 fct = 1;
542 u16 res;
543
544 BUILD_BUG_ON(fct > TXPWR_FACTOR_OF_RTW89_ACPI_SAR);
545
546 res = (bias << TXPWR_FACTOR_OF_RTW89_ACPI_SAR) +
547 (v << (TXPWR_FACTOR_OF_RTW89_ACPI_SAR - fct));
548
549 return min_t(s32, res, MAX_VAL_OF_RTW89_ACPI_SAR);
550 }
551
rtw89_acpi_sar_normalize_rt_val(u8 v)552 static s16 rtw89_acpi_sar_normalize_rt_val(u8 v)
553 {
554 static const u8 fct = 3;
555 u16 res;
556
557 BUILD_BUG_ON(fct > TXPWR_FACTOR_OF_RTW89_ACPI_SAR);
558
559 res = v << (TXPWR_FACTOR_OF_RTW89_ACPI_SAR - fct);
560
561 return min_t(s32, res, MAX_VAL_OF_RTW89_ACPI_SAR);
562 }
563
564 static
rtw89_acpi_sar_load_std_legacy(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_recognition * rec,const void * content,struct rtw89_sar_entry_from_acpi * ent)565 void rtw89_acpi_sar_load_std_legacy(struct rtw89_dev *rtwdev,
566 const struct rtw89_acpi_sar_recognition *rec,
567 const void *content,
568 struct rtw89_sar_entry_from_acpi *ent)
569 {
570 const struct rtw89_acpi_sar_std_legacy *ptr = content;
571 enum rtw89_acpi_sar_subband subband;
572 enum rtw89_rf_path path;
573
574 for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
575 for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
576 u8 antidx = rec->rfpath_to_antidx(path);
577
578 if (subband < RTW89_ACPI_SAR_SUBBAND_NR_LEGACY)
579 ent->v[subband][path] =
580 rec->normalize(ptr->v[antidx][subband]);
581 else
582 ent->v[subband][path] = MAX_VAL_OF_RTW89_ACPI_SAR;
583 }
584 }
585 }
586
587 static
rtw89_acpi_sar_load_std_has_6ghz(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_recognition * rec,const void * content,struct rtw89_sar_entry_from_acpi * ent)588 void rtw89_acpi_sar_load_std_has_6ghz(struct rtw89_dev *rtwdev,
589 const struct rtw89_acpi_sar_recognition *rec,
590 const void *content,
591 struct rtw89_sar_entry_from_acpi *ent)
592 {
593 const struct rtw89_acpi_sar_std_has_6ghz *ptr = content;
594 enum rtw89_acpi_sar_subband subband;
595 enum rtw89_rf_path path;
596
597 BUILD_BUG_ON(RTW89_ACPI_SAR_SUBBAND_NR_HAS_6GHZ != NUM_OF_RTW89_ACPI_SAR_SUBBAND);
598
599 for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
600 for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
601 u8 antidx = rec->rfpath_to_antidx(path);
602
603 ent->v[subband][path] = rec->normalize(ptr->v[antidx][subband]);
604 }
605 }
606 }
607
608 static
rtw89_acpi_sar_load_sml_legacy(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_recognition * rec,const void * content,struct rtw89_sar_entry_from_acpi * ent)609 void rtw89_acpi_sar_load_sml_legacy(struct rtw89_dev *rtwdev,
610 const struct rtw89_acpi_sar_recognition *rec,
611 const void *content,
612 struct rtw89_sar_entry_from_acpi *ent)
613 {
614 const struct rtw89_acpi_sar_sml_legacy *ptr = content;
615 enum rtw89_acpi_sar_subband subband;
616 enum rtw89_rf_path path;
617
618 for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
619 for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
620 u8 antidx = rec->rfpath_to_antidx(path);
621
622 if (subband < RTW89_ACPI_SAR_SUBBAND_NR_LEGACY)
623 ent->v[subband][path] =
624 rec->normalize(ptr->v[antidx][subband]);
625 else
626 ent->v[subband][path] = MAX_VAL_OF_RTW89_ACPI_SAR;
627 }
628 }
629 }
630
631 static
rtw89_acpi_sar_load_sml_has_6ghz(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_recognition * rec,const void * content,struct rtw89_sar_entry_from_acpi * ent)632 void rtw89_acpi_sar_load_sml_has_6ghz(struct rtw89_dev *rtwdev,
633 const struct rtw89_acpi_sar_recognition *rec,
634 const void *content,
635 struct rtw89_sar_entry_from_acpi *ent)
636 {
637 const struct rtw89_acpi_sar_sml_has_6ghz *ptr = content;
638 enum rtw89_acpi_sar_subband subband;
639 enum rtw89_rf_path path;
640
641 BUILD_BUG_ON(RTW89_ACPI_SAR_SUBBAND_NR_HAS_6GHZ != NUM_OF_RTW89_ACPI_SAR_SUBBAND);
642
643 for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
644 for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
645 u8 antidx = rec->rfpath_to_antidx(path);
646
647 ent->v[subband][path] = rec->normalize(ptr->v[antidx][subband]);
648 }
649 }
650 }
651
rtw89_acpi_geo_sar_normalize_delta(s8 delta)652 static s16 rtw89_acpi_geo_sar_normalize_delta(s8 delta)
653 {
654 static const u8 fct = 1;
655
656 BUILD_BUG_ON(fct > TXPWR_FACTOR_OF_RTW89_ACPI_SAR);
657
658 return delta << (TXPWR_FACTOR_OF_RTW89_ACPI_SAR - fct);
659 }
660
661 static enum rtw89_acpi_geo_sar_regd_hp
rtw89_acpi_geo_sar_regd_convert_hp_idx(enum rtw89_regulation_type regd)662 rtw89_acpi_geo_sar_regd_convert_hp_idx(enum rtw89_regulation_type regd)
663 {
664 switch (regd) {
665 case RTW89_FCC:
666 case RTW89_IC:
667 case RTW89_NCC:
668 case RTW89_CHILE:
669 case RTW89_MEXICO:
670 return RTW89_ACPI_GEO_SAR_REGD_HP_FCC;
671 case RTW89_ETSI:
672 case RTW89_MKK:
673 case RTW89_ACMA:
674 return RTW89_ACPI_GEO_SAR_REGD_HP_ETSI;
675 default:
676 case RTW89_WW:
677 case RTW89_NA:
678 case RTW89_KCC:
679 return RTW89_ACPI_GEO_SAR_REGD_HP_WW;
680 }
681 }
682
683 static enum rtw89_acpi_geo_sar_regd_rt
rtw89_acpi_geo_sar_regd_convert_rt_idx(enum rtw89_regulation_type regd)684 rtw89_acpi_geo_sar_regd_convert_rt_idx(enum rtw89_regulation_type regd)
685 {
686 switch (regd) {
687 case RTW89_FCC:
688 case RTW89_NCC:
689 case RTW89_CHILE:
690 case RTW89_MEXICO:
691 return RTW89_ACPI_GEO_SAR_REGD_RT_FCC;
692 case RTW89_ETSI:
693 case RTW89_ACMA:
694 return RTW89_ACPI_GEO_SAR_REGD_RT_ETSI;
695 case RTW89_MKK:
696 return RTW89_ACPI_GEO_SAR_REGD_RT_MKK;
697 case RTW89_IC:
698 return RTW89_ACPI_GEO_SAR_REGD_RT_IC;
699 case RTW89_KCC:
700 return RTW89_ACPI_GEO_SAR_REGD_RT_KCC;
701 default:
702 case RTW89_WW:
703 case RTW89_NA:
704 return RTW89_ACPI_GEO_SAR_REGD_RT_WW;
705 }
706 }
707
708 static
rtw89_acpi_geo_sar_load_by_hp(struct rtw89_dev * rtwdev,const struct rtw89_acpi_geo_sar_hp_val * ptr,enum rtw89_rf_path path,s16 * val)709 void rtw89_acpi_geo_sar_load_by_hp(struct rtw89_dev *rtwdev,
710 const struct rtw89_acpi_geo_sar_hp_val *ptr,
711 enum rtw89_rf_path path, s16 *val)
712 {
713 u8 antidx = rtw89_acpi_sar_rfpath_to_hp_antidx(path);
714 s16 delta = rtw89_acpi_geo_sar_normalize_delta(ptr->delta[antidx]);
715 s16 max = rtw89_acpi_sar_normalize_hp_val(ptr->max);
716
717 *val = clamp_t(s32, (*val) + delta, MIN_VAL_OF_RTW89_ACPI_SAR, max);
718 }
719
720 static
rtw89_acpi_geo_sar_load_by_rt(struct rtw89_dev * rtwdev,const struct rtw89_acpi_geo_sar_rt_val * ptr,s16 * val)721 void rtw89_acpi_geo_sar_load_by_rt(struct rtw89_dev *rtwdev,
722 const struct rtw89_acpi_geo_sar_rt_val *ptr,
723 s16 *val)
724 {
725 s16 delta = rtw89_acpi_geo_sar_normalize_delta(ptr->delta);
726 s16 max = rtw89_acpi_sar_normalize_rt_val(ptr->max);
727
728 *val = clamp_t(s32, (*val) + delta, MIN_VAL_OF_RTW89_ACPI_SAR, max);
729 }
730
731 static
rtw89_acpi_geo_sar_load_hp_legacy(struct rtw89_dev * rtwdev,const void * content,enum rtw89_regulation_type regd,struct rtw89_sar_entry_from_acpi * ent)732 void rtw89_acpi_geo_sar_load_hp_legacy(struct rtw89_dev *rtwdev,
733 const void *content,
734 enum rtw89_regulation_type regd,
735 struct rtw89_sar_entry_from_acpi *ent)
736 {
737 const struct rtw89_acpi_geo_sar_hp_legacy *ptr = content;
738 const struct rtw89_acpi_geo_sar_hp_legacy_entry *ptr_ent;
739 const struct rtw89_acpi_geo_sar_hp_val *ptr_ent_val;
740 enum rtw89_acpi_geo_sar_regd_hp geo_idx =
741 rtw89_acpi_geo_sar_regd_convert_hp_idx(regd);
742 enum rtw89_acpi_sar_subband subband;
743 enum rtw89_rf_path path;
744 enum rtw89_band band;
745
746 ptr_ent = &ptr->entries[geo_idx];
747
748 for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
749 band = rtw89_acpi_sar_subband_to_band(rtwdev, subband);
750 switch (band) {
751 case RTW89_BAND_2G:
752 ptr_ent_val = &ptr_ent->val_2ghz;
753 break;
754 case RTW89_BAND_5G:
755 ptr_ent_val = &ptr_ent->val_5ghz;
756 break;
757 default:
758 case RTW89_BAND_6G:
759 ptr_ent_val = NULL;
760 break;
761 }
762
763 if (!ptr_ent_val)
764 continue;
765
766 for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++)
767 rtw89_acpi_geo_sar_load_by_hp(rtwdev, ptr_ent_val, path,
768 &ent->v[subband][path]);
769 }
770 }
771
772 static
rtw89_acpi_geo_sar_load_hp_has_6ghz(struct rtw89_dev * rtwdev,const void * content,enum rtw89_regulation_type regd,struct rtw89_sar_entry_from_acpi * ent)773 void rtw89_acpi_geo_sar_load_hp_has_6ghz(struct rtw89_dev *rtwdev,
774 const void *content,
775 enum rtw89_regulation_type regd,
776 struct rtw89_sar_entry_from_acpi *ent)
777 {
778 const struct rtw89_acpi_geo_sar_hp_has_6ghz *ptr = content;
779 const struct rtw89_acpi_geo_sar_hp_has_6ghz_entry *ptr_ent;
780 const struct rtw89_acpi_geo_sar_hp_val *ptr_ent_val;
781 enum rtw89_acpi_geo_sar_regd_hp geo_idx =
782 rtw89_acpi_geo_sar_regd_convert_hp_idx(regd);
783 enum rtw89_acpi_sar_subband subband;
784 enum rtw89_rf_path path;
785 enum rtw89_band band;
786
787 ptr_ent = &ptr->entries[geo_idx];
788
789 for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
790 band = rtw89_acpi_sar_subband_to_band(rtwdev, subband);
791 switch (band) {
792 case RTW89_BAND_2G:
793 ptr_ent_val = &ptr_ent->val_2ghz;
794 break;
795 case RTW89_BAND_5G:
796 ptr_ent_val = &ptr_ent->val_5ghz;
797 break;
798 case RTW89_BAND_6G:
799 ptr_ent_val = &ptr_ent->val_6ghz;
800 break;
801 default:
802 ptr_ent_val = NULL;
803 break;
804 }
805
806 if (!ptr_ent_val)
807 continue;
808
809 for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++)
810 rtw89_acpi_geo_sar_load_by_hp(rtwdev, ptr_ent_val, path,
811 &ent->v[subband][path]);
812 }
813 }
814
815 static
rtw89_acpi_geo_sar_load_rt_legacy(struct rtw89_dev * rtwdev,const void * content,enum rtw89_regulation_type regd,struct rtw89_sar_entry_from_acpi * ent)816 void rtw89_acpi_geo_sar_load_rt_legacy(struct rtw89_dev *rtwdev,
817 const void *content,
818 enum rtw89_regulation_type regd,
819 struct rtw89_sar_entry_from_acpi *ent)
820 {
821 const struct rtw89_acpi_geo_sar_rt_legacy *ptr = content;
822 const struct rtw89_acpi_geo_sar_rt_legacy_entry *ptr_ent;
823 const struct rtw89_acpi_geo_sar_rt_val *ptr_ent_val;
824 enum rtw89_acpi_geo_sar_regd_rt geo_idx =
825 rtw89_acpi_geo_sar_regd_convert_rt_idx(regd);
826 enum rtw89_acpi_sar_subband subband;
827 enum rtw89_rf_path path;
828 enum rtw89_band band;
829
830 ptr_ent = &ptr->entries[geo_idx];
831
832 for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
833 band = rtw89_acpi_sar_subband_to_band(rtwdev, subband);
834 switch (band) {
835 case RTW89_BAND_2G:
836 ptr_ent_val = &ptr_ent->val_2ghz;
837 break;
838 case RTW89_BAND_5G:
839 ptr_ent_val = &ptr_ent->val_5ghz;
840 break;
841 default:
842 case RTW89_BAND_6G:
843 ptr_ent_val = NULL;
844 break;
845 }
846
847 if (!ptr_ent_val)
848 continue;
849
850 for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++)
851 rtw89_acpi_geo_sar_load_by_rt(rtwdev, ptr_ent_val,
852 &ent->v[subband][path]);
853 }
854 }
855
856 static
rtw89_acpi_geo_sar_load_rt_has_6ghz(struct rtw89_dev * rtwdev,const void * content,enum rtw89_regulation_type regd,struct rtw89_sar_entry_from_acpi * ent)857 void rtw89_acpi_geo_sar_load_rt_has_6ghz(struct rtw89_dev *rtwdev,
858 const void *content,
859 enum rtw89_regulation_type regd,
860 struct rtw89_sar_entry_from_acpi *ent)
861 {
862 const struct rtw89_acpi_geo_sar_rt_has_6ghz *ptr = content;
863 const struct rtw89_acpi_geo_sar_rt_has_6ghz_entry *ptr_ent;
864 const struct rtw89_acpi_geo_sar_rt_val *ptr_ent_val;
865 enum rtw89_acpi_geo_sar_regd_rt geo_idx =
866 rtw89_acpi_geo_sar_regd_convert_rt_idx(regd);
867 enum rtw89_acpi_sar_subband subband;
868 enum rtw89_rf_path path;
869 enum rtw89_band band;
870
871 ptr_ent = &ptr->entries[geo_idx];
872
873 for (subband = 0; subband < NUM_OF_RTW89_ACPI_SAR_SUBBAND; subband++) {
874 band = rtw89_acpi_sar_subband_to_band(rtwdev, subband);
875 switch (band) {
876 case RTW89_BAND_2G:
877 ptr_ent_val = &ptr_ent->val_2ghz;
878 break;
879 case RTW89_BAND_5G:
880 ptr_ent_val = &ptr_ent->val_5ghz;
881 break;
882 case RTW89_BAND_6G:
883 ptr_ent_val = &ptr_ent->val_6ghz;
884 break;
885 default:
886 ptr_ent_val = NULL;
887 break;
888 }
889
890 if (!ptr_ent_val)
891 continue;
892
893 for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++)
894 rtw89_acpi_geo_sar_load_by_rt(rtwdev, ptr_ent_val,
895 &ent->v[subband][path]);
896 }
897 }
898
899 #define RTW89_ACPI_GEO_SAR_DECL_HANDLER(type) \
900 static const struct rtw89_acpi_geo_sar_handler \
901 rtw89_acpi_geo_sar_handler_ ## type = { \
902 .data_size = RTW89_ACPI_GEO_SAR_SIZE_OF(type), \
903 .load = rtw89_acpi_geo_sar_load_ ## type, \
904 }
905
906 RTW89_ACPI_GEO_SAR_DECL_HANDLER(hp_legacy);
907 RTW89_ACPI_GEO_SAR_DECL_HANDLER(hp_has_6ghz);
908 RTW89_ACPI_GEO_SAR_DECL_HANDLER(rt_legacy);
909 RTW89_ACPI_GEO_SAR_DECL_HANDLER(rt_has_6ghz);
910
911 static const struct rtw89_acpi_sar_recognition rtw89_acpi_sar_recs[] = {
912 {
913 .id = {
914 .cid = RTW89_ACPI_SAR_CID_HP,
915 .rev = RTW89_ACPI_SAR_REV_LEGACY,
916 .size = RTW89_ACPI_SAR_SIZE_OF(std_legacy),
917 },
918 .geo = &rtw89_acpi_geo_sar_handler_hp_legacy,
919
920 .rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_hp_antidx,
921 .normalize = rtw89_acpi_sar_normalize_hp_val,
922 .load = rtw89_acpi_sar_load_std_legacy,
923 },
924 {
925 .id = {
926 .cid = RTW89_ACPI_SAR_CID_HP,
927 .rev = RTW89_ACPI_SAR_REV_HAS_6GHZ,
928 .size = RTW89_ACPI_SAR_SIZE_OF(std_has_6ghz),
929 },
930 .geo = &rtw89_acpi_geo_sar_handler_hp_has_6ghz,
931
932 .rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_hp_antidx,
933 .normalize = rtw89_acpi_sar_normalize_hp_val,
934 .load = rtw89_acpi_sar_load_std_has_6ghz,
935 },
936 {
937 .id = {
938 .cid = RTW89_ACPI_SAR_CID_RT,
939 .rev = RTW89_ACPI_SAR_REV_LEGACY,
940 .size = RTW89_ACPI_SAR_SIZE_OF(std_legacy),
941 },
942 .geo = &rtw89_acpi_geo_sar_handler_rt_legacy,
943
944 .rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_rt_antidx,
945 .normalize = rtw89_acpi_sar_normalize_rt_val,
946 .load = rtw89_acpi_sar_load_std_legacy,
947 },
948 {
949 .id = {
950 .cid = RTW89_ACPI_SAR_CID_RT,
951 .rev = RTW89_ACPI_SAR_REV_HAS_6GHZ,
952 .size = RTW89_ACPI_SAR_SIZE_OF(std_has_6ghz),
953 },
954 .geo = &rtw89_acpi_geo_sar_handler_rt_has_6ghz,
955
956 .rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_rt_antidx,
957 .normalize = rtw89_acpi_sar_normalize_rt_val,
958 .load = rtw89_acpi_sar_load_std_has_6ghz,
959 },
960 {
961 .id = {
962 .cid = RTW89_ACPI_SAR_CID_RT,
963 .rev = RTW89_ACPI_SAR_REV_LEGACY,
964 .size = RTW89_ACPI_SAR_SIZE_OF(sml_legacy),
965 },
966 .geo = &rtw89_acpi_geo_sar_handler_rt_legacy,
967
968 .rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_rt_antidx,
969 .normalize = rtw89_acpi_sar_normalize_rt_val,
970 .load = rtw89_acpi_sar_load_sml_legacy,
971 },
972 {
973 .id = {
974 .cid = RTW89_ACPI_SAR_CID_RT,
975 .rev = RTW89_ACPI_SAR_REV_HAS_6GHZ,
976 .size = RTW89_ACPI_SAR_SIZE_OF(sml_has_6ghz),
977 },
978 .geo = &rtw89_acpi_geo_sar_handler_rt_has_6ghz,
979
980 .rfpath_to_antidx = rtw89_acpi_sar_rfpath_to_rt_antidx,
981 .normalize = rtw89_acpi_sar_normalize_rt_val,
982 .load = rtw89_acpi_sar_load_sml_has_6ghz,
983 },
984 };
985
986 struct rtw89_acpi_sar_rec_parm {
987 u32 pld_len;
988 u8 tbl_cnt;
989 u16 cid;
990 u8 rev;
991 };
992
993 static const struct rtw89_acpi_sar_recognition *
rtw89_acpi_sar_recognize(struct rtw89_dev * rtwdev,const struct rtw89_acpi_sar_rec_parm * parm)994 rtw89_acpi_sar_recognize(struct rtw89_dev *rtwdev,
995 const struct rtw89_acpi_sar_rec_parm *parm)
996 {
997 const u32 tbl_len = parm->pld_len / parm->tbl_cnt;
998 const struct rtw89_acpi_sar_recognition *rec;
999 struct rtw89_acpi_sar_identifier id = {};
1000
1001 rtw89_debug(rtwdev, RTW89_DBG_ACPI,
1002 "%s: cid %u, rev %u, tbl len %u, tbl cnt %u\n",
1003 __func__, parm->cid, parm->rev, tbl_len, parm->tbl_cnt);
1004
1005 if (unlikely(parm->pld_len % parm->tbl_cnt)) {
1006 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid pld len %u\n",
1007 parm->pld_len);
1008 return NULL;
1009 }
1010
1011 if (unlikely(tbl_len > RTW89_ACPI_SAR_SIZE_MAX)) {
1012 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid tbl len %u\n",
1013 tbl_len);
1014 return NULL;
1015 }
1016
1017 if (unlikely(parm->tbl_cnt > MAX_NUM_OF_RTW89_ACPI_SAR_TBL)) {
1018 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid tbl cnt %u\n",
1019 parm->tbl_cnt);
1020 return NULL;
1021 }
1022
1023 switch (parm->cid) {
1024 case RTW89_ACPI_SAR_CID_HP:
1025 case RTW89_ACPI_SAR_CID_RT:
1026 id.cid = parm->cid;
1027 break;
1028 default:
1029 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid cid 0x%x\n",
1030 parm->cid);
1031 return NULL;
1032 }
1033
1034 switch (parm->rev) {
1035 case RTW89_ACPI_SAR_REV_LEGACY:
1036 case RTW89_ACPI_SAR_REV_HAS_6GHZ:
1037 id.rev = parm->rev;
1038 break;
1039 default:
1040 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid rev %u\n",
1041 parm->rev);
1042 return NULL;
1043 }
1044
1045 id.size = tbl_len;
1046 for (unsigned int i = 0; i < ARRAY_SIZE(rtw89_acpi_sar_recs); i++) {
1047 rec = &rtw89_acpi_sar_recs[i];
1048 if (memcmp(&rec->id, &id, sizeof(rec->id)) == 0)
1049 return rec;
1050 }
1051
1052 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "failed to recognize\n");
1053 return NULL;
1054 }
1055
1056 static const struct rtw89_acpi_sar_recognition *
rtw89_acpi_evaluate_static_sar(struct rtw89_dev * rtwdev,struct rtw89_sar_cfg_acpi * cfg)1057 rtw89_acpi_evaluate_static_sar(struct rtw89_dev *rtwdev,
1058 struct rtw89_sar_cfg_acpi *cfg)
1059 {
1060 const struct rtw89_acpi_sar_recognition *rec = NULL;
1061 const struct rtw89_acpi_static_sar_hdr *hdr;
1062 struct rtw89_sar_entry_from_acpi tmp = {};
1063 struct rtw89_acpi_sar_rec_parm parm = {};
1064 struct rtw89_sar_table_from_acpi *tbl;
1065 const struct rtw89_acpi_data *data;
1066 u32 len;
1067
1068 data = rtw89_acpi_evaluate_method(rtwdev, RTW89_ACPI_METHOD_STATIC_SAR);
1069 if (!data)
1070 return NULL;
1071
1072 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi load static sar\n");
1073
1074 len = data->len;
1075 if (len <= sizeof(*hdr)) {
1076 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid buf len %u\n", len);
1077 goto out;
1078 }
1079
1080 hdr = (typeof(hdr))data->buf;
1081
1082 parm.cid = le16_to_cpu(hdr->cid);
1083 parm.rev = hdr->rev;
1084 parm.tbl_cnt = 1;
1085 parm.pld_len = len - sizeof(*hdr);
1086
1087 rec = rtw89_acpi_sar_recognize(rtwdev, &parm);
1088 if (!rec)
1089 goto out;
1090
1091 rec->load(rtwdev, rec, hdr->content, &tmp);
1092
1093 tbl = &cfg->tables[0];
1094 for (u8 regd = 0; regd < RTW89_REGD_NUM; regd++)
1095 tbl->entries[regd] = tmp;
1096
1097 cfg->valid_num = 1;
1098
1099 out:
1100 kfree(data);
1101 return rec;
1102 }
1103
1104 static const struct rtw89_acpi_sar_recognition *
rtw89_acpi_evaluate_dynamic_sar(struct rtw89_dev * rtwdev,struct rtw89_sar_cfg_acpi * cfg)1105 rtw89_acpi_evaluate_dynamic_sar(struct rtw89_dev *rtwdev,
1106 struct rtw89_sar_cfg_acpi *cfg)
1107 {
1108 const struct rtw89_acpi_sar_recognition *rec = NULL;
1109 const struct rtw89_acpi_dynamic_sar_hdr *hdr;
1110 struct rtw89_acpi_sar_rec_parm parm = {};
1111 struct rtw89_sar_table_from_acpi *tbl;
1112 const struct rtw89_acpi_data *data;
1113 u32 len;
1114
1115 data = rtw89_acpi_evaluate_method(rtwdev, RTW89_ACPI_METHOD_DYNAMIC_SAR);
1116 if (!data)
1117 return NULL;
1118
1119 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi load dynamic sar\n");
1120
1121 len = data->len;
1122 if (len <= sizeof(*hdr)) {
1123 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid buf len %u\n", len);
1124 goto out;
1125 }
1126
1127 hdr = (typeof(hdr))data->buf;
1128
1129 parm.cid = le16_to_cpu(hdr->cid);
1130 parm.rev = hdr->rev;
1131 parm.tbl_cnt = hdr->cnt;
1132 parm.pld_len = len - sizeof(*hdr);
1133
1134 rec = rtw89_acpi_sar_recognize(rtwdev, &parm);
1135 if (!rec)
1136 goto out;
1137
1138 for (unsigned int i = 0; i < hdr->cnt; i++) {
1139 const u8 *content = hdr->content + rec->id.size * i;
1140 struct rtw89_sar_entry_from_acpi tmp = {};
1141
1142 rec->load(rtwdev, rec, content, &tmp);
1143
1144 tbl = &cfg->tables[i];
1145 for (u8 regd = 0; regd < RTW89_REGD_NUM; regd++)
1146 tbl->entries[regd] = tmp;
1147 }
1148
1149 cfg->valid_num = hdr->cnt;
1150
1151 out:
1152 kfree(data);
1153 return rec;
1154 }
1155
rtw89_acpi_evaluate_dynamic_sar_indicator(struct rtw89_dev * rtwdev,struct rtw89_sar_cfg_acpi * cfg,bool * poll_changed)1156 int rtw89_acpi_evaluate_dynamic_sar_indicator(struct rtw89_dev *rtwdev,
1157 struct rtw89_sar_cfg_acpi *cfg,
1158 bool *poll_changed)
1159 {
1160 struct rtw89_sar_indicator_from_acpi *ind = &cfg->indicator;
1161 struct rtw89_sar_indicator_from_acpi tmp = *ind;
1162 const struct rtw89_acpi_data *data;
1163 const u8 *tbl_base1_by_ant;
1164 enum rtw89_rf_path path;
1165 int ret = 0;
1166 u32 len;
1167
1168 data = rtw89_acpi_evaluate_method(rtwdev, RTW89_ACPI_METHOD_DYNAMIC_SAR_INDICATOR);
1169 if (!data)
1170 return -EFAULT;
1171
1172 if (!poll_changed)
1173 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi load dynamic sar indicator\n");
1174
1175 len = data->len;
1176 if (len != ind->fields) {
1177 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid buf len %u\n", len);
1178 ret = -EINVAL;
1179 goto out;
1180 }
1181
1182 tbl_base1_by_ant = data->buf;
1183
1184 for (path = 0; path < NUM_OF_RTW89_ACPI_SAR_RF_PATH; path++) {
1185 u8 antidx = ind->rfpath_to_antidx(path);
1186 u8 sel;
1187
1188 if (antidx >= ind->fields)
1189 antidx = 0;
1190
1191 /* convert the table index from 1-based to 0-based */
1192 sel = tbl_base1_by_ant[antidx] - 1;
1193 if (sel >= cfg->valid_num)
1194 sel = 0;
1195
1196 tmp.tblsel[path] = sel;
1197 }
1198
1199 if (memcmp(ind, &tmp, sizeof(*ind)) == 0) {
1200 if (poll_changed)
1201 *poll_changed = false;
1202 } else {
1203 if (poll_changed)
1204 *poll_changed = true;
1205
1206 *ind = tmp;
1207 }
1208
1209 out:
1210 kfree(data);
1211 return ret;
1212 }
1213
1214 static
rtw89_acpi_evaluate_geo_sar(struct rtw89_dev * rtwdev,const struct rtw89_acpi_geo_sar_handler * hdl,struct rtw89_sar_cfg_acpi * cfg)1215 void rtw89_acpi_evaluate_geo_sar(struct rtw89_dev *rtwdev,
1216 const struct rtw89_acpi_geo_sar_handler *hdl,
1217 struct rtw89_sar_cfg_acpi *cfg)
1218 {
1219 const struct rtw89_acpi_data *data;
1220 u32 len;
1221
1222 data = rtw89_acpi_evaluate_method(rtwdev, RTW89_ACPI_METHOD_GEO_SAR);
1223 if (!data)
1224 return;
1225
1226 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi load geo sar\n");
1227
1228 len = data->len;
1229 if (len != hdl->data_size) {
1230 rtw89_debug(rtwdev, RTW89_DBG_ACPI, "invalid buf len %u (expected %u)\n",
1231 len, hdl->data_size);
1232 goto out;
1233 }
1234
1235 for (unsigned int i = 0; i < cfg->valid_num; i++)
1236 for (u8 regd = 0; regd < RTW89_REGD_NUM; regd++)
1237 hdl->load(rtwdev, data->buf, regd, &cfg->tables[i].entries[regd]);
1238
1239 out:
1240 kfree(data);
1241 }
1242
rtw89_acpi_evaluate_sar(struct rtw89_dev * rtwdev,struct rtw89_sar_cfg_acpi * cfg)1243 int rtw89_acpi_evaluate_sar(struct rtw89_dev *rtwdev,
1244 struct rtw89_sar_cfg_acpi *cfg)
1245 {
1246 struct rtw89_sar_indicator_from_acpi *ind = &cfg->indicator;
1247 const struct rtw89_acpi_sar_recognition *rec;
1248 bool fetch_indicator = false;
1249 int ret;
1250
1251 rec = rtw89_acpi_evaluate_static_sar(rtwdev, cfg);
1252 if (rec)
1253 goto recognized;
1254
1255 rec = rtw89_acpi_evaluate_dynamic_sar(rtwdev, cfg);
1256 if (!rec)
1257 return -ENOENT;
1258
1259 fetch_indicator = true;
1260
1261 recognized:
1262 rtw89_acpi_evaluate_geo_sar(rtwdev, rec->geo, cfg);
1263
1264 switch (rec->id.cid) {
1265 case RTW89_ACPI_SAR_CID_HP:
1266 cfg->downgrade_2tx = 3 << TXPWR_FACTOR_OF_RTW89_ACPI_SAR;
1267 ind->fields = RTW89_ACPI_SAR_ANT_NR_STD;
1268 break;
1269 case RTW89_ACPI_SAR_CID_RT:
1270 cfg->downgrade_2tx = 0;
1271 ind->fields = 1;
1272 break;
1273 default:
1274 return -EFAULT;
1275 }
1276
1277 if (fetch_indicator) {
1278 ind->rfpath_to_antidx = rec->rfpath_to_antidx;
1279 ret = rtw89_acpi_evaluate_dynamic_sar_indicator(rtwdev, cfg, NULL);
1280 if (ret)
1281 fetch_indicator = false;
1282 }
1283
1284 if (!fetch_indicator)
1285 memset(ind->tblsel, 0, sizeof(ind->tblsel));
1286
1287 ind->enable_sync = fetch_indicator;
1288 return 0;
1289 }
1290