1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2019-2020 Realtek Corporation 3 */ 4 5 #include "acpi.h" 6 #include "debug.h" 7 #include "phy.h" 8 #include "reg.h" 9 #include "sar.h" 10 11 #define RTW89_TAS_FACTOR 2 /* unit: 0.25 dBm */ 12 #define RTW89_TAS_DPR_GAP (1 << RTW89_TAS_FACTOR) 13 #define RTW89_TAS_DELTA (2 << RTW89_TAS_FACTOR) 14 15 static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev, 16 u32 center_freq) 17 { 18 switch (center_freq) { 19 default: 20 rtw89_debug(rtwdev, RTW89_DBG_SAR, 21 "center freq: %u to SAR subband is unhandled\n", 22 center_freq); 23 fallthrough; 24 case 2412 ... 2484: 25 return RTW89_SAR_2GHZ_SUBBAND; 26 case 5180 ... 5320: 27 return RTW89_SAR_5GHZ_SUBBAND_1_2; 28 case 5500 ... 5720: 29 return RTW89_SAR_5GHZ_SUBBAND_2_E; 30 case 5745 ... 5825: 31 return RTW89_SAR_5GHZ_SUBBAND_3; 32 case 5955 ... 6155: 33 return RTW89_SAR_6GHZ_SUBBAND_5_L; 34 case 6175 ... 6415: 35 return RTW89_SAR_6GHZ_SUBBAND_5_H; 36 case 6435 ... 6515: 37 return RTW89_SAR_6GHZ_SUBBAND_6; 38 case 6535 ... 6695: 39 return RTW89_SAR_6GHZ_SUBBAND_7_L; 40 case 6715 ... 6855: 41 return RTW89_SAR_6GHZ_SUBBAND_7_H; 42 43 /* freq 6875 (ch 185, 20MHz) spans RTW89_SAR_6GHZ_SUBBAND_7_H 44 * and RTW89_SAR_6GHZ_SUBBAND_8, so directly describe it with 45 * struct rtw89_sar_span in the following. 46 */ 47 48 case 6895 ... 7115: 49 return RTW89_SAR_6GHZ_SUBBAND_8; 50 } 51 } 52 53 struct rtw89_sar_span { 54 enum rtw89_sar_subband subband_low; 55 enum rtw89_sar_subband subband_high; 56 }; 57 58 #define RTW89_SAR_SPAN_VALID(span) ((span)->subband_high) 59 60 #define RTW89_SAR_6GHZ_SPAN_HEAD 6145 61 #define RTW89_SAR_6GHZ_SPAN_IDX(center_freq) \ 62 ((((int)(center_freq) - RTW89_SAR_6GHZ_SPAN_HEAD) / 5) / 2) 63 64 #define RTW89_DECL_SAR_6GHZ_SPAN(center_freq, subband_l, subband_h) \ 65 [RTW89_SAR_6GHZ_SPAN_IDX(center_freq)] = { \ 66 .subband_low = RTW89_SAR_6GHZ_ ## subband_l, \ 67 .subband_high = RTW89_SAR_6GHZ_ ## subband_h, \ 68 } 69 70 /* Since 6GHz SAR subbands are not edge aligned, some cases span two SAR 71 * subbands. In the following, we describe each of them with rtw89_sar_span. 72 */ 73 static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = { 74 RTW89_DECL_SAR_6GHZ_SPAN(6145, SUBBAND_5_L, SUBBAND_5_H), 75 RTW89_DECL_SAR_6GHZ_SPAN(6165, SUBBAND_5_L, SUBBAND_5_H), 76 RTW89_DECL_SAR_6GHZ_SPAN(6185, SUBBAND_5_L, SUBBAND_5_H), 77 RTW89_DECL_SAR_6GHZ_SPAN(6505, SUBBAND_6, SUBBAND_7_L), 78 RTW89_DECL_SAR_6GHZ_SPAN(6525, SUBBAND_6, SUBBAND_7_L), 79 RTW89_DECL_SAR_6GHZ_SPAN(6545, SUBBAND_6, SUBBAND_7_L), 80 RTW89_DECL_SAR_6GHZ_SPAN(6665, SUBBAND_7_L, SUBBAND_7_H), 81 RTW89_DECL_SAR_6GHZ_SPAN(6705, SUBBAND_7_L, SUBBAND_7_H), 82 RTW89_DECL_SAR_6GHZ_SPAN(6825, SUBBAND_7_H, SUBBAND_8), 83 RTW89_DECL_SAR_6GHZ_SPAN(6865, SUBBAND_7_H, SUBBAND_8), 84 RTW89_DECL_SAR_6GHZ_SPAN(6875, SUBBAND_7_H, SUBBAND_8), 85 RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8), 86 }; 87 88 static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, 89 u32 center_freq, s32 *cfg) 90 { 91 struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common; 92 const struct rtw89_sar_span *span = NULL; 93 enum rtw89_sar_subband subband_l, subband_h; 94 int idx; 95 96 if (center_freq >= RTW89_SAR_6GHZ_SPAN_HEAD) { 97 idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq); 98 /* To decrease size of rtw89_sar_overlapping_6ghz[], 99 * RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs 100 * to make first span as index 0 of the table. So, if center 101 * frequency is less than the first one, it will get netative. 102 */ 103 if (idx >= 0 && idx < ARRAY_SIZE(rtw89_sar_overlapping_6ghz)) 104 span = &rtw89_sar_overlapping_6ghz[idx]; 105 } 106 107 if (span && RTW89_SAR_SPAN_VALID(span)) { 108 subband_l = span->subband_low; 109 subband_h = span->subband_high; 110 } else { 111 subband_l = rtw89_sar_get_subband(rtwdev, center_freq); 112 subband_h = subband_l; 113 } 114 115 rtw89_debug(rtwdev, RTW89_DBG_SAR, 116 "center_freq %u: SAR subband {%u, %u}\n", 117 center_freq, subband_l, subband_h); 118 119 if (!rtwsar->set[subband_l] && !rtwsar->set[subband_h]) 120 return -ENODATA; 121 122 if (!rtwsar->set[subband_l]) 123 *cfg = rtwsar->cfg[subband_h]; 124 else if (!rtwsar->set[subband_h]) 125 *cfg = rtwsar->cfg[subband_l]; 126 else 127 *cfg = min(rtwsar->cfg[subband_l], rtwsar->cfg[subband_h]); 128 129 return 0; 130 } 131 132 static const 133 struct rtw89_sar_handler rtw89_sar_handlers[RTW89_SAR_SOURCE_NR] = { 134 [RTW89_SAR_SOURCE_COMMON] = { 135 .descr_sar_source = "RTW89_SAR_SOURCE_COMMON", 136 .txpwr_factor_sar = 2, 137 .query_sar_config = rtw89_query_sar_config_common, 138 }, 139 }; 140 141 #define rtw89_sar_set_src(_dev, _src, _cfg_name, _cfg_data) \ 142 do { \ 143 typeof(_src) _s = (_src); \ 144 typeof(_dev) _d = (_dev); \ 145 BUILD_BUG_ON(!rtw89_sar_handlers[_s].descr_sar_source); \ 146 BUILD_BUG_ON(!rtw89_sar_handlers[_s].query_sar_config); \ 147 lockdep_assert_held(&_d->mutex); \ 148 _d->sar._cfg_name = *(_cfg_data); \ 149 _d->sar.src = _s; \ 150 } while (0) 151 152 static s8 rtw89_txpwr_sar_to_mac(struct rtw89_dev *rtwdev, u8 fct, s32 cfg) 153 { 154 const u8 fct_mac = rtwdev->chip->txpwr_factor_mac; 155 s32 cfg_mac; 156 157 cfg_mac = fct > fct_mac ? 158 cfg >> (fct - fct_mac) : cfg << (fct_mac - fct); 159 160 return (s8)clamp_t(s32, cfg_mac, 161 RTW89_SAR_TXPWR_MAC_MIN, 162 RTW89_SAR_TXPWR_MAC_MAX); 163 } 164 165 static s8 rtw89_txpwr_tas_to_sar(const struct rtw89_sar_handler *sar_hdl, 166 s8 cfg) 167 { 168 const u8 fct = sar_hdl->txpwr_factor_sar; 169 170 if (fct > RTW89_TAS_FACTOR) 171 return cfg << (fct - RTW89_TAS_FACTOR); 172 else 173 return cfg >> (RTW89_TAS_FACTOR - fct); 174 } 175 176 static s8 rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler *sar_hdl, 177 s8 cfg) 178 { 179 const u8 fct = sar_hdl->txpwr_factor_sar; 180 181 if (fct > RTW89_TAS_FACTOR) 182 return cfg >> (fct - RTW89_TAS_FACTOR); 183 else 184 return cfg << (RTW89_TAS_FACTOR - fct); 185 } 186 187 s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq) 188 { 189 const enum rtw89_sar_sources src = rtwdev->sar.src; 190 /* its members are protected by rtw89_sar_set_src() */ 191 const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src]; 192 struct rtw89_tas_info *tas = &rtwdev->tas; 193 s8 delta; 194 int ret; 195 s32 cfg; 196 u8 fct; 197 198 lockdep_assert_held(&rtwdev->mutex); 199 200 if (src == RTW89_SAR_SOURCE_NONE) 201 return RTW89_SAR_TXPWR_MAC_MAX; 202 203 ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg); 204 if (ret) 205 return RTW89_SAR_TXPWR_MAC_MAX; 206 207 if (tas->enable) { 208 switch (tas->state) { 209 case RTW89_TAS_STATE_DPR_OFF: 210 return RTW89_SAR_TXPWR_MAC_MAX; 211 case RTW89_TAS_STATE_DPR_ON: 212 delta = rtw89_txpwr_tas_to_sar(sar_hdl, tas->delta); 213 cfg -= delta; 214 break; 215 case RTW89_TAS_STATE_DPR_FORBID: 216 default: 217 break; 218 } 219 } 220 221 fct = sar_hdl->txpwr_factor_sar; 222 223 return rtw89_txpwr_sar_to_mac(rtwdev, fct, cfg); 224 } 225 226 void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev, u32 center_freq) 227 { 228 const enum rtw89_sar_sources src = rtwdev->sar.src; 229 /* its members are protected by rtw89_sar_set_src() */ 230 const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src]; 231 const u8 fct_mac = rtwdev->chip->txpwr_factor_mac; 232 int ret; 233 s32 cfg; 234 u8 fct; 235 236 lockdep_assert_held(&rtwdev->mutex); 237 238 if (src == RTW89_SAR_SOURCE_NONE) { 239 seq_puts(m, "no SAR is applied\n"); 240 return; 241 } 242 243 seq_printf(m, "source: %d (%s)\n", src, sar_hdl->descr_sar_source); 244 245 ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg); 246 if (ret) { 247 seq_printf(m, "config: return code: %d\n", ret); 248 seq_printf(m, "assign: max setting: %d (unit: 1/%lu dBm)\n", 249 RTW89_SAR_TXPWR_MAC_MAX, BIT(fct_mac)); 250 return; 251 } 252 253 fct = sar_hdl->txpwr_factor_sar; 254 255 seq_printf(m, "config: %d (unit: 1/%lu dBm)\n", cfg, BIT(fct)); 256 } 257 258 void rtw89_print_tas(struct seq_file *m, struct rtw89_dev *rtwdev) 259 { 260 struct rtw89_tas_info *tas = &rtwdev->tas; 261 262 if (!tas->enable) { 263 seq_puts(m, "no TAS is applied\n"); 264 return; 265 } 266 267 seq_printf(m, "DPR gap: %d\n", tas->dpr_gap); 268 seq_printf(m, "TAS delta: %d\n", tas->delta); 269 } 270 271 static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev, 272 const struct rtw89_sar_cfg_common *sar) 273 { 274 enum rtw89_sar_sources src; 275 int ret = 0; 276 277 mutex_lock(&rtwdev->mutex); 278 279 src = rtwdev->sar.src; 280 if (src != RTW89_SAR_SOURCE_NONE && src != RTW89_SAR_SOURCE_COMMON) { 281 rtw89_warn(rtwdev, "SAR source: %d is in use", src); 282 ret = -EBUSY; 283 goto exit; 284 } 285 286 rtw89_sar_set_src(rtwdev, RTW89_SAR_SOURCE_COMMON, cfg_common, sar); 287 rtw89_core_set_chip_txpwr(rtwdev); 288 289 exit: 290 mutex_unlock(&rtwdev->mutex); 291 return ret; 292 } 293 294 static const struct cfg80211_sar_freq_ranges rtw89_common_sar_freq_ranges[] = { 295 { .start_freq = 2412, .end_freq = 2484, }, 296 { .start_freq = 5180, .end_freq = 5320, }, 297 { .start_freq = 5500, .end_freq = 5720, }, 298 { .start_freq = 5745, .end_freq = 5825, }, 299 { .start_freq = 5955, .end_freq = 6155, }, 300 { .start_freq = 6175, .end_freq = 6415, }, 301 { .start_freq = 6435, .end_freq = 6515, }, 302 { .start_freq = 6535, .end_freq = 6695, }, 303 { .start_freq = 6715, .end_freq = 6875, }, 304 { .start_freq = 6875, .end_freq = 7115, }, 305 }; 306 307 #if defined(__linux__) 308 static_assert(RTW89_SAR_SUBBAND_NR == 309 #elif defined(__FreeBSD__) 310 rtw89_static_assert(RTW89_SAR_SUBBAND_NR == 311 #endif 312 ARRAY_SIZE(rtw89_common_sar_freq_ranges)); 313 314 const struct cfg80211_sar_capa rtw89_sar_capa = { 315 .type = NL80211_SAR_TYPE_POWER, 316 .num_freq_ranges = ARRAY_SIZE(rtw89_common_sar_freq_ranges), 317 .freq_ranges = rtw89_common_sar_freq_ranges, 318 }; 319 320 int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw, 321 const struct cfg80211_sar_specs *sar) 322 { 323 struct rtw89_dev *rtwdev = hw->priv; 324 struct rtw89_sar_cfg_common sar_common = {0}; 325 u8 fct; 326 u32 freq_start; 327 u32 freq_end; 328 s32 power; 329 u32 i, idx; 330 331 if (sar->type != NL80211_SAR_TYPE_POWER) 332 return -EINVAL; 333 334 fct = rtw89_sar_handlers[RTW89_SAR_SOURCE_COMMON].txpwr_factor_sar; 335 336 for (i = 0; i < sar->num_sub_specs; i++) { 337 idx = sar->sub_specs[i].freq_range_index; 338 if (idx >= ARRAY_SIZE(rtw89_common_sar_freq_ranges)) 339 return -EINVAL; 340 341 freq_start = rtw89_common_sar_freq_ranges[idx].start_freq; 342 freq_end = rtw89_common_sar_freq_ranges[idx].end_freq; 343 power = sar->sub_specs[i].power; 344 345 rtw89_debug(rtwdev, RTW89_DBG_SAR, 346 "On freq %u to %u, set SAR limit %d (unit: 1/%lu dBm)\n", 347 freq_start, freq_end, power, BIT(fct)); 348 349 sar_common.set[idx] = true; 350 sar_common.cfg[idx] = power; 351 } 352 353 return rtw89_apply_sar_common(rtwdev, &sar_common); 354 } 355 356 static void rtw89_tas_state_update(struct rtw89_dev *rtwdev) 357 { 358 const enum rtw89_sar_sources src = rtwdev->sar.src; 359 /* its members are protected by rtw89_sar_set_src() */ 360 const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src]; 361 struct rtw89_tas_info *tas = &rtwdev->tas; 362 s32 txpwr_avg = tas->total_txpwr / RTW89_TAS_MAX_WINDOW / PERCENT; 363 s32 dpr_on_threshold, dpr_off_threshold, cfg; 364 enum rtw89_tas_state state = tas->state; 365 const struct rtw89_chan *chan; 366 int ret; 367 368 lockdep_assert_held(&rtwdev->mutex); 369 370 if (src == RTW89_SAR_SOURCE_NONE) 371 return; 372 373 chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); 374 ret = sar_hdl->query_sar_config(rtwdev, chan->freq, &cfg); 375 if (ret) 376 return; 377 378 cfg = rtw89_txpwr_sar_to_tas(sar_hdl, cfg); 379 380 if (tas->delta >= cfg) { 381 rtw89_debug(rtwdev, RTW89_DBG_SAR, 382 "TAS delta exceed SAR limit\n"); 383 state = RTW89_TAS_STATE_DPR_FORBID; 384 goto out; 385 } 386 387 dpr_on_threshold = cfg; 388 dpr_off_threshold = cfg - tas->dpr_gap; 389 rtw89_debug(rtwdev, RTW89_DBG_SAR, 390 "DPR_ON thold: %d, DPR_OFF thold: %d, txpwr_avg: %d\n", 391 dpr_on_threshold, dpr_off_threshold, txpwr_avg); 392 393 if (txpwr_avg >= dpr_on_threshold) 394 state = RTW89_TAS_STATE_DPR_ON; 395 else if (txpwr_avg < dpr_off_threshold) 396 state = RTW89_TAS_STATE_DPR_OFF; 397 398 out: 399 if (tas->state == state) 400 return; 401 402 rtw89_debug(rtwdev, RTW89_DBG_SAR, 403 "TAS old state: %d, new state: %d\n", tas->state, state); 404 tas->state = state; 405 rtw89_core_set_chip_txpwr(rtwdev); 406 } 407 408 void rtw89_tas_init(struct rtw89_dev *rtwdev) 409 { 410 struct rtw89_tas_info *tas = &rtwdev->tas; 411 struct rtw89_acpi_dsm_result res = {}; 412 int ret; 413 u8 val; 414 415 ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_TAS_EN, &res); 416 if (ret) { 417 rtw89_debug(rtwdev, RTW89_DBG_SAR, 418 "acpi: cannot get TAS: %d\n", ret); 419 return; 420 } 421 422 val = res.u.value; 423 switch (val) { 424 case 0: 425 tas->enable = false; 426 break; 427 case 1: 428 tas->enable = true; 429 break; 430 default: 431 break; 432 } 433 434 if (!tas->enable) { 435 rtw89_debug(rtwdev, RTW89_DBG_SAR, "TAS not enable\n"); 436 return; 437 } 438 439 tas->dpr_gap = RTW89_TAS_DPR_GAP; 440 tas->delta = RTW89_TAS_DELTA; 441 } 442 443 void rtw89_tas_reset(struct rtw89_dev *rtwdev) 444 { 445 struct rtw89_tas_info *tas = &rtwdev->tas; 446 447 if (!tas->enable) 448 return; 449 450 memset(&tas->txpwr_history, 0, sizeof(tas->txpwr_history)); 451 tas->total_txpwr = 0; 452 tas->cur_idx = 0; 453 tas->state = RTW89_TAS_STATE_DPR_OFF; 454 } 455 456 static const struct rtw89_reg_def txpwr_regs[] = { 457 {R_PATH0_TXPWR, B_PATH0_TXPWR}, 458 {R_PATH1_TXPWR, B_PATH1_TXPWR}, 459 }; 460 461 void rtw89_tas_track(struct rtw89_dev *rtwdev) 462 { 463 struct rtw89_env_monitor_info *env = &rtwdev->env_monitor; 464 const enum rtw89_sar_sources src = rtwdev->sar.src; 465 u8 max_nss_num = rtwdev->chip->rf_path_num; 466 struct rtw89_tas_info *tas = &rtwdev->tas; 467 s16 tmp, txpwr, instant_txpwr = 0; 468 u32 val; 469 int i; 470 471 if (!tas->enable || src == RTW89_SAR_SOURCE_NONE) 472 return; 473 474 if (env->ccx_watchdog_result != RTW89_PHY_ENV_MON_IFS_CLM) 475 return; 476 477 for (i = 0; i < max_nss_num; i++) { 478 val = rtw89_phy_read32_mask(rtwdev, txpwr_regs[i].addr, 479 txpwr_regs[i].mask); 480 tmp = sign_extend32(val, 8); 481 if (tmp <= 0) 482 return; 483 instant_txpwr += tmp; 484 } 485 486 instant_txpwr /= max_nss_num; 487 /* in unit of 0.25 dBm multiply by percentage */ 488 txpwr = instant_txpwr * env->ifs_clm_tx_ratio; 489 tas->total_txpwr += txpwr - tas->txpwr_history[tas->cur_idx]; 490 tas->txpwr_history[tas->cur_idx] = txpwr; 491 rtw89_debug(rtwdev, RTW89_DBG_SAR, 492 "instant_txpwr: %d, tx_ratio: %d, txpwr: %d\n", 493 instant_txpwr, env->ifs_clm_tx_ratio, txpwr); 494 495 tas->cur_idx = (tas->cur_idx + 1) % RTW89_TAS_MAX_WINDOW; 496 497 rtw89_tas_state_update(rtwdev); 498 } 499