| /****************************************************************************** |
| * |
| * Copyright(c) 2016 - 2017 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. |
| * |
| *****************************************************************************/ |
| /*============================================================*/ |
| /* 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 = (struct PHY_DM_STRUCT *)p_dm_void; |
| u8 ntx = 0; |
| |
| #if DEV_BUS_TYPE == RT_USB_INTERFACE |
| if (p_dm->support_interface == ODM_ITRF_USB) { |
| if (*p_dm->hub_usb_mode == 2) {/*USB3.0*/ |
| if (p_dm->rf_type == RF_4T4R) |
| ntx = 3; |
| else if (p_dm->rf_type == RF_3T3R) |
| ntx = 2; |
| else |
| ntx = 1; |
| } else if (*p_dm->hub_usb_mode == 1) /*USB 2.0 always 2Tx*/ |
| ntx = 1; |
| else |
| ntx = 1; |
| } else |
| #endif |
| { |
| if (p_dm->rf_type == RF_4T4R) |
| ntx = 3; |
| else if (p_dm->rf_type == RF_3T3R) |
| ntx = 2; |
| else |
| ntx = 1; |
| } |
| |
| return ntx; |
| |
| } |
| |
| u8 |
| hal_txbf_8822b_get_nrx( |
| void *p_dm_void |
| ) |
| { |
| struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void; |
| u8 nrx = 0; |
| |
| if (p_dm->rf_type == RF_4T4R) |
| nrx = 3; |
| else if (p_dm->rf_type == RF_3T3R) |
| nrx = 2; |
| else if (p_dm->rf_type == RF_2T2R) |
| nrx = 1; |
| else if (p_dm->rf_type == RF_2T3R) |
| nrx = 2; |
| else if (p_dm->rf_type == RF_2T4R) |
| nrx = 3; |
| else if (p_dm->rf_type == RF_1T1R) |
| nrx = 0; |
| else if (p_dm->rf_type == RF_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 |
| ) |
| { |
| #if 0 |
| struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void; |
| u8 i, nr_index = 0; |
| boolean is_self_beamformer = false; |
| boolean is_self_beamformee = false; |
| struct _RT_BEAMFORMEE_ENTRY beamformee_entry; |
| |
| if (idx < BEAMFORMEE_ENTRY_NUM) |
| beamformee_entry = p_beamforming_info->beamformee_entry[idx]; |
| else |
| return; |
| |
| if (p_dm->rf_type == RF_1T1R) |
| return; |
| |
| for (i = RF_PATH_A; i < RF_PATH_B; i++) { |
| odm_set_rf_reg(p_dm, (enum rf_path)i, rf_welut_jaguar, 0x80000, 0x1); |
| /*RF mode table write enable*/ |
| } |
| |
| if ((p_beamforming_info->beamformee_su_cnt > 0) || (p_beamforming_info->beamformee_mu_cnt > 0)) { |
| for (i = RF_PATH_A; i < RF_PATH_B; i++) { |
| odm_set_rf_reg(p_dm, (enum rf_path)i, rf_mode_table_addr, 0xfffff, 0x18000); |
| /*Select RX mode*/ |
| odm_set_rf_reg(p_dm, (enum rf_path)i, rf_mode_table_data0, 0xfffff, 0xBE77F); |
| /*Set Table data*/ |
| odm_set_rf_reg(p_dm, (enum rf_path)i, rf_mode_table_data1, 0xfffff, 0x226BF); |
| /*Enable TXIQGEN in RX mode*/ |
| } |
| odm_set_rf_reg(p_dm, RF_PATH_A, rf_mode_table_data1, 0xfffff, 0xE26BF); |
| /*Enable TXIQGEN in RX mode*/ |
| } |
| |
| for (i = RF_PATH_A; i < RF_PATH_B; i++) { |
| odm_set_rf_reg(p_dm, (enum rf_path)i, rf_welut_jaguar, 0x80000, 0x0); |
| /*RF mode table write disable*/ |
| } |
| |
| if (p_beamforming_info->beamformee_su_cnt > 0) { |
| |
| /*for 8814 19ac(idx 1), 19b4(idx 0), different Tx ant setting*/ |
| odm_set_bb_reg(p_dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x2); /*enable BB TxBF ant mapping register*/ |
| |
| if (idx == 0) { |
| /*Nsts = 2 AB*/ |
| odm_set_bb_reg(p_dm, REG_BB_TXBF_ANT_SET_BF0_8822B, 0xffff, 0x0433); |
| odm_set_bb_reg(p_dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043); |
| /*odm_set_bb_reg(p_dm, REG_BB_TX_PATH_SEL_2, MASKLWORD, 0x430);*/ |
| |
| } else {/*IDX =1*/ |
| odm_set_bb_reg(p_dm, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433); |
| odm_set_bb_reg(p_dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043); |
| /*odm_set_bb_reg(p_dm, REG_BB_TX_PATH_SEL_2, MASKLWORD, 0x430;*/ |
| } |
| } else { |
| odm_set_bb_reg(p_dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x1); /*1SS by path-A*/ |
| odm_set_bb_reg(p_dm, REG_BB_TX_PATH_SEL_2_8822B, MASKLWORD, 0x430); /*2SS by path-A,B*/ |
| } |
| |
| if (p_beamforming_info->beamformee_mu_cnt > 0) { |
| /*MU STAs share the common setting*/ |
| odm_set_bb_reg(p_dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 1); |
| odm_set_bb_reg(p_dm, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433); |
| odm_set_bb_reg(p_dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043); |
| } |
| #endif |
| } |
| #if 0 |
| void |
| hal_txbf_8822b_download_ndpa( |
| struct _ADAPTER *adapter, |
| u8 idx |
| ) |
| { |
| u8 u1b_tmp = 0, tmp_reg422 = 0; |
| u8 bcn_valid_reg = 0, count = 0, dl_bcn_count = 0; |
| u16 head_page = 0x7FE; |
| boolean is_send_beacon = false; |
| HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter); |
| u16 tx_page_bndy = LAST_ENTRY_OF_TX_PKT_BUFFER_8814A; /*default reseved 1 page for the IC type which is undefined.*/ |
| struct _RT_BEAMFORMING_INFO *p_beam_info = GET_BEAMFORM_INFO(adapter); |
| struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = p_beam_info->beamformee_entry + idx; |
| |
| p_hal_data->is_fw_dw_rsvd_page_in_progress = true; |
| phydm_get_hal_def_var_handler_interface(p_dm, HAL_DEF_TX_PAGE_BOUNDARY, (u16 *)&tx_page_bndy); |
| |
| /*Set REG_CR bit 8. DMA beacon by SW.*/ |
| u1b_tmp = platform_efio_read_1byte(adapter, REG_CR_8814A + 1); |
| platform_efio_write_1byte(adapter, REG_CR_8814A + 1, (u1b_tmp | BIT(0))); |
| |
| |
| /*Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.*/ |
| tmp_reg422 = platform_efio_read_1byte(adapter, REG_FWHW_TXQ_CTRL_8814A + 2); |
| platform_efio_write_1byte(adapter, REG_FWHW_TXQ_CTRL_8814A + 2, tmp_reg422 & (~BIT(6))); |
| |
| if (tmp_reg422 & BIT(6)) { |
| RT_TRACE(COMP_INIT, DBG_LOUD, ("SetBeamformDownloadNDPA_8814A(): There is an adapter is sending beacon.\n")); |
| is_send_beacon = true; |
| } |
| |
| /*0x204[11:0] Beacon Head for TXDMA*/ |
| platform_efio_write_2byte(adapter, REG_FIFOPAGE_CTRL_2_8814A, head_page); |
| |
| do { |
| /*Clear beacon valid check bit.*/ |
| bcn_valid_reg = platform_efio_read_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 1); |
| platform_efio_write_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 1, (bcn_valid_reg | BIT(7))); |
| |
| /*download NDPA rsvd page.*/ |
| if (p_beam_entry->beamform_entry_cap & BEAMFORMER_CAP_VHT_SU) |
| beamforming_send_vht_ndpa_packet(p_dm, p_beam_entry->mac_addr, p_beam_entry->AID, p_beam_entry->sound_bw, BEACON_QUEUE); |
| else |
| beamforming_send_ht_ndpa_packet(p_dm, p_beam_entry->mac_addr, p_beam_entry->sound_bw, BEACON_QUEUE); |
| |
| /*check rsvd page download OK.*/ |
| bcn_valid_reg = platform_efio_read_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 1); |
| count = 0; |
| while (!(bcn_valid_reg & BIT(7)) && count < 20) { |
| count++; |
| delay_us(10); |
| bcn_valid_reg = platform_efio_read_1byte(adapter, REG_FIFOPAGE_CTRL_2_8814A + 2); |
| } |
| dl_bcn_count++; |
| } while (!(bcn_valid_reg & BIT(7)) && dl_bcn_count < 5); |
| |
| if (!(bcn_valid_reg & BIT(0))) |
| RT_DISP(FBEAM, FBEAM_ERROR, ("%s Download RSVD page failed!\n", __func__)); |
| |
| /*0x204[11:0] Beacon Head for TXDMA*/ |
| platform_efio_write_2byte(adapter, REG_FIFOPAGE_CTRL_2_8814A, tx_page_bndy); |
| |
| /*To make sure that if there exists an adapter which would like to send beacon.*/ |
| /*If exists, the origianl value of 0x422[6] will be 1, we should check this to*/ |
| /*prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */ |
| /*the beacon cannot be sent by HW.*/ |
| /*2010.06.23. Added by tynli.*/ |
| if (is_send_beacon) |
| platform_efio_write_1byte(adapter, REG_FWHW_TXQ_CTRL_8814A + 2, tmp_reg422); |
| |
| /*Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.*/ |
| /*Clear CR[8] or beacon packet will not be send to TxBuf anymore.*/ |
| u1b_tmp = platform_efio_read_1byte(adapter, REG_CR_8814A + 1); |
| platform_efio_write_1byte(adapter, REG_CR_8814A + 1, (u1b_tmp & (~BIT(0)))); |
| |
| p_beam_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSED; |
| |
| p_hal_data->is_fw_dw_rsvd_page_in_progress = false; |
| } |
| |
| void |
| hal_txbf_8822b_fw_txbf_cmd( |
| struct _ADAPTER *adapter |
| ) |
| { |
| u8 idx, period = 0; |
| u8 PageNum0 = 0xFF, PageNum1 = 0xFF; |
| u8 u1_tx_bf_parm[3] = {0}; |
| |
| PMGNT_INFO p_mgnt_info = &(adapter->MgntInfo); |
| struct _RT_BEAMFORMING_INFO *p_beam_info = GET_BEAMFORM_INFO(adapter); |
| |
| for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) { |
| if (p_beam_info->beamformee_entry[idx].is_used && p_beam_info->beamformee_entry[idx].beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) { |
| if (p_beam_info->beamformee_entry[idx].is_sound) { |
| PageNum0 = 0xFE; |
| PageNum1 = 0x07; |
| period = (u8)(p_beam_info->beamformee_entry[idx].sound_period); |
| } else if (PageNum0 == 0xFF) { |
| PageNum0 = 0xFF; /*stop sounding*/ |
| PageNum1 = 0x0F; |
| } |
| } |
| } |
| |
| u1_tx_bf_parm[0] = PageNum0; |
| u1_tx_bf_parm[1] = PageNum1; |
| u1_tx_bf_parm[2] = period; |
| fill_h2c_cmd(adapter, PHYDM_H2C_TXBF, 3, u1_tx_bf_parm); |
| |
| RT_DISP(FBEAM, FBEAM_FUN, ("@%s End, PageNum0 = 0x%x, PageNum1 = 0x%x period = %d", __func__, PageNum0, PageNum1, period)); |
| } |
| #endif |
| |
| #if 0 |
| void |
| hal_txbf_8822b_init( |
| void *p_dm_void |
| ) |
| { |
| struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void; |
| u8 u1b_tmp; |
| struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm->beamforming_info; |
| struct _ADAPTER *adapter = p_dm->adapter; |
| |
| odm_set_bb_reg(p_dm, 0x14c0, BIT(16), 1); /*Enable P1 aggr new packet according to P0 transfer time*/ |
| odm_set_bb_reg(p_dm, 0x14c0, BIT(15) | BIT14 | BIT13 | BIT12, 10); /*MU Retry Limit*/ |
| odm_set_bb_reg(p_dm, 0x14c0, BIT(7), 0); /*Disable Tx MU-MIMO until sounding done*/ |
| odm_set_bb_reg(p_dm, 0x14c0, 0x3F, 0); /* Clear validity of MU STAs */ |
| odm_write_1byte(p_dm, 0x167c, 0x70); /*MU-MIMO Option as default value*/ |
| odm_write_2byte(p_dm, 0x1680, 0); /*MU-MIMO Control as default value*/ |
| |
| /* Set MU NDPA rate & BW source */ |
| /* 0x42C[30] = 1 (0: from Tx desc, 1: from 0x45F) */ |
| u1b_tmp = odm_read_1byte(p_dm, 0x42C); |
| odm_write_1byte(p_dm, REG_TXBF_CTRL_8822B, (u1b_tmp | BIT(6))); |
| /* 0x45F[7:0] = 0x10 (rate=OFDM_6M, BW20) */ |
| odm_write_1byte(p_dm, REG_NDPA_OPT_CTRL_8822B, 0x10); |
| |
| /*Temp Settings*/ |
| odm_set_bb_reg(p_dm, 0x6DC, 0x3F000000, 4); /*STA2's CSI rate is fixed at 6M*/ |
| odm_set_bb_reg(p_dm, 0x1C94, MASKDWORD, 0xAFFFAFFF); /*Grouping bitmap parameters*/ |
| |
| /* Init HW variable */ |
| p_beamforming_info->reg_mu_tx_ctrl = odm_read_4byte(p_dm, 0x14c0); |
| |
| if (p_dm->rf_type == RF_2T2R) { /*2T2R*/ |
| PHYDM_DBG(p_dm, DBG_TXBF, ("%s: rf_type is 2T2R\n", __func__)); |
| config_phydm_trx_mode_8822b(p_dm, (enum bb_path)3, (enum bb_path)3, true);/*Tx2path*/ |
| } |
| |
| #if (OMNIPEEK_SNIFFER_ENABLED == 1) |
| /* Config HW to receive packet on the user position from registry for sniffer mode. */ |
| /* odm_set_bb_reg(p_dm, 0xB00, BIT(9), 1);*/ /* For A-cut only. RegB00[9] = 1 (enable PMAC Rx) */ |
| odm_set_bb_reg(p_dm, 0xB54, BIT(30), 1); /* RegB54[30] = 1 (force user position) */ |
| odm_set_bb_reg(p_dm, 0xB54, (BIT(29) | BIT28), adapter->MgntInfo.sniff_user_position); /* RegB54[29:28] = user position (0~3) */ |
| PHYDM_DBG(p_dm, DBG_TXBF, ("Set adapter->MgntInfo.sniff_user_position=%#X\n", adapter->MgntInfo.sniff_user_position)); |
| #endif |
| } |
| #endif |
| |
| void |
| hal_txbf_8822b_enter( |
| void *p_dm_void, |
| u8 bfer_bfee_idx |
| ) |
| { |
| struct PHY_DM_STRUCT *p_dm = (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->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, 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, (REG_ASSOCIATED_BFMER0_INFO_8822B + i), p_beamformer_entry->mac_addr[i]); |
| } else { |
| for (i = 0; i < 6 ; i++) |
| odm_write_1byte(p_dm, (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); /*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, REG_TX_CSI_RPT_PARAM_BW20_8822B, csi_param); |
| else |
| odm_write_2byte(p_dm, 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, 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, p_beamforming_info, bfee_idx); |
| |
| if (phydm_acting_determine(p_dm, 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, REG_TXBF_CTRL_8822B, sta_id); |
| odm_write_1byte(p_dm, REG_TXBF_CTRL_8822B + 3, odm_read_1byte(p_dm, REG_TXBF_CTRL_8822B + 3) | BIT(4) | BIT(6) | BIT(7)); |
| } else |
| odm_write_2byte(p_dm, 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, REG_ASSOCIATED_BFMEE_SEL_8822B + 3) & 0x3; |
| |
| odm_write_1byte(p_dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 3, tmp | 0x60); |
| odm_write_2byte(p_dm, REG_ASSOCIATED_BFMEE_SEL_8822B, sta_id | BIT(9)); |
| } else |
| odm_write_2byte(p_dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2, sta_id | 0xE200); /*Set BIT25*/ |
| |
| phydm_beamforming_notify(p_dm); |
| } |
| |
| /*************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, REG_SND_PTCL_CTRL_8822B, 0xDB); |
| |
| /* MAC address */ |
| for (i = 0; i < 6 ; i++) |
| odm_write_1byte(p_dm, (REG_ASSOCIATED_BFMER0_INFO_8822B + i), p_beamformer_entry->mac_addr[i]); |
| |
| /* Set partial AID */ |
| odm_write_2byte(p_dm, (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, 0x1680); |
| u1b_tmp = (p_beamformer_entry->p_aid) & 0xFFF; |
| odm_write_1byte(p_dm, 0x1680, u1b_tmp); |
| |
| /* Set 80us for leaving ndp_rx_standby_state */ |
| odm_write_1byte(p_dm, 0x71B, 0x50); |
| |
| /* Set 0x6A0[14] = 1 to accept action_no_ack */ |
| u1b_tmp = odm_read_1byte(p_dm, REG_RXFLTMAP0_8822B + 1); |
| u1b_tmp |= 0x40; |
| odm_write_1byte(p_dm, REG_RXFLTMAP0_8822B + 1, u1b_tmp); |
| /* Set 0x6A2[5:4] = 1 to NDPA and BF report poll */ |
| u1b_tmp = odm_read_1byte(p_dm, REG_RXFLTMAP1_8822B); |
| u1b_tmp |= 0x30; |
| odm_write_1byte(p_dm, REG_RXFLTMAP1_8822B, u1b_tmp); |
| |
| /*CSI report parameters of Beamformer*/ |
| nc_index = hal_txbf_8822b_get_nrx(p_dm); /* 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, 0x6F4, csi_param); |
| |
| /*for B-cut*/ |
| odm_set_bb_reg(p_dm, 0x6A0, BIT(20), 0); |
| odm_set_bb_reg(p_dm, 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, 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, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl); |
| |
| odm_set_bb_reg(p_dm, 0x14c4, MASKDWORD, 0); /*Reset gid_valid table*/ |
| odm_set_bb_reg(p_dm, 0x14c8, MASKDWORD, user_position_l); |
| odm_set_bb_reg(p_dm, 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, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl); |
| |
| PHYDM_DBG(p_dm, DBG_TXBF, ("@%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, 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, 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, REG_TXBF_CTRL_8822B + 3); |
| u1b_tmp |= 0xD0; /* Set bit 28, 30, 31 to 3b'111*/ |
| odm_write_1byte(p_dm, REG_TXBF_CTRL_8822B + 3, u1b_tmp); |
| /* Set NDPA to 6M*/ |
| odm_write_1byte(p_dm, REG_NDPA_RATE_8822B, 0x4); |
| |
| u1b_tmp = odm_read_1byte(p_dm, REG_NDPA_OPT_CTRL_8822B); |
| u1b_tmp &= 0xFC; /* Clear bit 0, 1*/ |
| odm_write_1byte(p_dm, REG_NDPA_OPT_CTRL_8822B, u1b_tmp); |
| |
| u4b_tmp = odm_read_4byte(p_dm, REG_SND_PTCL_CTRL_8822B); |
| u4b_tmp = ((u4b_tmp & 0xFF0000FF) | 0x020200); /* Set [23:8] to 0x0202*/ |
| odm_write_4byte(p_dm, REG_SND_PTCL_CTRL_8822B, u4b_tmp); |
| |
| /* Set 0x6A0[14] = 1 to accept action_no_ack */ |
| u1b_tmp = odm_read_1byte(p_dm, REG_RXFLTMAP0_8822B + 1); |
| u1b_tmp |= 0x40; |
| odm_write_1byte(p_dm, REG_RXFLTMAP0_8822B + 1, u1b_tmp); |
| /* End of MAC registers setting */ |
| |
| hal_txbf_8822b_rf_mode(p_dm, 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, p_beamformee_entry->mac_addr, bfee_idx); |
| #endif |
| |
| phydm_beamforming_notify(p_dm); |
| #if 1 |
| { |
| u32 ctrl_info_offset, index; |
| /*Set Ctrl Info*/ |
| odm_write_2byte(p_dm, 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, ctrl_info_offset + index * 4, 0); |
| |
| odm_write_4byte(p_dm, ctrl_info_offset, (p_beamformee_entry->mu_reg_index + 1) << 16); |
| odm_write_1byte(p_dm, 0x81, 0x80); /*RPTBUF ready*/ |
| |
| PHYDM_DBG(p_dm, DBG_TXBF, ("@%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)); |
| } |
| #endif |
| } |
| |
| } |
| |
| |
| void |
| hal_txbf_8822b_leave( |
| void *p_dm_void, |
| u8 idx |
| ) |
| { |
| struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void; |
| struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm->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, 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, REG_ASSOCIATED_BFMER0_INFO_8822B, 0); |
| odm_write_2byte(p_dm, REG_ASSOCIATED_BFMER0_INFO_8822B + 4, 0); |
| odm_write_2byte(p_dm, REG_TX_CSI_RPT_PARAM_BW20_8822B, 0); |
| } else { |
| odm_write_4byte(p_dm, REG_ASSOCIATED_BFMER1_INFO_8822B, 0); |
| odm_write_2byte(p_dm, REG_ASSOCIATED_BFMER1_INFO_8822B + 4, 0); |
| odm_write_2byte(p_dm, 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, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl); |
| |
| odm_memory_set(p_dm, p_beamformer_entry->gid_valid, 0, 8); |
| odm_memory_set(p_dm, 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, 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, REG_TXBF_CTRL_8822B, 0x0); |
| odm_write_1byte(p_dm, REG_TXBF_CTRL_8822B + 3, odm_read_1byte(p_dm, REG_TXBF_CTRL_8822B + 3) | BIT(4) | BIT(6) | BIT(7)); |
| odm_write_2byte(p_dm, REG_ASSOCIATED_BFMEE_SEL_8822B, 0); |
| } else { |
| odm_write_2byte(p_dm, REG_TXBF_CTRL_8822B + 2, 0x0 | BIT(14) | BIT(15) | BIT(12)); |
| |
| odm_write_2byte(p_dm, REG_ASSOCIATED_BFMEE_SEL_8822B + 2, |
| odm_read_2byte(p_dm, 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, 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, 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 = (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->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 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, phydm_acting_as_ibss)) |
| beam_ctrl_val = p_beamform_entry->mac_id; |
| else |
| beam_ctrl_val = p_beamform_entry->p_aid; |
| |
| PHYDM_DBG(p_dm, DBG_TXBF, ("@%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 { |
| PHYDM_DBG(p_dm, DBG_TXBF, ("@%s, Don't apply Vmatrix", __func__)); |
| beam_ctrl_val &= ~(BIT(9) | BIT(10) | BIT(11)); |
| } |
| |
| odm_write_2byte(p_dm, beam_ctrl_reg, beam_ctrl_val); |
| /*disable NDP packet use beamforming */ |
| tmp_val = odm_read_2byte(p_dm, REG_TXBF_CTRL_8822B); |
| odm_write_2byte(p_dm, REG_TXBF_CTRL_8822B, tmp_val | BIT(15)); |
| } else { |
| PHYDM_DBG(p_dm, DBG_TXBF, ("@%s, MU Sounding Done\n", __func__)); |
| /*MU sounding done */ |
| if (1) { /* (p_beamform_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) { */ |
| PHYDM_DBG(p_dm, DBG_TXBF, ("@%s, BEAMFORMING_ENTRY_STATE_PROGRESSED\n", __func__)); |
| |
| value32 = odm_get_bb_reg(p_dm, 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, 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, 0x168C, MASKDWORD); |
| is_sounding_success[4] = (value32 & BIT(10)) ? 1 : 0; |
| is_sounding_success[5] = (value32 & BIT(26)) ? 1 : 0; |
| |
| PHYDM_DBG(p_dm, DBG_TXBF, ("@%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, 0xF4C, 0xFFFF0000); |
| /* odm_set_bb_reg(p_dm, 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, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl); |
| odm_set_mac_reg(p_dm, 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, 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 = (struct PHY_DM_STRUCT *)p_dm_void; |
| struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm->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; |
| |
| PHYDM_DBG(p_dm, DBG_TXBF, ("%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, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl); |
| odm_set_bb_reg(p_dm, 0x14c4, MASKDWORD, gid_valid); |
| odm_set_bb_reg(p_dm, 0x14c8, MASKDWORD, user_position_l); |
| odm_set_bb_reg(p_dm, 0x14cc, MASKDWORD, user_position_h); |
| |
| PHYDM_DBG(p_dm, DBG_TXBF, ("%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, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl); |
| odm_set_bb_reg(p_dm, 0x14c4, MASKDWORD, gid_valid); |
| odm_set_bb_reg(p_dm, 0x14c8, MASKDWORD, user_position_l); |
| odm_set_bb_reg(p_dm, 0x14cc, MASKDWORD, user_position_h); |
| |
| PHYDM_DBG(p_dm, DBG_TXBF, ("%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, 0x14c0, p_beamforming_info->reg_mu_tx_ctrl); |
| |
| } |
| |
| |
| |
| #if 0 |
| /*This function translate the bitmap to GTAB*/ |
| void |
| haltxbf8822b_gtab_translation( |
| struct PHY_DM_STRUCT *p_dm |
| ) |
| { |
| u8 idx, gid; |
| u8 id1, id0; |
| u32 gid_valid[6] = {0}; |
| u32 user_position_lsb[6] = {0}; |
| u32 user_position_msb[6] = {0}; |
| |
| 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); |
| } |
| |
| /*Pair 1*/ |
| gid = (idx << 1) + 1; |
| gid_valid[id0] |= (1 << gid); |
| gid_valid[id1] |= (1 << gid); |
| if (gid < 16) { |
| /*user_position_lsb[id0] |= (0 << (gid << 1));*/ |
| user_position_lsb[id1] |= (1 << (gid << 1)); |
| } else { |
| /*user_position_msb[id0] |= (0 << ((gid - 16) << 1));*/ |
| user_position_msb[id1] |= (1 << ((gid - 16) << 1)); |
| } |
| |
| /*Pair 2*/ |
| gid += 1; |
| gid_valid[id0] |= (1 << gid); |
| gid_valid[id1] |= (1 << gid); |
| if (gid < 16) { |
| user_position_lsb[id0] |= (1 << (gid << 1)); |
| /*user_position_lsb[id1] |= (0 << (gid << 1));*/ |
| } else { |
| user_position_msb[id0] |= (1 << ((gid - 16) << 1)); |
| /*user_position_msb[id1] |= (0 << ((gid - 16) << 1));*/ |
| } |
| |
| } |
| |
| |
| for (idx = 0; idx < 6; idx++) { |
| /*dbg_print("gid_valid[%d] = 0x%x\n", idx, gid_valid[idx]); |
| dbg_print("user_position[%d] = 0x%x %x\n", idx, user_position_msb[idx], user_position_lsb[idx]);*/ |
| } |
| } |
| #endif |
| |
| void |
| hal_txbf_8822b_fw_txbf( |
| void *p_dm_void, |
| u8 idx |
| ) |
| { |
| #if 0 |
| struct _RT_BEAMFORMING_INFO *p_beam_info = GET_BEAMFORM_INFO(adapter); |
| struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = p_beam_info->beamformee_entry + idx; |
| |
| if (p_beam_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSING) |
| hal_txbf_8822b_download_ndpa(adapter, idx); |
| |
| hal_txbf_8822b_fw_txbf_cmd(adapter); |
| #endif |
| } |
| |
| #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 = (struct PHY_DM_STRUCT *)p_dm_void; |
| u8 i; |
| |
| if (p_dm->rf_type == RF_1T1R) |
| return; |
| |
| if ((su_bfee_cnt > 0) || (mu_bfee_cnt > 0)) { |
| for (i = RF_PATH_A; i <= RF_PATH_B; i++) { |
| odm_set_rf_reg(p_dm, (enum rf_path)i, 0xEF, BIT(19), 0x1); /*RF mode table write enable*/ |
| odm_set_rf_reg(p_dm, (enum rf_path)i, 0x33, 0xF, 3); /*Select RX mode*/ |
| odm_set_rf_reg(p_dm, (enum rf_path)i, 0x3E, 0xfffff, 0x00036); /*Set Table data*/ |
| odm_set_rf_reg(p_dm, (enum rf_path)i, 0x3F, 0xfffff, 0x5AFCE); /*Set Table data*/ |
| odm_set_rf_reg(p_dm, (enum rf_path)i, 0xEF, BIT(19), 0x0); /*RF mode table write disable*/ |
| } |
| } |
| |
| odm_set_bb_reg(p_dm, 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, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x2); /*enable BB TxBF ant mapping register*/ |
| odm_set_bb_reg(p_dm, 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, REG_BB_TXBF_ANT_SET_BF1_8822B, 0xffff, 0x0433); |
| odm_set_bb_reg(p_dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x043); |
| |
| } else { |
| odm_set_bb_reg(p_dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(28) | BIT29, 0x0); /*enable BB TxBF ant mapping register*/ |
| odm_set_bb_reg(p_dm, REG_BB_TXBF_ANT_SET_BF1_8822B, BIT(31), 0); /*ignore user since 8822B only 2Tx*/ |
| |
| odm_set_bb_reg(p_dm, REG_BB_TX_PATH_SEL_1_8822B, 0xfff00000, 0x1); /*1SS by path-A*/ |
| odm_set_bb_reg(p_dm, 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 = (struct PHY_DM_STRUCT *)p_dm_void; |
| |
| if (enable_su_bfer) { |
| odm_set_bb_reg(p_dm, 0x19f8, BIT(22) | BIT(21) | BIT(20), 0x1); |
| odm_set_bb_reg(p_dm, 0x19f8, BIT(25) | BIT(24) | BIT(23), 0x0); |
| odm_set_bb_reg(p_dm, 0x19f8, BIT(16), 0x1); |
| |
| if (is_vht) |
| odm_set_bb_reg(p_dm, 0x19f0, BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x1f); |
| else |
| odm_set_bb_reg(p_dm, 0x19f0, BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0), 0x22); |
| |
| odm_set_bb_reg(p_dm, 0x19f0, BIT(7) | BIT(6), nc); |
| odm_set_bb_reg(p_dm, 0x19f0, BIT(9) | BIT(8), nr); |
| odm_set_bb_reg(p_dm, 0x19f0, BIT(11) | BIT(10), ng); |
| odm_set_bb_reg(p_dm, 0x19f0, BIT(13) | BIT(12), CB); |
| |
| odm_set_bb_reg(p_dm, 0xb58, BIT(3) | BIT(2), BW); |
| odm_set_bb_reg(p_dm, 0xb58, BIT(7) | BIT(6) | BIT(5) | BIT(4), 0x0); |
| odm_set_bb_reg(p_dm, 0xb58, BIT(9) | BIT(8), BW); |
| odm_set_bb_reg(p_dm, 0xb58, BIT(13) | BIT(12) | BIT(11) | BIT(10), 0x0); |
| } else |
| odm_set_bb_reg(p_dm, 0x19f8, BIT(16), 0x0); |
| |
| PHYDM_DBG(p_dm, DBG_TXBF, ("[%s] enable_su_bfer = %d, is_vht = %d\n", __func__, enable_su_bfer, is_vht)); |
| PHYDM_DBG(p_dm, DBG_TXBF, ("[%s] nc = %d, nr = %d, ng = %d, CB = %d, BW = %d\n", __func__, nc, nr, ng, CB, BW)); |
| |
| |
| } |
| #endif |
| #endif /* (RTL8822B_SUPPORT == 1)*/ |