xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8723be/dm.c (revision 0526b56cbc3c489642bd6a5fe4b718dea7ef0ee8)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2014  Realtek Corporation.*/
3 
4 #include "../wifi.h"
5 #include "../base.h"
6 #include "../pci.h"
7 #include "../core.h"
8 #include "reg.h"
9 #include "def.h"
10 #include "phy.h"
11 #include "dm.h"
12 #include "../rtl8723com/dm_common.h"
13 #include "fw.h"
14 #include "trx.h"
15 #include "../btcoexist/rtl_btc.h"
16 
17 static const u32 ofdmswing_table[] = {
18 	0x0b40002d, /* 0,  -15.0dB */
19 	0x0c000030, /* 1,  -14.5dB */
20 	0x0cc00033, /* 2,  -14.0dB */
21 	0x0d800036, /* 3,  -13.5dB */
22 	0x0e400039, /* 4,  -13.0dB */
23 	0x0f00003c, /* 5,  -12.5dB */
24 	0x10000040, /* 6,  -12.0dB */
25 	0x11000044, /* 7,  -11.5dB */
26 	0x12000048, /* 8,  -11.0dB */
27 	0x1300004c, /* 9,  -10.5dB */
28 	0x14400051, /* 10, -10.0dB */
29 	0x15800056, /* 11, -9.5dB */
30 	0x16c0005b, /* 12, -9.0dB */
31 	0x18000060, /* 13, -8.5dB */
32 	0x19800066, /* 14, -8.0dB */
33 	0x1b00006c, /* 15, -7.5dB */
34 	0x1c800072, /* 16, -7.0dB */
35 	0x1e400079, /* 17, -6.5dB */
36 	0x20000080, /* 18, -6.0dB */
37 	0x22000088, /* 19, -5.5dB */
38 	0x24000090, /* 20, -5.0dB */
39 	0x26000098, /* 21, -4.5dB */
40 	0x288000a2, /* 22, -4.0dB */
41 	0x2ac000ab, /* 23, -3.5dB */
42 	0x2d4000b5, /* 24, -3.0dB */
43 	0x300000c0, /* 25, -2.5dB */
44 	0x32c000cb, /* 26, -2.0dB */
45 	0x35c000d7, /* 27, -1.5dB */
46 	0x390000e4, /* 28, -1.0dB */
47 	0x3c8000f2, /* 29, -0.5dB */
48 	0x40000100, /* 30, +0dB */
49 	0x43c0010f, /* 31, +0.5dB */
50 	0x47c0011f, /* 32, +1.0dB */
51 	0x4c000130, /* 33, +1.5dB */
52 	0x50800142, /* 34, +2.0dB */
53 	0x55400155, /* 35, +2.5dB */
54 	0x5a400169, /* 36, +3.0dB */
55 	0x5fc0017f, /* 37, +3.5dB */
56 	0x65400195, /* 38, +4.0dB */
57 	0x6b8001ae, /* 39, +4.5dB */
58 	0x71c001c7, /* 40, +5.0dB */
59 	0x788001e2, /* 41, +5.5dB */
60 	0x7f8001fe  /* 42, +6.0dB */
61 };
62 
63 static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
64 	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /*  0, -16.0dB */
65 	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /*  1, -15.5dB */
66 	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  2, -15.0dB */
67 	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  3, -14.5dB */
68 	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  4, -14.0dB */
69 	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  5, -13.5dB */
70 	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /*  6, -13.0dB */
71 	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /*  7, -12.5dB */
72 	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /*  8, -12.0dB */
73 	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /*  9, -11.5dB */
74 	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */
75 	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */
76 	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */
77 	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */
78 	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */
79 	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */
80 	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
81 	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */
82 	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */
83 	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */
84 	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */
85 	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */
86 	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */
87 	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */
88 	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */
89 	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */
90 	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */
91 	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */
92 	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */
93 	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */
94 	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */
95 	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */
96 	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}  /* 32, +0dB */
97 };
98 
99 static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
100 	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /*  0, -16.0dB */
101 	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  1, -15.5dB */
102 	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  2, -15.0dB */
103 	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  3, -14.5dB */
104 	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  4, -14.0dB */
105 	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  5, -13.5dB */
106 	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  6, -13.0dB */
107 	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  7, -12.5dB */
108 	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  8, -12.0dB */
109 	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  9, -11.5dB */
110 	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */
111 	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */
112 	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */
113 	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */
114 	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */
115 	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */
116 	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
117 	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */
118 	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */
119 	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */
120 	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */
121 	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */
122 	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */
123 	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */
124 	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */
125 	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */
126 	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */
127 	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */
128 	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */
129 	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */
130 	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */
131 	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */
132 	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}  /* 32, +0dB */
133 };
134 
135 static const u32 edca_setting_dl[PEER_MAX] = {
136 	0xa44f,		/* 0 UNKNOWN */
137 	0x5ea44f,	/* 1 REALTEK_90 */
138 	0x5e4322,	/* 2 REALTEK_92SE */
139 	0x5ea42b,	/* 3 BROAD */
140 	0xa44f,		/* 4 RAL */
141 	0xa630,		/* 5 ATH */
142 	0x5ea630,	/* 6 CISCO */
143 	0x5ea42b,	/* 7 MARVELL */
144 };
145 
146 static const u32 edca_setting_ul[PEER_MAX] = {
147 	0x5e4322,	/* 0 UNKNOWN */
148 	0xa44f,		/* 1 REALTEK_90 */
149 	0x5ea44f,	/* 2 REALTEK_92SE */
150 	0x5ea32b,	/* 3 BROAD */
151 	0x5ea422,	/* 4 RAL */
152 	0x5ea322,	/* 5 ATH */
153 	0x3ea430,	/* 6 CISCO */
154 	0x5ea44f,	/* 7 MARV */
155 };
156 
157 void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type,
158 				       u8 *pdirection, u32 *poutwrite_val)
159 {
160 	struct rtl_priv *rtlpriv = rtl_priv(hw);
161 	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
162 	u8 pwr_val = 0;
163 	u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A];
164 	u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
165 	u8 cck_base = rtldm->swing_idx_cck_base;
166 	u8 cck_val = rtldm->swing_idx_cck;
167 
168 	if (type == 0) {
169 		if (ofdm_val <= ofdm_base) {
170 			*pdirection = 1;
171 			pwr_val = ofdm_base - ofdm_val;
172 		} else {
173 			*pdirection = 2;
174 			pwr_val = ofdm_val - ofdm_base;
175 		}
176 	} else if (type == 1) {
177 		if (cck_val <= cck_base) {
178 			*pdirection = 1;
179 			pwr_val = cck_base - cck_val;
180 		} else {
181 			*pdirection = 2;
182 			pwr_val = cck_val - cck_base;
183 		}
184 	}
185 
186 	if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
187 		pwr_val = TXPWRTRACK_MAX_IDX;
188 
189 	*poutwrite_val = pwr_val | (pwr_val << 8) |
190 		(pwr_val << 16) | (pwr_val << 24);
191 }
192 
193 void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
194 {
195 	struct rtl_priv *rtlpriv = rtl_priv(hw);
196 	struct rate_adaptive *p_ra = &rtlpriv->ra;
197 
198 	p_ra->ratr_state = DM_RATR_STA_INIT;
199 	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
200 
201 	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
202 		rtlpriv->dm.useramask = true;
203 	else
204 		rtlpriv->dm.useramask = false;
205 
206 	p_ra->high_rssi_thresh_for_ra = 50;
207 	p_ra->low_rssi_thresh_for_ra40m = 20;
208 }
209 
210 static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw)
211 {
212 	struct rtl_priv *rtlpriv = rtl_priv(hw);
213 
214 	rtlpriv->dm.txpower_tracking = true;
215 	rtlpriv->dm.txpower_track_control = true;
216 	rtlpriv->dm.thermalvalue = 0;
217 
218 	rtlpriv->dm.ofdm_index[0] = 30;
219 	rtlpriv->dm.cck_index = 20;
220 
221 	rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index;
222 
223 	rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0];
224 	rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0;
225 	rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0;
226 	rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0;
227 
228 	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
229 		"rtlpriv->dm.txpower_tracking = %d\n",
230 		rtlpriv->dm.txpower_tracking);
231 }
232 
233 static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
234 {
235 	struct rtl_priv *rtlpriv = rtl_priv(hw);
236 
237 	rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
238 
239 	rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800);
240 	rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
241 }
242 
243 void rtl8723be_dm_init(struct ieee80211_hw *hw)
244 {
245 	struct rtl_priv *rtlpriv = rtl_priv(hw);
246 	u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
247 
248 	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
249 	rtl_dm_diginit(hw, cur_igvalue);
250 	rtl8723be_dm_init_rate_adaptive_mask(hw);
251 	rtl8723_dm_init_edca_turbo(hw);
252 	rtl8723_dm_init_dynamic_bb_powersaving(hw);
253 	rtl8723_dm_init_dynamic_txpower(hw);
254 	rtl8723be_dm_init_txpower_tracking(hw);
255 	rtl8723be_dm_init_dynamic_atc_switch(hw);
256 }
257 
258 static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw)
259 {
260 	struct rtl_priv *rtlpriv = rtl_priv(hw);
261 	struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
262 	struct rtl_mac *mac = rtl_mac(rtlpriv);
263 
264 	/* Determine the minimum RSSI  */
265 	if ((mac->link_state < MAC80211_LINKED) &&
266 	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
267 		rtl_dm_dig->min_undec_pwdb_for_dm = 0;
268 		rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
269 			"Not connected to any\n");
270 	}
271 	if (mac->link_state >= MAC80211_LINKED) {
272 		if (mac->opmode == NL80211_IFTYPE_AP ||
273 		    mac->opmode == NL80211_IFTYPE_ADHOC) {
274 			rtl_dm_dig->min_undec_pwdb_for_dm =
275 			    rtlpriv->dm.entry_min_undec_sm_pwdb;
276 			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
277 				"AP Client PWDB = 0x%lx\n",
278 				rtlpriv->dm.entry_min_undec_sm_pwdb);
279 		} else {
280 			rtl_dm_dig->min_undec_pwdb_for_dm =
281 			    rtlpriv->dm.undec_sm_pwdb;
282 			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
283 				"STA Default Port PWDB = 0x%x\n",
284 				rtl_dm_dig->min_undec_pwdb_for_dm);
285 		}
286 	} else {
287 		rtl_dm_dig->min_undec_pwdb_for_dm =
288 				rtlpriv->dm.entry_min_undec_sm_pwdb;
289 		rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
290 			"AP Ext Port or disconnect PWDB = 0x%x\n",
291 			rtl_dm_dig->min_undec_pwdb_for_dm);
292 	}
293 	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
294 		rtl_dm_dig->min_undec_pwdb_for_dm);
295 }
296 
297 static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw)
298 {
299 	struct rtl_priv *rtlpriv = rtl_priv(hw);
300 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
301 	struct rtl_sta_info *drv_priv;
302 	u8 h2c_parameter[3] = { 0 };
303 	long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
304 
305 	/* AP & ADHOC & MESH */
306 	spin_lock_bh(&rtlpriv->locks.entry_list_lock);
307 	list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
308 		if (drv_priv->rssi_stat.undec_sm_pwdb <
309 						tmp_entry_min_pwdb)
310 			tmp_entry_min_pwdb =
311 				drv_priv->rssi_stat.undec_sm_pwdb;
312 		if (drv_priv->rssi_stat.undec_sm_pwdb >
313 						tmp_entry_max_pwdb)
314 			tmp_entry_max_pwdb =
315 				drv_priv->rssi_stat.undec_sm_pwdb;
316 	}
317 	spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
318 
319 	/* If associated entry is found */
320 	if (tmp_entry_max_pwdb != 0) {
321 		rtlpriv->dm.entry_max_undec_sm_pwdb =
322 							tmp_entry_max_pwdb;
323 		RTPRINT(rtlpriv, FDM, DM_PWDB,
324 			"EntryMaxPWDB = 0x%lx(%ld)\n",
325 			 tmp_entry_max_pwdb, tmp_entry_max_pwdb);
326 	} else {
327 		rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
328 	}
329 	/* If associated entry is found */
330 	if (tmp_entry_min_pwdb != 0xff) {
331 		rtlpriv->dm.entry_min_undec_sm_pwdb =
332 							tmp_entry_min_pwdb;
333 		RTPRINT(rtlpriv, FDM, DM_PWDB,
334 			"EntryMinPWDB = 0x%lx(%ld)\n",
335 			 tmp_entry_min_pwdb, tmp_entry_min_pwdb);
336 	} else {
337 		rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
338 	}
339 	/* Indicate Rx signal strength to FW. */
340 	if (rtlpriv->dm.useramask) {
341 		h2c_parameter[2] =
342 			(u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
343 		h2c_parameter[1] = 0x20;
344 		h2c_parameter[0] = 0;
345 		rtl8723be_fill_h2c_cmd(hw, H2C_RSSIBE_REPORT, 3, h2c_parameter);
346 	} else {
347 		rtl_write_byte(rtlpriv, 0x4fe,
348 			       rtlpriv->dm.undec_sm_pwdb);
349 	}
350 	rtl8723be_dm_find_minimum_rssi(hw);
351 	dm_digtable->rssi_val_min =
352 			rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
353 }
354 
355 void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
356 {
357 	struct rtl_priv *rtlpriv = rtl_priv(hw);
358 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
359 
360 	if (dm_digtable->stop_dig)
361 		return;
362 
363 	if (dm_digtable->cur_igvalue != current_igi) {
364 		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi);
365 		if (rtlpriv->phy.rf_type != RF_1T1R)
366 			rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1,
367 				      0x7f, current_igi);
368 	}
369 	dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
370 	dm_digtable->cur_igvalue = current_igi;
371 }
372 
373 static void rtl8723be_dm_dig(struct ieee80211_hw *hw)
374 {
375 	struct rtl_priv *rtlpriv = rtl_priv(hw);
376 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
377 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
378 	u8 dig_min_0, dig_maxofmin;
379 	bool bfirstconnect, bfirstdisconnect;
380 	u8 dm_dig_max, dm_dig_min;
381 	u8 current_igi = dm_digtable->cur_igvalue;
382 	u8 offset;
383 
384 	/* AP,BT */
385 	if (mac->act_scanning)
386 		return;
387 
388 	dig_min_0 = dm_digtable->dig_min_0;
389 	bfirstconnect = (mac->link_state >= MAC80211_LINKED) &&
390 			!dm_digtable->media_connect_0;
391 	bfirstdisconnect = (mac->link_state < MAC80211_LINKED) &&
392 			(dm_digtable->media_connect_0);
393 
394 	dm_dig_max = 0x5a;
395 	dm_dig_min = DM_DIG_MIN;
396 	dig_maxofmin = DM_DIG_MAX_AP;
397 
398 	if (mac->link_state >= MAC80211_LINKED) {
399 		if ((dm_digtable->rssi_val_min + 10) > dm_dig_max)
400 			dm_digtable->rx_gain_max = dm_dig_max;
401 		else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min)
402 			dm_digtable->rx_gain_max = dm_dig_min;
403 		else
404 			dm_digtable->rx_gain_max =
405 				dm_digtable->rssi_val_min + 10;
406 
407 		if (rtlpriv->dm.one_entry_only) {
408 			offset = 12;
409 			if (dm_digtable->rssi_val_min - offset < dm_dig_min)
410 				dig_min_0 = dm_dig_min;
411 			else if (dm_digtable->rssi_val_min - offset >
412 							dig_maxofmin)
413 				dig_min_0 = dig_maxofmin;
414 			else
415 				dig_min_0 =
416 					dm_digtable->rssi_val_min - offset;
417 		} else {
418 			dig_min_0 = dm_dig_min;
419 		}
420 
421 	} else {
422 		dm_digtable->rx_gain_max = dm_dig_max;
423 		dig_min_0 = dm_dig_min;
424 		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
425 	}
426 
427 	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
428 		if (dm_digtable->large_fa_hit != 3)
429 			dm_digtable->large_fa_hit++;
430 		if (dm_digtable->forbidden_igi < current_igi) {
431 			dm_digtable->forbidden_igi = current_igi;
432 			dm_digtable->large_fa_hit = 1;
433 		}
434 
435 		if (dm_digtable->large_fa_hit >= 3) {
436 			if ((dm_digtable->forbidden_igi + 1) >
437 			     dm_digtable->rx_gain_max)
438 				dm_digtable->rx_gain_min =
439 						dm_digtable->rx_gain_max;
440 			else
441 				dm_digtable->rx_gain_min =
442 						dm_digtable->forbidden_igi + 1;
443 			dm_digtable->recover_cnt = 3600;
444 		}
445 	} else {
446 		if (dm_digtable->recover_cnt != 0) {
447 			dm_digtable->recover_cnt--;
448 		} else {
449 			if (dm_digtable->large_fa_hit < 3) {
450 				if ((dm_digtable->forbidden_igi - 1) <
451 				     dig_min_0) {
452 					dm_digtable->forbidden_igi =
453 							dig_min_0;
454 					dm_digtable->rx_gain_min =
455 							dig_min_0;
456 				} else {
457 					dm_digtable->forbidden_igi--;
458 					dm_digtable->rx_gain_min =
459 						dm_digtable->forbidden_igi + 1;
460 				}
461 			} else {
462 				dm_digtable->large_fa_hit = 0;
463 			}
464 		}
465 	}
466 	if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
467 		dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
468 
469 	if (mac->link_state >= MAC80211_LINKED) {
470 		if (bfirstconnect) {
471 			if (dm_digtable->rssi_val_min <= dig_maxofmin)
472 				current_igi = dm_digtable->rssi_val_min;
473 			else
474 				current_igi = dig_maxofmin;
475 
476 			dm_digtable->large_fa_hit = 0;
477 		} else {
478 			if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
479 				current_igi += 4;
480 			else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
481 				current_igi += 2;
482 			else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
483 				current_igi -= 2;
484 		}
485 	} else {
486 		if (bfirstdisconnect) {
487 			current_igi = dm_digtable->rx_gain_min;
488 		} else {
489 			if (rtlpriv->falsealm_cnt.cnt_all > 10000)
490 				current_igi += 4;
491 			else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
492 				current_igi += 2;
493 			else if (rtlpriv->falsealm_cnt.cnt_all < 500)
494 				current_igi -= 2;
495 		}
496 	}
497 
498 	if (current_igi > dm_digtable->rx_gain_max)
499 		current_igi = dm_digtable->rx_gain_max;
500 	else if (current_igi < dm_digtable->rx_gain_min)
501 		current_igi = dm_digtable->rx_gain_min;
502 
503 	rtl8723be_dm_write_dig(hw, current_igi);
504 	dm_digtable->media_connect_0 =
505 		((mac->link_state >= MAC80211_LINKED) ? true : false);
506 	dm_digtable->dig_min_0 = dig_min_0;
507 }
508 
509 static void rtl8723be_dm_false_alarm_counter_statistics(
510 					struct ieee80211_hw *hw)
511 {
512 	u32 ret_value;
513 	struct rtl_priv *rtlpriv = rtl_priv(hw);
514 	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
515 
516 	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
517 	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
518 
519 	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD);
520 	falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff;
521 	falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16;
522 
523 	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD);
524 	falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff;
525 	falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16;
526 
527 	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD);
528 	falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff;
529 	falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16;
530 
531 	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD);
532 	falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff;
533 
534 	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
535 				      falsealm_cnt->cnt_rate_illegal +
536 				      falsealm_cnt->cnt_crc8_fail +
537 				      falsealm_cnt->cnt_mcs_fail +
538 				      falsealm_cnt->cnt_fast_fsync_fail +
539 				      falsealm_cnt->cnt_sb_search_fail;
540 
541 	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1);
542 	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1);
543 
544 	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0);
545 	falsealm_cnt->cnt_cck_fail = ret_value;
546 
547 	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3);
548 	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
549 
550 	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD);
551 	falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
552 				    ((ret_value & 0xff00) >> 8);
553 
554 	falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
555 				falsealm_cnt->cnt_sb_search_fail +
556 				falsealm_cnt->cnt_parity_fail +
557 				falsealm_cnt->cnt_rate_illegal +
558 				falsealm_cnt->cnt_crc8_fail +
559 				falsealm_cnt->cnt_mcs_fail +
560 				falsealm_cnt->cnt_cck_fail;
561 
562 	falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca +
563 				    falsealm_cnt->cnt_cck_cca;
564 
565 	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
566 	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
567 	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
568 	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
569 
570 	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
571 	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
572 
573 	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
574 	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
575 
576 	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
577 	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
578 
579 	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
580 		"cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
581 		falsealm_cnt->cnt_parity_fail,
582 		falsealm_cnt->cnt_rate_illegal,
583 		falsealm_cnt->cnt_crc8_fail,
584 		falsealm_cnt->cnt_mcs_fail);
585 
586 	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
587 		"cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
588 		falsealm_cnt->cnt_ofdm_fail,
589 		falsealm_cnt->cnt_cck_fail,
590 		falsealm_cnt->cnt_all);
591 }
592 
593 static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw)
594 {
595 	/* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/
596 	return;
597 }
598 
599 static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index,
600 				     u8 rfpath, long iqk_result_x,
601 				     long iqk_result_y)
602 {
603 	long ele_a = 0, ele_d, ele_c = 0, value32;
604 
605 	if (ofdm_index >= 43)
606 		ofdm_index = 43 - 1;
607 
608 	ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22;
609 
610 	if (iqk_result_x != 0) {
611 		if ((iqk_result_x & 0x00000200) != 0)
612 			iqk_result_x = iqk_result_x | 0xFFFFFC00;
613 		ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF;
614 
615 		if ((iqk_result_y & 0x00000200) != 0)
616 			iqk_result_y = iqk_result_y | 0xFFFFFC00;
617 		ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF;
618 
619 		switch (rfpath) {
620 		case RF90_PATH_A:
621 			value32 = (ele_d << 22) |
622 				((ele_c & 0x3F) << 16) | ele_a;
623 			rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
624 				      value32);
625 			value32 = (ele_c & 0x000003C0) >> 6;
626 			rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
627 			value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
628 			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
629 				      value32);
630 			break;
631 		default:
632 			break;
633 		}
634 	} else {
635 		switch (rfpath) {
636 		case RF90_PATH_A:
637 			rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
638 				      ofdmswing_table[ofdm_index]);
639 			rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
640 			rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00);
641 			break;
642 		default:
643 			break;
644 		}
645 	}
646 }
647 
648 static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw,
649 					enum pwr_track_control_method method,
650 					u8 rfpath, u8 idx)
651 {
652 	struct rtl_priv *rtlpriv = rtl_priv(hw);
653 	struct rtl_phy *rtlphy = &rtlpriv->phy;
654 	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
655 	u8 swing_idx_ofdm_limit = 36;
656 
657 	if (method == TXAGC) {
658 		rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel);
659 	} else if (method == BBSWING) {
660 		if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE)
661 			rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1;
662 
663 		if (!rtldm->cck_inch14) {
664 			rtl_write_byte(rtlpriv, 0xa22,
665 			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]);
666 			rtl_write_byte(rtlpriv, 0xa23,
667 			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]);
668 			rtl_write_byte(rtlpriv, 0xa24,
669 			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]);
670 			rtl_write_byte(rtlpriv, 0xa25,
671 			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]);
672 			rtl_write_byte(rtlpriv, 0xa26,
673 			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]);
674 			rtl_write_byte(rtlpriv, 0xa27,
675 			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]);
676 			rtl_write_byte(rtlpriv, 0xa28,
677 			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]);
678 			rtl_write_byte(rtlpriv, 0xa29,
679 			    cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]);
680 		} else {
681 			rtl_write_byte(rtlpriv, 0xa22,
682 			    cckswing_table_ch14[rtldm->swing_idx_cck][0]);
683 			rtl_write_byte(rtlpriv, 0xa23,
684 			    cckswing_table_ch14[rtldm->swing_idx_cck][1]);
685 			rtl_write_byte(rtlpriv, 0xa24,
686 			    cckswing_table_ch14[rtldm->swing_idx_cck][2]);
687 			rtl_write_byte(rtlpriv, 0xa25,
688 			    cckswing_table_ch14[rtldm->swing_idx_cck][3]);
689 			rtl_write_byte(rtlpriv, 0xa26,
690 			    cckswing_table_ch14[rtldm->swing_idx_cck][4]);
691 			rtl_write_byte(rtlpriv, 0xa27,
692 			    cckswing_table_ch14[rtldm->swing_idx_cck][5]);
693 			rtl_write_byte(rtlpriv, 0xa28,
694 			    cckswing_table_ch14[rtldm->swing_idx_cck][6]);
695 			rtl_write_byte(rtlpriv, 0xa29,
696 			    cckswing_table_ch14[rtldm->swing_idx_cck][7]);
697 		}
698 
699 		if (rfpath == RF90_PATH_A) {
700 			if (rtldm->swing_idx_ofdm[RF90_PATH_A] <
701 			    swing_idx_ofdm_limit)
702 				swing_idx_ofdm_limit =
703 					rtldm->swing_idx_ofdm[RF90_PATH_A];
704 
705 			rtl8723be_set_iqk_matrix(hw,
706 				rtldm->swing_idx_ofdm[rfpath], rfpath,
707 				rtlphy->iqk_matrix[idx].value[0][0],
708 				rtlphy->iqk_matrix[idx].value[0][1]);
709 		} else if (rfpath == RF90_PATH_B) {
710 			if (rtldm->swing_idx_ofdm[RF90_PATH_B] <
711 			    swing_idx_ofdm_limit)
712 				swing_idx_ofdm_limit =
713 					rtldm->swing_idx_ofdm[RF90_PATH_B];
714 
715 			rtl8723be_set_iqk_matrix(hw,
716 				rtldm->swing_idx_ofdm[rfpath], rfpath,
717 				rtlphy->iqk_matrix[idx].value[0][4],
718 				rtlphy->iqk_matrix[idx].value[0][5]);
719 		}
720 	} else {
721 		return;
722 	}
723 }
724 
725 static void rtl8723be_dm_txpower_tracking_callback_thermalmeter(
726 							struct ieee80211_hw *hw)
727 {
728 	struct rtl_priv *rtlpriv = rtl_priv(hw);
729 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
730 	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
731 	u8 thermalvalue = 0, delta, delta_lck, delta_iqk;
732 	u8 thermalvalue_avg_count = 0;
733 	u32 thermalvalue_avg = 0;
734 	int i = 0;
735 
736 	u8 ofdm_min_index = 6;
737 	u8 index_for_channel = 0;
738 
739 	static const s8 delta_swing_table_idx_tup_a[TXSCALE_TABLE_SIZE] = {
740 		0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
741 		5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10,
742 		10, 11, 11, 12, 12, 13, 14, 15};
743 	static const s8 delta_swing_table_idx_tdown_a[TXSCALE_TABLE_SIZE] = {
744 		0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
745 		5, 6, 6, 6, 6, 7, 7, 7, 8, 8,  9,
746 		9, 10, 10, 11, 12, 13, 14, 15};
747 
748 	/*Initilization ( 7 steps in total )*/
749 	rtlpriv->dm.txpower_trackinginit = true;
750 	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
751 		"%s\n", __func__);
752 
753 	thermalvalue = (u8)rtl_get_rfreg(hw,
754 		RF90_PATH_A, RF_T_METER, 0xfc00);
755 	if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 ||
756 	    rtlefuse->eeprom_thermalmeter == 0xFF)
757 		return;
758 	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
759 		"Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
760 		thermalvalue, rtldm->thermalvalue,
761 		rtlefuse->eeprom_thermalmeter);
762 	/*3 Initialize ThermalValues of RFCalibrateInfo*/
763 	if (!rtldm->thermalvalue) {
764 		rtlpriv->dm.thermalvalue_lck = thermalvalue;
765 		rtlpriv->dm.thermalvalue_iqk = thermalvalue;
766 	}
767 
768 	/*4 Calculate average thermal meter*/
769 	rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
770 	rtldm->thermalvalue_avg_index++;
771 	if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE)
772 		rtldm->thermalvalue_avg_index = 0;
773 
774 	for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) {
775 		if (rtldm->thermalvalue_avg[i]) {
776 			thermalvalue_avg += rtldm->thermalvalue_avg[i];
777 			thermalvalue_avg_count++;
778 		}
779 	}
780 
781 	if (thermalvalue_avg_count)
782 		thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count);
783 
784 	/* 5 Calculate delta, delta_LCK, delta_IQK.*/
785 	delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
786 		(thermalvalue - rtlpriv->dm.thermalvalue) :
787 		(rtlpriv->dm.thermalvalue - thermalvalue);
788 	delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
789 		    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
790 		    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
791 	delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
792 		    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
793 		    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
794 
795 	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
796 		"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",
797 		thermalvalue, rtlpriv->dm.thermalvalue,
798 		rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk);
799 	/* 6 If necessary, do LCK.*/
800 	if (delta_lck >= IQK_THRESHOLD) {
801 		rtlpriv->dm.thermalvalue_lck = thermalvalue;
802 		rtl8723be_phy_lc_calibrate(hw);
803 	}
804 
805 	/* 7 If necessary, move the index of
806 	 * swing table to adjust Tx power.
807 	 */
808 	if (delta > 0 && rtlpriv->dm.txpower_track_control) {
809 		delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
810 			(thermalvalue - rtlefuse->eeprom_thermalmeter) :
811 			(rtlefuse->eeprom_thermalmeter - thermalvalue);
812 
813 		if (delta >= TXSCALE_TABLE_SIZE)
814 			delta = TXSCALE_TABLE_SIZE - 1;
815 		/* 7.1 Get the final CCK_index and
816 		 * OFDM_index for each swing table.
817 		 */
818 		if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
819 			rtldm->delta_power_index_last[RF90_PATH_A] =
820 					rtldm->delta_power_index[RF90_PATH_A];
821 			rtldm->delta_power_index[RF90_PATH_A] =
822 					delta_swing_table_idx_tup_a[delta];
823 		} else {
824 			rtldm->delta_power_index_last[RF90_PATH_A] =
825 					rtldm->delta_power_index[RF90_PATH_A];
826 			rtldm->delta_power_index[RF90_PATH_A] =
827 				-1 * delta_swing_table_idx_tdown_a[delta];
828 		}
829 
830 		/* 7.2 Handle boundary conditions of index.*/
831 		if (rtldm->delta_power_index[RF90_PATH_A] ==
832 		    rtldm->delta_power_index_last[RF90_PATH_A])
833 			rtldm->power_index_offset[RF90_PATH_A] = 0;
834 		else
835 			rtldm->power_index_offset[RF90_PATH_A] =
836 				rtldm->delta_power_index[RF90_PATH_A] -
837 				rtldm->delta_power_index_last[RF90_PATH_A];
838 
839 		rtldm->ofdm_index[0] =
840 			rtldm->swing_idx_ofdm_base[RF90_PATH_A] +
841 			rtldm->power_index_offset[RF90_PATH_A];
842 		rtldm->cck_index = rtldm->swing_idx_cck_base +
843 				   rtldm->power_index_offset[RF90_PATH_A];
844 
845 		rtldm->swing_idx_cck = rtldm->cck_index;
846 		rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0];
847 
848 		if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1)
849 			rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1;
850 		else if (rtldm->ofdm_index[0] < ofdm_min_index)
851 			rtldm->ofdm_index[0] = ofdm_min_index;
852 
853 		if (rtldm->cck_index > CCK_TABLE_SIZE - 1)
854 			rtldm->cck_index = CCK_TABLE_SIZE - 1;
855 		else if (rtldm->cck_index < 0)
856 			rtldm->cck_index = 0;
857 	} else {
858 		rtldm->power_index_offset[RF90_PATH_A] = 0;
859 	}
860 
861 	if ((rtldm->power_index_offset[RF90_PATH_A] != 0) &&
862 	    (rtldm->txpower_track_control)) {
863 		rtldm->done_txpower = true;
864 		rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
865 						      index_for_channel);
866 
867 		rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
868 		rtldm->swing_idx_ofdm_base[RF90_PATH_A] =
869 						rtldm->swing_idx_ofdm[0];
870 		rtldm->thermalvalue = thermalvalue;
871 	}
872 
873 	if (delta_iqk >= IQK_THRESHOLD) {
874 		rtldm->thermalvalue_iqk = thermalvalue;
875 		rtl8723be_phy_iq_calibrate(hw, false);
876 	}
877 
878 	rtldm->txpowercount = 0;
879 	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
880 
881 }
882 
883 void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
884 {
885 	struct rtl_priv *rtlpriv = rtl_priv(hw);
886 
887 	if (!rtlpriv->dm.txpower_tracking)
888 		return;
889 
890 	if (!rtlpriv->dm.tm_trigger) {
891 		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
892 			      0x03);
893 		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
894 			"Trigger 8723be Thermal Meter!!\n");
895 		rtlpriv->dm.tm_trigger = 1;
896 		return;
897 	} else {
898 		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
899 			"Schedule TxPowerTracking !!\n");
900 		rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw);
901 		rtlpriv->dm.tm_trigger = 0;
902 	}
903 }
904 
905 static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
906 {
907 	struct rtl_priv *rtlpriv = rtl_priv(hw);
908 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
909 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
910 	struct rate_adaptive *p_ra = &rtlpriv->ra;
911 	u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
912 	u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
913 	u8 go_up_gap = 5;
914 	struct ieee80211_sta *sta = NULL;
915 
916 	if (is_hal_stop(rtlhal)) {
917 		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
918 			"driver is going to unload\n");
919 		return;
920 	}
921 
922 	if (!rtlpriv->dm.useramask) {
923 		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
924 			"driver does not control rate adaptive mask\n");
925 		return;
926 	}
927 
928 	if (mac->link_state == MAC80211_LINKED &&
929 		mac->opmode == NL80211_IFTYPE_STATION) {
930 		switch (p_ra->pre_ratr_state) {
931 		case DM_RATR_STA_MIDDLE:
932 			high_rssithresh_for_ra += go_up_gap;
933 			break;
934 		case DM_RATR_STA_LOW:
935 			high_rssithresh_for_ra += go_up_gap;
936 			low_rssithresh_for_ra += go_up_gap;
937 			break;
938 		default:
939 			break;
940 		}
941 
942 		if (rtlpriv->dm.undec_sm_pwdb >
943 		    (long)high_rssithresh_for_ra)
944 			p_ra->ratr_state = DM_RATR_STA_HIGH;
945 		else if (rtlpriv->dm.undec_sm_pwdb >
946 			 (long)low_rssithresh_for_ra)
947 			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
948 		else
949 			p_ra->ratr_state = DM_RATR_STA_LOW;
950 
951 		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
952 			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
953 				"RSSI = %ld\n",
954 				 rtlpriv->dm.undec_sm_pwdb);
955 			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
956 				"RSSI_LEVEL = %d\n", p_ra->ratr_state);
957 			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
958 				"PreState = %d, CurState = %d\n",
959 				p_ra->pre_ratr_state, p_ra->ratr_state);
960 
961 			rcu_read_lock();
962 			sta = rtl_find_sta(hw, mac->bssid);
963 			if (sta)
964 				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
965 							   p_ra->ratr_state,
966 							   true);
967 			rcu_read_unlock();
968 
969 			p_ra->pre_ratr_state = p_ra->ratr_state;
970 		}
971 	}
972 }
973 
974 static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
975 {
976 	struct rtl_priv *rtlpriv = rtl_priv(hw);
977 
978 	if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
979 		return true;
980 
981 	return false;
982 }
983 
984 static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw)
985 {
986 	struct rtl_priv *rtlpriv = rtl_priv(hw);
987 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
988 
989 	static u64 last_txok_cnt;
990 	static u64 last_rxok_cnt;
991 	u64 cur_txok_cnt = 0;
992 	u64 cur_rxok_cnt = 0;
993 	u32 edca_be_ul = 0x6ea42b;
994 	u32 edca_be_dl = 0x6ea42b;/*not sure*/
995 	u32 edca_be = 0x5ea42b;
996 	u32 iot_peer = 0;
997 	bool b_is_cur_rdlstate;
998 	bool b_bias_on_rx = false;
999 	bool b_edca_turbo_on = false;
1000 
1001 	cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
1002 	cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
1003 
1004 	iot_peer = rtlpriv->mac80211.vendor;
1005 	b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ?
1006 		       true : false;
1007 	b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
1008 			   (!rtlpriv->dm.disable_framebursting)) ?
1009 			   true : false;
1010 
1011 	if ((iot_peer == PEER_CISCO) &&
1012 	    (mac->mode == WIRELESS_MODE_N_24G)) {
1013 		edca_be_dl = edca_setting_dl[iot_peer];
1014 		edca_be_ul = edca_setting_ul[iot_peer];
1015 	}
1016 	if (rtl8723be_dm_is_edca_turbo_disable(hw))
1017 		goto exit;
1018 
1019 	if (b_edca_turbo_on) {
1020 		if (b_bias_on_rx)
1021 			b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ?
1022 					    false : true;
1023 		else
1024 			b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
1025 					    true : false;
1026 
1027 		edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul;
1028 		rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be);
1029 		rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate;
1030 		rtlpriv->dm.current_turbo_edca = true;
1031 	} else {
1032 		if (rtlpriv->dm.current_turbo_edca) {
1033 			u8 tmp = AC0_BE;
1034 			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
1035 						      (u8 *)(&tmp));
1036 		}
1037 		rtlpriv->dm.current_turbo_edca = false;
1038 	}
1039 
1040 exit:
1041 	rtlpriv->dm.is_any_nonbepkts = false;
1042 	last_txok_cnt = rtlpriv->stats.txbytesunicast;
1043 	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1044 }
1045 
1046 static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
1047 {
1048 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1049 	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
1050 	u8 cur_cck_cca_thresh;
1051 
1052 	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1053 		if (dm_digtable->rssi_val_min > 25) {
1054 			cur_cck_cca_thresh = 0xcd;
1055 		} else if ((dm_digtable->rssi_val_min <= 25) &&
1056 			   (dm_digtable->rssi_val_min > 10)) {
1057 			cur_cck_cca_thresh = 0x83;
1058 		} else {
1059 			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1060 				cur_cck_cca_thresh = 0x83;
1061 			else
1062 				cur_cck_cca_thresh = 0x40;
1063 		}
1064 	} else {
1065 		if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1066 			cur_cck_cca_thresh = 0x83;
1067 		else
1068 			cur_cck_cca_thresh = 0x40;
1069 	}
1070 
1071 	if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
1072 		rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
1073 
1074 	dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
1075 	dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
1076 	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
1077 		"CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
1078 }
1079 
1080 static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw)
1081 {
1082 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1083 	u8 reg_c50, reg_c58;
1084 	bool fw_current_in_ps_mode = false;
1085 
1086 	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1087 				      (u8 *)(&fw_current_in_ps_mode));
1088 	if (fw_current_in_ps_mode)
1089 		return;
1090 
1091 	reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
1092 	reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
1093 
1094 	if (reg_c50 > 0x28 && reg_c58 > 0x28) {
1095 		if (!rtlpriv->rtlhal.pre_edcca_enable) {
1096 			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
1097 			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
1098 		}
1099 	} else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
1100 		if (rtlpriv->rtlhal.pre_edcca_enable) {
1101 			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
1102 			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
1103 		}
1104 	}
1105 }
1106 
1107 static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
1108 {
1109 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1110 	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1111 	u8 crystal_cap;
1112 	u32 packet_count;
1113 	int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
1114 	int cfo_ave_diff;
1115 
1116 	if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1117 		if (rtldm->atc_status == ATC_STATUS_OFF) {
1118 			rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1119 				      ATC_STATUS_ON);
1120 			rtldm->atc_status = ATC_STATUS_ON;
1121 		}
1122 		if (rtlpriv->cfg->ops->get_btc_status()) {
1123 			if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) {
1124 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
1125 					"odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n");
1126 				return;
1127 			}
1128 		}
1129 
1130 		if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
1131 			rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
1132 			crystal_cap = rtldm->crystal_cap & 0x3f;
1133 			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1134 				      (crystal_cap | (crystal_cap << 6)));
1135 		}
1136 	} else {
1137 		cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
1138 		cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
1139 		packet_count = rtldm->packet_count;
1140 
1141 		if (packet_count == rtldm->packet_count_pre)
1142 			return;
1143 
1144 		rtldm->packet_count_pre = packet_count;
1145 
1146 		if (rtlpriv->phy.rf_type == RF_1T1R)
1147 			cfo_ave = cfo_khz_a;
1148 		else
1149 			cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
1150 
1151 		cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
1152 			       (rtldm->cfo_ave_pre - cfo_ave) :
1153 			       (cfo_ave - rtldm->cfo_ave_pre);
1154 
1155 		if (cfo_ave_diff > 20 && !rtldm->large_cfo_hit) {
1156 			rtldm->large_cfo_hit = true;
1157 			return;
1158 		} else
1159 			rtldm->large_cfo_hit = false;
1160 
1161 		rtldm->cfo_ave_pre = cfo_ave;
1162 
1163 		if (cfo_ave >= -rtldm->cfo_threshold &&
1164 		    cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
1165 			if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
1166 				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
1167 				rtldm->is_freeze = 1;
1168 			} else {
1169 				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
1170 			}
1171 		}
1172 
1173 		if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
1174 			adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1;
1175 		else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
1176 					rtlpriv->dm.crystal_cap > 0)
1177 			adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1;
1178 
1179 		if (adjust_xtal != 0) {
1180 			rtldm->is_freeze = 0;
1181 			rtldm->crystal_cap += adjust_xtal;
1182 
1183 			if (rtldm->crystal_cap > 0x3f)
1184 				rtldm->crystal_cap = 0x3f;
1185 			else if (rtldm->crystal_cap < 0)
1186 				rtldm->crystal_cap = 0;
1187 
1188 			crystal_cap = rtldm->crystal_cap & 0x3f;
1189 			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1190 				      (crystal_cap | (crystal_cap << 6)));
1191 		}
1192 
1193 		if (cfo_ave < CFO_THRESHOLD_ATC &&
1194 		    cfo_ave > -CFO_THRESHOLD_ATC) {
1195 			if (rtldm->atc_status == ATC_STATUS_ON) {
1196 				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1197 					      ATC_STATUS_OFF);
1198 				rtldm->atc_status = ATC_STATUS_OFF;
1199 			}
1200 		} else {
1201 			if (rtldm->atc_status == ATC_STATUS_OFF) {
1202 				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1203 					      ATC_STATUS_ON);
1204 				rtldm->atc_status = ATC_STATUS_ON;
1205 			}
1206 		}
1207 	}
1208 }
1209 
1210 static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw)
1211 {
1212 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1213 	u8 cnt = 0;
1214 	struct rtl_sta_info *drv_priv;
1215 
1216 	rtlpriv->dm.one_entry_only = false;
1217 
1218 	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1219 		rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1220 		rtlpriv->dm.one_entry_only = true;
1221 		return;
1222 	}
1223 
1224 	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1225 		rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1226 		rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1227 		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1228 		list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
1229 			cnt++;
1230 		}
1231 		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1232 
1233 		if (cnt == 1)
1234 			rtlpriv->dm.one_entry_only = true;
1235 	}
1236 }
1237 
1238 void rtl8723be_dm_watchdog(struct ieee80211_hw *hw)
1239 {
1240 	struct rtl_priv *rtlpriv = rtl_priv(hw);
1241 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1242 	bool fw_current_inpsmode = false;
1243 	bool fw_ps_awake = true;
1244 
1245 	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1246 				      (u8 *)(&fw_current_inpsmode));
1247 
1248 	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1249 				      (u8 *)(&fw_ps_awake));
1250 
1251 	if (ppsc->p2p_ps_info.p2p_ps_mode)
1252 		fw_ps_awake = false;
1253 
1254 	spin_lock(&rtlpriv->locks.rf_ps_lock);
1255 	if ((ppsc->rfpwr_state == ERFON) &&
1256 		((!fw_current_inpsmode) && fw_ps_awake) &&
1257 		(!ppsc->rfchange_inprogress)) {
1258 		rtl8723be_dm_common_info_self_update(hw);
1259 		rtl8723be_dm_false_alarm_counter_statistics(hw);
1260 		rtl8723be_dm_check_rssi_monitor(hw);
1261 		rtl8723be_dm_dig(hw);
1262 		rtl8723be_dm_dynamic_edcca(hw);
1263 		rtl8723be_dm_cck_packet_detection_thresh(hw);
1264 		rtl8723be_dm_refresh_rate_adaptive_mask(hw);
1265 		rtl8723be_dm_check_edca_turbo(hw);
1266 		rtl8723be_dm_dynamic_atc_switch(hw);
1267 		rtl8723be_dm_check_txpower_tracking(hw);
1268 		rtl8723be_dm_dynamic_txpower(hw);
1269 	}
1270 	spin_unlock(&rtlpriv->locks.rf_ps_lock);
1271 	rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
1272 }
1273