Skip to content

amdv/drm: Dolby Vision output-path fixes#29

Open
allolive wants to merge 3 commits into
CoreELEC:5.15.196_20260225from
allolive:dv-output-fixes
Open

amdv/drm: Dolby Vision output-path fixes#29
allolive wants to merge 3 commits into
CoreELEC:5.15.196_20260225from
allolive:dv-output-fixes

Conversation

@allolive

Copy link
Copy Markdown
Contributor

Three DV output-path fixes:

  • drm/hdmi: keep 4:4:4 base at 4K50/60 while a DV title is active: at 4K50/60 the HDMI path forces subsampled chroma, which the DV VSIF can't tunnel over, so the sink drops the link. Keep 4:4:4 while in DV; SDR/HDR10 unchanged.
  • amdv: reset the core on the DV SDR fallback: the DV→SDR fallback re-committed with a stale EL flag/metadata and skipped the core reset, stranding a core pointer and smashing the stack canary. Build a clean SDR input and reset the core first.
  • amdv: debounce spurious away-from-DV output-mode switches: a title-start BYPASS→DV→SDR8→DV oscillation forces an uncommitted core reset. Hold DV for a few frames when the request drops to SDR while the source is still DV; genuine changes honored immediately.

allolive added 3 commits July 13, 2026 20:02
meson_hdmitx_decide_color_attr() forces subsampled chroma (YUV422, or YUV420
where 4:2:2 is unsupported) at 4K50/60 via is_hdmi4k_support_420(). Dolby Vision
cannot tunnel over subsampled chroma: when the DV core raises its VSIF over that
base the sink drops the link (no picture). At forced-4K60 there is no resolution
change on DV entry, so nothing re-picks a DV-compatible base.

Gate the forced subsampling on !is_amdv_enable(): while a DV title is active
(Kodi sets dolby_vision_enable per stream, before the DV core turns on) keep
4:4:4 at 4K50/60. The existing colourdepth block then pins RGB/4:4:4 at those
VICs to 8-bit, so the base is 4:4:4/8 - a valid DV container the VSIF can land
on. Confined to DV via the per-video flag, so SDR/HDR10 keep their subsampled
base unchanged (no bandwidth/HDR10 regression).
When Dolby Vision detection fails and the driver falls back to SDR, it
re-committed with the stale enhancement-layer flag and metadata still attached,
and skipped the core reset that every other format change performs. That could
leave a core pointer stranded and smash the kernel stack canary. Build a clean
SDR input (dropping the leftover EL fields) and reset the core before
re-committing.

Signed-off-by: Olivier Allauzen <olivier.allauzen@gmail.com>
At the start of a Dolby Vision title the output-mode policy briefly oscillates
BYPASS -> DV -> SDR8 -> DV. The transient DV->SDR8 step, taken while the source
is still Dolby Vision, forces an unnecessary core reset with no config commit
following it; this leaves an internal core pointer stranded and may be
implicated in a rare stack-corruption.

Hold the DV output for a few frames when the requested mode drops to SDR while
the source is still Dolby Vision, so the spurious away-switch never commits.
Genuine changes (the source leaving Dolby Vision, or DV->HDR10/BYPASS) are
honored immediately. The hold length is tunable via the amdv_away_from_dv_debounce
module parameter (frames to hold; 1 disables it).

Signed-off-by: Olivier Allauzen <olivier.allauzen@gmail.com>
Comment thread drivers/drm/meson_hdmi.c
strstr(common->fmt_attr, "422") == NULL &&
strstr(common->fmt_attr, "444") == NULL) {
if (is_hdmi4k_support_420(vic & 0xff)) {
if (is_hdmi4k_support_420(vic & 0xff) && !is_amdv_enable()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not need as it is already be checked by hdmi_current_eotf_type.
It get set/reset by vsif package from amdv. So it never reach this place when in DV mode.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, on its own in this driver PR is a no-op. A Kodi side fix is needed.

When a Dolby Vision stream starts at the same HDMI timing as the current (SDR) desktop mode, no resolution change occurs, so Kodi never triggers a modeset and the driver keeps the existing SDR color attribute instead of re-deciding it for DV. The DV tunnel is then stuffed into whatever base was already on the wire: at 4K50/60 that's the kernel's forced 10-bit YUV420 base, which is an invalid DV container, so the sink drops the link (audio passes, TV shows no picture). Even when it does lock, the leftover color depth is nondeterministic so the output ends up player-led or TV-led "at random", not matching the user's selection. Both stem from the same gap: DV entry needs to force an HDMI color-attr re-decide to the correct DV base ({444,8}) even when the resolution itself doesn't change.

I can send a Kodi PR with these two changes to make the issue clearer. I'm also happy to work on a better fix if this one doesn't work.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current_mode = dolby_vision_mode;
if (amdv_policy_process
(vf, &current_mode, check_format)) {
if (amdv_honor_output_change(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's caused maybe by the amdv_wait_delay where it wait for default 2 frames to decide if DV or not.
So double checked?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, I checked it directly. With the debounce compiled out, I swept amdv_wait_delay = 0 / 1 / 2 / 6 and replayed a DV title from the start each time. The BYPASS→DV→SDR8→DV oscillation is identical at every value so it doesn't look that the wait delay produces it:

# amdv_wait_delay=0  (debounce off)
output change from 5 to 1        # BYPASS -> DV (IPT_TUNNEL)
decide_color_attr [eotf:1] => attr[YUV444,8bit]
output change from 1 to 4        # DV -> SDR8   <-- the away excursion
VOUT_EVENT_MODE_CHANGE
output change from 4 to 1        # SDR8 -> DV
output change from 1 to 4        # ...and again
output change from 4 to 1
# amdv_wait_delay = 1, 2, 6: same sequence, same timing

Happy to move to a better layer if you see one, but lowering amdv_wait_delay doesn't remove the excursion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants