Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / net / wireless / realtek / rtlwifi / rtl8821ae / rf.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2010  Realtek Corporation.*/
3
4 #include "../wifi.h"
5 #include "reg.h"
6 #include "def.h"
7 #include "phy.h"
8 #include "rf.h"
9 #include "dm.h"
10
11 static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
12
13 void rtl8821ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
14 {
15         switch (bandwidth) {
16         case HT_CHANNEL_WIDTH_20:
17                 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 3);
18                 rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 3);
19                 break;
20         case HT_CHANNEL_WIDTH_20_40:
21                 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 1);
22                 rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 1);
23                 break;
24         case HT_CHANNEL_WIDTH_80:
25                 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 0);
26                 rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 0);
27                 break;
28         default:
29                 pr_err("unknown bandwidth: %#X\n", bandwidth);
30                 break;
31         }
32 }
33
34 void rtl8821ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
35                                           u8 *ppowerlevel)
36 {
37         struct rtl_priv *rtlpriv = rtl_priv(hw);
38         struct rtl_phy *rtlphy = &rtlpriv->phy;
39         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
40         struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
41         u32 tx_agc[2] = {0, 0}, tmpval;
42         bool turbo_scanoff = false;
43         u8 idx1, idx2;
44         u8 *ptr;
45         u8 direction;
46         u32 pwrtrac_value;
47
48         if (rtlefuse->eeprom_regulatory != 0)
49                 turbo_scanoff = true;
50
51         if (mac->act_scanning) {
52                 tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
53                 tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
54
55                 if (turbo_scanoff) {
56                         for (idx1 = RF90_PATH_A;
57                                 idx1 <= RF90_PATH_B;
58                                 idx1++) {
59                                 tx_agc[idx1] = ppowerlevel[idx1] |
60                                     (ppowerlevel[idx1] << 8) |
61                                     (ppowerlevel[idx1] << 16) |
62                                     (ppowerlevel[idx1] << 24);
63                         }
64                 }
65         } else {
66                 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
67                         tx_agc[idx1] = ppowerlevel[idx1] |
68                             (ppowerlevel[idx1] << 8) |
69                             (ppowerlevel[idx1] << 16) |
70                             (ppowerlevel[idx1] << 24);
71                 }
72
73                 if (rtlefuse->eeprom_regulatory == 0) {
74                         tmpval =
75                             (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
76                             (rtlphy->mcs_txpwrlevel_origoffset[0][7] <<
77                              8);
78                         tx_agc[RF90_PATH_A] += tmpval;
79
80                         tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
81                             (rtlphy->mcs_txpwrlevel_origoffset[0][15] <<
82                              24);
83                         tx_agc[RF90_PATH_B] += tmpval;
84                 }
85         }
86
87         for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
88                 ptr = (u8 *)(&tx_agc[idx1]);
89                 for (idx2 = 0; idx2 < 4; idx2++) {
90                         if (*ptr > RF6052_MAX_TX_PWR)
91                                 *ptr = RF6052_MAX_TX_PWR;
92                         ptr++;
93                 }
94         }
95         rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
96         if (direction == 1) {
97                 tx_agc[0] += pwrtrac_value;
98                 tx_agc[1] += pwrtrac_value;
99         } else if (direction == 2) {
100                 tx_agc[0] -= pwrtrac_value;
101                 tx_agc[1] -= pwrtrac_value;
102         }
103         tmpval = tx_agc[RF90_PATH_A];
104         rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, MASKDWORD, tmpval);
105
106         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
107                 "CCK PWR 1~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
108                  RTXAGC_A_CCK11_CCK1);
109
110         tmpval = tx_agc[RF90_PATH_B];
111         rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, MASKDWORD, tmpval);
112
113         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
114                 "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
115                  RTXAGC_B_CCK11_CCK1);
116 }
117
118 static void rtl8821ae_phy_get_power_base(struct ieee80211_hw *hw,
119                                          u8 *ppowerlevel_ofdm,
120                                          u8 *ppowerlevel_bw20,
121                                          u8 *ppowerlevel_bw40, u8 channel,
122                                          u32 *ofdmbase, u32 *mcsbase)
123 {
124         struct rtl_priv *rtlpriv = rtl_priv(hw);
125         struct rtl_phy *rtlphy = &rtlpriv->phy;
126         u32 powerbase0, powerbase1;
127         u8 i, powerlevel[2];
128
129         for (i = 0; i < 2; i++) {
130                 powerbase0 = ppowerlevel_ofdm[i];
131
132                 powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
133                     (powerbase0 << 8) | powerbase0;
134                 *(ofdmbase + i) = powerbase0;
135                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
136                         " [OFDM power base index rf(%c) = 0x%x]\n",
137                          ((i == 0) ? 'A' : 'B'), *(ofdmbase + i));
138         }
139
140         for (i = 0; i < 2; i++) {
141                 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
142                         powerlevel[i] = ppowerlevel_bw20[i];
143                 else
144                         powerlevel[i] = ppowerlevel_bw40[i];
145
146                 powerbase1 = powerlevel[i];
147                 powerbase1 = (powerbase1 << 24) |
148                     (powerbase1 << 16) | (powerbase1 << 8) | powerbase1;
149
150                 *(mcsbase + i) = powerbase1;
151
152                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
153                         " [MCS power base index rf(%c) = 0x%x]\n",
154                          ((i == 0) ? 'A' : 'B'), *(mcsbase + i));
155         }
156 }
157
158 static void get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
159                                                u8 channel, u8 index,
160                                                u32 *powerbase0,
161                                                u32 *powerbase1,
162                                                u32 *p_outwriteval)
163 {
164         struct rtl_priv *rtlpriv = rtl_priv(hw);
165         struct rtl_phy *rtlphy = &rtlpriv->phy;
166         struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
167         u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff;
168         u32 writeval, customer_limit, rf;
169
170         for (rf = 0; rf < 2; rf++) {
171                 switch (rtlefuse->eeprom_regulatory) {
172                 case 0:
173                         chnlgroup = 0;
174
175                         writeval =
176                             rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index +
177                                                         (rf ? 8 : 0)]
178                             + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
179
180                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
181                                 "RTK better performance, writeval(%c) = 0x%x\n",
182                                  ((rf == 0) ? 'A' : 'B'), writeval);
183                         break;
184                 case 1:
185                         if (rtlphy->pwrgroup_cnt == 1) {
186                                 chnlgroup = 0;
187                         } else {
188                                 if (channel < 3)
189                                         chnlgroup = 0;
190                                 else if (channel < 6)
191                                         chnlgroup = 1;
192                                 else if (channel < 9)
193                                         chnlgroup = 2;
194                                 else if (channel < 12)
195                                         chnlgroup = 3;
196                                 else if (channel < 14)
197                                         chnlgroup = 4;
198                                 else if (channel == 14)
199                                         chnlgroup = 5;
200                         }
201
202                         writeval =
203                             rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
204                             [index + (rf ? 8 : 0)] + ((index < 2) ?
205                                                       powerbase0[rf] :
206                                                       powerbase1[rf]);
207
208                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
209                                 "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",
210                                  ((rf == 0) ? 'A' : 'B'), writeval);
211
212                         break;
213                 case 2:
214                         writeval =
215                             ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
216
217                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
218                                 "Better regulatory, writeval(%c) = 0x%x\n",
219                                  ((rf == 0) ? 'A' : 'B'), writeval);
220                         break;
221                 case 3:
222                         chnlgroup = 0;
223
224                         if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
225                                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
226                                         "customer's limit, 40MHz rf(%c) = 0x%x\n",
227                                          ((rf == 0) ? 'A' : 'B'),
228                                          rtlefuse->pwrgroup_ht40[rf][channel -
229                                                                      1]);
230                         } else {
231                                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
232                                         "customer's limit, 20MHz rf(%c) = 0x%x\n",
233                                          ((rf == 0) ? 'A' : 'B'),
234                                          rtlefuse->pwrgroup_ht20[rf][channel -
235                                                                      1]);
236                         }
237
238                         if (index < 2)
239                                 pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][channel-1];
240                         else if (rtlphy->current_chan_bw ==  HT_CHANNEL_WIDTH_20)
241                                 pwr_diff =
242                                   rtlefuse->txpwr_ht20diff[rf][channel-1];
243
244                         if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)
245                                 customer_pwr_diff =
246                                   rtlefuse->pwrgroup_ht40[rf][channel-1];
247                         else
248                                 customer_pwr_diff =
249                                   rtlefuse->pwrgroup_ht20[rf][channel-1];
250
251                         if (pwr_diff > customer_pwr_diff)
252                                 pwr_diff = 0;
253                         else
254                                 pwr_diff = customer_pwr_diff - pwr_diff;
255
256                         for (i = 0; i < 4; i++) {
257                                 pwr_diff_limit[i] =
258                                     (u8)((rtlphy->mcs_txpwrlevel_origoffset
259                                     [chnlgroup][index + (rf ? 8 : 0)] &
260                                     (0x7f << (i * 8))) >> (i * 8));
261
262                                 if (pwr_diff_limit[i] > pwr_diff)
263                                         pwr_diff_limit[i] = pwr_diff;
264                         }
265
266                         customer_limit = (pwr_diff_limit[3] << 24) |
267                             (pwr_diff_limit[2] << 16) |
268                             (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
269
270                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
271                                 "Customer's limit rf(%c) = 0x%x\n",
272                                  ((rf == 0) ? 'A' : 'B'), customer_limit);
273
274                         writeval = customer_limit +
275                             ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
276
277                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
278                                 "Customer, writeval rf(%c)= 0x%x\n",
279                                  ((rf == 0) ? 'A' : 'B'), writeval);
280                         break;
281                 default:
282                         chnlgroup = 0;
283                         writeval =
284                             rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
285                             [index + (rf ? 8 : 0)]
286                             + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
287
288                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
289                                 "RTK better performance, writeval rf(%c) = 0x%x\n",
290                                  ((rf == 0) ? 'A' : 'B'), writeval);
291                         break;
292                 }
293
294                 if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
295                         writeval = writeval - 0x06060606;
296                 else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
297                          TXHIGHPWRLEVEL_BT2)
298                         writeval = writeval - 0x0c0c0c0c;
299                 *(p_outwriteval + rf) = writeval;
300         }
301 }
302
303 static void _rtl8821ae_write_ofdm_power_reg(struct ieee80211_hw *hw,
304                                             u8 index, u32 *pvalue)
305 {
306         struct rtl_priv *rtlpriv = rtl_priv(hw);
307         u16 regoffset_a[6] = {
308                 RTXAGC_A_OFDM18_OFDM6, RTXAGC_A_OFDM54_OFDM24,
309                 RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
310                 RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
311         };
312         u16 regoffset_b[6] = {
313                 RTXAGC_B_OFDM18_OFDM6, RTXAGC_B_OFDM54_OFDM24,
314                 RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
315                 RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
316         };
317         u8 i, rf, pwr_val[4];
318         u32 writeval;
319         u16 regoffset;
320
321         for (rf = 0; rf < 2; rf++) {
322                 writeval = pvalue[rf];
323                 for (i = 0; i < 4; i++) {
324                         pwr_val[i] = (u8)((writeval & (0x7f <<
325                                                         (i * 8))) >> (i * 8));
326
327                         if (pwr_val[i] > RF6052_MAX_TX_PWR)
328                                 pwr_val[i] = RF6052_MAX_TX_PWR;
329                 }
330                 writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
331                     (pwr_val[1] << 8) | pwr_val[0];
332
333                 if (rf == 0)
334                         regoffset = regoffset_a[index];
335                 else
336                         regoffset = regoffset_b[index];
337                 rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);
338
339                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
340                         "Set 0x%x = %08x\n", regoffset, writeval);
341         }
342 }
343
344 void rtl8821ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
345                                            u8 *ppowerlevel_ofdm,
346                                            u8 *ppowerlevel_bw20,
347                                            u8 *ppowerlevel_bw40,
348                                            u8 channel)
349 {
350         u32 writeval[2], powerbase0[2], powerbase1[2];
351         u8 index;
352         u8 direction;
353         u32 pwrtrac_value;
354
355         rtl8821ae_phy_get_power_base(hw, ppowerlevel_ofdm,
356                                      ppowerlevel_bw20,
357                                      ppowerlevel_bw40,
358                                      channel,
359                                      &powerbase0[0],
360                                      &powerbase1[0]);
361
362         rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
363
364         for (index = 0; index < 6; index++) {
365                 get_txpower_writeval_by_regulatory(hw, channel, index,
366                                                    &powerbase0[0],
367                                                    &powerbase1[0],
368                                                    &writeval[0]);
369                 if (direction == 1) {
370                         writeval[0] += pwrtrac_value;
371                         writeval[1] += pwrtrac_value;
372                 } else if (direction == 2) {
373                         writeval[0] -= pwrtrac_value;
374                         writeval[1] -= pwrtrac_value;
375                 }
376                 _rtl8821ae_write_ofdm_power_reg(hw, index, &writeval[0]);
377         }
378 }
379
380 bool rtl8821ae_phy_rf6052_config(struct ieee80211_hw *hw)
381 {
382         struct rtl_priv *rtlpriv = rtl_priv(hw);
383         struct rtl_phy *rtlphy = &rtlpriv->phy;
384
385         if (rtlphy->rf_type == RF_1T1R)
386                 rtlphy->num_total_rfpath = 1;
387         else
388                 rtlphy->num_total_rfpath = 2;
389
390         return _rtl8821ae_phy_rf6052_config_parafile(hw);
391 }
392
393 static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
394 {
395         struct rtl_priv *rtlpriv = rtl_priv(hw);
396         struct rtl_phy *rtlphy = &rtlpriv->phy;
397         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
398         u8 rfpath;
399         bool rtstatus = true;
400
401         for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
402                 switch (rfpath) {
403                 case RF90_PATH_A: {
404                         if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
405                                 rtstatus =
406                                   rtl8812ae_phy_config_rf_with_headerfile(hw,
407                                                         (enum radio_path)rfpath);
408                         else
409                                 rtstatus =
410                                   rtl8821ae_phy_config_rf_with_headerfile(hw,
411                                                         (enum radio_path)rfpath);
412                         break;
413                         }
414                 case RF90_PATH_B:
415                         if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
416                                 rtstatus =
417                                   rtl8812ae_phy_config_rf_with_headerfile(hw,
418                                                         (enum radio_path)rfpath);
419                         else
420                                 rtstatus =
421                                   rtl8821ae_phy_config_rf_with_headerfile(hw,
422                                                         (enum radio_path)rfpath);
423                         break;
424                 case RF90_PATH_C:
425                         break;
426                 case RF90_PATH_D:
427                         break;
428                 }
429
430                 if (!rtstatus) {
431                         RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
432                                  "Radio[%d] Fail!!\n", rfpath);
433                         return false;
434                 }
435         }
436
437         /*put arrays in dm.c*/
438         RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n");
439         return rtstatus;
440 }