OSDN Git Service

Add rtl8812au driver version 5.2.6.2
[android-x86/external-kernel-drivers.git] / rtl8812au / hal / phydm / txbf / haltxbf8822b.c
diff --git a/rtl8812au/hal/phydm/txbf/haltxbf8822b.c b/rtl8812au/hal/phydm/txbf/haltxbf8822b.c
new file mode 100644 (file)
index 0000000..0f9c6ca
--- /dev/null
@@ -0,0 +1,793 @@
+/*============================================================*/
+/* Description:                                              */
+/*                                                           */
+/* This file is for 8814A TXBF mechanism                     */
+/*                                                           */
+/*============================================================*/
+
+#include "mp_precomp.h"
+#include "phydm_precomp.h"
+
+#if (RTL8822B_SUPPORT == 1)
+#if (BEAMFORMING_SUPPORT == 1)
+
+u8
+hal_txbf_8822b_get_ntx(
+       void                    *p_dm_void
+)
+{
+       struct PHY_DM_STRUCT    *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
+       u8                      ntx = 0;
+
+#if DEV_BUS_TYPE == RT_USB_INTERFACE
+       if (p_dm_odm->support_interface == ODM_ITRF_USB) {
+               if (*p_dm_odm->hub_usb_mode == 2) {/*USB3.0*/
+                       if (p_dm_odm->rf_type == ODM_4T4R)
+                               ntx = 3;
+                       else if (p_dm_odm->rf_type == ODM_3T3R)
+                               ntx = 2;
+                       else
+                               ntx = 1;
+               } else if (*p_dm_odm->hub_usb_mode == 1)        /*USB 2.0 always 2Tx*/
+                       ntx = 1;
+               else
+                       ntx = 1;
+       } else
+#endif
+       {
+               if (p_dm_odm->rf_type == ODM_4T4R)
+                       ntx = 3;
+               else if (p_dm_odm->rf_type == ODM_3T3R)
+                       ntx = 2;
+               else
+                       ntx = 1;
+       }
+
+       return ntx;
+
+}
+
+u8
+hal_txbf_8822b_get_nrx(
+       void                    *p_dm_void
+)
+{
+       struct PHY_DM_STRUCT    *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
+       u8                      nrx = 0;
+
+       if (p_dm_odm->rf_type == ODM_4T4R)
+               nrx = 3;
+       else if (p_dm_odm->rf_type == ODM_3T3R)
+               nrx = 2;
+       else if (p_dm_odm->rf_type == ODM_2T2R)
+               nrx = 1;
+       else if (p_dm_odm->rf_type == ODM_2T3R)
+               nrx = 2;
+       else if (p_dm_odm->rf_type == ODM_2T4R)
+               nrx = 3;
+       else if (p_dm_odm->rf_type == ODM_1T1R)
+               nrx = 0;
+       else if (p_dm_odm->rf_type == ODM_1T2R)
+               nrx = 1;
+       else
+               nrx = 0;
+
+       return nrx;
+
+}
+
+/***************SU & MU BFee Entry********************/
+void
+hal_txbf_8822b_rf_mode(
+       void                    *p_dm_void,
+       struct _RT_BEAMFORMING_INFO     *p_beamforming_info,
+       u8                                      idx
+)
+{
+}
+
+void
+hal_txbf_8822b_enter(
+       void                    *p_dm_void,
+       u8                              bfer_bfee_idx
+)
+{
+       struct PHY_DM_STRUCT    *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
+       u8                                      i = 0;
+       u8                                      bfer_idx = (bfer_bfee_idx & 0xF0) >> 4;
+       u8                                      bfee_idx = (bfer_bfee_idx & 0xF);
+       u16                                     csi_param = 0;
+       struct _RT_BEAMFORMING_INFO             *p_beamforming_info = &p_dm_odm->beamforming_info;
+       struct _RT_BEAMFORMEE_ENTRY     *p_beamformee_entry;
+       struct _RT_BEAMFORMER_ENTRY     *p_beamformer_entry;
+       u16                                     value16, sta_id = 0;
+       u8                                      nc_index = 0, nr_index = 0, grouping = 0, codebookinfo = 0, coefficientsize = 0;
+       u32                                     gid_valid, user_position_l, user_position_h;
+       u32                                     mu_reg[6] = {0x1684, 0x1686, 0x1688, 0x168a, 0x168c, 0x168e};
+       u8                                      u1b_tmp;
+       u32                                     u4b_tmp;
+
+       RT_DISP(FBEAM, FBEAM_FUN, ("%s: bfer_bfee_idx=%d, bfer_idx=%d, bfee_idx=%d\n", __func__, bfer_bfee_idx, bfer_idx, bfee_idx));
+
+       /*************SU BFer Entry Init*************/
+       if ((p_beamforming_info->beamformer_su_cnt > 0) && (bfer_idx < BEAMFORMER_ENTRY_NUM)) {
+               p_beamformer_entry = &p_beamforming_info->beamformer_entry[bfer_idx];
+               p_beamformer_entry->is_mu_ap = false;
+               /*Sounding protocol control*/
+               odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8822B, 0xDB);
+
+
+               for (i = 0; i < MAX_BEAMFORMER_SU; i++) {
+                       if ((p_beamforming_info->beamformer_su_reg_maping & BIT(i)) == 0) {
+                               p_beamforming_info->beamformer_su_reg_maping |= BIT(i);
+                               p_beamformer_entry->su_reg_index = i;
+                               break;
+                       }
+               }
+
+               /*MAC address/Partial AID of Beamformer*/
+               if (p_beamformer_entry->su_reg_index == 0) {
+                       for (i = 0; i < 6 ; i++)
+                               odm_write_1byte(p_dm_odm, (REG_ASSOCIATED_BFMER0_INFO_8822B + i), p_beamformer_entry->mac_addr[i]);
+               } else {
+                       for (i = 0; i < 6 ; i++)
+                               odm_write_1byte(p_dm_odm, (REG_ASSOCIATED_BFMER1_INFO_8822B + i), p_beamformer_entry->mac_addr[i]);
+               }
+
+               /*CSI report parameters of Beamformer*/
+               nc_index = hal_txbf_8822b_get_nrx(p_dm_odm);    /*for 8814A nrx = 3(4 ant), min=0(1 ant)*/
+               nr_index = p_beamformer_entry->num_of_sounding_dim;     /*0x718[7] = 1 use Nsts, 0x718[7] = 0 use reg setting. as Bfee, we use Nsts, so nr_index don't care*/
+
+               grouping = 0;
+
+               /*for ac = 1, for n = 3*/
+               if (p_beamformer_entry->beamform_entry_cap & BEAMFORMEE_CAP_VHT_SU)
+                       codebookinfo = 1;
+               else if (p_beamformer_entry->beamform_entry_cap & BEAMFORMEE_CAP_HT_EXPLICIT)
+                       codebookinfo = 3;
+
+               coefficientsize = 3;
+
+               csi_param = (u16)((coefficientsize << 10) | (codebookinfo << 8) | (grouping << 6) | (nr_index << 3) | (nc_index));
+
+               if (bfer_idx == 0)
+                       odm_write_2byte(p_dm_odm, REG_TX_CSI_RPT_PARAM_BW20_8822B, csi_param);
+               else
+                       odm_write_2byte(p_dm_odm, REG_TX_CSI_RPT_PARAM_BW20_8822B + 2, csi_param);
+               /*ndp_rx_standby_timer, 8814 need > 0x56, suggest from Dvaid*/
+               odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8822B + 3, 0x70);
+
+       }
+
+       /*************SU BFee Entry Init*************/
+       if ((p_beamforming_info->beamformee_su_cnt > 0) && (bfee_idx < BEAMFORMEE_ENTRY_NUM)) {
+               p_beamformee_entry = &p_beamforming_info->beamformee_entry[bfee_idx];
+               p_beamformee_entry->is_mu_sta = false;
+               hal_txbf_8822b_rf_mode(p_dm_odm, p_beamforming_info, bfee_idx);
+
+               if (phydm_acting_determine(p_dm_odm, phydm_acting_as_ibss))
+                       sta_id = p_beamformee_entry->mac_id;
+               else
+                       sta_id = p_beamformee_entry->p_aid;
+
+               for (i = 0; i < MAX_BEAMFORMEE_SU; i++) {
+                       if ((p_beamforming_info->beamformee_su_reg_maping & BIT(i)) == 0) {
+                               p_beamforming_info->beamformee_su_reg_maping |= BIT(i);
+                               p_beamformee_entry->su_reg_index = i;
+                               break;
+                       }
+               }
+
+               /*P_AID of Beamformee & enable NDPA transmission & enable NDPA interrupt*/
+               if (p_beamformee_entry->su_reg_index == 0) {
+                       odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8822B, sta_id);
+                       odm_write_1byte(p_dm_odm, REG_TXBF_CTRL_8822B + 3, odm_read_1byte(p_dm_odm, REG_TXBF_CTRL_8822B + 3) | BIT(4) | BIT(6) | BIT(7));
+               } else
+                       odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8822B + 2, sta_id | BIT(14) | BIT(15) | BIT(12));
+
+               /*CSI report parameters of Beamformee*/
+               if (p_beamformee_entry->su_reg_index == 0) {
+                       /*Get BIT24 & BIT25*/
+                       u8      tmp = odm_read_1byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8822B + 3) & 0x3;
+
+                       odm_write_1byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8822B + 3, tmp | 0x60);
+                       odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8822B, sta_id | BIT(9));
+               } else
+                       odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2, sta_id | 0xE200); /*Set BIT25*/
+
+               phydm_beamforming_notify(p_dm_odm);
+       }
+
+       /*************MU BFer Entry Init*************/
+       if ((p_beamforming_info->beamformer_mu_cnt > 0) && (bfer_idx < BEAMFORMER_ENTRY_NUM)) {
+               p_beamformer_entry = &p_beamforming_info->beamformer_entry[bfer_idx];
+               p_beamforming_info->mu_ap_index = bfer_idx;
+               p_beamformer_entry->is_mu_ap = true;
+               for (i = 0; i < 8; i++)
+                       p_beamformer_entry->gid_valid[i] = 0;
+               for (i = 0; i < 16; i++)
+                       p_beamformer_entry->user_position[i] = 0;
+
+               /*Sounding protocol control*/
+               odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8822B, 0xDB);
+
+               /* MAC address */
+               for (i = 0; i < 6 ; i++)
+                       odm_write_1byte(p_dm_odm, (REG_ASSOCIATED_BFMER0_INFO_8822B + i), p_beamformer_entry->mac_addr[i]);
+
+               /* Set partial AID */
+               odm_write_2byte(p_dm_odm, (REG_ASSOCIATED_BFMER0_INFO_8822B + 6), p_beamformer_entry->p_aid);
+
+               /* Fill our AID to 0x1680[11:0] and [13:12] = 2b'00, BF report segment select to 3895 bytes*/
+               u1b_tmp = odm_read_1byte(p_dm_odm, 0x1680);
+               u1b_tmp = (p_beamformer_entry->p_aid) & 0xFFF;
+               odm_write_1byte(p_dm_odm, 0x1680, u1b_tmp);
+
+               /* Set 80us for leaving ndp_rx_standby_state */
+               odm_write_1byte(p_dm_odm, 0x71B, 0x50);
+
+               /* Set 0x6A0[14] = 1 to accept action_no_ack */
+               u1b_tmp = odm_read_1byte(p_dm_odm, REG_RXFLTMAP0_8822B + 1);
+               u1b_tmp |= 0x40;
+               odm_write_1byte(p_dm_odm, REG_RXFLTMAP0_8822B + 1, u1b_tmp);
+               /* Set 0x6A2[5:4] = 1 to NDPA and BF report poll */
+               u1b_tmp = odm_read_1byte(p_dm_odm, REG_RXFLTMAP1_8822B);
+               u1b_tmp |= 0x30;
+               odm_write_1byte(p_dm_odm, REG_RXFLTMAP1_8822B, u1b_tmp);
+
+               /*CSI report parameters of Beamformer*/
+               nc_index = hal_txbf_8822b_get_nrx(p_dm_odm);    /* Depend on RF type */
+               nr_index = 1;   /*0x718[7] = 1 use Nsts, 0x718[7] = 0 use reg setting. as Bfee, we use Nsts, so nr_index don't care*/
+               grouping = 0; /*no grouping*/
+               codebookinfo = 1; /*7 bit for psi, 9 bit for phi*/
+               coefficientsize = 0; /*This is nothing really matter*/
+               csi_param = (u16)((coefficientsize << 10) | (codebookinfo << 8) | (grouping << 6) | (nr_index << 3) | (nc_index));
+               odm_write_2byte(p_dm_odm, 0x6F4, csi_param);
+
+               /*for B-cut*/
+               odm_set_bb_reg(p_dm_odm, 0x6A0, BIT(20), 0);
+               odm_set_bb_reg(p_dm_odm, 0x688, BIT(20), 0);
+
+       }
+
+       /*************MU BFee Entry Init*************/
+       if ((p_beamforming_info->beamformee_mu_cnt > 0) && (bfee_idx < BEAMFORMEE_ENTRY_NUM)) {
+               p_beamformee_entry = &p_beamforming_info->beamformee_entry[bfee_idx];
+               p_beamformee_entry->is_mu_sta = true;
+               for (i = 0; i < MAX_BEAMFORMEE_MU; i++) {
+                       if ((p_beamforming_info->beamformee_mu_reg_maping & BIT(i)) == 0) {
+                               p_beamforming_info->beamformee_mu_reg_maping |= BIT(i);
+                               p_beamformee_entry->mu_reg_index = i;
+                               break;
+                       }
+               }
+
+               if (p_beamformee_entry->mu_reg_index == 0xFF) {
+                       /* There is no valid bit in beamformee_mu_reg_maping */
+                       RT_DISP(FBEAM, FBEAM_FUN, ("%s: ERROR! There is no valid bit in beamformee_mu_reg_maping!\n", __func__));
+                       return;
+               }
+
+               /*User position table*/
+               switch (p_beamformee_entry->mu_reg_index) {
+               case 0:
+                       gid_valid = 0x7fe;
+                       user_position_l = 0x111110;
+                       user_position_h = 0x0;
+                       break;
+               case 1:
+                       gid_valid = 0x7f806;
+                       user_position_l = 0x11000004;
+                       user_position_h = 0x11;
+                       break;
+               case 2:
+                       gid_valid = 0x1f81818;
+                       user_position_l = 0x400040;
+                       user_position_h = 0x11100;
+                       break;
+               case 3:
+                       gid_valid = 0x1e186060;
+                       user_position_l = 0x4000400;
+                       user_position_h = 0x1100040;
+                       break;
+               case 4:
+                       gid_valid = 0x66618180;
+                       user_position_l = 0x40004000;
+                       user_position_h = 0x10040400;
+                       break;
+               case 5:
+                       gid_valid = 0x79860600;
+                       user_position_l = 0x40000;
+                       user_position_h = 0x4404004;
+                       break;
+               }
+
+               for (i = 0; i < 8; i++) {
+                       if (i < 4) {
+                               p_beamformee_entry->gid_valid[i] = (u8)(gid_valid & 0xFF);
+                               gid_valid = (gid_valid >> 8);
+                       } else
+                               p_beamformee_entry->gid_valid[i] = 0;
+               }
+               for (i = 0; i < 16; i++) {
+                       if (i < 4)
+                               p_beamformee_entry->user_position[i] = (u8)((user_position_l >> (i * 8)) & 0xFF);
+                       else if (i < 8)
+                               p_beamformee_entry->user_position[i] = (u8)((user_position_h >> ((i - 4) * 8)) & 0xFF);
+                       else
+                               p_beamformee_entry->user_position[i] = 0;
+               }
+
+               /*Sounding protocol control*/
+               odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8822B, 0xDB);
+
+               /*select MU STA table*/
+               p_beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
+               p_beamforming_info->reg_mu_tx_ctrl |= (p_beamformee_entry->mu_reg_index << 8) & (BIT(8) | BIT(9) | BIT(10));
+               odm_write_4byte(p_dm_odm, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl);
+
+               odm_set_bb_reg(p_dm_odm, 0x14c4, MASKDWORD, 0); /*Reset gid_valid table*/
+               odm_set_bb_reg(p_dm_odm, 0x14c8, MASKDWORD, user_position_l);
+               odm_set_bb_reg(p_dm_odm, 0x14cc, MASKDWORD, user_position_h);
+
+               /*set validity of MU STAs*/
+               p_beamforming_info->reg_mu_tx_ctrl &= 0xFFFFFFC0;
+               p_beamforming_info->reg_mu_tx_ctrl |= p_beamforming_info->beamformee_mu_reg_maping & 0x3F;
+               odm_write_4byte(p_dm_odm, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl);
+
+               ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, reg_mu_tx_ctrl = 0x%x, user_position_l = 0x%x, user_position_h = 0x%x\n",
+                       __func__, p_beamforming_info->reg_mu_tx_ctrl, user_position_l, user_position_h));
+
+               value16 = odm_read_2byte(p_dm_odm, mu_reg[p_beamformee_entry->mu_reg_index]);
+               value16 &= 0xFE00; /*Clear PAID*/
+               value16 |= BIT(9); /*Enable MU BFee*/
+               value16 |= p_beamformee_entry->p_aid;
+               odm_write_2byte(p_dm_odm, mu_reg[p_beamformee_entry->mu_reg_index], value16);
+
+               /* 0x42C[30] = 1 (0: from Tx desc, 1: from 0x45F) */
+               u1b_tmp = odm_read_1byte(p_dm_odm, REG_TXBF_CTRL_8822B + 3);
+               u1b_tmp |= 0xD0; /* Set bit 28, 30, 31 to 3b'111*/
+               odm_write_1byte(p_dm_odm, REG_TXBF_CTRL_8822B + 3, u1b_tmp);
+               /* Set NDPA to 6M*/
+               odm_write_1byte(p_dm_odm, REG_NDPA_RATE_8822B, 0x4);
+
+               u1b_tmp = odm_read_1byte(p_dm_odm, REG_NDPA_OPT_CTRL_8822B);
+               u1b_tmp &= 0xFC; /* Clear bit 0, 1*/
+               odm_write_1byte(p_dm_odm, REG_NDPA_OPT_CTRL_8822B, u1b_tmp);
+
+               u4b_tmp = odm_read_4byte(p_dm_odm, REG_SND_PTCL_CTRL_8822B);
+               u4b_tmp = ((u4b_tmp & 0xFF0000FF) | 0x020200); /* Set [23:8] to 0x0202*/
+               odm_write_4byte(p_dm_odm, REG_SND_PTCL_CTRL_8822B, u4b_tmp);
+
+               /* Set 0x6A0[14] = 1 to accept action_no_ack */
+               u1b_tmp = odm_read_1byte(p_dm_odm, REG_RXFLTMAP0_8822B + 1);
+               u1b_tmp |= 0x40;
+               odm_write_1byte(p_dm_odm, REG_RXFLTMAP0_8822B + 1, u1b_tmp);
+               /* End of MAC registers setting */
+
+               hal_txbf_8822b_rf_mode(p_dm_odm, p_beamforming_info, bfee_idx);
+#if (SUPPORT_MU_BF == 1)
+               /*Special for plugfest*/
+               delay_ms(50); /* wait for 4-way handshake ending*/
+               send_sw_vht_gid_mgnt_frame(p_dm_odm, p_beamformee_entry->mac_addr, bfee_idx);
+#endif
+
+               phydm_beamforming_notify(p_dm_odm);
+               {
+                       u32 ctrl_info_offset, index;
+                       /*Set Ctrl Info*/
+                       odm_write_2byte(p_dm_odm, 0x140, 0x660);
+                       ctrl_info_offset = 0x8000 + 32 * p_beamformee_entry->mac_id;
+                       /*Reset Ctrl Info*/
+                       for (index = 0; index < 8; index++)
+                               odm_write_4byte(p_dm_odm, ctrl_info_offset + index * 4, 0);
+
+                       odm_write_4byte(p_dm_odm, ctrl_info_offset, (p_beamformee_entry->mu_reg_index + 1) << 16);
+                       odm_write_1byte(p_dm_odm, 0x81, 0x80); /*RPTBUF ready*/
+
+                       ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, mac_id = %d, ctrl_info_offset = 0x%x, mu_reg_index = %x\n",
+                               __func__, p_beamformee_entry->mac_id, ctrl_info_offset, p_beamformee_entry->mu_reg_index));
+               }
+       }
+}
+
+
+void
+hal_txbf_8822b_leave(
+       void                    *p_dm_void,
+       u8                              idx
+)
+{
+       struct PHY_DM_STRUCT    *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
+       struct _RT_BEAMFORMING_INFO     *p_beamforming_info = &p_dm_odm->beamforming_info;
+       struct _RT_BEAMFORMER_ENTRY     *p_beamformer_entry;
+       struct _RT_BEAMFORMEE_ENTRY     *p_beamformee_entry;
+       u32                                     mu_reg[6] = {0x1684, 0x1686, 0x1688, 0x168a, 0x168c, 0x168e};
+
+       if (idx < BEAMFORMER_ENTRY_NUM) {
+               p_beamformer_entry = &p_beamforming_info->beamformer_entry[idx];
+               p_beamformee_entry = &p_beamforming_info->beamformee_entry[idx];
+       } else
+               return;
+
+       /*Clear P_AID of Beamformee*/
+       /*Clear MAC address of Beamformer*/
+       /*Clear Associated Bfmee Sel*/
+
+       if (p_beamformer_entry->beamform_entry_cap == BEAMFORMING_CAP_NONE) {
+               odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8822B, 0xD8);
+               if (p_beamformer_entry->is_mu_ap == 0) { /*SU BFer */
+                       if (p_beamformer_entry->su_reg_index == 0) {
+                               odm_write_4byte(p_dm_odm, REG_ASSOCIATED_BFMER0_INFO_8822B, 0);
+                               odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMER0_INFO_8822B + 4, 0);
+                               odm_write_2byte(p_dm_odm, REG_TX_CSI_RPT_PARAM_BW20_8822B, 0);
+                       } else {
+                               odm_write_4byte(p_dm_odm, REG_ASSOCIATED_BFMER1_INFO_8822B, 0);
+                               odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMER1_INFO_8822B + 4, 0);
+                               odm_write_2byte(p_dm_odm, REG_TX_CSI_RPT_PARAM_BW20_8822B + 2, 0);
+                       }
+                       p_beamforming_info->beamformer_su_reg_maping &= ~(BIT(p_beamformer_entry->su_reg_index));
+                       p_beamformer_entry->su_reg_index = 0xFF;
+               } else { /*MU BFer */
+                       /*set validity of MU STA0 and MU STA1*/
+                       p_beamforming_info->reg_mu_tx_ctrl &= 0xFFFFFFC0;
+                       odm_write_4byte(p_dm_odm, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl);
+
+                       odm_memory_set(p_dm_odm, p_beamformer_entry->gid_valid, 0, 8);
+                       odm_memory_set(p_dm_odm, p_beamformer_entry->user_position, 0, 16);
+                       p_beamformer_entry->is_mu_ap = false;
+               }
+       }
+
+       if (p_beamformee_entry->beamform_entry_cap == BEAMFORMING_CAP_NONE) {
+               hal_txbf_8822b_rf_mode(p_dm_odm, p_beamforming_info, idx);
+               if (p_beamformee_entry->is_mu_sta == 0) { /*SU BFee*/
+                       if (p_beamformee_entry->su_reg_index == 0) {
+                               odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8822B, 0x0);
+                               odm_write_1byte(p_dm_odm, REG_TXBF_CTRL_8822B + 3, odm_read_1byte(p_dm_odm, REG_TXBF_CTRL_8822B + 3) | BIT(4) | BIT(6) | BIT(7));
+                               odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8822B, 0);
+                       } else {
+                               odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8822B + 2, 0x0 | BIT(14) | BIT(15) | BIT(12));
+
+                               odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2,
+                                       odm_read_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2) & 0x60);
+                       }
+                       p_beamforming_info->beamformee_su_reg_maping &= ~(BIT(p_beamformee_entry->su_reg_index));
+                       p_beamformee_entry->su_reg_index = 0xFF;
+               } else { /*MU BFee */
+                       /*Disable sending NDPA & BF-rpt-poll to this BFee*/
+                       odm_write_2byte(p_dm_odm, mu_reg[p_beamformee_entry->mu_reg_index], 0);
+                       /*set validity of MU STA*/
+                       p_beamforming_info->reg_mu_tx_ctrl &= ~(BIT(p_beamformee_entry->mu_reg_index));
+                       odm_write_4byte(p_dm_odm, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl);
+
+
+                       p_beamformee_entry->is_mu_sta = false;
+                       p_beamforming_info->beamformee_mu_reg_maping &= ~(BIT(p_beamformee_entry->mu_reg_index));
+                       p_beamformee_entry->mu_reg_index = 0xFF;
+               }
+       }
+}
+
+
+/***********SU & MU BFee Entry Only when souding done****************/
+void
+hal_txbf_8822b_status(
+       void                    *p_dm_void,
+       u8                              beamform_idx
+)
+{
+       struct PHY_DM_STRUCT    *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
+       u16                                     beam_ctrl_val, tmp_val;
+       u32                                     beam_ctrl_reg;
+       struct _RT_BEAMFORMING_INFO     *p_beamforming_info = &p_dm_odm->beamforming_info;
+       struct _RT_BEAMFORMEE_ENTRY     *p_beamform_entry;
+       boolean is_mu_sounding = p_beamforming_info->is_mu_sounding, is_bitmap_ready = false;
+       u16 bitmap;
+       u8 idx, gid, i;
+       u8 id1, id0;
+       u32 gid_valid[6] = {0};
+       u32 user_position_lsb[6] = {0};
+       u32 user_position_msb[6] = {0};
+       u32 value32;
+       boolean is_sounding_success[6] = {false};
+
+       if (beamform_idx < BEAMFORMEE_ENTRY_NUM)
+               p_beamform_entry = &p_beamforming_info->beamformee_entry[beamform_idx];
+       else
+               return;
+
+       /*SU sounding done */
+       if (is_mu_sounding == false) {
+
+               if (phydm_acting_determine(p_dm_odm, phydm_acting_as_ibss))
+                       beam_ctrl_val = p_beamform_entry->mac_id;
+               else
+                       beam_ctrl_val = p_beamform_entry->p_aid;
+
+               ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, beamform_entry.beamform_entry_state = %d", __func__, p_beamform_entry->beamform_entry_state));
+
+               if (p_beamform_entry->su_reg_index == 0)
+                       beam_ctrl_reg = REG_TXBF_CTRL_8822B;
+               else {
+                       beam_ctrl_reg = REG_TXBF_CTRL_8822B + 2;
+                       beam_ctrl_val |= BIT(12) | BIT(14) | BIT(15);
+               }
+
+               if (p_beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
+                       if (p_beamform_entry->sound_bw == CHANNEL_WIDTH_20)
+                               beam_ctrl_val |= BIT(9);
+                       else if (p_beamform_entry->sound_bw == CHANNEL_WIDTH_40)
+                               beam_ctrl_val |= (BIT(9) | BIT(10));
+                       else if (p_beamform_entry->sound_bw == CHANNEL_WIDTH_80)
+                               beam_ctrl_val |= (BIT(9) | BIT(10) | BIT(11));
+               } else {
+                       ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, Don't apply Vmatrix",  __func__));
+                       beam_ctrl_val &= ~(BIT(9) | BIT(10) | BIT(11));
+               }
+
+               odm_write_2byte(p_dm_odm, beam_ctrl_reg, beam_ctrl_val);
+               /*disable NDP packet use beamforming */
+               tmp_val = odm_read_2byte(p_dm_odm, REG_TXBF_CTRL_8822B);
+               odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8822B, tmp_val | BIT(15));
+       } else {
+               ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, MU Sounding Done\n",  __func__));
+               /*MU sounding done */
+               if (1) { /* (p_beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) { */
+                       ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, BEAMFORMING_ENTRY_STATE_PROGRESSED\n",  __func__));
+
+                       value32 = odm_get_bb_reg(p_dm_odm, 0x1684, MASKDWORD);
+                       is_sounding_success[0] = (value32 & BIT(10)) ? 1 : 0;
+                       is_sounding_success[1] = (value32 & BIT(26)) ? 1 : 0;
+                       value32 = odm_get_bb_reg(p_dm_odm, 0x1688, MASKDWORD);
+                       is_sounding_success[2] = (value32 & BIT(10)) ? 1 : 0;
+                       is_sounding_success[3] = (value32 & BIT(26)) ? 1 : 0;
+                       value32 = odm_get_bb_reg(p_dm_odm, 0x168C, MASKDWORD);
+                       is_sounding_success[4] = (value32 & BIT(10)) ? 1 : 0;
+                       is_sounding_success[5] = (value32 & BIT(26)) ? 1 : 0;
+
+                       ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, is_sounding_success STA1:%d,  STA2:%d, STA3:%d, STA4:%d, STA5:%d, STA6:%d\n",
+                               __func__, is_sounding_success[0], is_sounding_success[1], is_sounding_success[2], is_sounding_success[3], is_sounding_success[4], is_sounding_success[5]));
+
+                       value32 = odm_get_bb_reg(p_dm_odm, 0xF4C, 0xFFFF0000);
+                       /* odm_set_bb_reg(p_dm_odm, 0x19E0, MASKHWORD, 0xFFFF);Let MAC ignore bitmap */
+
+                       is_bitmap_ready = (boolean)((value32 & BIT(15)) >> 15);
+                       bitmap = (u16)(value32 & 0x3FFF);
+
+                       for (idx = 0; idx < 15; idx++) {
+                               if (idx < 5) {/*bit0~4*/
+                                       id0 = 0;
+                                       id1 = (u8)(idx + 1);
+                               } else if (idx < 9) { /*bit5~8*/
+                                       id0 = 1;
+                                       id1 = (u8)(idx - 3);
+                               } else if (idx < 12) { /*bit9~11*/
+                                       id0 = 2;
+                                       id1 = (u8)(idx - 6);
+                               } else if (idx < 14) { /*bit12~13*/
+                                       id0 = 3;
+                                       id1 = (u8)(idx - 8);
+                               } else { /*bit14*/
+                                       id0 = 4;
+                                       id1 = (u8)(idx - 9);
+                               }
+                               if (bitmap & BIT(idx)) {
+                                       /*Pair 1*/
+                                       gid = (idx << 1) + 1;
+                                       gid_valid[id0] |= (BIT(gid));
+                                       gid_valid[id1] |= (BIT(gid));
+                                       /*Pair 2*/
+                                       gid += 1;
+                                       gid_valid[id0] |= (BIT(gid));
+                                       gid_valid[id1] |= (BIT(gid));
+                               } else {
+                                       /*Pair 1*/
+                                       gid = (idx << 1) + 1;
+                                       gid_valid[id0] &= ~(BIT(gid));
+                                       gid_valid[id1] &= ~(BIT(gid));
+                                       /*Pair 2*/
+                                       gid += 1;
+                                       gid_valid[id0] &= ~(BIT(gid));
+                                       gid_valid[id1] &= ~(BIT(gid));
+                               }
+                       }
+
+                       for (i = 0; i < BEAMFORMEE_ENTRY_NUM; i++) {
+                               p_beamform_entry = &p_beamforming_info->beamformee_entry[i];
+                               if ((p_beamform_entry->is_mu_sta) && (p_beamform_entry->mu_reg_index < 6)) {
+                                       value32 = gid_valid[p_beamform_entry->mu_reg_index];
+                                       for (idx = 0; idx < 4; idx++) {
+                                               p_beamform_entry->gid_valid[idx] = (u8)(value32 & 0xFF);
+                                               value32 = (value32 >> 8);
+                                       }
+                               }
+                       }
+
+                       for (idx = 0; idx < 6; idx++) {
+                               p_beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
+                               p_beamforming_info->reg_mu_tx_ctrl |= ((idx << 8) & (BIT(8) | BIT(9) | BIT(10)));
+                               odm_write_4byte(p_dm_odm, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl);
+                               odm_set_mac_reg(p_dm_odm, 0x14C4, MASKDWORD, gid_valid[idx]); /*set MU STA gid valid table*/
+                       }
+
+                       /*Enable TxMU PPDU*/
+                       if (p_beamforming_info->dbg_disable_mu_tx == false)
+                               p_beamforming_info->reg_mu_tx_ctrl |= BIT(7);
+                       else
+                               p_beamforming_info->reg_mu_tx_ctrl &= ~BIT(7);
+                       odm_write_4byte(p_dm_odm, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl);
+               }
+       }
+}
+
+/*Only used for MU BFer Entry when get GID management frame (self is as MU STA)*/
+void
+hal_txbf_8822b_config_gtab(
+       void                    *p_dm_void
+)
+{
+       struct PHY_DM_STRUCT    *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
+       struct _RT_BEAMFORMING_INFO     *p_beamforming_info = &p_dm_odm->beamforming_info;
+       struct _RT_BEAMFORMER_ENTRY     *p_beamformer_entry = NULL;
+       u32             gid_valid = 0, user_position_l = 0, user_position_h = 0, i;
+
+       if (p_beamforming_info->mu_ap_index < BEAMFORMER_ENTRY_NUM)
+               p_beamformer_entry = &p_beamforming_info->beamformer_entry[p_beamforming_info->mu_ap_index];
+       else
+               return;
+
+       ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s==>\n", __func__));
+
+       /*For GID 0~31*/
+       for (i = 0; i < 4; i++)
+               gid_valid |= (p_beamformer_entry->gid_valid[i] << (i << 3));
+       for (i = 0; i < 8; i++) {
+               if (i < 4)
+                       user_position_l |= (p_beamformer_entry->user_position[i] << (i << 3));
+               else
+                       user_position_h |= (p_beamformer_entry->user_position[i] << ((i - 4) << 3));
+       }
+       /*select MU STA0 table*/
+       p_beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
+       odm_write_4byte(p_dm_odm, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl);
+       odm_set_bb_reg(p_dm_odm, 0x14c4, MASKDWORD, gid_valid);
+       odm_set_bb_reg(p_dm_odm, 0x14c8, MASKDWORD, user_position_l);
+       odm_set_bb_reg(p_dm_odm, 0x14cc, MASKDWORD, user_position_h);
+
+       ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: STA0: gid_valid = 0x%x, user_position_l = 0x%x, user_position_h = 0x%x\n",
+                       __func__, gid_valid, user_position_l, user_position_h));
+
+       gid_valid = 0;
+       user_position_l = 0;
+       user_position_h = 0;
+
+       /*For GID 32~64*/
+       for (i = 4; i < 8; i++)
+               gid_valid |= (p_beamformer_entry->gid_valid[i] << ((i - 4) << 3));
+       for (i = 8; i < 16; i++) {
+               if (i < 4)
+                       user_position_l |= (p_beamformer_entry->user_position[i] << ((i - 8) << 3));
+               else
+                       user_position_h |= (p_beamformer_entry->user_position[i] << ((i - 12) << 3));
+       }
+       /*select MU STA1 table*/
+       p_beamforming_info->reg_mu_tx_ctrl &= ~(BIT(8) | BIT(9) | BIT(10));
+       p_beamforming_info->reg_mu_tx_ctrl |= BIT(8);
+       odm_write_4byte(p_dm_odm, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl);
+       odm_set_bb_reg(p_dm_odm, 0x14c4, MASKDWORD, gid_valid);
+       odm_set_bb_reg(p_dm_odm, 0x14c8, MASKDWORD, user_position_l);
+       odm_set_bb_reg(p_dm_odm, 0x14cc, MASKDWORD, user_position_h);
+
+       ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: STA1: gid_valid = 0x%x, user_position_l = 0x%x, user_position_h = 0x%x\n",
+                       __func__, gid_valid, user_position_l, user_position_h));
+
+       /* Set validity of MU STA0 and MU STA1*/
+       p_beamforming_info->reg_mu_tx_ctrl &= 0xFFFFFFC0;
+       p_beamforming_info->reg_mu_tx_ctrl |= 0x3; /* STA0, STA1*/
+       odm_write_4byte(p_dm_odm, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl);
+
+}
+
+void
+hal_txbf_8822b_fw_txbf(
+       void                    *p_dm_void,
+       u8                              idx
+)
+{
+}
+
+#endif
+
+#if (defined(CONFIG_BB_TXBF_API))
+/*this function is only used for BFer*/
+void
+phydm_8822btxbf_rfmode(
+       void            *p_dm_void,
+       u8      su_bfee_cnt,
+       u8      mu_bfee_cnt
+)
+{
+       struct PHY_DM_STRUCT    *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
+       u8              i, nr_index = 0;
+
+       if (p_dm_odm->rf_type == ODM_1T1R)
+               return;
+
+       if ((su_bfee_cnt > 0) || (mu_bfee_cnt > 0)) {
+               for (i = ODM_RF_PATH_A; i <= ODM_RF_PATH_B; i++) {
+                       odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)i, 0xEF, BIT(19), 0x1); /*RF mode table write enable*/
+                       odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)i, 0x33, 0xF, 3); /*Select RX mode*/
+                       odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)i, 0x3E, 0xfffff, 0x00036); /*Set Table data*/
+                       odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)i, 0x3F, 0xfffff, 0x5AFCE); /*Set Table data*/
+                       odm_set_rf_reg(p_dm_odm, (enum odm_rf_radio_path_e)i, 0xEF, BIT(19), 0x0); /*RF mode table write disable*/
+               }
+       }
+
+       odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(30), 1);                    /*if Nsts > Nc, don't apply V matrix*/
+
+       if (su_bfee_cnt > 0 || mu_bfee_cnt > 0) {
+               /*for 8814 19ac(idx 1), 19b4(idx 0), different Tx ant setting*/
+               odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x2);  /*enable BB TxBF ant mapping register*/
+               odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 1);                    /*ignore user since 8822B only 2Tx*/
+
+
+               /*Nsts = 2      AB*/
+               odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433);
+               odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043);
+
+       } else {
+               odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x0);  /*enable BB TxBF ant mapping register*/
+               odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 0);                    /*ignore user since 8822B only 2Tx*/
+
+               odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x1); /*1SS by path-A*/
+               odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8822B, MASKLWORD, 0x430); /*2SS by path-A,B*/
+       }
+
+}
+
+
+/*this function is for BFer bug workaround*/
+void
+phydm_8822b_sutxbfer_workaroud(
+       void            *p_dm_void,
+       boolean enable_su_bfer,
+       u8      nc,
+       u8      nr,
+       u8      ng,
+       u8      CB,
+       u8      BW,
+       boolean is_vht
+)
+{
+       struct PHY_DM_STRUCT    *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
+
+       if (enable_su_bfer) {
+               odm_set_bb_reg(p_dm_odm, 0x19f8, BIT(22) | BIT(21) | BIT(20), 0x1);
+               odm_set_bb_reg(p_dm_odm, 0x19f8, BIT(25) | BIT(24) | BIT(23), 0x0);
+               odm_set_bb_reg(p_dm_odm, 0x19f8, BIT(16), 0x1);
+
+               if (is_vht)
+                       odm_set_bb_reg(p_dm_odm, 0x19f0, BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x1f);
+               else
+                       odm_set_bb_reg(p_dm_odm, 0x19f0, BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x22);
+
+               odm_set_bb_reg(p_dm_odm, 0x19f0, BIT(7) | BIT(6), nc);
+               odm_set_bb_reg(p_dm_odm, 0x19f0, BIT(9) | BIT(8), nr);
+               odm_set_bb_reg(p_dm_odm, 0x19f0, BIT(11) | BIT(10), ng);
+               odm_set_bb_reg(p_dm_odm, 0x19f0, BIT(13) | BIT(12), CB);
+
+               odm_set_bb_reg(p_dm_odm, 0xb58, BIT(3) | BIT(2), BW);
+               odm_set_bb_reg(p_dm_odm, 0xb58, BIT(7) | BIT(6) | BIT(5) | BIT(4), 0x0);
+               odm_set_bb_reg(p_dm_odm, 0xb58, BIT(9) | BIT(8), BW);
+               odm_set_bb_reg(p_dm_odm, 0xb58, BIT(13) | BIT(12) | BIT(11) | BIT(10), 0x0);
+       } else
+               odm_set_bb_reg(p_dm_odm, 0x19f8, BIT(16), 0x0);
+
+       ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_TRACE, ("[%s] enable_su_bfer = %d, is_vht = %d\n", __func__, enable_su_bfer, is_vht));
+       ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_TRACE, ("[%s] nc = %d, nr = %d, ng = %d, CB = %d, BW = %d\n", __func__, nc, nr, ng, CB, BW));
+
+
+}
+#endif
+#endif /* (RTL8822B_SUPPORT == 1)*/