diff options
author | Larry Finger <Larry.Finger@lwfinger.net> | 2014-02-28 16:16:50 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-03-04 13:25:39 -0500 |
commit | a619d1abe20cc892ddd8f6f60345b24d43971fb4 (patch) | |
tree | 25643f37e962f1753f45fb3763313ba63cf94144 /drivers/net/wireless/rtlwifi/rtl8723be/phy.c | |
parent | 57d9d9630a6b3f289ae87b1fc00e83ae44636766 (diff) |
rtlwifi: rtl8723be: Add new driver
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtlwifi/rtl8723be/phy.c')
-rw-r--r-- | drivers/net/wireless/rtlwifi/rtl8723be/phy.c | 2175 |
1 files changed, 2175 insertions, 0 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/phy.c b/drivers/net/wireless/rtlwifi/rtl8723be/phy.c new file mode 100644 index 000000000000..ebc1e2788fca --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8723be/phy.c | |||
@@ -0,0 +1,2175 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2014 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 | * The full GNU General Public License is included in this distribution in the | ||
15 | * file called LICENSE. | ||
16 | * | ||
17 | * Contact Information: | ||
18 | * wlanfae <wlanfae@realtek.com> | ||
19 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
20 | * Hsinchu 300, Taiwan. | ||
21 | * | ||
22 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
23 | * | ||
24 | *****************************************************************************/ | ||
25 | |||
26 | #include "../wifi.h" | ||
27 | #include "../pci.h" | ||
28 | #include "../ps.h" | ||
29 | #include "reg.h" | ||
30 | #include "def.h" | ||
31 | #include "phy.h" | ||
32 | #include "../rtl8723com/phy_common.h" | ||
33 | #include "rf.h" | ||
34 | #include "dm.h" | ||
35 | #include "table.h" | ||
36 | #include "trx.h" | ||
37 | |||
38 | static bool _rtl8723be_phy_bb8723b_config_parafile(struct ieee80211_hw *hw); | ||
39 | static bool _rtl8723be_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, | ||
40 | u8 configtype); | ||
41 | static bool rtl8723be_phy_sw_chn_step_by_step(struct ieee80211_hw *hw, | ||
42 | u8 channel, u8 *stage, | ||
43 | u8 *step, u32 *delay); | ||
44 | static void _rtl8723be_config_bb_reg(struct ieee80211_hw *hw, | ||
45 | u32 addr, u32 data); | ||
46 | |||
47 | static bool _rtl8723be_check_condition(struct ieee80211_hw *hw, | ||
48 | const u32 condition) | ||
49 | { | ||
50 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
51 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
52 | u32 _board = rtlefuse->board_type; /*need efuse define*/ | ||
53 | u32 _interface = rtlhal->interface; | ||
54 | u32 _platform = 0x08;/*SupportPlatform */ | ||
55 | u32 cond = condition; | ||
56 | |||
57 | if (condition == 0xCDCDCDCD) | ||
58 | return true; | ||
59 | |||
60 | cond = condition & 0xFF; | ||
61 | if ((_board & cond) == 0 && cond != 0x1F) | ||
62 | return false; | ||
63 | |||
64 | cond = condition & 0xFF00; | ||
65 | cond = cond >> 8; | ||
66 | if ((_interface & cond) == 0 && cond != 0x07) | ||
67 | return false; | ||
68 | |||
69 | cond = condition & 0xFF0000; | ||
70 | cond = cond >> 16; | ||
71 | if ((_platform & cond) == 0 && cond != 0x0F) | ||
72 | return false; | ||
73 | return true; | ||
74 | } | ||
75 | |||
76 | static bool _rtl8723be_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) | ||
77 | { | ||
78 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
79 | u32 i; | ||
80 | u32 arraylength; | ||
81 | u32 *ptrarray; | ||
82 | |||
83 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read rtl8723beMACPHY_Array\n"); | ||
84 | arraylength = RTL8723BEMAC_1T_ARRAYLEN; | ||
85 | ptrarray = RTL8723BEMAC_1T_ARRAY; | ||
86 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
87 | "Img:RTL8723bEMAC_1T_ARRAY LEN %d\n", arraylength); | ||
88 | for (i = 0; i < arraylength; i = i + 2) | ||
89 | rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); | ||
90 | return true; | ||
91 | } | ||
92 | |||
93 | static bool _rtl8723be_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, | ||
94 | u8 configtype) | ||
95 | { | ||
96 | #define READ_NEXT_PAIR(v1, v2, i) \ | ||
97 | do { \ | ||
98 | i += 2; \ | ||
99 | v1 = array_table[i];\ | ||
100 | v2 = array_table[i+1]; \ | ||
101 | } while (0) | ||
102 | |||
103 | int i; | ||
104 | u32 *array_table; | ||
105 | u16 arraylen; | ||
106 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
107 | u32 v1 = 0, v2 = 0; | ||
108 | |||
109 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | ||
110 | arraylen = RTL8723BEPHY_REG_1TARRAYLEN; | ||
111 | array_table = RTL8723BEPHY_REG_1TARRAY; | ||
112 | |||
113 | for (i = 0; i < arraylen; i = i + 2) { | ||
114 | v1 = array_table[i]; | ||
115 | v2 = array_table[i+1]; | ||
116 | if (v1 < 0xcdcdcdcd) { | ||
117 | _rtl8723be_config_bb_reg(hw, v1, v2); | ||
118 | } else {/*This line is the start line of branch.*/ | ||
119 | if (!_rtl8723be_check_condition(hw, array_table[i])) { | ||
120 | /*Discard the following (offset, data) pairs*/ | ||
121 | READ_NEXT_PAIR(v1, v2, i); | ||
122 | while (v2 != 0xDEAD && | ||
123 | v2 != 0xCDEF && | ||
124 | v2 != 0xCDCD && | ||
125 | i < arraylen - 2) { | ||
126 | READ_NEXT_PAIR(v1, v2, i); | ||
127 | } | ||
128 | i -= 2; /* prevent from for-loop += 2*/ | ||
129 | /* Configure matched pairs and | ||
130 | * skip to end of if-else. | ||
131 | */ | ||
132 | } else { | ||
133 | READ_NEXT_PAIR(v1, v2, i); | ||
134 | while (v2 != 0xDEAD && | ||
135 | v2 != 0xCDEF && | ||
136 | v2 != 0xCDCD && | ||
137 | i < arraylen - 2) { | ||
138 | _rtl8723be_config_bb_reg(hw, | ||
139 | v1, v2); | ||
140 | READ_NEXT_PAIR(v1, v2, i); | ||
141 | } | ||
142 | |||
143 | while (v2 != 0xDEAD && i < arraylen - 2) | ||
144 | READ_NEXT_PAIR(v1, v2, i); | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { | ||
149 | arraylen = RTL8723BEAGCTAB_1TARRAYLEN; | ||
150 | array_table = RTL8723BEAGCTAB_1TARRAY; | ||
151 | |||
152 | for (i = 0; i < arraylen; i = i + 2) { | ||
153 | v1 = array_table[i]; | ||
154 | v2 = array_table[i+1]; | ||
155 | if (v1 < 0xCDCDCDCD) { | ||
156 | rtl_set_bbreg(hw, array_table[i], | ||
157 | MASKDWORD, | ||
158 | array_table[i + 1]); | ||
159 | udelay(1); | ||
160 | continue; | ||
161 | } else {/*This line is the start line of branch.*/ | ||
162 | if (!_rtl8723be_check_condition(hw, array_table[i])) { | ||
163 | /* Discard the following | ||
164 | * (offset, data) pairs | ||
165 | */ | ||
166 | READ_NEXT_PAIR(v1, v2, i); | ||
167 | while (v2 != 0xDEAD && | ||
168 | v2 != 0xCDEF && | ||
169 | v2 != 0xCDCD && | ||
170 | i < arraylen - 2) { | ||
171 | READ_NEXT_PAIR(v1, v2, i); | ||
172 | } | ||
173 | i -= 2; /* prevent from for-loop += 2*/ | ||
174 | /*Configure matched pairs and | ||
175 | *skip to end of if-else. | ||
176 | */ | ||
177 | } else { | ||
178 | READ_NEXT_PAIR(v1, v2, i); | ||
179 | while (v2 != 0xDEAD && | ||
180 | v2 != 0xCDEF && | ||
181 | v2 != 0xCDCD && | ||
182 | i < arraylen - 2) { | ||
183 | rtl_set_bbreg(hw, array_table[i], | ||
184 | MASKDWORD, | ||
185 | array_table[i + 1]); | ||
186 | udelay(1); | ||
187 | READ_NEXT_PAIR(v1, v2, i); | ||
188 | } | ||
189 | |||
190 | while (v2 != 0xDEAD && i < arraylen - 2) | ||
191 | READ_NEXT_PAIR(v1, v2, i); | ||
192 | } | ||
193 | } | ||
194 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
195 | "The agctab_array_table[0] is " | ||
196 | "%x Rtl818EEPHY_REGArray[1] is %x\n", | ||
197 | array_table[i], array_table[i + 1]); | ||
198 | } | ||
199 | } | ||
200 | return true; | ||
201 | } | ||
202 | |||
203 | static u8 _rtl8723be_get_rate_section_index(u32 regaddr) | ||
204 | { | ||
205 | u8 index = 0; | ||
206 | |||
207 | switch (regaddr) { | ||
208 | case RTXAGC_A_RATE18_06: | ||
209 | case RTXAGC_B_RATE18_06: | ||
210 | index = 0; | ||
211 | break; | ||
212 | case RTXAGC_A_RATE54_24: | ||
213 | case RTXAGC_B_RATE54_24: | ||
214 | index = 1; | ||
215 | break; | ||
216 | case RTXAGC_A_CCK1_MCS32: | ||
217 | case RTXAGC_B_CCK1_55_MCS32: | ||
218 | index = 2; | ||
219 | break; | ||
220 | case RTXAGC_B_CCK11_A_CCK2_11: | ||
221 | index = 3; | ||
222 | break; | ||
223 | case RTXAGC_A_MCS03_MCS00: | ||
224 | case RTXAGC_B_MCS03_MCS00: | ||
225 | index = 4; | ||
226 | break; | ||
227 | case RTXAGC_A_MCS07_MCS04: | ||
228 | case RTXAGC_B_MCS07_MCS04: | ||
229 | index = 5; | ||
230 | break; | ||
231 | case RTXAGC_A_MCS11_MCS08: | ||
232 | case RTXAGC_B_MCS11_MCS08: | ||
233 | index = 6; | ||
234 | break; | ||
235 | case RTXAGC_A_MCS15_MCS12: | ||
236 | case RTXAGC_B_MCS15_MCS12: | ||
237 | index = 7; | ||
238 | break; | ||
239 | default: | ||
240 | regaddr &= 0xFFF; | ||
241 | if (regaddr >= 0xC20 && regaddr <= 0xC4C) | ||
242 | index = (u8) ((regaddr - 0xC20) / 4); | ||
243 | else if (regaddr >= 0xE20 && regaddr <= 0xE4C) | ||
244 | index = (u8) ((regaddr - 0xE20) / 4); | ||
245 | break; | ||
246 | }; | ||
247 | return index; | ||
248 | } | ||
249 | |||
250 | u32 rtl8723be_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, | ||
251 | u32 regaddr, u32 bitmask) | ||
252 | { | ||
253 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
254 | u32 original_value, readback_value, bitshift; | ||
255 | unsigned long flags; | ||
256 | |||
257 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
258 | "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", | ||
259 | regaddr, rfpath, bitmask); | ||
260 | |||
261 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | ||
262 | |||
263 | original_value = rtl8723_phy_rf_serial_read(hw, rfpath, regaddr); | ||
264 | bitshift = rtl8723_phy_calculate_bit_shift(bitmask); | ||
265 | readback_value = (original_value & bitmask) >> bitshift; | ||
266 | |||
267 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | ||
268 | |||
269 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
270 | "regaddr(%#x), rfpath(%#x), " | ||
271 | "bitmask(%#x), original_value(%#x)\n", | ||
272 | regaddr, rfpath, bitmask, original_value); | ||
273 | |||
274 | return readback_value; | ||
275 | } | ||
276 | |||
277 | void rtl8723be_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path path, | ||
278 | u32 regaddr, u32 bitmask, u32 data) | ||
279 | { | ||
280 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
281 | u32 original_value, bitshift; | ||
282 | unsigned long flags; | ||
283 | |||
284 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
285 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", | ||
286 | regaddr, bitmask, data, path); | ||
287 | |||
288 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | ||
289 | |||
290 | if (bitmask != RFREG_OFFSET_MASK) { | ||
291 | original_value = rtl8723_phy_rf_serial_read(hw, path, | ||
292 | regaddr); | ||
293 | bitshift = rtl8723_phy_calculate_bit_shift(bitmask); | ||
294 | data = ((original_value & (~bitmask)) | | ||
295 | (data << bitshift)); | ||
296 | } | ||
297 | |||
298 | rtl8723_phy_rf_serial_write(hw, path, regaddr, data); | ||
299 | |||
300 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | ||
301 | |||
302 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
303 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", | ||
304 | regaddr, bitmask, data, path); | ||
305 | } | ||
306 | |||
307 | bool rtl8723be_phy_mac_config(struct ieee80211_hw *hw) | ||
308 | { | ||
309 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
310 | bool rtstatus = _rtl8723be_phy_config_mac_with_headerfile(hw); | ||
311 | |||
312 | rtl_write_byte(rtlpriv, 0x04CA, 0x0B); | ||
313 | return rtstatus; | ||
314 | } | ||
315 | |||
316 | bool rtl8723be_phy_bb_config(struct ieee80211_hw *hw) | ||
317 | { | ||
318 | bool rtstatus = true; | ||
319 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
320 | u16 regval; | ||
321 | u8 reg_hwparafile = 1; | ||
322 | u32 tmp; | ||
323 | u8 crystalcap = rtlpriv->efuse.crystalcap; | ||
324 | rtl8723_phy_init_bb_rf_reg_def(hw); | ||
325 | regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); | ||
326 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, | ||
327 | regval | BIT(13) | BIT(0) | BIT(1)); | ||
328 | |||
329 | rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); | ||
330 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, | ||
331 | FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | | ||
332 | FEN_BB_GLB_RSTN | FEN_BBRSTB); | ||
333 | tmp = rtl_read_dword(rtlpriv, 0x4c); | ||
334 | rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23)); | ||
335 | |||
336 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); | ||
337 | |||
338 | if (reg_hwparafile == 1) | ||
339 | rtstatus = _rtl8723be_phy_bb8723b_config_parafile(hw); | ||
340 | |||
341 | crystalcap = crystalcap & 0x3F; | ||
342 | rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, | ||
343 | (crystalcap | crystalcap << 6)); | ||
344 | |||
345 | return rtstatus; | ||
346 | } | ||
347 | |||
348 | bool rtl8723be_phy_rf_config(struct ieee80211_hw *hw) | ||
349 | { | ||
350 | return rtl8723be_phy_rf6052_config(hw); | ||
351 | } | ||
352 | |||
353 | static void _rtl8723be_config_rf_reg(struct ieee80211_hw *hw, u32 addr, | ||
354 | u32 data, enum radio_path rfpath, | ||
355 | u32 regaddr) | ||
356 | { | ||
357 | if (addr == 0xfe || addr == 0xffe) { | ||
358 | mdelay(50); | ||
359 | } else { | ||
360 | rtl_set_rfreg(hw, rfpath, regaddr, RFREG_OFFSET_MASK, data); | ||
361 | udelay(1); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | static void _rtl8723be_config_rf_radio_a(struct ieee80211_hw *hw, | ||
366 | u32 addr, u32 data) | ||
367 | { | ||
368 | u32 content = 0x1000; /*RF Content: radio_a_txt*/ | ||
369 | u32 maskforphyset = (u32)(content & 0xE000); | ||
370 | |||
371 | _rtl8723be_config_rf_reg(hw, addr, data, RF90_PATH_A, | ||
372 | addr | maskforphyset); | ||
373 | } | ||
374 | |||
375 | static void _rtl8723be_phy_init_tx_power_by_rate(struct ieee80211_hw *hw) | ||
376 | { | ||
377 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
378 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
379 | |||
380 | u8 band, path, txnum, section; | ||
381 | |||
382 | for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band) | ||
383 | for (path = 0; path < TX_PWR_BY_RATE_NUM_RF; ++path) | ||
384 | for (txnum = 0; txnum < TX_PWR_BY_RATE_NUM_RF; ++txnum) | ||
385 | for (section = 0; | ||
386 | section < TX_PWR_BY_RATE_NUM_SECTION; | ||
387 | ++section) | ||
388 | rtlphy->tx_power_by_rate_offset[band] | ||
389 | [path][txnum][section] = 0; | ||
390 | } | ||
391 | |||
392 | static void _rtl8723be_config_bb_reg(struct ieee80211_hw *hw, | ||
393 | u32 addr, u32 data) | ||
394 | { | ||
395 | if (addr == 0xfe) { | ||
396 | mdelay(50); | ||
397 | } else if (addr == 0xfd) { | ||
398 | mdelay(5); | ||
399 | } else if (addr == 0xfc) { | ||
400 | mdelay(1); | ||
401 | } else if (addr == 0xfb) { | ||
402 | udelay(50); | ||
403 | } else if (addr == 0xfa) { | ||
404 | udelay(5); | ||
405 | } else if (addr == 0xf9) { | ||
406 | udelay(1); | ||
407 | } else { | ||
408 | rtl_set_bbreg(hw, addr, MASKDWORD, data); | ||
409 | udelay(1); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | static void phy_set_txpwr_by_rate_base(struct ieee80211_hw *hw, u8 band, | ||
414 | u8 path, u8 rate_section, | ||
415 | u8 txnum, u8 value) | ||
416 | { | ||
417 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
418 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
419 | |||
420 | if (path > RF90_PATH_D) { | ||
421 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
422 | "Invalid Rf Path %d in phy_SetTxPowerByRatBase()\n", | ||
423 | path); | ||
424 | return; | ||
425 | } | ||
426 | |||
427 | if (band == BAND_ON_2_4G) { | ||
428 | switch (rate_section) { | ||
429 | case CCK: | ||
430 | rtlphy->txpwr_by_rate_base_24g[path][txnum][0] = value; | ||
431 | break; | ||
432 | case OFDM: | ||
433 | rtlphy->txpwr_by_rate_base_24g[path][txnum][1] = value; | ||
434 | break; | ||
435 | case HT_MCS0_MCS7: | ||
436 | rtlphy->txpwr_by_rate_base_24g[path][txnum][2] = value; | ||
437 | break; | ||
438 | case HT_MCS8_MCS15: | ||
439 | rtlphy->txpwr_by_rate_base_24g[path][txnum][3] = value; | ||
440 | break; | ||
441 | default: | ||
442 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
443 | "Invalid RateSection %d in Band 2.4G, Rf Path" | ||
444 | " %d, %dTx in PHY_SetTxPowerByRateBase()\n", | ||
445 | rate_section, path, txnum); | ||
446 | break; | ||
447 | }; | ||
448 | } else { | ||
449 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
450 | "Invalid Band %d in PHY_SetTxPowerByRateBase()\n", | ||
451 | band); | ||
452 | } | ||
453 | } | ||
454 | |||
455 | static u8 phy_get_txpwr_by_rate_base(struct ieee80211_hw *hw, u8 band, u8 path, | ||
456 | u8 txnum, u8 rate_section) | ||
457 | { | ||
458 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
459 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
460 | u8 value = 0; | ||
461 | if (path > RF90_PATH_D) { | ||
462 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
463 | "Invalid Rf Path %d in PHY_GetTxPowerByRateBase()\n", | ||
464 | path); | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | if (band == BAND_ON_2_4G) { | ||
469 | switch (rate_section) { | ||
470 | case CCK: | ||
471 | value = rtlphy->txpwr_by_rate_base_24g[path][txnum][0]; | ||
472 | break; | ||
473 | case OFDM: | ||
474 | value = rtlphy->txpwr_by_rate_base_24g[path][txnum][1]; | ||
475 | break; | ||
476 | case HT_MCS0_MCS7: | ||
477 | value = rtlphy->txpwr_by_rate_base_24g[path][txnum][2]; | ||
478 | break; | ||
479 | case HT_MCS8_MCS15: | ||
480 | value = rtlphy->txpwr_by_rate_base_24g[path][txnum][3]; | ||
481 | break; | ||
482 | default: | ||
483 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
484 | "Invalid RateSection %d in Band 2.4G, Rf Path" | ||
485 | " %d, %dTx in PHY_GetTxPowerByRateBase()\n", | ||
486 | rate_section, path, txnum); | ||
487 | break; | ||
488 | }; | ||
489 | } else { | ||
490 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
491 | "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", | ||
492 | band); | ||
493 | } | ||
494 | |||
495 | return value; | ||
496 | } | ||
497 | |||
498 | static void _rtl8723be_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw) | ||
499 | { | ||
500 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
501 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
502 | u16 raw_value = 0; | ||
503 | u8 base = 0, path = 0; | ||
504 | |||
505 | for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) { | ||
506 | if (path == RF90_PATH_A) { | ||
507 | raw_value = (u16) (rtlphy->tx_power_by_rate_offset | ||
508 | [BAND_ON_2_4G][path][RF_1TX][3] >> 24) & 0xFF; | ||
509 | base = (raw_value >> 4) * 10 + (raw_value & 0xF); | ||
510 | phy_set_txpwr_by_rate_base(hw, BAND_ON_2_4G, path, CCK, | ||
511 | RF_1TX, base); | ||
512 | } else if (path == RF90_PATH_B) { | ||
513 | raw_value = (u16) (rtlphy->tx_power_by_rate_offset | ||
514 | [BAND_ON_2_4G][path][RF_1TX][3] >> 0) & 0xFF; | ||
515 | base = (raw_value >> 4) * 10 + (raw_value & 0xF); | ||
516 | phy_set_txpwr_by_rate_base(hw, BAND_ON_2_4G, path, | ||
517 | CCK, RF_1TX, base); | ||
518 | } | ||
519 | raw_value = (u16) (rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
520 | [path][RF_1TX][1] >> 24) & 0xFF; | ||
521 | base = (raw_value >> 4) * 10 + (raw_value & 0xF); | ||
522 | phy_set_txpwr_by_rate_base(hw, BAND_ON_2_4G, path, OFDM, RF_1TX, | ||
523 | base); | ||
524 | |||
525 | raw_value = (u16) (rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
526 | [path][RF_1TX][5] >> 24) & 0xFF; | ||
527 | base = (raw_value >> 4) * 10 + (raw_value & 0xF); | ||
528 | phy_set_txpwr_by_rate_base(hw, BAND_ON_2_4G, path, HT_MCS0_MCS7, | ||
529 | RF_1TX, base); | ||
530 | |||
531 | raw_value = (u16) (rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
532 | [path][RF_2TX][7] >> 24) & 0xFF; | ||
533 | base = (raw_value >> 4) * 10 + (raw_value & 0xF); | ||
534 | phy_set_txpwr_by_rate_base(hw, BAND_ON_2_4G, path, | ||
535 | HT_MCS8_MCS15, RF_2TX, base); | ||
536 | } | ||
537 | } | ||
538 | |||
539 | static void phy_conv_dbm_to_rel(u32 *data, u8 start, u8 end, u8 base_val) | ||
540 | { | ||
541 | char i = 0; | ||
542 | u8 temp_value = 0; | ||
543 | u32 temp_data = 0; | ||
544 | |||
545 | for (i = 3; i >= 0; --i) { | ||
546 | if (i >= start && i <= end) { | ||
547 | /* Get the exact value */ | ||
548 | temp_value = (u8) (*data >> (i * 8)) & 0xF; | ||
549 | temp_value += ((u8) ((*data >> (i*8 + 4)) & 0xF)) * 10; | ||
550 | |||
551 | /* Change the value to a relative value */ | ||
552 | temp_value = (temp_value > base_val) ? | ||
553 | temp_value - base_val : | ||
554 | base_val - temp_value; | ||
555 | } else { | ||
556 | temp_value = (u8) (*data >> (i * 8)) & 0xFF; | ||
557 | } | ||
558 | temp_data <<= 8; | ||
559 | temp_data |= temp_value; | ||
560 | } | ||
561 | *data = temp_data; | ||
562 | } | ||
563 | |||
564 | static void conv_dbm_to_rel(struct ieee80211_hw *hw) | ||
565 | { | ||
566 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
567 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
568 | u8 base = 0, rfpath = RF90_PATH_A; | ||
569 | |||
570 | base = phy_get_txpwr_by_rate_base(hw, BAND_ON_2_4G, rfpath, | ||
571 | RF_1TX, CCK); | ||
572 | phy_conv_dbm_to_rel(&(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
573 | [rfpath][RF_1TX][2]), 1, 1, base); | ||
574 | phy_conv_dbm_to_rel(&(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
575 | [rfpath][RF_1TX][3]), 1, 3, base); | ||
576 | |||
577 | base = phy_get_txpwr_by_rate_base(hw, BAND_ON_2_4G, rfpath, | ||
578 | RF_1TX, OFDM); | ||
579 | phy_conv_dbm_to_rel(&(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
580 | [rfpath][RF_1TX][0]), 0, 3, base); | ||
581 | phy_conv_dbm_to_rel(&(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
582 | [rfpath][RF_1TX][1]), 0, 3, base); | ||
583 | |||
584 | base = phy_get_txpwr_by_rate_base(hw, BAND_ON_2_4G, rfpath, | ||
585 | RF_1TX, HT_MCS0_MCS7); | ||
586 | phy_conv_dbm_to_rel(&(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
587 | [rfpath][RF_1TX][4]), 0, 3, base); | ||
588 | phy_conv_dbm_to_rel(&(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
589 | [rfpath][RF_1TX][5]), 0, 3, base); | ||
590 | |||
591 | base = phy_get_txpwr_by_rate_base(hw, BAND_ON_2_4G, rfpath, | ||
592 | RF_2TX, HT_MCS8_MCS15); | ||
593 | phy_conv_dbm_to_rel(&(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
594 | [rfpath][RF_2TX][6]), 0, 3, base); | ||
595 | |||
596 | phy_conv_dbm_to_rel(&(rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G] | ||
597 | [rfpath][RF_2TX][7]), 0, 3, base); | ||
598 | |||
599 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, | ||
600 | "<=== conv_dbm_to_rel()\n"); | ||
601 | } | ||
602 | |||
603 | static void _rtl8723be_phy_txpower_by_rate_configuration( | ||
604 | struct ieee80211_hw *hw) | ||
605 | { | ||
606 | _rtl8723be_phy_store_txpower_by_rate_base(hw); | ||
607 | conv_dbm_to_rel(hw); | ||
608 | } | ||
609 | |||
610 | static bool _rtl8723be_phy_bb8723b_config_parafile(struct ieee80211_hw *hw) | ||
611 | { | ||
612 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
613 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
614 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
615 | bool rtstatus; | ||
616 | |||
617 | rtstatus = _rtl8723be_phy_config_bb_with_headerfile(hw, | ||
618 | BASEBAND_CONFIG_PHY_REG); | ||
619 | if (!rtstatus) { | ||
620 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); | ||
621 | return false; | ||
622 | } | ||
623 | _rtl8723be_phy_init_tx_power_by_rate(hw); | ||
624 | if (!rtlefuse->autoload_failflag) { | ||
625 | rtlphy->pwrgroup_cnt = 0; | ||
626 | rtstatus = _rtl8723be_phy_config_bb_with_pgheaderfile(hw, | ||
627 | BASEBAND_CONFIG_PHY_REG); | ||
628 | } | ||
629 | _rtl8723be_phy_txpower_by_rate_configuration(hw); | ||
630 | if (!rtstatus) { | ||
631 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); | ||
632 | return false; | ||
633 | } | ||
634 | rtstatus = _rtl8723be_phy_config_bb_with_headerfile(hw, | ||
635 | BASEBAND_CONFIG_AGC_TAB); | ||
636 | if (!rtstatus) { | ||
637 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); | ||
638 | return false; | ||
639 | } | ||
640 | rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, | ||
641 | RFPGA0_XA_HSSIPARAMETER2, | ||
642 | 0x200)); | ||
643 | return true; | ||
644 | } | ||
645 | |||
646 | static void _rtl8723be_store_tx_power_by_rate(struct ieee80211_hw *hw, | ||
647 | u32 band, u32 rfpath, | ||
648 | u32 txnum, u32 regaddr, | ||
649 | u32 bitmask, u32 data) | ||
650 | { | ||
651 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
652 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
653 | u8 rate_section = _rtl8723be_get_rate_section_index(regaddr); | ||
654 | |||
655 | if (band != BAND_ON_2_4G && band != BAND_ON_5G) | ||
656 | RT_TRACE(rtlpriv, COMP_POWER, PHY_TXPWR, | ||
657 | "Invalid Band %d\n", band); | ||
658 | |||
659 | if (rfpath > MAX_RF_PATH) | ||
660 | RT_TRACE(rtlpriv, COMP_POWER, PHY_TXPWR, | ||
661 | "Invalid RfPath %d\n", rfpath); | ||
662 | |||
663 | if (txnum > MAX_RF_PATH) | ||
664 | RT_TRACE(rtlpriv, COMP_POWER, PHY_TXPWR, | ||
665 | "Invalid TxNum %d\n", txnum); | ||
666 | |||
667 | rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = | ||
668 | data; | ||
669 | } | ||
670 | |||
671 | static bool _rtl8723be_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, | ||
672 | u8 configtype) | ||
673 | { | ||
674 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
675 | int i; | ||
676 | u32 *phy_regarray_table_pg; | ||
677 | u16 phy_regarray_pg_len; | ||
678 | u32 v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0, v6 = 0; | ||
679 | |||
680 | phy_regarray_pg_len = RTL8723BEPHY_REG_ARRAY_PGLEN; | ||
681 | phy_regarray_table_pg = RTL8723BEPHY_REG_ARRAY_PG; | ||
682 | |||
683 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | ||
684 | for (i = 0; i < phy_regarray_pg_len; i = i + 6) { | ||
685 | v1 = phy_regarray_table_pg[i]; | ||
686 | v2 = phy_regarray_table_pg[i+1]; | ||
687 | v3 = phy_regarray_table_pg[i+2]; | ||
688 | v4 = phy_regarray_table_pg[i+3]; | ||
689 | v5 = phy_regarray_table_pg[i+4]; | ||
690 | v6 = phy_regarray_table_pg[i+5]; | ||
691 | |||
692 | if (v1 < 0xcdcdcdcd) { | ||
693 | if (phy_regarray_table_pg[i] == 0xfe || | ||
694 | phy_regarray_table_pg[i] == 0xffe) | ||
695 | mdelay(50); | ||
696 | else | ||
697 | _rtl8723be_store_tx_power_by_rate(hw, | ||
698 | v1, v2, v3, v4, v5, v6); | ||
699 | continue; | ||
700 | } else { | ||
701 | /*don't need the hw_body*/ | ||
702 | if (!_rtl8723be_check_condition(hw, | ||
703 | phy_regarray_table_pg[i])) { | ||
704 | i += 2; /* skip the pair of expression*/ | ||
705 | v1 = phy_regarray_table_pg[i]; | ||
706 | v2 = phy_regarray_table_pg[i+1]; | ||
707 | v3 = phy_regarray_table_pg[i+2]; | ||
708 | while (v2 != 0xDEAD) { | ||
709 | i += 3; | ||
710 | v1 = phy_regarray_table_pg[i]; | ||
711 | v2 = phy_regarray_table_pg[i+1]; | ||
712 | v3 = phy_regarray_table_pg[i+2]; | ||
713 | } | ||
714 | } | ||
715 | } | ||
716 | } | ||
717 | } else { | ||
718 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | ||
719 | "configtype != BaseBand_Config_PHY_REG\n"); | ||
720 | } | ||
721 | return true; | ||
722 | } | ||
723 | |||
724 | bool rtl8723be_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, | ||
725 | enum radio_path rfpath) | ||
726 | { | ||
727 | #define READ_NEXT_RF_PAIR(v1, v2, i) \ | ||
728 | do { \ | ||
729 | i += 2; \ | ||
730 | v1 = radioa_array_table[i]; \ | ||
731 | v2 = radioa_array_table[i+1]; \ | ||
732 | } while (0) | ||
733 | |||
734 | int i; | ||
735 | bool rtstatus = true; | ||
736 | u32 *radioa_array_table; | ||
737 | u16 radioa_arraylen; | ||
738 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
739 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
740 | u32 v1 = 0, v2 = 0; | ||
741 | |||
742 | radioa_arraylen = RTL8723BE_RADIOA_1TARRAYLEN; | ||
743 | radioa_array_table = RTL8723BE_RADIOA_1TARRAY; | ||
744 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
745 | "Radio_A:RTL8723BE_RADIOA_1TARRAY %d\n", radioa_arraylen); | ||
746 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath); | ||
747 | rtstatus = true; | ||
748 | switch (rfpath) { | ||
749 | case RF90_PATH_A: | ||
750 | for (i = 0; i < radioa_arraylen; i = i + 2) { | ||
751 | v1 = radioa_array_table[i]; | ||
752 | v2 = radioa_array_table[i+1]; | ||
753 | if (v1 < 0xcdcdcdcd) { | ||
754 | _rtl8723be_config_rf_radio_a(hw, v1, v2); | ||
755 | } else { /*This line is the start line of branch.*/ | ||
756 | if (!_rtl8723be_check_condition(hw, | ||
757 | radioa_array_table[i])) { | ||
758 | /* Discard the following | ||
759 | * (offset, data) pairs | ||
760 | */ | ||
761 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
762 | while (v2 != 0xDEAD && | ||
763 | v2 != 0xCDEF && | ||
764 | v2 != 0xCDCD && | ||
765 | i < radioa_arraylen - 2) | ||
766 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
767 | i -= 2; /* prevent from for-loop += 2*/ | ||
768 | } else { | ||
769 | /* Configure matched pairs | ||
770 | * and skip to end of if-else. | ||
771 | */ | ||
772 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
773 | while (v2 != 0xDEAD && | ||
774 | v2 != 0xCDEF && | ||
775 | v2 != 0xCDCD && | ||
776 | i < radioa_arraylen - 2) { | ||
777 | _rtl8723be_config_rf_radio_a(hw, | ||
778 | v1, v2); | ||
779 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
780 | } | ||
781 | |||
782 | while (v2 != 0xDEAD && | ||
783 | i < radioa_arraylen - 2) { | ||
784 | READ_NEXT_RF_PAIR(v1, v2, i); | ||
785 | } | ||
786 | } | ||
787 | } | ||
788 | } | ||
789 | |||
790 | if (rtlhal->oem_id == RT_CID_819X_HP) | ||
791 | _rtl8723be_config_rf_radio_a(hw, 0x52, 0x7E4BD); | ||
792 | |||
793 | break; | ||
794 | case RF90_PATH_B: | ||
795 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
796 | "switch case not process\n"); | ||
797 | break; | ||
798 | case RF90_PATH_C: | ||
799 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
800 | "switch case not process\n"); | ||
801 | break; | ||
802 | case RF90_PATH_D: | ||
803 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
804 | "switch case not process\n"); | ||
805 | break; | ||
806 | } | ||
807 | return true; | ||
808 | } | ||
809 | |||
810 | void rtl8723be_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) | ||
811 | { | ||
812 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
813 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
814 | |||
815 | rtlphy->default_initialgain[0] = | ||
816 | (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); | ||
817 | rtlphy->default_initialgain[1] = | ||
818 | (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); | ||
819 | rtlphy->default_initialgain[2] = | ||
820 | (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); | ||
821 | rtlphy->default_initialgain[3] = | ||
822 | (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); | ||
823 | |||
824 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
825 | "Default initial gain (c50 = 0x%x, " | ||
826 | "c58 = 0x%x, c60 = 0x%x, c68 = 0x%x\n", | ||
827 | rtlphy->default_initialgain[0], | ||
828 | rtlphy->default_initialgain[1], | ||
829 | rtlphy->default_initialgain[2], | ||
830 | rtlphy->default_initialgain[3]); | ||
831 | |||
832 | rtlphy->framesync = (u8) rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, | ||
833 | MASKBYTE0); | ||
834 | rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, | ||
835 | MASKDWORD); | ||
836 | |||
837 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
838 | "Default framesync (0x%x) = 0x%x\n", | ||
839 | ROFDM0_RXDETECTOR3, rtlphy->framesync); | ||
840 | } | ||
841 | |||
842 | void rtl8723be_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) | ||
843 | { | ||
844 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
845 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
846 | u8 txpwr_level; | ||
847 | long txpwr_dbm; | ||
848 | |||
849 | txpwr_level = rtlphy->cur_cck_txpwridx; | ||
850 | txpwr_dbm = rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_B, | ||
851 | txpwr_level); | ||
852 | txpwr_level = rtlphy->cur_ofdm24g_txpwridx; | ||
853 | if (rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, txpwr_level) > | ||
854 | txpwr_dbm) | ||
855 | txpwr_dbm = | ||
856 | rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, | ||
857 | txpwr_level); | ||
858 | txpwr_level = rtlphy->cur_ofdm24g_txpwridx; | ||
859 | if (rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, | ||
860 | txpwr_level) > txpwr_dbm) | ||
861 | txpwr_dbm = | ||
862 | rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, | ||
863 | txpwr_level); | ||
864 | *powerlevel = txpwr_dbm; | ||
865 | } | ||
866 | |||
867 | static u8 _rtl8723be_phy_get_ratesection_intxpower_byrate(enum radio_path path, | ||
868 | u8 rate) | ||
869 | { | ||
870 | u8 rate_section = 0; | ||
871 | |||
872 | switch (rate) { | ||
873 | case DESC92C_RATE1M: | ||
874 | rate_section = 2; | ||
875 | break; | ||
876 | case DESC92C_RATE2M: | ||
877 | case DESC92C_RATE5_5M: | ||
878 | if (path == RF90_PATH_A) | ||
879 | rate_section = 3; | ||
880 | else if (path == RF90_PATH_B) | ||
881 | rate_section = 2; | ||
882 | break; | ||
883 | case DESC92C_RATE11M: | ||
884 | rate_section = 3; | ||
885 | break; | ||
886 | case DESC92C_RATE6M: | ||
887 | case DESC92C_RATE9M: | ||
888 | case DESC92C_RATE12M: | ||
889 | case DESC92C_RATE18M: | ||
890 | rate_section = 0; | ||
891 | break; | ||
892 | case DESC92C_RATE24M: | ||
893 | case DESC92C_RATE36M: | ||
894 | case DESC92C_RATE48M: | ||
895 | case DESC92C_RATE54M: | ||
896 | rate_section = 1; | ||
897 | break; | ||
898 | case DESC92C_RATEMCS0: | ||
899 | case DESC92C_RATEMCS1: | ||
900 | case DESC92C_RATEMCS2: | ||
901 | case DESC92C_RATEMCS3: | ||
902 | rate_section = 4; | ||
903 | break; | ||
904 | case DESC92C_RATEMCS4: | ||
905 | case DESC92C_RATEMCS5: | ||
906 | case DESC92C_RATEMCS6: | ||
907 | case DESC92C_RATEMCS7: | ||
908 | rate_section = 5; | ||
909 | break; | ||
910 | case DESC92C_RATEMCS8: | ||
911 | case DESC92C_RATEMCS9: | ||
912 | case DESC92C_RATEMCS10: | ||
913 | case DESC92C_RATEMCS11: | ||
914 | rate_section = 6; | ||
915 | break; | ||
916 | case DESC92C_RATEMCS12: | ||
917 | case DESC92C_RATEMCS13: | ||
918 | case DESC92C_RATEMCS14: | ||
919 | case DESC92C_RATEMCS15: | ||
920 | rate_section = 7; | ||
921 | break; | ||
922 | default: | ||
923 | RT_ASSERT(true, "Rate_Section is Illegal\n"); | ||
924 | break; | ||
925 | } | ||
926 | return rate_section; | ||
927 | } | ||
928 | |||
929 | static u8 _rtl8723be_get_txpower_by_rate(struct ieee80211_hw *hw, | ||
930 | enum band_type band, | ||
931 | enum radio_path rfpath, u8 rate) | ||
932 | { | ||
933 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
934 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
935 | u8 shift = 0, rate_section, tx_num; | ||
936 | char tx_pwr_diff = 0; | ||
937 | |||
938 | rate_section = _rtl8723be_phy_get_ratesection_intxpower_byrate(rfpath, | ||
939 | rate); | ||
940 | tx_num = RF_TX_NUM_NONIMPLEMENT; | ||
941 | |||
942 | if (tx_num == RF_TX_NUM_NONIMPLEMENT) { | ||
943 | if (rate >= DESC92C_RATEMCS8 && rate <= DESC92C_RATEMCS15) | ||
944 | tx_num = RF_2TX; | ||
945 | else | ||
946 | tx_num = RF_1TX; | ||
947 | } | ||
948 | |||
949 | switch (rate) { | ||
950 | case DESC92C_RATE6M: | ||
951 | case DESC92C_RATE24M: | ||
952 | case DESC92C_RATEMCS0: | ||
953 | case DESC92C_RATEMCS4: | ||
954 | case DESC92C_RATEMCS8: | ||
955 | case DESC92C_RATEMCS12: | ||
956 | shift = 0; | ||
957 | break; | ||
958 | case DESC92C_RATE1M: | ||
959 | case DESC92C_RATE2M: | ||
960 | case DESC92C_RATE9M: | ||
961 | case DESC92C_RATE36M: | ||
962 | case DESC92C_RATEMCS1: | ||
963 | case DESC92C_RATEMCS5: | ||
964 | case DESC92C_RATEMCS9: | ||
965 | case DESC92C_RATEMCS13: | ||
966 | shift = 8; | ||
967 | break; | ||
968 | case DESC92C_RATE5_5M: | ||
969 | case DESC92C_RATE12M: | ||
970 | case DESC92C_RATE48M: | ||
971 | case DESC92C_RATEMCS2: | ||
972 | case DESC92C_RATEMCS6: | ||
973 | case DESC92C_RATEMCS10: | ||
974 | case DESC92C_RATEMCS14: | ||
975 | shift = 16; | ||
976 | break; | ||
977 | case DESC92C_RATE11M: | ||
978 | case DESC92C_RATE18M: | ||
979 | case DESC92C_RATE54M: | ||
980 | case DESC92C_RATEMCS3: | ||
981 | case DESC92C_RATEMCS7: | ||
982 | case DESC92C_RATEMCS11: | ||
983 | case DESC92C_RATEMCS15: | ||
984 | shift = 24; | ||
985 | break; | ||
986 | default: | ||
987 | RT_ASSERT(true, "Rate_Section is Illegal\n"); | ||
988 | break; | ||
989 | } | ||
990 | tx_pwr_diff = (u8)(rtlphy->tx_power_by_rate_offset[band][rfpath][tx_num] | ||
991 | [rate_section] >> shift) & 0xff; | ||
992 | |||
993 | return tx_pwr_diff; | ||
994 | } | ||
995 | |||
996 | static u8 _rtl8723be_get_txpower_index(struct ieee80211_hw *hw, u8 path, | ||
997 | u8 rate, u8 bandwidth, u8 channel) | ||
998 | { | ||
999 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1000 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1001 | u8 index = (channel - 1); | ||
1002 | u8 txpower; | ||
1003 | u8 power_diff_byrate = 0; | ||
1004 | |||
1005 | if (channel > 14 || channel < 1) { | ||
1006 | index = 0; | ||
1007 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1008 | "Illegal channel!\n"); | ||
1009 | } | ||
1010 | if (RTL8723E_RX_HAL_IS_CCK_RATE(rate)) | ||
1011 | txpower = rtlefuse->txpwrlevel_cck[path][index]; | ||
1012 | else if (DESC92C_RATE6M <= rate) | ||
1013 | txpower = rtlefuse->txpwrlevel_ht40_1s[path][index]; | ||
1014 | else | ||
1015 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
1016 | "invalid rate\n"); | ||
1017 | |||
1018 | if (DESC92C_RATE6M <= rate && rate <= DESC92C_RATE54M && | ||
1019 | !RTL8723E_RX_HAL_IS_CCK_RATE(rate)) | ||
1020 | txpower += rtlefuse->txpwr_legacyhtdiff[0][TX_1S]; | ||
1021 | |||
1022 | if (bandwidth == HT_CHANNEL_WIDTH_20) { | ||
1023 | if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) | ||
1024 | txpower += rtlefuse->txpwr_ht20diff[0][TX_1S]; | ||
1025 | if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) | ||
1026 | txpower += rtlefuse->txpwr_ht20diff[0][TX_2S]; | ||
1027 | } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) { | ||
1028 | if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15) | ||
1029 | txpower += rtlefuse->txpwr_ht40diff[0][TX_1S]; | ||
1030 | if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15) | ||
1031 | txpower += rtlefuse->txpwr_ht40diff[0][TX_2S]; | ||
1032 | } | ||
1033 | if (rtlefuse->eeprom_regulatory != 2) | ||
1034 | power_diff_byrate = _rtl8723be_get_txpower_by_rate(hw, | ||
1035 | BAND_ON_2_4G, | ||
1036 | path, rate); | ||
1037 | |||
1038 | txpower += power_diff_byrate; | ||
1039 | |||
1040 | if (txpower > MAX_POWER_INDEX) | ||
1041 | txpower = MAX_POWER_INDEX; | ||
1042 | |||
1043 | return txpower; | ||
1044 | } | ||
1045 | |||
1046 | static void _rtl8723be_phy_set_txpower_index(struct ieee80211_hw *hw, | ||
1047 | u8 power_index, u8 path, u8 rate) | ||
1048 | { | ||
1049 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1050 | if (path == RF90_PATH_A) { | ||
1051 | switch (rate) { | ||
1052 | case DESC92C_RATE1M: | ||
1053 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_CCK1_MCS32, | ||
1054 | MASKBYTE1, power_index); | ||
1055 | break; | ||
1056 | case DESC92C_RATE2M: | ||
1057 | rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11, | ||
1058 | MASKBYTE1, power_index); | ||
1059 | break; | ||
1060 | case DESC92C_RATE5_5M: | ||
1061 | rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11, | ||
1062 | MASKBYTE2, power_index); | ||
1063 | break; | ||
1064 | case DESC92C_RATE11M: | ||
1065 | rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11, | ||
1066 | MASKBYTE3, power_index); | ||
1067 | break; | ||
1068 | case DESC92C_RATE6M: | ||
1069 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, | ||
1070 | MASKBYTE0, power_index); | ||
1071 | break; | ||
1072 | case DESC92C_RATE9M: | ||
1073 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, | ||
1074 | MASKBYTE1, power_index); | ||
1075 | break; | ||
1076 | case DESC92C_RATE12M: | ||
1077 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, | ||
1078 | MASKBYTE2, power_index); | ||
1079 | break; | ||
1080 | case DESC92C_RATE18M: | ||
1081 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06, | ||
1082 | MASKBYTE3, power_index); | ||
1083 | break; | ||
1084 | case DESC92C_RATE24M: | ||
1085 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, | ||
1086 | MASKBYTE0, power_index); | ||
1087 | break; | ||
1088 | case DESC92C_RATE36M: | ||
1089 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, | ||
1090 | MASKBYTE1, power_index); | ||
1091 | break; | ||
1092 | case DESC92C_RATE48M: | ||
1093 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, | ||
1094 | MASKBYTE2, power_index); | ||
1095 | break; | ||
1096 | case DESC92C_RATE54M: | ||
1097 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24, | ||
1098 | MASKBYTE3, power_index); | ||
1099 | break; | ||
1100 | case DESC92C_RATEMCS0: | ||
1101 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, | ||
1102 | MASKBYTE0, power_index); | ||
1103 | break; | ||
1104 | case DESC92C_RATEMCS1: | ||
1105 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, | ||
1106 | MASKBYTE1, power_index); | ||
1107 | break; | ||
1108 | case DESC92C_RATEMCS2: | ||
1109 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, | ||
1110 | MASKBYTE2, power_index); | ||
1111 | break; | ||
1112 | case DESC92C_RATEMCS3: | ||
1113 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00, | ||
1114 | MASKBYTE3, power_index); | ||
1115 | break; | ||
1116 | case DESC92C_RATEMCS4: | ||
1117 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, | ||
1118 | MASKBYTE0, power_index); | ||
1119 | break; | ||
1120 | case DESC92C_RATEMCS5: | ||
1121 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, | ||
1122 | MASKBYTE1, power_index); | ||
1123 | break; | ||
1124 | case DESC92C_RATEMCS6: | ||
1125 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, | ||
1126 | MASKBYTE2, power_index); | ||
1127 | break; | ||
1128 | case DESC92C_RATEMCS7: | ||
1129 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04, | ||
1130 | MASKBYTE3, power_index); | ||
1131 | break; | ||
1132 | case DESC92C_RATEMCS8: | ||
1133 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, | ||
1134 | MASKBYTE0, power_index); | ||
1135 | break; | ||
1136 | case DESC92C_RATEMCS9: | ||
1137 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, | ||
1138 | MASKBYTE1, power_index); | ||
1139 | break; | ||
1140 | case DESC92C_RATEMCS10: | ||
1141 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, | ||
1142 | MASKBYTE2, power_index); | ||
1143 | break; | ||
1144 | case DESC92C_RATEMCS11: | ||
1145 | rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08, | ||
1146 | MASKBYTE3, power_index); | ||
1147 | break; | ||
1148 | default: | ||
1149 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
1150 | "Invalid Rate!!\n"); | ||
1151 | break; | ||
1152 | } | ||
1153 | } else { | ||
1154 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid RFPath!!\n"); | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | void rtl8723be_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) | ||
1159 | { | ||
1160 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1161 | u8 cck_rates[] = {DESC92C_RATE1M, DESC92C_RATE2M, | ||
1162 | DESC92C_RATE5_5M, DESC92C_RATE11M}; | ||
1163 | u8 ofdm_rates[] = {DESC92C_RATE6M, DESC92C_RATE9M, | ||
1164 | DESC92C_RATE12M, DESC92C_RATE18M, | ||
1165 | DESC92C_RATE24M, DESC92C_RATE36M, | ||
1166 | DESC92C_RATE48M, DESC92C_RATE54M}; | ||
1167 | u8 ht_rates_1t[] = {DESC92C_RATEMCS0, DESC92C_RATEMCS1, | ||
1168 | DESC92C_RATEMCS2, DESC92C_RATEMCS3, | ||
1169 | DESC92C_RATEMCS4, DESC92C_RATEMCS5, | ||
1170 | DESC92C_RATEMCS6, DESC92C_RATEMCS7}; | ||
1171 | u8 i, size; | ||
1172 | u8 power_index; | ||
1173 | |||
1174 | if (!rtlefuse->txpwr_fromeprom) | ||
1175 | return; | ||
1176 | |||
1177 | size = sizeof(cck_rates) / sizeof(u8); | ||
1178 | for (i = 0; i < size; i++) { | ||
1179 | power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A, | ||
1180 | cck_rates[i], | ||
1181 | rtl_priv(hw)->phy.current_chan_bw, | ||
1182 | channel); | ||
1183 | _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A, | ||
1184 | cck_rates[i]); | ||
1185 | } | ||
1186 | size = sizeof(ofdm_rates) / sizeof(u8); | ||
1187 | for (i = 0; i < size; i++) { | ||
1188 | power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A, | ||
1189 | ofdm_rates[i], | ||
1190 | rtl_priv(hw)->phy.current_chan_bw, | ||
1191 | channel); | ||
1192 | _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A, | ||
1193 | ofdm_rates[i]); | ||
1194 | } | ||
1195 | size = sizeof(ht_rates_1t) / sizeof(u8); | ||
1196 | for (i = 0; i < size; i++) { | ||
1197 | power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A, | ||
1198 | ht_rates_1t[i], | ||
1199 | rtl_priv(hw)->phy.current_chan_bw, | ||
1200 | channel); | ||
1201 | _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A, | ||
1202 | ht_rates_1t[i]); | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1206 | void rtl8723be_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) | ||
1207 | { | ||
1208 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1209 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1210 | enum io_type iotype; | ||
1211 | |||
1212 | if (!is_hal_stop(rtlhal)) { | ||
1213 | switch (operation) { | ||
1214 | case SCAN_OPT_BACKUP: | ||
1215 | iotype = IO_CMD_PAUSE_DM_BY_SCAN; | ||
1216 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, | ||
1217 | (u8 *)&iotype); | ||
1218 | break; | ||
1219 | case SCAN_OPT_RESTORE: | ||
1220 | iotype = IO_CMD_RESUME_DM_BY_SCAN; | ||
1221 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD, | ||
1222 | (u8 *)&iotype); | ||
1223 | break; | ||
1224 | default: | ||
1225 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1226 | "Unknown Scan Backup operation.\n"); | ||
1227 | break; | ||
1228 | } | ||
1229 | } | ||
1230 | } | ||
1231 | |||
1232 | void rtl8723be_phy_set_bw_mode_callback(struct ieee80211_hw *hw) | ||
1233 | { | ||
1234 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1235 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1236 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1237 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1238 | u8 reg_bw_opmode; | ||
1239 | u8 reg_prsr_rsc; | ||
1240 | |||
1241 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, | ||
1242 | "Switch to %s bandwidth\n", | ||
1243 | rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? | ||
1244 | "20MHz" : "40MHz"); | ||
1245 | |||
1246 | if (is_hal_stop(rtlhal)) { | ||
1247 | rtlphy->set_bwmode_inprogress = false; | ||
1248 | return; | ||
1249 | } | ||
1250 | |||
1251 | reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); | ||
1252 | reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); | ||
1253 | |||
1254 | switch (rtlphy->current_chan_bw) { | ||
1255 | case HT_CHANNEL_WIDTH_20: | ||
1256 | reg_bw_opmode |= BW_OPMODE_20MHZ; | ||
1257 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | ||
1258 | break; | ||
1259 | case HT_CHANNEL_WIDTH_20_40: | ||
1260 | reg_bw_opmode &= ~BW_OPMODE_20MHZ; | ||
1261 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | ||
1262 | reg_prsr_rsc = (reg_prsr_rsc & 0x90) | | ||
1263 | (mac->cur_40_prime_sc << 5); | ||
1264 | rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); | ||
1265 | break; | ||
1266 | default: | ||
1267 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1268 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); | ||
1269 | break; | ||
1270 | } | ||
1271 | |||
1272 | switch (rtlphy->current_chan_bw) { | ||
1273 | case HT_CHANNEL_WIDTH_20: | ||
1274 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); | ||
1275 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); | ||
1276 | break; | ||
1277 | case HT_CHANNEL_WIDTH_20_40: | ||
1278 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); | ||
1279 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); | ||
1280 | rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, | ||
1281 | (mac->cur_40_prime_sc >> 1)); | ||
1282 | rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); | ||
1283 | rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), | ||
1284 | (mac->cur_40_prime_sc == | ||
1285 | HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); | ||
1286 | break; | ||
1287 | default: | ||
1288 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1289 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); | ||
1290 | break; | ||
1291 | } | ||
1292 | rtl8723be_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); | ||
1293 | rtlphy->set_bwmode_inprogress = false; | ||
1294 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_LOUD, "\n"); | ||
1295 | } | ||
1296 | |||
1297 | void rtl8723be_phy_set_bw_mode(struct ieee80211_hw *hw, | ||
1298 | enum nl80211_channel_type ch_type) | ||
1299 | { | ||
1300 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1301 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1302 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1303 | u8 tmp_bw = rtlphy->current_chan_bw; | ||
1304 | |||
1305 | if (rtlphy->set_bwmode_inprogress) | ||
1306 | return; | ||
1307 | rtlphy->set_bwmode_inprogress = true; | ||
1308 | if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | ||
1309 | rtl8723be_phy_set_bw_mode_callback(hw); | ||
1310 | } else { | ||
1311 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1312 | "false driver sleep or unload\n"); | ||
1313 | rtlphy->set_bwmode_inprogress = false; | ||
1314 | rtlphy->current_chan_bw = tmp_bw; | ||
1315 | } | ||
1316 | } | ||
1317 | |||
1318 | void rtl8723be_phy_sw_chnl_callback(struct ieee80211_hw *hw) | ||
1319 | { | ||
1320 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1321 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1322 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1323 | u32 delay; | ||
1324 | |||
1325 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, | ||
1326 | "switch to channel%d\n", rtlphy->current_channel); | ||
1327 | if (is_hal_stop(rtlhal)) | ||
1328 | return; | ||
1329 | do { | ||
1330 | if (!rtlphy->sw_chnl_inprogress) | ||
1331 | break; | ||
1332 | if (!rtl8723be_phy_sw_chn_step_by_step(hw, | ||
1333 | rtlphy->current_channel, | ||
1334 | &rtlphy->sw_chnl_stage, | ||
1335 | &rtlphy->sw_chnl_step, | ||
1336 | &delay)) { | ||
1337 | if (delay > 0) | ||
1338 | mdelay(delay); | ||
1339 | else | ||
1340 | continue; | ||
1341 | } else { | ||
1342 | rtlphy->sw_chnl_inprogress = false; | ||
1343 | } | ||
1344 | break; | ||
1345 | } while (true); | ||
1346 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); | ||
1347 | } | ||
1348 | |||
1349 | u8 rtl8723be_phy_sw_chnl(struct ieee80211_hw *hw) | ||
1350 | { | ||
1351 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1352 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1353 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1354 | |||
1355 | if (rtlphy->sw_chnl_inprogress) | ||
1356 | return 0; | ||
1357 | if (rtlphy->set_bwmode_inprogress) | ||
1358 | return 0; | ||
1359 | RT_ASSERT((rtlphy->current_channel <= 14), | ||
1360 | "WIRELESS_MODE_G but channel>14"); | ||
1361 | rtlphy->sw_chnl_inprogress = true; | ||
1362 | rtlphy->sw_chnl_stage = 0; | ||
1363 | rtlphy->sw_chnl_step = 0; | ||
1364 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | ||
1365 | rtl8723be_phy_sw_chnl_callback(hw); | ||
1366 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | ||
1367 | "sw_chnl_inprogress false schdule " | ||
1368 | "workitem current channel %d\n", | ||
1369 | rtlphy->current_channel); | ||
1370 | rtlphy->sw_chnl_inprogress = false; | ||
1371 | } else { | ||
1372 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | ||
1373 | "sw_chnl_inprogress false driver sleep or" | ||
1374 | " unload\n"); | ||
1375 | rtlphy->sw_chnl_inprogress = false; | ||
1376 | } | ||
1377 | return 1; | ||
1378 | } | ||
1379 | |||
1380 | static bool rtl8723be_phy_sw_chn_step_by_step(struct ieee80211_hw *hw, | ||
1381 | u8 channel, u8 *stage, | ||
1382 | u8 *step, u32 *delay) | ||
1383 | { | ||
1384 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1385 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1386 | struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; | ||
1387 | u32 precommoncmdcnt; | ||
1388 | struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; | ||
1389 | u32 postcommoncmdcnt; | ||
1390 | struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; | ||
1391 | u32 rfdependcmdcnt; | ||
1392 | struct swchnlcmd *currentcmd = NULL; | ||
1393 | u8 rfpath; | ||
1394 | u8 num_total_rfpath = rtlphy->num_total_rfpath; | ||
1395 | |||
1396 | precommoncmdcnt = 0; | ||
1397 | rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, | ||
1398 | MAX_PRECMD_CNT, | ||
1399 | CMDID_SET_TXPOWEROWER_LEVEL, | ||
1400 | 0, 0, 0); | ||
1401 | rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, | ||
1402 | MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); | ||
1403 | postcommoncmdcnt = 0; | ||
1404 | rtl8723_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, | ||
1405 | MAX_POSTCMD_CNT, CMDID_END, | ||
1406 | 0, 0, 0); | ||
1407 | rfdependcmdcnt = 0; | ||
1408 | |||
1409 | RT_ASSERT((channel >= 1 && channel <= 14), | ||
1410 | "illegal channel for Zebra: %d\n", channel); | ||
1411 | |||
1412 | rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, | ||
1413 | MAX_RFDEPENDCMD_CNT, | ||
1414 | CMDID_RF_WRITEREG, | ||
1415 | RF_CHNLBW, channel, 10); | ||
1416 | |||
1417 | rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, | ||
1418 | MAX_RFDEPENDCMD_CNT, | ||
1419 | CMDID_END, 0, 0, 0); | ||
1420 | |||
1421 | do { | ||
1422 | switch (*stage) { | ||
1423 | case 0: | ||
1424 | currentcmd = &precommoncmd[*step]; | ||
1425 | break; | ||
1426 | case 1: | ||
1427 | currentcmd = &rfdependcmd[*step]; | ||
1428 | break; | ||
1429 | case 2: | ||
1430 | currentcmd = &postcommoncmd[*step]; | ||
1431 | break; | ||
1432 | } | ||
1433 | |||
1434 | if (currentcmd->cmdid == CMDID_END) { | ||
1435 | if ((*stage) == 2) { | ||
1436 | return true; | ||
1437 | } else { | ||
1438 | (*stage)++; | ||
1439 | (*step) = 0; | ||
1440 | continue; | ||
1441 | } | ||
1442 | } | ||
1443 | |||
1444 | switch (currentcmd->cmdid) { | ||
1445 | case CMDID_SET_TXPOWEROWER_LEVEL: | ||
1446 | rtl8723be_phy_set_txpower_level(hw, channel); | ||
1447 | break; | ||
1448 | case CMDID_WRITEPORT_ULONG: | ||
1449 | rtl_write_dword(rtlpriv, currentcmd->para1, | ||
1450 | currentcmd->para2); | ||
1451 | break; | ||
1452 | case CMDID_WRITEPORT_USHORT: | ||
1453 | rtl_write_word(rtlpriv, currentcmd->para1, | ||
1454 | (u16) currentcmd->para2); | ||
1455 | break; | ||
1456 | case CMDID_WRITEPORT_UCHAR: | ||
1457 | rtl_write_byte(rtlpriv, currentcmd->para1, | ||
1458 | (u8) currentcmd->para2); | ||
1459 | break; | ||
1460 | case CMDID_RF_WRITEREG: | ||
1461 | for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { | ||
1462 | rtlphy->rfreg_chnlval[rfpath] = | ||
1463 | ((rtlphy->rfreg_chnlval[rfpath] & | ||
1464 | 0xfffffc00) | currentcmd->para2); | ||
1465 | |||
1466 | rtl_set_rfreg(hw, (enum radio_path)rfpath, | ||
1467 | currentcmd->para1, | ||
1468 | RFREG_OFFSET_MASK, | ||
1469 | rtlphy->rfreg_chnlval[rfpath]); | ||
1470 | } | ||
1471 | break; | ||
1472 | default: | ||
1473 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1474 | "switch case not process\n"); | ||
1475 | break; | ||
1476 | } | ||
1477 | |||
1478 | break; | ||
1479 | } while (true); | ||
1480 | |||
1481 | (*delay) = currentcmd->msdelay; | ||
1482 | (*step)++; | ||
1483 | return false; | ||
1484 | } | ||
1485 | |||
1486 | static u8 _rtl8723be_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) | ||
1487 | { | ||
1488 | u32 reg_eac, reg_e94, reg_e9c, reg_ea4; | ||
1489 | u8 result = 0x00; | ||
1490 | |||
1491 | rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1c); | ||
1492 | rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x30008c1c); | ||
1493 | rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x8214032a); | ||
1494 | rtl_set_bbreg(hw, 0xe3c, MASKDWORD, 0x28160000); | ||
1495 | |||
1496 | rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x00462911); | ||
1497 | rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); | ||
1498 | rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); | ||
1499 | |||
1500 | mdelay(IQK_DELAY_TIME); | ||
1501 | |||
1502 | reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); | ||
1503 | reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); | ||
1504 | reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); | ||
1505 | reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); | ||
1506 | |||
1507 | if (!(reg_eac & BIT(28)) && | ||
1508 | (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && | ||
1509 | (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) | ||
1510 | result |= 0x01; | ||
1511 | return result; | ||
1512 | } | ||
1513 | |||
1514 | static bool phy_similarity_cmp(struct ieee80211_hw *hw, long result[][8], | ||
1515 | u8 c1, u8 c2) | ||
1516 | { | ||
1517 | u32 i, j, diff, simularity_bitmap, bound; | ||
1518 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1519 | |||
1520 | u8 final_candidate[2] = { 0xFF, 0xFF }; | ||
1521 | bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version); | ||
1522 | |||
1523 | if (is2t) | ||
1524 | bound = 8; | ||
1525 | else | ||
1526 | bound = 4; | ||
1527 | |||
1528 | simularity_bitmap = 0; | ||
1529 | |||
1530 | for (i = 0; i < bound; i++) { | ||
1531 | diff = (result[c1][i] > result[c2][i]) ? | ||
1532 | (result[c1][i] - result[c2][i]) : | ||
1533 | (result[c2][i] - result[c1][i]); | ||
1534 | |||
1535 | if (diff > MAX_TOLERANCE) { | ||
1536 | if ((i == 2 || i == 6) && !simularity_bitmap) { | ||
1537 | if (result[c1][i] + result[c1][i + 1] == 0) | ||
1538 | final_candidate[(i / 4)] = c2; | ||
1539 | else if (result[c2][i] + result[c2][i + 1] == 0) | ||
1540 | final_candidate[(i / 4)] = c1; | ||
1541 | else | ||
1542 | simularity_bitmap |= (1 << i); | ||
1543 | } else { | ||
1544 | simularity_bitmap |= (1 << i); | ||
1545 | } | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | if (simularity_bitmap == 0) { | ||
1550 | for (i = 0; i < (bound / 4); i++) { | ||
1551 | if (final_candidate[i] != 0xFF) { | ||
1552 | for (j = i * 4; j < (i + 1) * 4 - 2; j++) | ||
1553 | result[3][j] = | ||
1554 | result[final_candidate[i]][j]; | ||
1555 | bresult = false; | ||
1556 | } | ||
1557 | } | ||
1558 | return bresult; | ||
1559 | } else if (!(simularity_bitmap & 0x0F)) { | ||
1560 | for (i = 0; i < 4; i++) | ||
1561 | result[3][i] = result[c1][i]; | ||
1562 | return false; | ||
1563 | } else if (!(simularity_bitmap & 0xF0) && is2t) { | ||
1564 | for (i = 4; i < 8; i++) | ||
1565 | result[3][i] = result[c1][i]; | ||
1566 | return false; | ||
1567 | } else { | ||
1568 | return false; | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | static void _rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, | ||
1573 | long result[][8], u8 t, bool is2t) | ||
1574 | { | ||
1575 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1576 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1577 | u32 i; | ||
1578 | u8 patha_ok; | ||
1579 | u32 adda_reg[IQK_ADDA_REG_NUM] = { | ||
1580 | 0x85c, 0xe6c, 0xe70, 0xe74, | ||
1581 | 0xe78, 0xe7c, 0xe80, 0xe84, | ||
1582 | 0xe88, 0xe8c, 0xed0, 0xed4, | ||
1583 | 0xed8, 0xedc, 0xee0, 0xeec | ||
1584 | }; | ||
1585 | |||
1586 | u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { | ||
1587 | 0x522, 0x550, 0x551, 0x040 | ||
1588 | }; | ||
1589 | u32 iqk_bb_reg[IQK_BB_REG_NUM] = { | ||
1590 | ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR, | ||
1591 | RFPGA0_XCD_RFINTERFACESW, 0xb68, 0xb6c, | ||
1592 | 0x870, 0x860, | ||
1593 | 0x864, 0x800 | ||
1594 | }; | ||
1595 | const u32 retrycount = 2; | ||
1596 | u32 path_sel_bb, path_sel_rf; | ||
1597 | u8 tmp_reg_c50, tmp_reg_c58; | ||
1598 | |||
1599 | tmp_reg_c50 = rtl_get_bbreg(hw, 0xc50, MASKBYTE0); | ||
1600 | tmp_reg_c58 = rtl_get_bbreg(hw, 0xc58, MASKBYTE0); | ||
1601 | |||
1602 | if (t == 0) { | ||
1603 | rtl8723_save_adda_registers(hw, adda_reg, | ||
1604 | rtlphy->adda_backup, 16); | ||
1605 | rtl8723_phy_save_mac_registers(hw, iqk_mac_reg, | ||
1606 | rtlphy->iqk_mac_backup); | ||
1607 | rtl8723_save_adda_registers(hw, iqk_bb_reg, | ||
1608 | rtlphy->iqk_bb_backup, | ||
1609 | IQK_BB_REG_NUM); | ||
1610 | } | ||
1611 | rtl8723_phy_path_adda_on(hw, adda_reg, true, is2t); | ||
1612 | if (t == 0) { | ||
1613 | rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, | ||
1614 | RFPGA0_XA_HSSIPARAMETER1, | ||
1615 | BIT(8)); | ||
1616 | } | ||
1617 | if (!rtlphy->rfpi_enable) | ||
1618 | rtl8723_phy_pi_mode_switch(hw, true); | ||
1619 | |||
1620 | path_sel_bb = rtl_get_bbreg(hw, 0x948, MASKDWORD); | ||
1621 | path_sel_rf = rtl_get_rfreg(hw, RF90_PATH_A, 0xb0, 0xfffff); | ||
1622 | |||
1623 | /*BB Setting*/ | ||
1624 | rtl_set_bbreg(hw, 0x800, BIT(24), 0x00); | ||
1625 | rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); | ||
1626 | rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); | ||
1627 | rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); | ||
1628 | |||
1629 | rtl_set_bbreg(hw, 0x870, BIT(10), 0x01); | ||
1630 | rtl_set_bbreg(hw, 0x870, BIT(26), 0x01); | ||
1631 | rtl_set_bbreg(hw, 0x860, BIT(10), 0x00); | ||
1632 | rtl_set_bbreg(hw, 0x864, BIT(10), 0x00); | ||
1633 | |||
1634 | if (is2t) | ||
1635 | rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASKDWORD, 0x10000); | ||
1636 | rtl8723_phy_mac_setting_calibration(hw, iqk_mac_reg, | ||
1637 | rtlphy->iqk_mac_backup); | ||
1638 | rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x0f600000); | ||
1639 | |||
1640 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); | ||
1641 | rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); | ||
1642 | rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x81004800); | ||
1643 | for (i = 0; i < retrycount; i++) { | ||
1644 | patha_ok = _rtl8723be_phy_path_a_iqk(hw, is2t); | ||
1645 | if (patha_ok == 0x01) { | ||
1646 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1647 | "Path A Tx IQK Success!!\n"); | ||
1648 | result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & | ||
1649 | 0x3FF0000) >> 16; | ||
1650 | result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & | ||
1651 | 0x3FF0000) >> 16; | ||
1652 | break; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | if (0 == patha_ok) | ||
1657 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1658 | "Path A IQK Success!!\n"); | ||
1659 | if (is2t) { | ||
1660 | rtl8723_phy_path_a_standby(hw); | ||
1661 | rtl8723_phy_path_adda_on(hw, adda_reg, false, is2t); | ||
1662 | } | ||
1663 | |||
1664 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); | ||
1665 | |||
1666 | if (t != 0) { | ||
1667 | if (!rtlphy->rfpi_enable) | ||
1668 | rtl8723_phy_pi_mode_switch(hw, false); | ||
1669 | rtl8723_phy_reload_adda_registers(hw, adda_reg, | ||
1670 | rtlphy->adda_backup, 16); | ||
1671 | rtl8723_phy_reload_mac_registers(hw, iqk_mac_reg, | ||
1672 | rtlphy->iqk_mac_backup); | ||
1673 | rtl8723_phy_reload_adda_registers(hw, iqk_bb_reg, | ||
1674 | rtlphy->iqk_bb_backup, | ||
1675 | IQK_BB_REG_NUM); | ||
1676 | |||
1677 | rtl_set_bbreg(hw, 0x948, MASKDWORD, path_sel_bb); | ||
1678 | rtl_set_rfreg(hw, RF90_PATH_B, 0xb0, 0xfffff, path_sel_rf); | ||
1679 | |||
1680 | rtl_set_bbreg(hw, 0xc50, MASKBYTE0, 0x50); | ||
1681 | rtl_set_bbreg(hw, 0xc50, MASKBYTE0, tmp_reg_c50); | ||
1682 | if (is2t) { | ||
1683 | rtl_set_bbreg(hw, 0xc58, MASKBYTE0, 0x50); | ||
1684 | rtl_set_bbreg(hw, 0xc58, MASKBYTE0, tmp_reg_c58); | ||
1685 | } | ||
1686 | rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00); | ||
1687 | rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00); | ||
1688 | } | ||
1689 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "8723be IQK Finish!!\n"); | ||
1690 | } | ||
1691 | |||
1692 | static void _rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) | ||
1693 | { | ||
1694 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1695 | u8 tmpreg; | ||
1696 | u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; | ||
1697 | |||
1698 | tmpreg = rtl_read_byte(rtlpriv, 0xd03); | ||
1699 | |||
1700 | if ((tmpreg & 0x70) != 0) | ||
1701 | rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); | ||
1702 | else | ||
1703 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | ||
1704 | |||
1705 | if ((tmpreg & 0x70) != 0) { | ||
1706 | rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); | ||
1707 | |||
1708 | if (is2t) | ||
1709 | rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, | ||
1710 | MASK12BITS); | ||
1711 | |||
1712 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, | ||
1713 | (rf_a_mode & 0x8FFFF) | 0x10000); | ||
1714 | |||
1715 | if (is2t) | ||
1716 | rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, | ||
1717 | (rf_b_mode & 0x8FFFF) | 0x10000); | ||
1718 | } | ||
1719 | lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); | ||
1720 | |||
1721 | rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, RFREG_OFFSET_MASK, 0xdfbe0); | ||
1722 | rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, 0x8c0a); | ||
1723 | |||
1724 | mdelay(100); | ||
1725 | |||
1726 | rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, RFREG_OFFSET_MASK, 0xdffe0); | ||
1727 | |||
1728 | if ((tmpreg & 0x70) != 0) { | ||
1729 | rtl_write_byte(rtlpriv, 0xd03, tmpreg); | ||
1730 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); | ||
1731 | |||
1732 | if (is2t) | ||
1733 | rtl_set_rfreg(hw, RF90_PATH_B, 0x00, | ||
1734 | MASK12BITS, rf_b_mode); | ||
1735 | } else { | ||
1736 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | ||
1737 | } | ||
1738 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); | ||
1739 | } | ||
1740 | |||
1741 | static void _rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, | ||
1742 | bool bmain, bool is2t) | ||
1743 | { | ||
1744 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1745 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1746 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1747 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, "\n"); | ||
1748 | |||
1749 | if (is_hal_stop(rtlhal)) { | ||
1750 | u8 u1btmp; | ||
1751 | u1btmp = rtl_read_byte(rtlpriv, REG_LEDCFG0); | ||
1752 | rtl_write_byte(rtlpriv, REG_LEDCFG0, u1btmp | BIT(7)); | ||
1753 | rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); | ||
1754 | } | ||
1755 | if (is2t) { | ||
1756 | if (bmain) | ||
1757 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | ||
1758 | BIT(5) | BIT(6), 0x1); | ||
1759 | else | ||
1760 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | ||
1761 | BIT(5) | BIT(6), 0x2); | ||
1762 | } else { | ||
1763 | rtl_set_bbreg(hw, RFPGA0_XAB_RFINTERFACESW, BIT(8) | BIT(9), 0); | ||
1764 | rtl_set_bbreg(hw, 0x914, MASKLWORD, 0x0201); | ||
1765 | |||
1766 | /* We use the RF definition of MAIN and AUX, | ||
1767 | * left antenna and right antenna repectively. | ||
1768 | * Default output at AUX. | ||
1769 | */ | ||
1770 | if (bmain) { | ||
1771 | rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, | ||
1772 | BIT(14) | BIT(13) | BIT(12), 0); | ||
1773 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | ||
1774 | BIT(5) | BIT(4) | BIT(3), 0); | ||
1775 | if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1776 | rtl_set_bbreg(hw, CONFIG_RAM64X16, BIT(31), 0); | ||
1777 | } else { | ||
1778 | rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, | ||
1779 | BIT(14) | BIT(13) | BIT(12), 1); | ||
1780 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | ||
1781 | BIT(5) | BIT(4) | BIT(3), 1); | ||
1782 | if (rtlefuse->antenna_div_type == CGCS_RX_HW_ANTDIV) | ||
1783 | rtl_set_bbreg(hw, CONFIG_RAM64X16, BIT(31), 1); | ||
1784 | } | ||
1785 | } | ||
1786 | } | ||
1787 | |||
1788 | #undef IQK_ADDA_REG_NUM | ||
1789 | #undef IQK_DELAY_TIME | ||
1790 | |||
1791 | void rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery) | ||
1792 | { | ||
1793 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1794 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1795 | long result[4][8]; | ||
1796 | u8 i, final_candidate; | ||
1797 | bool patha_ok, pathb_ok; | ||
1798 | long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, | ||
1799 | reg_ecc, reg_tmp = 0; | ||
1800 | bool is12simular, is13simular, is23simular; | ||
1801 | u32 iqk_bb_reg[9] = { | ||
1802 | ROFDM0_XARXIQIMBALANCE, | ||
1803 | ROFDM0_XBRXIQIMBALANCE, | ||
1804 | ROFDM0_ECCATHRESHOLD, | ||
1805 | ROFDM0_AGCRSSITABLE, | ||
1806 | ROFDM0_XATXIQIMBALANCE, | ||
1807 | ROFDM0_XBTXIQIMBALANCE, | ||
1808 | ROFDM0_XCTXAFE, | ||
1809 | ROFDM0_XDTXAFE, | ||
1810 | ROFDM0_RXIQEXTANTA | ||
1811 | }; | ||
1812 | |||
1813 | if (recovery) { | ||
1814 | rtl8723_phy_reload_adda_registers(hw, iqk_bb_reg, | ||
1815 | rtlphy->iqk_bb_backup, 9); | ||
1816 | return; | ||
1817 | } | ||
1818 | |||
1819 | for (i = 0; i < 8; i++) { | ||
1820 | result[0][i] = 0; | ||
1821 | result[1][i] = 0; | ||
1822 | result[2][i] = 0; | ||
1823 | result[3][i] = 0; | ||
1824 | } | ||
1825 | final_candidate = 0xff; | ||
1826 | patha_ok = false; | ||
1827 | pathb_ok = false; | ||
1828 | is12simular = false; | ||
1829 | is23simular = false; | ||
1830 | is13simular = false; | ||
1831 | for (i = 0; i < 3; i++) { | ||
1832 | if (get_rf_type(rtlphy) == RF_2T2R) | ||
1833 | _rtl8723be_phy_iq_calibrate(hw, result, i, true); | ||
1834 | else | ||
1835 | _rtl8723be_phy_iq_calibrate(hw, result, i, false); | ||
1836 | if (i == 1) { | ||
1837 | is12simular = phy_similarity_cmp(hw, result, 0, 1); | ||
1838 | if (is12simular) { | ||
1839 | final_candidate = 0; | ||
1840 | break; | ||
1841 | } | ||
1842 | } | ||
1843 | if (i == 2) { | ||
1844 | is13simular = phy_similarity_cmp(hw, result, 0, 2); | ||
1845 | if (is13simular) { | ||
1846 | final_candidate = 0; | ||
1847 | break; | ||
1848 | } | ||
1849 | is23simular = phy_similarity_cmp(hw, result, 1, 2); | ||
1850 | if (is23simular) { | ||
1851 | final_candidate = 1; | ||
1852 | } else { | ||
1853 | for (i = 0; i < 8; i++) | ||
1854 | reg_tmp += result[3][i]; | ||
1855 | |||
1856 | if (reg_tmp != 0) | ||
1857 | final_candidate = 3; | ||
1858 | else | ||
1859 | final_candidate = 0xFF; | ||
1860 | } | ||
1861 | } | ||
1862 | } | ||
1863 | for (i = 0; i < 4; i++) { | ||
1864 | reg_e94 = result[i][0]; | ||
1865 | reg_e9c = result[i][1]; | ||
1866 | reg_ea4 = result[i][2]; | ||
1867 | reg_eac = result[i][3]; | ||
1868 | reg_eb4 = result[i][4]; | ||
1869 | reg_ebc = result[i][5]; | ||
1870 | reg_ec4 = result[i][6]; | ||
1871 | reg_ecc = result[i][7]; | ||
1872 | } | ||
1873 | if (final_candidate != 0xff) { | ||
1874 | reg_e94 = result[final_candidate][0]; | ||
1875 | rtlphy->reg_e94 = reg_e94; | ||
1876 | reg_e9c = result[final_candidate][1]; | ||
1877 | rtlphy->reg_e9c = reg_e9c; | ||
1878 | reg_ea4 = result[final_candidate][2]; | ||
1879 | reg_eac = result[final_candidate][3]; | ||
1880 | reg_eb4 = result[final_candidate][4]; | ||
1881 | rtlphy->reg_eb4 = reg_eb4; | ||
1882 | reg_ebc = result[final_candidate][5]; | ||
1883 | rtlphy->reg_ebc = reg_ebc; | ||
1884 | reg_ec4 = result[final_candidate][6]; | ||
1885 | reg_ecc = result[final_candidate][7]; | ||
1886 | patha_ok = true; | ||
1887 | pathb_ok = true; | ||
1888 | } else { | ||
1889 | rtlphy->reg_e94 = 0x100; | ||
1890 | rtlphy->reg_eb4 = 0x100; | ||
1891 | rtlphy->reg_e9c = 0x0; | ||
1892 | rtlphy->reg_ebc = 0x0; | ||
1893 | } | ||
1894 | if (reg_e94 != 0) /*&&(reg_ea4 != 0) */ | ||
1895 | rtl8723_phy_path_a_fill_iqk_matrix(hw, patha_ok, result, | ||
1896 | final_candidate, | ||
1897 | (reg_ea4 == 0)); | ||
1898 | if (final_candidate != 0xFF) { | ||
1899 | for (i = 0; i < IQK_MATRIX_REG_NUM; i++) | ||
1900 | rtlphy->iqk_matrix[0].value[0][i] = | ||
1901 | result[final_candidate][i]; | ||
1902 | rtlphy->iqk_matrix[0].iqk_done = true; | ||
1903 | } | ||
1904 | rtl8723_save_adda_registers(hw, iqk_bb_reg, rtlphy->iqk_bb_backup, 9); | ||
1905 | } | ||
1906 | |||
1907 | void rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw) | ||
1908 | { | ||
1909 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1910 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1911 | struct rtl_hal *rtlhal = &(rtlpriv->rtlhal); | ||
1912 | u32 timeout = 2000, timecount = 0; | ||
1913 | |||
1914 | while (rtlpriv->mac80211.act_scanning && timecount < timeout) { | ||
1915 | udelay(50); | ||
1916 | timecount += 50; | ||
1917 | } | ||
1918 | |||
1919 | rtlphy->lck_inprogress = true; | ||
1920 | RTPRINT(rtlpriv, FINIT, INIT_EEPROM, | ||
1921 | "LCK:Start!!! currentband %x delay %d ms\n", | ||
1922 | rtlhal->current_bandtype, timecount); | ||
1923 | |||
1924 | _rtl8723be_phy_lc_calibrate(hw, false); | ||
1925 | |||
1926 | rtlphy->lck_inprogress = false; | ||
1927 | } | ||
1928 | |||
1929 | void rtl23b_phy_ap_calibrate(struct ieee80211_hw *hw, char delta) | ||
1930 | { | ||
1931 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1932 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1933 | |||
1934 | if (rtlphy->apk_done) | ||
1935 | return; | ||
1936 | |||
1937 | return; | ||
1938 | } | ||
1939 | |||
1940 | void rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) | ||
1941 | { | ||
1942 | _rtl8723be_phy_set_rfpath_switch(hw, bmain, false); | ||
1943 | } | ||
1944 | |||
1945 | static void rtl8723be_phy_set_io(struct ieee80211_hw *hw) | ||
1946 | { | ||
1947 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1948 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1949 | |||
1950 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
1951 | "--->Cmd(%#x), set_io_inprogress(%d)\n", | ||
1952 | rtlphy->current_io_type, rtlphy->set_io_inprogress); | ||
1953 | switch (rtlphy->current_io_type) { | ||
1954 | case IO_CMD_RESUME_DM_BY_SCAN: | ||
1955 | rtlpriv->dm_digtable.cur_igvalue = | ||
1956 | rtlphy->initgain_backup.xaagccore1; | ||
1957 | /*rtl92c_dm_write_dig(hw);*/ | ||
1958 | rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel); | ||
1959 | rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83); | ||
1960 | break; | ||
1961 | case IO_CMD_PAUSE_DM_BY_SCAN: | ||
1962 | rtlphy->initgain_backup.xaagccore1 = | ||
1963 | rtlpriv->dm_digtable.cur_igvalue; | ||
1964 | rtlpriv->dm_digtable.cur_igvalue = 0x17; | ||
1965 | rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40); | ||
1966 | break; | ||
1967 | default: | ||
1968 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1969 | "switch case not process\n"); | ||
1970 | break; | ||
1971 | } | ||
1972 | rtlphy->set_io_inprogress = false; | ||
1973 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
1974 | "(%#x)\n", rtlphy->current_io_type); | ||
1975 | } | ||
1976 | |||
1977 | bool rtl8723be_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) | ||
1978 | { | ||
1979 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1980 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1981 | bool postprocessing = false; | ||
1982 | |||
1983 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
1984 | "-->IO Cmd(%#x), set_io_inprogress(%d)\n", | ||
1985 | iotype, rtlphy->set_io_inprogress); | ||
1986 | do { | ||
1987 | switch (iotype) { | ||
1988 | case IO_CMD_RESUME_DM_BY_SCAN: | ||
1989 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
1990 | "[IO CMD] Resume DM after scan.\n"); | ||
1991 | postprocessing = true; | ||
1992 | break; | ||
1993 | case IO_CMD_PAUSE_DM_BY_SCAN: | ||
1994 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | ||
1995 | "[IO CMD] Pause DM before scan.\n"); | ||
1996 | postprocessing = true; | ||
1997 | break; | ||
1998 | default: | ||
1999 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2000 | "switch case not process\n"); | ||
2001 | break; | ||
2002 | } | ||
2003 | } while (false); | ||
2004 | if (postprocessing && !rtlphy->set_io_inprogress) { | ||
2005 | rtlphy->set_io_inprogress = true; | ||
2006 | rtlphy->current_io_type = iotype; | ||
2007 | } else { | ||
2008 | return false; | ||
2009 | } | ||
2010 | rtl8723be_phy_set_io(hw); | ||
2011 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); | ||
2012 | return true; | ||
2013 | } | ||
2014 | |||
2015 | static void rtl8723be_phy_set_rf_on(struct ieee80211_hw *hw) | ||
2016 | { | ||
2017 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2018 | |||
2019 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); | ||
2020 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | ||
2021 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | ||
2022 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | ||
2023 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | ||
2024 | } | ||
2025 | |||
2026 | static void _rtl8723be_phy_set_rf_sleep(struct ieee80211_hw *hw) | ||
2027 | { | ||
2028 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2029 | |||
2030 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | ||
2031 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); | ||
2032 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | ||
2033 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); | ||
2034 | } | ||
2035 | |||
2036 | static bool _rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
2037 | enum rf_pwrstate rfpwr_state) | ||
2038 | { | ||
2039 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2040 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
2041 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2042 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2043 | bool bresult = true; | ||
2044 | u8 i, queue_id; | ||
2045 | struct rtl8192_tx_ring *ring = NULL; | ||
2046 | |||
2047 | switch (rfpwr_state) { | ||
2048 | case ERFON: | ||
2049 | if ((ppsc->rfpwr_state == ERFOFF) && | ||
2050 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { | ||
2051 | bool rtstatus; | ||
2052 | u32 initialize_count = 0; | ||
2053 | do { | ||
2054 | initialize_count++; | ||
2055 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2056 | "IPS Set eRf nic enable\n"); | ||
2057 | rtstatus = rtl_ps_enable_nic(hw); | ||
2058 | } while (!rtstatus && (initialize_count < 10)); | ||
2059 | RT_CLEAR_PS_LEVEL(ppsc, | ||
2060 | RT_RF_OFF_LEVL_HALT_NIC); | ||
2061 | } else { | ||
2062 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2063 | "Set ERFON sleeped:%d ms\n", | ||
2064 | jiffies_to_msecs(jiffies - | ||
2065 | ppsc->last_sleep_jiffies)); | ||
2066 | ppsc->last_awake_jiffies = jiffies; | ||
2067 | rtl8723be_phy_set_rf_on(hw); | ||
2068 | } | ||
2069 | if (mac->link_state == MAC80211_LINKED) | ||
2070 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK); | ||
2071 | else | ||
2072 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK); | ||
2073 | break; | ||
2074 | case ERFOFF: | ||
2075 | for (queue_id = 0, i = 0; | ||
2076 | queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { | ||
2077 | ring = &pcipriv->dev.tx_ring[queue_id]; | ||
2078 | if (skb_queue_len(&ring->queue) == 0) { | ||
2079 | queue_id++; | ||
2080 | continue; | ||
2081 | } else { | ||
2082 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2083 | "eRf Off/Sleep: %d times " | ||
2084 | "TcbBusyQueue[%d] =%d before " | ||
2085 | "doze!\n", (i + 1), queue_id, | ||
2086 | skb_queue_len(&ring->queue)); | ||
2087 | |||
2088 | udelay(10); | ||
2089 | i++; | ||
2090 | } | ||
2091 | if (i >= MAX_DOZE_WAITING_TIMES_9x) { | ||
2092 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2093 | "\n ERFSLEEP: %d times " | ||
2094 | "TcbBusyQueue[%d] = %d !\n", | ||
2095 | MAX_DOZE_WAITING_TIMES_9x, | ||
2096 | queue_id, | ||
2097 | skb_queue_len(&ring->queue)); | ||
2098 | break; | ||
2099 | } | ||
2100 | } | ||
2101 | |||
2102 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { | ||
2103 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2104 | "IPS Set eRf nic disable\n"); | ||
2105 | rtl_ps_disable_nic(hw); | ||
2106 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
2107 | } else { | ||
2108 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { | ||
2109 | rtlpriv->cfg->ops->led_control(hw, | ||
2110 | LED_CTL_NO_LINK); | ||
2111 | } else { | ||
2112 | rtlpriv->cfg->ops->led_control(hw, | ||
2113 | LED_CTL_POWER_OFF); | ||
2114 | } | ||
2115 | } | ||
2116 | break; | ||
2117 | case ERFSLEEP: | ||
2118 | if (ppsc->rfpwr_state == ERFOFF) | ||
2119 | break; | ||
2120 | for (queue_id = 0, i = 0; | ||
2121 | queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { | ||
2122 | ring = &pcipriv->dev.tx_ring[queue_id]; | ||
2123 | if (skb_queue_len(&ring->queue) == 0) { | ||
2124 | queue_id++; | ||
2125 | continue; | ||
2126 | } else { | ||
2127 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2128 | "eRf Off/Sleep: %d times " | ||
2129 | "TcbBusyQueue[%d] =%d before " | ||
2130 | "doze!\n", (i + 1), queue_id, | ||
2131 | skb_queue_len(&ring->queue)); | ||
2132 | |||
2133 | udelay(10); | ||
2134 | i++; | ||
2135 | } | ||
2136 | if (i >= MAX_DOZE_WAITING_TIMES_9x) { | ||
2137 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
2138 | "\n ERFSLEEP: %d times " | ||
2139 | "TcbBusyQueue[%d] = %d !\n", | ||
2140 | MAX_DOZE_WAITING_TIMES_9x, | ||
2141 | queue_id, | ||
2142 | skb_queue_len(&ring->queue)); | ||
2143 | break; | ||
2144 | } | ||
2145 | } | ||
2146 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2147 | "Set ERFSLEEP awaked:%d ms\n", | ||
2148 | jiffies_to_msecs(jiffies - | ||
2149 | ppsc->last_awake_jiffies)); | ||
2150 | ppsc->last_sleep_jiffies = jiffies; | ||
2151 | _rtl8723be_phy_set_rf_sleep(hw); | ||
2152 | break; | ||
2153 | default: | ||
2154 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2155 | "switch case not process\n"); | ||
2156 | bresult = false; | ||
2157 | break; | ||
2158 | } | ||
2159 | if (bresult) | ||
2160 | ppsc->rfpwr_state = rfpwr_state; | ||
2161 | return bresult; | ||
2162 | } | ||
2163 | |||
2164 | bool rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
2165 | enum rf_pwrstate rfpwr_state) | ||
2166 | { | ||
2167 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2168 | |||
2169 | bool bresult = false; | ||
2170 | |||
2171 | if (rfpwr_state == ppsc->rfpwr_state) | ||
2172 | return bresult; | ||
2173 | bresult = _rtl8723be_phy_set_rf_power_state(hw, rfpwr_state); | ||
2174 | return bresult; | ||
2175 | } | ||