]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/blob - drivers/net/wireless/rtlwifi/rtl8723ae/rf.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
[can-eth-gw-linux.git] / drivers / net / wireless / rtlwifi / rtl8723ae / rf.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2012  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  * The full GNU General Public License is included in this distribution in the
19  * file called LICENSE.
20  *
21  * Contact Information:
22  * wlanfae <wlanfae@realtek.com>
23  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24  * Hsinchu 300, Taiwan.
25  *
26  * Larry Finger <Larry.Finger@lwfinger.net>
27  *
28  *****************************************************************************/
29
30 #include "../wifi.h"
31 #include "reg.h"
32 #include "def.h"
33 #include "phy.h"
34 #include "rf.h"
35 #include "dm.h"
36
37 void rtl8723ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
38 {
39         struct rtl_priv *rtlpriv = rtl_priv(hw);
40         struct rtl_phy *rtlphy = &(rtlpriv->phy);
41
42         switch (bandwidth) {
43         case HT_CHANNEL_WIDTH_20:
44                 rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
45                                              0xfffff3ff) | 0x0400);
46                 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
47                               rtlphy->rfreg_chnlval[0]);
48                 break;
49         case HT_CHANNEL_WIDTH_20_40:
50                 rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
51                                              0xfffff3ff));
52                 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
53                               rtlphy->rfreg_chnlval[0]);
54                 break;
55         default:
56                 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
57                          "unknown bandwidth: %#X\n", bandwidth);
58                 break;
59         }
60 }
61
62 void rtl8723ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
63                                           u8 *ppowerlevel)
64 {
65         struct rtl_priv *rtlpriv = rtl_priv(hw);
66         struct rtl_phy *rtlphy = &(rtlpriv->phy);
67         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
68         struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
69         u32 tx_agc[2] = {0, 0}, tmpval;
70         bool turbo_scanoff = false;
71         u8 idx1, idx2;
72         u8 *ptr;
73
74         if (rtlefuse->eeprom_regulatory != 0)
75                 turbo_scanoff = true;
76
77         if (mac->act_scanning == true) {
78                 tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
79                 tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
80
81                 if (turbo_scanoff) {
82                         for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
83                                 tx_agc[idx1] = ppowerlevel[idx1] |
84                                     (ppowerlevel[idx1] << 8) |
85                                     (ppowerlevel[idx1] << 16) |
86                                     (ppowerlevel[idx1] << 24);
87                         }
88                 }
89         } else {
90                 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
91                         tx_agc[idx1] = ppowerlevel[idx1] |
92                                        (ppowerlevel[idx1] << 8) |
93                                        (ppowerlevel[idx1] << 16) |
94                                        (ppowerlevel[idx1] << 24);
95                 }
96
97                 if (rtlefuse->eeprom_regulatory == 0) {
98                         tmpval = (rtlphy->mcs_offset[0][6]) +
99                                 (rtlphy->mcs_offset[0][7] << 8);
100                         tx_agc[RF90_PATH_A] += tmpval;
101
102                         tmpval = (rtlphy->mcs_offset[0][14]) +
103                             (rtlphy->mcs_offset[0][15] << 24);
104                         tx_agc[RF90_PATH_B] += tmpval;
105                 }
106         }
107
108         for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
109                 ptr = (u8 *) (&(tx_agc[idx1]));
110                 for (idx2 = 0; idx2 < 4; idx2++) {
111                         if (*ptr > RF6052_MAX_TX_PWR)
112                                 *ptr = RF6052_MAX_TX_PWR;
113                         ptr++;
114                 }
115         }
116
117         tmpval = tx_agc[RF90_PATH_A] & 0xff;
118         rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
119
120         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
121                 "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
122                 RTXAGC_A_CCK1_MCS32);
123
124         tmpval = tx_agc[RF90_PATH_A] >> 8;
125
126         tmpval = tmpval & 0xff00ffff;
127
128         rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
129
130         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
131                 "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
132                 RTXAGC_B_CCK11_A_CCK2_11);
133
134         tmpval = tx_agc[RF90_PATH_B] >> 24;
135         rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
136
137         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
138                 "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
139                 RTXAGC_B_CCK11_A_CCK2_11);
140
141         tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
142         rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
143
144         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
145                 "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
146                 RTXAGC_B_CCK1_55_MCS32);
147 }
148
149 static void rtl8723ae_phy_get_power_base(struct ieee80211_hw *hw,
150                                          u8 *ppowerlevel, u8 channel,
151                                          u32 *ofdmbase, u32 *mcsbase)
152 {
153         struct rtl_priv *rtlpriv = rtl_priv(hw);
154         struct rtl_phy *rtlphy = &(rtlpriv->phy);
155         struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
156         u32 powerBase0, powerBase1;
157         u8 legacy_pwrdiff, ht20_pwrdiff;
158         u8 i, powerlevel[2];
159
160         for (i = 0; i < 2; i++) {
161                 powerlevel[i] = ppowerlevel[i];
162                 legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
163                 powerBase0 = powerlevel[i] + legacy_pwrdiff;
164
165                 powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
166                     (powerBase0 << 8) | powerBase0;
167                 *(ofdmbase + i) = powerBase0;
168                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
169                         " [OFDM power base index rf(%c) = 0x%x]\n",
170                         ((i == 0) ? 'A' : 'B'), *(ofdmbase + i));
171         }
172
173         for (i = 0; i < 2; i++) {
174                 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
175                         ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
176                         powerlevel[i] += ht20_pwrdiff;
177                 }
178                 powerBase1 = powerlevel[i];
179                 powerBase1 = (powerBase1 << 24) |
180                     (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
181
182                 *(mcsbase + i) = powerBase1;
183
184                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
185                         " [MCS power base index rf(%c) = 0x%x]\n",
186                         ((i == 0) ? 'A' : 'B'), *(mcsbase + i));
187         }
188 }
189
190 static void rtl8723ae_get_txpwr_val_by_reg(struct ieee80211_hw *hw,
191                                            u8 channel, u8 index,
192                                            u32 *powerBase0,
193                                            u32 *powerBase1,
194                                            u32 *p_outwriteval)
195 {
196         struct rtl_priv *rtlpriv = rtl_priv(hw);
197         struct rtl_phy *rtlphy = &(rtlpriv->phy);
198         struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
199         u8 i, chnlgroup = 0, pwr_diff_limit[4];
200         u32 writeVal, customer_limit, rf;
201
202         for (rf = 0; rf < 2; rf++) {
203                 switch (rtlefuse->eeprom_regulatory) {
204                 case 0:
205                         chnlgroup = 0;
206
207                         writeVal = rtlphy->mcs_offset[chnlgroup]
208                                    [index + (rf ? 8 : 0)] +
209                                    ((index < 2) ? powerBase0[rf] :
210                                    powerBase1[rf]);
211
212                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
213                                 "RTK better performance, "
214                                 "writeVal(%c) = 0x%x\n",
215                                 ((rf == 0) ? 'A' : 'B'), writeVal);
216                         break;
217                 case 1:
218                         if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
219                                 writeVal = ((index < 2) ? powerBase0[rf] :
220                                             powerBase1[rf]);
221
222                                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
223                                         "Realtek regulatory, 40MHz, "
224                                         "writeVal(%c) = 0x%x\n",
225                                         ((rf == 0) ? 'A' : 'B'), writeVal);
226                         } else {
227                                 if (rtlphy->pwrgroup_cnt == 1)
228                                         chnlgroup = 0;
229                                 if (rtlphy->pwrgroup_cnt >= 3) {
230                                         if (channel <= 3)
231                                                 chnlgroup = 0;
232                                         else if (channel >= 4 && channel <= 9)
233                                                 chnlgroup = 1;
234                                         else if (channel > 9)
235                                                 chnlgroup = 2;
236                                         if (rtlphy->current_chan_bw ==
237                                             HT_CHANNEL_WIDTH_20)
238                                                 chnlgroup++;
239                                         else
240                                                 chnlgroup += 4;
241                                 }
242
243                                 writeVal = rtlphy->mcs_offset[chnlgroup]
244                                     [index + (rf ? 8 : 0)] + ((index < 2) ?
245                                                               powerBase0[rf] :
246                                                               powerBase1[rf]);
247
248                                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
249                                         "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n",
250                                         ((rf == 0) ? 'A' : 'B'), writeVal);
251                         }
252                         break;
253                 case 2:
254                         writeVal =
255                             ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
256
257                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
258                                 "Better regulatory, writeVal(%c) = 0x%x\n",
259                                 ((rf == 0) ? 'A' : 'B'), writeVal);
260                         break;
261                 case 3:
262                         chnlgroup = 0;
263
264                         if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
265                                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
266                                         "customer's limit, 40MHz rf(%c) = 0x%x\n",
267                                         ((rf == 0) ? 'A' : 'B'),
268                                         rtlefuse->pwrgroup_ht40[rf][channel-1]);
269                         } else {
270                                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
271                                         "customer's limit, 20MHz rf(%c) = 0x%x\n",
272                                         ((rf == 0) ? 'A' : 'B'),
273                                         rtlefuse->pwrgroup_ht20[rf][channel-1]);
274                         }
275                         for (i = 0; i < 4; i++) {
276                                 pwr_diff_limit[i] =
277                                         (u8) ((rtlphy->mcs_offset
278                                         [chnlgroup][index + (rf ? 8 : 0)] &
279                                         (0x7f << (i * 8))) >> (i * 8));
280
281                                 if (rtlphy->current_chan_bw ==
282                                     HT_CHANNEL_WIDTH_20_40) {
283                                         if (pwr_diff_limit[i] >
284                                             rtlefuse->
285                                             pwrgroup_ht40[rf][channel - 1])
286                                                 pwr_diff_limit[i] =
287                                                     rtlefuse->pwrgroup_ht40[rf]
288                                                     [channel - 1];
289                                 } else {
290                                         if (pwr_diff_limit[i] >
291                                             rtlefuse->
292                                             pwrgroup_ht20[rf][channel - 1])
293                                                 pwr_diff_limit[i] =
294                                                     rtlefuse->pwrgroup_ht20[rf]
295                                                     [channel - 1];
296                                 }
297                         }
298
299                         customer_limit = (pwr_diff_limit[3] << 24) |
300                             (pwr_diff_limit[2] << 16) |
301                             (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
302
303                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
304                                 "Customer's limit rf(%c) = 0x%x\n",
305                                 ((rf == 0) ? 'A' : 'B'), customer_limit);
306
307                         writeVal = customer_limit +
308                             ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
309
310                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
311                                 "Customer, writeVal rf(%c)= 0x%x\n",
312                                 ((rf == 0) ? 'A' : 'B'), writeVal);
313                         break;
314                 default:
315                         chnlgroup = 0;
316                         writeVal = rtlphy->mcs_offset[chnlgroup][index +
317                             (rf ? 8 : 0)] + ((index < 2) ? powerBase0[rf] :
318                             powerBase1[rf]);
319
320                         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
321                                 "RTK better performance, writeVal rf(%c) = 0x%x\n",
322                                 ((rf == 0) ? 'A' : 'B'), writeVal);
323                         break;
324                 }
325
326                 if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
327                         writeVal = writeVal - 0x06060606;
328                 else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
329                          TXHIGHPWRLEVEL_BT2)
330                         writeVal = writeVal - 0x0c0c0c0c;
331                 *(p_outwriteval + rf) = writeVal;
332         }
333 }
334
335 static void _rtl8723ae_write_ofdm_power_reg(struct ieee80211_hw *hw,
336                                             u8 index, u32 *pValue)
337 {
338         struct rtl_priv *rtlpriv = rtl_priv(hw);
339         struct rtl_phy *rtlphy = &(rtlpriv->phy);
340
341         u16 regoffset_a[6] = {
342                 RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
343                 RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
344                 RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
345         };
346         u16 regoffset_b[6] = {
347                 RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
348                 RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
349                 RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
350         };
351         u8 i, rf, pwr_val[4];
352         u32 writeVal;
353         u16 regoffset;
354
355         for (rf = 0; rf < 2; rf++) {
356                 writeVal = pValue[rf];
357                 for (i = 0; i < 4; i++) {
358                         pwr_val[i] = (u8) ((writeVal & (0x7f <<
359                                                         (i * 8))) >> (i * 8));
360
361                         if (pwr_val[i] > RF6052_MAX_TX_PWR)
362                                 pwr_val[i] = RF6052_MAX_TX_PWR;
363                 }
364                 writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
365                     (pwr_val[1] << 8) | pwr_val[0];
366
367                 if (rf == 0)
368                         regoffset = regoffset_a[index];
369                 else
370                         regoffset = regoffset_b[index];
371                 rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
372
373                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
374                         "Set 0x%x = %08x\n", regoffset, writeVal);
375
376                 if (((get_rf_type(rtlphy) == RF_2T2R) &&
377                      (regoffset == RTXAGC_A_MCS15_MCS12 ||
378                       regoffset == RTXAGC_B_MCS15_MCS12)) ||
379                     ((get_rf_type(rtlphy) != RF_2T2R) &&
380                      (regoffset == RTXAGC_A_MCS07_MCS04 ||
381                       regoffset == RTXAGC_B_MCS07_MCS04))) {
382
383                         writeVal = pwr_val[3];
384                         if (regoffset == RTXAGC_A_MCS15_MCS12 ||
385                             regoffset == RTXAGC_A_MCS07_MCS04)
386                                 regoffset = 0xc90;
387                         if (regoffset == RTXAGC_B_MCS15_MCS12 ||
388                             regoffset == RTXAGC_B_MCS07_MCS04)
389                                 regoffset = 0xc98;
390
391                         for (i = 0; i < 3; i++) {
392                                 writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
393                                 rtl_write_byte(rtlpriv, (u32) (regoffset + i),
394                                                (u8) writeVal);
395                         }
396                 }
397         }
398 }
399
400 void rtl8723ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
401                                            u8 *ppowerlevel, u8 channel)
402 {
403         u32 writeVal[2], powerBase0[2], powerBase1[2];
404         u8 index;
405
406         rtl8723ae_phy_get_power_base(hw, ppowerlevel,
407                                   channel, &powerBase0[0], &powerBase1[0]);
408
409         for (index = 0; index < 6; index++) {
410                 rtl8723ae_get_txpwr_val_by_reg(hw, channel, index,
411                                               &powerBase0[0],
412                                               &powerBase1[0],
413                                               &writeVal[0]);
414
415                 _rtl8723ae_write_ofdm_power_reg(hw, index, &writeVal[0]);
416         }
417 }
418
419 static bool _rtl8723ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
420 {
421         struct rtl_priv *rtlpriv = rtl_priv(hw);
422         struct rtl_phy *rtlphy = &(rtlpriv->phy);
423         u32 u4_regvalue = 0;
424         u8 rfpath;
425         bool rtstatus = true;
426         struct bb_reg_def *pphyreg;
427
428         for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
429
430                 pphyreg = &rtlphy->phyreg_def[rfpath];
431
432                 switch (rfpath) {
433                 case RF90_PATH_A:
434                 case RF90_PATH_C:
435                         u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
436                                                     BRFSI_RFENV);
437                         break;
438                 case RF90_PATH_B:
439                 case RF90_PATH_D:
440                         u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
441                                                     BRFSI_RFENV << 16);
442                         break;
443                 }
444
445                 rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
446                 udelay(1);
447
448                 rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
449                 udelay(1);
450
451                 rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
452                               B3WIREADDREAALENGTH, 0x0);
453                 udelay(1);
454
455                 rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
456                 udelay(1);
457
458                 switch (rfpath) {
459                 case RF90_PATH_A:
460                         rtstatus = rtl8723ae_phy_config_rf_with_headerfile(hw,
461                                                 (enum radio_path)rfpath);
462                         break;
463                 case RF90_PATH_B:
464                         rtstatus = rtl8723ae_phy_config_rf_with_headerfile(hw,
465                                                 (enum radio_path)rfpath);
466                         break;
467                 case RF90_PATH_C:
468                         break;
469                 case RF90_PATH_D:
470                         break;
471                 }
472                 switch (rfpath) {
473                 case RF90_PATH_A:
474                 case RF90_PATH_C:
475                         rtl_set_bbreg(hw, pphyreg->rfintfs,
476                                       BRFSI_RFENV, u4_regvalue);
477                         break;
478                 case RF90_PATH_B:
479                 case RF90_PATH_D:
480                         rtl_set_bbreg(hw, pphyreg->rfintfs,
481                                       BRFSI_RFENV << 16, u4_regvalue);
482                         break;
483                 }
484                 if (rtstatus != true) {
485                         RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
486                                  "Radio[%d] Fail!!", rfpath);
487                         return false;
488                 }
489         }
490         RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");
491         return rtstatus;
492 }
493
494 bool rtl8723ae_phy_rf6052_config(struct ieee80211_hw *hw)
495 {
496         struct rtl_priv *rtlpriv = rtl_priv(hw);
497         struct rtl_phy *rtlphy = &(rtlpriv->phy);
498
499         if (rtlphy->rf_type == RF_1T1R)
500                 rtlphy->num_total_rfpath = 1;
501         else
502                 rtlphy->num_total_rfpath = 2;
503
504         return _rtl8723ae_phy_rf6052_config_parafile(hw);
505 }