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