diff --git a/drivers/net/wireless/realtek/rtw88/sar.c b/drivers/net/wireless/realtek/rtw88/sar.c
index d81a6511f138..80b8913d1a49 100644
--- a/drivers/net/wireless/realtek/rtw88/sar.c
+++ b/drivers/net/wireless/realtek/rtw88/sar.c
@@ -267,17 +267,101 @@ union rtw_sar_rwgs {
 	struct rtw_sar_rwgs_rt rt;
 };
 
+struct rtw_sar_geo_map {
+	int idx;	/* index of rwgs.geo[] */
+	int rd;		/* RTW_REGD_xxx */
+};
+
+static const struct rtw_sar_geo_map geo_map_hp[] = {
+	{RTW_SAR_RWGS_HP_FCC_IC,   RTW_REGD_FCC},
+	{RTW_SAR_RWGS_HP_FCC_IC,   RTW_REGD_IC},
+	{RTW_SAR_RWGS_HP_ETSI_MKK, RTW_REGD_ETSI},
+	{RTW_SAR_RWGS_HP_ETSI_MKK, RTW_REGD_MKK},
+	{RTW_SAR_RWGS_HP_WW_KCC,   RTW_REGD_KCC},
+	{RTW_SAR_RWGS_HP_WW_KCC,   RTW_REGD_WW},
+};
+
+static const struct rtw_sar_geo_map geo_map_rt[] = {
+	{RTW_SAR_RWGS_RT_FCC, RTW_REGD_FCC},
+	{RTW_SAR_RWGS_RT_CE,  RTW_REGD_ETSI},
+	{RTW_SAR_RWGS_RT_MKK, RTW_REGD_MKK},
+	{RTW_SAR_RWGS_RT_IC,  RTW_REGD_IC},
+	{RTW_SAR_RWGS_RT_KCC, RTW_REGD_KCC},
+	{RTW_SAR_RWGS_RT_WW,  RTW_REGD_WW},
+};
+
 struct rtw_sar_read {
+	int (*rwsi_mode)(struct rtw_dev *rtwdev, int path);
+	int (*rwrd_base_q3)(struct rtw_dev *rtwdev, int mode, int path, int chidx);
+	int (*rwgs_delta_q3)(struct rtw_dev *rtwdev, int gi, int path, int band);
+	int (*rwgs_max_q3)(struct rtw_dev *rtwdev, int gi, int band);
+	const struct rtw_sar_geo_map *gm, *gm_end;
 	int rwsi_sz;
 	int rwgs_sz;
 };
 
+static int rwsi_mode_hp(struct rtw_dev *rtwdev, int path)
+{
+	return rtwdev->sar.rwsi->hp.index[path] - 1;
+}
+
+static int rwrd_base_q3_hp(struct rtw_dev *rtwdev, int mode, int path, int chidx)
+{
+	int sar;
+
+	sar = rtwdev->sar.rwrd->mode[mode].chain[path].limit[chidx];
+
+	return (10 << 3) + (sar << 2);
+}
+
+static int rwgs_delta_q3_hp(struct rtw_dev *rtwdev, int gi, int path, int band)
+{
+	return rtwdev->sar.rwgs->hp.geo[gi].band[band].delta[path] << 2;
+}
+
+static int rwgs_max_q3_hp(struct rtw_dev *rtwdev, int gi, int band)
+{
+	return (10 << 3) + (rtwdev->sar.rwgs->hp.geo[gi].band[band].max << 2);
+}
+
 static const struct rtw_sar_read sar_read_hp = {
+	.rwsi_mode = rwsi_mode_hp,
+	.rwrd_base_q3 = rwrd_base_q3_hp,
+	.rwgs_delta_q3 = rwgs_delta_q3_hp,
+	.rwgs_max_q3 = rwgs_max_q3_hp,
+	.gm = geo_map_hp,
+	.gm_end = geo_map_hp + ARRAY_SIZE(geo_map_hp),
 	.rwsi_sz = sizeof(struct rtw_sar_rwsi_hp),
 	.rwgs_sz = sizeof(struct rtw_sar_rwgs_hp),
 };
 
+static int rwsi_mode_rt(struct rtw_dev *rtwdev, int path)
+{
+	return rtwdev->sar.rwsi->rt.index - 1;
+}
+
+static int rwrd_base_q3_rt(struct rtw_dev *rtwdev, int mode, int path, int chidx)
+{
+	return rtwdev->sar.rwrd->mode[mode].chain[path].limit[chidx] << 3;
+}
+
+static int rwgs_delta_q3_rt(struct rtw_dev *rtwdev, int gi, int path, int band)
+{
+	return rtwdev->sar.rwgs->rt.geo[gi].band[band].delta << 2;
+}
+
+static int rwgs_max_q3_rt(struct rtw_dev *rtwdev, int gi, int band)
+{
+	return rtwdev->sar.rwgs->rt.geo[gi].band[band].max;
+}
+
 static const struct rtw_sar_read sar_read_rt = {
+	.rwsi_mode = rwsi_mode_rt,
+	.rwrd_base_q3 = rwrd_base_q3_rt,
+	.rwgs_delta_q3 = rwgs_delta_q3_rt,
+	.rwgs_max_q3 = rwgs_max_q3_rt,
+	.gm = geo_map_rt,
+	.gm_end = geo_map_rt + ARRAY_SIZE(geo_map_rt),
 	.rwsi_sz = sizeof(struct rtw_sar_rwsi_rt),
 	.rwgs_sz = sizeof(struct rtw_sar_rwgs_rt),
 };
@@ -420,6 +504,49 @@ static bool is_valid_rwgs(struct rtw_dev *rtwdev, const struct rtw_sar_rwrd *rwr
 	return false;
 }
 
+static void rtw_sar_apply_dynamic_tables(struct rtw_dev *rtwdev)
+{
+	struct rtw_hal *hal = &rtwdev->hal;
+	const struct rtw_sar_read *r = rtwdev->sar.read;
+	const struct rtw_sar_geo_map *gm = r->gm;
+	const struct rtw_sar_geo_map *gm_end = r->gm_end;
+	int path_num = min_t(int, RTW_SAR_RWRD_CHAIN_NR, hal->rf_path_num);
+	int path, mode;
+	int sar, delta, max;
+
+	for (; gm < gm_end; gm++) {
+		for (path = 0; path < path_num; path++) {
+			mode = r->rwsi_mode(rtwdev, path);
+
+			/* 2.4G part */
+			delta = r->rwgs_delta_q3(rtwdev, gm->idx, path, RTW_SAR_RWGS_2G);
+			max = r->rwgs_max_q3(rtwdev, gm->idx, RTW_SAR_RWGS_2G);
+
+			sar = r->rwrd_base_q3(rtwdev, mode, path, RTW_SAR_LMT_CH1_14);
+			sar = min(sar + delta, max);
+			rtw_phy_set_tx_power_sar(rtwdev, gm->rd, path, 1, 14, sar);
+
+			/* 5G part */
+			delta = r->rwgs_delta_q3(rtwdev, gm->idx, path, RTW_SAR_RWGS_5G);
+			max = r->rwgs_max_q3(rtwdev, gm->idx, RTW_SAR_RWGS_5G);
+
+			sar = r->rwrd_base_q3(rtwdev, mode, path, RTW_SAR_LMT_CH36_64);
+			sar = min(sar + delta, max);
+			rtw_phy_set_tx_power_sar(rtwdev, gm->rd, path, 36, 64, sar);
+
+			sar = r->rwrd_base_q3(rtwdev, mode, path, RTW_SAR_LMT_CH100_144);
+			sar = min(sar + delta, max);
+			rtw_phy_set_tx_power_sar(rtwdev, gm->rd, path, 100, 144, sar);
+
+			sar = r->rwrd_base_q3(rtwdev, mode, path, RTW_SAR_LMT_CH149_165);
+			sar = min(sar + delta, max);
+			rtw_phy_set_tx_power_sar(rtwdev, gm->rd, path, 149, 165, sar);
+		}
+	}
+
+	rtwdev->sar.source = RTW_SAR_SOURCE_ACPI_DYNAMIC;
+}
+
 static int rtw_sar_load_dynamic_tables(struct rtw_dev *rtwdev)
 {
 	struct rtw_sar_rwrd *rwrd;
@@ -457,6 +584,8 @@ static int rtw_sar_load_dynamic_tables(struct rtw_dev *rtwdev)
 	rtwdev->sar.rwsi = rwsi;
 	rtwdev->sar.rwgs = rwgs;
 
+	rtw_sar_apply_dynamic_tables(rtwdev);
+
 	rtw_dbg(rtwdev, RTW_DBG_REGD, "SAR: RWRD/RWSI/RWGS is adopted\n");
 
 	return 0;
