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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 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 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 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