android13/external/wifi_driver/rtl8852be/phl/hal_g6/hal_sound.c

1026 lines
32 KiB
C

/******************************************************************************
*
* 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_SOUND_C_
#include "hal_headers.h"
struct csi_rpt_na {
u8 nr;
u8 nc;
u8 na;
};
#define CSI_NA_MATRIX_SIZE 35
static const struct csi_rpt_na csi_na[CSI_NA_MATRIX_SIZE] =
{
{2, 1, 2}, {2, 2, 2},
{3, 1, 4}, {3, 2, 6}, {3, 3, 6},
{4, 1, 6}, {4, 2, 10}, {4, 3, 12}, {4, 4, 12},
{5, 1, 8}, {5, 2, 14}, {5, 3, 18}, {5, 4, 20}, {5, 5, 20},
{6, 1, 10}, {6, 2, 18}, {6, 3, 24}, {6, 4, 28}, {6, 5, 30},
{6, 6, 30},
{7, 1, 12}, {7, 2, 22}, {7, 3, 30}, {7, 4, 36},
{7, 5, 40}, {7, 6, 42}, {7, 7, 42},
{8, 1, 14}, {8, 2, 26}, {8, 3, 36}, {8, 4, 55},
{8, 5, 50}, {8, 6, 54}, {8, 7, 56}, {8, 8, 56}
};
u32 _cal_he_csi_size(u8 mu, enum channel_width bw, u8 nr, u8 nc, u8 ng, u8 cb)
{
u8 na = 0;
u8 ns = 0;
u8 i = 0;
u32 csi_size = 0;
u8 cb_s = 0;
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
"%s : mu(%d) ; bw(%d) ; nr(%d) ; nc(%d), ng(%d), cb(%d)\n",
__func__, mu, bw, nr, nc, ng ,cb);
do {
if (CHANNEL_WIDTH_80 == bw)
ns = (ng == 4) ? 250 : 64;
else if(CHANNEL_WIDTH_40 == bw)
ns = (ng == 4) ? 122 : 32;
else if(CHANNEL_WIDTH_20 == bw)
ns = (ng == 4) ? 64 : 20;
else
break;
for (i = 0; i < CSI_NA_MATRIX_SIZE; i++) {
if ((nr == csi_na[i].nr) && (nc ==csi_na[i].nc)) {
na = csi_na[i].na;
break;
}
}
if (na == 0)
break;
if (cb) {
if(mu)
cb_s = 8;
else
cb_s = 5;
} else {
if(mu)
cb_s = 6;
else
cb_s = 3;
}
} while(0);
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
"%s : na %d ; ns %d ; cb_s %d",__func__, na, ns, cb_s);
if ((0 != na) && (0 != ns) && (0 != cb_s)) {
csi_size = ((8 * (u32)nc) +
((u32)na * (u32)cb_s * (u32)ns)) / 8;
if(mu)
csi_size += (4 * (u32)nc * (u32)ns) / 8;
}
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
"%s : expected he csi report size = %d byte",
__func__, csi_size);
return csi_size;
}
u32 _cal_he_cqi_only_rpt_size(enum channel_width bw, u8 nc)
{
u32 ret = 0;
if (CHANNEL_WIDTH_80 == bw)
ret = (u32)nc * 37;
else if(CHANNEL_WIDTH_40 == bw)
ret = (u32)nc * 18;
else if(CHANNEL_WIDTH_20 == bw)
ret = (u32)nc * 9;
return ret;
}
/*1. BF Resource Related*/
u8 _get_bw_ru_end_idx(enum channel_width bw) {
u8 ru_end_idx = 0;
switch (bw) {
case CHANNEL_WIDTH_20:
ru_end_idx = HAL_NPDA_RU_IDX_END_20MHZ;
break;
case CHANNEL_WIDTH_40:
ru_end_idx = HAL_NPDA_RU_IDX_END_40MHZ;
break;
case CHANNEL_WIDTH_80:
ru_end_idx = HAL_NPDA_RU_IDX_END_80MHZ;
break;
case CHANNEL_WIDTH_160:
case CHANNEL_WIDTH_80_80:
ru_end_idx = HAL_NPDA_RU_IDX_END_160MHZ;
default:
break;
}
return ru_end_idx;
}
void _hal_snd_set_default_var(struct hal_snd_obj *snd_obj)
{
snd_obj->ndpa_xpara.bw = CHANNEL_WIDTH_20;
snd_obj->ndpa_xpara.rate = RTW_DATA_RATE_OFDM6;
snd_obj->ndpa_xpara.gi_ltf = RTW_GILTF_LGI_4XHE32;
snd_obj->ndpa_xpara.stbc = 0;
snd_obj->ndpa_xpara.ldpc = 0;
snd_obj->bfrp_xpara.bw = CHANNEL_WIDTH_20;
snd_obj->bfrp_xpara.rate = RTW_DATA_RATE_OFDM6;
snd_obj->bfrp_xpara.gi_ltf = RTW_GILTF_LGI_4XHE32;
snd_obj->bfrp_xpara.stbc = 0;
snd_obj->bfrp_xpara.ldpc = 0;
}
enum rtw_hal_status
hal_snd_obj_init(void *hal)
{
enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct rtw_hal_com_t *hal_com = hal_info->hal_com;
struct hal_snd_obj *snd_obj = NULL;
do {
hal_com->snd_obj = _os_mem_alloc(hal_to_drvpriv(hal_info),
sizeof(struct hal_snd_obj));
if (NULL == hal_com->snd_obj) {
break;
}
snd_obj = hal_com->snd_obj;
/* preset hal sounding default values */
_hal_snd_set_default_var(snd_obj);
hstatus = RTW_HAL_STATUS_SUCCESS;
} while (0);
return hstatus;
}
enum rtw_hal_status
hal_snd_obj_deinit(void *hal)
{
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct rtw_hal_com_t *hal_com = hal_info->hal_com;
do {
if (hal_com->snd_obj == NULL)
break;
_os_mem_free(hal_to_drvpriv(hal_info), hal_com->snd_obj,
sizeof(struct hal_snd_obj));
hal_com->snd_obj = NULL;
} while (0);
return hstatus;
}
/**
* rtw_hal_snd_release_proc_sta_res
* free the resource for a STA used in sounding process
* input:
* @hal: (struct hal_info_t *)
* @sta: (struct rtw_phl_stainfo_t *)
**/
enum rtw_hal_status
rtw_hal_snd_release_proc_sta_res(void *hal, struct rtw_phl_stainfo_t *sta)
{
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct rtw_hal_stainfo_t *hal_sta = sta->hal_sta;
do {
if (hal_sta->bf_entry != NULL) {
hal_status = hal_bf_release_target_bf_entry(
hal_info, hal_sta->bf_entry);
}
if (hal_is_csi_buf_valid(hal_info, &hal_sta->bf_csi_buf)) {
hal_status = hal_csi_release_csi_buf(
hal_info, &hal_sta->bf_csi_buf);
}
if (hal_is_csi_buf_valid(hal_info, &hal_sta->bf_csi_buf_swap)) {
hal_status = hal_csi_release_csi_buf(
hal_info, &hal_sta->bf_csi_buf_swap);
}
} while(0);
return hal_status;
}
/**
* rtw_hal_snd_query_proc_sta_res
* input:
* @hal: hal_info
* @sta: rtw_phl_stainfo_t
* @mu: is this MU-MIMO STA resource request
* @bw: enum channel_width sounding bandwidth
**/
enum rtw_hal_status
rtw_hal_snd_query_proc_sta_res(
void *hal,
struct rtw_phl_stainfo_t *sta,
bool mu,
enum channel_width bw,
bool en_swap)
{
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct rtw_hal_stainfo_t *hal_sta = sta->hal_sta;
do {
if (hal_sta->bf_entry != NULL) {
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "[WARNING] sta->bf_entry != NULL\n");
/* TODO:Shall Release First ?*/
/* rtw_hal_snd_release_proc_sta_res(hal, sta); */
}
hal_sta->bf_entry =
(void *)hal_bf_query_idle_bf_entry(hal_info, mu);
if (hal_sta->bf_entry == NULL)
break;
hal_status = hal_csi_query_idle_csi_buf(
hal_info, mu, bw, &hal_sta->bf_csi_buf);
if (hal_status != RTW_HAL_STATUS_SUCCESS)
break;
if (mu && en_swap) {
hal_status = hal_csi_query_idle_csi_buf(
hal_info, mu, bw, &hal_sta->bf_csi_buf_swap);
}
if (hal_status == RTW_HAL_STATUS_FAILURE) {
PHL_INFO("Cannot Enable Swap Mode! Because of the CSI resource is not enougth.\n");
break;
}
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "sta->bf_csi_buf 0x%x \n",
hal_sta->bf_csi_buf);
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "sta->bf_csi_buf_swap 0x%x \n",
hal_sta->bf_csi_buf_swap);
/* Set STA-INFO info to BF Entry */
hal_status = hal_bf_cfg_swbf_entry(sta, en_swap);
} while (0);
if (hal_status != RTW_HAL_STATUS_SUCCESS) {
PHL_INFO("rtw_hal_snd_query_proc_sta_res FAIL \n");
rtw_hal_snd_release_proc_sta_res(hal, sta);
}
return hal_status;
}
/**
* rtw_hal_snd_proc_pre_cfg_sta
* hw preconfiguration for a sounding sta
* input:
* @hal: hal_info
* @sta: (struct rtw_phl_stainfo_t *)
**/
enum rtw_hal_status
rtw_hal_snd_proc_pre_cfg_sta(
void *hal,
struct rtw_phl_stainfo_t *sta)
{
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct rtw_hal_stainfo_t *hal_sta = sta->hal_sta;
/* 1. MAC HW BF Entry Settings */
hal_status = hal_bf_set_entry_hwcfg(
hal_info, hal_sta->bf_entry);
/* 2. Add other HAL setting here */
/*TODO:*/
return hal_status;
}
/**
* rtw_hal_snd_proc_post_cfg
* hw/fw post configuration for a sounding event
* input:
* @hal: hal_info
**/
enum rtw_hal_status
rtw_hal_snd_proc_post_cfg(void *hal, bool he, bool mu, bool en_fixed_mode)
{
enum rtw_hal_status hal_status = RTW_HAL_STATUS_SUCCESS;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct hal_mu_score_tbl *hal_score_table = &hal_info->hal_com->bb_mu_score_tbl;
if (mu) {
/*1. MU Score Board */
hal_status = rtw_hal_mac_ax_set_mu_table_whole(
hal_info->mac, hal_score_table);
/*2. (optional) MU Fixed Mode */
if (en_fixed_mode)
hal_status = rtw_hal_bf_set_fix_mode(hal, mu, he);
}
return hal_status;
}
/**
* rtw_hal_snd_proc_post_cfg_gid
* hw/fw post configuration for a vht/he gid
* input:
* @hal: hal_info
* @gid: wifi protolcol gid (PLCP) for configuration
* @ba_info: pointer of struct rtw_hal_muba_info
**/
enum rtw_hal_status
rtw_hal_snd_proc_post_cfg_gid(void *hal, u8 gid, void *ba_info)
{
enum rtw_hal_status hal_status = RTW_HAL_STATUS_SUCCESS;
/*
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct rtw_hal_muba_info *hal_ba_info = (struct rtw_hal_muba_info *)ba_info;
*/
/*TODO:*/
/*1. MU BAR Table : Table ID = GID, GID = STA-x + sSTA-y*/
return hal_status;
}
/**
* rtw_hal_snd_proc_post_cfg_sta
* hw/fw post configuration for a single sounding sta
* input:
* @hal: hal_info
* @sta: (struct rtw_phl_stainfo_t *)
**/
enum rtw_hal_status
rtw_hal_snd_proc_post_cfg_sta(
void *hal,
struct rtw_phl_stainfo_t *sta,
bool mu)
{
enum rtw_hal_status hal_status = RTW_HAL_STATUS_SUCCESS;
/* MAC/FW Settings */
if (mu) {
/*1. FW MU STA Update */
hal_status = hal_bf_set_mu_sta_fw(hal, sta);
/*2. MU Score Board */
/* mac->mac_set_mu_table_single_sta */
}
/* BB/FW Settings */
/*TODO:*/
/* 2. Add other setting here */
/*TODO:*/
return hal_status;
}
/**
* rtw_hal_snd_mac_ctrl
* control sounding process : pause or start.
* @hal: hal_info
* @band: band0 / band1
* @ctrl: 0 = pause souning / 1 = start sounding
**/
enum rtw_hal_status
rtw_hal_snd_mac_ctrl(void *hal, u8 band, u8 ctrl)
{
enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
hstatus = rtw_hal_mac_ax_hw_snd_control(hal_info->mac, band, ctrl);
return hstatus;
}
/**
* rtw_hal_snd_chk_bf_res
* check the sta's sounding resource is enough for sounding
* input :
* @hal: hal_info
* @sta: (struct rtw_hal_stainfo_t *)
* @mu: true = mu / false = su
* @bw: enum channel_width
* return :
* @hstatus: RTW_HAL_STATUS_FAILURE = need release and query bf entry and CSI buffer
* RTW_HAL_STATUS_SUCCESS = STA's BF Entry and CSI Buffer is same to condition.
**/
enum rtw_hal_status
rtw_hal_snd_chk_bf_res(void *hal, struct rtw_phl_stainfo_t *sta,
bool mu, enum channel_width bw)
{
enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
struct rtw_hal_stainfo_t *hal_sta = sta->hal_sta;
do {
if (sta == NULL)
break;
if (false == rtw_hal_bf_chk_bf_type(hal, sta, mu))
break;
if (mu != rtw_hal_get_csi_buf_type(&hal_sta->bf_csi_buf))
break;
if (bw != rtw_hal_get_csi_buf_bw(&hal_sta->bf_csi_buf))
break;
hstatus = RTW_HAL_STATUS_SUCCESS;
} while (0);
return hstatus;
}
/**
* rtw_hal_snd_polling_snd_sts
* update the sta's sounding status into sta->hal_sta->bf_entry->bfee
* input :
* @hal: hal_info
* @sta: (struct rtw_hal_stainfo_t *)
**/
void
rtw_hal_snd_polling_snd_sts(void *hal, struct rtw_phl_stainfo_t *sta)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
do {
if (sta == NULL)
break;
hal_bf_update_entry_snd_sts(hal_info, sta->hal_sta->bf_entry);
} while (0);
}
/* SND H2C CMD related functions */
void
rtw_hal_snd_ndpa_sta_info_vht(struct rtw_phl_stainfo_t *psta_info,
u32 *ndpa, u8 mu)
{
struct hal_vht_ndpa_sta_info *ndpa_sta =
(struct hal_vht_ndpa_sta_info *)ndpa;
if (PHL_RTYPE_STATION == psta_info->wrole->type)
ndpa_sta->aid12 = 0; /* Target is an AP, AID = 0 */
else
ndpa_sta->aid12 = psta_info->aid;
ndpa_sta->feedback_type = (mu == 0) ? HAL_NPDA_AC_SU : HAL_NPDA_AC_MU;
/* Nc shall alwary <= Nr */
if (psta_info->asoc_cap.max_nc >
psta_info->wrole->proto_role_cap.num_snd_dim) {
ndpa_sta->nc = psta_info->wrole->proto_role_cap.num_snd_dim;
} else {
ndpa_sta->nc = psta_info->asoc_cap.max_nc;
}
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "vht ndpa_sta aid12 0x%x ; fb 0x%x ; nc 0x%x\n",
ndpa_sta->aid12, ndpa_sta->feedback_type, ndpa_sta->nc);
}
void
rtw_hal_snd_ndpa_sta_info_he(struct rtw_phl_stainfo_t *psta_info,
u32 *ndpa, enum channel_width bw, u8 fb_type)
{
struct hal_he_ndpa_sta_info *ndpa_sta =
(struct hal_he_ndpa_sta_info *)ndpa;
u16 ru_start = HAL_NPDA_RU_IDX_START;
u16 ru_end = _get_bw_ru_end_idx(bw);
if (PHL_RTYPE_STATION == psta_info->wrole->type)
ndpa_sta->aid = 0; /* Target is and AP, AID = 0 */
else
ndpa_sta->aid = (psta_info->aid&0x7FF);
ndpa_sta->bw = ((ru_start&0x7F) << 0) | ((ru_end&0x7F) << 7);
if (0 == fb_type) {
ndpa_sta->fb_ng = psta_info->asoc_cap.ng_16_su_fb ?
HAL_NDPA_AX_FB_SU_NG_16 : HAL_NDPA_AX_FB_SU_NG_4;
ndpa_sta->cb = psta_info->asoc_cap.cb_sz_su_fb ?
HAL_NPDA_AX_CB_SU42_MU75 : HAL_NPDA_AX_CB_SU64_MU97;
} else if (1 == fb_type) {
ndpa_sta->fb_ng = psta_info->asoc_cap.ng_16_mu_fb ?
HAL_NDPA_AX_FB_MU_NG_16 : HAL_NDPA_AX_FB_MU_NG_4;
ndpa_sta->cb = psta_info->asoc_cap.cb_sz_mu_fb ?
HAL_NPDA_AX_CB_SU42_MU75 : HAL_NPDA_AX_CB_SU64_MU97;
} else {
ndpa_sta->fb_ng = HAL_NDPA_AX_FB_CQI;
ndpa_sta->cb = 1;
}
ndpa_sta->disambiguation = 1;
/* Nc shall alwary <= Nr */
if (psta_info->asoc_cap.max_nc >
psta_info->wrole->proto_role_cap.num_snd_dim) {
ndpa_sta->nc = psta_info->wrole->proto_role_cap.num_snd_dim;
} else {
ndpa_sta->nc = psta_info->asoc_cap.max_nc;
}
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "HE NDPA : aid 0x%x fb_ng 0x%x cb 0x%x nc 0x%x \n",
ndpa_sta->aid, ndpa_sta->fb_ng, ndpa_sta->cb, ndpa_sta->nc);
}
/**
* rtw_hal_snd_set_fw_cmd_dialogtkn()
* Set cmd dialog token value in NDPA
* input
* @he: is NDPA HE or not(VHT).
* @token: dialog token value.
**/
void rtw_hal_snd_set_fw_cmd_dialogtkn(void *hal, u8 *buf, u8 he, u8 token)
{
struct hal_ax_fwcmd_snd *cmd = (struct hal_ax_fwcmd_snd *)buf;
cmd->ndpa.snd_dialog.he = he;
cmd->ndpa.snd_dialog.token = token;
}
/**
* rtw_hal_snd_vht_fwcmd_su()
* Prepared VHT SU Sounding Fw Cmd.
* @hal:
* @buf: (struct hal_ax_fwcmd_snd *) cmd buffer pointer.
* @psta: (struct rtw_phl_stainfo_t *) STA to be sounding.
* @npda_sta: NPDA sta_info value
**/
void rtw_hal_snd_vht_fwcmd_su(void *hal, u8 *buf, enum channel_width bw,
struct rtw_phl_stainfo_t *psta, u32 *npda_sta)
{
struct hal_ax_fwcmd_snd *cmd = (struct hal_ax_fwcmd_snd *)buf;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct hal_snd_obj *snd_obj =
(struct hal_snd_obj *)hal_info->hal_com->snd_obj;
u8 i = 0;
cmd->frame_ex_type = HAL_FEXG_TYPE_AC_SU;
cmd->macid[0] = psta->macid;
cmd->ndpa.common.frame_ctl = HAL_SND_VHT_NDPA_FRM_CTRL; /*TODO*/
for (i = 0; i < 6;i++) {
cmd->ndpa.common.addr1[i] = psta->mac_addr[i]; /* NDPA-RA*/
cmd->ndpa.common.addr2[i] = psta->wrole->mac_addr[i]; /* NDPA-TA*/
}
cmd->ndpa.common.duration = 100;
cmd->ndpa.ndpa_sta_info[0] = *npda_sta;
/* NDPA WD */
cmd->wd[0].txpktsize = 21;/* 2 + 2 + 6 + 6 + 1 + 4, NO FCS */
cmd->wd[0].ndpa_duration = 100;
cmd->wd[0].disdatafb = 1;
cmd->wd[0].datarate = snd_obj->ndpa_xpara.rate;
cmd->wd[0].data_bw = snd_obj->ndpa_xpara.bw;
cmd->wd[0].macid = psta->macid;
cmd->wd[0].gi_ltf = snd_obj->ndpa_xpara.gi_ltf;
cmd->wd[0].data_stbc = snd_obj->ndpa_xpara.stbc;
cmd->wd[0].data_ldpc = snd_obj->ndpa_xpara.ldpc;
cmd->wd[0].sifs_tx = 1;
cmd->wd[0].snd_pkt_sel = HAL_SND_PKT_SEL_UST_NDPA;/* unicast ndpa */
cmd->wd[0].ndpa = HAL_SND_PKT_NDPA_VHT;
/* NDP WD */
cmd->wd[1].disdatafb = 1;
if (1 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_VHT_NSS2_MCS0;
else if (2 ==psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_VHT_NSS3_MCS0;
else if (3 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_VHT_NSS4_MCS0;
else
cmd->wd[1].datarate = RTW_DATA_RATE_VHT_NSS2_MCS0;
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "psta->asoc_cap.nss_rx = 0x%x\n", psta->asoc_cap.nss_rx);
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "cmd->wd[1].datarate = 0x%x\n", cmd->wd[1].datarate);
cmd->wd[1].data_bw = bw;
cmd->wd[1].macid = psta->macid;
cmd->wd[1].gi_ltf = RTW_GILTF_LGI_4XHE32;
cmd->wd[1].sifs_tx = 0;
cmd->wd[1].snd_pkt_sel = HAL_SND_PKT_SEL_LAST_NDP;
cmd->wd[1].ndpa = HAL_SND_PKT_NDPA_VHT;
}
void rtw_hal_snd_vht_fwcmd_mu_add_sta(void *hal, u8 *buf, u32 *ndpa_sta,
struct rtw_phl_stainfo_t *sta,
u8 ndpa_idx, u8 last)
{
struct hal_ax_fwcmd_snd *cmd = (struct hal_ax_fwcmd_snd *)buf;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct hal_snd_obj *snd_obj =
(struct hal_snd_obj *)hal_info->hal_com->snd_obj;
u8 i = 0;
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "==> rtw_hal_snd_vht_fwcmd_mu_add_sta\n");
if (ndpa_idx >= HAL_MAX_VHT_SND_STA_NUM)
return;
cmd->macid[ndpa_idx] = sta->macid;
/* NDPA sta_info*/
cmd->ndpa.ndpa_sta_info[ndpa_idx] = *ndpa_sta;
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "mac id 0x%x ; ndpa sta_info 0x%x\n",
cmd->macid[ndpa_idx], cmd->ndpa.ndpa_sta_info[ndpa_idx]);
/* VHT BFRP */
cmd->bfrp.hdr[ndpa_idx - 1].frame_ctl = HAL_SND_VHT_BFRP_FRM_CTRL;
cmd->bfrp.hdr[ndpa_idx - 1].duration = 100;
for (i = 0; i < 6; i++) {
cmd->bfrp.hdr[ndpa_idx - 1].addr1[i] = sta->mac_addr[i]; /* NDPA-RA = Broadcast*/
cmd->bfrp.hdr[ndpa_idx - 1].addr2[i] = sta->wrole->mac_addr[i]; /* NDPA-TA*/
}
cmd->bfrp.vht_para[ndpa_idx - 1].rexmit_bmp = 0;
/*BFRP WD*/
cmd->wd[1 + ndpa_idx].txpktsize = 17; /* 2 + 2 + 6 + 6 + 1 */
cmd->wd[1 + ndpa_idx].ndpa_duration = 100;
cmd->wd[1 + ndpa_idx].datarate = snd_obj->bfrp_xpara.rate;
cmd->wd[1 + ndpa_idx].data_ldpc = snd_obj->bfrp_xpara.ldpc;
cmd->wd[1 + ndpa_idx].data_stbc = snd_obj->bfrp_xpara.stbc;
cmd->wd[1 + ndpa_idx].macid = sta->macid;
cmd->wd[1 + ndpa_idx].data_bw = snd_obj->bfrp_xpara.bw;
cmd->wd[1 + ndpa_idx].gi_ltf = snd_obj->bfrp_xpara.gi_ltf;
cmd->wd[1 + ndpa_idx].disdatafb = 1;
if(last) {
cmd->wd[1 + ndpa_idx].sifs_tx = 0;
cmd->wd[1 + ndpa_idx].snd_pkt_sel = HAL_SND_PKT_SEL_LAST_BFRP;/* Final BFRP */
} else {
cmd->wd[1 + ndpa_idx].sifs_tx = 1;
cmd->wd[1 + ndpa_idx].snd_pkt_sel = HAL_SND_PKT_SEL_MID_BFRP;
}
cmd->wd[1 + ndpa_idx].ndpa = HAL_SND_PKT_NDPA_VHT;
}
void rtw_hal_snd_vht_fwcmd_mu_pri(void *hal, u8 *buf, enum channel_width bw,
struct rtw_phl_stainfo_t *psta, u8 sta_nr, u32 *ndpa_sta)
{
struct hal_ax_fwcmd_snd *cmd = (struct hal_ax_fwcmd_snd *)buf;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct hal_snd_obj *snd_obj =
(struct hal_snd_obj *)hal_info->hal_com->snd_obj;
u8 i = 0;
if (sta_nr == 4)
cmd->frame_ex_type = HAL_FEXG_TYPE_AC_MU_3;
else if(sta_nr == 3)
cmd->frame_ex_type = HAL_FEXG_TYPE_AC_MU_2;
else if(sta_nr == 2)
cmd->frame_ex_type = HAL_FEXG_TYPE_AC_MU_1;
else
PHL_INFO("rtw_hal_snd_vht_fwcmd_mu_pri : ERROR!!!!!!!!!!!!!!!");
cmd->macid[0] = psta->macid;
/* NDPA */
cmd->ndpa.common.frame_ctl = HAL_SND_VHT_NDPA_FRM_CTRL;
for (i = 0; i < 6;i++) {
/**
* Addr1: In VHT Case, Fill User_0's MAC Address to match BF Entry,
* HW will auto re-fill to Broadcast Address
**/
cmd->ndpa.common.addr1[i] = psta->mac_addr[i];
cmd->ndpa.common.addr2[i] = psta->wrole->mac_addr[i]; /* NDPA-TA*/
}
cmd->ndpa.common.duration = 150;/*TODO:*/
/* primary sta ndpa sta_info*/
cmd->ndpa.ndpa_sta_info[0] = *ndpa_sta;
/* VHT BFRP ==> by STA */
/* NDPA WD */
cmd->wd[0].txpktsize = 17 + HAL_SND_VHT_NDPA_STA_SZ * sta_nr;/* 2 + 2 + 6 + 6 + 1 + 2, NO FCS */
cmd->wd[0].ndpa_duration = 150;
cmd->wd[0].disdatafb = 1;
cmd->wd[0].datarate = snd_obj->ndpa_xpara.rate;
cmd->wd[0].data_bw = snd_obj->ndpa_xpara.bw;
cmd->wd[0].data_ldpc = snd_obj->ndpa_xpara.ldpc;
cmd->wd[0].data_stbc = snd_obj->ndpa_xpara.stbc;
cmd->wd[0].macid = psta->macid;
cmd->wd[0].gi_ltf = snd_obj->ndpa_xpara.gi_ltf;
cmd->wd[0].sifs_tx = 1;
cmd->wd[0].snd_pkt_sel = HAL_SND_PKT_SEL_BST_NDPA;
cmd->wd[0].ndpa = HAL_SND_PKT_NDPA_VHT;
/* NDP WD */
cmd->wd[1].disdatafb = 1;
if (1 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_VHT_NSS2_MCS0;
else if (2 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_VHT_NSS3_MCS0;
else if (3 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_VHT_NSS4_MCS0;
else
cmd->wd[1].datarate = RTW_DATA_RATE_VHT_NSS2_MCS0;
cmd->wd[1].data_bw = bw;
cmd->wd[1].macid = psta->macid;
cmd->wd[1].gi_ltf = RTW_GILTF_LGI_4XHE32;
cmd->wd[1].sifs_tx = 1;
cmd->wd[1].snd_pkt_sel = HAL_SND_PKT_SEL_MID_NDP;/*Last NDP*/
cmd->wd[1].ndpa = HAL_SND_PKT_NDPA_VHT;
}
/* HE FW Command */
/**
* rtw_hal_snd_ax_fwcmd_su()
* fill the fw cmd for HE sounding type HE Non-TB : NDPA - NDP - CSI Report
*
**/
void rtw_hal_snd_ax_fwcmd_nontb(void *hal, u8 *buf, enum channel_width bw,
struct rtw_phl_stainfo_t *psta, u32 *npda_sta)
{
struct hal_ax_fwcmd_snd *cmd = (struct hal_ax_fwcmd_snd *)buf;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct hal_snd_obj *snd_obj =
(struct hal_snd_obj *)hal_info->hal_com->snd_obj;
u8 i = 0;
cmd->frame_ex_type = HAL_FEXG_TYPE_AX_SU;
cmd->macid[0] = psta->macid;
cmd->ndpa.common.frame_ctl = HAL_SND_HE_NDPA_FRM_CTRL;
for (i = 0; i < 6;i++) {
cmd->ndpa.common.addr1[i] = psta->mac_addr[i]; /* NDPA-RA*/
cmd->ndpa.common.addr2[i] = psta->wrole->mac_addr[i]; /* NDPA-TA*/
}
cmd->ndpa.common.duration = 100;
cmd->ndpa.ndpa_sta_info[0] = *npda_sta;
/* NDPA WD */
cmd->wd[0].txpktsize = 21;/* 2 + 2 + 6 + 6 + 1 + 4, NO FCS */
cmd->wd[0].ndpa_duration = 100;
cmd->wd[0].disdatafb = 1;
cmd->wd[0].datarate = snd_obj->ndpa_xpara.rate;
cmd->wd[0].data_bw = snd_obj->ndpa_xpara.bw;
cmd->wd[0].data_stbc = snd_obj->ndpa_xpara.stbc;
cmd->wd[0].data_ldpc = snd_obj->ndpa_xpara.ldpc;
cmd->wd[0].macid = psta->macid;
cmd->wd[0].gi_ltf = snd_obj->ndpa_xpara.gi_ltf;
cmd->wd[0].sifs_tx = 1;
cmd->wd[0].snd_pkt_sel = HAL_SND_PKT_SEL_UST_NDPA;/*unicast ndpa*/
cmd->wd[0].ndpa = HAL_SND_PKT_NDPA_HE;
/* NDP WD */
cmd->wd[1].disdatafb = 1;
if (1 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_HE_NSS2_MCS0;
else if (2 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_HE_NSS3_MCS0;
else if (3 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_HE_NSS4_MCS0;
else
cmd->wd[1].datarate = RTW_DATA_RATE_HE_NSS2_MCS0;
cmd->wd[1].data_bw = bw;
cmd->wd[1].macid = psta->macid;
cmd->wd[1].gi_ltf = RTW_GILTF_2XHE16; /* TODO: if psta->asoc_cap.ltf_gi support NDP 4XHE32;*/
cmd->wd[1].sifs_tx = 0;
cmd->wd[1].snd_pkt_sel = HAL_SND_PKT_SEL_LAST_NDP;
cmd->wd[1].ndpa = HAL_SND_PKT_NDPA_HE;
}
/**
* rtw_hal_snd_ax_fwcmd_tb_add_sta()
* fill fw cmd for HE sounding with TB case.
* shall call rtw_hal_snd_ax_fwcmd_tb_pri() first, and add STA by this api.
* Note that RU-Allocation shall dicide from phl caller,
* and shall avoid same with others
* function input:
* @hal:
* @buf: (struct hal_ax_fwcmd_snd *) command buf pointer.
* @ndpa_sta:
* @sta: (struct rtw_phl_stainfo_t *)
* @ru_idx: RU Allocation index;
* @ndpa_idx: 0-7 for 8852a
* @bfrp_idx: 0-1 for 8852a
* @bfrp_u_idx: 0-3 for 8852a
**/
void rtw_hal_snd_ax_fwcmd_tb_add_sta(void *hal, u8 *buf, u32 *ndpa_sta,
struct rtw_phl_stainfo_t *sta, u8 ru_idx,
u8 ndpa_idx, u8 bfrp_idx, u8 bfrp_u_idx)
{
struct hal_ax_fwcmd_snd *cmd = (struct hal_ax_fwcmd_snd *)buf;
struct hal_he_ndpa_sta_info *ndpa =
(struct hal_he_ndpa_sta_info *)ndpa_sta;
u8 mu = 0, ng = 4;
u32 rpt_size = 0;
if (ndpa_idx >= HAL_MAX_HE_SND_STA_NUM)
return;
if (bfrp_idx >= HAL_MAX_HE_BFRP_NUM)
return;
cmd->macid[ndpa_idx] = sta->macid;
/* NDPA sta_info*/
cmd->ndpa.ndpa_sta_info[ndpa_idx] = *ndpa_sta;
/* BFRP user_info */
cmd->bfrp.he_para[bfrp_idx].fbseg_rexmit_bmp[bfrp_u_idx] = 0;
cmd->bfrp.he_para[bfrp_idx].user[bfrp_u_idx].aid12 = sta->aid;
if (cmd->bfrp.he_para[bfrp_idx].common.ul_bw > CHANNEL_WIDTH_80) {
ru_idx = (ru_idx << 1) | BIT(0);
} else {
ru_idx = (ru_idx << 1) &(~BIT(0));
}
cmd->bfrp.he_para[bfrp_idx].user[bfrp_u_idx].ru_pos = ru_idx;
cmd->bfrp.he_para[bfrp_idx].user[bfrp_u_idx].ul_fec_code = 0;
cmd->bfrp.he_para[bfrp_idx].user[bfrp_u_idx].ul_mcs = 3;/* HE-MCS3, TODO: Default value of golden */
cmd->bfrp.he_para[bfrp_idx].user[bfrp_u_idx].ul_dcm = 0 ;
cmd->bfrp.he_para[bfrp_idx].user[bfrp_u_idx].ss_alloc = 0;/* 1SS, TODO: Default value of golden */
cmd->bfrp.he_para[bfrp_idx].user[bfrp_u_idx].ul_tgt_rssi =
(u8)(sta->hal_sta->rssi_stat.rssi >> 1);/*TODO: From Rx ST SU RSSI */
if (ndpa->fb_ng == HAL_NDPA_AX_FB_MU_NG_4) {
mu = 1;
ng = 4;
} else if (ndpa->fb_ng == HAL_NDPA_AX_FB_MU_NG_16) {
mu = 1;
ng = 16;
} else if (ndpa->fb_ng == HAL_NDPA_AX_FB_SU_NG_4) {
mu = 0;
ng = 4;
} else if (ndpa->fb_ng == HAL_NDPA_AX_FB_SU_NG_16) {
mu = 0;
ng = 4;
}
rpt_size = _cal_he_csi_size(mu, sta->chandef.bw,
(sta->wrole->proto_role_cap.num_snd_dim + 1),
((u8)ndpa->nc + 1), ng, (u8)ndpa->cb);
if (cmd->bfrp.he_para[bfrp_idx].f2p_info.csi_len_bfrp < (rpt_size/64))
cmd->bfrp.he_para[bfrp_idx].f2p_info.csi_len_bfrp =
(u16)(rpt_size / 64); /*unit 64 byte*/
}
void rtw_hal_snd_ax_fwcmd_tb_pri(void *hal, u8 *buf, enum channel_width bw,
struct rtw_phl_stainfo_t *psta, u8 sta_nr1, u8 sta_nr2)
{
struct hal_ax_fwcmd_snd *cmd = (struct hal_ax_fwcmd_snd *)buf;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
struct hal_snd_obj *snd_obj =
(struct hal_snd_obj *)hal_info->hal_com->snd_obj;
u8 i = 0;
u8 sta_nr = sta_nr1 + sta_nr2;
if (sta_nr2 != 0)
cmd->frame_ex_type = HAL_FEXG_TYPE_AX_MU_2;
else
cmd->frame_ex_type = HAL_FEXG_TYPE_AX_MU_1;
cmd->bfrp0_sta_nr = sta_nr1;
cmd->bfrp1_sta_nr = sta_nr2;
cmd->macid[0] = psta->macid;
/* NDPA */
cmd->ndpa.common.frame_ctl = HAL_SND_HE_NDPA_FRM_CTRL; /*TODO:*/
for (i = 0; i < 6;i++) {
cmd->ndpa.common.addr1[i] = 0xFF; /* NDPA-RA = Broadcast*/
cmd->ndpa.common.addr2[i] = psta->wrole->mac_addr[i]; /* NDPA-TA*/
/* BFRP - 1*/
cmd->bfrp.hdr[0].addr1[i] = 0xFF;
cmd->bfrp.hdr[0].addr2[i] = psta->wrole->mac_addr[i];
if (sta_nr2 != 0) {
/* BFRP - 2*/
cmd->bfrp.hdr[1].addr1[i] = 0xFF;
cmd->bfrp.hdr[1].addr2[i] = psta->wrole->mac_addr[i];
}
}
cmd->ndpa.common.duration = 150;/*TODO:*/
/*TODO: ndpa user info in other api */
/* BFRP #1 */
cmd->bfrp.hdr[0].frame_ctl = HAL_SND_HE_BFRP_FRM_CTRL; /* Trigger Frame */
cmd->bfrp.hdr[0].duration = 100;
cmd->bfrp.he_para[0].common.tgr_info = HAL_SND_TRIG_INFO_BFRP;/*BFRP*/
cmd->bfrp.he_para[0].common.ul_len = 0xFFF;/*TODO: LSIG Length : sw provide or fw calculate */
cmd->bfrp.he_para[0].common.more_tf = 0;
cmd->bfrp.he_para[0].common.cs_rqd = 1;
cmd->bfrp.he_para[0].common.ul_bw = bw;
cmd->bfrp.he_para[0].common.gi_ltf = RTW_TB_GILTF_4XHE32;/* 8852A Limitation of UL OFDMA */
cmd->bfrp.he_para[0].common.num_heltf = 0;/* TODO: Default value of golden */
cmd->bfrp.he_para[0].common.ul_pktext = 0;/* TODO: fw? hw? */
cmd->bfrp.he_para[0].common.ap_tx_pwr = 0x3C;/* TODO: Default value of golden */
/* F2P cmd parameters */
cmd->bfrp.he_para[0].f2p_info.tb_t_pe_bfrp = 2;
cmd->bfrp.he_para[0].f2p_info.tri_pad_bfrp = 2;
cmd->bfrp.he_para[0].f2p_info.ul_cqi_rpt_tri_bfrp = 0;
cmd->bfrp.he_para[0].f2p_info.rf_gain_idx_bfrp = 0;/* ?? */
cmd->bfrp.he_para[0].f2p_info.fix_gain_en_bfrp = 0;/* ?? */
if (sta_nr2) {
cmd->bfrp.hdr[1].frame_ctl = HAL_SND_HE_BFRP_FRM_CTRL; /* Trigger Frame */
cmd->bfrp.hdr[1].duration = 100;
cmd->bfrp.he_para[1].common.tgr_info = HAL_SND_TRIG_INFO_BFRP;/*BFRP*/
cmd->bfrp.he_para[1].common.ul_len = 0xFFF;/*TODO: LSIG Length : sw provide or fw calculate */
cmd->bfrp.he_para[1].common.more_tf = 0;
cmd->bfrp.he_para[1].common.cs_rqd = 1;
cmd->bfrp.he_para[1].common.ul_bw = bw;
cmd->bfrp.he_para[1].common.gi_ltf = RTW_TB_GILTF_4XHE32;/* 8852A Limitation of UL OFDMA */
cmd->bfrp.he_para[1].common.num_heltf = 0;/* TODO: Default value of golden */
cmd->bfrp.he_para[1].common.ul_pktext = 0;/* TODO: fw? hw? */
cmd->bfrp.he_para[1].common.ap_tx_pwr = 0x32;/* TODO: Default value of golden */
cmd->bfrp.he_para[1].f2p_info.tb_t_pe_bfrp = 2;
cmd->bfrp.he_para[1].f2p_info.tri_pad_bfrp = 2;
cmd->bfrp.he_para[1].f2p_info.ul_cqi_rpt_tri_bfrp = 0;
cmd->bfrp.he_para[1].f2p_info.rf_gain_idx_bfrp = 0;
cmd->bfrp.he_para[1].f2p_info.fix_gain_en_bfrp = 0;
}
/* NDPA WD */
cmd->wd[0].txpktsize = 17 + HAL_SND_HE_NDPA_STA_SZ * sta_nr;/* 2 + 2 + 6 + 6 + 1 + 4, NO FCS */
cmd->wd[0].ndpa_duration = 100;
cmd->wd[0].disdatafb = 1;
cmd->wd[0].datarate = snd_obj->ndpa_xpara.rate;
cmd->wd[0].data_bw = snd_obj->ndpa_xpara.bw;
cmd->wd[0].data_stbc = snd_obj->ndpa_xpara.stbc;
cmd->wd[0].data_ldpc = snd_obj->ndpa_xpara.ldpc;
cmd->wd[0].macid = psta->macid;
cmd->wd[0].gi_ltf = snd_obj->ndpa_xpara.gi_ltf;
cmd->wd[0].sifs_tx = 1;
cmd->wd[0].snd_pkt_sel = HAL_SND_PKT_SEL_BST_NDPA;
cmd->wd[0].ndpa = HAL_SND_PKT_NDPA_HE;
/* NDP WD */
cmd->wd[1].disdatafb = 1;
if (1 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_HE_NSS2_MCS0;
else if (2 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_HE_NSS3_MCS0;
else if(3 == psta->wrole->proto_role_cap.num_snd_dim)
cmd->wd[1].datarate = RTW_DATA_RATE_HE_NSS4_MCS0;
else
cmd->wd[1].datarate = RTW_DATA_RATE_HE_NSS2_MCS0;
cmd->wd[1].data_bw = bw;
cmd->wd[1].macid = psta->macid;
cmd->wd[1].gi_ltf = RTW_GILTF_2XHE16; /* TODO: if support 4x32 NDP */
cmd->wd[1].sifs_tx = 0;
cmd->wd[1].snd_pkt_sel = HAL_SND_PKT_SEL_MID_NDP;
cmd->wd[1].ndpa = HAL_SND_PKT_NDPA_HE;
/* BFRP #1 WD */
cmd->wd[2].txpktsize = 24 + HAL_SND_HE_BFRP_STA_SZ * sta_nr1; /* 2 + 2 + 6 + 6 + 8 + 5*N */
cmd->wd[2].ndpa_duration = 100;
cmd->wd[2].datarate = snd_obj->bfrp_xpara.rate;
//cmd->wd[2].macid
cmd->wd[2].data_bw = snd_obj->bfrp_xpara.bw;
cmd->wd[2].data_stbc = snd_obj->bfrp_xpara.stbc;
cmd->wd[2].data_ldpc = snd_obj->bfrp_xpara.ldpc;
cmd->wd[2].gi_ltf = snd_obj->bfrp_xpara.gi_ltf;
cmd->wd[2].disdatafb = 1;
if(sta_nr2) {
cmd->wd[2].sifs_tx = 1;
cmd->wd[2].snd_pkt_sel = HAL_SND_PKT_SEL_MID_BFRP;
} else {
cmd->wd[2].sifs_tx = 0;/* Final BFRP */
cmd->wd[2].snd_pkt_sel = HAL_SND_PKT_SEL_LAST_BFRP;
}
cmd->wd[2].ndpa = HAL_SND_PKT_NDPA_HE;
if (sta_nr2) {
cmd->wd[3].txpktsize = 24 + HAL_SND_HE_BFRP_STA_SZ * sta_nr2; /* 2 + 2 + 6 + 6 + 8 + 5*N */
cmd->wd[3].ndpa_duration = 100;
cmd->wd[3].datarate = snd_obj->bfrp_xpara.rate;
cmd->wd[3].data_bw = snd_obj->bfrp_xpara.bw;
cmd->wd[3].data_stbc = snd_obj->bfrp_xpara.stbc;
cmd->wd[3].data_ldpc = snd_obj->bfrp_xpara.ldpc;
cmd->wd[3].gi_ltf = snd_obj->bfrp_xpara.gi_ltf;
cmd->wd[3].disdatafb = 1;
cmd->wd[3].sifs_tx = 0;/* Final BFRP */
cmd->wd[3].snd_pkt_sel = HAL_SND_PKT_SEL_LAST_BFRP;
cmd->wd[3].ndpa = HAL_SND_PKT_NDPA_HE;
}
}
u8 *
rtw_hal_snd_prepare_snd_cmd(void *hal)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
u8 *buf = NULL;
buf = _os_mem_alloc(hal_to_drvpriv(hal_info),
sizeof(struct hal_ax_fwcmd_snd));
return buf;
}
enum rtw_hal_status
rtw_hal_snd_release_snd_cmd(void *hal, u8 *buf)
{
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
do {
if (buf == NULL)
break;
_os_mem_free(hal_to_drvpriv(hal_info), buf,
sizeof(struct hal_ax_fwcmd_snd));
} while (0);
return hstatus;
}
enum rtw_hal_status
rtw_hal_snd_send_fw_cmd(void *hal, u8 *cmd)
{
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "==> rtw_hal_snd_send_fw_cmd \n");
hstatus = hal_mac_ax_send_fw_snd(hal_info,
(struct hal_ax_fwcmd_snd *)cmd);
/*TODO: Dump CMD content */
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "<== rtw_hal_snd_send_fw_cmd \n");
return hstatus;
}