* [PATCH rtw-next 1/7] wifi: rtw89: fw: load TX power track element according to AID
2026-05-20 12:38 [PATCH rtw-next 0/7] wifi: rtw89: update firmware elements formats of power track, compensation and MRU Ping-Ke Shih
@ 2026-05-20 12:38 ` Ping-Ke Shih
2026-05-27 8:42 ` Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 2/7] wifi: rtw89: 8922d: refactor digital power compensation to support new format Ping-Ke Shih
` (5 subsequent siblings)
6 siblings, 1 reply; 9+ messages in thread
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
To: linux-wireless; +Cc: kevin_yang
From: Zong-Zhe Yang <kevin_yang@realtek.com>
RF parameters has different TX power track table for different AID.
FW elements may include multiple TX power track tables for different
AID. So, load the corresponding one.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/fw.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index ff3914a16b81..5d0b3ba9a358 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -1209,12 +1209,17 @@ int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev,
{
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_hal *hal = &rtwdev->hal;
+ u16 aid = le16_to_cpu(elm->aid);
u32 needed_bitmap = 0;
u32 offset = 0;
int subband;
u32 bitmap;
int type;
+ if (aid && aid != hal->aid)
+ return 1;
+
if (chip->support_bands & BIT(NL80211_BAND_6GHZ))
needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_6GHZ;
if (chip->support_bands & BIT(NL80211_BAND_5GHZ))
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH rtw-next 1/7] wifi: rtw89: fw: load TX power track element according to AID
2026-05-20 12:38 ` [PATCH rtw-next 1/7] wifi: rtw89: fw: load TX power track element according to AID Ping-Ke Shih
@ 2026-05-27 8:42 ` Ping-Ke Shih
0 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-05-27 8:42 UTC (permalink / raw)
To: Ping-Ke Shih, linux-wireless; +Cc: kevin_yang
Ping-Ke Shih <pkshih@realtek.com> wrote:
> From: Zong-Zhe Yang <kevin_yang@realtek.com>
>
> RF parameters has different TX power track table for different AID.
> FW elements may include multiple TX power track tables for different
> AID. So, load the corresponding one.
>
> Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
7 patch(es) applied to rtw-next branch of rtw.git, thanks.
f50cf5f5d6a3 wifi: rtw89: fw: load TX power track element according to AID
57efc7b096a6 wifi: rtw89: 8922d: refactor digital power compensation to support new format
c77a155c96d7 wifi: rtw89: 8922d: support new digital power compensation format
89ab7535e428 wifi: rtw89: fw: load TX compensation element by RFE type
ed438b312d07 wifi: rtw89: Wi-Fi 7 configure TX power limit for large MRU
a153f9ce94e6 wifi: rtw89: debug: show large MRU in txpwr_table dbgfs
756abe2ebe3e wifi: rtw89: 8922d: configure TX shape settings
---
https://github.com/pkshih/rtw.git
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH rtw-next 2/7] wifi: rtw89: 8922d: refactor digital power compensation to support new format
2026-05-20 12:38 [PATCH rtw-next 0/7] wifi: rtw89: update firmware elements formats of power track, compensation and MRU Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 1/7] wifi: rtw89: fw: load TX power track element according to AID Ping-Ke Shih
@ 2026-05-20 12:38 ` Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 3/7] wifi: rtw89: 8922d: support new digital power compensation format Ping-Ke Shih
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
To: linux-wireless; +Cc: kevin_yang
Because base settings of digital power compensation can be shared across
all bands, the settings are divided into two parts -- base and individual
values per bands. Refactor the code to be reuse with new format.
No change logic at all.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 31 +++++++++++++------
1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index c6c37e25e4c8..af2df4adfa85 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2118,29 +2118,42 @@ static void rtw8922d_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
enum rtw89_rf_path path,
enum rtw89_phy_idx phy_idx)
{
-#define DIGITAL_PWR_COMP_REG_NUM 22
+#define DIGITAL_PWR_COMP_BASE_NUM 7
+#define DIGITAL_PWR_COMP_VALS_NUM 15
static const u32 pw_comp_cr[2] = {R_RX_PATH0_TBL0_BE4, R_RX_PATH1_TBL0_BE4};
- const __le32 (*pwr_comp_val)[2][RTW89_TX_COMP_BAND_NR]
- [BB_PATH_NUM_8922D][DIGITAL_PWR_COMP_REG_NUM];
+ const struct {
+ struct {
+ __le32 base[DIGITAL_PWR_COMP_BASE_NUM];
+ __le32 vals[DIGITAL_PWR_COMP_VALS_NUM];
+ } sets[2][RTW89_TX_COMP_BAND_NR][BB_PATH_NUM_8922D];
+ } *pwr_comp_v0;
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
const struct rtw89_fw_element_hdr *txcomp_elm = elm_info->tx_comp;
- const __le32 *digital_pwr_comp;
+ const __le32 (*comp_base)[DIGITAL_PWR_COMP_BASE_NUM];
+ const __le32 (*comp_vals)[DIGITAL_PWR_COMP_VALS_NUM];
u32 addr, val;
u32 i;
- if (sizeof(*pwr_comp_val) != le32_to_cpu(txcomp_elm->size)) {
+ if (sizeof(*pwr_comp_v0) == le32_to_cpu(txcomp_elm->size)) {
+ pwr_comp_v0 = (const void *)txcomp_elm->u.common.contents;
+ comp_base = &pwr_comp_v0->sets[nss][chan->tx_comp_band][path].base;
+ comp_vals = &pwr_comp_v0->sets[nss][chan->tx_comp_band][path].vals;
+ } else {
rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
"incorrect power comp size %d\n",
le32_to_cpu(txcomp_elm->size));
return;
}
- pwr_comp_val = (const void *)txcomp_elm->u.common.contents;
- digital_pwr_comp = (*pwr_comp_val)[nss][chan->tx_comp_band][path];
addr = pw_comp_cr[path];
- for (i = 0; i < DIGITAL_PWR_COMP_REG_NUM; i++, addr += 4) {
- val = le32_to_cpu(digital_pwr_comp[i]);
+ for (i = 0; i < ARRAY_SIZE(*comp_base); i++, addr += 4) {
+ val = le32_to_cpu((*comp_base)[i]);
+ rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(*comp_vals); i++, addr += 4) {
+ val = le32_to_cpu((*comp_vals)[i]);
rtw89_phy_write32_idx(rtwdev, addr, MASKDWORD, val, phy_idx);
}
}
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH rtw-next 3/7] wifi: rtw89: 8922d: support new digital power compensation format
2026-05-20 12:38 [PATCH rtw-next 0/7] wifi: rtw89: update firmware elements formats of power track, compensation and MRU Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 1/7] wifi: rtw89: fw: load TX power track element according to AID Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 2/7] wifi: rtw89: 8922d: refactor digital power compensation to support new format Ping-Ke Shih
@ 2026-05-20 12:38 ` Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 4/7] wifi: rtw89: fw: load TX compensation element by RFE type Ping-Ke Shih
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
To: linux-wireless; +Cc: kevin_yang
The new format shared the base set (7 elements). As there are total 40
sets, save 7 * 39 elements.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index af2df4adfa85..18af9211c2df 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2127,6 +2127,12 @@ static void rtw8922d_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
__le32 vals[DIGITAL_PWR_COMP_VALS_NUM];
} sets[2][RTW89_TX_COMP_BAND_NR][BB_PATH_NUM_8922D];
} *pwr_comp_v0;
+ const struct {
+ __le32 base[DIGITAL_PWR_COMP_BASE_NUM];
+ struct {
+ __le32 vals[DIGITAL_PWR_COMP_VALS_NUM];
+ } sets[2][RTW89_TX_COMP_BAND_NR][BB_PATH_NUM_8922D];
+ } *pwr_comp;
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
const struct rtw89_fw_element_hdr *txcomp_elm = elm_info->tx_comp;
const __le32 (*comp_base)[DIGITAL_PWR_COMP_BASE_NUM];
@@ -2134,7 +2140,11 @@ static void rtw8922d_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
u32 addr, val;
u32 i;
- if (sizeof(*pwr_comp_v0) == le32_to_cpu(txcomp_elm->size)) {
+ if (sizeof(*pwr_comp) == le32_to_cpu(txcomp_elm->size)) {
+ pwr_comp = (const void *)txcomp_elm->u.common.contents;
+ comp_base = &pwr_comp->base;
+ comp_vals = &pwr_comp->sets[nss][chan->tx_comp_band][path].vals;
+ } else if (sizeof(*pwr_comp_v0) == le32_to_cpu(txcomp_elm->size)) {
pwr_comp_v0 = (const void *)txcomp_elm->u.common.contents;
comp_base = &pwr_comp_v0->sets[nss][chan->tx_comp_band][path].base;
comp_vals = &pwr_comp_v0->sets[nss][chan->tx_comp_band][path].vals;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH rtw-next 4/7] wifi: rtw89: fw: load TX compensation element by RFE type
2026-05-20 12:38 [PATCH rtw-next 0/7] wifi: rtw89: update firmware elements formats of power track, compensation and MRU Ping-Ke Shih
` (2 preceding siblings ...)
2026-05-20 12:38 ` [PATCH rtw-next 3/7] wifi: rtw89: 8922d: support new digital power compensation format Ping-Ke Shih
@ 2026-05-20 12:38 ` Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 5/7] wifi: rtw89: Wi-Fi 7 configure TX power limit for large MRU Ping-Ke Shih
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
To: linux-wireless; +Cc: kevin_yang
Originally driver uses TX compensation element by AID, and now tables are
by RFE type. Add the logic accordingly.
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/fw.c | 6 ++++++
drivers/net/wireless/realtek/rtw89/fw.h | 5 +++++
2 files changed, 11 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 5d0b3ba9a358..47649079d7b5 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -1423,12 +1423,18 @@ int rtw89_build_tx_comp_from_elm(struct rtw89_dev *rtwdev,
const union rtw89_fw_element_arg arg)
{
struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
+ struct rtw89_efuse *efuse = &rtwdev->efuse;
struct rtw89_hal *hal = &rtwdev->hal;
+ u8 rfe_type;
u16 aid;
aid = le16_to_cpu(elm->aid);
+ rfe_type = elm->u.tx_comp.rfe_type;
+
if (aid && aid != hal->aid)
return 1; /* ignore if aid not matched */
+ else if (rfe_type && rfe_type != efuse->rfe_type)
+ return 1; /* ignore if rfe_type not matched */
else if (elm_info->tx_comp)
return 1; /* ignore if an element is existing */
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index cde8fd34723b..20721d5209aa 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -4548,6 +4548,11 @@ struct rtw89_fw_element_hdr {
u8 rsvd[4];
u8 rules_and_msgs[];
} __packed diag_mac;
+ struct {
+ u8 rfe_type;
+ u8 priv[7];
+ u8 contents[];
+ } __packed tx_comp;
struct __rtw89_fw_txpwr_element txpwr;
struct __rtw89_fw_regd_element regd;
} __packed u;
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH rtw-next 5/7] wifi: rtw89: Wi-Fi 7 configure TX power limit for large MRU
2026-05-20 12:38 [PATCH rtw-next 0/7] wifi: rtw89: update firmware elements formats of power track, compensation and MRU Ping-Ke Shih
` (3 preceding siblings ...)
2026-05-20 12:38 ` [PATCH rtw-next 4/7] wifi: rtw89: fw: load TX compensation element by RFE type Ping-Ke Shih
@ 2026-05-20 12:38 ` Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 6/7] wifi: rtw89: debug: show large MRU in txpwr_table dbgfs Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 7/7] wifi: rtw89: 8922d: configure TX shape settings Ping-Ke Shih
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
To: linux-wireless; +Cc: kevin_yang
From: Zong-Zhe Yang <kevin_yang@realtek.com>
Support of Large MRU (Multiple Resource Unit) starts from RTL8922D_CID7090,
i.e. RTL8922A and RTL8922D-VS variant do not support it. There are the new
corresponding control registers. So, configure them.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/core.h | 3 +
drivers/net/wireless/realtek/rtw89/phy.h | 10 ++
drivers/net/wireless/realtek/rtw89/phy_be.c | 163 ++++++++++++++++++++
drivers/net/wireless/realtek/rtw89/reg.h | 9 ++
4 files changed, 185 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 4666e3041ef3..17f9a61686b7 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -998,6 +998,9 @@ enum rtw89_ru_bandwidth {
RTW89_RU106 = 2,
RTW89_RU52_26 = 3,
RTW89_RU106_26 = 4,
+ RTW89_RU484_242 = 5,
+ RTW89_RU996_484 = 6,
+ RTW89_RU996_484_242 = 7,
RTW89_RU_NUM,
};
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 5af66656d0b8..532232892831 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -568,6 +568,16 @@ struct rtw89_txpwr_limit_ru_be {
s8 ru106_26[RTW89_RU_SEC_NUM_BE];
};
+#define RTW89_RU484_242_SEC_NUM_BE 4
+#define RTW89_RU996_484_SEC_NUM_BE 2
+#define RTW89_RU996_484_242_SEC_NUM_BE 2
+
+struct rtw89_txpwr_limit_large_mru_be {
+ s8 ru484_242[RTW89_NSS_NUM][RTW89_RU484_242_SEC_NUM_BE];
+ s8 ru996_484[RTW89_NSS_NUM][RTW89_RU996_484_SEC_NUM_BE];
+ s8 ru996_484_242[RTW89_NSS_NUM][RTW89_RU996_484_242_SEC_NUM_BE];
+};
+
struct rtw89_phy_rfk_log_fmt {
const struct rtw89_fw_element_hdr *elm[RTW89_PHY_C2H_RFK_LOG_FUNC_NUM];
};
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index d0a6dfdbfea7..99263355e2f1 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -1699,11 +1699,168 @@ static void rtw89_phy_fill_limit_ru_be(struct rtw89_dev *rtwdev,
}
}
+static
+void rtw89_phy_fill_limit_ru484_242_be(struct rtw89_dev *rtwdev,
+ s8 (*lmt)[RTW89_RU484_242_SEC_NUM_BE],
+ u8 ntx, u8 band, u8 ch, u8 bw)
+{
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_80:
+ (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU484_242,
+ ntx, ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_160:
+ (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU484_242,
+ ntx, ch - 8);
+ (*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU484_242,
+ ntx, ch + 8);
+ break;
+ case RTW89_CHANNEL_WIDTH_320:
+ (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU484_242,
+ ntx, ch - 24);
+ (*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU484_242,
+ ntx, ch - 8);
+ (*lmt)[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU484_242,
+ ntx, ch + 8);
+ (*lmt)[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU484_242,
+ ntx, ch + 24);
+ break;
+ }
+}
+
+static
+void rtw89_phy_fill_limit_ru996_484_be(struct rtw89_dev *rtwdev,
+ s8 (*lmt)[RTW89_RU996_484_SEC_NUM_BE],
+ u8 ntx, u8 band, u8 ch, u8 bw)
+{
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_160:
+ (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU996_484,
+ ntx, ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_320:
+ (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU996_484,
+ ntx, ch - 16);
+ (*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU996_484,
+ ntx, ch + 16);
+ break;
+ }
+}
+
+static
+void rtw89_phy_fill_limit_ru996_484_242_be(struct rtw89_dev *rtwdev,
+ s8 (*lmt)[RTW89_RU996_484_242_SEC_NUM_BE],
+ u8 ntx, u8 band, u8 ch, u8 bw)
+{
+ switch (bw) {
+ case RTW89_CHANNEL_WIDTH_160:
+ (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU996_484_242,
+ ntx, ch);
+ break;
+ case RTW89_CHANNEL_WIDTH_320:
+ (*lmt)[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU996_484_242,
+ ntx, ch - 16);
+ (*lmt)[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+ RTW89_RU996_484_242,
+ ntx, ch + 16);
+ break;
+ }
+}
+
+static
+void rtw89_phy_fill_limit_large_mru_be(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ struct rtw89_txpwr_limit_large_mru_be *lmt,
+ bool has_bf)
+{
+ u8 band = chan->band_type;
+ u8 ch = chan->channel;
+ u8 bw = chan->band_width;
+ int i;
+
+ memset(lmt, 0, sizeof(*lmt));
+
+ if (has_bf)
+ return;
+
+ for (i = 0; i <= RTW89_NSS_2; i++) {
+ rtw89_phy_fill_limit_ru484_242_be(rtwdev, &lmt->ru484_242[i],
+ i, band, ch, bw);
+ rtw89_phy_fill_limit_ru996_484_be(rtwdev, &lmt->ru996_484[i],
+ i, band, ch, bw);
+ rtw89_phy_fill_limit_ru996_484_242_be(rtwdev, &lmt->ru996_484_242[i],
+ i, band, ch, bw);
+ }
+}
+
+static
+void rtw89_phy_conf_limit_large_mru_be(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx,
+ bool has_bf)
+{
+ struct rtw89_txpwr_limit_large_mru_be lmt_lmru;
+ u32 addr, val;
+
+ rtw89_phy_fill_limit_large_mru_be(rtwdev, chan, &lmt_lmru, has_bf);
+
+ addr = has_bf ? R_BE_TXAGC_MAX_1TX_BF_RU484_242_0 :
+ R_BE_TXAGC_MAX_1TX_RU484_242_0;
+
+ val = u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][0], GENMASK(7, 0)) |
+ u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][1], GENMASK(15, 8)) |
+ u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][2], GENMASK(23, 16)) |
+ u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_1][3], GENMASK(31, 24));
+
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
+
+ val = u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][0], GENMASK(7, 0)) |
+ u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][1], GENMASK(15, 8)) |
+ u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][2], GENMASK(23, 16)) |
+ u32_encode_bits(lmt_lmru.ru484_242[RTW89_NSS_2][3], GENMASK(31, 24));
+
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr + 4, val);
+
+ addr = has_bf ? R_BE_TXAGC_MAX_1TX_BF_RU996_484_0 :
+ R_BE_TXAGC_MAX_1TX_RU996_484_0;
+
+ val = u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_1][0], GENMASK(7, 0)) |
+ u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_1][1], GENMASK(15, 8)) |
+ u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_2][0], GENMASK(23, 16)) |
+ u32_encode_bits(lmt_lmru.ru996_484[RTW89_NSS_2][1], GENMASK(31, 24));
+
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
+
+ addr = has_bf ? R_BE_TXAGC_MAX_1TX_BF_RU996_484_242_0 :
+ R_BE_TXAGC_MAX_1TX_RU996_484_242_0;
+
+ val = u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_1][0], GENMASK(7, 0)) |
+ u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_1][1], GENMASK(15, 8)) |
+ u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_2][0], GENMASK(23, 16)) |
+ u32_encode_bits(lmt_lmru.ru996_484_242[RTW89_NSS_2][1], GENMASK(31, 24));
+
+ rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
+}
+
static void rtw89_phy_set_txpwr_limit_ru_be(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
struct rtw89_txpwr_limit_ru_be lmt_ru;
+ struct rtw89_hal *hal = &rtwdev->hal;
const s8 *ptr;
u32 addr, val;
u8 i, j;
@@ -1730,6 +1887,12 @@ static void rtw89_phy_set_txpwr_limit_ru_be(struct rtw89_dev *rtwdev,
rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
}
}
+
+ if (!(chip->chip_id == RTL8922D && hal->cid == RTL8922D_CID7090))
+ return;
+
+ rtw89_phy_conf_limit_large_mru_be(rtwdev, chan, phy_idx, false);
+ rtw89_phy_conf_limit_large_mru_be(rtwdev, chan, phy_idx, true);
}
const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index c9bfb163c32e..c0279e9e9bed 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -8358,6 +8358,11 @@
#define R_BE_PWR_LISTEN_PATH 0x11988
#define B_BE_PWR_LISTEN_PATH_EN GENMASK(31, 28)
+#define R_BE_TXAGC_MAX_1TX_RU484_242_0 0x11990
+#define R_BE_TXAGC_MAX_1TX_RU996_484_0 0x119A4
+#define R_BE_TXAGC_MAX_1TX_RU996_484_242_0 0x119AC
+#define R_BE_TXAGC_MAX_1TX_BF_RU484_242_0 0x119DC
+
#define R_BE_PWR_REF_CTRL 0x11A20
#define B_BE_PWR_REF_CTRL_OFDM GENMASK(9, 1)
#define B_BE_PWR_REF_CTRL_CCK GENMASK(18, 10)
@@ -8395,6 +8400,8 @@
B_BE_PWR_FORCE_MACID_EN_VAL | \
B_BE_PWR_FORCE_MACID_EN_ON)
+#define R_BE_TXAGC_MAX_1TX_BF_RU996_484_0 0x11A4C
+
#define R_BE_PWR_REG_CTRL 0x11A50
#define B_BE_PWR_BT_EN BIT(23)
@@ -8408,6 +8415,8 @@
#define R_BE_PWR_TH 0x11A78
#define R_BE_PWR_RSSI_TARGET_LMT 0x11A84
+#define R_BE_TXAGC_MAX_1TX_BF_RU996_484_242_0 0x11ADC
+
#define R_BE_PWR_OFST_SW 0x11AE8
#define B_BE_PWR_OFST_SW_DB GENMASK(27, 24)
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH rtw-next 6/7] wifi: rtw89: debug: show large MRU in txpwr_table dbgfs
2026-05-20 12:38 [PATCH rtw-next 0/7] wifi: rtw89: update firmware elements formats of power track, compensation and MRU Ping-Ke Shih
` (4 preceding siblings ...)
2026-05-20 12:38 ` [PATCH rtw-next 5/7] wifi: rtw89: Wi-Fi 7 configure TX power limit for large MRU Ping-Ke Shih
@ 2026-05-20 12:38 ` Ping-Ke Shih
2026-05-20 12:38 ` [PATCH rtw-next 7/7] wifi: rtw89: 8922d: configure TX shape settings Ping-Ke Shih
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
To: linux-wireless; +Cc: kevin_yang
From: Zong-Zhe Yang <kevin_yang@realtek.com>
Read and print the CR settings of large MRU.
For now, only RTL8922D_CID7090 support it.
For example,
[TX power limit_large_mru]
RU484_242 1TX - IDX_0 IDX_1 IDX_2 IDX_3 | 17, 0, 0, 0, dBm
RU484_242 2TX - IDX_0 IDX_1 IDX_2 IDX_3 | 16, 0, 0, 0, dBm
RU996_484 1TX - IDX_0 IDX_1 | 0, 0, dBm
RU996_484 2TX - IDX_0 IDX_1 | 0, 0, dBm
RU996_484_242 1TX - IDX_0 IDX_1 | 0, 0, dBm
RU996_484_242 2TX - IDX_0 IDX_1 | 0, 0, dBm
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/debug.c | 76 ++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 8ee800c76cfe..eb9106932187 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -767,6 +767,45 @@ static const struct txpwr_map __txpwr_map_lmt_ru_be = {
.addr_to_1ss = 0, /* not support */
};
+static const struct txpwr_ent __txpwr_ent_lmt_ru484_242_be[] = {
+ __GEN_TXPWR_ENT4("RU484_242 1TX ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 "),
+ __GEN_TXPWR_ENT4("RU484_242 2TX ", "IDX_0 ", "IDX_1 ", "IDX_2 ", "IDX_3 "),
+};
+
+static const struct txpwr_map __txpwr_map_lmt_ru484_242_be = {
+ .ent = __txpwr_ent_lmt_ru484_242_be,
+ .size = ARRAY_SIZE(__txpwr_ent_lmt_ru484_242_be),
+ .addr_from = R_BE_TXAGC_MAX_1TX_RU484_242_0,
+ .addr_to = R_BE_TXAGC_MAX_1TX_RU484_242_0 + 4,
+ .addr_to_1ss = 0, /* not support */
+};
+
+static const struct txpwr_ent __txpwr_ent_lmt_ru996_484_be[] = {
+ __GEN_TXPWR_ENT2("RU996_484 1TX ", "IDX_0 ", "IDX_1 "),
+ __GEN_TXPWR_ENT2("RU996_484 2TX ", "IDX_0 ", "IDX_1 "),
+};
+
+static const struct txpwr_map __txpwr_map_lmt_ru996_484_be = {
+ .ent = __txpwr_ent_lmt_ru996_484_be,
+ .size = ARRAY_SIZE(__txpwr_ent_lmt_ru996_484_be),
+ .addr_from = R_BE_TXAGC_MAX_1TX_RU996_484_0,
+ .addr_to = R_BE_TXAGC_MAX_1TX_RU996_484_0,
+ .addr_to_1ss = 0, /* not support */
+};
+
+static const struct txpwr_ent __txpwr_ent_lmt_ru996_484_242_be[] = {
+ __GEN_TXPWR_ENT2("RU996_484_242 1TX ", "IDX_0 ", "IDX_1 "),
+ __GEN_TXPWR_ENT2("RU996_484_242 2TX ", "IDX_0 ", "IDX_1 "),
+};
+
+static const struct txpwr_map __txpwr_map_lmt_ru996_484_242_be = {
+ .ent = __txpwr_ent_lmt_ru996_484_242_be,
+ .size = ARRAY_SIZE(__txpwr_ent_lmt_ru996_484_242_be),
+ .addr_from = R_BE_TXAGC_MAX_1TX_RU996_484_242_0,
+ .addr_to = R_BE_TXAGC_MAX_1TX_RU996_484_242_0,
+ .addr_to_1ss = 0, /* not support */
+};
+
static unsigned int
__print_txpwr_ent(char *buf, size_t bufsz, const struct txpwr_ent *ent,
const s8 *bufp, const unsigned int cur, unsigned int *ate)
@@ -882,6 +921,9 @@ struct dbgfs_txpwr_table {
const struct txpwr_map *byr;
const struct txpwr_map *lmt;
const struct txpwr_map *lmt_ru;
+ const struct txpwr_map *lmt_ru484_242;
+ const struct txpwr_map *lmt_ru996_484;
+ const struct txpwr_map *lmt_ru996_484_242;
};
static const struct dbgfs_txpwr_table dbgfs_txpwr_table_ax = {
@@ -894,6 +936,9 @@ static const struct dbgfs_txpwr_table dbgfs_txpwr_table_be = {
.byr = &__txpwr_map_byr_be,
.lmt = &__txpwr_map_lmt_be,
.lmt_ru = &__txpwr_map_lmt_ru_be,
+ .lmt_ru484_242 = &__txpwr_map_lmt_ru484_242_be,
+ .lmt_ru996_484 = &__txpwr_map_lmt_ru996_484_be,
+ .lmt_ru996_484_242 = &__txpwr_map_lmt_ru996_484_242_be,
};
static const struct dbgfs_txpwr_table *dbgfs_txpwr_tables[RTW89_CHIP_GEN_NUM] = {
@@ -934,6 +979,8 @@ ssize_t rtw89_debug_priv_txpwr_table_get(struct rtw89_dev *rtwdev,
char *buf, size_t bufsz)
{
enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_hal *hal = &rtwdev->hal;
struct rtw89_sar_parm sar_parm = {};
const struct dbgfs_txpwr_table *tbl;
const struct rtw89_chan *chan;
@@ -979,6 +1026,35 @@ ssize_t rtw89_debug_priv_txpwr_table_get(struct rtw89_dev *rtwdev,
return n;
p += n;
+ switch (chip_gen) {
+ case RTW89_CHIP_AX:
+ goto out;
+ case RTW89_CHIP_BE:
+ if (!(chip->chip_id == RTL8922D && hal->cid == RTL8922D_CID7090))
+ goto out;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ p += scnprintf(p, end - p, "\n[TX power limit_large_mru]\n");
+
+ n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt_ru484_242);
+ if (n < 0)
+ return n;
+ p += n;
+
+ n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt_ru996_484);
+ if (n < 0)
+ return n;
+ p += n;
+
+ n = __print_txpwr_map(rtwdev, p, end - p, tbl->lmt_ru996_484_242);
+ if (n < 0)
+ return n;
+ p += n;
+
+out:
return p - buf;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH rtw-next 7/7] wifi: rtw89: 8922d: configure TX shape settings
2026-05-20 12:38 [PATCH rtw-next 0/7] wifi: rtw89: update firmware elements formats of power track, compensation and MRU Ping-Ke Shih
` (5 preceding siblings ...)
2026-05-20 12:38 ` [PATCH rtw-next 6/7] wifi: rtw89: debug: show large MRU in txpwr_table dbgfs Ping-Ke Shih
@ 2026-05-20 12:38 ` Ping-Ke Shih
6 siblings, 0 replies; 9+ messages in thread
From: Ping-Ke Shih @ 2026-05-20 12:38 UTC (permalink / raw)
To: linux-wireless; +Cc: kevin_yang
From: Zong-Zhe Yang <kevin_yang@realtek.com>
By default, BB enables triangular spectrum by a series of register
settings. According to band and regulation, RF parameters determine whether
TX shape needs to be restricted or not. So now, clear the corresponding
settings if it has no need to do.
Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
drivers/net/wireless/realtek/rtw89/reg.h | 4 ++
drivers/net/wireless/realtek/rtw89/rtw8922d.c | 61 +++++++++++++++++++
2 files changed, 65 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index c0279e9e9bed..b704d3251e97 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -10622,6 +10622,8 @@
#define R_RFSI_CT_OPT_0_BE4 0x11A94
#define R_RFSI_CT_OPT_8_BE4 0x11A98
#define R_QAM_COMP_TH0_BE4 0x11A9C
+#define B_QAM_COMP_TH_TRIANGULAR_L GENMASK(11, 10)
+#define B_QAM_COMP_TH_TRIANGULAR_H GENMASK(27, 26)
#define R_QAM_COMP_TH1_BE4 0x11AA0
#define R_QAM_COMP_TH2_BE4 0x11AA4
#define R_QAM_COMP_TH3_BE4 0x11AA8
@@ -10645,6 +10647,8 @@
#define B_QAM_COMP_TH6_2L GENMASK(9, 5)
#define B_QAM_COMP_TH6_2M GENMASK(19, 15)
#define R_OW_VAL_0_BE4 0x11AAC
+#define B_OW_VAL_TRIANGULAR_L GENMASK(11, 10)
+#define B_OW_VAL_TRIANGULAR_H GENMASK(27, 26)
#define R_OW_VAL_1_BE4 0x11AB0
#define R_OW_VAL_2_BE4 0x11AB4
#define R_OW_VAL_3_BE4 0x11AB8
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 18af9211c2df..c38a38856398 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2680,6 +2680,66 @@ static void rtw8922d_set_txpwr_ref(struct rtw89_dev *rtwdev,
B_BE_PWR_REF_CTRL_CCK, ref_cck);
}
+static void rtw8922d_set_tx_shape(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ const struct rtw89_bb_wrap_data *d = rtwdev->phy_info.bb_wrap_data;
+ const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
+ const struct rtw89_tx_shape *tx_shape = &rfe_parms->tx_shape;
+ u8 tx_shape_idx;
+ u8 band, regd;
+ const u16 *th;
+
+ band = chan->band_type;
+ regd = rtw89_regd_get(rtwdev, band);
+ tx_shape_idx = (*tx_shape->lmt)[band][RTW89_RS_OFDM][regd];
+
+ if (tx_shape_idx == 0)
+ goto disable;
+
+ th = d->bands[chan->rfsi_band].qam_comp_th0;
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKLWORD, th[0], phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, MASKHWORD, th[1], phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKLWORD, th[2], phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, MASKHWORD, th[3], phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKLWORD, th[4], phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, MASKHWORD, th[5], phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKLWORD, th[6], phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, MASKHWORD, th[7], phy_idx);
+
+ th = d->bands[chan->rfsi_band].qam_comp_ow;
+ rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKLWORD, th[0], phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, MASKHWORD, th[1], phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKLWORD, th[2], phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, MASKHWORD, th[3], phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKLWORD, th[4], phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, MASKHWORD, th[5], phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKLWORD, th[6], phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, MASKHWORD, th[7], phy_idx);
+
+ return;
+
+disable:
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, B_QAM_COMP_TH_TRIANGULAR_L, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH0_BE4, B_QAM_COMP_TH_TRIANGULAR_H, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, B_QAM_COMP_TH_TRIANGULAR_L, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH1_BE4, B_QAM_COMP_TH_TRIANGULAR_H, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, B_QAM_COMP_TH_TRIANGULAR_L, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH2_BE4, B_QAM_COMP_TH_TRIANGULAR_H, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, B_QAM_COMP_TH_TRIANGULAR_L, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_QAM_COMP_TH3_BE4, B_QAM_COMP_TH_TRIANGULAR_H, 0, phy_idx);
+
+ rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, B_OW_VAL_TRIANGULAR_L, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_0_BE4, B_OW_VAL_TRIANGULAR_H, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, B_OW_VAL_TRIANGULAR_L, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_1_BE4, B_OW_VAL_TRIANGULAR_H, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, B_OW_VAL_TRIANGULAR_L, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_2_BE4, B_OW_VAL_TRIANGULAR_H, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, B_OW_VAL_TRIANGULAR_L, 0, phy_idx);
+ rtw89_write32_idx(rtwdev, R_OW_VAL_3_BE4, B_OW_VAL_TRIANGULAR_H, 0, phy_idx);
+}
+
static void rtw8922d_set_txpwr_sar_diff(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
@@ -2711,6 +2771,7 @@ static void rtw8922d_set_txpwr(struct rtw89_dev *rtwdev,
{
rtw89_phy_set_txpwr_byrate(rtwdev, chan, phy_idx);
rtw89_phy_set_txpwr_offset(rtwdev, chan, phy_idx);
+ rtw8922d_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);
rtw8922d_set_txpwr_ref(rtwdev, chan, phy_idx);
--
2.25.1
^ permalink raw reply related [flat|nested] 9+ messages in thread