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