From a87678bbbf781a59053be7e0ad21c00fa7c6dd9a Mon Sep 17 00:00:00 2001 From: "Claude (noether)" Date: Sat, 16 May 2026 23:15:11 +0000 Subject: [PATCH] =?UTF-8?q?Phase=202:=20field-mapping=20table=20=E2=80=94?= =?UTF-8?q?=20legacy=20rkvdec=5Fregs=20=E2=86=92=20rkvdec=5Fvdpu381=5Fregs?= =?UTF-8?q?=5Fvp9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The translation guide for porting rkvdec_vp9_run and its config_* helpers from the flat vdpu34x register layout to the segmented vdpu381 layout. Each row maps a legacy field to its new location across the 4 segments (common, vp9_param, common_addr, vp9_addr). Key semantic deltas captured: - reg02.dec_mode → reg009_dec_mode.dec_mode (VDPU381_MODE_VP9=2) - Per-ref indexed arrays (reg17_19[i], reg29_31[i], reg37_39[i], reg48_50[i]) become separate per-frame-slot registers (last/golden/altref triplets) in vdpu381 - Decode trigger moves from RKVDEC_REG_INTERRUPT=0x004 + RKVDEC_INTERRUPT_DEC_E mask to VDPU381_REG_DEC_E=0x028 + VDPU381_DEC_E_BIT (single bit) - reg09.yuv_virstride dropped (legacy-only convenience field) - reg51.lastref_yuv_virstride dropped (not in vdpu381 layout) - NEW fields surfaced: reg103_frame_flags (intra_only, prob_update_en, refresh_en, allow_high_precision_mv, interp_filter_switch_en), reg064_cprheader.cprheader_offset, reg105.count_update_en Also captures 5 open questions for the next code-writing session (prob-index rotation, delta_prob_base aliasing, RCB integration, timeout threshold sizing). This document IS the load-bearing artifact for the Phase 2 backend implementation. The .c file translation walks this table line-by-line. Companion to commit 47431635801d (regs header VP9 struct definitions). Co-Authored-By: Claude Opus 4.7 --- phase2_field_mapping.md | 129 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 phase2_field_mapping.md diff --git a/phase2_field_mapping.md b/phase2_field_mapping.md new file mode 100644 index 0000000..62e429e --- /dev/null +++ b/phase2_field_mapping.md @@ -0,0 +1,129 @@ +# Phase 2 field-mapping table — legacy `struct rkvdec_regs` → `struct rkvdec_vdpu381_regs_vp9` + +The translation guide for porting `rkvdec_vp9_run` and its helpers from the legacy vdpu34x flat register layout to the vdpu381 segmented layout. Each row gives the legacy field, the new vdpu381 field, and notes on the semantic delta. Sourced from cross-reading legacy `rkvdec-vp9.c`, mainline `rkvdec-vdpu381-hevc.c`, mainline `rkvdec-vdpu381-regs.h`, and Rockchip BSP MPP `mpp/hal/rkdec/vp9d/hal_vp9d_vdpu382.c`. + +## Common block (segment 1, `OFFSET_COMMON_REGS = 0x020`) + +| Legacy | New (vdpu381) | Notes | +|---|---|---| +| `common.reg02.dec_mode = RKVDEC_MODE_VP9` | `common.reg009_dec_mode.dec_mode = VDPU381_MODE_VP9` | `VDPU381_MODE_VP9 = 2` already defined in `rkvdec-vdpu381-regs.h:22` | +| `common.reg03.y_hor_virstride` | `common.reg018_y_hor_stride.y_hor_virstride` | same semantic (aligned_pitch / 16) | +| `common.reg03.uv_hor_virstride` | `common.reg019_uv_hor_stride.uv_hor_virstride` | same semantic | +| `common.reg08.y_virstride` | `common.reg020_y_stride.y_virstride` | same semantic (y_len / 16) | +| `common.reg09.yuv_virstride` | **dropped** | vdpu381 common-block doesn't carry yuv_virstride; not consulted by hardware in segmented layout | +| `common.stream_len` | `common.reg016_stream_len` | same field | +| `common.decout_base` | `common_addr.reg130_decout_base` | moved to common_addr segment | +| `common.strm_rlc_base` | `common_addr.reg128_rlc_base` | moved to common_addr segment | +| `common.cabactbl_base` | `vp9_addr.reg197_cabactbl_base` | moved to vp9_addr segment | +| — | `common.reg028_multiply_core_ctrl.vp9_rd_prob_idx` | NEW: set per frame, prob slot ID | +| — | `common.reg028_multiply_core_ctrl.vp9_wr_prob_idx` | NEW: prob writeback slot | +| — | `common.reg011_important_en.dec_e_strmd_clkgate_dis = 1` | NEW: vdpu381 boilerplate | +| — | `common.reg011_important_en.dec_irq_dis = 0` | NEW: ensure IRQ enabled | +| — | `common.reg011_important_en.dec_timeout_e = 1` | NEW: timeout monitor | +| — | `common.reg026_block_gating_en.*` | NEW: per-block clock gates (mirror HEVC defaults from `rkvdec-vdpu381-hevc.c`) | + +## VP9 params block (segment 2, `OFFSET_CODEC_PARAMS_REGS = 0x100`) + +| Legacy | New (vdpu381) | Notes | +|---|---|---| +| `vp9.reg17_19[i].framewidth/frameheight` | `vp9_param.reg106_framewidth_last`, `reg107_frameheight_last`, `reg108_framewidth_golden`, `reg109_frameheight_golden`, `reg110_framewidth_altref`, `reg111_frameheight_altref` | indexed array → separate per-ref registers (last/golden/altref) | +| `vp9.reg20_27[segid]` (8 entries) | `vp9_param.reg067_074_segid[segid]` | direct array mapping, fields preserved (segid_*, segid_frame_qp_delta, segid_frame_loopfilter_value, etc.) | +| `vp9.reg28.tx_mode` | `vp9_param.reg076_tx_and_ref_mode.tx_mode` | same semantic | +| `vp9.reg28.frame_reference_mode` | `vp9_param.reg076_tx_and_ref_mode.frame_reference_mode` | same semantic | +| `vp9.reg29_31[i].ref_hor_scale` | `vp9_param.reg088_lref_hor_scale`, `reg090_gref_hor_scale`, `reg092_aref_hor_scale` | per-ref separation | +| `vp9.reg29_31[i].ref_ver_scale` | `vp9_param.reg089_lref_ver_scale`, `reg091_gref_ver_scale`, `reg093_aref_ver_scale` | per-ref separation | +| `vp9.reg32.ref_deltas_lastframe0..3` | `vp9_param.reg094_ref_deltas_lastframe.ref_deltas_lastframe` (single 28-bit field) | pack 4× 7-bit deltas into 28 bits | +| `vp9.reg33.mode_deltas_lastframe0/1` | `vp9_param.reg075_last_frame_info.mode_deltas_lastframe` (single 14-bit field) | pack 2× 7-bit deltas into 14 bits | +| `vp9.reg33.last_show_frame` | `vp9_param.reg075_last_frame_info.last_show_frame` | same semantic | +| `vp9.reg33.last_intra_only` | `vp9_param.reg075_last_frame_info.last_intra_only` | same semantic | +| `vp9.reg33.last_widthheight_eqcur` | `vp9_param.reg075_last_frame_info.last_widthheight_eqcur` | same semantic | +| `vp9.reg33.segmentation_enable_lstframe` | `vp9_param.reg075_last_frame_info.segmentation_enable_lstframe` | same semantic | +| `vp9.reg36.lasttile_size` | `vp9_param.reg078_lasttile_size.lasttile_size` | same semantic | +| `vp9.reg37_39[i].y_hor_virstride/uv_hor_virstride` | `vp9_param.reg079_lastfy_hor_stride`, `reg080_lastfuv_hor_stride`, `reg081_goldenfy_hor_stride`, `reg082_goldenfuv_hor_stride`, `reg083_altreffy_hor_stride`, `reg084_altreffuv_hor_stride` | per-ref separation | +| `vp9.reg48_50[i].virstride` | `vp9_param.reg085_lastfy_virstride`, `reg086_goldeny_virstride`, `reg087_altrefy_virstride` | per-ref separation | +| `vp9.reg51.lastref_yuv_virstride` | **dropped** | not present in vdpu381 layout; legacy-only convenience field | +| — | `vp9_param.reg103_frame_flags.intra_only_flag` | NEW: set when KEY_FRAME or INTRA_ONLY | +| — | `vp9_param.reg103_frame_flags.prob_update_en` | NEW: ! (compressed_header.tx_mode == previous && ...) | +| — | `vp9_param.reg103_frame_flags.refresh_en` | NEW: from V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX | +| — | `vp9_param.reg103_frame_flags.allow_high_precision_mv` | NEW: from V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV | +| — | `vp9_param.reg103_frame_flags.interp_filter_switch_en` | NEW: from dec_params->interpolation_filter == SWITCHABLE | +| — | `vp9_param.reg064_cprheader.cprheader_offset` | NEW: byte offset of compressed header (= dec_params->uncompressed_header_size) | +| — | `vp9_param.reg105_count_update_en.count_update_en = 1` | NEW: always enable count update on RX | + +## Common address block (segment 3, `OFFSET_COMMON_ADDR_REGS = 0x200`) + +| Legacy | New | Notes | +|---|---|---| +| `common.strm_rlc_base` | `common_addr.reg128_rlc_base` | bitstream OUTPUT buffer DMA addr | +| `common.decout_base` | `common_addr.reg130_decout_base` | CAPTURE buffer DMA addr | +| `vp9.refcolmv_base` (target buf's mv area) | `common_addr.reg131_colmv_cur_base` | current frame's collocated MV buffer | +| (legacy RCB allocations) | `common_addr.reg133_142[10]` from `rkvdec_allocate_rcb` | populated automatically by `rkvdec_start_streaming`; backend just writes the RCB array | + +## VP9 address block (segment 4, `OFFSET_CODEC_ADDR_REGS = 0x280`) + +| Legacy | New | Notes | +|---|---|---| +| `vp9.refer_bases[0]` (last_frame) | `vp9_addr.reg164_ref_last_base` | DMA addr of last ref frame | +| `vp9.refer_bases[1]` (golden) | `vp9_addr.reg165_ref_golden_base` | DMA addr of golden ref | +| `vp9.refer_bases[2]` (altref) | `vp9_addr.reg166_ref_alfter_base` | DMA addr of alt ref (BSP typo "alfter") | +| `common.cabactbl_base` | `vp9_addr.reg197_cabactbl_base` | probs table DMA addr | +| `vp9.count_base` | `vp9_addr.reg167_count_prob_base` | count buffer DMA addr | +| `vp9.segidlast_base` | `vp9_addr.reg168_segidlast_base` | last segmap DMA addr | +| `vp9.segidcur_base` | `vp9_addr.reg169_segidcur_base` | current segmap DMA addr | +| `vp9.refcolmv_base` (mv_ref) | `vp9_addr.reg170_ref_colmv_base` | reference collocated MV buffer | +| — | `vp9_addr.reg161_pps_base = 0` | not used for VP9 (HEVC concept); zero-init | +| — | `vp9_addr.reg163_rps_base = 0` | not used for VP9 (HEVC RPS); zero-init | +| — | `vp9_addr.reg160_delta_prob_base = probs.dma + offsetof(..., delta)` | NEW: forward-update probability delta input | +| — | `vp9_addr.reg162_last_prob_base` | NEW: previous frame's saved probs (frame_context) | +| — | `vp9_addr.reg171_intercmd_base = 0` | inter-frame command buffer (optional, can be 0) | +| — | `vp9_addr.reg172_update_prob_wr_base` | probs to write back after decode | +| — | `vp9_addr.reg180_scanlist_base = 0` | scanlist (not used for VP9 modes) | +| — | `vp9_addr.reg181_196_ref_colmv_base[16]` | unused for VP9 (HEVC DPB feature); zero-init | +| — | `vp9_addr.reg198_scale_down_luma_base = 0` | scale-down output (optional) | +| — | `vp9_addr.reg199_scale_down_chroma_base = 0` | scale-down output (optional) | + +## Decode trigger (NOT in any segmented write — done with `writel` after segment memcpy) + +| Legacy | New | +|---|---| +| `writel(RKVDEC_INTERRUPT_DEC_E \| RKVDEC_CONFIG_DEC_CLK_GATE_E \| RKVDEC_TIMEOUT_E \| RKVDEC_BUF_EMPTY_E, rkvdec->regs + RKVDEC_REG_INTERRUPT)` (0x004) | `writel(VDPU381_DEC_E_BIT, rkvdec->regs + VDPU381_REG_DEC_E)` (0x028) | +| `writel(1, rkvdec->regs + RKVDEC_REG_PREF_LUMA_CACHE_COMMAND)` | **drop** — vdpu381 path doesn't precharge cache this way | +| `writel(1, rkvdec->regs + RKVDEC_REG_PREF_CHR_CACHE_COMMAND)` | **drop** — same | + +## Segment write sequence in new `rkvdec_vdpu381_vp9_run` + +```c +rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_REGS, + &vp9_ctx->regs.common, sizeof(vp9_ctx->regs.common)); +rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_PARAMS_REGS, + &vp9_ctx->regs.vp9_param, sizeof(vp9_ctx->regs.vp9_param)); +rkvdec_memcpy_toio(rkvdec->regs + OFFSET_COMMON_ADDR_REGS, + &vp9_ctx->regs.common_addr, sizeof(vp9_ctx->regs.common_addr)); +rkvdec_memcpy_toio(rkvdec->regs + OFFSET_CODEC_ADDR_REGS, + &vp9_ctx->regs.vp9_addr, sizeof(vp9_ctx->regs.vp9_addr)); + +/* Trigger decode */ +writel(VDPU381_DEC_E_BIT, rkvdec->regs + VDPU381_REG_DEC_E); +``` + +## Open implementation questions for Phase 2 code + +| # | Question | +|---|---| +| C-1 | `reg103_frame_flags` has many flags not present in legacy (`prob_update_en`, `refresh_en`, etc.). Are these required for first decode, or can they be left zero? Cross-check against BSP `hal_vp9d_vdpu382.c` `vp9d_gen_regs_legacy` or equivalent setup function | +| C-2 | `reg160_delta_prob_base` and `reg162_last_prob_base` — do they require new DMA allocations in `rkvdec_vp9_start`, or can they alias existing probs/count buffers? | +| C-3 | `reg028_multiply_core_ctrl.vp9_rd_prob_idx`/`vp9_wr_prob_idx` — what values for first-frame intra? Check BSP `Vdpu382Vp9dCtx_t::prob_idx` rotation logic | +| C-4 | RCB write-out is done by `rkvdec_setup_rcb` or similar shared helper — need to confirm legacy VP9 doesn't touch RCB but vdpu381 VP9 must (mirror HEVC backend) | +| C-5 | `reg032_timeout_threshold` — set to `RKVDEC_TIMEOUT_4K` for 4K-max VP9? | + +## Files to be written in Phase 2 + +| File | Status | +|---|---| +| `rkvdec-vdpu381-regs.h` extension (VP9 structs) | DONE, committed `47431635801d` | +| `rkvdec-vp9-common.h` static-inline helpers | next session — straightforward extraction | +| `rkvdec-vdpu381-vp9.c` (new backend) | next session — uses this field-mapping | +| `rkvdec.c` wiring (vdpu38x_vp9_ctrls + vdpu381_coded_fmts[] entry) | next session — minimal | +| `rkvdec-vp9.c` refactor (consume common header) | next session — minimal | + +This field-mapping table is the load-bearing artifact for the Phase 2 code-writing session. Future-self: start by walking this table line-by-line in `rkvdec_vdpu381_vp9_run` / `config_vp9_common_regs` / `config_vp9_param_regs` / `config_vp9_addr_regs` helpers.