xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c (revision ae22a94997b8a03dcb3c922857c203246711f9d4)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2012  Realtek Corporation.*/
3 
4 #include "hal_bt_coexist.h"
5 #include "../pci.h"
6 #include "dm.h"
7 #include "fw.h"
8 #include "phy.h"
9 #include "reg.h"
10 #include "hal_btc.h"
11 
12 static bool bt_operation_on;
13 
14 void rtl8723e_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw,
15 						bool b_reject)
16 {
17 }
18 
19 void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw)
20 {
21 	struct rtl_priv *rtlpriv = rtl_priv(hw);
22 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
23 
24 	if (rtlpriv->link_info.busytraffic) {
25 		rtlpriv->btcoexist.cstate &=
26 			~BT_COEX_STATE_WIFI_IDLE;
27 
28 		if (rtlpriv->link_info.tx_busy_traffic)
29 			rtlpriv->btcoexist.cstate |=
30 				BT_COEX_STATE_WIFI_UPLINK;
31 		else
32 			rtlpriv->btcoexist.cstate &=
33 				~BT_COEX_STATE_WIFI_UPLINK;
34 
35 		if (rtlpriv->link_info.rx_busy_traffic)
36 			rtlpriv->btcoexist.cstate |=
37 				BT_COEX_STATE_WIFI_DOWNLINK;
38 		else
39 			rtlpriv->btcoexist.cstate &=
40 				~BT_COEX_STATE_WIFI_DOWNLINK;
41 	} else {
42 		rtlpriv->btcoexist.cstate |= BT_COEX_STATE_WIFI_IDLE;
43 		rtlpriv->btcoexist.cstate &=
44 			~BT_COEX_STATE_WIFI_UPLINK;
45 		rtlpriv->btcoexist.cstate &=
46 			~BT_COEX_STATE_WIFI_DOWNLINK;
47 	}
48 
49 	if (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
50 	    rtlpriv->mac80211.mode == WIRELESS_MODE_B) {
51 		rtlpriv->btcoexist.cstate |=
52 			BT_COEX_STATE_WIFI_LEGACY;
53 		rtlpriv->btcoexist.cstate &=
54 			~BT_COEX_STATE_WIFI_HT20;
55 		rtlpriv->btcoexist.cstate &=
56 			~BT_COEX_STATE_WIFI_HT40;
57 	} else {
58 		rtlpriv->btcoexist.cstate &=
59 			~BT_COEX_STATE_WIFI_LEGACY;
60 		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
61 			rtlpriv->btcoexist.cstate |=
62 				BT_COEX_STATE_WIFI_HT40;
63 			rtlpriv->btcoexist.cstate &=
64 				~BT_COEX_STATE_WIFI_HT20;
65 		} else {
66 			rtlpriv->btcoexist.cstate |=
67 				BT_COEX_STATE_WIFI_HT20;
68 			rtlpriv->btcoexist.cstate &=
69 				~BT_COEX_STATE_WIFI_HT40;
70 		}
71 	}
72 
73 	if (bt_operation_on)
74 		rtlpriv->btcoexist.cstate |= BT_COEX_STATE_BT30;
75 	else
76 		rtlpriv->btcoexist.cstate &= ~BT_COEX_STATE_BT30;
77 }
78 
79 u8 rtl8723e_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw,
80 					 u8 level_num, u8 rssi_thresh,
81 					 u8 rssi_thresh1)
82 
83 {
84 	struct rtl_priv *rtlpriv = rtl_priv(hw);
85 	long undecoratedsmoothed_pwdb;
86 	u8 bt_rssi_state = 0;
87 
88 	undecoratedsmoothed_pwdb = rtl8723e_dm_bt_get_rx_ss(hw);
89 
90 	if (level_num == 2) {
91 		rtlpriv->btcoexist.cstate &=
92 			~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
93 
94 		if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
95 		     BT_RSSI_STATE_LOW) ||
96 		    (rtlpriv->btcoexist.bt_pre_rssi_state ==
97 		     BT_RSSI_STATE_STAY_LOW)) {
98 			if (undecoratedsmoothed_pwdb >=
99 			    (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
100 				bt_rssi_state = BT_RSSI_STATE_HIGH;
101 				rtlpriv->btcoexist.cstate |=
102 					BT_COEX_STATE_WIFI_RSSI_1_HIGH;
103 				rtlpriv->btcoexist.cstate &=
104 					~BT_COEX_STATE_WIFI_RSSI_1_LOW;
105 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
106 					"[DM][BT], RSSI_1 state switch to High\n");
107 			} else {
108 				bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
109 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
110 					"[DM][BT], RSSI_1 state stay at Low\n");
111 			}
112 		} else {
113 			if (undecoratedsmoothed_pwdb < rssi_thresh) {
114 				bt_rssi_state = BT_RSSI_STATE_LOW;
115 				rtlpriv->btcoexist.cstate |=
116 					BT_COEX_STATE_WIFI_RSSI_1_LOW;
117 				rtlpriv->btcoexist.cstate &=
118 					~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
119 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
120 					"[DM][BT], RSSI_1 state switch to Low\n");
121 			} else {
122 				bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
123 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
124 					"[DM][BT], RSSI_1 state stay at High\n");
125 			}
126 		}
127 	} else if (level_num == 3) {
128 		if (rssi_thresh > rssi_thresh1) {
129 			rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
130 				"[DM][BT], RSSI_1 thresh error!!\n");
131 			return rtlpriv->btcoexist.bt_pre_rssi_state;
132 		}
133 
134 		if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
135 		     BT_RSSI_STATE_LOW) ||
136 		    (rtlpriv->btcoexist.bt_pre_rssi_state ==
137 		     BT_RSSI_STATE_STAY_LOW)) {
138 			if (undecoratedsmoothed_pwdb >=
139 			    (rssi_thresh+BT_FW_COEX_THRESH_TOL)) {
140 				bt_rssi_state = BT_RSSI_STATE_MEDIUM;
141 				rtlpriv->btcoexist.cstate |=
142 					BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
143 				rtlpriv->btcoexist.cstate &=
144 					~BT_COEX_STATE_WIFI_RSSI_1_LOW;
145 				rtlpriv->btcoexist.cstate &=
146 					~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
147 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
148 					"[DM][BT], RSSI_1 state switch to Medium\n");
149 			} else {
150 				bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
151 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
152 					"[DM][BT], RSSI_1 state stay at Low\n");
153 			}
154 		} else if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
155 			    BT_RSSI_STATE_MEDIUM) ||
156 			   (rtlpriv->btcoexist.bt_pre_rssi_state ==
157 			    BT_RSSI_STATE_STAY_MEDIUM)) {
158 			if (undecoratedsmoothed_pwdb >=
159 			    (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) {
160 				bt_rssi_state = BT_RSSI_STATE_HIGH;
161 				rtlpriv->btcoexist.cstate |=
162 					BT_COEX_STATE_WIFI_RSSI_1_HIGH;
163 				rtlpriv->btcoexist.cstate &=
164 					~BT_COEX_STATE_WIFI_RSSI_1_LOW;
165 				rtlpriv->btcoexist.cstate &=
166 					~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
167 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
168 					"[DM][BT], RSSI_1 state switch to High\n");
169 			} else if (undecoratedsmoothed_pwdb < rssi_thresh) {
170 				bt_rssi_state = BT_RSSI_STATE_LOW;
171 				rtlpriv->btcoexist.cstate |=
172 					BT_COEX_STATE_WIFI_RSSI_1_LOW;
173 				rtlpriv->btcoexist.cstate &=
174 					~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
175 				rtlpriv->btcoexist.cstate &=
176 					~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
177 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
178 					"[DM][BT], RSSI_1 state switch to Low\n");
179 			} else {
180 				bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM;
181 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
182 					"[DM][BT], RSSI_1 state stay at Medium\n");
183 			}
184 		} else {
185 			if (undecoratedsmoothed_pwdb < rssi_thresh1) {
186 				bt_rssi_state = BT_RSSI_STATE_MEDIUM;
187 				rtlpriv->btcoexist.cstate |=
188 					BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
189 				rtlpriv->btcoexist.cstate &=
190 					~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
191 				rtlpriv->btcoexist.cstate &=
192 					~BT_COEX_STATE_WIFI_RSSI_1_LOW;
193 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
194 					"[DM][BT], RSSI_1 state switch to Medium\n");
195 			} else {
196 				bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
197 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
198 					"[DM][BT], RSSI_1 state stay at High\n");
199 			}
200 		}
201 	}
202 	rtlpriv->btcoexist.bt_pre_rssi_state1 = bt_rssi_state;
203 
204 	return bt_rssi_state;
205 }
206 
207 u8 rtl8723e_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw,
208 					u8 level_num,
209 					u8 rssi_thresh,
210 					u8 rssi_thresh1)
211 {
212 	struct rtl_priv *rtlpriv = rtl_priv(hw);
213 	long undecoratedsmoothed_pwdb = 0;
214 	u8 bt_rssi_state = 0;
215 
216 	undecoratedsmoothed_pwdb = rtl8723e_dm_bt_get_rx_ss(hw);
217 
218 	if (level_num == 2) {
219 		rtlpriv->btcoexist.cstate &=
220 			~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
221 
222 		if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
223 		     BT_RSSI_STATE_LOW) ||
224 		    (rtlpriv->btcoexist.bt_pre_rssi_state ==
225 		     BT_RSSI_STATE_STAY_LOW)) {
226 			if (undecoratedsmoothed_pwdb >=
227 			    (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
228 				bt_rssi_state = BT_RSSI_STATE_HIGH;
229 				rtlpriv->btcoexist.cstate
230 					|= BT_COEX_STATE_WIFI_RSSI_HIGH;
231 				rtlpriv->btcoexist.cstate
232 					&= ~BT_COEX_STATE_WIFI_RSSI_LOW;
233 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
234 					"[DM][BT], RSSI state switch to High\n");
235 			} else {
236 				bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
237 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
238 					"[DM][BT], RSSI state stay at Low\n");
239 			}
240 		} else {
241 			if (undecoratedsmoothed_pwdb < rssi_thresh) {
242 				bt_rssi_state = BT_RSSI_STATE_LOW;
243 				rtlpriv->btcoexist.cstate
244 					|= BT_COEX_STATE_WIFI_RSSI_LOW;
245 				rtlpriv->btcoexist.cstate
246 					&= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
247 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
248 					"[DM][BT], RSSI state switch to Low\n");
249 			} else {
250 				bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
251 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
252 					"[DM][BT], RSSI state stay at High\n");
253 			}
254 		}
255 	} else if (level_num == 3) {
256 		if (rssi_thresh > rssi_thresh1) {
257 			rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
258 				"[DM][BT], RSSI thresh error!!\n");
259 			return rtlpriv->btcoexist.bt_pre_rssi_state;
260 		}
261 		if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
262 		     BT_RSSI_STATE_LOW) ||
263 		    (rtlpriv->btcoexist.bt_pre_rssi_state ==
264 		     BT_RSSI_STATE_STAY_LOW)) {
265 			if (undecoratedsmoothed_pwdb >=
266 			    (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
267 				bt_rssi_state = BT_RSSI_STATE_MEDIUM;
268 				rtlpriv->btcoexist.cstate
269 					|= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
270 				rtlpriv->btcoexist.cstate
271 					&= ~BT_COEX_STATE_WIFI_RSSI_LOW;
272 				rtlpriv->btcoexist.cstate
273 					&= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
274 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
275 					"[DM][BT], RSSI state switch to Medium\n");
276 			} else {
277 				bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
278 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
279 					"[DM][BT], RSSI state stay at Low\n");
280 			}
281 		} else if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
282 				BT_RSSI_STATE_MEDIUM) ||
283 			(rtlpriv->btcoexist.bt_pre_rssi_state ==
284 				BT_RSSI_STATE_STAY_MEDIUM)) {
285 			if (undecoratedsmoothed_pwdb >=
286 			    (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) {
287 				bt_rssi_state = BT_RSSI_STATE_HIGH;
288 				rtlpriv->btcoexist.cstate
289 					|= BT_COEX_STATE_WIFI_RSSI_HIGH;
290 				rtlpriv->btcoexist.cstate
291 					&= ~BT_COEX_STATE_WIFI_RSSI_LOW;
292 				rtlpriv->btcoexist.cstate
293 					&= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
294 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
295 					"[DM][BT], RSSI state switch to High\n");
296 			} else if (undecoratedsmoothed_pwdb < rssi_thresh) {
297 				bt_rssi_state = BT_RSSI_STATE_LOW;
298 				rtlpriv->btcoexist.cstate
299 					|= BT_COEX_STATE_WIFI_RSSI_LOW;
300 				rtlpriv->btcoexist.cstate
301 					&= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
302 				rtlpriv->btcoexist.cstate
303 					&= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
304 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
305 					"[DM][BT], RSSI state switch to Low\n");
306 			} else {
307 				bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM;
308 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
309 					"[DM][BT], RSSI state stay at Medium\n");
310 			}
311 		} else {
312 			if (undecoratedsmoothed_pwdb < rssi_thresh1) {
313 				bt_rssi_state = BT_RSSI_STATE_MEDIUM;
314 				rtlpriv->btcoexist.cstate
315 					|= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
316 				rtlpriv->btcoexist.cstate
317 					&= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
318 				rtlpriv->btcoexist.cstate
319 					&= ~BT_COEX_STATE_WIFI_RSSI_LOW;
320 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
321 					"[DM][BT], RSSI state switch to Medium\n");
322 			} else {
323 				bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
324 				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
325 					"[DM][BT], RSSI state stay at High\n");
326 			}
327 		}
328 	}
329 	rtlpriv->btcoexist.bt_pre_rssi_state = bt_rssi_state;
330 	return bt_rssi_state;
331 }
332 
333 long rtl8723e_dm_bt_get_rx_ss(struct ieee80211_hw *hw)
334 {
335 	struct rtl_priv *rtlpriv = rtl_priv(hw);
336 	long undecoratedsmoothed_pwdb = 0;
337 
338 	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
339 		undecoratedsmoothed_pwdb =
340 			GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
341 	} else {
342 		undecoratedsmoothed_pwdb
343 			= rtlpriv->dm.entry_min_undec_sm_pwdb;
344 	}
345 	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
346 		"%s = %ld\n", __func__,
347 		undecoratedsmoothed_pwdb);
348 
349 	return undecoratedsmoothed_pwdb;
350 }
351 
352 void rtl8723e_dm_bt_balance(struct ieee80211_hw *hw,
353 			    bool balance_on, u8 ms0, u8 ms1)
354 {
355 	struct rtl_priv *rtlpriv = rtl_priv(hw);
356 	u8 h2c_parameter[3] = {0};
357 
358 	if (balance_on) {
359 		h2c_parameter[2] = 1;
360 		h2c_parameter[1] = ms1;
361 		h2c_parameter[0] = ms0;
362 		rtlpriv->btcoexist.fw_coexist_all_off = false;
363 	} else {
364 		h2c_parameter[2] = 0;
365 		h2c_parameter[1] = 0;
366 		h2c_parameter[0] = 0;
367 	}
368 	rtlpriv->btcoexist.balance_on = balance_on;
369 
370 	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
371 		"[DM][BT], Balance=[%s:%dms:%dms], write 0xc=0x%x\n",
372 		balance_on ? "ON" : "OFF", ms0, ms1, h2c_parameter[0] << 16 |
373 		h2c_parameter[1] << 8 | h2c_parameter[2]);
374 
375 	rtl8723e_fill_h2c_cmd(hw, 0xc, 3, h2c_parameter);
376 }
377 
378 
379 void rtl8723e_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type)
380 {
381 	struct rtl_priv *rtlpriv = rtl_priv(hw);
382 
383 	if (type == BT_AGCTABLE_OFF) {
384 		rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
385 			"[BT]AGCTable Off!\n");
386 		rtl_write_dword(rtlpriv, 0xc78, 0x641c0001);
387 		rtl_write_dword(rtlpriv, 0xc78, 0x631d0001);
388 		rtl_write_dword(rtlpriv, 0xc78, 0x621e0001);
389 		rtl_write_dword(rtlpriv, 0xc78, 0x611f0001);
390 		rtl_write_dword(rtlpriv, 0xc78, 0x60200001);
391 
392 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
393 					RF_RX_AGC_HP, 0xfffff, 0x32000);
394 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
395 					RF_RX_AGC_HP, 0xfffff, 0x71000);
396 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
397 					RF_RX_AGC_HP, 0xfffff, 0xb0000);
398 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
399 					RF_RX_AGC_HP, 0xfffff, 0xfc000);
400 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
401 					RF_RX_G1, 0xfffff, 0x30355);
402 	} else if (type == BT_AGCTABLE_ON) {
403 		rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
404 			"[BT]AGCTable On!\n");
405 		rtl_write_dword(rtlpriv, 0xc78, 0x4e1c0001);
406 		rtl_write_dword(rtlpriv, 0xc78, 0x4d1d0001);
407 		rtl_write_dword(rtlpriv, 0xc78, 0x4c1e0001);
408 		rtl_write_dword(rtlpriv, 0xc78, 0x4b1f0001);
409 		rtl_write_dword(rtlpriv, 0xc78, 0x4a200001);
410 
411 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
412 					RF_RX_AGC_HP, 0xfffff, 0xdc000);
413 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
414 					RF_RX_AGC_HP, 0xfffff, 0x90000);
415 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
416 					RF_RX_AGC_HP, 0xfffff, 0x51000);
417 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
418 					RF_RX_AGC_HP, 0xfffff, 0x12000);
419 		rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
420 					RF_RX_G1, 0xfffff, 0x00355);
421 
422 		rtlpriv->btcoexist.sw_coexist_all_off = false;
423 	}
424 }
425 
426 void rtl8723e_dm_bt_bb_back_off_level(struct ieee80211_hw *hw, u8 type)
427 {
428 	struct rtl_priv *rtlpriv = rtl_priv(hw);
429 
430 	if (type == BT_BB_BACKOFF_OFF) {
431 		rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
432 			"[BT]BBBackOffLevel Off!\n");
433 		rtl_write_dword(rtlpriv, 0xc04, 0x3a05611);
434 	} else if (type == BT_BB_BACKOFF_ON) {
435 		rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
436 			"[BT]BBBackOffLevel On!\n");
437 		rtl_write_dword(rtlpriv, 0xc04, 0x3a07611);
438 		rtlpriv->btcoexist.sw_coexist_all_off = false;
439 	}
440 }
441 
442 void rtl8723e_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw)
443 {
444 	struct rtl_priv *rtlpriv = rtl_priv(hw);
445 	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
446 		"rtl8723e_dm_bt_fw_coex_all_off()\n");
447 
448 	if (rtlpriv->btcoexist.fw_coexist_all_off)
449 		return;
450 
451 	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
452 		"rtl8723e_dm_bt_fw_coex_all_off(), real Do\n");
453 	rtl8723e_dm_bt_fw_coex_all_off_8723a(hw);
454 	rtlpriv->btcoexist.fw_coexist_all_off = true;
455 }
456 
457 void rtl8723e_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw)
458 {
459 	struct rtl_priv *rtlpriv = rtl_priv(hw);
460 
461 	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
462 		"%s\n", __func__);
463 
464 	if (rtlpriv->btcoexist.sw_coexist_all_off)
465 		return;
466 
467 	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
468 		"%s, real Do\n", __func__);
469 	rtl8723e_dm_bt_sw_coex_all_off_8723a(hw);
470 	rtlpriv->btcoexist.sw_coexist_all_off = true;
471 }
472 
473 void rtl8723e_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw)
474 {
475 	struct rtl_priv *rtlpriv = rtl_priv(hw);
476 
477 	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
478 		"%s\n", __func__);
479 
480 	if (rtlpriv->btcoexist.hw_coexist_all_off)
481 		return;
482 	rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
483 		"%s, real Do\n", __func__);
484 
485 	rtl8723e_dm_bt_hw_coex_all_off_8723a(hw);
486 
487 	rtlpriv->btcoexist.hw_coexist_all_off = true;
488 }
489 
490 void rtl8723e_btdm_coex_all_off(struct ieee80211_hw *hw)
491 {
492 	rtl8723e_dm_bt_fw_coex_all_off(hw);
493 	rtl8723e_dm_bt_sw_coex_all_off(hw);
494 	rtl8723e_dm_bt_hw_coex_all_off(hw);
495 }
496 
497 bool rtl8723e_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw)
498 {
499 	struct rtl_priv *rtlpriv = rtl_priv(hw);
500 
501 	if ((rtlpriv->btcoexist.previous_state == rtlpriv->btcoexist.cstate) &&
502 	    (rtlpriv->btcoexist.previous_state_h ==
503 	     rtlpriv->btcoexist.cstate_h))
504 		return false;
505 	return true;
506 }
507 
508 bool rtl8723e_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw)
509 {
510 	struct rtl_priv *rtlpriv = rtl_priv(hw);
511 
512 	if (rtlpriv->link_info.tx_busy_traffic)
513 		return true;
514 	return false;
515 }
516