1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
2 | /* Copyright(c) 2018-2019 Realtek Corporation |
3 | */ |
4 | |
5 | #include <linux/bcd.h> |
6 | |
7 | #include "main.h" |
8 | #include "reg.h" |
9 | #include "fw.h" |
10 | #include "phy.h" |
11 | #include "debug.h" |
12 | #include "regd.h" |
13 | #include "sar.h" |
14 | |
15 | struct phy_cfg_pair { |
16 | u32 addr; |
17 | u32 data; |
18 | }; |
19 | |
20 | union phy_table_tile { |
21 | struct rtw_phy_cond cond; |
22 | struct phy_cfg_pair cfg; |
23 | }; |
24 | |
25 | static const u32 db_invert_table[12][8] = { |
26 | {10, 13, 16, 20, |
27 | 25, 32, 40, 50}, |
28 | {64, 80, 101, 128, |
29 | 160, 201, 256, 318}, |
30 | {401, 505, 635, 800, |
31 | 1007, 1268, 1596, 2010}, |
32 | {316, 398, 501, 631, |
33 | 794, 1000, 1259, 1585}, |
34 | {1995, 2512, 3162, 3981, |
35 | 5012, 6310, 7943, 10000}, |
36 | {12589, 15849, 19953, 25119, |
37 | 31623, 39811, 50119, 63098}, |
38 | {79433, 100000, 125893, 158489, |
39 | 199526, 251189, 316228, 398107}, |
40 | {501187, 630957, 794328, 1000000, |
41 | 1258925, 1584893, 1995262, 2511886}, |
42 | {3162278, 3981072, 5011872, 6309573, |
43 | 7943282, 1000000, 12589254, 15848932}, |
44 | {19952623, 25118864, 31622777, 39810717, |
45 | 50118723, 63095734, 79432823, 100000000}, |
46 | {125892541, 158489319, 199526232, 251188643, |
47 | 316227766, 398107171, 501187234, 630957345}, |
48 | {794328235, 1000000000, 1258925412, 1584893192, |
49 | 1995262315, 2511886432U, 3162277660U, 3981071706U} |
50 | }; |
51 | |
52 | u8 rtw_cck_rates[] = { DESC_RATE1M, DESC_RATE2M, DESC_RATE5_5M, DESC_RATE11M }; |
53 | u8 rtw_ofdm_rates[] = { |
54 | DESC_RATE6M, DESC_RATE9M, DESC_RATE12M, |
55 | DESC_RATE18M, DESC_RATE24M, DESC_RATE36M, |
56 | DESC_RATE48M, DESC_RATE54M |
57 | }; |
58 | u8 rtw_ht_1s_rates[] = { |
59 | DESC_RATEMCS0, DESC_RATEMCS1, DESC_RATEMCS2, |
60 | DESC_RATEMCS3, DESC_RATEMCS4, DESC_RATEMCS5, |
61 | DESC_RATEMCS6, DESC_RATEMCS7 |
62 | }; |
63 | u8 rtw_ht_2s_rates[] = { |
64 | DESC_RATEMCS8, DESC_RATEMCS9, DESC_RATEMCS10, |
65 | DESC_RATEMCS11, DESC_RATEMCS12, DESC_RATEMCS13, |
66 | DESC_RATEMCS14, DESC_RATEMCS15 |
67 | }; |
68 | u8 rtw_vht_1s_rates[] = { |
69 | DESC_RATEVHT1SS_MCS0, DESC_RATEVHT1SS_MCS1, |
70 | DESC_RATEVHT1SS_MCS2, DESC_RATEVHT1SS_MCS3, |
71 | DESC_RATEVHT1SS_MCS4, DESC_RATEVHT1SS_MCS5, |
72 | DESC_RATEVHT1SS_MCS6, DESC_RATEVHT1SS_MCS7, |
73 | DESC_RATEVHT1SS_MCS8, DESC_RATEVHT1SS_MCS9 |
74 | }; |
75 | u8 rtw_vht_2s_rates[] = { |
76 | DESC_RATEVHT2SS_MCS0, DESC_RATEVHT2SS_MCS1, |
77 | DESC_RATEVHT2SS_MCS2, DESC_RATEVHT2SS_MCS3, |
78 | DESC_RATEVHT2SS_MCS4, DESC_RATEVHT2SS_MCS5, |
79 | DESC_RATEVHT2SS_MCS6, DESC_RATEVHT2SS_MCS7, |
80 | DESC_RATEVHT2SS_MCS8, DESC_RATEVHT2SS_MCS9 |
81 | }; |
82 | u8 *rtw_rate_section[RTW_RATE_SECTION_MAX] = { |
83 | rtw_cck_rates, rtw_ofdm_rates, |
84 | rtw_ht_1s_rates, rtw_ht_2s_rates, |
85 | rtw_vht_1s_rates, rtw_vht_2s_rates |
86 | }; |
87 | EXPORT_SYMBOL(rtw_rate_section); |
88 | |
89 | u8 rtw_rate_size[RTW_RATE_SECTION_MAX] = { |
90 | ARRAY_SIZE(rtw_cck_rates), |
91 | ARRAY_SIZE(rtw_ofdm_rates), |
92 | ARRAY_SIZE(rtw_ht_1s_rates), |
93 | ARRAY_SIZE(rtw_ht_2s_rates), |
94 | ARRAY_SIZE(rtw_vht_1s_rates), |
95 | ARRAY_SIZE(rtw_vht_2s_rates) |
96 | }; |
97 | EXPORT_SYMBOL(rtw_rate_size); |
98 | |
99 | static const u8 rtw_cck_size = ARRAY_SIZE(rtw_cck_rates); |
100 | static const u8 rtw_ofdm_size = ARRAY_SIZE(rtw_ofdm_rates); |
101 | static const u8 rtw_ht_1s_size = ARRAY_SIZE(rtw_ht_1s_rates); |
102 | static const u8 rtw_ht_2s_size = ARRAY_SIZE(rtw_ht_2s_rates); |
103 | static const u8 rtw_vht_1s_size = ARRAY_SIZE(rtw_vht_1s_rates); |
104 | static const u8 rtw_vht_2s_size = ARRAY_SIZE(rtw_vht_2s_rates); |
105 | |
106 | enum rtw_phy_band_type { |
107 | PHY_BAND_2G = 0, |
108 | PHY_BAND_5G = 1, |
109 | }; |
110 | |
111 | static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev) |
112 | { |
113 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
114 | u8 i, j; |
115 | |
116 | for (i = 0; i <= RTW_CHANNEL_WIDTH_40; i++) { |
117 | for (j = 0; j < RTW_RF_PATH_MAX; j++) |
118 | dm_info->cck_pd_lv[i][j] = CCK_PD_LV0; |
119 | } |
120 | |
121 | dm_info->cck_fa_avg = CCK_FA_AVG_RESET; |
122 | } |
123 | |
124 | void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l) |
125 | { |
126 | struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; |
127 | |
128 | rtw_write32_mask(rtwdev, |
129 | addr: edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr, |
130 | mask: edcca_th[EDCCA_TH_L2H_IDX].hw_reg.mask, |
131 | data: l2h + edcca_th[EDCCA_TH_L2H_IDX].offset); |
132 | rtw_write32_mask(rtwdev, |
133 | addr: edcca_th[EDCCA_TH_H2L_IDX].hw_reg.addr, |
134 | mask: edcca_th[EDCCA_TH_H2L_IDX].hw_reg.mask, |
135 | data: h2l + edcca_th[EDCCA_TH_H2L_IDX].offset); |
136 | } |
137 | EXPORT_SYMBOL(rtw_phy_set_edcca_th); |
138 | |
139 | void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev) |
140 | { |
141 | const struct rtw_chip_info *chip = rtwdev->chip; |
142 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
143 | |
144 | /* turn off in debugfs for debug usage */ |
145 | if (!rtw_edcca_enabled) { |
146 | dm_info->edcca_mode = RTW_EDCCA_NORMAL; |
147 | rtw_dbg(rtwdev, mask: RTW_DBG_PHY, fmt: "EDCCA disabled, cannot be set\n" ); |
148 | return; |
149 | } |
150 | |
151 | switch (rtwdev->regd.dfs_region) { |
152 | case NL80211_DFS_ETSI: |
153 | dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY; |
154 | dm_info->l2h_th_ini = chip->l2h_th_ini_ad; |
155 | break; |
156 | case NL80211_DFS_JP: |
157 | dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY; |
158 | dm_info->l2h_th_ini = chip->l2h_th_ini_cs; |
159 | break; |
160 | default: |
161 | dm_info->edcca_mode = RTW_EDCCA_NORMAL; |
162 | break; |
163 | } |
164 | } |
165 | |
166 | static void rtw_phy_adaptivity_init(struct rtw_dev *rtwdev) |
167 | { |
168 | const struct rtw_chip_info *chip = rtwdev->chip; |
169 | |
170 | rtw_phy_adaptivity_set_mode(rtwdev); |
171 | if (chip->ops->adaptivity_init) |
172 | chip->ops->adaptivity_init(rtwdev); |
173 | } |
174 | |
175 | static void rtw_phy_adaptivity(struct rtw_dev *rtwdev) |
176 | { |
177 | if (rtwdev->chip->ops->adaptivity) |
178 | rtwdev->chip->ops->adaptivity(rtwdev); |
179 | } |
180 | |
181 | static void rtw_phy_cfo_init(struct rtw_dev *rtwdev) |
182 | { |
183 | const struct rtw_chip_info *chip = rtwdev->chip; |
184 | |
185 | if (chip->ops->cfo_init) |
186 | chip->ops->cfo_init(rtwdev); |
187 | } |
188 | |
189 | static void rtw_phy_tx_path_div_init(struct rtw_dev *rtwdev) |
190 | { |
191 | struct rtw_path_div *path_div = &rtwdev->dm_path_div; |
192 | |
193 | path_div->current_tx_path = rtwdev->chip->default_1ss_tx_path; |
194 | path_div->path_a_cnt = 0; |
195 | path_div->path_a_sum = 0; |
196 | path_div->path_b_cnt = 0; |
197 | path_div->path_b_sum = 0; |
198 | } |
199 | |
200 | void rtw_phy_init(struct rtw_dev *rtwdev) |
201 | { |
202 | const struct rtw_chip_info *chip = rtwdev->chip; |
203 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
204 | u32 addr, mask; |
205 | |
206 | dm_info->fa_history[3] = 0; |
207 | dm_info->fa_history[2] = 0; |
208 | dm_info->fa_history[1] = 0; |
209 | dm_info->fa_history[0] = 0; |
210 | dm_info->igi_bitmap = 0; |
211 | dm_info->igi_history[3] = 0; |
212 | dm_info->igi_history[2] = 0; |
213 | dm_info->igi_history[1] = 0; |
214 | |
215 | addr = chip->dig[0].addr; |
216 | mask = chip->dig[0].mask; |
217 | dm_info->igi_history[0] = rtw_read32_mask(rtwdev, addr, mask); |
218 | rtw_phy_cck_pd_init(rtwdev); |
219 | |
220 | dm_info->iqk.done = false; |
221 | rtw_phy_adaptivity_init(rtwdev); |
222 | rtw_phy_cfo_init(rtwdev); |
223 | rtw_phy_tx_path_div_init(rtwdev); |
224 | } |
225 | EXPORT_SYMBOL(rtw_phy_init); |
226 | |
227 | void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi) |
228 | { |
229 | const struct rtw_chip_info *chip = rtwdev->chip; |
230 | struct rtw_hal *hal = &rtwdev->hal; |
231 | u32 addr, mask; |
232 | u8 path; |
233 | |
234 | if (chip->dig_cck) { |
235 | const struct rtw_hw_reg *dig_cck = &chip->dig_cck[0]; |
236 | rtw_write32_mask(rtwdev, addr: dig_cck->addr, mask: dig_cck->mask, data: igi >> 1); |
237 | } |
238 | |
239 | for (path = 0; path < hal->rf_path_num; path++) { |
240 | addr = chip->dig[path].addr; |
241 | mask = chip->dig[path].mask; |
242 | rtw_write32_mask(rtwdev, addr, mask, data: igi); |
243 | } |
244 | } |
245 | |
246 | static void rtw_phy_stat_false_alarm(struct rtw_dev *rtwdev) |
247 | { |
248 | const struct rtw_chip_info *chip = rtwdev->chip; |
249 | |
250 | chip->ops->false_alarm_statistics(rtwdev); |
251 | } |
252 | |
253 | #define RA_FLOOR_TABLE_SIZE 7 |
254 | #define RA_FLOOR_UP_GAP 3 |
255 | |
256 | static u8 (u8 old_level, u8 ) |
257 | { |
258 | u8 table[RA_FLOOR_TABLE_SIZE] = {20, 34, 38, 42, 46, 50, 100}; |
259 | u8 new_level = 0; |
260 | int i; |
261 | |
262 | for (i = 0; i < RA_FLOOR_TABLE_SIZE; i++) |
263 | if (i >= old_level) |
264 | table[i] += RA_FLOOR_UP_GAP; |
265 | |
266 | for (i = 0; i < RA_FLOOR_TABLE_SIZE; i++) { |
267 | if (rssi < table[i]) { |
268 | new_level = i; |
269 | break; |
270 | } |
271 | } |
272 | |
273 | return new_level; |
274 | } |
275 | |
276 | struct rtw_phy_stat_iter_data { |
277 | struct rtw_dev *rtwdev; |
278 | u8 ; |
279 | }; |
280 | |
281 | static void (void *data, struct ieee80211_sta *sta) |
282 | { |
283 | struct rtw_phy_stat_iter_data *iter_data = data; |
284 | struct rtw_dev *rtwdev = iter_data->rtwdev; |
285 | struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; |
286 | u8 ; |
287 | |
288 | rssi = ewma_rssi_read(e: &si->avg_rssi); |
289 | si->rssi_level = rtw_phy_get_rssi_level(old_level: si->rssi_level, rssi); |
290 | |
291 | rtw_fw_send_rssi_info(rtwdev, si); |
292 | |
293 | iter_data->min_rssi = min_t(u8, rssi, iter_data->min_rssi); |
294 | } |
295 | |
296 | static void (struct rtw_dev *rtwdev) |
297 | { |
298 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
299 | struct rtw_phy_stat_iter_data data = {}; |
300 | |
301 | data.rtwdev = rtwdev; |
302 | data.min_rssi = U8_MAX; |
303 | rtw_iterate_stas(rtwdev, iterator: rtw_phy_stat_rssi_iter, data: &data); |
304 | |
305 | dm_info->pre_min_rssi = dm_info->min_rssi; |
306 | dm_info->min_rssi = data.min_rssi; |
307 | } |
308 | |
309 | static void rtw_phy_stat_rate_cnt(struct rtw_dev *rtwdev) |
310 | { |
311 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
312 | |
313 | dm_info->last_pkt_count = dm_info->cur_pkt_count; |
314 | memset(&dm_info->cur_pkt_count, 0, sizeof(dm_info->cur_pkt_count)); |
315 | } |
316 | |
317 | static void rtw_phy_statistics(struct rtw_dev *rtwdev) |
318 | { |
319 | rtw_phy_stat_rssi(rtwdev); |
320 | rtw_phy_stat_false_alarm(rtwdev); |
321 | rtw_phy_stat_rate_cnt(rtwdev); |
322 | } |
323 | |
324 | #define DIG_PERF_FA_TH_LOW 250 |
325 | #define DIG_PERF_FA_TH_HIGH 500 |
326 | #define 750 |
327 | #define DIG_PERF_MAX 0x5a |
328 | #define DIG_PERF_MID 0x40 |
329 | #define DIG_CVRG_FA_TH_LOW 2000 |
330 | #define DIG_CVRG_FA_TH_HIGH 4000 |
331 | #define 5000 |
332 | #define DIG_CVRG_MAX 0x2a |
333 | #define DIG_CVRG_MID 0x26 |
334 | #define DIG_CVRG_MIN 0x1c |
335 | #define 15 |
336 | |
337 | static bool |
338 | rtw_phy_dig_check_damping(struct rtw_dm_info *dm_info) |
339 | { |
340 | u16 fa_lo = DIG_PERF_FA_TH_LOW; |
341 | u16 fa_hi = DIG_PERF_FA_TH_HIGH; |
342 | u16 *fa_history; |
343 | u8 *igi_history; |
344 | u8 ; |
345 | u8 ; |
346 | u8 diff; |
347 | u8 igi_bitmap; |
348 | bool damping = false; |
349 | |
350 | min_rssi = dm_info->min_rssi; |
351 | if (dm_info->damping) { |
352 | damping_rssi = dm_info->damping_rssi; |
353 | diff = min_rssi > damping_rssi ? min_rssi - damping_rssi : |
354 | damping_rssi - min_rssi; |
355 | if (diff > 3 || dm_info->damping_cnt++ > 20) { |
356 | dm_info->damping = false; |
357 | return false; |
358 | } |
359 | |
360 | return true; |
361 | } |
362 | |
363 | igi_history = dm_info->igi_history; |
364 | fa_history = dm_info->fa_history; |
365 | igi_bitmap = dm_info->igi_bitmap & 0xf; |
366 | switch (igi_bitmap) { |
367 | case 5: |
368 | /* down -> up -> down -> up */ |
369 | if (igi_history[0] > igi_history[1] && |
370 | igi_history[2] > igi_history[3] && |
371 | igi_history[0] - igi_history[1] >= 2 && |
372 | igi_history[2] - igi_history[3] >= 2 && |
373 | fa_history[0] > fa_hi && fa_history[1] < fa_lo && |
374 | fa_history[2] > fa_hi && fa_history[3] < fa_lo) |
375 | damping = true; |
376 | break; |
377 | case 9: |
378 | /* up -> down -> down -> up */ |
379 | if (igi_history[0] > igi_history[1] && |
380 | igi_history[3] > igi_history[2] && |
381 | igi_history[0] - igi_history[1] >= 4 && |
382 | igi_history[3] - igi_history[2] >= 2 && |
383 | fa_history[0] > fa_hi && fa_history[1] < fa_lo && |
384 | fa_history[2] < fa_lo && fa_history[3] > fa_hi) |
385 | damping = true; |
386 | break; |
387 | default: |
388 | return false; |
389 | } |
390 | |
391 | if (damping) { |
392 | dm_info->damping = true; |
393 | dm_info->damping_cnt = 0; |
394 | dm_info->damping_rssi = min_rssi; |
395 | } |
396 | |
397 | return damping; |
398 | } |
399 | |
400 | static void rtw_phy_dig_get_boundary(struct rtw_dev *rtwdev, |
401 | struct rtw_dm_info *dm_info, |
402 | u8 *upper, u8 *lower, bool linked) |
403 | { |
404 | u8 dig_max, dig_min, dig_mid; |
405 | u8 ; |
406 | |
407 | if (linked) { |
408 | dig_max = DIG_PERF_MAX; |
409 | dig_mid = DIG_PERF_MID; |
410 | dig_min = rtwdev->chip->dig_min; |
411 | min_rssi = max_t(u8, dm_info->min_rssi, dig_min); |
412 | } else { |
413 | dig_max = DIG_CVRG_MAX; |
414 | dig_mid = DIG_CVRG_MID; |
415 | dig_min = DIG_CVRG_MIN; |
416 | min_rssi = dig_min; |
417 | } |
418 | |
419 | /* DIG MAX should be bounded by minimum RSSI with offset +15 */ |
420 | dig_max = min_t(u8, dig_max, min_rssi + DIG_RSSI_GAIN_OFFSET); |
421 | |
422 | *lower = clamp_t(u8, min_rssi, dig_min, dig_mid); |
423 | *upper = clamp_t(u8, *lower + DIG_RSSI_GAIN_OFFSET, dig_min, dig_max); |
424 | } |
425 | |
426 | static void rtw_phy_dig_get_threshold(struct rtw_dm_info *dm_info, |
427 | u16 *fa_th, u8 *step, bool linked) |
428 | { |
429 | u8 , ; |
430 | |
431 | min_rssi = dm_info->min_rssi; |
432 | pre_min_rssi = dm_info->pre_min_rssi; |
433 | step[0] = 4; |
434 | step[1] = 3; |
435 | step[2] = 2; |
436 | |
437 | if (linked) { |
438 | fa_th[0] = DIG_PERF_FA_TH_EXTRA_HIGH; |
439 | fa_th[1] = DIG_PERF_FA_TH_HIGH; |
440 | fa_th[2] = DIG_PERF_FA_TH_LOW; |
441 | if (pre_min_rssi > min_rssi) { |
442 | step[0] = 6; |
443 | step[1] = 4; |
444 | step[2] = 2; |
445 | } |
446 | } else { |
447 | fa_th[0] = DIG_CVRG_FA_TH_EXTRA_HIGH; |
448 | fa_th[1] = DIG_CVRG_FA_TH_HIGH; |
449 | fa_th[2] = DIG_CVRG_FA_TH_LOW; |
450 | } |
451 | } |
452 | |
453 | static void rtw_phy_dig_recorder(struct rtw_dm_info *dm_info, u8 igi, u16 fa) |
454 | { |
455 | u8 *igi_history; |
456 | u16 *fa_history; |
457 | u8 igi_bitmap; |
458 | bool up; |
459 | |
460 | igi_bitmap = dm_info->igi_bitmap << 1 & 0xfe; |
461 | igi_history = dm_info->igi_history; |
462 | fa_history = dm_info->fa_history; |
463 | |
464 | up = igi > igi_history[0]; |
465 | igi_bitmap |= up; |
466 | |
467 | igi_history[3] = igi_history[2]; |
468 | igi_history[2] = igi_history[1]; |
469 | igi_history[1] = igi_history[0]; |
470 | igi_history[0] = igi; |
471 | |
472 | fa_history[3] = fa_history[2]; |
473 | fa_history[2] = fa_history[1]; |
474 | fa_history[1] = fa_history[0]; |
475 | fa_history[0] = fa; |
476 | |
477 | dm_info->igi_bitmap = igi_bitmap; |
478 | } |
479 | |
480 | static void rtw_phy_dig(struct rtw_dev *rtwdev) |
481 | { |
482 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
483 | u8 upper_bound, lower_bound; |
484 | u8 pre_igi, cur_igi; |
485 | u16 fa_th[3], fa_cnt; |
486 | u8 level; |
487 | u8 step[3]; |
488 | bool linked; |
489 | |
490 | if (test_bit(RTW_FLAG_DIG_DISABLE, rtwdev->flags)) |
491 | return; |
492 | |
493 | if (rtw_phy_dig_check_damping(dm_info)) |
494 | return; |
495 | |
496 | linked = !!rtwdev->sta_cnt; |
497 | |
498 | fa_cnt = dm_info->total_fa_cnt; |
499 | pre_igi = dm_info->igi_history[0]; |
500 | |
501 | rtw_phy_dig_get_threshold(dm_info, fa_th, step, linked); |
502 | |
503 | /* test the false alarm count from the highest threshold level first, |
504 | * and increase it by corresponding step size |
505 | * |
506 | * note that the step size is offset by -2, compensate it afterall |
507 | */ |
508 | cur_igi = pre_igi; |
509 | for (level = 0; level < 3; level++) { |
510 | if (fa_cnt > fa_th[level]) { |
511 | cur_igi += step[level]; |
512 | break; |
513 | } |
514 | } |
515 | cur_igi -= 2; |
516 | |
517 | /* calculate the upper/lower bound by the minimum rssi we have among |
518 | * the peers connected with us, meanwhile make sure the igi value does |
519 | * not beyond the hardware limitation |
520 | */ |
521 | rtw_phy_dig_get_boundary(rtwdev, dm_info, upper: &upper_bound, lower: &lower_bound, |
522 | linked); |
523 | cur_igi = clamp_t(u8, cur_igi, lower_bound, upper_bound); |
524 | |
525 | /* record current igi value and false alarm statistics for further |
526 | * damping checks, and record the trend of igi values |
527 | */ |
528 | rtw_phy_dig_recorder(dm_info, igi: cur_igi, fa: fa_cnt); |
529 | |
530 | if (cur_igi != pre_igi) |
531 | rtw_phy_dig_write(rtwdev, igi: cur_igi); |
532 | } |
533 | |
534 | static void rtw_phy_ra_info_update_iter(void *data, struct ieee80211_sta *sta) |
535 | { |
536 | struct rtw_dev *rtwdev = data; |
537 | struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; |
538 | |
539 | rtw_update_sta_info(rtwdev, si, reset_ra_mask: false); |
540 | } |
541 | |
542 | static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev) |
543 | { |
544 | if (rtwdev->watch_dog_cnt & 0x3) |
545 | return; |
546 | |
547 | rtw_iterate_stas(rtwdev, iterator: rtw_phy_ra_info_update_iter, data: rtwdev); |
548 | } |
549 | |
550 | static u32 rtw_phy_get_rrsr_mask(struct rtw_dev *rtwdev, u8 rate_idx) |
551 | { |
552 | u8 rate_order; |
553 | |
554 | rate_order = rate_idx; |
555 | |
556 | if (rate_idx >= DESC_RATEVHT4SS_MCS0) |
557 | rate_order -= DESC_RATEVHT4SS_MCS0; |
558 | else if (rate_idx >= DESC_RATEVHT3SS_MCS0) |
559 | rate_order -= DESC_RATEVHT3SS_MCS0; |
560 | else if (rate_idx >= DESC_RATEVHT2SS_MCS0) |
561 | rate_order -= DESC_RATEVHT2SS_MCS0; |
562 | else if (rate_idx >= DESC_RATEVHT1SS_MCS0) |
563 | rate_order -= DESC_RATEVHT1SS_MCS0; |
564 | else if (rate_idx >= DESC_RATEMCS24) |
565 | rate_order -= DESC_RATEMCS24; |
566 | else if (rate_idx >= DESC_RATEMCS16) |
567 | rate_order -= DESC_RATEMCS16; |
568 | else if (rate_idx >= DESC_RATEMCS8) |
569 | rate_order -= DESC_RATEMCS8; |
570 | else if (rate_idx >= DESC_RATEMCS0) |
571 | rate_order -= DESC_RATEMCS0; |
572 | else if (rate_idx >= DESC_RATE6M) |
573 | rate_order -= DESC_RATE6M; |
574 | else |
575 | rate_order -= DESC_RATE1M; |
576 | |
577 | if (rate_idx >= DESC_RATEMCS0 || rate_order == 0) |
578 | rate_order++; |
579 | |
580 | return GENMASK(rate_order + RRSR_RATE_ORDER_CCK_LEN - 1, 0); |
581 | } |
582 | |
583 | static void rtw_phy_rrsr_mask_min_iter(void *data, struct ieee80211_sta *sta) |
584 | { |
585 | struct rtw_dev *rtwdev = (struct rtw_dev *)data; |
586 | struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; |
587 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
588 | u32 mask = 0; |
589 | |
590 | mask = rtw_phy_get_rrsr_mask(rtwdev, rate_idx: si->ra_report.desc_rate); |
591 | if (mask < dm_info->rrsr_mask_min) |
592 | dm_info->rrsr_mask_min = mask; |
593 | } |
594 | |
595 | static void rtw_phy_rrsr_update(struct rtw_dev *rtwdev) |
596 | { |
597 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
598 | |
599 | dm_info->rrsr_mask_min = RRSR_RATE_ORDER_MAX; |
600 | rtw_iterate_stas(rtwdev, iterator: rtw_phy_rrsr_mask_min_iter, data: rtwdev); |
601 | rtw_write32(rtwdev, REG_RRSR, val: dm_info->rrsr_val_init & dm_info->rrsr_mask_min); |
602 | } |
603 | |
604 | static void rtw_phy_dpk_track(struct rtw_dev *rtwdev) |
605 | { |
606 | const struct rtw_chip_info *chip = rtwdev->chip; |
607 | |
608 | if (chip->ops->dpk_track) |
609 | chip->ops->dpk_track(rtwdev); |
610 | } |
611 | |
612 | struct rtw_rx_addr_match_data { |
613 | struct rtw_dev *rtwdev; |
614 | struct ieee80211_hdr *hdr; |
615 | struct rtw_rx_pkt_stat *pkt_stat; |
616 | u8 *bssid; |
617 | }; |
618 | |
619 | static void rtw_phy_parsing_cfo_iter(void *data, u8 *mac, |
620 | struct ieee80211_vif *vif) |
621 | { |
622 | struct rtw_rx_addr_match_data *iter_data = data; |
623 | struct rtw_dev *rtwdev = iter_data->rtwdev; |
624 | struct rtw_rx_pkt_stat *pkt_stat = iter_data->pkt_stat; |
625 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
626 | struct rtw_cfo_track *cfo = &dm_info->cfo_track; |
627 | u8 *bssid = iter_data->bssid; |
628 | u8 i; |
629 | |
630 | if (!ether_addr_equal(addr1: vif->bss_conf.bssid, addr2: bssid)) |
631 | return; |
632 | |
633 | for (i = 0; i < rtwdev->hal.rf_path_num; i++) { |
634 | cfo->cfo_tail[i] += pkt_stat->cfo_tail[i]; |
635 | cfo->cfo_cnt[i]++; |
636 | } |
637 | |
638 | cfo->packet_count++; |
639 | } |
640 | |
641 | void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev, |
642 | struct rtw_rx_pkt_stat *pkt_stat) |
643 | { |
644 | struct ieee80211_hdr *hdr = pkt_stat->hdr; |
645 | struct rtw_rx_addr_match_data data = {}; |
646 | |
647 | if (pkt_stat->crc_err || pkt_stat->icv_err || !pkt_stat->phy_status || |
648 | ieee80211_is_ctl(fc: hdr->frame_control)) |
649 | return; |
650 | |
651 | data.rtwdev = rtwdev; |
652 | data.hdr = hdr; |
653 | data.pkt_stat = pkt_stat; |
654 | data.bssid = get_hdr_bssid(hdr); |
655 | |
656 | rtw_iterate_vifs_atomic(rtwdev, rtw_phy_parsing_cfo_iter, &data); |
657 | } |
658 | EXPORT_SYMBOL(rtw_phy_parsing_cfo); |
659 | |
660 | static void rtw_phy_cfo_track(struct rtw_dev *rtwdev) |
661 | { |
662 | const struct rtw_chip_info *chip = rtwdev->chip; |
663 | |
664 | if (chip->ops->cfo_track) |
665 | chip->ops->cfo_track(rtwdev); |
666 | } |
667 | |
668 | #define CCK_PD_FA_LV1_MIN 1000 |
669 | #define CCK_PD_FA_LV0_MAX 500 |
670 | |
671 | static u8 rtw_phy_cck_pd_lv_unlink(struct rtw_dev *rtwdev) |
672 | { |
673 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
674 | u32 cck_fa_avg = dm_info->cck_fa_avg; |
675 | |
676 | if (cck_fa_avg > CCK_PD_FA_LV1_MIN) |
677 | return CCK_PD_LV1; |
678 | |
679 | if (cck_fa_avg < CCK_PD_FA_LV0_MAX) |
680 | return CCK_PD_LV0; |
681 | |
682 | return CCK_PD_LV_MAX; |
683 | } |
684 | |
685 | #define CCK_PD_IGI_LV4_VAL 0x38 |
686 | #define CCK_PD_IGI_LV3_VAL 0x2a |
687 | #define CCK_PD_IGI_LV2_VAL 0x24 |
688 | #define 32 |
689 | #define 32 |
690 | #define 24 |
691 | |
692 | static u8 rtw_phy_cck_pd_lv_link(struct rtw_dev *rtwdev) |
693 | { |
694 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
695 | u8 igi = dm_info->igi_history[0]; |
696 | u8 = dm_info->min_rssi; |
697 | u32 cck_fa_avg = dm_info->cck_fa_avg; |
698 | |
699 | if (igi > CCK_PD_IGI_LV4_VAL && rssi > CCK_PD_RSSI_LV4_VAL) |
700 | return CCK_PD_LV4; |
701 | if (igi > CCK_PD_IGI_LV3_VAL && rssi > CCK_PD_RSSI_LV3_VAL) |
702 | return CCK_PD_LV3; |
703 | if (igi > CCK_PD_IGI_LV2_VAL || rssi > CCK_PD_RSSI_LV2_VAL) |
704 | return CCK_PD_LV2; |
705 | if (cck_fa_avg > CCK_PD_FA_LV1_MIN) |
706 | return CCK_PD_LV1; |
707 | if (cck_fa_avg < CCK_PD_FA_LV0_MAX) |
708 | return CCK_PD_LV0; |
709 | |
710 | return CCK_PD_LV_MAX; |
711 | } |
712 | |
713 | static u8 rtw_phy_cck_pd_lv(struct rtw_dev *rtwdev) |
714 | { |
715 | if (!rtw_is_assoc(rtwdev)) |
716 | return rtw_phy_cck_pd_lv_unlink(rtwdev); |
717 | else |
718 | return rtw_phy_cck_pd_lv_link(rtwdev); |
719 | } |
720 | |
721 | static void rtw_phy_cck_pd(struct rtw_dev *rtwdev) |
722 | { |
723 | const struct rtw_chip_info *chip = rtwdev->chip; |
724 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
725 | u32 cck_fa = dm_info->cck_fa_cnt; |
726 | u8 level; |
727 | |
728 | if (rtwdev->hal.current_band_type != RTW_BAND_2G) |
729 | return; |
730 | |
731 | if (dm_info->cck_fa_avg == CCK_FA_AVG_RESET) |
732 | dm_info->cck_fa_avg = cck_fa; |
733 | else |
734 | dm_info->cck_fa_avg = (dm_info->cck_fa_avg * 3 + cck_fa) >> 2; |
735 | |
736 | rtw_dbg(rtwdev, mask: RTW_DBG_PHY, fmt: "IGI=0x%x, rssi_min=%d, cck_fa=%d\n" , |
737 | dm_info->igi_history[0], dm_info->min_rssi, |
738 | dm_info->fa_history[0]); |
739 | rtw_dbg(rtwdev, mask: RTW_DBG_PHY, fmt: "cck_fa_avg=%d, cck_pd_default=%d\n" , |
740 | dm_info->cck_fa_avg, dm_info->cck_pd_default); |
741 | |
742 | level = rtw_phy_cck_pd_lv(rtwdev); |
743 | |
744 | if (level >= CCK_PD_LV_MAX) |
745 | return; |
746 | |
747 | if (chip->ops->cck_pd_set) |
748 | chip->ops->cck_pd_set(rtwdev, level); |
749 | } |
750 | |
751 | static void rtw_phy_pwr_track(struct rtw_dev *rtwdev) |
752 | { |
753 | rtwdev->chip->ops->pwr_track(rtwdev); |
754 | } |
755 | |
756 | static void rtw_phy_ra_track(struct rtw_dev *rtwdev) |
757 | { |
758 | rtw_fw_update_wl_phy_info(rtwdev); |
759 | rtw_phy_ra_info_update(rtwdev); |
760 | rtw_phy_rrsr_update(rtwdev); |
761 | } |
762 | |
763 | void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev) |
764 | { |
765 | /* for further calculation */ |
766 | rtw_phy_statistics(rtwdev); |
767 | rtw_phy_dig(rtwdev); |
768 | rtw_phy_cck_pd(rtwdev); |
769 | rtw_phy_ra_track(rtwdev); |
770 | rtw_phy_tx_path_diversity(rtwdev); |
771 | rtw_phy_cfo_track(rtwdev); |
772 | rtw_phy_dpk_track(rtwdev); |
773 | rtw_phy_pwr_track(rtwdev); |
774 | |
775 | if (rtw_fw_feature_check(fw: &rtwdev->fw, feature: FW_FEATURE_ADAPTIVITY)) |
776 | rtw_fw_adaptivity(rtwdev); |
777 | else |
778 | rtw_phy_adaptivity(rtwdev); |
779 | } |
780 | |
781 | #define FRAC_BITS 3 |
782 | |
783 | static u8 rtw_phy_power_2_db(s8 power) |
784 | { |
785 | if (power <= -100 || power >= 20) |
786 | return 0; |
787 | else if (power >= 0) |
788 | return 100; |
789 | else |
790 | return 100 + power; |
791 | } |
792 | |
793 | static u64 rtw_phy_db_2_linear(u8 power_db) |
794 | { |
795 | u8 i, j; |
796 | u64 linear; |
797 | |
798 | if (power_db > 96) |
799 | power_db = 96; |
800 | else if (power_db < 1) |
801 | return 1; |
802 | |
803 | /* 1dB ~ 96dB */ |
804 | i = (power_db - 1) >> 3; |
805 | j = (power_db - 1) - (i << 3); |
806 | |
807 | linear = db_invert_table[i][j]; |
808 | linear = i > 2 ? linear << FRAC_BITS : linear; |
809 | |
810 | return linear; |
811 | } |
812 | |
813 | static u8 rtw_phy_linear_2_db(u64 linear) |
814 | { |
815 | u8 i; |
816 | u8 j; |
817 | u32 dB; |
818 | |
819 | for (i = 0; i < 12; i++) { |
820 | for (j = 0; j < 8; j++) { |
821 | if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j]) |
822 | goto cnt; |
823 | else if (i > 2 && linear <= db_invert_table[i][j]) |
824 | goto cnt; |
825 | } |
826 | } |
827 | |
828 | return 96; /* maximum 96 dB */ |
829 | |
830 | cnt: |
831 | if (j == 0 && i == 0) |
832 | goto end; |
833 | |
834 | if (j == 0) { |
835 | if (i != 3) { |
836 | if (db_invert_table[i][0] - linear > |
837 | linear - db_invert_table[i - 1][7]) { |
838 | i = i - 1; |
839 | j = 7; |
840 | } |
841 | } else { |
842 | if (db_invert_table[3][0] - linear > |
843 | linear - db_invert_table[2][7]) { |
844 | i = 2; |
845 | j = 7; |
846 | } |
847 | } |
848 | } else { |
849 | if (db_invert_table[i][j] - linear > |
850 | linear - db_invert_table[i][j - 1]) { |
851 | j = j - 1; |
852 | } |
853 | } |
854 | end: |
855 | dB = (i << 3) + j + 1; |
856 | |
857 | return dB; |
858 | } |
859 | |
860 | u8 (s8 *rf_power, u8 path_num) |
861 | { |
862 | s8 power; |
863 | u8 power_db; |
864 | u64 linear; |
865 | u64 sum = 0; |
866 | u8 path; |
867 | |
868 | for (path = 0; path < path_num; path++) { |
869 | power = rf_power[path]; |
870 | power_db = rtw_phy_power_2_db(power); |
871 | linear = rtw_phy_db_2_linear(power_db); |
872 | sum += linear; |
873 | } |
874 | |
875 | sum = (sum + (1 << (FRAC_BITS - 1))) >> FRAC_BITS; |
876 | switch (path_num) { |
877 | case 2: |
878 | sum >>= 1; |
879 | break; |
880 | case 3: |
881 | sum = ((sum) + ((sum) << 1) + ((sum) << 3)) >> 5; |
882 | break; |
883 | case 4: |
884 | sum >>= 2; |
885 | break; |
886 | default: |
887 | break; |
888 | } |
889 | |
890 | return rtw_phy_linear_2_db(linear: sum); |
891 | } |
892 | EXPORT_SYMBOL(rtw_phy_rf_power_2_rssi); |
893 | |
894 | u32 rtw_phy_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, |
895 | u32 addr, u32 mask) |
896 | { |
897 | struct rtw_hal *hal = &rtwdev->hal; |
898 | const struct rtw_chip_info *chip = rtwdev->chip; |
899 | const u32 *base_addr = chip->rf_base_addr; |
900 | u32 val, direct_addr; |
901 | |
902 | if (rf_path >= hal->rf_phy_num) { |
903 | rtw_err(rtwdev, "unsupported rf path (%d)\n" , rf_path); |
904 | return INV_RF_DATA; |
905 | } |
906 | |
907 | addr &= 0xff; |
908 | direct_addr = base_addr[rf_path] + (addr << 2); |
909 | mask &= RFREG_MASK; |
910 | |
911 | val = rtw_read32_mask(rtwdev, addr: direct_addr, mask); |
912 | |
913 | return val; |
914 | } |
915 | EXPORT_SYMBOL(rtw_phy_read_rf); |
916 | |
917 | u32 rtw_phy_read_rf_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, |
918 | u32 addr, u32 mask) |
919 | { |
920 | struct rtw_hal *hal = &rtwdev->hal; |
921 | const struct rtw_chip_info *chip = rtwdev->chip; |
922 | const struct rtw_rf_sipi_addr *rf_sipi_addr; |
923 | const struct rtw_rf_sipi_addr *rf_sipi_addr_a; |
924 | u32 val32; |
925 | u32 en_pi; |
926 | u32 r_addr; |
927 | u32 shift; |
928 | |
929 | if (rf_path >= hal->rf_phy_num) { |
930 | rtw_err(rtwdev, "unsupported rf path (%d)\n" , rf_path); |
931 | return INV_RF_DATA; |
932 | } |
933 | |
934 | if (!chip->rf_sipi_read_addr) { |
935 | rtw_err(rtwdev, "rf_sipi_read_addr isn't defined\n" ); |
936 | return INV_RF_DATA; |
937 | } |
938 | |
939 | rf_sipi_addr = &chip->rf_sipi_read_addr[rf_path]; |
940 | rf_sipi_addr_a = &chip->rf_sipi_read_addr[RF_PATH_A]; |
941 | |
942 | addr &= 0xff; |
943 | |
944 | val32 = rtw_read32(rtwdev, addr: rf_sipi_addr->hssi_2); |
945 | val32 = (val32 & ~LSSI_READ_ADDR_MASK) | (addr << 23); |
946 | rtw_write32(rtwdev, addr: rf_sipi_addr->hssi_2, val: val32); |
947 | |
948 | /* toggle read edge of path A */ |
949 | val32 = rtw_read32(rtwdev, addr: rf_sipi_addr_a->hssi_2); |
950 | rtw_write32(rtwdev, addr: rf_sipi_addr_a->hssi_2, val: val32 & ~LSSI_READ_EDGE_MASK); |
951 | rtw_write32(rtwdev, addr: rf_sipi_addr_a->hssi_2, val: val32 | LSSI_READ_EDGE_MASK); |
952 | |
953 | udelay(120); |
954 | |
955 | en_pi = rtw_read32_mask(rtwdev, addr: rf_sipi_addr->hssi_1, BIT(8)); |
956 | r_addr = en_pi ? rf_sipi_addr->lssi_read_pi : rf_sipi_addr->lssi_read; |
957 | |
958 | val32 = rtw_read32_mask(rtwdev, addr: r_addr, LSSI_READ_DATA_MASK); |
959 | |
960 | shift = __ffs(mask); |
961 | |
962 | return (val32 & mask) >> shift; |
963 | } |
964 | EXPORT_SYMBOL(rtw_phy_read_rf_sipi); |
965 | |
966 | bool rtw_phy_write_rf_reg_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, |
967 | u32 addr, u32 mask, u32 data) |
968 | { |
969 | struct rtw_hal *hal = &rtwdev->hal; |
970 | const struct rtw_chip_info *chip = rtwdev->chip; |
971 | const u32 *sipi_addr = chip->rf_sipi_addr; |
972 | u32 data_and_addr; |
973 | u32 old_data = 0; |
974 | u32 shift; |
975 | |
976 | if (rf_path >= hal->rf_phy_num) { |
977 | rtw_err(rtwdev, "unsupported rf path (%d)\n" , rf_path); |
978 | return false; |
979 | } |
980 | |
981 | addr &= 0xff; |
982 | mask &= RFREG_MASK; |
983 | |
984 | if (mask != RFREG_MASK) { |
985 | old_data = chip->ops->read_rf(rtwdev, rf_path, addr, RFREG_MASK); |
986 | |
987 | if (old_data == INV_RF_DATA) { |
988 | rtw_err(rtwdev, "Write fail, rf is disabled\n" ); |
989 | return false; |
990 | } |
991 | |
992 | shift = __ffs(mask); |
993 | data = ((old_data) & (~mask)) | (data << shift); |
994 | } |
995 | |
996 | data_and_addr = ((addr << 20) | (data & 0x000fffff)) & 0x0fffffff; |
997 | |
998 | rtw_write32(rtwdev, addr: sipi_addr[rf_path], val: data_and_addr); |
999 | |
1000 | udelay(13); |
1001 | |
1002 | return true; |
1003 | } |
1004 | EXPORT_SYMBOL(rtw_phy_write_rf_reg_sipi); |
1005 | |
1006 | bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, |
1007 | u32 addr, u32 mask, u32 data) |
1008 | { |
1009 | struct rtw_hal *hal = &rtwdev->hal; |
1010 | const struct rtw_chip_info *chip = rtwdev->chip; |
1011 | const u32 *base_addr = chip->rf_base_addr; |
1012 | u32 direct_addr; |
1013 | |
1014 | if (rf_path >= hal->rf_phy_num) { |
1015 | rtw_err(rtwdev, "unsupported rf path (%d)\n" , rf_path); |
1016 | return false; |
1017 | } |
1018 | |
1019 | addr &= 0xff; |
1020 | direct_addr = base_addr[rf_path] + (addr << 2); |
1021 | mask &= RFREG_MASK; |
1022 | |
1023 | rtw_write32_mask(rtwdev, addr: direct_addr, mask, data); |
1024 | |
1025 | udelay(1); |
1026 | |
1027 | return true; |
1028 | } |
1029 | |
1030 | bool rtw_phy_write_rf_reg_mix(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, |
1031 | u32 addr, u32 mask, u32 data) |
1032 | { |
1033 | if (addr != 0x00) |
1034 | return rtw_phy_write_rf_reg(rtwdev, rf_path, addr, mask, data); |
1035 | |
1036 | return rtw_phy_write_rf_reg_sipi(rtwdev, rf_path, addr, mask, data); |
1037 | } |
1038 | EXPORT_SYMBOL(rtw_phy_write_rf_reg_mix); |
1039 | |
1040 | void rtw_phy_setup_phy_cond(struct rtw_dev *rtwdev, u32 pkg) |
1041 | { |
1042 | struct rtw_hal *hal = &rtwdev->hal; |
1043 | struct rtw_efuse *efuse = &rtwdev->efuse; |
1044 | struct rtw_phy_cond cond = {0}; |
1045 | |
1046 | cond.cut = hal->cut_version ? hal->cut_version : 15; |
1047 | cond.pkg = pkg ? pkg : 15; |
1048 | cond.plat = 0x04; |
1049 | cond.rfe = efuse->rfe_option; |
1050 | |
1051 | switch (rtw_hci_type(rtwdev)) { |
1052 | case RTW_HCI_TYPE_USB: |
1053 | cond.intf = INTF_USB; |
1054 | break; |
1055 | case RTW_HCI_TYPE_SDIO: |
1056 | cond.intf = INTF_SDIO; |
1057 | break; |
1058 | case RTW_HCI_TYPE_PCIE: |
1059 | default: |
1060 | cond.intf = INTF_PCIE; |
1061 | break; |
1062 | } |
1063 | |
1064 | hal->phy_cond = cond; |
1065 | |
1066 | rtw_dbg(rtwdev, mask: RTW_DBG_PHY, fmt: "phy cond=0x%08x\n" , *((u32 *)&hal->phy_cond)); |
1067 | } |
1068 | |
1069 | static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond) |
1070 | { |
1071 | struct rtw_hal *hal = &rtwdev->hal; |
1072 | struct rtw_phy_cond drv_cond = hal->phy_cond; |
1073 | |
1074 | if (cond.cut && cond.cut != drv_cond.cut) |
1075 | return false; |
1076 | |
1077 | if (cond.pkg && cond.pkg != drv_cond.pkg) |
1078 | return false; |
1079 | |
1080 | if (cond.intf && cond.intf != drv_cond.intf) |
1081 | return false; |
1082 | |
1083 | if (cond.rfe != drv_cond.rfe) |
1084 | return false; |
1085 | |
1086 | return true; |
1087 | } |
1088 | |
1089 | void rtw_parse_tbl_phy_cond(struct rtw_dev *rtwdev, const struct rtw_table *tbl) |
1090 | { |
1091 | const union phy_table_tile *p = tbl->data; |
1092 | const union phy_table_tile *end = p + tbl->size / 2; |
1093 | struct rtw_phy_cond pos_cond = {0}; |
1094 | bool is_matched = true, is_skipped = false; |
1095 | |
1096 | BUILD_BUG_ON(sizeof(union phy_table_tile) != sizeof(struct phy_cfg_pair)); |
1097 | |
1098 | for (; p < end; p++) { |
1099 | if (p->cond.pos) { |
1100 | switch (p->cond.branch) { |
1101 | case BRANCH_ENDIF: |
1102 | is_matched = true; |
1103 | is_skipped = false; |
1104 | break; |
1105 | case BRANCH_ELSE: |
1106 | is_matched = is_skipped ? false : true; |
1107 | break; |
1108 | case BRANCH_IF: |
1109 | case BRANCH_ELIF: |
1110 | default: |
1111 | pos_cond = p->cond; |
1112 | break; |
1113 | } |
1114 | } else if (p->cond.neg) { |
1115 | if (!is_skipped) { |
1116 | if (check_positive(rtwdev, cond: pos_cond)) { |
1117 | is_matched = true; |
1118 | is_skipped = true; |
1119 | } else { |
1120 | is_matched = false; |
1121 | is_skipped = false; |
1122 | } |
1123 | } else { |
1124 | is_matched = false; |
1125 | } |
1126 | } else if (is_matched) { |
1127 | (*tbl->do_cfg)(rtwdev, tbl, p->cfg.addr, p->cfg.data); |
1128 | } |
1129 | } |
1130 | } |
1131 | EXPORT_SYMBOL(rtw_parse_tbl_phy_cond); |
1132 | |
1133 | #define bcd_to_dec_pwr_by_rate(val, i) bcd2bin(val >> (i * 8)) |
1134 | |
1135 | static u8 tbl_to_dec_pwr_by_rate(struct rtw_dev *rtwdev, u32 hex, u8 i) |
1136 | { |
1137 | if (rtwdev->chip->is_pwr_by_rate_dec) |
1138 | return bcd_to_dec_pwr_by_rate(hex, i); |
1139 | |
1140 | return (hex >> (i * 8)) & 0xFF; |
1141 | } |
1142 | |
1143 | static void |
1144 | rtw_phy_get_rate_values_of_txpwr_by_rate(struct rtw_dev *rtwdev, |
1145 | u32 addr, u32 mask, u32 val, u8 *rate, |
1146 | u8 *pwr_by_rate, u8 *rate_num) |
1147 | { |
1148 | int i; |
1149 | |
1150 | switch (addr) { |
1151 | case 0xE00: |
1152 | case 0x830: |
1153 | rate[0] = DESC_RATE6M; |
1154 | rate[1] = DESC_RATE9M; |
1155 | rate[2] = DESC_RATE12M; |
1156 | rate[3] = DESC_RATE18M; |
1157 | for (i = 0; i < 4; ++i) |
1158 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1159 | *rate_num = 4; |
1160 | break; |
1161 | case 0xE04: |
1162 | case 0x834: |
1163 | rate[0] = DESC_RATE24M; |
1164 | rate[1] = DESC_RATE36M; |
1165 | rate[2] = DESC_RATE48M; |
1166 | rate[3] = DESC_RATE54M; |
1167 | for (i = 0; i < 4; ++i) |
1168 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1169 | *rate_num = 4; |
1170 | break; |
1171 | case 0xE08: |
1172 | rate[0] = DESC_RATE1M; |
1173 | pwr_by_rate[0] = bcd_to_dec_pwr_by_rate(val, 1); |
1174 | *rate_num = 1; |
1175 | break; |
1176 | case 0x86C: |
1177 | if (mask == 0xffffff00) { |
1178 | rate[0] = DESC_RATE2M; |
1179 | rate[1] = DESC_RATE5_5M; |
1180 | rate[2] = DESC_RATE11M; |
1181 | for (i = 1; i < 4; ++i) |
1182 | pwr_by_rate[i - 1] = |
1183 | tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1184 | *rate_num = 3; |
1185 | } else if (mask == 0x000000ff) { |
1186 | rate[0] = DESC_RATE11M; |
1187 | pwr_by_rate[0] = bcd_to_dec_pwr_by_rate(val, 0); |
1188 | *rate_num = 1; |
1189 | } |
1190 | break; |
1191 | case 0xE10: |
1192 | case 0x83C: |
1193 | rate[0] = DESC_RATEMCS0; |
1194 | rate[1] = DESC_RATEMCS1; |
1195 | rate[2] = DESC_RATEMCS2; |
1196 | rate[3] = DESC_RATEMCS3; |
1197 | for (i = 0; i < 4; ++i) |
1198 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1199 | *rate_num = 4; |
1200 | break; |
1201 | case 0xE14: |
1202 | case 0x848: |
1203 | rate[0] = DESC_RATEMCS4; |
1204 | rate[1] = DESC_RATEMCS5; |
1205 | rate[2] = DESC_RATEMCS6; |
1206 | rate[3] = DESC_RATEMCS7; |
1207 | for (i = 0; i < 4; ++i) |
1208 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1209 | *rate_num = 4; |
1210 | break; |
1211 | case 0xE18: |
1212 | case 0x84C: |
1213 | rate[0] = DESC_RATEMCS8; |
1214 | rate[1] = DESC_RATEMCS9; |
1215 | rate[2] = DESC_RATEMCS10; |
1216 | rate[3] = DESC_RATEMCS11; |
1217 | for (i = 0; i < 4; ++i) |
1218 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1219 | *rate_num = 4; |
1220 | break; |
1221 | case 0xE1C: |
1222 | case 0x868: |
1223 | rate[0] = DESC_RATEMCS12; |
1224 | rate[1] = DESC_RATEMCS13; |
1225 | rate[2] = DESC_RATEMCS14; |
1226 | rate[3] = DESC_RATEMCS15; |
1227 | for (i = 0; i < 4; ++i) |
1228 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1229 | *rate_num = 4; |
1230 | break; |
1231 | case 0x838: |
1232 | rate[0] = DESC_RATE1M; |
1233 | rate[1] = DESC_RATE2M; |
1234 | rate[2] = DESC_RATE5_5M; |
1235 | for (i = 1; i < 4; ++i) |
1236 | pwr_by_rate[i - 1] = tbl_to_dec_pwr_by_rate(rtwdev, |
1237 | hex: val, i); |
1238 | *rate_num = 3; |
1239 | break; |
1240 | case 0xC20: |
1241 | case 0xE20: |
1242 | case 0x1820: |
1243 | case 0x1A20: |
1244 | rate[0] = DESC_RATE1M; |
1245 | rate[1] = DESC_RATE2M; |
1246 | rate[2] = DESC_RATE5_5M; |
1247 | rate[3] = DESC_RATE11M; |
1248 | for (i = 0; i < 4; ++i) |
1249 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1250 | *rate_num = 4; |
1251 | break; |
1252 | case 0xC24: |
1253 | case 0xE24: |
1254 | case 0x1824: |
1255 | case 0x1A24: |
1256 | rate[0] = DESC_RATE6M; |
1257 | rate[1] = DESC_RATE9M; |
1258 | rate[2] = DESC_RATE12M; |
1259 | rate[3] = DESC_RATE18M; |
1260 | for (i = 0; i < 4; ++i) |
1261 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1262 | *rate_num = 4; |
1263 | break; |
1264 | case 0xC28: |
1265 | case 0xE28: |
1266 | case 0x1828: |
1267 | case 0x1A28: |
1268 | rate[0] = DESC_RATE24M; |
1269 | rate[1] = DESC_RATE36M; |
1270 | rate[2] = DESC_RATE48M; |
1271 | rate[3] = DESC_RATE54M; |
1272 | for (i = 0; i < 4; ++i) |
1273 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1274 | *rate_num = 4; |
1275 | break; |
1276 | case 0xC2C: |
1277 | case 0xE2C: |
1278 | case 0x182C: |
1279 | case 0x1A2C: |
1280 | rate[0] = DESC_RATEMCS0; |
1281 | rate[1] = DESC_RATEMCS1; |
1282 | rate[2] = DESC_RATEMCS2; |
1283 | rate[3] = DESC_RATEMCS3; |
1284 | for (i = 0; i < 4; ++i) |
1285 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1286 | *rate_num = 4; |
1287 | break; |
1288 | case 0xC30: |
1289 | case 0xE30: |
1290 | case 0x1830: |
1291 | case 0x1A30: |
1292 | rate[0] = DESC_RATEMCS4; |
1293 | rate[1] = DESC_RATEMCS5; |
1294 | rate[2] = DESC_RATEMCS6; |
1295 | rate[3] = DESC_RATEMCS7; |
1296 | for (i = 0; i < 4; ++i) |
1297 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1298 | *rate_num = 4; |
1299 | break; |
1300 | case 0xC34: |
1301 | case 0xE34: |
1302 | case 0x1834: |
1303 | case 0x1A34: |
1304 | rate[0] = DESC_RATEMCS8; |
1305 | rate[1] = DESC_RATEMCS9; |
1306 | rate[2] = DESC_RATEMCS10; |
1307 | rate[3] = DESC_RATEMCS11; |
1308 | for (i = 0; i < 4; ++i) |
1309 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1310 | *rate_num = 4; |
1311 | break; |
1312 | case 0xC38: |
1313 | case 0xE38: |
1314 | case 0x1838: |
1315 | case 0x1A38: |
1316 | rate[0] = DESC_RATEMCS12; |
1317 | rate[1] = DESC_RATEMCS13; |
1318 | rate[2] = DESC_RATEMCS14; |
1319 | rate[3] = DESC_RATEMCS15; |
1320 | for (i = 0; i < 4; ++i) |
1321 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1322 | *rate_num = 4; |
1323 | break; |
1324 | case 0xC3C: |
1325 | case 0xE3C: |
1326 | case 0x183C: |
1327 | case 0x1A3C: |
1328 | rate[0] = DESC_RATEVHT1SS_MCS0; |
1329 | rate[1] = DESC_RATEVHT1SS_MCS1; |
1330 | rate[2] = DESC_RATEVHT1SS_MCS2; |
1331 | rate[3] = DESC_RATEVHT1SS_MCS3; |
1332 | for (i = 0; i < 4; ++i) |
1333 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1334 | *rate_num = 4; |
1335 | break; |
1336 | case 0xC40: |
1337 | case 0xE40: |
1338 | case 0x1840: |
1339 | case 0x1A40: |
1340 | rate[0] = DESC_RATEVHT1SS_MCS4; |
1341 | rate[1] = DESC_RATEVHT1SS_MCS5; |
1342 | rate[2] = DESC_RATEVHT1SS_MCS6; |
1343 | rate[3] = DESC_RATEVHT1SS_MCS7; |
1344 | for (i = 0; i < 4; ++i) |
1345 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1346 | *rate_num = 4; |
1347 | break; |
1348 | case 0xC44: |
1349 | case 0xE44: |
1350 | case 0x1844: |
1351 | case 0x1A44: |
1352 | rate[0] = DESC_RATEVHT1SS_MCS8; |
1353 | rate[1] = DESC_RATEVHT1SS_MCS9; |
1354 | rate[2] = DESC_RATEVHT2SS_MCS0; |
1355 | rate[3] = DESC_RATEVHT2SS_MCS1; |
1356 | for (i = 0; i < 4; ++i) |
1357 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1358 | *rate_num = 4; |
1359 | break; |
1360 | case 0xC48: |
1361 | case 0xE48: |
1362 | case 0x1848: |
1363 | case 0x1A48: |
1364 | rate[0] = DESC_RATEVHT2SS_MCS2; |
1365 | rate[1] = DESC_RATEVHT2SS_MCS3; |
1366 | rate[2] = DESC_RATEVHT2SS_MCS4; |
1367 | rate[3] = DESC_RATEVHT2SS_MCS5; |
1368 | for (i = 0; i < 4; ++i) |
1369 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1370 | *rate_num = 4; |
1371 | break; |
1372 | case 0xC4C: |
1373 | case 0xE4C: |
1374 | case 0x184C: |
1375 | case 0x1A4C: |
1376 | rate[0] = DESC_RATEVHT2SS_MCS6; |
1377 | rate[1] = DESC_RATEVHT2SS_MCS7; |
1378 | rate[2] = DESC_RATEVHT2SS_MCS8; |
1379 | rate[3] = DESC_RATEVHT2SS_MCS9; |
1380 | for (i = 0; i < 4; ++i) |
1381 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1382 | *rate_num = 4; |
1383 | break; |
1384 | case 0xCD8: |
1385 | case 0xED8: |
1386 | case 0x18D8: |
1387 | case 0x1AD8: |
1388 | rate[0] = DESC_RATEMCS16; |
1389 | rate[1] = DESC_RATEMCS17; |
1390 | rate[2] = DESC_RATEMCS18; |
1391 | rate[3] = DESC_RATEMCS19; |
1392 | for (i = 0; i < 4; ++i) |
1393 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1394 | *rate_num = 4; |
1395 | break; |
1396 | case 0xCDC: |
1397 | case 0xEDC: |
1398 | case 0x18DC: |
1399 | case 0x1ADC: |
1400 | rate[0] = DESC_RATEMCS20; |
1401 | rate[1] = DESC_RATEMCS21; |
1402 | rate[2] = DESC_RATEMCS22; |
1403 | rate[3] = DESC_RATEMCS23; |
1404 | for (i = 0; i < 4; ++i) |
1405 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1406 | *rate_num = 4; |
1407 | break; |
1408 | case 0xCE0: |
1409 | case 0xEE0: |
1410 | case 0x18E0: |
1411 | case 0x1AE0: |
1412 | rate[0] = DESC_RATEVHT3SS_MCS0; |
1413 | rate[1] = DESC_RATEVHT3SS_MCS1; |
1414 | rate[2] = DESC_RATEVHT3SS_MCS2; |
1415 | rate[3] = DESC_RATEVHT3SS_MCS3; |
1416 | for (i = 0; i < 4; ++i) |
1417 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1418 | *rate_num = 4; |
1419 | break; |
1420 | case 0xCE4: |
1421 | case 0xEE4: |
1422 | case 0x18E4: |
1423 | case 0x1AE4: |
1424 | rate[0] = DESC_RATEVHT3SS_MCS4; |
1425 | rate[1] = DESC_RATEVHT3SS_MCS5; |
1426 | rate[2] = DESC_RATEVHT3SS_MCS6; |
1427 | rate[3] = DESC_RATEVHT3SS_MCS7; |
1428 | for (i = 0; i < 4; ++i) |
1429 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1430 | *rate_num = 4; |
1431 | break; |
1432 | case 0xCE8: |
1433 | case 0xEE8: |
1434 | case 0x18E8: |
1435 | case 0x1AE8: |
1436 | rate[0] = DESC_RATEVHT3SS_MCS8; |
1437 | rate[1] = DESC_RATEVHT3SS_MCS9; |
1438 | for (i = 0; i < 2; ++i) |
1439 | pwr_by_rate[i] = tbl_to_dec_pwr_by_rate(rtwdev, hex: val, i); |
1440 | *rate_num = 2; |
1441 | break; |
1442 | default: |
1443 | rtw_warn(rtwdev, "invalid tx power index addr 0x%08x\n" , addr); |
1444 | break; |
1445 | } |
1446 | } |
1447 | |
1448 | static void rtw_phy_store_tx_power_by_rate(struct rtw_dev *rtwdev, |
1449 | u32 band, u32 rfpath, u32 txnum, |
1450 | u32 regaddr, u32 bitmask, u32 data) |
1451 | { |
1452 | struct rtw_hal *hal = &rtwdev->hal; |
1453 | u8 rate_num = 0; |
1454 | u8 rate; |
1455 | u8 rates[RTW_RF_PATH_MAX] = {0}; |
1456 | s8 offset; |
1457 | s8 pwr_by_rate[RTW_RF_PATH_MAX] = {0}; |
1458 | int i; |
1459 | |
1460 | rtw_phy_get_rate_values_of_txpwr_by_rate(rtwdev, addr: regaddr, mask: bitmask, val: data, |
1461 | rate: rates, pwr_by_rate, rate_num: &rate_num); |
1462 | |
1463 | if (WARN_ON(rfpath >= RTW_RF_PATH_MAX || |
1464 | (band != PHY_BAND_2G && band != PHY_BAND_5G) || |
1465 | rate_num > RTW_RF_PATH_MAX)) |
1466 | return; |
1467 | |
1468 | for (i = 0; i < rate_num; i++) { |
1469 | offset = pwr_by_rate[i]; |
1470 | rate = rates[i]; |
1471 | if (band == PHY_BAND_2G) |
1472 | hal->tx_pwr_by_rate_offset_2g[rfpath][rate] = offset; |
1473 | else if (band == PHY_BAND_5G) |
1474 | hal->tx_pwr_by_rate_offset_5g[rfpath][rate] = offset; |
1475 | else |
1476 | continue; |
1477 | } |
1478 | } |
1479 | |
1480 | void rtw_parse_tbl_bb_pg(struct rtw_dev *rtwdev, const struct rtw_table *tbl) |
1481 | { |
1482 | const struct rtw_phy_pg_cfg_pair *p = tbl->data; |
1483 | const struct rtw_phy_pg_cfg_pair *end = p + tbl->size; |
1484 | |
1485 | for (; p < end; p++) { |
1486 | if (p->addr == 0xfe || p->addr == 0xffe) { |
1487 | msleep(msecs: 50); |
1488 | continue; |
1489 | } |
1490 | rtw_phy_store_tx_power_by_rate(rtwdev, band: p->band, rfpath: p->rf_path, |
1491 | txnum: p->tx_num, regaddr: p->addr, bitmask: p->bitmask, |
1492 | data: p->data); |
1493 | } |
1494 | } |
1495 | EXPORT_SYMBOL(rtw_parse_tbl_bb_pg); |
1496 | |
1497 | static const u8 rtw_channel_idx_5g[RTW_MAX_CHANNEL_NUM_5G] = { |
1498 | 36, 38, 40, 42, 44, 46, 48, /* Band 1 */ |
1499 | 52, 54, 56, 58, 60, 62, 64, /* Band 2 */ |
1500 | 100, 102, 104, 106, 108, 110, 112, /* Band 3 */ |
1501 | 116, 118, 120, 122, 124, 126, 128, /* Band 3 */ |
1502 | 132, 134, 136, 138, 140, 142, 144, /* Band 3 */ |
1503 | 149, 151, 153, 155, 157, 159, 161, /* Band 4 */ |
1504 | 165, 167, 169, 171, 173, 175, 177}; /* Band 4 */ |
1505 | |
1506 | static int rtw_channel_to_idx(u8 band, u8 channel) |
1507 | { |
1508 | int ch_idx; |
1509 | u8 n_channel; |
1510 | |
1511 | if (band == PHY_BAND_2G) { |
1512 | ch_idx = channel - 1; |
1513 | n_channel = RTW_MAX_CHANNEL_NUM_2G; |
1514 | } else if (band == PHY_BAND_5G) { |
1515 | n_channel = RTW_MAX_CHANNEL_NUM_5G; |
1516 | for (ch_idx = 0; ch_idx < n_channel; ch_idx++) |
1517 | if (rtw_channel_idx_5g[ch_idx] == channel) |
1518 | break; |
1519 | } else { |
1520 | return -1; |
1521 | } |
1522 | |
1523 | if (ch_idx >= n_channel) |
1524 | return -1; |
1525 | |
1526 | return ch_idx; |
1527 | } |
1528 | |
1529 | static void rtw_phy_set_tx_power_limit(struct rtw_dev *rtwdev, u8 regd, u8 band, |
1530 | u8 bw, u8 rs, u8 ch, s8 pwr_limit) |
1531 | { |
1532 | struct rtw_hal *hal = &rtwdev->hal; |
1533 | u8 max_power_index = rtwdev->chip->max_power_index; |
1534 | s8 ww; |
1535 | int ch_idx; |
1536 | |
1537 | pwr_limit = clamp_t(s8, pwr_limit, |
1538 | -max_power_index, max_power_index); |
1539 | ch_idx = rtw_channel_to_idx(band, channel: ch); |
1540 | |
1541 | if (regd >= RTW_REGD_MAX || bw >= RTW_CHANNEL_WIDTH_MAX || |
1542 | rs >= RTW_RATE_SECTION_MAX || ch_idx < 0) { |
1543 | WARN(1, |
1544 | "wrong txpwr_lmt regd=%u, band=%u bw=%u, rs=%u, ch_idx=%u, pwr_limit=%d\n" , |
1545 | regd, band, bw, rs, ch_idx, pwr_limit); |
1546 | return; |
1547 | } |
1548 | |
1549 | if (band == PHY_BAND_2G) { |
1550 | hal->tx_pwr_limit_2g[regd][bw][rs][ch_idx] = pwr_limit; |
1551 | ww = hal->tx_pwr_limit_2g[RTW_REGD_WW][bw][rs][ch_idx]; |
1552 | ww = min_t(s8, ww, pwr_limit); |
1553 | hal->tx_pwr_limit_2g[RTW_REGD_WW][bw][rs][ch_idx] = ww; |
1554 | } else if (band == PHY_BAND_5G) { |
1555 | hal->tx_pwr_limit_5g[regd][bw][rs][ch_idx] = pwr_limit; |
1556 | ww = hal->tx_pwr_limit_5g[RTW_REGD_WW][bw][rs][ch_idx]; |
1557 | ww = min_t(s8, ww, pwr_limit); |
1558 | hal->tx_pwr_limit_5g[RTW_REGD_WW][bw][rs][ch_idx] = ww; |
1559 | } |
1560 | } |
1561 | |
1562 | /* cross-reference 5G power limits if values are not assigned */ |
1563 | static void |
1564 | rtw_xref_5g_txpwr_lmt(struct rtw_dev *rtwdev, u8 regd, |
1565 | u8 bw, u8 ch_idx, u8 rs_ht, u8 rs_vht) |
1566 | { |
1567 | struct rtw_hal *hal = &rtwdev->hal; |
1568 | u8 max_power_index = rtwdev->chip->max_power_index; |
1569 | s8 lmt_ht = hal->tx_pwr_limit_5g[regd][bw][rs_ht][ch_idx]; |
1570 | s8 lmt_vht = hal->tx_pwr_limit_5g[regd][bw][rs_vht][ch_idx]; |
1571 | |
1572 | if (lmt_ht == lmt_vht) |
1573 | return; |
1574 | |
1575 | if (lmt_ht == max_power_index) |
1576 | hal->tx_pwr_limit_5g[regd][bw][rs_ht][ch_idx] = lmt_vht; |
1577 | |
1578 | else if (lmt_vht == max_power_index) |
1579 | hal->tx_pwr_limit_5g[regd][bw][rs_vht][ch_idx] = lmt_ht; |
1580 | } |
1581 | |
1582 | /* cross-reference power limits for ht and vht */ |
1583 | static void |
1584 | rtw_xref_txpwr_lmt_by_rs(struct rtw_dev *rtwdev, u8 regd, u8 bw, u8 ch_idx) |
1585 | { |
1586 | u8 rs_idx, rs_ht, rs_vht; |
1587 | u8 rs_cmp[2][2] = {{RTW_RATE_SECTION_HT_1S, RTW_RATE_SECTION_VHT_1S}, |
1588 | {RTW_RATE_SECTION_HT_2S, RTW_RATE_SECTION_VHT_2S} }; |
1589 | |
1590 | for (rs_idx = 0; rs_idx < 2; rs_idx++) { |
1591 | rs_ht = rs_cmp[rs_idx][0]; |
1592 | rs_vht = rs_cmp[rs_idx][1]; |
1593 | |
1594 | rtw_xref_5g_txpwr_lmt(rtwdev, regd, bw, ch_idx, rs_ht, rs_vht); |
1595 | } |
1596 | } |
1597 | |
1598 | /* cross-reference power limits for 5G channels */ |
1599 | static void |
1600 | rtw_xref_5g_txpwr_lmt_by_ch(struct rtw_dev *rtwdev, u8 regd, u8 bw) |
1601 | { |
1602 | u8 ch_idx; |
1603 | |
1604 | for (ch_idx = 0; ch_idx < RTW_MAX_CHANNEL_NUM_5G; ch_idx++) |
1605 | rtw_xref_txpwr_lmt_by_rs(rtwdev, regd, bw, ch_idx); |
1606 | } |
1607 | |
1608 | /* cross-reference power limits for 20/40M bandwidth */ |
1609 | static void |
1610 | rtw_xref_txpwr_lmt_by_bw(struct rtw_dev *rtwdev, u8 regd) |
1611 | { |
1612 | u8 bw; |
1613 | |
1614 | for (bw = RTW_CHANNEL_WIDTH_20; bw <= RTW_CHANNEL_WIDTH_40; bw++) |
1615 | rtw_xref_5g_txpwr_lmt_by_ch(rtwdev, regd, bw); |
1616 | } |
1617 | |
1618 | /* cross-reference power limits */ |
1619 | static void rtw_xref_txpwr_lmt(struct rtw_dev *rtwdev) |
1620 | { |
1621 | u8 regd; |
1622 | |
1623 | for (regd = 0; regd < RTW_REGD_MAX; regd++) |
1624 | rtw_xref_txpwr_lmt_by_bw(rtwdev, regd); |
1625 | } |
1626 | |
1627 | static void |
1628 | __cfg_txpwr_lmt_by_alt(struct rtw_hal *hal, u8 regd, u8 regd_alt, u8 bw, u8 rs) |
1629 | { |
1630 | u8 ch; |
1631 | |
1632 | for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_2G; ch++) |
1633 | hal->tx_pwr_limit_2g[regd][bw][rs][ch] = |
1634 | hal->tx_pwr_limit_2g[regd_alt][bw][rs][ch]; |
1635 | |
1636 | for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_5G; ch++) |
1637 | hal->tx_pwr_limit_5g[regd][bw][rs][ch] = |
1638 | hal->tx_pwr_limit_5g[regd_alt][bw][rs][ch]; |
1639 | } |
1640 | |
1641 | static void |
1642 | rtw_cfg_txpwr_lmt_by_alt(struct rtw_dev *rtwdev, u8 regd, u8 regd_alt) |
1643 | { |
1644 | u8 bw, rs; |
1645 | |
1646 | for (bw = 0; bw < RTW_CHANNEL_WIDTH_MAX; bw++) |
1647 | for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) |
1648 | __cfg_txpwr_lmt_by_alt(hal: &rtwdev->hal, regd, regd_alt, |
1649 | bw, rs); |
1650 | } |
1651 | |
1652 | void rtw_parse_tbl_txpwr_lmt(struct rtw_dev *rtwdev, |
1653 | const struct rtw_table *tbl) |
1654 | { |
1655 | const struct rtw_txpwr_lmt_cfg_pair *p = tbl->data; |
1656 | const struct rtw_txpwr_lmt_cfg_pair *end = p + tbl->size; |
1657 | u32 regd_cfg_flag = 0; |
1658 | u8 regd_alt; |
1659 | u8 i; |
1660 | |
1661 | for (; p < end; p++) { |
1662 | regd_cfg_flag |= BIT(p->regd); |
1663 | rtw_phy_set_tx_power_limit(rtwdev, regd: p->regd, band: p->band, |
1664 | bw: p->bw, rs: p->rs, ch: p->ch, pwr_limit: p->txpwr_lmt); |
1665 | } |
1666 | |
1667 | for (i = 0; i < RTW_REGD_MAX; i++) { |
1668 | if (i == RTW_REGD_WW) |
1669 | continue; |
1670 | |
1671 | if (regd_cfg_flag & BIT(i)) |
1672 | continue; |
1673 | |
1674 | rtw_dbg(rtwdev, mask: RTW_DBG_REGD, |
1675 | fmt: "txpwr regd %d does not be configured\n" , i); |
1676 | |
1677 | if (rtw_regd_has_alt(regd: i, regd_alt: ®d_alt) && |
1678 | regd_cfg_flag & BIT(regd_alt)) { |
1679 | rtw_dbg(rtwdev, mask: RTW_DBG_REGD, |
1680 | fmt: "cfg txpwr regd %d by regd %d as alternative\n" , |
1681 | i, regd_alt); |
1682 | |
1683 | rtw_cfg_txpwr_lmt_by_alt(rtwdev, regd: i, regd_alt); |
1684 | continue; |
1685 | } |
1686 | |
1687 | rtw_dbg(rtwdev, mask: RTW_DBG_REGD, fmt: "cfg txpwr regd %d by WW\n" , i); |
1688 | rtw_cfg_txpwr_lmt_by_alt(rtwdev, regd: i, regd_alt: RTW_REGD_WW); |
1689 | } |
1690 | |
1691 | rtw_xref_txpwr_lmt(rtwdev); |
1692 | } |
1693 | EXPORT_SYMBOL(rtw_parse_tbl_txpwr_lmt); |
1694 | |
1695 | void rtw_phy_cfg_mac(struct rtw_dev *rtwdev, const struct rtw_table *tbl, |
1696 | u32 addr, u32 data) |
1697 | { |
1698 | rtw_write8(rtwdev, addr, val: data); |
1699 | } |
1700 | EXPORT_SYMBOL(rtw_phy_cfg_mac); |
1701 | |
1702 | void rtw_phy_cfg_agc(struct rtw_dev *rtwdev, const struct rtw_table *tbl, |
1703 | u32 addr, u32 data) |
1704 | { |
1705 | rtw_write32(rtwdev, addr, val: data); |
1706 | } |
1707 | EXPORT_SYMBOL(rtw_phy_cfg_agc); |
1708 | |
1709 | void rtw_phy_cfg_bb(struct rtw_dev *rtwdev, const struct rtw_table *tbl, |
1710 | u32 addr, u32 data) |
1711 | { |
1712 | if (addr == 0xfe) |
1713 | msleep(msecs: 50); |
1714 | else if (addr == 0xfd) |
1715 | mdelay(5); |
1716 | else if (addr == 0xfc) |
1717 | mdelay(1); |
1718 | else if (addr == 0xfb) |
1719 | usleep_range(min: 50, max: 60); |
1720 | else if (addr == 0xfa) |
1721 | udelay(5); |
1722 | else if (addr == 0xf9) |
1723 | udelay(1); |
1724 | else |
1725 | rtw_write32(rtwdev, addr, val: data); |
1726 | } |
1727 | EXPORT_SYMBOL(rtw_phy_cfg_bb); |
1728 | |
1729 | void rtw_phy_cfg_rf(struct rtw_dev *rtwdev, const struct rtw_table *tbl, |
1730 | u32 addr, u32 data) |
1731 | { |
1732 | if (addr == 0xffe) { |
1733 | msleep(msecs: 50); |
1734 | } else if (addr == 0xfe) { |
1735 | usleep_range(min: 100, max: 110); |
1736 | } else { |
1737 | rtw_write_rf(rtwdev, rf_path: tbl->rf_path, addr, RFREG_MASK, data); |
1738 | udelay(1); |
1739 | } |
1740 | } |
1741 | EXPORT_SYMBOL(rtw_phy_cfg_rf); |
1742 | |
1743 | static void rtw_load_rfk_table(struct rtw_dev *rtwdev) |
1744 | { |
1745 | const struct rtw_chip_info *chip = rtwdev->chip; |
1746 | struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info; |
1747 | |
1748 | if (!chip->rfk_init_tbl) |
1749 | return; |
1750 | |
1751 | rtw_write32_mask(rtwdev, addr: 0x1e24, BIT(17), data: 0x1); |
1752 | rtw_write32_mask(rtwdev, addr: 0x1cd0, BIT(28), data: 0x1); |
1753 | rtw_write32_mask(rtwdev, addr: 0x1cd0, BIT(29), data: 0x1); |
1754 | rtw_write32_mask(rtwdev, addr: 0x1cd0, BIT(30), data: 0x1); |
1755 | rtw_write32_mask(rtwdev, addr: 0x1cd0, BIT(31), data: 0x0); |
1756 | |
1757 | rtw_load_table(rtwdev, tbl: chip->rfk_init_tbl); |
1758 | |
1759 | dpk_info->is_dpk_pwr_on = true; |
1760 | } |
1761 | |
1762 | void rtw_phy_load_tables(struct rtw_dev *rtwdev) |
1763 | { |
1764 | const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); |
1765 | const struct rtw_chip_info *chip = rtwdev->chip; |
1766 | u8 rf_path; |
1767 | |
1768 | rtw_load_table(rtwdev, tbl: chip->mac_tbl); |
1769 | rtw_load_table(rtwdev, tbl: chip->bb_tbl); |
1770 | rtw_load_table(rtwdev, tbl: chip->agc_tbl); |
1771 | if (rfe_def->agc_btg_tbl) |
1772 | rtw_load_table(rtwdev, tbl: rfe_def->agc_btg_tbl); |
1773 | rtw_load_rfk_table(rtwdev); |
1774 | |
1775 | for (rf_path = 0; rf_path < rtwdev->hal.rf_path_num; rf_path++) { |
1776 | const struct rtw_table *tbl; |
1777 | |
1778 | tbl = chip->rf_tbl[rf_path]; |
1779 | rtw_load_table(rtwdev, tbl); |
1780 | } |
1781 | } |
1782 | EXPORT_SYMBOL(rtw_phy_load_tables); |
1783 | |
1784 | static u8 rtw_get_channel_group(u8 channel, u8 rate) |
1785 | { |
1786 | switch (channel) { |
1787 | default: |
1788 | WARN_ON(1); |
1789 | fallthrough; |
1790 | case 1: |
1791 | case 2: |
1792 | case 36: |
1793 | case 38: |
1794 | case 40: |
1795 | case 42: |
1796 | return 0; |
1797 | case 3: |
1798 | case 4: |
1799 | case 5: |
1800 | case 44: |
1801 | case 46: |
1802 | case 48: |
1803 | case 50: |
1804 | return 1; |
1805 | case 6: |
1806 | case 7: |
1807 | case 8: |
1808 | case 52: |
1809 | case 54: |
1810 | case 56: |
1811 | case 58: |
1812 | return 2; |
1813 | case 9: |
1814 | case 10: |
1815 | case 11: |
1816 | case 60: |
1817 | case 62: |
1818 | case 64: |
1819 | return 3; |
1820 | case 12: |
1821 | case 13: |
1822 | case 100: |
1823 | case 102: |
1824 | case 104: |
1825 | case 106: |
1826 | return 4; |
1827 | case 14: |
1828 | return rate <= DESC_RATE11M ? 5 : 4; |
1829 | case 108: |
1830 | case 110: |
1831 | case 112: |
1832 | case 114: |
1833 | return 5; |
1834 | case 116: |
1835 | case 118: |
1836 | case 120: |
1837 | case 122: |
1838 | return 6; |
1839 | case 124: |
1840 | case 126: |
1841 | case 128: |
1842 | case 130: |
1843 | return 7; |
1844 | case 132: |
1845 | case 134: |
1846 | case 136: |
1847 | case 138: |
1848 | return 8; |
1849 | case 140: |
1850 | case 142: |
1851 | case 144: |
1852 | return 9; |
1853 | case 149: |
1854 | case 151: |
1855 | case 153: |
1856 | case 155: |
1857 | return 10; |
1858 | case 157: |
1859 | case 159: |
1860 | case 161: |
1861 | return 11; |
1862 | case 165: |
1863 | case 167: |
1864 | case 169: |
1865 | case 171: |
1866 | return 12; |
1867 | case 173: |
1868 | case 175: |
1869 | case 177: |
1870 | return 13; |
1871 | } |
1872 | } |
1873 | |
1874 | static s8 rtw_phy_get_dis_dpd_by_rate_diff(struct rtw_dev *rtwdev, u16 rate) |
1875 | { |
1876 | const struct rtw_chip_info *chip = rtwdev->chip; |
1877 | s8 dpd_diff = 0; |
1878 | |
1879 | if (!chip->en_dis_dpd) |
1880 | return 0; |
1881 | |
1882 | #define RTW_DPD_RATE_CHECK(_rate) \ |
1883 | case DESC_RATE ## _rate: \ |
1884 | if (DIS_DPD_RATE ## _rate & chip->dpd_ratemask) \ |
1885 | dpd_diff = -6 * chip->txgi_factor; \ |
1886 | break |
1887 | |
1888 | switch (rate) { |
1889 | RTW_DPD_RATE_CHECK(6M); |
1890 | RTW_DPD_RATE_CHECK(9M); |
1891 | RTW_DPD_RATE_CHECK(MCS0); |
1892 | RTW_DPD_RATE_CHECK(MCS1); |
1893 | RTW_DPD_RATE_CHECK(MCS8); |
1894 | RTW_DPD_RATE_CHECK(MCS9); |
1895 | RTW_DPD_RATE_CHECK(VHT1SS_MCS0); |
1896 | RTW_DPD_RATE_CHECK(VHT1SS_MCS1); |
1897 | RTW_DPD_RATE_CHECK(VHT2SS_MCS0); |
1898 | RTW_DPD_RATE_CHECK(VHT2SS_MCS1); |
1899 | } |
1900 | #undef RTW_DPD_RATE_CHECK |
1901 | |
1902 | return dpd_diff; |
1903 | } |
1904 | |
1905 | static u8 rtw_phy_get_2g_tx_power_index(struct rtw_dev *rtwdev, |
1906 | struct rtw_2g_txpwr_idx *pwr_idx_2g, |
1907 | enum rtw_bandwidth bandwidth, |
1908 | u8 rate, u8 group) |
1909 | { |
1910 | const struct rtw_chip_info *chip = rtwdev->chip; |
1911 | u8 tx_power; |
1912 | bool mcs_rate; |
1913 | bool above_2ss; |
1914 | u8 factor = chip->txgi_factor; |
1915 | |
1916 | if (rate <= DESC_RATE11M) |
1917 | tx_power = pwr_idx_2g->cck_base[group]; |
1918 | else |
1919 | tx_power = pwr_idx_2g->bw40_base[group]; |
1920 | |
1921 | if (rate >= DESC_RATE6M && rate <= DESC_RATE54M) |
1922 | tx_power += pwr_idx_2g->ht_1s_diff.ofdm * factor; |
1923 | |
1924 | mcs_rate = (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) || |
1925 | (rate >= DESC_RATEVHT1SS_MCS0 && |
1926 | rate <= DESC_RATEVHT2SS_MCS9); |
1927 | above_2ss = (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) || |
1928 | (rate >= DESC_RATEVHT2SS_MCS0); |
1929 | |
1930 | if (!mcs_rate) |
1931 | return tx_power; |
1932 | |
1933 | switch (bandwidth) { |
1934 | default: |
1935 | WARN_ON(1); |
1936 | fallthrough; |
1937 | case RTW_CHANNEL_WIDTH_20: |
1938 | tx_power += pwr_idx_2g->ht_1s_diff.bw20 * factor; |
1939 | if (above_2ss) |
1940 | tx_power += pwr_idx_2g->ht_2s_diff.bw20 * factor; |
1941 | break; |
1942 | case RTW_CHANNEL_WIDTH_40: |
1943 | /* bw40 is the base power */ |
1944 | if (above_2ss) |
1945 | tx_power += pwr_idx_2g->ht_2s_diff.bw40 * factor; |
1946 | break; |
1947 | } |
1948 | |
1949 | return tx_power; |
1950 | } |
1951 | |
1952 | static u8 rtw_phy_get_5g_tx_power_index(struct rtw_dev *rtwdev, |
1953 | struct rtw_5g_txpwr_idx *pwr_idx_5g, |
1954 | enum rtw_bandwidth bandwidth, |
1955 | u8 rate, u8 group) |
1956 | { |
1957 | const struct rtw_chip_info *chip = rtwdev->chip; |
1958 | u8 tx_power; |
1959 | u8 upper, lower; |
1960 | bool mcs_rate; |
1961 | bool above_2ss; |
1962 | u8 factor = chip->txgi_factor; |
1963 | |
1964 | tx_power = pwr_idx_5g->bw40_base[group]; |
1965 | |
1966 | mcs_rate = (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS15) || |
1967 | (rate >= DESC_RATEVHT1SS_MCS0 && |
1968 | rate <= DESC_RATEVHT2SS_MCS9); |
1969 | above_2ss = (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) || |
1970 | (rate >= DESC_RATEVHT2SS_MCS0); |
1971 | |
1972 | if (!mcs_rate) { |
1973 | tx_power += pwr_idx_5g->ht_1s_diff.ofdm * factor; |
1974 | return tx_power; |
1975 | } |
1976 | |
1977 | switch (bandwidth) { |
1978 | default: |
1979 | WARN_ON(1); |
1980 | fallthrough; |
1981 | case RTW_CHANNEL_WIDTH_20: |
1982 | tx_power += pwr_idx_5g->ht_1s_diff.bw20 * factor; |
1983 | if (above_2ss) |
1984 | tx_power += pwr_idx_5g->ht_2s_diff.bw20 * factor; |
1985 | break; |
1986 | case RTW_CHANNEL_WIDTH_40: |
1987 | /* bw40 is the base power */ |
1988 | if (above_2ss) |
1989 | tx_power += pwr_idx_5g->ht_2s_diff.bw40 * factor; |
1990 | break; |
1991 | case RTW_CHANNEL_WIDTH_80: |
1992 | /* the base idx of bw80 is the average of bw40+/bw40- */ |
1993 | lower = pwr_idx_5g->bw40_base[group]; |
1994 | upper = pwr_idx_5g->bw40_base[group + 1]; |
1995 | |
1996 | tx_power = (lower + upper) / 2; |
1997 | tx_power += pwr_idx_5g->vht_1s_diff.bw80 * factor; |
1998 | if (above_2ss) |
1999 | tx_power += pwr_idx_5g->vht_2s_diff.bw80 * factor; |
2000 | break; |
2001 | } |
2002 | |
2003 | return tx_power; |
2004 | } |
2005 | |
2006 | /* return RTW_RATE_SECTION_MAX to indicate rate is invalid */ |
2007 | static u8 rtw_phy_rate_to_rate_section(u8 rate) |
2008 | { |
2009 | if (rate >= DESC_RATE1M && rate <= DESC_RATE11M) |
2010 | return RTW_RATE_SECTION_CCK; |
2011 | else if (rate >= DESC_RATE6M && rate <= DESC_RATE54M) |
2012 | return RTW_RATE_SECTION_OFDM; |
2013 | else if (rate >= DESC_RATEMCS0 && rate <= DESC_RATEMCS7) |
2014 | return RTW_RATE_SECTION_HT_1S; |
2015 | else if (rate >= DESC_RATEMCS8 && rate <= DESC_RATEMCS15) |
2016 | return RTW_RATE_SECTION_HT_2S; |
2017 | else if (rate >= DESC_RATEVHT1SS_MCS0 && rate <= DESC_RATEVHT1SS_MCS9) |
2018 | return RTW_RATE_SECTION_VHT_1S; |
2019 | else if (rate >= DESC_RATEVHT2SS_MCS0 && rate <= DESC_RATEVHT2SS_MCS9) |
2020 | return RTW_RATE_SECTION_VHT_2S; |
2021 | else |
2022 | return RTW_RATE_SECTION_MAX; |
2023 | } |
2024 | |
2025 | static s8 rtw_phy_get_tx_power_limit(struct rtw_dev *rtwdev, u8 band, |
2026 | enum rtw_bandwidth bw, u8 rf_path, |
2027 | u8 rate, u8 channel, u8 regd) |
2028 | { |
2029 | struct rtw_hal *hal = &rtwdev->hal; |
2030 | u8 *cch_by_bw = hal->cch_by_bw; |
2031 | s8 power_limit = (s8)rtwdev->chip->max_power_index; |
2032 | u8 rs = rtw_phy_rate_to_rate_section(rate); |
2033 | int ch_idx; |
2034 | u8 cur_bw, cur_ch; |
2035 | s8 cur_lmt; |
2036 | |
2037 | if (regd > RTW_REGD_WW) |
2038 | return power_limit; |
2039 | |
2040 | if (rs == RTW_RATE_SECTION_MAX) |
2041 | goto err; |
2042 | |
2043 | /* only 20M BW with cck and ofdm */ |
2044 | if (rs == RTW_RATE_SECTION_CCK || rs == RTW_RATE_SECTION_OFDM) |
2045 | bw = RTW_CHANNEL_WIDTH_20; |
2046 | |
2047 | /* only 20/40M BW with ht */ |
2048 | if (rs == RTW_RATE_SECTION_HT_1S || rs == RTW_RATE_SECTION_HT_2S) |
2049 | bw = min_t(u8, bw, RTW_CHANNEL_WIDTH_40); |
2050 | |
2051 | /* select min power limit among [20M BW ~ current BW] */ |
2052 | for (cur_bw = RTW_CHANNEL_WIDTH_20; cur_bw <= bw; cur_bw++) { |
2053 | cur_ch = cch_by_bw[cur_bw]; |
2054 | |
2055 | ch_idx = rtw_channel_to_idx(band, channel: cur_ch); |
2056 | if (ch_idx < 0) |
2057 | goto err; |
2058 | |
2059 | cur_lmt = cur_ch <= RTW_MAX_CHANNEL_NUM_2G ? |
2060 | hal->tx_pwr_limit_2g[regd][cur_bw][rs][ch_idx] : |
2061 | hal->tx_pwr_limit_5g[regd][cur_bw][rs][ch_idx]; |
2062 | |
2063 | power_limit = min_t(s8, cur_lmt, power_limit); |
2064 | } |
2065 | |
2066 | return power_limit; |
2067 | |
2068 | err: |
2069 | WARN(1, "invalid arguments, band=%d, bw=%d, path=%d, rate=%d, ch=%d\n" , |
2070 | band, bw, rf_path, rate, channel); |
2071 | return (s8)rtwdev->chip->max_power_index; |
2072 | } |
2073 | |
2074 | static s8 rtw_phy_get_tx_power_sar(struct rtw_dev *rtwdev, u8 sar_band, |
2075 | u8 rf_path, u8 rate) |
2076 | { |
2077 | u8 rs = rtw_phy_rate_to_rate_section(rate); |
2078 | struct rtw_sar_arg arg = { |
2079 | .sar_band = sar_band, |
2080 | .path = rf_path, |
2081 | .rs = rs, |
2082 | }; |
2083 | |
2084 | if (rs == RTW_RATE_SECTION_MAX) |
2085 | goto err; |
2086 | |
2087 | return rtw_query_sar(rtwdev, arg: &arg); |
2088 | |
2089 | err: |
2090 | WARN(1, "invalid arguments, sar_band=%d, path=%d, rate=%d\n" , |
2091 | sar_band, rf_path, rate); |
2092 | return (s8)rtwdev->chip->max_power_index; |
2093 | } |
2094 | |
2095 | void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, |
2096 | u8 ch, u8 regd, struct rtw_power_params *pwr_param) |
2097 | { |
2098 | struct rtw_hal *hal = &rtwdev->hal; |
2099 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
2100 | struct rtw_txpwr_idx *pwr_idx; |
2101 | u8 group, band; |
2102 | u8 *base = &pwr_param->pwr_base; |
2103 | s8 *offset = &pwr_param->pwr_offset; |
2104 | s8 *limit = &pwr_param->pwr_limit; |
2105 | s8 *remnant = &pwr_param->pwr_remnant; |
2106 | s8 *sar = &pwr_param->pwr_sar; |
2107 | |
2108 | pwr_idx = &rtwdev->efuse.txpwr_idx_table[path]; |
2109 | group = rtw_get_channel_group(channel: ch, rate); |
2110 | |
2111 | /* base power index for 2.4G/5G */ |
2112 | if (IS_CH_2G_BAND(ch)) { |
2113 | band = PHY_BAND_2G; |
2114 | *base = rtw_phy_get_2g_tx_power_index(rtwdev, |
2115 | pwr_idx_2g: &pwr_idx->pwr_idx_2g, |
2116 | bandwidth: bw, rate, group); |
2117 | *offset = hal->tx_pwr_by_rate_offset_2g[path][rate]; |
2118 | } else { |
2119 | band = PHY_BAND_5G; |
2120 | *base = rtw_phy_get_5g_tx_power_index(rtwdev, |
2121 | pwr_idx_5g: &pwr_idx->pwr_idx_5g, |
2122 | bandwidth: bw, rate, group); |
2123 | *offset = hal->tx_pwr_by_rate_offset_5g[path][rate]; |
2124 | } |
2125 | |
2126 | *limit = rtw_phy_get_tx_power_limit(rtwdev, band, bw, rf_path: path, |
2127 | rate, channel: ch, regd); |
2128 | *remnant = (rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck : |
2129 | dm_info->txagc_remnant_ofdm); |
2130 | *sar = rtw_phy_get_tx_power_sar(rtwdev, sar_band: hal->sar_band, rf_path: path, rate); |
2131 | } |
2132 | |
2133 | u8 |
2134 | rtw_phy_get_tx_power_index(struct rtw_dev *rtwdev, u8 rf_path, u8 rate, |
2135 | enum rtw_bandwidth bandwidth, u8 channel, u8 regd) |
2136 | { |
2137 | struct rtw_power_params pwr_param = {0}; |
2138 | u8 tx_power; |
2139 | s8 offset; |
2140 | |
2141 | rtw_get_tx_power_params(rtwdev, path: rf_path, rate, bw: bandwidth, |
2142 | ch: channel, regd, pwr_param: &pwr_param); |
2143 | |
2144 | tx_power = pwr_param.pwr_base; |
2145 | offset = min3(pwr_param.pwr_offset, |
2146 | pwr_param.pwr_limit, |
2147 | pwr_param.pwr_sar); |
2148 | |
2149 | if (rtwdev->chip->en_dis_dpd) |
2150 | offset += rtw_phy_get_dis_dpd_by_rate_diff(rtwdev, rate); |
2151 | |
2152 | tx_power += offset + pwr_param.pwr_remnant; |
2153 | |
2154 | if (tx_power > rtwdev->chip->max_power_index) |
2155 | tx_power = rtwdev->chip->max_power_index; |
2156 | |
2157 | return tx_power; |
2158 | } |
2159 | EXPORT_SYMBOL(rtw_phy_get_tx_power_index); |
2160 | |
2161 | static void rtw_phy_set_tx_power_index_by_rs(struct rtw_dev *rtwdev, |
2162 | u8 ch, u8 path, u8 rs) |
2163 | { |
2164 | struct rtw_hal *hal = &rtwdev->hal; |
2165 | u8 regd = rtw_regd_get(rtwdev); |
2166 | u8 *rates; |
2167 | u8 size; |
2168 | u8 rate; |
2169 | u8 pwr_idx; |
2170 | u8 bw; |
2171 | int i; |
2172 | |
2173 | if (rs >= RTW_RATE_SECTION_MAX) |
2174 | return; |
2175 | |
2176 | rates = rtw_rate_section[rs]; |
2177 | size = rtw_rate_size[rs]; |
2178 | bw = hal->current_band_width; |
2179 | for (i = 0; i < size; i++) { |
2180 | rate = rates[i]; |
2181 | pwr_idx = rtw_phy_get_tx_power_index(rtwdev, path, rate, |
2182 | bw, ch, regd); |
2183 | hal->tx_pwr_tbl[path][rate] = pwr_idx; |
2184 | } |
2185 | } |
2186 | |
2187 | /* set tx power level by path for each rates, note that the order of the rates |
2188 | * are *very* important, bacause 8822B/8821C combines every four bytes of tx |
2189 | * power index into a four-byte power index register, and calls set_tx_agc to |
2190 | * write these values into hardware |
2191 | */ |
2192 | static void rtw_phy_set_tx_power_level_by_path(struct rtw_dev *rtwdev, |
2193 | u8 ch, u8 path) |
2194 | { |
2195 | struct rtw_hal *hal = &rtwdev->hal; |
2196 | u8 rs; |
2197 | |
2198 | /* do not need cck rates if we are not in 2.4G */ |
2199 | if (hal->current_band_type == RTW_BAND_2G) |
2200 | rs = RTW_RATE_SECTION_CCK; |
2201 | else |
2202 | rs = RTW_RATE_SECTION_OFDM; |
2203 | |
2204 | for (; rs < RTW_RATE_SECTION_MAX; rs++) |
2205 | rtw_phy_set_tx_power_index_by_rs(rtwdev, ch, path, rs); |
2206 | } |
2207 | |
2208 | void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel) |
2209 | { |
2210 | const struct rtw_chip_info *chip = rtwdev->chip; |
2211 | struct rtw_hal *hal = &rtwdev->hal; |
2212 | u8 path; |
2213 | |
2214 | mutex_lock(&hal->tx_power_mutex); |
2215 | |
2216 | for (path = 0; path < hal->rf_path_num; path++) |
2217 | rtw_phy_set_tx_power_level_by_path(rtwdev, ch: channel, path); |
2218 | |
2219 | chip->ops->set_tx_power_index(rtwdev); |
2220 | mutex_unlock(lock: &hal->tx_power_mutex); |
2221 | } |
2222 | EXPORT_SYMBOL(rtw_phy_set_tx_power_level); |
2223 | |
2224 | static void |
2225 | rtw_phy_tx_power_by_rate_config_by_path(struct rtw_hal *hal, u8 path, |
2226 | u8 rs, u8 size, u8 *rates) |
2227 | { |
2228 | u8 rate; |
2229 | u8 base_idx, rate_idx; |
2230 | s8 base_2g, base_5g; |
2231 | |
2232 | if (rs >= RTW_RATE_SECTION_VHT_1S) |
2233 | base_idx = rates[size - 3]; |
2234 | else |
2235 | base_idx = rates[size - 1]; |
2236 | base_2g = hal->tx_pwr_by_rate_offset_2g[path][base_idx]; |
2237 | base_5g = hal->tx_pwr_by_rate_offset_5g[path][base_idx]; |
2238 | hal->tx_pwr_by_rate_base_2g[path][rs] = base_2g; |
2239 | hal->tx_pwr_by_rate_base_5g[path][rs] = base_5g; |
2240 | for (rate = 0; rate < size; rate++) { |
2241 | rate_idx = rates[rate]; |
2242 | hal->tx_pwr_by_rate_offset_2g[path][rate_idx] -= base_2g; |
2243 | hal->tx_pwr_by_rate_offset_5g[path][rate_idx] -= base_5g; |
2244 | } |
2245 | } |
2246 | |
2247 | void rtw_phy_tx_power_by_rate_config(struct rtw_hal *hal) |
2248 | { |
2249 | u8 path; |
2250 | |
2251 | for (path = 0; path < RTW_RF_PATH_MAX; path++) { |
2252 | rtw_phy_tx_power_by_rate_config_by_path(hal, path, |
2253 | rs: RTW_RATE_SECTION_CCK, |
2254 | size: rtw_cck_size, rates: rtw_cck_rates); |
2255 | rtw_phy_tx_power_by_rate_config_by_path(hal, path, |
2256 | rs: RTW_RATE_SECTION_OFDM, |
2257 | size: rtw_ofdm_size, rates: rtw_ofdm_rates); |
2258 | rtw_phy_tx_power_by_rate_config_by_path(hal, path, |
2259 | rs: RTW_RATE_SECTION_HT_1S, |
2260 | size: rtw_ht_1s_size, rates: rtw_ht_1s_rates); |
2261 | rtw_phy_tx_power_by_rate_config_by_path(hal, path, |
2262 | rs: RTW_RATE_SECTION_HT_2S, |
2263 | size: rtw_ht_2s_size, rates: rtw_ht_2s_rates); |
2264 | rtw_phy_tx_power_by_rate_config_by_path(hal, path, |
2265 | rs: RTW_RATE_SECTION_VHT_1S, |
2266 | size: rtw_vht_1s_size, rates: rtw_vht_1s_rates); |
2267 | rtw_phy_tx_power_by_rate_config_by_path(hal, path, |
2268 | rs: RTW_RATE_SECTION_VHT_2S, |
2269 | size: rtw_vht_2s_size, rates: rtw_vht_2s_rates); |
2270 | } |
2271 | } |
2272 | |
2273 | static void |
2274 | __rtw_phy_tx_power_limit_config(struct rtw_hal *hal, u8 regd, u8 bw, u8 rs) |
2275 | { |
2276 | s8 base; |
2277 | u8 ch; |
2278 | |
2279 | for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_2G; ch++) { |
2280 | base = hal->tx_pwr_by_rate_base_2g[0][rs]; |
2281 | hal->tx_pwr_limit_2g[regd][bw][rs][ch] -= base; |
2282 | } |
2283 | |
2284 | for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_5G; ch++) { |
2285 | base = hal->tx_pwr_by_rate_base_5g[0][rs]; |
2286 | hal->tx_pwr_limit_5g[regd][bw][rs][ch] -= base; |
2287 | } |
2288 | } |
2289 | |
2290 | void rtw_phy_tx_power_limit_config(struct rtw_hal *hal) |
2291 | { |
2292 | u8 regd, bw, rs; |
2293 | |
2294 | /* default at channel 1 */ |
2295 | hal->cch_by_bw[RTW_CHANNEL_WIDTH_20] = 1; |
2296 | |
2297 | for (regd = 0; regd < RTW_REGD_MAX; regd++) |
2298 | for (bw = 0; bw < RTW_CHANNEL_WIDTH_MAX; bw++) |
2299 | for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) |
2300 | __rtw_phy_tx_power_limit_config(hal, regd, bw, rs); |
2301 | } |
2302 | |
2303 | static void rtw_phy_init_tx_power_limit(struct rtw_dev *rtwdev, |
2304 | u8 regd, u8 bw, u8 rs) |
2305 | { |
2306 | struct rtw_hal *hal = &rtwdev->hal; |
2307 | s8 max_power_index = (s8)rtwdev->chip->max_power_index; |
2308 | u8 ch; |
2309 | |
2310 | /* 2.4G channels */ |
2311 | for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_2G; ch++) |
2312 | hal->tx_pwr_limit_2g[regd][bw][rs][ch] = max_power_index; |
2313 | |
2314 | /* 5G channels */ |
2315 | for (ch = 0; ch < RTW_MAX_CHANNEL_NUM_5G; ch++) |
2316 | hal->tx_pwr_limit_5g[regd][bw][rs][ch] = max_power_index; |
2317 | } |
2318 | |
2319 | void rtw_phy_init_tx_power(struct rtw_dev *rtwdev) |
2320 | { |
2321 | struct rtw_hal *hal = &rtwdev->hal; |
2322 | u8 regd, path, rate, rs, bw; |
2323 | |
2324 | /* init tx power by rate offset */ |
2325 | for (path = 0; path < RTW_RF_PATH_MAX; path++) { |
2326 | for (rate = 0; rate < DESC_RATE_MAX; rate++) { |
2327 | hal->tx_pwr_by_rate_offset_2g[path][rate] = 0; |
2328 | hal->tx_pwr_by_rate_offset_5g[path][rate] = 0; |
2329 | } |
2330 | } |
2331 | |
2332 | /* init tx power limit */ |
2333 | for (regd = 0; regd < RTW_REGD_MAX; regd++) |
2334 | for (bw = 0; bw < RTW_CHANNEL_WIDTH_MAX; bw++) |
2335 | for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) |
2336 | rtw_phy_init_tx_power_limit(rtwdev, regd, bw, |
2337 | rs); |
2338 | } |
2339 | |
2340 | void rtw_phy_config_swing_table(struct rtw_dev *rtwdev, |
2341 | struct rtw_swing_table *swing_table) |
2342 | { |
2343 | const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl; |
2344 | u8 channel = rtwdev->hal.current_channel; |
2345 | |
2346 | if (IS_CH_2G_BAND(channel)) { |
2347 | if (rtwdev->dm_info.tx_rate <= DESC_RATE11M) { |
2348 | swing_table->p[RF_PATH_A] = tbl->pwrtrk_2g_ccka_p; |
2349 | swing_table->n[RF_PATH_A] = tbl->pwrtrk_2g_ccka_n; |
2350 | swing_table->p[RF_PATH_B] = tbl->pwrtrk_2g_cckb_p; |
2351 | swing_table->n[RF_PATH_B] = tbl->pwrtrk_2g_cckb_n; |
2352 | } else { |
2353 | swing_table->p[RF_PATH_A] = tbl->pwrtrk_2ga_p; |
2354 | swing_table->n[RF_PATH_A] = tbl->pwrtrk_2ga_n; |
2355 | swing_table->p[RF_PATH_B] = tbl->pwrtrk_2gb_p; |
2356 | swing_table->n[RF_PATH_B] = tbl->pwrtrk_2gb_n; |
2357 | } |
2358 | } else if (IS_CH_5G_BAND_1(channel) || IS_CH_5G_BAND_2(channel)) { |
2359 | swing_table->p[RF_PATH_A] = tbl->pwrtrk_5ga_p[RTW_PWR_TRK_5G_1]; |
2360 | swing_table->n[RF_PATH_A] = tbl->pwrtrk_5ga_n[RTW_PWR_TRK_5G_1]; |
2361 | swing_table->p[RF_PATH_B] = tbl->pwrtrk_5gb_p[RTW_PWR_TRK_5G_1]; |
2362 | swing_table->n[RF_PATH_B] = tbl->pwrtrk_5gb_n[RTW_PWR_TRK_5G_1]; |
2363 | } else if (IS_CH_5G_BAND_3(channel)) { |
2364 | swing_table->p[RF_PATH_A] = tbl->pwrtrk_5ga_p[RTW_PWR_TRK_5G_2]; |
2365 | swing_table->n[RF_PATH_A] = tbl->pwrtrk_5ga_n[RTW_PWR_TRK_5G_2]; |
2366 | swing_table->p[RF_PATH_B] = tbl->pwrtrk_5gb_p[RTW_PWR_TRK_5G_2]; |
2367 | swing_table->n[RF_PATH_B] = tbl->pwrtrk_5gb_n[RTW_PWR_TRK_5G_2]; |
2368 | } else if (IS_CH_5G_BAND_4(channel)) { |
2369 | swing_table->p[RF_PATH_A] = tbl->pwrtrk_5ga_p[RTW_PWR_TRK_5G_3]; |
2370 | swing_table->n[RF_PATH_A] = tbl->pwrtrk_5ga_n[RTW_PWR_TRK_5G_3]; |
2371 | swing_table->p[RF_PATH_B] = tbl->pwrtrk_5gb_p[RTW_PWR_TRK_5G_3]; |
2372 | swing_table->n[RF_PATH_B] = tbl->pwrtrk_5gb_n[RTW_PWR_TRK_5G_3]; |
2373 | } else { |
2374 | swing_table->p[RF_PATH_A] = tbl->pwrtrk_2ga_p; |
2375 | swing_table->n[RF_PATH_A] = tbl->pwrtrk_2ga_n; |
2376 | swing_table->p[RF_PATH_B] = tbl->pwrtrk_2gb_p; |
2377 | swing_table->n[RF_PATH_B] = tbl->pwrtrk_2gb_n; |
2378 | } |
2379 | } |
2380 | EXPORT_SYMBOL(rtw_phy_config_swing_table); |
2381 | |
2382 | void rtw_phy_pwrtrack_avg(struct rtw_dev *rtwdev, u8 thermal, u8 path) |
2383 | { |
2384 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
2385 | |
2386 | ewma_thermal_add(e: &dm_info->avg_thermal[path], val: thermal); |
2387 | dm_info->thermal_avg[path] = |
2388 | ewma_thermal_read(e: &dm_info->avg_thermal[path]); |
2389 | } |
2390 | EXPORT_SYMBOL(rtw_phy_pwrtrack_avg); |
2391 | |
2392 | bool rtw_phy_pwrtrack_thermal_changed(struct rtw_dev *rtwdev, u8 thermal, |
2393 | u8 path) |
2394 | { |
2395 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
2396 | u8 avg = ewma_thermal_read(e: &dm_info->avg_thermal[path]); |
2397 | |
2398 | if (avg == thermal) |
2399 | return false; |
2400 | |
2401 | return true; |
2402 | } |
2403 | EXPORT_SYMBOL(rtw_phy_pwrtrack_thermal_changed); |
2404 | |
2405 | u8 rtw_phy_pwrtrack_get_delta(struct rtw_dev *rtwdev, u8 path) |
2406 | { |
2407 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
2408 | u8 therm_avg, therm_efuse, therm_delta; |
2409 | |
2410 | therm_avg = dm_info->thermal_avg[path]; |
2411 | therm_efuse = rtwdev->efuse.thermal_meter[path]; |
2412 | therm_delta = abs(therm_avg - therm_efuse); |
2413 | |
2414 | return min_t(u8, therm_delta, RTW_PWR_TRK_TBL_SZ - 1); |
2415 | } |
2416 | EXPORT_SYMBOL(rtw_phy_pwrtrack_get_delta); |
2417 | |
2418 | s8 rtw_phy_pwrtrack_get_pwridx(struct rtw_dev *rtwdev, |
2419 | struct rtw_swing_table *swing_table, |
2420 | u8 tbl_path, u8 therm_path, u8 delta) |
2421 | { |
2422 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
2423 | const u8 *delta_swing_table_idx_pos; |
2424 | const u8 *delta_swing_table_idx_neg; |
2425 | |
2426 | if (delta >= RTW_PWR_TRK_TBL_SZ) { |
2427 | rtw_warn(rtwdev, "power track table overflow\n" ); |
2428 | return 0; |
2429 | } |
2430 | |
2431 | if (!swing_table) { |
2432 | rtw_warn(rtwdev, "swing table not configured\n" ); |
2433 | return 0; |
2434 | } |
2435 | |
2436 | delta_swing_table_idx_pos = swing_table->p[tbl_path]; |
2437 | delta_swing_table_idx_neg = swing_table->n[tbl_path]; |
2438 | |
2439 | if (!delta_swing_table_idx_pos || !delta_swing_table_idx_neg) { |
2440 | rtw_warn(rtwdev, "invalid swing table index\n" ); |
2441 | return 0; |
2442 | } |
2443 | |
2444 | if (dm_info->thermal_avg[therm_path] > |
2445 | rtwdev->efuse.thermal_meter[therm_path]) |
2446 | return delta_swing_table_idx_pos[delta]; |
2447 | else |
2448 | return -delta_swing_table_idx_neg[delta]; |
2449 | } |
2450 | EXPORT_SYMBOL(rtw_phy_pwrtrack_get_pwridx); |
2451 | |
2452 | bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev) |
2453 | { |
2454 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
2455 | u8 delta_lck; |
2456 | |
2457 | delta_lck = abs(dm_info->thermal_avg[0] - dm_info->thermal_meter_lck); |
2458 | if (delta_lck >= rtwdev->chip->lck_threshold) { |
2459 | dm_info->thermal_meter_lck = dm_info->thermal_avg[0]; |
2460 | return true; |
2461 | } |
2462 | return false; |
2463 | } |
2464 | EXPORT_SYMBOL(rtw_phy_pwrtrack_need_lck); |
2465 | |
2466 | bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev) |
2467 | { |
2468 | struct rtw_dm_info *dm_info = &rtwdev->dm_info; |
2469 | u8 delta_iqk; |
2470 | |
2471 | delta_iqk = abs(dm_info->thermal_avg[0] - dm_info->thermal_meter_k); |
2472 | if (delta_iqk >= rtwdev->chip->iqk_threshold) { |
2473 | dm_info->thermal_meter_k = dm_info->thermal_avg[0]; |
2474 | return true; |
2475 | } |
2476 | return false; |
2477 | } |
2478 | EXPORT_SYMBOL(rtw_phy_pwrtrack_need_iqk); |
2479 | |
2480 | static void rtw_phy_set_tx_path_by_reg(struct rtw_dev *rtwdev, |
2481 | enum rtw_bb_path tx_path_sel_1ss) |
2482 | { |
2483 | struct rtw_path_div *path_div = &rtwdev->dm_path_div; |
2484 | enum rtw_bb_path tx_path_sel_cck = tx_path_sel_1ss; |
2485 | const struct rtw_chip_info *chip = rtwdev->chip; |
2486 | |
2487 | if (tx_path_sel_1ss == path_div->current_tx_path) |
2488 | return; |
2489 | |
2490 | path_div->current_tx_path = tx_path_sel_1ss; |
2491 | rtw_dbg(rtwdev, mask: RTW_DBG_PATH_DIV, fmt: "Switch TX path=%s\n" , |
2492 | tx_path_sel_1ss == BB_PATH_A ? "A" : "B" ); |
2493 | chip->ops->config_tx_path(rtwdev, rtwdev->hal.antenna_tx, |
2494 | tx_path_sel_1ss, tx_path_sel_cck, false); |
2495 | } |
2496 | |
2497 | static void rtw_phy_tx_path_div_select(struct rtw_dev *rtwdev) |
2498 | { |
2499 | struct rtw_path_div *path_div = &rtwdev->dm_path_div; |
2500 | enum rtw_bb_path path = path_div->current_tx_path; |
2501 | s32 = 0, = 0; |
2502 | |
2503 | if (path_div->path_a_cnt) |
2504 | rssi_a = path_div->path_a_sum / path_div->path_a_cnt; |
2505 | else |
2506 | rssi_a = 0; |
2507 | if (path_div->path_b_cnt) |
2508 | rssi_b = path_div->path_b_sum / path_div->path_b_cnt; |
2509 | else |
2510 | rssi_b = 0; |
2511 | |
2512 | if (rssi_a != rssi_b) |
2513 | path = (rssi_a > rssi_b) ? BB_PATH_A : BB_PATH_B; |
2514 | |
2515 | path_div->path_a_cnt = 0; |
2516 | path_div->path_a_sum = 0; |
2517 | path_div->path_b_cnt = 0; |
2518 | path_div->path_b_sum = 0; |
2519 | rtw_phy_set_tx_path_by_reg(rtwdev, tx_path_sel_1ss: path); |
2520 | } |
2521 | |
2522 | static void rtw_phy_tx_path_diversity_2ss(struct rtw_dev *rtwdev) |
2523 | { |
2524 | if (rtwdev->hal.antenna_rx != BB_PATH_AB) { |
2525 | rtw_dbg(rtwdev, mask: RTW_DBG_PATH_DIV, |
2526 | fmt: "[Return] tx_Path_en=%d, rx_Path_en=%d\n" , |
2527 | rtwdev->hal.antenna_tx, rtwdev->hal.antenna_rx); |
2528 | return; |
2529 | } |
2530 | if (rtwdev->sta_cnt == 0) { |
2531 | rtw_dbg(rtwdev, mask: RTW_DBG_PATH_DIV, fmt: "No Link\n" ); |
2532 | return; |
2533 | } |
2534 | |
2535 | rtw_phy_tx_path_div_select(rtwdev); |
2536 | } |
2537 | |
2538 | void rtw_phy_tx_path_diversity(struct rtw_dev *rtwdev) |
2539 | { |
2540 | const struct rtw_chip_info *chip = rtwdev->chip; |
2541 | |
2542 | if (!chip->path_div_supported) |
2543 | return; |
2544 | |
2545 | rtw_phy_tx_path_diversity_2ss(rtwdev); |
2546 | } |
2547 | |