rtw89_fw_recognize_txpwr_from_elm,
                { .offset = offsetof(struct rtw89_rfe_data, lmt_6ghz.conf) }, NULL,
        },
+       [RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_2GHZ] = {
+               rtw89_fw_recognize_txpwr_from_elm,
+               { .offset = offsetof(struct rtw89_rfe_data, da_lmt_2ghz.conf) }, NULL,
+       },
+       [RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_5GHZ] = {
+               rtw89_fw_recognize_txpwr_from_elm,
+               { .offset = offsetof(struct rtw89_rfe_data, da_lmt_5ghz.conf) }, NULL,
+       },
+       [RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_6GHZ] = {
+               rtw89_fw_recognize_txpwr_from_elm,
+               { .offset = offsetof(struct rtw89_rfe_data, da_lmt_6ghz.conf) }, NULL,
+       },
        [RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_2GHZ] = {
                rtw89_fw_recognize_txpwr_from_elm,
                { .offset = offsetof(struct rtw89_rfe_data, lmt_ru_2ghz.conf) }, NULL,
                rtw89_fw_recognize_txpwr_from_elm,
                { .offset = offsetof(struct rtw89_rfe_data, lmt_ru_6ghz.conf) }, NULL,
        },
+       [RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_2GHZ] = {
+               rtw89_fw_recognize_txpwr_from_elm,
+               { .offset = offsetof(struct rtw89_rfe_data, da_lmt_ru_2ghz.conf) }, NULL,
+       },
+       [RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_5GHZ] = {
+               rtw89_fw_recognize_txpwr_from_elm,
+               { .offset = offsetof(struct rtw89_rfe_data, da_lmt_ru_5ghz.conf) }, NULL,
+       },
+       [RTW89_FW_ELEMENT_ID_TXPWR_DA_LMT_RU_6GHZ] = {
+               rtw89_fw_recognize_txpwr_from_elm,
+               { .offset = offsetof(struct rtw89_rfe_data, da_lmt_ru_6ghz.conf) }, NULL,
+       },
        [RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT] = {
                rtw89_fw_recognize_txpwr_from_elm,
                { .offset = offsetof(struct rtw89_rfe_data, tx_shape_lmt.conf) }, NULL,
        }
 }
 
+static bool rtw89_fw_has_da_txpwr_table(struct rtw89_dev *rtwdev,
+                                       const struct rtw89_rfe_parms *parms)
+{
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+
+       if (chip->support_bands & BIT(NL80211_BAND_2GHZ) &&
+           !(parms->rule_da_2ghz.lmt && parms->rule_da_2ghz.lmt_ru))
+               return false;
+
+       if (chip->support_bands & BIT(NL80211_BAND_5GHZ) &&
+           !(parms->rule_da_5ghz.lmt && parms->rule_da_5ghz.lmt_ru))
+               return false;
+
+       if (chip->support_bands & BIT(NL80211_BAND_6GHZ) &&
+           !(parms->rule_da_6ghz.lmt && parms->rule_da_6ghz.lmt_ru))
+               return false;
+
+       return true;
+}
+
 const struct rtw89_rfe_parms *
 rtw89_load_rfe_data_from_fw(struct rtw89_dev *rtwdev,
                            const struct rtw89_rfe_parms *init)
                parms->rule_6ghz.lmt = &rfe_data->lmt_6ghz.v;
        }
 
+       if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_2ghz.conf)) {
+               rtw89_fw_load_txpwr_lmt_2ghz(&rfe_data->da_lmt_2ghz);
+               parms->rule_da_2ghz.lmt = &rfe_data->da_lmt_2ghz.v;
+       }
+
+       if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_5ghz.conf)) {
+               rtw89_fw_load_txpwr_lmt_5ghz(&rfe_data->da_lmt_5ghz);
+               parms->rule_da_5ghz.lmt = &rfe_data->da_lmt_5ghz.v;
+       }
+
+       if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_6ghz.conf)) {
+               rtw89_fw_load_txpwr_lmt_6ghz(&rfe_data->da_lmt_6ghz);
+               parms->rule_da_6ghz.lmt = &rfe_data->da_lmt_6ghz.v;
+       }
+
        if (rtw89_txpwr_conf_valid(&rfe_data->lmt_ru_2ghz.conf)) {
                rtw89_fw_load_txpwr_lmt_ru_2ghz(&rfe_data->lmt_ru_2ghz);
                parms->rule_2ghz.lmt_ru = &rfe_data->lmt_ru_2ghz.v;
                parms->rule_6ghz.lmt_ru = &rfe_data->lmt_ru_6ghz.v;
        }
 
+       if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_ru_2ghz.conf)) {
+               rtw89_fw_load_txpwr_lmt_ru_2ghz(&rfe_data->da_lmt_ru_2ghz);
+               parms->rule_da_2ghz.lmt_ru = &rfe_data->da_lmt_ru_2ghz.v;
+       }
+
+       if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_ru_5ghz.conf)) {
+               rtw89_fw_load_txpwr_lmt_ru_5ghz(&rfe_data->da_lmt_ru_5ghz);
+               parms->rule_da_5ghz.lmt_ru = &rfe_data->da_lmt_ru_5ghz.v;
+       }
+
+       if (rtw89_txpwr_conf_valid(&rfe_data->da_lmt_ru_6ghz.conf)) {
+               rtw89_fw_load_txpwr_lmt_ru_6ghz(&rfe_data->da_lmt_ru_6ghz);
+               parms->rule_da_6ghz.lmt_ru = &rfe_data->da_lmt_ru_6ghz.v;
+       }
+
        if (rtw89_txpwr_conf_valid(&rfe_data->tx_shape_lmt.conf)) {
                rtw89_fw_load_tx_shape_lmt(&rfe_data->tx_shape_lmt);
                parms->tx_shape.lmt = &rfe_data->tx_shape_lmt.v;
                parms->tx_shape.lmt_ru = &rfe_data->tx_shape_lmt_ru.v;
        }
 
+       parms->has_da = rtw89_fw_has_da_txpwr_table(rtwdev, parms);
+
        return parms;
 }
 
                   ant_gain->offset[path][subband_h]);
 }
 
-static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, u8 band, u32 center_freq)
+static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, u32 center_freq)
 {
-       struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
-       const struct rtw89_chip_info *chip = rtwdev->chip;
-       u8 regd = rtw89_regd_get(rtwdev, band);
        s8 offset_patha, offset_pathb;
 
-       if (!chip->support_ant_gain)
-               return 0;
-
-       if (ant_gain->block_country || !(ant_gain->regd_enabled & BIT(regd)))
-               return 0;
-
        offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, center_freq);
        offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, center_freq);
 
        return max(offset_patha, offset_pathb);
 }
 
-s16 rtw89_phy_ant_gain_pwr_offset(struct rtw89_dev *rtwdev,
-                                 const struct rtw89_chan *chan)
+static bool rtw89_can_apply_ant_gain(struct rtw89_dev *rtwdev, u8 band)
 {
+       const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
        struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
        const struct rtw89_chip_info *chip = rtwdev->chip;
-       u8 regd = rtw89_regd_get(rtwdev, chan->band_type);
-       s8 offset_patha, offset_pathb;
+       u8 regd = rtw89_regd_get(rtwdev, band);
 
        if (!chip->support_ant_gain)
-               return 0;
+               return false;
 
        if (ant_gain->block_country || !(ant_gain->regd_enabled & BIT(regd)))
+               return false;
+
+       if (!rfe_parms->has_da)
+               return false;
+
+       return true;
+}
+
+s16 rtw89_phy_ant_gain_pwr_offset(struct rtw89_dev *rtwdev,
+                                 const struct rtw89_chan *chan)
+{
+       s8 offset_patha, offset_pathb;
+
+       if (!rtw89_can_apply_ant_gain(rtwdev, chan->band_type))
                return 0;
 
        if (RTW89_CHK_FW_FEATURE(NO_POWER_DIFFERENCE, &rtwdev->fw))
 int rtw89_print_ant_gain(struct rtw89_dev *rtwdev, char *buf, size_t bufsz,
                         const struct rtw89_chan *chan)
 {
-       struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
-       const struct rtw89_chip_info *chip = rtwdev->chip;
-       u8 regd = rtw89_regd_get(rtwdev, chan->band_type);
        char *p = buf, *end = buf + bufsz;
        s8 offset_patha, offset_pathb;
 
-       if (!(chip->support_ant_gain && (ant_gain->regd_enabled & BIT(regd))) ||
-           ant_gain->block_country) {
+       if (!rtw89_can_apply_ant_gain(rtwdev, chan->band_type)) {
                p += scnprintf(p, end - p, "no DAG is applied\n");
                goto out;
        }
                              u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch)
 {
        const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
+       const struct rtw89_txpwr_rule_2ghz *rule_da_2ghz = &rfe_parms->rule_da_2ghz;
+       const struct rtw89_txpwr_rule_5ghz *rule_da_5ghz = &rfe_parms->rule_da_5ghz;
+       const struct rtw89_txpwr_rule_6ghz *rule_da_6ghz = &rfe_parms->rule_da_6ghz;
        const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
        const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
        const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
        struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
        enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
+       bool has_ant_gain = rtw89_can_apply_ant_gain(rtwdev, band);
        u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
        u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
+       s8 lmt = 0, da_lmt = S8_MAX, sar, offset = 0;
        u8 regd = rtw89_regd_get(rtwdev, band);
        u8 reg6 = regulatory->reg_6ghz_power;
        struct rtw89_sar_parm sar_parm = {
                .center_freq = freq,
                .ntx = ntx,
        };
-       s8 lmt = 0, sar, offset;
        s8 cstr;
 
        switch (band) {
        case RTW89_BAND_2G:
+               if (has_ant_gain)
+                       da_lmt = (*rule_da_2ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
+
                lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
                if (lmt)
                        break;
                lmt = (*rule_2ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
                break;
        case RTW89_BAND_5G:
+               if (has_ant_gain)
+                       da_lmt = (*rule_da_5ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
+
                lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx];
                if (lmt)
                        break;
                lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx];
                break;
        case RTW89_BAND_6G:
+               if (has_ant_gain)
+                       da_lmt = (*rule_da_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx];
+
                lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx];
                if (lmt)
                        break;
                return 0;
        }
 
-       offset = rtw89_phy_ant_gain_offset(rtwdev, band, freq);
-       lmt = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt + offset);
+       da_lmt = da_lmt ?: S8_MAX;
+       if (da_lmt != S8_MAX)
+               offset = rtw89_phy_ant_gain_offset(rtwdev, freq);
+
+       lmt = rtw89_phy_txpwr_rf_to_mac(rtwdev, min(lmt + offset, da_lmt));
        sar = rtw89_query_sar(rtwdev, &sar_parm);
        cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);
 
                                 u8 ru, u8 ntx, u8 ch)
 {
        const struct rtw89_rfe_parms *rfe_parms = rtwdev->rfe_parms;
+       const struct rtw89_txpwr_rule_2ghz *rule_da_2ghz = &rfe_parms->rule_da_2ghz;
+       const struct rtw89_txpwr_rule_5ghz *rule_da_5ghz = &rfe_parms->rule_da_5ghz;
+       const struct rtw89_txpwr_rule_6ghz *rule_da_6ghz = &rfe_parms->rule_da_6ghz;
        const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz;
        const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz;
        const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz;
        struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
        enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
+       bool has_ant_gain = rtw89_can_apply_ant_gain(rtwdev, band);
        u32 freq = ieee80211_channel_to_frequency(ch, nl_band);
        u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
+       s8 lmt_ru = 0, da_lmt_ru = S8_MAX, sar, offset = 0;
        u8 regd = rtw89_regd_get(rtwdev, band);
        u8 reg6 = regulatory->reg_6ghz_power;
        struct rtw89_sar_parm sar_parm = {
                .center_freq = freq,
                .ntx = ntx,
        };
-       s8 lmt_ru = 0, sar, offset;
        s8 cstr;
 
        switch (band) {
        case RTW89_BAND_2G:
+               if (has_ant_gain)
+                       da_lmt_ru = (*rule_da_2ghz->lmt_ru)[ru][ntx][regd][ch_idx];
+
                lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][regd][ch_idx];
                if (lmt_ru)
                        break;
                lmt_ru = (*rule_2ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
                break;
        case RTW89_BAND_5G:
+               if (has_ant_gain)
+                       da_lmt_ru = (*rule_da_5ghz->lmt_ru)[ru][ntx][regd][ch_idx];
+
                lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][regd][ch_idx];
                if (lmt_ru)
                        break;
                lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx];
                break;
        case RTW89_BAND_6G:
+               if (has_ant_gain)
+                       da_lmt_ru = (*rule_da_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx];
+
                lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx];
                if (lmt_ru)
                        break;
                return 0;
        }
 
-       offset = rtw89_phy_ant_gain_offset(rtwdev, band, freq);
-       lmt_ru = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt_ru + offset);
+       da_lmt_ru = da_lmt_ru ?: S8_MAX;
+       if (da_lmt_ru != S8_MAX)
+               offset = rtw89_phy_ant_gain_offset(rtwdev, freq);
+
+       lmt_ru = rtw89_phy_txpwr_rf_to_mac(rtwdev, min(lmt_ru + offset, da_lmt_ru));
        sar = rtw89_query_sar(rtwdev, &sar_parm);
        cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);