]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/net/wireless/realtek/rtw88/coex.c
rtw88: not to control LPS by each vif
[linux.git] / drivers / net / wireless / realtek / rtw88 / coex.c
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2018-2019  Realtek Corporation
3  */
4
5 #include "main.h"
6 #include "coex.h"
7 #include "fw.h"
8 #include "ps.h"
9 #include "debug.h"
10 #include "reg.h"
11
12 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
13                                    u8 rssi, u8 rssi_thresh)
14 {
15         struct rtw_chip_info *chip = rtwdev->chip;
16         u8 tol = chip->rssi_tolerance;
17         u8 next_state;
18
19         if (pre_state == COEX_RSSI_STATE_LOW ||
20             pre_state == COEX_RSSI_STATE_STAY_LOW) {
21                 if (rssi >= (rssi_thresh + tol))
22                         next_state = COEX_RSSI_STATE_HIGH;
23                 else
24                         next_state = COEX_RSSI_STATE_STAY_LOW;
25         } else {
26                 if (rssi < rssi_thresh)
27                         next_state = COEX_RSSI_STATE_LOW;
28                 else
29                         next_state = COEX_RSSI_STATE_STAY_HIGH;
30         }
31
32         return next_state;
33 }
34
35 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
36                                 bool tx_limit_en, bool ampdu_limit_en)
37 {
38         struct rtw_chip_info *chip = rtwdev->chip;
39         struct rtw_coex *coex = &rtwdev->coex;
40         struct rtw_coex_stat *coex_stat = &coex->stat;
41         bool wifi_under_b_mode = false;
42
43         if (!chip->scbd_support)
44                 return;
45
46         /* force max tx retry limit = 8 */
47         if (coex_stat->wl_tx_limit_en == tx_limit_en &&
48             coex_stat->wl_ampdu_limit_en == ampdu_limit_en)
49                 return;
50
51         if (!coex_stat->wl_tx_limit_en) {
52                 coex_stat->darfrc = rtw_read32(rtwdev, REG_DARFRC);
53                 coex_stat->darfrch = rtw_read32(rtwdev, REG_DARFRCH);
54                 coex_stat->retry_limit = rtw_read16(rtwdev, REG_RETRY_LIMIT);
55         }
56
57         if (!coex_stat->wl_ampdu_limit_en)
58                 coex_stat->ampdu_max_time =
59                                 rtw_read8(rtwdev, REG_AMPDU_MAX_TIME_V1);
60
61         coex_stat->wl_tx_limit_en = tx_limit_en;
62         coex_stat->wl_ampdu_limit_en = ampdu_limit_en;
63
64         if (tx_limit_en) {
65                 /* set BT polluted packet on for tx rate adaptive,
66                  * not including tx retry broken by PTA
67                  */
68                 rtw_write8_set(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
69
70                 /* set queue life time to avoid can't reach tx retry limit
71                  * if tx is always broken by GNT_BT
72                  */
73                 rtw_write8_set(rtwdev, REG_LIFETIME_EN, 0xf);
74                 rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x0808);
75
76                 /* auto rate fallback step within 8 retries */
77                 if (wifi_under_b_mode) {
78                         rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
79                         rtw_write32(rtwdev, REG_DARFRCH, 0x1010101);
80                 } else {
81                         rtw_write32(rtwdev, REG_DARFRC, 0x1000000);
82                         rtw_write32(rtwdev, REG_DARFRCH, 0x4030201);
83                 }
84         } else {
85                 rtw_write8_clr(rtwdev, REG_TX_HANG_CTRL, BIT_EN_GNT_BT_AWAKE);
86                 rtw_write8_clr(rtwdev, REG_LIFETIME_EN, 0xf);
87
88                 rtw_write16(rtwdev, REG_RETRY_LIMIT, coex_stat->retry_limit);
89                 rtw_write32(rtwdev, REG_DARFRC, coex_stat->darfrc);
90                 rtw_write32(rtwdev, REG_DARFRCH, coex_stat->darfrch);
91         }
92
93         if (ampdu_limit_en)
94                 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1, 0x20);
95         else
96                 rtw_write8(rtwdev, REG_AMPDU_MAX_TIME_V1,
97                            coex_stat->ampdu_max_time);
98 }
99
100 static void rtw_coex_limited_wl(struct rtw_dev *rtwdev)
101 {
102         struct rtw_coex *coex = &rtwdev->coex;
103         struct rtw_coex_dm *coex_dm = &coex->dm;
104         struct rtw_coex_stat *coex_stat = &coex->stat;
105         bool tx_limit = false;
106         bool tx_agg_ctrl = false;
107
108         if (coex->under_5g ||
109             coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
110                 /* no need to limit tx */
111         } else {
112                 tx_limit = true;
113                 if (coex_stat->bt_hid_exist || coex_stat->bt_hfp_exist ||
114                     coex_stat->bt_hid_pair_num > 0)
115                         tx_agg_ctrl = true;
116         }
117
118         rtw_coex_limited_tx(rtwdev, tx_limit, tx_agg_ctrl);
119 }
120
121 static void rtw_coex_wl_ccklock_action(struct rtw_dev *rtwdev)
122 {
123         struct rtw_coex *coex = &rtwdev->coex;
124         struct rtw_coex_stat *coex_stat = &coex->stat;
125         u8 para[6] = {0};
126
127         if (coex->stop_dm)
128                 return;
129
130         para[0] = COEX_H2C69_WL_LEAKAP;
131
132         if (coex_stat->tdma_timer_base == 3 && coex_stat->wl_slot_extend) {
133                 para[1] = PARA1_H2C69_DIS_5MS; /* disable 5ms extend */
134                 rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
135                 coex_stat->wl_slot_extend = false;
136                 coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
137                 return;
138         }
139
140         if (coex_stat->wl_slot_extend && coex_stat->wl_force_lps_ctrl &&
141             !coex_stat->wl_cck_lock_ever) {
142                 if (coex_stat->wl_fw_dbg_info[7] <= 5)
143                         coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND]++;
144                 else
145                         coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
146
147                 if (coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] == 7) {
148                         para[1] = 0x1; /* disable 5ms extend */
149                         rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
150                         coex_stat->wl_slot_extend = false;
151                         coex_stat->cnt_wl[COEX_CNT_WL_5MS_NOEXTEND] = 0;
152                 }
153         } else if (!coex_stat->wl_slot_extend && coex_stat->wl_cck_lock) {
154                 para[1] = 0x0; /* enable 5ms extend */
155                 rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
156                 coex_stat->wl_slot_extend = true;
157         }
158 }
159
160 static void rtw_coex_wl_ccklock_detect(struct rtw_dev *rtwdev)
161 {
162         struct rtw_coex *coex = &rtwdev->coex;
163         struct rtw_coex_stat *coex_stat = &coex->stat;
164
165         /* TODO: wait for rx_rate_change_notify implement */
166         coex_stat->wl_cck_lock = false;
167         coex_stat->wl_cck_lock_pre = false;
168         coex_stat->wl_cck_lock_ever = false;
169 }
170
171 static void rtw_coex_wl_noisy_detect(struct rtw_dev *rtwdev)
172 {
173         struct rtw_coex *coex = &rtwdev->coex;
174         struct rtw_coex_stat *coex_stat = &coex->stat;
175         struct rtw_dm_info *dm_info = &rtwdev->dm_info;
176         u32 cnt_cck;
177
178         /* wifi noisy environment identification */
179         cnt_cck = dm_info->cck_ok_cnt + dm_info->cck_err_cnt;
180
181         if (!coex_stat->wl_gl_busy) {
182                 if (cnt_cck > 250) {
183                         if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] < 5)
184                                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2]++;
185
186                         if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5) {
187                                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
188                                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
189                         }
190                 } else if (cnt_cck < 100) {
191                         if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] < 5)
192                                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0]++;
193
194                         if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] == 5) {
195                                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] = 0;
196                                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
197                         }
198                 } else {
199                         if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] < 5)
200                                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY1]++;
201
202                         if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5) {
203                                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY0] = 0;
204                                 coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] = 0;
205                         }
206                 }
207
208                 if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY2] == 5)
209                         coex_stat->wl_noisy_level = 2;
210                 else if (coex_stat->cnt_wl[COEX_CNT_WL_NOISY1] == 5)
211                         coex_stat->wl_noisy_level = 1;
212                 else
213                         coex_stat->wl_noisy_level = 0;
214         }
215 }
216
217 static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type)
218 {
219         struct rtw_coex *coex = &rtwdev->coex;
220         struct rtw_coex_stat *coex_stat = &coex->stat;
221         u8 para[2] = {0};
222
223         if (coex_stat->tdma_timer_base == type)
224                 return;
225
226         coex_stat->tdma_timer_base = type;
227
228         para[0] = COEX_H2C69_TDMA_SLOT;
229
230         if (type == 3) /* 4-slot  */
231                 para[1] = PARA1_H2C69_TDMA_4SLOT; /* 4-slot */
232         else /* 2-slot  */
233                 para[1] = PARA1_H2C69_TDMA_2SLOT;
234
235         rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
236
237         /* no 5ms_wl_slot_extend for 4-slot mode  */
238         if (coex_stat->tdma_timer_base == 3)
239                 rtw_coex_wl_ccklock_action(rtwdev);
240 }
241
242 static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
243                                      u8 data)
244 {
245         u32 addr;
246
247         addr = REG_BT_COEX_TABLE_H + (bitmap / 8);
248         bitmap = bitmap % 8;
249
250         rtw_write8_mask(rtwdev, addr, BIT(bitmap), data);
251 }
252
253 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
254 {
255         struct rtw_chip_info *chip = rtwdev->chip;
256         struct rtw_coex *coex = &rtwdev->coex;
257         struct rtw_coex_stat *coex_stat = &coex->stat;
258         u16 val = 0x2;
259
260         if (!chip->scbd_support)
261                 return;
262
263         val |= coex_stat->score_board;
264
265         /* for 8822b, scbd[10] is CQDDR on
266          * for 8822c, scbd[10] is no fix 2M
267          */
268         if (!chip->new_scbd10_def && (bitpos & COEX_SCBD_FIX2M)) {
269                 if (set)
270                         val &= ~COEX_SCBD_FIX2M;
271                 else
272                         val |= COEX_SCBD_FIX2M;
273         } else {
274                 if (set)
275                         val |= bitpos;
276                 else
277                         val &= ~bitpos;
278         }
279
280         if (val != coex_stat->score_board) {
281                 coex_stat->score_board = val;
282                 val |= BIT_BT_INT_EN;
283                 rtw_write16(rtwdev, REG_WIFI_BT_INFO, val);
284         }
285 }
286
287 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
288 {
289         struct rtw_chip_info *chip = rtwdev->chip;
290
291         if (!chip->scbd_support)
292                 return 0;
293
294         return (rtw_read16(rtwdev, REG_WIFI_BT_INFO)) & ~(BIT_BT_INT_EN);
295 }
296
297 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
298 {
299         struct rtw_chip_info *chip = rtwdev->chip;
300         struct rtw_coex *coex = &rtwdev->coex;
301         struct rtw_coex_stat *coex_stat = &coex->stat;
302         struct rtw_coex_rfe *coex_rfe = &coex->rfe;
303         u8 cnt = 0;
304         u32 wait_cnt;
305         bool btk, wlk;
306
307         if (coex_rfe->wlg_at_btg && chip->scbd_support &&
308             coex_stat->bt_iqk_state != 0xff) {
309                 wait_cnt = COEX_RFK_TIMEOUT / COEX_MIN_DELAY;
310                 do {
311                         /* BT RFK */
312                         btk = !!(rtw_coex_read_scbd(rtwdev) & COEX_SCBD_BT_RFK);
313
314                         /* WL RFK */
315                         wlk = !!(rtw_read8(rtwdev, REG_ARFR4) & BIT_WL_RFK);
316
317                         if (!btk && !wlk)
318                                 break;
319
320                         mdelay(COEX_MIN_DELAY);
321                 } while (++cnt < wait_cnt);
322
323                 if (cnt >= wait_cnt)
324                         coex_stat->bt_iqk_state = 0xff;
325         }
326 }
327
328 static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
329 {
330         struct rtw_coex *coex = &rtwdev->coex;
331         struct rtw_coex_stat *coex_stat = &coex->stat;
332
333         if (coex_stat->bt_disabled)
334                 return;
335
336         rtw_fw_query_bt_info(rtwdev);
337 }
338
339 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
340 {
341         struct rtw_chip_info *chip = rtwdev->chip;
342         struct rtw_coex *coex = &rtwdev->coex;
343         struct rtw_coex_stat *coex_stat = &coex->stat;
344         struct rtw_coex_dm *coex_dm = &coex->dm;
345         bool bt_disabled = false;
346         u16 score_board;
347
348         if (chip->scbd_support) {
349                 score_board = rtw_coex_read_scbd(rtwdev);
350                 bt_disabled = !(score_board & COEX_SCBD_ONOFF);
351         }
352
353         if (coex_stat->bt_disabled != bt_disabled) {
354                 rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: BT state changed (%d) -> (%d)\n",
355                         coex_stat->bt_disabled, bt_disabled);
356
357                 coex_stat->bt_disabled = bt_disabled;
358                 coex_stat->bt_ble_scan_type = 0;
359                 coex_dm->cur_bt_lna_lvl = 0;
360         }
361
362         if (!coex_stat->bt_disabled) {
363                 coex_stat->bt_reenable = true;
364                 ieee80211_queue_delayed_work(rtwdev->hw,
365                                              &coex->bt_reenable_work, 15 * HZ);
366         } else {
367                 coex_stat->bt_mailbox_reply = false;
368                 coex_stat->bt_reenable = false;
369         }
370 }
371
372 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
373 {
374         struct rtw_coex *coex = &rtwdev->coex;
375         struct rtw_coex_stat *coex_stat = &coex->stat;
376         struct rtw_coex_dm *coex_dm = &coex->dm;
377         struct rtw_chip_info *chip = rtwdev->chip;
378         struct rtw_traffic_stats *stats = &rtwdev->stats;
379         bool is_5G = false;
380         bool scan = false, link = false;
381         int i;
382         u8 rssi_state;
383         u8 rssi_step;
384         u8 rssi;
385
386         scan = test_bit(RTW_FLAG_SCANNING, rtwdev->flags);
387         coex_stat->wl_connected = !!rtwdev->sta_cnt;
388         coex_stat->wl_gl_busy = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
389
390         if (stats->tx_throughput > stats->rx_throughput)
391                 coex_stat->wl_tput_dir = COEX_WL_TPUT_TX;
392         else
393                 coex_stat->wl_tput_dir = COEX_WL_TPUT_RX;
394
395         if (scan || link || reason == COEX_RSN_2GCONSTART ||
396             reason == COEX_RSN_2GSCANSTART || reason == COEX_RSN_2GSWITCHBAND)
397                 coex_stat->wl_linkscan_proc = true;
398         else
399                 coex_stat->wl_linkscan_proc = false;
400
401         rtw_coex_wl_noisy_detect(rtwdev);
402
403         for (i = 0; i < 4; i++) {
404                 rssi_state = coex_dm->wl_rssi_state[i];
405                 rssi_step = chip->wl_rssi_step[i];
406                 rssi = rtwdev->dm_info.min_rssi;
407                 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
408                                                       rssi, rssi_step);
409                 coex_dm->wl_rssi_state[i] = rssi_state;
410         }
411
412         switch (reason) {
413         case COEX_RSN_5GSCANSTART:
414         case COEX_RSN_5GSWITCHBAND:
415         case COEX_RSN_5GCONSTART:
416
417                 is_5G = true;
418                 break;
419         case COEX_RSN_2GSCANSTART:
420         case COEX_RSN_2GSWITCHBAND:
421         case COEX_RSN_2GCONSTART:
422
423                 is_5G = false;
424                 break;
425         default:
426                 if (rtwdev->hal.current_band_type == RTW_BAND_5G)
427                         is_5G = true;
428                 else
429                         is_5G = false;
430                 break;
431         }
432
433         coex->under_5g = is_5G;
434 }
435
436 static inline u8 *get_payload_from_coex_resp(struct sk_buff *resp)
437 {
438         struct rtw_c2h_cmd *c2h;
439         u32 pkt_offset;
440
441         pkt_offset = *((u32 *)resp->cb);
442         c2h = (struct rtw_c2h_cmd *)(resp->data + pkt_offset);
443
444         return c2h->payload;
445 }
446
447 void rtw_coex_info_response(struct rtw_dev *rtwdev, struct sk_buff *skb)
448 {
449         struct rtw_coex *coex = &rtwdev->coex;
450         u8 *payload = get_payload_from_coex_resp(skb);
451
452         if (payload[0] != COEX_RESP_ACK_BY_WL_FW)
453                 return;
454
455         skb_queue_tail(&coex->queue, skb);
456         wake_up(&coex->wait);
457 }
458
459 static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev,
460                                              struct rtw_coex_info_req *req)
461 {
462         struct rtw_coex *coex = &rtwdev->coex;
463         struct sk_buff *skb_resp = NULL;
464
465         mutex_lock(&coex->mutex);
466
467         rtw_fw_query_bt_mp_info(rtwdev, req);
468
469         if (!wait_event_timeout(coex->wait, !skb_queue_empty(&coex->queue),
470                                 COEX_REQUEST_TIMEOUT)) {
471                 rtw_err(rtwdev, "coex request time out\n");
472                 goto out;
473         }
474
475         skb_resp = skb_dequeue(&coex->queue);
476         if (!skb_resp) {
477                 rtw_err(rtwdev, "failed to get coex info response\n");
478                 goto out;
479         }
480
481 out:
482         mutex_unlock(&coex->mutex);
483         return skb_resp;
484 }
485
486 static bool rtw_coex_get_bt_scan_type(struct rtw_dev *rtwdev, u8 *scan_type)
487 {
488         struct rtw_coex_info_req req = {0};
489         struct sk_buff *skb;
490         u8 *payload;
491         bool ret = false;
492
493         req.op_code = BT_MP_INFO_OP_SCAN_TYPE;
494         skb = rtw_coex_info_request(rtwdev, &req);
495         if (!skb)
496                 goto out;
497
498         payload = get_payload_from_coex_resp(skb);
499         *scan_type = GET_COEX_RESP_BT_SCAN_TYPE(payload);
500         dev_kfree_skb_any(skb);
501         ret = true;
502
503 out:
504         return ret;
505 }
506
507 static bool rtw_coex_set_lna_constrain_level(struct rtw_dev *rtwdev,
508                                              u8 lna_constrain_level)
509 {
510         struct rtw_coex_info_req req = {0};
511         struct sk_buff *skb;
512         bool ret = false;
513
514         req.op_code = BT_MP_INFO_OP_LNA_CONSTRAINT;
515         req.para1 = lna_constrain_level;
516         skb = rtw_coex_info_request(rtwdev, &req);
517         if (!skb)
518                 goto out;
519
520         dev_kfree_skb_any(skb);
521         ret = true;
522
523 out:
524         return ret;
525 }
526
527 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
528 {
529         struct rtw_coex *coex = &rtwdev->coex;
530         struct rtw_coex_stat *coex_stat = &coex->stat;
531         struct rtw_coex_dm *coex_dm = &coex->dm;
532         struct rtw_chip_info *chip = rtwdev->chip;
533         u8 i;
534         u8 rssi_state;
535         u8 rssi_step;
536         u8 rssi;
537
538         /* update wl/bt rssi by btinfo */
539         for (i = 0; i < COEX_RSSI_STEP; i++) {
540                 rssi_state = coex_dm->bt_rssi_state[i];
541                 rssi_step = chip->bt_rssi_step[i];
542                 rssi = coex_stat->bt_rssi;
543                 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
544                                                       rssi, rssi_step);
545                 coex_dm->bt_rssi_state[i] = rssi_state;
546         }
547
548         for (i = 0; i < COEX_RSSI_STEP; i++) {
549                 rssi_state = coex_dm->wl_rssi_state[i];
550                 rssi_step = chip->wl_rssi_step[i];
551                 rssi = rtwdev->dm_info.min_rssi;
552                 rssi_state = rtw_coex_next_rssi_state(rtwdev, rssi_state,
553                                                       rssi, rssi_step);
554                 coex_dm->wl_rssi_state[i] = rssi_state;
555         }
556
557         if (coex_stat->bt_ble_scan_en &&
558             coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE] % 3 == 0) {
559                 u8 scan_type;
560
561                 if (rtw_coex_get_bt_scan_type(rtwdev, &scan_type)) {
562                         coex_stat->bt_ble_scan_type = scan_type;
563                         if ((coex_stat->bt_ble_scan_type & 0x1) == 0x1)
564                                 coex_stat->bt_init_scan = true;
565                         else
566                                 coex_stat->bt_init_scan = false;
567                 }
568         }
569
570         coex_stat->bt_profile_num = 0;
571
572         /* set link exist status */
573         if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
574                 coex_stat->bt_link_exist = false;
575                 coex_stat->bt_pan_exist = false;
576                 coex_stat->bt_a2dp_exist = false;
577                 coex_stat->bt_hid_exist = false;
578                 coex_stat->bt_hfp_exist = false;
579         } else {
580                 /* connection exists */
581                 coex_stat->bt_link_exist = true;
582                 if (coex_stat->bt_info_lb2 & COEX_INFO_FTP) {
583                         coex_stat->bt_pan_exist = true;
584                         coex_stat->bt_profile_num++;
585                 } else {
586                         coex_stat->bt_pan_exist = false;
587                 }
588
589                 if (coex_stat->bt_info_lb2 & COEX_INFO_A2DP) {
590                         coex_stat->bt_a2dp_exist = true;
591                         coex_stat->bt_profile_num++;
592                 } else {
593                         coex_stat->bt_a2dp_exist = false;
594                 }
595
596                 if (coex_stat->bt_info_lb2 & COEX_INFO_HID) {
597                         coex_stat->bt_hid_exist = true;
598                         coex_stat->bt_profile_num++;
599                 } else {
600                         coex_stat->bt_hid_exist = false;
601                 }
602
603                 if (coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) {
604                         coex_stat->bt_hfp_exist = true;
605                         coex_stat->bt_profile_num++;
606                 } else {
607                         coex_stat->bt_hfp_exist = false;
608                 }
609         }
610
611         if (coex_stat->bt_info_lb2 & COEX_INFO_INQ_PAGE) {
612                 coex_dm->bt_status = COEX_BTSTATUS_INQ_PAGE;
613         } else if (!(coex_stat->bt_info_lb2 & COEX_INFO_CONNECTION)) {
614                 coex_dm->bt_status = COEX_BTSTATUS_NCON_IDLE;
615         } else if (coex_stat->bt_info_lb2 == COEX_INFO_CONNECTION) {
616                 coex_dm->bt_status = COEX_BTSTATUS_CON_IDLE;
617         } else if ((coex_stat->bt_info_lb2 & COEX_INFO_SCO_ESCO) ||
618                    (coex_stat->bt_info_lb2 & COEX_INFO_SCO_BUSY)) {
619                 if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY)
620                         coex_dm->bt_status = COEX_BTSTATUS_ACL_SCO_BUSY;
621                 else
622                         coex_dm->bt_status = COEX_BTSTATUS_SCO_BUSY;
623         } else if (coex_stat->bt_info_lb2 & COEX_INFO_ACL_BUSY) {
624                 coex_dm->bt_status = COEX_BTSTATUS_ACL_BUSY;
625         } else {
626                 coex_dm->bt_status = COEX_BTSTATUS_MAX;
627         }
628
629         coex_stat->cnt_bt[COEX_CNT_BT_INFOUPDATE]++;
630
631         rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: bt status(%d)\n", coex_dm->bt_status);
632 }
633
634 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
635 {
636         struct rtw_chip_info *chip = rtwdev->chip;
637         struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
638         struct rtw_efuse *efuse = &rtwdev->efuse;
639         u8 link = 0;
640         u8 center_chan = 0;
641         u8 bw;
642         int i;
643
644         bw = rtwdev->hal.current_band_width;
645
646         if (type != COEX_MEDIA_DISCONNECT)
647                 center_chan = rtwdev->hal.current_channel;
648
649         if (center_chan == 0 || (efuse->share_ant && center_chan <= 14)) {
650                 link = 0;
651         } else if (center_chan <= 14) {
652                 link = 0x1;
653
654                 if (bw == RTW_CHANNEL_WIDTH_40)
655                         bw = chip->bt_afh_span_bw40;
656                 else
657                         bw = chip->bt_afh_span_bw20;
658         } else if (chip->afh_5g_num > 1) {
659                 for (i = 0; i < chip->afh_5g_num; i++) {
660                         if (center_chan == chip->afh_5g[i].wl_5g_ch) {
661                                 link = 0x3;
662                                 center_chan = chip->afh_5g[i].bt_skip_ch;
663                                 bw = chip->afh_5g[i].bt_skip_span;
664                                 break;
665                         }
666                 }
667         }
668
669         coex_dm->wl_ch_info[0] = link;
670         coex_dm->wl_ch_info[1] = center_chan;
671         coex_dm->wl_ch_info[2] = bw;
672
673         rtw_fw_wl_ch_info(rtwdev, link, center_chan, bw);
674 }
675
676 static void rtw_coex_set_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
677 {
678         struct rtw_coex *coex = &rtwdev->coex;
679         struct rtw_coex_dm *coex_dm = &coex->dm;
680
681         if (bt_pwr_dec_lvl == coex_dm->cur_bt_pwr_lvl)
682                 return;
683
684         coex_dm->cur_bt_pwr_lvl = bt_pwr_dec_lvl;
685
686         rtw_fw_force_bt_tx_power(rtwdev, bt_pwr_dec_lvl);
687 }
688
689 static void rtw_coex_set_bt_rx_gain(struct rtw_dev *rtwdev, u8 bt_lna_lvl)
690 {
691         struct rtw_coex *coex = &rtwdev->coex;
692         struct rtw_coex_dm *coex_dm = &coex->dm;
693
694         if (bt_lna_lvl == coex_dm->cur_bt_lna_lvl)
695                 return;
696
697         coex_dm->cur_bt_lna_lvl = bt_lna_lvl;
698
699         /* notify BT rx gain table changed */
700         if (bt_lna_lvl < 7) {
701                 rtw_coex_set_lna_constrain_level(rtwdev, bt_lna_lvl);
702                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, true);
703         } else {
704                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_RXGAIN, false);
705         }
706 }
707
708 static void rtw_coex_set_rf_para(struct rtw_dev *rtwdev,
709                                  struct coex_rf_para para)
710 {
711         struct rtw_coex *coex = &rtwdev->coex;
712         struct rtw_coex_stat *coex_stat = &coex->stat;
713         u8 offset = 0;
714
715         if (coex->freerun && coex_stat->wl_noisy_level <= 1)
716                 offset = 3;
717
718         rtw_coex_set_wl_tx_power(rtwdev, para.wl_pwr_dec_lvl);
719         rtw_coex_set_bt_tx_power(rtwdev, para.bt_pwr_dec_lvl + offset);
720         rtw_coex_set_wl_rx_gain(rtwdev, para.wl_low_gain_en);
721         rtw_coex_set_bt_rx_gain(rtwdev, para.bt_lna_lvl);
722 }
723
724 u32 rtw_coex_read_indirect_reg(struct rtw_dev *rtwdev, u16 addr)
725 {
726         u32 val;
727
728         if (!ltecoex_read_reg(rtwdev, addr, &val)) {
729                 rtw_err(rtwdev, "failed to read indirect register\n");
730                 return 0;
731         }
732
733         return val;
734 }
735
736 void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
737                                  u32 mask, u32 val)
738 {
739         u32 shift = __ffs(mask);
740         u32 tmp;
741
742         tmp = rtw_coex_read_indirect_reg(rtwdev, addr);
743         tmp = (tmp & (~mask)) | ((val << shift) & mask);
744
745         if (!ltecoex_reg_write(rtwdev, addr, tmp))
746                 rtw_err(rtwdev, "failed to write indirect register\n");
747 }
748
749 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
750 {
751         if (wifi_control)
752                 rtw_write32_set(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
753         else
754                 rtw_write32_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT_LTE_MUX_CTRL_PATH);
755 }
756
757 static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
758 {
759         rtw_coex_write_indirect_reg(rtwdev, 0x38, 0xc000, state);
760         rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0c00, state);
761 }
762
763 static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
764 {
765         rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x3000, state);
766         rtw_coex_write_indirect_reg(rtwdev, 0x38, 0x0300, state);
767 }
768
769 static void rtw_coex_set_table(struct rtw_dev *rtwdev, u32 table0, u32 table1)
770 {
771 #define DEF_BRK_TABLE_VAL       0xf0ffffff
772         rtw_write32(rtwdev, REG_BT_COEX_TABLE0, table0);
773         rtw_write32(rtwdev, REG_BT_COEX_TABLE1, table1);
774         rtw_write32(rtwdev, REG_BT_COEX_BRK_TABLE, DEF_BRK_TABLE_VAL);
775 }
776
777 static void rtw_coex_table(struct rtw_dev *rtwdev, u8 type)
778 {
779         struct rtw_coex *coex = &rtwdev->coex;
780         struct rtw_coex_dm *coex_dm = &coex->dm;
781         struct rtw_chip_info *chip = rtwdev->chip;
782         struct rtw_efuse *efuse = &rtwdev->efuse;
783
784         coex_dm->cur_table = type;
785
786         if (efuse->share_ant) {
787                 if (type < chip->table_sant_num)
788                         rtw_coex_set_table(rtwdev,
789                                            chip->table_sant[type].bt,
790                                            chip->table_sant[type].wl);
791         } else {
792                 type = type - 100;
793                 if (type < chip->table_nsant_num)
794                         rtw_coex_set_table(rtwdev,
795                                            chip->table_nsant[type].bt,
796                                            chip->table_nsant[type].wl);
797         }
798 }
799
800 static void rtw_coex_ignore_wlan_act(struct rtw_dev *rtwdev, bool enable)
801 {
802         struct rtw_coex *coex = &rtwdev->coex;
803
804         if (coex->stop_dm)
805                 return;
806
807         rtw_fw_bt_ignore_wlan_action(rtwdev, enable);
808 }
809
810 static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
811                                       u8 lps_val, u8 rpwm_val)
812 {
813         struct rtw_coex *coex = &rtwdev->coex;
814         struct rtw_coex_stat *coex_stat = &coex->stat;
815         u8 lps_mode = 0x0;
816
817         lps_mode = rtwdev->lps_conf.mode;
818
819         switch (ps_type) {
820         case COEX_PS_WIFI_NATIVE:
821                 /* recover to original 32k low power setting */
822                 coex_stat->wl_force_lps_ctrl = false;
823
824                 rtw_leave_lps(rtwdev);
825                 break;
826         case COEX_PS_LPS_OFF:
827                 coex_stat->wl_force_lps_ctrl = true;
828                 if (lps_mode)
829                         rtw_fw_coex_tdma_type(rtwdev, 0x8, 0, 0, 0, 0);
830
831                 rtw_leave_lps(rtwdev);
832                 break;
833         default:
834                 break;
835         }
836 }
837
838 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
839                               u8 byte3, u8 byte4, u8 byte5)
840 {
841         struct rtw_coex *coex = &rtwdev->coex;
842         struct rtw_coex_dm *coex_dm = &coex->dm;
843         struct rtw_chip_info *chip = rtwdev->chip;
844         u8 ps_type = COEX_PS_WIFI_NATIVE;
845         bool ap_enable = false;
846
847         if (ap_enable && (byte1 & BIT(4) && !(byte1 & BIT(5)))) {
848                 byte1 &= ~BIT(4);
849                 byte1 |= BIT(5);
850
851                 byte5 |= BIT(5);
852                 byte5 &= ~BIT(6);
853
854                 ps_type = COEX_PS_WIFI_NATIVE;
855                 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
856         } else if (byte1 & BIT(4) && !(byte1 & BIT(5))) {
857                 if (chip->pstdma_type == COEX_PSTDMA_FORCE_LPSOFF)
858                         ps_type = COEX_PS_LPS_OFF;
859                 else
860                         ps_type = COEX_PS_LPS_ON;
861                 rtw_coex_power_save_state(rtwdev, ps_type, 0x50, 0x4);
862         } else {
863                 ps_type = COEX_PS_WIFI_NATIVE;
864                 rtw_coex_power_save_state(rtwdev, ps_type, 0x0, 0x0);
865         }
866
867         coex_dm->ps_tdma_para[0] = byte1;
868         coex_dm->ps_tdma_para[1] = byte2;
869         coex_dm->ps_tdma_para[2] = byte3;
870         coex_dm->ps_tdma_para[3] = byte4;
871         coex_dm->ps_tdma_para[4] = byte5;
872
873         rtw_fw_coex_tdma_type(rtwdev, byte1, byte2, byte3, byte4, byte5);
874 }
875
876 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
877 {
878         struct rtw_coex *coex = &rtwdev->coex;
879         struct rtw_coex_dm *coex_dm = &coex->dm;
880         struct rtw_chip_info *chip = rtwdev->chip;
881         struct rtw_efuse *efuse = &rtwdev->efuse;
882         u8 n, type;
883         bool turn_on;
884
885         if (tcase & TDMA_4SLOT)/* 4-slot (50ms) mode */
886                 rtw_coex_tdma_timer_base(rtwdev, 3);
887         else
888                 rtw_coex_tdma_timer_base(rtwdev, 0);
889
890         type = (u8)(tcase & 0xff);
891
892         turn_on = (type == 0 || type == 100) ? false : true;
893
894         if (!force) {
895                 if (turn_on == coex_dm->cur_ps_tdma_on &&
896                     type == coex_dm->cur_ps_tdma) {
897                         return;
898                 }
899         }
900
901         if (turn_on) {
902                 /* enable TBTT interrupt */
903                 rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);
904                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, true);
905         } else {
906                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_TDMA, false);
907         }
908
909         if (efuse->share_ant) {
910                 if (type < chip->tdma_sant_num)
911                         rtw_coex_set_tdma(rtwdev,
912                                           chip->tdma_sant[type].para[0],
913                                           chip->tdma_sant[type].para[1],
914                                           chip->tdma_sant[type].para[2],
915                                           chip->tdma_sant[type].para[3],
916                                           chip->tdma_sant[type].para[4]);
917         } else {
918                 n = type - 100;
919                 if (n < chip->tdma_nsant_num)
920                         rtw_coex_set_tdma(rtwdev,
921                                           chip->tdma_nsant[n].para[0],
922                                           chip->tdma_nsant[n].para[1],
923                                           chip->tdma_nsant[n].para[2],
924                                           chip->tdma_nsant[n].para[3],
925                                           chip->tdma_nsant[n].para[4]);
926         }
927
928         /* update pre state */
929         coex_dm->cur_ps_tdma_on = turn_on;
930         coex_dm->cur_ps_tdma = type;
931
932         rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: coex tdma type (%d)\n", type);
933 }
934
935 static void rtw_coex_set_ant_path(struct rtw_dev *rtwdev, bool force, u8 phase)
936 {
937         struct rtw_coex *coex = &rtwdev->coex;
938         struct rtw_coex_stat *coex_stat = &coex->stat;
939         struct rtw_coex_dm *coex_dm = &coex->dm;
940         u8 ctrl_type = COEX_SWITCH_CTRL_MAX;
941         u8 pos_type = COEX_SWITCH_TO_MAX;
942
943         if (!force && coex_dm->cur_ant_pos_type == phase)
944                 return;
945
946         coex_dm->cur_ant_pos_type = phase;
947
948         /* avoid switch coex_ctrl_owner during BT IQK */
949         rtw_coex_check_rfk(rtwdev);
950
951         switch (phase) {
952         case COEX_SET_ANT_POWERON:
953                 /* set path control owner to BT at power-on */
954                 if (coex_stat->bt_disabled)
955                         rtw_coex_coex_ctrl_owner(rtwdev, true);
956                 else
957                         rtw_coex_coex_ctrl_owner(rtwdev, false);
958
959                 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
960                 pos_type = COEX_SWITCH_TO_BT;
961                 break;
962         case COEX_SET_ANT_INIT:
963                 if (coex_stat->bt_disabled) {
964                         /* set GNT_BT to SW low */
965                         rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
966
967                         /* set GNT_WL to SW high */
968                         rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
969                 } else {
970                         /* set GNT_BT to SW high */
971                         rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
972
973                         /* set GNT_WL to SW low */
974                         rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_LOW);
975                 }
976
977                 /* set path control owner to wl at initial step */
978                 rtw_coex_coex_ctrl_owner(rtwdev, true);
979
980                 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
981                 pos_type = COEX_SWITCH_TO_BT;
982                 break;
983         case COEX_SET_ANT_WONLY:
984                 /* set GNT_BT to SW Low */
985                 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_LOW);
986
987                 /* Set GNT_WL to SW high */
988                 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
989
990                 /* set path control owner to wl at initial step */
991                 rtw_coex_coex_ctrl_owner(rtwdev, true);
992
993                 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
994                 pos_type = COEX_SWITCH_TO_WLG;
995                 break;
996         case COEX_SET_ANT_WOFF:
997                 /* set path control owner to BT */
998                 rtw_coex_coex_ctrl_owner(rtwdev, false);
999
1000                 ctrl_type = COEX_SWITCH_CTRL_BY_BT;
1001                 pos_type = COEX_SWITCH_TO_NOCARE;
1002                 break;
1003         case COEX_SET_ANT_2G:
1004                 /* set GNT_BT to PTA */
1005                 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1006
1007                 /* set GNT_WL to PTA */
1008                 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1009
1010                 /* set path control owner to wl at runtime step */
1011                 rtw_coex_coex_ctrl_owner(rtwdev, true);
1012
1013                 ctrl_type = COEX_SWITCH_CTRL_BY_PTA;
1014                 pos_type = COEX_SWITCH_TO_NOCARE;
1015                 break;
1016         case COEX_SET_ANT_5G:
1017                 /* set GNT_BT to PTA */
1018                 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1019
1020                 /* set GNT_WL to SW high */
1021                 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1022
1023                 /* set path control owner to wl at runtime step */
1024                 rtw_coex_coex_ctrl_owner(rtwdev, true);
1025
1026                 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1027                 pos_type = COEX_SWITCH_TO_WLA;
1028                 break;
1029         case COEX_SET_ANT_2G_FREERUN:
1030                 /* set GNT_BT to SW high */
1031                 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_SW_HIGH);
1032
1033                 /* Set GNT_WL to SW high */
1034                 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_SW_HIGH);
1035
1036                 /* set path control owner to wl at runtime step */
1037                 rtw_coex_coex_ctrl_owner(rtwdev, true);
1038
1039                 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1040                 pos_type = COEX_SWITCH_TO_WLG_BT;
1041                 break;
1042         case COEX_SET_ANT_2G_WLBT:
1043                 /* set GNT_BT to SW high */
1044                 rtw_coex_set_gnt_bt(rtwdev, COEX_GNT_SET_HW_PTA);
1045
1046                 /* Set GNT_WL to SW high */
1047                 rtw_coex_set_gnt_wl(rtwdev, COEX_GNT_SET_HW_PTA);
1048
1049                 /* set path control owner to wl at runtime step */
1050                 rtw_coex_coex_ctrl_owner(rtwdev, true);
1051
1052                 ctrl_type = COEX_SWITCH_CTRL_BY_BBSW;
1053                 pos_type = COEX_SWITCH_TO_WLG_BT;
1054                 break;
1055         default:
1056                 WARN(1, "unknown phase when setting antenna path\n");
1057                 return;
1058         }
1059
1060         if (ctrl_type < COEX_SWITCH_CTRL_MAX && pos_type < COEX_SWITCH_TO_MAX)
1061                 rtw_coex_set_ant_switch(rtwdev, ctrl_type, pos_type);
1062 }
1063
1064 static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
1065 {
1066         struct rtw_coex *coex = &rtwdev->coex;
1067         struct rtw_coex_stat *coex_stat = &coex->stat;
1068         u8 algorithm = COEX_ALGO_NOPROFILE;
1069         u8 profile_map = 0;
1070
1071         if (coex_stat->bt_hfp_exist)
1072                 profile_map |= BPM_HFP;
1073         if (coex_stat->bt_hid_exist)
1074                 profile_map |= BPM_HID;
1075         if (coex_stat->bt_a2dp_exist)
1076                 profile_map |= BPM_A2DP;
1077         if (coex_stat->bt_pan_exist)
1078                 profile_map |= BPM_PAN;
1079
1080         switch (profile_map) {
1081         case BPM_HFP:
1082                 algorithm = COEX_ALGO_HFP;
1083                 break;
1084         case           BPM_HID:
1085         case BPM_HFP + BPM_HID:
1086                 algorithm = COEX_ALGO_HID;
1087                 break;
1088         case BPM_HFP           + BPM_A2DP:
1089         case           BPM_HID + BPM_A2DP:
1090         case BPM_HFP + BPM_HID + BPM_A2DP:
1091                 algorithm = COEX_ALGO_A2DP_HID;
1092                 break;
1093         case BPM_HFP                      + BPM_PAN:
1094         case           BPM_HID            + BPM_PAN:
1095         case BPM_HFP + BPM_HID            + BPM_PAN:
1096                 algorithm = COEX_ALGO_PAN_HID;
1097                 break;
1098         case BPM_HFP           + BPM_A2DP + BPM_PAN:
1099         case           BPM_HID + BPM_A2DP + BPM_PAN:
1100         case BPM_HFP + BPM_HID + BPM_A2DP + BPM_PAN:
1101                 algorithm = COEX_ALGO_A2DP_PAN_HID;
1102                 break;
1103         case                                BPM_PAN:
1104                 algorithm = COEX_ALGO_PAN;
1105                 break;
1106         case                     BPM_A2DP + BPM_PAN:
1107                 algorithm = COEX_ALGO_A2DP_PAN;
1108                 break;
1109         case                     BPM_A2DP:
1110                 if (coex_stat->bt_multi_link) {
1111                         if (coex_stat->bt_hid_pair_num > 0)
1112                                 algorithm = COEX_ALGO_A2DP_HID;
1113                         else
1114                                 algorithm = COEX_ALGO_A2DP_PAN;
1115                 } else {
1116                         algorithm = COEX_ALGO_A2DP;
1117                 }
1118                 break;
1119         default:
1120                 algorithm = COEX_ALGO_NOPROFILE;
1121                 break;
1122         }
1123
1124         return algorithm;
1125 }
1126
1127 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
1128 {
1129         struct rtw_efuse *efuse = &rtwdev->efuse;
1130         struct rtw_chip_info *chip = rtwdev->chip;
1131         u8 table_case, tdma_case;
1132
1133         if (efuse->share_ant) {
1134                 /* Shared-Ant */
1135                 table_case = 2;
1136                 tdma_case = 0;
1137         } else {
1138                 /* Non-Shared-Ant */
1139                 table_case = 100;
1140                 tdma_case = 100;
1141         }
1142
1143         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1144         rtw_coex_table(rtwdev, table_case);
1145         rtw_coex_tdma(rtwdev, false, tdma_case);
1146 }
1147
1148 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
1149 {
1150         struct rtw_coex *coex = &rtwdev->coex;
1151         struct rtw_coex_stat *coex_stat = &coex->stat;
1152         struct rtw_coex_dm *coex_dm = &coex->dm;
1153         struct rtw_efuse *efuse = &rtwdev->efuse;
1154         struct rtw_chip_info *chip = rtwdev->chip;
1155         u8 level = 0;
1156
1157         if (efuse->share_ant)
1158                 return;
1159
1160         coex->freerun = true;
1161
1162         if (coex_stat->wl_connected)
1163                 rtw_coex_update_wl_ch_info(rtwdev, COEX_MEDIA_CONNECT);
1164
1165         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1166
1167         rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1168
1169         if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[0]))
1170                 level = 2;
1171         else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1172                 level = 3;
1173         else if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[2]))
1174                 level = 4;
1175         else
1176                 level = 5;
1177
1178         if (level > chip->wl_rf_para_num - 1)
1179                 level = chip->wl_rf_para_num - 1;
1180
1181         if (coex_stat->wl_tput_dir == COEX_WL_TPUT_TX)
1182                 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_tx[level]);
1183         else
1184                 rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[level]);
1185
1186         rtw_coex_table(rtwdev, 100);
1187         rtw_coex_tdma(rtwdev, false, 100);
1188 }
1189
1190 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
1191 {
1192         struct rtw_efuse *efuse = &rtwdev->efuse;
1193         struct rtw_chip_info *chip = rtwdev->chip;
1194         u8 table_case, tdma_case;
1195
1196         if (efuse->share_ant) {
1197                 /* Shared-Ant */
1198                 table_case = 2;
1199                 tdma_case = 0;
1200         } else {
1201                 /* Non-Shared-Ant */
1202                 table_case = 100;
1203                 tdma_case = 100;
1204         }
1205
1206         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1207         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1208         rtw_coex_table(rtwdev, table_case);
1209         rtw_coex_tdma(rtwdev, false, tdma_case);
1210 }
1211
1212 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
1213 {
1214         struct rtw_efuse *efuse = &rtwdev->efuse;
1215         struct rtw_chip_info *chip = rtwdev->chip;
1216         u8 table_case, tdma_case;
1217
1218         if (efuse->share_ant) {
1219                 /* Shared-Ant */
1220                 table_case = 1;
1221                 tdma_case = 0;
1222         } else {
1223                 /* Non-Shared-Ant */
1224                 table_case = 100;
1225                 tdma_case = 100;
1226         }
1227
1228         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1229         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1230         rtw_coex_table(rtwdev, table_case);
1231         rtw_coex_tdma(rtwdev, false, tdma_case);
1232 }
1233
1234 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
1235 {
1236         struct rtw_coex *coex = &rtwdev->coex;
1237         struct rtw_coex_stat *coex_stat = &coex->stat;
1238         struct rtw_coex_dm *coex_dm = &coex->dm;
1239         struct rtw_efuse *efuse = &rtwdev->efuse;
1240         struct rtw_chip_info *chip = rtwdev->chip;
1241         struct rtw_coex_rfe *coex_rfe = &coex->rfe;
1242         u8 table_case = 0xff, tdma_case = 0xff;
1243
1244         if (coex_rfe->ant_switch_with_bt &&
1245             coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1246                 if (efuse->share_ant &&
1247                     COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1])) {
1248                         table_case = 0;
1249                         tdma_case = 0;
1250                 } else if (!efuse->share_ant) {
1251                         table_case = 100;
1252                         tdma_case = 100;
1253                 }
1254         }
1255
1256         if (table_case != 0xff && tdma_case != 0xff) {
1257                 rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G_FREERUN);
1258                 rtw_coex_table(rtwdev, table_case);
1259                 rtw_coex_tdma(rtwdev, false, tdma_case);
1260                 return;
1261         }
1262
1263         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1264
1265         if (efuse->share_ant) {
1266                 /* Shared-Ant */
1267                 if (!coex_stat->wl_gl_busy) {
1268                         table_case = 10;
1269                         tdma_case = 3;
1270                 } else if (coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1271                         table_case = 6;
1272                         tdma_case = 7;
1273                 } else {
1274                         table_case = 12;
1275                         tdma_case = 7;
1276                 }
1277         } else {
1278                 /* Non-Shared-Ant */
1279                 if (!coex_stat->wl_gl_busy) {
1280                         table_case = 112;
1281                         tdma_case = 104;
1282                 } else if ((coex_stat->bt_ble_scan_type & 0x2) &&
1283                             coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE) {
1284                         table_case = 114;
1285                         tdma_case = 103;
1286                 } else {
1287                         table_case = 112;
1288                         tdma_case = 103;
1289                 }
1290         }
1291
1292         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1293         rtw_coex_table(rtwdev, table_case);
1294         rtw_coex_tdma(rtwdev, false, tdma_case);
1295 }
1296
1297 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
1298 {
1299         struct rtw_coex *coex = &rtwdev->coex;
1300         struct rtw_coex_stat *coex_stat = &coex->stat;
1301         struct rtw_efuse *efuse = &rtwdev->efuse;
1302         struct rtw_chip_info *chip = rtwdev->chip;
1303         bool wl_hi_pri = false;
1304         u8 table_case, tdma_case;
1305
1306         if (coex_stat->wl_linkscan_proc || coex_stat->wl_hi_pri_task1 ||
1307             coex_stat->wl_hi_pri_task2)
1308                 wl_hi_pri = true;
1309
1310         if (efuse->share_ant) {
1311                 /* Shared-Ant */
1312                 if (wl_hi_pri) {
1313                         table_case = 15;
1314                         if (coex_stat->bt_a2dp_exist &&
1315                             !coex_stat->bt_pan_exist)
1316                                 tdma_case = 11;
1317                         else if (coex_stat->wl_hi_pri_task1)
1318                                 tdma_case = 6;
1319                         else if (!coex_stat->bt_page)
1320                                 tdma_case = 8;
1321                         else
1322                                 tdma_case = 9;
1323                 } else if (coex_stat->wl_connected) {
1324                         table_case = 10;
1325                         tdma_case = 10;
1326                 } else {
1327                         table_case = 1;
1328                         tdma_case = 0;
1329                 }
1330         } else {
1331                 /* Non_Shared-Ant */
1332                 if (wl_hi_pri) {
1333                         table_case = 113;
1334                         if (coex_stat->bt_a2dp_exist &&
1335                             !coex_stat->bt_pan_exist)
1336                                 tdma_case = 111;
1337                         else if (coex_stat->wl_hi_pri_task1)
1338                                 tdma_case = 106;
1339                         else if (!coex_stat->bt_page)
1340                                 tdma_case = 108;
1341                         else
1342                                 tdma_case = 109;
1343                 } else if (coex_stat->wl_connected) {
1344                         table_case = 101;
1345                         tdma_case = 110;
1346                 } else {
1347                         table_case = 100;
1348                         tdma_case = 100;
1349                 }
1350         }
1351
1352         rtw_dbg(rtwdev, RTW_DBG_COEX, "coex: wifi hi(%d), bt page(%d)\n",
1353                 wl_hi_pri, coex_stat->bt_page);
1354
1355         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1356         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1357         rtw_coex_table(rtwdev, table_case);
1358         rtw_coex_tdma(rtwdev, false, tdma_case);
1359 }
1360
1361 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
1362 {
1363         struct rtw_coex *coex = &rtwdev->coex;
1364         struct rtw_coex_stat *coex_stat = &coex->stat;
1365         struct rtw_efuse *efuse = &rtwdev->efuse;
1366         struct rtw_chip_info *chip = rtwdev->chip;
1367         u8 table_case, tdma_case;
1368
1369         if (efuse->share_ant) {
1370                 /* Shared-Ant */
1371                 if (coex_stat->bt_multi_link) {
1372                         table_case = 10;
1373                         tdma_case = 17;
1374                 } else {
1375                         table_case = 10;
1376                         tdma_case = 5;
1377                 }
1378         } else {
1379                 /* Non-Shared-Ant */
1380                 if (coex_stat->bt_multi_link) {
1381                         table_case = 112;
1382                         tdma_case = 117;
1383                 } else {
1384                         table_case = 105;
1385                         tdma_case = 100;
1386                 }
1387         }
1388
1389         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1390         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1391         rtw_coex_table(rtwdev, table_case);
1392         rtw_coex_tdma(rtwdev, false, tdma_case);
1393 }
1394
1395 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
1396 {
1397         struct rtw_coex *coex = &rtwdev->coex;
1398         struct rtw_coex_stat *coex_stat = &coex->stat;
1399         struct rtw_efuse *efuse = &rtwdev->efuse;
1400         struct rtw_chip_info *chip = rtwdev->chip;
1401         u8 table_case, tdma_case;
1402         u32 wl_bw;
1403
1404         wl_bw = rtwdev->hal.current_band_width;
1405
1406         if (efuse->share_ant) {
1407                 /* Shared-Ant */
1408                 if (coex_stat->bt_ble_exist) {
1409                         /* RCU */
1410                         if (!coex_stat->wl_gl_busy)
1411                                 table_case = 14;
1412                         else
1413                                 table_case = 15;
1414
1415                         if (coex_stat->bt_a2dp_active || wl_bw == 0)
1416                                 tdma_case = 18;
1417                         else if (coex_stat->wl_gl_busy)
1418                                 tdma_case = 8;
1419                         else
1420                                 tdma_case = 4;
1421                 } else {
1422                         if (coex_stat->bt_a2dp_active || wl_bw == 0) {
1423                                 table_case = 8;
1424                                 tdma_case = 4;
1425                         } else {
1426                                 /* for 4/18 HID */
1427                                 if (coex_stat->bt_418_hid_exist &&
1428                                     coex_stat->wl_gl_busy)
1429                                         table_case = 12;
1430                                 else
1431                                         table_case = 10;
1432                                 tdma_case = 4;
1433                         }
1434                 }
1435         } else {
1436                 /* Non-Shared-Ant */
1437                 if (coex_stat->bt_a2dp_active) {
1438                         table_case = 113;
1439                         tdma_case = 118;
1440                 } else if (coex_stat->bt_ble_exist) {
1441                         /* BLE */
1442                         table_case = 113;
1443
1444                         if (coex_stat->wl_gl_busy)
1445                                 tdma_case = 106;
1446                         else
1447                                 tdma_case = 104;
1448                 } else {
1449                         table_case = 113;
1450                         tdma_case = 104;
1451                 }
1452         }
1453
1454         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1455         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1456         rtw_coex_table(rtwdev, table_case);
1457         rtw_coex_tdma(rtwdev, false, tdma_case);
1458 }
1459
1460 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
1461 {
1462         struct rtw_coex *coex = &rtwdev->coex;
1463         struct rtw_coex_stat *coex_stat = &coex->stat;
1464         struct rtw_coex_dm *coex_dm = &coex->dm;
1465         struct rtw_efuse *efuse = &rtwdev->efuse;
1466         struct rtw_chip_info *chip = rtwdev->chip;
1467         u8 table_case, tdma_case;
1468         u32 slot_type = 0;
1469
1470         if (efuse->share_ant) {
1471                 /* Shared-Ant */
1472                 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1473                         table_case = 10;
1474                 else
1475                         table_case = 9;
1476
1477                 slot_type = TDMA_4SLOT;
1478
1479                 if (coex_stat->wl_gl_busy)
1480                         tdma_case = 13;
1481                 else
1482                         tdma_case = 14;
1483         } else {
1484                 /* Non-Shared-Ant */
1485                 table_case = 112;
1486
1487                 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1488                         tdma_case = 112;
1489                 else
1490                         tdma_case = 113;
1491         }
1492
1493         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1494         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1495         rtw_coex_table(rtwdev, table_case);
1496         rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1497 }
1498
1499 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
1500 {
1501         struct rtw_coex *coex = &rtwdev->coex;
1502         struct rtw_coex_stat *coex_stat = &coex->stat;
1503         struct rtw_efuse *efuse = &rtwdev->efuse;
1504         struct rtw_chip_info *chip = rtwdev->chip;
1505         u8 table_case, tdma_case;
1506         bool ap_enable = false;
1507
1508         if (efuse->share_ant) { /* Shared-Ant */
1509                 if (ap_enable) {
1510                         table_case = 2;
1511                         tdma_case = 0;
1512                 } else if (coex_stat->wl_gl_busy) {
1513                         table_case = 28;
1514                         tdma_case = 20;
1515                 } else {
1516                         table_case = 28;
1517                         tdma_case = 26;
1518                 }
1519         } else { /* Non-Shared-Ant */
1520                 if (ap_enable) {
1521                         table_case = 100;
1522                         tdma_case = 100;
1523                 } else {
1524                         table_case = 119;
1525                         tdma_case = 120;
1526                 }
1527         }
1528
1529         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1530         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1531         rtw_coex_table(rtwdev, table_case);
1532         rtw_coex_tdma(rtwdev, false, tdma_case);
1533 }
1534
1535 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
1536 {
1537         struct rtw_coex *coex = &rtwdev->coex;
1538         struct rtw_coex_stat *coex_stat = &coex->stat;
1539         struct rtw_efuse *efuse = &rtwdev->efuse;
1540         struct rtw_chip_info *chip = rtwdev->chip;
1541         u8 table_case, tdma_case;
1542
1543         if (efuse->share_ant) {
1544                 /* Shared-Ant */
1545                 if (coex_stat->wl_gl_busy && coex_stat->wl_noisy_level == 0)
1546                         table_case = 14;
1547                 else
1548                         table_case = 10;
1549
1550                 if (coex_stat->wl_gl_busy)
1551                         tdma_case = 17;
1552                 else
1553                         tdma_case = 19;
1554         } else {
1555                 /* Non-Shared-Ant */
1556                 table_case = 112;
1557
1558                 if (coex_stat->wl_gl_busy)
1559                         tdma_case = 117;
1560                 else
1561                         tdma_case = 119;
1562         }
1563
1564         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1565         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1566         rtw_coex_table(rtwdev, table_case);
1567         rtw_coex_tdma(rtwdev, false, tdma_case);
1568 }
1569
1570 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
1571 {
1572         struct rtw_coex *coex = &rtwdev->coex;
1573         struct rtw_coex_stat *coex_stat = &coex->stat;
1574         struct rtw_coex_dm *coex_dm = &coex->dm;
1575         struct rtw_efuse *efuse = &rtwdev->efuse;
1576         struct rtw_chip_info *chip = rtwdev->chip;
1577         u8 table_case, tdma_case;
1578         u32 slot_type = 0;
1579
1580         if (efuse->share_ant) {
1581                 /* Shared-Ant */
1582                 if (coex_stat->bt_ble_exist)
1583                         table_case = 26;
1584                 else
1585                         table_case = 9;
1586
1587                 if (coex_stat->wl_gl_busy) {
1588                         slot_type = TDMA_4SLOT;
1589                         tdma_case = 13;
1590                 } else {
1591                         tdma_case = 14;
1592                 }
1593         } else {
1594                 /* Non-Shared-Ant */
1595                 if (coex_stat->bt_ble_exist)
1596                         table_case = 121;
1597                 else
1598                         table_case = 113;
1599
1600                 if (COEX_RSSI_HIGH(coex_dm->wl_rssi_state[1]))
1601                         tdma_case = 112;
1602                 else
1603                         tdma_case = 113;
1604         }
1605
1606         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1607         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1608         rtw_coex_table(rtwdev, table_case);
1609         rtw_coex_tdma(rtwdev, false, tdma_case | slot_type);
1610 }
1611
1612 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
1613 {
1614         struct rtw_coex *coex = &rtwdev->coex;
1615         struct rtw_coex_stat *coex_stat = &coex->stat;
1616         struct rtw_efuse *efuse = &rtwdev->efuse;
1617         struct rtw_chip_info *chip = rtwdev->chip;
1618         u8 table_case, tdma_case;
1619
1620         if (efuse->share_ant) {
1621                 /* Shared-Ant */
1622                 if (coex_stat->wl_gl_busy &&
1623                     coex_stat->wl_noisy_level == 0)
1624                         table_case = 14;
1625                 else
1626                         table_case = 10;
1627
1628                 if (coex_stat->wl_gl_busy)
1629                         tdma_case = 15;
1630                 else
1631                         tdma_case = 20;
1632         } else {
1633                 /* Non-Shared-Ant */
1634                 table_case = 112;
1635
1636                 if (coex_stat->wl_gl_busy)
1637                         tdma_case = 115;
1638                 else
1639                         tdma_case = 120;
1640         }
1641
1642         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1643         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1644         rtw_coex_table(rtwdev, table_case);
1645         rtw_coex_tdma(rtwdev, false, tdma_case);
1646 }
1647
1648 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
1649 {
1650         struct rtw_coex *coex = &rtwdev->coex;
1651         struct rtw_coex_stat *coex_stat = &coex->stat;
1652         struct rtw_efuse *efuse = &rtwdev->efuse;
1653         struct rtw_chip_info *chip = rtwdev->chip;
1654         u8 table_case, tdma_case;
1655
1656         if (efuse->share_ant) {
1657                 /* Shared-Ant */
1658                 table_case = 9;
1659
1660                 if (coex_stat->wl_gl_busy)
1661                         tdma_case = 18;
1662                 else
1663                         tdma_case = 19;
1664         } else {
1665                 /* Non-Shared-Ant */
1666                 table_case = 113;
1667
1668                 if (coex_stat->wl_gl_busy)
1669                         tdma_case = 117;
1670                 else
1671                         tdma_case = 119;
1672         }
1673
1674         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1675         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1676         rtw_coex_table(rtwdev, table_case);
1677         rtw_coex_tdma(rtwdev, false, tdma_case);
1678 }
1679
1680 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
1681 {
1682         struct rtw_coex *coex = &rtwdev->coex;
1683         struct rtw_coex_stat *coex_stat = &coex->stat;
1684         struct rtw_efuse *efuse = &rtwdev->efuse;
1685         struct rtw_chip_info *chip = rtwdev->chip;
1686         u8 table_case, tdma_case;
1687
1688         if (efuse->share_ant) {
1689                 /* Shared-Ant */
1690                 table_case = 10;
1691
1692                 if (coex_stat->wl_gl_busy)
1693                         tdma_case = 15;
1694                 else
1695                         tdma_case = 20;
1696         } else {
1697                 /* Non-Shared-Ant */
1698                 table_case = 113;
1699
1700                 if (coex_stat->wl_gl_busy)
1701                         tdma_case = 115;
1702                 else
1703                         tdma_case = 120;
1704         }
1705
1706         rtw_coex_set_ant_path(rtwdev, false, COEX_SET_ANT_2G);
1707         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1708         rtw_coex_table(rtwdev, table_case);
1709         rtw_coex_tdma(rtwdev, false, tdma_case);
1710 }
1711
1712 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
1713 {
1714         struct rtw_efuse *efuse = &rtwdev->efuse;
1715         struct rtw_chip_info *chip = rtwdev->chip;
1716         u8 table_case, tdma_case;
1717
1718         rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1719
1720         if (efuse->share_ant) {
1721                 /* Shared-Ant */
1722                 table_case = 0;
1723                 tdma_case = 0;
1724         } else {
1725                 /* Non-Shared-Ant */
1726                 table_case = 100;
1727                 tdma_case = 100;
1728         }
1729
1730         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
1731         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1732         rtw_coex_table(rtwdev, table_case);
1733         rtw_coex_tdma(rtwdev, false, tdma_case);
1734 }
1735
1736 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
1737 {
1738         struct rtw_efuse *efuse = &rtwdev->efuse;
1739         struct rtw_chip_info *chip = rtwdev->chip;
1740         u8 table_case, tdma_case;
1741
1742         if (efuse->share_ant) {
1743                 /* Shared-Ant */
1744                 table_case = 2;
1745                 tdma_case = 0;
1746         } else {
1747                 /* Non-Shared-Ant */
1748                 table_case = 100;
1749                 tdma_case = 100;
1750         }
1751
1752         rtw_coex_set_ant_path(rtwdev, true, 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
1758 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
1759 {
1760         struct rtw_coex *coex = &rtwdev->coex;
1761         struct rtw_efuse *efuse = &rtwdev->efuse;
1762         struct rtw_chip_info *chip = rtwdev->chip;
1763         u8 table_case, tdma_case;
1764
1765         if (coex->under_5g)
1766                 return;
1767
1768         if (efuse->share_ant) {
1769                 /* Shared-Ant */
1770                 table_case = 28;
1771                 tdma_case = 0;
1772         } else {
1773                 /* Non-Shared-Ant */
1774                 table_case = 100;
1775                 tdma_case = 100;
1776         }
1777
1778         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1779         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1780         rtw_coex_table(rtwdev, table_case);
1781         rtw_coex_tdma(rtwdev, false, tdma_case);
1782 }
1783
1784 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
1785 {
1786         struct rtw_coex *coex = &rtwdev->coex;
1787         struct rtw_coex_stat *coex_stat = &coex->stat;
1788         struct rtw_efuse *efuse = &rtwdev->efuse;
1789         struct rtw_chip_info *chip = rtwdev->chip;
1790         u8 table_case, tdma_case;
1791
1792         if (efuse->share_ant) {
1793                 /* Shared-Ant */
1794                 if (coex_stat->bt_a2dp_exist) {
1795                         table_case = 9;
1796                         tdma_case = 11;
1797                 } else {
1798                         table_case = 9;
1799                         tdma_case = 7;
1800                 }
1801         } else {
1802                 /* Non-Shared-Ant */
1803                 if (coex_stat->bt_a2dp_exist) {
1804                         table_case = 112;
1805                         tdma_case = 111;
1806                 } else {
1807                         table_case = 112;
1808                         tdma_case = 107;
1809                 }
1810         }
1811
1812         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1813         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1814         rtw_coex_table(rtwdev, table_case);
1815         rtw_coex_tdma(rtwdev, false, tdma_case);
1816 }
1817
1818 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
1819 {
1820         struct rtw_efuse *efuse = &rtwdev->efuse;
1821         struct rtw_chip_info *chip = rtwdev->chip;
1822         u8 table_case, tdma_case;
1823
1824         if (efuse->share_ant) {
1825                 /* Shared-Ant */
1826                 table_case = 1;
1827                 tdma_case = 0;
1828         } else {
1829                 /* Non-Shared-Ant */
1830                 table_case = 100;
1831                 tdma_case = 100;
1832         }
1833
1834         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
1835         rtw_coex_set_rf_para(rtwdev, chip->wl_rf_para_rx[0]);
1836         rtw_coex_table(rtwdev, table_case);
1837         rtw_coex_tdma(rtwdev, false, tdma_case);
1838 }
1839
1840 static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
1841 {
1842         struct rtw_coex *coex = &rtwdev->coex;
1843         struct rtw_coex_stat *coex_stat = &coex->stat;
1844         struct rtw_coex_dm *coex_dm = &coex->dm;
1845         struct rtw_efuse *efuse = &rtwdev->efuse;
1846         u8 algorithm;
1847
1848         /* Non-Shared-Ant */
1849         if (!efuse->share_ant && coex_stat->wl_gl_busy &&
1850             COEX_RSSI_HIGH(coex_dm->wl_rssi_state[3]) &&
1851             COEX_RSSI_HIGH(coex_dm->bt_rssi_state[0])) {
1852                 rtw_coex_action_freerun(rtwdev);
1853                 return;
1854         }
1855
1856         algorithm = rtw_coex_algorithm(rtwdev);
1857
1858         switch (algorithm) {
1859         case COEX_ALGO_HFP:
1860                 rtw_coex_action_bt_hfp(rtwdev);
1861                 break;
1862         case COEX_ALGO_HID:
1863                 rtw_coex_action_bt_hid(rtwdev);
1864                 break;
1865         case COEX_ALGO_A2DP:
1866                 if (coex_stat->bt_a2dp_sink)
1867                         rtw_coex_action_bt_a2dpsink(rtwdev);
1868                 else
1869                         rtw_coex_action_bt_a2dp(rtwdev);
1870                 break;
1871         case COEX_ALGO_PAN:
1872                 rtw_coex_action_bt_pan(rtwdev);
1873                 break;
1874         case COEX_ALGO_A2DP_HID:
1875                 rtw_coex_action_bt_a2dp_hid(rtwdev);
1876                 break;
1877         case COEX_ALGO_A2DP_PAN:
1878                 rtw_coex_action_bt_a2dp_pan(rtwdev);
1879                 break;
1880         case COEX_ALGO_PAN_HID:
1881                 rtw_coex_action_bt_pan_hid(rtwdev);
1882                 break;
1883         case COEX_ALGO_A2DP_PAN_HID:
1884                 rtw_coex_action_bt_a2dp_pan_hid(rtwdev);
1885                 break;
1886         default:
1887         case COEX_ALGO_NOPROFILE:
1888                 rtw_coex_action_bt_idle(rtwdev);
1889                 break;
1890         }
1891 }
1892
1893 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
1894 {
1895         struct rtw_coex *coex = &rtwdev->coex;
1896         struct rtw_coex_dm *coex_dm = &coex->dm;
1897         struct rtw_coex_stat *coex_stat = &coex->stat;
1898
1899         lockdep_assert_held(&rtwdev->mutex);
1900
1901         coex_dm->reason = reason;
1902
1903         /* update wifi_link_info_ext variable */
1904         rtw_coex_update_wl_link_info(rtwdev, reason);
1905
1906         rtw_coex_monitor_bt_enable(rtwdev);
1907
1908         if (coex->stop_dm)
1909                 return;
1910
1911         if (coex_stat->wl_under_ips)
1912                 return;
1913
1914         if (coex->freeze && !coex_stat->bt_setup_link)
1915                 return;
1916
1917         coex_stat->cnt_wl[COEX_CNT_WL_COEXRUN]++;
1918         coex->freerun = false;
1919
1920         /* Pure-5G Coex Process */
1921         if (coex->under_5g) {
1922                 coex_stat->wl_coex_mode = COEX_WLINK_5G;
1923                 rtw_coex_action_wl_under5g(rtwdev);
1924                 goto exit;
1925         }
1926
1927         coex_stat->wl_coex_mode = COEX_WLINK_2G1PORT;
1928         rtw_coex_write_scbd(rtwdev, COEX_SCBD_FIX2M, false);
1929         if (coex_stat->bt_disabled) {
1930                 rtw_coex_action_wl_only(rtwdev);
1931                 goto exit;
1932         }
1933
1934         if (coex_stat->wl_under_lps && !coex_stat->wl_force_lps_ctrl) {
1935                 rtw_coex_action_wl_native_lps(rtwdev);
1936                 goto exit;
1937         }
1938
1939         if (coex_stat->bt_whck_test) {
1940                 rtw_coex_action_bt_whql_test(rtwdev);
1941                 goto exit;
1942         }
1943
1944         if (coex_stat->bt_setup_link) {
1945                 rtw_coex_action_bt_relink(rtwdev);
1946                 goto exit;
1947         }
1948
1949         if (coex_stat->bt_inq_page) {
1950                 rtw_coex_action_bt_inquiry(rtwdev);
1951                 goto exit;
1952         }
1953
1954         if ((coex_dm->bt_status == COEX_BTSTATUS_NCON_IDLE ||
1955              coex_dm->bt_status == COEX_BTSTATUS_CON_IDLE) &&
1956              coex_stat->wl_connected) {
1957                 rtw_coex_action_bt_idle(rtwdev);
1958                 goto exit;
1959         }
1960
1961         if (coex_stat->wl_linkscan_proc) {
1962                 rtw_coex_action_wl_linkscan(rtwdev);
1963                 goto exit;
1964         }
1965
1966         if (coex_stat->wl_connected)
1967                 rtw_coex_action_wl_connected(rtwdev);
1968         else
1969                 rtw_coex_action_wl_not_connected(rtwdev);
1970
1971 exit:
1972         rtw_coex_set_gnt_fix(rtwdev);
1973         rtw_coex_limited_wl(rtwdev);
1974 }
1975
1976 static void rtw_coex_init_coex_var(struct rtw_dev *rtwdev)
1977 {
1978         struct rtw_coex *coex = &rtwdev->coex;
1979         struct rtw_coex_stat *coex_stat = &coex->stat;
1980         struct rtw_coex_dm *coex_dm = &coex->dm;
1981         u8 i;
1982
1983         memset(coex_dm, 0, sizeof(*coex_dm));
1984         memset(coex_stat, 0, sizeof(*coex_stat));
1985
1986         for (i = 0; i < COEX_CNT_WL_MAX; i++)
1987                 coex_stat->cnt_wl[i] = 0;
1988
1989         for (i = 0; i < COEX_CNT_BT_MAX; i++)
1990                 coex_stat->cnt_bt[i] = 0;
1991
1992         for (i = 0; i < ARRAY_SIZE(coex_dm->bt_rssi_state); i++)
1993                 coex_dm->bt_rssi_state[i] = COEX_RSSI_STATE_LOW;
1994
1995         for (i = 0; i < ARRAY_SIZE(coex_dm->wl_rssi_state); i++)
1996                 coex_dm->wl_rssi_state[i] = COEX_RSSI_STATE_LOW;
1997
1998         coex_stat->wl_coex_mode = COEX_WLINK_MAX;
1999 }
2000
2001 static void __rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2002 {
2003         struct rtw_coex *coex = &rtwdev->coex;
2004
2005         rtw_coex_init_coex_var(rtwdev);
2006         rtw_coex_monitor_bt_enable(rtwdev);
2007         rtw_coex_set_rfe_type(rtwdev);
2008         rtw_coex_set_init(rtwdev);
2009
2010         /* set Tx response = Hi-Pri (ex: Transmitting ACK,BA,CTS) */
2011         rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_RSP, 1);
2012
2013         /* set Tx beacon = Hi-Pri */
2014         rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACON, 1);
2015
2016         /* set Tx beacon queue = Hi-Pri */
2017         rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_TX_BEACONQ, 1);
2018
2019         /* antenna config */
2020         if (coex->wl_rf_off) {
2021                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2022                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2023                 coex->stop_dm = true;
2024         } else if (wifi_only) {
2025                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WONLY);
2026                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2027                                     true);
2028                 coex->stop_dm = true;
2029         } else {
2030                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_INIT);
2031                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN,
2032                                     true);
2033                 coex->stop_dm = false;
2034                 coex->freeze = true;
2035         }
2036
2037         /* PTA parameter */
2038         rtw_coex_table(rtwdev, 0);
2039         rtw_coex_tdma(rtwdev, true, 0);
2040         rtw_coex_query_bt_info(rtwdev);
2041 }
2042
2043 void rtw_coex_power_on_setting(struct rtw_dev *rtwdev)
2044 {
2045         struct rtw_coex *coex = &rtwdev->coex;
2046
2047         coex->stop_dm = true;
2048         coex->wl_rf_off = false;
2049
2050         /* enable BB, we can write 0x948 */
2051         rtw_write8_set(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1));
2052
2053         rtw_coex_monitor_bt_enable(rtwdev);
2054         rtw_coex_set_rfe_type(rtwdev);
2055
2056         /* set antenna path to BT */
2057         rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_POWERON);
2058
2059         /* red x issue */
2060         rtw_write8(rtwdev, 0xff1a, 0x0);
2061 }
2062
2063 void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
2064 {
2065         __rtw_coex_init_hw_config(rtwdev, wifi_only);
2066 }
2067
2068 void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
2069 {
2070         struct rtw_coex *coex = &rtwdev->coex;
2071         struct rtw_coex_stat *coex_stat = &coex->stat;
2072
2073         if (coex->stop_dm)
2074                 return;
2075
2076         if (type == COEX_IPS_ENTER) {
2077                 coex_stat->wl_under_ips = true;
2078
2079                 /* for lps off */
2080                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ALL, false);
2081
2082                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_WOFF);
2083                 rtw_coex_action_coex_all_off(rtwdev);
2084         } else if (type == COEX_IPS_LEAVE) {
2085                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_ONOFF, true);
2086
2087                 /* run init hw config (exclude wifi only) */
2088                 __rtw_coex_init_hw_config(rtwdev, false);
2089                 /* sw all off */
2090
2091                 coex_stat->wl_under_ips = false;
2092         }
2093 }
2094
2095 void rtw_coex_lps_notify(struct rtw_dev *rtwdev, u8 type)
2096 {
2097         struct rtw_coex *coex = &rtwdev->coex;
2098         struct rtw_coex_stat *coex_stat = &coex->stat;
2099
2100         if (coex->stop_dm)
2101                 return;
2102
2103         if (type == COEX_LPS_ENABLE) {
2104                 coex_stat->wl_under_lps = true;
2105
2106                 if (coex_stat->wl_force_lps_ctrl) {
2107                         /* for ps-tdma */
2108                         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2109                 } else {
2110                         /* for native ps */
2111                         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2112
2113                         rtw_coex_run_coex(rtwdev, COEX_RSN_LPS);
2114                 }
2115         } else if (type == COEX_LPS_DISABLE) {
2116                 coex_stat->wl_under_lps = false;
2117
2118                 /* for lps off */
2119                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2120
2121                 if (!coex_stat->wl_force_lps_ctrl)
2122                         rtw_coex_query_bt_info(rtwdev);
2123         }
2124 }
2125
2126 void rtw_coex_scan_notify(struct rtw_dev *rtwdev, u8 type)
2127 {
2128         struct rtw_coex *coex = &rtwdev->coex;
2129         struct rtw_coex_stat *coex_stat = &coex->stat;
2130
2131         if (coex->stop_dm)
2132                 return;
2133
2134         coex->freeze = false;
2135
2136         if (type != COEX_SCAN_FINISH)
2137                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2138                                     COEX_SCBD_ONOFF, true);
2139
2140         if (type == COEX_SCAN_START_5G) {
2141                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2142                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSCANSTART);
2143         } else if ((type == COEX_SCAN_START_2G) || (type == COEX_SCAN_START)) {
2144                 coex_stat->wl_hi_pri_task2 = true;
2145
2146                 /* Force antenna setup for no scan result issue */
2147                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2148                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSCANSTART);
2149         } else {
2150                 coex_stat->wl_hi_pri_task2 = false;
2151                 rtw_coex_run_coex(rtwdev, COEX_RSN_SCANFINISH);
2152         }
2153 }
2154
2155 void rtw_coex_switchband_notify(struct rtw_dev *rtwdev, u8 type)
2156 {
2157         struct rtw_coex *coex = &rtwdev->coex;
2158
2159         if (coex->stop_dm)
2160                 return;
2161
2162         if (type == COEX_SWITCH_TO_5G)
2163                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GSWITCHBAND);
2164         else if (type == COEX_SWITCH_TO_24G_NOFORSCAN)
2165                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GSWITCHBAND);
2166         else
2167                 rtw_coex_scan_notify(rtwdev, COEX_SCAN_START_2G);
2168 }
2169
2170 void rtw_coex_connect_notify(struct rtw_dev *rtwdev, u8 type)
2171 {
2172         struct rtw_coex *coex = &rtwdev->coex;
2173         struct rtw_coex_stat *coex_stat = &coex->stat;
2174
2175         if (coex->stop_dm)
2176                 return;
2177
2178         rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE | COEX_SCBD_SCAN |
2179                             COEX_SCBD_ONOFF, true);
2180
2181         if (type == COEX_ASSOCIATE_5G_START) {
2182                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2183                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONSTART);
2184         } else if (type == COEX_ASSOCIATE_5G_FINISH) {
2185                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2186                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GCONFINISH);
2187         } else if (type == COEX_ASSOCIATE_START) {
2188                 coex_stat->wl_hi_pri_task1 = true;
2189                 coex_stat->cnt_wl[COEX_CNT_WL_CONNPKT] = 2;
2190
2191                 /* Force antenna setup for no scan result issue */
2192                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2193
2194                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONSTART);
2195
2196                 /* To keep TDMA case during connect process,
2197                  * to avoid changed by Btinfo and runcoexmechanism
2198                  */
2199                 coex->freeze = true;
2200                 ieee80211_queue_delayed_work(rtwdev->hw, &coex->defreeze_work,
2201                                              5 * HZ);
2202         } else {
2203                 coex_stat->wl_hi_pri_task1 = false;
2204                 coex->freeze = false;
2205
2206                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GCONFINISH);
2207         }
2208 }
2209
2210 void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
2211 {
2212         struct rtw_coex *coex = &rtwdev->coex;
2213         struct rtw_coex_stat *coex_stat = &coex->stat;
2214         u8 para[6] = {0};
2215
2216         if (coex->stop_dm)
2217                 return;
2218
2219         if (type == COEX_MEDIA_CONNECT_5G) {
2220                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2221
2222                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_5G);
2223                 rtw_coex_run_coex(rtwdev, COEX_RSN_5GMEDIA);
2224         } else if (type == COEX_MEDIA_CONNECT) {
2225                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, true);
2226
2227                 /* Force antenna setup for no scan result issue */
2228                 rtw_coex_set_ant_path(rtwdev, true, COEX_SET_ANT_2G);
2229
2230                 /* Set CCK Rx high Pri */
2231                 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 1);
2232
2233                 /* always enable 5ms extend if connect */
2234                 para[0] = COEX_H2C69_WL_LEAKAP;
2235                 para[1] = PARA1_H2C69_EN_5MS; /* enable 5ms extend */
2236                 rtw_fw_bt_wifi_control(rtwdev, para[0], &para[1]);
2237                 coex_stat->wl_slot_extend = true;
2238                 rtw_coex_run_coex(rtwdev, COEX_RSN_2GMEDIA);
2239         } else {
2240                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_ACTIVE, false);
2241
2242                 rtw_coex_set_wl_pri_mask(rtwdev, COEX_WLPRI_RX_CCK, 0);
2243
2244                 rtw_coex_run_coex(rtwdev, COEX_RSN_MEDIADISCON);
2245         }
2246
2247         rtw_coex_update_wl_ch_info(rtwdev, type);
2248 }
2249
2250 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2251 {
2252         struct rtw_coex *coex = &rtwdev->coex;
2253         struct rtw_coex_stat *coex_stat = &coex->stat;
2254         struct rtw_chip_info *chip = rtwdev->chip;
2255         unsigned long bt_relink_time;
2256         u8 i, rsp_source = 0, type;
2257
2258         rsp_source = buf[0] & 0xf;
2259         if (rsp_source >= COEX_BTINFO_SRC_MAX)
2260                 rsp_source = COEX_BTINFO_SRC_WL_FW;
2261
2262         if (rsp_source == COEX_BTINFO_SRC_BT_IQK) {
2263                 coex_stat->bt_iqk_state = buf[1];
2264                 if (coex_stat->bt_iqk_state == 1)
2265                         coex_stat->cnt_bt[COEX_CNT_BT_IQK]++;
2266                 else if (coex_stat->bt_iqk_state == 2)
2267                         coex_stat->cnt_bt[COEX_CNT_BT_IQKFAIL]++;
2268
2269                 return;
2270         }
2271
2272         if (rsp_source == COEX_BTINFO_SRC_BT_SCBD) {
2273                 rtw_coex_monitor_bt_enable(rtwdev);
2274                 if (coex_stat->bt_disabled != coex_stat->bt_disabled_pre) {
2275                         coex_stat->bt_disabled_pre = coex_stat->bt_disabled;
2276                         rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2277                 }
2278                 return;
2279         }
2280
2281         if (rsp_source == COEX_BTINFO_SRC_BT_RSP ||
2282             rsp_source == COEX_BTINFO_SRC_BT_ACT) {
2283                 if (coex_stat->bt_disabled) {
2284                         coex_stat->bt_disabled = false;
2285                         coex_stat->bt_reenable = true;
2286                         ieee80211_queue_delayed_work(rtwdev->hw,
2287                                                      &coex->bt_reenable_work,
2288                                                      15 * HZ);
2289                 }
2290         }
2291
2292         for (i = 0; i < length; i++) {
2293                 if (i < COEX_BTINFO_LENGTH_MAX)
2294                         coex_stat->bt_info_c2h[rsp_source][i] = buf[i];
2295                 else
2296                         break;
2297         }
2298
2299         if (rsp_source == COEX_BTINFO_SRC_WL_FW) {
2300                 rtw_coex_update_bt_link_info(rtwdev);
2301                 rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2302                 return;
2303         }
2304
2305         /* get the same info from bt, skip it */
2306         if (coex_stat->bt_info_c2h[rsp_source][1] == coex_stat->bt_info_lb2 &&
2307             coex_stat->bt_info_c2h[rsp_source][2] == coex_stat->bt_info_lb3 &&
2308             coex_stat->bt_info_c2h[rsp_source][3] == coex_stat->bt_info_hb0 &&
2309             coex_stat->bt_info_c2h[rsp_source][4] == coex_stat->bt_info_hb1 &&
2310             coex_stat->bt_info_c2h[rsp_source][5] == coex_stat->bt_info_hb2 &&
2311             coex_stat->bt_info_c2h[rsp_source][6] == coex_stat->bt_info_hb3)
2312                 return;
2313
2314         coex_stat->bt_info_lb2 = coex_stat->bt_info_c2h[rsp_source][1];
2315         coex_stat->bt_info_lb3 = coex_stat->bt_info_c2h[rsp_source][2];
2316         coex_stat->bt_info_hb0 = coex_stat->bt_info_c2h[rsp_source][3];
2317         coex_stat->bt_info_hb1 = coex_stat->bt_info_c2h[rsp_source][4];
2318         coex_stat->bt_info_hb2 = coex_stat->bt_info_c2h[rsp_source][5];
2319         coex_stat->bt_info_hb3 = coex_stat->bt_info_c2h[rsp_source][6];
2320
2321         /* 0xff means BT is under WHCK test */
2322         coex_stat->bt_whck_test = (coex_stat->bt_info_lb2 == 0xff);
2323         coex_stat->bt_inq_page = ((coex_stat->bt_info_lb2 & BIT(2)) == BIT(2));
2324         coex_stat->bt_acl_busy = ((coex_stat->bt_info_lb2 & BIT(3)) == BIT(3));
2325         coex_stat->cnt_bt[COEX_CNT_BT_RETRY] = coex_stat->bt_info_lb3 & 0xf;
2326         if (coex_stat->cnt_bt[COEX_CNT_BT_RETRY] >= 1)
2327                 coex_stat->cnt_bt[COEX_CNT_BT_POPEVENT]++;
2328
2329         coex_stat->bt_fix_2M = ((coex_stat->bt_info_lb3 & BIT(4)) == BIT(4));
2330         coex_stat->bt_inq = ((coex_stat->bt_info_lb3 & BIT(5)) == BIT(5));
2331         if (coex_stat->bt_inq)
2332                 coex_stat->cnt_bt[COEX_CNT_BT_INQ]++;
2333
2334         coex_stat->bt_page = ((coex_stat->bt_info_lb3 & BIT(7)) == BIT(7));
2335         if (coex_stat->bt_page) {
2336                 coex_stat->cnt_bt[COEX_CNT_BT_PAGE]++;
2337                 if (coex_stat->wl_linkscan_proc ||
2338                     coex_stat->wl_hi_pri_task1 ||
2339                     coex_stat->wl_hi_pri_task2 || coex_stat->wl_gl_busy)
2340                         rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, true);
2341                 else
2342                         rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2343         } else {
2344                 rtw_coex_write_scbd(rtwdev, COEX_SCBD_SCAN, false);
2345         }
2346
2347         /* unit: % (value-100 to translate to unit: dBm in coex info) */
2348         if (chip->bt_rssi_type == COEX_BTRSSI_RATIO) {
2349                 coex_stat->bt_rssi = coex_stat->bt_info_hb0 * 2 + 10;
2350         } else { /* original unit: dbm -> unit: % ->  value-100 in coex info */
2351                 if (coex_stat->bt_info_hb0 <= 127)
2352                         coex_stat->bt_rssi = 100;
2353                 else if (256 - coex_stat->bt_info_hb0 <= 100)
2354                         coex_stat->bt_rssi = 100 - (256 - coex_stat->bt_info_hb0);
2355                 else
2356                         coex_stat->bt_rssi = 0;
2357         }
2358
2359         coex_stat->bt_ble_exist = ((coex_stat->bt_info_hb1 & BIT(0)) == BIT(0));
2360         if (coex_stat->bt_info_hb1 & BIT(1))
2361                 coex_stat->cnt_bt[COEX_CNT_BT_REINIT]++;
2362
2363         if (coex_stat->bt_info_hb1 & BIT(2)) {
2364                 coex_stat->cnt_bt[COEX_CNT_BT_SETUPLINK]++;
2365                 coex_stat->bt_setup_link = true;
2366                 if (coex_stat->bt_reenable)
2367                         bt_relink_time = 6 * HZ;
2368                 else
2369                         bt_relink_time = 2 * HZ;
2370
2371                 ieee80211_queue_delayed_work(rtwdev->hw,
2372                                              &coex->bt_relink_work,
2373                                              bt_relink_time);
2374         }
2375
2376         if (coex_stat->bt_info_hb1 & BIT(3))
2377                 coex_stat->cnt_bt[COEX_CNT_BT_IGNWLANACT]++;
2378
2379         coex_stat->bt_ble_voice = ((coex_stat->bt_info_hb1 & BIT(4)) == BIT(4));
2380         coex_stat->bt_ble_scan_en = ((coex_stat->bt_info_hb1 & BIT(5)) == BIT(5));
2381         if (coex_stat->bt_info_hb1 & BIT(6))
2382                 coex_stat->cnt_bt[COEX_CNT_BT_ROLESWITCH]++;
2383
2384         coex_stat->bt_multi_link = ((coex_stat->bt_info_hb1 & BIT(7)) == BIT(7));
2385         /* resend wifi info to bt, it is reset and lost the info */
2386         if ((coex_stat->bt_info_hb1 & BIT(1))) {
2387                 if (coex_stat->wl_connected)
2388                         type = COEX_MEDIA_CONNECT;
2389                 else
2390                         type = COEX_MEDIA_DISCONNECT;
2391                 rtw_coex_update_wl_ch_info(rtwdev, type);
2392         }
2393
2394         /* if ignore_wlan_act && not set_up_link */
2395         if ((coex_stat->bt_info_hb1 & BIT(3)) &&
2396             (!(coex_stat->bt_info_hb1 & BIT(2))))
2397                 rtw_coex_ignore_wlan_act(rtwdev, false);
2398
2399         coex_stat->bt_opp_exist = ((coex_stat->bt_info_hb2 & BIT(0)) == BIT(0));
2400         if (coex_stat->bt_info_hb2 & BIT(1))
2401                 coex_stat->cnt_bt[COEX_CNT_BT_AFHUPDATE]++;
2402
2403         coex_stat->bt_a2dp_active = (coex_stat->bt_info_hb2 & BIT(2)) == BIT(2);
2404         coex_stat->bt_slave = ((coex_stat->bt_info_hb2 & BIT(3)) == BIT(3));
2405         coex_stat->bt_hid_slot = (coex_stat->bt_info_hb2 & 0x30) >> 4;
2406         coex_stat->bt_hid_pair_num = (coex_stat->bt_info_hb2 & 0xc0) >> 6;
2407         if (coex_stat->bt_hid_pair_num > 0 && coex_stat->bt_hid_slot >= 2)
2408                 coex_stat->bt_418_hid_exist = true;
2409         else if (coex_stat->bt_hid_pair_num == 0)
2410                 coex_stat->bt_418_hid_exist = false;
2411
2412         if ((coex_stat->bt_info_lb2 & 0x49) == 0x49)
2413                 coex_stat->bt_a2dp_bitpool = (coex_stat->bt_info_hb3 & 0x7f);
2414         else
2415                 coex_stat->bt_a2dp_bitpool = 0;
2416
2417         coex_stat->bt_a2dp_sink = ((coex_stat->bt_info_hb3 & BIT(7)) == BIT(7));
2418
2419         rtw_coex_update_bt_link_info(rtwdev);
2420         rtw_coex_run_coex(rtwdev, COEX_RSN_BTINFO);
2421 }
2422
2423 void rtw_coex_wl_fwdbginfo_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
2424 {
2425         struct rtw_coex *coex = &rtwdev->coex;
2426         struct rtw_coex_stat *coex_stat = &coex->stat;
2427         u8 val;
2428         int i;
2429
2430         if (WARN(length < 8, "invalid wl info c2h length\n"))
2431                 return;
2432
2433         if (buf[0] != 0x08)
2434                 return;
2435
2436         for (i = 1; i < 8; i++) {
2437                 val = coex_stat->wl_fw_dbg_info_pre[i];
2438                 if (buf[i] >= val)
2439                         coex_stat->wl_fw_dbg_info[i] = buf[i] - val;
2440                 else
2441                         coex_stat->wl_fw_dbg_info[i] = val - buf[i];
2442
2443                 coex_stat->wl_fw_dbg_info_pre[i] = buf[i];
2444         }
2445
2446         coex_stat->cnt_wl[COEX_CNT_WL_FW_NOTIFY]++;
2447         rtw_coex_wl_ccklock_action(rtwdev);
2448         rtw_coex_wl_ccklock_detect(rtwdev);
2449 }
2450
2451 void rtw_coex_wl_status_change_notify(struct rtw_dev *rtwdev)
2452 {
2453         struct rtw_coex *coex = &rtwdev->coex;
2454
2455         if (coex->stop_dm)
2456                 return;
2457
2458         rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2459 }
2460
2461 void rtw_coex_bt_relink_work(struct work_struct *work)
2462 {
2463         struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2464                                               coex.bt_relink_work.work);
2465         struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2466
2467         mutex_lock(&rtwdev->mutex);
2468         coex_stat->bt_setup_link = false;
2469         rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2470         mutex_unlock(&rtwdev->mutex);
2471 }
2472
2473 void rtw_coex_bt_reenable_work(struct work_struct *work)
2474 {
2475         struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2476                                               coex.bt_reenable_work.work);
2477         struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2478
2479         mutex_lock(&rtwdev->mutex);
2480         coex_stat->bt_reenable = false;
2481         mutex_unlock(&rtwdev->mutex);
2482 }
2483
2484 void rtw_coex_defreeze_work(struct work_struct *work)
2485 {
2486         struct rtw_dev *rtwdev = container_of(work, struct rtw_dev,
2487                                               coex.defreeze_work.work);
2488         struct rtw_coex *coex = &rtwdev->coex;
2489         struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
2490
2491         mutex_lock(&rtwdev->mutex);
2492         coex->freeze = false;
2493         coex_stat->wl_hi_pri_task1 = false;
2494         rtw_coex_run_coex(rtwdev, COEX_RSN_WLSTATUS);
2495         mutex_unlock(&rtwdev->mutex);
2496 }