phydm_cfotracking.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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 "mp_precomp.h"
  21. #include "phydm_precomp.h"
  22. void
  23. odm_set_crystal_cap(
  24. void *p_dm_void,
  25. u8 crystal_cap
  26. )
  27. {
  28. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  29. struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
  30. struct _ADAPTER *adapter = p_dm_odm->adapter;/* JJ modified 20161115 */
  31. if (p_cfo_track->crystal_cap == crystal_cap)
  32. return;
  33. p_cfo_track->crystal_cap = crystal_cap;
  34. #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
  35. if (p_dm_odm->support_ic_type & (ODM_RTL8188E | ODM_RTL8188F)) {
  36. /* write 0x24[22:17] = 0x24[16:11] = crystal_cap */
  37. crystal_cap = crystal_cap & 0x3F;
  38. odm_set_bb_reg(p_dm_odm, REG_AFE_XTAL_CTRL, 0x007ff800, (crystal_cap | (crystal_cap << 6)));
  39. } else if (p_dm_odm->support_ic_type & ODM_RTL8812) {
  40. /* write 0x2C[30:25] = 0x2C[24:19] = crystal_cap */
  41. crystal_cap = crystal_cap & 0x3F;
  42. odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0x7FF80000, (crystal_cap | (crystal_cap << 6)));
  43. } else if ((p_dm_odm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723B | ODM_RTL8192E | ODM_RTL8821 | ODM_RTL8723D))) {
  44. /* 0x2C[23:18] = 0x2C[17:12] = crystal_cap */
  45. crystal_cap = crystal_cap & 0x3F;
  46. odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0x00FFF000, (crystal_cap | (crystal_cap << 6)));
  47. } else if (p_dm_odm->support_ic_type & ODM_RTL8814A) {
  48. /* write 0x2C[26:21] = 0x2C[20:15] = crystal_cap */
  49. crystal_cap = crystal_cap & 0x3F;
  50. odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0x07FF8000, (crystal_cap | (crystal_cap << 6)));
  51. } else if (p_dm_odm->support_ic_type & (ODM_RTL8822B | ODM_RTL8821C)) {
  52. /* write 0x24[30:25] = 0x28[6:1] = crystal_cap */
  53. crystal_cap = crystal_cap & 0x3F;
  54. odm_set_bb_reg(p_dm_odm, REG_AFE_XTAL_CTRL, 0x7e000000, crystal_cap);
  55. odm_set_bb_reg(p_dm_odm, REG_AFE_PLL_CTRL, 0x7e, crystal_cap);
  56. } else {
  57. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_set_crystal_cap(): Use default setting.\n"));
  58. odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0xFFF000, (crystal_cap | (crystal_cap << 6)));
  59. }
  60. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_set_crystal_cap(): crystal_cap = 0x%x\n", crystal_cap));
  61. #endif
  62. /* JJ modified 20161115 */
  63. #if (DM_ODM_SUPPORT_TYPE & ODM_WIN)
  64. if (p_dm_odm->support_ic_type & (ODM_RTL8710B)) {
  65. /* write 0x60[29:24] = 0x60[23:18] = crystal_cap */
  66. crystal_cap = crystal_cap & 0x3F;
  67. HAL_SetSYSOnReg(adapter, REG_SYS_XTAL_CTRL0, 0x3FFC0000, (crystal_cap | (crystal_cap << 6)));
  68. }
  69. #endif
  70. }
  71. u8
  72. odm_get_default_crytaltal_cap(
  73. void *p_dm_void
  74. )
  75. {
  76. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  77. u8 crystal_cap = 0x20;
  78. #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
  79. struct _ADAPTER *adapter = p_dm_odm->adapter;
  80. HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter);
  81. crystal_cap = p_hal_data->crystal_cap;
  82. #else
  83. struct rtl8192cd_priv *priv = p_dm_odm->priv;
  84. if (priv->pmib->dot11RFEntry.xcap > 0)
  85. crystal_cap = priv->pmib->dot11RFEntry.xcap;
  86. #endif
  87. crystal_cap = crystal_cap & 0x3f;
  88. return crystal_cap;
  89. }
  90. void
  91. odm_set_atc_status(
  92. void *p_dm_void,
  93. boolean atc_status
  94. )
  95. {
  96. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  97. struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
  98. if (p_cfo_track->is_atc_status == atc_status)
  99. return;
  100. odm_set_bb_reg(p_dm_odm, ODM_REG(BB_ATC, p_dm_odm), ODM_BIT(BB_ATC, p_dm_odm), atc_status);
  101. p_cfo_track->is_atc_status = atc_status;
  102. }
  103. boolean
  104. odm_get_atc_status(
  105. void *p_dm_void
  106. )
  107. {
  108. boolean atc_status;
  109. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  110. atc_status = (boolean)odm_get_bb_reg(p_dm_odm, ODM_REG(BB_ATC, p_dm_odm), ODM_BIT(BB_ATC, p_dm_odm));
  111. return atc_status;
  112. }
  113. void
  114. odm_cfo_tracking_reset(
  115. void *p_dm_void
  116. )
  117. {
  118. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  119. struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
  120. p_cfo_track->def_x_cap = odm_get_default_crytaltal_cap(p_dm_odm);
  121. p_cfo_track->is_adjust = true;
  122. if (p_cfo_track->crystal_cap > p_cfo_track->def_x_cap) {
  123. odm_set_crystal_cap(p_dm_odm, p_cfo_track->crystal_cap - 1);
  124. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD,
  125. ("odm_cfo_tracking_reset(): approch default value (0x%x)\n", p_cfo_track->crystal_cap));
  126. } else if (p_cfo_track->crystal_cap < p_cfo_track->def_x_cap) {
  127. odm_set_crystal_cap(p_dm_odm, p_cfo_track->crystal_cap + 1);
  128. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD,
  129. ("odm_cfo_tracking_reset(): approch default value (0x%x)\n", p_cfo_track->crystal_cap));
  130. }
  131. #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
  132. odm_set_atc_status(p_dm_odm, true);
  133. #endif
  134. }
  135. void
  136. odm_cfo_tracking_init(
  137. void *p_dm_void
  138. )
  139. {
  140. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  141. struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
  142. p_cfo_track->def_x_cap = p_cfo_track->crystal_cap = odm_get_default_crytaltal_cap(p_dm_odm);
  143. p_cfo_track->is_atc_status = odm_get_atc_status(p_dm_odm);
  144. p_cfo_track->is_adjust = true;
  145. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("ODM_CfoTracking_init()=========>\n"));
  146. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("ODM_CfoTracking_init(): is_atc_status = %d, crystal_cap = 0x%x\n", p_cfo_track->is_atc_status, p_cfo_track->def_x_cap));
  147. #if RTL8822B_SUPPORT
  148. /* Crystal cap. control by WiFi */
  149. if (p_dm_odm->support_ic_type & ODM_RTL8822B)
  150. odm_set_bb_reg(p_dm_odm, 0x10, 0x40, 0x1);
  151. #endif
  152. #if RTL8821C_SUPPORT
  153. /* Crystal cap. control by WiFi */
  154. if (p_dm_odm->support_ic_type & ODM_RTL8821C)
  155. odm_set_bb_reg(p_dm_odm, 0x10, 0x40, 0x1);
  156. #endif
  157. }
  158. void
  159. odm_cfo_tracking(
  160. void *p_dm_void
  161. )
  162. {
  163. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  164. struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
  165. s32 CFO_ave = 0;
  166. u32 CFO_rpt_sum, cfo_khz_avg[4] = {0};
  167. s32 CFO_ave_diff;
  168. s8 crystal_cap = p_cfo_track->crystal_cap;
  169. u8 adjust_xtal = 1, i, valid_path_cnt = 0;
  170. /* 4 Support ability */
  171. if (!(p_dm_odm->support_ability & ODM_BB_CFO_TRACKING)) {
  172. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Return: support_ability ODM_BB_CFO_TRACKING is disabled\n"));
  173. return;
  174. }
  175. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking()=========>\n"));
  176. if (!p_dm_odm->is_linked || !p_dm_odm->is_one_entry_only) {
  177. /* 4 No link or more than one entry */
  178. odm_cfo_tracking_reset(p_dm_odm);
  179. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Reset: is_linked = %d, is_one_entry_only = %d\n",
  180. p_dm_odm->is_linked, p_dm_odm->is_one_entry_only));
  181. } else {
  182. /* 3 1. CFO Tracking */
  183. /* 4 1.1 No new packet */
  184. if (p_cfo_track->packet_count == p_cfo_track->packet_count_pre) {
  185. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): packet counter doesn't change\n"));
  186. return;
  187. }
  188. p_cfo_track->packet_count_pre = p_cfo_track->packet_count;
  189. /* 4 1.2 Calculate CFO */
  190. for (i = 0; i < p_dm_odm->num_rf_path; i++) {
  191. if (p_cfo_track->CFO_cnt[i] == 0)
  192. continue;
  193. valid_path_cnt++;
  194. CFO_rpt_sum = (u32)((p_cfo_track->CFO_tail[i] < 0) ? (0 - p_cfo_track->CFO_tail[i]) : p_cfo_track->CFO_tail[i]);
  195. cfo_khz_avg[i] = CFO_HW_RPT_2_MHZ(CFO_rpt_sum) / p_cfo_track->CFO_cnt[i];
  196. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("[path %d] CFO_rpt_sum = (( %d )), CFO_cnt = (( %d )) , CFO_avg= (( %s%d )) kHz\n",
  197. i, CFO_rpt_sum, p_cfo_track->CFO_cnt[i], ((p_cfo_track->CFO_tail[i] < 0) ? "-" : " "), cfo_khz_avg[i]));
  198. }
  199. for (i = 0; i < valid_path_cnt; i++) {
  200. /* ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("path [%d], p_cfo_track->CFO_tail = %d\n", i, p_cfo_track->CFO_tail[i])); */
  201. if (p_cfo_track->CFO_tail[i] < 0) {
  202. CFO_ave += (0 - (s32)cfo_khz_avg[i]);
  203. /* ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("CFO_ave = %d\n", CFO_ave)); */
  204. } else
  205. CFO_ave += (s32)cfo_khz_avg[i];
  206. }
  207. if (valid_path_cnt >= 2)
  208. CFO_ave = CFO_ave / valid_path_cnt;
  209. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("valid_path_cnt = ((%d)), CFO_ave = ((%d kHz))\n", valid_path_cnt, CFO_ave));
  210. /*reset counter*/
  211. for (i = 0; i < p_dm_odm->num_rf_path; i++) {
  212. p_cfo_track->CFO_tail[i] = 0;
  213. p_cfo_track->CFO_cnt[i] = 0;
  214. }
  215. /* 4 1.3 Avoid abnormal large CFO */
  216. CFO_ave_diff = (p_cfo_track->CFO_ave_pre >= CFO_ave) ? (p_cfo_track->CFO_ave_pre - CFO_ave) : (CFO_ave - p_cfo_track->CFO_ave_pre);
  217. if (CFO_ave_diff > 20 && p_cfo_track->large_cfo_hit == 0 && !p_cfo_track->is_adjust) {
  218. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): first large CFO hit\n"));
  219. p_cfo_track->large_cfo_hit = 1;
  220. return;
  221. } else
  222. p_cfo_track->large_cfo_hit = 0;
  223. p_cfo_track->CFO_ave_pre = CFO_ave;
  224. /* 4 1.4 Dynamic Xtal threshold */
  225. if (p_cfo_track->is_adjust == false) {
  226. if (CFO_ave > CFO_TH_XTAL_HIGH || CFO_ave < (-CFO_TH_XTAL_HIGH))
  227. p_cfo_track->is_adjust = true;
  228. } else {
  229. if (CFO_ave < CFO_TH_XTAL_LOW && CFO_ave > (-CFO_TH_XTAL_LOW))
  230. p_cfo_track->is_adjust = false;
  231. }
  232. #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
  233. /* 4 1.5 BT case: Disable CFO tracking */
  234. if (p_dm_odm->is_bt_enabled) {
  235. p_cfo_track->is_adjust = false;
  236. odm_set_crystal_cap(p_dm_odm, p_cfo_track->def_x_cap);
  237. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Disable CFO tracking for BT!!\n"));
  238. }
  239. #if 0
  240. /* 4 1.6 Big jump */
  241. if (p_cfo_track->is_adjust) {
  242. if (CFO_ave > CFO_TH_XTAL_LOW)
  243. adjust_xtal = adjust_xtal + ((CFO_ave - CFO_TH_XTAL_LOW) >> 2);
  244. else if (CFO_ave < (-CFO_TH_XTAL_LOW))
  245. adjust_xtal = adjust_xtal + ((CFO_TH_XTAL_LOW - CFO_ave) >> 2);
  246. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Crystal cap offset = %d\n", adjust_xtal));
  247. }
  248. #endif
  249. #endif
  250. /* 4 1.7 Adjust Crystal Cap. */
  251. if (p_cfo_track->is_adjust) {
  252. if (CFO_ave > CFO_TH_XTAL_LOW)
  253. crystal_cap = crystal_cap + adjust_xtal;
  254. else if (CFO_ave < (-CFO_TH_XTAL_LOW))
  255. crystal_cap = crystal_cap - adjust_xtal;
  256. if (crystal_cap > 0x3f)
  257. crystal_cap = 0x3f;
  258. else if (crystal_cap < 0)
  259. crystal_cap = 0;
  260. odm_set_crystal_cap(p_dm_odm, (u8)crystal_cap);
  261. }
  262. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Crystal cap = 0x%x, Default Crystal cap = 0x%x\n",
  263. p_cfo_track->crystal_cap, p_cfo_track->def_x_cap));
  264. #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
  265. if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES)
  266. return;
  267. /* 3 2. Dynamic ATC switch */
  268. if (CFO_ave < CFO_TH_ATC && CFO_ave > -CFO_TH_ATC) {
  269. odm_set_atc_status(p_dm_odm, false);
  270. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Disable ATC!!\n"));
  271. } else {
  272. odm_set_atc_status(p_dm_odm, true);
  273. ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Enable ATC!!\n"));
  274. }
  275. #endif
  276. }
  277. }
  278. void
  279. odm_parsing_cfo(
  280. void *p_dm_void,
  281. void *p_pktinfo_void,
  282. s8 *pcfotail,
  283. u8 num_ss
  284. )
  285. {
  286. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  287. struct _odm_per_pkt_info_ *p_pktinfo = (struct _odm_per_pkt_info_ *)p_pktinfo_void;
  288. struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
  289. u8 i;
  290. if (!(p_dm_odm->support_ability & ODM_BB_CFO_TRACKING))
  291. return;
  292. #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
  293. if (p_pktinfo->is_packet_match_bssid)
  294. #else
  295. if (p_pktinfo->station_id != 0)
  296. #endif
  297. {
  298. if (num_ss > p_dm_odm->num_rf_path) /*For fool proof*/
  299. num_ss = p_dm_odm->num_rf_path;
  300. /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("num_ss = ((%d)), p_dm_odm->num_rf_path = ((%d))\n", num_ss, p_dm_odm->num_rf_path));*/
  301. /* 3 Update CFO report for path-A & path-B */
  302. /* Only paht-A and path-B have CFO tail and short CFO */
  303. for (i = 0; i < num_ss; i++) {
  304. p_cfo_track->CFO_tail[i] += pcfotail[i];
  305. p_cfo_track->CFO_cnt[i]++;
  306. /*ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("[ID %d][path %d][rate 0x%x] CFO_tail = ((%d)), CFO_tail_sum = ((%d)), CFO_cnt = ((%d))\n",
  307. p_pktinfo->station_id, i, p_pktinfo->data_rate, pcfotail[i], p_cfo_track->CFO_tail[i], p_cfo_track->CFO_cnt[i]));
  308. */
  309. }
  310. /* 3 Update packet counter */
  311. if (p_cfo_track->packet_count == 0xffffffff)
  312. p_cfo_track->packet_count = 0;
  313. else
  314. p_cfo_track->packet_count++;
  315. }
  316. }