Skip to content

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

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

amdv/drm: Dolby Vision output-path fixes#29
allolive wants to merge 2 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.

Comment thread drivers/drm/meson_hdmi.c Outdated
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.

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.

@Portisch, you're right again. The DV on/off case is covered by your force-switch rework, so that's not it. My patch was trying to fix two remaining problems by forcing a colour re-decide, and I think that approach is in the wrong place. Two issues:

  1. Display at 4K50/60, auto-refresh-rate disabled, play a 24p DV file. There's no resolution change on DV entry, so decide runs and lands on an invalid DV base (YUV420) that the sink can't tunnel → no signal on my TV. With the CoreElec TV-Led setting, it should output RGB 444 to start the tunnel.

  2. Display at any resolution, auto-refresh-rate enabled, TV-led selected in settings. Play a 24.000Hz movie → correct TV-led 8-bit RGB. Then, while it's playing, start another DV title at 23.976Hz → it comes out player-led 12-bit RGB (and the reverse, 23.976→24.000, breaks the same way). So it isn't resolution changes as you suggested, it's the fractional-rate crossing (23.976 ↔ 24.000). Same-rate switches stay correct; both directions across the boundary break. My "always re-evaluate on DV transition" suggested patch catches it as it triggers all the time, but the real trigger is the frac-rate mode switch.

Happy to share logs / a repro for either.

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.

  1. auto-refresh-rate disabled
    This interpretation is not technically correct. When users disable the automatic refresh‑rate switching, Kodi will adhere to that setting and intentionally avoid any mode change. In other words, the absence of a mode switch is expected behavior and originates from the user’s configuration, not from a functional limitation.

    A forced Dolby Vision mode switch is already on my roadmap. Implementing it, however, is non‑trivial: Kodi contains several internal safeguards that explicitly suppress mode changes when the refresh‑rate option is disabled. Achieving a DV‑specific override requires modifying multiple points in the video and windowing pipeline to bypass these checks without destabilizing normal mode‑switch logic.

  2. comes out player-led 12-bit RGB
    Works here:
    Playback of first sample: 4K24 RGB BT2020 8b DV 297MHz
    Then switch directly without stop to second sample: 4K23.976 RGB BT2020 8b DV 297MHz
    And back to first sample: 4K24 RGB BT2020 8b DV 297MHz

@allolive allolive Jul 15, 2026

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.

For #2, I was wrong to say "any resolution." The real trigger is that the second file's color depth changes on the switch except if your GUI depth is 8-bit, in which case it stays 8-bit the whole time and you never see the toggle.

Could you try again with a switch to player-led mode and run the same test.

My tests:

  1. 4K @ 59.94Hz, default GUI color depth = 10-bit (automatically selected), TV-led, switch resolution on start/stop, no delay after refresh rate change. Playing the two DV files then toggles the second one to 10-bit RGB, which the display reads as player-led.

  2. 1080p @ 59.94Hz, GUI color depth = 8-bit (forced), player-led, switch resolution on start/stop, no delay after refresh rate change. Playing the two DV files then toggles the second one to YUV422 16-bit (invalid 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.

@Portisch, I pulled this drm/hdmi colour-base commit out of this PR. It's a topic of its own.

I've "got a fix for it" that's probably on the wrong track compared to what you laid out above, but I'll send it as 2 PRs in case any of it is useful. Two parts:

  • a Kodi AML change that triggers a mode switch when it's needed
  • a driver change to correct the colour depth

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.

allolive added 2 commits July 17, 2026 19:18
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>
@Portisch

Copy link
Copy Markdown
Contributor

The commit about the core reset look valid to me.
Maybe split the two commits in two PR so I can merge it.

About the mode toggle please check and debug hdmitx_common_output_disable. It does clear out the current set info packet by clear_pkt.

Maybe a fix like this will do already the job and the TV stay in the mode set before by the vsif package.

@Portisch

Portisch commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

After merge of 6e10fef I maybe see what you mean. It's from like 1080p50 to 1080p50 and then to 2160p24 DV.

This is a new behaviour because of the last commit. Kodi only switch to 2160p24, nothing else.

Edit:
Same happens on HDR10, so not really DV related.
https://paste.coreelec.org/LatinHonored

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