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