Commit | Line | Data |
---|---|---|
c592e631 LF |
1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2009-2012 Realtek Corporation. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
c592e631 LF |
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 "rf.h" | |
33 | #include "dm.h" | |
34 | #include "table.h" | |
0a168b48 | 35 | #include "../rtl8723com/phy_common.h" |
c592e631 | 36 | |
0529c6b8 LF |
37 | static void _rtl8723e_phy_fw_rf_serial_write(struct ieee80211_hw *hw, |
38 | enum radio_path rfpath, u32 offset, | |
39 | u32 data); | |
40 | static bool _rtl8723e_phy_bb8192c_config_parafile(struct ieee80211_hw *hw); | |
41 | static bool _rtl8723e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); | |
42 | static bool _rtl8723e_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, | |
43 | u8 configtype); | |
44 | static bool _rtl8723e_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, | |
45 | u8 configtype); | |
46 | static bool _rtl8723e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, | |
47 | u8 channel, u8 *stage, u8 *step, | |
48 | u32 *delay); | |
49 | static u8 _rtl8723e_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, | |
50 | enum wireless_mode wirelessmode, | |
51 | long power_indbm); | |
52 | static void rtl8723e_phy_set_rf_on(struct ieee80211_hw *hw); | |
53 | static void rtl8723e_phy_set_io(struct ieee80211_hw *hw); | |
54 | ||
55 | u32 rtl8723e_phy_query_rf_reg(struct ieee80211_hw *hw, | |
56 | enum radio_path rfpath, | |
57 | u32 regaddr, u32 bitmask) | |
c592e631 LF |
58 | { |
59 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 LF |
60 | u32 original_value = 0, readback_value, bitshift; |
61 | struct rtl_phy *rtlphy = &rtlpriv->phy; | |
c592e631 LF |
62 | unsigned long flags; |
63 | ||
64 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | |
65 | "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", | |
66 | regaddr, rfpath, bitmask); | |
67 | ||
68 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | |
69 | ||
0529c6b8 LF |
70 | if (rtlphy->rf_mode != RF_OP_BY_FW) { |
71 | original_value = rtl8723_phy_rf_serial_read(hw, | |
72 | rfpath, regaddr); | |
73 | } | |
c592e631 | 74 | |
0a168b48 | 75 | bitshift = rtl8723_phy_calculate_bit_shift(bitmask); |
c592e631 LF |
76 | readback_value = (original_value & bitmask) >> bitshift; |
77 | ||
78 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | |
79 | ||
80 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | |
81 | "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", | |
0529c6b8 | 82 | regaddr, rfpath, bitmask, original_value); |
c592e631 LF |
83 | |
84 | return readback_value; | |
85 | } | |
86 | ||
0529c6b8 LF |
87 | void rtl8723e_phy_set_rf_reg(struct ieee80211_hw *hw, |
88 | enum radio_path rfpath, | |
89 | u32 regaddr, u32 bitmask, u32 data) | |
c592e631 LF |
90 | { |
91 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 LF |
92 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
93 | u32 original_value = 0, bitshift; | |
c592e631 LF |
94 | unsigned long flags; |
95 | ||
96 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | |
97 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", | |
0529c6b8 | 98 | regaddr, bitmask, data, rfpath); |
c592e631 LF |
99 | |
100 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | |
101 | ||
102 | if (rtlphy->rf_mode != RF_OP_BY_FW) { | |
103 | if (bitmask != RFREG_OFFSET_MASK) { | |
0529c6b8 LF |
104 | original_value = rtl8723_phy_rf_serial_read(hw, |
105 | rfpath, | |
0a168b48 LF |
106 | regaddr); |
107 | bitshift = rtl8723_phy_calculate_bit_shift(bitmask); | |
0529c6b8 LF |
108 | data = |
109 | ((original_value & (~bitmask)) | | |
110 | (data << bitshift)); | |
c592e631 LF |
111 | } |
112 | ||
0a168b48 | 113 | rtl8723_phy_rf_serial_write(hw, rfpath, regaddr, data); |
c592e631 LF |
114 | } else { |
115 | if (bitmask != RFREG_OFFSET_MASK) { | |
0a168b48 | 116 | bitshift = rtl8723_phy_calculate_bit_shift(bitmask); |
0529c6b8 LF |
117 | data = |
118 | ((original_value & (~bitmask)) | | |
119 | (data << bitshift)); | |
c592e631 | 120 | } |
0529c6b8 | 121 | _rtl8723e_phy_fw_rf_serial_write(hw, rfpath, regaddr, data); |
c592e631 LF |
122 | } |
123 | ||
124 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | |
125 | ||
126 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | |
127 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", | |
128 | regaddr, bitmask, data, rfpath); | |
c592e631 | 129 | |
c592e631 LF |
130 | } |
131 | ||
0529c6b8 LF |
132 | static void _rtl8723e_phy_fw_rf_serial_write(struct ieee80211_hw *hw, |
133 | enum radio_path rfpath, u32 offset, | |
134 | u32 data) | |
c592e631 LF |
135 | { |
136 | RT_ASSERT(false, "deprecated!\n"); | |
137 | } | |
138 | ||
0529c6b8 | 139 | static void _rtl8723e_phy_bb_config_1t(struct ieee80211_hw *hw) |
c592e631 LF |
140 | { |
141 | rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2); | |
142 | rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022); | |
143 | rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45); | |
144 | rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23); | |
145 | rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1); | |
146 | rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2); | |
147 | rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2); | |
148 | rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2); | |
149 | rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2); | |
150 | rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2); | |
151 | } | |
152 | ||
0529c6b8 | 153 | bool rtl8723e_phy_mac_config(struct ieee80211_hw *hw) |
c592e631 LF |
154 | { |
155 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 156 | bool rtstatus = _rtl8723e_phy_config_mac_with_headerfile(hw); |
c592e631 LF |
157 | rtl_write_byte(rtlpriv, 0x04CA, 0x0A); |
158 | return rtstatus; | |
159 | } | |
160 | ||
0529c6b8 | 161 | bool rtl8723e_phy_bb_config(struct ieee80211_hw *hw) |
c592e631 LF |
162 | { |
163 | bool rtstatus = true; | |
164 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
165 | u8 tmpu1b; | |
0529c6b8 | 166 | u8 b_reg_hwparafile = 1; |
c592e631 | 167 | |
0a168b48 | 168 | rtl8723_phy_init_bb_rf_reg_def(hw); |
c592e631 LF |
169 | |
170 | /* 1. 0x28[1] = 1 */ | |
171 | tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_PLL_CTRL); | |
172 | udelay(2); | |
173 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, (tmpu1b|BIT(1))); | |
174 | udelay(2); | |
175 | /* 2. 0x29[7:0] = 0xFF */ | |
176 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL+1, 0xff); | |
177 | udelay(2); | |
178 | ||
179 | /* 3. 0x02[1:0] = 2b'11 */ | |
180 | tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); | |
0529c6b8 LF |
181 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, |
182 | (tmpu1b | FEN_BB_GLB_RSTN | FEN_BBRSTB)); | |
c592e631 LF |
183 | |
184 | /* 4. 0x25[6] = 0 */ | |
185 | tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+1); | |
0529c6b8 | 186 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+1, (tmpu1b & (~BIT(6)))); |
c592e631 | 187 | |
0529c6b8 | 188 | /* 5. 0x24[20] = 0 //Advised by SD3 Alex Wang. 2011.02.09. */ |
c592e631 | 189 | tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2); |
0529c6b8 | 190 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, (tmpu1b & (~BIT(4)))); |
c592e631 LF |
191 | |
192 | /* 6. 0x1f[7:0] = 0x07 */ | |
193 | rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x07); | |
194 | ||
0529c6b8 LF |
195 | if (b_reg_hwparafile == 1) |
196 | rtstatus = _rtl8723e_phy_bb8192c_config_parafile(hw); | |
c592e631 LF |
197 | return rtstatus; |
198 | } | |
199 | ||
0529c6b8 | 200 | bool rtl8723e_phy_rf_config(struct ieee80211_hw *hw) |
c592e631 | 201 | { |
0529c6b8 | 202 | return rtl8723e_phy_rf6052_config(hw); |
c592e631 LF |
203 | } |
204 | ||
0529c6b8 | 205 | static bool _rtl8723e_phy_bb8192c_config_parafile(struct ieee80211_hw *hw) |
c592e631 LF |
206 | { |
207 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 208 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
209 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
210 | bool rtstatus; | |
211 | ||
0529c6b8 LF |
212 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); |
213 | rtstatus = _rtl8723e_phy_config_bb_with_headerfile(hw, | |
214 | BASEBAND_CONFIG_PHY_REG); | |
c592e631 LF |
215 | if (rtstatus != true) { |
216 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Write BB Reg Fail!!"); | |
217 | return false; | |
218 | } | |
219 | ||
220 | if (rtlphy->rf_type == RF_1T2R) { | |
0529c6b8 | 221 | _rtl8723e_phy_bb_config_1t(hw); |
c592e631 LF |
222 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n"); |
223 | } | |
224 | if (rtlefuse->autoload_failflag == false) { | |
225 | rtlphy->pwrgroup_cnt = 0; | |
0529c6b8 LF |
226 | rtstatus = _rtl8723e_phy_config_bb_with_pgheaderfile(hw, |
227 | BASEBAND_CONFIG_PHY_REG); | |
c592e631 LF |
228 | } |
229 | if (rtstatus != true) { | |
230 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "BB_PG Reg Fail!!"); | |
231 | return false; | |
232 | } | |
0529c6b8 LF |
233 | rtstatus = |
234 | _rtl8723e_phy_config_bb_with_headerfile(hw, BASEBAND_CONFIG_AGC_TAB); | |
c592e631 LF |
235 | if (rtstatus != true) { |
236 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "AGC Table Fail\n"); | |
237 | return false; | |
238 | } | |
239 | rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw, | |
0529c6b8 LF |
240 | RFPGA0_XA_HSSIPARAMETER2, |
241 | 0x200)); | |
242 | ||
c592e631 LF |
243 | return true; |
244 | } | |
245 | ||
0529c6b8 | 246 | static bool _rtl8723e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) |
c592e631 LF |
247 | { |
248 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
249 | u32 i; | |
250 | u32 arraylength; | |
251 | u32 *ptrarray; | |
252 | ||
253 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl723MACPHY_Array\n"); | |
254 | arraylength = RTL8723E_MACARRAYLENGTH; | |
255 | ptrarray = RTL8723EMAC_ARRAY; | |
256 | ||
257 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
258 | "Img:RTL8192CEMAC_2T_ARRAY\n"); | |
259 | for (i = 0; i < arraylength; i = i + 2) | |
260 | rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); | |
261 | return true; | |
262 | } | |
263 | ||
0529c6b8 LF |
264 | static bool _rtl8723e_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, |
265 | u8 configtype) | |
c592e631 LF |
266 | { |
267 | int i; | |
268 | u32 *phy_regarray_table; | |
269 | u32 *agctab_array_table; | |
270 | u16 phy_reg_arraylen, agctab_arraylen; | |
271 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
272 | ||
273 | agctab_arraylen = RTL8723E_AGCTAB_1TARRAYLENGTH; | |
274 | agctab_array_table = RTL8723EAGCTAB_1TARRAY; | |
275 | phy_reg_arraylen = RTL8723E_PHY_REG_1TARRAY_LENGTH; | |
276 | phy_regarray_table = RTL8723EPHY_REG_1TARRAY; | |
277 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | |
278 | for (i = 0; i < phy_reg_arraylen; i = i + 2) { | |
0529c6b8 LF |
279 | if (phy_regarray_table[i] == 0xfe) |
280 | mdelay(50); | |
281 | else if (phy_regarray_table[i] == 0xfd) | |
282 | mdelay(5); | |
283 | else if (phy_regarray_table[i] == 0xfc) | |
284 | mdelay(1); | |
285 | else if (phy_regarray_table[i] == 0xfb) | |
286 | udelay(50); | |
287 | else if (phy_regarray_table[i] == 0xfa) | |
288 | udelay(5); | |
289 | else if (phy_regarray_table[i] == 0xf9) | |
290 | udelay(1); | |
c592e631 LF |
291 | rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, |
292 | phy_regarray_table[i + 1]); | |
293 | udelay(1); | |
294 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
0529c6b8 | 295 | "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", |
c592e631 LF |
296 | phy_regarray_table[i], |
297 | phy_regarray_table[i + 1]); | |
298 | } | |
299 | } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { | |
300 | for (i = 0; i < agctab_arraylen; i = i + 2) { | |
301 | rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD, | |
302 | agctab_array_table[i + 1]); | |
303 | udelay(1); | |
304 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
0529c6b8 | 305 | "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", |
c592e631 LF |
306 | agctab_array_table[i], |
307 | agctab_array_table[i + 1]); | |
308 | } | |
309 | } | |
310 | return true; | |
311 | } | |
312 | ||
0529c6b8 LF |
313 | static void store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, |
314 | u32 regaddr, u32 bitmask, | |
315 | u32 data) | |
c592e631 LF |
316 | { |
317 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 318 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 | 319 | |
0529c6b8 LF |
320 | if (regaddr == RTXAGC_A_RATE18_06) { |
321 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = | |
322 | data; | |
c592e631 LF |
323 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
324 | "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", | |
0529c6b8 LF |
325 | rtlphy->pwrgroup_cnt, |
326 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
327 | pwrgroup_cnt][0]); | |
328 | } | |
329 | if (regaddr == RTXAGC_A_RATE54_24) { | |
330 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = | |
331 | data; | |
c592e631 LF |
332 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
333 | "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", | |
0529c6b8 LF |
334 | rtlphy->pwrgroup_cnt, |
335 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
336 | pwrgroup_cnt][1]); | |
337 | } | |
338 | if (regaddr == RTXAGC_A_CCK1_MCS32) { | |
339 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = | |
340 | data; | |
c592e631 LF |
341 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
342 | "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", | |
0529c6b8 LF |
343 | rtlphy->pwrgroup_cnt, |
344 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
345 | pwrgroup_cnt][6]); | |
346 | } | |
347 | if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { | |
348 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] = | |
349 | data; | |
350 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
351 | "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", | |
352 | rtlphy->pwrgroup_cnt, | |
353 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
354 | pwrgroup_cnt][7]); | |
355 | } | |
356 | if (regaddr == RTXAGC_A_MCS03_MCS00) { | |
357 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = | |
358 | data; | |
c592e631 LF |
359 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
360 | "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", | |
0529c6b8 LF |
361 | rtlphy->pwrgroup_cnt, |
362 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
363 | pwrgroup_cnt][2]); | |
364 | } | |
365 | if (regaddr == RTXAGC_A_MCS07_MCS04) { | |
366 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = | |
367 | data; | |
c592e631 LF |
368 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
369 | "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", | |
0529c6b8 LF |
370 | rtlphy->pwrgroup_cnt, |
371 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
372 | pwrgroup_cnt][3]); | |
373 | } | |
374 | if (regaddr == RTXAGC_A_MCS11_MCS08) { | |
375 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = | |
376 | data; | |
c592e631 LF |
377 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
378 | "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", | |
0529c6b8 LF |
379 | rtlphy->pwrgroup_cnt, |
380 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
381 | pwrgroup_cnt][4]); | |
382 | } | |
383 | if (regaddr == RTXAGC_A_MCS15_MCS12) { | |
384 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = | |
385 | data; | |
c592e631 LF |
386 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
387 | "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", | |
0529c6b8 LF |
388 | rtlphy->pwrgroup_cnt, |
389 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
390 | pwrgroup_cnt][5]); | |
391 | } | |
392 | if (regaddr == RTXAGC_B_RATE18_06) { | |
393 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] = | |
394 | data; | |
c592e631 LF |
395 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
396 | "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", | |
0529c6b8 LF |
397 | rtlphy->pwrgroup_cnt, |
398 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
399 | pwrgroup_cnt][8]); | |
400 | } | |
401 | if (regaddr == RTXAGC_B_RATE54_24) { | |
402 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] = | |
403 | data; | |
c592e631 LF |
404 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
405 | "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", | |
0529c6b8 LF |
406 | rtlphy->pwrgroup_cnt, |
407 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
408 | pwrgroup_cnt][9]); | |
409 | } | |
410 | if (regaddr == RTXAGC_B_CCK1_55_MCS32) { | |
411 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] = | |
412 | data; | |
c592e631 LF |
413 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
414 | "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", | |
0529c6b8 LF |
415 | rtlphy->pwrgroup_cnt, |
416 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
417 | pwrgroup_cnt][14]); | |
418 | } | |
419 | if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { | |
420 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] = | |
421 | data; | |
422 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
423 | "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", | |
424 | rtlphy->pwrgroup_cnt, | |
425 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
426 | pwrgroup_cnt][15]); | |
427 | } | |
428 | if (regaddr == RTXAGC_B_MCS03_MCS00) { | |
429 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] = | |
430 | data; | |
c592e631 LF |
431 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
432 | "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", | |
0529c6b8 LF |
433 | rtlphy->pwrgroup_cnt, |
434 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
435 | pwrgroup_cnt][10]); | |
436 | } | |
437 | if (regaddr == RTXAGC_B_MCS07_MCS04) { | |
438 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] = | |
439 | data; | |
c592e631 LF |
440 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
441 | "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", | |
0529c6b8 LF |
442 | rtlphy->pwrgroup_cnt, |
443 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
444 | pwrgroup_cnt][11]); | |
445 | } | |
446 | if (regaddr == RTXAGC_B_MCS11_MCS08) { | |
447 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] = | |
448 | data; | |
c592e631 LF |
449 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
450 | "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", | |
0529c6b8 LF |
451 | rtlphy->pwrgroup_cnt, |
452 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
453 | pwrgroup_cnt][12]); | |
454 | } | |
455 | if (regaddr == RTXAGC_B_MCS15_MCS12) { | |
456 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] = | |
457 | data; | |
c592e631 LF |
458 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
459 | "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", | |
0529c6b8 LF |
460 | rtlphy->pwrgroup_cnt, |
461 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy-> | |
462 | pwrgroup_cnt][13]); | |
463 | ||
c592e631 | 464 | rtlphy->pwrgroup_cnt++; |
c592e631 LF |
465 | } |
466 | } | |
467 | ||
0529c6b8 LF |
468 | static bool _rtl8723e_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, |
469 | u8 configtype) | |
c592e631 LF |
470 | { |
471 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
472 | int i; | |
473 | u32 *phy_regarray_table_pg; | |
474 | u16 phy_regarray_pg_len; | |
475 | ||
476 | phy_regarray_pg_len = RTL8723E_PHY_REG_ARRAY_PGLENGTH; | |
477 | phy_regarray_table_pg = RTL8723EPHY_REG_ARRAY_PG; | |
478 | ||
479 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | |
480 | for (i = 0; i < phy_regarray_pg_len; i = i + 3) { | |
0529c6b8 LF |
481 | if (phy_regarray_table_pg[i] == 0xfe) |
482 | mdelay(50); | |
483 | else if (phy_regarray_table_pg[i] == 0xfd) | |
484 | mdelay(5); | |
485 | else if (phy_regarray_table_pg[i] == 0xfc) | |
486 | mdelay(1); | |
487 | else if (phy_regarray_table_pg[i] == 0xfb) | |
488 | udelay(50); | |
489 | else if (phy_regarray_table_pg[i] == 0xfa) | |
490 | udelay(5); | |
491 | else if (phy_regarray_table_pg[i] == 0xf9) | |
492 | udelay(1); | |
493 | ||
494 | store_pwrindex_diffrate_offset(hw, | |
495 | phy_regarray_table_pg[i], | |
496 | phy_regarray_table_pg[i + 1], | |
497 | phy_regarray_table_pg[i + 2]); | |
c592e631 LF |
498 | } |
499 | } else { | |
500 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | |
501 | "configtype != BaseBand_Config_PHY_REG\n"); | |
502 | } | |
503 | return true; | |
504 | } | |
505 | ||
0529c6b8 LF |
506 | bool rtl8723e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, |
507 | enum radio_path rfpath) | |
c592e631 | 508 | { |
c592e631 | 509 | int i; |
0529c6b8 | 510 | bool rtstatus = true; |
c592e631 | 511 | u32 *radioa_array_table; |
0529c6b8 LF |
512 | u32 *radiob_array_table; |
513 | u16 radioa_arraylen, radiob_arraylen; | |
c592e631 | 514 | |
0529c6b8 | 515 | radioa_arraylen = RTL8723ERADIOA_1TARRAYLENGTH; |
c592e631 | 516 | radioa_array_table = RTL8723E_RADIOA_1TARRAY; |
0529c6b8 LF |
517 | radiob_arraylen = RTL8723E_RADIOB_1TARRAYLENGTH; |
518 | radiob_array_table = RTL8723E_RADIOB_1TARRAY; | |
519 | ||
520 | rtstatus = true; | |
c592e631 LF |
521 | |
522 | switch (rfpath) { | |
523 | case RF90_PATH_A: | |
524 | for (i = 0; i < radioa_arraylen; i = i + 2) { | |
0529c6b8 LF |
525 | if (radioa_array_table[i] == 0xfe) { |
526 | mdelay(50); | |
527 | } else if (radioa_array_table[i] == 0xfd) { | |
528 | mdelay(5); | |
529 | } else if (radioa_array_table[i] == 0xfc) { | |
530 | mdelay(1); | |
531 | } else if (radioa_array_table[i] == 0xfb) { | |
532 | udelay(50); | |
533 | } else if (radioa_array_table[i] == 0xfa) { | |
534 | udelay(5); | |
535 | } else if (radioa_array_table[i] == 0xf9) { | |
536 | udelay(1); | |
537 | } else { | |
538 | rtl_set_rfreg(hw, rfpath, radioa_array_table[i], | |
539 | RFREG_OFFSET_MASK, | |
540 | radioa_array_table[i + 1]); | |
541 | udelay(1); | |
542 | } | |
c592e631 LF |
543 | } |
544 | break; | |
545 | case RF90_PATH_B: | |
c592e631 | 546 | case RF90_PATH_C: |
c592e631 | 547 | case RF90_PATH_D: |
c592e631 LF |
548 | break; |
549 | } | |
550 | return true; | |
551 | } | |
552 | ||
0529c6b8 | 553 | void rtl8723e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) |
c592e631 LF |
554 | { |
555 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 556 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
557 | |
558 | rtlphy->default_initialgain[0] = | |
559 | (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); | |
560 | rtlphy->default_initialgain[1] = | |
561 | (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); | |
562 | rtlphy->default_initialgain[2] = | |
563 | (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0); | |
564 | rtlphy->default_initialgain[3] = | |
565 | (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0); | |
566 | ||
567 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
568 | "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n", | |
0529c6b8 LF |
569 | rtlphy->default_initialgain[0], |
570 | rtlphy->default_initialgain[1], | |
571 | rtlphy->default_initialgain[2], | |
572 | rtlphy->default_initialgain[3]); | |
c592e631 LF |
573 | |
574 | rtlphy->framesync = (u8) rtl_get_bbreg(hw, | |
575 | ROFDM0_RXDETECTOR3, MASKBYTE0); | |
576 | rtlphy->framesync_c34 = rtl_get_bbreg(hw, | |
577 | ROFDM0_RXDETECTOR2, MASKDWORD); | |
578 | ||
579 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
580 | "Default framesync (0x%x) = 0x%x\n", | |
0529c6b8 | 581 | ROFDM0_RXDETECTOR3, rtlphy->framesync); |
c592e631 LF |
582 | } |
583 | ||
0529c6b8 | 584 | void rtl8723e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel) |
c592e631 LF |
585 | { |
586 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 587 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
588 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
589 | u8 txpwr_level; | |
590 | long txpwr_dbm; | |
591 | ||
592 | txpwr_level = rtlphy->cur_cck_txpwridx; | |
0529c6b8 LF |
593 | txpwr_dbm = rtl8723_phy_txpwr_idx_to_dbm(hw, |
594 | WIRELESS_MODE_B, txpwr_level); | |
c592e631 LF |
595 | txpwr_level = rtlphy->cur_ofdm24g_txpwridx + |
596 | rtlefuse->legacy_ht_txpowerdiff; | |
0529c6b8 LF |
597 | if (rtl8723_phy_txpwr_idx_to_dbm(hw, |
598 | WIRELESS_MODE_G, | |
599 | txpwr_level) > txpwr_dbm) | |
600 | txpwr_dbm = | |
601 | rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G, | |
602 | txpwr_level); | |
c592e631 | 603 | txpwr_level = rtlphy->cur_ofdm24g_txpwridx; |
0529c6b8 LF |
604 | if (rtl8723_phy_txpwr_idx_to_dbm(hw, |
605 | WIRELESS_MODE_N_24G, | |
606 | txpwr_level) > txpwr_dbm) | |
607 | txpwr_dbm = | |
608 | rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G, | |
609 | txpwr_level); | |
c592e631 LF |
610 | *powerlevel = txpwr_dbm; |
611 | } | |
612 | ||
0529c6b8 LF |
613 | static void _rtl8723e_get_txpower_index(struct ieee80211_hw *hw, u8 channel, |
614 | u8 *cckpowerlevel, u8 *ofdmpowerlevel) | |
c592e631 LF |
615 | { |
616 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 617 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
618 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
619 | u8 index = (channel - 1); | |
620 | ||
621 | cckpowerlevel[RF90_PATH_A] = | |
622 | rtlefuse->txpwrlevel_cck[RF90_PATH_A][index]; | |
623 | cckpowerlevel[RF90_PATH_B] = | |
624 | rtlefuse->txpwrlevel_cck[RF90_PATH_B][index]; | |
625 | if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) { | |
626 | ofdmpowerlevel[RF90_PATH_A] = | |
627 | rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index]; | |
628 | ofdmpowerlevel[RF90_PATH_B] = | |
629 | rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index]; | |
630 | } else if (get_rf_type(rtlphy) == RF_2T2R) { | |
631 | ofdmpowerlevel[RF90_PATH_A] = | |
632 | rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index]; | |
633 | ofdmpowerlevel[RF90_PATH_B] = | |
634 | rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index]; | |
635 | } | |
636 | } | |
637 | ||
0529c6b8 LF |
638 | static void _rtl8723e_ccxpower_index_check(struct ieee80211_hw *hw, |
639 | u8 channel, u8 *cckpowerlevel, | |
640 | u8 *ofdmpowerlevel) | |
c592e631 LF |
641 | { |
642 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 643 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
644 | |
645 | rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; | |
646 | rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; | |
0529c6b8 | 647 | |
c592e631 LF |
648 | } |
649 | ||
0529c6b8 | 650 | void rtl8723e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel) |
c592e631 LF |
651 | { |
652 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | |
653 | u8 cckpowerlevel[2], ofdmpowerlevel[2]; | |
654 | ||
655 | if (rtlefuse->txpwr_fromeprom == false) | |
656 | return; | |
0529c6b8 LF |
657 | _rtl8723e_get_txpower_index(hw, channel, |
658 | &cckpowerlevel[0], &ofdmpowerlevel[0]); | |
659 | _rtl8723e_ccxpower_index_check(hw, | |
660 | channel, &cckpowerlevel[0], | |
661 | &ofdmpowerlevel[0]); | |
662 | rtl8723e_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]); | |
663 | rtl8723e_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel); | |
c592e631 LF |
664 | } |
665 | ||
0529c6b8 | 666 | bool rtl8723e_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm) |
c592e631 LF |
667 | { |
668 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 669 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
670 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
671 | u8 idx; | |
672 | u8 rf_path; | |
0529c6b8 LF |
673 | u8 ccktxpwridx = _rtl8723e_phy_dbm_to_txpwr_idx(hw, |
674 | WIRELESS_MODE_B, | |
675 | power_indbm); | |
676 | u8 ofdmtxpwridx = _rtl8723e_phy_dbm_to_txpwr_idx(hw, | |
677 | WIRELESS_MODE_N_24G, | |
678 | power_indbm); | |
c592e631 LF |
679 | if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0) |
680 | ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff; | |
681 | else | |
682 | ofdmtxpwridx = 0; | |
683 | RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE, | |
684 | "%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n", | |
0529c6b8 | 685 | power_indbm, ccktxpwridx, ofdmtxpwridx); |
c592e631 LF |
686 | for (idx = 0; idx < 14; idx++) { |
687 | for (rf_path = 0; rf_path < 2; rf_path++) { | |
688 | rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx; | |
689 | rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] = | |
0529c6b8 | 690 | ofdmtxpwridx; |
c592e631 | 691 | rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] = |
0529c6b8 | 692 | ofdmtxpwridx; |
c592e631 LF |
693 | } |
694 | } | |
0529c6b8 | 695 | rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel); |
c592e631 LF |
696 | return true; |
697 | } | |
698 | ||
0529c6b8 LF |
699 | static u8 _rtl8723e_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw, |
700 | enum wireless_mode wirelessmode, | |
701 | long power_indbm) | |
c592e631 LF |
702 | { |
703 | u8 txpwridx; | |
704 | long offset; | |
705 | ||
706 | switch (wirelessmode) { | |
707 | case WIRELESS_MODE_B: | |
708 | offset = -7; | |
709 | break; | |
710 | case WIRELESS_MODE_G: | |
711 | case WIRELESS_MODE_N_24G: | |
712 | offset = -8; | |
713 | break; | |
714 | default: | |
715 | offset = -8; | |
716 | break; | |
717 | } | |
718 | ||
719 | if ((power_indbm - offset) > 0) | |
0529c6b8 | 720 | txpwridx = (u8)((power_indbm - offset) * 2); |
c592e631 LF |
721 | else |
722 | txpwridx = 0; | |
723 | ||
724 | if (txpwridx > MAX_TXPWR_IDX_NMODE_92S) | |
725 | txpwridx = MAX_TXPWR_IDX_NMODE_92S; | |
726 | ||
727 | return txpwridx; | |
728 | } | |
729 | ||
0529c6b8 LF |
730 | void rtl8723e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation) |
731 | { | |
732 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
733 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
734 | enum io_type iotype; | |
735 | ||
736 | if (!is_hal_stop(rtlhal)) { | |
737 | switch (operation) { | |
738 | case SCAN_OPT_BACKUP_BAND0: | |
739 | iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN; | |
740 | rtlpriv->cfg->ops->set_hw_reg(hw, | |
741 | HW_VAR_IO_CMD, | |
742 | (u8 *)&iotype); | |
743 | ||
744 | break; | |
745 | case SCAN_OPT_RESTORE: | |
746 | iotype = IO_CMD_RESUME_DM_BY_SCAN; | |
747 | rtlpriv->cfg->ops->set_hw_reg(hw, | |
748 | HW_VAR_IO_CMD, | |
749 | (u8 *)&iotype); | |
750 | break; | |
751 | default: | |
752 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | |
753 | "Unknown Scan Backup operation.\n"); | |
754 | break; | |
755 | } | |
756 | } | |
757 | } | |
758 | ||
759 | void rtl8723e_phy_set_bw_mode_callback(struct ieee80211_hw *hw) | |
c592e631 LF |
760 | { |
761 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
762 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
0529c6b8 | 763 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
764 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
765 | u8 reg_bw_opmode; | |
766 | u8 reg_prsr_rsc; | |
767 | ||
768 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, | |
769 | "Switch to %s bandwidth\n", | |
0529c6b8 LF |
770 | rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? |
771 | "20MHz" : "40MHz"); | |
c592e631 LF |
772 | |
773 | if (is_hal_stop(rtlhal)) { | |
774 | rtlphy->set_bwmode_inprogress = false; | |
775 | return; | |
776 | } | |
777 | ||
778 | reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); | |
779 | reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); | |
780 | ||
781 | switch (rtlphy->current_chan_bw) { | |
782 | case HT_CHANNEL_WIDTH_20: | |
783 | reg_bw_opmode |= BW_OPMODE_20MHZ; | |
784 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | |
785 | break; | |
786 | case HT_CHANNEL_WIDTH_20_40: | |
787 | reg_bw_opmode &= ~BW_OPMODE_20MHZ; | |
788 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | |
789 | reg_prsr_rsc = | |
790 | (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); | |
791 | rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); | |
792 | break; | |
793 | default: | |
794 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | |
795 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); | |
796 | break; | |
797 | } | |
798 | ||
799 | switch (rtlphy->current_chan_bw) { | |
800 | case HT_CHANNEL_WIDTH_20: | |
801 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); | |
802 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); | |
803 | rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); | |
804 | break; | |
805 | case HT_CHANNEL_WIDTH_20_40: | |
806 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); | |
807 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); | |
808 | ||
809 | rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, | |
810 | (mac->cur_40_prime_sc >> 1)); | |
811 | rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); | |
812 | rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); | |
813 | ||
814 | rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), | |
815 | (mac->cur_40_prime_sc == | |
816 | HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); | |
817 | break; | |
818 | default: | |
819 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | |
820 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); | |
821 | break; | |
822 | } | |
0529c6b8 | 823 | rtl8723e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); |
c592e631 | 824 | rtlphy->set_bwmode_inprogress = false; |
0529c6b8 | 825 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); |
c592e631 LF |
826 | } |
827 | ||
0529c6b8 LF |
828 | void rtl8723e_phy_set_bw_mode(struct ieee80211_hw *hw, |
829 | enum nl80211_channel_type ch_type) | |
c592e631 LF |
830 | { |
831 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 832 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
833 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
834 | u8 tmp_bw = rtlphy->current_chan_bw; | |
835 | ||
836 | if (rtlphy->set_bwmode_inprogress) | |
837 | return; | |
838 | rtlphy->set_bwmode_inprogress = true; | |
839 | if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | |
0529c6b8 | 840 | rtl8723e_phy_set_bw_mode_callback(hw); |
c592e631 LF |
841 | } else { |
842 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | |
0529c6b8 | 843 | "false driver sleep or unload\n"); |
c592e631 LF |
844 | rtlphy->set_bwmode_inprogress = false; |
845 | rtlphy->current_chan_bw = tmp_bw; | |
846 | } | |
847 | } | |
848 | ||
0529c6b8 | 849 | void rtl8723e_phy_sw_chnl_callback(struct ieee80211_hw *hw) |
c592e631 LF |
850 | { |
851 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
852 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
0529c6b8 | 853 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
854 | u32 delay; |
855 | ||
856 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, | |
857 | "switch to channel%d\n", rtlphy->current_channel); | |
858 | if (is_hal_stop(rtlhal)) | |
859 | return; | |
860 | do { | |
861 | if (!rtlphy->sw_chnl_inprogress) | |
862 | break; | |
0529c6b8 | 863 | if (!_rtl8723e_phy_sw_chnl_step_by_step |
c592e631 LF |
864 | (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage, |
865 | &rtlphy->sw_chnl_step, &delay)) { | |
866 | if (delay > 0) | |
867 | mdelay(delay); | |
868 | else | |
869 | continue; | |
870 | } else { | |
871 | rtlphy->sw_chnl_inprogress = false; | |
872 | } | |
873 | break; | |
874 | } while (true); | |
0529c6b8 | 875 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n"); |
c592e631 LF |
876 | } |
877 | ||
0529c6b8 | 878 | u8 rtl8723e_phy_sw_chnl(struct ieee80211_hw *hw) |
c592e631 LF |
879 | { |
880 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 881 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
882 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
883 | ||
884 | if (rtlphy->sw_chnl_inprogress) | |
885 | return 0; | |
886 | if (rtlphy->set_bwmode_inprogress) | |
887 | return 0; | |
888 | RT_ASSERT((rtlphy->current_channel <= 14), | |
889 | "WIRELESS_MODE_G but channel>14"); | |
890 | rtlphy->sw_chnl_inprogress = true; | |
891 | rtlphy->sw_chnl_stage = 0; | |
892 | rtlphy->sw_chnl_step = 0; | |
893 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | |
0529c6b8 | 894 | rtl8723e_phy_sw_chnl_callback(hw); |
c592e631 | 895 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
0529c6b8 | 896 | "sw_chnl_inprogress false schdule workitem\n"); |
c592e631 LF |
897 | rtlphy->sw_chnl_inprogress = false; |
898 | } else { | |
899 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | |
900 | "sw_chnl_inprogress false driver sleep or unload\n"); | |
901 | rtlphy->sw_chnl_inprogress = false; | |
902 | } | |
903 | return 1; | |
904 | } | |
905 | ||
0529c6b8 | 906 | static void _rtl8723e_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel) |
c592e631 LF |
907 | { |
908 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 909 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
910 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
911 | ||
912 | if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { | |
913 | if (channel == 6 && rtlphy->current_chan_bw == | |
0529c6b8 LF |
914 | HT_CHANNEL_WIDTH_20) |
915 | rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, | |
916 | MASKDWORD, 0x00255); | |
c592e631 | 917 | else{ |
0529c6b8 LF |
918 | u32 backuprf0x1a = (u32)rtl_get_rfreg(hw, |
919 | RF90_PATH_A, RF_RX_G1, | |
920 | RFREG_OFFSET_MASK); | |
921 | rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, | |
922 | MASKDWORD, backuprf0x1a); | |
c592e631 LF |
923 | } |
924 | } | |
925 | } | |
926 | ||
0529c6b8 LF |
927 | static bool _rtl8723e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, |
928 | u8 channel, u8 *stage, u8 *step, | |
929 | u32 *delay) | |
c592e631 LF |
930 | { |
931 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 932 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
933 | struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; |
934 | u32 precommoncmdcnt; | |
935 | struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; | |
936 | u32 postcommoncmdcnt; | |
937 | struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; | |
938 | u32 rfdependcmdcnt; | |
939 | struct swchnlcmd *currentcmd = NULL; | |
940 | u8 rfpath; | |
941 | u8 num_total_rfpath = rtlphy->num_total_rfpath; | |
942 | ||
943 | precommoncmdcnt = 0; | |
0a168b48 | 944 | rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, |
0529c6b8 LF |
945 | MAX_PRECMD_CNT, |
946 | CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); | |
0a168b48 LF |
947 | rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, |
948 | MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); | |
0529c6b8 | 949 | |
c592e631 LF |
950 | postcommoncmdcnt = 0; |
951 | ||
0a168b48 LF |
952 | rtl8723_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, |
953 | MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); | |
0529c6b8 | 954 | |
c592e631 LF |
955 | rfdependcmdcnt = 0; |
956 | ||
957 | RT_ASSERT((channel >= 1 && channel <= 14), | |
958 | "illegal channel for Zebra: %d\n", channel); | |
959 | ||
0a168b48 LF |
960 | rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, |
961 | MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, | |
0529c6b8 | 962 | RF_CHNLBW, channel, 10); |
c592e631 | 963 | |
0a168b48 | 964 | rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, |
0529c6b8 LF |
965 | MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, |
966 | 0); | |
c592e631 LF |
967 | |
968 | do { | |
969 | switch (*stage) { | |
970 | case 0: | |
971 | currentcmd = &precommoncmd[*step]; | |
972 | break; | |
973 | case 1: | |
974 | currentcmd = &rfdependcmd[*step]; | |
975 | break; | |
976 | case 2: | |
977 | currentcmd = &postcommoncmd[*step]; | |
978 | break; | |
0529c6b8 LF |
979 | default: |
980 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | |
981 | "Invalid 'stage' = %d, Check it!\n", *stage); | |
982 | return true; | |
c592e631 LF |
983 | } |
984 | ||
985 | if (currentcmd->cmdid == CMDID_END) { | |
986 | if ((*stage) == 2) { | |
987 | return true; | |
988 | } else { | |
989 | (*stage)++; | |
990 | (*step) = 0; | |
991 | continue; | |
992 | } | |
993 | } | |
994 | ||
995 | switch (currentcmd->cmdid) { | |
996 | case CMDID_SET_TXPOWEROWER_LEVEL: | |
0529c6b8 | 997 | rtl8723e_phy_set_txpower_level(hw, channel); |
c592e631 LF |
998 | break; |
999 | case CMDID_WRITEPORT_ULONG: | |
1000 | rtl_write_dword(rtlpriv, currentcmd->para1, | |
1001 | currentcmd->para2); | |
1002 | break; | |
1003 | case CMDID_WRITEPORT_USHORT: | |
1004 | rtl_write_word(rtlpriv, currentcmd->para1, | |
1005 | (u16) currentcmd->para2); | |
1006 | break; | |
1007 | case CMDID_WRITEPORT_UCHAR: | |
1008 | rtl_write_byte(rtlpriv, currentcmd->para1, | |
1009 | (u8) currentcmd->para2); | |
1010 | break; | |
1011 | case CMDID_RF_WRITEREG: | |
1012 | for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { | |
1013 | rtlphy->rfreg_chnlval[rfpath] = | |
1014 | ((rtlphy->rfreg_chnlval[rfpath] & | |
1015 | 0xfffffc00) | currentcmd->para2); | |
1016 | ||
1017 | rtl_set_rfreg(hw, (enum radio_path)rfpath, | |
1018 | currentcmd->para1, | |
1019 | RFREG_OFFSET_MASK, | |
1020 | rtlphy->rfreg_chnlval[rfpath]); | |
1021 | } | |
0529c6b8 | 1022 | _rtl8723e_phy_sw_rf_seting(hw, channel); |
c592e631 LF |
1023 | break; |
1024 | default: | |
0529c6b8 | 1025 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, |
c592e631 LF |
1026 | "switch case not process\n"); |
1027 | break; | |
1028 | } | |
1029 | ||
1030 | break; | |
1031 | } while (true); | |
1032 | ||
1033 | (*delay) = currentcmd->msdelay; | |
1034 | (*step)++; | |
1035 | return false; | |
1036 | } | |
1037 | ||
0529c6b8 | 1038 | static u8 _rtl8723e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb) |
c592e631 LF |
1039 | { |
1040 | u32 reg_eac, reg_e94, reg_e9c, reg_ea4; | |
1041 | u8 result = 0x00; | |
1042 | ||
1043 | rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f); | |
1044 | rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f); | |
1045 | rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102); | |
1046 | rtl_set_bbreg(hw, 0xe3c, MASKDWORD, | |
1047 | config_pathb ? 0x28160202 : 0x28160502); | |
1048 | ||
1049 | if (config_pathb) { | |
1050 | rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22); | |
1051 | rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22); | |
1052 | rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102); | |
1053 | rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202); | |
1054 | } | |
1055 | ||
1056 | rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1); | |
1057 | rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000); | |
1058 | rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000); | |
1059 | ||
1060 | mdelay(IQK_DELAY_TIME); | |
1061 | ||
1062 | reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); | |
1063 | reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD); | |
1064 | reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD); | |
1065 | reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD); | |
1066 | ||
1067 | if (!(reg_eac & BIT(28)) && | |
1068 | (((reg_e94 & 0x03FF0000) >> 16) != 0x142) && | |
1069 | (((reg_e9c & 0x03FF0000) >> 16) != 0x42)) | |
1070 | result |= 0x01; | |
1071 | else | |
1072 | return result; | |
1073 | ||
1074 | if (!(reg_eac & BIT(27)) && | |
1075 | (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) && | |
1076 | (((reg_eac & 0x03FF0000) >> 16) != 0x36)) | |
1077 | result |= 0x02; | |
1078 | return result; | |
1079 | } | |
1080 | ||
0529c6b8 | 1081 | static u8 _rtl8723e_phy_path_b_iqk(struct ieee80211_hw *hw) |
c592e631 LF |
1082 | { |
1083 | u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc; | |
1084 | u8 result = 0x00; | |
1085 | ||
1086 | rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002); | |
1087 | rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000); | |
1088 | mdelay(IQK_DELAY_TIME); | |
1089 | reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD); | |
1090 | reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD); | |
1091 | reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD); | |
1092 | reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD); | |
1093 | reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD); | |
1094 | ||
1095 | if (!(reg_eac & BIT(31)) && | |
1096 | (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) && | |
1097 | (((reg_ebc & 0x03FF0000) >> 16) != 0x42)) | |
1098 | result |= 0x01; | |
1099 | else | |
1100 | return result; | |
1101 | if (!(reg_eac & BIT(30)) && | |
1102 | (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) && | |
1103 | (((reg_ecc & 0x03FF0000) >> 16) != 0x36)) | |
1104 | result |= 0x02; | |
1105 | return result; | |
1106 | } | |
1107 | ||
0529c6b8 LF |
1108 | static bool _rtl8723e_phy_simularity_compare(struct ieee80211_hw *hw, |
1109 | long result[][8], u8 c1, u8 c2) | |
c592e631 LF |
1110 | { |
1111 | u32 i, j, diff, simularity_bitmap, bound; | |
1112 | ||
1113 | u8 final_candidate[2] = { 0xFF, 0xFF }; | |
1114 | bool bresult = true; | |
1115 | ||
1116 | bound = 4; | |
1117 | ||
1118 | simularity_bitmap = 0; | |
1119 | ||
1120 | for (i = 0; i < bound; i++) { | |
1121 | diff = (result[c1][i] > result[c2][i]) ? | |
1122 | (result[c1][i] - result[c2][i]) : | |
1123 | (result[c2][i] - result[c1][i]); | |
1124 | ||
1125 | if (diff > MAX_TOLERANCE) { | |
1126 | if ((i == 2 || i == 6) && !simularity_bitmap) { | |
1127 | if (result[c1][i] + result[c1][i + 1] == 0) | |
1128 | final_candidate[(i / 4)] = c2; | |
1129 | else if (result[c2][i] + result[c2][i + 1] == 0) | |
1130 | final_candidate[(i / 4)] = c1; | |
1131 | else | |
1132 | simularity_bitmap = simularity_bitmap | | |
1133 | (1 << i); | |
1134 | } else | |
1135 | simularity_bitmap = | |
1136 | simularity_bitmap | (1 << i); | |
1137 | } | |
1138 | } | |
1139 | ||
1140 | if (simularity_bitmap == 0) { | |
1141 | for (i = 0; i < (bound / 4); i++) { | |
1142 | if (final_candidate[i] != 0xFF) { | |
1143 | for (j = i * 4; j < (i + 1) * 4 - 2; j++) | |
1144 | result[3][j] = | |
1145 | result[final_candidate[i]][j]; | |
1146 | bresult = false; | |
1147 | } | |
1148 | } | |
1149 | return bresult; | |
1150 | } else if (!(simularity_bitmap & 0x0F)) { | |
1151 | for (i = 0; i < 4; i++) | |
1152 | result[3][i] = result[c1][i]; | |
1153 | return false; | |
1154 | } else { | |
1155 | return false; | |
1156 | } | |
1157 | ||
1158 | } | |
1159 | ||
0529c6b8 LF |
1160 | static void _rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw, |
1161 | long result[][8], u8 t, bool is2t) | |
c592e631 LF |
1162 | { |
1163 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 1164 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
1165 | u32 i; |
1166 | u8 patha_ok, pathb_ok; | |
1167 | u32 adda_reg[IQK_ADDA_REG_NUM] = { | |
1168 | 0x85c, 0xe6c, 0xe70, 0xe74, | |
1169 | 0xe78, 0xe7c, 0xe80, 0xe84, | |
1170 | 0xe88, 0xe8c, 0xed0, 0xed4, | |
1171 | 0xed8, 0xedc, 0xee0, 0xeec | |
1172 | }; | |
0529c6b8 | 1173 | |
c592e631 LF |
1174 | u32 iqk_mac_reg[IQK_MAC_REG_NUM] = { |
1175 | 0x522, 0x550, 0x551, 0x040 | |
1176 | }; | |
0529c6b8 | 1177 | |
c592e631 | 1178 | const u32 retrycount = 2; |
c592e631 | 1179 | |
0529c6b8 LF |
1180 | u32 bbvalue; |
1181 | ||
c592e631 | 1182 | if (t == 0) { |
0529c6b8 LF |
1183 | bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD); |
1184 | ||
5c99f04f LF |
1185 | rtl8723_save_adda_registers(hw, adda_reg, |
1186 | rtlphy->adda_backup, 16); | |
0a168b48 LF |
1187 | rtl8723_phy_save_mac_registers(hw, iqk_mac_reg, |
1188 | rtlphy->iqk_mac_backup); | |
c592e631 | 1189 | } |
0a168b48 | 1190 | rtl8723_phy_path_adda_on(hw, adda_reg, true, is2t); |
c592e631 LF |
1191 | if (t == 0) { |
1192 | rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw, | |
0529c6b8 LF |
1193 | RFPGA0_XA_HSSIPARAMETER1, |
1194 | BIT(8)); | |
c592e631 LF |
1195 | } |
1196 | ||
1197 | if (!rtlphy->rfpi_enable) | |
0a168b48 | 1198 | rtl8723_phy_pi_mode_switch(hw, true); |
c592e631 LF |
1199 | if (t == 0) { |
1200 | rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD); | |
1201 | rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD); | |
1202 | rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD); | |
1203 | } | |
1204 | rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600); | |
1205 | rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4); | |
1206 | rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000); | |
1207 | if (is2t) { | |
1208 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000); | |
1209 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000); | |
1210 | } | |
0a168b48 | 1211 | rtl8723_phy_mac_setting_calibration(hw, iqk_mac_reg, |
c592e631 LF |
1212 | rtlphy->iqk_mac_backup); |
1213 | rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000); | |
1214 | if (is2t) | |
1215 | rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000); | |
1216 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000); | |
1217 | rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00); | |
1218 | rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800); | |
1219 | for (i = 0; i < retrycount; i++) { | |
0529c6b8 | 1220 | patha_ok = _rtl8723e_phy_path_a_iqk(hw, is2t); |
c592e631 LF |
1221 | if (patha_ok == 0x03) { |
1222 | result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) & | |
1223 | 0x3FF0000) >> 16; | |
1224 | result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & | |
1225 | 0x3FF0000) >> 16; | |
1226 | result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) & | |
1227 | 0x3FF0000) >> 16; | |
1228 | result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) & | |
1229 | 0x3FF0000) >> 16; | |
1230 | break; | |
1231 | } else if (i == (retrycount - 1) && patha_ok == 0x01) | |
1232 | ||
1233 | result[t][0] = (rtl_get_bbreg(hw, 0xe94, | |
0529c6b8 LF |
1234 | MASKDWORD) & 0x3FF0000) >> |
1235 | 16; | |
c592e631 LF |
1236 | result[t][1] = |
1237 | (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16; | |
1238 | ||
1239 | } | |
1240 | ||
1241 | if (is2t) { | |
0a168b48 LF |
1242 | rtl8723_phy_path_a_standby(hw); |
1243 | rtl8723_phy_path_adda_on(hw, adda_reg, false, is2t); | |
c592e631 | 1244 | for (i = 0; i < retrycount; i++) { |
0529c6b8 | 1245 | pathb_ok = _rtl8723e_phy_path_b_iqk(hw); |
c592e631 | 1246 | if (pathb_ok == 0x03) { |
0529c6b8 LF |
1247 | result[t][4] = (rtl_get_bbreg(hw, |
1248 | 0xeb4, | |
1249 | MASKDWORD) & | |
1250 | 0x3FF0000) >> 16; | |
c592e631 LF |
1251 | result[t][5] = |
1252 | (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & | |
1253 | 0x3FF0000) >> 16; | |
1254 | result[t][6] = | |
1255 | (rtl_get_bbreg(hw, 0xec4, MASKDWORD) & | |
1256 | 0x3FF0000) >> 16; | |
1257 | result[t][7] = | |
1258 | (rtl_get_bbreg(hw, 0xecc, MASKDWORD) & | |
1259 | 0x3FF0000) >> 16; | |
1260 | break; | |
1261 | } else if (i == (retrycount - 1) && pathb_ok == 0x01) { | |
0529c6b8 LF |
1262 | result[t][4] = (rtl_get_bbreg(hw, |
1263 | 0xeb4, | |
1264 | MASKDWORD) & | |
1265 | 0x3FF0000) >> 16; | |
c592e631 LF |
1266 | } |
1267 | result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) & | |
1268 | 0x3FF0000) >> 16; | |
1269 | } | |
1270 | } | |
1271 | rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04); | |
1272 | rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874); | |
1273 | rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08); | |
1274 | rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0); | |
1275 | rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3); | |
1276 | if (is2t) | |
1277 | rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3); | |
1278 | if (t != 0) { | |
1279 | if (!rtlphy->rfpi_enable) | |
0a168b48 LF |
1280 | rtl8723_phy_pi_mode_switch(hw, false); |
1281 | rtl8723_phy_reload_adda_registers(hw, adda_reg, | |
1282 | rtlphy->adda_backup, 16); | |
1283 | rtl8723_phy_reload_mac_registers(hw, iqk_mac_reg, | |
1284 | rtlphy->iqk_mac_backup); | |
c592e631 LF |
1285 | } |
1286 | } | |
1287 | ||
0529c6b8 | 1288 | static void _rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) |
c592e631 | 1289 | { |
c592e631 LF |
1290 | u8 tmpreg; |
1291 | u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; | |
0529c6b8 | 1292 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
c592e631 LF |
1293 | |
1294 | tmpreg = rtl_read_byte(rtlpriv, 0xd03); | |
1295 | ||
1296 | if ((tmpreg & 0x70) != 0) | |
1297 | rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); | |
1298 | else | |
1299 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | |
1300 | ||
1301 | if ((tmpreg & 0x70) != 0) { | |
1302 | rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); | |
1303 | ||
1304 | if (is2t) | |
1305 | rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, | |
1306 | MASK12BITS); | |
1307 | ||
1308 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, | |
1309 | (rf_a_mode & 0x8FFFF) | 0x10000); | |
1310 | ||
1311 | if (is2t) | |
1312 | rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, | |
1313 | (rf_b_mode & 0x8FFFF) | 0x10000); | |
1314 | } | |
1315 | lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); | |
1316 | ||
1317 | rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); | |
1318 | ||
1319 | mdelay(100); | |
1320 | ||
1321 | if ((tmpreg & 0x70) != 0) { | |
1322 | rtl_write_byte(rtlpriv, 0xd03, tmpreg); | |
1323 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); | |
1324 | ||
1325 | if (is2t) | |
1326 | rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, | |
1327 | rf_b_mode); | |
1328 | } else { | |
1329 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | |
1330 | } | |
1331 | } | |
1332 | ||
0529c6b8 LF |
1333 | static void _rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw, |
1334 | bool bmain, bool is2t) | |
c592e631 LF |
1335 | { |
1336 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
1337 | ||
1338 | if (is_hal_stop(rtlhal)) { | |
1339 | rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01); | |
0529c6b8 | 1340 | rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01); |
c592e631 LF |
1341 | } |
1342 | if (is2t) { | |
1343 | if (bmain) | |
1344 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | |
1345 | BIT(5) | BIT(6), 0x1); | |
1346 | else | |
1347 | rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE, | |
1348 | BIT(5) | BIT(6), 0x2); | |
1349 | } else { | |
1350 | if (bmain) | |
1351 | rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2); | |
1352 | else | |
1353 | rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1); | |
1354 | ||
1355 | } | |
0529c6b8 | 1356 | |
c592e631 LF |
1357 | } |
1358 | ||
1359 | #undef IQK_ADDA_REG_NUM | |
1360 | #undef IQK_DELAY_TIME | |
1361 | ||
0529c6b8 | 1362 | void rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery) |
c592e631 LF |
1363 | { |
1364 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 LF |
1365 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
1366 | ||
c592e631 LF |
1367 | long result[4][8]; |
1368 | u8 i, final_candidate; | |
0529c6b8 LF |
1369 | bool b_patha_ok, b_pathb_ok; |
1370 | long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, | |
1371 | reg_ecc, reg_tmp = 0; | |
c592e631 | 1372 | bool is12simular, is13simular, is23simular; |
c592e631 LF |
1373 | u32 iqk_bb_reg[10] = { |
1374 | ROFDM0_XARXIQIMBALANCE, | |
1375 | ROFDM0_XBRXIQIMBALANCE, | |
1376 | ROFDM0_ECCATHRESHOLD, | |
1377 | ROFDM0_AGCRSSITABLE, | |
1378 | ROFDM0_XATXIQIMBALANCE, | |
1379 | ROFDM0_XBTXIQIMBALANCE, | |
1380 | ROFDM0_XCTXIQIMBALANCE, | |
1381 | ROFDM0_XCTXAFE, | |
1382 | ROFDM0_XDTXAFE, | |
1383 | ROFDM0_RXIQEXTANTA | |
1384 | }; | |
1385 | ||
0529c6b8 LF |
1386 | if (b_recovery) { |
1387 | rtl8723_phy_reload_adda_registers(hw, | |
1388 | iqk_bb_reg, | |
0a168b48 | 1389 | rtlphy->iqk_bb_backup, 10); |
c592e631 LF |
1390 | return; |
1391 | } | |
c592e631 LF |
1392 | for (i = 0; i < 8; i++) { |
1393 | result[0][i] = 0; | |
1394 | result[1][i] = 0; | |
1395 | result[2][i] = 0; | |
1396 | result[3][i] = 0; | |
1397 | } | |
1398 | final_candidate = 0xff; | |
0529c6b8 LF |
1399 | b_patha_ok = false; |
1400 | b_pathb_ok = false; | |
c592e631 LF |
1401 | is12simular = false; |
1402 | is23simular = false; | |
1403 | is13simular = false; | |
1404 | for (i = 0; i < 3; i++) { | |
0529c6b8 | 1405 | _rtl8723e_phy_iq_calibrate(hw, result, i, false); |
c592e631 | 1406 | if (i == 1) { |
0529c6b8 LF |
1407 | is12simular = |
1408 | _rtl8723e_phy_simularity_compare(hw, result, 0, 1); | |
c592e631 LF |
1409 | if (is12simular) { |
1410 | final_candidate = 0; | |
1411 | break; | |
1412 | } | |
1413 | } | |
1414 | if (i == 2) { | |
0529c6b8 LF |
1415 | is13simular = |
1416 | _rtl8723e_phy_simularity_compare(hw, result, 0, 2); | |
c592e631 LF |
1417 | if (is13simular) { |
1418 | final_candidate = 0; | |
1419 | break; | |
1420 | } | |
0529c6b8 LF |
1421 | is23simular = |
1422 | _rtl8723e_phy_simularity_compare(hw, result, 1, 2); | |
1423 | if (is23simular) | |
c592e631 | 1424 | final_candidate = 1; |
0529c6b8 | 1425 | else { |
c592e631 LF |
1426 | for (i = 0; i < 8; i++) |
1427 | reg_tmp += result[3][i]; | |
1428 | ||
1429 | if (reg_tmp != 0) | |
1430 | final_candidate = 3; | |
1431 | else | |
1432 | final_candidate = 0xFF; | |
1433 | } | |
1434 | } | |
1435 | } | |
1436 | for (i = 0; i < 4; i++) { | |
1437 | reg_e94 = result[i][0]; | |
1438 | reg_e9c = result[i][1]; | |
1439 | reg_ea4 = result[i][2]; | |
0529c6b8 | 1440 | reg_eac = result[i][3]; |
c592e631 LF |
1441 | reg_eb4 = result[i][4]; |
1442 | reg_ebc = result[i][5]; | |
0529c6b8 LF |
1443 | reg_ec4 = result[i][6]; |
1444 | reg_ecc = result[i][7]; | |
c592e631 LF |
1445 | } |
1446 | if (final_candidate != 0xff) { | |
1447 | rtlphy->reg_e94 = reg_e94 = result[final_candidate][0]; | |
1448 | rtlphy->reg_e9c = reg_e9c = result[final_candidate][1]; | |
1449 | reg_ea4 = result[final_candidate][2]; | |
0529c6b8 | 1450 | reg_eac = result[final_candidate][3]; |
c592e631 LF |
1451 | rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4]; |
1452 | rtlphy->reg_ebc = reg_ebc = result[final_candidate][5]; | |
0529c6b8 LF |
1453 | reg_ec4 = result[final_candidate][6]; |
1454 | reg_ecc = result[final_candidate][7]; | |
1455 | b_patha_ok = true; | |
1456 | b_pathb_ok = true; | |
c592e631 LF |
1457 | } else { |
1458 | rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; | |
1459 | rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0; | |
1460 | } | |
0529c6b8 LF |
1461 | if (reg_e94 != 0) |
1462 | rtl8723_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result, | |
0a168b48 LF |
1463 | final_candidate, |
1464 | (reg_ea4 == 0)); | |
5c99f04f LF |
1465 | rtl8723_save_adda_registers(hw, iqk_bb_reg, |
1466 | rtlphy->iqk_bb_backup, 10); | |
c592e631 LF |
1467 | } |
1468 | ||
0529c6b8 | 1469 | void rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw) |
c592e631 | 1470 | { |
0529c6b8 | 1471 | _rtl8723e_phy_lc_calibrate(hw, false); |
c592e631 LF |
1472 | } |
1473 | ||
0529c6b8 | 1474 | void rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain) |
c592e631 | 1475 | { |
0529c6b8 | 1476 | _rtl8723e_phy_set_rfpath_switch(hw, bmain, false); |
c592e631 LF |
1477 | } |
1478 | ||
0529c6b8 | 1479 | bool rtl8723e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype) |
c592e631 LF |
1480 | { |
1481 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 1482 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
1483 | bool postprocessing = false; |
1484 | ||
1485 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | |
1486 | "-->IO Cmd(%#x), set_io_inprogress(%d)\n", | |
0529c6b8 | 1487 | iotype, rtlphy->set_io_inprogress); |
c592e631 LF |
1488 | do { |
1489 | switch (iotype) { | |
1490 | case IO_CMD_RESUME_DM_BY_SCAN: | |
1491 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | |
1492 | "[IO CMD] Resume DM after scan.\n"); | |
1493 | postprocessing = true; | |
1494 | break; | |
0529c6b8 | 1495 | case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: |
c592e631 LF |
1496 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, |
1497 | "[IO CMD] Pause DM before scan.\n"); | |
1498 | postprocessing = true; | |
1499 | break; | |
1500 | default: | |
0529c6b8 | 1501 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, |
c592e631 LF |
1502 | "switch case not process\n"); |
1503 | break; | |
1504 | } | |
1505 | } while (false); | |
1506 | if (postprocessing && !rtlphy->set_io_inprogress) { | |
1507 | rtlphy->set_io_inprogress = true; | |
1508 | rtlphy->current_io_type = iotype; | |
1509 | } else { | |
1510 | return false; | |
1511 | } | |
0529c6b8 LF |
1512 | rtl8723e_phy_set_io(hw); |
1513 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype); | |
c592e631 LF |
1514 | return true; |
1515 | } | |
1516 | ||
0529c6b8 | 1517 | static void rtl8723e_phy_set_io(struct ieee80211_hw *hw) |
c592e631 LF |
1518 | { |
1519 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
0529c6b8 | 1520 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
c592e631 LF |
1521 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; |
1522 | ||
1523 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | |
1524 | "--->Cmd(%#x), set_io_inprogress(%d)\n", | |
0529c6b8 | 1525 | rtlphy->current_io_type, rtlphy->set_io_inprogress); |
c592e631 LF |
1526 | switch (rtlphy->current_io_type) { |
1527 | case IO_CMD_RESUME_DM_BY_SCAN: | |
1528 | dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1; | |
0529c6b8 LF |
1529 | rtl8723e_dm_write_dig(hw); |
1530 | rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel); | |
c592e631 | 1531 | break; |
0529c6b8 | 1532 | case IO_CMD_PAUSE_BAND0_DM_BY_SCAN: |
c592e631 LF |
1533 | rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue; |
1534 | dm_digtable->cur_igvalue = 0x17; | |
0529c6b8 | 1535 | rtl8723e_dm_write_dig(hw); |
c592e631 LF |
1536 | break; |
1537 | default: | |
0529c6b8 | 1538 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, |
c592e631 LF |
1539 | "switch case not process\n"); |
1540 | break; | |
1541 | } | |
1542 | rtlphy->set_io_inprogress = false; | |
1543 | RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, | |
0529c6b8 | 1544 | "(%#x)\n", rtlphy->current_io_type); |
c592e631 LF |
1545 | } |
1546 | ||
0529c6b8 | 1547 | static void rtl8723e_phy_set_rf_on(struct ieee80211_hw *hw) |
c592e631 LF |
1548 | { |
1549 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
1550 | ||
1551 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); | |
1552 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | |
1553 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); | |
1554 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | |
1555 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | |
1556 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | |
1557 | } | |
1558 | ||
0529c6b8 | 1559 | static void _rtl8723e_phy_set_rf_sleep(struct ieee80211_hw *hw) |
c592e631 | 1560 | { |
c592e631 LF |
1561 | u32 u4b_tmp; |
1562 | u8 delay = 5; | |
0529c6b8 | 1563 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
c592e631 LF |
1564 | |
1565 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | |
1566 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); | |
1567 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); | |
1568 | u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); | |
1569 | while (u4b_tmp != 0 && delay > 0) { | |
1570 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); | |
1571 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); | |
1572 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); | |
1573 | u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); | |
1574 | delay--; | |
1575 | } | |
1576 | if (delay == 0) { | |
1577 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); | |
1578 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | |
1579 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | |
1580 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | |
1581 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, | |
1582 | "Switch RF timeout !!!.\n"); | |
1583 | return; | |
1584 | } | |
1585 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | |
1586 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); | |
1587 | } | |
1588 | ||
0529c6b8 LF |
1589 | static bool _rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw, |
1590 | enum rf_pwrstate rfpwr_state) | |
c592e631 LF |
1591 | { |
1592 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
1593 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | |
1594 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | |
1595 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | |
c592e631 LF |
1596 | bool bresult = true; |
1597 | u8 i, queue_id; | |
0529c6b8 | 1598 | struct rtl8192_tx_ring *ring = NULL; |
c592e631 LF |
1599 | |
1600 | switch (rfpwr_state) { | |
1601 | case ERFON: | |
1602 | if ((ppsc->rfpwr_state == ERFOFF) && | |
1603 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { | |
1604 | bool rtstatus; | |
0529c6b8 LF |
1605 | u32 initializecount = 0; |
1606 | ||
c592e631 | 1607 | do { |
0529c6b8 | 1608 | initializecount++; |
c592e631 LF |
1609 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, |
1610 | "IPS Set eRf nic enable\n"); | |
1611 | rtstatus = rtl_ps_enable_nic(hw); | |
0529c6b8 | 1612 | } while (!rtstatus && (initializecount < 10)); |
c592e631 LF |
1613 | RT_CLEAR_PS_LEVEL(ppsc, |
1614 | RT_RF_OFF_LEVL_HALT_NIC); | |
1615 | } else { | |
1616 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | |
1617 | "Set ERFON sleeped:%d ms\n", | |
0529c6b8 LF |
1618 | jiffies_to_msecs(jiffies - |
1619 | ppsc-> | |
1620 | last_sleep_jiffies)); | |
c592e631 | 1621 | ppsc->last_awake_jiffies = jiffies; |
0529c6b8 | 1622 | rtl8723e_phy_set_rf_on(hw); |
c592e631 LF |
1623 | } |
1624 | if (mac->link_state == MAC80211_LINKED) { | |
1625 | rtlpriv->cfg->ops->led_control(hw, | |
0529c6b8 | 1626 | LED_CTL_LINK); |
c592e631 LF |
1627 | } else { |
1628 | rtlpriv->cfg->ops->led_control(hw, | |
0529c6b8 | 1629 | LED_CTL_NO_LINK); |
c592e631 LF |
1630 | } |
1631 | break; | |
1632 | case ERFOFF: | |
1633 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { | |
1634 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | |
1635 | "IPS Set eRf nic disable\n"); | |
1636 | rtl_ps_disable_nic(hw); | |
1637 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | |
1638 | } else { | |
1639 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { | |
1640 | rtlpriv->cfg->ops->led_control(hw, | |
0529c6b8 | 1641 | LED_CTL_NO_LINK); |
c592e631 LF |
1642 | } else { |
1643 | rtlpriv->cfg->ops->led_control(hw, | |
0529c6b8 | 1644 | LED_CTL_POWER_OFF); |
c592e631 LF |
1645 | } |
1646 | } | |
1647 | break; | |
1648 | case ERFSLEEP: | |
1649 | if (ppsc->rfpwr_state == ERFOFF) | |
1650 | break; | |
1651 | for (queue_id = 0, i = 0; | |
1652 | queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { | |
1653 | ring = &pcipriv->dev.tx_ring[queue_id]; | |
0529c6b8 LF |
1654 | if (queue_id == BEACON_QUEUE || |
1655 | skb_queue_len(&ring->queue) == 0) { | |
c592e631 LF |
1656 | queue_id++; |
1657 | continue; | |
1658 | } else { | |
1659 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | |
1660 | "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", | |
1661 | (i + 1), queue_id, | |
1662 | skb_queue_len(&ring->queue)); | |
1663 | ||
1664 | udelay(10); | |
1665 | i++; | |
1666 | } | |
1667 | if (i >= MAX_DOZE_WAITING_TIMES_9x) { | |
1668 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | |
0529c6b8 LF |
1669 | "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", |
1670 | MAX_DOZE_WAITING_TIMES_9x, | |
1671 | queue_id, | |
1672 | skb_queue_len(&ring->queue)); | |
c592e631 LF |
1673 | break; |
1674 | } | |
1675 | } | |
1676 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | |
1677 | "Set ERFSLEEP awaked:%d ms\n", | |
0529c6b8 LF |
1678 | jiffies_to_msecs(jiffies - |
1679 | ppsc->last_awake_jiffies)); | |
c592e631 | 1680 | ppsc->last_sleep_jiffies = jiffies; |
0529c6b8 | 1681 | _rtl8723e_phy_set_rf_sleep(hw); |
c592e631 LF |
1682 | break; |
1683 | default: | |
0529c6b8 LF |
1684 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, |
1685 | "switch case not process\n"); | |
c592e631 LF |
1686 | bresult = false; |
1687 | break; | |
1688 | } | |
1689 | if (bresult) | |
1690 | ppsc->rfpwr_state = rfpwr_state; | |
1691 | return bresult; | |
1692 | } | |
1693 | ||
0529c6b8 LF |
1694 | bool rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw, |
1695 | enum rf_pwrstate rfpwr_state) | |
c592e631 LF |
1696 | { |
1697 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | |
0529c6b8 | 1698 | |
c592e631 LF |
1699 | bool bresult = false; |
1700 | ||
1701 | if (rfpwr_state == ppsc->rfpwr_state) | |
1702 | return bresult; | |
0529c6b8 | 1703 | bresult = _rtl8723e_phy_set_rf_power_state(hw, rfpwr_state); |
c592e631 LF |
1704 | return bresult; |
1705 | } |