diff --git a/sys/dev/rtwn/rtl8812a/r12a_chan.c b/sys/dev/rtwn/rtl8812a/r12a_chan.c --- a/sys/dev/rtwn/rtl8812a/r12a_chan.c +++ b/sys/dev/rtwn/rtl8812a/r12a_chan.c @@ -180,6 +180,36 @@ SM(R12A_TXAGC_OFDM54, power[RTWN_RIDX_OFDM54])); } +static void +r12a_tx_power_training(struct rtwn_softc *sc, int chain, + const struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) +{ + uint32_t write_data; + int32_t power_level; + int i; + + write_data = 0; + + power_level = (int32_t) power[RTWN_RIDX_HT_MCS(7)]; + for (i = 0; i < 3; i++) { + if (i == 0) + power_level -= 10; + else if (i == 1) + power_level -= 8; + else + power_level -= 6; + + /* Handle underflow and the minimum value (2) */ + if (power_level < 2) + power_level = 2; + + write_data |= ((power_level & 0xff) << (i * 8)); + } + + rtwn_bb_setbits(sc, R12A_TX_PWR_TRAINING(chain), + 0x00ffffff, write_data); +} + static void r12a_write_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) @@ -189,6 +219,8 @@ r12a_write_txpower_ofdm(sc, chain, c, power); r12a_write_txpower_ht(sc, chain, c, power); r12a_write_txpower_vht(sc, chain, c, power); + + r12a_tx_power_training(sc, chain, c, power); } static int diff --git a/sys/dev/rtwn/rtl8812a/r12a_reg.h b/sys/dev/rtwn/rtl8812a/r12a_reg.h --- a/sys/dev/rtwn/rtl8812a/r12a_reg.h +++ b/sys/dev/rtwn/rtl8812a/r12a_reg.h @@ -124,6 +124,7 @@ #define R12A_TXAGC_NSS2IX5_2IX2(chain) (0xc48 + (chain) * 0x200) #define R12A_TXAGC_NSS2IX9_2IX6(chain) (0xc4c + (chain) * 0x200) #define R12A_INITIAL_GAIN(chain) (0xc50 + (chain) * 0x200) +#define R12A_TX_PWR_TRAINING(chain) (0xc54 + (chain) * 0x200) #define R12A_AFE_POWER_1(chain) (0xc60 + (chain) * 0x200) #define R12A_AFE_POWER_2(chain) (0xc64 + (chain) * 0x200) #define R12A_SLEEP_NAV(chain) (0xc80 + (chain) * 0x200)