Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/rtw89/acpi.c
105585 views
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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 *
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
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
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
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
1291