Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D
@ 2026-07-07  9:10 Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 01/15] wifi: rtw89: 8922d: remove CCK bandwidth compensation Ping-Ke Shih
                   ` (14 more replies)
  0 siblings, 15 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

First 5 patches and patch 11 and 13 are related to PHY settings to
improve PHY performance.

Patches 6-9 are main change to support voltage thermal protection, which
adjusts voltage according to thermal value to reduce power consumption.

Patch 10 is to adjust hardware clock for ANA circuit.

Patch 12 is a improvement of RTL8852A.

Since we have prepared firmware containing BB/RF parameters and etc, notify
users that we are going to remove built-in tables of BB/RF parameters from
driver. Patches 14-15 are to add transition state to notify users to update
their old firmware. Currently users can still use old firmware, and we plan
to remove built-in tables years later.

Chih-Kang Chang (1):
  wifi: rtw89: 8852a: fix RSSI report when average beacon RSSI is not
    ready

Eric Huang (4):
  wifi: rtw89: 8922d: remove CCK bandwidth compensation
  wifi: rtw89: 8922d: dynamic adjust channel smoothing
  wifi: rtw89: 8922d: fix EMLSR BB switch sequence for MLO mode
    transition
  wifi: rtw89: phy: fix bandedge primary channel for 2.4GHz 40MHz and
    6GHz

Ping-Ke Shih (10):
  wifi: rtw89: 8922d: set TX compensation by format v2
  wifi: rtw89: efuse: no need to export rtw89_efuse_read_ecv_be()
  wifi: rtw89: efuse: read thermal calibration value for RTL8922D
  wifi: rtw89: 8922d: read default digital voltage calibration values
  wifi: rtw89: add thermal protect by digital voltage reduction
  wifi: rtw89: 8922d: set ANA CLK enter to 500KHz
  wifi: rtw89: 8922d: update scaling factor for RX path
  wifi: rtw89: phy: add NCTL check for WiFi 7 chips
  wifi: rtw89: unify access struct of TX power track tables
  wifi: rtw89: set needed firmware elements for early chips transition

 drivers/net/wireless/realtek/rtw89/core.c     |  17 ++
 drivers/net/wireless/realtek/rtw89/core.h     |  34 +++
 drivers/net/wireless/realtek/rtw89/debug.c    |   1 +
 drivers/net/wireless/realtek/rtw89/efuse.h    |   7 +
 drivers/net/wireless/realtek/rtw89/efuse_be.c | 117 ++++++++++-
 drivers/net/wireless/realtek/rtw89/fw.c       |  10 +
 drivers/net/wireless/realtek/rtw89/fw.h       |  27 ++-
 drivers/net/wireless/realtek/rtw89/mac.c      |   7 +
 drivers/net/wireless/realtek/rtw89/mac.h      |  47 +++++
 drivers/net/wireless/realtek/rtw89/mac_be.c   |  40 ++++
 drivers/net/wireless/realtek/rtw89/phy.c      |  33 +++
 drivers/net/wireless/realtek/rtw89/phy.h      |  25 +--
 drivers/net/wireless/realtek/rtw89/phy_be.c   |  45 +++-
 drivers/net/wireless/realtek/rtw89/reg.h      |  53 +++++
 drivers/net/wireless/realtek/rtw89/rtw8851b.c |   4 +-
 .../net/wireless/realtek/rtw89/rtw8851b_rfk.c |  20 +-
 .../wireless/realtek/rtw89/rtw8851b_table.c   |  15 +-
 .../wireless/realtek/rtw89/rtw8851b_table.h   |   2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |   6 +-
 .../net/wireless/realtek/rtw89/rtw8852a_rfk.c |  36 ++--
 .../wireless/realtek/rtw89/rtw8852a_table.c   |  27 +--
 .../wireless/realtek/rtw89/rtw8852a_table.h   |   2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |   4 +-
 .../net/wireless/realtek/rtw89/rtw8852b_rfk.c |  36 ++--
 .../wireless/realtek/rtw89/rtw8852b_table.c   |  27 +--
 .../wireless/realtek/rtw89/rtw8852b_table.h   |   2 +-
 .../net/wireless/realtek/rtw89/rtw8852bt.c    |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |   4 +-
 .../net/wireless/realtek/rtw89/rtw8852c_rfk.c | 101 ++++-----
 .../wireless/realtek/rtw89/rtw8852c_table.c   |  35 ++--
 .../wireless/realtek/rtw89/rtw8852c_table.h   |   2 +-
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |   1 +
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 196 ++++++++++++++----
 33 files changed, 750 insertions(+), 234 deletions(-)


base-commit: 2b7858891b100587c10c136cf07205335a897be0
-- 
2.25.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 01/15] wifi: rtw89: 8922d: remove CCK bandwidth compensation
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-12  1:55   ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 02/15] wifi: rtw89: 8922d: dynamic adjust channel smoothing Ping-Ke Shih
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

From: Eric Huang <echuang@realtek.com>

Remove the 40MHz bandwidth compensation from CCK efuse gain calculation.
The design no longer requires the +3dB compensation for 40MHz channels.

Signed-off-by: Eric Huang <echuang@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index f78d6d46e65f..625f8d675f08 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -1634,10 +1634,6 @@ static void rtw8922d_calc_rx_gain_normal_cck(struct rtw89_dev *rtwdev,
 	s8 rx_gain_offset;
 
 	rx_gain_offset = -rtw8922d_get_rx_gain_by_chan(rtwdev, chan, path, true);
-
-	if (chan->band_width == RTW89_CHANNEL_WIDTH_40)
-		rx_gain_offset += (3 << 2); /* compensate RPL loss of 3dB */
-
 	calc->cck_mean_gain_bias = (rx_gain_offset & 0x3) << 1;
 	calc->cck_rpl_ofst = (rx_gain_offset >> 2) + gain->cck_rpl_base[phy_idx];
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 02/15] wifi: rtw89: 8922d: dynamic adjust channel smoothing
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 01/15] wifi: rtw89: 8922d: remove CCK bandwidth compensation Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 03/15] wifi: rtw89: 8922d: fix EMLSR BB switch sequence for MLO mode transition Ping-Ke Shih
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

From: Eric Huang <echuang@realtek.com>

Add support for path difference based channel smoothing for RTL8922D chip.
This feature measures the ratio of NDP frames and uses a moving average
filter to decide whether to enable beamforming channel smoothing. Tone
index selection is dynamically adjusted based on bandwidth and link mode
(HE/EHT vs VHT). The feature is only enabled for RTL8922D_CID7090 variant.

Signed-off-by: Eric Huang <echuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.c     |  8 +++
 drivers/net/wireless/realtek/rtw89/core.h     | 21 ++++++
 drivers/net/wireless/realtek/rtw89/phy.c      |  5 ++
 drivers/net/wireless/realtek/rtw89/reg.h      | 24 +++++++
 drivers/net/wireless/realtek/rtw89/rtw8851b.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |  1 +
 .../net/wireless/realtek/rtw89/rtw8852bt.c    |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 68 +++++++++++++++++++
 11 files changed, 132 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 26b744dfbcf8..9dbf01e82383 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -5806,6 +5806,7 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
 									 rtwsta_link);
 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
 						       rtwvif_link->chanctx_idx);
+	struct rtw89_bb_ctx *bb = rtw89_get_bb_ctx(rtwdev, rtwvif_link->phy_idx);
 	struct ieee80211_link_sta *link_sta;
 	int ret;
 
@@ -5858,6 +5859,7 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
 
 	if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
 		struct ieee80211_bss_conf *bss_conf;
+		u8 link_mode = 0;
 
 		rcu_read_lock();
 
@@ -5865,6 +5867,12 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
 		link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
 		rtwsta_link->er_cap = rtw89_sta_link_can_er(rtwdev, bss_conf, link_sta);
 
+		if (link_sta->he_cap.has_he || link_sta->eht_cap.has_eht)
+			link_mode = 2;
+		else if (link_sta->vht_cap.vht_supported)
+			link_mode = 1;
+		bb->path_diff.link_mode = link_mode;
+
 		rcu_read_unlock();
 
 		rtw89_btc_ntfy_role_info(rtwdev, rtwvif_link, rtwsta_link,
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 5dde620b1e5e..9a4d42b60bbb 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -14,6 +14,7 @@
 #include <net/mac80211.h>
 
 struct rtw89_dev;
+struct rtw89_bb_ctx;
 struct rtw89_pci_info;
 struct rtw89_usb_info;
 struct rtw89_mac_gen_def;
@@ -3948,6 +3949,8 @@ struct rtw89_chip_ops {
 				    enum rtw89_rf_path path,
 				    enum rtw89_phy_idx phy_idx,
 				    struct rtw89_phy_calc_efuse_gain *calc);
+	void (*path_diff_update)(struct rtw89_dev *rtwdev,
+				 struct rtw89_bb_ctx *bb);
 	int (*pwr_on_func)(struct rtw89_dev *rtwdev);
 	int (*pwr_off_func)(struct rtw89_dev *rtwdev);
 	void (*query_rxdesc)(struct rtw89_dev *rtwdev,
@@ -5504,6 +5507,14 @@ struct rtw89_beacon_stat {
 };
 
 DECLARE_EWMA(thermal, 4, 4);
+DECLARE_EWMA(path_diff, 4, 2);
+
+struct rtw89_phy_path_diff {
+	struct ewma_path_diff avg;
+	u8 raw;
+	bool bf_smo_en;
+	u8 link_mode;
+};
 
 #define RTW89_TX_RATE_NR 40
 struct rtw89_phy_stat {
@@ -6562,6 +6573,7 @@ struct rtw89_dev {
 		struct rtw89_pmac_stat_info pmac_stat;
 		struct rtw89_tx_stat_info tx_stat;
 		struct rtw89_diag_bb diag;
+		struct rtw89_phy_path_diff path_diff;
 	} bbs[RTW89_PHY_NUM];
 
 	struct wiphy_delayed_work track_work;
@@ -7673,6 +7685,15 @@ static inline void rtw89_chip_power_trim(struct rtw89_dev *rtwdev)
 		chip->ops->power_trim(rtwdev);
 }
 
+static inline void rtw89_chip_path_diff_update(struct rtw89_dev *rtwdev,
+					       struct rtw89_bb_ctx *bb)
+{
+	const struct rtw89_chip_info *chip = rtwdev->chip;
+
+	if (chip->ops->path_diff_update)
+		chip->ops->path_diff_update(rtwdev, bb);
+}
+
 static inline void __rtw89_chip_init_txpwr_unit(struct rtw89_dev *rtwdev,
 						enum rtw89_phy_idx phy_idx)
 {
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 759be4dab42b..981c7f02271a 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -5842,6 +5842,9 @@ static void rtw89_phy_stat_init(struct rtw89_dev *rtwdev)
 		memset(&bb->last_pkt_stat, 0, sizeof(bb->last_pkt_stat));
 
 		ewma_rssi_init(&bb->bcn_rssi);
+		bb->path_diff.raw = 0;
+		ewma_path_diff_init(&bb->path_diff.avg);
+		bb->path_diff.bf_smo_en = false;
 	}
 
 	rtwdev->hal.thermal_prot_lv = 0;
@@ -6190,6 +6193,8 @@ void rtw89_phy_stat_track(struct rtw89_dev *rtwdev)
 	rtw89_for_each_active_bb(rtwdev, bb) {
 		bb->last_pkt_stat = bb->cur_pkt_stat;
 		memset(&bb->cur_pkt_stat, 0, sizeof(bb->cur_pkt_stat));
+
+		rtw89_chip_path_diff_update(rtwdev, bb);
 	}
 }
 
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index bf1c6cb0ae9c..1ff788c24eec 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -10822,6 +10822,13 @@
 #define B_TXINFO_PATH_MB_BE4 BIT(19)
 #define R_SHAPER_COEFF_BE4 0x20CBC
 #define B_SHAPER_COEFF_BE4 BIT(19)
+
+#define R_CL_MODE_CNT_BE4 0x20DE0
+#define B_CL_MODE_NDP_CNT_PHY0_BE4 GENMASK(31, 24)
+#define B_CL_MODE_NDP_CNT_PHY1_BE4 GENMASK(15, 8)
+#define B_CL_MODE_CL_CNT_PHY0_BE4 GENMASK(23, 16)
+#define B_CL_MODE_CL_CNT_PHY1_BE4 GENMASK(7, 0)
+
 #define R_IFS_T1_AVG_BE4 0x20EDC
 #define B_IFS_T1_AVG_BE4 GENMASK(15, 0)
 #define B_IFS_T2_AVG_BE4 GENMASK(31, 16)
@@ -10940,6 +10947,14 @@
 #define R_GAIN_BIAS_BE4 0x260A0
 #define B_GAIN_BIAS_BW20_BE4 GENMASK(11, 6)
 #define B_GAIN_BIAS_BW40_BE4 GENMASK(17, 12)
+
+#define R_BF_SMO_PDP_LMT_EHT_BE4 0x26568
+#define B_BF_SMO_PDP_LMT_EHT_BE4 BIT(30)
+#define R_BF_SMO_PDP_LMT_HE_BE4 0x26568
+#define B_BF_SMO_PDP_LMT_HE_BE4 BIT(31)
+#define R_BF_SMO_PDP_LMT_VHT_BE4 0x2656C
+#define B_BF_SMO_PDP_LMT_VHT_BE4 BIT(31)
+
 #define R_AWGN_DET_BE4 0x2668C
 #define B_AWGN_DET_BE4 GENMASK(17, 9)
 #define R_CSI_WGT_BE4 0x26770
@@ -10981,6 +10996,15 @@
 #define R_BSS_CLR_VLD_BE4 0x26920
 #define B_BSS_CLR_VLD_BE4 BIT(2)
 
+#define R_CL_MODE_TRIG_BE4 0x26F44
+#define B_CL_MODE_TRIG_BE4 BIT(31)
+#define R_SELECTED_TONE_IDX_BE4 0x26F4C
+#define B_SELECTED_TONE_IDX_BE4 GENMASK(11, 0)
+#define R_OS_TRIG_BY_SW_BE4 0x26F50
+#define B_OS_TRIG_BY_SW_BE4 BIT(30)
+#define R_OS_TRIG_SOURCE_BE4 0x26F6C
+#define B_OS_TRIG_SOURCE_BE4 BIT(0)
+
 #define R_SW_SI_DATA_BE4 0x2CF4C
 #define B_SW_SI_READ_DATA_BE4 GENMASK(19, 0)
 #define B_SW_SI_W_BUSY_BE4 BIT(24)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 4caf231c6287..d0c262c3dffe 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -2580,6 +2580,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
 	.set_txpwr_ul_tb_offset	= rtw8851b_set_txpwr_ul_tb_offset,
 	.digital_pwr_comp	= NULL,
 	.calc_rx_gain_normal	= NULL,
+	.path_diff_update	= NULL,
 	.pwr_on_func		= rtw8851b_pwr_on_func,
 	.pwr_off_func		= rtw8851b_pwr_off_func,
 	.query_rxdesc		= rtw89_core_query_rxdesc,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 78addc0aef69..a5a06ae5c446 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2326,6 +2326,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
 	.set_txpwr_ul_tb_offset	= rtw8852a_set_txpwr_ul_tb_offset,
 	.digital_pwr_comp	= NULL,
 	.calc_rx_gain_normal	= NULL,
+	.path_diff_update	= NULL,
 	.pwr_on_func		= NULL,
 	.pwr_off_func		= NULL,
 	.query_rxdesc		= rtw89_core_query_rxdesc,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index debcdb2eacd6..a8638024b54a 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -907,6 +907,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
 	.set_txpwr_ul_tb_offset	= rtw8852bx_set_txpwr_ul_tb_offset,
 	.digital_pwr_comp	= NULL,
 	.calc_rx_gain_normal	= NULL,
+	.path_diff_update	= NULL,
 	.pwr_on_func		= rtw8852b_pwr_on_func,
 	.pwr_off_func		= rtw8852b_pwr_off_func,
 	.query_rxdesc		= rtw89_core_query_rxdesc,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index fc8a17fb95f4..e68f73827fa5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -753,6 +753,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = {
 	.set_txpwr_ul_tb_offset	= rtw8852bx_set_txpwr_ul_tb_offset,
 	.digital_pwr_comp	= NULL,
 	.calc_rx_gain_normal	= NULL,
+	.path_diff_update	= NULL,
 	.pwr_on_func		= rtw8852bt_pwr_on_func,
 	.pwr_off_func		= rtw8852bt_pwr_off_func,
 	.query_rxdesc		= rtw89_core_query_rxdesc,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 29a3c90021f3..52986b982ecd 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -3125,6 +3125,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
 	.set_txpwr_ul_tb_offset	= rtw8852c_set_txpwr_ul_tb_offset,
 	.digital_pwr_comp	= NULL,
 	.calc_rx_gain_normal	= NULL,
+	.path_diff_update	= NULL,
 	.pwr_on_func		= rtw8852c_pwr_on_func,
 	.pwr_off_func		= rtw8852c_pwr_off_func,
 	.query_rxdesc		= rtw89_core_query_rxdesc,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 6d4301661b04..5389c8cd07f4 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -3110,6 +3110,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
 	.set_txpwr_ul_tb_offset	= NULL,
 	.digital_pwr_comp	= rtw8922a_digital_pwr_comp,
 	.calc_rx_gain_normal	= NULL,
+	.path_diff_update	= NULL,
 	.pwr_on_func		= rtw8922a_pwr_on_func,
 	.pwr_off_func		= rtw8922a_pwr_off_func,
 	.query_rxdesc		= rtw89_core_query_rxdesc_v2,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 625f8d675f08..805dd96e61e6 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -1716,6 +1716,73 @@ static void rtw8922d_calc_rx_gain_normal(struct rtw89_dev *rtwdev,
 	rtw8922d_calc_rx_gain_normal_cck(rtwdev, chan, path, phy_idx, calc);
 }
 
+static void rtw8922d_path_diff_update(struct rtw89_dev *rtwdev,
+				      struct rtw89_bb_ctx *bb)
+{
+#define BF_SMOOTH_TH 80
+	static const u32 path_diff_cnt_mask[] = {0xff0000, 0xff};
+	static const u32 ndp_cnt_mask[] = {0xff000000, 0xff00};
+	static const u16 he_eht_sel_tone[4] = {27, 54, 56, 56};
+	static const u16 vht_sel_tone[4] = {11, 25, 25, 25};
+	struct rtw89_hal *hal = &rtwdev->hal;
+	struct rtw89_entity_conf conf;
+	const struct rtw89_chan *chan;
+	u8 phy_idx = bb->phy_idx;
+	u32 path_diff_cnt;
+	u16 sel_tone = 0;
+	bool bf_smo_lmt;
+	u32 ndp_cnt;
+
+	if (hal->cid != RTL8922D_CID7090)
+		return;
+
+	ndp_cnt = rtw89_phy_read32_mask(rtwdev, R_CL_MODE_CNT_BE4, ndp_cnt_mask[phy_idx]);
+	path_diff_cnt = rtw89_phy_read32_mask(rtwdev, R_CL_MODE_CNT_BE4,
+					      path_diff_cnt_mask[phy_idx]);
+
+	bb->path_diff.raw = clamp(phy_div(path_diff_cnt * 100, ndp_cnt), 0, 255);
+
+	if (ndp_cnt == 0)
+		ewma_path_diff_init(&bb->path_diff.avg);
+	else
+		ewma_path_diff_add(&bb->path_diff.avg, bb->path_diff.raw);
+
+	rtw89_phy_write32_mask(rtwdev, R_CL_MODE_TRIG_BE4, B_CL_MODE_TRIG_BE4, 1);
+	rtw89_phy_write32_mask(rtwdev, R_CL_MODE_TRIG_BE4, B_CL_MODE_TRIG_BE4, 0);
+
+	bf_smo_lmt = ewma_path_diff_read(&bb->path_diff.avg) < BF_SMOOTH_TH;
+	bb->path_diff.bf_smo_en = !bf_smo_lmt;
+
+	rtw89_phy_write32_mask(rtwdev, R_BF_SMO_PDP_LMT_EHT_BE4,
+			       B_BF_SMO_PDP_LMT_EHT_BE4, bf_smo_lmt);
+	rtw89_phy_write32_mask(rtwdev, R_BF_SMO_PDP_LMT_HE_BE4,
+			       B_BF_SMO_PDP_LMT_HE_BE4, bf_smo_lmt);
+	rtw89_phy_write32_mask(rtwdev, R_BF_SMO_PDP_LMT_VHT_BE4,
+			       B_BF_SMO_PDP_LMT_VHT_BE4, bf_smo_lmt);
+
+	rtw89_phy_write32_mask(rtwdev, R_OS_TRIG_BY_SW_BE4,
+			       B_OS_TRIG_BY_SW_BE4, !bf_smo_lmt);
+	rtw89_phy_write32_mask(rtwdev, R_OS_TRIG_SOURCE_BE4,
+			       B_OS_TRIG_SOURCE_BE4, !bf_smo_lmt);
+
+	rtw89_entity_get_conf(rtwdev, &conf);
+	chan = conf.chans[phy_idx];
+	if (chan->band_width <= RTW89_CHANNEL_WIDTH_160) {
+		if (bb->path_diff.link_mode >= 2)
+			sel_tone = he_eht_sel_tone[chan->band_width];
+		else if (bb->path_diff.link_mode == 1)
+			sel_tone = vht_sel_tone[chan->band_width];
+		rtw89_phy_write32_mask(rtwdev, R_SELECTED_TONE_IDX_BE4,
+				       B_SELECTED_TONE_IDX_BE4, sel_tone);
+	}
+
+	rtw89_debug(rtwdev, RTW89_DBG_PHY_TRACK,
+		    "[PATH_DIFF] raw=%d%%, ma=%ld%%, bf_smo_en=%d, tone=%d\n",
+		    bb->path_diff.raw,
+		    ewma_path_diff_read(&bb->path_diff.avg),
+		    bb->path_diff.bf_smo_en, sel_tone);
+}
+
 static void rtw8922d_set_cck_parameters(struct rtw89_dev *rtwdev,
 					const struct rtw89_chan *chan,
 					enum rtw89_phy_idx phy_idx)
@@ -3288,6 +3355,7 @@ static const struct rtw89_chip_ops rtw8922d_chip_ops = {
 	.set_txpwr_ul_tb_offset	= NULL,
 	.digital_pwr_comp	= rtw8922d_digital_pwr_comp,
 	.calc_rx_gain_normal	= rtw8922d_calc_rx_gain_normal,
+	.path_diff_update	= rtw8922d_path_diff_update,
 	.pwr_on_func		= rtw8922d_pwr_on_func,
 	.pwr_off_func		= rtw8922d_pwr_off_func,
 	.query_rxdesc		= rtw89_core_query_rxdesc_v3,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 03/15] wifi: rtw89: 8922d: fix EMLSR BB switch sequence for MLO mode transition
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 01/15] wifi: rtw89: 8922d: remove CCK bandwidth compensation Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 02/15] wifi: rtw89: 8922d: dynamic adjust channel smoothing Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 04/15] wifi: rtw89: phy: fix bandedge primary channel for 2.4GHz 40MHz and 6GHz Ping-Ke Shih
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

From: Eric Huang <echuang@realtek.com>

Assert BB reset in the intermediate "switch to 1+1" step of the EMLSR
switch sequence for all three MLO mode transitions by updating the
B_EMLSR_SWITCH_BE4 intermediate value from 0xAFFF to 0x3BAB.

Without the BB reset in this step, the baseband can be left in an
inconsistent state before settling into the final MLO configuration.

Signed-off-by: Eric Huang <echuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/reg.h      |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 45 ++++++++-----------
 2 files changed, 20 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 1ff788c24eec..3908f9729736 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -10782,6 +10782,7 @@
 #define B_SYS_DBCC_24G_BAND_SEL_BE4 BIT(1)
 #define R_EMLSR_SWITCH_BE4 0x20044
 #define B_EMLSR_SWITCH_BE4 GENMASK(27, 12)
+#define B_EMLSR_CLR_FORCE_BE4 GENMASK(20, 19)
 #define B_EMLSR_BB_CLK_BE4 GENMASK(31, 30)
 #define R_CHINFO_SEG_BE4 0x200B4
 #define B_CHINFO_SEG_LEN_BE4 GENMASK(12, 10)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 805dd96e61e6..212917db7154 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2309,17 +2309,16 @@ static void rtw8922d_digital_pwr_comp(struct rtw89_dev *rtwdev,
 	}
 }
 
-static int rtw8922d_ctrl_mlo(struct rtw89_dev *rtwdev, enum rtw89_mlo_dbcc_mode mode,
-			     bool pwr_comp)
+static void rtw8922d_ctrl_mlo_mode_core(struct rtw89_dev *rtwdev,
+					enum rtw89_mlo_dbcc_mode mode)
 {
-	u32 reg0, reg1;
-	u8 cck_phy_idx;
+	rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_CLR_FORCE_BE4, 0x3);
 
 	if (mode == MLO_2_PLUS_0_1RF) {
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xBBBB);
 		udelay(1);
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_BB_CLK_BE4, 0x3);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xAFFF);
+		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0x3BAB);
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xEBAD);
 		udelay(1);
 
@@ -2329,7 +2328,7 @@ static int rtw8922d_ctrl_mlo(struct rtw89_dev *rtwdev, enum rtw89_mlo_dbcc_mode
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xBBBB);
 		udelay(1);
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_BB_CLK_BE4, 0x3);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xAFFF);
+		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0x3BAB);
 		udelay(1);
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xEFFF);
 
@@ -2339,7 +2338,7 @@ static int rtw8922d_ctrl_mlo(struct rtw89_dev *rtwdev, enum rtw89_mlo_dbcc_mode
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xBBBB);
 		udelay(1);
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_BB_CLK_BE4, 0x3);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xAFFF);
+		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0x3BAB);
 		udelay(1);
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_BB_CLK_BE4, 0x0);
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0x3AAB);
@@ -2351,6 +2350,15 @@ static int rtw8922d_ctrl_mlo(struct rtw89_dev *rtwdev, enum rtw89_mlo_dbcc_mode
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_BB_CLK_BE4, 0x0);
 		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0x0);
 	}
+}
+
+static int rtw8922d_ctrl_mlo(struct rtw89_dev *rtwdev, enum rtw89_mlo_dbcc_mode mode,
+			     bool pwr_comp)
+{
+	u32 reg0, reg1;
+	u8 cck_phy_idx;
+
+	rtw8922d_ctrl_mlo_mode_core(rtwdev, mode);
 
 	if (pwr_comp)
 		rtw8922d_digital_pwr_comp(rtwdev, RTW89_PHY_0);
@@ -2474,25 +2482,10 @@ static void rtw8922d_pre_set_channel_bb(struct rtw89_dev *rtwdev,
 
 	rtw89_phy_write32_mask(rtwdev, R_SYS_DBCC_BE4, B_SYS_DBCC_BE4, 0x0);
 
-	if (phy_idx == RTW89_PHY_0) {
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xBBBB);
-		fsleep(1);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_BB_CLK_BE4, 0x3);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xAFFF);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xEBAD);
-		fsleep(1);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_BB_CLK_BE4, 0x0);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xEAAD);
-	} else {
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xBBBB);
-		fsleep(1);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_BB_CLK_BE4, 0x3);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xAFFF);
-		fsleep(1);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xEFFF);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_BB_CLK_BE4, 0x0);
-		rtw89_phy_write32_mask(rtwdev, R_EMLSR_SWITCH_BE4, B_EMLSR_SWITCH_BE4, 0xEEFF);
-	}
+	if (phy_idx == RTW89_PHY_0)
+		rtw8922d_ctrl_mlo_mode_core(rtwdev, MLO_2_PLUS_0_1RF);
+	else
+		rtw8922d_ctrl_mlo_mode_core(rtwdev, MLO_0_PLUS_2_1RF);
 
 	fsleep(1);
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 04/15] wifi: rtw89: phy: fix bandedge primary channel for 2.4GHz 40MHz and 6GHz
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (2 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 03/15] wifi: rtw89: 8922d: fix EMLSR BB switch sequence for MLO mode transition Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 05/15] wifi: rtw89: 8922d: set TX compensation by format v2 Ping-Ke Shih
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

From: Eric Huang <echuang@realtek.com>

Correct 2.4GHz bandwidth 40MHz bandedge check: pri_ch 5/9 instead of 3/11.
Remove stale 6GHz bandedge case; no restricted band borders 6GHz range.

Signed-off-by: Eric Huang <echuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy_be.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index 99263355e2f1..ac4ce30445b3 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -623,7 +623,7 @@ static u32 rtw89_phy_bb_wrap_be_bandedge_decision(struct rtw89_dev *rtwdev,
 	case RTW89_BAND_2G:
 		if (pri_ch == 1 || pri_ch == 13)
 			val = BIT(1) | BIT(0);
-		else if (pri_ch == 3 || pri_ch == 11)
+		else if (pri_ch == 5 || pri_ch == 9)
 			val = BIT(1);
 		break;
 	case RTW89_BAND_5G:
@@ -637,8 +637,6 @@ static u32 rtw89_phy_bb_wrap_be_bandedge_decision(struct rtw89_dev *rtwdev,
 			val = BIT(3);
 		break;
 	case RTW89_BAND_6G:
-		if (pri_ch == 233)
-			val = BIT(0);
 		break;
 	}
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 05/15] wifi: rtw89: 8922d: set TX compensation by format v2
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (3 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 04/15] wifi: rtw89: phy: fix bandedge primary channel for 2.4GHz 40MHz and 6GHz Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 06/15] wifi: rtw89: efuse: no need to export rtw89_efuse_read_ecv_be() Ping-Ke Shih
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

The total number of TX compensation registers is 22, including 7 base and
15 ones according to operating channel.

The v0 is 22 ones per channel. To reduce array size, v1 treats 7 base as
common part across all conditions. However, we can fine tune the base part
to yield better performance, so divide base into two sets according to NSS.
Summarize dimensions as follows

	base (7)		vals(15)
  v0	nss * band * path	nss * band * path
  v1	1			nss * band * path
  v2	nss			nss * band * path

Currently, v1 and v2 can present in a file, but only one fw element with
a specific format will be used for specific RFE type.

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 212917db7154..e8267173bd4c 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2249,6 +2249,12 @@ static void rtw8922d_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
 		struct {
 			__le32 vals[DIGITAL_PWR_COMP_VALS_NUM];
 		} sets[2][RTW89_TX_COMP_BAND_NR][BB_PATH_NUM_8922D];
+	} *pwr_comp_v1;
+	const struct {
+		__le32 base[2][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;
@@ -2259,8 +2265,12 @@ static void rtw8922d_set_digital_pwr_comp(struct rtw89_dev *rtwdev,
 
 	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_base = &pwr_comp->base[nss];
 		comp_vals = &pwr_comp->sets[nss][chan->tx_comp_band][path].vals;
+	} else if (sizeof(*pwr_comp_v1) == le32_to_cpu(txcomp_elm->size)) {
+		pwr_comp_v1 = (const void *)txcomp_elm->u.common.contents;
+		comp_base = &pwr_comp_v1->base;
+		comp_vals = &pwr_comp_v1->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;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 06/15] wifi: rtw89: efuse: no need to export rtw89_efuse_read_ecv_be()
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (4 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 05/15] wifi: rtw89: 8922d: set TX compensation by format v2 Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 07/15] wifi: rtw89: efuse: read thermal calibration value for RTL8922D Ping-Ke Shih
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

The consumer of rtw89_efuse_read_ecv_be() is in the same ko. No need to
export it.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/efuse_be.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/efuse_be.c b/drivers/net/wireless/realtek/rtw89/efuse_be.c
index 70c1b8be662e..a716ad54fce5 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse_be.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse_be.c
@@ -537,4 +537,3 @@ int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev)
 
 	return 0;
 }
-EXPORT_SYMBOL(rtw89_efuse_read_ecv_be);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 07/15] wifi: rtw89: efuse: read thermal calibration value for RTL8922D
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (5 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 06/15] wifi: rtw89: efuse: no need to export rtw89_efuse_read_ecv_be() Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 08/15] wifi: rtw89: 8922d: read default digital voltage calibration values Ping-Ke Shih
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

The thermal calibration value programmed in efuse is the offset to adjust
thermal value read from hardware, so that output will be accurate.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.h     |  2 ++
 drivers/net/wireless/realtek/rtw89/efuse.h    |  6 ++++
 drivers/net/wireless/realtek/rtw89/efuse_be.c | 29 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/mac.c      |  2 ++
 drivers/net/wireless/realtek/rtw89/mac.h      | 11 +++++++
 drivers/net/wireless/realtek/rtw89/mac_be.c   |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922d.c |  2 ++
 7 files changed, 53 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 9a4d42b60bbb..888a09fb2a9a 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -5884,6 +5884,8 @@ struct rtw89_power_trim_info {
 	u8 pa_bias_trim[RF_PATH_MAX];
 	u8 pad_bias_trim[RF_PATH_MAX];
 	u8 vco_trim[RF_PATH_MAX];
+
+	s16 thermal_k;
 };
 
 enum rtw89_regd_func {
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h
index a14a9dfed8e8..c6415da749a3 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.h
+++ b/drivers/net/wireless/realtek/rtw89/efuse.h
@@ -16,6 +16,11 @@
 #define EF_CV_MASK GENMASK(7, 4)
 #define EF_CV_INV 15
 
+#define EFUSE_THERMAL_K_OFFSET_BE 0x17CC
+#define EFUSE_THERMAL_K_VALID_BE BIT(9)
+#define EFUSE_THERMAL_K_SIGN_BE BIT(8)
+#define EFUSE_THERMAL_K_VAL_BE GENMASK(7, 0)
+
 struct rtw89_efuse_block_cfg {
 	u32 offset;
 	u32 size;
@@ -32,5 +37,6 @@ int rtw89_efuse_recognize_mss_info_v1(struct rtw89_dev *rtwdev, u8 b1, u8 b2);
 int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev);
 int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev);
 int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev);
+int rtw89_efuse_read_thermal_k_be(struct rtw89_dev *rtwdev);
 
 #endif
diff --git a/drivers/net/wireless/realtek/rtw89/efuse_be.c b/drivers/net/wireless/realtek/rtw89/efuse_be.c
index a716ad54fce5..67036c89883f 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse_be.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse_be.c
@@ -537,3 +537,32 @@ int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev)
 
 	return 0;
 }
+
+int rtw89_efuse_read_thermal_k_be(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
+	u32 dump_addr = EFUSE_THERMAL_K_OFFSET_BE;
+	u8 buff[4]; /* efuse access must be multiple of 4 bytes in size */
+	bool no_k;
+	u16 val16;
+	int ret;
+
+	ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false);
+	if (ret)
+		return ret;
+
+	val16 = buff[0] | buff[1] << 8;
+
+	no_k = !!u16_get_bits(val16, EFUSE_THERMAL_K_VALID_BE);
+	if (no_k) {
+		info->thermal_k = 0;
+		return -ENOENT;
+	}
+
+	info->thermal_k = u16_get_bits(val16, EFUSE_THERMAL_K_VAL_BE);
+
+	if (u16_get_bits(val16, EFUSE_THERMAL_K_SIGN_BE))
+		info->thermal_k *= -1;
+
+	return 0;
+}
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 99de1b202976..3d3f683046a7 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1558,6 +1558,7 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
 		if (!test_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags)) {
 			rtw89_mac_efuse_read_ecv(rtwdev);
 			mac->efuse_read_fw_secure(rtwdev);
+			rtw89_mac_efuse_read_thermal_k(rtwdev);
 		}
 
 		set_bit(RTW89_FLAG_POWERON, rtwdev->flags);
@@ -7500,6 +7501,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
 	.cnv_efuse_state = rtw89_cnv_efuse_state_ax,
 	.efuse_read_fw_secure = rtw89_efuse_read_fw_secure_ax,
 	.efuse_read_ecv = NULL,
+	.efuse_read_thermal_k = NULL,
 
 	.cfg_plt = rtw89_mac_cfg_plt_ax,
 	.get_plt_cnt = rtw89_mac_get_plt_cnt_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 539061fc15e8..7256d64ea07f 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -1132,6 +1132,7 @@ struct rtw89_mac_gen_def {
 	int (*cnv_efuse_state)(struct rtw89_dev *rtwdev, bool idle);
 	int (*efuse_read_fw_secure)(struct rtw89_dev *rtwdev);
 	int (*efuse_read_ecv)(struct rtw89_dev *rtwdev);
+	int (*efuse_read_thermal_k)(struct rtw89_dev *rtwdev);
 
 	int (*cfg_plt)(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt);
 	u16 (*get_plt_cnt)(struct rtw89_dev *rtwdev, u8 band);
@@ -1735,6 +1736,16 @@ static inline int rtw89_mac_efuse_read_ecv(struct rtw89_dev *rtwdev)
 	return mac->efuse_read_ecv(rtwdev);
 }
 
+static inline int rtw89_mac_efuse_read_thermal_k(struct rtw89_dev *rtwdev)
+{
+	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+	if (!mac->efuse_read_thermal_k)
+		return -ENOENT;
+
+	return mac->efuse_read_thermal_k(rtwdev);
+}
+
 static inline
 void rtw89_mac_fwdl_preconfig(struct rtw89_dev *rtwdev)
 {
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index 14f1e30066e9..077ddf4f77c5 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -3312,6 +3312,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
 	.cnv_efuse_state = rtw89_cnv_efuse_state_be,
 	.efuse_read_fw_secure = rtw89_efuse_read_fw_secure_be,
 	.efuse_read_ecv = rtw89_efuse_read_ecv_be,
+	.efuse_read_thermal_k = rtw89_efuse_read_thermal_k_be,
 
 	.cfg_plt = rtw89_mac_cfg_plt_be,
 	.get_plt_cnt = rtw89_mac_get_plt_cnt_be,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index e8267173bd4c..8b91c552a309 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -3006,6 +3006,7 @@ static void rtw8922d_bb_cfg_txrx_path(struct rtw89_dev *rtwdev)
 
 static u8 rtw8922d_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path)
 {
+	struct rtw89_power_trim_info *info = &rtwdev->pwr_trim;
 	u8 val;
 
 	rtw89_phy_write32_mask(rtwdev, R_TC_EN_BE4, B_TC_EN_BE4, 0x1);
@@ -3015,6 +3016,7 @@ static u8 rtw8922d_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_p
 	fsleep(100);
 
 	val = rtw89_phy_read32_mask(rtwdev, R_TC_VAL_BE4, B_TC_VAL_BE4);
+	val = clamp_t(int, val + info->thermal_k, 0, 255);
 
 	return val;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 08/15] wifi: rtw89: 8922d: read default digital voltage calibration values
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (6 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 07/15] wifi: rtw89: efuse: read thermal calibration value for RTL8922D Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 09/15] wifi: rtw89: add thermal protect by digital voltage reduction Ping-Ke Shih
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

In order to lower temperature when WiFi is running, reduce the digital
voltage for the purpose.

The calibration values of digital voltage are programmed in efuse. One is
for normal use, which driver stores it into hal->thermal_prot_vmax. The
other is the minimum voltage, which is stored into hal->thermal_prot_vmin.
These two values define a range of supported voltage, which latter patch
uses them to adjust voltage depends on thermal value (temperature).

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.h     |  7 ++
 drivers/net/wireless/realtek/rtw89/efuse.h    |  1 +
 drivers/net/wireless/realtek/rtw89/efuse_be.c | 87 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/mac.c      |  2 +
 drivers/net/wireless/realtek/rtw89/mac.h      | 11 +++
 drivers/net/wireless/realtek/rtw89/mac_be.c   |  1 +
 drivers/net/wireless/realtek/rtw89/reg.h      | 17 ++++
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 24 +++++
 8 files changed, 150 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 888a09fb2a9a..7729e7d4a792 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -3661,6 +3661,8 @@ struct rtw89_sta_link {
 struct rtw89_efuse {
 	bool valid;
 	bool power_k_valid;
+	bool vcore_valid;
+	bool dswr_valid;
 	u8 xtal_cap;
 	u8 addr[ETH_ALEN];
 	u8 rfe_type;
@@ -3670,6 +3672,8 @@ struct rtw89_efuse {
 	u8 bt_setting_3;
 	u8 sn[RTW89_EFUSE_SN_LEN];
 	u8 uuid[RTW89_EFUSE_UUID_LEN];
+	u8 vcore_vmax_reduce;
+	u8 dswr_vmin;
 };
 
 struct rtw89_phy_rate_pattern {
@@ -5382,6 +5386,9 @@ struct rtw89_hal {
 	u8 thermal_prot_th;
 	u8 thermal_prot_lv; /* 0 ~ RTW89_THERMAL_PROT_LV_MAX */
 
+	u8 thermal_prot_vmax;
+	u8 thermal_prot_vmin;
+
 	u8 fixed_dig_pd_th; /* v = (X(dBm) + 102)/2 */
 	s8 fixed_dig_cck_pd_th; /* dBm */
 };
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h
index c6415da749a3..4eb629273ab9 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.h
+++ b/drivers/net/wireless/realtek/rtw89/efuse.h
@@ -38,5 +38,6 @@ int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev);
 int rtw89_efuse_read_fw_secure_be(struct rtw89_dev *rtwdev);
 int rtw89_efuse_read_ecv_be(struct rtw89_dev *rtwdev);
 int rtw89_efuse_read_thermal_k_be(struct rtw89_dev *rtwdev);
+int rtw89_efuse_read_pwr_data_be(struct rtw89_dev *rtwdev);
 
 #endif
diff --git a/drivers/net/wireless/realtek/rtw89/efuse_be.c b/drivers/net/wireless/realtek/rtw89/efuse_be.c
index 67036c89883f..825274bd7c41 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse_be.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse_be.c
@@ -16,6 +16,15 @@
 #define EFUSE_SEC_BE_START 0x1580
 #define EFUSE_SEC_BE_SIZE 4
 
+#define EFUSE_VCORE_PWR_BE 0x17D6
+#define EFUSE_VCORE_PWR_BE_VALID BIT(12)
+#define EFUSE_VCORE_PWR_BE_VAL GENMASK(11, 0)
+#define SWR_DIG_MIN 860
+#define EFUSE_DIG_K_STEP 0xC
+#define EFUSE_DSWR_V0_86_BE 0x17DA
+#define EFUSE_DSWR_V0_86_BE_VALID BIT(5)
+#define EFUSE_DSWR_V0_86_BE_VAL GENMASK(4, 0)
+
 static const u32 sb_sel_mgn[SB_SEL_MGN_MAX_SIZE] = {
 	0x8000100, 0xC000180
 };
@@ -392,6 +401,17 @@ int rtw89_parse_efuse_map_be(struct rtw89_dev *rtwdev)
 		goto out_free;
 	}
 
+	if (rtwdev->chip->chip_id != RTL8922D)
+		goto out_free;
+
+	ret = rtw89_parse_logical_efuse_block_be(rtwdev, phy_map, phy_size,
+						 RTW89_EFUSE_BLOCK_SYS);
+	if (ret) {
+		rtw89_warn(rtwdev, "failed to parse efuse logic block %d\n",
+			   RTW89_EFUSE_BLOCK_SYS);
+		goto out_free;
+	}
+
 out_free:
 	kfree(dav_phy_map);
 	kfree(phy_map);
@@ -566,3 +586,70 @@ int rtw89_efuse_read_thermal_k_be(struct rtw89_dev *rtwdev)
 
 	return 0;
 }
+
+static int rtw89_efuse_read_pwr_data_vcore_be(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_efuse *efuse = &rtwdev->efuse;
+	u32 dump_addr;
+	u8 buff[4]; /* efuse access must 4 bytes align */
+	u16 val16;
+	int ret;
+
+	dump_addr = ALIGN_DOWN(EFUSE_VCORE_PWR_BE, 4);
+
+	ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false);
+	if (ret)
+		return ret;
+
+	val16 = buff[EFUSE_VCORE_PWR_BE - dump_addr] |
+		buff[EFUSE_VCORE_PWR_BE - dump_addr + 1] << 8;
+
+	if (val16 & EFUSE_VCORE_PWR_BE_VALID)
+		return 0;
+
+	efuse->vcore_valid = true;
+	efuse->vcore_vmax_reduce =
+		(u16_get_bits(val16, EFUSE_VCORE_PWR_BE_VAL) - SWR_DIG_MIN) /
+		EFUSE_DIG_K_STEP;
+
+	return 0;
+}
+
+static int rtw89_efuse_read_pwr_data_dswr_be(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_efuse *efuse = &rtwdev->efuse;
+	u32 dump_addr;
+	u8 buff[4]; /* efuse access must 4 bytes align */
+	u8 val8;
+	int ret;
+
+	dump_addr = ALIGN_DOWN(EFUSE_DSWR_V0_86_BE, 4);
+
+	ret = rtw89_dump_physical_efuse_map_be(rtwdev, buff, dump_addr, 4, false);
+	if (ret)
+		return ret;
+
+	val8 = buff[EFUSE_DSWR_V0_86_BE - dump_addr];
+
+	if (val8 & EFUSE_DSWR_V0_86_BE_VALID)
+		return 0;
+
+	efuse->dswr_valid = true;
+	efuse->dswr_vmin = u8_get_bits(val8, EFUSE_DSWR_V0_86_BE_VAL);
+
+	return 0;
+}
+
+int rtw89_efuse_read_pwr_data_be(struct rtw89_dev *rtwdev)
+{
+	int ret;
+
+	if (rtwdev->chip->chip_id != RTL8922D)
+		return 0;
+
+	ret = rtw89_efuse_read_pwr_data_vcore_be(rtwdev);
+	if (ret)
+		return ret;
+
+	return rtw89_efuse_read_pwr_data_dswr_be(rtwdev);
+}
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 3d3f683046a7..f5e55e6be119 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1559,6 +1559,7 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
 			rtw89_mac_efuse_read_ecv(rtwdev);
 			mac->efuse_read_fw_secure(rtwdev);
 			rtw89_mac_efuse_read_thermal_k(rtwdev);
+			rtw89_mac_efuse_read_pwr_data(rtwdev);
 		}
 
 		set_bit(RTW89_FLAG_POWERON, rtwdev->flags);
@@ -7502,6 +7503,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
 	.efuse_read_fw_secure = rtw89_efuse_read_fw_secure_ax,
 	.efuse_read_ecv = NULL,
 	.efuse_read_thermal_k = NULL,
+	.efuse_read_pwr_data = NULL,
 
 	.cfg_plt = rtw89_mac_cfg_plt_ax,
 	.get_plt_cnt = rtw89_mac_get_plt_cnt_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 7256d64ea07f..8bbe49492d4c 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -1133,6 +1133,7 @@ struct rtw89_mac_gen_def {
 	int (*efuse_read_fw_secure)(struct rtw89_dev *rtwdev);
 	int (*efuse_read_ecv)(struct rtw89_dev *rtwdev);
 	int (*efuse_read_thermal_k)(struct rtw89_dev *rtwdev);
+	int (*efuse_read_pwr_data)(struct rtw89_dev *rtwdev);
 
 	int (*cfg_plt)(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_plt *plt);
 	u16 (*get_plt_cnt)(struct rtw89_dev *rtwdev, u8 band);
@@ -1746,6 +1747,16 @@ static inline int rtw89_mac_efuse_read_thermal_k(struct rtw89_dev *rtwdev)
 	return mac->efuse_read_thermal_k(rtwdev);
 }
 
+static inline int rtw89_mac_efuse_read_pwr_data(struct rtw89_dev *rtwdev)
+{
+	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+	if (!mac->efuse_read_pwr_data)
+		return -ENOENT;
+
+	return mac->efuse_read_pwr_data(rtwdev);
+}
+
 static inline
 void rtw89_mac_fwdl_preconfig(struct rtw89_dev *rtwdev)
 {
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index 077ddf4f77c5..0fe317929b1b 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -3313,6 +3313,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
 	.efuse_read_fw_secure = rtw89_efuse_read_fw_secure_be,
 	.efuse_read_ecv = rtw89_efuse_read_ecv_be,
 	.efuse_read_thermal_k = rtw89_efuse_read_thermal_k_be,
+	.efuse_read_pwr_data = rtw89_efuse_read_pwr_data_be,
 
 	.cfg_plt = rtw89_mac_cfg_plt_be,
 	.get_plt_cnt = rtw89_mac_get_plt_cnt_be,
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 3908f9729736..72f7b80fe1fb 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -4573,6 +4573,23 @@
 #define R_BE_UDM2 0x01F8
 #define B_BE_UDM2_EPC_RA_MASK GENMASK(31, 0)
 
+#define R_BE_SPS_DIG_ON_CTRL0 0x0200
+#define B_BE_PFMCMP_IQ BIT(31)
+#define B_BE_FREQ_MASK GENMASK(30, 27)
+#define B_BE_OFF_END_SEL BIT(26)
+#define B_BE_POW_MINOFF_L BIT(25)
+#define B_BE_REG_BYPASS_L BIT(24)
+#define B_BE_VREFPFM_L_MASK GENMASK(23, 19)
+#define B_BE_REG_ZCDC_H_MASK GENMASK(18, 17)
+#define B_BE_FORCE_ZCD_BIAS BIT(16)
+#define B_BE_ZCD_SDZ_L_MASK GENMASK(15, 14)
+#define B_BE_ISAW_MASK GENMASK(13, 10)
+#define B_BE_SS_DIVSEL_MASK GENMASK(9, 8)
+#define B_BE_REG_BG_H BIT(7)
+#define B_BE_FPWM_L1 BIT(6)
+#define B_BE_POW_ZCD_L BIT(5)
+#define B_BE_PWMTUNE_MASK GENMASK(4, 0)
+
 #define R_BE_SPS_DIG_ON_CTRL1 0x0204
 #define B_BE_SN_N_L_MASK GENMASK(31, 28)
 #define B_BE_SP_N_L_MASK GENMASK(27, 24)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 8b91c552a309..a6693c8413d5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -881,6 +881,28 @@ static int rtw8922d_read_efuse_rf(struct rtw89_dev *rtwdev, u8 *log_map)
 	return 0;
 }
 
+static int rtw8922d_read_sys(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+	struct rtw89_efuse *efuse = &rtwdev->efuse;
+	struct rtw89_hal *hal = &rtwdev->hal;
+	u16 digk;
+	u8 vmin;
+
+	digk = log_map[0x200] | log_map[0x201] << 8;
+	hal->thermal_prot_vmax = u16_get_bits(digk, B_BE_PWMTUNE_MASK);
+
+	if (efuse->dswr_valid)
+		vmin = efuse->dswr_vmin;
+	else if (efuse->vcore_valid)
+		vmin = hal->thermal_prot_vmax - efuse->vcore_vmax_reduce;
+	else
+		vmin = hal->thermal_prot_vmax - 3;
+
+	hal->thermal_prot_vmin = vmin;
+
+	return 0;
+}
+
 static int rtw8922d_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
 			       enum rtw89_efuse_block block)
 {
@@ -891,6 +913,8 @@ static int rtw8922d_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
 		return rtw8922d_read_efuse_usb(rtwdev, log_map);
 	case RTW89_EFUSE_BLOCK_RF:
 		return rtw8922d_read_efuse_rf(rtwdev, log_map);
+	case RTW89_EFUSE_BLOCK_SYS:
+		return rtw8922d_read_sys(rtwdev, log_map);
 	default:
 		return 0;
 	}
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 09/15] wifi: rtw89: add thermal protect by digital voltage reduction
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (7 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 08/15] wifi: rtw89: 8922d: read default digital voltage calibration values Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 10/15] wifi: rtw89: 8922d: set ANA CLK enter to 500KHz Ping-Ke Shih
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

The temperature is rising when WiFi does high throughput, and reduce
voltage is a way to ease temperature.

The existing method to do thermal protect is to reduce TX duty, which
can affect throughput obviously. Before doing reduce TX duty (with -20
thermal value offset), driver does voltage reduction first, which doesn't
affect throughput but lower power consumption.

The voltage gram of register is 0.01 voltage, and the suggested maximum
reduction is 6 grams, which driver defines 6 as maximum voltage level.
When thermal value is over threshold, driver will try to adjust level and
corresponding register value. It should be adjust grams one by one with
additional 50 ms delay to ensure hardware work properly.

A note that the voltage must reset to normal value before entering power
save mode, otherwise WiFi card might get lost. Since it takes 50 ms delay
for each gram to adjust voltage, we stop to enter power save if protect
level is not zero.

By the way, adjust thermal threshold to 0xB4 as desired.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.c     |  9 +++++
 drivers/net/wireless/realtek/rtw89/core.h     |  4 ++
 drivers/net/wireless/realtek/rtw89/debug.c    |  1 +
 drivers/net/wireless/realtek/rtw89/mac.c      |  3 ++
 drivers/net/wireless/realtek/rtw89/mac.h      | 24 ++++++++++++
 drivers/net/wireless/realtek/rtw89/mac_be.c   | 38 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/phy.c      | 27 +++++++++++++
 drivers/net/wireless/realtek/rtw89/rtw8922d.c |  2 +-
 8 files changed, 107 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 9dbf01e82383..74b9aa8398ff 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -5236,9 +5236,18 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev)
 static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev,
 				  enum rtw89_tfc_interval interval)
 {
+	struct rtw89_hal *hal = &rtwdev->hal;
 	struct ieee80211_vif *vif;
 	struct rtw89_vif *rtwvif;
 
+	/*
+	 * If vcore level is set, temperature is high and voltage is low. As
+	 * entering power save must reset voltage to default, avoid power save
+	 * until vcore decreases to zero resulting from temperature becomes low.
+	 */
+	if (hal->thermal_prot_vlv)
+		return;
+
 	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
 		if (rtwvif->tdls_peer)
 			continue;
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 7729e7d4a792..2b388407bf6e 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -5344,10 +5344,13 @@ enum rtw89_dm_type {
 	RTW89_DM_HW_SCAN,
 	RTW89_DM_INACTIVE_PS,
 	RTW89_DM_DIG_PD,
+	RTW89_DM_VCORE,
 };
 
 #define RTW89_THERMAL_PROT_LV_MAX 5
 #define RTW89_THERMAL_PROT_STEP 5 /* -5% for each level */
+#define RTW89_THERMAL_PROT_VLV_MAX 6
+#define RTW89_THERMAL_PROT_VLV_TH_OFFSET 20
 
 struct rtw89_hal {
 	u32 rx_fltr;
@@ -5388,6 +5391,7 @@ struct rtw89_hal {
 
 	u8 thermal_prot_vmax;
 	u8 thermal_prot_vmin;
+	u8 thermal_prot_vlv; /* 0 ~ RTW89_THERMAL_PROT_VLV_MAX (6) */
 
 	u8 fixed_dig_pd_th; /* v = (X(dBm) + 102)/2 */
 	s8 fixed_dig_cck_pd_th; /* dBm */
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 5786120602ab..e42dc5707576 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -4778,6 +4778,7 @@ static const struct rtw89_disabled_dm_info {
 	DM_INFO(HW_SCAN),
 	DM_INFO(INACTIVE_PS),
 	DM_INFO(DIG_PD),
+	DM_INFO(VCORE),
 };
 
 static ssize_t
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index f5e55e6be119..6e3da5e4a1b3 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1602,6 +1602,8 @@ int rtw89_mac_pwr_on(struct rtw89_dev *rtwdev)
 
 void rtw89_mac_pwr_off(struct rtw89_dev *rtwdev)
 {
+	rtw89_mac_set_vcore_reset(rtwdev);
+
 	rtw89_mac_power_switch(rtwdev, false);
 }
 
@@ -7477,6 +7479,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
 	.cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_ax,
 	.cfg_phy_rpt = NULL,
 	.set_edcca_mode = NULL,
+	.set_vcore_cfg = NULL,
 
 	.dle_mix_cfg = dle_mix_cfg_ax,
 	.chk_dle_rdy = chk_dle_rdy_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 8bbe49492d4c..f85c14ca0f35 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -1100,6 +1100,7 @@ struct rtw89_mac_gen_def {
 	int (*cfg_ppdu_status)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable);
 	void (*cfg_phy_rpt)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable);
 	void (*set_edcca_mode)(struct rtw89_dev *rtwdev, u8 mac_idx, bool normal);
+	void (*set_vcore_cfg)(struct rtw89_dev *rtwdev, u8 vlv);
 
 	int (*dle_mix_cfg)(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg);
 	int (*chk_dle_rdy)(struct rtw89_dev *rtwdev, bool wde_or_ple);
@@ -1459,6 +1460,29 @@ void rtw89_mac_set_edcca_mode(struct rtw89_dev *rtwdev, u8 mac_idx, bool normal)
 	mac->set_edcca_mode(rtwdev, mac_idx, normal);
 }
 
+static inline
+void rtw89_mac_set_vcore_cfg(struct rtw89_dev *rtwdev, u8 vlv)
+{
+	const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+	if (!mac->set_vcore_cfg)
+		return;
+
+	mac->set_vcore_cfg(rtwdev, vlv);
+}
+
+static inline
+void rtw89_mac_set_vcore_reset(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_hal *hal = &rtwdev->hal;
+
+	if (hal->thermal_prot_vlv == 0)
+		return;
+
+	hal->thermal_prot_vlv = 0;
+	rtw89_mac_set_vcore_cfg(rtwdev, 0);
+}
+
 static inline
 void rtw89_mac_set_edcca_mode_bands(struct rtw89_dev *rtwdev, bool normal)
 {
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index 0fe317929b1b..4bdf20b7ba6d 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -2676,6 +2676,43 @@ void rtw89_mac_set_edcca_mode_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool norm
 	}
 }
 
+static
+void rtw89_mac_set_vcore_cfg_be(struct rtw89_dev *rtwdev, u8 vlv)
+{
+	struct rtw89_hal *hal = &rtwdev->hal;
+	u32 val32;
+	u8 target;
+	u8 vpwm;
+	int i;
+
+	if (rtwdev->chip->chip_id != RTL8922D)
+		return;
+
+	target = clamp(hal->thermal_prot_vmax - vlv,
+		       hal->thermal_prot_vmin, hal->thermal_prot_vmax);
+
+	val32 = rtw89_read32(rtwdev, R_BE_SPS_DIG_ON_CTRL0);
+	vpwm = u32_get_bits(val32, B_BE_PWMTUNE_MASK);
+	val32 &= ~B_BE_PWMTUNE_MASK;
+
+	if (vpwm == target)
+		return;
+
+	for (i = 0; i < RTW89_THERMAL_PROT_VLV_MAX; i++) {
+		if (vpwm > target)
+			vpwm--;
+		else
+			vpwm++;
+
+		rtw89_write32(rtwdev, R_BE_SPS_DIG_ON_CTRL0, val32 | vpwm);
+
+		if (vpwm == target)
+			break;
+
+		mdelay(50);
+	}
+}
+
 static
 int rtw89_mac_cfg_ppdu_status_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
 {
@@ -3287,6 +3324,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
 	.cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_be,
 	.cfg_phy_rpt = rtw89_mac_cfg_phy_rpt_be,
 	.set_edcca_mode = rtw89_mac_set_edcca_mode_be,
+	.set_vcore_cfg = rtw89_mac_set_vcore_cfg_be,
 
 	.dle_mix_cfg = dle_mix_cfg_be,
 	.chk_dle_rdy = chk_dle_rdy_be,
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 981c7f02271a..dcd54be58a33 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -5718,6 +5718,32 @@ static void rtw89_phy_antdiv_init(struct rtw89_dev *rtwdev)
 	rtw89_phy_antdiv_reg_init(rtwdev);
 }
 
+static void rtw89_phy_thermal_protect_vcore(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_phy_stat *phystat = &rtwdev->phystat;
+	struct rtw89_hal *hal = &rtwdev->hal;
+	bool vcore_enabled = !!hal->thermal_prot_vmax;
+	u8 th_max = phystat->last_thermal_max;
+	u8 vlv = hal->thermal_prot_vlv;
+	u8 prot_th;
+
+	if (!vcore_enabled || (hal->disabled_dm_bitmap & BIT(RTW89_DM_VCORE)))
+		return;
+
+	prot_th = hal->thermal_prot_th - RTW89_THERMAL_PROT_VLV_TH_OFFSET;
+	if (th_max > prot_th && vlv < RTW89_THERMAL_PROT_VLV_MAX)
+		vlv++;
+	else if (th_max < prot_th - 2 && vlv > 0)
+		vlv--;
+	else
+		return;
+
+	rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, "thermal protection vlv=%d\n", vlv);
+
+	hal->thermal_prot_vlv = vlv;
+	rtw89_mac_set_vcore_cfg(rtwdev, vlv);
+}
+
 static void rtw89_phy_thermal_protect(struct rtw89_dev *rtwdev)
 {
 	struct rtw89_phy_stat *phystat = &rtwdev->phystat;
@@ -6186,6 +6212,7 @@ void rtw89_phy_stat_track(struct rtw89_dev *rtwdev)
 	struct rtw89_bb_ctx *bb;
 
 	rtw89_phy_stat_thermal_update(rtwdev);
+	rtw89_phy_thermal_protect_vcore(rtwdev);
 	rtw89_phy_thermal_protect(rtwdev);
 	rtw89_phy_stat_rssi_update(rtwdev);
 	rtw89_phy_stat_update(rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index a6693c8413d5..36b9b529195d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -3451,7 +3451,7 @@ const struct rtw89_chip_info rtw8922d_chip_info = {
 	.wde_qempty_acq_grpnum	= 8,
 	.wde_qempty_mgq_grpsel	= 8,
 	.rf_base_addr		= {0x3e000, 0x3f000},
-	.thermal_th		= {0xac, 0xad},
+	.thermal_th		= {0xac, 0xb4},
 	.pwr_on_seq		= NULL,
 	.pwr_off_seq		= NULL,
 	.bb_table		= NULL,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 10/15] wifi: rtw89: 8922d: set ANA CLK enter to 500KHz
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (8 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 09/15] wifi: rtw89: add thermal protect by digital voltage reduction Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 11/15] wifi: rtw89: 8922d: update scaling factor for RX path Ping-Ke Shih
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

To power save, change the clock of ANA hardware from 12MHz to 500KHz.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/mac.h      |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 13 +++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index f85c14ca0f35..a5f1694af91a 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -1680,6 +1680,7 @@ enum rtw89_mac_xtal_si_offset {
 	XTAL_SI_PWR_CUT = 0x10,
 #define XTAL_SI_SMALL_PWR_CUT	BIT(0)
 #define XTAL_SI_BIG_PWR_CUT	BIT(1)
+	XTAL_SI_AONLDO_CTRL = 0x10,
 	XTAL_SI_XTAL_DRV = 0x15,
 #define XTAL_SI_DRV_LATCH	BIT(4)
 	XTAL_SI_XTAL_PLL = 0x16,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 36b9b529195d..8ca07aeb377a 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -535,6 +535,19 @@ static int rtw8922d_pwr_on_func(struct rtw89_dev *rtwdev)
 	rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
 	rtw89_write32_set(rtwdev, R_BE_WLRESUME_CTRL, B_BE_LPSROP_CMAC0 |
 						      B_BE_LPSROP_CMAC1);
+
+	if (hal->aid == RTL8922D_AID7102) {
+		ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_AONLDO_CTRL, 0, 0x20);
+		if (ret)
+			return ret;
+
+		udelay(1);
+
+		ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_AONLDO_CTRL, 0, 0x40);
+		if (ret)
+			return ret;
+	}
+
 	rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFN_ONMAC);
 
 	ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_APFN_ONMAC),
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 11/15] wifi: rtw89: 8922d: update scaling factor for RX path
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (9 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 10/15] wifi: rtw89: 8922d: set ANA CLK enter to 500KHz Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 12/15] wifi: rtw89: 8852a: fix RSSI report when average beacon RSSI is not ready Ping-Ke Shih
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

Update the per-MCS calibration values of RX scaling factors on RX path
(1R or 2R) for BCC and LDPC coding schemes.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/reg.h      |  5 ++++
 drivers/net/wireless/realtek/rtw89/rtw8922d.c | 26 +++++++++++--------
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 72f7b80fe1fb..2caefb929199 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -11002,6 +11002,11 @@
 #define R_RX_LDPC02_BE4 0x26834
 #define B_RX_LDPC10_BE4 GENMASK(17, 12)
 #define B_RX_LDPC11_BE4 GENMASK(23, 18)
+#define B_RX_LDPC12_BE4 GENMASK(29, 24)
+#define R_RX_LDPC03_BE4 0x26838
+#define B_RX_LDPC13_BE4 GENMASK(5, 0)
+#define B_RX_LDPC02_BE4 GENMASK(23, 18)
+#define B_RX_LDPC03_BE4 GENMASK(29, 24)
 #define R_RX_LDPC00_BE4 0x2683C
 #define B_RX_LDPC04_BE4 GENMASK(5, 0)
 #define B_RX_LDPC05_BE4 GENMASK(11, 6)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922d.c b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
index 8ca07aeb377a..768434db14c6 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922d.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922d.c
@@ -2230,38 +2230,42 @@ static int rtw8922d_ctrl_rx_path_tmac(struct rtw89_dev *rtwdev,
 		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC1_BE4, B_RXCH_MCS6_BE4, 3, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC1_BE4, B_RXCH_MCS7_BE4, 7, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC1_BE4, B_RXCH_MCS8_BE4, 2, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC1_BE4, B_RXCH_MCS9_BE4, 2, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_AWGN00_BE4, B_RX_AWGN04_BE4, 4, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_AWGN00_BE4, B_RX_AWGN07_BE4, 2, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_AWGN01_BE4, B_RX_AWGN09_BE4, 0, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_AWGN02_BE4, B_RX_AWGN11_BE4, 1, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC04_BE4, 8, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC05_BE4, 5, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC06_BE4, 3, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC07_BE4, 5, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC08_BE4, 1, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC01_BE4, B_RX_LDPC09_BE4, 2, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC02_BE4, B_RX_LDPC10_BE4, 4, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC02_BE4, B_RX_LDPC11_BE4, 2, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC03_BE4, B_RX_LDPC02_BE4, 0x6, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC03_BE4, B_RX_LDPC03_BE4, 0xf, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC04_BE4, 0x10, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC05_BE4, 0xa, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC06_BE4, 0x8, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC07_BE4, 0x14, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC01_BE4, B_RX_LDPC09_BE4, 0x14, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC02_BE4, B_RX_LDPC10_BE4, 0xc, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC02_BE4, B_RX_LDPC11_BE4, 0xb, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC02_BE4, B_RX_LDPC12_BE4, 0x14, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC03_BE4, B_RX_LDPC13_BE4, 0x2d, phy_idx);
 	} else {
 		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC0_BE4, B_RXCH_MCS4_BE4, 13, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC1_BE4, B_RXCH_MCS5_BE4, 15, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC1_BE4, B_RXCH_MCS6_BE4, 6, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC1_BE4, B_RXCH_MCS7_BE4, 15, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC1_BE4, B_RXCH_MCS8_BE4, 4, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RXCH_BCC1_BE4, B_RXCH_MCS9_BE4, 15, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_AWGN00_BE4, B_RX_AWGN04_BE4, 9, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_AWGN00_BE4, B_RX_AWGN07_BE4, 3, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_AWGN01_BE4, B_RX_AWGN09_BE4, 1, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_AWGN02_BE4, B_RX_AWGN11_BE4, 0, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC03_BE4, B_RX_LDPC02_BE4, 0x3, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC03_BE4, B_RX_LDPC03_BE4, 0x9, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC04_BE4, 9, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC05_BE4, 8, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC06_BE4, 6, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC07_BE4, 16, phy_idx);
-		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC00_BE4, B_RX_LDPC08_BE4, 4, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC01_BE4, B_RX_LDPC09_BE4, 9, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC02_BE4, B_RX_LDPC10_BE4, 9, phy_idx);
 		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC02_BE4, B_RX_LDPC11_BE4, 7, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC02_BE4, B_RX_LDPC12_BE4, 0x17, phy_idx);
+		rtw89_phy_write32_idx(rtwdev, R_RX_LDPC03_BE4, B_RX_LDPC13_BE4, 0x1a, phy_idx);
 	}
 
 	return 0;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 12/15] wifi: rtw89: 8852a: fix RSSI report when average beacon RSSI is not ready
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (10 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 11/15] wifi: rtw89: 8922d: update scaling factor for RX path Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 13/15] wifi: rtw89: phy: add NCTL check for WiFi 7 chips Ping-Ke Shih
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

From: Chih-Kang Chang <gary.chang@realtek.com>

8852A uses the average beacon RSSI to smooth the RSSI. However, before
the average beacon RSSI is available, the RSSI should use the PPDU
status RSSI of the received packet to avoid reporting the RSSI as -110 dBm.

Fixes: f0f3bf4b370c ("wifi: rtw89: 8852a: report average RSSI to avoid unnecessary scanning")
Signed-off-by: Chih-Kang Chang <gary.chang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8852a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index a5a06ae5c446..61b6b76c5bdb 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2212,7 +2212,7 @@ static void rtw8852a_query_ppdu(struct rtw89_dev *rtwdev,
 	u8 raw;
 
 	if (!status->signal) {
-		if (phy_ppdu->to_self)
+		if (phy_ppdu->to_self && ewma_rssi_read(&bb->bcn_rssi))
 			raw = ewma_rssi_read(&bb->bcn_rssi);
 		else
 			raw = max(rx_power[RF_PATH_A], rx_power[RF_PATH_B]);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 13/15] wifi: rtw89: phy: add NCTL check for WiFi 7 chips
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (11 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 12/15] wifi: rtw89: 8852a: fix RSSI report when average beacon RSSI is not ready Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 14/15] wifi: rtw89: unify access struct of TX power track tables Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 15/15] wifi: rtw89: set needed firmware elements for early chips transition Ping-Ke Shih
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

Initialize NCTL hardware and check the state before downloading NCTL.
Otherwise, the following RF calibrations relying on NCTL may fail.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.c    |  1 +
 drivers/net/wireless/realtek/rtw89/phy.h    |  6 +++
 drivers/net/wireless/realtek/rtw89/phy_be.c | 41 +++++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/reg.h    |  6 +++
 4 files changed, 54 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index dcd54be58a33..30d5741da87e 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -9010,6 +9010,7 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_ax = {
 	.physts = &rtw89_physts_regs_ax,
 	.cfo = &rtw89_cfo_regs_ax,
 	.bb_wrap = NULL,
+	.nctl = NULL,
 	.phy0_phy1_offset = rtw89_phy0_phy1_offset_ax,
 	.config_bb_gain = rtw89_phy_config_bb_gain_ax,
 	.preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index 532232892831..e31034377b54 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -502,6 +502,11 @@ struct rtw89_bb_wrap_regs {
 	u32 pwr_macid_path;
 };
 
+struct rtw89_nctl_regs {
+	u32 cfg;
+	u32 rw;
+};
+
 enum rtw89_bandwidth_section_num_ax {
 	RTW89_BW20_SEC_NUM_AX = 8,
 	RTW89_BW40_SEC_NUM_AX = 4,
@@ -679,6 +684,7 @@ struct rtw89_phy_gen_def {
 	const struct rtw89_physts_regs *physts;
 	const struct rtw89_cfo_regs *cfo;
 	const struct rtw89_bb_wrap_regs *bb_wrap;
+	const struct rtw89_nctl_regs *nctl;
 	u32 (*phy0_phy1_offset)(struct rtw89_dev *rtwdev, u32 addr);
 	void (*config_bb_gain)(struct rtw89_dev *rtwdev,
 			       const struct rtw89_reg2_def *reg,
diff --git a/drivers/net/wireless/realtek/rtw89/phy_be.c b/drivers/net/wireless/realtek/rtw89/phy_be.c
index ac4ce30445b3..2187b448fe75 100644
--- a/drivers/net/wireless/realtek/rtw89/phy_be.c
+++ b/drivers/net/wireless/realtek/rtw89/phy_be.c
@@ -225,6 +225,16 @@ static const struct rtw89_bb_wrap_regs rtw89_bb_wrap_regs_be_v1 = {
 	.pwr_macid_path = R_BE_PWR_MACID_PATH_BASE_V1,
 };
 
+static const struct rtw89_nctl_regs rtw89_nctl_regs_be = {
+	.cfg = R_NCTL_CFG,
+	.rw = R_NCTL_RW,
+};
+
+static const struct rtw89_nctl_regs rtw89_nctl_regs_be_v1 = {
+	.cfg = R_NCTL_CFG_BE4,
+	.rw = R_NCTL_RW_BE4,
+};
+
 static u32 rtw89_phy0_phy1_offset_be(struct rtw89_dev *rtwdev, u32 addr)
 {
 	u32 phy_page = addr >> 8;
@@ -440,6 +450,28 @@ static void rtw89_phy_config_bb_gain_be(struct rtw89_dev *rtwdev,
 	}
 }
 
+static void rtw89_phy_preinit_rf_nctl_check_be(struct rtw89_dev *rtwdev)
+{
+	const struct rtw89_phy_gen_def *phy = rtwdev->chip->phy_def;
+	const struct rtw89_nctl_regs *nctl = phy->nctl;
+	int poll;
+	u32 val;
+
+	rtw89_phy_write32(rtwdev, nctl->cfg, B_NCTL_CHK_EN);
+
+	for (poll = 0; poll < 10000; poll++) {
+		rtw89_phy_write32(rtwdev, nctl->rw, B_NCTL_CHECK);
+
+		fsleep(10);
+
+		val = rtw89_phy_read32(rtwdev, nctl->rw);
+		if (val == B_NCTL_CHECK)
+			return;
+	}
+
+	rtw89_warn(rtwdev, "NCTL INIT check 0x%x[2]TIMEOUT!\n", nctl->rw);
+}
+
 static void rtw89_phy_preinit_rf_nctl_be(struct rtw89_dev *rtwdev)
 {
 	rtw89_phy_write32_mask(rtwdev, R_GOTX_IQKDPK_C0, B_GOTX_IQKDPK, 0x3);
@@ -456,6 +488,11 @@ static void rtw89_phy_preinit_rf_nctl_be(struct rtw89_dev *rtwdev)
 		rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_RST_C1, B_IQK_DPK_RST, 0x1);
 		rtw89_phy_write32_mask(rtwdev, R_TXRFC_C1, B_TXRFC_RST, 0x1);
 	}
+
+	rtw89_phy_write32_mask(rtwdev, R_TX_COLLISION_T2R_ST, B_RX_CFIR_PATH_EN, 0x1);
+	rtw89_phy_write32_mask(rtwdev, R_TX_COLLISION_T2R_ST, B_RX_CFIR_PATH, 0x3);
+
+	rtw89_phy_preinit_rf_nctl_check_be(rtwdev);
 }
 
 static void rtw89_phy_preinit_rf_nctl_be_v1(struct rtw89_dev *rtwdev)
@@ -466,6 +503,8 @@ static void rtw89_phy_preinit_rf_nctl_be_v1(struct rtw89_dev *rtwdev)
 	rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_RST_BE4, B_IQK_DPK_RST, 0x1);
 	rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_PRST_BE4, B_IQK_DPK_PRST, 0x1);
 	rtw89_phy_write32_mask(rtwdev, R_IQK_DPK_PRST_C1_BE4, B_IQK_DPK_PRST, 0x1);
+
+	rtw89_phy_preinit_rf_nctl_check_be(rtwdev);
 }
 
 static u32 rtw89_phy_bb_wrap_flush_addr(struct rtw89_dev *rtwdev, u32 addr)
@@ -1905,6 +1944,7 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_be = {
 	.physts = &rtw89_physts_regs_be,
 	.cfo = &rtw89_cfo_regs_be,
 	.bb_wrap = &rtw89_bb_wrap_regs_be,
+	.nctl = &rtw89_nctl_regs_be,
 	.phy0_phy1_offset = rtw89_phy0_phy1_offset_be,
 	.config_bb_gain = rtw89_phy_config_bb_gain_be,
 	.preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_be,
@@ -1930,6 +1970,7 @@ const struct rtw89_phy_gen_def rtw89_phy_gen_be_v1 = {
 	.physts = &rtw89_physts_regs_be_v1,
 	.cfo = &rtw89_cfo_regs_be_v1,
 	.bb_wrap = &rtw89_bb_wrap_regs_be_v1,
+	.nctl = &rtw89_nctl_regs_be_v1,
 	.phy0_phy1_offset = rtw89_phy0_phy1_offset_be_v1,
 	.config_bb_gain = rtw89_phy_config_bb_gain_be,
 	.preinit_rf_nctl = rtw89_phy_preinit_rf_nctl_be_v1,
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 2caefb929199..4d2117de798b 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -9022,6 +9022,8 @@
 #define B_IQK_DPK_RST BIT(0)
 #define R_TX_COLLISION_T2R_ST 0x0C70
 #define B_TX_COLLISION_T2R_ST_M GENMASK(25, 20)
+#define B_RX_CFIR_PATH_EN BIT(9)
+#define B_RX_CFIR_PATH GENMASK(6, 5)
 #define B_TXRX_FORCE_VAL GENMASK(9, 0)
 #define R_TXGATING 0x0C74
 #define B_TXGATING_EN BIT(4)
@@ -10115,6 +10117,8 @@
 #define R_S1_DACKQ8 0x7E98
 #define B_S1_DACKQ8_K GENMASK(15, 8)
 #define R_NCTL_CFG 0x8000
+#define R_NCTL_CFG_BE4 0x38000
+#define B_NCTL_CHK_EN BIT(3)
 #define B_NCTL_CFG_SPAGE GENMASK(2, 1)
 #define R_NCTL_RPT 0x8008
 #define B_NCTL_RPT_FLG BIT(26)
@@ -10148,6 +10152,8 @@
 #define R_KIP_MOD 0x8078
 #define B_KIP_MOD GENMASK(19, 0)
 #define R_NCTL_RW 0x8080
+#define R_NCTL_RW_BE4 0x38080
+#define B_NCTL_CHECK BIT(2)
 #define R_KIP_SYSCFG 0x8088
 #define R_KIP_CLK 0x808C
 #define R_DPK_IDL 0x809C
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 14/15] wifi: rtw89: unify access struct of TX power track tables
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (12 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 13/15] wifi: rtw89: phy: add NCTL check for WiFi 7 chips Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  2026-07-07  9:10 ` [PATCH rtw-next 15/15] wifi: rtw89: set needed firmware elements for early chips transition Ping-Ke Shih
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

There are two struct to access TX power track tables. One is to access
driver built-in tables, and the other one is to access the tables in fw
element. As we are going to remove the built-in tables from driver, unify
to use the struct as fw element style.

The precedence is to use tables in fw element if present, and then
built-in tables.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/phy.h      |  19 ----
 .../net/wireless/realtek/rtw89/rtw8851b_rfk.c |  20 ++--
 .../wireless/realtek/rtw89/rtw8851b_table.c   |  15 +--
 .../wireless/realtek/rtw89/rtw8851b_table.h   |   2 +-
 .../net/wireless/realtek/rtw89/rtw8852a_rfk.c |  36 ++++---
 .../wireless/realtek/rtw89/rtw8852a_table.c   |  27 ++---
 .../wireless/realtek/rtw89/rtw8852a_table.h   |   2 +-
 .../net/wireless/realtek/rtw89/rtw8852b_rfk.c |  36 ++++---
 .../wireless/realtek/rtw89/rtw8852b_table.c   |  27 ++---
 .../wireless/realtek/rtw89/rtw8852b_table.h   |   2 +-
 .../net/wireless/realtek/rtw89/rtw8852c_rfk.c | 101 +++++++-----------
 .../wireless/realtek/rtw89/rtw8852c_table.c   |  35 +++---
 .../wireless/realtek/rtw89/rtw8852c_table.h   |   2 +-
 13 files changed, 146 insertions(+), 178 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index e31034377b54..b0c82bac72f0 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -353,25 +353,6 @@ struct rtw89_txpwr_byrate_cfg {
 	u32 data;
 };
 
-struct rtw89_txpwr_track_cfg {
-	const s8 (*delta_swingidx_6gb_n)[DELTA_SWINGIDX_SIZE];
-	const s8 (*delta_swingidx_6gb_p)[DELTA_SWINGIDX_SIZE];
-	const s8 (*delta_swingidx_6ga_n)[DELTA_SWINGIDX_SIZE];
-	const s8 (*delta_swingidx_6ga_p)[DELTA_SWINGIDX_SIZE];
-	const s8 (*delta_swingidx_5gb_n)[DELTA_SWINGIDX_SIZE];
-	const s8 (*delta_swingidx_5gb_p)[DELTA_SWINGIDX_SIZE];
-	const s8 (*delta_swingidx_5ga_n)[DELTA_SWINGIDX_SIZE];
-	const s8 (*delta_swingidx_5ga_p)[DELTA_SWINGIDX_SIZE];
-	const s8 *delta_swingidx_2gb_n;
-	const s8 *delta_swingidx_2gb_p;
-	const s8 *delta_swingidx_2ga_n;
-	const s8 *delta_swingidx_2ga_p;
-	const s8 *delta_swingidx_2g_cck_b_n;
-	const s8 *delta_swingidx_2g_cck_b_p;
-	const s8 *delta_swingidx_2g_cck_a_n;
-	const s8 *delta_swingidx_2g_cck_a_p;
-};
-
 struct rtw89_phy_dig_gain_cfg {
 	const struct rtw89_reg_def *table;
 	u8 size;
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
index a6c7f59223ef..c63f0e6364da 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
@@ -2823,6 +2823,7 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 	}						\
 	__val;						\
 })
+	const struct rtw89_fw_txpwr_track_cfg *trk = rtwdev->fw.elm_info.txpwr_trk;
 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
 	u8 ch = chan->channel;
 	u8 subband = chan->subband_type;
@@ -2833,23 +2834,26 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 	u32 tmp = 0;
 	u8 i, j;
 
+	if (!trk)
+		trk = &rtw89_8851b_trk_cfg;
+
 	switch (subband) {
 	default:
 	case RTW89_CH_2G:
-		thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_p;
-		thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_n;
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P][0];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N][0];
 		break;
 	case RTW89_CH_5G_BAND_1:
-		thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[0];
-		thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[0];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][0];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][0];
 		break;
 	case RTW89_CH_5G_BAND_3:
-		thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[1];
-		thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[1];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][1];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][1];
 		break;
 	case RTW89_CH_5G_BAND_4:
-		thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[2];
-		thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[2];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][2];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][2];
 		break;
 	}
 
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
index a9c309c245c3..b8105f6e94f1 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.c
@@ -2,6 +2,7 @@
 /* Copyright(c) 2022-2023  Realtek Corporation
  */
 
+#include "fw.h"
 #include "phy.h"
 #include "reg.h"
 #include "rtw8851b_table.h"
@@ -14866,13 +14867,13 @@ const struct rtw89_txpwr_table rtw89_8851b_byr_table_type2 = {
 	.load = rtw89_phy_load_txpwr_byrate,
 };
 
-const struct rtw89_txpwr_track_cfg rtw89_8851b_trk_cfg = {
-	.delta_swingidx_5ga_n = _txpwr_track_delta_swingidx_5ga_n,
-	.delta_swingidx_5ga_p = _txpwr_track_delta_swingidx_5ga_p,
-	.delta_swingidx_2ga_n = _txpwr_track_delta_swingidx_2ga_n,
-	.delta_swingidx_2ga_p = _txpwr_track_delta_swingidx_2ga_p,
-	.delta_swingidx_2g_cck_a_n = _txpwr_track_delta_swingidx_2g_cck_a_n,
-	.delta_swingidx_2g_cck_a_p = _txpwr_track_delta_swingidx_2g_cck_a_p,
+const struct rtw89_fw_txpwr_track_cfg rtw89_8851b_trk_cfg = {
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N] = _txpwr_track_delta_swingidx_5ga_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P] = _txpwr_track_delta_swingidx_5ga_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N] = &_txpwr_track_delta_swingidx_2ga_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P] = &_txpwr_track_delta_swingidx_2ga_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N] = &_txpwr_track_delta_swingidx_2g_cck_a_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P] = &_txpwr_track_delta_swingidx_2g_cck_a_p,
 };
 
 const struct rtw89_rfe_parms rtw89_8851b_dflt_parms = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
index d8cf545d40a0..a73c0a6f03df 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_table.h
@@ -11,7 +11,7 @@ extern const struct rtw89_phy_table rtw89_8851b_phy_bb_table;
 extern const struct rtw89_phy_table rtw89_8851b_phy_bb_gain_table;
 extern const struct rtw89_phy_table rtw89_8851b_phy_radioa_table;
 extern const struct rtw89_phy_table rtw89_8851b_phy_nctl_table;
-extern const struct rtw89_txpwr_track_cfg rtw89_8851b_trk_cfg;
+extern const struct rtw89_fw_txpwr_track_cfg rtw89_8851b_trk_cfg;
 extern const struct rtw89_rfe_parms rtw89_8851b_dflt_parms;
 extern const struct rtw89_rfe_parms_conf rtw89_8851b_rfe_parms_conf[];
 
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
index 8679b21fd3fd..609cc300f24e 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
@@ -2910,6 +2910,7 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 	}						\
 	__val;						\
 })
+	const struct rtw89_fw_txpwr_track_cfg *trk = rtwdev->fw.elm_info.txpwr_trk;
 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
 	u8 ch = chan->channel;
 	u8 subband = chan->subband_type;
@@ -2922,31 +2923,34 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 	u32 tmp = 0;
 	u8 i, j;
 
+	if (!trk)
+		trk = &rtw89_8852a_trk_cfg;
+
 	switch (subband) {
 	default:
 	case RTW89_CH_2G:
-		thm_up_a = rtw89_8852a_trk_cfg.delta_swingidx_2ga_p;
-		thm_down_a = rtw89_8852a_trk_cfg.delta_swingidx_2ga_n;
-		thm_up_b = rtw89_8852a_trk_cfg.delta_swingidx_2gb_p;
-		thm_down_b = rtw89_8852a_trk_cfg.delta_swingidx_2gb_n;
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P][0];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N][0];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_P][0];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_N][0];
 		break;
 	case RTW89_CH_5G_BAND_1:
-		thm_up_a = rtw89_8852a_trk_cfg.delta_swingidx_5ga_p[0];
-		thm_down_a = rtw89_8852a_trk_cfg.delta_swingidx_5ga_n[0];
-		thm_up_b = rtw89_8852a_trk_cfg.delta_swingidx_5gb_p[0];
-		thm_down_b = rtw89_8852a_trk_cfg.delta_swingidx_5gb_n[0];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][0];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][0];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][0];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][0];
 		break;
 	case RTW89_CH_5G_BAND_3:
-		thm_up_a = rtw89_8852a_trk_cfg.delta_swingidx_5ga_p[1];
-		thm_down_a = rtw89_8852a_trk_cfg.delta_swingidx_5ga_n[1];
-		thm_up_b = rtw89_8852a_trk_cfg.delta_swingidx_5gb_p[1];
-		thm_down_b = rtw89_8852a_trk_cfg.delta_swingidx_5gb_n[1];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][1];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][1];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][1];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][1];
 		break;
 	case RTW89_CH_5G_BAND_4:
-		thm_up_a = rtw89_8852a_trk_cfg.delta_swingidx_5ga_p[2];
-		thm_down_a = rtw89_8852a_trk_cfg.delta_swingidx_5ga_n[2];
-		thm_up_b = rtw89_8852a_trk_cfg.delta_swingidx_5gb_p[2];
-		thm_down_b = rtw89_8852a_trk_cfg.delta_swingidx_5gb_n[2];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][2];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][2];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][2];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][2];
 		break;
 	}
 
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c
index ffdeb3801991..f1bcef64a91f 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.c
@@ -2,6 +2,7 @@
 /* Copyright(c) 2019-2020  Realtek Corporation
  */
 
+#include "fw.h"
 #include "phy.h"
 #include "reg.h"
 #include "rtw8852a_table.h"
@@ -50983,19 +50984,19 @@ const struct rtw89_txpwr_table rtw89_8852a_byr_table = {
 	.load = rtw89_phy_load_txpwr_byrate,
 };
 
-const struct rtw89_txpwr_track_cfg rtw89_8852a_trk_cfg = {
-	.delta_swingidx_5gb_n = _txpwr_track_delta_swingidx_5gb_n,
-	.delta_swingidx_5gb_p = _txpwr_track_delta_swingidx_5gb_p,
-	.delta_swingidx_5ga_n = _txpwr_track_delta_swingidx_5ga_n,
-	.delta_swingidx_5ga_p = _txpwr_track_delta_swingidx_5ga_p,
-	.delta_swingidx_2gb_n = _txpwr_track_delta_swingidx_2gb_n,
-	.delta_swingidx_2gb_p = _txpwr_track_delta_swingidx_2gb_p,
-	.delta_swingidx_2ga_n = _txpwr_track_delta_swingidx_2ga_n,
-	.delta_swingidx_2ga_p = _txpwr_track_delta_swingidx_2ga_p,
-	.delta_swingidx_2g_cck_b_n = _txpwr_track_delta_swingidx_2g_cck_b_n,
-	.delta_swingidx_2g_cck_b_p = _txpwr_track_delta_swingidx_2g_cck_b_p,
-	.delta_swingidx_2g_cck_a_n = _txpwr_track_delta_swingidx_2g_cck_a_n,
-	.delta_swingidx_2g_cck_a_p = _txpwr_track_delta_swingidx_2g_cck_a_p,
+const struct rtw89_fw_txpwr_track_cfg rtw89_8852a_trk_cfg = {
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N] = _txpwr_track_delta_swingidx_5gb_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P] = _txpwr_track_delta_swingidx_5gb_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N] = _txpwr_track_delta_swingidx_5ga_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P] = _txpwr_track_delta_swingidx_5ga_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_N] = &_txpwr_track_delta_swingidx_2gb_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_P] = &_txpwr_track_delta_swingidx_2gb_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N] = &_txpwr_track_delta_swingidx_2ga_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P] = &_txpwr_track_delta_swingidx_2ga_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_N] = &_txpwr_track_delta_swingidx_2g_cck_b_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_P] = &_txpwr_track_delta_swingidx_2g_cck_b_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N] = &_txpwr_track_delta_swingidx_2g_cck_a_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P] = &_txpwr_track_delta_swingidx_2g_cck_a_p,
 };
 
 const struct rtw89_rfe_parms rtw89_8852a_dflt_parms = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h
index 58fe8575c1c9..501a8248d1ce 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a_table.h
@@ -11,7 +11,7 @@ extern const struct rtw89_phy_table rtw89_8852a_phy_bb_table;
 extern const struct rtw89_phy_table rtw89_8852a_phy_radioa_table;
 extern const struct rtw89_phy_table rtw89_8852a_phy_radiob_table;
 extern const struct rtw89_phy_table rtw89_8852a_phy_nctl_table;
-extern const struct rtw89_txpwr_track_cfg rtw89_8852a_trk_cfg;
+extern const struct rtw89_fw_txpwr_track_cfg rtw89_8852a_trk_cfg;
 extern const struct rtw89_rfe_parms rtw89_8852a_dflt_parms;
 
 #endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c
index 5cfacc10e7c8..29a82b1c4457 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_rfk.c
@@ -2784,6 +2784,7 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 	}						\
 	__val;						\
 })
+	const struct rtw89_fw_txpwr_track_cfg *trk = rtwdev->fw.elm_info.txpwr_trk;
 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
 	u8 ch = chan->channel;
 	u8 subband = chan->subband_type;
@@ -2796,31 +2797,34 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 	u32 tmp = 0;
 	u8 i, j;
 
+	if (!trk)
+		trk = &rtw89_8852b_trk_cfg;
+
 	switch (subband) {
 	default:
 	case RTW89_CH_2G:
-		thm_up_a = rtw89_8852b_trk_cfg.delta_swingidx_2ga_p;
-		thm_down_a = rtw89_8852b_trk_cfg.delta_swingidx_2ga_n;
-		thm_up_b = rtw89_8852b_trk_cfg.delta_swingidx_2gb_p;
-		thm_down_b = rtw89_8852b_trk_cfg.delta_swingidx_2gb_n;
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P][0];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N][0];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_P][0];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_N][0];
 		break;
 	case RTW89_CH_5G_BAND_1:
-		thm_up_a = rtw89_8852b_trk_cfg.delta_swingidx_5ga_p[0];
-		thm_down_a = rtw89_8852b_trk_cfg.delta_swingidx_5ga_n[0];
-		thm_up_b = rtw89_8852b_trk_cfg.delta_swingidx_5gb_p[0];
-		thm_down_b = rtw89_8852b_trk_cfg.delta_swingidx_5gb_n[0];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][0];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][0];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][0];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][0];
 		break;
 	case RTW89_CH_5G_BAND_3:
-		thm_up_a = rtw89_8852b_trk_cfg.delta_swingidx_5ga_p[1];
-		thm_down_a = rtw89_8852b_trk_cfg.delta_swingidx_5ga_n[1];
-		thm_up_b = rtw89_8852b_trk_cfg.delta_swingidx_5gb_p[1];
-		thm_down_b = rtw89_8852b_trk_cfg.delta_swingidx_5gb_n[1];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][1];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][1];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][1];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][1];
 		break;
 	case RTW89_CH_5G_BAND_4:
-		thm_up_a = rtw89_8852b_trk_cfg.delta_swingidx_5ga_p[2];
-		thm_down_a = rtw89_8852b_trk_cfg.delta_swingidx_5ga_n[2];
-		thm_up_b = rtw89_8852b_trk_cfg.delta_swingidx_5gb_p[2];
-		thm_down_b = rtw89_8852b_trk_cfg.delta_swingidx_5gb_n[2];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][2];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][2];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][2];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][2];
 		break;
 	}
 
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
index 07945d06dc59..96b18e9095b3 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.c
@@ -2,6 +2,7 @@
 /* Copyright(c) 2019-2020  Realtek Corporation
  */
 
+#include "fw.h"
 #include "phy.h"
 #include "reg.h"
 #include "rtw8852b_table.h"
@@ -22895,19 +22896,19 @@ const struct rtw89_txpwr_table rtw89_8852b_byr_table = {
 	.load = rtw89_phy_load_txpwr_byrate,
 };
 
-const struct rtw89_txpwr_track_cfg rtw89_8852b_trk_cfg = {
-	.delta_swingidx_5gb_n = _txpwr_track_delta_swingidx_5gb_n,
-	.delta_swingidx_5gb_p = _txpwr_track_delta_swingidx_5gb_p,
-	.delta_swingidx_5ga_n = _txpwr_track_delta_swingidx_5ga_n,
-	.delta_swingidx_5ga_p = _txpwr_track_delta_swingidx_5ga_p,
-	.delta_swingidx_2gb_n = _txpwr_track_delta_swingidx_2gb_n,
-	.delta_swingidx_2gb_p = _txpwr_track_delta_swingidx_2gb_p,
-	.delta_swingidx_2ga_n = _txpwr_track_delta_swingidx_2ga_n,
-	.delta_swingidx_2ga_p = _txpwr_track_delta_swingidx_2ga_p,
-	.delta_swingidx_2g_cck_b_n = _txpwr_track_delta_swingidx_2g_cck_b_n,
-	.delta_swingidx_2g_cck_b_p = _txpwr_track_delta_swingidx_2g_cck_b_p,
-	.delta_swingidx_2g_cck_a_n = _txpwr_track_delta_swingidx_2g_cck_a_n,
-	.delta_swingidx_2g_cck_a_p = _txpwr_track_delta_swingidx_2g_cck_a_p,
+const struct rtw89_fw_txpwr_track_cfg rtw89_8852b_trk_cfg = {
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N] = _txpwr_track_delta_swingidx_5gb_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P] = _txpwr_track_delta_swingidx_5gb_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N] = _txpwr_track_delta_swingidx_5ga_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P] = _txpwr_track_delta_swingidx_5ga_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_N] = &_txpwr_track_delta_swingidx_2gb_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_P] = &_txpwr_track_delta_swingidx_2gb_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N] = &_txpwr_track_delta_swingidx_2ga_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P] = &_txpwr_track_delta_swingidx_2ga_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_N] = &_txpwr_track_delta_swingidx_2g_cck_b_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_P] = &_txpwr_track_delta_swingidx_2g_cck_b_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N] = &_txpwr_track_delta_swingidx_2g_cck_a_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P] = &_txpwr_track_delta_swingidx_2g_cck_a_p,
 };
 
 const struct rtw89_rfe_parms rtw89_8852b_dflt_parms = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
index da6c90e2ba93..d30a1fb43e96 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_table.h
@@ -12,7 +12,7 @@ extern const struct rtw89_phy_table rtw89_8852b_phy_bb_gain_table;
 extern const struct rtw89_phy_table rtw89_8852b_phy_radioa_table;
 extern const struct rtw89_phy_table rtw89_8852b_phy_radiob_table;
 extern const struct rtw89_phy_table rtw89_8852b_phy_nctl_table;
-extern const struct rtw89_txpwr_track_cfg rtw89_8852b_trk_cfg;
+extern const struct rtw89_fw_txpwr_track_cfg rtw89_8852b_trk_cfg;
 extern const struct rtw89_rfe_parms rtw89_8852b_dflt_parms;
 
 #endif
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
index cbee484dee30..8d03a4645947 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
@@ -2992,7 +2992,7 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 	}						\
 	__val;						\
 })
-	struct rtw89_fw_txpwr_track_cfg *trk = rtwdev->fw.elm_info.txpwr_trk;
+	const struct rtw89_fw_txpwr_track_cfg *trk = rtwdev->fw.elm_info.txpwr_trk;
 	struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
 	u8 ch = chan->channel;
 	u8 subband = chan->subband_type;
@@ -3005,91 +3005,62 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 	u32 tmp = 0;
 	u8 i, j;
 
+	if (!trk)
+		trk = &rtw89_8852c_trk_cfg;
+
 	switch (subband) {
 	default:
 	case RTW89_CH_2G:
-		thm_up_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P][0] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_2ga_p;
-		thm_down_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N][0] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_2ga_n;
-		thm_up_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_P][0] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_2gb_p;
-		thm_down_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_N][0] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_2gb_n;
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P][0];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N][0];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_P][0];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_N][0];
 		break;
 	case RTW89_CH_5G_BAND_1:
-		thm_up_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][0] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_5ga_p[0];
-		thm_down_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][0] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_5ga_n[0];
-		thm_up_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][0] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_5gb_p[0];
-		thm_down_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][0] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_5gb_n[0];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][0];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][0];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][0];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][0];
 		break;
 	case RTW89_CH_5G_BAND_3:
-		thm_up_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][1] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_5ga_p[1];
-		thm_down_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][1] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_5ga_n[1];
-		thm_up_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][1] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_5gb_p[1];
-		thm_down_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][1] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_5gb_n[1];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][1];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][1];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][1];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][1];
 		break;
 	case RTW89_CH_5G_BAND_4:
-		thm_up_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][2] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_5ga_p[2];
-		thm_down_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][2] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_5ga_n[2];
-		thm_up_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][2] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_5gb_p[2];
-		thm_down_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][2] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_5gb_n[2];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P][2];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N][2];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P][2];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N][2];
 		break;
 	case RTW89_CH_6G_BAND_IDX0:
 	case RTW89_CH_6G_BAND_IDX1:
-		thm_up_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][0] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_6ga_p[0];
-		thm_down_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][0] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_6ga_n[0];
-		thm_up_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][0] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_6gb_p[0];
-		thm_down_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][0] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_6gb_n[0];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][0];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][0];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][0];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][0];
 		break;
 	case RTW89_CH_6G_BAND_IDX2:
 	case RTW89_CH_6G_BAND_IDX3:
-		thm_up_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][1] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_6ga_p[1];
-		thm_down_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][1] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_6ga_n[1];
-		thm_up_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][1] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_6gb_p[1];
-		thm_down_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][1] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_6gb_n[1];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][1];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][1];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][1];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][1];
 		break;
 	case RTW89_CH_6G_BAND_IDX4:
 	case RTW89_CH_6G_BAND_IDX5:
-		thm_up_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][2] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_6ga_p[2];
-		thm_down_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][2] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_6ga_n[2];
-		thm_up_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][2] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_6gb_p[2];
-		thm_down_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][2] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_6gb_n[2];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][2];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][2];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][2];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][2];
 		break;
 	case RTW89_CH_6G_BAND_IDX6:
 	case RTW89_CH_6G_BAND_IDX7:
-		thm_up_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][3] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_6ga_p[3];
-		thm_down_a = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][3] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_6ga_n[3];
-		thm_up_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][3] :
-				 rtw89_8852c_trk_cfg.delta_swingidx_6gb_p[3];
-		thm_down_b = trk ? trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][3] :
-				   rtw89_8852c_trk_cfg.delta_swingidx_6gb_n[3];
+		thm_up_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P][3];
+		thm_down_a = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N][3];
+		thm_up_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P][3];
+		thm_down_b = trk->delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N][3];
 		break;
 	}
 
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
index 24c390b6f3d3..b4cf497e8524 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
@@ -2,6 +2,7 @@
 /* Copyright(c) 2019-2022  Realtek Corporation
  */
 
+#include "fw.h"
 #include "phy.h"
 #include "reg.h"
 #include "rtw8852c_table.h"
@@ -57109,23 +57110,23 @@ const struct rtw89_txpwr_table rtw89_8852c_byr_table = {
 	.load = rtw89_phy_load_txpwr_byrate,
 };
 
-const struct rtw89_txpwr_track_cfg rtw89_8852c_trk_cfg = {
-	.delta_swingidx_6gb_n = _txpwr_track_delta_swingidx_6gb_n,
-	.delta_swingidx_6gb_p = _txpwr_track_delta_swingidx_6gb_p,
-	.delta_swingidx_6ga_n = _txpwr_track_delta_swingidx_6ga_n,
-	.delta_swingidx_6ga_p = _txpwr_track_delta_swingidx_6ga_p,
-	.delta_swingidx_5gb_n = _txpwr_track_delta_swingidx_5gb_n,
-	.delta_swingidx_5gb_p = _txpwr_track_delta_swingidx_5gb_p,
-	.delta_swingidx_5ga_n = _txpwr_track_delta_swingidx_5ga_n,
-	.delta_swingidx_5ga_p = _txpwr_track_delta_swingidx_5ga_p,
-	.delta_swingidx_2gb_n = _txpwr_track_delta_swingidx_2gb_n,
-	.delta_swingidx_2gb_p = _txpwr_track_delta_swingidx_2gb_p,
-	.delta_swingidx_2ga_n = _txpwr_track_delta_swingidx_2ga_n,
-	.delta_swingidx_2ga_p = _txpwr_track_delta_swingidx_2ga_p,
-	.delta_swingidx_2g_cck_b_n = _txpwr_track_delta_swingidx_2g_cck_b_n,
-	.delta_swingidx_2g_cck_b_p = _txpwr_track_delta_swingidx_2g_cck_b_p,
-	.delta_swingidx_2g_cck_a_n = _txpwr_track_delta_swingidx_2g_cck_a_n,
-	.delta_swingidx_2g_cck_a_p = _txpwr_track_delta_swingidx_2g_cck_a_p,
+const struct rtw89_fw_txpwr_track_cfg rtw89_8852c_trk_cfg = {
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_N] = _txpwr_track_delta_swingidx_6gb_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_6GB_P] = _txpwr_track_delta_swingidx_6gb_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_N] = _txpwr_track_delta_swingidx_6ga_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_6GA_P] = _txpwr_track_delta_swingidx_6ga_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_N] = _txpwr_track_delta_swingidx_5gb_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GB_P] = _txpwr_track_delta_swingidx_5gb_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_N] = _txpwr_track_delta_swingidx_5ga_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_5GA_P] = _txpwr_track_delta_swingidx_5ga_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_N] = &_txpwr_track_delta_swingidx_2gb_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GB_P] = &_txpwr_track_delta_swingidx_2gb_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_N] = &_txpwr_track_delta_swingidx_2ga_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2GA_P] = &_txpwr_track_delta_swingidx_2ga_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_N] = &_txpwr_track_delta_swingidx_2g_cck_b_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_B_P] = &_txpwr_track_delta_swingidx_2g_cck_b_p,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_N] = &_txpwr_track_delta_swingidx_2g_cck_a_n,
+	.delta[RTW89_FW_TXPWR_TRK_TYPE_2G_CCK_A_P] = &_txpwr_track_delta_swingidx_2g_cck_a_p,
 };
 
 const struct rtw89_phy_tssi_dbw_table rtw89_8852c_tssi_dbw_table = {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
index 7c9f3ecdc4e7..69c95f35b535 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.h
@@ -13,7 +13,7 @@ extern const struct rtw89_phy_table rtw89_8852c_phy_radioa_table;
 extern const struct rtw89_phy_table rtw89_8852c_phy_radiob_table;
 extern const struct rtw89_phy_table rtw89_8852c_phy_nctl_table;
 extern const struct rtw89_phy_tssi_dbw_table rtw89_8852c_tssi_dbw_table;
-extern const struct rtw89_txpwr_track_cfg rtw89_8852c_trk_cfg;
+extern const struct rtw89_fw_txpwr_track_cfg rtw89_8852c_trk_cfg;
 extern const struct rtw89_rfe_parms rtw89_8852c_dflt_parms;
 
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH rtw-next 15/15] wifi: rtw89: set needed firmware elements for early chips transition
  2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
                   ` (13 preceding siblings ...)
  2026-07-07  9:10 ` [PATCH rtw-next 14/15] wifi: rtw89: unify access struct of TX power track tables Ping-Ke Shih
@ 2026-07-07  9:10 ` Ping-Ke Shih
  14 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-07  9:10 UTC (permalink / raw)
  To: linux-wireless; +Cc: gary.chang, echuang

The early chips including RTL8852A, RTL8851B, RTL8852B and RTL8852C have
driver built-in tables, which are not preferred. New firmware is prepared
with corresponding tables in firmware elements, so we can start to
transition. After this patch, old firmware is still usable, but add a
prompt text for users to update firmware.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/fw.c       | 10 +++++++
 drivers/net/wireless/realtek/rtw89/fw.h       | 27 ++++++++++++++++---
 drivers/net/wireless/realtek/rtw89/rtw8851b.c |  3 ++-
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |  3 ++-
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |  3 ++-
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |  3 ++-
 6 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 9d98805835d6..6b293611d5a8 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -1562,6 +1562,7 @@ int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
 	u32 unrecognized_elements = chip->needed_fw_elms;
 	const struct rtw89_fw_element_handler *handler;
 	const struct rtw89_fw_element_hdr *hdr;
+	bool transition;
 	u32 elm_size;
 	u32 elem_id;
 	u32 offset;
@@ -1569,6 +1570,9 @@ int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
 
 	BUILD_BUG_ON(sizeof(chip->needed_fw_elms) * 8 < RTW89_FW_ELEMENT_ID_NUM);
 
+	transition = !!((chip->needed_fw_elms & BIT(__RTW89_FW_ELEMENT_ID_INTL_TRANSITION)));
+	unrecognized_elements &= ~BIT(__RTW89_FW_ELEMENT_ID_INTL_TRANSITION);
+
 	offset = rtw89_mfw_get_size(rtwdev);
 	offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN);
 	if (offset == 0)
@@ -1608,6 +1612,12 @@ int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
 	}
 
 	if (unrecognized_elements) {
+		if (transition) {
+			rtw89_info(rtwdev, "NOTE: This firmware is going to be obsolete!\n"
+				   "Please download the latest firmware from https://gitlab.com/kernel-firmware/linux-firmware.git\n");
+			return 0;
+		}
+
 		rtw89_err(rtwdev, "Firmware elements 0x%08x are unrecognized\n",
 			  unrecognized_elements);
 		return -ENOENT;
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index 71e8554a7af7..e4c81b893780 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -4346,31 +4346,50 @@ enum rtw89_fw_element_id {
 	RTW89_FW_ELEMENT_ID_DIAG_MAC = 28,
 	RTW89_FW_ELEMENT_ID_TX_COMP = 29,
 
+	__RTW89_FW_ELEMENT_ID_INTL_TRANSITION,
 	RTW89_FW_ELEMENT_ID_NUM,
 };
 
+#define BITS_OF_RTW89_TXPWR_FW_ELEMENTS_TX_SHAPE \
+	(BIT(RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT) | \
+	 BIT(RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT_RU))
+
 #define BITS_OF_RTW89_TXPWR_FW_ELEMENTS_NO_6GHZ \
 	(BIT(RTW89_FW_ELEMENT_ID_TXPWR_BYRATE) | \
 	 BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_2GHZ) | \
 	 BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_5GHZ) | \
 	 BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_2GHZ) | \
 	 BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_5GHZ) | \
-	 BIT(RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT) | \
-	 BIT(RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT_RU))
+	 BITS_OF_RTW89_TXPWR_FW_ELEMENTS_TX_SHAPE)
 
 #define BITS_OF_RTW89_TXPWR_FW_ELEMENTS \
 	(BITS_OF_RTW89_TXPWR_FW_ELEMENTS_NO_6GHZ | \
 	 BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_6GHZ) | \
 	 BIT(RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_6GHZ))
 
-#define RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ \
+#define RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_BASE \
 	(BIT(RTW89_FW_ELEMENT_ID_BB_REG) | \
 	 BIT(RTW89_FW_ELEMENT_ID_RADIO_A) | \
 	 BIT(RTW89_FW_ELEMENT_ID_RADIO_B) | \
 	 BIT(RTW89_FW_ELEMENT_ID_RF_NCTL) | \
-	 BIT(RTW89_FW_ELEMENT_ID_TXPWR_TRK) | \
+	 BIT(RTW89_FW_ELEMENT_ID_TXPWR_TRK))
+
+#define RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ \
+	(RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_BASE | \
 	 BITS_OF_RTW89_TXPWR_FW_ELEMENTS_NO_6GHZ)
 
+#define RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS \
+	(RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_BASE | \
+	 BITS_OF_RTW89_TXPWR_FW_ELEMENTS)
+
+#define RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_RTL8852A \
+	(RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ & \
+	 ~BITS_OF_RTW89_TXPWR_FW_ELEMENTS_TX_SHAPE)
+
+#define RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_RTL8851B \
+	(RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ & \
+	 ~BIT(RTW89_FW_ELEMENT_ID_RADIO_B))
+
 #define RTW89_BE_GEN_DEF_NEEDED_FW_ELEMENTS_BASE \
 	(BIT(RTW89_FW_ELEMENT_ID_BB_REG) | \
 	 BIT(RTW89_FW_ELEMENT_ID_RADIO_A) | \
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index d0c262c3dffe..818cf82861d9 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -2637,7 +2637,8 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
 	},
 	.try_ce_fw		= true,
 	.bbmcu_nr		= 0,
-	.needed_fw_elms		= 0,
+	.needed_fw_elms		= RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_RTL8851B |
+				  BIT(__RTW89_FW_ELEMENT_ID_INTL_TRANSITION),
 	.fw_blacklist		= NULL,
 	.fifo_size		= 196608,
 	.small_fifo_size	= true,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 61b6b76c5bdb..08821af48f02 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2374,7 +2374,8 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
 	},
 	.try_ce_fw		= false,
 	.bbmcu_nr		= 0,
-	.needed_fw_elms		= 0,
+	.needed_fw_elms		= RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_RTL8852A |
+				  BIT(__RTW89_FW_ELEMENT_ID_INTL_TRANSITION),
 	.fw_blacklist		= NULL,
 	.fifo_size		= 458752,
 	.small_fifo_size	= false,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index a8638024b54a..5904127cc836 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -968,7 +968,8 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
 	},
 	.try_ce_fw		= true,
 	.bbmcu_nr		= 0,
-	.needed_fw_elms		= 0,
+	.needed_fw_elms		= RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS_NO_6GHZ |
+				  BIT(__RTW89_FW_ELEMENT_ID_INTL_TRANSITION),
 	.fw_blacklist		= &rtw89_fw_blacklist_default,
 	.fifo_size		= 196608,
 	.small_fifo_size	= true,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 52986b982ecd..35cbb59b3e56 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -3173,7 +3173,8 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
 	},
 	.try_ce_fw		= false,
 	.bbmcu_nr		= 0,
-	.needed_fw_elms		= 0,
+	.needed_fw_elms		= RTW89_AX_GEN_DEF_NEEDED_FW_ELEMENTS |
+				  BIT(__RTW89_FW_ELEMENT_ID_INTL_TRANSITION),
 	.fw_blacklist		= &rtw89_fw_blacklist_default,
 	.fifo_size		= 458752,
 	.small_fifo_size	= false,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH rtw-next 01/15] wifi: rtw89: 8922d: remove CCK bandwidth compensation
  2026-07-07  9:10 ` [PATCH rtw-next 01/15] wifi: rtw89: 8922d: remove CCK bandwidth compensation Ping-Ke Shih
@ 2026-07-12  1:55   ` Ping-Ke Shih
  0 siblings, 0 replies; 17+ messages in thread
From: Ping-Ke Shih @ 2026-07-12  1:55 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless; +Cc: gary.chang, echuang

Ping-Ke Shih <pkshih@realtek.com> wrote:

> From: Eric Huang <echuang@realtek.com>
> 
> Remove the 40MHz bandwidth compensation from CCK efuse gain calculation.
> The design no longer requires the +3dB compensation for 40MHz channels.
> 
> Signed-off-by: Eric Huang <echuang@realtek.com>

15 patch(es) applied to rtw-next branch of rtw.git, thanks.

be8aedb68c96 wifi: rtw89: 8922d: remove CCK bandwidth compensation
daa3fda5aeb9 wifi: rtw89: 8922d: dynamic adjust channel smoothing
8da4883c81ae wifi: rtw89: 8922d: fix EMLSR BB switch sequence for MLO mode transition
852927114f6e wifi: rtw89: phy: fix bandedge primary channel for 2.4GHz 40MHz and 6GHz
390f58e29de3 wifi: rtw89: 8922d: set TX compensation by format v2
d193bdc73396 wifi: rtw89: efuse: no need to export rtw89_efuse_read_ecv_be()
4260edb3b1a6 wifi: rtw89: efuse: read thermal calibration value for RTL8922D
4e199cd66614 wifi: rtw89: 8922d: read default digital voltage calibration values
47ad03f1eca5 wifi: rtw89: add thermal protect by digital voltage reduction
b7911466b6db wifi: rtw89: 8922d: set ANA CLK enter to 500KHz
79afed9426ce wifi: rtw89: 8922d: update scaling factor for RX path
9bf6bd6ed5ac wifi: rtw89: 8852a: fix RSSI report when average beacon RSSI is not ready
235fa79d7561 wifi: rtw89: phy: add NCTL check for WiFi 7 chips
5c925d7722c6 wifi: rtw89: unify access struct of TX power track tables
56d32cdc6040 wifi: rtw89: set needed firmware elements for early chips transition

---
https://github.com/pkshih/rtw.git


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2026-07-12  1:55 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-07  9:10 [PATCH rtw-next 00/15] wifi: rtw89: add voltage thermal protect and some random patches for RTL8922D Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 01/15] wifi: rtw89: 8922d: remove CCK bandwidth compensation Ping-Ke Shih
2026-07-12  1:55   ` Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 02/15] wifi: rtw89: 8922d: dynamic adjust channel smoothing Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 03/15] wifi: rtw89: 8922d: fix EMLSR BB switch sequence for MLO mode transition Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 04/15] wifi: rtw89: phy: fix bandedge primary channel for 2.4GHz 40MHz and 6GHz Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 05/15] wifi: rtw89: 8922d: set TX compensation by format v2 Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 06/15] wifi: rtw89: efuse: no need to export rtw89_efuse_read_ecv_be() Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 07/15] wifi: rtw89: efuse: read thermal calibration value for RTL8922D Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 08/15] wifi: rtw89: 8922d: read default digital voltage calibration values Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 09/15] wifi: rtw89: add thermal protect by digital voltage reduction Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 10/15] wifi: rtw89: 8922d: set ANA CLK enter to 500KHz Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 11/15] wifi: rtw89: 8922d: update scaling factor for RX path Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 12/15] wifi: rtw89: 8852a: fix RSSI report when average beacon RSSI is not ready Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 13/15] wifi: rtw89: phy: add NCTL check for WiFi 7 chips Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 14/15] wifi: rtw89: unify access struct of TX power track tables Ping-Ke Shih
2026-07-07  9:10 ` [PATCH rtw-next 15/15] wifi: rtw89: set needed firmware elements for early chips transition Ping-Ke Shih

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox