1
/******************************************************************************
3
* Copyright(c) 2009-2010 Realtek Corporation.
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.
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
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
18
* The full GNU General Public License is included in this distribution in the
19
* file called LICENSE.
21
* Contact Information:
22
* wlanfae <wlanfae@realtek.com>
23
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24
* Hsinchu 300, Taiwan.
26
* Larry Finger <Larry.Finger@lwfinger.net>
28
*****************************************************************************/
37
static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
39
void rtl92ce_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
41
struct rtl_priv *rtlpriv = rtl_priv(hw);
42
struct rtl_phy *rtlphy = &(rtlpriv->phy);
45
case HT_CHANNEL_WIDTH_20:
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]);
51
case HT_CHANNEL_WIDTH_20_40:
52
rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
54
rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
55
rtlphy->rfreg_chnlval[0]);
58
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
59
("unknown bandwidth: %#X\n", bandwidth));
64
void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
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;
76
if (rtlefuse->eeprom_regulatory != 0)
79
if (mac->act_scanning) {
80
tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
81
tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
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);
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);
99
if (rtlefuse->eeprom_regulatory == 0) {
101
(rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
102
(rtlphy->mcs_txpwrlevel_origoffset[0][7] <<
104
tx_agc[RF90_PATH_A] += tmpval;
106
tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
107
(rtlphy->mcs_txpwrlevel_origoffset[0][15] <<
109
tx_agc[RF90_PATH_B] += tmpval;
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;
122
tmpval = tx_agc[RF90_PATH_A] & 0xff;
123
rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
125
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
126
("CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
127
RTXAGC_A_CCK1_MCS32));
129
tmpval = tx_agc[RF90_PATH_A] >> 8;
131
tmpval = tmpval & 0xff00ffff;
133
rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
135
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
136
("CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
137
RTXAGC_B_CCK11_A_CCK2_11));
139
tmpval = tx_agc[RF90_PATH_B] >> 24;
140
rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
142
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
143
("CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
144
RTXAGC_B_CCK11_A_CCK2_11));
146
tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
147
rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
149
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
150
("CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
151
RTXAGC_B_CCK1_55_MCS32));
154
static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
155
u8 *ppowerlevel, u8 channel,
156
u32 *ofdmbase, u32 *mcsbase)
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;
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;
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)));
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;
183
powerBase1 = powerlevel[i];
184
powerBase1 = (powerBase1 << 24) |
185
(powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
187
*(mcsbase + i) = powerBase1;
189
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
190
(" [MCS power base index rf(%c) = 0x%x]\n",
191
((i == 0) ? 'A' : 'B'), *(mcsbase + i)));
195
static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
196
u8 channel, u8 index,
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;
207
for (rf = 0; rf < 2; rf++) {
208
switch (rtlefuse->eeprom_regulatory) {
213
rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index +
215
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
217
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
218
("RTK better performance, "
219
"writeVal(%c) = 0x%x\n",
220
((rf == 0) ? 'A' : 'B'), writeVal));
223
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
224
writeVal = ((index < 2) ? powerBase0[rf] :
227
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
228
("Realtek regulatory, 40MHz, "
229
"writeVal(%c) = 0x%x\n",
230
((rf == 0) ? 'A' : 'B'), writeVal));
232
if (rtlphy->pwrgroup_cnt == 1)
234
if (rtlphy->pwrgroup_cnt >= 3) {
237
else if (channel >= 4 && channel <= 9)
239
else if (channel > 9)
241
if (rtlphy->pwrgroup_cnt == 4)
246
rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
247
[index + (rf ? 8 : 0)] + ((index < 2) ?
251
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
252
("Realtek regulatory, 20MHz, "
253
"writeVal(%c) = 0x%x\n",
254
((rf == 0) ? 'A' : 'B'), writeVal));
259
((index < 2) ? powerBase0[rf] : powerBase1[rf]);
261
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
262
("Better regulatory, "
263
"writeVal(%c) = 0x%x\n",
264
((rf == 0) ? 'A' : 'B'), writeVal));
269
if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
270
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
271
("customer's limit, 40MHz "
273
((rf == 0) ? 'A' : 'B'),
274
rtlefuse->pwrgroup_ht40[rf][channel -
277
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
278
("customer's limit, 20MHz "
280
((rf == 0) ? 'A' : 'B'),
281
rtlefuse->pwrgroup_ht20[rf][channel -
284
for (i = 0; i < 4; i++) {
286
(u8) ((rtlphy->mcs_txpwrlevel_origoffset
288
(rf ? 8 : 0)] & (0x7f << (i * 8))) >>
291
if (rtlphy->current_chan_bw ==
292
HT_CHANNEL_WIDTH_20_40) {
293
if (pwr_diff_limit[i] >
295
pwrgroup_ht40[rf][channel - 1])
297
rtlefuse->pwrgroup_ht40[rf]
300
if (pwr_diff_limit[i] >
302
pwrgroup_ht20[rf][channel - 1])
304
rtlefuse->pwrgroup_ht20[rf]
309
customer_limit = (pwr_diff_limit[3] << 24) |
310
(pwr_diff_limit[2] << 16) |
311
(pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
313
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
314
("Customer's limit rf(%c) = 0x%x\n",
315
((rf == 0) ? 'A' : 'B'), customer_limit));
317
writeVal = customer_limit +
318
((index < 2) ? powerBase0[rf] : powerBase1[rf]);
320
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
321
("Customer, writeVal rf(%c)= 0x%x\n",
322
((rf == 0) ? 'A' : 'B'), writeVal));
327
rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
328
[index + (rf ? 8 : 0)]
329
+ ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
331
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
332
("RTK better performance, writeVal "
334
((rf == 0) ? 'A' : 'B'), writeVal));
338
if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
339
writeVal = writeVal - 0x06060606;
340
else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
342
writeVal = writeVal - 0x0c0c0c0c;
343
*(p_outwriteval + rf) = writeVal;
347
static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
348
u8 index, u32 *pValue)
350
struct rtl_priv *rtlpriv = rtl_priv(hw);
351
struct rtl_phy *rtlphy = &(rtlpriv->phy);
353
u16 regoffset_a[6] = {
354
RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
355
RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
356
RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
358
u16 regoffset_b[6] = {
359
RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
360
RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
361
RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
363
u8 i, rf, pwr_val[4];
367
for (rf = 0; rf < 2; rf++) {
368
writeVal = pValue[rf];
369
for (i = 0; i < 4; i++) {
370
pwr_val[i] = (u8) ((writeVal & (0x7f <<
371
(i * 8))) >> (i * 8));
373
if (pwr_val[i] > RF6052_MAX_TX_PWR)
374
pwr_val[i] = RF6052_MAX_TX_PWR;
376
writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
377
(pwr_val[1] << 8) | pwr_val[0];
380
regoffset = regoffset_a[index];
382
regoffset = regoffset_b[index];
383
rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
385
RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
386
("Set 0x%x = %08x\n", regoffset, writeVal));
388
if (((get_rf_type(rtlphy) == RF_2T2R) &&
389
(regoffset == RTXAGC_A_MCS15_MCS12 ||
390
regoffset == RTXAGC_B_MCS15_MCS12)) ||
391
((get_rf_type(rtlphy) != RF_2T2R) &&
392
(regoffset == RTXAGC_A_MCS07_MCS04 ||
393
regoffset == RTXAGC_B_MCS07_MCS04))) {
395
writeVal = pwr_val[3];
396
if (regoffset == RTXAGC_A_MCS15_MCS12 ||
397
regoffset == RTXAGC_A_MCS07_MCS04)
399
if (regoffset == RTXAGC_B_MCS15_MCS12 ||
400
regoffset == RTXAGC_B_MCS07_MCS04)
403
for (i = 0; i < 3; i++) {
404
writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
405
rtl_write_byte(rtlpriv, (u32) (regoffset + i),
412
void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
413
u8 *ppowerlevel, u8 channel)
415
u32 writeVal[2], powerBase0[2], powerBase1[2];
418
rtl92c_phy_get_power_base(hw, ppowerlevel,
419
channel, &powerBase0[0], &powerBase1[0]);
421
for (index = 0; index < 6; index++) {
422
_rtl92c_get_txpower_writeval_by_regulatory(hw,
428
_rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]);
432
bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw)
434
struct rtl_priv *rtlpriv = rtl_priv(hw);
435
struct rtl_phy *rtlphy = &(rtlpriv->phy);
437
if (rtlphy->rf_type == RF_1T1R)
438
rtlphy->num_total_rfpath = 1;
440
rtlphy->num_total_rfpath = 2;
442
return _rtl92ce_phy_rf6052_config_parafile(hw);
446
static bool _rtl92ce_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
448
struct rtl_priv *rtlpriv = rtl_priv(hw);
449
struct rtl_phy *rtlphy = &(rtlpriv->phy);
452
bool rtstatus = true;
453
struct bb_reg_def *pphyreg;
455
for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
457
pphyreg = &rtlphy->phyreg_def[rfpath];
462
u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
467
u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
472
rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
475
rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
478
rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
479
B3WIREADDREAALENGTH, 0x0);
482
rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
487
rtstatus = rtl92c_phy_config_rf_with_headerfile(hw,
488
(enum radio_path)rfpath);
491
rtstatus = rtl92c_phy_config_rf_with_headerfile(hw,
492
(enum radio_path)rfpath);
503
rtl_set_bbreg(hw, pphyreg->rfintfs,
504
BRFSI_RFENV, u4_regvalue);
508
rtl_set_bbreg(hw, pphyreg->rfintfs,
509
BRFSI_RFENV << 16, u4_regvalue);
513
if (rtstatus != true) {
514
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
515
("Radio[%d] Fail!!", rfpath));
521
RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n"));