18c086312SLarry Finger // SPDX-License-Identifier: GPL-2.0
28c086312SLarry Finger /* Copyright(c) 2009-2013 Realtek Corporation.*/
38c086312SLarry Finger
4f1d2b4d3SLarry Finger #include "../wifi.h"
5f1d2b4d3SLarry Finger #include <linux/vmalloc.h>
6f1d2b4d3SLarry Finger #include <linux/module.h>
7f1d2b4d3SLarry Finger
8f1d2b4d3SLarry Finger #include "rtl_btc.h"
9f1d2b4d3SLarry Finger #include "halbt_precomp.h"
10f1d2b4d3SLarry Finger
11f1d2b4d3SLarry Finger static struct rtl_btc_ops rtl_btc_operation = {
12f1d2b4d3SLarry Finger .btc_init_variables = rtl_btc_init_variables,
139177c336SPing-Ke Shih .btc_init_variables_wifi_only = rtl_btc_init_variables_wifi_only,
1440d9dd4fSPing-Ke Shih .btc_deinit_variables = rtl_btc_deinit_variables,
15f1d2b4d3SLarry Finger .btc_init_hal_vars = rtl_btc_init_hal_vars,
16a44709bbSPing-Ke Shih .btc_power_on_setting = rtl_btc_power_on_setting,
17f1d2b4d3SLarry Finger .btc_init_hw_config = rtl_btc_init_hw_config,
189177c336SPing-Ke Shih .btc_init_hw_config_wifi_only = rtl_btc_init_hw_config_wifi_only,
19f1d2b4d3SLarry Finger .btc_ips_notify = rtl_btc_ips_notify,
20f1d2b4d3SLarry Finger .btc_lps_notify = rtl_btc_lps_notify,
21f1d2b4d3SLarry Finger .btc_scan_notify = rtl_btc_scan_notify,
229177c336SPing-Ke Shih .btc_scan_notify_wifi_only = rtl_btc_scan_notify_wifi_only,
23f1d2b4d3SLarry Finger .btc_connect_notify = rtl_btc_connect_notify,
24f1d2b4d3SLarry Finger .btc_mediastatus_notify = rtl_btc_mediastatus_notify,
25f1d2b4d3SLarry Finger .btc_periodical = rtl_btc_periodical,
26f1d2b4d3SLarry Finger .btc_halt_notify = rtl_btc_halt_notify,
27f1d2b4d3SLarry Finger .btc_btinfo_notify = rtl_btc_btinfo_notify,
286aad6075SPing-Ke Shih .btc_btmpinfo_notify = rtl_btc_btmpinfo_notify,
29f1d2b4d3SLarry Finger .btc_is_limited_dig = rtl_btc_is_limited_dig,
30f1d2b4d3SLarry Finger .btc_is_disable_edca_turbo = rtl_btc_is_disable_edca_turbo,
31f1d2b4d3SLarry Finger .btc_is_bt_disabled = rtl_btc_is_bt_disabled,
32f1d2b4d3SLarry Finger .btc_special_packet_notify = rtl_btc_special_packet_notify,
3317bf8510SPing-Ke Shih .btc_switch_band_notify = rtl_btc_switch_band_notify,
349177c336SPing-Ke Shih .btc_switch_band_notify_wifi_only = rtl_btc_switch_band_notify_wifionly,
3554685f9cSPing-Ke Shih .btc_record_pwr_mode = rtl_btc_record_pwr_mode,
3642213f2fSPing-Ke Shih .btc_get_lps_val = rtl_btc_get_lps_val,
3742213f2fSPing-Ke Shih .btc_get_rpwm_val = rtl_btc_get_rpwm_val,
3842213f2fSPing-Ke Shih .btc_is_bt_ctrl_lps = rtl_btc_is_bt_ctrl_lps,
39c692205dSPing-Ke Shih .btc_is_bt_lps_on = rtl_btc_is_bt_lps_on,
402635664eSPing-Ke Shih .btc_get_ampdu_cfg = rtl_btc_get_ampdu_cfg,
41610247f4SPing-Ke Shih .btc_display_bt_coex_info = rtl_btc_display_bt_coex_info,
42f1d2b4d3SLarry Finger };
43f1d2b4d3SLarry Finger
rtl_btc_display_bt_coex_info(struct rtl_priv * rtlpriv,struct seq_file * m)44610247f4SPing-Ke Shih void rtl_btc_display_bt_coex_info(struct rtl_priv *rtlpriv, struct seq_file *m)
45610247f4SPing-Ke Shih {
4640d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
4740d9dd4fSPing-Ke Shih
4840d9dd4fSPing-Ke Shih if (!btcoexist) {
4940d9dd4fSPing-Ke Shih seq_puts(m, "btc_coexist context is NULL!\n");
5040d9dd4fSPing-Ke Shih return;
5140d9dd4fSPing-Ke Shih }
5240d9dd4fSPing-Ke Shih
5340d9dd4fSPing-Ke Shih exhalbtc_display_bt_coex_info(btcoexist, m);
54610247f4SPing-Ke Shih }
55610247f4SPing-Ke Shih
rtl_btc_record_pwr_mode(struct rtl_priv * rtlpriv,u8 * buf,u8 len)5654685f9cSPing-Ke Shih void rtl_btc_record_pwr_mode(struct rtl_priv *rtlpriv, u8 *buf, u8 len)
5754685f9cSPing-Ke Shih {
5840d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
5954685f9cSPing-Ke Shih u8 safe_len;
6054685f9cSPing-Ke Shih
6140d9dd4fSPing-Ke Shih if (!btcoexist)
6240d9dd4fSPing-Ke Shih return;
6340d9dd4fSPing-Ke Shih
6440d9dd4fSPing-Ke Shih safe_len = sizeof(btcoexist->pwr_mode_val);
6554685f9cSPing-Ke Shih
6654685f9cSPing-Ke Shih if (safe_len > len)
6754685f9cSPing-Ke Shih safe_len = len;
6854685f9cSPing-Ke Shih
6940d9dd4fSPing-Ke Shih memcpy(btcoexist->pwr_mode_val, buf, safe_len);
7054685f9cSPing-Ke Shih }
7154685f9cSPing-Ke Shih
rtl_btc_get_lps_val(struct rtl_priv * rtlpriv)7242213f2fSPing-Ke Shih u8 rtl_btc_get_lps_val(struct rtl_priv *rtlpriv)
7342213f2fSPing-Ke Shih {
7440d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
7540d9dd4fSPing-Ke Shih
7640d9dd4fSPing-Ke Shih if (!btcoexist)
7740d9dd4fSPing-Ke Shih return 0;
7840d9dd4fSPing-Ke Shih
7940d9dd4fSPing-Ke Shih return btcoexist->bt_info.lps_val;
8042213f2fSPing-Ke Shih }
8142213f2fSPing-Ke Shih
rtl_btc_get_rpwm_val(struct rtl_priv * rtlpriv)8242213f2fSPing-Ke Shih u8 rtl_btc_get_rpwm_val(struct rtl_priv *rtlpriv)
8342213f2fSPing-Ke Shih {
8440d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
8540d9dd4fSPing-Ke Shih
8640d9dd4fSPing-Ke Shih if (!btcoexist)
8740d9dd4fSPing-Ke Shih return 0;
8840d9dd4fSPing-Ke Shih
8940d9dd4fSPing-Ke Shih return btcoexist->bt_info.rpwm_val;
9042213f2fSPing-Ke Shih }
9142213f2fSPing-Ke Shih
rtl_btc_is_bt_ctrl_lps(struct rtl_priv * rtlpriv)9242213f2fSPing-Ke Shih bool rtl_btc_is_bt_ctrl_lps(struct rtl_priv *rtlpriv)
9342213f2fSPing-Ke Shih {
9440d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
9540d9dd4fSPing-Ke Shih
9640d9dd4fSPing-Ke Shih if (!btcoexist)
9740d9dd4fSPing-Ke Shih return false;
9840d9dd4fSPing-Ke Shih
9940d9dd4fSPing-Ke Shih return btcoexist->bt_info.bt_ctrl_lps;
10042213f2fSPing-Ke Shih }
10142213f2fSPing-Ke Shih
rtl_btc_is_bt_lps_on(struct rtl_priv * rtlpriv)102c692205dSPing-Ke Shih bool rtl_btc_is_bt_lps_on(struct rtl_priv *rtlpriv)
103c692205dSPing-Ke Shih {
10440d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
10540d9dd4fSPing-Ke Shih
10640d9dd4fSPing-Ke Shih if (!btcoexist)
10740d9dd4fSPing-Ke Shih return false;
10840d9dd4fSPing-Ke Shih
10940d9dd4fSPing-Ke Shih return btcoexist->bt_info.bt_lps_on;
110c692205dSPing-Ke Shih }
111c692205dSPing-Ke Shih
rtl_btc_get_ampdu_cfg(struct rtl_priv * rtlpriv,u8 * reject_agg,u8 * ctrl_agg_size,u8 * agg_size)1122635664eSPing-Ke Shih void rtl_btc_get_ampdu_cfg(struct rtl_priv *rtlpriv, u8 *reject_agg,
1132635664eSPing-Ke Shih u8 *ctrl_agg_size, u8 *agg_size)
1142635664eSPing-Ke Shih {
11540d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
11640d9dd4fSPing-Ke Shih
11740d9dd4fSPing-Ke Shih if (!btcoexist) {
11840d9dd4fSPing-Ke Shih *reject_agg = false;
11940d9dd4fSPing-Ke Shih *ctrl_agg_size = false;
12040d9dd4fSPing-Ke Shih return;
12140d9dd4fSPing-Ke Shih }
12240d9dd4fSPing-Ke Shih
1232635664eSPing-Ke Shih if (reject_agg)
12440d9dd4fSPing-Ke Shih *reject_agg = btcoexist->bt_info.reject_agg_pkt;
1252635664eSPing-Ke Shih if (ctrl_agg_size)
12640d9dd4fSPing-Ke Shih *ctrl_agg_size = btcoexist->bt_info.bt_ctrl_agg_buf_size;
1272635664eSPing-Ke Shih if (agg_size)
12840d9dd4fSPing-Ke Shih *agg_size = btcoexist->bt_info.agg_buf_size;
12940d9dd4fSPing-Ke Shih }
13040d9dd4fSPing-Ke Shih
rtl_btc_alloc_variable(struct rtl_priv * rtlpriv,bool wifi_only)13140d9dd4fSPing-Ke Shih static void rtl_btc_alloc_variable(struct rtl_priv *rtlpriv, bool wifi_only)
13240d9dd4fSPing-Ke Shih {
1339177c336SPing-Ke Shih if (wifi_only)
1349177c336SPing-Ke Shih rtlpriv->btcoexist.wifi_only_context =
1359177c336SPing-Ke Shih kzalloc(sizeof(struct wifi_only_cfg), GFP_KERNEL);
1369177c336SPing-Ke Shih else
13740d9dd4fSPing-Ke Shih rtlpriv->btcoexist.btc_context =
13840d9dd4fSPing-Ke Shih kzalloc(sizeof(struct btc_coexist), GFP_KERNEL);
13940d9dd4fSPing-Ke Shih }
14040d9dd4fSPing-Ke Shih
rtl_btc_free_variable(struct rtl_priv * rtlpriv)14140d9dd4fSPing-Ke Shih static void rtl_btc_free_variable(struct rtl_priv *rtlpriv)
14240d9dd4fSPing-Ke Shih {
14340d9dd4fSPing-Ke Shih kfree(rtlpriv->btcoexist.btc_context);
14440d9dd4fSPing-Ke Shih rtlpriv->btcoexist.btc_context = NULL;
1459177c336SPing-Ke Shih
1469177c336SPing-Ke Shih kfree(rtlpriv->btcoexist.wifi_only_context);
1479177c336SPing-Ke Shih rtlpriv->btcoexist.wifi_only_context = NULL;
1482635664eSPing-Ke Shih }
1492635664eSPing-Ke Shih
rtl_btc_init_variables(struct rtl_priv * rtlpriv)150f1d2b4d3SLarry Finger void rtl_btc_init_variables(struct rtl_priv *rtlpriv)
151f1d2b4d3SLarry Finger {
15240d9dd4fSPing-Ke Shih rtl_btc_alloc_variable(rtlpriv, false);
15340d9dd4fSPing-Ke Shih
15440d9dd4fSPing-Ke Shih exhalbtc_initlize_variables(rtlpriv);
15587d8a9f3SPing-Ke Shih exhalbtc_bind_bt_coex_withadapter(rtlpriv);
156f1d2b4d3SLarry Finger }
157f1d2b4d3SLarry Finger
rtl_btc_init_variables_wifi_only(struct rtl_priv * rtlpriv)1589177c336SPing-Ke Shih void rtl_btc_init_variables_wifi_only(struct rtl_priv *rtlpriv)
1599177c336SPing-Ke Shih {
1609177c336SPing-Ke Shih rtl_btc_alloc_variable(rtlpriv, true);
1619177c336SPing-Ke Shih
1629177c336SPing-Ke Shih exhalbtc_initlize_variables_wifi_only(rtlpriv);
1639177c336SPing-Ke Shih }
1649177c336SPing-Ke Shih
rtl_btc_deinit_variables(struct rtl_priv * rtlpriv)16540d9dd4fSPing-Ke Shih void rtl_btc_deinit_variables(struct rtl_priv *rtlpriv)
16640d9dd4fSPing-Ke Shih {
16740d9dd4fSPing-Ke Shih rtl_btc_free_variable(rtlpriv);
16840d9dd4fSPing-Ke Shih }
16940d9dd4fSPing-Ke Shih
rtl_btc_init_hal_vars(struct rtl_priv * rtlpriv)170f1d2b4d3SLarry Finger void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
171f1d2b4d3SLarry Finger {
1720199103eSYan-Hsuan Chuang /* move ant_num, bt_type and single_ant_path to
1730199103eSYan-Hsuan Chuang * exhalbtc_bind_bt_coex_withadapter()
1740199103eSYan-Hsuan Chuang */
175f1d2b4d3SLarry Finger }
176f1d2b4d3SLarry Finger
rtl_btc_power_on_setting(struct rtl_priv * rtlpriv)177a44709bbSPing-Ke Shih void rtl_btc_power_on_setting(struct rtl_priv *rtlpriv)
178a44709bbSPing-Ke Shih {
17940d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
18040d9dd4fSPing-Ke Shih
18140d9dd4fSPing-Ke Shih if (!btcoexist)
18240d9dd4fSPing-Ke Shih return;
18340d9dd4fSPing-Ke Shih
18440d9dd4fSPing-Ke Shih exhalbtc_power_on_setting(btcoexist);
185a44709bbSPing-Ke Shih }
186a44709bbSPing-Ke Shih
rtl_btc_init_hw_config(struct rtl_priv * rtlpriv)187f1d2b4d3SLarry Finger void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
188f1d2b4d3SLarry Finger {
18940d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
19040d9dd4fSPing-Ke Shih
1910199103eSYan-Hsuan Chuang u8 bt_exist;
1920199103eSYan-Hsuan Chuang
1930199103eSYan-Hsuan Chuang bt_exist = rtl_get_hwpg_bt_exist(rtlpriv);
194*c8159c3fSLarry Finger rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG,
1950199103eSYan-Hsuan Chuang "%s, bt_exist is %d\n", __func__, bt_exist);
1960199103eSYan-Hsuan Chuang
19740d9dd4fSPing-Ke Shih if (!btcoexist)
19840d9dd4fSPing-Ke Shih return;
19940d9dd4fSPing-Ke Shih
20040d9dd4fSPing-Ke Shih exhalbtc_init_hw_config(btcoexist, !bt_exist);
20140d9dd4fSPing-Ke Shih exhalbtc_init_coex_dm(btcoexist);
202f1d2b4d3SLarry Finger }
203f1d2b4d3SLarry Finger
rtl_btc_init_hw_config_wifi_only(struct rtl_priv * rtlpriv)2049177c336SPing-Ke Shih void rtl_btc_init_hw_config_wifi_only(struct rtl_priv *rtlpriv)
2059177c336SPing-Ke Shih {
2069177c336SPing-Ke Shih struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
2079177c336SPing-Ke Shih
2089177c336SPing-Ke Shih if (!wifionly_cfg)
2099177c336SPing-Ke Shih return;
2109177c336SPing-Ke Shih
2119177c336SPing-Ke Shih exhalbtc_init_hw_config_wifi_only(wifionly_cfg);
2129177c336SPing-Ke Shih }
2139177c336SPing-Ke Shih
rtl_btc_ips_notify(struct rtl_priv * rtlpriv,u8 type)214f1d2b4d3SLarry Finger void rtl_btc_ips_notify(struct rtl_priv *rtlpriv, u8 type)
215f1d2b4d3SLarry Finger {
21640d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
21740d9dd4fSPing-Ke Shih
21840d9dd4fSPing-Ke Shih if (!btcoexist)
21940d9dd4fSPing-Ke Shih return;
22040d9dd4fSPing-Ke Shih
22140d9dd4fSPing-Ke Shih exhalbtc_ips_notify(btcoexist, type);
222ee373844SPing-Ke Shih
223ee373844SPing-Ke Shih if (type == ERFON) {
224ee373844SPing-Ke Shih /* In some situation, it doesn't scan after leaving IPS, and
225ee373844SPing-Ke Shih * this will cause btcoex in wrong state.
226ee373844SPing-Ke Shih */
227ee373844SPing-Ke Shih exhalbtc_scan_notify(btcoexist, 1);
228ee373844SPing-Ke Shih exhalbtc_scan_notify(btcoexist, 0);
229ee373844SPing-Ke Shih }
230f1d2b4d3SLarry Finger }
231f1d2b4d3SLarry Finger
rtl_btc_lps_notify(struct rtl_priv * rtlpriv,u8 type)232f1d2b4d3SLarry Finger void rtl_btc_lps_notify(struct rtl_priv *rtlpriv, u8 type)
233f1d2b4d3SLarry Finger {
23440d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
23540d9dd4fSPing-Ke Shih
23640d9dd4fSPing-Ke Shih if (!btcoexist)
23740d9dd4fSPing-Ke Shih return;
23840d9dd4fSPing-Ke Shih
23940d9dd4fSPing-Ke Shih exhalbtc_lps_notify(btcoexist, type);
240f1d2b4d3SLarry Finger }
241f1d2b4d3SLarry Finger
rtl_btc_scan_notify(struct rtl_priv * rtlpriv,u8 scantype)242f1d2b4d3SLarry Finger void rtl_btc_scan_notify(struct rtl_priv *rtlpriv, u8 scantype)
243f1d2b4d3SLarry Finger {
24440d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
24540d9dd4fSPing-Ke Shih
24640d9dd4fSPing-Ke Shih if (!btcoexist)
24740d9dd4fSPing-Ke Shih return;
24840d9dd4fSPing-Ke Shih
24940d9dd4fSPing-Ke Shih exhalbtc_scan_notify(btcoexist, scantype);
250f1d2b4d3SLarry Finger }
251f1d2b4d3SLarry Finger
rtl_btc_scan_notify_wifi_only(struct rtl_priv * rtlpriv,u8 scantype)2529177c336SPing-Ke Shih void rtl_btc_scan_notify_wifi_only(struct rtl_priv *rtlpriv, u8 scantype)
2539177c336SPing-Ke Shih {
2549177c336SPing-Ke Shih struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
2559177c336SPing-Ke Shih struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
2569177c336SPing-Ke Shih u8 is_5g = (rtlhal->current_bandtype == BAND_ON_5G);
2579177c336SPing-Ke Shih
2589177c336SPing-Ke Shih if (!wifionly_cfg)
2599177c336SPing-Ke Shih return;
2609177c336SPing-Ke Shih
2619177c336SPing-Ke Shih exhalbtc_scan_notify_wifi_only(wifionly_cfg, is_5g);
2629177c336SPing-Ke Shih }
2639177c336SPing-Ke Shih
rtl_btc_connect_notify(struct rtl_priv * rtlpriv,u8 action)264f1d2b4d3SLarry Finger void rtl_btc_connect_notify(struct rtl_priv *rtlpriv, u8 action)
265f1d2b4d3SLarry Finger {
26640d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
26740d9dd4fSPing-Ke Shih
26840d9dd4fSPing-Ke Shih if (!btcoexist)
26940d9dd4fSPing-Ke Shih return;
27040d9dd4fSPing-Ke Shih
27140d9dd4fSPing-Ke Shih exhalbtc_connect_notify(btcoexist, action);
272f1d2b4d3SLarry Finger }
273f1d2b4d3SLarry Finger
rtl_btc_mediastatus_notify(struct rtl_priv * rtlpriv,enum rt_media_status mstatus)274f1d2b4d3SLarry Finger void rtl_btc_mediastatus_notify(struct rtl_priv *rtlpriv,
275f1d2b4d3SLarry Finger enum rt_media_status mstatus)
276f1d2b4d3SLarry Finger {
27740d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
27840d9dd4fSPing-Ke Shih
27940d9dd4fSPing-Ke Shih if (!btcoexist)
28040d9dd4fSPing-Ke Shih return;
28140d9dd4fSPing-Ke Shih
28240d9dd4fSPing-Ke Shih exhalbtc_mediastatus_notify(btcoexist, mstatus);
283f1d2b4d3SLarry Finger }
284f1d2b4d3SLarry Finger
rtl_btc_periodical(struct rtl_priv * rtlpriv)285f1d2b4d3SLarry Finger void rtl_btc_periodical(struct rtl_priv *rtlpriv)
286f1d2b4d3SLarry Finger {
28740d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
28840d9dd4fSPing-Ke Shih
28940d9dd4fSPing-Ke Shih if (!btcoexist)
29040d9dd4fSPing-Ke Shih return;
29140d9dd4fSPing-Ke Shih
292f1d2b4d3SLarry Finger /*rtl_bt_dm_monitor();*/
29340d9dd4fSPing-Ke Shih exhalbtc_periodical(btcoexist);
294f1d2b4d3SLarry Finger }
295f1d2b4d3SLarry Finger
rtl_btc_halt_notify(struct rtl_priv * rtlpriv)29640d9dd4fSPing-Ke Shih void rtl_btc_halt_notify(struct rtl_priv *rtlpriv)
297f1d2b4d3SLarry Finger {
29840d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
29940d9dd4fSPing-Ke Shih
30040d9dd4fSPing-Ke Shih if (!btcoexist)
30140d9dd4fSPing-Ke Shih return;
302c42ea613SYan-Hsuan Chuang
303c42ea613SYan-Hsuan Chuang exhalbtc_halt_notify(btcoexist);
304f1d2b4d3SLarry Finger }
305f1d2b4d3SLarry Finger
rtl_btc_btinfo_notify(struct rtl_priv * rtlpriv,u8 * tmp_buf,u8 length)306f1d2b4d3SLarry Finger void rtl_btc_btinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
307f1d2b4d3SLarry Finger {
30840d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
30940d9dd4fSPing-Ke Shih
31040d9dd4fSPing-Ke Shih if (!btcoexist)
31140d9dd4fSPing-Ke Shih return;
31240d9dd4fSPing-Ke Shih
31340d9dd4fSPing-Ke Shih exhalbtc_bt_info_notify(btcoexist, tmp_buf, length);
314f1d2b4d3SLarry Finger }
315f1d2b4d3SLarry Finger
rtl_btc_btmpinfo_notify(struct rtl_priv * rtlpriv,u8 * tmp_buf,u8 length)3166aad6075SPing-Ke Shih void rtl_btc_btmpinfo_notify(struct rtl_priv *rtlpriv, u8 *tmp_buf, u8 length)
3176aad6075SPing-Ke Shih {
31840d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
319d477a485SYueHaibing u8 extid, seq;
3206aad6075SPing-Ke Shih u16 bt_real_fw_ver;
3216aad6075SPing-Ke Shih u8 bt_fw_ver;
322b2283dadSPing-Ke Shih u8 *data;
3236aad6075SPing-Ke Shih
32440d9dd4fSPing-Ke Shih if (!btcoexist)
32540d9dd4fSPing-Ke Shih return;
32640d9dd4fSPing-Ke Shih
3276aad6075SPing-Ke Shih if ((length < 4) || (!tmp_buf))
3286aad6075SPing-Ke Shih return;
3296aad6075SPing-Ke Shih
3306aad6075SPing-Ke Shih extid = tmp_buf[0];
3316aad6075SPing-Ke Shih /* not response from BT FW then exit*/
3326aad6075SPing-Ke Shih if (extid != 1) /* C2H_TRIG_BY_BT_FW = 1 */
3336aad6075SPing-Ke Shih return;
3346aad6075SPing-Ke Shih
3356aad6075SPing-Ke Shih seq = tmp_buf[2] >> 4;
336b2283dadSPing-Ke Shih data = &tmp_buf[3];
3376aad6075SPing-Ke Shih
3386aad6075SPing-Ke Shih /* BT Firmware version response */
339b2283dadSPing-Ke Shih switch (seq) {
340b2283dadSPing-Ke Shih case BT_SEQ_GET_BT_VERSION:
3416aad6075SPing-Ke Shih bt_real_fw_ver = tmp_buf[3] | (tmp_buf[4] << 8);
3426aad6075SPing-Ke Shih bt_fw_ver = tmp_buf[5];
3436aad6075SPing-Ke Shih
34440d9dd4fSPing-Ke Shih btcoexist->bt_info.bt_real_fw_ver = bt_real_fw_ver;
34540d9dd4fSPing-Ke Shih btcoexist->bt_info.bt_fw_ver = bt_fw_ver;
346b2283dadSPing-Ke Shih break;
347b2283dadSPing-Ke Shih case BT_SEQ_GET_AFH_MAP_L:
348b2283dadSPing-Ke Shih btcoexist->bt_info.afh_map_l = le32_to_cpu(*(__le32 *)data);
349b2283dadSPing-Ke Shih break;
350b2283dadSPing-Ke Shih case BT_SEQ_GET_AFH_MAP_M:
351b2283dadSPing-Ke Shih btcoexist->bt_info.afh_map_m = le32_to_cpu(*(__le32 *)data);
352b2283dadSPing-Ke Shih break;
353b2283dadSPing-Ke Shih case BT_SEQ_GET_AFH_MAP_H:
354b2283dadSPing-Ke Shih btcoexist->bt_info.afh_map_h = le16_to_cpu(*(__le16 *)data);
355b2283dadSPing-Ke Shih break;
356b2283dadSPing-Ke Shih case BT_SEQ_GET_BT_COEX_SUPPORTED_FEATURE:
357b2283dadSPing-Ke Shih btcoexist->bt_info.bt_supported_feature = tmp_buf[3] |
358b2283dadSPing-Ke Shih (tmp_buf[4] << 8);
359b2283dadSPing-Ke Shih break;
360b2283dadSPing-Ke Shih case BT_SEQ_GET_BT_COEX_SUPPORTED_VERSION:
361b2283dadSPing-Ke Shih btcoexist->bt_info.bt_supported_version = tmp_buf[3] |
362b2283dadSPing-Ke Shih (tmp_buf[4] << 8);
363b2283dadSPing-Ke Shih break;
364b2283dadSPing-Ke Shih case BT_SEQ_GET_BT_ANT_DET_VAL:
365b2283dadSPing-Ke Shih btcoexist->bt_info.bt_ant_det_val = tmp_buf[3];
366b2283dadSPing-Ke Shih break;
367b2283dadSPing-Ke Shih case BT_SEQ_GET_BT_BLE_SCAN_PARA:
368b2283dadSPing-Ke Shih btcoexist->bt_info.bt_ble_scan_para = tmp_buf[3] |
369b2283dadSPing-Ke Shih (tmp_buf[4] << 8) |
370b2283dadSPing-Ke Shih (tmp_buf[5] << 16) |
371b2283dadSPing-Ke Shih (tmp_buf[6] << 24);
372b2283dadSPing-Ke Shih break;
373b2283dadSPing-Ke Shih case BT_SEQ_GET_BT_BLE_SCAN_TYPE:
374b2283dadSPing-Ke Shih btcoexist->bt_info.bt_ble_scan_type = tmp_buf[3];
375b2283dadSPing-Ke Shih break;
376b2283dadSPing-Ke Shih case BT_SEQ_GET_BT_DEVICE_INFO:
377b2283dadSPing-Ke Shih btcoexist->bt_info.bt_device_info =
378b2283dadSPing-Ke Shih le32_to_cpu(*(__le32 *)data);
379b2283dadSPing-Ke Shih break;
380b2283dadSPing-Ke Shih case BT_OP_GET_BT_FORBIDDEN_SLOT_VAL:
381b2283dadSPing-Ke Shih btcoexist->bt_info.bt_forb_slot_val =
382b2283dadSPing-Ke Shih le32_to_cpu(*(__le32 *)data);
383b2283dadSPing-Ke Shih break;
3846aad6075SPing-Ke Shih }
385b2283dadSPing-Ke Shih
386*c8159c3fSLarry Finger rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
387b2283dadSPing-Ke Shih "btmpinfo complete req_num=%d\n", seq);
388b2283dadSPing-Ke Shih
389b2283dadSPing-Ke Shih complete(&btcoexist->bt_mp_comp);
3906aad6075SPing-Ke Shih }
3916aad6075SPing-Ke Shih
rtl_btc_is_limited_dig(struct rtl_priv * rtlpriv)392f1d2b4d3SLarry Finger bool rtl_btc_is_limited_dig(struct rtl_priv *rtlpriv)
393f1d2b4d3SLarry Finger {
39440d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
39540d9dd4fSPing-Ke Shih
39640d9dd4fSPing-Ke Shih if (!btcoexist)
39740d9dd4fSPing-Ke Shih return false;
39840d9dd4fSPing-Ke Shih
39940d9dd4fSPing-Ke Shih return btcoexist->bt_info.limited_dig;
400f1d2b4d3SLarry Finger }
401f1d2b4d3SLarry Finger
rtl_btc_is_disable_edca_turbo(struct rtl_priv * rtlpriv)402f1d2b4d3SLarry Finger bool rtl_btc_is_disable_edca_turbo(struct rtl_priv *rtlpriv)
403f1d2b4d3SLarry Finger {
404f1d2b4d3SLarry Finger bool bt_change_edca = false;
405f1d2b4d3SLarry Finger u32 cur_edca_val;
406f1d2b4d3SLarry Finger u32 edca_bt_hs_uplink = 0x5ea42b, edca_bt_hs_downlink = 0x5ea42b;
407f1d2b4d3SLarry Finger u32 edca_hs;
408f1d2b4d3SLarry Finger u32 edca_addr = 0x504;
409f1d2b4d3SLarry Finger
410f1d2b4d3SLarry Finger cur_edca_val = rtl_read_dword(rtlpriv, edca_addr);
411f1d2b4d3SLarry Finger if (halbtc_is_wifi_uplink(rtlpriv)) {
412f1d2b4d3SLarry Finger if (cur_edca_val != edca_bt_hs_uplink) {
413f1d2b4d3SLarry Finger edca_hs = edca_bt_hs_uplink;
414f1d2b4d3SLarry Finger bt_change_edca = true;
415f1d2b4d3SLarry Finger }
416f1d2b4d3SLarry Finger } else {
417f1d2b4d3SLarry Finger if (cur_edca_val != edca_bt_hs_downlink) {
418f1d2b4d3SLarry Finger edca_hs = edca_bt_hs_downlink;
419f1d2b4d3SLarry Finger bt_change_edca = true;
420f1d2b4d3SLarry Finger }
421f1d2b4d3SLarry Finger }
422f1d2b4d3SLarry Finger
423f1d2b4d3SLarry Finger if (bt_change_edca)
424f1d2b4d3SLarry Finger rtl_write_dword(rtlpriv, edca_addr, edca_hs);
425f1d2b4d3SLarry Finger
426f1d2b4d3SLarry Finger return true;
427f1d2b4d3SLarry Finger }
428f1d2b4d3SLarry Finger
rtl_btc_is_bt_disabled(struct rtl_priv * rtlpriv)429f1d2b4d3SLarry Finger bool rtl_btc_is_bt_disabled(struct rtl_priv *rtlpriv)
430f1d2b4d3SLarry Finger {
43140d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
43240d9dd4fSPing-Ke Shih
43340d9dd4fSPing-Ke Shih if (!btcoexist)
43440d9dd4fSPing-Ke Shih return true;
43540d9dd4fSPing-Ke Shih
436f1d2b4d3SLarry Finger /* It seems 'bt_disabled' is never be initialized or set. */
43740d9dd4fSPing-Ke Shih if (btcoexist->bt_info.bt_disabled)
438f1d2b4d3SLarry Finger return true;
439f1d2b4d3SLarry Finger else
440f1d2b4d3SLarry Finger return false;
441f1d2b4d3SLarry Finger }
442f1d2b4d3SLarry Finger
rtl_btc_special_packet_notify(struct rtl_priv * rtlpriv,u8 pkt_type)443f1d2b4d3SLarry Finger void rtl_btc_special_packet_notify(struct rtl_priv *rtlpriv, u8 pkt_type)
444f1d2b4d3SLarry Finger {
44540d9dd4fSPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
44640d9dd4fSPing-Ke Shih
44740d9dd4fSPing-Ke Shih if (!btcoexist)
44840d9dd4fSPing-Ke Shih return;
44940d9dd4fSPing-Ke Shih
45040d9dd4fSPing-Ke Shih return exhalbtc_special_packet_notify(btcoexist, pkt_type);
451f1d2b4d3SLarry Finger }
452f1d2b4d3SLarry Finger
rtl_btc_switch_band_notify(struct rtl_priv * rtlpriv,u8 band_type,bool scanning)45317bf8510SPing-Ke Shih void rtl_btc_switch_band_notify(struct rtl_priv *rtlpriv, u8 band_type,
45417bf8510SPing-Ke Shih bool scanning)
45517bf8510SPing-Ke Shih {
45617bf8510SPing-Ke Shih struct btc_coexist *btcoexist = rtl_btc_coexist(rtlpriv);
45717bf8510SPing-Ke Shih u8 type = BTC_NOT_SWITCH;
45817bf8510SPing-Ke Shih
45917bf8510SPing-Ke Shih if (!btcoexist)
46017bf8510SPing-Ke Shih return;
46117bf8510SPing-Ke Shih
46217bf8510SPing-Ke Shih switch (band_type) {
46317bf8510SPing-Ke Shih case BAND_ON_2_4G:
46417bf8510SPing-Ke Shih if (scanning)
46517bf8510SPing-Ke Shih type = BTC_SWITCH_TO_24G;
46617bf8510SPing-Ke Shih else
46717bf8510SPing-Ke Shih type = BTC_SWITCH_TO_24G_NOFORSCAN;
46817bf8510SPing-Ke Shih break;
46917bf8510SPing-Ke Shih
47017bf8510SPing-Ke Shih case BAND_ON_5G:
47117bf8510SPing-Ke Shih type = BTC_SWITCH_TO_5G;
47217bf8510SPing-Ke Shih break;
47317bf8510SPing-Ke Shih }
47417bf8510SPing-Ke Shih
47517bf8510SPing-Ke Shih if (type != BTC_NOT_SWITCH)
47617bf8510SPing-Ke Shih exhalbtc_switch_band_notify(btcoexist, type);
47717bf8510SPing-Ke Shih }
47817bf8510SPing-Ke Shih
rtl_btc_switch_band_notify_wifionly(struct rtl_priv * rtlpriv,u8 band_type,bool scanning)4799177c336SPing-Ke Shih void rtl_btc_switch_band_notify_wifionly(struct rtl_priv *rtlpriv, u8 band_type,
4809177c336SPing-Ke Shih bool scanning)
4819177c336SPing-Ke Shih {
4829177c336SPing-Ke Shih struct wifi_only_cfg *wifionly_cfg = rtl_btc_wifi_only(rtlpriv);
4839177c336SPing-Ke Shih u8 is_5g = (band_type == BAND_ON_5G);
4849177c336SPing-Ke Shih
4859177c336SPing-Ke Shih if (!wifionly_cfg)
4869177c336SPing-Ke Shih return;
4879177c336SPing-Ke Shih
4889177c336SPing-Ke Shih exhalbtc_switch_band_notify_wifi_only(wifionly_cfg, is_5g);
4899177c336SPing-Ke Shih }
4909177c336SPing-Ke Shih
rtl_btc_get_ops_pointer(void)491f1d2b4d3SLarry Finger struct rtl_btc_ops *rtl_btc_get_ops_pointer(void)
492f1d2b4d3SLarry Finger {
493f1d2b4d3SLarry Finger return &rtl_btc_operation;
494f1d2b4d3SLarry Finger }
495f1d2b4d3SLarry Finger EXPORT_SYMBOL(rtl_btc_get_ops_pointer);
496f1d2b4d3SLarry Finger
497f1d2b4d3SLarry Finger
mgnt_link_status_query(struct ieee80211_hw * hw)498f1d2b4d3SLarry Finger enum rt_media_status mgnt_link_status_query(struct ieee80211_hw *hw)
499f1d2b4d3SLarry Finger {
500f1d2b4d3SLarry Finger struct rtl_priv *rtlpriv = rtl_priv(hw);
501f1d2b4d3SLarry Finger struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
502f1d2b4d3SLarry Finger enum rt_media_status m_status = RT_MEDIA_DISCONNECT;
503f1d2b4d3SLarry Finger
504f1d2b4d3SLarry Finger u8 bibss = (mac->opmode == NL80211_IFTYPE_ADHOC) ? 1 : 0;
505f1d2b4d3SLarry Finger
506f1d2b4d3SLarry Finger if (bibss || rtlpriv->mac80211.link_state >= MAC80211_LINKED)
507f1d2b4d3SLarry Finger m_status = RT_MEDIA_CONNECT;
508f1d2b4d3SLarry Finger
509f1d2b4d3SLarry Finger return m_status;
510f1d2b4d3SLarry Finger }
511f1d2b4d3SLarry Finger
rtl_get_hwpg_bt_exist(struct rtl_priv * rtlpriv)512f1d2b4d3SLarry Finger u8 rtl_get_hwpg_bt_exist(struct rtl_priv *rtlpriv)
513f1d2b4d3SLarry Finger {
514f1d2b4d3SLarry Finger return rtlpriv->btcoexist.btc_info.btcoexist;
515f1d2b4d3SLarry Finger }
516f1d2b4d3SLarry Finger
517f1d2b4d3SLarry Finger MODULE_AUTHOR("Page He <page_he@realsil.com.cn>");
518f1d2b4d3SLarry Finger MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
519f1d2b4d3SLarry Finger MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
520f1d2b4d3SLarry Finger MODULE_LICENSE("GPL");
521f1d2b4d3SLarry Finger MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
522f1d2b4d3SLarry Finger
rtl_btcoexist_module_init(void)523f1d2b4d3SLarry Finger static int __init rtl_btcoexist_module_init(void)
524f1d2b4d3SLarry Finger {
525f1d2b4d3SLarry Finger return 0;
526f1d2b4d3SLarry Finger }
527f1d2b4d3SLarry Finger
rtl_btcoexist_module_exit(void)528f1d2b4d3SLarry Finger static void __exit rtl_btcoexist_module_exit(void)
529f1d2b4d3SLarry Finger {
530f1d2b4d3SLarry Finger return;
531f1d2b4d3SLarry Finger }
532f1d2b4d3SLarry Finger
533f1d2b4d3SLarry Finger module_init(rtl_btcoexist_module_init);
534f1d2b4d3SLarry Finger module_exit(rtl_btcoexist_module_exit);
535