1 /******************************************************************************
3 * Copyright(c) 2009-2014 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
33 #include "../rtl8723com/dm_common.h"
36 #include "../btcoexist/rtl_btc.h"
38 static const u32 ofdmswing_table[] = {
39 0x0b40002d, /* 0, -15.0dB */
40 0x0c000030, /* 1, -14.5dB */
41 0x0cc00033, /* 2, -14.0dB */
42 0x0d800036, /* 3, -13.5dB */
43 0x0e400039, /* 4, -13.0dB */
44 0x0f00003c, /* 5, -12.5dB */
45 0x10000040, /* 6, -12.0dB */
46 0x11000044, /* 7, -11.5dB */
47 0x12000048, /* 8, -11.0dB */
48 0x1300004c, /* 9, -10.5dB */
49 0x14400051, /* 10, -10.0dB */
50 0x15800056, /* 11, -9.5dB */
51 0x16c0005b, /* 12, -9.0dB */
52 0x18000060, /* 13, -8.5dB */
53 0x19800066, /* 14, -8.0dB */
54 0x1b00006c, /* 15, -7.5dB */
55 0x1c800072, /* 16, -7.0dB */
56 0x1e400079, /* 17, -6.5dB */
57 0x20000080, /* 18, -6.0dB */
58 0x22000088, /* 19, -5.5dB */
59 0x24000090, /* 20, -5.0dB */
60 0x26000098, /* 21, -4.5dB */
61 0x288000a2, /* 22, -4.0dB */
62 0x2ac000ab, /* 23, -3.5dB */
63 0x2d4000b5, /* 24, -3.0dB */
64 0x300000c0, /* 25, -2.5dB */
65 0x32c000cb, /* 26, -2.0dB */
66 0x35c000d7, /* 27, -1.5dB */
67 0x390000e4, /* 28, -1.0dB */
68 0x3c8000f2, /* 29, -0.5dB */
69 0x40000100, /* 30, +0dB */
70 0x43c0010f, /* 31, +0.5dB */
71 0x47c0011f, /* 32, +1.0dB */
72 0x4c000130, /* 33, +1.5dB */
73 0x50800142, /* 34, +2.0dB */
74 0x55400155, /* 35, +2.5dB */
75 0x5a400169, /* 36, +3.0dB */
76 0x5fc0017f, /* 37, +3.5dB */
77 0x65400195, /* 38, +4.0dB */
78 0x6b8001ae, /* 39, +4.5dB */
79 0x71c001c7, /* 40, +5.0dB */
80 0x788001e2, /* 41, +5.5dB */
81 0x7f8001fe /* 42, +6.0dB */
84 static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
85 {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */
86 {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */
87 {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */
88 {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */
89 {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */
90 {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */
91 {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */
92 {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */
93 {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */
94 {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */
95 {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */
96 {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */
97 {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */
98 {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */
99 {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */
100 {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */
101 {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
102 {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */
103 {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */
104 {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */
105 {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */
106 {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */
107 {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */
108 {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */
109 {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */
110 {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */
111 {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */
112 {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */
113 {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */
114 {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */
115 {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */
116 {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */
117 {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */
120 static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
121 {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */
122 {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */
123 {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */
124 {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */
125 {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */
126 {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */
127 {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */
128 {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */
129 {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */
130 {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */
131 {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */
132 {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */
133 {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */
134 {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */
135 {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */
136 {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */
137 {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
138 {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */
139 {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */
140 {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */
141 {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */
142 {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */
143 {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */
144 {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */
145 {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */
146 {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */
147 {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */
148 {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */
149 {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */
150 {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */
151 {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */
152 {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */
153 {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */
156 static const u32 edca_setting_dl[PEER_MAX] = {
157 0xa44f, /* 0 UNKNOWN */
158 0x5ea44f, /* 1 REALTEK_90 */
159 0x5e4322, /* 2 REALTEK_92SE */
160 0x5ea42b, /* 3 BROAD */
163 0x5ea630, /* 6 CISCO */
164 0x5ea42b, /* 7 MARVELL */
167 static const u32 edca_setting_ul[PEER_MAX] = {
168 0x5e4322, /* 0 UNKNOWN */
169 0xa44f, /* 1 REALTEK_90 */
170 0x5ea44f, /* 2 REALTEK_92SE */
171 0x5ea32b, /* 3 BROAD */
172 0x5ea422, /* 4 RAL */
173 0x5ea322, /* 5 ATH */
174 0x3ea430, /* 6 CISCO */
175 0x5ea44f, /* 7 MARV */
178 void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type,
179 u8 *pdirection, u32 *poutwrite_val)
181 struct rtl_priv *rtlpriv = rtl_priv(hw);
182 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
184 u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A];
185 u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
186 u8 cck_base = rtldm->swing_idx_cck_base;
187 u8 cck_val = rtldm->swing_idx_cck;
190 if (ofdm_val <= ofdm_base) {
192 pwr_val = ofdm_base - ofdm_val;
195 pwr_val = ofdm_val - ofdm_base;
197 } else if (type == 1) {
198 if (cck_val <= cck_base) {
200 pwr_val = cck_base - cck_val;
203 pwr_val = cck_val - cck_base;
207 if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
208 pwr_val = TXPWRTRACK_MAX_IDX;
210 *poutwrite_val = pwr_val | (pwr_val << 8) |
211 (pwr_val << 16) | (pwr_val << 24);
214 static void rtl8723be_dm_diginit(struct ieee80211_hw *hw)
216 struct rtl_priv *rtlpriv = rtl_priv(hw);
217 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
219 dm_digtable->dig_enable_flag = true;
220 dm_digtable->cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
221 dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
222 dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
223 dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
224 dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
225 dm_digtable->rx_gain_max = DM_DIG_MAX;
226 dm_digtable->rx_gain_min = DM_DIG_MIN;
227 dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
228 dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
229 dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
230 dm_digtable->pre_cck_cca_thres = 0xff;
231 dm_digtable->cur_cck_cca_thres = 0x83;
232 dm_digtable->forbidden_igi = DM_DIG_MIN;
233 dm_digtable->large_fa_hit = 0;
234 dm_digtable->recover_cnt = 0;
235 dm_digtable->dig_dynamic_min = DM_DIG_MIN;
236 dm_digtable->dig_dynamic_min_1 = DM_DIG_MIN;
237 dm_digtable->media_connect_0 = false;
238 dm_digtable->media_connect_1 = false;
239 rtlpriv->dm.dm_initialgain_enable = true;
240 dm_digtable->bt30_cur_igi = 0x32;
243 void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
245 struct rtl_priv *rtlpriv = rtl_priv(hw);
246 struct rate_adaptive *p_ra = &rtlpriv->ra;
248 p_ra->ratr_state = DM_RATR_STA_INIT;
249 p_ra->pre_ratr_state = DM_RATR_STA_INIT;
251 if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
252 rtlpriv->dm.useramask = true;
254 rtlpriv->dm.useramask = false;
256 p_ra->high_rssi_thresh_for_ra = 50;
257 p_ra->low_rssi_thresh_for_ra40m = 20;
260 static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw)
262 struct rtl_priv *rtlpriv = rtl_priv(hw);
264 rtlpriv->dm.txpower_tracking = true;
265 rtlpriv->dm.txpower_track_control = true;
266 rtlpriv->dm.thermalvalue = 0;
268 rtlpriv->dm.ofdm_index[0] = 30;
269 rtlpriv->dm.cck_index = 20;
271 rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index;
273 rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0];
274 rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0;
275 rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0;
276 rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0;
278 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
279 " rtlpriv->dm.txpower_tracking = %d\n",
280 rtlpriv->dm.txpower_tracking);
283 static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
285 struct rtl_priv *rtlpriv = rtl_priv(hw);
287 rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
289 rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800);
290 rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
293 void rtl8723be_dm_init(struct ieee80211_hw *hw)
295 struct rtl_priv *rtlpriv = rtl_priv(hw);
297 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
298 rtl8723be_dm_diginit(hw);
299 rtl8723be_dm_init_rate_adaptive_mask(hw);
300 rtl8723_dm_init_edca_turbo(hw);
301 rtl8723_dm_init_dynamic_bb_powersaving(hw);
302 rtl8723_dm_init_dynamic_txpower(hw);
303 rtl8723be_dm_init_txpower_tracking(hw);
304 rtl8723be_dm_init_dynamic_atc_switch(hw);
307 static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw)
309 struct rtl_priv *rtlpriv = rtl_priv(hw);
310 struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
311 struct rtl_mac *mac = rtl_mac(rtlpriv);
313 /* Determine the minimum RSSI */
314 if ((mac->link_state < MAC80211_LINKED) &&
315 (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
316 rtl_dm_dig->min_undec_pwdb_for_dm = 0;
317 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
318 "Not connected to any\n");
320 if (mac->link_state >= MAC80211_LINKED) {
321 if (mac->opmode == NL80211_IFTYPE_AP ||
322 mac->opmode == NL80211_IFTYPE_ADHOC) {
323 rtl_dm_dig->min_undec_pwdb_for_dm =
324 rtlpriv->dm.entry_min_undec_sm_pwdb;
325 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
326 "AP Client PWDB = 0x%lx\n",
327 rtlpriv->dm.entry_min_undec_sm_pwdb);
329 rtl_dm_dig->min_undec_pwdb_for_dm =
330 rtlpriv->dm.undec_sm_pwdb;
331 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
332 "STA Default Port PWDB = 0x%x\n",
333 rtl_dm_dig->min_undec_pwdb_for_dm);
336 rtl_dm_dig->min_undec_pwdb_for_dm =
337 rtlpriv->dm.entry_min_undec_sm_pwdb;
338 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
339 "AP Ext Port or disconnect PWDB = 0x%x\n",
340 rtl_dm_dig->min_undec_pwdb_for_dm);
342 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
343 rtl_dm_dig->min_undec_pwdb_for_dm);
346 static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw)
348 struct rtl_priv *rtlpriv = rtl_priv(hw);
349 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
350 struct rtl_sta_info *drv_priv;
351 u8 h2c_parameter[3] = { 0 };
352 long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
354 /* AP & ADHOC & MESH */
355 spin_lock_bh(&rtlpriv->locks.entry_list_lock);
356 list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
357 if (drv_priv->rssi_stat.undec_sm_pwdb <
360 drv_priv->rssi_stat.undec_sm_pwdb;
361 if (drv_priv->rssi_stat.undec_sm_pwdb >
364 drv_priv->rssi_stat.undec_sm_pwdb;
366 spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
368 /* If associated entry is found */
369 if (tmp_entry_max_pwdb != 0) {
370 rtlpriv->dm.entry_max_undec_sm_pwdb =
372 RTPRINT(rtlpriv, FDM, DM_PWDB,
373 "EntryMaxPWDB = 0x%lx(%ld)\n",
374 tmp_entry_max_pwdb, tmp_entry_max_pwdb);
376 rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
378 /* If associated entry is found */
379 if (tmp_entry_min_pwdb != 0xff) {
380 rtlpriv->dm.entry_min_undec_sm_pwdb =
382 RTPRINT(rtlpriv, FDM, DM_PWDB,
383 "EntryMinPWDB = 0x%lx(%ld)\n",
384 tmp_entry_min_pwdb, tmp_entry_min_pwdb);
386 rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
388 /* Indicate Rx signal strength to FW. */
389 if (rtlpriv->dm.useramask) {
391 (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
392 h2c_parameter[1] = 0x20;
393 h2c_parameter[0] = 0;
394 rtl8723be_fill_h2c_cmd(hw, H2C_RSSIBE_REPORT, 3, h2c_parameter);
396 rtl_write_byte(rtlpriv, 0x4fe,
397 rtlpriv->dm.undec_sm_pwdb);
399 rtl8723be_dm_find_minimum_rssi(hw);
400 dm_digtable->rssi_val_min =
401 rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
404 void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
406 struct rtl_priv *rtlpriv = rtl_priv(hw);
407 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
409 if (dm_digtable->stop_dig)
412 if (dm_digtable->cur_igvalue != current_igi) {
413 rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi);
414 if (rtlpriv->phy.rf_type != RF_1T1R)
415 rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1,
418 dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
419 dm_digtable->cur_igvalue = current_igi;
422 static void rtl8723be_dm_dig(struct ieee80211_hw *hw)
424 struct rtl_priv *rtlpriv = rtl_priv(hw);
425 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
426 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
427 u8 dig_dynamic_min, dig_maxofmin;
428 bool bfirstconnect, bfirstdisconnect;
429 u8 dm_dig_max, dm_dig_min;
430 u8 current_igi = dm_digtable->cur_igvalue;
434 if (mac->act_scanning)
437 dig_dynamic_min = dm_digtable->dig_dynamic_min;
438 bfirstconnect = (mac->link_state >= MAC80211_LINKED) &&
439 !dm_digtable->media_connect_0;
440 bfirstdisconnect = (mac->link_state < MAC80211_LINKED) &&
441 (dm_digtable->media_connect_0);
444 dm_dig_min = DM_DIG_MIN;
445 dig_maxofmin = DM_DIG_MAX_AP;
447 if (mac->link_state >= MAC80211_LINKED) {
448 if ((dm_digtable->rssi_val_min + 10) > dm_dig_max)
449 dm_digtable->rx_gain_max = dm_dig_max;
450 else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min)
451 dm_digtable->rx_gain_max = dm_dig_min;
453 dm_digtable->rx_gain_max =
454 dm_digtable->rssi_val_min + 10;
456 if (rtlpriv->dm.one_entry_only) {
458 if (dm_digtable->rssi_val_min - offset < dm_dig_min)
459 dig_dynamic_min = dm_dig_min;
460 else if (dm_digtable->rssi_val_min - offset >
462 dig_dynamic_min = dig_maxofmin;
465 dm_digtable->rssi_val_min - offset;
467 dig_dynamic_min = dm_dig_min;
471 dm_digtable->rx_gain_max = dm_dig_max;
472 dig_dynamic_min = dm_dig_min;
473 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
476 if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
477 if (dm_digtable->large_fa_hit != 3)
478 dm_digtable->large_fa_hit++;
479 if (dm_digtable->forbidden_igi < current_igi) {
480 dm_digtable->forbidden_igi = current_igi;
481 dm_digtable->large_fa_hit = 1;
484 if (dm_digtable->large_fa_hit >= 3) {
485 if ((dm_digtable->forbidden_igi + 1) >
486 dm_digtable->rx_gain_max)
487 dm_digtable->rx_gain_min =
488 dm_digtable->rx_gain_max;
490 dm_digtable->rx_gain_min =
491 dm_digtable->forbidden_igi + 1;
492 dm_digtable->recover_cnt = 3600;
495 if (dm_digtable->recover_cnt != 0) {
496 dm_digtable->recover_cnt--;
498 if (dm_digtable->large_fa_hit < 3) {
499 if ((dm_digtable->forbidden_igi - 1) <
501 dm_digtable->forbidden_igi =
503 dm_digtable->rx_gain_min =
506 dm_digtable->forbidden_igi--;
507 dm_digtable->rx_gain_min =
508 dm_digtable->forbidden_igi + 1;
511 dm_digtable->large_fa_hit = 0;
515 if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
516 dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
518 if (mac->link_state >= MAC80211_LINKED) {
520 if (dm_digtable->rssi_val_min <= dig_maxofmin)
521 current_igi = dm_digtable->rssi_val_min;
523 current_igi = dig_maxofmin;
525 dm_digtable->large_fa_hit = 0;
527 if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
529 else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
531 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
535 if (bfirstdisconnect) {
536 current_igi = dm_digtable->rx_gain_min;
538 if (rtlpriv->falsealm_cnt.cnt_all > 10000)
540 else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
542 else if (rtlpriv->falsealm_cnt.cnt_all < 500)
547 if (current_igi > dm_digtable->rx_gain_max)
548 current_igi = dm_digtable->rx_gain_max;
549 else if (current_igi < dm_digtable->rx_gain_min)
550 current_igi = dm_digtable->rx_gain_min;
552 rtl8723be_dm_write_dig(hw, current_igi);
553 dm_digtable->media_connect_0 =
554 ((mac->link_state >= MAC80211_LINKED) ? true : false);
555 dm_digtable->dig_dynamic_min = dig_dynamic_min;
558 static void rtl8723be_dm_false_alarm_counter_statistics(
559 struct ieee80211_hw *hw)
562 struct rtl_priv *rtlpriv = rtl_priv(hw);
563 struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
565 rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
566 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
568 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD);
569 falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff;
570 falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16;
572 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD);
573 falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff;
574 falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16;
576 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD);
577 falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff;
578 falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16;
580 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD);
581 falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff;
583 falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
584 falsealm_cnt->cnt_rate_illegal +
585 falsealm_cnt->cnt_crc8_fail +
586 falsealm_cnt->cnt_mcs_fail +
587 falsealm_cnt->cnt_fast_fsync_fail +
588 falsealm_cnt->cnt_sb_search_fail;
590 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1);
591 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1);
593 ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0);
594 falsealm_cnt->cnt_cck_fail = ret_value;
596 ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3);
597 falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
599 ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD);
600 falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
601 ((ret_value & 0xff00) >> 8);
603 falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
604 falsealm_cnt->cnt_sb_search_fail +
605 falsealm_cnt->cnt_parity_fail +
606 falsealm_cnt->cnt_rate_illegal +
607 falsealm_cnt->cnt_crc8_fail +
608 falsealm_cnt->cnt_mcs_fail +
609 falsealm_cnt->cnt_cck_fail;
611 falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca +
612 falsealm_cnt->cnt_cck_cca;
614 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
615 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
616 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
617 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
619 rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
620 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
622 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
623 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
625 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
626 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
628 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
629 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
630 falsealm_cnt->cnt_parity_fail,
631 falsealm_cnt->cnt_rate_illegal,
632 falsealm_cnt->cnt_crc8_fail,
633 falsealm_cnt->cnt_mcs_fail);
635 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
636 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
637 falsealm_cnt->cnt_ofdm_fail,
638 falsealm_cnt->cnt_cck_fail,
639 falsealm_cnt->cnt_all);
642 static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw)
644 /* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/
648 static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index,
649 u8 rfpath, long iqk_result_x,
652 long ele_a = 0, ele_d, ele_c = 0, value32;
654 if (ofdm_index >= 43)
657 ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22;
659 if (iqk_result_x != 0) {
660 if ((iqk_result_x & 0x00000200) != 0)
661 iqk_result_x = iqk_result_x | 0xFFFFFC00;
662 ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF;
664 if ((iqk_result_y & 0x00000200) != 0)
665 iqk_result_y = iqk_result_y | 0xFFFFFC00;
666 ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF;
670 value32 = (ele_d << 22) |
671 ((ele_c & 0x3F) << 16) | ele_a;
672 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
674 value32 = (ele_c & 0x000003C0) >> 6;
675 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
676 value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
677 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
686 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
687 ofdmswing_table[ofdm_index]);
688 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
689 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00);
697 static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw,
698 enum pwr_track_control_method method,
701 struct rtl_priv *rtlpriv = rtl_priv(hw);
702 struct rtl_phy *rtlphy = &rtlpriv->phy;
703 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
704 u8 swing_idx_ofdm_limit = 36;
706 if (method == TXAGC) {
707 rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel);
708 } else if (method == BBSWING) {
709 if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE)
710 rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1;
712 if (!rtldm->cck_inch14) {
713 rtl_write_byte(rtlpriv, 0xa22,
714 cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]);
715 rtl_write_byte(rtlpriv, 0xa23,
716 cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]);
717 rtl_write_byte(rtlpriv, 0xa24,
718 cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]);
719 rtl_write_byte(rtlpriv, 0xa25,
720 cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]);
721 rtl_write_byte(rtlpriv, 0xa26,
722 cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]);
723 rtl_write_byte(rtlpriv, 0xa27,
724 cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]);
725 rtl_write_byte(rtlpriv, 0xa28,
726 cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]);
727 rtl_write_byte(rtlpriv, 0xa29,
728 cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]);
730 rtl_write_byte(rtlpriv, 0xa22,
731 cckswing_table_ch14[rtldm->swing_idx_cck][0]);
732 rtl_write_byte(rtlpriv, 0xa23,
733 cckswing_table_ch14[rtldm->swing_idx_cck][1]);
734 rtl_write_byte(rtlpriv, 0xa24,
735 cckswing_table_ch14[rtldm->swing_idx_cck][2]);
736 rtl_write_byte(rtlpriv, 0xa25,
737 cckswing_table_ch14[rtldm->swing_idx_cck][3]);
738 rtl_write_byte(rtlpriv, 0xa26,
739 cckswing_table_ch14[rtldm->swing_idx_cck][4]);
740 rtl_write_byte(rtlpriv, 0xa27,
741 cckswing_table_ch14[rtldm->swing_idx_cck][5]);
742 rtl_write_byte(rtlpriv, 0xa28,
743 cckswing_table_ch14[rtldm->swing_idx_cck][6]);
744 rtl_write_byte(rtlpriv, 0xa29,
745 cckswing_table_ch14[rtldm->swing_idx_cck][7]);
748 if (rfpath == RF90_PATH_A) {
749 if (rtldm->swing_idx_ofdm[RF90_PATH_A] <
750 swing_idx_ofdm_limit)
751 swing_idx_ofdm_limit =
752 rtldm->swing_idx_ofdm[RF90_PATH_A];
754 rtl8723be_set_iqk_matrix(hw,
755 rtldm->swing_idx_ofdm[rfpath], rfpath,
756 rtlphy->iqk_matrix[idx].value[0][0],
757 rtlphy->iqk_matrix[idx].value[0][1]);
758 } else if (rfpath == RF90_PATH_B) {
759 if (rtldm->swing_idx_ofdm[RF90_PATH_B] <
760 swing_idx_ofdm_limit)
761 swing_idx_ofdm_limit =
762 rtldm->swing_idx_ofdm[RF90_PATH_B];
764 rtl8723be_set_iqk_matrix(hw,
765 rtldm->swing_idx_ofdm[rfpath], rfpath,
766 rtlphy->iqk_matrix[idx].value[0][4],
767 rtlphy->iqk_matrix[idx].value[0][5]);
774 static void rtl8723be_dm_txpower_tracking_callback_thermalmeter(
775 struct ieee80211_hw *hw)
777 struct rtl_priv *rtlpriv = rtl_priv(hw);
778 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
779 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
780 u8 thermalvalue = 0, delta, delta_lck, delta_iqk;
781 u8 thermalvalue_avg_count = 0;
782 u32 thermalvalue_avg = 0;
785 u8 ofdm_min_index = 6;
786 u8 index_for_channel = 0;
788 char delta_swing_table_idx_tup_a[TXSCALE_TABLE_SIZE] = {
789 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5,
790 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10,
791 10, 11, 11, 12, 12, 13, 14, 15};
792 char delta_swing_table_idx_tdown_a[TXSCALE_TABLE_SIZE] = {
793 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5,
794 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9,
795 9, 10, 10, 11, 12, 13, 14, 15};
797 /*Initilization ( 7 steps in total )*/
798 rtlpriv->dm.txpower_trackinginit = true;
799 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
800 "rtl8723be_dm_txpower_tracking_callback_thermalmeter\n");
802 thermalvalue = (u8)rtl_get_rfreg(hw,
803 RF90_PATH_A, RF_T_METER, 0xfc00);
804 if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 ||
805 rtlefuse->eeprom_thermalmeter == 0xFF)
807 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
808 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
809 thermalvalue, rtldm->thermalvalue,
810 rtlefuse->eeprom_thermalmeter);
811 /*3 Initialize ThermalValues of RFCalibrateInfo*/
812 if (!rtldm->thermalvalue) {
813 rtlpriv->dm.thermalvalue_lck = thermalvalue;
814 rtlpriv->dm.thermalvalue_iqk = thermalvalue;
817 /*4 Calculate average thermal meter*/
818 rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
819 rtldm->thermalvalue_avg_index++;
820 if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE)
821 rtldm->thermalvalue_avg_index = 0;
823 for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) {
824 if (rtldm->thermalvalue_avg[i]) {
825 thermalvalue_avg += rtldm->thermalvalue_avg[i];
826 thermalvalue_avg_count++;
830 if (thermalvalue_avg_count)
831 thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count);
833 /* 5 Calculate delta, delta_LCK, delta_IQK.*/
834 delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
835 (thermalvalue - rtlpriv->dm.thermalvalue) :
836 (rtlpriv->dm.thermalvalue - thermalvalue);
837 delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
838 (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
839 (rtlpriv->dm.thermalvalue_lck - thermalvalue);
840 delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
841 (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
842 (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
844 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
845 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n",
846 thermalvalue, rtlpriv->dm.thermalvalue,
847 rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk);
848 /* 6 If necessary, do LCK.*/
849 if (delta_lck >= IQK_THRESHOLD) {
850 rtlpriv->dm.thermalvalue_lck = thermalvalue;
851 rtl8723be_phy_lc_calibrate(hw);
854 /* 7 If necessary, move the index of
855 * swing table to adjust Tx power.
857 if (delta > 0 && rtlpriv->dm.txpower_track_control) {
858 delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
859 (thermalvalue - rtlefuse->eeprom_thermalmeter) :
860 (rtlefuse->eeprom_thermalmeter - thermalvalue);
862 if (delta >= TXSCALE_TABLE_SIZE)
863 delta = TXSCALE_TABLE_SIZE - 1;
864 /* 7.1 Get the final CCK_index and
865 * OFDM_index for each swing table.
867 if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
868 rtldm->delta_power_index_last[RF90_PATH_A] =
869 rtldm->delta_power_index[RF90_PATH_A];
870 rtldm->delta_power_index[RF90_PATH_A] =
871 delta_swing_table_idx_tup_a[delta];
873 rtldm->delta_power_index_last[RF90_PATH_A] =
874 rtldm->delta_power_index[RF90_PATH_A];
875 rtldm->delta_power_index[RF90_PATH_A] =
876 -1 * delta_swing_table_idx_tdown_a[delta];
879 /* 7.2 Handle boundary conditions of index.*/
880 if (rtldm->delta_power_index[RF90_PATH_A] ==
881 rtldm->delta_power_index_last[RF90_PATH_A])
882 rtldm->power_index_offset[RF90_PATH_A] = 0;
884 rtldm->power_index_offset[RF90_PATH_A] =
885 rtldm->delta_power_index[RF90_PATH_A] -
886 rtldm->delta_power_index_last[RF90_PATH_A];
888 rtldm->ofdm_index[0] =
889 rtldm->swing_idx_ofdm_base[RF90_PATH_A] +
890 rtldm->power_index_offset[RF90_PATH_A];
891 rtldm->cck_index = rtldm->swing_idx_cck_base +
892 rtldm->power_index_offset[RF90_PATH_A];
894 rtldm->swing_idx_cck = rtldm->cck_index;
895 rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0];
897 if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1)
898 rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1;
899 else if (rtldm->ofdm_index[0] < ofdm_min_index)
900 rtldm->ofdm_index[0] = ofdm_min_index;
902 if (rtldm->cck_index > CCK_TABLE_SIZE - 1)
903 rtldm->cck_index = CCK_TABLE_SIZE - 1;
904 else if (rtldm->cck_index < 0)
905 rtldm->cck_index = 0;
907 rtldm->power_index_offset[RF90_PATH_A] = 0;
910 if ((rtldm->power_index_offset[RF90_PATH_A] != 0) &&
911 (rtldm->txpower_track_control)) {
912 rtldm->done_txpower = true;
913 if (thermalvalue > rtlefuse->eeprom_thermalmeter)
914 rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
917 rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
920 rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
921 rtldm->swing_idx_ofdm_base[RF90_PATH_A] =
922 rtldm->swing_idx_ofdm[0];
923 rtldm->thermalvalue = thermalvalue;
926 if (delta_iqk >= IQK_THRESHOLD) {
927 rtldm->thermalvalue_iqk = thermalvalue;
928 rtl8723be_phy_iq_calibrate(hw, false);
931 rtldm->txpowercount = 0;
932 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
936 void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
938 struct rtl_priv *rtlpriv = rtl_priv(hw);
939 static u8 tm_trigger;
941 if (!rtlpriv->dm.txpower_tracking)
945 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
947 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
948 "Trigger 8723be Thermal Meter!!\n");
952 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
953 "Schedule TxPowerTracking !!\n");
954 rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw);
959 static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
961 struct rtl_priv *rtlpriv = rtl_priv(hw);
962 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
963 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
964 struct rate_adaptive *p_ra = &rtlpriv->ra;
965 u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
966 u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
968 struct ieee80211_sta *sta = NULL;
970 if (is_hal_stop(rtlhal)) {
971 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
972 "driver is going to unload\n");
976 if (!rtlpriv->dm.useramask) {
977 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
978 "driver does not control rate adaptive mask\n");
982 if (mac->link_state == MAC80211_LINKED &&
983 mac->opmode == NL80211_IFTYPE_STATION) {
984 switch (p_ra->pre_ratr_state) {
985 case DM_RATR_STA_MIDDLE:
986 high_rssithresh_for_ra += go_up_gap;
988 case DM_RATR_STA_LOW:
989 high_rssithresh_for_ra += go_up_gap;
990 low_rssithresh_for_ra += go_up_gap;
996 if (rtlpriv->dm.undec_sm_pwdb >
997 (long)high_rssithresh_for_ra)
998 p_ra->ratr_state = DM_RATR_STA_HIGH;
999 else if (rtlpriv->dm.undec_sm_pwdb >
1000 (long)low_rssithresh_for_ra)
1001 p_ra->ratr_state = DM_RATR_STA_MIDDLE;
1003 p_ra->ratr_state = DM_RATR_STA_LOW;
1005 if (p_ra->pre_ratr_state != p_ra->ratr_state) {
1006 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1008 rtlpriv->dm.undec_sm_pwdb);
1009 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1010 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
1011 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1012 "PreState = %d, CurState = %d\n",
1013 p_ra->pre_ratr_state, p_ra->ratr_state);
1016 sta = rtl_find_sta(hw, mac->bssid);
1018 rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
1022 p_ra->pre_ratr_state = p_ra->ratr_state;
1027 static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
1029 struct rtl_priv *rtlpriv = rtl_priv(hw);
1031 if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
1037 static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw)
1039 struct rtl_priv *rtlpriv = rtl_priv(hw);
1040 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1042 static u64 last_txok_cnt;
1043 static u64 last_rxok_cnt;
1044 u64 cur_txok_cnt = 0;
1045 u64 cur_rxok_cnt = 0;
1046 u32 edca_be_ul = 0x6ea42b;
1047 u32 edca_be_dl = 0x6ea42b;/*not sure*/
1048 u32 edca_be = 0x5ea42b;
1050 bool b_is_cur_rdlstate;
1051 bool b_last_is_cur_rdlstate = false;
1052 bool b_bias_on_rx = false;
1053 bool b_edca_turbo_on = false;
1055 b_last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate;
1057 cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
1058 cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
1060 iot_peer = rtlpriv->mac80211.vendor;
1061 b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ?
1063 b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
1064 (!rtlpriv->dm.disable_framebursting)) ?
1067 if ((iot_peer == PEER_CISCO) &&
1068 (mac->mode == WIRELESS_MODE_N_24G)) {
1069 edca_be_dl = edca_setting_dl[iot_peer];
1070 edca_be_ul = edca_setting_ul[iot_peer];
1072 if (rtl8723be_dm_is_edca_turbo_disable(hw))
1075 if (b_edca_turbo_on) {
1077 b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ?
1080 b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
1083 edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul;
1084 rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be);
1085 rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate;
1086 rtlpriv->dm.current_turbo_edca = true;
1088 if (rtlpriv->dm.current_turbo_edca) {
1090 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
1093 rtlpriv->dm.current_turbo_edca = false;
1097 rtlpriv->dm.is_any_nonbepkts = false;
1098 last_txok_cnt = rtlpriv->stats.txbytesunicast;
1099 last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1102 static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
1104 struct rtl_priv *rtlpriv = rtl_priv(hw);
1105 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
1106 u8 cur_cck_cca_thresh;
1108 if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1109 if (dm_digtable->rssi_val_min > 25) {
1110 cur_cck_cca_thresh = 0xcd;
1111 } else if ((dm_digtable->rssi_val_min <= 25) &&
1112 (dm_digtable->rssi_val_min > 10)) {
1113 cur_cck_cca_thresh = 0x83;
1115 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1116 cur_cck_cca_thresh = 0x83;
1118 cur_cck_cca_thresh = 0x40;
1121 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1122 cur_cck_cca_thresh = 0x83;
1124 cur_cck_cca_thresh = 0x40;
1127 if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
1128 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
1130 dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
1131 dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
1132 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
1133 "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
1136 static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw)
1138 struct rtl_priv *rtlpriv = rtl_priv(hw);
1139 u8 reg_c50, reg_c58;
1140 bool fw_current_in_ps_mode = false;
1142 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1143 (u8 *)(&fw_current_in_ps_mode));
1144 if (fw_current_in_ps_mode)
1147 reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
1148 reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
1150 if (reg_c50 > 0x28 && reg_c58 > 0x28) {
1151 if (!rtlpriv->rtlhal.pre_edcca_enable) {
1152 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
1153 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
1155 } else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
1156 if (rtlpriv->rtlhal.pre_edcca_enable) {
1157 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
1158 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
1163 static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
1165 struct rtl_priv *rtlpriv = rtl_priv(hw);
1166 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1169 int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
1172 if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1173 if (rtldm->atc_status == ATC_STATUS_OFF) {
1174 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1176 rtldm->atc_status = ATC_STATUS_ON;
1178 if (rtlpriv->cfg->ops->get_btc_status()) {
1179 if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) {
1180 RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
1181 "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n");
1186 if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
1187 rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
1188 crystal_cap = rtldm->crystal_cap & 0x3f;
1189 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1190 (crystal_cap | (crystal_cap << 6)));
1193 cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
1194 cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
1195 packet_count = rtldm->packet_count;
1197 if (packet_count == rtldm->packet_count_pre)
1200 rtldm->packet_count_pre = packet_count;
1202 if (rtlpriv->phy.rf_type == RF_1T1R)
1203 cfo_ave = cfo_khz_a;
1205 cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
1207 cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
1208 (rtldm->cfo_ave_pre - cfo_ave) :
1209 (cfo_ave - rtldm->cfo_ave_pre);
1211 if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) {
1212 rtldm->large_cfo_hit = 1;
1215 rtldm->large_cfo_hit = 0;
1217 rtldm->cfo_ave_pre = cfo_ave;
1219 if (cfo_ave >= -rtldm->cfo_threshold &&
1220 cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
1221 if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
1222 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
1223 rtldm->is_freeze = 1;
1225 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
1229 if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
1230 adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1;
1231 else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
1232 rtlpriv->dm.crystal_cap > 0)
1233 adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1;
1235 if (adjust_xtal != 0) {
1236 rtldm->is_freeze = 0;
1237 rtldm->crystal_cap += adjust_xtal;
1239 if (rtldm->crystal_cap > 0x3f)
1240 rtldm->crystal_cap = 0x3f;
1241 else if (rtldm->crystal_cap < 0)
1242 rtldm->crystal_cap = 0;
1244 crystal_cap = rtldm->crystal_cap & 0x3f;
1245 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1246 (crystal_cap | (crystal_cap << 6)));
1249 if (cfo_ave < CFO_THRESHOLD_ATC &&
1250 cfo_ave > -CFO_THRESHOLD_ATC) {
1251 if (rtldm->atc_status == ATC_STATUS_ON) {
1252 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1254 rtldm->atc_status = ATC_STATUS_OFF;
1257 if (rtldm->atc_status == ATC_STATUS_OFF) {
1258 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1260 rtldm->atc_status = ATC_STATUS_ON;
1266 static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw)
1268 struct rtl_priv *rtlpriv = rtl_priv(hw);
1270 struct rtl_sta_info *drv_priv;
1272 rtlpriv->dm.one_entry_only = false;
1274 if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1275 rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1276 rtlpriv->dm.one_entry_only = true;
1280 if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1281 rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1282 rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1283 spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1284 list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
1287 spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1290 rtlpriv->dm.one_entry_only = true;
1294 void rtl8723be_dm_watchdog(struct ieee80211_hw *hw)
1296 struct rtl_priv *rtlpriv = rtl_priv(hw);
1297 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1298 bool fw_current_inpsmode = false;
1299 bool fw_ps_awake = true;
1301 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1302 (u8 *)(&fw_current_inpsmode));
1304 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1305 (u8 *)(&fw_ps_awake));
1307 if (ppsc->p2p_ps_info.p2p_ps_mode)
1308 fw_ps_awake = false;
1310 if ((ppsc->rfpwr_state == ERFON) &&
1311 ((!fw_current_inpsmode) && fw_ps_awake) &&
1312 (!ppsc->rfchange_inprogress)) {
1313 rtl8723be_dm_common_info_self_update(hw);
1314 rtl8723be_dm_false_alarm_counter_statistics(hw);
1315 rtl8723be_dm_check_rssi_monitor(hw);
1316 rtl8723be_dm_dig(hw);
1317 rtl8723be_dm_dynamic_edcca(hw);
1318 rtl8723be_dm_cck_packet_detection_thresh(hw);
1319 rtl8723be_dm_refresh_rate_adaptive_mask(hw);
1320 rtl8723be_dm_check_edca_turbo(hw);
1321 rtl8723be_dm_dynamic_atc_switch(hw);
1322 rtl8723be_dm_check_txpower_tracking(hw);
1323 rtl8723be_dm_dynamic_txpower(hw);
1325 rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;