rf.c 12 KB

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