Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
0002 /* Copyright(c) 2018-2019  Realtek Corporation
0003  */
0004 
0005 #include "main.h"
0006 #include "coex.h"
0007 #include "fw.h"
0008 #include "ps.h"
0009 #include "debug.h"
0010 #include "reg.h"
0011 #include "phy.h"
0012 
0013 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
0014                    u8 rssi, u8 rssi_thresh)
0015 {
0016     struct rtw_chip_info *chip = rtwdev->chip;
0017     u8 tol = chip->rssi_tolerance;
0018     u8 next_state;
0019 
0020     if (pre_state == COEX_RSSI_STATE_LOW ||
0021         pre_state == COEX_RSSI_STATE_STAY_LOW) {
0022         if (rssi >= (rssi_thresh + tol))
0023             next_state = COEX_RSSI_STATE_HIGH;
0024         else
0025             next_state = COEX_RSSI_STATE_STAY_LOW;
0026     } else {
0027         if (rssi < rssi_thresh)
0028             next_state = COEX_RSSI_STATE_LOW;
0029         else
0030             next_state = COEX_RSSI_STATE_STAY_HIGH;
0031     }
0032 
0033     return next_state;
0034 }
0035 
0036 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
0037                 bool tx_limit_en, bool ampdu_limit_en)
0038 {
0039     struct rtw_chip_info *chip = rtwdev->chip;
0040     struct rtw_coex *coex = &rtwdev->coex;
0041     struct rtw_coex_stat *coex_stat = &coex->stat;
0042     u8 num_of_active_port = 1;
0043 
0044     if (!chip->scbd_support)
0045         return;
0046 
0047     /* force max tx retry limit = 8 */
0048     if (coex_stat->wl_tx_limit_en == tx_limit_en &&
0049         coex_stat->wl_ampdu_limit_en == ampdu_limit_en)
0050         return;
0051 
0052     if (!coex_stat->wl_tx_limit_en) {
0053         coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC);
0054         coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH);
0055         coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT);
0056     }
0057 
0058     if (!coex_stat->wl_ampdu_limit_en)
0059         coex_stat->ampdu_max_time =
0060                 rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);
0061 
0062     coex_stat->wl_tx_limit_en = tx_limit_en;
0063     coex_stat->wl_ampdu_limit_en = ampdu_limit_en;
0064 
0065     if (tx_limit_en) {
0066         /* set BT polluted packet on for tx rate adaptive,
0067          * not including tx retry broken by PTA
0068          */
0069         rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
0070 
0071         /* set queue life time to avoid can't reach tx retry limit
0072          * if tx is always broken by GNT_BT
0073          */
0074         if (num_of_active_port <= 1)
0075             rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
0076         rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
0077 
0078         /* auto rate fallback step within 8 retries */
0079         rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
0080         rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
0081     } else {
0082         rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
0083         rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
0084 
0085         rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit);
0086         rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc);
0087         rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch);
0088     }
0089 
0090     if (ampdu_limit_en)
0091         rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);
0092     else
0093         rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,
0094                coex_stat->ampdu_max_time);
0095 }
0096 
0097 static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
0098 {
0099     struct rtw_coex *coex = &rtwdev->coex;
0100     struct rtw_coex_dm *coex_dm = &coex->dm;
0101     bool tx_limit = false;
0102     bool tx_agg_ctrl = false;
0103 
0104     if (!coex->under_5g && coex_dm->bt_status != COEX_BTSTATUS_NCON_IDLE) {
0105         tx_limit = true;
0106         tx_agg_ctrl = true;
0107     }
0108 
0109     rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
0110 }
0111 
0112 static bool rtw_coex_freerun_check(struct rtw_dev *rtwdev)
0113 {
0114     struct rtw_coex *coex = &rtwdev->coex;
0115     struct rtw_coex_dm *coex_dm = &coex->dm;
0116     struct rtw_coex_stat *coex_stat = &coex->stat;
0117     struct rtw_efuse *efuse = &rtwdev->efuse;
0118     u8 bt_rssi;
0119     u8 ant_distance = 10;
0120 
0121     if (coex_stat->bt_disabled)
0122         return false;
0123 
0124     if (efuse->share_ant || ant_distance <= 5 || !coex_stat->wl_gl_busy)
0125         return false;
0126 
0127     if (ant_distance >= 40 || coex_stat->bt_hid_pair_num >= 2)
0128         return true;
0129 
0130     /* ant_distance = 5 ~ 40  */
0131     if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]) &&
0132         COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0]))
0133         return true;
0134 
0135     if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
0136         bt_rssi = coex_dm->bt_rssi_state[0];
0137     else
0138         bt_rssi = coex_dm->bt_rssi_state[1];
0139 
0140     if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
0141         COEX_RSSI_HIGH(bt_rssi) &&
0142         coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)
0143         return true;
0144 
0145     return false;
0146 }
0147 
0148 static void rtw_coex_wl_slot_extend(struct rtw_dev *rtwdev, bool enable)
0149 {
0150     struct rtw_coex *coex = &rtwdev->coex;
0151     struct rtw_coex_stat *coex_stat = &coex->stat;
0152     u8 para[6] = {0};
0153 
0154     para[0] = COEX_H2C69_WL_LEAKAP;
0155     para[1] = PARA1_H2C69_DIS_5MS;
0156 
0157     if (enable)
0158         para[1] = PARA1_H2C69_EN_5MS;
0159     else
0160         coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
0161 
0162     coex_stat->wl_slot_extend = enable;
0163     rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
0164 }
0165 
0166 static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
0167 {
0168     struct rtw_coex *coex = &rtwdev->coex;
0169     struct rtw_coex_stat *coex_stat = &coex->stat;
0170 
0171     if (coex->manual_control || coex->stop_dm)
0172         return;
0173 
0174 
0175     if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {
0176         rtw_dbg(rtwdev, RTW_DBG_COEX,
0177             "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");
0178         rtw_coex_wl_slot_extend(rtwdev, false);
0179         return;
0180     }
0181 
0182     if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl &&
0183         !coex_stat->wl_cck_lock_ever) {
0184         if (coex_stat->wl_fw_dbg_info[7] <= 5)
0185             coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++;
0186         else
0187             coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
0188 
0189         rtw_dbg(rtwdev, RTW_DBG_COEX,
0190             "[BTCoex], 5ms WL slot extend cnt = %d!!\n",
0191             coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]);
0192 
0193         if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {
0194             rtw_dbg(rtwdev, RTW_DBG_COEX,
0195                 "[BTCoex], set h2c 0x69 opcode 12 to turn off 5ms WL slot extend!!\n");
0196             rtw_coex_wl_slot_extend(rtwdev, false);
0197         }
0198     } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {
0199         rtw_dbg(rtwdev, RTW_DBG_COEX,
0200             "[BTCoex], set h2c 0x69 opcode 12 to turn on 5ms WL slot extend!!\n");
0201 
0202         rtw_coex_wl_slot_extend(rtwdev, true);
0203     }
0204 }
0205 
0206 static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
0207 {
0208     struct rtw_coex *coex = &rtwdev->coex;
0209     struct rtw_coex_stat *coex_stat = &coex->stat;
0210     struct rtw_coex_dm *coex_dm = &coex->dm;
0211 
0212     bool is_cck_lock_rate = false;
0213 
0214     if (coex_stat->wl_coex_mode != COEX_WLINK_2G1PORT &&
0215         coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)
0216         return;
0217 
0218     if (coex_dm->bt_status == COEX_BTSTATUS_INQ_PAGE ||
0219         coex_stat->bt_setup_link) {
0220         coex_stat->wl_cck_lock = false;
0221         coex_stat->wl_cck_lock_pre = false;
0222         return;
0223     }
0224 
0225     if (coex_stat->wl_rx_rate <= COEX_CCK_2 ||
0226         coex_stat->wl_rts_rx_rate <= COEX_CCK_2)
0227         is_cck_lock_rate = true;
0228 
0229     if (coex_stat->wl_connected && coex_stat->wl_gl_busy &&
0230         COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
0231         (coex_dm->bt_status == COEX_BTSTATUS_ACL_BUSY ||
0232          coex_dm->bt_status == COEX_BTSTATUS_ACL_SCO_BUSY ||
0233          coex_dm->bt_status == COEX_BTSTATUS_SCO_BUSY)) {
0234         if (is_cck_lock_rate) {
0235             coex_stat->wl_cck_lock = true;
0236 
0237             rtw_dbg(rtwdev, RTW_DBG_COEX,
0238                 "[BTCoex], cck locking...\n");
0239 
0240         } else {
0241             coex_stat->wl_cck_lock = false;
0242 
0243             rtw_dbg(rtwdev, RTW_DBG_COEX,
0244                 "[BTCoex], cck unlock...\n");
0245         }
0246     } else {
0247         coex_stat->wl_cck_lock = false;
0248     }
0249 
0250     /* CCK lock identification */
0251     if (coex_stat->wl_cck_lock && !coex_stat->wl_cck_lock_pre)
0252         ieee80211_queue_delayed_work(rtwdev->hw, &coex->wl_ccklock_work,
0253                          3 * HZ);
0254 
0255     coex_stat->wl_cck_lock_pre = coex_stat->wl_cck_lock;
0256 }
0257 
0258 static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
0259 {
0260     struct rtw_coex *coex = &rtwdev->coex;
0261     struct rtw_coex_stat *coex_stat = &coex->stat;
0262     struct rtw_dm_info *dm_info = &rtwdev->dm_info;
0263     u32 cnt_cck;
0264     bool wl_cck_lock = false;
0265 
0266     /* wifi noisy environment identification */
0267     cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
0268 
0269     if (!coex_stat->wl_gl_busy && !wl_cck_lock) {
0270         if (cnt_cck > 250) {
0271             if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
0272                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
0273 
0274             if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) {
0275                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
0276                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
0277             }
0278         } else if (cnt_cck < 100) {
0279             if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5)
0280                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++;
0281 
0282             if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) {
0283                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
0284                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
0285             }
0286         } else {
0287             if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)
0288                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;
0289 
0290             if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) {
0291                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
0292                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
0293             }
0294         }
0295 
0296         if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5)
0297             coex_stat->wl_noisy_level = 2;
0298         else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5)
0299             coex_stat->wl_noisy_level = 1;
0300         else
0301             coex_stat->wl_noisy_level = 0;
0302 
0303         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wl_noisy_level = %d\n",
0304             coex_stat->wl_noisy_level);
0305     }
0306 }
0307 
0308 static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
0309 {
0310     struct rtw_coex *coex = &rtwdev->coex;
0311     struct rtw_coex_stat *coex_stat = &coex->stat;
0312     u8 para[2] = {0};
0313     u8 times;
0314     u16 tbtt_interval = coex_stat->wl_beacon_interval;
0315 
0316     if (coex_stat->tdma_timer_base == type)
0317         return;
0318 
0319     coex_stat->tdma_timer_base = type;
0320 
0321     para[0] = COEX_H2C69_TDMA_SLOT;
0322 
0323     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], tbtt_interval = %d\n",
0324         tbtt_interval);
0325 
0326     if (type == TDMA_TIMER_TYPE_4SLOT && tbtt_interval < 120) {
0327         para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */
0328     } else if (tbtt_interval < 80 && tbtt_interval > 0) {
0329         times = 100 / tbtt_interval;
0330         if (100 % tbtt_interval != 0)
0331             times++;
0332 
0333         para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times);
0334     } else if (tbtt_interval >= 180) {
0335         times = tbtt_interval / 100;
0336         if (tbtt_interval % 100 <= 80)
0337             times--;
0338 
0339         para[1] = FIELD_PREP(PARA1_H2C69_TBTT_TIMES, times) |
0340               FIELD_PREP(PARA1_H2C69_TBTT_DIV100, 1);
0341     } else {
0342         para[1] = PARA1_H2C69_TDMA_2SLOT;
0343     }
0344 
0345     rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
0346 
0347     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): h2c_0x69 = 0x%x\n",
0348         __func__, para[1]);
0349 
0350     /* no 5ms_wl_slot_extend for 4-slot mode  */
0351     if (coex_stat->tdma_timer_base == 3)
0352         rtw_coex_wl_ccklock_action(rtwdev);
0353 }
0354 
0355 static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
0356                      u8 data)
0357 {
0358     u32 addr;
0359 
0360     addr = REG_BT_COEX_TABLE_H + (bitmap / 8);
0361     bitmap = bitmap % 8;
0362 
0363     rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);
0364 }
0365 
0366 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
0367 {
0368     struct rtw_chip_info *chip = rtwdev->chip;
0369     struct rtw_coex *coex = &rtwdev->coex;
0370     struct rtw_coex_stat *coex_stat = &coex->stat;
0371     u16 val = 0x2;
0372 
0373     if (!chip->scbd_support)
0374         return;
0375 
0376     val |= coex_stat->score_board;
0377 
0378     /* for 8822b, scbd[10] is CQDDR on
0379      * for 8822c, scbd[10] is no fix 2M
0380      */
0381     if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {
0382         if (set)
0383             val &= ~COEX_SCBD_FIX2M;
0384         else
0385             val |= COEX_SCBD_FIX2M;
0386     } else {
0387         if (set)
0388             val |= bitpos;
0389         else
0390             val &= ~bitpos;
0391     }
0392 
0393     if (val != coex_stat->score_board) {
0394         coex_stat->score_board = val;
0395         val |= BIT_BT_INT_EN;
0396         rtw_write16(rtwdev, REG_WIFI_BT_INFO, val);
0397     }
0398 }
0399 EXPORT_SYMBOL(rtw_coex_write_scbd);
0400 
0401 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
0402 {
0403     struct rtw_chip_info *chip = rtwdev->chip;
0404 
0405     if (!chip->scbd_support)
0406         return 0;
0407 
0408     return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);
0409 }
0410 
0411 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
0412 {
0413     struct rtw_chip_info *chip = rtwdev->chip;
0414     struct rtw_coex *coex = &rtwdev->coex;
0415     struct rtw_coex_stat *coex_stat = &coex->stat;
0416     struct rtw_coex_rfe *coex_rfe = &coex->rfe;
0417     u8 cnt = 0;
0418     u32 wait_cnt;
0419     bool btk, wlk;
0420 
0421     if (coex_rfe->wlg_at_btg && chip->scbd_support &&
0422         coex_stat->bt_iqk_state != 0xff) {
0423         rtw_dbg(rtwdev, RTW_DBG_COEX,
0424             "[BTCoex], (Before Ant Setup) Delay by IQK\n");
0425 
0426         wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
0427         do {
0428             /* BT RFK */
0429             btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);
0430 
0431             /* WL RFK */
0432             wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);
0433 
0434             if (!btk && !wlk)
0435                 break;
0436 
0437             rtw_dbg(rtwdev, RTW_DBG_COEX,
0438                 "[BTCoex], (Before Ant Setup) wlk = %d, btk = %d\n",
0439                 wlk, btk);
0440 
0441             mdelay(COEX_MIN_DELAY);
0442         } while (++cnt < wait_cnt);
0443 
0444         if (cnt >= wait_cnt)
0445             coex_stat->bt_iqk_state = 0xff;
0446     }
0447 }
0448 
0449 static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
0450 {
0451     struct rtw_coex *coex = &rtwdev->coex;
0452     struct rtw_coex_stat *coex_stat = &coex->stat;
0453 
0454     if (coex_stat->bt_disabled)
0455         return;
0456 
0457     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
0458 
0459     rtw_fw_query_bt_info(rtwdev);
0460 }
0461 
0462 static void rtw_coex_gnt_workaround(struct rtw_dev *rtwdev, bool force, u8 mode)
0463 {
0464     rtw_coex_set_gnt_fix(rtwdev);
0465 }
0466 
0467 static void rtw_coex_monitor_bt_ctr(struct rtw_dev *rtwdev)
0468 {
0469     struct rtw_coex *coex = &rtwdev->coex;
0470     struct rtw_coex_stat *coex_stat = &coex->stat;
0471     u32 tmp;
0472 
0473     tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS);
0474     coex_stat->hi_pri_tx = FIELD_GET(MASKLWORD, tmp);
0475     coex_stat->hi_pri_rx = FIELD_GET(MASKHWORD, tmp);
0476 
0477     tmp = rtw_read32(rtwdev, REG_BT_ACT_STATISTICS_1);
0478     coex_stat->lo_pri_tx = FIELD_GET(MASKLWORD, tmp);
0479     coex_stat->lo_pri_rx = FIELD_GET(MASKHWORD, tmp);
0480 
0481     rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL,
0482            BIT_R_GRANTALL_WLMASK | BIT_STATIS_BT_EN);
0483 
0484     rtw_dbg(rtwdev, RTW_DBG_COEX,
0485         "[BTCoex], Hi-Pri Rx/Tx: %d/%d, Lo-Pri Rx/Tx: %d/%d\n",
0486         coex_stat->hi_pri_rx, coex_stat->hi_pri_tx,
0487         coex_stat->lo_pri_rx, coex_stat->lo_pri_tx);
0488 }
0489 
0490 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
0491 {
0492     struct rtw_chip_info *chip = rtwdev->chip;
0493     struct rtw_coex *coex = &rtwdev->coex;
0494     struct rtw_coex_stat *coex_stat = &coex->stat;
0495     struct rtw_coex_dm *coex_dm = &coex->dm;
0496     bool bt_disabled = false;
0497     u16 score_board;
0498 
0499     if (chip->scbd_support) {
0500         score_board = rtw_coex_read_scbd(rtwdev);
0501         bt_disabled = !(score_board & COEX_SCBD_ONOFF);
0502     }
0503 
0504     if (coex_stat->bt_disabled != bt_disabled) {
0505         rtw_dbg(rtwdev, RTW_DBG_COEX,
0506             "[BTCoex], BT state changed (%d) -> (%d)\n",
0507             coex_stat->bt_disabled, bt_disabled);
0508 
0509         coex_stat->bt_disabled = bt_disabled;
0510         coex_stat->bt_ble_scan_type = 0;
0511         coex_dm->cur_bt_lna_lvl = 0;
0512 
0513         if (!coex_stat->bt_disabled) {
0514             coex_stat->bt_reenable = true;
0515             ieee80211_queue_delayed_work(rtwdev->hw,
0516                              &coex->bt_reenable_work,
0517                              15 * HZ);
0518         } else {
0519             coex_stat->bt_mailbox_reply = false;
0520             coex_stat->bt_reenable = false;
0521         }
0522     }
0523 }
0524 
0525 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
0526 {
0527     struct rtw_coex *coex = &rtwdev->coex;
0528     struct rtw_coex_stat *coex_stat = &coex->stat;
0529     struct rtw_coex_dm *coex_dm = &coex->dm;
0530     struct rtw_chip_info *chip = rtwdev->chip;
0531     struct rtw_traffic_stats *stats = &rtwdev->stats;
0532     bool is_5G = false;
0533     bool wl_busy = false;
0534     bool scan = false, link = false;
0535     int i;
0536     u8 rssi_state;
0537     u8 rssi_step;
0538     u8 rssi;
0539 
0540     scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);
0541     coex_stat->wl_connected = !!rtwdev->sta_cnt;
0542 
0543     wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
0544     if (wl_busy != coex_stat->wl_gl_busy) {
0545         if (wl_busy)
0546             coex_stat->wl_gl_busy = true;
0547         else
0548             ieee80211_queue_delayed_work(rtwdev->hw,
0549                              &coex->wl_remain_work,
0550                              12 * HZ);
0551     }
0552 
0553     if (stats->tx_throughput > stats->rx_throughput)
0554         coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
0555     else
0556         coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;
0557 
0558     if (scan || link || reason == COEX_RSN_2GCONSTART ||
0559         reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)
0560         coex_stat->wl_linkscan_proc = true;
0561     else
0562         coex_stat->wl_linkscan_proc = false;
0563 
0564     rtw_coex_wl_noisy_detect(rtwdev);
0565 
0566     for (i = 0; i < 4; i++) {
0567         rssi_state = coex_dm->wl_rssi_state[i];
0568         rssi_step = chip->wl_rssi_step[i];
0569         rssi = rtwdev->dm_info.min_rssi;
0570         rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
0571                               rssi, rssi_step);
0572         coex_dm->wl_rssi_state[i] = rssi_state;
0573     }
0574 
0575     if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
0576         coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
0577         rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
0578     else
0579         rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
0580 
0581     switch (reason) {
0582     case COEX_RSN_5GSCANSTART:
0583     case COEX_RSN_5GSWITCHBAND:
0584     case COEX_RSN_5GCONSTART:
0585 
0586         is_5G = true;
0587         break;
0588     case COEX_RSN_2GSCANSTART:
0589     case COEX_RSN_2GSWITCHBAND:
0590     case COEX_RSN_2GCONSTART:
0591 
0592         is_5G = false;
0593         break;
0594     default:
0595         if (rtwdev->hal.current_band_type == RTW_BAND_5G)
0596             is_5G = true;
0597         else
0598             is_5G = false;
0599         break;
0600     }
0601 
0602     coex->under_5g = is_5G;
0603 }
0604 
0605 static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)
0606 {
0607     struct rtw_c2h_cmd *c2h;
0608     u32 pkt_offset;
0609 
0610     pkt_offset = *((u32 *)resp->cb);
0611     c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);
0612 
0613     return c2h->payload;
0614 }
0615 
0616 void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)
0617 {
0618     struct rtw_coex *coex = &rtwdev->coex;
0619     u8 *payload = get_payload_from_coex_resp(skb);
0620 
0621     if (payload[0] != COEX_RESP_ACK_BY_WL_FW) {
0622         dev_kfree_skb_any(skb);
0623         return;
0624     }
0625 
0626     skb_queue_tail(&coex->queue, skb);
0627     wake_up(&coex->wait);
0628 }
0629 
0630 static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
0631                          struct rtw_coex_info_req *req)
0632 {
0633     struct rtw_coex *coex = &rtwdev->coex;
0634     struct sk_buff *skb_resp = NULL;
0635 
0636     mutex_lock(&coex->mutex);
0637 
0638     rtw_fw_query_bt_mp_info(rtwdev, req);
0639 
0640     if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
0641                 COEX_REQUEST_TIMEOUT)) {
0642         rtw_err(rtwdev, "coex request time out\n");
0643         goto out;
0644     }
0645 
0646     skb_resp = skb_dequeue(&coex->queue);
0647     if (!skb_resp) {
0648         rtw_err(rtwdev, "failed to get coex info response\n");
0649         goto out;
0650     }
0651 
0652 out:
0653     mutex_unlock(&coex->mutex);
0654     return skb_resp;
0655 }
0656 
0657 static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
0658 {
0659     struct rtw_coex_info_req req = {0};
0660     struct sk_buff *skb;
0661     u8 *payload;
0662 
0663     req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
0664     skb = rtw_coex_info_request(rtwdev, &req);
0665     if (!skb)
0666         return false;
0667 
0668     payload = get_payload_from_coex_resp(skb);
0669     *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
0670     dev_kfree_skb_any(skb);
0671     return true;
0672 }
0673 
0674 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
0675                          u8 lna_constrain_level)
0676 {
0677     struct rtw_coex_info_req req = {0};
0678     struct sk_buff *skb;
0679 
0680     req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
0681     req.para1 = lna_constrain_level;
0682     skb = rtw_coex_info_request(rtwdev, &req);
0683     if (!skb)
0684         return false;
0685 
0686     dev_kfree_skb_any(skb);
0687     return true;
0688 }
0689 
0690 #define case_BTSTATUS(src) \
0691     case COEX_BTSTATUS_##src: return #src
0692 
0693 static const char *rtw_coex_get_bt_status_string(u8 bt_status)
0694 {
0695     switch (bt_status) {
0696     case_BTSTATUS(NCON_IDLE);
0697     case_BTSTATUS(CON_IDLE);
0698     case_BTSTATUS(INQ_PAGE);
0699     case_BTSTATUS(ACL_BUSY);
0700     case_BTSTATUS(SCO_BUSY);
0701     case_BTSTATUS(ACL_SCO_BUSY);
0702     default:
0703         return "Unknown";
0704     }
0705 }
0706 
0707 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
0708 {
0709     struct rtw_coex *coex = &rtwdev->coex;
0710     struct rtw_coex_stat *coex_stat = &coex->stat;
0711     struct rtw_coex_dm *coex_dm = &coex->dm;
0712     struct rtw_chip_info *chip = rtwdev->chip;
0713     u8 i;
0714     u8 rssi_state;
0715     u8 rssi_step;
0716     u8 rssi;
0717 
0718     /* update wl/bt rssi by btinfo */
0719     for (i = 0; i < COEX_RSSI_STEP; i++) {
0720         rssi_state = coex_dm->bt_rssi_state[i];
0721         rssi_step = chip->bt_rssi_step[i];
0722         rssi = coex_stat->bt_rssi;
0723         rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, rssi,
0724                               rssi_step);
0725         coex_dm->bt_rssi_state[i] = rssi_state;
0726     }
0727 
0728     if (coex_stat->bt_ble_scan_en &&
0729         coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
0730         u8 scan_type;
0731 
0732         if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {
0733             coex_stat->bt_ble_scan_type = scan_type;
0734             if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)
0735                 coex_stat->bt_init_scan = true;
0736             else
0737                 coex_stat->bt_init_scan = false;
0738         }
0739     }
0740 
0741     coex_stat->bt_profile_num = 0;
0742 
0743     /* set link exist status */
0744     if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
0745         coex_stat->bt_link_exist = false;
0746         coex_stat->bt_pan_exist = false;
0747         coex_stat->bt_a2dp_exist = false;
0748         coex_stat->bt_hid_exist = false;
0749         coex_stat->bt_hfp_exist = false;
0750     } else {
0751         /* connection exists */
0752         coex_stat->bt_link_exist = true;
0753         if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {
0754             coex_stat->bt_pan_exist = true;
0755             coex_stat->bt_profile_num++;
0756         } else {
0757             coex_stat->bt_pan_exist = false;
0758         }
0759 
0760         if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {
0761             coex_stat->bt_a2dp_exist = true;
0762             coex_stat->bt_profile_num++;
0763         } else {
0764             coex_stat->bt_a2dp_exist = false;
0765         }
0766 
0767         if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {
0768             coex_stat->bt_hid_exist = true;
0769             coex_stat->bt_profile_num++;
0770         } else {
0771             coex_stat->bt_hid_exist = false;
0772         }
0773 
0774         if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {
0775             coex_stat->bt_hfp_exist = true;
0776             coex_stat->bt_profile_num++;
0777         } else {
0778             coex_stat->bt_hfp_exist = false;
0779         }
0780     }
0781 
0782     if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {
0783         coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
0784     } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
0785         coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
0786         coex_stat->bt_multi_link_remain = false;
0787     } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
0788         coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
0789     } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
0790            (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {
0791         if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)
0792             coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;
0793         else
0794             coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;
0795     } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {
0796         coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;
0797     } else {
0798         coex_dm->bt_status = COEX_BTSTATUS_MAX;
0799     }
0800 
0801     coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
0802 
0803     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(), %s!!!\n", __func__,
0804         rtw_coex_get_bt_status_string(coex_dm->bt_status));
0805 }
0806 
0807 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
0808 {
0809     struct rtw_chip_info *chip = rtwdev->chip;
0810     struct rtw_efuse *efuse = &rtwdev->efuse;
0811     struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
0812     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
0813     u8 link = 0;
0814     u8 center_chan = 0;
0815     u8 bw;
0816     int i;
0817 
0818     bw = rtwdev->hal.current_band_width;
0819 
0820     if (type != COEX_MEDIA_DISCONNECT)
0821         center_chan = rtwdev->hal.current_channel;
0822 
0823     if (center_chan == 0 ||
0824         (efuse->share_ant && center_chan <= 14 &&
0825          coex_stat->wl_coex_mode != COEX_WLINK_2GFREE)) {
0826         link = 0;
0827         center_chan = 0;
0828         bw = 0;
0829     } else if (center_chan <= 14) {
0830         link = 0x1;
0831 
0832         if (bw == RTW_CHANNEL_WIDTH_40)
0833             bw = chip->bt_afh_span_bw40;
0834         else
0835             bw = chip->bt_afh_span_bw20;
0836     } else if (chip->afh_5g_num > 1) {
0837         for (i = 0; i < chip->afh_5g_num; i++) {
0838             if (center_chan == chip->afh_5g[i].wl_5g_ch) {
0839                 link = 0x3;
0840                 center_chan = chip->afh_5g[i].bt_skip_ch;
0841                 bw = chip->afh_5g[i].bt_skip_span;
0842                 break;
0843             }
0844         }
0845     }
0846 
0847     coex_dm->wl_ch_info[0] = link;
0848     coex_dm->wl_ch_info[1] = center_chan;
0849     coex_dm->wl_ch_info[2] = bw;
0850 
0851     rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
0852     rtw_dbg(rtwdev, RTW_DBG_COEX,
0853         "[BTCoex], %s: para[0:2] = 0x%x 0x%x 0x%x\n", __func__, link,
0854         center_chan, bw);
0855 }
0856 
0857 static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
0858 {
0859     struct rtw_coex *coex = &rtwdev->coex;
0860     struct rtw_coex_dm *coex_dm = &coex->dm;
0861 
0862     if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)
0863         return;
0864 
0865     coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;
0866 
0867     rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);
0868 }
0869 
0870 static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
0871 {
0872     struct rtw_coex *coex = &rtwdev->coex;
0873     struct rtw_coex_dm *coex_dm = &coex->dm;
0874 
0875     if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)
0876         return;
0877 
0878     coex_dm->cur_bt_lna_lvl = bt_lna_lvl;
0879 
0880     /* notify BT rx gain table changed */
0881     if (bt_lna_lvl < 7) {
0882         rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);
0883         rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);
0884     } else {
0885         rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
0886     }
0887     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): bt_rx_LNA_level = %d\n",
0888         __func__, bt_lna_lvl);
0889 }
0890 
0891 static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
0892                  struct coex_rf_para para)
0893 {
0894     struct rtw_coex *coex = &rtwdev->coex;
0895     struct rtw_coex_stat *coex_stat = &coex->stat;
0896     u8 offset = 0;
0897 
0898     if (coex->freerun && coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] <= 5)
0899         offset = 3;
0900 
0901     rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
0902     rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);
0903     rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);
0904     rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
0905 }
0906 
0907 u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
0908 {
0909     u32 val;
0910 
0911     if (!ltecoex_read_reg(rtwdev, addr, &val)) {
0912         rtw_err(rtwdev, "failed to read indirect register\n");
0913         return 0;
0914     }
0915 
0916     return val;
0917 }
0918 EXPORT_SYMBOL(rtw_coex_read_indirect_reg);
0919 
0920 void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
0921                  u32 mask, u32 val)
0922 {
0923     u32 shift = __ffs(mask);
0924     u32 tmp;
0925 
0926     tmp = rtw_coex_read_indirect_reg(rtwdev, addr);
0927     tmp = (tmp & (~mask)) | ((val << shift) & mask);
0928 
0929     if (!ltecoex_reg_write(rtwdev, addr, tmp))
0930         rtw_err(rtwdev, "failed to write indirect register\n");
0931 }
0932 EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
0933 
0934 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
0935 {
0936     struct rtw_chip_info *chip = rtwdev->chip;
0937     const struct rtw_hw_reg *btg_reg = chip->btg_reg;
0938 
0939     if (wifi_control) {
0940         rtw_write8_set(rtwdev, REG_SYS_SDIO_CTRL + 3,
0941                    BIT_LTE_MUX_CTRL_PATH >> 24);
0942         if (btg_reg)
0943             rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
0944     } else {
0945         rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL + 3,
0946                    BIT_LTE_MUX_CTRL_PATH >> 24);
0947         if (btg_reg)
0948             rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
0949     }
0950 }
0951 
0952 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
0953 {
0954     rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state);
0955     rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state);
0956 }
0957 
0958 static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
0959 {
0960     rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state);
0961     rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state);
0962 }
0963 
0964 static void rtw_coex_mimo_ps(struct rtw_dev *rtwdev, bool force, bool state)
0965 {
0966     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
0967 
0968     if (!force && state == coex_stat->wl_mimo_ps)
0969         return;
0970 
0971     coex_stat->wl_mimo_ps = state;
0972 
0973     rtw_set_txrx_1ss(rtwdev, state);
0974 
0975     rtw_coex_update_wl_ch_info(rtwdev, (u8)coex_stat->wl_connected);
0976 
0977     rtw_dbg(rtwdev, RTW_DBG_COEX,
0978         "[BTCoex], %s(): state = %d\n", __func__, state);
0979 }
0980 
0981 static void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force,
0982                      u8 table_case)
0983 {
0984     struct rtw_chip_info *chip = rtwdev->chip;
0985     struct rtw_efuse *efuse = &rtwdev->efuse;
0986     u8 h2c_para[6] = {0};
0987     u32 table_wl = 0x5a5a5a5a;
0988 
0989     h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_A;
0990     /* no definition */
0991     h2c_para[1] = 0x1;
0992 
0993     if (efuse->share_ant) {
0994         if (table_case < chip->table_sant_num)
0995             table_wl = chip->table_sant[table_case].wl;
0996     } else {
0997         if (table_case < chip->table_nsant_num)
0998             table_wl = chip->table_nsant[table_case].wl;
0999     }
1000 
1001     /* tell WL FW WL slot toggle table-A*/
1002     h2c_para[2] = (u8)u32_get_bits(table_wl, GENMASK(7, 0));
1003     h2c_para[3] = (u8)u32_get_bits(table_wl, GENMASK(15, 8));
1004     h2c_para[4] = (u8)u32_get_bits(table_wl, GENMASK(23, 16));
1005     h2c_para[5] = (u8)u32_get_bits(table_wl, GENMASK(31, 24));
1006 
1007     rtw_fw_bt_wifi_control(rtwdev, h2c_para[0], &h2c_para[1]);
1008 
1009     rtw_dbg(rtwdev, RTW_DBG_COEX,
1010         "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
1011         __func__, h2c_para[0], h2c_para[1], h2c_para[2],
1012         h2c_para[3], h2c_para[4], h2c_para[5]);
1013 }
1014 
1015 #define COEX_WL_SLOT_TOGLLE 0x5a5a5aaa
1016 static void rtw_btc_wltoggle_table_b(struct rtw_dev *rtwdev, bool force,
1017                      u8 interval, u32 table)
1018 {
1019     struct rtw_coex *coex = &rtwdev->coex;
1020     struct rtw_coex_stat *coex_stat = &coex->stat;
1021     u8 cur_h2c_para[6] = {0};
1022     u8 i;
1023 
1024     cur_h2c_para[0] = COEX_H2C69_TOGGLE_TABLE_B;
1025     cur_h2c_para[1] = interval;
1026     cur_h2c_para[2] = (u8)u32_get_bits(table, GENMASK(7, 0));
1027     cur_h2c_para[3] = (u8)u32_get_bits(table, GENMASK(15, 8));
1028     cur_h2c_para[4] = (u8)u32_get_bits(table, GENMASK(23, 16));
1029     cur_h2c_para[5] = (u8)u32_get_bits(table, GENMASK(31, 24));
1030 
1031     coex_stat->wl_toggle_interval = interval;
1032 
1033     for (i = 0; i <= 5; i++)
1034         coex_stat->wl_toggle_para[i] = cur_h2c_para[i];
1035 
1036     rtw_fw_bt_wifi_control(rtwdev, cur_h2c_para[0], &cur_h2c_para[1]);
1037 
1038     rtw_dbg(rtwdev, RTW_DBG_COEX,
1039         "[BTCoex], %s(): H2C = [%02x %02x %02x %02x %02x %02x]\n",
1040         __func__, cur_h2c_para[0], cur_h2c_para[1], cur_h2c_para[2],
1041         cur_h2c_para[3], cur_h2c_para[4], cur_h2c_para[5]);
1042 }
1043 
1044 static void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0,
1045                    u32 table1)
1046 {
1047 #define DEF_BRK_TABLE_VAL 0xf0ffffff
1048     struct rtw_coex *coex = &rtwdev->coex;
1049     struct rtw_coex_dm *coex_dm = &coex->dm;
1050 
1051     /* If last tdma is wl slot toggle, force write table*/
1052     if (!force && coex_dm->reason != COEX_RSN_LPS) {
1053         if (table0 == rtw_read32(rtwdev, REG_BT_COEX_TABLE0) &&
1054             table1 == rtw_read32(rtwdev, REG_BT_COEX_TABLE1))
1055             return;
1056     }
1057     rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
1058     rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
1059     rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
1060 
1061     rtw_dbg(rtwdev, RTW_DBG_COEX,
1062         "[BTCoex], %s(): 0x6c0 = %x, 0x6c4 = %x\n", __func__, table0,
1063         table1);
1064 }
1065 
1066 static void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type)
1067 {
1068     struct rtw_coex *coex = &rtwdev->coex;
1069     struct rtw_coex_dm *coex_dm = &coex->dm;
1070     struct rtw_chip_info *chip = rtwdev->chip;
1071     struct rtw_efuse *efuse = &rtwdev->efuse;
1072     struct rtw_coex_stat *coex_stat = &coex->stat;
1073 
1074     coex_dm->cur_table = type;
1075 
1076     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], Coex_Table - %d\n", type);
1077 
1078     if (efuse->share_ant) {
1079         if (type < chip->table_sant_num)
1080             rtw_coex_set_table(rtwdev, force,
1081                        chip->table_sant[type].bt,
1082                        chip->table_sant[type].wl);
1083     } else {
1084         type = type - 100;
1085         if (type < chip->table_nsant_num)
1086             rtw_coex_set_table(rtwdev, force,
1087                        chip->table_nsant[type].bt,
1088                        chip->table_nsant[type].wl);
1089     }
1090     if (coex_stat->wl_slot_toggle_change)
1091         rtw_btc_wltoggle_table_a(rtwdev, true, type);
1092 }
1093 
1094 static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
1095 {
1096     struct rtw_coex *coex = &rtwdev->coex;
1097 
1098     if (coex->manual_control || coex->stop_dm)
1099         return;
1100 
1101     rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
1102 }
1103 
1104 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
1105                       u8 lps_val, u8 rpwm_val)
1106 {
1107     struct rtw_coex *coex = &rtwdev->coex;
1108     struct rtw_coex_stat *coex_stat = &coex->stat;
1109     u8 lps_mode = 0x0;
1110 
1111     lps_mode = rtwdev->lps_conf.mode;
1112 
1113     switch (ps_type) {
1114     case COEX_PS_WIFI_NATIVE:
1115         /* recover to original 32k low power setting */
1116         coex_stat->wl_force_lps_ctrl = false;
1117         rtw_dbg(rtwdev, RTW_DBG_COEX,
1118             "[BTCoex], %s(): COEX_PS_WIFI_NATIVE\n", __func__);
1119         rtw_leave_lps(rtwdev);
1120         break;
1121     case COEX_PS_LPS_OFF:
1122         coex_stat->wl_force_lps_ctrl = true;
1123         if (lps_mode)
1124             rtw_fw_coex_tdma_type(rtwdev, 0, 0, 0, 0, 0);
1125 
1126         rtw_leave_lps(rtwdev);
1127         rtw_dbg(rtwdev, RTW_DBG_COEX,
1128             "[BTCoex], %s(): COEX_PS_LPS_OFF\n", __func__);
1129         break;
1130     default:
1131         break;
1132     }
1133 }
1134 
1135 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
1136                   u8 byte3, u8 byte4, u8 byte5)
1137 {
1138     struct rtw_coex *coex = &rtwdev->coex;
1139     struct rtw_coex_dm *coex_dm = &coex->dm;
1140     struct rtw_chip_info *chip = rtwdev->chip;
1141     struct rtw_coex_stat *coex_stat = &coex->stat;
1142     u8 ps_type = COEX_PS_WIFI_NATIVE;
1143     bool ap_enable = false;
1144 
1145     if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
1146         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): AP mode\n",
1147             __func__);
1148 
1149         byte1 &= ~BIT(4);
1150         byte1 |= BIT(5);
1151 
1152         byte5 |= BIT(5);
1153         byte5 &= ~BIT(6);
1154 
1155         ps_type = COEX_PS_WIFI_NATIVE;
1156         rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
1157     } else if ((byte1 & BIT(4) && !(byte1 & BIT(5))) ||
1158            coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
1159         rtw_dbg(rtwdev, RTW_DBG_COEX,
1160             "[BTCoex], %s(): Force LPS (byte1 = 0x%x)\n", __func__,
1161             byte1);
1162 
1163         if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
1164             ps_type = COEX_PS_LPS_OFF;
1165         else
1166             ps_type = COEX_PS_LPS_ON;
1167         rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
1168     } else {
1169         rtw_dbg(rtwdev, RTW_DBG_COEX,
1170             "[BTCoex], %s(): native power save (byte1 = 0x%x)\n",
1171             __func__, byte1);
1172 
1173         ps_type = COEX_PS_WIFI_NATIVE;
1174         rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
1175     }
1176 
1177     coex_dm->ps_tdma_para[0] = byte1;
1178     coex_dm->ps_tdma_para[1] = byte2;
1179     coex_dm->ps_tdma_para[2] = byte3;
1180     coex_dm->ps_tdma_para[3] = byte4;
1181     coex_dm->ps_tdma_para[4] = byte5;
1182 
1183     rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
1184 
1185     if (byte1 & BIT(2)) {
1186         coex_stat->wl_slot_toggle = true;
1187         coex_stat->wl_slot_toggle_change = false;
1188     } else {
1189         coex_stat->wl_slot_toggle_change = coex_stat->wl_slot_toggle;
1190         coex_stat->wl_slot_toggle = false;
1191     }
1192 }
1193 
1194 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
1195 {
1196     struct rtw_coex *coex = &rtwdev->coex;
1197     struct rtw_coex_dm *coex_dm = &coex->dm;
1198     struct rtw_coex_stat *coex_stat = &coex->stat;
1199     struct rtw_chip_info *chip = rtwdev->chip;
1200     struct rtw_efuse *efuse = &rtwdev->efuse;
1201     u8 n, type;
1202     bool turn_on;
1203     bool wl_busy = false;
1204 
1205     if (tcase & TDMA_4SLOT) /* 4-slot (50ms) mode */
1206         rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_4SLOT);
1207     else
1208         rtw_coex_tdma_timer_base(rtwdev, TDMA_TIMER_TYPE_2SLOT);
1209 
1210     type = (u8)(tcase & 0xff);
1211 
1212     turn_on = (type == 0 || type == 100) ? false : true;
1213 
1214     if (!force && turn_on == coex_dm->cur_ps_tdma_on &&
1215         type == coex_dm->cur_ps_tdma) {
1216         rtw_dbg(rtwdev, RTW_DBG_COEX,
1217             "[BTCoex], Skip TDMA because no change TDMA(%s, %d)\n",
1218             (coex_dm->cur_ps_tdma_on ? "on" : "off"),
1219             coex_dm->cur_ps_tdma);
1220 
1221         return;
1222     }
1223     wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
1224 
1225     if ((coex_stat->bt_a2dp_exist &&
1226          (coex_stat->bt_inq_remain || coex_stat->bt_multi_link)) ||
1227         !wl_busy)
1228         rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);
1229     else
1230         rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
1231 
1232     /* update pre state */
1233     coex_dm->cur_ps_tdma_on = turn_on;
1234     coex_dm->cur_ps_tdma = type;
1235 
1236     if (efuse->share_ant) {
1237         if (type < chip->tdma_sant_num)
1238             rtw_coex_set_tdma(rtwdev,
1239                       chip->tdma_sant[type].para[0],
1240                       chip->tdma_sant[type].para[1],
1241                       chip->tdma_sant[type].para[2],
1242                       chip->tdma_sant[type].para[3],
1243                       chip->tdma_sant[type].para[4]);
1244     } else {
1245         n = type - 100;
1246         if (n < chip->tdma_nsant_num)
1247             rtw_coex_set_tdma(rtwdev,
1248                       chip->tdma_nsant[n].para[0],
1249                       chip->tdma_nsant[n].para[1],
1250                       chip->tdma_nsant[n].para[2],
1251                       chip->tdma_nsant[n].para[3],
1252                       chip->tdma_nsant[n].para[4]);
1253     }
1254 
1255 
1256     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], coex tdma type(%s, %d)\n",
1257         turn_on ? "on" : "off", type);
1258 }
1259 
1260 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
1261 {
1262     struct rtw_coex *coex = &rtwdev->coex;
1263     struct rtw_coex_stat *coex_stat = &coex->stat;
1264     struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1265     struct rtw_coex_dm *coex_dm = &coex->dm;
1266     u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
1267     u8 pos_type = COEX_SWITCH_TO_MAX;
1268 
1269     if (!force && coex_dm->cur_ant_pos_type == phase)
1270         return;
1271 
1272     coex_dm->cur_ant_pos_type = phase;
1273 
1274     /* avoid switch coex_ctrl_owner during BT IQK */
1275     rtw_coex_check_rfk(rtwdev);
1276 
1277     rtw_dbg(rtwdev, RTW_DBG_COEX,
1278         "[BTCoex],  coex_stat->bt_disabled = 0x%x\n",
1279         coex_stat->bt_disabled);
1280 
1281     switch (phase) {
1282     case COEX_SET_ANT_POWERON:
1283         rtw_dbg(rtwdev, RTW_DBG_COEX,
1284             "[BTCoex], %s() - PHASE_COEX_POWERON\n", __func__);
1285         /* set path control owner to BT at power-on */
1286         if (coex_stat->bt_disabled)
1287             rtw_coex_coex_ctrl_owner(rtwdev, true);
1288         else
1289             rtw_coex_coex_ctrl_owner(rtwdev, false);
1290 
1291         ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1292         pos_type = COEX_SWITCH_TO_BT;
1293         break;
1294     case COEX_SET_ANT_INIT:
1295         rtw_dbg(rtwdev, RTW_DBG_COEX,
1296             "[BTCoex], %s() - PHASE_COEX_INIT\n", __func__);
1297         if (coex_stat->bt_disabled) {
1298             /* set GNT_BT to SW low */
1299             rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1300 
1301             /* set GNT_WL to SW high */
1302             rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1303         } else {
1304             /* set GNT_BT to SW high */
1305             rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1306 
1307             /* set GNT_WL to SW low */
1308             rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);
1309         }
1310 
1311         /* set path control owner to wl at initial step */
1312         rtw_coex_coex_ctrl_owner(rtwdev, true);
1313 
1314         ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1315         pos_type = COEX_SWITCH_TO_BT;
1316         break;
1317     case COEX_SET_ANT_WONLY:
1318         rtw_dbg(rtwdev, RTW_DBG_COEX,
1319             "[BTCoex], %s() - PHASE_WLANONLY_INIT\n", __func__);
1320         /* set GNT_BT to SW Low */
1321         rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1322 
1323         /* set GNT_WL to SW high */
1324         rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1325 
1326         /* set path control owner to wl at initial step */
1327         rtw_coex_coex_ctrl_owner(rtwdev, true);
1328 
1329         ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1330         pos_type = COEX_SWITCH_TO_WLG;
1331         break;
1332     case COEX_SET_ANT_WOFF:
1333         rtw_dbg(rtwdev, RTW_DBG_COEX,
1334             "[BTCoex], %s() - PHASE_WLAN_OFF\n", __func__);
1335         /* set path control owner to BT */
1336         rtw_coex_coex_ctrl_owner(rtwdev, false);
1337 
1338         ctrl_type = COEX_SWITCH_CTRL_BY_BT;
1339         pos_type = COEX_SWITCH_TO_NOCARE;
1340         break;
1341     case COEX_SET_ANT_2G:
1342         rtw_dbg(rtwdev, RTW_DBG_COEX,
1343             "[BTCoex], %s() - PHASE_2G_RUNTIME\n", __func__);
1344         /* set GNT_BT to PTA */
1345         rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1346 
1347         /* set GNT_WL to PTA */
1348         rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1349 
1350         /* set path control owner to wl at runtime step */
1351         rtw_coex_coex_ctrl_owner(rtwdev, true);
1352 
1353         ctrl_type = COEX_SWITCH_CTRL_BY_PTA;
1354         pos_type = COEX_SWITCH_TO_NOCARE;
1355         break;
1356     case COEX_SET_ANT_5G:
1357         rtw_dbg(rtwdev, RTW_DBG_COEX,
1358             "[BTCoex], %s() - PHASE_5G_RUNTIME\n", __func__);
1359 
1360         /* set GNT_BT to HW PTA */
1361         rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1362 
1363         /* set GNT_WL to SW high */
1364         rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1365 
1366         /* set path control owner to wl at runtime step */
1367         rtw_coex_coex_ctrl_owner(rtwdev, true);
1368 
1369         ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1370         pos_type = COEX_SWITCH_TO_WLA;
1371         break;
1372     case COEX_SET_ANT_2G_FREERUN:
1373         rtw_dbg(rtwdev, RTW_DBG_COEX,
1374             "[BTCoex], %s() - PHASE_2G_FREERUN\n", __func__);
1375 
1376         /* set GNT_BT to HW PTA */
1377         rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1378 
1379         /* Set GNT_WL to SW high */
1380         rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1381 
1382         /* set path control owner to wl at runtime step */
1383         rtw_coex_coex_ctrl_owner(rtwdev, true);
1384 
1385         ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1386         pos_type = COEX_SWITCH_TO_WLG_BT;
1387         break;
1388     case COEX_SET_ANT_2G_WLBT:
1389         rtw_dbg(rtwdev, RTW_DBG_COEX,
1390             "[BTCoex], %s() - PHASE_2G_WLBT\n", __func__);
1391         /* set GNT_BT to HW PTA */
1392         rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1393 
1394         /* Set GNT_WL to HW PTA */
1395         rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1396 
1397         /* set path control owner to wl at runtime step */
1398         rtw_coex_coex_ctrl_owner(rtwdev, true);
1399 
1400         ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1401         pos_type = COEX_SWITCH_TO_WLG_BT;
1402         break;
1403     default:
1404         WARN(1, "unknown phase when setting antenna path\n");
1405         return;
1406     }
1407 
1408     if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX &&
1409         coex_rfe->ant_switch_exist)
1410         rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
1411 }
1412 
1413 #define case_ALGO(src) \
1414     case COEX_ALGO_##src: return #src
1415 
1416 static const char *rtw_coex_get_algo_string(u8 algo)
1417 {
1418     switch (algo) {
1419     case_ALGO(NOPROFILE);
1420     case_ALGO(HFP);
1421     case_ALGO(HID);
1422     case_ALGO(A2DP);
1423     case_ALGO(PAN);
1424     case_ALGO(A2DP_HID);
1425     case_ALGO(A2DP_PAN);
1426     case_ALGO(PAN_HID);
1427     case_ALGO(A2DP_PAN_HID);
1428     default:
1429         return "Unknown";
1430     }
1431 }
1432 
1433 #define case_BT_PROFILE(src) \
1434     case BPM_##src: return #src
1435 
1436 static const char *rtw_coex_get_bt_profile_string(u8 bt_profile)
1437 {
1438     switch (bt_profile) {
1439     case_BT_PROFILE(NOPROFILE);
1440     case_BT_PROFILE(HFP);
1441     case_BT_PROFILE(HID);
1442     case_BT_PROFILE(A2DP);
1443     case_BT_PROFILE(PAN);
1444     case_BT_PROFILE(HID_HFP);
1445     case_BT_PROFILE(A2DP_HFP);
1446     case_BT_PROFILE(A2DP_HID);
1447     case_BT_PROFILE(A2DP_HID_HFP);
1448     case_BT_PROFILE(PAN_HFP);
1449     case_BT_PROFILE(PAN_HID);
1450     case_BT_PROFILE(PAN_HID_HFP);
1451     case_BT_PROFILE(PAN_A2DP);
1452     case_BT_PROFILE(PAN_A2DP_HFP);
1453     case_BT_PROFILE(PAN_A2DP_HID);
1454     case_BT_PROFILE(PAN_A2DP_HID_HFP);
1455     default:
1456         return "Unknown";
1457     }
1458 }
1459 
1460 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
1461 {
1462     struct rtw_coex *coex = &rtwdev->coex;
1463     struct rtw_coex_stat *coex_stat = &coex->stat;
1464     u8 algorithm = COEX_ALGO_NOPROFILE;
1465     u8 profile_map = 0;
1466 
1467     if (coex_stat->bt_hfp_exist)
1468         profile_map |= BPM_HFP;
1469     if (coex_stat->bt_hid_exist)
1470         profile_map |= BPM_HID;
1471     if (coex_stat->bt_a2dp_exist)
1472         profile_map |= BPM_A2DP;
1473     if (coex_stat->bt_pan_exist)
1474         profile_map |= BPM_PAN;
1475 
1476     switch (profile_map) {
1477     case BPM_HFP:
1478         algorithm = COEX_ALGO_HFP;
1479         break;
1480     case           BPM_HID:
1481     case BPM_HFP + BPM_HID:
1482         algorithm = COEX_ALGO_HID;
1483         break;
1484     case BPM_HFP           + BPM_A2DP:
1485     case           BPM_HID + BPM_A2DP:
1486     case BPM_HFP + BPM_HID + BPM_A2DP:
1487         algorithm = COEX_ALGO_A2DP_HID;
1488         break;
1489     case BPM_HFP                      + BPM_PAN:
1490     case           BPM_HID            + BPM_PAN:
1491     case BPM_HFP + BPM_HID            + BPM_PAN:
1492         algorithm = COEX_ALGO_PAN_HID;
1493         break;
1494     case BPM_HFP           + BPM_A2DP + BPM_PAN:
1495     case           BPM_HID + BPM_A2DP + BPM_PAN:
1496     case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN:
1497         algorithm = COEX_ALGO_A2DP_PAN_HID;
1498         break;
1499     case                                BPM_PAN:
1500         algorithm = COEX_ALGO_PAN;
1501         break;
1502     case                     BPM_A2DP + BPM_PAN:
1503         algorithm = COEX_ALGO_A2DP_PAN;
1504         break;
1505     case                     BPM_A2DP:
1506         if (coex_stat->bt_multi_link) {
1507             if (coex_stat->bt_hid_pair_num > 0)
1508                 algorithm = COEX_ALGO_A2DP_HID;
1509             else
1510                 algorithm = COEX_ALGO_A2DP_PAN;
1511         } else {
1512             algorithm = COEX_ALGO_A2DP;
1513         }
1514         break;
1515     default:
1516         algorithm = COEX_ALGO_NOPROFILE;
1517         break;
1518     }
1519 
1520     rtw_dbg(rtwdev, RTW_DBG_COEX,
1521         "[BTCoex], BT Profile = %s => Algorithm = %s\n",
1522         rtw_coex_get_bt_profile_string(profile_map),
1523         rtw_coex_get_algo_string(algorithm));
1524     return algorithm;
1525 }
1526 
1527 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
1528 {
1529     struct rtw_efuse *efuse = &rtwdev->efuse;
1530     struct rtw_chip_info *chip = rtwdev->chip;
1531     u8 table_case, tdma_case;
1532 
1533     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1534     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1535 
1536     if (efuse->share_ant) {
1537         /* Shared-Ant */
1538         table_case = 2;
1539         tdma_case = 0;
1540     } else {
1541         /* Non-Shared-Ant */
1542         table_case = 100;
1543         tdma_case = 100;
1544     }
1545 
1546     rtw_coex_table(rtwdev, false, table_case);
1547     rtw_coex_tdma(rtwdev, false, tdma_case);
1548 }
1549 
1550 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
1551 {
1552     struct rtw_coex *coex = &rtwdev->coex;
1553     struct rtw_coex_stat *coex_stat = &coex->stat;
1554     struct rtw_coex_dm *coex_dm = &coex->dm;
1555     struct rtw_efuse *efuse = &rtwdev->efuse;
1556     struct rtw_chip_info *chip = rtwdev->chip;
1557     u8 level = 0;
1558     bool bt_afh_loss = true;
1559 
1560     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1561 
1562     if (efuse->share_ant)
1563         return;
1564 
1565     coex->freerun = true;
1566 
1567     if (bt_afh_loss)
1568         rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
1569 
1570     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1571 
1572     rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1573 
1574     if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))
1575         level = 2;
1576     else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1577         level = 3;
1578     else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))
1579         level = 4;
1580     else
1581         level = 5;
1582 
1583     if (level > chip->wl_rf_para_num - 1)
1584         level = chip->wl_rf_para_num - 1;
1585 
1586     if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1587         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);
1588     else
1589         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
1590 
1591     rtw_coex_table(rtwdev, false, 100);
1592     rtw_coex_tdma(rtwdev, false, 100);
1593 }
1594 
1595 static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)
1596 {
1597     struct rtw_efuse *efuse = &rtwdev->efuse;
1598     struct rtw_chip_info *chip = rtwdev->chip;
1599     u8 table_case, tdma_case;
1600 
1601     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1602 
1603     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1604     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1605 
1606     if (efuse->share_ant) {
1607         /* Shared-Ant */
1608         table_case = 9;
1609         tdma_case = 16;
1610     } else {
1611         /* Non-Shared-Ant */
1612         table_case = 100;
1613         tdma_case = 100;
1614     }
1615 
1616     rtw_coex_table(rtwdev, false, table_case);
1617     rtw_coex_tdma(rtwdev, false, tdma_case);
1618 }
1619 
1620 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
1621 {
1622     struct rtw_efuse *efuse = &rtwdev->efuse;
1623     struct rtw_chip_info *chip = rtwdev->chip;
1624     u8 table_case, tdma_case;
1625 
1626     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1627 
1628     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1629     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1630 
1631     if (efuse->share_ant) {
1632         /* Shared-Ant */
1633         table_case = 2;
1634         tdma_case = 0;
1635     } else {
1636         /* Non-Shared-Ant */
1637         table_case = 100;
1638         tdma_case = 100;
1639     }
1640 
1641     rtw_coex_table(rtwdev, false, table_case);
1642     rtw_coex_tdma(rtwdev, false, tdma_case);
1643 }
1644 
1645 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
1646 {
1647     struct rtw_coex *coex = &rtwdev->coex;
1648     struct rtw_coex_stat *coex_stat = &coex->stat;
1649     struct rtw_efuse *efuse = &rtwdev->efuse;
1650     struct rtw_chip_info *chip = rtwdev->chip;
1651     u8 table_case, tdma_case;
1652     u32 slot_type = 0;
1653 
1654     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1655 
1656     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1657     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1658 
1659     if (efuse->share_ant) { /* Shared-Ant */
1660         if (coex_stat->wl_gl_busy) {
1661             table_case = 26;
1662             if (coex_stat->bt_hid_exist &&
1663                 coex_stat->bt_profile_num == 1) {
1664                 slot_type = TDMA_4SLOT;
1665                 tdma_case = 20;
1666             } else {
1667                 tdma_case = 20;
1668             }
1669         } else {
1670             table_case = 1;
1671             tdma_case = 0;
1672         }
1673     } else { /* Non-Shared-Ant */
1674         if (coex_stat->wl_gl_busy)
1675             table_case = 115;
1676         else
1677             table_case = 100;
1678         tdma_case = 100;
1679     }
1680 
1681     rtw_coex_table(rtwdev, false, table_case);
1682     rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1683 }
1684 
1685 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
1686 {
1687     struct rtw_coex *coex = &rtwdev->coex;
1688     struct rtw_coex_stat *coex_stat = &coex->stat;
1689     struct rtw_coex_dm *coex_dm = &coex->dm;
1690     struct rtw_efuse *efuse = &rtwdev->efuse;
1691     struct rtw_chip_info *chip = rtwdev->chip;
1692     struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1693     u8 table_case = 0xff, tdma_case = 0xff;
1694 
1695     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1696     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1697 
1698     if (coex_rfe->ant_switch_with_bt &&
1699         coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1700         if (efuse->share_ant &&
1701             COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
1702             coex_stat->wl_gl_busy) {
1703             table_case = 0;
1704             tdma_case = 0;
1705         } else if (!efuse->share_ant) {
1706             table_case = 100;
1707             tdma_case = 100;
1708         }
1709     }
1710 
1711     if (table_case != 0xff && tdma_case != 0xff) {
1712         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1713         goto exit;
1714     }
1715 
1716     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1717 
1718     if (efuse->share_ant) {
1719         /* Shared-Ant */
1720         if (!coex_stat->wl_gl_busy) {
1721             table_case = 10;
1722             tdma_case = 3;
1723         } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1724             table_case = 11;
1725 
1726             if (coex_stat->lo_pri_rx + coex_stat->lo_pri_tx > 250)
1727                 tdma_case = 17;
1728             else
1729                 tdma_case = 7;
1730         } else {
1731             table_case = 12;
1732             tdma_case = 7;
1733         }
1734     } else {
1735         /* Non-Shared-Ant */
1736         if (!coex_stat->wl_gl_busy) {
1737             table_case = 112;
1738             tdma_case = 104;
1739         } else if ((coex_stat->bt_ble_scan_type & 0x2) &&
1740                coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1741             table_case = 114;
1742             tdma_case = 103;
1743         } else {
1744             table_case = 112;
1745             tdma_case = 103;
1746         }
1747     }
1748 
1749 exit:
1750     rtw_coex_table(rtwdev, false, table_case);
1751     rtw_coex_tdma(rtwdev, false, tdma_case);
1752 }
1753 
1754 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
1755 {
1756     struct rtw_coex *coex = &rtwdev->coex;
1757     struct rtw_coex_stat *coex_stat = &coex->stat;
1758     struct rtw_efuse *efuse = &rtwdev->efuse;
1759     struct rtw_chip_info *chip = rtwdev->chip;
1760     bool wl_hi_pri = false;
1761     u8 table_case, tdma_case;
1762     u32 slot_type = 0;
1763 
1764     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1765     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1766     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1767 
1768     if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
1769         coex_stat->wl_hi_pri_task2)
1770         wl_hi_pri = true;
1771 
1772     if (efuse->share_ant) {
1773         /* Shared-Ant */
1774         if (wl_hi_pri) {
1775             rtw_dbg(rtwdev, RTW_DBG_COEX,
1776                 "[BTCoex], bt inq/page +  wifi hi-pri task\n");
1777             table_case = 15;
1778 
1779             if (coex_stat->bt_profile_num > 0)
1780                 tdma_case = 10;
1781             else if (coex_stat->wl_hi_pri_task1)
1782                 tdma_case = 6;
1783             else if (!coex_stat->bt_page)
1784                 tdma_case = 8;
1785             else
1786                 tdma_case = 9;
1787         } else if (coex_stat->wl_gl_busy) {
1788             rtw_dbg(rtwdev, RTW_DBG_COEX,
1789                 "[BTCoex], bt inq/page + wifi busy\n");
1790             if (coex_stat->bt_profile_num == 0) {
1791                 table_case = 12;
1792                 tdma_case = 18;
1793             } else if (coex_stat->bt_profile_num == 1 &&
1794                    !coex_stat->bt_a2dp_exist) {
1795                 slot_type = TDMA_4SLOT;
1796                 table_case = 12;
1797                 tdma_case = 20;
1798             } else {
1799                 slot_type = TDMA_4SLOT;
1800                 table_case = 12;
1801                 tdma_case = 26;
1802             }
1803         } else if (coex_stat->wl_connected) {
1804             rtw_dbg(rtwdev, RTW_DBG_COEX,
1805                 "[BTCoex], bt inq/page + wifi connected\n");
1806             table_case = 9;
1807             tdma_case = 27;
1808         } else {
1809             rtw_dbg(rtwdev, RTW_DBG_COEX,
1810                 "[BTCoex], bt inq/page + wifi not-connected\n");
1811             table_case = 1;
1812             tdma_case = 0;
1813         }
1814     } else {
1815         /* Non_Shared-Ant */
1816         if (wl_hi_pri) {
1817             rtw_dbg(rtwdev, RTW_DBG_COEX,
1818                 "[BTCoex], bt inq/page +  wifi hi-pri task\n");
1819             table_case = 114;
1820 
1821             if (coex_stat->bt_profile_num > 0)
1822                 tdma_case = 110;
1823             else if (coex_stat->wl_hi_pri_task1)
1824                 tdma_case = 106;
1825             else if (!coex_stat->bt_page)
1826                 tdma_case = 108;
1827             else
1828                 tdma_case = 109;
1829         }  else if (coex_stat->wl_gl_busy) {
1830             rtw_dbg(rtwdev, RTW_DBG_COEX,
1831                 "[BTCoex], bt inq/page + wifi busy\n");
1832             table_case = 114;
1833             tdma_case = 121;
1834         } else if (coex_stat->wl_connected) {
1835             rtw_dbg(rtwdev, RTW_DBG_COEX,
1836                 "[BTCoex], bt inq/page +  wifi connected\n");
1837             table_case = 101;
1838             tdma_case = 100;
1839         } else {
1840             rtw_dbg(rtwdev, RTW_DBG_COEX,
1841                 "[BTCoex], bt inq/page +  wifi not-connected\n");
1842             table_case = 101;
1843             tdma_case = 100;
1844         }
1845     }
1846 
1847     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], wifi hi(%d), bt page(%d)\n",
1848         wl_hi_pri, coex_stat->bt_page);
1849 
1850     rtw_coex_table(rtwdev, false, table_case);
1851     rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1852 }
1853 
1854 static void rtw_coex_action_bt_game_hid(struct rtw_dev *rtwdev)
1855 {
1856     struct rtw_coex *coex = &rtwdev->coex;
1857     struct rtw_coex_stat *coex_stat = &coex->stat;
1858     struct rtw_efuse *efuse = &rtwdev->efuse;
1859     struct rtw_coex_dm *coex_dm = &coex->dm;
1860     struct rtw_chip_info *chip = rtwdev->chip;
1861     u8 table_case, tdma_case;
1862 
1863     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1864     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1865 
1866     if (efuse->share_ant) {
1867         coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;
1868         if (coex_stat->bt_whck_test)
1869             table_case = 2;
1870         else if (coex_stat->wl_linkscan_proc || coex_stat->bt_hid_exist)
1871             table_case = 33;
1872         else if (coex_stat->bt_setup_link || coex_stat->bt_inq_page)
1873             table_case = 0;
1874         else if (coex_stat->bt_a2dp_exist)
1875             table_case = 34;
1876         else
1877             table_case = 33;
1878 
1879         tdma_case = 0;
1880     } else {
1881         if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1882             tdma_case = 112;
1883         else
1884             tdma_case = 113;
1885 
1886         table_case = 121;
1887     }
1888 
1889     if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
1890         if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1891             rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]);
1892         else
1893             rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]);
1894     } else {
1895         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1896     }
1897 
1898     rtw_coex_table(rtwdev, false, table_case);
1899     rtw_coex_tdma(rtwdev, false, tdma_case);
1900 }
1901 
1902 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
1903 {
1904     struct rtw_coex *coex = &rtwdev->coex;
1905     struct rtw_coex_stat *coex_stat = &coex->stat;
1906     struct rtw_efuse *efuse = &rtwdev->efuse;
1907     struct rtw_chip_info *chip = rtwdev->chip;
1908     u8 table_case, tdma_case;
1909 
1910     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1911     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1912     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1913 
1914     if (efuse->share_ant) {
1915         /* Shared-Ant */
1916         table_case = 10;
1917         tdma_case = 5;
1918     } else {
1919         /* Non-Shared-Ant */
1920         if (coex_stat->bt_multi_link) {
1921             table_case = 112;
1922             tdma_case = 117;
1923         } else {
1924             table_case = 105;
1925             tdma_case = 100;
1926         }
1927     }
1928 
1929     rtw_coex_table(rtwdev, false, table_case);
1930     rtw_coex_tdma(rtwdev, false, tdma_case);
1931 }
1932 
1933 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
1934 {
1935     struct rtw_coex *coex = &rtwdev->coex;
1936     struct rtw_coex_stat *coex_stat = &coex->stat;
1937     struct rtw_efuse *efuse = &rtwdev->efuse;
1938     struct rtw_chip_info *chip = rtwdev->chip;
1939     u8 table_case, tdma_case;
1940     u32 slot_type = 0;
1941     bool bt_multi_link_remain = false, is_toggle_table = false;
1942 
1943     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
1944     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1945     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1946 
1947     if (efuse->share_ant) {
1948         /* Shared-Ant */
1949         if (coex_stat->bt_ble_exist) {
1950             /* RCU */
1951             if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
1952                 table_case = 26;
1953                 tdma_case = 2;
1954             } else {
1955                 table_case = 27;
1956                 tdma_case = 9;
1957             }
1958         } else {
1959             /* Legacy HID  */
1960             if (coex_stat->bt_profile_num == 1 &&
1961                 (coex_stat->bt_multi_link ||
1962                 (coex_stat->lo_pri_rx +
1963                  coex_stat->lo_pri_tx > 360) ||
1964                  coex_stat->bt_slave ||
1965                  bt_multi_link_remain)) {
1966                 slot_type = TDMA_4SLOT;
1967                 table_case = 12;
1968                 tdma_case = 20;
1969             } else if (coex_stat->bt_a2dp_active) {
1970                 table_case = 9;
1971                 tdma_case = 18;
1972             } else if (coex_stat->bt_418_hid_exist &&
1973                    coex_stat->wl_gl_busy) {
1974                 is_toggle_table = true;
1975                 slot_type = TDMA_4SLOT;
1976                 table_case = 9;
1977                 tdma_case = 24;
1978             } else if (coex_stat->bt_ble_hid_exist &&
1979                    coex_stat->wl_gl_busy) {
1980                 table_case = 32;
1981                 tdma_case = 9;
1982             } else {
1983                 table_case = 9;
1984                 tdma_case = 9;
1985             }
1986         }
1987     } else {
1988         /* Non-Shared-Ant */
1989         if (coex_stat->bt_ble_exist) {
1990             /* BLE */
1991             if (coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] > 5) {
1992                 table_case = 121;
1993                 tdma_case = 102;
1994             } else {
1995                 table_case = 122;
1996                 tdma_case = 109;
1997             }
1998         } else if (coex_stat->bt_a2dp_active) {
1999             table_case = 113;
2000             tdma_case = 118;
2001         } else {
2002             table_case = 113;
2003             tdma_case = 104;
2004         }
2005     }
2006 
2007     rtw_coex_table(rtwdev, false, table_case);
2008     if (is_toggle_table) {
2009         rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
2010         rtw_btc_wltoggle_table_b(rtwdev, false, 1, COEX_WL_SLOT_TOGLLE);
2011     }
2012 
2013     rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2014 }
2015 
2016 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
2017 {
2018     struct rtw_coex *coex = &rtwdev->coex;
2019     struct rtw_coex_stat *coex_stat = &coex->stat;
2020     struct rtw_coex_dm *coex_dm = &coex->dm;
2021     struct rtw_efuse *efuse = &rtwdev->efuse;
2022     struct rtw_chip_info *chip = rtwdev->chip;
2023     u8 table_case, tdma_case;
2024     u32 slot_type = 0;
2025 
2026     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2027 
2028     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2029     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2030 
2031     slot_type = TDMA_4SLOT;
2032 
2033     if (efuse->share_ant) {
2034         /* Shared-Ant */
2035         if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
2036             table_case = 12;
2037         else
2038             table_case = 9;
2039 
2040         if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy)
2041             tdma_case = 14;
2042         else
2043             tdma_case = 13;
2044     } else {
2045         /* Non-Shared-Ant */
2046         table_case = 112;
2047 
2048         if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
2049             tdma_case = 112;
2050         else
2051             tdma_case = 113;
2052     }
2053 
2054     rtw_coex_table(rtwdev, false, table_case);
2055     rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2056 }
2057 
2058 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
2059 {
2060     struct rtw_coex *coex = &rtwdev->coex;
2061     struct rtw_coex_stat *coex_stat = &coex->stat;
2062     struct rtw_efuse *efuse = &rtwdev->efuse;
2063     struct rtw_chip_info *chip = rtwdev->chip;
2064     u8 table_case, tdma_case;
2065     bool ap_enable = false;
2066 
2067     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2068 
2069     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2070     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2071 
2072     if (efuse->share_ant) { /* Shared-Ant */
2073         if (ap_enable) {
2074             table_case = 2;
2075             tdma_case = 0;
2076         } else if (coex_stat->wl_gl_busy) {
2077             table_case = 28;
2078             tdma_case = 20;
2079         } else {
2080             table_case = 28;
2081             tdma_case = 26;
2082         }
2083     } else { /* Non-Shared-Ant */
2084         if (ap_enable) {
2085             table_case = 100;
2086             tdma_case = 100;
2087         } else {
2088             table_case = 119;
2089             tdma_case = 120;
2090         }
2091     }
2092 
2093     rtw_coex_table(rtwdev, false, table_case);
2094     rtw_coex_tdma(rtwdev, false, tdma_case);
2095 }
2096 
2097 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
2098 {
2099     struct rtw_coex *coex = &rtwdev->coex;
2100     struct rtw_coex_stat *coex_stat = &coex->stat;
2101     struct rtw_efuse *efuse = &rtwdev->efuse;
2102     struct rtw_chip_info *chip = rtwdev->chip;
2103     u8 table_case, tdma_case;
2104 
2105     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2106     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2107     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2108 
2109     if (efuse->share_ant) {
2110         /* Shared-Ant */
2111         if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
2112             table_case = 14;
2113         else
2114             table_case = 10;
2115 
2116         if (coex_stat->wl_gl_busy)
2117             tdma_case = 17;
2118         else
2119             tdma_case = 20;
2120     } else {
2121         /* Non-Shared-Ant */
2122         table_case = 112;
2123 
2124         if (coex_stat->wl_gl_busy)
2125             tdma_case = 117;
2126         else
2127             tdma_case = 119;
2128     }
2129 
2130     rtw_coex_table(rtwdev, false, table_case);
2131     rtw_coex_tdma(rtwdev, false, tdma_case);
2132 }
2133 
2134 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
2135 {
2136     struct rtw_coex *coex = &rtwdev->coex;
2137     struct rtw_coex_stat *coex_stat = &coex->stat;
2138     struct rtw_coex_dm *coex_dm = &coex->dm;
2139     struct rtw_efuse *efuse = &rtwdev->efuse;
2140     struct rtw_chip_info *chip = rtwdev->chip;
2141     u8 table_case, tdma_case, interval = 0;
2142     u32 slot_type = 0;
2143     bool is_toggle_table = false;
2144 
2145     slot_type = TDMA_4SLOT;
2146 
2147     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2148     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2149     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2150 
2151     if (efuse->share_ant) {
2152         /* Shared-Ant */
2153         if (coex_stat->bt_ble_exist) {
2154             table_case = 26; /* for RCU */
2155         } else if (coex_stat->bt_418_hid_exist) {
2156             table_case = 9;
2157             interval = 1;
2158         } else {
2159             table_case = 9;
2160         }
2161 
2162         if (coex_stat->wl_connecting || !coex_stat->wl_gl_busy) {
2163             tdma_case = 14;
2164         } else if (coex_stat->bt_418_hid_exist) {
2165             is_toggle_table = true;
2166             tdma_case = 23;
2167         } else {
2168             tdma_case = 13;
2169         }
2170     } else {
2171         /* Non-Shared-Ant */
2172         if (coex_stat->bt_ble_exist)
2173             table_case = 121;
2174         else
2175             table_case = 113;
2176 
2177         if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
2178             tdma_case = 112;
2179         else
2180             tdma_case = 113;
2181     }
2182 
2183     rtw_coex_table(rtwdev, false, table_case);
2184     if (is_toggle_table) {
2185         rtw_btc_wltoggle_table_a(rtwdev, true, table_case);
2186         rtw_btc_wltoggle_table_b(rtwdev, false, interval, COEX_WL_SLOT_TOGLLE);
2187     }
2188     rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2189 }
2190 
2191 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
2192 {
2193     struct rtw_coex *coex = &rtwdev->coex;
2194     struct rtw_coex_stat *coex_stat = &coex->stat;
2195     struct rtw_efuse *efuse = &rtwdev->efuse;
2196     struct rtw_chip_info *chip = rtwdev->chip;
2197     u8 table_case, tdma_case;
2198     bool wl_cpt_test = false, bt_cpt_test = false;
2199 
2200     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2201 
2202     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2203     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2204     if (efuse->share_ant) {
2205         /* Shared-Ant */
2206         if (wl_cpt_test) {
2207             if (coex_stat->wl_gl_busy) {
2208                 table_case = 20;
2209                 tdma_case = 17;
2210             } else {
2211                 table_case = 10;
2212                 tdma_case = 15;
2213             }
2214         } else if (bt_cpt_test) {
2215             table_case = 26;
2216             tdma_case = 26;
2217         } else {
2218             if (coex_stat->wl_gl_busy &&
2219                 coex_stat->wl_noisy_level == 0)
2220                 table_case = 14;
2221             else
2222                 table_case = 10;
2223 
2224             if (coex_stat->wl_gl_busy)
2225                 tdma_case = 15;
2226             else
2227                 tdma_case = 20;
2228         }
2229     } else {
2230         /* Non-Shared-Ant */
2231         table_case = 112;
2232 
2233         if (coex_stat->wl_gl_busy)
2234             tdma_case = 115;
2235         else
2236             tdma_case = 120;
2237     }
2238 
2239     if (wl_cpt_test)
2240         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[1]);
2241     else
2242         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2243 
2244     rtw_coex_table(rtwdev, false, table_case);
2245     rtw_coex_tdma(rtwdev, false, tdma_case);
2246 }
2247 
2248 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
2249 {
2250     struct rtw_coex *coex = &rtwdev->coex;
2251     struct rtw_coex_stat *coex_stat = &coex->stat;
2252     struct rtw_efuse *efuse = &rtwdev->efuse;
2253     struct rtw_chip_info *chip = rtwdev->chip;
2254     u8 table_case, tdma_case;
2255 
2256     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2257 
2258     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2259     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2260 
2261     if (efuse->share_ant) {
2262         /* Shared-Ant */
2263         table_case = 9;
2264 
2265         if (coex_stat->wl_gl_busy)
2266             tdma_case = 18;
2267         else
2268             tdma_case = 19;
2269     } else {
2270         /* Non-Shared-Ant */
2271         table_case = 113;
2272 
2273         if (coex_stat->wl_gl_busy)
2274             tdma_case = 117;
2275         else
2276             tdma_case = 119;
2277     }
2278 
2279     rtw_coex_table(rtwdev, false, table_case);
2280     rtw_coex_tdma(rtwdev, false, tdma_case);
2281 }
2282 
2283 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
2284 {
2285     struct rtw_coex *coex = &rtwdev->coex;
2286     struct rtw_coex_stat *coex_stat = &coex->stat;
2287     struct rtw_efuse *efuse = &rtwdev->efuse;
2288     struct rtw_chip_info *chip = rtwdev->chip;
2289     u8 table_case, tdma_case;
2290 
2291     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2292     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2293     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2294 
2295     if (efuse->share_ant) {
2296         /* Shared-Ant */
2297         table_case = 10;
2298 
2299         if (coex_stat->wl_gl_busy)
2300             tdma_case = 15;
2301         else
2302             tdma_case = 20;
2303     } else {
2304         /* Non-Shared-Ant */
2305         table_case = 113;
2306 
2307         if (coex_stat->wl_gl_busy)
2308             tdma_case = 115;
2309         else
2310             tdma_case = 120;
2311     }
2312 
2313     rtw_coex_table(rtwdev, false, table_case);
2314     rtw_coex_tdma(rtwdev, false, tdma_case);
2315 }
2316 
2317 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
2318 {
2319     struct rtw_coex *coex = &rtwdev->coex;
2320     struct rtw_efuse *efuse = &rtwdev->efuse;
2321     struct rtw_chip_info *chip = rtwdev->chip;
2322     struct rtw_coex_stat *coex_stat = &coex->stat;
2323     u8 table_case, tdma_case;
2324 
2325     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2326 
2327     rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2328     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2329 
2330     rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
2331 
2332     if (coex_stat->bt_game_hid_exist && coex_stat->wl_linkscan_proc)
2333         coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;
2334 
2335     if (efuse->share_ant) {
2336         /* Shared-Ant */
2337         table_case = 0;
2338         tdma_case = 0;
2339     } else {
2340         /* Non-Shared-Ant */
2341         table_case = 100;
2342         tdma_case = 100;
2343     }
2344 
2345     rtw_coex_table(rtwdev, false, table_case);
2346     rtw_coex_tdma(rtwdev, false, tdma_case);
2347 }
2348 
2349 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
2350 {
2351     struct rtw_efuse *efuse = &rtwdev->efuse;
2352     struct rtw_chip_info *chip = rtwdev->chip;
2353     u8 table_case, tdma_case;
2354 
2355     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2356     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2357     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2358 
2359     if (efuse->share_ant) {
2360         /* Shared-Ant */
2361         table_case = 2;
2362         tdma_case = 0;
2363     } else {
2364         /* Non-Shared-Ant */
2365         table_case = 100;
2366         tdma_case = 100;
2367     }
2368 
2369     rtw_coex_table(rtwdev, false, table_case);
2370     rtw_coex_tdma(rtwdev, false, tdma_case);
2371 }
2372 
2373 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
2374 {
2375     struct rtw_coex *coex = &rtwdev->coex;
2376     struct rtw_efuse *efuse = &rtwdev->efuse;
2377     struct rtw_chip_info *chip = rtwdev->chip;
2378     struct rtw_coex_stat *coex_stat = &coex->stat;
2379     u8 table_case, tdma_case;
2380 
2381     if (coex->under_5g)
2382         return;
2383 
2384     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2385 
2386     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2387 
2388     if (efuse->share_ant) {
2389         /* Shared-Ant */
2390         table_case = 28;
2391         tdma_case = 0;
2392     } else {
2393         /* Non-Shared-Ant */
2394         table_case = 100;
2395         tdma_case = 100;
2396     }
2397 
2398     if (coex_stat->bt_game_hid_exist) {
2399         coex_stat->wl_coex_mode = COEX_WLINK_2GFREE;
2400         if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
2401             rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[6]);
2402         else
2403             rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[5]);
2404     } else {
2405         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2406     }
2407 
2408     rtw_coex_table(rtwdev, false, table_case);
2409     rtw_coex_tdma(rtwdev, false, tdma_case);
2410 }
2411 
2412 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
2413 {
2414     struct rtw_coex *coex = &rtwdev->coex;
2415     struct rtw_coex_stat *coex_stat = &coex->stat;
2416     struct rtw_efuse *efuse = &rtwdev->efuse;
2417     struct rtw_chip_info *chip = rtwdev->chip;
2418     u8 table_case, tdma_case;
2419     u32 slot_type = 0;
2420 
2421     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2422     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2423     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2424 
2425     if (efuse->share_ant) { /* Shared-Ant */
2426         if (coex_stat->bt_a2dp_exist) {
2427             slot_type = TDMA_4SLOT;
2428             tdma_case = 11;
2429             if (coex_stat->wl_gl_busy)
2430                 table_case = 26;
2431             else
2432                 table_case = 9;
2433         } else {
2434             table_case = 9;
2435             tdma_case = 7;
2436         }
2437     } else { /* Non-Shared-Ant */
2438         if (coex_stat->bt_a2dp_exist) {
2439             slot_type = TDMA_4SLOT;
2440             table_case = 112;
2441             tdma_case = 111;
2442         } else {
2443             table_case = 112;
2444             tdma_case = 107;
2445         }
2446     }
2447 
2448     rtw_coex_table(rtwdev, false, table_case);
2449     rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
2450 }
2451 
2452 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
2453 {
2454     struct rtw_efuse *efuse = &rtwdev->efuse;
2455     struct rtw_chip_info *chip = rtwdev->chip;
2456     u8 table_case, tdma_case;
2457 
2458     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2459     rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
2460     rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
2461 
2462     if (efuse->share_ant) {
2463         /* Shared-Ant */
2464         table_case = 1;
2465         tdma_case = 0;
2466     } else {
2467         /* Non-Shared-Ant */
2468         table_case = 100;
2469         tdma_case = 100;
2470     }
2471 
2472     rtw_coex_table(rtwdev, false, table_case);
2473     rtw_coex_tdma(rtwdev, false, tdma_case);
2474 }
2475 
2476 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
2477 {
2478     struct rtw_coex *coex = &rtwdev->coex;
2479     struct rtw_coex_stat *coex_stat = &coex->stat;
2480     u8 algorithm;
2481 
2482     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2483 
2484     algorithm = rtw_coex_algorithm(rtwdev);
2485 
2486     switch (algorithm) {
2487     case COEX_ALGO_HFP:
2488         rtw_coex_action_bt_hfp(rtwdev);
2489         break;
2490     case COEX_ALGO_HID:
2491         if (rtw_coex_freerun_check(rtwdev))
2492             rtw_coex_action_freerun(rtwdev);
2493         else
2494             rtw_coex_action_bt_hid(rtwdev);
2495         break;
2496     case COEX_ALGO_A2DP:
2497         if (rtw_coex_freerun_check(rtwdev))
2498             rtw_coex_action_freerun(rtwdev);
2499         else if (coex_stat->bt_a2dp_sink)
2500             rtw_coex_action_bt_a2dpsink(rtwdev);
2501         else
2502             rtw_coex_action_bt_a2dp(rtwdev);
2503         break;
2504     case COEX_ALGO_PAN:
2505         rtw_coex_action_bt_pan(rtwdev);
2506         break;
2507     case COEX_ALGO_A2DP_HID:
2508         if (rtw_coex_freerun_check(rtwdev))
2509             rtw_coex_action_freerun(rtwdev);
2510         else
2511             rtw_coex_action_bt_a2dp_hid(rtwdev);
2512         break;
2513     case COEX_ALGO_A2DP_PAN:
2514         rtw_coex_action_bt_a2dp_pan(rtwdev);
2515         break;
2516     case COEX_ALGO_PAN_HID:
2517         rtw_coex_action_bt_pan_hid(rtwdev);
2518         break;
2519     case COEX_ALGO_A2DP_PAN_HID:
2520         rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
2521         break;
2522     default:
2523     case COEX_ALGO_NOPROFILE:
2524         rtw_coex_action_bt_idle(rtwdev);
2525         break;
2526     }
2527 }
2528 
2529 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
2530 {
2531     struct rtw_coex *coex = &rtwdev->coex;
2532     struct rtw_chip_info *chip = rtwdev->chip;
2533     struct rtw_coex_dm *coex_dm = &coex->dm;
2534     struct rtw_coex_stat *coex_stat = &coex->stat;
2535     bool rf4ce_en = false;
2536 
2537     lockdep_assert_held(&rtwdev->mutex);
2538 
2539     if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
2540         return;
2541 
2542     coex_dm->reason = reason;
2543 
2544     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): reason = %d\n", __func__,
2545         reason);
2546 
2547     /* update wifi_link_info_ext variable */
2548     rtw_coex_update_wl_link_info(rtwdev, reason);
2549 
2550     rtw_coex_monitor_bt_enable(rtwdev);
2551 
2552     if (coex->manual_control) {
2553         rtw_dbg(rtwdev, RTW_DBG_COEX,
2554             "[BTCoex], return for Manual CTRL!!\n");
2555         return;
2556     }
2557 
2558     if (coex->stop_dm) {
2559         rtw_dbg(rtwdev, RTW_DBG_COEX,
2560             "[BTCoex], return for Stop Coex DM!!\n");
2561         return;
2562     }
2563 
2564     if (coex_stat->wl_under_ips) {
2565         rtw_dbg(rtwdev, RTW_DBG_COEX,
2566             "[BTCoex], return for wifi is under IPS!!\n");
2567         return;
2568     }
2569 
2570     if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&
2571         !coex_stat->bt_setup_link) {
2572         rtw_dbg(rtwdev, RTW_DBG_COEX,
2573             "[BTCoex], return for coex_freeze!!\n");
2574         return;
2575     }
2576 
2577     coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
2578     coex->freerun = false;
2579 
2580     /* Pure-5G Coex Process */
2581     if (coex->under_5g) {
2582         coex_stat->wl_coex_mode = COEX_WLINK_5G;
2583         rtw_coex_action_wl_under5g(rtwdev);
2584         goto exit;
2585     }
2586 
2587     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WiFi is single-port 2G!!\n");
2588     coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
2589 
2590     if (coex_stat->bt_disabled) {
2591         if (coex_stat->wl_connected && rf4ce_en)
2592             rtw_coex_action_rf4ce(rtwdev);
2593         else if (!coex_stat->wl_connected)
2594             rtw_coex_action_wl_not_connected(rtwdev);
2595         else
2596             rtw_coex_action_wl_only(rtwdev);
2597         goto exit;
2598     }
2599 
2600     if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
2601         rtw_coex_action_wl_native_lps(rtwdev);
2602         goto exit;
2603     }
2604 
2605     if (coex_stat->bt_game_hid_exist && coex_stat->wl_connected) {
2606         rtw_coex_action_bt_game_hid(rtwdev);
2607         goto exit;
2608     }
2609 
2610     if (coex_stat->bt_whck_test) {
2611         rtw_coex_action_bt_whql_test(rtwdev);
2612         goto exit;
2613     }
2614 
2615     if (coex_stat->bt_setup_link) {
2616         rtw_coex_action_bt_relink(rtwdev);
2617         goto exit;
2618     }
2619 
2620     if (coex_stat->bt_inq_page) {
2621         rtw_coex_action_bt_inquiry(rtwdev);
2622         goto exit;
2623     }
2624 
2625     if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
2626          coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
2627          coex_stat->wl_connected) {
2628         rtw_coex_action_bt_idle(rtwdev);
2629         goto exit;
2630     }
2631 
2632     if (coex_stat->wl_linkscan_proc && !coex->freerun) {
2633         rtw_coex_action_wl_linkscan(rtwdev);
2634         goto exit;
2635     }
2636 
2637     if (coex_stat->wl_connected) {
2638         rtw_coex_action_wl_connected(rtwdev);
2639         goto exit;
2640     } else {
2641         rtw_coex_action_wl_not_connected(rtwdev);
2642         goto exit;
2643     }
2644 
2645 exit:
2646 
2647     if (chip->wl_mimo_ps_support) {
2648         if (coex_stat->wl_coex_mode == COEX_WLINK_2GFREE) {
2649             if (coex_dm->reason == COEX_RSN_2GMEDIA)
2650                 rtw_coex_mimo_ps(rtwdev, true, true);
2651             else
2652                 rtw_coex_mimo_ps(rtwdev, false, true);
2653         } else {
2654             rtw_coex_mimo_ps(rtwdev, false, false);
2655         }
2656     }
2657 
2658     rtw_coex_gnt_workaround(rtwdev, false, coex_stat->wl_coex_mode);
2659     rtw_coex_limited_wl(rtwdev);
2660 }
2661 
2662 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
2663 {
2664     struct rtw_coex *coex = &rtwdev->coex;
2665     struct rtw_coex_stat *coex_stat = &coex->stat;
2666     struct rtw_coex_dm *coex_dm = &coex->dm;
2667     u8 i;
2668 
2669     memset(coex_dm, 0, sizeof(*coex_dm));
2670     memset(coex_stat, 0, sizeof(*coex_stat));
2671 
2672     for (i = 0; i < COEX_CNT_WL_MAX; i++)
2673         coex_stat->cnt_wl[i] = 0;
2674 
2675     for (i = 0; i < COEX_CNT_BT_MAX; i++)
2676         coex_stat->cnt_bt[i] = 0;
2677 
2678     for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
2679         coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
2680 
2681     for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
2682         coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
2683 
2684     coex_stat->wl_coex_mode = COEX_WLINK_MAX;
2685     coex_stat->wl_rx_rate = DESC_RATE5_5M;
2686     coex_stat->wl_rts_rx_rate = DESC_RATE5_5M;
2687 }
2688 
2689 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2690 {
2691     struct rtw_coex *coex = &rtwdev->coex;
2692     struct rtw_coex_stat *coex_stat = &coex->stat;
2693 
2694     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2695 
2696     rtw_coex_init_coex_var(rtwdev);
2697 
2698     coex_stat->kt_ver = u8_get_bits(rtw_read8(rtwdev, 0xf1), GENMASK(7, 4));
2699 
2700     rtw_coex_monitor_bt_enable(rtwdev);
2701     rtw_coex_wl_slot_extend(rtwdev, coex_stat->wl_slot_extend);
2702 
2703     rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
2704 
2705     rtw_coex_set_rfe_type(rtwdev);
2706     rtw_coex_set_init(rtwdev);
2707 
2708     /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
2709     rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
2710 
2711     /* set Tx beacon = Hi-Pri */
2712     rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
2713 
2714     /* set Tx beacon queue = Hi-Pri */
2715     rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
2716 
2717     /* antenna config */
2718     if (coex->wl_rf_off) {
2719         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2720         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2721         coex->stop_dm = true;
2722 
2723         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): RF Off\n",
2724             __func__);
2725     } else if (wifi_only) {
2726         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
2727         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
2728                     true);
2729         coex->stop_dm = true;
2730     } else {
2731         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
2732         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF,
2733                     true);
2734         coex->stop_dm = false;
2735         coex->freeze = true;
2736     }
2737 
2738     /* PTA parameter */
2739     rtw_coex_table(rtwdev, true, 1);
2740     rtw_coex_tdma(rtwdev, true, 0);
2741     rtw_coex_query_bt_info(rtwdev);
2742 }
2743 
2744 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
2745 {
2746     struct rtw_coex *coex = &rtwdev->coex;
2747     u8 table_case = 1;
2748 
2749     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
2750 
2751     coex->stop_dm = true;
2752     coex->wl_rf_off = false;
2753 
2754     /* enable BB, we can write 0x948 */
2755     rtw_write8_set(rtwdev, REG_SYS_FUNC_EN,
2756                BIT_FEN_BB_GLB_RST | BIT_FEN_BB_RSTB);
2757 
2758     rtw_coex_monitor_bt_enable(rtwdev);
2759     rtw_coex_set_rfe_type(rtwdev);
2760 
2761     /* set antenna path to BT */
2762     rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
2763 
2764     rtw_coex_table(rtwdev, true, table_case);
2765     /* red x issue */
2766     rtw_write8(rtwdev, 0xff1a, 0x0);
2767     rtw_coex_set_gnt_debug(rtwdev);
2768 }
2769 
2770 void rtw_coex_power_off_setting(struct rtw_dev *rtwdev)
2771 {
2772     rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN);
2773 }
2774 
2775 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2776 {
2777     __rtw_coex_init_hw_config(rtwdev, wifi_only);
2778 }
2779 
2780 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
2781 {
2782     struct rtw_coex *coex = &rtwdev->coex;
2783     struct rtw_coex_stat *coex_stat = &coex->stat;
2784 
2785     if (coex->manual_control || coex->stop_dm)
2786         return;
2787 
2788     if (type == COEX_IPS_ENTER) {
2789         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS ENTER notify\n");
2790 
2791         coex_stat->wl_under_ips = true;
2792 
2793         /* for lps off */
2794         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2795 
2796         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2797         rtw_coex_action_coex_all_off(rtwdev);
2798     } else if (type == COEX_IPS_LEAVE) {
2799         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], IPS LEAVE notify\n");
2800 
2801         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2802         /* run init hw config (exclude wifi only) */
2803         __rtw_coex_init_hw_config(rtwdev, false);
2804 
2805         coex_stat->wl_under_ips = false;
2806     }
2807 }
2808 
2809 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
2810 {
2811     struct rtw_coex *coex = &rtwdev->coex;
2812     struct rtw_coex_stat *coex_stat = &coex->stat;
2813 
2814     if (coex->manual_control || coex->stop_dm)
2815         return;
2816 
2817     if (type == COEX_LPS_ENABLE) {
2818         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS ENABLE notify\n");
2819 
2820         coex_stat->wl_under_lps = true;
2821 
2822         if (coex_stat->wl_force_lps_ctrl) {
2823             /* for ps-tdma */
2824             rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2825         } else {
2826             /* for native ps */
2827             rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2828             rtw_coex_write_scbd(rtwdev, COEX_SCBD_WLBUSY, false);
2829 
2830             rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2831         }
2832     } else if (type == COEX_LPS_DISABLE) {
2833         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], LPS DISABLE notify\n");
2834 
2835         coex_stat->wl_under_lps = false;
2836 
2837         /* for lps off */
2838         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2839 
2840         if (!coex_stat->wl_force_lps_ctrl)
2841             rtw_coex_query_bt_info(rtwdev);
2842 
2843         rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2844     }
2845 }
2846 
2847 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
2848 {
2849     struct rtw_coex *coex = &rtwdev->coex;
2850     struct rtw_coex_stat *coex_stat = &coex->stat;
2851 
2852     if (coex->manual_control || coex->stop_dm)
2853         return;
2854 
2855     coex->freeze = false;
2856     rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2857 
2858     if (type == COEX_SCAN_START_5G) {
2859         rtw_dbg(rtwdev, RTW_DBG_COEX,
2860             "[BTCoex], SCAN START notify (5G)\n");
2861 
2862         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2863         rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
2864     } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
2865         rtw_dbg(rtwdev, RTW_DBG_COEX,
2866             "[BTCoex], SCAN START notify (2G)\n");
2867 
2868         coex_stat->wl_hi_pri_task2 = true;
2869 
2870         /* Force antenna setup for no scan result issue */
2871         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2872         rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
2873     } else {
2874         coex_stat->cnt_wl[COEX_CNT_WL_SCANAP] = 30; /* To do */
2875 
2876         rtw_dbg(rtwdev, RTW_DBG_COEX,
2877             "[BTCoex], SCAN FINISH notify (Scan-AP = %d)\n",
2878             coex_stat->cnt_wl[COEX_CNT_WL_SCANAP]);
2879 
2880         coex_stat->wl_hi_pri_task2 = false;
2881         rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
2882     }
2883 }
2884 
2885 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
2886 {
2887     struct rtw_coex *coex = &rtwdev->coex;
2888 
2889     if (coex->manual_control || coex->stop_dm)
2890         return;
2891 
2892     if (type == COEX_SWITCH_TO_5G) {
2893         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_5G\n",
2894             __func__);
2895     } else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) {
2896         rtw_dbg(rtwdev, RTW_DBG_COEX,
2897             "[BTCoex], %s(): TO_24G_NOFORSCAN\n", __func__);
2898     } else {
2899         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): TO_2G\n",
2900             __func__);
2901     }
2902 
2903     if (type == COEX_SWITCH_TO_5G)
2904         rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
2905     else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
2906         rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
2907     else
2908         rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
2909 }
2910 
2911 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
2912 {
2913     struct rtw_coex *coex = &rtwdev->coex;
2914     struct rtw_coex_stat *coex_stat = &coex->stat;
2915 
2916     if (coex->manual_control || coex->stop_dm)
2917         return;
2918 
2919     rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2920 
2921     if (type == COEX_ASSOCIATE_5G_START) {
2922         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G start\n",
2923             __func__);
2924 
2925         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2926         rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
2927     } else if (type == COEX_ASSOCIATE_5G_FINISH) {
2928         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G finish\n",
2929             __func__);
2930 
2931         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2932         rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
2933     } else if (type == COEX_ASSOCIATE_START) {
2934         coex_stat->wl_hi_pri_task1 = true;
2935         coex_stat->wl_connecting = true;
2936         coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
2937         coex_stat->wl_connecting = true;
2938         ieee80211_queue_delayed_work(rtwdev->hw,
2939                          &coex->wl_connecting_work, 2 * HZ);
2940 
2941         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G start\n",
2942             __func__);
2943         /* Force antenna setup for no scan result issue */
2944         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2945 
2946         rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
2947 
2948         /* To keep TDMA case during connect process,
2949          * to avoid changed by Btinfo and runcoexmechanism
2950          */
2951         coex->freeze = true;
2952         ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
2953                          5 * HZ);
2954     } else {
2955         coex_stat->wl_hi_pri_task1 = false;
2956         coex->freeze = false;
2957         coex_stat->wl_connecting = false;
2958 
2959         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G finish\n",
2960             __func__);
2961         rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
2962     }
2963 }
2964 
2965 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
2966 {
2967     struct rtw_coex *coex = &rtwdev->coex;
2968     struct rtw_coex_stat *coex_stat = &coex->stat;
2969 
2970     if (coex->manual_control || coex->stop_dm)
2971         return;
2972 
2973     if (type == COEX_MEDIA_CONNECT_5G) {
2974         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 5G\n", __func__);
2975 
2976         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2977 
2978         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2979         rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
2980     } else if (type == COEX_MEDIA_CONNECT) {
2981         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): 2G\n", __func__);
2982 
2983         coex_stat->wl_connecting = false;
2984 
2985         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2986 
2987         /* Force antenna setup for no scan result issue */
2988         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2989 
2990         /* Set CCK Rx high Pri */
2991         rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
2992         rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
2993     } else {
2994         rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s(): disconnect!!\n",
2995             __func__);
2996         rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
2997         rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
2998     }
2999 
3000     rtw_coex_update_wl_ch_info(rtwdev, type);
3001 }
3002 
3003 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
3004 {
3005     struct rtw_coex *coex = &rtwdev->coex;
3006     struct rtw_coex_stat *coex_stat = &coex->stat;
3007     struct rtw_chip_info *chip = rtwdev->chip;
3008     struct rtw_coex_dm *coex_dm = &coex->dm;
3009     u32 bt_relink_time;
3010     u8 i, rsp_source = 0, type;
3011     bool inq_page = false;
3012 
3013     rsp_source = buf[0] & 0xf;
3014     if (rsp_source >= COEX_BTINFO_SRC_MAX)
3015         return;
3016     coex_stat->cnt_bt_info_c2h[rsp_source]++;
3017 
3018     if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
3019         coex_stat->bt_iqk_state = buf[1];
3020         if (coex_stat->bt_iqk_state == 0)
3021             coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
3022         else if (coex_stat->bt_iqk_state == 2)
3023             coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
3024 
3025         rtw_dbg(rtwdev, RTW_DBG_COEX,
3026             "[BTCoex], BT IQK by bt_info, data0 = 0x%02x\n",
3027             buf[1]);
3028 
3029         return;
3030     }
3031 
3032     if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
3033         rtw_dbg(rtwdev, RTW_DBG_COEX,
3034             "[BTCoex], BT Scoreboard change notify by WL FW c2h, 0xaa = 0x%02x, 0xab = 0x%02x\n",
3035             buf[1], buf[2]);
3036 
3037         rtw_coex_monitor_bt_enable(rtwdev);
3038         if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
3039             coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
3040             rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
3041         }
3042         return;
3043     }
3044 
3045     if (rsp_source == COEX_BTINFO_SRC_H2C60) {
3046         rtw_dbg(rtwdev, RTW_DBG_COEX,
3047             "[BTCoex], H2C 0x60 content replied by WL FW: H2C_0x60 = [%02x %02x %02x %02x %02x]\n",
3048             buf[1], buf[2], buf[3], buf[4], buf[5]);
3049 
3050         for (i = 1; i <= COEX_WL_TDMA_PARA_LENGTH; i++)
3051             coex_dm->fw_tdma_para[i - 1] = buf[i];
3052         return;
3053     }
3054 
3055     if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
3056         rtw_dbg(rtwdev, RTW_DBG_COEX,
3057             "[BTCoex], bt_info reply by WL FW\n");
3058 
3059         rtw_coex_update_bt_link_info(rtwdev);
3060         return;
3061     }
3062 
3063     if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
3064         rsp_source == COEX_BTINFO_SRC_BT_ACT) {
3065         if (coex_stat->bt_disabled) {
3066             coex_stat->bt_disabled = false;
3067             coex_stat->bt_reenable = true;
3068             ieee80211_queue_delayed_work(rtwdev->hw,
3069                              &coex->bt_reenable_work,
3070                              15 * HZ);
3071             rtw_dbg(rtwdev, RTW_DBG_COEX,
3072                 "[BTCoex], BT enable detected by bt_info\n");
3073         }
3074     }
3075 
3076     if (length != COEX_BTINFO_LENGTH) {
3077         rtw_dbg(rtwdev, RTW_DBG_COEX,
3078             "[BTCoex], Bt_info length = %d invalid!!\n", length);
3079 
3080         return;
3081     }
3082 
3083     rtw_dbg(rtwdev, RTW_DBG_COEX,
3084         "[BTCoex], Bt_info[%d], len=%d, data=[%02x %02x %02x %02x %02x %02x]\n",
3085         buf[0], length, buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
3086 
3087     for (i = 0; i < COEX_BTINFO_LENGTH; i++)
3088         coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
3089 
3090     /* get the same info from bt, skip it */
3091     if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
3092         coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
3093         coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
3094         coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
3095         coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
3096         coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) {
3097         rtw_dbg(rtwdev, RTW_DBG_COEX,
3098             "[BTCoex], Return because Btinfo duplicate!!\n");
3099         return;
3100     }
3101 
3102     coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
3103     coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
3104     coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
3105     coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
3106     coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
3107     coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
3108 
3109     /* 0xff means BT is under WHCK test */
3110     coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
3111 
3112     inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
3113 
3114     if (inq_page != coex_stat->bt_inq_page) {
3115         cancel_delayed_work_sync(&coex->bt_remain_work);
3116         coex_stat->bt_inq_page = inq_page;
3117 
3118         if (inq_page)
3119             coex_stat->bt_inq_remain = true;
3120         else
3121             ieee80211_queue_delayed_work(rtwdev->hw,
3122                              &coex->bt_remain_work,
3123                              4 * HZ);
3124     }
3125     coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
3126     if (chip->ble_hid_profile_support) {
3127         if (coex_stat->bt_info_lb2 & BIT(5)) {
3128             if (coex_stat->bt_info_hb1 & BIT(0)) {
3129                 /*BLE HID*/
3130                 coex_stat->bt_ble_hid_exist = true;
3131             } else {
3132                 coex_stat->bt_ble_hid_exist = false;
3133             }
3134             coex_stat->bt_ble_exist = false;
3135         } else if (coex_stat->bt_info_hb1 & BIT(0)) {
3136             /*RCU*/
3137             coex_stat->bt_ble_hid_exist = false;
3138             coex_stat->bt_ble_exist = true;
3139         } else {
3140             coex_stat->bt_ble_hid_exist = false;
3141             coex_stat->bt_ble_exist = false;
3142         }
3143     } else {
3144         if (coex_stat->bt_info_hb1 & BIT(0)) {
3145             if (coex_stat->bt_hid_slot == 1 &&
3146                 coex_stat->hi_pri_rx + 100 < coex_stat->hi_pri_tx &&
3147                 coex_stat->hi_pri_rx < 100) {
3148                 coex_stat->bt_ble_hid_exist = true;
3149                 coex_stat->bt_ble_exist = false;
3150             } else {
3151                 coex_stat->bt_ble_hid_exist = false;
3152                 coex_stat->bt_ble_exist = true;
3153             }
3154         } else {
3155             coex_stat->bt_ble_hid_exist = false;
3156             coex_stat->bt_ble_exist = false;
3157         }
3158     }
3159 
3160     coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
3161     if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
3162         coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
3163 
3164     coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
3165     coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
3166     if (coex_stat->bt_inq)
3167         coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
3168 
3169     coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
3170     if (coex_stat->bt_page)
3171         coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
3172 
3173     /* unit: % (value-100 to translate to unit: dBm in coex info) */
3174     if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
3175         coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
3176     } else {
3177         if (coex_stat->bt_info_hb0 <= 127)
3178             coex_stat->bt_rssi = 100;
3179         else if (256 - coex_stat->bt_info_hb0 <= 100)
3180             coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
3181         else
3182             coex_stat->bt_rssi = 0;
3183     }
3184 
3185     if (coex_stat->bt_info_hb1 & BIT(1))
3186         coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
3187 
3188     if (coex_stat->bt_info_hb1 & BIT(2)) {
3189         coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
3190         coex_stat->bt_setup_link = true;
3191         if (coex_stat->bt_reenable)
3192             bt_relink_time = 6 * HZ;
3193         else
3194             bt_relink_time = 1 * HZ;
3195 
3196         ieee80211_queue_delayed_work(rtwdev->hw,
3197                          &coex->bt_relink_work,
3198                          bt_relink_time);
3199 
3200         rtw_dbg(rtwdev, RTW_DBG_COEX,
3201             "[BTCoex], Re-Link start in BT info!!\n");
3202     }
3203 
3204     if (coex_stat->bt_info_hb1 & BIT(3))
3205         coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
3206 
3207     coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
3208     coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
3209     if (coex_stat->bt_info_hb1 & BIT(6))
3210         coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
3211 
3212     coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
3213     /* for multi_link = 0 but bt pkt remain exist */
3214     /* Use PS-TDMA to protect WL RX */
3215     if (!coex_stat->bt_multi_link && coex_stat->bt_multi_link_pre) {
3216         coex_stat->bt_multi_link_remain = true;
3217         ieee80211_queue_delayed_work(rtwdev->hw,
3218                          &coex->bt_multi_link_remain_work,
3219                          3 * HZ);
3220     }
3221     coex_stat->bt_multi_link_pre = coex_stat->bt_multi_link;
3222 
3223     /* resend wifi info to bt, it is reset and lost the info */
3224     if (coex_stat->bt_info_hb1 & BIT(1)) {
3225         rtw_dbg(rtwdev, RTW_DBG_COEX,
3226             "[BTCoex], BT Re-init, send wifi BW & Chnl to BT!!\n");
3227 
3228         if (coex_stat->wl_connected)
3229             type = COEX_MEDIA_CONNECT;
3230         else
3231             type = COEX_MEDIA_DISCONNECT;
3232         rtw_coex_update_wl_ch_info(rtwdev, type);
3233     }
3234 
3235     /* if ignore_wlan_act && not set_up_link */
3236     if ((coex_stat->bt_info_hb1 & BIT(3)) &&
3237         (!(coex_stat->bt_info_hb1 & BIT(2)))) {
3238         rtw_dbg(rtwdev, RTW_DBG_COEX,
3239             "[BTCoex], BT ext info bit3 check, set BT NOT to ignore Wlan active!!\n");
3240         rtw_coex_ignore_wlan_act(rtwdev, false);
3241     }
3242 
3243     coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
3244     if (coex_stat->bt_info_hb2 & BIT(1))
3245         coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
3246 
3247     coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
3248     coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
3249     coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
3250     coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
3251     if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
3252         coex_stat->bt_418_hid_exist = true;
3253     else if (coex_stat->bt_hid_pair_num == 0 || coex_stat->bt_hid_slot == 1)
3254         coex_stat->bt_418_hid_exist = false;
3255 
3256     if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
3257         coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
3258     else
3259         coex_stat->bt_a2dp_bitpool = 0;
3260 
3261     coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
3262 
3263     rtw_coex_update_bt_link_info(rtwdev);
3264     rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
3265 }
3266 
3267 #define COEX_BT_HIDINFO_MTK 0x46
3268 static const u8 coex_bt_hidinfo_ps[] = {0x57, 0x69, 0x72};
3269 static const u8 coex_bt_hidinfo_xb[] = {0x58, 0x62, 0x6f};
3270 
3271 void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
3272 {
3273     struct rtw_coex *coex = &rtwdev->coex;
3274     struct rtw_chip_info *chip = rtwdev->chip;
3275     struct rtw_coex_stat *coex_stat = &coex->stat;
3276     struct rtw_coex_hid *hidinfo;
3277     struct rtw_coex_hid_info_a *hida;
3278     struct rtw_coex_hid_handle_list *hl, *bhl;
3279     u8 sub_id = buf[2], gamehid_cnt = 0, handle, i;
3280     bool cur_game_hid_exist, complete;
3281 
3282     if (!chip->wl_mimo_ps_support &&
3283         (sub_id == COEX_BT_HIDINFO_LIST || sub_id == COEX_BT_HIDINFO_A))
3284         return;
3285 
3286     rtw_dbg(rtwdev, RTW_DBG_COEX,
3287         "[BTCoex], HID info notify, sub_id = 0x%x\n", sub_id);
3288 
3289     switch (sub_id) {
3290     case COEX_BT_HIDINFO_LIST:
3291         hl = &coex_stat->hid_handle_list;
3292         bhl = (struct rtw_coex_hid_handle_list *)buf;
3293         if (!memcmp(hl, bhl, sizeof(*hl)))
3294             return;
3295         coex_stat->hid_handle_list = *bhl;
3296         memset(&coex_stat->hid_info, 0, sizeof(coex_stat->hid_info));
3297         for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
3298             hidinfo = &coex_stat->hid_info[i];
3299             if (hl->handle[i] != COEX_BT_HIDINFO_NOTCON &&
3300                 hl->handle[i] != 0)
3301                 hidinfo->hid_handle = hl->handle[i];
3302         }
3303         break;
3304     case COEX_BT_HIDINFO_A:
3305         hida = (struct rtw_coex_hid_info_a *)buf;
3306         handle = hida->handle;
3307         for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
3308             hidinfo = &coex_stat->hid_info[i];
3309             if (hidinfo->hid_handle == handle) {
3310                 hidinfo->hid_vendor = hida->vendor;
3311                 memcpy(hidinfo->hid_name, hida->name,
3312                        sizeof(hidinfo->hid_name));
3313                 hidinfo->hid_info_completed = true;
3314                 break;
3315             }
3316         }
3317         break;
3318     }
3319     for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
3320         hidinfo = &coex_stat->hid_info[i];
3321         complete = hidinfo->hid_info_completed;
3322         handle = hidinfo->hid_handle;
3323         if (!complete || handle == COEX_BT_HIDINFO_NOTCON ||
3324             handle == 0 || handle >= COEX_BT_BLE_HANDLE_THRS) {
3325             hidinfo->is_game_hid = false;
3326             continue;
3327         }
3328 
3329         if (hidinfo->hid_vendor == COEX_BT_HIDINFO_MTK) {
3330             if ((memcmp(hidinfo->hid_name,
3331                     coex_bt_hidinfo_ps,
3332                     COEX_BT_HIDINFO_NAME)) == 0)
3333                 hidinfo->is_game_hid = true;
3334             else if ((memcmp(hidinfo->hid_name,
3335                      coex_bt_hidinfo_xb,
3336                      COEX_BT_HIDINFO_NAME)) == 0)
3337                 hidinfo->is_game_hid = true;
3338             else
3339                 hidinfo->is_game_hid = false;
3340         } else {
3341             hidinfo->is_game_hid = false;
3342         }
3343         if (hidinfo->is_game_hid)
3344             gamehid_cnt++;
3345     }
3346 
3347     if (gamehid_cnt > 0)
3348         cur_game_hid_exist = true;
3349     else
3350         cur_game_hid_exist = false;
3351 
3352     if (cur_game_hid_exist != coex_stat->bt_game_hid_exist) {
3353         coex_stat->bt_game_hid_exist = cur_game_hid_exist;
3354         rtw_dbg(rtwdev, RTW_DBG_COEX,
3355             "[BTCoex], HID info changed!bt_game_hid_exist = %d!\n",
3356             coex_stat->bt_game_hid_exist);
3357         rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
3358     }
3359 }
3360 
3361 void rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev)
3362 {
3363     struct rtw_coex *coex = &rtwdev->coex;
3364     struct rtw_chip_info *chip = rtwdev->chip;
3365     struct rtw_coex_stat *coex_stat = &coex->stat;
3366     struct rtw_coex_hid *hidinfo;
3367     u8 i, handle;
3368     bool complete;
3369 
3370     if (!chip->wl_mimo_ps_support || coex_stat->wl_under_ips ||
3371         (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl))
3372         return;
3373 
3374     if (!coex_stat->bt_hid_exist &&
3375         !((coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION) &&
3376           (coex_stat->hi_pri_tx + coex_stat->hi_pri_rx >
3377            COEX_BT_GAMEHID_CNT)))
3378         return;
3379 
3380     rtw_fw_coex_query_hid_info(rtwdev, COEX_BT_HIDINFO_LIST, 0);
3381 
3382     for (i = 0; i < COEX_BT_HIDINFO_HANDLE_NUM; i++) {
3383         hidinfo = &coex_stat->hid_info[i];
3384         complete = hidinfo->hid_info_completed;
3385         handle = hidinfo->hid_handle;
3386         if (handle == 0 || handle == COEX_BT_HIDINFO_NOTCON ||
3387             handle >= COEX_BT_BLE_HANDLE_THRS || complete)
3388             continue;
3389 
3390         rtw_fw_coex_query_hid_info(rtwdev,
3391                        COEX_BT_HIDINFO_A,
3392                        handle);
3393     }
3394 }
3395 
3396 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
3397 {
3398     struct rtw_coex *coex = &rtwdev->coex;
3399     struct rtw_coex_stat *coex_stat = &coex->stat;
3400     u8 val;
3401     int i;
3402 
3403     rtw_dbg(rtwdev, RTW_DBG_COEX,
3404         "[BTCoex], WiFi Fw Dbg info = %8ph (len = %d)\n",
3405         buf, length);
3406     if (WARN(length < 8, "invalid wl info c2h length\n"))
3407         return;
3408 
3409     if (buf[0] != 0x08)
3410         return;
3411 
3412     for (i = 1; i < 8; i++) {
3413         val = coex_stat->wl_fw_dbg_info_pre[i];
3414         if (buf[i] >= val)
3415             coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
3416         else
3417             coex_stat->wl_fw_dbg_info[i] = 255 - val + buf[i];
3418 
3419         coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
3420     }
3421 
3422     coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
3423     rtw_coex_wl_ccklock_action(rtwdev);
3424     rtw_coex_wl_ccklock_detect(rtwdev);
3425 }
3426 
3427 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev, u32 type)
3428 {
3429     rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3430 }
3431 
3432 void rtw_coex_wl_status_check(struct rtw_dev *rtwdev)
3433 {
3434     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3435 
3436     if ((coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) ||
3437         coex_stat->wl_under_ips)
3438         return;
3439 
3440     rtw_coex_monitor_bt_ctr(rtwdev);
3441 }
3442 
3443 void rtw_coex_bt_relink_work(struct work_struct *work)
3444 {
3445     struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3446                           coex.bt_relink_work.work);
3447     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3448 
3449     mutex_lock(&rtwdev->mutex);
3450     coex_stat->bt_setup_link = false;
3451     rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3452     mutex_unlock(&rtwdev->mutex);
3453 }
3454 
3455 void rtw_coex_bt_reenable_work(struct work_struct *work)
3456 {
3457     struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3458                           coex.bt_reenable_work.work);
3459     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3460 
3461     mutex_lock(&rtwdev->mutex);
3462     coex_stat->bt_reenable = false;
3463     mutex_unlock(&rtwdev->mutex);
3464 }
3465 
3466 void rtw_coex_defreeze_work(struct work_struct *work)
3467 {
3468     struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3469                           coex.defreeze_work.work);
3470     struct rtw_coex *coex = &rtwdev->coex;
3471     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3472 
3473     mutex_lock(&rtwdev->mutex);
3474     coex->freeze = false;
3475     coex_stat->wl_hi_pri_task1 = false;
3476     rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3477     mutex_unlock(&rtwdev->mutex);
3478 }
3479 
3480 void rtw_coex_wl_remain_work(struct work_struct *work)
3481 {
3482     struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3483                           coex.wl_remain_work.work);
3484     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3485 
3486     mutex_lock(&rtwdev->mutex);
3487     coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
3488     rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3489     mutex_unlock(&rtwdev->mutex);
3490 }
3491 
3492 void rtw_coex_bt_remain_work(struct work_struct *work)
3493 {
3494     struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3495                           coex.bt_remain_work.work);
3496     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3497 
3498     mutex_lock(&rtwdev->mutex);
3499     coex_stat->bt_inq_remain = coex_stat->bt_inq_page;
3500     rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
3501     mutex_unlock(&rtwdev->mutex);
3502 }
3503 
3504 void rtw_coex_wl_connecting_work(struct work_struct *work)
3505 {
3506     struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3507                           coex.wl_connecting_work.work);
3508     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3509 
3510     mutex_lock(&rtwdev->mutex);
3511     coex_stat->wl_connecting = false;
3512     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], WL connecting stop!!\n");
3513     rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
3514     mutex_unlock(&rtwdev->mutex);
3515 }
3516 
3517 void rtw_coex_bt_multi_link_remain_work(struct work_struct *work)
3518 {
3519     struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3520         coex.bt_multi_link_remain_work.work);
3521     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3522 
3523     mutex_lock(&rtwdev->mutex);
3524     coex_stat->bt_multi_link_remain = false;
3525     mutex_unlock(&rtwdev->mutex);
3526 }
3527 
3528 void rtw_coex_wl_ccklock_work(struct work_struct *work)
3529 {
3530     struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
3531                           coex.wl_ccklock_work.work);
3532     struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
3533 
3534     mutex_lock(&rtwdev->mutex);
3535     coex_stat->wl_cck_lock = false;
3536     mutex_unlock(&rtwdev->mutex);
3537 }
3538 
3539 #ifdef CONFIG_RTW88_DEBUGFS
3540 #define INFO_SIZE   80
3541 
3542 #define case_BTINFO(src) \
3543     case COEX_BTINFO_SRC_##src: return #src
3544 
3545 static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src)
3546 {
3547     switch (bt_info_src) {
3548     case_BTINFO(WL_FW);
3549     case_BTINFO(BT_RSP);
3550     case_BTINFO(BT_ACT);
3551     default:
3552         return "Unknown";
3553     }
3554 }
3555 
3556 #define case_RSN(src) \
3557     case COEX_RSN_##src: return #src
3558 
3559 static const char *rtw_coex_get_reason_string(u8 reason)
3560 {
3561     switch (reason) {
3562     case_RSN(2GSCANSTART);
3563     case_RSN(5GSCANSTART);
3564     case_RSN(SCANFINISH);
3565     case_RSN(2GSWITCHBAND);
3566     case_RSN(5GSWITCHBAND);
3567     case_RSN(2GCONSTART);
3568     case_RSN(5GCONSTART);
3569     case_RSN(2GCONFINISH);
3570     case_RSN(5GCONFINISH);
3571     case_RSN(2GMEDIA);
3572     case_RSN(5GMEDIA);
3573     case_RSN(MEDIADISCON);
3574     case_RSN(BTINFO);
3575     case_RSN(LPS);
3576     case_RSN(WLSTATUS);
3577     default:
3578         return "Unknown";
3579     }
3580 }
3581 
3582 static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,
3583                    u32 wl_reg_6c4)
3584 {
3585     struct rtw_chip_info *chip = rtwdev->chip;
3586     struct rtw_efuse *efuse = &rtwdev->efuse;
3587     u8 ans = 0xFF;
3588     u8 n, i;
3589     u32 load_bt_val;
3590     u32 load_wl_val;
3591     bool share_ant = efuse->share_ant;
3592 
3593     if (share_ant)
3594         n = chip->table_sant_num;
3595     else
3596         n = chip->table_nsant_num;
3597 
3598     for (i = 0; i < n; i++) {
3599         if (share_ant) {
3600             load_bt_val = chip->table_sant[i].bt;
3601             load_wl_val = chip->table_sant[i].wl;
3602         } else {
3603             load_bt_val = chip->table_nsant[i].bt;
3604             load_wl_val = chip->table_nsant[i].wl;
3605         }
3606 
3607         if (wl_reg_6c0 == load_bt_val &&
3608             wl_reg_6c4 == load_wl_val) {
3609             ans = i;
3610             if (!share_ant)
3611                 ans += 100;
3612             break;
3613         }
3614     }
3615 
3616     return ans;
3617 }
3618 
3619 static u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para)
3620 {
3621     struct rtw_efuse *efuse = &rtwdev->efuse;
3622     struct rtw_chip_info *chip = rtwdev->chip;
3623     u8 ans = 0xFF;
3624     u8 n, i, j;
3625     u8 load_cur_tab_val;
3626     bool valid = false;
3627     bool share_ant = efuse->share_ant;
3628 
3629     if (share_ant)
3630         n = chip->tdma_sant_num;
3631     else
3632         n = chip->tdma_nsant_num;
3633 
3634     for (i = 0; i < n; i++) {
3635         valid = false;
3636         for (j = 0; j < 5; j++) {
3637             if (share_ant)
3638                 load_cur_tab_val = chip->tdma_sant[i].para[j];
3639             else
3640                 load_cur_tab_val = chip->tdma_nsant[i].para[j];
3641 
3642             if (*(tdma_para + j) != load_cur_tab_val)
3643                 break;
3644 
3645             if (j == 4)
3646                 valid = true;
3647         }
3648         if (valid) {
3649             ans = i;
3650             break;
3651         }
3652     }
3653 
3654     return ans;
3655 }
3656 
3657 static int rtw_coex_addr_info(struct rtw_dev *rtwdev,
3658                   const struct rtw_reg_domain *reg,
3659                   char addr_info[], int n)
3660 {
3661     const char *rf_prefix = "";
3662     const char *sep = n == 0 ? "" : "/ ";
3663     int ffs, fls;
3664     int max_fls;
3665 
3666     if (INFO_SIZE - n <= 0)
3667         return 0;
3668 
3669     switch (reg->domain) {
3670     case RTW_REG_DOMAIN_MAC32:
3671         max_fls = 31;
3672         break;
3673     case RTW_REG_DOMAIN_MAC16:
3674         max_fls = 15;
3675         break;
3676     case RTW_REG_DOMAIN_MAC8:
3677         max_fls = 7;
3678         break;
3679     case RTW_REG_DOMAIN_RF_A:
3680     case RTW_REG_DOMAIN_RF_B:
3681         rf_prefix = "RF_";
3682         max_fls = 19;
3683         break;
3684     default:
3685         return 0;
3686     }
3687 
3688     ffs = __ffs(reg->mask);
3689     fls = __fls(reg->mask);
3690 
3691     if (ffs == 0 && fls == max_fls)
3692         return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x",
3693                  sep, rf_prefix, reg->addr);
3694     else if (ffs == fls)
3695         return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]",
3696                  sep, rf_prefix, reg->addr, ffs);
3697     else
3698         return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]",
3699                  sep, rf_prefix, reg->addr, fls, ffs);
3700 }
3701 
3702 static int rtw_coex_val_info(struct rtw_dev *rtwdev,
3703                  const struct rtw_reg_domain *reg,
3704                  char val_info[], int n)
3705 {
3706     const char *sep = n == 0 ? "" : "/ ";
3707     u8 rf_path;
3708 
3709     if (INFO_SIZE - n <= 0)
3710         return 0;
3711 
3712     switch (reg->domain) {
3713     case RTW_REG_DOMAIN_MAC32:
3714         return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3715                  rtw_read32_mask(rtwdev, reg->addr, reg->mask));
3716     case RTW_REG_DOMAIN_MAC16:
3717         return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3718                  rtw_read16_mask(rtwdev, reg->addr, reg->mask));
3719     case RTW_REG_DOMAIN_MAC8:
3720         return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3721                  rtw_read8_mask(rtwdev, reg->addr, reg->mask));
3722     case RTW_REG_DOMAIN_RF_A:
3723         rf_path = RF_PATH_A;
3724         break;
3725     case RTW_REG_DOMAIN_RF_B:
3726         rf_path = RF_PATH_B;
3727         break;
3728     default:
3729         return 0;
3730     }
3731 
3732     /* only RF go through here */
3733     return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
3734              rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask));
3735 }
3736 
3737 static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
3738 {
3739     struct rtw_chip_info *chip = rtwdev->chip;
3740     const struct rtw_reg_domain *reg;
3741     char addr_info[INFO_SIZE];
3742     int n_addr = 0;
3743     char val_info[INFO_SIZE];
3744     int n_val = 0;
3745     int i;
3746 
3747     for (i = 0; i < chip->coex_info_hw_regs_num; i++) {
3748         reg = &chip->coex_info_hw_regs[i];
3749 
3750         n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr);
3751         n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val);
3752 
3753         if (reg->domain == RTW_REG_DOMAIN_NL) {
3754             seq_printf(m, "%-40s = %s\n", addr_info, val_info);
3755             n_addr = 0;
3756             n_val = 0;
3757         }
3758     }
3759 
3760     if (n_addr != 0 && n_val != 0)
3761         seq_printf(m, "%-40s = %s\n", addr_info, val_info);
3762 }
3763 
3764 static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev,
3765                 u8 type, u16 addr, u16 *val)
3766 {
3767     struct rtw_coex_info_req req = {0};
3768     struct sk_buff *skb;
3769     __le16 le_addr;
3770     u8 *payload;
3771 
3772     le_addr = cpu_to_le16(addr);
3773     req.op_code = BT_MP_INFO_OP_READ_REG;
3774     req.para1 = type;
3775     req.para2 = le16_get_bits(le_addr, GENMASK(7, 0));
3776     req.para3 = le16_get_bits(le_addr, GENMASK(15, 8));
3777     skb = rtw_coex_info_request(rtwdev, &req);
3778     if (!skb) {
3779         *val = 0xeaea;
3780         return false;
3781     }
3782 
3783     payload = get_payload_from_coex_resp(skb);
3784     *val = GET_COEX_RESP_BT_REG_VAL(payload);
3785     dev_kfree_skb_any(skb);
3786 
3787     return true;
3788 }
3789 
3790 static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev,
3791                       u32 *patch_version)
3792 {
3793     struct rtw_coex_info_req req = {0};
3794     struct sk_buff *skb;
3795     u8 *payload;
3796 
3797     req.op_code = BT_MP_INFO_OP_PATCH_VER;
3798     skb = rtw_coex_info_request(rtwdev, &req);
3799     if (!skb)
3800         return false;
3801 
3802     payload = get_payload_from_coex_resp(skb);
3803     *patch_version = GET_COEX_RESP_BT_PATCH_VER(payload);
3804     dev_kfree_skb_any(skb);
3805 
3806     return true;
3807 }
3808 
3809 static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev,
3810                           u32 *supported_version)
3811 {
3812     struct rtw_coex_info_req req = {0};
3813     struct sk_buff *skb;
3814     u8 *payload;
3815 
3816     req.op_code = BT_MP_INFO_OP_SUPP_VER;
3817     skb = rtw_coex_info_request(rtwdev, &req);
3818     if (!skb)
3819         return false;
3820 
3821     payload = get_payload_from_coex_resp(skb);
3822     *supported_version = GET_COEX_RESP_BT_SUPP_VER(payload);
3823     dev_kfree_skb_any(skb);
3824 
3825     return true;
3826 }
3827 
3828 static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev,
3829                           u32 *supported_feature)
3830 {
3831     struct rtw_coex_info_req req = {0};
3832     struct sk_buff *skb;
3833     u8 *payload;
3834 
3835     req.op_code = BT_MP_INFO_OP_SUPP_FEAT;
3836     skb = rtw_coex_info_request(rtwdev, &req);
3837     if (!skb)
3838         return false;
3839 
3840     payload = get_payload_from_coex_resp(skb);
3841     *supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload);
3842     dev_kfree_skb_any(skb);
3843 
3844     return true;
3845 }
3846 
3847 struct rtw_coex_sta_stat_iter_data {
3848     struct rtw_vif *rtwvif;
3849     struct seq_file *file;
3850 };
3851 
3852 static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta)
3853 {
3854     struct rtw_coex_sta_stat_iter_data *sta_iter_data = data;
3855     struct rtw_vif *rtwvif = sta_iter_data->rtwvif;
3856     struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
3857     struct seq_file *m = sta_iter_data->file;
3858     struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
3859     u8 rssi;
3860 
3861     if (si->vif != vif)
3862         return;
3863 
3864     rssi = ewma_rssi_read(&si->avg_rssi);
3865     seq_printf(m, "\tPeer %3d\n", si->mac_id);
3866     seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi);
3867     seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode);
3868 }
3869 
3870 struct rtw_coex_vif_stat_iter_data {
3871     struct rtw_dev *rtwdev;
3872     struct seq_file *file;
3873 };
3874 
3875 static void rtw_coex_vif_stat_iter(void *data, u8 *mac,
3876                    struct ieee80211_vif *vif)
3877 {
3878     struct rtw_coex_vif_stat_iter_data *vif_iter_data = data;
3879     struct rtw_coex_sta_stat_iter_data sta_iter_data;
3880     struct rtw_dev *rtwdev = vif_iter_data->rtwdev;
3881     struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
3882     struct seq_file *m = vif_iter_data->file;
3883     struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
3884 
3885     seq_printf(m, "Iface on Port (%d)\n", rtwvif->port);
3886     seq_printf(m, "\t%-32s = %d\n",
3887            "Beacon interval", bss_conf->beacon_int);
3888     seq_printf(m, "\t%-32s = %d\n",
3889            "Network Type", rtwvif->net_type);
3890 
3891     sta_iter_data.rtwvif = rtwvif;
3892     sta_iter_data.file = m;
3893     rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter,
3894                 &sta_iter_data);
3895 }
3896 
3897 #define case_WLINK(src) \
3898     case COEX_WLINK_##src: return #src
3899 
3900 static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)
3901 {
3902     switch (coex_wl_link_mode) {
3903     case_WLINK(2G1PORT);
3904     case_WLINK(5G);
3905     case_WLINK(2GFREE);
3906     default:
3907         return "Unknown";
3908     }
3909 }
3910 
3911 void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
3912 {
3913     struct rtw_chip_info *chip = rtwdev->chip;
3914     struct rtw_dm_info *dm_info = &rtwdev->dm_info;
3915     struct rtw_coex *coex = &rtwdev->coex;
3916     struct rtw_coex_stat *coex_stat = &coex->stat;
3917     struct rtw_coex_dm *coex_dm = &coex->dm;
3918     struct rtw_hal *hal = &rtwdev->hal;
3919     struct rtw_efuse *efuse = &rtwdev->efuse;
3920     struct rtw_fw_state *fw = &rtwdev->fw;
3921     struct rtw_coex_vif_stat_iter_data vif_iter_data;
3922     u8 reason = coex_dm->reason;
3923     u8 sys_lte;
3924     u16 score_board_WB, score_board_BW;
3925     u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
3926     u32 lte_coex, bt_coex;
3927     int i;
3928 
3929     score_board_BW = rtw_coex_read_scbd(rtwdev);
3930     score_board_WB = coex_stat->score_board;
3931     wl_reg_6c0 = rtw_read32(rtwdev, REG_BT_COEX_TABLE0);
3932     wl_reg_6c4 = rtw_read32(rtwdev, REG_BT_COEX_TABLE1);
3933     wl_reg_6c8 = rtw_read32(rtwdev, REG_BT_COEX_BRK_TABLE);
3934     wl_reg_6cc = rtw_read32(rtwdev, REG_BT_COEX_TABLE_H);
3935     wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL);
3936 
3937     sys_lte = rtw_read8(rtwdev, 0x73);
3938     lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
3939     bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
3940 
3941     if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
3942         rtw_coex_get_bt_supported_version(rtwdev,
3943                 &coex_stat->bt_supported_version);
3944         rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);
3945         rtw_coex_get_bt_supported_feature(rtwdev,
3946                 &coex_stat->bt_supported_feature);
3947         rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae);
3948         rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac);
3949 
3950         if (coex_stat->patch_ver != 0)
3951             coex_stat->bt_mailbox_reply = true;
3952     }
3953 
3954     rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
3955     seq_printf(m, "**********************************************\n");
3956     seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);
3957     seq_printf(m, "**********************************************\n");
3958 
3959     if (coex->manual_control) {
3960         seq_puts(m, "============[Under Manual Control]============\n");
3961         seq_puts(m, "==========================================\n");
3962 
3963     } else if (coex->stop_dm) {
3964         seq_puts(m, "============[Coex is STOPPED]============\n");
3965         seq_puts(m, "==========================================\n");
3966 
3967     } else if (coex->freeze) {
3968         seq_puts(m, "============[coex_freeze]============\n");
3969         seq_puts(m, "==========================================\n");
3970     }
3971 
3972     seq_printf(m, "%-40s = %s/ %d\n",
3973            "Mech/ RFE",
3974            efuse->share_ant ? "Shared" : "Non-Shared",
3975            efuse->rfe_option);
3976     seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",
3977            "Coex Ver/ BT Dez/ BT Rpt",
3978            chip->coex_para_ver, chip->bt_desired_ver,
3979            coex_stat->bt_supported_version,
3980            coex_stat->bt_disabled ? "(BT disabled)" :
3981            coex_stat->bt_supported_version >= chip->bt_desired_ver ?
3982            "(Match)" : "(Mismatch)");
3983     seq_printf(m, "%-40s = %s/ %u/ %d\n",
3984            "Role/ RoleSwCnt/ IgnWL/ Feature",
3985            coex_stat->bt_slave ? "Slave" : "Master",
3986            coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],
3987            coex_dm->ignore_wl_act);
3988     seq_printf(m, "%-40s = %u.%u/ 0x%x/ 0x%x/ %c\n",
3989            "WL FW/ BT FW/ BT FW Desired/ KT",
3990            fw->version, fw->sub_version,
3991            coex_stat->patch_ver,
3992            chip->wl_fw_desired_ver, coex_stat->kt_ver + 65);
3993     seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
3994            "AFH Map",
3995            coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],
3996            coex_dm->wl_ch_info[2], hal->current_channel);
3997 
3998     rtw_debugfs_get_simple_phy_info(m);
3999     seq_printf(m, "**********************************************\n");
4000     seq_printf(m, "\t\tBT Status\n");
4001     seq_printf(m, "**********************************************\n");
4002     seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n",
4003            "BT status/ rssi/ retry/ pop",
4004            coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" :
4005            coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy",
4006            coex_stat->bt_rssi - 100,
4007            coex_stat->cnt_bt[COEX_CNT_BT_RETRY],
4008            coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]);
4009     seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n",
4010            "Profiles",
4011            coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ?
4012                            "A2DP sink," : "A2DP,") : "",
4013            coex_stat->bt_hfp_exist ? "HFP," : "",
4014            coex_stat->bt_hid_exist ?
4015            (coex_stat->bt_ble_exist ? "HID(RCU)," :
4016             coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :
4017             coex_stat->bt_ble_hid_exist ? "HID(BLE)" :
4018             "HID(2/18),") : "",
4019            coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?
4020            "OPP," : "PAN," : "",
4021            coex_stat->bt_ble_voice ? "Voice," : "",
4022            coex_stat->bt_multi_link);
4023     seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n",
4024            "Reinit/ Relink/ IgnWl/ Feature",
4025            coex_stat->cnt_bt[COEX_CNT_BT_REINIT],
4026            coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK],
4027            coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT],
4028            coex_stat->bt_supported_feature);
4029     seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
4030            "Page/ Inq/ iqk/ iqk fail",
4031            coex_stat->cnt_bt[COEX_CNT_BT_PAGE],
4032            coex_stat->cnt_bt[COEX_CNT_BT_INQ],
4033            coex_stat->cnt_bt[COEX_CNT_BT_IQK],
4034            coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]);
4035     seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",
4036            "0xae/ 0xac/ score board (W->B)/ (B->W)",
4037            coex_stat->bt_reg_vendor_ae,
4038            coex_stat->bt_reg_vendor_ac,
4039            score_board_WB, score_board_BW);
4040     seq_printf(m, "%-40s = %u/%u, %u/%u\n",
4041            "Hi-Pri TX/RX, Lo-Pri TX/RX",
4042            coex_stat->hi_pri_tx, coex_stat->hi_pri_rx,
4043            coex_stat->lo_pri_tx, coex_stat->lo_pri_rx);
4044     for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)
4045         seq_printf(m, "%-40s = %7ph\n",
4046                rtw_coex_get_bt_info_src_string(i),
4047                coex_stat->bt_info_c2h[i]);
4048 
4049     seq_printf(m, "**********************************************\n");
4050     seq_printf(m, "\t\tWiFi Status\n");
4051     seq_printf(m, "**********************************************\n");
4052     seq_printf(m, "%-40s = %d\n",
4053            "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags));
4054     seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",
4055            "G_busy/ TX/ RX",
4056            coex_stat->wl_gl_busy,
4057            rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
4058     seq_printf(m, "%-40s = %u/ %u/ %u\n",
4059            "IPS/ Low Power/ PS mode",
4060            test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags),
4061            test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
4062            rtwdev->lps_conf.mode);
4063 
4064     vif_iter_data.rtwdev = rtwdev;
4065     vif_iter_data.file = m;
4066     rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);
4067 
4068     if (coex->manual_control) {
4069         seq_printf(m, "**********************************************\n");
4070         seq_printf(m, "\t\tMechanism (Under Manual)\n");
4071         seq_printf(m, "**********************************************\n");
4072         seq_printf(m, "%-40s = %5ph (%d)\n",
4073                "TDMA Now",
4074                coex_dm->fw_tdma_para,
4075                rtw_coex_get_tdma_index(rtwdev,
4076                            &coex_dm->fw_tdma_para[0]));
4077     } else {
4078         seq_printf(m, "**********************************************\n");
4079         seq_printf(m, "\t\tMechanism\n");
4080         seq_printf(m, "**********************************************\n");
4081         seq_printf(m, "%-40s = %5ph (case-%d)\n",
4082                "TDMA",
4083                coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
4084     }
4085     seq_printf(m, "%-40s = %s/ %s/ %d\n",
4086            "Coex Mode/Free Run/Timer base",
4087            rtw_coex_get_wl_coex_mode(coex_stat->wl_coex_mode),
4088            coex->freerun ? "Yes" : "No",
4089            coex_stat->tdma_timer_base);
4090     seq_printf(m, "%-40s = %d(%d)/ 0x%08x/ 0x%08x/ 0x%08x\n",
4091            "Table/ 0x6c0/ 0x6c4/ 0x6c8",
4092            coex_dm->cur_table,
4093            rtw_coex_get_table_index(rtwdev, wl_reg_6c0, wl_reg_6c4),
4094            wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
4095     seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ %d/ reason (%s)\n",
4096            "0x778/ 0x6cc/ Run Count/ Reason",
4097            wl_reg_778, wl_reg_6cc,
4098            coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN],
4099            rtw_coex_get_reason_string(reason));
4100     seq_printf(m, "%-40s = %3ph\n",
4101            "AFH Map to BT",
4102            coex_dm->wl_ch_info);
4103     seq_printf(m, "%-40s = %s/ %d\n",
4104            "AntDiv/ BtCtrlLPS/ g_busy",
4105            coex_stat->wl_force_lps_ctrl ? "On" : "Off",
4106            coex_stat->wl_gl_busy);
4107     seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",
4108            "Null All/ Retry/ Ack/ BT Empty/ BT Late",
4109            coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],
4110            coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4],
4111            coex_stat->wl_fw_dbg_info[5]);
4112     seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n",
4113            "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",
4114            coex_stat->wl_fw_dbg_info[6],
4115            coex_stat->wl_fw_dbg_info[7],
4116            coex_stat->wl_slot_extend ? "Yes" : "No",
4117            coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);
4118     seq_printf(m, "%-40s = %d/ %d/ %s/ %d\n",
4119            "WL_TxPw/ BT_TxPw/ WL_Rx/ BT_LNA_Lvl",
4120            coex_dm->cur_wl_pwr_lvl,
4121            coex_dm->cur_bt_pwr_lvl,
4122            coex_dm->cur_wl_rx_low_gain_en ? "On" : "Off",
4123            coex_dm->cur_bt_lna_lvl);
4124 
4125     seq_printf(m, "**********************************************\n");
4126     seq_printf(m, "\t\tHW setting\n");
4127     seq_printf(m, "**********************************************\n");
4128     seq_printf(m, "%-40s = %s/ %s\n",
4129            "LTE Coex/ Path Owner",
4130            lte_coex & BIT(7) ? "ON" : "OFF",
4131            sys_lte & BIT(2) ? "WL" : "BT");
4132     seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",
4133            "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",
4134            lte_coex & BIT(12) ? "SW" : "HW",
4135            lte_coex & BIT(8) ? "SW" : "HW",
4136            lte_coex & BIT(14) ? "SW" : "HW",
4137            lte_coex & BIT(10) ? "SW" : "HW",
4138            sys_lte & BIT(3) ? "On" : "Off");
4139     seq_printf(m, "%-40s = %lu/ %lu\n",
4140            "GNT_WL/ GNT_BT",
4141            (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3);
4142     seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
4143            "CRC OK CCK/ OFDM/ HT/ VHT",
4144            dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
4145            dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
4146     seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
4147            "CRC ERR CCK/ OFDM/ HT/ VHT",
4148            dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
4149            dm_info->ht_err_cnt, dm_info->vht_err_cnt);
4150     seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n",
4151            "HiPr/ Locking/ Locked/ Noisy",
4152            coex_stat->wl_hi_pri_task1 ? "Y" : "N",
4153            coex_stat->wl_cck_lock ? "Y" : "N",
4154            coex_stat->wl_cck_lock_ever ? "Y" : "N",
4155            coex_stat->wl_noisy_level);
4156 
4157     rtw_coex_set_coexinfo_hw(rtwdev, m);
4158     seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
4159            "EVM A/ EVM B/ SNR A/ SNR B",
4160            -dm_info->rx_evm_dbm[RF_PATH_A],
4161            -dm_info->rx_evm_dbm[RF_PATH_B],
4162            -dm_info->rx_snr[RF_PATH_A],
4163            -dm_info->rx_snr[RF_PATH_B]);
4164     seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n",
4165            "CCK-CCA/CCK-FA/OFDM-CCA/OFDM-FA",
4166            dm_info->cck_cca_cnt, dm_info->cck_fa_cnt,
4167            dm_info->ofdm_cca_cnt, dm_info->ofdm_fa_cnt);
4168     seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC OK CCK/11g/11n/11ac",
4169            dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
4170            dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
4171     seq_printf(m, "%-40s = %d/ %d/ %d/ %d\n", "CRC Err CCK/11g/11n/11ac",
4172            dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
4173            dm_info->ht_err_cnt, dm_info->vht_err_cnt);
4174 
4175 }
4176 #endif /* CONFIG_RTW88_DEBUGFS */