1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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.
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
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
19 ******************************************************************************/
20 #include "mp_precomp.h"
21 #include "phydm_precomp.h"
29 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
30 struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
31 struct _ADAPTER *adapter = p_dm_odm->adapter;/* JJ modified 20161115 */
33 if (p_cfo_track->crystal_cap == crystal_cap)
36 p_cfo_track->crystal_cap = crystal_cap;
38 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
39 if (p_dm_odm->support_ic_type & (ODM_RTL8188E | ODM_RTL8188F)) {
40 /* write 0x24[22:17] = 0x24[16:11] = crystal_cap */
41 crystal_cap = crystal_cap & 0x3F;
42 odm_set_bb_reg(p_dm_odm, REG_AFE_XTAL_CTRL, 0x007ff800, (crystal_cap | (crystal_cap << 6)));
43 } else if (p_dm_odm->support_ic_type & ODM_RTL8812) {
44 /* write 0x2C[30:25] = 0x2C[24:19] = crystal_cap */
45 crystal_cap = crystal_cap & 0x3F;
46 odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0x7FF80000, (crystal_cap | (crystal_cap << 6)));
47 } else if ((p_dm_odm->support_ic_type & (ODM_RTL8703B | ODM_RTL8723B | ODM_RTL8192E | ODM_RTL8821))) {
48 /* 0x2C[23:18] = 0x2C[17:12] = crystal_cap */
49 crystal_cap = crystal_cap & 0x3F;
50 odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0x00FFF000, (crystal_cap | (crystal_cap << 6)));
51 } else if (p_dm_odm->support_ic_type & ODM_RTL8814A) {
52 /* write 0x2C[26:21] = 0x2C[20:15] = crystal_cap */
53 crystal_cap = crystal_cap & 0x3F;
54 odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0x07FF8000, (crystal_cap | (crystal_cap << 6)));
55 } else if (p_dm_odm->support_ic_type & (ODM_RTL8822B | ODM_RTL8821C)) {
56 /* write 0x24[30:25] = 0x28[6:1] = crystal_cap */
57 crystal_cap = crystal_cap & 0x3F;
58 odm_set_bb_reg(p_dm_odm, REG_AFE_XTAL_CTRL, 0x7e000000, crystal_cap);
59 odm_set_bb_reg(p_dm_odm, REG_AFE_PLL_CTRL, 0x7e, crystal_cap);
61 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_set_crystal_cap(): Use default setting.\n"));
62 odm_set_bb_reg(p_dm_odm, REG_MAC_PHY_CTRL, 0xFFF000, (crystal_cap | (crystal_cap << 6)));
65 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_set_crystal_cap(): crystal_cap = 0x%x\n", crystal_cap));
68 /* JJ modified 20161115 */
69 #if (DM_ODM_SUPPORT_TYPE & ODM_WIN)
70 if (p_dm_odm->support_ic_type & (ODM_RTL8710B)) {
71 /* write 0x60[29:24] = 0x60[23:18] = crystal_cap */
72 crystal_cap = crystal_cap & 0x3F;
73 HAL_SetSYSOnReg(adapter, REG_SYS_XTAL_CTRL0, 0x3FFC0000, (crystal_cap | (crystal_cap << 6)));
80 odm_get_default_crytaltal_cap(
84 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
85 u8 crystal_cap = 0x20;
87 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
88 struct _ADAPTER *adapter = p_dm_odm->adapter;
89 HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter);
91 crystal_cap = p_hal_data->crystal_cap;
93 struct rtl8192cd_priv *priv = p_dm_odm->priv;
95 if (priv->pmib->dot11RFEntry.xcap > 0)
96 crystal_cap = priv->pmib->dot11RFEntry.xcap;
99 crystal_cap = crystal_cap & 0x3f;
110 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
111 struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
113 if (p_cfo_track->is_atc_status == atc_status)
116 odm_set_bb_reg(p_dm_odm, ODM_REG(BB_ATC, p_dm_odm), ODM_BIT(BB_ATC, p_dm_odm), atc_status);
117 p_cfo_track->is_atc_status = atc_status;
126 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
128 atc_status = (boolean)odm_get_bb_reg(p_dm_odm, ODM_REG(BB_ATC, p_dm_odm), ODM_BIT(BB_ATC, p_dm_odm));
133 odm_cfo_tracking_reset(
137 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
138 struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
140 p_cfo_track->def_x_cap = odm_get_default_crytaltal_cap(p_dm_odm);
141 p_cfo_track->is_adjust = true;
143 if (p_cfo_track->crystal_cap > p_cfo_track->def_x_cap) {
144 odm_set_crystal_cap(p_dm_odm, p_cfo_track->crystal_cap - 1);
145 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD,
146 ("odm_cfo_tracking_reset(): approch default value (0x%x)\n", p_cfo_track->crystal_cap));
147 } else if (p_cfo_track->crystal_cap < p_cfo_track->def_x_cap) {
148 odm_set_crystal_cap(p_dm_odm, p_cfo_track->crystal_cap + 1);
149 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD,
150 ("odm_cfo_tracking_reset(): approch default value (0x%x)\n", p_cfo_track->crystal_cap));
153 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
154 odm_set_atc_status(p_dm_odm, true);
159 odm_cfo_tracking_init(
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);
166 p_cfo_track->def_x_cap = p_cfo_track->crystal_cap = odm_get_default_crytaltal_cap(p_dm_odm);
167 p_cfo_track->is_atc_status = odm_get_atc_status(p_dm_odm);
168 p_cfo_track->is_adjust = true;
169 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("ODM_CfoTracking_init()=========>\n"));
170 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));
173 /* Crystal cap. control by WiFi */
174 if (p_dm_odm->support_ic_type & ODM_RTL8822B)
175 odm_set_bb_reg(p_dm_odm, 0x10, 0x40, 0x1);
179 /* Crystal cap. control by WiFi */
180 if (p_dm_odm->support_ic_type & ODM_RTL8821C)
181 odm_set_bb_reg(p_dm_odm, 0x10, 0x40, 0x1);
190 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
191 struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
193 u32 CFO_rpt_sum, cfo_khz_avg[4] = {0};
195 s8 crystal_cap = p_cfo_track->crystal_cap;
196 u8 adjust_xtal = 1, i, valid_path_cnt = 0;
198 /* 4 Support ability */
199 if (!(p_dm_odm->support_ability & ODM_BB_CFO_TRACKING)) {
200 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"));
204 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking()=========>\n"));
206 if (!p_dm_odm->is_linked || !p_dm_odm->is_one_entry_only) {
207 /* 4 No link or more than one entry */
208 odm_cfo_tracking_reset(p_dm_odm);
209 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",
210 p_dm_odm->is_linked, p_dm_odm->is_one_entry_only));
212 /* 3 1. CFO Tracking */
213 /* 4 1.1 No new packet */
214 if (p_cfo_track->packet_count == p_cfo_track->packet_count_pre) {
215 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): packet counter doesn't change\n"));
218 p_cfo_track->packet_count_pre = p_cfo_track->packet_count;
220 /* 4 1.2 Calculate CFO */
221 for (i = 0; i < p_dm_odm->num_rf_path; i++) {
223 if (p_cfo_track->CFO_cnt[i] == 0)
227 CFO_rpt_sum = (u32)((p_cfo_track->CFO_tail[i] < 0) ? (0 - p_cfo_track->CFO_tail[i]) : p_cfo_track->CFO_tail[i]);
228 cfo_khz_avg[i] = CFO_HW_RPT_2_MHZ(CFO_rpt_sum) / p_cfo_track->CFO_cnt[i];
230 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",
231 i, CFO_rpt_sum, p_cfo_track->CFO_cnt[i], ((p_cfo_track->CFO_tail[i] < 0) ? "-" : " "), cfo_khz_avg[i]));
234 for (i = 0; i < valid_path_cnt; i++) {
236 /* 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])); */
237 if (p_cfo_track->CFO_tail[i] < 0) {
238 CFO_ave += (0 - (s32)cfo_khz_avg[i]);
239 /* ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("CFO_ave = %d\n", CFO_ave)); */
241 CFO_ave += (s32)cfo_khz_avg[i];
244 if (valid_path_cnt >= 2)
245 CFO_ave = CFO_ave / valid_path_cnt;
247 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));
250 for (i = 0; i < p_dm_odm->num_rf_path; i++) {
251 p_cfo_track->CFO_tail[i] = 0;
252 p_cfo_track->CFO_cnt[i] = 0;
255 /* 4 1.3 Avoid abnormal large CFO */
256 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);
257 if (CFO_ave_diff > 20 && p_cfo_track->large_cfo_hit == 0 && !p_cfo_track->is_adjust) {
258 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): first large CFO hit\n"));
259 p_cfo_track->large_cfo_hit = 1;
262 p_cfo_track->large_cfo_hit = 0;
263 p_cfo_track->CFO_ave_pre = CFO_ave;
265 /* 4 1.4 Dynamic Xtal threshold */
266 if (p_cfo_track->is_adjust == false) {
267 if (CFO_ave > CFO_TH_XTAL_HIGH || CFO_ave < (-CFO_TH_XTAL_HIGH))
268 p_cfo_track->is_adjust = true;
270 if (CFO_ave < CFO_TH_XTAL_LOW && CFO_ave > (-CFO_TH_XTAL_LOW))
271 p_cfo_track->is_adjust = false;
274 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
275 /* 4 1.5 BT case: Disable CFO tracking */
276 if (p_dm_odm->is_bt_enabled) {
277 p_cfo_track->is_adjust = false;
278 odm_set_crystal_cap(p_dm_odm, p_cfo_track->def_x_cap);
279 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Disable CFO tracking for BT!!\n"));
283 if (p_cfo_track->is_adjust) {
284 if (CFO_ave > CFO_TH_XTAL_LOW)
285 adjust_xtal = adjust_xtal + ((CFO_ave - CFO_TH_XTAL_LOW) >> 2);
286 else if (CFO_ave < (-CFO_TH_XTAL_LOW))
287 adjust_xtal = adjust_xtal + ((CFO_TH_XTAL_LOW - CFO_ave) >> 2);
289 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Crystal cap offset = %d\n", adjust_xtal));
294 /* 4 1.7 Adjust Crystal Cap. */
295 if (p_cfo_track->is_adjust) {
296 if (CFO_ave > CFO_TH_XTAL_LOW)
297 crystal_cap = crystal_cap + adjust_xtal;
298 else if (CFO_ave < (-CFO_TH_XTAL_LOW))
299 crystal_cap = crystal_cap - adjust_xtal;
301 if (crystal_cap > 0x3f)
303 else if (crystal_cap < 0)
306 odm_set_crystal_cap(p_dm_odm, (u8)crystal_cap);
308 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",
309 p_cfo_track->crystal_cap, p_cfo_track->def_x_cap));
311 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
312 if (p_dm_odm->support_ic_type & ODM_IC_11AC_SERIES)
315 /* 3 2. Dynamic ATC switch */
316 if (CFO_ave < CFO_TH_ATC && CFO_ave > -CFO_TH_ATC) {
317 odm_set_atc_status(p_dm_odm, false);
318 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Disable ATC!!\n"));
320 odm_set_atc_status(p_dm_odm, true);
321 ODM_RT_TRACE(p_dm_odm, ODM_COMP_CFO_TRACKING, ODM_DBG_LOUD, ("odm_cfo_tracking(): Enable ATC!!\n"));
330 void *p_pktinfo_void,
335 struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
336 struct _odm_per_pkt_info_ *p_pktinfo = (struct _odm_per_pkt_info_ *)p_pktinfo_void;
337 struct _CFO_TRACKING_ *p_cfo_track = (struct _CFO_TRACKING_ *)phydm_get_structure(p_dm_odm, PHYDM_CFOTRACK);
340 if (!(p_dm_odm->support_ability & ODM_BB_CFO_TRACKING))
343 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
344 if (p_pktinfo->is_packet_match_bssid)
346 if (p_pktinfo->station_id != 0)
349 if (num_ss > p_dm_odm->num_rf_path) /*For fool proof*/
350 num_ss = p_dm_odm->num_rf_path;
352 /*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));*/
355 /* 3 Update CFO report for path-A & path-B */
356 /* Only paht-A and path-B have CFO tail and short CFO */
357 for (i = 0; i < num_ss; i++) {
358 p_cfo_track->CFO_tail[i] += pcfotail[i];
359 p_cfo_track->CFO_cnt[i]++;
360 /*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",
361 p_pktinfo->station_id, i, p_pktinfo->data_rate, pcfotail[i], p_cfo_track->CFO_tail[i], p_cfo_track->CFO_cnt[i]));
365 /* 3 Update packet counter */
366 if (p_cfo_track->packet_count == 0xffffffff)
367 p_cfo_track->packet_count = 0;
369 p_cfo_track->packet_count++;