PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/staging/rtl8188eu/hal/odm_RTL8188E.c

https://gitlab.com/openbar/rpi-linux
C | 370 lines | 297 code | 34 blank | 39 comment | 84 complexity | 43808803222fb732d58416c138eebf49 MD5 | raw file
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12. * more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. *
  19. ******************************************************************************/
  20. #include "odm_precomp.h"
  21. #include "phy.h"
  22. static void dm_rx_hw_antena_div_init(struct odm_dm_struct *dm_odm)
  23. {
  24. struct adapter *adapter = dm_odm->Adapter;
  25. u32 value32;
  26. if (*(dm_odm->mp_mode) == 1) {
  27. dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
  28. phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
  29. phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
  30. return;
  31. }
  32. /* MAC Setting */
  33. value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
  34. phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
  35. value32|(BIT(23) | BIT(25)));
  36. /* Pin Settings */
  37. phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
  38. phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
  39. phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 1);
  40. phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
  41. /* OFDM Settings */
  42. phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
  43. 0x000000a0);
  44. /* CCK Settings */
  45. phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
  46. phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
  47. rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
  48. phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, 0xFFFF, 0x0201);
  49. }
  50. static void dm_trx_hw_antenna_div_init(struct odm_dm_struct *dm_odm)
  51. {
  52. struct adapter *adapter = dm_odm->Adapter;
  53. u32 value32;
  54. if (*(dm_odm->mp_mode) == 1) {
  55. dm_odm->AntDivType = CGCS_RX_SW_ANTDIV;
  56. phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
  57. phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
  58. BIT(5) | BIT(4) | BIT(3), 0);
  59. return;
  60. }
  61. /* MAC Setting */
  62. value32 = phy_query_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord);
  63. phy_set_bb_reg(adapter, ODM_REG_ANTSEL_PIN_11N, bMaskDWord,
  64. value32|(BIT(23) | BIT(25)));
  65. /* Pin Settings */
  66. phy_set_bb_reg(adapter, ODM_REG_PIN_CTRL_11N, BIT(9) | BIT(8), 0);
  67. phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N, BIT(10), 0);
  68. phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(22), 0);
  69. phy_set_bb_reg(adapter, ODM_REG_LNA_SWITCH_11N, BIT(31), 1);
  70. /* OFDM Settings */
  71. phy_set_bb_reg(adapter, ODM_REG_ANTDIV_PARA1_11N, bMaskDWord,
  72. 0x000000a0);
  73. /* CCK Settings */
  74. phy_set_bb_reg(adapter, ODM_REG_BB_PWR_SAV4_11N, BIT(7), 1);
  75. phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA2_11N, BIT(4), 1);
  76. /* Tx Settings */
  77. phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N, BIT(21), 0);
  78. rtl88eu_dm_update_rx_idle_ant(dm_odm, MAIN_ANT);
  79. /* antenna mapping table */
  80. if (!dm_odm->bIsMPChip) { /* testchip */
  81. phy_set_bb_reg(adapter, ODM_REG_RX_DEFUALT_A_11N,
  82. BIT(10) | BIT(9) | BIT(8), 1);
  83. phy_set_bb_reg(adapter, ODM_REG_RX_DEFUALT_A_11N,
  84. BIT(13) | BIT(12) | BIT(11), 2);
  85. } else { /* MPchip */
  86. phy_set_bb_reg(adapter, ODM_REG_ANT_MAPPING1_11N, bMaskDWord,
  87. 0x0201);
  88. }
  89. }
  90. static void dm_fast_training_init(struct odm_dm_struct *dm_odm)
  91. {
  92. struct adapter *adapter = dm_odm->Adapter;
  93. u32 value32, i;
  94. struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
  95. u32 AntCombination = 2;
  96. if (*(dm_odm->mp_mode) == 1) {
  97. return;
  98. }
  99. for (i = 0; i < 6; i++) {
  100. dm_fat_tbl->Bssid[i] = 0;
  101. dm_fat_tbl->antSumRSSI[i] = 0;
  102. dm_fat_tbl->antRSSIcnt[i] = 0;
  103. dm_fat_tbl->antAveRSSI[i] = 0;
  104. }
  105. dm_fat_tbl->TrainIdx = 0;
  106. dm_fat_tbl->FAT_State = FAT_NORMAL_STATE;
  107. /* MAC Setting */
  108. value32 = phy_query_bb_reg(adapter, 0x4c, bMaskDWord);
  109. phy_set_bb_reg(adapter, 0x4c, bMaskDWord, value32|(BIT(23) | BIT(25)));
  110. value32 = phy_query_bb_reg(adapter, 0x7B4, bMaskDWord);
  111. phy_set_bb_reg(adapter, 0x7b4, bMaskDWord, value32|(BIT(16) | BIT(17)));
  112. /* Match MAC ADDR */
  113. phy_set_bb_reg(adapter, 0x7b4, 0xFFFF, 0);
  114. phy_set_bb_reg(adapter, 0x7b0, bMaskDWord, 0);
  115. phy_set_bb_reg(adapter, 0x870, BIT(9) | BIT(8), 0);
  116. phy_set_bb_reg(adapter, 0x864, BIT(10), 0);
  117. phy_set_bb_reg(adapter, 0xb2c, BIT(22), 0);
  118. phy_set_bb_reg(adapter, 0xb2c, BIT(31), 1);
  119. phy_set_bb_reg(adapter, 0xca4, bMaskDWord, 0x000000a0);
  120. /* antenna mapping table */
  121. if (AntCombination == 2) {
  122. if (!dm_odm->bIsMPChip) { /* testchip */
  123. phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 1);
  124. phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 2);
  125. } else { /* MPchip */
  126. phy_set_bb_reg(adapter, 0x914, bMaskByte0, 1);
  127. phy_set_bb_reg(adapter, 0x914, bMaskByte1, 2);
  128. }
  129. } else if (AntCombination == 7) {
  130. if (!dm_odm->bIsMPChip) { /* testchip */
  131. phy_set_bb_reg(adapter, 0x858, BIT(10) | BIT(9) | BIT(8), 0);
  132. phy_set_bb_reg(adapter, 0x858, BIT(13) | BIT(12) | BIT(11), 1);
  133. phy_set_bb_reg(adapter, 0x878, BIT(16), 0);
  134. phy_set_bb_reg(adapter, 0x858, BIT(15) | BIT(14), 2);
  135. phy_set_bb_reg(adapter, 0x878, BIT(19) | BIT(18) | BIT(17), 3);
  136. phy_set_bb_reg(adapter, 0x878, BIT(22) | BIT(21) | BIT(20), 4);
  137. phy_set_bb_reg(adapter, 0x878, BIT(25) | BIT(24) | BIT(23), 5);
  138. phy_set_bb_reg(adapter, 0x878, BIT(28) | BIT(27) | BIT(26), 6);
  139. phy_set_bb_reg(adapter, 0x878, BIT(31) | BIT(30) | BIT(29), 7);
  140. } else { /* MPchip */
  141. phy_set_bb_reg(adapter, 0x914, bMaskByte0, 0);
  142. phy_set_bb_reg(adapter, 0x914, bMaskByte1, 1);
  143. phy_set_bb_reg(adapter, 0x914, bMaskByte2, 2);
  144. phy_set_bb_reg(adapter, 0x914, bMaskByte3, 3);
  145. phy_set_bb_reg(adapter, 0x918, bMaskByte0, 4);
  146. phy_set_bb_reg(adapter, 0x918, bMaskByte1, 5);
  147. phy_set_bb_reg(adapter, 0x918, bMaskByte2, 6);
  148. phy_set_bb_reg(adapter, 0x918, bMaskByte3, 7);
  149. }
  150. }
  151. /* Default Ant Setting when no fast training */
  152. phy_set_bb_reg(adapter, 0x80c, BIT(21), 1);
  153. phy_set_bb_reg(adapter, 0x864, BIT(5) | BIT(4) | BIT(3), 0);
  154. phy_set_bb_reg(adapter, 0x864, BIT(8) | BIT(7) | BIT(6), 1);
  155. /* Enter Traing state */
  156. phy_set_bb_reg(adapter, 0x864, BIT(2) | BIT(1) | BIT(0), (AntCombination-1));
  157. phy_set_bb_reg(adapter, 0xc50, BIT(7), 1);
  158. }
  159. void rtl88eu_dm_antenna_div_init(struct odm_dm_struct *dm_odm)
  160. {
  161. if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV)
  162. dm_rx_hw_antena_div_init(dm_odm);
  163. else if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
  164. dm_trx_hw_antenna_div_init(dm_odm);
  165. else if (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)
  166. dm_fast_training_init(dm_odm);
  167. }
  168. void rtl88eu_dm_update_rx_idle_ant(struct odm_dm_struct *dm_odm, u8 ant)
  169. {
  170. struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
  171. struct adapter *adapter = dm_odm->Adapter;
  172. u32 default_ant, optional_ant;
  173. if (dm_fat_tbl->RxIdleAnt != ant) {
  174. if (ant == MAIN_ANT) {
  175. default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
  176. MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
  177. optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
  178. AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
  179. } else {
  180. default_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
  181. AUX_ANT_CG_TRX : AUX_ANT_CGCS_RX;
  182. optional_ant = (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ?
  183. MAIN_ANT_CG_TRX : MAIN_ANT_CGCS_RX;
  184. }
  185. if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
  186. phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
  187. BIT(5) | BIT(4) | BIT(3), default_ant);
  188. phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
  189. BIT(8) | BIT(7) | BIT(6), optional_ant);
  190. phy_set_bb_reg(adapter, ODM_REG_ANTSEL_CTRL_11N,
  191. BIT(14) | BIT(13) | BIT(12), default_ant);
  192. phy_set_bb_reg(adapter, ODM_REG_RESP_TX_11N,
  193. BIT(6) | BIT(7), default_ant);
  194. } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
  195. phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
  196. BIT(5) | BIT(4) | BIT(3), default_ant);
  197. phy_set_bb_reg(adapter, ODM_REG_RX_ANT_CTRL_11N,
  198. BIT(8) | BIT(7) | BIT(6), optional_ant);
  199. }
  200. }
  201. dm_fat_tbl->RxIdleAnt = ant;
  202. }
  203. static void update_tx_ant_88eu(struct odm_dm_struct *dm_odm, u8 ant, u32 mac_id)
  204. {
  205. struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
  206. u8 target_ant;
  207. if (ant == MAIN_ANT)
  208. target_ant = MAIN_ANT_CG_TRX;
  209. else
  210. target_ant = AUX_ANT_CG_TRX;
  211. dm_fat_tbl->antsel_a[mac_id] = target_ant & BIT(0);
  212. dm_fat_tbl->antsel_b[mac_id] = (target_ant & BIT(1))>>1;
  213. dm_fat_tbl->antsel_c[mac_id] = (target_ant & BIT(2))>>2;
  214. }
  215. void rtl88eu_dm_set_tx_ant_by_tx_info(struct odm_dm_struct *dm_odm,
  216. u8 *desc, u8 mac_id)
  217. {
  218. struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
  219. if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
  220. (dm_odm->AntDivType == CG_TRX_SMART_ANTDIV)) {
  221. SET_TX_DESC_ANTSEL_A_88E(desc, dm_fat_tbl->antsel_a[mac_id]);
  222. SET_TX_DESC_ANTSEL_B_88E(desc, dm_fat_tbl->antsel_b[mac_id]);
  223. SET_TX_DESC_ANTSEL_C_88E(desc, dm_fat_tbl->antsel_c[mac_id]);
  224. }
  225. }
  226. void rtl88eu_dm_ant_sel_statistics(struct odm_dm_struct *dm_odm,
  227. u8 antsel_tr_mux, u32 mac_id, u8 rx_pwdb_all)
  228. {
  229. struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
  230. if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV) {
  231. if (antsel_tr_mux == MAIN_ANT_CG_TRX) {
  232. dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
  233. dm_fat_tbl->MainAnt_Cnt[mac_id]++;
  234. } else {
  235. dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
  236. dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
  237. }
  238. } else if (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV) {
  239. if (antsel_tr_mux == MAIN_ANT_CGCS_RX) {
  240. dm_fat_tbl->MainAnt_Sum[mac_id] += rx_pwdb_all;
  241. dm_fat_tbl->MainAnt_Cnt[mac_id]++;
  242. } else {
  243. dm_fat_tbl->AuxAnt_Sum[mac_id] += rx_pwdb_all;
  244. dm_fat_tbl->AuxAnt_Cnt[mac_id]++;
  245. }
  246. }
  247. }
  248. static void rtl88eu_dm_hw_ant_div(struct odm_dm_struct *dm_odm)
  249. {
  250. struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
  251. struct rtw_dig *dig_table = &dm_odm->DM_DigTable;
  252. struct sta_info *entry;
  253. u32 i, min_rssi = 0xFF, ant_div_max_rssi = 0, max_rssi = 0;
  254. u32 local_min_rssi, local_max_rssi;
  255. u32 main_rssi, aux_rssi;
  256. u8 RxIdleAnt = 0, target_ant = 7;
  257. for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
  258. entry = dm_odm->pODM_StaInfo[i];
  259. if (IS_STA_VALID(entry)) {
  260. /* 2 Caculate RSSI per Antenna */
  261. main_rssi = (dm_fat_tbl->MainAnt_Cnt[i] != 0) ?
  262. (dm_fat_tbl->MainAnt_Sum[i]/dm_fat_tbl->MainAnt_Cnt[i]) : 0;
  263. aux_rssi = (dm_fat_tbl->AuxAnt_Cnt[i] != 0) ?
  264. (dm_fat_tbl->AuxAnt_Sum[i]/dm_fat_tbl->AuxAnt_Cnt[i]) : 0;
  265. target_ant = (main_rssi >= aux_rssi) ? MAIN_ANT : AUX_ANT;
  266. /* 2 Select max_rssi for DIG */
  267. local_max_rssi = max(main_rssi, aux_rssi);
  268. if ((local_max_rssi > ant_div_max_rssi) &&
  269. (local_max_rssi < 40))
  270. ant_div_max_rssi = local_max_rssi;
  271. if (local_max_rssi > max_rssi)
  272. max_rssi = local_max_rssi;
  273. /* 2 Select RX Idle Antenna */
  274. if ((dm_fat_tbl->RxIdleAnt == MAIN_ANT) &&
  275. (main_rssi == 0))
  276. main_rssi = aux_rssi;
  277. else if ((dm_fat_tbl->RxIdleAnt == AUX_ANT) &&
  278. (aux_rssi == 0))
  279. aux_rssi = main_rssi;
  280. local_min_rssi = min(main_rssi, aux_rssi);
  281. if (local_min_rssi < min_rssi) {
  282. min_rssi = local_min_rssi;
  283. RxIdleAnt = target_ant;
  284. }
  285. /* 2 Select TRX Antenna */
  286. if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
  287. update_tx_ant_88eu(dm_odm, target_ant, i);
  288. }
  289. dm_fat_tbl->MainAnt_Sum[i] = 0;
  290. dm_fat_tbl->AuxAnt_Sum[i] = 0;
  291. dm_fat_tbl->MainAnt_Cnt[i] = 0;
  292. dm_fat_tbl->AuxAnt_Cnt[i] = 0;
  293. }
  294. /* 2 Set RX Idle Antenna */
  295. rtl88eu_dm_update_rx_idle_ant(dm_odm, RxIdleAnt);
  296. dig_table->AntDiv_RSSI_max = ant_div_max_rssi;
  297. dig_table->RSSI_max = max_rssi;
  298. }
  299. void rtl88eu_dm_antenna_diversity(struct odm_dm_struct *dm_odm)
  300. {
  301. struct fast_ant_train *dm_fat_tbl = &dm_odm->DM_FatTable;
  302. struct adapter *adapter = dm_odm->Adapter;
  303. if (!(dm_odm->SupportAbility & ODM_BB_ANT_DIV))
  304. return;
  305. if (!dm_odm->bLinked) {
  306. ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
  307. ("ODM_AntennaDiversity_88E(): No Link.\n"));
  308. if (dm_fat_tbl->bBecomeLinked) {
  309. ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
  310. ("Need to Turn off HW AntDiv\n"));
  311. phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 0);
  312. phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
  313. BIT(15), 0);
  314. if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
  315. phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
  316. BIT(21), 0);
  317. dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
  318. }
  319. return;
  320. } else {
  321. if (!dm_fat_tbl->bBecomeLinked) {
  322. ODM_RT_TRACE(dm_odm, ODM_COMP_ANT_DIV, ODM_DBG_LOUD,
  323. ("Need to Turn on HW AntDiv\n"));
  324. phy_set_bb_reg(adapter, ODM_REG_IGI_A_11N, BIT(7), 1);
  325. phy_set_bb_reg(adapter, ODM_REG_CCK_ANTDIV_PARA1_11N,
  326. BIT(15), 1);
  327. if (dm_odm->AntDivType == CG_TRX_HW_ANTDIV)
  328. phy_set_bb_reg(adapter, ODM_REG_TX_ANT_CTRL_11N,
  329. BIT(21), 1);
  330. dm_fat_tbl->bBecomeLinked = dm_odm->bLinked;
  331. }
  332. }
  333. if ((dm_odm->AntDivType == CG_TRX_HW_ANTDIV) ||
  334. (dm_odm->AntDivType == CGCS_RX_HW_ANTDIV))
  335. rtl88eu_dm_hw_ant_div(dm_odm);
  336. }