xref: /linux/drivers/net/wireless/realtek/rtw88/coex.c (revision 91a4855d6c03e770e42f17c798a36a3c46e63de2)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2018-2019  Realtek Corporation
3  */
4 
5 #include "main.h"
6 #include "coex.h"
7 #include "fw.h"
8 #include "ps.h"
9 #include "debug.h"
10 #include "reg.h"
11 #include "phy.h"
12 
13 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
14 				   u8 rssi, u8 rssi_thresh)
15 {
16 	const struct rtw_chip_info *chip = rtwdev->chip;
17 	u8 tol = chip->rssi_tolerance;
18 	u8 next_state;
19 
20 	if (pre_state == COEX_RSSI_STATE_LOW ||
21 	    pre_state == COEX_RSSI_STATE_STAY_LOW) {
22 		if (rssi >= (rssi_thresh + tol))
23 			next_state = COEX_RSSI_STATE_HIGH;
24 		else
25 			next_state = COEX_RSSI_STATE_STAY_LOW;
26 	} else {
27 		if (rssi < rssi_thresh)
28 			next_state = COEX_RSSI_STATE_LOW;
29 		else
30 			next_state = COEX_RSSI_STATE_STAY_HIGH;
31 	}
32 
33 	return next_state;
34 }
35 
36 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
37 				bool tx_limit_en, bool ampdu_limit_en)
38 {
39 	const struct rtw_chip_info *chip = rtwdev->chip;
40 	struct rtw_coex *coex = &rtwdev->coex;
41 	struct rtw_coex_stat *coex_stat = &coex->stat;
42 	u8 num_of_active_port = 1;
43 
44 	if (!chip->scbd_support)
45 		return;
46 
47 	/* force max tx retry limit = 8 */
48 	if (coex_stat->wl_tx_limit_en == tx_limit_en &&
49 	    coex_stat->wl_ampdu_limit_en == ampdu_limit_en)
50 		return;
51 
52 	if (!coex_stat->wl_tx_limit_en) {
53 		coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC);
54 		coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH);
55 		coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT);
56 	}
57 
58 	if (!coex_stat->wl_ampdu_limit_en)
59 		coex_stat->ampdu_max_time =
60 				rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);
61 
62 	coex_stat->wl_tx_limit_en = tx_limit_en;
63 	coex_stat->wl_ampdu_limit_en = ampdu_limit_en;
64 
65 	if (tx_limit_en) {
66 		/* set BT polluted packet on for tx rate adaptive,
67 		 * not including tx retry broken by PTA
68 		 */
69 		rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
70 
71 		/* set queue life time to avoid can't reach tx retry limit
72 		 * if tx is always broken by GNT_BT
73 		 */
74 		if (num_of_active_port <= 1)
75 			rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
76 		rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
77 
78 		/* auto rate fallback step within 8 retries */
79 		rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
80 		rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
81 	} else {
82 		rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
83 		rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
84 
85 		rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit);
86 		rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc);
87 		rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch);
88 	}
89 
90 	if (ampdu_limit_en)
91 		rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);
92 	else
93 		rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,
94 			   coex_stat->ampdu_max_time);
95 }
96 
97 static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
98 {
99 	struct rtw_coex *coex = &rtwdev->coex;
100 	struct rtw_coex_dm *coex_dm = &coex->dm;
101 	bool tx_limit = false;
102 	bool tx_agg_ctrl = false;
103 
104 	if (!coex->under_5g && coex_dm->bt_status != COEX_BTSTATUS_NCON_IDLE) {
105 		tx_limit = true;
106 		tx_agg_ctrl = true;
107 	}
108 
109 	rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
110 }
111 
112 static bool rtw_coex_freerun_check(struct rtw_dev *rtwdev)
113 {
114 	struct rtw_coex *coex = &rtwdev->coex;
115 	struct rtw_coex_dm *coex_dm = &coex->dm;
116 	struct rtw_coex_stat *coex_stat = &coex->stat;
117 	struct rtw_efuse *efuse = &rtwdev->efuse;
118 	u8 bt_rssi;
119 	u8 ant_distance = 10;
120 
121 	if (coex_stat->bt_disabled)
122 		return false;
123 
124 	if (efuse->share_ant || ant_distance <= 5 || !coex_stat->wl_gl_busy)
125 		return false;
126 
127 	if (ant_distance >= 40 || coex_stat->bt_hid_pair_num >= 2)
128 		return true;
129 
130 	/* ant_distance = 5 ~ 40  */
131 	if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]) &&
132 	    COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0]))
133 		return true;
134 
135 	if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
136 		bt_rssi = coex_dm->bt_rssi_state[0];
137 	else
138 		bt_rssi = coex_dm->bt_rssi_state[1];
139 
140 	if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
141 	    COEX_RSSI_HIGH(bt_rssi) &&
142 	    coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)
143 		return true;
144 
145 	return false;
146 }
147 
148 static void rtw_coex_wl_slot_extend(struct rtw_dev *rtwdev, bool enable)
149 {
150 	struct rtw_coex *coex = &rtwdev->coex;
151 	struct rtw_coex_stat *coex_stat = &coex->stat;
152 	u8 para[6] = {0};
153 
154 	para[0] = COEX_H2C69_WL_LEAKAP;
155 	para[1] = PARA1_H2C69_DIS_5MS;
156 
157 	if (enable)
158 		para[1] = PARA1_H2C69_EN_5MS;
159 	else
160 		coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
161 
162 	coex_stat->wl_slot_extend = enable;
163 	rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
164 }
165 
166 static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
167 {
168 	struct rtw_coex *coex = &rtwdev->coex;
169 	struct rtw_coex_stat *coex_stat = &coex->stat;
170 
171 	if (coex->manual_control || coex->stop_dm)
172 		return;
173 
174 
175 	if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {
176 		rtw_dbg(rtwdev, RTW_DBG_COEX,
177 			"[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");
178 		rtw_coex_wl_slot_extend(rtwdev, false);
179 		return;
180 	}
181 
182 	if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl &&
183 	    !coex_stat->wl_cck_lock_ever) {
184 		if (coex_stat->wl_fw_dbg_info[7] <= 5)
185 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++;
186 		else
187 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
188 
189 		rtw_dbg(rtwdev, RTW_DBG_COEX,
190 			"[BTCoex], 5ms WL slot extend cnt = %d!!\n",
191 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]);
192 
193 		if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {
194 			rtw_dbg(rtwdev, RTW_DBG_COEX,
195 				"[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");
196 			rtw_coex_wl_slot_extend(rtwdev, false);
197 		}
198 	} else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {
199 		rtw_dbg(rtwdev, RTW_DBG_COEX,
200 			"[BTCoex], set h2c 0x69 opcode 12 to turn on 5ms WL slot extend!!\n");
201 
202 		rtw_coex_wl_slot_extend(rtwdev, true);
203 	}
204 }
205 
206 static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
207 {
208 	struct rtw_coex *coex = &rtwdev->coex;
209 	struct rtw_coex_stat *coex_stat = &coex->stat;
210 	struct rtw_coex_dm *coex_dm = &coex->dm;
211 
212 	bool is_cck_lock_rate = false;
213 
214 	if (coex_stat->wl_coex_mode != COEX_WLINK_2G1PORT &&
215 	    coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)
216 		return;
217 
218 	if (coex_dm->bt_status == COEX_BTSTATUS_INQ_PAGE ||
219 	    coex_stat->bt_setup_link) {
220 		coex_stat->wl_cck_lock = false;
221 		coex_stat->wl_cck_lock_pre = false;
222 		return;
223 	}
224 
225 	if (coex_stat->wl_rx_rate <= COEX_CCK_2 ||
226 	    coex_stat->wl_rts_rx_rate <= COEX_CCK_2)
227 		is_cck_lock_rate = true;
228 
229 	if (coex_stat->wl_connected && coex_stat->wl_gl_busy &&
230 	    COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
231 	    (coex_dm->bt_status == COEX_BTSTATUS_ACL_BUSY ||
232 	     coex_dm->bt_status == COEX_BTSTATUS_ACL_SCO_BUSY ||
233 	     coex_dm->bt_status == COEX_BTSTATUS_SCO_BUSY)) {
234 		if (is_cck_lock_rate) {
235 			coex_stat->wl_cck_lock = true;
236 
237 			rtw_dbg(rtwdev, RTW_DBG_COEX,
238 				"[BTCoex], cck locking...\n");
239 
240 		} else {
241 			coex_stat->wl_cck_lock = false;
242 
243 			rtw_dbg(rtwdev, RTW_DBG_COEX,
244 				"[BTCoex], cck unlock...\n");
245 		}
246 	} else {
247 		coex_stat->wl_cck_lock = false;
248 	}
249 
250 	/* CCK lock identification */
251 	if (coex_stat->wl_cck_lock && !coex_stat->wl_cck_lock_pre)
252 		ieee80211_queue_delayed_work(rtwdev->hw, &coex->wl_ccklock_work,
253 					     3 * HZ);
254 
255 	coex_stat->wl_cck_lock_pre = coex_stat->wl_cck_lock;
256 }
257 
258 static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
259 {
260 	struct rtw_coex *coex = &rtwdev->coex;
261 	struct rtw_coex_stat *coex_stat = &coex->stat;
262 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
263 	u32 cnt_cck;
264 	bool wl_cck_lock = false;
265 
266 	/* wifi noisy environment identification */
267 	cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
268 
269 	if (!coex_stat->wl_gl_busy && !wl_cck_lock) {
270 		if (cnt_cck > 250) {
271 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
272 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
273 
274 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) {
275 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
276 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
277 			}
278 		} else if (cnt_cck < 100) {
279 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5)
280 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++;
281 
282 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) {
283 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
284 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
285 			}
286 		} else {
287 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)
288 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;
289 
290 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) {
291 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
292 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
293 			}
294 		}
295 
296 		if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5)
297 			coex_stat->wl_noisy_level = 2;
298 		else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5)
299 			coex_stat->wl_noisy_level = 1;
300 		else
301 			coex_stat->wl_noisy_level = 0;
302 
303 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wl_noisy_level = %d\n",
304 			coex_stat->wl_noisy_level);
305 	}
306 }
307 
308 static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
309 {
310 	struct rtw_coex *coex = &rtwdev->coex;
311 	struct rtw_coex_stat *coex_stat = &coex->stat;
312 	u8 para[6] = {};
313 	u8 times;
314 	u16 tbtt_interval = coex_stat->wl_beacon_interval;
315 
316 	if (coex_stat->tdma_timer_base == type)
317 		return;
318 
319 	coex_stat->tdma_timer_base = type;
320 
321 	para[0] = COEX_H2C69_TDMA_SLOT;
322 
323 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], tbtt_interval = %d\n",
324 		tbtt_interval);
325 
326 	if (type == TDMA_TIMER_TYPE_4SLOT && tbtt_interval < 120) {
327 		para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */
328 	} else if (tbtt_interval < 80 && tbtt_interval > 0) {
329 		times = 100 / tbtt_interval;
330 		if (100 % tbtt_interval != 0)
331 			times++;
332 
333 		para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times);
334 	} else if (tbtt_interval >= 180) {
335 		times = tbtt_interval / 100;
336 		if (tbtt_interval % 100 <= 80)
337 			times--;
338 
339 		para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times) |
340 			  FIELD_PREP(PARA1_H2C69_TBTT_DIV100, 1);
341 	} else {
342 		para[1] = PARA1_H2C69_TDMA_2SLOT;
343 	}
344 
345 	rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
346 
347 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): h2c_0x69 = 0x%x\n",
348 		__func__, para[1]);
349 
350 	/* no 5ms_wl_slot_extend for 4-slot mode  */
351 	if (coex_stat->tdma_timer_base == 3)
352 		rtw_coex_wl_ccklock_action(rtwdev);
353 }
354 
355 static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
356 				     u8 data)
357 {
358 	u32 addr;
359 
360 	addr = REG_BT_COEX_TABLE_H + (bitmap / 8);
361 	bitmap = bitmap % 8;
362 
363 	rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);
364 }
365 
366 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
367 {
368 	const struct rtw_chip_info *chip = rtwdev->chip;
369 	struct rtw_coex *coex = &rtwdev->coex;
370 	struct rtw_coex_stat *coex_stat = &coex->stat;
371 	u16 val = 0x2;
372 
373 	if (!chip->scbd_support)
374 		return;
375 
376 	val |= coex_stat->score_board;
377 
378 	/* for 8822b, scbd[10] is CQDDR on
379 	 * for 8822c, scbd[10] is no fix 2M
380 	 */
381 	if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {
382 		if (set)
383 			val &= ~COEX_SCBD_FIX2M;
384 		else
385 			val |= COEX_SCBD_FIX2M;
386 	} else {
387 		if (set)
388 			val |= bitpos;
389 		else
390 			val &= ~bitpos;
391 	}
392 
393 	if (val != coex_stat->score_board) {
394 		coex_stat->score_board = val;
395 		val |= BIT_BT_INT_EN;
396 		rtw_write16(rtwdev, REG_WIFI_BT_INFO, val);
397 	}
398 }
399 EXPORT_SYMBOL(rtw_coex_write_scbd);
400 
401 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
402 {
403 	const struct rtw_chip_info *chip = rtwdev->chip;
404 
405 	if (!chip->scbd_support)
406 		return 0;
407 
408 	return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);
409 }
410 
411 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
412 {
413 	const struct rtw_chip_info *chip = rtwdev->chip;
414 	struct rtw_coex *coex = &rtwdev->coex;
415 	struct rtw_coex_stat *coex_stat = &coex->stat;
416 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
417 	u8 cnt = 0;
418 	u32 wait_cnt;
419 	bool btk, wlk;
420 
421 	if (coex_rfe->wlg_at_btg && chip->scbd_support &&
422 	    coex_stat->bt_iqk_state != 0xff) {
423 		rtw_dbg(rtwdev, RTW_DBG_COEX,
424 			"[BTCoex], (Before Ant Setup) Delay by IQK\n");
425 
426 		wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
427 		do {
428 			/* BT RFK */
429 			btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);
430 
431 			/* WL RFK */
432 			wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);
433 
434 			if (!btk && !wlk)
435 				break;
436 
437 			rtw_dbg(rtwdev, RTW_DBG_COEX,
438 				"[BTCoex], (Before Ant Setup) wlk = %d, btk = %d\n",
439 				wlk, btk);
440 
441 			mdelay(COEX_MIN_DELAY);
442 		} while (++cnt < wait_cnt);
443 
444 		if (cnt >= wait_cnt)
445 			coex_stat->bt_iqk_state = 0xff;
446 	}
447 }
448 
449 void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
450 {
451 	struct rtw_coex *coex = &rtwdev->coex;
452 	struct rtw_coex_stat *coex_stat = &coex->stat;
453 
454 	if (coex_stat->bt_disabled)
455 		return;
456 
457 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
458 
459 	rtw_fw_query_bt_info(rtwdev);
460 }
461 
462 static void rtw_coex_gnt_workaround(struct rtw_dev *rtwdev, bool force, u8 mode)
463 {
464 	rtw_coex_set_gnt_fix(rtwdev);
465 }
466 
467 static void rtw_coex_monitor_bt_ctr(struct rtw_dev *rtwdev)
468 {
469 	struct rtw_coex *coex = &rtwdev->coex;
470 	struct rtw_coex_stat *coex_stat = &coex->stat;
471 	u32 tmp;
472 
473 	tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS);
474 	coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, tmp);
475 	coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, tmp);
476 
477 	tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1);
478 	coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, tmp);
479 	coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, tmp);
480 
481 	rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL,
482 		   BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN);
483 
484 	rtw_dbg(rtwdev, RTW_DBG_COEX,
485 		"[BTCoex], Hi-Pri Rx/Tx: %d/%d, Lo-Pri Rx/Tx: %d/%d\n",
486 		coex_stat->hi_pri_rx, coex_stat->hi_pri_tx,
487 		coex_stat->lo_pri_rx, coex_stat->lo_pri_tx);
488 
489 	if (coex_stat->wl_under_lps || coex_stat->wl_under_ips ||
490 	    (coex_stat->hi_pri_rx > 60000 && coex_stat->hi_pri_tx == 60000 &&
491 	     coex_stat->lo_pri_rx > 60000 && coex_stat->lo_pri_tx == 60000))
492 		coex_stat->bt_ctr_ok = false;
493 	else
494 		coex_stat->bt_ctr_ok = true;
495 }
496 
497 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
498 {
499 	const struct rtw_chip_info *chip = rtwdev->chip;
500 	struct rtw_coex *coex = &rtwdev->coex;
501 	struct rtw_coex_stat *coex_stat = &coex->stat;
502 	struct rtw_coex_dm *coex_dm = &coex->dm;
503 	bool bt_disabled = false;
504 	bool bt_active = true;
505 	u16 score_board;
506 
507 	if (chip->scbd_support) {
508 		score_board = rtw_coex_read_scbd(rtwdev);
509 		bt_disabled = !(score_board & COEX_SCBD_ONOFF);
510 	} else {
511 		if (coex_stat->hi_pri_tx == 0 && coex_stat->hi_pri_rx == 0 &&
512 		    coex_stat->lo_pri_tx == 0 && coex_stat->lo_pri_rx == 0)
513 			bt_active = false;
514 
515 		if (coex_stat->hi_pri_tx == 0xffff && coex_stat->hi_pri_rx == 0xffff &&
516 		    coex_stat->lo_pri_tx == 0xffff && coex_stat->lo_pri_rx == 0xffff)
517 			bt_active = false;
518 
519 		if (bt_active) {
520 			coex_stat->bt_disable_cnt = 0;
521 			bt_disabled = false;
522 		} else {
523 			coex_stat->bt_disable_cnt++;
524 			if (coex_stat->bt_disable_cnt >= 10)
525 				bt_disabled = true;
526 		}
527 	}
528 
529 	if (coex_stat->bt_disabled != bt_disabled) {
530 		rtw_dbg(rtwdev, RTW_DBG_COEX,
531 			"[BTCoex], BT state changed (%d) -> (%d)\n",
532 			coex_stat->bt_disabled, bt_disabled);
533 
534 		coex_stat->bt_disabled = bt_disabled;
535 		coex_stat->bt_ble_scan_type = 0;
536 		coex_dm->cur_bt_lna_lvl = 0;
537 
538 		if (!coex_stat->bt_disabled) {
539 			coex_stat->bt_reenable = true;
540 			ieee80211_queue_delayed_work(rtwdev->hw,
541 						     &coex->bt_reenable_work,
542 						     15 * HZ);
543 		} else {
544 			coex_stat->bt_mailbox_reply = false;
545 			coex_stat->bt_reenable = false;
546 		}
547 	}
548 }
549 
550 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
551 {
552 	const struct rtw_chip_info *chip = rtwdev->chip;
553 	struct rtw_coex *coex = &rtwdev->coex;
554 	struct rtw_coex_stat *coex_stat = &coex->stat;
555 	struct rtw_coex_dm *coex_dm = &coex->dm;
556 	struct rtw_traffic_stats *stats = &rtwdev->stats;
557 	bool is_5G = false;
558 	bool wl_busy = false;
559 	bool scan = false, link = false;
560 	int i;
561 	u8 rssi_state;
562 	u8 rssi_step;
563 	u8 rssi;
564 
565 	scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);
566 	coex_stat->wl_connected = !!rtwdev->sta_cnt;
567 
568 	wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
569 	if (wl_busy != coex_stat->wl_gl_busy) {
570 		if (wl_busy)
571 			coex_stat->wl_gl_busy = true;
572 		else
573 			ieee80211_queue_delayed_work(rtwdev->hw,
574 						     &coex->wl_remain_work,
575 						     12 * HZ);
576 	}
577 
578 	if (stats->tx_throughput > stats->rx_throughput)
579 		coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
580 	else
581 		coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;
582 
583 	if (scan || link || reason == COEX_RSN_2GCONSTART ||
584 	    reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)
585 		coex_stat->wl_linkscan_proc = true;
586 	else
587 		coex_stat->wl_linkscan_proc = false;
588 
589 	rtw_coex_wl_noisy_detect(rtwdev);
590 
591 	for (i = 0; i < 4; i++) {
592 		rssi_state = coex_dm->wl_rssi_state[i];
593 		rssi_step = chip->wl_rssi_step[i];
594 		rssi = rtwdev->dm_info.min_rssi;
595 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
596 						      rssi, rssi_step);
597 		coex_dm->wl_rssi_state[i] = rssi_state;
598 	}
599 
600 	if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
601 	    coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
602 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
603 	else
604 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
605 
606 	switch (reason) {
607 	case COEX_RSN_5GSCANSTART:
608 	case COEX_RSN_5GSWITCHBAND:
609 	case COEX_RSN_5GCONSTART:
610 
611 		is_5G = true;
612 		break;
613 	case COEX_RSN_2GSCANSTART:
614 	case COEX_RSN_2GSWITCHBAND:
615 	case COEX_RSN_2GCONSTART:
616 
617 		is_5G = false;
618 		break;
619 	default:
620 		if (rtwdev->hal.current_band_type == RTW_BAND_5G)
621 			is_5G = true;
622 		else
623 			is_5G = false;
624 		break;
625 	}
626 
627 	coex->under_5g = is_5G;
628 }
629 
630 static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)
631 {
632 	struct rtw_c2h_cmd *c2h;
633 	u32 pkt_offset;
634 
635 	pkt_offset = *((u32 *)resp->cb);
636 	c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);
637 
638 	return c2h->payload;
639 }
640 
641 void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)
642 {
643 	struct rtw_coex *coex = &rtwdev->coex;
644 	u8 *payload = get_payload_from_coex_resp(skb);
645 
646 	if (payload[0] != COEX_RESP_ACK_BY_WL_FW) {
647 		dev_kfree_skb_any(skb);
648 		return;
649 	}
650 
651 	skb_queue_tail(&coex->queue, skb);
652 	wake_up(&coex->wait);
653 }
654 
655 static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
656 					     struct rtw_coex_info_req *req)
657 {
658 	struct rtw_coex *coex = &rtwdev->coex;
659 	struct sk_buff *skb_resp = NULL;
660 
661 	lockdep_assert_held(&rtwdev->mutex);
662 
663 	rtw_fw_query_bt_mp_info(rtwdev, req);
664 
665 	if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
666 				COEX_REQUEST_TIMEOUT)) {
667 		rtw_err(rtwdev, "coex request time out\n");
668 		goto out;
669 	}
670 
671 	skb_resp = skb_dequeue(&coex->queue);
672 	if (!skb_resp) {
673 		rtw_err(rtwdev, "failed to get coex info response\n");
674 		goto out;
675 	}
676 
677 out:
678 	return skb_resp;
679 }
680 
681 static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
682 {
683 	struct rtw_coex_info_req req = {0};
684 	struct sk_buff *skb;
685 	u8 *payload;
686 
687 	req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
688 	skb = rtw_coex_info_request(rtwdev, &req);
689 	if (!skb)
690 		return false;
691 
692 	payload = get_payload_from_coex_resp(skb);
693 	*scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
694 	dev_kfree_skb_any(skb);
695 	return true;
696 }
697 
698 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
699 					     u8 lna_constrain_level)
700 {
701 	struct rtw_coex_info_req req = {0};
702 	struct sk_buff *skb;
703 
704 	req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
705 	req.para1 = lna_constrain_level;
706 	skb = rtw_coex_info_request(rtwdev, &req);
707 	if (!skb)
708 		return false;
709 
710 	dev_kfree_skb_any(skb);
711 	return true;
712 }
713 
714 #define case_BTSTATUS(src) \
715 	case COEX_BTSTATUS_##src: return #src
716 
717 static const char *rtw_coex_get_bt_status_string(u8 bt_status)
718 {
719 	switch (bt_status) {
720 	case_BTSTATUS(NCON_IDLE);
721 	case_BTSTATUS(CON_IDLE);
722 	case_BTSTATUS(INQ_PAGE);
723 	case_BTSTATUS(ACL_BUSY);
724 	case_BTSTATUS(SCO_BUSY);
725 	case_BTSTATUS(ACL_SCO_BUSY);
726 	default:
727 		return "Unknown";
728 	}
729 }
730 
731 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
732 {
733 	const struct rtw_chip_info *chip = rtwdev->chip;
734 	struct rtw_coex *coex = &rtwdev->coex;
735 	struct rtw_coex_stat *coex_stat = &coex->stat;
736 	struct rtw_coex_dm *coex_dm = &coex->dm;
737 	u8 i;
738 	u8 rssi_state;
739 	u8 rssi_step;
740 	u8 rssi;
741 
742 	/* update wl/bt rssi by btinfo */
743 	for (i = 0; i < COEX_RSSI_STEP; i++) {
744 		rssi_state = coex_dm->bt_rssi_state[i];
745 		rssi_step = chip->bt_rssi_step[i];
746 		rssi = coex_stat->bt_rssi;
747 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, rssi,
748 						      rssi_step);
749 		coex_dm->bt_rssi_state[i] = rssi_state;
750 	}
751 
752 	if (coex_stat->bt_ble_scan_en &&
753 	    coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
754 		u8 scan_type;
755 
756 		if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {
757 			coex_stat->bt_ble_scan_type = scan_type;
758 			if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)
759 				coex_stat->bt_init_scan = true;
760 			else
761 				coex_stat->bt_init_scan = false;
762 		}
763 	}
764 
765 	coex_stat->bt_profile_num = 0;
766 
767 	/* set link exist status */
768 	if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
769 		coex_stat->bt_link_exist = false;
770 		coex_stat->bt_pan_exist = false;
771 		coex_stat->bt_a2dp_exist = false;
772 		coex_stat->bt_hid_exist = false;
773 		coex_stat->bt_hfp_exist = false;
774 	} else {
775 		/* connection exists */
776 		coex_stat->bt_link_exist = true;
777 		if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {
778 			coex_stat->bt_pan_exist = true;
779 			coex_stat->bt_profile_num++;
780 		} else {
781 			coex_stat->bt_pan_exist = false;
782 		}
783 
784 		if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {
785 			coex_stat->bt_a2dp_exist = true;
786 			coex_stat->bt_profile_num++;
787 		} else {
788 			coex_stat->bt_a2dp_exist = false;
789 		}
790 
791 		if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {
792 			coex_stat->bt_hid_exist = true;
793 			coex_stat->bt_profile_num++;
794 		} else {
795 			coex_stat->bt_hid_exist = false;
796 		}
797 
798 		if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {
799 			coex_stat->bt_hfp_exist = true;
800 			coex_stat->bt_profile_num++;
801 		} else {
802 			coex_stat->bt_hfp_exist = false;
803 		}
804 	}
805 
806 	if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {
807 		coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
808 	} else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
809 		coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
810 		coex_stat->bt_multi_link_remain = false;
811 	} else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
812 		coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
813 	} else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
814 		   (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {
815 		if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)
816 			coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;
817 		else
818 			coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;
819 	} else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {
820 		coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;
821 	} else {
822 		coex_dm->bt_status = COEX_BTSTATUS_MAX;
823 	}
824 
825 	coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
826 
827 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(), %s!!!\n", __func__,
828 		rtw_coex_get_bt_status_string(coex_dm->bt_status));
829 }
830 
831 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
832 {
833 	const struct rtw_chip_info *chip = rtwdev->chip;
834 	struct rtw_efuse *efuse = &rtwdev->efuse;
835 	struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
836 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
837 	u8 link = 0;
838 	u8 center_chan = 0;
839 	u8 bw;
840 	int i;
841 
842 	bw = rtwdev->hal.current_band_width;
843 
844 	if (type != COEX_MEDIA_DISCONNECT)
845 		center_chan = rtwdev->hal.current_channel;
846 
847 	if (center_chan == 0 ||
848 	    (efuse->share_ant && center_chan <= 14 &&
849 	     coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)) {
850 		link = 0;
851 		center_chan = 0;
852 		bw = 0;
853 	} else if (center_chan <= 14) {
854 		link = 0x1;
855 
856 		if (bw == RTW_CHANNEL_WIDTH_40)
857 			bw = chip->bt_afh_span_bw40;
858 		else
859 			bw = chip->bt_afh_span_bw20;
860 	} else if (chip->afh_5g_num > 1) {
861 		for (i = 0; i < chip->afh_5g_num; i++) {
862 			if (center_chan == chip->afh_5g[i].wl_5g_ch) {
863 				link = 0x3;
864 				center_chan = chip->afh_5g[i].bt_skip_ch;
865 				bw = chip->afh_5g[i].bt_skip_span;
866 				break;
867 			}
868 		}
869 	}
870 
871 	coex_dm->wl_ch_info[0] = link;
872 	coex_dm->wl_ch_info[1] = center_chan;
873 	coex_dm->wl_ch_info[2] = bw;
874 
875 	rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
876 	rtw_dbg(rtwdev, RTW_DBG_COEX,
877 		"[BTCoex], %s: para[0:2] = 0x%x 0x%x 0x%x\n", __func__, link,
878 		center_chan, bw);
879 }
880 
881 static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
882 {
883 	struct rtw_coex *coex = &rtwdev->coex;
884 	struct rtw_coex_dm *coex_dm = &coex->dm;
885 
886 	if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)
887 		return;
888 
889 	coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;
890 
891 	rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);
892 }
893 
894 static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
895 {
896 	struct rtw_coex *coex = &rtwdev->coex;
897 	struct rtw_coex_dm *coex_dm = &coex->dm;
898 
899 	if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)
900 		return;
901 
902 	coex_dm->cur_bt_lna_lvl = bt_lna_lvl;
903 
904 	/* notify BT rx gain table changed */
905 	if (bt_lna_lvl < 7) {
906 		rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);
907 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);
908 	} else {
909 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
910 	}
911 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): bt_rx_LNA_level = %d\n",
912 		__func__, bt_lna_lvl);
913 }
914 
915 static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
916 				 struct coex_rf_para para)
917 {
918 	struct rtw_coex *coex = &rtwdev->coex;
919 	struct rtw_coex_stat *coex_stat = &coex->stat;
920 	u8 offset = 0;
921 
922 	if (coex->freerun && coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)
923 		offset = 3;
924 
925 	rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
926 	rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);
927 	rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);
928 	rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
929 }
930 
931 u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
932 {
933 	u32 val;
934 
935 	if (!ltecoex_read_reg(rtwdev, addr, &val)) {
936 		rtw_err(rtwdev, "failed to read indirect register\n");
937 		return 0;
938 	}
939 
940 	return val;
941 }
942 EXPORT_SYMBOL(rtw_coex_read_indirect_reg);
943 
944 void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
945 				 u32 mask, u32 val)
946 {
947 	u32 shift = __ffs(mask);
948 	u32 tmp;
949 
950 	tmp = rtw_coex_read_indirect_reg(rtwdev, addr);
951 	tmp = (tmp & (~mask)) | ((val << shift) & mask);
952 
953 	if (!ltecoex_reg_write(rtwdev, addr, tmp))
954 		rtw_err(rtwdev, "failed to write indirect register\n");
955 }
956 EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
957 
958 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
959 {
960 	const struct rtw_chip_info *chip = rtwdev->chip;
961 	const struct rtw_hw_reg *btg_reg = chip->btg_reg;
962 
963 	if (wifi_control) {
964 		rtw_write8_set(rtwdev, REG_SYS_SDIO_CTRL + 3,
965 			       BIT_LTE_MUX_CTRL_PATH >> 24);
966 		if (btg_reg)
967 			rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
968 	} else {
969 		rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL + 3,
970 			       BIT_LTE_MUX_CTRL_PATH >> 24);
971 		if (btg_reg)
972 			rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
973 	}
974 }
975 
976 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
977 {
978 	if (!rtwdev->chip->ltecoex_addr)
979 		return;
980 
981 	rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state);
982 	rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state);
983 }
984 
985 static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
986 {
987 	if (!rtwdev->chip->ltecoex_addr)
988 		return;
989 
990 	rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state);
991 	rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state);
992 }
993 
994 static void rtw_coex_mimo_ps(struct rtw_dev *rtwdev, bool force, bool state)
995 {
996 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
997 
998 	if (!force && state == coex_stat->wl_mimo_ps)
999 		return;
1000 
1001 	coex_stat->wl_mimo_ps = state;
1002 
1003 	rtw_set_txrx_1ss(rtwdev, state);
1004 
1005 	rtw_coex_update_wl_ch_info(rtwdev, (u8)coex_stat->wl_connected);
1006 
1007 	rtw_dbg(rtwdev, RTW_DBG_COEX,
1008 		"[BTCoex], %s(): state = %d\n", __func__, state);
1009 }
1010 
1011 static void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force,
1012 				     u8 table_case)
1013 {
1014 	const struct rtw_chip_info *chip = rtwdev->chip;
1015 	struct rtw_efuse *efuse = &rtwdev->efuse;
1016 	u8 h2c_para[6] = {0};
1017 	u32 table_wl = 0x5a5a5a5a;
1018 
1019 	h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_A;
1020 	/* no definition */
1021 	h2c_para[1] = 0x1;
1022 
1023 	if (efuse->share_ant) {
1024 		if (table_case < chip->table_sant_num)
1025 			table_wl = chip->table_sant[table_case].wl;
1026 	} else {
1027 		if (table_case < chip->table_nsant_num)
1028 			table_wl = chip->table_nsant[table_case].wl;
1029 	}
1030 
1031 	/* tell WL FW WL slot toggle table-A*/
1032 	h2c_para[2] = (u8)u32_get_bits(table_wl, GENMASK(7, 0));
1033 	h2c_para[3] = (u8)u32_get_bits(table_wl, GENMASK(15, 8));
1034 	h2c_para[4] = (u8)u32_get_bits(table_wl, GENMASK(23, 16));
1035 	h2c_para[5] = (u8)u32_get_bits(table_wl, GENMASK(31, 24));
1036 
1037 	rtw_fw_bt_wifi_control(rtwdev, h2c_para[0], &h2c_para[1]);
1038 
1039 	rtw_dbg(rtwdev, RTW_DBG_COEX,
1040 		"[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
1041 		__func__, h2c_para[0], h2c_para[1], h2c_para[2],
1042 		h2c_para[3], h2c_para[4], h2c_para[5]);
1043 }
1044 
1045 #define COEX_WL_SLOT_TOGLLE 0x5a5a5aaa
1046 static void rtw_btc_wltoggle_table_b(struct rtw_dev *rtwdev, bool force,
1047 				     u8 interval, u32 table)
1048 {
1049 	struct rtw_coex *coex = &rtwdev->coex;
1050 	struct rtw_coex_stat *coex_stat = &coex->stat;
1051 	u8 cur_h2c_para[6] = {0};
1052 	u8 i;
1053 
1054 	cur_h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_B;
1055 	cur_h2c_para[1] = interval;
1056 	cur_h2c_para[2] = (u8)u32_get_bits(table, GENMASK(7, 0));
1057 	cur_h2c_para[3] = (u8)u32_get_bits(table, GENMASK(15, 8));
1058 	cur_h2c_para[4] = (u8)u32_get_bits(table, GENMASK(23, 16));
1059 	cur_h2c_para[5] = (u8)u32_get_bits(table, GENMASK(31, 24));
1060 
1061 	coex_stat->wl_toggle_interval = interval;
1062 
1063 	for (i = 0; i <= 5; i++)
1064 		coex_stat->wl_toggle_para[i] = cur_h2c_para[i];
1065 
1066 	rtw_fw_bt_wifi_control(rtwdev, cur_h2c_para[0], &cur_h2c_para[1]);
1067 
1068 	rtw_dbg(rtwdev, RTW_DBG_COEX,
1069 		"[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
1070 		__func__, cur_h2c_para[0], cur_h2c_para[1], cur_h2c_para[2],
1071 		cur_h2c_para[3], cur_h2c_para[4], cur_h2c_para[5]);
1072 }
1073 
1074 static void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0,
1075 			       u32 table1)
1076 {
1077 #define DEF_BRK_TABLE_VAL 0xf0ffffff
1078 	struct rtw_coex *coex = &rtwdev->coex;
1079 	struct rtw_coex_dm *coex_dm = &coex->dm;
1080 
1081 	/* If last tdma is wl slot toggle, force write table*/
1082 	if (!force && coex_dm->reason != COEX_RSN_LPS) {
1083 		if (table0 == rtw_read32(rtwdev, REG_BT_COEX_TABLE0) &&
1084 		    table1 == rtw_read32(rtwdev, REG_BT_COEX_TABLE1))
1085 			return;
1086 	}
1087 	rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
1088 	rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
1089 	rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
1090 
1091 	rtw_dbg(rtwdev, RTW_DBG_COEX,
1092 		"[BTCoex], %s(): 0x6c0 = %x, 0x6c4 = %x\n", __func__, table0,
1093 		table1);
1094 }
1095 
1096 static void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type)
1097 {
1098 	const struct rtw_chip_info *chip = rtwdev->chip;
1099 	struct rtw_coex *coex = &rtwdev->coex;
1100 	struct rtw_coex_dm *coex_dm = &coex->dm;
1101 	struct rtw_efuse *efuse = &rtwdev->efuse;
1102 	struct rtw_coex_stat *coex_stat = &coex->stat;
1103 
1104 	coex_dm->cur_table = type;
1105 
1106 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Coex_Table - %d\n", type);
1107 
1108 	if (efuse->share_ant) {
1109 		if (type < chip->table_sant_num)
1110 			rtw_coex_set_table(rtwdev, force,
1111 					   chip->table_sant[type].bt,
1112 					   chip->table_sant[type].wl);
1113 	} else {
1114 		type = type - 100;
1115 		if (type < chip->table_nsant_num)
1116 			rtw_coex_set_table(rtwdev, force,
1117 					   chip->table_nsant[type].bt,
1118 					   chip->table_nsant[type].wl);
1119 	}
1120 	if (coex_stat->wl_slot_toggle_change)
1121 		rtw_btc_wltoggle_table_a(rtwdev, true, type);
1122 }
1123 
1124 static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
1125 {
1126 	struct rtw_coex *coex = &rtwdev->coex;
1127 
1128 	if (coex->manual_control || coex->stop_dm)
1129 		return;
1130 
1131 	rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
1132 }
1133 
1134 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
1135 				      u8 lps_val, u8 rpwm_val)
1136 {
1137 	struct rtw_coex *coex = &rtwdev->coex;
1138 	struct rtw_coex_stat *coex_stat = &coex->stat;
1139 	u8 lps_mode = 0x0;
1140 
1141 	lps_mode = rtwdev->lps_conf.mode;
1142 
1143 	switch (ps_type) {
1144 	case COEX_PS_WIFI_NATIVE:
1145 		/* recover to original 32k low power setting */
1146 		coex_stat->wl_force_lps_ctrl = false;
1147 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1148 			"[BTCoex], %s(): COEX_PS_WIFI_NATIVE\n", __func__);
1149 		rtw_leave_lps(rtwdev);
1150 		break;
1151 	case COEX_PS_LPS_OFF:
1152 		coex_stat->wl_force_lps_ctrl = true;
1153 		if (lps_mode)
1154 			rtw_fw_coex_tdma_type(rtwdev, 0, 0, 0, 0, 0);
1155 
1156 		rtw_leave_lps(rtwdev);
1157 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1158 			"[BTCoex], %s(): COEX_PS_LPS_OFF\n", __func__);
1159 		break;
1160 	default:
1161 		break;
1162 	}
1163 }
1164 
1165 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
1166 			      u8 byte3, u8 byte4, u8 byte5)
1167 {
1168 	const struct rtw_chip_info *chip = rtwdev->chip;
1169 	struct rtw_coex *coex = &rtwdev->coex;
1170 	struct rtw_coex_dm *coex_dm = &coex->dm;
1171 	struct rtw_coex_stat *coex_stat = &coex->stat;
1172 	u8 ps_type = COEX_PS_WIFI_NATIVE;
1173 	bool ap_enable = false;
1174 
1175 	if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
1176 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): AP mode\n",
1177 			__func__);
1178 
1179 		byte1 &= ~BIT(4);
1180 		byte1 |= BIT(5);
1181 
1182 		byte5 |= BIT(5);
1183 		byte5 &= ~BIT(6);
1184 
1185 		ps_type = COEX_PS_WIFI_NATIVE;
1186 		rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
1187 	} else if ((byte1 & BIT(4) && !(byte1 & BIT(5))) ||
1188 		   coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
1189 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1190 			"[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__,
1191 			byte1);
1192 
1193 		if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
1194 			ps_type = COEX_PS_LPS_OFF;
1195 		else
1196 			ps_type = COEX_PS_LPS_ON;
1197 		rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
1198 	} else {
1199 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1200 			"[BTCoex], %s(): native power save (byte1 = 0x%x)\n",
1201 			__func__, byte1);
1202 
1203 		ps_type = COEX_PS_WIFI_NATIVE;
1204 		rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
1205 	}
1206 
1207 	coex_dm->ps_tdma_para[0] = byte1;
1208 	coex_dm->ps_tdma_para[1] = byte2;
1209 	coex_dm->ps_tdma_para[2] = byte3;
1210 	coex_dm->ps_tdma_para[3] = byte4;
1211 	coex_dm->ps_tdma_para[4] = byte5;
1212 
1213 	rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
1214 
1215 	if (byte1 & BIT(2)) {
1216 		coex_stat->wl_slot_toggle = true;
1217 		coex_stat->wl_slot_toggle_change = false;
1218 	} else {
1219 		coex_stat->wl_slot_toggle_change = coex_stat->wl_slot_toggle;
1220 		coex_stat->wl_slot_toggle = false;
1221 	}
1222 }
1223 
1224 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
1225 {
1226 	const struct rtw_chip_info *chip = rtwdev->chip;
1227 	struct rtw_coex *coex = &rtwdev->coex;
1228 	struct rtw_coex_dm *coex_dm = &coex->dm;
1229 	struct rtw_coex_stat *coex_stat = &coex->stat;
1230 	struct rtw_efuse *efuse = &rtwdev->efuse;
1231 	u8 n, type;
1232 	bool turn_on;
1233 	bool wl_busy = false;
1234 
1235 	if (tcase & TDMA_4SLOT) /* 4-slot (50ms) mode */
1236 		rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_4SLOT);
1237 	else
1238 		rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_2SLOT);
1239 
1240 	type = (u8)(tcase & 0xff);
1241 
1242 	turn_on = (type == 0 || type == 100) ? false : true;
1243 
1244 	if (!force && turn_on == coex_dm->cur_ps_tdma_on &&
1245 	    type == coex_dm->cur_ps_tdma) {
1246 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1247 			"[BTCoex], Skip TDMA because no change TDMA(%s, %d)\n",
1248 			(coex_dm->cur_ps_tdma_on ? "on" : "off"),
1249 			coex_dm->cur_ps_tdma);
1250 
1251 		return;
1252 	}
1253 	wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
1254 
1255 	if ((coex_stat->bt_a2dp_exist &&
1256 	     (coex_stat->bt_inq_remain || coex_stat->bt_multi_link)) ||
1257 	    !wl_busy)
1258 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);
1259 	else
1260 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
1261 
1262 	/* update pre state */
1263 	coex_dm->cur_ps_tdma_on = turn_on;
1264 	coex_dm->cur_ps_tdma = type;
1265 
1266 	if (efuse->share_ant) {
1267 		if (type < chip->tdma_sant_num)
1268 			rtw_coex_set_tdma(rtwdev,
1269 					  chip->tdma_sant[type].para[0],
1270 					  chip->tdma_sant[type].para[1],
1271 					  chip->tdma_sant[type].para[2],
1272 					  chip->tdma_sant[type].para[3],
1273 					  chip->tdma_sant[type].para[4]);
1274 	} else {
1275 		n = type - 100;
1276 		if (n < chip->tdma_nsant_num)
1277 			rtw_coex_set_tdma(rtwdev,
1278 					  chip->tdma_nsant[n].para[0],
1279 					  chip->tdma_nsant[n].para[1],
1280 					  chip->tdma_nsant[n].para[2],
1281 					  chip->tdma_nsant[n].para[3],
1282 					  chip->tdma_nsant[n].para[4]);
1283 	}
1284 
1285 
1286 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], coex tdma type(%s, %d)\n",
1287 		turn_on ? "on" : "off", type);
1288 }
1289 
1290 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
1291 {
1292 	struct rtw_coex *coex = &rtwdev->coex;
1293 	struct rtw_coex_stat *coex_stat = &coex->stat;
1294 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1295 	struct rtw_coex_dm *coex_dm = &coex->dm;
1296 	u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
1297 	u8 pos_type = COEX_SWITCH_TO_MAX;
1298 
1299 	if (!force && coex_dm->cur_ant_pos_type == phase)
1300 		return;
1301 
1302 	coex_dm->cur_ant_pos_type = phase;
1303 
1304 	/* avoid switch coex_ctrl_owner during BT IQK */
1305 	rtw_coex_check_rfk(rtwdev);
1306 
1307 	rtw_dbg(rtwdev, RTW_DBG_COEX,
1308 		"[BTCoex],  coex_stat->bt_disabled = 0x%x\n",
1309 		coex_stat->bt_disabled);
1310 
1311 	switch (phase) {
1312 	case COEX_SET_ANT_POWERON:
1313 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1314 			"[BTCoex], %s() - PHASE_COEX_POWERON\n", __func__);
1315 		/* set path control owner to BT at power-on */
1316 		if (coex_stat->bt_disabled)
1317 			rtw_coex_coex_ctrl_owner(rtwdev, true);
1318 		else
1319 			rtw_coex_coex_ctrl_owner(rtwdev, false);
1320 
1321 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1322 		pos_type = COEX_SWITCH_TO_BT;
1323 		break;
1324 	case COEX_SET_ANT_INIT:
1325 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1326 			"[BTCoex], %s() - PHASE_COEX_INIT\n", __func__);
1327 		if (coex_stat->bt_disabled) {
1328 			/* set GNT_BT to SW low */
1329 			rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1330 
1331 			/* set GNT_WL to SW high */
1332 			rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1333 		} else {
1334 			/* set GNT_BT to SW high */
1335 			rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1336 
1337 			/* set GNT_WL to SW low */
1338 			rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);
1339 		}
1340 
1341 		/* set path control owner to wl at initial step */
1342 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1343 
1344 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1345 		pos_type = COEX_SWITCH_TO_BT;
1346 		break;
1347 	case COEX_SET_ANT_WONLY:
1348 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1349 			"[BTCoex], %s() - PHASE_WLANONLY_INIT\n", __func__);
1350 		/* set GNT_BT to SW Low */
1351 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1352 
1353 		/* set GNT_WL to SW high */
1354 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1355 
1356 		/* set path control owner to wl at initial step */
1357 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1358 
1359 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1360 		pos_type = COEX_SWITCH_TO_WLG;
1361 		break;
1362 	case COEX_SET_ANT_WOFF:
1363 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1364 			"[BTCoex], %s() - PHASE_WLAN_OFF\n", __func__);
1365 		/* set path control owner to BT */
1366 		rtw_coex_coex_ctrl_owner(rtwdev, false);
1367 
1368 		ctrl_type = COEX_SWITCH_CTRL_BY_BT;
1369 		pos_type = COEX_SWITCH_TO_NOCARE;
1370 		break;
1371 	case COEX_SET_ANT_2G:
1372 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1373 			"[BTCoex], %s() - PHASE_2G_RUNTIME\n", __func__);
1374 		/* set GNT_BT to PTA */
1375 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1376 
1377 		/* set GNT_WL to PTA */
1378 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1379 
1380 		/* set path control owner to wl at runtime step */
1381 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1382 
1383 		ctrl_type = COEX_SWITCH_CTRL_BY_PTA;
1384 		pos_type = COEX_SWITCH_TO_NOCARE;
1385 		break;
1386 	case COEX_SET_ANT_5G:
1387 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1388 			"[BTCoex], %s() - PHASE_5G_RUNTIME\n", __func__);
1389 
1390 		/* set GNT_BT to HW PTA */
1391 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1392 
1393 		/* set GNT_WL to SW high */
1394 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1395 
1396 		/* set path control owner to wl at runtime step */
1397 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1398 
1399 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1400 		pos_type = COEX_SWITCH_TO_WLA;
1401 		break;
1402 	case COEX_SET_ANT_2G_FREERUN:
1403 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1404 			"[BTCoex], %s() - PHASE_2G_FREERUN\n", __func__);
1405 
1406 		/* set GNT_BT to HW PTA */
1407 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1408 
1409 		/* Set GNT_WL to SW high */
1410 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1411 
1412 		/* set path control owner to wl at runtime step */
1413 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1414 
1415 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1416 		pos_type = COEX_SWITCH_TO_WLG_BT;
1417 		break;
1418 	case COEX_SET_ANT_2G_WLBT:
1419 		rtw_dbg(rtwdev, RTW_DBG_COEX,
1420 			"[BTCoex], %s() - PHASE_2G_WLBT\n", __func__);
1421 		/* set GNT_BT to HW PTA */
1422 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1423 
1424 		/* Set GNT_WL to HW PTA */
1425 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1426 
1427 		/* set path control owner to wl at runtime step */
1428 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1429 
1430 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1431 		pos_type = COEX_SWITCH_TO_WLG_BT;
1432 		break;
1433 	default:
1434 		WARN(1, "unknown phase when setting antenna path\n");
1435 		return;
1436 	}
1437 
1438 	if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX &&
1439 	    coex_rfe->ant_switch_exist)
1440 		rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
1441 }
1442 
1443 #define case_ALGO(src) \
1444 	case COEX_ALGO_##src: return #src
1445 
1446 static const char *rtw_coex_get_algo_string(u8 algo)
1447 {
1448 	switch (algo) {
1449 	case_ALGO(NOPROFILE);
1450 	case_ALGO(HFP);
1451 	case_ALGO(HID);
1452 	case_ALGO(A2DP);
1453 	case_ALGO(PAN);
1454 	case_ALGO(A2DP_HID);
1455 	case_ALGO(A2DP_PAN);
1456 	case_ALGO(PAN_HID);
1457 	case_ALGO(A2DP_PAN_HID);
1458 	default:
1459 		return "Unknown";
1460 	}
1461 }
1462 
1463 #define case_BT_PROFILE(src) \
1464 	case BPM_##src: return #src
1465 
1466 static const char *rtw_coex_get_bt_profile_string(u8 bt_profile)
1467 {
1468 	switch (bt_profile) {
1469 	case_BT_PROFILE(NOPROFILE);
1470 	case_BT_PROFILE(HFP);
1471 	case_BT_PROFILE(HID);
1472 	case_BT_PROFILE(A2DP);
1473 	case_BT_PROFILE(PAN);
1474 	case_BT_PROFILE(HID_HFP);
1475 	case_BT_PROFILE(A2DP_HFP);
1476 	case_BT_PROFILE(A2DP_HID);
1477 	case_BT_PROFILE(A2DP_HID_HFP);
1478 	case_BT_PROFILE(PAN_HFP);
1479 	case_BT_PROFILE(PAN_HID);
1480 	case_BT_PROFILE(PAN_HID_HFP);
1481 	case_BT_PROFILE(PAN_A2DP);
1482 	case_BT_PROFILE(PAN_A2DP_HFP);
1483 	case_BT_PROFILE(PAN_A2DP_HID);
1484 	case_BT_PROFILE(PAN_A2DP_HID_HFP);
1485 	default:
1486 		return "Unknown";
1487 	}
1488 }
1489 
1490 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
1491 {
1492 	struct rtw_coex *coex = &rtwdev->coex;
1493 	struct rtw_coex_stat *coex_stat = &coex->stat;
1494 	u8 algorithm = COEX_ALGO_NOPROFILE;
1495 	u8 profile_map = 0;
1496 
1497 	if (coex_stat->bt_hfp_exist)
1498 		profile_map |= BPM_HFP;
1499 	if (coex_stat->bt_hid_exist)
1500 		profile_map |= BPM_HID;
1501 	if (coex_stat->bt_a2dp_exist)
1502 		profile_map |= BPM_A2DP;
1503 	if (coex_stat->bt_pan_exist)
1504 		profile_map |= BPM_PAN;
1505 
1506 	switch (profile_map) {
1507 	case BPM_HFP:
1508 		algorithm = COEX_ALGO_HFP;
1509 		break;
1510 	case           BPM_HID:
1511 	case BPM_HFP | BPM_HID:
1512 		algorithm = COEX_ALGO_HID;
1513 		break;
1514 	case BPM_HFP           | BPM_A2DP:
1515 	case           BPM_HID | BPM_A2DP:
1516 	case BPM_HFP | BPM_HID | BPM_A2DP:
1517 		algorithm = COEX_ALGO_A2DP_HID;
1518 		break;
1519 	case BPM_HFP                      | BPM_PAN:
1520 	case           BPM_HID            | BPM_PAN:
1521 	case BPM_HFP | BPM_HID            | BPM_PAN:
1522 		algorithm = COEX_ALGO_PAN_HID;
1523 		break;
1524 	case BPM_HFP           | BPM_A2DP | BPM_PAN:
1525 	case           BPM_HID | BPM_A2DP | BPM_PAN:
1526 	case BPM_HFP | BPM_HID | BPM_A2DP | BPM_PAN:
1527 		algorithm = COEX_ALGO_A2DP_PAN_HID;
1528 		break;
1529 	case                                BPM_PAN:
1530 		algorithm = COEX_ALGO_PAN;
1531 		break;
1532 	case                     BPM_A2DP | BPM_PAN:
1533 		algorithm = COEX_ALGO_A2DP_PAN;
1534 		break;
1535 	case                     BPM_A2DP:
1536 		if (coex_stat->bt_multi_link) {
1537 			if (coex_stat->bt_hid_pair_num > 0)
1538 				algorithm = COEX_ALGO_A2DP_HID;
1539 			else
1540 				algorithm = COEX_ALGO_A2DP_PAN;
1541 		} else {
1542 			algorithm = COEX_ALGO_A2DP;
1543 		}
1544 		break;
1545 	default:
1546 		algorithm = COEX_ALGO_NOPROFILE;
1547 		break;
1548 	}
1549 
1550 	rtw_dbg(rtwdev, RTW_DBG_COEX,
1551 		"[BTCoex], BT Profile = %s => Algorithm = %s\n",
1552 		rtw_coex_get_bt_profile_string(profile_map),
1553 		rtw_coex_get_algo_string(algorithm));
1554 	return algorithm;
1555 }
1556 
1557 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
1558 {
1559 	const struct rtw_chip_info *chip = rtwdev->chip;
1560 	struct rtw_efuse *efuse = &rtwdev->efuse;
1561 	u8 table_case, tdma_case;
1562 
1563 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1564 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1565 
1566 	if (efuse->share_ant) {
1567 		/* Shared-Ant */
1568 		table_case = 2;
1569 		tdma_case = 0;
1570 	} else {
1571 		/* Non-Shared-Ant */
1572 		table_case = 100;
1573 		tdma_case = 100;
1574 	}
1575 
1576 	rtw_coex_table(rtwdev, false, table_case);
1577 	rtw_coex_tdma(rtwdev, false, tdma_case);
1578 }
1579 
1580 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
1581 {
1582 	const struct rtw_chip_info *chip = rtwdev->chip;
1583 	struct rtw_coex *coex = &rtwdev->coex;
1584 	struct rtw_coex_stat *coex_stat = &coex->stat;
1585 	struct rtw_coex_dm *coex_dm = &coex->dm;
1586 	struct rtw_efuse *efuse = &rtwdev->efuse;
1587 	u8 level = 0;
1588 	bool bt_afh_loss = true;
1589 
1590 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1591 
1592 	if (efuse->share_ant)
1593 		return;
1594 
1595 	coex->freerun = true;
1596 
1597 	if (bt_afh_loss)
1598 		rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
1599 
1600 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1601 
1602 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1603 
1604 	if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))
1605 		level = 2;
1606 	else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1607 		level = 3;
1608 	else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))
1609 		level = 4;
1610 	else
1611 		level = 5;
1612 
1613 	if (level > chip->wl_rf_para_num - 1)
1614 		level = chip->wl_rf_para_num - 1;
1615 
1616 	if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1617 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);
1618 	else
1619 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
1620 
1621 	rtw_coex_table(rtwdev, false, 100);
1622 	rtw_coex_tdma(rtwdev, false, 100);
1623 }
1624 
1625 static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)
1626 {
1627 	const struct rtw_chip_info *chip = rtwdev->chip;
1628 	struct rtw_efuse *efuse = &rtwdev->efuse;
1629 	u8 table_case, tdma_case;
1630 
1631 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1632 
1633 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1634 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1635 
1636 	if (efuse->share_ant) {
1637 		/* Shared-Ant */
1638 		table_case = 9;
1639 		tdma_case = 16;
1640 	} else {
1641 		/* Non-Shared-Ant */
1642 		table_case = 100;
1643 		tdma_case = 100;
1644 	}
1645 
1646 	rtw_coex_table(rtwdev, false, table_case);
1647 	rtw_coex_tdma(rtwdev, false, tdma_case);
1648 }
1649 
1650 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
1651 {
1652 	const struct rtw_chip_info *chip = rtwdev->chip;
1653 	struct rtw_efuse *efuse = &rtwdev->efuse;
1654 	u8 table_case, tdma_case;
1655 
1656 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1657 
1658 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1659 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1660 
1661 	if (efuse->share_ant) {
1662 		/* Shared-Ant */
1663 		table_case = 2;
1664 		tdma_case = 0;
1665 	} else {
1666 		/* Non-Shared-Ant */
1667 		table_case = 100;
1668 		tdma_case = 100;
1669 	}
1670 
1671 	rtw_coex_table(rtwdev, false, table_case);
1672 	rtw_coex_tdma(rtwdev, false, tdma_case);
1673 }
1674 
1675 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
1676 {
1677 	const struct rtw_chip_info *chip = rtwdev->chip;
1678 	struct rtw_coex *coex = &rtwdev->coex;
1679 	struct rtw_coex_stat *coex_stat = &coex->stat;
1680 	struct rtw_efuse *efuse = &rtwdev->efuse;
1681 	u8 table_case, tdma_case;
1682 	u32 slot_type = 0;
1683 
1684 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1685 
1686 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1687 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1688 
1689 	if (efuse->share_ant) { /* Shared-Ant */
1690 		if (coex_stat->wl_gl_busy) {
1691 			table_case = 26;
1692 			if (coex_stat->bt_hid_exist &&
1693 			    coex_stat->bt_profile_num == 1) {
1694 				slot_type = TDMA_4SLOT;
1695 				tdma_case = 20;
1696 			} else {
1697 				tdma_case = 20;
1698 			}
1699 		} else {
1700 			table_case = 1;
1701 			tdma_case = 0;
1702 		}
1703 	} else { /* Non-Shared-Ant */
1704 		if (coex_stat->wl_gl_busy)
1705 			table_case = 115;
1706 		else
1707 			table_case = 100;
1708 		tdma_case = 100;
1709 	}
1710 
1711 	rtw_coex_table(rtwdev, false, table_case);
1712 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1713 }
1714 
1715 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
1716 {
1717 	const struct rtw_chip_info *chip = rtwdev->chip;
1718 	struct rtw_coex *coex = &rtwdev->coex;
1719 	struct rtw_coex_stat *coex_stat = &coex->stat;
1720 	struct rtw_coex_dm *coex_dm = &coex->dm;
1721 	struct rtw_efuse *efuse = &rtwdev->efuse;
1722 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1723 	u8 table_case = 0xff, tdma_case = 0xff;
1724 
1725 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1726 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1727 
1728 	if (coex_rfe->ant_switch_with_bt &&
1729 	    coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1730 		if (efuse->share_ant &&
1731 		    COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
1732 		    coex_stat->wl_gl_busy) {
1733 			table_case = 0;
1734 			tdma_case = 0;
1735 		} else if (!efuse->share_ant) {
1736 			table_case = 100;
1737 			tdma_case = 100;
1738 		}
1739 	}
1740 
1741 	if (table_case != 0xff && tdma_case != 0xff) {
1742 		rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1743 		goto exit;
1744 	}
1745 
1746 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1747 
1748 	if (efuse->share_ant) {
1749 		/* Shared-Ant */
1750 		if (!coex_stat->wl_gl_busy) {
1751 			table_case = 10;
1752 			tdma_case = 3;
1753 		} else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1754 			table_case = 11;
1755 
1756 			if (coex_stat->lo_pri_rx + coex_stat->lo_pri_tx > 250)
1757 				tdma_case = 17;
1758 			else
1759 				tdma_case = 7;
1760 		} else {
1761 			table_case = 12;
1762 			tdma_case = 7;
1763 		}
1764 	} else {
1765 		/* Non-Shared-Ant */
1766 		if (!coex_stat->wl_gl_busy) {
1767 			table_case = 112;
1768 			tdma_case = 104;
1769 		} else if ((coex_stat->bt_ble_scan_type & 0x2) &&
1770 			   coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1771 			table_case = 114;
1772 			tdma_case = 103;
1773 		} else {
1774 			table_case = 112;
1775 			tdma_case = 103;
1776 		}
1777 	}
1778 
1779 exit:
1780 	rtw_coex_table(rtwdev, false, table_case);
1781 	rtw_coex_tdma(rtwdev, false, tdma_case);
1782 }
1783 
1784 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
1785 {
1786 	const struct rtw_chip_info *chip = rtwdev->chip;
1787 	struct rtw_coex *coex = &rtwdev->coex;
1788 	struct rtw_coex_stat *coex_stat = &coex->stat;
1789 	struct rtw_efuse *efuse = &rtwdev->efuse;
1790 	bool wl_hi_pri = false;
1791 	u8 table_case, tdma_case;
1792 	u32 slot_type = 0;
1793 
1794 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1795 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1796 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1797 
1798 	if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
1799 	    coex_stat->wl_hi_pri_task2)
1800 		wl_hi_pri = true;
1801 
1802 	if (efuse->share_ant) {
1803 		/* Shared-Ant */
1804 		if (wl_hi_pri) {
1805 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1806 				"[BTCoex], bt inq/page +  wifi hi-pri task\n");
1807 			table_case = 15;
1808 
1809 			if (coex_stat->bt_profile_num > 0)
1810 				tdma_case = 10;
1811 			else if (coex_stat->wl_hi_pri_task1)
1812 				tdma_case = 6;
1813 			else if (!coex_stat->bt_page)
1814 				tdma_case = 8;
1815 			else
1816 				tdma_case = 9;
1817 		} else if (coex_stat->wl_gl_busy) {
1818 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1819 				"[BTCoex], bt inq/page + wifi busy\n");
1820 			if (coex_stat->bt_profile_num == 0) {
1821 				table_case = 12;
1822 				tdma_case = 18;
1823 			} else if (coex_stat->bt_profile_num == 1 &&
1824 				   !coex_stat->bt_a2dp_exist) {
1825 				slot_type = TDMA_4SLOT;
1826 				table_case = 12;
1827 				tdma_case = 20;
1828 			} else {
1829 				slot_type = TDMA_4SLOT;
1830 				table_case = 12;
1831 				tdma_case = 26;
1832 			}
1833 		} else if (coex_stat->wl_connected) {
1834 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1835 				"[BTCoex], bt inq/page + wifi connected\n");
1836 			table_case = 9;
1837 			tdma_case = 27;
1838 		} else {
1839 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1840 				"[BTCoex], bt inq/page + wifi not-connected\n");
1841 			table_case = 1;
1842 			tdma_case = 0;
1843 		}
1844 	} else {
1845 		/* Non_Shared-Ant */
1846 		if (wl_hi_pri) {
1847 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1848 				"[BTCoex], bt inq/page +  wifi hi-pri task\n");
1849 			table_case = 114;
1850 
1851 			if (coex_stat->bt_profile_num > 0)
1852 				tdma_case = 110;
1853 			else if (coex_stat->wl_hi_pri_task1)
1854 				tdma_case = 106;
1855 			else if (!coex_stat->bt_page)
1856 				tdma_case = 108;
1857 			else
1858 				tdma_case = 109;
1859 		}  else if (coex_stat->wl_gl_busy) {
1860 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1861 				"[BTCoex], bt inq/page + wifi busy\n");
1862 			table_case = 114;
1863 			tdma_case = 121;
1864 		} else if (coex_stat->wl_connected) {
1865 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1866 				"[BTCoex], bt inq/page +  wifi connected\n");
1867 			table_case = 101;
1868 			tdma_case = 100;
1869 		} else {
1870 			rtw_dbg(rtwdev, RTW_DBG_COEX,
1871 				"[BTCoex], bt inq/page +  wifi not-connected\n");
1872 			table_case = 101;
1873 			tdma_case = 100;
1874 		}
1875 	}
1876 
1877 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wifi hi(%d), bt page(%d)\n",
1878 		wl_hi_pri, coex_stat->bt_page);
1879 
1880 	rtw_coex_table(rtwdev, false, table_case);
1881 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1882 }
1883 
1884 static void rtw_coex_action_bt_game_hid(struct rtw_dev *rtwdev)
1885 {
1886 	const struct rtw_chip_info *chip = rtwdev->chip;
1887 	struct rtw_coex *coex = &rtwdev->coex;
1888 	struct rtw_coex_stat *coex_stat = &coex->stat;
1889 	struct rtw_efuse *efuse = &rtwdev->efuse;
1890 	struct rtw_coex_dm *coex_dm = &coex->dm;
1891 	u8 table_case, tdma_case;
1892 
1893 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1894 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1895 
1896 	if (efuse->share_ant) {
1897 		coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;
1898 		if (coex_stat->bt_whck_test)
1899 			table_case = 2;
1900 		else if (coex_stat->wl_linkscan_proc || coex_stat->bt_hid_exist)
1901 			table_case = 33;
1902 		else if (coex_stat->bt_setup_link || coex_stat->bt_inq_page)
1903 			table_case = 0;
1904 		else if (coex_stat->bt_a2dp_exist)
1905 			table_case = 34;
1906 		else
1907 			table_case = 33;
1908 
1909 		tdma_case = 0;
1910 	} else {
1911 		if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1912 			tdma_case = 112;
1913 		else
1914 			tdma_case = 113;
1915 
1916 		table_case = 121;
1917 	}
1918 
1919 	if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
1920 		if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1921 			rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]);
1922 		else
1923 			rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]);
1924 	} else {
1925 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1926 	}
1927 
1928 	rtw_coex_table(rtwdev, false, table_case);
1929 	rtw_coex_tdma(rtwdev, false, tdma_case);
1930 }
1931 
1932 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
1933 {
1934 	const struct rtw_chip_info *chip = rtwdev->chip;
1935 	struct rtw_coex *coex = &rtwdev->coex;
1936 	struct rtw_coex_stat *coex_stat = &coex->stat;
1937 	struct rtw_efuse *efuse = &rtwdev->efuse;
1938 	u8 table_case, tdma_case;
1939 
1940 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1941 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1942 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1943 
1944 	if (efuse->share_ant) {
1945 		/* Shared-Ant */
1946 		table_case = 10;
1947 		tdma_case = 5;
1948 	} else {
1949 		/* Non-Shared-Ant */
1950 		if (coex_stat->bt_multi_link) {
1951 			table_case = 112;
1952 			tdma_case = 117;
1953 		} else {
1954 			table_case = 105;
1955 			tdma_case = 100;
1956 		}
1957 	}
1958 
1959 	rtw_coex_table(rtwdev, false, table_case);
1960 	rtw_coex_tdma(rtwdev, false, tdma_case);
1961 }
1962 
1963 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
1964 {
1965 	const struct rtw_chip_info *chip = rtwdev->chip;
1966 	struct rtw_coex *coex = &rtwdev->coex;
1967 	struct rtw_coex_stat *coex_stat = &coex->stat;
1968 	struct rtw_efuse *efuse = &rtwdev->efuse;
1969 	bool is_bt_ctr_hi = false, is_toggle_table = false;
1970 	u8 table_case, tdma_case;
1971 	u32 slot_type = 0;
1972 
1973 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1974 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1975 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1976 
1977 	if (coex_stat->bt_ctr_ok &&
1978 	    coex_stat->lo_pri_rx + coex_stat->lo_pri_tx > 360)
1979 		is_bt_ctr_hi = true;
1980 
1981 	if (efuse->share_ant) {
1982 		/* Shared-Ant */
1983 		if (coex_stat->bt_ble_exist) {
1984 			/* RCU */
1985 			if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
1986 				table_case = 26;
1987 				tdma_case = 2;
1988 			} else {
1989 				table_case = 27;
1990 				tdma_case = 9;
1991 			}
1992 		} else {
1993 			/* Legacy HID  */
1994 			if (coex_stat->bt_a2dp_active) {
1995 				table_case = 9;
1996 				tdma_case = 18;
1997 			} else if (coex_stat->bt_profile_num == 1 &&
1998 				   (coex_stat->bt_multi_link &&
1999 				    (is_bt_ctr_hi || coex_stat->bt_slave ||
2000 				     coex_stat->bt_multi_link_remain))) {
2001 				if (coex_stat->wl_gl_busy &&
2002 				    (coex_stat->wl_rx_rate <= 3 ||
2003 				     coex_stat->wl_rts_rx_rate <= 3))
2004 					table_case = 13;
2005 				else
2006 					table_case = 12;
2007 
2008 				tdma_case = 26;
2009 			} else if (coex_stat->bt_418_hid_exist &&
2010 				   coex_stat->wl_gl_busy) {
2011 				is_toggle_table = true;
2012 				slot_type = TDMA_4SLOT;
2013 				table_case = 32;
2014 				tdma_case = 27;
2015 			} else if (coex_stat->bt_ble_hid_exist &&
2016 				   coex_stat->wl_gl_busy) {
2017 				table_case = 36;
2018 				tdma_case = 0;
2019 			} else {
2020 				table_case = 9;
2021 				tdma_case = 9;
2022 			}
2023 		}
2024 	} else {
2025 		/* Non-Shared-Ant */
2026 		if (coex_stat->bt_ble_exist) {
2027 			/* BLE */
2028 			if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
2029 				table_case = 121;
2030 				tdma_case = 102;
2031 			} else {
2032 				table_case = 122;
2033 				tdma_case = 109;
2034 			}
2035 		} else if (coex_stat->bt_a2dp_active) {
2036 			table_case = 113;
2037 			tdma_case = 118;
2038 		} else {
2039 			table_case = 113;
2040 			tdma_case = 104;
2041 		}
2042 	}
2043 
2044 	rtw_coex_table(rtwdev, false, table_case);
2045 	if (is_toggle_table) {
2046 		rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
2047 		rtw_btc_wltoggle_table_b(rtwdev, false, 1, COEX_WL_SLOT_TOGLLE);
2048 	}
2049 
2050 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2051 }
2052 
2053 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
2054 {
2055 	const struct rtw_chip_info *chip = rtwdev->chip;
2056 	struct rtw_coex *coex = &rtwdev->coex;
2057 	struct rtw_coex_stat *coex_stat = &coex->stat;
2058 	struct rtw_coex_dm *coex_dm = &coex->dm;
2059 	struct rtw_efuse *efuse = &rtwdev->efuse;
2060 	u8 table_case, tdma_case;
2061 	u32 slot_type = 0;
2062 
2063 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2064 
2065 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2066 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2067 
2068 	slot_type = TDMA_4SLOT;
2069 
2070 	if (efuse->share_ant) {
2071 		/* Shared-Ant */
2072 		if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
2073 			table_case = 12;
2074 		else
2075 			table_case = 9;
2076 
2077 		if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy)
2078 			tdma_case = 14;
2079 		else
2080 			tdma_case = 13;
2081 	} else {
2082 		/* Non-Shared-Ant */
2083 		table_case = 112;
2084 
2085 		if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
2086 			tdma_case = 112;
2087 		else
2088 			tdma_case = 113;
2089 	}
2090 
2091 	rtw_coex_table(rtwdev, false, table_case);
2092 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2093 }
2094 
2095 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
2096 {
2097 	const struct rtw_chip_info *chip = rtwdev->chip;
2098 	struct rtw_coex *coex = &rtwdev->coex;
2099 	struct rtw_coex_stat *coex_stat = &coex->stat;
2100 	struct rtw_efuse *efuse = &rtwdev->efuse;
2101 	u8 table_case, tdma_case;
2102 	bool ap_enable = false;
2103 
2104 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2105 
2106 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2107 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2108 
2109 	if (efuse->share_ant) { /* Shared-Ant */
2110 		if (ap_enable) {
2111 			table_case = 2;
2112 			tdma_case = 0;
2113 		} else if (coex_stat->wl_gl_busy) {
2114 			table_case = 28;
2115 			tdma_case = 20;
2116 		} else {
2117 			table_case = 28;
2118 			tdma_case = 26;
2119 		}
2120 	} else { /* Non-Shared-Ant */
2121 		if (ap_enable) {
2122 			table_case = 100;
2123 			tdma_case = 100;
2124 		} else {
2125 			table_case = 119;
2126 			tdma_case = 120;
2127 		}
2128 	}
2129 
2130 	rtw_coex_table(rtwdev, false, table_case);
2131 	rtw_coex_tdma(rtwdev, false, tdma_case);
2132 }
2133 
2134 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
2135 {
2136 	const struct rtw_chip_info *chip = rtwdev->chip;
2137 	struct rtw_coex *coex = &rtwdev->coex;
2138 	struct rtw_coex_stat *coex_stat = &coex->stat;
2139 	struct rtw_efuse *efuse = &rtwdev->efuse;
2140 	u8 table_case, tdma_case;
2141 
2142 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2143 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2144 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2145 
2146 	if (efuse->share_ant) {
2147 		/* Shared-Ant */
2148 		if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
2149 			table_case = 14;
2150 		else
2151 			table_case = 10;
2152 
2153 		if (coex_stat->wl_gl_busy)
2154 			tdma_case = 17;
2155 		else
2156 			tdma_case = 20;
2157 	} else {
2158 		/* Non-Shared-Ant */
2159 		table_case = 112;
2160 
2161 		if (coex_stat->wl_gl_busy)
2162 			tdma_case = 117;
2163 		else
2164 			tdma_case = 119;
2165 	}
2166 
2167 	rtw_coex_table(rtwdev, false, table_case);
2168 	rtw_coex_tdma(rtwdev, false, tdma_case);
2169 }
2170 
2171 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
2172 {
2173 	const struct rtw_chip_info *chip = rtwdev->chip;
2174 	struct rtw_coex *coex = &rtwdev->coex;
2175 	struct rtw_coex_stat *coex_stat = &coex->stat;
2176 	struct rtw_coex_dm *coex_dm = &coex->dm;
2177 	struct rtw_efuse *efuse = &rtwdev->efuse;
2178 	u8 table_case, tdma_case, interval = 0;
2179 	u32 slot_type = 0;
2180 	bool is_toggle_table = false;
2181 
2182 	slot_type = TDMA_4SLOT;
2183 
2184 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2185 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2186 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2187 
2188 	if (efuse->share_ant) {
2189 		/* Shared-Ant */
2190 		if (coex_stat->bt_ble_exist) {
2191 			table_case = 26; /* for RCU */
2192 		} else if (coex_stat->bt_418_hid_exist) {
2193 			table_case = 9;
2194 			interval = 1;
2195 		} else {
2196 			table_case = 9;
2197 		}
2198 
2199 		if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) {
2200 			tdma_case = 14;
2201 		} else if (coex_stat->bt_418_hid_exist) {
2202 			is_toggle_table = true;
2203 			tdma_case = 23;
2204 		} else {
2205 			tdma_case = 13;
2206 		}
2207 	} else {
2208 		/* Non-Shared-Ant */
2209 		if (coex_stat->bt_ble_exist)
2210 			table_case = 121;
2211 		else
2212 			table_case = 113;
2213 
2214 		if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
2215 			tdma_case = 112;
2216 		else
2217 			tdma_case = 113;
2218 	}
2219 
2220 	rtw_coex_table(rtwdev, false, table_case);
2221 	if (is_toggle_table) {
2222 		rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
2223 		rtw_btc_wltoggle_table_b(rtwdev, false, interval, COEX_WL_SLOT_TOGLLE);
2224 	}
2225 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2226 }
2227 
2228 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
2229 {
2230 	const struct rtw_chip_info *chip = rtwdev->chip;
2231 	struct rtw_coex *coex = &rtwdev->coex;
2232 	struct rtw_coex_stat *coex_stat = &coex->stat;
2233 	struct rtw_efuse *efuse = &rtwdev->efuse;
2234 	u8 table_case, tdma_case;
2235 
2236 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2237 
2238 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2239 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2240 	if (efuse->share_ant) {
2241 		/* Shared-Ant */
2242 		if (coex_stat->wl_gl_busy &&
2243 		    coex_stat->wl_noisy_level == 0)
2244 			table_case = 14;
2245 		else
2246 			table_case = 10;
2247 
2248 		if (coex_stat->wl_gl_busy)
2249 			tdma_case = 15;
2250 		else
2251 			tdma_case = 20;
2252 	} else {
2253 		/* Non-Shared-Ant */
2254 		table_case = 112;
2255 
2256 		if (coex_stat->wl_gl_busy)
2257 			tdma_case = 115;
2258 		else
2259 			tdma_case = 120;
2260 	}
2261 
2262 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2263 	rtw_coex_table(rtwdev, false, table_case);
2264 	rtw_coex_tdma(rtwdev, false, tdma_case);
2265 }
2266 
2267 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
2268 {
2269 	const struct rtw_chip_info *chip = rtwdev->chip;
2270 	struct rtw_coex *coex = &rtwdev->coex;
2271 	struct rtw_coex_stat *coex_stat = &coex->stat;
2272 	struct rtw_efuse *efuse = &rtwdev->efuse;
2273 	u8 table_case, tdma_case;
2274 
2275 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2276 
2277 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2278 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2279 
2280 	if (efuse->share_ant) {
2281 		/* Shared-Ant */
2282 		table_case = 9;
2283 
2284 		if (coex_stat->wl_gl_busy)
2285 			tdma_case = 18;
2286 		else
2287 			tdma_case = 19;
2288 	} else {
2289 		/* Non-Shared-Ant */
2290 		table_case = 113;
2291 
2292 		if (coex_stat->wl_gl_busy)
2293 			tdma_case = 117;
2294 		else
2295 			tdma_case = 119;
2296 	}
2297 
2298 	rtw_coex_table(rtwdev, false, table_case);
2299 	rtw_coex_tdma(rtwdev, false, tdma_case);
2300 }
2301 
2302 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
2303 {
2304 	const struct rtw_chip_info *chip = rtwdev->chip;
2305 	struct rtw_coex *coex = &rtwdev->coex;
2306 	struct rtw_coex_stat *coex_stat = &coex->stat;
2307 	struct rtw_efuse *efuse = &rtwdev->efuse;
2308 	u8 table_case, tdma_case;
2309 
2310 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2311 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2312 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2313 
2314 	if (efuse->share_ant) {
2315 		/* Shared-Ant */
2316 		table_case = 10;
2317 
2318 		if (coex_stat->wl_gl_busy)
2319 			tdma_case = 15;
2320 		else
2321 			tdma_case = 20;
2322 	} else {
2323 		/* Non-Shared-Ant */
2324 		table_case = 113;
2325 
2326 		if (coex_stat->wl_gl_busy)
2327 			tdma_case = 115;
2328 		else
2329 			tdma_case = 120;
2330 	}
2331 
2332 	rtw_coex_table(rtwdev, false, table_case);
2333 	rtw_coex_tdma(rtwdev, false, tdma_case);
2334 }
2335 
2336 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
2337 {
2338 	const struct rtw_chip_info *chip = rtwdev->chip;
2339 	struct rtw_coex *coex = &rtwdev->coex;
2340 	struct rtw_efuse *efuse = &rtwdev->efuse;
2341 	struct rtw_coex_stat *coex_stat = &coex->stat;
2342 	u8 table_case, tdma_case;
2343 
2344 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2345 
2346 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2347 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2348 
2349 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
2350 
2351 	if (coex_stat->bt_game_hid_exist && coex_stat->wl_linkscan_proc)
2352 		coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;
2353 
2354 	if (efuse->share_ant) {
2355 		/* Shared-Ant */
2356 		table_case = 0;
2357 		tdma_case = 0;
2358 	} else {
2359 		/* Non-Shared-Ant */
2360 		table_case = 100;
2361 		tdma_case = 100;
2362 	}
2363 
2364 	rtw_coex_table(rtwdev, false, table_case);
2365 	rtw_coex_tdma(rtwdev, false, tdma_case);
2366 }
2367 
2368 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
2369 {
2370 	const struct rtw_chip_info *chip = rtwdev->chip;
2371 	struct rtw_efuse *efuse = &rtwdev->efuse;
2372 	u8 table_case, tdma_case;
2373 
2374 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2375 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2376 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2377 
2378 	if (efuse->share_ant) {
2379 		/* Shared-Ant */
2380 		table_case = 2;
2381 		tdma_case = 0;
2382 	} else {
2383 		/* Non-Shared-Ant */
2384 		table_case = 100;
2385 		tdma_case = 100;
2386 	}
2387 
2388 	rtw_coex_table(rtwdev, false, table_case);
2389 	rtw_coex_tdma(rtwdev, false, tdma_case);
2390 }
2391 
2392 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
2393 {
2394 	const struct rtw_chip_info *chip = rtwdev->chip;
2395 	struct rtw_coex *coex = &rtwdev->coex;
2396 	struct rtw_efuse *efuse = &rtwdev->efuse;
2397 	struct rtw_coex_stat *coex_stat = &coex->stat;
2398 	u8 table_case, tdma_case;
2399 
2400 	if (coex->under_5g)
2401 		return;
2402 
2403 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2404 
2405 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2406 
2407 	if (efuse->share_ant) {
2408 		/* Shared-Ant */
2409 		table_case = 28;
2410 		tdma_case = 0;
2411 	} else {
2412 		/* Non-Shared-Ant */
2413 		table_case = 100;
2414 		tdma_case = 100;
2415 	}
2416 
2417 	if (coex_stat->bt_game_hid_exist) {
2418 		coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;
2419 		if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
2420 			rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]);
2421 		else
2422 			rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]);
2423 	} else {
2424 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2425 	}
2426 
2427 	rtw_coex_table(rtwdev, false, table_case);
2428 	rtw_coex_tdma(rtwdev, false, tdma_case);
2429 }
2430 
2431 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
2432 {
2433 	const struct rtw_chip_info *chip = rtwdev->chip;
2434 	struct rtw_coex *coex = &rtwdev->coex;
2435 	struct rtw_coex_stat *coex_stat = &coex->stat;
2436 	struct rtw_efuse *efuse = &rtwdev->efuse;
2437 	u8 table_case, tdma_case;
2438 	u32 slot_type = 0;
2439 
2440 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2441 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2442 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2443 
2444 	if (efuse->share_ant) { /* Shared-Ant */
2445 		if (coex_stat->bt_a2dp_exist) {
2446 			slot_type = TDMA_4SLOT;
2447 			tdma_case = 11;
2448 			if (coex_stat->wl_gl_busy)
2449 				table_case = 26;
2450 			else
2451 				table_case = 9;
2452 		} else {
2453 			table_case = 9;
2454 			tdma_case = 7;
2455 		}
2456 	} else { /* Non-Shared-Ant */
2457 		if (coex_stat->bt_a2dp_exist) {
2458 			slot_type = TDMA_4SLOT;
2459 			table_case = 112;
2460 			tdma_case = 111;
2461 		} else {
2462 			table_case = 112;
2463 			tdma_case = 107;
2464 		}
2465 	}
2466 
2467 	rtw_coex_table(rtwdev, false, table_case);
2468 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2469 }
2470 
2471 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
2472 {
2473 	const struct rtw_chip_info *chip = rtwdev->chip;
2474 	struct rtw_efuse *efuse = &rtwdev->efuse;
2475 	u8 table_case, tdma_case;
2476 
2477 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2478 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2479 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2480 
2481 	if (efuse->share_ant) {
2482 		/* Shared-Ant */
2483 		table_case = 1;
2484 		tdma_case = 0;
2485 	} else {
2486 		/* Non-Shared-Ant */
2487 		table_case = 100;
2488 		tdma_case = 100;
2489 	}
2490 
2491 	rtw_coex_table(rtwdev, false, table_case);
2492 	rtw_coex_tdma(rtwdev, false, tdma_case);
2493 }
2494 
2495 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
2496 {
2497 	struct rtw_coex *coex = &rtwdev->coex;
2498 	struct rtw_coex_stat *coex_stat = &coex->stat;
2499 	u8 algorithm;
2500 
2501 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2502 
2503 	algorithm = rtw_coex_algorithm(rtwdev);
2504 
2505 	switch (algorithm) {
2506 	case COEX_ALGO_HFP:
2507 		rtw_coex_action_bt_hfp(rtwdev);
2508 		break;
2509 	case COEX_ALGO_HID:
2510 		if (rtw_coex_freerun_check(rtwdev))
2511 			rtw_coex_action_freerun(rtwdev);
2512 		else
2513 			rtw_coex_action_bt_hid(rtwdev);
2514 		break;
2515 	case COEX_ALGO_A2DP:
2516 		if (rtw_coex_freerun_check(rtwdev))
2517 			rtw_coex_action_freerun(rtwdev);
2518 		else if (coex_stat->bt_a2dp_sink)
2519 			rtw_coex_action_bt_a2dpsink(rtwdev);
2520 		else
2521 			rtw_coex_action_bt_a2dp(rtwdev);
2522 		break;
2523 	case COEX_ALGO_PAN:
2524 		rtw_coex_action_bt_pan(rtwdev);
2525 		break;
2526 	case COEX_ALGO_A2DP_HID:
2527 		if (rtw_coex_freerun_check(rtwdev))
2528 			rtw_coex_action_freerun(rtwdev);
2529 		else
2530 			rtw_coex_action_bt_a2dp_hid(rtwdev);
2531 		break;
2532 	case COEX_ALGO_A2DP_PAN:
2533 		rtw_coex_action_bt_a2dp_pan(rtwdev);
2534 		break;
2535 	case COEX_ALGO_PAN_HID:
2536 		rtw_coex_action_bt_pan_hid(rtwdev);
2537 		break;
2538 	case COEX_ALGO_A2DP_PAN_HID:
2539 		rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
2540 		break;
2541 	default:
2542 	case COEX_ALGO_NOPROFILE:
2543 		rtw_coex_action_bt_idle(rtwdev);
2544 		break;
2545 	}
2546 }
2547 
2548 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
2549 {
2550 	const struct rtw_chip_info *chip = rtwdev->chip;
2551 	struct rtw_coex *coex = &rtwdev->coex;
2552 	struct rtw_coex_dm *coex_dm = &coex->dm;
2553 	struct rtw_coex_stat *coex_stat = &coex->stat;
2554 	bool rf4ce_en = false;
2555 
2556 	lockdep_assert_held(&rtwdev->mutex);
2557 
2558 	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
2559 		return;
2560 
2561 	coex_dm->reason = reason;
2562 
2563 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): reason = %d\n", __func__,
2564 		reason);
2565 
2566 	/* update wifi_link_info_ext variable */
2567 	rtw_coex_update_wl_link_info(rtwdev, reason);
2568 
2569 	rtw_coex_monitor_bt_enable(rtwdev);
2570 
2571 	if (coex->manual_control) {
2572 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2573 			"[BTCoex], return for Manual CTRL!!\n");
2574 		return;
2575 	}
2576 
2577 	if (coex->stop_dm) {
2578 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2579 			"[BTCoex], return for Stop Coex DM!!\n");
2580 		return;
2581 	}
2582 
2583 	if (coex_stat->wl_under_ips) {
2584 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2585 			"[BTCoex], return for wifi is under IPS!!\n");
2586 		return;
2587 	}
2588 
2589 	if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&
2590 	    !coex_stat->bt_setup_link) {
2591 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2592 			"[BTCoex], return for coex_freeze!!\n");
2593 		return;
2594 	}
2595 
2596 	coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
2597 	coex->freerun = false;
2598 
2599 	/* Pure-5G Coex Process */
2600 	if (coex->under_5g) {
2601 		coex_stat->wl_coex_mode = COEX_WLINK_5G;
2602 		rtw_coex_action_wl_under5g(rtwdev);
2603 		goto exit;
2604 	}
2605 
2606 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WiFi is single-port 2G!!\n");
2607 	coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
2608 
2609 	if (coex_stat->bt_disabled) {
2610 		if (coex_stat->wl_connected && rf4ce_en)
2611 			rtw_coex_action_rf4ce(rtwdev);
2612 		else if (!coex_stat->wl_connected)
2613 			rtw_coex_action_wl_not_connected(rtwdev);
2614 		else
2615 			rtw_coex_action_wl_only(rtwdev);
2616 		goto exit;
2617 	}
2618 
2619 	if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
2620 		rtw_coex_action_wl_native_lps(rtwdev);
2621 		goto exit;
2622 	}
2623 
2624 	if (coex_stat->bt_game_hid_exist && coex_stat->wl_connected) {
2625 		rtw_coex_action_bt_game_hid(rtwdev);
2626 		goto exit;
2627 	}
2628 
2629 	if (coex_stat->bt_whck_test) {
2630 		rtw_coex_action_bt_whql_test(rtwdev);
2631 		goto exit;
2632 	}
2633 
2634 	if (coex_stat->bt_setup_link) {
2635 		rtw_coex_action_bt_relink(rtwdev);
2636 		goto exit;
2637 	}
2638 
2639 	if (coex_stat->bt_inq_page) {
2640 		rtw_coex_action_bt_inquiry(rtwdev);
2641 		goto exit;
2642 	}
2643 
2644 	if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
2645 	     coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
2646 	     coex_stat->wl_connected) {
2647 		rtw_coex_action_bt_idle(rtwdev);
2648 		goto exit;
2649 	}
2650 
2651 	if (coex_stat->wl_linkscan_proc && !coex->freerun) {
2652 		rtw_coex_action_wl_linkscan(rtwdev);
2653 		goto exit;
2654 	}
2655 
2656 	if (coex_stat->wl_connected) {
2657 		rtw_coex_action_wl_connected(rtwdev);
2658 		goto exit;
2659 	} else {
2660 		rtw_coex_action_wl_not_connected(rtwdev);
2661 		goto exit;
2662 	}
2663 
2664 exit:
2665 
2666 	if (chip->wl_mimo_ps_support) {
2667 		if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
2668 			if (coex_dm->reason == COEX_RSN_2GMEDIA)
2669 				rtw_coex_mimo_ps(rtwdev, true, true);
2670 			else
2671 				rtw_coex_mimo_ps(rtwdev, false, true);
2672 		} else {
2673 			rtw_coex_mimo_ps(rtwdev, false, false);
2674 		}
2675 	}
2676 
2677 	rtw_coex_gnt_workaround(rtwdev, false, coex_stat->wl_coex_mode);
2678 	rtw_coex_limited_wl(rtwdev);
2679 }
2680 
2681 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
2682 {
2683 	struct rtw_coex *coex = &rtwdev->coex;
2684 	struct rtw_coex_stat *coex_stat = &coex->stat;
2685 	struct rtw_coex_dm *coex_dm = &coex->dm;
2686 	u8 i;
2687 
2688 	memset(coex_dm, 0, sizeof(*coex_dm));
2689 	memset(coex_stat, 0, sizeof(*coex_stat));
2690 
2691 	for (i = 0; i < COEX_CNT_WL_MAX; i++)
2692 		coex_stat->cnt_wl[i] = 0;
2693 
2694 	for (i = 0; i < COEX_CNT_BT_MAX; i++)
2695 		coex_stat->cnt_bt[i] = 0;
2696 
2697 	for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
2698 		coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
2699 
2700 	for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
2701 		coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
2702 
2703 	coex_stat->wl_coex_mode = COEX_WLINK_MAX;
2704 	coex_stat->wl_rx_rate = DESC_RATE5_5M;
2705 	coex_stat->wl_rts_rx_rate = DESC_RATE5_5M;
2706 }
2707 
2708 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2709 {
2710 	struct rtw_coex *coex = &rtwdev->coex;
2711 	struct rtw_coex_stat *coex_stat = &coex->stat;
2712 
2713 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2714 
2715 	rtw_coex_init_coex_var(rtwdev);
2716 
2717 	coex_stat->kt_ver = u8_get_bits(rtw_read8(rtwdev, 0xf1), GENMASK(7, 4));
2718 
2719 	rtw_coex_monitor_bt_enable(rtwdev);
2720 	rtw_coex_wl_slot_extend(rtwdev, coex_stat->wl_slot_extend);
2721 
2722 	rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
2723 
2724 	rtw_coex_set_rfe_type(rtwdev);
2725 	rtw_coex_set_init(rtwdev);
2726 
2727 	/* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
2728 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
2729 
2730 	/* set Tx beacon = Hi-Pri */
2731 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
2732 
2733 	/* set Tx beacon queue = Hi-Pri */
2734 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
2735 
2736 	/* antenna config */
2737 	if (coex->wl_rf_off) {
2738 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2739 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2740 		coex->stop_dm = true;
2741 
2742 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): RF Off\n",
2743 			__func__);
2744 	} else if (wifi_only) {
2745 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
2746 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
2747 				    true);
2748 		coex->stop_dm = true;
2749 	} else {
2750 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
2751 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
2752 				    true);
2753 		coex->stop_dm = false;
2754 		coex->freeze = true;
2755 	}
2756 
2757 	/* PTA parameter */
2758 	rtw_coex_table(rtwdev, true, 1);
2759 	rtw_coex_tdma(rtwdev, true, 0);
2760 	rtw_coex_query_bt_info(rtwdev);
2761 }
2762 
2763 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
2764 {
2765 	struct rtw_coex *coex = &rtwdev->coex;
2766 	u8 table_case = 1;
2767 
2768 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2769 
2770 	coex->stop_dm = true;
2771 	coex->wl_rf_off = false;
2772 
2773 	/* enable BB, we can write 0x948 */
2774 	rtw_write8_set(rtwdev, REG_SYS_FUNC_EN,
2775 		       BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB);
2776 
2777 	rtw_coex_monitor_bt_enable(rtwdev);
2778 	rtw_coex_set_rfe_type(rtwdev);
2779 
2780 	/* set antenna path to BT */
2781 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
2782 
2783 	rtw_coex_table(rtwdev, true, table_case);
2784 	/* red x issue */
2785 	rtw_write8(rtwdev, 0xff1a, 0x0);
2786 	rtw_coex_set_gnt_debug(rtwdev);
2787 }
2788 EXPORT_SYMBOL(rtw_coex_power_on_setting);
2789 
2790 void rtw_coex_power_off_setting(struct rtw_dev *rtwdev)
2791 {
2792 	rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN);
2793 }
2794 EXPORT_SYMBOL(rtw_coex_power_off_setting);
2795 
2796 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2797 {
2798 	__rtw_coex_init_hw_config(rtwdev, wifi_only);
2799 }
2800 EXPORT_SYMBOL(rtw_coex_init_hw_config);
2801 
2802 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
2803 {
2804 	struct rtw_coex *coex = &rtwdev->coex;
2805 	struct rtw_coex_stat *coex_stat = &coex->stat;
2806 
2807 	if (coex->manual_control || coex->stop_dm)
2808 		return;
2809 
2810 	if (type == COEX_IPS_ENTER) {
2811 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS ENTER notify\n");
2812 
2813 		coex_stat->wl_under_ips = true;
2814 
2815 		/* for lps off */
2816 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2817 
2818 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2819 		rtw_coex_action_coex_all_off(rtwdev);
2820 	} else if (type == COEX_IPS_LEAVE) {
2821 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS LEAVE notify\n");
2822 
2823 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2824 		/* run init hw config (exclude wifi only) */
2825 		__rtw_coex_init_hw_config(rtwdev, false);
2826 
2827 		coex_stat->wl_under_ips = false;
2828 	}
2829 }
2830 
2831 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
2832 {
2833 	struct rtw_coex *coex = &rtwdev->coex;
2834 	struct rtw_coex_stat *coex_stat = &coex->stat;
2835 
2836 	if (coex->manual_control || coex->stop_dm)
2837 		return;
2838 
2839 	if (type == COEX_LPS_ENABLE) {
2840 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS ENABLE notify\n");
2841 
2842 		coex_stat->wl_under_lps = true;
2843 
2844 		if (coex_stat->wl_force_lps_ctrl) {
2845 			/* for ps-tdma */
2846 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2847 		} else {
2848 			/* for native ps */
2849 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2850 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_WLBUSY, false);
2851 
2852 			rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2853 		}
2854 	} else if (type == COEX_LPS_DISABLE) {
2855 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS DISABLE notify\n");
2856 
2857 		coex_stat->wl_under_lps = false;
2858 
2859 		/* for lps off */
2860 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2861 
2862 		if (!coex_stat->wl_force_lps_ctrl)
2863 			rtw_coex_query_bt_info(rtwdev);
2864 
2865 		rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2866 	}
2867 }
2868 
2869 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
2870 {
2871 	struct rtw_coex *coex = &rtwdev->coex;
2872 	struct rtw_coex_stat *coex_stat = &coex->stat;
2873 
2874 	if (coex->manual_control || coex->stop_dm)
2875 		return;
2876 
2877 	coex->freeze = false;
2878 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2879 
2880 	if (type == COEX_SCAN_START_5G) {
2881 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2882 			"[BTCoex], SCAN START notify (5G)\n");
2883 
2884 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2885 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
2886 	} else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
2887 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2888 			"[BTCoex], SCAN START notify (2G)\n");
2889 
2890 		coex_stat->wl_hi_pri_task2 = true;
2891 
2892 		/* Force antenna setup for no scan result issue */
2893 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2894 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
2895 	} else {
2896 		coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] = 30; /* To do */
2897 
2898 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2899 			"[BTCoex], SCAN FINISH notify (Scan-AP = %d)\n",
2900 			coex_stat->cnt_wl[COEX_CNT_WL_SCANAP]);
2901 
2902 		coex_stat->wl_hi_pri_task2 = false;
2903 		rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
2904 	}
2905 }
2906 
2907 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
2908 {
2909 	struct rtw_coex *coex = &rtwdev->coex;
2910 
2911 	if (coex->manual_control || coex->stop_dm)
2912 		return;
2913 
2914 	if (type == COEX_SWITCH_TO_5G) {
2915 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_5G\n",
2916 			__func__);
2917 	} else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) {
2918 		rtw_dbg(rtwdev, RTW_DBG_COEX,
2919 			"[BTCoex], %s(): TO_24G_NOFORSCAN\n", __func__);
2920 	} else {
2921 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_2G\n",
2922 			__func__);
2923 	}
2924 
2925 	if (type == COEX_SWITCH_TO_5G)
2926 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
2927 	else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
2928 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
2929 	else
2930 		rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
2931 }
2932 
2933 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
2934 {
2935 	struct rtw_coex *coex = &rtwdev->coex;
2936 	struct rtw_coex_stat *coex_stat = &coex->stat;
2937 
2938 	if (coex->manual_control || coex->stop_dm)
2939 		return;
2940 
2941 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2942 
2943 	if (type == COEX_ASSOCIATE_5G_START) {
2944 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G start\n",
2945 			__func__);
2946 
2947 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2948 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
2949 	} else if (type == COEX_ASSOCIATE_5G_FINISH) {
2950 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G finish\n",
2951 			__func__);
2952 
2953 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2954 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
2955 	} else if (type == COEX_ASSOCIATE_START) {
2956 		coex_stat->wl_hi_pri_task1 = true;
2957 		coex_stat->wl_connecting = true;
2958 		coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
2959 		coex_stat->wl_connecting = true;
2960 		ieee80211_queue_delayed_work(rtwdev->hw,
2961 					     &coex->wl_connecting_work, 2 * HZ);
2962 
2963 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G start\n",
2964 			__func__);
2965 		/* Force antenna setup for no scan result issue */
2966 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2967 
2968 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
2969 
2970 		/* To keep TDMA case during connect process,
2971 		 * to avoid changed by Btinfo and runcoexmechanism
2972 		 */
2973 		coex->freeze = true;
2974 		ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
2975 					     5 * HZ);
2976 	} else {
2977 		coex_stat->wl_hi_pri_task1 = false;
2978 		coex->freeze = false;
2979 		coex_stat->wl_connecting = false;
2980 
2981 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G finish\n",
2982 			__func__);
2983 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
2984 	}
2985 }
2986 
2987 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
2988 {
2989 	struct rtw_coex *coex = &rtwdev->coex;
2990 	struct rtw_coex_stat *coex_stat = &coex->stat;
2991 
2992 	if (coex->manual_control || coex->stop_dm)
2993 		return;
2994 
2995 	if (type == COEX_MEDIA_CONNECT_5G) {
2996 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G\n", __func__);
2997 
2998 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2999 
3000 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
3001 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
3002 	} else if (type == COEX_MEDIA_CONNECT) {
3003 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G\n", __func__);
3004 
3005 		coex_stat->wl_connecting = false;
3006 
3007 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
3008 
3009 		/* Force antenna setup for no scan result issue */
3010 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
3011 
3012 		/* Set CCK Rx high Pri */
3013 		rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
3014 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
3015 	} else {
3016 		rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): disconnect!!\n",
3017 			__func__);
3018 		rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
3019 		rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
3020 	}
3021 
3022 	rtw_coex_update_wl_ch_info(rtwdev, type);
3023 }
3024 
3025 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
3026 {
3027 	const struct rtw_chip_info *chip = rtwdev->chip;
3028 	struct rtw_coex *coex = &rtwdev->coex;
3029 	struct rtw_coex_stat *coex_stat = &coex->stat;
3030 	struct rtw_coex_dm *coex_dm = &coex->dm;
3031 	u32 bt_relink_time;
3032 	u8 i, rsp_source = 0, type;
3033 	bool inq_page = false;
3034 
3035 	rsp_source = buf[0] & 0xf;
3036 	if (rsp_source >= COEX_BTINFO_SRC_MAX)
3037 		return;
3038 	coex_stat->cnt_bt_info_c2h[rsp_source]++;
3039 
3040 	if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
3041 		coex_stat->bt_iqk_state = buf[1];
3042 		if (coex_stat->bt_iqk_state == 0)
3043 			coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
3044 		else if (coex_stat->bt_iqk_state == 2)
3045 			coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
3046 
3047 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3048 			"[BTCoex], BT IQK by bt_info, data0 = 0x%02x\n",
3049 			buf[1]);
3050 
3051 		return;
3052 	}
3053 
3054 	if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
3055 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3056 			"[BTCoex], BT Scoreboard change notify by WL FW c2h, 0xaa = 0x%02x, 0xab = 0x%02x\n",
3057 			buf[1], buf[2]);
3058 
3059 		rtw_coex_monitor_bt_enable(rtwdev);
3060 		if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
3061 			coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
3062 			rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
3063 		}
3064 		return;
3065 	}
3066 
3067 	if (rsp_source == COEX_BTINFO_SRC_H2C60) {
3068 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3069 			"[BTCoex], H2C 0x60 content replied by WL FW: H2C_0x60 = [%02x %02x %02x %02x %02x]\n",
3070 			buf[1], buf[2], buf[3], buf[4], buf[5]);
3071 
3072 		for (i = 1; i <= COEX_WL_TDMA_PARA_LENGTH; i++)
3073 			coex_dm->fw_tdma_para[i - 1] = buf[i];
3074 		return;
3075 	}
3076 
3077 	if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
3078 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3079 			"[BTCoex], bt_info reply by WL FW\n");
3080 
3081 		rtw_coex_update_bt_link_info(rtwdev);
3082 		return;
3083 	}
3084 
3085 	if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
3086 	    rsp_source == COEX_BTINFO_SRC_BT_ACT) {
3087 		if (coex_stat->bt_disabled) {
3088 			coex_stat->bt_disabled = false;
3089 			coex_stat->bt_reenable = true;
3090 			ieee80211_queue_delayed_work(rtwdev->hw,
3091 						     &coex->bt_reenable_work,
3092 						     15 * HZ);
3093 			rtw_dbg(rtwdev, RTW_DBG_COEX,
3094 				"[BTCoex], BT enable detected by bt_info\n");
3095 		}
3096 	}
3097 
3098 	if (length != COEX_BTINFO_LENGTH) {
3099 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3100 			"[BTCoex], Bt_info length = %d invalid!!\n", length);
3101 
3102 		return;
3103 	}
3104 
3105 	rtw_dbg(rtwdev, RTW_DBG_COEX,
3106 		"[BTCoex], Bt_info[%d], len=%d, data=[%02x %02x %02x %02x %02x %02x]\n",
3107 		buf[0], length, buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
3108 
3109 	for (i = 0; i < COEX_BTINFO_LENGTH; i++)
3110 		coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
3111 
3112 	if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A)
3113 		coex_stat->bt_info_c2h[rsp_source][5] = 0;
3114 
3115 	/* get the same info from bt, skip it */
3116 	if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
3117 	    coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
3118 	    coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
3119 	    coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
3120 	    coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
3121 	    coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) {
3122 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3123 			"[BTCoex], Return because Btinfo duplicate!!\n");
3124 		return;
3125 	}
3126 
3127 	coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
3128 	coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
3129 	coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
3130 	coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
3131 	coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
3132 	coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
3133 
3134 	/* 0xff means BT is under WHCK test */
3135 	coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
3136 
3137 	inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
3138 
3139 	if (inq_page != coex_stat->bt_inq_page) {
3140 		cancel_delayed_work_sync(&coex->bt_remain_work);
3141 		coex_stat->bt_inq_page = inq_page;
3142 
3143 		if (inq_page)
3144 			coex_stat->bt_inq_remain = true;
3145 		else
3146 			ieee80211_queue_delayed_work(rtwdev->hw,
3147 						     &coex->bt_remain_work,
3148 						     4 * HZ);
3149 	}
3150 	coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
3151 	if (chip->ble_hid_profile_support) {
3152 		if (coex_stat->bt_info_lb2 & BIT(5)) {
3153 			if (coex_stat->bt_info_hb1 & BIT(0)) {
3154 				/*BLE HID*/
3155 				coex_stat->bt_ble_hid_exist = true;
3156 			} else {
3157 				coex_stat->bt_ble_hid_exist = false;
3158 			}
3159 			coex_stat->bt_ble_exist = false;
3160 		} else if (coex_stat->bt_info_hb1 & BIT(0)) {
3161 			/*RCU*/
3162 			coex_stat->bt_ble_hid_exist = false;
3163 			coex_stat->bt_ble_exist = true;
3164 		} else {
3165 			coex_stat->bt_ble_hid_exist = false;
3166 			coex_stat->bt_ble_exist = false;
3167 		}
3168 	} else {
3169 		if (coex_stat->bt_info_hb1 & BIT(0)) {
3170 			if (coex_stat->bt_hid_slot == 1 &&
3171 			    coex_stat->hi_pri_rx + 100 < coex_stat->hi_pri_tx &&
3172 			    coex_stat->hi_pri_rx < 100) {
3173 				coex_stat->bt_ble_hid_exist = true;
3174 				coex_stat->bt_ble_exist = false;
3175 			} else {
3176 				coex_stat->bt_ble_hid_exist = false;
3177 				coex_stat->bt_ble_exist = true;
3178 			}
3179 		} else {
3180 			coex_stat->bt_ble_hid_exist = false;
3181 			coex_stat->bt_ble_exist = false;
3182 		}
3183 	}
3184 
3185 	coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
3186 	if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
3187 		coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
3188 
3189 	coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
3190 	coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
3191 	if (coex_stat->bt_inq)
3192 		coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
3193 
3194 	coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
3195 	if (coex_stat->bt_page)
3196 		coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
3197 
3198 	/* unit: % (value-100 to translate to unit: dBm in coex info) */
3199 	if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
3200 		coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
3201 	} else {
3202 		if (coex_stat->bt_info_hb0 <= 127)
3203 			coex_stat->bt_rssi = 100;
3204 		else if (256 - coex_stat->bt_info_hb0 <= 100)
3205 			coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
3206 		else
3207 			coex_stat->bt_rssi = 0;
3208 	}
3209 
3210 	if (coex_stat->bt_info_hb1 & BIT(1))
3211 		coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
3212 
3213 	if (coex_stat->bt_info_hb1 & BIT(2)) {
3214 		coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
3215 		coex_stat->bt_setup_link = true;
3216 		if (coex_stat->bt_reenable)
3217 			bt_relink_time = 6 * HZ;
3218 		else
3219 			bt_relink_time = 1 * HZ;
3220 
3221 		ieee80211_queue_delayed_work(rtwdev->hw,
3222 					     &coex->bt_relink_work,
3223 					     bt_relink_time);
3224 
3225 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3226 			"[BTCoex], Re-Link start in BT info!!\n");
3227 	}
3228 
3229 	if (coex_stat->bt_info_hb1 & BIT(3))
3230 		coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
3231 
3232 	coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
3233 	coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
3234 	if (coex_stat->bt_info_hb1 & BIT(6))
3235 		coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
3236 
3237 	coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
3238 	/* for multi_link = 0 but bt pkt remain exist */
3239 	/* Use PS-TDMA to protect WL RX */
3240 	if (!coex_stat->bt_multi_link && coex_stat->bt_multi_link_pre) {
3241 		coex_stat->bt_multi_link_remain = true;
3242 		ieee80211_queue_delayed_work(rtwdev->hw,
3243 					     &coex->bt_multi_link_remain_work,
3244 					     3 * HZ);
3245 	}
3246 	coex_stat->bt_multi_link_pre = coex_stat->bt_multi_link;
3247 
3248 	/* resend wifi info to bt, it is reset and lost the info */
3249 	if (coex_stat->bt_info_hb1 & BIT(1)) {
3250 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3251 			"[BTCoex], BT Re-init, send wifi BW & Chnl to BT!!\n");
3252 
3253 		if (coex_stat->wl_connected)
3254 			type = COEX_MEDIA_CONNECT;
3255 		else
3256 			type = COEX_MEDIA_DISCONNECT;
3257 		rtw_coex_update_wl_ch_info(rtwdev, type);
3258 	}
3259 
3260 	/* if ignore_wlan_act && not set_up_link */
3261 	if ((coex_stat->bt_info_hb1 & BIT(3)) &&
3262 	    (!(coex_stat->bt_info_hb1 & BIT(2)))) {
3263 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3264 			"[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
3265 		rtw_coex_ignore_wlan_act(rtwdev, false);
3266 	}
3267 
3268 	coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
3269 	if (coex_stat->bt_info_hb2 & BIT(1))
3270 		coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
3271 
3272 	coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
3273 	coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
3274 	coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
3275 	coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
3276 	if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
3277 		coex_stat->bt_418_hid_exist = true;
3278 	else if (coex_stat->bt_hid_pair_num == 0 || coex_stat->bt_hid_slot == 1)
3279 		coex_stat->bt_418_hid_exist = false;
3280 
3281 	if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
3282 		coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
3283 	else
3284 		coex_stat->bt_a2dp_bitpool = 0;
3285 
3286 	coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
3287 
3288 	rtw_coex_update_bt_link_info(rtwdev);
3289 	rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
3290 }
3291 
3292 #define COEX_BT_HIDINFO_MTK	0x46
3293 static const u8 coex_bt_hidinfo_ps[] = {0x57, 0x69, 0x72};
3294 static const u8 coex_bt_hidinfo_xb[] = {0x58, 0x62, 0x6f};
3295 
3296 void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
3297 {
3298 	const struct rtw_chip_info *chip = rtwdev->chip;
3299 	struct rtw_coex *coex = &rtwdev->coex;
3300 	struct rtw_coex_stat *coex_stat = &coex->stat;
3301 	struct rtw_coex_hid *hidinfo;
3302 	struct rtw_coex_hid_info_a *hida;
3303 	struct rtw_coex_hid_handle_list *hl, *bhl;
3304 	u8 sub_id = buf[2], gamehid_cnt = 0, handle, i;
3305 	bool cur_game_hid_exist, complete;
3306 
3307 	if (!chip->wl_mimo_ps_support &&
3308 	    (sub_id == COEX_BT_HIDINFO_LIST || sub_id == COEX_BT_HIDINFO_A))
3309 		return;
3310 
3311 	rtw_dbg(rtwdev, RTW_DBG_COEX,
3312 		"[BTCoex], HID info notify, sub_id = 0x%x\n", sub_id);
3313 
3314 	switch (sub_id) {
3315 	case COEX_BT_HIDINFO_LIST:
3316 		hl = &coex_stat->hid_handle_list;
3317 		bhl = (struct rtw_coex_hid_handle_list *)buf;
3318 		if (!memcmp(hl, bhl, sizeof(*hl)))
3319 			return;
3320 		coex_stat->hid_handle_list = *bhl;
3321 		memset(&coex_stat->hid_info, 0, sizeof(coex_stat->hid_info));
3322 		for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
3323 			hidinfo = &coex_stat->hid_info[i];
3324 			if (hl->handle[i] != COEX_BT_HIDINFO_NOTCON &&
3325 			    hl->handle[i] != 0)
3326 				hidinfo->hid_handle = hl->handle[i];
3327 		}
3328 		break;
3329 	case COEX_BT_HIDINFO_A:
3330 		hida = (struct rtw_coex_hid_info_a *)buf;
3331 		handle = hida->handle;
3332 		for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
3333 			hidinfo = &coex_stat->hid_info[i];
3334 			if (hidinfo->hid_handle == handle) {
3335 				hidinfo->hid_vendor = hida->vendor;
3336 				memcpy(hidinfo->hid_name, hida->name,
3337 				       sizeof(hidinfo->hid_name));
3338 				hidinfo->hid_info_completed = true;
3339 				break;
3340 			}
3341 		}
3342 		break;
3343 	}
3344 	for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
3345 		hidinfo = &coex_stat->hid_info[i];
3346 		complete = hidinfo->hid_info_completed;
3347 		handle = hidinfo->hid_handle;
3348 		if (!complete || handle == COEX_BT_HIDINFO_NOTCON ||
3349 		    handle == 0 || handle >= COEX_BT_BLE_HANDLE_THRS) {
3350 			hidinfo->is_game_hid = false;
3351 			continue;
3352 		}
3353 
3354 		if (hidinfo->hid_vendor == COEX_BT_HIDINFO_MTK) {
3355 			if ((memcmp(hidinfo->hid_name,
3356 				    coex_bt_hidinfo_ps,
3357 				    COEX_BT_HIDINFO_NAME)) == 0)
3358 				hidinfo->is_game_hid = true;
3359 			else if ((memcmp(hidinfo->hid_name,
3360 					 coex_bt_hidinfo_xb,
3361 					 COEX_BT_HIDINFO_NAME)) == 0)
3362 				hidinfo->is_game_hid = true;
3363 			else
3364 				hidinfo->is_game_hid = false;
3365 		} else {
3366 			hidinfo->is_game_hid = false;
3367 		}
3368 		if (hidinfo->is_game_hid)
3369 			gamehid_cnt++;
3370 	}
3371 
3372 	if (gamehid_cnt > 0)
3373 		cur_game_hid_exist = true;
3374 	else
3375 		cur_game_hid_exist = false;
3376 
3377 	if (cur_game_hid_exist != coex_stat->bt_game_hid_exist) {
3378 		coex_stat->bt_game_hid_exist = cur_game_hid_exist;
3379 		rtw_dbg(rtwdev, RTW_DBG_COEX,
3380 			"[BTCoex], HID info changed!bt_game_hid_exist = %d!\n",
3381 			coex_stat->bt_game_hid_exist);
3382 		rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
3383 	}
3384 }
3385 
3386 void rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev)
3387 {
3388 	const struct rtw_chip_info *chip = rtwdev->chip;
3389 	struct rtw_coex *coex = &rtwdev->coex;
3390 	struct rtw_coex_stat *coex_stat = &coex->stat;
3391 	struct rtw_coex_hid *hidinfo;
3392 	u8 i, handle;
3393 	bool complete;
3394 
3395 	if (!chip->wl_mimo_ps_support || coex_stat->wl_under_ips ||
3396 	    (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl))
3397 		return;
3398 
3399 	if (!coex_stat->bt_hid_exist &&
3400 	    !((coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION) &&
3401 	      (coex_stat->hi_pri_tx + coex_stat->hi_pri_rx >
3402 	       COEX_BT_GAMEHID_CNT)))
3403 		return;
3404 
3405 	rtw_fw_coex_query_hid_info(rtwdev, COEX_BT_HIDINFO_LIST, 0);
3406 
3407 	for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
3408 		hidinfo = &coex_stat->hid_info[i];
3409 		complete = hidinfo->hid_info_completed;
3410 		handle = hidinfo->hid_handle;
3411 		if (handle == 0 || handle == COEX_BT_HIDINFO_NOTCON ||
3412 		    handle >= COEX_BT_BLE_HANDLE_THRS || complete)
3413 			continue;
3414 
3415 		rtw_fw_coex_query_hid_info(rtwdev,
3416 					   COEX_BT_HIDINFO_A,
3417 					   handle);
3418 	}
3419 }
3420 
3421 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
3422 {
3423 	struct rtw_coex *coex = &rtwdev->coex;
3424 	struct rtw_coex_stat *coex_stat = &coex->stat;
3425 	u8 val;
3426 	int i;
3427 
3428 	rtw_dbg(rtwdev, RTW_DBG_COEX,
3429 		"[BTCoex], WiFi Fw Dbg info = %8ph (len = %d)\n",
3430 		buf, length);
3431 	if (WARN(length < 8, "invalid wl info c2h length\n"))
3432 		return;
3433 
3434 	if (buf[0] != 0x08)
3435 		return;
3436 
3437 	for (i = 1; i < 8; i++) {
3438 		val = coex_stat->wl_fw_dbg_info_pre[i];
3439 		if (buf[i] >= val)
3440 			coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
3441 		else
3442 			coex_stat->wl_fw_dbg_info[i] = 255 - val + buf[i];
3443 
3444 		coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
3445 	}
3446 
3447 	coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
3448 	rtw_coex_wl_ccklock_action(rtwdev);
3449 	rtw_coex_wl_ccklock_detect(rtwdev);
3450 }
3451 
3452 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type)
3453 {
3454 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3455 }
3456 
3457 void rtw_coex_wl_status_check(struct rtw_dev *rtwdev)
3458 {
3459 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3460 
3461 	if ((coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) ||
3462 	    coex_stat->wl_under_ips)
3463 		return;
3464 
3465 	rtw_coex_monitor_bt_ctr(rtwdev);
3466 }
3467 
3468 void rtw_coex_bt_relink_work(struct work_struct *work)
3469 {
3470 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3471 					      coex.bt_relink_work.work);
3472 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3473 
3474 	mutex_lock(&rtwdev->mutex);
3475 	coex_stat->bt_setup_link = false;
3476 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3477 	mutex_unlock(&rtwdev->mutex);
3478 }
3479 
3480 void rtw_coex_bt_reenable_work(struct work_struct *work)
3481 {
3482 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3483 					      coex.bt_reenable_work.work);
3484 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3485 
3486 	mutex_lock(&rtwdev->mutex);
3487 	coex_stat->bt_reenable = false;
3488 	mutex_unlock(&rtwdev->mutex);
3489 }
3490 
3491 void rtw_coex_defreeze_work(struct work_struct *work)
3492 {
3493 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3494 					      coex.defreeze_work.work);
3495 	struct rtw_coex *coex = &rtwdev->coex;
3496 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3497 
3498 	mutex_lock(&rtwdev->mutex);
3499 	coex->freeze = false;
3500 	coex_stat->wl_hi_pri_task1 = false;
3501 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3502 	mutex_unlock(&rtwdev->mutex);
3503 }
3504 
3505 void rtw_coex_wl_remain_work(struct work_struct *work)
3506 {
3507 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3508 					      coex.wl_remain_work.work);
3509 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3510 
3511 	mutex_lock(&rtwdev->mutex);
3512 	coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
3513 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3514 	mutex_unlock(&rtwdev->mutex);
3515 }
3516 
3517 void rtw_coex_bt_remain_work(struct work_struct *work)
3518 {
3519 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3520 					      coex.bt_remain_work.work);
3521 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3522 
3523 	mutex_lock(&rtwdev->mutex);
3524 	coex_stat->bt_inq_remain = coex_stat->bt_inq_page;
3525 	rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
3526 	mutex_unlock(&rtwdev->mutex);
3527 }
3528 
3529 void rtw_coex_wl_connecting_work(struct work_struct *work)
3530 {
3531 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3532 					      coex.wl_connecting_work.work);
3533 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3534 
3535 	mutex_lock(&rtwdev->mutex);
3536 	coex_stat->wl_connecting = false;
3537 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WL connecting stop!!\n");
3538 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3539 	mutex_unlock(&rtwdev->mutex);
3540 }
3541 
3542 void rtw_coex_bt_multi_link_remain_work(struct work_struct *work)
3543 {
3544 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3545 		coex.bt_multi_link_remain_work.work);
3546 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3547 
3548 	mutex_lock(&rtwdev->mutex);
3549 	coex_stat->bt_multi_link_remain = false;
3550 	mutex_unlock(&rtwdev->mutex);
3551 }
3552 
3553 void rtw_coex_wl_ccklock_work(struct work_struct *work)
3554 {
3555 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3556 					      coex.wl_ccklock_work.work);
3557 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3558 
3559 	mutex_lock(&rtwdev->mutex);
3560 	coex_stat->wl_cck_lock = false;
3561 	mutex_unlock(&rtwdev->mutex);
3562 }
3563 
3564 #ifdef CONFIG_RTW88_DEBUGFS
3565 #define INFO_SIZE	80
3566 
3567 #define case_BTINFO(src) \
3568 	case COEX_BTINFO_SRC_##src: return #src
3569 
3570 static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src)
3571 {
3572 	switch (bt_info_src) {
3573 	case_BTINFO(WL_FW);
3574 	case_BTINFO(BT_RSP);
3575 	case_BTINFO(BT_ACT);
3576 	default:
3577 		return "Unknown";
3578 	}
3579 }
3580 
3581 #define case_RSN(src) \
3582 	case COEX_RSN_##src: return #src
3583 
3584 static const char *rtw_coex_get_reason_string(u8 reason)
3585 {
3586 	switch (reason) {
3587 	case_RSN(2GSCANSTART);
3588 	case_RSN(5GSCANSTART);
3589 	case_RSN(SCANFINISH);
3590 	case_RSN(2GSWITCHBAND);
3591 	case_RSN(5GSWITCHBAND);
3592 	case_RSN(2GCONSTART);
3593 	case_RSN(5GCONSTART);
3594 	case_RSN(2GCONFINISH);
3595 	case_RSN(5GCONFINISH);
3596 	case_RSN(2GMEDIA);
3597 	case_RSN(5GMEDIA);
3598 	case_RSN(MEDIADISCON);
3599 	case_RSN(BTINFO);
3600 	case_RSN(LPS);
3601 	case_RSN(WLSTATUS);
3602 	default:
3603 		return "Unknown";
3604 	}
3605 }
3606 
3607 static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,
3608 				   u32 wl_reg_6c4)
3609 {
3610 	const struct rtw_chip_info *chip = rtwdev->chip;
3611 	struct rtw_efuse *efuse = &rtwdev->efuse;
3612 	u8 ans = 0xFF;
3613 	u8 n, i;
3614 	u32 load_bt_val;
3615 	u32 load_wl_val;
3616 	bool share_ant = efuse->share_ant;
3617 
3618 	if (share_ant)
3619 		n = chip->table_sant_num;
3620 	else
3621 		n = chip->table_nsant_num;
3622 
3623 	for (i = 0; i < n; i++) {
3624 		if (share_ant) {
3625 			load_bt_val = chip->table_sant[i].bt;
3626 			load_wl_val = chip->table_sant[i].wl;
3627 		} else {
3628 			load_bt_val = chip->table_nsant[i].bt;
3629 			load_wl_val = chip->table_nsant[i].wl;
3630 		}
3631 
3632 		if (wl_reg_6c0 == load_bt_val &&
3633 		    wl_reg_6c4 == load_wl_val) {
3634 			ans = i;
3635 			if (!share_ant)
3636 				ans += 100;
3637 			break;
3638 		}
3639 	}
3640 
3641 	return ans;
3642 }
3643 
3644 static u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para)
3645 {
3646 	const struct rtw_chip_info *chip = rtwdev->chip;
3647 	struct rtw_efuse *efuse = &rtwdev->efuse;
3648 	u8 ans = 0xFF;
3649 	u8 n, i, j;
3650 	u8 load_cur_tab_val;
3651 	bool valid = false;
3652 	bool share_ant = efuse->share_ant;
3653 
3654 	if (share_ant)
3655 		n = chip->tdma_sant_num;
3656 	else
3657 		n = chip->tdma_nsant_num;
3658 
3659 	for (i = 0; i < n; i++) {
3660 		valid = false;
3661 		for (j = 0; j < 5; j++) {
3662 			if (share_ant)
3663 				load_cur_tab_val = chip->tdma_sant[i].para[j];
3664 			else
3665 				load_cur_tab_val = chip->tdma_nsant[i].para[j];
3666 
3667 			if (*(tdma_para + j) != load_cur_tab_val)
3668 				break;
3669 
3670 			if (j == 4)
3671 				valid = true;
3672 		}
3673 		if (valid) {
3674 			ans = i;
3675 			break;
3676 		}
3677 	}
3678 
3679 	return ans;
3680 }
3681 
3682 static int rtw_coex_addr_info(struct rtw_dev *rtwdev,
3683 			      const struct rtw_reg_domain *reg,
3684 			      char addr_info[], int n)
3685 {
3686 	const char *rf_prefix = "";
3687 	const char *sep = n == 0 ? "" : "/ ";
3688 	int ffs, fls;
3689 	int max_fls;
3690 
3691 	if (INFO_SIZE - n <= 0)
3692 		return 0;
3693 
3694 	switch (reg->domain) {
3695 	case RTW_REG_DOMAIN_MAC32:
3696 		max_fls = 31;
3697 		break;
3698 	case RTW_REG_DOMAIN_MAC16:
3699 		max_fls = 15;
3700 		break;
3701 	case RTW_REG_DOMAIN_MAC8:
3702 		max_fls = 7;
3703 		break;
3704 	case RTW_REG_DOMAIN_RF_A:
3705 	case RTW_REG_DOMAIN_RF_B:
3706 		rf_prefix = "RF_";
3707 		max_fls = 19;
3708 		break;
3709 	default:
3710 		return 0;
3711 	}
3712 
3713 	ffs = __ffs(reg->mask);
3714 	fls = __fls(reg->mask);
3715 
3716 	if (ffs == 0 && fls == max_fls)
3717 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x",
3718 				 sep, rf_prefix, reg->addr);
3719 	else if (ffs == fls)
3720 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]",
3721 				 sep, rf_prefix, reg->addr, ffs);
3722 	else
3723 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]",
3724 				 sep, rf_prefix, reg->addr, fls, ffs);
3725 }
3726 
3727 static int rtw_coex_val_info(struct rtw_dev *rtwdev,
3728 			     const struct rtw_reg_domain *reg,
3729 			     char val_info[], int n)
3730 {
3731 	const char *sep = n == 0 ? "" : "/ ";
3732 	u8 rf_path;
3733 
3734 	if (INFO_SIZE - n <= 0)
3735 		return 0;
3736 
3737 	switch (reg->domain) {
3738 	case RTW_REG_DOMAIN_MAC32:
3739 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3740 				 rtw_read32_mask(rtwdev, reg->addr, reg->mask));
3741 	case RTW_REG_DOMAIN_MAC16:
3742 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3743 				 rtw_read16_mask(rtwdev, reg->addr, reg->mask));
3744 	case RTW_REG_DOMAIN_MAC8:
3745 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3746 				 rtw_read8_mask(rtwdev, reg->addr, reg->mask));
3747 	case RTW_REG_DOMAIN_RF_A:
3748 		rf_path = RF_PATH_A;
3749 		break;
3750 	case RTW_REG_DOMAIN_RF_B:
3751 		rf_path = RF_PATH_B;
3752 		break;
3753 	default:
3754 		return 0;
3755 	}
3756 
3757 	/* only RF go through here */
3758 	return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3759 			 rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask));
3760 }
3761 
3762 static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
3763 {
3764 	const struct rtw_chip_info *chip = rtwdev->chip;
3765 	const struct rtw_reg_domain *reg;
3766 	char addr_info[INFO_SIZE];
3767 	int n_addr = 0;
3768 	char val_info[INFO_SIZE];
3769 	int n_val = 0;
3770 	int i;
3771 
3772 	for (i = 0; i < chip->coex_info_hw_regs_num; i++) {
3773 		reg = &chip->coex_info_hw_regs[i];
3774 
3775 		n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr);
3776 		n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val);
3777 
3778 		if (reg->domain == RTW_REG_DOMAIN_NL) {
3779 			seq_printf(m, "%-40s = %s\n", addr_info, val_info);
3780 			n_addr = 0;
3781 			n_val = 0;
3782 		}
3783 	}
3784 
3785 	if (n_addr != 0 && n_val != 0)
3786 		seq_printf(m, "%-40s = %s\n", addr_info, val_info);
3787 }
3788 
3789 static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev,
3790 				u8 type, u16 addr, u16 *val)
3791 {
3792 	struct rtw_coex_info_req req = {0};
3793 	struct sk_buff *skb;
3794 	__le16 le_addr;
3795 	u8 *payload;
3796 
3797 	le_addr = cpu_to_le16(addr);
3798 	req.op_code = BT_MP_INFO_OP_READ_REG;
3799 	req.para1 = type;
3800 	req.para2 = le16_get_bits(le_addr, GENMASK(7, 0));
3801 	req.para3 = le16_get_bits(le_addr, GENMASK(15, 8));
3802 	skb = rtw_coex_info_request(rtwdev, &req);
3803 	if (!skb) {
3804 		*val = 0xeaea;
3805 		return false;
3806 	}
3807 
3808 	payload = get_payload_from_coex_resp(skb);
3809 	*val = GET_COEX_RESP_BT_REG_VAL(payload);
3810 	dev_kfree_skb_any(skb);
3811 
3812 	return true;
3813 }
3814 
3815 static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev,
3816 					  u32 *patch_version)
3817 {
3818 	struct rtw_coex_info_req req = {0};
3819 	struct sk_buff *skb;
3820 	u8 *payload;
3821 
3822 	req.op_code = BT_MP_INFO_OP_PATCH_VER;
3823 	skb = rtw_coex_info_request(rtwdev, &req);
3824 	if (!skb)
3825 		return false;
3826 
3827 	payload = get_payload_from_coex_resp(skb);
3828 	*patch_version = GET_COEX_RESP_BT_PATCH_VER(payload);
3829 	dev_kfree_skb_any(skb);
3830 
3831 	return true;
3832 }
3833 
3834 static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev,
3835 					      u32 *supported_version)
3836 {
3837 	struct rtw_coex_info_req req = {0};
3838 	struct sk_buff *skb;
3839 	u8 *payload;
3840 
3841 	req.op_code = BT_MP_INFO_OP_SUPP_VER;
3842 	skb = rtw_coex_info_request(rtwdev, &req);
3843 	if (!skb)
3844 		return false;
3845 
3846 	payload = get_payload_from_coex_resp(skb);
3847 	*supported_version = GET_COEX_RESP_BT_SUPP_VER(payload);
3848 	dev_kfree_skb_any(skb);
3849 
3850 	return true;
3851 }
3852 
3853 static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev,
3854 					      u32 *supported_feature)
3855 {
3856 	struct rtw_coex_info_req req = {0};
3857 	struct sk_buff *skb;
3858 	u8 *payload;
3859 
3860 	req.op_code = BT_MP_INFO_OP_SUPP_FEAT;
3861 	skb = rtw_coex_info_request(rtwdev, &req);
3862 	if (!skb)
3863 		return false;
3864 
3865 	payload = get_payload_from_coex_resp(skb);
3866 	*supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload);
3867 	dev_kfree_skb_any(skb);
3868 
3869 	return true;
3870 }
3871 
3872 struct rtw_coex_sta_stat_iter_data {
3873 	struct rtw_vif *rtwvif;
3874 	struct seq_file *file;
3875 };
3876 
3877 static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta)
3878 {
3879 	struct rtw_coex_sta_stat_iter_data *sta_iter_data = data;
3880 	struct rtw_vif *rtwvif = sta_iter_data->rtwvif;
3881 	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
3882 	struct seq_file *m = sta_iter_data->file;
3883 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
3884 	u8 rssi;
3885 
3886 	if (si->vif != vif)
3887 		return;
3888 
3889 	rssi = ewma_rssi_read(&si->avg_rssi);
3890 	seq_printf(m, "\tPeer %3d\n", si->mac_id);
3891 	seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi);
3892 	seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode);
3893 }
3894 
3895 struct rtw_coex_vif_stat_iter_data {
3896 	struct rtw_dev *rtwdev;
3897 	struct seq_file *file;
3898 };
3899 
3900 static void rtw_coex_vif_stat_iter(void *data, u8 *mac,
3901 				   struct ieee80211_vif *vif)
3902 {
3903 	struct rtw_coex_vif_stat_iter_data *vif_iter_data = data;
3904 	struct rtw_coex_sta_stat_iter_data sta_iter_data;
3905 	struct rtw_dev *rtwdev = vif_iter_data->rtwdev;
3906 	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
3907 	struct seq_file *m = vif_iter_data->file;
3908 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
3909 
3910 	seq_printf(m, "Iface on Port (%d)\n", rtwvif->port);
3911 	seq_printf(m, "\t%-32s = %d\n",
3912 		   "Beacon interval", bss_conf->beacon_int);
3913 	seq_printf(m, "\t%-32s = %d\n",
3914 		   "Network Type", rtwvif->net_type);
3915 
3916 	sta_iter_data.rtwvif = rtwvif;
3917 	sta_iter_data.file = m;
3918 	rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter,
3919 				&sta_iter_data);
3920 }
3921 
3922 #define case_WLINK(src) \
3923 	case COEX_WLINK_##src: return #src
3924 
3925 static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)
3926 {
3927 	switch (coex_wl_link_mode) {
3928 	case_WLINK(2G1PORT);
3929 	case_WLINK(5G);
3930 	case_WLINK(2GFREE);
3931 	default:
3932 		return "Unknown";
3933 	}
3934 }
3935 
3936 void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
3937 {
3938 	const struct rtw_chip_info *chip = rtwdev->chip;
3939 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
3940 	struct rtw_coex *coex = &rtwdev->coex;
3941 	struct rtw_coex_stat *coex_stat = &coex->stat;
3942 	struct rtw_coex_dm *coex_dm = &coex->dm;
3943 	struct rtw_hal *hal = &rtwdev->hal;
3944 	struct rtw_efuse *efuse = &rtwdev->efuse;
3945 	struct rtw_fw_state *fw = &rtwdev->fw;
3946 	struct rtw_coex_vif_stat_iter_data vif_iter_data;
3947 	u8 reason = coex_dm->reason;
3948 	u8 sys_lte;
3949 	u16 score_board_WB, score_board_BW;
3950 	u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
3951 	u32 lte_coex = 0, bt_coex = 0;
3952 	int i;
3953 
3954 	score_board_BW = rtw_coex_read_scbd(rtwdev);
3955 	score_board_WB = coex_stat->score_board;
3956 	wl_reg_6c0 = rtw_read32(rtwdev, REG_BT_COEX_TABLE0);
3957 	wl_reg_6c4 = rtw_read32(rtwdev, REG_BT_COEX_TABLE1);
3958 	wl_reg_6c8 = rtw_read32(rtwdev, REG_BT_COEX_BRK_TABLE);
3959 	wl_reg_6cc = rtw_read32(rtwdev, REG_BT_COEX_TABLE_H);
3960 	wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL);
3961 
3962 	sys_lte = rtw_read8(rtwdev, 0x73);
3963 	if (rtwdev->chip->ltecoex_addr) {
3964 		lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
3965 		bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
3966 	}
3967 
3968 	if (!coex_stat->wl_under_ips &&
3969 	    (!coex_stat->wl_under_lps || coex_stat->wl_force_lps_ctrl) &&
3970 	    !coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
3971 		rtw_coex_get_bt_supported_version(rtwdev,
3972 				&coex_stat->bt_supported_version);
3973 		rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);
3974 		rtw_coex_get_bt_supported_feature(rtwdev,
3975 				&coex_stat->bt_supported_feature);
3976 		rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae);
3977 		rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac);
3978 
3979 		if (coex_stat->patch_ver != 0)
3980 			coex_stat->bt_mailbox_reply = true;
3981 	}
3982 
3983 	rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
3984 	seq_printf(m, "**********************************************\n");
3985 	seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);
3986 	seq_printf(m, "**********************************************\n");
3987 
3988 	if (coex->manual_control) {
3989 		seq_puts(m, "============[Under Manual Control]============\n");
3990 		seq_puts(m, "==========================================\n");
3991 
3992 	} else if (coex->stop_dm) {
3993 		seq_puts(m, "============[Coex is STOPPED]============\n");
3994 		seq_puts(m, "==========================================\n");
3995 
3996 	} else if (coex->freeze) {
3997 		seq_puts(m, "============[coex_freeze]============\n");
3998 		seq_puts(m, "==========================================\n");
3999 	}
4000 
4001 	seq_printf(m, "%-40s = %s/ %d\n",
4002 		   "Mech/ RFE",
4003 		   efuse->share_ant ? "Shared" : "Non-Shared",
4004 		   efuse->rfe_option);
4005 	seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",
4006 		   "Coex Ver/ BT Dez/ BT Rpt",
4007 		   chip->coex_para_ver, chip->bt_desired_ver,
4008 		   coex_stat->bt_supported_version,
4009 		   coex_stat->bt_disabled ? "(BT disabled)" :
4010 		   coex_stat->bt_supported_version >= chip->bt_desired_ver ?
4011 		   "(Match)" : "(Mismatch)");
4012 	seq_printf(m, "%-40s = %s/ %u/ %d\n",
4013 		   "Role/ RoleSwCnt/ IgnWL/ Feature",
4014 		   coex_stat->bt_slave ? "Slave" : "Master",
4015 		   coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],
4016 		   coex_dm->ignore_wl_act);
4017 	seq_printf(m, "%-40s = %u.%u/ 0x%x/ 0x%x/ %c\n",
4018 		   "WL FW/ BT FW/ BT FW Desired/ KT",
4019 		   fw->version, fw->sub_version,
4020 		   coex_stat->patch_ver,
4021 		   chip->wl_fw_desired_ver, coex_stat->kt_ver + 65);
4022 	seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
4023 		   "AFH Map",
4024 		   coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],
4025 		   coex_dm->wl_ch_info[2], hal->current_channel);
4026 
4027 	rtw_debugfs_get_simple_phy_info(m);
4028 	seq_printf(m, "**********************************************\n");
4029 	seq_printf(m, "\t\tBT Status\n");
4030 	seq_printf(m, "**********************************************\n");
4031 	seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n",
4032 		   "BT status/ rssi/ retry/ pop",
4033 		   coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" :
4034 		   coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy",
4035 		   coex_stat->bt_rssi - 100,
4036 		   coex_stat->cnt_bt[COEX_CNT_BT_RETRY],
4037 		   coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]);
4038 	seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n",
4039 		   "Profiles",
4040 		   coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ?
4041 					       "A2DP sink," : "A2DP,") : "",
4042 		   coex_stat->bt_hfp_exist ? "HFP," : "",
4043 		   coex_stat->bt_hid_exist ?
4044 		   (coex_stat->bt_ble_exist ? "HID(RCU)," :
4045 		    coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :
4046 		    coex_stat->bt_ble_hid_exist ? "HID(BLE)" :
4047 		    "HID(2/18),") : "",
4048 		   coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?
4049 		   "OPP," : "PAN," : "",
4050 		   coex_stat->bt_ble_voice ? "Voice," : "",
4051 		   coex_stat->bt_multi_link);
4052 	seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n",
4053 		   "Reinit/ Relink/ IgnWl/ Feature",
4054 		   coex_stat->cnt_bt[COEX_CNT_BT_REINIT],
4055 		   coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK],
4056 		   coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT],
4057 		   coex_stat->bt_supported_feature);
4058 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
4059 		   "Page/ Inq/ iqk/ iqk fail",
4060 		   coex_stat->cnt_bt[COEX_CNT_BT_PAGE],
4061 		   coex_stat->cnt_bt[COEX_CNT_BT_INQ],
4062 		   coex_stat->cnt_bt[COEX_CNT_BT_IQK],
4063 		   coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]);
4064 	seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",
4065 		   "0xae/ 0xac/ score board (W->B)/ (B->W)",
4066 		   coex_stat->bt_reg_vendor_ae,
4067 		   coex_stat->bt_reg_vendor_ac,
4068 		   score_board_WB, score_board_BW);
4069 	seq_printf(m, "%-40s = %u/%u, %u/%u\n",
4070 		   "Hi-Pri TX/RX, Lo-Pri TX/RX",
4071 		   coex_stat->hi_pri_tx, coex_stat->hi_pri_rx,
4072 		   coex_stat->lo_pri_tx, coex_stat->lo_pri_rx);
4073 	for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)
4074 		seq_printf(m, "%-40s = %7ph\n",
4075 			   rtw_coex_get_bt_info_src_string(i),
4076 			   coex_stat->bt_info_c2h[i]);
4077 
4078 	seq_printf(m, "**********************************************\n");
4079 	seq_printf(m, "\t\tWiFi Status\n");
4080 	seq_printf(m, "**********************************************\n");
4081 	seq_printf(m, "%-40s = %d\n",
4082 		   "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags));
4083 	seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",
4084 		   "G_busy/ TX/ RX",
4085 		   coex_stat->wl_gl_busy,
4086 		   rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
4087 	seq_printf(m, "%-40s = %u/ %u/ %u\n",
4088 		   "IPS/ Low Power/ PS mode",
4089 		   !test_bit(RTW_FLAG_POWERON, rtwdev->flags),
4090 		   test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
4091 		   rtwdev->lps_conf.mode);
4092 
4093 	vif_iter_data.rtwdev = rtwdev;
4094 	vif_iter_data.file = m;
4095 	rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);
4096 
4097 	if (coex->manual_control) {
4098 		seq_printf(m, "**********************************************\n");
4099 		seq_printf(m, "\t\tMechanism (Under Manual)\n");
4100 		seq_printf(m, "**********************************************\n");
4101 		seq_printf(m, "%-40s = %5ph (%d)\n",
4102 			   "TDMA Now",
4103 			   coex_dm->fw_tdma_para,
4104 			   rtw_coex_get_tdma_index(rtwdev,
4105 						   &coex_dm->fw_tdma_para[0]));
4106 	} else {
4107 		seq_printf(m, "**********************************************\n");
4108 		seq_printf(m, "\t\tMechanism\n");
4109 		seq_printf(m, "**********************************************\n");
4110 		seq_printf(m, "%-40s = %5ph (case-%d)\n",
4111 			   "TDMA",
4112 			   coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
4113 	}
4114 	seq_printf(m, "%-40s = %s/ %s/ %d\n",
4115 		   "Coex Mode/Free Run/Timer base",
4116 		   rtw_coex_get_wl_coex_mode(coex_stat->wl_coex_mode),
4117 		   coex->freerun ? "Yes" : "No",
4118 		   coex_stat->tdma_timer_base);
4119 	seq_printf(m, "%-40s = %d(%d)/ 0x%08x/ 0x%08x/ 0x%08x\n",
4120 		   "Table/ 0x6c0/ 0x6c4/ 0x6c8",
4121 		   coex_dm->cur_table,
4122 		   rtw_coex_get_table_index(rtwdev, wl_reg_6c0, wl_reg_6c4),
4123 		   wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
4124 	seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ %d/ reason (%s)\n",
4125 		   "0x778/ 0x6cc/ Run Count/ Reason",
4126 		   wl_reg_778, wl_reg_6cc,
4127 		   coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN],
4128 		   rtw_coex_get_reason_string(reason));
4129 	seq_printf(m, "%-40s = %3ph\n",
4130 		   "AFH Map to BT",
4131 		   coex_dm->wl_ch_info);
4132 	seq_printf(m, "%-40s = %s/ %d\n",
4133 		   "AntDiv/ BtCtrlLPS/ g_busy",
4134 		   coex_stat->wl_force_lps_ctrl ? "On" : "Off",
4135 		   coex_stat->wl_gl_busy);
4136 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",
4137 		   "Null All/ Retry/ Ack/ BT Empty/ BT Late",
4138 		   coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],
4139 		   coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4],
4140 		   coex_stat->wl_fw_dbg_info[5]);
4141 	seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n",
4142 		   "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",
4143 		   coex_stat->wl_fw_dbg_info[6],
4144 		   coex_stat->wl_fw_dbg_info[7],
4145 		   coex_stat->wl_slot_extend ? "Yes" : "No",
4146 		   coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);
4147 	seq_printf(m, "%-40s = %d/ %d/ %s/ %d\n",
4148 		   "WL_TxPw/ BT_TxPw/ WL_Rx/ BT_LNA_Lvl",
4149 		   coex_dm->cur_wl_pwr_lvl,
4150 		   coex_dm->cur_bt_pwr_lvl,
4151 		   coex_dm->cur_wl_rx_low_gain_en ? "On" : "Off",
4152 		   coex_dm->cur_bt_lna_lvl);
4153 
4154 	seq_printf(m, "**********************************************\n");
4155 	seq_printf(m, "\t\tHW setting\n");
4156 	seq_printf(m, "**********************************************\n");
4157 	seq_printf(m, "%-40s = %s/ %s\n",
4158 		   "LTE Coex/ Path Owner",
4159 		   lte_coex & BIT(7) ? "ON" : "OFF",
4160 		   sys_lte & BIT(2) ? "WL" : "BT");
4161 	seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",
4162 		   "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",
4163 		   lte_coex & BIT(12) ? "SW" : "HW",
4164 		   lte_coex & BIT(8) ? "SW" : "HW",
4165 		   lte_coex & BIT(14) ? "SW" : "HW",
4166 		   lte_coex & BIT(10) ? "SW" : "HW",
4167 		   sys_lte & BIT(3) ? "On" : "Off");
4168 	seq_printf(m, "%-40s = %lu/ %lu\n",
4169 		   "GNT_WL/ GNT_BT",
4170 		   (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3);
4171 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
4172 		   "CRC OK CCK/ OFDM/ HT/ VHT",
4173 		   dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
4174 		   dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
4175 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
4176 		   "CRC ERR CCK/ OFDM/ HT/ VHT",
4177 		   dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
4178 		   dm_info->ht_err_cnt, dm_info->vht_err_cnt);
4179 	seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n",
4180 		   "HiPr/ Locking/ Locked/ Noisy",
4181 		   coex_stat->wl_hi_pri_task1 ? "Y" : "N",
4182 		   coex_stat->wl_cck_lock ? "Y" : "N",
4183 		   coex_stat->wl_cck_lock_ever ? "Y" : "N",
4184 		   coex_stat->wl_noisy_level);
4185 
4186 	rtw_coex_set_coexinfo_hw(rtwdev, m);
4187 	seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
4188 		   "EVM A/ EVM B/ SNR A/ SNR B",
4189 		   -dm_info->rx_evm_dbm[RF_PATH_A],
4190 		   -dm_info->rx_evm_dbm[RF_PATH_B],
4191 		   -dm_info->rx_snr[RF_PATH_A],
4192 		   -dm_info->rx_snr[RF_PATH_B]);
4193 	seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
4194 		   "CCK-CCA/CCK-FA/OFDM-CCA/OFDM-FA",
4195 		   dm_info->cck_cca_cnt, dm_info->cck_fa_cnt,
4196 		   dm_info->ofdm_cca_cnt, dm_info->ofdm_fa_cnt);
4197 	seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC OK CCK/11g/11n/11ac",
4198 		   dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
4199 		   dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
4200 	seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC Err CCK/11g/11n/11ac",
4201 		   dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
4202 		   dm_info->ht_err_cnt, dm_info->vht_err_cnt);
4203 
4204 }
4205 #endif /* CONFIG_RTW88_DEBUGFS */
4206