24 KiB
Native AMD GPU support — feasibility and roadmap
Status: research snapshot, not implemented. This records what a minimal, display-only
native driver for a real discrete AMD GPU — specifically an RX 6600-class card (Navi 23,
RDNA2, DCN 3.0.2), the market analog of the RTX 3060 — would take, and how it slots into
danos's pluggable scanout architecture. It is a survey of primary sources (the Linux
amdgpu Display Core
driver and its kernel documentation,
the AtomBIOS interpreter in
drivers/gpu/drm/amd,
linux-firmware's LICENSE.amdgpu, and Haiku's
radeon_hd),
not an implementation. It completes the trilogy with nvidia-gpus.md and
intel-igpu.md and should be read against both — AMD lands between them:
NVIDIA-class discrete-card mechanics, but Intel-class (better, in one way) reference material.
Read display.md and display-v2.md first — this doc assumes the
v2 model where scanout is a pluggable backend and a native driver is just another .scanout
service (like the virtio-gpu one), announcing to the compositor over attach_scanout.
TL;DR
- AMD's decisive advantage is that the vendor's own display driver is the register manual, and
it's MIT-licensed. The entire Display Core (DC) — hardware sequencer, per-block code for
OTG/OPTC, HUBP, DPP, MPC, DIO/link encoders, plus the
asic_regregister headers — ships in the Linux tree under MIT/X11, deliberately written OS-agnostic because AMD shares it across operating systems. You can study it, port it, even copy from it into a danos driver without license contamination. NVIDIA has no analog (nouveau is GPL); Intel has PRM prose but you still write the code yourself. - The firmware wall is one small blob, not a GSP. The only display-side firmware the Linux
driver hard-requires is DMCUB (the display microcontroller), and only on DCN 2.1
through 4.x — which includes Navi 23. It is redistributable from linux-firmware, and it is
a display helper, not a full-card resource manager: on DCN 3.0.x, hardware init
(
dcn30_init_hw) is host-driven direct register programming — the only DMUB call in it is a capability query. All DCE generations, DCN 1.0 (Raven), and DCN 2.0 (Navi 10/12/14) run display with no display firmware at all. - Whether the silicon (vs. the Linux driver) needs DMCUB for a bare GOP-inheriting modeset
is unproven — Linux fails init with
-EINVALif the blob is missing on a DMUB ASIC, but what it's used for at minimum scope (vs. PSR/ABM/offloaded DP link training) isn't documented. The safe plan ships the blob; it's legally and practically cheap to do so. - Programming model is direct MMIO, not channel DMA. DCN mode-set is ordered register-write sequences (the DC "hardware sequencer") against named, header-documented registers — no pushbuffers, no method streams, no RAMHT, no supervisor-interrupt handshake. This deletes the hardest structural layer of the NVIDIA path.
- Scanout is VRAM-only on discrete cards — the claim that DCN can scan out of GTT/system memory was checked and refuted for dGPUs (Linux allows GTT scanout only on select APUs). So a small VRAM allocator + BAR CPU mapping is required, same as NVIDIA. Pitch-linear surfaces are supported; no DCC/tiling needed.
- danos's GOP boot helps here too, with a caveat. DC explicitly models taking over a
VBIOS/GOP-lit pipe (
dc_validate_boot_timingreads back live DIG/OTG/pixel-clock state), so "repoint the surface on the running pipe" is demonstrably hardware-feasible — but Linux's seamless-boot path is eDP-only and default-off on discrete cards, so plan on a full self-owned modeset (including DP retrain) right after first light rather than living on the inherited link. - AMD has real non-Linux prior art — but only for the old hardware. Haiku's MIT
radeon_hdmode-sets by executing VBIOS AtomBIOS command tables through AMD's own MIT interpreter; its compiled-in ceiling is DCE 8.5 (Hawaii, ~2013) — every Polaris/Vega/Navi entry sits in a#if 0block. There is zero non-Linux DCN precedent; a danos DCN driver would be first. - Effort tier ≈ high-3 to 4 for a native DCN 3.0.x display-only driver on Navi 23 — the raw register surface is GA106-class (tier 4), but the MIT vendor reference, the one-blob firmware wall, and the absence of channel-DMA plumbing pull real risk out. The AtomBIOS-interpreter route is tier ≈ 3 but dead-ends at pre-2016 silicon.
- Recommendation: the same sober conclusion as the other two docs — GOP already gives native-res scanout for zero code — but if danos ever does drive real discrete silicon natively, an RDNA2 card is the best target of the three: modern, mainstream, in-warranty hardware with a legally clean, vendor-authored reference. That combination exists nowhere else.
The firmware wall (a fence, next to NVIDIA's wall)
AMD GPUs carry a zoo of firmware: PSP (security processor), SMU (power/clock management), CP/RLC
(graphics), SDMA, VCN (media) — and, on the display side, DMCU (legacy) then DMCUB
("Display Micro-Controller Unit, version B"), a per-generation blob in linux-firmware
(navi23_dmcub.bin etc.). The display-only question is: which of these does a scanout driver
actually need?
The Linux answer is precise and readable in
amdgpu_dm.c:
dm_init_microcode() switches on the display IP version — DCN 2.1 (Renoir) through DCN
3.0.x / 3.1.x / 3.2 / 3.5 / 4.x request a DMCUB blob as AMDGPU_UCODE_REQUIRED, and
dm_dmub_hw_init() fails driver init with -EINVAL if it's absent. Everything earlier — all
of DCE (Southern Islands through Vega), DCN 1.0 (Raven), and DCN 2.0 (Navi 10/12/14) — hits
the default: case, dmub_srv stays NULL, and display runs with no display firmware at all
(kernel display-manager doc).
Two nuances survive verification:
- The requirement is Linux-driver enforcement backed by real functional need, and it's
version-sensitive. AMD force-switched all Renoir ASICs to DMUB to fix a USB-C/resume bug
(kernel commit
652de07addd2, "with new dmub f/w dmcu is superseded"), which regressed users on old blobs and had to be patched with explicitdmcub_fw_versiongating (91adec9e0709). What DMUB is used for varies with blob version. Ship a current blob. - DMCUB is an architectural fixture, not a bolt-on — the DCN hardware itself contains a DMU
block housing the microcontroller
(DCN overview) — but it is
not a mediator of the programming model on DCN 3.0:
dcn30_init_hw()initializes clocks, disables power gating, and powers up link encoders via direct register writes; its sole DMUB interaction isdc_dmub_srv_query_caps_cmd. Firmware-assisted PHY/link bring-up appears from DCN 3.1 onward — one more reason to target 3.0.x. Features like PSR and ABM are DMUB-offloaded on all generations; a minimal driver simply doesn't enable them.
Contrast with NVIDIA's GSP: the GSP is a full resource manager with a signed multi-stage boot chain and a firmware ABI that breaks every driver release. DMCUB is a display helper blob you copy onto the boot image once, load into a reserved buffer, and mostly ignore. There is no signature fuse-matching, no WPR carve-out, no RPC-only register access. The one genuinely open question — whether a GOP-inheriting minimal modeset could skip DMCUB entirely on DCN 3.0.2 — doesn't need answering, because shipping the blob costs nothing (see Licensing).
PSP/SMU remain the flagged risk. Nothing display-only touches CP/RLC/SDMA (those gate the
graphics rings, exactly like NVIDIA's PGRAPH — irrelevant here). But dcn30_init_hw calls into
the clock manager, and on discrete cards the clock manager may message the SMU to change display
clocks (DISPCLK/DPPCLK). Whether inherited GOP boot clocks suffice for a same-or-lower mode —
avoiding SMU (and hence PSP firmware-load) entirely — is the largest unverified assumption in
the milestone list below. The survey produced no confirmed claim either way.
The display engine landscape
Two eras, one boundary that matters:
| Generation | Display IP | Cards | Display firmware | Route |
|---|---|---|---|---|
| GCN 1–4 (SI→Polaris) | DCE 6/8/10/11 | HD 7000 → RX 580 | none | AtomBIOS tables or direct DCE registers |
| Vega / Raven | DCE 12 / DCN 1.0 | Vega 56/64, APUs | none | DC code (first DCN) |
| Navi 1x (RDNA1) | DCN 2.0 | RX 5500–5700 | none | DC code |
| Renoir APU | DCN 2.1 | 4000-series APUs | DMCUB required | DC code |
| Navi 2x (RDNA2) | DCN 3.0.x | RX 6600–6900 | DMCUB required | DC code, host-driven init |
| RDNA3/RDNA4+ | DCN 3.1+/3.2/3.5/4.x | RX 7000/9000 | DMCUB required, fw-assisted PHY | DC code, more DMUB offload |
The best modern first-pixel target is DCN 3.0.x: it has the full MIT block stack from the June 2020 Sienna Cichlid patch series (207 patches, Linux 5.9; Navi 23 reuses the dcn30 sequencer), host-driven hardware init, and sits before the DCN 3.1 shift toward firmware-assisted link management. Older DCE cards are even simpler (no firmware at all, plus the AtomBIOS escape hatch) but are 2013–2016 hardware; newer DCN 3.5/4.x pushes more into DMUB.
The DCN pipe, in one line each (the vocabulary the DC code speaks — programming model): HUBP fetches and unpacks the surface from memory (this is where the scanout address and pitch live), DPP scales/converts colors, MPC blends planes (bypassable for one plane), OPP packs output, OTG/OPTC generates raster timings (the CRTC), and the DIO block's DIG encoders + PHY drive the connector. Mode-set is the DC hardware sequencer walking these blocks with ordered register writes — plain MMIO with polling, no pushbuffer channels, no supervisor interrupts. Structurally this is Intel-shaped, not NVIDIA-shaped.
Two routes: AtomBIOS interpreter vs. native DC-derived registers
AtomBIOS is AMD's VBIOS bytecode: every card's ROM carries data tables (connector
topology, clock limits — the DCB equivalent) and command tables (SetPixelClock,
SetCRTC_Timing, EnableCRTC, DIG encoder/transmitter control), executed by a small
interpreter the driver embeds (atom.c, ~1.5k lines). The classic radeon driver and Haiku's
radeon_hd mode-set this way: parse the tables, execute them, and the VBIOS does the
register-level work for you — inherently per-board correct, since the tables come from the
card's own ROM.
- Where it's proven: through DCE 8.5 (Haiku's ceiling, below) and in Linux's pre-DC code
through Polaris (DCE 11.2). AMD's interpreter itself is MIT (Haiku ships AMD's own
atom.cpp, "Copyright 2008 Advanced Micro Devices"). - Where it's unproven: DCN. amdgpu's DC still uses AtomBIOS for init sub-steps
(
bios_golden_initindcn30_init_hwexecutes host-interpreted tables) and reads the data tables for connector topology — but nobody drives a full DCN modeset from command tables, and whether RDNA2 VBIOSes still carry a complete modeset path or vestigial init-only tables is an open question no source answers. Do not bet on it.
The native route is: port the relevant slice of DC. Not wholesale — in-tree DC has
accumulated Linux-isms (kernel-FPU guards around DML, the bandwidth-calculation library, which a
single-plane fixed-mode driver can largely sidestep) — but the DC core is designed to be
retargeted: the kernel docs state outright that DC "is shared with other OSes" and holds the
OS-agnostic hardware programming behind a dm_services shim (register access, memory, delays,
firmware loading). Dave Airlie initially rejected the DAL/DC merge in 2016 because it was
AMD's cross-OS codebase — hostile-witness confirmation that this exact code runs outside Linux.
Reimplement the shim in Zig, and the dcn30 sequences sit on top.
The memory floor
Same shape as NVIDIA's, and the survey hardened one assumption:
- VRAM-only scanout on discrete cards. The documented DCN fetch path is VRAM → Data Fabric (SDP) → DCHUB → HUBP; the claim that display buffers can live in GTT/system memory was refuted for dGPUs in verification — Linux permits GTT scanout only on select APUs. The NVIDIA doc's "maybe sysmem ctxdma?" hope has a firm no here. Budget for a small VRAM allocator.
- Pitch-linear is fine. HUBP programs a surface address + pitch; linear (untiled, no DCC) surfaces are first-class for scanout. No tiling math.
- CPU access via the VRAM BAR. Compositing writes go through the PCI VRAM aperture; resizable BAR helps but isn't needed — one pitch-linear surface fits comfortably in a fixed 256 MB small-BAR window.
- No GPU VMM. Display addresses are physical VRAM addresses programmed into HUBP; no page tables, no GEM/TTM, no eviction.
Net: (1) a contiguous aligned VRAM allocator, (2) a BAR CPU mapping, (3) a small reserved buffer for the DMCUB firmware regions. That's the whole memory story.
Inheriting GOP state
danos's GOP boot pays off again, with sharper edges than on NVIDIA:
- DC models pipe takeover explicitly.
dc_validate_boot_timing()(dc.c) reads back live hardware —is_dig_enabledon the link encoder, OTG timing registers, pixel clock within tolerance — and keeps the VBIOS/GOP-lit pipe running until first flip. This is a vendor-blessed recipe for milestone 2 below: the exact register set that tells you which pipe is alive and how it's configured. - But Linux's seamless path is eDP-only and APU-gated. The code comment is blunt: "Support
seamless boot on EDP displays only", and the enabling check requires an APU with DCN ≥ 3.0
unless forced with
amdgpu.seamless=1. On a discrete RX 6600 with DP/HDMI, Linux does a full modeset at takeover. Read that as a warning, not a prohibition: repointing HUBP at your own surface on the live pipe should still work (the readback code proves the state is inspectable), but plan the full self-owned modeset — including DP retraining — as the immediate next step, not a someday. - No supervisor handshake exists to re-learn. The NVIDIA doc's SV1/SV2/SV3 open question has no AMD counterpart; commit sequencing is ordered register writes + vblank/lock waits in the hwseq, all visible in MIT source.
Licensing
The inverse of the NVIDIA situation, and the single strongest argument for AMD:
- The reference code is MIT.
amdgpu_dm.ccarriesSPDX-License-Identifier: MIT;dc/core/dc.canddmub_srv.hcarry the full X11-style grant (use, copy, modify, merge, publish, distribute, sell). Theasic_regregister headers ship under the same terms. One diligence note: SPDX tagging isn't uniform across the tree, so header-check each file before copying from it — but no GPL files are known insidedc/. Where nouveau forces a GPL-or-clean-room choice, here the easy technical path and the permissive path are the same path. - Firmware redistribution is a solved problem. linux-firmware's
LICENSE.amdgpugrants anyone a royalty-free right to reproduce and distribute the blobs, binary-only, with the license text attached — no OSI-license gate like NVIDIA's, no AMD agreement needed. danos can shipnavi23_dmcub.bin(and PSP/SMU blobs if ever needed) on its boot image today. The same license prohibits reverse-engineering the blobs — all programming knowledge must come from the MIT source, never from blob disassembly. (VBIOS images aren't in linux-firmware; they're read from the card's own ROM, as Haiku does.) - Prose register docs are a DCE-era artifact. AMD's classic X.Org-hosted PDFs cover the old
families — and the famous
R6xx_3D_Registers.pdfturns out to be 3D-only (verified: zero display content; the display material lives in the separate per-ASIC Register Reference Guides). For DCN there is no prose display spec at all: the MIT DC source plus theasic_regheaders are the register manual. Plan accordingly.
Prior art
AMD, unlike NVIDIA, has genuine working non-Linux precedent — with a hard generational ceiling:
- Haiku
radeon_hd(MIT, still in the tree): a real, shipping, from-scratch display driver that executes AtomBIOS command tables via AMD's own MIT interpreter. Verified ceiling: the last enabled device entry is Hawaii (DCE 8.5, 0x67be); everything newer — Tonga/Fiji, Carrizo/Polaris, Vega/Raven, and every Navi/RDNA2 entry up to the RX 6900 XT — sits inside one#if 0 /* disabled for R1/beta5 */block under the comment "WARN: DCE versions below here get sketchy." - AmigaOS/MorphOS RadeonHD drivers (hdrlab): commercial non-Linux Radeon display drivers, again for the DCE era.
- FreeBSD
drm-kmod: a port of Linux amdgpu (DC and all), not independent prior art — but proof the DC codebase transplants.
Nobody has driven DCN outside Linux-derived code. A danos DCN 3.0.x driver would be a first — but a first with the vendor's MIT code as its map, which is a different proposition from nouveau-as-only-reference.
Alternatives
| Option | What you get | The tradeoff |
|---|---|---|
| Stay on GOP (working today) | Native-res scanout, zero GPU code/firmware/maintenance | Resolution frozen at ExitBootServices; no runtime mode change, no hardware vsync, no multihead |
| AtomBIOS interpreter on an old DCE card | Proven end-to-end (Haiku); interpreter is small + MIT; board-correct by construction | 2013–2016 hardware ceiling; tier ≈ 3; teaches AtomBIOS, not modern DCN |
| Native DCN 3.0.x on RX 6600 (this doc) | Runtime modeset, vsync, multihead on modern silicon; MIT vendor reference; one redistributable blob | Tier ≈ high-3–4; SMU/clock question open; no non-Linux precedent |
Port DC wholesale (reimplement dm_services) |
Vendor-maintained sequences verbatim; designed-for-porting seam | Big codebase to carry (DML, abstractions); Linux-isms to shear off; overkill for one plane |
| RDNA3+/DCN 3.5+ | Newer cards | More DMUB offload (fw-assisted PHY from DCN 3.1); strictly harder than 3.0.x for no display-only gain |
"First light" milestones (native DCN 3.0.x path)
Framed as a danos .scanout service, inheriting the GOP-initialized display:
- PCI/BAR bring-up — enumerate Navi 23, map the register BAR and the VRAM BAR via danos MMIO grants; prove the pipe is GOP-live by writing pixels into the existing GOP framebuffer through the VRAM BAR.
- Read back the live pipe — port the
dc_validate_boot_timingregister set: which OTG is running, its timings, which DIG/link encoder is enabled, current HUBP surface address/pitch. This is pure reads — zero risk, high information. - Repoint the surface — allocate a danos-owned pitch-linear VRAM surface, program the HUBP surface address/pitch on the live pipe at vblank. First self-owned pixel with no modeset, no firmware, no clock changes.
- DMCUB bring-up — load
navi23_dmcub.bin(redistributed perLICENSE.amdgpu) into its reserved regions, minimaldmub_srvinit, verify the caps query answers. - Full owned modeset — port the dcn30 hwseq slice: OTG timing programming, MPC bypass (single plane), DIG/PHY enable, DP link retrain (or start on HDMI to defer it, exactly as the NVIDIA doc advises). This is where the SMU/clock question lands — first attempt: reuse inherited boot clocks for a same-or-lower mode.
- EDID — AUX (DP) / DDC (HDMI) over the DCN AUX engine registers; parse and build the mode list; connector topology from the VBIOS AtomBIOS data tables.
- Wire into the compositor —
attach_scanout, vsync from the vblank/pageflip interrupt, then multihead.
Keep the GOP backend as the fallback the whole way — a stall at any step still leaves danos with a working display (the resilience v2 already provides via re-attach).
Reading list
The DC core (MIT — the register manual for DCN):
drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c— hardware init + the modeset sequencer for the target generation (host-driven; one DMUB caps query).dc/dcn30/+dc/dcn302/blocks:dcn30_hubp.c(surface address/pitch — milestone 3),dcn30_optc.c(OTG timings),dcn30_dio_link_encoder.c(DIG/PHY),dcn30_mpc.c(bypass),clk_mgr/dcn30/(the SMU question, read before milestone 5).dc/core/dc.c—dc_validate_boot_timing(): the GOP-takeover readback recipe.asic_reg/dcn/dcn_3_0_0_{offset,sh_mask}.h— every register name and bitfield.dmub/(dmub_srv.h,src/dmub_dcn30.c) — firmware regions + bring-up for milestone 4.
The Linux glue (for logic, not porting):
amdgpu_dm.c
— dm_init_microcode / dm_dmub_hw_init (the firmware-wall switch), seamless-boot gating.
Kernel docs (read first): DCN overview (the block diagram
- VRAM→DF→DCHUB fetch path) · DC programming model (dc_plane/dc_stream/dc_link objects, hwseq, block APIs) · display manager.
AtomBIOS: drivers/gpu/drm/amd/amdgpu/atom.c (the interpreter), atombios.h (table
formats), osdev AMD AtomBIOS (hobby-OS orientation),
Haiku radeon_hd
(a complete worked example, MIT, through DCE 8.5).
Licensing: linux-firmware
LICENSE.amdgpu;
DCE-era prose specs at x.org/docs/AMD (Register Reference
Guides — display; note R6xx_3D_Registers.pdf is 3D-only).
Open questions (unresolved by the survey)
- Does DCN 3.0.2 silicon need DMCUB for a bare inherit-and-modeset path, or only for PSR/ABM/offloaded features? (Moot if the blob is shipped regardless — but it decides whether milestone 3 can precede milestone 4.)
- Can a display-only driver avoid PSP and SMU entirely by inheriting GOP boot clocks — what does the dcn30 clock manager actually require from SMU messaging on Navi 23 for a same-or-lower mode? The largest open risk in the plan.
- Do RDNA2 VBIOS command tables still carry a complete modeset path, or are they vestigial init-only tables? (Would open a Haiku-style route on modern cards; no source answers it.)
- Is the DCN 3.0 AUX/DDC engine and DP retrain fully host-drivable without DMUB, as
dcn30_hwseqimplies? - Exact HUBP surface alignment/pitch constraints for linear scanout on Navi 23 (in the headers; not captured verbatim in the survey).
Research snapshot (2026-07); findings pinned to Linux master and Haiku master as of the survey
date. DMUB coverage only grows with new DCN generations — re-verify the firmware-wall switch in
amdgpu_dm.c against current source before building.