]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: 8922a: enable dynamic antenna gain
authorKuan-Chung Chen <damon.chen@realtek.com>
Thu, 6 Mar 2025 02:11:43 +0000 (10:11 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Thu, 13 Mar 2025 00:45:43 +0000 (08:45 +0800)
The 8922A now supports dynamic antenna gain. However, in firmware
before v0.35.64.0, different transmit powers cannot be applied to
each RF path. To comply with regulatory limits in these older
firmware, the lower of the two requested transmit powers will
be used for both paths when they differ.

Signed-off-by: Kuan-Chung Chen <damon.chen@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250306021144.12854-5-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/phy.c
drivers/net/wireless/realtek/rtw89/phy.h
drivers/net/wireless/realtek/rtw89/reg.h
drivers/net/wireless/realtek/rtw89/rtw8922a.c

index b8f46207141e7adcdc73289f164b06b2f7d46a71..c32b74df1443a2c6e911a0910416ad04d5b0dd01 100644 (file)
@@ -4492,6 +4492,7 @@ enum rtw89_fw_feature {
        RTW89_FW_FEATURE_CH_INFO_BE_V0,
        RTW89_FW_FEATURE_LPS_CH_INFO,
        RTW89_FW_FEATURE_NO_PHYCAP_P1,
+       RTW89_FW_FEATURE_NO_POWER_DIFFERENCE,
 };
 
 struct rtw89_fw_suit {
index d0a246f415ffc66c27c97037dfc1f3566b686a6e..8643b17866f89773c15729bcf427a6bd2602622a 100644 (file)
@@ -849,6 +849,7 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
        __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 47, 0, CH_INFO_BE_V0),
        __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 49, 0, RFK_PRE_NOTIFY_V1),
        __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 51, 0, NO_PHYCAP_P1),
+       __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 64, 0, NO_POWER_DIFFERENCE),
 };
 
 static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
index bd736417f46779d601ab17905e208d0e84d16622..f4eee642e5ced512eb3c387f60f3930b4a721cd4 100644 (file)
@@ -2050,6 +2050,9 @@ static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, u8 band, u32 cente
        offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, center_freq);
        offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, center_freq);
 
+       if (RTW89_CHK_FW_FEATURE(NO_POWER_DIFFERENCE, &rtwdev->fw))
+               return min(offset_patha, offset_pathb);
+
        return max(offset_patha, offset_pathb);
 }
 
@@ -2067,6 +2070,9 @@ s16 rtw89_phy_ant_gain_pwr_offset(struct rtw89_dev *rtwdev,
        if (ant_gain->block_country || !(ant_gain->regd_enabled & BIT(regd)))
                return 0;
 
+       if (RTW89_CHK_FW_FEATURE(NO_POWER_DIFFERENCE, &rtwdev->fw))
+               return 0;
+
        offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, chan->freq);
        offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, chan->freq);
 
index e20fff9bac3ee93f5e15aa084839730bfe86169e..518a100375fb3101cf44c814d5b300a196e14803 100644 (file)
@@ -914,6 +914,13 @@ static inline s8 rtw89_phy_txpwr_rf_to_bb(struct rtw89_dev *rtwdev, s8 txpwr_rf)
        return txpwr_rf << (chip->txpwr_factor_bb - chip->txpwr_factor_rf);
 }
 
+static inline s8 rtw89_phy_txpwr_bb_to_rf(struct rtw89_dev *rtwdev, s8 txpwr_bb)
+{
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+
+       return txpwr_bb >> (chip->txpwr_factor_bb - chip->txpwr_factor_rf);
+}
+
 static inline s8 rtw89_phy_txpwr_rf_to_mac(struct rtw89_dev *rtwdev, s8 txpwr_rf)
 {
        const struct rtw89_chip_info *chip = rtwdev->chip;
index ec06f5bd0fab24da3586f48de5c41aa41f38f95c..44201efee01caf4bceff96b52b258aefc1d9231b 100644 (file)
 #define B_IQKINF2_FCNT GENMASK(23, 16)
 #define B_IQKINF2_KCNT GENMASK(15, 8)
 #define B_IQKINF2_NCTLV GENMASK(7, 0)
+#define R_TXAGC_REF_DBM_RF1_P0 0xBC04
+#define B_TXAGC_OFDM_REF_DBM_RF1_P0 GENMASK(10, 2)
+#define B_TXAGC_CCK_REF_DBM_RF1_P0 GENMASK(19, 11)
+#define R_TSSI_K_RF1_P0 0xBC28
+#define B_TSSI_K_OFDM_RF1_P0 GENMASK(9, 0)
+#define R_TXAGC_REF_DBM_RF1_P1 0xBD04
+#define B_TXAGC_OFDM_REF_DBM_RF1_P1 GENMASK(10, 2)
+#define B_TXAGC_CCK_REF_DBM_RF1_P1 GENMASK(19, 11)
+#define R_TSSI_K_RF1_P1 0xBD28
+#define B_TSSI_K_OFDM_RF1_P1 GENMASK(9, 0)
 #define R_RFK_ST 0xBFF8
 #define R_DCOF0 0xC000
 #define B_DCOF0_RST BIT(17)
 #define R_TSSI_MAP_OFST_P1 0xE720
 #define B_TSSI_MAP_OFST_OFDM GENMASK(17, 9)
 #define B_TSSI_MAP_OFST_CCK GENMASK(26, 18)
-#define R_TXAGC_REF0_P0 0xE628
-#define R_TXAGC_REF0_P1 0xE728
-#define B_TXAGC_REF0_OFDM_DBM GENMASK(8, 0)
-#define B_TXAGC_REF0_CCK_DBM GENMASK(17, 9)
-#define B_TXAGC_REF0_OFDM_CW GENMASK(26, 18)
-#define R_TXAGC_REF1_P0 0xE62C
-#define R_TXAGC_REF1_P1 0xE72C
-#define B_TXAGC_REF1_CCK_CW GENMASK(8, 0)
+#define R_TXAGC_REF_DBM_P0 0xE628
+#define B_TXAGC_OFDM_REF_DBM_P0 GENMASK(8, 0)
+#define B_TXAGC_CCK_REF_DBM_P0 GENMASK(17, 9)
+#define R_TSSI_K_P0 0xE6A0
+#define B_TSSI_K_OFDM_P0 GENMASK(29, 20)
 #define R_TXPWR_RSTB 0xE70C
 #define B_TXPWR_RSTB BIT(16)
+#define R_TXAGC_REF_DBM_P1 0xE728
+#define B_TXAGC_OFDM_REF_DBM_P1 GENMASK(8, 0)
+#define B_TXAGC_CCK_REF_DBM_P1 GENMASK(17, 9)
+#define R_TSSI_K_P1 0xE7A0
+#define B_TSSI_K_OFDM_P1 GENMASK(29, 20)
 
 /* WiFi CPU local domain */
 #define R_AX_WDT_CTRL 0x0040
index d90af2daebcf7583e97dddeb56bb7b313ccd7ceb..8082592db84a1da75c5e4022b037752fb92c9a03 100644 (file)
@@ -2156,6 +2156,56 @@ static void rtw8922a_set_txpwr_ref(struct rtw89_dev *rtwdev,
                                     B_BE_PWR_REF_CTRL_CCK, ref_cck);
 }
 
+static const struct rtw89_reg_def rtw8922a_txpwr_ref[][3] = {
+       {{ .addr = R_TXAGC_REF_DBM_P0, .mask = B_TXAGC_OFDM_REF_DBM_P0},
+        { .addr = R_TXAGC_REF_DBM_P0, .mask = B_TXAGC_CCK_REF_DBM_P0},
+        { .addr = R_TSSI_K_P0, .mask = B_TSSI_K_OFDM_P0}
+       },
+       {{ .addr = R_TXAGC_REF_DBM_RF1_P0, .mask = B_TXAGC_OFDM_REF_DBM_RF1_P0},
+        { .addr = R_TXAGC_REF_DBM_RF1_P0, .mask = B_TXAGC_CCK_REF_DBM_RF1_P0},
+        { .addr = R_TSSI_K_RF1_P0, .mask = B_TSSI_K_OFDM_RF1_P0}
+       },
+};
+
+static void rtw8922a_set_txpwr_diff(struct rtw89_dev *rtwdev,
+                                   const struct rtw89_chan *chan,
+                                   enum rtw89_phy_idx phy_idx)
+{
+       s16 pwr_ofst = rtw89_phy_ant_gain_pwr_offset(rtwdev, chan);
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+       static const u32 path_ofst[] = {0x0, 0x100};
+       const struct rtw89_reg_def *txpwr_ref;
+       static const s16 tssi_k_base = 0x12;
+       s16 tssi_k_ofst = abs(pwr_ofst) + tssi_k_base;
+       s16 ofst_dec[RF_PATH_NUM_8922A];
+       s16 tssi_k[RF_PATH_NUM_8922A];
+       s16 pwr_ref_ofst;
+       s16 pwr_ref = 0;
+       u8 i;
+
+       if (rtwdev->hal.cv == CHIP_CAV)
+               pwr_ref = 16;
+
+       pwr_ref <<= chip->txpwr_factor_rf;
+       pwr_ref_ofst = pwr_ref - rtw89_phy_txpwr_bb_to_rf(rtwdev, abs(pwr_ofst));
+
+       ofst_dec[RF_PATH_A] = pwr_ofst > 0 ? pwr_ref : pwr_ref_ofst;
+       ofst_dec[RF_PATH_B] = pwr_ofst > 0 ? pwr_ref_ofst : pwr_ref;
+       tssi_k[RF_PATH_A] = pwr_ofst > 0 ? tssi_k_base : tssi_k_ofst;
+       tssi_k[RF_PATH_B] = pwr_ofst > 0 ? tssi_k_ofst : tssi_k_base;
+
+       for (i = 0; i < RF_PATH_NUM_8922A; i++) {
+               txpwr_ref = rtw8922a_txpwr_ref[phy_idx];
+
+               rtw89_phy_write32_mask(rtwdev, txpwr_ref[0].addr + path_ofst[i],
+                                      txpwr_ref[0].mask, ofst_dec[i]);
+               rtw89_phy_write32_mask(rtwdev, txpwr_ref[1].addr + path_ofst[i],
+                                      txpwr_ref[1].mask, ofst_dec[i]);
+               rtw89_phy_write32_mask(rtwdev, txpwr_ref[2].addr + path_ofst[i],
+                                      txpwr_ref[2].mask, tssi_k[i]);
+       }
+}
+
 static void rtw8922a_bb_tx_triangular(struct rtw89_dev *rtwdev, bool en,
                                      enum rtw89_phy_idx phy_idx)
 {
@@ -2192,6 +2242,8 @@ static void rtw8922a_set_txpwr(struct rtw89_dev *rtwdev,
        rtw8922a_set_tx_shape(rtwdev, chan, phy_idx);
        rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx);
        rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
+       rtw8922a_set_txpwr_diff(rtwdev, chan, phy_idx);
+       rtw8922a_set_txpwr_ref(rtwdev, phy_idx);
 }
 
 static void rtw8922a_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
@@ -2769,7 +2821,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
                                  BIT(NL80211_CHAN_WIDTH_80) |
                                  BIT(NL80211_CHAN_WIDTH_160),
        .support_unii4          = true,
-       .support_ant_gain       = false,
+       .support_ant_gain       = true,
        .support_tas            = false,
        .ul_tb_waveform_ctrl    = false,
        .ul_tb_pwr_diff         = false,