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