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
rtw89_sar_get_subband(struct rtw89_dev * rtwdev,u32 center_freq)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
rtw89_query_sar_config_common(struct rtw89_dev * rtwdev,u32 center_freq,s32 * cfg)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_held(&_d->mutex); \
103 _d->sar._cfg_name = *(_cfg_data); \
104 _d->sar.src = _s; \
105 } while (0)
106
rtw89_txpwr_sar_to_mac(struct rtw89_dev * rtwdev,u8 fct,s32 cfg)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
rtw89_txpwr_tas_to_sar(const struct rtw89_sar_handler * sar_hdl,s8 cfg)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
rtw89_txpwr_sar_to_tas(const struct rtw89_sar_handler * sar_hdl,s8 cfg)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
rtw89_query_sar(struct rtw89_dev * rtwdev,u32 center_freq)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_held(&rtwdev->mutex);
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
rtw89_print_sar(struct seq_file * m,struct rtw89_dev * rtwdev,u32 center_freq)181 void rtw89_print_sar(struct seq_file *m, struct rtw89_dev *rtwdev, u32 center_freq)
182 {
183 const enum rtw89_sar_sources src = rtwdev->sar.src;
184 /* its members are protected by rtw89_sar_set_src() */
185 const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src];
186 const u8 fct_mac = rtwdev->chip->txpwr_factor_mac;
187 int ret;
188 s32 cfg;
189 u8 fct;
190
191 lockdep_assert_held(&rtwdev->mutex);
192
193 if (src == RTW89_SAR_SOURCE_NONE) {
194 seq_puts(m, "no SAR is applied\n");
195 return;
196 }
197
198 seq_printf(m, "source: %d (%s)\n", src, sar_hdl->descr_sar_source);
199
200 ret = sar_hdl->query_sar_config(rtwdev, center_freq, &cfg);
201 if (ret) {
202 seq_printf(m, "config: return code: %d\n", ret);
203 seq_printf(m, "assign: max setting: %d (unit: 1/%lu dBm)\n",
204 RTW89_SAR_TXPWR_MAC_MAX, BIT(fct_mac));
205 return;
206 }
207
208 fct = sar_hdl->txpwr_factor_sar;
209
210 seq_printf(m, "config: %d (unit: 1/%lu dBm)\n", cfg, BIT(fct));
211 }
212
rtw89_print_tas(struct seq_file * m,struct rtw89_dev * rtwdev)213 void rtw89_print_tas(struct seq_file *m, struct rtw89_dev *rtwdev)
214 {
215 struct rtw89_tas_info *tas = &rtwdev->tas;
216
217 if (!tas->enable) {
218 seq_puts(m, "no TAS is applied\n");
219 return;
220 }
221
222 seq_printf(m, "DPR gap: %d\n", tas->dpr_gap);
223 seq_printf(m, "TAS delta: %d\n", tas->delta);
224 }
225
rtw89_apply_sar_common(struct rtw89_dev * rtwdev,const struct rtw89_sar_cfg_common * sar)226 static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev,
227 const struct rtw89_sar_cfg_common *sar)
228 {
229 enum rtw89_sar_sources src;
230 int ret = 0;
231
232 mutex_lock(&rtwdev->mutex);
233
234 src = rtwdev->sar.src;
235 if (src != RTW89_SAR_SOURCE_NONE && src != RTW89_SAR_SOURCE_COMMON) {
236 rtw89_warn(rtwdev, "SAR source: %d is in use", src);
237 ret = -EBUSY;
238 goto exit;
239 }
240
241 rtw89_sar_set_src(rtwdev, RTW89_SAR_SOURCE_COMMON, cfg_common, sar);
242 rtw89_core_set_chip_txpwr(rtwdev);
243
244 exit:
245 mutex_unlock(&rtwdev->mutex);
246 return ret;
247 }
248
249 static const struct cfg80211_sar_freq_ranges rtw89_common_sar_freq_ranges[] = {
250 { .start_freq = 2412, .end_freq = 2484, },
251 { .start_freq = 5180, .end_freq = 5320, },
252 { .start_freq = 5500, .end_freq = 5720, },
253 { .start_freq = 5745, .end_freq = 5885, },
254 { .start_freq = 5955, .end_freq = 6155, },
255 { .start_freq = 6175, .end_freq = 6415, },
256 { .start_freq = 6435, .end_freq = 6515, },
257 { .start_freq = 6535, .end_freq = 6695, },
258 { .start_freq = 6715, .end_freq = 6875, },
259 { .start_freq = 6875, .end_freq = 7115, },
260 };
261
262 static_assert(RTW89_SAR_SUBBAND_NR ==
263 ARRAY_SIZE(rtw89_common_sar_freq_ranges));
264
265 const struct cfg80211_sar_capa rtw89_sar_capa = {
266 .type = NL80211_SAR_TYPE_POWER,
267 .num_freq_ranges = ARRAY_SIZE(rtw89_common_sar_freq_ranges),
268 .freq_ranges = rtw89_common_sar_freq_ranges,
269 };
270
rtw89_ops_set_sar_specs(struct ieee80211_hw * hw,const struct cfg80211_sar_specs * sar)271 int rtw89_ops_set_sar_specs(struct ieee80211_hw *hw,
272 const struct cfg80211_sar_specs *sar)
273 {
274 struct rtw89_dev *rtwdev = hw->priv;
275 struct rtw89_sar_cfg_common sar_common = {0};
276 u8 fct;
277 u32 freq_start;
278 u32 freq_end;
279 s32 power;
280 u32 i, idx;
281
282 if (sar->type != NL80211_SAR_TYPE_POWER)
283 return -EINVAL;
284
285 fct = rtw89_sar_handlers[RTW89_SAR_SOURCE_COMMON].txpwr_factor_sar;
286
287 for (i = 0; i < sar->num_sub_specs; i++) {
288 idx = sar->sub_specs[i].freq_range_index;
289 if (idx >= ARRAY_SIZE(rtw89_common_sar_freq_ranges))
290 return -EINVAL;
291
292 freq_start = rtw89_common_sar_freq_ranges[idx].start_freq;
293 freq_end = rtw89_common_sar_freq_ranges[idx].end_freq;
294 power = sar->sub_specs[i].power;
295
296 rtw89_debug(rtwdev, RTW89_DBG_SAR,
297 "On freq %u to %u, set SAR limit %d (unit: 1/%lu dBm)\n",
298 freq_start, freq_end, power, BIT(fct));
299
300 sar_common.set[idx] = true;
301 sar_common.cfg[idx] = power;
302 }
303
304 return rtw89_apply_sar_common(rtwdev, &sar_common);
305 }
306
rtw89_tas_state_update(struct rtw89_dev * rtwdev)307 static void rtw89_tas_state_update(struct rtw89_dev *rtwdev)
308 {
309 const enum rtw89_sar_sources src = rtwdev->sar.src;
310 /* its members are protected by rtw89_sar_set_src() */
311 const struct rtw89_sar_handler *sar_hdl = &rtw89_sar_handlers[src];
312 struct rtw89_tas_info *tas = &rtwdev->tas;
313 s32 txpwr_avg = tas->total_txpwr / RTW89_TAS_MAX_WINDOW / PERCENT;
314 s32 dpr_on_threshold, dpr_off_threshold, cfg;
315 enum rtw89_tas_state state = tas->state;
316 const struct rtw89_chan *chan;
317 int ret;
318
319 lockdep_assert_held(&rtwdev->mutex);
320
321 if (src == RTW89_SAR_SOURCE_NONE)
322 return;
323
324 chan = rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
325 ret = sar_hdl->query_sar_config(rtwdev, chan->freq, &cfg);
326 if (ret)
327 return;
328
329 cfg = rtw89_txpwr_sar_to_tas(sar_hdl, cfg);
330
331 if (tas->delta >= cfg) {
332 rtw89_debug(rtwdev, RTW89_DBG_SAR,
333 "TAS delta exceed SAR limit\n");
334 state = RTW89_TAS_STATE_DPR_FORBID;
335 goto out;
336 }
337
338 dpr_on_threshold = cfg;
339 dpr_off_threshold = cfg - tas->dpr_gap;
340 rtw89_debug(rtwdev, RTW89_DBG_SAR,
341 "DPR_ON thold: %d, DPR_OFF thold: %d, txpwr_avg: %d\n",
342 dpr_on_threshold, dpr_off_threshold, txpwr_avg);
343
344 if (txpwr_avg >= dpr_on_threshold)
345 state = RTW89_TAS_STATE_DPR_ON;
346 else if (txpwr_avg < dpr_off_threshold)
347 state = RTW89_TAS_STATE_DPR_OFF;
348
349 out:
350 if (tas->state == state)
351 return;
352
353 rtw89_debug(rtwdev, RTW89_DBG_SAR,
354 "TAS old state: %d, new state: %d\n", tas->state, state);
355 tas->state = state;
356 rtw89_core_set_chip_txpwr(rtwdev);
357 }
358
rtw89_tas_init(struct rtw89_dev * rtwdev)359 void rtw89_tas_init(struct rtw89_dev *rtwdev)
360 {
361 struct rtw89_tas_info *tas = &rtwdev->tas;
362 struct rtw89_acpi_dsm_result res = {};
363 int ret;
364 u8 val;
365
366 ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_TAS_EN, &res);
367 if (ret) {
368 rtw89_debug(rtwdev, RTW89_DBG_SAR,
369 "acpi: cannot get TAS: %d\n", ret);
370 return;
371 }
372
373 val = res.u.value;
374 switch (val) {
375 case 0:
376 tas->enable = false;
377 break;
378 case 1:
379 tas->enable = true;
380 break;
381 default:
382 break;
383 }
384
385 if (!tas->enable) {
386 rtw89_debug(rtwdev, RTW89_DBG_SAR, "TAS not enable\n");
387 return;
388 }
389
390 tas->dpr_gap = RTW89_TAS_DPR_GAP;
391 tas->delta = RTW89_TAS_DELTA;
392 }
393
rtw89_tas_reset(struct rtw89_dev * rtwdev)394 void rtw89_tas_reset(struct rtw89_dev *rtwdev)
395 {
396 struct rtw89_tas_info *tas = &rtwdev->tas;
397
398 if (!tas->enable)
399 return;
400
401 memset(&tas->txpwr_history, 0, sizeof(tas->txpwr_history));
402 tas->total_txpwr = 0;
403 tas->cur_idx = 0;
404 tas->state = RTW89_TAS_STATE_DPR_OFF;
405 }
406
407 static const struct rtw89_reg_def txpwr_regs[] = {
408 {R_PATH0_TXPWR, B_PATH0_TXPWR},
409 {R_PATH1_TXPWR, B_PATH1_TXPWR},
410 };
411
rtw89_tas_track(struct rtw89_dev * rtwdev)412 void rtw89_tas_track(struct rtw89_dev *rtwdev)
413 {
414 struct rtw89_env_monitor_info *env = &rtwdev->env_monitor;
415 const enum rtw89_sar_sources src = rtwdev->sar.src;
416 u8 max_nss_num = rtwdev->chip->rf_path_num;
417 struct rtw89_tas_info *tas = &rtwdev->tas;
418 s16 tmp, txpwr, instant_txpwr = 0;
419 u32 val;
420 int i;
421
422 if (!tas->enable || src == RTW89_SAR_SOURCE_NONE)
423 return;
424
425 if (env->ccx_watchdog_result != RTW89_PHY_ENV_MON_IFS_CLM)
426 return;
427
428 for (i = 0; i < max_nss_num; i++) {
429 val = rtw89_phy_read32_mask(rtwdev, txpwr_regs[i].addr,
430 txpwr_regs[i].mask);
431 tmp = sign_extend32(val, 8);
432 if (tmp <= 0)
433 return;
434 instant_txpwr += tmp;
435 }
436
437 instant_txpwr /= max_nss_num;
438 /* in unit of 0.25 dBm multiply by percentage */
439 txpwr = instant_txpwr * env->ifs_clm_tx_ratio;
440 tas->total_txpwr += txpwr - tas->txpwr_history[tas->cur_idx];
441 tas->txpwr_history[tas->cur_idx] = txpwr;
442 rtw89_debug(rtwdev, RTW89_DBG_SAR,
443 "instant_txpwr: %d, tx_ratio: %d, txpwr: %d\n",
444 instant_txpwr, env->ifs_clm_tx_ratio, txpwr);
445
446 tas->cur_idx = (tas->cur_idx + 1) % RTW89_TAS_MAX_WINDOW;
447
448 rtw89_tas_state_update(rtwdev);
449 }
450