From 211ebd845b6aba8046ac99352efcdefce2d6575a Mon Sep 17 00:00:00 2001 From: Olivier Allauzen Date: Mon, 13 Jul 2026 20:02:03 -0400 Subject: [PATCH 1/2] amdv: reset the core on the Dolby Vision SDR fallback 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 --- drivers/media/enhancement/amdolby_vision/amdv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/enhancement/amdolby_vision/amdv.c b/drivers/media/enhancement/amdolby_vision/amdv.c index 84d1bd975..b0809f752 100644 --- a/drivers/media/enhancement/amdolby_vision/amdv.c +++ b/drivers/media/enhancement/amdolby_vision/amdv.c @@ -11115,6 +11115,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); } From 18440d4baffa8d8490053a2086f32b826b78fe4a Mon Sep 17 00:00:00 2001 From: Olivier Allauzen Date: Mon, 13 Jul 2026 20:02:03 -0400 Subject: [PATCH 2/2] amdv: debounce spurious away-from-DV output-mode switches 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 --- .../media/enhancement/amdolby_vision/amdv.c | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/media/enhancement/amdolby_vision/amdv.c b/drivers/media/enhancement/amdolby_vision/amdv.c index b0809f752..7dc5dd856 100644 --- a/drivers/media/enhancement/amdolby_vision/amdv.c +++ b/drivers/media/enhancement/amdolby_vision/amdv.c @@ -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( + 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;