1
2
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
12static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
13 u8 rssi, u8 rssi_thresh)
14{
15 struct rtw_chip_info *chip = rtwdev->chip;
16 u8 tol = chip->rssi_tolerance;
17 u8 next_state;
18
19 if (pre_state == COEX_RSSI_STATE_LOW ||
20 pre_state == COEX_RSSI_STATE_STAY_LOW) {
21 if (rssi >= (rssi_thresh + tol))
22 next_state = COEX_RSSI_STATE_HIGH;
23 else
24 next_state = COEX_RSSI_STATE_STAY_LOW;
25 } else {
26 if (rssi < rssi_thresh)
27 next_state = COEX_RSSI_STATE_LOW;
28 else
29 next_state = COEX_RSSI_STATE_STAY_HIGH;
30 }
31
32 return next_state;
33}
34
35static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
36 bool tx_limit_en, bool ampdu_limit_en)
37{
38 struct rtw_chip_info *chip = rtwdev->chip;
39 struct rtw_coex *coex = &rtwdev->coex;
40 struct rtw_coex_stat *coex_stat = &coex->stat;
41 bool wifi_under_b_mode = false;
42
43 if (!chip->scbd_support)
44 return;
45
46
47 if (coex_stat->wl_tx_limit_en == tx_limit_en &&
48 coex_stat->wl_ampdu_limit_en == ampdu_limit_en)
49 return;
50
51 if (!coex_stat->wl_tx_limit_en) {
52 coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC);
53 coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH);
54 coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT);
55 }
56
57 if (!coex_stat->wl_ampdu_limit_en)
58 coex_stat->ampdu_max_time =
59 rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);
60
61 coex_stat->wl_tx_limit_en = tx_limit_en;
62 coex_stat->wl_ampdu_limit_en = ampdu_limit_en;
63
64 if (tx_limit_en) {
65
66
67
68 rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
69
70
71
72
73 rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
74 rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
75
76
77 if (wifi_under_b_mode) {
78 rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
79 rtw_write32(rtwdev, REG_DARFRCH, 0x1010101);
80 } else {
81 rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
82 rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
83 }
84 } else {
85 rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
86 rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
87
88 rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit);
89 rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc);
90 rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch);
91 }
92
93 if (ampdu_limit_en)
94 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);
95 else
96 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,
97 coex_stat->ampdu_max_time);
98}
99
100static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
101{
102 struct rtw_coex *coex = &rtwdev->coex;
103 struct rtw_coex_dm *coex_dm = &coex->dm;
104 struct rtw_coex_stat *coex_stat = &coex->stat;
105 bool tx_limit = false;
106 bool tx_agg_ctrl = false;
107
108 if (coex->under_5g ||
109 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
110
111 } else {
112 tx_limit = true;
113 if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist ||
114 coex_stat->bt_hid_pair_num > 0)
115 tx_agg_ctrl = true;
116 }
117
118 rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
119}
120
121static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
122{
123 struct rtw_coex *coex = &rtwdev->coex;
124 struct rtw_coex_stat *coex_stat = &coex->stat;
125 u8 para[6] = {0};
126
127 if (coex->stop_dm)
128 return;
129
130 para[0] = COEX_H2C69_WL_LEAKAP;
131
132 if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {
133 para[1] = PARA1_H2C69_DIS_5MS;
134 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
135 coex_stat->wl_slot_extend = false;
136 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
137 return;
138 }
139
140 if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl &&
141 !coex_stat->wl_cck_lock_ever) {
142 if (coex_stat->wl_fw_dbg_info[7] <= 5)
143 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++;
144 else
145 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
146
147 if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {
148 para[1] = 0x1;
149 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
150 coex_stat->wl_slot_extend = false;
151 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
152 }
153 } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {
154 para[1] = 0x0;
155 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
156 coex_stat->wl_slot_extend = true;
157 }
158}
159
160static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
161{
162 struct rtw_coex *coex = &rtwdev->coex;
163 struct rtw_coex_stat *coex_stat = &coex->stat;
164
165
166 coex_stat->wl_cck_lock = false;
167 coex_stat->wl_cck_lock_pre = false;
168 coex_stat->wl_cck_lock_ever = false;
169}
170
171static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
172{
173 struct rtw_coex *coex = &rtwdev->coex;
174 struct rtw_coex_stat *coex_stat = &coex->stat;
175 struct rtw_dm_info *dm_info = &rtwdev->dm_info;
176 u32 cnt_cck;
177
178
179 cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
180
181 if (!coex_stat->wl_gl_busy) {
182 if (cnt_cck > 250) {
183 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
184 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
185
186 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) {
187 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
188 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
189 }
190 } else if (cnt_cck < 100) {
191 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5)
192 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++;
193
194 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) {
195 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
196 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
197 }
198 } else {
199 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)
200 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;
201
202 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) {
203 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
204 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
205 }
206 }
207
208 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5)
209 coex_stat->wl_noisy_level = 2;
210 else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5)
211 coex_stat->wl_noisy_level = 1;
212 else
213 coex_stat->wl_noisy_level = 0;
214 }
215}
216
217static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
218{
219 struct rtw_coex *coex = &rtwdev->coex;
220 struct rtw_coex_stat *coex_stat = &coex->stat;
221 u8 para[2] = {0};
222
223 if (coex_stat->tdma_timer_base == type)
224 return;
225
226 coex_stat->tdma_timer_base = type;
227
228 para[0] = COEX_H2C69_TDMA_SLOT;
229
230 if (type == 3)
231 para[1] = PARA1_H2C69_TDMA_4SLOT;
232 else
233 para[1] = PARA1_H2C69_TDMA_2SLOT;
234
235 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
236
237
238 if (coex_stat->tdma_timer_base == 3)
239 rtw_coex_wl_ccklock_action(rtwdev);
240}
241
242static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
243 u8 data)
244{
245 u32 addr;
246
247 addr = REG_BT_COEX_TABLE_H + (bitmap / 8);
248 bitmap = bitmap % 8;
249
250 rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);
251}
252
253void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
254{
255 struct rtw_chip_info *chip = rtwdev->chip;
256 struct rtw_coex *coex = &rtwdev->coex;
257 struct rtw_coex_stat *coex_stat = &coex->stat;
258 u16 val = 0x2;
259
260 if (!chip->scbd_support)
261 return;
262
263 val |= coex_stat->score_board;
264
265
266
267
268 if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {
269 if (set)
270 val &= ~COEX_SCBD_FIX2M;
271 else
272 val |= COEX_SCBD_FIX2M;
273 } else {
274 if (set)
275 val |= bitpos;
276 else
277 val &= ~bitpos;
278 }
279
280 if (val != coex_stat->score_board) {
281 coex_stat->score_board = val;
282 val |= BIT_BT_INT_EN;
283 rtw_write16(rtwdev, REG_WIFI_BT_INFO, val);
284 }
285}
286EXPORT_SYMBOL(rtw_coex_write_scbd);
287
288static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
289{
290 struct rtw_chip_info *chip = rtwdev->chip;
291
292 if (!chip->scbd_support)
293 return 0;
294
295 return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);
296}
297
298static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
299{
300 struct rtw_chip_info *chip = rtwdev->chip;
301 struct rtw_coex *coex = &rtwdev->coex;
302 struct rtw_coex_stat *coex_stat = &coex->stat;
303 struct rtw_coex_rfe *coex_rfe = &coex->rfe;
304 u8 cnt = 0;
305 u32 wait_cnt;
306 bool btk, wlk;
307
308 if (coex_rfe->wlg_at_btg && chip->scbd_support &&
309 coex_stat->bt_iqk_state != 0xff) {
310 wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
311 do {
312
313 btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);
314
315
316 wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);
317
318 if (!btk && !wlk)
319 break;
320
321 mdelay(COEX_MIN_DELAY);
322 } while (++cnt < wait_cnt);
323
324 if (cnt >= wait_cnt)
325 coex_stat->bt_iqk_state = 0xff;
326 }
327}
328
329static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
330{
331 struct rtw_coex *coex = &rtwdev->coex;
332 struct rtw_coex_stat *coex_stat = &coex->stat;
333
334 if (coex_stat->bt_disabled)
335 return;
336
337 rtw_fw_query_bt_info(rtwdev);
338}
339
340static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
341{
342 struct rtw_chip_info *chip = rtwdev->chip;
343 struct rtw_coex *coex = &rtwdev->coex;
344 struct rtw_coex_stat *coex_stat = &coex->stat;
345 struct rtw_coex_dm *coex_dm = &coex->dm;
346 bool bt_disabled = false;
347 u16 score_board;
348
349 if (chip->scbd_support) {
350 score_board = rtw_coex_read_scbd(rtwdev);
351 bt_disabled = !(score_board & COEX_SCBD_ONOFF);
352 }
353
354 if (coex_stat->bt_disabled != bt_disabled) {
355 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n",
356 coex_stat->bt_disabled, bt_disabled);
357
358 coex_stat->bt_disabled = bt_disabled;
359 coex_stat->bt_ble_scan_type = 0;
360 coex_dm->cur_bt_lna_lvl = 0;
361 }
362
363 if (!coex_stat->bt_disabled) {
364 coex_stat->bt_reenable = true;
365 ieee80211_queue_delayed_work(rtwdev->hw,
366 &coex->bt_reenable_work, 15 * HZ);
367 } else {
368 coex_stat->bt_mailbox_reply = false;
369 coex_stat->bt_reenable = false;
370 }
371}
372
373static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
374{
375 struct rtw_coex *coex = &rtwdev->coex;
376 struct rtw_coex_stat *coex_stat = &coex->stat;
377 struct rtw_coex_dm *coex_dm = &coex->dm;
378 struct rtw_chip_info *chip = rtwdev->chip;
379 struct rtw_traffic_stats *stats = &rtwdev->stats;
380 bool is_5G = false;
381 bool wl_busy = false;
382 bool scan = false, link = false;
383 int i;
384 u8 rssi_state;
385 u8 rssi_step;
386 u8 rssi;
387
388 scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);
389 coex_stat->wl_connected = !!rtwdev->sta_cnt;
390
391 wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
392 if (wl_busy != coex_stat->wl_gl_busy) {
393 if (wl_busy)
394 coex_stat->wl_gl_busy = true;
395 else
396 ieee80211_queue_delayed_work(rtwdev->hw,
397 &coex->wl_remain_work,
398 12 * HZ);
399 }
400
401 if (stats->tx_throughput > stats->rx_throughput)
402 coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
403 else
404 coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;
405
406 if (scan || link || reason == COEX_RSN_2GCONSTART ||
407 reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)
408 coex_stat->wl_linkscan_proc = true;
409 else
410 coex_stat->wl_linkscan_proc = false;
411
412 rtw_coex_wl_noisy_detect(rtwdev);
413
414 for (i = 0; i < 4; i++) {
415 rssi_state = coex_dm->wl_rssi_state[i];
416 rssi_step = chip->wl_rssi_step[i];
417 rssi = rtwdev->dm_info.min_rssi;
418 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
419 rssi, rssi_step);
420 coex_dm->wl_rssi_state[i] = rssi_state;
421 }
422
423 switch (reason) {
424 case COEX_RSN_5GSCANSTART:
425 case COEX_RSN_5GSWITCHBAND:
426 case COEX_RSN_5GCONSTART:
427
428 is_5G = true;
429 break;
430 case COEX_RSN_2GSCANSTART:
431 case COEX_RSN_2GSWITCHBAND:
432 case COEX_RSN_2GCONSTART:
433
434 is_5G = false;
435 break;
436 default:
437 if (rtwdev->hal.current_band_type == RTW_BAND_5G)
438 is_5G = true;
439 else
440 is_5G = false;
441 break;
442 }
443
444 coex->under_5g = is_5G;
445}
446
447static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)
448{
449 struct rtw_c2h_cmd *c2h;
450 u32 pkt_offset;
451
452 pkt_offset = *((u32 *)resp->cb);
453 c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);
454
455 return c2h->payload;
456}
457
458void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)
459{
460 struct rtw_coex *coex = &rtwdev->coex;
461 u8 *payload = get_payload_from_coex_resp(skb);
462
463 if (payload[0] != COEX_RESP_ACK_BY_WL_FW)
464 return;
465
466 skb_queue_tail(&coex->queue, skb);
467 wake_up(&coex->wait);
468}
469
470static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
471 struct rtw_coex_info_req *req)
472{
473 struct rtw_coex *coex = &rtwdev->coex;
474 struct sk_buff *skb_resp = NULL;
475
476 mutex_lock(&coex->mutex);
477
478 rtw_fw_query_bt_mp_info(rtwdev, req);
479
480 if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
481 COEX_REQUEST_TIMEOUT)) {
482 rtw_err(rtwdev, "coex request time out\n");
483 goto out;
484 }
485
486 skb_resp = skb_dequeue(&coex->queue);
487 if (!skb_resp) {
488 rtw_err(rtwdev, "failed to get coex info response\n");
489 goto out;
490 }
491
492out:
493 mutex_unlock(&coex->mutex);
494 return skb_resp;
495}
496
497static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
498{
499 struct rtw_coex_info_req req = {0};
500 struct sk_buff *skb;
501 u8 *payload;
502 bool ret = false;
503
504 req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
505 skb = rtw_coex_info_request(rtwdev, &req);
506 if (!skb)
507 goto out;
508
509 payload = get_payload_from_coex_resp(skb);
510 *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
511 dev_kfree_skb_any(skb);
512 ret = true;
513
514out:
515 return ret;
516}
517
518static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
519 u8 lna_constrain_level)
520{
521 struct rtw_coex_info_req req = {0};
522 struct sk_buff *skb;
523 bool ret = false;
524
525 req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
526 req.para1 = lna_constrain_level;
527 skb = rtw_coex_info_request(rtwdev, &req);
528 if (!skb)
529 goto out;
530
531 dev_kfree_skb_any(skb);
532 ret = true;
533
534out:
535 return ret;
536}
537
538static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
539{
540 struct rtw_coex *coex = &rtwdev->coex;
541 struct rtw_coex_stat *coex_stat = &coex->stat;
542 struct rtw_coex_dm *coex_dm = &coex->dm;
543 struct rtw_chip_info *chip = rtwdev->chip;
544 u8 i;
545 u8 rssi_state;
546 u8 rssi_step;
547 u8 rssi;
548
549
550 for (i = 0; i < COEX_RSSI_STEP; i++) {
551 rssi_state = coex_dm->bt_rssi_state[i];
552 rssi_step = chip->bt_rssi_step[i];
553 rssi = coex_stat->bt_rssi;
554 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
555 rssi, rssi_step);
556 coex_dm->bt_rssi_state[i] = rssi_state;
557 }
558
559 for (i = 0; i < COEX_RSSI_STEP; i++) {
560 rssi_state = coex_dm->wl_rssi_state[i];
561 rssi_step = chip->wl_rssi_step[i];
562 rssi = rtwdev->dm_info.min_rssi;
563 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
564 rssi, rssi_step);
565 coex_dm->wl_rssi_state[i] = rssi_state;
566 }
567
568 if (coex_stat->bt_ble_scan_en &&
569 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
570 u8 scan_type;
571
572 if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {
573 coex_stat->bt_ble_scan_type = scan_type;
574 if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)
575 coex_stat->bt_init_scan = true;
576 else
577 coex_stat->bt_init_scan = false;
578 }
579 }
580
581 coex_stat->bt_profile_num = 0;
582
583
584 if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
585 coex_stat->bt_link_exist = false;
586 coex_stat->bt_pan_exist = false;
587 coex_stat->bt_a2dp_exist = false;
588 coex_stat->bt_hid_exist = false;
589 coex_stat->bt_hfp_exist = false;
590 } else {
591
592 coex_stat->bt_link_exist = true;
593 if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {
594 coex_stat->bt_pan_exist = true;
595 coex_stat->bt_profile_num++;
596 } else {
597 coex_stat->bt_pan_exist = false;
598 }
599
600 if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {
601 coex_stat->bt_a2dp_exist = true;
602 coex_stat->bt_profile_num++;
603 } else {
604 coex_stat->bt_a2dp_exist = false;
605 }
606
607 if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {
608 coex_stat->bt_hid_exist = true;
609 coex_stat->bt_profile_num++;
610 } else {
611 coex_stat->bt_hid_exist = false;
612 }
613
614 if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {
615 coex_stat->bt_hfp_exist = true;
616 coex_stat->bt_profile_num++;
617 } else {
618 coex_stat->bt_hfp_exist = false;
619 }
620 }
621
622 if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {
623 coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
624 } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
625 coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
626 } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
627 coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
628 } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
629 (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {
630 if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)
631 coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;
632 else
633 coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;
634 } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {
635 coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;
636 } else {
637 coex_dm->bt_status = COEX_BTSTATUS_MAX;
638 }
639
640 coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
641
642 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status);
643}
644
645static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
646{
647 struct rtw_chip_info *chip = rtwdev->chip;
648 struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
649 struct rtw_efuse *efuse = &rtwdev->efuse;
650 u8 link = 0;
651 u8 center_chan = 0;
652 u8 bw;
653 int i;
654
655 bw = rtwdev->hal.current_band_width;
656
657 if (type != COEX_MEDIA_DISCONNECT)
658 center_chan = rtwdev->hal.current_channel;
659
660 if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) {
661 link = 0;
662 } else if (center_chan <= 14) {
663 link = 0x1;
664
665 if (bw == RTW_CHANNEL_WIDTH_40)
666 bw = chip->bt_afh_span_bw40;
667 else
668 bw = chip->bt_afh_span_bw20;
669 } else if (chip->afh_5g_num > 1) {
670 for (i = 0; i < chip->afh_5g_num; i++) {
671 if (center_chan == chip->afh_5g[i].wl_5g_ch) {
672 link = 0x3;
673 center_chan = chip->afh_5g[i].bt_skip_ch;
674 bw = chip->afh_5g[i].bt_skip_span;
675 break;
676 }
677 }
678 }
679
680 coex_dm->wl_ch_info[0] = link;
681 coex_dm->wl_ch_info[1] = center_chan;
682 coex_dm->wl_ch_info[2] = bw;
683
684 rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
685}
686
687static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
688{
689 struct rtw_coex *coex = &rtwdev->coex;
690 struct rtw_coex_dm *coex_dm = &coex->dm;
691
692 if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)
693 return;
694
695 coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;
696
697 rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);
698}
699
700static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
701{
702 struct rtw_coex *coex = &rtwdev->coex;
703 struct rtw_coex_dm *coex_dm = &coex->dm;
704
705 if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)
706 return;
707
708 coex_dm->cur_bt_lna_lvl = bt_lna_lvl;
709
710
711 if (bt_lna_lvl < 7) {
712 rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);
713 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);
714 } else {
715 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
716 }
717}
718
719static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
720 struct coex_rf_para para)
721{
722 struct rtw_coex *coex = &rtwdev->coex;
723 struct rtw_coex_stat *coex_stat = &coex->stat;
724 u8 offset = 0;
725
726 if (coex->freerun && coex_stat->wl_noisy_level <= 1)
727 offset = 3;
728
729 rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
730 rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);
731 rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);
732 rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
733}
734
735u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
736{
737 u32 val;
738
739 if (!ltecoex_read_reg(rtwdev, addr, &val)) {
740 rtw_err(rtwdev, "failed to read indirect register\n");
741 return 0;
742 }
743
744 return val;
745}
746EXPORT_SYMBOL(rtw_coex_read_indirect_reg);
747
748void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
749 u32 mask, u32 val)
750{
751 u32 shift = __ffs(mask);
752 u32 tmp;
753
754 tmp = rtw_coex_read_indirect_reg(rtwdev, addr);
755 tmp = (tmp & (~mask)) | ((val << shift) & mask);
756
757 if (!ltecoex_reg_write(rtwdev, addr, tmp))
758 rtw_err(rtwdev, "failed to write indirect register\n");
759}
760EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
761
762static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
763{
764 struct rtw_chip_info *chip = rtwdev->chip;
765 const struct rtw_hw_reg *btg_reg = chip->btg_reg;
766
767 if (wifi_control) {
768 rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
769 if (btg_reg)
770 rtw_write8_set(rtwdev, btg_reg->addr, btg_reg->mask);
771 } else {
772 rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
773 if (btg_reg)
774 rtw_write8_clr(rtwdev, btg_reg->addr, btg_reg->mask);
775 }
776}
777
778static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
779{
780 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state);
781 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state);
782}
783
784static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
785{
786 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state);
787 rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state);
788}
789
790static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1)
791{
792#define DEF_BRK_TABLE_VAL 0xf0ffffff
793 rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
794 rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
795 rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
796}
797
798static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type)
799{
800 struct rtw_coex *coex = &rtwdev->coex;
801 struct rtw_coex_dm *coex_dm = &coex->dm;
802 struct rtw_chip_info *chip = rtwdev->chip;
803 struct rtw_efuse *efuse = &rtwdev->efuse;
804
805 coex_dm->cur_table = type;
806
807 if (efuse->share_ant) {
808 if (type < chip->table_sant_num)
809 rtw_coex_set_table(rtwdev,
810 chip->table_sant[type].bt,
811 chip->table_sant[type].wl);
812 } else {
813 type = type - 100;
814 if (type < chip->table_nsant_num)
815 rtw_coex_set_table(rtwdev,
816 chip->table_nsant[type].bt,
817 chip->table_nsant[type].wl);
818 }
819}
820
821static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
822{
823 struct rtw_coex *coex = &rtwdev->coex;
824
825 if (coex->stop_dm)
826 return;
827
828 rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
829}
830
831static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
832 u8 lps_val, u8 rpwm_val)
833{
834 struct rtw_coex *coex = &rtwdev->coex;
835 struct rtw_coex_stat *coex_stat = &coex->stat;
836 u8 lps_mode = 0x0;
837
838 lps_mode = rtwdev->lps_conf.mode;
839
840 switch (ps_type) {
841 case COEX_PS_WIFI_NATIVE:
842
843 coex_stat->wl_force_lps_ctrl = false;
844
845 rtw_leave_lps(rtwdev);
846 break;
847 case COEX_PS_LPS_OFF:
848 coex_stat->wl_force_lps_ctrl = true;
849 if (lps_mode)
850 rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0);
851
852 rtw_leave_lps(rtwdev);
853 break;
854 default:
855 break;
856 }
857}
858
859static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
860 u8 byte3, u8 byte4, u8 byte5)
861{
862 struct rtw_coex *coex = &rtwdev->coex;
863 struct rtw_coex_dm *coex_dm = &coex->dm;
864 struct rtw_chip_info *chip = rtwdev->chip;
865 u8 ps_type = COEX_PS_WIFI_NATIVE;
866 bool ap_enable = false;
867
868 if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
869 byte1 &= ~BIT(4);
870 byte1 |= BIT(5);
871
872 byte5 |= BIT(5);
873 byte5 &= ~BIT(6);
874
875 ps_type = COEX_PS_WIFI_NATIVE;
876 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
877 } else if (byte1 & BIT(4) && !(byte1 & BIT(5))) {
878 if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
879 ps_type = COEX_PS_LPS_OFF;
880 else
881 ps_type = COEX_PS_LPS_ON;
882 rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
883 } else {
884 ps_type = COEX_PS_WIFI_NATIVE;
885 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
886 }
887
888 coex_dm->ps_tdma_para[0] = byte1;
889 coex_dm->ps_tdma_para[1] = byte2;
890 coex_dm->ps_tdma_para[2] = byte3;
891 coex_dm->ps_tdma_para[3] = byte4;
892 coex_dm->ps_tdma_para[4] = byte5;
893
894 rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
895}
896
897static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
898{
899 struct rtw_coex *coex = &rtwdev->coex;
900 struct rtw_coex_dm *coex_dm = &coex->dm;
901 struct rtw_coex_stat *coex_stat = &coex->stat;
902 struct rtw_chip_info *chip = rtwdev->chip;
903 struct rtw_efuse *efuse = &rtwdev->efuse;
904 u8 n, type;
905 bool turn_on;
906 bool wl_busy = false;
907
908 if (tcase & TDMA_4SLOT)
909 rtw_coex_tdma_timer_base(rtwdev, 3);
910 else
911 rtw_coex_tdma_timer_base(rtwdev, 0);
912
913 type = (u8)(tcase & 0xff);
914
915 turn_on = (type == 0 || type == 100) ? false : true;
916
917 if (!force) {
918 if (turn_on == coex_dm->cur_ps_tdma_on &&
919 type == coex_dm->cur_ps_tdma) {
920 return;
921 }
922 }
923
924
925 if (turn_on)
926 rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
927
928 wl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
929
930 if ((coex_stat->bt_a2dp_exist &&
931 (coex_stat->bt_inq_remain || coex_stat->bt_multi_link)) ||
932 !wl_busy)
933 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);
934 else
935 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
936
937 if (efuse->share_ant) {
938 if (type < chip->tdma_sant_num)
939 rtw_coex_set_tdma(rtwdev,
940 chip->tdma_sant[type].para[0],
941 chip->tdma_sant[type].para[1],
942 chip->tdma_sant[type].para[2],
943 chip->tdma_sant[type].para[3],
944 chip->tdma_sant[type].para[4]);
945 } else {
946 n = type - 100;
947 if (n < chip->tdma_nsant_num)
948 rtw_coex_set_tdma(rtwdev,
949 chip->tdma_nsant[n].para[0],
950 chip->tdma_nsant[n].para[1],
951 chip->tdma_nsant[n].para[2],
952 chip->tdma_nsant[n].para[3],
953 chip->tdma_nsant[n].para[4]);
954 }
955
956
957 coex_dm->cur_ps_tdma_on = turn_on;
958 coex_dm->cur_ps_tdma = type;
959
960 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type);
961}
962
963static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
964{
965 struct rtw_coex *coex = &rtwdev->coex;
966 struct rtw_coex_stat *coex_stat = &coex->stat;
967 struct rtw_coex_dm *coex_dm = &coex->dm;
968 u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
969 u8 pos_type = COEX_SWITCH_TO_MAX;
970
971 if (!force && coex_dm->cur_ant_pos_type == phase)
972 return;
973
974 coex_dm->cur_ant_pos_type = phase;
975
976
977 rtw_coex_check_rfk(rtwdev);
978
979 switch (phase) {
980 case COEX_SET_ANT_POWERON:
981
982 if (coex_stat->bt_disabled)
983 rtw_coex_coex_ctrl_owner(rtwdev, true);
984 else
985 rtw_coex_coex_ctrl_owner(rtwdev, false);
986
987 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
988 pos_type = COEX_SWITCH_TO_BT;
989 break;
990 case COEX_SET_ANT_INIT:
991 if (coex_stat->bt_disabled) {
992
993 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
994
995
996 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
997 } else {
998
999 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1000
1001
1002 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);
1003 }
1004
1005
1006 rtw_coex_coex_ctrl_owner(rtwdev, true);
1007
1008 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1009 pos_type = COEX_SWITCH_TO_BT;
1010 break;
1011 case COEX_SET_ANT_WONLY:
1012
1013 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
1014
1015
1016 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1017
1018
1019 rtw_coex_coex_ctrl_owner(rtwdev, true);
1020
1021 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1022 pos_type = COEX_SWITCH_TO_WLG;
1023 break;
1024 case COEX_SET_ANT_WOFF:
1025
1026 rtw_coex_coex_ctrl_owner(rtwdev, false);
1027
1028 ctrl_type = COEX_SWITCH_CTRL_BY_BT;
1029 pos_type = COEX_SWITCH_TO_NOCARE;
1030 break;
1031 case COEX_SET_ANT_2G:
1032
1033 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1034
1035
1036 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1037
1038
1039 rtw_coex_coex_ctrl_owner(rtwdev, true);
1040
1041 ctrl_type = COEX_SWITCH_CTRL_BY_PTA;
1042 pos_type = COEX_SWITCH_TO_NOCARE;
1043 break;
1044 case COEX_SET_ANT_5G:
1045
1046 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1047
1048
1049 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1050
1051
1052 rtw_coex_coex_ctrl_owner(rtwdev, true);
1053
1054 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1055 pos_type = COEX_SWITCH_TO_WLA;
1056 break;
1057 case COEX_SET_ANT_2G_FREERUN:
1058
1059 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1060
1061
1062 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1063
1064
1065 rtw_coex_coex_ctrl_owner(rtwdev, true);
1066
1067 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1068 pos_type = COEX_SWITCH_TO_WLG_BT;
1069 break;
1070 case COEX_SET_ANT_2G_WLBT:
1071
1072 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1073
1074
1075 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1076
1077
1078 rtw_coex_coex_ctrl_owner(rtwdev, true);
1079
1080 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1081 pos_type = COEX_SWITCH_TO_WLG_BT;
1082 break;
1083 default:
1084 WARN(1, "unknown phase when setting antenna path\n");
1085 return;
1086 }
1087
1088 if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX)
1089 rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
1090}
1091
1092static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
1093{
1094 struct rtw_coex *coex = &rtwdev->coex;
1095 struct rtw_coex_stat *coex_stat = &coex->stat;
1096 u8 algorithm = COEX_ALGO_NOPROFILE;
1097 u8 profile_map = 0;
1098
1099 if (coex_stat->bt_hfp_exist)
1100 profile_map |= BPM_HFP;
1101 if (coex_stat->bt_hid_exist)
1102 profile_map |= BPM_HID;
1103 if (coex_stat->bt_a2dp_exist)
1104 profile_map |= BPM_A2DP;
1105 if (coex_stat->bt_pan_exist)
1106 profile_map |= BPM_PAN;
1107
1108 switch (profile_map) {
1109 case BPM_HFP:
1110 algorithm = COEX_ALGO_HFP;
1111 break;
1112 case BPM_HID:
1113 case BPM_HFP + BPM_HID:
1114 algorithm = COEX_ALGO_HID;
1115 break;
1116 case BPM_HFP + BPM_A2DP:
1117 case BPM_HID + BPM_A2DP:
1118 case BPM_HFP + BPM_HID + BPM_A2DP:
1119 algorithm = COEX_ALGO_A2DP_HID;
1120 break;
1121 case BPM_HFP + BPM_PAN:
1122 case BPM_HID + BPM_PAN:
1123 case BPM_HFP + BPM_HID + BPM_PAN:
1124 algorithm = COEX_ALGO_PAN_HID;
1125 break;
1126 case BPM_HFP + BPM_A2DP + BPM_PAN:
1127 case BPM_HID + BPM_A2DP + BPM_PAN:
1128 case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN:
1129 algorithm = COEX_ALGO_A2DP_PAN_HID;
1130 break;
1131 case BPM_PAN:
1132 algorithm = COEX_ALGO_PAN;
1133 break;
1134 case BPM_A2DP + BPM_PAN:
1135 algorithm = COEX_ALGO_A2DP_PAN;
1136 break;
1137 case BPM_A2DP:
1138 if (coex_stat->bt_multi_link) {
1139 if (coex_stat->bt_hid_pair_num > 0)
1140 algorithm = COEX_ALGO_A2DP_HID;
1141 else
1142 algorithm = COEX_ALGO_A2DP_PAN;
1143 } else {
1144 algorithm = COEX_ALGO_A2DP;
1145 }
1146 break;
1147 default:
1148 algorithm = COEX_ALGO_NOPROFILE;
1149 break;
1150 }
1151
1152 return algorithm;
1153}
1154
1155static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
1156{
1157 struct rtw_efuse *efuse = &rtwdev->efuse;
1158 struct rtw_chip_info *chip = rtwdev->chip;
1159 u8 table_case, tdma_case;
1160
1161 if (efuse->share_ant) {
1162
1163 table_case = 2;
1164 tdma_case = 0;
1165 } else {
1166
1167 table_case = 100;
1168 tdma_case = 100;
1169 }
1170
1171 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1172 rtw_coex_table(rtwdev, table_case);
1173 rtw_coex_tdma(rtwdev, false, tdma_case);
1174}
1175
1176static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
1177{
1178 struct rtw_coex *coex = &rtwdev->coex;
1179 struct rtw_coex_stat *coex_stat = &coex->stat;
1180 struct rtw_coex_dm *coex_dm = &coex->dm;
1181 struct rtw_efuse *efuse = &rtwdev->efuse;
1182 struct rtw_chip_info *chip = rtwdev->chip;
1183 u8 level = 0;
1184
1185 if (efuse->share_ant)
1186 return;
1187
1188 coex->freerun = true;
1189
1190 if (coex_stat->wl_connected)
1191 rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
1192
1193 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1194
1195 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1196
1197 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))
1198 level = 2;
1199 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1200 level = 3;
1201 else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))
1202 level = 4;
1203 else
1204 level = 5;
1205
1206 if (level > chip->wl_rf_para_num - 1)
1207 level = chip->wl_rf_para_num - 1;
1208
1209 if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1210 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);
1211 else
1212 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
1213
1214 rtw_coex_table(rtwdev, 100);
1215 rtw_coex_tdma(rtwdev, false, 100);
1216}
1217
1218static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
1219{
1220 struct rtw_efuse *efuse = &rtwdev->efuse;
1221 struct rtw_chip_info *chip = rtwdev->chip;
1222 u8 table_case, tdma_case;
1223
1224 if (efuse->share_ant) {
1225
1226 table_case = 2;
1227 tdma_case = 0;
1228 } else {
1229
1230 table_case = 100;
1231 tdma_case = 100;
1232 }
1233
1234 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1235 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1236 rtw_coex_table(rtwdev, table_case);
1237 rtw_coex_tdma(rtwdev, false, tdma_case);
1238}
1239
1240static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
1241{
1242 struct rtw_efuse *efuse = &rtwdev->efuse;
1243 struct rtw_chip_info *chip = rtwdev->chip;
1244 u8 table_case, tdma_case;
1245
1246 if (efuse->share_ant) {
1247
1248 table_case = 1;
1249 tdma_case = 0;
1250 } else {
1251
1252 table_case = 100;
1253 tdma_case = 100;
1254 }
1255
1256 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1257 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1258 rtw_coex_table(rtwdev, table_case);
1259 rtw_coex_tdma(rtwdev, false, tdma_case);
1260}
1261
1262static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
1263{
1264 struct rtw_coex *coex = &rtwdev->coex;
1265 struct rtw_coex_stat *coex_stat = &coex->stat;
1266 struct rtw_coex_dm *coex_dm = &coex->dm;
1267 struct rtw_efuse *efuse = &rtwdev->efuse;
1268 struct rtw_chip_info *chip = rtwdev->chip;
1269 struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1270 u8 table_case = 0xff, tdma_case = 0xff;
1271
1272 if (coex_rfe->ant_switch_with_bt &&
1273 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1274 if (efuse->share_ant &&
1275 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) {
1276 table_case = 0;
1277 tdma_case = 0;
1278 } else if (!efuse->share_ant) {
1279 table_case = 100;
1280 tdma_case = 100;
1281 }
1282 }
1283
1284 if (table_case != 0xff && tdma_case != 0xff) {
1285 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1286 rtw_coex_table(rtwdev, table_case);
1287 rtw_coex_tdma(rtwdev, false, tdma_case);
1288 return;
1289 }
1290
1291 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1292
1293 if (efuse->share_ant) {
1294
1295 if (!coex_stat->wl_gl_busy) {
1296 table_case = 10;
1297 tdma_case = 3;
1298 } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1299 table_case = 6;
1300 tdma_case = 7;
1301 } else {
1302 table_case = 12;
1303 tdma_case = 7;
1304 }
1305 } else {
1306
1307 if (!coex_stat->wl_gl_busy) {
1308 table_case = 112;
1309 tdma_case = 104;
1310 } else if ((coex_stat->bt_ble_scan_type & 0x2) &&
1311 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1312 table_case = 114;
1313 tdma_case = 103;
1314 } else {
1315 table_case = 112;
1316 tdma_case = 103;
1317 }
1318 }
1319
1320 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1321 rtw_coex_table(rtwdev, table_case);
1322 rtw_coex_tdma(rtwdev, false, tdma_case);
1323}
1324
1325static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
1326{
1327 struct rtw_coex *coex = &rtwdev->coex;
1328 struct rtw_coex_stat *coex_stat = &coex->stat;
1329 struct rtw_efuse *efuse = &rtwdev->efuse;
1330 struct rtw_chip_info *chip = rtwdev->chip;
1331 bool wl_hi_pri = false;
1332 u8 table_case, tdma_case;
1333 u32 slot_type = 0;
1334
1335 if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
1336 coex_stat->wl_hi_pri_task2)
1337 wl_hi_pri = true;
1338
1339 if (efuse->share_ant) {
1340
1341 if (wl_hi_pri) {
1342 table_case = 15;
1343 if (coex_stat->bt_profile_num > 0)
1344 tdma_case = 10;
1345 else if (coex_stat->wl_hi_pri_task1)
1346 tdma_case = 6;
1347 else if (!coex_stat->bt_page)
1348 tdma_case = 8;
1349 else
1350 tdma_case = 9;
1351 } else if (coex_stat->wl_gl_busy) {
1352 if (coex_stat->bt_profile_num == 0) {
1353 table_case = 12;
1354 tdma_case = 18;
1355 } else if (coex_stat->bt_profile_num == 1 &&
1356 !coex_stat->bt_a2dp_exist) {
1357 slot_type = TDMA_4SLOT;
1358 table_case = 12;
1359 tdma_case = 20;
1360 } else {
1361 slot_type = TDMA_4SLOT;
1362 table_case = 12;
1363 tdma_case = 26;
1364 }
1365 } else if (coex_stat->wl_connected) {
1366 table_case = 9;
1367 tdma_case = 27;
1368 } else {
1369 table_case = 1;
1370 tdma_case = 0;
1371 }
1372 } else {
1373
1374 if (wl_hi_pri) {
1375 table_case = 113;
1376 if (coex_stat->bt_a2dp_exist &&
1377 !coex_stat->bt_pan_exist)
1378 tdma_case = 111;
1379 else if (coex_stat->wl_hi_pri_task1)
1380 tdma_case = 106;
1381 else if (!coex_stat->bt_page)
1382 tdma_case = 108;
1383 else
1384 tdma_case = 109;
1385 } else if (coex_stat->wl_gl_busy) {
1386 table_case = 114;
1387 tdma_case = 121;
1388 } else if (coex_stat->wl_connected) {
1389 table_case = 100;
1390 tdma_case = 100;
1391 } else {
1392 table_case = 101;
1393 tdma_case = 100;
1394 }
1395 }
1396
1397 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n",
1398 wl_hi_pri, coex_stat->bt_page);
1399
1400 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1401 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1402 rtw_coex_table(rtwdev, table_case);
1403 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1404}
1405
1406static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
1407{
1408 struct rtw_coex *coex = &rtwdev->coex;
1409 struct rtw_coex_stat *coex_stat = &coex->stat;
1410 struct rtw_efuse *efuse = &rtwdev->efuse;
1411 struct rtw_chip_info *chip = rtwdev->chip;
1412 u8 table_case, tdma_case;
1413
1414 if (efuse->share_ant) {
1415
1416 if (coex_stat->bt_multi_link) {
1417 table_case = 10;
1418 tdma_case = 17;
1419 } else {
1420 table_case = 10;
1421 tdma_case = 5;
1422 }
1423 } else {
1424
1425 if (coex_stat->bt_multi_link) {
1426 table_case = 112;
1427 tdma_case = 117;
1428 } else {
1429 table_case = 105;
1430 tdma_case = 100;
1431 }
1432 }
1433
1434 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1435 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1436 rtw_coex_table(rtwdev, table_case);
1437 rtw_coex_tdma(rtwdev, false, tdma_case);
1438}
1439
1440static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
1441{
1442 struct rtw_coex *coex = &rtwdev->coex;
1443 struct rtw_coex_stat *coex_stat = &coex->stat;
1444 struct rtw_efuse *efuse = &rtwdev->efuse;
1445 struct rtw_chip_info *chip = rtwdev->chip;
1446 u8 table_case, tdma_case;
1447 u32 wl_bw;
1448
1449 wl_bw = rtwdev->hal.current_band_width;
1450
1451 if (efuse->share_ant) {
1452
1453 if (coex_stat->bt_ble_exist) {
1454
1455 if (!coex_stat->wl_gl_busy)
1456 table_case = 14;
1457 else
1458 table_case = 15;
1459
1460 if (coex_stat->bt_a2dp_active || wl_bw == 0)
1461 tdma_case = 18;
1462 else if (coex_stat->wl_gl_busy)
1463 tdma_case = 8;
1464 else
1465 tdma_case = 4;
1466 } else {
1467 if (coex_stat->bt_a2dp_active || wl_bw == 0) {
1468 table_case = 8;
1469 tdma_case = 4;
1470 } else {
1471
1472 if (coex_stat->bt_418_hid_exist &&
1473 coex_stat->wl_gl_busy)
1474 table_case = 12;
1475 else
1476 table_case = 10;
1477 tdma_case = 4;
1478 }
1479 }
1480 } else {
1481
1482 if (coex_stat->bt_a2dp_active) {
1483 table_case = 113;
1484 tdma_case = 118;
1485 } else if (coex_stat->bt_ble_exist) {
1486
1487 table_case = 113;
1488
1489 if (coex_stat->wl_gl_busy)
1490 tdma_case = 106;
1491 else
1492 tdma_case = 104;
1493 } else {
1494 table_case = 113;
1495 tdma_case = 104;
1496 }
1497 }
1498
1499 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1500 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1501 rtw_coex_table(rtwdev, table_case);
1502 rtw_coex_tdma(rtwdev, false, tdma_case);
1503}
1504
1505static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
1506{
1507 struct rtw_coex *coex = &rtwdev->coex;
1508 struct rtw_coex_stat *coex_stat = &coex->stat;
1509 struct rtw_coex_dm *coex_dm = &coex->dm;
1510 struct rtw_efuse *efuse = &rtwdev->efuse;
1511 struct rtw_chip_info *chip = rtwdev->chip;
1512 u8 table_case, tdma_case;
1513 u32 slot_type = 0;
1514
1515 if (efuse->share_ant) {
1516
1517 slot_type = TDMA_4SLOT;
1518
1519 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1520 table_case = 10;
1521 else
1522 table_case = 9;
1523
1524 if (coex_stat->wl_gl_busy)
1525 tdma_case = 13;
1526 else
1527 tdma_case = 14;
1528 } else {
1529
1530 table_case = 112;
1531
1532 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1533 tdma_case = 112;
1534 else
1535 tdma_case = 113;
1536 }
1537
1538 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1539 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1540 rtw_coex_table(rtwdev, table_case);
1541 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1542}
1543
1544static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
1545{
1546 struct rtw_coex *coex = &rtwdev->coex;
1547 struct rtw_coex_stat *coex_stat = &coex->stat;
1548 struct rtw_efuse *efuse = &rtwdev->efuse;
1549 struct rtw_chip_info *chip = rtwdev->chip;
1550 u8 table_case, tdma_case;
1551 bool ap_enable = false;
1552
1553 if (efuse->share_ant) {
1554 if (ap_enable) {
1555 table_case = 2;
1556 tdma_case = 0;
1557 } else if (coex_stat->wl_gl_busy) {
1558 table_case = 28;
1559 tdma_case = 20;
1560 } else {
1561 table_case = 28;
1562 tdma_case = 26;
1563 }
1564 } else {
1565 if (ap_enable) {
1566 table_case = 100;
1567 tdma_case = 100;
1568 } else {
1569 table_case = 119;
1570 tdma_case = 120;
1571 }
1572 }
1573
1574 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1575 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1576 rtw_coex_table(rtwdev, table_case);
1577 rtw_coex_tdma(rtwdev, false, tdma_case);
1578}
1579
1580static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
1581{
1582 struct rtw_coex *coex = &rtwdev->coex;
1583 struct rtw_coex_stat *coex_stat = &coex->stat;
1584 struct rtw_efuse *efuse = &rtwdev->efuse;
1585 struct rtw_chip_info *chip = rtwdev->chip;
1586 u8 table_case, tdma_case;
1587
1588 if (efuse->share_ant) {
1589
1590 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1591 table_case = 14;
1592 else
1593 table_case = 10;
1594
1595 if (coex_stat->wl_gl_busy)
1596 tdma_case = 17;
1597 else
1598 tdma_case = 19;
1599 } else {
1600
1601 table_case = 112;
1602
1603 if (coex_stat->wl_gl_busy)
1604 tdma_case = 117;
1605 else
1606 tdma_case = 119;
1607 }
1608
1609 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1610 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1611 rtw_coex_table(rtwdev, table_case);
1612 rtw_coex_tdma(rtwdev, false, tdma_case);
1613}
1614
1615static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
1616{
1617 struct rtw_coex *coex = &rtwdev->coex;
1618 struct rtw_coex_stat *coex_stat = &coex->stat;
1619 struct rtw_coex_dm *coex_dm = &coex->dm;
1620 struct rtw_efuse *efuse = &rtwdev->efuse;
1621 struct rtw_chip_info *chip = rtwdev->chip;
1622 u8 table_case, tdma_case;
1623 u32 slot_type = 0;
1624
1625 if (efuse->share_ant) {
1626
1627 slot_type = TDMA_4SLOT;
1628
1629 if (coex_stat->bt_ble_exist)
1630 table_case = 26;
1631 else
1632 table_case = 9;
1633
1634 if (coex_stat->wl_gl_busy) {
1635 tdma_case = 13;
1636 } else {
1637 tdma_case = 14;
1638 }
1639 } else {
1640
1641 if (coex_stat->bt_ble_exist)
1642 table_case = 121;
1643 else
1644 table_case = 113;
1645
1646 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1647 tdma_case = 112;
1648 else
1649 tdma_case = 113;
1650 }
1651
1652 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1653 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1654 rtw_coex_table(rtwdev, table_case);
1655 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1656}
1657
1658static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
1659{
1660 struct rtw_coex *coex = &rtwdev->coex;
1661 struct rtw_coex_stat *coex_stat = &coex->stat;
1662 struct rtw_efuse *efuse = &rtwdev->efuse;
1663 struct rtw_chip_info *chip = rtwdev->chip;
1664 u8 table_case, tdma_case;
1665
1666 if (efuse->share_ant) {
1667
1668 if (coex_stat->wl_gl_busy &&
1669 coex_stat->wl_noisy_level == 0)
1670 table_case = 14;
1671 else
1672 table_case = 10;
1673
1674 if (coex_stat->wl_gl_busy)
1675 tdma_case = 15;
1676 else
1677 tdma_case = 20;
1678 } else {
1679
1680 table_case = 112;
1681
1682 if (coex_stat->wl_gl_busy)
1683 tdma_case = 115;
1684 else
1685 tdma_case = 120;
1686 }
1687
1688 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1689 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1690 rtw_coex_table(rtwdev, table_case);
1691 rtw_coex_tdma(rtwdev, false, tdma_case);
1692}
1693
1694static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
1695{
1696 struct rtw_coex *coex = &rtwdev->coex;
1697 struct rtw_coex_stat *coex_stat = &coex->stat;
1698 struct rtw_efuse *efuse = &rtwdev->efuse;
1699 struct rtw_chip_info *chip = rtwdev->chip;
1700 u8 table_case, tdma_case;
1701
1702 if (efuse->share_ant) {
1703
1704 table_case = 9;
1705
1706 if (coex_stat->wl_gl_busy)
1707 tdma_case = 18;
1708 else
1709 tdma_case = 19;
1710 } else {
1711
1712 table_case = 113;
1713
1714 if (coex_stat->wl_gl_busy)
1715 tdma_case = 117;
1716 else
1717 tdma_case = 119;
1718 }
1719
1720 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1721 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1722 rtw_coex_table(rtwdev, table_case);
1723 rtw_coex_tdma(rtwdev, false, tdma_case);
1724}
1725
1726static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
1727{
1728 struct rtw_coex *coex = &rtwdev->coex;
1729 struct rtw_coex_stat *coex_stat = &coex->stat;
1730 struct rtw_efuse *efuse = &rtwdev->efuse;
1731 struct rtw_chip_info *chip = rtwdev->chip;
1732 u8 table_case, tdma_case;
1733
1734 if (efuse->share_ant) {
1735
1736 table_case = 10;
1737
1738 if (coex_stat->wl_gl_busy)
1739 tdma_case = 15;
1740 else
1741 tdma_case = 20;
1742 } else {
1743
1744 table_case = 113;
1745
1746 if (coex_stat->wl_gl_busy)
1747 tdma_case = 115;
1748 else
1749 tdma_case = 120;
1750 }
1751
1752 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1753 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1754 rtw_coex_table(rtwdev, table_case);
1755 rtw_coex_tdma(rtwdev, false, tdma_case);
1756}
1757
1758static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
1759{
1760 struct rtw_efuse *efuse = &rtwdev->efuse;
1761 struct rtw_chip_info *chip = rtwdev->chip;
1762 u8 table_case, tdma_case;
1763
1764 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1765
1766 if (efuse->share_ant) {
1767
1768 table_case = 0;
1769 tdma_case = 0;
1770 } else {
1771
1772 table_case = 100;
1773 tdma_case = 100;
1774 }
1775
1776 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
1777 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1778 rtw_coex_table(rtwdev, table_case);
1779 rtw_coex_tdma(rtwdev, false, tdma_case);
1780}
1781
1782static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
1783{
1784 struct rtw_efuse *efuse = &rtwdev->efuse;
1785 struct rtw_chip_info *chip = rtwdev->chip;
1786 u8 table_case, tdma_case;
1787
1788 if (efuse->share_ant) {
1789
1790 table_case = 2;
1791 tdma_case = 0;
1792 } else {
1793
1794 table_case = 100;
1795 tdma_case = 100;
1796 }
1797
1798 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1799 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1800 rtw_coex_table(rtwdev, table_case);
1801 rtw_coex_tdma(rtwdev, false, tdma_case);
1802}
1803
1804static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
1805{
1806 struct rtw_coex *coex = &rtwdev->coex;
1807 struct rtw_efuse *efuse = &rtwdev->efuse;
1808 struct rtw_chip_info *chip = rtwdev->chip;
1809 u8 table_case, tdma_case;
1810
1811 if (coex->under_5g)
1812 return;
1813
1814 if (efuse->share_ant) {
1815
1816 table_case = 28;
1817 tdma_case = 0;
1818 } else {
1819
1820 table_case = 100;
1821 tdma_case = 100;
1822 }
1823
1824 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1825 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1826 rtw_coex_table(rtwdev, table_case);
1827 rtw_coex_tdma(rtwdev, false, tdma_case);
1828}
1829
1830static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
1831{
1832 struct rtw_coex *coex = &rtwdev->coex;
1833 struct rtw_coex_stat *coex_stat = &coex->stat;
1834 struct rtw_efuse *efuse = &rtwdev->efuse;
1835 struct rtw_chip_info *chip = rtwdev->chip;
1836 u8 table_case, tdma_case;
1837 u32 slot_type = 0;
1838
1839 if (efuse->share_ant) {
1840
1841 if (coex_stat->bt_a2dp_exist) {
1842 slot_type = TDMA_4SLOT;
1843 table_case = 9;
1844 tdma_case = 11;
1845 } else {
1846 table_case = 9;
1847 tdma_case = 7;
1848 }
1849 } else {
1850
1851 if (coex_stat->bt_a2dp_exist) {
1852 table_case = 112;
1853 tdma_case = 111;
1854 } else {
1855 table_case = 112;
1856 tdma_case = 107;
1857 }
1858 }
1859
1860 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1861 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1862 rtw_coex_table(rtwdev, table_case);
1863 rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1864}
1865
1866static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
1867{
1868 struct rtw_efuse *efuse = &rtwdev->efuse;
1869 struct rtw_chip_info *chip = rtwdev->chip;
1870 u8 table_case, tdma_case;
1871
1872 if (efuse->share_ant) {
1873
1874 table_case = 1;
1875 tdma_case = 0;
1876 } else {
1877
1878 table_case = 100;
1879 tdma_case = 100;
1880 }
1881
1882 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1883 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1884 rtw_coex_table(rtwdev, table_case);
1885 rtw_coex_tdma(rtwdev, false, tdma_case);
1886}
1887
1888static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
1889{
1890 struct rtw_coex *coex = &rtwdev->coex;
1891 struct rtw_coex_stat *coex_stat = &coex->stat;
1892 struct rtw_coex_dm *coex_dm = &coex->dm;
1893 struct rtw_efuse *efuse = &rtwdev->efuse;
1894 u8 algorithm;
1895
1896
1897 if (!efuse->share_ant && coex_stat->wl_gl_busy &&
1898 COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
1899 COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) {
1900 rtw_coex_action_freerun(rtwdev);
1901 return;
1902 }
1903
1904 algorithm = rtw_coex_algorithm(rtwdev);
1905
1906 switch (algorithm) {
1907 case COEX_ALGO_HFP:
1908 rtw_coex_action_bt_hfp(rtwdev);
1909 break;
1910 case COEX_ALGO_HID:
1911 rtw_coex_action_bt_hid(rtwdev);
1912 break;
1913 case COEX_ALGO_A2DP:
1914 if (coex_stat->bt_a2dp_sink)
1915 rtw_coex_action_bt_a2dpsink(rtwdev);
1916 else
1917 rtw_coex_action_bt_a2dp(rtwdev);
1918 break;
1919 case COEX_ALGO_PAN:
1920 rtw_coex_action_bt_pan(rtwdev);
1921 break;
1922 case COEX_ALGO_A2DP_HID:
1923 rtw_coex_action_bt_a2dp_hid(rtwdev);
1924 break;
1925 case COEX_ALGO_A2DP_PAN:
1926 rtw_coex_action_bt_a2dp_pan(rtwdev);
1927 break;
1928 case COEX_ALGO_PAN_HID:
1929 rtw_coex_action_bt_pan_hid(rtwdev);
1930 break;
1931 case COEX_ALGO_A2DP_PAN_HID:
1932 rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
1933 break;
1934 default:
1935 case COEX_ALGO_NOPROFILE:
1936 rtw_coex_action_bt_idle(rtwdev);
1937 break;
1938 }
1939}
1940
1941static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
1942{
1943 struct rtw_coex *coex = &rtwdev->coex;
1944 struct rtw_coex_dm *coex_dm = &coex->dm;
1945 struct rtw_coex_stat *coex_stat = &coex->stat;
1946
1947 lockdep_assert_held(&rtwdev->mutex);
1948
1949 if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
1950 return;
1951
1952 coex_dm->reason = reason;
1953
1954
1955 rtw_coex_update_wl_link_info(rtwdev, reason);
1956
1957 rtw_coex_monitor_bt_enable(rtwdev);
1958
1959 if (coex->stop_dm)
1960 return;
1961
1962 if (coex_stat->wl_under_ips)
1963 return;
1964
1965 if (coex->freeze && coex_dm->reason == COEX_RSN_BTINFO &&
1966 !coex_stat->bt_setup_link)
1967 return;
1968
1969 coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
1970 coex->freerun = false;
1971
1972
1973 if (coex->under_5g) {
1974 coex_stat->wl_coex_mode = COEX_WLINK_5G;
1975 rtw_coex_action_wl_under5g(rtwdev);
1976 goto exit;
1977 }
1978
1979 coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
1980 rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1981 if (coex_stat->bt_disabled) {
1982 rtw_coex_action_wl_only(rtwdev);
1983 goto exit;
1984 }
1985
1986 if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
1987 rtw_coex_action_wl_native_lps(rtwdev);
1988 goto exit;
1989 }
1990
1991 if (coex_stat->bt_whck_test) {
1992 rtw_coex_action_bt_whql_test(rtwdev);
1993 goto exit;
1994 }
1995
1996 if (coex_stat->bt_setup_link) {
1997 rtw_coex_action_bt_relink(rtwdev);
1998 goto exit;
1999 }
2000
2001 if (coex_stat->bt_inq_page) {
2002 rtw_coex_action_bt_inquiry(rtwdev);
2003 goto exit;
2004 }
2005
2006 if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
2007 coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
2008 coex_stat->wl_connected) {
2009 rtw_coex_action_bt_idle(rtwdev);
2010 goto exit;
2011 }
2012
2013 if (coex_stat->wl_linkscan_proc) {
2014 rtw_coex_action_wl_linkscan(rtwdev);
2015 goto exit;
2016 }
2017
2018 if (coex_stat->wl_connected)
2019 rtw_coex_action_wl_connected(rtwdev);
2020 else
2021 rtw_coex_action_wl_not_connected(rtwdev);
2022
2023exit:
2024 rtw_coex_set_gnt_fix(rtwdev);
2025 rtw_coex_limited_wl(rtwdev);
2026}
2027
2028static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
2029{
2030 struct rtw_coex *coex = &rtwdev->coex;
2031 struct rtw_coex_stat *coex_stat = &coex->stat;
2032 struct rtw_coex_dm *coex_dm = &coex->dm;
2033 u8 i;
2034
2035 memset(coex_dm, 0, sizeof(*coex_dm));
2036 memset(coex_stat, 0, sizeof(*coex_stat));
2037
2038 for (i = 0; i < COEX_CNT_WL_MAX; i++)
2039 coex_stat->cnt_wl[i] = 0;
2040
2041 for (i = 0; i < COEX_CNT_BT_MAX; i++)
2042 coex_stat->cnt_bt[i] = 0;
2043
2044 for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
2045 coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
2046
2047 for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
2048 coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
2049
2050 coex_stat->wl_coex_mode = COEX_WLINK_MAX;
2051}
2052
2053static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2054{
2055 struct rtw_coex *coex = &rtwdev->coex;
2056
2057 rtw_coex_init_coex_var(rtwdev);
2058 rtw_coex_monitor_bt_enable(rtwdev);
2059 rtw_coex_set_rfe_type(rtwdev);
2060 rtw_coex_set_init(rtwdev);
2061
2062
2063 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
2064
2065
2066 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
2067
2068
2069 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
2070
2071
2072 if (coex->wl_rf_off) {
2073 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2074 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2075 coex->stop_dm = true;
2076 } else if (wifi_only) {
2077 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
2078 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2079 true);
2080 coex->stop_dm = true;
2081 } else {
2082 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
2083 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2084 true);
2085 coex->stop_dm = false;
2086 coex->freeze = true;
2087 }
2088
2089
2090 rtw_coex_table(rtwdev, 0);
2091 rtw_coex_tdma(rtwdev, true, 0);
2092 rtw_coex_query_bt_info(rtwdev);
2093}
2094
2095void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
2096{
2097 struct rtw_coex *coex = &rtwdev->coex;
2098
2099 coex->stop_dm = true;
2100 coex->wl_rf_off = false;
2101
2102
2103 rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1));
2104
2105 rtw_coex_monitor_bt_enable(rtwdev);
2106 rtw_coex_set_rfe_type(rtwdev);
2107
2108
2109 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
2110
2111
2112 rtw_write8(rtwdev, 0xff1a, 0x0);
2113}
2114
2115void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2116{
2117 __rtw_coex_init_hw_config(rtwdev, wifi_only);
2118}
2119
2120void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
2121{
2122 struct rtw_coex *coex = &rtwdev->coex;
2123 struct rtw_coex_stat *coex_stat = &coex->stat;
2124
2125 if (coex->stop_dm)
2126 return;
2127
2128 if (type == COEX_IPS_ENTER) {
2129 coex_stat->wl_under_ips = true;
2130
2131
2132 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2133
2134 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2135 rtw_coex_action_coex_all_off(rtwdev);
2136 } else if (type == COEX_IPS_LEAVE) {
2137 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2138
2139
2140 __rtw_coex_init_hw_config(rtwdev, false);
2141
2142
2143 coex_stat->wl_under_ips = false;
2144 }
2145}
2146
2147void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
2148{
2149 struct rtw_coex *coex = &rtwdev->coex;
2150 struct rtw_coex_stat *coex_stat = &coex->stat;
2151
2152 if (coex->stop_dm)
2153 return;
2154
2155 if (type == COEX_LPS_ENABLE) {
2156 coex_stat->wl_under_lps = true;
2157
2158 if (coex_stat->wl_force_lps_ctrl) {
2159
2160 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2161 } else {
2162
2163 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2164
2165 rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2166 }
2167 } else if (type == COEX_LPS_DISABLE) {
2168 coex_stat->wl_under_lps = false;
2169
2170
2171 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2172
2173 if (!coex_stat->wl_force_lps_ctrl)
2174 rtw_coex_query_bt_info(rtwdev);
2175 }
2176}
2177
2178void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
2179{
2180 struct rtw_coex *coex = &rtwdev->coex;
2181 struct rtw_coex_stat *coex_stat = &coex->stat;
2182
2183 if (coex->stop_dm)
2184 return;
2185
2186 coex->freeze = false;
2187
2188 if (type != COEX_SCAN_FINISH)
2189 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2190 COEX_SCBD_ONOFF, true);
2191
2192 if (type == COEX_SCAN_START_5G) {
2193 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2194 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
2195 } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
2196 coex_stat->wl_hi_pri_task2 = true;
2197
2198
2199 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2200 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
2201 } else {
2202 coex_stat->wl_hi_pri_task2 = false;
2203 rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
2204 }
2205}
2206
2207void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
2208{
2209 struct rtw_coex *coex = &rtwdev->coex;
2210
2211 if (coex->stop_dm)
2212 return;
2213
2214 if (type == COEX_SWITCH_TO_5G)
2215 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
2216 else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
2217 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
2218 else
2219 rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
2220}
2221
2222void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
2223{
2224 struct rtw_coex *coex = &rtwdev->coex;
2225 struct rtw_coex_stat *coex_stat = &coex->stat;
2226
2227 if (coex->stop_dm)
2228 return;
2229
2230 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2231 COEX_SCBD_ONOFF, true);
2232
2233 if (type == COEX_ASSOCIATE_5G_START) {
2234 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2235 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
2236 } else if (type == COEX_ASSOCIATE_5G_FINISH) {
2237 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2238 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
2239 } else if (type == COEX_ASSOCIATE_START) {
2240 coex_stat->wl_hi_pri_task1 = true;
2241 coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
2242
2243
2244 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2245
2246 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
2247
2248
2249
2250
2251 coex->freeze = true;
2252 ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
2253 5 * HZ);
2254 } else {
2255 coex_stat->wl_hi_pri_task1 = false;
2256 coex->freeze = false;
2257
2258 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
2259 }
2260}
2261
2262void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
2263{
2264 struct rtw_coex *coex = &rtwdev->coex;
2265 struct rtw_coex_stat *coex_stat = &coex->stat;
2266 u8 para[6] = {0};
2267
2268 if (coex->stop_dm)
2269 return;
2270
2271 if (type == COEX_MEDIA_CONNECT_5G) {
2272 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2273
2274 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2275 rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
2276 } else if (type == COEX_MEDIA_CONNECT) {
2277 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2278
2279
2280 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2281
2282
2283 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
2284
2285
2286 para[0] = COEX_H2C69_WL_LEAKAP;
2287 para[1] = PARA1_H2C69_EN_5MS;
2288 rtw_fw_bt_wifi_control(rtwdev, para[0], ¶[1]);
2289 coex_stat->wl_slot_extend = true;
2290 rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
2291 } else {
2292 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2293
2294 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
2295
2296 rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
2297 }
2298
2299 rtw_coex_update_wl_ch_info(rtwdev, type);
2300}
2301
2302void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2303{
2304 struct rtw_coex *coex = &rtwdev->coex;
2305 struct rtw_coex_stat *coex_stat = &coex->stat;
2306 struct rtw_chip_info *chip = rtwdev->chip;
2307 unsigned long bt_relink_time;
2308 u8 i, rsp_source = 0, type;
2309 bool inq_page = false;
2310
2311 rsp_source = buf[0] & 0xf;
2312 if (rsp_source >= COEX_BTINFO_SRC_MAX)
2313 rsp_source = COEX_BTINFO_SRC_WL_FW;
2314
2315 if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
2316 coex_stat->bt_iqk_state = buf[1];
2317 if (coex_stat->bt_iqk_state == 1)
2318 coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
2319 else if (coex_stat->bt_iqk_state == 2)
2320 coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
2321
2322 return;
2323 }
2324
2325 if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
2326 rtw_coex_monitor_bt_enable(rtwdev);
2327 if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
2328 coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
2329 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2330 }
2331 return;
2332 }
2333
2334 if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
2335 rsp_source == COEX_BTINFO_SRC_BT_ACT) {
2336 if (coex_stat->bt_disabled) {
2337 coex_stat->bt_disabled = false;
2338 coex_stat->bt_reenable = true;
2339 ieee80211_queue_delayed_work(rtwdev->hw,
2340 &coex->bt_reenable_work,
2341 15 * HZ);
2342 }
2343 }
2344
2345 for (i = 0; i < length; i++) {
2346 if (i < COEX_BTINFO_LENGTH_MAX)
2347 coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
2348 else
2349 break;
2350 }
2351
2352 if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
2353 rtw_coex_update_bt_link_info(rtwdev);
2354 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2355 return;
2356 }
2357
2358
2359 if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
2360 coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
2361 coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
2362 coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
2363 coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
2364 coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3)
2365 return;
2366
2367 coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
2368 coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
2369 coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
2370 coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
2371 coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
2372 coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
2373
2374
2375 coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
2376
2377 inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
2378
2379 if (inq_page != coex_stat->bt_inq_page) {
2380 cancel_delayed_work_sync(&coex->bt_remain_work);
2381 coex_stat->bt_inq_page = inq_page;
2382
2383 if (inq_page)
2384 coex_stat->bt_inq_remain = true;
2385 else
2386 ieee80211_queue_delayed_work(rtwdev->hw,
2387 &coex->bt_remain_work,
2388 4 * HZ);
2389 }
2390 coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
2391 coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
2392 if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
2393 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
2394
2395 coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
2396 coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
2397 if (coex_stat->bt_inq)
2398 coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
2399
2400 coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
2401 if (coex_stat->bt_page) {
2402 coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
2403 if (coex_stat->wl_linkscan_proc ||
2404 coex_stat->wl_hi_pri_task1 ||
2405 coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
2406 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
2407 else
2408 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2409 } else {
2410 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2411 }
2412
2413
2414 if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
2415 coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
2416 } else {
2417 if (coex_stat->bt_info_hb0 <= 127)
2418 coex_stat->bt_rssi = 100;
2419 else if (256 - coex_stat->bt_info_hb0 <= 100)
2420 coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
2421 else
2422 coex_stat->bt_rssi = 0;
2423 }
2424
2425 coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0));
2426 if (coex_stat->bt_info_hb1 & BIT(1))
2427 coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
2428
2429 if (coex_stat->bt_info_hb1 & BIT(2)) {
2430 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
2431 coex_stat->bt_setup_link = true;
2432 if (coex_stat->bt_reenable)
2433 bt_relink_time = 6 * HZ;
2434 else
2435 bt_relink_time = 2 * HZ;
2436
2437 ieee80211_queue_delayed_work(rtwdev->hw,
2438 &coex->bt_relink_work,
2439 bt_relink_time);
2440 }
2441
2442 if (coex_stat->bt_info_hb1 & BIT(3))
2443 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
2444
2445 coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
2446 coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
2447 if (coex_stat->bt_info_hb1 & BIT(6))
2448 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
2449
2450 coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
2451
2452 if ((coex_stat->bt_info_hb1 & BIT(1))) {
2453 if (coex_stat->wl_connected)
2454 type = COEX_MEDIA_CONNECT;
2455 else
2456 type = COEX_MEDIA_DISCONNECT;
2457 rtw_coex_update_wl_ch_info(rtwdev, type);
2458 }
2459
2460
2461 if ((coex_stat->bt_info_hb1 & BIT(3)) &&
2462 (!(coex_stat->bt_info_hb1 & BIT(2))))
2463 rtw_coex_ignore_wlan_act(rtwdev, false);
2464
2465 coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
2466 if (coex_stat->bt_info_hb2 & BIT(1))
2467 coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
2468
2469 coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
2470 coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
2471 coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
2472 coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
2473 if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
2474 coex_stat->bt_418_hid_exist = true;
2475 else if (coex_stat->bt_hid_pair_num == 0)
2476 coex_stat->bt_418_hid_exist = false;
2477
2478 if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
2479 coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
2480 else
2481 coex_stat->bt_a2dp_bitpool = 0;
2482
2483 coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
2484
2485 rtw_coex_update_bt_link_info(rtwdev);
2486 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2487}
2488
2489void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2490{
2491 struct rtw_coex *coex = &rtwdev->coex;
2492 struct rtw_coex_stat *coex_stat = &coex->stat;
2493 u8 val;
2494 int i;
2495
2496 if (WARN(length < 8, "invalid wl info c2h length\n"))
2497 return;
2498
2499 if (buf[0] != 0x08)
2500 return;
2501
2502 for (i = 1; i < 8; i++) {
2503 val = coex_stat->wl_fw_dbg_info_pre[i];
2504 if (buf[i] >= val)
2505 coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
2506 else
2507 coex_stat->wl_fw_dbg_info[i] = val - buf[i];
2508
2509 coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
2510 }
2511
2512 coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
2513 rtw_coex_wl_ccklock_action(rtwdev);
2514 rtw_coex_wl_ccklock_detect(rtwdev);
2515}
2516
2517void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev)
2518{
2519 struct rtw_coex *coex = &rtwdev->coex;
2520
2521 if (coex->stop_dm)
2522 return;
2523
2524 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2525}
2526
2527void rtw_coex_bt_relink_work(struct work_struct *work)
2528{
2529 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2530 coex.bt_relink_work.work);
2531 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2532
2533 mutex_lock(&rtwdev->mutex);
2534 coex_stat->bt_setup_link = false;
2535 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2536 mutex_unlock(&rtwdev->mutex);
2537}
2538
2539void rtw_coex_bt_reenable_work(struct work_struct *work)
2540{
2541 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2542 coex.bt_reenable_work.work);
2543 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2544
2545 mutex_lock(&rtwdev->mutex);
2546 coex_stat->bt_reenable = false;
2547 mutex_unlock(&rtwdev->mutex);
2548}
2549
2550void rtw_coex_defreeze_work(struct work_struct *work)
2551{
2552 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2553 coex.defreeze_work.work);
2554 struct rtw_coex *coex = &rtwdev->coex;
2555 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2556
2557 mutex_lock(&rtwdev->mutex);
2558 coex->freeze = false;
2559 coex_stat->wl_hi_pri_task1 = false;
2560 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2561 mutex_unlock(&rtwdev->mutex);
2562}
2563
2564void rtw_coex_wl_remain_work(struct work_struct *work)
2565{
2566 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2567 coex.wl_remain_work.work);
2568 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2569
2570 mutex_lock(&rtwdev->mutex);
2571 coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
2572 rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2573 mutex_unlock(&rtwdev->mutex);
2574}
2575
2576void rtw_coex_bt_remain_work(struct work_struct *work)
2577{
2578 struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2579 coex.bt_remain_work.work);
2580 struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2581
2582 mutex_lock(&rtwdev->mutex);
2583 coex_stat->bt_inq_remain = coex_stat->bt_inq_page;
2584 rtw_coex_run_coex(rtwdev, COEX_RSN_BTSTATUS);
2585 mutex_unlock(&rtwdev->mutex);
2586}
2587
2588#ifdef CONFIG_RTW88_DEBUGFS
2589#define INFO_SIZE 80
2590
2591#define case_BTINFO(src) \
2592 case COEX_BTINFO_SRC_##src: return #src
2593
2594static const char *rtw_coex_get_bt_info_src_string(u8 bt_info_src)
2595{
2596 switch (bt_info_src) {
2597 case_BTINFO(WL_FW);
2598 case_BTINFO(BT_RSP);
2599 case_BTINFO(BT_ACT);
2600 default:
2601 return "Unknown";
2602 }
2603}
2604
2605#define case_RSN(src) \
2606 case COEX_RSN_##src: return #src
2607
2608static const char *rtw_coex_get_reason_string(u8 reason)
2609{
2610 switch (reason) {
2611 case_RSN(2GSCANSTART);
2612 case_RSN(5GSCANSTART);
2613 case_RSN(SCANFINISH);
2614 case_RSN(2GSWITCHBAND);
2615 case_RSN(5GSWITCHBAND);
2616 case_RSN(2GCONSTART);
2617 case_RSN(5GCONSTART);
2618 case_RSN(2GCONFINISH);
2619 case_RSN(5GCONFINISH);
2620 case_RSN(2GMEDIA);
2621 case_RSN(5GMEDIA);
2622 case_RSN(MEDIADISCON);
2623 case_RSN(BTINFO);
2624 case_RSN(LPS);
2625 case_RSN(WLSTATUS);
2626 default:
2627 return "Unknown";
2628 }
2629}
2630
2631static int rtw_coex_addr_info(struct rtw_dev *rtwdev,
2632 const struct rtw_reg_domain *reg,
2633 char addr_info[], int n)
2634{
2635 const char *rf_prefix = "";
2636 const char *sep = n == 0 ? "" : "/ ";
2637 int ffs, fls;
2638 int max_fls;
2639
2640 if (INFO_SIZE - n <= 0)
2641 return 0;
2642
2643 switch (reg->domain) {
2644 case RTW_REG_DOMAIN_MAC32:
2645 max_fls = 31;
2646 break;
2647 case RTW_REG_DOMAIN_MAC16:
2648 max_fls = 15;
2649 break;
2650 case RTW_REG_DOMAIN_MAC8:
2651 max_fls = 7;
2652 break;
2653 case RTW_REG_DOMAIN_RF_A:
2654 case RTW_REG_DOMAIN_RF_B:
2655 rf_prefix = "RF_";
2656 max_fls = 19;
2657 break;
2658 default:
2659 return 0;
2660 }
2661
2662 ffs = __ffs(reg->mask);
2663 fls = __fls(reg->mask);
2664
2665 if (ffs == 0 && fls == max_fls)
2666 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x",
2667 sep, rf_prefix, reg->addr);
2668 else if (ffs == fls)
2669 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d]",
2670 sep, rf_prefix, reg->addr, ffs);
2671 else
2672 return scnprintf(addr_info + n, INFO_SIZE - n, "%s%s%x[%d:%d]",
2673 sep, rf_prefix, reg->addr, fls, ffs);
2674}
2675
2676static int rtw_coex_val_info(struct rtw_dev *rtwdev,
2677 const struct rtw_reg_domain *reg,
2678 char val_info[], int n)
2679{
2680 const char *sep = n == 0 ? "" : "/ ";
2681 u8 rf_path;
2682
2683 if (INFO_SIZE - n <= 0)
2684 return 0;
2685
2686 switch (reg->domain) {
2687 case RTW_REG_DOMAIN_MAC32:
2688 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2689 rtw_read32_mask(rtwdev, reg->addr, reg->mask));
2690 case RTW_REG_DOMAIN_MAC16:
2691 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2692 rtw_read16_mask(rtwdev, reg->addr, reg->mask));
2693 case RTW_REG_DOMAIN_MAC8:
2694 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2695 rtw_read8_mask(rtwdev, reg->addr, reg->mask));
2696 case RTW_REG_DOMAIN_RF_A:
2697 rf_path = RF_PATH_A;
2698 break;
2699 case RTW_REG_DOMAIN_RF_B:
2700 rf_path = RF_PATH_B;
2701 break;
2702 default:
2703 return 0;
2704 }
2705
2706
2707 return scnprintf(val_info + n, INFO_SIZE - n, "%s0x%x", sep,
2708 rtw_read_rf(rtwdev, rf_path, reg->addr, reg->mask));
2709}
2710
2711static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
2712{
2713 struct rtw_chip_info *chip = rtwdev->chip;
2714 const struct rtw_reg_domain *reg;
2715 char addr_info[INFO_SIZE];
2716 int n_addr = 0;
2717 char val_info[INFO_SIZE];
2718 int n_val = 0;
2719 int i;
2720
2721 for (i = 0; i < chip->coex_info_hw_regs_num; i++) {
2722 reg = &chip->coex_info_hw_regs[i];
2723
2724 n_addr += rtw_coex_addr_info(rtwdev, reg, addr_info, n_addr);
2725 n_val += rtw_coex_val_info(rtwdev, reg, val_info, n_val);
2726
2727 if (reg->domain == RTW_REG_DOMAIN_NL) {
2728 seq_printf(m, "%-40s = %s\n", addr_info, val_info);
2729 n_addr = 0;
2730 n_val = 0;
2731 }
2732 }
2733
2734 if (n_addr != 0 && n_val != 0)
2735 seq_printf(m, "%-40s = %s\n", addr_info, val_info);
2736}
2737
2738static bool rtw_coex_get_bt_reg(struct rtw_dev *rtwdev,
2739 u8 type, u16 addr, u16 *val)
2740{
2741 struct rtw_coex_info_req req = {0};
2742 struct sk_buff *skb;
2743 __le16 le_addr;
2744 u8 *payload;
2745
2746 le_addr = cpu_to_le16(addr);
2747 req.op_code = BT_MP_INFO_OP_READ_REG;
2748 req.para1 = type;
2749 req.para2 = le16_get_bits(le_addr, GENMASK(7, 0));
2750 req.para3 = le16_get_bits(le_addr, GENMASK(15, 8));
2751 skb = rtw_coex_info_request(rtwdev, &req);
2752 if (!skb) {
2753 *val = 0xeaea;
2754 return false;
2755 }
2756
2757 payload = get_payload_from_coex_resp(skb);
2758 *val = GET_COEX_RESP_BT_REG_VAL(payload);
2759
2760 return true;
2761}
2762
2763static bool rtw_coex_get_bt_patch_version(struct rtw_dev *rtwdev,
2764 u32 *patch_version)
2765{
2766 struct rtw_coex_info_req req = {0};
2767 struct sk_buff *skb;
2768 u8 *payload;
2769 bool ret = false;
2770
2771 req.op_code = BT_MP_INFO_OP_PATCH_VER;
2772 skb = rtw_coex_info_request(rtwdev, &req);
2773 if (!skb)
2774 goto out;
2775
2776 payload = get_payload_from_coex_resp(skb);
2777 *patch_version = GET_COEX_RESP_BT_PATCH_VER(payload);
2778 ret = true;
2779
2780out:
2781 return ret;
2782}
2783
2784static bool rtw_coex_get_bt_supported_version(struct rtw_dev *rtwdev,
2785 u32 *supported_version)
2786{
2787 struct rtw_coex_info_req req = {0};
2788 struct sk_buff *skb;
2789 u8 *payload;
2790 bool ret = false;
2791
2792 req.op_code = BT_MP_INFO_OP_SUPP_VER;
2793 skb = rtw_coex_info_request(rtwdev, &req);
2794 if (!skb)
2795 goto out;
2796
2797 payload = get_payload_from_coex_resp(skb);
2798 *supported_version = GET_COEX_RESP_BT_SUPP_VER(payload);
2799 ret = true;
2800
2801out:
2802 return ret;
2803}
2804
2805static bool rtw_coex_get_bt_supported_feature(struct rtw_dev *rtwdev,
2806 u32 *supported_feature)
2807{
2808 struct rtw_coex_info_req req = {0};
2809 struct sk_buff *skb;
2810 u8 *payload;
2811 bool ret = false;
2812
2813 req.op_code = BT_MP_INFO_OP_SUPP_FEAT;
2814 skb = rtw_coex_info_request(rtwdev, &req);
2815 if (!skb)
2816 goto out;
2817
2818 payload = get_payload_from_coex_resp(skb);
2819 *supported_feature = GET_COEX_RESP_BT_SUPP_FEAT(payload);
2820 ret = true;
2821
2822out:
2823 return ret;
2824}
2825
2826struct rtw_coex_sta_stat_iter_data {
2827 struct rtw_vif *rtwvif;
2828 struct seq_file *file;
2829};
2830
2831static void rtw_coex_sta_stat_iter(void *data, struct ieee80211_sta *sta)
2832{
2833 struct rtw_coex_sta_stat_iter_data *sta_iter_data = data;
2834 struct rtw_vif *rtwvif = sta_iter_data->rtwvif;
2835 struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
2836 struct seq_file *m = sta_iter_data->file;
2837 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
2838 u8 rssi;
2839
2840 if (si->vif != vif)
2841 return;
2842
2843 rssi = ewma_rssi_read(&si->avg_rssi);
2844 seq_printf(m, "\tPeer %3d\n", si->mac_id);
2845 seq_printf(m, "\t\t%-24s = %d\n", "RSSI", rssi);
2846 seq_printf(m, "\t\t%-24s = %d\n", "BW mode", si->bw_mode);
2847}
2848
2849struct rtw_coex_vif_stat_iter_data {
2850 struct rtw_dev *rtwdev;
2851 struct seq_file *file;
2852};
2853
2854static void rtw_coex_vif_stat_iter(void *data, u8 *mac,
2855 struct ieee80211_vif *vif)
2856{
2857 struct rtw_coex_vif_stat_iter_data *vif_iter_data = data;
2858 struct rtw_coex_sta_stat_iter_data sta_iter_data;
2859 struct rtw_dev *rtwdev = vif_iter_data->rtwdev;
2860 struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
2861 struct seq_file *m = vif_iter_data->file;
2862 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
2863
2864 seq_printf(m, "Iface on Port (%d)\n", rtwvif->port);
2865 seq_printf(m, "\t%-32s = %d\n",
2866 "Beacon interval", bss_conf->beacon_int);
2867 seq_printf(m, "\t%-32s = %d\n",
2868 "Network Type", rtwvif->net_type);
2869
2870 sta_iter_data.rtwvif = rtwvif;
2871 sta_iter_data.file = m;
2872 rtw_iterate_stas_atomic(rtwdev, rtw_coex_sta_stat_iter,
2873 &sta_iter_data);
2874}
2875
2876void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
2877{
2878 struct rtw_chip_info *chip = rtwdev->chip;
2879 struct rtw_dm_info *dm_info = &rtwdev->dm_info;
2880 struct rtw_coex *coex = &rtwdev->coex;
2881 struct rtw_coex_stat *coex_stat = &coex->stat;
2882 struct rtw_coex_dm *coex_dm = &coex->dm;
2883 struct rtw_hal *hal = &rtwdev->hal;
2884 struct rtw_efuse *efuse = &rtwdev->efuse;
2885 struct rtw_fw_state *fw = &rtwdev->fw;
2886 struct rtw_coex_vif_stat_iter_data vif_iter_data;
2887 u8 reason = coex_dm->reason;
2888 u8 sys_lte;
2889 u16 score_board_WB, score_board_BW;
2890 u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
2891 u32 lte_coex, bt_coex;
2892 u32 bt_hi_pri, bt_lo_pri;
2893 int i;
2894
2895 score_board_BW = rtw_coex_read_scbd(rtwdev);
2896 score_board_WB = coex_stat->score_board;
2897 wl_reg_6c0 = rtw_read32(rtwdev, 0x6c0);
2898 wl_reg_6c4 = rtw_read32(rtwdev, 0x6c4);
2899 wl_reg_6c8 = rtw_read32(rtwdev, 0x6c8);
2900 wl_reg_6cc = rtw_read32(rtwdev, 0x6cc);
2901 wl_reg_778 = rtw_read32(rtwdev, 0x778);
2902 bt_hi_pri = rtw_read32(rtwdev, 0x770);
2903 bt_lo_pri = rtw_read32(rtwdev, 0x774);
2904 rtw_write8(rtwdev, 0x76e, 0xc);
2905 sys_lte = rtw_read8(rtwdev, 0x73);
2906 lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
2907 bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
2908
2909 if (!coex_stat->bt_disabled && !coex_stat->bt_mailbox_reply) {
2910 rtw_coex_get_bt_supported_version(rtwdev,
2911 &coex_stat->bt_supported_version);
2912 rtw_coex_get_bt_patch_version(rtwdev, &coex_stat->patch_ver);
2913 rtw_coex_get_bt_supported_feature(rtwdev,
2914 &coex_stat->bt_supported_feature);
2915 rtw_coex_get_bt_reg(rtwdev, 3, 0xae, &coex_stat->bt_reg_vendor_ae);
2916 rtw_coex_get_bt_reg(rtwdev, 3, 0xac, &coex_stat->bt_reg_vendor_ac);
2917
2918 if (coex_stat->patch_ver != 0)
2919 coex_stat->bt_mailbox_reply = true;
2920 }
2921
2922 seq_printf(m, "**********************************************\n");
2923 seq_printf(m, "\t\tBT Coexist info %x\n", chip->id);
2924 seq_printf(m, "**********************************************\n");
2925 seq_printf(m, "%-40s = %s/ %d\n",
2926 "Mech/ RFE",
2927 efuse->share_ant ? "Shared" : "Non-Shared",
2928 efuse->rfe_option);
2929 seq_printf(m, "%-40s = %08x/ 0x%02x/ 0x%08x %s\n",
2930 "Coex Ver/ BT Dez/ BT Rpt",
2931 chip->coex_para_ver, chip->bt_desired_ver,
2932 coex_stat->bt_supported_version,
2933 coex_stat->bt_disabled ? "(BT disabled)" :
2934 coex_stat->bt_supported_version >= chip->bt_desired_ver ?
2935 "(Match)" : "(Mismatch)");
2936 seq_printf(m, "%-40s = %s/ %u/ %d\n",
2937 "Role/ RoleSwCnt/ IgnWL/ Feature",
2938 coex_stat->bt_slave ? "Slave" : "Master",
2939 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH],
2940 coex_dm->ignore_wl_act);
2941 seq_printf(m, "%-40s = %u.%u/ 0x%x/ %c\n",
2942 "WL FW/ BT FW/ KT",
2943 fw->version, fw->sub_version,
2944 coex_stat->patch_ver, coex_stat->kt_ver + 65);
2945 seq_printf(m, "%-40s = %u/ %u/ %u/ ch-(%u)\n",
2946 "AFH Map",
2947 coex_dm->wl_ch_info[0], coex_dm->wl_ch_info[1],
2948 coex_dm->wl_ch_info[2], hal->current_channel);
2949
2950 seq_printf(m, "**********************************************\n");
2951 seq_printf(m, "\t\tBT Status\n");
2952 seq_printf(m, "**********************************************\n");
2953 seq_printf(m, "%-40s = %s/ %ddBm/ %u/ %u\n",
2954 "BT status/ rssi/ retry/ pop",
2955 coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ? "non-conn" :
2956 coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE ? "conn-idle" : "busy",
2957 coex_stat->bt_rssi - 100,
2958 coex_stat->cnt_bt[COEX_CNT_BT_RETRY],
2959 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]);
2960 seq_printf(m, "%-40s = %s%s%s%s%s (multi-link %d)\n",
2961 "Profiles",
2962 coex_stat->bt_a2dp_exist ? (coex_stat->bt_a2dp_sink ?
2963 "A2DP sink," : "A2DP,") : "",
2964 coex_stat->bt_hfp_exist ? "HFP," : "",
2965 coex_stat->bt_hid_exist ?
2966 (coex_stat->bt_ble_exist ? "HID(RCU)," :
2967 coex_stat->bt_hid_slot >= 2 ? "HID(4/18)" :
2968 "HID(2/18),") : "",
2969 coex_stat->bt_pan_exist ? coex_stat->bt_opp_exist ?
2970 "OPP," : "PAN," : "",
2971 coex_stat->bt_ble_voice ? "Voice," : "",
2972 coex_stat->bt_multi_link);
2973 seq_printf(m, "%-40s = %u/ %u/ %u/ 0x%08x\n",
2974 "Reinit/ Relink/ IgnWl/ Feature",
2975 coex_stat->cnt_bt[COEX_CNT_BT_REINIT],
2976 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK],
2977 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT],
2978 coex_stat->bt_supported_feature);
2979 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
2980 "Page/ Inq/ iqk/ iqk fail",
2981 coex_stat->cnt_bt[COEX_CNT_BT_PAGE],
2982 coex_stat->cnt_bt[COEX_CNT_BT_INQ],
2983 coex_stat->cnt_bt[COEX_CNT_BT_IQK],
2984 coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]);
2985 seq_printf(m, "%-40s = 0x%04x/ 0x%04x/ 0x%04x/ 0x%04x\n",
2986 "0xae/ 0xac/ score board (W->B)/ (B->W)",
2987 coex_stat->bt_reg_vendor_ae,
2988 coex_stat->bt_reg_vendor_ac,
2989 score_board_WB, score_board_BW);
2990 seq_printf(m, "%-40s = %u/%u, %u/%u\n",
2991 "Hi-Pri TX/RX, Lo-Pri TX/RX",
2992 bt_hi_pri & 0xffff, bt_hi_pri >> 16,
2993 bt_lo_pri & 0xffff, bt_lo_pri >> 16);
2994 for (i = 0; i < COEX_BTINFO_SRC_BT_IQK; i++)
2995 seq_printf(m, "%-40s = %7ph\n",
2996 rtw_coex_get_bt_info_src_string(i),
2997 coex_stat->bt_info_c2h[i]);
2998
2999 seq_printf(m, "**********************************************\n");
3000 seq_printf(m, "\t\tWiFi Status\n");
3001 seq_printf(m, "**********************************************\n");
3002 seq_printf(m, "%-40s = %d\n",
3003 "Scanning", test_bit(RTW_FLAG_SCANNING, rtwdev->flags));
3004 seq_printf(m, "%-40s = %u/ TX %d Mbps/ RX %d Mbps\n",
3005 "G_busy/ TX/ RX",
3006 coex_stat->wl_gl_busy,
3007 rtwdev->stats.tx_throughput, rtwdev->stats.rx_throughput);
3008 seq_printf(m, "%-40s = %u/ %u/ %u\n",
3009 "IPS/ Low Power/ PS mode",
3010 test_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags),
3011 test_bit(RTW_FLAG_LEISURE_PS_DEEP, rtwdev->flags),
3012 rtwdev->lps_conf.mode);
3013
3014 vif_iter_data.rtwdev = rtwdev;
3015 vif_iter_data.file = m;
3016 rtw_iterate_vifs_atomic(rtwdev, rtw_coex_vif_stat_iter, &vif_iter_data);
3017
3018 seq_printf(m, "**********************************************\n");
3019 seq_printf(m, "\t\tMechanism\n");
3020 seq_printf(m, "**********************************************\n");
3021 seq_printf(m, "%-40s = %5ph (case-%d)\n",
3022 "TDMA",
3023 coex_dm->ps_tdma_para, coex_dm->cur_ps_tdma);
3024 seq_printf(m, "%-40s = %d\n",
3025 "Timer base", coex_stat->tdma_timer_base);
3026 seq_printf(m, "%-40s = %d/ 0x%08x/ 0x%08x/ 0x%08x\n",
3027 "Table/ 0x6c0/ 0x6c4/ 0x6c8",
3028 coex_dm->cur_table, wl_reg_6c0, wl_reg_6c4, wl_reg_6c8);
3029 seq_printf(m, "%-40s = 0x%08x/ 0x%08x/ reason (%s)\n",
3030 "0x778/ 0x6cc/ Reason",
3031 wl_reg_778, wl_reg_6cc, rtw_coex_get_reason_string(reason));
3032 seq_printf(m, "%-40s = %u/ %u/ %u/ %u/ %u\n",
3033 "Null All/ Retry/ Ack/ BT Empty/ BT Late",
3034 coex_stat->wl_fw_dbg_info[1], coex_stat->wl_fw_dbg_info[2],
3035 coex_stat->wl_fw_dbg_info[3], coex_stat->wl_fw_dbg_info[4],
3036 coex_stat->wl_fw_dbg_info[5]);
3037 seq_printf(m, "%-40s = %u/ %u/ %s/ %u\n",
3038 "Cnt TDMA Toggle/ Lk 5ms/ Lk 5ms on/ FW",
3039 coex_stat->wl_fw_dbg_info[6],
3040 coex_stat->wl_fw_dbg_info[7],
3041 coex_stat->wl_slot_extend ? "Yes" : "No",
3042 coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]);
3043
3044 seq_printf(m, "**********************************************\n");
3045 seq_printf(m, "\t\tHW setting\n");
3046 seq_printf(m, "**********************************************\n");
3047 seq_printf(m, "%-40s = %s/ %s\n",
3048 "LTE Coex/ Path Owner",
3049 lte_coex & BIT(7) ? "ON" : "OFF",
3050 sys_lte & BIT(2) ? "WL" : "BT");
3051 seq_printf(m, "%-40s = RF:%s_BB:%s/ RF:%s_BB:%s/ %s\n",
3052 "GNT_WL_CTRL/ GNT_BT_CTRL/ Dbg",
3053 lte_coex & BIT(12) ? "SW" : "HW",
3054 lte_coex & BIT(8) ? "SW" : "HW",
3055 lte_coex & BIT(14) ? "SW" : "HW",
3056 lte_coex & BIT(10) ? "SW" : "HW",
3057 sys_lte & BIT(3) ? "On" : "Off");
3058 seq_printf(m, "%-40s = %lu/ %lu\n",
3059 "GNT_WL/ GNT_BT",
3060 (bt_coex & BIT(2)) >> 2, (bt_coex & BIT(3)) >> 3);
3061 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3062 "CRC OK CCK/ OFDM/ HT/ VHT",
3063 dm_info->cck_ok_cnt, dm_info->ofdm_ok_cnt,
3064 dm_info->ht_ok_cnt, dm_info->vht_ok_cnt);
3065 seq_printf(m, "%-40s = %u/ %u/ %u/ %u\n",
3066 "CRC ERR CCK/ OFDM/ HT/ VHT",
3067 dm_info->cck_err_cnt, dm_info->ofdm_err_cnt,
3068 dm_info->ht_err_cnt, dm_info->vht_err_cnt);
3069 seq_printf(m, "%-40s = %s/ %s/ %s/ %u\n",
3070 "HiPr/ Locking/ Locked/ Noisy",
3071 coex_stat->wl_hi_pri_task1 ? "Y" : "N",
3072 coex_stat->wl_cck_lock ? "Y" : "N",
3073 coex_stat->wl_cck_lock_ever ? "Y" : "N",
3074 coex_stat->wl_noisy_level);
3075
3076 rtw_coex_set_coexinfo_hw(rtwdev, m);
3077}
3078#endif
3079