summaryrefslogtreecommitdiff
path: root/drivers/staging/rtlwifi/phydm/phydm_dig.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rtlwifi/phydm/phydm_dig.c')
-rw-r--r--drivers/staging/rtlwifi/phydm/phydm_dig.c1526
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;
+}