6.12 bpi r2 vpu - #1
Draft
filipleple wants to merge 7 commits into
Draft
Conversation
filipleple
force-pushed
the
6.12_bpi-r2_vpu
branch
from
June 25, 2026 13:24
ffa577e to
a6af593
Compare
…userspace
The MT7623N (BPI-R2) hardware video decoder has no mainline driver: the
working stack is a prebuilt armhf userspace (libvcodec_utility.so ->
libvcodecdrv.so) that drives the VPU by direct register programming through a
/dev/Vcodec char device. The android-mtk-3.18 "videocodec" driver it targets
does not build on mainline (mtk_smi_larb_get() was removed, there is no
drivers/misc/mediatek/ tree, and it depends on the BSP VAL/HAL framework).
Add a minimal modern re-implementation providing exactly the recovered ABI:
- /dev/Vcodec misc device;
- mmap() of the VDEC register banks (0x16000000 + 0x16020000..0x16028fff,
noncached) and of driver-allocated DMA-coherent buffers;
- the _IOW('M', nr) ioctl family: real LOCKHW/UNLOCKHW (mutex), WAITISR,
ALLOC/FREE_NON_CACHE_BUFFER, GET_CORE_NUMBER; the rest no-op success;
- VDEC power via a PM device link to larb1 + pm_runtime_resume_and_get(),
the same pattern as the lima MT7623 SMI-larb fix (pulls up
MT2701_POWER_DOMAIN_VDEC + CLK_VDEC_CKGEN/CLK_VDEC_LARB);
- poll-based decode completion (VDEC_BASE+0xA4 bit16), because the MT7623
VDEC GIC SPI is not published in the datasheet or any device tree.
The ioctl numbers and argument structs are vendored byte-identical from the
android driver so the prebuilt blob sees an unchanged ABI. Wire up Kconfig,
Makefile, the vcodec@16020000 DT node in mt7623n.dtsi, and enable
CONFIG_MTK_VCODEC_SHIM=y in mt7623n_evb_fwu_defconfig.
Signed-off-by: Filip Lewiński <filip.lewinski@3mdeb.com>
filipleple
force-pushed
the
6.12_bpi-r2_vpu
branch
from
July 2, 2026 17:25
bf5e4ef to
e5abb44
Compare
Three defects from review of the /dev/Vcodec shim, all around client lifetime and the poll-decode path: 1. LOCKHW/UNLOCKHW used a bare mutex. The prebuilt userspace may lock in one thread and unlock in another, and mutex_unlock() from a task that didn't lock is UB; worse, a client that crashes while holding it (e.g. vcodec_probe's fork-isolated children) wedges the HW forever. Replace with a counting semaphore (init 1) plus explicit fd ownership tracked under a spinlock. LOCKHW honors VAL_HW_LOCK_T.u4TimeoutMs (0 -> 2000ms default) via down_timeout(). UNLOCKHW only ups the semaphore if this fd owns it. .release() drops a lock left held by a dead client. 2. DMA buffers lived on one module-global list, so a crashed client leaked them until reboot. Move the buffer list to per-open state (struct vcodec_file, file->private_data) and free the remainder in .release(); mmap/alloc/free now operate on the fd's own buffers. 3. WAITISR returned 0 on poll timeout, which the blob reads as decode-done -> it then consumes garbage register state, indistinguishable from bad programming. Return -2, matching the android videocodec driver's VAL_RESULT_INVALID_ISR path (the blob treats a negative return as "no ISR / retry"). Timeout stays a ratelimited warn. Adds vcodec_shim_priv.h holding the shared struct vcodec_shim (device, larb link, HW-lock semaphore/owner) so the forthcoming /proc/M4U_device front-end can share this module's single struct device / dma domain. Signed-off-by: Filip Lewiński <filip.lewinski@3mdeb.com>
The prebuilt VPU userspace maps its (malloc'd, physically scattered)
decoder buffers through MediaTek's legacy M4U ABI -- libm4u.so opens
/proc/M4U_device and issues the MTK_M4U_T_* ('g' magic) ioctl family to
get back a single contiguous MVA the VDEC masters with. Mainline exposes
that gen1 IOMMU only through MTK_IOMMU_V1, so eVDecDrvCreate() currently
fails at its first allocation (ALLOC_MVA -> no device).
Add the M4U front-end as part of this module (shared struct device, one
dma/IOMMU domain). The key bridge is in ALLOC_MVA:
pin_user_pages_fast(FOLL_WRITE|FOLL_LONGTERM) the scattered range ->
sg_alloc_table_from_pages() (keeps the sub-page start offset) ->
dma_map_sgtable(BIDIRECTIONAL).
With an "iommus" property on the vcodec DT node, MTK_IOMMU_V1 has attached
an arm_iommu mapping and arm_iommu_map_sg() coalesces the pages into ONE
IOVA -> nents==1 -> that IOVA (offset included) is the MVA. Without it
(bypass / first bring-up) only a physically-contiguous range collapses to
nents==1; a scattered multi-page buffer yields nents>1 and we fail loudly
so the missing translation is obvious in dmesg. Same contract either way.
CACHE_SYNC -> dma_sync on the pin found by VA; DEALLOC -> unmap+unpin;
QUERY_MVA -> VA lookup. CONSTRUCT/DECONSTRUCT accept a NULL arg; port
config / TLB / power / monitor requests succeed as no-ops. Pins are tied
to the open file and released in .proc_release.
ioctl numbers and the gen1 arg layout (MVA read back at offset 0x0c,
0x2c-byte struct -- differs from the 3.18 header) are in vcodec_m4u_abi.h,
recovered per docs/vpu/m4u-notes.md. Module is now built from
vcodec_shim.o + m4u_shim.o and renamed mtk-vcodec-shim.ko.
Signed-off-by: Filip Lewiński <filip.lewinski@3mdeb.com>
Give the vcodec@16020000 node the larb1 VDEC master ports (flat numbering 11,12,14,15,16,17; PPWRAP/13 skipped) as generic "iommus" entries. With this, MTK_IOMMU_V1 attaches an arm_iommu mapping to the shim's struct device, so the /proc/M4U_device bridge's dma_map_sgtable coalesces the decoder's malloc'd, physically scattered buffers into a single MVA the VDEC can master. The port set is exactly the one the prebuilt libm4u enables on the decode path (see docs/vpu/m4u-notes.md). Kept as a standalone commit so the board session can A/B translation-on vs bypass by reverting just this patch. Signed-off-by: Filip Lewiński <filip.lewinski@3mdeb.com>
Signed-off-by: Filip Lewiński <filip.lewinski@3mdeb.com>
With .of_xlate in place, client probing now reaches mtk_iommu_v1_probe_device() -> mtk_iommu_v1_create_mapping(), which calls arm_iommu_create_mapping(dev, ...). Since 6.12 that helper allocates the paging domain through the client device (iommu_paging_domain_alloc()), which rejects any device where dev->iommu->iommu_dev is unset -- and the core only sets iommu_dev after ->probe_device() returns. The result is a silent -ENODEV: 'Adding to IOMMU failed: -19' at client probe, no master ever attaches, /sys/kernel/iommu_groups stays empty. Create the shared dma_iommu_mapping lazily in ->probe_finalize() instead, which runs after iommu_dev is set (and right before the existing arm_iommu_attach_device() call). Guard attach_dev against a NULL data->mapping for domains attached before the mapping exists (e.g. a core-allocated default domain). Signed-off-by: Filip Lewiński <filip.lewinski@3mdeb.com>
ALLOC_MVA maps a scattered user buffer through the IOMMU and requires it to collapse to a single IOVA (nents==1) so the MVA is contiguous for the VPU. dma_map_sg() only merges segments up to the device max_seg_size, which defaults to 64KB. H.264 work/frame buffers exceed that (observed: a 77312-byte 19-page buffer split into nents=2 at the 64KB boundary), so ALLOC_MVA returned -ENOMEM and eVDecDrvInit failed with 'Fail to open Vdec Drv H264 instance -81'. Set max_seg_size to the full 32-bit range so the whole buffer merges into one IOVA regardless of size. (smoke_m4u's 20KB test stayed under the cap, which is why it passed while real decode did not.) Signed-off-by: Filip Lewiński <filip.lewinski@3mdeb.com>
filipleple
force-pushed
the
6.12_bpi-r2_vpu
branch
from
July 19, 2026 12:46
e4a097f to
0aab9b5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.