phy.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2009-2012 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 "../pci.h"
  27. #include "../ps.h"
  28. #include "../core.h"
  29. #include "reg.h"
  30. #include "def.h"
  31. #include "phy.h"
  32. #include "../rtl8192c/phy_common.h"
  33. #include "rf.h"
  34. #include "dm.h"
  35. #include "../rtl8192c/dm_common.h"
  36. #include "../rtl8192c/fw_common.h"
  37. #include "table.h"
  38. u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
  39. enum radio_path rfpath, u32 regaddr, u32 bitmask)
  40. {
  41. struct rtl_priv *rtlpriv = rtl_priv(hw);
  42. u32 original_value, readback_value, bitshift;
  43. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  44. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  45. "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
  46. regaddr, rfpath, bitmask);
  47. if (rtlphy->rf_mode != RF_OP_BY_FW) {
  48. original_value = _rtl92c_phy_rf_serial_read(hw,
  49. rfpath, regaddr);
  50. } else {
  51. original_value = _rtl92c_phy_fw_rf_serial_read(hw,
  52. rfpath, regaddr);
  53. }
  54. bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  55. readback_value = (original_value & bitmask) >> bitshift;
  56. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  57. "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
  58. regaddr, rfpath, bitmask, original_value);
  59. return readback_value;
  60. }
  61. void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
  62. enum radio_path rfpath,
  63. u32 regaddr, u32 bitmask, u32 data)
  64. {
  65. struct rtl_priv *rtlpriv = rtl_priv(hw);
  66. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  67. u32 original_value, bitshift;
  68. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  69. "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
  70. regaddr, bitmask, data, rfpath);
  71. if (rtlphy->rf_mode != RF_OP_BY_FW) {
  72. if (bitmask != RFREG_OFFSET_MASK) {
  73. original_value = _rtl92c_phy_rf_serial_read(hw,
  74. rfpath,
  75. regaddr);
  76. bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  77. data =
  78. ((original_value & (~bitmask)) |
  79. (data << bitshift));
  80. }
  81. _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data);
  82. } else {
  83. if (bitmask != RFREG_OFFSET_MASK) {
  84. original_value = _rtl92c_phy_fw_rf_serial_read(hw,
  85. rfpath,
  86. regaddr);
  87. bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  88. data =
  89. ((original_value & (~bitmask)) |
  90. (data << bitshift));
  91. }
  92. _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
  93. }
  94. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  95. "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
  96. regaddr, bitmask, data, rfpath);
  97. }
  98. bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw)
  99. {
  100. bool rtstatus;
  101. rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw);
  102. return rtstatus;
  103. }
  104. bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
  105. {
  106. bool rtstatus = true;
  107. struct rtl_priv *rtlpriv = rtl_priv(hw);
  108. u16 regval;
  109. u32 regval32;
  110. u8 b_reg_hwparafile = 1;
  111. _rtl92c_phy_init_bb_rf_register_definition(hw);
  112. regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
  113. rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, regval | BIT(13) |
  114. BIT(0) | BIT(1));
  115. rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
  116. rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
  117. rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
  118. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
  119. FEN_BB_GLB_RSTn | FEN_BBRSTB);
  120. regval32 = rtl_read_dword(rtlpriv, 0x87c);
  121. rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31)));
  122. rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
  123. rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
  124. if (b_reg_hwparafile == 1)
  125. rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
  126. return rtstatus;
  127. }
  128. bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
  129. {
  130. struct rtl_priv *rtlpriv = rtl_priv(hw);
  131. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  132. u32 i;
  133. u32 arraylength;
  134. u32 *ptrarray;
  135. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n");
  136. arraylength = rtlphy->hwparam_tables[MAC_REG].length ;
  137. ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata;
  138. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CUMAC_2T_ARRAY\n");
  139. for (i = 0; i < arraylength; i = i + 2)
  140. rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
  141. return true;
  142. }
  143. bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
  144. u8 configtype)
  145. {
  146. int i;
  147. u32 *phy_regarray_table;
  148. u32 *agctab_array_table;
  149. u16 phy_reg_arraylen, agctab_arraylen;
  150. struct rtl_priv *rtlpriv = rtl_priv(hw);
  151. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  152. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  153. if (IS_92C_SERIAL(rtlhal->version)) {
  154. agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_2T].length;
  155. agctab_array_table = rtlphy->hwparam_tables[AGCTAB_2T].pdata;
  156. phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_2T].length;
  157. phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_2T].pdata;
  158. } else {
  159. agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_1T].length;
  160. agctab_array_table = rtlphy->hwparam_tables[AGCTAB_1T].pdata;
  161. phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_1T].length;
  162. phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_1T].pdata;
  163. }
  164. if (configtype == BASEBAND_CONFIG_PHY_REG) {
  165. for (i = 0; i < phy_reg_arraylen; i = i + 2) {
  166. rtl_addr_delay(phy_regarray_table[i]);
  167. rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD,
  168. phy_regarray_table[i + 1]);
  169. udelay(1);
  170. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  171. "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
  172. phy_regarray_table[i],
  173. phy_regarray_table[i + 1]);
  174. }
  175. } else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
  176. for (i = 0; i < agctab_arraylen; i = i + 2) {
  177. rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
  178. agctab_array_table[i + 1]);
  179. udelay(1);
  180. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  181. "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
  182. agctab_array_table[i],
  183. agctab_array_table[i + 1]);
  184. }
  185. }
  186. return true;
  187. }
  188. bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
  189. u8 configtype)
  190. {
  191. struct rtl_priv *rtlpriv = rtl_priv(hw);
  192. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  193. int i;
  194. u32 *phy_regarray_table_pg;
  195. u16 phy_regarray_pg_len;
  196. rtlphy->pwrgroup_cnt = 0;
  197. phy_regarray_pg_len = rtlphy->hwparam_tables[PHY_REG_PG].length;
  198. phy_regarray_table_pg = rtlphy->hwparam_tables[PHY_REG_PG].pdata;
  199. if (configtype == BASEBAND_CONFIG_PHY_REG) {
  200. for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
  201. rtl_addr_delay(phy_regarray_table_pg[i]);
  202. _rtl92c_store_pwrIndex_diffrate_offset(hw,
  203. phy_regarray_table_pg[i],
  204. phy_regarray_table_pg[i + 1],
  205. phy_regarray_table_pg[i + 2]);
  206. }
  207. } else {
  208. RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
  209. "configtype != BaseBand_Config_PHY_REG\n");
  210. }
  211. return true;
  212. }
  213. bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
  214. enum radio_path rfpath)
  215. {
  216. int i;
  217. u32 *radioa_array_table;
  218. u32 *radiob_array_table;
  219. u16 radioa_arraylen, radiob_arraylen;
  220. struct rtl_priv *rtlpriv = rtl_priv(hw);
  221. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  222. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  223. if (IS_92C_SERIAL(rtlhal->version)) {
  224. radioa_arraylen = rtlphy->hwparam_tables[RADIOA_2T].length;
  225. radioa_array_table = rtlphy->hwparam_tables[RADIOA_2T].pdata;
  226. radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length;
  227. radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata;
  228. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  229. "Radio_A:RTL8192CURADIOA_2TARRAY\n");
  230. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  231. "Radio_B:RTL8192CU_RADIOB_2TARRAY\n");
  232. } else {
  233. radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length;
  234. radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata;
  235. radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length;
  236. radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata;
  237. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  238. "Radio_A:RTL8192CU_RADIOA_1TARRAY\n");
  239. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  240. "Radio_B:RTL8192CU_RADIOB_1TARRAY\n");
  241. }
  242. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath);
  243. switch (rfpath) {
  244. case RF90_PATH_A:
  245. for (i = 0; i < radioa_arraylen; i = i + 2) {
  246. rtl_rfreg_delay(hw, rfpath, radioa_array_table[i],
  247. RFREG_OFFSET_MASK,
  248. radioa_array_table[i + 1]);
  249. }
  250. break;
  251. case RF90_PATH_B:
  252. for (i = 0; i < radiob_arraylen; i = i + 2) {
  253. rtl_rfreg_delay(hw, rfpath, radiob_array_table[i],
  254. RFREG_OFFSET_MASK,
  255. radiob_array_table[i + 1]);
  256. }
  257. break;
  258. case RF90_PATH_C:
  259. case RF90_PATH_D:
  260. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  261. "switch case %#x not processed\n", rfpath);
  262. break;
  263. default:
  264. break;
  265. }
  266. return true;
  267. }
  268. void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
  269. {
  270. struct rtl_priv *rtlpriv = rtl_priv(hw);
  271. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  272. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  273. struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
  274. u8 reg_bw_opmode;
  275. u8 reg_prsr_rsc;
  276. RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n",
  277. rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
  278. "20MHz" : "40MHz");
  279. if (is_hal_stop(rtlhal)) {
  280. rtlphy->set_bwmode_inprogress = false;
  281. return;
  282. }
  283. reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
  284. reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
  285. switch (rtlphy->current_chan_bw) {
  286. case HT_CHANNEL_WIDTH_20:
  287. reg_bw_opmode |= BW_OPMODE_20MHZ;
  288. rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
  289. break;
  290. case HT_CHANNEL_WIDTH_20_40:
  291. reg_bw_opmode &= ~BW_OPMODE_20MHZ;
  292. rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
  293. reg_prsr_rsc =
  294. (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
  295. rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
  296. break;
  297. default:
  298. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  299. "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
  300. break;
  301. }
  302. switch (rtlphy->current_chan_bw) {
  303. case HT_CHANNEL_WIDTH_20:
  304. rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
  305. rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
  306. rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
  307. break;
  308. case HT_CHANNEL_WIDTH_20_40:
  309. rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
  310. rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
  311. rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
  312. (mac->cur_40_prime_sc >> 1));
  313. rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
  314. rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);
  315. rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
  316. (mac->cur_40_prime_sc ==
  317. HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
  318. break;
  319. default:
  320. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  321. "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
  322. break;
  323. }
  324. rtl92cu_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
  325. rtlphy->set_bwmode_inprogress = false;
  326. RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
  327. }
  328. void rtl92cu_bb_block_on(struct ieee80211_hw *hw)
  329. {
  330. struct rtl_priv *rtlpriv = rtl_priv(hw);
  331. mutex_lock(&rtlpriv->io.bb_mutex);
  332. rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
  333. rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
  334. mutex_unlock(&rtlpriv->io.bb_mutex);
  335. }
  336. void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
  337. {
  338. u8 tmpreg;
  339. u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
  340. struct rtl_priv *rtlpriv = rtl_priv(hw);
  341. tmpreg = rtl_read_byte(rtlpriv, 0xd03);
  342. if ((tmpreg & 0x70) != 0)
  343. rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
  344. else
  345. rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
  346. if ((tmpreg & 0x70) != 0) {
  347. rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS);
  348. if (is2t)
  349. rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
  350. MASK12BITS);
  351. rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
  352. (rf_a_mode & 0x8FFFF) | 0x10000);
  353. if (is2t)
  354. rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
  355. (rf_b_mode & 0x8FFFF) | 0x10000);
  356. }
  357. lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
  358. rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000);
  359. mdelay(100);
  360. if ((tmpreg & 0x70) != 0) {
  361. rtl_write_byte(rtlpriv, 0xd03, tmpreg);
  362. rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
  363. if (is2t)
  364. rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
  365. rf_b_mode);
  366. } else {
  367. rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
  368. }
  369. }
  370. static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
  371. enum rf_pwrstate rfpwr_state)
  372. {
  373. struct rtl_priv *rtlpriv = rtl_priv(hw);
  374. struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
  375. struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
  376. struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
  377. bool bresult = true;
  378. u8 i, queue_id;
  379. struct rtl8192_tx_ring *ring = NULL;
  380. switch (rfpwr_state) {
  381. case ERFON:
  382. if ((ppsc->rfpwr_state == ERFOFF) &&
  383. RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
  384. bool rtstatus;
  385. u32 InitializeCount = 0;
  386. do {
  387. InitializeCount++;
  388. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  389. "IPS Set eRf nic enable\n");
  390. rtstatus = rtl_ps_enable_nic(hw);
  391. } while (!rtstatus && (InitializeCount < 10));
  392. RT_CLEAR_PS_LEVEL(ppsc,
  393. RT_RF_OFF_LEVL_HALT_NIC);
  394. } else {
  395. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  396. "Set ERFON sleeped:%d ms\n",
  397. jiffies_to_msecs(jiffies -
  398. ppsc->last_sleep_jiffies));
  399. ppsc->last_awake_jiffies = jiffies;
  400. rtl92ce_phy_set_rf_on(hw);
  401. }
  402. if (mac->link_state == MAC80211_LINKED) {
  403. rtlpriv->cfg->ops->led_control(hw,
  404. LED_CTL_LINK);
  405. } else {
  406. rtlpriv->cfg->ops->led_control(hw,
  407. LED_CTL_NO_LINK);
  408. }
  409. break;
  410. case ERFOFF:
  411. for (queue_id = 0, i = 0;
  412. queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
  413. ring = &pcipriv->dev.tx_ring[queue_id];
  414. if (skb_queue_len(&ring->queue) == 0 ||
  415. queue_id == BEACON_QUEUE) {
  416. queue_id++;
  417. continue;
  418. } else {
  419. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  420. "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
  421. i + 1,
  422. queue_id,
  423. skb_queue_len(&ring->queue));
  424. udelay(10);
  425. i++;
  426. }
  427. if (i >= MAX_DOZE_WAITING_TIMES_9x) {
  428. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  429. "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n",
  430. MAX_DOZE_WAITING_TIMES_9x,
  431. queue_id,
  432. skb_queue_len(&ring->queue));
  433. break;
  434. }
  435. }
  436. if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
  437. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  438. "IPS Set eRf nic disable\n");
  439. rtl_ps_disable_nic(hw);
  440. RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
  441. } else {
  442. if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
  443. rtlpriv->cfg->ops->led_control(hw,
  444. LED_CTL_NO_LINK);
  445. } else {
  446. rtlpriv->cfg->ops->led_control(hw,
  447. LED_CTL_POWER_OFF);
  448. }
  449. }
  450. break;
  451. case ERFSLEEP:
  452. if (ppsc->rfpwr_state == ERFOFF)
  453. return false;
  454. for (queue_id = 0, i = 0;
  455. queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
  456. ring = &pcipriv->dev.tx_ring[queue_id];
  457. if (skb_queue_len(&ring->queue) == 0) {
  458. queue_id++;
  459. continue;
  460. } else {
  461. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  462. "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
  463. i + 1, queue_id,
  464. skb_queue_len(&ring->queue));
  465. udelay(10);
  466. i++;
  467. }
  468. if (i >= MAX_DOZE_WAITING_TIMES_9x) {
  469. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  470. "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
  471. MAX_DOZE_WAITING_TIMES_9x,
  472. queue_id,
  473. skb_queue_len(&ring->queue));
  474. break;
  475. }
  476. }
  477. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  478. "Set ERFSLEEP awaked:%d ms\n",
  479. jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies));
  480. ppsc->last_sleep_jiffies = jiffies;
  481. _rtl92c_phy_set_rf_sleep(hw);
  482. break;
  483. default:
  484. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  485. "switch case %#x not processed\n", rfpwr_state);
  486. bresult = false;
  487. break;
  488. }
  489. if (bresult)
  490. ppsc->rfpwr_state = rfpwr_state;
  491. return bresult;
  492. }
  493. bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
  494. enum rf_pwrstate rfpwr_state)
  495. {
  496. struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
  497. bool bresult = false;
  498. if (rfpwr_state == ppsc->rfpwr_state)
  499. return bresult;
  500. bresult = _rtl92cu_phy_set_rf_power_state(hw, rfpwr_state);
  501. return bresult;
  502. }