diff options
Diffstat (limited to 'drivers/staging/rtlwifi/phydm/phydm_dig.c')
-rw-r--r-- | drivers/staging/rtlwifi/phydm/phydm_dig.c | 1526 |
1 files changed, 1526 insertions, 0 deletions
diff --git a/drivers/staging/rtlwifi/phydm/phydm_dig.c b/drivers/staging/rtlwifi/phydm/phydm_dig.c new file mode 100644 index 0000000..3115e7b --- /dev/null +++ b/drivers/staging/rtlwifi/phydm/phydm_dig.c @@ -0,0 +1,1526 @@ +// SPDX-License-Identifier: GPL-2.0 +/****************************************************************************** + * + * Copyright(c) 2007 - 2016 Realtek Corporation. + * + * Contact Information: + * wlanfae <wlanfae@realtek.com> + * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, + * Hsinchu 300, Taiwan. + * + * Larry Finger <Larry.Finger@lwfinger.net> + * + *****************************************************************************/ + +/* ************************************************************ + * include files + * *************************************************************/ +#include "mp_precomp.h" +#include "phydm_precomp.h" + +static int get_igi_for_diff(int); + +static inline void phydm_check_ap_write_dig(struct phy_dm_struct *dm, + u8 current_igi) +{ + switch (*dm->one_path_cca) { + case ODM_CCA_2R: + odm_set_bb_reg(dm, ODM_REG(IGI_A, dm), ODM_BIT(IGI, dm), + current_igi); + + if (dm->rf_type > ODM_1T1R) + odm_set_bb_reg(dm, ODM_REG(IGI_B, dm), ODM_BIT(IGI, dm), + current_igi); + break; + case ODM_CCA_1R_A: + odm_set_bb_reg(dm, ODM_REG(IGI_A, dm), ODM_BIT(IGI, dm), + current_igi); + if (dm->rf_type != ODM_1T1R) + odm_set_bb_reg(dm, ODM_REG(IGI_B, dm), ODM_BIT(IGI, dm), + get_igi_for_diff(current_igi)); + break; + case ODM_CCA_1R_B: + odm_set_bb_reg(dm, ODM_REG(IGI_B, dm), ODM_BIT(IGI, dm), + get_igi_for_diff(current_igi)); + if (dm->rf_type != ODM_1T1R) + odm_set_bb_reg(dm, ODM_REG(IGI_A, dm), ODM_BIT(IGI, dm), + current_igi); + break; + } +} + +static inline u8 phydm_get_current_igi(u8 dig_max_of_min, u8 rssi_min, + u8 current_igi) +{ + if (rssi_min < dig_max_of_min) { + if (current_igi < rssi_min) + return rssi_min; + } else { + if (current_igi < dig_max_of_min) + return dig_max_of_min; + } + return current_igi; +} + +void odm_change_dynamic_init_gain_thresh(void *dm_void, u32 dm_type, + u32 dm_value) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + + if (dm_type == DIG_TYPE_THRESH_HIGH) { + dig_tab->rssi_high_thresh = dm_value; + } else if (dm_type == DIG_TYPE_THRESH_LOW) { + dig_tab->rssi_low_thresh = dm_value; + } else if (dm_type == DIG_TYPE_ENABLE) { + dig_tab->dig_enable_flag = true; + } else if (dm_type == DIG_TYPE_DISABLE) { + dig_tab->dig_enable_flag = false; + } else if (dm_type == DIG_TYPE_BACKOFF) { + if (dm_value > 30) + dm_value = 30; + dig_tab->backoff_val = (u8)dm_value; + } else if (dm_type == DIG_TYPE_RX_GAIN_MIN) { + if (dm_value == 0) + dm_value = 0x1; + dig_tab->rx_gain_range_min = (u8)dm_value; + } else if (dm_type == DIG_TYPE_RX_GAIN_MAX) { + if (dm_value > 0x50) + dm_value = 0x50; + dig_tab->rx_gain_range_max = (u8)dm_value; + } +} /* dm_change_dynamic_init_gain_thresh */ + +static int get_igi_for_diff(int value_IGI) +{ +#define ONERCCA_LOW_TH 0x30 +#define ONERCCA_LOW_DIFF 8 + + if (value_IGI < ONERCCA_LOW_TH) { + if ((ONERCCA_LOW_TH - value_IGI) < ONERCCA_LOW_DIFF) + return ONERCCA_LOW_TH; + else + return value_IGI + ONERCCA_LOW_DIFF; + } + + return value_IGI; +} + +static void odm_fa_threshold_check(void *dm_void, bool is_dfs_band, + bool is_performance, u32 rx_tp, u32 tx_tp, + u32 *dm_FA_thres) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + + if (dm->is_linked && (is_performance || is_dfs_band)) { + /*For NIC*/ + dm_FA_thres[0] = DM_DIG_FA_TH0; + dm_FA_thres[1] = DM_DIG_FA_TH1; + dm_FA_thres[2] = DM_DIG_FA_TH2; + } else { + if (is_dfs_band) { + /* For DFS band and no link */ + dm_FA_thres[0] = 250; + dm_FA_thres[1] = 1000; + dm_FA_thres[2] = 2000; + } else { + dm_FA_thres[0] = 2000; + dm_FA_thres[1] = 4000; + dm_FA_thres[2] = 5000; + } + } +} + +static u8 odm_forbidden_igi_check(void *dm_void, u8 dig_dynamic_min, + u8 current_igi) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + struct false_alarm_stat *fa_cnt = + (struct false_alarm_stat *)phydm_get_structure( + dm, PHYDM_FALSEALMCNT); + u8 rx_gain_range_min = dig_tab->rx_gain_range_min; + + if (dig_tab->large_fa_timeout) { + if (--dig_tab->large_fa_timeout == 0) + dig_tab->large_fa_hit = 0; + } + + if (fa_cnt->cnt_all > 10000) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Abnormally false alarm case.\n", __func__); + + if (dig_tab->large_fa_hit != 3) + dig_tab->large_fa_hit++; + + if (dig_tab->forbidden_igi < current_igi) { + dig_tab->forbidden_igi = current_igi; + dig_tab->large_fa_hit = 1; + dig_tab->large_fa_timeout = LARGE_FA_TIMEOUT; + } + + if (dig_tab->large_fa_hit >= 3) { + if ((dig_tab->forbidden_igi + 2) > + dig_tab->rx_gain_range_max) + rx_gain_range_min = dig_tab->rx_gain_range_max; + else + rx_gain_range_min = + (dig_tab->forbidden_igi + 2); + dig_tab->recover_cnt = 1800; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): Abnormally false alarm case: recover_cnt = %d\n", + __func__, dig_tab->recover_cnt); + } + } + + else if (fa_cnt->cnt_all > 2000) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "Abnormally false alarm case.\n"); + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "cnt_all=%d, cnt_all_pre=%d, current_igi=0x%x, pre_ig_value=0x%x\n", + fa_cnt->cnt_all, fa_cnt->cnt_all_pre, current_igi, + dig_tab->pre_ig_value); + + /* fa_cnt->cnt_all = 1.1875*fa_cnt->cnt_all_pre */ + if ((fa_cnt->cnt_all > + (fa_cnt->cnt_all_pre + (fa_cnt->cnt_all_pre >> 3) + + (fa_cnt->cnt_all_pre >> 4))) && + current_igi < dig_tab->pre_ig_value) { + if (dig_tab->large_fa_hit != 3) + dig_tab->large_fa_hit++; + + if (dig_tab->forbidden_igi < current_igi) { + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "Updating forbidden_igi by current_igi, forbidden_igi=0x%x, current_igi=0x%x\n", + dig_tab->forbidden_igi, current_igi); + + dig_tab->forbidden_igi = current_igi; + dig_tab->large_fa_hit = 1; + dig_tab->large_fa_timeout = LARGE_FA_TIMEOUT; + } + } + + if (dig_tab->large_fa_hit >= 3) { + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "FaHit is greater than 3, rx_gain_range_max=0x%x, rx_gain_range_min=0x%x, forbidden_igi=0x%x\n", + dig_tab->rx_gain_range_max, rx_gain_range_min, + dig_tab->forbidden_igi); + + if ((dig_tab->forbidden_igi + 1) > + dig_tab->rx_gain_range_max) + rx_gain_range_min = dig_tab->rx_gain_range_max; + else + rx_gain_range_min = + (dig_tab->forbidden_igi + 1); + + dig_tab->recover_cnt = 1200; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "Abnormally false alarm case: recover_cnt = %d, rx_gain_range_min = 0x%x\n", + dig_tab->recover_cnt, rx_gain_range_min); + } + } else { + if (dig_tab->recover_cnt != 0) { + dig_tab->recover_cnt--; + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Normal Case: recover_cnt = %d\n", + __func__, dig_tab->recover_cnt); + return rx_gain_range_min; + } + + if (dig_tab->large_fa_hit >= 3) { + dig_tab->large_fa_hit = 0; + return rx_gain_range_min; + } + + if ((dig_tab->forbidden_igi - 2) < + dig_dynamic_min) { /* DM_DIG_MIN) */ + dig_tab->forbidden_igi = + dig_dynamic_min; /* DM_DIG_MIN; */ + rx_gain_range_min = dig_dynamic_min; /* DM_DIG_MIN; */ + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Normal Case: At Lower Bound\n", + __func__); + } else { + if (dig_tab->large_fa_hit == 0) { + dig_tab->forbidden_igi -= 2; + rx_gain_range_min = + (dig_tab->forbidden_igi + 2); + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): Normal Case: Approach Lower Bound\n", + __func__); + } + } + } + + return rx_gain_range_min; +} + +static void phydm_set_big_jump_step(void *dm_void, u8 current_igi) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + u8 step1[8] = {24, 30, 40, 50, 60, 70, 80, 90}; + u8 i; + + if (dig_tab->enable_adjust_big_jump == 0) + return; + + for (i = 0; i <= dig_tab->big_jump_step1; i++) { + if ((current_igi + step1[i]) > + dig_tab->big_jump_lmt[dig_tab->agc_table_idx]) { + if (i != 0) + i = i - 1; + break; + } else if (i == dig_tab->big_jump_step1) { + break; + } + } + if (dm->support_ic_type & ODM_RTL8822B) + odm_set_bb_reg(dm, 0x8c8, 0xe, i); + else if (dm->support_ic_type & ODM_RTL8197F) + odm_set_bb_reg(dm, ODM_REG_BB_AGC_SET_2_11N, 0xe, i); + + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): bigjump = %d (ori = 0x%x), LMT=0x%x\n", __func__, i, + dig_tab->big_jump_step1, + dig_tab->big_jump_lmt[dig_tab->agc_table_idx]); +} + +void odm_write_dig(void *dm_void, u8 current_igi) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + + if (dig_tab->is_stop_dig) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): Stop Writing IGI\n", + __func__); + return; + } + + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): ODM_REG(IGI_A,dm)=0x%x, ODM_BIT(IGI,dm)=0x%x\n", + __func__, ODM_REG(IGI_A, dm), ODM_BIT(IGI, dm)); + + /* 1 Check initial gain by upper bound */ + if (!dig_tab->is_psd_in_progress && dm->is_linked) { + if (current_igi > dig_tab->rx_gain_range_max) { + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): current_igi(0x%02x) is larger than upper bound !!\n", + __func__, current_igi); + current_igi = dig_tab->rx_gain_range_max; + } + if (dm->support_ability & ODM_BB_ADAPTIVITY && + dm->adaptivity_flag) { + if (current_igi > dm->adaptivity_igi_upper) + current_igi = dm->adaptivity_igi_upper; + + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): adaptivity case: Force upper bound to 0x%x !!!!!!\n", + __func__, current_igi); + } + } + + if (dig_tab->cur_ig_value != current_igi) { + /* Modify big jump step for 8822B and 8197F */ + if (dm->support_ic_type & (ODM_RTL8822B | ODM_RTL8197F)) + phydm_set_big_jump_step(dm, current_igi); + + /* Set IGI value of CCK for new CCK AGC */ + if (dm->cck_new_agc) { + if (dm->support_ic_type & ODM_IC_PHY_STATUE_NEW_TYPE) + odm_set_bb_reg(dm, 0xa0c, 0x00003f00, + (current_igi >> 1)); + } + + /*Add by YuChen for USB IO too slow issue*/ + if ((dm->support_ability & ODM_BB_ADAPTIVITY) && + current_igi > dig_tab->cur_ig_value) { + dig_tab->cur_ig_value = current_igi; + phydm_adaptivity(dm); + } + + /* 1 Set IGI value */ + if (dm->support_platform & (ODM_WIN | ODM_CE)) { + odm_set_bb_reg(dm, ODM_REG(IGI_A, dm), ODM_BIT(IGI, dm), + current_igi); + + if (dm->rf_type > ODM_1T1R) + odm_set_bb_reg(dm, ODM_REG(IGI_B, dm), + ODM_BIT(IGI, dm), current_igi); + + } else if (dm->support_platform & (ODM_AP)) { + phydm_check_ap_write_dig(dm, current_igi); + } + + dig_tab->cur_ig_value = current_igi; + } + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): current_igi(0x%02x).\n", __func__, + current_igi); +} + +void odm_pause_dig(void *dm_void, enum phydm_pause_type pause_type, + enum phydm_pause_level pause_level, u8 igi_value) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + s8 max_level; + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s()=========> level = %d\n", __func__, + pause_level); + + if (dig_tab->pause_dig_level == 0 && + (!(dm->support_ability & ODM_BB_DIG) || + !(dm->support_ability & ODM_BB_FA_CNT))) { + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): Return: support_ability DIG or FA is disabled !!\n", + __func__); + return; + } + + if (pause_level > DM_DIG_MAX_PAUSE_TYPE) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Return: Wrong pause level !!\n", __func__); + return; + } + + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): pause level = 0x%x, Current value = 0x%x\n", + __func__, dig_tab->pause_dig_level, igi_value); + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): pause value = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + __func__, dig_tab->pause_dig_value[7], + dig_tab->pause_dig_value[6], dig_tab->pause_dig_value[5], + dig_tab->pause_dig_value[4], dig_tab->pause_dig_value[3], + dig_tab->pause_dig_value[2], dig_tab->pause_dig_value[1], + dig_tab->pause_dig_value[0]); + + switch (pause_type) { + /* Pause DIG */ + case PHYDM_PAUSE: { + /* Disable DIG */ + odm_cmn_info_update(dm, ODM_CMNINFO_ABILITY, + dm->support_ability & (~ODM_BB_DIG)); + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): Pause DIG !!\n", + __func__); + + /* Backup IGI value */ + if (dig_tab->pause_dig_level == 0) { + dig_tab->igi_backup = dig_tab->cur_ig_value; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): Backup IGI = 0x%x, new IGI = 0x%x\n", + __func__, dig_tab->igi_backup, igi_value); + } + + /* Record IGI value */ + dig_tab->pause_dig_value[pause_level] = igi_value; + + /* Update pause level */ + dig_tab->pause_dig_level = + (dig_tab->pause_dig_level | BIT(pause_level)); + + /* Write new IGI value */ + if (BIT(pause_level + 1) > dig_tab->pause_dig_level) { + odm_write_dig(dm, igi_value); + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): IGI of higher level = 0x%x\n", + __func__, igi_value); + } + break; + } + /* Resume DIG */ + case PHYDM_RESUME: { + /* check if the level is illegal or not */ + if ((dig_tab->pause_dig_level & (BIT(pause_level))) != 0) { + dig_tab->pause_dig_level = dig_tab->pause_dig_level & + (~(BIT(pause_level))); + dig_tab->pause_dig_value[pause_level] = 0; + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): Resume DIG !!\n", + __func__); + } else { + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Wrong resume level !!\n", __func__); + break; + } + + /* Resume DIG */ + if (dig_tab->pause_dig_level == 0) { + /* Write backup IGI value */ + odm_write_dig(dm, dig_tab->igi_backup); + dig_tab->is_ignore_dig = true; + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Write original IGI = 0x%x\n", + __func__, dig_tab->igi_backup); + + /* Enable DIG */ + odm_cmn_info_update(dm, ODM_CMNINFO_ABILITY, + dm->support_ability | ODM_BB_DIG); + break; + } + + if (BIT(pause_level) <= dig_tab->pause_dig_level) + break; + + /* Calculate the maximum level now */ + for (max_level = (pause_level - 1); max_level >= 0; + max_level--) { + if ((dig_tab->pause_dig_level & BIT(max_level)) > 0) + break; + } + + /* pin max_level to be >= 0 */ + max_level = max_t(s8, 0, max_level); + /* write IGI of lower level */ + odm_write_dig(dm, dig_tab->pause_dig_value[max_level]); + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Write IGI (0x%x) of level (%d)\n", __func__, + dig_tab->pause_dig_value[max_level], max_level); + break; + } + default: + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): Wrong type !!\n", + __func__); + break; + } + + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): pause level = 0x%x, Current value = 0x%x\n", + __func__, dig_tab->pause_dig_level, igi_value); + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): pause value = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + __func__, dig_tab->pause_dig_value[7], + dig_tab->pause_dig_value[6], dig_tab->pause_dig_value[5], + dig_tab->pause_dig_value[4], dig_tab->pause_dig_value[3], + dig_tab->pause_dig_value[2], dig_tab->pause_dig_value[1], + dig_tab->pause_dig_value[0]); +} + +static bool odm_dig_abort(void *dm_void) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + + /* support_ability */ + if (!(dm->support_ability & ODM_BB_FA_CNT)) { + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): Return: support_ability ODM_BB_FA_CNT is disabled\n", + __func__); + return true; + } + + /* support_ability */ + if (!(dm->support_ability & ODM_BB_DIG)) { + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): Return: support_ability ODM_BB_DIG is disabled\n", + __func__); + return true; + } + + /* ScanInProcess */ + if (*dm->is_scan_in_process) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Return: In Scan Progress\n", __func__); + return true; + } + + if (dig_tab->is_ignore_dig) { + dig_tab->is_ignore_dig = false; + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): Return: Ignore DIG\n", + __func__); + return true; + } + + /* add by Neil Chen to avoid PSD is processing */ + if (!dm->is_dm_initial_gain_enable) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Return: PSD is Processing\n", __func__); + return true; + } + + return false; +} + +void odm_dig_init(void *dm_void) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + u32 ret_value; + u8 i; + + dig_tab->is_stop_dig = false; + dig_tab->is_ignore_dig = false; + dig_tab->is_psd_in_progress = false; + dig_tab->cur_ig_value = + (u8)odm_get_bb_reg(dm, ODM_REG(IGI_A, dm), ODM_BIT(IGI, dm)); + dig_tab->pre_ig_value = 0; + dig_tab->rssi_low_thresh = DM_DIG_THRESH_LOW; + dig_tab->rssi_high_thresh = DM_DIG_THRESH_HIGH; + dig_tab->fa_low_thresh = DM_FALSEALARM_THRESH_LOW; + dig_tab->fa_high_thresh = DM_FALSEALARM_THRESH_HIGH; + dig_tab->backoff_val = DM_DIG_BACKOFF_DEFAULT; + dig_tab->backoff_val_range_max = DM_DIG_BACKOFF_MAX; + dig_tab->backoff_val_range_min = DM_DIG_BACKOFF_MIN; + dig_tab->pre_cck_cca_thres = 0xFF; + dig_tab->cur_cck_cca_thres = 0x83; + dig_tab->forbidden_igi = DM_DIG_MIN_NIC; + dig_tab->large_fa_hit = 0; + dig_tab->large_fa_timeout = 0; + dig_tab->recover_cnt = 0; + dig_tab->is_media_connect_0 = false; + dig_tab->is_media_connect_1 = false; + + /*To initialize dm->is_dm_initial_gain_enable==false to avoid DIG err*/ + dm->is_dm_initial_gain_enable = true; + + dig_tab->dig_dynamic_min_0 = DM_DIG_MIN_NIC; + dig_tab->dig_dynamic_min_1 = DM_DIG_MIN_NIC; + + /* To Initi BT30 IGI */ + dig_tab->bt30_cur_igi = 0x32; + + odm_memory_set(dm, dig_tab->pause_dig_value, 0, + (DM_DIG_MAX_PAUSE_TYPE + 1)); + dig_tab->pause_dig_level = 0; + odm_memory_set(dm, dig_tab->pause_cckpd_value, 0, + (DM_DIG_MAX_PAUSE_TYPE + 1)); + dig_tab->pause_cckpd_level = 0; + + if (dm->board_type & (ODM_BOARD_EXT_PA | ODM_BOARD_EXT_LNA)) { + dig_tab->rx_gain_range_max = DM_DIG_MAX_NIC; + dig_tab->rx_gain_range_min = DM_DIG_MIN_NIC; + } else { + dig_tab->rx_gain_range_max = DM_DIG_MAX_NIC; + dig_tab->rx_gain_range_min = DM_DIG_MIN_NIC; + } + + dig_tab->enable_adjust_big_jump = 1; + if (dm->support_ic_type & ODM_RTL8822B) { + ret_value = odm_get_bb_reg(dm, 0x8c8, MASKLWORD); + dig_tab->big_jump_step1 = (u8)(ret_value & 0xe) >> 1; + dig_tab->big_jump_step2 = (u8)(ret_value & 0x30) >> 4; + dig_tab->big_jump_step3 = (u8)(ret_value & 0xc0) >> 6; + + } else if (dm->support_ic_type & ODM_RTL8197F) { + ret_value = + odm_get_bb_reg(dm, ODM_REG_BB_AGC_SET_2_11N, MASKLWORD); + dig_tab->big_jump_step1 = (u8)(ret_value & 0xe) >> 1; + dig_tab->big_jump_step2 = (u8)(ret_value & 0x30) >> 4; + dig_tab->big_jump_step3 = (u8)(ret_value & 0xc0) >> 6; + } + if (dm->support_ic_type & (ODM_RTL8822B | ODM_RTL8197F)) { + for (i = 0; i < sizeof(dig_tab->big_jump_lmt); i++) { + if (dig_tab->big_jump_lmt[i] == 0) + dig_tab->big_jump_lmt[i] = + 0x64; /* Set -10dBm as default value */ + } + } +} + +void odm_DIG(void *dm_void) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + + /* Common parameters */ + struct dig_thres *dig_tab = &dm->dm_dig_table; + struct false_alarm_stat *fa_cnt = + (struct false_alarm_stat *)phydm_get_structure( + dm, PHYDM_FALSEALMCNT); + bool first_connect, first_dis_connect; + u8 dig_max_of_min, dig_dynamic_min; + u8 dm_dig_max, dm_dig_min; + u8 current_igi = dig_tab->cur_ig_value; + u8 offset; + u32 dm_FA_thres[3]; + u32 tx_tp = 0, rx_tp = 0; + bool is_dfs_band = false; + bool is_performance = true, is_first_tp_target = false, + is_first_coverage = false; + + if (odm_dig_abort(dm)) + return; + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "DIG Start===>\n"); + + /* 1 Update status */ + { + dig_dynamic_min = dig_tab->dig_dynamic_min_0; + first_connect = (dm->is_linked) && !dig_tab->is_media_connect_0; + first_dis_connect = + (!dm->is_linked) && dig_tab->is_media_connect_0; + } + + /* 1 Boundary Decision */ + { + /* 2 For WIN\CE */ + if (dm->support_ic_type >= ODM_RTL8188E) + dm_dig_max = 0x5A; + else + dm_dig_max = DM_DIG_MAX_NIC; + + if (dm->support_ic_type != ODM_RTL8821) + dm_dig_min = DM_DIG_MIN_NIC; + else + dm_dig_min = 0x1C; + + dig_max_of_min = DM_DIG_MAX_AP; + + /* Modify lower bound for DFS band */ + if ((((*dm->channel >= 52) && (*dm->channel <= 64)) || + ((*dm->channel >= 100) && (*dm->channel <= 140))) && + phydm_dfs_master_enabled(dm)) { + is_dfs_band = true; + if (*dm->band_width == ODM_BW20M) + dm_dig_min = DM_DIG_MIN_AP_DFS + 2; + else + dm_dig_min = DM_DIG_MIN_AP_DFS; + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "DIG: ====== In DFS band ======\n"); + } + } + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "DIG: Absolutly upper bound = 0x%x, lower bound = 0x%x\n", + dm_dig_max, dm_dig_min); + + if (dm->pu1_forced_igi_lb && (*dm->pu1_forced_igi_lb > 0)) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, "DIG: Force IGI lb to: 0x%02x\n", + *dm->pu1_forced_igi_lb); + dm_dig_min = *dm->pu1_forced_igi_lb; + dm_dig_max = (dm_dig_min <= dm_dig_max) ? (dm_dig_max) : + (dm_dig_min + 1); + } + + /* 1 Adjust boundary by RSSI */ + if (dm->is_linked && is_performance) { + /* 2 Modify DIG upper bound */ + /* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */ + if ((dm->support_ic_type & (ODM_RTL8192E | ODM_RTL8723B | + ODM_RTL8812 | ODM_RTL8821)) && + dm->is_bt_limited_dig == 1) { + offset = 10; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: Coex. case: Force upper bound to RSSI + %d\n", + offset); + } else { + offset = 15; + } + + if ((dm->rssi_min + offset) > dm_dig_max) + dig_tab->rx_gain_range_max = dm_dig_max; + else if ((dm->rssi_min + offset) < dm_dig_min) + dig_tab->rx_gain_range_max = dm_dig_min; + else + dig_tab->rx_gain_range_max = dm->rssi_min + offset; + + /* 2 Modify DIG lower bound */ + /* if(dm->is_one_entry_only) */ + { + if (dm->rssi_min < dm_dig_min) + dig_dynamic_min = dm_dig_min; + else if (dm->rssi_min > dig_max_of_min) + dig_dynamic_min = dig_max_of_min; + else + dig_dynamic_min = dm->rssi_min; + + if (is_dfs_band) { + dig_dynamic_min = dm_dig_min; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: DFS band: Force lower bound to 0x%x after link\n", + dm_dig_min); + } + } + } else { + if (is_performance && is_dfs_band) { + dig_tab->rx_gain_range_max = 0x28; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: DFS band: Force upper bound to 0x%x before link\n", + dig_tab->rx_gain_range_max); + } else { + if (is_performance) + dig_tab->rx_gain_range_max = DM_DIG_MAX_OF_MIN; + else + dig_tab->rx_gain_range_max = dm_dig_max; + } + dig_dynamic_min = dm_dig_min; + } + + /* 1 Force Lower Bound for AntDiv */ + if (dm->is_linked && !dm->is_one_entry_only && + (dm->support_ic_type & ODM_ANTDIV_SUPPORT) && + (dm->support_ability & ODM_BB_ANT_DIV)) { + if (dm->ant_div_type == CG_TRX_HW_ANTDIV || + dm->ant_div_type == CG_TRX_SMART_ANTDIV) { + if (dig_tab->ant_div_rssi_max > dig_max_of_min) + dig_dynamic_min = dig_max_of_min; + else + dig_dynamic_min = (u8)dig_tab->ant_div_rssi_max; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: AntDiv case: Force lower bound to 0x%x\n", + dig_dynamic_min); + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "DIG: AntDiv case: rssi_max = 0x%x\n", + dig_tab->ant_div_rssi_max); + } + } + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: Adjust boundary by RSSI Upper bound = 0x%x, Lower bound = 0x%x\n", + dig_tab->rx_gain_range_max, dig_dynamic_min); + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: Link status: is_linked = %d, RSSI = %d, bFirstConnect = %d, bFirsrDisConnect = %d\n", + dm->is_linked, dm->rssi_min, first_connect, first_dis_connect); + + /* 1 Modify DIG lower bound, deal with abnormal case */ + /* 2 Abnormal false alarm case */ + if (is_dfs_band) { + dig_tab->rx_gain_range_min = dig_dynamic_min; + } else { + if (!dm->is_linked) { + dig_tab->rx_gain_range_min = dig_dynamic_min; + + if (first_dis_connect) + dig_tab->forbidden_igi = dig_dynamic_min; + } else { + dig_tab->rx_gain_range_min = odm_forbidden_igi_check( + dm, dig_dynamic_min, current_igi); + } + } + + /* 2 Abnormal # beacon case */ + if (dm->is_linked && !first_connect) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, "Beacon Num (%d)\n", + dm->phy_dbg_info.num_qry_beacon_pkt); + if (dm->phy_dbg_info.num_qry_beacon_pkt < 5 && + dm->bsta_state) { + dig_tab->rx_gain_range_min = 0x1c; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: Abnrormal #beacon (%d) case in STA mode: Force lower bound to 0x%x\n", + dm->phy_dbg_info.num_qry_beacon_pkt, + dig_tab->rx_gain_range_min); + } + } + + /* 2 Abnormal lower bound case */ + if (dig_tab->rx_gain_range_min > dig_tab->rx_gain_range_max) { + dig_tab->rx_gain_range_min = dig_tab->rx_gain_range_max; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: Abnrormal lower bound case: Force lower bound to 0x%x\n", + dig_tab->rx_gain_range_min); + } + + /* 1 False alarm threshold decision */ + odm_fa_threshold_check(dm, is_dfs_band, is_performance, rx_tp, tx_tp, + dm_FA_thres); + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "DIG: False alarm threshold = %d, %d, %d\n", + dm_FA_thres[0], dm_FA_thres[1], dm_FA_thres[2]); + + /* 1 Adjust initial gain by false alarm */ + if (dm->is_linked && is_performance) { + /* 2 After link */ + ODM_RT_TRACE(dm, ODM_COMP_DIG, "DIG: Adjust IGI after link\n"); + + if (is_first_tp_target || (first_connect && is_performance)) { + dig_tab->large_fa_hit = 0; + + if (is_dfs_band) { + u8 rssi = dm->rssi_min; + + current_igi = + (dm->rssi_min > 0x28) ? 0x28 : rssi; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: DFS band: One-shot to 0x28 upmost\n"); + } else { + current_igi = phydm_get_current_igi( + dig_max_of_min, dm->rssi_min, + current_igi); + } + + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: First connect case: IGI does on-shot to 0x%x\n", + current_igi); + + } else { + if (fa_cnt->cnt_all > dm_FA_thres[2]) + current_igi = current_igi + 4; + else if (fa_cnt->cnt_all > dm_FA_thres[1]) + current_igi = current_igi + 2; + else if (fa_cnt->cnt_all < dm_FA_thres[0]) + current_igi = current_igi - 2; + + /* 4 Abnormal # beacon case */ + if (dm->phy_dbg_info.num_qry_beacon_pkt < 5 && + fa_cnt->cnt_all < DM_DIG_FA_TH1 && + dm->bsta_state) { + current_igi = dig_tab->rx_gain_range_min; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: Abnormal #beacon (%d) case: IGI does one-shot to 0x%x\n", + dm->phy_dbg_info.num_qry_beacon_pkt, + current_igi); + } + } + } else { + /* 2 Before link */ + ODM_RT_TRACE(dm, ODM_COMP_DIG, "DIG: Adjust IGI before link\n"); + + if (first_dis_connect || is_first_coverage) { + current_igi = dm_dig_min; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "DIG: First disconnect case: IGI does on-shot to lower bound\n"); + } else { + if (fa_cnt->cnt_all > dm_FA_thres[2]) + current_igi = current_igi + 4; + else if (fa_cnt->cnt_all > dm_FA_thres[1]) + current_igi = current_igi + 2; + else if (fa_cnt->cnt_all < dm_FA_thres[0]) + current_igi = current_igi - 2; + } + } + + /* 1 Check initial gain by upper/lower bound */ + if (current_igi < dig_tab->rx_gain_range_min) + current_igi = dig_tab->rx_gain_range_min; + + if (current_igi > dig_tab->rx_gain_range_max) + current_igi = dig_tab->rx_gain_range_max; + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "DIG: cur_ig_value=0x%x, TotalFA = %d\n", + current_igi, fa_cnt->cnt_all); + + /* 1 Update status */ + if (dm->is_bt_hs_operation) { + if (dm->is_linked) { + if (dig_tab->bt30_cur_igi > (current_igi)) + odm_write_dig(dm, current_igi); + else + odm_write_dig(dm, dig_tab->bt30_cur_igi); + + dig_tab->is_media_connect_0 = dm->is_linked; + dig_tab->dig_dynamic_min_0 = dig_dynamic_min; + } else { + if (dm->is_link_in_process) + odm_write_dig(dm, 0x1c); + else if (dm->is_bt_connect_process) + odm_write_dig(dm, 0x28); + else + odm_write_dig(dm, dig_tab->bt30_cur_igi); + } + } else { /* BT is not using */ + odm_write_dig(dm, current_igi); + dig_tab->is_media_connect_0 = dm->is_linked; + dig_tab->dig_dynamic_min_0 = dig_dynamic_min; + } + ODM_RT_TRACE(dm, ODM_COMP_DIG, "DIG end\n"); +} + +void odm_dig_by_rssi_lps(void *dm_void) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct false_alarm_stat *fa_cnt = + (struct false_alarm_stat *)phydm_get_structure( + dm, PHYDM_FALSEALMCNT); + + u8 rssi_lower = DM_DIG_MIN_NIC; /* 0x1E or 0x1C */ + u8 current_igi = dm->rssi_min; + + if (odm_dig_abort(dm)) + return; + + current_igi = current_igi + RSSI_OFFSET_DIG; + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s()==>\n", __func__); + + /* Using FW PS mode to make IGI */ + /* Adjust by FA in LPS MODE */ + if (fa_cnt->cnt_all > DM_DIG_FA_TH2_LPS) + current_igi = current_igi + 4; + else if (fa_cnt->cnt_all > DM_DIG_FA_TH1_LPS) + current_igi = current_igi + 2; + else if (fa_cnt->cnt_all < DM_DIG_FA_TH0_LPS) + current_igi = current_igi - 2; + + /* Lower bound checking */ + + /* RSSI Lower bound check */ + if ((dm->rssi_min - 10) > DM_DIG_MIN_NIC) + rssi_lower = (dm->rssi_min - 10); + else + rssi_lower = DM_DIG_MIN_NIC; + + /* Upper and Lower Bound checking */ + if (current_igi > DM_DIG_MAX_NIC) + current_igi = DM_DIG_MAX_NIC; + else if (current_igi < rssi_lower) + current_igi = rssi_lower; + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): fa_cnt->cnt_all = %d\n", __func__, + fa_cnt->cnt_all); + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): dm->rssi_min = %d\n", __func__, + dm->rssi_min); + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): current_igi = 0x%x\n", __func__, + current_igi); + + odm_write_dig( + dm, + current_igi); /* odm_write_dig(dm, dig_tab->cur_ig_value); */ +} + +/* 3============================================================ + * 3 FASLE ALARM CHECK + * 3============================================================ + */ + +void odm_false_alarm_counter_statistics(void *dm_void) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct false_alarm_stat *false_alm_cnt = + (struct false_alarm_stat *)phydm_get_structure( + dm, PHYDM_FALSEALMCNT); + struct rt_adcsmp *adc_smp = &dm->adcsmp; + u32 ret_value; + + if (!(dm->support_ability & ODM_BB_FA_CNT)) + return; + + ODM_RT_TRACE(dm, ODM_COMP_FA_CNT, "%s()======>\n", __func__); + + if (dm->support_ic_type & ODM_IC_11N_SERIES) { + /* hold ofdm counter */ + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), + 1); /* hold page C counter */ + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), + 1); /* hold page D counter */ + + ret_value = odm_get_bb_reg(dm, ODM_REG_OFDM_FA_TYPE1_11N, + MASKDWORD); + false_alm_cnt->cnt_fast_fsync = (ret_value & 0xffff); + false_alm_cnt->cnt_sb_search_fail = + ((ret_value & 0xffff0000) >> 16); + + ret_value = odm_get_bb_reg(dm, ODM_REG_OFDM_FA_TYPE2_11N, + MASKDWORD); + false_alm_cnt->cnt_ofdm_cca = (ret_value & 0xffff); + false_alm_cnt->cnt_parity_fail = + ((ret_value & 0xffff0000) >> 16); + + ret_value = odm_get_bb_reg(dm, ODM_REG_OFDM_FA_TYPE3_11N, + MASKDWORD); + false_alm_cnt->cnt_rate_illegal = (ret_value & 0xffff); + false_alm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); + + ret_value = odm_get_bb_reg(dm, ODM_REG_OFDM_FA_TYPE4_11N, + MASKDWORD); + false_alm_cnt->cnt_mcs_fail = (ret_value & 0xffff); + + false_alm_cnt->cnt_ofdm_fail = + false_alm_cnt->cnt_parity_fail + + false_alm_cnt->cnt_rate_illegal + + false_alm_cnt->cnt_crc8_fail + + false_alm_cnt->cnt_mcs_fail + + false_alm_cnt->cnt_fast_fsync + + false_alm_cnt->cnt_sb_search_fail; + + /* read CCK CRC32 counter */ + false_alm_cnt->cnt_cck_crc32_error = odm_get_bb_reg( + dm, ODM_REG_CCK_CRC32_ERROR_CNT_11N, MASKDWORD); + false_alm_cnt->cnt_cck_crc32_ok = odm_get_bb_reg( + dm, ODM_REG_CCK_CRC32_OK_CNT_11N, MASKDWORD); + + /* read OFDM CRC32 counter */ + ret_value = odm_get_bb_reg(dm, ODM_REG_OFDM_CRC32_CNT_11N, + MASKDWORD); + false_alm_cnt->cnt_ofdm_crc32_error = + (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_ofdm_crc32_ok = ret_value & 0xffff; + + /* read HT CRC32 counter */ + ret_value = + odm_get_bb_reg(dm, ODM_REG_HT_CRC32_CNT_11N, MASKDWORD); + false_alm_cnt->cnt_ht_crc32_error = + (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_ht_crc32_ok = ret_value & 0xffff; + + /* read VHT CRC32 counter */ + false_alm_cnt->cnt_vht_crc32_error = 0; + false_alm_cnt->cnt_vht_crc32_ok = 0; + + { + /* hold cck counter */ + odm_set_bb_reg(dm, ODM_REG_CCK_FA_RST_11N, BIT(12), 1); + odm_set_bb_reg(dm, ODM_REG_CCK_FA_RST_11N, BIT(14), 1); + + ret_value = odm_get_bb_reg(dm, ODM_REG_CCK_FA_LSB_11N, + MASKBYTE0); + false_alm_cnt->cnt_cck_fail = ret_value; + + ret_value = odm_get_bb_reg(dm, ODM_REG_CCK_FA_MSB_11N, + MASKBYTE3); + false_alm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; + + ret_value = odm_get_bb_reg(dm, ODM_REG_CCK_CCA_CNT_11N, + MASKDWORD); + false_alm_cnt->cnt_cck_cca = + ((ret_value & 0xFF) << 8) | + ((ret_value & 0xFF00) >> 8); + } + + false_alm_cnt->cnt_all_pre = false_alm_cnt->cnt_all; + + false_alm_cnt->cnt_all = (false_alm_cnt->cnt_fast_fsync + + false_alm_cnt->cnt_sb_search_fail + + false_alm_cnt->cnt_parity_fail + + false_alm_cnt->cnt_rate_illegal + + false_alm_cnt->cnt_crc8_fail + + false_alm_cnt->cnt_mcs_fail + + false_alm_cnt->cnt_cck_fail); + + false_alm_cnt->cnt_cca_all = false_alm_cnt->cnt_ofdm_cca + + false_alm_cnt->cnt_cck_cca; + + if (dm->support_ic_type >= ODM_RTL8188E) { + /*reset false alarm counter registers*/ + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_RSTC_11N, BIT(31), + 1); + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_RSTC_11N, BIT(31), + 0); + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), + 1); + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_RSTD_11N, BIT(27), + 0); + + /*update ofdm counter*/ + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_HOLDC_11N, BIT(31), + 0); /*update page C counter*/ + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_RSTD_11N, BIT(31), + 0); /*update page D counter*/ + + /*reset CCK CCA counter*/ + odm_set_bb_reg(dm, ODM_REG_CCK_FA_RST_11N, + BIT(13) | BIT(12), 0); + odm_set_bb_reg(dm, ODM_REG_CCK_FA_RST_11N, + BIT(13) | BIT(12), 2); + + /*reset CCK FA counter*/ + odm_set_bb_reg(dm, ODM_REG_CCK_FA_RST_11N, + BIT(15) | BIT(14), 0); + odm_set_bb_reg(dm, ODM_REG_CCK_FA_RST_11N, + BIT(15) | BIT(14), 2); + + /*reset CRC32 counter*/ + odm_set_bb_reg(dm, ODM_REG_PAGE_F_RST_11N, BIT(16), 1); + odm_set_bb_reg(dm, ODM_REG_PAGE_F_RST_11N, BIT(16), 0); + } + + /* Get debug port 0 */ + odm_set_bb_reg(dm, ODM_REG_DBG_RPT_11N, MASKDWORD, 0x0); + false_alm_cnt->dbg_port0 = + odm_get_bb_reg(dm, ODM_REG_RPT_11N, MASKDWORD); + + /* Get EDCCA flag */ + odm_set_bb_reg(dm, ODM_REG_DBG_RPT_11N, MASKDWORD, 0x208); + false_alm_cnt->edcca_flag = + (bool)odm_get_bb_reg(dm, ODM_REG_RPT_11N, BIT(30)); + + ODM_RT_TRACE( + dm, ODM_COMP_FA_CNT, + "[OFDM FA Detail] Parity_Fail = (( %d )), Rate_Illegal = (( %d )), CRC8_fail = (( %d )), Mcs_fail = (( %d )), Fast_Fsync = (( %d )), SB_Search_fail = (( %d ))\n", + false_alm_cnt->cnt_parity_fail, + false_alm_cnt->cnt_rate_illegal, + false_alm_cnt->cnt_crc8_fail, + false_alm_cnt->cnt_mcs_fail, + false_alm_cnt->cnt_fast_fsync, + false_alm_cnt->cnt_sb_search_fail); + } + + if (dm->support_ic_type & ODM_IC_11AC_SERIES) { + u32 cck_enable; + + /* read OFDM FA counter */ + false_alm_cnt->cnt_ofdm_fail = + odm_get_bb_reg(dm, ODM_REG_OFDM_FA_11AC, MASKLWORD); + + /* Read CCK FA counter */ + false_alm_cnt->cnt_cck_fail = + odm_get_bb_reg(dm, ODM_REG_CCK_FA_11AC, MASKLWORD); + + /* read CCK/OFDM CCA counter */ + ret_value = + odm_get_bb_reg(dm, ODM_REG_CCK_CCA_CNT_11AC, MASKDWORD); + false_alm_cnt->cnt_ofdm_cca = (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_cck_cca = ret_value & 0xffff; + + /* read CCK CRC32 counter */ + ret_value = odm_get_bb_reg(dm, ODM_REG_CCK_CRC32_CNT_11AC, + MASKDWORD); + false_alm_cnt->cnt_cck_crc32_error = + (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_cck_crc32_ok = ret_value & 0xffff; + + /* read OFDM CRC32 counter */ + ret_value = odm_get_bb_reg(dm, ODM_REG_OFDM_CRC32_CNT_11AC, + MASKDWORD); + false_alm_cnt->cnt_ofdm_crc32_error = + (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_ofdm_crc32_ok = ret_value & 0xffff; + + /* read HT CRC32 counter */ + ret_value = odm_get_bb_reg(dm, ODM_REG_HT_CRC32_CNT_11AC, + MASKDWORD); + false_alm_cnt->cnt_ht_crc32_error = + (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_ht_crc32_ok = ret_value & 0xffff; + + /* read VHT CRC32 counter */ + ret_value = odm_get_bb_reg(dm, ODM_REG_VHT_CRC32_CNT_11AC, + MASKDWORD); + false_alm_cnt->cnt_vht_crc32_error = + (ret_value & 0xffff0000) >> 16; + false_alm_cnt->cnt_vht_crc32_ok = ret_value & 0xffff; + + /* reset OFDM FA counter */ + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1); + odm_set_bb_reg(dm, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0); + + /* reset CCK FA counter */ + odm_set_bb_reg(dm, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0); + odm_set_bb_reg(dm, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1); + + /* reset CCA counter */ + odm_set_bb_reg(dm, ODM_REG_RST_RPT_11AC, BIT(0), 1); + odm_set_bb_reg(dm, ODM_REG_RST_RPT_11AC, BIT(0), 0); + + cck_enable = + odm_get_bb_reg(dm, ODM_REG_BB_RX_PATH_11AC, BIT(28)); + if (cck_enable) { /* if(*dm->band_type == ODM_BAND_2_4G) */ + false_alm_cnt->cnt_all = false_alm_cnt->cnt_ofdm_fail + + false_alm_cnt->cnt_cck_fail; + false_alm_cnt->cnt_cca_all = + false_alm_cnt->cnt_cck_cca + + false_alm_cnt->cnt_ofdm_cca; + } else { + false_alm_cnt->cnt_all = false_alm_cnt->cnt_ofdm_fail; + false_alm_cnt->cnt_cca_all = + false_alm_cnt->cnt_ofdm_cca; + } + + if (adc_smp->adc_smp_state == ADCSMP_STATE_IDLE) { + if (phydm_set_bb_dbg_port( + dm, BB_DBGPORT_PRIORITY_1, + 0x0)) { /*set debug port to 0x0*/ + false_alm_cnt->dbg_port0 = + phydm_get_bb_dbg_port_value(dm); + phydm_release_bb_dbg_port(dm); + } + + if (phydm_set_bb_dbg_port( + dm, BB_DBGPORT_PRIORITY_1, + 0x209)) { /*set debug port to 0x0*/ + false_alm_cnt->edcca_flag = + (bool)((phydm_get_bb_dbg_port_value( + dm) & + BIT(30)) >> + 30); + phydm_release_bb_dbg_port(dm); + } + } + } + + false_alm_cnt->cnt_crc32_error_all = + false_alm_cnt->cnt_vht_crc32_error + + false_alm_cnt->cnt_ht_crc32_error + + false_alm_cnt->cnt_ofdm_crc32_error + + false_alm_cnt->cnt_cck_crc32_error; + false_alm_cnt->cnt_crc32_ok_all = false_alm_cnt->cnt_vht_crc32_ok + + false_alm_cnt->cnt_ht_crc32_ok + + false_alm_cnt->cnt_ofdm_crc32_ok + + false_alm_cnt->cnt_cck_crc32_ok; + + ODM_RT_TRACE(dm, ODM_COMP_FA_CNT, + "[CCA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n", + false_alm_cnt->cnt_cck_cca, false_alm_cnt->cnt_ofdm_cca, + false_alm_cnt->cnt_cca_all); + + ODM_RT_TRACE(dm, ODM_COMP_FA_CNT, + "[FA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n", + false_alm_cnt->cnt_cck_fail, false_alm_cnt->cnt_ofdm_fail, + false_alm_cnt->cnt_all); + + ODM_RT_TRACE(dm, ODM_COMP_FA_CNT, + "[CCK] CRC32 {error, ok}= {%d, %d}\n", + false_alm_cnt->cnt_cck_crc32_error, + false_alm_cnt->cnt_cck_crc32_ok); + ODM_RT_TRACE(dm, ODM_COMP_FA_CNT, "[OFDM]CRC32 {error, ok}= {%d, %d}\n", + false_alm_cnt->cnt_ofdm_crc32_error, + false_alm_cnt->cnt_ofdm_crc32_ok); + ODM_RT_TRACE(dm, ODM_COMP_FA_CNT, + "[ HT ] CRC32 {error, ok}= {%d, %d}\n", + false_alm_cnt->cnt_ht_crc32_error, + false_alm_cnt->cnt_ht_crc32_ok); + ODM_RT_TRACE(dm, ODM_COMP_FA_CNT, + "[VHT] CRC32 {error, ok}= {%d, %d}\n", + false_alm_cnt->cnt_vht_crc32_error, + false_alm_cnt->cnt_vht_crc32_ok); + ODM_RT_TRACE(dm, ODM_COMP_FA_CNT, + "[VHT] CRC32 {error, ok}= {%d, %d}\n", + false_alm_cnt->cnt_crc32_error_all, + false_alm_cnt->cnt_crc32_ok_all); + ODM_RT_TRACE(dm, ODM_COMP_FA_CNT, + "FA_Cnt: Dbg port 0x0 = 0x%x, EDCCA = %d\n\n", + false_alm_cnt->dbg_port0, false_alm_cnt->edcca_flag); +} + +/* 3============================================================ + * 3 CCK Packet Detect threshold + * 3============================================================ + */ + +void odm_pause_cck_packet_detection(void *dm_void, + enum phydm_pause_type pause_type, + enum phydm_pause_level pause_level, + u8 cck_pd_threshold) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + s8 max_level; + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s()=========> level = %d\n", __func__, + pause_level); + + if (dig_tab->pause_cckpd_level == 0 && + (!(dm->support_ability & ODM_BB_CCK_PD) || + !(dm->support_ability & ODM_BB_FA_CNT))) { + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "Return: support_ability ODM_BB_CCK_PD or ODM_BB_FA_CNT is disabled\n"); + return; + } + + if (pause_level > DM_DIG_MAX_PAUSE_TYPE) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Return: Wrong pause level !!\n", __func__); + return; + } + + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): pause level = 0x%x, Current value = 0x%x\n", + __func__, dig_tab->pause_cckpd_level, cck_pd_threshold); + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): pause value = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + __func__, dig_tab->pause_cckpd_value[7], + dig_tab->pause_cckpd_value[6], dig_tab->pause_cckpd_value[5], + dig_tab->pause_cckpd_value[4], dig_tab->pause_cckpd_value[3], + dig_tab->pause_cckpd_value[2], dig_tab->pause_cckpd_value[1], + dig_tab->pause_cckpd_value[0]); + + switch (pause_type) { + /* Pause CCK Packet Detection threshold */ + case PHYDM_PAUSE: { + /* Disable CCK PD */ + odm_cmn_info_update(dm, ODM_CMNINFO_ABILITY, + dm->support_ability & (~ODM_BB_CCK_PD)); + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Pause CCK packet detection threshold !!\n", + __func__); + + /*Backup original CCK PD threshold decided by CCK PD mechanism*/ + if (dig_tab->pause_cckpd_level == 0) { + dig_tab->cck_pd_backup = dig_tab->cur_cck_cca_thres; + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): Backup CCKPD = 0x%x, new CCKPD = 0x%x\n", + __func__, dig_tab->cck_pd_backup, + cck_pd_threshold); + } + + /* Update pause level */ + dig_tab->pause_cckpd_level = + (dig_tab->pause_cckpd_level | BIT(pause_level)); + + /* Record CCK PD threshold */ + dig_tab->pause_cckpd_value[pause_level] = cck_pd_threshold; + + /* Write new CCK PD threshold */ + if (BIT(pause_level + 1) > dig_tab->pause_cckpd_level) { + odm_write_cck_cca_thres(dm, cck_pd_threshold); + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): CCKPD of higher level = 0x%x\n", + __func__, cck_pd_threshold); + } + break; + } + /* Resume CCK Packet Detection threshold */ + case PHYDM_RESUME: { + /* check if the level is illegal or not */ + if ((dig_tab->pause_cckpd_level & (BIT(pause_level))) != 0) { + dig_tab->pause_cckpd_level = + dig_tab->pause_cckpd_level & + (~(BIT(pause_level))); + dig_tab->pause_cckpd_value[pause_level] = 0; + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Resume CCK PD !!\n", __func__); + } else { + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Wrong resume level !!\n", __func__); + break; + } + + /* Resume DIG */ + if (dig_tab->pause_cckpd_level == 0) { + /* Write backup IGI value */ + odm_write_cck_cca_thres(dm, dig_tab->cck_pd_backup); + /* dig_tab->is_ignore_dig = true; */ + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Write original CCKPD = 0x%x\n", + __func__, dig_tab->cck_pd_backup); + + /* Enable DIG */ + odm_cmn_info_update(dm, ODM_CMNINFO_ABILITY, + dm->support_ability | + ODM_BB_CCK_PD); + break; + } + + if (BIT(pause_level) <= dig_tab->pause_cckpd_level) + break; + + /* Calculate the maximum level now */ + for (max_level = (pause_level - 1); max_level >= 0; + max_level--) { + if ((dig_tab->pause_cckpd_level & BIT(max_level)) > 0) + break; + } + + /* write CCKPD of lower level */ + odm_write_cck_cca_thres(dm, + dig_tab->pause_cckpd_value[max_level]); + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): Write CCKPD (0x%x) of level (%d)\n", + __func__, dig_tab->pause_cckpd_value[max_level], + max_level); + break; + } + default: + ODM_RT_TRACE(dm, ODM_COMP_DIG, "%s(): Wrong type !!\n", + __func__); + break; + } + + ODM_RT_TRACE(dm, ODM_COMP_DIG, + "%s(): pause level = 0x%x, Current value = 0x%x\n", + __func__, dig_tab->pause_cckpd_level, cck_pd_threshold); + ODM_RT_TRACE( + dm, ODM_COMP_DIG, + "%s(): pause value = 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + __func__, dig_tab->pause_cckpd_value[7], + dig_tab->pause_cckpd_value[6], dig_tab->pause_cckpd_value[5], + dig_tab->pause_cckpd_value[4], dig_tab->pause_cckpd_value[3], + dig_tab->pause_cckpd_value[2], dig_tab->pause_cckpd_value[1], + dig_tab->pause_cckpd_value[0]); +} + +void odm_cck_packet_detection_thresh(void *dm_void) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + struct false_alarm_stat *false_alm_cnt = + (struct false_alarm_stat *)phydm_get_structure( + dm, PHYDM_FALSEALMCNT); + u8 cur_cck_cca_thres = dig_tab->cur_cck_cca_thres, rssi_thd = 35; + + if ((!(dm->support_ability & ODM_BB_CCK_PD)) || + (!(dm->support_ability & ODM_BB_FA_CNT))) { + ODM_RT_TRACE(dm, ODM_COMP_DIG, "CCK_PD: return==========\n"); + return; + } + + if (dm->ext_lna) + return; + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "CCK_PD: ==========>\n"); + + if (dig_tab->cck_fa_ma == 0xffffffff) + dig_tab->cck_fa_ma = false_alm_cnt->cnt_cck_fail; + else + dig_tab->cck_fa_ma = + ((dig_tab->cck_fa_ma << 1) + dig_tab->cck_fa_ma + + false_alm_cnt->cnt_cck_fail) >> + 2; + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "CCK_PD: CCK FA moving average = %d\n", + dig_tab->cck_fa_ma); + + if (dm->is_linked) { + if (dm->rssi_min > rssi_thd) { + cur_cck_cca_thres = 0xcd; + } else if (dm->rssi_min > 20) { + if (dig_tab->cck_fa_ma > + ((DM_DIG_FA_TH1 >> 1) + (DM_DIG_FA_TH1 >> 3))) + cur_cck_cca_thres = 0xcd; + else if (dig_tab->cck_fa_ma < (DM_DIG_FA_TH0 >> 1)) + cur_cck_cca_thres = 0x83; + } else if (dm->rssi_min > 7) { + cur_cck_cca_thres = 0x83; + } else { + cur_cck_cca_thres = 0x40; + } + + } else { + if (dig_tab->cck_fa_ma > 0x400) + cur_cck_cca_thres = 0x83; + else if (dig_tab->cck_fa_ma < 0x200) + cur_cck_cca_thres = 0x40; + } + + { + odm_write_cck_cca_thres(dm, cur_cck_cca_thres); + } + + ODM_RT_TRACE(dm, ODM_COMP_DIG, "CCK_PD: cck_cca_th=((0x%x))\n\n", + cur_cck_cca_thres); +} + +void odm_write_cck_cca_thres(void *dm_void, u8 cur_cck_cca_thres) +{ + struct phy_dm_struct *dm = (struct phy_dm_struct *)dm_void; + struct dig_thres *dig_tab = &dm->dm_dig_table; + + if (dig_tab->cur_cck_cca_thres != + cur_cck_cca_thres) { /* modify by Guo.Mingzhi 2012-01-03 */ + odm_write_1byte(dm, ODM_REG(CCK_CCA, dm), cur_cck_cca_thres); + dig_tab->cck_fa_ma = 0xffffffff; + } + dig_tab->pre_cck_cca_thres = dig_tab->cur_cck_cca_thres; + dig_tab->cur_cck_cca_thres = cur_cck_cca_thres; +} + +bool phydm_dig_go_up_check(void *dm_void) +{ + bool ret = true; + + return ret; +} |