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 *(p_outwriteval + rf) = writeVal;
303 }
304}
305
306static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
307 u8 index, u32 *pValue)
308{
309 struct rtl_priv *rtlpriv = rtl_priv(hw);
310 struct rtl_phy *rtlphy = &(rtlpriv->phy);
311 u16 regoffset_a[6] = {
312 RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
313 RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
314 RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
315 };
316 u16 regoffset_b[6] = {
317 RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
318 RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
319 RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
320 };
321 u8 i, rf, pwr_val[4];
322 u32 writeVal;
323 u16 regoffset;
324
325 for (rf = 0; rf < 2; rf++) {
326 writeVal = pValue[rf];
327 for (i = 0; i < 4; i++) {
328 pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >>
329 (i * 8));
330 if (pwr_val[i] > RF6052_MAX_TX_PWR)
331 pwr_val[i] = RF6052_MAX_TX_PWR;
332 }
333 writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
334 (pwr_val[1] << 8) | pwr_val[0];
335 if (rf == 0)
336 regoffset = regoffset_a[index];
337 else
338 regoffset = regoffset_b[index];
339 rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
340 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
341 "Set 0x%x = %08x\n", regoffset, writeVal);
342 if (((get_rf_type(rtlphy) == RF_2T2R) &&
343 (regoffset == RTXAGC_A_MCS15_MCS12 ||
344 regoffset == RTXAGC_B_MCS15_MCS12)) ||
345 ((get_rf_type(rtlphy) != RF_2T2R) &&
346 (regoffset == RTXAGC_A_MCS07_MCS04 ||
347 regoffset == RTXAGC_B_MCS07_MCS04))) {
348 writeVal = pwr_val[3];
349 if (regoffset == RTXAGC_A_MCS15_MCS12 ||
350 regoffset == RTXAGC_A_MCS07_MCS04)
351 regoffset = 0xc90;
352 if (regoffset == RTXAGC_B_MCS15_MCS12 ||
353 regoffset == RTXAGC_B_MCS07_MCS04)
354 regoffset = 0xc98;
355 for (i = 0; i < 3; i++) {
356 if (i != 2)
357 writeVal = (writeVal > 8) ?
358 (writeVal - 8) : 0;
359 else
360 writeVal = (writeVal > 6) ?
361 (writeVal - 6) : 0;
362 rtl_write_byte(rtlpriv, (u32)(regoffset + i),
363 (u8)writeVal);
364 }
365 }
366 }
367}
368
369void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
370 u8 *ppowerlevel, u8 channel)
371{
372 u32 writeVal[2], powerBase0[2], powerBase1[2];
373 u8 index = 0;
374
375 rtl92c_phy_get_power_base(hw, ppowerlevel,
376 channel, &powerBase0[0], &powerBase1[0]);
377 for (index = 0; index < 6; index++) {
378 _rtl92c_get_txpower_writeval_by_regulatory(hw,
379 channel, index,
380 &powerBase0[0],
381 &powerBase1[0],
382 &writeVal[0]);
383 _rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]);
384 }
385}
386
387bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw)
388{
389 struct rtl_priv *rtlpriv = rtl_priv(hw);
390 struct rtl_phy *rtlphy = &(rtlpriv->phy);
391 bool rtstatus = true;
392 u8 b_reg_hwparafile = 1;
393
394 if (rtlphy->rf_type == RF_1T1R)
395 rtlphy->num_total_rfpath = 1;
396 else
397 rtlphy->num_total_rfpath = 2;
398 if (b_reg_hwparafile == 1)
399 rtstatus = _rtl92c_phy_rf6052_config_parafile(hw);
400 return rtstatus;
401}
402
403static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
404{
405 struct rtl_priv *rtlpriv = rtl_priv(hw);
406 struct rtl_phy *rtlphy = &(rtlpriv->phy);
407 u32 u4_regvalue = 0;
408 u8 rfpath;
409 bool rtstatus = true;
410 struct bb_reg_def *pphyreg;
411
412 for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
413 pphyreg = &rtlphy->phyreg_def[rfpath];
414 switch (rfpath) {
415 case RF90_PATH_A:
416 case RF90_PATH_C:
417 u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
418 BRFSI_RFENV);
419 break;
420 case RF90_PATH_B:
421 case RF90_PATH_D:
422 u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
423 BRFSI_RFENV << 16);
424 break;
425 }
426 rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
427 udelay(1);
428 rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
429 udelay(1);
430 rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
431 B3WIREADDREAALENGTH, 0x0);
432 udelay(1);
433 rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
434 udelay(1);
435 switch (rfpath) {
436 case RF90_PATH_A:
437 case RF90_PATH_B:
438 rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,
439 (enum radio_path) rfpath);
440 break;
441 case RF90_PATH_C:
442 break;
443 case RF90_PATH_D:
444 break;
445 }
446 switch (rfpath) {
447 case RF90_PATH_A:
448 case RF90_PATH_C:
449 rtl_set_bbreg(hw, pphyreg->rfintfs,
450 BRFSI_RFENV, u4_regvalue);
451 break;
452 case RF90_PATH_B:
453 case RF90_PATH_D:
454 rtl_set_bbreg(hw, pphyreg->rfintfs,
455 BRFSI_RFENV << 16, u4_regvalue);
456 break;
457 }
458 if (!rtstatus) {
459 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
460 "Radio[%d] Fail!!\n", rfpath);
461 goto phy_rf_cfg_fail;
462 }
463 }
464 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");
465phy_rf_cfg_fail:
466 return rtstatus;
467}
468