xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8192du/dm.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2024  Realtek Corporation.*/
3 
4 #include "../wifi.h"
5 #include "../core.h"
6 #include "../rtl8192d/reg.h"
7 #include "../rtl8192d/def.h"
8 #include "../rtl8192d/dm_common.h"
9 #include "../rtl8192d/fw_common.h"
10 #include "dm.h"
11 
12 static void rtl92du_dm_init_1r_cca(struct ieee80211_hw *hw)
13 {
14 	struct rtl_priv *rtlpriv = rtl_priv(hw);
15 	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
16 
17 	dm_pstable->pre_ccastate = CCA_MAX;
18 	dm_pstable->cur_ccasate = CCA_MAX;
19 }
20 
21 static void rtl92du_dm_1r_cca(struct ieee80211_hw *hw)
22 {
23 	struct rtl_priv *rtlpriv = rtl_priv(hw);
24 	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
25 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
26 	int pwdb = rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
27 
28 	if (rtlhal->macphymode != SINGLEMAC_SINGLEPHY ||
29 	    rtlhal->current_bandtype != BAND_ON_5G)
30 		return;
31 
32 	if (pwdb != 0) {
33 		if (dm_pstable->pre_ccastate == CCA_2R ||
34 		    dm_pstable->pre_ccastate == CCA_MAX)
35 			dm_pstable->cur_ccasate = (pwdb >= 35) ? CCA_1R : CCA_2R;
36 		else
37 			dm_pstable->cur_ccasate = (pwdb <= 30) ? CCA_2R : CCA_1R;
38 	} else {
39 		dm_pstable->cur_ccasate = CCA_MAX;
40 	}
41 
42 	if (dm_pstable->pre_ccastate == dm_pstable->cur_ccasate)
43 		return;
44 
45 	rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_TRACE,
46 		"Old CCA state: %d new CCA state: %d\n",
47 		dm_pstable->pre_ccastate, dm_pstable->cur_ccasate);
48 
49 	if (dm_pstable->cur_ccasate == CCA_1R) {
50 		if (rtlpriv->phy.rf_type == RF_2T2R)
51 			rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x13);
52 		else /* Is this branch reachable? */
53 			rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23);
54 	} else { /* CCA_2R or CCA_MAX */
55 		rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x33);
56 	}
57 }
58 
59 static void rtl92du_dm_pwdb_monitor(struct ieee80211_hw *hw)
60 {
61 	struct rtl_priv *rtlpriv = rtl_priv(hw);
62 	const u32 max_macid = 32;
63 	u32 temp;
64 
65 	/* AP & ADHOC & MESH will return tmp */
66 	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
67 		return;
68 
69 	/* Indicate Rx signal strength to FW. */
70 	if (rtlpriv->dm.useramask) {
71 		temp = rtlpriv->dm.undec_sm_pwdb << 16;
72 		temp |= max_macid << 8;
73 
74 		rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *)(&temp));
75 	} else {
76 		rtl_write_byte(rtlpriv, 0x4fe, (u8)rtlpriv->dm.undec_sm_pwdb);
77 	}
78 }
79 
80 void rtl92du_dm_init(struct ieee80211_hw *hw)
81 {
82 	struct rtl_priv *rtlpriv = rtl_priv(hw);
83 
84 	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
85 	rtl_dm_diginit(hw, 0x20);
86 	rtlpriv->dm_digtable.rx_gain_max = DM_DIG_FA_UPPER;
87 	rtlpriv->dm_digtable.rx_gain_min = DM_DIG_FA_LOWER;
88 	rtl92d_dm_init_edca_turbo(hw);
89 	rtl92du_dm_init_1r_cca(hw);
90 	rtl92d_dm_init_rate_adaptive_mask(hw);
91 	rtl92d_dm_initialize_txpower_tracking(hw);
92 }
93 
94 void rtl92du_dm_watchdog(struct ieee80211_hw *hw)
95 {
96 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
97 	bool fw_current_inpsmode = false;
98 	bool fwps_awake = true;
99 
100 	/* 1. RF is OFF. (No need to do DM.)
101 	 * 2. Fw is under power saving mode for FwLPS.
102 	 *    (Prevent from SW/FW I/O racing.)
103 	 * 3. IPS workitem is scheduled. (Prevent from IPS sequence
104 	 *    to be swapped with DM.
105 	 * 4. RFChangeInProgress is TRUE.
106 	 *    (Prevent from broken by IPS/HW/SW Rf off.)
107 	 */
108 
109 	if (ppsc->rfpwr_state != ERFON || fw_current_inpsmode ||
110 	    !fwps_awake || ppsc->rfchange_inprogress)
111 		return;
112 
113 	rtl92du_dm_pwdb_monitor(hw);
114 	rtl92d_dm_false_alarm_counter_statistics(hw);
115 	rtl92d_dm_find_minimum_rssi(hw);
116 	rtl92d_dm_dig(hw);
117 	rtl92d_dm_check_txpower_tracking_thermal_meter(hw);
118 	rtl92d_dm_check_edca_turbo(hw);
119 	rtl92du_dm_1r_cca(hw);
120 }
121