xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8192de/dm.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2012  Realtek Corporation.*/
3 
4 #include "../wifi.h"
5 #include "../base.h"
6 #include "../core.h"
7 #include "../rtl8192d/reg.h"
8 #include "../rtl8192d/def.h"
9 #include "../rtl8192d/dm_common.h"
10 #include "../rtl8192d/phy_common.h"
11 #include "../rtl8192d/fw_common.h"
12 #include "phy.h"
13 #include "dm.h"
14 
15 #define UNDEC_SM_PWDB	entry_min_undec_sm_pwdb
16 
17 static void rtl92d_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
18 {
19 	struct rtl_priv *rtlpriv = rtl_priv(hw);
20 
21 	rtlpriv->dm.dynamic_txpower_enable = true;
22 	rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
23 	rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
24 }
25 
26 static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw)
27 {
28 	struct rtl_priv *rtlpriv = rtl_priv(hw);
29 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
30 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
31 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
32 	long undec_sm_pwdb;
33 
34 	if ((!rtlpriv->dm.dynamic_txpower_enable)
35 	    || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
36 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
37 		return;
38 	}
39 	if ((mac->link_state < MAC80211_LINKED) &&
40 	    (rtlpriv->dm.UNDEC_SM_PWDB == 0)) {
41 		rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE,
42 			"Not connected to any\n");
43 		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
44 		rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
45 		return;
46 	}
47 	if (mac->link_state >= MAC80211_LINKED) {
48 		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
49 			undec_sm_pwdb =
50 			    rtlpriv->dm.UNDEC_SM_PWDB;
51 			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
52 				"IBSS Client PWDB = 0x%lx\n",
53 				undec_sm_pwdb);
54 		} else {
55 			undec_sm_pwdb =
56 			    rtlpriv->dm.undec_sm_pwdb;
57 			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
58 				"STA Default Port PWDB = 0x%lx\n",
59 				undec_sm_pwdb);
60 		}
61 	} else {
62 		undec_sm_pwdb =
63 		    rtlpriv->dm.UNDEC_SM_PWDB;
64 
65 		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
66 			"AP Ext Port PWDB = 0x%lx\n",
67 			undec_sm_pwdb);
68 	}
69 	if (rtlhal->current_bandtype == BAND_ON_5G) {
70 		if (undec_sm_pwdb >= 0x33) {
71 			rtlpriv->dm.dynamic_txhighpower_lvl =
72 						 TXHIGHPWRLEVEL_LEVEL2;
73 			rtl_dbg(rtlpriv, COMP_HIPWR, DBG_LOUD,
74 				"5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n");
75 		} else if ((undec_sm_pwdb < 0x33)
76 			   && (undec_sm_pwdb >= 0x2b)) {
77 			rtlpriv->dm.dynamic_txhighpower_lvl =
78 						 TXHIGHPWRLEVEL_LEVEL1;
79 			rtl_dbg(rtlpriv, COMP_HIPWR, DBG_LOUD,
80 				"5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n");
81 		} else if (undec_sm_pwdb < 0x2b) {
82 			rtlpriv->dm.dynamic_txhighpower_lvl =
83 						 TXHIGHPWRLEVEL_NORMAL;
84 			rtl_dbg(rtlpriv, COMP_HIPWR, DBG_LOUD,
85 				"5G:TxHighPwrLevel_Normal\n");
86 		}
87 	} else {
88 		if (undec_sm_pwdb >=
89 		    TX_POWER_NEAR_FIELD_THRESH_LVL2) {
90 			rtlpriv->dm.dynamic_txhighpower_lvl =
91 						 TXHIGHPWRLEVEL_LEVEL2;
92 			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
93 				"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
94 		} else
95 		    if ((undec_sm_pwdb <
96 			 (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3))
97 			&& (undec_sm_pwdb >=
98 			    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
99 
100 			rtlpriv->dm.dynamic_txhighpower_lvl =
101 						 TXHIGHPWRLEVEL_LEVEL1;
102 			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
103 				"TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
104 		} else if (undec_sm_pwdb <
105 			   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
106 			rtlpriv->dm.dynamic_txhighpower_lvl =
107 						 TXHIGHPWRLEVEL_NORMAL;
108 			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
109 				"TXHIGHPWRLEVEL_NORMAL\n");
110 		}
111 	}
112 	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
113 		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
114 			"PHY_SetTxPowerLevel8192S() Channel = %d\n",
115 			rtlphy->current_channel);
116 		rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel);
117 	}
118 	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
119 }
120 
121 static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw)
122 {
123 	struct rtl_priv *rtlpriv = rtl_priv(hw);
124 
125 	/* AP & ADHOC & MESH will return tmp */
126 	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
127 		return;
128 	/* Indicate Rx signal strength to FW. */
129 	if (rtlpriv->dm.useramask) {
130 		u32 temp = rtlpriv->dm.undec_sm_pwdb;
131 
132 		temp <<= 16;
133 		temp |= 0x100;
134 		/* fw v12 cmdid 5:use max macid ,for nic ,
135 		 * default macid is 0 ,max macid is 1 */
136 		rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp));
137 	} else {
138 		rtl_write_byte(rtlpriv, 0x4fe,
139 			       (u8) rtlpriv->dm.undec_sm_pwdb);
140 	}
141 }
142 
143 void rtl92de_dm_init(struct ieee80211_hw *hw)
144 {
145 	struct rtl_priv *rtlpriv = rtl_priv(hw);
146 
147 	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
148 	rtl_dm_diginit(hw, 0x20);
149 	rtlpriv->dm_digtable.rx_gain_max = DM_DIG_FA_UPPER;
150 	rtlpriv->dm_digtable.rx_gain_min = DM_DIG_FA_LOWER;
151 	rtl92d_dm_init_dynamic_txpower(hw);
152 	rtl92d_dm_init_edca_turbo(hw);
153 	rtl92d_dm_init_rate_adaptive_mask(hw);
154 	rtl92d_dm_initialize_txpower_tracking(hw);
155 }
156 
157 void rtl92de_dm_watchdog(struct ieee80211_hw *hw)
158 {
159 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
160 	bool fw_current_inpsmode = false;
161 	bool fwps_awake = true;
162 
163 	/* 1. RF is OFF. (No need to do DM.)
164 	 * 2. Fw is under power saving mode for FwLPS.
165 	 *    (Prevent from SW/FW I/O racing.)
166 	 * 3. IPS workitem is scheduled. (Prevent from IPS sequence
167 	 *    to be swapped with DM.
168 	 * 4. RFChangeInProgress is TRUE.
169 	 *    (Prevent from broken by IPS/HW/SW Rf off.) */
170 
171 	if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
172 	    fwps_awake) && (!ppsc->rfchange_inprogress)) {
173 		rtl92d_dm_pwdb_monitor(hw);
174 		rtl92d_dm_false_alarm_counter_statistics(hw);
175 		rtl92d_dm_find_minimum_rssi(hw);
176 		rtl92d_dm_dig(hw);
177 		/* rtl92d_dm_dynamic_bb_powersaving(hw); */
178 		rtl92d_dm_dynamic_txpower(hw);
179 		/* rtl92d_dm_check_txpower_tracking_thermal_meter(hw); */
180 		/* rtl92d_dm_refresh_rate_adaptive_mask(hw); */
181 		/* rtl92d_dm_interrupt_migration(hw); */
182 		rtl92d_dm_check_edca_turbo(hw);
183 	}
184 }
185