summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek/rtw89/phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek/rtw89/phy.c')
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index a2ebef0051b8..9733ad1135f1 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -3660,6 +3660,62 @@ void rtw89_phy_dig(struct rtw89_dev *rtwdev)
rtw89_phy_dig_sdagc_follow_pagc_config(rtwdev, false);
}
+static void rtw89_phy_tx_path_div_sta_iter(void *data, struct ieee80211_sta *sta)
+{
+ struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+ struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ bool *done = data;
+ u8 rssi_a, rssi_b;
+ u32 candidate;
+
+ if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION || sta->tdls)
+ return;
+
+ if (*done)
+ return;
+
+ *done = true;
+
+ rssi_a = ewma_rssi_read(&rtwsta->rssi[RF_PATH_A]);
+ rssi_b = ewma_rssi_read(&rtwsta->rssi[RF_PATH_B]);
+
+ if (rssi_a > rssi_b + RTW89_TX_DIV_RSSI_RAW_TH)
+ candidate = RF_A;
+ else if (rssi_b > rssi_a + RTW89_TX_DIV_RSSI_RAW_TH)
+ candidate = RF_B;
+ else
+ return;
+
+ if (hal->antenna_tx == candidate)
+ return;
+
+ hal->antenna_tx = candidate;
+ rtw89_fw_h2c_txpath_cmac_tbl(rtwdev, rtwsta);
+
+ if (hal->antenna_tx == RF_A) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x12);
+ rtw89_phy_write32_mask(rtwdev, R_P1_RFMODE, B_P1_RFMODE_MUX, 0x11);
+ } else if (hal->antenna_tx == RF_B) {
+ rtw89_phy_write32_mask(rtwdev, R_P0_RFMODE, B_P0_RFMODE_MUX, 0x11);
+ rtw89_phy_write32_mask(rtwdev, R_P1_RFMODE, B_P1_RFMODE_MUX, 0x12);
+ }
+}
+
+void rtw89_phy_tx_path_div_track(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_hal *hal = &rtwdev->hal;
+ bool done = false;
+
+ if (!hal->tx_path_diversity)
+ return;
+
+ ieee80211_iterate_stations_atomic(rtwdev->hw,
+ rtw89_phy_tx_path_div_sta_iter,
+ &done);
+}
+
static void rtw89_phy_env_monitor_init(struct rtw89_dev *rtwdev)
{
rtw89_phy_ccx_top_setting_init(rtwdev);