162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 262306a36Sopenharmony_ci/* Copyright(c) 2018-2019 Realtek Corporation 362306a36Sopenharmony_ci */ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include "main.h" 662306a36Sopenharmony_ci#include "coex.h" 762306a36Sopenharmony_ci#include "fw.h" 862306a36Sopenharmony_ci#include "ps.h" 962306a36Sopenharmony_ci#include "debug.h" 1062306a36Sopenharmony_ci#include "reg.h" 1162306a36Sopenharmony_ci#include "phy.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state, 1462306a36Sopenharmony_ci u8 rssi, u8 rssi_thresh) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 1762306a36Sopenharmony_ci u8 tol = chip->rssi_tolerance; 1862306a36Sopenharmony_ci u8 next_state; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci if (pre_state == COEX_RSSI_STATE_LOW || 2162306a36Sopenharmony_ci pre_state == COEX_RSSI_STATE_STAY_LOW) { 2262306a36Sopenharmony_ci if (rssi >= (rssi_thresh + tol)) 2362306a36Sopenharmony_ci next_state = COEX_RSSI_STATE_HIGH; 2462306a36Sopenharmony_ci else 2562306a36Sopenharmony_ci next_state = COEX_RSSI_STATE_STAY_LOW; 2662306a36Sopenharmony_ci } else { 2762306a36Sopenharmony_ci if (rssi < rssi_thresh) 2862306a36Sopenharmony_ci next_state = COEX_RSSI_STATE_LOW; 2962306a36Sopenharmony_ci else 3062306a36Sopenharmony_ci next_state = COEX_RSSI_STATE_STAY_HIGH; 3162306a36Sopenharmony_ci } 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci return next_state; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic void rtw_coex_limited_tx(struct rtw_dev *rtwdev, 3762306a36Sopenharmony_ci bool tx_limit_en, bool ampdu_limit_en) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 4062306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 4162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 4262306a36Sopenharmony_ci u8 num_of_active_port = 1; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci if (!chip->scbd_support) 4562306a36Sopenharmony_ci return; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci /* force max tx retry limit = 8 */ 4862306a36Sopenharmony_ci if (coex_stat->wl_tx_limit_en == tx_limit_en && 4962306a36Sopenharmony_ci coex_stat->wl_ampdu_limit_en == ampdu_limit_en) 5062306a36Sopenharmony_ci return; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci if (!coex_stat->wl_tx_limit_en) { 5362306a36Sopenharmony_ci coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC); 5462306a36Sopenharmony_ci coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH); 5562306a36Sopenharmony_ci coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT); 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci if (!coex_stat->wl_ampdu_limit_en) 5962306a36Sopenharmony_ci coex_stat->ampdu_max_time = 6062306a36Sopenharmony_ci rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci coex_stat->wl_tx_limit_en = tx_limit_en; 6362306a36Sopenharmony_ci coex_stat->wl_ampdu_limit_en = ampdu_limit_en; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (tx_limit_en) { 6662306a36Sopenharmony_ci /* set BT polluted packet on for tx rate adaptive, 6762306a36Sopenharmony_ci * not including tx retry broken by PTA 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_ci rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* set queue life time to avoid can't reach tx retry limit 7262306a36Sopenharmony_ci * if tx is always broken by GNT_BT 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_ci if (num_of_active_port <= 1) 7562306a36Sopenharmony_ci rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf); 7662306a36Sopenharmony_ci rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* auto rate fallback step within 8 retries */ 7962306a36Sopenharmony_ci rtw_write32(rtwdev, REG_DARFRC, 0x1000000); 8062306a36Sopenharmony_ci rtw_write32(rtwdev, REG_DARFRCH, 0x4030201); 8162306a36Sopenharmony_ci } else { 8262306a36Sopenharmony_ci rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE); 8362306a36Sopenharmony_ci rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit); 8662306a36Sopenharmony_ci rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc); 8762306a36Sopenharmony_ci rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch); 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci if (ampdu_limit_en) 9162306a36Sopenharmony_ci rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20); 9262306a36Sopenharmony_ci else 9362306a36Sopenharmony_ci rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 9462306a36Sopenharmony_ci coex_stat->ampdu_max_time); 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void rtw_coex_limited_wl(struct rtw_dev *rtwdev) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 10062306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 10162306a36Sopenharmony_ci bool tx_limit = false; 10262306a36Sopenharmony_ci bool tx_agg_ctrl = false; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (!coex->under_5g && coex_dm->bt_status != COEX_BTSTATUS_NCON_IDLE) { 10562306a36Sopenharmony_ci tx_limit = true; 10662306a36Sopenharmony_ci tx_agg_ctrl = true; 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic bool rtw_coex_freerun_check(struct rtw_dev *rtwdev) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 11562306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 11662306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 11762306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 11862306a36Sopenharmony_ci u8 bt_rssi; 11962306a36Sopenharmony_ci u8 ant_distance = 10; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (coex_stat->bt_disabled) 12262306a36Sopenharmony_ci return false; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (efuse->share_ant || ant_distance <= 5 || !coex_stat->wl_gl_busy) 12562306a36Sopenharmony_ci return false; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (ant_distance >= 40 || coex_stat->bt_hid_pair_num >= 2) 12862306a36Sopenharmony_ci return true; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* ant_distance = 5 ~ 40 */ 13162306a36Sopenharmony_ci if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]) && 13262306a36Sopenharmony_ci COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) 13362306a36Sopenharmony_ci return true; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) 13662306a36Sopenharmony_ci bt_rssi = coex_dm->bt_rssi_state[0]; 13762306a36Sopenharmony_ci else 13862306a36Sopenharmony_ci bt_rssi = coex_dm->bt_rssi_state[1]; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && 14162306a36Sopenharmony_ci COEX_RSSI_HIGH(bt_rssi) && 14262306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5) 14362306a36Sopenharmony_ci return true; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci return false; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic void rtw_coex_wl_slot_extend(struct rtw_dev *rtwdev, bool enable) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 15162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 15262306a36Sopenharmony_ci u8 para[6] = {0}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci para[0] = COEX_H2C69_WL_LEAKAP; 15562306a36Sopenharmony_ci para[1] = PARA1_H2C69_DIS_5MS; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci if (enable) 15862306a36Sopenharmony_ci para[1] = PARA1_H2C69_EN_5MS; 15962306a36Sopenharmony_ci else 16062306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci coex_stat->wl_slot_extend = enable; 16362306a36Sopenharmony_ci rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 16462306a36Sopenharmony_ci} 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cistatic void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 16962306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci if (coex->manual_control || coex->stop_dm) 17262306a36Sopenharmony_ci return; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) { 17662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 17762306a36Sopenharmony_ci "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n"); 17862306a36Sopenharmony_ci rtw_coex_wl_slot_extend(rtwdev, false); 17962306a36Sopenharmony_ci return; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl && 18362306a36Sopenharmony_ci !coex_stat->wl_cck_lock_ever) { 18462306a36Sopenharmony_ci if (coex_stat->wl_fw_dbg_info[7] <= 5) 18562306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++; 18662306a36Sopenharmony_ci else 18762306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 19062306a36Sopenharmony_ci "[BTCoex], 5ms WL slot extend cnt = %d!!\n", 19162306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) { 19462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 19562306a36Sopenharmony_ci "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n"); 19662306a36Sopenharmony_ci rtw_coex_wl_slot_extend(rtwdev, false); 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) { 19962306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 20062306a36Sopenharmony_ci "[BTCoex], set h2c 0x69 opcode 12 to turn on 5ms WL slot extend!!\n"); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci rtw_coex_wl_slot_extend(rtwdev, true); 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 20962306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 21062306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci bool is_cck_lock_rate = false; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci if (coex_stat->wl_coex_mode != COEX_WLINK_2G1PORT && 21562306a36Sopenharmony_ci coex_stat->wl_coex_mode != COEX_WLINK_2GFREE) 21662306a36Sopenharmony_ci return; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci if (coex_dm->bt_status == COEX_BTSTATUS_INQ_PAGE || 21962306a36Sopenharmony_ci coex_stat->bt_setup_link) { 22062306a36Sopenharmony_ci coex_stat->wl_cck_lock = false; 22162306a36Sopenharmony_ci coex_stat->wl_cck_lock_pre = false; 22262306a36Sopenharmony_ci return; 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci if (coex_stat->wl_rx_rate <= COEX_CCK_2 || 22662306a36Sopenharmony_ci coex_stat->wl_rts_rx_rate <= COEX_CCK_2) 22762306a36Sopenharmony_ci is_cck_lock_rate = true; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci if (coex_stat->wl_connected && coex_stat->wl_gl_busy && 23062306a36Sopenharmony_ci COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && 23162306a36Sopenharmony_ci (coex_dm->bt_status == COEX_BTSTATUS_ACL_BUSY || 23262306a36Sopenharmony_ci coex_dm->bt_status == COEX_BTSTATUS_ACL_SCO_BUSY || 23362306a36Sopenharmony_ci coex_dm->bt_status == COEX_BTSTATUS_SCO_BUSY)) { 23462306a36Sopenharmony_ci if (is_cck_lock_rate) { 23562306a36Sopenharmony_ci coex_stat->wl_cck_lock = true; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 23862306a36Sopenharmony_ci "[BTCoex], cck locking...\n"); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci } else { 24162306a36Sopenharmony_ci coex_stat->wl_cck_lock = false; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 24462306a36Sopenharmony_ci "[BTCoex], cck unlock...\n"); 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci } else { 24762306a36Sopenharmony_ci coex_stat->wl_cck_lock = false; 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* CCK lock identification */ 25162306a36Sopenharmony_ci if (coex_stat->wl_cck_lock && !coex_stat->wl_cck_lock_pre) 25262306a36Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, &coex->wl_ccklock_work, 25362306a36Sopenharmony_ci 3 * HZ); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci coex_stat->wl_cck_lock_pre = coex_stat->wl_cck_lock; 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev) 25962306a36Sopenharmony_ci{ 26062306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 26162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 26262306a36Sopenharmony_ci struct rtw_dm_info *dm_info = &rtwdev->dm_info; 26362306a36Sopenharmony_ci u32 cnt_cck; 26462306a36Sopenharmony_ci bool wl_cck_lock = false; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* wifi noisy environment identification */ 26762306a36Sopenharmony_ci cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci if (!coex_stat->wl_gl_busy && !wl_cck_lock) { 27062306a36Sopenharmony_ci if (cnt_cck > 250) { 27162306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5) 27262306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) { 27562306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0; 27662306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci } else if (cnt_cck < 100) { 27962306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5) 28062306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) { 28362306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0; 28462306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci } else { 28762306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5) 28862306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) { 29162306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0; 29262306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0; 29362306a36Sopenharmony_ci } 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) 29762306a36Sopenharmony_ci coex_stat->wl_noisy_level = 2; 29862306a36Sopenharmony_ci else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) 29962306a36Sopenharmony_ci coex_stat->wl_noisy_level = 1; 30062306a36Sopenharmony_ci else 30162306a36Sopenharmony_ci coex_stat->wl_noisy_level = 0; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wl_noisy_level = %d\n", 30462306a36Sopenharmony_ci coex_stat->wl_noisy_level); 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 31162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 31262306a36Sopenharmony_ci u8 para[2] = {0}; 31362306a36Sopenharmony_ci u8 times; 31462306a36Sopenharmony_ci u16 tbtt_interval = coex_stat->wl_beacon_interval; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (coex_stat->tdma_timer_base == type) 31762306a36Sopenharmony_ci return; 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci coex_stat->tdma_timer_base = type; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci para[0] = COEX_H2C69_TDMA_SLOT; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], tbtt_interval = %d\n", 32462306a36Sopenharmony_ci tbtt_interval); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (type == TDMA_TIMER_TYPE_4SLOT && tbtt_interval < 120) { 32762306a36Sopenharmony_ci para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */ 32862306a36Sopenharmony_ci } else if (tbtt_interval < 80 && tbtt_interval > 0) { 32962306a36Sopenharmony_ci times = 100 / tbtt_interval; 33062306a36Sopenharmony_ci if (100 % tbtt_interval != 0) 33162306a36Sopenharmony_ci times++; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times); 33462306a36Sopenharmony_ci } else if (tbtt_interval >= 180) { 33562306a36Sopenharmony_ci times = tbtt_interval / 100; 33662306a36Sopenharmony_ci if (tbtt_interval % 100 <= 80) 33762306a36Sopenharmony_ci times--; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times) | 34062306a36Sopenharmony_ci FIELD_PREP(PARA1_H2C69_TBTT_DIV100, 1); 34162306a36Sopenharmony_ci } else { 34262306a36Sopenharmony_ci para[1] = PARA1_H2C69_TDMA_2SLOT; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): h2c_0x69 = 0x%x\n", 34862306a36Sopenharmony_ci __func__, para[1]); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* no 5ms_wl_slot_extend for 4-slot mode */ 35162306a36Sopenharmony_ci if (coex_stat->tdma_timer_base == 3) 35262306a36Sopenharmony_ci rtw_coex_wl_ccklock_action(rtwdev); 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap, 35662306a36Sopenharmony_ci u8 data) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci u32 addr; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci addr = REG_BT_COEX_TABLE_H + (bitmap / 8); 36162306a36Sopenharmony_ci bitmap = bitmap % 8; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci rtw_write8_mask(rtwdev, addr, BIT(bitmap), data); 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_civoid rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set) 36762306a36Sopenharmony_ci{ 36862306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 36962306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 37062306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 37162306a36Sopenharmony_ci u16 val = 0x2; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if (!chip->scbd_support) 37462306a36Sopenharmony_ci return; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci val |= coex_stat->score_board; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci /* for 8822b, scbd[10] is CQDDR on 37962306a36Sopenharmony_ci * for 8822c, scbd[10] is no fix 2M 38062306a36Sopenharmony_ci */ 38162306a36Sopenharmony_ci if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) { 38262306a36Sopenharmony_ci if (set) 38362306a36Sopenharmony_ci val &= ~COEX_SCBD_FIX2M; 38462306a36Sopenharmony_ci else 38562306a36Sopenharmony_ci val |= COEX_SCBD_FIX2M; 38662306a36Sopenharmony_ci } else { 38762306a36Sopenharmony_ci if (set) 38862306a36Sopenharmony_ci val |= bitpos; 38962306a36Sopenharmony_ci else 39062306a36Sopenharmony_ci val &= ~bitpos; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci if (val != coex_stat->score_board) { 39462306a36Sopenharmony_ci coex_stat->score_board = val; 39562306a36Sopenharmony_ci val |= BIT_BT_INT_EN; 39662306a36Sopenharmony_ci rtw_write16(rtwdev, REG_WIFI_BT_INFO, val); 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_coex_write_scbd); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (!chip->scbd_support) 40662306a36Sopenharmony_ci return 0; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN); 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic void rtw_coex_check_rfk(struct rtw_dev *rtwdev) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 41462306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 41562306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 41662306a36Sopenharmony_ci struct rtw_coex_rfe *coex_rfe = &coex->rfe; 41762306a36Sopenharmony_ci u8 cnt = 0; 41862306a36Sopenharmony_ci u32 wait_cnt; 41962306a36Sopenharmony_ci bool btk, wlk; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci if (coex_rfe->wlg_at_btg && chip->scbd_support && 42262306a36Sopenharmony_ci coex_stat->bt_iqk_state != 0xff) { 42362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 42462306a36Sopenharmony_ci "[BTCoex], (Before Ant Setup) Delay by IQK\n"); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY; 42762306a36Sopenharmony_ci do { 42862306a36Sopenharmony_ci /* BT RFK */ 42962306a36Sopenharmony_ci btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci /* WL RFK */ 43262306a36Sopenharmony_ci wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci if (!btk && !wlk) 43562306a36Sopenharmony_ci break; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 43862306a36Sopenharmony_ci "[BTCoex], (Before Ant Setup) wlk = %d, btk = %d\n", 43962306a36Sopenharmony_ci wlk, btk); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci mdelay(COEX_MIN_DELAY); 44262306a36Sopenharmony_ci } while (++cnt < wait_cnt); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (cnt >= wait_cnt) 44562306a36Sopenharmony_ci coex_stat->bt_iqk_state = 0xff; 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic void rtw_coex_query_bt_info(struct rtw_dev *rtwdev) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 45262306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (coex_stat->bt_disabled) 45562306a36Sopenharmony_ci return; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci rtw_fw_query_bt_info(rtwdev); 46062306a36Sopenharmony_ci} 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_cistatic void rtw_coex_gnt_workaround(struct rtw_dev *rtwdev, bool force, u8 mode) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci rtw_coex_set_gnt_fix(rtwdev); 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic void rtw_coex_monitor_bt_ctr(struct rtw_dev *rtwdev) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 47062306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 47162306a36Sopenharmony_ci u32 tmp; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS); 47462306a36Sopenharmony_ci coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, tmp); 47562306a36Sopenharmony_ci coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, tmp); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1); 47862306a36Sopenharmony_ci coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, tmp); 47962306a36Sopenharmony_ci coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, tmp); 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL, 48262306a36Sopenharmony_ci BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN); 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 48562306a36Sopenharmony_ci "[BTCoex], Hi-Pri Rx/Tx: %d/%d, Lo-Pri Rx/Tx: %d/%d\n", 48662306a36Sopenharmony_ci coex_stat->hi_pri_rx, coex_stat->hi_pri_tx, 48762306a36Sopenharmony_ci coex_stat->lo_pri_rx, coex_stat->lo_pri_tx); 48862306a36Sopenharmony_ci} 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cistatic void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev) 49162306a36Sopenharmony_ci{ 49262306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 49362306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 49462306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 49562306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 49662306a36Sopenharmony_ci bool bt_disabled = false; 49762306a36Sopenharmony_ci u16 score_board; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci if (chip->scbd_support) { 50062306a36Sopenharmony_ci score_board = rtw_coex_read_scbd(rtwdev); 50162306a36Sopenharmony_ci bt_disabled = !(score_board & COEX_SCBD_ONOFF); 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci if (coex_stat->bt_disabled != bt_disabled) { 50562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 50662306a36Sopenharmony_ci "[BTCoex], BT state changed (%d) -> (%d)\n", 50762306a36Sopenharmony_ci coex_stat->bt_disabled, bt_disabled); 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci coex_stat->bt_disabled = bt_disabled; 51062306a36Sopenharmony_ci coex_stat->bt_ble_scan_type = 0; 51162306a36Sopenharmony_ci coex_dm->cur_bt_lna_lvl = 0; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci if (!coex_stat->bt_disabled) { 51462306a36Sopenharmony_ci coex_stat->bt_reenable = true; 51562306a36Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, 51662306a36Sopenharmony_ci &coex->bt_reenable_work, 51762306a36Sopenharmony_ci 15 * HZ); 51862306a36Sopenharmony_ci } else { 51962306a36Sopenharmony_ci coex_stat->bt_mailbox_reply = false; 52062306a36Sopenharmony_ci coex_stat->bt_reenable = false; 52162306a36Sopenharmony_ci } 52262306a36Sopenharmony_ci } 52362306a36Sopenharmony_ci} 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_cistatic void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason) 52662306a36Sopenharmony_ci{ 52762306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 52862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 52962306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 53062306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 53162306a36Sopenharmony_ci struct rtw_traffic_stats *stats = &rtwdev->stats; 53262306a36Sopenharmony_ci bool is_5G = false; 53362306a36Sopenharmony_ci bool wl_busy = false; 53462306a36Sopenharmony_ci bool scan = false, link = false; 53562306a36Sopenharmony_ci int i; 53662306a36Sopenharmony_ci u8 rssi_state; 53762306a36Sopenharmony_ci u8 rssi_step; 53862306a36Sopenharmony_ci u8 rssi; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags); 54162306a36Sopenharmony_ci coex_stat->wl_connected = !!rtwdev->sta_cnt; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); 54462306a36Sopenharmony_ci if (wl_busy != coex_stat->wl_gl_busy) { 54562306a36Sopenharmony_ci if (wl_busy) 54662306a36Sopenharmony_ci coex_stat->wl_gl_busy = true; 54762306a36Sopenharmony_ci else 54862306a36Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, 54962306a36Sopenharmony_ci &coex->wl_remain_work, 55062306a36Sopenharmony_ci 12 * HZ); 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci if (stats->tx_throughput > stats->rx_throughput) 55462306a36Sopenharmony_ci coex_stat->wl_tput_dir = COEX_WL_TPUT_TX; 55562306a36Sopenharmony_ci else 55662306a36Sopenharmony_ci coex_stat->wl_tput_dir = COEX_WL_TPUT_RX; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci if (scan || link || reason == COEX_RSN_2GCONSTART || 55962306a36Sopenharmony_ci reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND) 56062306a36Sopenharmony_ci coex_stat->wl_linkscan_proc = true; 56162306a36Sopenharmony_ci else 56262306a36Sopenharmony_ci coex_stat->wl_linkscan_proc = false; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci rtw_coex_wl_noisy_detect(rtwdev); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 56762306a36Sopenharmony_ci rssi_state = coex_dm->wl_rssi_state[i]; 56862306a36Sopenharmony_ci rssi_step = chip->wl_rssi_step[i]; 56962306a36Sopenharmony_ci rssi = rtwdev->dm_info.min_rssi; 57062306a36Sopenharmony_ci rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, 57162306a36Sopenharmony_ci rssi, rssi_step); 57262306a36Sopenharmony_ci coex_dm->wl_rssi_state[i] = rssi_state; 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 || 57662306a36Sopenharmony_ci coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy) 57762306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true); 57862306a36Sopenharmony_ci else 57962306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci switch (reason) { 58262306a36Sopenharmony_ci case COEX_RSN_5GSCANSTART: 58362306a36Sopenharmony_ci case COEX_RSN_5GSWITCHBAND: 58462306a36Sopenharmony_ci case COEX_RSN_5GCONSTART: 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci is_5G = true; 58762306a36Sopenharmony_ci break; 58862306a36Sopenharmony_ci case COEX_RSN_2GSCANSTART: 58962306a36Sopenharmony_ci case COEX_RSN_2GSWITCHBAND: 59062306a36Sopenharmony_ci case COEX_RSN_2GCONSTART: 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci is_5G = false; 59362306a36Sopenharmony_ci break; 59462306a36Sopenharmony_ci default: 59562306a36Sopenharmony_ci if (rtwdev->hal.current_band_type == RTW_BAND_5G) 59662306a36Sopenharmony_ci is_5G = true; 59762306a36Sopenharmony_ci else 59862306a36Sopenharmony_ci is_5G = false; 59962306a36Sopenharmony_ci break; 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci coex->under_5g = is_5G; 60362306a36Sopenharmony_ci} 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_cistatic inline u8 *get_payload_from_coex_resp(struct sk_buff *resp) 60662306a36Sopenharmony_ci{ 60762306a36Sopenharmony_ci struct rtw_c2h_cmd *c2h; 60862306a36Sopenharmony_ci u32 pkt_offset; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci pkt_offset = *((u32 *)resp->cb); 61162306a36Sopenharmony_ci c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci return c2h->payload; 61462306a36Sopenharmony_ci} 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_civoid rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 61962306a36Sopenharmony_ci u8 *payload = get_payload_from_coex_resp(skb); 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci if (payload[0] != COEX_RESP_ACK_BY_WL_FW) { 62262306a36Sopenharmony_ci dev_kfree_skb_any(skb); 62362306a36Sopenharmony_ci return; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci skb_queue_tail(&coex->queue, skb); 62762306a36Sopenharmony_ci wake_up(&coex->wait); 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_cistatic struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev, 63162306a36Sopenharmony_ci struct rtw_coex_info_req *req) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 63462306a36Sopenharmony_ci struct sk_buff *skb_resp = NULL; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci lockdep_assert_held(&rtwdev->mutex); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci rtw_fw_query_bt_mp_info(rtwdev, req); 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue), 64162306a36Sopenharmony_ci COEX_REQUEST_TIMEOUT)) { 64262306a36Sopenharmony_ci rtw_err(rtwdev, "coex request time out\n"); 64362306a36Sopenharmony_ci goto out; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci skb_resp = skb_dequeue(&coex->queue); 64762306a36Sopenharmony_ci if (!skb_resp) { 64862306a36Sopenharmony_ci rtw_err(rtwdev, "failed to get coex info response\n"); 64962306a36Sopenharmony_ci goto out; 65062306a36Sopenharmony_ci } 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ciout: 65362306a36Sopenharmony_ci return skb_resp; 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type) 65762306a36Sopenharmony_ci{ 65862306a36Sopenharmony_ci struct rtw_coex_info_req req = {0}; 65962306a36Sopenharmony_ci struct sk_buff *skb; 66062306a36Sopenharmony_ci u8 *payload; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci req.op_code = BT_MP_INFO_OP_SCAN_TYPE; 66362306a36Sopenharmony_ci skb = rtw_coex_info_request(rtwdev, &req); 66462306a36Sopenharmony_ci if (!skb) 66562306a36Sopenharmony_ci return false; 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci payload = get_payload_from_coex_resp(skb); 66862306a36Sopenharmony_ci *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload); 66962306a36Sopenharmony_ci dev_kfree_skb_any(skb); 67062306a36Sopenharmony_ci return true; 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_cistatic bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev, 67462306a36Sopenharmony_ci u8 lna_constrain_level) 67562306a36Sopenharmony_ci{ 67662306a36Sopenharmony_ci struct rtw_coex_info_req req = {0}; 67762306a36Sopenharmony_ci struct sk_buff *skb; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT; 68062306a36Sopenharmony_ci req.para1 = lna_constrain_level; 68162306a36Sopenharmony_ci skb = rtw_coex_info_request(rtwdev, &req); 68262306a36Sopenharmony_ci if (!skb) 68362306a36Sopenharmony_ci return false; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci dev_kfree_skb_any(skb); 68662306a36Sopenharmony_ci return true; 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci#define case_BTSTATUS(src) \ 69062306a36Sopenharmony_ci case COEX_BTSTATUS_##src: return #src 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic const char *rtw_coex_get_bt_status_string(u8 bt_status) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci switch (bt_status) { 69562306a36Sopenharmony_ci case_BTSTATUS(NCON_IDLE); 69662306a36Sopenharmony_ci case_BTSTATUS(CON_IDLE); 69762306a36Sopenharmony_ci case_BTSTATUS(INQ_PAGE); 69862306a36Sopenharmony_ci case_BTSTATUS(ACL_BUSY); 69962306a36Sopenharmony_ci case_BTSTATUS(SCO_BUSY); 70062306a36Sopenharmony_ci case_BTSTATUS(ACL_SCO_BUSY); 70162306a36Sopenharmony_ci default: 70262306a36Sopenharmony_ci return "Unknown"; 70362306a36Sopenharmony_ci } 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cistatic void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev) 70762306a36Sopenharmony_ci{ 70862306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 70962306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 71062306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 71162306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 71262306a36Sopenharmony_ci u8 i; 71362306a36Sopenharmony_ci u8 rssi_state; 71462306a36Sopenharmony_ci u8 rssi_step; 71562306a36Sopenharmony_ci u8 rssi; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci /* update wl/bt rssi by btinfo */ 71862306a36Sopenharmony_ci for (i = 0; i < COEX_RSSI_STEP; i++) { 71962306a36Sopenharmony_ci rssi_state = coex_dm->bt_rssi_state[i]; 72062306a36Sopenharmony_ci rssi_step = chip->bt_rssi_step[i]; 72162306a36Sopenharmony_ci rssi = coex_stat->bt_rssi; 72262306a36Sopenharmony_ci rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, rssi, 72362306a36Sopenharmony_ci rssi_step); 72462306a36Sopenharmony_ci coex_dm->bt_rssi_state[i] = rssi_state; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci if (coex_stat->bt_ble_scan_en && 72862306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) { 72962306a36Sopenharmony_ci u8 scan_type; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) { 73262306a36Sopenharmony_ci coex_stat->bt_ble_scan_type = scan_type; 73362306a36Sopenharmony_ci if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1) 73462306a36Sopenharmony_ci coex_stat->bt_init_scan = true; 73562306a36Sopenharmony_ci else 73662306a36Sopenharmony_ci coex_stat->bt_init_scan = false; 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci } 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci coex_stat->bt_profile_num = 0; 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci /* set link exist status */ 74362306a36Sopenharmony_ci if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) { 74462306a36Sopenharmony_ci coex_stat->bt_link_exist = false; 74562306a36Sopenharmony_ci coex_stat->bt_pan_exist = false; 74662306a36Sopenharmony_ci coex_stat->bt_a2dp_exist = false; 74762306a36Sopenharmony_ci coex_stat->bt_hid_exist = false; 74862306a36Sopenharmony_ci coex_stat->bt_hfp_exist = false; 74962306a36Sopenharmony_ci } else { 75062306a36Sopenharmony_ci /* connection exists */ 75162306a36Sopenharmony_ci coex_stat->bt_link_exist = true; 75262306a36Sopenharmony_ci if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) { 75362306a36Sopenharmony_ci coex_stat->bt_pan_exist = true; 75462306a36Sopenharmony_ci coex_stat->bt_profile_num++; 75562306a36Sopenharmony_ci } else { 75662306a36Sopenharmony_ci coex_stat->bt_pan_exist = false; 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) { 76062306a36Sopenharmony_ci coex_stat->bt_a2dp_exist = true; 76162306a36Sopenharmony_ci coex_stat->bt_profile_num++; 76262306a36Sopenharmony_ci } else { 76362306a36Sopenharmony_ci coex_stat->bt_a2dp_exist = false; 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci if (coex_stat->bt_info_lb2 & COEX_INFO_HID) { 76762306a36Sopenharmony_ci coex_stat->bt_hid_exist = true; 76862306a36Sopenharmony_ci coex_stat->bt_profile_num++; 76962306a36Sopenharmony_ci } else { 77062306a36Sopenharmony_ci coex_stat->bt_hid_exist = false; 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) { 77462306a36Sopenharmony_ci coex_stat->bt_hfp_exist = true; 77562306a36Sopenharmony_ci coex_stat->bt_profile_num++; 77662306a36Sopenharmony_ci } else { 77762306a36Sopenharmony_ci coex_stat->bt_hfp_exist = false; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) { 78262306a36Sopenharmony_ci coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE; 78362306a36Sopenharmony_ci } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) { 78462306a36Sopenharmony_ci coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE; 78562306a36Sopenharmony_ci coex_stat->bt_multi_link_remain = false; 78662306a36Sopenharmony_ci } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) { 78762306a36Sopenharmony_ci coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE; 78862306a36Sopenharmony_ci } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) || 78962306a36Sopenharmony_ci (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) { 79062306a36Sopenharmony_ci if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) 79162306a36Sopenharmony_ci coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY; 79262306a36Sopenharmony_ci else 79362306a36Sopenharmony_ci coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY; 79462306a36Sopenharmony_ci } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) { 79562306a36Sopenharmony_ci coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY; 79662306a36Sopenharmony_ci } else { 79762306a36Sopenharmony_ci coex_dm->bt_status = COEX_BTSTATUS_MAX; 79862306a36Sopenharmony_ci } 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(), %s!!!\n", __func__, 80362306a36Sopenharmony_ci rtw_coex_get_bt_status_string(coex_dm->bt_status)); 80462306a36Sopenharmony_ci} 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_cistatic void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type) 80762306a36Sopenharmony_ci{ 80862306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 80962306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 81062306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm; 81162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 81262306a36Sopenharmony_ci u8 link = 0; 81362306a36Sopenharmony_ci u8 center_chan = 0; 81462306a36Sopenharmony_ci u8 bw; 81562306a36Sopenharmony_ci int i; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci bw = rtwdev->hal.current_band_width; 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci if (type != COEX_MEDIA_DISCONNECT) 82062306a36Sopenharmony_ci center_chan = rtwdev->hal.current_channel; 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci if (center_chan == 0 || 82362306a36Sopenharmony_ci (efuse->share_ant && center_chan <= 14 && 82462306a36Sopenharmony_ci coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)) { 82562306a36Sopenharmony_ci link = 0; 82662306a36Sopenharmony_ci center_chan = 0; 82762306a36Sopenharmony_ci bw = 0; 82862306a36Sopenharmony_ci } else if (center_chan <= 14) { 82962306a36Sopenharmony_ci link = 0x1; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci if (bw == RTW_CHANNEL_WIDTH_40) 83262306a36Sopenharmony_ci bw = chip->bt_afh_span_bw40; 83362306a36Sopenharmony_ci else 83462306a36Sopenharmony_ci bw = chip->bt_afh_span_bw20; 83562306a36Sopenharmony_ci } else if (chip->afh_5g_num > 1) { 83662306a36Sopenharmony_ci for (i = 0; i < chip->afh_5g_num; i++) { 83762306a36Sopenharmony_ci if (center_chan == chip->afh_5g[i].wl_5g_ch) { 83862306a36Sopenharmony_ci link = 0x3; 83962306a36Sopenharmony_ci center_chan = chip->afh_5g[i].bt_skip_ch; 84062306a36Sopenharmony_ci bw = chip->afh_5g[i].bt_skip_span; 84162306a36Sopenharmony_ci break; 84262306a36Sopenharmony_ci } 84362306a36Sopenharmony_ci } 84462306a36Sopenharmony_ci } 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci coex_dm->wl_ch_info[0] = link; 84762306a36Sopenharmony_ci coex_dm->wl_ch_info[1] = center_chan; 84862306a36Sopenharmony_ci coex_dm->wl_ch_info[2] = bw; 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw); 85162306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 85262306a36Sopenharmony_ci "[BTCoex], %s: para[0:2] = 0x%x 0x%x 0x%x\n", __func__, link, 85362306a36Sopenharmony_ci center_chan, bw); 85462306a36Sopenharmony_ci} 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_cistatic void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl) 85762306a36Sopenharmony_ci{ 85862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 85962306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl) 86262306a36Sopenharmony_ci return; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl); 86762306a36Sopenharmony_ci} 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_cistatic void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl) 87062306a36Sopenharmony_ci{ 87162306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 87262306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl) 87562306a36Sopenharmony_ci return; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci coex_dm->cur_bt_lna_lvl = bt_lna_lvl; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci /* notify BT rx gain table changed */ 88062306a36Sopenharmony_ci if (bt_lna_lvl < 7) { 88162306a36Sopenharmony_ci rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl); 88262306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true); 88362306a36Sopenharmony_ci } else { 88462306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false); 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): bt_rx_LNA_level = %d\n", 88762306a36Sopenharmony_ci __func__, bt_lna_lvl); 88862306a36Sopenharmony_ci} 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_cistatic void rtw_coex_set_rf_para(struct rtw_dev *rtwdev, 89162306a36Sopenharmony_ci struct coex_rf_para para) 89262306a36Sopenharmony_ci{ 89362306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 89462306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 89562306a36Sopenharmony_ci u8 offset = 0; 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci if (coex->freerun && coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5) 89862306a36Sopenharmony_ci offset = 3; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl); 90162306a36Sopenharmony_ci rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset); 90262306a36Sopenharmony_ci rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en); 90362306a36Sopenharmony_ci rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl); 90462306a36Sopenharmony_ci} 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ciu32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr) 90762306a36Sopenharmony_ci{ 90862306a36Sopenharmony_ci u32 val; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci if (!ltecoex_read_reg(rtwdev, addr, &val)) { 91162306a36Sopenharmony_ci rtw_err(rtwdev, "failed to read indirect register\n"); 91262306a36Sopenharmony_ci return 0; 91362306a36Sopenharmony_ci } 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci return val; 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_coex_read_indirect_reg); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_civoid rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr, 92062306a36Sopenharmony_ci u32 mask, u32 val) 92162306a36Sopenharmony_ci{ 92262306a36Sopenharmony_ci u32 shift = __ffs(mask); 92362306a36Sopenharmony_ci u32 tmp; 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci tmp = rtw_coex_read_indirect_reg(rtwdev, addr); 92662306a36Sopenharmony_ci tmp = (tmp & (~mask)) | ((val << shift) & mask); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (!ltecoex_reg_write(rtwdev, addr, tmp)) 92962306a36Sopenharmony_ci rtw_err(rtwdev, "failed to write indirect register\n"); 93062306a36Sopenharmony_ci} 93162306a36Sopenharmony_ciEXPORT_SYMBOL(rtw_coex_write_indirect_reg); 93262306a36Sopenharmony_ci 93362306a36Sopenharmony_cistatic void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control) 93462306a36Sopenharmony_ci{ 93562306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 93662306a36Sopenharmony_ci const struct rtw_hw_reg *btg_reg = chip->btg_reg; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci if (wifi_control) { 93962306a36Sopenharmony_ci rtw_write8_set(rtwdev, REG_SYS_SDIO_CTRL + 3, 94062306a36Sopenharmony_ci BIT_LTE_MUX_CTRL_PATH >> 24); 94162306a36Sopenharmony_ci if (btg_reg) 94262306a36Sopenharmony_ci rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask); 94362306a36Sopenharmony_ci } else { 94462306a36Sopenharmony_ci rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL + 3, 94562306a36Sopenharmony_ci BIT_LTE_MUX_CTRL_PATH >> 24); 94662306a36Sopenharmony_ci if (btg_reg) 94762306a36Sopenharmony_ci rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask); 94862306a36Sopenharmony_ci } 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistatic void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state); 95462306a36Sopenharmony_ci rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state); 95562306a36Sopenharmony_ci} 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_cistatic void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state) 95862306a36Sopenharmony_ci{ 95962306a36Sopenharmony_ci rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state); 96062306a36Sopenharmony_ci rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state); 96162306a36Sopenharmony_ci} 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_cistatic void rtw_coex_mimo_ps(struct rtw_dev *rtwdev, bool force, bool state) 96462306a36Sopenharmony_ci{ 96562306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci if (!force && state == coex_stat->wl_mimo_ps) 96862306a36Sopenharmony_ci return; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci coex_stat->wl_mimo_ps = state; 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci rtw_set_txrx_1ss(rtwdev, state); 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci rtw_coex_update_wl_ch_info(rtwdev, (u8)coex_stat->wl_connected); 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 97762306a36Sopenharmony_ci "[BTCoex], %s(): state = %d\n", __func__, state); 97862306a36Sopenharmony_ci} 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_cistatic void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force, 98162306a36Sopenharmony_ci u8 table_case) 98262306a36Sopenharmony_ci{ 98362306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 98462306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 98562306a36Sopenharmony_ci u8 h2c_para[6] = {0}; 98662306a36Sopenharmony_ci u32 table_wl = 0x5a5a5a5a; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_A; 98962306a36Sopenharmony_ci /* no definition */ 99062306a36Sopenharmony_ci h2c_para[1] = 0x1; 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci if (efuse->share_ant) { 99362306a36Sopenharmony_ci if (table_case < chip->table_sant_num) 99462306a36Sopenharmony_ci table_wl = chip->table_sant[table_case].wl; 99562306a36Sopenharmony_ci } else { 99662306a36Sopenharmony_ci if (table_case < chip->table_nsant_num) 99762306a36Sopenharmony_ci table_wl = chip->table_nsant[table_case].wl; 99862306a36Sopenharmony_ci } 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci /* tell WL FW WL slot toggle table-A*/ 100162306a36Sopenharmony_ci h2c_para[2] = (u8)u32_get_bits(table_wl, GENMASK(7, 0)); 100262306a36Sopenharmony_ci h2c_para[3] = (u8)u32_get_bits(table_wl, GENMASK(15, 8)); 100362306a36Sopenharmony_ci h2c_para[4] = (u8)u32_get_bits(table_wl, GENMASK(23, 16)); 100462306a36Sopenharmony_ci h2c_para[5] = (u8)u32_get_bits(table_wl, GENMASK(31, 24)); 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci rtw_fw_bt_wifi_control(rtwdev, h2c_para[0], &h2c_para[1]); 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 100962306a36Sopenharmony_ci "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n", 101062306a36Sopenharmony_ci __func__, h2c_para[0], h2c_para[1], h2c_para[2], 101162306a36Sopenharmony_ci h2c_para[3], h2c_para[4], h2c_para[5]); 101262306a36Sopenharmony_ci} 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci#define COEX_WL_SLOT_TOGLLE 0x5a5a5aaa 101562306a36Sopenharmony_cistatic void rtw_btc_wltoggle_table_b(struct rtw_dev *rtwdev, bool force, 101662306a36Sopenharmony_ci u8 interval, u32 table) 101762306a36Sopenharmony_ci{ 101862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 101962306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 102062306a36Sopenharmony_ci u8 cur_h2c_para[6] = {0}; 102162306a36Sopenharmony_ci u8 i; 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci cur_h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_B; 102462306a36Sopenharmony_ci cur_h2c_para[1] = interval; 102562306a36Sopenharmony_ci cur_h2c_para[2] = (u8)u32_get_bits(table, GENMASK(7, 0)); 102662306a36Sopenharmony_ci cur_h2c_para[3] = (u8)u32_get_bits(table, GENMASK(15, 8)); 102762306a36Sopenharmony_ci cur_h2c_para[4] = (u8)u32_get_bits(table, GENMASK(23, 16)); 102862306a36Sopenharmony_ci cur_h2c_para[5] = (u8)u32_get_bits(table, GENMASK(31, 24)); 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_ci coex_stat->wl_toggle_interval = interval; 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci for (i = 0; i <= 5; i++) 103362306a36Sopenharmony_ci coex_stat->wl_toggle_para[i] = cur_h2c_para[i]; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci rtw_fw_bt_wifi_control(rtwdev, cur_h2c_para[0], &cur_h2c_para[1]); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 103862306a36Sopenharmony_ci "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n", 103962306a36Sopenharmony_ci __func__, cur_h2c_para[0], cur_h2c_para[1], cur_h2c_para[2], 104062306a36Sopenharmony_ci cur_h2c_para[3], cur_h2c_para[4], cur_h2c_para[5]); 104162306a36Sopenharmony_ci} 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_cistatic void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0, 104462306a36Sopenharmony_ci u32 table1) 104562306a36Sopenharmony_ci{ 104662306a36Sopenharmony_ci#define DEF_BRK_TABLE_VAL 0xf0ffffff 104762306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 104862306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci /* If last tdma is wl slot toggle, force write table*/ 105162306a36Sopenharmony_ci if (!force && coex_dm->reason != COEX_RSN_LPS) { 105262306a36Sopenharmony_ci if (table0 == rtw_read32(rtwdev, REG_BT_COEX_TABLE0) && 105362306a36Sopenharmony_ci table1 == rtw_read32(rtwdev, REG_BT_COEX_TABLE1)) 105462306a36Sopenharmony_ci return; 105562306a36Sopenharmony_ci } 105662306a36Sopenharmony_ci rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0); 105762306a36Sopenharmony_ci rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1); 105862306a36Sopenharmony_ci rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL); 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 106162306a36Sopenharmony_ci "[BTCoex], %s(): 0x6c0 = %x, 0x6c4 = %x\n", __func__, table0, 106262306a36Sopenharmony_ci table1); 106362306a36Sopenharmony_ci} 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_cistatic void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type) 106662306a36Sopenharmony_ci{ 106762306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 106862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 106962306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 107062306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 107162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 107262306a36Sopenharmony_ci 107362306a36Sopenharmony_ci coex_dm->cur_table = type; 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Coex_Table - %d\n", type); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci if (efuse->share_ant) { 107862306a36Sopenharmony_ci if (type < chip->table_sant_num) 107962306a36Sopenharmony_ci rtw_coex_set_table(rtwdev, force, 108062306a36Sopenharmony_ci chip->table_sant[type].bt, 108162306a36Sopenharmony_ci chip->table_sant[type].wl); 108262306a36Sopenharmony_ci } else { 108362306a36Sopenharmony_ci type = type - 100; 108462306a36Sopenharmony_ci if (type < chip->table_nsant_num) 108562306a36Sopenharmony_ci rtw_coex_set_table(rtwdev, force, 108662306a36Sopenharmony_ci chip->table_nsant[type].bt, 108762306a36Sopenharmony_ci chip->table_nsant[type].wl); 108862306a36Sopenharmony_ci } 108962306a36Sopenharmony_ci if (coex_stat->wl_slot_toggle_change) 109062306a36Sopenharmony_ci rtw_btc_wltoggle_table_a(rtwdev, true, type); 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_cistatic void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable) 109462306a36Sopenharmony_ci{ 109562306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci if (coex->manual_control || coex->stop_dm) 109862306a36Sopenharmony_ci return; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci rtw_fw_bt_ignore_wlan_action(rtwdev, enable); 110162306a36Sopenharmony_ci} 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_cistatic void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type, 110462306a36Sopenharmony_ci u8 lps_val, u8 rpwm_val) 110562306a36Sopenharmony_ci{ 110662306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 110762306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 110862306a36Sopenharmony_ci u8 lps_mode = 0x0; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci lps_mode = rtwdev->lps_conf.mode; 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci switch (ps_type) { 111362306a36Sopenharmony_ci case COEX_PS_WIFI_NATIVE: 111462306a36Sopenharmony_ci /* recover to original 32k low power setting */ 111562306a36Sopenharmony_ci coex_stat->wl_force_lps_ctrl = false; 111662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 111762306a36Sopenharmony_ci "[BTCoex], %s(): COEX_PS_WIFI_NATIVE\n", __func__); 111862306a36Sopenharmony_ci rtw_leave_lps(rtwdev); 111962306a36Sopenharmony_ci break; 112062306a36Sopenharmony_ci case COEX_PS_LPS_OFF: 112162306a36Sopenharmony_ci coex_stat->wl_force_lps_ctrl = true; 112262306a36Sopenharmony_ci if (lps_mode) 112362306a36Sopenharmony_ci rtw_fw_coex_tdma_type(rtwdev, 0, 0, 0, 0, 0); 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci rtw_leave_lps(rtwdev); 112662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 112762306a36Sopenharmony_ci "[BTCoex], %s(): COEX_PS_LPS_OFF\n", __func__); 112862306a36Sopenharmony_ci break; 112962306a36Sopenharmony_ci default: 113062306a36Sopenharmony_ci break; 113162306a36Sopenharmony_ci } 113262306a36Sopenharmony_ci} 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_cistatic void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2, 113562306a36Sopenharmony_ci u8 byte3, u8 byte4, u8 byte5) 113662306a36Sopenharmony_ci{ 113762306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 113862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 113962306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 114062306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 114162306a36Sopenharmony_ci u8 ps_type = COEX_PS_WIFI_NATIVE; 114262306a36Sopenharmony_ci bool ap_enable = false; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) { 114562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): AP mode\n", 114662306a36Sopenharmony_ci __func__); 114762306a36Sopenharmony_ci 114862306a36Sopenharmony_ci byte1 &= ~BIT(4); 114962306a36Sopenharmony_ci byte1 |= BIT(5); 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci byte5 |= BIT(5); 115262306a36Sopenharmony_ci byte5 &= ~BIT(6); 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci ps_type = COEX_PS_WIFI_NATIVE; 115562306a36Sopenharmony_ci rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); 115662306a36Sopenharmony_ci } else if ((byte1 & BIT(4) && !(byte1 & BIT(5))) || 115762306a36Sopenharmony_ci coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) { 115862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 115962306a36Sopenharmony_ci "[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__, 116062306a36Sopenharmony_ci byte1); 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF) 116362306a36Sopenharmony_ci ps_type = COEX_PS_LPS_OFF; 116462306a36Sopenharmony_ci else 116562306a36Sopenharmony_ci ps_type = COEX_PS_LPS_ON; 116662306a36Sopenharmony_ci rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4); 116762306a36Sopenharmony_ci } else { 116862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 116962306a36Sopenharmony_ci "[BTCoex], %s(): native power save (byte1 = 0x%x)\n", 117062306a36Sopenharmony_ci __func__, byte1); 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci ps_type = COEX_PS_WIFI_NATIVE; 117362306a36Sopenharmony_ci rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); 117462306a36Sopenharmony_ci } 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci coex_dm->ps_tdma_para[0] = byte1; 117762306a36Sopenharmony_ci coex_dm->ps_tdma_para[1] = byte2; 117862306a36Sopenharmony_ci coex_dm->ps_tdma_para[2] = byte3; 117962306a36Sopenharmony_ci coex_dm->ps_tdma_para[3] = byte4; 118062306a36Sopenharmony_ci coex_dm->ps_tdma_para[4] = byte5; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5); 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci if (byte1 & BIT(2)) { 118562306a36Sopenharmony_ci coex_stat->wl_slot_toggle = true; 118662306a36Sopenharmony_ci coex_stat->wl_slot_toggle_change = false; 118762306a36Sopenharmony_ci } else { 118862306a36Sopenharmony_ci coex_stat->wl_slot_toggle_change = coex_stat->wl_slot_toggle; 118962306a36Sopenharmony_ci coex_stat->wl_slot_toggle = false; 119062306a36Sopenharmony_ci } 119162306a36Sopenharmony_ci} 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_cistatic void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase) 119462306a36Sopenharmony_ci{ 119562306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 119662306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 119762306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 119862306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 119962306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 120062306a36Sopenharmony_ci u8 n, type; 120162306a36Sopenharmony_ci bool turn_on; 120262306a36Sopenharmony_ci bool wl_busy = false; 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_ci if (tcase & TDMA_4SLOT) /* 4-slot (50ms) mode */ 120562306a36Sopenharmony_ci rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_4SLOT); 120662306a36Sopenharmony_ci else 120762306a36Sopenharmony_ci rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_2SLOT); 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci type = (u8)(tcase & 0xff); 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci turn_on = (type == 0 || type == 100) ? false : true; 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci if (!force && turn_on == coex_dm->cur_ps_tdma_on && 121462306a36Sopenharmony_ci type == coex_dm->cur_ps_tdma) { 121562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 121662306a36Sopenharmony_ci "[BTCoex], Skip TDMA because no change TDMA(%s, %d)\n", 121762306a36Sopenharmony_ci (coex_dm->cur_ps_tdma_on ? "on" : "off"), 121862306a36Sopenharmony_ci coex_dm->cur_ps_tdma); 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci return; 122162306a36Sopenharmony_ci } 122262306a36Sopenharmony_ci wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci if ((coex_stat->bt_a2dp_exist && 122562306a36Sopenharmony_ci (coex_stat->bt_inq_remain || coex_stat->bt_multi_link)) || 122662306a36Sopenharmony_ci !wl_busy) 122762306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false); 122862306a36Sopenharmony_ci else 122962306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true); 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci /* update pre state */ 123262306a36Sopenharmony_ci coex_dm->cur_ps_tdma_on = turn_on; 123362306a36Sopenharmony_ci coex_dm->cur_ps_tdma = type; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci if (efuse->share_ant) { 123662306a36Sopenharmony_ci if (type < chip->tdma_sant_num) 123762306a36Sopenharmony_ci rtw_coex_set_tdma(rtwdev, 123862306a36Sopenharmony_ci chip->tdma_sant[type].para[0], 123962306a36Sopenharmony_ci chip->tdma_sant[type].para[1], 124062306a36Sopenharmony_ci chip->tdma_sant[type].para[2], 124162306a36Sopenharmony_ci chip->tdma_sant[type].para[3], 124262306a36Sopenharmony_ci chip->tdma_sant[type].para[4]); 124362306a36Sopenharmony_ci } else { 124462306a36Sopenharmony_ci n = type - 100; 124562306a36Sopenharmony_ci if (n < chip->tdma_nsant_num) 124662306a36Sopenharmony_ci rtw_coex_set_tdma(rtwdev, 124762306a36Sopenharmony_ci chip->tdma_nsant[n].para[0], 124862306a36Sopenharmony_ci chip->tdma_nsant[n].para[1], 124962306a36Sopenharmony_ci chip->tdma_nsant[n].para[2], 125062306a36Sopenharmony_ci chip->tdma_nsant[n].para[3], 125162306a36Sopenharmony_ci chip->tdma_nsant[n].para[4]); 125262306a36Sopenharmony_ci } 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], coex tdma type(%s, %d)\n", 125662306a36Sopenharmony_ci turn_on ? "on" : "off", type); 125762306a36Sopenharmony_ci} 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_cistatic void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) 126062306a36Sopenharmony_ci{ 126162306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 126262306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 126362306a36Sopenharmony_ci struct rtw_coex_rfe *coex_rfe = &coex->rfe; 126462306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 126562306a36Sopenharmony_ci u8 ctrl_type = COEX_SWITCH_CTRL_MAX; 126662306a36Sopenharmony_ci u8 pos_type = COEX_SWITCH_TO_MAX; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci if (!force && coex_dm->cur_ant_pos_type == phase) 126962306a36Sopenharmony_ci return; 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci coex_dm->cur_ant_pos_type = phase; 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci /* avoid switch coex_ctrl_owner during BT IQK */ 127462306a36Sopenharmony_ci rtw_coex_check_rfk(rtwdev); 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 127762306a36Sopenharmony_ci "[BTCoex], coex_stat->bt_disabled = 0x%x\n", 127862306a36Sopenharmony_ci coex_stat->bt_disabled); 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci switch (phase) { 128162306a36Sopenharmony_ci case COEX_SET_ANT_POWERON: 128262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 128362306a36Sopenharmony_ci "[BTCoex], %s() - PHASE_COEX_POWERON\n", __func__); 128462306a36Sopenharmony_ci /* set path control owner to BT at power-on */ 128562306a36Sopenharmony_ci if (coex_stat->bt_disabled) 128662306a36Sopenharmony_ci rtw_coex_coex_ctrl_owner(rtwdev, true); 128762306a36Sopenharmony_ci else 128862306a36Sopenharmony_ci rtw_coex_coex_ctrl_owner(rtwdev, false); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 129162306a36Sopenharmony_ci pos_type = COEX_SWITCH_TO_BT; 129262306a36Sopenharmony_ci break; 129362306a36Sopenharmony_ci case COEX_SET_ANT_INIT: 129462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 129562306a36Sopenharmony_ci "[BTCoex], %s() - PHASE_COEX_INIT\n", __func__); 129662306a36Sopenharmony_ci if (coex_stat->bt_disabled) { 129762306a36Sopenharmony_ci /* set GNT_BT to SW low */ 129862306a36Sopenharmony_ci rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); 129962306a36Sopenharmony_ci 130062306a36Sopenharmony_ci /* set GNT_WL to SW high */ 130162306a36Sopenharmony_ci rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 130262306a36Sopenharmony_ci } else { 130362306a36Sopenharmony_ci /* set GNT_BT to SW high */ 130462306a36Sopenharmony_ci rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci /* set GNT_WL to SW low */ 130762306a36Sopenharmony_ci rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW); 130862306a36Sopenharmony_ci } 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci /* set path control owner to wl at initial step */ 131162306a36Sopenharmony_ci rtw_coex_coex_ctrl_owner(rtwdev, true); 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 131462306a36Sopenharmony_ci pos_type = COEX_SWITCH_TO_BT; 131562306a36Sopenharmony_ci break; 131662306a36Sopenharmony_ci case COEX_SET_ANT_WONLY: 131762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 131862306a36Sopenharmony_ci "[BTCoex], %s() - PHASE_WLANONLY_INIT\n", __func__); 131962306a36Sopenharmony_ci /* set GNT_BT to SW Low */ 132062306a36Sopenharmony_ci rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci /* set GNT_WL to SW high */ 132362306a36Sopenharmony_ci rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci /* set path control owner to wl at initial step */ 132662306a36Sopenharmony_ci rtw_coex_coex_ctrl_owner(rtwdev, true); 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 132962306a36Sopenharmony_ci pos_type = COEX_SWITCH_TO_WLG; 133062306a36Sopenharmony_ci break; 133162306a36Sopenharmony_ci case COEX_SET_ANT_WOFF: 133262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 133362306a36Sopenharmony_ci "[BTCoex], %s() - PHASE_WLAN_OFF\n", __func__); 133462306a36Sopenharmony_ci /* set path control owner to BT */ 133562306a36Sopenharmony_ci rtw_coex_coex_ctrl_owner(rtwdev, false); 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci ctrl_type = COEX_SWITCH_CTRL_BY_BT; 133862306a36Sopenharmony_ci pos_type = COEX_SWITCH_TO_NOCARE; 133962306a36Sopenharmony_ci break; 134062306a36Sopenharmony_ci case COEX_SET_ANT_2G: 134162306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 134262306a36Sopenharmony_ci "[BTCoex], %s() - PHASE_2G_RUNTIME\n", __func__); 134362306a36Sopenharmony_ci /* set GNT_BT to PTA */ 134462306a36Sopenharmony_ci rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 134562306a36Sopenharmony_ci 134662306a36Sopenharmony_ci /* set GNT_WL to PTA */ 134762306a36Sopenharmony_ci rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_ci /* set path control owner to wl at runtime step */ 135062306a36Sopenharmony_ci rtw_coex_coex_ctrl_owner(rtwdev, true); 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_ci ctrl_type = COEX_SWITCH_CTRL_BY_PTA; 135362306a36Sopenharmony_ci pos_type = COEX_SWITCH_TO_NOCARE; 135462306a36Sopenharmony_ci break; 135562306a36Sopenharmony_ci case COEX_SET_ANT_5G: 135662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 135762306a36Sopenharmony_ci "[BTCoex], %s() - PHASE_5G_RUNTIME\n", __func__); 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci /* set GNT_BT to HW PTA */ 136062306a36Sopenharmony_ci rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci /* set GNT_WL to SW high */ 136362306a36Sopenharmony_ci rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci /* set path control owner to wl at runtime step */ 136662306a36Sopenharmony_ci rtw_coex_coex_ctrl_owner(rtwdev, true); 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 136962306a36Sopenharmony_ci pos_type = COEX_SWITCH_TO_WLA; 137062306a36Sopenharmony_ci break; 137162306a36Sopenharmony_ci case COEX_SET_ANT_2G_FREERUN: 137262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 137362306a36Sopenharmony_ci "[BTCoex], %s() - PHASE_2G_FREERUN\n", __func__); 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci /* set GNT_BT to HW PTA */ 137662306a36Sopenharmony_ci rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci /* Set GNT_WL to SW high */ 137962306a36Sopenharmony_ci rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 138062306a36Sopenharmony_ci 138162306a36Sopenharmony_ci /* set path control owner to wl at runtime step */ 138262306a36Sopenharmony_ci rtw_coex_coex_ctrl_owner(rtwdev, true); 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 138562306a36Sopenharmony_ci pos_type = COEX_SWITCH_TO_WLG_BT; 138662306a36Sopenharmony_ci break; 138762306a36Sopenharmony_ci case COEX_SET_ANT_2G_WLBT: 138862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 138962306a36Sopenharmony_ci "[BTCoex], %s() - PHASE_2G_WLBT\n", __func__); 139062306a36Sopenharmony_ci /* set GNT_BT to HW PTA */ 139162306a36Sopenharmony_ci rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci /* Set GNT_WL to HW PTA */ 139462306a36Sopenharmony_ci rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci /* set path control owner to wl at runtime step */ 139762306a36Sopenharmony_ci rtw_coex_coex_ctrl_owner(rtwdev, true); 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 140062306a36Sopenharmony_ci pos_type = COEX_SWITCH_TO_WLG_BT; 140162306a36Sopenharmony_ci break; 140262306a36Sopenharmony_ci default: 140362306a36Sopenharmony_ci WARN(1, "unknown phase when setting antenna path\n"); 140462306a36Sopenharmony_ci return; 140562306a36Sopenharmony_ci } 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX && 140862306a36Sopenharmony_ci coex_rfe->ant_switch_exist) 140962306a36Sopenharmony_ci rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type); 141062306a36Sopenharmony_ci} 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci#define case_ALGO(src) \ 141362306a36Sopenharmony_ci case COEX_ALGO_##src: return #src 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_cistatic const char *rtw_coex_get_algo_string(u8 algo) 141662306a36Sopenharmony_ci{ 141762306a36Sopenharmony_ci switch (algo) { 141862306a36Sopenharmony_ci case_ALGO(NOPROFILE); 141962306a36Sopenharmony_ci case_ALGO(HFP); 142062306a36Sopenharmony_ci case_ALGO(HID); 142162306a36Sopenharmony_ci case_ALGO(A2DP); 142262306a36Sopenharmony_ci case_ALGO(PAN); 142362306a36Sopenharmony_ci case_ALGO(A2DP_HID); 142462306a36Sopenharmony_ci case_ALGO(A2DP_PAN); 142562306a36Sopenharmony_ci case_ALGO(PAN_HID); 142662306a36Sopenharmony_ci case_ALGO(A2DP_PAN_HID); 142762306a36Sopenharmony_ci default: 142862306a36Sopenharmony_ci return "Unknown"; 142962306a36Sopenharmony_ci } 143062306a36Sopenharmony_ci} 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci#define case_BT_PROFILE(src) \ 143362306a36Sopenharmony_ci case BPM_##src: return #src 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_cistatic const char *rtw_coex_get_bt_profile_string(u8 bt_profile) 143662306a36Sopenharmony_ci{ 143762306a36Sopenharmony_ci switch (bt_profile) { 143862306a36Sopenharmony_ci case_BT_PROFILE(NOPROFILE); 143962306a36Sopenharmony_ci case_BT_PROFILE(HFP); 144062306a36Sopenharmony_ci case_BT_PROFILE(HID); 144162306a36Sopenharmony_ci case_BT_PROFILE(A2DP); 144262306a36Sopenharmony_ci case_BT_PROFILE(PAN); 144362306a36Sopenharmony_ci case_BT_PROFILE(HID_HFP); 144462306a36Sopenharmony_ci case_BT_PROFILE(A2DP_HFP); 144562306a36Sopenharmony_ci case_BT_PROFILE(A2DP_HID); 144662306a36Sopenharmony_ci case_BT_PROFILE(A2DP_HID_HFP); 144762306a36Sopenharmony_ci case_BT_PROFILE(PAN_HFP); 144862306a36Sopenharmony_ci case_BT_PROFILE(PAN_HID); 144962306a36Sopenharmony_ci case_BT_PROFILE(PAN_HID_HFP); 145062306a36Sopenharmony_ci case_BT_PROFILE(PAN_A2DP); 145162306a36Sopenharmony_ci case_BT_PROFILE(PAN_A2DP_HFP); 145262306a36Sopenharmony_ci case_BT_PROFILE(PAN_A2DP_HID); 145362306a36Sopenharmony_ci case_BT_PROFILE(PAN_A2DP_HID_HFP); 145462306a36Sopenharmony_ci default: 145562306a36Sopenharmony_ci return "Unknown"; 145662306a36Sopenharmony_ci } 145762306a36Sopenharmony_ci} 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_cistatic u8 rtw_coex_algorithm(struct rtw_dev *rtwdev) 146062306a36Sopenharmony_ci{ 146162306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 146262306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 146362306a36Sopenharmony_ci u8 algorithm = COEX_ALGO_NOPROFILE; 146462306a36Sopenharmony_ci u8 profile_map = 0; 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci if (coex_stat->bt_hfp_exist) 146762306a36Sopenharmony_ci profile_map |= BPM_HFP; 146862306a36Sopenharmony_ci if (coex_stat->bt_hid_exist) 146962306a36Sopenharmony_ci profile_map |= BPM_HID; 147062306a36Sopenharmony_ci if (coex_stat->bt_a2dp_exist) 147162306a36Sopenharmony_ci profile_map |= BPM_A2DP; 147262306a36Sopenharmony_ci if (coex_stat->bt_pan_exist) 147362306a36Sopenharmony_ci profile_map |= BPM_PAN; 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci switch (profile_map) { 147662306a36Sopenharmony_ci case BPM_HFP: 147762306a36Sopenharmony_ci algorithm = COEX_ALGO_HFP; 147862306a36Sopenharmony_ci break; 147962306a36Sopenharmony_ci case BPM_HID: 148062306a36Sopenharmony_ci case BPM_HFP + BPM_HID: 148162306a36Sopenharmony_ci algorithm = COEX_ALGO_HID; 148262306a36Sopenharmony_ci break; 148362306a36Sopenharmony_ci case BPM_HFP + BPM_A2DP: 148462306a36Sopenharmony_ci case BPM_HID + BPM_A2DP: 148562306a36Sopenharmony_ci case BPM_HFP + BPM_HID + BPM_A2DP: 148662306a36Sopenharmony_ci algorithm = COEX_ALGO_A2DP_HID; 148762306a36Sopenharmony_ci break; 148862306a36Sopenharmony_ci case BPM_HFP + BPM_PAN: 148962306a36Sopenharmony_ci case BPM_HID + BPM_PAN: 149062306a36Sopenharmony_ci case BPM_HFP + BPM_HID + BPM_PAN: 149162306a36Sopenharmony_ci algorithm = COEX_ALGO_PAN_HID; 149262306a36Sopenharmony_ci break; 149362306a36Sopenharmony_ci case BPM_HFP + BPM_A2DP + BPM_PAN: 149462306a36Sopenharmony_ci case BPM_HID + BPM_A2DP + BPM_PAN: 149562306a36Sopenharmony_ci case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN: 149662306a36Sopenharmony_ci algorithm = COEX_ALGO_A2DP_PAN_HID; 149762306a36Sopenharmony_ci break; 149862306a36Sopenharmony_ci case BPM_PAN: 149962306a36Sopenharmony_ci algorithm = COEX_ALGO_PAN; 150062306a36Sopenharmony_ci break; 150162306a36Sopenharmony_ci case BPM_A2DP + BPM_PAN: 150262306a36Sopenharmony_ci algorithm = COEX_ALGO_A2DP_PAN; 150362306a36Sopenharmony_ci break; 150462306a36Sopenharmony_ci case BPM_A2DP: 150562306a36Sopenharmony_ci if (coex_stat->bt_multi_link) { 150662306a36Sopenharmony_ci if (coex_stat->bt_hid_pair_num > 0) 150762306a36Sopenharmony_ci algorithm = COEX_ALGO_A2DP_HID; 150862306a36Sopenharmony_ci else 150962306a36Sopenharmony_ci algorithm = COEX_ALGO_A2DP_PAN; 151062306a36Sopenharmony_ci } else { 151162306a36Sopenharmony_ci algorithm = COEX_ALGO_A2DP; 151262306a36Sopenharmony_ci } 151362306a36Sopenharmony_ci break; 151462306a36Sopenharmony_ci default: 151562306a36Sopenharmony_ci algorithm = COEX_ALGO_NOPROFILE; 151662306a36Sopenharmony_ci break; 151762306a36Sopenharmony_ci } 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 152062306a36Sopenharmony_ci "[BTCoex], BT Profile = %s => Algorithm = %s\n", 152162306a36Sopenharmony_ci rtw_coex_get_bt_profile_string(profile_map), 152262306a36Sopenharmony_ci rtw_coex_get_algo_string(algorithm)); 152362306a36Sopenharmony_ci return algorithm; 152462306a36Sopenharmony_ci} 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_cistatic void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev) 152762306a36Sopenharmony_ci{ 152862306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 152962306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 153062306a36Sopenharmony_ci u8 table_case, tdma_case; 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 153362306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci if (efuse->share_ant) { 153662306a36Sopenharmony_ci /* Shared-Ant */ 153762306a36Sopenharmony_ci table_case = 2; 153862306a36Sopenharmony_ci tdma_case = 0; 153962306a36Sopenharmony_ci } else { 154062306a36Sopenharmony_ci /* Non-Shared-Ant */ 154162306a36Sopenharmony_ci table_case = 100; 154262306a36Sopenharmony_ci tdma_case = 100; 154362306a36Sopenharmony_ci } 154462306a36Sopenharmony_ci 154562306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 154662306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 154762306a36Sopenharmony_ci} 154862306a36Sopenharmony_ci 154962306a36Sopenharmony_cistatic void rtw_coex_action_freerun(struct rtw_dev *rtwdev) 155062306a36Sopenharmony_ci{ 155162306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 155262306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 155362306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 155462306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 155562306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 155662306a36Sopenharmony_ci u8 level = 0; 155762306a36Sopenharmony_ci bool bt_afh_loss = true; 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci if (efuse->share_ant) 156262306a36Sopenharmony_ci return; 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci coex->freerun = true; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci if (bt_afh_loss) 156762306a36Sopenharmony_ci rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT); 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0])) 157462306a36Sopenharmony_ci level = 2; 157562306a36Sopenharmony_ci else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 157662306a36Sopenharmony_ci level = 3; 157762306a36Sopenharmony_ci else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2])) 157862306a36Sopenharmony_ci level = 4; 157962306a36Sopenharmony_ci else 158062306a36Sopenharmony_ci level = 5; 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci if (level > chip->wl_rf_para_num - 1) 158362306a36Sopenharmony_ci level = chip->wl_rf_para_num - 1; 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) 158662306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]); 158762306a36Sopenharmony_ci else 158862306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]); 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, 100); 159162306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, 100); 159262306a36Sopenharmony_ci} 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_cistatic void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev) 159562306a36Sopenharmony_ci{ 159662306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 159762306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 159862306a36Sopenharmony_ci u8 table_case, tdma_case; 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 160362306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci if (efuse->share_ant) { 160662306a36Sopenharmony_ci /* Shared-Ant */ 160762306a36Sopenharmony_ci table_case = 9; 160862306a36Sopenharmony_ci tdma_case = 16; 160962306a36Sopenharmony_ci } else { 161062306a36Sopenharmony_ci /* Non-Shared-Ant */ 161162306a36Sopenharmony_ci table_case = 100; 161262306a36Sopenharmony_ci tdma_case = 100; 161362306a36Sopenharmony_ci } 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 161662306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 161762306a36Sopenharmony_ci} 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_cistatic void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev) 162062306a36Sopenharmony_ci{ 162162306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 162262306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 162362306a36Sopenharmony_ci u8 table_case, tdma_case; 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 162662306a36Sopenharmony_ci 162762306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 162862306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci if (efuse->share_ant) { 163162306a36Sopenharmony_ci /* Shared-Ant */ 163262306a36Sopenharmony_ci table_case = 2; 163362306a36Sopenharmony_ci tdma_case = 0; 163462306a36Sopenharmony_ci } else { 163562306a36Sopenharmony_ci /* Non-Shared-Ant */ 163662306a36Sopenharmony_ci table_case = 100; 163762306a36Sopenharmony_ci tdma_case = 100; 163862306a36Sopenharmony_ci } 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 164162306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 164262306a36Sopenharmony_ci} 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_cistatic void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev) 164562306a36Sopenharmony_ci{ 164662306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 164762306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 164862306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 164962306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 165062306a36Sopenharmony_ci u8 table_case, tdma_case; 165162306a36Sopenharmony_ci u32 slot_type = 0; 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 165662306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci if (efuse->share_ant) { /* Shared-Ant */ 165962306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) { 166062306a36Sopenharmony_ci table_case = 26; 166162306a36Sopenharmony_ci if (coex_stat->bt_hid_exist && 166262306a36Sopenharmony_ci coex_stat->bt_profile_num == 1) { 166362306a36Sopenharmony_ci slot_type = TDMA_4SLOT; 166462306a36Sopenharmony_ci tdma_case = 20; 166562306a36Sopenharmony_ci } else { 166662306a36Sopenharmony_ci tdma_case = 20; 166762306a36Sopenharmony_ci } 166862306a36Sopenharmony_ci } else { 166962306a36Sopenharmony_ci table_case = 1; 167062306a36Sopenharmony_ci tdma_case = 0; 167162306a36Sopenharmony_ci } 167262306a36Sopenharmony_ci } else { /* Non-Shared-Ant */ 167362306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 167462306a36Sopenharmony_ci table_case = 115; 167562306a36Sopenharmony_ci else 167662306a36Sopenharmony_ci table_case = 100; 167762306a36Sopenharmony_ci tdma_case = 100; 167862306a36Sopenharmony_ci } 167962306a36Sopenharmony_ci 168062306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 168162306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 168262306a36Sopenharmony_ci} 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_cistatic void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) 168562306a36Sopenharmony_ci{ 168662306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 168762306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 168862306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 168962306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 169062306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 169162306a36Sopenharmony_ci struct rtw_coex_rfe *coex_rfe = &coex->rfe; 169262306a36Sopenharmony_ci u8 table_case = 0xff, tdma_case = 0xff; 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 169562306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci if (coex_rfe->ant_switch_with_bt && 169862306a36Sopenharmony_ci coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 169962306a36Sopenharmony_ci if (efuse->share_ant && 170062306a36Sopenharmony_ci COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && 170162306a36Sopenharmony_ci coex_stat->wl_gl_busy) { 170262306a36Sopenharmony_ci table_case = 0; 170362306a36Sopenharmony_ci tdma_case = 0; 170462306a36Sopenharmony_ci } else if (!efuse->share_ant) { 170562306a36Sopenharmony_ci table_case = 100; 170662306a36Sopenharmony_ci tdma_case = 100; 170762306a36Sopenharmony_ci } 170862306a36Sopenharmony_ci } 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci if (table_case != 0xff && tdma_case != 0xff) { 171162306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); 171262306a36Sopenharmony_ci goto exit; 171362306a36Sopenharmony_ci } 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci if (efuse->share_ant) { 171862306a36Sopenharmony_ci /* Shared-Ant */ 171962306a36Sopenharmony_ci if (!coex_stat->wl_gl_busy) { 172062306a36Sopenharmony_ci table_case = 10; 172162306a36Sopenharmony_ci tdma_case = 3; 172262306a36Sopenharmony_ci } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 172362306a36Sopenharmony_ci table_case = 11; 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci if (coex_stat->lo_pri_rx + coex_stat->lo_pri_tx > 250) 172662306a36Sopenharmony_ci tdma_case = 17; 172762306a36Sopenharmony_ci else 172862306a36Sopenharmony_ci tdma_case = 7; 172962306a36Sopenharmony_ci } else { 173062306a36Sopenharmony_ci table_case = 12; 173162306a36Sopenharmony_ci tdma_case = 7; 173262306a36Sopenharmony_ci } 173362306a36Sopenharmony_ci } else { 173462306a36Sopenharmony_ci /* Non-Shared-Ant */ 173562306a36Sopenharmony_ci if (!coex_stat->wl_gl_busy) { 173662306a36Sopenharmony_ci table_case = 112; 173762306a36Sopenharmony_ci tdma_case = 104; 173862306a36Sopenharmony_ci } else if ((coex_stat->bt_ble_scan_type & 0x2) && 173962306a36Sopenharmony_ci coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 174062306a36Sopenharmony_ci table_case = 114; 174162306a36Sopenharmony_ci tdma_case = 103; 174262306a36Sopenharmony_ci } else { 174362306a36Sopenharmony_ci table_case = 112; 174462306a36Sopenharmony_ci tdma_case = 103; 174562306a36Sopenharmony_ci } 174662306a36Sopenharmony_ci } 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ciexit: 174962306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 175062306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 175162306a36Sopenharmony_ci} 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_cistatic void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) 175462306a36Sopenharmony_ci{ 175562306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 175662306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 175762306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 175862306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 175962306a36Sopenharmony_ci bool wl_hi_pri = false; 176062306a36Sopenharmony_ci u8 table_case, tdma_case; 176162306a36Sopenharmony_ci u32 slot_type = 0; 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 176462306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 176562306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 || 176862306a36Sopenharmony_ci coex_stat->wl_hi_pri_task2) 176962306a36Sopenharmony_ci wl_hi_pri = true; 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci if (efuse->share_ant) { 177262306a36Sopenharmony_ci /* Shared-Ant */ 177362306a36Sopenharmony_ci if (wl_hi_pri) { 177462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 177562306a36Sopenharmony_ci "[BTCoex], bt inq/page + wifi hi-pri task\n"); 177662306a36Sopenharmony_ci table_case = 15; 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci if (coex_stat->bt_profile_num > 0) 177962306a36Sopenharmony_ci tdma_case = 10; 178062306a36Sopenharmony_ci else if (coex_stat->wl_hi_pri_task1) 178162306a36Sopenharmony_ci tdma_case = 6; 178262306a36Sopenharmony_ci else if (!coex_stat->bt_page) 178362306a36Sopenharmony_ci tdma_case = 8; 178462306a36Sopenharmony_ci else 178562306a36Sopenharmony_ci tdma_case = 9; 178662306a36Sopenharmony_ci } else if (coex_stat->wl_gl_busy) { 178762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 178862306a36Sopenharmony_ci "[BTCoex], bt inq/page + wifi busy\n"); 178962306a36Sopenharmony_ci if (coex_stat->bt_profile_num == 0) { 179062306a36Sopenharmony_ci table_case = 12; 179162306a36Sopenharmony_ci tdma_case = 18; 179262306a36Sopenharmony_ci } else if (coex_stat->bt_profile_num == 1 && 179362306a36Sopenharmony_ci !coex_stat->bt_a2dp_exist) { 179462306a36Sopenharmony_ci slot_type = TDMA_4SLOT; 179562306a36Sopenharmony_ci table_case = 12; 179662306a36Sopenharmony_ci tdma_case = 20; 179762306a36Sopenharmony_ci } else { 179862306a36Sopenharmony_ci slot_type = TDMA_4SLOT; 179962306a36Sopenharmony_ci table_case = 12; 180062306a36Sopenharmony_ci tdma_case = 26; 180162306a36Sopenharmony_ci } 180262306a36Sopenharmony_ci } else if (coex_stat->wl_connected) { 180362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 180462306a36Sopenharmony_ci "[BTCoex], bt inq/page + wifi connected\n"); 180562306a36Sopenharmony_ci table_case = 9; 180662306a36Sopenharmony_ci tdma_case = 27; 180762306a36Sopenharmony_ci } else { 180862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 180962306a36Sopenharmony_ci "[BTCoex], bt inq/page + wifi not-connected\n"); 181062306a36Sopenharmony_ci table_case = 1; 181162306a36Sopenharmony_ci tdma_case = 0; 181262306a36Sopenharmony_ci } 181362306a36Sopenharmony_ci } else { 181462306a36Sopenharmony_ci /* Non_Shared-Ant */ 181562306a36Sopenharmony_ci if (wl_hi_pri) { 181662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 181762306a36Sopenharmony_ci "[BTCoex], bt inq/page + wifi hi-pri task\n"); 181862306a36Sopenharmony_ci table_case = 114; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci if (coex_stat->bt_profile_num > 0) 182162306a36Sopenharmony_ci tdma_case = 110; 182262306a36Sopenharmony_ci else if (coex_stat->wl_hi_pri_task1) 182362306a36Sopenharmony_ci tdma_case = 106; 182462306a36Sopenharmony_ci else if (!coex_stat->bt_page) 182562306a36Sopenharmony_ci tdma_case = 108; 182662306a36Sopenharmony_ci else 182762306a36Sopenharmony_ci tdma_case = 109; 182862306a36Sopenharmony_ci } else if (coex_stat->wl_gl_busy) { 182962306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 183062306a36Sopenharmony_ci "[BTCoex], bt inq/page + wifi busy\n"); 183162306a36Sopenharmony_ci table_case = 114; 183262306a36Sopenharmony_ci tdma_case = 121; 183362306a36Sopenharmony_ci } else if (coex_stat->wl_connected) { 183462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 183562306a36Sopenharmony_ci "[BTCoex], bt inq/page + wifi connected\n"); 183662306a36Sopenharmony_ci table_case = 101; 183762306a36Sopenharmony_ci tdma_case = 100; 183862306a36Sopenharmony_ci } else { 183962306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 184062306a36Sopenharmony_ci "[BTCoex], bt inq/page + wifi not-connected\n"); 184162306a36Sopenharmony_ci table_case = 101; 184262306a36Sopenharmony_ci tdma_case = 100; 184362306a36Sopenharmony_ci } 184462306a36Sopenharmony_ci } 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wifi hi(%d), bt page(%d)\n", 184762306a36Sopenharmony_ci wl_hi_pri, coex_stat->bt_page); 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 185062306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 185162306a36Sopenharmony_ci} 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_cistatic void rtw_coex_action_bt_game_hid(struct rtw_dev *rtwdev) 185462306a36Sopenharmony_ci{ 185562306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 185662306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 185762306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 185862306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 185962306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 186062306a36Sopenharmony_ci u8 table_case, tdma_case; 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 186362306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 186462306a36Sopenharmony_ci 186562306a36Sopenharmony_ci if (efuse->share_ant) { 186662306a36Sopenharmony_ci coex_stat->wl_coex_mode = COEX_WLINK_2GFREE; 186762306a36Sopenharmony_ci if (coex_stat->bt_whck_test) 186862306a36Sopenharmony_ci table_case = 2; 186962306a36Sopenharmony_ci else if (coex_stat->wl_linkscan_proc || coex_stat->bt_hid_exist) 187062306a36Sopenharmony_ci table_case = 33; 187162306a36Sopenharmony_ci else if (coex_stat->bt_setup_link || coex_stat->bt_inq_page) 187262306a36Sopenharmony_ci table_case = 0; 187362306a36Sopenharmony_ci else if (coex_stat->bt_a2dp_exist) 187462306a36Sopenharmony_ci table_case = 34; 187562306a36Sopenharmony_ci else 187662306a36Sopenharmony_ci table_case = 33; 187762306a36Sopenharmony_ci 187862306a36Sopenharmony_ci tdma_case = 0; 187962306a36Sopenharmony_ci } else { 188062306a36Sopenharmony_ci if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 188162306a36Sopenharmony_ci tdma_case = 112; 188262306a36Sopenharmony_ci else 188362306a36Sopenharmony_ci tdma_case = 113; 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci table_case = 121; 188662306a36Sopenharmony_ci } 188762306a36Sopenharmony_ci 188862306a36Sopenharmony_ci if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) { 188962306a36Sopenharmony_ci if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) 189062306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]); 189162306a36Sopenharmony_ci else 189262306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]); 189362306a36Sopenharmony_ci } else { 189462306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 189562306a36Sopenharmony_ci } 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 189862306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 189962306a36Sopenharmony_ci} 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_cistatic void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev) 190262306a36Sopenharmony_ci{ 190362306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 190462306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 190562306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 190662306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 190762306a36Sopenharmony_ci u8 table_case, tdma_case; 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 191062306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 191162306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 191262306a36Sopenharmony_ci 191362306a36Sopenharmony_ci if (efuse->share_ant) { 191462306a36Sopenharmony_ci /* Shared-Ant */ 191562306a36Sopenharmony_ci table_case = 10; 191662306a36Sopenharmony_ci tdma_case = 5; 191762306a36Sopenharmony_ci } else { 191862306a36Sopenharmony_ci /* Non-Shared-Ant */ 191962306a36Sopenharmony_ci if (coex_stat->bt_multi_link) { 192062306a36Sopenharmony_ci table_case = 112; 192162306a36Sopenharmony_ci tdma_case = 117; 192262306a36Sopenharmony_ci } else { 192362306a36Sopenharmony_ci table_case = 105; 192462306a36Sopenharmony_ci tdma_case = 100; 192562306a36Sopenharmony_ci } 192662306a36Sopenharmony_ci } 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 192962306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 193062306a36Sopenharmony_ci} 193162306a36Sopenharmony_ci 193262306a36Sopenharmony_cistatic void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev) 193362306a36Sopenharmony_ci{ 193462306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 193562306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 193662306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 193762306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 193862306a36Sopenharmony_ci u8 table_case, tdma_case; 193962306a36Sopenharmony_ci u32 slot_type = 0; 194062306a36Sopenharmony_ci bool bt_multi_link_remain = false, is_toggle_table = false; 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 194362306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 194462306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 194562306a36Sopenharmony_ci 194662306a36Sopenharmony_ci if (efuse->share_ant) { 194762306a36Sopenharmony_ci /* Shared-Ant */ 194862306a36Sopenharmony_ci if (coex_stat->bt_ble_exist) { 194962306a36Sopenharmony_ci /* RCU */ 195062306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) { 195162306a36Sopenharmony_ci table_case = 26; 195262306a36Sopenharmony_ci tdma_case = 2; 195362306a36Sopenharmony_ci } else { 195462306a36Sopenharmony_ci table_case = 27; 195562306a36Sopenharmony_ci tdma_case = 9; 195662306a36Sopenharmony_ci } 195762306a36Sopenharmony_ci } else { 195862306a36Sopenharmony_ci /* Legacy HID */ 195962306a36Sopenharmony_ci if (coex_stat->bt_profile_num == 1 && 196062306a36Sopenharmony_ci (coex_stat->bt_multi_link || 196162306a36Sopenharmony_ci (coex_stat->lo_pri_rx + 196262306a36Sopenharmony_ci coex_stat->lo_pri_tx > 360) || 196362306a36Sopenharmony_ci coex_stat->bt_slave || 196462306a36Sopenharmony_ci bt_multi_link_remain)) { 196562306a36Sopenharmony_ci slot_type = TDMA_4SLOT; 196662306a36Sopenharmony_ci table_case = 12; 196762306a36Sopenharmony_ci tdma_case = 20; 196862306a36Sopenharmony_ci } else if (coex_stat->bt_a2dp_active) { 196962306a36Sopenharmony_ci table_case = 9; 197062306a36Sopenharmony_ci tdma_case = 18; 197162306a36Sopenharmony_ci } else if (coex_stat->bt_418_hid_exist && 197262306a36Sopenharmony_ci coex_stat->wl_gl_busy) { 197362306a36Sopenharmony_ci is_toggle_table = true; 197462306a36Sopenharmony_ci slot_type = TDMA_4SLOT; 197562306a36Sopenharmony_ci table_case = 9; 197662306a36Sopenharmony_ci tdma_case = 24; 197762306a36Sopenharmony_ci } else if (coex_stat->bt_ble_hid_exist && 197862306a36Sopenharmony_ci coex_stat->wl_gl_busy) { 197962306a36Sopenharmony_ci table_case = 32; 198062306a36Sopenharmony_ci tdma_case = 9; 198162306a36Sopenharmony_ci } else { 198262306a36Sopenharmony_ci table_case = 9; 198362306a36Sopenharmony_ci tdma_case = 9; 198462306a36Sopenharmony_ci } 198562306a36Sopenharmony_ci } 198662306a36Sopenharmony_ci } else { 198762306a36Sopenharmony_ci /* Non-Shared-Ant */ 198862306a36Sopenharmony_ci if (coex_stat->bt_ble_exist) { 198962306a36Sopenharmony_ci /* BLE */ 199062306a36Sopenharmony_ci if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) { 199162306a36Sopenharmony_ci table_case = 121; 199262306a36Sopenharmony_ci tdma_case = 102; 199362306a36Sopenharmony_ci } else { 199462306a36Sopenharmony_ci table_case = 122; 199562306a36Sopenharmony_ci tdma_case = 109; 199662306a36Sopenharmony_ci } 199762306a36Sopenharmony_ci } else if (coex_stat->bt_a2dp_active) { 199862306a36Sopenharmony_ci table_case = 113; 199962306a36Sopenharmony_ci tdma_case = 118; 200062306a36Sopenharmony_ci } else { 200162306a36Sopenharmony_ci table_case = 113; 200262306a36Sopenharmony_ci tdma_case = 104; 200362306a36Sopenharmony_ci } 200462306a36Sopenharmony_ci } 200562306a36Sopenharmony_ci 200662306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 200762306a36Sopenharmony_ci if (is_toggle_table) { 200862306a36Sopenharmony_ci rtw_btc_wltoggle_table_a(rtwdev, true, table_case); 200962306a36Sopenharmony_ci rtw_btc_wltoggle_table_b(rtwdev, false, 1, COEX_WL_SLOT_TOGLLE); 201062306a36Sopenharmony_ci } 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 201362306a36Sopenharmony_ci} 201462306a36Sopenharmony_ci 201562306a36Sopenharmony_cistatic void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev) 201662306a36Sopenharmony_ci{ 201762306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 201862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 201962306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 202062306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 202162306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 202262306a36Sopenharmony_ci u8 table_case, tdma_case; 202362306a36Sopenharmony_ci u32 slot_type = 0; 202462306a36Sopenharmony_ci 202562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 202862306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci slot_type = TDMA_4SLOT; 203162306a36Sopenharmony_ci 203262306a36Sopenharmony_ci if (efuse->share_ant) { 203362306a36Sopenharmony_ci /* Shared-Ant */ 203462306a36Sopenharmony_ci if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) 203562306a36Sopenharmony_ci table_case = 12; 203662306a36Sopenharmony_ci else 203762306a36Sopenharmony_ci table_case = 9; 203862306a36Sopenharmony_ci 203962306a36Sopenharmony_ci if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) 204062306a36Sopenharmony_ci tdma_case = 14; 204162306a36Sopenharmony_ci else 204262306a36Sopenharmony_ci tdma_case = 13; 204362306a36Sopenharmony_ci } else { 204462306a36Sopenharmony_ci /* Non-Shared-Ant */ 204562306a36Sopenharmony_ci table_case = 112; 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 204862306a36Sopenharmony_ci tdma_case = 112; 204962306a36Sopenharmony_ci else 205062306a36Sopenharmony_ci tdma_case = 113; 205162306a36Sopenharmony_ci } 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 205462306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 205562306a36Sopenharmony_ci} 205662306a36Sopenharmony_ci 205762306a36Sopenharmony_cistatic void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev) 205862306a36Sopenharmony_ci{ 205962306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 206062306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 206162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 206262306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 206362306a36Sopenharmony_ci u8 table_case, tdma_case; 206462306a36Sopenharmony_ci bool ap_enable = false; 206562306a36Sopenharmony_ci 206662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 206962306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 207062306a36Sopenharmony_ci 207162306a36Sopenharmony_ci if (efuse->share_ant) { /* Shared-Ant */ 207262306a36Sopenharmony_ci if (ap_enable) { 207362306a36Sopenharmony_ci table_case = 2; 207462306a36Sopenharmony_ci tdma_case = 0; 207562306a36Sopenharmony_ci } else if (coex_stat->wl_gl_busy) { 207662306a36Sopenharmony_ci table_case = 28; 207762306a36Sopenharmony_ci tdma_case = 20; 207862306a36Sopenharmony_ci } else { 207962306a36Sopenharmony_ci table_case = 28; 208062306a36Sopenharmony_ci tdma_case = 26; 208162306a36Sopenharmony_ci } 208262306a36Sopenharmony_ci } else { /* Non-Shared-Ant */ 208362306a36Sopenharmony_ci if (ap_enable) { 208462306a36Sopenharmony_ci table_case = 100; 208562306a36Sopenharmony_ci tdma_case = 100; 208662306a36Sopenharmony_ci } else { 208762306a36Sopenharmony_ci table_case = 119; 208862306a36Sopenharmony_ci tdma_case = 120; 208962306a36Sopenharmony_ci } 209062306a36Sopenharmony_ci } 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 209362306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 209462306a36Sopenharmony_ci} 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_cistatic void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev) 209762306a36Sopenharmony_ci{ 209862306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 209962306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 210062306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 210162306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 210262306a36Sopenharmony_ci u8 table_case, tdma_case; 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 210562306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 210662306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci if (efuse->share_ant) { 210962306a36Sopenharmony_ci /* Shared-Ant */ 211062306a36Sopenharmony_ci if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) 211162306a36Sopenharmony_ci table_case = 14; 211262306a36Sopenharmony_ci else 211362306a36Sopenharmony_ci table_case = 10; 211462306a36Sopenharmony_ci 211562306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 211662306a36Sopenharmony_ci tdma_case = 17; 211762306a36Sopenharmony_ci else 211862306a36Sopenharmony_ci tdma_case = 20; 211962306a36Sopenharmony_ci } else { 212062306a36Sopenharmony_ci /* Non-Shared-Ant */ 212162306a36Sopenharmony_ci table_case = 112; 212262306a36Sopenharmony_ci 212362306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 212462306a36Sopenharmony_ci tdma_case = 117; 212562306a36Sopenharmony_ci else 212662306a36Sopenharmony_ci tdma_case = 119; 212762306a36Sopenharmony_ci } 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 213062306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 213162306a36Sopenharmony_ci} 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_cistatic void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev) 213462306a36Sopenharmony_ci{ 213562306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 213662306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 213762306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 213862306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 213962306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 214062306a36Sopenharmony_ci u8 table_case, tdma_case, interval = 0; 214162306a36Sopenharmony_ci u32 slot_type = 0; 214262306a36Sopenharmony_ci bool is_toggle_table = false; 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_ci slot_type = TDMA_4SLOT; 214562306a36Sopenharmony_ci 214662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 214762306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 214862306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 214962306a36Sopenharmony_ci 215062306a36Sopenharmony_ci if (efuse->share_ant) { 215162306a36Sopenharmony_ci /* Shared-Ant */ 215262306a36Sopenharmony_ci if (coex_stat->bt_ble_exist) { 215362306a36Sopenharmony_ci table_case = 26; /* for RCU */ 215462306a36Sopenharmony_ci } else if (coex_stat->bt_418_hid_exist) { 215562306a36Sopenharmony_ci table_case = 9; 215662306a36Sopenharmony_ci interval = 1; 215762306a36Sopenharmony_ci } else { 215862306a36Sopenharmony_ci table_case = 9; 215962306a36Sopenharmony_ci } 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) { 216262306a36Sopenharmony_ci tdma_case = 14; 216362306a36Sopenharmony_ci } else if (coex_stat->bt_418_hid_exist) { 216462306a36Sopenharmony_ci is_toggle_table = true; 216562306a36Sopenharmony_ci tdma_case = 23; 216662306a36Sopenharmony_ci } else { 216762306a36Sopenharmony_ci tdma_case = 13; 216862306a36Sopenharmony_ci } 216962306a36Sopenharmony_ci } else { 217062306a36Sopenharmony_ci /* Non-Shared-Ant */ 217162306a36Sopenharmony_ci if (coex_stat->bt_ble_exist) 217262306a36Sopenharmony_ci table_case = 121; 217362306a36Sopenharmony_ci else 217462306a36Sopenharmony_ci table_case = 113; 217562306a36Sopenharmony_ci 217662306a36Sopenharmony_ci if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 217762306a36Sopenharmony_ci tdma_case = 112; 217862306a36Sopenharmony_ci else 217962306a36Sopenharmony_ci tdma_case = 113; 218062306a36Sopenharmony_ci } 218162306a36Sopenharmony_ci 218262306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 218362306a36Sopenharmony_ci if (is_toggle_table) { 218462306a36Sopenharmony_ci rtw_btc_wltoggle_table_a(rtwdev, true, table_case); 218562306a36Sopenharmony_ci rtw_btc_wltoggle_table_b(rtwdev, false, interval, COEX_WL_SLOT_TOGLLE); 218662306a36Sopenharmony_ci } 218762306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 218862306a36Sopenharmony_ci} 218962306a36Sopenharmony_ci 219062306a36Sopenharmony_cistatic void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) 219162306a36Sopenharmony_ci{ 219262306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 219362306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 219462306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 219562306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 219662306a36Sopenharmony_ci u8 table_case, tdma_case; 219762306a36Sopenharmony_ci bool wl_cpt_test = false, bt_cpt_test = false; 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 220062306a36Sopenharmony_ci 220162306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 220262306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 220362306a36Sopenharmony_ci if (efuse->share_ant) { 220462306a36Sopenharmony_ci /* Shared-Ant */ 220562306a36Sopenharmony_ci if (wl_cpt_test) { 220662306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) { 220762306a36Sopenharmony_ci table_case = 20; 220862306a36Sopenharmony_ci tdma_case = 17; 220962306a36Sopenharmony_ci } else { 221062306a36Sopenharmony_ci table_case = 10; 221162306a36Sopenharmony_ci tdma_case = 15; 221262306a36Sopenharmony_ci } 221362306a36Sopenharmony_ci } else if (bt_cpt_test) { 221462306a36Sopenharmony_ci table_case = 26; 221562306a36Sopenharmony_ci tdma_case = 26; 221662306a36Sopenharmony_ci } else { 221762306a36Sopenharmony_ci if (coex_stat->wl_gl_busy && 221862306a36Sopenharmony_ci coex_stat->wl_noisy_level == 0) 221962306a36Sopenharmony_ci table_case = 14; 222062306a36Sopenharmony_ci else 222162306a36Sopenharmony_ci table_case = 10; 222262306a36Sopenharmony_ci 222362306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 222462306a36Sopenharmony_ci tdma_case = 15; 222562306a36Sopenharmony_ci else 222662306a36Sopenharmony_ci tdma_case = 20; 222762306a36Sopenharmony_ci } 222862306a36Sopenharmony_ci } else { 222962306a36Sopenharmony_ci /* Non-Shared-Ant */ 223062306a36Sopenharmony_ci table_case = 112; 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 223362306a36Sopenharmony_ci tdma_case = 115; 223462306a36Sopenharmony_ci else 223562306a36Sopenharmony_ci tdma_case = 120; 223662306a36Sopenharmony_ci } 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci if (wl_cpt_test) 223962306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[1]); 224062306a36Sopenharmony_ci else 224162306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 224262306a36Sopenharmony_ci 224362306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 224462306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 224562306a36Sopenharmony_ci} 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_cistatic void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev) 224862306a36Sopenharmony_ci{ 224962306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 225062306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 225162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 225262306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 225362306a36Sopenharmony_ci u8 table_case, tdma_case; 225462306a36Sopenharmony_ci 225562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 225662306a36Sopenharmony_ci 225762306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 225862306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci if (efuse->share_ant) { 226162306a36Sopenharmony_ci /* Shared-Ant */ 226262306a36Sopenharmony_ci table_case = 9; 226362306a36Sopenharmony_ci 226462306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 226562306a36Sopenharmony_ci tdma_case = 18; 226662306a36Sopenharmony_ci else 226762306a36Sopenharmony_ci tdma_case = 19; 226862306a36Sopenharmony_ci } else { 226962306a36Sopenharmony_ci /* Non-Shared-Ant */ 227062306a36Sopenharmony_ci table_case = 113; 227162306a36Sopenharmony_ci 227262306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 227362306a36Sopenharmony_ci tdma_case = 117; 227462306a36Sopenharmony_ci else 227562306a36Sopenharmony_ci tdma_case = 119; 227662306a36Sopenharmony_ci } 227762306a36Sopenharmony_ci 227862306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 227962306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 228062306a36Sopenharmony_ci} 228162306a36Sopenharmony_ci 228262306a36Sopenharmony_cistatic void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev) 228362306a36Sopenharmony_ci{ 228462306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 228562306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 228662306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 228762306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 228862306a36Sopenharmony_ci u8 table_case, tdma_case; 228962306a36Sopenharmony_ci 229062306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 229162306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 229262306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 229362306a36Sopenharmony_ci 229462306a36Sopenharmony_ci if (efuse->share_ant) { 229562306a36Sopenharmony_ci /* Shared-Ant */ 229662306a36Sopenharmony_ci table_case = 10; 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 229962306a36Sopenharmony_ci tdma_case = 15; 230062306a36Sopenharmony_ci else 230162306a36Sopenharmony_ci tdma_case = 20; 230262306a36Sopenharmony_ci } else { 230362306a36Sopenharmony_ci /* Non-Shared-Ant */ 230462306a36Sopenharmony_ci table_case = 113; 230562306a36Sopenharmony_ci 230662306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 230762306a36Sopenharmony_ci tdma_case = 115; 230862306a36Sopenharmony_ci else 230962306a36Sopenharmony_ci tdma_case = 120; 231062306a36Sopenharmony_ci } 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 231362306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 231462306a36Sopenharmony_ci} 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_cistatic void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev) 231762306a36Sopenharmony_ci{ 231862306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 231962306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 232062306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 232162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 232262306a36Sopenharmony_ci u8 table_case, tdma_case; 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 232562306a36Sopenharmony_ci 232662306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 232762306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 232862306a36Sopenharmony_ci 232962306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 233062306a36Sopenharmony_ci 233162306a36Sopenharmony_ci if (coex_stat->bt_game_hid_exist && coex_stat->wl_linkscan_proc) 233262306a36Sopenharmony_ci coex_stat->wl_coex_mode = COEX_WLINK_2GFREE; 233362306a36Sopenharmony_ci 233462306a36Sopenharmony_ci if (efuse->share_ant) { 233562306a36Sopenharmony_ci /* Shared-Ant */ 233662306a36Sopenharmony_ci table_case = 0; 233762306a36Sopenharmony_ci tdma_case = 0; 233862306a36Sopenharmony_ci } else { 233962306a36Sopenharmony_ci /* Non-Shared-Ant */ 234062306a36Sopenharmony_ci table_case = 100; 234162306a36Sopenharmony_ci tdma_case = 100; 234262306a36Sopenharmony_ci } 234362306a36Sopenharmony_ci 234462306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 234562306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 234662306a36Sopenharmony_ci} 234762306a36Sopenharmony_ci 234862306a36Sopenharmony_cistatic void rtw_coex_action_wl_only(struct rtw_dev *rtwdev) 234962306a36Sopenharmony_ci{ 235062306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 235162306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 235262306a36Sopenharmony_ci u8 table_case, tdma_case; 235362306a36Sopenharmony_ci 235462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 235562306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 235662306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci if (efuse->share_ant) { 235962306a36Sopenharmony_ci /* Shared-Ant */ 236062306a36Sopenharmony_ci table_case = 2; 236162306a36Sopenharmony_ci tdma_case = 0; 236262306a36Sopenharmony_ci } else { 236362306a36Sopenharmony_ci /* Non-Shared-Ant */ 236462306a36Sopenharmony_ci table_case = 100; 236562306a36Sopenharmony_ci tdma_case = 100; 236662306a36Sopenharmony_ci } 236762306a36Sopenharmony_ci 236862306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 236962306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 237062306a36Sopenharmony_ci} 237162306a36Sopenharmony_ci 237262306a36Sopenharmony_cistatic void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev) 237362306a36Sopenharmony_ci{ 237462306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 237562306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 237662306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 237762306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 237862306a36Sopenharmony_ci u8 table_case, tdma_case; 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci if (coex->under_5g) 238162306a36Sopenharmony_ci return; 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 238462306a36Sopenharmony_ci 238562306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 238662306a36Sopenharmony_ci 238762306a36Sopenharmony_ci if (efuse->share_ant) { 238862306a36Sopenharmony_ci /* Shared-Ant */ 238962306a36Sopenharmony_ci table_case = 28; 239062306a36Sopenharmony_ci tdma_case = 0; 239162306a36Sopenharmony_ci } else { 239262306a36Sopenharmony_ci /* Non-Shared-Ant */ 239362306a36Sopenharmony_ci table_case = 100; 239462306a36Sopenharmony_ci tdma_case = 100; 239562306a36Sopenharmony_ci } 239662306a36Sopenharmony_ci 239762306a36Sopenharmony_ci if (coex_stat->bt_game_hid_exist) { 239862306a36Sopenharmony_ci coex_stat->wl_coex_mode = COEX_WLINK_2GFREE; 239962306a36Sopenharmony_ci if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) 240062306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]); 240162306a36Sopenharmony_ci else 240262306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]); 240362306a36Sopenharmony_ci } else { 240462306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 240562306a36Sopenharmony_ci } 240662306a36Sopenharmony_ci 240762306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 240862306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 240962306a36Sopenharmony_ci} 241062306a36Sopenharmony_ci 241162306a36Sopenharmony_cistatic void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev) 241262306a36Sopenharmony_ci{ 241362306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 241462306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 241562306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 241662306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 241762306a36Sopenharmony_ci u8 table_case, tdma_case; 241862306a36Sopenharmony_ci u32 slot_type = 0; 241962306a36Sopenharmony_ci 242062306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 242162306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 242262306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 242362306a36Sopenharmony_ci 242462306a36Sopenharmony_ci if (efuse->share_ant) { /* Shared-Ant */ 242562306a36Sopenharmony_ci if (coex_stat->bt_a2dp_exist) { 242662306a36Sopenharmony_ci slot_type = TDMA_4SLOT; 242762306a36Sopenharmony_ci tdma_case = 11; 242862306a36Sopenharmony_ci if (coex_stat->wl_gl_busy) 242962306a36Sopenharmony_ci table_case = 26; 243062306a36Sopenharmony_ci else 243162306a36Sopenharmony_ci table_case = 9; 243262306a36Sopenharmony_ci } else { 243362306a36Sopenharmony_ci table_case = 9; 243462306a36Sopenharmony_ci tdma_case = 7; 243562306a36Sopenharmony_ci } 243662306a36Sopenharmony_ci } else { /* Non-Shared-Ant */ 243762306a36Sopenharmony_ci if (coex_stat->bt_a2dp_exist) { 243862306a36Sopenharmony_ci slot_type = TDMA_4SLOT; 243962306a36Sopenharmony_ci table_case = 112; 244062306a36Sopenharmony_ci tdma_case = 111; 244162306a36Sopenharmony_ci } else { 244262306a36Sopenharmony_ci table_case = 112; 244362306a36Sopenharmony_ci tdma_case = 107; 244462306a36Sopenharmony_ci } 244562306a36Sopenharmony_ci } 244662306a36Sopenharmony_ci 244762306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 244862306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 244962306a36Sopenharmony_ci} 245062306a36Sopenharmony_ci 245162306a36Sopenharmony_cistatic void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev) 245262306a36Sopenharmony_ci{ 245362306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 245462306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 245562306a36Sopenharmony_ci u8 table_case, tdma_case; 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 245862306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 245962306a36Sopenharmony_ci rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 246062306a36Sopenharmony_ci 246162306a36Sopenharmony_ci if (efuse->share_ant) { 246262306a36Sopenharmony_ci /* Shared-Ant */ 246362306a36Sopenharmony_ci table_case = 1; 246462306a36Sopenharmony_ci tdma_case = 0; 246562306a36Sopenharmony_ci } else { 246662306a36Sopenharmony_ci /* Non-Shared-Ant */ 246762306a36Sopenharmony_ci table_case = 100; 246862306a36Sopenharmony_ci tdma_case = 100; 246962306a36Sopenharmony_ci } 247062306a36Sopenharmony_ci 247162306a36Sopenharmony_ci rtw_coex_table(rtwdev, false, table_case); 247262306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, false, tdma_case); 247362306a36Sopenharmony_ci} 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_cistatic void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev) 247662306a36Sopenharmony_ci{ 247762306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 247862306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 247962306a36Sopenharmony_ci u8 algorithm; 248062306a36Sopenharmony_ci 248162306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 248262306a36Sopenharmony_ci 248362306a36Sopenharmony_ci algorithm = rtw_coex_algorithm(rtwdev); 248462306a36Sopenharmony_ci 248562306a36Sopenharmony_ci switch (algorithm) { 248662306a36Sopenharmony_ci case COEX_ALGO_HFP: 248762306a36Sopenharmony_ci rtw_coex_action_bt_hfp(rtwdev); 248862306a36Sopenharmony_ci break; 248962306a36Sopenharmony_ci case COEX_ALGO_HID: 249062306a36Sopenharmony_ci if (rtw_coex_freerun_check(rtwdev)) 249162306a36Sopenharmony_ci rtw_coex_action_freerun(rtwdev); 249262306a36Sopenharmony_ci else 249362306a36Sopenharmony_ci rtw_coex_action_bt_hid(rtwdev); 249462306a36Sopenharmony_ci break; 249562306a36Sopenharmony_ci case COEX_ALGO_A2DP: 249662306a36Sopenharmony_ci if (rtw_coex_freerun_check(rtwdev)) 249762306a36Sopenharmony_ci rtw_coex_action_freerun(rtwdev); 249862306a36Sopenharmony_ci else if (coex_stat->bt_a2dp_sink) 249962306a36Sopenharmony_ci rtw_coex_action_bt_a2dpsink(rtwdev); 250062306a36Sopenharmony_ci else 250162306a36Sopenharmony_ci rtw_coex_action_bt_a2dp(rtwdev); 250262306a36Sopenharmony_ci break; 250362306a36Sopenharmony_ci case COEX_ALGO_PAN: 250462306a36Sopenharmony_ci rtw_coex_action_bt_pan(rtwdev); 250562306a36Sopenharmony_ci break; 250662306a36Sopenharmony_ci case COEX_ALGO_A2DP_HID: 250762306a36Sopenharmony_ci if (rtw_coex_freerun_check(rtwdev)) 250862306a36Sopenharmony_ci rtw_coex_action_freerun(rtwdev); 250962306a36Sopenharmony_ci else 251062306a36Sopenharmony_ci rtw_coex_action_bt_a2dp_hid(rtwdev); 251162306a36Sopenharmony_ci break; 251262306a36Sopenharmony_ci case COEX_ALGO_A2DP_PAN: 251362306a36Sopenharmony_ci rtw_coex_action_bt_a2dp_pan(rtwdev); 251462306a36Sopenharmony_ci break; 251562306a36Sopenharmony_ci case COEX_ALGO_PAN_HID: 251662306a36Sopenharmony_ci rtw_coex_action_bt_pan_hid(rtwdev); 251762306a36Sopenharmony_ci break; 251862306a36Sopenharmony_ci case COEX_ALGO_A2DP_PAN_HID: 251962306a36Sopenharmony_ci rtw_coex_action_bt_a2dp_pan_hid(rtwdev); 252062306a36Sopenharmony_ci break; 252162306a36Sopenharmony_ci default: 252262306a36Sopenharmony_ci case COEX_ALGO_NOPROFILE: 252362306a36Sopenharmony_ci rtw_coex_action_bt_idle(rtwdev); 252462306a36Sopenharmony_ci break; 252562306a36Sopenharmony_ci } 252662306a36Sopenharmony_ci} 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_cistatic void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) 252962306a36Sopenharmony_ci{ 253062306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 253162306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 253262306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 253362306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 253462306a36Sopenharmony_ci bool rf4ce_en = false; 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ci lockdep_assert_held(&rtwdev->mutex); 253762306a36Sopenharmony_ci 253862306a36Sopenharmony_ci if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags)) 253962306a36Sopenharmony_ci return; 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci coex_dm->reason = reason; 254262306a36Sopenharmony_ci 254362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): reason = %d\n", __func__, 254462306a36Sopenharmony_ci reason); 254562306a36Sopenharmony_ci 254662306a36Sopenharmony_ci /* update wifi_link_info_ext variable */ 254762306a36Sopenharmony_ci rtw_coex_update_wl_link_info(rtwdev, reason); 254862306a36Sopenharmony_ci 254962306a36Sopenharmony_ci rtw_coex_monitor_bt_enable(rtwdev); 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci if (coex->manual_control) { 255262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 255362306a36Sopenharmony_ci "[BTCoex], return for Manual CTRL!!\n"); 255462306a36Sopenharmony_ci return; 255562306a36Sopenharmony_ci } 255662306a36Sopenharmony_ci 255762306a36Sopenharmony_ci if (coex->stop_dm) { 255862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 255962306a36Sopenharmony_ci "[BTCoex], return for Stop Coex DM!!\n"); 256062306a36Sopenharmony_ci return; 256162306a36Sopenharmony_ci } 256262306a36Sopenharmony_ci 256362306a36Sopenharmony_ci if (coex_stat->wl_under_ips) { 256462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 256562306a36Sopenharmony_ci "[BTCoex], return for wifi is under IPS!!\n"); 256662306a36Sopenharmony_ci return; 256762306a36Sopenharmony_ci } 256862306a36Sopenharmony_ci 256962306a36Sopenharmony_ci if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO && 257062306a36Sopenharmony_ci !coex_stat->bt_setup_link) { 257162306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 257262306a36Sopenharmony_ci "[BTCoex], return for coex_freeze!!\n"); 257362306a36Sopenharmony_ci return; 257462306a36Sopenharmony_ci } 257562306a36Sopenharmony_ci 257662306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++; 257762306a36Sopenharmony_ci coex->freerun = false; 257862306a36Sopenharmony_ci 257962306a36Sopenharmony_ci /* Pure-5G Coex Process */ 258062306a36Sopenharmony_ci if (coex->under_5g) { 258162306a36Sopenharmony_ci coex_stat->wl_coex_mode = COEX_WLINK_5G; 258262306a36Sopenharmony_ci rtw_coex_action_wl_under5g(rtwdev); 258362306a36Sopenharmony_ci goto exit; 258462306a36Sopenharmony_ci } 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WiFi is single-port 2G!!\n"); 258762306a36Sopenharmony_ci coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT; 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_ci if (coex_stat->bt_disabled) { 259062306a36Sopenharmony_ci if (coex_stat->wl_connected && rf4ce_en) 259162306a36Sopenharmony_ci rtw_coex_action_rf4ce(rtwdev); 259262306a36Sopenharmony_ci else if (!coex_stat->wl_connected) 259362306a36Sopenharmony_ci rtw_coex_action_wl_not_connected(rtwdev); 259462306a36Sopenharmony_ci else 259562306a36Sopenharmony_ci rtw_coex_action_wl_only(rtwdev); 259662306a36Sopenharmony_ci goto exit; 259762306a36Sopenharmony_ci } 259862306a36Sopenharmony_ci 259962306a36Sopenharmony_ci if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) { 260062306a36Sopenharmony_ci rtw_coex_action_wl_native_lps(rtwdev); 260162306a36Sopenharmony_ci goto exit; 260262306a36Sopenharmony_ci } 260362306a36Sopenharmony_ci 260462306a36Sopenharmony_ci if (coex_stat->bt_game_hid_exist && coex_stat->wl_connected) { 260562306a36Sopenharmony_ci rtw_coex_action_bt_game_hid(rtwdev); 260662306a36Sopenharmony_ci goto exit; 260762306a36Sopenharmony_ci } 260862306a36Sopenharmony_ci 260962306a36Sopenharmony_ci if (coex_stat->bt_whck_test) { 261062306a36Sopenharmony_ci rtw_coex_action_bt_whql_test(rtwdev); 261162306a36Sopenharmony_ci goto exit; 261262306a36Sopenharmony_ci } 261362306a36Sopenharmony_ci 261462306a36Sopenharmony_ci if (coex_stat->bt_setup_link) { 261562306a36Sopenharmony_ci rtw_coex_action_bt_relink(rtwdev); 261662306a36Sopenharmony_ci goto exit; 261762306a36Sopenharmony_ci } 261862306a36Sopenharmony_ci 261962306a36Sopenharmony_ci if (coex_stat->bt_inq_page) { 262062306a36Sopenharmony_ci rtw_coex_action_bt_inquiry(rtwdev); 262162306a36Sopenharmony_ci goto exit; 262262306a36Sopenharmony_ci } 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_ci if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE || 262562306a36Sopenharmony_ci coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) && 262662306a36Sopenharmony_ci coex_stat->wl_connected) { 262762306a36Sopenharmony_ci rtw_coex_action_bt_idle(rtwdev); 262862306a36Sopenharmony_ci goto exit; 262962306a36Sopenharmony_ci } 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ci if (coex_stat->wl_linkscan_proc && !coex->freerun) { 263262306a36Sopenharmony_ci rtw_coex_action_wl_linkscan(rtwdev); 263362306a36Sopenharmony_ci goto exit; 263462306a36Sopenharmony_ci } 263562306a36Sopenharmony_ci 263662306a36Sopenharmony_ci if (coex_stat->wl_connected) { 263762306a36Sopenharmony_ci rtw_coex_action_wl_connected(rtwdev); 263862306a36Sopenharmony_ci goto exit; 263962306a36Sopenharmony_ci } else { 264062306a36Sopenharmony_ci rtw_coex_action_wl_not_connected(rtwdev); 264162306a36Sopenharmony_ci goto exit; 264262306a36Sopenharmony_ci } 264362306a36Sopenharmony_ci 264462306a36Sopenharmony_ciexit: 264562306a36Sopenharmony_ci 264662306a36Sopenharmony_ci if (chip->wl_mimo_ps_support) { 264762306a36Sopenharmony_ci if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) { 264862306a36Sopenharmony_ci if (coex_dm->reason == COEX_RSN_2GMEDIA) 264962306a36Sopenharmony_ci rtw_coex_mimo_ps(rtwdev, true, true); 265062306a36Sopenharmony_ci else 265162306a36Sopenharmony_ci rtw_coex_mimo_ps(rtwdev, false, true); 265262306a36Sopenharmony_ci } else { 265362306a36Sopenharmony_ci rtw_coex_mimo_ps(rtwdev, false, false); 265462306a36Sopenharmony_ci } 265562306a36Sopenharmony_ci } 265662306a36Sopenharmony_ci 265762306a36Sopenharmony_ci rtw_coex_gnt_workaround(rtwdev, false, coex_stat->wl_coex_mode); 265862306a36Sopenharmony_ci rtw_coex_limited_wl(rtwdev); 265962306a36Sopenharmony_ci} 266062306a36Sopenharmony_ci 266162306a36Sopenharmony_cistatic void rtw_coex_init_coex_var(struct rtw_dev *rtwdev) 266262306a36Sopenharmony_ci{ 266362306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 266462306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 266562306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 266662306a36Sopenharmony_ci u8 i; 266762306a36Sopenharmony_ci 266862306a36Sopenharmony_ci memset(coex_dm, 0, sizeof(*coex_dm)); 266962306a36Sopenharmony_ci memset(coex_stat, 0, sizeof(*coex_stat)); 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ci for (i = 0; i < COEX_CNT_WL_MAX; i++) 267262306a36Sopenharmony_ci coex_stat->cnt_wl[i] = 0; 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci for (i = 0; i < COEX_CNT_BT_MAX; i++) 267562306a36Sopenharmony_ci coex_stat->cnt_bt[i] = 0; 267662306a36Sopenharmony_ci 267762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++) 267862306a36Sopenharmony_ci coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW; 267962306a36Sopenharmony_ci 268062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++) 268162306a36Sopenharmony_ci coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW; 268262306a36Sopenharmony_ci 268362306a36Sopenharmony_ci coex_stat->wl_coex_mode = COEX_WLINK_MAX; 268462306a36Sopenharmony_ci coex_stat->wl_rx_rate = DESC_RATE5_5M; 268562306a36Sopenharmony_ci coex_stat->wl_rts_rx_rate = DESC_RATE5_5M; 268662306a36Sopenharmony_ci} 268762306a36Sopenharmony_ci 268862306a36Sopenharmony_cistatic void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) 268962306a36Sopenharmony_ci{ 269062306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 269162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 269262306a36Sopenharmony_ci 269362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_ci rtw_coex_init_coex_var(rtwdev); 269662306a36Sopenharmony_ci 269762306a36Sopenharmony_ci coex_stat->kt_ver = u8_get_bits(rtw_read8(rtwdev, 0xf1), GENMASK(7, 4)); 269862306a36Sopenharmony_ci 269962306a36Sopenharmony_ci rtw_coex_monitor_bt_enable(rtwdev); 270062306a36Sopenharmony_ci rtw_coex_wl_slot_extend(rtwdev, coex_stat->wl_slot_extend); 270162306a36Sopenharmony_ci 270262306a36Sopenharmony_ci rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); 270362306a36Sopenharmony_ci 270462306a36Sopenharmony_ci rtw_coex_set_rfe_type(rtwdev); 270562306a36Sopenharmony_ci rtw_coex_set_init(rtwdev); 270662306a36Sopenharmony_ci 270762306a36Sopenharmony_ci /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */ 270862306a36Sopenharmony_ci rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1); 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_ci /* set Tx beacon = Hi-Pri */ 271162306a36Sopenharmony_ci rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1); 271262306a36Sopenharmony_ci 271362306a36Sopenharmony_ci /* set Tx beacon queue = Hi-Pri */ 271462306a36Sopenharmony_ci rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1); 271562306a36Sopenharmony_ci 271662306a36Sopenharmony_ci /* antenna config */ 271762306a36Sopenharmony_ci if (coex->wl_rf_off) { 271862306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); 271962306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false); 272062306a36Sopenharmony_ci coex->stop_dm = true; 272162306a36Sopenharmony_ci 272262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): RF Off\n", 272362306a36Sopenharmony_ci __func__); 272462306a36Sopenharmony_ci } else if (wifi_only) { 272562306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY); 272662306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, 272762306a36Sopenharmony_ci true); 272862306a36Sopenharmony_ci coex->stop_dm = true; 272962306a36Sopenharmony_ci } else { 273062306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT); 273162306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, 273262306a36Sopenharmony_ci true); 273362306a36Sopenharmony_ci coex->stop_dm = false; 273462306a36Sopenharmony_ci coex->freeze = true; 273562306a36Sopenharmony_ci } 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_ci /* PTA parameter */ 273862306a36Sopenharmony_ci rtw_coex_table(rtwdev, true, 1); 273962306a36Sopenharmony_ci rtw_coex_tdma(rtwdev, true, 0); 274062306a36Sopenharmony_ci rtw_coex_query_bt_info(rtwdev); 274162306a36Sopenharmony_ci} 274262306a36Sopenharmony_ci 274362306a36Sopenharmony_civoid rtw_coex_power_on_setting(struct rtw_dev *rtwdev) 274462306a36Sopenharmony_ci{ 274562306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 274662306a36Sopenharmony_ci u8 table_case = 1; 274762306a36Sopenharmony_ci 274862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci coex->stop_dm = true; 275162306a36Sopenharmony_ci coex->wl_rf_off = false; 275262306a36Sopenharmony_ci 275362306a36Sopenharmony_ci /* enable BB, we can write 0x948 */ 275462306a36Sopenharmony_ci rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, 275562306a36Sopenharmony_ci BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB); 275662306a36Sopenharmony_ci 275762306a36Sopenharmony_ci rtw_coex_monitor_bt_enable(rtwdev); 275862306a36Sopenharmony_ci rtw_coex_set_rfe_type(rtwdev); 275962306a36Sopenharmony_ci 276062306a36Sopenharmony_ci /* set antenna path to BT */ 276162306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON); 276262306a36Sopenharmony_ci 276362306a36Sopenharmony_ci rtw_coex_table(rtwdev, true, table_case); 276462306a36Sopenharmony_ci /* red x issue */ 276562306a36Sopenharmony_ci rtw_write8(rtwdev, 0xff1a, 0x0); 276662306a36Sopenharmony_ci rtw_coex_set_gnt_debug(rtwdev); 276762306a36Sopenharmony_ci} 276862306a36Sopenharmony_ci 276962306a36Sopenharmony_civoid rtw_coex_power_off_setting(struct rtw_dev *rtwdev) 277062306a36Sopenharmony_ci{ 277162306a36Sopenharmony_ci rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN); 277262306a36Sopenharmony_ci} 277362306a36Sopenharmony_ci 277462306a36Sopenharmony_civoid rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) 277562306a36Sopenharmony_ci{ 277662306a36Sopenharmony_ci __rtw_coex_init_hw_config(rtwdev, wifi_only); 277762306a36Sopenharmony_ci} 277862306a36Sopenharmony_ci 277962306a36Sopenharmony_civoid rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type) 278062306a36Sopenharmony_ci{ 278162306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 278262306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 278362306a36Sopenharmony_ci 278462306a36Sopenharmony_ci if (coex->manual_control || coex->stop_dm) 278562306a36Sopenharmony_ci return; 278662306a36Sopenharmony_ci 278762306a36Sopenharmony_ci if (type == COEX_IPS_ENTER) { 278862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS ENTER notify\n"); 278962306a36Sopenharmony_ci 279062306a36Sopenharmony_ci coex_stat->wl_under_ips = true; 279162306a36Sopenharmony_ci 279262306a36Sopenharmony_ci /* for lps off */ 279362306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false); 279462306a36Sopenharmony_ci 279562306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); 279662306a36Sopenharmony_ci rtw_coex_action_coex_all_off(rtwdev); 279762306a36Sopenharmony_ci } else if (type == COEX_IPS_LEAVE) { 279862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS LEAVE notify\n"); 279962306a36Sopenharmony_ci 280062306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); 280162306a36Sopenharmony_ci /* run init hw config (exclude wifi only) */ 280262306a36Sopenharmony_ci __rtw_coex_init_hw_config(rtwdev, false); 280362306a36Sopenharmony_ci 280462306a36Sopenharmony_ci coex_stat->wl_under_ips = false; 280562306a36Sopenharmony_ci } 280662306a36Sopenharmony_ci} 280762306a36Sopenharmony_ci 280862306a36Sopenharmony_civoid rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type) 280962306a36Sopenharmony_ci{ 281062306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 281162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 281262306a36Sopenharmony_ci 281362306a36Sopenharmony_ci if (coex->manual_control || coex->stop_dm) 281462306a36Sopenharmony_ci return; 281562306a36Sopenharmony_ci 281662306a36Sopenharmony_ci if (type == COEX_LPS_ENABLE) { 281762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS ENABLE notify\n"); 281862306a36Sopenharmony_ci 281962306a36Sopenharmony_ci coex_stat->wl_under_lps = true; 282062306a36Sopenharmony_ci 282162306a36Sopenharmony_ci if (coex_stat->wl_force_lps_ctrl) { 282262306a36Sopenharmony_ci /* for ps-tdma */ 282362306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 282462306a36Sopenharmony_ci } else { 282562306a36Sopenharmony_ci /* for native ps */ 282662306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false); 282762306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_WLBUSY, false); 282862306a36Sopenharmony_ci 282962306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_LPS); 283062306a36Sopenharmony_ci } 283162306a36Sopenharmony_ci } else if (type == COEX_LPS_DISABLE) { 283262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS DISABLE notify\n"); 283362306a36Sopenharmony_ci 283462306a36Sopenharmony_ci coex_stat->wl_under_lps = false; 283562306a36Sopenharmony_ci 283662306a36Sopenharmony_ci /* for lps off */ 283762306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 283862306a36Sopenharmony_ci 283962306a36Sopenharmony_ci if (!coex_stat->wl_force_lps_ctrl) 284062306a36Sopenharmony_ci rtw_coex_query_bt_info(rtwdev); 284162306a36Sopenharmony_ci 284262306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_LPS); 284362306a36Sopenharmony_ci } 284462306a36Sopenharmony_ci} 284562306a36Sopenharmony_ci 284662306a36Sopenharmony_civoid rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type) 284762306a36Sopenharmony_ci{ 284862306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 284962306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 285062306a36Sopenharmony_ci 285162306a36Sopenharmony_ci if (coex->manual_control || coex->stop_dm) 285262306a36Sopenharmony_ci return; 285362306a36Sopenharmony_ci 285462306a36Sopenharmony_ci coex->freeze = false; 285562306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); 285662306a36Sopenharmony_ci 285762306a36Sopenharmony_ci if (type == COEX_SCAN_START_5G) { 285862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 285962306a36Sopenharmony_ci "[BTCoex], SCAN START notify (5G)\n"); 286062306a36Sopenharmony_ci 286162306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 286262306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART); 286362306a36Sopenharmony_ci } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) { 286462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 286562306a36Sopenharmony_ci "[BTCoex], SCAN START notify (2G)\n"); 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_ci coex_stat->wl_hi_pri_task2 = true; 286862306a36Sopenharmony_ci 286962306a36Sopenharmony_ci /* Force antenna setup for no scan result issue */ 287062306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 287162306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART); 287262306a36Sopenharmony_ci } else { 287362306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] = 30; /* To do */ 287462306a36Sopenharmony_ci 287562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 287662306a36Sopenharmony_ci "[BTCoex], SCAN FINISH notify (Scan-AP = %d)\n", 287762306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_SCANAP]); 287862306a36Sopenharmony_ci 287962306a36Sopenharmony_ci coex_stat->wl_hi_pri_task2 = false; 288062306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH); 288162306a36Sopenharmony_ci } 288262306a36Sopenharmony_ci} 288362306a36Sopenharmony_ci 288462306a36Sopenharmony_civoid rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type) 288562306a36Sopenharmony_ci{ 288662306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 288762306a36Sopenharmony_ci 288862306a36Sopenharmony_ci if (coex->manual_control || coex->stop_dm) 288962306a36Sopenharmony_ci return; 289062306a36Sopenharmony_ci 289162306a36Sopenharmony_ci if (type == COEX_SWITCH_TO_5G) { 289262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_5G\n", 289362306a36Sopenharmony_ci __func__); 289462306a36Sopenharmony_ci } else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) { 289562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 289662306a36Sopenharmony_ci "[BTCoex], %s(): TO_24G_NOFORSCAN\n", __func__); 289762306a36Sopenharmony_ci } else { 289862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_2G\n", 289962306a36Sopenharmony_ci __func__); 290062306a36Sopenharmony_ci } 290162306a36Sopenharmony_ci 290262306a36Sopenharmony_ci if (type == COEX_SWITCH_TO_5G) 290362306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND); 290462306a36Sopenharmony_ci else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) 290562306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND); 290662306a36Sopenharmony_ci else 290762306a36Sopenharmony_ci rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G); 290862306a36Sopenharmony_ci} 290962306a36Sopenharmony_ci 291062306a36Sopenharmony_civoid rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type) 291162306a36Sopenharmony_ci{ 291262306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 291362306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 291462306a36Sopenharmony_ci 291562306a36Sopenharmony_ci if (coex->manual_control || coex->stop_dm) 291662306a36Sopenharmony_ci return; 291762306a36Sopenharmony_ci 291862306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); 291962306a36Sopenharmony_ci 292062306a36Sopenharmony_ci if (type == COEX_ASSOCIATE_5G_START) { 292162306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G start\n", 292262306a36Sopenharmony_ci __func__); 292362306a36Sopenharmony_ci 292462306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 292562306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART); 292662306a36Sopenharmony_ci } else if (type == COEX_ASSOCIATE_5G_FINISH) { 292762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G finish\n", 292862306a36Sopenharmony_ci __func__); 292962306a36Sopenharmony_ci 293062306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 293162306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH); 293262306a36Sopenharmony_ci } else if (type == COEX_ASSOCIATE_START) { 293362306a36Sopenharmony_ci coex_stat->wl_hi_pri_task1 = true; 293462306a36Sopenharmony_ci coex_stat->wl_connecting = true; 293562306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2; 293662306a36Sopenharmony_ci coex_stat->wl_connecting = true; 293762306a36Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, 293862306a36Sopenharmony_ci &coex->wl_connecting_work, 2 * HZ); 293962306a36Sopenharmony_ci 294062306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G start\n", 294162306a36Sopenharmony_ci __func__); 294262306a36Sopenharmony_ci /* Force antenna setup for no scan result issue */ 294362306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 294462306a36Sopenharmony_ci 294562306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART); 294662306a36Sopenharmony_ci 294762306a36Sopenharmony_ci /* To keep TDMA case during connect process, 294862306a36Sopenharmony_ci * to avoid changed by Btinfo and runcoexmechanism 294962306a36Sopenharmony_ci */ 295062306a36Sopenharmony_ci coex->freeze = true; 295162306a36Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work, 295262306a36Sopenharmony_ci 5 * HZ); 295362306a36Sopenharmony_ci } else { 295462306a36Sopenharmony_ci coex_stat->wl_hi_pri_task1 = false; 295562306a36Sopenharmony_ci coex->freeze = false; 295662306a36Sopenharmony_ci coex_stat->wl_connecting = false; 295762306a36Sopenharmony_ci 295862306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G finish\n", 295962306a36Sopenharmony_ci __func__); 296062306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH); 296162306a36Sopenharmony_ci } 296262306a36Sopenharmony_ci} 296362306a36Sopenharmony_ci 296462306a36Sopenharmony_civoid rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type) 296562306a36Sopenharmony_ci{ 296662306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 296762306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 296862306a36Sopenharmony_ci 296962306a36Sopenharmony_ci if (coex->manual_control || coex->stop_dm) 297062306a36Sopenharmony_ci return; 297162306a36Sopenharmony_ci 297262306a36Sopenharmony_ci if (type == COEX_MEDIA_CONNECT_5G) { 297362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G\n", __func__); 297462306a36Sopenharmony_ci 297562306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 297662306a36Sopenharmony_ci 297762306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 297862306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA); 297962306a36Sopenharmony_ci } else if (type == COEX_MEDIA_CONNECT) { 298062306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G\n", __func__); 298162306a36Sopenharmony_ci 298262306a36Sopenharmony_ci coex_stat->wl_connecting = false; 298362306a36Sopenharmony_ci 298462306a36Sopenharmony_ci rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 298562306a36Sopenharmony_ci 298662306a36Sopenharmony_ci /* Force antenna setup for no scan result issue */ 298762306a36Sopenharmony_ci rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 298862306a36Sopenharmony_ci 298962306a36Sopenharmony_ci /* Set CCK Rx high Pri */ 299062306a36Sopenharmony_ci rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1); 299162306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA); 299262306a36Sopenharmony_ci } else { 299362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): disconnect!!\n", 299462306a36Sopenharmony_ci __func__); 299562306a36Sopenharmony_ci rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0); 299662306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON); 299762306a36Sopenharmony_ci } 299862306a36Sopenharmony_ci 299962306a36Sopenharmony_ci rtw_coex_update_wl_ch_info(rtwdev, type); 300062306a36Sopenharmony_ci} 300162306a36Sopenharmony_ci 300262306a36Sopenharmony_civoid rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) 300362306a36Sopenharmony_ci{ 300462306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 300562306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 300662306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 300762306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 300862306a36Sopenharmony_ci u32 bt_relink_time; 300962306a36Sopenharmony_ci u8 i, rsp_source = 0, type; 301062306a36Sopenharmony_ci bool inq_page = false; 301162306a36Sopenharmony_ci 301262306a36Sopenharmony_ci rsp_source = buf[0] & 0xf; 301362306a36Sopenharmony_ci if (rsp_source >= COEX_BTINFO_SRC_MAX) 301462306a36Sopenharmony_ci return; 301562306a36Sopenharmony_ci coex_stat->cnt_bt_info_c2h[rsp_source]++; 301662306a36Sopenharmony_ci 301762306a36Sopenharmony_ci if (rsp_source == COEX_BTINFO_SRC_BT_IQK) { 301862306a36Sopenharmony_ci coex_stat->bt_iqk_state = buf[1]; 301962306a36Sopenharmony_ci if (coex_stat->bt_iqk_state == 0) 302062306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_IQK]++; 302162306a36Sopenharmony_ci else if (coex_stat->bt_iqk_state == 2) 302262306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++; 302362306a36Sopenharmony_ci 302462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 302562306a36Sopenharmony_ci "[BTCoex], BT IQK by bt_info, data0 = 0x%02x\n", 302662306a36Sopenharmony_ci buf[1]); 302762306a36Sopenharmony_ci 302862306a36Sopenharmony_ci return; 302962306a36Sopenharmony_ci } 303062306a36Sopenharmony_ci 303162306a36Sopenharmony_ci if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) { 303262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 303362306a36Sopenharmony_ci "[BTCoex], BT Scoreboard change notify by WL FW c2h, 0xaa = 0x%02x, 0xab = 0x%02x\n", 303462306a36Sopenharmony_ci buf[1], buf[2]); 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_ci rtw_coex_monitor_bt_enable(rtwdev); 303762306a36Sopenharmony_ci if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) { 303862306a36Sopenharmony_ci coex_stat->bt_disabled_pre = coex_stat->bt_disabled; 303962306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); 304062306a36Sopenharmony_ci } 304162306a36Sopenharmony_ci return; 304262306a36Sopenharmony_ci } 304362306a36Sopenharmony_ci 304462306a36Sopenharmony_ci if (rsp_source == COEX_BTINFO_SRC_H2C60) { 304562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 304662306a36Sopenharmony_ci "[BTCoex], H2C 0x60 content replied by WL FW: H2C_0x60 = [%02x %02x %02x %02x %02x]\n", 304762306a36Sopenharmony_ci buf[1], buf[2], buf[3], buf[4], buf[5]); 304862306a36Sopenharmony_ci 304962306a36Sopenharmony_ci for (i = 1; i <= COEX_WL_TDMA_PARA_LENGTH; i++) 305062306a36Sopenharmony_ci coex_dm->fw_tdma_para[i - 1] = buf[i]; 305162306a36Sopenharmony_ci return; 305262306a36Sopenharmony_ci } 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_ci if (rsp_source == COEX_BTINFO_SRC_WL_FW) { 305562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 305662306a36Sopenharmony_ci "[BTCoex], bt_info reply by WL FW\n"); 305762306a36Sopenharmony_ci 305862306a36Sopenharmony_ci rtw_coex_update_bt_link_info(rtwdev); 305962306a36Sopenharmony_ci return; 306062306a36Sopenharmony_ci } 306162306a36Sopenharmony_ci 306262306a36Sopenharmony_ci if (rsp_source == COEX_BTINFO_SRC_BT_RSP || 306362306a36Sopenharmony_ci rsp_source == COEX_BTINFO_SRC_BT_ACT) { 306462306a36Sopenharmony_ci if (coex_stat->bt_disabled) { 306562306a36Sopenharmony_ci coex_stat->bt_disabled = false; 306662306a36Sopenharmony_ci coex_stat->bt_reenable = true; 306762306a36Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, 306862306a36Sopenharmony_ci &coex->bt_reenable_work, 306962306a36Sopenharmony_ci 15 * HZ); 307062306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 307162306a36Sopenharmony_ci "[BTCoex], BT enable detected by bt_info\n"); 307262306a36Sopenharmony_ci } 307362306a36Sopenharmony_ci } 307462306a36Sopenharmony_ci 307562306a36Sopenharmony_ci if (length != COEX_BTINFO_LENGTH) { 307662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 307762306a36Sopenharmony_ci "[BTCoex], Bt_info length = %d invalid!!\n", length); 307862306a36Sopenharmony_ci 307962306a36Sopenharmony_ci return; 308062306a36Sopenharmony_ci } 308162306a36Sopenharmony_ci 308262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 308362306a36Sopenharmony_ci "[BTCoex], Bt_info[%d], len=%d, data=[%02x %02x %02x %02x %02x %02x]\n", 308462306a36Sopenharmony_ci buf[0], length, buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); 308562306a36Sopenharmony_ci 308662306a36Sopenharmony_ci for (i = 0; i < COEX_BTINFO_LENGTH; i++) 308762306a36Sopenharmony_ci coex_stat->bt_info_c2h[rsp_source][i] = buf[i]; 308862306a36Sopenharmony_ci 308962306a36Sopenharmony_ci /* get the same info from bt, skip it */ 309062306a36Sopenharmony_ci if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 && 309162306a36Sopenharmony_ci coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 && 309262306a36Sopenharmony_ci coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 && 309362306a36Sopenharmony_ci coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 && 309462306a36Sopenharmony_ci coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 && 309562306a36Sopenharmony_ci coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) { 309662306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 309762306a36Sopenharmony_ci "[BTCoex], Return because Btinfo duplicate!!\n"); 309862306a36Sopenharmony_ci return; 309962306a36Sopenharmony_ci } 310062306a36Sopenharmony_ci 310162306a36Sopenharmony_ci coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1]; 310262306a36Sopenharmony_ci coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2]; 310362306a36Sopenharmony_ci coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3]; 310462306a36Sopenharmony_ci coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4]; 310562306a36Sopenharmony_ci coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5]; 310662306a36Sopenharmony_ci coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6]; 310762306a36Sopenharmony_ci 310862306a36Sopenharmony_ci /* 0xff means BT is under WHCK test */ 310962306a36Sopenharmony_ci coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff); 311062306a36Sopenharmony_ci 311162306a36Sopenharmony_ci inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2)); 311262306a36Sopenharmony_ci 311362306a36Sopenharmony_ci if (inq_page != coex_stat->bt_inq_page) { 311462306a36Sopenharmony_ci cancel_delayed_work_sync(&coex->bt_remain_work); 311562306a36Sopenharmony_ci coex_stat->bt_inq_page = inq_page; 311662306a36Sopenharmony_ci 311762306a36Sopenharmony_ci if (inq_page) 311862306a36Sopenharmony_ci coex_stat->bt_inq_remain = true; 311962306a36Sopenharmony_ci else 312062306a36Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, 312162306a36Sopenharmony_ci &coex->bt_remain_work, 312262306a36Sopenharmony_ci 4 * HZ); 312362306a36Sopenharmony_ci } 312462306a36Sopenharmony_ci coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3)); 312562306a36Sopenharmony_ci if (chip->ble_hid_profile_support) { 312662306a36Sopenharmony_ci if (coex_stat->bt_info_lb2 & BIT(5)) { 312762306a36Sopenharmony_ci if (coex_stat->bt_info_hb1 & BIT(0)) { 312862306a36Sopenharmony_ci /*BLE HID*/ 312962306a36Sopenharmony_ci coex_stat->bt_ble_hid_exist = true; 313062306a36Sopenharmony_ci } else { 313162306a36Sopenharmony_ci coex_stat->bt_ble_hid_exist = false; 313262306a36Sopenharmony_ci } 313362306a36Sopenharmony_ci coex_stat->bt_ble_exist = false; 313462306a36Sopenharmony_ci } else if (coex_stat->bt_info_hb1 & BIT(0)) { 313562306a36Sopenharmony_ci /*RCU*/ 313662306a36Sopenharmony_ci coex_stat->bt_ble_hid_exist = false; 313762306a36Sopenharmony_ci coex_stat->bt_ble_exist = true; 313862306a36Sopenharmony_ci } else { 313962306a36Sopenharmony_ci coex_stat->bt_ble_hid_exist = false; 314062306a36Sopenharmony_ci coex_stat->bt_ble_exist = false; 314162306a36Sopenharmony_ci } 314262306a36Sopenharmony_ci } else { 314362306a36Sopenharmony_ci if (coex_stat->bt_info_hb1 & BIT(0)) { 314462306a36Sopenharmony_ci if (coex_stat->bt_hid_slot == 1 && 314562306a36Sopenharmony_ci coex_stat->hi_pri_rx + 100 < coex_stat->hi_pri_tx && 314662306a36Sopenharmony_ci coex_stat->hi_pri_rx < 100) { 314762306a36Sopenharmony_ci coex_stat->bt_ble_hid_exist = true; 314862306a36Sopenharmony_ci coex_stat->bt_ble_exist = false; 314962306a36Sopenharmony_ci } else { 315062306a36Sopenharmony_ci coex_stat->bt_ble_hid_exist = false; 315162306a36Sopenharmony_ci coex_stat->bt_ble_exist = true; 315262306a36Sopenharmony_ci } 315362306a36Sopenharmony_ci } else { 315462306a36Sopenharmony_ci coex_stat->bt_ble_hid_exist = false; 315562306a36Sopenharmony_ci coex_stat->bt_ble_exist = false; 315662306a36Sopenharmony_ci } 315762306a36Sopenharmony_ci } 315862306a36Sopenharmony_ci 315962306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf; 316062306a36Sopenharmony_ci if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1) 316162306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++; 316262306a36Sopenharmony_ci 316362306a36Sopenharmony_ci coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4)); 316462306a36Sopenharmony_ci coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5)); 316562306a36Sopenharmony_ci if (coex_stat->bt_inq) 316662306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_INQ]++; 316762306a36Sopenharmony_ci 316862306a36Sopenharmony_ci coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7)); 316962306a36Sopenharmony_ci if (coex_stat->bt_page) 317062306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++; 317162306a36Sopenharmony_ci 317262306a36Sopenharmony_ci /* unit: % (value-100 to translate to unit: dBm in coex info) */ 317362306a36Sopenharmony_ci if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) { 317462306a36Sopenharmony_ci coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10; 317562306a36Sopenharmony_ci } else { 317662306a36Sopenharmony_ci if (coex_stat->bt_info_hb0 <= 127) 317762306a36Sopenharmony_ci coex_stat->bt_rssi = 100; 317862306a36Sopenharmony_ci else if (256 - coex_stat->bt_info_hb0 <= 100) 317962306a36Sopenharmony_ci coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0); 318062306a36Sopenharmony_ci else 318162306a36Sopenharmony_ci coex_stat->bt_rssi = 0; 318262306a36Sopenharmony_ci } 318362306a36Sopenharmony_ci 318462306a36Sopenharmony_ci if (coex_stat->bt_info_hb1 & BIT(1)) 318562306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++; 318662306a36Sopenharmony_ci 318762306a36Sopenharmony_ci if (coex_stat->bt_info_hb1 & BIT(2)) { 318862306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++; 318962306a36Sopenharmony_ci coex_stat->bt_setup_link = true; 319062306a36Sopenharmony_ci if (coex_stat->bt_reenable) 319162306a36Sopenharmony_ci bt_relink_time = 6 * HZ; 319262306a36Sopenharmony_ci else 319362306a36Sopenharmony_ci bt_relink_time = 1 * HZ; 319462306a36Sopenharmony_ci 319562306a36Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, 319662306a36Sopenharmony_ci &coex->bt_relink_work, 319762306a36Sopenharmony_ci bt_relink_time); 319862306a36Sopenharmony_ci 319962306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 320062306a36Sopenharmony_ci "[BTCoex], Re-Link start in BT info!!\n"); 320162306a36Sopenharmony_ci } 320262306a36Sopenharmony_ci 320362306a36Sopenharmony_ci if (coex_stat->bt_info_hb1 & BIT(3)) 320462306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++; 320562306a36Sopenharmony_ci 320662306a36Sopenharmony_ci coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4)); 320762306a36Sopenharmony_ci coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5)); 320862306a36Sopenharmony_ci if (coex_stat->bt_info_hb1 & BIT(6)) 320962306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++; 321062306a36Sopenharmony_ci 321162306a36Sopenharmony_ci coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7)); 321262306a36Sopenharmony_ci /* for multi_link = 0 but bt pkt remain exist */ 321362306a36Sopenharmony_ci /* Use PS-TDMA to protect WL RX */ 321462306a36Sopenharmony_ci if (!coex_stat->bt_multi_link && coex_stat->bt_multi_link_pre) { 321562306a36Sopenharmony_ci coex_stat->bt_multi_link_remain = true; 321662306a36Sopenharmony_ci ieee80211_queue_delayed_work(rtwdev->hw, 321762306a36Sopenharmony_ci &coex->bt_multi_link_remain_work, 321862306a36Sopenharmony_ci 3 * HZ); 321962306a36Sopenharmony_ci } 322062306a36Sopenharmony_ci coex_stat->bt_multi_link_pre = coex_stat->bt_multi_link; 322162306a36Sopenharmony_ci 322262306a36Sopenharmony_ci /* resend wifi info to bt, it is reset and lost the info */ 322362306a36Sopenharmony_ci if (coex_stat->bt_info_hb1 & BIT(1)) { 322462306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 322562306a36Sopenharmony_ci "[BTCoex], BT Re-init, send wifi BW & Chnl to BT!!\n"); 322662306a36Sopenharmony_ci 322762306a36Sopenharmony_ci if (coex_stat->wl_connected) 322862306a36Sopenharmony_ci type = COEX_MEDIA_CONNECT; 322962306a36Sopenharmony_ci else 323062306a36Sopenharmony_ci type = COEX_MEDIA_DISCONNECT; 323162306a36Sopenharmony_ci rtw_coex_update_wl_ch_info(rtwdev, type); 323262306a36Sopenharmony_ci } 323362306a36Sopenharmony_ci 323462306a36Sopenharmony_ci /* if ignore_wlan_act && not set_up_link */ 323562306a36Sopenharmony_ci if ((coex_stat->bt_info_hb1 & BIT(3)) && 323662306a36Sopenharmony_ci (!(coex_stat->bt_info_hb1 & BIT(2)))) { 323762306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 323862306a36Sopenharmony_ci "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n"); 323962306a36Sopenharmony_ci rtw_coex_ignore_wlan_act(rtwdev, false); 324062306a36Sopenharmony_ci } 324162306a36Sopenharmony_ci 324262306a36Sopenharmony_ci coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0)); 324362306a36Sopenharmony_ci if (coex_stat->bt_info_hb2 & BIT(1)) 324462306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++; 324562306a36Sopenharmony_ci 324662306a36Sopenharmony_ci coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2); 324762306a36Sopenharmony_ci coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3)); 324862306a36Sopenharmony_ci coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4; 324962306a36Sopenharmony_ci coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6; 325062306a36Sopenharmony_ci if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2) 325162306a36Sopenharmony_ci coex_stat->bt_418_hid_exist = true; 325262306a36Sopenharmony_ci else if (coex_stat->bt_hid_pair_num == 0 || coex_stat->bt_hid_slot == 1) 325362306a36Sopenharmony_ci coex_stat->bt_418_hid_exist = false; 325462306a36Sopenharmony_ci 325562306a36Sopenharmony_ci if ((coex_stat->bt_info_lb2 & 0x49) == 0x49) 325662306a36Sopenharmony_ci coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f); 325762306a36Sopenharmony_ci else 325862306a36Sopenharmony_ci coex_stat->bt_a2dp_bitpool = 0; 325962306a36Sopenharmony_ci 326062306a36Sopenharmony_ci coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7)); 326162306a36Sopenharmony_ci 326262306a36Sopenharmony_ci rtw_coex_update_bt_link_info(rtwdev); 326362306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); 326462306a36Sopenharmony_ci} 326562306a36Sopenharmony_ci 326662306a36Sopenharmony_ci#define COEX_BT_HIDINFO_MTK 0x46 326762306a36Sopenharmony_cistatic const u8 coex_bt_hidinfo_ps[] = {0x57, 0x69, 0x72}; 326862306a36Sopenharmony_cistatic const u8 coex_bt_hidinfo_xb[] = {0x58, 0x62, 0x6f}; 326962306a36Sopenharmony_ci 327062306a36Sopenharmony_civoid rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) 327162306a36Sopenharmony_ci{ 327262306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 327362306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 327462306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 327562306a36Sopenharmony_ci struct rtw_coex_hid *hidinfo; 327662306a36Sopenharmony_ci struct rtw_coex_hid_info_a *hida; 327762306a36Sopenharmony_ci struct rtw_coex_hid_handle_list *hl, *bhl; 327862306a36Sopenharmony_ci u8 sub_id = buf[2], gamehid_cnt = 0, handle, i; 327962306a36Sopenharmony_ci bool cur_game_hid_exist, complete; 328062306a36Sopenharmony_ci 328162306a36Sopenharmony_ci if (!chip->wl_mimo_ps_support && 328262306a36Sopenharmony_ci (sub_id == COEX_BT_HIDINFO_LIST || sub_id == COEX_BT_HIDINFO_A)) 328362306a36Sopenharmony_ci return; 328462306a36Sopenharmony_ci 328562306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 328662306a36Sopenharmony_ci "[BTCoex], HID info notify, sub_id = 0x%x\n", sub_id); 328762306a36Sopenharmony_ci 328862306a36Sopenharmony_ci switch (sub_id) { 328962306a36Sopenharmony_ci case COEX_BT_HIDINFO_LIST: 329062306a36Sopenharmony_ci hl = &coex_stat->hid_handle_list; 329162306a36Sopenharmony_ci bhl = (struct rtw_coex_hid_handle_list *)buf; 329262306a36Sopenharmony_ci if (!memcmp(hl, bhl, sizeof(*hl))) 329362306a36Sopenharmony_ci return; 329462306a36Sopenharmony_ci coex_stat->hid_handle_list = *bhl; 329562306a36Sopenharmony_ci memset(&coex_stat->hid_info, 0, sizeof(coex_stat->hid_info)); 329662306a36Sopenharmony_ci for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) { 329762306a36Sopenharmony_ci hidinfo = &coex_stat->hid_info[i]; 329862306a36Sopenharmony_ci if (hl->handle[i] != COEX_BT_HIDINFO_NOTCON && 329962306a36Sopenharmony_ci hl->handle[i] != 0) 330062306a36Sopenharmony_ci hidinfo->hid_handle = hl->handle[i]; 330162306a36Sopenharmony_ci } 330262306a36Sopenharmony_ci break; 330362306a36Sopenharmony_ci case COEX_BT_HIDINFO_A: 330462306a36Sopenharmony_ci hida = (struct rtw_coex_hid_info_a *)buf; 330562306a36Sopenharmony_ci handle = hida->handle; 330662306a36Sopenharmony_ci for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) { 330762306a36Sopenharmony_ci hidinfo = &coex_stat->hid_info[i]; 330862306a36Sopenharmony_ci if (hidinfo->hid_handle == handle) { 330962306a36Sopenharmony_ci hidinfo->hid_vendor = hida->vendor; 331062306a36Sopenharmony_ci memcpy(hidinfo->hid_name, hida->name, 331162306a36Sopenharmony_ci sizeof(hidinfo->hid_name)); 331262306a36Sopenharmony_ci hidinfo->hid_info_completed = true; 331362306a36Sopenharmony_ci break; 331462306a36Sopenharmony_ci } 331562306a36Sopenharmony_ci } 331662306a36Sopenharmony_ci break; 331762306a36Sopenharmony_ci } 331862306a36Sopenharmony_ci for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) { 331962306a36Sopenharmony_ci hidinfo = &coex_stat->hid_info[i]; 332062306a36Sopenharmony_ci complete = hidinfo->hid_info_completed; 332162306a36Sopenharmony_ci handle = hidinfo->hid_handle; 332262306a36Sopenharmony_ci if (!complete || handle == COEX_BT_HIDINFO_NOTCON || 332362306a36Sopenharmony_ci handle == 0 || handle >= COEX_BT_BLE_HANDLE_THRS) { 332462306a36Sopenharmony_ci hidinfo->is_game_hid = false; 332562306a36Sopenharmony_ci continue; 332662306a36Sopenharmony_ci } 332762306a36Sopenharmony_ci 332862306a36Sopenharmony_ci if (hidinfo->hid_vendor == COEX_BT_HIDINFO_MTK) { 332962306a36Sopenharmony_ci if ((memcmp(hidinfo->hid_name, 333062306a36Sopenharmony_ci coex_bt_hidinfo_ps, 333162306a36Sopenharmony_ci COEX_BT_HIDINFO_NAME)) == 0) 333262306a36Sopenharmony_ci hidinfo->is_game_hid = true; 333362306a36Sopenharmony_ci else if ((memcmp(hidinfo->hid_name, 333462306a36Sopenharmony_ci coex_bt_hidinfo_xb, 333562306a36Sopenharmony_ci COEX_BT_HIDINFO_NAME)) == 0) 333662306a36Sopenharmony_ci hidinfo->is_game_hid = true; 333762306a36Sopenharmony_ci else 333862306a36Sopenharmony_ci hidinfo->is_game_hid = false; 333962306a36Sopenharmony_ci } else { 334062306a36Sopenharmony_ci hidinfo->is_game_hid = false; 334162306a36Sopenharmony_ci } 334262306a36Sopenharmony_ci if (hidinfo->is_game_hid) 334362306a36Sopenharmony_ci gamehid_cnt++; 334462306a36Sopenharmony_ci } 334562306a36Sopenharmony_ci 334662306a36Sopenharmony_ci if (gamehid_cnt > 0) 334762306a36Sopenharmony_ci cur_game_hid_exist = true; 334862306a36Sopenharmony_ci else 334962306a36Sopenharmony_ci cur_game_hid_exist = false; 335062306a36Sopenharmony_ci 335162306a36Sopenharmony_ci if (cur_game_hid_exist != coex_stat->bt_game_hid_exist) { 335262306a36Sopenharmony_ci coex_stat->bt_game_hid_exist = cur_game_hid_exist; 335362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 335462306a36Sopenharmony_ci "[BTCoex], HID info changed!bt_game_hid_exist = %d!\n", 335562306a36Sopenharmony_ci coex_stat->bt_game_hid_exist); 335662306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS); 335762306a36Sopenharmony_ci } 335862306a36Sopenharmony_ci} 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_civoid rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev) 336162306a36Sopenharmony_ci{ 336262306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 336362306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 336462306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 336562306a36Sopenharmony_ci struct rtw_coex_hid *hidinfo; 336662306a36Sopenharmony_ci u8 i, handle; 336762306a36Sopenharmony_ci bool complete; 336862306a36Sopenharmony_ci 336962306a36Sopenharmony_ci if (!chip->wl_mimo_ps_support || coex_stat->wl_under_ips || 337062306a36Sopenharmony_ci (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl)) 337162306a36Sopenharmony_ci return; 337262306a36Sopenharmony_ci 337362306a36Sopenharmony_ci if (!coex_stat->bt_hid_exist && 337462306a36Sopenharmony_ci !((coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION) && 337562306a36Sopenharmony_ci (coex_stat->hi_pri_tx + coex_stat->hi_pri_rx > 337662306a36Sopenharmony_ci COEX_BT_GAMEHID_CNT))) 337762306a36Sopenharmony_ci return; 337862306a36Sopenharmony_ci 337962306a36Sopenharmony_ci rtw_fw_coex_query_hid_info(rtwdev, COEX_BT_HIDINFO_LIST, 0); 338062306a36Sopenharmony_ci 338162306a36Sopenharmony_ci for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) { 338262306a36Sopenharmony_ci hidinfo = &coex_stat->hid_info[i]; 338362306a36Sopenharmony_ci complete = hidinfo->hid_info_completed; 338462306a36Sopenharmony_ci handle = hidinfo->hid_handle; 338562306a36Sopenharmony_ci if (handle == 0 || handle == COEX_BT_HIDINFO_NOTCON || 338662306a36Sopenharmony_ci handle >= COEX_BT_BLE_HANDLE_THRS || complete) 338762306a36Sopenharmony_ci continue; 338862306a36Sopenharmony_ci 338962306a36Sopenharmony_ci rtw_fw_coex_query_hid_info(rtwdev, 339062306a36Sopenharmony_ci COEX_BT_HIDINFO_A, 339162306a36Sopenharmony_ci handle); 339262306a36Sopenharmony_ci } 339362306a36Sopenharmony_ci} 339462306a36Sopenharmony_ci 339562306a36Sopenharmony_civoid rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) 339662306a36Sopenharmony_ci{ 339762306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 339862306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 339962306a36Sopenharmony_ci u8 val; 340062306a36Sopenharmony_ci int i; 340162306a36Sopenharmony_ci 340262306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, 340362306a36Sopenharmony_ci "[BTCoex], WiFi Fw Dbg info = %8ph (len = %d)\n", 340462306a36Sopenharmony_ci buf, length); 340562306a36Sopenharmony_ci if (WARN(length < 8, "invalid wl info c2h length\n")) 340662306a36Sopenharmony_ci return; 340762306a36Sopenharmony_ci 340862306a36Sopenharmony_ci if (buf[0] != 0x08) 340962306a36Sopenharmony_ci return; 341062306a36Sopenharmony_ci 341162306a36Sopenharmony_ci for (i = 1; i < 8; i++) { 341262306a36Sopenharmony_ci val = coex_stat->wl_fw_dbg_info_pre[i]; 341362306a36Sopenharmony_ci if (buf[i] >= val) 341462306a36Sopenharmony_ci coex_stat->wl_fw_dbg_info[i] = buf[i] - val; 341562306a36Sopenharmony_ci else 341662306a36Sopenharmony_ci coex_stat->wl_fw_dbg_info[i] = 255 - val + buf[i]; 341762306a36Sopenharmony_ci 341862306a36Sopenharmony_ci coex_stat->wl_fw_dbg_info_pre[i] = buf[i]; 341962306a36Sopenharmony_ci } 342062306a36Sopenharmony_ci 342162306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++; 342262306a36Sopenharmony_ci rtw_coex_wl_ccklock_action(rtwdev); 342362306a36Sopenharmony_ci rtw_coex_wl_ccklock_detect(rtwdev); 342462306a36Sopenharmony_ci} 342562306a36Sopenharmony_ci 342662306a36Sopenharmony_civoid rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type) 342762306a36Sopenharmony_ci{ 342862306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 342962306a36Sopenharmony_ci} 343062306a36Sopenharmony_ci 343162306a36Sopenharmony_civoid rtw_coex_wl_status_check(struct rtw_dev *rtwdev) 343262306a36Sopenharmony_ci{ 343362306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 343462306a36Sopenharmony_ci 343562306a36Sopenharmony_ci if ((coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) || 343662306a36Sopenharmony_ci coex_stat->wl_under_ips) 343762306a36Sopenharmony_ci return; 343862306a36Sopenharmony_ci 343962306a36Sopenharmony_ci rtw_coex_monitor_bt_ctr(rtwdev); 344062306a36Sopenharmony_ci} 344162306a36Sopenharmony_ci 344262306a36Sopenharmony_civoid rtw_coex_bt_relink_work(struct work_struct *work) 344362306a36Sopenharmony_ci{ 344462306a36Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 344562306a36Sopenharmony_ci coex.bt_relink_work.work); 344662306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 344762306a36Sopenharmony_ci 344862306a36Sopenharmony_ci mutex_lock(&rtwdev->mutex); 344962306a36Sopenharmony_ci coex_stat->bt_setup_link = false; 345062306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 345162306a36Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 345262306a36Sopenharmony_ci} 345362306a36Sopenharmony_ci 345462306a36Sopenharmony_civoid rtw_coex_bt_reenable_work(struct work_struct *work) 345562306a36Sopenharmony_ci{ 345662306a36Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 345762306a36Sopenharmony_ci coex.bt_reenable_work.work); 345862306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 345962306a36Sopenharmony_ci 346062306a36Sopenharmony_ci mutex_lock(&rtwdev->mutex); 346162306a36Sopenharmony_ci coex_stat->bt_reenable = false; 346262306a36Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 346362306a36Sopenharmony_ci} 346462306a36Sopenharmony_ci 346562306a36Sopenharmony_civoid rtw_coex_defreeze_work(struct work_struct *work) 346662306a36Sopenharmony_ci{ 346762306a36Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 346862306a36Sopenharmony_ci coex.defreeze_work.work); 346962306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 347062306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 347162306a36Sopenharmony_ci 347262306a36Sopenharmony_ci mutex_lock(&rtwdev->mutex); 347362306a36Sopenharmony_ci coex->freeze = false; 347462306a36Sopenharmony_ci coex_stat->wl_hi_pri_task1 = false; 347562306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 347662306a36Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 347762306a36Sopenharmony_ci} 347862306a36Sopenharmony_ci 347962306a36Sopenharmony_civoid rtw_coex_wl_remain_work(struct work_struct *work) 348062306a36Sopenharmony_ci{ 348162306a36Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 348262306a36Sopenharmony_ci coex.wl_remain_work.work); 348362306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 348462306a36Sopenharmony_ci 348562306a36Sopenharmony_ci mutex_lock(&rtwdev->mutex); 348662306a36Sopenharmony_ci coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); 348762306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 348862306a36Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 348962306a36Sopenharmony_ci} 349062306a36Sopenharmony_ci 349162306a36Sopenharmony_civoid rtw_coex_bt_remain_work(struct work_struct *work) 349262306a36Sopenharmony_ci{ 349362306a36Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 349462306a36Sopenharmony_ci coex.bt_remain_work.work); 349562306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 349662306a36Sopenharmony_ci 349762306a36Sopenharmony_ci mutex_lock(&rtwdev->mutex); 349862306a36Sopenharmony_ci coex_stat->bt_inq_remain = coex_stat->bt_inq_page; 349962306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS); 350062306a36Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 350162306a36Sopenharmony_ci} 350262306a36Sopenharmony_ci 350362306a36Sopenharmony_civoid rtw_coex_wl_connecting_work(struct work_struct *work) 350462306a36Sopenharmony_ci{ 350562306a36Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 350662306a36Sopenharmony_ci coex.wl_connecting_work.work); 350762306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 350862306a36Sopenharmony_ci 350962306a36Sopenharmony_ci mutex_lock(&rtwdev->mutex); 351062306a36Sopenharmony_ci coex_stat->wl_connecting = false; 351162306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WL connecting stop!!\n"); 351262306a36Sopenharmony_ci rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 351362306a36Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 351462306a36Sopenharmony_ci} 351562306a36Sopenharmony_ci 351662306a36Sopenharmony_civoid rtw_coex_bt_multi_link_remain_work(struct work_struct *work) 351762306a36Sopenharmony_ci{ 351862306a36Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 351962306a36Sopenharmony_ci coex.bt_multi_link_remain_work.work); 352062306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 352162306a36Sopenharmony_ci 352262306a36Sopenharmony_ci mutex_lock(&rtwdev->mutex); 352362306a36Sopenharmony_ci coex_stat->bt_multi_link_remain = false; 352462306a36Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 352562306a36Sopenharmony_ci} 352662306a36Sopenharmony_ci 352762306a36Sopenharmony_civoid rtw_coex_wl_ccklock_work(struct work_struct *work) 352862306a36Sopenharmony_ci{ 352962306a36Sopenharmony_ci struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 353062306a36Sopenharmony_ci coex.wl_ccklock_work.work); 353162306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 353262306a36Sopenharmony_ci 353362306a36Sopenharmony_ci mutex_lock(&rtwdev->mutex); 353462306a36Sopenharmony_ci coex_stat->wl_cck_lock = false; 353562306a36Sopenharmony_ci mutex_unlock(&rtwdev->mutex); 353662306a36Sopenharmony_ci} 353762306a36Sopenharmony_ci 353862306a36Sopenharmony_ci#ifdef CONFIG_RTW88_DEBUGFS 353962306a36Sopenharmony_ci#define INFO_SIZE 80 354062306a36Sopenharmony_ci 354162306a36Sopenharmony_ci#define case_BTINFO(src) \ 354262306a36Sopenharmony_ci case COEX_BTINFO_SRC_##src: return #src 354362306a36Sopenharmony_ci 354462306a36Sopenharmony_cistatic const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src) 354562306a36Sopenharmony_ci{ 354662306a36Sopenharmony_ci switch (bt_info_src) { 354762306a36Sopenharmony_ci case_BTINFO(WL_FW); 354862306a36Sopenharmony_ci case_BTINFO(BT_RSP); 354962306a36Sopenharmony_ci case_BTINFO(BT_ACT); 355062306a36Sopenharmony_ci default: 355162306a36Sopenharmony_ci return "Unknown"; 355262306a36Sopenharmony_ci } 355362306a36Sopenharmony_ci} 355462306a36Sopenharmony_ci 355562306a36Sopenharmony_ci#define case_RSN(src) \ 355662306a36Sopenharmony_ci case COEX_RSN_##src: return #src 355762306a36Sopenharmony_ci 355862306a36Sopenharmony_cistatic const char *rtw_coex_get_reason_string(u8 reason) 355962306a36Sopenharmony_ci{ 356062306a36Sopenharmony_ci switch (reason) { 356162306a36Sopenharmony_ci case_RSN(2GSCANSTART); 356262306a36Sopenharmony_ci case_RSN(5GSCANSTART); 356362306a36Sopenharmony_ci case_RSN(SCANFINISH); 356462306a36Sopenharmony_ci case_RSN(2GSWITCHBAND); 356562306a36Sopenharmony_ci case_RSN(5GSWITCHBAND); 356662306a36Sopenharmony_ci case_RSN(2GCONSTART); 356762306a36Sopenharmony_ci case_RSN(5GCONSTART); 356862306a36Sopenharmony_ci case_RSN(2GCONFINISH); 356962306a36Sopenharmony_ci case_RSN(5GCONFINISH); 357062306a36Sopenharmony_ci case_RSN(2GMEDIA); 357162306a36Sopenharmony_ci case_RSN(5GMEDIA); 357262306a36Sopenharmony_ci case_RSN(MEDIADISCON); 357362306a36Sopenharmony_ci case_RSN(BTINFO); 357462306a36Sopenharmony_ci case_RSN(LPS); 357562306a36Sopenharmony_ci case_RSN(WLSTATUS); 357662306a36Sopenharmony_ci default: 357762306a36Sopenharmony_ci return "Unknown"; 357862306a36Sopenharmony_ci } 357962306a36Sopenharmony_ci} 358062306a36Sopenharmony_ci 358162306a36Sopenharmony_cistatic u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0, 358262306a36Sopenharmony_ci u32 wl_reg_6c4) 358362306a36Sopenharmony_ci{ 358462306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 358562306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 358662306a36Sopenharmony_ci u8 ans = 0xFF; 358762306a36Sopenharmony_ci u8 n, i; 358862306a36Sopenharmony_ci u32 load_bt_val; 358962306a36Sopenharmony_ci u32 load_wl_val; 359062306a36Sopenharmony_ci bool share_ant = efuse->share_ant; 359162306a36Sopenharmony_ci 359262306a36Sopenharmony_ci if (share_ant) 359362306a36Sopenharmony_ci n = chip->table_sant_num; 359462306a36Sopenharmony_ci else 359562306a36Sopenharmony_ci n = chip->table_nsant_num; 359662306a36Sopenharmony_ci 359762306a36Sopenharmony_ci for (i = 0; i < n; i++) { 359862306a36Sopenharmony_ci if (share_ant) { 359962306a36Sopenharmony_ci load_bt_val = chip->table_sant[i].bt; 360062306a36Sopenharmony_ci load_wl_val = chip->table_sant[i].wl; 360162306a36Sopenharmony_ci } else { 360262306a36Sopenharmony_ci load_bt_val = chip->table_nsant[i].bt; 360362306a36Sopenharmony_ci load_wl_val = chip->table_nsant[i].wl; 360462306a36Sopenharmony_ci } 360562306a36Sopenharmony_ci 360662306a36Sopenharmony_ci if (wl_reg_6c0 == load_bt_val && 360762306a36Sopenharmony_ci wl_reg_6c4 == load_wl_val) { 360862306a36Sopenharmony_ci ans = i; 360962306a36Sopenharmony_ci if (!share_ant) 361062306a36Sopenharmony_ci ans += 100; 361162306a36Sopenharmony_ci break; 361262306a36Sopenharmony_ci } 361362306a36Sopenharmony_ci } 361462306a36Sopenharmony_ci 361562306a36Sopenharmony_ci return ans; 361662306a36Sopenharmony_ci} 361762306a36Sopenharmony_ci 361862306a36Sopenharmony_cistatic u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para) 361962306a36Sopenharmony_ci{ 362062306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 362162306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 362262306a36Sopenharmony_ci u8 ans = 0xFF; 362362306a36Sopenharmony_ci u8 n, i, j; 362462306a36Sopenharmony_ci u8 load_cur_tab_val; 362562306a36Sopenharmony_ci bool valid = false; 362662306a36Sopenharmony_ci bool share_ant = efuse->share_ant; 362762306a36Sopenharmony_ci 362862306a36Sopenharmony_ci if (share_ant) 362962306a36Sopenharmony_ci n = chip->tdma_sant_num; 363062306a36Sopenharmony_ci else 363162306a36Sopenharmony_ci n = chip->tdma_nsant_num; 363262306a36Sopenharmony_ci 363362306a36Sopenharmony_ci for (i = 0; i < n; i++) { 363462306a36Sopenharmony_ci valid = false; 363562306a36Sopenharmony_ci for (j = 0; j < 5; j++) { 363662306a36Sopenharmony_ci if (share_ant) 363762306a36Sopenharmony_ci load_cur_tab_val = chip->tdma_sant[i].para[j]; 363862306a36Sopenharmony_ci else 363962306a36Sopenharmony_ci load_cur_tab_val = chip->tdma_nsant[i].para[j]; 364062306a36Sopenharmony_ci 364162306a36Sopenharmony_ci if (*(tdma_para + j) != load_cur_tab_val) 364262306a36Sopenharmony_ci break; 364362306a36Sopenharmony_ci 364462306a36Sopenharmony_ci if (j == 4) 364562306a36Sopenharmony_ci valid = true; 364662306a36Sopenharmony_ci } 364762306a36Sopenharmony_ci if (valid) { 364862306a36Sopenharmony_ci ans = i; 364962306a36Sopenharmony_ci break; 365062306a36Sopenharmony_ci } 365162306a36Sopenharmony_ci } 365262306a36Sopenharmony_ci 365362306a36Sopenharmony_ci return ans; 365462306a36Sopenharmony_ci} 365562306a36Sopenharmony_ci 365662306a36Sopenharmony_cistatic int rtw_coex_addr_info(struct rtw_dev *rtwdev, 365762306a36Sopenharmony_ci const struct rtw_reg_domain *reg, 365862306a36Sopenharmony_ci char addr_info[], int n) 365962306a36Sopenharmony_ci{ 366062306a36Sopenharmony_ci const char *rf_prefix = ""; 366162306a36Sopenharmony_ci const char *sep = n == 0 ? "" : "/ "; 366262306a36Sopenharmony_ci int ffs, fls; 366362306a36Sopenharmony_ci int max_fls; 366462306a36Sopenharmony_ci 366562306a36Sopenharmony_ci if (INFO_SIZE - n <= 0) 366662306a36Sopenharmony_ci return 0; 366762306a36Sopenharmony_ci 366862306a36Sopenharmony_ci switch (reg->domain) { 366962306a36Sopenharmony_ci case RTW_REG_DOMAIN_MAC32: 367062306a36Sopenharmony_ci max_fls = 31; 367162306a36Sopenharmony_ci break; 367262306a36Sopenharmony_ci case RTW_REG_DOMAIN_MAC16: 367362306a36Sopenharmony_ci max_fls = 15; 367462306a36Sopenharmony_ci break; 367562306a36Sopenharmony_ci case RTW_REG_DOMAIN_MAC8: 367662306a36Sopenharmony_ci max_fls = 7; 367762306a36Sopenharmony_ci break; 367862306a36Sopenharmony_ci case RTW_REG_DOMAIN_RF_A: 367962306a36Sopenharmony_ci case RTW_REG_DOMAIN_RF_B: 368062306a36Sopenharmony_ci rf_prefix = "RF_"; 368162306a36Sopenharmony_ci max_fls = 19; 368262306a36Sopenharmony_ci break; 368362306a36Sopenharmony_ci default: 368462306a36Sopenharmony_ci return 0; 368562306a36Sopenharmony_ci } 368662306a36Sopenharmony_ci 368762306a36Sopenharmony_ci ffs = __ffs(reg->mask); 368862306a36Sopenharmony_ci fls = __fls(reg->mask); 368962306a36Sopenharmony_ci 369062306a36Sopenharmony_ci if (ffs == 0 && fls == max_fls) 369162306a36Sopenharmony_ci return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x", 369262306a36Sopenharmony_ci sep, rf_prefix, reg->addr); 369362306a36Sopenharmony_ci else if (ffs == fls) 369462306a36Sopenharmony_ci return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]", 369562306a36Sopenharmony_ci sep, rf_prefix, reg->addr, ffs); 369662306a36Sopenharmony_ci else 369762306a36Sopenharmony_ci return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]", 369862306a36Sopenharmony_ci sep, rf_prefix, reg->addr, fls, ffs); 369962306a36Sopenharmony_ci} 370062306a36Sopenharmony_ci 370162306a36Sopenharmony_cistatic int rtw_coex_val_info(struct rtw_dev *rtwdev, 370262306a36Sopenharmony_ci const struct rtw_reg_domain *reg, 370362306a36Sopenharmony_ci char val_info[], int n) 370462306a36Sopenharmony_ci{ 370562306a36Sopenharmony_ci const char *sep = n == 0 ? "" : "/ "; 370662306a36Sopenharmony_ci u8 rf_path; 370762306a36Sopenharmony_ci 370862306a36Sopenharmony_ci if (INFO_SIZE - n <= 0) 370962306a36Sopenharmony_ci return 0; 371062306a36Sopenharmony_ci 371162306a36Sopenharmony_ci switch (reg->domain) { 371262306a36Sopenharmony_ci case RTW_REG_DOMAIN_MAC32: 371362306a36Sopenharmony_ci return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, 371462306a36Sopenharmony_ci rtw_read32_mask(rtwdev, reg->addr, reg->mask)); 371562306a36Sopenharmony_ci case RTW_REG_DOMAIN_MAC16: 371662306a36Sopenharmony_ci return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, 371762306a36Sopenharmony_ci rtw_read16_mask(rtwdev, reg->addr, reg->mask)); 371862306a36Sopenharmony_ci case RTW_REG_DOMAIN_MAC8: 371962306a36Sopenharmony_ci return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, 372062306a36Sopenharmony_ci rtw_read8_mask(rtwdev, reg->addr, reg->mask)); 372162306a36Sopenharmony_ci case RTW_REG_DOMAIN_RF_A: 372262306a36Sopenharmony_ci rf_path = RF_PATH_A; 372362306a36Sopenharmony_ci break; 372462306a36Sopenharmony_ci case RTW_REG_DOMAIN_RF_B: 372562306a36Sopenharmony_ci rf_path = RF_PATH_B; 372662306a36Sopenharmony_ci break; 372762306a36Sopenharmony_ci default: 372862306a36Sopenharmony_ci return 0; 372962306a36Sopenharmony_ci } 373062306a36Sopenharmony_ci 373162306a36Sopenharmony_ci /* only RF go through here */ 373262306a36Sopenharmony_ci return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep, 373362306a36Sopenharmony_ci rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask)); 373462306a36Sopenharmony_ci} 373562306a36Sopenharmony_ci 373662306a36Sopenharmony_cistatic void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m) 373762306a36Sopenharmony_ci{ 373862306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 373962306a36Sopenharmony_ci const struct rtw_reg_domain *reg; 374062306a36Sopenharmony_ci char addr_info[INFO_SIZE]; 374162306a36Sopenharmony_ci int n_addr = 0; 374262306a36Sopenharmony_ci char val_info[INFO_SIZE]; 374362306a36Sopenharmony_ci int n_val = 0; 374462306a36Sopenharmony_ci int i; 374562306a36Sopenharmony_ci 374662306a36Sopenharmony_ci for (i = 0; i < chip->coex_info_hw_regs_num; i++) { 374762306a36Sopenharmony_ci reg = &chip->coex_info_hw_regs[i]; 374862306a36Sopenharmony_ci 374962306a36Sopenharmony_ci n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr); 375062306a36Sopenharmony_ci n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val); 375162306a36Sopenharmony_ci 375262306a36Sopenharmony_ci if (reg->domain == RTW_REG_DOMAIN_NL) { 375362306a36Sopenharmony_ci seq_printf(m, "%-40s = %s\n", addr_info, val_info); 375462306a36Sopenharmony_ci n_addr = 0; 375562306a36Sopenharmony_ci n_val = 0; 375662306a36Sopenharmony_ci } 375762306a36Sopenharmony_ci } 375862306a36Sopenharmony_ci 375962306a36Sopenharmony_ci if (n_addr != 0 && n_val != 0) 376062306a36Sopenharmony_ci seq_printf(m, "%-40s = %s\n", addr_info, val_info); 376162306a36Sopenharmony_ci} 376262306a36Sopenharmony_ci 376362306a36Sopenharmony_cistatic bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev, 376462306a36Sopenharmony_ci u8 type, u16 addr, u16 *val) 376562306a36Sopenharmony_ci{ 376662306a36Sopenharmony_ci struct rtw_coex_info_req req = {0}; 376762306a36Sopenharmony_ci struct sk_buff *skb; 376862306a36Sopenharmony_ci __le16 le_addr; 376962306a36Sopenharmony_ci u8 *payload; 377062306a36Sopenharmony_ci 377162306a36Sopenharmony_ci le_addr = cpu_to_le16(addr); 377262306a36Sopenharmony_ci req.op_code = BT_MP_INFO_OP_READ_REG; 377362306a36Sopenharmony_ci req.para1 = type; 377462306a36Sopenharmony_ci req.para2 = le16_get_bits(le_addr, GENMASK(7, 0)); 377562306a36Sopenharmony_ci req.para3 = le16_get_bits(le_addr, GENMASK(15, 8)); 377662306a36Sopenharmony_ci skb = rtw_coex_info_request(rtwdev, &req); 377762306a36Sopenharmony_ci if (!skb) { 377862306a36Sopenharmony_ci *val = 0xeaea; 377962306a36Sopenharmony_ci return false; 378062306a36Sopenharmony_ci } 378162306a36Sopenharmony_ci 378262306a36Sopenharmony_ci payload = get_payload_from_coex_resp(skb); 378362306a36Sopenharmony_ci *val = GET_COEX_RESP_BT_REG_VAL(payload); 378462306a36Sopenharmony_ci dev_kfree_skb_any(skb); 378562306a36Sopenharmony_ci 378662306a36Sopenharmony_ci return true; 378762306a36Sopenharmony_ci} 378862306a36Sopenharmony_ci 378962306a36Sopenharmony_cistatic bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev, 379062306a36Sopenharmony_ci u32 *patch_version) 379162306a36Sopenharmony_ci{ 379262306a36Sopenharmony_ci struct rtw_coex_info_req req = {0}; 379362306a36Sopenharmony_ci struct sk_buff *skb; 379462306a36Sopenharmony_ci u8 *payload; 379562306a36Sopenharmony_ci 379662306a36Sopenharmony_ci req.op_code = BT_MP_INFO_OP_PATCH_VER; 379762306a36Sopenharmony_ci skb = rtw_coex_info_request(rtwdev, &req); 379862306a36Sopenharmony_ci if (!skb) 379962306a36Sopenharmony_ci return false; 380062306a36Sopenharmony_ci 380162306a36Sopenharmony_ci payload = get_payload_from_coex_resp(skb); 380262306a36Sopenharmony_ci *patch_version = GET_COEX_RESP_BT_PATCH_VER(payload); 380362306a36Sopenharmony_ci dev_kfree_skb_any(skb); 380462306a36Sopenharmony_ci 380562306a36Sopenharmony_ci return true; 380662306a36Sopenharmony_ci} 380762306a36Sopenharmony_ci 380862306a36Sopenharmony_cistatic bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev, 380962306a36Sopenharmony_ci u32 *supported_version) 381062306a36Sopenharmony_ci{ 381162306a36Sopenharmony_ci struct rtw_coex_info_req req = {0}; 381262306a36Sopenharmony_ci struct sk_buff *skb; 381362306a36Sopenharmony_ci u8 *payload; 381462306a36Sopenharmony_ci 381562306a36Sopenharmony_ci req.op_code = BT_MP_INFO_OP_SUPP_VER; 381662306a36Sopenharmony_ci skb = rtw_coex_info_request(rtwdev, &req); 381762306a36Sopenharmony_ci if (!skb) 381862306a36Sopenharmony_ci return false; 381962306a36Sopenharmony_ci 382062306a36Sopenharmony_ci payload = get_payload_from_coex_resp(skb); 382162306a36Sopenharmony_ci *supported_version = GET_COEX_RESP_BT_SUPP_VER(payload); 382262306a36Sopenharmony_ci dev_kfree_skb_any(skb); 382362306a36Sopenharmony_ci 382462306a36Sopenharmony_ci return true; 382562306a36Sopenharmony_ci} 382662306a36Sopenharmony_ci 382762306a36Sopenharmony_cistatic bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev, 382862306a36Sopenharmony_ci u32 *supported_feature) 382962306a36Sopenharmony_ci{ 383062306a36Sopenharmony_ci struct rtw_coex_info_req req = {0}; 383162306a36Sopenharmony_ci struct sk_buff *skb; 383262306a36Sopenharmony_ci u8 *payload; 383362306a36Sopenharmony_ci 383462306a36Sopenharmony_ci req.op_code = BT_MP_INFO_OP_SUPP_FEAT; 383562306a36Sopenharmony_ci skb = rtw_coex_info_request(rtwdev, &req); 383662306a36Sopenharmony_ci if (!skb) 383762306a36Sopenharmony_ci return false; 383862306a36Sopenharmony_ci 383962306a36Sopenharmony_ci payload = get_payload_from_coex_resp(skb); 384062306a36Sopenharmony_ci *supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload); 384162306a36Sopenharmony_ci dev_kfree_skb_any(skb); 384262306a36Sopenharmony_ci 384362306a36Sopenharmony_ci return true; 384462306a36Sopenharmony_ci} 384562306a36Sopenharmony_ci 384662306a36Sopenharmony_cistruct rtw_coex_sta_stat_iter_data { 384762306a36Sopenharmony_ci struct rtw_vif *rtwvif; 384862306a36Sopenharmony_ci struct seq_file *file; 384962306a36Sopenharmony_ci}; 385062306a36Sopenharmony_ci 385162306a36Sopenharmony_cistatic void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta) 385262306a36Sopenharmony_ci{ 385362306a36Sopenharmony_ci struct rtw_coex_sta_stat_iter_data *sta_iter_data = data; 385462306a36Sopenharmony_ci struct rtw_vif *rtwvif = sta_iter_data->rtwvif; 385562306a36Sopenharmony_ci struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; 385662306a36Sopenharmony_ci struct seq_file *m = sta_iter_data->file; 385762306a36Sopenharmony_ci struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); 385862306a36Sopenharmony_ci u8 rssi; 385962306a36Sopenharmony_ci 386062306a36Sopenharmony_ci if (si->vif != vif) 386162306a36Sopenharmony_ci return; 386262306a36Sopenharmony_ci 386362306a36Sopenharmony_ci rssi = ewma_rssi_read(&si->avg_rssi); 386462306a36Sopenharmony_ci seq_printf(m, "\tPeer %3d\n", si->mac_id); 386562306a36Sopenharmony_ci seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi); 386662306a36Sopenharmony_ci seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode); 386762306a36Sopenharmony_ci} 386862306a36Sopenharmony_ci 386962306a36Sopenharmony_cistruct rtw_coex_vif_stat_iter_data { 387062306a36Sopenharmony_ci struct rtw_dev *rtwdev; 387162306a36Sopenharmony_ci struct seq_file *file; 387262306a36Sopenharmony_ci}; 387362306a36Sopenharmony_ci 387462306a36Sopenharmony_cistatic void rtw_coex_vif_stat_iter(void *data, u8 *mac, 387562306a36Sopenharmony_ci struct ieee80211_vif *vif) 387662306a36Sopenharmony_ci{ 387762306a36Sopenharmony_ci struct rtw_coex_vif_stat_iter_data *vif_iter_data = data; 387862306a36Sopenharmony_ci struct rtw_coex_sta_stat_iter_data sta_iter_data; 387962306a36Sopenharmony_ci struct rtw_dev *rtwdev = vif_iter_data->rtwdev; 388062306a36Sopenharmony_ci struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; 388162306a36Sopenharmony_ci struct seq_file *m = vif_iter_data->file; 388262306a36Sopenharmony_ci struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; 388362306a36Sopenharmony_ci 388462306a36Sopenharmony_ci seq_printf(m, "Iface on Port (%d)\n", rtwvif->port); 388562306a36Sopenharmony_ci seq_printf(m, "\t%-32s = %d\n", 388662306a36Sopenharmony_ci "Beacon interval", bss_conf->beacon_int); 388762306a36Sopenharmony_ci seq_printf(m, "\t%-32s = %d\n", 388862306a36Sopenharmony_ci "Network Type", rtwvif->net_type); 388962306a36Sopenharmony_ci 389062306a36Sopenharmony_ci sta_iter_data.rtwvif = rtwvif; 389162306a36Sopenharmony_ci sta_iter_data.file = m; 389262306a36Sopenharmony_ci rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter, 389362306a36Sopenharmony_ci &sta_iter_data); 389462306a36Sopenharmony_ci} 389562306a36Sopenharmony_ci 389662306a36Sopenharmony_ci#define case_WLINK(src) \ 389762306a36Sopenharmony_ci case COEX_WLINK_##src: return #src 389862306a36Sopenharmony_ci 389962306a36Sopenharmony_cistatic const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode) 390062306a36Sopenharmony_ci{ 390162306a36Sopenharmony_ci switch (coex_wl_link_mode) { 390262306a36Sopenharmony_ci case_WLINK(2G1PORT); 390362306a36Sopenharmony_ci case_WLINK(5G); 390462306a36Sopenharmony_ci case_WLINK(2GFREE); 390562306a36Sopenharmony_ci default: 390662306a36Sopenharmony_ci return "Unknown"; 390762306a36Sopenharmony_ci } 390862306a36Sopenharmony_ci} 390962306a36Sopenharmony_ci 391062306a36Sopenharmony_civoid rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m) 391162306a36Sopenharmony_ci{ 391262306a36Sopenharmony_ci const struct rtw_chip_info *chip = rtwdev->chip; 391362306a36Sopenharmony_ci struct rtw_dm_info *dm_info = &rtwdev->dm_info; 391462306a36Sopenharmony_ci struct rtw_coex *coex = &rtwdev->coex; 391562306a36Sopenharmony_ci struct rtw_coex_stat *coex_stat = &coex->stat; 391662306a36Sopenharmony_ci struct rtw_coex_dm *coex_dm = &coex->dm; 391762306a36Sopenharmony_ci struct rtw_hal *hal = &rtwdev->hal; 391862306a36Sopenharmony_ci struct rtw_efuse *efuse = &rtwdev->efuse; 391962306a36Sopenharmony_ci struct rtw_fw_state *fw = &rtwdev->fw; 392062306a36Sopenharmony_ci struct rtw_coex_vif_stat_iter_data vif_iter_data; 392162306a36Sopenharmony_ci u8 reason = coex_dm->reason; 392262306a36Sopenharmony_ci u8 sys_lte; 392362306a36Sopenharmony_ci u16 score_board_WB, score_board_BW; 392462306a36Sopenharmony_ci u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc; 392562306a36Sopenharmony_ci u32 lte_coex, bt_coex; 392662306a36Sopenharmony_ci int i; 392762306a36Sopenharmony_ci 392862306a36Sopenharmony_ci score_board_BW = rtw_coex_read_scbd(rtwdev); 392962306a36Sopenharmony_ci score_board_WB = coex_stat->score_board; 393062306a36Sopenharmony_ci wl_reg_6c0 = rtw_read32(rtwdev, REG_BT_COEX_TABLE0); 393162306a36Sopenharmony_ci wl_reg_6c4 = rtw_read32(rtwdev, REG_BT_COEX_TABLE1); 393262306a36Sopenharmony_ci wl_reg_6c8 = rtw_read32(rtwdev, REG_BT_COEX_BRK_TABLE); 393362306a36Sopenharmony_ci wl_reg_6cc = rtw_read32(rtwdev, REG_BT_COEX_TABLE_H); 393462306a36Sopenharmony_ci wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL); 393562306a36Sopenharmony_ci 393662306a36Sopenharmony_ci sys_lte = rtw_read8(rtwdev, 0x73); 393762306a36Sopenharmony_ci lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38); 393862306a36Sopenharmony_ci bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54); 393962306a36Sopenharmony_ci 394062306a36Sopenharmony_ci if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) { 394162306a36Sopenharmony_ci rtw_coex_get_bt_supported_version(rtwdev, 394262306a36Sopenharmony_ci &coex_stat->bt_supported_version); 394362306a36Sopenharmony_ci rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver); 394462306a36Sopenharmony_ci rtw_coex_get_bt_supported_feature(rtwdev, 394562306a36Sopenharmony_ci &coex_stat->bt_supported_feature); 394662306a36Sopenharmony_ci rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae); 394762306a36Sopenharmony_ci rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac); 394862306a36Sopenharmony_ci 394962306a36Sopenharmony_ci if (coex_stat->patch_ver != 0) 395062306a36Sopenharmony_ci coex_stat->bt_mailbox_reply = true; 395162306a36Sopenharmony_ci } 395262306a36Sopenharmony_ci 395362306a36Sopenharmony_ci rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__); 395462306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 395562306a36Sopenharmony_ci seq_printf(m, "\t\tBT Coexist info %x\n", chip->id); 395662306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 395762306a36Sopenharmony_ci 395862306a36Sopenharmony_ci if (coex->manual_control) { 395962306a36Sopenharmony_ci seq_puts(m, "============[Under Manual Control]============\n"); 396062306a36Sopenharmony_ci seq_puts(m, "==========================================\n"); 396162306a36Sopenharmony_ci 396262306a36Sopenharmony_ci } else if (coex->stop_dm) { 396362306a36Sopenharmony_ci seq_puts(m, "============[Coex is STOPPED]============\n"); 396462306a36Sopenharmony_ci seq_puts(m, "==========================================\n"); 396562306a36Sopenharmony_ci 396662306a36Sopenharmony_ci } else if (coex->freeze) { 396762306a36Sopenharmony_ci seq_puts(m, "============[coex_freeze]============\n"); 396862306a36Sopenharmony_ci seq_puts(m, "==========================================\n"); 396962306a36Sopenharmony_ci } 397062306a36Sopenharmony_ci 397162306a36Sopenharmony_ci seq_printf(m, "%-40s = %s/ %d\n", 397262306a36Sopenharmony_ci "Mech/ RFE", 397362306a36Sopenharmony_ci efuse->share_ant ? "Shared" : "Non-Shared", 397462306a36Sopenharmony_ci efuse->rfe_option); 397562306a36Sopenharmony_ci seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n", 397662306a36Sopenharmony_ci "Coex Ver/ BT Dez/ BT Rpt", 397762306a36Sopenharmony_ci chip->coex_para_ver, chip->bt_desired_ver, 397862306a36Sopenharmony_ci coex_stat->bt_supported_version, 397962306a36Sopenharmony_ci coex_stat->bt_disabled ? "(BT disabled)" : 398062306a36Sopenharmony_ci coex_stat->bt_supported_version >= chip->bt_desired_ver ? 398162306a36Sopenharmony_ci "(Match)" : "(Mismatch)"); 398262306a36Sopenharmony_ci seq_printf(m, "%-40s = %s/ %u/ %d\n", 398362306a36Sopenharmony_ci "Role/ RoleSwCnt/ IgnWL/ Feature", 398462306a36Sopenharmony_ci coex_stat->bt_slave ? "Slave" : "Master", 398562306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH], 398662306a36Sopenharmony_ci coex_dm->ignore_wl_act); 398762306a36Sopenharmony_ci seq_printf(m, "%-40s = %u.%u/ 0x%x/ 0x%x/ %c\n", 398862306a36Sopenharmony_ci "WL FW/ BT FW/ BT FW Desired/ KT", 398962306a36Sopenharmony_ci fw->version, fw->sub_version, 399062306a36Sopenharmony_ci coex_stat->patch_ver, 399162306a36Sopenharmony_ci chip->wl_fw_desired_ver, coex_stat->kt_ver + 65); 399262306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n", 399362306a36Sopenharmony_ci "AFH Map", 399462306a36Sopenharmony_ci coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1], 399562306a36Sopenharmony_ci coex_dm->wl_ch_info[2], hal->current_channel); 399662306a36Sopenharmony_ci 399762306a36Sopenharmony_ci rtw_debugfs_get_simple_phy_info(m); 399862306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 399962306a36Sopenharmony_ci seq_printf(m, "\t\tBT Status\n"); 400062306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 400162306a36Sopenharmony_ci seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n", 400262306a36Sopenharmony_ci "BT status/ rssi/ retry/ pop", 400362306a36Sopenharmony_ci coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" : 400462306a36Sopenharmony_ci coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy", 400562306a36Sopenharmony_ci coex_stat->bt_rssi - 100, 400662306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_RETRY], 400762306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]); 400862306a36Sopenharmony_ci seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n", 400962306a36Sopenharmony_ci "Profiles", 401062306a36Sopenharmony_ci coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ? 401162306a36Sopenharmony_ci "A2DP sink," : "A2DP,") : "", 401262306a36Sopenharmony_ci coex_stat->bt_hfp_exist ? "HFP," : "", 401362306a36Sopenharmony_ci coex_stat->bt_hid_exist ? 401462306a36Sopenharmony_ci (coex_stat->bt_ble_exist ? "HID(RCU)," : 401562306a36Sopenharmony_ci coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" : 401662306a36Sopenharmony_ci coex_stat->bt_ble_hid_exist ? "HID(BLE)" : 401762306a36Sopenharmony_ci "HID(2/18),") : "", 401862306a36Sopenharmony_ci coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ? 401962306a36Sopenharmony_ci "OPP," : "PAN," : "", 402062306a36Sopenharmony_ci coex_stat->bt_ble_voice ? "Voice," : "", 402162306a36Sopenharmony_ci coex_stat->bt_multi_link); 402262306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n", 402362306a36Sopenharmony_ci "Reinit/ Relink/ IgnWl/ Feature", 402462306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_REINIT], 402562306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK], 402662306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT], 402762306a36Sopenharmony_ci coex_stat->bt_supported_feature); 402862306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n", 402962306a36Sopenharmony_ci "Page/ Inq/ iqk/ iqk fail", 403062306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_PAGE], 403162306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_INQ], 403262306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_IQK], 403362306a36Sopenharmony_ci coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]); 403462306a36Sopenharmony_ci seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n", 403562306a36Sopenharmony_ci "0xae/ 0xac/ score board (W->B)/ (B->W)", 403662306a36Sopenharmony_ci coex_stat->bt_reg_vendor_ae, 403762306a36Sopenharmony_ci coex_stat->bt_reg_vendor_ac, 403862306a36Sopenharmony_ci score_board_WB, score_board_BW); 403962306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/%u, %u/%u\n", 404062306a36Sopenharmony_ci "Hi-Pri TX/RX, Lo-Pri TX/RX", 404162306a36Sopenharmony_ci coex_stat->hi_pri_tx, coex_stat->hi_pri_rx, 404262306a36Sopenharmony_ci coex_stat->lo_pri_tx, coex_stat->lo_pri_rx); 404362306a36Sopenharmony_ci for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++) 404462306a36Sopenharmony_ci seq_printf(m, "%-40s = %7ph\n", 404562306a36Sopenharmony_ci rtw_coex_get_bt_info_src_string(i), 404662306a36Sopenharmony_ci coex_stat->bt_info_c2h[i]); 404762306a36Sopenharmony_ci 404862306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 404962306a36Sopenharmony_ci seq_printf(m, "\t\tWiFi Status\n"); 405062306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 405162306a36Sopenharmony_ci seq_printf(m, "%-40s = %d\n", 405262306a36Sopenharmony_ci "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags)); 405362306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n", 405462306a36Sopenharmony_ci "G_busy/ TX/ RX", 405562306a36Sopenharmony_ci coex_stat->wl_gl_busy, 405662306a36Sopenharmony_ci rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput); 405762306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/ %u/ %u\n", 405862306a36Sopenharmony_ci "IPS/ Low Power/ PS mode", 405962306a36Sopenharmony_ci !test_bit(RTW_FLAG_POWERON, rtwdev->flags), 406062306a36Sopenharmony_ci test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags), 406162306a36Sopenharmony_ci rtwdev->lps_conf.mode); 406262306a36Sopenharmony_ci 406362306a36Sopenharmony_ci vif_iter_data.rtwdev = rtwdev; 406462306a36Sopenharmony_ci vif_iter_data.file = m; 406562306a36Sopenharmony_ci rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data); 406662306a36Sopenharmony_ci 406762306a36Sopenharmony_ci if (coex->manual_control) { 406862306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 406962306a36Sopenharmony_ci seq_printf(m, "\t\tMechanism (Under Manual)\n"); 407062306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 407162306a36Sopenharmony_ci seq_printf(m, "%-40s = %5ph (%d)\n", 407262306a36Sopenharmony_ci "TDMA Now", 407362306a36Sopenharmony_ci coex_dm->fw_tdma_para, 407462306a36Sopenharmony_ci rtw_coex_get_tdma_index(rtwdev, 407562306a36Sopenharmony_ci &coex_dm->fw_tdma_para[0])); 407662306a36Sopenharmony_ci } else { 407762306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 407862306a36Sopenharmony_ci seq_printf(m, "\t\tMechanism\n"); 407962306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 408062306a36Sopenharmony_ci seq_printf(m, "%-40s = %5ph (case-%d)\n", 408162306a36Sopenharmony_ci "TDMA", 408262306a36Sopenharmony_ci coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma); 408362306a36Sopenharmony_ci } 408462306a36Sopenharmony_ci seq_printf(m, "%-40s = %s/ %s/ %d\n", 408562306a36Sopenharmony_ci "Coex Mode/Free Run/Timer base", 408662306a36Sopenharmony_ci rtw_coex_get_wl_coex_mode(coex_stat->wl_coex_mode), 408762306a36Sopenharmony_ci coex->freerun ? "Yes" : "No", 408862306a36Sopenharmony_ci coex_stat->tdma_timer_base); 408962306a36Sopenharmony_ci seq_printf(m, "%-40s = %d(%d)/ 0x%08x/ 0x%08x/ 0x%08x\n", 409062306a36Sopenharmony_ci "Table/ 0x6c0/ 0x6c4/ 0x6c8", 409162306a36Sopenharmony_ci coex_dm->cur_table, 409262306a36Sopenharmony_ci rtw_coex_get_table_index(rtwdev, wl_reg_6c0, wl_reg_6c4), 409362306a36Sopenharmony_ci wl_reg_6c0, wl_reg_6c4, wl_reg_6c8); 409462306a36Sopenharmony_ci seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ %d/ reason (%s)\n", 409562306a36Sopenharmony_ci "0x778/ 0x6cc/ Run Count/ Reason", 409662306a36Sopenharmony_ci wl_reg_778, wl_reg_6cc, 409762306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN], 409862306a36Sopenharmony_ci rtw_coex_get_reason_string(reason)); 409962306a36Sopenharmony_ci seq_printf(m, "%-40s = %3ph\n", 410062306a36Sopenharmony_ci "AFH Map to BT", 410162306a36Sopenharmony_ci coex_dm->wl_ch_info); 410262306a36Sopenharmony_ci seq_printf(m, "%-40s = %s/ %d\n", 410362306a36Sopenharmony_ci "AntDiv/ BtCtrlLPS/ g_busy", 410462306a36Sopenharmony_ci coex_stat->wl_force_lps_ctrl ? "On" : "Off", 410562306a36Sopenharmony_ci coex_stat->wl_gl_busy); 410662306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n", 410762306a36Sopenharmony_ci "Null All/ Retry/ Ack/ BT Empty/ BT Late", 410862306a36Sopenharmony_ci coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2], 410962306a36Sopenharmony_ci coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4], 411062306a36Sopenharmony_ci coex_stat->wl_fw_dbg_info[5]); 411162306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n", 411262306a36Sopenharmony_ci "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW", 411362306a36Sopenharmony_ci coex_stat->wl_fw_dbg_info[6], 411462306a36Sopenharmony_ci coex_stat->wl_fw_dbg_info[7], 411562306a36Sopenharmony_ci coex_stat->wl_slot_extend ? "Yes" : "No", 411662306a36Sopenharmony_ci coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]); 411762306a36Sopenharmony_ci seq_printf(m, "%-40s = %d/ %d/ %s/ %d\n", 411862306a36Sopenharmony_ci "WL_TxPw/ BT_TxPw/ WL_Rx/ BT_LNA_Lvl", 411962306a36Sopenharmony_ci coex_dm->cur_wl_pwr_lvl, 412062306a36Sopenharmony_ci coex_dm->cur_bt_pwr_lvl, 412162306a36Sopenharmony_ci coex_dm->cur_wl_rx_low_gain_en ? "On" : "Off", 412262306a36Sopenharmony_ci coex_dm->cur_bt_lna_lvl); 412362306a36Sopenharmony_ci 412462306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 412562306a36Sopenharmony_ci seq_printf(m, "\t\tHW setting\n"); 412662306a36Sopenharmony_ci seq_printf(m, "**********************************************\n"); 412762306a36Sopenharmony_ci seq_printf(m, "%-40s = %s/ %s\n", 412862306a36Sopenharmony_ci "LTE Coex/ Path Owner", 412962306a36Sopenharmony_ci lte_coex & BIT(7) ? "ON" : "OFF", 413062306a36Sopenharmony_ci sys_lte & BIT(2) ? "WL" : "BT"); 413162306a36Sopenharmony_ci seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n", 413262306a36Sopenharmony_ci "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg", 413362306a36Sopenharmony_ci lte_coex & BIT(12) ? "SW" : "HW", 413462306a36Sopenharmony_ci lte_coex & BIT(8) ? "SW" : "HW", 413562306a36Sopenharmony_ci lte_coex & BIT(14) ? "SW" : "HW", 413662306a36Sopenharmony_ci lte_coex & BIT(10) ? "SW" : "HW", 413762306a36Sopenharmony_ci sys_lte & BIT(3) ? "On" : "Off"); 413862306a36Sopenharmony_ci seq_printf(m, "%-40s = %lu/ %lu\n", 413962306a36Sopenharmony_ci "GNT_WL/ GNT_BT", 414062306a36Sopenharmony_ci (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3); 414162306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n", 414262306a36Sopenharmony_ci "CRC OK CCK/ OFDM/ HT/ VHT", 414362306a36Sopenharmony_ci dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt, 414462306a36Sopenharmony_ci dm_info->ht_ok_cnt, dm_info->vht_ok_cnt); 414562306a36Sopenharmony_ci seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n", 414662306a36Sopenharmony_ci "CRC ERR CCK/ OFDM/ HT/ VHT", 414762306a36Sopenharmony_ci dm_info->cck_err_cnt, dm_info->ofdm_err_cnt, 414862306a36Sopenharmony_ci dm_info->ht_err_cnt, dm_info->vht_err_cnt); 414962306a36Sopenharmony_ci seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n", 415062306a36Sopenharmony_ci "HiPr/ Locking/ Locked/ Noisy", 415162306a36Sopenharmony_ci coex_stat->wl_hi_pri_task1 ? "Y" : "N", 415262306a36Sopenharmony_ci coex_stat->wl_cck_lock ? "Y" : "N", 415362306a36Sopenharmony_ci coex_stat->wl_cck_lock_ever ? "Y" : "N", 415462306a36Sopenharmony_ci coex_stat->wl_noisy_level); 415562306a36Sopenharmony_ci 415662306a36Sopenharmony_ci rtw_coex_set_coexinfo_hw(rtwdev, m); 415762306a36Sopenharmony_ci seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", 415862306a36Sopenharmony_ci "EVM A/ EVM B/ SNR A/ SNR B", 415962306a36Sopenharmony_ci -dm_info->rx_evm_dbm[RF_PATH_A], 416062306a36Sopenharmony_ci -dm_info->rx_evm_dbm[RF_PATH_B], 416162306a36Sopenharmony_ci -dm_info->rx_snr[RF_PATH_A], 416262306a36Sopenharmony_ci -dm_info->rx_snr[RF_PATH_B]); 416362306a36Sopenharmony_ci seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", 416462306a36Sopenharmony_ci "CCK-CCA/CCK-FA/OFDM-CCA/OFDM-FA", 416562306a36Sopenharmony_ci dm_info->cck_cca_cnt, dm_info->cck_fa_cnt, 416662306a36Sopenharmony_ci dm_info->ofdm_cca_cnt, dm_info->ofdm_fa_cnt); 416762306a36Sopenharmony_ci seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC OK CCK/11g/11n/11ac", 416862306a36Sopenharmony_ci dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt, 416962306a36Sopenharmony_ci dm_info->ht_ok_cnt, dm_info->vht_ok_cnt); 417062306a36Sopenharmony_ci seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC Err CCK/11g/11n/11ac", 417162306a36Sopenharmony_ci dm_info->cck_err_cnt, dm_info->ofdm_err_cnt, 417262306a36Sopenharmony_ci dm_info->ht_err_cnt, dm_info->vht_err_cnt); 417362306a36Sopenharmony_ci 417462306a36Sopenharmony_ci} 417562306a36Sopenharmony_ci#endif /* CONFIG_RTW88_DEBUGFS */ 4176