162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 2009-2014  Realtek Corporation.*/
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include "../wifi.h"
562306a36Sopenharmony_ci#include "../base.h"
662306a36Sopenharmony_ci#include "../pci.h"
762306a36Sopenharmony_ci#include "../core.h"
862306a36Sopenharmony_ci#include "reg.h"
962306a36Sopenharmony_ci#include "def.h"
1062306a36Sopenharmony_ci#include "phy.h"
1162306a36Sopenharmony_ci#include "dm.h"
1262306a36Sopenharmony_ci#include "fw.h"
1362306a36Sopenharmony_ci#include "trx.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistatic void rtl92ee_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	u32 ret_value;
1862306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
1962306a36Sopenharmony_ci	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
2262306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD);
2562306a36Sopenharmony_ci	falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
2662306a36Sopenharmony_ci	falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD);
2962306a36Sopenharmony_ci	falsealm_cnt->cnt_ofdm_cca = (ret_value & 0xffff);
3062306a36Sopenharmony_ci	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD);
3362306a36Sopenharmony_ci	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
3462306a36Sopenharmony_ci	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD);
3762306a36Sopenharmony_ci	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
4062306a36Sopenharmony_ci				      falsealm_cnt->cnt_rate_illegal +
4162306a36Sopenharmony_ci				      falsealm_cnt->cnt_crc8_fail +
4262306a36Sopenharmony_ci				      falsealm_cnt->cnt_mcs_fail +
4362306a36Sopenharmony_ci				      falsealm_cnt->cnt_fast_fsync_fail +
4462306a36Sopenharmony_ci				      falsealm_cnt->cnt_sb_search_fail;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	ret_value = rtl_get_bbreg(hw, DM_REG_SC_CNT_11N, MASKDWORD);
4762306a36Sopenharmony_ci	falsealm_cnt->cnt_bw_lsc = (ret_value & 0xffff);
4862306a36Sopenharmony_ci	falsealm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1);
5162306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_LSB_11N, MASKBYTE0);
5462306a36Sopenharmony_ci	falsealm_cnt->cnt_cck_fail = ret_value;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3);
5762306a36Sopenharmony_ci	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD);
6062306a36Sopenharmony_ci	falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
6162306a36Sopenharmony_ci				    ((ret_value & 0xFF00) >> 8);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
6462306a36Sopenharmony_ci				falsealm_cnt->cnt_sb_search_fail +
6562306a36Sopenharmony_ci				falsealm_cnt->cnt_parity_fail +
6662306a36Sopenharmony_ci				falsealm_cnt->cnt_rate_illegal +
6762306a36Sopenharmony_ci				falsealm_cnt->cnt_crc8_fail +
6862306a36Sopenharmony_ci				falsealm_cnt->cnt_mcs_fail +
6962306a36Sopenharmony_ci				falsealm_cnt->cnt_cck_fail;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca +
7262306a36Sopenharmony_ci				    falsealm_cnt->cnt_cck_cca;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	/*reset false alarm counter registers*/
7562306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
7662306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
7762306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
7862306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
7962306a36Sopenharmony_ci	/*update ofdm counter*/
8062306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
8162306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
8262306a36Sopenharmony_ci	/*reset CCK CCA counter*/
8362306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
8462306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
8562306a36Sopenharmony_ci	/*reset CCK FA counter*/
8662306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
8762306a36Sopenharmony_ci	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
9062306a36Sopenharmony_ci		"cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
9162306a36Sopenharmony_ci		falsealm_cnt->cnt_parity_fail,
9262306a36Sopenharmony_ci		falsealm_cnt->cnt_rate_illegal,
9362306a36Sopenharmony_ci		falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
9662306a36Sopenharmony_ci		"cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
9762306a36Sopenharmony_ci		falsealm_cnt->cnt_ofdm_fail,
9862306a36Sopenharmony_ci		falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic void rtl92ee_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
10462306a36Sopenharmony_ci	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
10562306a36Sopenharmony_ci	u8 cur_cck_cca_thresh;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
10862306a36Sopenharmony_ci		if (dm_dig->rssi_val_min > 25) {
10962306a36Sopenharmony_ci			cur_cck_cca_thresh = 0xcd;
11062306a36Sopenharmony_ci		} else if ((dm_dig->rssi_val_min <= 25) &&
11162306a36Sopenharmony_ci			   (dm_dig->rssi_val_min > 10)) {
11262306a36Sopenharmony_ci			cur_cck_cca_thresh = 0x83;
11362306a36Sopenharmony_ci		} else {
11462306a36Sopenharmony_ci			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
11562306a36Sopenharmony_ci				cur_cck_cca_thresh = 0x83;
11662306a36Sopenharmony_ci			else
11762306a36Sopenharmony_ci				cur_cck_cca_thresh = 0x40;
11862306a36Sopenharmony_ci		}
11962306a36Sopenharmony_ci	} else {
12062306a36Sopenharmony_ci		if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
12162306a36Sopenharmony_ci			cur_cck_cca_thresh = 0x83;
12262306a36Sopenharmony_ci		else
12362306a36Sopenharmony_ci			cur_cck_cca_thresh = 0x40;
12462306a36Sopenharmony_ci	}
12562306a36Sopenharmony_ci	rtl92ee_dm_write_cck_cca_thres(hw, cur_cck_cca_thresh);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic void rtl92ee_dm_dig(struct ieee80211_hw *hw)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
13162306a36Sopenharmony_ci	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
13262306a36Sopenharmony_ci	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
13362306a36Sopenharmony_ci	u8 dig_min_0, dig_maxofmin;
13462306a36Sopenharmony_ci	bool bfirstconnect , bfirstdisconnect;
13562306a36Sopenharmony_ci	u8 dm_dig_max, dm_dig_min;
13662306a36Sopenharmony_ci	u8 current_igi = dm_dig->cur_igvalue;
13762306a36Sopenharmony_ci	u8 offset;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	/* AP,BT */
14062306a36Sopenharmony_ci	if (mac->act_scanning)
14162306a36Sopenharmony_ci		return;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	dig_min_0 = dm_dig->dig_min_0;
14462306a36Sopenharmony_ci	bfirstconnect = (mac->link_state >= MAC80211_LINKED) &&
14562306a36Sopenharmony_ci			!dm_dig->media_connect_0;
14662306a36Sopenharmony_ci	bfirstdisconnect = (mac->link_state < MAC80211_LINKED) &&
14762306a36Sopenharmony_ci			   dm_dig->media_connect_0;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	dm_dig_max = 0x5a;
15062306a36Sopenharmony_ci	dm_dig_min = DM_DIG_MIN;
15162306a36Sopenharmony_ci	dig_maxofmin = DM_DIG_MAX_AP;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (mac->link_state >= MAC80211_LINKED) {
15462306a36Sopenharmony_ci		if ((dm_dig->rssi_val_min + 10) > dm_dig_max)
15562306a36Sopenharmony_ci			dm_dig->rx_gain_max = dm_dig_max;
15662306a36Sopenharmony_ci		else if ((dm_dig->rssi_val_min + 10) < dm_dig_min)
15762306a36Sopenharmony_ci			dm_dig->rx_gain_max = dm_dig_min;
15862306a36Sopenharmony_ci		else
15962306a36Sopenharmony_ci			dm_dig->rx_gain_max = dm_dig->rssi_val_min + 10;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci		if (rtlpriv->dm.one_entry_only) {
16262306a36Sopenharmony_ci			offset = 0;
16362306a36Sopenharmony_ci			if (dm_dig->rssi_val_min - offset < dm_dig_min)
16462306a36Sopenharmony_ci				dig_min_0 = dm_dig_min;
16562306a36Sopenharmony_ci			else if (dm_dig->rssi_val_min - offset >
16662306a36Sopenharmony_ci				 dig_maxofmin)
16762306a36Sopenharmony_ci				dig_min_0 = dig_maxofmin;
16862306a36Sopenharmony_ci			else
16962306a36Sopenharmony_ci				dig_min_0 = dm_dig->rssi_val_min - offset;
17062306a36Sopenharmony_ci		} else {
17162306a36Sopenharmony_ci			dig_min_0 = dm_dig_min;
17262306a36Sopenharmony_ci		}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	} else {
17562306a36Sopenharmony_ci		dm_dig->rx_gain_max = dm_dig_max;
17662306a36Sopenharmony_ci		dig_min_0 = dm_dig_min;
17762306a36Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
17862306a36Sopenharmony_ci	}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
18162306a36Sopenharmony_ci		if (dm_dig->large_fa_hit != 3)
18262306a36Sopenharmony_ci			dm_dig->large_fa_hit++;
18362306a36Sopenharmony_ci		if (dm_dig->forbidden_igi < current_igi) {
18462306a36Sopenharmony_ci			dm_dig->forbidden_igi = current_igi;
18562306a36Sopenharmony_ci			dm_dig->large_fa_hit = 1;
18662306a36Sopenharmony_ci		}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci		if (dm_dig->large_fa_hit >= 3) {
18962306a36Sopenharmony_ci			if (dm_dig->forbidden_igi + 1 > dm_dig->rx_gain_max)
19062306a36Sopenharmony_ci				dm_dig->rx_gain_min =
19162306a36Sopenharmony_ci						dm_dig->rx_gain_max;
19262306a36Sopenharmony_ci			else
19362306a36Sopenharmony_ci				dm_dig->rx_gain_min =
19462306a36Sopenharmony_ci						dm_dig->forbidden_igi + 1;
19562306a36Sopenharmony_ci			dm_dig->recover_cnt = 3600;
19662306a36Sopenharmony_ci		}
19762306a36Sopenharmony_ci	} else {
19862306a36Sopenharmony_ci		if (dm_dig->recover_cnt != 0) {
19962306a36Sopenharmony_ci			dm_dig->recover_cnt--;
20062306a36Sopenharmony_ci		} else {
20162306a36Sopenharmony_ci			if (dm_dig->large_fa_hit < 3) {
20262306a36Sopenharmony_ci				if ((dm_dig->forbidden_igi - 1) <
20362306a36Sopenharmony_ci				    dig_min_0) {
20462306a36Sopenharmony_ci					dm_dig->forbidden_igi = dig_min_0;
20562306a36Sopenharmony_ci					dm_dig->rx_gain_min =
20662306a36Sopenharmony_ci								dig_min_0;
20762306a36Sopenharmony_ci				} else {
20862306a36Sopenharmony_ci					dm_dig->forbidden_igi--;
20962306a36Sopenharmony_ci					dm_dig->rx_gain_min =
21062306a36Sopenharmony_ci						dm_dig->forbidden_igi + 1;
21162306a36Sopenharmony_ci				}
21262306a36Sopenharmony_ci			} else {
21362306a36Sopenharmony_ci				dm_dig->large_fa_hit = 0;
21462306a36Sopenharmony_ci			}
21562306a36Sopenharmony_ci		}
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 5)
21962306a36Sopenharmony_ci		dm_dig->rx_gain_min = dm_dig_min;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	if (dm_dig->rx_gain_min > dm_dig->rx_gain_max)
22262306a36Sopenharmony_ci		dm_dig->rx_gain_min = dm_dig->rx_gain_max;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	if (mac->link_state >= MAC80211_LINKED) {
22562306a36Sopenharmony_ci		if (bfirstconnect) {
22662306a36Sopenharmony_ci			if (dm_dig->rssi_val_min <= dig_maxofmin)
22762306a36Sopenharmony_ci				current_igi = dm_dig->rssi_val_min;
22862306a36Sopenharmony_ci			else
22962306a36Sopenharmony_ci				current_igi = dig_maxofmin;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci			dm_dig->large_fa_hit = 0;
23262306a36Sopenharmony_ci		} else {
23362306a36Sopenharmony_ci			if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
23462306a36Sopenharmony_ci				current_igi += 4;
23562306a36Sopenharmony_ci			else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
23662306a36Sopenharmony_ci				current_igi += 2;
23762306a36Sopenharmony_ci			else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
23862306a36Sopenharmony_ci				current_igi -= 2;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci			if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 5 &&
24162306a36Sopenharmony_ci			    rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
24262306a36Sopenharmony_ci				current_igi = dm_dig->rx_gain_min;
24362306a36Sopenharmony_ci		}
24462306a36Sopenharmony_ci	} else {
24562306a36Sopenharmony_ci		if (bfirstdisconnect) {
24662306a36Sopenharmony_ci			current_igi = dm_dig->rx_gain_min;
24762306a36Sopenharmony_ci		} else {
24862306a36Sopenharmony_ci			if (rtlpriv->falsealm_cnt.cnt_all > 10000)
24962306a36Sopenharmony_ci				current_igi += 4;
25062306a36Sopenharmony_ci			else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
25162306a36Sopenharmony_ci				current_igi += 2;
25262306a36Sopenharmony_ci			else if (rtlpriv->falsealm_cnt.cnt_all < 500)
25362306a36Sopenharmony_ci				current_igi -= 2;
25462306a36Sopenharmony_ci		}
25562306a36Sopenharmony_ci	}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	if (current_igi > dm_dig->rx_gain_max)
25862306a36Sopenharmony_ci		current_igi = dm_dig->rx_gain_max;
25962306a36Sopenharmony_ci	if (current_igi < dm_dig->rx_gain_min)
26062306a36Sopenharmony_ci		current_igi = dm_dig->rx_gain_min;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	rtl92ee_dm_write_dig(hw , current_igi);
26362306a36Sopenharmony_ci	dm_dig->media_connect_0 = ((mac->link_state >= MAC80211_LINKED) ?
26462306a36Sopenharmony_ci				   true : false);
26562306a36Sopenharmony_ci	dm_dig->dig_min_0 = dig_min_0;
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_civoid rtl92ee_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 cur_thres)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
27162306a36Sopenharmony_ci	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	if (dm_dig->cur_cck_cca_thres != cur_thres)
27462306a36Sopenharmony_ci		rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11N, cur_thres);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres;
27762306a36Sopenharmony_ci	dm_dig->cur_cck_cca_thres = cur_thres;
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_civoid rtl92ee_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
28362306a36Sopenharmony_ci	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	if (dm_dig->stop_dig)
28662306a36Sopenharmony_ci		return;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	if (dm_dig->cur_igvalue != current_igi) {
28962306a36Sopenharmony_ci		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi);
29062306a36Sopenharmony_ci		if (rtlpriv->phy.rf_type != RF_1T1R)
29162306a36Sopenharmony_ci			rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, current_igi);
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci	dm_dig->pre_igvalue = dm_dig->cur_igvalue;
29462306a36Sopenharmony_ci	dm_dig->cur_igvalue = current_igi;
29562306a36Sopenharmony_ci}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistatic void rtl92ee_rssi_dump_to_register(struct ieee80211_hw *hw)
29862306a36Sopenharmony_ci{
29962306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	rtl_write_byte(rtlpriv, RA_RSSIDUMP,
30262306a36Sopenharmony_ci		       rtlpriv->stats.rx_rssi_percentage[0]);
30362306a36Sopenharmony_ci	rtl_write_byte(rtlpriv, RB_RSSIDUMP,
30462306a36Sopenharmony_ci		       rtlpriv->stats.rx_rssi_percentage[1]);
30562306a36Sopenharmony_ci	/*It seems the following values are not initialized.
30662306a36Sopenharmony_ci	  *According to Windows code,
30762306a36Sopenharmony_ci	  *these value will only be valid with JAGUAR chips
30862306a36Sopenharmony_ci	  */
30962306a36Sopenharmony_ci	/* Rx EVM */
31062306a36Sopenharmony_ci	rtl_write_byte(rtlpriv, RS1_RXEVMDUMP, rtlpriv->stats.rx_evm_dbm[0]);
31162306a36Sopenharmony_ci	rtl_write_byte(rtlpriv, RS2_RXEVMDUMP, rtlpriv->stats.rx_evm_dbm[1]);
31262306a36Sopenharmony_ci	/* Rx SNR */
31362306a36Sopenharmony_ci	rtl_write_byte(rtlpriv, RA_RXSNRDUMP,
31462306a36Sopenharmony_ci		       (u8)(rtlpriv->stats.rx_snr_db[0]));
31562306a36Sopenharmony_ci	rtl_write_byte(rtlpriv, RB_RXSNRDUMP,
31662306a36Sopenharmony_ci		       (u8)(rtlpriv->stats.rx_snr_db[1]));
31762306a36Sopenharmony_ci	/* Rx Cfo_Short */
31862306a36Sopenharmony_ci	rtl_write_word(rtlpriv, RA_CFOSHORTDUMP,
31962306a36Sopenharmony_ci		       rtlpriv->stats.rx_cfo_short[0]);
32062306a36Sopenharmony_ci	rtl_write_word(rtlpriv, RB_CFOSHORTDUMP,
32162306a36Sopenharmony_ci		       rtlpriv->stats.rx_cfo_short[1]);
32262306a36Sopenharmony_ci	/* Rx Cfo_Tail */
32362306a36Sopenharmony_ci	rtl_write_word(rtlpriv, RA_CFOLONGDUMP, rtlpriv->stats.rx_cfo_tail[0]);
32462306a36Sopenharmony_ci	rtl_write_word(rtlpriv, RB_CFOLONGDUMP, rtlpriv->stats.rx_cfo_tail[1]);
32562306a36Sopenharmony_ci}
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic void rtl92ee_dm_find_minimum_rssi(struct ieee80211_hw *hw)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
33062306a36Sopenharmony_ci	struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
33162306a36Sopenharmony_ci	struct rtl_mac *mac = rtl_mac(rtlpriv);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/* Determine the minimum RSSI  */
33462306a36Sopenharmony_ci	if ((mac->link_state < MAC80211_LINKED) &&
33562306a36Sopenharmony_ci	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
33662306a36Sopenharmony_ci		rtl_dm_dig->min_undec_pwdb_for_dm = 0;
33762306a36Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
33862306a36Sopenharmony_ci			"Not connected to any\n");
33962306a36Sopenharmony_ci	}
34062306a36Sopenharmony_ci	if (mac->link_state >= MAC80211_LINKED) {
34162306a36Sopenharmony_ci		if (mac->opmode == NL80211_IFTYPE_AP ||
34262306a36Sopenharmony_ci		    mac->opmode == NL80211_IFTYPE_ADHOC) {
34362306a36Sopenharmony_ci			rtl_dm_dig->min_undec_pwdb_for_dm =
34462306a36Sopenharmony_ci				rtlpriv->dm.entry_min_undec_sm_pwdb;
34562306a36Sopenharmony_ci			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
34662306a36Sopenharmony_ci				"AP Client PWDB = 0x%lx\n",
34762306a36Sopenharmony_ci				rtlpriv->dm.entry_min_undec_sm_pwdb);
34862306a36Sopenharmony_ci		} else {
34962306a36Sopenharmony_ci			rtl_dm_dig->min_undec_pwdb_for_dm =
35062306a36Sopenharmony_ci			    rtlpriv->dm.undec_sm_pwdb;
35162306a36Sopenharmony_ci			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
35262306a36Sopenharmony_ci				"STA Default Port PWDB = 0x%x\n",
35362306a36Sopenharmony_ci				rtl_dm_dig->min_undec_pwdb_for_dm);
35462306a36Sopenharmony_ci		}
35562306a36Sopenharmony_ci	} else {
35662306a36Sopenharmony_ci		rtl_dm_dig->min_undec_pwdb_for_dm =
35762306a36Sopenharmony_ci			rtlpriv->dm.entry_min_undec_sm_pwdb;
35862306a36Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
35962306a36Sopenharmony_ci			"AP Ext Port or disconnect PWDB = 0x%x\n",
36062306a36Sopenharmony_ci			rtl_dm_dig->min_undec_pwdb_for_dm);
36162306a36Sopenharmony_ci	}
36262306a36Sopenharmony_ci	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
36362306a36Sopenharmony_ci		"MinUndecoratedPWDBForDM =%d\n",
36462306a36Sopenharmony_ci		rtl_dm_dig->min_undec_pwdb_for_dm);
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic void rtl92ee_dm_check_rssi_monitor(struct ieee80211_hw *hw)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
37062306a36Sopenharmony_ci	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
37162306a36Sopenharmony_ci	struct rtl_mac *mac = rtl_mac(rtlpriv);
37262306a36Sopenharmony_ci	struct rtl_dm *dm = rtl_dm(rtlpriv);
37362306a36Sopenharmony_ci	struct rtl_sta_info *drv_priv;
37462306a36Sopenharmony_ci	u8 h2c[4] = { 0 };
37562306a36Sopenharmony_ci	long max = 0, min = 0xff;
37662306a36Sopenharmony_ci	u8 i = 0;
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	if (mac->opmode == NL80211_IFTYPE_AP ||
37962306a36Sopenharmony_ci	    mac->opmode == NL80211_IFTYPE_ADHOC ||
38062306a36Sopenharmony_ci	    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
38162306a36Sopenharmony_ci		/* AP & ADHOC & MESH */
38262306a36Sopenharmony_ci		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
38362306a36Sopenharmony_ci		list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
38462306a36Sopenharmony_ci			struct rssi_sta *stat = &drv_priv->rssi_stat;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci			if (stat->undec_sm_pwdb < min)
38762306a36Sopenharmony_ci				min = stat->undec_sm_pwdb;
38862306a36Sopenharmony_ci			if (stat->undec_sm_pwdb > max)
38962306a36Sopenharmony_ci				max = stat->undec_sm_pwdb;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci			h2c[3] = 0;
39262306a36Sopenharmony_ci			h2c[2] = (u8)(dm->undec_sm_pwdb & 0xFF);
39362306a36Sopenharmony_ci			h2c[1] = 0x20;
39462306a36Sopenharmony_ci			h2c[0] = ++i;
39562306a36Sopenharmony_ci			rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSSI_REPORT, 4, h2c);
39662306a36Sopenharmony_ci		}
39762306a36Sopenharmony_ci		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci		/* If associated entry is found */
40062306a36Sopenharmony_ci		if (max != 0) {
40162306a36Sopenharmony_ci			dm->entry_max_undec_sm_pwdb = max;
40262306a36Sopenharmony_ci			RTPRINT(rtlpriv, FDM, DM_PWDB,
40362306a36Sopenharmony_ci				"EntryMaxPWDB = 0x%lx(%ld)\n", max, max);
40462306a36Sopenharmony_ci		} else {
40562306a36Sopenharmony_ci			dm->entry_max_undec_sm_pwdb = 0;
40662306a36Sopenharmony_ci		}
40762306a36Sopenharmony_ci		/* If associated entry is found */
40862306a36Sopenharmony_ci		if (min != 0xff) {
40962306a36Sopenharmony_ci			dm->entry_min_undec_sm_pwdb = min;
41062306a36Sopenharmony_ci			RTPRINT(rtlpriv, FDM, DM_PWDB,
41162306a36Sopenharmony_ci				"EntryMinPWDB = 0x%lx(%ld)\n", min, min);
41262306a36Sopenharmony_ci		} else {
41362306a36Sopenharmony_ci			dm->entry_min_undec_sm_pwdb = 0;
41462306a36Sopenharmony_ci		}
41562306a36Sopenharmony_ci	}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	/* Indicate Rx signal strength to FW. */
41862306a36Sopenharmony_ci	if (dm->useramask) {
41962306a36Sopenharmony_ci		h2c[3] = 0;
42062306a36Sopenharmony_ci		h2c[2] = (u8)(dm->undec_sm_pwdb & 0xFF);
42162306a36Sopenharmony_ci		h2c[1] = 0x20;
42262306a36Sopenharmony_ci		h2c[0] = 0;
42362306a36Sopenharmony_ci		rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSSI_REPORT, 4, h2c);
42462306a36Sopenharmony_ci	} else {
42562306a36Sopenharmony_ci		rtl_write_byte(rtlpriv, 0x4fe, dm->undec_sm_pwdb);
42662306a36Sopenharmony_ci	}
42762306a36Sopenharmony_ci	rtl92ee_rssi_dump_to_register(hw);
42862306a36Sopenharmony_ci	rtl92ee_dm_find_minimum_rssi(hw);
42962306a36Sopenharmony_ci	dm_dig->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
43062306a36Sopenharmony_ci}
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_cistatic void rtl92ee_dm_init_primary_cca_check(struct ieee80211_hw *hw)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
43562306a36Sopenharmony_ci	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
43662306a36Sopenharmony_ci	struct dynamic_primary_cca *primarycca = &rtlpriv->primarycca;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	rtlhal->rts_en = 0;
43962306a36Sopenharmony_ci	primarycca->dup_rts_flag = 0;
44062306a36Sopenharmony_ci	primarycca->intf_flag = 0;
44162306a36Sopenharmony_ci	primarycca->intf_type = 0;
44262306a36Sopenharmony_ci	primarycca->monitor_flag = 0;
44362306a36Sopenharmony_ci	primarycca->ch_offset = 0;
44462306a36Sopenharmony_ci	primarycca->mf_state = 0;
44562306a36Sopenharmony_ci}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_cistatic bool rtl92ee_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
44862306a36Sopenharmony_ci{
44962306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
45262306a36Sopenharmony_ci		return true;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	return false;
45562306a36Sopenharmony_ci}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_civoid rtl92ee_dm_init_edca_turbo(struct ieee80211_hw *hw)
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	rtlpriv->dm.current_turbo_edca = false;
46262306a36Sopenharmony_ci	rtlpriv->dm.is_cur_rdlstate = false;
46362306a36Sopenharmony_ci	rtlpriv->dm.is_any_nonbepkts = false;
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_cistatic void rtl92ee_dm_check_edca_turbo(struct ieee80211_hw *hw)
46762306a36Sopenharmony_ci{
46862306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	static u64 last_txok_cnt;
47162306a36Sopenharmony_ci	static u64 last_rxok_cnt;
47262306a36Sopenharmony_ci	u64 cur_txok_cnt = 0;
47362306a36Sopenharmony_ci	u64 cur_rxok_cnt = 0;
47462306a36Sopenharmony_ci	u32 edca_be_ul = 0x5ea42b;
47562306a36Sopenharmony_ci	u32 edca_be_dl = 0x5ea42b; /*not sure*/
47662306a36Sopenharmony_ci	u32 edca_be = 0x5ea42b;
47762306a36Sopenharmony_ci	bool is_cur_rdlstate;
47862306a36Sopenharmony_ci	bool b_edca_turbo_on = false;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100)
48162306a36Sopenharmony_ci		rtlpriv->dm.is_any_nonbepkts = true;
48262306a36Sopenharmony_ci	rtlpriv->dm.dbginfo.num_non_be_pkt = 0;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
48562306a36Sopenharmony_ci	cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	/*b_bias_on_rx = false;*/
48862306a36Sopenharmony_ci	b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
48962306a36Sopenharmony_ci			   (!rtlpriv->dm.disable_framebursting)) ?
49062306a36Sopenharmony_ci			  true : false;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	if (rtl92ee_dm_is_edca_turbo_disable(hw))
49362306a36Sopenharmony_ci		goto check_exit;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	if (b_edca_turbo_on) {
49662306a36Sopenharmony_ci		is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
49762306a36Sopenharmony_ci				    true : false;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci		edca_be = is_cur_rdlstate ? edca_be_dl : edca_be_ul;
50062306a36Sopenharmony_ci		rtl_write_dword(rtlpriv , REG_EDCA_BE_PARAM , edca_be);
50162306a36Sopenharmony_ci		rtlpriv->dm.is_cur_rdlstate = is_cur_rdlstate;
50262306a36Sopenharmony_ci		rtlpriv->dm.current_turbo_edca = true;
50362306a36Sopenharmony_ci	} else {
50462306a36Sopenharmony_ci		if (rtlpriv->dm.current_turbo_edca) {
50562306a36Sopenharmony_ci			u8 tmp = AC0_BE;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
50862306a36Sopenharmony_ci						      (u8 *)(&tmp));
50962306a36Sopenharmony_ci		}
51062306a36Sopenharmony_ci		rtlpriv->dm.current_turbo_edca = false;
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_cicheck_exit:
51462306a36Sopenharmony_ci	rtlpriv->dm.is_any_nonbepkts = false;
51562306a36Sopenharmony_ci	last_txok_cnt = rtlpriv->stats.txbytesunicast;
51662306a36Sopenharmony_ci	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
51762306a36Sopenharmony_ci}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_cistatic void rtl92ee_dm_dynamic_edcca(struct ieee80211_hw *hw)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
52262306a36Sopenharmony_ci	u8 reg_c50 , reg_c58;
52362306a36Sopenharmony_ci	bool fw_current_in_ps_mode = false;
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
52662306a36Sopenharmony_ci				      (u8 *)(&fw_current_in_ps_mode));
52762306a36Sopenharmony_ci	if (fw_current_in_ps_mode)
52862306a36Sopenharmony_ci		return;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
53162306a36Sopenharmony_ci	reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	if (reg_c50 > 0x28 && reg_c58 > 0x28) {
53462306a36Sopenharmony_ci		if (!rtlpriv->rtlhal.pre_edcca_enable) {
53562306a36Sopenharmony_ci			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
53662306a36Sopenharmony_ci			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
53762306a36Sopenharmony_ci			rtlpriv->rtlhal.pre_edcca_enable = true;
53862306a36Sopenharmony_ci		}
53962306a36Sopenharmony_ci	} else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
54062306a36Sopenharmony_ci		if (rtlpriv->rtlhal.pre_edcca_enable) {
54162306a36Sopenharmony_ci			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
54262306a36Sopenharmony_ci			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
54362306a36Sopenharmony_ci			rtlpriv->rtlhal.pre_edcca_enable = false;
54462306a36Sopenharmony_ci		}
54562306a36Sopenharmony_ci	}
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_cistatic void rtl92ee_dm_adaptivity(struct ieee80211_hw *hw)
54962306a36Sopenharmony_ci{
55062306a36Sopenharmony_ci	rtl92ee_dm_dynamic_edcca(hw);
55162306a36Sopenharmony_ci}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_cistatic void rtl92ee_dm_write_dynamic_cca(struct ieee80211_hw *hw,
55462306a36Sopenharmony_ci					 u8 cur_mf_state)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	struct dynamic_primary_cca *primarycca = &rtl_priv(hw)->primarycca;
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	if (primarycca->mf_state != cur_mf_state)
55962306a36Sopenharmony_ci		rtl_set_bbreg(hw, DM_REG_L1SBD_PD_CH_11N, BIT(8) | BIT(7),
56062306a36Sopenharmony_ci			      cur_mf_state);
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	primarycca->mf_state = cur_mf_state;
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_cistatic void rtl92ee_dm_dynamic_primary_cca_ckeck(struct ieee80211_hw *hw)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
56862306a36Sopenharmony_ci	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
56962306a36Sopenharmony_ci	struct dynamic_primary_cca *primarycca = &rtlpriv->primarycca;
57062306a36Sopenharmony_ci	bool is40mhz = false;
57162306a36Sopenharmony_ci	u64 ofdm_cca, ofdm_fa, bw_usc_cnt, bw_lsc_cnt;
57262306a36Sopenharmony_ci	u8 sec_ch_offset;
57362306a36Sopenharmony_ci	u8 cur_mf_state;
57462306a36Sopenharmony_ci	static u8 count_down = MONITOR_TIME;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	ofdm_cca = falsealm_cnt->cnt_ofdm_cca;
57762306a36Sopenharmony_ci	ofdm_fa = falsealm_cnt->cnt_ofdm_fail;
57862306a36Sopenharmony_ci	bw_usc_cnt = falsealm_cnt->cnt_bw_usc;
57962306a36Sopenharmony_ci	bw_lsc_cnt = falsealm_cnt->cnt_bw_lsc;
58062306a36Sopenharmony_ci	is40mhz = rtlpriv->mac80211.bw_40;
58162306a36Sopenharmony_ci	sec_ch_offset = rtlpriv->mac80211.cur_40_prime_sc;
58262306a36Sopenharmony_ci	/* NIC: 2: sec is below,  1: sec is above */
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) {
58562306a36Sopenharmony_ci		cur_mf_state = MF_USC_LSC;
58662306a36Sopenharmony_ci		rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
58762306a36Sopenharmony_ci		return;
58862306a36Sopenharmony_ci	}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	if (rtlpriv->mac80211.link_state < MAC80211_LINKED)
59162306a36Sopenharmony_ci		return;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	if (is40mhz)
59462306a36Sopenharmony_ci		return;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	if (primarycca->pricca_flag == 0) {
59762306a36Sopenharmony_ci		/* Primary channel is above
59862306a36Sopenharmony_ci		 * NOTE: duplicate CTS can remove this condition
59962306a36Sopenharmony_ci		 */
60062306a36Sopenharmony_ci		if (sec_ch_offset == 2) {
60162306a36Sopenharmony_ci			if ((ofdm_cca > OFDMCCA_TH) &&
60262306a36Sopenharmony_ci			    (bw_lsc_cnt > (bw_usc_cnt + BW_IND_BIAS)) &&
60362306a36Sopenharmony_ci			    (ofdm_fa > (ofdm_cca >> 1))) {
60462306a36Sopenharmony_ci				primarycca->intf_type = 1;
60562306a36Sopenharmony_ci				primarycca->intf_flag = 1;
60662306a36Sopenharmony_ci				cur_mf_state = MF_USC;
60762306a36Sopenharmony_ci				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
60862306a36Sopenharmony_ci				primarycca->pricca_flag = 1;
60962306a36Sopenharmony_ci			} else if ((ofdm_cca > OFDMCCA_TH) &&
61062306a36Sopenharmony_ci				   (bw_lsc_cnt > (bw_usc_cnt + BW_IND_BIAS)) &&
61162306a36Sopenharmony_ci				   (ofdm_fa < (ofdm_cca >> 1))) {
61262306a36Sopenharmony_ci				primarycca->intf_type = 2;
61362306a36Sopenharmony_ci				primarycca->intf_flag = 1;
61462306a36Sopenharmony_ci				cur_mf_state = MF_USC;
61562306a36Sopenharmony_ci				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
61662306a36Sopenharmony_ci				primarycca->pricca_flag = 1;
61762306a36Sopenharmony_ci				primarycca->dup_rts_flag = 1;
61862306a36Sopenharmony_ci				rtlpriv->rtlhal.rts_en = 1;
61962306a36Sopenharmony_ci			} else {
62062306a36Sopenharmony_ci				primarycca->intf_type = 0;
62162306a36Sopenharmony_ci				primarycca->intf_flag = 0;
62262306a36Sopenharmony_ci				cur_mf_state = MF_USC_LSC;
62362306a36Sopenharmony_ci				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
62462306a36Sopenharmony_ci				rtlpriv->rtlhal.rts_en = 0;
62562306a36Sopenharmony_ci				primarycca->dup_rts_flag = 0;
62662306a36Sopenharmony_ci			}
62762306a36Sopenharmony_ci		} else if (sec_ch_offset == 1) {
62862306a36Sopenharmony_ci			if ((ofdm_cca > OFDMCCA_TH) &&
62962306a36Sopenharmony_ci			    (bw_usc_cnt > (bw_lsc_cnt + BW_IND_BIAS)) &&
63062306a36Sopenharmony_ci			    (ofdm_fa > (ofdm_cca >> 1))) {
63162306a36Sopenharmony_ci				primarycca->intf_type = 1;
63262306a36Sopenharmony_ci				primarycca->intf_flag = 1;
63362306a36Sopenharmony_ci				cur_mf_state = MF_LSC;
63462306a36Sopenharmony_ci				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
63562306a36Sopenharmony_ci				primarycca->pricca_flag = 1;
63662306a36Sopenharmony_ci			} else if ((ofdm_cca > OFDMCCA_TH) &&
63762306a36Sopenharmony_ci				   (bw_usc_cnt > (bw_lsc_cnt + BW_IND_BIAS)) &&
63862306a36Sopenharmony_ci				   (ofdm_fa < (ofdm_cca >> 1))) {
63962306a36Sopenharmony_ci				primarycca->intf_type = 2;
64062306a36Sopenharmony_ci				primarycca->intf_flag = 1;
64162306a36Sopenharmony_ci				cur_mf_state = MF_LSC;
64262306a36Sopenharmony_ci				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
64362306a36Sopenharmony_ci				primarycca->pricca_flag = 1;
64462306a36Sopenharmony_ci				primarycca->dup_rts_flag = 1;
64562306a36Sopenharmony_ci				rtlpriv->rtlhal.rts_en = 1;
64662306a36Sopenharmony_ci			} else {
64762306a36Sopenharmony_ci				primarycca->intf_type = 0;
64862306a36Sopenharmony_ci				primarycca->intf_flag = 0;
64962306a36Sopenharmony_ci				cur_mf_state = MF_USC_LSC;
65062306a36Sopenharmony_ci				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
65162306a36Sopenharmony_ci				rtlpriv->rtlhal.rts_en = 0;
65262306a36Sopenharmony_ci				primarycca->dup_rts_flag = 0;
65362306a36Sopenharmony_ci			}
65462306a36Sopenharmony_ci		}
65562306a36Sopenharmony_ci	} else {/* PrimaryCCA->PriCCA_flag==1 */
65662306a36Sopenharmony_ci		count_down--;
65762306a36Sopenharmony_ci		if (count_down == 0) {
65862306a36Sopenharmony_ci			count_down = MONITOR_TIME;
65962306a36Sopenharmony_ci			primarycca->pricca_flag = 0;
66062306a36Sopenharmony_ci			cur_mf_state = MF_USC_LSC;
66162306a36Sopenharmony_ci			/* default */
66262306a36Sopenharmony_ci			rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
66362306a36Sopenharmony_ci			rtlpriv->rtlhal.rts_en = 0;
66462306a36Sopenharmony_ci			primarycca->dup_rts_flag = 0;
66562306a36Sopenharmony_ci			primarycca->intf_type = 0;
66662306a36Sopenharmony_ci			primarycca->intf_flag = 0;
66762306a36Sopenharmony_ci		}
66862306a36Sopenharmony_ci	}
66962306a36Sopenharmony_ci}
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_cistatic void rtl92ee_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
67262306a36Sopenharmony_ci{
67362306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
67462306a36Sopenharmony_ci	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
67562306a36Sopenharmony_ci	u8 crystal_cap;
67662306a36Sopenharmony_ci	u32 packet_count;
67762306a36Sopenharmony_ci	int cfo_khz_a , cfo_khz_b , cfo_ave = 0, adjust_xtal = 0;
67862306a36Sopenharmony_ci	int cfo_ave_diff;
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
68162306a36Sopenharmony_ci		if (rtldm->atc_status == ATC_STATUS_OFF) {
68262306a36Sopenharmony_ci			rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
68362306a36Sopenharmony_ci				      ATC_STATUS_ON);
68462306a36Sopenharmony_ci			rtldm->atc_status = ATC_STATUS_ON;
68562306a36Sopenharmony_ci		}
68662306a36Sopenharmony_ci		/* Disable CFO tracking for BT */
68762306a36Sopenharmony_ci		if (rtlpriv->cfg->ops->get_btc_status()) {
68862306a36Sopenharmony_ci			if (!rtlpriv->btcoexist.btc_ops->
68962306a36Sopenharmony_ci			    btc_is_bt_disabled(rtlpriv)) {
69062306a36Sopenharmony_ci				rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
69162306a36Sopenharmony_ci					"odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n");
69262306a36Sopenharmony_ci				return;
69362306a36Sopenharmony_ci			}
69462306a36Sopenharmony_ci		}
69562306a36Sopenharmony_ci		/* Reset Crystal Cap */
69662306a36Sopenharmony_ci		if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
69762306a36Sopenharmony_ci			rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
69862306a36Sopenharmony_ci			crystal_cap = rtldm->crystal_cap & 0x3f;
69962306a36Sopenharmony_ci			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
70062306a36Sopenharmony_ci				      (crystal_cap | (crystal_cap << 6)));
70162306a36Sopenharmony_ci		}
70262306a36Sopenharmony_ci	} else {
70362306a36Sopenharmony_ci		cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
70462306a36Sopenharmony_ci		cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
70562306a36Sopenharmony_ci		packet_count = rtldm->packet_count;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci		if (packet_count == rtldm->packet_count_pre)
70862306a36Sopenharmony_ci			return;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci		rtldm->packet_count_pre = packet_count;
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci		if (rtlpriv->phy.rf_type == RF_1T1R)
71362306a36Sopenharmony_ci			cfo_ave = cfo_khz_a;
71462306a36Sopenharmony_ci		else
71562306a36Sopenharmony_ci			cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci		cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
71862306a36Sopenharmony_ci			       (rtldm->cfo_ave_pre - cfo_ave) :
71962306a36Sopenharmony_ci			       (cfo_ave - rtldm->cfo_ave_pre);
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci		if (cfo_ave_diff > 20 && !rtldm->large_cfo_hit) {
72262306a36Sopenharmony_ci			rtldm->large_cfo_hit = true;
72362306a36Sopenharmony_ci			return;
72462306a36Sopenharmony_ci		}
72562306a36Sopenharmony_ci		rtldm->large_cfo_hit = false;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci		rtldm->cfo_ave_pre = cfo_ave;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci		if (cfo_ave >= -rtldm->cfo_threshold &&
73062306a36Sopenharmony_ci		    cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
73162306a36Sopenharmony_ci			if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
73262306a36Sopenharmony_ci				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
73362306a36Sopenharmony_ci				rtldm->is_freeze = 1;
73462306a36Sopenharmony_ci			} else {
73562306a36Sopenharmony_ci				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
73662306a36Sopenharmony_ci			}
73762306a36Sopenharmony_ci		}
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci		if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
74062306a36Sopenharmony_ci			adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1;
74162306a36Sopenharmony_ci		else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
74262306a36Sopenharmony_ci			 rtlpriv->dm.crystal_cap > 0)
74362306a36Sopenharmony_ci			adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1;
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci		if (adjust_xtal != 0) {
74662306a36Sopenharmony_ci			rtldm->is_freeze = 0;
74762306a36Sopenharmony_ci			rtldm->crystal_cap += adjust_xtal;
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci			if (rtldm->crystal_cap > 0x3f)
75062306a36Sopenharmony_ci				rtldm->crystal_cap = 0x3f;
75162306a36Sopenharmony_ci			else if (rtldm->crystal_cap < 0)
75262306a36Sopenharmony_ci				rtldm->crystal_cap = 0;
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_ci			crystal_cap = rtldm->crystal_cap & 0x3f;
75562306a36Sopenharmony_ci			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
75662306a36Sopenharmony_ci				      (crystal_cap | (crystal_cap << 6)));
75762306a36Sopenharmony_ci		}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci		if (cfo_ave < CFO_THRESHOLD_ATC &&
76062306a36Sopenharmony_ci		    cfo_ave > -CFO_THRESHOLD_ATC) {
76162306a36Sopenharmony_ci			if (rtldm->atc_status == ATC_STATUS_ON) {
76262306a36Sopenharmony_ci				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
76362306a36Sopenharmony_ci					      ATC_STATUS_OFF);
76462306a36Sopenharmony_ci				rtldm->atc_status = ATC_STATUS_OFF;
76562306a36Sopenharmony_ci			}
76662306a36Sopenharmony_ci		} else {
76762306a36Sopenharmony_ci			if (rtldm->atc_status == ATC_STATUS_OFF) {
76862306a36Sopenharmony_ci				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
76962306a36Sopenharmony_ci					      ATC_STATUS_ON);
77062306a36Sopenharmony_ci				rtldm->atc_status = ATC_STATUS_ON;
77162306a36Sopenharmony_ci			}
77262306a36Sopenharmony_ci		}
77362306a36Sopenharmony_ci	}
77462306a36Sopenharmony_ci}
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_cistatic void rtl92ee_dm_init_txpower_tracking(struct ieee80211_hw *hw)
77762306a36Sopenharmony_ci{
77862306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
77962306a36Sopenharmony_ci	struct rtl_dm *dm = rtl_dm(rtlpriv);
78062306a36Sopenharmony_ci	u8 path;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	dm->txpower_tracking = true;
78362306a36Sopenharmony_ci	dm->default_ofdm_index = 30;
78462306a36Sopenharmony_ci	dm->default_cck_index = 20;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	dm->swing_idx_cck_base = dm->default_cck_index;
78762306a36Sopenharmony_ci	dm->cck_index = dm->default_cck_index;
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	for (path = RF90_PATH_A; path < MAX_RF_PATH; path++) {
79062306a36Sopenharmony_ci		dm->swing_idx_ofdm_base[path] = dm->default_ofdm_index;
79162306a36Sopenharmony_ci		dm->ofdm_index[path] = dm->default_ofdm_index;
79262306a36Sopenharmony_ci		dm->delta_power_index[path] = 0;
79362306a36Sopenharmony_ci		dm->delta_power_index_last[path] = 0;
79462306a36Sopenharmony_ci		dm->power_index_offset[path] = 0;
79562306a36Sopenharmony_ci	}
79662306a36Sopenharmony_ci}
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_civoid rtl92ee_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
79962306a36Sopenharmony_ci{
80062306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
80162306a36Sopenharmony_ci	struct rate_adaptive *p_ra = &rtlpriv->ra;
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	p_ra->ratr_state = DM_RATR_STA_INIT;
80462306a36Sopenharmony_ci	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
80762306a36Sopenharmony_ci		rtlpriv->dm.useramask = true;
80862306a36Sopenharmony_ci	else
80962306a36Sopenharmony_ci		rtlpriv->dm.useramask = false;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	p_ra->ldpc_thres = 35;
81262306a36Sopenharmony_ci	p_ra->use_ldpc = false;
81362306a36Sopenharmony_ci	p_ra->high_rssi_thresh_for_ra = 50;
81462306a36Sopenharmony_ci	p_ra->low_rssi_thresh_for_ra40m = 20;
81562306a36Sopenharmony_ci}
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_cistatic bool _rtl92ee_dm_ra_state_check(struct ieee80211_hw *hw,
81862306a36Sopenharmony_ci				       s32 rssi, u8 *ratr_state)
81962306a36Sopenharmony_ci{
82062306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
82162306a36Sopenharmony_ci	struct rate_adaptive *p_ra = &rtlpriv->ra;
82262306a36Sopenharmony_ci	const u8 go_up_gap = 5;
82362306a36Sopenharmony_ci	u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
82462306a36Sopenharmony_ci	u32 low_rssithresh_for_ra = p_ra->low_rssi_thresh_for_ra40m;
82562306a36Sopenharmony_ci	u8 state;
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	/* Threshold Adjustment:
82862306a36Sopenharmony_ci	 * when RSSI state trends to go up one or two levels,
82962306a36Sopenharmony_ci	 * make sure RSSI is high enough.
83062306a36Sopenharmony_ci	 * Here GoUpGap is added to solve
83162306a36Sopenharmony_ci	 * the boundary's level alternation issue.
83262306a36Sopenharmony_ci	 */
83362306a36Sopenharmony_ci	switch (*ratr_state) {
83462306a36Sopenharmony_ci	case DM_RATR_STA_INIT:
83562306a36Sopenharmony_ci	case DM_RATR_STA_HIGH:
83662306a36Sopenharmony_ci		break;
83762306a36Sopenharmony_ci	case DM_RATR_STA_MIDDLE:
83862306a36Sopenharmony_ci		high_rssithresh_for_ra += go_up_gap;
83962306a36Sopenharmony_ci		break;
84062306a36Sopenharmony_ci	case DM_RATR_STA_LOW:
84162306a36Sopenharmony_ci		high_rssithresh_for_ra += go_up_gap;
84262306a36Sopenharmony_ci		low_rssithresh_for_ra += go_up_gap;
84362306a36Sopenharmony_ci		break;
84462306a36Sopenharmony_ci	default:
84562306a36Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_RATR, DBG_DMESG,
84662306a36Sopenharmony_ci			"wrong rssi level setting %d !\n", *ratr_state);
84762306a36Sopenharmony_ci		break;
84862306a36Sopenharmony_ci	}
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci	/* Decide RATRState by RSSI. */
85162306a36Sopenharmony_ci	if (rssi > high_rssithresh_for_ra)
85262306a36Sopenharmony_ci		state = DM_RATR_STA_HIGH;
85362306a36Sopenharmony_ci	else if (rssi > low_rssithresh_for_ra)
85462306a36Sopenharmony_ci		state = DM_RATR_STA_MIDDLE;
85562306a36Sopenharmony_ci	else
85662306a36Sopenharmony_ci		state = DM_RATR_STA_LOW;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	if (*ratr_state != state) {
85962306a36Sopenharmony_ci		*ratr_state = state;
86062306a36Sopenharmony_ci		return true;
86162306a36Sopenharmony_ci	}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	return false;
86462306a36Sopenharmony_ci}
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_cistatic void rtl92ee_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
86762306a36Sopenharmony_ci{
86862306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
86962306a36Sopenharmony_ci	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
87062306a36Sopenharmony_ci	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
87162306a36Sopenharmony_ci	struct rate_adaptive *p_ra = &rtlpriv->ra;
87262306a36Sopenharmony_ci	struct ieee80211_sta *sta = NULL;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	if (is_hal_stop(rtlhal)) {
87562306a36Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
87662306a36Sopenharmony_ci			"driver is going to unload\n");
87762306a36Sopenharmony_ci		return;
87862306a36Sopenharmony_ci	}
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	if (!rtlpriv->dm.useramask) {
88162306a36Sopenharmony_ci		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
88262306a36Sopenharmony_ci			"driver does not control rate adaptive mask\n");
88362306a36Sopenharmony_ci		return;
88462306a36Sopenharmony_ci	}
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	if (mac->link_state == MAC80211_LINKED &&
88762306a36Sopenharmony_ci	    mac->opmode == NL80211_IFTYPE_STATION) {
88862306a36Sopenharmony_ci		if (rtlpriv->dm.undec_sm_pwdb < p_ra->ldpc_thres) {
88962306a36Sopenharmony_ci			p_ra->use_ldpc = true;
89062306a36Sopenharmony_ci			p_ra->lower_rts_rate = true;
89162306a36Sopenharmony_ci		} else if (rtlpriv->dm.undec_sm_pwdb >
89262306a36Sopenharmony_ci			   (p_ra->ldpc_thres - 5)) {
89362306a36Sopenharmony_ci			p_ra->use_ldpc = false;
89462306a36Sopenharmony_ci			p_ra->lower_rts_rate = false;
89562306a36Sopenharmony_ci		}
89662306a36Sopenharmony_ci		if (_rtl92ee_dm_ra_state_check(hw, rtlpriv->dm.undec_sm_pwdb,
89762306a36Sopenharmony_ci					       &p_ra->ratr_state)) {
89862306a36Sopenharmony_ci			rcu_read_lock();
89962306a36Sopenharmony_ci			sta = rtl_find_sta(hw, mac->bssid);
90062306a36Sopenharmony_ci			if (sta)
90162306a36Sopenharmony_ci				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
90262306a36Sopenharmony_ci							      p_ra->ratr_state,
90362306a36Sopenharmony_ci							      true);
90462306a36Sopenharmony_ci			rcu_read_unlock();
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci			p_ra->pre_ratr_state = p_ra->ratr_state;
90762306a36Sopenharmony_ci		}
90862306a36Sopenharmony_ci	}
90962306a36Sopenharmony_ci}
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_cistatic void rtl92ee_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
91262306a36Sopenharmony_ci{
91362306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11));
91862306a36Sopenharmony_ci	rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
91962306a36Sopenharmony_ci}
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_civoid rtl92ee_dm_init(struct ieee80211_hw *hw)
92262306a36Sopenharmony_ci{
92362306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
92462306a36Sopenharmony_ci	u32 cur_igvalue = rtl_get_bbreg(hw, DM_REG_IGI_A_11N, DM_BIT_IGI_11N);
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	rtl_dm_diginit(hw, cur_igvalue);
92962306a36Sopenharmony_ci	rtl92ee_dm_init_rate_adaptive_mask(hw);
93062306a36Sopenharmony_ci	rtl92ee_dm_init_primary_cca_check(hw);
93162306a36Sopenharmony_ci	rtl92ee_dm_init_edca_turbo(hw);
93262306a36Sopenharmony_ci	rtl92ee_dm_init_txpower_tracking(hw);
93362306a36Sopenharmony_ci	rtl92ee_dm_init_dynamic_atc_switch(hw);
93462306a36Sopenharmony_ci}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_cistatic void rtl92ee_dm_common_info_self_update(struct ieee80211_hw *hw)
93762306a36Sopenharmony_ci{
93862306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
93962306a36Sopenharmony_ci	struct rtl_sta_info *drv_priv;
94062306a36Sopenharmony_ci	u8 cnt = 0;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	rtlpriv->dm.one_entry_only = false;
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
94562306a36Sopenharmony_ci	    rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
94662306a36Sopenharmony_ci		rtlpriv->dm.one_entry_only = true;
94762306a36Sopenharmony_ci		return;
94862306a36Sopenharmony_ci	}
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
95162306a36Sopenharmony_ci	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
95262306a36Sopenharmony_ci	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
95362306a36Sopenharmony_ci		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
95462306a36Sopenharmony_ci		list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
95562306a36Sopenharmony_ci			cnt++;
95662306a36Sopenharmony_ci		}
95762306a36Sopenharmony_ci		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci		if (cnt == 1)
96062306a36Sopenharmony_ci			rtlpriv->dm.one_entry_only = true;
96162306a36Sopenharmony_ci	}
96262306a36Sopenharmony_ci}
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_civoid rtl92ee_dm_dynamic_arfb_select(struct ieee80211_hw *hw,
96562306a36Sopenharmony_ci				    u8 rate, bool collision_state)
96662306a36Sopenharmony_ci{
96762306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci	if (rate >= DESC92C_RATEMCS8  && rate <= DESC92C_RATEMCS12) {
97062306a36Sopenharmony_ci		if (collision_state == 1) {
97162306a36Sopenharmony_ci			if (rate == DESC92C_RATEMCS12) {
97262306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
97362306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
97462306a36Sopenharmony_ci						0x07060501);
97562306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS11) {
97662306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
97762306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
97862306a36Sopenharmony_ci						0x07070605);
97962306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS10) {
98062306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
98162306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
98262306a36Sopenharmony_ci						0x08080706);
98362306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS9) {
98462306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
98562306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
98662306a36Sopenharmony_ci						0x08080707);
98762306a36Sopenharmony_ci			} else {
98862306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
98962306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
99062306a36Sopenharmony_ci						0x09090808);
99162306a36Sopenharmony_ci			}
99262306a36Sopenharmony_ci		} else {   /* collision_state == 0 */
99362306a36Sopenharmony_ci			if (rate == DESC92C_RATEMCS12) {
99462306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
99562306a36Sopenharmony_ci						0x05010000);
99662306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
99762306a36Sopenharmony_ci						0x09080706);
99862306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS11) {
99962306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
100062306a36Sopenharmony_ci						0x06050000);
100162306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
100262306a36Sopenharmony_ci						0x09080807);
100362306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS10) {
100462306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
100562306a36Sopenharmony_ci						0x07060000);
100662306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
100762306a36Sopenharmony_ci						0x0a090908);
100862306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS9) {
100962306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
101062306a36Sopenharmony_ci						0x07070000);
101162306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
101262306a36Sopenharmony_ci						0x0a090808);
101362306a36Sopenharmony_ci			} else {
101462306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
101562306a36Sopenharmony_ci						0x08080000);
101662306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
101762306a36Sopenharmony_ci						0x0b0a0909);
101862306a36Sopenharmony_ci			}
101962306a36Sopenharmony_ci		}
102062306a36Sopenharmony_ci	} else {  /* MCS13~MCS15,  1SS, G-mode */
102162306a36Sopenharmony_ci		if (collision_state == 1) {
102262306a36Sopenharmony_ci			if (rate == DESC92C_RATEMCS15) {
102362306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
102462306a36Sopenharmony_ci						0x00000000);
102562306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
102662306a36Sopenharmony_ci						0x05040302);
102762306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS14) {
102862306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
102962306a36Sopenharmony_ci						0x00000000);
103062306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
103162306a36Sopenharmony_ci						0x06050302);
103262306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS13) {
103362306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
103462306a36Sopenharmony_ci						0x00000000);
103562306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
103662306a36Sopenharmony_ci						0x07060502);
103762306a36Sopenharmony_ci			} else {
103862306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
103962306a36Sopenharmony_ci						0x00000000);
104062306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
104162306a36Sopenharmony_ci						0x06050402);
104262306a36Sopenharmony_ci			}
104362306a36Sopenharmony_ci		} else{   /* collision_state == 0 */
104462306a36Sopenharmony_ci			if (rate == DESC92C_RATEMCS15) {
104562306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
104662306a36Sopenharmony_ci						0x03020000);
104762306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
104862306a36Sopenharmony_ci						0x07060504);
104962306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS14) {
105062306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
105162306a36Sopenharmony_ci						0x03020000);
105262306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
105362306a36Sopenharmony_ci						0x08070605);
105462306a36Sopenharmony_ci			} else if (rate == DESC92C_RATEMCS13) {
105562306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
105662306a36Sopenharmony_ci						0x05020000);
105762306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
105862306a36Sopenharmony_ci						0x09080706);
105962306a36Sopenharmony_ci			} else {
106062306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC,
106162306a36Sopenharmony_ci						0x04020000);
106262306a36Sopenharmony_ci				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
106362306a36Sopenharmony_ci						0x08070605);
106462306a36Sopenharmony_ci			}
106562306a36Sopenharmony_ci		}
106662306a36Sopenharmony_ci	}
106762306a36Sopenharmony_ci}
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_civoid rtl92ee_dm_watchdog(struct ieee80211_hw *hw)
107062306a36Sopenharmony_ci{
107162306a36Sopenharmony_ci	struct rtl_priv *rtlpriv = rtl_priv(hw);
107262306a36Sopenharmony_ci	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
107362306a36Sopenharmony_ci	bool fw_current_inpsmode = false;
107462306a36Sopenharmony_ci	bool fw_ps_awake = true;
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
107762306a36Sopenharmony_ci				      (u8 *)(&fw_current_inpsmode));
107862306a36Sopenharmony_ci	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
107962306a36Sopenharmony_ci				      (u8 *)(&fw_ps_awake));
108062306a36Sopenharmony_ci	if (ppsc->p2p_ps_info.p2p_ps_mode)
108162306a36Sopenharmony_ci		fw_ps_awake = false;
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	spin_lock(&rtlpriv->locks.rf_ps_lock);
108462306a36Sopenharmony_ci	if ((ppsc->rfpwr_state == ERFON) &&
108562306a36Sopenharmony_ci	    ((!fw_current_inpsmode) && fw_ps_awake) &&
108662306a36Sopenharmony_ci	    (!ppsc->rfchange_inprogress)) {
108762306a36Sopenharmony_ci		rtl92ee_dm_common_info_self_update(hw);
108862306a36Sopenharmony_ci		rtl92ee_dm_false_alarm_counter_statistics(hw);
108962306a36Sopenharmony_ci		rtl92ee_dm_check_rssi_monitor(hw);
109062306a36Sopenharmony_ci		rtl92ee_dm_dig(hw);
109162306a36Sopenharmony_ci		rtl92ee_dm_adaptivity(hw);
109262306a36Sopenharmony_ci		rtl92ee_dm_cck_packet_detection_thresh(hw);
109362306a36Sopenharmony_ci		rtl92ee_dm_refresh_rate_adaptive_mask(hw);
109462306a36Sopenharmony_ci		rtl92ee_dm_check_edca_turbo(hw);
109562306a36Sopenharmony_ci		rtl92ee_dm_dynamic_atc_switch(hw);
109662306a36Sopenharmony_ci		rtl92ee_dm_dynamic_primary_cca_ckeck(hw);
109762306a36Sopenharmony_ci	}
109862306a36Sopenharmony_ci	spin_unlock(&rtlpriv->locks.rf_ps_lock);
109962306a36Sopenharmony_ci}
1100