From 5c4f7d2580e4cd8af4ec6803f2f56e65f87df072 Mon Sep 17 00:00:00 2001 From: vasilito Date: Wed, 5 Aug 2026 08:29:51 +0300 Subject: [PATCH] docs(gpu): DCN315 closure record + AGENTS.md surface list (closure-first) --- .../task-33-ryzen-7000-x670e-compat.txt | 43 ++ AGENTS.md | 78 +- .../evidence/ryzen-x670e/dcn315-closure.md | 723 ++++++++++++++++++ 3 files changed, 843 insertions(+), 1 deletion(-) create mode 100644 .omo/evidence/task-33-ryzen-7000-x670e-compat.txt create mode 100644 local/docs/evidence/ryzen-x670e/dcn315-closure.md diff --git a/.omo/evidence/task-33-ryzen-7000-x670e-compat.txt b/.omo/evidence/task-33-ryzen-7000-x670e-compat.txt new file mode 100644 index 0000000000..a52089df04 --- /dev/null +++ b/.omo/evidence/task-33-ryzen-7000-x670e-compat.txt @@ -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. diff --git a/AGENTS.md b/AGENTS.md index 3ec51f2059..e9237aaa72 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 106–1,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) diff --git a/local/docs/evidence/ryzen-x670e/dcn315-closure.md b/local/docs/evidence/ryzen-x670e/dcn315-closure.md new file mode 100644 index 0000000000..a1e4e385ed --- /dev/null +++ b/local/docs/evidence/ryzen-x670e/dcn315-closure.md @@ -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 = ` + - **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.*