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