brintos

brintos / linux-shallow public Read only

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