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