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 _rtl92c_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_hal *rtlhal = rtl_hal(rtlpriv);
70  struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
71  struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
72  u32 tx_agc[2] = { 0, 0 }, tmpval = 0;
73  bool turbo_scanoff = false;
74  u8 idx1, idx2;
75  u8 *ptr;
76 
77  if (rtlhal->interface == INTF_PCI) {
78  if (rtlefuse->eeprom_regulatory != 0)
79  turbo_scanoff = true;
80  } else {
81  if ((rtlefuse->eeprom_regulatory != 0) ||
82  (rtlefuse->external_pa))
83  turbo_scanoff = true;
84  }
85  if (mac->act_scanning) {
86  tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
87  tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
88  if (turbo_scanoff) {
89  for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
90  tx_agc[idx1] = ppowerlevel[idx1] |
91  (ppowerlevel[idx1] << 8) |
92  (ppowerlevel[idx1] << 16) |
93  (ppowerlevel[idx1] << 24);
94  if (rtlhal->interface == INTF_USB) {
95  if (tx_agc[idx1] > 0x20 &&
96  rtlefuse->external_pa)
97  tx_agc[idx1] = 0x20;
98  }
99  }
100  }
101  } else {
102  if (rtlpriv->dm.dynamic_txhighpower_lvl ==
104  tx_agc[RF90_PATH_A] = 0x10101010;
105  tx_agc[RF90_PATH_B] = 0x10101010;
106  } else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
108  tx_agc[RF90_PATH_A] = 0x00000000;
109  tx_agc[RF90_PATH_B] = 0x00000000;
110  } else{
111  for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
112  tx_agc[idx1] = ppowerlevel[idx1] |
113  (ppowerlevel[idx1] << 8) |
114  (ppowerlevel[idx1] << 16) |
115  (ppowerlevel[idx1] << 24);
116  }
117  if (rtlefuse->eeprom_regulatory == 0) {
118  tmpval = (rtlphy->mcs_txpwrlevel_origoffset
119  [0][6]) +
121  [0][7] << 8);
122  tx_agc[RF90_PATH_A] += tmpval;
123  tmpval = (rtlphy->mcs_txpwrlevel_origoffset
124  [0][14]) +
126  [0][15] << 24);
127  tx_agc[RF90_PATH_B] += tmpval;
128  }
129  }
130  }
131  for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
132  ptr = (u8 *) (&(tx_agc[idx1]));
133  for (idx2 = 0; idx2 < 4; idx2++) {
134  if (*ptr > RF6052_MAX_TX_PWR)
135  *ptr = RF6052_MAX_TX_PWR;
136  ptr++;
137  }
138  }
139  tmpval = tx_agc[RF90_PATH_A] & 0xff;
140  rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
141 
142  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
143  "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n",
144  tmpval, RTXAGC_A_CCK1_MCS32);
145 
146  tmpval = tx_agc[RF90_PATH_A] >> 8;
147  if (mac->mode == WIRELESS_MODE_B)
148  tmpval = tmpval & 0xff00ffff;
149  rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
150  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
151  "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n",
152  tmpval, RTXAGC_B_CCK11_A_CCK2_11);
153  tmpval = tx_agc[RF90_PATH_B] >> 24;
154  rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
155  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
156  "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n",
157  tmpval, RTXAGC_B_CCK11_A_CCK2_11);
158  tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
159  rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
160  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
161  "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n",
162  tmpval, RTXAGC_B_CCK1_55_MCS32);
163 }
164 
165 static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
166  u8 *ppowerlevel, u8 channel,
167  u32 *ofdmbase, u32 *mcsbase)
168 {
169  struct rtl_priv *rtlpriv = rtl_priv(hw);
170  struct rtl_phy *rtlphy = &(rtlpriv->phy);
171  struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
172  u32 powerBase0, powerBase1;
173  u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0;
174  u8 i, powerlevel[2];
175 
176  for (i = 0; i < 2; i++) {
177  powerlevel[i] = ppowerlevel[i];
178  legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
179  powerBase0 = powerlevel[i] + legacy_pwrdiff;
180  powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
181  (powerBase0 << 8) | powerBase0;
182  *(ofdmbase + i) = powerBase0;
183  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
184  " [OFDM power base index rf(%c) = 0x%x]\n",
185  i == 0 ? 'A' : 'B', *(ofdmbase + i));
186  }
187  for (i = 0; i < 2; i++) {
188  if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
189  ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
190  powerlevel[i] += ht20_pwrdiff;
191  }
192  powerBase1 = powerlevel[i];
193  powerBase1 = (powerBase1 << 24) |
194  (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
195  *(mcsbase + i) = powerBase1;
196  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
197  " [MCS power base index rf(%c) = 0x%x]\n",
198  i == 0 ? 'A' : 'B', *(mcsbase + i));
199  }
200 }
201 
202 static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
203  u8 channel, u8 index,
204  u32 *powerBase0,
205  u32 *powerBase1,
206  u32 *p_outwriteval)
207 {
208  struct rtl_priv *rtlpriv = rtl_priv(hw);
209  struct rtl_phy *rtlphy = &(rtlpriv->phy);
210  struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
211  u8 i, chnlgroup = 0, pwr_diff_limit[4];
212  u32 writeVal, customer_limit, rf;
213 
214  for (rf = 0; rf < 2; rf++) {
215  switch (rtlefuse->eeprom_regulatory) {
216  case 0:
217  chnlgroup = 0;
218  writeVal = rtlphy->mcs_txpwrlevel_origoffset
219  [chnlgroup][index + (rf ? 8 : 0)]
220  + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
221  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
222  "RTK better performance,writeVal(%c) = 0x%x\n",
223  rf == 0 ? 'A' : 'B', writeVal);
224  break;
225  case 1:
226  if (rtlphy->pwrgroup_cnt == 1)
227  chnlgroup = 0;
228  if (rtlphy->pwrgroup_cnt >= 3) {
229  if (channel <= 3)
230  chnlgroup = 0;
231  else if (channel >= 4 && channel <= 9)
232  chnlgroup = 1;
233  else if (channel > 9)
234  chnlgroup = 2;
235  if (rtlphy->current_chan_bw ==
237  chnlgroup++;
238  else
239  chnlgroup += 4;
240  }
241  writeVal = rtlphy->mcs_txpwrlevel_origoffset
242  [chnlgroup][index +
243  (rf ? 8 : 0)] +
244  ((index < 2) ? powerBase0[rf] :
245  powerBase1[rf]);
246  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
247  "Realtek regulatory, 20MHz, writeVal(%c) = 0x%x\n",
248  rf == 0 ? 'A' : 'B', writeVal);
249  break;
250  case 2:
251  writeVal = ((index < 2) ? powerBase0[rf] :
252  powerBase1[rf]);
253  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
254  "Better regulatory,writeVal(%c) = 0x%x\n",
255  rf == 0 ? 'A' : 'B', writeVal);
256  break;
257  case 3:
258  chnlgroup = 0;
259  if (rtlphy->current_chan_bw ==
261  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
262  "customer's limit, 40MHzrf(%c) = 0x%x\n",
263  rf == 0 ? 'A' : 'B',
264  rtlefuse->pwrgroup_ht40[rf]
265  [channel - 1]);
266  } else {
267  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
268  "customer's limit, 20MHz rf(%c) = 0x%x\n",
269  rf == 0 ? 'A' : 'B',
270  rtlefuse->pwrgroup_ht20[rf]
271  [channel - 1]);
272  }
273  for (i = 0; i < 4; i++) {
274  pwr_diff_limit[i] =
275  (u8) ((rtlphy->mcs_txpwrlevel_origoffset
276  [chnlgroup][index + (rf ? 8 : 0)]
277  & (0x7f << (i * 8))) >> (i * 8));
278  if (rtlphy->current_chan_bw ==
280  if (pwr_diff_limit[i] >
281  rtlefuse->pwrgroup_ht40[rf]
282  [channel - 1])
283  pwr_diff_limit[i] = rtlefuse->
284  pwrgroup_ht40[rf]
285  [channel - 1];
286  } else {
287  if (pwr_diff_limit[i] >
288  rtlefuse->pwrgroup_ht20[rf]
289  [channel - 1])
290  pwr_diff_limit[i] =
291  rtlefuse->pwrgroup_ht20[rf]
292  [channel - 1];
293  }
294  }
295  customer_limit = (pwr_diff_limit[3] << 24) |
296  (pwr_diff_limit[2] << 16) |
297  (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
298  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
299  "Customer's limit rf(%c) = 0x%x\n",
300  rf == 0 ? 'A' : 'B', customer_limit);
301  writeVal = customer_limit + ((index < 2) ?
302  powerBase0[rf] : powerBase1[rf]);
303  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
304  "Customer, writeVal rf(%c)= 0x%x\n",
305  rf == 0 ? 'A' : 'B', writeVal);
306  break;
307  default:
308  chnlgroup = 0;
309  writeVal = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
310  [index + (rf ? 8 : 0)] + ((index < 2) ?
311  powerBase0[rf] : powerBase1[rf]);
312  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
313  "RTK better performance, writeValrf(%c) = 0x%x\n",
314  rf == 0 ? 'A' : 'B', writeVal);
315  break;
316  }
317  if (rtlpriv->dm.dynamic_txhighpower_lvl ==
319  writeVal = 0x14141414;
320  else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
322  writeVal = 0x00000000;
323  if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
324  writeVal = writeVal - 0x06060606;
325  else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
327  writeVal = writeVal;
328  *(p_outwriteval + rf) = writeVal;
329  }
330 }
331 
332 static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
333  u8 index, u32 *pValue)
334 {
335  struct rtl_priv *rtlpriv = rtl_priv(hw);
336  struct rtl_phy *rtlphy = &(rtlpriv->phy);
337  u16 regoffset_a[6] = {
341  };
342  u16 regoffset_b[6] = {
346  };
347  u8 i, rf, pwr_val[4];
348  u32 writeVal;
349  u16 regoffset;
350 
351  for (rf = 0; rf < 2; rf++) {
352  writeVal = pValue[rf];
353  for (i = 0; i < 4; i++) {
354  pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >>
355  (i * 8));
356  if (pwr_val[i] > RF6052_MAX_TX_PWR)
357  pwr_val[i] = RF6052_MAX_TX_PWR;
358  }
359  writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
360  (pwr_val[1] << 8) | pwr_val[0];
361  if (rf == 0)
362  regoffset = regoffset_a[index];
363  else
364  regoffset = regoffset_b[index];
365  rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
366  RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
367  "Set 0x%x = %08x\n", regoffset, writeVal);
368  if (((get_rf_type(rtlphy) == RF_2T2R) &&
369  (regoffset == RTXAGC_A_MCS15_MCS12 ||
370  regoffset == RTXAGC_B_MCS15_MCS12)) ||
371  ((get_rf_type(rtlphy) != RF_2T2R) &&
372  (regoffset == RTXAGC_A_MCS07_MCS04 ||
373  regoffset == RTXAGC_B_MCS07_MCS04))) {
374  writeVal = pwr_val[3];
375  if (regoffset == RTXAGC_A_MCS15_MCS12 ||
376  regoffset == RTXAGC_A_MCS07_MCS04)
377  regoffset = 0xc90;
378  if (regoffset == RTXAGC_B_MCS15_MCS12 ||
379  regoffset == RTXAGC_B_MCS07_MCS04)
380  regoffset = 0xc98;
381  for (i = 0; i < 3; i++) {
382  writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
383  rtl_write_byte(rtlpriv, (u32)(regoffset + i),
384  (u8)writeVal);
385  }
386  }
387  }
388 }
389 
391  u8 *ppowerlevel, u8 channel)
392 {
393  u32 writeVal[2], powerBase0[2], powerBase1[2];
394  u8 index = 0;
395 
396  rtl92c_phy_get_power_base(hw, ppowerlevel,
397  channel, &powerBase0[0], &powerBase1[0]);
398  for (index = 0; index < 6; index++) {
399  _rtl92c_get_txpower_writeval_by_regulatory(hw,
400  channel, index,
401  &powerBase0[0],
402  &powerBase1[0],
403  &writeVal[0]);
404  _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]);
405  }
406 }
407 
409 {
410  struct rtl_priv *rtlpriv = rtl_priv(hw);
411  struct rtl_phy *rtlphy = &(rtlpriv->phy);
412  bool rtstatus = true;
413  u8 b_reg_hwparafile = 1;
414 
415  if (rtlphy->rf_type == RF_1T1R)
416  rtlphy->num_total_rfpath = 1;
417  else
418  rtlphy->num_total_rfpath = 2;
419  if (b_reg_hwparafile == 1)
420  rtstatus = _rtl92c_phy_rf6052_config_parafile(hw);
421  return rtstatus;
422 }
423 
424 static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
425 {
426  struct rtl_priv *rtlpriv = rtl_priv(hw);
427  struct rtl_phy *rtlphy = &(rtlpriv->phy);
428  u32 u4_regvalue = 0;
429  u8 rfpath;
430  bool rtstatus = true;
431  struct bb_reg_def *pphyreg;
432 
433  for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
434  pphyreg = &rtlphy->phyreg_def[rfpath];
435  switch (rfpath) {
436  case RF90_PATH_A:
437  case RF90_PATH_C:
438  u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
439  BRFSI_RFENV);
440  break;
441  case RF90_PATH_B:
442  case RF90_PATH_D:
443  u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
444  BRFSI_RFENV << 16);
445  break;
446  }
447  rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
448  udelay(1);
449  rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
450  udelay(1);
451  rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
452  B3WIREADDREAALENGTH, 0x0);
453  udelay(1);
454  rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
455  udelay(1);
456  switch (rfpath) {
457  case RF90_PATH_A:
459  (enum radio_path) rfpath);
460  break;
461  case RF90_PATH_B:
463  (enum radio_path) rfpath);
464  break;
465  case RF90_PATH_C:
466  break;
467  case RF90_PATH_D:
468  break;
469  }
470  switch (rfpath) {
471  case RF90_PATH_A:
472  case RF90_PATH_C:
473  rtl_set_bbreg(hw, pphyreg->rfintfs,
474  BRFSI_RFENV, u4_regvalue);
475  break;
476  case RF90_PATH_B:
477  case RF90_PATH_D:
478  rtl_set_bbreg(hw, pphyreg->rfintfs,
479  BRFSI_RFENV << 16, u4_regvalue);
480  break;
481  }
482  if (!rtstatus) {
483  RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
484  "Radio[%d] Fail!!", rfpath);
485  goto phy_rf_cfg_fail;
486  }
487  }
488  RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");
489  return rtstatus;
490 phy_rf_cfg_fail:
491  return rtstatus;
492 }