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