docs(gpu): DCN315 closure record + AGENTS.md surface list (closure-first)
redbear-ci / check (push) Has been cancelled

This commit is contained in:
2026-08-05 08:29:51 +03:00
parent 1625af95d3
commit 5c4f7d2580
3 changed files with 843 additions and 1 deletions
@@ -0,0 +1,43 @@
TASK 33 — DCN315 Minimal Display Slice Closure Record
=====================================================
Status: FIRST DELIVERABLE COMPLETE (2026-08-05)
Artifacts produced:
1. local/docs/evidence/ryzen-x670e/dcn315-closure.md
- 17,558 lines of source analyzed from Linux 7.1
- 193,970 lines of register headers enumerated
- 34 C ABI surface units classified
- 21 Rust reimplementation units classified
- Complete init order documented (6-stage sequence)
- Scanout-memory path analysis with GMC scope ruling
- Raphael unknowns flagged pending-probe (7 items)
- Dependency graph with full include closure
2. AGENTS.md amendment applied
- "Concrete surface list: PENDING" replaced with full classified list
- Line ~484 in root AGENTS.md
Key rulings:
- C ABI: register headers, register tables, MMIO write sequences,
DMUB firmware interface, SMU mailbox registers, NBIO/IH access
- Rust: DML math (7,504 lines mode VBA), resource pool construction,
HW sequencer orchestration, modeset policy, clock manager policy
- Scanout memory: DCN VM page tables are IN SCOPE (evidence-required
for APU framebuffer scanout); GMC/GART-for-3D is OUT OF SCOPE
- DMCUB firmware: direct-load path viable (no PSP required)
- SMU: assumed pre-initialized by UEFI; clock requests only
Probe unknowns (Raphael probe report not found):
- FB aperture location/size
- DMCUB region requirements
- Clock frequency table
- Physical connector routing
- VM page table depth supported
- NBIO base segment verification
Classification counts:
Authorized C ABI surface: 34 units
Reference-only Rust reimplementation: 21 units
No port code written. No builds performed. No commits made.
Orchestrator will commit the AGENTS.md amendment + closure record.
+77 -1
View File
@@ -481,7 +481,83 @@ ryzen-7000-x670e-compat program); the DCN315 closure record (derived from Linux
exactly one of the two classes above and is appended to this block as the concrete
surface list. No C may be added beyond the units the closure record classifies as C ABI.
Concrete surface list: **PENDING** appended by the DCN315 closure record (todo 33).
Concrete surface list (appended by the DCN315 closure record, todo 33, 2026-08-05):
**Authorized C ABI surface** (34 units; register access, DMUB interface, firmware load — no modeset policy, no connector state, no scheme logic in C):
Register headers — the hardware ABI contract (generated from XML; only referenced subsets are in scope):
- `amd/include/asic_reg/dcn/dcn_3_1_5_offset.h` (15,306 lines) — DCN 3.1.5 register offsets
- `amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h` (62,619 lines) — DCN 3.1.5 shift/mask
- `amd/include/asic_reg/dpcs/dpcs_4_2_2_offset.h` (11,957 lines) — DPCS 4.2.2 register offsets
- `amd/include/asic_reg/dpcs/dpcs_4_2_2_sh_mask.h` (103,633 lines) — DPCS 4.2.2 shift/mask
- `amd/include/asic_reg/mp/mp_13_0_5_offset.h` (455 lines) — MP0/SMU register offsets
DCN315 register tables (~1,000 lines in `dcn315_resource.c` lines 1061,900): `bios_regs`, `clk_src_regs[5]`, `abm_regs[4]`, `audio_regs[7]`, `vpg_regs[10]`, `afmt_regs[6]`, `apg_regs[4]`, `stream_enc_regs[5]`, `link_enc_aux_regs[5]`, `link_enc_hpd_regs[5]`, `link_enc_regs[5]`, `hpo_frl_stream_enc_regs[1]`, `hpo_frl_link_enc_regs[1]`, `hpo_dp_stream_enc_regs[4]`, `hpo_dp_link_enc_regs[2]`, `dpp_regs[4]`, `opp_regs[4]`, `dsc_regs[3]`, `mpc_regs`, `optc_regs[4]`, `hubp_regs[4]`, `hubbub_reg`, `dccg_regs`, `hwseq_reg` (~30 regs, DCN31 layout), `vmid_regs[16]`, `dio_regs`, `dwbc30_regs[1]`, `mcif_wb30_regs[1]`, `i2c_hw_regs[5]`
Clock manager (register programming + SMU mailbox MMIO):
- `dc/clk_mgr/dcn315/dcn315_clk_mgr.c` (747 lines) — register-level clock programming
- `dc/clk_mgr/dcn315/dcn315_clk_mgr.h` (49 lines)
- `dc/clk_mgr/dcn315/dcn315_smu.c` (366 lines) — SMU message passing via RSMU/MP1 registers
- `dc/clk_mgr/dcn315/dcn315_smu.h` (130 lines) — SMU protocol constants
GPIO subsystem (pure register/pin definition, no policy):
- `dc/gpio/dcn315/hw_factory_dcn315.c` (260 lines)
- `dc/gpio/dcn315/hw_factory_dcn315.h` (31 lines)
- `dc/gpio/dcn315/hw_translate_dcn315.c` (374 lines)
- `dc/gpio/dcn315/hw_translate_dcn315.h` (33 lines)
Interrupt service (IH IRQ routing, hardware-defined IV-to-IRQ mapping):
- `dc/irq/dcn315/irq_service_dcn315.c` (413 lines)
- `dc/irq/dcn315/irq_service_dcn315.h` (34 lines)
DMUB interface (firmware load, command ring, region management):
- `dmub/src/dmub_dcn315.c` (62 lines) — register table
- `dmub/src/dmub_dcn315.h` (68 lines) — field definitions (inherits `dmub_dcn31.h`)
- `dmub/src/dmub_srv.c` (1,483 lines) — firmware load + command submission
- `dmub/dmub_srv.h` (~200 lines) — DMUB service types
- `dmub/src/dmub_dcn31.h` (~120 lines) — base DCN31 DMUB register definitions
DCN31 pipe subsystem register macro headers (no control flow; register ABI only):
- `dcn31_hubbub.h`, `dcn31_hubp.h`, `dcn31_optc.h`, `dcn31_dccg.h`, `dcn31_vpg.h`, `dcn31_afmt.h`, `dcn31_apg.h`, `dcn31_panel_cntl.h`, `dcn31_hpo_dp_stream_encoder.h`, `dcn31_hpo_dp_link_encoder.h`, `dcn31_dio_link_encoder.h`
HW sequencer — register-level functions (no policy decisions):
- `dc/hwss/dcn31/dcn31_hwseq.c` (745 lines) — register write sequences (init_hw, memory low power, domain power gate, clock gate control, info frame registers)
Firmware blob:
- `amdgpu/dcn_3_1_5_dmcub.bin` (~180 KB) — DMCUB firmware, loaded into DMUB region memory
**Reference-only Rust reimplementation** (21 units; DML math, resource-pool construction, HWSS sequencing, modeset policy — ported into Rust, NOT compiled as C):
Resource pool construction (policy — decides WHAT to create, in what order, with what capabilities; register tables used by construct are C ABI but the orchestration is Rust):
- `dcn315_resource_construct()` (~340 lines) — resource creation ordering, pipe count, capabilities, error handling
- `dcn315_res_pool_funcs` (~30 lines) — function dispatch table
- `dcn315_populate_dml_pipes_from_context()` (~100 lines) — pipe parameter policy, DET buffer allocation
- `dcn315_create_resource_pool()` (~15 lines) — allocator + constructor wrapper
- `dcn315_resource.h` type definitions (~7 lines)
DML math (mode validation, bandwidth calculation, scheduling — pure computation, no register access):
- `dc/dml/dcn31/dcn31_fpu.c` (830 lines) — IP/SOC parameters, bounding box calculation
- `dc/dml/dcn31/display_mode_vba_31.c` (7,504 lines) — complete mode validation and bandwidth analysis
- `dc/dml/dcn31/display_rq_dlg_calc_31.c` (1,599 lines) — display request and DLG calculation
HWSS orchestration (decides which functions handle which operations):
- `dc/hwss/dcn31/dcn31_init.c` (160 lines) — HW sequencer function table (~50 ops → implementations)
- `dc/hwss/dcn31/dcn31_init.h` (33 lines)
Policy function groups (modeset policy, pipe allocation, stream management, clock transitions, encoder matching — reimplemented in Rust using C ABI register tables for MMIO writes):
- Bandwidth policy: `dcn31_validate_bandwidth`, `dcn31_calculate_wm_and_dlg`, `dcn315_update_soc_for_wm_a`, `dcn315_update_bw_bounding_box`
- Pipe allocation: `dcn20_acquire_free_pipe_for_layer`, `dcn20_release_pipe`
- Stream management: `dcn30_add_stream_to_ctx`, `dcn20_remove_stream_from_ctx`
- Modeset enable/disable: `dcn20_enable_stream`, `dce110_disable_stream`, `dcn20_unblank_stream`, `dce110_blank_stream`
- Front-end programming: `dcn20_program_front_end_for_ctx`, `dcn20_update_plane_addr`
- Encoder matching: `dcn10_find_first_free_match_stream_enc_for_link`
- Clock transition: `dcn20_prepare_bandwidth`, `dcn20_optimize_bandwidth`
- LUT management: `dcn30_acquire_post_bldn_3dlut`, `dcn30_release_post_bldn_3dlut`
- Plane state: `dcn20_patch_unknown_plane_state`, `dcn10_get_default_tiling_info`
- MCIF arbitration: `dcn31_set_mcif_arb_params`
- Debug/config defaults (~100 lines)
**Counts:** 34 C ABI surface units, 21 Rust reimplementation units. No C may be added beyond the above C ABI list. Full detail: `local/docs/evidence/ryzen-x670e/dcn315-closure.md`.
### Firmware redistribution note (operator-approved 2026-08-04)
@@ -0,0 +1,723 @@
# DCN315 Minimal Display Slice — Compile/Link Closure
**Derived from:** Linux 7.1 `dcn315_resource.c` and its full include closure
**Date:** 2026-08-05
**Purpose:** Todo 33 first deliverable — record every compile/link unit BEFORE port code
**Target outcome:** DC-init + one connector (HDMI or DP per ATOM routing) + legacy modeset producing a framebuffer
**Scope boundary:** NO atomic KMS, NO rendering/3D, NO Mesa
---
## 1. Summary of Classification
| Class | Count | Description |
|-------|-------|-------------|
| **Authorized C ABI surface** | 34 units | Register offset/mask tables, MMIO access, DMUB firmware interface, NBIO/SMU register access |
| **Reference-only Rust reimplementation** | 21 units | DML math, resource-pool construction, HWSS sequencing, modeset policy, pipe allocation |
---
## 2. Authorized C ABI Surface — Complete File List
These units encode the hardware ABI contract: register addresses, bit fields, firmware format
structs, and low-level MMIO read/write routines. **They are compiled as C** and linked into
the port. No modeset policy, no connector state, no scheme logic in C.
### 2.1 Register Header Files (Generated from XML, ~194K lines total)
These are the ASIC register definition headers — the canonical hardware ABI for DCN 3.1.5.
They define every register offset, bit field position, and bit mask. **In scope: only the
registers actually referenced by the DCN315 closure.** The full headers are carried for
completeness but only the referenced subsets need to be present at compile time.
| # | File | Lines | Size | Purpose |
|---|------|-------|------|---------|
| R1 | `amd/include/asic_reg/dcn/dcn_3_1_5_offset.h` | 15,306 | 1.55 MB | DCN 3.1.5 display controller register offsets |
| R2 | `amd/include/asic_reg/dcn/dcn_3_1_5_sh_mask.h` | 62,619 | ~2.7 MB | DCN 3.1.5 register shift/mask definitions |
| R3 | `amd/include/asic_reg/dpcs/dpcs_4_2_2_offset.h` | 11,957 | ~0.5 MB | DPCS 4.2.2 (Display PHY Common Subsystem) register offsets |
| R4 | `amd/include/asic_reg/dpcs/dpcs_4_2_2_sh_mask.h` | 103,633 | ~4.3 MB | DPCS 4.2.2 shift/mask definitions |
| R5 | `amd/include/asic_reg/mp/mp_13_0_5_offset.h` | 455 | ~19 KB | MP0 (SMU) register offsets for SMU mailbox communication |
These are pure data headers — `#define` constants and preprocessor macros. No C code,
no control flow. Classification rationale: they are the hardware register ABI contract.
Without them, no register can be programmed. They are the definition of the interface
between software and the DCN315 silicon.
### 2.2 DCN315 Resource — Register Tables (~900 lines of register table data)
**File:** `dc/resource/dcn315/dcn315_resource.c` (2,358 lines total)
The first ~1,900 lines of this file are **register table definitions** — static `const`
struct arrays that encode the register addresses, shifts, and masks for every hardware
block in the DCN315 pipe. These ARE the C ABI surface:
| Block | Lines | Registers defined | Description |
|-------|-------|-------------------|-------------|
| BIOS scratch | 106-218 | `bios_regs` (2 regs) | NBIO BIF scratch registers for ATOMBIOS communication |
| Clock sources | 220-239 | `clk_src_regs[5]` + `cs_shift`/`cs_mask` | PLL0-4 clock source registers |
| ABM | 241-258 | `abm_regs[4]` + `abm_shift`/`abm_mask` | Adaptive backlight management registers |
| Audio (AZ) | 261-287 | `audio_regs[7]` + `audio_shift`/`audio_mask` | Azalia audio endpoint registers (7 instances) |
| VPG | 289-313 | `vpg_regs[10]` + `vpg_shift`/`vpg_mask` | Video pattern generator (DCN31 layout) |
| AFMT | 315-335 | `afmt_regs[6]` + `afmt_shift`/`afmt_mask` | Audio format (DCN31 layout) |
| APG | 337-355 | `apg_regs[4]` + `apg_shift`/`apg_mask` | Audio packet generator (DCN31 layout) |
| Stream encoders | 357-376 | `stream_enc_regs[5]` + `se_shift`/`se_mask` | DCN3 stream encoder (5 instances) |
| AUX engines | 379-417 | `link_enc_aux_regs[5]` + `aux_shift`/`aux_mask` | DCN2 AUX channel registers |
| HPD | 392-403 | `link_enc_hpd_regs[5]` | Hot-plug detect registers |
| Link encoders | 405-436 | `link_enc_regs[5]` + `le_shift`/`le_mask` | DCN31 link encoder + DPCS |
| HPO FRL stream enc | 438-458 | `hpo_frl_stream_enc_regs[1]` + shift/mask | HDMI FRL stream encoder |
| HPO FRL link enc | 460-475 | `hpo_frl_link_enc_regs[1]` + shift/mask | HDMI FRL link encoder |
| HPO DP stream enc | 477-495 | `hpo_dp_stream_enc_regs[4]` + shift/mask | HPO (High-Performance Output) DP stream encoder |
| HPO DP link enc | 497-519 | `hpo_dp_link_enc_regs[2]` + shift/mask | HPO DP link encoder + RDPCSTX |
| DPP | 521-539 | `dpp_regs[4]` + `tf_shift`/`tf_mask` | Display Pipe Processor (DCN30 layout) |
| OPP | 541-559 | `opp_regs[4]` + `opp_shift`/`opp_mask` | Output Pixel Processor (DCN20 layout) |
| DSC | 611-628 | `dsc_regs[3]` + `dsc_shift`/`dsc_mask` | Display Stream Compression (DCN20 layout) |
| MPC | 630-648 | `mpc_regs` + `mpc_shift`/`mpc_mask` | Multi-Plane Compositor (DCN30 layout) |
| OPTC | 650-666 | `optc_regs[4]` + `optc_shift`/`optc_mask` | Output Timing Controller (DCN3.1 layout) |
| HUBP | 668-687 | `hubp_regs[4]` + `hubp_shift`/`hubp_mask` | HUBP (DCN30 regs, DCN31 shifts/masks) |
| HUBBUB | 688-698 | `hubbub_reg` + `hubbub_shift`/`hubbub_mask` | DCHUBBUB registers (DCN31 layout) |
| DCCG | 700-710 | `dccg_regs` + `dccg_shift`/`dccg_mask` | Display Clock Generator (DCN31 layout) |
| HWSEQ | 719-821 | `hwseq_reg` + `hwseq_shift`/`hwseq_mask` | HW sequencer registers (~30 regs, DCN31 layout) |
| VMID | 822-852 | `vmid_regs[16]` + `vmid_shifts`/`vmid_masks` | Virtual Memory ID page table registers |
| DIO | 854-867 | `dio_regs` + `dio_shift`/`dio_mask` | Display I/O registers (DCN10 layout) |
| DWB | 577-592 | `dwbc30_regs[1]` + shift/mask | Display Writeback (DCN30 layout) |
| MMHUBBUB | 594-609 | `mcif_wb30_regs[1]` + shift/mask | Multi-Media Hub (DCN30 layout) |
| I2C | 1029-1037 | `i2c_hw_regs[5]` + shifts/masks | I²C hardware engine registers |
**Total register table data in this file:** ~1,000 lines of `static const` struct arrays.
**Classification: C ABI** — these encode the hardware register layout. They are the
definition of WHAT registers exist and WHERE they are. The Rust port will include
equivalent Rust `const` arrays generated from the same header data, but the source
of truth is the register offset/mask headers above.
### 2.3 DCN315 Clock Manager
| # | File | Lines | Content | Classification |
|---|------|-------|---------|----------------|
| C1 | `dc/clk_mgr/dcn315/dcn315_clk_mgr.c` | 747 | Clock manager: DCFCLK/DISPCLK/DPPCLK/DTBCLK/PHYCLK configuration, active display count, SMU clock requests, FCLK/PSTATE change support, watermark calculation dispatch | **C ABI** — writes clock registers and communicates with SMU via MMIO |
| C2 | `dc/clk_mgr/dcn315/dcn315_clk_mgr.h` | 49 | `clk_mgr_dcn315` struct, `dcn315_clk_mgr_create()` declaration | **C ABI** — struct definition for clock manager state |
| C3 | `dc/clk_mgr/dcn315/dcn315_smu.c` | 366 | SMU message passing: `dcn315_smu_send_msg_with_param()`, `dcn315_smu_send_allow_toggle_df_state()`, `dcn315_smu_set_dispclk()`, `dcn315_smu_set_dprefclk()`, `dcn315_smu_set_hard_min_dcfclk()`, `dcn315_smu_set_min_deep_sleep_dcfclk()`, RSMU indirect register access (`regBIF_BX_PF2_RSMU_INDEX/DATA`), MP1 C2PMSG_3 mailbox | **C ABI** — MMIO register read/write of SMU mailbox registers |
| C4 | `dc/clk_mgr/dcn315/dcn315_smu.h` | 130 | SMU message IDs, `dcn315_smu` struct, clock table entry types, VBIOS boot clock values | **C ABI** — SMU protocol constants (message IDs, struct layouts) |
### 2.4 DCN315 GPIO Subsystem
| # | File | Lines | Content | Classification |
|---|------|-------|---------|----------------|
| G1 | `dc/gpio/dcn315/hw_factory_dcn315.c` | 260 | GPIO hardware factory: defines which GPIO pins exist (HPD, DDC, generic, sync, GSL), registers the pin-to-DDC/HPD mapping for DCN315 | **C ABI** — pure register and pin definition, no policy |
| G2 | `dc/gpio/dcn315/hw_factory_dcn315.h` | 31 | `dal_hw_factory_dcn315_init()` declaration | **C ABI** — interface declaration |
| G3 | `dc/gpio/dcn315/hw_translate_dcn315.c` | 374 | GPIO offset-to-ID translation: maps hardware register offsets to logical GPIO IDs (HPD1-5, DDC1-5, generic GPIOs) | **C ABI** — register address mapping, no policy |
| G4 | `dc/gpio/dcn315/hw_translate_dcn315.h` | 33 | `dal_hw_translate_dcn315_init()` declaration | **C ABI** — interface declaration |
### 2.5 DCN315 Interrupt Service
| # | File | Lines | Content | Classification |
|---|------|-------|---------|----------------|
| I1 | `dc/irq/dcn315/irq_service_dcn315.c` | 413 | Interrupt routing: `to_dal_irq_source_dcn315()` maps IV source IDs → DC IRQ types (VBLANK1-6, VLINE0-5, PFLIP1-6, HPD, VUPDATE), constructs `irq_source_info_dcn315` table, `dal_irq_service_dcn315_create()` | **C ABI** — interrupt controller register access + IV-to-IRQ routing (hardware-defined mapping) |
| I2 | `dc/irq/dcn315/irq_service_dcn315.h` | 34 | `dal_irq_service_dcn315_create()` declaration | **C ABI** — interface declaration |
### 2.6 DMUB (Display Microcontroller Unit B) Interface
| # | File | Lines | Content | Classification |
|---|------|-------|---------|----------------|
| D1 | `dmub/src/dmub_dcn315.c` | 62 | `dmub_srv_dcn315_regs` — register table for DMCUB control registers (DMCUB_CNTL, DMCUB_REGION*_TOP_ADDRESS, DCN_VM_FB_LOCATION_BASE/OFFSET, DMCUB_INBOX0_WPTR, etc.) | **C ABI** — register offset table for the DMUB hardware |
| D2 | `dmub/src/dmub_dcn315.h` | 68 | `DMUB_DCN315_FIELDS()` macro — defines bit field names for all DCN315 DMUB registers, inherits `dmub_dcn31.h` for base region registers | **C ABI** — register field definitions |
| D3 | `dmub/src/dmub_srv.c` | 1,483 | DMUB service layer: firmware load (`dmub_srv_hw_init()` — copies firmware to DMUB memory region, sets up CW0-CW7 region windows, resets and enables DMCUB), command submission (`dmub_srv_cmd_queue()`), inbox/outbox ring management, interrupt handling, region calculation | **C ABI** — firmware load + MMIO register programming. The firmware loading sequence (PSP handshake or direct memory copy + reset-enable) is register-level |
| D4 | `dmub/dmub_srv.h` | ~200 | DMUB service state struct, region constants, API declarations | **C ABI** — interface definition |
| D5 | `dmub/src/dmub_dcn31.h` | ~120 | Base DMUB register definitions for all DCN31 variants (DMCUB_REGION*_BASE, DMCUB_INBOX/OUTBOX base, CW window sizes) | **C ABI** — register offset constants, inherited by dmub_dcn315.h |
### 2.7 DCN31 Pipe Subsystem Headers (Register Macros)
These are the header files that the DCN315 resource file `#include`s to get register list
macros (e.g., `HUBBUB_REG_LIST_DCN31`, `OPTC_COMMON_REG_LIST_DCN3_1`, etc.). They define
preprocessor macros that expand to register offset/field references. **No control flow,
no logic — they are register ABI definitions.**
| # | File | Includes pulled from | Purpose |
|---|------|---------------------|---------|
| H1 | `dc/dcn31/dcn31_hubbub.h` | `dcn315_resource.c:42` | DCHUBBUB register list macros |
| H2 | `dc/dcn31/dcn31_hubp.h` | `dcn315_resource.c:44` | HUBP shift/mask macros (DCN31 layout) |
| H3 | `dc/dcn31/dcn31_optc.h` | `dcn315_resource.c:47` | OPTC register list macros (DCN3.1 layout) |
| H4 | `dc/dcn31/dcn31_dccg.h` | `dcn315_resource.c:73` | DCCG register list macros (DCN31 layout) |
| H5 | `dc/dcn31/dcn31_vpg.h` | `dcn315_resource.c:62` | VPG register list macros (DCN31 layout) |
| H6 | `dc/dcn31/dcn31_afmt.h` | `dcn315_resource.c:63` | AFMT register list macros (DCN31 layout) |
| H7 | `dc/dcn31/dcn31_apg.h` | `dcn315_resource.c:60` | APG register list macros (DCN31 layout) |
| H8 | `dc/dcn31/dcn31_panel_cntl.h` | `dcn315_resource.c:75` | Panel control register macros |
| H9 | `dc/dcn31/dcn31_hpo_dp_stream_encoder.h` | `dcn315_resource.c:58` | HPO DP stream encoder register macro list |
| H10 | `dc/dcn31/dcn31_hpo_dp_link_encoder.h` | `dcn315_resource.c:59` | HPO DP link encoder register macro list |
| H11 | `dc/dcn31/dcn31_dio_link_encoder.h` | `dcn315_resource.c:61` | DIO link encoder register macros (DCN31 layout) |
### 2.8 HW Sequencer — Register-Level Functions (in dcn31_hwseq.c)
**File:** `dc/hwss/dcn31/dcn31_hwseq.c` (745 lines)
This file contains the **low-level register programming sequences** that the HW sequencer
function table dispatches to. These are C ABI because they write specific register bit fields:
- `dcn31_init_hw()` — register reset sequence (domain power gating, memory low power, clock gate disable)
- `dcn31_init_sys_ctx()` — system context initialization (HUBBUB, DCHUB, DCCG register writes)
- `dcn31_set_static_screen_control()` — static screen detection register programming
- `dcn31_reset_back_end_for_pipe()` — pipe back-end register reset
- `dcn31_update_info_frame()` — info frame register writes
- `enable_memory_low_power()` — memory power register writes
**Classification: C ABI** — these are register write sequences, not policy decisions.
### 2.9 NBIO/IH Register Access
Referenced indirectly through:
- `bios_regs` in `dcn315_resource.c:215-218` — BIF scratch registers (NBIO)
- `irq_service_dcn315.c` — IH (Interrupt Handler) IV source ID routing
- `dcn315_smu.c` — RSMU indirect register access through BIF (NBIO)
The NBIO registers needed are:
- `regBIF_BX_PF2_RSMU_INDEX` / `regBIF_BX_PF2_RSMU_DATA` — RSMU indirect access (SMU communication)
- `regBIF_BX2_BIOS_SCRATCH_2/3/6` — ATOMBIOS scratch registers
**Classification: C ABI** — pure register access, no policy.
### 2.10 Shared DC Infrastructure (C Headers, Struct Definitions)
These are C header files needed for type definitions and function signatures. They define
the structs that the C ABI surface uses (register types, pointer types, etc.):
| # | File | Purpose |
|---|------|---------|
| S1 | `dc/core_types.h` | Core DC types: `struct dc_context`, `struct dc_bios`, `struct dc_debug_options` |
| S2 | `dc/dc.h` | Main DC struct, version enums (`DCN_VERSION_3_15`) |
| S3 | `dc/resource.h` | `struct resource_pool`, `struct resource_funcs` |
| S4 | `dm_services.h` | Service layer abstraction (kzalloc, dm_error, etc.) — must be adapted for Redox |
| S5 | `reg_helper.h` | Register read/write helper macros (`REG_GET`, `REG_SET`, `REG_UPDATE`) |
| S6 | `include/irq_service_interface.h` | IRQ service interface types |
| S7 | `dc/clk_mgr.h` | Clock manager base types |
| S8 | `dc/clk_mgr_internal.h` | Clock manager internal types |
| S9 | `dc/dccg.h` | DCCG types |
| S10 | `dc/hw_sequencer.h` | `struct hw_sequencer_funcs` — function table (the table itself is Rust, but the struct definition and individual register-write functions are C ABI) |
| S11 | `dc/link_service.h` | Link service types |
| S12 | `dc/dm_helpers.h` | Display Manager helpers |
| S13 | `dc/core/dc_resource.c:356-357` | Resource pool dispatch table — maps `DCN_VERSION_3_15``dcn315_create_resource_pool()` **(Purely a dispatch table — C ABI because it's a direct mapping from version enum to factory function)** |
### 2.11 Firmware Blob
| # | Blob | Size | Purpose |
|---|------|------|---------|
| F1 | `amdgpu/dcn_3_1_5_dmcub.bin` | ~180 KB (typical DMCUB size) | DMCUB firmware for DCN 3.1.5. Loaded into DMUB region memory. Referenced by `amdgpu_dm.c:130` as `FIRMWARE_DCN_315_DMUB` and selected at `amdgpu_dm.c:6131-6132` for `IP_VERSION(3,1,5)`. |
**Classification: C ABI** — firmware blob loaded into hardware. The firmware is a black box;
the interface to it is register-level (DMCUB_CNTL, DMCUB_REGION*_TOP_ADDRESS registers in dmub_dcn315.c/h).
### 2.12 ATOMBIOS / ATOM Table Interface
The DCN315 resource pool communicates with the system BIOS through:
- `ctx->dc_bios->regs = &bios_regs` (NBIO scratch registers)
- `ctx->dc_bios->funcs->get_lttpr_caps()` — reads LTTPR (Link Training Tunable PHY Repeater) capabilities from VBIOS
The ATOM table usage in the DCN315 closure is **minimal**: it reads LTTPR caps once during
resource construction. For a minimal display slice targeting a single physical connector,
the LTTPR cap can be defaulted (no LTTPR on most consumer boards, including MS-7D70).
**Classification: C ABI** — the bios_regs are register access; the VBIOS query functions
are a C ABI boundary. The Rust port will replace the VBIOS query with a static default or
a minimal ATOM table parser in Rust.
---
## 3. Reference-Only Rust Reimplementation — Complete File List
These units contain **policy, logic, and orchestration**. They are ported into Rust using
the Linux source as reference, **never compiled as C**.
### 3.1 Resource Pool Construction
| # | File | Lines | Content | Why Rust |
|---|------|-------|---------|----------|
| P1 | `dc/resource/dcn315/dcn315_resource.c:2018-2358` | ~340 lines | `dcn315_resource_construct()` — resource creation ordering, pipe count, capabilities, error handling, `resource_construct()` call, `dcn31_hw_sequencer_construct()` call | Policy: decides WHAT resources to create, in what order, with what capabilities. The register tables used by construct are C ABI, but the construction orchestration is policy. |
| P2 | `dc/resource/dcn315/dcn315_resource.c:1985-2016` | ~30 lines | `dcn315_res_pool_funcs` — function table linking each resource operation to its implementation | Policy: the function dispatch table is a design decision about which functions handle which operations. |
| P3 | `dc/resource/dcn315/dcn315_resource.c:1865-1962` | ~100 lines | `dcn315_populate_dml_pipes_from_context()` — pipe parameters for DML, bandwidth policy for DET buffer allocation | Policy: bandwidth allocation decisions, pipe splitting policy |
| P4 | `dc/resource/dcn315/dcn315_resource.c:2342-2358` | ~15 lines | `dcn315_create_resource_pool()` — allocator + constructor call | Trivial wrapper, but Rust idiom is different |
| P5 | `dc/resource/dcn315/dcn315_resource.h:36-43` | ~7 lines | `struct dcn315_resource_pool`, `dcn315_create_resource_pool()` declaration | Type definition |
### 3.2 DML (Display Mode Library) Math — DCN31 Family
| # | File | Lines | Content | Why Rust |
|---|------|-------|---------|----------|
| M1 | `dc/dml/dcn31/dcn31_fpu.c` | 830 | `dcn3_1_ip` (IP parameters struct), `dcn3_1_soc` (SoC parameters with clock/voltage tables), `dcn315_update_bw_bounding_box_fpu()` — updates bandwidth bounding box from SMU-provided clock/voltage data, SOC bounding box calculation | Policy + math: these are parameter tables and computation, not register access. The IP params define capabilities (ODM combine, DSC, number of DPPs, etc.); the SOC params define clock/voltage operating points. |
| M2 | `dc/dml/dcn31/display_mode_vba_31.c` | 7,504 | VBA (Visual Basic for Applications → "Video Bandwidth Analysis") — complete mode validation and bandwidth calculation for DCN31. Computes: DET buffer sizing, data flow, watermarks, DCFCLK/PHYCLK requirements, return buffer sizing, prefetch calculations, urgent latency, cursor requirements, writeback requirements | Policy: this IS the modeset policy — it decides whether a given display mode is viable. Porting this to Rust gives type safety (physical units as distinct types) and exhaustiveness. |
| M3 | `dc/dml/dcn31/display_rq_dlg_calc_31.c` | 1,599 | Display request and DLG (Display Line Generator) calculation: computes the DCHUB request schedule, TTL (time-to-line) parameters, chunk sizes, and DLG parameters per pipe | Math: pure computation from mode parameters to hardware scheduling parameters. No register access. |
### 3.3 HWSS (Hardware Sequencer) Orchestration
| # | File | Lines | Content | Why Rust |
|---|------|-------|---------|----------|
| W1 | `dc/hwss/dcn31/dcn31_init.c` | 160 | `dcn31_funcs` — the HW sequencer function table: ~50 function pointers mapping operations to implementations. `dcn31_hw_sequencer_construct()` — assigns the function table to DC. | Policy: the function table IS the software architecture — it decides which code handles init_hw, apply_ctx_to_hw, update_plane_addr, enable_stream, etc. This is a design decision, not register access. |
| W2 | `dc/hwss/dcn31/dcn31_init.h` | 33 | `dcn31_hw_sequencer_construct()` declaration | Interface |
### 3.4 Modeset Policy & Plane Management (Shared across DCN2x/3x families)
These are the **upstream** functions that the DCN315 resource pool's function table
dispatches to. They are shared across multiple ASIC generations (dcn20/dcn30/dcn31).
Only the functions actually referenced by the DCN315 function table (`dcn315_res_pool_funcs`
and `dcn31_funcs`) are in scope:
**From `dcn315_res_pool_funcs`** (resource_pool operations — Rust):
- `dcn315_destroy_resource_pool` — resource destruction
- `dcn31_link_encoder_create` / `dcn31_link_enc_create_minimal` — link encoder allocation
- `link_enc_cfg_link_encs_assign` / `link_enc_cfg_link_enc_unassign` — link-to-encoder mapping
- `dcn31_validate_bandwidth` — bandwidth validation entry point → dispatches to DML
- `dcn31_calculate_wm_and_dlg` — watermark/DLG calculation → dispatches to DML
- `dcn315_update_soc_for_wm_a` — SoC parameters for watermark set A
- `dcn315_populate_dml_pipes_from_context` — pipes → DML input translation
- `dcn20_acquire_free_pipe_for_layer` — pipe allocation policy
- `dcn20_release_pipe` — pipe release
- `dcn30_add_stream_to_ctx` / `dcn20_remove_stream_from_ctx` — stream management
- `dcn10_find_first_free_match_stream_enc_for_link` — encoder matching
- `dcn315_update_bw_bounding_box` — bounding box update → dispatches to dcn31_fpu
- `dcn20_patch_unknown_plane_state` — plane state defaults
- `dcn10_get_default_tiling_info` — tiling defaults
- `dcn31_set_mcif_arb_params` — MCIF arbitration parameters
- `dcn30_acquire_post_bldn_3dlut` / `dcn30_release_post_bldn_3dlut` — 3D LUT allocation
**From `dcn31_funcs`** (hw_sequencer operations — Rust):
- Application of context to hardware: `dce110_apply_ctx_to_hw` → pipeline programming orchestration
- Front-end programming: `dcn20_program_front_end_for_ctx` → pipe front-end setup policy
- Plane operations: `dcn20_update_plane_addr` → surface address programming
- Stream operations: `dcn20_enable_stream`, `dce110_disable_stream` → DIG enable/disable
- Blanking: `dcn20_unblank_stream`, `dce110_blank_stream` → blanking policy
- Bandwidth: `dcn20_prepare_bandwidth`, `dcn20_optimize_bandwidth` → bandwidth transition policy
**Classification: Rust** — these are policy functions that orchestrate hardware state transitions.
They use the C ABI register tables to read/write registers, but they decide WHAT to program,
not HOW the bit fields are laid out.
### 3.5 Clock Manager Policy Layer
The clock manager C files (`dcn315_clk_mgr.c`, `dcn315_smu.c`) contain both register access
(C ABI) and policy decisions (Rust). The policy parts include:
- Clock state machine transitions (DCFCLK, DISPCLK, DPPCLK, DTBCLK, FCLK)
- Active display count heuristic (dcn315_get_active_display_cnt_wa)
- P-state support decision based on display configuration
- Clock frequency selection based on bandwidth requirements
- Deep sleep / idle power state decisions
**Classification: Rust** — these policy decisions are reimplemented in Rust using the
C ABI register tables for the actual MMIO writes.
---
## 4. Init Order
The DCN315 display initialization sequence (simplified for minimal display slice):
```
1. FW LOAD: PSP/SMU loads dcn_3_1_5_dmcub.bin into DMUB memory
└── DMCUB_CNTL.DMCUB_ENABLE (hardware reset sequence)
└── DMCUB_REGION*_TOP_ADDRESS (CW0-CW7 region windows)
└── Wait for DMCUB_SEC_CNTL.DMCUB_SEC_RESET_STATUS = 0
2. RESOURCE POOL: dcn315_create_resource_pool(init_data, dc)
├── 2a. Capability population (dc->caps, dc->config)
├── 2b. Register table initialization (bios_regs → dc_bios)
├── 2c. dc->caps.is_apu = true (UMA framebuffer)
├── 2d. dc->caps.dmcub_support = true
├── 2e. VM helper init (16 VMIDs, page table block size)
└── 2f. Hardware block creation (in order):
├── Clock sources (PLL0-PLL4 + DP DTO)
├── DCCG (Display Clock Generator)
├── IRQ service (interrupt routing table)
├── DIO (Display I/O)
├── HUBBUB (Display Controller Hub)
├── HUBPs (4x Hub Pipe)
├── DPPs (4x Display Pipe Processor)
├── OPPs (4x Output Pixel Processor)
├── Timing Generators (4x)
├── PSR / Replay / ABM objects
├── MPC (Multi-Plane Compositor)
├── DSC (3x Display Stream Compression)
├── DWB / MMHUBBUB (Writeback)
├── AUX engines (5x)
├── I2C engines (5x)
├── Audio / Stream Encoders / HPO / Virtual
└── HW Sequencer function table (dcn31_funcs)
3. CLK INIT: dcn315_clk_mgr_create(ctx)
├── SMU version query (via RSMU registers)
├── SMU message: GetDprefclk, GetDcfclk, GetDtbclk, GetFclkFrequency
├── SMU message: SetHardMinDcfclkByFreq, SetMinDeepSleepDcfclk
├── SMU message: AllowDfPstate, SetDispclk
└── Clock notifications enabled
4. DMUB INIT: dmub_srv_hw_init(dmub)
├── Calculate region memory layout (CW windows, inbox/outbox, fw state)
├── Copy firmware to DMUB region memory
├── Set DMCUB_REGION*_TOP_ADDRESS for each region
├── Set DCN_VM_FB_LOCATION_BASE/OFFSET (framebuffer physical address)
├── Reset DMCUB (DMCUB_SOFT_RESET)
└── Enable DMCUB (DMCUB_ENABLE)
└── Wait for firmware ready (inbox message or interrupt)
5. DC INIT: dc_hardware_init() → hwss->init_hw(dc)
└── dcn31_init_hw(dc):
├── Power domain force-on (DOMAIN0-3,16-18_PG_CONFIG)
├── Enable memory low power (VGA, I2C, DSCL, CM, MPC, OPTC, VPG, AFMT)
├── Disable clock gating (DCCG_GATE_DISABLE_CNTL)
├── Set DCFCLK_CNTL for display clock
├── Program DCHUBBUB_GLOBAL_TIMER_CNTL
└── Set DC_IP_REQUEST_CNTL.IP_REQUEST_EN
6. MODESET: (per-connector, user-triggered)
├── EDID read via AUX channel (DCN2 AUX engine)
├── Mode validation (dcn31_validate_bandwidth → DML VBA)
├── Link training (DP or HDMI FRL via link encoder)
├── Pipe resource assignment (acquire_free_pipe, stream_enc matching)
├── DCCG clock programming (DISPCLK, DPPCLK)
├── OPTC timing programming (pixel clock, htotal/vtotal, sync polarities)
├── DIO stream encoder configuration
├── HUBP surface programming (pitch, format, address)
├── DPP configuration (color pipeline: CSC, gamma, etc.)
├── MPC blending configuration
└── DIG enable → pixels flow to display
Key: 1-4 are init-time (cold boot). 5 is DC hardware init. 6 is per-connector modeset.
```
---
## 5. Scanout-Memory Path Analysis
### 5.1 APU Architecture (Raphael / Ryzen 7000)
Raphael is an APU (Accelerated Processing Unit) — CPU + GPU share the same physical
memory (UMA — Unified Memory Architecture). The display controller reads framebuffer
pixels directly from system DRAM through the Data Fabric (DF) and Memory Controller.
### 5.2 DCN315 Framebuffer Addressing
The DCN315 display controller addresses framebuffer memory through two mechanisms:
1. **DCN_VM_FB_LOCATION_BASE / FB_OFFSET** — defines the physical base address of the
framebuffer aperture in system memory. These registers tell the DCN hardware where
in physical address space the framebuffer lives.
2. **VMID Page Tables** — 16 Virtual Memory IDs (DCN_VM_CONTEXT0 through DCN_VM_CONTEXT15).
Each VMID has a page table (PAGE_TABLE_BASE_ADDR, PAGE_TABLE_START_ADDR,
PAGE_TABLE_END_ADDR) that translates virtual addresses used by display pipes into
physical addresses. For the display controller (scanout), these are **separate from
the GPU VM page tables** used for compute/rendering.
### 5.3 Minimal GMC Translation — APU Scanout Analysis
**Question:** Does APU scanout require minimal GMC address translation?
**Answer: YES, but it is bounded.** The DCN VM (DCN_VM_CONTEXT) is the translation
mechanism for scanout, and it is **separate from the GMC/GART/GPU-MMU used for
rendering.** For a framebuffer-only APU setup:
**Required:**
- **VMID initialization** — At minimum, one VMID configured for identity mapping:
- `PAGE_TABLE_DEPTH = 0` (1-level page table — no multi-level walk)
- `PAGE_TABLE_BLOCK_SIZE = 0` (4KB pages)
- `PAGE_TABLE_BASE_ADDR` → physical address of a 1:1 page directory
- `PAGE_TABLE_START_ADDR = 0`, `PAGE_TABLE_END_ADDR = <fb_size>`
- **Or**, for zero-page-table operation: set `VM_CONTEXT0_PAGE_TABLE_DEPTH = 0`
with flat 1:1 mapping through a minimal page directory.
- **DCN_VM_FB_LOCATION_BASE / FB_OFFSET** registers set to the physical framebuffer address
- **HUBP surface address** set to the VM-mapped address of the framebuffer surface
- **DCHUBBUB_ARB_HOSTVM_CNTL** configured for APU mode (DISABLE_HOSTVM_FORCE_ALLOW_PSTATE)
**NOT required (OUT OF SCOPE for framebuffer-only):**
- GPU page tables (GMC/GART/GFXHUB PTEs for shader access) — these are for 3D rendering
- IOMMU/GART aperture for GPU virtual addressing — render path only
- Multi-level GPU VM for sparse resources — compute/3D only
- GMC address translation for shader resource binding — rendering only
- PRT (Partially Resident Textures) page fault handling — rendering only
**The prohibition in the todo-24(b) exemption is on render/GART-for-3D, NOT on
evidence-required scanout translation.** The DCN VM setup is evidence-required: the
display controller hardware requires VMID page table registers to be configured
before it can scan out pixels. Without DCN VM initialization, the display pipe
reports page faults and produces no output.
**Cache coherency:** On APU, the display controller reads through the same memory
fabric as the CPU. The framebuffer memory should be allocated as:
- Write-combining (WC) for the CPU side (framebuffer writes)
- The DCN hardware handles its own coherency through the Data Fabric
**IOMMU interaction:** If the system IOMMU is enabled (AMD-Vi), the framebuffer
physical pages must be in an identity-mapped or pass-through domain. The DCN VM
page tables operate independently of the system IOMMU; they translate DCN virtual
addresses to physical addresses within the FB aperture. The physical FB pages must
be accessible (IOMMU identity-mapped or not translated).
### 5.4 Raphael-Specific Unknowns (Pending Probe)
The Raphael probe report (`local/docs/evidence/ryzen-x670e/raphael-probe.md`) was not
found at analysis time. The following items require probing to resolve:
| Unknown | Probe method | Impact if true |
|---------|-------------|----------------|
| FB aperture location (FB_LOCATION_BASE value) | Read PCI BAR or ATOM FW info table | Determines physical address region for scanout |
| FB aperture size on Raphael | Read from `amdgpu_gmc` VBIOS/register | Determines maximum framebuffer resolution |
| DMCUB firmware region requirement | DMCUB_REGION4 size from DMUB SRAM layout | Affects memory allocation for DMUB FW + trace buffers |
| Clock frequency table (SMU-provided) | SMU GetDcfclk/GetFclkFrequency response | Determines clock operating points for DML |
| Physical connector routing (HDMI vs DP vs eDP) | ATOM BIOS connector table or DDC probe | Determines which connector to target first |
| DCN_VM page table depth supported on Raphael APU | Try depth 0,1,2 and check for faults | Affects minimal VM setup complexity |
| Whether NBIO base address segments differ from dcn315_resource.c defines | Compare with actual PCI BAR | If different, all register offsets shift |
### 5.5 IOMMU Interaction
The system IOMMU (AMD-Vi) on Raphael translates DMA addresses. For DCN315 scanout:
- The framebuffer physical pages must be in an IOMMU identity-mapped domain (DMA remapping
disabled for the framebuffer aperture) OR the IOMMU must be configured with a 1:1
pass-through mapping for the FB region.
- The DCN VM page tables operate within the FB aperture AFTER IOMMU translation (if IOMMU
is active). The DCN hardware sees post-IOMMU physical addresses.
- If the IOMMU is disabled or in pass-through mode (which is the normal Red Bear OS
configuration for initial bringup), the FB aperture is directly physical.
---
## 6. PSP/SMU Init Prerequisites
### 6.1 SMU (System Management Unit)
The DCN315 clock manager communicates with the SMU via:
- RSMU (Register SMU) indirect access: `regBIF_BX_PF2_RSMU_INDEX` / `regBIF_BX_PF2_RSMU_DATA`
at NBIO base segment 1 (offset `0x14`)
- MP1 mailbox: `mmMP1_C2PMSG_3` at MP0 base segment 0 (`0x00016000`)
The SMU must be **already initialized** by the platform firmware (AGESA/UEFI) before the
display driver loads. The display driver sends clock requests to the SMU; it does not
initialize the SMU itself. The SMU responds to:
- `GetDprefclk` — display reference clock frequency
- `GetDcfclk` — display controller fabric clock
- `GetFclkFrequency` — fabric clock
- `SetHardMinDcfclkByFreq` — minimum DCFCLK request
- `SetMinDeepSleepDcfclk` — deep sleep DCFCLK
- `SetDispclk` — display pixel clock request
- `AllowDfPstate` — data fabric P-state transition permission
### 6.2 PSP (Platform Security Processor)
The PSP is responsible for loading authenticated firmware into the DMCUB. In Linux,
the PSP loads `dcn_3_1_5_dmcub.bin` via `psp_dmub_init()` / `psp_execute_np_fw_load()`.
For Red Bear OS:
- **PSP may not be available** (Red Bear OS may not have PSP driver).
- **Fallback:** The DMUB firmware can be loaded by direct memory write (the legacy path
used before PSP DMUB loading was added). The DMCUB memory regions are mapped via the
DCN MMIO BAR, and the firmware can be copied directly to the DMCUB_REGION4_TOP_ADDRESS
region with subsequent soft reset + enable.
- **Evidence:** The `dmub_srv.c` code supports both PSP-assisted and direct-load paths.
`dmub_srv_hw_init()` handles the direct load: copy FW to region memory, set region
addresses, soft-reset, enable, wait for ready.
---
## 7. Dependency Graph (Closure Units)
```
dcn315_resource.c ─────────────────────────────────────────────────────────────
├── dm_services.h (service abstraction)
├── dc.h (DCN_VERSION_3_15, struct dc)
├── dcn31/dcn31_init.h (HW sequencer function table)
├── resource.h (struct resource_pool)
├── include/irq_service_interface.h
├── dcn20/dcn20_resource.h
├── dcn30/dcn30_resource.h
├── dcn31/dcn31_resource.h
│ └── dcn31/dcn31_resource.c (base resource pool functions)
├── dcn10/dcn10_ipp.h
├── dcn30/dcn30_hubbub.h
├── dcn31/dcn31_hubbub.h
├── dcn30/dcn30_mpc.h
├── dcn31/dcn31_hubp.h
├── irq/dcn315/irq_service_dcn315.h
│ └── irq/dcn315/irq_service_dcn315.c (IH routing)
├── dcn30/dcn30_dpp.h
├── dcn31/dcn31_optc.h
├── dcn20/dcn20_hwseq.h
├── dcn30/dcn30_hwseq.h
├── dce110/dce110_hwseq.h
├── dcn30/dcn30_opp.h
├── dcn20/dcn20_dsc.h
├── dcn30/dcn30_vpg.h
├── dcn31/dcn31_vpg.h
├── dcn30/dcn30_afmt.h
├── dcn31/dcn31_afmt.h
├── dcn30/dcn30_dio_stream_encoder.h
├── dcn30/dcn30_hpo_frl_stream_encoder.h
├── dcn30/dcn30_hpo_frl_link_encoder.h
├── dcn31/dcn31_hpo_dp_stream_encoder.h
├── dcn31/dcn31_hpo_dp_link_encoder.h
├── dcn31/dcn31_apg.h
├── dcn31/dcn31_dio_link_encoder.h
├── dce/dce_clock_source.h
├── dce/dce_audio.h
├── dce/dce_hwseq.h
├── clk_mgr.h
│ └── dc/clk_mgr/dcn315/dcn315_clk_mgr.c (clock programming)
│ └── dc/clk_mgr/dcn315/dcn315_smu.c (SMU messages)
├── dio/dcn10/dcn10_dio.h
├── dio/virtual/virtual_stream_encoder.h
├── dce110/dce110_resource.h
├── dml/display_mode_vba.h
├── dml/dcn31/dcn31_fpu.h
│ └── dml/dcn31/dcn31_fpu.c (IP/SOC params → pure math)
├── dcn31/dcn31_dccg.h
├── dcn10/dcn10_resource.h
├── dcn31/dcn31_panel_cntl.h
├── dcn30/dcn30_dwb.h
├── dcn30/dcn30_mmhubbub.h
├── dcn/dcn_3_1_5_offset.h (15K lines register offsets)
├── dcn/dcn_3_1_5_sh_mask.h (62K lines shift/mask)
├── dpcs/dpcs_4_2_2_offset.h (12K lines DPCS offsets)
├── dpcs/dpcs_4_2_2_sh_mask.h (103K lines DPCS shift/mask)
├── reg_helper.h
├── dce/dmub_abm.h
├── dce/dmub_psr.h
├── dce/dmub_replay.h
├── dce/dce_aux.h
├── dce/dce_i2c.h
├── dml/dcn30/display_mode_vba_30.h
├── vm_helper.h
└── dcn20/dcn20_vmid.h
GPIO subsystem:
gpio/dcn315/hw_factory_dcn315.c
├── dm_services.h
├── include/gpio_types.h
├── gpio/hw_factory.h
├── gpio/hw_gpio.h
├── gpio/hw_ddc.h
├── gpio/hw_hpd.h
├── gpio/hw_generic.h
├── gpio/hw_factory_dcn315.h
├── dcn/dcn_3_1_5_offset.h
└── dcn/dcn_3_1_5_sh_mask.h
DMUB subsystem:
dmub/src/dmub_srv.c
├── dmub/dmub_srv.h
├── dmub/src/dmub_dcn315.h (DCN315 field definitions)
│ └── dmub/src/dmub_dcn31.h (base DCN31 fields)
├── dmub/src/dmub_dcn315.c (register table)
├── dmub/src/dmub_cmd.h (command structures)
└── dmub/src/os_types.h (platform abstraction)
```
---
## 8. Per-Unit Classification Table
### Authorized C ABI Surface (34 units)
| ID | File | Lines | Type |
|----|------|-------|------|
| R1 | `dcn_3_1_5_offset.h` | 15,306 | Register header |
| R2 | `dcn_3_1_5_sh_mask.h` | 62,619 | Register header |
| R3 | `dpcs_4_2_2_offset.h` | 11,957 | Register header |
| R4 | `dpcs_4_2_2_sh_mask.h` | 103,633 | Register header |
| R5 | `mp_13_0_5_offset.h` | 455 | Register header |
| C1 | `dcn315_clk_mgr.c` | 747 | Register programming |
| C2 | `dcn315_clk_mgr.h` | 49 | Type definition |
| C3 | `dcn315_smu.c` | 366 | SMU mailbox MMIO |
| C4 | `dcn315_smu.h` | 130 | SMU protocol |
| G1 | `hw_factory_dcn315.c` | 260 | GPIO register tables |
| G2 | `hw_factory_dcn315.h` | 31 | Interface |
| G3 | `hw_translate_dcn315.c` | 374 | GPIO offset mapping |
| G4 | `hw_translate_dcn315.h` | 33 | Interface |
| I1 | `irq_service_dcn315.c` | 413 | IH IRQ routing |
| I2 | `irq_service_dcn315.h` | 34 | Interface |
| D1 | `dmub_dcn315.c` | 62 | DMUB register table |
| D2 | `dmub_dcn315.h` | 68 | DMUB field definitions |
| D3 | `dmub_srv.c` | 1,483 | DMUB FW load + cmd ring |
| D4 | `dmub_srv.h` | ~200 | DMUB service types |
| D5 | `dmub_dcn31.h` | ~120 | DMUB base registers |
| H1 | `dcn31_hubbub.h` | ~50 | Register macros |
| H2 | `dcn31_hubp.h` | ~60 | Register macros |
| H3 | `dcn31_optc.h` | ~60 | Register macros |
| H4 | `dcn31_dccg.h` | ~60 | Register macros |
| H5 | `dcn31_vpg.h` | ~163 | Register macros |
| H6 | `dcn31_afmt.h` | ~126 | Register macros |
| H7 | `dcn31_apg.h` | ~124 | Register macros |
| H8 | `dcn31_panel_cntl.h` | ~43 | Register macros |
| H9 | `dcn31_hpo_dp_stream_encoder.h` | ~100 | Register macros |
| H10 | `dcn31_hpo_dp_link_encoder.h` | ~100 | Register macros |
| H11 | `dcn31_dio_link_encoder.h` | ~100 | Register macros |
| W1 | `dcn31_hwseq.c` | 745 | Register-level HW seq |
| F1 | `dcn_3_1_5_dmcub.bin` | ~180KB | Firmware blob |
| T1 | `dcn315_resource.c` (register tables) | ~1,000 | Register table data |
### Reference-Only Rust Reimplementation (21 units)
| ID | File | Lines | Type |
|----|------|-------|------|
| P1 | `dcn315_resource_construct()` | ~340 | Resource pool construction |
| P2 | `dcn315_res_pool_funcs` | ~30 | Function dispatch table |
| P3 | `dcn315_populate_dml_pipes` | ~100 | Pipe parameter policy |
| P4 | `dcn315_create_resource_pool()` | ~15 | Allocator + constructor |
| P5 | `dcn315_resource.h` (types) | ~7 | Resource pool type |
| M1 | `dcn31_fpu.c` | 830 | DML IP/SOC params + BW boxing |
| M2 | `display_mode_vba_31.c` | 7,504 | Mode validation + BW calc |
| M3 | `display_rq_dlg_calc_31.c` | 1,599 | Display request + DLG calc |
| W1 | `dcn31_init.c` | 160 | HW sequencer function table |
| W2 | `dcn31_init.h` | 33 | Interface |
| O1 | `dcn315_clk_mgr.c` (policy) | ~150 | Clock state machine policy |
| O2 | `dcn315_smu.c` (policy) | ~50 | SMU message sequencing |
| O3 | Bandwidth policy functions | spread | Validate, WM, DET allocation |
| O4 | Pipe allocation policy | spread | Acquire/release/free pipe |
| O5 | Stream management | spread | Add/remove stream to context |
| O6 | Modeset enable/disable | spread | Stream enable/blanking policy |
| O7 | Front-end program policy | spread | Pipe front-end setup |
| O8 | Plane address update policy | spread | Surface address programming |
| O9 | Clock transition policy | spread | Clock change sequencing |
| O10 | Encoder matching policy | spread | Stream→encoder assignment |
| O11 | Debug defaults / config | ~100 lines | Default debug/check config |
**Counts:**
- Authorized C ABI surface: **34 units** (14 files + ~13 register macro headers + firmware + register table data in resource file + NBIO/IH + shared type headers)
- Reference-only Rust reimplementation: **21 units** (5 resource pool + 3 DML math + 2 HWSS orchestration + 11 policy function groups)
---
## 9. Closure Document Metadata
| Field | Value |
|-------|-------|
| Derived from | Linux 7.1 at `local/reference/linux-7.1/` |
| Anchor file | `drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c` |
| DCN family | dcn31 (NOT dcn314) — DCN315 pulls dcn31 headers for register macros, init, hubbub, hubp, optc, hpo_dp, apg |
| DML family | dml/dcn31/ (NOT dcn314) |
| DMUB FW | `dcn_3_1_5_dmcub.bin` via `FIRMWARE_DCN_315_DMUB` at `amdgpu_dm.c:130` |
| Raphael probe | **NOT FOUND** at `local/docs/evidence/ryzen-x670e/raphael-probe.md` — unknowns marked pending-probe |
| Source analyzed | 17,558 LoC source + 193,970 LoC register headers |
| Date analyzed | 2026-08-05 |
| Task | Todo 33 of `.omo/plans/ryzen-7000-x670e-compat.md` |
| Governed by | AGENTS.md § "amdgpu + redbear DCN315 display-slice exemption (operator-approved 2026-08-04)" |
---
## 10. Key Design Decisions for the Port
1. **DMCUB firmware load without PSP:** The DMUB firmware can be loaded directly via MMIO
to the DMUB region memory without requiring a PSP driver. This matches the pattern used
in Linux before PSP-assisted DMUB loading was added (the `dmub_srv_hw_init()` path).
2. **SMU communication via RSMU registers:** The SMU is assumed pre-initialized by UEFI.
The display driver only sends clock requests to the already-running SMU.
3. **DCN VM for scanout (not GPU VM):** The DCN_VM_CONTEXT page tables are separate from
the GPU VM used for rendering. Minimal identity-mapped page tables suffice for scanout.
4. **Register tables as C ABI:** The register offset/mask/shift table data from
`dcn_3_1_5_offset.h` and `dcn_3_1_5_sh_mask.h` is the hardware ABI. The Rust port
will generate equivalent Rust `const` tables from the same header data.
5. **No ATOMBIOS dependency:** The minimal display slice uses static defaults for LTTPR
caps instead of querying VBIOS. This is safe for consumer boards without LTTPR.
6. **Single connector target:** The first deliverable targets one physical connector
(HDMI or DP per ATOM routing). Multi-head is out of scope.
---
*End of closure record. This document is the FIRST deliverable of todo 33. No port code
has been written. Classifications are per the todo-24(b) exemption boundary.*