-
Notifications
You must be signed in to change notification settings - Fork 24
amdv/drm: Dolby Vision output-path fixes #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 5.15.196_20260225
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -532,6 +532,10 @@ bool amdv_wait_on; | |
| module_param(amdv_wait_on, bool, 0664); | ||
| MODULE_PARM_DESC(amdv_wait_on, "\n amdv_wait_on\n"); | ||
|
|
||
| static unsigned int amdv_away_from_dv_debounce = 8; /* frames to hold; 1 = disabled */ | ||
| module_param(amdv_away_from_dv_debounce, uint, 0644); | ||
| static int amdv_away_debounce_cnt; | ||
|
|
||
| static int amdv_uboot_on; | ||
| static bool amdv_wait_init; | ||
| static int amdv_wait_count; | ||
|
|
@@ -9427,6 +9431,30 @@ bool is_dv_unique_drm(struct vframe_s *vf) | |
| return false; | ||
| } | ||
|
|
||
| /* Hold a spurious DV->SDR output switch while the source is still Dolby Vision. */ | ||
| static bool amdv_honor_output_change(bool changed, unsigned int cur_mode, | ||
| unsigned int *req_mode, | ||
| enum signal_format_enum src_fmt) | ||
| { | ||
| bool away = changed && | ||
| (cur_mode == AMDV_OUTPUT_MODE_IPT_TUNNEL || | ||
| cur_mode == AMDV_OUTPUT_MODE_IPT) && | ||
| (*req_mode == AMDV_OUTPUT_MODE_SDR8 || | ||
| *req_mode == AMDV_OUTPUT_MODE_SDR10) && | ||
| (src_fmt == FORMAT_DOVI || src_fmt == FORMAT_DOVI_LL); | ||
|
|
||
| if (!away) { | ||
| amdv_away_debounce_cnt = 0; | ||
| return changed; | ||
| } | ||
| if (++amdv_away_debounce_cnt < amdv_away_from_dv_debounce) { | ||
| *req_mode = cur_mode; /* keep DV; drop the spurious away-switch */ | ||
| return false; | ||
| } | ||
| amdv_away_debounce_cnt = 0; | ||
| return true; | ||
| } | ||
|
|
||
| /* toggle mode: 0: not toggle; 1: toggle frame; 2: use keep frame */ | ||
| /* ret 0: parser done for v2*/ | ||
| /* ret 1: both dolby and hdr module bypass */ | ||
|
|
@@ -10154,8 +10182,9 @@ int amdv_parse_metadata_v2_stb(struct vframe_s *vf, | |
| dolby_vision_request_mode = 0xff; | ||
| } | ||
| current_mode = dolby_vision_mode; | ||
| if (amdv_policy_process | ||
| (vf, ¤t_mode, check_format)) { | ||
| if (amdv_honor_output_change( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 Happy to move to a better layer if you see one, but lowering |
||
| amdv_policy_process(vf, ¤t_mode, check_format), | ||
| dolby_vision_mode, ¤t_mode, check_format)) { | ||
| if (!dv_inst[pri_input].amdv_wait_init) { | ||
| amdv_set_toggle_flag(1); | ||
| amdv_wait_on = true; | ||
|
|
@@ -11115,6 +11144,13 @@ int amdv_control_path(struct vframe_s *vf, struct vframe_s *vf_2, | |
| new_m_dovi_setting.input[0].src_format == FORMAT_DOVI) { | ||
| pr_dv_dbg("dv source but metadata checked as el, force as sdr source\n"); | ||
| new_m_dovi_setting.input[0].src_format = FORMAT_SDR; | ||
| new_m_dovi_setting.input[0].el_flag = 0; | ||
| new_m_dovi_setting.input[0].el_halfsize_flag = 0; | ||
| new_m_dovi_setting.input[0].in_md = NULL; | ||
| new_m_dovi_setting.input[0].in_md_size = 0; | ||
| new_m_dovi_setting.input[0].in_comp = NULL; | ||
| new_m_dovi_setting.input[0].in_comp_size = 0; | ||
| p_funcs_stb->multi_control_path(&invalid_m_dovi_setting); | ||
| flag = p_funcs_stb->multi_control_path(&new_m_dovi_setting); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not completely true, the case of same resolution but DV/non DV is already covered:
https://github.com/CoreELEC/xbmc/blob/f256069b8a6e43fd2596946dab611fe06271e3aa/xbmc/windowing/amlogic/WinSystemAmlogicGLESContext.cpp#L117
There was a problem hiding this comment.
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:
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.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
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
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
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:
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.
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).