rf.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2009-2010 Realtek Corporation.
  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. * The full GNU General Public License is included in this distribution in the
  15. * file called LICENSE.
  16. *
  17. * Contact Information:
  18. * wlanfae <wlanfae@realtek.com>
  19. * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20. * Hsinchu 300, Taiwan.
  21. *
  22. * Larry Finger <Larry.Finger@lwfinger.net>
  23. *
  24. *****************************************************************************/
  25. #include "../wifi.h"
  26. #include "reg.h"
  27. #include "def.h"
  28. #include "phy.h"
  29. #include "rf.h"
  30. #include "dm.h"
  31. static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
  32. void rtl8821ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
  33. {
  34. struct rtl_priv *rtlpriv = rtl_priv(hw);
  35. switch (bandwidth) {
  36. case HT_CHANNEL_WIDTH_20:
  37. rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 3);
  38. rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 3);
  39. break;
  40. case HT_CHANNEL_WIDTH_20_40:
  41. rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 1);
  42. rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 1);
  43. break;
  44. case HT_CHANNEL_WIDTH_80:
  45. rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 0);
  46. rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 0);
  47. break;
  48. default:
  49. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  50. "unknown bandwidth: %#X\n", bandwidth);
  51. break;
  52. }
  53. }
  54. void rtl8821ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
  55. u8 *ppowerlevel)
  56. {
  57. struct rtl_priv *rtlpriv = rtl_priv(hw);
  58. struct rtl_phy *rtlphy = &rtlpriv->phy;
  59. struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
  60. struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
  61. u32 tx_agc[2] = {0, 0}, tmpval;
  62. bool turbo_scanoff = false;
  63. u8 idx1, idx2;
  64. u8 *ptr;
  65. u8 direction;
  66. u32 pwrtrac_value;
  67. if (rtlefuse->eeprom_regulatory != 0)
  68. turbo_scanoff = true;
  69. if (mac->act_scanning) {
  70. tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
  71. tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
  72. if (turbo_scanoff) {
  73. for (idx1 = RF90_PATH_A;
  74. idx1 <= RF90_PATH_B;
  75. idx1++) {
  76. tx_agc[idx1] = ppowerlevel[idx1] |
  77. (ppowerlevel[idx1] << 8) |
  78. (ppowerlevel[idx1] << 16) |
  79. (ppowerlevel[idx1] << 24);
  80. }
  81. }
  82. } else {
  83. for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
  84. tx_agc[idx1] = ppowerlevel[idx1] |
  85. (ppowerlevel[idx1] << 8) |
  86. (ppowerlevel[idx1] << 16) |
  87. (ppowerlevel[idx1] << 24);
  88. }
  89. if (rtlefuse->eeprom_regulatory == 0) {
  90. tmpval =
  91. (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
  92. (rtlphy->mcs_txpwrlevel_origoffset[0][7] <<
  93. 8);
  94. tx_agc[RF90_PATH_A] += tmpval;
  95. tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
  96. (rtlphy->mcs_txpwrlevel_origoffset[0][15] <<
  97. 24);
  98. tx_agc[RF90_PATH_B] += tmpval;
  99. }
  100. }
  101. for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
  102. ptr = (u8 *)(&tx_agc[idx1]);
  103. for (idx2 = 0; idx2 < 4; idx2++) {
  104. if (*ptr > RF6052_MAX_TX_PWR)
  105. *ptr = RF6052_MAX_TX_PWR;
  106. ptr++;
  107. }
  108. }
  109. rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
  110. if (direction == 1) {
  111. tx_agc[0] += pwrtrac_value;
  112. tx_agc[1] += pwrtrac_value;
  113. } else if (direction == 2) {
  114. tx_agc[0] -= pwrtrac_value;
  115. tx_agc[1] -= pwrtrac_value;
  116. }
  117. tmpval = tx_agc[RF90_PATH_A];
  118. rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, MASKDWORD, tmpval);
  119. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  120. "CCK PWR 1~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
  121. RTXAGC_A_CCK11_CCK1);
  122. tmpval = tx_agc[RF90_PATH_B];
  123. rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, MASKDWORD, tmpval);
  124. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  125. "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
  126. RTXAGC_B_CCK11_CCK1);
  127. }
  128. static void rtl8821ae_phy_get_power_base(struct ieee80211_hw *hw,
  129. u8 *ppowerlevel_ofdm,
  130. u8 *ppowerlevel_bw20,
  131. u8 *ppowerlevel_bw40, u8 channel,
  132. u32 *ofdmbase, u32 *mcsbase)
  133. {
  134. struct rtl_priv *rtlpriv = rtl_priv(hw);
  135. struct rtl_phy *rtlphy = &rtlpriv->phy;
  136. u32 powerbase0, powerbase1;
  137. u8 i, powerlevel[2];
  138. for (i = 0; i < 2; i++) {
  139. powerbase0 = ppowerlevel_ofdm[i];
  140. powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
  141. (powerbase0 << 8) | powerbase0;
  142. *(ofdmbase + i) = powerbase0;
  143. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  144. " [OFDM power base index rf(%c) = 0x%x]\n",
  145. ((i == 0) ? 'A' : 'B'), *(ofdmbase + i));
  146. }
  147. for (i = 0; i < 2; i++) {
  148. if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
  149. powerlevel[i] = ppowerlevel_bw20[i];
  150. else
  151. powerlevel[i] = ppowerlevel_bw40[i];
  152. powerbase1 = powerlevel[i];
  153. powerbase1 = (powerbase1 << 24) |
  154. (powerbase1 << 16) | (powerbase1 << 8) | powerbase1;
  155. *(mcsbase + i) = powerbase1;
  156. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  157. " [MCS power base index rf(%c) = 0x%x]\n",
  158. ((i == 0) ? 'A' : 'B'), *(mcsbase + i));
  159. }
  160. }
  161. static void get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
  162. u8 channel, u8 index,
  163. u32 *powerbase0,
  164. u32 *powerbase1,
  165. u32 *p_outwriteval)
  166. {
  167. struct rtl_priv *rtlpriv = rtl_priv(hw);
  168. struct rtl_phy *rtlphy = &rtlpriv->phy;
  169. struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
  170. u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff;
  171. u32 writeval, customer_limit, rf;
  172. for (rf = 0; rf < 2; rf++) {
  173. switch (rtlefuse->eeprom_regulatory) {
  174. case 0:
  175. chnlgroup = 0;
  176. writeval =
  177. rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index +
  178. (rf ? 8 : 0)]
  179. + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
  180. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  181. "RTK better performance, writeval(%c) = 0x%x\n",
  182. ((rf == 0) ? 'A' : 'B'), writeval);
  183. break;
  184. case 1:
  185. if (rtlphy->pwrgroup_cnt == 1) {
  186. chnlgroup = 0;
  187. } else {
  188. if (channel < 3)
  189. chnlgroup = 0;
  190. else if (channel < 6)
  191. chnlgroup = 1;
  192. else if (channel < 9)
  193. chnlgroup = 2;
  194. else if (channel < 12)
  195. chnlgroup = 3;
  196. else if (channel < 14)
  197. chnlgroup = 4;
  198. else if (channel == 14)
  199. chnlgroup = 5;
  200. }
  201. writeval =
  202. rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
  203. [index + (rf ? 8 : 0)] + ((index < 2) ?
  204. powerbase0[rf] :
  205. powerbase1[rf]);
  206. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  207. "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",
  208. ((rf == 0) ? 'A' : 'B'), writeval);
  209. break;
  210. case 2:
  211. writeval =
  212. ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
  213. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  214. "Better regulatory, writeval(%c) = 0x%x\n",
  215. ((rf == 0) ? 'A' : 'B'), writeval);
  216. break;
  217. case 3:
  218. chnlgroup = 0;
  219. if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
  220. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  221. "customer's limit, 40MHz rf(%c) = 0x%x\n",
  222. ((rf == 0) ? 'A' : 'B'),
  223. rtlefuse->pwrgroup_ht40[rf][channel -
  224. 1]);
  225. } else {
  226. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  227. "customer's limit, 20MHz rf(%c) = 0x%x\n",
  228. ((rf == 0) ? 'A' : 'B'),
  229. rtlefuse->pwrgroup_ht20[rf][channel -
  230. 1]);
  231. }
  232. if (index < 2)
  233. pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][channel-1];
  234. else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20)
  235. pwr_diff =
  236. rtlefuse->txpwr_ht20diff[rf][channel-1];
  237. if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40)
  238. customer_pwr_diff =
  239. rtlefuse->pwrgroup_ht40[rf][channel-1];
  240. else
  241. customer_pwr_diff =
  242. rtlefuse->pwrgroup_ht20[rf][channel-1];
  243. if (pwr_diff > customer_pwr_diff)
  244. pwr_diff = 0;
  245. else
  246. pwr_diff = customer_pwr_diff - pwr_diff;
  247. for (i = 0; i < 4; i++) {
  248. pwr_diff_limit[i] =
  249. (u8)((rtlphy->mcs_txpwrlevel_origoffset
  250. [chnlgroup][index + (rf ? 8 : 0)] &
  251. (0x7f << (i * 8))) >> (i * 8));
  252. if (pwr_diff_limit[i] > pwr_diff)
  253. pwr_diff_limit[i] = pwr_diff;
  254. }
  255. customer_limit = (pwr_diff_limit[3] << 24) |
  256. (pwr_diff_limit[2] << 16) |
  257. (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
  258. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  259. "Customer's limit rf(%c) = 0x%x\n",
  260. ((rf == 0) ? 'A' : 'B'), customer_limit);
  261. writeval = customer_limit +
  262. ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
  263. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  264. "Customer, writeval rf(%c)= 0x%x\n",
  265. ((rf == 0) ? 'A' : 'B'), writeval);
  266. break;
  267. default:
  268. chnlgroup = 0;
  269. writeval =
  270. rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
  271. [index + (rf ? 8 : 0)]
  272. + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
  273. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  274. "RTK better performance, writeval rf(%c) = 0x%x\n",
  275. ((rf == 0) ? 'A' : 'B'), writeval);
  276. break;
  277. }
  278. if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
  279. writeval = writeval - 0x06060606;
  280. else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
  281. TXHIGHPWRLEVEL_BT2)
  282. writeval = writeval - 0x0c0c0c0c;
  283. *(p_outwriteval + rf) = writeval;
  284. }
  285. }
  286. static void _rtl8821ae_write_ofdm_power_reg(struct ieee80211_hw *hw,
  287. u8 index, u32 *pvalue)
  288. {
  289. struct rtl_priv *rtlpriv = rtl_priv(hw);
  290. u16 regoffset_a[6] = {
  291. RTXAGC_A_OFDM18_OFDM6, RTXAGC_A_OFDM54_OFDM24,
  292. RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
  293. RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
  294. };
  295. u16 regoffset_b[6] = {
  296. RTXAGC_B_OFDM18_OFDM6, RTXAGC_B_OFDM54_OFDM24,
  297. RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
  298. RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
  299. };
  300. u8 i, rf, pwr_val[4];
  301. u32 writeval;
  302. u16 regoffset;
  303. for (rf = 0; rf < 2; rf++) {
  304. writeval = pvalue[rf];
  305. for (i = 0; i < 4; i++) {
  306. pwr_val[i] = (u8)((writeval & (0x7f <<
  307. (i * 8))) >> (i * 8));
  308. if (pwr_val[i] > RF6052_MAX_TX_PWR)
  309. pwr_val[i] = RF6052_MAX_TX_PWR;
  310. }
  311. writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
  312. (pwr_val[1] << 8) | pwr_val[0];
  313. if (rf == 0)
  314. regoffset = regoffset_a[index];
  315. else
  316. regoffset = regoffset_b[index];
  317. rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);
  318. RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
  319. "Set 0x%x = %08x\n", regoffset, writeval);
  320. }
  321. }
  322. void rtl8821ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
  323. u8 *ppowerlevel_ofdm,
  324. u8 *ppowerlevel_bw20,
  325. u8 *ppowerlevel_bw40,
  326. u8 channel)
  327. {
  328. u32 writeval[2], powerbase0[2], powerbase1[2];
  329. u8 index;
  330. u8 direction;
  331. u32 pwrtrac_value;
  332. rtl8821ae_phy_get_power_base(hw, ppowerlevel_ofdm,
  333. ppowerlevel_bw20,
  334. ppowerlevel_bw40,
  335. channel,
  336. &powerbase0[0],
  337. &powerbase1[0]);
  338. rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value);
  339. for (index = 0; index < 6; index++) {
  340. get_txpower_writeval_by_regulatory(hw, channel, index,
  341. &powerbase0[0],
  342. &powerbase1[0],
  343. &writeval[0]);
  344. if (direction == 1) {
  345. writeval[0] += pwrtrac_value;
  346. writeval[1] += pwrtrac_value;
  347. } else if (direction == 2) {
  348. writeval[0] -= pwrtrac_value;
  349. writeval[1] -= pwrtrac_value;
  350. }
  351. _rtl8821ae_write_ofdm_power_reg(hw, index, &writeval[0]);
  352. }
  353. }
  354. bool rtl8821ae_phy_rf6052_config(struct ieee80211_hw *hw)
  355. {
  356. struct rtl_priv *rtlpriv = rtl_priv(hw);
  357. struct rtl_phy *rtlphy = &rtlpriv->phy;
  358. if (rtlphy->rf_type == RF_1T1R)
  359. rtlphy->num_total_rfpath = 1;
  360. else
  361. rtlphy->num_total_rfpath = 2;
  362. return _rtl8821ae_phy_rf6052_config_parafile(hw);
  363. }
  364. static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
  365. {
  366. struct rtl_priv *rtlpriv = rtl_priv(hw);
  367. struct rtl_phy *rtlphy = &rtlpriv->phy;
  368. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  369. u8 rfpath;
  370. bool rtstatus = true;
  371. for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
  372. switch (rfpath) {
  373. case RF90_PATH_A: {
  374. if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
  375. rtstatus =
  376. rtl8812ae_phy_config_rf_with_headerfile(hw,
  377. (enum radio_path)rfpath);
  378. else
  379. rtstatus =
  380. rtl8821ae_phy_config_rf_with_headerfile(hw,
  381. (enum radio_path)rfpath);
  382. break;
  383. }
  384. case RF90_PATH_B:
  385. if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
  386. rtstatus =
  387. rtl8812ae_phy_config_rf_with_headerfile(hw,
  388. (enum radio_path)rfpath);
  389. else
  390. rtstatus =
  391. rtl8821ae_phy_config_rf_with_headerfile(hw,
  392. (enum radio_path)rfpath);
  393. break;
  394. case RF90_PATH_C:
  395. break;
  396. case RF90_PATH_D:
  397. break;
  398. }
  399. if (!rtstatus) {
  400. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  401. "Radio[%d] Fail!!", rfpath);
  402. return false;
  403. }
  404. }
  405. /*put arrays in dm.c*/
  406. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n");
  407. return rtstatus;
  408. }