root/drivers/net/wireless/realtek/rtw88/coex.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtw_coex_next_rssi_state
  2. rtw_coex_limited_tx
  3. rtw_coex_limited_wl
  4. rtw_coex_wl_ccklock_action
  5. rtw_coex_wl_ccklock_detect
  6. rtw_coex_wl_noisy_detect
  7. rtw_coex_tdma_timer_base
  8. rtw_coex_set_wl_pri_mask
  9. rtw_coex_write_scbd
  10. rtw_coex_read_scbd
  11. rtw_coex_check_rfk
  12. rtw_coex_query_bt_info
  13. rtw_coex_monitor_bt_enable
  14. rtw_coex_update_wl_link_info
  15. get_payload_from_coex_resp
  16. rtw_coex_info_response
  17. rtw_coex_info_request
  18. rtw_coex_get_bt_scan_type
  19. rtw_coex_set_lna_constrain_level
  20. rtw_coex_update_bt_link_info
  21. rtw_coex_update_wl_ch_info
  22. rtw_coex_set_bt_tx_power
  23. rtw_coex_set_bt_rx_gain
  24. rtw_coex_set_rf_para
  25. rtw_coex_read_indirect_reg
  26. rtw_coex_write_indirect_reg
  27. rtw_coex_coex_ctrl_owner
  28. rtw_coex_set_gnt_bt
  29. rtw_coex_set_gnt_wl
  30. rtw_coex_set_table
  31. rtw_coex_table
  32. rtw_coex_ignore_wlan_act
  33. rtw_coex_power_save_state
  34. rtw_coex_set_tdma
  35. rtw_coex_tdma
  36. rtw_coex_set_ant_path
  37. rtw_coex_algorithm
  38. rtw_coex_action_coex_all_off
  39. rtw_coex_action_freerun
  40. rtw_coex_action_bt_whql_test
  41. rtw_coex_action_bt_relink
  42. rtw_coex_action_bt_idle
  43. rtw_coex_action_bt_inquiry
  44. rtw_coex_action_bt_hfp
  45. rtw_coex_action_bt_hid
  46. rtw_coex_action_bt_a2dp
  47. rtw_coex_action_bt_a2dpsink
  48. rtw_coex_action_bt_pan
  49. rtw_coex_action_bt_a2dp_hid
  50. rtw_coex_action_bt_a2dp_pan
  51. rtw_coex_action_bt_pan_hid
  52. rtw_coex_action_bt_a2dp_pan_hid
  53. rtw_coex_action_wl_under5g
  54. rtw_coex_action_wl_only
  55. rtw_coex_action_wl_native_lps
  56. rtw_coex_action_wl_linkscan
  57. rtw_coex_action_wl_not_connected
  58. rtw_coex_action_wl_connected
  59. rtw_coex_run_coex
  60. rtw_coex_init_coex_var
  61. __rtw_coex_init_hw_config
  62. rtw_coex_power_on_setting
  63. rtw_coex_init_hw_config
  64. rtw_coex_ips_notify
  65. rtw_coex_lps_notify
  66. rtw_coex_scan_notify
  67. rtw_coex_switchband_notify
  68. rtw_coex_connect_notify
  69. rtw_coex_media_status_notify
  70. rtw_coex_bt_info_notify
  71. rtw_coex_wl_fwdbginfo_notify
  72. rtw_coex_wl_status_change_notify
  73. rtw_coex_bt_relink_work
  74. rtw_coex_bt_reenable_work
  75. rtw_coex_defreeze_work

   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], &para[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], &para[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], &para[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], &para[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         u32 slot_type = 0;
1312 
1313         if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
1314             coex_stat->wl_hi_pri_task2)
1315                 wl_hi_pri = true;
1316 
1317         if (efuse->share_ant) {
1318                 /* Shared-Ant */
1319                 if (wl_hi_pri) {
1320                         table_case = 15;
1321                         if (coex_stat->bt_a2dp_exist &&
1322                             !coex_stat->bt_pan_exist) {
1323                                 slot_type = TDMA_4SLOT;
1324                                 tdma_case = 11;
1325                         } else if (coex_stat->wl_hi_pri_task1) {
1326                                 tdma_case = 6;
1327                         } else if (!coex_stat->bt_page) {
1328                                 tdma_case = 8;
1329                         } else {
1330                                 tdma_case = 9;
1331                         }
1332                 } else if (coex_stat->wl_connected) {
1333                         table_case = 10;
1334                         tdma_case = 10;
1335                 } else {
1336                         table_case = 1;
1337                         tdma_case = 0;
1338                 }
1339         } else {
1340                 /* Non_Shared-Ant */
1341                 if (wl_hi_pri) {
1342                         table_case = 113;
1343                         if (coex_stat->bt_a2dp_exist &&
1344                             !coex_stat->bt_pan_exist)
1345                                 tdma_case = 111;
1346                         else if (coex_stat->wl_hi_pri_task1)
1347                                 tdma_case = 106;
1348                         else if (!coex_stat->bt_page)
1349                                 tdma_case = 108;
1350                         else
1351                                 tdma_case = 109;
1352                 } else if (coex_stat->wl_connected) {
1353                         table_case = 101;
1354                         tdma_case = 110;
1355                 } else {
1356                         table_case = 100;
1357                         tdma_case = 100;
1358                 }
1359         }
1360 
1361         rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n",
1362                 wl_hi_pri, coex_stat->bt_page);
1363 
1364         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1365         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1366         rtw_coex_table(rtwdev, table_case);
1367         rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1368 }
1369 
1370 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
1371 {
1372         struct rtw_coex *coex = &rtwdev->coex;
1373         struct rtw_coex_stat *coex_stat = &coex->stat;
1374         struct rtw_efuse *efuse = &rtwdev->efuse;
1375         struct rtw_chip_info *chip = rtwdev->chip;
1376         u8 table_case, tdma_case;
1377 
1378         if (efuse->share_ant) {
1379                 /* Shared-Ant */
1380                 if (coex_stat->bt_multi_link) {
1381                         table_case = 10;
1382                         tdma_case = 17;
1383                 } else {
1384                         table_case = 10;
1385                         tdma_case = 5;
1386                 }
1387         } else {
1388                 /* Non-Shared-Ant */
1389                 if (coex_stat->bt_multi_link) {
1390                         table_case = 112;
1391                         tdma_case = 117;
1392                 } else {
1393                         table_case = 105;
1394                         tdma_case = 100;
1395                 }
1396         }
1397 
1398         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1399         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1400         rtw_coex_table(rtwdev, table_case);
1401         rtw_coex_tdma(rtwdev, false, tdma_case);
1402 }
1403 
1404 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
1405 {
1406         struct rtw_coex *coex = &rtwdev->coex;
1407         struct rtw_coex_stat *coex_stat = &coex->stat;
1408         struct rtw_efuse *efuse = &rtwdev->efuse;
1409         struct rtw_chip_info *chip = rtwdev->chip;
1410         u8 table_case, tdma_case;
1411         u32 wl_bw;
1412 
1413         wl_bw = rtwdev->hal.current_band_width;
1414 
1415         if (efuse->share_ant) {
1416                 /* Shared-Ant */
1417                 if (coex_stat->bt_ble_exist) {
1418                         /* RCU */
1419                         if (!coex_stat->wl_gl_busy)
1420                                 table_case = 14;
1421                         else
1422                                 table_case = 15;
1423 
1424                         if (coex_stat->bt_a2dp_active || wl_bw == 0)
1425                                 tdma_case = 18;
1426                         else if (coex_stat->wl_gl_busy)
1427                                 tdma_case = 8;
1428                         else
1429                                 tdma_case = 4;
1430                 } else {
1431                         if (coex_stat->bt_a2dp_active || wl_bw == 0) {
1432                                 table_case = 8;
1433                                 tdma_case = 4;
1434                         } else {
1435                                 /* for 4/18 HID */
1436                                 if (coex_stat->bt_418_hid_exist &&
1437                                     coex_stat->wl_gl_busy)
1438                                         table_case = 12;
1439                                 else
1440                                         table_case = 10;
1441                                 tdma_case = 4;
1442                         }
1443                 }
1444         } else {
1445                 /* Non-Shared-Ant */
1446                 if (coex_stat->bt_a2dp_active) {
1447                         table_case = 113;
1448                         tdma_case = 118;
1449                 } else if (coex_stat->bt_ble_exist) {
1450                         /* BLE */
1451                         table_case = 113;
1452 
1453                         if (coex_stat->wl_gl_busy)
1454                                 tdma_case = 106;
1455                         else
1456                                 tdma_case = 104;
1457                 } else {
1458                         table_case = 113;
1459                         tdma_case = 104;
1460                 }
1461         }
1462 
1463         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1464         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1465         rtw_coex_table(rtwdev, table_case);
1466         rtw_coex_tdma(rtwdev, false, tdma_case);
1467 }
1468 
1469 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
1470 {
1471         struct rtw_coex *coex = &rtwdev->coex;
1472         struct rtw_coex_stat *coex_stat = &coex->stat;
1473         struct rtw_coex_dm *coex_dm = &coex->dm;
1474         struct rtw_efuse *efuse = &rtwdev->efuse;
1475         struct rtw_chip_info *chip = rtwdev->chip;
1476         u8 table_case, tdma_case;
1477         u32 slot_type = 0;
1478 
1479         if (efuse->share_ant) {
1480                 /* Shared-Ant */
1481                 slot_type = TDMA_4SLOT;
1482 
1483                 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1484                         table_case = 10;
1485                 else
1486                         table_case = 9;
1487 
1488                 if (coex_stat->wl_gl_busy)
1489                         tdma_case = 13;
1490                 else
1491                         tdma_case = 14;
1492         } else {
1493                 /* Non-Shared-Ant */
1494                 table_case = 112;
1495 
1496                 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1497                         tdma_case = 112;
1498                 else
1499                         tdma_case = 113;
1500         }
1501 
1502         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1503         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1504         rtw_coex_table(rtwdev, table_case);
1505         rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1506 }
1507 
1508 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
1509 {
1510         struct rtw_coex *coex = &rtwdev->coex;
1511         struct rtw_coex_stat *coex_stat = &coex->stat;
1512         struct rtw_efuse *efuse = &rtwdev->efuse;
1513         struct rtw_chip_info *chip = rtwdev->chip;
1514         u8 table_case, tdma_case;
1515         bool ap_enable = false;
1516 
1517         if (efuse->share_ant) { /* Shared-Ant */
1518                 if (ap_enable) {
1519                         table_case = 2;
1520                         tdma_case = 0;
1521                 } else if (coex_stat->wl_gl_busy) {
1522                         table_case = 28;
1523                         tdma_case = 20;
1524                 } else {
1525                         table_case = 28;
1526                         tdma_case = 26;
1527                 }
1528         } else { /* Non-Shared-Ant */
1529                 if (ap_enable) {
1530                         table_case = 100;
1531                         tdma_case = 100;
1532                 } else {
1533                         table_case = 119;
1534                         tdma_case = 120;
1535                 }
1536         }
1537 
1538         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1539         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1540         rtw_coex_table(rtwdev, table_case);
1541         rtw_coex_tdma(rtwdev, false, tdma_case);
1542 }
1543 
1544 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
1545 {
1546         struct rtw_coex *coex = &rtwdev->coex;
1547         struct rtw_coex_stat *coex_stat = &coex->stat;
1548         struct rtw_efuse *efuse = &rtwdev->efuse;
1549         struct rtw_chip_info *chip = rtwdev->chip;
1550         u8 table_case, tdma_case;
1551 
1552         if (efuse->share_ant) {
1553                 /* Shared-Ant */
1554                 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1555                         table_case = 14;
1556                 else
1557                         table_case = 10;
1558 
1559                 if (coex_stat->wl_gl_busy)
1560                         tdma_case = 17;
1561                 else
1562                         tdma_case = 19;
1563         } else {
1564                 /* Non-Shared-Ant */
1565                 table_case = 112;
1566 
1567                 if (coex_stat->wl_gl_busy)
1568                         tdma_case = 117;
1569                 else
1570                         tdma_case = 119;
1571         }
1572 
1573         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1574         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1575         rtw_coex_table(rtwdev, table_case);
1576         rtw_coex_tdma(rtwdev, false, tdma_case);
1577 }
1578 
1579 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
1580 {
1581         struct rtw_coex *coex = &rtwdev->coex;
1582         struct rtw_coex_stat *coex_stat = &coex->stat;
1583         struct rtw_coex_dm *coex_dm = &coex->dm;
1584         struct rtw_efuse *efuse = &rtwdev->efuse;
1585         struct rtw_chip_info *chip = rtwdev->chip;
1586         u8 table_case, tdma_case;
1587         u32 slot_type = 0;
1588 
1589         if (efuse->share_ant) {
1590                 /* Shared-Ant */
1591                 slot_type = TDMA_4SLOT;
1592 
1593                 if (coex_stat->bt_ble_exist)
1594                         table_case = 26;
1595                 else
1596                         table_case = 9;
1597 
1598                 if (coex_stat->wl_gl_busy) {
1599                         tdma_case = 13;
1600                 } else {
1601                         tdma_case = 14;
1602                 }
1603         } else {
1604                 /* Non-Shared-Ant */
1605                 if (coex_stat->bt_ble_exist)
1606                         table_case = 121;
1607                 else
1608                         table_case = 113;
1609 
1610                 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1611                         tdma_case = 112;
1612                 else
1613                         tdma_case = 113;
1614         }
1615 
1616         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1617         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1618         rtw_coex_table(rtwdev, table_case);
1619         rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1620 }
1621 
1622 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
1623 {
1624         struct rtw_coex *coex = &rtwdev->coex;
1625         struct rtw_coex_stat *coex_stat = &coex->stat;
1626         struct rtw_efuse *efuse = &rtwdev->efuse;
1627         struct rtw_chip_info *chip = rtwdev->chip;
1628         u8 table_case, tdma_case;
1629 
1630         if (efuse->share_ant) {
1631                 /* Shared-Ant */
1632                 if (coex_stat->wl_gl_busy &&
1633                     coex_stat->wl_noisy_level == 0)
1634                         table_case = 14;
1635                 else
1636                         table_case = 10;
1637 
1638                 if (coex_stat->wl_gl_busy)
1639                         tdma_case = 15;
1640                 else
1641                         tdma_case = 20;
1642         } else {
1643                 /* Non-Shared-Ant */
1644                 table_case = 112;
1645 
1646                 if (coex_stat->wl_gl_busy)
1647                         tdma_case = 115;
1648                 else
1649                         tdma_case = 120;
1650         }
1651 
1652         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1653         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1654         rtw_coex_table(rtwdev, table_case);
1655         rtw_coex_tdma(rtwdev, false, tdma_case);
1656 }
1657 
1658 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
1659 {
1660         struct rtw_coex *coex = &rtwdev->coex;
1661         struct rtw_coex_stat *coex_stat = &coex->stat;
1662         struct rtw_efuse *efuse = &rtwdev->efuse;
1663         struct rtw_chip_info *chip = rtwdev->chip;
1664         u8 table_case, tdma_case;
1665 
1666         if (efuse->share_ant) {
1667                 /* Shared-Ant */
1668                 table_case = 9;
1669 
1670                 if (coex_stat->wl_gl_busy)
1671                         tdma_case = 18;
1672                 else
1673                         tdma_case = 19;
1674         } else {
1675                 /* Non-Shared-Ant */
1676                 table_case = 113;
1677 
1678                 if (coex_stat->wl_gl_busy)
1679                         tdma_case = 117;
1680                 else
1681                         tdma_case = 119;
1682         }
1683 
1684         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1685         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1686         rtw_coex_table(rtwdev, table_case);
1687         rtw_coex_tdma(rtwdev, false, tdma_case);
1688 }
1689 
1690 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
1691 {
1692         struct rtw_coex *coex = &rtwdev->coex;
1693         struct rtw_coex_stat *coex_stat = &coex->stat;
1694         struct rtw_efuse *efuse = &rtwdev->efuse;
1695         struct rtw_chip_info *chip = rtwdev->chip;
1696         u8 table_case, tdma_case;
1697 
1698         if (efuse->share_ant) {
1699                 /* Shared-Ant */
1700                 table_case = 10;
1701 
1702                 if (coex_stat->wl_gl_busy)
1703                         tdma_case = 15;
1704                 else
1705                         tdma_case = 20;
1706         } else {
1707                 /* Non-Shared-Ant */
1708                 table_case = 113;
1709 
1710                 if (coex_stat->wl_gl_busy)
1711                         tdma_case = 115;
1712                 else
1713                         tdma_case = 120;
1714         }
1715 
1716         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1717         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1718         rtw_coex_table(rtwdev, table_case);
1719         rtw_coex_tdma(rtwdev, false, tdma_case);
1720 }
1721 
1722 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
1723 {
1724         struct rtw_efuse *efuse = &rtwdev->efuse;
1725         struct rtw_chip_info *chip = rtwdev->chip;
1726         u8 table_case, tdma_case;
1727 
1728         rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1729 
1730         if (efuse->share_ant) {
1731                 /* Shared-Ant */
1732                 table_case = 0;
1733                 tdma_case = 0;
1734         } else {
1735                 /* Non-Shared-Ant */
1736                 table_case = 100;
1737                 tdma_case = 100;
1738         }
1739 
1740         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
1741         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1742         rtw_coex_table(rtwdev, table_case);
1743         rtw_coex_tdma(rtwdev, false, tdma_case);
1744 }
1745 
1746 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
1747 {
1748         struct rtw_efuse *efuse = &rtwdev->efuse;
1749         struct rtw_chip_info *chip = rtwdev->chip;
1750         u8 table_case, tdma_case;
1751 
1752         if (efuse->share_ant) {
1753                 /* Shared-Ant */
1754                 table_case = 2;
1755                 tdma_case = 0;
1756         } else {
1757                 /* Non-Shared-Ant */
1758                 table_case = 100;
1759                 tdma_case = 100;
1760         }
1761 
1762         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1763         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1764         rtw_coex_table(rtwdev, table_case);
1765         rtw_coex_tdma(rtwdev, false, tdma_case);
1766 }
1767 
1768 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
1769 {
1770         struct rtw_coex *coex = &rtwdev->coex;
1771         struct rtw_efuse *efuse = &rtwdev->efuse;
1772         struct rtw_chip_info *chip = rtwdev->chip;
1773         u8 table_case, tdma_case;
1774 
1775         if (coex->under_5g)
1776                 return;
1777 
1778         if (efuse->share_ant) {
1779                 /* Shared-Ant */
1780                 table_case = 28;
1781                 tdma_case = 0;
1782         } else {
1783                 /* Non-Shared-Ant */
1784                 table_case = 100;
1785                 tdma_case = 100;
1786         }
1787 
1788         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1789         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1790         rtw_coex_table(rtwdev, table_case);
1791         rtw_coex_tdma(rtwdev, false, tdma_case);
1792 }
1793 
1794 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
1795 {
1796         struct rtw_coex *coex = &rtwdev->coex;
1797         struct rtw_coex_stat *coex_stat = &coex->stat;
1798         struct rtw_efuse *efuse = &rtwdev->efuse;
1799         struct rtw_chip_info *chip = rtwdev->chip;
1800         u8 table_case, tdma_case;
1801         u32 slot_type = 0;
1802 
1803         if (efuse->share_ant) {
1804                 /* Shared-Ant */
1805                 if (coex_stat->bt_a2dp_exist) {
1806                         slot_type = TDMA_4SLOT;
1807                         table_case = 9;
1808                         tdma_case = 11;
1809                 } else {
1810                         table_case = 9;
1811                         tdma_case = 7;
1812                 }
1813         } else {
1814                 /* Non-Shared-Ant */
1815                 if (coex_stat->bt_a2dp_exist) {
1816                         table_case = 112;
1817                         tdma_case = 111;
1818                 } else {
1819                         table_case = 112;
1820                         tdma_case = 107;
1821                 }
1822         }
1823 
1824         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1825         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1826         rtw_coex_table(rtwdev, table_case);
1827         rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1828 }
1829 
1830 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
1831 {
1832         struct rtw_efuse *efuse = &rtwdev->efuse;
1833         struct rtw_chip_info *chip = rtwdev->chip;
1834         u8 table_case, tdma_case;
1835 
1836         if (efuse->share_ant) {
1837                 /* Shared-Ant */
1838                 table_case = 1;
1839                 tdma_case = 0;
1840         } else {
1841                 /* Non-Shared-Ant */
1842                 table_case = 100;
1843                 tdma_case = 100;
1844         }
1845 
1846         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1847         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1848         rtw_coex_table(rtwdev, table_case);
1849         rtw_coex_tdma(rtwdev, false, tdma_case);
1850 }
1851 
1852 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
1853 {
1854         struct rtw_coex *coex = &rtwdev->coex;
1855         struct rtw_coex_stat *coex_stat = &coex->stat;
1856         struct rtw_coex_dm *coex_dm = &coex->dm;
1857         struct rtw_efuse *efuse = &rtwdev->efuse;
1858         u8 algorithm;
1859 
1860         /* Non-Shared-Ant */
1861         if (!efuse->share_ant && coex_stat->wl_gl_busy &&
1862             COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
1863             COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) {
1864                 rtw_coex_action_freerun(rtwdev);
1865                 return;
1866         }
1867 
1868         algorithm = rtw_coex_algorithm(rtwdev);
1869 
1870         switch (algorithm) {
1871         case COEX_ALGO_HFP:
1872                 rtw_coex_action_bt_hfp(rtwdev);
1873                 break;
1874         case COEX_ALGO_HID:
1875                 rtw_coex_action_bt_hid(rtwdev);
1876                 break;
1877         case COEX_ALGO_A2DP:
1878                 if (coex_stat->bt_a2dp_sink)
1879                         rtw_coex_action_bt_a2dpsink(rtwdev);
1880                 else
1881                         rtw_coex_action_bt_a2dp(rtwdev);
1882                 break;
1883         case COEX_ALGO_PAN:
1884                 rtw_coex_action_bt_pan(rtwdev);
1885                 break;
1886         case COEX_ALGO_A2DP_HID:
1887                 rtw_coex_action_bt_a2dp_hid(rtwdev);
1888                 break;
1889         case COEX_ALGO_A2DP_PAN:
1890                 rtw_coex_action_bt_a2dp_pan(rtwdev);
1891                 break;
1892         case COEX_ALGO_PAN_HID:
1893                 rtw_coex_action_bt_pan_hid(rtwdev);
1894                 break;
1895         case COEX_ALGO_A2DP_PAN_HID:
1896                 rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
1897                 break;
1898         default:
1899         case COEX_ALGO_NOPROFILE:
1900                 rtw_coex_action_bt_idle(rtwdev);
1901                 break;
1902         }
1903 }
1904 
1905 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
1906 {
1907         struct rtw_coex *coex = &rtwdev->coex;
1908         struct rtw_coex_dm *coex_dm = &coex->dm;
1909         struct rtw_coex_stat *coex_stat = &coex->stat;
1910 
1911         lockdep_assert_held(&rtwdev->mutex);
1912 
1913         coex_dm->reason = reason;
1914 
1915         /* update wifi_link_info_ext variable */
1916         rtw_coex_update_wl_link_info(rtwdev, reason);
1917 
1918         rtw_coex_monitor_bt_enable(rtwdev);
1919 
1920         if (coex->stop_dm)
1921                 return;
1922 
1923         if (coex_stat->wl_under_ips)
1924                 return;
1925 
1926         if (coex->freeze && !coex_stat->bt_setup_link)
1927                 return;
1928 
1929         coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
1930         coex->freerun = false;
1931 
1932         /* Pure-5G Coex Process */
1933         if (coex->under_5g) {
1934                 coex_stat->wl_coex_mode = COEX_WLINK_5G;
1935                 rtw_coex_action_wl_under5g(rtwdev);
1936                 goto exit;
1937         }
1938 
1939         coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
1940         rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1941         if (coex_stat->bt_disabled) {
1942                 rtw_coex_action_wl_only(rtwdev);
1943                 goto exit;
1944         }
1945 
1946         if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
1947                 rtw_coex_action_wl_native_lps(rtwdev);
1948                 goto exit;
1949         }
1950 
1951         if (coex_stat->bt_whck_test) {
1952                 rtw_coex_action_bt_whql_test(rtwdev);
1953                 goto exit;
1954         }
1955 
1956         if (coex_stat->bt_setup_link) {
1957                 rtw_coex_action_bt_relink(rtwdev);
1958                 goto exit;
1959         }
1960 
1961         if (coex_stat->bt_inq_page) {
1962                 rtw_coex_action_bt_inquiry(rtwdev);
1963                 goto exit;
1964         }
1965 
1966         if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
1967              coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
1968              coex_stat->wl_connected) {
1969                 rtw_coex_action_bt_idle(rtwdev);
1970                 goto exit;
1971         }
1972 
1973         if (coex_stat->wl_linkscan_proc) {
1974                 rtw_coex_action_wl_linkscan(rtwdev);
1975                 goto exit;
1976         }
1977 
1978         if (coex_stat->wl_connected)
1979                 rtw_coex_action_wl_connected(rtwdev);
1980         else
1981                 rtw_coex_action_wl_not_connected(rtwdev);
1982 
1983 exit:
1984         rtw_coex_set_gnt_fix(rtwdev);
1985         rtw_coex_limited_wl(rtwdev);
1986 }
1987 
1988 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
1989 {
1990         struct rtw_coex *coex = &rtwdev->coex;
1991         struct rtw_coex_stat *coex_stat = &coex->stat;
1992         struct rtw_coex_dm *coex_dm = &coex->dm;
1993         u8 i;
1994 
1995         memset(coex_dm, 0, sizeof(*coex_dm));
1996         memset(coex_stat, 0, sizeof(*coex_stat));
1997 
1998         for (i = 0; i < COEX_CNT_WL_MAX; i++)
1999                 coex_stat->cnt_wl[i] = 0;
2000 
2001         for (i = 0; i < COEX_CNT_BT_MAX; i++)
2002                 coex_stat->cnt_bt[i] = 0;
2003 
2004         for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
2005                 coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
2006 
2007         for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
2008                 coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
2009 
2010         coex_stat->wl_coex_mode = COEX_WLINK_MAX;
2011 }
2012 
2013 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2014 {
2015         struct rtw_coex *coex = &rtwdev->coex;
2016 
2017         rtw_coex_init_coex_var(rtwdev);
2018         rtw_coex_monitor_bt_enable(rtwdev);
2019         rtw_coex_set_rfe_type(rtwdev);
2020         rtw_coex_set_init(rtwdev);
2021 
2022         /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
2023         rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
2024 
2025         /* set Tx beacon = Hi-Pri */
2026         rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
2027 
2028         /* set Tx beacon queue = Hi-Pri */
2029         rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
2030 
2031         /* antenna config */
2032         if (coex->wl_rf_off) {
2033                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2034                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2035                 coex->stop_dm = true;
2036         } else if (wifi_only) {
2037                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
2038                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2039                                     true);
2040                 coex->stop_dm = true;
2041         } else {
2042                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
2043                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2044                                     true);
2045                 coex->stop_dm = false;
2046                 coex->freeze = true;
2047         }
2048 
2049         /* PTA parameter */
2050         rtw_coex_table(rtwdev, 0);
2051         rtw_coex_tdma(rtwdev, true, 0);
2052         rtw_coex_query_bt_info(rtwdev);
2053 }
2054 
2055 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
2056 {
2057         struct rtw_coex *coex = &rtwdev->coex;
2058 
2059         coex->stop_dm = true;
2060         coex->wl_rf_off = false;
2061 
2062         /* enable BB, we can write 0x948 */
2063         rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1));
2064 
2065         rtw_coex_monitor_bt_enable(rtwdev);
2066         rtw_coex_set_rfe_type(rtwdev);
2067 
2068         /* set antenna path to BT */
2069         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
2070 
2071         /* red x issue */
2072         rtw_write8(rtwdev, 0xff1a, 0x0);
2073 }
2074 
2075 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2076 {
2077         __rtw_coex_init_hw_config(rtwdev, wifi_only);
2078 }
2079 
2080 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
2081 {
2082         struct rtw_coex *coex = &rtwdev->coex;
2083         struct rtw_coex_stat *coex_stat = &coex->stat;
2084 
2085         if (coex->stop_dm)
2086                 return;
2087 
2088         if (type == COEX_IPS_ENTER) {
2089                 coex_stat->wl_under_ips = true;
2090 
2091                 /* for lps off */
2092                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2093 
2094                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2095                 rtw_coex_action_coex_all_off(rtwdev);
2096         } else if (type == COEX_IPS_LEAVE) {
2097                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2098 
2099                 /* run init hw config (exclude wifi only) */
2100                 __rtw_coex_init_hw_config(rtwdev, false);
2101                 /* sw all off */
2102 
2103                 coex_stat->wl_under_ips = false;
2104         }
2105 }
2106 
2107 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
2108 {
2109         struct rtw_coex *coex = &rtwdev->coex;
2110         struct rtw_coex_stat *coex_stat = &coex->stat;
2111 
2112         if (coex->stop_dm)
2113                 return;
2114 
2115         if (type == COEX_LPS_ENABLE) {
2116                 coex_stat->wl_under_lps = true;
2117 
2118                 if (coex_stat->wl_force_lps_ctrl) {
2119                         /* for ps-tdma */
2120                         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2121                 } else {
2122                         /* for native ps */
2123                         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2124 
2125                         rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2126                 }
2127         } else if (type == COEX_LPS_DISABLE) {
2128                 coex_stat->wl_under_lps = false;
2129 
2130                 /* for lps off */
2131                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2132 
2133                 if (!coex_stat->wl_force_lps_ctrl)
2134                         rtw_coex_query_bt_info(rtwdev);
2135         }
2136 }
2137 
2138 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
2139 {
2140         struct rtw_coex *coex = &rtwdev->coex;
2141         struct rtw_coex_stat *coex_stat = &coex->stat;
2142 
2143         if (coex->stop_dm)
2144                 return;
2145 
2146         coex->freeze = false;
2147 
2148         if (type != COEX_SCAN_FINISH)
2149                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2150                                     COEX_SCBD_ONOFF, true);
2151 
2152         if (type == COEX_SCAN_START_5G) {
2153                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2154                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
2155         } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
2156                 coex_stat->wl_hi_pri_task2 = true;
2157 
2158                 /* Force antenna setup for no scan result issue */
2159                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2160                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
2161         } else {
2162                 coex_stat->wl_hi_pri_task2 = false;
2163                 rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
2164         }
2165 }
2166 
2167 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
2168 {
2169         struct rtw_coex *coex = &rtwdev->coex;
2170 
2171         if (coex->stop_dm)
2172                 return;
2173 
2174         if (type == COEX_SWITCH_TO_5G)
2175                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
2176         else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
2177                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
2178         else
2179                 rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
2180 }
2181 
2182 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
2183 {
2184         struct rtw_coex *coex = &rtwdev->coex;
2185         struct rtw_coex_stat *coex_stat = &coex->stat;
2186 
2187         if (coex->stop_dm)
2188                 return;
2189 
2190         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2191                             COEX_SCBD_ONOFF, true);
2192 
2193         if (type == COEX_ASSOCIATE_5G_START) {
2194                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2195                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
2196         } else if (type == COEX_ASSOCIATE_5G_FINISH) {
2197                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2198                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
2199         } else if (type == COEX_ASSOCIATE_START) {
2200                 coex_stat->wl_hi_pri_task1 = true;
2201                 coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
2202 
2203                 /* Force antenna setup for no scan result issue */
2204                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2205 
2206                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
2207 
2208                 /* To keep TDMA case during connect process,
2209                  * to avoid changed by Btinfo and runcoexmechanism
2210                  */
2211                 coex->freeze = true;
2212                 ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
2213                                              5 * HZ);
2214         } else {
2215                 coex_stat->wl_hi_pri_task1 = false;
2216                 coex->freeze = false;
2217 
2218                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
2219         }
2220 }
2221 
2222 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
2223 {
2224         struct rtw_coex *coex = &rtwdev->coex;
2225         struct rtw_coex_stat *coex_stat = &coex->stat;
2226         u8 para[6] = {0};
2227 
2228         if (coex->stop_dm)
2229                 return;
2230 
2231         if (type == COEX_MEDIA_CONNECT_5G) {
2232                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2233 
2234                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2235                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
2236         } else if (type == COEX_MEDIA_CONNECT) {
2237                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2238 
2239                 /* Force antenna setup for no scan result issue */
2240                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2241 
2242                 /* Set CCK Rx high Pri */
2243                 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
2244 
2245                 /* always enable 5ms extend if connect */
2246                 para[0] = COEX_H2C69_WL_LEAKAP;
2247                 para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */
2248                 rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
2249                 coex_stat->wl_slot_extend = true;
2250                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
2251         } else {
2252                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2253 
2254                 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
2255 
2256                 rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
2257         }
2258 
2259         rtw_coex_update_wl_ch_info(rtwdev, type);
2260 }
2261 
2262 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2263 {
2264         struct rtw_coex *coex = &rtwdev->coex;
2265         struct rtw_coex_stat *coex_stat = &coex->stat;
2266         struct rtw_chip_info *chip = rtwdev->chip;
2267         unsigned long bt_relink_time;
2268         u8 i, rsp_source = 0, type;
2269 
2270         rsp_source = buf[0] & 0xf;
2271         if (rsp_source >= COEX_BTINFO_SRC_MAX)
2272                 rsp_source = COEX_BTINFO_SRC_WL_FW;
2273 
2274         if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
2275                 coex_stat->bt_iqk_state = buf[1];
2276                 if (coex_stat->bt_iqk_state == 1)
2277                         coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
2278                 else if (coex_stat->bt_iqk_state == 2)
2279                         coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
2280 
2281                 return;
2282         }
2283 
2284         if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
2285                 rtw_coex_monitor_bt_enable(rtwdev);
2286                 if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
2287                         coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
2288                         rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2289                 }
2290                 return;
2291         }
2292 
2293         if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
2294             rsp_source == COEX_BTINFO_SRC_BT_ACT) {
2295                 if (coex_stat->bt_disabled) {
2296                         coex_stat->bt_disabled = false;
2297                         coex_stat->bt_reenable = true;
2298                         ieee80211_queue_delayed_work(rtwdev->hw,
2299                                                      &coex->bt_reenable_work,
2300                                                      15 * HZ);
2301                 }
2302         }
2303 
2304         for (i = 0; i < length; i++) {
2305                 if (i < COEX_BTINFO_LENGTH_MAX)
2306                         coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
2307                 else
2308                         break;
2309         }
2310 
2311         if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
2312                 rtw_coex_update_bt_link_info(rtwdev);
2313                 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2314                 return;
2315         }
2316 
2317         /* get the same info from bt, skip it */
2318         if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
2319             coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
2320             coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
2321             coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
2322             coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
2323             coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3)
2324                 return;
2325 
2326         coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
2327         coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
2328         coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
2329         coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
2330         coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
2331         coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
2332 
2333         /* 0xff means BT is under WHCK test */
2334         coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
2335         coex_stat->bt_inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
2336         coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
2337         coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
2338         if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
2339                 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
2340 
2341         coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
2342         coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
2343         if (coex_stat->bt_inq)
2344                 coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
2345 
2346         coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
2347         if (coex_stat->bt_page) {
2348                 coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
2349                 if (coex_stat->wl_linkscan_proc ||
2350                     coex_stat->wl_hi_pri_task1 ||
2351                     coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
2352                         rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
2353                 else
2354                         rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2355         } else {
2356                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2357         }
2358 
2359         /* unit: % (value-100 to translate to unit: dBm in coex info) */
2360         if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
2361                 coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
2362         } else { /* original unit: dbm -> unit: % ->  value-100 in coex info */
2363                 if (coex_stat->bt_info_hb0 <= 127)
2364                         coex_stat->bt_rssi = 100;
2365                 else if (256 - coex_stat->bt_info_hb0 <= 100)
2366                         coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
2367                 else
2368                         coex_stat->bt_rssi = 0;
2369         }
2370 
2371         coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0));
2372         if (coex_stat->bt_info_hb1 & BIT(1))
2373                 coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
2374 
2375         if (coex_stat->bt_info_hb1 & BIT(2)) {
2376                 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
2377                 coex_stat->bt_setup_link = true;
2378                 if (coex_stat->bt_reenable)
2379                         bt_relink_time = 6 * HZ;
2380                 else
2381                         bt_relink_time = 2 * HZ;
2382 
2383                 ieee80211_queue_delayed_work(rtwdev->hw,
2384                                              &coex->bt_relink_work,
2385                                              bt_relink_time);
2386         }
2387 
2388         if (coex_stat->bt_info_hb1 & BIT(3))
2389                 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
2390 
2391         coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
2392         coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
2393         if (coex_stat->bt_info_hb1 & BIT(6))
2394                 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
2395 
2396         coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
2397         /* resend wifi info to bt, it is reset and lost the info */
2398         if ((coex_stat->bt_info_hb1 & BIT(1))) {
2399                 if (coex_stat->wl_connected)
2400                         type = COEX_MEDIA_CONNECT;
2401                 else
2402                         type = COEX_MEDIA_DISCONNECT;
2403                 rtw_coex_update_wl_ch_info(rtwdev, type);
2404         }
2405 
2406         /* if ignore_wlan_act && not set_up_link */
2407         if ((coex_stat->bt_info_hb1 & BIT(3)) &&
2408             (!(coex_stat->bt_info_hb1 & BIT(2))))
2409                 rtw_coex_ignore_wlan_act(rtwdev, false);
2410 
2411         coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
2412         if (coex_stat->bt_info_hb2 & BIT(1))
2413                 coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
2414 
2415         coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
2416         coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
2417         coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
2418         coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
2419         if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
2420                 coex_stat->bt_418_hid_exist = true;
2421         else if (coex_stat->bt_hid_pair_num == 0)
2422                 coex_stat->bt_418_hid_exist = false;
2423 
2424         if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
2425                 coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
2426         else
2427                 coex_stat->bt_a2dp_bitpool = 0;
2428 
2429         coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
2430 
2431         rtw_coex_update_bt_link_info(rtwdev);
2432         rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2433 }
2434 
2435 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2436 {
2437         struct rtw_coex *coex = &rtwdev->coex;
2438         struct rtw_coex_stat *coex_stat = &coex->stat;
2439         u8 val;
2440         int i;
2441 
2442         if (WARN(length < 8, "invalid wl info c2h length\n"))
2443                 return;
2444 
2445         if (buf[0] != 0x08)
2446                 return;
2447 
2448         for (i = 1; i < 8; i++) {
2449                 val = coex_stat->wl_fw_dbg_info_pre[i];
2450                 if (buf[i] >= val)
2451                         coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
2452                 else
2453                         coex_stat->wl_fw_dbg_info[i] = val - buf[i];
2454 
2455                 coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
2456         }
2457 
2458         coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
2459         rtw_coex_wl_ccklock_action(rtwdev);
2460         rtw_coex_wl_ccklock_detect(rtwdev);
2461 }
2462 
2463 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev)
2464 {
2465         struct rtw_coex *coex = &rtwdev->coex;
2466 
2467         if (coex->stop_dm)
2468                 return;
2469 
2470         rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2471 }
2472 
2473 void rtw_coex_bt_relink_work(struct work_struct *work)
2474 {
2475         struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2476                                               coex.bt_relink_work.work);
2477         struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2478 
2479         mutex_lock(&rtwdev->mutex);
2480         coex_stat->bt_setup_link = false;
2481         rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2482         mutex_unlock(&rtwdev->mutex);
2483 }
2484 
2485 void rtw_coex_bt_reenable_work(struct work_struct *work)
2486 {
2487         struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2488                                               coex.bt_reenable_work.work);
2489         struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2490 
2491         mutex_lock(&rtwdev->mutex);
2492         coex_stat->bt_reenable = false;
2493         mutex_unlock(&rtwdev->mutex);
2494 }
2495 
2496 void rtw_coex_defreeze_work(struct work_struct *work)
2497 {
2498         struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2499                                               coex.defreeze_work.work);
2500         struct rtw_coex *coex = &rtwdev->coex;
2501         struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2502 
2503         mutex_lock(&rtwdev->mutex);
2504         coex->freeze = false;
2505         coex_stat->wl_hi_pri_task1 = false;
2506         rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2507         mutex_unlock(&rtwdev->mutex);
2508 }

/* [<][>][^][v][top][bottom][index][help] */