haltxbf8814a.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /* ************************************************************
  2. * Description:
  3. *
  4. * This file is for 8814A TXBF mechanism
  5. *
  6. * ************************************************************ */
  7. #include "mp_precomp.h"
  8. #include "../phydm_precomp.h"
  9. #if (BEAMFORMING_SUPPORT == 1)
  10. #if (RTL8814A_SUPPORT == 1)
  11. boolean
  12. phydm_beamforming_set_iqgen_8814A(
  13. void *p_dm_void
  14. )
  15. {
  16. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  17. u8 i = 0;
  18. u16 counter = 0;
  19. u32 rf_mode[4];
  20. for (i = ODM_RF_PATH_A ; i < MAX_RF_PATH ; i++)
  21. odm_set_rf_reg(p_dm_odm, i, RF_WE_LUT, 0x80000, 0x1); /*RF mode table write enable*/
  22. while (1) {
  23. counter++;
  24. for (i = ODM_RF_PATH_A; i < MAX_RF_PATH; i++)
  25. odm_set_rf_reg(p_dm_odm, i, RF_RCK_OS, 0xfffff, 0x18000); /*Select Rx mode*/
  26. ODM_delay_us(2);
  27. for (i = ODM_RF_PATH_A; i < MAX_RF_PATH; i++)
  28. rf_mode[i] = odm_get_rf_reg(p_dm_odm, i, RF_RCK_OS, 0xfffff);
  29. if ((rf_mode[0] == 0x18000) && (rf_mode[1] == 0x18000) && (rf_mode[2] == 0x18000) && (rf_mode[3] == 0x18000))
  30. break;
  31. else if (counter == 100) {
  32. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_TRACE, ("iqgen setting fail:8814A\n"));
  33. return false;
  34. }
  35. }
  36. for (i = ODM_RF_PATH_A ; i < MAX_RF_PATH ; i++) {
  37. odm_set_rf_reg(p_dm_odm, i, RF_TXPA_G1, 0xfffff, 0xBE77F); /*Set Table data*/
  38. odm_set_rf_reg(p_dm_odm, i, RF_TXPA_G2, 0xfffff, 0x226BF); /*Enable TXIQGEN in Rx mode*/
  39. }
  40. odm_set_rf_reg(p_dm_odm, ODM_RF_PATH_A, RF_TXPA_G2, 0xfffff, 0xE26BF); /*Enable TXIQGEN in Rx mode*/
  41. for (i = ODM_RF_PATH_A; i < MAX_RF_PATH; i++)
  42. odm_set_rf_reg(p_dm_odm, i, RF_WE_LUT, 0x80000, 0x0); /*RF mode table write disable*/
  43. return true;
  44. }
  45. void
  46. hal_txbf_8814a_set_ndpa_rate(
  47. void *p_dm_void,
  48. u8 BW,
  49. u8 rate
  50. )
  51. {
  52. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  53. odm_write_1byte(p_dm_odm, REG_NDPA_OPT_CTRL_8814A, BW);
  54. odm_write_1byte(p_dm_odm, REG_NDPA_RATE_8814A, (u8) rate);
  55. }
  56. #define PHYDM_MEMORY_MAP_BUF_READ 0x8000
  57. #define PHYDM_CTRL_INFO_PAGE 0x660
  58. void
  59. phydm_data_rate_8814a(
  60. struct PHY_DM_STRUCT *p_dm_odm,
  61. u8 mac_id,
  62. u32 *data,
  63. u8 data_len
  64. )
  65. {
  66. u8 i = 0;
  67. u16 x_read_data_addr = 0;
  68. odm_write_2byte(p_dm_odm, REG_PKTBUF_DBG_CTRL_8814A, PHYDM_CTRL_INFO_PAGE);
  69. x_read_data_addr = PHYDM_MEMORY_MAP_BUF_READ + mac_id * 32; /*Ctrl Info: 32Bytes for each macid(n)*/
  70. if ((x_read_data_addr < PHYDM_MEMORY_MAP_BUF_READ) || (x_read_data_addr > 0x8FFF)) {
  71. 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));
  72. return;
  73. }
  74. /* Read data */
  75. for (i = 0; i < data_len; i++)
  76. *(data + i) = odm_read_2byte(p_dm_odm, x_read_data_addr + i);
  77. }
  78. void
  79. hal_txbf_8814a_get_tx_rate(
  80. void *p_dm_void
  81. )
  82. {
  83. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  84. struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
  85. struct _RT_BEAMFORMEE_ENTRY *p_entry;
  86. u32 tx_rpt_data = 0;
  87. u8 data_rate = 0xFF;
  88. p_entry = &(p_beam_info->beamformee_entry[p_beam_info->beamformee_cur_idx]);
  89. phydm_data_rate_8814a(p_dm_odm, (u8)p_entry->mac_id, &tx_rpt_data, 1);
  90. data_rate = (u8)tx_rpt_data;
  91. data_rate &= 0x7f; /*Bit7 indicates SGI*/
  92. p_dm_odm->tx_bf_data_rate = data_rate;
  93. 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));
  94. }
  95. void
  96. hal_txbf_8814a_reset_tx_path(
  97. void *p_dm_void,
  98. u8 idx
  99. )
  100. {
  101. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  102. #if DEV_BUS_TYPE == RT_USB_INTERFACE
  103. struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info;
  104. struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
  105. u8 nr_index = 0, tx_ss = 0;
  106. if (idx < BEAMFORMEE_ENTRY_NUM)
  107. beamformee_entry = p_beamforming_info->beamformee_entry[idx];
  108. else
  109. return;
  110. if ((p_dm_odm->last_usb_hub) != (*p_dm_odm->hub_usb_mode)) {
  111. nr_index = tx_bf_nr(hal_txbf_8814a_get_ntx(p_dm_odm), beamformee_entry.comp_steering_num_of_bfer);
  112. if (*p_dm_odm->hub_usb_mode == 2) {
  113. if (p_dm_odm->rf_type == ODM_4T4R)
  114. tx_ss = 0xf;
  115. else if (p_dm_odm->rf_type == ODM_3T3R)
  116. tx_ss = 0xe;
  117. else
  118. tx_ss = 0x6;
  119. } else if (*p_dm_odm->hub_usb_mode == 1) /*USB 2.0 always 2Tx*/
  120. tx_ss = 0x6;
  121. else
  122. tx_ss = 0x6;
  123. if (tx_ss == 0xf) {
  124. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x93f);
  125. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKDWORD, 0x93f93f0);
  126. } else if (tx_ss == 0xe) {
  127. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x93e);
  128. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKDWORD, 0x93e93e0);
  129. } else if (tx_ss == 0x6) {
  130. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x936);
  131. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKLWORD, 0x9360);
  132. }
  133. if (idx == 0) {
  134. switch (nr_index) {
  135. case 0:
  136. break;
  137. case 1: /*Nsts = 2 BC*/
  138. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x9366); /*tx2path, BC*/
  139. break;
  140. case 2: /*Nsts = 3 BCD*/
  141. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93e93ee); /*tx3path, BCD*/
  142. break;
  143. default: /*nr>3, same as Case 3*/
  144. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93f93ff); /*tx4path, ABCD*/
  145. break;
  146. }
  147. } else {
  148. switch (nr_index) {
  149. case 0:
  150. break;
  151. case 1: /*Nsts = 2 BC*/
  152. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x9366); /*tx2path, BC*/
  153. break;
  154. case 2: /*Nsts = 3 BCD*/
  155. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93e93ee); /*tx3path, BCD*/
  156. break;
  157. default: /*nr>3, same as Case 3*/
  158. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93f93ff); /*tx4path, ABCD*/
  159. break;
  160. }
  161. }
  162. p_dm_odm->last_usb_hub = *p_dm_odm->hub_usb_mode;
  163. } else
  164. return;
  165. #endif
  166. }
  167. u8
  168. hal_txbf_8814a_get_ntx(
  169. void *p_dm_void
  170. )
  171. {
  172. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  173. u8 ntx = 0, tx_ss = 3;
  174. #if DEV_BUS_TYPE == RT_USB_INTERFACE
  175. tx_ss = *p_dm_odm->hub_usb_mode;
  176. #endif
  177. if (tx_ss == 3 || tx_ss == 2) {
  178. if (p_dm_odm->rf_type == ODM_4T4R)
  179. ntx = 3;
  180. else if (p_dm_odm->rf_type == ODM_3T3R)
  181. ntx = 2;
  182. else
  183. ntx = 1;
  184. } else if (tx_ss == 1) /*USB 2.0 always 2Tx*/
  185. ntx = 1;
  186. else
  187. ntx = 1;
  188. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] ntx = %d\n", __func__, ntx));
  189. return ntx;
  190. }
  191. u8
  192. hal_txbf_8814a_get_nrx(
  193. void *p_dm_void
  194. )
  195. {
  196. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  197. u8 nrx = 0;
  198. if (p_dm_odm->rf_type == ODM_4T4R)
  199. nrx = 3;
  200. else if (p_dm_odm->rf_type == ODM_3T3R)
  201. nrx = 2;
  202. else if (p_dm_odm->rf_type == ODM_2T2R)
  203. nrx = 1;
  204. else if (p_dm_odm->rf_type == ODM_2T3R)
  205. nrx = 2;
  206. else if (p_dm_odm->rf_type == ODM_2T4R)
  207. nrx = 3;
  208. else if (p_dm_odm->rf_type == ODM_1T1R)
  209. nrx = 0;
  210. else if (p_dm_odm->rf_type == ODM_1T2R)
  211. nrx = 1;
  212. else
  213. nrx = 0;
  214. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] nrx = %d\n", __func__, nrx));
  215. return nrx;
  216. }
  217. void
  218. hal_txbf_8814a_rf_mode(
  219. void *p_dm_void,
  220. struct _RT_BEAMFORMING_INFO *p_beamforming_info,
  221. u8 idx
  222. )
  223. {
  224. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  225. u8 i, nr_index = 0;
  226. u8 tx_ss = 3; /*default use 3 Tx*/
  227. struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
  228. if (idx < BEAMFORMEE_ENTRY_NUM)
  229. beamformee_entry = p_beamforming_info->beamformee_entry[idx];
  230. else
  231. return;
  232. nr_index = tx_bf_nr(hal_txbf_8814a_get_ntx(p_dm_odm), beamformee_entry.comp_steering_num_of_bfer);
  233. if (p_dm_odm->rf_type == ODM_1T1R)
  234. return;
  235. if (p_beamforming_info->beamformee_su_cnt > 0) {
  236. #if DEV_BUS_TYPE == RT_USB_INTERFACE
  237. p_dm_odm->last_usb_hub = *p_dm_odm->hub_usb_mode;
  238. tx_ss = *p_dm_odm->hub_usb_mode;
  239. #endif
  240. if (tx_ss == 3 || tx_ss == 2) {
  241. if (p_dm_odm->rf_type == ODM_4T4R)
  242. tx_ss = 0xf;
  243. else if (p_dm_odm->rf_type == ODM_3T3R)
  244. tx_ss = 0xe;
  245. else
  246. tx_ss = 0x6;
  247. } else if (tx_ss == 1) /*USB 2.0 always 2Tx*/
  248. tx_ss = 0x6;
  249. else
  250. tx_ss = 0x6;
  251. if (tx_ss == 0xf) {
  252. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x93f);
  253. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKDWORD, 0x93f93f0);
  254. } else if (tx_ss == 0xe) {
  255. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x93e);
  256. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKDWORD, 0x93e93e0);
  257. } else if (tx_ss == 0x6) {
  258. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_1_8814A, MASKBYTE3 | MASKBYTE2HIGHNIBBLE, 0x936);
  259. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKLWORD, 0x9360);
  260. }
  261. /*for 8814 19ac(idx 1), 19b4(idx 0), different Tx ant setting*/
  262. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, BIT(28) | BIT29, 0x2); /*enable BB TxBF ant mapping register*/
  263. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, BIT30, 0x1); /*if Nsts > Nc don't apply V matrix*/
  264. if (idx == 0) {
  265. switch (nr_index) {
  266. case 0:
  267. break;
  268. case 1: /*Nsts = 2 BC*/
  269. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x9366); /*tx2path, BC*/
  270. break;
  271. case 2: /*Nsts = 3 BCD*/
  272. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93e93ee); /*tx3path, BCD*/
  273. break;
  274. default: /*nr>3, same as Case 3*/
  275. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF0_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93f93ff); /*tx4path, ABCD*/
  276. break;
  277. }
  278. } else {
  279. switch (nr_index) {
  280. case 0:
  281. break;
  282. case 1: /*Nsts = 2 BC*/
  283. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x9366); /*tx2path, BC*/
  284. break;
  285. case 2: /*Nsts = 3 BCD*/
  286. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93e93ee); /*tx3path, BCD*/
  287. break;
  288. default: /*nr>3, same as Case 3*/
  289. odm_set_bb_reg(p_dm_odm, REG_BB_TXBF_ANT_SET_BF1_8814A, MASKBYTE3LOWNIBBLE | MASKL3BYTES, 0x93f93ff); /*tx4path, ABCD*/
  290. break;
  291. }
  292. }
  293. }
  294. if ((p_beamforming_info->beamformee_su_cnt == 0) && (p_beamforming_info->beamformer_su_cnt == 0)) {
  295. 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*/
  296. odm_set_bb_reg(p_dm_odm, REG_BB_TX_PATH_SEL_2_8814A, MASKDWORD, 0x93e9360);
  297. }
  298. }
  299. #if 0
  300. void
  301. hal_txbf_8814a_download_ndpa(
  302. void *p_dm_void,
  303. u8 idx
  304. )
  305. {
  306. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  307. u8 u1b_tmp = 0, tmp_reg422 = 0;
  308. u8 bcn_valid_reg = 0, count = 0, dl_bcn_count = 0;
  309. u16 head_page = 0x7FE;
  310. boolean is_send_beacon = false;
  311. u16 tx_page_bndy = LAST_ENTRY_OF_TX_PKT_BUFFER_8814A; /*default reseved 1 page for the IC type which is undefined.*/
  312. struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
  313. struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = p_beam_info->beamformee_entry + idx;
  314. struct _ADAPTER *adapter = p_dm_odm->adapter;
  315. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  316. *p_dm_odm->p_is_fw_dw_rsvd_page_in_progress = true;
  317. #endif
  318. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));
  319. phydm_get_hal_def_var_handler_interface(p_dm_odm, HAL_DEF_TX_PAGE_BOUNDARY, (u16 *)&tx_page_bndy);
  320. /*Set REG_CR bit 8. DMA beacon by SW.*/
  321. u1b_tmp = odm_read_1byte(p_dm_odm, REG_CR_8814A + 1);
  322. odm_write_1byte(p_dm_odm, REG_CR_8814A + 1, (u1b_tmp | BIT(0)));
  323. /*Set FWHW_TXQ_CTRL 0x422[6]=0 to tell Hw the packet is not a real beacon frame.*/
  324. tmp_reg422 = odm_read_1byte(p_dm_odm, REG_FWHW_TXQ_CTRL_8814A + 2);
  325. odm_write_1byte(p_dm_odm, REG_FWHW_TXQ_CTRL_8814A + 2, tmp_reg422 & (~BIT(6)));
  326. if (tmp_reg422 & BIT(6)) {
  327. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s: There is an adapter is sending beacon.\n", __func__));
  328. is_send_beacon = true;
  329. }
  330. /*0x204[11:0] Beacon Head for TXDMA*/
  331. odm_write_2byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A, head_page);
  332. do {
  333. /*Clear beacon valid check bit.*/
  334. bcn_valid_reg = odm_read_1byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A + 1);
  335. odm_write_1byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A + 1, (bcn_valid_reg | BIT(7)));
  336. /*download NDPA rsvd page.*/
  337. if (p_beam_entry->beamform_entry_cap & BEAMFORMER_CAP_VHT_SU)
  338. beamforming_send_vht_ndpa_packet(p_dm_odm, p_beam_entry->mac_addr, p_beam_entry->AID, p_beam_entry->sound_bw, BEACON_QUEUE);
  339. else
  340. beamforming_send_ht_ndpa_packet(p_dm_odm, p_beam_entry->mac_addr, p_beam_entry->sound_bw, BEACON_QUEUE);
  341. /*check rsvd page download OK.*/
  342. bcn_valid_reg = odm_read_1byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A + 1);
  343. count = 0;
  344. while (!(bcn_valid_reg & BIT(7)) && count < 20) {
  345. count++;
  346. ODM_delay_ms(10);
  347. bcn_valid_reg = odm_read_1byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A + 2);
  348. }
  349. dl_bcn_count++;
  350. } while (!(bcn_valid_reg & BIT(7)) && dl_bcn_count < 5);
  351. if (!(bcn_valid_reg & BIT(7)))
  352. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("%s Download RSVD page failed!\n", __func__));
  353. /*0x204[11:0] Beacon Head for TXDMA*/
  354. odm_write_2byte(p_dm_odm, REG_FIFOPAGE_CTRL_2_8814A, tx_page_bndy);
  355. /*To make sure that if there exists an adapter which would like to send beacon.*/
  356. /*If exists, the origianl value of 0x422[6] will be 1, we should check this to*/
  357. /*prevent from setting 0x422[6] to 0 after download reserved page, or it will cause */
  358. /*the beacon cannot be sent by HW.*/
  359. /*2010.06.23. Added by tynli.*/
  360. if (is_send_beacon)
  361. odm_write_1byte(p_dm_odm, REG_FWHW_TXQ_CTRL_8814A + 2, tmp_reg422);
  362. /*Do not enable HW DMA BCN or it will cause Pcie interface hang by timing issue. 2011.11.24. by tynli.*/
  363. /*Clear CR[8] or beacon packet will not be send to TxBuf anymore.*/
  364. u1b_tmp = odm_read_1byte(p_dm_odm, REG_CR_8814A + 1);
  365. odm_write_1byte(p_dm_odm, REG_CR_8814A + 1, (u1b_tmp & (~BIT(0))));
  366. p_beam_entry->beamform_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSED;
  367. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  368. *p_dm_odm->p_is_fw_dw_rsvd_page_in_progress = false;
  369. #endif
  370. }
  371. void
  372. hal_txbf_8814a_fw_txbf_cmd(
  373. void *p_dm_void
  374. )
  375. {
  376. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  377. u8 idx, period = 0;
  378. u8 PageNum0 = 0xFF, PageNum1 = 0xFF;
  379. u8 u1_tx_bf_parm[3] = {0};
  380. struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
  381. for (idx = 0; idx < BEAMFORMEE_ENTRY_NUM; idx++) {
  382. if (p_beam_info->beamformee_entry[idx].is_used && p_beam_info->beamformee_entry[idx].beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) {
  383. if (p_beam_info->beamformee_entry[idx].is_sound) {
  384. PageNum0 = 0xFE;
  385. PageNum1 = 0x07;
  386. period = (u8)(p_beam_info->beamformee_entry[idx].sound_period);
  387. } else if (PageNum0 == 0xFF) {
  388. PageNum0 = 0xFF; /*stop sounding*/
  389. PageNum1 = 0x0F;
  390. }
  391. }
  392. }
  393. u1_tx_bf_parm[0] = PageNum0;
  394. u1_tx_bf_parm[1] = PageNum1;
  395. u1_tx_bf_parm[2] = period;
  396. odm_fill_h2c_cmd(p_dm_odm, PHYDM_H2C_TXBF, 3, u1_tx_bf_parm);
  397. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD,
  398. ("[%s] PageNum0 = %d, PageNum1 = %d period = %d\n", __func__, PageNum0, PageNum1, period));
  399. }
  400. #endif
  401. void
  402. hal_txbf_8814a_enter(
  403. void *p_dm_void,
  404. u8 bfer_bfee_idx
  405. )
  406. {
  407. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  408. u8 i = 0;
  409. u8 bfer_idx = (bfer_bfee_idx & 0xF0) >> 4;
  410. u8 bfee_idx = (bfer_bfee_idx & 0xF);
  411. struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info;
  412. struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
  413. struct _RT_BEAMFORMER_ENTRY beamformer_entry;
  414. u16 sta_id = 0, csi_param = 0;
  415. u8 nc_index = 0, nr_index = 0, grouping = 0, codebookinfo = 0, coefficientsize = 0;
  416. 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));
  417. odm_set_mac_reg(p_dm_odm, REG_SND_PTCL_CTRL_8814A, MASKBYTE1 | MASKBYTE2, 0x0202);
  418. if ((p_beamforming_info->beamformer_su_cnt > 0) && (bfer_idx < BEAMFORMER_ENTRY_NUM)) {
  419. beamformer_entry = p_beamforming_info->beamformer_entry[bfer_idx];
  420. /*Sounding protocol control*/
  421. odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8814A, 0xDB);
  422. /*MAC address/Partial AID of Beamformer*/
  423. if (bfer_idx == 0) {
  424. for (i = 0; i < 6 ; i++)
  425. odm_write_1byte(p_dm_odm, (REG_ASSOCIATED_BFMER0_INFO_8814A + i), beamformer_entry.mac_addr[i]);
  426. } else {
  427. for (i = 0; i < 6 ; i++)
  428. odm_write_1byte(p_dm_odm, (REG_ASSOCIATED_BFMER1_INFO_8814A + i), beamformer_entry.mac_addr[i]);
  429. }
  430. /*CSI report parameters of Beamformer*/
  431. nc_index = hal_txbf_8814a_get_nrx(p_dm_odm); /*for 8814A nrx = 3(4 ant), min=0(1 ant)*/
  432. 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*/
  433. grouping = 0;
  434. /*for ac = 1, for n = 3*/
  435. if (beamformer_entry.beamform_entry_cap & BEAMFORMEE_CAP_VHT_SU)
  436. codebookinfo = 1;
  437. else if (beamformer_entry.beamform_entry_cap & BEAMFORMEE_CAP_HT_EXPLICIT)
  438. codebookinfo = 3;
  439. coefficientsize = 3;
  440. csi_param = (u16)((coefficientsize << 10) | (codebookinfo << 8) | (grouping << 6) | (nr_index << 3) | (nc_index));
  441. if (bfer_idx == 0)
  442. odm_write_2byte(p_dm_odm, REG_CSI_RPT_PARAM_BW20_8814A, csi_param);
  443. else
  444. odm_write_2byte(p_dm_odm, REG_CSI_RPT_PARAM_BW20_8814A + 2, csi_param);
  445. /*ndp_rx_standby_timer, 8814 need > 0x56, suggest from Dvaid*/
  446. odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8814A + 3, 0x40);
  447. }
  448. if ((p_beamforming_info->beamformee_su_cnt > 0) && (bfee_idx < BEAMFORMEE_ENTRY_NUM)) {
  449. beamformee_entry = p_beamforming_info->beamformee_entry[bfee_idx];
  450. hal_txbf_8814a_rf_mode(p_dm_odm, p_beamforming_info, bfee_idx);
  451. if (phydm_acting_determine(p_dm_odm, phydm_acting_as_ibss))
  452. sta_id = beamformee_entry.mac_id;
  453. else
  454. sta_id = beamformee_entry.p_aid;
  455. /*P_AID of Beamformee & enable NDPA transmission & enable NDPA interrupt*/
  456. if (bfee_idx == 0) {
  457. odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A, sta_id);
  458. 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));
  459. } else
  460. odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A + 2, sta_id | BIT(14) | BIT(15) | BIT(12));
  461. /*CSI report parameters of Beamformee*/
  462. if (bfee_idx == 0) {
  463. /*Get BIT24 & BIT25*/
  464. u8 tmp = odm_read_1byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A + 3) & 0x3;
  465. odm_write_1byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A + 3, tmp | 0x60);
  466. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A, sta_id | BIT(9));
  467. } else
  468. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A + 2, sta_id | 0xE200); /*Set BIT25*/
  469. phydm_beamforming_notify(p_dm_odm);
  470. }
  471. }
  472. void
  473. hal_txbf_8814a_leave(
  474. void *p_dm_void,
  475. u8 idx
  476. )
  477. {
  478. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  479. struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info;
  480. struct _RT_BEAMFORMER_ENTRY beamformer_entry;
  481. struct _RT_BEAMFORMEE_ENTRY beamformee_entry;
  482. if (idx < BEAMFORMER_ENTRY_NUM) {
  483. beamformer_entry = p_beamforming_info->beamformer_entry[idx];
  484. beamformee_entry = p_beamforming_info->beamformee_entry[idx];
  485. } else
  486. return;
  487. /*Clear P_AID of Beamformee*/
  488. /*Clear MAC address of Beamformer*/
  489. /*Clear Associated Bfmee Sel*/
  490. if (beamformer_entry.beamform_entry_cap == BEAMFORMING_CAP_NONE) {
  491. odm_write_1byte(p_dm_odm, REG_SND_PTCL_CTRL_8814A, 0xD8);
  492. if (idx == 0) {
  493. odm_write_4byte(p_dm_odm, REG_ASSOCIATED_BFMER0_INFO_8814A, 0);
  494. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMER0_INFO_8814A + 4, 0);
  495. odm_write_2byte(p_dm_odm, REG_CSI_RPT_PARAM_BW20_8814A, 0);
  496. } else {
  497. odm_write_4byte(p_dm_odm, REG_ASSOCIATED_BFMER1_INFO_8814A, 0);
  498. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMER1_INFO_8814A + 4, 0);
  499. odm_write_2byte(p_dm_odm, REG_CSI_RPT_PARAM_BW20_8814A + 2, 0);
  500. }
  501. }
  502. if (beamformee_entry.beamform_entry_cap == BEAMFORMING_CAP_NONE) {
  503. hal_txbf_8814a_rf_mode(p_dm_odm, p_beamforming_info, idx);
  504. if (idx == 0) {
  505. odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A, 0x0);
  506. 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));
  507. odm_write_2byte(p_dm_odm, REG_ASSOCIATED_BFMEE_SEL_8814A, 0);
  508. } else {
  509. odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A + 2, 0x0 | BIT(14) | BIT(15) | BIT(12));
  510. 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);
  511. }
  512. }
  513. }
  514. void
  515. hal_txbf_8814a_status(
  516. void *p_dm_void,
  517. u8 idx
  518. )
  519. {
  520. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  521. u16 beam_ctrl_val, tmp_val;
  522. u32 beam_ctrl_reg;
  523. struct _RT_BEAMFORMING_INFO *p_beamforming_info = &p_dm_odm->beamforming_info;
  524. struct _RT_BEAMFORMEE_ENTRY beamform_entry;
  525. if (idx < BEAMFORMEE_ENTRY_NUM)
  526. beamform_entry = p_beamforming_info->beamformee_entry[idx];
  527. else
  528. return;
  529. if (phydm_acting_determine(p_dm_odm, phydm_acting_as_ibss))
  530. beam_ctrl_val = beamform_entry.mac_id;
  531. else
  532. beam_ctrl_val = beamform_entry.p_aid;
  533. 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));
  534. if (idx == 0)
  535. beam_ctrl_reg = REG_TXBF_CTRL_8814A;
  536. else {
  537. beam_ctrl_reg = REG_TXBF_CTRL_8814A + 2;
  538. beam_ctrl_val |= BIT(12) | BIT(14) | BIT(15);
  539. }
  540. if ((beamform_entry.beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSED) && (p_beamforming_info->apply_v_matrix == true)) {
  541. if (beamform_entry.sound_bw == CHANNEL_WIDTH_20)
  542. beam_ctrl_val |= BIT(9);
  543. else if (beamform_entry.sound_bw == CHANNEL_WIDTH_40)
  544. beam_ctrl_val |= (BIT(9) | BIT(10));
  545. else if (beamform_entry.sound_bw == CHANNEL_WIDTH_80)
  546. beam_ctrl_val |= (BIT(9) | BIT(10) | BIT(11));
  547. } else {
  548. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("@%s, Don't apply Vmatrix", __func__));
  549. beam_ctrl_val &= ~(BIT(9) | BIT(10) | BIT(11));
  550. }
  551. odm_write_2byte(p_dm_odm, beam_ctrl_reg, beam_ctrl_val);
  552. /*disable NDP packet use beamforming */
  553. tmp_val = odm_read_2byte(p_dm_odm, REG_TXBF_CTRL_8814A);
  554. odm_write_2byte(p_dm_odm, REG_TXBF_CTRL_8814A, tmp_val | BIT(15));
  555. }
  556. void
  557. hal_txbf_8814a_fw_txbf(
  558. void *p_dm_void,
  559. u8 idx
  560. )
  561. {
  562. #if 0
  563. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  564. struct _RT_BEAMFORMING_INFO *p_beam_info = &p_dm_odm->beamforming_info;
  565. struct _RT_BEAMFORMEE_ENTRY *p_beam_entry = p_beam_info->beamformee_entry + idx;
  566. ODM_RT_TRACE(p_dm_odm, PHYDM_COMP_TXBF, ODM_DBG_LOUD, ("[%s] Start!\n", __func__));
  567. if (p_beam_entry->beamform_entry_state == BEAMFORMING_ENTRY_STATE_PROGRESSING)
  568. hal_txbf_8814a_download_ndpa(p_dm_odm, idx);
  569. hal_txbf_8814a_fw_txbf_cmd(p_dm_odm);
  570. #endif
  571. }
  572. #endif /* (RTL8814A_SUPPORT == 1)*/
  573. #endif