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