docs(gpu): DCN315 closure record + AGENTS.md surface list (closure-first)
redbear-ci / check (push) Has been cancelled
redbear-ci / check (push) Has been cancelled
This commit is contained in:
@@ -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.
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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.*
|
||||
Reference in New Issue
Block a user