1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright(c) 2009-2014 Realtek Corporation.*/
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include "../wifi.h"
5*4882a593Smuzhiyun #include "../pci.h"
6*4882a593Smuzhiyun #include "../ps.h"
7*4882a593Smuzhiyun #include "reg.h"
8*4882a593Smuzhiyun #include "def.h"
9*4882a593Smuzhiyun #include "phy.h"
10*4882a593Smuzhiyun #include "../rtl8723com/phy_common.h"
11*4882a593Smuzhiyun #include "rf.h"
12*4882a593Smuzhiyun #include "dm.h"
13*4882a593Smuzhiyun #include "../rtl8723com/dm_common.h"
14*4882a593Smuzhiyun #include "table.h"
15*4882a593Smuzhiyun #include "trx.h"
16*4882a593Smuzhiyun #include <linux/kernel.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun static bool _rtl8723be_phy_bb8723b_config_parafile(struct ieee80211_hw *hw);
19*4882a593Smuzhiyun static bool _rtl8723be_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
20*4882a593Smuzhiyun static bool _rtl8723be_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
21*4882a593Smuzhiyun u8 configtype);
22*4882a593Smuzhiyun static bool _rtl8723be_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
23*4882a593Smuzhiyun u8 configtype);
24*4882a593Smuzhiyun static bool _rtl8723be_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
25*4882a593Smuzhiyun u8 channel, u8 *stage,
26*4882a593Smuzhiyun u8 *step, u32 *delay);
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun static void rtl8723be_phy_set_rf_on(struct ieee80211_hw *hw);
29*4882a593Smuzhiyun static void rtl8723be_phy_set_io(struct ieee80211_hw *hw);
30*4882a593Smuzhiyun
rtl8723be_phy_query_rf_reg(struct ieee80211_hw * hw,enum radio_path rfpath,u32 regaddr,u32 bitmask)31*4882a593Smuzhiyun u32 rtl8723be_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath,
32*4882a593Smuzhiyun u32 regaddr, u32 bitmask)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
35*4882a593Smuzhiyun u32 original_value, readback_value, bitshift;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
38*4882a593Smuzhiyun "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
39*4882a593Smuzhiyun regaddr, rfpath, bitmask);
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun spin_lock(&rtlpriv->locks.rf_lock);
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun original_value = rtl8723_phy_rf_serial_read(hw, rfpath, regaddr);
44*4882a593Smuzhiyun bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
45*4882a593Smuzhiyun readback_value = (original_value & bitmask) >> bitshift;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun spin_unlock(&rtlpriv->locks.rf_lock);
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
50*4882a593Smuzhiyun "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
51*4882a593Smuzhiyun regaddr, rfpath, bitmask, original_value);
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun return readback_value;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun
rtl8723be_phy_set_rf_reg(struct ieee80211_hw * hw,enum radio_path path,u32 regaddr,u32 bitmask,u32 data)56*4882a593Smuzhiyun void rtl8723be_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path path,
57*4882a593Smuzhiyun u32 regaddr, u32 bitmask, u32 data)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
60*4882a593Smuzhiyun u32 original_value, bitshift;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
63*4882a593Smuzhiyun "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
64*4882a593Smuzhiyun regaddr, bitmask, data, path);
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun spin_lock(&rtlpriv->locks.rf_lock);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun if (bitmask != RFREG_OFFSET_MASK) {
69*4882a593Smuzhiyun original_value = rtl8723_phy_rf_serial_read(hw, path,
70*4882a593Smuzhiyun regaddr);
71*4882a593Smuzhiyun bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
72*4882a593Smuzhiyun data = ((original_value & (~bitmask)) |
73*4882a593Smuzhiyun (data << bitshift));
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun rtl8723_phy_rf_serial_write(hw, path, regaddr, data);
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun spin_unlock(&rtlpriv->locks.rf_lock);
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RF, DBG_TRACE,
81*4882a593Smuzhiyun "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
82*4882a593Smuzhiyun regaddr, bitmask, data, path);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
rtl8723be_phy_mac_config(struct ieee80211_hw * hw)86*4882a593Smuzhiyun bool rtl8723be_phy_mac_config(struct ieee80211_hw *hw)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
89*4882a593Smuzhiyun bool rtstatus = _rtl8723be_phy_config_mac_with_headerfile(hw);
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun rtl_write_byte(rtlpriv, 0x04CA, 0x0B);
92*4882a593Smuzhiyun return rtstatus;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
rtl8723be_phy_bb_config(struct ieee80211_hw * hw)95*4882a593Smuzhiyun bool rtl8723be_phy_bb_config(struct ieee80211_hw *hw)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun bool rtstatus = true;
98*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
99*4882a593Smuzhiyun u16 regval;
100*4882a593Smuzhiyun u8 b_reg_hwparafile = 1;
101*4882a593Smuzhiyun u32 tmp;
102*4882a593Smuzhiyun u8 crystalcap = rtlpriv->efuse.crystalcap;
103*4882a593Smuzhiyun rtl8723_phy_init_bb_rf_reg_def(hw);
104*4882a593Smuzhiyun regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
105*4882a593Smuzhiyun rtl_write_word(rtlpriv, REG_SYS_FUNC_EN,
106*4882a593Smuzhiyun regval | BIT(13) | BIT(0) | BIT(1));
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
109*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN,
110*4882a593Smuzhiyun FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE |
111*4882a593Smuzhiyun FEN_BB_GLB_RSTN | FEN_BBRSTB);
112*4882a593Smuzhiyun tmp = rtl_read_dword(rtlpriv, 0x4c);
113*4882a593Smuzhiyun rtl_write_dword(rtlpriv, 0x4c, tmp | BIT(23));
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun if (b_reg_hwparafile == 1)
118*4882a593Smuzhiyun rtstatus = _rtl8723be_phy_bb8723b_config_parafile(hw);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun crystalcap = crystalcap & 0x3F;
121*4882a593Smuzhiyun rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
122*4882a593Smuzhiyun (crystalcap | crystalcap << 6));
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun return rtstatus;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
rtl8723be_phy_rf_config(struct ieee80211_hw * hw)127*4882a593Smuzhiyun bool rtl8723be_phy_rf_config(struct ieee80211_hw *hw)
128*4882a593Smuzhiyun {
129*4882a593Smuzhiyun return rtl8723be_phy_rf6052_config(hw);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
_rtl8723be_check_positive(struct ieee80211_hw * hw,const u32 condition1,const u32 condition2)132*4882a593Smuzhiyun static bool _rtl8723be_check_positive(struct ieee80211_hw *hw,
133*4882a593Smuzhiyun const u32 condition1,
134*4882a593Smuzhiyun const u32 condition2)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
137*4882a593Smuzhiyun struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
138*4882a593Smuzhiyun u32 cut_ver = ((rtlhal->version & CHIP_VER_RTL_MASK)
139*4882a593Smuzhiyun >> CHIP_VER_RTL_SHIFT);
140*4882a593Smuzhiyun u32 intf = (rtlhal->interface == INTF_USB ? BIT(1) : BIT(0));
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun u8 board_type = ((rtlhal->board_type & BIT(4)) >> 4) << 0 | /* _GLNA */
143*4882a593Smuzhiyun ((rtlhal->board_type & BIT(3)) >> 3) << 1 | /* _GPA */
144*4882a593Smuzhiyun ((rtlhal->board_type & BIT(7)) >> 7) << 2 | /* _ALNA */
145*4882a593Smuzhiyun ((rtlhal->board_type & BIT(6)) >> 6) << 3 | /* _APA */
146*4882a593Smuzhiyun ((rtlhal->board_type & BIT(2)) >> 2) << 4; /* _BT */
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun u32 cond1 = condition1, cond2 = condition2;
149*4882a593Smuzhiyun u32 driver1 = cut_ver << 24 | /* CUT ver */
150*4882a593Smuzhiyun 0 << 20 | /* interface 2/2 */
151*4882a593Smuzhiyun 0x04 << 16 | /* platform */
152*4882a593Smuzhiyun rtlhal->package_type << 12 |
153*4882a593Smuzhiyun intf << 8 | /* interface 1/2 */
154*4882a593Smuzhiyun board_type;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun u32 driver2 = rtlhal->type_glna << 0 |
157*4882a593Smuzhiyun rtlhal->type_gpa << 8 |
158*4882a593Smuzhiyun rtlhal->type_alna << 16 |
159*4882a593Smuzhiyun rtlhal->type_apa << 24;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
162*4882a593Smuzhiyun "===> [8812A] CheckPositive (cond1, cond2) = (0x%X 0x%X)\n",
163*4882a593Smuzhiyun cond1, cond2);
164*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
165*4882a593Smuzhiyun "===> [8812A] CheckPositive (driver1, driver2) = (0x%X 0x%X)\n",
166*4882a593Smuzhiyun driver1, driver2);
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
169*4882a593Smuzhiyun "(Platform, Interface) = (0x%X, 0x%X)\n", 0x04, intf);
170*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
171*4882a593Smuzhiyun "(Board, Package) = (0x%X, 0x%X)\n",
172*4882a593Smuzhiyun rtlhal->board_type, rtlhal->package_type);
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun /*============== Value Defined Check ===============*/
175*4882a593Smuzhiyun /*QFN Type [15:12] and Cut Version [27:24] need to do value check*/
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if (((cond1 & 0x0000F000) != 0) && ((cond1 & 0x0000F000) !=
178*4882a593Smuzhiyun (driver1 & 0x0000F000)))
179*4882a593Smuzhiyun return false;
180*4882a593Smuzhiyun if (((cond1 & 0x0F000000) != 0) && ((cond1 & 0x0F000000) !=
181*4882a593Smuzhiyun (driver1 & 0x0F000000)))
182*4882a593Smuzhiyun return false;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /*=============== Bit Defined Check ================*/
185*4882a593Smuzhiyun /* We don't care [31:28] */
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun cond1 &= 0x00FF0FFF;
188*4882a593Smuzhiyun driver1 &= 0x00FF0FFF;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun if ((cond1 & driver1) == cond1) {
191*4882a593Smuzhiyun u32 mask = 0;
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun if ((cond1 & 0x0F) == 0) /* BoardType is DONTCARE*/
194*4882a593Smuzhiyun return true;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if ((cond1 & BIT(0)) != 0) /*GLNA*/
197*4882a593Smuzhiyun mask |= 0x000000FF;
198*4882a593Smuzhiyun if ((cond1 & BIT(1)) != 0) /*GPA*/
199*4882a593Smuzhiyun mask |= 0x0000FF00;
200*4882a593Smuzhiyun if ((cond1 & BIT(2)) != 0) /*ALNA*/
201*4882a593Smuzhiyun mask |= 0x00FF0000;
202*4882a593Smuzhiyun if ((cond1 & BIT(3)) != 0) /*APA*/
203*4882a593Smuzhiyun mask |= 0xFF000000;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun /* BoardType of each RF path is matched*/
206*4882a593Smuzhiyun if ((cond2 & mask) == (driver2 & mask))
207*4882a593Smuzhiyun return true;
208*4882a593Smuzhiyun else
209*4882a593Smuzhiyun return false;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun return false;
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
_rtl8723be_config_rf_reg(struct ieee80211_hw * hw,u32 addr,u32 data,enum radio_path rfpath,u32 regaddr)214*4882a593Smuzhiyun static void _rtl8723be_config_rf_reg(struct ieee80211_hw *hw, u32 addr,
215*4882a593Smuzhiyun u32 data, enum radio_path rfpath,
216*4882a593Smuzhiyun u32 regaddr)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun if (addr == 0xfe || addr == 0xffe) {
219*4882a593Smuzhiyun /* In order not to disturb BT music
220*4882a593Smuzhiyun * when wifi init.(1ant NIC only)
221*4882a593Smuzhiyun */
222*4882a593Smuzhiyun mdelay(50);
223*4882a593Smuzhiyun } else {
224*4882a593Smuzhiyun rtl_set_rfreg(hw, rfpath, regaddr, RFREG_OFFSET_MASK, data);
225*4882a593Smuzhiyun udelay(1);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun }
_rtl8723be_config_rf_radio_a(struct ieee80211_hw * hw,u32 addr,u32 data)228*4882a593Smuzhiyun static void _rtl8723be_config_rf_radio_a(struct ieee80211_hw *hw,
229*4882a593Smuzhiyun u32 addr, u32 data)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun u32 content = 0x1000; /*RF Content: radio_a_txt*/
232*4882a593Smuzhiyun u32 maskforphyset = (u32)(content & 0xE000);
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun _rtl8723be_config_rf_reg(hw, addr, data, RF90_PATH_A,
235*4882a593Smuzhiyun addr | maskforphyset);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun
_rtl8723be_phy_init_tx_power_by_rate(struct ieee80211_hw * hw)239*4882a593Smuzhiyun static void _rtl8723be_phy_init_tx_power_by_rate(struct ieee80211_hw *hw)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
242*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun u8 band, path, txnum, section;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun for (band = BAND_ON_2_4G; band <= BAND_ON_5G; ++band)
247*4882a593Smuzhiyun for (path = 0; path < TX_PWR_BY_RATE_NUM_RF; ++path)
248*4882a593Smuzhiyun for (txnum = 0; txnum < TX_PWR_BY_RATE_NUM_RF; ++txnum)
249*4882a593Smuzhiyun for (section = 0;
250*4882a593Smuzhiyun section < TX_PWR_BY_RATE_NUM_SECTION;
251*4882a593Smuzhiyun ++section)
252*4882a593Smuzhiyun rtlphy->tx_power_by_rate_offset
253*4882a593Smuzhiyun [band][path][txnum][section] = 0;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
_rtl8723be_config_bb_reg(struct ieee80211_hw * hw,u32 addr,u32 data)256*4882a593Smuzhiyun static void _rtl8723be_config_bb_reg(struct ieee80211_hw *hw,
257*4882a593Smuzhiyun u32 addr, u32 data)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun if (addr == 0xfe) {
260*4882a593Smuzhiyun mdelay(50);
261*4882a593Smuzhiyun } else if (addr == 0xfd) {
262*4882a593Smuzhiyun mdelay(5);
263*4882a593Smuzhiyun } else if (addr == 0xfc) {
264*4882a593Smuzhiyun mdelay(1);
265*4882a593Smuzhiyun } else if (addr == 0xfb) {
266*4882a593Smuzhiyun udelay(50);
267*4882a593Smuzhiyun } else if (addr == 0xfa) {
268*4882a593Smuzhiyun udelay(5);
269*4882a593Smuzhiyun } else if (addr == 0xf9) {
270*4882a593Smuzhiyun udelay(1);
271*4882a593Smuzhiyun } else {
272*4882a593Smuzhiyun rtl_set_bbreg(hw, addr, MASKDWORD, data);
273*4882a593Smuzhiyun udelay(1);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun
_rtl8723be_phy_set_txpower_by_rate_base(struct ieee80211_hw * hw,u8 band,u8 path,u8 rate_section,u8 txnum,u8 value)277*4882a593Smuzhiyun static void _rtl8723be_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw,
278*4882a593Smuzhiyun u8 band,
279*4882a593Smuzhiyun u8 path, u8 rate_section,
280*4882a593Smuzhiyun u8 txnum, u8 value)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
283*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun if (path > RF90_PATH_D) {
286*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
287*4882a593Smuzhiyun "Invalid Rf Path %d in phy_SetTxPowerByRatBase()\n",
288*4882a593Smuzhiyun path);
289*4882a593Smuzhiyun return;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun if (band == BAND_ON_2_4G) {
293*4882a593Smuzhiyun switch (rate_section) {
294*4882a593Smuzhiyun case CCK:
295*4882a593Smuzhiyun rtlphy->txpwr_by_rate_base_24g[path][txnum][0] = value;
296*4882a593Smuzhiyun break;
297*4882a593Smuzhiyun case OFDM:
298*4882a593Smuzhiyun rtlphy->txpwr_by_rate_base_24g[path][txnum][1] = value;
299*4882a593Smuzhiyun break;
300*4882a593Smuzhiyun case HT_MCS0_MCS7:
301*4882a593Smuzhiyun rtlphy->txpwr_by_rate_base_24g[path][txnum][2] = value;
302*4882a593Smuzhiyun break;
303*4882a593Smuzhiyun case HT_MCS8_MCS15:
304*4882a593Smuzhiyun rtlphy->txpwr_by_rate_base_24g[path][txnum][3] = value;
305*4882a593Smuzhiyun break;
306*4882a593Smuzhiyun default:
307*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
308*4882a593Smuzhiyun "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n",
309*4882a593Smuzhiyun rate_section, path, txnum);
310*4882a593Smuzhiyun break;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun } else {
313*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
314*4882a593Smuzhiyun "Invalid Band %d in PHY_SetTxPowerByRateBase()\n",
315*4882a593Smuzhiyun band);
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
_rtl8723be_phy_get_txpower_by_rate_base(struct ieee80211_hw * hw,u8 band,u8 path,u8 txnum,u8 rate_section)320*4882a593Smuzhiyun static u8 _rtl8723be_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw,
321*4882a593Smuzhiyun u8 band, u8 path, u8 txnum,
322*4882a593Smuzhiyun u8 rate_section)
323*4882a593Smuzhiyun {
324*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
325*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
326*4882a593Smuzhiyun u8 value = 0;
327*4882a593Smuzhiyun if (path > RF90_PATH_D) {
328*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
329*4882a593Smuzhiyun "Invalid Rf Path %d in PHY_GetTxPowerByRateBase()\n",
330*4882a593Smuzhiyun path);
331*4882a593Smuzhiyun return 0;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (band == BAND_ON_2_4G) {
335*4882a593Smuzhiyun switch (rate_section) {
336*4882a593Smuzhiyun case CCK:
337*4882a593Smuzhiyun value = rtlphy->txpwr_by_rate_base_24g[path][txnum][0];
338*4882a593Smuzhiyun break;
339*4882a593Smuzhiyun case OFDM:
340*4882a593Smuzhiyun value = rtlphy->txpwr_by_rate_base_24g[path][txnum][1];
341*4882a593Smuzhiyun break;
342*4882a593Smuzhiyun case HT_MCS0_MCS7:
343*4882a593Smuzhiyun value = rtlphy->txpwr_by_rate_base_24g[path][txnum][2];
344*4882a593Smuzhiyun break;
345*4882a593Smuzhiyun case HT_MCS8_MCS15:
346*4882a593Smuzhiyun value = rtlphy->txpwr_by_rate_base_24g[path][txnum][3];
347*4882a593Smuzhiyun break;
348*4882a593Smuzhiyun default:
349*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
350*4882a593Smuzhiyun "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n",
351*4882a593Smuzhiyun rate_section, path, txnum);
352*4882a593Smuzhiyun break;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun } else {
355*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
356*4882a593Smuzhiyun "Invalid Band %d in PHY_GetTxPowerByRateBase()\n",
357*4882a593Smuzhiyun band);
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun return value;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
_rtl8723be_phy_store_txpower_by_rate_base(struct ieee80211_hw * hw)363*4882a593Smuzhiyun static void _rtl8723be_phy_store_txpower_by_rate_base(struct ieee80211_hw *hw)
364*4882a593Smuzhiyun {
365*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
366*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
367*4882a593Smuzhiyun u16 rawvalue = 0;
368*4882a593Smuzhiyun u8 base = 0, path = 0;
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun for (path = RF90_PATH_A; path <= RF90_PATH_B; ++path) {
371*4882a593Smuzhiyun if (path == RF90_PATH_A) {
372*4882a593Smuzhiyun rawvalue = (u16)(rtlphy->tx_power_by_rate_offset
373*4882a593Smuzhiyun [BAND_ON_2_4G][path][RF_1TX][3] >> 24) & 0xFF;
374*4882a593Smuzhiyun base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
375*4882a593Smuzhiyun _rtl8723be_phy_set_txpower_by_rate_base(hw,
376*4882a593Smuzhiyun BAND_ON_2_4G, path, CCK, RF_1TX, base);
377*4882a593Smuzhiyun } else if (path == RF90_PATH_B) {
378*4882a593Smuzhiyun rawvalue = (u16)(rtlphy->tx_power_by_rate_offset
379*4882a593Smuzhiyun [BAND_ON_2_4G][path][RF_1TX][3] >> 0) & 0xFF;
380*4882a593Smuzhiyun base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
381*4882a593Smuzhiyun _rtl8723be_phy_set_txpower_by_rate_base(hw,
382*4882a593Smuzhiyun BAND_ON_2_4G,
383*4882a593Smuzhiyun path, CCK,
384*4882a593Smuzhiyun RF_1TX, base);
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun rawvalue = (u16)(rtlphy->tx_power_by_rate_offset
387*4882a593Smuzhiyun [BAND_ON_2_4G][path][RF_1TX][1] >> 24) & 0xFF;
388*4882a593Smuzhiyun base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
389*4882a593Smuzhiyun _rtl8723be_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G,
390*4882a593Smuzhiyun path, OFDM, RF_1TX,
391*4882a593Smuzhiyun base);
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun rawvalue = (u16)(rtlphy->tx_power_by_rate_offset
394*4882a593Smuzhiyun [BAND_ON_2_4G][path][RF_1TX][5] >> 24) & 0xFF;
395*4882a593Smuzhiyun base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
396*4882a593Smuzhiyun _rtl8723be_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G,
397*4882a593Smuzhiyun path, HT_MCS0_MCS7,
398*4882a593Smuzhiyun RF_1TX, base);
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun rawvalue = (u16)(rtlphy->tx_power_by_rate_offset
401*4882a593Smuzhiyun [BAND_ON_2_4G][path][RF_2TX][7] >> 24) & 0xFF;
402*4882a593Smuzhiyun base = (rawvalue >> 4) * 10 + (rawvalue & 0xF);
403*4882a593Smuzhiyun _rtl8723be_phy_set_txpower_by_rate_base(hw, BAND_ON_2_4G,
404*4882a593Smuzhiyun path, HT_MCS8_MCS15,
405*4882a593Smuzhiyun RF_2TX, base);
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
_phy_convert_txpower_dbm_to_relative_value(u32 * data,u8 start,u8 end,u8 base_val)409*4882a593Smuzhiyun static void _phy_convert_txpower_dbm_to_relative_value(u32 *data, u8 start,
410*4882a593Smuzhiyun u8 end, u8 base_val)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun s8 i = 0;
413*4882a593Smuzhiyun u8 temp_value = 0;
414*4882a593Smuzhiyun u32 temp_data = 0;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun for (i = 3; i >= 0; --i) {
417*4882a593Smuzhiyun if (i >= start && i <= end) {
418*4882a593Smuzhiyun /* Get the exact value */
419*4882a593Smuzhiyun temp_value = (u8)(*data >> (i * 8)) & 0xF;
420*4882a593Smuzhiyun temp_value += ((u8)((*data >> (i*8 + 4)) & 0xF)) * 10;
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun /* Change the value to a relative value */
423*4882a593Smuzhiyun temp_value = (temp_value > base_val) ?
424*4882a593Smuzhiyun temp_value - base_val :
425*4882a593Smuzhiyun base_val - temp_value;
426*4882a593Smuzhiyun } else {
427*4882a593Smuzhiyun temp_value = (u8)(*data >> (i * 8)) & 0xFF;
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun temp_data <<= 8;
430*4882a593Smuzhiyun temp_data |= temp_value;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun *data = temp_data;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun
_rtl8723be_phy_convert_txpower_dbm_to_relative_value(struct ieee80211_hw * hw)435*4882a593Smuzhiyun static void _rtl8723be_phy_convert_txpower_dbm_to_relative_value(
436*4882a593Smuzhiyun struct ieee80211_hw *hw)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
439*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
440*4882a593Smuzhiyun u8 base = 0, rfpath = RF90_PATH_A;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun base = _rtl8723be_phy_get_txpower_by_rate_base(hw,
443*4882a593Smuzhiyun BAND_ON_2_4G, rfpath, RF_1TX, CCK);
444*4882a593Smuzhiyun _phy_convert_txpower_dbm_to_relative_value(
445*4882a593Smuzhiyun &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][2],
446*4882a593Smuzhiyun 1, 1, base);
447*4882a593Smuzhiyun _phy_convert_txpower_dbm_to_relative_value(
448*4882a593Smuzhiyun &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][3],
449*4882a593Smuzhiyun 1, 3, base);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun base = _rtl8723be_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G, rfpath,
452*4882a593Smuzhiyun RF_1TX, OFDM);
453*4882a593Smuzhiyun _phy_convert_txpower_dbm_to_relative_value(
454*4882a593Smuzhiyun &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][0],
455*4882a593Smuzhiyun 0, 3, base);
456*4882a593Smuzhiyun _phy_convert_txpower_dbm_to_relative_value(
457*4882a593Smuzhiyun &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][1],
458*4882a593Smuzhiyun 0, 3, base);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun base = _rtl8723be_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G,
461*4882a593Smuzhiyun rfpath, RF_1TX, HT_MCS0_MCS7);
462*4882a593Smuzhiyun _phy_convert_txpower_dbm_to_relative_value(
463*4882a593Smuzhiyun &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][4],
464*4882a593Smuzhiyun 0, 3, base);
465*4882a593Smuzhiyun _phy_convert_txpower_dbm_to_relative_value(
466*4882a593Smuzhiyun &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_1TX][5],
467*4882a593Smuzhiyun 0, 3, base);
468*4882a593Smuzhiyun
469*4882a593Smuzhiyun base = _rtl8723be_phy_get_txpower_by_rate_base(hw, BAND_ON_2_4G,
470*4882a593Smuzhiyun rfpath, RF_2TX,
471*4882a593Smuzhiyun HT_MCS8_MCS15);
472*4882a593Smuzhiyun _phy_convert_txpower_dbm_to_relative_value(
473*4882a593Smuzhiyun &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][6],
474*4882a593Smuzhiyun 0, 3, base);
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun _phy_convert_txpower_dbm_to_relative_value(
477*4882a593Smuzhiyun &rtlphy->tx_power_by_rate_offset[BAND_ON_2_4G][rfpath][RF_2TX][7],
478*4882a593Smuzhiyun 0, 3, base);
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
481*4882a593Smuzhiyun "<===%s\n", __func__);
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun
phy_txpower_by_rate_config(struct ieee80211_hw * hw)484*4882a593Smuzhiyun static void phy_txpower_by_rate_config(struct ieee80211_hw *hw)
485*4882a593Smuzhiyun {
486*4882a593Smuzhiyun _rtl8723be_phy_store_txpower_by_rate_base(hw);
487*4882a593Smuzhiyun _rtl8723be_phy_convert_txpower_dbm_to_relative_value(hw);
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
_rtl8723be_phy_bb8723b_config_parafile(struct ieee80211_hw * hw)490*4882a593Smuzhiyun static bool _rtl8723be_phy_bb8723b_config_parafile(struct ieee80211_hw *hw)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
493*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
494*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
495*4882a593Smuzhiyun bool rtstatus;
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun /* switch ant to BT */
498*4882a593Smuzhiyun if (rtlpriv->rtlhal.interface == INTF_USB) {
499*4882a593Smuzhiyun rtl_write_dword(rtlpriv, 0x948, 0x0);
500*4882a593Smuzhiyun } else {
501*4882a593Smuzhiyun if (rtlpriv->btcoexist.btc_info.single_ant_path == 0)
502*4882a593Smuzhiyun rtl_write_dword(rtlpriv, 0x948, 0x280);
503*4882a593Smuzhiyun else
504*4882a593Smuzhiyun rtl_write_dword(rtlpriv, 0x948, 0x0);
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun rtstatus = _rtl8723be_phy_config_bb_with_headerfile(hw,
508*4882a593Smuzhiyun BASEBAND_CONFIG_PHY_REG);
509*4882a593Smuzhiyun if (!rtstatus) {
510*4882a593Smuzhiyun pr_err("Write BB Reg Fail!!\n");
511*4882a593Smuzhiyun return false;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun _rtl8723be_phy_init_tx_power_by_rate(hw);
514*4882a593Smuzhiyun if (!rtlefuse->autoload_failflag) {
515*4882a593Smuzhiyun rtlphy->pwrgroup_cnt = 0;
516*4882a593Smuzhiyun rtstatus = _rtl8723be_phy_config_bb_with_pgheaderfile(hw,
517*4882a593Smuzhiyun BASEBAND_CONFIG_PHY_REG);
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun phy_txpower_by_rate_config(hw);
520*4882a593Smuzhiyun if (!rtstatus) {
521*4882a593Smuzhiyun pr_err("BB_PG Reg Fail!!\n");
522*4882a593Smuzhiyun return false;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun rtstatus = _rtl8723be_phy_config_bb_with_headerfile(hw,
525*4882a593Smuzhiyun BASEBAND_CONFIG_AGC_TAB);
526*4882a593Smuzhiyun if (!rtstatus) {
527*4882a593Smuzhiyun pr_err("AGC Table Fail\n");
528*4882a593Smuzhiyun return false;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun rtlphy->cck_high_power = (bool)(rtl_get_bbreg(hw,
531*4882a593Smuzhiyun RFPGA0_XA_HSSIPARAMETER2,
532*4882a593Smuzhiyun 0x200));
533*4882a593Smuzhiyun return true;
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun
rtl8723be_phy_config_with_headerfile(struct ieee80211_hw * hw,u32 * array_table,u16 arraylen,void (* set_reg)(struct ieee80211_hw * hw,u32 regaddr,u32 data))536*4882a593Smuzhiyun static bool rtl8723be_phy_config_with_headerfile(struct ieee80211_hw *hw,
537*4882a593Smuzhiyun u32 *array_table,
538*4882a593Smuzhiyun u16 arraylen,
539*4882a593Smuzhiyun void (*set_reg)(struct ieee80211_hw *hw, u32 regaddr, u32 data))
540*4882a593Smuzhiyun {
541*4882a593Smuzhiyun #define COND_ELSE 2
542*4882a593Smuzhiyun #define COND_ENDIF 3
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun int i = 0;
545*4882a593Smuzhiyun u8 cond;
546*4882a593Smuzhiyun bool matched = true, skipped = false;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun while ((i + 1) < arraylen) {
549*4882a593Smuzhiyun u32 v1 = array_table[i];
550*4882a593Smuzhiyun u32 v2 = array_table[i + 1];
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun if (v1 & (BIT(31) | BIT(30))) {/*positive & negative condition*/
553*4882a593Smuzhiyun if (v1 & BIT(31)) {/* positive condition*/
554*4882a593Smuzhiyun cond = (u8)((v1 & (BIT(29) | BIT(28))) >> 28);
555*4882a593Smuzhiyun if (cond == COND_ENDIF) { /*end*/
556*4882a593Smuzhiyun matched = true;
557*4882a593Smuzhiyun skipped = false;
558*4882a593Smuzhiyun } else if (cond == COND_ELSE) { /*else*/
559*4882a593Smuzhiyun matched = skipped ? false : true;
560*4882a593Smuzhiyun } else {/*if , else if*/
561*4882a593Smuzhiyun if (skipped) {
562*4882a593Smuzhiyun matched = false;
563*4882a593Smuzhiyun } else {
564*4882a593Smuzhiyun if (_rtl8723be_check_positive(
565*4882a593Smuzhiyun hw, v1, v2)) {
566*4882a593Smuzhiyun matched = true;
567*4882a593Smuzhiyun skipped = true;
568*4882a593Smuzhiyun } else {
569*4882a593Smuzhiyun matched = false;
570*4882a593Smuzhiyun skipped = false;
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun } else if (v1 & BIT(30)) { /*negative condition*/
575*4882a593Smuzhiyun /*do nothing*/
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun } else {
578*4882a593Smuzhiyun if (matched)
579*4882a593Smuzhiyun set_reg(hw, v1, v2);
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun i = i + 2;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun return true;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun
_rtl8723be_phy_config_mac_with_headerfile(struct ieee80211_hw * hw)587*4882a593Smuzhiyun static bool _rtl8723be_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "Read rtl8723beMACPHY_Array\n");
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun return rtl8723be_phy_config_with_headerfile(hw,
594*4882a593Smuzhiyun RTL8723BEMAC_1T_ARRAY, RTL8723BEMAC_1T_ARRAYLEN,
595*4882a593Smuzhiyun rtl_write_byte_with_val32);
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
_rtl8723be_phy_config_bb_with_headerfile(struct ieee80211_hw * hw,u8 configtype)598*4882a593Smuzhiyun static bool _rtl8723be_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
599*4882a593Smuzhiyun u8 configtype)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun if (configtype == BASEBAND_CONFIG_PHY_REG)
603*4882a593Smuzhiyun return rtl8723be_phy_config_with_headerfile(hw,
604*4882a593Smuzhiyun RTL8723BEPHY_REG_1TARRAY,
605*4882a593Smuzhiyun RTL8723BEPHY_REG_1TARRAYLEN,
606*4882a593Smuzhiyun _rtl8723be_config_bb_reg);
607*4882a593Smuzhiyun else if (configtype == BASEBAND_CONFIG_AGC_TAB)
608*4882a593Smuzhiyun return rtl8723be_phy_config_with_headerfile(hw,
609*4882a593Smuzhiyun RTL8723BEAGCTAB_1TARRAY,
610*4882a593Smuzhiyun RTL8723BEAGCTAB_1TARRAYLEN,
611*4882a593Smuzhiyun rtl_set_bbreg_with_dwmask);
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun return false;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
_rtl8723be_get_rate_section_index(u32 regaddr)616*4882a593Smuzhiyun static u8 _rtl8723be_get_rate_section_index(u32 regaddr)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun u8 index = 0;
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun switch (regaddr) {
621*4882a593Smuzhiyun case RTXAGC_A_RATE18_06:
622*4882a593Smuzhiyun index = 0;
623*4882a593Smuzhiyun break;
624*4882a593Smuzhiyun case RTXAGC_A_RATE54_24:
625*4882a593Smuzhiyun index = 1;
626*4882a593Smuzhiyun break;
627*4882a593Smuzhiyun case RTXAGC_A_CCK1_MCS32:
628*4882a593Smuzhiyun index = 2;
629*4882a593Smuzhiyun break;
630*4882a593Smuzhiyun case RTXAGC_B_CCK11_A_CCK2_11:
631*4882a593Smuzhiyun index = 3;
632*4882a593Smuzhiyun break;
633*4882a593Smuzhiyun case RTXAGC_A_MCS03_MCS00:
634*4882a593Smuzhiyun index = 4;
635*4882a593Smuzhiyun break;
636*4882a593Smuzhiyun case RTXAGC_A_MCS07_MCS04:
637*4882a593Smuzhiyun index = 5;
638*4882a593Smuzhiyun break;
639*4882a593Smuzhiyun case RTXAGC_A_MCS11_MCS08:
640*4882a593Smuzhiyun index = 6;
641*4882a593Smuzhiyun break;
642*4882a593Smuzhiyun case RTXAGC_A_MCS15_MCS12:
643*4882a593Smuzhiyun index = 7;
644*4882a593Smuzhiyun break;
645*4882a593Smuzhiyun case RTXAGC_B_RATE18_06:
646*4882a593Smuzhiyun index = 0;
647*4882a593Smuzhiyun break;
648*4882a593Smuzhiyun case RTXAGC_B_RATE54_24:
649*4882a593Smuzhiyun index = 1;
650*4882a593Smuzhiyun break;
651*4882a593Smuzhiyun case RTXAGC_B_CCK1_55_MCS32:
652*4882a593Smuzhiyun index = 2;
653*4882a593Smuzhiyun break;
654*4882a593Smuzhiyun case RTXAGC_B_MCS03_MCS00:
655*4882a593Smuzhiyun index = 4;
656*4882a593Smuzhiyun break;
657*4882a593Smuzhiyun case RTXAGC_B_MCS07_MCS04:
658*4882a593Smuzhiyun index = 5;
659*4882a593Smuzhiyun break;
660*4882a593Smuzhiyun case RTXAGC_B_MCS11_MCS08:
661*4882a593Smuzhiyun index = 6;
662*4882a593Smuzhiyun break;
663*4882a593Smuzhiyun case RTXAGC_B_MCS15_MCS12:
664*4882a593Smuzhiyun index = 7;
665*4882a593Smuzhiyun break;
666*4882a593Smuzhiyun default:
667*4882a593Smuzhiyun regaddr &= 0xFFF;
668*4882a593Smuzhiyun if (regaddr >= 0xC20 && regaddr <= 0xC4C)
669*4882a593Smuzhiyun index = (u8)((regaddr - 0xC20) / 4);
670*4882a593Smuzhiyun else if (regaddr >= 0xE20 && regaddr <= 0xE4C)
671*4882a593Smuzhiyun index = (u8)((regaddr - 0xE20) / 4);
672*4882a593Smuzhiyun break;
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun return index;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
_rtl8723be_store_tx_power_by_rate(struct ieee80211_hw * hw,u32 band,u32 rfpath,u32 txnum,u32 regaddr,u32 bitmask,u32 data)677*4882a593Smuzhiyun static void _rtl8723be_store_tx_power_by_rate(struct ieee80211_hw *hw,
678*4882a593Smuzhiyun u32 band, u32 rfpath,
679*4882a593Smuzhiyun u32 txnum, u32 regaddr,
680*4882a593Smuzhiyun u32 bitmask, u32 data)
681*4882a593Smuzhiyun {
682*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
683*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
684*4882a593Smuzhiyun u8 rate_section = _rtl8723be_get_rate_section_index(regaddr);
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun if (band != BAND_ON_2_4G && band != BAND_ON_5G) {
687*4882a593Smuzhiyun rtl_dbg(rtlpriv, FPHY, PHY_TXPWR, "Invalid Band %d\n", band);
688*4882a593Smuzhiyun return;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun if (rfpath > MAX_RF_PATH - 1) {
691*4882a593Smuzhiyun rtl_dbg(rtlpriv, FPHY, PHY_TXPWR,
692*4882a593Smuzhiyun "Invalid RfPath %d\n", rfpath);
693*4882a593Smuzhiyun return;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun if (txnum > MAX_RF_PATH - 1) {
696*4882a593Smuzhiyun rtl_dbg(rtlpriv, FPHY, PHY_TXPWR, "Invalid TxNum %d\n", txnum);
697*4882a593Smuzhiyun return;
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] =
701*4882a593Smuzhiyun data;
702*4882a593Smuzhiyun
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun
_rtl8723be_phy_config_bb_with_pgheaderfile(struct ieee80211_hw * hw,u8 configtype)705*4882a593Smuzhiyun static bool _rtl8723be_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
706*4882a593Smuzhiyun u8 configtype)
707*4882a593Smuzhiyun {
708*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
709*4882a593Smuzhiyun int i;
710*4882a593Smuzhiyun u32 *phy_regarray_table_pg;
711*4882a593Smuzhiyun u16 phy_regarray_pg_len;
712*4882a593Smuzhiyun u32 v1 = 0, v2 = 0, v3 = 0, v4 = 0, v5 = 0, v6 = 0;
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun phy_regarray_pg_len = RTL8723BEPHY_REG_ARRAY_PGLEN;
715*4882a593Smuzhiyun phy_regarray_table_pg = RTL8723BEPHY_REG_ARRAY_PG;
716*4882a593Smuzhiyun
717*4882a593Smuzhiyun if (configtype == BASEBAND_CONFIG_PHY_REG) {
718*4882a593Smuzhiyun for (i = 0; i < phy_regarray_pg_len; i = i + 6) {
719*4882a593Smuzhiyun v1 = phy_regarray_table_pg[i];
720*4882a593Smuzhiyun v2 = phy_regarray_table_pg[i+1];
721*4882a593Smuzhiyun v3 = phy_regarray_table_pg[i+2];
722*4882a593Smuzhiyun v4 = phy_regarray_table_pg[i+3];
723*4882a593Smuzhiyun v5 = phy_regarray_table_pg[i+4];
724*4882a593Smuzhiyun v6 = phy_regarray_table_pg[i+5];
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun if (v1 < 0xcdcdcdcd) {
727*4882a593Smuzhiyun if (phy_regarray_table_pg[i] == 0xfe ||
728*4882a593Smuzhiyun phy_regarray_table_pg[i] == 0xffe)
729*4882a593Smuzhiyun mdelay(50);
730*4882a593Smuzhiyun else
731*4882a593Smuzhiyun _rtl8723be_store_tx_power_by_rate(hw,
732*4882a593Smuzhiyun v1, v2, v3, v4, v5, v6);
733*4882a593Smuzhiyun continue;
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun }
736*4882a593Smuzhiyun } else {
737*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SEND, DBG_TRACE,
738*4882a593Smuzhiyun "configtype != BaseBand_Config_PHY_REG\n");
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun return true;
741*4882a593Smuzhiyun }
742*4882a593Smuzhiyun
rtl8723be_phy_config_rf_with_headerfile(struct ieee80211_hw * hw,enum radio_path rfpath)743*4882a593Smuzhiyun bool rtl8723be_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
744*4882a593Smuzhiyun enum radio_path rfpath)
745*4882a593Smuzhiyun {
746*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
747*4882a593Smuzhiyun struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
748*4882a593Smuzhiyun bool ret = true;
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Radio No %x\n", rfpath);
751*4882a593Smuzhiyun switch (rfpath) {
752*4882a593Smuzhiyun case RF90_PATH_A:
753*4882a593Smuzhiyun ret = rtl8723be_phy_config_with_headerfile(hw,
754*4882a593Smuzhiyun RTL8723BE_RADIOA_1TARRAY,
755*4882a593Smuzhiyun RTL8723BE_RADIOA_1TARRAYLEN,
756*4882a593Smuzhiyun _rtl8723be_config_rf_radio_a);
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun if (rtlhal->oem_id == RT_CID_819X_HP)
759*4882a593Smuzhiyun _rtl8723be_config_rf_radio_a(hw, 0x52, 0x7E4BD);
760*4882a593Smuzhiyun break;
761*4882a593Smuzhiyun case RF90_PATH_B:
762*4882a593Smuzhiyun case RF90_PATH_C:
763*4882a593Smuzhiyun break;
764*4882a593Smuzhiyun case RF90_PATH_D:
765*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
766*4882a593Smuzhiyun "switch case %#x not processed\n", rfpath);
767*4882a593Smuzhiyun break;
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun return ret;
770*4882a593Smuzhiyun }
771*4882a593Smuzhiyun
rtl8723be_phy_get_hw_reg_originalvalue(struct ieee80211_hw * hw)772*4882a593Smuzhiyun void rtl8723be_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
773*4882a593Smuzhiyun {
774*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
775*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun rtlphy->default_initialgain[0] =
778*4882a593Smuzhiyun (u8)rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
779*4882a593Smuzhiyun rtlphy->default_initialgain[1] =
780*4882a593Smuzhiyun (u8)rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
781*4882a593Smuzhiyun rtlphy->default_initialgain[2] =
782*4882a593Smuzhiyun (u8)rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0);
783*4882a593Smuzhiyun rtlphy->default_initialgain[3] =
784*4882a593Smuzhiyun (u8)rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0);
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
787*4882a593Smuzhiyun "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n",
788*4882a593Smuzhiyun rtlphy->default_initialgain[0],
789*4882a593Smuzhiyun rtlphy->default_initialgain[1],
790*4882a593Smuzhiyun rtlphy->default_initialgain[2],
791*4882a593Smuzhiyun rtlphy->default_initialgain[3]);
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun rtlphy->framesync = (u8)rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3,
794*4882a593Smuzhiyun MASKBYTE0);
795*4882a593Smuzhiyun rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2,
796*4882a593Smuzhiyun MASKDWORD);
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
799*4882a593Smuzhiyun "Default framesync (0x%x) = 0x%x\n",
800*4882a593Smuzhiyun ROFDM0_RXDETECTOR3, rtlphy->framesync);
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun
_rtl8723be_phy_get_ratesection_intxpower_byrate(enum radio_path path,u8 rate)803*4882a593Smuzhiyun static u8 _rtl8723be_phy_get_ratesection_intxpower_byrate(enum radio_path path,
804*4882a593Smuzhiyun u8 rate)
805*4882a593Smuzhiyun {
806*4882a593Smuzhiyun u8 rate_section = 0;
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun switch (rate) {
809*4882a593Smuzhiyun case DESC92C_RATE1M:
810*4882a593Smuzhiyun rate_section = 2;
811*4882a593Smuzhiyun break;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun case DESC92C_RATE2M:
814*4882a593Smuzhiyun case DESC92C_RATE5_5M:
815*4882a593Smuzhiyun if (path == RF90_PATH_A)
816*4882a593Smuzhiyun rate_section = 3;
817*4882a593Smuzhiyun else if (path == RF90_PATH_B)
818*4882a593Smuzhiyun rate_section = 2;
819*4882a593Smuzhiyun break;
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun case DESC92C_RATE11M:
822*4882a593Smuzhiyun rate_section = 3;
823*4882a593Smuzhiyun break;
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun case DESC92C_RATE6M:
826*4882a593Smuzhiyun case DESC92C_RATE9M:
827*4882a593Smuzhiyun case DESC92C_RATE12M:
828*4882a593Smuzhiyun case DESC92C_RATE18M:
829*4882a593Smuzhiyun rate_section = 0;
830*4882a593Smuzhiyun break;
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun case DESC92C_RATE24M:
833*4882a593Smuzhiyun case DESC92C_RATE36M:
834*4882a593Smuzhiyun case DESC92C_RATE48M:
835*4882a593Smuzhiyun case DESC92C_RATE54M:
836*4882a593Smuzhiyun rate_section = 1;
837*4882a593Smuzhiyun break;
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun case DESC92C_RATEMCS0:
840*4882a593Smuzhiyun case DESC92C_RATEMCS1:
841*4882a593Smuzhiyun case DESC92C_RATEMCS2:
842*4882a593Smuzhiyun case DESC92C_RATEMCS3:
843*4882a593Smuzhiyun rate_section = 4;
844*4882a593Smuzhiyun break;
845*4882a593Smuzhiyun
846*4882a593Smuzhiyun case DESC92C_RATEMCS4:
847*4882a593Smuzhiyun case DESC92C_RATEMCS5:
848*4882a593Smuzhiyun case DESC92C_RATEMCS6:
849*4882a593Smuzhiyun case DESC92C_RATEMCS7:
850*4882a593Smuzhiyun rate_section = 5;
851*4882a593Smuzhiyun break;
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun case DESC92C_RATEMCS8:
854*4882a593Smuzhiyun case DESC92C_RATEMCS9:
855*4882a593Smuzhiyun case DESC92C_RATEMCS10:
856*4882a593Smuzhiyun case DESC92C_RATEMCS11:
857*4882a593Smuzhiyun rate_section = 6;
858*4882a593Smuzhiyun break;
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun case DESC92C_RATEMCS12:
861*4882a593Smuzhiyun case DESC92C_RATEMCS13:
862*4882a593Smuzhiyun case DESC92C_RATEMCS14:
863*4882a593Smuzhiyun case DESC92C_RATEMCS15:
864*4882a593Smuzhiyun rate_section = 7;
865*4882a593Smuzhiyun break;
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun default:
868*4882a593Smuzhiyun WARN_ONCE(true, "rtl8723be: Rate_Section is Illegal\n");
869*4882a593Smuzhiyun break;
870*4882a593Smuzhiyun }
871*4882a593Smuzhiyun
872*4882a593Smuzhiyun return rate_section;
873*4882a593Smuzhiyun }
874*4882a593Smuzhiyun
_rtl8723be_get_txpower_by_rate(struct ieee80211_hw * hw,enum band_type band,enum radio_path rfpath,u8 rate)875*4882a593Smuzhiyun static u8 _rtl8723be_get_txpower_by_rate(struct ieee80211_hw *hw,
876*4882a593Smuzhiyun enum band_type band,
877*4882a593Smuzhiyun enum radio_path rfpath, u8 rate)
878*4882a593Smuzhiyun {
879*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
880*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
881*4882a593Smuzhiyun u8 shift = 0, rate_section, tx_num;
882*4882a593Smuzhiyun s8 tx_pwr_diff = 0;
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun rate_section = _rtl8723be_phy_get_ratesection_intxpower_byrate(rfpath,
885*4882a593Smuzhiyun rate);
886*4882a593Smuzhiyun tx_num = RF_TX_NUM_NONIMPLEMENT;
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun if (tx_num == RF_TX_NUM_NONIMPLEMENT) {
889*4882a593Smuzhiyun if (rate >= DESC92C_RATEMCS8 && rate <= DESC92C_RATEMCS15)
890*4882a593Smuzhiyun tx_num = RF_2TX;
891*4882a593Smuzhiyun else
892*4882a593Smuzhiyun tx_num = RF_1TX;
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun
895*4882a593Smuzhiyun switch (rate) {
896*4882a593Smuzhiyun case DESC92C_RATE6M:
897*4882a593Smuzhiyun case DESC92C_RATE24M:
898*4882a593Smuzhiyun case DESC92C_RATEMCS0:
899*4882a593Smuzhiyun case DESC92C_RATEMCS4:
900*4882a593Smuzhiyun case DESC92C_RATEMCS8:
901*4882a593Smuzhiyun case DESC92C_RATEMCS12:
902*4882a593Smuzhiyun shift = 0;
903*4882a593Smuzhiyun break;
904*4882a593Smuzhiyun case DESC92C_RATE1M:
905*4882a593Smuzhiyun case DESC92C_RATE2M:
906*4882a593Smuzhiyun case DESC92C_RATE9M:
907*4882a593Smuzhiyun case DESC92C_RATE36M:
908*4882a593Smuzhiyun case DESC92C_RATEMCS1:
909*4882a593Smuzhiyun case DESC92C_RATEMCS5:
910*4882a593Smuzhiyun case DESC92C_RATEMCS9:
911*4882a593Smuzhiyun case DESC92C_RATEMCS13:
912*4882a593Smuzhiyun shift = 8;
913*4882a593Smuzhiyun break;
914*4882a593Smuzhiyun case DESC92C_RATE5_5M:
915*4882a593Smuzhiyun case DESC92C_RATE12M:
916*4882a593Smuzhiyun case DESC92C_RATE48M:
917*4882a593Smuzhiyun case DESC92C_RATEMCS2:
918*4882a593Smuzhiyun case DESC92C_RATEMCS6:
919*4882a593Smuzhiyun case DESC92C_RATEMCS10:
920*4882a593Smuzhiyun case DESC92C_RATEMCS14:
921*4882a593Smuzhiyun shift = 16;
922*4882a593Smuzhiyun break;
923*4882a593Smuzhiyun case DESC92C_RATE11M:
924*4882a593Smuzhiyun case DESC92C_RATE18M:
925*4882a593Smuzhiyun case DESC92C_RATE54M:
926*4882a593Smuzhiyun case DESC92C_RATEMCS3:
927*4882a593Smuzhiyun case DESC92C_RATEMCS7:
928*4882a593Smuzhiyun case DESC92C_RATEMCS11:
929*4882a593Smuzhiyun case DESC92C_RATEMCS15:
930*4882a593Smuzhiyun shift = 24;
931*4882a593Smuzhiyun break;
932*4882a593Smuzhiyun default:
933*4882a593Smuzhiyun WARN_ONCE(true, "rtl8723be: Rate_Section is Illegal\n");
934*4882a593Smuzhiyun break;
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun tx_pwr_diff = (u8)(rtlphy->tx_power_by_rate_offset[band][rfpath][tx_num]
937*4882a593Smuzhiyun [rate_section] >> shift) & 0xff;
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun return tx_pwr_diff;
940*4882a593Smuzhiyun }
941*4882a593Smuzhiyun
_rtl8723be_get_txpower_index(struct ieee80211_hw * hw,u8 path,u8 rate,u8 bandwidth,u8 channel)942*4882a593Smuzhiyun static u8 _rtl8723be_get_txpower_index(struct ieee80211_hw *hw, u8 path,
943*4882a593Smuzhiyun u8 rate, u8 bandwidth, u8 channel)
944*4882a593Smuzhiyun {
945*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
946*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
947*4882a593Smuzhiyun u8 index = (channel - 1);
948*4882a593Smuzhiyun u8 txpower = 0;
949*4882a593Smuzhiyun u8 power_diff_byrate = 0;
950*4882a593Smuzhiyun
951*4882a593Smuzhiyun if (channel > 14 || channel < 1) {
952*4882a593Smuzhiyun index = 0;
953*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
954*4882a593Smuzhiyun "Illegal channel!\n");
955*4882a593Smuzhiyun }
956*4882a593Smuzhiyun if (RX_HAL_IS_CCK_RATE(rate))
957*4882a593Smuzhiyun txpower = rtlefuse->txpwrlevel_cck[path][index];
958*4882a593Smuzhiyun else if (DESC92C_RATE6M <= rate)
959*4882a593Smuzhiyun txpower = rtlefuse->txpwrlevel_ht40_1s[path][index];
960*4882a593Smuzhiyun else
961*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
962*4882a593Smuzhiyun "invalid rate\n");
963*4882a593Smuzhiyun
964*4882a593Smuzhiyun if (DESC92C_RATE6M <= rate && rate <= DESC92C_RATE54M &&
965*4882a593Smuzhiyun !RX_HAL_IS_CCK_RATE(rate))
966*4882a593Smuzhiyun txpower += rtlefuse->txpwr_legacyhtdiff[0][TX_1S];
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun if (bandwidth == HT_CHANNEL_WIDTH_20) {
969*4882a593Smuzhiyun if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15)
970*4882a593Smuzhiyun txpower += rtlefuse->txpwr_ht20diff[0][TX_1S];
971*4882a593Smuzhiyun if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15)
972*4882a593Smuzhiyun txpower += rtlefuse->txpwr_ht20diff[0][TX_2S];
973*4882a593Smuzhiyun } else if (bandwidth == HT_CHANNEL_WIDTH_20_40) {
974*4882a593Smuzhiyun if (DESC92C_RATEMCS0 <= rate && rate <= DESC92C_RATEMCS15)
975*4882a593Smuzhiyun txpower += rtlefuse->txpwr_ht40diff[0][TX_1S];
976*4882a593Smuzhiyun if (DESC92C_RATEMCS8 <= rate && rate <= DESC92C_RATEMCS15)
977*4882a593Smuzhiyun txpower += rtlefuse->txpwr_ht40diff[0][TX_2S];
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun
980*4882a593Smuzhiyun if (rtlefuse->eeprom_regulatory != 2)
981*4882a593Smuzhiyun power_diff_byrate = _rtl8723be_get_txpower_by_rate(hw,
982*4882a593Smuzhiyun BAND_ON_2_4G,
983*4882a593Smuzhiyun path, rate);
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun txpower += power_diff_byrate;
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun if (txpower > MAX_POWER_INDEX)
988*4882a593Smuzhiyun txpower = MAX_POWER_INDEX;
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun return txpower;
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun
_rtl8723be_phy_set_txpower_index(struct ieee80211_hw * hw,u8 power_index,u8 path,u8 rate)993*4882a593Smuzhiyun static void _rtl8723be_phy_set_txpower_index(struct ieee80211_hw *hw,
994*4882a593Smuzhiyun u8 power_index, u8 path, u8 rate)
995*4882a593Smuzhiyun {
996*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
997*4882a593Smuzhiyun if (path == RF90_PATH_A) {
998*4882a593Smuzhiyun switch (rate) {
999*4882a593Smuzhiyun case DESC92C_RATE1M:
1000*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_CCK1_MCS32,
1001*4882a593Smuzhiyun MASKBYTE1, power_index);
1002*4882a593Smuzhiyun break;
1003*4882a593Smuzhiyun case DESC92C_RATE2M:
1004*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11,
1005*4882a593Smuzhiyun MASKBYTE1, power_index);
1006*4882a593Smuzhiyun break;
1007*4882a593Smuzhiyun case DESC92C_RATE5_5M:
1008*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11,
1009*4882a593Smuzhiyun MASKBYTE2, power_index);
1010*4882a593Smuzhiyun break;
1011*4882a593Smuzhiyun case DESC92C_RATE11M:
1012*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_B_CCK11_A_CCK2_11,
1013*4882a593Smuzhiyun MASKBYTE3, power_index);
1014*4882a593Smuzhiyun break;
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun case DESC92C_RATE6M:
1017*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06,
1018*4882a593Smuzhiyun MASKBYTE0, power_index);
1019*4882a593Smuzhiyun break;
1020*4882a593Smuzhiyun case DESC92C_RATE9M:
1021*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06,
1022*4882a593Smuzhiyun MASKBYTE1, power_index);
1023*4882a593Smuzhiyun break;
1024*4882a593Smuzhiyun case DESC92C_RATE12M:
1025*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06,
1026*4882a593Smuzhiyun MASKBYTE2, power_index);
1027*4882a593Smuzhiyun break;
1028*4882a593Smuzhiyun case DESC92C_RATE18M:
1029*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE18_06,
1030*4882a593Smuzhiyun MASKBYTE3, power_index);
1031*4882a593Smuzhiyun break;
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun case DESC92C_RATE24M:
1034*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24,
1035*4882a593Smuzhiyun MASKBYTE0, power_index);
1036*4882a593Smuzhiyun break;
1037*4882a593Smuzhiyun case DESC92C_RATE36M:
1038*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24,
1039*4882a593Smuzhiyun MASKBYTE1, power_index);
1040*4882a593Smuzhiyun break;
1041*4882a593Smuzhiyun case DESC92C_RATE48M:
1042*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24,
1043*4882a593Smuzhiyun MASKBYTE2, power_index);
1044*4882a593Smuzhiyun break;
1045*4882a593Smuzhiyun case DESC92C_RATE54M:
1046*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_RATE54_24,
1047*4882a593Smuzhiyun MASKBYTE3, power_index);
1048*4882a593Smuzhiyun break;
1049*4882a593Smuzhiyun
1050*4882a593Smuzhiyun case DESC92C_RATEMCS0:
1051*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00,
1052*4882a593Smuzhiyun MASKBYTE0, power_index);
1053*4882a593Smuzhiyun break;
1054*4882a593Smuzhiyun case DESC92C_RATEMCS1:
1055*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00,
1056*4882a593Smuzhiyun MASKBYTE1, power_index);
1057*4882a593Smuzhiyun break;
1058*4882a593Smuzhiyun case DESC92C_RATEMCS2:
1059*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00,
1060*4882a593Smuzhiyun MASKBYTE2, power_index);
1061*4882a593Smuzhiyun break;
1062*4882a593Smuzhiyun case DESC92C_RATEMCS3:
1063*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS03_MCS00,
1064*4882a593Smuzhiyun MASKBYTE3, power_index);
1065*4882a593Smuzhiyun break;
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun case DESC92C_RATEMCS4:
1068*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04,
1069*4882a593Smuzhiyun MASKBYTE0, power_index);
1070*4882a593Smuzhiyun break;
1071*4882a593Smuzhiyun case DESC92C_RATEMCS5:
1072*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04,
1073*4882a593Smuzhiyun MASKBYTE1, power_index);
1074*4882a593Smuzhiyun break;
1075*4882a593Smuzhiyun case DESC92C_RATEMCS6:
1076*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04,
1077*4882a593Smuzhiyun MASKBYTE2, power_index);
1078*4882a593Smuzhiyun break;
1079*4882a593Smuzhiyun case DESC92C_RATEMCS7:
1080*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS07_MCS04,
1081*4882a593Smuzhiyun MASKBYTE3, power_index);
1082*4882a593Smuzhiyun break;
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun case DESC92C_RATEMCS8:
1085*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08,
1086*4882a593Smuzhiyun MASKBYTE0, power_index);
1087*4882a593Smuzhiyun break;
1088*4882a593Smuzhiyun case DESC92C_RATEMCS9:
1089*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08,
1090*4882a593Smuzhiyun MASKBYTE1, power_index);
1091*4882a593Smuzhiyun break;
1092*4882a593Smuzhiyun case DESC92C_RATEMCS10:
1093*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08,
1094*4882a593Smuzhiyun MASKBYTE2, power_index);
1095*4882a593Smuzhiyun break;
1096*4882a593Smuzhiyun case DESC92C_RATEMCS11:
1097*4882a593Smuzhiyun rtl8723_phy_set_bb_reg(hw, RTXAGC_A_MCS11_MCS08,
1098*4882a593Smuzhiyun MASKBYTE3, power_index);
1099*4882a593Smuzhiyun break;
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun default:
1102*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid Rate!!\n");
1103*4882a593Smuzhiyun break;
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun } else {
1106*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "Invalid RFPath!!\n");
1107*4882a593Smuzhiyun }
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun
rtl8723be_phy_set_txpower_level(struct ieee80211_hw * hw,u8 channel)1110*4882a593Smuzhiyun void rtl8723be_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
1111*4882a593Smuzhiyun {
1112*4882a593Smuzhiyun struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1113*4882a593Smuzhiyun u8 cck_rates[] = {DESC92C_RATE1M, DESC92C_RATE2M,
1114*4882a593Smuzhiyun DESC92C_RATE5_5M, DESC92C_RATE11M};
1115*4882a593Smuzhiyun u8 ofdm_rates[] = {DESC92C_RATE6M, DESC92C_RATE9M,
1116*4882a593Smuzhiyun DESC92C_RATE12M, DESC92C_RATE18M,
1117*4882a593Smuzhiyun DESC92C_RATE24M, DESC92C_RATE36M,
1118*4882a593Smuzhiyun DESC92C_RATE48M, DESC92C_RATE54M};
1119*4882a593Smuzhiyun u8 ht_rates_1t[] = {DESC92C_RATEMCS0, DESC92C_RATEMCS1,
1120*4882a593Smuzhiyun DESC92C_RATEMCS2, DESC92C_RATEMCS3,
1121*4882a593Smuzhiyun DESC92C_RATEMCS4, DESC92C_RATEMCS5,
1122*4882a593Smuzhiyun DESC92C_RATEMCS6, DESC92C_RATEMCS7};
1123*4882a593Smuzhiyun u8 i;
1124*4882a593Smuzhiyun u8 power_index;
1125*4882a593Smuzhiyun
1126*4882a593Smuzhiyun if (!rtlefuse->txpwr_fromeprom)
1127*4882a593Smuzhiyun return;
1128*4882a593Smuzhiyun
1129*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(cck_rates); i++) {
1130*4882a593Smuzhiyun power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A,
1131*4882a593Smuzhiyun cck_rates[i],
1132*4882a593Smuzhiyun rtl_priv(hw)->phy.current_chan_bw,
1133*4882a593Smuzhiyun channel);
1134*4882a593Smuzhiyun _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A,
1135*4882a593Smuzhiyun cck_rates[i]);
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(ofdm_rates); i++) {
1138*4882a593Smuzhiyun power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A,
1139*4882a593Smuzhiyun ofdm_rates[i],
1140*4882a593Smuzhiyun rtl_priv(hw)->phy.current_chan_bw,
1141*4882a593Smuzhiyun channel);
1142*4882a593Smuzhiyun _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A,
1143*4882a593Smuzhiyun ofdm_rates[i]);
1144*4882a593Smuzhiyun }
1145*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(ht_rates_1t); i++) {
1146*4882a593Smuzhiyun power_index = _rtl8723be_get_txpower_index(hw, RF90_PATH_A,
1147*4882a593Smuzhiyun ht_rates_1t[i],
1148*4882a593Smuzhiyun rtl_priv(hw)->phy.current_chan_bw,
1149*4882a593Smuzhiyun channel);
1150*4882a593Smuzhiyun _rtl8723be_phy_set_txpower_index(hw, power_index, RF90_PATH_A,
1151*4882a593Smuzhiyun ht_rates_1t[i]);
1152*4882a593Smuzhiyun }
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun
rtl8723be_phy_scan_operation_backup(struct ieee80211_hw * hw,u8 operation)1155*4882a593Smuzhiyun void rtl8723be_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
1156*4882a593Smuzhiyun {
1157*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1158*4882a593Smuzhiyun struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1159*4882a593Smuzhiyun enum io_type iotype;
1160*4882a593Smuzhiyun
1161*4882a593Smuzhiyun if (!is_hal_stop(rtlhal)) {
1162*4882a593Smuzhiyun switch (operation) {
1163*4882a593Smuzhiyun case SCAN_OPT_BACKUP_BAND0:
1164*4882a593Smuzhiyun iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN;
1165*4882a593Smuzhiyun rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
1166*4882a593Smuzhiyun (u8 *)&iotype);
1167*4882a593Smuzhiyun
1168*4882a593Smuzhiyun break;
1169*4882a593Smuzhiyun case SCAN_OPT_RESTORE:
1170*4882a593Smuzhiyun iotype = IO_CMD_RESUME_DM_BY_SCAN;
1171*4882a593Smuzhiyun rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_IO_CMD,
1172*4882a593Smuzhiyun (u8 *)&iotype);
1173*4882a593Smuzhiyun break;
1174*4882a593Smuzhiyun default:
1175*4882a593Smuzhiyun pr_err("Unknown Scan Backup operation.\n");
1176*4882a593Smuzhiyun break;
1177*4882a593Smuzhiyun }
1178*4882a593Smuzhiyun }
1179*4882a593Smuzhiyun }
1180*4882a593Smuzhiyun
rtl8723be_phy_set_bw_mode_callback(struct ieee80211_hw * hw)1181*4882a593Smuzhiyun void rtl8723be_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
1182*4882a593Smuzhiyun {
1183*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1184*4882a593Smuzhiyun struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1185*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
1186*4882a593Smuzhiyun struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1187*4882a593Smuzhiyun u8 reg_bw_opmode;
1188*4882a593Smuzhiyun u8 reg_prsr_rsc;
1189*4882a593Smuzhiyun
1190*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SCAN, DBG_TRACE,
1191*4882a593Smuzhiyun "Switch to %s bandwidth\n",
1192*4882a593Smuzhiyun rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
1193*4882a593Smuzhiyun "20MHz" : "40MHz");
1194*4882a593Smuzhiyun
1195*4882a593Smuzhiyun if (is_hal_stop(rtlhal)) {
1196*4882a593Smuzhiyun rtlphy->set_bwmode_inprogress = false;
1197*4882a593Smuzhiyun return;
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun
1200*4882a593Smuzhiyun reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
1201*4882a593Smuzhiyun reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
1202*4882a593Smuzhiyun
1203*4882a593Smuzhiyun switch (rtlphy->current_chan_bw) {
1204*4882a593Smuzhiyun case HT_CHANNEL_WIDTH_20:
1205*4882a593Smuzhiyun reg_bw_opmode |= BW_OPMODE_20MHZ;
1206*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
1207*4882a593Smuzhiyun break;
1208*4882a593Smuzhiyun case HT_CHANNEL_WIDTH_20_40:
1209*4882a593Smuzhiyun reg_bw_opmode &= ~BW_OPMODE_20MHZ;
1210*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
1211*4882a593Smuzhiyun reg_prsr_rsc = (reg_prsr_rsc & 0x90) |
1212*4882a593Smuzhiyun (mac->cur_40_prime_sc << 5);
1213*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
1214*4882a593Smuzhiyun break;
1215*4882a593Smuzhiyun default:
1216*4882a593Smuzhiyun pr_err("unknown bandwidth: %#X\n",
1217*4882a593Smuzhiyun rtlphy->current_chan_bw);
1218*4882a593Smuzhiyun break;
1219*4882a593Smuzhiyun }
1220*4882a593Smuzhiyun
1221*4882a593Smuzhiyun switch (rtlphy->current_chan_bw) {
1222*4882a593Smuzhiyun case HT_CHANNEL_WIDTH_20:
1223*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
1224*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
1225*4882a593Smuzhiyun /* rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);*/
1226*4882a593Smuzhiyun break;
1227*4882a593Smuzhiyun case HT_CHANNEL_WIDTH_20_40:
1228*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
1229*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
1232*4882a593Smuzhiyun (mac->cur_40_prime_sc >> 1));
1233*4882a593Smuzhiyun rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
1234*4882a593Smuzhiyun /*rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);*/
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
1237*4882a593Smuzhiyun (mac->cur_40_prime_sc ==
1238*4882a593Smuzhiyun HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
1239*4882a593Smuzhiyun break;
1240*4882a593Smuzhiyun default:
1241*4882a593Smuzhiyun pr_err("unknown bandwidth: %#X\n",
1242*4882a593Smuzhiyun rtlphy->current_chan_bw);
1243*4882a593Smuzhiyun break;
1244*4882a593Smuzhiyun }
1245*4882a593Smuzhiyun rtl8723be_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
1246*4882a593Smuzhiyun rtlphy->set_bwmode_inprogress = false;
1247*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD, "\n");
1248*4882a593Smuzhiyun }
1249*4882a593Smuzhiyun
rtl8723be_phy_set_bw_mode(struct ieee80211_hw * hw,enum nl80211_channel_type ch_type)1250*4882a593Smuzhiyun void rtl8723be_phy_set_bw_mode(struct ieee80211_hw *hw,
1251*4882a593Smuzhiyun enum nl80211_channel_type ch_type)
1252*4882a593Smuzhiyun {
1253*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1254*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
1255*4882a593Smuzhiyun struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1256*4882a593Smuzhiyun u8 tmp_bw = rtlphy->current_chan_bw;
1257*4882a593Smuzhiyun
1258*4882a593Smuzhiyun if (rtlphy->set_bwmode_inprogress)
1259*4882a593Smuzhiyun return;
1260*4882a593Smuzhiyun rtlphy->set_bwmode_inprogress = true;
1261*4882a593Smuzhiyun if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
1262*4882a593Smuzhiyun rtl8723be_phy_set_bw_mode_callback(hw);
1263*4882a593Smuzhiyun } else {
1264*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
1265*4882a593Smuzhiyun "false driver sleep or unload\n");
1266*4882a593Smuzhiyun rtlphy->set_bwmode_inprogress = false;
1267*4882a593Smuzhiyun rtlphy->current_chan_bw = tmp_bw;
1268*4882a593Smuzhiyun }
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun
rtl8723be_phy_sw_chnl_callback(struct ieee80211_hw * hw)1271*4882a593Smuzhiyun void rtl8723be_phy_sw_chnl_callback(struct ieee80211_hw *hw)
1272*4882a593Smuzhiyun {
1273*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1274*4882a593Smuzhiyun struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1275*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
1276*4882a593Smuzhiyun u32 delay = 0;
1277*4882a593Smuzhiyun
1278*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SCAN, DBG_TRACE,
1279*4882a593Smuzhiyun "switch to channel%d\n", rtlphy->current_channel);
1280*4882a593Smuzhiyun if (is_hal_stop(rtlhal))
1281*4882a593Smuzhiyun return;
1282*4882a593Smuzhiyun do {
1283*4882a593Smuzhiyun if (!rtlphy->sw_chnl_inprogress)
1284*4882a593Smuzhiyun break;
1285*4882a593Smuzhiyun if (!_rtl8723be_phy_sw_chnl_step_by_step(hw,
1286*4882a593Smuzhiyun rtlphy->current_channel,
1287*4882a593Smuzhiyun &rtlphy->sw_chnl_stage,
1288*4882a593Smuzhiyun &rtlphy->sw_chnl_step,
1289*4882a593Smuzhiyun &delay)) {
1290*4882a593Smuzhiyun if (delay > 0)
1291*4882a593Smuzhiyun mdelay(delay);
1292*4882a593Smuzhiyun else
1293*4882a593Smuzhiyun continue;
1294*4882a593Smuzhiyun } else {
1295*4882a593Smuzhiyun rtlphy->sw_chnl_inprogress = false;
1296*4882a593Smuzhiyun }
1297*4882a593Smuzhiyun break;
1298*4882a593Smuzhiyun } while (true);
1299*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_SCAN, DBG_TRACE, "\n");
1300*4882a593Smuzhiyun }
1301*4882a593Smuzhiyun
rtl8723be_phy_sw_chnl(struct ieee80211_hw * hw)1302*4882a593Smuzhiyun u8 rtl8723be_phy_sw_chnl(struct ieee80211_hw *hw)
1303*4882a593Smuzhiyun {
1304*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1305*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
1306*4882a593Smuzhiyun struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1307*4882a593Smuzhiyun
1308*4882a593Smuzhiyun if (rtlphy->sw_chnl_inprogress)
1309*4882a593Smuzhiyun return 0;
1310*4882a593Smuzhiyun if (rtlphy->set_bwmode_inprogress)
1311*4882a593Smuzhiyun return 0;
1312*4882a593Smuzhiyun WARN_ONCE((rtlphy->current_channel > 14),
1313*4882a593Smuzhiyun "rtl8723be: WIRELESS_MODE_G but channel>14");
1314*4882a593Smuzhiyun rtlphy->sw_chnl_inprogress = true;
1315*4882a593Smuzhiyun rtlphy->sw_chnl_stage = 0;
1316*4882a593Smuzhiyun rtlphy->sw_chnl_step = 0;
1317*4882a593Smuzhiyun if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
1318*4882a593Smuzhiyun rtl8723be_phy_sw_chnl_callback(hw);
1319*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_CHAN, DBG_LOUD,
1320*4882a593Smuzhiyun "sw_chnl_inprogress false schedule workitem current channel %d\n",
1321*4882a593Smuzhiyun rtlphy->current_channel);
1322*4882a593Smuzhiyun rtlphy->sw_chnl_inprogress = false;
1323*4882a593Smuzhiyun } else {
1324*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_CHAN, DBG_LOUD,
1325*4882a593Smuzhiyun "sw_chnl_inprogress false driver sleep or unload\n");
1326*4882a593Smuzhiyun rtlphy->sw_chnl_inprogress = false;
1327*4882a593Smuzhiyun }
1328*4882a593Smuzhiyun return 1;
1329*4882a593Smuzhiyun }
1330*4882a593Smuzhiyun
_rtl8723be_phy_sw_chnl_step_by_step(struct ieee80211_hw * hw,u8 channel,u8 * stage,u8 * step,u32 * delay)1331*4882a593Smuzhiyun static bool _rtl8723be_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
1332*4882a593Smuzhiyun u8 channel, u8 *stage,
1333*4882a593Smuzhiyun u8 *step, u32 *delay)
1334*4882a593Smuzhiyun {
1335*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
1336*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
1337*4882a593Smuzhiyun struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
1338*4882a593Smuzhiyun u32 precommoncmdcnt;
1339*4882a593Smuzhiyun struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
1340*4882a593Smuzhiyun u32 postcommoncmdcnt;
1341*4882a593Smuzhiyun struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
1342*4882a593Smuzhiyun u32 rfdependcmdcnt;
1343*4882a593Smuzhiyun struct swchnlcmd *currentcmd = NULL;
1344*4882a593Smuzhiyun u8 rfpath;
1345*4882a593Smuzhiyun u8 num_total_rfpath = rtlphy->num_total_rfpath;
1346*4882a593Smuzhiyun
1347*4882a593Smuzhiyun precommoncmdcnt = 0;
1348*4882a593Smuzhiyun rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
1349*4882a593Smuzhiyun MAX_PRECMD_CNT,
1350*4882a593Smuzhiyun CMDID_SET_TXPOWEROWER_LEVEL,
1351*4882a593Smuzhiyun 0, 0, 0);
1352*4882a593Smuzhiyun rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
1353*4882a593Smuzhiyun MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun postcommoncmdcnt = 0;
1356*4882a593Smuzhiyun
1357*4882a593Smuzhiyun rtl8723_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
1358*4882a593Smuzhiyun MAX_POSTCMD_CNT, CMDID_END,
1359*4882a593Smuzhiyun 0, 0, 0);
1360*4882a593Smuzhiyun
1361*4882a593Smuzhiyun rfdependcmdcnt = 0;
1362*4882a593Smuzhiyun
1363*4882a593Smuzhiyun WARN_ONCE((channel < 1 || channel > 14),
1364*4882a593Smuzhiyun "rtl8723be: illegal channel for Zebra: %d\n", channel);
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
1367*4882a593Smuzhiyun MAX_RFDEPENDCMD_CNT,
1368*4882a593Smuzhiyun CMDID_RF_WRITEREG,
1369*4882a593Smuzhiyun RF_CHNLBW, channel, 10);
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
1372*4882a593Smuzhiyun MAX_RFDEPENDCMD_CNT,
1373*4882a593Smuzhiyun CMDID_END, 0, 0, 0);
1374*4882a593Smuzhiyun
1375*4882a593Smuzhiyun do {
1376*4882a593Smuzhiyun switch (*stage) {
1377*4882a593Smuzhiyun case 0:
1378*4882a593Smuzhiyun currentcmd = &precommoncmd[*step];
1379*4882a593Smuzhiyun break;
1380*4882a593Smuzhiyun case 1:
1381*4882a593Smuzhiyun currentcmd = &rfdependcmd[*step];
1382*4882a593Smuzhiyun break;
1383*4882a593Smuzhiyun case 2:
1384*4882a593Smuzhiyun currentcmd = &postcommoncmd[*step];
1385*4882a593Smuzhiyun break;
1386*4882a593Smuzhiyun default:
1387*4882a593Smuzhiyun pr_err("Invalid 'stage' = %d, Check it!\n",
1388*4882a593Smuzhiyun *stage);
1389*4882a593Smuzhiyun return true;
1390*4882a593Smuzhiyun }
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun if (currentcmd->cmdid == CMDID_END) {
1393*4882a593Smuzhiyun if ((*stage) == 2) {
1394*4882a593Smuzhiyun return true;
1395*4882a593Smuzhiyun } else {
1396*4882a593Smuzhiyun (*stage)++;
1397*4882a593Smuzhiyun (*step) = 0;
1398*4882a593Smuzhiyun continue;
1399*4882a593Smuzhiyun }
1400*4882a593Smuzhiyun }
1401*4882a593Smuzhiyun
1402*4882a593Smuzhiyun switch (currentcmd->cmdid) {
1403*4882a593Smuzhiyun case CMDID_SET_TXPOWEROWER_LEVEL:
1404*4882a593Smuzhiyun rtl8723be_phy_set_txpower_level(hw, channel);
1405*4882a593Smuzhiyun break;
1406*4882a593Smuzhiyun case CMDID_WRITEPORT_ULONG:
1407*4882a593Smuzhiyun rtl_write_dword(rtlpriv, currentcmd->para1,
1408*4882a593Smuzhiyun currentcmd->para2);
1409*4882a593Smuzhiyun break;
1410*4882a593Smuzhiyun case CMDID_WRITEPORT_USHORT:
1411*4882a593Smuzhiyun rtl_write_word(rtlpriv, currentcmd->para1,
1412*4882a593Smuzhiyun (u16)currentcmd->para2);
1413*4882a593Smuzhiyun break;
1414*4882a593Smuzhiyun case CMDID_WRITEPORT_UCHAR:
1415*4882a593Smuzhiyun rtl_write_byte(rtlpriv, currentcmd->para1,
1416*4882a593Smuzhiyun (u8)currentcmd->para2);
1417*4882a593Smuzhiyun break;
1418*4882a593Smuzhiyun case CMDID_RF_WRITEREG:
1419*4882a593Smuzhiyun for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
1420*4882a593Smuzhiyun rtlphy->rfreg_chnlval[rfpath] =
1421*4882a593Smuzhiyun ((rtlphy->rfreg_chnlval[rfpath] &
1422*4882a593Smuzhiyun 0xfffffc00) | currentcmd->para2);
1423*4882a593Smuzhiyun
1424*4882a593Smuzhiyun rtl_set_rfreg(hw, (enum radio_path)rfpath,
1425*4882a593Smuzhiyun currentcmd->para1,
1426*4882a593Smuzhiyun RFREG_OFFSET_MASK,
1427*4882a593Smuzhiyun rtlphy->rfreg_chnlval[rfpath]);
1428*4882a593Smuzhiyun }
1429*4882a593Smuzhiyun break;
1430*4882a593Smuzhiyun default:
1431*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
1432*4882a593Smuzhiyun "switch case %#x not processed\n",
1433*4882a593Smuzhiyun currentcmd->cmdid);
1434*4882a593Smuzhiyun break;
1435*4882a593Smuzhiyun }
1436*4882a593Smuzhiyun
1437*4882a593Smuzhiyun break;
1438*4882a593Smuzhiyun } while (true);
1439*4882a593Smuzhiyun
1440*4882a593Smuzhiyun (*delay) = currentcmd->msdelay;
1441*4882a593Smuzhiyun (*step)++;
1442*4882a593Smuzhiyun return false;
1443*4882a593Smuzhiyun }
1444*4882a593Smuzhiyun
_rtl8723be_phy_path_a_iqk(struct ieee80211_hw * hw)1445*4882a593Smuzhiyun static u8 _rtl8723be_phy_path_a_iqk(struct ieee80211_hw *hw)
1446*4882a593Smuzhiyun {
1447*4882a593Smuzhiyun u32 reg_eac, reg_e94, reg_e9c, tmp;
1448*4882a593Smuzhiyun u8 result = 0x00;
1449*4882a593Smuzhiyun
1450*4882a593Smuzhiyun /* leave IQK mode */
1451*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1452*4882a593Smuzhiyun /* switch to path A */
1453*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000000);
1454*4882a593Smuzhiyun /* enable path A PA in TXIQK mode */
1455*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0);
1456*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x20000);
1457*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0003f);
1458*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xc7f87);
1459*4882a593Smuzhiyun
1460*4882a593Smuzhiyun /* 1. TX IQK */
1461*4882a593Smuzhiyun /* path-A IQK setting */
1462*4882a593Smuzhiyun /* IQK setting */
1463*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00);
1464*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800);
1465*4882a593Smuzhiyun /* path-A IQK setting */
1466*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c);
1467*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c);
1468*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1469*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1470*4882a593Smuzhiyun
1471*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x821403ea);
1472*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28160000);
1473*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000);
1474*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000);
1475*4882a593Smuzhiyun /* LO calibration setting */
1476*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911);
1477*4882a593Smuzhiyun /* enter IQK mode */
1478*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
1479*4882a593Smuzhiyun
1480*4882a593Smuzhiyun /* One shot, path A LOK & IQK */
1481*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
1482*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
1483*4882a593Smuzhiyun
1484*4882a593Smuzhiyun mdelay(IQK_DELAY_TIME);
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun /* leave IQK mode */
1487*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1488*4882a593Smuzhiyun
1489*4882a593Smuzhiyun /* Check failed */
1490*4882a593Smuzhiyun reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
1491*4882a593Smuzhiyun reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD);
1492*4882a593Smuzhiyun reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD);
1493*4882a593Smuzhiyun
1494*4882a593Smuzhiyun if (!(reg_eac & BIT(28)) &&
1495*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
1496*4882a593Smuzhiyun (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
1497*4882a593Smuzhiyun result |= 0x01;
1498*4882a593Smuzhiyun else /* if Tx not OK, ignore Rx */
1499*4882a593Smuzhiyun return result;
1500*4882a593Smuzhiyun
1501*4882a593Smuzhiyun /* Allen 20131125 */
1502*4882a593Smuzhiyun tmp = (reg_e9c & 0x03FF0000) >> 16;
1503*4882a593Smuzhiyun if ((tmp & 0x200) > 0)
1504*4882a593Smuzhiyun tmp = 0x400 - tmp;
1505*4882a593Smuzhiyun
1506*4882a593Smuzhiyun if (!(reg_eac & BIT(28)) &&
1507*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) < 0x110) &&
1508*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) &&
1509*4882a593Smuzhiyun (tmp < 0xf))
1510*4882a593Smuzhiyun result |= 0x01;
1511*4882a593Smuzhiyun else /* if Tx not OK, ignore Rx */
1512*4882a593Smuzhiyun return result;
1513*4882a593Smuzhiyun
1514*4882a593Smuzhiyun return result;
1515*4882a593Smuzhiyun }
1516*4882a593Smuzhiyun
1517*4882a593Smuzhiyun /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
_rtl8723be_phy_path_a_rx_iqk(struct ieee80211_hw * hw)1518*4882a593Smuzhiyun static u8 _rtl8723be_phy_path_a_rx_iqk(struct ieee80211_hw *hw)
1519*4882a593Smuzhiyun {
1520*4882a593Smuzhiyun u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u32tmp, tmp;
1521*4882a593Smuzhiyun u8 result = 0x00;
1522*4882a593Smuzhiyun
1523*4882a593Smuzhiyun /* leave IQK mode */
1524*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1525*4882a593Smuzhiyun
1526*4882a593Smuzhiyun /* switch to path A */
1527*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000000);
1528*4882a593Smuzhiyun
1529*4882a593Smuzhiyun /* 1 Get TXIMR setting */
1530*4882a593Smuzhiyun /* modify RXIQK mode table */
1531*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x1);
1532*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000);
1533*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f);
1534*4882a593Smuzhiyun /* LNA2 off, PA on for Dcut */
1535*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7fb7);
1536*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
1537*4882a593Smuzhiyun
1538*4882a593Smuzhiyun /* IQK setting */
1539*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00);
1540*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800);
1541*4882a593Smuzhiyun
1542*4882a593Smuzhiyun /* path-A IQK setting */
1543*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c);
1544*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c);
1545*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1546*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1547*4882a593Smuzhiyun
1548*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160ff0);
1549*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28110000);
1550*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000);
1551*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000);
1552*4882a593Smuzhiyun
1553*4882a593Smuzhiyun /* LO calibration setting */
1554*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911);
1555*4882a593Smuzhiyun
1556*4882a593Smuzhiyun /* enter IQK mode */
1557*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
1558*4882a593Smuzhiyun
1559*4882a593Smuzhiyun /* One shot, path A LOK & IQK */
1560*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
1561*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
1562*4882a593Smuzhiyun
1563*4882a593Smuzhiyun mdelay(IQK_DELAY_TIME);
1564*4882a593Smuzhiyun
1565*4882a593Smuzhiyun /* leave IQK mode */
1566*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1567*4882a593Smuzhiyun
1568*4882a593Smuzhiyun /* Check failed */
1569*4882a593Smuzhiyun reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD);
1570*4882a593Smuzhiyun reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD);
1571*4882a593Smuzhiyun reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD);
1572*4882a593Smuzhiyun
1573*4882a593Smuzhiyun if (!(reg_eac & BIT(28)) &&
1574*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
1575*4882a593Smuzhiyun (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
1576*4882a593Smuzhiyun result |= 0x01;
1577*4882a593Smuzhiyun else /* if Tx not OK, ignore Rx */
1578*4882a593Smuzhiyun return result;
1579*4882a593Smuzhiyun
1580*4882a593Smuzhiyun /* Allen 20131125 */
1581*4882a593Smuzhiyun tmp = (reg_e9c & 0x03FF0000) >> 16;
1582*4882a593Smuzhiyun if ((tmp & 0x200) > 0)
1583*4882a593Smuzhiyun tmp = 0x400 - tmp;
1584*4882a593Smuzhiyun
1585*4882a593Smuzhiyun if (!(reg_eac & BIT(28)) &&
1586*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) < 0x110) &&
1587*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) &&
1588*4882a593Smuzhiyun (tmp < 0xf))
1589*4882a593Smuzhiyun result |= 0x01;
1590*4882a593Smuzhiyun else /* if Tx not OK, ignore Rx */
1591*4882a593Smuzhiyun return result;
1592*4882a593Smuzhiyun
1593*4882a593Smuzhiyun u32tmp = 0x80007C00 | (reg_e94 & 0x3FF0000) |
1594*4882a593Smuzhiyun ((reg_e9c & 0x3FF0000) >> 16);
1595*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32tmp);
1596*4882a593Smuzhiyun
1597*4882a593Smuzhiyun /* 1 RX IQK */
1598*4882a593Smuzhiyun /* modify RXIQK mode table */
1599*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1600*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x1);
1601*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000);
1602*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f);
1603*4882a593Smuzhiyun /* LAN2 on, PA off for Dcut */
1604*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7d77);
1605*4882a593Smuzhiyun
1606*4882a593Smuzhiyun /* PA, PAD setting */
1607*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0xf80);
1608*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0x55, RFREG_OFFSET_MASK, 0x4021f);
1609*4882a593Smuzhiyun
1610*4882a593Smuzhiyun /* IQK setting */
1611*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800);
1612*4882a593Smuzhiyun
1613*4882a593Smuzhiyun /* path-A IQK setting */
1614*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c);
1615*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x18008c1c);
1616*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1617*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1618*4882a593Smuzhiyun
1619*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82110000);
1620*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x2816001f);
1621*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000);
1622*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000);
1623*4882a593Smuzhiyun
1624*4882a593Smuzhiyun /* LO calibration setting */
1625*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a8d1);
1626*4882a593Smuzhiyun
1627*4882a593Smuzhiyun /* enter IQK mode */
1628*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
1629*4882a593Smuzhiyun
1630*4882a593Smuzhiyun /* One shot, path A LOK & IQK */
1631*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
1632*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
1633*4882a593Smuzhiyun
1634*4882a593Smuzhiyun mdelay(IQK_DELAY_TIME);
1635*4882a593Smuzhiyun
1636*4882a593Smuzhiyun /* leave IQK mode */
1637*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1638*4882a593Smuzhiyun
1639*4882a593Smuzhiyun /* Check failed */
1640*4882a593Smuzhiyun reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD);
1641*4882a593Smuzhiyun reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD);
1642*4882a593Smuzhiyun
1643*4882a593Smuzhiyun /* leave IQK mode */
1644*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1645*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0xdf, RFREG_OFFSET_MASK, 0x780);
1646*4882a593Smuzhiyun
1647*4882a593Smuzhiyun /* Allen 20131125 */
1648*4882a593Smuzhiyun tmp = (reg_eac & 0x03FF0000) >> 16;
1649*4882a593Smuzhiyun if ((tmp & 0x200) > 0)
1650*4882a593Smuzhiyun tmp = 0x400 - tmp;
1651*4882a593Smuzhiyun /* if Tx is OK, check whether Rx is OK */
1652*4882a593Smuzhiyun if (!(reg_eac & BIT(27)) &&
1653*4882a593Smuzhiyun (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
1654*4882a593Smuzhiyun (((reg_eac & 0x03FF0000) >> 16) != 0x36))
1655*4882a593Smuzhiyun result |= 0x02;
1656*4882a593Smuzhiyun else if (!(reg_eac & BIT(27)) &&
1657*4882a593Smuzhiyun (((reg_ea4 & 0x03FF0000) >> 16) < 0x110) &&
1658*4882a593Smuzhiyun (((reg_ea4 & 0x03FF0000) >> 16) > 0xf0) &&
1659*4882a593Smuzhiyun (tmp < 0xf))
1660*4882a593Smuzhiyun result |= 0x02;
1661*4882a593Smuzhiyun
1662*4882a593Smuzhiyun return result;
1663*4882a593Smuzhiyun }
1664*4882a593Smuzhiyun
_rtl8723be_phy_path_b_iqk(struct ieee80211_hw * hw)1665*4882a593Smuzhiyun static u8 _rtl8723be_phy_path_b_iqk(struct ieee80211_hw *hw)
1666*4882a593Smuzhiyun {
1667*4882a593Smuzhiyun u32 reg_eac, reg_e94, reg_e9c, tmp;
1668*4882a593Smuzhiyun u8 result = 0x00;
1669*4882a593Smuzhiyun
1670*4882a593Smuzhiyun /* leave IQK mode */
1671*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1672*4882a593Smuzhiyun /* switch to path B */
1673*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000280);
1674*4882a593Smuzhiyun
1675*4882a593Smuzhiyun /* enable path B PA in TXIQK mode */
1676*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0xed, RFREG_OFFSET_MASK, 0x00020);
1677*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0x43, RFREG_OFFSET_MASK, 0x40fc1);
1678*4882a593Smuzhiyun
1679*4882a593Smuzhiyun /* 1 Tx IQK */
1680*4882a593Smuzhiyun /* IQK setting */
1681*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00);
1682*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800);
1683*4882a593Smuzhiyun /* path-A IQK setting */
1684*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c);
1685*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c);
1686*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1687*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1688*4882a593Smuzhiyun
1689*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x821403ea);
1690*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28110000);
1691*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000);
1692*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000);
1693*4882a593Smuzhiyun
1694*4882a593Smuzhiyun /* LO calibration setting */
1695*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x00462911);
1696*4882a593Smuzhiyun
1697*4882a593Smuzhiyun /* enter IQK mode */
1698*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
1699*4882a593Smuzhiyun
1700*4882a593Smuzhiyun /* One shot, path B LOK & IQK */
1701*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
1702*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
1703*4882a593Smuzhiyun
1704*4882a593Smuzhiyun mdelay(IQK_DELAY_TIME);
1705*4882a593Smuzhiyun
1706*4882a593Smuzhiyun /* leave IQK mode */
1707*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1708*4882a593Smuzhiyun
1709*4882a593Smuzhiyun /* Check failed */
1710*4882a593Smuzhiyun reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD);
1711*4882a593Smuzhiyun reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD);
1712*4882a593Smuzhiyun reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD);
1713*4882a593Smuzhiyun
1714*4882a593Smuzhiyun if (!(reg_eac & BIT(28)) &&
1715*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
1716*4882a593Smuzhiyun (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
1717*4882a593Smuzhiyun result |= 0x01;
1718*4882a593Smuzhiyun else
1719*4882a593Smuzhiyun return result;
1720*4882a593Smuzhiyun
1721*4882a593Smuzhiyun /* Allen 20131125 */
1722*4882a593Smuzhiyun tmp = (reg_e9c & 0x03FF0000) >> 16;
1723*4882a593Smuzhiyun if ((tmp & 0x200) > 0)
1724*4882a593Smuzhiyun tmp = 0x400 - tmp;
1725*4882a593Smuzhiyun
1726*4882a593Smuzhiyun if (!(reg_eac & BIT(28)) &&
1727*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) < 0x110) &&
1728*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) &&
1729*4882a593Smuzhiyun (tmp < 0xf))
1730*4882a593Smuzhiyun result |= 0x01;
1731*4882a593Smuzhiyun else
1732*4882a593Smuzhiyun return result;
1733*4882a593Smuzhiyun
1734*4882a593Smuzhiyun return result;
1735*4882a593Smuzhiyun }
1736*4882a593Smuzhiyun
1737*4882a593Smuzhiyun /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
_rtl8723be_phy_path_b_rx_iqk(struct ieee80211_hw * hw)1738*4882a593Smuzhiyun static u8 _rtl8723be_phy_path_b_rx_iqk(struct ieee80211_hw *hw)
1739*4882a593Smuzhiyun {
1740*4882a593Smuzhiyun u32 reg_e94, reg_e9c, reg_ea4, reg_eac, u32tmp, tmp;
1741*4882a593Smuzhiyun u8 result = 0x00;
1742*4882a593Smuzhiyun
1743*4882a593Smuzhiyun /* leave IQK mode */
1744*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1745*4882a593Smuzhiyun /* switch to path B */
1746*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x948, MASKDWORD, 0x00000280);
1747*4882a593Smuzhiyun
1748*4882a593Smuzhiyun /* 1 Get TXIMR setting */
1749*4882a593Smuzhiyun /* modify RXIQK mode table */
1750*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, RFREG_OFFSET_MASK, 0x800a0);
1751*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000);
1752*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f);
1753*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7ff7);
1754*4882a593Smuzhiyun
1755*4882a593Smuzhiyun /* open PA S1 & SMIXER */
1756*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0xed, RFREG_OFFSET_MASK, 0x00020);
1757*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0x43, RFREG_OFFSET_MASK, 0x60fed);
1758*4882a593Smuzhiyun
1759*4882a593Smuzhiyun /* IQK setting */
1760*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, 0x01007c00);
1761*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800);
1762*4882a593Smuzhiyun
1763*4882a593Smuzhiyun /* path-B IQK setting */
1764*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x18008c1c);
1765*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x38008c1c);
1766*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1767*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1768*4882a593Smuzhiyun
1769*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82160ff0);
1770*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x28110000);
1771*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000);
1772*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000);
1773*4882a593Smuzhiyun
1774*4882a593Smuzhiyun /* LO calibration setting */
1775*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a911);
1776*4882a593Smuzhiyun /* enter IQK mode */
1777*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
1778*4882a593Smuzhiyun
1779*4882a593Smuzhiyun /* One shot, path B TXIQK @ RXIQK */
1780*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
1781*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
1782*4882a593Smuzhiyun
1783*4882a593Smuzhiyun mdelay(IQK_DELAY_TIME);
1784*4882a593Smuzhiyun
1785*4882a593Smuzhiyun /* leave IQK mode */
1786*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1787*4882a593Smuzhiyun /* Check failed */
1788*4882a593Smuzhiyun reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD);
1789*4882a593Smuzhiyun reg_e94 = rtl_get_bbreg(hw, RTX_POWER_BEFORE_IQK_A, MASKDWORD);
1790*4882a593Smuzhiyun reg_e9c = rtl_get_bbreg(hw, RTX_POWER_AFTER_IQK_A, MASKDWORD);
1791*4882a593Smuzhiyun
1792*4882a593Smuzhiyun if (!(reg_eac & BIT(28)) &&
1793*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
1794*4882a593Smuzhiyun (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
1795*4882a593Smuzhiyun result |= 0x01;
1796*4882a593Smuzhiyun else /* if Tx not OK, ignore Rx */
1797*4882a593Smuzhiyun return result;
1798*4882a593Smuzhiyun
1799*4882a593Smuzhiyun /* Allen 20131125 */
1800*4882a593Smuzhiyun tmp = (reg_e9c & 0x03FF0000) >> 16;
1801*4882a593Smuzhiyun if ((tmp & 0x200) > 0)
1802*4882a593Smuzhiyun tmp = 0x400 - tmp;
1803*4882a593Smuzhiyun
1804*4882a593Smuzhiyun if (!(reg_eac & BIT(28)) &&
1805*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) < 0x110) &&
1806*4882a593Smuzhiyun (((reg_e94 & 0x03FF0000) >> 16) > 0xf0) &&
1807*4882a593Smuzhiyun (tmp < 0xf))
1808*4882a593Smuzhiyun result |= 0x01;
1809*4882a593Smuzhiyun else
1810*4882a593Smuzhiyun return result;
1811*4882a593Smuzhiyun
1812*4882a593Smuzhiyun u32tmp = 0x80007C00 | (reg_e94 & 0x3FF0000) |
1813*4882a593Smuzhiyun ((reg_e9c & 0x3FF0000) >> 16);
1814*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK, MASKDWORD, u32tmp);
1815*4882a593Smuzhiyun
1816*4882a593Smuzhiyun /* 1 RX IQK */
1817*4882a593Smuzhiyun
1818*4882a593Smuzhiyun /* <20121009, Kordan> RF Mode = 3 */
1819*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1820*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x1);
1821*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK_OS, RFREG_OFFSET_MASK, 0x30000);
1822*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G1, RFREG_OFFSET_MASK, 0x0001f);
1823*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_TXPA_G2, RFREG_OFFSET_MASK, 0xf7d77);
1824*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, RF_WE_LUT, 0x80000, 0x0);
1825*4882a593Smuzhiyun
1826*4882a593Smuzhiyun /* open PA S1 & close SMIXER */
1827*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0xed, RFREG_OFFSET_MASK, 0x00020);
1828*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0x43, RFREG_OFFSET_MASK, 0x60fbd);
1829*4882a593Smuzhiyun
1830*4882a593Smuzhiyun /* IQK setting */
1831*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK, MASKDWORD, 0x01004800);
1832*4882a593Smuzhiyun
1833*4882a593Smuzhiyun /* path-B IQK setting */
1834*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_A, MASKDWORD, 0x38008c1c);
1835*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_A, MASKDWORD, 0x18008c1c);
1836*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1837*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_TONE_B, MASKDWORD, 0x38008c1c);
1838*4882a593Smuzhiyun
1839*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_A, MASKDWORD, 0x82110000);
1840*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_A, MASKDWORD, 0x2816001f);
1841*4882a593Smuzhiyun rtl_set_bbreg(hw, RTX_IQK_PI_B, MASKDWORD, 0x82110000);
1842*4882a593Smuzhiyun rtl_set_bbreg(hw, RRX_IQK_PI_B, MASKDWORD, 0x28110000);
1843*4882a593Smuzhiyun
1844*4882a593Smuzhiyun /* LO calibration setting */
1845*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_RSP, MASKDWORD, 0x0046a8d1);
1846*4882a593Smuzhiyun /* enter IQK mode */
1847*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x80800000);
1848*4882a593Smuzhiyun
1849*4882a593Smuzhiyun /* One shot, path B LOK & IQK */
1850*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf9000000);
1851*4882a593Smuzhiyun rtl_set_bbreg(hw, RIQK_AGC_PTS, MASKDWORD, 0xf8000000);
1852*4882a593Smuzhiyun
1853*4882a593Smuzhiyun mdelay(IQK_DELAY_TIME);
1854*4882a593Smuzhiyun
1855*4882a593Smuzhiyun /* leave IQK mode */
1856*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0x00000000);
1857*4882a593Smuzhiyun /* Check failed */
1858*4882a593Smuzhiyun reg_eac = rtl_get_bbreg(hw, RRX_POWER_AFTER_IQK_A_2, MASKDWORD);
1859*4882a593Smuzhiyun reg_ea4 = rtl_get_bbreg(hw, RRX_POWER_BEFORE_IQK_A_2, MASKDWORD);
1860*4882a593Smuzhiyun
1861*4882a593Smuzhiyun /* Allen 20131125 */
1862*4882a593Smuzhiyun tmp = (reg_eac & 0x03FF0000) >> 16;
1863*4882a593Smuzhiyun if ((tmp & 0x200) > 0)
1864*4882a593Smuzhiyun tmp = 0x400 - tmp;
1865*4882a593Smuzhiyun
1866*4882a593Smuzhiyun /* if Tx is OK, check whether Rx is OK */
1867*4882a593Smuzhiyun if (!(reg_eac & BIT(27)) &&
1868*4882a593Smuzhiyun (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
1869*4882a593Smuzhiyun (((reg_eac & 0x03FF0000) >> 16) != 0x36))
1870*4882a593Smuzhiyun result |= 0x02;
1871*4882a593Smuzhiyun else if (!(reg_eac & BIT(27)) &&
1872*4882a593Smuzhiyun (((reg_ea4 & 0x03FF0000) >> 16) < 0x110) &&
1873*4882a593Smuzhiyun (((reg_ea4 & 0x03FF0000) >> 16) > 0xf0) &&
1874*4882a593Smuzhiyun (tmp < 0xf))
1875*4882a593Smuzhiyun result |= 0x02;
1876*4882a593Smuzhiyun else
1877*4882a593Smuzhiyun return result;
1878*4882a593Smuzhiyun
1879*4882a593Smuzhiyun return result;
1880*4882a593Smuzhiyun }
1881*4882a593Smuzhiyun
_rtl8723be_phy_path_b_fill_iqk_matrix(struct ieee80211_hw * hw,bool b_iqk_ok,long result[][8],u8 final_candidate,bool btxonly)1882*4882a593Smuzhiyun static void _rtl8723be_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw,
1883*4882a593Smuzhiyun bool b_iqk_ok,
1884*4882a593Smuzhiyun long result[][8],
1885*4882a593Smuzhiyun u8 final_candidate,
1886*4882a593Smuzhiyun bool btxonly)
1887*4882a593Smuzhiyun {
1888*4882a593Smuzhiyun u32 oldval_1, x, tx1_a, reg;
1889*4882a593Smuzhiyun long y, tx1_c;
1890*4882a593Smuzhiyun
1891*4882a593Smuzhiyun if (final_candidate == 0xFF) {
1892*4882a593Smuzhiyun return;
1893*4882a593Smuzhiyun } else if (b_iqk_ok) {
1894*4882a593Smuzhiyun oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
1895*4882a593Smuzhiyun MASKDWORD) >> 22) & 0x3FF;
1896*4882a593Smuzhiyun x = result[final_candidate][4];
1897*4882a593Smuzhiyun if ((x & 0x00000200) != 0)
1898*4882a593Smuzhiyun x = x | 0xFFFFFC00;
1899*4882a593Smuzhiyun tx1_a = (x * oldval_1) >> 8;
1900*4882a593Smuzhiyun rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a);
1901*4882a593Smuzhiyun rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27),
1902*4882a593Smuzhiyun ((x * oldval_1 >> 7) & 0x1));
1903*4882a593Smuzhiyun y = result[final_candidate][5];
1904*4882a593Smuzhiyun if ((y & 0x00000200) != 0)
1905*4882a593Smuzhiyun y = y | 0xFFFFFC00;
1906*4882a593Smuzhiyun tx1_c = (y * oldval_1) >> 8;
1907*4882a593Smuzhiyun rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000,
1908*4882a593Smuzhiyun ((tx1_c & 0x3C0) >> 6));
1909*4882a593Smuzhiyun rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000,
1910*4882a593Smuzhiyun (tx1_c & 0x3F));
1911*4882a593Smuzhiyun rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25),
1912*4882a593Smuzhiyun ((y * oldval_1 >> 7) & 0x1));
1913*4882a593Smuzhiyun if (btxonly)
1914*4882a593Smuzhiyun return;
1915*4882a593Smuzhiyun reg = result[final_candidate][6];
1916*4882a593Smuzhiyun rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg);
1917*4882a593Smuzhiyun reg = result[final_candidate][7] & 0x3F;
1918*4882a593Smuzhiyun rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg);
1919*4882a593Smuzhiyun reg = (result[final_candidate][7] >> 6) & 0xF;
1920*4882a593Smuzhiyun /* rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg); */
1921*4882a593Smuzhiyun }
1922*4882a593Smuzhiyun }
1923*4882a593Smuzhiyun
_rtl8723be_phy_simularity_compare(struct ieee80211_hw * hw,long result[][8],u8 c1,u8 c2)1924*4882a593Smuzhiyun static bool _rtl8723be_phy_simularity_compare(struct ieee80211_hw *hw,
1925*4882a593Smuzhiyun long result[][8], u8 c1, u8 c2)
1926*4882a593Smuzhiyun {
1927*4882a593Smuzhiyun u32 i, j, diff, simularity_bitmap, bound = 0;
1928*4882a593Smuzhiyun
1929*4882a593Smuzhiyun u8 final_candidate[2] = {0xFF, 0xFF}; /* for path A and path B */
1930*4882a593Smuzhiyun bool bresult = true; /* is2t = true*/
1931*4882a593Smuzhiyun s32 tmp1 = 0, tmp2 = 0;
1932*4882a593Smuzhiyun
1933*4882a593Smuzhiyun bound = 8;
1934*4882a593Smuzhiyun
1935*4882a593Smuzhiyun simularity_bitmap = 0;
1936*4882a593Smuzhiyun
1937*4882a593Smuzhiyun for (i = 0; i < bound; i++) {
1938*4882a593Smuzhiyun if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
1939*4882a593Smuzhiyun if ((result[c1][i] & 0x00000200) != 0)
1940*4882a593Smuzhiyun tmp1 = result[c1][i] | 0xFFFFFC00;
1941*4882a593Smuzhiyun else
1942*4882a593Smuzhiyun tmp1 = result[c1][i];
1943*4882a593Smuzhiyun
1944*4882a593Smuzhiyun if ((result[c2][i] & 0x00000200) != 0)
1945*4882a593Smuzhiyun tmp2 = result[c2][i] | 0xFFFFFC00;
1946*4882a593Smuzhiyun else
1947*4882a593Smuzhiyun tmp2 = result[c2][i];
1948*4882a593Smuzhiyun } else {
1949*4882a593Smuzhiyun tmp1 = result[c1][i];
1950*4882a593Smuzhiyun tmp2 = result[c2][i];
1951*4882a593Smuzhiyun }
1952*4882a593Smuzhiyun
1953*4882a593Smuzhiyun diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1);
1954*4882a593Smuzhiyun
1955*4882a593Smuzhiyun if (diff > MAX_TOLERANCE) {
1956*4882a593Smuzhiyun if ((i == 2 || i == 6) && !simularity_bitmap) {
1957*4882a593Smuzhiyun if (result[c1][i] + result[c1][i + 1] == 0)
1958*4882a593Smuzhiyun final_candidate[(i / 4)] = c2;
1959*4882a593Smuzhiyun else if (result[c2][i] + result[c2][i + 1] == 0)
1960*4882a593Smuzhiyun final_candidate[(i / 4)] = c1;
1961*4882a593Smuzhiyun else
1962*4882a593Smuzhiyun simularity_bitmap |= (1 << i);
1963*4882a593Smuzhiyun } else
1964*4882a593Smuzhiyun simularity_bitmap |= (1 << i);
1965*4882a593Smuzhiyun }
1966*4882a593Smuzhiyun }
1967*4882a593Smuzhiyun
1968*4882a593Smuzhiyun if (simularity_bitmap == 0) {
1969*4882a593Smuzhiyun for (i = 0; i < (bound / 4); i++) {
1970*4882a593Smuzhiyun if (final_candidate[i] != 0xFF) {
1971*4882a593Smuzhiyun for (j = i * 4; j < (i + 1) * 4 - 2; j++)
1972*4882a593Smuzhiyun result[3][j] =
1973*4882a593Smuzhiyun result[final_candidate[i]][j];
1974*4882a593Smuzhiyun bresult = false;
1975*4882a593Smuzhiyun }
1976*4882a593Smuzhiyun }
1977*4882a593Smuzhiyun return bresult;
1978*4882a593Smuzhiyun } else {
1979*4882a593Smuzhiyun if (!(simularity_bitmap & 0x03)) { /* path A TX OK */
1980*4882a593Smuzhiyun for (i = 0; i < 2; i++)
1981*4882a593Smuzhiyun result[3][i] = result[c1][i];
1982*4882a593Smuzhiyun }
1983*4882a593Smuzhiyun if (!(simularity_bitmap & 0x0c)) { /* path A RX OK */
1984*4882a593Smuzhiyun for (i = 2; i < 4; i++)
1985*4882a593Smuzhiyun result[3][i] = result[c1][i];
1986*4882a593Smuzhiyun }
1987*4882a593Smuzhiyun if (!(simularity_bitmap & 0x30)) { /* path B TX OK */
1988*4882a593Smuzhiyun for (i = 4; i < 6; i++)
1989*4882a593Smuzhiyun result[3][i] = result[c1][i];
1990*4882a593Smuzhiyun }
1991*4882a593Smuzhiyun if (!(simularity_bitmap & 0xc0)) { /* path B RX OK */
1992*4882a593Smuzhiyun for (i = 6; i < 8; i++)
1993*4882a593Smuzhiyun result[3][i] = result[c1][i];
1994*4882a593Smuzhiyun }
1995*4882a593Smuzhiyun return false;
1996*4882a593Smuzhiyun }
1997*4882a593Smuzhiyun }
1998*4882a593Smuzhiyun
_rtl8723be_phy_iq_calibrate(struct ieee80211_hw * hw,long result[][8],u8 t,bool is2t)1999*4882a593Smuzhiyun static void _rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw,
2000*4882a593Smuzhiyun long result[][8], u8 t, bool is2t)
2001*4882a593Smuzhiyun {
2002*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2003*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
2004*4882a593Smuzhiyun u32 i;
2005*4882a593Smuzhiyun u8 patha_ok, pathb_ok;
2006*4882a593Smuzhiyun u32 adda_reg[IQK_ADDA_REG_NUM] = {
2007*4882a593Smuzhiyun 0x85c, 0xe6c, 0xe70, 0xe74,
2008*4882a593Smuzhiyun 0xe78, 0xe7c, 0xe80, 0xe84,
2009*4882a593Smuzhiyun 0xe88, 0xe8c, 0xed0, 0xed4,
2010*4882a593Smuzhiyun 0xed8, 0xedc, 0xee0, 0xeec
2011*4882a593Smuzhiyun };
2012*4882a593Smuzhiyun
2013*4882a593Smuzhiyun u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
2014*4882a593Smuzhiyun 0x522, 0x550, 0x551, 0x040
2015*4882a593Smuzhiyun };
2016*4882a593Smuzhiyun u32 iqk_bb_reg[IQK_BB_REG_NUM] = {
2017*4882a593Smuzhiyun ROFDM0_TRXPATHENABLE, ROFDM0_TRMUXPAR,
2018*4882a593Smuzhiyun RFPGA0_XCD_RFINTERFACESW, 0xb68, 0xb6c,
2019*4882a593Smuzhiyun 0x870, 0x860,
2020*4882a593Smuzhiyun 0x864, 0xa04
2021*4882a593Smuzhiyun };
2022*4882a593Smuzhiyun const u32 retrycount = 2;
2023*4882a593Smuzhiyun
2024*4882a593Smuzhiyun u32 path_sel_bb;/* path_sel_rf */
2025*4882a593Smuzhiyun
2026*4882a593Smuzhiyun u8 tmp_reg_c50, tmp_reg_c58;
2027*4882a593Smuzhiyun
2028*4882a593Smuzhiyun tmp_reg_c50 = rtl_get_bbreg(hw, 0xc50, MASKBYTE0);
2029*4882a593Smuzhiyun tmp_reg_c58 = rtl_get_bbreg(hw, 0xc58, MASKBYTE0);
2030*4882a593Smuzhiyun
2031*4882a593Smuzhiyun if (t == 0) {
2032*4882a593Smuzhiyun rtl8723_save_adda_registers(hw, adda_reg,
2033*4882a593Smuzhiyun rtlphy->adda_backup, 16);
2034*4882a593Smuzhiyun rtl8723_phy_save_mac_registers(hw, iqk_mac_reg,
2035*4882a593Smuzhiyun rtlphy->iqk_mac_backup);
2036*4882a593Smuzhiyun rtl8723_save_adda_registers(hw, iqk_bb_reg,
2037*4882a593Smuzhiyun rtlphy->iqk_bb_backup,
2038*4882a593Smuzhiyun IQK_BB_REG_NUM);
2039*4882a593Smuzhiyun }
2040*4882a593Smuzhiyun rtl8723_phy_path_adda_on(hw, adda_reg, true, is2t);
2041*4882a593Smuzhiyun if (t == 0) {
2042*4882a593Smuzhiyun rtlphy->rfpi_enable = (u8)rtl_get_bbreg(hw,
2043*4882a593Smuzhiyun RFPGA0_XA_HSSIPARAMETER1,
2044*4882a593Smuzhiyun BIT(8));
2045*4882a593Smuzhiyun }
2046*4882a593Smuzhiyun
2047*4882a593Smuzhiyun path_sel_bb = rtl_get_bbreg(hw, 0x948, MASKDWORD);
2048*4882a593Smuzhiyun
2049*4882a593Smuzhiyun rtl8723_phy_mac_setting_calibration(hw, iqk_mac_reg,
2050*4882a593Smuzhiyun rtlphy->iqk_mac_backup);
2051*4882a593Smuzhiyun /*BB Setting*/
2052*4882a593Smuzhiyun rtl_set_bbreg(hw, 0xa04, 0x0f000000, 0xf);
2053*4882a593Smuzhiyun rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
2054*4882a593Smuzhiyun rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
2055*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
2056*4882a593Smuzhiyun
2057*4882a593Smuzhiyun /* path A TX IQK */
2058*4882a593Smuzhiyun for (i = 0; i < retrycount; i++) {
2059*4882a593Smuzhiyun patha_ok = _rtl8723be_phy_path_a_iqk(hw);
2060*4882a593Smuzhiyun if (patha_ok == 0x01) {
2061*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
2062*4882a593Smuzhiyun "Path A Tx IQK Success!!\n");
2063*4882a593Smuzhiyun result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
2064*4882a593Smuzhiyun 0x3FF0000) >> 16;
2065*4882a593Smuzhiyun result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
2066*4882a593Smuzhiyun 0x3FF0000) >> 16;
2067*4882a593Smuzhiyun break;
2068*4882a593Smuzhiyun } else {
2069*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
2070*4882a593Smuzhiyun "Path A Tx IQK Fail!!\n");
2071*4882a593Smuzhiyun }
2072*4882a593Smuzhiyun }
2073*4882a593Smuzhiyun /* path A RX IQK */
2074*4882a593Smuzhiyun for (i = 0; i < retrycount; i++) {
2075*4882a593Smuzhiyun patha_ok = _rtl8723be_phy_path_a_rx_iqk(hw);
2076*4882a593Smuzhiyun if (patha_ok == 0x03) {
2077*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
2078*4882a593Smuzhiyun "Path A Rx IQK Success!!\n");
2079*4882a593Smuzhiyun result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
2080*4882a593Smuzhiyun 0x3FF0000) >> 16;
2081*4882a593Smuzhiyun result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
2082*4882a593Smuzhiyun 0x3FF0000) >> 16;
2083*4882a593Smuzhiyun break;
2084*4882a593Smuzhiyun }
2085*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
2086*4882a593Smuzhiyun "Path A Rx IQK Fail!!\n");
2087*4882a593Smuzhiyun }
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun if (0x00 == patha_ok)
2090*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Path A IQK Fail!!\n");
2091*4882a593Smuzhiyun
2092*4882a593Smuzhiyun if (is2t) {
2093*4882a593Smuzhiyun /* path B TX IQK */
2094*4882a593Smuzhiyun for (i = 0; i < retrycount; i++) {
2095*4882a593Smuzhiyun pathb_ok = _rtl8723be_phy_path_b_iqk(hw);
2096*4882a593Smuzhiyun if (pathb_ok == 0x01) {
2097*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
2098*4882a593Smuzhiyun "Path B Tx IQK Success!!\n");
2099*4882a593Smuzhiyun result[t][4] = (rtl_get_bbreg(hw, 0xe94,
2100*4882a593Smuzhiyun MASKDWORD) &
2101*4882a593Smuzhiyun 0x3FF0000) >> 16;
2102*4882a593Smuzhiyun result[t][5] = (rtl_get_bbreg(hw, 0xe9c,
2103*4882a593Smuzhiyun MASKDWORD) &
2104*4882a593Smuzhiyun 0x3FF0000) >> 16;
2105*4882a593Smuzhiyun break;
2106*4882a593Smuzhiyun }
2107*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
2108*4882a593Smuzhiyun "Path B Tx IQK Fail!!\n");
2109*4882a593Smuzhiyun }
2110*4882a593Smuzhiyun /* path B RX IQK */
2111*4882a593Smuzhiyun for (i = 0; i < retrycount; i++) {
2112*4882a593Smuzhiyun pathb_ok = _rtl8723be_phy_path_b_rx_iqk(hw);
2113*4882a593Smuzhiyun if (pathb_ok == 0x03) {
2114*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
2115*4882a593Smuzhiyun "Path B Rx IQK Success!!\n");
2116*4882a593Smuzhiyun result[t][6] = (rtl_get_bbreg(hw, 0xea4,
2117*4882a593Smuzhiyun MASKDWORD) &
2118*4882a593Smuzhiyun 0x3FF0000) >> 16;
2119*4882a593Smuzhiyun result[t][7] = (rtl_get_bbreg(hw, 0xeac,
2120*4882a593Smuzhiyun MASKDWORD) &
2121*4882a593Smuzhiyun 0x3FF0000) >> 16;
2122*4882a593Smuzhiyun break;
2123*4882a593Smuzhiyun }
2124*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
2125*4882a593Smuzhiyun "Path B Rx IQK Fail!!\n");
2126*4882a593Smuzhiyun }
2127*4882a593Smuzhiyun }
2128*4882a593Smuzhiyun
2129*4882a593Smuzhiyun /* Back to BB mode, load original value */
2130*4882a593Smuzhiyun rtl_set_bbreg(hw, RFPGA0_IQK, MASKDWORD, 0);
2131*4882a593Smuzhiyun
2132*4882a593Smuzhiyun if (t != 0) {
2133*4882a593Smuzhiyun rtl8723_phy_reload_adda_registers(hw, adda_reg,
2134*4882a593Smuzhiyun rtlphy->adda_backup, 16);
2135*4882a593Smuzhiyun rtl8723_phy_reload_mac_registers(hw, iqk_mac_reg,
2136*4882a593Smuzhiyun rtlphy->iqk_mac_backup);
2137*4882a593Smuzhiyun rtl8723_phy_reload_adda_registers(hw, iqk_bb_reg,
2138*4882a593Smuzhiyun rtlphy->iqk_bb_backup,
2139*4882a593Smuzhiyun IQK_BB_REG_NUM);
2140*4882a593Smuzhiyun
2141*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x948, MASKDWORD, path_sel_bb);
2142*4882a593Smuzhiyun /*rtl_set_rfreg(hw, RF90_PATH_B, 0xb0, 0xfffff, path_sel_rf);*/
2143*4882a593Smuzhiyun
2144*4882a593Smuzhiyun rtl_set_bbreg(hw, 0xc50, MASKBYTE0, 0x50);
2145*4882a593Smuzhiyun rtl_set_bbreg(hw, 0xc50, MASKBYTE0, tmp_reg_c50);
2146*4882a593Smuzhiyun if (is2t) {
2147*4882a593Smuzhiyun rtl_set_bbreg(hw, 0xc58, MASKBYTE0, 0x50);
2148*4882a593Smuzhiyun rtl_set_bbreg(hw, 0xc58, MASKBYTE0, tmp_reg_c58);
2149*4882a593Smuzhiyun }
2150*4882a593Smuzhiyun rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x01008c00);
2151*4882a593Smuzhiyun rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x01008c00);
2152*4882a593Smuzhiyun }
2153*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "8723be IQK Finish!!\n");
2154*4882a593Smuzhiyun }
2155*4882a593Smuzhiyun
_get_right_chnl_place_for_iqk(u8 chnl)2156*4882a593Smuzhiyun static u8 _get_right_chnl_place_for_iqk(u8 chnl)
2157*4882a593Smuzhiyun {
2158*4882a593Smuzhiyun u8 channel_all[TARGET_CHNL_NUM_2G_5G] = {
2159*4882a593Smuzhiyun 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
2160*4882a593Smuzhiyun 13, 14, 36, 38, 40, 42, 44, 46,
2161*4882a593Smuzhiyun 48, 50, 52, 54, 56, 58, 60, 62, 64,
2162*4882a593Smuzhiyun 100, 102, 104, 106, 108, 110,
2163*4882a593Smuzhiyun 112, 114, 116, 118, 120, 122,
2164*4882a593Smuzhiyun 124, 126, 128, 130, 132, 134, 136,
2165*4882a593Smuzhiyun 138, 140, 149, 151, 153, 155, 157,
2166*4882a593Smuzhiyun 159, 161, 163, 165};
2167*4882a593Smuzhiyun u8 place = chnl;
2168*4882a593Smuzhiyun
2169*4882a593Smuzhiyun if (chnl > 14) {
2170*4882a593Smuzhiyun for (place = 14; place < sizeof(channel_all); place++) {
2171*4882a593Smuzhiyun if (channel_all[place] == chnl)
2172*4882a593Smuzhiyun return place - 13;
2173*4882a593Smuzhiyun }
2174*4882a593Smuzhiyun }
2175*4882a593Smuzhiyun return 0;
2176*4882a593Smuzhiyun }
2177*4882a593Smuzhiyun
_rtl8723be_phy_lc_calibrate(struct ieee80211_hw * hw,bool is2t)2178*4882a593Smuzhiyun static void _rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
2179*4882a593Smuzhiyun {
2180*4882a593Smuzhiyun u8 tmpreg;
2181*4882a593Smuzhiyun u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
2182*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2183*4882a593Smuzhiyun
2184*4882a593Smuzhiyun tmpreg = rtl_read_byte(rtlpriv, 0xd03);
2185*4882a593Smuzhiyun
2186*4882a593Smuzhiyun if ((tmpreg & 0x70) != 0)
2187*4882a593Smuzhiyun rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
2188*4882a593Smuzhiyun else
2189*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
2190*4882a593Smuzhiyun
2191*4882a593Smuzhiyun if ((tmpreg & 0x70) != 0) {
2192*4882a593Smuzhiyun rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS);
2193*4882a593Smuzhiyun
2194*4882a593Smuzhiyun if (is2t)
2195*4882a593Smuzhiyun rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
2196*4882a593Smuzhiyun MASK12BITS);
2197*4882a593Smuzhiyun
2198*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
2199*4882a593Smuzhiyun (rf_a_mode & 0x8FFFF) | 0x10000);
2200*4882a593Smuzhiyun
2201*4882a593Smuzhiyun if (is2t)
2202*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
2203*4882a593Smuzhiyun (rf_b_mode & 0x8FFFF) | 0x10000);
2204*4882a593Smuzhiyun }
2205*4882a593Smuzhiyun lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
2206*4882a593Smuzhiyun
2207*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, RFREG_OFFSET_MASK, 0xdfbe0);
2208*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, 0x8c0a);
2209*4882a593Smuzhiyun
2210*4882a593Smuzhiyun /* In order not to disturb BT music when wifi init.(1ant NIC only) */
2211*4882a593Smuzhiyun /*mdelay(100);*/
2212*4882a593Smuzhiyun /* In order not to disturb BT music when wifi init.(1ant NIC only) */
2213*4882a593Smuzhiyun mdelay(50);
2214*4882a593Smuzhiyun
2215*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, RFREG_OFFSET_MASK, 0xdffe0);
2216*4882a593Smuzhiyun
2217*4882a593Smuzhiyun if ((tmpreg & 0x70) != 0) {
2218*4882a593Smuzhiyun rtl_write_byte(rtlpriv, 0xd03, tmpreg);
2219*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
2220*4882a593Smuzhiyun
2221*4882a593Smuzhiyun if (is2t)
2222*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_B, 0x00,
2223*4882a593Smuzhiyun MASK12BITS, rf_b_mode);
2224*4882a593Smuzhiyun } else {
2225*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
2226*4882a593Smuzhiyun }
2227*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "\n");
2228*4882a593Smuzhiyun }
2229*4882a593Smuzhiyun
_rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw * hw,bool bmain,bool is2t)2230*4882a593Smuzhiyun static void _rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw,
2231*4882a593Smuzhiyun bool bmain, bool is2t)
2232*4882a593Smuzhiyun {
2233*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2234*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "\n");
2235*4882a593Smuzhiyun
2236*4882a593Smuzhiyun if (bmain) /* left antenna */
2237*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x92C, MASKDWORD, 0x1);
2238*4882a593Smuzhiyun else
2239*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x92C, MASKDWORD, 0x2);
2240*4882a593Smuzhiyun }
2241*4882a593Smuzhiyun
2242*4882a593Smuzhiyun #undef IQK_ADDA_REG_NUM
2243*4882a593Smuzhiyun #undef IQK_DELAY_TIME
2244*4882a593Smuzhiyun /* IQK is merge from Merge Temp */
rtl8723be_phy_iq_calibrate(struct ieee80211_hw * hw,bool b_recovery)2245*4882a593Smuzhiyun void rtl8723be_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery)
2246*4882a593Smuzhiyun {
2247*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2248*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
2249*4882a593Smuzhiyun long result[4][8];
2250*4882a593Smuzhiyun u8 i, final_candidate, idx;
2251*4882a593Smuzhiyun bool b_patha_ok, b_pathb_ok;
2252*4882a593Smuzhiyun long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4;
2253*4882a593Smuzhiyun long reg_tmp = 0;
2254*4882a593Smuzhiyun bool is12simular, is13simular, is23simular;
2255*4882a593Smuzhiyun u32 iqk_bb_reg[9] = {
2256*4882a593Smuzhiyun ROFDM0_XARXIQIMBALANCE,
2257*4882a593Smuzhiyun ROFDM0_XBRXIQIMBALANCE,
2258*4882a593Smuzhiyun ROFDM0_ECCATHRESHOLD,
2259*4882a593Smuzhiyun ROFDM0_AGCRSSITABLE,
2260*4882a593Smuzhiyun ROFDM0_XATXIQIMBALANCE,
2261*4882a593Smuzhiyun ROFDM0_XBTXIQIMBALANCE,
2262*4882a593Smuzhiyun ROFDM0_XCTXAFE,
2263*4882a593Smuzhiyun ROFDM0_XDTXAFE,
2264*4882a593Smuzhiyun ROFDM0_RXIQEXTANTA
2265*4882a593Smuzhiyun };
2266*4882a593Smuzhiyun u32 path_sel_bb = 0; /* path_sel_rf = 0 */
2267*4882a593Smuzhiyun
2268*4882a593Smuzhiyun if (rtlphy->lck_inprogress)
2269*4882a593Smuzhiyun return;
2270*4882a593Smuzhiyun
2271*4882a593Smuzhiyun spin_lock(&rtlpriv->locks.iqk_lock);
2272*4882a593Smuzhiyun rtlphy->lck_inprogress = true;
2273*4882a593Smuzhiyun spin_unlock(&rtlpriv->locks.iqk_lock);
2274*4882a593Smuzhiyun
2275*4882a593Smuzhiyun if (b_recovery) {
2276*4882a593Smuzhiyun rtl8723_phy_reload_adda_registers(hw, iqk_bb_reg,
2277*4882a593Smuzhiyun rtlphy->iqk_bb_backup, 9);
2278*4882a593Smuzhiyun goto label_done;
2279*4882a593Smuzhiyun }
2280*4882a593Smuzhiyun /* Save RF Path */
2281*4882a593Smuzhiyun path_sel_bb = rtl_get_bbreg(hw, 0x948, MASKDWORD);
2282*4882a593Smuzhiyun /* path_sel_rf = rtl_get_rfreg(hw, RF90_PATH_A, 0xb0, 0xfffff); */
2283*4882a593Smuzhiyun
2284*4882a593Smuzhiyun for (i = 0; i < 8; i++) {
2285*4882a593Smuzhiyun result[0][i] = 0;
2286*4882a593Smuzhiyun result[1][i] = 0;
2287*4882a593Smuzhiyun result[2][i] = 0;
2288*4882a593Smuzhiyun result[3][i] = 0;
2289*4882a593Smuzhiyun }
2290*4882a593Smuzhiyun final_candidate = 0xff;
2291*4882a593Smuzhiyun b_patha_ok = false;
2292*4882a593Smuzhiyun b_pathb_ok = false;
2293*4882a593Smuzhiyun is12simular = false;
2294*4882a593Smuzhiyun is23simular = false;
2295*4882a593Smuzhiyun is13simular = false;
2296*4882a593Smuzhiyun for (i = 0; i < 3; i++) {
2297*4882a593Smuzhiyun _rtl8723be_phy_iq_calibrate(hw, result, i, true);
2298*4882a593Smuzhiyun if (i == 1) {
2299*4882a593Smuzhiyun is12simular = _rtl8723be_phy_simularity_compare(hw,
2300*4882a593Smuzhiyun result,
2301*4882a593Smuzhiyun 0, 1);
2302*4882a593Smuzhiyun if (is12simular) {
2303*4882a593Smuzhiyun final_candidate = 0;
2304*4882a593Smuzhiyun break;
2305*4882a593Smuzhiyun }
2306*4882a593Smuzhiyun }
2307*4882a593Smuzhiyun if (i == 2) {
2308*4882a593Smuzhiyun is13simular = _rtl8723be_phy_simularity_compare(hw,
2309*4882a593Smuzhiyun result,
2310*4882a593Smuzhiyun 0, 2);
2311*4882a593Smuzhiyun if (is13simular) {
2312*4882a593Smuzhiyun final_candidate = 0;
2313*4882a593Smuzhiyun break;
2314*4882a593Smuzhiyun }
2315*4882a593Smuzhiyun is23simular = _rtl8723be_phy_simularity_compare(hw,
2316*4882a593Smuzhiyun result,
2317*4882a593Smuzhiyun 1, 2);
2318*4882a593Smuzhiyun if (is23simular) {
2319*4882a593Smuzhiyun final_candidate = 1;
2320*4882a593Smuzhiyun } else {
2321*4882a593Smuzhiyun for (i = 0; i < 8; i++)
2322*4882a593Smuzhiyun reg_tmp += result[3][i];
2323*4882a593Smuzhiyun
2324*4882a593Smuzhiyun if (reg_tmp != 0)
2325*4882a593Smuzhiyun final_candidate = 3;
2326*4882a593Smuzhiyun else
2327*4882a593Smuzhiyun final_candidate = 0xFF;
2328*4882a593Smuzhiyun }
2329*4882a593Smuzhiyun }
2330*4882a593Smuzhiyun }
2331*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
2332*4882a593Smuzhiyun reg_e94 = result[i][0];
2333*4882a593Smuzhiyun reg_e9c = result[i][1];
2334*4882a593Smuzhiyun reg_ea4 = result[i][2];
2335*4882a593Smuzhiyun reg_eb4 = result[i][4];
2336*4882a593Smuzhiyun reg_ebc = result[i][5];
2337*4882a593Smuzhiyun reg_ec4 = result[i][6];
2338*4882a593Smuzhiyun }
2339*4882a593Smuzhiyun if (final_candidate != 0xff) {
2340*4882a593Smuzhiyun reg_e94 = result[final_candidate][0];
2341*4882a593Smuzhiyun rtlphy->reg_e94 = reg_e94;
2342*4882a593Smuzhiyun reg_e9c = result[final_candidate][1];
2343*4882a593Smuzhiyun rtlphy->reg_e9c = reg_e9c;
2344*4882a593Smuzhiyun reg_ea4 = result[final_candidate][2];
2345*4882a593Smuzhiyun reg_eb4 = result[final_candidate][4];
2346*4882a593Smuzhiyun rtlphy->reg_eb4 = reg_eb4;
2347*4882a593Smuzhiyun reg_ebc = result[final_candidate][5];
2348*4882a593Smuzhiyun rtlphy->reg_ebc = reg_ebc;
2349*4882a593Smuzhiyun reg_ec4 = result[final_candidate][6];
2350*4882a593Smuzhiyun b_patha_ok = true;
2351*4882a593Smuzhiyun b_pathb_ok = true;
2352*4882a593Smuzhiyun } else {
2353*4882a593Smuzhiyun rtlphy->reg_e94 = 0x100;
2354*4882a593Smuzhiyun rtlphy->reg_eb4 = 0x100;
2355*4882a593Smuzhiyun rtlphy->reg_e9c = 0x0;
2356*4882a593Smuzhiyun rtlphy->reg_ebc = 0x0;
2357*4882a593Smuzhiyun }
2358*4882a593Smuzhiyun if (reg_e94 != 0)
2359*4882a593Smuzhiyun rtl8723_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result,
2360*4882a593Smuzhiyun final_candidate,
2361*4882a593Smuzhiyun (reg_ea4 == 0));
2362*4882a593Smuzhiyun if (reg_eb4 != 0)
2363*4882a593Smuzhiyun _rtl8723be_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok, result,
2364*4882a593Smuzhiyun final_candidate,
2365*4882a593Smuzhiyun (reg_ec4 == 0));
2366*4882a593Smuzhiyun
2367*4882a593Smuzhiyun idx = _get_right_chnl_place_for_iqk(rtlphy->current_channel);
2368*4882a593Smuzhiyun
2369*4882a593Smuzhiyun if (final_candidate < 4) {
2370*4882a593Smuzhiyun for (i = 0; i < IQK_MATRIX_REG_NUM; i++)
2371*4882a593Smuzhiyun rtlphy->iqk_matrix[idx].value[0][i] =
2372*4882a593Smuzhiyun result[final_candidate][i];
2373*4882a593Smuzhiyun rtlphy->iqk_matrix[idx].iqk_done = true;
2374*4882a593Smuzhiyun
2375*4882a593Smuzhiyun }
2376*4882a593Smuzhiyun rtl8723_save_adda_registers(hw, iqk_bb_reg,
2377*4882a593Smuzhiyun rtlphy->iqk_bb_backup, 9);
2378*4882a593Smuzhiyun
2379*4882a593Smuzhiyun rtl_set_bbreg(hw, 0x948, MASKDWORD, path_sel_bb);
2380*4882a593Smuzhiyun /* rtl_set_rfreg(hw, RF90_PATH_A, 0xb0, 0xfffff, path_sel_rf); */
2381*4882a593Smuzhiyun
2382*4882a593Smuzhiyun label_done:
2383*4882a593Smuzhiyun spin_lock(&rtlpriv->locks.iqk_lock);
2384*4882a593Smuzhiyun rtlphy->lck_inprogress = false;
2385*4882a593Smuzhiyun spin_unlock(&rtlpriv->locks.iqk_lock);
2386*4882a593Smuzhiyun }
2387*4882a593Smuzhiyun
rtl8723be_phy_lc_calibrate(struct ieee80211_hw * hw)2388*4882a593Smuzhiyun void rtl8723be_phy_lc_calibrate(struct ieee80211_hw *hw)
2389*4882a593Smuzhiyun {
2390*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2391*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
2392*4882a593Smuzhiyun struct rtl_hal *rtlhal = &rtlpriv->rtlhal;
2393*4882a593Smuzhiyun u32 timeout = 2000, timecount = 0;
2394*4882a593Smuzhiyun
2395*4882a593Smuzhiyun while (rtlpriv->mac80211.act_scanning && timecount < timeout) {
2396*4882a593Smuzhiyun udelay(50);
2397*4882a593Smuzhiyun timecount += 50;
2398*4882a593Smuzhiyun }
2399*4882a593Smuzhiyun
2400*4882a593Smuzhiyun rtlphy->lck_inprogress = true;
2401*4882a593Smuzhiyun RTPRINT(rtlpriv, FINIT, INIT_IQK,
2402*4882a593Smuzhiyun "LCK:Start!!! currentband %x delay %d ms\n",
2403*4882a593Smuzhiyun rtlhal->current_bandtype, timecount);
2404*4882a593Smuzhiyun
2405*4882a593Smuzhiyun _rtl8723be_phy_lc_calibrate(hw, false);
2406*4882a593Smuzhiyun
2407*4882a593Smuzhiyun rtlphy->lck_inprogress = false;
2408*4882a593Smuzhiyun }
2409*4882a593Smuzhiyun
rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw * hw,bool bmain)2410*4882a593Smuzhiyun void rtl8723be_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
2411*4882a593Smuzhiyun {
2412*4882a593Smuzhiyun _rtl8723be_phy_set_rfpath_switch(hw, bmain, true);
2413*4882a593Smuzhiyun }
2414*4882a593Smuzhiyun
rtl8723be_phy_set_io_cmd(struct ieee80211_hw * hw,enum io_type iotype)2415*4882a593Smuzhiyun bool rtl8723be_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
2416*4882a593Smuzhiyun {
2417*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2418*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
2419*4882a593Smuzhiyun bool b_postprocessing = false;
2420*4882a593Smuzhiyun
2421*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_CMD, DBG_TRACE,
2422*4882a593Smuzhiyun "-->IO Cmd(%#x), set_io_inprogress(%d)\n",
2423*4882a593Smuzhiyun iotype, rtlphy->set_io_inprogress);
2424*4882a593Smuzhiyun do {
2425*4882a593Smuzhiyun switch (iotype) {
2426*4882a593Smuzhiyun case IO_CMD_RESUME_DM_BY_SCAN:
2427*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_CMD, DBG_TRACE,
2428*4882a593Smuzhiyun "[IO CMD] Resume DM after scan.\n");
2429*4882a593Smuzhiyun b_postprocessing = true;
2430*4882a593Smuzhiyun break;
2431*4882a593Smuzhiyun case IO_CMD_PAUSE_BAND0_DM_BY_SCAN:
2432*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_CMD, DBG_TRACE,
2433*4882a593Smuzhiyun "[IO CMD] Pause DM before scan.\n");
2434*4882a593Smuzhiyun b_postprocessing = true;
2435*4882a593Smuzhiyun break;
2436*4882a593Smuzhiyun default:
2437*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
2438*4882a593Smuzhiyun "switch case %#x not processed\n", iotype);
2439*4882a593Smuzhiyun break;
2440*4882a593Smuzhiyun }
2441*4882a593Smuzhiyun } while (false);
2442*4882a593Smuzhiyun if (b_postprocessing && !rtlphy->set_io_inprogress) {
2443*4882a593Smuzhiyun rtlphy->set_io_inprogress = true;
2444*4882a593Smuzhiyun rtlphy->current_io_type = iotype;
2445*4882a593Smuzhiyun } else {
2446*4882a593Smuzhiyun return false;
2447*4882a593Smuzhiyun }
2448*4882a593Smuzhiyun rtl8723be_phy_set_io(hw);
2449*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype);
2450*4882a593Smuzhiyun return true;
2451*4882a593Smuzhiyun }
2452*4882a593Smuzhiyun
rtl8723be_phy_set_io(struct ieee80211_hw * hw)2453*4882a593Smuzhiyun static void rtl8723be_phy_set_io(struct ieee80211_hw *hw)
2454*4882a593Smuzhiyun {
2455*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2456*4882a593Smuzhiyun struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2457*4882a593Smuzhiyun struct rtl_phy *rtlphy = &rtlpriv->phy;
2458*4882a593Smuzhiyun
2459*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_CMD, DBG_TRACE,
2460*4882a593Smuzhiyun "--->Cmd(%#x), set_io_inprogress(%d)\n",
2461*4882a593Smuzhiyun rtlphy->current_io_type, rtlphy->set_io_inprogress);
2462*4882a593Smuzhiyun switch (rtlphy->current_io_type) {
2463*4882a593Smuzhiyun case IO_CMD_RESUME_DM_BY_SCAN:
2464*4882a593Smuzhiyun dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1;
2465*4882a593Smuzhiyun /*rtl92c_dm_write_dig(hw);*/
2466*4882a593Smuzhiyun rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel);
2467*4882a593Smuzhiyun rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x83);
2468*4882a593Smuzhiyun break;
2469*4882a593Smuzhiyun case IO_CMD_PAUSE_BAND0_DM_BY_SCAN:
2470*4882a593Smuzhiyun rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue;
2471*4882a593Smuzhiyun dm_digtable->cur_igvalue = 0x17;
2472*4882a593Smuzhiyun rtl_set_bbreg(hw, RCCK0_CCA, 0xff0000, 0x40);
2473*4882a593Smuzhiyun break;
2474*4882a593Smuzhiyun default:
2475*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
2476*4882a593Smuzhiyun "switch case %#x not processed\n",
2477*4882a593Smuzhiyun rtlphy->current_io_type);
2478*4882a593Smuzhiyun break;
2479*4882a593Smuzhiyun }
2480*4882a593Smuzhiyun rtlphy->set_io_inprogress = false;
2481*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_CMD, DBG_TRACE,
2482*4882a593Smuzhiyun "(%#x)\n", rtlphy->current_io_type);
2483*4882a593Smuzhiyun }
2484*4882a593Smuzhiyun
rtl8723be_phy_set_rf_on(struct ieee80211_hw * hw)2485*4882a593Smuzhiyun static void rtl8723be_phy_set_rf_on(struct ieee80211_hw *hw)
2486*4882a593Smuzhiyun {
2487*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2488*4882a593Smuzhiyun
2489*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
2490*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
2491*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
2492*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
2493*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
2494*4882a593Smuzhiyun }
2495*4882a593Smuzhiyun
_rtl8723be_phy_set_rf_sleep(struct ieee80211_hw * hw)2496*4882a593Smuzhiyun static void _rtl8723be_phy_set_rf_sleep(struct ieee80211_hw *hw)
2497*4882a593Smuzhiyun {
2498*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2499*4882a593Smuzhiyun
2500*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
2501*4882a593Smuzhiyun rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
2502*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
2503*4882a593Smuzhiyun rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
2504*4882a593Smuzhiyun }
2505*4882a593Smuzhiyun
_rtl8723be_phy_set_rf_power_state(struct ieee80211_hw * hw,enum rf_pwrstate rfpwr_state)2506*4882a593Smuzhiyun static bool _rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw,
2507*4882a593Smuzhiyun enum rf_pwrstate rfpwr_state)
2508*4882a593Smuzhiyun {
2509*4882a593Smuzhiyun struct rtl_priv *rtlpriv = rtl_priv(hw);
2510*4882a593Smuzhiyun struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
2511*4882a593Smuzhiyun struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2512*4882a593Smuzhiyun struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
2513*4882a593Smuzhiyun bool bresult = true;
2514*4882a593Smuzhiyun u8 i, queue_id;
2515*4882a593Smuzhiyun struct rtl8192_tx_ring *ring = NULL;
2516*4882a593Smuzhiyun
2517*4882a593Smuzhiyun switch (rfpwr_state) {
2518*4882a593Smuzhiyun case ERFON:
2519*4882a593Smuzhiyun if ((ppsc->rfpwr_state == ERFOFF) &&
2520*4882a593Smuzhiyun RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
2521*4882a593Smuzhiyun bool rtstatus;
2522*4882a593Smuzhiyun u32 initializecount = 0;
2523*4882a593Smuzhiyun do {
2524*4882a593Smuzhiyun initializecount++;
2525*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
2526*4882a593Smuzhiyun "IPS Set eRf nic enable\n");
2527*4882a593Smuzhiyun rtstatus = rtl_ps_enable_nic(hw);
2528*4882a593Smuzhiyun } while (!rtstatus && (initializecount < 10));
2529*4882a593Smuzhiyun RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
2530*4882a593Smuzhiyun } else {
2531*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
2532*4882a593Smuzhiyun "Set ERFON slept:%d ms\n",
2533*4882a593Smuzhiyun jiffies_to_msecs(jiffies -
2534*4882a593Smuzhiyun ppsc->last_sleep_jiffies));
2535*4882a593Smuzhiyun ppsc->last_awake_jiffies = jiffies;
2536*4882a593Smuzhiyun rtl8723be_phy_set_rf_on(hw);
2537*4882a593Smuzhiyun }
2538*4882a593Smuzhiyun if (mac->link_state == MAC80211_LINKED)
2539*4882a593Smuzhiyun rtlpriv->cfg->ops->led_control(hw, LED_CTL_LINK);
2540*4882a593Smuzhiyun else
2541*4882a593Smuzhiyun rtlpriv->cfg->ops->led_control(hw, LED_CTL_NO_LINK);
2542*4882a593Smuzhiyun
2543*4882a593Smuzhiyun break;
2544*4882a593Smuzhiyun
2545*4882a593Smuzhiyun case ERFOFF:
2546*4882a593Smuzhiyun for (queue_id = 0, i = 0;
2547*4882a593Smuzhiyun queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
2548*4882a593Smuzhiyun ring = &pcipriv->dev.tx_ring[queue_id];
2549*4882a593Smuzhiyun /* Don't check BEACON Q.
2550*4882a593Smuzhiyun * BEACON Q is always not empty,
2551*4882a593Smuzhiyun * because '_rtl8723be_cmd_send_packet'
2552*4882a593Smuzhiyun */
2553*4882a593Smuzhiyun if (queue_id == BEACON_QUEUE ||
2554*4882a593Smuzhiyun skb_queue_len(&ring->queue) == 0) {
2555*4882a593Smuzhiyun queue_id++;
2556*4882a593Smuzhiyun continue;
2557*4882a593Smuzhiyun } else {
2558*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
2559*4882a593Smuzhiyun "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
2560*4882a593Smuzhiyun (i + 1), queue_id,
2561*4882a593Smuzhiyun skb_queue_len(&ring->queue));
2562*4882a593Smuzhiyun
2563*4882a593Smuzhiyun udelay(10);
2564*4882a593Smuzhiyun i++;
2565*4882a593Smuzhiyun }
2566*4882a593Smuzhiyun if (i >= MAX_DOZE_WAITING_TIMES_9x) {
2567*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
2568*4882a593Smuzhiyun "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
2569*4882a593Smuzhiyun MAX_DOZE_WAITING_TIMES_9x,
2570*4882a593Smuzhiyun queue_id,
2571*4882a593Smuzhiyun skb_queue_len(&ring->queue));
2572*4882a593Smuzhiyun break;
2573*4882a593Smuzhiyun }
2574*4882a593Smuzhiyun }
2575*4882a593Smuzhiyun
2576*4882a593Smuzhiyun if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
2577*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
2578*4882a593Smuzhiyun "IPS Set eRf nic disable\n");
2579*4882a593Smuzhiyun rtl_ps_disable_nic(hw);
2580*4882a593Smuzhiyun RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
2581*4882a593Smuzhiyun } else {
2582*4882a593Smuzhiyun if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
2583*4882a593Smuzhiyun rtlpriv->cfg->ops->led_control(hw,
2584*4882a593Smuzhiyun LED_CTL_NO_LINK);
2585*4882a593Smuzhiyun } else {
2586*4882a593Smuzhiyun rtlpriv->cfg->ops->led_control(hw,
2587*4882a593Smuzhiyun LED_CTL_POWER_OFF);
2588*4882a593Smuzhiyun }
2589*4882a593Smuzhiyun }
2590*4882a593Smuzhiyun break;
2591*4882a593Smuzhiyun
2592*4882a593Smuzhiyun case ERFSLEEP:
2593*4882a593Smuzhiyun if (ppsc->rfpwr_state == ERFOFF)
2594*4882a593Smuzhiyun break;
2595*4882a593Smuzhiyun for (queue_id = 0, i = 0;
2596*4882a593Smuzhiyun queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
2597*4882a593Smuzhiyun ring = &pcipriv->dev.tx_ring[queue_id];
2598*4882a593Smuzhiyun if (skb_queue_len(&ring->queue) == 0) {
2599*4882a593Smuzhiyun queue_id++;
2600*4882a593Smuzhiyun continue;
2601*4882a593Smuzhiyun } else {
2602*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
2603*4882a593Smuzhiyun "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
2604*4882a593Smuzhiyun (i + 1), queue_id,
2605*4882a593Smuzhiyun skb_queue_len(&ring->queue));
2606*4882a593Smuzhiyun
2607*4882a593Smuzhiyun udelay(10);
2608*4882a593Smuzhiyun i++;
2609*4882a593Smuzhiyun }
2610*4882a593Smuzhiyun if (i >= MAX_DOZE_WAITING_TIMES_9x) {
2611*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
2612*4882a593Smuzhiyun "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
2613*4882a593Smuzhiyun MAX_DOZE_WAITING_TIMES_9x,
2614*4882a593Smuzhiyun queue_id,
2615*4882a593Smuzhiyun skb_queue_len(&ring->queue));
2616*4882a593Smuzhiyun break;
2617*4882a593Smuzhiyun }
2618*4882a593Smuzhiyun }
2619*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_RF, DBG_DMESG,
2620*4882a593Smuzhiyun "Set ERFSLEEP awaked:%d ms\n",
2621*4882a593Smuzhiyun jiffies_to_msecs(jiffies -
2622*4882a593Smuzhiyun ppsc->last_awake_jiffies));
2623*4882a593Smuzhiyun ppsc->last_sleep_jiffies = jiffies;
2624*4882a593Smuzhiyun _rtl8723be_phy_set_rf_sleep(hw);
2625*4882a593Smuzhiyun break;
2626*4882a593Smuzhiyun
2627*4882a593Smuzhiyun default:
2628*4882a593Smuzhiyun rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
2629*4882a593Smuzhiyun "switch case %#x not processed\n", rfpwr_state);
2630*4882a593Smuzhiyun bresult = false;
2631*4882a593Smuzhiyun break;
2632*4882a593Smuzhiyun }
2633*4882a593Smuzhiyun if (bresult)
2634*4882a593Smuzhiyun ppsc->rfpwr_state = rfpwr_state;
2635*4882a593Smuzhiyun return bresult;
2636*4882a593Smuzhiyun }
2637*4882a593Smuzhiyun
rtl8723be_phy_set_rf_power_state(struct ieee80211_hw * hw,enum rf_pwrstate rfpwr_state)2638*4882a593Smuzhiyun bool rtl8723be_phy_set_rf_power_state(struct ieee80211_hw *hw,
2639*4882a593Smuzhiyun enum rf_pwrstate rfpwr_state)
2640*4882a593Smuzhiyun {
2641*4882a593Smuzhiyun struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
2642*4882a593Smuzhiyun
2643*4882a593Smuzhiyun bool bresult = false;
2644*4882a593Smuzhiyun
2645*4882a593Smuzhiyun if (rfpwr_state == ppsc->rfpwr_state)
2646*4882a593Smuzhiyun return bresult;
2647*4882a593Smuzhiyun bresult = _rtl8723be_phy_set_rf_power_state(hw, rfpwr_state);
2648*4882a593Smuzhiyun return bresult;
2649*4882a593Smuzhiyun }
2650