summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek/rtlwifi/rtl8192du/dm.c
blob: dd57707a9184b2c6f438e3c0060394f8fb99dac6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2024  Realtek Corporation.*/

#include "../wifi.h"
#include "../core.h"
#include "../rtl8192d/reg.h"
#include "../rtl8192d/def.h"
#include "../rtl8192d/dm_common.h"
#include "../rtl8192d/fw_common.h"
#include "dm.h"

static void rtl92du_dm_init_1r_cca(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;

	dm_pstable->pre_ccastate = CCA_MAX;
	dm_pstable->cur_ccasate = CCA_MAX;
}

static void rtl92du_dm_1r_cca(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
	int pwdb = rtlpriv->dm_digtable.min_undec_pwdb_for_dm;

	if (rtlhal->macphymode != SINGLEMAC_SINGLEPHY ||
	    rtlhal->current_bandtype != BAND_ON_5G)
		return;

	if (pwdb != 0) {
		if (dm_pstable->pre_ccastate == CCA_2R ||
		    dm_pstable->pre_ccastate == CCA_MAX)
			dm_pstable->cur_ccasate = (pwdb >= 35) ? CCA_1R : CCA_2R;
		else
			dm_pstable->cur_ccasate = (pwdb <= 30) ? CCA_2R : CCA_1R;
	} else {
		dm_pstable->cur_ccasate = CCA_MAX;
	}

	if (dm_pstable->pre_ccastate == dm_pstable->cur_ccasate)
		return;

	rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_TRACE,
		"Old CCA state: %d new CCA state: %d\n",
		dm_pstable->pre_ccastate, dm_pstable->cur_ccasate);

	if (dm_pstable->cur_ccasate == CCA_1R) {
		if (rtlpriv->phy.rf_type == RF_2T2R)
			rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x13);
		else /* Is this branch reachable? */
			rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23);
	} else { /* CCA_2R or CCA_MAX */
		rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x33);
	}
}

static void rtl92du_dm_pwdb_monitor(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	const u32 max_macid = 32;
	u32 temp;

	/* AP & ADHOC & MESH will return tmp */
	if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
		return;

	/* Indicate Rx signal strength to FW. */
	if (rtlpriv->dm.useramask) {
		temp = rtlpriv->dm.undec_sm_pwdb << 16;
		temp |= max_macid << 8;

		rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *)(&temp));
	} else {
		rtl_write_byte(rtlpriv, 0x4fe, (u8)rtlpriv->dm.undec_sm_pwdb);
	}
}

void rtl92du_dm_init(struct ieee80211_hw *hw)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);

	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
	rtl_dm_diginit(hw, 0x20);
	rtlpriv->dm_digtable.rx_gain_max = DM_DIG_FA_UPPER;
	rtlpriv->dm_digtable.rx_gain_min = DM_DIG_FA_LOWER;
	rtl92d_dm_init_edca_turbo(hw);
	rtl92du_dm_init_1r_cca(hw);
	rtl92d_dm_init_rate_adaptive_mask(hw);
	rtl92d_dm_initialize_txpower_tracking(hw);
}

void rtl92du_dm_watchdog(struct ieee80211_hw *hw)
{
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	bool fw_current_inpsmode = false;
	bool fwps_awake = true;

	/* 1. RF is OFF. (No need to do DM.)
	 * 2. Fw is under power saving mode for FwLPS.
	 *    (Prevent from SW/FW I/O racing.)
	 * 3. IPS workitem is scheduled. (Prevent from IPS sequence
	 *    to be swapped with DM.
	 * 4. RFChangeInProgress is TRUE.
	 *    (Prevent from broken by IPS/HW/SW Rf off.)
	 */

	if (ppsc->rfpwr_state != ERFON || fw_current_inpsmode ||
	    !fwps_awake || ppsc->rfchange_inprogress)
		return;

	rtl92du_dm_pwdb_monitor(hw);
	rtl92d_dm_false_alarm_counter_statistics(hw);
	rtl92d_dm_find_minimum_rssi(hw);
	rtl92d_dm_dig(hw);
	rtl92d_dm_check_txpower_tracking_thermal_meter(hw);
	rtl92d_dm_check_edca_turbo(hw);
	rtl92du_dm_1r_cca(hw);
}