1 /* ************************************************************
4 * This file is for 8814A TXBF mechanism
6 * ************************************************************ */
8 #include "mp_precomp.h"
9 #include "../phydm_precomp.h"
11 #if (BEAMFORMING_SUPPORT == 1)
12 #if (RTL8814A_SUPPORT == 1)
15 phydm_beamforming_set_iqgen_8814A(
19 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
24 for (i = ODM_RF_PATH_A ; i < MAX_RF_PATH ; i++)
25 odm_set_rf_reg(p_dm_odm, i, RF_WE_LUT, 0x80000, 0x1); /*RF mode table write enable*/
29 for (i = ODM_RF_PATH_A; i < MAX_RF_PATH; i++)
30 odm_set_rf_reg(p_dm_odm, i, RF_RCK_OS, 0xfffff, 0x18000); /*Select Rx mode*/
34 for (i = ODM_RF_PATH_A; i < MAX_RF_PATH; i++)
35 rf_mode[i] = odm_get_rf_reg(p_dm_odm, i, RF_RCK_OS, 0xfffff);
37 if ((rf_mode[0] == 0x180000) && (rf_mode[1] == 0x180000) && (rf_mode[2] == 0x180000) && (rf_mode[3] == 0x180000))
39 else if (counter == 100) {
40 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_TRACE, ("iqgen setting fail:8814A\n"));
45 for (i = ODM_RF_PATH_A ; i < MAX_RF_PATH ; i++) {
46 odm_set_rf_reg(p_dm_odm, i, RF_TXPA_G1, 0xfffff, 0xBE77F); /*Set Table data*/
47 odm_set_rf_reg(p_dm_odm, i, RF_TXPA_G2, 0xfffff, 0x226BF); /*Enable TXIQGEN in Rx mode*/
49 odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_TXPA_G2, 0xfffff, 0xE26BF); /*Enable TXIQGEN in Rx mode*/
51 for (i = ODM_RF_PATH_A; i < MAX_RF_PATH; i++)
52 odm_set_rf_reg(p_dm_odm, i, RF_WE_LUT, 0x80000, 0x0); /*RF mode table write disable*/
61 hal_txbf_8814a_set_ndpa_rate(
67 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
69 odm_write_1byte(p_dm_odm, REG_NDPA_OPT_CTRL_8814A, BW);
70 odm_write_1byte(p_dm_odm, REG_NDPA_RATE_8814A, (u8) rate);
74 #define PHYDM_MEMORY_MAP_BUF_READ 0x8000
75 #define PHYDM_CTRL_INFO_PAGE 0x660
78 phydm_data_rate_8814a(
79 struct PHY_DM_STRUCT *p_dm_odm,
86 u16 x_read_data_addr = 0;
88 odm_write_2byte(p_dm_odm, REG_PKTBUF_DBG_CTRL_8814A, PHYDM_CTRL_INFO_PAGE);
89 x_read_data_addr = PHYDM_MEMORY_MAP_BUF_READ + mac_id * 32; /*Ctrl Info: 32Bytes for each macid(n)*/
91 if ((x_read_data_addr < PHYDM_MEMORY_MAP_BUF_READ) || (x_read_data_addr > 0x8FFF)) {
92 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("x_read_data_addr(0x%x) is not correct!\n", x_read_data_addr));
97 for (i = 0; i < data_len; i++)
98 *(data + i) = odm_read_2byte(p_dm_odm, x_read_data_addr + i);
103 hal_txbf_8814a_get_tx_rate(
107 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
108 struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
109 struct _RT_BEAMFORMEE_ENTRY *p_entry;
113 p_entry = &(p_beam_info->beamformee_entry[p_beam_info->beamformee_cur_idx]);
115 phydm_data_rate_8814a(p_dm_odm, (u8)p_entry->mac_id, &tx_rpt_data, 1);
116 data_rate = (u8)tx_rpt_data;
117 data_rate &= 0x7f; /*Bit7 indicates SGI*/
119 p_dm_odm->tx_bf_data_rate = data_rate;
121 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] p_dm_odm->tx_bf_data_rate = 0x%x\n", __func__, p_dm_odm->tx_bf_data_rate));
125 hal_txbf_8814a_reset_tx_path(
130 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
131 #if DEV_BUS_TYPE == RT_USB_INTERFACE
132 struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info;
133 struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
134 u8 nr_index = 0, tx_ss = 0;
136 if (idx < BEAMFORMEE_ENTRY_NUM)
137 beamformee_entry = p_beamforming_info->beamformee_entry[idx];
141 if ((p_dm_odm->last_usb_hub) != (*p_dm_odm->hub_usb_mode)) {
142 nr_index = tx_bf_nr(hal_txbf_8814a_get_ntx(p_dm_odm), beamformee_entry.comp_steering_num_of_bfer);
144 if (*p_dm_odm->hub_usb_mode == 2) {
145 if (p_dm_odm->rf_type == ODM_4T4R)
147 else if (p_dm_odm->rf_type == ODM_3T3R)
151 } else if (*p_dm_odm->hub_usb_mode == 1) /*USB 2.0 always 2Tx*/
157 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x93f);
158 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKDWORD, 0x93f93f0);
159 } else if (tx_ss == 0xe) {
160 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x93e);
161 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKDWORD, 0x93e93e0);
162 } else if (tx_ss == 0x6) {
163 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x936);
164 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKLWORD, 0x9360);
172 case 1: /*Nsts = 2 BC*/
173 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x9366); /*tx2path, BC*/
176 case 2: /*Nsts = 3 BCD*/
177 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93e93ee); /*tx3path, BCD*/
180 default: /*nr>3, same as Case 3*/
181 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93f93ff); /*tx4path, ABCD*/
189 case 1: /*Nsts = 2 BC*/
190 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x9366); /*tx2path, BC*/
193 case 2: /*Nsts = 3 BCD*/
194 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93e93ee); /*tx3path, BCD*/
197 default: /*nr>3, same as Case 3*/
198 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93f93ff); /*tx4path, ABCD*/
203 p_dm_odm->last_usb_hub = *p_dm_odm->hub_usb_mode;
211 hal_txbf_8814a_get_ntx(
215 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
216 u8 ntx = 0, tx_ss = 3;
218 #if DEV_BUS_TYPE == RT_USB_INTERFACE
219 tx_ss = *p_dm_odm->hub_usb_mode;
221 if (tx_ss == 3 || tx_ss == 2) {
222 if (p_dm_odm->rf_type == ODM_4T4R)
224 else if (p_dm_odm->rf_type == ODM_3T3R)
228 } else if (tx_ss == 1) /*USB 2.0 always 2Tx*/
233 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] ntx = %d\n", __func__, ntx));
238 hal_txbf_8814a_get_nrx(
242 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
245 if (p_dm_odm->rf_type == ODM_4T4R)
247 else if (p_dm_odm->rf_type == ODM_3T3R)
249 else if (p_dm_odm->rf_type == ODM_2T2R)
251 else if (p_dm_odm->rf_type == ODM_2T3R)
253 else if (p_dm_odm->rf_type == ODM_2T4R)
255 else if (p_dm_odm->rf_type == ODM_1T1R)
257 else if (p_dm_odm->rf_type == ODM_1T2R)
262 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] nrx = %d\n", __func__, nrx));
267 hal_txbf_8814a_rf_mode(
269 struct _RT_BEAMFORMING_INFO *p_beamforming_info,
273 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
275 u8 tx_ss = 3; /*default use 3 Tx*/
276 struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
278 if (idx < BEAMFORMEE_ENTRY_NUM)
279 beamformee_entry = p_beamforming_info->beamformee_entry[idx];
283 nr_index = tx_bf_nr(hal_txbf_8814a_get_ntx(p_dm_odm), beamformee_entry.comp_steering_num_of_bfer);
285 if (p_dm_odm->rf_type == ODM_1T1R)
288 if (p_beamforming_info->beamformee_su_cnt > 0) {
289 #if DEV_BUS_TYPE == RT_USB_INTERFACE
290 p_dm_odm->last_usb_hub = *p_dm_odm->hub_usb_mode;
291 tx_ss = *p_dm_odm->hub_usb_mode;
293 if (tx_ss == 3 || tx_ss == 2) {
294 if (p_dm_odm->rf_type == ODM_4T4R)
296 else if (p_dm_odm->rf_type == ODM_3T3R)
300 } else if (tx_ss == 1) /*USB 2.0 always 2Tx*/
306 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x93f);
307 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKDWORD, 0x93f93f0);
308 } else if (tx_ss == 0xe) {
309 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x93e);
310 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKDWORD, 0x93e93e0);
311 } else if (tx_ss == 0x6) {
312 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x936);
313 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKLWORD, 0x9360);
316 /*for 8814 19ac(idx 1), 19b4(idx 0), different Tx ant setting*/
317 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, BIT(28) | BIT29, 0x2); /*enable BB TxBF ant mapping register*/
318 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, BIT30, 0x1); /*if Nsts > Nc don't apply V matrix*/
325 case 1: /*Nsts = 2 BC*/
326 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x9366); /*tx2path, BC*/
329 case 2: /*Nsts = 3 BCD*/
330 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93e93ee); /*tx3path, BCD*/
333 default: /*nr>3, same as Case 3*/
334 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93f93ff); /*tx4path, ABCD*/
343 case 1: /*Nsts = 2 BC*/
344 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x9366); /*tx2path, BC*/
347 case 2: /*Nsts = 3 BCD*/
348 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93e93ee); /*tx3path, BCD*/
351 default: /*nr>3, same as Case 3*/
352 odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93f93ff); /*tx4path, ABCD*/
358 if ((p_beamforming_info->beamformee_su_cnt == 0) && (p_beamforming_info->beamformer_su_cnt == 0)) {
359 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x932); /*set tx_path selection for 8814a BFer bug refine*/
360 odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKDWORD, 0x93e9360);
365 hal_txbf_8814a_download_ndpa(
370 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
371 u8 u1b_tmp = 0, tmp_reg422 = 0;
372 u8 bcn_valid_reg = 0, count = 0, dl_bcn_count = 0;
373 u16 head_page = 0x7FE;
374 boolean is_send_beacon = false;
375 u16 tx_page_bndy = LAST_ENTRY_OF_TX_PKT_BUFFER_8814A; /*default reseved 1 page for the IC type which is undefined.*/
376 struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
377 struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = p_beam_info->beamformee_entry + idx;
378 struct _ADAPTER *adapter = p_dm_odm->adapter;
380 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
381 *p_dm_odm->p_is_fw_dw_rsvd_page_in_progress = true;
383 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));
385 phydm_get_hal_def_var_handler_interface(p_dm_odm, HAL_DEF_TX_PAGE_BOUNDARY, (u16 *)&tx_page_bndy);
387 /*Set REG_CR bit 8. DMA beacon by SW.*/
388 u1b_tmp = odm_read_1byte(p_dm_odm, REG_CR_8814A + 1);
389 odm_write_1byte(p_dm_odm, REG_CR_8814A + 1, (u1b_tmp | BIT(0)));
392 /*Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.*/
393 tmp_reg422 = odm_read_1byte(p_dm_odm, REG_FWHW_TXQ_CTRL_8814A + 2);
394 odm_write_1byte(p_dm_odm, REG_FWHW_TXQ_CTRL_8814A + 2, tmp_reg422 & (~BIT(6)));
396 if (tmp_reg422 & BIT(6)) {
397 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: There is an adapter is sending beacon.\n", __func__));
398 is_send_beacon = true;
401 /*0x204[11:0] Beacon Head for TXDMA*/
402 odm_write_2byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A, head_page);
405 /*Clear beacon valid check bit.*/
406 bcn_valid_reg = odm_read_1byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A + 1);
407 odm_write_1byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A + 1, (bcn_valid_reg | BIT(7)));
409 /*download NDPA rsvd page.*/
410 if (p_beam_entry->beamform_entry_cap & BEAMFORMER_CAP_VHT_SU)
411 beamforming_send_vht_ndpa_packet(p_dm_odm, p_beam_entry->mac_addr, p_beam_entry->AID, p_beam_entry->sound_bw, BEACON_QUEUE);
413 beamforming_send_ht_ndpa_packet(p_dm_odm, p_beam_entry->mac_addr, p_beam_entry->sound_bw, BEACON_QUEUE);
415 /*check rsvd page download OK.*/
416 bcn_valid_reg = odm_read_1byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A + 1);
418 while (!(bcn_valid_reg & BIT(7)) && count < 20) {
421 bcn_valid_reg = odm_read_1byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A + 2);
424 } while (!(bcn_valid_reg & BIT(7)) && dl_bcn_count < 5);
426 if (!(bcn_valid_reg & BIT(7)))
427 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Download RSVD page failed!\n", __func__));
429 /*0x204[11:0] Beacon Head for TXDMA*/
430 odm_write_2byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A, tx_page_bndy);
432 /*To make sure that if there exists an adapter which would like to send beacon.*/
433 /*If exists, the origianl value of 0x422[6] will be 1, we should check this to*/
434 /*prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
435 /*the beacon cannot be sent by HW.*/
436 /*2010.06.23. Added by tynli.*/
438 odm_write_1byte(p_dm_odm, REG_FWHW_TXQ_CTRL_8814A + 2, tmp_reg422);
440 /*Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.*/
441 /*Clear CR[8] or beacon packet will not be send to TxBuf anymore.*/
442 u1b_tmp = odm_read_1byte(p_dm_odm, REG_CR_8814A + 1);
443 odm_write_1byte(p_dm_odm, REG_CR_8814A + 1, (u1b_tmp & (~BIT(0))));
445 p_beam_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSED;
447 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
448 *p_dm_odm->p_is_fw_dw_rsvd_page_in_progress = false;
453 hal_txbf_8814a_fw_txbf_cmd(
457 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
459 u8 PageNum0 = 0xFF, PageNum1 = 0xFF;
460 u8 u1_tx_bf_parm[3] = {0};
461 struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
463 for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {
464 if (p_beam_info->beamformee_entry[idx].is_used && p_beam_info->beamformee_entry[idx].beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
465 if (p_beam_info->beamformee_entry[idx].is_sound) {
468 period = (u8)(p_beam_info->beamformee_entry[idx].sound_period);
469 } else if (PageNum0 == 0xFF) {
470 PageNum0 = 0xFF; /*stop sounding*/
476 u1_tx_bf_parm[0] = PageNum0;
477 u1_tx_bf_parm[1] = PageNum1;
478 u1_tx_bf_parm[2] = period;
479 odm_fill_h2c_cmd(p_dm_odm, PHYDM_H2C_TXBF, 3, u1_tx_bf_parm);
481 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD,
482 ("[%s] PageNum0 = %d, PageNum1 = %d period = %d\n", __func__, PageNum0, PageNum1, period));
486 hal_txbf_8814a_enter(
491 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
493 u8 bfer_idx = (bfer_bfee_idx & 0xF0) >> 4;
494 u8 bfee_idx = (bfer_bfee_idx & 0xF);
495 struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info;
496 struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
497 struct _RT_BEAMFORMER_ENTRY beamformer_entry;
498 u16 sta_id = 0, csi_param = 0;
499 u8 nc_index = 0, nr_index = 0, grouping = 0, codebookinfo = 0, coefficientsize = 0;
501 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] bfer_idx=%d, bfee_idx=%d\n", __func__, bfer_idx, bfee_idx));
502 odm_set_mac_reg(p_dm_odm, REG_SND_PTCL_CTRL_8814A, MASKBYTE1 | MASKBYTE2, 0x0202);
504 if ((p_beamforming_info->beamformer_su_cnt > 0) && (bfer_idx < BEAMFORMER_ENTRY_NUM)) {
505 beamformer_entry = p_beamforming_info->beamformer_entry[bfer_idx];
506 /*Sounding protocol control*/
507 odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8814A, 0xDB);
509 /*MAC address/Partial AID of Beamformer*/
511 for (i = 0; i < 6 ; i++)
512 odm_write_1byte(p_dm_odm, (REG_ASSOCIATED_BFMER0_INFO_8814A + i), beamformer_entry.mac_addr[i]);
514 for (i = 0; i < 6 ; i++)
515 odm_write_1byte(p_dm_odm, (REG_ASSOCIATED_BFMER1_INFO_8814A + i), beamformer_entry.mac_addr[i]);
518 /*CSI report parameters of Beamformer*/
519 nc_index = hal_txbf_8814a_get_nrx(p_dm_odm); /*for 8814A nrx = 3(4 ant), min=0(1 ant)*/
520 nr_index = 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*/
524 /*for ac = 1, for n = 3*/
525 if (beamformer_entry.beamform_entry_cap & BEAMFORMEE_CAP_VHT_SU)
527 else if (beamformer_entry.beamform_entry_cap & BEAMFORMEE_CAP_HT_EXPLICIT)
532 csi_param = (u16)((coefficientsize << 10) | (codebookinfo << 8) | (grouping << 6) | (nr_index << 3) | (nc_index));
535 odm_write_2byte(p_dm_odm, REG_CSI_RPT_PARAM_BW20_8814A, csi_param);
537 odm_write_2byte(p_dm_odm, REG_CSI_RPT_PARAM_BW20_8814A + 2, csi_param);
538 /*ndp_rx_standby_timer, 8814 need > 0x56, suggest from Dvaid*/
539 odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8814A + 3, 0x40);
543 if ((p_beamforming_info->beamformee_su_cnt > 0) && (bfee_idx < BEAMFORMEE_ENTRY_NUM)) {
544 beamformee_entry = p_beamforming_info->beamformee_entry[bfee_idx];
546 hal_txbf_8814a_rf_mode(p_dm_odm, p_beamforming_info, bfee_idx);
548 if (phydm_acting_determine(p_dm_odm, phydm_acting_as_ibss))
549 sta_id = beamformee_entry.mac_id;
551 sta_id = beamformee_entry.p_aid;
553 /*P_AID of Beamformee & enable NDPA transmission & enable NDPA interrupt*/
555 odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A, sta_id);
556 odm_write_1byte(p_dm_odm, REG_TXBF_CTRL_8814A + 3, odm_read_1byte(p_dm_odm, REG_TXBF_CTRL_8814A + 3) | BIT(4) | BIT(6) | BIT(7));
558 odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A + 2, sta_id | BIT(14) | BIT(15) | BIT(12));
560 /*CSI report parameters of Beamformee*/
562 /*Get BIT24 & BIT25*/
563 u8 tmp = odm_read_1byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A + 3) & 0x3;
565 odm_write_1byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A + 3, tmp | 0x60);
566 odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A, sta_id);
568 odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A + 2, sta_id | 0xE200); /*Set BIT25*/
570 phydm_beamforming_notify(p_dm_odm);
577 hal_txbf_8814a_leave(
582 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
583 struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info;
584 struct _RT_BEAMFORMER_ENTRY beamformer_entry;
585 struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
587 if (idx < BEAMFORMER_ENTRY_NUM) {
588 beamformer_entry = p_beamforming_info->beamformer_entry[idx];
589 beamformee_entry = p_beamforming_info->beamformee_entry[idx];
593 /*Clear P_AID of Beamformee*/
594 /*Clear MAC address of Beamformer*/
595 /*Clear Associated Bfmee Sel*/
597 if (beamformer_entry.beamform_entry_cap == BEAMFORMING_CAP_NONE) {
598 odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8814A, 0xD8);
600 odm_write_4byte(p_dm_odm, REG_ASSOCIATED_BFMER0_INFO_8814A, 0);
601 odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMER0_INFO_8814A + 4, 0);
602 odm_write_2byte(p_dm_odm, REG_CSI_RPT_PARAM_BW20_8814A, 0);
604 odm_write_4byte(p_dm_odm, REG_ASSOCIATED_BFMER1_INFO_8814A, 0);
605 odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMER1_INFO_8814A + 4, 0);
606 odm_write_2byte(p_dm_odm, REG_CSI_RPT_PARAM_BW20_8814A + 2, 0);
610 if (beamformee_entry.beamform_entry_cap == BEAMFORMING_CAP_NONE) {
611 hal_txbf_8814a_rf_mode(p_dm_odm, p_beamforming_info, idx);
613 odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A, 0x0);
614 odm_write_1byte(p_dm_odm, REG_TXBF_CTRL_8814A + 3, odm_read_1byte(p_dm_odm, REG_TXBF_CTRL_8814A + 3) | BIT(4) | BIT(6) | BIT(7));
615 odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A, 0);
617 odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A + 2, 0x0 | BIT(14) | BIT(15) | BIT(12));
619 odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A + 2, odm_read_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A + 2) & 0x60);
625 hal_txbf_8814a_status(
630 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
631 u16 beam_ctrl_val, tmp_val;
633 struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info;
634 struct _RT_BEAMFORMEE_ENTRY beamform_entry;
636 if (idx < BEAMFORMEE_ENTRY_NUM)
637 beamform_entry = p_beamforming_info->beamformee_entry[idx];
641 if (phydm_acting_determine(p_dm_odm, phydm_acting_as_ibss))
642 beam_ctrl_val = beamform_entry.mac_id;
644 beam_ctrl_val = beamform_entry.p_aid;
646 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, beamform_entry.beamform_entry_state = %d", __func__, beamform_entry.beamform_entry_state));
649 beam_ctrl_reg = REG_TXBF_CTRL_8814A;
651 beam_ctrl_reg = REG_TXBF_CTRL_8814A + 2;
652 beam_ctrl_val |= BIT(12) | BIT(14) | BIT(15);
655 if ((beamform_entry.beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) && (p_beamforming_info->apply_v_matrix == true)) {
656 if (beamform_entry.sound_bw == CHANNEL_WIDTH_20)
657 beam_ctrl_val |= BIT(9);
658 else if (beamform_entry.sound_bw == CHANNEL_WIDTH_40)
659 beam_ctrl_val |= (BIT(9) | BIT(10));
660 else if (beamform_entry.sound_bw == CHANNEL_WIDTH_80)
661 beam_ctrl_val |= (BIT(9) | BIT(10) | BIT(11));
663 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, Don't apply Vmatrix", __func__));
664 beam_ctrl_val &= ~(BIT(9) | BIT(10) | BIT(11));
667 odm_write_2byte(p_dm_odm, beam_ctrl_reg, beam_ctrl_val);
668 /*disable NDP packet use beamforming */
669 tmp_val = odm_read_2byte(p_dm_odm, REG_TXBF_CTRL_8814A);
670 odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A, tmp_val | BIT(15));
679 hal_txbf_8814a_fw_txbf(
685 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
686 struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
687 struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = p_beam_info->beamformee_entry + idx;
689 ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));
691 if (p_beam_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSING)
692 hal_txbf_8814a_download_ndpa(p_dm_odm, idx);
694 hal_txbf_8814a_fw_txbf_cmd(p_dm_odm);
698 #endif /* (RTL8814A_SUPPORT == 1)*/