git: cf6b389f7c48 - main - rtwn: add tx power training for RTL8812/RTL8821

From: Adrian Chadd <adrian_at_FreeBSD.org>
Date: Wed, 18 Dec 2024 19:32:39 UTC
The branch main has been updated by adrian:

URL: https://cgit.FreeBSD.org/src/commit/?id=cf6b389f7c485f735c3d84a7e3fe6833e91321e4

commit cf6b389f7c485f735c3d84a7e3fe6833e91321e4
Author:     Adrian Chadd <adrian@FreeBSD.org>
AuthorDate: 2024-12-07 15:47:45 +0000
Commit:     Adrian Chadd <adrian@FreeBSD.org>
CommitDate: 2024-12-18 19:31:18 +0000

    rtwn: add tx power training for RTL8812/RTL8821
    
    This apparently kicks off TX power level self-calibration, which
    can't hurt.
    
    Locally tested:
    
    * RTL8812AU, STA
    * RTL8821AU, STA
    
    Obtained from:  Linux rtw88
    
    Differential Revision:  https://reviews.freebsd.org/D47978
    
    Reviewed by:    bz, imp
---
 sys/dev/rtwn/rtl8812a/r12a_chan.c | 32 ++++++++++++++++++++++++++++++++
 sys/dev/rtwn/rtl8812a/r12a_reg.h  |  1 +
 2 files changed, 33 insertions(+)

diff --git a/sys/dev/rtwn/rtl8812a/r12a_chan.c b/sys/dev/rtwn/rtl8812a/r12a_chan.c
index 749f0e09e831..d71e0a8177fd 100644
--- a/sys/dev/rtwn/rtl8812a/r12a_chan.c
+++ b/sys/dev/rtwn/rtl8812a/r12a_chan.c
@@ -180,6 +180,36 @@ r12a_write_txpower_ofdm(struct rtwn_softc *sc, int chain,
 	    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(struct rtwn_softc *sc, int chain,
 	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
index 13867fb76973..f1fc4ee2f302 100644
--- 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)