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 12 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state, 13 u8 rssi, u8 rssi_thresh) 14 { 15 struct rtw_chip_info *chip = rtwdev->chip; 16 u8 tol = chip->rssi_tolerance; 17 u8 next_state; 18 19 if (pre_state == COEX_RSSI_STATE_LOW || 20 pre_state == COEX_RSSI_STATE_STAY_LOW) { 21 if (rssi >= (rssi_thresh + tol)) 22 next_state = COEX_RSSI_STATE_HIGH; 23 else 24 next_state = COEX_RSSI_STATE_STAY_LOW; 25 } else { 26 if (rssi < rssi_thresh) 27 next_state = COEX_RSSI_STATE_LOW; 28 else 29 next_state = COEX_RSSI_STATE_STAY_HIGH; 30 } 31 32 return next_state; 33 } 34 35 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev, 36 bool tx_limit_en, bool ampdu_limit_en) 37 { 38 struct rtw_chip_info *chip = rtwdev->chip; 39 struct rtw_coex *coex = &rtwdev->coex; 40 struct rtw_coex_stat *coex_stat = &coex->stat; 41 bool wifi_under_b_mode = false; 42 43 if (!chip->scbd_support) 44 return; 45 46 /* force max tx retry limit = 8 */ 47 if (coex_stat->wl_tx_limit_en == tx_limit_en && 48 coex_stat->wl_ampdu_limit_en == ampdu_limit_en) 49 return; 50 51 if (!coex_stat->wl_tx_limit_en) { 52 coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC); 53 coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH); 54 coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT); 55 } 56 57 if (!coex_stat->wl_ampdu_limit_en) 58 coex_stat->ampdu_max_time = 59 rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1); 60 61 coex_stat->wl_tx_limit_en = tx_limit_en; 62 coex_stat->wl_ampdu_limit_en = ampdu_limit_en; 63 64 if (tx_limit_en) { 65 /* set BT polluted packet on for tx rate adaptive, 66 * not including tx retry broken by PTA 67 */ 68 rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE); 69 70 /* set queue life time to avoid can't reach tx retry limit 71 * if tx is always broken by GNT_BT 72 */ 73 rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf); 74 rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808); 75 76 /* auto rate fallback step within 8 retries */ 77 if (wifi_under_b_mode) { 78 rtw_write32(rtwdev, REG_DARFRC, 0x1000000); 79 rtw_write32(rtwdev, REG_DARFRCH, 0x1010101); 80 } else { 81 rtw_write32(rtwdev, REG_DARFRC, 0x1000000); 82 rtw_write32(rtwdev, REG_DARFRCH, 0x4030201); 83 } 84 } else { 85 rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE); 86 rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf); 87 88 rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit); 89 rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc); 90 rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch); 91 } 92 93 if (ampdu_limit_en) 94 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20); 95 else 96 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 97 coex_stat->ampdu_max_time); 98 } 99 100 static void rtw_coex_limited_wl(struct rtw_dev *rtwdev) 101 { 102 struct rtw_coex *coex = &rtwdev->coex; 103 struct rtw_coex_dm *coex_dm = &coex->dm; 104 struct rtw_coex_stat *coex_stat = &coex->stat; 105 bool tx_limit = false; 106 bool tx_agg_ctrl = false; 107 108 if (coex->under_5g || 109 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 110 /* no need to limit tx */ 111 } else { 112 tx_limit = true; 113 if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist || 114 coex_stat->bt_hid_pair_num > 0) 115 tx_agg_ctrl = true; 116 } 117 118 rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl); 119 } 120 121 static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev) 122 { 123 struct rtw_coex *coex = &rtwdev->coex; 124 struct rtw_coex_stat *coex_stat = &coex->stat; 125 u8 para[6] = {0}; 126 127 if (coex->stop_dm) 128 return; 129 130 para[0] = COEX_H2C69_WL_LEAKAP; 131 132 if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) { 133 para[1] = PARA1_H2C69_DIS_5MS; /* disable 5ms extend */ 134 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 135 coex_stat->wl_slot_extend = false; 136 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; 137 return; 138 } 139 140 if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl && 141 !coex_stat->wl_cck_lock_ever) { 142 if (coex_stat->wl_fw_dbg_info[7] <= 5) 143 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++; 144 else 145 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; 146 147 if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) { 148 para[1] = 0x1; /* disable 5ms extend */ 149 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 150 coex_stat->wl_slot_extend = false; 151 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0; 152 } 153 } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) { 154 para[1] = 0x0; /* enable 5ms extend */ 155 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 156 coex_stat->wl_slot_extend = true; 157 } 158 } 159 160 static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev) 161 { 162 struct rtw_coex *coex = &rtwdev->coex; 163 struct rtw_coex_stat *coex_stat = &coex->stat; 164 165 /* TODO: wait for rx_rate_change_notify implement */ 166 coex_stat->wl_cck_lock = false; 167 coex_stat->wl_cck_lock_pre = false; 168 coex_stat->wl_cck_lock_ever = false; 169 } 170 171 static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev) 172 { 173 struct rtw_coex *coex = &rtwdev->coex; 174 struct rtw_coex_stat *coex_stat = &coex->stat; 175 struct rtw_dm_info *dm_info = &rtwdev->dm_info; 176 u32 cnt_cck; 177 178 /* wifi noisy environment identification */ 179 cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt; 180 181 if (!coex_stat->wl_gl_busy) { 182 if (cnt_cck > 250) { 183 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5) 184 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++; 185 186 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) { 187 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0; 188 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0; 189 } 190 } else if (cnt_cck < 100) { 191 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5) 192 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++; 193 194 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) { 195 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0; 196 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0; 197 } 198 } else { 199 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5) 200 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++; 201 202 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) { 203 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0; 204 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0; 205 } 206 } 207 208 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) 209 coex_stat->wl_noisy_level = 2; 210 else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) 211 coex_stat->wl_noisy_level = 1; 212 else 213 coex_stat->wl_noisy_level = 0; 214 } 215 } 216 217 static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type) 218 { 219 struct rtw_coex *coex = &rtwdev->coex; 220 struct rtw_coex_stat *coex_stat = &coex->stat; 221 u8 para[2] = {0}; 222 223 if (coex_stat->tdma_timer_base == type) 224 return; 225 226 coex_stat->tdma_timer_base = type; 227 228 para[0] = COEX_H2C69_TDMA_SLOT; 229 230 if (type == 3) /* 4-slot */ 231 para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */ 232 else /* 2-slot */ 233 para[1] = PARA1_H2C69_TDMA_2SLOT; 234 235 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 236 237 /* no 5ms_wl_slot_extend for 4-slot mode */ 238 if (coex_stat->tdma_timer_base == 3) 239 rtw_coex_wl_ccklock_action(rtwdev); 240 } 241 242 static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap, 243 u8 data) 244 { 245 u32 addr; 246 247 addr = REG_BT_COEX_TABLE_H + (bitmap / 8); 248 bitmap = bitmap % 8; 249 250 rtw_write8_mask(rtwdev, addr, BIT(bitmap), data); 251 } 252 253 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set) 254 { 255 struct rtw_chip_info *chip = rtwdev->chip; 256 struct rtw_coex *coex = &rtwdev->coex; 257 struct rtw_coex_stat *coex_stat = &coex->stat; 258 u16 val = 0x2; 259 260 if (!chip->scbd_support) 261 return; 262 263 val |= coex_stat->score_board; 264 265 /* for 8822b, scbd[10] is CQDDR on 266 * for 8822c, scbd[10] is no fix 2M 267 */ 268 if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) { 269 if (set) 270 val &= ~COEX_SCBD_FIX2M; 271 else 272 val |= COEX_SCBD_FIX2M; 273 } else { 274 if (set) 275 val |= bitpos; 276 else 277 val &= ~bitpos; 278 } 279 280 if (val != coex_stat->score_board) { 281 coex_stat->score_board = val; 282 val |= BIT_BT_INT_EN; 283 rtw_write16(rtwdev, REG_WIFI_BT_INFO, val); 284 } 285 } 286 287 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev) 288 { 289 struct rtw_chip_info *chip = rtwdev->chip; 290 291 if (!chip->scbd_support) 292 return 0; 293 294 return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN); 295 } 296 297 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev) 298 { 299 struct rtw_chip_info *chip = rtwdev->chip; 300 struct rtw_coex *coex = &rtwdev->coex; 301 struct rtw_coex_stat *coex_stat = &coex->stat; 302 struct rtw_coex_rfe *coex_rfe = &coex->rfe; 303 u8 cnt = 0; 304 u32 wait_cnt; 305 bool btk, wlk; 306 307 if (coex_rfe->wlg_at_btg && chip->scbd_support && 308 coex_stat->bt_iqk_state != 0xff) { 309 wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY; 310 do { 311 /* BT RFK */ 312 btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK); 313 314 /* WL RFK */ 315 wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK); 316 317 if (!btk && !wlk) 318 break; 319 320 mdelay(COEX_MIN_DELAY); 321 } while (++cnt < wait_cnt); 322 323 if (cnt >= wait_cnt) 324 coex_stat->bt_iqk_state = 0xff; 325 } 326 } 327 328 static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev) 329 { 330 struct rtw_coex *coex = &rtwdev->coex; 331 struct rtw_coex_stat *coex_stat = &coex->stat; 332 333 if (coex_stat->bt_disabled) 334 return; 335 336 rtw_fw_query_bt_info(rtwdev); 337 } 338 339 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev) 340 { 341 struct rtw_chip_info *chip = rtwdev->chip; 342 struct rtw_coex *coex = &rtwdev->coex; 343 struct rtw_coex_stat *coex_stat = &coex->stat; 344 struct rtw_coex_dm *coex_dm = &coex->dm; 345 bool bt_disabled = false; 346 u16 score_board; 347 348 if (chip->scbd_support) { 349 score_board = rtw_coex_read_scbd(rtwdev); 350 bt_disabled = !(score_board & COEX_SCBD_ONOFF); 351 } 352 353 if (coex_stat->bt_disabled != bt_disabled) { 354 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n", 355 coex_stat->bt_disabled, bt_disabled); 356 357 coex_stat->bt_disabled = bt_disabled; 358 coex_stat->bt_ble_scan_type = 0; 359 coex_dm->cur_bt_lna_lvl = 0; 360 } 361 362 if (!coex_stat->bt_disabled) { 363 coex_stat->bt_reenable = true; 364 ieee80211_queue_delayed_work(rtwdev->hw, 365 &coex->bt_reenable_work, 15 * HZ); 366 } else { 367 coex_stat->bt_mailbox_reply = false; 368 coex_stat->bt_reenable = false; 369 } 370 } 371 372 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason) 373 { 374 struct rtw_coex *coex = &rtwdev->coex; 375 struct rtw_coex_stat *coex_stat = &coex->stat; 376 struct rtw_coex_dm *coex_dm = &coex->dm; 377 struct rtw_chip_info *chip = rtwdev->chip; 378 struct rtw_traffic_stats *stats = &rtwdev->stats; 379 bool is_5G = false; 380 bool scan = false, link = false; 381 int i; 382 u8 rssi_state; 383 u8 rssi_step; 384 u8 rssi; 385 386 scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags); 387 coex_stat->wl_connected = !!rtwdev->sta_cnt; 388 coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); 389 390 if (stats->tx_throughput > stats->rx_throughput) 391 coex_stat->wl_tput_dir = COEX_WL_TPUT_TX; 392 else 393 coex_stat->wl_tput_dir = COEX_WL_TPUT_RX; 394 395 if (scan || link || reason == COEX_RSN_2GCONSTART || 396 reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND) 397 coex_stat->wl_linkscan_proc = true; 398 else 399 coex_stat->wl_linkscan_proc = false; 400 401 rtw_coex_wl_noisy_detect(rtwdev); 402 403 for (i = 0; i < 4; i++) { 404 rssi_state = coex_dm->wl_rssi_state[i]; 405 rssi_step = chip->wl_rssi_step[i]; 406 rssi = rtwdev->dm_info.min_rssi; 407 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, 408 rssi, rssi_step); 409 coex_dm->wl_rssi_state[i] = rssi_state; 410 } 411 412 switch (reason) { 413 case COEX_RSN_5GSCANSTART: 414 case COEX_RSN_5GSWITCHBAND: 415 case COEX_RSN_5GCONSTART: 416 417 is_5G = true; 418 break; 419 case COEX_RSN_2GSCANSTART: 420 case COEX_RSN_2GSWITCHBAND: 421 case COEX_RSN_2GCONSTART: 422 423 is_5G = false; 424 break; 425 default: 426 if (rtwdev->hal.current_band_type == RTW_BAND_5G) 427 is_5G = true; 428 else 429 is_5G = false; 430 break; 431 } 432 433 coex->under_5g = is_5G; 434 } 435 436 static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp) 437 { 438 struct rtw_c2h_cmd *c2h; 439 u32 pkt_offset; 440 441 pkt_offset = *((u32 *)resp->cb); 442 c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset); 443 444 return c2h->payload; 445 } 446 447 void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb) 448 { 449 struct rtw_coex *coex = &rtwdev->coex; 450 u8 *payload = get_payload_from_coex_resp(skb); 451 452 if (payload[0] != COEX_RESP_ACK_BY_WL_FW) 453 return; 454 455 skb_queue_tail(&coex->queue, skb); 456 wake_up(&coex->wait); 457 } 458 459 static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev, 460 struct rtw_coex_info_req *req) 461 { 462 struct rtw_coex *coex = &rtwdev->coex; 463 struct sk_buff *skb_resp = NULL; 464 465 mutex_lock(&coex->mutex); 466 467 rtw_fw_query_bt_mp_info(rtwdev, req); 468 469 if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue), 470 COEX_REQUEST_TIMEOUT)) { 471 rtw_err(rtwdev, "coex request time out\n"); 472 goto out; 473 } 474 475 skb_resp = skb_dequeue(&coex->queue); 476 if (!skb_resp) { 477 rtw_err(rtwdev, "failed to get coex info response\n"); 478 goto out; 479 } 480 481 out: 482 mutex_unlock(&coex->mutex); 483 return skb_resp; 484 } 485 486 static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type) 487 { 488 struct rtw_coex_info_req req = {0}; 489 struct sk_buff *skb; 490 u8 *payload; 491 bool ret = false; 492 493 req.op_code = BT_MP_INFO_OP_SCAN_TYPE; 494 skb = rtw_coex_info_request(rtwdev, &req); 495 if (!skb) 496 goto out; 497 498 payload = get_payload_from_coex_resp(skb); 499 *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload); 500 dev_kfree_skb_any(skb); 501 ret = true; 502 503 out: 504 return ret; 505 } 506 507 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev, 508 u8 lna_constrain_level) 509 { 510 struct rtw_coex_info_req req = {0}; 511 struct sk_buff *skb; 512 bool ret = false; 513 514 req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT; 515 req.para1 = lna_constrain_level; 516 skb = rtw_coex_info_request(rtwdev, &req); 517 if (!skb) 518 goto out; 519 520 dev_kfree_skb_any(skb); 521 ret = true; 522 523 out: 524 return ret; 525 } 526 527 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev) 528 { 529 struct rtw_coex *coex = &rtwdev->coex; 530 struct rtw_coex_stat *coex_stat = &coex->stat; 531 struct rtw_coex_dm *coex_dm = &coex->dm; 532 struct rtw_chip_info *chip = rtwdev->chip; 533 u8 i; 534 u8 rssi_state; 535 u8 rssi_step; 536 u8 rssi; 537 538 /* update wl/bt rssi by btinfo */ 539 for (i = 0; i < COEX_RSSI_STEP; i++) { 540 rssi_state = coex_dm->bt_rssi_state[i]; 541 rssi_step = chip->bt_rssi_step[i]; 542 rssi = coex_stat->bt_rssi; 543 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, 544 rssi, rssi_step); 545 coex_dm->bt_rssi_state[i] = rssi_state; 546 } 547 548 for (i = 0; i < COEX_RSSI_STEP; i++) { 549 rssi_state = coex_dm->wl_rssi_state[i]; 550 rssi_step = chip->wl_rssi_step[i]; 551 rssi = rtwdev->dm_info.min_rssi; 552 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state, 553 rssi, rssi_step); 554 coex_dm->wl_rssi_state[i] = rssi_state; 555 } 556 557 if (coex_stat->bt_ble_scan_en && 558 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) { 559 u8 scan_type; 560 561 if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) { 562 coex_stat->bt_ble_scan_type = scan_type; 563 if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1) 564 coex_stat->bt_init_scan = true; 565 else 566 coex_stat->bt_init_scan = false; 567 } 568 } 569 570 coex_stat->bt_profile_num = 0; 571 572 /* set link exist status */ 573 if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) { 574 coex_stat->bt_link_exist = false; 575 coex_stat->bt_pan_exist = false; 576 coex_stat->bt_a2dp_exist = false; 577 coex_stat->bt_hid_exist = false; 578 coex_stat->bt_hfp_exist = false; 579 } else { 580 /* connection exists */ 581 coex_stat->bt_link_exist = true; 582 if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) { 583 coex_stat->bt_pan_exist = true; 584 coex_stat->bt_profile_num++; 585 } else { 586 coex_stat->bt_pan_exist = false; 587 } 588 589 if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) { 590 coex_stat->bt_a2dp_exist = true; 591 coex_stat->bt_profile_num++; 592 } else { 593 coex_stat->bt_a2dp_exist = false; 594 } 595 596 if (coex_stat->bt_info_lb2 & COEX_INFO_HID) { 597 coex_stat->bt_hid_exist = true; 598 coex_stat->bt_profile_num++; 599 } else { 600 coex_stat->bt_hid_exist = false; 601 } 602 603 if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) { 604 coex_stat->bt_hfp_exist = true; 605 coex_stat->bt_profile_num++; 606 } else { 607 coex_stat->bt_hfp_exist = false; 608 } 609 } 610 611 if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) { 612 coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE; 613 } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) { 614 coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE; 615 } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) { 616 coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE; 617 } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) || 618 (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) { 619 if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) 620 coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY; 621 else 622 coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY; 623 } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) { 624 coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY; 625 } else { 626 coex_dm->bt_status = COEX_BTSTATUS_MAX; 627 } 628 629 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++; 630 631 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status); 632 } 633 634 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type) 635 { 636 struct rtw_chip_info *chip = rtwdev->chip; 637 struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm; 638 struct rtw_efuse *efuse = &rtwdev->efuse; 639 u8 link = 0; 640 u8 center_chan = 0; 641 u8 bw; 642 int i; 643 644 bw = rtwdev->hal.current_band_width; 645 646 if (type != COEX_MEDIA_DISCONNECT) 647 center_chan = rtwdev->hal.current_channel; 648 649 if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) { 650 link = 0; 651 } else if (center_chan <= 14) { 652 link = 0x1; 653 654 if (bw == RTW_CHANNEL_WIDTH_40) 655 bw = chip->bt_afh_span_bw40; 656 else 657 bw = chip->bt_afh_span_bw20; 658 } else if (chip->afh_5g_num > 1) { 659 for (i = 0; i < chip->afh_5g_num; i++) { 660 if (center_chan == chip->afh_5g[i].wl_5g_ch) { 661 link = 0x3; 662 center_chan = chip->afh_5g[i].bt_skip_ch; 663 bw = chip->afh_5g[i].bt_skip_span; 664 break; 665 } 666 } 667 } 668 669 coex_dm->wl_ch_info[0] = link; 670 coex_dm->wl_ch_info[1] = center_chan; 671 coex_dm->wl_ch_info[2] = bw; 672 673 rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw); 674 } 675 676 static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl) 677 { 678 struct rtw_coex *coex = &rtwdev->coex; 679 struct rtw_coex_dm *coex_dm = &coex->dm; 680 681 if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl) 682 return; 683 684 coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl; 685 686 rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl); 687 } 688 689 static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl) 690 { 691 struct rtw_coex *coex = &rtwdev->coex; 692 struct rtw_coex_dm *coex_dm = &coex->dm; 693 694 if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl) 695 return; 696 697 coex_dm->cur_bt_lna_lvl = bt_lna_lvl; 698 699 /* notify BT rx gain table changed */ 700 if (bt_lna_lvl < 7) { 701 rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl); 702 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true); 703 } else { 704 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false); 705 } 706 } 707 708 static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev, 709 struct coex_rf_para para) 710 { 711 struct rtw_coex *coex = &rtwdev->coex; 712 struct rtw_coex_stat *coex_stat = &coex->stat; 713 u8 offset = 0; 714 715 if (coex->freerun && coex_stat->wl_noisy_level <= 1) 716 offset = 3; 717 718 rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl); 719 rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset); 720 rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en); 721 rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl); 722 } 723 724 u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr) 725 { 726 u32 val; 727 728 if (!ltecoex_read_reg(rtwdev, addr, &val)) { 729 rtw_err(rtwdev, "failed to read indirect register\n"); 730 return 0; 731 } 732 733 return val; 734 } 735 736 void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr, 737 u32 mask, u32 val) 738 { 739 u32 shift = __ffs(mask); 740 u32 tmp; 741 742 tmp = rtw_coex_read_indirect_reg(rtwdev, addr); 743 tmp = (tmp & (~mask)) | ((val << shift) & mask); 744 745 if (!ltecoex_reg_write(rtwdev, addr, tmp)) 746 rtw_err(rtwdev, "failed to write indirect register\n"); 747 } 748 749 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control) 750 { 751 if (wifi_control) 752 rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); 753 else 754 rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH); 755 } 756 757 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state) 758 { 759 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state); 760 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state); 761 } 762 763 static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state) 764 { 765 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state); 766 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state); 767 } 768 769 static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1) 770 { 771 #define DEF_BRK_TABLE_VAL 0xf0ffffff 772 rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0); 773 rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1); 774 rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL); 775 } 776 777 static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type) 778 { 779 struct rtw_coex *coex = &rtwdev->coex; 780 struct rtw_coex_dm *coex_dm = &coex->dm; 781 struct rtw_chip_info *chip = rtwdev->chip; 782 struct rtw_efuse *efuse = &rtwdev->efuse; 783 784 coex_dm->cur_table = type; 785 786 if (efuse->share_ant) { 787 if (type < chip->table_sant_num) 788 rtw_coex_set_table(rtwdev, 789 chip->table_sant[type].bt, 790 chip->table_sant[type].wl); 791 } else { 792 type = type - 100; 793 if (type < chip->table_nsant_num) 794 rtw_coex_set_table(rtwdev, 795 chip->table_nsant[type].bt, 796 chip->table_nsant[type].wl); 797 } 798 } 799 800 static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable) 801 { 802 struct rtw_coex *coex = &rtwdev->coex; 803 804 if (coex->stop_dm) 805 return; 806 807 rtw_fw_bt_ignore_wlan_action(rtwdev, enable); 808 } 809 810 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type, 811 u8 lps_val, u8 rpwm_val) 812 { 813 struct rtw_coex *coex = &rtwdev->coex; 814 struct rtw_coex_stat *coex_stat = &coex->stat; 815 u8 lps_mode = 0x0; 816 817 lps_mode = rtwdev->lps_conf.mode; 818 819 switch (ps_type) { 820 case COEX_PS_WIFI_NATIVE: 821 /* recover to original 32k low power setting */ 822 coex_stat->wl_force_lps_ctrl = false; 823 824 rtw_leave_lps(rtwdev); 825 break; 826 case COEX_PS_LPS_OFF: 827 coex_stat->wl_force_lps_ctrl = true; 828 if (lps_mode) 829 rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0); 830 831 rtw_leave_lps(rtwdev); 832 break; 833 default: 834 break; 835 } 836 } 837 838 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2, 839 u8 byte3, u8 byte4, u8 byte5) 840 { 841 struct rtw_coex *coex = &rtwdev->coex; 842 struct rtw_coex_dm *coex_dm = &coex->dm; 843 struct rtw_chip_info *chip = rtwdev->chip; 844 u8 ps_type = COEX_PS_WIFI_NATIVE; 845 bool ap_enable = false; 846 847 if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) { 848 byte1 &= ~BIT(4); 849 byte1 |= BIT(5); 850 851 byte5 |= BIT(5); 852 byte5 &= ~BIT(6); 853 854 ps_type = COEX_PS_WIFI_NATIVE; 855 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); 856 } else if (byte1 & BIT(4) && !(byte1 & BIT(5))) { 857 if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF) 858 ps_type = COEX_PS_LPS_OFF; 859 else 860 ps_type = COEX_PS_LPS_ON; 861 rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4); 862 } else { 863 ps_type = COEX_PS_WIFI_NATIVE; 864 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); 865 } 866 867 coex_dm->ps_tdma_para[0] = byte1; 868 coex_dm->ps_tdma_para[1] = byte2; 869 coex_dm->ps_tdma_para[2] = byte3; 870 coex_dm->ps_tdma_para[3] = byte4; 871 coex_dm->ps_tdma_para[4] = byte5; 872 873 rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5); 874 } 875 876 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase) 877 { 878 struct rtw_coex *coex = &rtwdev->coex; 879 struct rtw_coex_dm *coex_dm = &coex->dm; 880 struct rtw_chip_info *chip = rtwdev->chip; 881 struct rtw_efuse *efuse = &rtwdev->efuse; 882 u8 n, type; 883 bool turn_on; 884 885 if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */ 886 rtw_coex_tdma_timer_base(rtwdev, 3); 887 else 888 rtw_coex_tdma_timer_base(rtwdev, 0); 889 890 type = (u8)(tcase & 0xff); 891 892 turn_on = (type == 0 || type == 100) ? false : true; 893 894 if (!force) { 895 if (turn_on == coex_dm->cur_ps_tdma_on && 896 type == coex_dm->cur_ps_tdma) { 897 return; 898 } 899 } 900 901 if (turn_on) { 902 /* enable TBTT interrupt */ 903 rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); 904 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true); 905 } else { 906 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false); 907 } 908 909 if (efuse->share_ant) { 910 if (type < chip->tdma_sant_num) 911 rtw_coex_set_tdma(rtwdev, 912 chip->tdma_sant[type].para[0], 913 chip->tdma_sant[type].para[1], 914 chip->tdma_sant[type].para[2], 915 chip->tdma_sant[type].para[3], 916 chip->tdma_sant[type].para[4]); 917 } else { 918 n = type - 100; 919 if (n < chip->tdma_nsant_num) 920 rtw_coex_set_tdma(rtwdev, 921 chip->tdma_nsant[n].para[0], 922 chip->tdma_nsant[n].para[1], 923 chip->tdma_nsant[n].para[2], 924 chip->tdma_nsant[n].para[3], 925 chip->tdma_nsant[n].para[4]); 926 } 927 928 /* update pre state */ 929 coex_dm->cur_ps_tdma_on = turn_on; 930 coex_dm->cur_ps_tdma = type; 931 932 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type); 933 } 934 935 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) 936 { 937 struct rtw_coex *coex = &rtwdev->coex; 938 struct rtw_coex_stat *coex_stat = &coex->stat; 939 struct rtw_coex_dm *coex_dm = &coex->dm; 940 u8 ctrl_type = COEX_SWITCH_CTRL_MAX; 941 u8 pos_type = COEX_SWITCH_TO_MAX; 942 943 if (!force && coex_dm->cur_ant_pos_type == phase) 944 return; 945 946 coex_dm->cur_ant_pos_type = phase; 947 948 /* avoid switch coex_ctrl_owner during BT IQK */ 949 rtw_coex_check_rfk(rtwdev); 950 951 switch (phase) { 952 case COEX_SET_ANT_POWERON: 953 /* set path control owner to BT at power-on */ 954 if (coex_stat->bt_disabled) 955 rtw_coex_coex_ctrl_owner(rtwdev, true); 956 else 957 rtw_coex_coex_ctrl_owner(rtwdev, false); 958 959 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 960 pos_type = COEX_SWITCH_TO_BT; 961 break; 962 case COEX_SET_ANT_INIT: 963 if (coex_stat->bt_disabled) { 964 /* set GNT_BT to SW low */ 965 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); 966 967 /* set GNT_WL to SW high */ 968 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 969 } else { 970 /* set GNT_BT to SW high */ 971 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 972 973 /* set GNT_WL to SW low */ 974 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW); 975 } 976 977 /* set path control owner to wl at initial step */ 978 rtw_coex_coex_ctrl_owner(rtwdev, true); 979 980 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 981 pos_type = COEX_SWITCH_TO_BT; 982 break; 983 case COEX_SET_ANT_WONLY: 984 /* set GNT_BT to SW Low */ 985 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); 986 987 /* Set GNT_WL to SW high */ 988 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 989 990 /* set path control owner to wl at initial step */ 991 rtw_coex_coex_ctrl_owner(rtwdev, true); 992 993 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 994 pos_type = COEX_SWITCH_TO_WLG; 995 break; 996 case COEX_SET_ANT_WOFF: 997 /* set path control owner to BT */ 998 rtw_coex_coex_ctrl_owner(rtwdev, false); 999 1000 ctrl_type = COEX_SWITCH_CTRL_BY_BT; 1001 pos_type = COEX_SWITCH_TO_NOCARE; 1002 break; 1003 case COEX_SET_ANT_2G: 1004 /* set GNT_BT to PTA */ 1005 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 1006 1007 /* set GNT_WL to PTA */ 1008 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); 1009 1010 /* set path control owner to wl at runtime step */ 1011 rtw_coex_coex_ctrl_owner(rtwdev, true); 1012 1013 ctrl_type = COEX_SWITCH_CTRL_BY_PTA; 1014 pos_type = COEX_SWITCH_TO_NOCARE; 1015 break; 1016 case COEX_SET_ANT_5G: 1017 /* set GNT_BT to PTA */ 1018 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 1019 1020 /* set GNT_WL to SW high */ 1021 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 1022 1023 /* set path control owner to wl at runtime step */ 1024 rtw_coex_coex_ctrl_owner(rtwdev, true); 1025 1026 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1027 pos_type = COEX_SWITCH_TO_WLA; 1028 break; 1029 case COEX_SET_ANT_2G_FREERUN: 1030 /* set GNT_BT to SW high */ 1031 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 1032 1033 /* Set GNT_WL to SW high */ 1034 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 1035 1036 /* set path control owner to wl at runtime step */ 1037 rtw_coex_coex_ctrl_owner(rtwdev, true); 1038 1039 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1040 pos_type = COEX_SWITCH_TO_WLG_BT; 1041 break; 1042 case COEX_SET_ANT_2G_WLBT: 1043 /* set GNT_BT to SW high */ 1044 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 1045 1046 /* Set GNT_WL to SW high */ 1047 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); 1048 1049 /* set path control owner to wl at runtime step */ 1050 rtw_coex_coex_ctrl_owner(rtwdev, true); 1051 1052 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1053 pos_type = COEX_SWITCH_TO_WLG_BT; 1054 break; 1055 default: 1056 WARN(1, "unknown phase when setting antenna path\n"); 1057 return; 1058 } 1059 1060 if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX) 1061 rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type); 1062 } 1063 1064 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev) 1065 { 1066 struct rtw_coex *coex = &rtwdev->coex; 1067 struct rtw_coex_stat *coex_stat = &coex->stat; 1068 u8 algorithm = COEX_ALGO_NOPROFILE; 1069 u8 profile_map = 0; 1070 1071 if (coex_stat->bt_hfp_exist) 1072 profile_map |= BPM_HFP; 1073 if (coex_stat->bt_hid_exist) 1074 profile_map |= BPM_HID; 1075 if (coex_stat->bt_a2dp_exist) 1076 profile_map |= BPM_A2DP; 1077 if (coex_stat->bt_pan_exist) 1078 profile_map |= BPM_PAN; 1079 1080 switch (profile_map) { 1081 case BPM_HFP: 1082 algorithm = COEX_ALGO_HFP; 1083 break; 1084 case BPM_HID: 1085 case BPM_HFP + BPM_HID: 1086 algorithm = COEX_ALGO_HID; 1087 break; 1088 case BPM_HFP + BPM_A2DP: 1089 case BPM_HID + BPM_A2DP: 1090 case BPM_HFP + BPM_HID + BPM_A2DP: 1091 algorithm = COEX_ALGO_A2DP_HID; 1092 break; 1093 case BPM_HFP + BPM_PAN: 1094 case BPM_HID + BPM_PAN: 1095 case BPM_HFP + BPM_HID + BPM_PAN: 1096 algorithm = COEX_ALGO_PAN_HID; 1097 break; 1098 case BPM_HFP + BPM_A2DP + BPM_PAN: 1099 case BPM_HID + BPM_A2DP + BPM_PAN: 1100 case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN: 1101 algorithm = COEX_ALGO_A2DP_PAN_HID; 1102 break; 1103 case BPM_PAN: 1104 algorithm = COEX_ALGO_PAN; 1105 break; 1106 case BPM_A2DP + BPM_PAN: 1107 algorithm = COEX_ALGO_A2DP_PAN; 1108 break; 1109 case BPM_A2DP: 1110 if (coex_stat->bt_multi_link) { 1111 if (coex_stat->bt_hid_pair_num > 0) 1112 algorithm = COEX_ALGO_A2DP_HID; 1113 else 1114 algorithm = COEX_ALGO_A2DP_PAN; 1115 } else { 1116 algorithm = COEX_ALGO_A2DP; 1117 } 1118 break; 1119 default: 1120 algorithm = COEX_ALGO_NOPROFILE; 1121 break; 1122 } 1123 1124 return algorithm; 1125 } 1126 1127 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev) 1128 { 1129 struct rtw_efuse *efuse = &rtwdev->efuse; 1130 struct rtw_chip_info *chip = rtwdev->chip; 1131 u8 table_case, tdma_case; 1132 1133 if (efuse->share_ant) { 1134 /* Shared-Ant */ 1135 table_case = 2; 1136 tdma_case = 0; 1137 } else { 1138 /* Non-Shared-Ant */ 1139 table_case = 100; 1140 tdma_case = 100; 1141 } 1142 1143 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1144 rtw_coex_table(rtwdev, table_case); 1145 rtw_coex_tdma(rtwdev, false, tdma_case); 1146 } 1147 1148 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev) 1149 { 1150 struct rtw_coex *coex = &rtwdev->coex; 1151 struct rtw_coex_stat *coex_stat = &coex->stat; 1152 struct rtw_coex_dm *coex_dm = &coex->dm; 1153 struct rtw_efuse *efuse = &rtwdev->efuse; 1154 struct rtw_chip_info *chip = rtwdev->chip; 1155 u8 level = 0; 1156 1157 if (efuse->share_ant) 1158 return; 1159 1160 coex->freerun = true; 1161 1162 if (coex_stat->wl_connected) 1163 rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT); 1164 1165 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); 1166 1167 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 1168 1169 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0])) 1170 level = 2; 1171 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 1172 level = 3; 1173 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2])) 1174 level = 4; 1175 else 1176 level = 5; 1177 1178 if (level > chip->wl_rf_para_num - 1) 1179 level = chip->wl_rf_para_num - 1; 1180 1181 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) 1182 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]); 1183 else 1184 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]); 1185 1186 rtw_coex_table(rtwdev, 100); 1187 rtw_coex_tdma(rtwdev, false, 100); 1188 } 1189 1190 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev) 1191 { 1192 struct rtw_efuse *efuse = &rtwdev->efuse; 1193 struct rtw_chip_info *chip = rtwdev->chip; 1194 u8 table_case, tdma_case; 1195 1196 if (efuse->share_ant) { 1197 /* Shared-Ant */ 1198 table_case = 2; 1199 tdma_case = 0; 1200 } else { 1201 /* Non-Shared-Ant */ 1202 table_case = 100; 1203 tdma_case = 100; 1204 } 1205 1206 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1207 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1208 rtw_coex_table(rtwdev, table_case); 1209 rtw_coex_tdma(rtwdev, false, tdma_case); 1210 } 1211 1212 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev) 1213 { 1214 struct rtw_efuse *efuse = &rtwdev->efuse; 1215 struct rtw_chip_info *chip = rtwdev->chip; 1216 u8 table_case, tdma_case; 1217 1218 if (efuse->share_ant) { 1219 /* Shared-Ant */ 1220 table_case = 1; 1221 tdma_case = 0; 1222 } else { 1223 /* Non-Shared-Ant */ 1224 table_case = 100; 1225 tdma_case = 100; 1226 } 1227 1228 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1229 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1230 rtw_coex_table(rtwdev, table_case); 1231 rtw_coex_tdma(rtwdev, false, tdma_case); 1232 } 1233 1234 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) 1235 { 1236 struct rtw_coex *coex = &rtwdev->coex; 1237 struct rtw_coex_stat *coex_stat = &coex->stat; 1238 struct rtw_coex_dm *coex_dm = &coex->dm; 1239 struct rtw_efuse *efuse = &rtwdev->efuse; 1240 struct rtw_chip_info *chip = rtwdev->chip; 1241 struct rtw_coex_rfe *coex_rfe = &coex->rfe; 1242 u8 table_case = 0xff, tdma_case = 0xff; 1243 1244 if (coex_rfe->ant_switch_with_bt && 1245 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 1246 if (efuse->share_ant && 1247 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) { 1248 table_case = 0; 1249 tdma_case = 0; 1250 } else if (!efuse->share_ant) { 1251 table_case = 100; 1252 tdma_case = 100; 1253 } 1254 } 1255 1256 if (table_case != 0xff && tdma_case != 0xff) { 1257 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); 1258 rtw_coex_table(rtwdev, table_case); 1259 rtw_coex_tdma(rtwdev, false, tdma_case); 1260 return; 1261 } 1262 1263 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1264 1265 if (efuse->share_ant) { 1266 /* Shared-Ant */ 1267 if (!coex_stat->wl_gl_busy) { 1268 table_case = 10; 1269 tdma_case = 3; 1270 } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 1271 table_case = 6; 1272 tdma_case = 7; 1273 } else { 1274 table_case = 12; 1275 tdma_case = 7; 1276 } 1277 } else { 1278 /* Non-Shared-Ant */ 1279 if (!coex_stat->wl_gl_busy) { 1280 table_case = 112; 1281 tdma_case = 104; 1282 } else if ((coex_stat->bt_ble_scan_type & 0x2) && 1283 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 1284 table_case = 114; 1285 tdma_case = 103; 1286 } else { 1287 table_case = 112; 1288 tdma_case = 103; 1289 } 1290 } 1291 1292 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1293 rtw_coex_table(rtwdev, table_case); 1294 rtw_coex_tdma(rtwdev, false, tdma_case); 1295 } 1296 1297 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) 1298 { 1299 struct rtw_coex *coex = &rtwdev->coex; 1300 struct rtw_coex_stat *coex_stat = &coex->stat; 1301 struct rtw_efuse *efuse = &rtwdev->efuse; 1302 struct rtw_chip_info *chip = rtwdev->chip; 1303 bool wl_hi_pri = false; 1304 u8 table_case, tdma_case; 1305 u32 slot_type = 0; 1306 1307 if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 || 1308 coex_stat->wl_hi_pri_task2) 1309 wl_hi_pri = true; 1310 1311 if (efuse->share_ant) { 1312 /* Shared-Ant */ 1313 if (wl_hi_pri) { 1314 table_case = 15; 1315 if (coex_stat->bt_a2dp_exist && 1316 !coex_stat->bt_pan_exist) { 1317 slot_type = TDMA_4SLOT; 1318 tdma_case = 11; 1319 } else if (coex_stat->wl_hi_pri_task1) { 1320 tdma_case = 6; 1321 } else if (!coex_stat->bt_page) { 1322 tdma_case = 8; 1323 } else { 1324 tdma_case = 9; 1325 } 1326 } else if (coex_stat->wl_connected) { 1327 table_case = 10; 1328 tdma_case = 10; 1329 } else { 1330 table_case = 1; 1331 tdma_case = 0; 1332 } 1333 } else { 1334 /* Non_Shared-Ant */ 1335 if (wl_hi_pri) { 1336 table_case = 113; 1337 if (coex_stat->bt_a2dp_exist && 1338 !coex_stat->bt_pan_exist) 1339 tdma_case = 111; 1340 else if (coex_stat->wl_hi_pri_task1) 1341 tdma_case = 106; 1342 else if (!coex_stat->bt_page) 1343 tdma_case = 108; 1344 else 1345 tdma_case = 109; 1346 } else if (coex_stat->wl_connected) { 1347 table_case = 101; 1348 tdma_case = 110; 1349 } else { 1350 table_case = 100; 1351 tdma_case = 100; 1352 } 1353 } 1354 1355 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n", 1356 wl_hi_pri, coex_stat->bt_page); 1357 1358 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1359 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1360 rtw_coex_table(rtwdev, table_case); 1361 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1362 } 1363 1364 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev) 1365 { 1366 struct rtw_coex *coex = &rtwdev->coex; 1367 struct rtw_coex_stat *coex_stat = &coex->stat; 1368 struct rtw_efuse *efuse = &rtwdev->efuse; 1369 struct rtw_chip_info *chip = rtwdev->chip; 1370 u8 table_case, tdma_case; 1371 1372 if (efuse->share_ant) { 1373 /* Shared-Ant */ 1374 if (coex_stat->bt_multi_link) { 1375 table_case = 10; 1376 tdma_case = 17; 1377 } else { 1378 table_case = 10; 1379 tdma_case = 5; 1380 } 1381 } else { 1382 /* Non-Shared-Ant */ 1383 if (coex_stat->bt_multi_link) { 1384 table_case = 112; 1385 tdma_case = 117; 1386 } else { 1387 table_case = 105; 1388 tdma_case = 100; 1389 } 1390 } 1391 1392 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1393 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1394 rtw_coex_table(rtwdev, table_case); 1395 rtw_coex_tdma(rtwdev, false, tdma_case); 1396 } 1397 1398 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev) 1399 { 1400 struct rtw_coex *coex = &rtwdev->coex; 1401 struct rtw_coex_stat *coex_stat = &coex->stat; 1402 struct rtw_efuse *efuse = &rtwdev->efuse; 1403 struct rtw_chip_info *chip = rtwdev->chip; 1404 u8 table_case, tdma_case; 1405 u32 wl_bw; 1406 1407 wl_bw = rtwdev->hal.current_band_width; 1408 1409 if (efuse->share_ant) { 1410 /* Shared-Ant */ 1411 if (coex_stat->bt_ble_exist) { 1412 /* RCU */ 1413 if (!coex_stat->wl_gl_busy) 1414 table_case = 14; 1415 else 1416 table_case = 15; 1417 1418 if (coex_stat->bt_a2dp_active || wl_bw == 0) 1419 tdma_case = 18; 1420 else if (coex_stat->wl_gl_busy) 1421 tdma_case = 8; 1422 else 1423 tdma_case = 4; 1424 } else { 1425 if (coex_stat->bt_a2dp_active || wl_bw == 0) { 1426 table_case = 8; 1427 tdma_case = 4; 1428 } else { 1429 /* for 4/18 HID */ 1430 if (coex_stat->bt_418_hid_exist && 1431 coex_stat->wl_gl_busy) 1432 table_case = 12; 1433 else 1434 table_case = 10; 1435 tdma_case = 4; 1436 } 1437 } 1438 } else { 1439 /* Non-Shared-Ant */ 1440 if (coex_stat->bt_a2dp_active) { 1441 table_case = 113; 1442 tdma_case = 118; 1443 } else if (coex_stat->bt_ble_exist) { 1444 /* BLE */ 1445 table_case = 113; 1446 1447 if (coex_stat->wl_gl_busy) 1448 tdma_case = 106; 1449 else 1450 tdma_case = 104; 1451 } else { 1452 table_case = 113; 1453 tdma_case = 104; 1454 } 1455 } 1456 1457 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1458 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1459 rtw_coex_table(rtwdev, table_case); 1460 rtw_coex_tdma(rtwdev, false, tdma_case); 1461 } 1462 1463 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev) 1464 { 1465 struct rtw_coex *coex = &rtwdev->coex; 1466 struct rtw_coex_stat *coex_stat = &coex->stat; 1467 struct rtw_coex_dm *coex_dm = &coex->dm; 1468 struct rtw_efuse *efuse = &rtwdev->efuse; 1469 struct rtw_chip_info *chip = rtwdev->chip; 1470 u8 table_case, tdma_case; 1471 u32 slot_type = 0; 1472 1473 if (efuse->share_ant) { 1474 /* Shared-Ant */ 1475 slot_type = TDMA_4SLOT; 1476 1477 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) 1478 table_case = 10; 1479 else 1480 table_case = 9; 1481 1482 if (coex_stat->wl_gl_busy) 1483 tdma_case = 13; 1484 else 1485 tdma_case = 14; 1486 } else { 1487 /* Non-Shared-Ant */ 1488 table_case = 112; 1489 1490 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 1491 tdma_case = 112; 1492 else 1493 tdma_case = 113; 1494 } 1495 1496 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1497 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1498 rtw_coex_table(rtwdev, table_case); 1499 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1500 } 1501 1502 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev) 1503 { 1504 struct rtw_coex *coex = &rtwdev->coex; 1505 struct rtw_coex_stat *coex_stat = &coex->stat; 1506 struct rtw_efuse *efuse = &rtwdev->efuse; 1507 struct rtw_chip_info *chip = rtwdev->chip; 1508 u8 table_case, tdma_case; 1509 bool ap_enable = false; 1510 1511 if (efuse->share_ant) { /* Shared-Ant */ 1512 if (ap_enable) { 1513 table_case = 2; 1514 tdma_case = 0; 1515 } else if (coex_stat->wl_gl_busy) { 1516 table_case = 28; 1517 tdma_case = 20; 1518 } else { 1519 table_case = 28; 1520 tdma_case = 26; 1521 } 1522 } else { /* Non-Shared-Ant */ 1523 if (ap_enable) { 1524 table_case = 100; 1525 tdma_case = 100; 1526 } else { 1527 table_case = 119; 1528 tdma_case = 120; 1529 } 1530 } 1531 1532 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1533 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1534 rtw_coex_table(rtwdev, table_case); 1535 rtw_coex_tdma(rtwdev, false, tdma_case); 1536 } 1537 1538 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev) 1539 { 1540 struct rtw_coex *coex = &rtwdev->coex; 1541 struct rtw_coex_stat *coex_stat = &coex->stat; 1542 struct rtw_efuse *efuse = &rtwdev->efuse; 1543 struct rtw_chip_info *chip = rtwdev->chip; 1544 u8 table_case, tdma_case; 1545 1546 if (efuse->share_ant) { 1547 /* Shared-Ant */ 1548 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) 1549 table_case = 14; 1550 else 1551 table_case = 10; 1552 1553 if (coex_stat->wl_gl_busy) 1554 tdma_case = 17; 1555 else 1556 tdma_case = 19; 1557 } else { 1558 /* Non-Shared-Ant */ 1559 table_case = 112; 1560 1561 if (coex_stat->wl_gl_busy) 1562 tdma_case = 117; 1563 else 1564 tdma_case = 119; 1565 } 1566 1567 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1568 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1569 rtw_coex_table(rtwdev, table_case); 1570 rtw_coex_tdma(rtwdev, false, tdma_case); 1571 } 1572 1573 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev) 1574 { 1575 struct rtw_coex *coex = &rtwdev->coex; 1576 struct rtw_coex_stat *coex_stat = &coex->stat; 1577 struct rtw_coex_dm *coex_dm = &coex->dm; 1578 struct rtw_efuse *efuse = &rtwdev->efuse; 1579 struct rtw_chip_info *chip = rtwdev->chip; 1580 u8 table_case, tdma_case; 1581 u32 slot_type = 0; 1582 1583 if (efuse->share_ant) { 1584 /* Shared-Ant */ 1585 slot_type = TDMA_4SLOT; 1586 1587 if (coex_stat->bt_ble_exist) 1588 table_case = 26; 1589 else 1590 table_case = 9; 1591 1592 if (coex_stat->wl_gl_busy) { 1593 tdma_case = 13; 1594 } else { 1595 tdma_case = 14; 1596 } 1597 } else { 1598 /* Non-Shared-Ant */ 1599 if (coex_stat->bt_ble_exist) 1600 table_case = 121; 1601 else 1602 table_case = 113; 1603 1604 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 1605 tdma_case = 112; 1606 else 1607 tdma_case = 113; 1608 } 1609 1610 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1611 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1612 rtw_coex_table(rtwdev, table_case); 1613 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1614 } 1615 1616 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) 1617 { 1618 struct rtw_coex *coex = &rtwdev->coex; 1619 struct rtw_coex_stat *coex_stat = &coex->stat; 1620 struct rtw_efuse *efuse = &rtwdev->efuse; 1621 struct rtw_chip_info *chip = rtwdev->chip; 1622 u8 table_case, tdma_case; 1623 1624 if (efuse->share_ant) { 1625 /* Shared-Ant */ 1626 if (coex_stat->wl_gl_busy && 1627 coex_stat->wl_noisy_level == 0) 1628 table_case = 14; 1629 else 1630 table_case = 10; 1631 1632 if (coex_stat->wl_gl_busy) 1633 tdma_case = 15; 1634 else 1635 tdma_case = 20; 1636 } else { 1637 /* Non-Shared-Ant */ 1638 table_case = 112; 1639 1640 if (coex_stat->wl_gl_busy) 1641 tdma_case = 115; 1642 else 1643 tdma_case = 120; 1644 } 1645 1646 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1647 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1648 rtw_coex_table(rtwdev, table_case); 1649 rtw_coex_tdma(rtwdev, false, tdma_case); 1650 } 1651 1652 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev) 1653 { 1654 struct rtw_coex *coex = &rtwdev->coex; 1655 struct rtw_coex_stat *coex_stat = &coex->stat; 1656 struct rtw_efuse *efuse = &rtwdev->efuse; 1657 struct rtw_chip_info *chip = rtwdev->chip; 1658 u8 table_case, tdma_case; 1659 1660 if (efuse->share_ant) { 1661 /* Shared-Ant */ 1662 table_case = 9; 1663 1664 if (coex_stat->wl_gl_busy) 1665 tdma_case = 18; 1666 else 1667 tdma_case = 19; 1668 } else { 1669 /* Non-Shared-Ant */ 1670 table_case = 113; 1671 1672 if (coex_stat->wl_gl_busy) 1673 tdma_case = 117; 1674 else 1675 tdma_case = 119; 1676 } 1677 1678 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1679 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1680 rtw_coex_table(rtwdev, table_case); 1681 rtw_coex_tdma(rtwdev, false, tdma_case); 1682 } 1683 1684 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev) 1685 { 1686 struct rtw_coex *coex = &rtwdev->coex; 1687 struct rtw_coex_stat *coex_stat = &coex->stat; 1688 struct rtw_efuse *efuse = &rtwdev->efuse; 1689 struct rtw_chip_info *chip = rtwdev->chip; 1690 u8 table_case, tdma_case; 1691 1692 if (efuse->share_ant) { 1693 /* Shared-Ant */ 1694 table_case = 10; 1695 1696 if (coex_stat->wl_gl_busy) 1697 tdma_case = 15; 1698 else 1699 tdma_case = 20; 1700 } else { 1701 /* Non-Shared-Ant */ 1702 table_case = 113; 1703 1704 if (coex_stat->wl_gl_busy) 1705 tdma_case = 115; 1706 else 1707 tdma_case = 120; 1708 } 1709 1710 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1711 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1712 rtw_coex_table(rtwdev, table_case); 1713 rtw_coex_tdma(rtwdev, false, tdma_case); 1714 } 1715 1716 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev) 1717 { 1718 struct rtw_efuse *efuse = &rtwdev->efuse; 1719 struct rtw_chip_info *chip = rtwdev->chip; 1720 u8 table_case, tdma_case; 1721 1722 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 1723 1724 if (efuse->share_ant) { 1725 /* Shared-Ant */ 1726 table_case = 0; 1727 tdma_case = 0; 1728 } else { 1729 /* Non-Shared-Ant */ 1730 table_case = 100; 1731 tdma_case = 100; 1732 } 1733 1734 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 1735 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1736 rtw_coex_table(rtwdev, table_case); 1737 rtw_coex_tdma(rtwdev, false, tdma_case); 1738 } 1739 1740 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev) 1741 { 1742 struct rtw_efuse *efuse = &rtwdev->efuse; 1743 struct rtw_chip_info *chip = rtwdev->chip; 1744 u8 table_case, tdma_case; 1745 1746 if (efuse->share_ant) { 1747 /* Shared-Ant */ 1748 table_case = 2; 1749 tdma_case = 0; 1750 } else { 1751 /* Non-Shared-Ant */ 1752 table_case = 100; 1753 tdma_case = 100; 1754 } 1755 1756 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1757 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1758 rtw_coex_table(rtwdev, table_case); 1759 rtw_coex_tdma(rtwdev, false, tdma_case); 1760 } 1761 1762 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev) 1763 { 1764 struct rtw_coex *coex = &rtwdev->coex; 1765 struct rtw_efuse *efuse = &rtwdev->efuse; 1766 struct rtw_chip_info *chip = rtwdev->chip; 1767 u8 table_case, tdma_case; 1768 1769 if (coex->under_5g) 1770 return; 1771 1772 if (efuse->share_ant) { 1773 /* Shared-Ant */ 1774 table_case = 28; 1775 tdma_case = 0; 1776 } else { 1777 /* Non-Shared-Ant */ 1778 table_case = 100; 1779 tdma_case = 100; 1780 } 1781 1782 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1783 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1784 rtw_coex_table(rtwdev, table_case); 1785 rtw_coex_tdma(rtwdev, false, tdma_case); 1786 } 1787 1788 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev) 1789 { 1790 struct rtw_coex *coex = &rtwdev->coex; 1791 struct rtw_coex_stat *coex_stat = &coex->stat; 1792 struct rtw_efuse *efuse = &rtwdev->efuse; 1793 struct rtw_chip_info *chip = rtwdev->chip; 1794 u8 table_case, tdma_case; 1795 u32 slot_type = 0; 1796 1797 if (efuse->share_ant) { 1798 /* Shared-Ant */ 1799 if (coex_stat->bt_a2dp_exist) { 1800 slot_type = TDMA_4SLOT; 1801 table_case = 9; 1802 tdma_case = 11; 1803 } else { 1804 table_case = 9; 1805 tdma_case = 7; 1806 } 1807 } else { 1808 /* Non-Shared-Ant */ 1809 if (coex_stat->bt_a2dp_exist) { 1810 table_case = 112; 1811 tdma_case = 111; 1812 } else { 1813 table_case = 112; 1814 tdma_case = 107; 1815 } 1816 } 1817 1818 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1819 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1820 rtw_coex_table(rtwdev, table_case); 1821 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1822 } 1823 1824 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev) 1825 { 1826 struct rtw_efuse *efuse = &rtwdev->efuse; 1827 struct rtw_chip_info *chip = rtwdev->chip; 1828 u8 table_case, tdma_case; 1829 1830 if (efuse->share_ant) { 1831 /* Shared-Ant */ 1832 table_case = 1; 1833 tdma_case = 0; 1834 } else { 1835 /* Non-Shared-Ant */ 1836 table_case = 100; 1837 tdma_case = 100; 1838 } 1839 1840 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1841 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1842 rtw_coex_table(rtwdev, table_case); 1843 rtw_coex_tdma(rtwdev, false, tdma_case); 1844 } 1845 1846 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev) 1847 { 1848 struct rtw_coex *coex = &rtwdev->coex; 1849 struct rtw_coex_stat *coex_stat = &coex->stat; 1850 struct rtw_coex_dm *coex_dm = &coex->dm; 1851 struct rtw_efuse *efuse = &rtwdev->efuse; 1852 u8 algorithm; 1853 1854 /* Non-Shared-Ant */ 1855 if (!efuse->share_ant && coex_stat->wl_gl_busy && 1856 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) && 1857 COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) { 1858 rtw_coex_action_freerun(rtwdev); 1859 return; 1860 } 1861 1862 algorithm = rtw_coex_algorithm(rtwdev); 1863 1864 switch (algorithm) { 1865 case COEX_ALGO_HFP: 1866 rtw_coex_action_bt_hfp(rtwdev); 1867 break; 1868 case COEX_ALGO_HID: 1869 rtw_coex_action_bt_hid(rtwdev); 1870 break; 1871 case COEX_ALGO_A2DP: 1872 if (coex_stat->bt_a2dp_sink) 1873 rtw_coex_action_bt_a2dpsink(rtwdev); 1874 else 1875 rtw_coex_action_bt_a2dp(rtwdev); 1876 break; 1877 case COEX_ALGO_PAN: 1878 rtw_coex_action_bt_pan(rtwdev); 1879 break; 1880 case COEX_ALGO_A2DP_HID: 1881 rtw_coex_action_bt_a2dp_hid(rtwdev); 1882 break; 1883 case COEX_ALGO_A2DP_PAN: 1884 rtw_coex_action_bt_a2dp_pan(rtwdev); 1885 break; 1886 case COEX_ALGO_PAN_HID: 1887 rtw_coex_action_bt_pan_hid(rtwdev); 1888 break; 1889 case COEX_ALGO_A2DP_PAN_HID: 1890 rtw_coex_action_bt_a2dp_pan_hid(rtwdev); 1891 break; 1892 default: 1893 case COEX_ALGO_NOPROFILE: 1894 rtw_coex_action_bt_idle(rtwdev); 1895 break; 1896 } 1897 } 1898 1899 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason) 1900 { 1901 struct rtw_coex *coex = &rtwdev->coex; 1902 struct rtw_coex_dm *coex_dm = &coex->dm; 1903 struct rtw_coex_stat *coex_stat = &coex->stat; 1904 1905 lockdep_assert_held(&rtwdev->mutex); 1906 1907 coex_dm->reason = reason; 1908 1909 /* update wifi_link_info_ext variable */ 1910 rtw_coex_update_wl_link_info(rtwdev, reason); 1911 1912 rtw_coex_monitor_bt_enable(rtwdev); 1913 1914 if (coex->stop_dm) 1915 return; 1916 1917 if (coex_stat->wl_under_ips) 1918 return; 1919 1920 if (coex->freeze && !coex_stat->bt_setup_link) 1921 return; 1922 1923 coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++; 1924 coex->freerun = false; 1925 1926 /* Pure-5G Coex Process */ 1927 if (coex->under_5g) { 1928 coex_stat->wl_coex_mode = COEX_WLINK_5G; 1929 rtw_coex_action_wl_under5g(rtwdev); 1930 goto exit; 1931 } 1932 1933 coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT; 1934 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 1935 if (coex_stat->bt_disabled) { 1936 rtw_coex_action_wl_only(rtwdev); 1937 goto exit; 1938 } 1939 1940 if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) { 1941 rtw_coex_action_wl_native_lps(rtwdev); 1942 goto exit; 1943 } 1944 1945 if (coex_stat->bt_whck_test) { 1946 rtw_coex_action_bt_whql_test(rtwdev); 1947 goto exit; 1948 } 1949 1950 if (coex_stat->bt_setup_link) { 1951 rtw_coex_action_bt_relink(rtwdev); 1952 goto exit; 1953 } 1954 1955 if (coex_stat->bt_inq_page) { 1956 rtw_coex_action_bt_inquiry(rtwdev); 1957 goto exit; 1958 } 1959 1960 if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE || 1961 coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) && 1962 coex_stat->wl_connected) { 1963 rtw_coex_action_bt_idle(rtwdev); 1964 goto exit; 1965 } 1966 1967 if (coex_stat->wl_linkscan_proc) { 1968 rtw_coex_action_wl_linkscan(rtwdev); 1969 goto exit; 1970 } 1971 1972 if (coex_stat->wl_connected) 1973 rtw_coex_action_wl_connected(rtwdev); 1974 else 1975 rtw_coex_action_wl_not_connected(rtwdev); 1976 1977 exit: 1978 rtw_coex_set_gnt_fix(rtwdev); 1979 rtw_coex_limited_wl(rtwdev); 1980 } 1981 1982 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev) 1983 { 1984 struct rtw_coex *coex = &rtwdev->coex; 1985 struct rtw_coex_stat *coex_stat = &coex->stat; 1986 struct rtw_coex_dm *coex_dm = &coex->dm; 1987 u8 i; 1988 1989 memset(coex_dm, 0, sizeof(*coex_dm)); 1990 memset(coex_stat, 0, sizeof(*coex_stat)); 1991 1992 for (i = 0; i < COEX_CNT_WL_MAX; i++) 1993 coex_stat->cnt_wl[i] = 0; 1994 1995 for (i = 0; i < COEX_CNT_BT_MAX; i++) 1996 coex_stat->cnt_bt[i] = 0; 1997 1998 for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++) 1999 coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW; 2000 2001 for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++) 2002 coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW; 2003 2004 coex_stat->wl_coex_mode = COEX_WLINK_MAX; 2005 } 2006 2007 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) 2008 { 2009 struct rtw_coex *coex = &rtwdev->coex; 2010 2011 rtw_coex_init_coex_var(rtwdev); 2012 rtw_coex_monitor_bt_enable(rtwdev); 2013 rtw_coex_set_rfe_type(rtwdev); 2014 rtw_coex_set_init(rtwdev); 2015 2016 /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */ 2017 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1); 2018 2019 /* set Tx beacon = Hi-Pri */ 2020 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1); 2021 2022 /* set Tx beacon queue = Hi-Pri */ 2023 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1); 2024 2025 /* antenna config */ 2026 if (coex->wl_rf_off) { 2027 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); 2028 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false); 2029 coex->stop_dm = true; 2030 } else if (wifi_only) { 2031 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY); 2032 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN, 2033 true); 2034 coex->stop_dm = true; 2035 } else { 2036 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT); 2037 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN, 2038 true); 2039 coex->stop_dm = false; 2040 coex->freeze = true; 2041 } 2042 2043 /* PTA parameter */ 2044 rtw_coex_table(rtwdev, 0); 2045 rtw_coex_tdma(rtwdev, true, 0); 2046 rtw_coex_query_bt_info(rtwdev); 2047 } 2048 2049 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev) 2050 { 2051 struct rtw_coex *coex = &rtwdev->coex; 2052 2053 coex->stop_dm = true; 2054 coex->wl_rf_off = false; 2055 2056 /* enable BB, we can write 0x948 */ 2057 rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1)); 2058 2059 rtw_coex_monitor_bt_enable(rtwdev); 2060 rtw_coex_set_rfe_type(rtwdev); 2061 2062 /* set antenna path to BT */ 2063 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON); 2064 2065 /* red x issue */ 2066 rtw_write8(rtwdev, 0xff1a, 0x0); 2067 } 2068 2069 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only) 2070 { 2071 __rtw_coex_init_hw_config(rtwdev, wifi_only); 2072 } 2073 2074 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type) 2075 { 2076 struct rtw_coex *coex = &rtwdev->coex; 2077 struct rtw_coex_stat *coex_stat = &coex->stat; 2078 2079 if (coex->stop_dm) 2080 return; 2081 2082 if (type == COEX_IPS_ENTER) { 2083 coex_stat->wl_under_ips = true; 2084 2085 /* for lps off */ 2086 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false); 2087 2088 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF); 2089 rtw_coex_action_coex_all_off(rtwdev); 2090 } else if (type == COEX_IPS_LEAVE) { 2091 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true); 2092 2093 /* run init hw config (exclude wifi only) */ 2094 __rtw_coex_init_hw_config(rtwdev, false); 2095 /* sw all off */ 2096 2097 coex_stat->wl_under_ips = false; 2098 } 2099 } 2100 2101 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type) 2102 { 2103 struct rtw_coex *coex = &rtwdev->coex; 2104 struct rtw_coex_stat *coex_stat = &coex->stat; 2105 2106 if (coex->stop_dm) 2107 return; 2108 2109 if (type == COEX_LPS_ENABLE) { 2110 coex_stat->wl_under_lps = true; 2111 2112 if (coex_stat->wl_force_lps_ctrl) { 2113 /* for ps-tdma */ 2114 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 2115 } else { 2116 /* for native ps */ 2117 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false); 2118 2119 rtw_coex_run_coex(rtwdev, COEX_RSN_LPS); 2120 } 2121 } else if (type == COEX_LPS_DISABLE) { 2122 coex_stat->wl_under_lps = false; 2123 2124 /* for lps off */ 2125 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 2126 2127 if (!coex_stat->wl_force_lps_ctrl) 2128 rtw_coex_query_bt_info(rtwdev); 2129 } 2130 } 2131 2132 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type) 2133 { 2134 struct rtw_coex *coex = &rtwdev->coex; 2135 struct rtw_coex_stat *coex_stat = &coex->stat; 2136 2137 if (coex->stop_dm) 2138 return; 2139 2140 coex->freeze = false; 2141 2142 if (type != COEX_SCAN_FINISH) 2143 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN | 2144 COEX_SCBD_ONOFF, true); 2145 2146 if (type == COEX_SCAN_START_5G) { 2147 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 2148 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART); 2149 } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) { 2150 coex_stat->wl_hi_pri_task2 = true; 2151 2152 /* Force antenna setup for no scan result issue */ 2153 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 2154 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART); 2155 } else { 2156 coex_stat->wl_hi_pri_task2 = false; 2157 rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH); 2158 } 2159 } 2160 2161 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type) 2162 { 2163 struct rtw_coex *coex = &rtwdev->coex; 2164 2165 if (coex->stop_dm) 2166 return; 2167 2168 if (type == COEX_SWITCH_TO_5G) 2169 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND); 2170 else if (type == COEX_SWITCH_TO_24G_NOFORSCAN) 2171 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND); 2172 else 2173 rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G); 2174 } 2175 2176 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type) 2177 { 2178 struct rtw_coex *coex = &rtwdev->coex; 2179 struct rtw_coex_stat *coex_stat = &coex->stat; 2180 2181 if (coex->stop_dm) 2182 return; 2183 2184 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN | 2185 COEX_SCBD_ONOFF, true); 2186 2187 if (type == COEX_ASSOCIATE_5G_START) { 2188 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 2189 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART); 2190 } else if (type == COEX_ASSOCIATE_5G_FINISH) { 2191 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 2192 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH); 2193 } else if (type == COEX_ASSOCIATE_START) { 2194 coex_stat->wl_hi_pri_task1 = true; 2195 coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2; 2196 2197 /* Force antenna setup for no scan result issue */ 2198 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 2199 2200 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART); 2201 2202 /* To keep TDMA case during connect process, 2203 * to avoid changed by Btinfo and runcoexmechanism 2204 */ 2205 coex->freeze = true; 2206 ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work, 2207 5 * HZ); 2208 } else { 2209 coex_stat->wl_hi_pri_task1 = false; 2210 coex->freeze = false; 2211 2212 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH); 2213 } 2214 } 2215 2216 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type) 2217 { 2218 struct rtw_coex *coex = &rtwdev->coex; 2219 struct rtw_coex_stat *coex_stat = &coex->stat; 2220 u8 para[6] = {0}; 2221 2222 if (coex->stop_dm) 2223 return; 2224 2225 if (type == COEX_MEDIA_CONNECT_5G) { 2226 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 2227 2228 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 2229 rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA); 2230 } else if (type == COEX_MEDIA_CONNECT) { 2231 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true); 2232 2233 /* Force antenna setup for no scan result issue */ 2234 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 2235 2236 /* Set CCK Rx high Pri */ 2237 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1); 2238 2239 /* always enable 5ms extend if connect */ 2240 para[0] = COEX_H2C69_WL_LEAKAP; 2241 para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */ 2242 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]); 2243 coex_stat->wl_slot_extend = true; 2244 rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA); 2245 } else { 2246 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false); 2247 2248 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0); 2249 2250 rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON); 2251 } 2252 2253 rtw_coex_update_wl_ch_info(rtwdev, type); 2254 } 2255 2256 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) 2257 { 2258 struct rtw_coex *coex = &rtwdev->coex; 2259 struct rtw_coex_stat *coex_stat = &coex->stat; 2260 struct rtw_chip_info *chip = rtwdev->chip; 2261 unsigned long bt_relink_time; 2262 u8 i, rsp_source = 0, type; 2263 2264 rsp_source = buf[0] & 0xf; 2265 if (rsp_source >= COEX_BTINFO_SRC_MAX) 2266 rsp_source = COEX_BTINFO_SRC_WL_FW; 2267 2268 if (rsp_source == COEX_BTINFO_SRC_BT_IQK) { 2269 coex_stat->bt_iqk_state = buf[1]; 2270 if (coex_stat->bt_iqk_state == 1) 2271 coex_stat->cnt_bt[COEX_CNT_BT_IQK]++; 2272 else if (coex_stat->bt_iqk_state == 2) 2273 coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++; 2274 2275 return; 2276 } 2277 2278 if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) { 2279 rtw_coex_monitor_bt_enable(rtwdev); 2280 if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) { 2281 coex_stat->bt_disabled_pre = coex_stat->bt_disabled; 2282 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); 2283 } 2284 return; 2285 } 2286 2287 if (rsp_source == COEX_BTINFO_SRC_BT_RSP || 2288 rsp_source == COEX_BTINFO_SRC_BT_ACT) { 2289 if (coex_stat->bt_disabled) { 2290 coex_stat->bt_disabled = false; 2291 coex_stat->bt_reenable = true; 2292 ieee80211_queue_delayed_work(rtwdev->hw, 2293 &coex->bt_reenable_work, 2294 15 * HZ); 2295 } 2296 } 2297 2298 for (i = 0; i < length; i++) { 2299 if (i < COEX_BTINFO_LENGTH_MAX) 2300 coex_stat->bt_info_c2h[rsp_source][i] = buf[i]; 2301 else 2302 break; 2303 } 2304 2305 if (rsp_source == COEX_BTINFO_SRC_WL_FW) { 2306 rtw_coex_update_bt_link_info(rtwdev); 2307 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); 2308 return; 2309 } 2310 2311 /* get the same info from bt, skip it */ 2312 if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 && 2313 coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 && 2314 coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 && 2315 coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 && 2316 coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 && 2317 coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3) 2318 return; 2319 2320 coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1]; 2321 coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2]; 2322 coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3]; 2323 coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4]; 2324 coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5]; 2325 coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6]; 2326 2327 /* 0xff means BT is under WHCK test */ 2328 coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff); 2329 coex_stat->bt_inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2)); 2330 coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3)); 2331 coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf; 2332 if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1) 2333 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++; 2334 2335 coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4)); 2336 coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5)); 2337 if (coex_stat->bt_inq) 2338 coex_stat->cnt_bt[COEX_CNT_BT_INQ]++; 2339 2340 coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7)); 2341 if (coex_stat->bt_page) { 2342 coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++; 2343 if (coex_stat->wl_linkscan_proc || 2344 coex_stat->wl_hi_pri_task1 || 2345 coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy) 2346 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true); 2347 else 2348 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); 2349 } else { 2350 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false); 2351 } 2352 2353 /* unit: % (value-100 to translate to unit: dBm in coex info) */ 2354 if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) { 2355 coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10; 2356 } else { /* original unit: dbm -> unit: % -> value-100 in coex info */ 2357 if (coex_stat->bt_info_hb0 <= 127) 2358 coex_stat->bt_rssi = 100; 2359 else if (256 - coex_stat->bt_info_hb0 <= 100) 2360 coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0); 2361 else 2362 coex_stat->bt_rssi = 0; 2363 } 2364 2365 coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0)); 2366 if (coex_stat->bt_info_hb1 & BIT(1)) 2367 coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++; 2368 2369 if (coex_stat->bt_info_hb1 & BIT(2)) { 2370 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++; 2371 coex_stat->bt_setup_link = true; 2372 if (coex_stat->bt_reenable) 2373 bt_relink_time = 6 * HZ; 2374 else 2375 bt_relink_time = 2 * HZ; 2376 2377 ieee80211_queue_delayed_work(rtwdev->hw, 2378 &coex->bt_relink_work, 2379 bt_relink_time); 2380 } 2381 2382 if (coex_stat->bt_info_hb1 & BIT(3)) 2383 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++; 2384 2385 coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4)); 2386 coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5)); 2387 if (coex_stat->bt_info_hb1 & BIT(6)) 2388 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++; 2389 2390 coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7)); 2391 /* resend wifi info to bt, it is reset and lost the info */ 2392 if ((coex_stat->bt_info_hb1 & BIT(1))) { 2393 if (coex_stat->wl_connected) 2394 type = COEX_MEDIA_CONNECT; 2395 else 2396 type = COEX_MEDIA_DISCONNECT; 2397 rtw_coex_update_wl_ch_info(rtwdev, type); 2398 } 2399 2400 /* if ignore_wlan_act && not set_up_link */ 2401 if ((coex_stat->bt_info_hb1 & BIT(3)) && 2402 (!(coex_stat->bt_info_hb1 & BIT(2)))) 2403 rtw_coex_ignore_wlan_act(rtwdev, false); 2404 2405 coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0)); 2406 if (coex_stat->bt_info_hb2 & BIT(1)) 2407 coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++; 2408 2409 coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2); 2410 coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3)); 2411 coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4; 2412 coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6; 2413 if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2) 2414 coex_stat->bt_418_hid_exist = true; 2415 else if (coex_stat->bt_hid_pair_num == 0) 2416 coex_stat->bt_418_hid_exist = false; 2417 2418 if ((coex_stat->bt_info_lb2 & 0x49) == 0x49) 2419 coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f); 2420 else 2421 coex_stat->bt_a2dp_bitpool = 0; 2422 2423 coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7)); 2424 2425 rtw_coex_update_bt_link_info(rtwdev); 2426 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO); 2427 } 2428 2429 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length) 2430 { 2431 struct rtw_coex *coex = &rtwdev->coex; 2432 struct rtw_coex_stat *coex_stat = &coex->stat; 2433 u8 val; 2434 int i; 2435 2436 if (WARN(length < 8, "invalid wl info c2h length\n")) 2437 return; 2438 2439 if (buf[0] != 0x08) 2440 return; 2441 2442 for (i = 1; i < 8; i++) { 2443 val = coex_stat->wl_fw_dbg_info_pre[i]; 2444 if (buf[i] >= val) 2445 coex_stat->wl_fw_dbg_info[i] = buf[i] - val; 2446 else 2447 coex_stat->wl_fw_dbg_info[i] = val - buf[i]; 2448 2449 coex_stat->wl_fw_dbg_info_pre[i] = buf[i]; 2450 } 2451 2452 coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++; 2453 rtw_coex_wl_ccklock_action(rtwdev); 2454 rtw_coex_wl_ccklock_detect(rtwdev); 2455 } 2456 2457 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev) 2458 { 2459 struct rtw_coex *coex = &rtwdev->coex; 2460 2461 if (coex->stop_dm) 2462 return; 2463 2464 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 2465 } 2466 2467 void rtw_coex_bt_relink_work(struct work_struct *work) 2468 { 2469 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 2470 coex.bt_relink_work.work); 2471 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 2472 2473 mutex_lock(&rtwdev->mutex); 2474 coex_stat->bt_setup_link = false; 2475 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 2476 mutex_unlock(&rtwdev->mutex); 2477 } 2478 2479 void rtw_coex_bt_reenable_work(struct work_struct *work) 2480 { 2481 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 2482 coex.bt_reenable_work.work); 2483 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 2484 2485 mutex_lock(&rtwdev->mutex); 2486 coex_stat->bt_reenable = false; 2487 mutex_unlock(&rtwdev->mutex); 2488 } 2489 2490 void rtw_coex_defreeze_work(struct work_struct *work) 2491 { 2492 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev, 2493 coex.defreeze_work.work); 2494 struct rtw_coex *coex = &rtwdev->coex; 2495 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat; 2496 2497 mutex_lock(&rtwdev->mutex); 2498 coex->freeze = false; 2499 coex_stat->wl_hi_pri_task1 = false; 2500 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS); 2501 mutex_unlock(&rtwdev->mutex); 2502 } 2503