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