Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rf.c
Go to the documentation of this file.
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 <[email protected]>
23  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24  * Hsinchu 300, Taiwan.
25  *
26  * Larry Finger <[email protected]>
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 static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
38 
40 {
41  struct rtl_priv *rtlpriv = rtl_priv(hw);
42  struct rtl_phy *rtlphy = &(rtlpriv->phy);
43 
44  switch (bandwidth) {
46  rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
47  0xfffff3ff) | 0x0400);
48  rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
49  rtlphy->rfreg_chnlval[0]);
50  break;
52  rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
53  0xfffff3ff));
54  rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
55  rtlphy->rfreg_chnlval[0]);
56  break;
57  default:
58  RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
59  "unknown bandwidth: %#X\n", bandwidth);
60  break;
61  }
62 }
63 
65  u8 *ppowerlevel)
66 {
67  struct rtl_priv *rtlpriv = rtl_priv(hw);
68  struct rtl_phy *rtlphy = &(rtlpriv->phy);
69  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
70  struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
71  u32 tx_agc[2] = {0, 0}, tmpval;
72  bool turbo_scanoff = false;
73  u8 idx1, idx2;
74  u8 *ptr;
75 
76  if (rtlefuse->eeprom_regulatory != 0)
77  turbo_scanoff = true;
78 
79  if (mac->act_scanning) {
80  tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
81  tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
82 
83  if (turbo_scanoff) {
84  for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
85  tx_agc[idx1] = ppowerlevel[idx1] |
86  (ppowerlevel[idx1] << 8) |
87  (ppowerlevel[idx1] << 16) |
88  (ppowerlevel[idx1] << 24);
89  }
90  }
91  } else {
92  for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
93  tx_agc[idx1] = ppowerlevel[idx1] |
94  (ppowerlevel[idx1] << 8) |
95  (ppowerlevel[idx1] << 16) |
96  (ppowerlevel[idx1] << 24);
97  }
98 
99  if (rtlefuse->eeprom_regulatory == 0) {
100  tmpval =
101  (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
102  (rtlphy->mcs_txpwrlevel_origoffset[0][7] <<
103  8);
104  tx_agc[RF90_PATH_A] += tmpval;
105 
106  tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
107  (rtlphy->mcs_txpwrlevel_origoffset[0][15] <<
108  24);
109  tx_agc[RF90_PATH_B] += tmpval;
110  }
111  }
112 
113  for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
114  ptr = (u8 *) (&(tx_agc[idx1]));
115  for (idx2 = 0; idx2 < 4; idx2++) {
116  if (*ptr > RF6052_MAX_TX_PWR)
117  *ptr = RF6052_MAX_TX_PWR;
118  ptr++;
119  }
120  }
121 
122  tmpval = tx_agc[RF90_PATH_A] & 0xff;
123  rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
124 
125  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
126  "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n",
127  tmpval, RTXAGC_A_CCK1_MCS32);
128 
129  tmpval = tx_agc[RF90_PATH_A] >> 8;
130 
131  tmpval = tmpval & 0xff00ffff;
132 
133  rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
134 
135  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
136  "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n",
137  tmpval, RTXAGC_B_CCK11_A_CCK2_11);
138 
139  tmpval = tx_agc[RF90_PATH_B] >> 24;
140  rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
141 
142  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
143  "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n",
144  tmpval, RTXAGC_B_CCK11_A_CCK2_11);
145 
146  tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
147  rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
148 
149  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
150  "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n",
151  tmpval, RTXAGC_B_CCK1_55_MCS32);
152 }
153 
154 static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
155  u8 *ppowerlevel, u8 channel,
156  u32 *ofdmbase, u32 *mcsbase)
157 {
158  struct rtl_priv *rtlpriv = rtl_priv(hw);
159  struct rtl_phy *rtlphy = &(rtlpriv->phy);
160  struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
161  u32 powerBase0, powerBase1;
162  u8 legacy_pwrdiff, ht20_pwrdiff;
163  u8 i, powerlevel[2];
164 
165  for (i = 0; i < 2; i++) {
166  powerlevel[i] = ppowerlevel[i];
167  legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
168  powerBase0 = powerlevel[i] + legacy_pwrdiff;
169 
170  powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
171  (powerBase0 << 8) | powerBase0;
172  *(ofdmbase + i) = powerBase0;
173  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
174  " [OFDM power base index rf(%c) = 0x%x]\n",
175  i == 0 ? 'A' : 'B', *(ofdmbase + i));
176  }
177 
178  for (i = 0; i < 2; i++) {
179  if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
180  ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
181  powerlevel[i] += ht20_pwrdiff;
182  }
183  powerBase1 = powerlevel[i];
184  powerBase1 = (powerBase1 << 24) |
185  (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
186 
187  *(mcsbase + i) = powerBase1;
188 
189  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
190  " [MCS power base index rf(%c) = 0x%x]\n",
191  i == 0 ? 'A' : 'B', *(mcsbase + i));
192  }
193 }
194 
195 static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
196  u8 channel, u8 index,
197  u32 *powerBase0,
198  u32 *powerBase1,
199  u32 *p_outwriteval)
200 {
201  struct rtl_priv *rtlpriv = rtl_priv(hw);
202  struct rtl_phy *rtlphy = &(rtlpriv->phy);
203  struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
204  u8 i, chnlgroup = 0, pwr_diff_limit[4];
205  u32 writeVal, customer_limit, rf;
206 
207  for (rf = 0; rf < 2; rf++) {
208  switch (rtlefuse->eeprom_regulatory) {
209  case 0:
210  chnlgroup = 0;
211 
212  writeVal =
213  rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index +
214  (rf ? 8 : 0)]
215  + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
216 
217  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
218  "RTK better performance, writeVal(%c) = 0x%x\n",
219  rf == 0 ? 'A' : 'B', writeVal);
220  break;
221  case 1:
222  if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
223  writeVal = ((index < 2) ? powerBase0[rf] :
224  powerBase1[rf]);
225 
226  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
227  "Realtek regulatory, 40MHz, writeVal(%c) = 0x%x\n",
228  rf == 0 ? 'A' : 'B', writeVal);
229  } else {
230  if (rtlphy->pwrgroup_cnt == 1)
231  chnlgroup = 0;
232  if (rtlphy->pwrgroup_cnt >= 3) {
233  if (channel <= 3)
234  chnlgroup = 0;
235  else if (channel >= 4 && channel <= 9)
236  chnlgroup = 1;
237  else if (channel > 9)
238  chnlgroup = 2;
239  if (rtlphy->pwrgroup_cnt == 4)
240  chnlgroup++;
241  }
242 
243  writeVal =
244  rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
245  [index + (rf ? 8 : 0)] + ((index < 2) ?
246  powerBase0[rf] :
247  powerBase1[rf]);
248 
249  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
250  "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n",
251  rf == 0 ? 'A' : 'B', writeVal);
252  }
253  break;
254  case 2:
255  writeVal =
256  ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
257 
258  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
259  "Better regulatory, writeVal(%c) = 0x%x\n",
260  rf == 0 ? 'A' : 'B', writeVal);
261  break;
262  case 3:
263  chnlgroup = 0;
264 
265  if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
266  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
267  "customer's limit, 40MHz rf(%c) = 0x%x\n",
268  rf == 0 ? 'A' : 'B',
269  rtlefuse->pwrgroup_ht40[rf][channel -
270  1]);
271  } else {
272  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
273  "customer's limit, 20MHz rf(%c) = 0x%x\n",
274  rf == 0 ? 'A' : 'B',
275  rtlefuse->pwrgroup_ht20[rf][channel -
276  1]);
277  }
278  for (i = 0; i < 4; i++) {
279  pwr_diff_limit[i] =
280  (u8) ((rtlphy->mcs_txpwrlevel_origoffset
281  [chnlgroup][index +
282  (rf ? 8 : 0)] & (0x7f << (i * 8))) >>
283  (i * 8));
284 
285  if (rtlphy->current_chan_bw ==
287  if (pwr_diff_limit[i] >
288  rtlefuse->
289  pwrgroup_ht40[rf][channel - 1])
290  pwr_diff_limit[i] =
291  rtlefuse->pwrgroup_ht40[rf]
292  [channel - 1];
293  } else {
294  if (pwr_diff_limit[i] >
295  rtlefuse->
296  pwrgroup_ht20[rf][channel - 1])
297  pwr_diff_limit[i] =
298  rtlefuse->pwrgroup_ht20[rf]
299  [channel - 1];
300  }
301  }
302 
303  customer_limit = (pwr_diff_limit[3] << 24) |
304  (pwr_diff_limit[2] << 16) |
305  (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
306 
307  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
308  "Customer's limit rf(%c) = 0x%x\n",
309  rf == 0 ? 'A' : 'B', customer_limit);
310 
311  writeVal = customer_limit +
312  ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
313 
314  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
315  "Customer, writeVal rf(%c)= 0x%x\n",
316  rf == 0 ? 'A' : 'B', writeVal);
317  break;
318  default:
319  chnlgroup = 0;
320  writeVal =
321  rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
322  [index + (rf ? 8 : 0)]
323  + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
324 
325  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
326  "RTK better performance, writeVal rf(%c) = 0x%x\n",
327  rf == 0 ? 'A' : 'B', writeVal);
328  break;
329  }
330 
331  if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
332  writeVal = writeVal - 0x06060606;
333  else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
335  writeVal = writeVal - 0x0c0c0c0c;
336  *(p_outwriteval + rf) = writeVal;
337  }
338 }
339 
340 static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
341  u8 index, u32 *pValue)
342 {
343  struct rtl_priv *rtlpriv = rtl_priv(hw);
344  struct rtl_phy *rtlphy = &(rtlpriv->phy);
345 
346  u16 regoffset_a[6] = {
350  };
351  u16 regoffset_b[6] = {
355  };
356  u8 i, rf, pwr_val[4];
357  u32 writeVal;
358  u16 regoffset;
359 
360  for (rf = 0; rf < 2; rf++) {
361  writeVal = pValue[rf];
362  for (i = 0; i < 4; i++) {
363  pwr_val[i] = (u8) ((writeVal & (0x7f <<
364  (i * 8))) >> (i * 8));
365 
366  if (pwr_val[i] > RF6052_MAX_TX_PWR)
367  pwr_val[i] = RF6052_MAX_TX_PWR;
368  }
369  writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
370  (pwr_val[1] << 8) | pwr_val[0];
371 
372  if (rf == 0)
373  regoffset = regoffset_a[index];
374  else
375  regoffset = regoffset_b[index];
376  rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
377 
378  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
379  "Set 0x%x = %08x\n", regoffset, writeVal);
380 
381  if (((get_rf_type(rtlphy) == RF_2T2R) &&
382  (regoffset == RTXAGC_A_MCS15_MCS12 ||
383  regoffset == RTXAGC_B_MCS15_MCS12)) ||
384  ((get_rf_type(rtlphy) != RF_2T2R) &&
385  (regoffset == RTXAGC_A_MCS07_MCS04 ||
386  regoffset == RTXAGC_B_MCS07_MCS04))) {
387 
388  writeVal = pwr_val[3];
389  if (regoffset == RTXAGC_A_MCS15_MCS12 ||
390  regoffset == RTXAGC_A_MCS07_MCS04)
391  regoffset = 0xc90;
392  if (regoffset == RTXAGC_B_MCS15_MCS12 ||
393  regoffset == RTXAGC_B_MCS07_MCS04)
394  regoffset = 0xc98;
395 
396  for (i = 0; i < 3; i++) {
397  writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
398  rtl_write_byte(rtlpriv, (u32) (regoffset + i),
399  (u8) writeVal);
400  }
401  }
402  }
403 }
404 
406  u8 *ppowerlevel, u8 channel)
407 {
408  u32 writeVal[2], powerBase0[2], powerBase1[2];
409  u8 index;
410 
411  rtl92c_phy_get_power_base(hw, ppowerlevel,
412  channel, &powerBase0[0], &powerBase1[0]);
413 
414  for (index = 0; index < 6; index++) {
415  _rtl92c_get_txpower_writeval_by_regulatory(hw,
416  channel, index,
417  &powerBase0[0],
418  &powerBase1[0],
419  &writeVal[0]);
420 
421  _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]);
422  }
423 }
424 
426 {
427  struct rtl_priv *rtlpriv = rtl_priv(hw);
428  struct rtl_phy *rtlphy = &(rtlpriv->phy);
429 
430  if (rtlphy->rf_type == RF_1T1R)
431  rtlphy->num_total_rfpath = 1;
432  else
433  rtlphy->num_total_rfpath = 2;
434 
435  return _rtl92ce_phy_rf6052_config_parafile(hw);
436 
437 }
438 
439 static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
440 {
441  struct rtl_priv *rtlpriv = rtl_priv(hw);
442  struct rtl_phy *rtlphy = &(rtlpriv->phy);
443  u32 u4_regvalue = 0;
444  u8 rfpath;
445  bool rtstatus = true;
446  struct bb_reg_def *pphyreg;
447 
448  for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
449 
450  pphyreg = &rtlphy->phyreg_def[rfpath];
451 
452  switch (rfpath) {
453  case RF90_PATH_A:
454  case RF90_PATH_C:
455  u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
456  BRFSI_RFENV);
457  break;
458  case RF90_PATH_B:
459  case RF90_PATH_D:
460  u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
461  BRFSI_RFENV << 16);
462  break;
463  }
464 
465  rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
466  udelay(1);
467 
468  rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
469  udelay(1);
470 
471  rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
472  B3WIREADDREAALENGTH, 0x0);
473  udelay(1);
474 
475  rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
476  udelay(1);
477 
478  switch (rfpath) {
479  case RF90_PATH_A:
481  (enum radio_path)rfpath);
482  break;
483  case RF90_PATH_B:
485  (enum radio_path)rfpath);
486  break;
487  case RF90_PATH_C:
488  break;
489  case RF90_PATH_D:
490  break;
491  }
492 
493  switch (rfpath) {
494  case RF90_PATH_A:
495  case RF90_PATH_C:
496  rtl_set_bbreg(hw, pphyreg->rfintfs,
497  BRFSI_RFENV, u4_regvalue);
498  break;
499  case RF90_PATH_B:
500  case RF90_PATH_D:
501  rtl_set_bbreg(hw, pphyreg->rfintfs,
502  BRFSI_RFENV << 16, u4_regvalue);
503  break;
504  }
505 
506  if (!rtstatus) {
507  RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
508  "Radio[%d] Fail!!\n", rfpath);
509  return false;
510  }
511 
512  }
513 
514  RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");
515  return rtstatus;
516 }