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