/******************************************************************************
|
*
|
* Copyright(c) 2019 Realtek Corporation.
|
*
|
* This program is free software; you can redistribute it and/or modify it
|
* under the terms of version 2 of the GNU General Public License as
|
* published by the Free Software Foundation.
|
*
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
* more details.
|
*
|
*****************************************************************************/
|
#define _HAL_BTC_ACTION_C_
|
#include "../hal_headers_le.h"
|
#include "hal_btc.h"
|
#include "halbtc_fw.h"
|
#include "halbtc_fwdef.h"
|
#include "halbtc_action.h"
|
#include "halbtc_def.h"
|
|
#ifdef CONFIG_BTCOEX
|
|
#define _set_cx_ctrl(btc, val) rtw_hal_mac_set_coex_ctrl(btc->hal, val)
|
|
/* tdma policy template */
|
struct fbtc_tdma t_def[] = {
|
{ CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, /*CXTD_OFF*/
|
{ CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0}, /*CXTD_B2*/
|
{ CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0}, /*CXTD_OFF_EXT*/
|
{ CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, /* CXTD_FIX */
|
{ CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, /* CXTD_PFIX */
|
{ CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, /* CXTD_AUTO */
|
{ CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}, /* CXTD_PAUTO */
|
{CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0}, /* CXTD_AUTO2 */
|
{CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0} /* CXTD_PAUTO2 */
|
};
|
|
/* slot policy template */
|
struct fbtc_slot s_def[] = {
|
{100, 0x55555555, SLOT_MIX}, /* CXST_OFF */
|
{ 5, 0xea5a5a5a, SLOT_ISO}, /* CXST_B2W */
|
{ 70, 0xea5a5a5a, SLOT_ISO}, /* CXST_W1 */
|
{ 15, 0xea5a5a5a, SLOT_ISO}, /* CXST_W2 */
|
{ 15, 0xea5a5a5a, SLOT_ISO}, /* CXST_W2B */
|
{250, 0xe5555555, SLOT_MIX}, /* CXST_B1 */
|
{ 7, 0xea5a5a5a, SLOT_MIX}, /* CXST_B2 */
|
{ 5, 0xe5555555, SLOT_MIX}, /* CXST_B3 */
|
{ 50, 0xe5555555, SLOT_MIX}, /* CXST_B4 */
|
{ 20, 0xea5a5a5a, SLOT_ISO}, /* CXST_LK */
|
{400, 0x55555555, SLOT_MIX}, /* CXST_BLK */
|
{ 0, 0xea5a5a5a, SLOT_MIX}, /* CXST_E2G */
|
{ 0, 0xffffffff, SLOT_MIX}, /* CXST_E5G */
|
{ 0, 0xe5555555, SLOT_MIX}, /* CXST_EBT */
|
{ 0, 0xaaaaaaaa, SLOT_ISO}, /* CXST_ENULL */
|
{250, 0xea5a5a5a, SLOT_MIX}, /* CXST_WLK */
|
{ 35, 0xfafafafa, SLOT_ISO}, /* CXST_W1FDD */
|
{250, 0xffffffff, SLOT_MIX} /* CXST_B1FDD */
|
};
|
|
const u32 cxtbl[] = {
|
0xffffffff, /* 0 */
|
0xaaaaaaaa, /* 1 */
|
0xe5555555, /* 2 */
|
0xee555555, /* 3 */
|
0xd5555555, /* 4 */
|
0x5a5a5a5a, /* 5 */
|
0x5a5a5aaa, /* 6 */
|
0xda5a5a5a, /* 7 */
|
0xea5a5a5a, /* 8 */
|
0x6a5a5aaa, /* 9 */
|
0x6a5a6a5a, /* 10 */
|
0x6a5a6aaa, /* 11 */
|
0x6afa5afa, /* 12 */
|
0xaaaa5aaa, /* 13 */
|
0xaaffffaa, /* 14 */
|
0xaa5555aa, /* 15 */
|
0xfafafafa, /* 16 */
|
0xffffddff, /* 17 */
|
0xdaffdaff, /* 18 */
|
0xfafadafa /* 19 */
|
};
|
|
void _set_bt_ignore_wlan_act(struct btc_t *btc, u8 enable)
|
{
|
u8 buf = 0;
|
|
PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): set bt %s wlan_act\n",
|
__func__, (enable? "ignore" : "do not ignore"));
|
|
buf = enable;
|
hal_btc_fw_set_bt(btc, SET_BT_IGNORE_WLAN_ACT, 1, &buf);
|
}
|
|
void _set_wl_tx_power(struct btc_t *btc, u32 level)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
|
if (wl->rf_para.tx_pwr_freerun == level)
|
return;
|
|
wl->rf_para.tx_pwr_freerun = level;
|
btc->dm.rf_trx_para.wl_tx_power = level;
|
|
PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): level = %d\n",
|
__func__, level);
|
|
btc->chip->ops->wl_tx_power(btc, level);
|
}
|
|
void _set_wl_rx_gain(struct btc_t *btc, u32 level)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
|
if (wl->rf_para.rx_gain_freerun == level)
|
return;
|
|
wl->rf_para.rx_gain_freerun = level;
|
btc->dm.rf_trx_para.wl_rx_gain = level;
|
|
PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): level = %d\n",
|
__func__, level);
|
|
btc->chip->ops->wl_rx_gain(btc, level);
|
}
|
|
void _set_bt_tx_power(struct btc_t *btc, u32 level)
|
{
|
struct btc_bt_info *bt = &btc->cx.bt;
|
u8 buf = 0;
|
|
if (bt->rf_para.tx_pwr_freerun == level)
|
return;
|
|
bt->rf_para.tx_pwr_freerun = level;
|
btc->dm.rf_trx_para.bt_tx_power = level;
|
|
PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): level = %d\n",
|
__func__, level);
|
|
buf = (0x100 - level) & bMASKB0;
|
hal_btc_fw_set_bt(btc, SET_BT_TX_PWR, 1, &buf);
|
}
|
|
void _set_bt_rx_gain(struct btc_t *btc, u32 level)
|
{
|
struct btc_bt_info *bt = &btc->cx.bt;
|
u8 buf = 0;
|
|
if (bt->rf_para.rx_gain_freerun == level ||
|
level > BTC_BT_RX_NORMAL_LVL)
|
return;
|
|
bt->rf_para.rx_gain_freerun = level;
|
btc->dm.rf_trx_para.bt_rx_gain = level;
|
|
PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): level = %d\n",
|
__func__, level);
|
|
buf = level & bMASKB0;
|
|
if (buf == BTC_BT_RX_NORMAL_LVL)
|
_write_scbd(btc, BTC_WSCB_RXGAIN, false);
|
else
|
_write_scbd(btc, BTC_WSCB_RXGAIN, true);
|
|
hal_btc_fw_set_bt(btc, SET_BT_LNA_CONSTRAIN, 1, &buf);
|
}
|
|
static void _set_rf_trx_para(struct btc_t *btc)
|
{
|
struct btc_dm *dm = &btc->dm;
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
struct btc_bt_link_info *b = &bt->link_info;
|
struct btc_rf_trx_para para;
|
u8 level_id = 0;
|
u32 wl_stb_chg = 0;
|
|
if (!dm->freerun) {
|
dm->trx_para_level = 0;
|
|
#if 1
|
/* fix LNA2 = level-5 for BT ACI issue at BTG */
|
if (btc->hal->chip_id == CHIP_WIFI6_8852A &&
|
btc->dm.wl_btg_rx && b->profile_cnt.now != 0)
|
dm->trx_para_level = 1;
|
#endif
|
}
|
|
level_id = (u8)dm->trx_para_level;
|
|
if (level_id >= btc->chip->rf_para_dlink_num ||
|
level_id >= btc->chip->rf_para_ulink_num) {
|
PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): invalid level_id: %d\n",
|
__func__, level_id);
|
return;
|
}
|
|
if (wl->status.map.traffic_dir & BIT(TRAFFIC_UL))
|
para = btc->chip->rf_para_ulink[level_id];
|
else
|
para = btc->chip->rf_para_dlink[level_id];
|
|
_set_wl_tx_power(btc, para.wl_tx_power);
|
_set_wl_rx_gain(btc, para.wl_rx_gain);
|
_set_bt_tx_power(btc, para.bt_tx_power);
|
_set_bt_rx_gain(btc, para.bt_rx_gain);
|
|
if (!bt->enable.now || dm->wl_only || wl->status.map.rf_off ||
|
wl->status.map.lps == BTC_LPS_RF_OFF ||
|
wl->role_info.link_mode == BTC_WLINK_5G ||
|
wl->role_info.link_mode == BTC_WLINK_NOLINK)
|
wl_stb_chg = 0;
|
else
|
wl_stb_chg = 1;
|
|
if (wl_stb_chg != dm->wl_stb_chg) {
|
dm->wl_stb_chg = wl_stb_chg;
|
btc->chip->ops->wl_s1_standby(btc, dm->wl_stb_chg);
|
}
|
|
}
|
|
void _update_btc_state_map(struct btc_t *btc)
|
{
|
struct btc_cx *cx = &btc->cx;
|
struct btc_wl_info *wl = &cx->wl;
|
struct btc_bt_info *bt = &cx->bt;
|
struct btc_bt_link_info *bt_linfo = &bt->link_info;
|
|
if (wl->status.map.connecting || wl->status.map._4way ||
|
wl->status.map.roaming) {
|
cx->state_map = BTC_WLINKING;
|
} else if (wl->status.map.scan) { /* wl scan */
|
if (bt_linfo->status.map.inq_pag)
|
cx->state_map = BTC_WSCAN_BSCAN;
|
else
|
cx->state_map = BTC_WSCAN_BNOSCAN;
|
} else if (wl->status.map.busy) { /* only busy */
|
if (bt_linfo->status.map.inq_pag)
|
cx->state_map = BTC_WBUSY_BSCAN;
|
else
|
cx->state_map = BTC_WBUSY_BNOSCAN;
|
} else { /* wl idle */
|
cx->state_map = BTC_WIDLE;
|
}
|
}
|
|
static void _set_bt_golden_rx_range(struct btc_t *btc, u8 p_id, u8 level)
|
{
|
struct btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
|
u8 buf[2] = {0}, pos = 0, i;
|
|
if (p_id > BTC_BT_PAN)
|
return;
|
|
for (i = 0; i< BTC_PROFILE_MAX; i++) {
|
if ((p_id >> i) & 0x1) {
|
pos = i;
|
break;
|
}
|
}
|
|
if (bt_linfo->golden_rx_shift[pos] == level)
|
return;
|
|
bt_linfo->golden_rx_shift[pos] = level;
|
|
PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): p_id=%d, level=%d\n",
|
__func__, p_id, level);
|
|
buf[0] = level;
|
buf[1] = pos;
|
hal_btc_fw_set_bt(btc, SET_BT_GOLDEN_RX_RANGE, sizeof(buf), buf);
|
}
|
|
static void _set_bt_afh_info(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
struct btc_bt_link_info *b = &bt->link_info;
|
struct btc_wl_role_info *wl_rinfo = &wl->role_info;
|
/*struct btc_module *module = &btc->mdinfo;*/
|
u8 en = 0, i, ch = 0, bw = CHANNEL_WIDTH_MAX;
|
u8 max_role_cnt = BTC_TDMA_WLROLE_MAX;
|
|
if (btc->ctrl.manual || wl->status.map.scan)
|
return;
|
|
if (btc->hal->dbcc_en)
|
max_role_cnt++;
|
|
/* TBD if include module->ant.type == BTC_ANT_SHARED */
|
if (wl->status.map.rf_off || bt->whql_test ||
|
wl_rinfo->link_mode == BTC_WLINK_NOLINK ||
|
wl_rinfo->link_mode == BTC_WLINK_5G ||
|
wl_rinfo->connect_cnt > max_role_cnt) {
|
en = false;
|
ch = 0;
|
bw = 0;
|
goto exit;
|
} else {
|
for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
|
/* get p2p channel for MCC */
|
if (wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
|
if (wl_rinfo->active_role[i].role == PHL_RTYPE_AP ||
|
wl_rinfo->active_role[i].role == PHL_RTYPE_P2P_GO ||
|
wl_rinfo->active_role[i].role == PHL_RTYPE_P2P_GC) {
|
en = true;
|
ch = wl_rinfo->active_role[i].ch;
|
bw = wl_rinfo->active_role[i].bw;
|
break;
|
}
|
} else if (wl_rinfo->active_role[i].connected &&
|
wl_rinfo->active_role[i].band == BAND_ON_24G) {
|
en = true;
|
ch = wl_rinfo->active_role[i].ch;
|
bw = wl_rinfo->active_role[i].bw;
|
|
/* get the max bw if scc */
|
if (wl_rinfo->link_mode != BTC_WLINK_2G_SCC ||
|
wl_rinfo->active_role[i].bw == CHANNEL_WIDTH_40) {
|
break;
|
}
|
}
|
}
|
}
|
|
|
if (!en || ch > 14 || ch == 0)
|
bw = CHANNEL_WIDTH_MAX;
|
|
/* default AFH channel sapn = center-ch +- 6MHz */
|
switch (bw) {
|
case CHANNEL_WIDTH_20:
|
if (btc->dm.freerun)
|
bw = 48;
|
else
|
bw = 20 + btc->chip->afh_guard_ch * 2;
|
break;
|
case CHANNEL_WIDTH_40:
|
bw = 40 + btc->chip->afh_guard_ch * 2;
|
break;
|
case CHANNEL_WIDTH_5:
|
bw = 5 + btc->chip->afh_guard_ch * 2;
|
break;
|
case CHANNEL_WIDTH_10:
|
bw = 10 + btc->chip->afh_guard_ch * 2;
|
break;
|
default:
|
case CHANNEL_WIDTH_MAX:
|
en = false; /* turn off AFH info if invalid BW */
|
bw = 0;
|
ch = 0;
|
break;
|
}
|
|
exit:
|
if (wl->afh_info.en == en &&
|
wl->afh_info.ch == ch &&
|
wl->afh_info.bw == bw &&
|
b->profile_cnt.last == b->profile_cnt.now)
|
return;
|
|
wl->afh_info.en = en;
|
wl->afh_info.ch = ch;
|
wl->afh_info.bw = bw;
|
hal_btc_fw_set_bt(btc, SET_BT_WL_CH_INFO, 3, (u8*)&wl->afh_info);
|
|
PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
|
__func__, en, ch, bw);
|
btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
|
}
|
|
static void _set_halbb_btg_ctrl(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_wl_role_info *wl_rinfo = &wl->role_info;
|
struct btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
|
bool is_btg = false;
|
|
if (btc->ctrl.manual)
|
return;
|
|
/* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
|
if (wl_rinfo->link_mode == BTC_WLINK_5G) /* always 0 if 5G */
|
is_btg = false;
|
else if (btc->dm.freerun)
|
is_btg = false;
|
else if (wl_rinfo->link_mode == BTC_WLINK_25G_DBCC &&
|
wl_dinfo->real_band[1] != BAND_ON_24G)
|
is_btg = false;
|
else
|
is_btg = true;
|
|
if (!run_rsn("_ntfy_init_coex") && is_btg == btc->dm.wl_btg_rx)
|
return;
|
|
btc->dm.wl_btg_rx = is_btg;
|
/* rtw_hal_bb_ctrl_btg control the following:
|
* if btc->dm.wl_btg_rx = false (gnt_wl always = 1)
|
* Lte_rx: 0x10980[17]=1, 0x10980[29]=0
|
* Gnt_wl: 0x10980[18]=1, 0x10980[28]=1
|
* Gnt_bt_tx: 0x10980[19]=1, 0x10980[27]=0
|
* Gnt_bt: 0x10980[20]=1, 0x10980[26]=0
|
* if if btc->dm.wl_btg_rx = true (gnt from MAC)
|
* Lte_rx: 0x10980[17]=0, 0x10980[29]=0
|
* Gnt_wl: 0x10980[18]=0, 0x10980[28]=1
|
* Gnt_bt_tx: 0x10980[19]=0, 0x10980[27]=0
|
* Gnt_bt: 0x10980[20]=0, 0x10980[26]=0
|
*/
|
|
/* skip if MCC dual_band, call ctrl_btg8852a() in WL FW by slot */
|
if (wl_rinfo->link_mode == BTC_WLINK_25G_MCC)
|
return;
|
|
rtw_hal_bb_ctrl_btg(btc->hal, is_btg);
|
}
|
|
static void _set_bt_slot_req(struct btc_t *btc)
|
{
|
struct btc_bt_link_info *b = &btc->cx.bt.link_info;
|
u8 len = 0;
|
|
/* don't change bt slot req state during RFK for p2p/mcc case*/
|
if (!run_rsn("_ntfy_wl_rfk") &&
|
btc->cx.wl.rfk_info.state == BTC_WRFK_STOP)
|
btc->bt_req_en = false;
|
|
/* enable bt-slot req if ext-slot-control */
|
if (btc->dm.tdma_now.type == CXTDMA_OFF &&
|
btc->dm.tdma_now.ext_ctrl == CXECTL_EXT)
|
btc->bt_req_en = true;
|
|
if (!btc->bt_req_en) {
|
len = 0;
|
} else {
|
if (b->a2dp_desc.exist || b->a2dp_desc.active ||
|
(b->profile_cnt.now == 1 &&
|
b->hid_desc.pair_cnt == 1 &&
|
b->multi_link.now)) /*a2dp, hid + acl-idle */ {
|
if (b->profile_cnt.now >= 2)
|
len = BTC_BSLOT_A2DP_HID;
|
else
|
len = BTC_BSLOT_A2DP;
|
} else if (b->pan_desc.exist || b->status.map.inq_pag) {
|
len = BTC_BSLOT_INQ;
|
} else {
|
len = BTC_BSLOT_IDLE;
|
}
|
}
|
|
if (len == btc->bt_req_len)
|
return;
|
|
btc->bt_req_len = len;
|
|
hal_btc_send_event(btc, (u8*)&btc->bt_req_len, 4, BTC_HMSG_SET_BT_REQ_SLOT);
|
|
PHL_INFO("[BTC], %s(): bt_req_len=%d\n", __func__, btc->bt_req_len);
|
}
|
|
static void _set_bt_rx_agc(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_wl_role_info *wl_rinfo = &wl->role_info;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
bool bt_hi_lna_rx = false;
|
|
if (wl_rinfo->link_mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
|
bt_hi_lna_rx = true;
|
|
if (bt_hi_lna_rx == bt->hi_lna_rx)
|
return;
|
|
/* true: bt use Hi-LNA rx gain table (f/e/3/2) in -3x~-9xdBm for co-rx
|
* false: bt use original rx gain table (f/b/7/3/2)
|
*/
|
|
_write_scbd(btc, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
|
}
|
|
static void _set_bt_rx_scan_pri(struct btc_t *btc)
|
{
|
struct btc_bt_info *bt = &btc->cx.bt;
|
|
_write_scbd(btc, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
|
}
|
|
static void _set_halmac_tx_limit(struct btc_t *btc)
|
{
|
struct btc_cx *cx = &btc->cx;
|
struct btc_dm *dm = &btc->dm;
|
struct btc_wl_info *wl = &cx->wl;
|
struct btc_bt_info *bt = &cx->bt;
|
struct btc_bt_link_info *b = &bt->link_info;
|
struct btc_bt_hfp_desc *hfp = &b->hfp_desc;
|
struct btc_bt_hid_desc *hid = &b->hid_desc;
|
struct btc_wl_role_info *wl_rinfo = &wl->role_info;
|
struct btc_wl_link_info *plink = NULL;
|
u8 mode = wl_rinfo->link_mode, i, tx_1ss_limit = 0, tx_1ss_en = 0;
|
u8 tx_retry = 0, enable = 0, reenable = 0;
|
u32 tx_time = 0;
|
|
if (btc->ctrl.manual)
|
return;
|
|
if (mode == BTC_WLINK_2G_GO ||
|
mode == BTC_WLINK_2G_GC ||
|
mode == BTC_WLINK_2G_SCC ||
|
mode == BTC_WLINK_2G_MCC ||
|
mode == BTC_WLINK_25G_MCC) {
|
if (hfp->exist || hid->exist)
|
tx_1ss_limit = 1;
|
else
|
tx_1ss_limit = 0;
|
} else {
|
tx_1ss_limit = 0;
|
}
|
|
dm->wl_tx_limit.tx_1ss = tx_1ss_limit;
|
|
for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
|
|
plink = &wl->link_info[i];
|
|
if (plink->connected == MLME_LINKED &&
|
plink->chdef.band == BAND_ON_24G)
|
tx_1ss_en = tx_1ss_limit;
|
else
|
tx_1ss_en = false;
|
|
if (tx_1ss_en != plink->stat.traffic.tx_1ss_limit)
|
rtw_hal_btc_cfg_tx_1ss(btc->hal, btc->phl,
|
i, tx_1ss_en);
|
}
|
|
if (btc->dm.freerun || btc->ctrl.igno_bt || b->profile_cnt.now == 0 ||
|
mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
|
enable = 0;
|
tx_time = BTC_MAX_TX_TIME_DEF;
|
tx_retry = BTC_MAX_TX_RETRY_DEF;
|
} else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
|
enable = 1;
|
tx_time = BTC_MAX_TX_TIME_L2;
|
tx_retry = BTC_MAX_TX_RETRY_L1;
|
} else if (hfp->exist || hid->exist) {
|
enable = 1;
|
tx_time = BTC_MAX_TX_TIME_L3;
|
tx_retry = BTC_MAX_TX_RETRY_L1;
|
} else {
|
enable = 0;
|
tx_time = BTC_MAX_TX_TIME_DEF;
|
tx_retry = BTC_MAX_TX_RETRY_DEF;
|
}
|
|
if (dm->wl_tx_limit.en == enable &&
|
dm->wl_tx_limit.tx_time == tx_time &&
|
dm->wl_tx_limit.tx_retry == tx_retry)
|
return;
|
|
if (!dm->wl_tx_limit.en && enable)
|
reenable = 1;
|
|
dm->wl_tx_limit.en = enable;
|
dm->wl_tx_limit.tx_time = tx_time;
|
dm->wl_tx_limit.tx_retry = tx_retry;
|
|
for (i = 0; i < MAX_WIFI_ROLE_NUMBER; i++) {
|
|
plink = &wl->link_info[i];
|
|
if (!plink->connected)
|
continue;
|
|
/* backup the original tx time before tx-limit on */
|
if (reenable) {
|
rtw_hal_mac_get_tx_time(btc->hal,
|
(u8)plink->mac_id,
|
&plink->tx_time);
|
rtw_hal_mac_get_tx_retry_limit(btc->hal,
|
(u8)plink->mac_id,
|
&plink->tx_retry);
|
}
|
|
/* restore the original tx time if no tx-limit */
|
if (!enable) {
|
rtw_hal_mac_set_tx_time(btc->hal, 1, 1,
|
(u8)plink->mac_id,
|
plink->tx_time);
|
rtw_hal_mac_set_tx_retry_limit(btc->hal, 1, 1,
|
(u8)plink->mac_id,
|
plink->tx_retry);
|
} else {
|
rtw_hal_mac_set_tx_time(btc->hal, 1, 0,
|
(u8)plink->mac_id, tx_time);
|
rtw_hal_mac_set_tx_retry_limit(btc->hal, 1, 0,
|
(u8)plink->mac_id,
|
tx_retry);
|
}
|
}
|
}
|
|
static bool _check_freerun(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
struct btc_wl_role_info *wl_rinfo = &wl->role_info;
|
struct btc_bt_link_info *bt_linfo = &bt->link_info;
|
struct btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
|
u8 max_role_cnt = BTC_TDMA_WLROLE_MAX;
|
|
if (btc->hal->dbcc_en)
|
max_role_cnt++;
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
|
btc->dm.trx_para_level = 0;
|
return false;
|
}
|
|
/* The below is dedicated antenna case */
|
|
if (wl_rinfo->connect_cnt > max_role_cnt) {
|
btc->dm.trx_para_level = 5;
|
return true;
|
}
|
|
if (bt_linfo->profile_cnt.now == 0) {
|
btc->dm.trx_para_level = 5;
|
return true;
|
}
|
|
if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
|
btc->dm.trx_para_level = 5;
|
return true;
|
}
|
|
/* Todo: get isolation by BT psd */
|
if (btc->mdinfo.ant.isolation >= BTC_FREERUN_ANTISO_MIN) {
|
btc->dm.trx_para_level = 5;
|
return true;
|
}
|
|
if (!wl->status.map.busy) {/* wl idle -> freerun */
|
btc->dm.trx_para_level = 5;
|
return true;
|
} else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
|
btc->dm.trx_para_level = 0;
|
return false;
|
} else if (wl->status.map.traffic_dir & BIT(TRAFFIC_UL)) { /* uplink */
|
if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
|
btc->dm.trx_para_level = 6;
|
return true;
|
} else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
|
btc->dm.trx_para_level = 7;
|
return true;
|
} else {
|
btc->dm.trx_para_level = 0;
|
return false;
|
}
|
} else if (wl->status.map.traffic_dir & BIT(TRAFFIC_DL)) { /*downlink*/
|
if (bt_linfo->rssi > 28) {
|
btc->dm.trx_para_level = 6;
|
return true;
|
}
|
}
|
|
btc->dm.trx_para_level = 0;
|
return false;
|
}
|
|
static void _set_policy(struct btc_t *btc, u16 policy_type, const char* action)
|
{
|
struct btc_dm *dm = &btc->dm;
|
struct fbtc_tdma *t = &dm->tdma;
|
struct fbtc_slot *s = dm->slot;
|
struct btc_wl_role_info *wl_rinfo = &btc->cx.wl.role_info;
|
struct btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
|
u8 type, null_role = 0;
|
u16 dur = 0;
|
u32 tbl_w1, tbl_b1, tbl_b4;
|
bool mode = NM_EXEC;
|
|
type = (u8)((policy_type & bMASKB1) >> 8);
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
|
if (btc->cx.wl.status.map._4way)
|
tbl_w1 = cxtbl[1];
|
else if (hid->exist && hid->type == BTC_HID_218)
|
tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
|
else
|
tbl_w1 = cxtbl[8];
|
|
if (dm->leak_ap &&
|
(type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
|
tbl_b1 = cxtbl[3];
|
tbl_b4 = cxtbl[3];
|
} else if (hid->exist && hid->type == BTC_HID_218) {
|
tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
|
tbl_b4 = cxtbl[4];
|
} else {
|
tbl_b1 = cxtbl[2];
|
tbl_b4 = cxtbl[2];
|
}
|
} else {
|
tbl_w1 = cxtbl[16]; /* 19 for HID exist */
|
tbl_b1 = cxtbl[17];
|
tbl_b4 = cxtbl[17];
|
}
|
|
switch(type) {
|
case BTC_CXP_USERDEF0:
|
mode = FC_EXEC;
|
_tdma_cpy(t, &t_def[CXTD_OFF]);
|
_slot_cpy(&s[CXST_OFF], &s_def[CXST_OFF]);
|
_slot_set_tbl(CXST_OFF, cxtbl[2]);
|
break;
|
case BTC_CXP_OFF: /* TDMA off */
|
_write_scbd(btc, BTC_WSCB_TDMA, false);
|
_tdma_cpy(t, &t_def[CXTD_OFF]);
|
_slot_cpy(&s[CXST_OFF], &s_def[CXST_OFF]);
|
|
switch (policy_type) {
|
case BTC_CXP_OFF_BT:
|
_slot_set_tbl(CXST_OFF, cxtbl[2]);
|
break;
|
case BTC_CXP_OFF_WL:
|
_slot_set_tbl(CXST_OFF, cxtbl[1]);
|
break;
|
case BTC_CXP_OFF_EQ0:
|
_slot_set_tbl(CXST_OFF, cxtbl[0]);
|
break;
|
case BTC_CXP_OFF_EQ1:
|
_slot_set_tbl(CXST_OFF, cxtbl[16]);
|
break;
|
case BTC_CXP_OFF_EQ2:
|
_slot_set_tbl(CXST_OFF, cxtbl[17]);
|
break;
|
case BTC_CXP_OFF_EQ3:
|
_slot_set_tbl(CXST_OFF, cxtbl[18]);
|
break;
|
case BTC_CXP_OFF_BWB0:
|
_slot_set_tbl(CXST_OFF, cxtbl[5]);
|
break;
|
case BTC_CXP_OFF_BWB1:
|
_slot_set_tbl(CXST_OFF, cxtbl[8]);
|
break;
|
case BTC_CXP_OFF_BWB2:
|
_slot_set_tbl(CXST_OFF, cxtbl[7]);
|
break;
|
}
|
break;
|
case BTC_CXP_OFFB: /* TDMA off + beacon protect */
|
_write_scbd(btc, BTC_WSCB_TDMA, false);
|
_tdma_cpy(t, &t_def[CXTD_OFF_B2]);
|
_slot_cpy(&s[CXST_OFF], &s_def[CXST_OFF]);
|
switch (policy_type) {
|
case BTC_CXP_OFFB_BWB0:
|
_slot_set_tbl(CXST_OFF, cxtbl[8]);
|
break;
|
}
|
break;
|
case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
|
_write_scbd(btc, BTC_WSCB_TDMA, true);
|
_tdma_cpy(t, &t_def[CXTD_OFF_EXT]);
|
|
if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC &&
|
dm->wl_scc.ebt_null) {
|
_tdma_set_rxflctrl(1);
|
_tdma_set_txflctrl(1);
|
if ((wl_rinfo->mrole_noa_duration > 0) &&
|
(wl_rinfo->mrole_noa_duration +
|
2 * BTC_NULL1_EBT_EARLY_T < BTC_SCC_CYCLE))
|
dur = BTC_SCC_CYCLE - BTC_NULL1_EBT_EARLY_T -
|
wl_rinfo->mrole_noa_duration;
|
}
|
|
switch (policy_type) {
|
case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */
|
_slot_set(CXST_E2G, dur, tbl_w1, SLOT_ISO);
|
_slot_cpy(&s[CXST_EBT], &s_def[CXST_EBT]);
|
break;
|
case BTC_CXP_OFFE_2GISOB: /* for bt no-link */
|
_slot_set(CXST_E2G, dur, cxtbl[1], SLOT_ISO);
|
_slot_cpy(&s[CXST_EBT], &s_def[CXST_EBT]);
|
break;
|
case BTC_CXP_OFFE_2GBWMIXB: /* for GC-only NOA < bt_slot_req */
|
_slot_set(CXST_E2G, dur, tbl_w1, SLOT_MIX);
|
_slot_cpy(&s[CXST_EBT], &s_def[CXST_EBT]);
|
break;
|
case BTC_CXP_OFFE_2GBWMIXB2: /* for GC+STA NOA < bt_slot_req */
|
_slot_set(CXST_E2G, dur, tbl_w1, SLOT_MIX);
|
_slot_set(CXST_EBT, BTC_BSLOT_A2DP_HID,
|
cxtbl[2], SLOT_MIX);
|
break;
|
case BTC_CXP_OFFE_WL: /*for 4-way */
|
_slot_set(CXST_E2G, dur, cxtbl[1], SLOT_MIX);
|
_slot_set(CXST_EBT, 0, cxtbl[1], SLOT_MIX);
|
break;
|
}
|
|
_slot_cpy(&s[CXST_E5G], &s_def[CXST_E5G]);
|
_slot_cpy(&s[CXST_ENULL], &s_def[CXST_ENULL]);
|
break;
|
case BTC_CXP_FIX: /* TDMA Fix-Slot */
|
_write_scbd(btc, BTC_WSCB_TDMA, true);
|
_tdma_cpy(t, &t_def[CXTD_FIX]);
|
switch (policy_type) {
|
case BTC_CXP_FIX_TD3030: /* W1:B1 = 30:30 */
|
_slot_set(CXST_W1, 30, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 30, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_FIX_TD5050: /* W1:B1 = 50:50 */
|
_slot_set(CXST_W1, 50, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 50, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_FIX_TD2030: /* W1:B1 = 20:30 */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 30, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_FIX_TD4010: /* W1:B1 = 40:10 */
|
_slot_set(CXST_W1, 40, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 10, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_FIX_TD4010ISO: /* W1:B1 = 40:10 for WL busy/scan */
|
_slot_set(CXST_W1, 40, cxtbl[1], SLOT_ISO);
|
_slot_set(CXST_B1, 10, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_FIX_TD7010: /* W1:B1 = 70:10 */
|
_slot_set(CXST_W1, 70, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 10, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_FIX_TD2060: /* W1:B1 = 20:60 */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 60, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_FIX_TD3060: /* W1:B1 = 30:60 */
|
_slot_set(CXST_W1, 30, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 60, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_FIX_TD2080: /* W1:B1 = 20:80 */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 80, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
|
_slot_set(CXST_W1, dm->slot_dur[CXST_W1],
|
tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, dm->slot_dur[CXST_B1],
|
tbl_b1, SLOT_MIX);
|
break;
|
}
|
break;
|
case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
|
_write_scbd(btc, BTC_WSCB_TDMA, true);
|
_tdma_cpy(t, &t_def[CXTD_PFIX]);
|
|
switch (policy_type) {
|
case BTC_CXP_PFIX_TD3030: /* W1:B1 = 30:30 */
|
_slot_set(CXST_W1, 30, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 30, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_PFIX_TD5050: /* W1:B1 = 50:50 */
|
_slot_set(CXST_W1, 50, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 50, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_PFIX_TD2030: /* W1:B1 = 20:30 */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 30, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_PFIX_TD2060: /* W1:B1 = 20:60 */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 60, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_PFIX_TD3070: /* W1:B1 = 30:60 */
|
_slot_set(CXST_W1, 30, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 60, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_PFIX_TD2080: /* W1:B1 = 20:80 */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, 80, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
|
_slot_set(CXST_W1, dm->slot_dur[CXST_W1],
|
tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, dm->slot_dur[CXST_B1],
|
tbl_b1, SLOT_MIX);
|
break;
|
}
|
break;
|
case BTC_CXP_AUTO: /* TDMA Auto-Slot */
|
_write_scbd(btc, BTC_WSCB_TDMA, true);
|
_tdma_cpy(t, &t_def[CXTD_AUTO]);
|
switch (policy_type) {
|
case BTC_CXP_AUTO_TD50B1: /* W1:B1 = 50:BTC_B1_MAX */
|
_slot_set(CXST_W1, 50, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_AUTO_TD60B1: /* W1:B1 = 60:BTC_B1_MAX */
|
_slot_set(CXST_W1, 60, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_AUTO_TD20B1: /* W1:B1 = 20:BTC_B1_MAX */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
|
_slot_set(CXST_W1, dm->slot_dur[CXST_W1],
|
tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, dm->slot_dur[CXST_B1],
|
tbl_b1, SLOT_MIX);
|
break;
|
}
|
break;
|
case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
|
_write_scbd(btc, BTC_WSCB_TDMA, true);
|
_tdma_cpy(t, &t_def[CXTD_PAUTO]);
|
switch (policy_type) {
|
case BTC_CXP_PAUTO_TD50B1: /* W1:B1 = 50:BTC_B1_MAX */
|
_slot_set(CXST_W1, 50, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_PAUTO_TD60B1: /* W1:B1 = 60:BTC_B1_MAX */
|
_slot_set(CXST_W1, 60, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_PAUTO_TD20B1: /* W1:B1 = 20:BTC_B1_MAX */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
break;
|
case BTC_CXP_PAUTO_TDW1B1: /* W1:B1 = user-define */
|
_slot_set(CXST_W1, dm->slot_dur[CXST_W1],
|
tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, dm->slot_dur[CXST_B1],
|
tbl_b1, SLOT_MIX);
|
break;
|
}
|
break;
|
case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
|
_write_scbd(btc, BTC_WSCB_TDMA, true);
|
_tdma_cpy(t, &t_def[CXTD_AUTO2]);
|
switch (policy_type) {
|
case BTC_CXP_AUTO2_TD3050: /* W1:B4 = 30:50 */
|
_slot_set(CXST_W1, 30, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, 50, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_AUTO2_TD3070: /* W1:B4 = 30:70 */
|
_slot_set(CXST_W1, 30, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, 70, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_AUTO2_TD5050: /* W1:B4 = 50:50 */
|
_slot_set(CXST_W1, 50, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, 50, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_AUTO2_TD6060: /* W1:B4 = 60:60 */
|
_slot_set(CXST_W1, 60, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, 60, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_AUTO2_TD2080: /* W1:B4 = 20:80 */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, 80, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
|
_slot_set(CXST_W1, dm->slot_dur[CXST_W1],
|
tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, dm->slot_dur[CXST_B1],
|
tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, dm->slot_dur[CXST_B4],
|
tbl_b4, SLOT_MIX);
|
break;
|
}
|
break;
|
case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
|
_write_scbd(btc, BTC_WSCB_TDMA, true);
|
_tdma_cpy(t, &t_def[CXTD_PAUTO2]);
|
switch (policy_type) {
|
case BTC_CXP_PAUTO2_TD3050: /* W1:B4 = 30:50 */
|
_slot_set(CXST_W1, 30, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, 50, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_PAUTO2_TD3070: /* W1:B4 = 30:70 */
|
_slot_set(CXST_W1, 30, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, cxtbl[3], SLOT_MIX);
|
_slot_set(CXST_B4, 70, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_PAUTO2_TD5050: /* W1:B4 = 50:50 */
|
_slot_set(CXST_W1, 50, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, 50, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_PAUTO2_TD6060: /* W1:B4 = 60:60 */
|
_slot_set(CXST_W1, 60, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, 60, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_PAUTO2_TD2080: /* W1:B4 = 20:80 */
|
_slot_set(CXST_W1, 20, tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, 80, tbl_b4, SLOT_MIX);
|
break;
|
case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
|
_slot_set(CXST_W1, dm->slot_dur[CXST_W1],
|
tbl_w1, SLOT_ISO);
|
_slot_set(CXST_B1, dm->slot_dur[CXST_B1],
|
tbl_b1, SLOT_MIX);
|
_slot_set(CXST_B4, dm->slot_dur[CXST_B4],
|
tbl_b4, SLOT_MIX);
|
break;
|
}
|
break;
|
}
|
|
if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
|
null_role = (dm->wl_scc.null_role1 & 0xf) +
|
((dm->wl_scc.null_role2 & 0xf) << 4);
|
_tdma_set_flctrl_role(null_role);
|
}
|
|
/* enter leak_slot after each null-1 */
|
if (dm->leak_ap && dm->tdma.leak_n > 1)
|
_tdma_set_lek(1);
|
|
if (run_rsn("_cmd_set_coex"))
|
mode = FC_EXEC;
|
|
_update_poicy(btc, mode, policy_type, action);
|
}
|
|
void _set_gnt_wl(struct btc_t *btc, u8 phy_map, u8 state)
|
{
|
struct rtw_hal_com_t *h = btc->hal;
|
struct btc_dm *dm = &btc->dm;
|
struct btc_gnt_ctrl *g = dm->gnt;
|
u8 i;
|
|
if (phy_map > BTC_PHY_ALL)
|
return;
|
|
for (i = 0; i < BTC_PHY_MAX; i++) {
|
if (!(phy_map & BIT(i)))
|
continue;
|
|
switch (state) {
|
case BTC_GNT_HW:
|
g[i].gnt_wl_sw_en = 0;
|
g[i].gnt_wl = 0;
|
break;
|
case BTC_GNT_SW_LO:
|
g[i].gnt_wl_sw_en = 1;
|
g[i].gnt_wl = 0;
|
break;
|
case BTC_GNT_SW_HI:
|
g[i].gnt_wl_sw_en = 1;
|
g[i].gnt_wl = 1;
|
break;
|
}
|
}
|
|
rtw_hal_mac_set_grant(h, (u8*)g);
|
}
|
|
void _set_gnt_bt(struct btc_t *btc, u8 phy_map, u8 state)
|
{
|
struct rtw_hal_com_t *h = btc->hal;
|
struct btc_dm *dm = &btc->dm;
|
struct btc_gnt_ctrl *g = dm->gnt;
|
u8 i;
|
|
if (phy_map > BTC_PHY_ALL)
|
return;
|
|
for (i = 0; i < BTC_PHY_MAX; i++) {
|
if (!(phy_map & BIT(i)))
|
continue;
|
|
switch (state) {
|
case BTC_GNT_HW:
|
g[i].gnt_bt_sw_en = 0;
|
g[i].gnt_bt = 0;
|
break;
|
case BTC_GNT_SW_LO:
|
g[i].gnt_bt_sw_en = 1;
|
g[i].gnt_bt = 0;
|
break;
|
case BTC_GNT_SW_HI:
|
g[i].gnt_bt_sw_en = 1;
|
g[i].gnt_bt = 1;
|
break;
|
}
|
}
|
|
rtw_hal_mac_set_grant(h, (u8*)g);
|
}
|
|
static void _set_bt_plut(struct btc_t *btc, u8 phy_map, u8 tx_val, u8 rx_val)
|
{
|
if (phy_map & BTC_PHY_0) {
|
rtw_hal_mac_set_polluted(btc->hal, HW_PHY_0, tx_val, rx_val);
|
btc->cx.wl.bt_polut_type[HW_PHY_0] = tx_val;
|
}
|
|
if (!btc->hal->dbcc_en)
|
return;
|
|
if (phy_map & BTC_PHY_1) {
|
rtw_hal_mac_set_polluted(btc->hal, HW_PHY_1, tx_val, rx_val);
|
btc->cx.wl.bt_polut_type[HW_PHY_1] = tx_val;
|
}
|
}
|
|
static void _set_ant(struct btc_t *btc, bool force_exec, u8 phy_map, u8 type)
|
{
|
struct btc_dm *dm = &btc->dm;
|
struct btc_cx *cx = &btc->cx;
|
struct btc_wl_info *wl = &cx->wl;
|
struct btc_bt_info *bt = &cx->bt;
|
struct btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
|
u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
|
u32 ant_path_type;
|
|
ant_path_type = ((phy_map << 8) + type);
|
|
if (run_rsn("_cmd_set_coex") || run_rsn("_ntfy_power_off") ||
|
run_rsn("_ntfy_radio_state"))
|
force_exec = FC_EXEC;
|
|
if (!force_exec && (ant_path_type == dm->set_ant_path)) {
|
PHL_TRACE(COMP_PHL_BTC, _PHL_DEBUG_, "[BTC], %s(): return by no change!!\n",
|
__func__);
|
return;
|
} else if (bt->rfk_info.map.run) {
|
PHL_INFO("[BTC], %s(): return by bt rfk!!\n", __func__);
|
return;
|
} else if (!run_rsn("_ntfy_wl_rfk") &&
|
wl->rfk_info.state != BTC_WRFK_STOP) {
|
PHL_INFO("[BTC], %s(): return by wl rfk!!\n", __func__);
|
return;
|
}
|
|
dm->set_ant_path = ant_path_type;
|
|
PHL_INFO("[BTC], %s(): path=0x%x, set_type=%s\n", __func__,
|
phy_map, id_to_str(BTC_STR_ANTPATH, dm->set_ant_path & 0xff));
|
|
switch (type){
|
case BTC_ANT_WPOWERON:
|
_set_cx_ctrl(btc, BTC_CTRL_BY_BT);
|
break;
|
case BTC_ANT_WINIT:
|
/* To avoid BT MP driver case (bt_enable but no mailbox) */
|
if (bt->enable.now && bt->run_patch_code) {
|
_set_gnt_wl(btc, phy_map, BTC_GNT_SW_LO);
|
_set_gnt_bt(btc, phy_map, BTC_GNT_SW_HI);
|
} else {
|
_set_gnt_wl(btc, phy_map, BTC_GNT_SW_HI);
|
_set_gnt_bt(btc, phy_map, BTC_GNT_SW_LO);
|
}
|
_set_cx_ctrl(btc, BTC_CTRL_BY_WL);
|
_set_bt_plut(btc, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
|
break;
|
case BTC_ANT_WONLY:
|
_set_gnt_wl(btc, phy_map, BTC_GNT_SW_HI);
|
_set_gnt_bt(btc, phy_map, BTC_GNT_SW_LO);
|
_set_cx_ctrl(btc, BTC_CTRL_BY_WL);
|
_set_bt_plut(btc, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
|
break;
|
case BTC_ANT_WOFF:
|
_set_cx_ctrl(btc, BTC_CTRL_BY_BT);
|
_set_bt_plut(btc, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
|
break;
|
case BTC_ANT_W2G:
|
_set_cx_ctrl(btc, BTC_CTRL_BY_WL);
|
if (btc->hal->dbcc_en) {
|
for (i = 0; i < HW_PHY_MAX; i++) {
|
b2g = (wl_dinfo->real_band[i] == BAND_ON_24G);
|
|
gnt_wl_ctrl = (b2g? BTC_GNT_HW : BTC_GNT_SW_HI);
|
_set_gnt_wl(btc, BIT(i), gnt_wl_ctrl);
|
|
gnt_bt_ctrl = BTC_GNT_HW;
|
_set_gnt_bt(btc, BIT(i), gnt_bt_ctrl);
|
|
plt_ctrl = (b2g? BTC_PLT_BT : BTC_PLT_NONE);
|
_set_bt_plut(btc, BIT(i), plt_ctrl, plt_ctrl);
|
}
|
} else {
|
_set_gnt_wl(btc, phy_map, BTC_GNT_HW);
|
_set_gnt_bt(btc, phy_map, BTC_GNT_HW);
|
plt_ctrl = BTC_PLT_BT;
|
_set_bt_plut(btc, BTC_PHY_ALL, plt_ctrl, plt_ctrl);
|
}
|
break;
|
case BTC_ANT_W5G:
|
_set_cx_ctrl(btc, BTC_CTRL_BY_WL);
|
_set_gnt_wl(btc, phy_map, BTC_GNT_SW_HI);
|
_set_gnt_bt(btc, phy_map, BTC_GNT_HW);
|
_set_bt_plut(btc, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
|
break;
|
case BTC_ANT_W25G:
|
_set_cx_ctrl(btc, BTC_CTRL_BY_WL);
|
if (btc->hal->dbcc_en) {
|
/* if BAND_ON_24G, the other role in the sane PHY = 5G*/
|
for (i = 0; i < HW_PHY_MAX; i++) {
|
b2g = (wl_dinfo->real_band[i] == BAND_ON_24G);
|
|
gnt_wl_ctrl = (b2g? BTC_GNT_HW : BTC_GNT_SW_HI);
|
_set_gnt_wl(btc, BIT(i), gnt_wl_ctrl);
|
|
gnt_bt_ctrl = BTC_GNT_HW;
|
_set_gnt_bt(btc, BIT(i), gnt_bt_ctrl);
|
|
plt_ctrl = (b2g? BTC_PLT_GNT_WL : BTC_PLT_NONE);
|
_set_bt_plut(btc, BIT(i), plt_ctrl, plt_ctrl);
|
}
|
} else {
|
_set_gnt_wl(btc, phy_map, BTC_GNT_HW);
|
_set_gnt_bt(btc, phy_map, BTC_GNT_HW);
|
plt_ctrl = BTC_PLT_GNT_WL;
|
_set_bt_plut(btc, BTC_PHY_ALL, plt_ctrl, plt_ctrl);
|
}
|
break;
|
case BTC_ANT_FREERUN:
|
_set_cx_ctrl(btc, BTC_CTRL_BY_WL);
|
_set_gnt_wl(btc, phy_map, BTC_GNT_SW_HI);
|
_set_gnt_bt(btc, phy_map, BTC_GNT_SW_HI);
|
_set_bt_plut(btc, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
|
break;
|
case BTC_ANT_WRFK:
|
_set_cx_ctrl(btc, BTC_CTRL_BY_WL);
|
_set_gnt_wl(btc, phy_map, BTC_GNT_SW_HI);
|
_set_gnt_bt(btc, phy_map, BTC_GNT_SW_LO);
|
_set_bt_plut(btc, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
|
break;
|
case BTC_ANT_BRFK:
|
_set_cx_ctrl(btc, BTC_CTRL_BY_BT);
|
_set_gnt_wl(btc, phy_map, BTC_GNT_SW_LO);
|
_set_gnt_bt(btc, phy_map, BTC_GNT_SW_HI);
|
_set_bt_plut(btc, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
|
break;
|
}
|
}
|
|
void _action_wl_only(struct btc_t *btc)
|
{
|
PHL_INFO("[BTC], %s !!\n", __func__);
|
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
|
_set_policy(btc, BTC_CXP_OFF_BT, __func__);
|
}
|
|
void _action_wl_init(struct btc_t *btc)
|
{
|
PHL_INFO("[BTC], %s !!\n", __func__);
|
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
|
_set_policy(btc, BTC_CXP_OFF_BT, __func__);
|
}
|
|
void _action_wl_off(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
|
PHL_INFO("[BTC], %s !!\n", __func__);
|
|
/* don't set PTA control if LPS */
|
if (wl->status.map.rf_off || btc->dm.bt_only) {
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
|
} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
|
if (wl->role_info.link_mode == BTC_WLINK_5G)
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
|
else
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
}
|
|
if (wl->role_info.link_mode == BTC_WLINK_5G) {
|
_set_policy(btc, BTC_CXP_OFF_EQ0, __func__);
|
} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
|
if (btc->cx.bt.link_info.a2dp_desc.active)
|
_set_policy(btc, BTC_CXP_OFF_BT, __func__);
|
else
|
_set_policy(btc, BTC_CXP_OFF_BWB1, __func__);
|
} else {
|
_set_policy(btc, BTC_CXP_OFF_BT, __func__);
|
}
|
}
|
|
void _action_freerun(struct btc_t *btc)
|
{
|
PHL_INFO("[BTC], %s !!\n", __func__);
|
btc->dm.freerun = true;
|
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
|
_set_policy(btc, BTC_CXP_OFF_BT, __func__);
|
}
|
|
void _action_bt_whql(struct btc_t *btc)
|
{
|
PHL_INFO("[BTC], %s !!\n", __func__);
|
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, BTC_CXP_OFF_BT, __func__);
|
}
|
|
void _action_bt_rfk(struct btc_t *btc)
|
{
|
PHL_INFO("[BTC], %s !!\n", __func__);
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_BRFK);
|
_set_policy(btc, BTC_CXP_OFF_BT, __func__);
|
}
|
|
void _action_bt_off(struct btc_t *btc)
|
{
|
PHL_INFO("[BTC], %s !!\n", __func__);
|
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
|
_set_policy(btc, BTC_CXP_OFF_BT, __func__);
|
}
|
|
static void _action_bt_idle(struct btc_t *btc)
|
{
|
struct btc_bt_info *bt = &btc->cx.bt;
|
struct btc_bt_link_info *b = &btc->cx.bt.link_info;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
|
switch(btc->cx.state_map) {
|
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt idle*/
|
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
|
if (b->status.map.connect)
|
policy_type = BTC_CXP_FIX_TD4010;
|
else
|
policy_type = BTC_CXP_FIX_TD4010ISO;
|
break;
|
case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
|
if (bt->pag)
|
policy_type = BTC_CXP_PFIX_TD2080;
|
else
|
policy_type = BTC_CXP_PFIX_TD5050;
|
break;
|
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
|
if (bt->pag)
|
policy_type = BTC_CXP_FIX_TD2080;
|
else
|
policy_type = BTC_CXP_FIX_TD5050;
|
break;
|
case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
|
if (bt->pag)
|
policy_type = BTC_CXP_FIX_TD2080;
|
else
|
policy_type = BTC_CXP_FIX_TD7010;
|
break;
|
case BTC_WIDLE: /* wl-idle + bt-idle */
|
policy_type = BTC_CXP_OFF_BWB1;
|
break;
|
}
|
} else { /* dedicated-antenna */
|
policy_type = BTC_CXP_OFF_EQ0;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
static void _action_bt_hfp(struct btc_t *btc)
|
{
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
|
if (btc->cx.wl.status.map._4way)
|
policy_type = BTC_CXP_OFF_WL;
|
else
|
policy_type = BTC_CXP_OFF_BWB1;
|
} else { /* dedicated-antenna */
|
policy_type = BTC_CXP_OFF_EQ2;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
static void _action_bt_hid(struct btc_t *btc)
|
{
|
struct btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
|
if (btc->cx.wl.status.map._4way) {
|
policy_type = BTC_CXP_OFF_WL;
|
} else if (hid->type == BTC_HID_218) {
|
btc->cx.bt.scan_rx_low_pri = true;
|
policy_type = BTC_CXP_OFF_BWB2;
|
} else {
|
policy_type = BTC_CXP_OFF_BWB1;
|
}
|
} else { /* dedicated-antenna */
|
policy_type = BTC_CXP_OFF_EQ3;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
static void _action_bt_a2dp(struct btc_t *btc)
|
{
|
struct btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
|
struct btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
|
struct btc_dm *dm = &btc->dm;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
switch(btc->cx.state_map) {
|
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
|
if (a2dp.vendor_id == 0x4c || dm->leak_ap ||
|
bt_linfo->slave_role) {
|
if (bt_linfo->slave_role)
|
dm->slot_dur[CXST_W1] = 20;
|
else
|
dm->slot_dur[CXST_W1] = 40;
|
dm->slot_dur[CXST_B1] = BTC_B1_MAX;
|
policy_type = BTC_CXP_PAUTO_TDW1B1;
|
} else {
|
policy_type = BTC_CXP_PAUTO_TD50B1;
|
}
|
break;
|
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
|
policy_type = BTC_CXP_PAUTO2_TD3050;
|
break;
|
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
|
policy_type = BTC_CXP_AUTO2_TD3050;
|
break;
|
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
|
case BTC_WLINKING: /* wl-connecting + bt-A2DP */
|
if (a2dp.vendor_id == 0x4c || dm->leak_ap ||
|
bt_linfo->slave_role) {
|
if (bt_linfo->slave_role)
|
dm->slot_dur[CXST_W1] = 20;
|
else
|
dm->slot_dur[CXST_W1] = 40;
|
dm->slot_dur[CXST_B1] = BTC_B1_MAX;
|
policy_type = BTC_CXP_AUTO_TDW1B1;
|
} else {
|
policy_type = BTC_CXP_AUTO_TD50B1;
|
}
|
break;
|
case BTC_WIDLE: /* wl-idle + bt-A2DP */
|
policy_type = BTC_CXP_AUTO_TD20B1;
|
break;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
static void _action_bt_a2dpsink(struct btc_t *btc)
|
{
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
switch(btc->cx.state_map) {
|
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
|
policy_type = BTC_CXP_PFIX_TD2030;
|
break;
|
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
|
policy_type = BTC_CXP_PFIX_TD2060;
|
break;
|
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
|
policy_type = BTC_CXP_FIX_TD2030;
|
break;
|
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
|
policy_type = BTC_CXP_FIX_TD2060;
|
break;
|
case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
|
policy_type = BTC_CXP_FIX_TD3030;
|
break;
|
case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
|
policy_type = BTC_CXP_FIX_TD2080;
|
break;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
static void _action_bt_pan(struct btc_t *btc)
|
{
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
switch(btc->cx.state_map) {
|
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
|
policy_type = BTC_CXP_PFIX_TD5050;
|
break;
|
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
|
policy_type = BTC_CXP_PFIX_TD3070;
|
break;
|
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
|
policy_type = BTC_CXP_FIX_TD3030;
|
break;
|
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
|
policy_type = BTC_CXP_FIX_TD3060;
|
break;
|
case BTC_WLINKING: /* wl-connecting + bt-PAN */
|
policy_type = BTC_CXP_FIX_TD4010ISO;
|
break;
|
case BTC_WIDLE: /* wl-idle + bt-pan */
|
policy_type = BTC_CXP_PFIX_TD2080;
|
break;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
static void _action_bt_a2dp_hid(struct btc_t *btc)
|
{
|
struct btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
|
struct btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
|
struct btc_dm *dm = &btc->dm;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
switch(btc->cx.state_map) {
|
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
|
case BTC_WIDLE: /* wl-idle + bt-A2DP */
|
if (a2dp.vendor_id == 0x4c || dm->leak_ap ||
|
bt_linfo->slave_role) {
|
if (bt_linfo->slave_role)
|
dm->slot_dur[CXST_W1] = 20;
|
else
|
dm->slot_dur[CXST_W1] = 40;
|
dm->slot_dur[CXST_W1] = 40;
|
dm->slot_dur[CXST_B1] = BTC_B1_MAX;
|
policy_type = BTC_CXP_PAUTO_TDW1B1;
|
} else {
|
policy_type = BTC_CXP_PAUTO_TD50B1;
|
}
|
break;
|
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
|
policy_type = BTC_CXP_PAUTO2_TD3050;
|
break;
|
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
|
policy_type = BTC_CXP_AUTO2_TD3050;
|
break;
|
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
|
case BTC_WLINKING: /* wl-connecting + bt-A2DP */
|
if (a2dp.vendor_id == 0x4c || dm->leak_ap ||
|
bt_linfo->slave_role) {
|
if (bt_linfo->slave_role)
|
dm->slot_dur[CXST_W1] = 20;
|
else
|
dm->slot_dur[CXST_W1] = 40;
|
dm->slot_dur[CXST_B1] = BTC_B1_MAX;
|
policy_type = BTC_CXP_AUTO_TDW1B1;
|
} else {
|
policy_type = BTC_CXP_AUTO_TD50B1;
|
}
|
break;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
static void _action_bt_a2dp_pan(struct btc_t *btc)
|
{
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
switch(btc->cx.state_map) {
|
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
|
policy_type = BTC_CXP_PAUTO2_TD3070;
|
break;
|
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
|
policy_type = BTC_CXP_PAUTO2_TD3070;
|
break;
|
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
|
policy_type = BTC_CXP_AUTO2_TD5050;
|
break;
|
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
|
policy_type = BTC_CXP_AUTO2_TD3070;
|
break;
|
case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
|
policy_type = BTC_CXP_AUTO2_TD3050;
|
break;
|
case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */
|
policy_type = BTC_CXP_PAUTO2_TD2080;
|
break;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
static void _action_bt_pan_hid(struct btc_t *btc)
|
{
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
switch(btc->cx.state_map) {
|
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
|
policy_type = BTC_CXP_PFIX_TD3030;
|
break;
|
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
|
policy_type = BTC_CXP_PFIX_TD3070;
|
break;
|
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
|
policy_type = BTC_CXP_FIX_TD3030;
|
break;
|
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
|
policy_type = BTC_CXP_FIX_TD3060;
|
break;
|
case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
|
policy_type = BTC_CXP_FIX_TD4010;
|
break;
|
case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
|
policy_type = BTC_CXP_PFIX_TD2080;
|
break;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
static void _action_bt_a2dp_pan_hid(struct btc_t *btc)
|
{
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
switch(btc->cx.state_map) {
|
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
|
policy_type = BTC_CXP_PAUTO2_TD3070;
|
break;
|
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
|
policy_type = BTC_CXP_PAUTO2_TD3070;
|
break;
|
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
|
policy_type = BTC_CXP_AUTO2_TD3070;
|
break;
|
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
|
case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
|
policy_type = BTC_CXP_AUTO2_TD3050;
|
break;
|
case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */
|
policy_type = BTC_CXP_PAUTO2_TD2080;
|
break;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
void _action_wl_5g(struct btc_t *btc)
|
{
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
|
_set_policy(btc, BTC_CXP_OFF_EQ0, __func__);
|
}
|
|
void _action_wl_other(struct btc_t *btc)
|
{
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED)
|
_set_policy(btc, BTC_CXP_OFFB_BWB0, __func__);
|
else
|
_set_policy(btc, BTC_CXP_OFF_EQ0, __func__);
|
}
|
|
void _action_wl_idle(struct btc_t *btc)
|
{
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED)
|
_set_policy(btc, BTC_CXP_OFFB_BWB0, __func__);
|
else
|
_set_policy(btc, BTC_CXP_OFF_EQ0, __func__);
|
}
|
|
void _action_wl_nc(struct btc_t *btc)
|
{
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, BTC_CXP_OFF_BT, __func__);
|
}
|
|
void _action_wl_rfk(struct btc_t *btc)
|
{
|
struct btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
|
|
if (rfk.state != BTC_WRFK_START)
|
return;
|
|
PHL_INFO("[BTC], %s(): band = %d\n", __func__, rfk.band);
|
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
|
_set_policy(btc, BTC_CXP_OFF_WL, __func__);
|
|
#if 0
|
if (rfk.band == BAND_ON_24G) {
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
|
_set_policy(btc, BTC_CXP_OFF_WL, __func__);
|
} else {
|
_set_ant(btc, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
|
_set_policy(btc, BTC_CXP_OFF_EQ0, __func__);
|
}
|
#endif
|
}
|
|
void _action_common(struct btc_t *btc)
|
{
|
_set_halbb_btg_ctrl(btc);
|
_set_halmac_tx_limit(btc);
|
_set_bt_afh_info(btc);
|
_set_bt_rx_agc(btc); /* must call after _set_halbb_btg_ctrl */
|
_set_bt_slot_req(btc);
|
_set_bt_rx_scan_pri(btc);
|
_set_rf_trx_para(btc);
|
}
|
|
static void _action_by_bt(struct btc_t *btc)
|
{
|
struct btc_bt_info *bt = &btc->cx.bt;
|
struct btc_bt_link_info *bt_linfo = &bt->link_info;
|
struct btc_bt_hid_desc hid = bt_linfo->hid_desc;
|
struct btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
|
struct btc_bt_pan_desc pan = bt_linfo->pan_desc;
|
u8 profile_map = 0;
|
|
if (bt_linfo->hfp_desc.exist)
|
profile_map |= BTC_BT_HFP;
|
|
if (bt_linfo->hid_desc.exist)
|
profile_map |= BTC_BT_HID;
|
|
if (bt_linfo->a2dp_desc.exist)
|
profile_map |= BTC_BT_A2DP;
|
|
if (bt_linfo->pan_desc.exist)
|
profile_map |= BTC_BT_PAN;
|
|
switch (profile_map) {
|
case 0:
|
if (_check_freerun(btc))
|
_action_freerun(btc);
|
else if (a2dp.active || pan.active)
|
_action_bt_pan(btc);
|
else
|
_action_bt_idle(btc);
|
break;
|
case BTC_BT_HFP:
|
if (_check_freerun(btc))
|
_action_freerun(btc);
|
else
|
_action_bt_hfp(btc);
|
break;
|
case BTC_BT_HFP | BTC_BT_HID:
|
case BTC_BT_HID:
|
if (_check_freerun(btc))
|
_action_freerun(btc);
|
else
|
_action_bt_hid(btc);
|
break;
|
case BTC_BT_A2DP:
|
if (_check_freerun(btc))
|
_action_freerun(btc);
|
else if (a2dp.sink)
|
_action_bt_a2dpsink(btc);
|
else if (bt_linfo->multi_link.now && !hid.pair_cnt)
|
_action_bt_a2dp_pan(btc);
|
else
|
_action_bt_a2dp(btc);
|
break;
|
case BTC_BT_PAN:
|
_action_bt_pan(btc);
|
break;
|
case BTC_BT_A2DP | BTC_BT_HFP:
|
case BTC_BT_A2DP | BTC_BT_HID:
|
case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
|
if (_check_freerun(btc))
|
_action_freerun(btc);
|
else
|
_action_bt_a2dp_hid(btc);
|
break;
|
case BTC_BT_A2DP | BTC_BT_PAN:
|
_action_bt_a2dp_pan(btc);
|
break;
|
case BTC_BT_PAN | BTC_BT_HFP:
|
case BTC_BT_PAN | BTC_BT_HID:
|
case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
|
_action_bt_pan_hid(btc);
|
break;
|
case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
|
case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
|
default:
|
_action_bt_a2dp_pan_hid(btc);
|
break;
|
}
|
}
|
|
void _action_wl_2g_sta(struct btc_t *btc)
|
{
|
_action_by_bt(btc);
|
}
|
|
void _action_wl_scan(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
|
|
if (btc->hal->dbcc_en) {
|
if (wl_dinfo->real_band[HW_PHY_0] != BAND_ON_24G &&
|
wl_dinfo->real_band[HW_PHY_1] != BAND_ON_24G)
|
_action_wl_5g(btc);
|
else
|
_action_by_bt(btc);
|
} else {
|
if (wl->scan_info.band[HW_PHY_0] != BAND_ON_24G)
|
_action_wl_5g(btc);
|
else
|
_action_by_bt(btc);
|
}
|
}
|
|
void _action_wl_25g_mcc(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED)/* shared-antenna */ {
|
if (wl->status.map._4way)
|
policy_type = BTC_CXP_OFFE_WL;
|
else if (bt->link_info.status.map.connect == 0)
|
policy_type = BTC_CXP_OFFE_2GISOB;
|
else
|
policy_type = BTC_CXP_OFFE_2GBWISOB;
|
} else { /* dedicated-antenna */
|
policy_type = BTC_CXP_OFF_EQ0;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
void _action_wl_2g_mcc(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
|
if (wl->status.map._4way)
|
policy_type = BTC_CXP_OFFE_WL;
|
else if (bt->link_info.status.map.connect == 0)
|
policy_type = BTC_CXP_OFFE_2GISOB;
|
else
|
policy_type = BTC_CXP_OFFE_2GBWISOB;
|
} else { /* dedicated-antenna */
|
policy_type = BTC_CXP_OFF_EQ0;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
void _action_wl_2g_scc(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
struct btc_dm *dm = &btc->dm;
|
struct btc_wl_role_info *wl_rinfo = &wl->role_info;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
u32 dur;
|
|
if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) {
|
policy_type = BTC_CXP_OFF_EQ0;
|
goto exit;
|
}
|
|
/* shared-antenna */
|
switch(wl_rinfo->mrole_type) {
|
default:
|
#if 0
|
case BTC_WLMROLE_STA_GO:
|
case BTC_WLMROLE_STA_GO_NOA:
|
dm->wl_scc.null_role1 = PHL_RTYPE_STATION;
|
dm->wl_scc.null_role2 = PHL_RTYPE_NONE;
|
dm->wl_scc.ebt_null = 0;
|
policy_type = BTC_CXP_OFF_BWB1;
|
#endif
|
break;
|
case BTC_WLMROLE_STA_GC:
|
dm->wl_scc.null_role1 = PHL_RTYPE_STATION;
|
dm->wl_scc.null_role2 = PHL_RTYPE_P2P_GC;
|
dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
|
_action_by_bt(btc);
|
return;
|
case BTC_WLMROLE_STA_STA:
|
dm->wl_scc.null_role1 = PHL_RTYPE_STATION;
|
dm->wl_scc.null_role2 = PHL_RTYPE_STATION;
|
dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
|
_action_by_bt(btc);
|
return;
|
case BTC_WLMROLE_STA_GC_NOA:
|
case BTC_WLMROLE_STA_GO:
|
case BTC_WLMROLE_STA_GO_NOA:
|
dm->wl_scc.null_role1 = PHL_RTYPE_STATION;
|
dm->wl_scc.null_role2 = PHL_RTYPE_NONE;
|
dur = wl_rinfo->mrole_noa_duration;
|
|
if (wl->status.map._4way) {
|
dm->wl_scc.ebt_null = 0;
|
policy_type = BTC_CXP_OFFE_WL;
|
} else if (bt->link_info.status.map.connect == 0) {
|
dm->wl_scc.ebt_null = 0;
|
policy_type = BTC_CXP_OFFE_2GISOB;
|
} else if (bt->link_info.a2dp_desc.exist &&
|
dur < btc->bt_req_len) {
|
dm->wl_scc.ebt_null = 1; /* tx null at EBT */
|
policy_type = BTC_CXP_OFFE_2GBWMIXB2;
|
} else if (bt->link_info.a2dp_desc.exist ||
|
bt->link_info.pan_desc.exist) {
|
dm->wl_scc.ebt_null = 1; /* tx null at EBT */
|
policy_type = BTC_CXP_OFFE_2GBWISOB;
|
}else {
|
dm->wl_scc.ebt_null = 0;
|
policy_type = BTC_CXP_OFFE_2GBWISOB;
|
}
|
|
break;
|
}
|
|
exit:
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
void _action_wl_2g_ap(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
/* Todo:if client issue Null-P, ap should follow Null/Null-P slot */
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
|
if (wl->status.map._4way)
|
policy_type = BTC_CXP_OFFE_WL;
|
else if (bt->link_info.status.map.connect == 0)
|
policy_type = BTC_CXP_OFFE_2GISOB;
|
else
|
policy_type = BTC_CXP_OFFE_2GBWISOB;
|
} else {/* dedicated-antenna */
|
policy_type = BTC_CXP_OFF_EQ0;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
void _action_wl_2g_go(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
|
if (wl->status.map._4way)
|
policy_type = BTC_CXP_OFFE_WL;
|
else if (bt->link_info.status.map.connect == 0)
|
policy_type = BTC_CXP_OFFE_2GISOB;
|
else
|
policy_type = BTC_CXP_OFFE_2GBWISOB;
|
} else { /* dedicated-antenna */
|
policy_type = BTC_CXP_OFF_EQ0;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
void _action_wl_2g_gc(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
struct btc_wl_role_info *wl_rinfo = &wl->role_info;
|
u8 noa = 0, pid = 0;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
u32 noa_duration = 0;
|
|
pid = _get_wl_role_idx(btc, PHL_RTYPE_P2P_GC);
|
|
if (pid < MAX_WIFI_ROLE_NUMBER) {
|
noa = wl_rinfo->active_role[pid].noa;
|
noa_duration = wl_rinfo->active_role[pid].noa_duration;
|
}
|
/* Check GC, GC+NOA */
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
|
if (!noa) { /* Gc without NOA */
|
_action_by_bt(btc);
|
return;
|
} else { /* Gc with NOA */
|
if (wl->status.map._4way)
|
policy_type = BTC_CXP_OFFE_WL;
|
else if (bt->link_info.status.map.connect == 0)
|
policy_type = BTC_CXP_OFFE_2GISOB;
|
else if (bt->link_info.a2dp_desc.exist &&
|
noa_duration < btc->bt_req_len)
|
policy_type = BTC_CXP_OFFE_2GBWMIXB;
|
else
|
policy_type = BTC_CXP_OFFE_2GBWISOB;
|
}
|
} else {/* dedicated-antenna */
|
policy_type = BTC_CXP_OFF_EQ0;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
void _action_wl_2g_nan(struct btc_t *btc)
|
{
|
struct btc_wl_info *wl = &btc->cx.wl;
|
struct btc_bt_info *bt = &btc->cx.bt;
|
u16 policy_type = BTC_CXP_OFF_BT;
|
|
if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
|
if (wl->status.map._4way)
|
policy_type = BTC_CXP_OFFE_WL;
|
else if (bt->link_info.status.map.connect == 0)
|
policy_type = BTC_CXP_OFFE_2GISOB;
|
else
|
policy_type = BTC_CXP_OFFE_2GBWISOB;
|
} else { /* dedicated-antenna */
|
policy_type = BTC_CXP_OFF_EQ0;
|
}
|
|
_set_ant(btc, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
|
_set_policy(btc, policy_type, __func__);
|
}
|
|
#endif
|