haltxbf8192e.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /* ************************************************************
  2. * Description:
  3. *
  4. * This file is for 8192E TXBF mechanism
  5. *
  6. * ************************************************************ */
  7. #include "mp_precomp.h"
  8. #include "../phydm_precomp.h"
  9. #if (BEAMFORMING_SUPPORT == 1)
  10. #if (RTL8192E_SUPPORT == 1)
  11. void
  12. hal_txbf_8192e_set_ndpa_rate(
  13. void *p_dm_void,
  14. u8 BW,
  15. u8 rate
  16. )
  17. {
  18. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  19. odm_write_1byte(p_dm_odm, REG_NDPA_OPT_CTRL_8192E, (rate << 2 | BW));
  20. }
  21. void
  22. hal_txbf_8192e_rf_mode(
  23. void *p_dm_void,
  24. struct _RT_BEAMFORMING_INFO *p_beam_info
  25. )
  26. {
  27. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  28. boolean is_self_beamformer = false;
  29. boolean is_self_beamformee = false;
  30. enum beamforming_cap beamform_cap = BEAMFORMING_CAP_NONE;
  31. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));
  32. if (p_dm_odm->rf_type == ODM_1T1R)
  33. return;
  34. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x1); /*RF mode table write enable*/
  35. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, RF_WE_LUT, 0x80000, 0x1); /*RF mode table write enable*/
  36. if (p_beam_info->beamformee_su_cnt > 0) {
  37. /*Path_A*/
  38. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*Select RX mode 0x30=0x18000*/
  39. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x0000f); /*Set Table data*/
  40. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0x77fc2); /*Enable TXIQGEN in RX mode*/
  41. /*Path_B*/
  42. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x30, 0xfffff, 0x18000); /*Select RX mode*/
  43. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x31, 0xfffff, 0x0000f); /*Set Table data*/
  44. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x32, 0xfffff, 0x77fc2); /*Enable TXIQGEN in RX mode*/
  45. } else {
  46. /*Path_A*/
  47. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x30, 0xfffff, 0x18000); /*Select RX mode*/
  48. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x31, 0xfffff, 0x0000f); /*Set Table data*/
  49. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, 0x32, 0xfffff, 0x77f82); /*Disable TXIQGEN in RX mode*/
  50. /*Path_B*/
  51. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x30, 0xfffff, 0x18000); /*Select RX mode*/
  52. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x31, 0xfffff, 0x0000f); /*Set Table data*/
  53. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, 0x32, 0xfffff, 0x77f82); /*Disable TXIQGEN in RX mode*/
  54. }
  55. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_WE_LUT, 0x80000, 0x0); /*RF mode table write disable*/
  56. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_B, RF_WE_LUT, 0x80000, 0x0); /*RF mode table write disable*/
  57. if (p_beam_info->beamformee_su_cnt > 0) {
  58. odm_set_bb_reg(p_dm_odm, 0x90c, MASKDWORD, 0x83321333);
  59. odm_set_bb_reg(p_dm_odm, 0xa04, MASKBYTE3, 0xc1);
  60. } else
  61. odm_set_bb_reg(p_dm_odm, 0x90c, MASKDWORD, 0x81121313);
  62. }
  63. void
  64. hal_txbf_8192e_fw_txbf_cmd(
  65. void *p_dm_void
  66. )
  67. {
  68. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  69. u8 idx, period0 = 0, period1 = 0;
  70. u8 PageNum0 = 0xFF, PageNum1 = 0xFF;
  71. u8 u1_tx_bf_parm[3] = {0};
  72. struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
  73. for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {
  74. if (p_beam_info->beamformee_entry[idx].beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
  75. if (idx == 0) {
  76. if (p_beam_info->beamformee_entry[idx].is_sound)
  77. PageNum0 = 0xFE;
  78. else
  79. PageNum0 = 0xFF; /* stop sounding */
  80. period0 = (u8)(p_beam_info->beamformee_entry[idx].sound_period);
  81. } else if (idx == 1) {
  82. if (p_beam_info->beamformee_entry[idx].is_sound)
  83. PageNum1 = 0xFE;
  84. else
  85. PageNum1 = 0xFF; /* stop sounding */
  86. period1 = (u8)(p_beam_info->beamformee_entry[idx].sound_period);
  87. }
  88. }
  89. }
  90. u1_tx_bf_parm[0] = PageNum0;
  91. u1_tx_bf_parm[1] = PageNum1;
  92. u1_tx_bf_parm[2] = (period1 << 4) | period0;
  93. odm_fill_h2c_cmd(p_dm_odm, PHYDM_H2C_TXBF, 3, u1_tx_bf_parm);
  94. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD,
  95. ("[%s] PageNum0 = %d period0 = %d, PageNum1 = %d period1 %d\n", __func__, PageNum0, period0, PageNum1, period1));
  96. }
  97. void
  98. hal_txbf_8192e_download_ndpa(
  99. void *p_dm_void,
  100. u8 idx
  101. )
  102. {
  103. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  104. u8 u1b_tmp = 0, tmp_reg422 = 0, head_page;
  105. u8 bcn_valid_reg = 0, count = 0, dl_bcn_count = 0;
  106. boolean is_send_beacon = false;
  107. struct _ADAPTER *adapter = p_dm_odm->adapter;
  108. u8 tx_page_bndy = LAST_ENTRY_OF_TX_PKT_BUFFER_8812;
  109. /*default reseved 1 page for the IC type which is undefined.*/
  110. struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
  111. struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = p_beam_info->beamformee_entry + idx;
  112. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));
  113. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  114. *p_dm_odm->p_is_fw_dw_rsvd_page_in_progress = true;
  115. #endif
  116. if (idx == 0)
  117. head_page = 0xFE;
  118. else
  119. head_page = 0xFE;
  120. phydm_get_hal_def_var_handler_interface(p_dm_odm, HAL_DEF_TX_PAGE_BOUNDARY, (u8 *)&tx_page_bndy);
  121. /*Set REG_CR bit 8. DMA beacon by SW.*/
  122. u1b_tmp = odm_read_1byte(p_dm_odm, REG_CR_8192E+1);
  123. odm_write_1byte(p_dm_odm, REG_CR_8192E+1, (u1b_tmp | BIT(0)));
  124. /*Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.*/
  125. tmp_reg422 = odm_read_1byte(p_dm_odm, REG_FWHW_TXQ_CTRL_8192E+2);
  126. odm_write_1byte(p_dm_odm, REG_FWHW_TXQ_CTRL_8192E+2, tmp_reg422 & (~BIT(6)));
  127. if (tmp_reg422 & BIT(6)) {
  128. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_WARNING, ("%s There is an adapter is sending beacon.\n", __func__));
  129. is_send_beacon = true;
  130. }
  131. /*TDECTRL[15:8] 0x209[7:0] = 0xFE/0xFD NDPA Head for TXDMA*/
  132. odm_write_1byte(p_dm_odm, REG_DWBCN0_CTRL_8192E+1, head_page);
  133. do {
  134. /*Clear beacon valid check bit.*/
  135. bcn_valid_reg = odm_read_1byte(p_dm_odm, REG_DWBCN0_CTRL_8192E+2);
  136. odm_write_1byte(p_dm_odm, REG_DWBCN0_CTRL_8192E+2, (bcn_valid_reg | BIT(0)));
  137. /* download NDPA rsvd page. */
  138. beamforming_send_ht_ndpa_packet(p_dm_odm, p_beam_entry->mac_addr, p_beam_entry->sound_bw, BEACON_QUEUE);
  139. #if (DEV_BUS_TYPE == RT_PCI_INTERFACE)
  140. u1b_tmp = odm_read_1byte(p_dm_odm, REG_MGQ_TXBD_NUM_8192E+3);
  141. count = 0;
  142. while ((count < 20) && (u1b_tmp & BIT(4))) {
  143. count++;
  144. ODM_delay_us(10);
  145. u1b_tmp = odm_read_1byte(p_dm_odm, REG_MGQ_TXBD_NUM_8192E+3);
  146. }
  147. odm_write_1byte(p_dm_odm, REG_MGQ_TXBD_NUM_8192E+3, u1b_tmp | BIT(4));
  148. #endif
  149. /*check rsvd page download OK.*/
  150. bcn_valid_reg = odm_read_1byte(p_dm_odm, REG_DWBCN0_CTRL_8192E+2);
  151. count = 0;
  152. while (!(bcn_valid_reg & BIT(0)) && count < 20) {
  153. count++;
  154. ODM_delay_us(10);
  155. bcn_valid_reg = odm_read_1byte(p_dm_odm, REG_DWBCN0_CTRL_8192E+2);
  156. }
  157. dl_bcn_count++;
  158. } while (!(bcn_valid_reg & BIT(0)) && dl_bcn_count < 5);
  159. if (!(bcn_valid_reg & BIT(0)))
  160. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_WARNING, ("%s Download RSVD page failed!\n", __func__));
  161. /*TDECTRL[15:8] 0x209[7:0] = 0xF9 Beacon Head for TXDMA*/
  162. odm_write_1byte(p_dm_odm, REG_DWBCN0_CTRL_8192E+1, tx_page_bndy);
  163. /*To make sure that if there exists an adapter which would like to send beacon.*/
  164. /*If exists, the origianl value of 0x422[6] will be 1, we should check this to*/
  165. /*prevent from setting 0x422[6] to 0 after download reserved page, or it will cause*/
  166. /*the beacon cannot be sent by HW.*/
  167. /*2010.06.23. Added by tynli.*/
  168. if (is_send_beacon)
  169. odm_write_1byte(p_dm_odm, REG_FWHW_TXQ_CTRL_8192E+2, tmp_reg422);
  170. /*Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.*/
  171. /*Clear CR[8] or beacon packet will not be send to TxBuf anymore.*/
  172. u1b_tmp = odm_read_1byte(p_dm_odm, REG_CR_8192E+1);
  173. odm_write_1byte(p_dm_odm, REG_CR_8192E+1, (u1b_tmp & (~BIT(0))));
  174. p_beam_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSED;
  175. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  176. *p_dm_odm->p_is_fw_dw_rsvd_page_in_progress = false;
  177. #endif
  178. }
  179. void
  180. hal_txbf_8192e_enter(
  181. void *p_dm_void,
  182. u8 bfer_bfee_idx
  183. )
  184. {
  185. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  186. u8 i = 0;
  187. u8 bfer_idx = (bfer_bfee_idx & 0xF0) >> 4;
  188. u8 bfee_idx = (bfer_bfee_idx & 0xF);
  189. u32 csi_param;
  190. struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info;
  191. struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
  192. struct _RT_BEAMFORMER_ENTRY beamformer_entry;
  193. u16 sta_id = 0;
  194. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));
  195. hal_txbf_8192e_rf_mode(p_dm_odm, p_beamforming_info);
  196. if (p_dm_odm->rf_type == ODM_2T2R)
  197. odm_write_4byte(p_dm_odm, 0xd80, 0x00000000); /*nc =2*/
  198. if ((p_beamforming_info->beamformer_su_cnt > 0) && (bfer_idx < BEAMFORMER_ENTRY_NUM)) {
  199. beamformer_entry = p_beamforming_info->beamformer_entry[bfer_idx];
  200. /*Sounding protocol control*/
  201. odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8192E, 0xCB);
  202. /*MAC address/Partial AID of Beamformer*/
  203. if (bfer_idx == 0) {
  204. for (i = 0; i < 6 ; i++)
  205. odm_write_1byte(p_dm_odm, (REG_ASSOCIATED_BFMER0_INFO_8192E+i), beamformer_entry.mac_addr[i]);
  206. } else {
  207. for (i = 0; i < 6 ; i++)
  208. odm_write_1byte(p_dm_odm, (REG_ASSOCIATED_BFMER1_INFO_8192E+i), beamformer_entry.mac_addr[i]);
  209. }
  210. /*CSI report parameters of Beamformer Default use nc = 2*/
  211. csi_param = 0x03090309;
  212. odm_write_4byte(p_dm_odm, REG_CSI_RPT_PARAM_BW20_8192E, csi_param);
  213. odm_write_4byte(p_dm_odm, REG_CSI_RPT_PARAM_BW40_8192E, csi_param);
  214. odm_write_4byte(p_dm_odm, REG_CSI_RPT_PARAM_BW80_8192E, csi_param);
  215. /*Timeout value for MAC to leave NDP_RX_standby_state (60 us, Test chip) (80 us, MP chip)*/
  216. odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8192E+3, 0x50);
  217. }
  218. if ((p_beamforming_info->beamformee_su_cnt > 0) && (bfee_idx < BEAMFORMEE_ENTRY_NUM)) {
  219. beamformee_entry = p_beamforming_info->beamformee_entry[bfee_idx];
  220. if (phydm_acting_determine(p_dm_odm, phydm_acting_as_ibss))
  221. sta_id = beamformee_entry.mac_id;
  222. else
  223. sta_id = beamformee_entry.p_aid;
  224. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s], sta_id=0x%X\n", __func__, sta_id));
  225. /*P_AID of Beamformee & enable NDPA transmission & enable NDPA interrupt*/
  226. if (bfee_idx == 0) {
  227. odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8192E, sta_id);
  228. odm_write_1byte(p_dm_odm, REG_TXBF_CTRL_8192E+3, odm_read_1byte(p_dm_odm, REG_TXBF_CTRL_8192E+3) | BIT(4) | BIT(6) | BIT(7));
  229. } else
  230. odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8192E+2, sta_id | BIT(12) | BIT(14) | BIT(15));
  231. /*CSI report parameters of Beamformee*/
  232. if (bfee_idx == 0) {
  233. /*Get BIT24 & BIT25*/
  234. u8 tmp = odm_read_1byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8192E+3) & 0x3;
  235. odm_write_1byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8192E+3, tmp | 0x60);
  236. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8192E, sta_id | BIT(9));
  237. } else {
  238. /*Set BIT25*/
  239. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8192E+2, sta_id | 0xE200);
  240. }
  241. phydm_beamforming_notify(p_dm_odm);
  242. }
  243. }
  244. void
  245. hal_txbf_8192e_leave(
  246. void *p_dm_void,
  247. u8 idx
  248. )
  249. {
  250. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  251. struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
  252. hal_txbf_8192e_rf_mode(p_dm_odm, p_beam_info);
  253. /* Clear P_AID of Beamformee
  254. * Clear MAC addresss of Beamformer
  255. * Clear Associated Bfmee Sel
  256. */
  257. if (p_beam_info->beamform_cap == BEAMFORMING_CAP_NONE)
  258. odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8192E, 0xC8);
  259. if (idx == 0) {
  260. odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8192E, 0);
  261. odm_write_4byte(p_dm_odm, REG_ASSOCIATED_BFMER0_INFO_8192E, 0);
  262. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMER0_INFO_8192E+4, 0);
  263. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8192E, 0);
  264. } else {
  265. odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8192E+2, odm_read_1byte(p_dm_odm, REG_TXBF_CTRL_8192E+2) & 0xF000);
  266. odm_write_4byte(p_dm_odm, REG_ASSOCIATED_BFMER1_INFO_8192E, 0);
  267. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMER1_INFO_8192E+4, 0);
  268. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8192E+2, odm_read_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8192E+2) & 0x60);
  269. }
  270. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] idx %d\n", __func__, idx));
  271. }
  272. void
  273. hal_txbf_8192e_status(
  274. void *p_dm_void,
  275. u8 idx
  276. )
  277. {
  278. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  279. u16 beam_ctrl_val;
  280. u32 beam_ctrl_reg;
  281. struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
  282. struct _RT_BEAMFORMEE_ENTRY beamform_entry = p_beam_info->beamformee_entry[idx];
  283. if (phydm_acting_determine(p_dm_odm, phydm_acting_as_ibss))
  284. beam_ctrl_val = beamform_entry.mac_id;
  285. else
  286. beam_ctrl_val = beamform_entry.p_aid;
  287. if (idx == 0)
  288. beam_ctrl_reg = REG_TXBF_CTRL_8192E;
  289. else {
  290. beam_ctrl_reg = REG_TXBF_CTRL_8192E+2;
  291. beam_ctrl_val |= BIT(12) | BIT(14) | BIT(15);
  292. }
  293. if ((beamform_entry.beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) && (p_beam_info->apply_v_matrix == true)) {
  294. if (beamform_entry.sound_bw == CHANNEL_WIDTH_20)
  295. beam_ctrl_val |= BIT(9);
  296. else if (beamform_entry.sound_bw == CHANNEL_WIDTH_40)
  297. beam_ctrl_val |= BIT(10);
  298. } else
  299. beam_ctrl_val &= ~(BIT(9) | BIT(10) | BIT(11));
  300. odm_write_2byte(p_dm_odm, beam_ctrl_reg, beam_ctrl_val);
  301. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] idx %d beam_ctrl_reg %x beam_ctrl_val %x\n", __func__, idx, beam_ctrl_reg, beam_ctrl_val));
  302. }
  303. void
  304. hal_txbf_8192e_fw_tx_bf(
  305. void *p_dm_void,
  306. u8 idx
  307. )
  308. {
  309. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  310. struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
  311. struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = p_beam_info->beamformee_entry + idx;
  312. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));
  313. if (p_beam_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSING)
  314. hal_txbf_8192e_download_ndpa(p_dm_odm, idx);
  315. hal_txbf_8192e_fw_txbf_cmd(p_dm_odm);
  316. }
  317. #endif /* #if (RTL8192E_SUPPORT == 1)*/
  318. #endif