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