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