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 
12 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
13 				   u8 rssi, u8 rssi_thresh)
14 {
15 	struct rtw_chip_info *chip = rtwdev->chip;
16 	u8 tol = chip->rssi_tolerance;
17 	u8 next_state;
18 
19 	if (pre_state == COEX_RSSI_STATE_LOW ||
20 	    pre_state == COEX_RSSI_STATE_STAY_LOW) {
21 		if (rssi >= (rssi_thresh + tol))
22 			next_state = COEX_RSSI_STATE_HIGH;
23 		else
24 			next_state = COEX_RSSI_STATE_STAY_LOW;
25 	} else {
26 		if (rssi < rssi_thresh)
27 			next_state = COEX_RSSI_STATE_LOW;
28 		else
29 			next_state = COEX_RSSI_STATE_STAY_HIGH;
30 	}
31 
32 	return next_state;
33 }
34 
35 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
36 				bool tx_limit_en, bool ampdu_limit_en)
37 {
38 	struct rtw_chip_info *chip = rtwdev->chip;
39 	struct rtw_coex *coex = &rtwdev->coex;
40 	struct rtw_coex_stat *coex_stat = &coex->stat;
41 	bool wifi_under_b_mode = false;
42 
43 	if (!chip->scbd_support)
44 		return;
45 
46 	/* force max tx retry limit = 8 */
47 	if (coex_stat->wl_tx_limit_en == tx_limit_en &&
48 	    coex_stat->wl_ampdu_limit_en == ampdu_limit_en)
49 		return;
50 
51 	if (!coex_stat->wl_tx_limit_en) {
52 		coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC);
53 		coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH);
54 		coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT);
55 	}
56 
57 	if (!coex_stat->wl_ampdu_limit_en)
58 		coex_stat->ampdu_max_time =
59 				rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);
60 
61 	coex_stat->wl_tx_limit_en = tx_limit_en;
62 	coex_stat->wl_ampdu_limit_en = ampdu_limit_en;
63 
64 	if (tx_limit_en) {
65 		/* set BT polluted packet on for tx rate adaptive,
66 		 * not including tx retry broken by PTA
67 		 */
68 		rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
69 
70 		/* set queue life time to avoid can't reach tx retry limit
71 		 * if tx is always broken by GNT_BT
72 		 */
73 		rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
74 		rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
75 
76 		/* auto rate fallback step within 8 retries */
77 		if (wifi_under_b_mode) {
78 			rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
79 			rtw_write32(rtwdev, REG_DARFRCH, 0x1010101);
80 		} else {
81 			rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
82 			rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
83 		}
84 	} else {
85 		rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
86 		rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
87 
88 		rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit);
89 		rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc);
90 		rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch);
91 	}
92 
93 	if (ampdu_limit_en)
94 		rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);
95 	else
96 		rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,
97 			   coex_stat->ampdu_max_time);
98 }
99 
100 static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
101 {
102 	struct rtw_coex *coex = &rtwdev->coex;
103 	struct rtw_coex_dm *coex_dm = &coex->dm;
104 	struct rtw_coex_stat *coex_stat = &coex->stat;
105 	bool tx_limit = false;
106 	bool tx_agg_ctrl = false;
107 
108 	if (coex->under_5g ||
109 	    coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
110 		/* no need to limit tx */
111 	} else {
112 		tx_limit = true;
113 		if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist ||
114 		    coex_stat->bt_hid_pair_num > 0)
115 			tx_agg_ctrl = true;
116 	}
117 
118 	rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
119 }
120 
121 static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
122 {
123 	struct rtw_coex *coex = &rtwdev->coex;
124 	struct rtw_coex_stat *coex_stat = &coex->stat;
125 	u8 para[6] = {0};
126 
127 	if (coex->stop_dm)
128 		return;
129 
130 	para[0] = COEX_H2C69_WL_LEAKAP;
131 
132 	if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {
133 		para[1] = PARA1_H2C69_DIS_5MS; /* disable 5ms extend */
134 		rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
135 		coex_stat->wl_slot_extend = false;
136 		coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
137 		return;
138 	}
139 
140 	if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl &&
141 	    !coex_stat->wl_cck_lock_ever) {
142 		if (coex_stat->wl_fw_dbg_info[7] <= 5)
143 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++;
144 		else
145 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
146 
147 		if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {
148 			para[1] = 0x1; /* disable 5ms extend */
149 			rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
150 			coex_stat->wl_slot_extend = false;
151 			coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
152 		}
153 	} else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {
154 		para[1] = 0x0; /* enable 5ms extend */
155 		rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
156 		coex_stat->wl_slot_extend = true;
157 	}
158 }
159 
160 static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
161 {
162 	struct rtw_coex *coex = &rtwdev->coex;
163 	struct rtw_coex_stat *coex_stat = &coex->stat;
164 
165 	/* TODO: wait for rx_rate_change_notify implement */
166 	coex_stat->wl_cck_lock = false;
167 	coex_stat->wl_cck_lock_pre = false;
168 	coex_stat->wl_cck_lock_ever = false;
169 }
170 
171 static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
172 {
173 	struct rtw_coex *coex = &rtwdev->coex;
174 	struct rtw_coex_stat *coex_stat = &coex->stat;
175 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
176 	u32 cnt_cck;
177 
178 	/* wifi noisy environment identification */
179 	cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
180 
181 	if (!coex_stat->wl_gl_busy) {
182 		if (cnt_cck > 250) {
183 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
184 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
185 
186 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) {
187 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
188 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
189 			}
190 		} else if (cnt_cck < 100) {
191 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5)
192 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++;
193 
194 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) {
195 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
196 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
197 			}
198 		} else {
199 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)
200 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;
201 
202 			if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) {
203 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
204 				coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
205 			}
206 		}
207 
208 		if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5)
209 			coex_stat->wl_noisy_level = 2;
210 		else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5)
211 			coex_stat->wl_noisy_level = 1;
212 		else
213 			coex_stat->wl_noisy_level = 0;
214 	}
215 }
216 
217 static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
218 {
219 	struct rtw_coex *coex = &rtwdev->coex;
220 	struct rtw_coex_stat *coex_stat = &coex->stat;
221 	u8 para[2] = {0};
222 
223 	if (coex_stat->tdma_timer_base == type)
224 		return;
225 
226 	coex_stat->tdma_timer_base = type;
227 
228 	para[0] = COEX_H2C69_TDMA_SLOT;
229 
230 	if (type == 3) /* 4-slot  */
231 		para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */
232 	else /* 2-slot  */
233 		para[1] = PARA1_H2C69_TDMA_2SLOT;
234 
235 	rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
236 
237 	/* no 5ms_wl_slot_extend for 4-slot mode  */
238 	if (coex_stat->tdma_timer_base == 3)
239 		rtw_coex_wl_ccklock_action(rtwdev);
240 }
241 
242 static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
243 				     u8 data)
244 {
245 	u32 addr;
246 
247 	addr = REG_BT_COEX_TABLE_H + (bitmap / 8);
248 	bitmap = bitmap % 8;
249 
250 	rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);
251 }
252 
253 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
254 {
255 	struct rtw_chip_info *chip = rtwdev->chip;
256 	struct rtw_coex *coex = &rtwdev->coex;
257 	struct rtw_coex_stat *coex_stat = &coex->stat;
258 	u16 val = 0x2;
259 
260 	if (!chip->scbd_support)
261 		return;
262 
263 	val |= coex_stat->score_board;
264 
265 	/* for 8822b, scbd[10] is CQDDR on
266 	 * for 8822c, scbd[10] is no fix 2M
267 	 */
268 	if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {
269 		if (set)
270 			val &= ~COEX_SCBD_FIX2M;
271 		else
272 			val |= COEX_SCBD_FIX2M;
273 	} else {
274 		if (set)
275 			val |= bitpos;
276 		else
277 			val &= ~bitpos;
278 	}
279 
280 	if (val != coex_stat->score_board) {
281 		coex_stat->score_board = val;
282 		val |= BIT_BT_INT_EN;
283 		rtw_write16(rtwdev, REG_WIFI_BT_INFO, val);
284 	}
285 }
286 EXPORT_SYMBOL(rtw_coex_write_scbd);
287 
288 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
289 {
290 	struct rtw_chip_info *chip = rtwdev->chip;
291 
292 	if (!chip->scbd_support)
293 		return 0;
294 
295 	return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);
296 }
297 
298 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
299 {
300 	struct rtw_chip_info *chip = rtwdev->chip;
301 	struct rtw_coex *coex = &rtwdev->coex;
302 	struct rtw_coex_stat *coex_stat = &coex->stat;
303 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
304 	u8 cnt = 0;
305 	u32 wait_cnt;
306 	bool btk, wlk;
307 
308 	if (coex_rfe->wlg_at_btg && chip->scbd_support &&
309 	    coex_stat->bt_iqk_state != 0xff) {
310 		wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
311 		do {
312 			/* BT RFK */
313 			btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);
314 
315 			/* WL RFK */
316 			wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);
317 
318 			if (!btk && !wlk)
319 				break;
320 
321 			mdelay(COEX_MIN_DELAY);
322 		} while (++cnt < wait_cnt);
323 
324 		if (cnt >= wait_cnt)
325 			coex_stat->bt_iqk_state = 0xff;
326 	}
327 }
328 
329 static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
330 {
331 	struct rtw_coex *coex = &rtwdev->coex;
332 	struct rtw_coex_stat *coex_stat = &coex->stat;
333 
334 	if (coex_stat->bt_disabled)
335 		return;
336 
337 	rtw_fw_query_bt_info(rtwdev);
338 }
339 
340 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
341 {
342 	struct rtw_chip_info *chip = rtwdev->chip;
343 	struct rtw_coex *coex = &rtwdev->coex;
344 	struct rtw_coex_stat *coex_stat = &coex->stat;
345 	struct rtw_coex_dm *coex_dm = &coex->dm;
346 	bool bt_disabled = false;
347 	u16 score_board;
348 
349 	if (chip->scbd_support) {
350 		score_board = rtw_coex_read_scbd(rtwdev);
351 		bt_disabled = !(score_board & COEX_SCBD_ONOFF);
352 	}
353 
354 	if (coex_stat->bt_disabled != bt_disabled) {
355 		rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n",
356 			coex_stat->bt_disabled, bt_disabled);
357 
358 		coex_stat->bt_disabled = bt_disabled;
359 		coex_stat->bt_ble_scan_type = 0;
360 		coex_dm->cur_bt_lna_lvl = 0;
361 	}
362 
363 	if (!coex_stat->bt_disabled) {
364 		coex_stat->bt_reenable = true;
365 		ieee80211_queue_delayed_work(rtwdev->hw,
366 					     &coex->bt_reenable_work, 15 * HZ);
367 	} else {
368 		coex_stat->bt_mailbox_reply = false;
369 		coex_stat->bt_reenable = false;
370 	}
371 }
372 
373 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
374 {
375 	struct rtw_coex *coex = &rtwdev->coex;
376 	struct rtw_coex_stat *coex_stat = &coex->stat;
377 	struct rtw_coex_dm *coex_dm = &coex->dm;
378 	struct rtw_chip_info *chip = rtwdev->chip;
379 	struct rtw_traffic_stats *stats = &rtwdev->stats;
380 	bool is_5G = false;
381 	bool wl_busy = false;
382 	bool scan = false, link = false;
383 	int i;
384 	u8 rssi_state;
385 	u8 rssi_step;
386 	u8 rssi;
387 
388 	scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);
389 	coex_stat->wl_connected = !!rtwdev->sta_cnt;
390 
391 	wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
392 	if (wl_busy != coex_stat->wl_gl_busy) {
393 		if (wl_busy)
394 			coex_stat->wl_gl_busy = true;
395 		else
396 			ieee80211_queue_delayed_work(rtwdev->hw,
397 						     &coex->wl_remain_work,
398 						     12 * HZ);
399 	}
400 
401 	if (stats->tx_throughput > stats->rx_throughput)
402 		coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
403 	else
404 		coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;
405 
406 	if (scan || link || reason == COEX_RSN_2GCONSTART ||
407 	    reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)
408 		coex_stat->wl_linkscan_proc = true;
409 	else
410 		coex_stat->wl_linkscan_proc = false;
411 
412 	rtw_coex_wl_noisy_detect(rtwdev);
413 
414 	for (i = 0; i < 4; i++) {
415 		rssi_state = coex_dm->wl_rssi_state[i];
416 		rssi_step = chip->wl_rssi_step[i];
417 		rssi = rtwdev->dm_info.min_rssi;
418 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
419 						      rssi, rssi_step);
420 		coex_dm->wl_rssi_state[i] = rssi_state;
421 	}
422 
423 	switch (reason) {
424 	case COEX_RSN_5GSCANSTART:
425 	case COEX_RSN_5GSWITCHBAND:
426 	case COEX_RSN_5GCONSTART:
427 
428 		is_5G = true;
429 		break;
430 	case COEX_RSN_2GSCANSTART:
431 	case COEX_RSN_2GSWITCHBAND:
432 	case COEX_RSN_2GCONSTART:
433 
434 		is_5G = false;
435 		break;
436 	default:
437 		if (rtwdev->hal.current_band_type == RTW_BAND_5G)
438 			is_5G = true;
439 		else
440 			is_5G = false;
441 		break;
442 	}
443 
444 	coex->under_5g = is_5G;
445 }
446 
447 static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)
448 {
449 	struct rtw_c2h_cmd *c2h;
450 	u32 pkt_offset;
451 
452 	pkt_offset = *((u32 *)resp->cb);
453 	c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);
454 
455 	return c2h->payload;
456 }
457 
458 void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)
459 {
460 	struct rtw_coex *coex = &rtwdev->coex;
461 	u8 *payload = get_payload_from_coex_resp(skb);
462 
463 	if (payload[0] != COEX_RESP_ACK_BY_WL_FW)
464 		return;
465 
466 	skb_queue_tail(&coex->queue, skb);
467 	wake_up(&coex->wait);
468 }
469 
470 static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
471 					     struct rtw_coex_info_req *req)
472 {
473 	struct rtw_coex *coex = &rtwdev->coex;
474 	struct sk_buff *skb_resp = NULL;
475 
476 	mutex_lock(&coex->mutex);
477 
478 	rtw_fw_query_bt_mp_info(rtwdev, req);
479 
480 	if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
481 				COEX_REQUEST_TIMEOUT)) {
482 		rtw_err(rtwdev, "coex request time out\n");
483 		goto out;
484 	}
485 
486 	skb_resp = skb_dequeue(&coex->queue);
487 	if (!skb_resp) {
488 		rtw_err(rtwdev, "failed to get coex info response\n");
489 		goto out;
490 	}
491 
492 out:
493 	mutex_unlock(&coex->mutex);
494 	return skb_resp;
495 }
496 
497 static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
498 {
499 	struct rtw_coex_info_req req = {0};
500 	struct sk_buff *skb;
501 	u8 *payload;
502 	bool ret = false;
503 
504 	req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
505 	skb = rtw_coex_info_request(rtwdev, &req);
506 	if (!skb)
507 		goto out;
508 
509 	payload = get_payload_from_coex_resp(skb);
510 	*scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
511 	dev_kfree_skb_any(skb);
512 	ret = true;
513 
514 out:
515 	return ret;
516 }
517 
518 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
519 					     u8 lna_constrain_level)
520 {
521 	struct rtw_coex_info_req req = {0};
522 	struct sk_buff *skb;
523 	bool ret = false;
524 
525 	req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
526 	req.para1 = lna_constrain_level;
527 	skb = rtw_coex_info_request(rtwdev, &req);
528 	if (!skb)
529 		goto out;
530 
531 	dev_kfree_skb_any(skb);
532 	ret = true;
533 
534 out:
535 	return ret;
536 }
537 
538 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
539 {
540 	struct rtw_coex *coex = &rtwdev->coex;
541 	struct rtw_coex_stat *coex_stat = &coex->stat;
542 	struct rtw_coex_dm *coex_dm = &coex->dm;
543 	struct rtw_chip_info *chip = rtwdev->chip;
544 	u8 i;
545 	u8 rssi_state;
546 	u8 rssi_step;
547 	u8 rssi;
548 
549 	/* update wl/bt rssi by btinfo */
550 	for (i = 0; i < COEX_RSSI_STEP; i++) {
551 		rssi_state = coex_dm->bt_rssi_state[i];
552 		rssi_step = chip->bt_rssi_step[i];
553 		rssi = coex_stat->bt_rssi;
554 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
555 						      rssi, rssi_step);
556 		coex_dm->bt_rssi_state[i] = rssi_state;
557 	}
558 
559 	for (i = 0; i < COEX_RSSI_STEP; i++) {
560 		rssi_state = coex_dm->wl_rssi_state[i];
561 		rssi_step = chip->wl_rssi_step[i];
562 		rssi = rtwdev->dm_info.min_rssi;
563 		rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
564 						      rssi, rssi_step);
565 		coex_dm->wl_rssi_state[i] = rssi_state;
566 	}
567 
568 	if (coex_stat->bt_ble_scan_en &&
569 	    coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
570 		u8 scan_type;
571 
572 		if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {
573 			coex_stat->bt_ble_scan_type = scan_type;
574 			if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)
575 				coex_stat->bt_init_scan = true;
576 			else
577 				coex_stat->bt_init_scan = false;
578 		}
579 	}
580 
581 	coex_stat->bt_profile_num = 0;
582 
583 	/* set link exist status */
584 	if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
585 		coex_stat->bt_link_exist = false;
586 		coex_stat->bt_pan_exist = false;
587 		coex_stat->bt_a2dp_exist = false;
588 		coex_stat->bt_hid_exist = false;
589 		coex_stat->bt_hfp_exist = false;
590 	} else {
591 		/* connection exists */
592 		coex_stat->bt_link_exist = true;
593 		if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {
594 			coex_stat->bt_pan_exist = true;
595 			coex_stat->bt_profile_num++;
596 		} else {
597 			coex_stat->bt_pan_exist = false;
598 		}
599 
600 		if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {
601 			coex_stat->bt_a2dp_exist = true;
602 			coex_stat->bt_profile_num++;
603 		} else {
604 			coex_stat->bt_a2dp_exist = false;
605 		}
606 
607 		if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {
608 			coex_stat->bt_hid_exist = true;
609 			coex_stat->bt_profile_num++;
610 		} else {
611 			coex_stat->bt_hid_exist = false;
612 		}
613 
614 		if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {
615 			coex_stat->bt_hfp_exist = true;
616 			coex_stat->bt_profile_num++;
617 		} else {
618 			coex_stat->bt_hfp_exist = false;
619 		}
620 	}
621 
622 	if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {
623 		coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
624 	} else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
625 		coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
626 	} else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
627 		coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
628 	} else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
629 		   (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {
630 		if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)
631 			coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;
632 		else
633 			coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;
634 	} else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {
635 		coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;
636 	} else {
637 		coex_dm->bt_status = COEX_BTSTATUS_MAX;
638 	}
639 
640 	coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
641 
642 	rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status);
643 }
644 
645 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
646 {
647 	struct rtw_chip_info *chip = rtwdev->chip;
648 	struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
649 	struct rtw_efuse *efuse = &rtwdev->efuse;
650 	u8 link = 0;
651 	u8 center_chan = 0;
652 	u8 bw;
653 	int i;
654 
655 	bw = rtwdev->hal.current_band_width;
656 
657 	if (type != COEX_MEDIA_DISCONNECT)
658 		center_chan = rtwdev->hal.current_channel;
659 
660 	if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) {
661 		link = 0;
662 	} else if (center_chan <= 14) {
663 		link = 0x1;
664 
665 		if (bw == RTW_CHANNEL_WIDTH_40)
666 			bw = chip->bt_afh_span_bw40;
667 		else
668 			bw = chip->bt_afh_span_bw20;
669 	} else if (chip->afh_5g_num > 1) {
670 		for (i = 0; i < chip->afh_5g_num; i++) {
671 			if (center_chan == chip->afh_5g[i].wl_5g_ch) {
672 				link = 0x3;
673 				center_chan = chip->afh_5g[i].bt_skip_ch;
674 				bw = chip->afh_5g[i].bt_skip_span;
675 				break;
676 			}
677 		}
678 	}
679 
680 	coex_dm->wl_ch_info[0] = link;
681 	coex_dm->wl_ch_info[1] = center_chan;
682 	coex_dm->wl_ch_info[2] = bw;
683 
684 	rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
685 }
686 
687 static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
688 {
689 	struct rtw_coex *coex = &rtwdev->coex;
690 	struct rtw_coex_dm *coex_dm = &coex->dm;
691 
692 	if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)
693 		return;
694 
695 	coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;
696 
697 	rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);
698 }
699 
700 static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
701 {
702 	struct rtw_coex *coex = &rtwdev->coex;
703 	struct rtw_coex_dm *coex_dm = &coex->dm;
704 
705 	if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)
706 		return;
707 
708 	coex_dm->cur_bt_lna_lvl = bt_lna_lvl;
709 
710 	/* notify BT rx gain table changed */
711 	if (bt_lna_lvl < 7) {
712 		rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);
713 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);
714 	} else {
715 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
716 	}
717 }
718 
719 static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
720 				 struct coex_rf_para para)
721 {
722 	struct rtw_coex *coex = &rtwdev->coex;
723 	struct rtw_coex_stat *coex_stat = &coex->stat;
724 	u8 offset = 0;
725 
726 	if (coex->freerun && coex_stat->wl_noisy_level <= 1)
727 		offset = 3;
728 
729 	rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
730 	rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);
731 	rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);
732 	rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
733 }
734 
735 u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
736 {
737 	u32 val;
738 
739 	if (!ltecoex_read_reg(rtwdev, addr, &val)) {
740 		rtw_err(rtwdev, "failed to read indirect register\n");
741 		return 0;
742 	}
743 
744 	return val;
745 }
746 EXPORT_SYMBOL(rtw_coex_read_indirect_reg);
747 
748 void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
749 				 u32 mask, u32 val)
750 {
751 	u32 shift = __ffs(mask);
752 	u32 tmp;
753 
754 	tmp = rtw_coex_read_indirect_reg(rtwdev, addr);
755 	tmp = (tmp & (~mask)) | ((val << shift) & mask);
756 
757 	if (!ltecoex_reg_write(rtwdev, addr, tmp))
758 		rtw_err(rtwdev, "failed to write indirect register\n");
759 }
760 EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
761 
762 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
763 {
764 	struct rtw_chip_info *chip = rtwdev->chip;
765 	const struct rtw_hw_reg *btg_reg = chip->btg_reg;
766 
767 	if (wifi_control) {
768 		rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
769 		if (btg_reg)
770 			rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
771 	} else {
772 		rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
773 		if (btg_reg)
774 			rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
775 	}
776 }
777 
778 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
779 {
780 	rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state);
781 	rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state);
782 }
783 
784 static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
785 {
786 	rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state);
787 	rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state);
788 }
789 
790 static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1)
791 {
792 #define DEF_BRK_TABLE_VAL	0xf0ffffff
793 	rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
794 	rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
795 	rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
796 }
797 
798 static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type)
799 {
800 	struct rtw_coex *coex = &rtwdev->coex;
801 	struct rtw_coex_dm *coex_dm = &coex->dm;
802 	struct rtw_chip_info *chip = rtwdev->chip;
803 	struct rtw_efuse *efuse = &rtwdev->efuse;
804 
805 	coex_dm->cur_table = type;
806 
807 	if (efuse->share_ant) {
808 		if (type < chip->table_sant_num)
809 			rtw_coex_set_table(rtwdev,
810 					   chip->table_sant[type].bt,
811 					   chip->table_sant[type].wl);
812 	} else {
813 		type = type - 100;
814 		if (type < chip->table_nsant_num)
815 			rtw_coex_set_table(rtwdev,
816 					   chip->table_nsant[type].bt,
817 					   chip->table_nsant[type].wl);
818 	}
819 }
820 
821 static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
822 {
823 	struct rtw_coex *coex = &rtwdev->coex;
824 
825 	if (coex->stop_dm)
826 		return;
827 
828 	rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
829 }
830 
831 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
832 				      u8 lps_val, u8 rpwm_val)
833 {
834 	struct rtw_coex *coex = &rtwdev->coex;
835 	struct rtw_coex_stat *coex_stat = &coex->stat;
836 	u8 lps_mode = 0x0;
837 
838 	lps_mode = rtwdev->lps_conf.mode;
839 
840 	switch (ps_type) {
841 	case COEX_PS_WIFI_NATIVE:
842 		/* recover to original 32k low power setting */
843 		coex_stat->wl_force_lps_ctrl = false;
844 
845 		rtw_leave_lps(rtwdev);
846 		break;
847 	case COEX_PS_LPS_OFF:
848 		coex_stat->wl_force_lps_ctrl = true;
849 		if (lps_mode)
850 			rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0);
851 
852 		rtw_leave_lps(rtwdev);
853 		break;
854 	default:
855 		break;
856 	}
857 }
858 
859 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
860 			      u8 byte3, u8 byte4, u8 byte5)
861 {
862 	struct rtw_coex *coex = &rtwdev->coex;
863 	struct rtw_coex_dm *coex_dm = &coex->dm;
864 	struct rtw_chip_info *chip = rtwdev->chip;
865 	u8 ps_type = COEX_PS_WIFI_NATIVE;
866 	bool ap_enable = false;
867 
868 	if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
869 		byte1 &= ~BIT(4);
870 		byte1 |= BIT(5);
871 
872 		byte5 |= BIT(5);
873 		byte5 &= ~BIT(6);
874 
875 		ps_type = COEX_PS_WIFI_NATIVE;
876 		rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
877 	} else if (byte1 & BIT(4) && !(byte1 & BIT(5))) {
878 		if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
879 			ps_type = COEX_PS_LPS_OFF;
880 		else
881 			ps_type = COEX_PS_LPS_ON;
882 		rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
883 	} else {
884 		ps_type = COEX_PS_WIFI_NATIVE;
885 		rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
886 	}
887 
888 	coex_dm->ps_tdma_para[0] = byte1;
889 	coex_dm->ps_tdma_para[1] = byte2;
890 	coex_dm->ps_tdma_para[2] = byte3;
891 	coex_dm->ps_tdma_para[3] = byte4;
892 	coex_dm->ps_tdma_para[4] = byte5;
893 
894 	rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
895 }
896 
897 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
898 {
899 	struct rtw_coex *coex = &rtwdev->coex;
900 	struct rtw_coex_dm *coex_dm = &coex->dm;
901 	struct rtw_coex_stat *coex_stat = &coex->stat;
902 	struct rtw_chip_info *chip = rtwdev->chip;
903 	struct rtw_efuse *efuse = &rtwdev->efuse;
904 	u8 n, type;
905 	bool turn_on;
906 	bool wl_busy = false;
907 
908 	if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */
909 		rtw_coex_tdma_timer_base(rtwdev, 3);
910 	else
911 		rtw_coex_tdma_timer_base(rtwdev, 0);
912 
913 	type = (u8)(tcase & 0xff);
914 
915 	turn_on = (type == 0 || type == 100) ? false : true;
916 
917 	if (!force) {
918 		if (turn_on == coex_dm->cur_ps_tdma_on &&
919 		    type == coex_dm->cur_ps_tdma) {
920 			return;
921 		}
922 	}
923 
924 	/* enable TBTT interrupt */
925 	if (turn_on)
926 		rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
927 
928 	wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
929 
930 	if ((coex_stat->bt_a2dp_exist &&
931 	     (coex_stat->bt_inq_remain || coex_stat->bt_multi_link)) ||
932 	    !wl_busy)
933 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);
934 	else
935 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
936 
937 	if (efuse->share_ant) {
938 		if (type < chip->tdma_sant_num)
939 			rtw_coex_set_tdma(rtwdev,
940 					  chip->tdma_sant[type].para[0],
941 					  chip->tdma_sant[type].para[1],
942 					  chip->tdma_sant[type].para[2],
943 					  chip->tdma_sant[type].para[3],
944 					  chip->tdma_sant[type].para[4]);
945 	} else {
946 		n = type - 100;
947 		if (n < chip->tdma_nsant_num)
948 			rtw_coex_set_tdma(rtwdev,
949 					  chip->tdma_nsant[n].para[0],
950 					  chip->tdma_nsant[n].para[1],
951 					  chip->tdma_nsant[n].para[2],
952 					  chip->tdma_nsant[n].para[3],
953 					  chip->tdma_nsant[n].para[4]);
954 	}
955 
956 	/* update pre state */
957 	coex_dm->cur_ps_tdma_on = turn_on;
958 	coex_dm->cur_ps_tdma = type;
959 
960 	rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type);
961 }
962 
963 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
964 {
965 	struct rtw_coex *coex = &rtwdev->coex;
966 	struct rtw_coex_stat *coex_stat = &coex->stat;
967 	struct rtw_coex_dm *coex_dm = &coex->dm;
968 	u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
969 	u8 pos_type = COEX_SWITCH_TO_MAX;
970 
971 	if (!force && coex_dm->cur_ant_pos_type == phase)
972 		return;
973 
974 	coex_dm->cur_ant_pos_type = phase;
975 
976 	/* avoid switch coex_ctrl_owner during BT IQK */
977 	rtw_coex_check_rfk(rtwdev);
978 
979 	switch (phase) {
980 	case COEX_SET_ANT_POWERON:
981 		/* set path control owner to BT at power-on */
982 		if (coex_stat->bt_disabled)
983 			rtw_coex_coex_ctrl_owner(rtwdev, true);
984 		else
985 			rtw_coex_coex_ctrl_owner(rtwdev, false);
986 
987 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
988 		pos_type = COEX_SWITCH_TO_BT;
989 		break;
990 	case COEX_SET_ANT_INIT:
991 		if (coex_stat->bt_disabled) {
992 			/* set GNT_BT to SW low */
993 			rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
994 
995 			/* set GNT_WL to SW high */
996 			rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
997 		} else {
998 			/* set GNT_BT to SW high */
999 			rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1000 
1001 			/* set GNT_WL to SW low */
1002 			rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);
1003 		}
1004 
1005 		/* set path control owner to wl at initial step */
1006 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1007 
1008 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1009 		pos_type = COEX_SWITCH_TO_BT;
1010 		break;
1011 	case COEX_SET_ANT_WONLY:
1012 		/* set GNT_BT to SW Low */
1013 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1014 
1015 		/* Set GNT_WL to SW high */
1016 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1017 
1018 		/* set path control owner to wl at initial step */
1019 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1020 
1021 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1022 		pos_type = COEX_SWITCH_TO_WLG;
1023 		break;
1024 	case COEX_SET_ANT_WOFF:
1025 		/* set path control owner to BT */
1026 		rtw_coex_coex_ctrl_owner(rtwdev, false);
1027 
1028 		ctrl_type = COEX_SWITCH_CTRL_BY_BT;
1029 		pos_type = COEX_SWITCH_TO_NOCARE;
1030 		break;
1031 	case COEX_SET_ANT_2G:
1032 		/* set GNT_BT to PTA */
1033 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1034 
1035 		/* set GNT_WL to PTA */
1036 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1037 
1038 		/* set path control owner to wl at runtime step */
1039 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1040 
1041 		ctrl_type = COEX_SWITCH_CTRL_BY_PTA;
1042 		pos_type = COEX_SWITCH_TO_NOCARE;
1043 		break;
1044 	case COEX_SET_ANT_5G:
1045 		/* set GNT_BT to PTA */
1046 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1047 
1048 		/* set GNT_WL to SW high */
1049 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1050 
1051 		/* set path control owner to wl at runtime step */
1052 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1053 
1054 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1055 		pos_type = COEX_SWITCH_TO_WLA;
1056 		break;
1057 	case COEX_SET_ANT_2G_FREERUN:
1058 		/* set GNT_BT to SW high */
1059 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1060 
1061 		/* Set GNT_WL to SW high */
1062 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1063 
1064 		/* set path control owner to wl at runtime step */
1065 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1066 
1067 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1068 		pos_type = COEX_SWITCH_TO_WLG_BT;
1069 		break;
1070 	case COEX_SET_ANT_2G_WLBT:
1071 		/* set GNT_BT to SW high */
1072 		rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1073 
1074 		/* Set GNT_WL to SW high */
1075 		rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1076 
1077 		/* set path control owner to wl at runtime step */
1078 		rtw_coex_coex_ctrl_owner(rtwdev, true);
1079 
1080 		ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1081 		pos_type = COEX_SWITCH_TO_WLG_BT;
1082 		break;
1083 	default:
1084 		WARN(1, "unknown phase when setting antenna path\n");
1085 		return;
1086 	}
1087 
1088 	if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX)
1089 		rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
1090 }
1091 
1092 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
1093 {
1094 	struct rtw_coex *coex = &rtwdev->coex;
1095 	struct rtw_coex_stat *coex_stat = &coex->stat;
1096 	u8 algorithm = COEX_ALGO_NOPROFILE;
1097 	u8 profile_map = 0;
1098 
1099 	if (coex_stat->bt_hfp_exist)
1100 		profile_map |= BPM_HFP;
1101 	if (coex_stat->bt_hid_exist)
1102 		profile_map |= BPM_HID;
1103 	if (coex_stat->bt_a2dp_exist)
1104 		profile_map |= BPM_A2DP;
1105 	if (coex_stat->bt_pan_exist)
1106 		profile_map |= BPM_PAN;
1107 
1108 	switch (profile_map) {
1109 	case BPM_HFP:
1110 		algorithm = COEX_ALGO_HFP;
1111 		break;
1112 	case           BPM_HID:
1113 	case BPM_HFP + BPM_HID:
1114 		algorithm = COEX_ALGO_HID;
1115 		break;
1116 	case BPM_HFP           + BPM_A2DP:
1117 	case           BPM_HID + BPM_A2DP:
1118 	case BPM_HFP + BPM_HID + BPM_A2DP:
1119 		algorithm = COEX_ALGO_A2DP_HID;
1120 		break;
1121 	case BPM_HFP                      + BPM_PAN:
1122 	case           BPM_HID            + BPM_PAN:
1123 	case BPM_HFP + BPM_HID            + BPM_PAN:
1124 		algorithm = COEX_ALGO_PAN_HID;
1125 		break;
1126 	case BPM_HFP           + BPM_A2DP + BPM_PAN:
1127 	case           BPM_HID + BPM_A2DP + BPM_PAN:
1128 	case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN:
1129 		algorithm = COEX_ALGO_A2DP_PAN_HID;
1130 		break;
1131 	case                                BPM_PAN:
1132 		algorithm = COEX_ALGO_PAN;
1133 		break;
1134 	case                     BPM_A2DP + BPM_PAN:
1135 		algorithm = COEX_ALGO_A2DP_PAN;
1136 		break;
1137 	case                     BPM_A2DP:
1138 		if (coex_stat->bt_multi_link) {
1139 			if (coex_stat->bt_hid_pair_num > 0)
1140 				algorithm = COEX_ALGO_A2DP_HID;
1141 			else
1142 				algorithm = COEX_ALGO_A2DP_PAN;
1143 		} else {
1144 			algorithm = COEX_ALGO_A2DP;
1145 		}
1146 		break;
1147 	default:
1148 		algorithm = COEX_ALGO_NOPROFILE;
1149 		break;
1150 	}
1151 
1152 	return algorithm;
1153 }
1154 
1155 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
1156 {
1157 	struct rtw_efuse *efuse = &rtwdev->efuse;
1158 	struct rtw_chip_info *chip = rtwdev->chip;
1159 	u8 table_case, tdma_case;
1160 
1161 	if (efuse->share_ant) {
1162 		/* Shared-Ant */
1163 		table_case = 2;
1164 		tdma_case = 0;
1165 	} else {
1166 		/* Non-Shared-Ant */
1167 		table_case = 100;
1168 		tdma_case = 100;
1169 	}
1170 
1171 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1172 	rtw_coex_table(rtwdev, table_case);
1173 	rtw_coex_tdma(rtwdev, false, tdma_case);
1174 }
1175 
1176 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
1177 {
1178 	struct rtw_coex *coex = &rtwdev->coex;
1179 	struct rtw_coex_stat *coex_stat = &coex->stat;
1180 	struct rtw_coex_dm *coex_dm = &coex->dm;
1181 	struct rtw_efuse *efuse = &rtwdev->efuse;
1182 	struct rtw_chip_info *chip = rtwdev->chip;
1183 	u8 level = 0;
1184 
1185 	if (efuse->share_ant)
1186 		return;
1187 
1188 	coex->freerun = true;
1189 
1190 	if (coex_stat->wl_connected)
1191 		rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
1192 
1193 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1194 
1195 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1196 
1197 	if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))
1198 		level = 2;
1199 	else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1200 		level = 3;
1201 	else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))
1202 		level = 4;
1203 	else
1204 		level = 5;
1205 
1206 	if (level > chip->wl_rf_para_num - 1)
1207 		level = chip->wl_rf_para_num - 1;
1208 
1209 	if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1210 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);
1211 	else
1212 		rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
1213 
1214 	rtw_coex_table(rtwdev, 100);
1215 	rtw_coex_tdma(rtwdev, false, 100);
1216 }
1217 
1218 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
1219 {
1220 	struct rtw_efuse *efuse = &rtwdev->efuse;
1221 	struct rtw_chip_info *chip = rtwdev->chip;
1222 	u8 table_case, tdma_case;
1223 
1224 	if (efuse->share_ant) {
1225 		/* Shared-Ant */
1226 		table_case = 2;
1227 		tdma_case = 0;
1228 	} else {
1229 		/* Non-Shared-Ant */
1230 		table_case = 100;
1231 		tdma_case = 100;
1232 	}
1233 
1234 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1235 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1236 	rtw_coex_table(rtwdev, table_case);
1237 	rtw_coex_tdma(rtwdev, false, tdma_case);
1238 }
1239 
1240 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
1241 {
1242 	struct rtw_efuse *efuse = &rtwdev->efuse;
1243 	struct rtw_chip_info *chip = rtwdev->chip;
1244 	u8 table_case, tdma_case;
1245 
1246 	if (efuse->share_ant) {
1247 		/* Shared-Ant */
1248 		table_case = 1;
1249 		tdma_case = 0;
1250 	} else {
1251 		/* Non-Shared-Ant */
1252 		table_case = 100;
1253 		tdma_case = 100;
1254 	}
1255 
1256 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1257 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1258 	rtw_coex_table(rtwdev, table_case);
1259 	rtw_coex_tdma(rtwdev, false, tdma_case);
1260 }
1261 
1262 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
1263 {
1264 	struct rtw_coex *coex = &rtwdev->coex;
1265 	struct rtw_coex_stat *coex_stat = &coex->stat;
1266 	struct rtw_coex_dm *coex_dm = &coex->dm;
1267 	struct rtw_efuse *efuse = &rtwdev->efuse;
1268 	struct rtw_chip_info *chip = rtwdev->chip;
1269 	struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1270 	u8 table_case = 0xff, tdma_case = 0xff;
1271 
1272 	if (coex_rfe->ant_switch_with_bt &&
1273 	    coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1274 		if (efuse->share_ant &&
1275 		    COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) {
1276 			table_case = 0;
1277 			tdma_case = 0;
1278 		} else if (!efuse->share_ant) {
1279 			table_case = 100;
1280 			tdma_case = 100;
1281 		}
1282 	}
1283 
1284 	if (table_case != 0xff && tdma_case != 0xff) {
1285 		rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1286 		rtw_coex_table(rtwdev, table_case);
1287 		rtw_coex_tdma(rtwdev, false, tdma_case);
1288 		return;
1289 	}
1290 
1291 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1292 
1293 	if (efuse->share_ant) {
1294 		/* Shared-Ant */
1295 		if (!coex_stat->wl_gl_busy) {
1296 			table_case = 10;
1297 			tdma_case = 3;
1298 		} else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1299 			table_case = 6;
1300 			tdma_case = 7;
1301 		} else {
1302 			table_case = 12;
1303 			tdma_case = 7;
1304 		}
1305 	} else {
1306 		/* Non-Shared-Ant */
1307 		if (!coex_stat->wl_gl_busy) {
1308 			table_case = 112;
1309 			tdma_case = 104;
1310 		} else if ((coex_stat->bt_ble_scan_type & 0x2) &&
1311 			    coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1312 			table_case = 114;
1313 			tdma_case = 103;
1314 		} else {
1315 			table_case = 112;
1316 			tdma_case = 103;
1317 		}
1318 	}
1319 
1320 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1321 	rtw_coex_table(rtwdev, table_case);
1322 	rtw_coex_tdma(rtwdev, false, tdma_case);
1323 }
1324 
1325 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
1326 {
1327 	struct rtw_coex *coex = &rtwdev->coex;
1328 	struct rtw_coex_stat *coex_stat = &coex->stat;
1329 	struct rtw_efuse *efuse = &rtwdev->efuse;
1330 	struct rtw_chip_info *chip = rtwdev->chip;
1331 	bool wl_hi_pri = false;
1332 	u8 table_case, tdma_case;
1333 	u32 slot_type = 0;
1334 
1335 	if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
1336 	    coex_stat->wl_hi_pri_task2)
1337 		wl_hi_pri = true;
1338 
1339 	if (efuse->share_ant) {
1340 		/* Shared-Ant */
1341 		if (wl_hi_pri) {
1342 			table_case = 15;
1343 			if (coex_stat->bt_profile_num > 0)
1344 				tdma_case = 10;
1345 			else if (coex_stat->wl_hi_pri_task1)
1346 				tdma_case = 6;
1347 			else if (!coex_stat->bt_page)
1348 				tdma_case = 8;
1349 			else
1350 				tdma_case = 9;
1351 		} else if (coex_stat->wl_gl_busy) {
1352 			if (coex_stat->bt_profile_num == 0) {
1353 				table_case = 12;
1354 				tdma_case = 18;
1355 			} else if (coex_stat->bt_profile_num == 1 &&
1356 				   !coex_stat->bt_a2dp_exist) {
1357 				slot_type = TDMA_4SLOT;
1358 				table_case = 12;
1359 				tdma_case = 20;
1360 			} else {
1361 				slot_type = TDMA_4SLOT;
1362 				table_case = 12;
1363 				tdma_case = 26;
1364 			}
1365 		} else if (coex_stat->wl_connected) {
1366 			table_case = 9;
1367 			tdma_case = 27;
1368 		} else {
1369 			table_case = 1;
1370 			tdma_case = 0;
1371 		}
1372 	} else {
1373 		/* Non_Shared-Ant */
1374 		if (wl_hi_pri) {
1375 			table_case = 113;
1376 			if (coex_stat->bt_a2dp_exist &&
1377 			    !coex_stat->bt_pan_exist)
1378 				tdma_case = 111;
1379 			else if (coex_stat->wl_hi_pri_task1)
1380 				tdma_case = 106;
1381 			else if (!coex_stat->bt_page)
1382 				tdma_case = 108;
1383 			else
1384 				tdma_case = 109;
1385 		} else if (coex_stat->wl_gl_busy) {
1386 			table_case = 114;
1387 			tdma_case = 121;
1388 		} else if (coex_stat->wl_connected) {
1389 			table_case = 100;
1390 			tdma_case = 100;
1391 		} else {
1392 			table_case = 101;
1393 			tdma_case = 100;
1394 		}
1395 	}
1396 
1397 	rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n",
1398 		wl_hi_pri, coex_stat->bt_page);
1399 
1400 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1401 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1402 	rtw_coex_table(rtwdev, table_case);
1403 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1404 }
1405 
1406 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
1407 {
1408 	struct rtw_coex *coex = &rtwdev->coex;
1409 	struct rtw_coex_stat *coex_stat = &coex->stat;
1410 	struct rtw_efuse *efuse = &rtwdev->efuse;
1411 	struct rtw_chip_info *chip = rtwdev->chip;
1412 	u8 table_case, tdma_case;
1413 
1414 	if (efuse->share_ant) {
1415 		/* Shared-Ant */
1416 		if (coex_stat->bt_multi_link) {
1417 			table_case = 10;
1418 			tdma_case = 17;
1419 		} else {
1420 			table_case = 10;
1421 			tdma_case = 5;
1422 		}
1423 	} else {
1424 		/* Non-Shared-Ant */
1425 		if (coex_stat->bt_multi_link) {
1426 			table_case = 112;
1427 			tdma_case = 117;
1428 		} else {
1429 			table_case = 105;
1430 			tdma_case = 100;
1431 		}
1432 	}
1433 
1434 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1435 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1436 	rtw_coex_table(rtwdev, table_case);
1437 	rtw_coex_tdma(rtwdev, false, tdma_case);
1438 }
1439 
1440 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
1441 {
1442 	struct rtw_coex *coex = &rtwdev->coex;
1443 	struct rtw_coex_stat *coex_stat = &coex->stat;
1444 	struct rtw_efuse *efuse = &rtwdev->efuse;
1445 	struct rtw_chip_info *chip = rtwdev->chip;
1446 	u8 table_case, tdma_case;
1447 	u32 wl_bw;
1448 
1449 	wl_bw = rtwdev->hal.current_band_width;
1450 
1451 	if (efuse->share_ant) {
1452 		/* Shared-Ant */
1453 		if (coex_stat->bt_ble_exist) {
1454 			/* RCU */
1455 			if (!coex_stat->wl_gl_busy)
1456 				table_case = 14;
1457 			else
1458 				table_case = 15;
1459 
1460 			if (coex_stat->bt_a2dp_active || wl_bw == 0)
1461 				tdma_case = 18;
1462 			else if (coex_stat->wl_gl_busy)
1463 				tdma_case = 8;
1464 			else
1465 				tdma_case = 4;
1466 		} else {
1467 			if (coex_stat->bt_a2dp_active || wl_bw == 0) {
1468 				table_case = 8;
1469 				tdma_case = 4;
1470 			} else {
1471 				/* for 4/18 HID */
1472 				if (coex_stat->bt_418_hid_exist &&
1473 				    coex_stat->wl_gl_busy)
1474 					table_case = 12;
1475 				else
1476 					table_case = 10;
1477 				tdma_case = 4;
1478 			}
1479 		}
1480 	} else {
1481 		/* Non-Shared-Ant */
1482 		if (coex_stat->bt_a2dp_active) {
1483 			table_case = 113;
1484 			tdma_case = 118;
1485 		} else if (coex_stat->bt_ble_exist) {
1486 			/* BLE */
1487 			table_case = 113;
1488 
1489 			if (coex_stat->wl_gl_busy)
1490 				tdma_case = 106;
1491 			else
1492 				tdma_case = 104;
1493 		} else {
1494 			table_case = 113;
1495 			tdma_case = 104;
1496 		}
1497 	}
1498 
1499 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1500 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1501 	rtw_coex_table(rtwdev, table_case);
1502 	rtw_coex_tdma(rtwdev, false, tdma_case);
1503 }
1504 
1505 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
1506 {
1507 	struct rtw_coex *coex = &rtwdev->coex;
1508 	struct rtw_coex_stat *coex_stat = &coex->stat;
1509 	struct rtw_coex_dm *coex_dm = &coex->dm;
1510 	struct rtw_efuse *efuse = &rtwdev->efuse;
1511 	struct rtw_chip_info *chip = rtwdev->chip;
1512 	u8 table_case, tdma_case;
1513 	u32 slot_type = 0;
1514 
1515 	if (efuse->share_ant) {
1516 		/* Shared-Ant */
1517 		slot_type = TDMA_4SLOT;
1518 
1519 		if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1520 			table_case = 10;
1521 		else
1522 			table_case = 9;
1523 
1524 		if (coex_stat->wl_gl_busy)
1525 			tdma_case = 13;
1526 		else
1527 			tdma_case = 14;
1528 	} else {
1529 		/* Non-Shared-Ant */
1530 		table_case = 112;
1531 
1532 		if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1533 			tdma_case = 112;
1534 		else
1535 			tdma_case = 113;
1536 	}
1537 
1538 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1539 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1540 	rtw_coex_table(rtwdev, table_case);
1541 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1542 }
1543 
1544 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
1545 {
1546 	struct rtw_coex *coex = &rtwdev->coex;
1547 	struct rtw_coex_stat *coex_stat = &coex->stat;
1548 	struct rtw_efuse *efuse = &rtwdev->efuse;
1549 	struct rtw_chip_info *chip = rtwdev->chip;
1550 	u8 table_case, tdma_case;
1551 	bool ap_enable = false;
1552 
1553 	if (efuse->share_ant) { /* Shared-Ant */
1554 		if (ap_enable) {
1555 			table_case = 2;
1556 			tdma_case = 0;
1557 		} else if (coex_stat->wl_gl_busy) {
1558 			table_case = 28;
1559 			tdma_case = 20;
1560 		} else {
1561 			table_case = 28;
1562 			tdma_case = 26;
1563 		}
1564 	} else { /* Non-Shared-Ant */
1565 		if (ap_enable) {
1566 			table_case = 100;
1567 			tdma_case = 100;
1568 		} else {
1569 			table_case = 119;
1570 			tdma_case = 120;
1571 		}
1572 	}
1573 
1574 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1575 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1576 	rtw_coex_table(rtwdev, table_case);
1577 	rtw_coex_tdma(rtwdev, false, tdma_case);
1578 }
1579 
1580 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
1581 {
1582 	struct rtw_coex *coex = &rtwdev->coex;
1583 	struct rtw_coex_stat *coex_stat = &coex->stat;
1584 	struct rtw_efuse *efuse = &rtwdev->efuse;
1585 	struct rtw_chip_info *chip = rtwdev->chip;
1586 	u8 table_case, tdma_case;
1587 
1588 	if (efuse->share_ant) {
1589 		/* Shared-Ant */
1590 		if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1591 			table_case = 14;
1592 		else
1593 			table_case = 10;
1594 
1595 		if (coex_stat->wl_gl_busy)
1596 			tdma_case = 17;
1597 		else
1598 			tdma_case = 19;
1599 	} else {
1600 		/* Non-Shared-Ant */
1601 		table_case = 112;
1602 
1603 		if (coex_stat->wl_gl_busy)
1604 			tdma_case = 117;
1605 		else
1606 			tdma_case = 119;
1607 	}
1608 
1609 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1610 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1611 	rtw_coex_table(rtwdev, table_case);
1612 	rtw_coex_tdma(rtwdev, false, tdma_case);
1613 }
1614 
1615 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
1616 {
1617 	struct rtw_coex *coex = &rtwdev->coex;
1618 	struct rtw_coex_stat *coex_stat = &coex->stat;
1619 	struct rtw_coex_dm *coex_dm = &coex->dm;
1620 	struct rtw_efuse *efuse = &rtwdev->efuse;
1621 	struct rtw_chip_info *chip = rtwdev->chip;
1622 	u8 table_case, tdma_case;
1623 	u32 slot_type = 0;
1624 
1625 	if (efuse->share_ant) {
1626 		/* Shared-Ant */
1627 		slot_type = TDMA_4SLOT;
1628 
1629 		if (coex_stat->bt_ble_exist)
1630 			table_case = 26;
1631 		else
1632 			table_case = 9;
1633 
1634 		if (coex_stat->wl_gl_busy) {
1635 			tdma_case = 13;
1636 		} else {
1637 			tdma_case = 14;
1638 		}
1639 	} else {
1640 		/* Non-Shared-Ant */
1641 		if (coex_stat->bt_ble_exist)
1642 			table_case = 121;
1643 		else
1644 			table_case = 113;
1645 
1646 		if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1647 			tdma_case = 112;
1648 		else
1649 			tdma_case = 113;
1650 	}
1651 
1652 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1653 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1654 	rtw_coex_table(rtwdev, table_case);
1655 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1656 }
1657 
1658 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
1659 {
1660 	struct rtw_coex *coex = &rtwdev->coex;
1661 	struct rtw_coex_stat *coex_stat = &coex->stat;
1662 	struct rtw_efuse *efuse = &rtwdev->efuse;
1663 	struct rtw_chip_info *chip = rtwdev->chip;
1664 	u8 table_case, tdma_case;
1665 
1666 	if (efuse->share_ant) {
1667 		/* Shared-Ant */
1668 		if (coex_stat->wl_gl_busy &&
1669 		    coex_stat->wl_noisy_level == 0)
1670 			table_case = 14;
1671 		else
1672 			table_case = 10;
1673 
1674 		if (coex_stat->wl_gl_busy)
1675 			tdma_case = 15;
1676 		else
1677 			tdma_case = 20;
1678 	} else {
1679 		/* Non-Shared-Ant */
1680 		table_case = 112;
1681 
1682 		if (coex_stat->wl_gl_busy)
1683 			tdma_case = 115;
1684 		else
1685 			tdma_case = 120;
1686 	}
1687 
1688 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1689 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1690 	rtw_coex_table(rtwdev, table_case);
1691 	rtw_coex_tdma(rtwdev, false, tdma_case);
1692 }
1693 
1694 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
1695 {
1696 	struct rtw_coex *coex = &rtwdev->coex;
1697 	struct rtw_coex_stat *coex_stat = &coex->stat;
1698 	struct rtw_efuse *efuse = &rtwdev->efuse;
1699 	struct rtw_chip_info *chip = rtwdev->chip;
1700 	u8 table_case, tdma_case;
1701 
1702 	if (efuse->share_ant) {
1703 		/* Shared-Ant */
1704 		table_case = 9;
1705 
1706 		if (coex_stat->wl_gl_busy)
1707 			tdma_case = 18;
1708 		else
1709 			tdma_case = 19;
1710 	} else {
1711 		/* Non-Shared-Ant */
1712 		table_case = 113;
1713 
1714 		if (coex_stat->wl_gl_busy)
1715 			tdma_case = 117;
1716 		else
1717 			tdma_case = 119;
1718 	}
1719 
1720 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1721 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1722 	rtw_coex_table(rtwdev, table_case);
1723 	rtw_coex_tdma(rtwdev, false, tdma_case);
1724 }
1725 
1726 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
1727 {
1728 	struct rtw_coex *coex = &rtwdev->coex;
1729 	struct rtw_coex_stat *coex_stat = &coex->stat;
1730 	struct rtw_efuse *efuse = &rtwdev->efuse;
1731 	struct rtw_chip_info *chip = rtwdev->chip;
1732 	u8 table_case, tdma_case;
1733 
1734 	if (efuse->share_ant) {
1735 		/* Shared-Ant */
1736 		table_case = 10;
1737 
1738 		if (coex_stat->wl_gl_busy)
1739 			tdma_case = 15;
1740 		else
1741 			tdma_case = 20;
1742 	} else {
1743 		/* Non-Shared-Ant */
1744 		table_case = 113;
1745 
1746 		if (coex_stat->wl_gl_busy)
1747 			tdma_case = 115;
1748 		else
1749 			tdma_case = 120;
1750 	}
1751 
1752 	rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1753 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1754 	rtw_coex_table(rtwdev, table_case);
1755 	rtw_coex_tdma(rtwdev, false, tdma_case);
1756 }
1757 
1758 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
1759 {
1760 	struct rtw_efuse *efuse = &rtwdev->efuse;
1761 	struct rtw_chip_info *chip = rtwdev->chip;
1762 	u8 table_case, tdma_case;
1763 
1764 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1765 
1766 	if (efuse->share_ant) {
1767 		/* Shared-Ant */
1768 		table_case = 0;
1769 		tdma_case = 0;
1770 	} else {
1771 		/* Non-Shared-Ant */
1772 		table_case = 100;
1773 		tdma_case = 100;
1774 	}
1775 
1776 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
1777 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1778 	rtw_coex_table(rtwdev, table_case);
1779 	rtw_coex_tdma(rtwdev, false, tdma_case);
1780 }
1781 
1782 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
1783 {
1784 	struct rtw_efuse *efuse = &rtwdev->efuse;
1785 	struct rtw_chip_info *chip = rtwdev->chip;
1786 	u8 table_case, tdma_case;
1787 
1788 	if (efuse->share_ant) {
1789 		/* Shared-Ant */
1790 		table_case = 2;
1791 		tdma_case = 0;
1792 	} else {
1793 		/* Non-Shared-Ant */
1794 		table_case = 100;
1795 		tdma_case = 100;
1796 	}
1797 
1798 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1799 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1800 	rtw_coex_table(rtwdev, table_case);
1801 	rtw_coex_tdma(rtwdev, false, tdma_case);
1802 }
1803 
1804 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
1805 {
1806 	struct rtw_coex *coex = &rtwdev->coex;
1807 	struct rtw_efuse *efuse = &rtwdev->efuse;
1808 	struct rtw_chip_info *chip = rtwdev->chip;
1809 	u8 table_case, tdma_case;
1810 
1811 	if (coex->under_5g)
1812 		return;
1813 
1814 	if (efuse->share_ant) {
1815 		/* Shared-Ant */
1816 		table_case = 28;
1817 		tdma_case = 0;
1818 	} else {
1819 		/* Non-Shared-Ant */
1820 		table_case = 100;
1821 		tdma_case = 100;
1822 	}
1823 
1824 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1825 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1826 	rtw_coex_table(rtwdev, table_case);
1827 	rtw_coex_tdma(rtwdev, false, tdma_case);
1828 }
1829 
1830 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
1831 {
1832 	struct rtw_coex *coex = &rtwdev->coex;
1833 	struct rtw_coex_stat *coex_stat = &coex->stat;
1834 	struct rtw_efuse *efuse = &rtwdev->efuse;
1835 	struct rtw_chip_info *chip = rtwdev->chip;
1836 	u8 table_case, tdma_case;
1837 	u32 slot_type = 0;
1838 
1839 	if (efuse->share_ant) {
1840 		/* Shared-Ant */
1841 		if (coex_stat->bt_a2dp_exist) {
1842 			slot_type = TDMA_4SLOT;
1843 			table_case = 9;
1844 			tdma_case = 11;
1845 		} else {
1846 			table_case = 9;
1847 			tdma_case = 7;
1848 		}
1849 	} else {
1850 		/* Non-Shared-Ant */
1851 		if (coex_stat->bt_a2dp_exist) {
1852 			table_case = 112;
1853 			tdma_case = 111;
1854 		} else {
1855 			table_case = 112;
1856 			tdma_case = 107;
1857 		}
1858 	}
1859 
1860 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1861 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1862 	rtw_coex_table(rtwdev, table_case);
1863 	rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1864 }
1865 
1866 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
1867 {
1868 	struct rtw_efuse *efuse = &rtwdev->efuse;
1869 	struct rtw_chip_info *chip = rtwdev->chip;
1870 	u8 table_case, tdma_case;
1871 
1872 	if (efuse->share_ant) {
1873 		/* Shared-Ant */
1874 		table_case = 1;
1875 		tdma_case = 0;
1876 	} else {
1877 		/* Non-Shared-Ant */
1878 		table_case = 100;
1879 		tdma_case = 100;
1880 	}
1881 
1882 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1883 	rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1884 	rtw_coex_table(rtwdev, table_case);
1885 	rtw_coex_tdma(rtwdev, false, tdma_case);
1886 }
1887 
1888 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
1889 {
1890 	struct rtw_coex *coex = &rtwdev->coex;
1891 	struct rtw_coex_stat *coex_stat = &coex->stat;
1892 	struct rtw_coex_dm *coex_dm = &coex->dm;
1893 	struct rtw_efuse *efuse = &rtwdev->efuse;
1894 	u8 algorithm;
1895 
1896 	/* Non-Shared-Ant */
1897 	if (!efuse->share_ant && coex_stat->wl_gl_busy &&
1898 	    COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
1899 	    COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) {
1900 		rtw_coex_action_freerun(rtwdev);
1901 		return;
1902 	}
1903 
1904 	algorithm = rtw_coex_algorithm(rtwdev);
1905 
1906 	switch (algorithm) {
1907 	case COEX_ALGO_HFP:
1908 		rtw_coex_action_bt_hfp(rtwdev);
1909 		break;
1910 	case COEX_ALGO_HID:
1911 		rtw_coex_action_bt_hid(rtwdev);
1912 		break;
1913 	case COEX_ALGO_A2DP:
1914 		if (coex_stat->bt_a2dp_sink)
1915 			rtw_coex_action_bt_a2dpsink(rtwdev);
1916 		else
1917 			rtw_coex_action_bt_a2dp(rtwdev);
1918 		break;
1919 	case COEX_ALGO_PAN:
1920 		rtw_coex_action_bt_pan(rtwdev);
1921 		break;
1922 	case COEX_ALGO_A2DP_HID:
1923 		rtw_coex_action_bt_a2dp_hid(rtwdev);
1924 		break;
1925 	case COEX_ALGO_A2DP_PAN:
1926 		rtw_coex_action_bt_a2dp_pan(rtwdev);
1927 		break;
1928 	case COEX_ALGO_PAN_HID:
1929 		rtw_coex_action_bt_pan_hid(rtwdev);
1930 		break;
1931 	case COEX_ALGO_A2DP_PAN_HID:
1932 		rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
1933 		break;
1934 	default:
1935 	case COEX_ALGO_NOPROFILE:
1936 		rtw_coex_action_bt_idle(rtwdev);
1937 		break;
1938 	}
1939 }
1940 
1941 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
1942 {
1943 	struct rtw_coex *coex = &rtwdev->coex;
1944 	struct rtw_coex_dm *coex_dm = &coex->dm;
1945 	struct rtw_coex_stat *coex_stat = &coex->stat;
1946 
1947 	lockdep_assert_held(&rtwdev->mutex);
1948 
1949 	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
1950 		return;
1951 
1952 	coex_dm->reason = reason;
1953 
1954 	/* update wifi_link_info_ext variable */
1955 	rtw_coex_update_wl_link_info(rtwdev, reason);
1956 
1957 	rtw_coex_monitor_bt_enable(rtwdev);
1958 
1959 	if (coex->stop_dm)
1960 		return;
1961 
1962 	if (coex_stat->wl_under_ips)
1963 		return;
1964 
1965 	if (coex->freeze && !coex_stat->bt_setup_link)
1966 		return;
1967 
1968 	coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
1969 	coex->freerun = false;
1970 
1971 	/* Pure-5G Coex Process */
1972 	if (coex->under_5g) {
1973 		coex_stat->wl_coex_mode = COEX_WLINK_5G;
1974 		rtw_coex_action_wl_under5g(rtwdev);
1975 		goto exit;
1976 	}
1977 
1978 	coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
1979 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1980 	if (coex_stat->bt_disabled) {
1981 		rtw_coex_action_wl_only(rtwdev);
1982 		goto exit;
1983 	}
1984 
1985 	if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
1986 		rtw_coex_action_wl_native_lps(rtwdev);
1987 		goto exit;
1988 	}
1989 
1990 	if (coex_stat->bt_whck_test) {
1991 		rtw_coex_action_bt_whql_test(rtwdev);
1992 		goto exit;
1993 	}
1994 
1995 	if (coex_stat->bt_setup_link) {
1996 		rtw_coex_action_bt_relink(rtwdev);
1997 		goto exit;
1998 	}
1999 
2000 	if (coex_stat->bt_inq_page) {
2001 		rtw_coex_action_bt_inquiry(rtwdev);
2002 		goto exit;
2003 	}
2004 
2005 	if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
2006 	     coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
2007 	     coex_stat->wl_connected) {
2008 		rtw_coex_action_bt_idle(rtwdev);
2009 		goto exit;
2010 	}
2011 
2012 	if (coex_stat->wl_linkscan_proc) {
2013 		rtw_coex_action_wl_linkscan(rtwdev);
2014 		goto exit;
2015 	}
2016 
2017 	if (coex_stat->wl_connected)
2018 		rtw_coex_action_wl_connected(rtwdev);
2019 	else
2020 		rtw_coex_action_wl_not_connected(rtwdev);
2021 
2022 exit:
2023 	rtw_coex_set_gnt_fix(rtwdev);
2024 	rtw_coex_limited_wl(rtwdev);
2025 }
2026 
2027 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
2028 {
2029 	struct rtw_coex *coex = &rtwdev->coex;
2030 	struct rtw_coex_stat *coex_stat = &coex->stat;
2031 	struct rtw_coex_dm *coex_dm = &coex->dm;
2032 	u8 i;
2033 
2034 	memset(coex_dm, 0, sizeof(*coex_dm));
2035 	memset(coex_stat, 0, sizeof(*coex_stat));
2036 
2037 	for (i = 0; i < COEX_CNT_WL_MAX; i++)
2038 		coex_stat->cnt_wl[i] = 0;
2039 
2040 	for (i = 0; i < COEX_CNT_BT_MAX; i++)
2041 		coex_stat->cnt_bt[i] = 0;
2042 
2043 	for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
2044 		coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
2045 
2046 	for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
2047 		coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
2048 
2049 	coex_stat->wl_coex_mode = COEX_WLINK_MAX;
2050 }
2051 
2052 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2053 {
2054 	struct rtw_coex *coex = &rtwdev->coex;
2055 
2056 	rtw_coex_init_coex_var(rtwdev);
2057 	rtw_coex_monitor_bt_enable(rtwdev);
2058 	rtw_coex_set_rfe_type(rtwdev);
2059 	rtw_coex_set_init(rtwdev);
2060 
2061 	/* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
2062 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
2063 
2064 	/* set Tx beacon = Hi-Pri */
2065 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
2066 
2067 	/* set Tx beacon queue = Hi-Pri */
2068 	rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
2069 
2070 	/* antenna config */
2071 	if (coex->wl_rf_off) {
2072 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2073 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2074 		coex->stop_dm = true;
2075 	} else if (wifi_only) {
2076 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
2077 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2078 				    true);
2079 		coex->stop_dm = true;
2080 	} else {
2081 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
2082 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2083 				    true);
2084 		coex->stop_dm = false;
2085 		coex->freeze = true;
2086 	}
2087 
2088 	/* PTA parameter */
2089 	rtw_coex_table(rtwdev, 0);
2090 	rtw_coex_tdma(rtwdev, true, 0);
2091 	rtw_coex_query_bt_info(rtwdev);
2092 }
2093 
2094 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
2095 {
2096 	struct rtw_coex *coex = &rtwdev->coex;
2097 
2098 	coex->stop_dm = true;
2099 	coex->wl_rf_off = false;
2100 
2101 	/* enable BB, we can write 0x948 */
2102 	rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1));
2103 
2104 	rtw_coex_monitor_bt_enable(rtwdev);
2105 	rtw_coex_set_rfe_type(rtwdev);
2106 
2107 	/* set antenna path to BT */
2108 	rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
2109 
2110 	/* red x issue */
2111 	rtw_write8(rtwdev, 0xff1a, 0x0);
2112 }
2113 
2114 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2115 {
2116 	__rtw_coex_init_hw_config(rtwdev, wifi_only);
2117 }
2118 
2119 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
2120 {
2121 	struct rtw_coex *coex = &rtwdev->coex;
2122 	struct rtw_coex_stat *coex_stat = &coex->stat;
2123 
2124 	if (coex->stop_dm)
2125 		return;
2126 
2127 	if (type == COEX_IPS_ENTER) {
2128 		coex_stat->wl_under_ips = true;
2129 
2130 		/* for lps off */
2131 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2132 
2133 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2134 		rtw_coex_action_coex_all_off(rtwdev);
2135 	} else if (type == COEX_IPS_LEAVE) {
2136 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2137 
2138 		/* run init hw config (exclude wifi only) */
2139 		__rtw_coex_init_hw_config(rtwdev, false);
2140 		/* sw all off */
2141 
2142 		coex_stat->wl_under_ips = false;
2143 	}
2144 }
2145 
2146 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
2147 {
2148 	struct rtw_coex *coex = &rtwdev->coex;
2149 	struct rtw_coex_stat *coex_stat = &coex->stat;
2150 
2151 	if (coex->stop_dm)
2152 		return;
2153 
2154 	if (type == COEX_LPS_ENABLE) {
2155 		coex_stat->wl_under_lps = true;
2156 
2157 		if (coex_stat->wl_force_lps_ctrl) {
2158 			/* for ps-tdma */
2159 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2160 		} else {
2161 			/* for native ps */
2162 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2163 
2164 			rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2165 		}
2166 	} else if (type == COEX_LPS_DISABLE) {
2167 		coex_stat->wl_under_lps = false;
2168 
2169 		/* for lps off */
2170 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2171 
2172 		if (!coex_stat->wl_force_lps_ctrl)
2173 			rtw_coex_query_bt_info(rtwdev);
2174 	}
2175 }
2176 
2177 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
2178 {
2179 	struct rtw_coex *coex = &rtwdev->coex;
2180 	struct rtw_coex_stat *coex_stat = &coex->stat;
2181 
2182 	if (coex->stop_dm)
2183 		return;
2184 
2185 	coex->freeze = false;
2186 
2187 	if (type != COEX_SCAN_FINISH)
2188 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2189 				    COEX_SCBD_ONOFF, true);
2190 
2191 	if (type == COEX_SCAN_START_5G) {
2192 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2193 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
2194 	} else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
2195 		coex_stat->wl_hi_pri_task2 = true;
2196 
2197 		/* Force antenna setup for no scan result issue */
2198 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2199 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
2200 	} else {
2201 		coex_stat->wl_hi_pri_task2 = false;
2202 		rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
2203 	}
2204 }
2205 
2206 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
2207 {
2208 	struct rtw_coex *coex = &rtwdev->coex;
2209 
2210 	if (coex->stop_dm)
2211 		return;
2212 
2213 	if (type == COEX_SWITCH_TO_5G)
2214 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
2215 	else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
2216 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
2217 	else
2218 		rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
2219 }
2220 
2221 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
2222 {
2223 	struct rtw_coex *coex = &rtwdev->coex;
2224 	struct rtw_coex_stat *coex_stat = &coex->stat;
2225 
2226 	if (coex->stop_dm)
2227 		return;
2228 
2229 	rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2230 			    COEX_SCBD_ONOFF, true);
2231 
2232 	if (type == COEX_ASSOCIATE_5G_START) {
2233 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2234 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
2235 	} else if (type == COEX_ASSOCIATE_5G_FINISH) {
2236 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2237 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
2238 	} else if (type == COEX_ASSOCIATE_START) {
2239 		coex_stat->wl_hi_pri_task1 = true;
2240 		coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
2241 
2242 		/* Force antenna setup for no scan result issue */
2243 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2244 
2245 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
2246 
2247 		/* To keep TDMA case during connect process,
2248 		 * to avoid changed by Btinfo and runcoexmechanism
2249 		 */
2250 		coex->freeze = true;
2251 		ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
2252 					     5 * HZ);
2253 	} else {
2254 		coex_stat->wl_hi_pri_task1 = false;
2255 		coex->freeze = false;
2256 
2257 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
2258 	}
2259 }
2260 
2261 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
2262 {
2263 	struct rtw_coex *coex = &rtwdev->coex;
2264 	struct rtw_coex_stat *coex_stat = &coex->stat;
2265 	u8 para[6] = {0};
2266 
2267 	if (coex->stop_dm)
2268 		return;
2269 
2270 	if (type == COEX_MEDIA_CONNECT_5G) {
2271 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2272 
2273 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2274 		rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
2275 	} else if (type == COEX_MEDIA_CONNECT) {
2276 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2277 
2278 		/* Force antenna setup for no scan result issue */
2279 		rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2280 
2281 		/* Set CCK Rx high Pri */
2282 		rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
2283 
2284 		/* always enable 5ms extend if connect */
2285 		para[0] = COEX_H2C69_WL_LEAKAP;
2286 		para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */
2287 		rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
2288 		coex_stat->wl_slot_extend = true;
2289 		rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
2290 	} else {
2291 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2292 
2293 		rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
2294 
2295 		rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
2296 	}
2297 
2298 	rtw_coex_update_wl_ch_info(rtwdev, type);
2299 }
2300 
2301 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2302 {
2303 	struct rtw_coex *coex = &rtwdev->coex;
2304 	struct rtw_coex_stat *coex_stat = &coex->stat;
2305 	struct rtw_chip_info *chip = rtwdev->chip;
2306 	unsigned long bt_relink_time;
2307 	u8 i, rsp_source = 0, type;
2308 	bool inq_page = false;
2309 
2310 	rsp_source = buf[0] & 0xf;
2311 	if (rsp_source >= COEX_BTINFO_SRC_MAX)
2312 		rsp_source = COEX_BTINFO_SRC_WL_FW;
2313 
2314 	if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
2315 		coex_stat->bt_iqk_state = buf[1];
2316 		if (coex_stat->bt_iqk_state == 1)
2317 			coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
2318 		else if (coex_stat->bt_iqk_state == 2)
2319 			coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
2320 
2321 		return;
2322 	}
2323 
2324 	if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
2325 		rtw_coex_monitor_bt_enable(rtwdev);
2326 		if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
2327 			coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
2328 			rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2329 		}
2330 		return;
2331 	}
2332 
2333 	if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
2334 	    rsp_source == COEX_BTINFO_SRC_BT_ACT) {
2335 		if (coex_stat->bt_disabled) {
2336 			coex_stat->bt_disabled = false;
2337 			coex_stat->bt_reenable = true;
2338 			ieee80211_queue_delayed_work(rtwdev->hw,
2339 						     &coex->bt_reenable_work,
2340 						     15 * HZ);
2341 		}
2342 	}
2343 
2344 	for (i = 0; i < length; i++) {
2345 		if (i < COEX_BTINFO_LENGTH_MAX)
2346 			coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
2347 		else
2348 			break;
2349 	}
2350 
2351 	if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
2352 		rtw_coex_update_bt_link_info(rtwdev);
2353 		rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2354 		return;
2355 	}
2356 
2357 	/* get the same info from bt, skip it */
2358 	if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
2359 	    coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
2360 	    coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
2361 	    coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
2362 	    coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
2363 	    coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3)
2364 		return;
2365 
2366 	coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
2367 	coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
2368 	coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
2369 	coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
2370 	coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
2371 	coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
2372 
2373 	/* 0xff means BT is under WHCK test */
2374 	coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
2375 
2376 	inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
2377 
2378 	if (inq_page != coex_stat->bt_inq_page) {
2379 		cancel_delayed_work_sync(&coex->bt_remain_work);
2380 		coex_stat->bt_inq_page = inq_page;
2381 
2382 		if (inq_page)
2383 			coex_stat->bt_inq_remain = true;
2384 		else
2385 			ieee80211_queue_delayed_work(rtwdev->hw,
2386 						     &coex->bt_remain_work,
2387 						     4 * HZ);
2388 	}
2389 	coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
2390 	coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
2391 	if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
2392 		coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
2393 
2394 	coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
2395 	coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
2396 	if (coex_stat->bt_inq)
2397 		coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
2398 
2399 	coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
2400 	if (coex_stat->bt_page) {
2401 		coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
2402 		if (coex_stat->wl_linkscan_proc ||
2403 		    coex_stat->wl_hi_pri_task1 ||
2404 		    coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
2405 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
2406 		else
2407 			rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2408 	} else {
2409 		rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2410 	}
2411 
2412 	/* unit: % (value-100 to translate to unit: dBm in coex info) */
2413 	if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
2414 		coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
2415 	} else { /* original unit: dbm -> unit: % ->  value-100 in coex info */
2416 		if (coex_stat->bt_info_hb0 <= 127)
2417 			coex_stat->bt_rssi = 100;
2418 		else if (256 - coex_stat->bt_info_hb0 <= 100)
2419 			coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
2420 		else
2421 			coex_stat->bt_rssi = 0;
2422 	}
2423 
2424 	coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0));
2425 	if (coex_stat->bt_info_hb1 & BIT(1))
2426 		coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
2427 
2428 	if (coex_stat->bt_info_hb1 & BIT(2)) {
2429 		coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
2430 		coex_stat->bt_setup_link = true;
2431 		if (coex_stat->bt_reenable)
2432 			bt_relink_time = 6 * HZ;
2433 		else
2434 			bt_relink_time = 2 * HZ;
2435 
2436 		ieee80211_queue_delayed_work(rtwdev->hw,
2437 					     &coex->bt_relink_work,
2438 					     bt_relink_time);
2439 	}
2440 
2441 	if (coex_stat->bt_info_hb1 & BIT(3))
2442 		coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
2443 
2444 	coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
2445 	coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
2446 	if (coex_stat->bt_info_hb1 & BIT(6))
2447 		coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
2448 
2449 	coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
2450 	/* resend wifi info to bt, it is reset and lost the info */
2451 	if ((coex_stat->bt_info_hb1 & BIT(1))) {
2452 		if (coex_stat->wl_connected)
2453 			type = COEX_MEDIA_CONNECT;
2454 		else
2455 			type = COEX_MEDIA_DISCONNECT;
2456 		rtw_coex_update_wl_ch_info(rtwdev, type);
2457 	}
2458 
2459 	/* if ignore_wlan_act && not set_up_link */
2460 	if ((coex_stat->bt_info_hb1 & BIT(3)) &&
2461 	    (!(coex_stat->bt_info_hb1 & BIT(2))))
2462 		rtw_coex_ignore_wlan_act(rtwdev, false);
2463 
2464 	coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
2465 	if (coex_stat->bt_info_hb2 & BIT(1))
2466 		coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
2467 
2468 	coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
2469 	coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
2470 	coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
2471 	coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
2472 	if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
2473 		coex_stat->bt_418_hid_exist = true;
2474 	else if (coex_stat->bt_hid_pair_num == 0)
2475 		coex_stat->bt_418_hid_exist = false;
2476 
2477 	if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
2478 		coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
2479 	else
2480 		coex_stat->bt_a2dp_bitpool = 0;
2481 
2482 	coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
2483 
2484 	rtw_coex_update_bt_link_info(rtwdev);
2485 	rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2486 }
2487 
2488 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2489 {
2490 	struct rtw_coex *coex = &rtwdev->coex;
2491 	struct rtw_coex_stat *coex_stat = &coex->stat;
2492 	u8 val;
2493 	int i;
2494 
2495 	if (WARN(length < 8, "invalid wl info c2h length\n"))
2496 		return;
2497 
2498 	if (buf[0] != 0x08)
2499 		return;
2500 
2501 	for (i = 1; i < 8; i++) {
2502 		val = coex_stat->wl_fw_dbg_info_pre[i];
2503 		if (buf[i] >= val)
2504 			coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
2505 		else
2506 			coex_stat->wl_fw_dbg_info[i] = val - buf[i];
2507 
2508 		coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
2509 	}
2510 
2511 	coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
2512 	rtw_coex_wl_ccklock_action(rtwdev);
2513 	rtw_coex_wl_ccklock_detect(rtwdev);
2514 }
2515 
2516 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev)
2517 {
2518 	struct rtw_coex *coex = &rtwdev->coex;
2519 
2520 	if (coex->stop_dm)
2521 		return;
2522 
2523 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2524 }
2525 
2526 void rtw_coex_bt_relink_work(struct work_struct *work)
2527 {
2528 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2529 					      coex.bt_relink_work.work);
2530 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2531 
2532 	mutex_lock(&rtwdev->mutex);
2533 	coex_stat->bt_setup_link = false;
2534 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2535 	mutex_unlock(&rtwdev->mutex);
2536 }
2537 
2538 void rtw_coex_bt_reenable_work(struct work_struct *work)
2539 {
2540 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2541 					      coex.bt_reenable_work.work);
2542 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2543 
2544 	mutex_lock(&rtwdev->mutex);
2545 	coex_stat->bt_reenable = false;
2546 	mutex_unlock(&rtwdev->mutex);
2547 }
2548 
2549 void rtw_coex_defreeze_work(struct work_struct *work)
2550 {
2551 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2552 					      coex.defreeze_work.work);
2553 	struct rtw_coex *coex = &rtwdev->coex;
2554 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2555 
2556 	mutex_lock(&rtwdev->mutex);
2557 	coex->freeze = false;
2558 	coex_stat->wl_hi_pri_task1 = false;
2559 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2560 	mutex_unlock(&rtwdev->mutex);
2561 }
2562 
2563 void rtw_coex_wl_remain_work(struct work_struct *work)
2564 {
2565 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2566 					      coex.wl_remain_work.work);
2567 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2568 
2569 	mutex_lock(&rtwdev->mutex);
2570 	coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
2571 	rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2572 	mutex_unlock(&rtwdev->mutex);
2573 }
2574 
2575 void rtw_coex_bt_remain_work(struct work_struct *work)
2576 {
2577 	struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2578 					      coex.bt_remain_work.work);
2579 	struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2580 
2581 	mutex_lock(&rtwdev->mutex);
2582 	coex_stat->bt_inq_remain = coex_stat->bt_inq_page;
2583 	rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
2584 	mutex_unlock(&rtwdev->mutex);
2585 }
2586 
2587 #ifdef CONFIG_RTW88_DEBUGFS
2588 #define INFO_SIZE	80
2589 
2590 #define case_BTINFO(src) \
2591 	case COEX_BTINFO_SRC_##src: return #src
2592 
2593 static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src)
2594 {
2595 	switch (bt_info_src) {
2596 	case_BTINFO(WL_FW);
2597 	case_BTINFO(BT_RSP);
2598 	case_BTINFO(BT_ACT);
2599 	default:
2600 		return "Unknown";
2601 	}
2602 }
2603 
2604 #define case_RSN(src) \
2605 	case COEX_RSN_##src: return #src
2606 
2607 static const char *rtw_coex_get_reason_string(u8 reason)
2608 {
2609 	switch (reason) {
2610 	case_RSN(2GSCANSTART);
2611 	case_RSN(5GSCANSTART);
2612 	case_RSN(SCANFINISH);
2613 	case_RSN(2GSWITCHBAND);
2614 	case_RSN(5GSWITCHBAND);
2615 	case_RSN(2GCONSTART);
2616 	case_RSN(5GCONSTART);
2617 	case_RSN(2GCONFINISH);
2618 	case_RSN(5GCONFINISH);
2619 	case_RSN(2GMEDIA);
2620 	case_RSN(5GMEDIA);
2621 	case_RSN(MEDIADISCON);
2622 	case_RSN(BTINFO);
2623 	case_RSN(LPS);
2624 	case_RSN(WLSTATUS);
2625 	default:
2626 		return "Unknown";
2627 	}
2628 }
2629 
2630 static int rtw_coex_addr_info(struct rtw_dev *rtwdev,
2631 			      const struct rtw_reg_domain *reg,
2632 			      char addr_info[], int n)
2633 {
2634 	const char *rf_prefix = "";
2635 	const char *sep = n == 0 ? "" : "/ ";
2636 	int ffs, fls;
2637 	int max_fls;
2638 
2639 	if (INFO_SIZE - n <= 0)
2640 		return 0;
2641 
2642 	switch (reg->domain) {
2643 	case RTW_REG_DOMAIN_MAC32:
2644 		max_fls = 31;
2645 		break;
2646 	case RTW_REG_DOMAIN_MAC16:
2647 		max_fls = 15;
2648 		break;
2649 	case RTW_REG_DOMAIN_MAC8:
2650 		max_fls = 7;
2651 		break;
2652 	case RTW_REG_DOMAIN_RF_A:
2653 	case RTW_REG_DOMAIN_RF_B:
2654 		rf_prefix = "RF_";
2655 		max_fls = 19;
2656 		break;
2657 	default:
2658 		return 0;
2659 	}
2660 
2661 	ffs = __ffs(reg->mask);
2662 	fls = __fls(reg->mask);
2663 
2664 	if (ffs == 0 && fls == max_fls)
2665 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x",
2666 				 sep, rf_prefix, reg->addr);
2667 	else if (ffs == fls)
2668 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]",
2669 				 sep, rf_prefix, reg->addr, ffs);
2670 	else
2671 		return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]",
2672 				 sep, rf_prefix, reg->addr, fls, ffs);
2673 }
2674 
2675 static int rtw_coex_val_info(struct rtw_dev *rtwdev,
2676 			     const struct rtw_reg_domain *reg,
2677 			     char val_info[], int n)
2678 {
2679 	const char *sep = n == 0 ? "" : "/ ";
2680 	u8 rf_path;
2681 
2682 	if (INFO_SIZE - n <= 0)
2683 		return 0;
2684 
2685 	switch (reg->domain) {
2686 	case RTW_REG_DOMAIN_MAC32:
2687 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2688 				 rtw_read32_mask(rtwdev, reg->addr, reg->mask));
2689 	case RTW_REG_DOMAIN_MAC16:
2690 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2691 				 rtw_read16_mask(rtwdev, reg->addr, reg->mask));
2692 	case RTW_REG_DOMAIN_MAC8:
2693 		return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2694 				 rtw_read8_mask(rtwdev, reg->addr, reg->mask));
2695 	case RTW_REG_DOMAIN_RF_A:
2696 		rf_path = RF_PATH_A;
2697 		break;
2698 	case RTW_REG_DOMAIN_RF_B:
2699 		rf_path = RF_PATH_B;
2700 		break;
2701 	default:
2702 		return 0;
2703 	}
2704 
2705 	/* only RF go through here */
2706 	return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2707 			 rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask));
2708 }
2709 
2710 static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
2711 {
2712 	struct rtw_chip_info *chip = rtwdev->chip;
2713 	const struct rtw_reg_domain *reg;
2714 	char addr_info[INFO_SIZE];
2715 	int n_addr = 0;
2716 	char val_info[INFO_SIZE];
2717 	int n_val = 0;
2718 	int i;
2719 
2720 	for (i = 0; i < chip->coex_info_hw_regs_num; i++) {
2721 		reg = &chip->coex_info_hw_regs[i];
2722 
2723 		n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr);
2724 		n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val);
2725 
2726 		if (reg->domain == RTW_REG_DOMAIN_NL) {
2727 			seq_printf(m, "%-40s = %s\n", addr_info, val_info);
2728 			n_addr = 0;
2729 			n_val = 0;
2730 		}
2731 	}
2732 
2733 	if (n_addr != 0 && n_val != 0)
2734 		seq_printf(m, "%-40s = %s\n", addr_info, val_info);
2735 }
2736 
2737 static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev,
2738 				u8 type, u16 addr, u16 *val)
2739 {
2740 	struct rtw_coex_info_req req = {0};
2741 	struct sk_buff *skb;
2742 	__le16 le_addr;
2743 	u8 *payload;
2744 
2745 	le_addr = cpu_to_le16(addr);
2746 	req.op_code = BT_MP_INFO_OP_READ_REG;
2747 	req.para1 = type;
2748 	req.para2 = le16_get_bits(le_addr, GENMASK(7, 0));
2749 	req.para3 = le16_get_bits(le_addr, GENMASK(15, 8));
2750 	skb = rtw_coex_info_request(rtwdev, &req);
2751 	if (!skb) {
2752 		*val = 0xeaea;
2753 		return false;
2754 	}
2755 
2756 	payload = get_payload_from_coex_resp(skb);
2757 	*val = GET_COEX_RESP_BT_REG_VAL(payload);
2758 
2759 	return true;
2760 }
2761 
2762 static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev,
2763 					  u32 *patch_version)
2764 {
2765 	struct rtw_coex_info_req req = {0};
2766 	struct sk_buff *skb;
2767 	u8 *payload;
2768 	bool ret = false;
2769 
2770 	req.op_code = BT_MP_INFO_OP_PATCH_VER;
2771 	skb = rtw_coex_info_request(rtwdev, &req);
2772 	if (!skb)
2773 		goto out;
2774 
2775 	payload = get_payload_from_coex_resp(skb);
2776 	*patch_version = GET_COEX_RESP_BT_PATCH_VER(payload);
2777 	ret = true;
2778 
2779 out:
2780 	return ret;
2781 }
2782 
2783 static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev,
2784 					      u32 *supported_version)
2785 {
2786 	struct rtw_coex_info_req req = {0};
2787 	struct sk_buff *skb;
2788 	u8 *payload;
2789 	bool ret = false;
2790 
2791 	req.op_code = BT_MP_INFO_OP_SUPP_VER;
2792 	skb = rtw_coex_info_request(rtwdev, &req);
2793 	if (!skb)
2794 		goto out;
2795 
2796 	payload = get_payload_from_coex_resp(skb);
2797 	*supported_version = GET_COEX_RESP_BT_SUPP_VER(payload);
2798 	ret = true;
2799 
2800 out:
2801 	return ret;
2802 }
2803 
2804 static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev,
2805 					      u32 *supported_feature)
2806 {
2807 	struct rtw_coex_info_req req = {0};
2808 	struct sk_buff *skb;
2809 	u8 *payload;
2810 	bool ret = false;
2811 
2812 	req.op_code = BT_MP_INFO_OP_SUPP_FEAT;
2813 	skb = rtw_coex_info_request(rtwdev, &req);
2814 	if (!skb)
2815 		goto out;
2816 
2817 	payload = get_payload_from_coex_resp(skb);
2818 	*supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload);
2819 	ret = true;
2820 
2821 out:
2822 	return ret;
2823 }
2824 
2825 struct rtw_coex_sta_stat_iter_data {
2826 	struct rtw_vif *rtwvif;
2827 	struct seq_file *file;
2828 };
2829 
2830 static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta)
2831 {
2832 	struct rtw_coex_sta_stat_iter_data *sta_iter_data = data;
2833 	struct rtw_vif *rtwvif = sta_iter_data->rtwvif;
2834 	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
2835 	struct seq_file *m = sta_iter_data->file;
2836 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
2837 	u8 rssi;
2838 
2839 	if (si->vif != vif)
2840 		return;
2841 
2842 	rssi = ewma_rssi_read(&si->avg_rssi);
2843 	seq_printf(m, "\tPeer %3d\n", si->mac_id);
2844 	seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi);
2845 	seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode);
2846 }
2847 
2848 struct rtw_coex_vif_stat_iter_data {
2849 	struct rtw_dev *rtwdev;
2850 	struct seq_file *file;
2851 };
2852 
2853 static void rtw_coex_vif_stat_iter(void *data, u8 *mac,
2854 				   struct ieee80211_vif *vif)
2855 {
2856 	struct rtw_coex_vif_stat_iter_data *vif_iter_data = data;
2857 	struct rtw_coex_sta_stat_iter_data sta_iter_data;
2858 	struct rtw_dev *rtwdev = vif_iter_data->rtwdev;
2859 	struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
2860 	struct seq_file *m = vif_iter_data->file;
2861 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
2862 
2863 	seq_printf(m, "Iface on Port (%d)\n", rtwvif->port);
2864 	seq_printf(m, "\t%-32s = %d\n",
2865 		   "Beacon interval", bss_conf->beacon_int);
2866 	seq_printf(m, "\t%-32s = %d\n",
2867 		   "Network Type", rtwvif->net_type);
2868 
2869 	sta_iter_data.rtwvif = rtwvif;
2870 	sta_iter_data.file = m;
2871 	rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter,
2872 				&sta_iter_data);
2873 }
2874 
2875 void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
2876 {
2877 	struct rtw_chip_info *chip = rtwdev->chip;
2878 	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
2879 	struct rtw_coex *coex = &rtwdev->coex;
2880 	struct rtw_coex_stat *coex_stat = &coex->stat;
2881 	struct rtw_coex_dm *coex_dm = &coex->dm;
2882 	struct rtw_hal *hal = &rtwdev->hal;
2883 	struct rtw_efuse *efuse = &rtwdev->efuse;
2884 	struct rtw_fw_state *fw = &rtwdev->fw;
2885 	struct rtw_coex_vif_stat_iter_data vif_iter_data;
2886 	u8 reason = coex_dm->reason;
2887 	u8 sys_lte;
2888 	u16 score_board_WB, score_board_BW;
2889 	u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
2890 	u32 lte_coex, bt_coex;
2891 	u32 bt_hi_pri, bt_lo_pri;
2892 	int i;
2893 
2894 	score_board_BW = rtw_coex_read_scbd(rtwdev);
2895 	score_board_WB = coex_stat->score_board;
2896 	wl_reg_6c0 = rtw_read32(rtwdev, 0x6c0);
2897 	wl_reg_6c4 = rtw_read32(rtwdev, 0x6c4);
2898 	wl_reg_6c8 = rtw_read32(rtwdev, 0x6c8);
2899 	wl_reg_6cc = rtw_read32(rtwdev, 0x6cc);
2900 	wl_reg_778 = rtw_read32(rtwdev, 0x778);
2901 	bt_hi_pri = rtw_read32(rtwdev, 0x770);
2902 	bt_lo_pri = rtw_read32(rtwdev, 0x774);
2903 	rtw_write8(rtwdev, 0x76e, 0xc);
2904 	sys_lte = rtw_read8(rtwdev, 0x73);
2905 	lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
2906 	bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
2907 
2908 	if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
2909 		rtw_coex_get_bt_supported_version(rtwdev,
2910 				&coex_stat->bt_supported_version);
2911 		rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);
2912 		rtw_coex_get_bt_supported_feature(rtwdev,
2913 				&coex_stat->bt_supported_feature);
2914 		rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae);
2915 		rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac);
2916 
2917 		if (coex_stat->patch_ver != 0)
2918 			coex_stat->bt_mailbox_reply = true;
2919 	}
2920 
2921 	seq_printf(m, "**********************************************\n");
2922 	seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);
2923 	seq_printf(m, "**********************************************\n");
2924 	seq_printf(m, "%-40s = %s/ %d\n",
2925 		   "Mech/ RFE",
2926 		   efuse->share_ant ? "Shared" : "Non-Shared",
2927 		   efuse->rfe_option);
2928 	seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",
2929 		   "Coex Ver/ BT Dez/ BT Rpt",
2930 		   chip->coex_para_ver, chip->bt_desired_ver,
2931 		   coex_stat->bt_supported_version,
2932 		   coex_stat->bt_disabled ? "(BT disabled)" :
2933 		   coex_stat->bt_supported_version >= chip->bt_desired_ver ?
2934 		   "(Match)" : "(Mismatch)");
2935 	seq_printf(m, "%-40s = %s/ %u/ %d\n",
2936 		   "Role/ RoleSwCnt/ IgnWL/ Feature",
2937 		   coex_stat->bt_slave ? "Slave" : "Master",
2938 		   coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],
2939 		   coex_dm->ignore_wl_act);
2940 	seq_printf(m, "%-40s = %u.%u/ 0x%x/ %c\n",
2941 		   "WL FW/ BT FW/ KT",
2942 		   fw->version, fw->sub_version,
2943 		   coex_stat->patch_ver, coex_stat->kt_ver + 65);
2944 	seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
2945 		   "AFH Map",
2946 		   coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],
2947 		   coex_dm->wl_ch_info[2], hal->current_channel);
2948 
2949 	seq_printf(m, "**********************************************\n");
2950 	seq_printf(m, "\t\tBT Status\n");
2951 	seq_printf(m, "**********************************************\n");
2952 	seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n",
2953 		   "BT status/ rssi/ retry/ pop",
2954 		   coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" :
2955 		   coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy",
2956 		   coex_stat->bt_rssi - 100,
2957 		   coex_stat->cnt_bt[COEX_CNT_BT_RETRY],
2958 		   coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]);
2959 	seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n",
2960 		   "Profiles",
2961 		   coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ?
2962 					       "A2DP sink," : "A2DP,") : "",
2963 		   coex_stat->bt_hfp_exist ? "HFP," : "",
2964 		   coex_stat->bt_hid_exist ?
2965 		   (coex_stat->bt_ble_exist ? "HID(RCU)," :
2966 		    coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :
2967 		    "HID(2/18),") : "",
2968 		   coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?
2969 		   "OPP," : "PAN," : "",
2970 		   coex_stat->bt_ble_voice ? "Voice," : "",
2971 		   coex_stat->bt_multi_link);
2972 	seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n",
2973 		   "Reinit/ Relink/ IgnWl/ Feature",
2974 		   coex_stat->cnt_bt[COEX_CNT_BT_REINIT],
2975 		   coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK],
2976 		   coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT],
2977 		   coex_stat->bt_supported_feature);
2978 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
2979 		   "Page/ Inq/ iqk/ iqk fail",
2980 		   coex_stat->cnt_bt[COEX_CNT_BT_PAGE],
2981 		   coex_stat->cnt_bt[COEX_CNT_BT_INQ],
2982 		   coex_stat->cnt_bt[COEX_CNT_BT_IQK],
2983 		   coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]);
2984 	seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",
2985 		   "0xae/ 0xac/ score board (W->B)/ (B->W)",
2986 		   coex_stat->bt_reg_vendor_ae,
2987 		   coex_stat->bt_reg_vendor_ac,
2988 		   score_board_WB, score_board_BW);
2989 	seq_printf(m, "%-40s = %u/%u, %u/%u\n",
2990 		   "Hi-Pri TX/RX, Lo-Pri TX/RX",
2991 		   bt_hi_pri & 0xffff, bt_hi_pri >> 16,
2992 		   bt_lo_pri & 0xffff, bt_lo_pri >> 16);
2993 	for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)
2994 		seq_printf(m, "%-40s = %7ph\n",
2995 			   rtw_coex_get_bt_info_src_string(i),
2996 			   coex_stat->bt_info_c2h[i]);
2997 
2998 	seq_printf(m, "**********************************************\n");
2999 	seq_printf(m, "\t\tWiFi Status\n");
3000 	seq_printf(m, "**********************************************\n");
3001 	seq_printf(m, "%-40s = %d\n",
3002 		   "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags));
3003 	seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",
3004 		   "G_busy/ TX/ RX",
3005 		   coex_stat->wl_gl_busy,
3006 		   rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
3007 	seq_printf(m, "%-40s = %u/ %u/ %u\n",
3008 		   "IPS/ Low Power/ PS mode",
3009 		   test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags),
3010 		   test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
3011 		   rtwdev->lps_conf.mode);
3012 
3013 	vif_iter_data.rtwdev = rtwdev;
3014 	vif_iter_data.file = m;
3015 	rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);
3016 
3017 	seq_printf(m, "**********************************************\n");
3018 	seq_printf(m, "\t\tMechanism\n");
3019 	seq_printf(m, "**********************************************\n");
3020 	seq_printf(m, "%-40s = %5ph (case-%d)\n",
3021 		   "TDMA",
3022 		   coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
3023 	seq_printf(m, "%-40s = %d\n",
3024 		   "Timer base", coex_stat->tdma_timer_base);
3025 	seq_printf(m, "%-40s = %d/ 0x%08x/ 0x%08x/ 0x%08x\n",
3026 		   "Table/ 0x6c0/ 0x6c4/ 0x6c8",
3027 		   coex_dm->cur_table, wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
3028 	seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ reason (%s)\n",
3029 		   "0x778/ 0x6cc/ Reason",
3030 		   wl_reg_778, wl_reg_6cc, rtw_coex_get_reason_string(reason));
3031 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",
3032 		   "Null All/ Retry/ Ack/ BT Empty/ BT Late",
3033 		   coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],
3034 		   coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4],
3035 		   coex_stat->wl_fw_dbg_info[5]);
3036 	seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n",
3037 		   "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",
3038 		   coex_stat->wl_fw_dbg_info[6],
3039 		   coex_stat->wl_fw_dbg_info[7],
3040 		   coex_stat->wl_slot_extend ? "Yes" : "No",
3041 		   coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);
3042 
3043 	seq_printf(m, "**********************************************\n");
3044 	seq_printf(m, "\t\tHW setting\n");
3045 	seq_printf(m, "**********************************************\n");
3046 	seq_printf(m, "%-40s = %s/ %s\n",
3047 		   "LTE Coex/ Path Owner",
3048 		   lte_coex & BIT(7) ? "ON" : "OFF",
3049 		   sys_lte & BIT(2) ? "WL" : "BT");
3050 	seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",
3051 		   "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",
3052 		   lte_coex & BIT(12) ? "SW" : "HW",
3053 		   lte_coex & BIT(8) ? "SW" : "HW",
3054 		   lte_coex & BIT(14) ? "SW" : "HW",
3055 		   lte_coex & BIT(10) ? "SW" : "HW",
3056 		   sys_lte & BIT(3) ? "On" : "Off");
3057 	seq_printf(m, "%-40s = %lu/ %lu\n",
3058 		   "GNT_WL/ GNT_BT",
3059 		   (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3);
3060 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3061 		   "CRC OK CCK/ OFDM/ HT/ VHT",
3062 		   dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
3063 		   dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
3064 	seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3065 		   "CRC ERR CCK/ OFDM/ HT/ VHT",
3066 		   dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
3067 		   dm_info->ht_err_cnt, dm_info->vht_err_cnt);
3068 	seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n",
3069 		   "HiPr/ Locking/ Locked/ Noisy",
3070 		   coex_stat->wl_hi_pri_task1 ? "Y" : "N",
3071 		   coex_stat->wl_cck_lock ? "Y" : "N",
3072 		   coex_stat->wl_cck_lock_ever ? "Y" : "N",
3073 		   coex_stat->wl_noisy_level);
3074 
3075 	rtw_coex_set_coexinfo_hw(rtwdev, m);
3076 }
3077 #endif /* CONFIG_RTW88_DEBUGFS */
3078