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 = rtw_flag_check(rtwdev, RTW_FLAG_SCANNING); 387 coex_stat->wl_connected = !!rtwdev->sta_cnt; 388 coex_stat->wl_gl_busy = rtw_flag_check(rtwdev, RTW_FLAG_BUSY_TRAFFIC); 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_lps_conf *lps_conf = &rtwdev->lps_conf; 814 struct rtw_vif *rtwvif; 815 struct rtw_coex *coex = &rtwdev->coex; 816 struct rtw_coex_stat *coex_stat = &coex->stat; 817 u8 lps_mode = 0x0; 818 819 lps_mode = rtwdev->lps_conf.mode; 820 821 switch (ps_type) { 822 case COEX_PS_WIFI_NATIVE: 823 /* recover to original 32k low power setting */ 824 coex_stat->wl_force_lps_ctrl = false; 825 826 rtwvif = lps_conf->rtwvif; 827 if (rtwvif && rtw_in_lps(rtwdev)) 828 rtw_leave_lps(rtwdev, rtwvif); 829 break; 830 case COEX_PS_LPS_OFF: 831 coex_stat->wl_force_lps_ctrl = true; 832 if (lps_mode) 833 rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0); 834 835 rtwvif = lps_conf->rtwvif; 836 if (rtwvif && rtw_in_lps(rtwdev)) 837 rtw_leave_lps(rtwdev, rtwvif); 838 break; 839 default: 840 break; 841 } 842 } 843 844 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2, 845 u8 byte3, u8 byte4, u8 byte5) 846 { 847 struct rtw_coex *coex = &rtwdev->coex; 848 struct rtw_coex_dm *coex_dm = &coex->dm; 849 struct rtw_chip_info *chip = rtwdev->chip; 850 u8 ps_type = COEX_PS_WIFI_NATIVE; 851 bool ap_enable = false; 852 853 if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) { 854 byte1 &= ~BIT(4); 855 byte1 |= BIT(5); 856 857 byte5 |= BIT(5); 858 byte5 &= ~BIT(6); 859 860 ps_type = COEX_PS_WIFI_NATIVE; 861 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); 862 } else if (byte1 & BIT(4) && !(byte1 & BIT(5))) { 863 if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF) 864 ps_type = COEX_PS_LPS_OFF; 865 else 866 ps_type = COEX_PS_LPS_ON; 867 rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4); 868 } else { 869 ps_type = COEX_PS_WIFI_NATIVE; 870 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0); 871 } 872 873 coex_dm->ps_tdma_para[0] = byte1; 874 coex_dm->ps_tdma_para[1] = byte2; 875 coex_dm->ps_tdma_para[2] = byte3; 876 coex_dm->ps_tdma_para[3] = byte4; 877 coex_dm->ps_tdma_para[4] = byte5; 878 879 rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5); 880 } 881 882 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase) 883 { 884 struct rtw_coex *coex = &rtwdev->coex; 885 struct rtw_coex_dm *coex_dm = &coex->dm; 886 struct rtw_chip_info *chip = rtwdev->chip; 887 struct rtw_efuse *efuse = &rtwdev->efuse; 888 u8 n, type; 889 bool turn_on; 890 891 if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */ 892 rtw_coex_tdma_timer_base(rtwdev, 3); 893 else 894 rtw_coex_tdma_timer_base(rtwdev, 0); 895 896 type = (u8)(tcase & 0xff); 897 898 turn_on = (type == 0 || type == 100) ? false : true; 899 900 if (!force) { 901 if (turn_on == coex_dm->cur_ps_tdma_on && 902 type == coex_dm->cur_ps_tdma) { 903 return; 904 } 905 } 906 907 if (turn_on) { 908 /* enable TBTT interrupt */ 909 rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); 910 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true); 911 } else { 912 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false); 913 } 914 915 if (efuse->share_ant) { 916 if (type < chip->tdma_sant_num) 917 rtw_coex_set_tdma(rtwdev, 918 chip->tdma_sant[type].para[0], 919 chip->tdma_sant[type].para[1], 920 chip->tdma_sant[type].para[2], 921 chip->tdma_sant[type].para[3], 922 chip->tdma_sant[type].para[4]); 923 } else { 924 n = type - 100; 925 if (n < chip->tdma_nsant_num) 926 rtw_coex_set_tdma(rtwdev, 927 chip->tdma_nsant[n].para[0], 928 chip->tdma_nsant[n].para[1], 929 chip->tdma_nsant[n].para[2], 930 chip->tdma_nsant[n].para[3], 931 chip->tdma_nsant[n].para[4]); 932 } 933 934 /* update pre state */ 935 coex_dm->cur_ps_tdma_on = turn_on; 936 coex_dm->cur_ps_tdma = type; 937 938 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type); 939 } 940 941 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase) 942 { 943 struct rtw_coex *coex = &rtwdev->coex; 944 struct rtw_coex_stat *coex_stat = &coex->stat; 945 struct rtw_coex_dm *coex_dm = &coex->dm; 946 u8 ctrl_type = COEX_SWITCH_CTRL_MAX; 947 u8 pos_type = COEX_SWITCH_TO_MAX; 948 949 if (!force && coex_dm->cur_ant_pos_type == phase) 950 return; 951 952 coex_dm->cur_ant_pos_type = phase; 953 954 /* avoid switch coex_ctrl_owner during BT IQK */ 955 rtw_coex_check_rfk(rtwdev); 956 957 switch (phase) { 958 case COEX_SET_ANT_POWERON: 959 /* set path control owner to BT at power-on */ 960 if (coex_stat->bt_disabled) 961 rtw_coex_coex_ctrl_owner(rtwdev, true); 962 else 963 rtw_coex_coex_ctrl_owner(rtwdev, false); 964 965 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 966 pos_type = COEX_SWITCH_TO_BT; 967 break; 968 case COEX_SET_ANT_INIT: 969 if (coex_stat->bt_disabled) { 970 /* set GNT_BT to SW low */ 971 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); 972 973 /* set GNT_WL to SW high */ 974 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 975 } else { 976 /* set GNT_BT to SW high */ 977 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 978 979 /* set GNT_WL to SW low */ 980 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW); 981 } 982 983 /* set path control owner to wl at initial step */ 984 rtw_coex_coex_ctrl_owner(rtwdev, true); 985 986 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 987 pos_type = COEX_SWITCH_TO_BT; 988 break; 989 case COEX_SET_ANT_WONLY: 990 /* set GNT_BT to SW Low */ 991 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW); 992 993 /* Set GNT_WL to SW high */ 994 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 995 996 /* set path control owner to wl at initial step */ 997 rtw_coex_coex_ctrl_owner(rtwdev, true); 998 999 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1000 pos_type = COEX_SWITCH_TO_WLG; 1001 break; 1002 case COEX_SET_ANT_WOFF: 1003 /* set path control owner to BT */ 1004 rtw_coex_coex_ctrl_owner(rtwdev, false); 1005 1006 ctrl_type = COEX_SWITCH_CTRL_BY_BT; 1007 pos_type = COEX_SWITCH_TO_NOCARE; 1008 break; 1009 case COEX_SET_ANT_2G: 1010 /* set GNT_BT to PTA */ 1011 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 1012 1013 /* set GNT_WL to PTA */ 1014 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); 1015 1016 /* set path control owner to wl at runtime step */ 1017 rtw_coex_coex_ctrl_owner(rtwdev, true); 1018 1019 ctrl_type = COEX_SWITCH_CTRL_BY_PTA; 1020 pos_type = COEX_SWITCH_TO_NOCARE; 1021 break; 1022 case COEX_SET_ANT_5G: 1023 /* set GNT_BT to PTA */ 1024 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 1025 1026 /* set GNT_WL to SW high */ 1027 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 1028 1029 /* set path control owner to wl at runtime step */ 1030 rtw_coex_coex_ctrl_owner(rtwdev, true); 1031 1032 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1033 pos_type = COEX_SWITCH_TO_WLA; 1034 break; 1035 case COEX_SET_ANT_2G_FREERUN: 1036 /* set GNT_BT to SW high */ 1037 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH); 1038 1039 /* Set GNT_WL to SW high */ 1040 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH); 1041 1042 /* set path control owner to wl at runtime step */ 1043 rtw_coex_coex_ctrl_owner(rtwdev, true); 1044 1045 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1046 pos_type = COEX_SWITCH_TO_WLG_BT; 1047 break; 1048 case COEX_SET_ANT_2G_WLBT: 1049 /* set GNT_BT to SW high */ 1050 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA); 1051 1052 /* Set GNT_WL to SW high */ 1053 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA); 1054 1055 /* set path control owner to wl at runtime step */ 1056 rtw_coex_coex_ctrl_owner(rtwdev, true); 1057 1058 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW; 1059 pos_type = COEX_SWITCH_TO_WLG_BT; 1060 break; 1061 default: 1062 WARN(1, "unknown phase when setting antenna path\n"); 1063 return; 1064 } 1065 1066 if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX) 1067 rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type); 1068 } 1069 1070 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev) 1071 { 1072 struct rtw_coex *coex = &rtwdev->coex; 1073 struct rtw_coex_stat *coex_stat = &coex->stat; 1074 u8 algorithm = COEX_ALGO_NOPROFILE; 1075 u8 profile_map = 0; 1076 1077 if (coex_stat->bt_hfp_exist) 1078 profile_map |= BPM_HFP; 1079 if (coex_stat->bt_hid_exist) 1080 profile_map |= BPM_HID; 1081 if (coex_stat->bt_a2dp_exist) 1082 profile_map |= BPM_A2DP; 1083 if (coex_stat->bt_pan_exist) 1084 profile_map |= BPM_PAN; 1085 1086 switch (profile_map) { 1087 case BPM_HFP: 1088 algorithm = COEX_ALGO_HFP; 1089 break; 1090 case BPM_HID: 1091 case BPM_HFP + BPM_HID: 1092 algorithm = COEX_ALGO_HID; 1093 break; 1094 case BPM_HFP + BPM_A2DP: 1095 case BPM_HID + BPM_A2DP: 1096 case BPM_HFP + BPM_HID + BPM_A2DP: 1097 algorithm = COEX_ALGO_A2DP_HID; 1098 break; 1099 case BPM_HFP + BPM_PAN: 1100 case BPM_HID + BPM_PAN: 1101 case BPM_HFP + BPM_HID + BPM_PAN: 1102 algorithm = COEX_ALGO_PAN_HID; 1103 break; 1104 case BPM_HFP + BPM_A2DP + BPM_PAN: 1105 case BPM_HID + BPM_A2DP + BPM_PAN: 1106 case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN: 1107 algorithm = COEX_ALGO_A2DP_PAN_HID; 1108 break; 1109 case BPM_PAN: 1110 algorithm = COEX_ALGO_PAN; 1111 break; 1112 case BPM_A2DP + BPM_PAN: 1113 algorithm = COEX_ALGO_A2DP_PAN; 1114 break; 1115 case BPM_A2DP: 1116 if (coex_stat->bt_multi_link) { 1117 if (coex_stat->bt_hid_pair_num > 0) 1118 algorithm = COEX_ALGO_A2DP_HID; 1119 else 1120 algorithm = COEX_ALGO_A2DP_PAN; 1121 } else { 1122 algorithm = COEX_ALGO_A2DP; 1123 } 1124 break; 1125 default: 1126 algorithm = COEX_ALGO_NOPROFILE; 1127 break; 1128 } 1129 1130 return algorithm; 1131 } 1132 1133 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev) 1134 { 1135 struct rtw_efuse *efuse = &rtwdev->efuse; 1136 struct rtw_chip_info *chip = rtwdev->chip; 1137 u8 table_case, tdma_case; 1138 1139 if (efuse->share_ant) { 1140 /* Shared-Ant */ 1141 table_case = 2; 1142 tdma_case = 0; 1143 } else { 1144 /* Non-Shared-Ant */ 1145 table_case = 100; 1146 tdma_case = 100; 1147 } 1148 1149 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1150 rtw_coex_table(rtwdev, table_case); 1151 rtw_coex_tdma(rtwdev, false, tdma_case); 1152 } 1153 1154 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev) 1155 { 1156 struct rtw_coex *coex = &rtwdev->coex; 1157 struct rtw_coex_stat *coex_stat = &coex->stat; 1158 struct rtw_coex_dm *coex_dm = &coex->dm; 1159 struct rtw_efuse *efuse = &rtwdev->efuse; 1160 struct rtw_chip_info *chip = rtwdev->chip; 1161 u8 level = 0; 1162 1163 if (efuse->share_ant) 1164 return; 1165 1166 coex->freerun = true; 1167 1168 if (coex_stat->wl_connected) 1169 rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT); 1170 1171 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); 1172 1173 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 1174 1175 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0])) 1176 level = 2; 1177 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 1178 level = 3; 1179 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2])) 1180 level = 4; 1181 else 1182 level = 5; 1183 1184 if (level > chip->wl_rf_para_num - 1) 1185 level = chip->wl_rf_para_num - 1; 1186 1187 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX) 1188 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]); 1189 else 1190 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]); 1191 1192 rtw_coex_table(rtwdev, 100); 1193 rtw_coex_tdma(rtwdev, false, 100); 1194 } 1195 1196 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev) 1197 { 1198 struct rtw_efuse *efuse = &rtwdev->efuse; 1199 struct rtw_chip_info *chip = rtwdev->chip; 1200 u8 table_case, tdma_case; 1201 1202 if (efuse->share_ant) { 1203 /* Shared-Ant */ 1204 table_case = 2; 1205 tdma_case = 0; 1206 } else { 1207 /* Non-Shared-Ant */ 1208 table_case = 100; 1209 tdma_case = 100; 1210 } 1211 1212 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1213 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1214 rtw_coex_table(rtwdev, table_case); 1215 rtw_coex_tdma(rtwdev, false, tdma_case); 1216 } 1217 1218 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev) 1219 { 1220 struct rtw_efuse *efuse = &rtwdev->efuse; 1221 struct rtw_chip_info *chip = rtwdev->chip; 1222 u8 table_case, tdma_case; 1223 1224 if (efuse->share_ant) { 1225 /* Shared-Ant */ 1226 table_case = 1; 1227 tdma_case = 0; 1228 } else { 1229 /* Non-Shared-Ant */ 1230 table_case = 100; 1231 tdma_case = 100; 1232 } 1233 1234 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1235 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1236 rtw_coex_table(rtwdev, table_case); 1237 rtw_coex_tdma(rtwdev, false, tdma_case); 1238 } 1239 1240 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev) 1241 { 1242 struct rtw_coex *coex = &rtwdev->coex; 1243 struct rtw_coex_stat *coex_stat = &coex->stat; 1244 struct rtw_coex_dm *coex_dm = &coex->dm; 1245 struct rtw_efuse *efuse = &rtwdev->efuse; 1246 struct rtw_chip_info *chip = rtwdev->chip; 1247 struct rtw_coex_rfe *coex_rfe = &coex->rfe; 1248 u8 table_case = 0xff, tdma_case = 0xff; 1249 1250 if (coex_rfe->ant_switch_with_bt && 1251 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 1252 if (efuse->share_ant && 1253 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) { 1254 table_case = 0; 1255 tdma_case = 0; 1256 } else if (!efuse->share_ant) { 1257 table_case = 100; 1258 tdma_case = 100; 1259 } 1260 } 1261 1262 if (table_case != 0xff && tdma_case != 0xff) { 1263 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN); 1264 rtw_coex_table(rtwdev, table_case); 1265 rtw_coex_tdma(rtwdev, false, tdma_case); 1266 return; 1267 } 1268 1269 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1270 1271 if (efuse->share_ant) { 1272 /* Shared-Ant */ 1273 if (!coex_stat->wl_gl_busy) { 1274 table_case = 10; 1275 tdma_case = 3; 1276 } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 1277 table_case = 6; 1278 tdma_case = 7; 1279 } else { 1280 table_case = 12; 1281 tdma_case = 7; 1282 } 1283 } else { 1284 /* Non-Shared-Ant */ 1285 if (!coex_stat->wl_gl_busy) { 1286 table_case = 112; 1287 tdma_case = 104; 1288 } else if ((coex_stat->bt_ble_scan_type & 0x2) && 1289 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) { 1290 table_case = 114; 1291 tdma_case = 103; 1292 } else { 1293 table_case = 112; 1294 tdma_case = 103; 1295 } 1296 } 1297 1298 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1299 rtw_coex_table(rtwdev, table_case); 1300 rtw_coex_tdma(rtwdev, false, tdma_case); 1301 } 1302 1303 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev) 1304 { 1305 struct rtw_coex *coex = &rtwdev->coex; 1306 struct rtw_coex_stat *coex_stat = &coex->stat; 1307 struct rtw_efuse *efuse = &rtwdev->efuse; 1308 struct rtw_chip_info *chip = rtwdev->chip; 1309 bool wl_hi_pri = false; 1310 u8 table_case, tdma_case; 1311 1312 if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 || 1313 coex_stat->wl_hi_pri_task2) 1314 wl_hi_pri = true; 1315 1316 if (efuse->share_ant) { 1317 /* Shared-Ant */ 1318 if (wl_hi_pri) { 1319 table_case = 15; 1320 if (coex_stat->bt_a2dp_exist && 1321 !coex_stat->bt_pan_exist) 1322 tdma_case = 11; 1323 else if (coex_stat->wl_hi_pri_task1) 1324 tdma_case = 6; 1325 else if (!coex_stat->bt_page) 1326 tdma_case = 8; 1327 else 1328 tdma_case = 9; 1329 } else if (coex_stat->wl_connected) { 1330 table_case = 10; 1331 tdma_case = 10; 1332 } else { 1333 table_case = 1; 1334 tdma_case = 0; 1335 } 1336 } else { 1337 /* Non_Shared-Ant */ 1338 if (wl_hi_pri) { 1339 table_case = 113; 1340 if (coex_stat->bt_a2dp_exist && 1341 !coex_stat->bt_pan_exist) 1342 tdma_case = 111; 1343 else if (coex_stat->wl_hi_pri_task1) 1344 tdma_case = 106; 1345 else if (!coex_stat->bt_page) 1346 tdma_case = 108; 1347 else 1348 tdma_case = 109; 1349 } else if (coex_stat->wl_connected) { 1350 table_case = 101; 1351 tdma_case = 110; 1352 } else { 1353 table_case = 100; 1354 tdma_case = 100; 1355 } 1356 } 1357 1358 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n", 1359 wl_hi_pri, coex_stat->bt_page); 1360 1361 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1362 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1363 rtw_coex_table(rtwdev, table_case); 1364 rtw_coex_tdma(rtwdev, false, tdma_case); 1365 } 1366 1367 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev) 1368 { 1369 struct rtw_coex *coex = &rtwdev->coex; 1370 struct rtw_coex_stat *coex_stat = &coex->stat; 1371 struct rtw_efuse *efuse = &rtwdev->efuse; 1372 struct rtw_chip_info *chip = rtwdev->chip; 1373 u8 table_case, tdma_case; 1374 1375 if (efuse->share_ant) { 1376 /* Shared-Ant */ 1377 if (coex_stat->bt_multi_link) { 1378 table_case = 10; 1379 tdma_case = 17; 1380 } else { 1381 table_case = 10; 1382 tdma_case = 5; 1383 } 1384 } else { 1385 /* Non-Shared-Ant */ 1386 if (coex_stat->bt_multi_link) { 1387 table_case = 112; 1388 tdma_case = 117; 1389 } else { 1390 table_case = 105; 1391 tdma_case = 100; 1392 } 1393 } 1394 1395 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1396 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1397 rtw_coex_table(rtwdev, table_case); 1398 rtw_coex_tdma(rtwdev, false, tdma_case); 1399 } 1400 1401 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev) 1402 { 1403 struct rtw_coex *coex = &rtwdev->coex; 1404 struct rtw_coex_stat *coex_stat = &coex->stat; 1405 struct rtw_efuse *efuse = &rtwdev->efuse; 1406 struct rtw_chip_info *chip = rtwdev->chip; 1407 u8 table_case, tdma_case; 1408 u32 wl_bw; 1409 1410 wl_bw = rtwdev->hal.current_band_width; 1411 1412 if (efuse->share_ant) { 1413 /* Shared-Ant */ 1414 if (coex_stat->bt_ble_exist) { 1415 /* RCU */ 1416 if (!coex_stat->wl_gl_busy) 1417 table_case = 14; 1418 else 1419 table_case = 15; 1420 1421 if (coex_stat->bt_a2dp_active || wl_bw == 0) 1422 tdma_case = 18; 1423 else if (coex_stat->wl_gl_busy) 1424 tdma_case = 8; 1425 else 1426 tdma_case = 4; 1427 } else { 1428 if (coex_stat->bt_a2dp_active || wl_bw == 0) { 1429 table_case = 8; 1430 tdma_case = 4; 1431 } else { 1432 /* for 4/18 HID */ 1433 if (coex_stat->bt_418_hid_exist && 1434 coex_stat->wl_gl_busy) 1435 table_case = 12; 1436 else 1437 table_case = 10; 1438 tdma_case = 4; 1439 } 1440 } 1441 } else { 1442 /* Non-Shared-Ant */ 1443 if (coex_stat->bt_a2dp_active) { 1444 table_case = 113; 1445 tdma_case = 118; 1446 } else if (coex_stat->bt_ble_exist) { 1447 /* BLE */ 1448 table_case = 113; 1449 1450 if (coex_stat->wl_gl_busy) 1451 tdma_case = 106; 1452 else 1453 tdma_case = 104; 1454 } else { 1455 table_case = 113; 1456 tdma_case = 104; 1457 } 1458 } 1459 1460 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1461 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1462 rtw_coex_table(rtwdev, table_case); 1463 rtw_coex_tdma(rtwdev, false, tdma_case); 1464 } 1465 1466 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev) 1467 { 1468 struct rtw_coex *coex = &rtwdev->coex; 1469 struct rtw_coex_stat *coex_stat = &coex->stat; 1470 struct rtw_coex_dm *coex_dm = &coex->dm; 1471 struct rtw_efuse *efuse = &rtwdev->efuse; 1472 struct rtw_chip_info *chip = rtwdev->chip; 1473 u8 table_case, tdma_case; 1474 u32 slot_type = 0; 1475 1476 if (efuse->share_ant) { 1477 /* Shared-Ant */ 1478 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) 1479 table_case = 10; 1480 else 1481 table_case = 9; 1482 1483 slot_type = TDMA_4SLOT; 1484 1485 if (coex_stat->wl_gl_busy) 1486 tdma_case = 13; 1487 else 1488 tdma_case = 14; 1489 } else { 1490 /* Non-Shared-Ant */ 1491 table_case = 112; 1492 1493 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 1494 tdma_case = 112; 1495 else 1496 tdma_case = 113; 1497 } 1498 1499 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1500 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1501 rtw_coex_table(rtwdev, table_case); 1502 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1503 } 1504 1505 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev) 1506 { 1507 struct rtw_coex *coex = &rtwdev->coex; 1508 struct rtw_coex_stat *coex_stat = &coex->stat; 1509 struct rtw_efuse *efuse = &rtwdev->efuse; 1510 struct rtw_chip_info *chip = rtwdev->chip; 1511 u8 table_case, tdma_case; 1512 bool ap_enable = false; 1513 1514 if (efuse->share_ant) { /* Shared-Ant */ 1515 if (ap_enable) { 1516 table_case = 2; 1517 tdma_case = 0; 1518 } else if (coex_stat->wl_gl_busy) { 1519 table_case = 28; 1520 tdma_case = 20; 1521 } else { 1522 table_case = 28; 1523 tdma_case = 26; 1524 } 1525 } else { /* Non-Shared-Ant */ 1526 if (ap_enable) { 1527 table_case = 100; 1528 tdma_case = 100; 1529 } else { 1530 table_case = 119; 1531 tdma_case = 120; 1532 } 1533 } 1534 1535 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1536 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1537 rtw_coex_table(rtwdev, table_case); 1538 rtw_coex_tdma(rtwdev, false, tdma_case); 1539 } 1540 1541 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev) 1542 { 1543 struct rtw_coex *coex = &rtwdev->coex; 1544 struct rtw_coex_stat *coex_stat = &coex->stat; 1545 struct rtw_efuse *efuse = &rtwdev->efuse; 1546 struct rtw_chip_info *chip = rtwdev->chip; 1547 u8 table_case, tdma_case; 1548 1549 if (efuse->share_ant) { 1550 /* Shared-Ant */ 1551 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0) 1552 table_case = 14; 1553 else 1554 table_case = 10; 1555 1556 if (coex_stat->wl_gl_busy) 1557 tdma_case = 17; 1558 else 1559 tdma_case = 19; 1560 } else { 1561 /* Non-Shared-Ant */ 1562 table_case = 112; 1563 1564 if (coex_stat->wl_gl_busy) 1565 tdma_case = 117; 1566 else 1567 tdma_case = 119; 1568 } 1569 1570 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1571 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1572 rtw_coex_table(rtwdev, table_case); 1573 rtw_coex_tdma(rtwdev, false, tdma_case); 1574 } 1575 1576 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev) 1577 { 1578 struct rtw_coex *coex = &rtwdev->coex; 1579 struct rtw_coex_stat *coex_stat = &coex->stat; 1580 struct rtw_coex_dm *coex_dm = &coex->dm; 1581 struct rtw_efuse *efuse = &rtwdev->efuse; 1582 struct rtw_chip_info *chip = rtwdev->chip; 1583 u8 table_case, tdma_case; 1584 u32 slot_type = 0; 1585 1586 if (efuse->share_ant) { 1587 /* Shared-Ant */ 1588 if (coex_stat->bt_ble_exist) 1589 table_case = 26; 1590 else 1591 table_case = 9; 1592 1593 if (coex_stat->wl_gl_busy) { 1594 slot_type = TDMA_4SLOT; 1595 tdma_case = 13; 1596 } else { 1597 tdma_case = 14; 1598 } 1599 } else { 1600 /* Non-Shared-Ant */ 1601 if (coex_stat->bt_ble_exist) 1602 table_case = 121; 1603 else 1604 table_case = 113; 1605 1606 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) 1607 tdma_case = 112; 1608 else 1609 tdma_case = 113; 1610 } 1611 1612 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1613 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1614 rtw_coex_table(rtwdev, table_case); 1615 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type); 1616 } 1617 1618 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev) 1619 { 1620 struct rtw_coex *coex = &rtwdev->coex; 1621 struct rtw_coex_stat *coex_stat = &coex->stat; 1622 struct rtw_efuse *efuse = &rtwdev->efuse; 1623 struct rtw_chip_info *chip = rtwdev->chip; 1624 u8 table_case, tdma_case; 1625 1626 if (efuse->share_ant) { 1627 /* Shared-Ant */ 1628 if (coex_stat->wl_gl_busy && 1629 coex_stat->wl_noisy_level == 0) 1630 table_case = 14; 1631 else 1632 table_case = 10; 1633 1634 if (coex_stat->wl_gl_busy) 1635 tdma_case = 15; 1636 else 1637 tdma_case = 20; 1638 } else { 1639 /* Non-Shared-Ant */ 1640 table_case = 112; 1641 1642 if (coex_stat->wl_gl_busy) 1643 tdma_case = 115; 1644 else 1645 tdma_case = 120; 1646 } 1647 1648 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1649 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1650 rtw_coex_table(rtwdev, table_case); 1651 rtw_coex_tdma(rtwdev, false, tdma_case); 1652 } 1653 1654 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev) 1655 { 1656 struct rtw_coex *coex = &rtwdev->coex; 1657 struct rtw_coex_stat *coex_stat = &coex->stat; 1658 struct rtw_efuse *efuse = &rtwdev->efuse; 1659 struct rtw_chip_info *chip = rtwdev->chip; 1660 u8 table_case, tdma_case; 1661 1662 if (efuse->share_ant) { 1663 /* Shared-Ant */ 1664 table_case = 9; 1665 1666 if (coex_stat->wl_gl_busy) 1667 tdma_case = 18; 1668 else 1669 tdma_case = 19; 1670 } else { 1671 /* Non-Shared-Ant */ 1672 table_case = 113; 1673 1674 if (coex_stat->wl_gl_busy) 1675 tdma_case = 117; 1676 else 1677 tdma_case = 119; 1678 } 1679 1680 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1681 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1682 rtw_coex_table(rtwdev, table_case); 1683 rtw_coex_tdma(rtwdev, false, tdma_case); 1684 } 1685 1686 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev) 1687 { 1688 struct rtw_coex *coex = &rtwdev->coex; 1689 struct rtw_coex_stat *coex_stat = &coex->stat; 1690 struct rtw_efuse *efuse = &rtwdev->efuse; 1691 struct rtw_chip_info *chip = rtwdev->chip; 1692 u8 table_case, tdma_case; 1693 1694 if (efuse->share_ant) { 1695 /* Shared-Ant */ 1696 table_case = 10; 1697 1698 if (coex_stat->wl_gl_busy) 1699 tdma_case = 15; 1700 else 1701 tdma_case = 20; 1702 } else { 1703 /* Non-Shared-Ant */ 1704 table_case = 113; 1705 1706 if (coex_stat->wl_gl_busy) 1707 tdma_case = 115; 1708 else 1709 tdma_case = 120; 1710 } 1711 1712 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G); 1713 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1714 rtw_coex_table(rtwdev, table_case); 1715 rtw_coex_tdma(rtwdev, false, tdma_case); 1716 } 1717 1718 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev) 1719 { 1720 struct rtw_efuse *efuse = &rtwdev->efuse; 1721 struct rtw_chip_info *chip = rtwdev->chip; 1722 u8 table_case, tdma_case; 1723 1724 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false); 1725 1726 if (efuse->share_ant) { 1727 /* Shared-Ant */ 1728 table_case = 0; 1729 tdma_case = 0; 1730 } else { 1731 /* Non-Shared-Ant */ 1732 table_case = 100; 1733 tdma_case = 100; 1734 } 1735 1736 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G); 1737 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1738 rtw_coex_table(rtwdev, table_case); 1739 rtw_coex_tdma(rtwdev, false, tdma_case); 1740 } 1741 1742 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev) 1743 { 1744 struct rtw_efuse *efuse = &rtwdev->efuse; 1745 struct rtw_chip_info *chip = rtwdev->chip; 1746 u8 table_case, tdma_case; 1747 1748 if (efuse->share_ant) { 1749 /* Shared-Ant */ 1750 table_case = 2; 1751 tdma_case = 0; 1752 } else { 1753 /* Non-Shared-Ant */ 1754 table_case = 100; 1755 tdma_case = 100; 1756 } 1757 1758 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1759 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1760 rtw_coex_table(rtwdev, table_case); 1761 rtw_coex_tdma(rtwdev, false, tdma_case); 1762 } 1763 1764 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev) 1765 { 1766 struct rtw_coex *coex = &rtwdev->coex; 1767 struct rtw_efuse *efuse = &rtwdev->efuse; 1768 struct rtw_chip_info *chip = rtwdev->chip; 1769 u8 table_case, tdma_case; 1770 1771 if (coex->under_5g) 1772 return; 1773 1774 if (efuse->share_ant) { 1775 /* Shared-Ant */ 1776 table_case = 28; 1777 tdma_case = 0; 1778 } else { 1779 /* Non-Shared-Ant */ 1780 table_case = 100; 1781 tdma_case = 100; 1782 } 1783 1784 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G); 1785 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]); 1786 rtw_coex_table(rtwdev, table_case); 1787 rtw_coex_tdma(rtwdev, false, tdma_case); 1788 } 1789 1790 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev) 1791 { 1792 struct rtw_coex *coex = &rtwdev->coex; 1793 struct rtw_coex_stat *coex_stat = &coex->stat; 1794 struct rtw_efuse *efuse = &rtwdev->efuse; 1795 struct rtw_chip_info *chip = rtwdev->chip; 1796 u8 table_case, tdma_case; 1797 1798 if (efuse->share_ant) { 1799 /* Shared-Ant */ 1800 if (coex_stat->bt_a2dp_exist) { 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); 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