Gap
Jaguar2 is the only chip family in devourer with no thermal TX-power tracking:
- Jaguar1 (
src/jaguar1/PowerTracking8812a.cpp): reads the RF thermal meter (RF 0x42[15:10]), computes delta vs the EFUSE baseline, looks up the per-band/per-path delta-swing tables (hal/phydm/rtl8812a/Hal8812a_TxPwrTrack.cpp) and writes the compensating BB TX-scale into 0xc1c/0xe1c[31:21] — both on every channel set and from the watchdog tick.
- Jaguar3 (
Halrf8822c::pwr_track / Halrf8822e::thermal_track_8822e): reads RF 0x42 per path, compares vs the efuse baseline (0xd0/0xd1 on the E), writes compensation into the TX-power-adjust registers 0x18a0/0x41a0, driven every ~2 s from the coex runtime thread; the 8822C additionally re-runs LCK when thermal delta ≥ 8.
- Jaguar2 (
src/jaguar2/): nothing. HalJaguar2::apply_tx_power programs the EFUSE-calibrated TXAGC (0x1d00/0x1d80) once at bring-up and it never moves again. There is no thermal meter read, no delta-swing table, no compensation write.
Consequence
On a sustained TX session (the OpenIPC long-range video use case) the PA heats, gain drops, and on-air power drifts down with nothing correcting for it — exactly the drift the other two families compensate. The 8822BU/8821CU are also uncovered by DEVOURER_THERMAL_POLL_MS reaction (the poll itself is read-only everywhere, but on J1/J3 the driver reacts; on J2 it doesn't).
What porting looks like
The vendor rtl88x2bu / rtl8821cu trees carry the halrf power-tracking implementation this HAL was ported from, minus this piece:
- Thermal meter read on
RF 0x42 (same register family as J1/J3) + EFUSE thermal baseline from the existing _efuse_map.
- Per-variant delta-swing tables (8822B and 8821C have separate tables in the vendor
halrf/rtl8822b/halhwimg8822b_rf.c / rtl8821c halrf) — likely extracted by a generator under tools/, like the existing txpwr_lmt extractors.
- Compensation write — vendor 8822B/8821C power tracking adjusts via the TXAGC diff/BB path; follow whichever register the vendor tracker actually writes rather than assuming the J1 BB-swing (
0xc1c) layout.
- A periodic tick. Jaguar2 already runs a DIG thread; the thermal tick can ride the same cadence (J3 precedent: piggyback on a runtime loop, serialize against retune).
- LCK re-trigger on large thermal delta (vendor parity, matches the J3 8822C behaviour).
Validation
DEVOURER_THERMAL_POLL_MS markers + SDR receive-power ground truth over a long full-duty TX soak (tests/thermal_gain_sweep.py harness, DEVOURER_TX_GAP_US=0 for max heating): on-air power should stay flat as delta climbs, instead of sagging.
- No-regression check on cold-boot TXAGC (register parity before/after first tick at delta=0).
Gap
Jaguar2 is the only chip family in devourer with no thermal TX-power tracking:
src/jaguar1/PowerTracking8812a.cpp): reads the RF thermal meter (RF 0x42[15:10]), computes delta vs the EFUSE baseline, looks up the per-band/per-path delta-swing tables (hal/phydm/rtl8812a/Hal8812a_TxPwrTrack.cpp) and writes the compensating BB TX-scale into0xc1c/0xe1c[31:21]— both on every channel set and from the watchdog tick.Halrf8822c::pwr_track/Halrf8822e::thermal_track_8822e): readsRF 0x42per path, compares vs the efuse baseline (0xd0/0xd1on the E), writes compensation into the TX-power-adjust registers0x18a0/0x41a0, driven every ~2 s from the coex runtime thread; the 8822C additionally re-runs LCK when thermal delta ≥ 8.src/jaguar2/): nothing.HalJaguar2::apply_tx_powerprograms the EFUSE-calibrated TXAGC (0x1d00/0x1d80) once at bring-up and it never moves again. There is no thermal meter read, no delta-swing table, no compensation write.Consequence
On a sustained TX session (the OpenIPC long-range video use case) the PA heats, gain drops, and on-air power drifts down with nothing correcting for it — exactly the drift the other two families compensate. The 8822BU/8821CU are also uncovered by
DEVOURER_THERMAL_POLL_MSreaction (the poll itself is read-only everywhere, but on J1/J3 the driver reacts; on J2 it doesn't).What porting looks like
The vendor rtl88x2bu / rtl8821cu trees carry the halrf power-tracking implementation this HAL was ported from, minus this piece:
RF 0x42(same register family as J1/J3) + EFUSE thermal baseline from the existing_efuse_map.halrf/rtl8822b/halhwimg8822b_rf.c/rtl8821chalrf) — likely extracted by a generator undertools/, like the existing txpwr_lmt extractors.0xc1c) layout.Validation
DEVOURER_THERMAL_POLL_MSmarkers + SDR receive-power ground truth over a long full-duty TX soak (tests/thermal_gain_sweep.pyharness,DEVOURER_TX_GAP_US=0for max heating): on-air power should stay flat asdeltaclimbs, instead of sagging.