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 ... 5885: 31 return RTW89_SAR_5GHZ_SUBBAND_3_4; 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_6ghz_span. 46 */ 47 48 case 6895 ... 7115: 49 return RTW89_SAR_6GHZ_SUBBAND_8; 50 } 51 } 52 53 static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, 54 u32 center_freq, s32 *cfg) 55 { 56 struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common; 57 enum rtw89_sar_subband subband_l, subband_h; 58 const struct rtw89_6ghz_span *span; 59 60 span = rtw89_get_6ghz_span(rtwdev, center_freq); 61 62 if (span && RTW89_SAR_SPAN_VALID(span)) { 63 subband_l = span->sar_subband_low; 64 subband_h = span->sar_subband_high; 65 } else { 66 subband_l = rtw89_sar_get_subband(rtwdev, center_freq); 67 subband_h = subband_l; 68 } 69 70 rtw89_debug(rtwdev, RTW89_DBG_SAR, 71 "center_freq %u: SAR subband {%u, %u}\n", 72 center_freq, subband_l, subband_h); 73 74 if (!rtwsar->set[subband_l] && !rtwsar->set[subband_h]) 75 return -ENODATA; 76 77 if (!rtwsar->set[subband_l]) 78 *cfg = rtwsar->cfg[subband_h]; 79 else if (!rtwsar->set[subband_h]) 80 *cfg = rtwsar->cfg[subband_l]; 81 else 82 *cfg = min(rtwsar->cfg[subband_l], rtwsar->cfg[subband_h]); 83 84 return 0; 85 } 86 87 static const 88 struct rtw89_sar_handler rtw89_sar_handlers[RTW89_SAR_SOURCE_NR] = { 89 [RTW89_SAR_SOURCE_COMMON] = { 90 .descr_sar_source = "RTW89_SAR_SOURCE_COMMON", 91 .txpwr_factor_sar = 2, 92 .query_sar_config = rtw89_query_sar_config_common, 93 }, 94 }; 95 96 #define rtw89_sar_set_src(_dev, _src, _cfg_name, _cfg_data) \ 97 do { \ 98 typeof(_src) _s = (_src); \ 99 typeof(_dev) _d = (_dev); \ 100 BUILD_BUG_ON(!rtw89_sar_handlers[_s].descr_sar_source); \ 101 BUILD_BUG_ON(!rtw89_sar_handlers[_s].query_sar_config); \ 102 lockdep_assert_wiphy(_d->hw->wiphy); \ 103 _d->sar._cfg_name = *(_cfg_data); \ 104 _d->sar.src = _s; \ 105 } while (0) 106 107 static s8 rtw89_txpwr_sar_to_mac(struct rtw89_dev *rtwdev, u8 fct, s32 cfg) 108 { 109 const u8 fct_mac = rtwdev->chip->txpwr_factor_mac; 110 s32 cfg_mac; 111 112 cfg_mac = fct > fct_mac ? 113 cfg >> (fct - fct_mac) : cfg << (fct_mac - fct); 114 115 return (s8)clamp_t(s32, cfg_mac, 116 RTW89_SAR_TXPWR_MAC_MIN, 117 RTW89_SAR_TXPWR_MAC_MAX); 118 } 119 120 static s8 rtw89_txpwr_tas_to_sar(const struct rtw89_sar_handler *sar_hdl, 121 s8 cfg) 122 { 123 const u8 fct = sar_hdl->txpwr_factor_sar; 124 125 if (fct > RTW89_TAS_FACTOR) 126 return cfg << (fct - RTW89_TAS_FACTOR); 127 else 128 return cfg >> (RTW89_TAS_FACTOR - fct); 129 } 130 131 static s8 rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler *sar_hdl, 132 s8 cfg) 133 { 134 const u8 fct = sar_hdl->txpwr_factor_sar; 135 136 if (fct > RTW89_TAS_FACTOR) 137 return cfg >> (fct - RTW89_TAS_FACTOR); 138 else 139 return cfg << (RTW89_TAS_FACTOR - fct); 140 } 141 142 s8 rtw89_query_sar(struct rtw89_dev *rtwdev, u32 center_freq) 143 { 144 const enum rtw89_sar_sources src = rtwdev->sar.src; 145 /* its members are protected by rtw89_sar_set_src() */ 146 const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src]; 147 struct rtw89_tas_info *tas = &rtwdev->tas; 148 s8 delta; 149 int ret; 150 s32 cfg; 151 u8 fct; 152 153 lockdep_assert_wiphy(rtwdev->hw->wiphy); 154 155 if (src == RTW89_SAR_SOURCE_NONE) 156 return RTW89_SAR_TXPWR_MAC_MAX; 157 158 ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg); 159 if (ret) 160 return RTW89_SAR_TXPWR_MAC_MAX; 161 162 if (tas->enable) { 163 switch (tas->state) { 164 case RTW89_TAS_STATE_DPR_OFF: 165 return RTW89_SAR_TXPWR_MAC_MAX; 166 case RTW89_TAS_STATE_DPR_ON: 167 delta = rtw89_txpwr_tas_to_sar(sar_hdl, tas->delta); 168 cfg -= delta; 169 break; 170 case RTW89_TAS_STATE_DPR_FORBID: 171 default: 172 break; 173 } 174 } 175 176 fct = sar_hdl->txpwr_factor_sar; 177 178 return rtw89_txpwr_sar_to_mac(rtwdev, fct, cfg); 179 } 180 181 int rtw89_print_sar(struct rtw89_dev *rtwdev, char *buf, size_t bufsz, 182 u32 center_freq) 183 { 184 const enum rtw89_sar_sources src = rtwdev->sar.src; 185 /* its members are protected by rtw89_sar_set_src() */ 186 const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src]; 187 const u8 fct_mac = rtwdev->chip->txpwr_factor_mac; 188 char *p = buf, *end = buf + bufsz; 189 int ret; 190 s32 cfg; 191 u8 fct; 192 193 lockdep_assert_wiphy(rtwdev->hw->wiphy); 194 195 if (src == RTW89_SAR_SOURCE_NONE) { 196 p += scnprintf(p, end - p, "no SAR is applied\n"); 197 goto out; 198 } 199 200 p += scnprintf(p, end - p, "source: %d (%s)\n", src, 201 sar_hdl->descr_sar_source); 202 203 ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg); 204 if (ret) { 205 p += scnprintf(p, end - p, "config: return code: %d\n", ret); 206 p += scnprintf(p, end - p, 207 "assign: max setting: %d (unit: 1/%lu dBm)\n", 208 RTW89_SAR_TXPWR_MAC_MAX, BIT(fct_mac)); 209 goto out; 210 } 211 212 fct = sar_hdl->txpwr_factor_sar; 213 214 p += scnprintf(p, end - p, "config: %d (unit: 1/%lu dBm)\n", cfg, 215 BIT(fct)); 216 217 out: 218 return p - buf; 219 } 220 221 int rtw89_print_tas(struct rtw89_dev *rtwdev, char *buf, size_t bufsz) 222 { 223 struct rtw89_tas_info *tas = &rtwdev->tas; 224 char *p = buf, *end = buf + bufsz; 225 226 if (!tas->enable) { 227 p += scnprintf(p, end - p, "no TAS is applied\n"); 228 goto out; 229 } 230 231 p += scnprintf(p, end - p, "DPR gap: %d\n", tas->dpr_gap); 232 p += scnprintf(p, end - p, "TAS delta: %d\n", tas->delta); 233 234 out: 235 return p - buf; 236 } 237 238 static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev, 239 const struct rtw89_sar_cfg_common *sar) 240 { 241 enum rtw89_sar_sources src; 242 243 lockdep_assert_wiphy(rtwdev->hw->wiphy); 244 245 src = rtwdev->sar.src; 246 if (src != RTW89_SAR_SOURCE_NONE && src != RTW89_SAR_SOURCE_COMMON) { 247 rtw89_warn(rtwdev, "SAR source: %d is in use", src); 248 return -EBUSY; 249 } 250 251 rtw89_sar_set_src(rtwdev, RTW89_SAR_SOURCE_COMMON, cfg_common, sar); 252 rtw89_core_set_chip_txpwr(rtwdev); 253 254 return 0; 255 } 256 257 static const struct cfg80211_sar_freq_ranges rtw89_common_sar_freq_ranges[] = { 258 { .start_freq = 2412, .end_freq = 2484, }, 259 { .start_freq = 5180, .end_freq = 5320, }, 260 { .start_freq = 5500, .end_freq = 5720, }, 261 { .start_freq = 5745, .end_freq = 5885, }, 262 { .start_freq = 5955, .end_freq = 6155, }, 263 { .start_freq = 6175, .end_freq = 6415, }, 264 { .start_freq = 6435, .end_freq = 6515, }, 265 { .start_freq = 6535, .end_freq = 6695, }, 266 { .start_freq = 6715, .end_freq = 6875, }, 267 { .start_freq = 6875, .end_freq = 7115, }, 268 }; 269 270 static_assert(RTW89_SAR_SUBBAND_NR == 271 ARRAY_SIZE(rtw89_common_sar_freq_ranges)); 272 273 const struct cfg80211_sar_capa rtw89_sar_capa = { 274 .type = NL80211_SAR_TYPE_POWER, 275 .num_freq_ranges = ARRAY_SIZE(rtw89_common_sar_freq_ranges), 276 .freq_ranges = rtw89_common_sar_freq_ranges, 277 }; 278 279 int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw, 280 const struct cfg80211_sar_specs *sar) 281 { 282 struct rtw89_dev *rtwdev = hw->priv; 283 struct rtw89_sar_cfg_common sar_common = {0}; 284 u8 fct; 285 u32 freq_start; 286 u32 freq_end; 287 s32 power; 288 u32 i, idx; 289 290 lockdep_assert_wiphy(rtwdev->hw->wiphy); 291 292 if (sar->type != NL80211_SAR_TYPE_POWER) 293 return -EINVAL; 294 295 fct = rtw89_sar_handlers[RTW89_SAR_SOURCE_COMMON].txpwr_factor_sar; 296 297 for (i = 0; i < sar->num_sub_specs; i++) { 298 idx = sar->sub_specs[i].freq_range_index; 299 if (idx >= ARRAY_SIZE(rtw89_common_sar_freq_ranges)) 300 return -EINVAL; 301 302 freq_start = rtw89_common_sar_freq_ranges[idx].start_freq; 303 freq_end = rtw89_common_sar_freq_ranges[idx].end_freq; 304 power = sar->sub_specs[i].power; 305 306 rtw89_debug(rtwdev, RTW89_DBG_SAR, 307 "On freq %u to %u, set SAR limit %d (unit: 1/%lu dBm)\n", 308 freq_start, freq_end, power, BIT(fct)); 309 310 sar_common.set[idx] = true; 311 sar_common.cfg[idx] = power; 312 } 313 314 return rtw89_apply_sar_common(rtwdev, &sar_common); 315 } 316 317 static void rtw89_tas_state_update(struct rtw89_dev *rtwdev) 318 { 319 const enum rtw89_sar_sources src = rtwdev->sar.src; 320 /* its members are protected by rtw89_sar_set_src() */ 321 const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src]; 322 struct rtw89_tas_info *tas = &rtwdev->tas; 323 s32 txpwr_avg = tas->total_txpwr / RTW89_TAS_MAX_WINDOW / PERCENT; 324 s32 dpr_on_threshold, dpr_off_threshold, cfg; 325 enum rtw89_tas_state state = tas->state; 326 const struct rtw89_chan *chan; 327 int ret; 328 329 lockdep_assert_wiphy(rtwdev->hw->wiphy); 330 331 if (src == RTW89_SAR_SOURCE_NONE) 332 return; 333 334 chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); 335 ret = sar_hdl->query_sar_config(rtwdev, chan->freq, &cfg); 336 if (ret) 337 return; 338 339 cfg = rtw89_txpwr_sar_to_tas(sar_hdl, cfg); 340 341 if (tas->delta >= cfg) { 342 rtw89_debug(rtwdev, RTW89_DBG_SAR, 343 "TAS delta exceed SAR limit\n"); 344 state = RTW89_TAS_STATE_DPR_FORBID; 345 goto out; 346 } 347 348 dpr_on_threshold = cfg; 349 dpr_off_threshold = cfg - tas->dpr_gap; 350 rtw89_debug(rtwdev, RTW89_DBG_SAR, 351 "DPR_ON thold: %d, DPR_OFF thold: %d, txpwr_avg: %d\n", 352 dpr_on_threshold, dpr_off_threshold, txpwr_avg); 353 354 if (txpwr_avg >= dpr_on_threshold) 355 state = RTW89_TAS_STATE_DPR_ON; 356 else if (txpwr_avg < dpr_off_threshold) 357 state = RTW89_TAS_STATE_DPR_OFF; 358 359 out: 360 if (tas->state == state) 361 return; 362 363 rtw89_debug(rtwdev, RTW89_DBG_SAR, 364 "TAS old state: %d, new state: %d\n", tas->state, state); 365 tas->state = state; 366 rtw89_core_set_chip_txpwr(rtwdev); 367 } 368 369 void rtw89_tas_init(struct rtw89_dev *rtwdev) 370 { 371 struct rtw89_tas_info *tas = &rtwdev->tas; 372 struct rtw89_acpi_dsm_result res = {}; 373 int ret; 374 u8 val; 375 376 ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_TAS_EN, &res); 377 if (ret) { 378 rtw89_debug(rtwdev, RTW89_DBG_SAR, 379 "acpi: cannot get TAS: %d\n", ret); 380 return; 381 } 382 383 val = res.u.value; 384 switch (val) { 385 case 0: 386 tas->enable = false; 387 break; 388 case 1: 389 tas->enable = true; 390 break; 391 default: 392 break; 393 } 394 395 if (!tas->enable) { 396 rtw89_debug(rtwdev, RTW89_DBG_SAR, "TAS not enable\n"); 397 return; 398 } 399 400 tas->dpr_gap = RTW89_TAS_DPR_GAP; 401 tas->delta = RTW89_TAS_DELTA; 402 } 403 404 void rtw89_tas_reset(struct rtw89_dev *rtwdev) 405 { 406 struct rtw89_tas_info *tas = &rtwdev->tas; 407 408 if (!tas->enable) 409 return; 410 411 memset(&tas->txpwr_history, 0, sizeof(tas->txpwr_history)); 412 tas->total_txpwr = 0; 413 tas->cur_idx = 0; 414 tas->state = RTW89_TAS_STATE_DPR_OFF; 415 } 416 417 static const struct rtw89_reg_def txpwr_regs[] = { 418 {R_PATH0_TXPWR, B_PATH0_TXPWR}, 419 {R_PATH1_TXPWR, B_PATH1_TXPWR}, 420 }; 421 422 void rtw89_tas_track(struct rtw89_dev *rtwdev) 423 { 424 struct rtw89_bb_ctx *bb = rtw89_get_bb_ctx(rtwdev, RTW89_PHY_0); 425 struct rtw89_env_monitor_info *env = &bb->env_monitor; 426 const enum rtw89_sar_sources src = rtwdev->sar.src; 427 u8 max_nss_num = rtwdev->chip->rf_path_num; 428 struct rtw89_tas_info *tas = &rtwdev->tas; 429 s16 tmp, txpwr, instant_txpwr = 0; 430 u32 val; 431 int i; 432 433 if (!tas->enable || src == RTW89_SAR_SOURCE_NONE) 434 return; 435 436 if (env->ccx_watchdog_result != RTW89_PHY_ENV_MON_IFS_CLM) 437 return; 438 439 for (i = 0; i < max_nss_num; i++) { 440 val = rtw89_phy_read32_mask(rtwdev, txpwr_regs[i].addr, 441 txpwr_regs[i].mask); 442 tmp = sign_extend32(val, 8); 443 if (tmp <= 0) 444 return; 445 instant_txpwr += tmp; 446 } 447 448 instant_txpwr /= max_nss_num; 449 /* in unit of 0.25 dBm multiply by percentage */ 450 txpwr = instant_txpwr * env->ifs_clm_tx_ratio; 451 tas->total_txpwr += txpwr - tas->txpwr_history[tas->cur_idx]; 452 tas->txpwr_history[tas->cur_idx] = txpwr; 453 rtw89_debug(rtwdev, RTW89_DBG_SAR, 454 "instant_txpwr: %d, tx_ratio: %d, txpwr: %d\n", 455 instant_txpwr, env->ifs_clm_tx_ratio, txpwr); 456 457 tas->cur_idx = (tas->cur_idx + 1) % RTW89_TAS_MAX_WINDOW; 458 459 rtw89_tas_state_update(rtwdev); 460 } 461