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