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