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