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