xref: /openbmc/linux/drivers/net/wireless/realtek/rtlwifi/rtl8192se/dm.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
16f3fcdc8SLarry Finger // SPDX-License-Identifier: GPL-2.0
26f3fcdc8SLarry Finger /* Copyright(c) 2009-2012  Realtek Corporation.*/
3f1d2b4d3SLarry Finger 
4f1d2b4d3SLarry Finger #include "../wifi.h"
5f1d2b4d3SLarry Finger #include "../base.h"
6f1d2b4d3SLarry Finger #include "../core.h"
7f1d2b4d3SLarry Finger #include "reg.h"
8f1d2b4d3SLarry Finger #include "def.h"
9f1d2b4d3SLarry Finger #include "phy.h"
10f1d2b4d3SLarry Finger #include "dm.h"
11f1d2b4d3SLarry Finger #include "fw.h"
12f1d2b4d3SLarry Finger 
13f1d2b4d3SLarry Finger static const u32 edca_setting_dl[PEER_MAX] = {
14f1d2b4d3SLarry Finger 	0xa44f,		/* 0 UNKNOWN */
15f1d2b4d3SLarry Finger 	0x5ea44f,	/* 1 REALTEK_90 */
16f1d2b4d3SLarry Finger 	0x5ea44f,	/* 2 REALTEK_92SE */
17f1d2b4d3SLarry Finger 	0xa630,		/* 3 BROAD	*/
18f1d2b4d3SLarry Finger 	0xa44f,		/* 4 RAL */
19f1d2b4d3SLarry Finger 	0xa630,		/* 5 ATH */
20f1d2b4d3SLarry Finger 	0xa630,		/* 6 CISCO */
21f1d2b4d3SLarry Finger 	0xa42b,		/* 7 MARV */
22f1d2b4d3SLarry Finger };
23f1d2b4d3SLarry Finger 
24f1d2b4d3SLarry Finger static const u32 edca_setting_dl_gmode[PEER_MAX] = {
25f1d2b4d3SLarry Finger 	0x4322,		/* 0 UNKNOWN */
26f1d2b4d3SLarry Finger 	0xa44f,		/* 1 REALTEK_90 */
27f1d2b4d3SLarry Finger 	0x5ea44f,	/* 2 REALTEK_92SE */
28f1d2b4d3SLarry Finger 	0xa42b,		/* 3 BROAD */
29f1d2b4d3SLarry Finger 	0x5e4322,	/* 4 RAL */
30f1d2b4d3SLarry Finger 	0x4322,		/* 5 ATH */
31f1d2b4d3SLarry Finger 	0xa430,		/* 6 CISCO */
32f1d2b4d3SLarry Finger 	0x5ea44f,	/* 7 MARV */
33f1d2b4d3SLarry Finger };
34f1d2b4d3SLarry Finger 
35f1d2b4d3SLarry Finger static const u32 edca_setting_ul[PEER_MAX] = {
36f1d2b4d3SLarry Finger 	0x5e4322,	/* 0 UNKNOWN */
37f1d2b4d3SLarry Finger 	0xa44f,		/* 1 REALTEK_90 */
38f1d2b4d3SLarry Finger 	0x5ea44f,	/* 2 REALTEK_92SE */
39f1d2b4d3SLarry Finger 	0x5ea322,	/* 3 BROAD */
40f1d2b4d3SLarry Finger 	0x5ea422,	/* 4 RAL */
41f1d2b4d3SLarry Finger 	0x5ea322,	/* 5 ATH */
42f1d2b4d3SLarry Finger 	0x3ea44f,	/* 6 CISCO */
43f1d2b4d3SLarry Finger 	0x5ea44f,	/* 7 MARV */
44f1d2b4d3SLarry Finger };
45f1d2b4d3SLarry Finger 
_rtl92s_dm_check_edca_turbo(struct ieee80211_hw * hw)46f1d2b4d3SLarry Finger static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw)
47f1d2b4d3SLarry Finger {
48f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
49f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
50f1d2b4d3SLarry Finger 
51f1d2b4d3SLarry Finger 	static u64 last_txok_cnt;
52f1d2b4d3SLarry Finger 	static u64 last_rxok_cnt;
53f1d2b4d3SLarry Finger 	u64 cur_txok_cnt = 0;
54f1d2b4d3SLarry Finger 	u64 cur_rxok_cnt = 0;
55f1d2b4d3SLarry Finger 
56f1d2b4d3SLarry Finger 	u32 edca_be_ul = edca_setting_ul[mac->vendor];
57f1d2b4d3SLarry Finger 	u32 edca_be_dl = edca_setting_dl[mac->vendor];
58f1d2b4d3SLarry Finger 	u32 edca_gmode = edca_setting_dl_gmode[mac->vendor];
59f1d2b4d3SLarry Finger 
60f1d2b4d3SLarry Finger 	if (mac->link_state != MAC80211_LINKED) {
61f1d2b4d3SLarry Finger 		rtlpriv->dm.current_turbo_edca = false;
62f1d2b4d3SLarry Finger 		goto dm_checkedcaturbo_exit;
63f1d2b4d3SLarry Finger 	}
64f1d2b4d3SLarry Finger 
65f1d2b4d3SLarry Finger 	if ((!rtlpriv->dm.is_any_nonbepkts) &&
66f1d2b4d3SLarry Finger 	    (!rtlpriv->dm.disable_framebursting)) {
67f1d2b4d3SLarry Finger 		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
68f1d2b4d3SLarry Finger 		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
69f1d2b4d3SLarry Finger 
70f1d2b4d3SLarry Finger 		if (rtlpriv->phy.rf_type == RF_1T2R) {
71f1d2b4d3SLarry Finger 			if (cur_txok_cnt > 4 * cur_rxok_cnt) {
72f1d2b4d3SLarry Finger 				/* Uplink TP is present. */
73f1d2b4d3SLarry Finger 				if (rtlpriv->dm.is_cur_rdlstate ||
74f1d2b4d3SLarry Finger 					!rtlpriv->dm.current_turbo_edca) {
75f1d2b4d3SLarry Finger 					rtl_write_dword(rtlpriv, EDCAPARA_BE,
76f1d2b4d3SLarry Finger 							edca_be_ul);
77f1d2b4d3SLarry Finger 					rtlpriv->dm.is_cur_rdlstate = false;
78f1d2b4d3SLarry Finger 				}
79f1d2b4d3SLarry Finger 			} else {/* Balance TP is present. */
80f1d2b4d3SLarry Finger 				if (!rtlpriv->dm.is_cur_rdlstate ||
81f1d2b4d3SLarry Finger 					!rtlpriv->dm.current_turbo_edca) {
82f1d2b4d3SLarry Finger 					if (mac->mode == WIRELESS_MODE_G ||
83f1d2b4d3SLarry Finger 					    mac->mode == WIRELESS_MODE_B)
84f1d2b4d3SLarry Finger 						rtl_write_dword(rtlpriv,
85f1d2b4d3SLarry Finger 								EDCAPARA_BE,
86f1d2b4d3SLarry Finger 								edca_gmode);
87f1d2b4d3SLarry Finger 					else
88f1d2b4d3SLarry Finger 						rtl_write_dword(rtlpriv,
89f1d2b4d3SLarry Finger 								EDCAPARA_BE,
90f1d2b4d3SLarry Finger 								edca_be_dl);
91f1d2b4d3SLarry Finger 					rtlpriv->dm.is_cur_rdlstate = true;
92f1d2b4d3SLarry Finger 				}
93f1d2b4d3SLarry Finger 			}
94f1d2b4d3SLarry Finger 			rtlpriv->dm.current_turbo_edca = true;
95f1d2b4d3SLarry Finger 		} else {
96f1d2b4d3SLarry Finger 			if (cur_rxok_cnt > 4 * cur_txok_cnt) {
97f1d2b4d3SLarry Finger 				if (!rtlpriv->dm.is_cur_rdlstate ||
98f1d2b4d3SLarry Finger 					!rtlpriv->dm.current_turbo_edca) {
99f1d2b4d3SLarry Finger 					if (mac->mode == WIRELESS_MODE_G ||
100f1d2b4d3SLarry Finger 					    mac->mode == WIRELESS_MODE_B)
101f1d2b4d3SLarry Finger 						rtl_write_dword(rtlpriv,
102f1d2b4d3SLarry Finger 								EDCAPARA_BE,
103f1d2b4d3SLarry Finger 								edca_gmode);
104f1d2b4d3SLarry Finger 					else
105f1d2b4d3SLarry Finger 						rtl_write_dword(rtlpriv,
106f1d2b4d3SLarry Finger 								EDCAPARA_BE,
107f1d2b4d3SLarry Finger 								edca_be_dl);
108f1d2b4d3SLarry Finger 					rtlpriv->dm.is_cur_rdlstate = true;
109f1d2b4d3SLarry Finger 				}
110f1d2b4d3SLarry Finger 			} else {
111f1d2b4d3SLarry Finger 				if (rtlpriv->dm.is_cur_rdlstate ||
112f1d2b4d3SLarry Finger 					!rtlpriv->dm.current_turbo_edca) {
113f1d2b4d3SLarry Finger 					rtl_write_dword(rtlpriv, EDCAPARA_BE,
114f1d2b4d3SLarry Finger 							edca_be_ul);
115f1d2b4d3SLarry Finger 					rtlpriv->dm.is_cur_rdlstate = false;
116f1d2b4d3SLarry Finger 				}
117f1d2b4d3SLarry Finger 			}
118f1d2b4d3SLarry Finger 			rtlpriv->dm.current_turbo_edca = true;
119f1d2b4d3SLarry Finger 		}
120f1d2b4d3SLarry Finger 	} else {
121f1d2b4d3SLarry Finger 		if (rtlpriv->dm.current_turbo_edca) {
122f1d2b4d3SLarry Finger 			u8 tmp = AC0_BE;
123f1d2b4d3SLarry Finger 			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
124f1d2b4d3SLarry Finger 						      &tmp);
125f1d2b4d3SLarry Finger 			rtlpriv->dm.current_turbo_edca = false;
126f1d2b4d3SLarry Finger 		}
127f1d2b4d3SLarry Finger 	}
128f1d2b4d3SLarry Finger 
129f1d2b4d3SLarry Finger dm_checkedcaturbo_exit:
130f1d2b4d3SLarry Finger 	rtlpriv->dm.is_any_nonbepkts = false;
131f1d2b4d3SLarry Finger 	last_txok_cnt = rtlpriv->stats.txbytesunicast;
132f1d2b4d3SLarry Finger 	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
133f1d2b4d3SLarry Finger }
134f1d2b4d3SLarry Finger 
_rtl92s_dm_txpowertracking_callback_thermalmeter(struct ieee80211_hw * hw)135f1d2b4d3SLarry Finger static void _rtl92s_dm_txpowertracking_callback_thermalmeter(
136f1d2b4d3SLarry Finger 					struct ieee80211_hw *hw)
137f1d2b4d3SLarry Finger {
138f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
139f1d2b4d3SLarry Finger 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
140f1d2b4d3SLarry Finger 	u8 thermalvalue = 0;
141f1d2b4d3SLarry Finger 	u32 fw_cmd = 0;
142f1d2b4d3SLarry Finger 
143f1d2b4d3SLarry Finger 	rtlpriv->dm.txpower_trackinginit = true;
144f1d2b4d3SLarry Finger 
145f1d2b4d3SLarry Finger 	thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
146f1d2b4d3SLarry Finger 
147*fca8218dSLarry Finger 	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
148f1d2b4d3SLarry Finger 		"Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermal meter 0x%x\n",
149f1d2b4d3SLarry Finger 		thermalvalue,
150f1d2b4d3SLarry Finger 		rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter);
151f1d2b4d3SLarry Finger 
152f1d2b4d3SLarry Finger 	if (thermalvalue) {
153f1d2b4d3SLarry Finger 		rtlpriv->dm.thermalvalue = thermalvalue;
154f1d2b4d3SLarry Finger 		if (hal_get_firmwareversion(rtlpriv) >= 0x35) {
155f1d2b4d3SLarry Finger 			rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL);
156f1d2b4d3SLarry Finger 		} else {
157f1d2b4d3SLarry Finger 			fw_cmd = (FW_TXPWR_TRACK_THERMAL |
158f1d2b4d3SLarry Finger 				 (rtlpriv->efuse.thermalmeter[0] << 8) |
159f1d2b4d3SLarry Finger 				 (thermalvalue << 16));
160f1d2b4d3SLarry Finger 
161*fca8218dSLarry Finger 			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
162f1d2b4d3SLarry Finger 				"Write to FW Thermal Val = 0x%x\n", fw_cmd);
163f1d2b4d3SLarry Finger 
164f1d2b4d3SLarry Finger 			rtl_write_dword(rtlpriv, WFM5, fw_cmd);
165f1d2b4d3SLarry Finger 			rtl92s_phy_chk_fwcmd_iodone(hw);
166f1d2b4d3SLarry Finger 		}
167f1d2b4d3SLarry Finger 	}
168f1d2b4d3SLarry Finger 
169f1d2b4d3SLarry Finger 	rtlpriv->dm.txpowercount = 0;
170f1d2b4d3SLarry Finger }
171f1d2b4d3SLarry Finger 
_rtl92s_dm_check_txpowertracking_thermalmeter(struct ieee80211_hw * hw)172f1d2b4d3SLarry Finger static void _rtl92s_dm_check_txpowertracking_thermalmeter(
173f1d2b4d3SLarry Finger 					struct ieee80211_hw *hw)
174f1d2b4d3SLarry Finger {
175f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
176f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
177f1d2b4d3SLarry Finger 	u8 tx_power_checkcnt = 5;
178f1d2b4d3SLarry Finger 
179f1d2b4d3SLarry Finger 	/* 2T2R TP issue */
180f1d2b4d3SLarry Finger 	if (rtlphy->rf_type == RF_2T2R)
181f1d2b4d3SLarry Finger 		return;
182f1d2b4d3SLarry Finger 
183f1d2b4d3SLarry Finger 	if (!rtlpriv->dm.txpower_tracking)
184f1d2b4d3SLarry Finger 		return;
185f1d2b4d3SLarry Finger 
186f1d2b4d3SLarry Finger 	if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) {
187f1d2b4d3SLarry Finger 		rtlpriv->dm.txpowercount++;
188f1d2b4d3SLarry Finger 		return;
189f1d2b4d3SLarry Finger 	}
190f1d2b4d3SLarry Finger 
191f1d2b4d3SLarry Finger 	if (!rtlpriv->dm.tm_trigger) {
192f1d2b4d3SLarry Finger 		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER,
193f1d2b4d3SLarry Finger 			      RFREG_OFFSET_MASK, 0x60);
194f1d2b4d3SLarry Finger 		rtlpriv->dm.tm_trigger = 1;
195f1d2b4d3SLarry Finger 	} else {
196f1d2b4d3SLarry Finger 		_rtl92s_dm_txpowertracking_callback_thermalmeter(hw);
197f1d2b4d3SLarry Finger 		rtlpriv->dm.tm_trigger = 0;
198f1d2b4d3SLarry Finger 	}
199f1d2b4d3SLarry Finger }
200f1d2b4d3SLarry Finger 
_rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw * hw)201f1d2b4d3SLarry Finger static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw)
202f1d2b4d3SLarry Finger {
203f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
204f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
205f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
206f1d2b4d3SLarry Finger 	struct rate_adaptive *ra = &(rtlpriv->ra);
207f1d2b4d3SLarry Finger 	struct ieee80211_sta *sta = NULL;
208f1d2b4d3SLarry Finger 	u32 low_rssi_thresh = 0;
209f1d2b4d3SLarry Finger 	u32 middle_rssi_thresh = 0;
210f1d2b4d3SLarry Finger 	u32 high_rssi_thresh = 0;
211f1d2b4d3SLarry Finger 
212f1d2b4d3SLarry Finger 	if (is_hal_stop(rtlhal))
213f1d2b4d3SLarry Finger 		return;
214f1d2b4d3SLarry Finger 
215f1d2b4d3SLarry Finger 	if (!rtlpriv->dm.useramask)
216f1d2b4d3SLarry Finger 		return;
217f1d2b4d3SLarry Finger 
218f1d2b4d3SLarry Finger 	if (hal_get_firmwareversion(rtlpriv) >= 61 &&
219f1d2b4d3SLarry Finger 	    !rtlpriv->dm.inform_fw_driverctrldm) {
220f1d2b4d3SLarry Finger 		rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER);
221f1d2b4d3SLarry Finger 		rtlpriv->dm.inform_fw_driverctrldm = true;
222f1d2b4d3SLarry Finger 	}
223f1d2b4d3SLarry Finger 
224f1d2b4d3SLarry Finger 	if ((mac->link_state == MAC80211_LINKED) &&
225f1d2b4d3SLarry Finger 	    (mac->opmode == NL80211_IFTYPE_STATION)) {
226f1d2b4d3SLarry Finger 		switch (ra->pre_ratr_state) {
227f1d2b4d3SLarry Finger 		case DM_RATR_STA_HIGH:
228f1d2b4d3SLarry Finger 			high_rssi_thresh = 40;
229f1d2b4d3SLarry Finger 			middle_rssi_thresh = 30;
230f1d2b4d3SLarry Finger 			low_rssi_thresh = 20;
231f1d2b4d3SLarry Finger 			break;
232f1d2b4d3SLarry Finger 		case DM_RATR_STA_MIDDLE:
233f1d2b4d3SLarry Finger 			high_rssi_thresh = 44;
234f1d2b4d3SLarry Finger 			middle_rssi_thresh = 30;
235f1d2b4d3SLarry Finger 			low_rssi_thresh = 20;
236f1d2b4d3SLarry Finger 			break;
237f1d2b4d3SLarry Finger 		case DM_RATR_STA_LOW:
238f1d2b4d3SLarry Finger 			high_rssi_thresh = 44;
239f1d2b4d3SLarry Finger 			middle_rssi_thresh = 34;
240f1d2b4d3SLarry Finger 			low_rssi_thresh = 20;
241f1d2b4d3SLarry Finger 			break;
242f1d2b4d3SLarry Finger 		case DM_RATR_STA_ULTRALOW:
243f1d2b4d3SLarry Finger 			high_rssi_thresh = 44;
244f1d2b4d3SLarry Finger 			middle_rssi_thresh = 34;
245f1d2b4d3SLarry Finger 			low_rssi_thresh = 24;
246f1d2b4d3SLarry Finger 			break;
247f1d2b4d3SLarry Finger 		default:
248f1d2b4d3SLarry Finger 			high_rssi_thresh = 44;
249f1d2b4d3SLarry Finger 			middle_rssi_thresh = 34;
250f1d2b4d3SLarry Finger 			low_rssi_thresh = 24;
251f1d2b4d3SLarry Finger 			break;
252f1d2b4d3SLarry Finger 		}
253f1d2b4d3SLarry Finger 
254f1d2b4d3SLarry Finger 		if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) {
255f1d2b4d3SLarry Finger 			ra->ratr_state = DM_RATR_STA_HIGH;
256f1d2b4d3SLarry Finger 		} else if (rtlpriv->dm.undec_sm_pwdb >
257f1d2b4d3SLarry Finger 			   (long)middle_rssi_thresh) {
258f1d2b4d3SLarry Finger 			ra->ratr_state = DM_RATR_STA_LOW;
259f1d2b4d3SLarry Finger 		} else if (rtlpriv->dm.undec_sm_pwdb >
260f1d2b4d3SLarry Finger 			   (long)low_rssi_thresh) {
261f1d2b4d3SLarry Finger 			ra->ratr_state = DM_RATR_STA_LOW;
262f1d2b4d3SLarry Finger 		} else {
263f1d2b4d3SLarry Finger 			ra->ratr_state = DM_RATR_STA_ULTRALOW;
264f1d2b4d3SLarry Finger 		}
265f1d2b4d3SLarry Finger 
266f1d2b4d3SLarry Finger 		if (ra->pre_ratr_state != ra->ratr_state) {
267*fca8218dSLarry Finger 			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
268f1d2b4d3SLarry Finger 				"RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n",
269f1d2b4d3SLarry Finger 				rtlpriv->dm.undec_sm_pwdb, ra->ratr_state,
270f1d2b4d3SLarry Finger 				ra->pre_ratr_state, ra->ratr_state);
271f1d2b4d3SLarry Finger 
272f1d2b4d3SLarry Finger 			rcu_read_lock();
273f1d2b4d3SLarry Finger 			sta = rtl_find_sta(hw, mac->bssid);
274f1d2b4d3SLarry Finger 			if (sta)
275f1d2b4d3SLarry Finger 				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
2761d22b177SPing-Ke Shih 							   ra->ratr_state,
2771d22b177SPing-Ke Shih 							   true);
278f1d2b4d3SLarry Finger 			rcu_read_unlock();
279f1d2b4d3SLarry Finger 
280f1d2b4d3SLarry Finger 			ra->pre_ratr_state = ra->ratr_state;
281f1d2b4d3SLarry Finger 		}
282f1d2b4d3SLarry Finger 	}
283f1d2b4d3SLarry Finger }
284f1d2b4d3SLarry Finger 
_rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw * hw)285f1d2b4d3SLarry Finger static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw)
286f1d2b4d3SLarry Finger {
287f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
288f1d2b4d3SLarry Finger 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
289f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
290f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
291f1d2b4d3SLarry Finger 	bool current_mrc;
292f1d2b4d3SLarry Finger 	bool enable_mrc = true;
293f1d2b4d3SLarry Finger 	long tmpentry_maxpwdb = 0;
294f1d2b4d3SLarry Finger 	u8 rssi_a = 0;
295f1d2b4d3SLarry Finger 	u8 rssi_b = 0;
296f1d2b4d3SLarry Finger 
297f1d2b4d3SLarry Finger 	if (is_hal_stop(rtlhal))
298f1d2b4d3SLarry Finger 		return;
299f1d2b4d3SLarry Finger 
300f1d2b4d3SLarry Finger 	if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R))
301f1d2b4d3SLarry Finger 		return;
302f1d2b4d3SLarry Finger 
303f1d2b4d3SLarry Finger 	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(&current_mrc));
304f1d2b4d3SLarry Finger 
305f1d2b4d3SLarry Finger 	if (mac->link_state >= MAC80211_LINKED) {
306f1d2b4d3SLarry Finger 		if (rtlpriv->dm.undec_sm_pwdb > tmpentry_maxpwdb) {
307f1d2b4d3SLarry Finger 			rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A];
308f1d2b4d3SLarry Finger 			rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B];
309f1d2b4d3SLarry Finger 		}
310f1d2b4d3SLarry Finger 	}
311f1d2b4d3SLarry Finger 
312f1d2b4d3SLarry Finger 	/* MRC settings would NOT affect TP on Wireless B mode. */
313f1d2b4d3SLarry Finger 	if (mac->mode != WIRELESS_MODE_B) {
314f1d2b4d3SLarry Finger 		if ((rssi_a == 0) && (rssi_b == 0)) {
315f1d2b4d3SLarry Finger 			enable_mrc = true;
316f1d2b4d3SLarry Finger 		} else if (rssi_b > 30) {
317f1d2b4d3SLarry Finger 			/* Turn on B-Path */
318f1d2b4d3SLarry Finger 			enable_mrc = true;
319f1d2b4d3SLarry Finger 		} else if (rssi_b < 5) {
320f1d2b4d3SLarry Finger 			/* Turn off B-path  */
321f1d2b4d3SLarry Finger 			enable_mrc = false;
322f1d2b4d3SLarry Finger 		/* Take care of RSSI differentiation. */
323f1d2b4d3SLarry Finger 		} else if (rssi_a > 15 && (rssi_a >= rssi_b)) {
324f1d2b4d3SLarry Finger 			if ((rssi_a - rssi_b) > 15)
325f1d2b4d3SLarry Finger 				/* Turn off B-path  */
326f1d2b4d3SLarry Finger 				enable_mrc = false;
327f1d2b4d3SLarry Finger 			else if ((rssi_a - rssi_b) < 10)
328f1d2b4d3SLarry Finger 				/* Turn on B-Path */
329f1d2b4d3SLarry Finger 				enable_mrc = true;
330f1d2b4d3SLarry Finger 			else
331f1d2b4d3SLarry Finger 				enable_mrc = current_mrc;
332f1d2b4d3SLarry Finger 		} else {
333f1d2b4d3SLarry Finger 			/* Turn on B-Path */
334f1d2b4d3SLarry Finger 			enable_mrc = true;
335f1d2b4d3SLarry Finger 		}
336f1d2b4d3SLarry Finger 	}
337f1d2b4d3SLarry Finger 
338f1d2b4d3SLarry Finger 	/* Update MRC settings if needed. */
339f1d2b4d3SLarry Finger 	if (enable_mrc != current_mrc)
340f1d2b4d3SLarry Finger 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC,
341f1d2b4d3SLarry Finger 					      (u8 *)&enable_mrc);
342f1d2b4d3SLarry Finger 
343f1d2b4d3SLarry Finger }
344f1d2b4d3SLarry Finger 
rtl92s_dm_init_edca_turbo(struct ieee80211_hw * hw)345f1d2b4d3SLarry Finger void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw)
346f1d2b4d3SLarry Finger {
347f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
348f1d2b4d3SLarry Finger 
349f1d2b4d3SLarry Finger 	rtlpriv->dm.current_turbo_edca = false;
350f1d2b4d3SLarry Finger 	rtlpriv->dm.is_any_nonbepkts = false;
351f1d2b4d3SLarry Finger 	rtlpriv->dm.is_cur_rdlstate = false;
352f1d2b4d3SLarry Finger }
353f1d2b4d3SLarry Finger 
_rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw * hw)354f1d2b4d3SLarry Finger static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
355f1d2b4d3SLarry Finger {
356f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
357f1d2b4d3SLarry Finger 	struct rate_adaptive *ra = &(rtlpriv->ra);
358f1d2b4d3SLarry Finger 
359f1d2b4d3SLarry Finger 	ra->ratr_state = DM_RATR_STA_MAX;
360f1d2b4d3SLarry Finger 	ra->pre_ratr_state = DM_RATR_STA_MAX;
361f1d2b4d3SLarry Finger 
362f1d2b4d3SLarry Finger 	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER &&
363f1d2b4d3SLarry Finger 	    hal_get_firmwareversion(rtlpriv) >= 60)
364f1d2b4d3SLarry Finger 		rtlpriv->dm.useramask = true;
365f1d2b4d3SLarry Finger 	else
366f1d2b4d3SLarry Finger 		rtlpriv->dm.useramask = false;
367f1d2b4d3SLarry Finger 
368f1d2b4d3SLarry Finger 	rtlpriv->dm.useramask = false;
369f1d2b4d3SLarry Finger 	rtlpriv->dm.inform_fw_driverctrldm = false;
370f1d2b4d3SLarry Finger }
371f1d2b4d3SLarry Finger 
_rtl92s_dm_init_txpowertracking_thermalmeter(struct ieee80211_hw * hw)372f1d2b4d3SLarry Finger static void _rtl92s_dm_init_txpowertracking_thermalmeter(
373f1d2b4d3SLarry Finger 				struct ieee80211_hw *hw)
374f1d2b4d3SLarry Finger {
375f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
376f1d2b4d3SLarry Finger 
377f1d2b4d3SLarry Finger 	rtlpriv->dm.txpower_tracking = true;
378f1d2b4d3SLarry Finger 	rtlpriv->dm.txpowercount = 0;
379f1d2b4d3SLarry Finger 	rtlpriv->dm.txpower_trackinginit = false;
380f1d2b4d3SLarry Finger }
381f1d2b4d3SLarry Finger 
_rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw * hw)382f1d2b4d3SLarry Finger static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
383f1d2b4d3SLarry Finger {
384f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
385f1d2b4d3SLarry Finger 	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
386f1d2b4d3SLarry Finger 	u32 ret_value;
387f1d2b4d3SLarry Finger 
388f1d2b4d3SLarry Finger 	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
389f1d2b4d3SLarry Finger 	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
390f1d2b4d3SLarry Finger 
391f1d2b4d3SLarry Finger 	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
392f1d2b4d3SLarry Finger 	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
393f1d2b4d3SLarry Finger 	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
394f1d2b4d3SLarry Finger 	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
395f1d2b4d3SLarry Finger 	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
396f1d2b4d3SLarry Finger 
397f1d2b4d3SLarry Finger 	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
398f1d2b4d3SLarry Finger 		falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail +
399f1d2b4d3SLarry Finger 		falsealm_cnt->cnt_mcs_fail;
400f1d2b4d3SLarry Finger 
401f1d2b4d3SLarry Finger 	/* read CCK false alarm */
402f1d2b4d3SLarry Finger 	ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD);
403f1d2b4d3SLarry Finger 	falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff);
404f1d2b4d3SLarry Finger 	falsealm_cnt->cnt_all =	falsealm_cnt->cnt_ofdm_fail +
405f1d2b4d3SLarry Finger 		falsealm_cnt->cnt_cck_fail;
406f1d2b4d3SLarry Finger }
407f1d2b4d3SLarry Finger 
rtl92s_backoff_enable_flag(struct ieee80211_hw * hw)408f1d2b4d3SLarry Finger static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw)
409f1d2b4d3SLarry Finger {
410f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
411f1d2b4d3SLarry Finger 	struct dig_t *digtable = &rtlpriv->dm_digtable;
412f1d2b4d3SLarry Finger 	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
413f1d2b4d3SLarry Finger 
414f1d2b4d3SLarry Finger 	if (falsealm_cnt->cnt_all > digtable->fa_highthresh) {
415f1d2b4d3SLarry Finger 		if ((digtable->back_val - 6) <
416f1d2b4d3SLarry Finger 			digtable->backoffval_range_min)
417f1d2b4d3SLarry Finger 			digtable->back_val = digtable->backoffval_range_min;
418f1d2b4d3SLarry Finger 		else
419f1d2b4d3SLarry Finger 			digtable->back_val -= 6;
420f1d2b4d3SLarry Finger 	} else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) {
421f1d2b4d3SLarry Finger 		if ((digtable->back_val + 6) >
422f1d2b4d3SLarry Finger 			digtable->backoffval_range_max)
423f1d2b4d3SLarry Finger 			digtable->back_val =
424f1d2b4d3SLarry Finger 				 digtable->backoffval_range_max;
425f1d2b4d3SLarry Finger 		else
426f1d2b4d3SLarry Finger 			digtable->back_val += 6;
427f1d2b4d3SLarry Finger 	}
428f1d2b4d3SLarry Finger }
429f1d2b4d3SLarry Finger 
_rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw * hw)430f1d2b4d3SLarry Finger static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
431f1d2b4d3SLarry Finger {
432f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
433f1d2b4d3SLarry Finger 	struct dig_t *digtable = &rtlpriv->dm_digtable;
434f1d2b4d3SLarry Finger 	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
435f1d2b4d3SLarry Finger 	static u8 initialized, force_write;
436f1d2b4d3SLarry Finger 	u8 initial_gain = 0;
437f1d2b4d3SLarry Finger 
438f1d2b4d3SLarry Finger 	if ((digtable->pre_sta_cstate == digtable->cur_sta_cstate) ||
439f1d2b4d3SLarry Finger 	    (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT)) {
440f1d2b4d3SLarry Finger 		if (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) {
441f1d2b4d3SLarry Finger 			if (rtlpriv->psc.rfpwr_state != ERFON)
442f1d2b4d3SLarry Finger 				return;
443f1d2b4d3SLarry Finger 
444f1d2b4d3SLarry Finger 			if (digtable->backoff_enable_flag)
445f1d2b4d3SLarry Finger 				rtl92s_backoff_enable_flag(hw);
446f1d2b4d3SLarry Finger 			else
447f1d2b4d3SLarry Finger 				digtable->back_val = DM_DIG_BACKOFF_MAX;
448f1d2b4d3SLarry Finger 
449f1d2b4d3SLarry Finger 			if ((digtable->rssi_val + 10 - digtable->back_val) >
450f1d2b4d3SLarry Finger 				digtable->rx_gain_max)
451f1d2b4d3SLarry Finger 				digtable->cur_igvalue =
452f1d2b4d3SLarry Finger 						digtable->rx_gain_max;
453f1d2b4d3SLarry Finger 			else if ((digtable->rssi_val + 10 - digtable->back_val)
454f1d2b4d3SLarry Finger 				 < digtable->rx_gain_min)
455f1d2b4d3SLarry Finger 				digtable->cur_igvalue =
456f1d2b4d3SLarry Finger 						digtable->rx_gain_min;
457f1d2b4d3SLarry Finger 			else
458f1d2b4d3SLarry Finger 				digtable->cur_igvalue = digtable->rssi_val + 10
459f1d2b4d3SLarry Finger 					- digtable->back_val;
460f1d2b4d3SLarry Finger 
461f1d2b4d3SLarry Finger 			if (falsealm_cnt->cnt_all > 10000)
462f1d2b4d3SLarry Finger 				digtable->cur_igvalue =
463f1d2b4d3SLarry Finger 					 (digtable->cur_igvalue > 0x33) ?
464f1d2b4d3SLarry Finger 					 digtable->cur_igvalue : 0x33;
465f1d2b4d3SLarry Finger 
466f1d2b4d3SLarry Finger 			if (falsealm_cnt->cnt_all > 16000)
467f1d2b4d3SLarry Finger 				digtable->cur_igvalue =
468f1d2b4d3SLarry Finger 						 digtable->rx_gain_max;
469f1d2b4d3SLarry Finger 		/* connected -> connected or disconnected -> disconnected  */
470f1d2b4d3SLarry Finger 		} else {
471f1d2b4d3SLarry Finger 			/* Firmware control DIG, do nothing in driver dm */
472f1d2b4d3SLarry Finger 			return;
473f1d2b4d3SLarry Finger 		}
474f1d2b4d3SLarry Finger 		/* disconnected -> connected or connected ->
475f1d2b4d3SLarry Finger 		 * disconnected or beforeconnect->(dis)connected */
476f1d2b4d3SLarry Finger 	} else {
477f1d2b4d3SLarry Finger 		/* Enable FW DIG */
478f1d2b4d3SLarry Finger 		digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
479f1d2b4d3SLarry Finger 		rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE);
480f1d2b4d3SLarry Finger 
481f1d2b4d3SLarry Finger 		digtable->back_val = DM_DIG_BACKOFF_MAX;
482f1d2b4d3SLarry Finger 		digtable->cur_igvalue = rtlpriv->phy.default_initialgain[0];
483f1d2b4d3SLarry Finger 		digtable->pre_igvalue = 0;
484f1d2b4d3SLarry Finger 		return;
485f1d2b4d3SLarry Finger 	}
486f1d2b4d3SLarry Finger 
487f1d2b4d3SLarry Finger 	/* Forced writing to prevent from fw-dig overwriting. */
488f1d2b4d3SLarry Finger 	if (digtable->pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1,
489f1d2b4d3SLarry Finger 						  MASKBYTE0))
490f1d2b4d3SLarry Finger 		force_write = 1;
491f1d2b4d3SLarry Finger 
492f1d2b4d3SLarry Finger 	if ((digtable->pre_igvalue != digtable->cur_igvalue) ||
493f1d2b4d3SLarry Finger 	    !initialized || force_write) {
494f1d2b4d3SLarry Finger 		/* Disable FW DIG */
495f1d2b4d3SLarry Finger 		rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE);
496f1d2b4d3SLarry Finger 
497f1d2b4d3SLarry Finger 		initial_gain = (u8)digtable->cur_igvalue;
498f1d2b4d3SLarry Finger 
499f1d2b4d3SLarry Finger 		/* Set initial gain. */
500f1d2b4d3SLarry Finger 		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain);
501f1d2b4d3SLarry Finger 		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain);
502f1d2b4d3SLarry Finger 		digtable->pre_igvalue = digtable->cur_igvalue;
503f1d2b4d3SLarry Finger 		initialized = 1;
504f1d2b4d3SLarry Finger 		force_write = 0;
505f1d2b4d3SLarry Finger 	}
506f1d2b4d3SLarry Finger }
507f1d2b4d3SLarry Finger 
_rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw * hw)508f1d2b4d3SLarry Finger static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw)
509f1d2b4d3SLarry Finger {
510f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
511f1d2b4d3SLarry Finger 	struct dig_t *dig = &rtlpriv->dm_digtable;
512f1d2b4d3SLarry Finger 
513f1d2b4d3SLarry Finger 	if (rtlpriv->mac80211.act_scanning)
514f1d2b4d3SLarry Finger 		return;
515f1d2b4d3SLarry Finger 
516f1d2b4d3SLarry Finger 	/* Decide the current status and if modify initial gain or not */
517f1d2b4d3SLarry Finger 	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED ||
518f1d2b4d3SLarry Finger 	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC)
519f1d2b4d3SLarry Finger 		dig->cur_sta_cstate = DIG_STA_CONNECT;
520f1d2b4d3SLarry Finger 	else
521f1d2b4d3SLarry Finger 		dig->cur_sta_cstate = DIG_STA_DISCONNECT;
522f1d2b4d3SLarry Finger 
523f1d2b4d3SLarry Finger 	dig->rssi_val = rtlpriv->dm.undec_sm_pwdb;
524f1d2b4d3SLarry Finger 
525f1d2b4d3SLarry Finger 	/* Change dig mode to rssi */
526f1d2b4d3SLarry Finger 	if (dig->cur_sta_cstate != DIG_STA_DISCONNECT) {
527f1d2b4d3SLarry Finger 		if (dig->dig_twoport_algorithm ==
528f1d2b4d3SLarry Finger 		    DIG_TWO_PORT_ALGO_FALSE_ALARM) {
529f1d2b4d3SLarry Finger 			dig->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
530f1d2b4d3SLarry Finger 			rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS);
531f1d2b4d3SLarry Finger 		}
532f1d2b4d3SLarry Finger 	}
533f1d2b4d3SLarry Finger 
534f1d2b4d3SLarry Finger 	_rtl92s_dm_false_alarm_counter_statistics(hw);
535f1d2b4d3SLarry Finger 	_rtl92s_dm_initial_gain_sta_beforeconnect(hw);
536f1d2b4d3SLarry Finger 
537f1d2b4d3SLarry Finger 	dig->pre_sta_cstate = dig->cur_sta_cstate;
538f1d2b4d3SLarry Finger }
539f1d2b4d3SLarry Finger 
_rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw * hw)540f1d2b4d3SLarry Finger static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw)
541f1d2b4d3SLarry Finger {
542f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
543f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
544f1d2b4d3SLarry Finger 	struct dig_t *digtable = &rtlpriv->dm_digtable;
545f1d2b4d3SLarry Finger 
546f1d2b4d3SLarry Finger 	/* 2T2R TP issue */
547f1d2b4d3SLarry Finger 	if (rtlphy->rf_type == RF_2T2R)
548f1d2b4d3SLarry Finger 		return;
549f1d2b4d3SLarry Finger 
550f1d2b4d3SLarry Finger 	if (!rtlpriv->dm.dm_initialgain_enable)
551f1d2b4d3SLarry Finger 		return;
552f1d2b4d3SLarry Finger 
553f1d2b4d3SLarry Finger 	if (digtable->dig_enable_flag == false)
554f1d2b4d3SLarry Finger 		return;
555f1d2b4d3SLarry Finger 
556f1d2b4d3SLarry Finger 	_rtl92s_dm_ctrl_initgain_bytwoport(hw);
557f1d2b4d3SLarry Finger }
558f1d2b4d3SLarry Finger 
_rtl92s_dm_dynamic_txpower(struct ieee80211_hw * hw)559f1d2b4d3SLarry Finger static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw)
560f1d2b4d3SLarry Finger {
561f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
562f1d2b4d3SLarry Finger 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
563f1d2b4d3SLarry Finger 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
564f1d2b4d3SLarry Finger 	long undec_sm_pwdb;
565f1d2b4d3SLarry Finger 	long txpwr_threshold_lv1, txpwr_threshold_lv2;
566f1d2b4d3SLarry Finger 
567f1d2b4d3SLarry Finger 	/* 2T2R TP issue */
568f1d2b4d3SLarry Finger 	if (rtlphy->rf_type == RF_2T2R)
569f1d2b4d3SLarry Finger 		return;
570f1d2b4d3SLarry Finger 
571f1d2b4d3SLarry Finger 	if (!rtlpriv->dm.dynamic_txpower_enable ||
572f1d2b4d3SLarry Finger 	    rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
573f1d2b4d3SLarry Finger 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
574f1d2b4d3SLarry Finger 		return;
575f1d2b4d3SLarry Finger 	}
576f1d2b4d3SLarry Finger 
577f1d2b4d3SLarry Finger 	if ((mac->link_state < MAC80211_LINKED) &&
578f1d2b4d3SLarry Finger 	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
579*fca8218dSLarry Finger 		rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
580f1d2b4d3SLarry Finger 			"Not connected to any\n");
581f1d2b4d3SLarry Finger 
582f1d2b4d3SLarry Finger 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
583f1d2b4d3SLarry Finger 
584f1d2b4d3SLarry Finger 		rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
585f1d2b4d3SLarry Finger 		return;
586f1d2b4d3SLarry Finger 	}
587f1d2b4d3SLarry Finger 
588f1d2b4d3SLarry Finger 	if (mac->link_state >= MAC80211_LINKED) {
589f1d2b4d3SLarry Finger 		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
590f1d2b4d3SLarry Finger 			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
591*fca8218dSLarry Finger 			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
592f1d2b4d3SLarry Finger 				"AP Client PWDB = 0x%lx\n",
593f1d2b4d3SLarry Finger 				undec_sm_pwdb);
594f1d2b4d3SLarry Finger 		} else {
595f1d2b4d3SLarry Finger 			undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
596*fca8218dSLarry Finger 			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
597f1d2b4d3SLarry Finger 				"STA Default Port PWDB = 0x%lx\n",
598f1d2b4d3SLarry Finger 				undec_sm_pwdb);
599f1d2b4d3SLarry Finger 		}
600f1d2b4d3SLarry Finger 	} else {
601f1d2b4d3SLarry Finger 		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
602f1d2b4d3SLarry Finger 
603*fca8218dSLarry Finger 		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
604f1d2b4d3SLarry Finger 			"AP Ext Port PWDB = 0x%lx\n",
605f1d2b4d3SLarry Finger 			undec_sm_pwdb);
606f1d2b4d3SLarry Finger 	}
607f1d2b4d3SLarry Finger 
608f1d2b4d3SLarry Finger 	txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2;
609f1d2b4d3SLarry Finger 	txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1;
610f1d2b4d3SLarry Finger 
611f1d2b4d3SLarry Finger 	if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1)
612f1d2b4d3SLarry Finger 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
613f1d2b4d3SLarry Finger 	else if (undec_sm_pwdb >= txpwr_threshold_lv2)
614f1d2b4d3SLarry Finger 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2;
615f1d2b4d3SLarry Finger 	else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) &&
616f1d2b4d3SLarry Finger 		(undec_sm_pwdb >= txpwr_threshold_lv1))
617f1d2b4d3SLarry Finger 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1;
618f1d2b4d3SLarry Finger 	else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3))
619f1d2b4d3SLarry Finger 		rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
620f1d2b4d3SLarry Finger 
621f1d2b4d3SLarry Finger 	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl))
622f1d2b4d3SLarry Finger 		rtl92s_phy_set_txpower(hw, rtlphy->current_channel);
623f1d2b4d3SLarry Finger 
624f1d2b4d3SLarry Finger 	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
625f1d2b4d3SLarry Finger }
626f1d2b4d3SLarry Finger 
_rtl92s_dm_init_dig(struct ieee80211_hw * hw)627f1d2b4d3SLarry Finger static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw)
628f1d2b4d3SLarry Finger {
629f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
630f1d2b4d3SLarry Finger 	struct dig_t *digtable = &rtlpriv->dm_digtable;
631f1d2b4d3SLarry Finger 
632f1d2b4d3SLarry Finger 	/* Disable DIG scheme now.*/
633f1d2b4d3SLarry Finger 	digtable->dig_enable_flag = true;
634f1d2b4d3SLarry Finger 	digtable->backoff_enable_flag = true;
635f1d2b4d3SLarry Finger 
636f1d2b4d3SLarry Finger 	if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) &&
637f1d2b4d3SLarry Finger 	    (hal_get_firmwareversion(rtlpriv) >= 0x3c))
638f1d2b4d3SLarry Finger 		digtable->dig_algorithm = DIG_ALGO_BY_TOW_PORT;
639f1d2b4d3SLarry Finger 	else
640f1d2b4d3SLarry Finger 		digtable->dig_algorithm =
641f1d2b4d3SLarry Finger 			 DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM;
642f1d2b4d3SLarry Finger 
643f1d2b4d3SLarry Finger 	digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI;
644f1d2b4d3SLarry Finger 	digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
645f1d2b4d3SLarry Finger 	/* off=by real rssi value, on=by digtable->rssi_val for new dig */
646f1d2b4d3SLarry Finger 	digtable->dig_dbgmode = DM_DBG_OFF;
647f1d2b4d3SLarry Finger 	digtable->dig_slgorithm_switch = 0;
648f1d2b4d3SLarry Finger 
649f1d2b4d3SLarry Finger 	/* 2007/10/04 MH Define init gain threshol. */
650f1d2b4d3SLarry Finger 	digtable->dig_state = DM_STA_DIG_MAX;
651f1d2b4d3SLarry Finger 	digtable->dig_highpwrstate = DM_STA_DIG_MAX;
652f1d2b4d3SLarry Finger 
653f1d2b4d3SLarry Finger 	digtable->cur_sta_cstate = DIG_STA_DISCONNECT;
654f1d2b4d3SLarry Finger 	digtable->pre_sta_cstate = DIG_STA_DISCONNECT;
655f1d2b4d3SLarry Finger 	digtable->cur_ap_cstate = DIG_AP_DISCONNECT;
656f1d2b4d3SLarry Finger 	digtable->pre_ap_cstate = DIG_AP_DISCONNECT;
657f1d2b4d3SLarry Finger 
658f1d2b4d3SLarry Finger 	digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
659f1d2b4d3SLarry Finger 	digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
660f1d2b4d3SLarry Finger 
661f1d2b4d3SLarry Finger 	digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
662f1d2b4d3SLarry Finger 	digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
663f1d2b4d3SLarry Finger 
664f1d2b4d3SLarry Finger 	digtable->rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW;
665f1d2b4d3SLarry Finger 	digtable->rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH;
666f1d2b4d3SLarry Finger 
667f1d2b4d3SLarry Finger 	/* for dig debug rssi value */
668f1d2b4d3SLarry Finger 	digtable->rssi_val = 50;
669f1d2b4d3SLarry Finger 	digtable->back_val = DM_DIG_BACKOFF_MAX;
670f1d2b4d3SLarry Finger 	digtable->rx_gain_max = DM_DIG_MAX;
671f1d2b4d3SLarry Finger 
672f1d2b4d3SLarry Finger 	digtable->rx_gain_min = DM_DIG_MIN;
673f1d2b4d3SLarry Finger 
674f1d2b4d3SLarry Finger 	digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX;
675f1d2b4d3SLarry Finger 	digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN;
676f1d2b4d3SLarry Finger }
677f1d2b4d3SLarry Finger 
_rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw * hw)678f1d2b4d3SLarry Finger static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
679f1d2b4d3SLarry Finger {
680f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
681f1d2b4d3SLarry Finger 
682f1d2b4d3SLarry Finger 	if ((hal_get_firmwareversion(rtlpriv) >= 60) &&
683f1d2b4d3SLarry Finger 	    (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER))
684f1d2b4d3SLarry Finger 		rtlpriv->dm.dynamic_txpower_enable = true;
685f1d2b4d3SLarry Finger 	else
686f1d2b4d3SLarry Finger 		rtlpriv->dm.dynamic_txpower_enable = false;
687f1d2b4d3SLarry Finger 
688f1d2b4d3SLarry Finger 	rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL;
689f1d2b4d3SLarry Finger 	rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL;
690f1d2b4d3SLarry Finger }
691f1d2b4d3SLarry Finger 
rtl92s_dm_init(struct ieee80211_hw * hw)692f1d2b4d3SLarry Finger void rtl92s_dm_init(struct ieee80211_hw *hw)
693f1d2b4d3SLarry Finger {
694f1d2b4d3SLarry Finger 	struct rtl_priv *rtlpriv = rtl_priv(hw);
695f1d2b4d3SLarry Finger 
696f1d2b4d3SLarry Finger 	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
697f1d2b4d3SLarry Finger 	rtlpriv->dm.undec_sm_pwdb = -1;
698f1d2b4d3SLarry Finger 
699f1d2b4d3SLarry Finger 	_rtl92s_dm_init_dynamic_txpower(hw);
700f1d2b4d3SLarry Finger 	rtl92s_dm_init_edca_turbo(hw);
701f1d2b4d3SLarry Finger 	_rtl92s_dm_init_rate_adaptive_mask(hw);
702f1d2b4d3SLarry Finger 	_rtl92s_dm_init_txpowertracking_thermalmeter(hw);
703f1d2b4d3SLarry Finger 	_rtl92s_dm_init_dig(hw);
704f1d2b4d3SLarry Finger 
705f1d2b4d3SLarry Finger 	rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE);
706f1d2b4d3SLarry Finger }
707f1d2b4d3SLarry Finger 
rtl92s_dm_watchdog(struct ieee80211_hw * hw)708f1d2b4d3SLarry Finger void rtl92s_dm_watchdog(struct ieee80211_hw *hw)
709f1d2b4d3SLarry Finger {
710f1d2b4d3SLarry Finger 	_rtl92s_dm_check_edca_turbo(hw);
711f1d2b4d3SLarry Finger 	_rtl92s_dm_check_txpowertracking_thermalmeter(hw);
712f1d2b4d3SLarry Finger 	_rtl92s_dm_ctrl_initgain_byrssi(hw);
713f1d2b4d3SLarry Finger 	_rtl92s_dm_dynamic_txpower(hw);
714f1d2b4d3SLarry Finger 	_rtl92s_dm_refresh_rateadaptive_mask(hw);
715f1d2b4d3SLarry Finger 	_rtl92s_dm_switch_baseband_mrc(hw);
716f1d2b4d3SLarry Finger }
717f1d2b4d3SLarry Finger 
718