root/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hal_bt_coexist.c
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009-2012  Realtek Corporation.*/

#include "hal_bt_coexist.h"
#include "../pci.h"
#include "dm.h"
#include "fw.h"
#include "phy.h"
#include "reg.h"
#include "hal_btc.h"

static bool bt_operation_on;

void rtl8723e_dm_bt_reject_ap_aggregated_packet(struct ieee80211_hw *hw,
                                                bool b_reject)
{
}

void _rtl8723_dm_bt_check_wifi_state(struct ieee80211_hw *hw)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_phy *rtlphy = &(rtlpriv->phy);

        if (rtlpriv->link_info.busytraffic) {
                rtlpriv->btcoexist.cstate &=
                        ~BT_COEX_STATE_WIFI_IDLE;

                if (rtlpriv->link_info.tx_busy_traffic)
                        rtlpriv->btcoexist.cstate |=
                                BT_COEX_STATE_WIFI_UPLINK;
                else
                        rtlpriv->btcoexist.cstate &=
                                ~BT_COEX_STATE_WIFI_UPLINK;

                if (rtlpriv->link_info.rx_busy_traffic)
                        rtlpriv->btcoexist.cstate |=
                                BT_COEX_STATE_WIFI_DOWNLINK;
                else
                        rtlpriv->btcoexist.cstate &=
                                ~BT_COEX_STATE_WIFI_DOWNLINK;
        } else {
                rtlpriv->btcoexist.cstate |= BT_COEX_STATE_WIFI_IDLE;
                rtlpriv->btcoexist.cstate &=
                        ~BT_COEX_STATE_WIFI_UPLINK;
                rtlpriv->btcoexist.cstate &=
                        ~BT_COEX_STATE_WIFI_DOWNLINK;
        }

        if (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
            rtlpriv->mac80211.mode == WIRELESS_MODE_B) {
                rtlpriv->btcoexist.cstate |=
                        BT_COEX_STATE_WIFI_LEGACY;
                rtlpriv->btcoexist.cstate &=
                        ~BT_COEX_STATE_WIFI_HT20;
                rtlpriv->btcoexist.cstate &=
                        ~BT_COEX_STATE_WIFI_HT40;
        } else {
                rtlpriv->btcoexist.cstate &=
                        ~BT_COEX_STATE_WIFI_LEGACY;
                if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
                        rtlpriv->btcoexist.cstate |=
                                BT_COEX_STATE_WIFI_HT40;
                        rtlpriv->btcoexist.cstate &=
                                ~BT_COEX_STATE_WIFI_HT20;
                } else {
                        rtlpriv->btcoexist.cstate |=
                                BT_COEX_STATE_WIFI_HT20;
                        rtlpriv->btcoexist.cstate &=
                                ~BT_COEX_STATE_WIFI_HT40;
                }
        }

        if (bt_operation_on)
                rtlpriv->btcoexist.cstate |= BT_COEX_STATE_BT30;
        else
                rtlpriv->btcoexist.cstate &= ~BT_COEX_STATE_BT30;
}

u8 rtl8723e_dm_bt_check_coex_rssi_state1(struct ieee80211_hw *hw,
                                         u8 level_num, u8 rssi_thresh,
                                         u8 rssi_thresh1)

{
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        long undecoratedsmoothed_pwdb;
        u8 bt_rssi_state = 0;

        undecoratedsmoothed_pwdb = rtl8723e_dm_bt_get_rx_ss(hw);

        if (level_num == 2) {
                rtlpriv->btcoexist.cstate &=
                        ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;

                if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
                     BT_RSSI_STATE_LOW) ||
                    (rtlpriv->btcoexist.bt_pre_rssi_state ==
                     BT_RSSI_STATE_STAY_LOW)) {
                        if (undecoratedsmoothed_pwdb >=
                            (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
                                bt_rssi_state = BT_RSSI_STATE_HIGH;
                                rtlpriv->btcoexist.cstate |=
                                        BT_COEX_STATE_WIFI_RSSI_1_HIGH;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state switch to High\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state stay at Low\n");
                        }
                } else {
                        if (undecoratedsmoothed_pwdb < rssi_thresh) {
                                bt_rssi_state = BT_RSSI_STATE_LOW;
                                rtlpriv->btcoexist.cstate |=
                                        BT_COEX_STATE_WIFI_RSSI_1_LOW;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state switch to Low\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state stay at High\n");
                        }
                }
        } else if (level_num == 3) {
                if (rssi_thresh > rssi_thresh1) {
                        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                "[DM][BT], RSSI_1 thresh error!!\n");
                        return rtlpriv->btcoexist.bt_pre_rssi_state;
                }

                if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
                     BT_RSSI_STATE_LOW) ||
                    (rtlpriv->btcoexist.bt_pre_rssi_state ==
                     BT_RSSI_STATE_STAY_LOW)) {
                        if (undecoratedsmoothed_pwdb >=
                            (rssi_thresh+BT_FW_COEX_THRESH_TOL)) {
                                bt_rssi_state = BT_RSSI_STATE_MEDIUM;
                                rtlpriv->btcoexist.cstate |=
                                        BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state switch to Medium\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state stay at Low\n");
                        }
                } else if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
                            BT_RSSI_STATE_MEDIUM) ||
                           (rtlpriv->btcoexist.bt_pre_rssi_state ==
                            BT_RSSI_STATE_STAY_MEDIUM)) {
                        if (undecoratedsmoothed_pwdb >=
                            (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) {
                                bt_rssi_state = BT_RSSI_STATE_HIGH;
                                rtlpriv->btcoexist.cstate |=
                                        BT_COEX_STATE_WIFI_RSSI_1_HIGH;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state switch to High\n");
                        } else if (undecoratedsmoothed_pwdb < rssi_thresh) {
                                bt_rssi_state = BT_RSSI_STATE_LOW;
                                rtlpriv->btcoexist.cstate |=
                                        BT_COEX_STATE_WIFI_RSSI_1_LOW;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state switch to Low\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state stay at Medium\n");
                        }
                } else {
                        if (undecoratedsmoothed_pwdb < rssi_thresh1) {
                                bt_rssi_state = BT_RSSI_STATE_MEDIUM;
                                rtlpriv->btcoexist.cstate |=
                                        BT_COEX_STATE_WIFI_RSSI_1_MEDIUM;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_HIGH;
                                rtlpriv->btcoexist.cstate &=
                                        ~BT_COEX_STATE_WIFI_RSSI_1_LOW;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state switch to Medium\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI_1 state stay at High\n");
                        }
                }
        }
        rtlpriv->btcoexist.bt_pre_rssi_state1 = bt_rssi_state;

        return bt_rssi_state;
}

u8 rtl8723e_dm_bt_check_coex_rssi_state(struct ieee80211_hw *hw,
                                        u8 level_num,
                                        u8 rssi_thresh,
                                        u8 rssi_thresh1)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        long undecoratedsmoothed_pwdb = 0;
        u8 bt_rssi_state = 0;

        undecoratedsmoothed_pwdb = rtl8723e_dm_bt_get_rx_ss(hw);

        if (level_num == 2) {
                rtlpriv->btcoexist.cstate &=
                        ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;

                if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
                     BT_RSSI_STATE_LOW) ||
                    (rtlpriv->btcoexist.bt_pre_rssi_state ==
                     BT_RSSI_STATE_STAY_LOW)) {
                        if (undecoratedsmoothed_pwdb >=
                            (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
                                bt_rssi_state = BT_RSSI_STATE_HIGH;
                                rtlpriv->btcoexist.cstate
                                        |= BT_COEX_STATE_WIFI_RSSI_HIGH;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state switch to High\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state stay at Low\n");
                        }
                } else {
                        if (undecoratedsmoothed_pwdb < rssi_thresh) {
                                bt_rssi_state = BT_RSSI_STATE_LOW;
                                rtlpriv->btcoexist.cstate
                                        |= BT_COEX_STATE_WIFI_RSSI_LOW;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state switch to Low\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state stay at High\n");
                        }
                }
        } else if (level_num == 3) {
                if (rssi_thresh > rssi_thresh1) {
                        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                "[DM][BT], RSSI thresh error!!\n");
                        return rtlpriv->btcoexist.bt_pre_rssi_state;
                }
                if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
                     BT_RSSI_STATE_LOW) ||
                    (rtlpriv->btcoexist.bt_pre_rssi_state ==
                     BT_RSSI_STATE_STAY_LOW)) {
                        if (undecoratedsmoothed_pwdb >=
                            (rssi_thresh + BT_FW_COEX_THRESH_TOL)) {
                                bt_rssi_state = BT_RSSI_STATE_MEDIUM;
                                rtlpriv->btcoexist.cstate
                                        |= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state switch to Medium\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_LOW;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state stay at Low\n");
                        }
                } else if ((rtlpriv->btcoexist.bt_pre_rssi_state ==
                                BT_RSSI_STATE_MEDIUM) ||
                        (rtlpriv->btcoexist.bt_pre_rssi_state ==
                                BT_RSSI_STATE_STAY_MEDIUM)) {
                        if (undecoratedsmoothed_pwdb >=
                            (rssi_thresh1 + BT_FW_COEX_THRESH_TOL)) {
                                bt_rssi_state = BT_RSSI_STATE_HIGH;
                                rtlpriv->btcoexist.cstate
                                        |= BT_COEX_STATE_WIFI_RSSI_HIGH;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state switch to High\n");
                        } else if (undecoratedsmoothed_pwdb < rssi_thresh) {
                                bt_rssi_state = BT_RSSI_STATE_LOW;
                                rtlpriv->btcoexist.cstate
                                        |= BT_COEX_STATE_WIFI_RSSI_LOW;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_MEDIUM;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state switch to Low\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_MEDIUM;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state stay at Medium\n");
                        }
                } else {
                        if (undecoratedsmoothed_pwdb < rssi_thresh1) {
                                bt_rssi_state = BT_RSSI_STATE_MEDIUM;
                                rtlpriv->btcoexist.cstate
                                        |= BT_COEX_STATE_WIFI_RSSI_MEDIUM;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_HIGH;
                                rtlpriv->btcoexist.cstate
                                        &= ~BT_COEX_STATE_WIFI_RSSI_LOW;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state switch to Medium\n");
                        } else {
                                bt_rssi_state = BT_RSSI_STATE_STAY_HIGH;
                                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                                        "[DM][BT], RSSI state stay at High\n");
                        }
                }
        }
        rtlpriv->btcoexist.bt_pre_rssi_state = bt_rssi_state;
        return bt_rssi_state;
}

long rtl8723e_dm_bt_get_rx_ss(struct ieee80211_hw *hw)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        long undecoratedsmoothed_pwdb = 0;

        if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
                undecoratedsmoothed_pwdb =
                        GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
        } else {
                undecoratedsmoothed_pwdb
                        = rtlpriv->dm.entry_min_undec_sm_pwdb;
        }
        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                "%s = %ld\n", __func__,
                undecoratedsmoothed_pwdb);

        return undecoratedsmoothed_pwdb;
}

void rtl8723e_dm_bt_balance(struct ieee80211_hw *hw,
                            bool balance_on, u8 ms0, u8 ms1)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        u8 h2c_parameter[3] = {0};

        if (balance_on) {
                h2c_parameter[2] = 1;
                h2c_parameter[1] = ms1;
                h2c_parameter[0] = ms0;
                rtlpriv->btcoexist.fw_coexist_all_off = false;
        } else {
                h2c_parameter[2] = 0;
                h2c_parameter[1] = 0;
                h2c_parameter[0] = 0;
        }
        rtlpriv->btcoexist.balance_on = balance_on;

        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                "[DM][BT], Balance=[%s:%dms:%dms], write 0xc=0x%x\n",
                balance_on ? "ON" : "OFF", ms0, ms1, h2c_parameter[0] << 16 |
                h2c_parameter[1] << 8 | h2c_parameter[2]);

        rtl8723e_fill_h2c_cmd(hw, 0xc, 3, h2c_parameter);
}


void rtl8723e_dm_bt_agc_table(struct ieee80211_hw *hw, u8 type)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);

        if (type == BT_AGCTABLE_OFF) {
                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                        "[BT]AGCTable Off!\n");
                rtl_write_dword(rtlpriv, 0xc78, 0x641c0001);
                rtl_write_dword(rtlpriv, 0xc78, 0x631d0001);
                rtl_write_dword(rtlpriv, 0xc78, 0x621e0001);
                rtl_write_dword(rtlpriv, 0xc78, 0x611f0001);
                rtl_write_dword(rtlpriv, 0xc78, 0x60200001);

                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_AGC_HP, 0xfffff, 0x32000);
                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_AGC_HP, 0xfffff, 0x71000);
                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_AGC_HP, 0xfffff, 0xb0000);
                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_AGC_HP, 0xfffff, 0xfc000);
                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_G1, 0xfffff, 0x30355);
        } else if (type == BT_AGCTABLE_ON) {
                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                        "[BT]AGCTable On!\n");
                rtl_write_dword(rtlpriv, 0xc78, 0x4e1c0001);
                rtl_write_dword(rtlpriv, 0xc78, 0x4d1d0001);
                rtl_write_dword(rtlpriv, 0xc78, 0x4c1e0001);
                rtl_write_dword(rtlpriv, 0xc78, 0x4b1f0001);
                rtl_write_dword(rtlpriv, 0xc78, 0x4a200001);

                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_AGC_HP, 0xfffff, 0xdc000);
                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_AGC_HP, 0xfffff, 0x90000);
                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_AGC_HP, 0xfffff, 0x51000);
                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_AGC_HP, 0xfffff, 0x12000);
                rtl8723e_phy_set_rf_reg(hw, RF90_PATH_A,
                                        RF_RX_G1, 0xfffff, 0x00355);

                rtlpriv->btcoexist.sw_coexist_all_off = false;
        }
}

void rtl8723e_dm_bt_bb_back_off_level(struct ieee80211_hw *hw, u8 type)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);

        if (type == BT_BB_BACKOFF_OFF) {
                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                        "[BT]BBBackOffLevel Off!\n");
                rtl_write_dword(rtlpriv, 0xc04, 0x3a05611);
        } else if (type == BT_BB_BACKOFF_ON) {
                rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                        "[BT]BBBackOffLevel On!\n");
                rtl_write_dword(rtlpriv, 0xc04, 0x3a07611);
                rtlpriv->btcoexist.sw_coexist_all_off = false;
        }
}

void rtl8723e_dm_bt_fw_coex_all_off(struct ieee80211_hw *hw)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                "rtl8723e_dm_bt_fw_coex_all_off()\n");

        if (rtlpriv->btcoexist.fw_coexist_all_off)
                return;

        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                "rtl8723e_dm_bt_fw_coex_all_off(), real Do\n");
        rtl8723e_dm_bt_fw_coex_all_off_8723a(hw);
        rtlpriv->btcoexist.fw_coexist_all_off = true;
}

void rtl8723e_dm_bt_sw_coex_all_off(struct ieee80211_hw *hw)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);

        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                "%s\n", __func__);

        if (rtlpriv->btcoexist.sw_coexist_all_off)
                return;

        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                "%s, real Do\n", __func__);
        rtl8723e_dm_bt_sw_coex_all_off_8723a(hw);
        rtlpriv->btcoexist.sw_coexist_all_off = true;
}

void rtl8723e_dm_bt_hw_coex_all_off(struct ieee80211_hw *hw)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);

        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                "%s\n", __func__);

        if (rtlpriv->btcoexist.hw_coexist_all_off)
                return;
        rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_TRACE,
                "%s, real Do\n", __func__);

        rtl8723e_dm_bt_hw_coex_all_off_8723a(hw);

        rtlpriv->btcoexist.hw_coexist_all_off = true;
}

void rtl8723e_btdm_coex_all_off(struct ieee80211_hw *hw)
{
        rtl8723e_dm_bt_fw_coex_all_off(hw);
        rtl8723e_dm_bt_sw_coex_all_off(hw);
        rtl8723e_dm_bt_hw_coex_all_off(hw);
}

bool rtl8723e_dm_bt_is_coexist_state_changed(struct ieee80211_hw *hw)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);

        if ((rtlpriv->btcoexist.previous_state == rtlpriv->btcoexist.cstate) &&
            (rtlpriv->btcoexist.previous_state_h ==
             rtlpriv->btcoexist.cstate_h))
                return false;
        return true;
}

bool rtl8723e_dm_bt_is_wifi_up_link(struct ieee80211_hw *hw)
{
        struct rtl_priv *rtlpriv = rtl_priv(hw);

        if (rtlpriv->link_info.tx_busy_traffic)
                return true;
        return false;
}